mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-02 15:28:30 +01:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5ae8b19a4 | ||
|
|
f2b1c41cdf | ||
|
|
ffd32dfe8a |
+130
-6
@@ -31,6 +31,27 @@ _dvc_compgen_remotes() {
|
||||
_dvc_compgen_config_vars() {
|
||||
compgen -W "${_dvc_config_vars[*]}" -- $1
|
||||
}
|
||||
|
||||
_dvc_compgen_remote_config_vars() {
|
||||
local cur prev words cword remote_name filtered
|
||||
_init_completion || return
|
||||
|
||||
# last non-option word before cursor
|
||||
local nonopts=()
|
||||
for w in "${words[@]:1:$((cword-1))}"; do
|
||||
[[ $w == -* ]] || nonopts+=("$w")
|
||||
done
|
||||
|
||||
remote_name="${nonopts[-1]}"
|
||||
if [[ -n $remote_name ]]; then
|
||||
local _dvc_remote_config_vars=($(
|
||||
dvc config --available-options -q 2> /dev/null \
|
||||
| grep "^remote\\.${remote_name}\\." \
|
||||
| sed "s/^remote\\.${remote_name}\\.//"
|
||||
))
|
||||
compgen -W "${_dvc_remote_config_vars[*]}" -- $1
|
||||
fi
|
||||
}
|
||||
"""
|
||||
|
||||
ZSH_PREAMBLE = """
|
||||
@@ -69,27 +90,111 @@ _dvc_compadd_remotes() {
|
||||
_describe 'remotes' "($(dvc remote list | cut -d' ' -f1))"
|
||||
}
|
||||
|
||||
_dvc_config_config_vars_for_completion() {
|
||||
dvc config --available-options -q 2> /dev/null
|
||||
}
|
||||
|
||||
_dvc_compadd_config_vars() {
|
||||
_describe 'config_vars' _dvc_config_vars
|
||||
}
|
||||
|
||||
_dvc_compadd_remote_config_vars() {
|
||||
local remote_name filtered
|
||||
|
||||
# last non-option word before cursor
|
||||
remote_name=${${words[1,CURRENT-1]##-*}[-1]}
|
||||
if [[ -n $remote_name ]]; then
|
||||
filtered=$(_dvc_config_config_vars_for_completion \\
|
||||
| grep "^remote.${remote_name}\\\\." \\
|
||||
| sed "s/^remote\\\\.${remote_name}\\\\.//"
|
||||
)
|
||||
compadd -- $=filtered
|
||||
fi
|
||||
}
|
||||
"""
|
||||
|
||||
FISH_PREAMBLE = """
|
||||
function __fish_complete_dvc_files
|
||||
__fish_complete_path | string match -re '\\*?.dvc|Dvcfile|dvc\\.yaml'
|
||||
end
|
||||
|
||||
function __fish_complete_dvc_stages
|
||||
for line in (dvc stage list -q)
|
||||
set -l parts (string split -m1 ' ' -- $line)
|
||||
set -l name $parts[1]
|
||||
set -l desc (string trim $parts[2])
|
||||
echo -e "$name $desc"
|
||||
end
|
||||
end
|
||||
|
||||
function __fish_complete_dvc_stages_and_files
|
||||
__fish_complete_dvc_stages
|
||||
__fish_complete_dvc_files
|
||||
end
|
||||
|
||||
function __fish_complete_dvc_experiments
|
||||
dvc exp list -q --all-commits --names-only
|
||||
end
|
||||
|
||||
function __fish_complete_dvc_remotes
|
||||
dvc remote list | cut -d' ' -f1
|
||||
end
|
||||
|
||||
function __fish_complete_dvc_remote_config_vars
|
||||
# last non-option word before cursor
|
||||
set -l remote_name (commandline -opc | string match -rv '^-' | tail -n 1)
|
||||
|
||||
if test -n "$remote_name"
|
||||
dvc config --available-options -q 2>/dev/null |
|
||||
string match -re "^remote\\.$remote_name\\." |
|
||||
string replace -r "^remote\\.$remote_name\\." ''
|
||||
end
|
||||
end
|
||||
"""
|
||||
|
||||
PREAMBLE = {
|
||||
"bash": BASH_PREAMBLE,
|
||||
"zsh": ZSH_PREAMBLE,
|
||||
"fish": FISH_PREAMBLE,
|
||||
}
|
||||
|
||||
FILE = shtab.FILE
|
||||
DIR = shtab.DIRECTORY
|
||||
DVC_FILE = {"bash": "_dvc_compgen_DVCFiles", "zsh": "_dvc_compadd_DVCFiles"}
|
||||
STAGE = {"bash": "_dvc_compgen_stages", "zsh": "_dvc_compadd_stages"}
|
||||
DVC_FILE = {
|
||||
"bash": "_dvc_compgen_DVCFiles",
|
||||
"zsh": "_dvc_compadd_DVCFiles",
|
||||
"fish": '-f -a "(__fish_complete_dvc_files)"',
|
||||
}
|
||||
STAGE = {
|
||||
"bash": "_dvc_compgen_stages",
|
||||
"zsh": "_dvc_compadd_stages",
|
||||
"fish": '-f -a "(__fish_complete_dvc_stages)"',
|
||||
}
|
||||
DVCFILES_AND_STAGE = {
|
||||
"bash": "_dvc_compgen_stages_and_files",
|
||||
"zsh": "_dvc_compadd_stages_and_files",
|
||||
"fish": '-f -a "(__fish_complete_dvc_stages_and_files)"',
|
||||
}
|
||||
EXPERIMENT = {
|
||||
"bash": "_dvc_compgen_exps",
|
||||
"zsh": "_dvc_compadd_exps",
|
||||
"fish": '-f -a "(__fish_complete_dvc_experiments)"',
|
||||
}
|
||||
REMOTE = {
|
||||
"bash": "_dvc_compgen_remotes",
|
||||
"zsh": "_dvc_compadd_remotes",
|
||||
"fish": '-f -a "(__fish_complete_dvc_remotes)"',
|
||||
}
|
||||
CONFIG_VARS = {
|
||||
"bash": "_dvc_compgen_config_vars",
|
||||
"zsh": "_dvc_compadd_config_vars",
|
||||
"fish": '-f -a "(__fish_complete_dvc_config_vars)"',
|
||||
}
|
||||
REMOTE_CONFIG_VARS = {
|
||||
"bash": "_dvc_compgen_remote_config_vars",
|
||||
"zsh": "_dvc_compadd_remote_config_vars",
|
||||
"fish": '-f -a "(__fish_complete_dvc_remote_config_vars)"',
|
||||
}
|
||||
EXPERIMENT = {"bash": "_dvc_compgen_exps", "zsh": "_dvc_compadd_exps"}
|
||||
REMOTE = {"bash": "_dvc_compgen_remotes", "zsh": "_dvc_compadd_remotes"}
|
||||
CONFIG_VARS = {"bash": "_dvc_compgen_config_vars", "zsh": "_dvc_compadd_config_vars"}
|
||||
|
||||
|
||||
def get_preamble() -> dict[str, str]:
|
||||
@@ -103,7 +208,26 @@ def get_preamble() -> dict[str, str]:
|
||||
_dvc_config_vars=(
|
||||
{nl.join(config_vars)}
|
||||
)
|
||||
"""
|
||||
indent = "\t\t".expandtabs(4) # 8 spaces
|
||||
lines = (
|
||||
"\n".join(
|
||||
f"{indent}{c} \\"
|
||||
for c in config_vars[:-1] # all but last
|
||||
)
|
||||
+ "\n"
|
||||
+ f"{indent}{config_vars[-1]}"
|
||||
) # last line without backslash
|
||||
config_vars_arr_fish = f"""
|
||||
function __fish_complete_dvc_config_vars
|
||||
set -l _dvc_config_vars \\
|
||||
{lines}
|
||||
printf %s\\n $_dvc_config_vars
|
||||
end
|
||||
"""
|
||||
for shell, preamble in PREAMBLE.items():
|
||||
ret[shell] = config_vars_arr + preamble
|
||||
if shell != "fish":
|
||||
ret[shell] = config_vars_arr + preamble
|
||||
else:
|
||||
ret[shell] = config_vars_arr_fish + preamble
|
||||
return ret
|
||||
|
||||
@@ -8,7 +8,7 @@ from dvc.ui import ui
|
||||
logger = logger.getChild(__name__)
|
||||
|
||||
|
||||
SUPPORTED_SHELLS = ["bash", "zsh"]
|
||||
SUPPORTED_SHELLS = ["bash", "zsh", "fish"]
|
||||
|
||||
|
||||
class CmdCompletion(CmdBaseNoRepo):
|
||||
|
||||
@@ -40,6 +40,15 @@ class CmdConfig(CmdBaseNoRepo):
|
||||
self.config = Config.from_cwd(validate=False)
|
||||
|
||||
def run(self):
|
||||
if self.args.available_options:
|
||||
from dvc.config_schema import contextual_config_vars_for_completion
|
||||
|
||||
ui.write(
|
||||
"\n".join(list(contextual_config_vars_for_completion(self.config))),
|
||||
force=True,
|
||||
)
|
||||
return 0
|
||||
|
||||
if self.args.show_origin and (self.args.value or self.args.unset):
|
||||
logger.error(
|
||||
"--show-origin can't be used together with any of these "
|
||||
@@ -212,6 +221,9 @@ def add_parser(subparsers, parent_parser):
|
||||
help=CONFIG_HELP,
|
||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||
)
|
||||
config_parser.add_argument(
|
||||
"--available-options", default=False, action="store_true"
|
||||
)
|
||||
config_parser.add_argument(
|
||||
"-u",
|
||||
"--unset",
|
||||
|
||||
@@ -233,7 +233,9 @@ def add_parser(subparsers, parent_parser):
|
||||
remote_modify_parser.add_argument(
|
||||
"name", help="Name of the remote"
|
||||
).complete = completion.REMOTE
|
||||
remote_modify_parser.add_argument("option", help="Name of the option to modify.")
|
||||
remote_modify_parser.add_argument(
|
||||
"option", help="Name of the option to modify."
|
||||
).complete = completion.REMOTE_CONFIG_VARS
|
||||
remote_modify_parser.add_argument(
|
||||
"value", nargs="?", help="(optional) Value of the option."
|
||||
)
|
||||
|
||||
+34
-14
@@ -60,23 +60,27 @@ def Choices(*choices): # noqa: N802
|
||||
return Any(*choices, msg="expected one of {}".format(", ".join(choices)))
|
||||
|
||||
|
||||
def _get_schema_from_url(url: str) -> str:
|
||||
parsed = urlparse(url)
|
||||
# Windows absolute paths should really have scheme == "" (local)
|
||||
if os.name == "nt" and len(parsed.scheme) == 1 and not parsed.netloc:
|
||||
return ""
|
||||
if not parsed.netloc:
|
||||
return ""
|
||||
return parsed.scheme
|
||||
|
||||
|
||||
def ByUrl(mapping): # noqa: N802
|
||||
schemas = walk_values(Schema, mapping)
|
||||
schemas: dict[str, Schema] = walk_values(Schema, mapping)
|
||||
|
||||
def validate(data):
|
||||
if "url" not in data:
|
||||
raise Invalid("expected 'url'")
|
||||
|
||||
parsed = urlparse(data["url"])
|
||||
# Windows absolute paths should really have scheme == "" (local)
|
||||
if os.name == "nt" and len(parsed.scheme) == 1 and not parsed.netloc:
|
||||
return schemas[""](data)
|
||||
if not parsed.netloc:
|
||||
return schemas[""](data)
|
||||
if parsed.scheme not in schemas:
|
||||
raise Invalid(f"Unsupported URL type {parsed.scheme}://")
|
||||
|
||||
return schemas[parsed.scheme](data)
|
||||
scheme = _get_schema_from_url(data["url"])
|
||||
if scheme not in schemas:
|
||||
raise Invalid(f"Unsupported URL type {scheme}://")
|
||||
return schemas[scheme](data)
|
||||
|
||||
return validate
|
||||
|
||||
@@ -396,9 +400,25 @@ def config_vars_for_completion(d: dict = SCHEMA, path: str = "") -> "Iterator[st
|
||||
k = k.schema
|
||||
if not isinstance(k, str):
|
||||
continue
|
||||
|
||||
keypath = path + k
|
||||
keypath = f"{path}.{k}" if path else k
|
||||
if isinstance(v, dict):
|
||||
yield from config_vars_for_completion(v, keypath + ".")
|
||||
yield from config_vars_for_completion(v, keypath)
|
||||
else:
|
||||
yield keypath
|
||||
|
||||
|
||||
def contextual_config_vars_for_completion(config) -> "Iterator[str]":
|
||||
yield from config_vars_for_completion()
|
||||
for name, data in config["remote"].items():
|
||||
if "url" not in data:
|
||||
continue
|
||||
scheme = _get_schema_from_url(data["url"])
|
||||
if scheme not in REMOTE_SCHEMAS:
|
||||
continue
|
||||
schema = REMOTE_SCHEMAS[scheme]
|
||||
if schema:
|
||||
yield from config_vars_for_completion(schema, f"remote.{name}") # type: ignore[arg-type]
|
||||
|
||||
db_schema = SCHEMA["db"][str] # type: ignore[index]
|
||||
for name in config["db"]:
|
||||
yield from config_vars_for_completion(db_schema, f"db.{name}") # type: ignore[arg-type]
|
||||
|
||||
+2
-1
@@ -69,7 +69,8 @@ dependencies = [
|
||||
"ruamel.yaml>=0.17.11",
|
||||
"scmrepo>=3.5.2,<4",
|
||||
"shortuuid>=0.5",
|
||||
"shtab<2,>=1.3.4",
|
||||
# "shtab<2,>=1.3.4",
|
||||
"shtab @ git+https://github.com/skshetry/shtab.git@fish-shell-v2",
|
||||
"tabulate>=0.8.7",
|
||||
"tomlkit>=0.11.1",
|
||||
"tqdm<5,>=4.63.1",
|
||||
|
||||
Reference in New Issue
Block a user