deadc0de6 / dotdrop

Save your dotfiles once, deploy them everywhere
https://dotdrop.readthedocs.io
GNU General Public License v3.0
1.79k stars 105 forks source link

[help] evalutation of dynamic variables #362

Closed DavidePatria closed 2 years ago

DavidePatria commented 2 years ago

What I am trying to achieve I have not found anything similar, and the documentation does not seem to talk about this.

I want to centralize the definition of paths only in my zshrc. I am trying to retrieve the following variables in this way:

actions:
  pre:
    pyenv_inst: scripts/pyenv_inst.sh
  post:
    source_zshrc: scripts/source_zshrc.sh
    zsh_autos_inst: scripts/zsh_autos.sh
    zsh_syntax_inst: scripts/zsh_syntax_hl_inst.sh
    omz_install: scripts/omz_install.sh
    birraio: scripts/birraio.sh
config:
  backup: true
  create: true
  longkey: true
  link_on_import: link
  link_dotfile_default: link
  dotpath: ficherospunto
dynvariables:
  OHMYZSH_ROOT: echo $ZSH
  PYENV_ROOT: echo $PYENV_ROOT
  PYENV_VENV: echo $PYENV_VENV
  PYENV_DEF: echo $PYENV_DEF

so, zshrc containes the definition of paths that are later used for dynamic variables. of course, while this works fine when the zshrc is already present, it doesn't when starting from scratch, because I understand that variables are evaluated at the beginning.

What I have tried so far

I thought about some possible solutions, such as storing the variables' values in the config and substituting them in the zshrc on install, which would kinda work.

my question is: am I using dynamic variables wrong? is there another way to avoid using full paths in the configuration?

deadc0de6 commented 2 years ago

You are using dynamic variables correctly.

A solution you already thought of is having the variables defined in dotdrop config and substitute them when installing. For a clean setup you could use a dedicated config with your variables, for example using import_variables. It's a bit of work at the beginning (depending on how many variables we are talking) but then you can even use those variables in other places/dotfiles easily thanks to templating.

Another way of doing this would be to source the zshrc file before calling dotdrop to have the variable defined in the environment and use them from there in your files. It is not very elegant but it works and could be use for initial bootstrapping while still allowing you to keep all your variables in you zshrc

f_test

{{@@ env['XYZ'] @@}}
{{@@ env['ZZZ'] @@}}

config file

config:
  backup: true
  banner: true
  create: true
  dotpath: dotfiles
  keepdot: false
  link_dotfile_default: nolink
  link_on_import: nolink
  longkey: false
dotfiles:
  f_test:
    src: test
    dst: ~/.test
profiles:
  host:
    dotfiles:
    - f_test

boostrap

$ cat dotfiles/vars
XYZ=abc
ZZZ=def
$ set -a; source dotfiles/vars; ./dotdrop.sh install -f f_test

Is that what you need? Where are those variables used, in the scripts called by the actions? If that's the case then by simply sourcing and exporting those variables as shown above you would solve your problem, at least for initial bootstrapping.

Regarding your second question is there another way to avoid using full paths in the configuration?, I'm not sure what you mean or where. If it's regarding the pre/post actions scripts, then you could of course simplify this with the following for example.

actions:
  pre:
    pyenv_inst: "{{@@ scripts_path @@}}/pyenv_inst.sh"
  post:
    source_zshrc: "{{@@ scripts_path @@}}/source_zshrc.sh"
    zsh_autos_inst: "{{@@ scripts_path @@}}/zsh_autos.sh"
    zsh_syntax_inst: "{{@@ scripts_path @@}}/zsh_syntax_hl_inst.sh"
    omz_install: "{{@@ scripts_path @@}}/omz_install.sh"
    birraio: "{{@@ scripts_path @@}}/birraio.sh"
variables:
  scripts_path: "scripts"

But I have the feeling you meant something else, can you elaborate on those full paths?

DavidePatria commented 2 years ago

so, if I understand correctly I can either :

by full paths I meant doing it like this last point. btw I need to check the guide for templating because I do not really see the point to using them right now

one more thing: substituting on instal doesn't work with linked files, right?

deadc0de6 commented 2 years ago

manually source variables for bootstrap, having them set in my zsh ans dotdrop variables

No you either have them only in .zshrc or only in dotdrop, not both

store them in dotdrop and substitute, I am not sure if I understand corrctly but I would be using commands like sed

No you would use templating (not sed), see example below

get rid to dyn var and write the full paths

My suggestion would indeed to define variables with the full paths

Here's a simplified example on how I would do this:

config.yaml

config:
  backup: true
  banner: true
  create: true
  dotpath: dotfiles
  keepdot: false
  link_dotfile_default: nolink
  link_on_import: nolink
  longkey: false
dotfiles:
  f_zshrc:
    src: zshrc
    dst: ~/.zshrc
  f_some_other_file:
    src: file
    dst: ~/.file
profiles:
  host:
    dotfiles:
    - f_zshrc
    - f_some_other_file
variables:
  PYENV_ROOT: ~/.pyenv

zshrc content

echo "this is pyenv root from zshrc: {{@@ PYENV_ROOT @@}}"

file content

echo "this is pyenv root from file: {{@@ PYENV_ROOT @@}}"

On install, dotdrop would substitute the PYENV_ROOT variable everywhere it is used with its content defined in the config (~/.pyenv).

DavidePatria commented 2 years ago

No you either have them only in .zshrc or only in dotdrop, not both

Sorry, I meant putting then only in zshrc and doing source zshrc before running dotdrop, so only in zshrc.

Now I understand how templates works: simply putting {{@@ PYENV_ROOT @@}} in my zshrc gets it substituted, right.

Still, as in your example, I cannot link files, right?

deadc0de6 commented 2 years ago

Yes templating allows you to substitute variables, execute macros, use if branch, and more. See the doc.

Sure you can link dotfiles with dotdrop, check the doc.

For example

config:
  backup: true
  banner: true
  create: true
  dotpath: dotfiles
  keepdot: false
  link_dotfile_default: nolink
  link_on_import: nolink
  longkey: false
dotfiles:
  f_zshrc:
    src: zshrc
    dst: ~/.zshrc
    link: absolute
  f_some_other_file:
    src: file
    dst: ~/.file
    link: absolute
profiles:
  host:
    dotfiles:
    - f_zshrc
    - f_some_other_file
variables:
  PYENV_ROOT: ~/.pyenv
DavidePatria commented 2 years ago

ok so, I am close, one last round.

Sure you can link dotfiles with dotdrop, check the doc.

I have been linking files before trying to move to templates, but, if I understand correctly, since the template variables get substituted the file cannot be linked but has to be created, right?

what I am doing right now is the following

variables:
  OHMYZSH_ROOT: $HOME/.oh-my-zsh
  PYENV_ROOT: $HOME/.pyenv
  PYENV_VENV: "{{@@ PYENV_ROOT @@}}/plugins/pyenv-virtualenv"
  PYENV_DEF: "{{@@ PYENV_ROOT @@}}/plugins/pyenv-default-packages"
actions:
  post:
    omz_install: scripts/omz_install.sh {{@@ OHMYZSH_ROOT @@}}
    # pyenv_inst: scripts/pyenv_inst.sh {{@@ PYENV_ROOT @@}} {{@@ PYENV_DEF @@}} {{@@ PYENV_VENV @@}}
    pyenv_inst: scripts/pyenv_inst.sh {{@@ PYENV_ROOT @@}}
    zsh_autos_inst: scripts/zsh_autos.sh {{@@ OHMYZSH_ROOT @@}}
    zsh_syntax_inst: scripts/zsh_syntax_hl_inst.sh {{@@ OHMYZSH_ROOT @@}}

so I am passing the paths as arguments to the scripts. the paths contain unexpanded env variables, so the shell scripts handle them correctly. moreover the variables get correclty subsituted in the files, e.g. .zshrc, unexpanded, as I wanted them to.

now, the problem rises when doing this

dotfiles:
 d_completions:
    src: oh-my-zsh/completions
    dst: '{{@@ OHMYZSH_ROOT @@}}/completions'
    chmod: '755'

here the variable would need to be expanded, but it isn't, so the files get installed to something like dotdrop_folder_path/$HOME/.oh-my-zsh/completions.

how do you suggest I solve this problem? another set of dynamic variable to echo the normal variables like so?

dynvariables:
  expanded_zsh: 'echo {{@@ OHMYZSH_ROOT @@}}'
deadc0de6 commented 2 years ago

No problem, always happy to help!

Regarding your first question on symlinked templated files, you are absolutely right, the files is first installed in the workdir and then symlinked from there, see the doc on symlinking templated files here for more.

You can fix your issue on non-expanded variables by using {{@@ env['HOME'] @@}} instead of $HOME in your variables:

variables:
  OHMYZSH_ROOT: "{{@@ env['HOME'] @@}}/.oh-my-zsh"
  PYENV_ROOT: "{{@@ env['HOME'] @@}}/.pyenv"
  PYENV_VENV: "{{@@ PYENV_ROOT @@}}/plugins/pyenv-virtualenv"
  PYENV_DEF: "{{@@ PYENV_ROOT @@}}/plugins/pyenv-default-packages"
DavidePatria commented 2 years ago

thank you! I solved the issues, now I might want to add variables to keep symbolic env vars in some of my dotfiles, but for now I am pretty happy with the result.