From 55e6ff46b8691443587a246a1babf9b6c943a8f6 Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Wed, 22 Sep 2021 11:16:17 +0200 Subject: [PATCH 01/11] implement user input for #318 --- dotdrop/cfg_aggregator.py | 5 +++-- dotdrop/cfg_yaml.py | 30 ++++++++++++++++++++++++++++-- dotdrop/utils.py | 14 ++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/dotdrop/cfg_aggregator.py b/dotdrop/cfg_aggregator.py index 9cce4cc..d7b3437 100644 --- a/dotdrop/cfg_aggregator.py +++ b/dotdrop/cfg_aggregator.py @@ -206,10 +206,11 @@ class CfgAggregator: # parsing ######################################################## - def _load(self): + def _load(self, reloading=False): """load lower level config""" self.cfgyaml = CfgYaml(self.path, self.profile_key, + reloading=reloading, debug=self.debug) # settings @@ -361,7 +362,7 @@ class CfgAggregator: self.log.dbg('reloading config') olddebug = self.debug self.debug = False - self._load() + self._load(reloading=True) self.debug = olddebug @classmethod diff --git a/dotdrop/cfg_yaml.py b/dotdrop/cfg_yaml.py index 3b8b868..cec8fa2 100644 --- a/dotdrop/cfg_yaml.py +++ b/dotdrop/cfg_yaml.py @@ -33,7 +33,7 @@ from dotdrop.settings import Settings from dotdrop.logger import Logger from dotdrop.templategen import Templategen from dotdrop.linktypes import LinkTypes -from dotdrop.utils import shellrun, uniq_list +from dotdrop.utils import shellrun, uniq_list, userinput from dotdrop.exceptions import YamlException, UndefinedException @@ -50,6 +50,7 @@ class CfgYaml: key_trans_w = 'trans_write' key_variables = 'variables' key_dvariables = 'dynvariables' + key_uvariables = 'uservariables' action_pre = 'pre' action_post = 'post' @@ -98,16 +99,19 @@ class CfgYaml: allowed_link_val = [lnk_nolink, lnk_link, lnk_children] top_entries = [key_dotfiles, key_settings, key_profiles] - def __init__(self, path, profile=None, addprofiles=None, debug=False): + def __init__(self, path, profile=None, addprofiles=None, + reloading=False, debug=False): """ config parser @path: config file path @profile: the selected profile @addprofiles: included profiles + @reloading: true when reloading @debug: debug flag """ self._path = os.path.abspath(path) self._profile = profile + self._reloading = reloading self._debug = debug self._log = Logger(debug=self._debug) # config needs to be written @@ -163,6 +167,10 @@ class CfgYaml: dvariables = self._parse_blk_dynvariables(self._yaml_dict) self._add_variables(dvariables, template=False) + # parse the "uservariables" block + uvariables = self._parse_blk_uservariables(self._yaml_dict) + self._add_variables(uvariables, template=False) + # now template variables and dynvariables from the same pool self._rec_resolve_variables(self.variables) # and execute dvariables @@ -565,6 +573,24 @@ class CfgYaml: self._debug_dict('dynvariables block', dvariables) return dvariables + def _parse_blk_uservariables(self, dic): + """parse the "uservariables" block""" + uvariables = self._get_entry(dic, + self.key_uvariables, + mandatory=False) + + uvars = {} + if not self._reloading and uvariables: + for k, v in uvariables.items(): + content = userinput(v, debug=self._debug) + uvars[k] = content + + if uvars: + uvars = uvars.copy() + if self._debug: + self._debug_dict('uservariables block', uvars) + return uvars + ######################################################## # parsing helpers ######################################################## diff --git a/dotdrop/utils.py b/dotdrop/utils.py index c3dcf1c..e9fe828 100644 --- a/dotdrop/utils.py +++ b/dotdrop/utils.py @@ -69,6 +69,20 @@ def shellrun(cmd, debug=False): return ret == 0, out +def userinput(prompt, debug=False): + """ + get user input + return user input + """ + if debug: + LOG.dbg('get user input for \"{}\"'.format(prompt), force=True) + pre = 'Please provide the value for \"{}\": '.format(prompt) + res = input(pre) + if debug: + LOG.dbg('user input result: {}'.format(res), force=True) + return res + + def fastdiff(left, right): """fast compare files and returns True if different""" return not filecmp.cmp(left, right, shallow=False) From 89aa98194436eaae197a08385d8ff87a61caf4ea Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Wed, 22 Sep 2021 11:19:55 +0200 Subject: [PATCH 02/11] linting --- dotdrop/cfg_yaml.py | 12 ++++++------ dotdrop/templategen.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dotdrop/cfg_yaml.py b/dotdrop/cfg_yaml.py index cec8fa2..95c1a68 100644 --- a/dotdrop/cfg_yaml.py +++ b/dotdrop/cfg_yaml.py @@ -436,7 +436,7 @@ class CfgYaml: if self._debug: self._dbg('saving to {}'.format(self._path)) try: - with open(self._path, 'w') as file: + with open(self._path, 'w', encoding='utf8') as file: self._yaml_dump(content, file) except Exception as exc: self._log.err(exc) @@ -581,9 +581,9 @@ class CfgYaml: uvars = {} if not self._reloading and uvariables: - for k, v in uvariables.items(): - content = userinput(v, debug=self._debug) - uvars[k] = content + for name, prompt in uvariables.items(): + content = userinput(prompt, debug=self._debug) + uvars[name] = content if uvars: uvars = uvars.copy() @@ -1105,7 +1105,7 @@ class CfgYaml: if self._debug: self._dbg('----------start:{}----------'.format(path)) cfg = '\n' - with open(path, 'r') as file: + with open(path, 'r', encoding='utf8') as file: for line in file: cfg += line self._dbg(cfg.rstrip()) @@ -1150,7 +1150,7 @@ class CfgYaml: @classmethod def _yaml_load(cls, path): """load from yaml""" - with open(path, 'r') as file: + with open(path, 'r', encoding='utf8') as file: data = yaml() data.typ = 'rt' content = data.load(file) diff --git a/dotdrop/templategen.py b/dotdrop/templategen.py index 400af67..8b35e07 100644 --- a/dotdrop/templategen.py +++ b/dotdrop/templategen.py @@ -183,7 +183,7 @@ class Templategen: path = os.path.normpath(path) if not os.path.exists(path): raise TemplateNotFound(path) - with open(path, 'r') as file: + with open(path, 'r', encoding='utf8') as file: content = file.read() return content From aa8e1d8b3ec5cb2e24e9c19cad7bfd4170127175 Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Wed, 22 Sep 2021 11:25:44 +0200 Subject: [PATCH 03/11] adding tests for #318 --- tests-ng/uservariables.sh | 94 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100755 tests-ng/uservariables.sh diff --git a/tests-ng/uservariables.sh b/tests-ng/uservariables.sh new file mode 100755 index 0000000..d1de238 --- /dev/null +++ b/tests-ng/uservariables.sh @@ -0,0 +1,94 @@ +#!/usr/bin/env bash +# author: deadc0de6 (https://github.com/deadc0de6) +# Copyright (c) 2021, deadc0de6 +# +# test user variables from yaml file +# returns 1 in case of error +# + +# exit on first error +set -e + +# all this crap to get current path +rl="readlink -f" +if ! ${rl} "${0}" >/dev/null 2>&1; then + rl="realpath" + + if ! hash ${rl}; then + echo "\"${rl}\" not found !" && exit 1 + fi +fi +cur=$(dirname "$(${rl} "${0}")") + +#hash dotdrop >/dev/null 2>&1 +#[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 + +#echo "called with ${1}" + +# dotdrop path can be pass as argument +ddpath="${cur}/../" +[ "${1}" != "" ] && ddpath="${1}" +[ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 + +export PYTHONPATH="${ddpath}:${PYTHONPATH}" +bin="python3 -m dotdrop.dotdrop" +hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true + +echo "dotdrop path: ${ddpath}" +echo "pythonpath: ${PYTHONPATH}" + +# get the helpers +source ${cur}/helpers + +echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" + +################################################################ +# this is the test +################################################################ + +# the dotfile source +tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` +mkdir -p ${tmps}/dotfiles +# the dotfile destination +tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` +#echo "dotfile destination: ${tmpd}" + +# create the config file +cfg="${tmps}/config.yaml" + +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles +uservariables: + var1: "var1" + var2: "var2" +dotfiles: + f_abc: + dst: ${tmpd}/abc + src: abc +profiles: + p1: + dotfiles: + - f_abc +_EOF +#cat ${cfg} + +# create the dotfile +echo "var1: {{@@ var1 @@}}" > ${tmps}/dotfiles/abc +echo "var2: {{@@ var2 @@}}" >> ${tmps}/dotfiles/abc + +# install +cd ${ddpath} | echo -e 'var1contentxxx\nvar2contentyyy\n' | ${bin} install -f -c ${cfg} -p p1 -V + +cat ${tmpd}/abc + +grep '^var1: var1contentxxx$' ${tmpd}/abc >/dev/null +grep '^var2: var2contentyyy$' ${tmpd}/abc >/dev/null + +## CLEANING +rm -rf ${tmps} ${tmpd} ${scr} + +echo "OK" +exit 0 From ac4c6213b1dd5e6f84513e7f2b9cfcf390fbbacb Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Wed, 22 Sep 2021 11:31:52 +0200 Subject: [PATCH 04/11] uservariables takes precendence over other variables --- dotdrop/cfg_yaml.py | 2 +- tests-ng/uservariables.sh | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/dotdrop/cfg_yaml.py b/dotdrop/cfg_yaml.py index 95c1a68..5741545 100644 --- a/dotdrop/cfg_yaml.py +++ b/dotdrop/cfg_yaml.py @@ -169,7 +169,7 @@ class CfgYaml: # parse the "uservariables" block uvariables = self._parse_blk_uservariables(self._yaml_dict) - self._add_variables(uvariables, template=False) + self._add_variables(uvariables, template=False, prio=True) # now template variables and dynvariables from the same pool self._rec_resolve_variables(self.variables) diff --git a/tests-ng/uservariables.sh b/tests-ng/uservariables.sh index d1de238..46321fe 100755 --- a/tests-ng/uservariables.sh +++ b/tests-ng/uservariables.sh @@ -61,6 +61,12 @@ config: backup: true create: true dotpath: dotfiles +variables: + var1: abc + var2: def +dynvariables: + var1: "echo ghi" + var2: "echo jkl" uservariables: var1: "var1" var2: "var2" From eb0133854ddbbdbb2725a26f7c77fba5eff78397 Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Wed, 22 Sep 2021 11:42:53 +0200 Subject: [PATCH 05/11] ignore f-string warning --- tests.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests.sh b/tests.sh index b52ec1e..641a916 100755 --- a/tests.sh +++ b/tests.sh @@ -30,6 +30,7 @@ pylint \ --disable=R0912 \ --disable=R0911 \ --disable=R1732 \ + --disable=C0209 \ dotdrop/ # retrieve the nosetests binary From 4dae77c0cc671452b0d4c966f24fbcf95d4f248e Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Wed, 22 Sep 2021 15:08:22 +0200 Subject: [PATCH 06/11] fix C0201 --- dotdrop/cfg_yaml.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotdrop/cfg_yaml.py b/dotdrop/cfg_yaml.py index 5741545..273b492 100644 --- a/dotdrop/cfg_yaml.py +++ b/dotdrop/cfg_yaml.py @@ -1308,7 +1308,7 @@ class CfgYaml: # the included profiles inc_profiles = [] - if self._profile and self._profile in self.profiles.keys(): + if self._profile and self._profile in self.profiles: pentry = self.profiles.get(self._profile) inc_profiles = pentry.get(self.key_profile_include, []) From dcdc10d31443be8e8499661ef72ad92381fe67df Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Wed, 22 Sep 2021 15:08:29 +0200 Subject: [PATCH 07/11] add lint tools versions --- tests.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests.sh b/tests.sh index 641a916..debebcf 100755 --- a/tests.sh +++ b/tests.sh @@ -6,6 +6,14 @@ #set -ev set -e +# versions +echo "pylint version:" +pylint --version +echo "pycodestyle version:" +pycodestyle --version +echo "pyflakes version:" +pyflakes --version + # PEP8 tests which pycodestyle >/dev/null 2>&1 [ "$?" != "0" ] && echo "Install pycodestyle" && exit 1 @@ -39,6 +47,8 @@ which ${nosebin} >/dev/null 2>&1 [ "$?" != "0" ] && nosebin="nosetests3" which ${nosebin} >/dev/null 2>&1 [ "$?" != "0" ] && echo "Install nosetests" && exit 1 +echo "nose version:" +${nosebin} --version # do not print debugs when running tests (faster) export DOTDROP_FORCE_NODEBUG=yes From 64eb15f97e4e9d514962273a5a0b874a9bccd7f7 Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Thu, 23 Sep 2021 21:05:51 +0200 Subject: [PATCH 08/11] change precedence of uservariables --- dotdrop/cfg_yaml.py | 2 +- tests-ng/uservariables.sh | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/dotdrop/cfg_yaml.py b/dotdrop/cfg_yaml.py index 273b492..e682792 100644 --- a/dotdrop/cfg_yaml.py +++ b/dotdrop/cfg_yaml.py @@ -169,7 +169,7 @@ class CfgYaml: # parse the "uservariables" block uvariables = self._parse_blk_uservariables(self._yaml_dict) - self._add_variables(uvariables, template=False, prio=True) + self._add_variables(uvariables, template=False, prio=False) # now template variables and dynvariables from the same pool self._rec_resolve_variables(self.variables) diff --git a/tests-ng/uservariables.sh b/tests-ng/uservariables.sh index 46321fe..cb7bf6b 100755 --- a/tests-ng/uservariables.sh +++ b/tests-ng/uservariables.sh @@ -62,14 +62,14 @@ config: create: true dotpath: dotfiles variables: - var1: abc - var2: def + var4: "variables_var4" dynvariables: - var1: "echo ghi" - var2: "echo jkl" + var3: "echo dynvariables_var3" uservariables: var1: "var1" var2: "var2" + var3: "var3" + var4: "var4" dotfiles: f_abc: dst: ${tmpd}/abc @@ -84,14 +84,18 @@ _EOF # create the dotfile echo "var1: {{@@ var1 @@}}" > ${tmps}/dotfiles/abc echo "var2: {{@@ var2 @@}}" >> ${tmps}/dotfiles/abc +echo "var3: {{@@ var3 @@}}" >> ${tmps}/dotfiles/abc +echo "var4: {{@@ var4 @@}}" >> ${tmps}/dotfiles/abc # install -cd ${ddpath} | echo -e 'var1contentxxx\nvar2contentyyy\n' | ${bin} install -f -c ${cfg} -p p1 -V +cd ${ddpath} | echo -e 'var1contentxxx\nvar2contentyyy\nvar3\nvar4\n' | ${bin} install -f -c ${cfg} -p p1 -V cat ${tmpd}/abc grep '^var1: var1contentxxx$' ${tmpd}/abc >/dev/null grep '^var2: var2contentyyy$' ${tmpd}/abc >/dev/null +grep '^var3: dynvariables_var3$' ${tmpd}/abc >/dev/null +grep '^var4: variables_var4$' ${tmpd}/abc >/dev/null ## CLEANING rm -rf ${tmps} ${tmpd} ${scr} From e2e86d3a9ddfc8a02b49be384d0a9657e6050cf3 Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Thu, 23 Sep 2021 21:34:47 +0200 Subject: [PATCH 09/11] save uservariables to file --- dotdrop/cfg_yaml.py | 70 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/dotdrop/cfg_yaml.py b/dotdrop/cfg_yaml.py index e682792..c44998a 100644 --- a/dotdrop/cfg_yaml.py +++ b/dotdrop/cfg_yaml.py @@ -55,6 +55,8 @@ class CfgYaml: action_pre = 'pre' action_post = 'post' + save_uservariables_name = 'uservariables{}.yaml' + # profiles/dotfiles entries key_dotfile_src = 'src' key_dotfile_dst = 'dst' @@ -167,10 +169,6 @@ class CfgYaml: dvariables = self._parse_blk_dynvariables(self._yaml_dict) self._add_variables(dvariables, template=False) - # parse the "uservariables" block - uvariables = self._parse_blk_uservariables(self._yaml_dict) - self._add_variables(uvariables, template=False, prio=False) - # now template variables and dynvariables from the same pool self._rec_resolve_variables(self.variables) # and execute dvariables @@ -257,6 +255,12 @@ class CfgYaml: # template dotfiles entries self._template_dotfiles_entries() + # parse the "uservariables" block + uvariables = self._parse_blk_uservariables(self._yaml_dict, + self.variables) + self._add_variables(uvariables, template=False, prio=False) + + # end of parsing if self._debug: self._dbg('########### {} ###########'.format('final config')) self._debug_entries() @@ -573,7 +577,7 @@ class CfgYaml: self._debug_dict('dynvariables block', dvariables) return dvariables - def _parse_blk_uservariables(self, dic): + def _parse_blk_uservariables(self, dic, current): """parse the "uservariables" block""" uvariables = self._get_entry(dic, self.key_uvariables, @@ -581,14 +585,31 @@ class CfgYaml: uvars = {} if not self._reloading and uvariables: - for name, prompt in uvariables.items(): - content = userinput(prompt, debug=self._debug) - uvars[name] = content + try: + for name, prompt in uvariables.items(): + if name in current: + # ignore if already defined + if self._debug: + self._dbg('ignore uservariables {}'.format(name)) + continue + content = userinput(prompt, debug=self._debug) + uvars[name] = content + except KeyboardInterrupt as exc: + raise YamlException('interrupted') from exc if uvars: uvars = uvars.copy() if self._debug: self._debug_dict('uservariables block', uvars) + + # save uservariables + if uvars: + try: + self._save_uservariables(uvars) + except YamlException: + # ignore + pass + return uvars ######################################################## @@ -1381,7 +1402,7 @@ class CfgYaml: - Checks for path existence, taking in account fatal_not_found. This method always returns a list containing only absolute paths existing on the filesystem. If the input is not a glob, the list - contains at most one element, otheriwse it could hold more. + contains at most one element, otherwise it could hold more. """ path, fatal_not_found = self._parse_extended_import_path(path_entry) path = self._norm_path(path) @@ -1541,3 +1562,34 @@ class CfgYaml: def _dbg(self, content): pre = os.path.basename(self._path) self._log.dbg('[{}] {}'.format(pre, content)) + + def _save_uservariables(self, uvars): + """save uservariables to file""" + parent = os.path.dirname(self._path) + # find a unique path + path = None + cnt = 0 + while True: + if cnt == 0: + name = self.save_uservariables_name.format('') + else: + name = self.save_uservariables_name.format('-{}'.format(cnt)) + cnt += 1 + + path = os.path.join(parent, name) + if not os.path.exists(path): + break + + # save the config + content = {'variables': uvars} + try: + if self._debug: + self._dbg('saving uservariables values to {}'.format(path)) + with open(path, 'w', encoding='utf8') as file: + self._yaml_dump(content, file) + except Exception as exc: + # self._log.err(exc) + err = 'error saving uservariables to {}'.format(path) + self._log.err(err) + raise YamlException(err) from exc + self._log.log('uservariables values saved to {}'.format(path)) From 3b7d290f4ad2520d1d46a42bb407eb64baadbc47 Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Fri, 24 Sep 2021 20:54:20 +0200 Subject: [PATCH 10/11] update doc --- docs/config-details.md | 31 +++++++++++++++++++++++++ docs/config-format.md | 15 ++++++++++-- docs/config.md | 3 +++ docs/howto/howto.md | 4 ++++ docs/howto/prompt-user-for-variables.md | 26 +++++++++++++++++++++ 5 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 docs/howto/prompt-user-for-variables.md diff --git a/docs/config-details.md b/docs/config-details.md index efe2cea..82a4f7f 100644 --- a/docs/config-details.md +++ b/docs/config-details.md @@ -287,6 +287,37 @@ variables: They have the same properties as [Variables](config.md#variables). +## Entry uservariables + +If you want to manually enter variables values, you can use the +`uservariables` entry. Each variable will be prompted to the user. + +For example +```yaml +uservariables: + emailvar: "email" +``` + +will prompt the user to enter a value for the variable `emailvar`: +``` +Please provide the value for "email": +``` + +And store the entered text as the value for the variable `email`. +The variable can then be used as any other [variables](config.md#variables). + +`uservariables` are eventually saved to `uservariables.yaml` (relatively to the +config file). +This allow to use the following construct to prompt once for some specific variables and +then store them in a file. You might also want to add `uservariables.yaml` to your `.gitignore`. +```yaml +uservariables: + emailvar: "email" +config: + import_variables: + - uservariables.yaml:optional +``` + ## Entry profile variables Profile variables will take precedence over globally defined variables. diff --git a/docs/config-format.md b/docs/config-format.md index d30bd92..17c7aa9 100644 --- a/docs/config-format.md +++ b/docs/config-format.md @@ -45,8 +45,8 @@ The **dotfiles** entry (mandatory) contains a list of dotfiles managed by dotdro Entry | Description -------- | ------------- -`dst` | where this dotfile needs to be deployed (dotfile with empty `dst` are ignored and considered installed, can use `variables` and `dynvariables`, make sure to quote) -`src` | dotfile path within the `dotpath` (dotfile with empty `src` are ignored and considered installed, can use `variables` and `dynvariables`, make sure to quote) +`dst` | where this dotfile needs to be deployed (dotfile with empty `dst` are ignored and considered installed, can use `variables`, make sure to quote) +`src` | dotfile path within the `dotpath` (dotfile with empty `src` are ignored and considered installed, can use `variables`, make sure to quote) `link` | define how this dotfile is installed. Possible values: *nolink*, *link*, *link_children* (see [Symlinking dotfiles](config.md#symlink-dotfiles)) (defaults to value of `link_dotfile_default`) `actions` | list of action keys that need to be defined in the **actions** entry below (see [actions](config-details.md#entry-actions)) `chmod` | defines the file permissions in octal notation to apply during installation (see [permissions](config.md#permissions)) @@ -177,3 +177,14 @@ The **dynvariables** entry (optional) contains a list of interpreted variables dynvariables: : ``` + +## uservariables entry + +The **uservariables** entry (optional) contains a list of variables +to be queried to the user for their values. +(see [User variables](config-details.md#entry-uservariables)) + +```yaml +uservariables: + : +``` diff --git a/docs/config.md b/docs/config.md index d1a1758..7990b33 100644 --- a/docs/config.md +++ b/docs/config.md @@ -39,6 +39,7 @@ Following variables are available in the config files: * [variables defined in the config](config-details.md#entry-variables) * [interpreted variables defined in the config](config-details.md#entry-dynvariables) +* [user variables defined in the config](config-details.md#entry-uservariables) * [profile variables defined in the config](config-details.md#entry-profile-variables) * environment variables: `{{@@ env['MY_VAR'] @@}}` * dotdrop header: `{{@@ header() @@}}` (see [Dotdrop header](templating.md#dotdrop-header)) @@ -60,6 +61,8 @@ Here are some rules on the use of variables in configs: * profile `(dyn)variables` take precedence over profile's included `(dyn)variables` * external/imported `(dyn)variables` take precedence over `(dyn)variables` defined inside the main config file +* [user variables](config-details.md#entry-uservariables) are ignored if + any other variable with the same key is defined ## Permissions diff --git a/docs/howto/howto.md b/docs/howto/howto.md index 5218664..bf066a2 100644 --- a/docs/howto/howto.md +++ b/docs/howto/howto.md @@ -43,3 +43,7 @@ ## Symlink dotfiles [Symlink dotfiles](symlink-dotfiles.md) + +## Prompt user for variables + +[Prompt user for variables](prompt-user-for-variables.md) diff --git a/docs/howto/prompt-user-for-variables.md b/docs/howto/prompt-user-for-variables.md new file mode 100644 index 0000000..fbc3db9 --- /dev/null +++ b/docs/howto/prompt-user-for-variables.md @@ -0,0 +1,26 @@ +# Prompt user for variables + +With the use of [uservariables](config-details.md#entry-uservariables), +one can define specific variables that need to be initially filled in manually +by the user on first run. + +The provided values are then automatically saved by dotdrop to `uservariables.yaml`, +which can be included in the main config as a file from which variables are imported +using [import_variables](config-details.md#entry-import_variables). + +Let's say for example that you want to provide manually the email value +on new hosts you deploy your dotfiles to. + +You'd add the following elements to your config: +```yaml +uservariables: + emailvar: "email" +config: + import_variables: + - uservariables.yaml:optional +``` + +On first run, the `emailvar` is prompted to the user and then saved +to `uservariables.yaml`. Since this file is imported, the value for +`emailvar` will automatically be filled in without prompting the +user on subsequent calls. From 0123ab4016d554e7766256088831bc1626a0dfcf Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Fri, 24 Sep 2021 20:55:51 +0200 Subject: [PATCH 11/11] fix doc links --- docs/howto/prompt-user-for-variables.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/howto/prompt-user-for-variables.md b/docs/howto/prompt-user-for-variables.md index fbc3db9..0b7e109 100644 --- a/docs/howto/prompt-user-for-variables.md +++ b/docs/howto/prompt-user-for-variables.md @@ -1,12 +1,12 @@ # Prompt user for variables -With the use of [uservariables](config-details.md#entry-uservariables), +With the use of [uservariables](../config-details.md#entry-uservariables), one can define specific variables that need to be initially filled in manually by the user on first run. The provided values are then automatically saved by dotdrop to `uservariables.yaml`, which can be included in the main config as a file from which variables are imported -using [import_variables](config-details.md#entry-import_variables). +using [import_variables](../config-details.md#entry-import_variables). Let's say for example that you want to provide manually the email value on new hosts you deploy your dotfiles to.