diff --git a/dvc/cli/__init__.py b/dvc/cli/__init__.py index 3910ebf731..bcdb1e5e66 100644 --- a/dvc/cli/__init__.py +++ b/dvc/cli/__init__.py @@ -32,6 +32,7 @@ def parse_args(argv=None): parser = get_main_parser() args = parser.parse_args(argv) + args.parser = parser return args diff --git a/dvc/cli/completion.py b/dvc/cli/completion.py new file mode 100644 index 0000000000..5d2025bf8d --- /dev/null +++ b/dvc/cli/completion.py @@ -0,0 +1,73 @@ +import shtab + +BASH_PREAMBLE = """ +# $1=COMP_WORDS[1] +_dvc_compgen_DVCFiles() { + compgen -d -S '/' -- $1 # recurse into subdirs + compgen -f -X '!*?.dvc' -- $1 + compgen -f -X '!*Dvcfile' -- $1 + compgen -f -X '!*dvc.yaml' -- $1 +} + +_dvc_compgen_stages() { + local _dvc_stages=($(dvc stage list -q --names-only)) + compgen -W "${_dvc_stages[*]}" -- $1 +} +_dvc_compgen_stages_and_files() { + _dvc_compgen_DVCFiles $1 + _dvc_compgen_stages $1 +} + +_dvc_compgen_exps() { + local _dvc_exps=($(dvc exp list -q --all-commits --names-only)) + compgen -W "${_dvc_exps[*]}" -- $1 +} +""" + +ZSH_PREAMBLE = """ +_dvc_compadd_DVCFiles() { + _files -g '(*?.dvc|Dvcfile|dvc.yaml)' +} +_dvc_compadd_stages() { + # this will also show up the description of the stages + _describe 'stages' "($(_dvc_stages_output))" +} + +_dvc_stages_output() { + dvc stage list -q | awk '{ + # escape possible `:` on the stage name + sub(/:/, "\\\\\\\\:", $1); + # read all of the columns except the first + # reading `out` from $2, so as not to have a leading whitespace + out=$2; for(i=3;i<=NF;i++){out=out" "$i}; + # print key, ":" and then single-quote the description + # colon is a delimiter used by `_describe` to separate field/description + print $1":""\\047"out"\\047" + # single quote -> \\047 + }' +} + +_dvc_compadd_stages_and_files() { + _dvc_compadd_DVCFiles + _dvc_compadd_stages +} + +_dvc_compadd_exps() { + _describe 'experiments' "($(dvc exp list -q --all-commits --names-only))" +} +""" + +PREAMBLE = { + "bash": BASH_PREAMBLE, + "zsh": ZSH_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"} +DVCFILES_AND_STAGE = { + "bash": "_dvc_compgen_stages_and_files", + "zsh": "_dvc_compadd_stages_and_files", +} +EXPERIMENT = {"bash": "_dvc_compgen_exps", "zsh": "_dvc_compadd_exps"} diff --git a/dvc/commands/add.py b/dvc/commands/add.py index 65491088dd..1cc508496f 100644 --- a/dvc/commands/add.py +++ b/dvc/commands/add.py @@ -1,9 +1,9 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion logger = logging.getLogger(__name__) diff --git a/dvc/commands/cache.py b/dvc/commands/cache.py index 5e9e5b94d4..6d23fdfae6 100644 --- a/dvc/commands/cache.py +++ b/dvc/commands/cache.py @@ -1,7 +1,7 @@ import argparse +from dvc.cli import completion from dvc.cli.utils import append_doc_link, fix_subparsers -from dvc.commands import completion from dvc.commands.config import CmdConfig from dvc.ui import ui diff --git a/dvc/commands/check_ignore.py b/dvc/commands/check_ignore.py index aeb6984207..fcfd9da572 100644 --- a/dvc/commands/check_ignore.py +++ b/dvc/commands/check_ignore.py @@ -1,8 +1,8 @@ import argparse +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion from dvc.ui import ui diff --git a/dvc/commands/checkout.py b/dvc/commands/checkout.py index 1cbf8e3c7f..c396b10d39 100644 --- a/dvc/commands/checkout.py +++ b/dvc/commands/checkout.py @@ -1,9 +1,9 @@ import argparse import operator +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion from dvc.exceptions import CheckoutError from dvc.ui import ui diff --git a/dvc/commands/commit.py b/dvc/commands/commit.py index bc28355be4..c494a3677d 100644 --- a/dvc/commands/commit.py +++ b/dvc/commands/commit.py @@ -1,9 +1,9 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion logger = logging.getLogger(__name__) diff --git a/dvc/commands/completion.py b/dvc/commands/completion.py index 6e56ce7b75..8ea5ae31d4 100644 --- a/dvc/commands/completion.py +++ b/dvc/commands/completion.py @@ -1,92 +1,20 @@ import argparse import logging -import shtab - from dvc.cli.command import CmdBaseNoRepo +from dvc.cli.completion import PREAMBLE from dvc.cli.utils import append_doc_link from dvc.ui import ui logger = logging.getLogger(__name__) -FILE = shtab.FILE -DIR = shtab.DIRECTORY - -PREAMBLE = { - "bash": """ -# $1=COMP_WORDS[1] -_dvc_compgen_DVCFiles() { - compgen -d -S '/' -- $1 # recurse into subdirs - compgen -f -X '!*?.dvc' -- $1 - compgen -f -X '!*Dvcfile' -- $1 - compgen -f -X '!*dvc.yaml' -- $1 -} - -_dvc_compgen_stages() { - local _dvc_stages=($(dvc stage list -q --names-only)) - compgen -W "${_dvc_stages[*]}" -- $1 -} -_dvc_compgen_stages_and_files() { - _dvc_compgen_DVCFiles $1 - _dvc_compgen_stages $1 -} - -_dvc_compgen_exps() { - local _dvc_exps=($(dvc exp list -q --all-commits --names-only)) - compgen -W "${_dvc_exps[*]}" -- $1 -} - """, - "zsh": """ -_dvc_compadd_DVCFiles() { - _files -g '(*?.dvc|Dvcfile|dvc.yaml)' -} -_dvc_compadd_stages() { - # this will also show up the description of the stages - _describe 'stages' "($(_dvc_stages_output))" -} - -_dvc_stages_output() { - dvc stage list -q | awk '{ - # escape possible `:` on the stage name - sub(/:/, "\\\\\\\\:", $1); - # read all of the columns except the first - # reading `out` from $2, so as not to have a leading whitespace - out=$2; for(i=3;i<=NF;i++){out=out" "$i}; - # print key, ":" and then single-quote the description - # colon is a delimiter used by `_describe` to separate field/description - print $1":""\\047"out"\\047" - # single quote -> \\047 - }' -} - -_dvc_compadd_stages_and_files() { - _dvc_compadd_DVCFiles - _dvc_compadd_stages -} - -_dvc_compadd_exps() { - _describe 'experiments' "($(dvc exp list -q --all-commits --names-only))" -} - """, -} - -DVC_FILE = {"bash": "_dvc_compgen_DVCFiles", "zsh": "_dvc_compadd_DVCFiles"} - -STAGE = {"bash": "_dvc_compgen_stages", "zsh": "_dvc_compadd_stages"} - -DVCFILES_AND_STAGE = { - "bash": "_dvc_compgen_stages_and_files", - "zsh": "_dvc_compadd_stages_and_files", -} - -EXPERIMENT = {"bash": "_dvc_compgen_exps", "zsh": "_dvc_compadd_exps"} class CmdCompletion(CmdBaseNoRepo): def run(self): - from dvc.cli.parser import get_main_parser + import shtab - parser = get_main_parser() shell = self.args.shell + parser = self.args.parser script = shtab.complete(parser, shell=shell, preamble=PREAMBLE) ui.write(script, force=True) return 0 diff --git a/dvc/commands/daemon.py b/dvc/commands/daemon.py index 3e21289932..2a22de3d7f 100644 --- a/dvc/commands/daemon.py +++ b/dvc/commands/daemon.py @@ -1,6 +1,6 @@ +from dvc.cli import completion from dvc.cli.command import CmdBaseNoRepo from dvc.cli.utils import fix_subparsers -from dvc.commands import completion class CmdDaemonBase(CmdBaseNoRepo): diff --git a/dvc/commands/data_sync.py b/dvc/commands/data_sync.py index dd56dd7f8f..22197a894c 100644 --- a/dvc/commands/data_sync.py +++ b/dvc/commands/data_sync.py @@ -1,9 +1,9 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion logger = logging.getLogger(__name__) diff --git a/dvc/commands/diff.py b/dvc/commands/diff.py index 98ff9c2b30..9313f6dc63 100644 --- a/dvc/commands/diff.py +++ b/dvc/commands/diff.py @@ -2,9 +2,9 @@ import logging import os +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion from dvc.ui import ui logger = logging.getLogger(__name__) diff --git a/dvc/commands/experiments/apply.py b/dvc/commands/experiments/apply.py index 9905fb0598..12e652ae59 100644 --- a/dvc/commands/experiments/apply.py +++ b/dvc/commands/experiments/apply.py @@ -1,9 +1,9 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion logger = logging.getLogger(__name__) diff --git a/dvc/commands/experiments/diff.py b/dvc/commands/experiments/diff.py index b39bdfc80f..9b750dff3c 100644 --- a/dvc/commands/experiments/diff.py +++ b/dvc/commands/experiments/diff.py @@ -1,9 +1,9 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion from dvc.commands.metrics import DEFAULT_PRECISION from dvc.exceptions import DvcException from dvc.ui import ui diff --git a/dvc/commands/experiments/push.py b/dvc/commands/experiments/push.py index 7673936c96..73c61bd57c 100644 --- a/dvc/commands/experiments/push.py +++ b/dvc/commands/experiments/push.py @@ -1,9 +1,9 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion from dvc.exceptions import InvalidArgumentError from dvc.ui import ui diff --git a/dvc/commands/experiments/run.py b/dvc/commands/experiments/run.py index 392ee2c2c6..2e9eac741f 100644 --- a/dvc/commands/experiments/run.py +++ b/dvc/commands/experiments/run.py @@ -1,8 +1,8 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.utils import append_doc_link -from dvc.commands import completion from dvc.commands.repro import CmdRepro from dvc.commands.repro import add_arguments as add_repro_arguments from dvc.exceptions import InvalidArgumentError diff --git a/dvc/commands/experiments/show.py b/dvc/commands/experiments/show.py index 28580b876c..6f01f76027 100644 --- a/dvc/commands/experiments/show.py +++ b/dvc/commands/experiments/show.py @@ -8,9 +8,9 @@ from funcy import lmap +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion from dvc.commands.metrics import DEFAULT_PRECISION from dvc.exceptions import DvcException, InvalidArgumentError from dvc.ui import ui diff --git a/dvc/commands/freeze.py b/dvc/commands/freeze.py index 31f0dafb5f..27c6075da8 100644 --- a/dvc/commands/freeze.py +++ b/dvc/commands/freeze.py @@ -1,9 +1,9 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion from dvc.exceptions import DvcException logger = logging.getLogger(__name__) diff --git a/dvc/commands/get.py b/dvc/commands/get.py index babc0f03d7..0098326716 100644 --- a/dvc/commands/get.py +++ b/dvc/commands/get.py @@ -1,11 +1,11 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBaseNoRepo from dvc.exceptions import DvcException from ..cli.utils import append_doc_link -from . import completion logger = logging.getLogger(__name__) diff --git a/dvc/commands/get_url.py b/dvc/commands/get_url.py index fc0d656ef9..37f0f6a307 100644 --- a/dvc/commands/get_url.py +++ b/dvc/commands/get_url.py @@ -1,11 +1,11 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBaseNoRepo from dvc.exceptions import DvcException from ..cli.utils import append_doc_link -from . import completion logger = logging.getLogger(__name__) diff --git a/dvc/commands/imp.py b/dvc/commands/imp.py index 6ddb03cac9..a31f69ecaf 100644 --- a/dvc/commands/imp.py +++ b/dvc/commands/imp.py @@ -1,9 +1,9 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion from dvc.exceptions import DvcException logger = logging.getLogger(__name__) diff --git a/dvc/commands/imp_url.py b/dvc/commands/imp_url.py index 5186dd66cc..0a8d0a15d6 100644 --- a/dvc/commands/imp_url.py +++ b/dvc/commands/imp_url.py @@ -1,9 +1,9 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion from dvc.exceptions import DvcException logger = logging.getLogger(__name__) diff --git a/dvc/commands/ls/__init__.py b/dvc/commands/ls/__init__.py index 449db04d58..dc08b70498 100644 --- a/dvc/commands/ls/__init__.py +++ b/dvc/commands/ls/__init__.py @@ -1,9 +1,9 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBaseNoRepo from dvc.cli.utils import append_doc_link -from dvc.commands import completion from dvc.commands.ls.ls_colors import LsColors from dvc.exceptions import DvcException from dvc.ui import ui diff --git a/dvc/commands/metrics.py b/dvc/commands/metrics.py index 91c793d68b..7726302448 100644 --- a/dvc/commands/metrics.py +++ b/dvc/commands/metrics.py @@ -1,9 +1,9 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link, fix_subparsers -from dvc.commands import completion from dvc.exceptions import DvcException from dvc.ui import ui from dvc.utils.serialize import encode_exception diff --git a/dvc/commands/move.py b/dvc/commands/move.py index a139e821b4..a794929985 100644 --- a/dvc/commands/move.py +++ b/dvc/commands/move.py @@ -1,9 +1,9 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion from dvc.exceptions import DvcException logger = logging.getLogger(__name__) diff --git a/dvc/commands/params.py b/dvc/commands/params.py index 90912a4c3a..8f82368b89 100644 --- a/dvc/commands/params.py +++ b/dvc/commands/params.py @@ -1,9 +1,9 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link, fix_subparsers -from dvc.commands import completion from dvc.exceptions import DvcException from dvc.ui import ui diff --git a/dvc/commands/plots.py b/dvc/commands/plots.py index 3534d92fb4..ebab8a1602 100644 --- a/dvc/commands/plots.py +++ b/dvc/commands/plots.py @@ -5,9 +5,9 @@ from funcy import first +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link, fix_subparsers -from dvc.commands import completion from dvc.exceptions import DvcException from dvc.ui import ui from dvc.utils import format_link diff --git a/dvc/commands/remove.py b/dvc/commands/remove.py index f893a3ed38..0da9c17653 100644 --- a/dvc/commands/remove.py +++ b/dvc/commands/remove.py @@ -1,9 +1,9 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion from dvc.exceptions import DvcException logger = logging.getLogger(__name__) diff --git a/dvc/commands/repro.py b/dvc/commands/repro.py index 362b20b685..137f368320 100644 --- a/dvc/commands/repro.py +++ b/dvc/commands/repro.py @@ -1,8 +1,8 @@ import argparse +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion from dvc.commands.status import CmdDataStatus diff --git a/dvc/commands/stage.py b/dvc/commands/stage.py index 6bb8985a99..4573716b45 100644 --- a/dvc/commands/stage.py +++ b/dvc/commands/stage.py @@ -3,9 +3,9 @@ from itertools import chain, filterfalse from typing import TYPE_CHECKING, Dict, Iterable, List +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link, fix_subparsers -from dvc.commands import completion from dvc.utils.cli_parse import parse_params from dvc.utils.humanize import truncate_text diff --git a/dvc/commands/unprotect.py b/dvc/commands/unprotect.py index 90a0942daf..aa24f57733 100644 --- a/dvc/commands/unprotect.py +++ b/dvc/commands/unprotect.py @@ -1,9 +1,9 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion from dvc.exceptions import DvcException logger = logging.getLogger(__name__) diff --git a/dvc/commands/update.py b/dvc/commands/update.py index 37a011d56c..709ae3c05d 100644 --- a/dvc/commands/update.py +++ b/dvc/commands/update.py @@ -1,9 +1,9 @@ import argparse import logging +from dvc.cli import completion from dvc.cli.command import CmdBase from dvc.cli.utils import append_doc_link -from dvc.commands import completion from dvc.exceptions import DvcException logger = logging.getLogger(__name__)