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

[feature] Prompt user for input #318

Closed klane closed 3 years ago

klane commented 3 years ago

I propose adding an optional prompt key to the config file, which will prompt the user for input when installing dotfiles. An example config entry could be:

prompt:
  email: email?

This would prompt the user with the string "email?" and dotdrop will set the variable email to the user input. This enables users to set machine-specific variables without storing them in git or needing to remember to set environment variables before running dotdrop. I tried to achieve the same effect with the read command in a dynvariables entry such as:

dynvariables:
  email: read -r -p "email? " email; echo "$email"

The shell waited for user input, but the prompt was consumed by dotdrop and became part of the variable. Perhaps there is a way to rewrite the command above and achieve the desired behavior without needing to modify dotdrop. If this is implemented, another consideration is storing the input so that users are not prompted on subsequent calls.

deadc0de6 commented 3 years ago

I made an attempt at this in branch userinput. The config entry is uservariables and is to be used like this:

uservariables:
  email: "email"

Dotdrop will prompt the user for the value of the variable like this:

Please provide the value for "email": 

The user variables are then available in the config as well as in templates for use.

Note that uservariables is a top entry and is optional (like top entries actions, variables, etc). The uservariables will take precedence over any top variables or dynvariables. I haven't documented it yet though.

Can you give it a try and let me know what you think?

deadc0de6 commented 3 years ago

Also note that obviously when uservariables is defined, dotdrop will wait for user input and thus using this will hinder you to script it or automate it. But I guess this was already understood when you made the feature request.

deadc0de6 commented 3 years ago

Regarding your second request, storing the input in the config for subsequent calls, I'm not sure this is the good approach as in my opinion, either you know the value (and thus set it in the config through variables or dynvariables) or you don't (or want it dynamic) and use the uservariables. Or am I missing the point?

klane commented 3 years ago

Thank you @deadc0de6 for adding this capability so quickly. I tried it out and it works as expected.

My thought process regarding storing the values is that users likely just want to set them on initial setup, at which point the variables are static and future dotdrop calls should not prompt the user for input. For example, perhaps users do not want to store certain machine-specific variables in git. This addition ensures users set them on a new machine when dotfiles are installed. However, at that point the variables are likely fixed for that machine. Future calls to compare, update, etc. should not require the user to input the same variables again.

I am not sure of the best way to go about this. Perhaps the values are written to another config that gets imported to the main one and whose values take precedence over uservariables. This second config could be added to .gitignore to avoid storing it in git.

deadc0de6 commented 3 years ago

You're welcome, happy it works as expected!

I understand the approach for storing the values. What I could do is save all uservariables after evaluation into a specific config file (and print that path to stdout). You would then need to add manually a line with import_variables to the config to load it and manually add this file to .gitignore.

Also, in order for this to work, I would need to change the precedence of uservariables (and bring them to the end). Meaning that if any variable is already defined with the same key, then the uservariables is ignored/not prompted.

For example:

uservariables:
  email: "email"
variables:
  email: user@example.com

In the above config, the email variable wouldn't be prompted to the user and the value user@example.com would be taken.

If all the above sounds ok to you, I'll go ahead and implement it.

klane commented 3 years ago

That sounds like exactly what I was thinking. The second config file could be written to ~/.config to avoid modifying the dotfiles repo, though I understand if you want to keep everything contained. For example, the main config could include:

uservariables:
  email: "email"
config:
  import_variables:
    - ~/.config/dotdrop/uservariables.yaml

and uservariables.yaml would be populated on the first call with the user input. Using your example above, ~/.config/dotdrop/uservariables.yaml would contain:

variables:
  email: user@example.com

Another possibility is to add an import_uservariables config entry, which acts just like import_variables and additionally specifies where uservariables should be written.

deadc0de6 commented 3 years ago

Ok I updated the branch with the changes.

Now uservariables are only queried if no other variable exists with the same key. Also the uservariables (when populated) are automatically saved to <main-config-path>/uservariables.yaml.

This means that you could define your config file like this:

uservariables:
  email: "email"
config:
  import_variables:
    - uservariables.yaml:optional

The keyword :optional will only warn if the file uservariables.yaml doesn't exist (instead of failing). So on first run, user will be prompted to enter the value for email which will then be saved to uservariables.yaml in the below form. Then, on subsequent calls, the variable email will already be defined (through variables imported from import_variables) and thus won't be queried.

uservariables.yaml

variables:
  email: user@example.com

You'd still need to add this file to your .gitignore. The path where uservariables are saved is printed to stdout on first run in the below form:

uservariables values saved to <some-path>/uservariables.yaml

Does this match your expectations?

klane commented 3 years ago

That sounds perfect. Thank you. I will test it out in the morning.

klane commented 3 years ago

It works as expected. Thank you!

deadc0de6 commented 3 years ago

Ok, will document it and create a new version once everything is ready. I'll keep you posted.

deadc0de6 commented 3 years ago

The new version 1.7.0 now contains the uservariables feature. Documentation is available here. Thanks for your help on this!

klane commented 3 years ago

Thank you for adding the feature! Hopefully others find it useful as well.