diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 01:03:18 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 01:03:18 +0000 |
commit | f2621414ee5f2f601424c22f00e207903e3b6104 (patch) | |
tree | 56a856dafd1ca684bb23263cacaa723ee4f404fc | |
parent | Adding debian version 1:2.11-8. (diff) | |
download | bash-completion-f2621414ee5f2f601424c22f00e207903e3b6104.tar.xz bash-completion-f2621414ee5f2f601424c22f00e207903e3b6104.zip |
Merging upstream version 1:2.12.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
961 files changed, 22661 insertions, 15480 deletions
diff --git a/.dir-locals.el b/.dir-locals.el index 56279de..19ffc12 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -2,7 +2,7 @@ ;;; For more information see (info "(emacs) Directory Variables") ((python-mode - (eval add-hook 'before-save-hook 'blacken-buffer nil t)) + (mode . ruff-format-on-save)) (sh-mode (mode . shfmt-on-save) (shfmt-arguments "-s") diff --git a/.editorconfig b/.editorconfig index 85032d1..89fd913 100644 --- a/.editorconfig +++ b/.editorconfig @@ -16,3 +16,6 @@ indent_style = tab [*.{yml,yaml}] indent_size = 2 + +[COMMIT_EDITMSG] +max_line_length = 72 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..b6505b6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,41 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +## Describe the bug + +<!-- A clear and concise description of what the bug is. --> + +## To reproduce + +<!-- Steps to reproduce the behavior: --> + +1. cd to '...' +2. Type '....' +3. See problem + +## Expected behavior + +<!-- A clear and concise description of what you expected to happen. --> + +## Versions (please complete the following information) + +- [ ] Operating system name/distribution and version: +- [ ] bash version, `echo "$BASH_VERSION"`: +- [ ] bash-completion version, `(IFS=.; echo "${BASH_COMPLETION_VERSINFO[*]}")`: + +## Additional context + +<!-- Add any other context about the problem here. --> + +## Debug trace + +<!-- + See Troubleshooting section in README.md how to generate a debug trace, + copy-paste it into a separate file and attach the file here. +--> diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..89f9eab --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,24 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +## Describe the feature/solution + +<!-- A clear and concise description of what you want to happen. --> + +## Maintenance (please complete the following information) + +<!-- + See CONTRIBUTING.md, many of the considerations for new completions + applies here, too. If upstream has been asked if they'd be interested in + shipping the completion instead of us here in bash-completion, include + link to the upstream query/issue below. +--> + +- [ ] This is a request for new completion +- [ ] Link to upstream project query about shipping the completion: diff --git a/.github/release-please-config.json b/.github/release-please-config.json new file mode 100644 index 0000000..2a16c5b --- /dev/null +++ b/.github/release-please-config.json @@ -0,0 +1,15 @@ +{ + "packages": { + ".": { + "package-name": "bash-completion", + "release-type": "simple", + "include-component-in-tag": false, + "include-v-in-tag": false + } + }, + "pull-request-title-pattern": "chore: release${component} ${version}", + "extra-files": [ + "bash_completion", + "configure.ac" + ] +} diff --git a/.github/release-please-manifest.json b/.github/release-please-manifest.json new file mode 100644 index 0000000..95b1793 --- /dev/null +++ b/.github/release-please-manifest.json @@ -0,0 +1 @@ +{".":"2.12.0"} diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 0000000..1fca10e --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,64 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base", + ":enablePreCommit", + ":prConcurrentLimit20", + ":preserveSemverRanges", + ":semanticPrefixChore" + ], + "ignorePresets": [ + ":dependencyDashboard", + ":ignoreModulesAndTests", + ":semanticPrefixFixDepsChoreOthers" + ], + "semanticCommits": "enabled", + "commitMessageTopic": "{{depName}}", + "dockerfile": { + "enabled": false + }, + "pip_requirements": { + "fileMatch": [ + "(^|/)requirements[\\w-]*\\.txt$" + ] + }, + "regexManagers": [ + { + "fileMatch": ["^\\.pre-commit-config\\.yaml$"], + "matchStrings": ["(?<depName>[\\w-]+)(?<currentValue>==[a-z0-9.]+)"], + "datasourceTemplate": "pypi" + } + ], + "packageRules": [ + { + "matchFiles": ["test/requirements.txt"], + "semanticCommitType": "test" + }, + { + "matchManagers": ["pre-commit"], + "commitMessageTopic": "{{depName}}", + "semanticCommitScope": "pre-commit" + }, + { + "matchPackagePatterns": ["(^|/)gitlint$"], + "versioning": "pep440", + "groupName": "gitlint" + }, + { + "matchPackageNames": ["perltidy/perltidy"], + "versioning": "regex:^(?<major>\\d{8})$" + }, + { + "matchPackagePatterns": ["(^|/)ruff(-pre-commit)?$"], + "groupName": "ruff", + "versioning": "pep440" + }, + { + "matchPackageNames": [ + "scop/pre-commit-shfmt", + "shellcheck-py/shellcheck-py" + ], + "versioning": "loose" + } + ] +} diff --git a/.github/requirements.txt b/.github/requirements.txt new file mode 100644 index 0000000..09ff6d5 --- /dev/null +++ b/.github/requirements.txt @@ -0,0 +1,4 @@ +-r ../test/requirements-dev.txt + +gitlint==0.19.1 +pre-commit>=2.4.0 diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..27480fa --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,94 @@ +name: ci + +on: + pull_request: + push: + branches: + - master + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: # for gitlint + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + - uses: actions/setup-python@v5 + with: + python-version: ">=3.7" + cache: pip + cache-dependency-path: | + .github/requirements.txt + test/requirements*.txt + - uses: actions/cache@v4 + with: + path: ~/.cache/pre-commit + key: pre-commit-${{hashFiles('.pre-commit-config.yaml')}} + - name: Install dependencies + run: | + python3 -m venv venv # for venv-run + source venv/bin/activate + python3 -m pip install -Ur .github/requirements.txt + - run: venv/bin/gitlint --commits "origin/$GITHUB_BASE_REF..HEAD" + if: github.event_name == 'pull_request' + - name: Run pre-commit checks + run: | + source venv/bin/activate + pre-commit run --color=always --all-files --show-diff-on-failure + + distcheck: + runs-on: ubuntu-latest + strategy: + matrix: + include: + - dist: alpine + - dist: centos7 + - dist: debian10 + - dist: debian10 + bsd: true + network: none + - dist: fedoradev + - dist: ubuntu14 + steps: + - uses: actions/checkout@v4 + - uses: google-github-actions/release-please-action@v4 + with: + config-file: .github/release-please-config.json + manifest-file: .github/release-please-manifest.json + id: release + if: github.event_name == 'push' && matrix.dist == 'alpine' + # A "container" workflow config would be cleaner here, but comes with + # some restrictions/oddities: changes root's $HOME to /github/home + # without changing the actual home dir that can cause some problems, + # and does not provide a way to run with --network none. + # fedoradev unconfined: https://bugzilla.redhat.com/1900021 + - name: Run main build + run: >- + docker run + --rm + --tty + --env CI=true + --env DIST=${{matrix.dist}} + --env BSD=${{matrix.bsd}} + --env PYTESTFLAGS="--verbose -p no:cacheprovider" + --env NETWORK=$NETWORK + ${NETWORK:+--network $NETWORK} + $(test $DIST = fedoradev && echo --security-opt seccomp=unconfined) + --volume $PWD:/usr/src/bash-completion + --workdir /usr/src/bash-completion + ghcr.io/scop/bash-completion/test:${{matrix.dist}} + test/docker/entrypoint.sh + env: + DIST: ${{matrix.dist}} + NETWORK: ${{matrix.network}} + - name: Upload release assets + run: | + set -x + gh release upload ${{steps.release.outputs.tag_name}} \ + bash-completion-$(cat version.txt).tar.xz + if: steps.release.outputs.release_created + - uses: actions/upload-artifact@v4 + with: + path: bash-completion-*.tar.xz + if: matrix.dist == 'alpine' diff --git a/.github/workflows/update-docker-images.yml b/.github/workflows/update-docker-images.yml new file mode 100644 index 0000000..5f6e269 --- /dev/null +++ b/.github/workflows/update-docker-images.yml @@ -0,0 +1,43 @@ +name: update-docker-images + +# Update Docker images when the set of commands required present for testing +# change. This is not perfect as it would be good to have the new commands +# installed already at PR time, and at least at time the change lands in the +# default branch. That way it'd be tested immediately then with images +# containing it, instead of later along with some other, completely unrelated +# change. + +on: + push: + paths: + - test/test-cmd-list.txt + - test/docker/*/Dockerfile + - test/docker/*/install-packages.sh + workflow_dispatch: + +jobs: + update-test-image: + runs-on: ubuntu-latest + if: github.repository_owner == 'scop' && github.ref == 'refs/heads/master' + strategy: + matrix: + include: + - dist: alpine + - dist: centos7 + - dist: debian10 + - dist: fedoradev + - dist: ubuntu14 + steps: + - uses: actions/checkout@v4 + - uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{github.repository_owner}} + password: ${{secrets.GITHUB_TOKEN}} + - uses: docker/build-push-action@v5 + with: + context: test + file: test/docker/${{matrix.dist}}/Dockerfile + tags: | + ghcr.io/scop/bash-completion/test:${{matrix.dist}} + push: true @@ -1,23 +1,23 @@ -*.tar* *.swp -Makefile -Makefile.in -aclocal.m4 -autom4te.cache -config.log -config.status -configure -configure.lineno -install-sh -missing -doc/*.xml +*.tar* *~ -doc/html* -bash_completion.sh -bash-completion.pc -bash-completion-config.cmake -bash-completion-config-version.cmake -__pycache__/ .pytest_cache/ -.python-version +__pycache__/ pytestdebug.log +/.python-version +/bash-completion-config-version.cmake +/bash-completion-config.cmake +/bash-completion.pc +/bash_completion.sh + +# Files generated by autotools +Makefile +Makefile.in +/aclocal.m4 +/autom4te.cache/ +/config.log +/config.status +/configure +/configure.lineno +/install-sh +/missing diff --git a/.gitlint b/.gitlint new file mode 100644 index 0000000..60fa173 --- /dev/null +++ b/.gitlint @@ -0,0 +1,13 @@ +[general] +ignore = body-is-missing +ignore-revert-commits = false +ignore-stdin = true +contrib = contrib-title-conventional-commits +regex-style-search = true + +[ignore-body-lines] +regex = ^(Co-authored-by:|((Refs|See|[*-]) )?https?://) + +[ignore-by-author-name] +regex = \[bot\] +ignore = body-is-missing,title-max-length diff --git a/.markdownlint.yaml b/.markdownlint.yaml deleted file mode 100644 index 0204e77..0000000 --- a/.markdownlint.yaml +++ /dev/null @@ -1,4 +0,0 @@ -MD007: - false # for lists in FAQ/A -MD033: - allowed_elements: [kbd] diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 57d1264..6ba2382 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,24 +1,28 @@ +default_stages: [commit] +minimum_pre_commit_version: 2.4.0 + repos: - - repo: local + - repo: https://github.com/jorisroovers/gitlint + rev: v0.19.1 + hooks: + - id: gitlint + + - repo: https://github.com/scop/pre-commit-shfmt + rev: v3.8.0-1 hooks: - id: shfmt - name: shfmt - language: golang - additional_dependencies: [mvdan.cc/sh/v3/cmd/shfmt@v3.1.2] - entry: shfmt - args: [-w, -s] types: [text] - files: ^(bash_completion|completions/.+|test/(config/bashrc|update-test-cmd-list)|.+\.sh(\.in)?)$ + files: ^(bash_completion(\.d/[^/]+\.bash)?|completions/.+|test/(config/bashrc|fallback/update-fallback-links|runLint|update-test-cmd-list)|.+\.sh(\.in)?)$ exclude: ^completions/(\.gitignore|Makefile.*)$ - repo: https://github.com/shellcheck-py/shellcheck-py - rev: v0.7.1.1 + rev: v0.9.0.6 hooks: - id: shellcheck args: [-f, gcc] types: [text] - files: ^(bash_completion|completions/.+|test/(config/bashrc|update-test-cmd-list)|.+\.sh(\.in)?)$ + files: ^(bash_completion(\.d/[^/]+\.bash)?|completions/.+|test/(config/bashrc|fallback/update-fallback-links|runLint|update-test-cmd-list)|.+\.sh(\.in)?)$ exclude: ^completions/(\.gitignore|Makefile.*)$ require_serial: false # We disable SC1090 anyway, so parallel is ok @@ -31,67 +35,70 @@ repos: files: ^test/t/.+\.py$ pass_filenames: false - - repo: https://github.com/psf/black - rev: 19.10b0 - hooks: - - id: black - types: [text] - files: ^(helpers/python|.+\.py)$ - exclude: ^completions/ + - id: update-test-fallback-links + name: update-test-fallback-links + language: script + entry: test/fallback/update-fallback-links + files: ^completions/_ + pass_filenames: false - - repo: https://gitlab.com/pycqa/flake8 - rev: 3.8.3 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.2.2 hooks: - - id: flake8 - args: [--config=test/setup.cfg] - additional_dependencies: [flake8-bugbear==20.1.4] + - id: ruff types: [text] files: ^(helpers/python|.+\.py)$ exclude: ^completions/ - - - repo: https://github.com/timothycrosley/isort - rev: 5.1.4 - hooks: - - id: isort - args: [--settings-path=test/setup.cfg] + - id: ruff-format types: [text] files: ^(helpers/python|.+\.py)$ exclude: ^completions/ - - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.782 + - repo: local hooks: - id: mypy + name: mypy + language: python + additional_dependencies: + - venv-run==0.2.0 + entry: venv-run mypy args: [--config-file=test/setup.cfg] - # Intentionally not run on helpers/python (support very old versions) + types: [python] + # Intentionally not run on helpers/python (we support very old versions) exclude: ^completions/|^test/fixtures/pytest/ - - repo: https://github.com/asottile/pyupgrade - rev: v2.7.2 - hooks: - - id: pyupgrade - args: [--py3-plus, --keep-percent-format] - exclude: ^completions/ - - repo: https://github.com/perltidy/perltidy - rev: "20200619" + rev: "20240202" hooks: - id: perltidy types: [text] files: ^(helpers/perl|.+\.p[ml])$ - - repo: local + - repo: https://github.com/scop/pre-commit-perlcritic + rev: v1.144-1 hooks: - id: perlcritic - name: perlcritic - language: perl - additional_dependencies: [PETDANCE/Perl-Critic-1.138.tar.gz] - entry: perlcritic args: [--quiet, --verbose, "5"] types: [text] files: ^(helpers/perl|.+\.p[ml])$ - - repo: https://github.com/igorshubovych/markdownlint-cli - rev: v0.23.2 + - repo: https://github.com/jackdewinter/pymarkdown + rev: v0.9.17 + hooks: + - id: pymarkdown + entry: pymarkdown + args: + - --config=.pymarkdown.json + - scan + exclude: ^CHANGELOG\.md$ + + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: check-case-conflict + + - repo: https://github.com/crate-ci/typos + rev: v1.18.2 hooks: - - id: markdownlint + - id: typos + exclude: ^(CHANGELOG\.md|test/(test-cmd-list\.txt|fixtures/.+))$ diff --git a/.pymarkdown.json b/.pymarkdown.json new file mode 100644 index 0000000..00afedc --- /dev/null +++ b/.pymarkdown.json @@ -0,0 +1,20 @@ +{ + "plugins": { + "first-line-heading": { + "//": "Does not work with GitHub issue templates", + "enabled": false + }, + "line-length": { + "//": "Disabled because necessary for tables, and no option to disable for them as of 0.9.6", + "enabled": false + }, + "no-inline-html": { + "//": "!-- for issue template, kbd for README and in general", + "allowed_elements": "!--,kbd" + }, + "ul-indent": { + "//": "Disabled for lists in FAQ/A", + "enabled": false + } + } +} diff --git a/.shellcheckrc b/.shellcheckrc index cf5ed4b..3a3d939 100644 --- a/.shellcheckrc +++ b/.shellcheckrc @@ -1,16 +1,14 @@ shell=bash +enable=deprecate-which +enable=require-double-brackets disable=SC1090 # not really fixable usually (ever?) disable=SC2034 # for localizing variables set in called functions disable=SC2128 # intentional style choice disable=SC2206 # suggested alternatives fail in posix mode or use temp files +disable=SC2209 # interferes with our `set` (literal) vs empty booleans disable=SC2207 # suggested alternatives fail in posix mode or use temp files # These disables are to be investigated and decided -disable=SC1004 -disable=SC2015 disable=SC2016 -disable=SC2086 disable=SC2155 -disable=SC2162 -disable=SC2231 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 1ab73f5..0000000 --- a/.travis.yml +++ /dev/null @@ -1,56 +0,0 @@ -language: generic - -dist: bionic - -services: - - docker - -jobs: - include: - - stage: lint - language: go - go: "1.14" - services: [] - cache: - directories: - - $HOME/.cache/pip - - $HOME/.cache/pre-commit - before_install: [] - script: - - pyenv shell 3.8 - - pip3 install "$(grep ^pre-commit test/requirements-dev.txt)" - - pre-commit run --all-files --color=always - - stage: test - env: DIST=alpine - - env: DIST=centos7 - - env: DIST=debian10 - - env: DIST=fedoradev - - env: DIST=ubuntu14 - - env: DIST=ubuntu14 BSD=true NETWORK=none - -before_install: - - docker build - --build-arg DIST=$DIST -t bash-completion:$DIST -f test/docker/Dockerfile . - -script: - - docker run --name bash-completion - -e CI=true -e DIST=$DIST -e BSD=$BSD -e NETWORK=$NETWORK - ${NETWORK:+--network $NETWORK} - -t bash-completion:$DIST - -before_deploy: - - docker start bash-completion - - docker exec bash-completion - sh -c "tar c bash-completion-$TRAVIS_TAG.tar.*" | tar xv - - docker kill bash-completion - -deploy: - provider: releases - api_key: - secure: MoK9nzmS6CBzPPIrhC0Ch6hIB3zEzLqZE6k4axoCyz/wmJFLJgX9OCq5K8zS4Jv8NuaA2C1YTcr+m56IO9N0RTmIWrS4q40fLIhKlYv6255u+wXMkGfqXbiFAZG5yndhUo8NE6QXAtixd3nQ/3/MOt2PdsOn+OdxTDmcPSXaW/ltkd/fMHynWzupdyRJ1v46IofPBrjsC1pTzW0iVqVHz64Ix3kPVjjPR9BMHzgKMJ8sPWBGZtF2ovjwsTHYPSpEyytVRecqrmEjM6QBCgfhQDqH87jOw6Y81xh1fWDCoxaZw7HlEcQ+HeHOkDdA24AYaxVoYXrKdIDXUXWt8w674Po7UWB6kIUn3J59Xaw60Sp4VaN88Y2eX9UKRcoDRHLWc8HKt4f9AUDR9YpFF08N+gKRmJFt9mCxqeJ+pyYD/coHGkGb8XvewTKihCSuH/qCWjM8XqM493DLDlJ5aELgMEcJXPXX4TmjsriOeErTY1qxRTRHJPmfUJ/kHtmpE+DxNXpwZOnyG+VoO5aEaIKbzHxX9QzWyyEhTflupdatZ2JFt1pmVDpwH9zcEifBwE0cUwhXk+LJuxHd5ePIIpvepAAnXKaxlYwchj4cFaJp7S9GZoAQughgQQkyfz0qr3J6hBhg360QAq4yjPOWjGgGz4iAG8kWd3MVXLvL+TtfBeY= - file: bash-completion-$TRAVIS_TAG.tar.xz - skip_cleanup: true - on: - repo: scop/bash-completion - condition: $DIST = alpine - tags: true diff --git a/.typos.toml b/.typos.toml new file mode 100644 index 0000000..327d012 --- /dev/null +++ b/.typos.toml @@ -0,0 +1,47 @@ +[default.extend-identifiers] +# https://github.com/crate-ci/typos/issues/436 +BRE = "BRE" + +[default.extend-words] +# completions/ri +ane = "ane" +# completions/reportbug +buildd = "buildd" +# completions/tar +caf = "caf" +# completions/chage, test/t/Makefile.am, test/t/test_chage.py, +# test/test-cmd-list.txt +chage = "chage" +# test/t/test_ccache.py +clea = "clea" +# test/t/test_pylint_3.py +clien = "clien" +# completions/openssl +ede = "ede" +# completions/make +fo = "fo" +# test/t/test_ccache.py +hel = "hel" +# completions/bts +helo = "helo" +# completions/ip +iif = "iif" +# completions/tcpdump +inout = "inout" +# test/t/unit/test_unit_expand_glob.py +ket = "ket" +# completions/tshark, test/t/test_screen.py +nd = "nd" +# completions/mplayer +oly = "oly" +# test/t/unit/test_unit_find_unique_completion_pair.py +ot = "ot" +# completions/modinfo +parm = "parm" +# completions/wget +referer = "referer" +# completions/ps +ser = "ser" + +[files] +extend-exclude = ["CHANGELOG.md"] diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..933aec8 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,1972 @@ +## 2.11 (2020-07-25) + +* lilo: add -B and -E completions ([7dd16ad](https://www.github.com/scop/bash-completion/commit/7dd16adf6ae409ee76256ac8b73977e9a88e341e)) +* lilo: honor -C when completing labels ([5b12f1d](https://www.github.com/scop/bash-completion/commit/5b12f1d49bf036f99ccd97df2c3effee63fb04d8)) +* lilo: don't complete on commented out labels ([ad6a349](https://www.github.com/scop/bash-completion/commit/ad6a3496c3517534e5791334094cc23ec7f09437)) +* test/dnssec-keygen: allow more alternatives in algorithm completion ([0f80613](https://www.github.com/scop/bash-completion/commit/0f80613bd8a554c6aece24cf694a4ba9a11e57ba)) +* test/wol: don't fail MAC test if test system has /etc/ethers entries ([8130f87](https://www.github.com/scop/bash-completion/commit/8130f87b4e035e3b439ce2f06bdb6bb495288e15)) +* : complete commands when prefixed with a backslash ([1e029e8](https://www.github.com/scop/bash-completion/commit/1e029e81dc0a121f575d35c925cc878448feccc4)) +* ipcalc: new completion ([1307b7a](https://www.github.com/scop/bash-completion/commit/1307b7ae9f809aec4d1cda74a13878c1947eb095)) +* README.md: add introduction ([3e941a6](https://www.github.com/scop/bash-completion/commit/3e941a643097d080277af00924e34ef925c4c41f)) +* chromium-browser, firefox: complete on *.txt (#379) ([d705123](https://www.github.com/scop/bash-completion/commit/d7051234afee6cc164b59660dade18f34fb0d52f)) +* test/ipcalc: fix tests with busybox ipcalc ([ba3b2ea](https://www.github.com/scop/bash-completion/commit/ba3b2ea05632e07920c4670d0297af557ba717c5)) +* lilo: work around shellcheck false positive ([42dbeef](https://www.github.com/scop/bash-completion/commit/42dbeefb8a681e52f381218c2b69e586537ab6e4)) +* test: port remaining finger, sftp, ssh, and xhost cases to pytest+pexpect ([aab32df](https://www.github.com/scop/bash-completion/commit/aab32df7ec7a9bff6059560d58c0c7088a983bd4)) +* test: port some scp test cases to pytest+pexpect ([f4f365d](https://www.github.com/scop/bash-completion/commit/f4f365dd6c619b41f9947eb3e53a120fd5173cbe)) +* test: fix spurious hosts fixture failure without avahi-browse installed ([b2c12be](https://www.github.com/scop/bash-completion/commit/b2c12be995eb4cb9aea931abb5f8c90a9f96907c)) +* test: remove some no longer needed tcl/expect code ([f066c67](https://www.github.com/scop/bash-completion/commit/f066c676f2145acb4df84461ba75847af35d2e9f)) +* test: port some _known_hosts_real unit tests to pytest+pexpect ([30aefd3](https://www.github.com/scop/bash-completion/commit/30aefd3ee918d2a2c70d24eeb37e7c36004d3ea8)) +* test: host helper lint and usage fixes ([bd3d509](https://www.github.com/scop/bash-completion/commit/bd3d509f04fe6ca0ef9477293006fada716aebca)) +* cryptsetup: add luksChangeKey arg completion (#380) ([5bb526a](https://www.github.com/scop/bash-completion/commit/5bb526a0b6f1af02b32464879c71a1fd5a5e4104)) +* tsig-keygen: new completion ([399771d](https://www.github.com/scop/bash-completion/commit/399771d6f19d839069f0eb45001887a04231885e)) +* test/upgradepkg: port remaining test case to pytest+pexpect ([3a0e9c1](https://www.github.com/scop/bash-completion/commit/3a0e9c1e78d33571f272d327c7f4fbb8dca250d8)) +* test/tsig-keygen: require command for test_options ([9f0ae30](https://www.github.com/scop/bash-completion/commit/9f0ae306200cbf5cc6e62f72f77ea8a774ea41e3)) +* test/chown,sudo: parametrize special case test, improve xfail targeting ([2f34e86](https://www.github.com/scop/bash-completion/commit/2f34e86d988733515e21b3050d4f4ab603b9adc4)) +* test: remove some no longer needed old test suite code ([8b3007f](https://www.github.com/scop/bash-completion/commit/8b3007f7315e7313add3518599ce44c288c48aa6)) +* test/cd: convert remaining test case to pytest+pexpect ([c23c807](https://www.github.com/scop/bash-completion/commit/c23c8079fb1d78f03acb5c183b85264f6c9e06db)) +* test/cd: make dir_at_point produce better debuggable failures ([a6cfbcd](https://www.github.com/scop/bash-completion/commit/a6cfbcdc729a640b1b89af4cd4c8f3d713d51a47)) +* nmap: parse options from -h output ([e99577a](https://www.github.com/scop/bash-completion/commit/e99577a3e7f7c571a61074242ab21e0245bfe3dd)) +* nmap: handle options split on equals sign ([c51ccb7](https://www.github.com/scop/bash-completion/commit/c51ccb76d1f4fa08f1260e8d204d3622dce76f4e)) +* openssl: support getting digest list from more recent openssl versions ([fe90e2a](https://www.github.com/scop/bash-completion/commit/fe90e2aef9364d2361bdc9ae57f06690de52a596)) +* openssl: parse available options from $command -help ([9e03fc5](https://www.github.com/scop/bash-completion/commit/9e03fc5ca07ecc7cbb863b2affdd06f8bbf8b415)) +* openssl: complete -writerand with filenames ([548feef](https://www.github.com/scop/bash-completion/commit/548feef55be93a99c488e31051f524a0e4c5549b)) +* totem: reuse kaffeine completions (#372) ([e4d5eba](https://www.github.com/scop/bash-completion/commit/e4d5ebadf2a7ae61162defb7d6045fb8bff3f0da)) +* test/cd: remove unused import ([9a9f09f](https://www.github.com/scop/bash-completion/commit/9a9f09fd175b859b53c014137b8c91722ef158f1)) +* test/totem: add basic test case ([9c33f68](https://www.github.com/scop/bash-completion/commit/9c33f68a04e0ec6766cb224ab025efbd42ca54e7)) +* extra/make-changelog: run through black ([c85e5b1](https://www.github.com/scop/bash-completion/commit/c85e5b16aed3e49b2a3445e67b5143c305c37883)) +* : python type hint fixes and improvements ([d1dee07](https://www.github.com/scop/bash-completion/commit/d1dee0769275e68d39ef4c49983f4c7c89534b8f)) +* test: drop redundant black args from docker runs ([eedaa1c](https://www.github.com/scop/bash-completion/commit/eedaa1c56c09d00d39347d4b4b12c5a9d2920b1f)) +* pre-commit: add config with black, flake8, and mypy ([3b82089](https://www.github.com/scop/bash-completion/commit/3b8208985813bb424bc58a2d013eda08c50f7591)) +* test: install black for Python 3.6 too ([3f1d1ee](https://www.github.com/scop/bash-completion/commit/3f1d1ee9e41f1976181fb9f8b7a8039ee42f0219)) +* test: add flake8-bugbear ([1dddc81](https://www.github.com/scop/bash-completion/commit/1dddc81eb7363dfefde6f3b595efaa8d12e05691)) +* test: add isort to pre-commit, run it ([092d20a](https://www.github.com/scop/bash-completion/commit/092d20a8c592cc801cd7604e7a2f6907a787fbf2)) +* test: shellcheck tweaks ([e0c9c5e](https://www.github.com/scop/bash-completion/commit/e0c9c5e67ffb9d3f5c4076ffd667fb4a9b6dafbe)) +* test: run pre-commit in tools container ([0a5d616](https://www.github.com/scop/bash-completion/commit/0a5d61699c25dc13fc7eec0a18a9e1ff87411dbe)) +* jarsigner: complete on *.apk too (#386) ([64449ed](https://www.github.com/scop/bash-completion/commit/64449edf99377f66739c4ce51eeaec077687b52b)) +* python: support executables with minor version (#389) ([bd3eba8](https://www.github.com/scop/bash-completion/commit/bd3eba8182e9cc72d838ea655a8c2aa25a3272fc)) +* _known_hosts_real: check that ruptime is present before calling (#390) ([6217345](https://www.github.com/scop/bash-completion/commit/62173450aa686bed5431342410eb6edd21c33e6d)) +* ip: improve completion of route subcommands (#326) ([9982cc3](https://www.github.com/scop/bash-completion/commit/9982cc34d6ea684720f171dcdfa1a20a0b5a81e3)) +* test: fix CompletionResult.__eq__ UnboundLocalError ([0e1fe15](https://www.github.com/scop/bash-completion/commit/0e1fe15aa71cd4fafe571613f9a77b17b71fbcc6)) +* copyright: add 2020 ([0055238](https://www.github.com/scop/bash-completion/commit/00552386675b8589943dc50748ab00e272979796)) +* printenv: new completion ([014b3f2](https://www.github.com/scop/bash-completion/commit/014b3f2a0e13e87f25f31fd0ccacbf09ba3bcec2)) +* _xinetd_services: look up from $BASHCOMP_XINETDDIR, add some unit tests ([ea1cfa1](https://www.github.com/scop/bash-completion/commit/ea1cfa1da4cd793f66e298dadc9b5b5a916d5a63)) +* test: ignore flake8 messages that are in black's domain ([6dae998](https://www.github.com/scop/bash-completion/commit/6dae998a9e8870fff5f9511383c5becc8005e7b1)) +* test: move shellcheck to pre-commit ([e908d02](https://www.github.com/scop/bash-completion/commit/e908d02129cf641784fcd14f0e3105bf573aaed3)) +* test: move perltidy to pre-commit, run with --converge ([15aacc9](https://www.github.com/scop/bash-completion/commit/15aacc96cb1c767f162836b121d18d7ecc744a55)) +* test: require openssl command for option argument tests ([4c64a1b](https://www.github.com/scop/bash-completion/commit/4c64a1bd293b6fe1b5ed182ac8306ed2036b2603)) +* git: trigger docker rebuild on pre-commit config change ([ffc5adf](https://www.github.com/scop/bash-completion/commit/ffc5adfb8f1d312bfc77664dc3144289e978d0ae)) +* test: split dependencies requiring Python 3.6.1+ to requirements-dev.txt ([009bf22](https://www.github.com/scop/bash-completion/commit/009bf2228c68894629eb6fd17b3dc0f1f6d67615)) +* test: upgrade mypy to 0.770 ([383cbad](https://www.github.com/scop/bash-completion/commit/383cbad64934208df355cb5c1d6f29026b3f3ebe)) +* printenv: indentation fixes ([3ac9f0a](https://www.github.com/scop/bash-completion/commit/3ac9f0a24331d0768ce16bdce4977694f037ed1e)) +* test/printenv: require command for arg completion test ([afc9052](https://www.github.com/scop/bash-completion/commit/afc9052be4990f41675766935933e95a2f8f9a20)) +* test/ldd: xfail if --help is not implemented ([71b465a](https://www.github.com/scop/bash-completion/commit/71b465a89801e60fc9c5172004e0d92353999adc)) +* test/python: add testcase for submodule completion ([900824d](https://www.github.com/scop/bash-completion/commit/900824d9162b42399c17331cbbcfe6bce56665b4)) +* pre-commit: run most python checks on helpers/python too ([5ed40e0](https://www.github.com/scop/bash-completion/commit/5ed40e089f5e5f33a125dc145f6d678fef0584ca)) +* lintian: complete paths for Ubuntu's .ddeb and Debian's buildinfo files (#397) ([0988831](https://www.github.com/scop/bash-completion/commit/0988831a7a4fea73e5d61e64dd657d69779cf8e3)) +* ip: add support for netns (#391) ([a2ccfa6](https://www.github.com/scop/bash-completion/commit/a2ccfa6bb0438cdb88ef1e551448e839bf70f99f)) +* apt-get etc: use _apt_cache_packages from apt-cache ([d90fbe3](https://www.github.com/scop/bash-completion/commit/d90fbe3bfd7e53c365897fa584edc9d2d0a2e9bf)) +* : whitespace tweaks ([3c87811](https://www.github.com/scop/bash-completion/commit/3c87811d8917852a132771e5c92b1e76886e493e)) +* : argument interaction improvements ([ec6995c](https://www.github.com/scop/bash-completion/commit/ec6995cadc3ab24246e363b4cbc2452091cd4d28)) +* test/aptitude: add some test cases ([762ee12](https://www.github.com/scop/bash-completion/commit/762ee12d24db419f02fc026e063962dde82e7275)) +* aptitude: parse options list from --help, hardcode less ([27219f8](https://www.github.com/scop/bash-completion/commit/27219f8e76970e7780062d6746ab609792bb7e3d)) +* aptitude: add some option arg (non)completions ([826b333](https://www.github.com/scop/bash-completion/commit/826b3336cfa25696b0886908609c29f87a37f8e4)) +* crontab, wodim: silence shellcheck SC2191 and SC2192 ([e81f690](https://www.github.com/scop/bash-completion/commit/e81f6908ffbbe8477f636e5ca68ffda0748c12de)) +* bash_completion: address shellcheck SC2220 ([a167497](https://www.github.com/scop/bash-completion/commit/a167497e3ea2136b51e62cb04851cb3178f9c332)) +* : address shellcheck SC2221 and SC2222 ([365fa76](https://www.github.com/scop/bash-completion/commit/365fa76e2b587bd6c9c39154433b9ced38fe091d)) +* smartctl: hush shellcheck SC2054 false positives ([0ad46d6](https://www.github.com/scop/bash-completion/commit/0ad46d6042d6dec1b28f3212551d668a1febe8d4)) +* mplayer: address shellcheck SC1078 false positive ([a6e5e99](https://www.github.com/scop/bash-completion/commit/a6e5e9953ee275b67aae8a1f34e3fdc3fa340e38)) +* java, pkgadd, sysbench: address shellcheck SC2124 ([5757fd4](https://www.github.com/scop/bash-completion/commit/5757fd4a3693da792f61ff600a0072218b4162dd)) +* chronyc, wvdial: address shellcheck SC2178 ([cddf99a](https://www.github.com/scop/bash-completion/commit/cddf99a63b9bd4d561691299a3eb04aa56e60fa1)) +* pkgadd: indentation fix ([523387e](https://www.github.com/scop/bash-completion/commit/523387e2891cf17dbf79767d0ee521c6946af46c)) +* sysbench: add --test= deprecation TODO ([9caf5c9](https://www.github.com/scop/bash-completion/commit/9caf5c99b64803be50d15421460978bfe33a85be)) +* protoc: complete all --*_out without more specific handling with dirs ([a10adf2](https://www.github.com/scop/bash-completion/commit/a10adf25a75bab2d9cd1eb5805e73d12149cb287)) +* test: don't run shellcheck on completions/.gitignore ([3f0d77f](https://www.github.com/scop/bash-completion/commit/3f0d77f079901c080d10cc2331c6def42648278e)) +* _known_hosts_real, op: address shellcheck SC2184 ([7fdd0a5](https://www.github.com/scop/bash-completion/commit/7fdd0a5582a0830d02575e290133b26f089c24e2)) +* test/aptitude: require command where necessary ([72a59a6](https://www.github.com/scop/bash-completion/commit/72a59a6a604a3fba297484732bc3eac66a702969)) +* test/printenv: xfail if --help doesn't contain options (e.g. busybox) ([2eccac4](https://www.github.com/scop/bash-completion/commit/2eccac4327e835f4ea553fe0fadf2f6103c24055)) +* insmod, modinfo, modprobe: support xz compressed modules (#401) ([2c6a522](https://www.github.com/scop/bash-completion/commit/2c6a52236026a8e3307faca7b897ae368489391d)) +* test: upgrade shellcheck to 0.7.1 ([6af1710](https://www.github.com/scop/bash-completion/commit/6af1710fcbf8ec1108a394a7d611394590957911)) +* quote_readline: fix $ret leak ([3f340bf](https://www.github.com/scop/bash-completion/commit/3f340bf8d7f63f86987a3c947db272ccd296487e)) +* info, java: address shellcheck SC2153 ([460f1b1](https://www.github.com/scop/bash-completion/commit/460f1b105f7ea3e6b26016cf61d6449c6b504c12)) +* man, perl, route, tipc: address shellcheck SC2053 ([0fcfa65](https://www.github.com/scop/bash-completion/commit/0fcfa6592bf6d4085c1e37f6d0dd00510c805a1f)) +* tipc: comment grammar and spelling fixes ([22b015e](https://www.github.com/scop/bash-completion/commit/22b015ec167cfe9cb8da1fc399067dc2d0a55f71)) +* renice: address shellcheck SC2254 ([5f25641](https://www.github.com/scop/bash-completion/commit/5f2564100ed436d4eb2dc7a664a2706304e80b66)) +* test/run: address shellcheck SC2164 ([49ac2d9](https://www.github.com/scop/bash-completion/commit/49ac2d9ffcc8cc2c58984ae1e38f360478ea80ed)) +* _upvar, _upvars, _variables, rpm: address shellcheck SC1083 ([e043fac](https://www.github.com/scop/bash-completion/commit/e043fac649b50c7c0e5d0a8d49ce8bd93a139322)) +* mutt: address shellcheck SC2088 ([2404e97](https://www.github.com/scop/bash-completion/commit/2404e9755aaba02bd11471f9a6bd3f11ce3a4386)) +* ssh: add new -Q completions in OpenSSH 8.2p1 (#400) ([a5890aa](https://www.github.com/scop/bash-completion/commit/a5890aa5e29e0f1cd1500df4758d7883dd55f2f5)) +* cvs, modprobe, sh: address shellcheck SC2209 ([f894bc1](https://www.github.com/scop/bash-completion/commit/f894bc19b770d83b91612219016674aed6546604)) +* rpm, ssh, umount.linux: address shellcheck SC2120 ([d7381be](https://www.github.com/scop/bash-completion/commit/d7381be935d96244838b0a3a603639d95a0e6564)) +* _filedir_xspec: address shellcheck SC2140 ([198d3f7](https://www.github.com/scop/bash-completion/commit/198d3f71fc09f11519321b9561c31b1ef796e7dd)) +* scp: address shellcheck SC2089 and SC2090 ([c906aeb](https://www.github.com/scop/bash-completion/commit/c906aeb76cae276b04d8cbe25f80a986fec42018)) +* java, pkgadd, sysbench: address shellchec SC2124 ([34e5e6a](https://www.github.com/scop/bash-completion/commit/34e5e6a0ad9d29b4f91e93a6952050e88c5ad2a6)) +* test/lib/library.sh: address shellcheck SC2125 ([bef80ef](https://www.github.com/scop/bash-completion/commit/bef80ef624c3d7101b3661895958365f71b890a8)) +* : address shellcheck SC2046 ([1d3add4](https://www.github.com/scop/bash-completion/commit/1d3add44563e48be7a6ec6cbd4cc8bb9e27d44f0)) +* test: bump shellcheck severity to warning + some disables ([a6cd66c](https://www.github.com/scop/bash-completion/commit/a6cd66cc4b0dcf8f36e788b0ecdb637c72f0118e)) +* test: tolerate duplicates from compgen actions ([bbd6814](https://www.github.com/scop/bash-completion/commit/bbd68147a9eb829ddbae4ffed6523b69a076b6ed)) +* test/xfreerdp: skip xfreerdp kbd test if kbd-list returns empty ([9746a39](https://www.github.com/scop/bash-completion/commit/9746a39cbc2a1102c3bc9f7fff36ce36e8d05881)) +* test: make it possible to not care whether command did output or not ([1ef3ad4](https://www.github.com/scop/bash-completion/commit/1ef3ad487fb9f02b8cc641439b2049529fbdfb9e)) +* test: run skipif and xfail commands without caring if they output or not ([005ab9f](https://www.github.com/scop/bash-completion/commit/005ab9f0957f33f092d415f2ab2e1b3a3f501dfd)) +* pgrep, pkill: add --ns and --nslist arg completions ([e649ea1](https://www.github.com/scop/bash-completion/commit/e649ea16374bbacfdb84c3d9803211754f62bfc1)) +* pytest: complete test classes ([f4ac160](https://www.github.com/scop/bash-completion/commit/f4ac16016d005d91652226272e3d496ede8e5ca1)) +* pytest: add some option arg (non-)completions ([61e5d8d](https://www.github.com/scop/bash-completion/commit/61e5d8de7fcbc426c5a1e3f7f5dcda9510051eed)) +* test/cd: fix test_dir_at_point for setups that repeat "trailer" ([25b4f1d](https://www.github.com/scop/bash-completion/commit/25b4f1db77f2373f7a700998327e9d9d837da89a)) +* test: generalize complete at point test ([8314c75](https://www.github.com/scop/bash-completion/commit/8314c7576134d2a1ae948bc6f3e008e15d837886)) +* test/alias: port remaining test case to pytest+pexpect ([f81d313](https://www.github.com/scop/bash-completion/commit/f81d313138cb6ab0fd155089b3c7499d733c118b)) +* nmap: fix option parsing with BSD sed ([e712b2f](https://www.github.com/scop/bash-completion/commit/e712b2f932a4f000c75a417ab62f19532147ed52)) +* carton: fix command parsing with BSD sed ([1968b3a](https://www.github.com/scop/bash-completion/commit/1968b3ae59b20ea16fe0004ecff53831a1728467)) +* _filedir*: update link to bug-bash discussion on -X (#404) ([bfd65f3](https://www.github.com/scop/bash-completion/commit/bfd65f3be7af378d944a269e77cdf5d93aaac022)) +* openssl: update -starttls completions (#403) ([28df326](https://www.github.com/scop/bash-completion/commit/28df3269a994a33ccb8a7946a960ba26a97b6790)) +* : replace various conditional expressions with arithmetic evaluation ([2ad992a](https://www.github.com/scop/bash-completion/commit/2ad992a1bca79e0a9353afc32cbb59749f2f07c0)) +* bash_completion, invoke-rc.d, svcadm: trivial cleanups ([69a835a](https://www.github.com/scop/bash-completion/commit/69a835a335c8ecea7c8f0453097ab909838eef08)) +* : enable and address shellcheck SC2053 ([333d590](https://www.github.com/scop/bash-completion/commit/333d5908887e5133916b5987ce67ba65b6a5b343)) +* ssh-keygen: -s and -n completion improvements ([6666ebb](https://www.github.com/scop/bash-completion/commit/6666ebbb0d9934fd999937c10028f51295be5d28)) +* : array subscript cleanups ([13b5a4b](https://www.github.com/scop/bash-completion/commit/13b5a4bea8bae0d67d9286ef1d732c5dad1de685)) +* doc: recommend arithmetic evaluation ([5e5c83b](https://www.github.com/scop/bash-completion/commit/5e5c83b13808b2c29c0264284042998e4cc0816e)) +* test: remove shellcheck severity filter, add explicit disables instead ([fd19ea0](https://www.github.com/scop/bash-completion/commit/fd19ea00db362d9a33a6d4edd0d626b3da26a69c)) +* test: enable parallel pre-commit shellcheck ([48ab77e](https://www.github.com/scop/bash-completion/commit/48ab77e2ac5518ffbf8c6a2ce5b205da4b072c97)) +* __reassemble_comp_words_by_ref, java: address and work around shellcheck SC2102 ([dcf9f39](https://www.github.com/scop/bash-completion/commit/dcf9f3991d94804591fac1941587f04d3f19b4c0)) +* : more arithmetic evaluation cleanups, thanks to shellcheck SC2004 ([b147516](https://www.github.com/scop/bash-completion/commit/b147516b6081f451ace1e8172e6041029177536e)) +* bash_completion, java, tipc: for loop whitespace consistency tweaks ([3abbd23](https://www.github.com/scop/bash-completion/commit/3abbd23be045138a1d63ecdd27b5c0de9f5c1cd1)) +* pytest: address shellcheck SC2002 ([fe53ef2](https://www.github.com/scop/bash-completion/commit/fe53ef2ae8e3615c5a1186bfbc980f918b1d0c99)) +* wget: address shellcheck SC2116 ([091a7cd](https://www.github.com/scop/bash-completion/commit/091a7cde3deaeb7650e6972f5dda8c943cd1c120)) +* mutt: address shellchec SC2236 ([566c5f5](https://www.github.com/scop/bash-completion/commit/566c5f521d1d4cc3bdcba4b7555a4460d78aeebe)) +* scp: work around shellcheck SC1003 ([e1cbe8f](https://www.github.com/scop/bash-completion/commit/e1cbe8f6f0d097b51f9815dcf6729ac3abca526c)) +* ssh, xsltproc: address shellcheck SC2006 ([32421d1](https://www.github.com/scop/bash-completion/commit/32421d1d74a2915c227caa5c08457c0d7a9f18e6)) +* test: make at-point completion tests easier ([e9450b8](https://www.github.com/scop/bash-completion/commit/e9450b88c38921aa9dd297f56c99c055857c1952)) +* doc: add loop variable naming guideline ([a6a59e3](https://www.github.com/scop/bash-completion/commit/a6a59e32b8dd165f04409897641ba72d11d44e1d)) +* apt-cache: fix command mode handling ([c41b772](https://www.github.com/scop/bash-completion/commit/c41b772dcb4e31c8a6ee8d3052f3d2742d7a889d)) +* crontab: fix loop over already given args ([568c658](https://www.github.com/scop/bash-completion/commit/568c658c2c0ac6097f5332d4bfe23a9cf7b4de37)) +* : various loop iteration improvements ([911a432](https://www.github.com/scop/bash-completion/commit/911a4322cdc8eb393921b2a52efbab4e394e67e2)) +* : remove some unused variables, thanks to shellcheck SC2034 ([95f3bec](https://www.github.com/scop/bash-completion/commit/95f3bec3ba948fdb4f26673e008e4bfa990b96a0)) +* test: add perlcritic to pre-commit, run on all perl ([dd890cd](https://www.github.com/scop/bash-completion/commit/dd890cd30ddc617a10c7ff114bef13ff6485536b)) +* test: run pre-commit on host instead of docker ([b8c2a95](https://www.github.com/scop/bash-completion/commit/b8c2a95c5ed41088cd94d6ece044f37b941d8a2f)) +* make: add bmake alias ([6b42551](https://www.github.com/scop/bash-completion/commit/6b42551fa0166508b1ef6c28751ccdf5c7c49f32)) +* test/make: mark more cases as requiring command ([6354520](https://www.github.com/scop/bash-completion/commit/63545202952c970146eced87ae156f023f7306e4)) +* test: run lint tests on Travis in a quickish separate first stage ([e493f6a](https://www.github.com/scop/bash-completion/commit/e493f6a2f2ea596f373c9f31e91f44633f6f2d4a)) +* test: add script to maintain list of executables for full test coverage ([e0b9397](https://www.github.com/scop/bash-completion/commit/e0b93973acdc6f3938ecc1103971a8a0d18bf5ad)) +* extra: trigger docker builds only on test-cmd-list.txt changes ([85f3c73](https://www.github.com/scop/bash-completion/commit/85f3c737d97e5f420885d9b875de73d56035c78a)) +* find: fix -exec etc argument and its completion ([3e849c2](https://www.github.com/scop/bash-completion/commit/3e849c25ef9a2a2dc95c713085898a9547a70e18)) +* reportbug, scp, sftp, svn: use compgen -c instead of _command ([e73535f](https://www.github.com/scop/bash-completion/commit/e73535f72e0190c953211625dd71d73cfb2fa7e6)) +* _command: improve commentary ([2cf6b67](https://www.github.com/scop/bash-completion/commit/2cf6b670323ad0e914c5bed13122d2ee0cf07821)) +* ssh-keygen: option and arg completion updates for new versions ([edc4f9b](https://www.github.com/scop/bash-completion/commit/edc4f9b0390ae07c572a3186bdb9741a5be321de)) +* ssh-keygen: add -b arg completions according to specified -t ([69b477b](https://www.github.com/scop/bash-completion/commit/69b477bada9672fa5ec9079f42758a866e874180)) +* ssh-keygen: -O arg updates and improvements ([63e04ee](https://www.github.com/scop/bash-completion/commit/63e04ee86aeee5dc33a0e5d80c5e4e28692ac937)) +* README: clarify loading automatically on demand ([f5e831b](https://www.github.com/scop/bash-completion/commit/f5e831bb789094dc0293e61727b0319bb5714909)) +* pre-commit, *.md: add markdownlint, address findings ([43e958a](https://www.github.com/scop/bash-completion/commit/43e958a6db294367451190624a73e5f532fb6174)) +* : doc and comment link updates ([a234784](https://www.github.com/scop/bash-completion/commit/a234784b39e657be671f292c384395ed2fd64a75)) +* pre-commit: use local perlcritic hook ([a277345](https://www.github.com/scop/bash-completion/commit/a277345460a38206837e5e98380b30c39be89734)) +* editorconfig: apply yaml settings to .yaml too ([7af92f5](https://www.github.com/scop/bash-completion/commit/7af92f506c60c32eb95d4625e542e4e67d77eee9)) +* test: add note about unescaped assert_complete single return values ([663ac51](https://www.github.com/scop/bash-completion/commit/663ac5175fd46b790beff1ac5952551b0e211f90)) +* test: port most umount test cases to pytest+pexpect ([b621591](https://www.github.com/scop/bash-completion/commit/b6215914784096189db0ef4fd9d580a249a19675)) +* Source user completion only if it's a file (#409) ([78bf738](https://www.github.com/scop/bash-completion/commit/78bf738eb082f67080ec26b64444fd9116907743)) +* test: prefix fake test commands with underscore ([5351161](https://www.github.com/scop/bash-completion/commit/53511617f0ab972d0b6912990ebf0adc3eeffe9d)) +* nmap: simplify help scraping a bit, don't try to emit unnecessary newlines ([8db05b4](https://www.github.com/scop/bash-completion/commit/8db05b4d1c6de665a76c330b484279dc279dff27)) +* test: upgrade markdownlint to 0.23.0 ([5520dd4](https://www.github.com/scop/bash-completion/commit/5520dd4a20a7e849d24cf239a63a876e48dabc1b)) +* test: fix incorrect fixtures/shared/default xfails/expectations ([f0fe52c](https://www.github.com/scop/bash-completion/commit/f0fe52c923a5becc0556798ea892d2710aa9500c)) +* pre-commit etc: add shfmt ([08db11f](https://www.github.com/scop/bash-completion/commit/08db11f12a04516622948bb6c1ff8cc50001fb3a)) +* : run all shell code through shfmt -s ([dbe0ec8](https://www.github.com/scop/bash-completion/commit/dbe0ec8c1a8a36752d3b63b685add075f36ba113)) +* travis: use golang 1.14 for shfmt ([d34719a](https://www.github.com/scop/bash-completion/commit/d34719aa79f80578fe4be11ac859f348ae62ed02)) +* apt-get: complete build-dep with dirs ([e7ea033](https://www.github.com/scop/bash-completion/commit/e7ea033f1075a99898b4ef8c3a364bb7ba23ef62)) +* secret-tool: new completion ([e9a556f](https://www.github.com/scop/bash-completion/commit/e9a556f4a233250c6f05dfd0c5e9ae17a0ffd747)) +* test/umount: convert remaining test case to pytest+pexpect ([4514d3e](https://www.github.com/scop/bash-completion/commit/4514d3e7ef774c4bdfc4fe3f9acdf66def16c664)) +* test/scp: port remaining test case to pytest+pexpect ([12de472](https://www.github.com/scop/bash-completion/commit/12de47263b5a49ae8adab7fb1c85d3a2f42852e5)) +* test/secret-tool: add to test command list ([25c1c76](https://www.github.com/scop/bash-completion/commit/25c1c76030107cf918015856299f899bfa251e80)) +* test/slapt-get: convert remaining test case to pytest+pexpect ([033f548](https://www.github.com/scop/bash-completion/commit/033f5488bdec49f635b6e0ef13784698cdf8d190)) +* apt-cache: avoid nonzero exit code from _apt_cache_packages ([ea97386](https://www.github.com/scop/bash-completion/commit/ea973866fdbb4f8f72d4e87d090950795ef68a49)) +* _xfunc: simplify ([c0f6a6d](https://www.github.com/scop/bash-completion/commit/c0f6a6d09c88a23441a46c351eff25f23e64b528)) +* test/slapt-src: convert remaining test case to pytest+pexpect ([62b3dc6](https://www.github.com/scop/bash-completion/commit/62b3dc6dc2024eb2101bddcd468552d485c60a8c)) +* test: drop some no longer needed old test suite code ([2612750](https://www.github.com/scop/bash-completion/commit/2612750d2527865f432218770ccaa0e3dd398f71)) +* lftp: use "bookmark list" command to list bookmarks ([c198a94](https://www.github.com/scop/bash-completion/commit/c198a94029aa33cfbd4bd0586e1674859337c35c)) +* test: run pytest --verbose in docker ([ea0236e](https://www.github.com/scop/bash-completion/commit/ea0236e1e6b6ad2f0ffc402e4a1d4da6365014a3)) +* test/_get_comp_words_by_ref: convert remaining test cases to pytest+pexpect ([322420d](https://www.github.com/scop/bash-completion/commit/322420d50b894e786226987c40c6d559313058f9)) +* test/__expand_tilde_by_ref: port remaining test cases to pytest+pexpect ([d258b3c](https://www.github.com/scop/bash-completion/commit/d258b3ca8ab65fec4dfc6a14c4697212e09ad69c)) +* test/_filedir: port more test cases to pytest+pexpect ([54c732a](https://www.github.com/scop/bash-completion/commit/54c732a82066e1595d8dd153e992987ea87b54b6)) +* test: drop not needed sudo on Travis ([a9822bc](https://www.github.com/scop/bash-completion/commit/a9822bc79b997cfb985b1d8c91f9c3402adce232)) +* test: run all Travis jobs on dist: bionic ([9c0a307](https://www.github.com/scop/bash-completion/commit/9c0a30729ce5dd9954ad32dd226021b733b94abd)) +* test/_filedir: port remaining test cases to pytest+pexpect ([fb7fb46](https://www.github.com/scop/bash-completion/commit/fb7fb461362fd99cf21de40821793c8a38bf6c56)) +* test: drop some no longer needed old test suite code ([4543212](https://www.github.com/scop/bash-completion/commit/4543212a52e9d569017013e1365e9d969683fb49)) +* test/_expand: port remaining test cases to pytest+pexpect ([db481c6](https://www.github.com/scop/bash-completion/commit/db481c67fd8ea17036bd432c7e41dbe578a274e4)) +* test/_filedir: fix shutil.rmtree on Python < 3.6 ([febf177](https://www.github.com/scop/bash-completion/commit/febf177e84162199394f71704cbcf58ce1dbefd3)) +* test: replace some echos with printfs ([bcdf00c](https://www.github.com/scop/bash-completion/commit/bcdf00ce3cec4e6f43521d6d24d75e4574f59b66)) +* test/_get_cword: port remaining test case to pytest+pexpect ([80ac63e](https://www.github.com/scop/bash-completion/commit/80ac63efbb3b4677514b900ba936d7af2d2c8eb9)) +* test/_known_hosts_real: port more test cases to pytest+pexpect ([5c7bb2d](https://www.github.com/scop/bash-completion/commit/5c7bb2d72c03ad28f700e82b8ca1aeaa4528fedd)) +* test: remove more no longer needed old test suite code ([b1a4de9](https://www.github.com/scop/bash-completion/commit/b1a4de9aee916b622889c28a61812092c4d76b9b)) +* test/_known_hosts_real: port remaining test cases to pytest+pexpect ([21d4fba](https://www.github.com/scop/bash-completion/commit/21d4fba9d75860454bc0c869f63d66c6cd66bca6)) +* test: remove old test suite code no longer used \o/ ([5afc3b5](https://www.github.com/scop/bash-completion/commit/5afc3b558f7651a4a0854fdd9ac0a4580876fd33)) +* test: remove unused run-shellcheck, shellcheck is in pre-commit now ([76aa130](https://www.github.com/scop/bash-completion/commit/76aa130483d6da9761715b89ce750eebed3a95b0)) +* test: shfmt bashrc ([ead40fa](https://www.github.com/scop/bash-completion/commit/ead40fab3e8e09833b632a6c1c0b828b92ae4ecb)) +* test: sync shfmt and shellcheck configs ([c21e0e1](https://www.github.com/scop/bash-completion/commit/c21e0e11025fa2117417d5ddcbe65a7edd116fe3)) +* test: upgrade pre-commit to 2.4.0+, drop shfmt kludge ([8af206f](https://www.github.com/scop/bash-completion/commit/8af206f45ad801c47e9e79060a0fbad033cd1d89)) +* test: pre-commit config cleanups, ordering ([b4eadfd](https://www.github.com/scop/bash-completion/commit/b4eadfd4b401f15acaab714c363cb0a7ee7bcf8c)) +* test: upgrade flake8 to 3.8.1 ([1f27374](https://www.github.com/scop/bash-completion/commit/1f27374d45e7062e6a74a0046bba289eda02f75a)) +* test/irb: xfail options test if --help is not available ([f5ea515](https://www.github.com/scop/bash-completion/commit/f5ea515f07ec2cbbbc63262d1f053327a9d466ae)) +* : use $ifs for storing/restoring $IFS ([acc43ed](https://www.github.com/scop/bash-completion/commit/acc43edf81c7eaf8b3556453a7cfc4b0104975cd)) +* test: try harder to restore environment and cwd on failures ([f0bf00a](https://www.github.com/scop/bash-completion/commit/f0bf00a53677285600cdf8d82e754abb7f0e0644)) +* : use more arithmetic evaluation ([328ce5b](https://www.github.com/scop/bash-completion/commit/328ce5be5b4b8822b3b9421dab4460c56990df0b)) +* test: upgrade markdownlint-cli to 0.23.1 ([2255f2a](https://www.github.com/scop/bash-completion/commit/2255f2a8577cf7d48b5572d84a6900d9ffdef75e)) +* dpkg-deb: fix --show/-W completion ([2eee0b5](https://www.github.com/scop/bash-completion/commit/2eee0b5063ae3fd8d48594bc03d2f5a9e4678ce5)) +* test: add some dpkg-query test cases ([034bdee](https://www.github.com/scop/bash-completion/commit/034bdeec06f36c12d3cbf927ca293eee321817f0)) +* dpkg-deb: add --raw-extract and -X arg completions ([69198c0](https://www.github.com/scop/bash-completion/commit/69198c0c4ef9830de1ea25d0b5c713adef8b5987)) +* test: mark known non-ASCII issues with test suite as xfail ([106e825](https://www.github.com/scop/bash-completion/commit/106e825a7f3b07c6c4d59f0b9c4e66bfa48a870f)) +* test/mr: handle missing "clean" with skipif ([eb93dde](https://www.github.com/scop/bash-completion/commit/eb93dde7304ee62e20d54cba003639b46bd18119)) +* mr: avoid herestrings, simplify command parsing ([cf64492](https://www.github.com/scop/bash-completion/commit/cf6449226350987f8d0d3ff3d329ca31c19cbcac)) +* _bashcomp_try_faketty: new function to try running command with a fake tty ([3829fe9](https://www.github.com/scop/bash-completion/commit/3829fe95d6583cc9eebc1abae1e553dedacd8cd5)) +* postfix: try to arrange a fake tty so we can tickle the usage message out ([7aea619](https://www.github.com/scop/bash-completion/commit/7aea619b1b4563f6a5a55877aeeea009e71cfd87)) +* 7z: fix -o/-w attached arg completion ([54774d6](https://www.github.com/scop/bash-completion/commit/54774d610323daff29e4cd00d5bcce23b714513f)) +* __reassemble_comp_words_by_ref: avoid triggering nounset on indirect references ([0b0323c](https://www.github.com/scop/bash-completion/commit/0b0323c514276c0143568b9e03646b65ee57e788)) +* bash_completion: line wrapping tweaks, NFC ([1d1d308](https://www.github.com/scop/bash-completion/commit/1d1d308d1f15e3ab2794c14ed54206cc56b96655)) +* test/unit: include test_unit_known_hosts_real.py in dist ([fdc9fc9](https://www.github.com/scop/bash-completion/commit/fdc9fc9b231c084c6e8de32587ec6a746898ce39)) +* test/unit: sort files included in dist ([d8f309f](https://www.github.com/scop/bash-completion/commit/d8f309f9fa8cb57067c6ef559269ea1eb3f9d98a)) +* : avoid more errors in nounset mode ([3687d27](https://www.github.com/scop/bash-completion/commit/3687d27f1ac266fa784dacc4492f0c554ed3091c)) +* test/inputrc: comment and whitespace tweaks ([1293d7c](https://www.github.com/scop/bash-completion/commit/1293d7c7258ef93c131e0e0d546064593610e731)) +* : avoid more errors in nounset mode ([b807460](https://www.github.com/scop/bash-completion/commit/b807460140aa6dda09eb2af2ecf3afa1971c84c4)) +* : avoid more errors in nounset mode ([d0a0eb5](https://www.github.com/scop/bash-completion/commit/d0a0eb5979d2831174b50e541d97559ac30d7d73)) +* : avoid more errors in nounset mode ([505fb2c](https://www.github.com/scop/bash-completion/commit/505fb2c68e38c9071542ff30fbafdab7ddc6f363)) +* : mark nounset mode as supported, issues with it are bugs now ([e85a361](https://www.github.com/scop/bash-completion/commit/e85a361199f02f3818312ba149dc64bf2c920d7a)) +* test: skip various tests if we don't get a useful usage message ([6f12de6](https://www.github.com/scop/bash-completion/commit/6f12de60230b85fbdd004c69be23be1bc9798767)) +* test/runLint: warn about [ ] instead of [[ ]] use ([f6f49db](https://www.github.com/scop/bash-completion/commit/f6f49db9175eb1ee5521bcb59ac6747bebaf1f28)) +* modprobe, tshark, _included_ssh_config_files: use [[ ]] instead of [ ] ([50ad3f8](https://www.github.com/scop/bash-completion/commit/50ad3f8d91a2782b5d10dc177e98f2ec06171e20)) +* scp, sftp, ssh: fix completion on options bundled with -4/-6 ([b4490f2](https://www.github.com/scop/bash-completion/commit/b4490f238ed534ce9084614a3580656e4cf759f6)) +* _pids, _pgids, _pnames: improve shfmt formatting ([2bfb0a7](https://www.github.com/scop/bash-completion/commit/2bfb0a7e22ca94624e13df5876fe80acc7017f1b)) +* _filedir: avoid unbound variable error on Ubuntu 14 and 16 ([ac37d77](https://www.github.com/scop/bash-completion/commit/ac37d77db99425aaa9d71fe9215e98623378a4b1)) +* ip: add more completions for ip-rule ([426d07e](https://www.github.com/scop/bash-completion/commit/426d07e33ce5379ce4fc7726c140ca3b8c7c7575)) +* ip: style fixes similar to ip-netns ([75093c0](https://www.github.com/scop/bash-completion/commit/75093c018a5dee8db1d7a97f42b0cc2c0902ef3e)) +* ip: route shfmt, arithmetic evaluation ([a1fe69a](https://www.github.com/scop/bash-completion/commit/a1fe69adf7d476984a3498e8c1616d84e9b694f1)) +* ip: complete route add table arg ([e4ad602](https://www.github.com/scop/bash-completion/commit/e4ad602f483f3574fd8630bfcd82bd88ef6def28)) +* _init_completion: fix unassigned redirect completion in nounset mode ([2e52b40](https://www.github.com/scop/bash-completion/commit/2e52b40d5087c55798c7bf006654aafd98e5deab)) +* : drop support for bash 4.1 ([e2d47ae](https://www.github.com/scop/bash-completion/commit/e2d47aea537ed18892ba485b2acba470ad79301a)) +* test: enable shellcheck SC2035 ([77a3505](https://www.github.com/scop/bash-completion/commit/77a35054a335323014f8d63879c0017ff200f9c9)) +* qemu, sbopkg: avoid unintentional globbing on option arg completions ([7dc4f61](https://www.github.com/scop/bash-completion/commit/7dc4f61dc0ebdbf45d64195ab9a8cb97768e455a)) +* qemu: add -machine arg completion ([11cd174](https://www.github.com/scop/bash-completion/commit/11cd1746d94a98fe12bd989a168204e03583bf78)) +* : avoid more errors in nounset mode ([5103c5d](https://www.github.com/scop/bash-completion/commit/5103c5dc3e236e3fa4e0e5a9048ada6ea99a9c76)) +* _command_offset, route: cleanups ([9994be6](https://www.github.com/scop/bash-completion/commit/9994be6476247261cb8d3e1befcce4af72a136b0)) +* cfrun: fix $hostfile leak ([68b5719](https://www.github.com/scop/bash-completion/commit/68b5719bbc2db1e71f76d843b4b6df41e671952b)) +* : avoid more errors in nounset mode ([f4fa0b6](https://www.github.com/scop/bash-completion/commit/f4fa0b6d0ca079e350c8a98ddaeaa4d932fb21ef)) +* bash_completion: fix array set checks with empty elements in them ([efaa991](https://www.github.com/scop/bash-completion/commit/efaa991d385e28eeb21490b3a91fd903e4f90b30)) +* _known_hosts: avoid errors in nounset mode and no arguments ([36475fc](https://www.github.com/scop/bash-completion/commit/36475fc6762edca0d52a4817aba53f7c2431b9a7)) +* pytest: add test class method completion ([ba4c941](https://www.github.com/scop/bash-completion/commit/ba4c941faa1ff5eb63e7984a6a52a7b703e2887f)) +* README: document GNU make build requirement ([3423e14](https://www.github.com/scop/bash-completion/commit/3423e14fb0e891a7d2764233eccd3cbecc983e22)) +* java, make: avoid errors in nounset mode on Ubuntu 14 and 16 ([1a633f3](https://www.github.com/scop/bash-completion/commit/1a633f3a551154ac3c70bfdc5263d73d8b3d9f3f)) +* man, mutt: avoid errors in nounset mode on Ubuntu 14 and 16 ([e5fa022](https://www.github.com/scop/bash-completion/commit/e5fa0221578dce638a84107f0ee813be89bbe3bd)) +* pytest: fix test class method completion with BSD awk ([3374911](https://www.github.com/scop/bash-completion/commit/337491161b1278a30d3f0aaf4a7cd2508ea809f5)) +* gcc: avoid errors in nounset mode ([221a6aa](https://www.github.com/scop/bash-completion/commit/221a6aa9b18bb8afe11435ee2244589bbaac0ff4)) +* bash_completion: trivial cleanups ([817d832](https://www.github.com/scop/bash-completion/commit/817d832fb7ac49eceda6ed3c21428dcc4659fa48)) +* test/_known_hosts_real: tolerate duplicates ([0b2866a](https://www.github.com/scop/bash-completion/commit/0b2866a9fe32ee24df242e200896125c7ecf65ad)) +* test/_known_hosts_real: reset COMP_KNOWN_HOSTS_WITH_HOSTFILE between tests ([5e63557](https://www.github.com/scop/bash-completion/commit/5e63557aac12251538091dc40bf587842327ced5)) +* test/_known_hosts_real: don't modify class scoped base expected list ([133790c](https://www.github.com/scop/bash-completion/commit/133790c464c68fa728b2957a66ee1fa012181a88)) +* test: upgrade mypy to 0.780 ([2e7271b](https://www.github.com/scop/bash-completion/commit/2e7271b3aed635a7fead1b97517673092eba5923)) +* test: regex escape our magic mark for completeness ([588b05c](https://www.github.com/scop/bash-completion/commit/588b05c1bf74feadad61bd1d1b39e752e639c201)) +* test/lspci: skip -A arg test if lspci fails -A help, e.g. busybox lspci ([e2cb804](https://www.github.com/scop/bash-completion/commit/e2cb80403d32af436a93782de4f33aee8352dd2b)) +* .gitignore: clean up some no longer needed ignores ([df7b81e](https://www.github.com/scop/bash-completion/commit/df7b81ea93d799affa858f26749f6aba8f0c1a38)) +* test/dpkg-query: mark as xfail on non-Debian based systems ([d176aaf](https://www.github.com/scop/bash-completion/commit/d176aafc18cb15a90c6c1d89918884d03382b20d)) +* test: simplify completion parsing ([726e4c0](https://www.github.com/scop/bash-completion/commit/726e4c08a96b1f0be1c931179f1b3edb31913917)) +* test: partial hostname completion fixes ([ba39695](https://www.github.com/scop/bash-completion/commit/ba39695792410c88f9d8e2303288274e2959cef7)) +* test/slapt-src: single expected result handling fixes ([1b9c9bc](https://www.github.com/scop/bash-completion/commit/1b9c9bcc285c296aa2c6df3e75ad75537080947e)) +* test/xhost: multiple expected result handling fixes ([888f39a](https://www.github.com/scop/bash-completion/commit/888f39a84a1847333c9e8bc06806886cd95eb103)) +* test: upgrade flake8 to 3.8.3 ([4730f3f](https://www.github.com/scop/bash-completion/commit/4730f3fcb0c0cefafc29cad7b0aed81ecd1decca)) +* _known_hosts_real: fix # handling in ssh configs ([ebabed1](https://www.github.com/scop/bash-completion/commit/ebabed1a4ca28f6e56a02831fee0e33f15047119)) +* _known_hosts_real: fix completion of Host entries after a wildcard etc ([0c69125](https://www.github.com/scop/bash-completion/commit/0c69125d65faaa60b0829db58c88dc33366bb67c)) +* test: upgrade perltidy to 20200619 ([87b169d](https://www.github.com/scop/bash-completion/commit/87b169dcf3b95d071280d70b3fc2fb0d8306c9e1)) +* test: upgrade mypy to 0.781 ([d46e8a5](https://www.github.com/scop/bash-completion/commit/d46e8a58e7840c0a8a5e942eb987479c69a0272a)) +* CONTRIBUTING.md: add posix and nounset mode item ([25887a3](https://www.github.com/scop/bash-completion/commit/25887a38ba3b81e9a6791ade89f5fa1a7c7ea5d3)) +* test: upgrade mypy to 0.782 ([f7c14b5](https://www.github.com/scop/bash-completion/commit/f7c14b5579b7bde9b57ae9bb175be7cba916edd9)) +* test/_known_hosts_real: add explicit no globbing test case ([8200b9a](https://www.github.com/scop/bash-completion/commit/8200b9a9529316f1f467aea18aaed2cbf4776bf0)) +* test/shfmt: upgrade to 3.1.2, reformat with it ([de35c91](https://www.github.com/scop/bash-completion/commit/de35c91dd3fe6c6c1adaeeb7e1a96f6a8360b0eb)) +* _known_hosts_real: prevent unwanted pathname expansion on host entries ([29be9d2](https://www.github.com/scop/bash-completion/commit/29be9d2e6bea356f16f12bfa7ad647b3ed67839e)) +* _included_ssh_config_files: support globs ([8bd47d4](https://www.github.com/scop/bash-completion/commit/8bd47d4ee25642b5fcddefb825d5025721840673)) +* _longopt: exclude too many dashes, allow underscores, require ends with alnum ([e2bcbd5](https://www.github.com/scop/bash-completion/commit/e2bcbd5115868bcfc048da1ce1b6b10f76762bf1)) +* _known_hosts_real: avoid errors in nounset mode on Ubuntu 14 and 16 ([54fd092](https://www.github.com/scop/bash-completion/commit/54fd092139e05c8fa01b3256b6c717ef3cdb9fb6)) +* test: upgrade markdownlint-cli to 0.23.2 ([95992bf](https://www.github.com/scop/bash-completion/commit/95992bfeee3c0409991fe45e89c1d08cd2eb4401)) +* __get_cword_at_cursor_by_ref: fix regression on bash 4.2 ([2ed8d90](https://www.github.com/scop/bash-completion/commit/2ed8d90b51e3ca6a337a15086f47c7dc982891a4)) +* pytest: complete async test class methods ([5c4f7a4](https://www.github.com/scop/bash-completion/commit/5c4f7a42d9864dcf91de845ea8167aad9cd3bdfc)) +* test/inputrc: comment typo fix ([0d2367b](https://www.github.com/scop/bash-completion/commit/0d2367bd46b722a23e7b83e8bc828342ba857fa5)) +* test/inputrc: do not set print-completions-horizontally ([d050205](https://www.github.com/scop/bash-completion/commit/d05020538be21f4b41a2f129c8f4eab83c077f40)) +* unzip, zipinfo: complete *.aar (#428) ([8273ce3](https://www.github.com/scop/bash-completion/commit/8273ce3138708ad1db851b74eafba38d6683ca0a)) +* pre-commit: update shellcheck-py URL ([08451ec](https://www.github.com/scop/bash-completion/commit/08451ec8383bb309d945589cab7d8c74a347a8b7)) +* pre-commit: upgrade isort to 5.0.7 ([d128d70](https://www.github.com/scop/bash-completion/commit/d128d70b1baef5a93f376fd44f18c7824d4643f3)) +* _known_hosts_real: exclude Host negations ([812e2ac](https://www.github.com/scop/bash-completion/commit/812e2acec01689b7c20488e2e11d335efd25ce9a)) +* test/ant: gitignore all target cache files ([6703c90](https://www.github.com/scop/bash-completion/commit/6703c9035b7a1639a1eded9989ede80848539078)) +* pre-commit: add pyupgrade, run it ([54b1e6f](https://www.github.com/scop/bash-completion/commit/54b1e6f70decfb8b8a5b15a1d14279e52551edf2)) +* pre-commit: upgrade pyupgrade to 2.7.2 ([5ac90cc](https://www.github.com/scop/bash-completion/commit/5ac90cc4eb6330d0a1999e598e6873d7dc545b77)) +* pre-commit: upgrade isort to 5.1.4 ([c2f0056](https://www.github.com/scop/bash-completion/commit/c2f0056c8edc35fc53f40a9b4d53d48e40f6676f)) +* _xinetd_services: avoid nounset error on bash 4.2 ([0df93b0](https://www.github.com/scop/bash-completion/commit/0df93b02d355b2faaad0d25d20d45967b82edd63)) +* test/ant: avoid complete-ant-cmd.pl interference with ANT_ARGS ([2ad91ec](https://www.github.com/scop/bash-completion/commit/2ad91ec985dc1fbc57d27f7b9815c7d0797426e8)) +* test/tshark: fix multiple -O completion with no http2 support ([53f624f](https://www.github.com/scop/bash-completion/commit/53f624f8212497c116afd4a365768237ac4069bb)) +* test/xfreerdp: skip --help failure cases ([b41b97c](https://www.github.com/scop/bash-completion/commit/b41b97cd2c646e813317429edbb8285c09cfd0b7)) +* tshark: complete -r arg with all filenames (#422) ([436b0cb](https://www.github.com/scop/bash-completion/commit/436b0cbe9e0839a51edcc7948e4ca11f2444a238)) +* pytest: rewrite in bash, support toplevel funcs, avoid nondef ones and classes ([bf3f720](https://www.github.com/scop/bash-completion/commit/bf3f72046f62ea86f43b65389d6d706a28544adb)) +* pre-commit: anchor exclude patterns ([cc697a6](https://www.github.com/scop/bash-completion/commit/cc697a646c1bd1100890abd367bb8d0274a42275)) +* extra/make-changelog: check and output usage message ([cf90b29](https://www.github.com/scop/bash-completion/commit/cf90b297696cee57650f4fb6c29cebe872f773a7)) + +## [2.12.0](https://github.com/scop/bash-completion/compare/v2.11.0...2.12.0) (2024-02-21) + + +### Features + +* **_comp_backup_glob:** add `ucf` generated backup files ([351be1c](https://github.com/scop/bash-completion/commit/351be1c81ecd97135d3df64475a93d57526d5630)) +* **_comp_backup_glob:** require dash in dpkg backup files ([59a57f9](https://github.com/scop/bash-completion/commit/59a57f9f8c6a47dc9d21c61d13ffb90a5f3b82f0)) +* **_comp_compgen_{filedir,set}:** define exit status ([7920c9d](https://github.com/scop/bash-completion/commit/7920c9dbe46bd5ad0a92e78b744f00ffe8b14e76)) +* **_comp_compgen_commands:** align return value with other compgens ([9d3362e](https://github.com/scop/bash-completion/commit/9d3362e4a092efaecda2fa2a5f01feca75e7b24e)) +* **_comp_compgen_commands:** auto set `-o filenames` when appropriate ([4d4839e](https://github.com/scop/bash-completion/commit/4d4839e50210de4d3a8780caa4b9d8ab44b8f86d)) +* **_comp_compgen_commands:** include dirs ([b9c7b5d](https://github.com/scop/bash-completion/commit/b9c7b5dc414c09d27a6b157d37bede70e662b91c)) +* **_comp_compgen_known_hosts:** return 2 on usage error ([43bb8f0](https://github.com/scop/bash-completion/commit/43bb8f03798811d95a3068a8a53d2eac9ad877b5)) +* **_comp_compgen:** support `-i cmd` and `-x cmd` ([39cc200](https://github.com/scop/bash-completion/commit/39cc200f9e6d9b03d1e76a924371f85304e786d5)) +* **_comp_compgen:** support `-U var` to unlocal var ([b603535](https://github.com/scop/bash-completion/commit/b60353508eb470515f1063a1e1a75bdf1fda730f)) +* **_comp_compgen:** support option -C ([6b3dfa5](https://github.com/scop/bash-completion/commit/6b3dfa529950f3bc51b8ead9323a82f65c5cfeb9)) +* **_comp_expand_glob:** fail when no paths are generated ([6b0a466](https://github.com/scop/bash-completion/commit/6b0a46644d587182c20f880755a821a7680753fe)) +* **_comp_get_fist_arg:** support "-o GLOB" to skip optargs ([0f14cc0](https://github.com/scop/bash-completion/commit/0f14cc030ebdb54f3d120d8cadc08651dad00624)) +* **_ip_addresses:** auto ltrim colon completions when appropriate ([ccdf953](https://github.com/scop/bash-completion/commit/ccdf953b7956d6fc65334e9049e157a3480a5cfa)) +* add _comp_compgen_split ([542bf73](https://github.com/scop/bash-completion/commit/542bf73f571312659293dac664bf257ef66fbfef)) +* add `_comp_locate_first_arg` ([0384bd5](https://github.com/scop/bash-completion/commit/0384bd51df3f68a3e065aeead4e921462fff6655)) +* **airflow:** add fallback 3rd party completion loader ([bf5550b](https://github.com/scop/bash-completion/commit/bf5550b5fc304ed956b6061221f173516408d82d)) +* **ansible*:** add fallback 3rd party completion loader ([5f8384e](https://github.com/scop/bash-completion/commit/5f8384ef71acd1dc6e214177e5bbe3b0b83ee976)) +* **apt-get:** prefer `apt-cache` in same dir as command ([a731bfd](https://github.com/scop/bash-completion/commit/a731bfd0acf77c7e5ec52315e3b470cffa177b4a)) +* **b2sum:** new completion ([cd985df](https://github.com/scop/bash-completion/commit/cd985df6d8e613fd5421066248db1c50dc1686bd)) +* **bash_completion:** add function _comp_compgen_ltrim_colon ([ce5889b](https://github.com/scop/bash-completion/commit/ce5889ba3b1364d9afe7096c6fa14d7c65d08cc6)) +* **black,blackd:** add fallback 3rd party completion loader ([47a1f05](https://github.com/scop/bash-completion/commit/47a1f05e75399d25dcf0281ae6f8ba363a82e6bc)) +* **carton:** support exec command completions ([0eb3a21](https://github.com/scop/bash-completion/commit/0eb3a21afdcd4c52966e0894f43f501dc3b727e3)) +* **chezmoi:** add 3rd-party completion loader (cobra) ([31baa69](https://github.com/scop/bash-completion/commit/31baa69954351a2d30047f707692d361646aea53)) +* **conda:** add 3rd-party completion loader (argcomplete) ([c0f5ba2](https://github.com/scop/bash-completion/commit/c0f5ba2e19abea70dcde4bf0aafe36de801b28c0)) +* **crc:** add 3rd-party completion loader (cobra) ([f10866e](https://github.com/scop/bash-completion/commit/f10866e1aaf810ae5cb29ccd5c1e8ac722d0f2ae)) +* **cz:** add fallback 3rd party completion loader ([b7ba70e](https://github.com/scop/bash-completion/commit/b7ba70e52e1e0f287c29b5d7362439dccd132e8b)) +* **dot:** support filename extension .gv ([be0010e](https://github.com/scop/bash-completion/commit/be0010e8517de89bf06bda02bdccacc51968136e)) +* **dprint:** add fallback 3rd party completion loader ([e201e0e](https://github.com/scop/bash-completion/commit/e201e0ee336e79c26bce2afc3f2b4f98d4fea12d)) +* **eog:** add missing extension .heif ([9e4a48f](https://github.com/scop/bash-completion/commit/9e4a48fdaa372a41e6ad5c7d021164394054aa97)) +* **eog:** associate with `*.avif` and `*.webp` ([#1005](https://github.com/scop/bash-completion/issues/1005)) ([f1c04b8](https://github.com/scop/bash-completion/commit/f1c04b816e1612acdac62605528d32b5d896916f)) +* **eog:** associate with `*.heic` and `*.jxl` ([20c9cea](https://github.com/scop/bash-completion/commit/20c9cea129e1f1e92045098ce7555a3f2add30e8)) +* **eog:** associate with `*.pbm` ([#1006](https://github.com/scop/bash-completion/issues/1006)) ([5472cc1](https://github.com/scop/bash-completion/commit/5472cc1fef9c60abf240bd8f4acf38dbdaabf1a1)) +* **feh:** associate with y4m and heic/heif/avif ([e252c73](https://github.com/scop/bash-completion/commit/e252c73ff2b92320dfabc9daf0d3f4ac15171e96)) +* **feh:** deassociate with avci/avcs ([af46f34](https://github.com/scop/bash-completion/commit/af46f3411acfbd28624f57ff6a7511148d1857f9)) +* **flask:** add fallback 3rd party completion loader ([3e0d00d](https://github.com/scop/bash-completion/commit/3e0d00d4ea55a200ea67196a6de841e8633fcad3)) +* **hash:** new completion ([#1013](https://github.com/scop/bash-completion/issues/1013)) ([4d0bffb](https://github.com/scop/bash-completion/commit/4d0bffb791c34c96114aeb2e4f6726b80aa8698e)) +* **httpx:** add fallback 3rd party completion loader ([3f4861c](https://github.com/scop/bash-completion/commit/3f4861cc41ea05982b2c4a98cc1f56f21895419b)) +* **ip:** Add completion for monitor subcommand ([fa696e6](https://github.com/scop/bash-completion/commit/fa696e60f3fe525a14bfbb409effb4e51b2e4450)) +* **jungle:** add fallback 3rd-party completion loader ([c69845a](https://github.com/scop/bash-completion/commit/c69845abf7efe9c226cef46ebf8b9129058db43d)) +* **keyring:** add fallback 3rd party completion loader ([8082602](https://github.com/scop/bash-completion/commit/80826028b7760409f20624a6fb4f4c5a4eaec8e3)) +* **kontena:** add fallback 3rd-party completion loader ([5eef0ce](https://github.com/scop/bash-completion/commit/5eef0ce3e5bd29f32d5830abfaf60da1295c4562)) +* **lefthook:** add fallback 3rd party completion loader ([dc9650e](https://github.com/scop/bash-completion/commit/dc9650e917d2018fa9eeb251e2c3db2b0f9d230a)) +* **mailman:** prefer `list_lists` in same dir as command ([a46ccf1](https://github.com/scop/bash-completion/commit/a46ccf132d53f4f5adf5ad3b0e51ec1dde931298)) +* **mysql:** prefer `mysqlshow` from same dir ([643886c](https://github.com/scop/bash-completion/commit/643886cf3c34eef47a86fbc6c2a64712c455dad3)) +* no empty command completion if `no_empty_cmd_completion` is on ([faab292](https://github.com/scop/bash-completion/commit/faab29286074ec3c952dfe50f0cb22af65dadbeb)) +* **npm:** add fallback 3rd-party completion loader ([f1c085c](https://github.com/scop/bash-completion/commit/f1c085cc56cf15d2bd0c97148535e36e81dfc5d4)) +* **nvm:** add fallback 3rd-party completion loader ([dea7e1d](https://github.com/scop/bash-completion/commit/dea7e1d431f1700c2515ece47b07ba472e1f999c)) +* **oc:** add 3rd-party completion loader (cobra) ([26b5f09](https://github.com/scop/bash-completion/commit/26b5f09490159fd8fc6b7c592cb70c40e8b214dc)) +* **pip{,3}:** add fallback 3rd-party completion loader ([e3cbfba](https://github.com/scop/bash-completion/commit/e3cbfba64e6f52ee49c59052ef40eb4a11a48849)) +* **pipenv:** add fallback 3rd party completion loader ([#1020](https://github.com/scop/bash-completion/issues/1020)) ([6ecf5bd](https://github.com/scop/bash-completion/commit/6ecf5bdb3c534db894da60e336f58235547de80d)) +* **pytest:** complete new --import-mode value ([#1021](https://github.com/scop/bash-completion/issues/1021)) ([2d636a3](https://github.com/scop/bash-completion/commit/2d636a3cb4ee66b4bc3355fadff1a1e4246199d4)) +* **rtx:** add fallback 3rd party completion loader ([0628e22](https://github.com/scop/bash-completion/commit/0628e223689b7bad0b9dc43e56d935a66b73b8a2)) +* **scp,sftp:** prefer `ssh` from same dir to resolve options etc ([d55f5e6](https://github.com/scop/bash-completion/commit/d55f5e6a9e9fb53b02bb86a8fc6278e671099bb0)) +* **ssh-copy-id,ssh-keygen:** prefer `ssh` from same dir ([5c1d270](https://github.com/scop/bash-completion/commit/5c1d2701456e14fbe946ef7ccfecc7e10829b806)) +* **ssh-inscribe:** add fallback 3rd party completion loader ([7f2c197](https://github.com/scop/bash-completion/commit/7f2c197e4e59b313d0f47cde902f57145106660e)) +* **ssh:** complete RequiredRSASize ([#1064](https://github.com/scop/bash-completion/issues/1064)) ([de15205](https://github.com/scop/bash-completion/commit/de15205d6c7997e8596dce4f9d2a2bfc476be716)) +* **tkn-pac:** add 3rd-party completion loader (cobra) ([d0f2604](https://github.com/scop/bash-completion/commit/d0f26045937276427ebb9844e84f40cff1b928f4)) +* **tkn:** add 3rd-party completion loader (cobra) ([161fc5d](https://github.com/scop/bash-completion/commit/161fc5d42cd7dd814a9197f788045ca052062c22)) +* **xrandr:** comma separated `--setmonitor` third argument ([8a76f3d](https://github.com/scop/bash-completion/commit/8a76f3d75db290302f94ea732e01a9afd25c2c24)) + + +### Bug Fixes + +* **__load_completion:** quoted compspec for variants ([#1008](https://github.com/scop/bash-completion/issues/1008)) ([0a2443e](https://github.com/scop/bash-completion/commit/0a2443e3eec8557273dd905df9a28dc177861023)) +* **_cd_devices:** `/dev/cdc-*` CDC device false positives ([5250728](https://github.com/scop/bash-completion/commit/52507286a6ea8c576414d7cca0f6a2d30dd78c84)) +* **_comp__init_set_up_service_completions:** work around failglob ([2529d40](https://github.com/scop/bash-completion/commit/2529d40f22039b344fd0bb5280a8469b8783f2a9)) +* **_comp_{first_arg,count_args}:** count - as argument ([e23a79e](https://github.com/scop/bash-completion/commit/e23a79e0fd715b0ae564082d9f1e4e7a907a195d)) +* **_comp_{first_arg,count_args}:** count any arguments after -- ([9bfd760](https://github.com/scop/bash-completion/commit/9bfd760c1192da7b3d0d8f0f9c8bea8ed16f4e47)) +* **_comp_command_offset:** Support complete -C ([80450ca](https://github.com/scop/bash-completion/commit/80450ca06973535671dc76ffe5abd6e377418f76)) +* **_comp_compgen_fstypes:** avoid unexpected expansions ([a856d81](https://github.com/scop/bash-completion/commit/a856d811b73500550d317eff5fec487e41581add)) +* **_comp_compgen_help:** allow dots to connect names in longopt ([79dadfc](https://github.com/scop/bash-completion/commit/79dadfc7fa37be26c7b263b809687db0907ae71f)) +* **_comp_compgen_known_hosts:** work around bash-4.2 nounset ([d2860cb](https://github.com/scop/bash-completion/commit/d2860cb481be8f3cf97172cb1bf063da8f238e53)) +* **_comp_compgen_split:** work around nounset ([f488f96](https://github.com/scop/bash-completion/commit/f488f9615a58140dc610bf2d406f3fcf6b8d82da)) +* **_comp_compgen_term:** replace completions by default ([d3696a3](https://github.com/scop/bash-completion/commit/d3696a3f793b2e0b9a0940287b3ab3dd23ef247d)) +* **_comp_compgen_usergroup:** avoid directly overwriting COMPREPLY ([d380498](https://github.com/scop/bash-completion/commit/d3804982650ec4fc7fbb7f7cab5522709b43f52d)) +* **_comp_compgen:** do not inherit -a for explicitly specified var ([3c20766](https://github.com/scop/bash-completion/commit/3c20766a6248aec000eb55731dd6b159ecf45dc2)) +* **_comp_compgen:** explicitly exclude `cur` from the target variable ([5fe98f3](https://github.com/scop/bash-completion/commit/5fe98f3c30fa69d0921703c7c90522a28bb00737)) +* **_comp_count_args:** check optarg correctly ([874c503](https://github.com/scop/bash-completion/commit/874c5031986e23a3ca7843d216d7dde94b0f1d4b)) +* **_comp_count_args:** exclude <>& from wordbreaks as _comp_initialize ([521d2bb](https://github.com/scop/bash-completion/commit/521d2bb5330de4a721ae20d37d330190aa4beef0)) +* **_comp_count_args:** ignore empty $3 ([76eea74](https://github.com/scop/bash-completion/commit/76eea74581d4f404e817f686ea86236c8c75a9fc)) +* **_comp_count_args:** perform optarg check also on $3 ([21d3122](https://github.com/scop/bash-completion/commit/21d3122fa933169849e9743212248c80b7843abb)) +* **_comp_count_args:** skip reassembling cword and words ([3127703](https://github.com/scop/bash-completion/commit/3127703f12f3e82ddf3f950a801ab430024aca22)) +* **_comp_delimited:** treat delimiter as a fixed string ([571a0f7](https://github.com/scop/bash-completion/commit/571a0f70f39fed70b2db51e1624b2a0ee29f00c4)) +* **_comp_deprecate_func:** argument order in usage error message ([597f62f](https://github.com/scop/bash-completion/commit/597f62fe38627452f5330d40bc9004f2b3d4dda5)) +* **_comp_get_words:** empty prev if unavailable (localvar_inherit) ([d8b8eef](https://github.com/scop/bash-completion/commit/d8b8eef63602cb0e34837320938b0819363d7d87)) +* **_comp_initialize:** fix completions of redirections without space ([da16bf6](https://github.com/scop/bash-completion/commit/da16bf61c2604ea4efa9b2d125aedd2dd4acd4e5)) +* **_comp_initialize:** protect against "localvar_inherit" ([0cc8d83](https://github.com/scop/bash-completion/commit/0cc8d833011c0763eb00939ad9a94d525d87bcea)) +* **_comp_split,_comp_compgen:** strip periods from error message ([b3b6a7c](https://github.com/scop/bash-completion/commit/b3b6a7cf2865b3591ab571dc2563d1980a822ac5)) +* **_comp_split:** update error message for the correct options ([3c4a89c](https://github.com/scop/bash-completion/commit/3c4a89ce48ca29c0c6461d12519bbf78bcc1ca02)) +* **_comp_sysvdirs:** work around nounset ([da26178](https://github.com/scop/bash-completion/commit/da26178b9c7eaf11711b451ae292a01bd423a80c)) +* **_filedir_xspec:** clean up unused variable `tmp` ([67f1189](https://github.com/scop/bash-completion/commit/67f11892351b710b9b3609e138a0a2c9248c4422)) +* **_get_cword_at_cursor,cvs:** quote array length ([201239c](https://github.com/scop/bash-completion/commit/201239cb597a3d7d0165a5e37a093f063fe700d1)) +* **_get_first_arg:** remove invalid doccomment ([eb40f56](https://github.com/scop/bash-completion/commit/eb40f566cc9e3c5a845a12caf0f4344dab2a0b2c)) +* **_known_hosts:** use array for `options` (work around SC2178,SC2179) ([743d0a9](https://github.com/scop/bash-completion/commit/743d0a9be714c516dce23415e3a5c5f81d5d7bea)) +* **_mock,rpm:** avoid icase flag `s/reg/rep/i` of GNU sed ([33c18ce](https://github.com/scop/bash-completion/commit/33c18ce90df153dabb89813d472dacf5a6259b92)) +* **_service:** quote word ([c2d7fb7](https://github.com/scop/bash-completion/commit/c2d7fb73844531ccb10576ddd905fb058e00c88e)) +* **_slackpkg:** do not scan after cword ([ecd1384](https://github.com/scop/bash-completion/commit/ecd13849f76966d9e15607bdd604972279bb9cd8)) +* **7z:** remove redundant `printf '%s\n' "..."` ([20c2e32](https://github.com/scop/bash-completion/commit/20c2e322f8eb93240de73b62647e7ca2f7b8fa4f)) +* **ant:** work around custom IFS ([584e567](https://github.com/scop/bash-completion/commit/584e56748da32e8f17a713b14c23ea2b7c92a4dc)) +* **apt-cache:** check all the words ([84cfeda](https://github.com/scop/bash-completion/commit/84cfedabe958ad6f7cfc52525d79e9b801de4233)) +* **aptitude:** do not use non-POSIX BRE \w ([cd8c870](https://github.com/scop/bash-completion/commit/cd8c8701b60f17f9aecc27482f64f121821085ee)) +* **aspell:** use `_comp_expand_glob` against unexpected splitting ([58d5176](https://github.com/scop/bash-completion/commit/58d5176cba8bb25fe5348aadef100c083afa992f)) +* **bash_completion:** remove some unnecessary `-a` to `_comp_compgen` ([636bb7c](https://github.com/scop/bash-completion/commit/636bb7c4062c3e410904769f1fde4f5b14a12afc)) +* **bts:** update functions to generators and fix variable conflicts ([7d2867c](https://github.com/scop/bash-completion/commit/7d2867c01527c3037579fe24da62cccfdfd1883e)) +* **carton:** remove a branch never happening ([cd063f9](https://github.com/scop/bash-completion/commit/cd063f9a40e4dc85e0a9de7ceeac019cdac57449)) +* **chgrp:** fix typo `_comp_compgen{d => _}filedir` ([#1063](https://github.com/scop/bash-completion/issues/1063)) ([4c98ce5](https://github.com/scop/bash-completion/commit/4c98ce58b7686b9f23f14bf05e809d9cd1a5669c)) +* **compat:** find compat dir for prefix-install ([b6d06bc](https://github.com/scop/bash-completion/commit/b6d06bc47119fcfc47f10eed328ff54e95ddc14d)) +* **completions/*:** quote array assignments properly ([848aa41](https://github.com/scop/bash-completion/commit/848aa413273516529ccc163966f138ad3a6c53a0)) +* **completions/*:** scan until cword instead of ${#words[@]}-1 ([17e0cc3](https://github.com/scop/bash-completion/commit/17e0cc36fdb4c6543c7729419d6f736ee779db1f)) +* **completions/*:** work around localvar_inherit ([e3a871d](https://github.com/scop/bash-completion/commit/e3a871d2517f688d7fe7132f33e96669a71b6aa1)) +* **curl,koji:** use _comp_compgen_help ([f37f221](https://github.com/scop/bash-completion/commit/f37f221f3f191fec0d301815d276d830f6119186)) +* **curl,qemu:** avoid using POSIX character classes for mawk ([d60c530](https://github.com/scop/bash-completion/commit/d60c5306f918b370c74f5ba6d3100720be139ad6)) +* **curl:** colon handling for IPv6 address completions ([8508d1d](https://github.com/scop/bash-completion/commit/8508d1d8f6f3d50ac6fb45ec2eb0f05dcef8d817)) +* **cvs,mutt,pkg_delete:** quote prefix to remove for literal matching ([533903e](https://github.com/scop/bash-completion/commit/533903edd5d0752cb4b910c3bcc6d86a0e55d779)) +* **cvs:** avoid variable conflicts ([0d145c9](https://github.com/scop/bash-completion/commit/0d145c9f2852955848ca1855d9fae216ebbd78c3)) +* **dict:** nounset error when host/port not set ([57191e2](https://github.com/scop/bash-completion/commit/57191e2731eb307434c2f11813d7dea303458dce)) +* **dict:** protect splitting from custom IFS ([b31fe1e](https://github.com/scop/bash-completion/commit/b31fe1e3e1b3480d9dc6a469cae4e83ed204b382)) +* **dict:** work around bash-4.2 array nounset ([d76dd9e](https://github.com/scop/bash-completion/commit/d76dd9ea448b71e111763e8048df49dde797d85e)) +* **dict:** work around bash-4.3 ${v+"$@"} with custom IFS ([cc21298](https://github.com/scop/bash-completion/commit/cc212983a2b2523e5b62e9735c6dff5f011bb80a)) +* **dmypy:** protect against "localvar_inherit" ([768ce65](https://github.com/scop/bash-completion/commit/768ce656099879ba1b81de04b75db11679791c47)) +* **dpkg-source:** filter completions by `cur` ([dbcef6e](https://github.com/scop/bash-completion/commit/dbcef6e37313b00f00ca65397be6a061b1af3bb8)) +* **filedir:** work around bash-4.2 `compgen -f -- "''"` ([c8bb123](https://github.com/scop/bash-completion/commit/c8bb123abc0c148bfa078cf8bfe01bafc5cf50ff)) +* fix problems with `set -o nounset` ([9c3e196](https://github.com/scop/bash-completion/commit/9c3e1961928248da8a6dd8e327c3860f71eb7dff)) +* **gdb:** fix regression that fails to generate command names ([ca8e240](https://github.com/scop/bash-completion/commit/ca8e2405ae49c927f9c9d312aa0efdde3d231bf2)) +* **gdb:** remove duplicate candidates ([532fc05](https://github.com/scop/bash-completion/commit/532fc05a73b415369ce1987463d82d791ee72dc0)) +* **gdb:** use POSIX-compatible find expression ([73938cd](https://github.com/scop/bash-completion/commit/73938cd857c3a7fa884e24be7216d1c5b12d5a1c)) +* **gdb:** work around bash 4.4 ${v+"$@"} ([41236da](https://github.com/scop/bash-completion/commit/41236da411794133d08792df28207e2a77271c57)) +* **get_words:** work around bash-4.3 connected ${v+"$@"} ([81affbd](https://github.com/scop/bash-completion/commit/81affbd999a24f796f79fb5c1eec80e88b3a98d8)) +* **getent:** check noargopts ([6143f25](https://github.com/scop/bash-completion/commit/6143f257f1593c319504c2627fe01b4c94e90a48)) +* **getent:** work around localvar_inherit ([a12f438](https://github.com/scop/bash-completion/commit/a12f438ebf93d7427d1b5df7056ace8ec67e890c)) +* **gzip,isort:** fix typo `_comp_com{gp => pg}en` ([462feb3](https://github.com/scop/bash-completion/commit/462feb34d3b49f70a2451cbf724d14e59bfd8e0a)) +* **iperf,puppet:** use \{m,n\} instead of \? and \+ for POSIX sed ([3f0322b](https://github.com/scop/bash-completion/commit/3f0322b73d98c177ede1973ad1b84e66ee593ca9)) +* **iperf:** work around failglob with backslash in bash-5.0 ([979f04f](https://github.com/scop/bash-completion/commit/979f04f67c76395e21f77b7945639f2eeaa3b37f)) +* **ip:** Remove non-existent route completion ([3b9ce4d](https://github.com/scop/bash-completion/commit/3b9ce4dc0ba0a14d1d390f0e83c7b7b53a26b5a5)) +* **isql:** work around nounset ([cb7007a](https://github.com/scop/bash-completion/commit/cb7007af225369e5872280411bb6871b55f274a5)) +* **java,kldload:** use `_comp_compgen` for filename-based mod names ([81adc6c](https://github.com/scop/bash-completion/commit/81adc6ce741f69e936dfb0e1e891c372341814f2)) +* **java:** localize `cur` ([ec0068d](https://github.com/scop/bash-completion/commit/ec0068d13f3c98551771e4ada4335f131c2f0cb4)) +* **kcov,povray:** quote array expansions to avoid extra processing ([215edab](https://github.com/scop/bash-completion/commit/215edabcceece2b53becc78cf88a24fb120db299)) +* **kldload,mplayer,mutt:** work around nounset ([5330fbe](https://github.com/scop/bash-completion/commit/5330fbeecdd490aa79f1cf7ce320e1b27a776d69)) +* **kldunload:** remove unused -X option ([35017d2](https://github.com/scop/bash-completion/commit/35017d25acee6830d4c30485a1b2cba2f12e00ed)) +* **known_hosts_real:** match `*.pub` instead of `*pub` ([470a644](https://github.com/scop/bash-completion/commit/470a644be3144d9fbd7d58d99d1c3fd73c773b9f)) +* **known_hosts_real:** use `_comp_expand_glob` to avoid failglob ([672215e](https://github.com/scop/bash-completion/commit/672215e010d5f78085caf61cecda620b4c67f4ae)) +* **known_hosts_real:** work around nounset ([07c619a](https://github.com/scop/bash-completion/commit/07c619a56950de1960312ae24411c27688e5aa1a)) +* **lilo,rpcdebug,slapt-{get,src}:** work around nounset ([cfc3eda](https://github.com/scop/bash-completion/commit/cfc3eda9575a8b0b48a531652875206db36957d5)) +* **lvm:** replace array slices with existing utility ([ea49840](https://github.com/scop/bash-completion/commit/ea498402ccf07eb1e4acef0ad40a7c188e567145)) +* **lvm:** update call to sub-command ([30494f7](https://github.com/scop/bash-completion/commit/30494f7b426c73b1a6a616f63d3510027c6fb02e)) +* **make:** handle multiple short options in skipping arguments ([24c80c9](https://github.com/scop/bash-completion/commit/24c80c91b7183ea5fcc9f2e7bc7ded303ea57d0a)) +* **make:** typo fix in a code comment ([e72cc82](https://github.com/scop/bash-completion/commit/e72cc826534a0ea9dc840546134c19962697c3a0)) +* **mdadm,update-alternatives:** fix leak variable ([14cd53b](https://github.com/scop/bash-completion/commit/14cd53bb38d0d0ef91bf82731e8946551f15023a)) +* **medusa:** filter completions by the current word `cur` ([f3ae706](https://github.com/scop/bash-completion/commit/f3ae706e114c4924416c50cca90473e6ce98ae20)) +* **mr:** avoid ${var/pat/$'...'} for compat42 in bash >= 4.3 ([b5ae5fa](https://github.com/scop/bash-completion/commit/b5ae5fada8b788885b0fd65cca34b85672f08189)) +* **mr:** exactly match command names ([800b103](https://github.com/scop/bash-completion/commit/800b10372e383124856c37b505d5dc9232eb1e45)) +* **mutt:** avoid unexpected word splitting ([3183e67](https://github.com/scop/bash-completion/commit/3183e67c72fcf5ba3d713de59a5d6898a9a64952)) +* **mutt:** fix use of regex in the glob context ([63924e6](https://github.com/scop/bash-completion/commit/63924e67527e5fa7698ac0610c7fd90c7ba36ecf)) +* **mutt:** rewrite ${cur/#!/X} to X${cur:1} against patsub_replacement ([6b8f82b](https://github.com/scop/bash-completion/commit/6b8f82b44e2308db66bc10e4f3529fe0ca5137e5)) +* **mutt:** use _comp_dequote for safe eval ([f98379d](https://github.com/scop/bash-completion/commit/f98379d33ee376df7a7f7de6fb85af8fffb469ee)) +* **openssl:** avoid variable conflicts ([a31906c](https://github.com/scop/bash-completion/commit/a31906cd2886b51e74d5d1bcbae3528a0f9f135b)) +* **openssl:** fix variable `i` leak ([83844b7](https://github.com/scop/bash-completion/commit/83844b7df11ad4ca02bb5da473fa4c5e8e3df80d)) +* **perl:** fix ineffective condition in an awk script ([302dc52](https://github.com/scop/bash-completion/commit/302dc52b9b02dc9a8fa9b1833012b3c4f96b6d7b)) +* **perl:** helper call regression from 01611dd3d ([b85263a](https://github.com/scop/bash-completion/commit/b85263a6de7f8e60f09489caac3f9a0d613e804f)) +* **pgrep:** do not rely on uncontrolled IFS ([99e38b2](https://github.com/scop/bash-completion/commit/99e38b27424a53f901ec274269f5646bb4b02850)) +* **portinstall:** use awk and _comp_compgen to filter completions ([791f56c](https://github.com/scop/bash-completion/commit/791f56c62656ba19c4db804b7ccf8c2e8ba1d55a)) +* **povray,sbopkg:** check filetype ([434eb08](https://github.com/scop/bash-completion/commit/434eb0853ed25c8730a38d5c3afbac170b397153)) +* **povray:** process each element against patsub_replacement ([0afc2e4](https://github.com/scop/bash-completion/commit/0afc2e4a5db45b569827ca3bbef90f70bc7e74f5)) +* **povray:** quote an argument properly ([0a240bd](https://github.com/scop/bash-completion/commit/0a240bd958a8aed9ef4251d0b223c42c60a77125)) +* **ps,ss:** avoid extra expansions by -W "$(...)" in _comp_delimited ([cb347cb](https://github.com/scop/bash-completion/commit/cb347cb208c5708e30aa3d847849aa6ce71ba814)) +* **pydoc:** specify -a to _comp_compgen_filedir ([34a91e9](https://github.com/scop/bash-completion/commit/34a91e9425992262913cbacf36706618a6f99bd4)) +* **pytest:** do not filter underscores from parsed option arg choices ([ea13241](https://github.com/scop/bash-completion/commit/ea13241b2aaa9361ba6d701aaadd8f4ce39dc28a)) +* **python:** avoid variable conflicts ([bef94c3](https://github.com/scop/bash-completion/commit/bef94c39b9fac23655c8b50181d7834869d72702)) +* **python:** complete filenames for script arguments ([#1018](https://github.com/scop/bash-completion/issues/1018)) ([397a49d](https://github.com/scop/bash-completion/commit/397a49d1c3a4faa5e15639d2852828f99b659bcc)) +* **python:** complete micropython and pyston script args consistently ([5b60ccc](https://github.com/scop/bash-completion/commit/5b60ccc1ee573637263bdaac070065af1406de4d)) +* **qdbus:** remove cur and all the rest arguments ([531b751](https://github.com/scop/bash-completion/commit/531b75142dc812a37b638de5c272c2356506fcc2)) +* replace \s with [[:space:]] for POSIX sed/awk ([1989ba9](https://github.com/scop/bash-completion/commit/1989ba9ad3de5cf33da3c9623fa87be5194fac08)) +* **ri:** avoid interference on existing COMPREPLY ([0a9d931](https://github.com/scop/bash-completion/commit/0a9d9319d50db21e0ca0051c19b9b3375790d353)) +* **ri:** fix wrongly quoted options to compgen ([5248bbf](https://github.com/scop/bash-completion/commit/5248bbf475d275bd6fc743d62f6f7f3ab0c30a39)) +* **ri:** properly split methods ([910a5a0](https://github.com/scop/bash-completion/commit/910a5a07c0f43095134c97c6b10db9d05505c3ef)) +* **ri:** split classes using `_comp_split` ([c95baa1](https://github.com/scop/bash-completion/commit/c95baa12d7879c81967b6dc9df896255d3253781)) +* **ri:** work around localvar_inherit ([9d6ff68](https://github.com/scop/bash-completion/commit/9d6ff689f44a2e560cbb643607f87551e7a88190)) +* **sbopkg:** add `;` mandatory before `}` in POSIX sed ([b286d53](https://github.com/scop/bash-completion/commit/b286d53dec9e7fb5edb513afa8bd60f8c0e9b68c)) +* **sbopkg:** work around nounset ([9709bdf](https://github.com/scop/bash-completion/commit/9709bdf226996878760ad87759f0011ff8587a3b)) +* **scp:** `nounset` mode error on unknown suboption, bash 4.2 ([82ca8d9](https://github.com/scop/bash-completion/commit/82ca8d924c4514f6570861d97b1ed953cbf9fe11)) +* **ssh-copy-id:** call ssh, not -copy-id for suboption completion check ([473278f](https://github.com/scop/bash-completion/commit/473278faed2f6d7d894dc674e71d1cef41022b6c)) +* **ssh-keygen:** call ssh, not -keygen to resolve supported protocols ([d569ea2](https://github.com/scop/bash-completion/commit/d569ea26389824b73732157947193efaea5f4ba8)) +* **ssh-keygen:** first arg to ssh query for protocol versions ([8a0a71e](https://github.com/scop/bash-completion/commit/8a0a71e449b5458f89fbc55b0ab7d6f6bf6656e9)) +* **ssh:** avoid variable conflicts ([f2df91d](https://github.com/scop/bash-completion/commit/f2df91d378004780d5237ab89faea2d6789169c0)) +* **ssh:** fix wrong quoting inside compgen -W ([febb3b3](https://github.com/scop/bash-completion/commit/febb3b3257fca6402fc4c33c4de293bbf962580c)) +* **ssh:** remove -a of generators ([55c5c45](https://github.com/scop/bash-completion/commit/55c5c459387e54ecdc869121fa97242e92ab87a8)) +* **ssh:** remove unnecessary -a to _comp_compgen ([992f28e](https://github.com/scop/bash-completion/commit/992f28e73c82f3157e346845ba9e440b7f3d8f22)) +* **ssh:** resolve relative ssh_config Include correctly ([4ac86e8](https://github.com/scop/bash-completion/commit/4ac86e84e55e793ba468c8cb6111510c9831377b)) +* **ssh:** use `_comp_compgen` for `_comp_xfunc_ssh_identityfile` ([05e70ed](https://github.com/scop/bash-completion/commit/05e70ede40dc4b50cdeb67bfa8484af53d24f995)) +* **ssh:** work around bash-4.2 nounset ([4447f83](https://github.com/scop/bash-completion/commit/4447f83c5d72823f336e3eefab2e8e10e080711b)) +* **ssh:** work around bash-4.2 nounset ([d0695d0](https://github.com/scop/bash-completion/commit/d0695d0bc9d44d851d41b5c7e123ab6b95f29e81)) +* **sudo:** use $1 (sudo) as $root_command ([329ca0e](https://github.com/scop/bash-completion/commit/329ca0eefd540b78e5fc287c2a4a2e2afdbfb45d)) +* **svcadm:** fix ineffective IFS for splitting ([1fd456e](https://github.com/scop/bash-completion/commit/1fd456e7435b88811b82809dc5845ee53ff7aafb)) +* **svcadm:** use the first matching name as command ([1870d5e](https://github.com/scop/bash-completion/commit/1870d5e0a67650a67c19895aefaae79eb2d6d76e)) +* **sysbench:** fix extraction of test-name option ([cc246a1](https://github.com/scop/bash-completion/commit/cc246a1b7d0433996c99534f64e0363170ac00cd)) +* **timeout:** always treat word after duration as command ([0d0531b](https://github.com/scop/bash-completion/commit/0d0531b254b03510f5dfa422a4198c33b5becd54)) +* **tipc:** remove filtered-out elements ([75b36b2](https://github.com/scop/bash-completion/commit/75b36b20b57e67a253d0c2622e88ba84ccc3bc25)) +* **update-alternatives:** quote dirname ([1205ed1](https://github.com/scop/bash-completion/commit/1205ed1958fa914faa8ccec778079e3f0ea2945b)) +* **update-alternatives:** suppress error for non-existent directory ([adbdab8](https://github.com/scop/bash-completion/commit/adbdab8fb5620e208826256e66851a1343f09e75)) +* **update-alternatives:** work around localvar_inherit ([1d9e19c](https://github.com/scop/bash-completion/commit/1d9e19cd2ae3650aa81512dc2ab811a80c16ca33)) +* **upgradepkg:** use `_comp_compgen` for `_comp_cmd_upgradepkg` ([a0973d7](https://github.com/scop/bash-completion/commit/a0973d77e8a3706490e33ba0f807727250b95c0e)) +* use _comp_compgen_split to avoid extra expansions by -W "$(...)" ([49997d0](https://github.com/scop/bash-completion/commit/49997d0b2ff4fbbea37558570632e096d777ee54)) +* use `_comp_compgen_split` to split and filter words ([158b8ba](https://github.com/scop/bash-completion/commit/158b8ba1de91913108507ae163611a44ae4871b0)) +* use `_comp_compgen_split` while keeping filtering by $cur ([a00ee19](https://github.com/scop/bash-completion/commit/a00ee19962e78f51a12b83bb1b11b89dc7512b22)) +* use `_comp_compgen` for word list ([83f033f](https://github.com/scop/bash-completion/commit/83f033f798c0fefbc9f37149d3bd40b0f238eabc)) +* use `_comp_split` while keeping filtering by $cur ([509e642](https://github.com/scop/bash-completion/commit/509e642d42a696a5737c94dc296c69ed60a4dd3b)) +* use compgen -P prefix -W '"${arr[@]}"' against patsub_replacement ([45d036a](https://github.com/scop/bash-completion/commit/45d036ad804973a4b1916e818a73421435db444d)) +* use XPG4 awk in Solaris ([cdd6da9](https://github.com/scop/bash-completion/commit/cdd6da9c77c7c99cab0aed7b9d7a5e4c0c5e0c78)) +* **wol:** filter IP addresses by `cur` ([c3505c5](https://github.com/scop/bash-completion/commit/c3505c518f9d2695f678d82a1efcf35118af08ec)) +* **wtf:** quote array assignment ([44c1d12](https://github.com/scop/bash-completion/commit/44c1d1292fdb840640a848aab6b2827002477ee9)) +* **xfreerdp:** support the new form of the option /list:kbd ([d8cadfe](https://github.com/scop/bash-completion/commit/d8cadfea1036cb558f5c6f663843a19eaa3b5025)) +* **xfunc ssh identityfile:** localize change to cur ([76b5726](https://github.com/scop/bash-completion/commit/76b572650f224e2e3b85918944af0bc8dfb49952)) + + +### Performance Improvements + +* **_comp_count_args:** skip reinitializing cword and words ([29398ef](https://github.com/scop/bash-completion/commit/29398efab4dd06fceb7c94c5329c5002b14cb8b4)) +* **mutt:** return earlier on empty `cur` ([a244587](https://github.com/scop/bash-completion/commit/a244587e3c2d83bbef090438b329478da1896a4c)) +* **portinstall:** return earlier for -lLo and non-existent file ([395e463](https://github.com/scop/bash-completion/commit/395e463d7e22bfb8b8b9f8ce4884ff7a979b2e35)) +* **vncviewer:** set nocasematch inside subshell ([5ed0020](https://github.com/scop/bash-completion/commit/5ed0020f4ec39c5ff9994882cae9f04eb45e4ed7)) + +## 2.10 (2019-12-05) + +* README: link to cygwin package ([8d60fd3](https://www.github.com/scop/bash-completion/commit/8d60fd32be777e4c6e734c1dac431b39b53fb216)) +* README: use light gray badges for unknown versions ([483968c](https://www.github.com/scop/bash-completion/commit/483968cd513142b71d1e6e9f199d5eaf958eb616)) +* test_rpm2tgz: Fix expected output ([ac51b00](https://www.github.com/scop/bash-completion/commit/ac51b00358ebe510f4899db9678480a6c6a4eda1)) +* test_chromium_browser: Skip test_2 if 'chromium-browser --help' fails ([0ee3982](https://www.github.com/scop/bash-completion/commit/0ee39821c67735fd16b5372cd4044775af1d1243)) +* tar: add missing bsdtar, gtar, and star symlinks ([af0b3d0](https://www.github.com/scop/bash-completion/commit/af0b3d0130f61a7d7960dd8eee99529fea6e39a2)) +* build: simplify symlink setup ([3bc0225](https://www.github.com/scop/bash-completion/commit/3bc0225ee28abc81800042c168b0721f5c68c49f)) +* build: really reset return value before completions check ([fce6732](https://www.github.com/scop/bash-completion/commit/fce673275bf2a024f91bb455e5353e02f3690cf8)) +* build: makefile whitespace tweaks ([a0949de](https://www.github.com/scop/bash-completion/commit/a0949de0f9988d3460b11820b97d6e4baab48cd3)) +* test: bashrc comment and whitespace tweaks ([27daf01](https://www.github.com/scop/bash-completion/commit/27daf018539500cad68e488cc81caf064e65075c)) +* test: more thorough system location interference avoidance ([7700896](https://www.github.com/scop/bash-completion/commit/77008960c7a402e96c24a5c9eab7d88ebc735896)) +* test: set up BASH_COMPLETION_COMPAT_DIR in bashrc (only) ([f7e2a41](https://www.github.com/scop/bash-completion/commit/f7e2a4192e6e2980859da1a64816fab75aa11b09)) +* test: reformat test_chromium_browser.py source ([7bf6281](https://www.github.com/scop/bash-completion/commit/7bf6281a47ce2fda45f8b7fec48e53e19e0f640d)) +* pkg_delete: don't limit to FreeBSD ([5bc9b8e](https://www.github.com/scop/bash-completion/commit/5bc9b8eb51ccc41f78af0e108503de5edc87f101)) +* tar: simplify locating tarball from command line ([26d9662](https://www.github.com/scop/bash-completion/commit/26d966207a2e4cef02a70d790f44812c1284d160)) +* test_arp: Skip if ARP tables are empty ([90ede98](https://www.github.com/scop/bash-completion/commit/90ede989622143dc93c9a05a18bc23767c4bff9c)) +* test: generalize check whether we're being run in a container ([1e3d3b4](https://www.github.com/scop/bash-completion/commit/1e3d3b4d40e3f6c150b9d31965f8b007ef823fc7)) +* test_feh, test_makepkg: invoke grep as "command grep" ([5e706a4](https://www.github.com/scop/bash-completion/commit/5e706a433440af4fad630d1b362f7e75578cbcdb)) +* test_getconf: skip if -a doesn't output any POSIX_V* ([70afc1e](https://www.github.com/scop/bash-completion/commit/70afc1ed3697c3171a004b7db2f19220117d2862)) +* test_iconv: skip option completion if --help fails ([2cdac1b](https://www.github.com/scop/bash-completion/commit/2cdac1b9f24df62a1fa80c1824ee8524c9b02393)) +* test_iconv: add basic file completion test ([0ba7af2](https://www.github.com/scop/bash-completion/commit/0ba7af221b3ec3ec7b1efecd3c8458068f1934b3)) +* iconv: weed out ... from encoding completions ([40be1f4](https://www.github.com/scop/bash-completion/commit/40be1f491bfbeec50787cbe6bd2c6a794b19ef46)) +* test: add Alpine Linux container, allow failures for now ([316289f](https://www.github.com/scop/bash-completion/commit/316289fb0837676f310925748070e1e1e87de750)) +* test: support xfail in our markers like skipif, use it a lot ([b3fecab](https://www.github.com/scop/bash-completion/commit/b3fecab48c22c07015a6fef7a00d4cb0ea1b74f3)) +* test: expect failures for various completions without useful --help ([0a777ff](https://www.github.com/scop/bash-completion/commit/0a777ff73bf5ddbd5de92f2bf1e3f8429e471f72)) +* test_lsusb: xfail with unparseable --help ([e717ce4](https://www.github.com/scop/bash-completion/commit/e717ce4503ab646055cd6b88d4087c162a529137)) +* test_wget: test --s instead of --h ([ddd4b39](https://www.github.com/scop/bash-completion/commit/ddd4b396b9a29c25715f6b2b768737b0b015c6c9)) +* timeout: fallback to _parse_usage from _parse_help ([7683eef](https://www.github.com/scop/bash-completion/commit/7683eefe974d7c508c7a7c3e2aa8f318f30c2699)) +* test_ifup: accept short option completions too ([071dc19](https://www.github.com/scop/bash-completion/commit/071dc199c1413146d485ee28bfa6c9a189c3681b)) +* test: use one Dockerfile for all dists ([495dab2](https://www.github.com/scop/bash-completion/commit/495dab2d80001aeabfe6136bd046a0231ff5d115)) +* test: run our docker script in test containers by default ([a59f00a](https://www.github.com/scop/bash-completion/commit/a59f00aeb2efa0decb3767e99c2445890a340d35)) +* _pnames: adapt for busybox ps, rewrite in pure bash ([5443c81](https://www.github.com/scop/bash-completion/commit/5443c819622495fcdc759d5dd4e5c31633eab389)) +* test: disallow Alpine failure on Travis ([2748b79](https://www.github.com/scop/bash-completion/commit/2748b79d678db1d06dac733b0ddc5a51a77cef1e)) +* iconv, lz4, tipc, xsltproc: replace some seds with compgen -X ([32e8b93](https://www.github.com/scop/bash-completion/commit/32e8b934c4bb3089b9a2b6e1677e7c014509f734)) +* test: port compgen and quote tests to pytest+pexpect ([3752208](https://www.github.com/scop/bash-completion/commit/37522086868ae6da2e3630b24056b443ba9706e0)) +* test: port _variables unit tests to pytest+pexpect ([b670968](https://www.github.com/scop/bash-completion/commit/b670968232cbc91e494658b2b06330693ee42939)) +* README: add some badges, tweak existing ([cd9f061](https://www.github.com/scop/bash-completion/commit/cd9f0616567eee91eb971575baabcb8d97f3780e)) +* test: convert finger partial test case to pytest+pexpect ([f3537dd](https://www.github.com/scop/bash-completion/commit/f3537dd02acb7e8cc8d6150f9e38785ee75f958d)) +* test: convert bunch of _filedir unit tests to pytest+pexpect ([2da46c3](https://www.github.com/scop/bash-completion/commit/2da46c3299403d93d1754b5ee2d8903cc874d267)) +* test: flake8 fix ([65aa0db](https://www.github.com/scop/bash-completion/commit/65aa0db5142f29ebd8a7e5d1bae91ffe8b2db516)) +* test: convert more _filedir unit tests to pytest+pexpect ([102e9a4](https://www.github.com/scop/bash-completion/commit/102e9a413101c702c1f458e55d79a861e80950a9)) +* test: add basic autossh test ([06cea18](https://www.github.com/scop/bash-completion/commit/06cea18e2ff03e90d1c663614e4d90422cfce246)) +* chsh, pwck: try _parse_help before _parse_usage ([696f90d](https://www.github.com/scop/bash-completion/commit/696f90d30a5cd6769be0affc166b2003de8a44e7)) +* test: add bunch of basic _parse_usage use test cases ([dcef445](https://www.github.com/scop/bash-completion/commit/dcef445f19d6c879144c09c5e6e96108fbe7c933)) +* cal: try _parse_help before _parse_usage ([2500b50](https://www.github.com/scop/bash-completion/commit/2500b504a16cfe8fd73caa5d1d53f377d1a90f11)) +* postfix: option completion is expected to fail at the moment ([2deda5b](https://www.github.com/scop/bash-completion/commit/2deda5b49d1fe722008c3d676a4e95a551237586)) +* badblocks: fix $i leak ([e8ac021](https://www.github.com/scop/bash-completion/commit/e8ac021ed13e5b110b9e0701b29d6c9704d33461)) +* .gitignore: add configure.lineno ([44ed05a](https://www.github.com/scop/bash-completion/commit/44ed05ac88888bbc0d156e89b62e63d630e1c2fc)) +* test: add bunch of basic _parse_help use test cases ([6b4fd9b](https://www.github.com/scop/bash-completion/commit/6b4fd9b783b1fe623f7fc1e55538a626076e5a8f)) +* test: add more basic _parse_help use test cases ([c64a4ac](https://www.github.com/scop/bash-completion/commit/c64a4acd6637f0718b8dabfb53f40e8a6d8b71d7)) +* test: xfail getent and pwdx option completions with unparseable --help ([ef215a6](https://www.github.com/scop/bash-completion/commit/ef215a624a3f83a0aadd02fe9ddd9da775a6aa91)) +* test: zopflipng flake8 fix ([026e52a](https://www.github.com/scop/bash-completion/commit/026e52a9b419cfb251f943be892b589b8520ff55)) +* test: enforce minimum pytest version ([69c94b9](https://www.github.com/scop/bash-completion/commit/69c94b9bf81811aba2b1b7f7bb7ade587880e95b)) +* build: make pytest executable configurable, look for pytest-3 too ([35188d9](https://www.github.com/scop/bash-completion/commit/35188d93848de125dc82c798dbcac0d6e93fb255)) +* test_pwdx: xfail more unparseable help cases ([98a7aa6](https://www.github.com/scop/bash-completion/commit/98a7aa6cfd694149a9ca3857d224fe85a4acf538)) +* test: xfail unparseable mock and munin-node-configure --help cases ([139acc9](https://www.github.com/scop/bash-completion/commit/139acc9fe3b35b000d899f54e06a7b638cc3e2e8)) +* pgrep: fix fallback to _parse_usage ([5cb4be4](https://www.github.com/scop/bash-completion/commit/5cb4be4220d649a78e85a6e772dcbe85622f9840)) +* test: don't try to install black on Python < 3.6 ([bfe14e7](https://www.github.com/scop/bash-completion/commit/bfe14e7b8e02f97d490a3b3c8087588e5318b5ee)) +* test_wsimport: xfail options test on unparseable -help ([2baab4f](https://www.github.com/scop/bash-completion/commit/2baab4f1a8ad70500cea543758aadc13cc219878)) +* man: fall back to _parse_usage for _parse_help ([2e1cb45](https://www.github.com/scop/bash-completion/commit/2e1cb45991af0e52a6be93b46264ffd45097d980)) +* test: add basic tox fixture ([a81a1e8](https://www.github.com/scop/bash-completion/commit/a81a1e80163147c1aabd9476507338dfa255b880)) +* tox: do simple parse on tox.ini if --listenvs* yields nothing ([d7c92e6](https://www.github.com/scop/bash-completion/commit/d7c92e602fc776272724c3c37a14181a4b01edf5)) +* README: badge title tweaks ([35411bf](https://www.github.com/scop/bash-completion/commit/35411bf821b66146d7dfcfc3abf4c7d7ba4a30bb)) +* influx: new completion ([378865d](https://www.github.com/scop/bash-completion/commit/378865db6e61d9a3ecfd0281b80b5d75167e792b)) +* test: source our profile.d test env script in docker ([3702ae0](https://www.github.com/scop/bash-completion/commit/3702ae08454974e8c847ef565a383384094a92b4)) +* chromium-browser: add --proxy-server arg completion ([fef4c9f](https://www.github.com/scop/bash-completion/commit/fef4c9f784f26d50af93d0b9c4f6628a91626a5b)) +* README: drop distro badges, link to Repology instead ([d2574f5](https://www.github.com/scop/bash-completion/commit/d2574f51c3cadde840a0601a561009d7a53a2ebf)) +* ip: invoke the tool as $1 ([bbe88bb](https://www.github.com/scop/bash-completion/commit/bbe88bb6b1b028adb103b9cbfafc7c7168ff0667)) +* test: fix required pytest version ([9cd7c03](https://www.github.com/scop/bash-completion/commit/9cd7c03f898559601e81e2a933d205d1ea1a51f6)) +* test: register our pytest markers to hush warnings from 4.5+ ([c187879](https://www.github.com/scop/bash-completion/commit/c18787923bc40b4ee599946deb579eab6d3fa5b2)) +* gssdp-discover: new completion ([f8fac3a](https://www.github.com/scop/bash-completion/commit/f8fac3aefd4067d039d1e088f227808259602676)) +* tox: complete defaults after a -- ([c06cfb0](https://www.github.com/scop/bash-completion/commit/c06cfb053eea2d5cbe478f5179ad5e3d824d760a)) +* tox: include -- in option completions ([0ee3a3b](https://www.github.com/scop/bash-completion/commit/0ee3a3b4db0a65a4ed6a2a07d5c259c1c398de59)) +* test: drop sourcing our no longer existing profile.d script ([ed14353](https://www.github.com/scop/bash-completion/commit/ed143530a2811d605de198a11bc699a90da645fd)) +* test: don't expect a .tox dir in fixture ([6dd937d](https://www.github.com/scop/bash-completion/commit/6dd937d3c86aa098b273002c9589f9e5ba2c5891)) +* test: expect failures for bc without --help useful with _longopt ([5fd2701](https://www.github.com/scop/bash-completion/commit/5fd2701371a491176b25fa9683481d6d143675f2)) +* test: skip gssdp-discover --message-type when option not available ([b0fb710](https://www.github.com/scop/bash-completion/commit/b0fb7101aaad984e21ce520b39e6416db261a354)) +* xvfb-run: new completion ([5c0e988](https://www.github.com/scop/bash-completion/commit/5c0e98832a1ee4e2829d47e2fb22f495ac09b641)) +* test: avoid gnome-mplayer core dump on Ubuntu 14 ([07eada3](https://www.github.com/scop/bash-completion/commit/07eada37598e19c282081102ad29d62a6e87e9f4)) +* test: remove unnecessary returns after pytest.skip ([d5fa7e3](https://www.github.com/scop/bash-completion/commit/d5fa7e31e2f88a438d224adde89e15c14e173ada)) +* test: fix acroread fixture dir ([1f7fdc6](https://www.github.com/scop/bash-completion/commit/1f7fdc67d3e015156d4622e6904a728f3717dadb)) +* test: installpkg test fixes ([322ec19](https://www.github.com/scop/bash-completion/commit/322ec19f06d4ec2ea32c861c023fb9644985150a)) +* java: make jar/zip listing work with unzip ([8b8783c](https://www.github.com/scop/bash-completion/commit/8b8783c48d58f0320fd72fa7805643a0f7615311)) +* test: use sh +* as ccache command test case ([87ba114](https://www.github.com/scop/bash-completion/commit/87ba114a2da100e4002240060a41b89fb9bbfdb5)) +* test: avoid some sed -r/-E runLint false positives ([970eab9](https://www.github.com/scop/bash-completion/commit/970eab95140451c04a11a515d9ee860154fce9d1)) +* ipv6calc: parse help instead of hardcoding option list ([151ac18](https://www.github.com/scop/bash-completion/commit/151ac18040eb27533ebca4815c6286e2d758c0f5)) +* lvm pv*, vg*: parse help instead of hardcoding option list ([a8d5489](https://www.github.com/scop/bash-completion/commit/a8d548950f6a79e14c131251091026730c2ddb49)) +* test: portinstall/upgrade test case and setup fixes ([669c3fe](https://www.github.com/scop/bash-completion/commit/669c3fe142f50d1f72c57c9639169691598622a0)) +* pkgutil: fix $i leak ([d375b63](https://www.github.com/scop/bash-completion/commit/d375b638160d9dea43528dc99054db0a0d5d4497)) +* pkg-get: fix $i leak ([07e8dc6](https://www.github.com/scop/bash-completion/commit/07e8dc6c89c81f72093ef1ff7dcd29b87016c2ee)) +* chromium-browser: Add support for .mhtml files ([a951666](https://www.github.com/scop/bash-completion/commit/a95166674def153222d46346863a456f73803877)) +* _terms: combine and simplify somewhat ([f6d4614](https://www.github.com/scop/bash-completion/commit/f6d461483ea7c6b3cc6710401cca6ba50c687ed4)) +* _terms: search directly from various terminfo dirs ([88ed3c7](https://www.github.com/scop/bash-completion/commit/88ed3c712df1b72d730496e736faba493488e892)) +* test: mark sbcl-mt xfail due to whitespace split issues ([9838cbf](https://www.github.com/scop/bash-completion/commit/9838cbfaf9e508b1ec1ad05959d89f3cf9e5d719)) +* test: explodepkg and upgradepkg test fixes ([f40a1ca](https://www.github.com/scop/bash-completion/commit/f40a1ca85658c9d7cc8366ac6766098f78b69412)) +* test: always run tests which don't require tested command ([674dd80](https://www.github.com/scop/bash-completion/commit/674dd805ba3639c7b507fd997fdf6e97708d84be)) +* test: add bunch of basic option parsing test cases ([faacf36](https://www.github.com/scop/bash-completion/commit/faacf36e3432fd740293788910ee6304e0b5a031)) +* test: don't sort expected completion lists under the hood ([1e3d504](https://www.github.com/scop/bash-completion/commit/1e3d50429d45e44d4fe65b3c7b2f37eb6e8c7b48)) +* test: hush flake8-bugbear B010 ([b6d74cc](https://www.github.com/scop/bash-completion/commit/b6d74cc99881e51e7bd9504ce55273a3f1b95def)) +* test: ignore _makepkg_bootstrap in makepkg test env ([b044a4f](https://www.github.com/scop/bash-completion/commit/b044a4f9d750410e4882e5badfa3b2f8a1145e28)) +* test: xfail MAC address completion without networking ([36db77a](https://www.github.com/scop/bash-completion/commit/36db77a14e516c4ab452ce57f83e4406852b83e3)) +* travis: pass NETWORK as env var, so we can actually use it ([0f8187d](https://www.github.com/scop/bash-completion/commit/0f8187ddc01dabc6129f7f1673e950d03d57cbfd)) +* test: fix retrieving command to test from request ([29ad382](https://www.github.com/scop/bash-completion/commit/29ad38254fa52ea159d2bc1959c80599c6b52128)) +* gprof: _parse_usage, drop hardcoded option list ([bebe43d](https://www.github.com/scop/bash-completion/commit/bebe43d6e7881d39e9c03faadf2927fa08042241)) +* lintian-info: _parse_help, add more option arg (non)completions ([29157d0](https://www.github.com/scop/bash-completion/commit/29157d07aafac3938fb26e93c542288d027eca9a)) +* screen, smartctl, update-alternatives: _parse_help, drop hardcoded option list ([bf207da](https://www.github.com/scop/bash-completion/commit/bf207da5b3879ca5c94fd382b609b5b41f6802b1)) +* sysctl: invoke completed sysctl instead of one from path to get variables ([e32ca04](https://www.github.com/scop/bash-completion/commit/e32ca04b96f4e7c78232d6d75bc3782847f8aa97)) +* test: mark more tests that parse command output as requiring command ([503143b](https://www.github.com/scop/bash-completion/commit/503143bf4dd7c43088b646f81eafa4494c476b26)) +* test: add require_longopt xfail helper, use it ([6d79948](https://www.github.com/scop/bash-completion/commit/6d79948d9fe5923a3ec9fcaf881fb182cb59569d)) +* dmypy: new completion ([3135bc3](https://www.github.com/scop/bash-completion/commit/3135bc3780fda004a2c04e2ae007ae9ae1672f22)) +* travis: generate dist tarball on alpine ([be2e8f3](https://www.github.com/scop/bash-completion/commit/be2e8f3fe6be17051a9aa6fe081b66897e0d8b43)) +* wine: install for wine-development and wine-stable too ([afc5a30](https://www.github.com/scop/bash-completion/commit/afc5a303ae25afdb109464e4f63fc17783383ed5)) +* perltidy: associate *.t (#338) ([96b5e07](https://www.github.com/scop/bash-completion/commit/96b5e07b585b3122d51c5c25bc4289daa96524a7)) +* travis: test with Debian 10 ([c0a3c55](https://www.github.com/scop/bash-completion/commit/c0a3c5592dadcee37cf41dcf5fac2a357d1b5f67)) +* ssh: option and argument completion updates (#332) ([29a14f0](https://www.github.com/scop/bash-completion/commit/29a14f0f33ea8f3e8a77070eb30d14d547f8ac2b)) +* java: don't assume jar is installed ([120bf77](https://www.github.com/scop/bash-completion/commit/120bf77ad2d644eba6fb506caed08fa475a426e7)) +* _sysvdirs: always return 0 ([debbff9](https://www.github.com/scop/bash-completion/commit/debbff95fe35082877ccda05153d6d87562088ea)) +* test: xfail locale-gen option completion if --help is not available ([4cf7e4f](https://www.github.com/scop/bash-completion/commit/4cf7e4f52d7da127198146cf57161f9bcee546da)) +* valgrind: look tool names from lib/*-linux-gnu dirs too ([6c8380d](https://www.github.com/scop/bash-completion/commit/6c8380df27f6af2704d15c2de7efbb87fe0d1f48)) +* test: adjust java expectations based on whether jars can be listed ([9e351e4](https://www.github.com/scop/bash-completion/commit/9e351e41eb4bbadd94f9df48915708f78b8246b9)) +* op: direct command parsing stderr to /dev/null ([d10dcdf](https://www.github.com/scop/bash-completion/commit/d10dcdf798890afcb361e6286dfbff1404d43916)) +* ri: hush some warnings ([f5d99f2](https://www.github.com/scop/bash-completion/commit/f5d99f22f6da6deb4fb037a2966d8b2f8532a4f3)) +* carton: new completion ([6722aaa](https://www.github.com/scop/bash-completion/commit/6722aaa018ff426953496577db2daf3980443ffd)) +* CONTRIBUTING: disable e-mail bug gateway due to spam ([8ef547a](https://www.github.com/scop/bash-completion/commit/8ef547aad3566cdf83e659bda1113a0de55a4738)) +* apt-get: fix pkg version completion if it contains a colon (#351) ([8f0595c](https://www.github.com/scop/bash-completion/commit/8f0595c6e2396e875aeffac03dbd8b9d5b3d10cf)) +* _variables: add TERM and LC_* completion (#353) ([d1756f0](https://www.github.com/scop/bash-completion/commit/d1756f06ef9bffb1b4621c4e63e47e181ddf1086)) +* cppcheck: Add new standards to --std option. (#356) ([d8df8b5](https://www.github.com/scop/bash-completion/commit/d8df8b5e2d56a5f2fa5930b7278cc2cc6b6c90b8)) +* test: mark dcop and mr testcases requiring the cmd as such ([73e8faf](https://www.github.com/scop/bash-completion/commit/73e8faf4d987aef26d52c2354d4336596a7cee92)) +* makepkg: fix option completion ([3566352](https://www.github.com/scop/bash-completion/commit/356635225de0fb1efecb6e17bb1284fb2c6c5a80)) +* .gitignore: mypy cache ([0dd1e65](https://www.github.com/scop/bash-completion/commit/0dd1e652c6045a51a4d5c6eb2952248d43fdc88e)) +* test: add minimal mypy config ([860766e](https://www.github.com/scop/bash-completion/commit/860766ea4f44ebb98497eb8990634b705dd3d4f9)) +* test: python typing fixes ([af136b5](https://www.github.com/scop/bash-completion/commit/af136b50b222dcbfb9d881a8c33280b5051dc266)) +* test: fix cpio users test in presence of usernames with whitespace ([20cacd2](https://www.github.com/scop/bash-completion/commit/20cacd2ebabfd1cb9178f0bccb2faf859e5469bc)) +* shellcheck: add some option arg (non)completions ([000fa10](https://www.github.com/scop/bash-completion/commit/000fa10469d4704803ed48563cf656449d77232a)) +* test: shellcheck config cleanups ([0f3922b](https://www.github.com/scop/bash-completion/commit/0f3922be10b83361505fffa76d7bb2931415d25e)) +* bash_completion.sh: shellcheck SC2086 fixes ([ded48bb](https://www.github.com/scop/bash-completion/commit/ded48bb7ab53c1836c6ec436cb304b6823a180f4)) +* _filedir: remove unused $x ([2701887](https://www.github.com/scop/bash-completion/commit/2701887f4862b29dafa0d9ecef329a766713a3fe)) +* _filedir: avoid duplicate dirs internally, and a compgen -d call for files ([da99bc5](https://www.github.com/scop/bash-completion/commit/da99bc55954e9f60b9c3a9e9071ff6301d7015cb)) +* curl: make @filename completion do the right thing with dirs ([aa3652b](https://www.github.com/scop/bash-completion/commit/aa3652b6b7de9aabfafa79f52c70825f23f967ab)) +* pkg-config: generate Name from autotools PACKAGE ([32369a0](https://www.github.com/scop/bash-completion/commit/32369a009d14f129e000cba4a0a2d1b8fc65ccea)) +* unzip, zipinfo: complete *.aab (#340) ([31b5cbc](https://www.github.com/scop/bash-completion/commit/31b5cbc8016b181675e10dd068c92008782d4196)) +* pkg-config: Relative paths ([8c53025](https://www.github.com/scop/bash-completion/commit/8c5302581ad20954cfa164dcae26f1ed6277dd90)) +* autotools: Replace pkgdatadir with datadir ([0cc34e8](https://www.github.com/scop/bash-completion/commit/0cc34e8de658bd11fa7f728eb9852c7e29d8d6d4)) +* cppcheck: Remove deprecated option 'posix' for '--std=' ([d1ae094](https://www.github.com/scop/bash-completion/commit/d1ae094807532e42b71c18e648b182c5c44a0daf)) +* perl: fix completion with space between option and argument ([8eba6d0](https://www.github.com/scop/bash-completion/commit/8eba6d0c6b88dacd80762ada3a3bc5fe14673fb2)) +* perl: indentation fixes ([1360ba9](https://www.github.com/scop/bash-completion/commit/1360ba95149d0880486d1abfdcfcf6f77355c44d)) +* test: add some trivial perl -E/-e cases ([188ca8a](https://www.github.com/scop/bash-completion/commit/188ca8af208f35ebdc9895d5fd41d6cdd83d90a6)) +* screen: complete first arg with serial devices ([9cde25b](https://www.github.com/scop/bash-completion/commit/9cde25bfd74bdd1cb51e46a4b1958ebd444cdbd6)) +* screen: add //telnet completion ([7a8e408](https://www.github.com/scop/bash-completion/commit/7a8e408267ca21530d6d6de4ae92b9a0362e14fd)) +* screen: add serial device basic arg (non)completion ([fb46fed](https://www.github.com/scop/bash-completion/commit/fb46fed657d6b6575974b2fd5a9b6529ed2472b7)) +* update-rc.d: remove dead code ([845be11](https://www.github.com/scop/bash-completion/commit/845be116278719c2a4ab4d4edaee81f38cc17b9f)) +* update-rc.d: indentation fix ([645cc41](https://www.github.com/scop/bash-completion/commit/645cc41deab3dce6a38120be05ab02ee1ca6bc89)) +* ssh, scp, sftp, ssh-copy-id, curl: improve identity file completion ([44ce113](https://www.github.com/scop/bash-completion/commit/44ce11334803f924f60e2e2c00c8b7d3dc81c33f)) +* unrar: complete on *.exe (#337) ([2b81989](https://www.github.com/scop/bash-completion/commit/2b8198919e4bc65efd8c68ade769e65f6df473f1)) +* gcc: support new --completion option (#222) ([87a9e9c](https://www.github.com/scop/bash-completion/commit/87a9e9c47f028efb6178c69ced2df74b62a73639)) +* test: bump black to >=19.10b0 ([540e5d1](https://www.github.com/scop/bash-completion/commit/540e5d1a7ec9599f404ec88d35aa37bf25557755)) + +## 2.9 (2019-04-27) + +* completions/Makefile: Fix check-local in VPATH builds ([57b2c93](https://www.github.com/scop/bash-completion/commit/57b2c937c1fa8409a4416702cf5b8844233a5566)) +* ssh: Order various switch cases closer to alphabetical ([cde26f0](https://www.github.com/scop/bash-completion/commit/cde26f07207d3256ec56f519256cb7a7d38d993e)) +* ssh: Sync query type list with OpenSSH 7.5p1 ([655ede3](https://www.github.com/scop/bash-completion/commit/655ede3db3f56ae7669c296110d8dbef9c329b3a)) +* ssh: Sync config option lists with OpenSSH 7.5p1, add some value completions ([15abc03](https://www.github.com/scop/bash-completion/commit/15abc03c71d49c1bfc328e5c860c1bd30b15feb0)) +* apt-get: Complete install package=versions ([c664b07](https://www.github.com/scop/bash-completion/commit/c664b07ac98bf46c0ea416161cef0a0dbe11ab50)) +* apt-get: Add indextargets to list of suggested commands ([d623786](https://www.github.com/scop/bash-completion/commit/d6237861144c897866630e2d3fb81da5d5413e81)) +* apt-get: Simplify -t and friends completion, support Ubuntu ([9b531a0](https://www.github.com/scop/bash-completion/commit/9b531a08cc825ec723ef8ff78f2072ace6f85a31)) +* apt-get: Sync option list with apt 1.5.1 ([f4e54d9](https://www.github.com/scop/bash-completion/commit/f4e54d918b5a367a7e665d563e2f8336553ea950)) +* apt-get: Add -h/-v/-o non-completions ([c80c82c](https://www.github.com/scop/bash-completion/commit/c80c82c9dcffeb2834f1bcb3edd38a228c20624a)) +* dpkg-source: Add --before-build --after-build --commit, and --print-format ([1404d3f](https://www.github.com/scop/bash-completion/commit/1404d3f995649e1f70ffbb8239acd585e8246df4)) +* README: Link to various distro packages ([c8f4f87](https://www.github.com/scop/bash-completion/commit/c8f4f87070150719249fc1c585d0ec414d120ce7)) +* README: Point Debian and openSUSE badges towards unstable and Tumbleweed ([2dc5865](https://www.github.com/scop/bash-completion/commit/2dc5865bb78d2d9ef131da53b15710528716054b)) +* ssh: Complete all *File option args with _filedir ([7cd0090](https://www.github.com/scop/bash-completion/commit/7cd00901477878d135a844624eff795995199761)) +* test: Add comment line to fixtures/_known_hosts_real/known_hosts ([a0e2ce3](https://www.github.com/scop/bash-completion/commit/a0e2ce369a28c5eb41dd8d96495457ddb9254b28)) +* _known_hosts_real: Reimplement known hosts file parsing in pure bash ([71ac42b](https://www.github.com/scop/bash-completion/commit/71ac42b98c0eba39819fb8478d6443032c6ef6f1)) +* mount, umount: Deprecate on Linux in favor of util-linux >= 2.28 ones ([861be75](https://www.github.com/scop/bash-completion/commit/861be7590ed96fb1aacc8b5161f10a00ae57eebe)) +* .dir-locals.el: Set -O extglob for flycheck bash checks ([b49a182](https://www.github.com/scop/bash-completion/commit/b49a182cc68a9d69d702754c3adc0b17d50e52f6)) +* reportbug: Add bunch of option arg (non-)completions ([81e2971](https://www.github.com/scop/bash-completion/commit/81e29716093a13dff3bde8b9f486e44f99662ac8)) +* a*,ccze,curl,wget: Support completing arg of last bundled short option ([b358aa1](https://www.github.com/scop/bash-completion/commit/b358aa1ebd88e353788f7c5655e9c489fe4eba40)) +* b*: Support completing arg of last bundled short option ([d664aeb](https://www.github.com/scop/bash-completion/commit/d664aebf6bd6ef5ca0602f6440887273bbe000e3)) +* cvs: Add completion for the log command ([7c5a752](https://www.github.com/scop/bash-completion/commit/7c5a75277842b0ac71d1154d87534fccd86ab22b)) +* chage, chpasswd: Add -R/--root arg completion ([5634cfe](https://www.github.com/scop/bash-completion/commit/5634cfe5923a0f9b83b5dc7275185578c9cac68e)) +* dhclient: Parse options with _parse_usage ([5789780](https://www.github.com/scop/bash-completion/commit/57897803dbce6cf90c24bfd59a08fb39cfdfd3c0)) +* dhclient: Add some option arg (non-)completions ([2a7d2e3](https://www.github.com/scop/bash-completion/commit/2a7d2e3eb540188cafda3bf0c103f59ef2b7991f)) +* dselect: Parse options with _parse_help ([1b15dc6](https://www.github.com/scop/bash-completion/commit/1b15dc6884a39928cd57f48f1d900f3d9fef86d7)) +* c*, d*: Support completing arg of last bundled short option ([ed24bbc](https://www.github.com/scop/bash-completion/commit/ed24bbc8e77e3fb40ef7bf730eebfaa3b06cac24)) +* ether-wake: Install for etherwake as well ([b6903bc](https://www.github.com/scop/bash-completion/commit/b6903bc346f6b97d12f02007676dfc280f051fb6)) +* e*: Support completing arg of last bundled short option ([008a407](https://www.github.com/scop/bash-completion/commit/008a4074c72152187195c7fd4a1e47e5ae348528)) +* f*: Support completing arg of last bundled short option ([c1dfa0f](https://www.github.com/scop/bash-completion/commit/c1dfa0f5ab43516e1c31978d05548ca2c8c6008a)) +* g*: Support completing arg of last bundled short option ([e00c119](https://www.github.com/scop/bash-completion/commit/e00c1195427bb092473ec7f753262e5751642d0f)) +* scrub: New completion ([6b5c8d4](https://www.github.com/scop/bash-completion/commit/6b5c8d4dc5ff49e84839279ca581202acc37fce5)) +* ecryptfs-migrate-home: New completion ([3f90f09](https://www.github.com/scop/bash-completion/commit/3f90f09f1b8dc32f9ffb55566bfe8ed88418c52b)) +* h*: Support completing arg of last bundled short option ([1c126ff](https://www.github.com/scop/bash-completion/commit/1c126ff5c64006edc58e33d8bee4546bafb49405)) +* i*: Support completing arg of last bundled short option ([665088a](https://www.github.com/scop/bash-completion/commit/665088ae3925e9d60352b898f35c449420702834)) +* test: Skip scrub -p test when its --help doesn't list available patterns ([9039d77](https://www.github.com/scop/bash-completion/commit/9039d771b63b562276151239c38f760418a9e5f4)) +* lftp: Support completing arg of last bundled short option, handle -s ([ff07e56](https://www.github.com/scop/bash-completion/commit/ff07e569964809400c652e4949c663e80a66fab1)) +* xgamma: Comment spelling fix ([6119b2c](https://www.github.com/scop/bash-completion/commit/6119b2cf0bd96b432482c3361634140a04a77f81)) +* links: Install completion for links2 too ([b1fbe75](https://www.github.com/scop/bash-completion/commit/b1fbe75475c140a7047cf8208650562332ef57ac)) +* iconv: Split charset completion to _iconv_charsets, add test case ([cefd0da](https://www.github.com/scop/bash-completion/commit/cefd0daf30e7022bdbce98de88dca5ba6244c1a5)) +* _filedir: Refactor to remove heredoc-dependent loop ([6ffde95](https://www.github.com/scop/bash-completion/commit/6ffde95c7ea257ff60cb51a263a8d33f4bb0898b)) +* _filedir: Drop unnecessary evals ([7be0dd6](https://www.github.com/scop/bash-completion/commit/7be0dd6c9556c264dfa0fe1b6a8f4d19a2216473)) +* wget: Remove nonexistent arg to _ip_addresses ([9214270](https://www.github.com/scop/bash-completion/commit/92142707893641834e177f6a928160878d6b0506)) +* _ip_addresses: Add option to complete all/v4/v6 addresses, add unit test ([dc72400](https://www.github.com/scop/bash-completion/commit/dc724002cb0291880a2daacc51f2e7ad4cf2950d)) +* links: Major rework, parse options from --help, add option arg completion ([173e104](https://www.github.com/scop/bash-completion/commit/173e1045361404cd9a765438885652cdcb5cef3b)) +* iperf, nc: Include IPv6 addresses in bind address completions ([209b16b](https://www.github.com/scop/bash-completion/commit/209b16bf0888ce6367c06d256e43afffa33a8d90)) +* chmod: New completion ([9501226](https://www.github.com/scop/bash-completion/commit/9501226cb139ac828c5079cb7c079d00277468c8)) +* json_xs: New completion ([1433694](https://www.github.com/scop/bash-completion/commit/143369404d844111a7f4cbd6f19cda16d3738d16)) +* README: Add Q/A on overriding a completion, modernize local install answer ([22e9a02](https://www.github.com/scop/bash-completion/commit/22e9a020adf1ab73896411ca2f3712a445062727)) +* build: Do cmake, pc, and profile variable replacements in Makefile ([81ba2c7](https://www.github.com/scop/bash-completion/commit/81ba2c7e7dfbaefbafa1e8615727c9612e5fb314)) +* build: Use AC_PROG_SED to locate sed ([3031df3](https://www.github.com/scop/bash-completion/commit/3031df31aba36be8fef11186a7bff5163433bae4)) +* pkg-config: Complete on *.pc files ([d8667ae](https://www.github.com/scop/bash-completion/commit/d8667ae379fa325ecd43626fe9cfd5e955450e85)) +* build: Improve cleanup of test/log and test/tmp dirs ([103db12](https://www.github.com/scop/bash-completion/commit/103db12fd29746ec88f69849842fa3d2f9d251d0)) +* test: Run perlcritic and flake8 on perl and python helpers in Travis ([da18668](https://www.github.com/scop/bash-completion/commit/da18668c64bcaa061db00ce17c86fb4dc39ac7dc)) +* lzma: Use _parse_help instead of hardcoded option list ([bca4c60](https://www.github.com/scop/bash-completion/commit/bca4c6002e9381310b3563551bf09b3865c15238)) +* [jkl]*: Support completing arg of last bundled short option ([9ab622e](https://www.github.com/scop/bash-completion/commit/9ab622e76be185380f627c68cd090e69d7b8466a)) +* __load_completion: Avoid bad array subscript on "commands" ending with slash ([583562b](https://www.github.com/scop/bash-completion/commit/583562b9e56207bd428497ceb96df4e1f1f53158)) +* aclocal, automake: Support versioned 1.16 executables ([485d6de](https://www.github.com/scop/bash-completion/commit/485d6de3909f9d8c83eb38c0a1797ba448a3a754)) +* test: Mark psql etc test cases untested if --help doesn't work ([e8e7a15](https://www.github.com/scop/bash-completion/commit/e8e7a154b2dbcad08b02396f114017d3caf02ac4)) +* _xspecs: Declare as global on bash >= 4.2 ([a47bd37](https://www.github.com/scop/bash-completion/commit/a47bd375bb0f95dc6d388d4097c420bddb72ae33)) +* README: Note $BASH_COMPLETION_USER_DIR ([8c67dad](https://www.github.com/scop/bash-completion/commit/8c67dadc402a370e082b372b2df7a9702ab72623)) +* README: Add instructions for overriding completions system wide ([7cbbf35](https://www.github.com/scop/bash-completion/commit/7cbbf353403292395dd4d3c04e506162a457c336)) +* pytest: Rename from py.test to follow upstream recommended name ([fbf2981](https://www.github.com/scop/bash-completion/commit/fbf298186fa94f001ae2ef01b4716e14fe8a544d)) +* rpm: Complete --licensefiles with -q ([fb13b2e](https://www.github.com/scop/bash-completion/commit/fb13b2ef4e7a10bf29ec30301bb8b2fc8654caf3)) +* ngrep, tshark: Complete on *.pcapng too ([550728e](https://www.github.com/scop/bash-completion/commit/550728eb93224da5442f6e9339cbb879a2af7300)) +* ifquery: New ifup alias completion ([932d0be](https://www.github.com/scop/bash-completion/commit/932d0be8904c3a65eb32d784a4b517ad68bf93da)) +* _count_args: Add support for not counting specified option args ([daf010a](https://www.github.com/scop/bash-completion/commit/daf010ad945d84f48ef672ab4905d56e34ad1886)) +* ifup etc: Add option and option argument completion ([f499aa3](https://www.github.com/scop/bash-completion/commit/f499aa3d3dc985d62e99b46198300ce19e0f9d2a)) +* ssh, scp, sftp: Support completing arg of last bundled short option ([645d901](https://www.github.com/scop/bash-completion/commit/645d90167c9d7cd737f49961a0730d9cb892f95b)) +* completions/Makefile.am: Use install-data-hook, not install-data-local ([ee6b37a](https://www.github.com/scop/bash-completion/commit/ee6b37ad7ff5b309cbb9b886a871252abd9398fa)) +* mplayer: Add common supported module music formats ([c2d4221](https://www.github.com/scop/bash-completion/commit/c2d4221655bc2267b8d992489316006a73cee498)) +* mplayer: Associate with *.S[3T]M, *.med, *.MED ([264fb85](https://www.github.com/scop/bash-completion/commit/264fb85647b4b70362cf5a34a69612e241e7fdf3)) +* minicom: Use _parse_help instead of hardcoded option list ([62578a3](https://www.github.com/scop/bash-completion/commit/62578a356387465ecdc878a6e3bb66395bf2b5b1)) +* modinfo: Use _parse_help instead of hardcoded option list ([1397fa7](https://www.github.com/scop/bash-completion/commit/1397fa72a918f5344798faf79273067ffa324345)) +* m*: Support completing arg of last bundled short option ([8f82fd9](https://www.github.com/scop/bash-completion/commit/8f82fd98cc56ac6973ff01407784c3c76b0e462a)) +* mysqladmin: Reuse --default-character-set completion from mysql ([b984e6a](https://www.github.com/scop/bash-completion/commit/b984e6a04a70088ac9c0d6bdb59279274b8a7137)) +* mysql, mysqladmin: Complete --ssl-{ca,cert,key} option arg ([d5ee055](https://www.github.com/scop/bash-completion/commit/d5ee055d6c30b6bc27a28547533912eb7e6b7bd2)) +* modinfo: Fall back to _parse_usage if _parse_help yields no results ([d2f55d0](https://www.github.com/scop/bash-completion/commit/d2f55d0d04eafc24d4a74a15c87d029b43942007)) +* cryptsetup, nc, sh: Skip option args when counting arguments ([11dee0e](https://www.github.com/scop/bash-completion/commit/11dee0e0497210443cf7a32c16ce913a62e449db)) +* cryptsetup: Add some option arg (non-)completions ([68295cc](https://www.github.com/scop/bash-completion/commit/68295cc7f40063e75ddaab0f08b90dcc5a653998)) +* n*: Support completing arg of last bundled short option ([02a13f7](https://www.github.com/scop/bash-completion/commit/02a13f7f0eda6db3e0017a625863c5c43af43829)) +* profile.d: Avoid tested variable values being confused as [ ] operators ([3f1c884](https://www.github.com/scop/bash-completion/commit/3f1c884bef639af2cae959b04b87fb3a41eeeb7d)) +* passwd: Try _parse_help before _parse_usage to parse options ([16e82b8](https://www.github.com/scop/bash-completion/commit/16e82b8c27a4ccce0cc0c4f203617f747d427b5f)) +* [op]*: Support completing arg of last bundled short option ([5a654a8](https://www.github.com/scop/bash-completion/commit/5a654a834a44c9569b527b543b39fbe969efbe74)) +* pyvenv: Support versioned 3.6-3.8 executables ([b0de719](https://www.github.com/scop/bash-completion/commit/b0de7196c1e211f0f832c8d7af3ce38f85f1ab94)) +* querybts: Use _parse_help, not hardcoded option list, misc improvements ([00de26b](https://www.github.com/scop/bash-completion/commit/00de26bf42b9d389dae36787386e4a2ab0cf6c1b)) +* reportbug: Run _parse_help and apt-cache more selectively ([ecdcdb5](https://www.github.com/scop/bash-completion/commit/ecdcdb5f240a2a63accaa1c5da35eb74fdbacef4)) +* [qr]*: Support completing arg of last bundled short option ([13579f2](https://www.github.com/scop/bash-completion/commit/13579f2426ca88b1ae966bea3abc6a6326d99e83)) +* jq: New completion ([8d57c41](https://www.github.com/scop/bash-completion/commit/8d57c41995f17eef59506d79d44ec4276d2086cc)) +* tune2fs: Update -o/-O argument lists ([27efd8c](https://www.github.com/scop/bash-completion/commit/27efd8c1d66a47a5313c3467ce6b67b6b150ef90)) +* sqlite3: Add some option arg (non-)completions ([1c2b0d7](https://www.github.com/scop/bash-completion/commit/1c2b0d778bcaf19dc13844100af3627c6367cbad)) +* sshow: Add -p arg completion ([c2acf69](https://www.github.com/scop/bash-completion/commit/c2acf697c57ff931d1c943f69c2745b7cf5eea20)) +* strace: Use _parse_help instead of hardcoded option list ([77539a5](https://www.github.com/scop/bash-completion/commit/77539a50d6073be3b4972ed14069002e69b3d41b)) +* sudo: Parse options from help/usage output, add some long option support ([46d5d2d](https://www.github.com/scop/bash-completion/commit/46d5d2d4ea9be932a48f7e7de5a9e4ad2231a74b)) +* test: Add sysctl option parsing test case ([5b8b66a](https://www.github.com/scop/bash-completion/commit/5b8b66a3feaf73bfa9780e69d0308e1d2d367f1d)) +* sysctl: Recognize --pattern/-r and --load options ([0f63ecb](https://www.github.com/scop/bash-completion/commit/0f63ecb8234f97a6669a7ee0bb4a57cbe3e5cb54)) +* sudo: Improve long option arg handling ([ca3b1f6](https://www.github.com/scop/bash-completion/commit/ca3b1f664f0bfa92cc688909dee68937fd638286)) +* s*: Support completing arg of last bundled short option ([bd1d93c](https://www.github.com/scop/bash-completion/commit/bd1d93cede385001667f0ad205f4e900711b42c8)) +* jq, sqlite3: Protect against negative array subscripts ([bd3e2f2](https://www.github.com/scop/bash-completion/commit/bd3e2f297018bdbcd81b719f47c433d8e0aa1d17)) +* test: Support running with local BSD binaries, do it w/ ubuntu14 in CI ([2fe53fe](https://www.github.com/scop/bash-completion/commit/2fe53fef669a9dc077784bf3ab73db650d879ab2)) +* xdg-settings: Make help parsing work on BSD ([40f1c24](https://www.github.com/scop/bash-completion/commit/40f1c24fb3109c074efdea1f897b062afccb725e)) +* test: Skip jq option completion test if its --help doesn't list them ([e407508](https://www.github.com/scop/bash-completion/commit/e40750884e25700aa02f3e1ffb9a7662b05e9a47)) +* tracepath: Actually use our separate completion instead of _known_hosts ([b0c0d5e](https://www.github.com/scop/bash-completion/commit/b0c0d5e201a15857c065ccea204ddaf67accfef0)) +* tracepath: Add -m and -p arg non-completions ([a7ee04e](https://www.github.com/scop/bash-completion/commit/a7ee04e98f0c30cab5e53f852e6373e75872a30c)) +* urlsnarf: Add -p arg completion ([8cf0ce3](https://www.github.com/scop/bash-completion/commit/8cf0ce3dc6f73aa67cee59846d1ec828814fe222)) +* uscan: Use _parse_help instead of hardcoded option list ([d13306d](https://www.github.com/scop/bash-completion/commit/d13306d74fbe879398bdc86a7b0dc4fc9bd5534b)) +* [tu]*: Support completing arg of last bundled short option ([26cb739](https://www.github.com/scop/bash-completion/commit/26cb739d3cd1a1935f1b5e186090ea9dfd4847fd)) +* test: Fix iwspy test case ([886f4a1](https://www.github.com/scop/bash-completion/commit/886f4a1e3168b6e413e5a9cb60c2b3ed714c3734)) +* [vwx]*: Support completing arg of last bundled short option ([bbd6296](https://www.github.com/scop/bash-completion/commit/bbd629670ca291e10d1d9a7a68941025d94959e0)) +* fio: New completion ([c92a426](https://www.github.com/scop/bash-completion/commit/c92a4264fe8522de6040a14e8e6f9a3ed1ddf792)) +* ngrep: Add "any" to -d arg completions ([507d593](https://www.github.com/scop/bash-completion/commit/507d593962ed8a305e17ac7807704ee5fc4f9ae1)) +* tshark: Get available interfaces from -D output ([8d7d24d](https://www.github.com/scop/bash-completion/commit/8d7d24d949ba77cd26ae904614fffdbae05e5246)) +* pylint: Option arg completion improvements ([fe69cb5](https://www.github.com/scop/bash-completion/commit/fe69cb582b42a02aebd6ea59ce6449de43da7f4c)) +* mplayer: Associate with *.w64 ([6526596](https://www.github.com/scop/bash-completion/commit/6526596964b311a830507c5342818253212ec405)) +* test: Mark flake8 untested if it seems broken ([a5d490a](https://www.github.com/scop/bash-completion/commit/a5d490a330be979c47f3a2b61c608c83a1e3db45)) +* test: Limit number of wget option completions to avoid unresolved result ([4f242f2](https://www.github.com/scop/bash-completion/commit/4f242f2bd70bd0706061c81600402f2887d032f9)) +* travis: Split long lines in script ([d765f75](https://www.github.com/scop/bash-completion/commit/d765f756036907574bcf9ecdb2be6f8ddb7bc056)) +* travis: Run ubuntu14/bsd with no network ([64c1817](https://www.github.com/scop/bash-completion/commit/64c18170a44df5fe3a0c384f9b95cebe80405997)) +* pydoc, pylint: Skip module completion if current looks like a path ([bdd6458](https://www.github.com/scop/bash-completion/commit/bdd64589f2466f1bdab9708aa530536c66a13bc7)) +* gpgv: New completion ([ff65882](https://www.github.com/scop/bash-completion/commit/ff6588216dc1e789b091a27430e6d512f5bbfcb0)) +* extra/git-post-commit.sh: Add git post-commit Docker Hub trigger hook ([03442fa](https://www.github.com/scop/bash-completion/commit/03442face6795c56ba0b89eadcc8f7e1ba1b0f14)) +* _services: Try systemctl list-unit-files if systemctl list-units fails ([9f52c69](https://www.github.com/scop/bash-completion/commit/9f52c693d9eecd66f6a92343121a8230c32215b3)) +* test: Run docker tests with --verbose ([d45f902](https://www.github.com/scop/bash-completion/commit/d45f9020ae30b5c70e0ddf449a6e7877ea637f44)) +* test: Bump expect's match_max to 20000 by default ([bda6e45](https://www.github.com/scop/bash-completion/commit/bda6e453e79123b1adbc7b979f93437ad2e4bcf0)) +* test: Fix buffer size option listing in run --help ([eb21e66](https://www.github.com/scop/bash-completion/commit/eb21e663bd82e1a6e13fef2fe272fcf7ebde6850)) +* pylint: Implement comma separated --confidence arg completion ([5aee5d7](https://www.github.com/scop/bash-completion/commit/5aee5d77ebb7c1a1e242558f72b0a1dd178b9945)) +* pylint: Bring -f/--format arg completion up to date with pylint 1.9.2 ([7e6a220](https://www.github.com/scop/bash-completion/commit/7e6a22079bfab2f9eb38d4743e43cadb89880a59)) +* pydoc, pylint: Determine python2/3 based on command basename only ([fa6ec59](https://www.github.com/scop/bash-completion/commit/fa6ec59dfacdb7067575ad0c2d13b8494fbd4397)) +* test: Limit number of pylint option completions ([9f75f4b](https://www.github.com/scop/bash-completion/commit/9f75f4bcd2da48dc24d9e5a0f8cce5658c164d94)) +* test: Add pylint-3 test case ([c401847](https://www.github.com/scop/bash-completion/commit/c40184702676816ea79cd1746867ffc1e5311e8d)) +* git-post-commit: Avoid some error trash when HEAD is not a symbolic ref ([579b733](https://www.github.com/scop/bash-completion/commit/579b73367d9437c1c5b33653d26be11c4a2a19b4)) +* tox: Fall back to --listenvs for env list if --listenvs-all fails ([6009de8](https://www.github.com/scop/bash-completion/commit/6009de8534cd24b71d0bfda479823abcc640e4b1)) +* test: Start converting test suite to pytest+pexpect ([641173e](https://www.github.com/scop/bash-completion/commit/641173e04e9819134a9ad1b02a4217f61bf7882c)) +* test: Update generate for pytest+pexpect ([8b1d916](https://www.github.com/scop/bash-completion/commit/8b1d916faf9841a6bbc09a36f2ba84049ce5be40)) +* test: Convert first bunch of completions to pytest+pexpect ([ff4289f](https://www.github.com/scop/bash-completion/commit/ff4289f9f2994eb807f4c0a9ec996fd78542e8c3)) +* test: Don't include our magic mark in completions ([d8712ad](https://www.github.com/scop/bash-completion/commit/d8712ad6a89827fef871e10c082a7fd2b533a337)) +* test: Fix completion list when there's one completion ([4fc8f71](https://www.github.com/scop/bash-completion/commit/4fc8f718d5bb0550c9e88452c43ce69437bfba57)) +* test: Convert remaining simple x* to pytest+pexpect ([ae9b3a9](https://www.github.com/scop/bash-completion/commit/ae9b3a9e8313e8403acfbb1d453dd2691f0c60c1)) +* test: Improve generate to handle basic args and problematic chars ([6fc2de1](https://www.github.com/scop/bash-completion/commit/6fc2de1b362dfbffa3d9156c68490d47259ba82e)) +* test: Convert trivial [u-z]* test cases to pytest+pexpect ([ac47b5c](https://www.github.com/scop/bash-completion/commit/ac47b5c49a9e8e2434bb33a86d687f347d6d03cb)) +* test: Add some additional simple completion test cases ([b2e0c51](https://www.github.com/scop/bash-completion/commit/b2e0c51ed5198bae5d9e1218f16967450eff93eb)) +* test: Use make pytest docker executable env-configurable, default pytest-3 ([2473d1f](https://www.github.com/scop/bash-completion/commit/2473d1f9490dd3cca631a8fb5e9722e0812e4cd0)) +* test: Use /root/.local/bin/pytest on centos6 by default ([6164b45](https://www.github.com/scop/bash-completion/commit/6164b45a48a5a058dcdfa7f5562ade4a126fc431)) +* test: Convert trivial t* test cases to pytest+pexpect ([4205d79](https://www.github.com/scop/bash-completion/commit/4205d7921caa09edae4a183133591fa2817e727c)) +* test: Convert trivial s* test cases to pytest+pexpect ([cd11331](https://www.github.com/scop/bash-completion/commit/cd113319ba73d14f6ed73782365902e6d938f10c)) +* test: Add new test files to EXTRA_DIST ([6130867](https://www.github.com/scop/bash-completion/commit/6130867362edd027183303aa174d2005e405a59c)) +* test: Add generated test files to t/Makefile.am automatically ([a672f55](https://www.github.com/scop/bash-completion/commit/a672f550aa0216b21ce8275a93cddb592e639481)) +* test: Convert trivial [qr]* test cases to pytest+pexpect ([2b79b27](https://www.github.com/scop/bash-completion/commit/2b79b273ce80bdd076335af22249929b7d3c09af)) +* test: Use /root/.local/bin/pytest on ubuntu14 by default ([36f73ad](https://www.github.com/scop/bash-completion/commit/36f73ad8a9a6cd7f29483823025c8ed06af2966c)) +* test: Convert trivial o* test cases to pytest+pexpect ([9ba87c3](https://www.github.com/scop/bash-completion/commit/9ba87c39a75b17b46894ad47217d83df2b5fe051)) +* test: Bulk convert lots of trivial test cases to pytest+pexpect ([cdb9a22](https://www.github.com/scop/bash-completion/commit/cdb9a224868449fefbe6447c5475b749d5a3851c)) +* test: Bulk convert some more trivial test cases to pytest+pexpect ([e546577](https://www.github.com/scop/bash-completion/commit/e5465771b901ac59fbbd67d121d26654e076c79a)) +* test: Make "generate" do the right thing with more partial args ([45d5ad9](https://www.github.com/scop/bash-completion/commit/45d5ad98adca66e20a6384aa825f492939d600c9)) +* test: Convert some more trivial test cases to pytest+pexpect ([de97e77](https://www.github.com/scop/bash-completion/commit/de97e775e08b4c60f93908927d85b45860e91dc2)) +* test: Convert some more trivial test cases to pytest+pexpect ([8c9c4f1](https://www.github.com/scop/bash-completion/commit/8c9c4f12d72c2b275e8d6d34edb2cf560d1aa93a)) +* test: Convert some more trivial test cases to pytest+pexpect ([5cab3b3](https://www.github.com/scop/bash-completion/commit/5cab3b32dcb22f585f16b4a34007b053bad90cc6)) +* test: Convert some more trivial test cases to pytest+pexpect ([cb17e4b](https://www.github.com/scop/bash-completion/commit/cb17e4be72e2ccf0c2704e97faa13ada8d22acac)) +* test: Treat non-dash args better in generate ([ecfa09d](https://www.github.com/scop/bash-completion/commit/ecfa09d4a5629d3adbc502940156db5498922049)) +* iperf: Add g/G to --format completions ([cfef384](https://www.github.com/scop/bash-completion/commit/cfef3841d1f38b724d1209a9e43885cde5b89b97)) +* iperf: Install for iperf3 too ([a520baa](https://www.github.com/scop/bash-completion/commit/a520baa0c68fabf283129521c2a59bc2e9597805)) +* iperf: Improve client/server specific option parsing ([51863c4](https://www.github.com/scop/bash-completion/commit/51863c4604771e04f7dca2f6f1a960fc7558b723)) +* xmodmap: Use _parse_help instead of hardcoded option list ([fa278dc](https://www.github.com/scop/bash-completion/commit/fa278dcf99bfae48ced96740712b231f069c1447)) +* iperf: Add g/G to --format completions ([a2277c0](https://www.github.com/scop/bash-completion/commit/a2277c0857ce13c2b4ada55206af72482c6c7d71)) +* iperf: Install for iperf3 too ([e4425bd](https://www.github.com/scop/bash-completion/commit/e4425bd5d36d94b2682c8ffb7cb60d91e8814be6)) +* iperf: Improve client/server specific option parsing ([c187063](https://www.github.com/scop/bash-completion/commit/c187063b955f837f9bbd22ec52ca4133aeac7d39)) +* xmodmap: Use _parse_help instead of hardcoded option list ([1b60881](https://www.github.com/scop/bash-completion/commit/1b608812e47a091933b685d01bcbed03dd2107f1)) +* test: Add some iperf, iperf3 and xmodmap test cases ([b3acc94](https://www.github.com/scop/bash-completion/commit/b3acc9412937abd92a9ff4d7a34515520df56b5c)) +* test: Make test base work with Python 3.3+ ([83e91da](https://www.github.com/scop/bash-completion/commit/83e91da21d33be89f0aa2a07a0706b4910f4ba2c)) +* test: Add support for pytest pre-test commands ([ccba78d](https://www.github.com/scop/bash-completion/commit/ccba78d32a82c2081d5d08beed2887f944f96335)) +* test: Convert some more test cases to pytest+pexpect ([987aa3d](https://www.github.com/scop/bash-completion/commit/987aa3d50cc3a5c6b1dd8620cd5c5c7ed7eb1d2e)) +* test: Add support for skipping individual tests based on shell command status ([6a4d824](https://www.github.com/scop/bash-completion/commit/6a4d8245f6919550f18c4534a25fd59f61d11437)) +* test: Convert some more test cases to pytest+pexpect ([8145625](https://www.github.com/scop/bash-completion/commit/81456254bb4e09a09447a4429c923e478088327b)) +* test: .gitignore pytestdebug.log ([24c66c1](https://www.github.com/scop/bash-completion/commit/24c66c1184c7f38d3c56fe6d4fcf8b8e38fc2514)) +* test: Convert some more test cases to pytest+pexpect ([27053d1](https://www.github.com/scop/bash-completion/commit/27053d104ce140291e9d2b024c313167facaf2e3)) +* test: Add support for running test case in a specified dir ([339874f](https://www.github.com/scop/bash-completion/commit/339874fdc5a5f9805fec6aaee0c4dd0f24febb6e)) +* test: Convert some more test cases to pytest+pexpect ([ed64828](https://www.github.com/scop/bash-completion/commit/ed64828e9f5c883946e93771b7d9a4f1bdaa0323)) +* test: Fix some regressions introduced in recent test conversions ([aaaa60d](https://www.github.com/scop/bash-completion/commit/aaaa60d67fea6322f54e2a79cb83b02f4f254e32)) +* test: Convert some more test cases to pytest+pexpect ([038fd4e](https://www.github.com/scop/bash-completion/commit/038fd4e2c92ebf487ca936edff2bd3cc6512706c)) +* test: Convert some more test cases to pytest+pexpect ([c32a405](https://www.github.com/scop/bash-completion/commit/c32a405000539483a4c5ad3527e297b640dd76b3)) +* test: Convert some more test cases to pytest+pexpect ([e0be296](https://www.github.com/scop/bash-completion/commit/e0be296af493d3998dca9acb44f82dce636af106)) +* test: Include command name in test class name, use numbered test method names ([649cd43](https://www.github.com/scop/bash-completion/commit/649cd43616fdba56648fbccaf5194c2a6022587d)) +* test: Convert some more test cases to pytest+pexpect ([aece7ad](https://www.github.com/scop/bash-completion/commit/aece7ad1bbc1870ba1016f00e9047094734a480a)) +* test: Add class level skipif based on bash exec result ([ae723ed](https://www.github.com/scop/bash-completion/commit/ae723ed0504c45afc1bb34fdc65d5329094ce083)) +* test: Add python3 test case ([9a0fddc](https://www.github.com/scop/bash-completion/commit/9a0fddc85b8f4d7c85446ea8e0e976187a4a4658)) +* test: Convert some more test cases to pytest+pexpect ([c5300cd](https://www.github.com/scop/bash-completion/commit/c5300cd5571cc432e277a8d9aff35f6f2d23eb8f)) +* test: Rename BASHCOMP_* test env variables to BASHCOMP_TEST_* ([2fa7566](https://www.github.com/scop/bash-completion/commit/2fa75666ee48edc744db322621398a4ffcc07d7d)) +* test: Log pexpect interaction to $BASHCOMP_TEST_LOGFILE if set ([5198bf5](https://www.github.com/scop/bash-completion/commit/5198bf5328fb5f6875b3b7c010e89efd6c92417a)) +* test: Pass through $HOME and $DISPLAY to test bash ([2c32433](https://www.github.com/scop/bash-completion/commit/2c3243300316d3ebff18045cb4e0f162a41a5fce)) +* test: Fixture reorganization ([c677b8e](https://www.github.com/scop/bash-completion/commit/c677b8e09bee213b6392dc4cd7364989ebb4f9a4)) +* test: Add ability to selectively ignore diffs in environment ([e575c8e](https://www.github.com/scop/bash-completion/commit/e575c8ed1e3e2f84c92c845790d50d5b31426e60)) +* test: Implement load_completion_for using assert_bash_exec ([dd9a6eb](https://www.github.com/scop/bash-completion/commit/dd9a6ebd14bec202ddf7809e2a18075e7e5bdcb4)) +* test: Convert some more test cases to pytest+pexpect ([73f05ba](https://www.github.com/scop/bash-completion/commit/73f05bad0c3db9dcee3572b8143ff13678951ad3)) +* test: Replace + with Plus in test class names ([d1c2c72](https://www.github.com/scop/bash-completion/commit/d1c2c72b9a79b97cc53b186d9c681a62f0a721c7)) +* test: Mark xfreerdp as expected failure for now ([489dc30](https://www.github.com/scop/bash-completion/commit/489dc30682529d2c2cce54f02bce8da1ec54e742)) +* test: Convert some more test cases to pytest+pexpect ([fff2fa3](https://www.github.com/scop/bash-completion/commit/fff2fa3098423cb1e2cfe52762c8fcf4a48fe5ee)) +* test: chdir to fixtures dir in Python as well ([08a89c0](https://www.github.com/scop/bash-completion/commit/08a89c08d531333966f54a70942d0c44a703856a)) +* test: Allow __load_completion to fail ([4abf2ba](https://www.github.com/scop/bash-completion/commit/4abf2bae1b5fcf58c6b981fcebf907ac83fe7107)) +* test: Sort completion results in Python for ease of use in Python tests ([f40cfe0](https://www.github.com/scop/bash-completion/commit/f40cfe0dfa40f2e7d6db68d370aa98ec2cbbd7b3)) +* test: Convert some more test cases to pytest+pexpect ([9e6ed13](https://www.github.com/scop/bash-completion/commit/9e6ed13f4936058e1042ad34558b95c1f46472c4)) +* test: Use more conventional Python file names for tests ([9c278da](https://www.github.com/scop/bash-completion/commit/9c278dada33667ff7edcfda2c21115fb8662909f)) +* test: Add support for per-test env modifications ([be3d073](https://www.github.com/scop/bash-completion/commit/be3d0735e78f1d3bc0e8eff17fcff86921bed6d4)) +* test: Don't require complete marker on test methods ([9d15992](https://www.github.com/scop/bash-completion/commit/9d1599228b07da22b6ec3ae876797ce3af1bbda8)) +* test: Fix jq and scrub skipif commands ([b7840bf](https://www.github.com/scop/bash-completion/commit/b7840bfccefe79189b782135aa85076723d72e24)) +* test: Convert some more test cases to pytest+pexpect ([ba4c972](https://www.github.com/scop/bash-completion/commit/ba4c972333bfbf86dbc94ccc9ed406b1883eb424)) +* test: Misc test suite fixes ([d1f983a](https://www.github.com/scop/bash-completion/commit/d1f983a9f5cdccaeb148b64f6887001c9182a8b0)) +* test: Convert some more test cases to pytest+pexpect ([ff1e0af](https://www.github.com/scop/bash-completion/commit/ff1e0afb01a8d4a655865cf40c0a46a25405454c)) +* test: Convert some more test cases to pytest+pexpect ([044e5da](https://www.github.com/scop/bash-completion/commit/044e5da3169137c8d777ab87cde5424430f65c66)) +* test: Misc test suite fixes ([6de89eb](https://www.github.com/scop/bash-completion/commit/6de89eb37d459d9a455ab7bb42c5fcbd97c5077c)) +* test: Convert some more test cases to pytest+pexpect ([75628f7](https://www.github.com/scop/bash-completion/commit/75628f77b481ed73120f9101e31e983057a16756)) +* test: Support setting cmd=None to require no command, for unit tests ([8884ceb](https://www.github.com/scop/bash-completion/commit/8884cebab72ae8d8ac3873d595ff501c3b54e27a)) +* test: Convert some more test cases to pytest+pexpect ([416fc05](https://www.github.com/scop/bash-completion/commit/416fc05ac24105a70f719419241fcff248827204)) +* test: Convert some more test cases to pytest+pexpect ([c85516b](https://www.github.com/scop/bash-completion/commit/c85516be79397c24ade9c12c89fd77f364f1ad46)) +* test: Use test_unit_* prefix for unit tests, to avoid name clashes ([c7b3427](https://www.github.com/scop/bash-completion/commit/c7b3427cb085d02b7559604489ded675752f58d1)) +* test: Convert some more test cases to pytest+pexpect ([d5b0d1b](https://www.github.com/scop/bash-completion/commit/d5b0d1b0a98fcea8de578a31e943d0187e4f1995)) +* test: Misc test suite fixes ([fddc36f](https://www.github.com/scop/bash-completion/commit/fddc36f36312eee100283d93baacf22a73952823)) +* test: Convert some more test cases to pytest+pexpect ([35e94b7](https://www.github.com/scop/bash-completion/commit/35e94b736a1304344a28430127bc5cae059dac63)) +* test: Misc test suite fixes ([e50dfec](https://www.github.com/scop/bash-completion/commit/e50dfeca93957f9b043538df6f7aa779d1f7f7e6)) +* test: Convert some more test cases to pytest+pexpect ([3ca2039](https://www.github.com/scop/bash-completion/commit/3ca20396fdb398c6c52956efe682c9d468da7266)) +* test: Convert some more test cases to pytest+pexpect ([451b3d1](https://www.github.com/scop/bash-completion/commit/451b3d1187547550cc382b2ee94c234dcf52d32b)) +* gccgo: Add as a GCC completion target (#227) ([ec9aefa](https://www.github.com/scop/bash-completion/commit/ec9aefa37fc9b0b53c004481402221e517a3a3ae)) +* gcc: Add g++, gcc, gccgo, and gfortran *-7 aliases ([bea1d6a](https://www.github.com/scop/bash-completion/commit/bea1d6a2419412513f11918f20fa74fd1f229403)) +* __load_completion: Avoid unnecessary lookups from nonexistent dirs ([f2b76a1](https://www.github.com/scop/bash-completion/commit/f2b76a1eb254bb6399c5d7a10bec659b691704e4)) +* unzip, zipinfo: Associate with *.whl ([df8bc32](https://www.github.com/scop/bash-completion/commit/df8bc32be0989cef6c4baaa30230848f9d1ea4ad)) +* test: Misc test suite fixes ([d1b0a75](https://www.github.com/scop/bash-completion/commit/d1b0a756a68e234b78861abf51b40f89123548d0)) +* test: Make case specific env entries shell code, not escaped ([703dcb8](https://www.github.com/scop/bash-completion/commit/703dcb860e2523f684479f73bb5caf14517d86d2)) +* test: Convert some more test cases to pytest+pexpect ([0518f62](https://www.github.com/scop/bash-completion/commit/0518f62c0c17fa48c574fe2cb915f8a75f87ab59)) +* test: Pylint fixes ([bbf6ff1](https://www.github.com/scop/bash-completion/commit/bbf6ff116f4be7236af996b014c24524513fe3e8)) +* test: Remove kill, killall remnants ([8e21442](https://www.github.com/scop/bash-completion/commit/8e214425bd53f6a7338e96b34748653abda781c2)) +* test: Mark MANPATH without leading/trailing colons test an xfail on CI CentOS 6 ([896aac9](https://www.github.com/scop/bash-completion/commit/896aac9b68cab927abf2351f4ea1041d30277156)) +* nc: Add some more option (non-)completions ([4d88339](https://www.github.com/scop/bash-completion/commit/4d88339928aa064a567d5feb40694dfd24a274c5)) +* test: Convert some more test cases to pytest+pexpect ([3f84586](https://www.github.com/scop/bash-completion/commit/3f8458652a65ad761b9b7f771385295c0cb43f73)) +* test: Pylint fixes ([1389110](https://www.github.com/scop/bash-completion/commit/13891101fc4e11b5fb9eab10b215f1caf501dc65)) +* test: Convert some more test cases to pytest+pexpect ([0db4768](https://www.github.com/scop/bash-completion/commit/0db4768883afbe01ec5f7333ee25289dee0eebd4)) +* test: Convert some more test cases to pytest+pexpect ([b6f4e50](https://www.github.com/scop/bash-completion/commit/b6f4e500b2389e92b69014cf316e521ac98c567a)) +* test: Convert some more test cases to pytest+pexpect ([23da5e6](https://www.github.com/scop/bash-completion/commit/23da5e63b7cee02e7f405f96cf8957b007abaf94)) +* firefox etc: New non-xspec completion ([ab572bb](https://www.github.com/scop/bash-completion/commit/ab572bbf1bd33785cf0c53b7c4ba87144413ea34)) +* chromium-browser, google-chrome*: New non-xspec completion ([9db48eb](https://www.github.com/scop/bash-completion/commit/9db48eb67e9a9b4479913f06b2384a6087051e81)) +* test: Convert some more test cases to pytest+pexpect ([f0f0976](https://www.github.com/scop/bash-completion/commit/f0f097642fb3aa8d91c403646367b65bddd2820f)) +* doc: Start documenting new pytest+pexpect tests ([58499ba](https://www.github.com/scop/bash-completion/commit/58499ba3c9d57ac2a08d9a8de29240e58d19de33)) +* mplayer etc: Complete on *.crdownload partial downloads in addition to *.part ([2837a48](https://www.github.com/scop/bash-completion/commit/2837a48c7954116b4e6d4e1c911798b6e54f6c68)) +* freeciv-gtk2: Install for freeciv and freeciv-gtk3, rename to freeciv ([f253e1e](https://www.github.com/scop/bash-completion/commit/f253e1e8edb4f7bd307afc5e7171e7995a4cb998)) +* freeciv: Option and arg completion updates ([fcaff16](https://www.github.com/scop/bash-completion/commit/fcaff164be94317b7cafbd05a5f5826105382df5)) +* isort: New completion ([c2dd674](https://www.github.com/scop/bash-completion/commit/c2dd6745661d886327bb79591a6c6911f6f5c3f6)) +* gnome-screenshot: New completion ([4581c6f](https://www.github.com/scop/bash-completion/commit/4581c6fe9715a57337af06648daad78d5d326d0e)) +* perlcritic: New completion ([2f8da81](https://www.github.com/scop/bash-completion/commit/2f8da814f715327db0f509c8e409e237fc9d5ff8)) +* gcc: Add g++, gcc, gccgo, and gfortran *-[568] aliases ([c9c14da](https://www.github.com/scop/bash-completion/commit/c9c14da4d32f3713b3a28e5c706f92a6f0903d35)) +* test: Remove leftover completion/ls.exp ([46ff7b3](https://www.github.com/scop/bash-completion/commit/46ff7b378430c5a3f456d2b096f9d16925f3f231)) +* tshark: update -T and -t completions ([5869351](https://www.github.com/scop/bash-completion/commit/58693518ecb561e7f7e9a0d4b6767cbf18f4238d)) +* tshark: prevent a single-character file from breaking -G completion ([8618ea5](https://www.github.com/scop/bash-completion/commit/8618ea52e48e55f04f001f0b90955b2a4a157e33)) +* tshark: support .gz and .cap files for -r expansion ([a250248](https://www.github.com/scop/bash-completion/commit/a25024815f43b99e9b77a2991ecc9ab16bfe7f41)) +* xmllint: Improve --encode, --pretty, and --xpath arg (non-)completions ([cf5fe10](https://www.github.com/scop/bash-completion/commit/cf5fe10fe03f67f6d477aef04585277fda3d3ee4)) +* chromium-browser: consider chrome and chromium as aliases ([58da331](https://www.github.com/scop/bash-completion/commit/58da33199ff84bf12ae561071a15fa825fda8487)) +* conftest: fix RemovedInPytest4Warning due to use of node.get_marker ([9249a2a](https://www.github.com/scop/bash-completion/commit/9249a2a9005a3b9c91ff6e432dd96337688254f6)) +* doc: Some pytest install clarifications ([e463b89](https://www.github.com/scop/bash-completion/commit/e463b89d600cc6a2d040556e24090a083f5c98cd)) +* test: fix flake8 complaints about unused imports ([27a9856](https://www.github.com/scop/bash-completion/commit/27a98567e3027fa006b3e4ee2702b14e5077d10d)) +* test: fix misinterpretation of completion output in tests ([85275cf](https://www.github.com/scop/bash-completion/commit/85275cf550433a90f4875845142ad93132b16820)) +* okular: Added support for xz-compressed files. ([0381d27](https://www.github.com/scop/bash-completion/commit/0381d275e085b63adf4842d0c6b3d41eeea02141)) +* hunspell: New completion ([eaecbf4](https://www.github.com/scop/bash-completion/commit/eaecbf4df704d43b27672a235e14cc3bf9d309b9)) +* op: New completion ([03ddd0b](https://www.github.com/scop/bash-completion/commit/03ddd0b4103d12b975a5a3be9c4b4627deae1e3a)) +* mypy: New completion ([12db483](https://www.github.com/scop/bash-completion/commit/12db483cdb08b4d602050f1ae63692e8d768fee2)) +* test: Convert remaining perl test cases to pytest+pexpect ([8aa8c84](https://www.github.com/scop/bash-completion/commit/8aa8c840ad636d4b31bdeaba63fb9d9a9e6c8fc1)) +* 7z: add .msi support ([d6b678c](https://www.github.com/scop/bash-completion/commit/d6b678cab235fa5b27fa4961bd4a92f19081b13d)) +* test: Convert more tar test cases to pytest+pexpect ([eaba3aa](https://www.github.com/scop/bash-completion/commit/eaba3aadf36751229b91215a24cb91bf3779ddb8)) +* dpkg: List held packages (#250) ([95042d0](https://www.github.com/scop/bash-completion/commit/95042d01826dd01340e09e948a2525a905e336d3)) +* makepkg: Use _parse_help instead of hardcoding option list ([bdbe5ef](https://www.github.com/scop/bash-completion/commit/bdbe5ef109d4942412e4f795bd29a7c79483832c)) +* test: Allow unknowns options in makepkg option completion ([9227e92](https://www.github.com/scop/bash-completion/commit/9227e920dbb35f47dcdf827e4561722ef0e8426f)) +* makepkg: Don't apply to other than Slackware makepkg ([d44e854](https://www.github.com/scop/bash-completion/commit/d44e8548cc8b8e4ee2656af7228248125de829eb)) +* locale-gen: New completion ([6176fd6](https://www.github.com/scop/bash-completion/commit/6176fd65af83cd7737d481d195030bdd0f92d1db)) +* test: Convert cancel test case to pytest+pexpect ([efd68b2](https://www.github.com/scop/bash-completion/commit/efd68b2b8b059328a7b39cc96bf4c236a0a55340)) +* cancel: Add some option arg (non-)completions ([9fcc52f](https://www.github.com/scop/bash-completion/commit/9fcc52fede350af591a9dad3295299afee5705aa)) +* cancel: Split long line ([896adae](https://www.github.com/scop/bash-completion/commit/896adaea7dbb703bb2b93879e5f293f2cf17063f)) +* test: Convert portinstall test case to pytest+pexpect (untested) ([da37fa3](https://www.github.com/scop/bash-completion/commit/da37fa341903565379523b6e85fb7626997e1879)) +* tar: Support completions for zstd compression extensions (#255) ([1d911cb](https://www.github.com/scop/bash-completion/commit/1d911cb0fe7ed2797d7ab16cd3858970b7dbae5c)) +* tar: Clean up some redundant code ([a143560](https://www.github.com/scop/bash-completion/commit/a143560f315ddfbe7c4662cba8a27b93137f425b)) +* ssh-copy-id: Add -i and -o arg (non-)completions ([f8d1280](https://www.github.com/scop/bash-completion/commit/f8d1280df57acfc1d0d49a9eb117f78cfb563ad3)) +* test suite: Ignore _scp_path_esc in env for ssh-copy-id ([84f40ab](https://www.github.com/scop/bash-completion/commit/84f40ab5dca1e70284e3bc56773b1de6a2974b68)) +* grpck: Add --root/-R arg completion ([5bd30be](https://www.github.com/scop/bash-completion/commit/5bd30be3990094f5ee6fc0468b6d24bc90465ebc)) +* grpck: Parse options with _parse_help, falling back to _parse_usage ([4f64fb0](https://www.github.com/scop/bash-completion/commit/4f64fb0d7ed7a83cd888e0f25d4050e26c20a060)) +* test: Add requirements.txt for installing dependencies ([b1192e2](https://www.github.com/scop/bash-completion/commit/b1192e26876ee01ae81b9dce2736a37beb9aeeba)) +* doc: Some test dependency doc updates ([9aaa0b8](https://www.github.com/scop/bash-completion/commit/9aaa0b80eb6798613781d8aa133975e5267eddcd)) +* _filedir_xspec: Fallback to suggesting all files if requested (#260) ([464c822](https://www.github.com/scop/bash-completion/commit/464c822ee44abb2f3d5a9f559099a303505668cf)) +* doc: Update docs on generating simple tests ([840f342](https://www.github.com/scop/bash-completion/commit/840f342d31c47debc9fdf69d6bb1733d24166608)) +* test: Expect failure in gkrellm if there's no X display ([eeb63ea](https://www.github.com/scop/bash-completion/commit/eeb63ead44b0eb28fe4c6f817a292f9a11e29436)) +* arp: New completion, somewhat incomplete ([a0d40e5](https://www.github.com/scop/bash-completion/commit/a0d40e53918a639a1550e4592871c86289badb78)) +* test: Be more consistent with "CI" env var examination and xfails ([0bfa552](https://www.github.com/scop/bash-completion/commit/0bfa5524f9ed318c5fcb44a4c73cdfb055bddc98)) +* unzip, zipinfo: Associate with *.xar (eXist-db application package) (#257) ([c263a3f](https://www.github.com/scop/bash-completion/commit/c263a3fc8ca098cb42eab88026e1ffa2fa809ec0)) +* test: Fix arp CI (non)expectations, remove redundant test case ([a7ece55](https://www.github.com/scop/bash-completion/commit/a7ece5532328f4901fa366f4ee23d9e3f7488674)) +* tcpdump: Various option and their arg completion updates ([e453c40](https://www.github.com/scop/bash-completion/commit/e453c401a9af815ea0c112f854fbca5a4e180d39)) +* doc: Note email issues gateway ([872164a](https://www.github.com/scop/bash-completion/commit/872164adb46a5c106442274d1cb9a56ecf88d723)) +* Travis: Remove unused PYTEST env var ([ff7bba7](https://www.github.com/scop/bash-completion/commit/ff7bba7eab63e32a456a97146145c08449b95ceb)) +* pydocstyle: New completion ([ebee700](https://www.github.com/scop/bash-completion/commit/ebee7008d2119c271f0ff216294b36fe9b2923c3)) +* test: Fix _count_args test_7 to test intended case ([7093e83](https://www.github.com/scop/bash-completion/commit/7093e8301852c0924dd94861e0d7ac47665bc761)) +* _count_args: Add 3rd arg for treating option-like things as args ([3809d95](https://www.github.com/scop/bash-completion/commit/3809d9558f2af6c63b675a1385f008f0ad3af388)) +* chmod: Fix file completion after modes starting with a dash ([75ec298](https://www.github.com/scop/bash-completion/commit/75ec298eaae391258da9418a55d3d47d855e5e9e)) +* .gitignore: Add pytestdebug.log ([3e9011a](https://www.github.com/scop/bash-completion/commit/3e9011aa012ef349d499f8ab96b019fe6b21e09a)) +* sysctl: Treat -f as alias for -p/--load ([76549bb](https://www.github.com/scop/bash-completion/commit/76549bb4e56bb4f968d686da52ca8b1ea46754a1)) +* xrandr: match the output name exactly for --mode ([3556fcb](https://www.github.com/scop/bash-completion/commit/3556fcbf478cbfe1ea631a98267056bb8a460240)) +* chmod: Fix "-" completion ([a269a60](https://www.github.com/scop/bash-completion/commit/a269a603207f5bf7b3a9eb17b8abeeb2159f159e)) +* _xspecs: Simplify bash version check ([ec630f5](https://www.github.com/scop/bash-completion/commit/ec630f50d62eb5599dd5c882da75681b69bf5608)) +* test: Remove some no longer used old test suite code ([a492414](https://www.github.com/scop/bash-completion/commit/a4924148f0c846cb8640fbc45e1a466058a16744)) +* tshark: Support preferences (-o) completion with memoization ([9b4098f](https://www.github.com/scop/bash-completion/commit/9b4098f748302568ff8c014f634fa822e962f029)) +* tshark: fix completion of -Xlua_script option ([50f52f7](https://www.github.com/scop/bash-completion/commit/50f52f77cf5c5339dfe7e1c3ff2991ea4a912c59)) +* test/t: Avoid trailing backslash in Makefile.am's to appease automake ([5c73b79](https://www.github.com/scop/bash-completion/commit/5c73b7948d924d48e84ea67000fdb7b07970f06b)) +* build: Include test/t in dist tarball ([698ef1d](https://www.github.com/scop/bash-completion/commit/698ef1dae56f366c729dd5c46cafc49e9fedb965)) +* test: Clean up and docker-ignore __pycache__ dirs ([a6916d6](https://www.github.com/scop/bash-completion/commit/a6916d682f5ded8e99c7918e27d6105e82cc7591)) +* test: Skip ifup options test if it doesn't grok --help, not in CI ([3780c80](https://www.github.com/scop/bash-completion/commit/3780c802fa6bdc915c4e667c003189c22d0f68bb)) +* test: Mark some xfails based on if in docker instead of in CI ([5af8f75](https://www.github.com/scop/bash-completion/commit/5af8f759b0ab7625e275873321db322c594bd750)) +* inotifywait: New completion ([8bea1ec](https://www.github.com/scop/bash-completion/commit/8bea1ec8f0e8a708bd22be5d7eddcdf37a19fcae)) +* _ip_addresses: Avoid completing ipv4 ones with -6 ([ebeecf8](https://www.github.com/scop/bash-completion/commit/ebeecf872dc0925e34177f862c371ad6e4010f08)) +* test: Convert _ip_addresses unit tests to pytest+pexpect, extend some ([186d47d](https://www.github.com/scop/bash-completion/commit/186d47dff33c8c2deea2c903dcc82f251a3d9bd0)) +* inotifywait: Avoid some false positive event names ([82a50b0](https://www.github.com/scop/bash-completion/commit/82a50b07719860a293c0dd12b53892ed3a86612d)) +* inotifywait: Fix -e completion with BSD sed ([cfa6432](https://www.github.com/scop/bash-completion/commit/cfa6432743b2107e4b7bba0ebe17a1dd8eac7ba7)) +* inotifywatch: New completion, common with inotifywait ([2aa57d1](https://www.github.com/scop/bash-completion/commit/2aa57d13202f15bf057ff5134ee6a56686032211)) +* man: Fix completion when failglob option is enabled (#225) ([b3a25cf](https://www.github.com/scop/bash-completion/commit/b3a25cfe429b8c87d9194c2d9042349ba71979c9)) +* test: Add pre_cmds support for completion fixture ([e56da98](https://www.github.com/scop/bash-completion/commit/e56da98dac7188b72c4df420c82452c438119636)) +* test: Add man failglob test case ([c1dd7f2](https://www.github.com/scop/bash-completion/commit/c1dd7f22995ba8c7c6064e47e2c557abdc2ddf78)) +* test: Rename completion.line to .output ([7d7032b](https://www.github.com/scop/bash-completion/commit/7d7032bfcfcd47f7ed3372c9c7ac95851d8402c0)) +* test: Match Python's default locale unaware sort in bash setup ([c46536a](https://www.github.com/scop/bash-completion/commit/c46536aa6e6e79764075800b5b747fea7e20bc2c)) +* test: Refactor/improve completion results checking ([0d9d375](https://www.github.com/scop/bash-completion/commit/0d9d375fed79651c8cd179df8bef032730506a5d)) +* __parse_options: Avoid non-zero exit status ([5ecb9d7](https://www.github.com/scop/bash-completion/commit/5ecb9d7e1372961f4f983b1fd0adaa273ac06bc4)) +* test: Convert remaining _parse_help unit test to pytest+pexpect ([a2c9da2](https://www.github.com/scop/bash-completion/commit/a2c9da2355e984eea8c9296e707bc77187d12b0d)) +* ifstat: New completion ([50251dc](https://www.github.com/scop/bash-completion/commit/50251dcaa79308c3926e331db944734d9aafa76e)) +* test: Fix test generation wrt results checking improvements ([39ab16a](https://www.github.com/scop/bash-completion/commit/39ab16a9be35c8942b2fa5371ea98ac1acb2a6ca)) +* iperf, iperf3: Add some option arg (non-)completions ([cd2b18a](https://www.github.com/scop/bash-completion/commit/cd2b18a53145f9f4dcca05ee583cc9b221d86f4f)) +* test: Convert remaining man test case to pytest+pexpect ([c10ece5](https://www.github.com/scop/bash-completion/commit/c10ece5f7646bbc7ffeb85943da1b45de85b8772)) +* ifstat: Make work with iproute2 version ([0b44673](https://www.github.com/scop/bash-completion/commit/0b4467343aeaab4d8760943bf26955505814b908)) +* test: Remove unnecessary autouse=True from fixtures ([cfd66c2](https://www.github.com/scop/bash-completion/commit/cfd66c236a19ec40dba7bfbf31cafff9cb537da9)) +* .gitignore: Add .python-version (for pyenv) ([2527706](https://www.github.com/scop/bash-completion/commit/2527706c0dbc65f125529101690087ad128d33ab)) +* test: Clean up man tmp dir ([e13640e](https://www.github.com/scop/bash-completion/commit/e13640eac170580211fed402473effc7f410670d)) +* test: Remove unnecessary ri xfail ([a4dd187](https://www.github.com/scop/bash-completion/commit/a4dd187c52e6270ae3dcc09c48a9f613b234f886)) +* jsonschema: New completion ([15fe639](https://www.github.com/scop/bash-completion/commit/15fe6395eb447a7e66a7aec07be2963c5f6c2131)) +* xfreerdp: Update for more modern xfreerdp ([7499fef](https://www.github.com/scop/bash-completion/commit/7499fefbd487196f78300e58f65138901862c128)) +* adb: Deprecate in favor of one shipped with the Android SDK ([479cc27](https://www.github.com/scop/bash-completion/commit/479cc270c594c3c1655519eba8745933b50d120c)) +* test: Convert remaining tar test cases to pytest+pexpect ([509878d](https://www.github.com/scop/bash-completion/commit/509878dcbc86b3528aac7b15e83203a3f7bfec38)) +* test: Fix declare test case with bash 5.0 ([89a0ed7](https://www.github.com/scop/bash-completion/commit/89a0ed758de066dec353687b6506b512f2901cf8)) +* test: Expect failure for chown all users test as non-root ([78bb3c0](https://www.github.com/scop/bash-completion/commit/78bb3c040f40bd903f7898812b3d2e95c4e7f47e)) +* xm: Deprecate completion for obsolete command (#284) ([c306a41](https://www.github.com/scop/bash-completion/commit/c306a418288d2e6cc94dac0f3f1443385405f3d1)) +* ssh: support RemoteCommand and SyslogFacility options ([8b2f90e](https://www.github.com/scop/bash-completion/commit/8b2f90e2174f8babb139097228d7923ef2ca4e90)) +* test: sort t/Makefile.am EXTRA_DIST in C locale ([17984a2](https://www.github.com/scop/bash-completion/commit/17984a2baa943b2166bc7217212dfa6d57a852d7)) +* test: rewrite "generate" in Python, fix trailing backslash in EXTRA_DIST ([7a9913f](https://www.github.com/scop/bash-completion/commit/7a9913ffa8c1508823ba05f832895d20b6a178a2)) +* xfreerdp: reinstate support for old versions with dash option syntax ([5f4f529](https://www.github.com/scop/bash-completion/commit/5f4f529ed3755a682e999d93f87dc5ac518ab51f)) +* test: remove no longer needed completion/*.exp ([2515f72](https://www.github.com/scop/bash-completion/commit/2515f726bd7195d8c80fdc8442fbd48bffe7398a)) +* test: avoid interrupting magic mark output ([1ea87c9](https://www.github.com/scop/bash-completion/commit/1ea87c99707fdc40c956560220e5a49d9e376383)) +* test: Increase expect pty to 160 columns ([b01cfe1](https://www.github.com/scop/bash-completion/commit/b01cfe1a4fed490ef1705f5c52e3c93e5187da49)) +* pytest: complete pytest-xdist --dist, --numprocesses, and --rsyncdir ([141e5e6](https://www.github.com/scop/bash-completion/commit/141e5e663789aa2243a0aa23c1bbe0b8c620e991)) +* post-commit: trigger on test/requirements.txt too ([51aa5c3](https://www.github.com/scop/bash-completion/commit/51aa5c3588fc22a3fef1313f5ed51cdce1c6a7f9)) +* test: add dependency on pytest-xdist ([eabce5b](https://www.github.com/scop/bash-completion/commit/eabce5b598b98489a831d44ec3e94b29e57926a6)) +* extra: add git pre-push hook for triggering Docker Hub builds ([7ab7a9b](https://www.github.com/scop/bash-completion/commit/7ab7a9bd418134b6c83d57f538dc5674b930e9a3)) +* test: use pytest-xdist ([0087574](https://www.github.com/scop/bash-completion/commit/0087574d5d130529c46d6c6a0b274439df652204)) +* python: make warning action list reusable ([fb0bb60](https://www.github.com/scop/bash-completion/commit/fb0bb6086864835d5bc71dfb1b43636767120267)) +* pytest: complete --pythonwarnings/-W arg ([6fad7d8](https://www.github.com/scop/bash-completion/commit/6fad7d8f411e734004a4f9b893dd32c266ed156f)) +* copyright: add 2019 ([95ae4bb](https://www.github.com/scop/bash-completion/commit/95ae4bbb17bb1ace29c4222fc7841ab69df23237)) +* _longopt: don't complete --no-* with file/dirname arg ([dd80f35](https://www.github.com/scop/bash-completion/commit/dd80f35279afd4f056dc191767b9869c9649d476)) +* nsupdate: new completion ([80ba367](https://www.github.com/scop/bash-completion/commit/80ba367c4e62c63927b2ffe6884ed9756ace5195)) +* _longopt: pick first long option on a line, not last ([54abb2e](https://www.github.com/scop/bash-completion/commit/54abb2e3c495e6732af6546b0fe41e0a5cd6922f)) +* _longopt: simplify regex, use printf instead of echo, drop unnecessary sort ([c1ec2e1](https://www.github.com/scop/bash-completion/commit/c1ec2e1b00913d9dc38e5dcf52bfbea4a2a9eff8)) +* test: add some _longopt unit tests ([6fdb0e2](https://www.github.com/scop/bash-completion/commit/6fdb0e2c3e47125ce29c2de0929d893452c2f595)) +* test: include test_unit_longopt.py in dist ([4a73043](https://www.github.com/scop/bash-completion/commit/4a73043f46be3f939c857f04673a659d8d10b0ac)) +* modprobe: append = to module parameter completions ([12d589e](https://www.github.com/scop/bash-completion/commit/12d589e705ccf8a44d4ce158c1c1c9885dce71ee)) +* dnssec-keygen: new completion ([6e008e2](https://www.github.com/scop/bash-completion/commit/6e008e200b700a303059a8c9658d3bcc79c11f98)) +* shellcheck: new completion ([fd37d6f](https://www.github.com/scop/bash-completion/commit/fd37d6f506013a42d35841b88d19851f192cf4ad)) +* ulimit: new completion ([2bf12d7](https://www.github.com/scop/bash-completion/commit/2bf12d7efb2ab73f5948d3c7868ff4c0273a71de)) +* ulimit: improvements when -a is specified ([6bc7bba](https://www.github.com/scop/bash-completion/commit/6bc7bba0315d64b1285861ad16a3f708d5437926)) +* ping, tracepath: parse options primarily with _parse_help ([09fa92d](https://www.github.com/scop/bash-completion/commit/09fa92d75e7b542c5ae601ba1fbd9c0155dbb66e)) +* modprobe: module parameter boolean values ([83b4b21](https://www.github.com/scop/bash-completion/commit/83b4b21d4075a88bd8e615b7e2da91520bd0a028)) +* bzip2: recognize *.tbz2 as bzipped ([c3e5447](https://www.github.com/scop/bash-completion/commit/c3e54476693dabecc1c8d52150001739d1404412)) +* : remove spaces immediately within $() ([90e380b](https://www.github.com/scop/bash-completion/commit/90e380b935afefbe63e4b68e4448a1bbb701696a)) +* : remove whitespace after redirections ([689beea](https://www.github.com/scop/bash-completion/commit/689beea52bd43bb45d96645f965e211351fbe579)) +* msynctool: code cleanups ([0fddd55](https://www.github.com/scop/bash-completion/commit/0fddd5512587cf717a9eb39ba422a80f8f7000e8)) +* : spelling fixes ([2a93236](https://www.github.com/scop/bash-completion/commit/2a932367917a9d7349bf049257e10840caa9c4da)) +* svn, svk, wget: use _iconv_charsets ([63257ba](https://www.github.com/scop/bash-completion/commit/63257ba4f8466fad3e4e219259554a0e8627def8)) +* : make _parse_usage fallbacks more concise ([3c10d4d](https://www.github.com/scop/bash-completion/commit/3c10d4d88015e096a0ee840d6a008508607cb81b)) +* valgrind: look up tools from libexec dirs too ([662cb72](https://www.github.com/scop/bash-completion/commit/662cb7267515ee6b26de9bea833a570a2df80be2)) +* .dir-locals.el: use flycheck-sh-bash-args ([77f2855](https://www.github.com/scop/bash-completion/commit/77f2855e10f08e9789908d7a91d42c407b67ea32)) +* : format Python code with black ([2c1a531](https://www.github.com/scop/bash-completion/commit/2c1a53114896d2f7b8bff075fd16fb811f17b311)) +* : format Perl code with perltidy ([ee73bf7](https://www.github.com/scop/bash-completion/commit/ee73bf7dce346d2ab20bd76d060c2906553c7792)) +* test: check for perltidy errors and warnings ([9be5de1](https://www.github.com/scop/bash-completion/commit/9be5de1e2ef3c9186c9cb317c12198073b50ed44)) +* test/tools: run all tools, don't stop at first failure ([4ebda77](https://www.github.com/scop/bash-completion/commit/4ebda77e88fce26e7e88abe035a6daae33a6c72a)) +* : arithmetic expression related cleanups ([834339f](https://www.github.com/scop/bash-completion/commit/834339fafabf9cab22c7708ca3c964e3fa8b769b)) +* test/tools: fix exit status incrementation ([9f4a18f](https://www.github.com/scop/bash-completion/commit/9f4a18fa20944d2cd2f30e196ddc9495c28566ac)) +* gdb: relax core filename pattern ([c59a2d0](https://www.github.com/scop/bash-completion/commit/c59a2d0950cb5b20da46598889f31bc17ac3658c)) +* _parse_help: look for long options somewhat more eagerly ([3f88944](https://www.github.com/scop/bash-completion/commit/3f88944e550b082984c71175e7a09a5f7801285e)) +* test: add some gdb non-core files ([6fa7458](https://www.github.com/scop/bash-completion/commit/6fa745848937b9714ca58cd0675d44c0f0145ea8)) +* test: port some more ssh test case to pytest+pexpect ([d2bec62](https://www.github.com/scop/bash-completion/commit/d2bec62f609e4ce4117ba74d5a81a45ad8e23369)) +* ssh: don't offer protocol v1 specific options if it's not supported ([aba5560](https://www.github.com/scop/bash-completion/commit/aba556019b7707e24093cc1c1ae082bec743ba3e)) +* : whitespace tweaks ([2f71b27](https://www.github.com/scop/bash-completion/commit/2f71b27557b196888971f2ada06f71f238939f00)) +* various: apply file vs dir special cases also when invoked with full path ([82ffbb2](https://www.github.com/scop/bash-completion/commit/82ffbb2d157bc401c0838fe98146fa89ecf8c56b)) +* phing: don't complete -l with files ([a8c4417](https://www.github.com/scop/bash-completion/commit/a8c4417ae5931fb9b172e3ff85d18e81061da8a3)) +* phing: fix getting just a tab for options on CentOS 6 ([e41f07e](https://www.github.com/scop/bash-completion/commit/e41f07e0be7aa22d19ad9f877ffe7ea5d1c99ce6)) +* : add missing "ex: filetype=sh" ([f237c25](https://www.github.com/scop/bash-completion/commit/f237c25fdf55ee1ce7076e2265ab5f80255efaaf)) +* _upvar: delete, unused ([b1a8a7d](https://www.github.com/scop/bash-completion/commit/b1a8a7d1c318d6fb2ffc5f050c887defa47ff77e)) +* Revert "_upvar: delete, unused" ([6970e6d](https://www.github.com/scop/bash-completion/commit/6970e6d62cf6ec1f6c79119843ad495b55f0d6de)) +* _upvar: deprecate in favor of _upvars ([4f35b0c](https://www.github.com/scop/bash-completion/commit/4f35b0cd7f6240addb68aa3127abe2a6dcc31411)) +* : error output consistency, use bash_completion prefix ([2a04042](https://www.github.com/scop/bash-completion/commit/2a04042d530ed5dd1b746073f8ffc059c42f3fa2)) +* : more arithmetic expression consistency ([c8c1b4d](https://www.github.com/scop/bash-completion/commit/c8c1b4da2f11f03db9665ca974fbe3d616b471b4)) +* tshark: ignore stderr when parsing -G, -L, and -h output ([7abc83e](https://www.github.com/scop/bash-completion/commit/7abc83ee03fbe61d82b568479a5c50ad543a09c5)) +* test: improve tshark -O arg completion test ([4548e71](https://www.github.com/scop/bash-completion/commit/4548e71e90bf591e537eaed2e7890fb85650cb2b)) +* tshark: speed up tshark -O completion ([b930bfc](https://www.github.com/scop/bash-completion/commit/b930bfc75af6229d456c58282e8bf80e04cfca5a)) +* apt-cache: protect showsrc against regex specials ([6e2ddea](https://www.github.com/scop/bash-completion/commit/6e2ddea986a3462070e6eafb098fc3d3f16bd835)) +* test: adjust _get_comp_words_by_ref test to changed error output ([56703df](https://www.github.com/scop/bash-completion/commit/56703df67ddfaeccb0cc2fd7f529c63527f031a0)) +* synclient: remove unused local variable "split" ([366488f](https://www.github.com/scop/bash-completion/commit/366488f2e3a806490eb1d7d6bcf674a8ea771f90)) +* mypy, mysql, xmms: don't complete unknown split long option args ([1a698d5](https://www.github.com/scop/bash-completion/commit/1a698d526c5b6747c9b40f23c1d91db421c9846b)) +* apt-get: protect source against regex specials ([22c5c3c](https://www.github.com/scop/bash-completion/commit/22c5c3c286575bd782f956e16abe4522474ae75a)) +* AUTHORS: remove unrelated project association from my entry ([8a74451](https://www.github.com/scop/bash-completion/commit/8a74451ec83af0741fff9d17003a13012fd1a00d)) +* test: shorten long gdb test core file name so tar doesn't croak on it ([e83bf9b](https://www.github.com/scop/bash-completion/commit/e83bf9b0a4e76d2ad361884a3c65eefbd685403f)) +* iptables: improve existing table arg parsing ([97a91f8](https://www.github.com/scop/bash-completion/commit/97a91f8993f45823c21fbc309c00915a0c1572e8)) +* test: add script to run shellcheck, run it in Travis, allowing failure for now ([f21c67f](https://www.github.com/scop/bash-completion/commit/f21c67f17fcc909745d59e3647398c50b2cd8eb9)) +* ebtables: improve existing table arg parsing ([996a203](https://www.github.com/scop/bash-completion/commit/996a203f07a075633baed3960763f34534ea2447)) +* test: add invoke-rc.d test case for not repeating already given options ([e0bb03a](https://www.github.com/scop/bash-completion/commit/e0bb03a588ba57a77424a19f690c1413b3de8086)) +* _included_ssh_config_files: doc grammar fixes ([bae4a3d](https://www.github.com/scop/bash-completion/commit/bae4a3d11ecb86767573c9b03aed85287a8c415a)) +* _included_ssh_config_files: store found included files in an array ([6d01267](https://www.github.com/scop/bash-completion/commit/6d012674ee28fd25f9bfa64b6409d7eb99844b61)) +* : shellcheck error fixes ([f1c32f4](https://www.github.com/scop/bash-completion/commit/f1c32f4b85227a4da5dbb6fc137a7703a4efe20a)) +* test: add make -C test case ([ea3c900](https://www.github.com/scop/bash-completion/commit/ea3c9001f42f31d49a13962586b71469aa416a4d)) +* make: quote eval array definitions to work around shellcheck SC1036 bug ([abe266c](https://www.github.com/scop/bash-completion/commit/abe266ce4d26c37cf8ad681136cc8fd7edd28d4e)) +* ri: shellcheck error fixes ([d45f9fa](https://www.github.com/scop/bash-completion/commit/d45f9faf432947ecf0e178d8be50f4c3163c2b4c)) +* travis: fail on shellcheck errors ([e146ef5](https://www.github.com/scop/bash-completion/commit/e146ef59c53ce311fb1f30f06499aa3c91ffb3f1)) +* travis: don't fail DIST != tools ([a3129ac](https://www.github.com/scop/bash-completion/commit/a3129ac624adf390b072f63f98c6f8be552b0415)) +* travis: run shellcheck on bash_completion.sh.in too ([0eebaef](https://www.github.com/scop/bash-completion/commit/0eebaef0a4296bf0c37c8fcdd0931701b25abb88)) +* tar, valgrind: avoid some herestrings ([3d3905c](https://www.github.com/scop/bash-completion/commit/3d3905cbb8232091c3b656567a843b97b8bc6e11)) +* test: make runLint search for herestrings ([8510da8](https://www.github.com/scop/bash-completion/commit/8510da8fb20658fbb18f3f0744214ddfc473f542)) +* test: move default shell option from run-shellcheck to .shellcheckrc ([4dc8da5](https://www.github.com/scop/bash-completion/commit/4dc8da5db79dd7d79312cdd139ab0422eb6fb532)) +* shellcheck: disable bunch of warnings when in "-S warning" mode ([a36f57f](https://www.github.com/scop/bash-completion/commit/a36f57f922d461558064be39f8cfb64288f64cbf)) +* arp, ccze, ifstat, inotifywait, makepkg: invoke sed with "command" ([5ff11ce](https://www.github.com/scop/bash-completion/commit/5ff11ced5729f9258b75b633fc366360b277cf4c)) +* __parse_options, 7z: avoid herestrings ([ff5fb58](https://www.github.com/scop/bash-completion/commit/ff5fb5864dc41629f216dbea0a1fbf892ded4e66)) +* CONTRIBUTING: note runLint and run-shellcheck ([07408a6](https://www.github.com/scop/bash-completion/commit/07408a6b3974c442f35dedf46ef49292b8664166)) +* CONTRIBUTING: add upstream vs bash-completion considerations ([34fb914](https://www.github.com/scop/bash-completion/commit/34fb91447ff9a92e8976732f042ba20cfa615326)) +* doc/testing: remove lots of legacy info, add some new ([d31f2c9](https://www.github.com/scop/bash-completion/commit/d31f2c9adbcab984754ecd93b44778e1e7a673d8)) +* xvnc4viewer: code cleanups ([3e193ed](https://www.github.com/scop/bash-completion/commit/3e193edea316461c2bf5d799ca90cce9c056e301)) +* ssh: fix suboption completion with combined -*o ([8d2c976](https://www.github.com/scop/bash-completion/commit/8d2c976c11e379f28430f1ae15be3764755dcffb)) +* ssh: make option completion case insensitive ([0984db6](https://www.github.com/scop/bash-completion/commit/0984db6747e3f3ef1e73cdadc4447b6cb091cc83)) +* ssh: make -o protocol completion less hardcoded ([73d8304](https://www.github.com/scop/bash-completion/commit/73d830445339df51eba37129c0151a250d290d84)) +* 7z: add some TODO notes on parsing "i" output for extensions ([7748282](https://www.github.com/scop/bash-completion/commit/7748282e1bff081b0507b09146cbbafab3c8cb1a)) +* : avoid shellcheck SC1010 ([a3aa845](https://www.github.com/scop/bash-completion/commit/a3aa84519e338d246925bf816b12f96224ba47ad)) +* : avoid shellcheck SC1007 ([659805b](https://www.github.com/scop/bash-completion/commit/659805bd2a834d2e58075b1807083eef54aa73fb)) +* dist: include various *.in explicitly ([f2f8c7b](https://www.github.com/scop/bash-completion/commit/f2f8c7b3c69039c0f1fe09e33c85c1075bdd409c)) +* test: use parallel make in docker test ([8efece6](https://www.github.com/scop/bash-completion/commit/8efece6123393c07c127375c9f754407d7702a20)) +* test: use $(RM) ([72b47aa](https://www.github.com/scop/bash-completion/commit/72b47aacefae825b670a1892665b74a6b690194e)) +* test: group dejagnu related stuff in one place in Makefile ([ce95fe4](https://www.github.com/scop/bash-completion/commit/ce95fe40fd88a2c425aece0b69544cc989da0b3e)) +* test: run pytest tests with make check ([5a53bc1](https://www.github.com/scop/bash-completion/commit/5a53bc1c24c672f774fde210c8bdd2f26992a58b)) +* test: run distcheck in docker, ditto test suite driven by it ([bdf40aa](https://www.github.com/scop/bash-completion/commit/bdf40aab2528d0c32a7fad97d3a1156b042ff81c)) +* test: add fixtures/make/extra_makefile to CLEANFILES ([47fc6d7](https://www.github.com/scop/bash-completion/commit/47fc6d7c217326aed607e21c8525084f3f0f6118)) +* travis: reindent with 2 spaces by usual convention ([54030ad](https://www.github.com/scop/bash-completion/commit/54030ad7738689d0709648e48d0177a1c9d00014)) +* travis: deploy release dist tarball to github ([8d91ee2](https://www.github.com/scop/bash-completion/commit/8d91ee269e4086cc1d3550865b3f9533796717b3)) + +## 2.8 (2018-03-17) + +* test suite: Limit number of screen -T completion matches ([1c5d13e](https://www.github.com/scop/bash-completion/commit/1c5d13ee8c60cc2ef22751d9e876296be731d749)) +* test suite: Support overriding default match buffer size (#141) ([e6a56b9](https://www.github.com/scop/bash-completion/commit/e6a56b97e05d5df29f61b0e23650a65f1492f1fb)) +* lftp: Support ~/.local/... bookmark location (#144) ([1e347ee](https://www.github.com/scop/bash-completion/commit/1e347eef6a9de89855aba8a8b92f25be1fe18c17)) +* test suite: Limit amount of output from process name completion ([f206607](https://www.github.com/scop/bash-completion/commit/f206607cbde36b46473a11cce9b3ebfd75ec36f4)) +* ktutil: Don't leak i and command environment variables ([fb8e5aa](https://www.github.com/scop/bash-completion/commit/fb8e5aa106463cf0ef3a5920010d4805ae22e985)) +* test suite: Add bunch of missing basic test cases ([ca61c5e](https://www.github.com/scop/bash-completion/commit/ca61c5e60eb422fd90ef940fec3aceba4a6a5dff)) +* uscan: Don't leak cword and words environment variables ([0ab85ec](https://www.github.com/scop/bash-completion/commit/0ab85ec0a4177bee07253eacac1faa072ff64ff9)) +* xm: Don't leak args and commands environment variables ([29fd200](https://www.github.com/scop/bash-completion/commit/29fd2001928af49898184b9ada988f63f924a097)) +* test suite: Enable wine in ubuntu14 ([9ccc3db](https://www.github.com/scop/bash-completion/commit/9ccc3db8834168b7af65e76ef320dda01b38046e)) +* test suite: Install aptitude in ubuntu14 container ([1fc5d30](https://www.github.com/scop/bash-completion/commit/1fc5d3022333fa08d3fbb5bc4995cf5acbaf7e7b)) +* aptitude-curses: Use aptitude completion ([c8d40ea](https://www.github.com/scop/bash-completion/commit/c8d40eab48735c0ef601b2a227d42594b7511e24)) +* groupdel: Parse and handle long options ([e987744](https://www.github.com/scop/bash-completion/commit/e987744d342812185d675ea428a197de7394051b)) +* curl: Fix -x etc option argument hostname completion ([3708590](https://www.github.com/scop/bash-completion/commit/3708590603920a6e67be0df3f22924e4ea236fc9)) +* : Protect _known_hosts_real from user input treated as options ([8706bc1](https://www.github.com/scop/bash-completion/commit/8706bc1d70873698d0d456254f415322343f6b03)) +* aptitude: Add keep to commands list (Debian: #867587) ([5ed2fc4](https://www.github.com/scop/bash-completion/commit/5ed2fc4a9a604c780da48e87964d4ac21fc7a85d)) +* test suite: Add basic hid2hci and munin-node-configure test cases ([c498655](https://www.github.com/scop/bash-completion/commit/c4986556555f5a6f45761ad2fdc3a1a2623f5b76)) +* test suite: Add info and pinfo option test cases ([deba602](https://www.github.com/scop/bash-completion/commit/deba602bec10e4dda56ebe2908404e13ebd1286d)) +* test suite: Limit amount of info and pinfo test output ([bb8645b](https://www.github.com/scop/bash-completion/commit/bb8645b5ff71e532de2bc9678f6e77d7009b0b37)) +* : Protect shopt reset from non-default $IFS ([5240618](https://www.github.com/scop/bash-completion/commit/5240618033fecc3032a421d39c2eaeb2e4c20d57)) +* alias: Fix completion followed by = (#146) ([2f21940](https://www.github.com/scop/bash-completion/commit/2f2194011db46beaa4e9eb44705bc6a8a08c56ab)) +* oggdec: New completion ([0dc16d3](https://www.github.com/scop/bash-completion/commit/0dc16d38076cdea90a00d7e346ab545e88abf1d5)) +* Add support for .lzo extension (--lzop) to tar (#155) ([49a8dd8](https://www.github.com/scop/bash-completion/commit/49a8dd857628807460468db92a38233c50c83196)) +* Add support for .lz4 extension to file-roller (#158) ([5268e43](https://www.github.com/scop/bash-completion/commit/5268e43824773ccaf6c3cd48d1d4a5185a6a11d0)) +* lsusb: New completion ([4e323d9](https://www.github.com/scop/bash-completion/commit/4e323d9a71e9bbd1c4432c3ade3794073a88d3d7)) +* lspci: New completion ([ea3d2b2](https://www.github.com/scop/bash-completion/commit/ea3d2b249413aeda28b51e7eaf545be243c0684a)) +* test suite: Skip fedoradev GPG checks at least for now ([2ef9387](https://www.github.com/scop/bash-completion/commit/2ef9387bc4628e4c5203a63f14b66d5765763589)) +* test suite: Drop no longer needed fedoradev /usr/bin/which workaround ([53feba3](https://www.github.com/scop/bash-completion/commit/53feba31e9b49340605304258e18ff06baacaa22)) +* vpnc: Improve config completions ([c695083](https://www.github.com/scop/bash-completion/commit/c695083125fb6ce4f944039fc94745a1a33d30cf)) +* vpnc: Add some option argument (non)completions ([0086850](https://www.github.com/scop/bash-completion/commit/0086850c28c41cb383249ba47d44edb8b3ec3b53)) +* iptables: Parse options from --help output ([0bdc11d](https://www.github.com/scop/bash-completion/commit/0bdc11d8c9838abf055fc7403fa9739eb5d29820)) +* iptables: Avoid stderr trashing when invoked as non-root ([c8c61f7](https://www.github.com/scop/bash-completion/commit/c8c61f70f9f2cee5b9f7f6276a52af1424dbc380)) +* iptables: Use invoked command instead of hardcoded "iptables" ([1b5c6e8](https://www.github.com/scop/bash-completion/commit/1b5c6e87e4517326c778dd67ba174828f2f40697)) +* README.md: Whitespace cleanup ([a6e3655](https://www.github.com/scop/bash-completion/commit/a6e3655747120aa1782a17b414ffc2e6f80c8b64)) +* ebtables: new completion (#150) ([334b47c](https://www.github.com/scop/bash-completion/commit/334b47cf663c5d7c8f197970a340e745f47cd55f)) +* test: Use prebuilt docker hub bash-completion images ([ecaec9a](https://www.github.com/scop/bash-completion/commit/ecaec9a86470c6d6299a6522c0fddde44ff0b5f6)) +* rfkill: Rename to _rfkill to avoid conflict with util-linux >= 2.31 ([d962f3a](https://www.github.com/scop/bash-completion/commit/d962f3a3be2b5c3811e546890c99b19694c2a08e)) +* test suite: man cleanup ([c8ff683](https://www.github.com/scop/bash-completion/commit/c8ff6833a9f113d9feb29f750ae638436f64cbf3)) +* test suite: Make man test subject names less generic ([78f4cec](https://www.github.com/scop/bash-completion/commit/78f4cec642381e7bfe25c22c8c7fde15775431e7)) +* test suite: Add bunch of man and MANPATH test cases ([3b2fd04](https://www.github.com/scop/bash-completion/commit/3b2fd04caa12b720d941d27b751e76a32af8290e)) +* man: Don't use $MANPATH directly (#161) ([e6a4715](https://www.github.com/scop/bash-completion/commit/e6a471511dfdc230ff3eed65ccba09b6d7d30262)) +* unzip, zipinfo: Associate *.gar (#165) ([e5ee408](https://www.github.com/scop/bash-completion/commit/e5ee408a5aee2f1c9d898150e256540d020fc5ee)) +* pylint: Install for pylint-2 and pylint-3 too ([fee4f3d](https://www.github.com/scop/bash-completion/commit/fee4f3d6c97c4cc48650533d96c16faa71171b39)) +* pylint: Invoke python3 to search for modules if command contains 3 ([d63b33d](https://www.github.com/scop/bash-completion/commit/d63b33d415bf3103daa2aaeead9860084da0d8f3)) +* tox: New completion (#163) ([89fb872](https://www.github.com/scop/bash-completion/commit/89fb872bcf9b6cc508a8079a7d203d31a2694620)) +* tox: Avoid stderr spewage when -e invoked without tox.ini ([1ac8895](https://www.github.com/scop/bash-completion/commit/1ac88953a8a81d7509648ebe9f8751319bca3609)) +* tox: Include ALL in -e completions ([9678f55](https://www.github.com/scop/bash-completion/commit/9678f55dabe921b62dd848bfa38b4d1ffffc21ca)) +* tox: Remove spurious executable bits ([609ed0d](https://www.github.com/scop/bash-completion/commit/609ed0de65732f9442a9c17d12ba88c0ba855cef)) +* xdg-settings: New completion ([6cf792b](https://www.github.com/scop/bash-completion/commit/6cf792bf3dffcafdfb5765bd0b300e3c10ace9e2)) +* test: run bash with --norc to avoid system bashrc ([77ea9fc](https://www.github.com/scop/bash-completion/commit/77ea9fc444db7d240cffc2cbf1b38f0b12075aed)) +* test: Add some comments regarding bash init in library.exp ([215301d](https://www.github.com/scop/bash-completion/commit/215301dfb869b803b1dbada879d8e37ca6641e41)) +* test: Remove things moved to library.exp from bashrc ([6495d88](https://www.github.com/scop/bash-completion/commit/6495d886d8e86ef8f54cc0aacbd08838482e6d58)) +* Whitespace ([3fa189e](https://www.github.com/scop/bash-completion/commit/3fa189ee0b4be4da9aa8c9ac34ddead27e74f861)) +* test: Add files to test older ri with ([a85f96c](https://www.github.com/scop/bash-completion/commit/a85f96c75dc81ee1e5a24433ac7741d414a77c0b)) +* ri: Fix integrated ri 1.8 class completion ([9035568](https://www.github.com/scop/bash-completion/commit/903556864dc366c55ce2904821ef31a4920babb4)) +* apt-get: Complete *.deb on install if argument contains a slash ([a36231e](https://www.github.com/scop/bash-completion/commit/a36231e81eaeb272777abe581dce06e988f219a3)) +* reportbug: Add -A/--attach arg completion ([339abbb](https://www.github.com/scop/bash-completion/commit/339abbbaa07c824a278fc1e836e25b335b314676)) +* reportbug: Don't hardcode option lists, split option args at = ([1d44276](https://www.github.com/scop/bash-completion/commit/1d4427621185a6f005232c6d769109dadd46f795)) +* ssh-keygen: Add -E arg completion ([3807a99](https://www.github.com/scop/bash-completion/commit/3807a996dbf8f4a94c4cb1be5861c0f228584225)) +* xdg-mime: New completion ([24e7c26](https://www.github.com/scop/bash-completion/commit/24e7c266748b575358f978a73b0b5ff02a5868ed)) +* test: dpkg,ls,_tilde: Skip gracefully if no uniq user for completion is found ([95a04fe](https://www.github.com/scop/bash-completion/commit/95a04feab494e55c14de866e02a8a8bfbae398ec)) +* test: Ignore duplicates in find_unique_completion_pair list ([d2f14a7](https://www.github.com/scop/bash-completion/commit/d2f14a7b7504d05d9cbdd048cf546fb55fbbfbd8)) +* ssh: Declare $prefix closer to use ([2516a25](https://www.github.com/scop/bash-completion/commit/2516a257081be11b49a3755358d1ca39463b7162)) +* ssh: Add -J/ProxyJump completion ([cc6667e](https://www.github.com/scop/bash-completion/commit/cc6667e293c670b04b0d827d16935681b9de7083)) +* _known_hosts_real: Document -a better ([693282c](https://www.github.com/scop/bash-completion/commit/693282caaa206676fc4d1d17713877d630b07d65)) +* nproc: New completion ([cb7877c](https://www.github.com/scop/bash-completion/commit/cb7877caa89184e28ae7b6b58d1d1c42abdeb9d1)) +* getconf: New completion ([55ed68d](https://www.github.com/scop/bash-completion/commit/55ed68dab30d66dce7be89e6e4a8fc846cbe4044)) +* pv: New completion ([f6f5f4f](https://www.github.com/scop/bash-completion/commit/f6f5f4f1fe8e225e06ca5174e6e36899a7baf81c)) +* cryptsetup: Update option lists ([89d1a3f](https://www.github.com/scop/bash-completion/commit/89d1a3fe4a0e0e977244c43be399cb13890bff45)) +* dpkg: Add -V/--verify arg completion ([bb0a82f](https://www.github.com/scop/bash-completion/commit/bb0a82f3dc5d60561362c8259eb9a4bbdac701bd)) +* lowriter,localc etc: Use corresponding oo* completions ([fbd52a5](https://www.github.com/scop/bash-completion/commit/fbd52a5e31747beb4974da97b9d3ed4f6ceb7a61)) +* perltidy: New completion ([9cddfdf](https://www.github.com/scop/bash-completion/commit/9cddfdf1b777e028a9dbf32b442a3ce2629d20cf)) +* flake8: Various option arg completion improvements ([15389e6](https://www.github.com/scop/bash-completion/commit/15389e66c92d61a4a1de593dd4017d76d7e2a0ef)) +* pycodestyle: New completion ([0de48aa](https://www.github.com/scop/bash-completion/commit/0de48aa77f2b84ed409d983279f8b1334242de2f)) +* travis: Don't build local docker images, use vskytta/bash-completion ones ([f1a1e14](https://www.github.com/scop/bash-completion/commit/f1a1e14092db8613d0274a37073f078c1689a94e)) +* test: Work around broken centos/fedora postfix config in non-IPv6 setup ([5db0365](https://www.github.com/scop/bash-completion/commit/5db036505cb9d50651b4e5035e040435256dfffc)) +* test: Add "postconf -" test case ([ac73726](https://www.github.com/scop/bash-completion/commit/ac73726de7421a4a61ba46a2c30795c9080dc24a)) +* Revert "travis: Don't build local docker images, use vskytta/bash-completion ones" ([ac9c468](https://www.github.com/scop/bash-completion/commit/ac9c468c9375289effa39741c048c6aa154164e1)) +* test: Try to skip postconf variable test on broken postfix configs altogether ([4ba2e73](https://www.github.com/scop/bash-completion/commit/4ba2e73104a323143a8060ef4e1e5098a183e445)) +* test/docker: Tweak work dir, add bash as default cmd ([e0a4385](https://www.github.com/scop/bash-completion/commit/e0a438549221ed4e8be0b6e5487bc5f62c2479ca)) +* python: Support completing dotted module hierarchies ([db9f81b](https://www.github.com/scop/bash-completion/commit/db9f81be1673d432afeb85fce8a35e93d9e48643)) +* lsscsi: New completion ([079b7ac](https://www.github.com/scop/bash-completion/commit/079b7ac19124e1d59db176465d7b7ca65884f7d1)) +* radvdump: New completion ([5b3e79e](https://www.github.com/scop/bash-completion/commit/5b3e79e25df9c6d50eb23d465008a71bbac7dbfd)) +* java: Complete *.war ([c1912bf](https://www.github.com/scop/bash-completion/commit/c1912bfd080d4eadba8bc81754ba7b2723115d78)) +* ssh,ssh-add,ssh-keygen: Complete pkcs11 options with *.so ([0fb4ae2](https://www.github.com/scop/bash-completion/commit/0fb4ae2fea44b857f854af8b02c838fbbb1700aa)) +* kldunload: Show modules with digits ([6f17a85](https://www.github.com/scop/bash-completion/commit/6f17a85fad28c0770bb4fe704c2ed5e92e242029)) +* kldunload: Increase robustness of compgen filters (#185) ([e2193c7](https://www.github.com/scop/bash-completion/commit/e2193c771a4b3284fc0e50593902d9edbf60d8c1)) +* _known_hosts_real: Add option to filter IPv4 and IPv6 addresses ([0c40185](https://www.github.com/scop/bash-completion/commit/0c40185fcf70ba6f7dfddbc3933bcab22a339c46)) +* ping*,ssh,scp,sftp,tracepath6: Filter IPv4/IPv6 literal addresses ([b547f22](https://www.github.com/scop/bash-completion/commit/b547f2231a1d6c588bf425e5cd1f0bb6012fc562)) +* geoiplookup: New completion ([7c7dfe8](https://www.github.com/scop/bash-completion/commit/7c7dfe8b1c4b98cea0b7b4fc254207f16651eb87)) +* xdg-mime,xdg-settings: Fix inclusion in tarball ([3e9e03b](https://www.github.com/scop/bash-completion/commit/3e9e03ba3494668cbe663f36231445e15c2f005f)) +* tox: Complete comma separated -e arguments ([eb8a7e7](https://www.github.com/scop/bash-completion/commit/eb8a7e760088cc0fc15f9f1310092e6ac85738f2)) +* mplayer: Disable user config when parsing options ([df36cae](https://www.github.com/scop/bash-completion/commit/df36cae3f85fbf2c386560f4e2da62bb7a67196b)) +* test suite: Some more mplayer and mencoder coverage ([c71f5fc](https://www.github.com/scop/bash-completion/commit/c71f5fcf25ef321074a9f0b215784b0e28c37058)) +* : Comma separated opt arg completion improvements ([021058b](https://www.github.com/scop/bash-completion/commit/021058b38ad7279c33ffbaa36d73041d607385ba)) +* xine etc, ogg123, mplayer -audiofile: Associate with *.oga ([b102367](https://www.github.com/scop/bash-completion/commit/b10236717bae7e1a072031fa9cbf0006b66b4057)) +* dpkg: Fix man page section in comment ([e16b320](https://www.github.com/scop/bash-completion/commit/e16b320ae1eb898f45f7eb891d036c059a2c0040)) +* dpkg: Complete --vextract on deb files ([facefd6](https://www.github.com/scop/bash-completion/commit/facefd6dd0ea0aab8005c8a42ef125e594ed637d)) +* dpkg-query: Fix -W/--show completion ([78cdbe1](https://www.github.com/scop/bash-completion/commit/78cdbe1bb8f7ab597a020a1c606154ccd4e39eea)) +* ccze: New completion ([e858751](https://www.github.com/scop/bash-completion/commit/e858751feb53ca76b48bc9cbd1e4021044c0c34d)) +* make: Pass script to sed as parameter instead of using process substitution ([153d6d4](https://www.github.com/scop/bash-completion/commit/153d6d4fab1faafbd33fccb0ba8a99964f05a95b)) +* openssl: Add completion for the genpkey, pkey, pkeyparam, and pkeyutl commands ([19759ad](https://www.github.com/scop/bash-completion/commit/19759ad14d825896997f70fb37a9f34b98a28903)) +* _avaiable_interfaces: Get rid of eval ([edb7d59](https://www.github.com/scop/bash-completion/commit/edb7d599242a184769a3aed2a7167c354cab6033)) +* __load_completion: Code cleanup ([5e69954](https://www.github.com/scop/bash-completion/commit/5e69954bd1dd6e346d1cb1e44a6d5b03d2c106fb)) +* __load_completion: Load "xspec" completions dynamically too ([e6781be](https://www.github.com/scop/bash-completion/commit/e6781bebfff6da5e3b5ce244c103e35d06dee9c6)) +* mkdir: Complete on files in addition to dirs ([dbb3870](https://www.github.com/scop/bash-completion/commit/dbb38708e39bc8cb463ccaab294b5d1ae1e173f6)) +* mkdir: Complete files without appending space ([b0babf8](https://www.github.com/scop/bash-completion/commit/b0babf873b21eb2f1d936e6e2288b451c1a58778)) +* Bump copyright years to -2018 ([e306ffd](https://www.github.com/scop/bash-completion/commit/e306ffda0e8e9eb38ea676f7d0916d68d0cb87f3)) +* __expand_tilde_by_ref: Eval tilde expansion only, simplify ([21f410a](https://www.github.com/scop/bash-completion/commit/21f410a860c20ab79a9afebcf8a0ca8f7fba9d08)) +* dd: Omit space only when offering one completion ending with = ([cea7cce](https://www.github.com/scop/bash-completion/commit/cea7cce326235531fa36c2e10a2b907b266186a2)) +* dd, find, gcc: Remove unnecessary tilde expansion ([6927248](https://www.github.com/scop/bash-completion/commit/692724843c93fdbf4f253f26c62ad1a9334f73f1)) +* test: Add assert_complete_homedir, use in dpkg and ls ([ec85ac4](https://www.github.com/scop/bash-completion/commit/ec85ac48e3a38360c86d89abb8fe6ed7ea2568fc)) +* bzip2, gzip, and other compressors: Use _tilde instead of _expand ([3c4fc36](https://www.github.com/scop/bash-completion/commit/3c4fc36fd65f414960b5ad1c17bb88f720bca20b)) +* test: Add some _expand unit tests ([3b8dfd3](https://www.github.com/scop/bash-completion/commit/3b8dfd34709d621d928a61fb04a811a96fb15c03)) +* _expand: Reuse __expand_tilde_by_ref and _tilde logic, clean up ([6365265](https://www.github.com/scop/bash-completion/commit/63652650a4f43938e2b7195084ad03cf4e93ff36)) +* info, man, rsync: Defer _expand invocation ([add4e3c](https://www.github.com/scop/bash-completion/commit/add4e3cd443da011e8302b5d1fcfb5673d850f7a)) +* test/unit: Whitespace tweaks ([69c318a](https://www.github.com/scop/bash-completion/commit/69c318a339901699b430af699145a8ff62394894)) +* test: Fix getting username in non-login shells ([6ae330f](https://www.github.com/scop/bash-completion/commit/6ae330f1ab90f15d97477a8c254dd29f166ecdb6)) +* make-changelog.py: Use python3 ([5f1d238](https://www.github.com/scop/bash-completion/commit/5f1d2381a54dc236b0419e78f1a733f2d033ed93)) + +## 2.7 (2017-07-01) + +* pdfunite: New *.pdf completion ([65239a9](https://www.github.com/scop/bash-completion/commit/65239a91a4fface3f1b183b17c79548916461077)) +* test suite: Fix __expand_tilde_by_ref test expectation output ([ff2afaf](https://www.github.com/scop/bash-completion/commit/ff2afaf4f8a89411b65e0f035509db1b6372e292)) +* Makefile: update default compatdir (#132) ([00a7b9f](https://www.github.com/scop/bash-completion/commit/00a7b9fb79ece368064cce41a74be5dd56f6b266)) +* pyflakes: Remove redundant xspec completion ([0a32296](https://www.github.com/scop/bash-completion/commit/0a32296840e928d25729a8661cd4d7196db3479e)) +* test suite: Generalize xspec completion install check ([1a7137f](https://www.github.com/scop/bash-completion/commit/1a7137fdf61a50a1ada5fe8cd3ae5c9dafddedc1)) +* Make user completion file configurable, disable in tests ([d231255](https://www.github.com/scop/bash-completion/commit/d231255201468e0b5a79c28d9a0e4b246dfeec90)) + +## 2.6 (2017-06-27) + +* xine etc: Associate *.webm and *.weba (#112) ([eee71d2](https://www.github.com/scop/bash-completion/commit/eee71d240feacbce8fe3dcde4fe9d8f730849d7f)) +* mplayer: Associate *.weba (#112) ([82dbb85](https://www.github.com/scop/bash-completion/commit/82dbb853bb2bfb720ece29f2fe806ee8f3695b52)) +* xine etc: Associate uppercase *.WM[AV] ([7250d5b](https://www.github.com/scop/bash-completion/commit/7250d5b721c37b507127285b94a1083de379dfdc)) +* Add missing sidedoor to .gitignore (#114) ([440f65c](https://www.github.com/scop/bash-completion/commit/440f65ce444c00519bc9fa6b5a87fbd4f10a2e67)) +* Bump copyright years ([922bc58](https://www.github.com/scop/bash-completion/commit/922bc58693ad5254142b7aed9a160f2291ddf087)) +* eog: Associate with *.j2c and *.jpg2 ([c91b36d](https://www.github.com/scop/bash-completion/commit/c91b36dd8cd31ea95a952c1fd858d1f3738f3998)) +* xv: Associate with *.j2c, *.j2k, *.jp2, *.jpf, and *.jpg2 (Debian: #859774) ([0de9b7b](https://www.github.com/scop/bash-completion/commit/0de9b7b086574213d21b28c25d1bd5d517880ba0)) +* Travis: Switch tests to docker, update to Ubuntu 14 ([82d85c1](https://www.github.com/scop/bash-completion/commit/82d85c1380707461ad8511b95349d8a56b9961ea)) +* test suite: Add WIP Fedora dev config ([6ed2857](https://www.github.com/scop/bash-completion/commit/6ed285773db08b1200a5063a58a9c0cce9f94c53)) +* synclient, udevadm: Avoid use of posix char classes for awk ([2abecdc](https://www.github.com/scop/bash-completion/commit/2abecdc60e06aebc397a7eb62ae053d34fc68315)) +* ssh-keygen: Make option parsing work with OpenSSH < 7 ([375bd17](https://www.github.com/scop/bash-completion/commit/375bd174aa5750b98c2a01fd3a42b669a7fefb9d)) +* (docker): Run completion tests with xvfb-run, e.g. for gkrellm ([c8f5dac](https://www.github.com/scop/bash-completion/commit/c8f5dac01ee1cd26452bc7e67c75a86924a272e4)) +* tshark -G: Avoid stderr noise when running as superuser ([ea6377d](https://www.github.com/scop/bash-completion/commit/ea6377d2b03be91d6af2fc11c6581eb7aafa1ec4)) +* (test suite): Fix mmsitepass completion test ([596d961](https://www.github.com/scop/bash-completion/commit/596d961152b94fa45470e565d9adf2c3997011c1)) +* mr: Avoid stderr trash and test suite failure if man is N/A ([be12bb2](https://www.github.com/scop/bash-completion/commit/be12bb2514730576ce170a1e7c1f136e20f0f385)) +* (docker): Pull in missing fedoradev xvfb-run which dependency ([e468e44](https://www.github.com/scop/bash-completion/commit/e468e44b32092531dfd3f3c764dccaa5cad1ccb2)) +* (test suite): Don't assume lists set up in newlist test cases ([a9494fe](https://www.github.com/scop/bash-completion/commit/a9494fe4501067388783a6dc454ebe5c2413d3b6)) +* (test suite): Delete trailing whitespace ([ca64e75](https://www.github.com/scop/bash-completion/commit/ca64e755f13b64b1eaec0f4233ff6286e11f68b2)) +* newlist: Parse options from --help, add some arg non-completions ([472db27](https://www.github.com/scop/bash-completion/commit/472db27ae1c5869f7a2b84fb8a1597229d4807a2)) +* (test suite): Don't assume mounted filesystems in quota* tests ([a9fc3dc](https://www.github.com/scop/bash-completion/commit/a9fc3dc7766f0415acb4aba3d14776c97e5ea9fc)) +* (test suite): Make chkconfig test behave better in container ([fcaac9a](https://www.github.com/scop/bash-completion/commit/fcaac9ac97dc963d87023fe4fda32c722677bfee)) +* (test suite): Unsupport various kill, renice cases if ps is N/A ([b5d81bf](https://www.github.com/scop/bash-completion/commit/b5d81bf4479c6454822f21537ec7aa47d592ed39)) +* (test suite): Fix tar test case for ones having --owner-map ([b719ee2](https://www.github.com/scop/bash-completion/commit/b719ee2f27393008f2f6dc5722241f118e822906)) +* (test suite): curl has lots of options, add more test prefix ([4698dbe](https://www.github.com/scop/bash-completion/commit/4698dbe5ccc807333b4128aa1463a90062167ee5)) +* (test suite): Fix perl -d* test cases with no Devel::* installed ([9941b3d](https://www.github.com/scop/bash-completion/commit/9941b3d63d35913e44e41a7b1a05c449543f7fda)) +* (test suite): Ensure /usr/(local/)games is in $PATH ([fda9c43](https://www.github.com/scop/bash-completion/commit/fda9c43c233e16380704ae0ed6500fa91c38b167)) +* (test suite): Add bunch of packages to ubuntu14 container ([ffeb91a](https://www.github.com/scop/bash-completion/commit/ffeb91a28bee72038215d968a1f9237a8ad0599e)) +* (test suite): Add our ./configure to PATH to test it, test opts ([07cbd0d](https://www.github.com/scop/bash-completion/commit/07cbd0df40629a4b0da1eb1ccaf201e7aba1463a)) +* (test suite): Add basic hping3 test case ([9f2efc5](https://www.github.com/scop/bash-completion/commit/9f2efc525d76db97b8bbf702c7b8f243451e5bf7)) +* (test suite): Test lsof on ubuntu14 ([db40d50](https://www.github.com/scop/bash-completion/commit/db40d5084e781399a5b1276caf8a5a43315ab7b2)) +* unshunt: Parse options from --help ([a7caf57](https://www.github.com/scop/bash-completion/commit/a7caf57cc49feae235cc15daa4bdf5b3d7e4a491)) +* (test suite): Install jshint to ubuntu14 container with npm ([4813904](https://www.github.com/scop/bash-completion/commit/48139045355dd9ddee5e67938f6e61123542d7ee)) +* (test suite): Add mailman bin dir to PATH for some mailman tools ([5eee6c5](https://www.github.com/scop/bash-completion/commit/5eee6c571df8156fec45c9dfbd0b733b73014346)) +* (test suite): Install jshint globally in ubuntu14 ([987f251](https://www.github.com/scop/bash-completion/commit/987f251c02b0d367ef0a7ababf18eccc6be64458)) +* alpine: Parse opts from -h output, add some opt arg completions ([7c5bc49](https://www.github.com/scop/bash-completion/commit/7c5bc49e29cf20ed5a338bad0da178dcecc63b6f)) +* (test suite): Add basic alpine test case ([282cdba](https://www.github.com/scop/bash-completion/commit/282cdbae6272e966e9fb0f91b06cf415ef929dda)) +* (test suite): Fix alias and cd cursor position tests ([35f1cd8](https://www.github.com/scop/bash-completion/commit/35f1cd844227c9ddcc36f316d87c4de9fe9db426)) +* (test suite): Add unrar to ubuntu14 container ([77fa46d](https://www.github.com/scop/bash-completion/commit/77fa46de688341bf229d27d05b51af434b7b5e0c)) +* (test suite): Install some things N/A in ubuntu14 to fedoradev ([f6c0d3a](https://www.github.com/scop/bash-completion/commit/f6c0d3a207c59caac74f4943126ea147d8c6896b)) +* (test suite): Avoid interference from user and system dirs (#87) ([1d3b6da](https://www.github.com/scop/bash-completion/commit/1d3b6da02a731e43077dc7dbef51036381b7889c)) +* (test suite): Accept non-whitespace single word in assert_complete_any ([476b260](https://www.github.com/scop/bash-completion/commit/476b26017e4168ad4be0b8d66ee9db03315fbdac)) +* (test suite): Load tested completions dynamically ([7fa35af](https://www.github.com/scop/bash-completion/commit/7fa35afb89e0a6614c173fef56191f01fa2e3ee7)) +* arch: Parse options from --help ([ca31dfa](https://www.github.com/scop/bash-completion/commit/ca31dfaf37ba0302da8b75427e36d3248e1c51ef)) +* (test suite): Add mailman bin dir to PATH for arch test ([222fbb8](https://www.github.com/scop/bash-completion/commit/222fbb80c19f1fa229a554a01726c2bffe6ab5c1)) +* (test suite): Ignore runtime loaded env function changes ([3dd8112](https://www.github.com/scop/bash-completion/commit/3dd81121c41767afa46cc5ef2911b33fad9de8ad)) +* (test suite): Add basic CentOS 6 container for bash 4.1 coverage ([537c9a0](https://www.github.com/scop/bash-completion/commit/537c9a0e9d59c699927a2eeb04d87c05a3638490)) +* Don't offer * as configured interface when there are none ([c287bb2](https://www.github.com/scop/bash-completion/commit/c287bb2af817cf12e065ea9c7c500532612bcd6d)) +* (test suite): Don't assume configured interfaces in CI setups ([dbaafbd](https://www.github.com/scop/bash-completion/commit/dbaafbdc79cd2abbe3ed27acad7293e507c67116)) +* (test suite): Simplify renice test, fix with only one completion ([8936b10](https://www.github.com/scop/bash-completion/commit/8936b10767144c4e5f84c04660f86c0828f7cc99)) +* (test suite): Fix CentOS 6 tcllib setup ([b253814](https://www.github.com/scop/bash-completion/commit/b253814289bcbe606a9bda2b961898585f814d80)) +* (test suite): Info test needs docs, don't exclude from CentOS ([f4b79ae](https://www.github.com/scop/bash-completion/commit/f4b79ae1c4ec89e1539f4bc026fc21ee8c0a25e2)) +* (test suite): Add our own dummy ri test fixture ([1a61fc8](https://www.github.com/scop/bash-completion/commit/1a61fc8b41504cea6372c9c9ceb118bea3133d7b)) +* ri: Add option and arg completions ([bf838e9](https://www.github.com/scop/bash-completion/commit/bf838e938342d4ebb8e3a45b837a60c80be661a9)) +* Don't define BASH_COMPLETION_COMPAT_DIR ([c41a762](https://www.github.com/scop/bash-completion/commit/c41a76237bc9dcbfa326eeddd026b66d7646d91d)) +* oowriter: Associate with *.pdf ([0cea46f](https://www.github.com/scop/bash-completion/commit/0cea46f1c88c1805ef3e9d11802d48c0a8013b4b)) +* py.test: New completion ([eae26d9](https://www.github.com/scop/bash-completion/commit/eae26d9bfac3df98eb047fc45d9b8a7c4bc5d7b9)) +* _configured_interfaces: Parse from /etc/network/interfaces.d/* on Debian ([d0c4410](https://www.github.com/scop/bash-completion/commit/d0c44102a8ed2e0a40d4e5456fc27bc21973a40e)) +* (test suite): Don't insist on loading all completions dynamically ([f845109](https://www.github.com/scop/bash-completion/commit/f845109a83bb7efbab89df9016f23595fea0bb7a)) +* (test suite): Set dcop result to untested if dcop server is not running ([25fa2f7](https://www.github.com/scop/bash-completion/commit/25fa2f72dce597a30e1e4a6088f175f159e9d159)) +* man: Don't check OSTYPE or GNU userland, just enable on all systems ([d0ff1a9](https://www.github.com/scop/bash-completion/commit/d0ff1a946a3bea2122b5adb77260faf06627a2de)) +* _user_at_host: Append @ suffix to username part completions ([f9f10a3](https://www.github.com/scop/bash-completion/commit/f9f10a396da44dddcd3f965cfe55fb3e16f85cf8)) +* _user_at_host: Set nospace only when completing username part ([a4c6763](https://www.github.com/scop/bash-completion/commit/a4c67638eaea89503c1623a78e1680ac1eb2331f)) +* bind: Add option and argument (non-)completions ([67e082c](https://www.github.com/scop/bash-completion/commit/67e082cf9dd0a9d9a0c7fd187e66db8fc8a374ee)) +* xine etc: Fix *.m4a association ([279c3cd](https://www.github.com/scop/bash-completion/commit/279c3cd6c66f0b18a74dbc96fde178998a7283d8)) +* mplayer, xine, etc: Associate *.mp4a and *.mp4v ([c868d7b](https://www.github.com/scop/bash-completion/commit/c868d7becbcb7ac16617a4858f40dd123821c32a)) +* mplayer: Remove duplicate *.m4a and *.m4v associations ([0845c21](https://www.github.com/scop/bash-completion/commit/0845c2183c91054013055ca1966ec1e547fa5b13)) +* Revert "(test suite): Fix alias and cd cursor position tests" ([c30a613](https://www.github.com/scop/bash-completion/commit/c30a6135f3f56931ed8e92b54733be3494805c14)) +* (test suite): Set TERM to dumb, not dummy ([81c72d4](https://www.github.com/scop/bash-completion/commit/81c72d444ab8aa8393371effd2334b2b83cb8503)) +* (test suite): Test screen -T completions ([c936d99](https://www.github.com/scop/bash-completion/commit/c936d99610d7a47fd75f7df38b9611faadd2167e)) +* gm: New completion, commands only for now ([1ac39db](https://www.github.com/scop/bash-completion/commit/1ac39db3f9906d23357661093360747b6b45f59d)) +* openssl: Add sha2 commands ([ec02542](https://www.github.com/scop/bash-completion/commit/ec02542c4293f3013dac3ad57a6775c4da66260d)) +* openssl: Parse available digests from dgst -h ([b6ddef3](https://www.github.com/scop/bash-completion/commit/b6ddef3d1f80c17b81c254ede4b362624a73b2a4)) +* python: Fix traceback avoidance on module completion error ([5faa19c](https://www.github.com/scop/bash-completion/commit/5faa19cb380fa31aa569401b30014dde3598a485)) +* test suite: Add Python module completion test case ([6abf9d6](https://www.github.com/scop/bash-completion/commit/6abf9d6c9ad848040f50a7a8732950789f831f97)) +* micropython: New completion, aliased from python ([9e5522f](https://www.github.com/scop/bash-completion/commit/9e5522fc29bda255caf9dd796c75c4c02662c756)) +* python: Split module completion to separate helper ([abb3016](https://www.github.com/scop/bash-completion/commit/abb3016cac990ffacf66a05ecd7a8d657589d817)) +* test suite: Improve ls home dir test descriptions ([fc8c976](https://www.github.com/scop/bash-completion/commit/fc8c9760368d4da2d97d78bae1f89d35fa0e4d42)) +* dpkg: Fix dpkg -i home dir completion ([dd8c53b](https://www.github.com/scop/bash-completion/commit/dd8c53b05f4954d0401d18b108d771e0d79d88a2)) +* test suite: Cosmetic tweaks ([a01c66b](https://www.github.com/scop/bash-completion/commit/a01c66b6e1e7b288fb96aefed777e4e3afb367bc)) +* test suite: Mark dpkg -L test case untested if no packages installed ([d3276a8](https://www.github.com/scop/bash-completion/commit/d3276a8c2c8e3b17549c21fc4daec1159495edac)) +* tar: Comment spelling fixes ([8c5283f](https://www.github.com/scop/bash-completion/commit/8c5283f89840fcb81811eae8fc19d4905f640c52)) +* test suite: If colon trim doesn't do anything, trim as usual ([f4ffafe](https://www.github.com/scop/bash-completion/commit/f4ffafe0e9d361cf4494962d70e5d6b76ed91407)) +* test suite: Ignore env var pulled in by use of scp in tests ([7f1f33b](https://www.github.com/scop/bash-completion/commit/7f1f33bdcb6e5eded2295ffeaec27199335ce65f)) +* test suite: Fix ifdown and ifup CI test skipping ([089288d](https://www.github.com/scop/bash-completion/commit/089288dd8b7a3c1abbcb0b230014ae03c92ca663)) +* test suite: Skip an expected make test case failure in centos6 CI ([4d5785f](https://www.github.com/scop/bash-completion/commit/4d5785f1b3bc320266addfecc8fab6d0b07d6904)) +* Expose version in BASH_COMPLETION_VERSINFO, use it in profile.d script ([eb6f40c](https://www.github.com/scop/bash-completion/commit/eb6f40c5a7e715d8a9104bf90c67018428ca2eb7)) +* test suite: Mark expected centos6 CI _filedir failures as such ([a1a4eb8](https://www.github.com/scop/bash-completion/commit/a1a4eb82050084a8447c4d2e9e248da9131d55b0)) + +## 2.5 (2017-02-04) + +* : Whitespace fixes ([2ed36b8](https://www.github.com/scop/bash-completion/commit/2ed36b808cee5416139a034477a223f4910b53d8)) +* Travis: zopfli is AWOL? ([96141cd](https://www.github.com/scop/bash-completion/commit/96141cd29817c38b30a6ede294d91913548e475e)) +* make: Declare _make_target_extract_script like other functions ([7be3f33](https://www.github.com/scop/bash-completion/commit/7be3f33541f6c18d36008b49d25d018d50a8fa28)) +* : Move indentation settings to .editorconfig ([619fb1f](https://www.github.com/scop/bash-completion/commit/619fb1f86ece68ea56e0e5c30c030376c1f8a07f)) +* CONTRIBUTING: Reorder sections ([fefcf16](https://www.github.com/scop/bash-completion/commit/fefcf162ffd00b34e24aae55ec92293c2a6590f3)) +* .ipa is just a zip file and we should let unzip handle it (#71) ([7b9dc46](https://www.github.com/scop/bash-completion/commit/7b9dc46c6a26a1a8e99409bb7752dfe153f2de0f)) +* deja-dup: New completion ([d3c483c](https://www.github.com/scop/bash-completion/commit/d3c483c6d13596062aafbe2e8359affb2c2a8a9e)) +* perl: Remove full path to cat in PERLDOC_PAGER call ([06e4c48](https://www.github.com/scop/bash-completion/commit/06e4c4859c270e0999f3c8c9ba02fc16adf8aa6b)) +* mr: New completion ([624a452](https://www.github.com/scop/bash-completion/commit/624a452f57c2a0a777984493a8756ef7388a3f72)) +* travis: Add mr ([78b0543](https://www.github.com/scop/bash-completion/commit/78b054319cc8f4dd39076fb1ffdf898c3aaf498f)) +* dd: Sync completions with coreutils 8.24 ([8b35dd3](https://www.github.com/scop/bash-completion/commit/8b35dd34233761c2b238858eae7b458a6d017672)) +* mplayer: Associate with *.mjpg, *.mjpeg (Debian: #837779) ([c16826e](https://www.github.com/scop/bash-completion/commit/c16826ee35ecb405fe87007404d0fb846ad61a15)) +* ssh-keygen: support ed25519 keys (#79) ([85b6951](https://www.github.com/scop/bash-completion/commit/85b6951358fc6d120f9bf73960694439050264a1)) +* ssh-keygen: Parse switches with _parse_usage, not _parse_help ([4dc0016](https://www.github.com/scop/bash-completion/commit/4dc0016625993487ed28ff0914ab8ebca47bd4e8)) +* Add support for Include in ssh config (#70) (#80) ([1016e43](https://www.github.com/scop/bash-completion/commit/1016e4336c2eaa95888275df6ea248b4e913fb76)) +* ant: parse targets in imported buildfiles (#84) ([62233c8](https://www.github.com/scop/bash-completion/commit/62233c87c030dfe96f4c55575c4ebb93bb984638)) +* mr: Disable "clean" test case, command N/A before mr 1.20141023 ([98146c9](https://www.github.com/scop/bash-completion/commit/98146c9275524e4db33d05c52147b103550be4a5)) +* Support for python gui source files (#91) ([84881eb](https://www.github.com/scop/bash-completion/commit/84881eb314f45a42e11f81e574777e3c05e86e72)) +* ip: Recognize address in addition to addr ([b53b287](https://www.github.com/scop/bash-completion/commit/b53b287c0c0166a0c66fea8aebe694086d71ba03)) +* ip: Recognize a as alias for address and l for link ([7029dd8](https://www.github.com/scop/bash-completion/commit/7029dd825201a1d75e052408102dd8a3f744ace1)) +* Add sidedoor to _ssh() completion (#106) ([7ecca5c](https://www.github.com/scop/bash-completion/commit/7ecca5c89aede4ddd39e516969f9bfc8aba219ee)) +* (test suite): Avoid loading user's ~/.bash_completion, fixes #87 ([c96f432](https://www.github.com/scop/bash-completion/commit/c96f4323c429b793cb03366faac59fbb78472dca)) +* test/config/*: Delete trailing whitespace ([d8cb128](https://www.github.com/scop/bash-completion/commit/d8cb1284245e23351ccc6d96346aea13ec1bcaf4)) +* travis: Skip bluez and nis for now due to post-install script issues ([58aaad3](https://www.github.com/scop/bash-completion/commit/58aaad3ee112333cdb1984d9838c6a7f747fdfc5)) +* Fix bug in 'make' completion when using BSD sed (#108) ([33f3ef3](https://www.github.com/scop/bash-completion/commit/33f3ef366e594ea8bf88d934031b63b5cd89285a)) +* ccache: fix completing compiler's flags ([ae84d53](https://www.github.com/scop/bash-completion/commit/ae84d53c44a3d4cb0bc38e7df53b69242dbd7cc7)) +* Add more tests for ccache ([b0ec56d](https://www.github.com/scop/bash-completion/commit/b0ec56d24caee277aaf35ee86beb939add648165)) +* javac: Complete -cp like -classpath ([c068fca](https://www.github.com/scop/bash-completion/commit/c068fcaa83c8e1b183df62df8f85be6012a56df0)) +* test suite: Add java/javac non-completion fixture ([b35c4c9](https://www.github.com/scop/bash-completion/commit/b35c4c9cbbf45b59206f1a4ed1260a554a0f920e)) +* Minor edits to README.md (mostly formatting) (#110) ([23cc43b](https://www.github.com/scop/bash-completion/commit/23cc43b4484c8d683d9c56400cc57698c2c2d984)) + +## 2.4 (2016-08-12) + +* tipc: add tipc completions ([a0b5863](https://www.github.com/scop/bash-completion/commit/a0b586332f32f5c4ba4735424f387915bd975946)) +* CONTRIBUTING: Highlight request for test cases ([0eb9600](https://www.github.com/scop/bash-completion/commit/0eb9600990b0197b2982a7f79bcfa9aa2401cb6f)) +* test suite: Add function and declare test cases ([81f2708](https://www.github.com/scop/bash-completion/commit/81f2708198dd87604c4257b94b18c0e96a2852fb)) +* mpv: Don't install symlink for it, fixes #24 ([0382773](https://www.github.com/scop/bash-completion/commit/0382773bbfc21dc1fb5467c1c0426ea3c984b6ec)) +* aclocal: Install completion for 1.14 and 1.15, fixes #25 ([a8f4357](https://www.github.com/scop/bash-completion/commit/a8f4357f154f142ef30347b87a378e07b22608e9)) +* Better handling of typeset/declare ([af3934a](https://www.github.com/scop/bash-completion/commit/af3934ad3474e94faa08f94523ed029e95c98767)) +* Add tests for declare/typeset ([71b9147](https://www.github.com/scop/bash-completion/commit/71b9147d375393c60e3628bd7cd5ab41fac8504d)) +* Support completing array variables and expansions ([dde1d31](https://www.github.com/scop/bash-completion/commit/dde1d314c4e8934693e7090ef4467dfac7d72a92)) +* tipc: add test framework ([f6d00ad](https://www.github.com/scop/bash-completion/commit/f6d00ad8af985c8790eb9151aa3840e0cf4e76a0)) +* tipc: merge functions into main ([935a98d](https://www.github.com/scop/bash-completion/commit/935a98d1550372d082abe4ac6965cf9ea1fe3989)) +* tipc: use bash here string instead of echo ([d03425e](https://www.github.com/scop/bash-completion/commit/d03425e23ff8e2957bc639c61f9d9bfbc2fac3a9)) +* tipc: remove unnecessary function _tipc_get_val() ([1969438](https://www.github.com/scop/bash-completion/commit/1969438c818c0829b78f87d34968357f3478b94a)) +* tipc: add command prefix to link sed ([cdbc193](https://www.github.com/scop/bash-completion/commit/cdbc193826cabe74f89650236ae1bda8f7e9aa9f)) +* The BitKeeper completion used the wrong set of commands ([be62355](https://www.github.com/scop/bash-completion/commit/be623550daf22492d58dfa359eea71cf36b723f3)) +* man: Prioritize MANPATH, simplify, add fallback e.g. for busybox, fixes #28 ([c9f54e7](https://www.github.com/scop/bash-completion/commit/c9f54e7a411613cbfba2b200d35059f5bcb87113)) +* cppcheck: Complete filenames too for --platform ([7634fe1](https://www.github.com/scop/bash-completion/commit/7634fe1b88948cbb724b6f3e8e3d8a6786973fd3)) +* tipc: use cur variable for flag completion ([696eb89](https://www.github.com/scop/bash-completion/commit/696eb8961e2038c88eaff85b3bea20fe938ccd87)) +* tipc: readd call to complete command ([831abc7](https://www.github.com/scop/bash-completion/commit/831abc716288b636ce4aa66a4e0b1e5b3100a469)) +* Use shell globbing instead of ls to source files in compat dir ([760bd6f](https://www.github.com/scop/bash-completion/commit/760bd6f2758437eac08c4133884434cfd1ca54b3)) +* aspell, minicom, mysql: Replace use of ls with printf ([751dbbb](https://www.github.com/scop/bash-completion/commit/751dbbb156aaa5171ba5e9136662ee5fbc6cf7d6)) +* rpm: Fix --whatenhances arg completion ([e236020](https://www.github.com/scop/bash-completion/commit/e236020f858fc8929eee2fc4f1f4b7ce0ac5b3b0)) +* make: Avoid a grep ([47c5c97](https://www.github.com/scop/bash-completion/commit/47c5c9773b00504a174326e356a5455892efe616)) +* vncviewer: Cleanup shopt use, drop an eval ([cfc6212](https://www.github.com/scop/bash-completion/commit/cfc62125a8fc9e3d72e9154a504f9548b0b2ba38)) +* aptitude: List packages using _apt_cache_packages, fixes #33 ([49265f0](https://www.github.com/scop/bash-completion/commit/49265f0094690bb9443de1c46a54d87d58876310)) +* tar: silence --version's stderr output ([e1b1fd2](https://www.github.com/scop/bash-completion/commit/e1b1fd29a781d6f760ba2735e183d03a3e0ea130)) +* test suite: Add bashcomp_bash env var for better control on tested bash ([93940c0](https://www.github.com/scop/bash-completion/commit/93940c099aa629d1990ba4fc995d9e44453253ab)) +* Travis: First steps toward testing with OS X ([60a5b47](https://www.github.com/scop/bash-completion/commit/60a5b47760710836338faf4867a08985fcbb10d5)) +* chroot: New (generic long options) completion, see #38 ([ce49e8d](https://www.github.com/scop/bash-completion/commit/ce49e8d87430bd640fb2ed1b5e03b05e02093b75)) +* pyvenv: New completion ([fd9515f](https://www.github.com/scop/bash-completion/commit/fd9515fbe33bd5fa40a86251bb9e8a2616012633)) +* abook: Parse long options from command including full path ([5ad751f](https://www.github.com/scop/bash-completion/commit/5ad751f89726a34ad0a22720a686e80a877c76b3)) +* test suite: Add basic pushd test case ([864cb34](https://www.github.com/scop/bash-completion/commit/864cb342b37110df17903e6bae94c6bf2b785cd3)) +* pushd: Use _cd completion for CDPATH support, closes #38 ([e35c504](https://www.github.com/scop/bash-completion/commit/e35c5046676b12d43bc19b5d2727ec03a6086dc6)) +* Support pod document files for perldoc (#39) ([40e7b4e](https://www.github.com/scop/bash-completion/commit/40e7b4e8730e515a075c1e4852aa98ffa7ac78e0)) +* perl: Remove some duplicated code ([cf559ae](https://www.github.com/scop/bash-completion/commit/cf559aeb1e67ee40a2b8c38e5581e02cd346ee22)) +* test suite: Add perldoc module+pod completion test case ([c6defa3](https://www.github.com/scop/bash-completion/commit/c6defa39cede252c9b3b39aaa35a6608b6310ad2)) +* mysql: Avoid --default-character-set error with failglob, fixes #46 ([fa10367](https://www.github.com/scop/bash-completion/commit/fa10367f319b91bda56b8cf972d60dfb5ae65c5b)) +* tipc: remove unnecessary return values ([6c3942c](https://www.github.com/scop/bash-completion/commit/6c3942c8844dd95613d178dd835e6253004ce14e)) +* tipc: make loop variables local ([e1b535e](https://www.github.com/scop/bash-completion/commit/e1b535e31f28097a6f90da1e0e5b11d5280dcde0)) +* tipc: use double brackets in if conditions ([d815b46](https://www.github.com/scop/bash-completion/commit/d815b46102e6a0d92ca7c0e3a8c9d8881f606a3a)) +* apache2ctl, aspell, make: Don't hardcode completion generator command ([3426649](https://www.github.com/scop/bash-completion/commit/342664947b241902d352dba2aede4cdcda5585f1)) +* python: Support -Q and -W arg completion without space ([a9d0250](https://www.github.com/scop/bash-completion/commit/a9d0250abf879468272c56068cda5a94e1e850b3)) +* xetex, xelatex, luatex, lualatex: Associate with tex files ([1e567a5](https://www.github.com/scop/bash-completion/commit/1e567a5eaf861804b6b8d636f976e947b4d2dc1c)) +* CONTRIBUTING: Note patch preferences if not using GitHub pull requests ([5017ee6](https://www.github.com/scop/bash-completion/commit/5017ee6a3be315bf66eb5ee642a0450aa93741e6)) +* (test suite): Remove test/fixtures/_filedir/a"b from git, create on the fly ([fec077d](https://www.github.com/scop/bash-completion/commit/fec077d555f112b9f455c45860f90a3b47392fcf)) +* (test suite): Remove Bash::Completion.3pm.gz from git, create on the fly ([52d05a6](https://www.github.com/scop/bash-completion/commit/52d05a68e4583c8ee4dcd2c1f0da5db6629e5ff1)) +* (test suite): Fix fallout from fec077d555f112b9f455c45860f90a3b47392fcf ([6170f07](https://www.github.com/scop/bash-completion/commit/6170f073a8765dabcd74f98c3362a10201f5322e)) +* tipc: suppress tipc error messages ([83f78d2](https://www.github.com/scop/bash-completion/commit/83f78d2b4c2942a01f16697963a5ff24540d9ca7)) +* tipc: handle complete words without trailing space ([1e778fc](https://www.github.com/scop/bash-completion/commit/1e778fcf780abe0f6d4044fe891b8385bf9bbd0b)) +* tipc: fix missing last char in link name completion ([502b718](https://www.github.com/scop/bash-completion/commit/502b7189350632cd074f86361b498294b745ee61)) +* tipc: Indentation fix ([48ab557](https://www.github.com/scop/bash-completion/commit/48ab5571b5a9c21db269cbf981cf7f9dae78bd44)) +* tipc: Invoke ls with "command" ([103dbe5](https://www.github.com/scop/bash-completion/commit/103dbe5cf25087da4e5804374debcf8e9bb289a1)) +* (test suite): Pass assert_complete_any for exact/only given arg completed ([847c2bf](https://www.github.com/scop/bash-completion/commit/847c2bf1aa30ca9f2718f583ad148ba558ca6cc2)) +* Travis: Install more packages for more test coverage ([6388b8f](https://www.github.com/scop/bash-completion/commit/6388b8f5e77e1357a2d99109a46df7b813fdfd52)) +* hcitool,svcadm,tar: Spelling fixes ([9a03b80](https://www.github.com/scop/bash-completion/commit/9a03b8068e20d4384786d9e5259b0d6d25575438)) +* pypy3: Alias to python ([35767bf](https://www.github.com/scop/bash-completion/commit/35767bfdf4c8751f2bb453aa65bf359b313b79de)) +* pypy*: Add basic --jit arg completion ([72beabe](https://www.github.com/scop/bash-completion/commit/72beabe4fcae1025a18e689b551b9c5c2d327c30)) +* : Remove redundant return 0's ([8611927](https://www.github.com/scop/bash-completion/commit/8611927cfd3f95b88adcd8eff34cb17250870291)) +* : Trivial cleanups ([b31c0f9](https://www.github.com/scop/bash-completion/commit/b31c0f95c7151beb8f97ebed042d555264aa6fc1)) +* pkg-get,pkgrm: Drop unnecessary _have calls ([2d2d15b](https://www.github.com/scop/bash-completion/commit/2d2d15b8f4eab836c39f7d31c4ef0c9586103ad8)) +* jarsigner: Add some option arg (non)completions ([5da97ee](https://www.github.com/scop/bash-completion/commit/5da97ee3da2582b988df7d9ecab788dc8b63485e)) +* pkg-get: Don't use hyphens in function names ([e194c31](https://www.github.com/scop/bash-completion/commit/e194c312c765cd87541ab46178b17521e098c64c)) +* lrzip: Add -m arg noncompletion ([fd6412e](https://www.github.com/scop/bash-completion/commit/fd6412e159143360972549233f28bb84e6cdc3f9)) +* javadoc: Add bunch of option arg (non)completions ([30598c8](https://www.github.com/scop/bash-completion/commit/30598c864c71e6a5184a7f4aef02cfed2df38e32)) +* rpm: Offer --filetriggers with -q ([8212aca](https://www.github.com/scop/bash-completion/commit/8212acae3588ecec0afcb0ac94a799b62a475737)) + +## 2.3 (2016-03-28) + +* lvm: fix all commands that should get all PVs ([caa2222](https://www.github.com/scop/bash-completion/commit/caa22225f86034f72e7020e0919b4a618c580509)) +* lvm: pvcreate should be able to use all block devcices ([2212dc5](https://www.github.com/scop/bash-completion/commit/2212dc584160977cfbca1eb43dd745b8056baf3b)) +* CONTRIBUTING.md: Ask for test cases ([78e9493](https://www.github.com/scop/bash-completion/commit/78e949363c0f1162d324d7d6c788f74e5b10cc57)) +* make check: Test syntax of all completion files ([b5d8a84](https://www.github.com/scop/bash-completion/commit/b5d8a84852c0ef9984f56f047ed296d1081ce668)) +* travis: configure and run completions syntax check ([75c537c](https://www.github.com/scop/bash-completion/commit/75c537c5a72c078dcaa21dad6c19bf90e2d444a3)) +* Completion for python zip archives ([f205719](https://www.github.com/scop/bash-completion/commit/f20571949641f44eb8a0e6e88a1aeffd1bd2a42d)) +* unzip, zipinfo: Complete on *.pyz ([a576160](https://www.github.com/scop/bash-completion/commit/a5761607bd37a201a2512f10bbc7be646e51b2fb)) +* test suite: Add some python test cases ([16d52f9](https://www.github.com/scop/bash-completion/commit/16d52f9a6c6be22d421ba2de07aec8413803c112)) +* python: Complete all files only if -c is before current word ([6eae809](https://www.github.com/scop/bash-completion/commit/6eae809beacc7c6ab3db5f5ccfa57dce48d00e3b)) +* python: Don't offer options after -c ([5f016fc](https://www.github.com/scop/bash-completion/commit/5f016fcd3991c389da27edd37668b0fd7db37cf4)) +* python: Complete all files also after -m ([f17407b](https://www.github.com/scop/bash-completion/commit/f17407bc3282f2abd5fb9ea47e07b18cf4a9e898)) +* python: Simplify code ([235f726](https://www.github.com/scop/bash-completion/commit/235f7269773b80fed4b41722de28df93ee0fd817)) +* tar: Don't write to /tmp/jetel ([6bdd922](https://www.github.com/scop/bash-completion/commit/6bdd92202f55d7c530dcbeb2a243604dac546cf1)) +* test suite: Add tar xvf filename test case ([807f903](https://www.github.com/scop/bash-completion/commit/807f903f86ad647425c83f7ad6fc499014c6734e)) +* tar: Fix GNU tar help output parsing regex, fixes #15 ([0b7189d](https://www.github.com/scop/bash-completion/commit/0b7189d4eee4597e11cab02e6b4dcae488db5ca8)) +* tar: Remove unused variable ([7ab05bf](https://www.github.com/scop/bash-completion/commit/7ab05bf9d97ce5a6ced7acdfc21235e06542c3f2)) +* tar: Detect GNU/other from --version only once per session ([88c671a](https://www.github.com/scop/bash-completion/commit/88c671a2c74bfde3bc2ec7c6f74133ac613c61da)) +* test suite: Fix tar failure caused by previous tar change ([198ab64](https://www.github.com/scop/bash-completion/commit/198ab64862777763f9750216131938300bf3a79c)) +* test suite: Tolerate "See 'man feh'" feh --help output ([b4b8916](https://www.github.com/scop/bash-completion/commit/b4b89162e376574980292eaab761d393a6fbd5f9)) +* test suite: Don't insist on property completions if synclient -l fails ([9716a54](https://www.github.com/scop/bash-completion/commit/9716a54837d43cbd8d79c04ac66251df8d3fcf1f)) +* test suite: Fix abook test case ([eae0183](https://www.github.com/scop/bash-completion/commit/eae0183322854ee51500482e2223f5c3091d39b7)) +* : Use [:blank:] instead of $'\t ' tricks where appropriate, fixes #19 ([657fcf6](https://www.github.com/scop/bash-completion/commit/657fcf62c77343ede3a21430a6c8e4faf4cd1dbe)) +* gnokii: Use <<< instead of echo + pipe ([b7ededc](https://www.github.com/scop/bash-completion/commit/b7ededc40fdf02f3ee110e057ebe103338ccbf0f)) +* make: Use <<< instead of printf + pipe ([1a122fb](https://www.github.com/scop/bash-completion/commit/1a122fb5827588d57339fc88f0692dd92a0c14b2)) + +## 2.2 (2016-03-03) + +* feh: Add new sort type ([0354981](https://www.github.com/scop/bash-completion/commit/0354981b1f348263edb7c2e6f1f8dc619a48c476)) +* kcov: Add new sort types, complete --replace-src-path arguments ([6cb7f96](https://www.github.com/scop/bash-completion/commit/6cb7f969745dd6b2075dd61244f8e60445a6a3d5)) +* Add config for cmake to bash-completion. ([94b7e63](https://www.github.com/scop/bash-completion/commit/94b7e63f6d525a029efac07e20f4102fe8563a71)) +* _mac_addresses: Use explicit C locale for ifconfig (Debian: #704832). ([a9db458](https://www.github.com/scop/bash-completion/commit/a9db458339fb518178b1b6cc234930bb869e95ea)) +* aclocal, automake: Install for *-1.10, *-1.12, and *-1.13 too. ([e772425](https://www.github.com/scop/bash-completion/commit/e772425cdd660d4d59914d2e067be07d7f4b3504)) +* cvs rm: Don't filter existing files with -f (RedHat: #949479). ([9852597](https://www.github.com/scop/bash-completion/commit/9852597d8c19567ee1e01c03a297692d9c1cd764)) +* Use == instead of =. ([497c209](https://www.github.com/scop/bash-completion/commit/497c20902a978098512674bbaa37a839e355c782)) +* nmcli completion was integrated upstream ([580a4cf](https://www.github.com/scop/bash-completion/commit/580a4cf6e55ab1afd6b1f8f7efc54436e7046e44)) +* Revert "nmcli completion was integrated upstream" ([cdd2c3d](https://www.github.com/scop/bash-completion/commit/cdd2c3d71d9eec2860ad99ba3f81ef65dbd1e723)) +* nmcli: Deprecate our completion, upstream has one in 0.9.8.0. ([9780b0a](https://www.github.com/scop/bash-completion/commit/9780b0a04472187cb4ac4557e21038caac31fd86)) +* sh: Complete script arguments with all filenames (Alioth: #314226). ([daaa541](https://www.github.com/scop/bash-completion/commit/daaa54100ed061a0c8e7ce89a8bda009530246a3)) +* cvs: Fix checkout -j non-completion. ([bb0739f](https://www.github.com/scop/bash-completion/commit/bb0739fafd87bfca2e5d43e8b448ec1293a43ada)) +* Clean up/compact various globs. ([d99c220](https://www.github.com/scop/bash-completion/commit/d99c2203b9ff6e35ce12fbe0572773a9f3abeadb)) +* wget: Stop completing after --help/--version. ([5786568](https://www.github.com/scop/bash-completion/commit/57865686de2d2ff0c455704428a49d5a3b4f98c8)) +* wget: Drop incorrect -nv arg completion. ([1969d12](https://www.github.com/scop/bash-completion/commit/1969d125bacde3da22c06e5ca729c7e766ce7d65)) +* wget: Add --accept-regex/--reject-regex/--regex-type arg (non)completions. ([5c6b1bb](https://www.github.com/scop/bash-completion/commit/5c6b1bb4a47ca522c111f110f44eff771d9aea5f)) +* perl*: Fix handling of relative paths in @INC. ([18c28bb](https://www.github.com/scop/bash-completion/commit/18c28bb9a2147e662755e393d1ec39f270948d30)) +* perl: Fix -dt: completion. ([97efc7c](https://www.github.com/scop/bash-completion/commit/97efc7ca08f22043ce5c55f41ac093de9c7ca082)) +* hcitool, rfcomm, ciptool, hciconfig: Don't leak $args. ([3a3290d](https://www.github.com/scop/bash-completion/commit/3a3290ddcf81181bbd9f22a739536b65df0c5647)) +* 7z: New completion. ([5a9e8f2](https://www.github.com/scop/bash-completion/commit/5a9e8f219b847a6c99f294b4cc492e77a63a22f0)) +* file-roller: Reuse unzip's xspec. ([42196ef](https://www.github.com/scop/bash-completion/commit/42196ef7fc1f91c51a471a1b50d2c1a48d77560f)) +* 2to3: New completion. ([a4b69e7](https://www.github.com/scop/bash-completion/commit/a4b69e75873b9b24e1da0c6bda22d42365cc97ac)) +* perl: -d/-dt option argument is optional (Alioth: #314242) ([ad455df](https://www.github.com/scop/bash-completion/commit/ad455dfa9de9253d52d6352888777f6a9328eade)) +* dpkg: Suppress unwanted error messages (Debian: #706502) ([9ca8d93](https://www.github.com/scop/bash-completion/commit/9ca8d933c69e5a52e7866227dfc823657c180f40)) +* cppcheck: Add new --enable option argument and --library argument completion ([77ebc93](https://www.github.com/scop/bash-completion/commit/77ebc93a023e6b1bba87b9572c17e824d248c540)) +* export, _variables: Do TZ= completion (Redhat: #994646). ([3f144be](https://www.github.com/scop/bash-completion/commit/3f144beb721525821136f76f53a3147b4688d331)) +* Cosmetics. ([62e0c3b](https://www.github.com/scop/bash-completion/commit/62e0c3ba7245741c9ef2a664a84a8f6c61a6f875)) +* make: Use only posix basic regexps with sed (Alioth: #314345) ([f230cfd](https://www.github.com/scop/bash-completion/commit/f230cfddbd12b8c777040e33bac1174c0e2898af)) +* _longopt: Run commands in C locale. ([a282d02](https://www.github.com/scop/bash-completion/commit/a282d0254cca2e9e1e851e251dc77f3b2aa653ce)) +* aptitude: safe-upgrade accepts package name as parameters (Alioth: #313638, Debian: 673235) ([e91a458](https://www.github.com/scop/bash-completion/commit/e91a45889f3fb8b4007949797fc3f07af24bb52f)) +* bzip2, gzip, lzma: Cleanups. ([61d1d7d](https://www.github.com/scop/bash-completion/commit/61d1d7df42cace84c5d706b43f44ea2083c54723)) +* zopfli: New completion. ([2da4ee9](https://www.github.com/scop/bash-completion/commit/2da4ee9ad5a9016e4e4a89e4822bf6e1688c6175)) +* make: Fix basic regex for portability (Alioth: #314345) ([3ac523f](https://www.github.com/scop/bash-completion/commit/3ac523f57e8d26e0943dfb2fd22f4a8879741c60)) +* _known_hosts_real: Pre-expand \t instead of relying on sed supporting it (Alioth: #314393). ([50ae579](https://www.github.com/scop/bash-completion/commit/50ae57927365a16c830899cc1714be73237bdcb2)) +* dict: Trivial regex cleanup. ([705be00](https://www.github.com/scop/bash-completion/commit/705be005027577ba540212be6b0bbb25e95f78f3)) +* abook, kldunload: Pre-expand \t instead of relying on sed supporting it. ([24f0c58](https://www.github.com/scop/bash-completion/commit/24f0c58c29885f89ef2a3a16db17e73b6cd6f64e)) +* cc, c++: Install minimal completion for non-gcc ones (Alioth: #314417). ([d6600e6](https://www.github.com/scop/bash-completion/commit/d6600e6a10a370961b4bd4e1e060ba79e080a8d7)) +* cc, c++: Check path to binary when finding out if it's gcc (Alioth: #314417). ([ffabc6f](https://www.github.com/scop/bash-completion/commit/ffabc6f2829201815c1a9c69cfdf8bdbe77ff648)) +* f77, f95: Use the same completion as for g77, g95 if they are links to gfortran ([df8782d](https://www.github.com/scop/bash-completion/commit/df8782d76928bd39b3de138305f9b0af36628a9f)) +* 7z: Improve completion ([d048a14](https://www.github.com/scop/bash-completion/commit/d048a14b2ae18c70ddcf54558cdc79eaf7e8d751)) +* mplayer: -dvd-devices takes dvd devices, dirs and .iso files as argument ([d482e74](https://www.github.com/scop/bash-completion/commit/d482e746821f102205475dfb835ca75a7fd02d63)) +* _known_hosts_real: Exclude %h HostName entries (RedHat: #1015935). ([fcc9545](https://www.github.com/scop/bash-completion/commit/fcc9545b44f32b627f75e1589fb93a5c7ad86bff)) +* timeout: New completion. ([63b4995](https://www.github.com/scop/bash-completion/commit/63b499593a595cffd09403852555577e3f590cb5)) +* complete on freerdp-specific known hosts list ([1cfbbdd](https://www.github.com/scop/bash-completion/commit/1cfbbdd52cafd6b995f7241e2b87a41ed0f7a87a)) +* bts: New completion, thanks to Federico Ceratto. ([b2e7951](https://www.github.com/scop/bash-completion/commit/b2e7951cd714bd31e6efd0b6e16c1f916fd94486)) +* appdata-validate: New completion. ([e93cc98](https://www.github.com/scop/bash-completion/commit/e93cc98523e722bc0557ae623b4bd9d16ee01486)) +* uscan: New completion, thanks to Federico Ceratto ([61fa261](https://www.github.com/scop/bash-completion/commit/61fa261502f904c3afa5f053a68cccd243cbfcd4)) +* Refactor bts and uscan, since they use common functions ([780d97c](https://www.github.com/scop/bash-completion/commit/780d97c5ac41a1d170fa294811e8cadffa550248)) +* wtf: Hush stderr when db file doesn't exist. ([f5df66f](https://www.github.com/scop/bash-completion/commit/f5df66f47653ebe781090411a8e03fa052053273)) +* wtf: Don't offer -f if it was already specified. ([e694978](https://www.github.com/scop/bash-completion/commit/e694978346b017d92dfeb7968fc57d018c8721a4)) +* wtf: Look for acronym db from /usr/share/games/bsdgames/acronyms too. ([920bbb8](https://www.github.com/scop/bash-completion/commit/920bbb8582bcd3039ff4e4388e795e3144eb30b6)) +* (testsuite): Limit wtf completions to A* to keep expect happier. ([c527b54](https://www.github.com/scop/bash-completion/commit/c527b543a84363449902e2be5e80786aceaa7931)) +* cppcheck: Include - in --file-list completions. ([4df6d3f](https://www.github.com/scop/bash-completion/commit/4df6d3ffb86cf2cd9f583d5e927f2661a8a83a84)) +* optipng: New completion. ([34a74df](https://www.github.com/scop/bash-completion/commit/34a74df61973d1f49805135e79045e2c7b1589e0)) +* lz4: New completion. ([a2e2f19](https://www.github.com/scop/bash-completion/commit/a2e2f198d820c55857e372f6477c6fe07a23df92)) +* (testsuite) Check for grep and ls invoked without "command", see README ([d98e56f](https://www.github.com/scop/bash-completion/commit/d98e56fb0725f96a5cb39362c2d9a60a39e69154)) +* lintian: Replace some grep+cuts with awk ([93ee009](https://www.github.com/scop/bash-completion/commit/93ee00947ae112f195ed368f3414f3622d113630)) +* gcc, lintian, make, pkgadd, slackpkg: grep -> "command grep" (Debian: #734095) ([e3edf7a](https://www.github.com/scop/bash-completion/commit/e3edf7ac423179f70acbd77d9ffbbf5cfa91ce58)) +* aptitude, dpkg: Replace some grep+cuts with awk ([e777395](https://www.github.com/scop/bash-completion/commit/e777395ac3ce25527e58e04bfc406ae03bdb3b12)) +* ip: Add some addr, addrlabel, and route arg completions ([b5d0cdd](https://www.github.com/scop/bash-completion/commit/b5d0cdd802817708bb1fdb03880eb95e9be9e67b)) +* jpegoptim: New completion ([8617e22](https://www.github.com/scop/bash-completion/commit/8617e227e541ffc3d34c69d861c52f188bd5ae15)) +* Bump copyright years to 2014. ([01fd3b4](https://www.github.com/scop/bash-completion/commit/01fd3b4f55407623dbef58b6b6a756ad623c334f)) +* ssh-keygen: New completion ([0b7d92c](https://www.github.com/scop/bash-completion/commit/0b7d92cf2bb3eb04668c73b6d39726caca617bf9)) +* portsnap: New completion. ([c3770c1](https://www.github.com/scop/bash-completion/commit/c3770c17984bb61255db6adb48886b466c335e03)) +* freebsd-update: New completion. ([5ff5a4e](https://www.github.com/scop/bash-completion/commit/5ff5a4e0f875e8d1a49848408cfe72778889cbe8)) +* testsuite: Add basic tests for portsnap and freebsd-update ([602d188](https://www.github.com/scop/bash-completion/commit/602d18853ccb71baa233c33d93503b0ce27070a0)) +* hwclock,ionice,rtcwake: Deprecate in favor of util-linux ones (Debian: #737672) ([e4b1740](https://www.github.com/scop/bash-completion/commit/e4b17402bbb5d53797a601de93771d8bd0df5213)) +* _*: Install our deprecated completions too, try loading them secondarily ([e201d1b](https://www.github.com/scop/bash-completion/commit/e201d1be7ed92bf35c249d6d01c4001378e0ed77)) +* testsuite: Add basic test cases for deprecated completions ([3e06371](https://www.github.com/scop/bash-completion/commit/3e0637128f67807500f3af042a6f536d1404b968)) +* testsuite: Add basic newgrp test case ([bb76897](https://www.github.com/scop/bash-completion/commit/bb768978ba2eee1ab5d0f4e3d6158d9df1643630)) +* cal,chfn,chsh,dmesg,eject,hexdump,look,newgrp,renice,runuser,su,write: Deprecate on Linux in favor of util-linux ones (Debian: #737672) ([e452f2e](https://www.github.com/scop/bash-completion/commit/e452f2e8d6788458830bf2afe55d641e6adfa940)) +* pyflakes: New completion ([e14617e](https://www.github.com/scop/bash-completion/commit/e14617e498f0e2e2faceea9205f96d72c3e9ef8d)) +* flake8: New completion ([5152356](https://www.github.com/scop/bash-completion/commit/5152356ad1b0c8384d52ea9648529c448bbb4af2)) +* ri: Fix colon handling in class completion. ([24ea53f](https://www.github.com/scop/bash-completion/commit/24ea53f01de9c218a133d8cf7b3c77d6ad07bc26)) +* ri: Fix class completion with ri >= 3. ([3cdcfde](https://www.github.com/scop/bash-completion/commit/3cdcfdeda65a281a4f175a6b2f330c983a4bd217)) +* (testsuite) Avoid complete-ant-cmd.pl errors with our build.xml ([14be62a](https://www.github.com/scop/bash-completion/commit/14be62aae4197a7f98e913c0ada910c5c2ea7f04)) +* FAQ: Clarify that we mean the bash man page for M-/ ([293bbaa](https://www.github.com/scop/bash-completion/commit/293bbaaa90238511b12ffb0efd3d5de0cbd5abfc)) +* profile.d: Don't return from a sourced script (Debian: #741657) ([867282a](https://www.github.com/scop/bash-completion/commit/867282a7341ccfff9a0e8a8ef6bba6e781b66afb)) +* man: Use -w instead of --path ([4927730](https://www.github.com/scop/bash-completion/commit/492773098004700d670b4e1c12eebac506471d90)) +* xrandr: Add (some) --setprovider* arg completion support ([c50313c](https://www.github.com/scop/bash-completion/commit/c50313c30df5eb3a7956b0420f882508e79da0a5)) +* xrandr: Use the invoked command internally, not hardcoded "xrandr" ([b758afc](https://www.github.com/scop/bash-completion/commit/b758afc105fd0656c13f88a5bd2f73bac81399db)) +* qemu: Apply completion to qemu-kvm/-system-i386/-system-x86_64 too ([61ad655](https://www.github.com/scop/bash-completion/commit/61ad655fc4a6c18947ce6f17d4ea8f87abd6c945)) +* qemu: Fix -balloon arg completion ([4a4afd5](https://www.github.com/scop/bash-completion/commit/4a4afd5eab0fcaf19ac1f2ce55c1bb305f89903f)) +* pngfix: New completion ([13ad1f1](https://www.github.com/scop/bash-completion/commit/13ad1f1966f5baa14d9785c4b732dda3a29f4f14)) +* gdb: support --args style completion (Alioth: #314664) ([b1f7803](https://www.github.com/scop/bash-completion/commit/b1f78035565dcca343841cc4fa7ff54b09cc81b9)) +* eog: Complete on *.pgm (RedHat: #1090481) ([77e11c4](https://www.github.com/scop/bash-completion/commit/77e11c41ea376e364ac83ddc54428b18052b8ffe)) +* nslookup: complete on hosts (Alioth: #314673) ([b74d537](https://www.github.com/scop/bash-completion/commit/b74d53761afb48e5e0948b70e7202a1c1cda4897)) +* hostname: New completion ([c924d32](https://www.github.com/scop/bash-completion/commit/c924d32b4c127bc9cc46cb71d3148c8bdbfdd6cf)) +* pypy: New completion identical to python (Alioth: #314501) ([38a013e](https://www.github.com/scop/bash-completion/commit/38a013e22cd30c0cce84caaaff2763d0c39ce131)) +* Use more straightforward way to check bash version ([768a958](https://www.github.com/scop/bash-completion/commit/768a95854616e25c8da3f9d79048f9bbb5ecb2a6)) +* dpkg: Add support in dpkg completion for .ddeb (LP: #568404) ([eafde37](https://www.github.com/scop/bash-completion/commit/eafde3784836391741c2264ad1b350fff1aa276a)) +* make: completion shouldn't be confused by the output of $(info confuse: make) ([54d53c6](https://www.github.com/scop/bash-completion/commit/54d53c622745e907d288d67d832a0b09aaa1d3df)) +* Puppet: use puppet terminology ([ac98c31](https://www.github.com/scop/bash-completion/commit/ac98c31f30b74b32ec0eea8df6c71b866b16b58e)) +* Puppet: puppet -* doesn't imply 'puppet apply' ([20e9bef](https://www.github.com/scop/bash-completion/commit/20e9befbff2b4cac09f7beec58e5ad6eac1425b4)) +* Puppet: puppet parser support ([b56df70](https://www.github.com/scop/bash-completion/commit/b56df708a1bbaf27bf76d06b18448bba6b2d59f6)) +* Puppet: agent: update options list, accordind to 'puppet help agent' ([af5ba56](https://www.github.com/scop/bash-completion/commit/af5ba56089088669e31bb49d855bcc42c98f0951)) +* Puppet: apply: update options list, accordind to 'puppet help apply' ([5a536ae](https://www.github.com/scop/bash-completion/commit/5a536aec4ca4e8bc6c179dfd2f98d71a3c541f1d)) +* Puppet: cert: update options list, accordind to 'puppet help cert' ([b46636a](https://www.github.com/scop/bash-completion/commit/b46636ae16c98045caf9c4dbfa4020f3c08671a5)) +* Puppet: describe: update options list, accordind to 'puppet help describe' ([0bbcc47](https://www.github.com/scop/bash-completion/commit/0bbcc476b2d8f54c8a6a3e633db97586ecb0e23c)) +* puppet: Exit early on -h|-V|--version in addition to --help ([f94d1a6](https://www.github.com/scop/bash-completion/commit/f94d1a6803a488b24b3b7005ce86c19949a381e6)) +* puppet: Parse most subcommand options from "help subcommand" output ([00a80a2](https://www.github.com/scop/bash-completion/commit/00a80a2a830cc5cfea262865e5d97d1f901ca177)) +* puppet: Recognize some short options ([dbe7325](https://www.github.com/scop/bash-completion/commit/dbe732517ef2a2d8c628e3578db330b64d177948)) +* (testsuite) Add puppet subcommand option test case ([d748a5a](https://www.github.com/scop/bash-completion/commit/d748a5a24914a9f5f0173a98bd6435aac3d39747)) +* mpv: New completion alias + adjustments for mplayer (Debian: #749115) ([de78c16](https://www.github.com/scop/bash-completion/commit/de78c1653aad081daf28cd349e0f52801db3a180)) +* _services: README in sysv init dir is not a service ([41cdfc6](https://www.github.com/scop/bash-completion/commit/41cdfc6510093ddb6766aabb1574d2064279620e)) +* __reassemble_comp_words_by_ref: Make work with failglob on (Alioth: #312741) ([732906b](https://www.github.com/scop/bash-completion/commit/732906b25096508fbc5d15d684dea0312ed7fca0)) +* psql: Tell psql to not load .psqlrc as it may change output format (Alioth: #314636) ([9186add](https://www.github.com/scop/bash-completion/commit/9186add6298cac3c684b1123ea3c8006f87fc24b)) +* Quote unset array element to avoid globbing interference (Alioth: #314708) ([84135d7](https://www.github.com/scop/bash-completion/commit/84135d756bd395aa720c3bd08c660bc54d24f90c)) +* Various mostly array element unsetting fixes under failglob ([1ed2377](https://www.github.com/scop/bash-completion/commit/1ed2377c895d3f1826df0820d992f746c10373a9)) +* ssh-add, ssh-keygen: -? needs to be quoted under failglob (Alioth: #314709) ([24c8f1e](https://www.github.com/scop/bash-completion/commit/24c8f1e44e4e3a094745a45896963c4b3edff9ad)) +* Quote _filedir arguments when appropriate to prevent failglob failures ([8566a5a](https://www.github.com/scop/bash-completion/commit/8566a5a89633a6d689192638410914910e2a1523)) +* slapt-src: split options from their arguments ([3a65be4](https://www.github.com/scop/bash-completion/commit/3a65be4a18f67d1b5101ce1d03398728aebe0668)) +* slapt-{get,src}: Fix issue with sed not being able to handle some characters ([70e52c8](https://www.github.com/scop/bash-completion/commit/70e52c8a1fc4ebc3ea5516879505ca5da504b32b)) +* gendiff: Quoting suffix pattern to avoid triggering failglob ([154f388](https://www.github.com/scop/bash-completion/commit/154f3884139825a38e161c2e66837a35e9aa3841)) +* sbopkg, slapt-{get,src}: expand tilde in config file name ([505481c](https://www.github.com/scop/bash-completion/commit/505481c8cc4bdb13b89de8505d5d84c31314245c)) +* slapt-src: Handle --config=FILE option properly ([7220727](https://www.github.com/scop/bash-completion/commit/72207276a5d4a92c9fa0baef1f21941f9f1ad891)) +* _filedir_xspec: Fix with failglob on ([b65232f](https://www.github.com/scop/bash-completion/commit/b65232fa34e310cf357e2ff4b8921e50e260d294)) +* lvm: _lvm_count_args parameter must be quoted in order to failglob not to complain ([3717fe7](https://www.github.com/scop/bash-completion/commit/3717fe7b6d97ba8e8e8eb55ce10c05808dc4d4b8)) +* (testsuite) Add vgcreate test case for _lvm_count_args with failglob on ([615fd18](https://www.github.com/scop/bash-completion/commit/615fd18195793cd867c0a365c25069cdbb89c565)) +* _lvm: using a single-pattern case and invoking function according to words[1] ([01024f5](https://www.github.com/scop/bash-completion/commit/01024f595e9e6e3f243b2abc1a3474529ce1f083)) +* umount: Fix mount points escaping/unescaping with Bash-4.3 ([292830b](https://www.github.com/scop/bash-completion/commit/292830be53f69456d284c10dc5fea28dd393d7bc)) +* (testsuite): move testing of _linux_fstab() to umount.exp ([dcb0ea2](https://www.github.com/scop/bash-completion/commit/dcb0ea2ca29cf2c335f1b075f51290d023fcda2e)) +* _parse_help: Fix failglob failures (Alioth: #314707) ([d238ab5](https://www.github.com/scop/bash-completion/commit/d238ab5445627b6fd9888507d1b7545bb20408a7)) +* modprobe: fix params with multi-line descriptions ([454f67a](https://www.github.com/scop/bash-completion/commit/454f67a0478e2097e765169191151e9cf83fe978)) +* modprobe: Try parsing help before using hardcoding option list ([c6ec8f9](https://www.github.com/scop/bash-completion/commit/c6ec8f979bb6a6c6bdfeae75749a5be4c5145fdb)) +* ssh-add, ssh-keygen: -? needs to be quoted under failglob (take 2) (Alioth: #314709) ([60b8fab](https://www.github.com/scop/bash-completion/commit/60b8fabec499dbd56636548369ff3796e0d0d0fd)) +* isql: Fix failglob failure ([9d250f9](https://www.github.com/scop/bash-completion/commit/9d250f9b53a58c70c7a388e5d2272d8a384d6eb1)) +* Added test/site.{bak,exp} to .gitignore ([afe39fd](https://www.github.com/scop/bash-completion/commit/afe39fd1e171d0ea3d4fb8ec0d8c8c14fa120ed8)) +* adb: New completion ([4bbab19](https://www.github.com/scop/bash-completion/commit/4bbab196cbce908dacbc225de71433272228a985)) +* (testsuite) Use 'set' command posix behaviour when saving env (Alioth: #314720) ([16361c8](https://www.github.com/scop/bash-completion/commit/16361c873ba04d941c56c7e6a3fbe8d446f07ca7)) +* (testsuite) Save shell variables when saving env (Alioth: #314720) ([dbb93ae](https://www.github.com/scop/bash-completion/commit/dbb93ae77ba6613d89081b9592fb3714b604476c)) +* xz: Complete -T/--threads argument ([9e2db8a](https://www.github.com/scop/bash-completion/commit/9e2db8a03ea661eb7f4a4c41cd0558c063c04aca)) +* xmllint, xmlwf, xsltproc: Complete on *.dbk and *.docbook (Alioth: #314770) ([ab8eeb3](https://www.github.com/scop/bash-completion/commit/ab8eeb3a713b1223752336fc4cb0d515c24579cc)) +* xsltproc. TODO fix for previous commit ([7c5c622](https://www.github.com/scop/bash-completion/commit/7c5c622dda132a2c4a78028273f86fd51a9d680c)) +* python(3): Add -X argument non-completion ([eb79f9d](https://www.github.com/scop/bash-completion/commit/eb79f9d97fc384b2cbfdb0c9a782d9ef935356ab)) +* 7z, adb: Trivial cleanups ([d259e71](https://www.github.com/scop/bash-completion/commit/d259e7175851f08cda10ae6c279ab1d0e7bc8045)) +* ant: Don't offer more completions after options that exit ([98d6b5e](https://www.github.com/scop/bash-completion/commit/98d6b5e440fc666256cfb3ee2fe2f07da45f31a7)) +* (testsuite) Add ant -f <buildfile> test case ([40db483](https://www.github.com/scop/bash-completion/commit/40db4831747a0a4f80fcb383c0c7b5398b327538)) +* ant: Support buildfile set in $ANT_ARGS (Alioth: #314735) ([86df56d](https://www.github.com/scop/bash-completion/commit/86df56d5ec986566a33cc5b1067c6dbc6078dab1)) +* mplayer, *xine: Complete on *.mts (Debian: #759219) ([852e0f6](https://www.github.com/scop/bash-completion/commit/852e0f60f0df8264a84a3be543d09f1d13c6f04f)) +* rpmbuild: Complete *.spec on --clean (RedHat: #1132959) ([e879eb0](https://www.github.com/scop/bash-completion/commit/e879eb0a1706cad92d6df8b3c665d1d5227b1f67)) +* rpmbuild: Complete *.spec on --nobuild ([42e1f34](https://www.github.com/scop/bash-completion/commit/42e1f344b7fef71100e42ab97f63e35281116ced)) +* Comment update ([fa064e8](https://www.github.com/scop/bash-completion/commit/fa064e85633cd56000f8bf2cd8eb3bc76eceeeed)) +* _completion_loader: Set empty command to _EmptycmD_ for cross version compat ([7394d74](https://www.github.com/scop/bash-completion/commit/7394d744aee259929012cbcd53a9c268dfe9c025)) +* _init_completion: Handle cword < 0 (LP: #1289597) ([a9c556c](https://www.github.com/scop/bash-completion/commit/a9c556ccad819869a6a5d932aac0a75a99372f08)) +* pigz, unpigz: Handle *.zz ([4038c71](https://www.github.com/scop/bash-completion/commit/4038c71357dd85ee049363c6c48c513e1c1c263d)) +* Protect various compgen invocations from -* leakage (Debian: #766163) ([882649b](https://www.github.com/scop/bash-completion/commit/882649b7123855a0b87fcee7e4bc043ca2cca711)) +* (testsuite) Add cd in dir without subdirs or CDPATH test case ([9444a87](https://www.github.com/scop/bash-completion/commit/9444a8742e3aa8d1ef8eb35a377a860f9e59fa43)) +* _pnames: Add -s for producing (possibly) truncated names (RedHat: #744406) ([52d8316](https://www.github.com/scop/bash-completion/commit/52d8316c5ce4060cf86154eea3ba6fa51447760a)) +* Actually install the lz4 completion ([ed07b18](https://www.github.com/scop/bash-completion/commit/ed07b18e61bc4756c94d3230e6a0b32798087e20)) +* _completion_loader: Protect compgen from -* leakage (Debian: #769399) ([32e6e49](https://www.github.com/scop/bash-completion/commit/32e6e4908885197ae3f48da0f4fe7d182245818b)) +* gphoto2: Fix split argument handing, and colon treatment in --port args ([7d66285](https://www.github.com/scop/bash-completion/commit/7d66285b42f7847e1b5dedf5ed7c4536cb2bb288)) +* : Invoke command to be completed, not its basename ([7d3de61](https://www.github.com/scop/bash-completion/commit/7d3de619d1d84cba29597a54b4f0c0b786e8abe0)) +* gphoto2: Replace tail with awk ([89add74](https://www.github.com/scop/bash-completion/commit/89add74ae07d17eaaff811159e086663e4791d85)) +* ccache: Add -o/--set-config arg name completion ([dfb2d01](https://www.github.com/scop/bash-completion/commit/dfb2d01babcf00ecbb57c97e648d97881004797d)) +* chrome, firefox etc: Complete on *.pdf ([6a60025](https://www.github.com/scop/bash-completion/commit/6a60025e01165cddce61257902358badd738f1fa)) +* strings: Fix -T/--target arg completion with non-English locale ([976ad96](https://www.github.com/scop/bash-completion/commit/976ad96007fbc8edac189737876e485e0cc38e08)) +* upstart support for service completion ([3567d93](https://www.github.com/scop/bash-completion/commit/3567d9354fbc40f050831559df17d442e3177a8d)) +* (testsuite): Add mcrypt -a and -m argument completion tests ([377e240](https://www.github.com/scop/bash-completion/commit/377e24024ee419a50fd21a1ae2e984f19ac512b3)) +* mcrypt: Simplify -m arg completion ([a592a09](https://www.github.com/scop/bash-completion/commit/a592a09cc6fb1d43ef737baf5b31371f55ad19d0)) +* tshark: Simplify cut usage ([23bf3bd](https://www.github.com/scop/bash-completion/commit/23bf3bd412adb3cfff774f019d8c376658d50152)) +* createdb, dropdb: Drop -o default, it does not appear to do anything good here ([e71b452](https://www.github.com/scop/bash-completion/commit/e71b4522d18306dfa98b013441122910a1166ea9)) +* createuser: New completion ([7999f28](https://www.github.com/scop/bash-completion/commit/7999f28f62f49caf2b736fd835152c2579c2646d)) +* dropuser: New completion ([3cf50a1](https://www.github.com/scop/bash-completion/commit/3cf50a1437f9f0b8ef16bd6ea58db18e7a9204f6)) +* profile.d: Avoid some warnings from shells in "nounset" mode (Debian: #776160) ([c725e6b](https://www.github.com/scop/bash-completion/commit/c725e6b195ea6ac2d25dfbb85b7e87bfbe42fe68)) +* cppcheck: Option argument (non-)completion update ([e687c3a](https://www.github.com/scop/bash-completion/commit/e687c3a1085e06502b882f71b4deab79266b9b14)) +* reptyr: Rename file to _reptyr to avoid conflict with upstreamed completion ([6a4ad49](https://www.github.com/scop/bash-completion/commit/6a4ad49fa53cc92d3bd23b5b4db0b3318f2ef136)) +* tune2fs: Add missing return in -M arg completion ([edea6cb](https://www.github.com/scop/bash-completion/commit/edea6cb6da246930c1314384ba2f150efd0c07d5)) +* synclient: New completion ([6a1bf8d](https://www.github.com/scop/bash-completion/commit/6a1bf8d11430fea80864bd0fef46210143d91407)) +* Drop reference to no longer used sysconf_DATA ([ba79e9e](https://www.github.com/scop/bash-completion/commit/ba79e9e5798ac4f25036ddf15885cd3bbaeed4bc)) +* README: Add autotools and cmake tips ([3a8e7bd](https://www.github.com/scop/bash-completion/commit/3a8e7bd0fe45b4ebf76b4cd6da9246034b2e0557)) +* README: Add cmake usage example ([889718b](https://www.github.com/scop/bash-completion/commit/889718be68ccd442ee824f6405d706d8e2734a03)) +* README: Don't hardcode /etc in cmake fallback dir ([2c5efee](https://www.github.com/scop/bash-completion/commit/2c5efeec3a3b8cf29dd2f161935e786988d9dc36)) +* Revert "README: Don't hardcode /etc in cmake fallback dir" ([caaa474](https://www.github.com/scop/bash-completion/commit/caaa4745e40a5d1d9122b0774ba589ef5fafbcbf)) +* Load user completions from $BASH_COMPLETION_USER_DIR/completions ([1d25d72](https://www.github.com/scop/bash-completion/commit/1d25d72ca8633c19cb089dff447d08c531379c59)) +* 2015 ([d423969](https://www.github.com/scop/bash-completion/commit/d423969756d0043007d80a7b30e5b4c611e06883)) +* _filedir: Fix overquoted argument to compgen -d (RedHat: #1171396) ([d2920b7](https://www.github.com/scop/bash-completion/commit/d2920b7e79e5f347fed064b2a5aa952ef200e615)) +* _filedir: Remove unused variable ([80c2bb6](https://www.github.com/scop/bash-completion/commit/80c2bb696437134d6d8a3fb9c9f455fec75f470a)) +* make: Add __BASH_MAKE_COMPLETION__ variable ([f9115ce](https://www.github.com/scop/bash-completion/commit/f9115ce0bb215e9089266d6f1ec20c3375aa970a)) +* _filedir: Avoid some unnecessary work with -d ([40c764a](https://www.github.com/scop/bash-completion/commit/40c764af57ea0cd0c5c5cebeba6c838230d30c93)) +* gnokii: New completion ([3eb1b0d](https://www.github.com/scop/bash-completion/commit/3eb1b0dda81f2bc15a6c4f104cb5f0d2169c3101)) +* gnokii: Various minor and cosmetic fixes ([b07e355](https://www.github.com/scop/bash-completion/commit/b07e35511138adc2a375ea3fcd21aee6a175e4f3)) +* (testsuite): Add basic gnokii test case ([90ebb7e](https://www.github.com/scop/bash-completion/commit/90ebb7eb54b5598a5780dab90c984bad160f4268)) +* gnokii: Drop dead code ([ca138d0](https://www.github.com/scop/bash-completion/commit/ca138d05db3853ea89f09979be3c32eea554de1c)) +* gnokii: Fix completions of options that are prefixes for others ([8930330](https://www.github.com/scop/bash-completion/commit/89303303bd28d2c0b9d1e7e69e607ca2cf650760)) +* gnokii: Include and install it ([1950590](https://www.github.com/scop/bash-completion/commit/1950590367838993fba00586139137a50a1d4f80)) +* make: Fix detection of intermediate targets where make has changed its database whitespace ([4b209b0](https://www.github.com/scop/bash-completion/commit/4b209b0b172ddecff1e9aaf5de9ea64267fb9053)) +* jshint: New completion ([adff509](https://www.github.com/scop/bash-completion/commit/adff509ec54a45957ac3c0f1facbe6dec3c5a0aa)) +* tar: rework the completion completely ([8b23c84](https://www.github.com/scop/bash-completion/commit/8b23c84cc2935b15b8cb2ac1a90d061b914229a6)) +* bsdtar, tar: Remove symlinks from git, have make create them ([81cfa06](https://www.github.com/scop/bash-completion/commit/81cfa067cc1bcb9d508beb8f6689e14e436e2220)) +* (testsuite) Add required "empty" dir for tar ([a8f4507](https://www.github.com/scop/bash-completion/commit/a8f450797b47c25670c87452392161609ea67c36)) +* tar: Style tweaks ([055d1ae](https://www.github.com/scop/bash-completion/commit/055d1ae59f54bf20d22b068631698427f38ce4a0)) +* tar: Plug $line var leak ([d049481](https://www.github.com/scop/bash-completion/commit/d0494819521c1a70e3d83e26f2a55620ea64e89d)) +* eog: Complete on *.ppm (RedHat: #1090481) ([6c2ae9f](https://www.github.com/scop/bash-completion/commit/6c2ae9fb18cb56d89b190286a422b60f03d85ba4)) +* Document how to avoid command_not_found_handler interference ([1d9e705](https://www.github.com/scop/bash-completion/commit/1d9e705639e40c28b3ae4ce2a99c9c7308e3c653)) +* sysctl: Try parsing options from help before usage ([e9fe2d9](https://www.github.com/scop/bash-completion/commit/e9fe2d9f7b9c3401f990b140d58de9e6c6b42a5c)) +* sysctl: Return early on --help, --version ([d01427d](https://www.github.com/scop/bash-completion/commit/d01427df599c8ef2a32c95e286a6c82045d4d26e)) +* ssh: Add -Q argument completion ([b6ffe26](https://www.github.com/scop/bash-completion/commit/b6ffe261f8515d4fddb319424b87d4d38d10dd91)) +* ssh: Query ciphers and macs from ssh before hardcoded fallback ([cf4c7eb](https://www.github.com/scop/bash-completion/commit/cf4c7ebf6c754028957fe0061d0ed247a47ecb1c)) +* ssh: Complete HostbasedKeyTypes,HostKeyAlgorithms,KexAlgorithms values ([2779b66](https://www.github.com/scop/bash-completion/commit/2779b66e5dc8d0278dcde921ed29fc60ce89f181)) +* checksec: New completion ([ffd9038](https://www.github.com/scop/bash-completion/commit/ffd9038923aed3e8be6fe1c746ea3d41407cacb6)) +* pdftotext: New completion ([4289460](https://www.github.com/scop/bash-completion/commit/4289460691719255ca5d34c04d2a7cacc6ccd1ba)) +* pgrep, pidof, pkill, pwdx, vmstat: Add support for procps-ng ([f68589f](https://www.github.com/scop/bash-completion/commit/f68589fde4a95c1b30c9cbb70dcfada133f0f09e)) +* __get_cword: avoid $index < 0 (Alioth: #315107) ([fa1ad7d](https://www.github.com/scop/bash-completion/commit/fa1ad7dff9e7099b14552a8782181e9b00f89cc2)) +* rpm: Add --whatenhances/recommends/suggests/supplements and --recommends/supplements completions ([81acda7](https://www.github.com/scop/bash-completion/commit/81acda727a9ca34eb156c69becf38eac68b50ea7)) +* modplug*: Associate *.oct and *.okt ([69cfaed](https://www.github.com/scop/bash-completion/commit/69cfaed89c25171d40d9d268de7ab6b9412b159f)) +* __load_completion: New function, use in _completion_loader and _xfunc ([cad3abf](https://www.github.com/scop/bash-completion/commit/cad3abfc7ec1cfc2ae17a2330bf9f23993c73f09)) +* mpv: Remove mplayer-aliased completion ([00abd48](https://www.github.com/scop/bash-completion/commit/00abd48e5b1d5d79fff46b7f791b2b90d1d6953b)) +* make: Offer hidden targets when it is clear that the user is trying to complete one of them ([e0c0832](https://www.github.com/scop/bash-completion/commit/e0c08321795c8174fa2275d2683c4ffc1b36db5b)) +* ssh-copy-id: Offer only *.pub to -i ([f9f66c3](https://www.github.com/scop/bash-completion/commit/f9f66c39d35c18c5985bc2baca2242c2e17d539a)) +* sftp: Add -l arg non-completion ([4d82190](https://www.github.com/scop/bash-completion/commit/4d82190da70621d6b0fc375c063e12f97b27edb4)) +* scp, sftp: Fix querying ssh options ([50ea015](https://www.github.com/scop/bash-completion/commit/50ea015f8bc66919eb0ecc7ed351c1f89755f8c0)) +* scp, sftp: Complete -S on commands ([35a0f97](https://www.github.com/scop/bash-completion/commit/35a0f97a5a9bb0aadf834a81761855ad65bb5e28)) +* (testsuite) Ignore files generated by complete-ant-cmd.pl ([f661811](https://www.github.com/scop/bash-completion/commit/f6618113b55e49c4c81f3a2a9fd5dc95a36a683f)) +* make: Don't pick up variables when makefile is reloaded ([c5451db](https://www.github.com/scop/bash-completion/commit/c5451dbd310074f8bceeada0e48e542713dada1e)) +* Load completions also from $XDG_DATA_DIRS (RedHat: #1264094) ([c89dcbb](https://www.github.com/scop/bash-completion/commit/c89dcbbd5510876f6304ef10806b00cc9fda19dc)) +* chronyc: Add -6 option ([7669f0c](https://www.github.com/scop/bash-completion/commit/7669f0c1bece8f4a344d8e22f7d4969f8f141c10)) +* chronyc: Add missing subcommands ([ef26136](https://www.github.com/scop/bash-completion/commit/ef26136ea3f4fcf123c1a4af741be625fbac1a05)) +* chronyc: Update help text parsing ([bc03de5](https://www.github.com/scop/bash-completion/commit/bc03de502c3d8391ee220a3a28ed964db8c5e73a)) +* chronyc: Wrap long lines ([aa404ca](https://www.github.com/scop/bash-completion/commit/aa404ca17d3838b18669e006ab30446cb402988b)) +* chronyc: Parse command args from help output ([5fd0077](https://www.github.com/scop/bash-completion/commit/5fd00776c49f1d4552630c986e70f21e4a6028ad)) +* ssh: Avoid completing commands before hostname ([f8f6ffa](https://www.github.com/scop/bash-completion/commit/f8f6ffa72ed3db9c6628b50f1bd3ef9582b4f264)) +* cppcheck: Add native to --platform completions ([9cbd68b](https://www.github.com/scop/bash-completion/commit/9cbd68becbd728d5fda88a6f456c4c72eac92ec8)) +* minicom: Recognize user ~/.minirc.* as config files ([39acdb2](https://www.github.com/scop/bash-completion/commit/39acdb21e89f89c207089da4c061c193d5d8af84)) +* test suite: Fix ssh-copy-id test on old setups with no identities ([e899139](https://www.github.com/scop/bash-completion/commit/e899139ee38b96ebbf2338d35b4f5e99dce514a4)) +* test suite: Expect failure in modinfo/modprobe if there are no modules ([0a6877e](https://www.github.com/scop/bash-completion/commit/0a6877e8395ac6b46b4bdf3877b674c37aa4dec8)) +* Set up Travis ([e3c8573](https://www.github.com/scop/bash-completion/commit/e3c8573d14866041516beb3a503e3bd752666ec2)) +* test suite: Output tool log on failure in CI ([fa6b80f](https://www.github.com/scop/bash-completion/commit/fa6b80f89c53233fd00b9c33fde2161eef9d8e2a)) +* test suite: Make apt-get test less sensitive to available commands ([7234914](https://www.github.com/scop/bash-completion/commit/7234914a9fb3a17bc116f18bd1a8b6e4beece147)) +* travis: Avoid Travis default ri, use distro one instead ([dc6e8c2](https://www.github.com/scop/bash-completion/commit/dc6e8c257fb895142564eac871daeec78331d522)) +* README: Update POSIX spec link ([ac9f41b](https://www.github.com/scop/bash-completion/commit/ac9f41b93d8d280c9069cfb06efffcef991404d0)) +* Update URLs and various instructions to GitHub ([53215d4](https://www.github.com/scop/bash-completion/commit/53215d4a74ace3477e48dc70e5be19f8bb3c0866)) +* aclocal, automake: Install for versioned 1.14 and 1.15 executables ([caf3b36](https://www.github.com/scop/bash-completion/commit/caf3b364e367bcb2bd518fd436ec134049c2c9e6)) +* build system: Switch to xz compressed tarball ([b51eb9d](https://www.github.com/scop/bash-completion/commit/b51eb9d7f1bc9a7ad6c6f5feb56fca5b963572fa)) +* Drop references to bash-completion-devel@lists.alioth.debian.org ([aee91a9](https://www.github.com/scop/bash-completion/commit/aee91a91baa3c32dc315be39d5f95f8045217594)) +* README: Convert to markdown ([0d3e597](https://www.github.com/scop/bash-completion/commit/0d3e59703fa016f2a8ed0fe6efdfe7fd00fa9250)) +* README: Split contributing to separate CONTRIBUTING doc ([0345d02](https://www.github.com/scop/bash-completion/commit/0345d028ee4ad7793d6293a54bb69929e442041b)) +* Use command built-in to run sed to avoid any custom aliases ([0b37725](https://www.github.com/scop/bash-completion/commit/0b377254203680cb483168f45eaac301db8ac1b3)) +* test suite: Fix ssh partial hostname completion test ([4f13792](https://www.github.com/scop/bash-completion/commit/4f13792b4fe87ebfcd6d9bbe15c9813f2a1b2a94)) +* travis: Run tests with --all to get some more useful output ([d04af62](https://www.github.com/scop/bash-completion/commit/d04af6260a7cfcb1c521298eae346bec9303bfc0)) +* travis: Install more packages for [0-9][ab]* test coverage ([0cec990](https://www.github.com/scop/bash-completion/commit/0cec99072d36ffe68bec89e4e668ec94b4534929)) +* test suite: Use unsupported instead of xfail for modinfo/modprobe cases ([501c106](https://www.github.com/scop/bash-completion/commit/501c10692dfcf744dbf333d78e0ed933b9dc51a8)) +* test suite: Mark unsupported look test case as such, not unresolved ([3dedaa9](https://www.github.com/scop/bash-completion/commit/3dedaa9dd971ea1177561c3f4525ad044ca5dfc5)) +* travis: Add note about (currently) N/A packages ([b5caa09](https://www.github.com/scop/bash-completion/commit/b5caa09b6d1a24d778e87cb65f31590e8ce8b8e6)) +* travis: Install more packages for c* test coverage ([e41426a](https://www.github.com/scop/bash-completion/commit/e41426a57d9924a22af16e2d92b062568470ee61)) +* travis: Install more packages for [de]* test coverage ([1cca6ed](https://www.github.com/scop/bash-completion/commit/1cca6ed104330e1541942204890063f8accf798d)) +* Modify all usages of 'sed' to be run with command bash builtin ([1aad419](https://www.github.com/scop/bash-completion/commit/1aad419db4851fc7fa4b2e384645ecda2f000d88)) +* lint: Check for sed without "command" ([417122b](https://www.github.com/scop/bash-completion/commit/417122bd0293d79921cde05d80ecc1b6654a3542)) +* gnokii, minicom: Use grep through "command" ([536d79f](https://www.github.com/scop/bash-completion/commit/536d79ff42b38b38cc7b7453b0219e6dda888efc)) +* mysql, puppet: sed portability fixes ([f8b0828](https://www.github.com/scop/bash-completion/commit/f8b0828e4fcb25f9628b268fb760aa23cc5db60f)) +* mysql: Fix --default-character-set completion with mariadb ([695b28a](https://www.github.com/scop/bash-completion/commit/695b28aa860d867c49c2ea17e62f1d5b6ebd80a7)) +* travis: Install more packages for [fg]* test coverage ([987af3f](https://www.github.com/scop/bash-completion/commit/987af3f463cbe48f7b31b1a7bed9f3262772b716)) +* travis: Install more packages for [hi]* test coverage ([e0ff9ce](https://www.github.com/scop/bash-completion/commit/e0ff9cea15612e529c9d0702c0cf7ecc61860e67)) +* Update copyright year ([68f3e4e](https://www.github.com/scop/bash-completion/commit/68f3e4eb144125ac3d5dfc57f9482f4815dc9c41)) +* indent: Remove generic long option completion ([c4517d3](https://www.github.com/scop/bash-completion/commit/c4517d393250863afbb9ddc9b481ea6a61519720)) +* Don't complete hostnames found after Hostname in ~/.ssh/config ([4621117](https://www.github.com/scop/bash-completion/commit/46211179bff660992417fccd68e598b4e612e56a)) +* travis: Install more packages for [jkl]* test coverage ([6699288](https://www.github.com/scop/bash-completion/commit/6699288aee3ffd0530ad268fe06bc5c042eecec5)) +* travis: Install more packages for m* test coverage ([3495a48](https://www.github.com/scop/bash-completion/commit/3495a48ecbef38ab5e12ff41ecdbd22cb54c933c)) +* travis: Install more packages for [op]* test coverage ([26c2d23](https://www.github.com/scop/bash-completion/commit/26c2d231dd5e081c7e45d693eeb0f8a667850b0c)) +* travis: Install more packages for [qr]* test coverage ([d491063](https://www.github.com/scop/bash-completion/commit/d4910632f213af7eb6ee537300b1f76ce2faa0b7)) +* travis: Install more packages for [stuvw]* test coverage ([9d12e2c](https://www.github.com/scop/bash-completion/commit/9d12e2c554b7e2963773792f6936dc75df540951)) +* travis: Install more packages for [xyz]* test coverage ([18ca938](https://www.github.com/scop/bash-completion/commit/18ca93839af37b1e494c832016d2a766833ea7f4)) +* Remove various comments related to bash versions we don't support ([ffdc9da](https://www.github.com/scop/bash-completion/commit/ffdc9daecebf5ca4b45995de40469579fd36aac7)) +* ssh: Extract duplicate code to _ssh_configfile ([09f56f8](https://www.github.com/scop/bash-completion/commit/09f56f80a68f2fddc52cf8c91637b80c6ae02164)) +* xmllint, xmlwf, xsltproc: Complete on Mallard *.page files ([1c005b1](https://www.github.com/scop/bash-completion/commit/1c005b19e9b262fdd40c8fc5aae4e75779b1d78b)) +* README: Expand troubleshooting section somewhat ([06996ea](https://www.github.com/scop/bash-completion/commit/06996ea0d4ac83a002613f1d7e50ce68a595cb31)) +* README.md: Not need for autoreconf, fixes #11 ([20f9013](https://www.github.com/scop/bash-completion/commit/20f9013f38d5c54892900654ab037c173e5cc167)) +* zopflipng: New completion ([56c3ea1](https://www.github.com/scop/bash-completion/commit/56c3ea163fd294a144a79d641881f34e625b77db)) +* README.md: Markdown tweaks ([8a748d3](https://www.github.com/scop/bash-completion/commit/8a748d32fae35f2dcf5a7c7061f183a18adae320)) +* README.md: More markdown tweaks ([76d8823](https://www.github.com/scop/bash-completion/commit/76d88231013b0027239a5523f9c70f0ad3f571ee)) +* make-changelog.py: Make work with Python 3 ([8a9cb54](https://www.github.com/scop/bash-completion/commit/8a9cb54d9769fcfebc37d85d204a5893b7ae0eee)) +* make-changelog.py: flake8 fixes ([47ca0cd](https://www.github.com/scop/bash-completion/commit/47ca0cdaba318f6419b20d86050c6ef04ce1ce66)) +* make-changelog.py: Fix footer line output ([d178db6](https://www.github.com/scop/bash-completion/commit/d178db64b28bc5db39a33641930deefeab4baf10)) +* make-changelog.py: Set myself in footer ([7c713e8](https://www.github.com/scop/bash-completion/commit/7c713e872606558fc7314425e3dbaf3d85fea81f)) +* README.md: Note autoreconf need only in unprepared tarball ([3c3b696](https://www.github.com/scop/bash-completion/commit/3c3b696e8a9604f3a0dec159aa5da2c1c4d0f09e)) + +## 2.1 (2013-04-05) + +* eog: New completion. ([3a1cdbd](https://www.github.com/scop/bash-completion/commit/3a1cdbdadc92e041b3b446f4d40d5ffcabe86d4e)) +* wsimport: New completion. ([bffce42](https://www.github.com/scop/bash-completion/commit/bffce4218e33bc61c0551b87e4b5bfbb41ad4223)) +* kcov: Add new sort types (introduced in kcov-9). ([36f1b83](https://www.github.com/scop/bash-completion/commit/36f1b832fd3544dd44dad7b6bce5c115f45cd50d)) +* kcov: Complete arguments of --limits option. ([f604f6c](https://www.github.com/scop/bash-completion/commit/f604f6ce5b952e10ea6053445e9f70c2079943b8)) +* Add .msi completion for Wine ([f3e3fc5](https://www.github.com/scop/bash-completion/commit/f3e3fc5a4d51367a3e8ce29255bb386c809d0947)) +* ssh: Add -O argument completion (Debian: #680652). ([217e143](https://www.github.com/scop/bash-completion/commit/217e143fd69ad2b83ec8187af2e9e1c21dcb759a)) +* Add more complete OpenDocument support to unzip completion. ([6a71ee5](https://www.github.com/scop/bash-completion/commit/6a71ee504c11b798125b9c85359d5b7367a27dd4)) +* Add support for OOXML document format extensions to unzip completion. ([7c7b560](https://www.github.com/scop/bash-completion/commit/7c7b5608c8505633aa55e106f98d2a943937d41a)) +* Fine tune previous commit. ([ca53345](https://www.github.com/scop/bash-completion/commit/ca533452195134de6ceb5c3f894e824fac53849a)) +* wine: Fix extension glob to work on its own. ([e2e64a1](https://www.github.com/scop/bash-completion/commit/e2e64a16329cf0005006dffea590dce20200469d)) +* man: Add support for .lz man pages (RedHat: #839310). ([c9ed166](https://www.github.com/scop/bash-completion/commit/c9ed16694da974ce9faa3f49a274c7c6cfb4abc9)) +* man: Trivial cleanups. ([a624cc2](https://www.github.com/scop/bash-completion/commit/a624cc2c3026981835330f4d001b7df53f8d84ae)) +* clzip, pdlzip, plzip: New lzip alias completions. ([fc107b4](https://www.github.com/scop/bash-completion/commit/fc107b4bdc5a42302b6316ab80755d6cca69d9ba)) +* lzip: Do not append space after equal sign in long options. ([9f0a6e4](https://www.github.com/scop/bash-completion/commit/9f0a6e45f8238e3220db3ffaa058c39110ea7a59)) +* mussh: New completion. ([882d527](https://www.github.com/scop/bash-completion/commit/882d527237c77cdc757672affa070bb1b150b778)) +* mount.linux: Add some new mount options intoduced in Linux 3.5 ([3ea1597](https://www.github.com/scop/bash-completion/commit/3ea1597d3c6c926553b850caad75527a08412eb1)) +* mount.linux: Clean up mount options, remove duplicates. ([3aa040d](https://www.github.com/scop/bash-completion/commit/3aa040d25f5556b6e9bf92c784072aba7620f729)) +* Remove trailing whitespace ([3f9fe7a](https://www.github.com/scop/bash-completion/commit/3f9fe7a853c74d68f64e05ecaca474e7a6819d81)) +* Remove more whitespace ([a9b253c](https://www.github.com/scop/bash-completion/commit/a9b253ca8b475dc2ffda6edc7451af28d23d4eed)) +* Trim trailing whitespace. ([a6ff579](https://www.github.com/scop/bash-completion/commit/a6ff57986f22d19e7a638e398a73a1a3ac19ff13)) +* slackpkg, slapt-get: Update the list of package sets. ([371fb91](https://www.github.com/scop/bash-completion/commit/371fb91b213c3bb4b86eb22e09701ec1be18b7dd)) +* colormake: New make alias completion (LP: #743208, Debian: #682557). ([31e262b](https://www.github.com/scop/bash-completion/commit/31e262bcaf9bee249deb24a0e08cd85346d7a628)) +* Ignore colormake symlink. ([6158bd2](https://www.github.com/scop/bash-completion/commit/6158bd2d86f6122cfc8d3df045e9f4c7c8f3293a)) +* opera: Handle options. ([3c49af9](https://www.github.com/scop/bash-completion/commit/3c49af9ec97b66553c3d756de8f4b5a5f8a54708)) +* mount.linux: Add options completion for davfs. ([f379e92](https://www.github.com/scop/bash-completion/commit/f379e9275c5a966dacd3b2bd45a5b651aae55641)) +* evince: Evince supports opening .pdf.xz files (Alioth: #313739). ([30f9335](https://www.github.com/scop/bash-completion/commit/30f93357c81bf3fbb03ef8a6b3b0f5ce9addde13)) +* Fix __reassemble_comp_words_by_ref for $COMP_CWORD == ${#COMP_WORDS[@]} ([dc15093](https://www.github.com/scop/bash-completion/commit/dc150937d126430f5cc20dfaf3239a71049fe0df)) +* valgrind: Add --soname-synonyms option arguments completion. ([904faab](https://www.github.com/scop/bash-completion/commit/904faab0c57b4f6a65a4f62dc9f644d4771e59fe)) +* eject: New completion. ([b9276c8](https://www.github.com/scop/bash-completion/commit/b9276c8a374ac5e8cbe7ac814fe3c989f903ddd0)) +* fusermount: Complete curlftpfs-mounts for "fusermount -u" (Debian: #685377) ([2897e62](https://www.github.com/scop/bash-completion/commit/2897e62fe7e535eb048f7e08f03ac3fbc3a84fa5)) +* gphoto2: new completion ([92ddcea](https://www.github.com/scop/bash-completion/commit/92ddcea20a473a8d59b1efaea94261b4b36fa35c)) +* nmcli: new completion ([7f1721d](https://www.github.com/scop/bash-completion/commit/7f1721dd9064e5685b984975a7819bfe18b8d71b)) +* cppcheck: Add new standards to --std option. ([1c362f4](https://www.github.com/scop/bash-completion/commit/1c362f4c99eea0ae32ffb6f006f71d1bfb18bc78)) +* make: convert make completion to use smarter parser ([b28d710](https://www.github.com/scop/bash-completion/commit/b28d7108d3677c61bd01c51ccee8bb1cf9e3bfba)) +* Fixed tilde expanding in _filedir_xspec ([fdb080f](https://www.github.com/scop/bash-completion/commit/fdb080ff89195f85e1b76d0752979dfefa777595)) +* make: Do not append space if target is a filepath. ([2babb45](https://www.github.com/scop/bash-completion/commit/2babb45402ee338b888056f01222a602d07a44cd)) +* tar: Fix detection if the $prev is a tar file. ([3622f2f](https://www.github.com/scop/bash-completion/commit/3622f2f9e531ddbb243b39774546cf11ee9ccf3e)) +* _parse_help, _parse_usage: Run commands in C locale. ([8227351](https://www.github.com/scop/bash-completion/commit/822735146f5a5ef71c75f6f8494ad3969eaf2cc5)) +* testsuite/_filedir: Remove the cruft from the a\$b->h unit test (Alioth: #313480) ([23ac383](https://www.github.com/scop/bash-completion/commit/23ac38333e469eac47d35dae7c640bff4a6b5203)) +* make: incremental completion for make with compact display ([39f00f9](https://www.github.com/scop/bash-completion/commit/39f00f92e52b783e7e9e43aac4b4274cc9dee152)) +* make: Convert internal variable names to lowercase, indentation fix. ([b93e399](https://www.github.com/scop/bash-completion/commit/b93e3999b0c485a9808c1d4cb0f825b8019b5a73)) +* lvm volumes: Complete on /dev/mapper/* (RedHat: #851787). ([8e63eaf](https://www.github.com/scop/bash-completion/commit/8e63eafb83342dec5a04fe3c49330c6cbe00f96d)) +* tar: Don't take -I to mean bzip2. ([f321357](https://www.github.com/scop/bash-completion/commit/f32135799155cbde9237567a5a3a811172adf341)) +* feh: Add new options introduced in feh-2.7. ([52163a3](https://www.github.com/scop/bash-completion/commit/52163a337f34cf185fe55833bbd41080a0228baf)) +* wget: New completion. ([e29c6bc](https://www.github.com/scop/bash-completion/commit/e29c6bc872ba437f48eae7c70347c843413de4cc)) +* wget: Fix completion of multiple tags for --{follow,ignore}-tags. ([e0c70ab](https://www.github.com/scop/bash-completion/commit/e0c70abc8b63bed961b736b17e4757ca0a5f1875)) +* useradd: Fix -k, -K, and --home-dir argument completions. ([09d24da](https://www.github.com/scop/bash-completion/commit/09d24da884fcf98a7a22a4487ab79f03c3f20026)) +* useradd, usermod: Support comma separated -G/--groups arg completion. ([8ec4846](https://www.github.com/scop/bash-completion/commit/8ec484692225f2f1565975a763df856dfbb7f27b)) +* wget: Use == instead of =. ([d803323](https://www.github.com/scop/bash-completion/commit/d803323974dd979a55f7f87e96e96b5bf9d9da4f)) +* cppcheck: Add --language/-x argument completion. ([b9189ce](https://www.github.com/scop/bash-completion/commit/b9189ce170388d87c46a4a37f3e05dba0cd8878a)) +* new completion: svcadm ([80356ca](https://www.github.com/scop/bash-completion/commit/80356ca816cfee198bad59359d7a641449183fec)) +* new completion: pkg-get ([6ddec67](https://www.github.com/scop/bash-completion/commit/6ddec67c2f923ce54f3935bc23822c9eaf350430)) +* new completion: pkgadd ([a54fa73](https://www.github.com/scop/bash-completion/commit/a54fa7340a617eabb2c3bfede9a24c9f142505be)) +* new completion: pkgrm ([ff444b5](https://www.github.com/scop/bash-completion/commit/ff444b528397f273d46da7c52a445b924adccc00)) +* new completion: pkgutil ([e5ac55d](https://www.github.com/scop/bash-completion/commit/e5ac55d5df03b04ff082cebd8245fc28c2ef59fd)) +* better entry ([166ac77](https://www.github.com/scop/bash-completion/commit/166ac7754f31d95e7230cb80c521cda01e441faa)) +* fix perms ([8002d32](https://www.github.com/scop/bash-completion/commit/8002d320afee9e38aa39c1acb553402f4f109f84)) +* zathura: Add simple completion for zathura document viewer. ([97eb4da](https://www.github.com/scop/bash-completion/commit/97eb4daa62004ee882961ccd49e7af7418443c81)) +* gpg, mplayer: Restore correct options. ([6be8628](https://www.github.com/scop/bash-completion/commit/6be86286d6db176b785dcea5fdd262b49e133934)) +* lvm: Fix typo in option name: s/continguous/contiguous/. ([b2365b3](https://www.github.com/scop/bash-completion/commit/b2365b3d8743fb0fdca70c5138e66e6b389ba5bd)) +* mplayer: Add -subcp argument completion. ([7f2eb83](https://www.github.com/scop/bash-completion/commit/7f2eb8327c9c59576cd181f813bd27e6e681b02b)) +* mplayer: Add some new option argument completions. ([f3e1079](https://www.github.com/scop/bash-completion/commit/f3e10798e68d9b714a0f527179c48b22ab5c16ce)) +* mplayer: Cleanup. ([2c28608](https://www.github.com/scop/bash-completion/commit/2c2860826fdc624b6aad6532dd46cef79389d872)) +* mplayer: Add opus to the list of supported formats. ([b5dce1c](https://www.github.com/scop/bash-completion/commit/b5dce1c4b69ff2e9935941e54bf9f1ef3ceee542)) +* completions/Makefile.am: symlinks depends on $(DATA) to avoid race conditions ([370b7a0](https://www.github.com/scop/bash-completion/commit/370b7a0d2fdf7f322b59f3c35c1cea19901ef2f2)) +* _command_offset: Restore compopts properly (Alioth: #313890) ([2472fad](https://www.github.com/scop/bash-completion/commit/2472fad5de03ef91864926240a709b3f2b72a173)) +* Update copyright year and release number. ([3b93c22](https://www.github.com/scop/bash-completion/commit/3b93c22a5bb9e47301fca89ec677a9805ea71518)) +* _known_hosts_real: Filter ruptime stdout error spewage (Alioth: #313893). ([f917b75](https://www.github.com/scop/bash-completion/commit/f917b750dda9dc977579c264840878a97ed0fdfe)) +* lv{create,resize,extend}, vg{create,reduce,extend,split}: Fix variable leaks. ([b2d985c](https://www.github.com/scop/bash-completion/commit/b2d985c0bf9c0013a86cb63247d67b0ed39c9e75)) +* man: Fix -P/--pager full path arg completion. ([b8cbf1b](https://www.github.com/scop/bash-completion/commit/b8cbf1ba9401fc99375e01cfc122a7ef2aa620f2)) +* tcpdump: Fix -z full path arg completion. ([f009a1b](https://www.github.com/scop/bash-completion/commit/f009a1bfca25e262a68bbe52520bf91531ae6773)) +* valgrind: Fix full path <command> arg completion. ([c6f6080](https://www.github.com/scop/bash-completion/commit/c6f6080569e3572893a6ff6561b3b8182dd2d2c1)) +* vgcreate: Add missing symlink. ([e3a1a49](https://www.github.com/scop/bash-completion/commit/e3a1a49b972d1ade7342cd53a0a47d2589466fa1)) +* lvm: Take option args into account when counting args (RedHat: #860510). ([e96613e](https://www.github.com/scop/bash-completion/commit/e96613e32e21ea389dddba9756bf3d78070acc4b)) +* lvm: Add _lvm prefix to helper functions. ([609034d](https://www.github.com/scop/bash-completion/commit/609034db74f60eab6ae4531696a44849647f7d42)) +* mount: Fix parsing /etc/fstab on *BSD. ([7d59112](https://www.github.com/scop/bash-completion/commit/7d591128a8baf91dfe3a461ae53f7acded4c7473)) +* feh: Fix list of background styles. ([9e04f3e](https://www.github.com/scop/bash-completion/commit/9e04f3edc8e70c5aeef98866e400f772c0395e10)) +* mount.linux: Add options completion for nfs. ([4a76f5a](https://www.github.com/scop/bash-completion/commit/4a76f5a16646ef3c0407e092a66f9f35e273ff81)) +* mount.linux: Add some new mount options intoduced in Linux 3.7 ([74a37e7](https://www.github.com/scop/bash-completion/commit/74a37e7507ff5c779a8cdd271b2aeb80d33bcc96)) +* chronyc: New completion. ([ff11fed](https://www.github.com/scop/bash-completion/commit/ff11fed5f8f1d73b02d515da3af335644807ab4d)) +* scp: Treat strings with slash before colon or starting with [.~] as local. ([41a37d7](https://www.github.com/scop/bash-completion/commit/41a37d767940af7928282874618e3dc60549de54)) +* useradd,userdel,usermod: Add -R/--root arg completion. ([5c8279b](https://www.github.com/scop/bash-completion/commit/5c8279b818560146176372752c4a87c588207674)) +* userdel: Add -h/--help non-completion. ([1d75b67](https://www.github.com/scop/bash-completion/commit/1d75b671a00337ae74a1295682c130649aef3bfe)) +* luseradd,lusermod,luserdel: New completions. ([08203f7](https://www.github.com/scop/bash-completion/commit/08203f7743ea41e7f10a891c130a18be713bd494)) +* man: Don't expand man page extensions too early. ([49ea121](https://www.github.com/scop/bash-completion/commit/49ea121e5d86eea76bfa18174fd8f70911217d09)) +* ssh: Add some -o and related arg completions. ([45c9ff5](https://www.github.com/scop/bash-completion/commit/45c9ff5f691cfb6decdba1bf362708a698b3d595)) +* fix interface completion ([b9b4c6b](https://www.github.com/scop/bash-completion/commit/b9b4c6bf2ce61d46a798f11a4d04bc55ba276b0a)) +* add -p option completion ([89098f7](https://www.github.com/scop/bash-completion/commit/89098f79fd33216a46f7135a994f4c0a8057671f)) +* nc: New completion. ([26991e1](https://www.github.com/scop/bash-completion/commit/26991e1bf4270a95dfea537b7ea514a1130b65bd)) +* tar: Simplify bzip patterns. ([9c80d8b](https://www.github.com/scop/bash-completion/commit/9c80d8b5217df396efa44e0eccf94616bf585013)) +* tar: Recognize taz and tb2 as compressed tarballs. ([e8daf2d](https://www.github.com/scop/bash-completion/commit/e8daf2d2790b90b2abebd63b7a5534f1ea7e446a)) +* ncftp: Add option completion. ([2eeffee](https://www.github.com/scop/bash-completion/commit/2eeffeea7a5c067f4dc0c7645f664cd6232264f0)) +* Avoid sourcing dirs in completion loader to avoid fd leaks (RedHat: #903540). ([fea1c17](https://www.github.com/scop/bash-completion/commit/fea1c178b47cf7ac95ab27c39a98e0464e19976c)) +* Brown paper bag fix for the previous commit. ([c4cc3eb](https://www.github.com/scop/bash-completion/commit/c4cc3eb63bf120cf81e25cb97780fd3e4a91ebff)) +* modprobe: Don't suggest installing already installed modules. ([d08b9f2](https://www.github.com/scop/bash-completion/commit/d08b9f233559b3dced20050ba312b08fe0de53b4)) +* ngrep: New completion. ([8c57295](https://www.github.com/scop/bash-completion/commit/8c572951330bb0ed3a669fd2d8e4dd219430ff11)) +* tshark: New completion. ([cee32c6](https://www.github.com/scop/bash-completion/commit/cee32c6424113a2149daa2830ecb3fa942781420)) +* _mac_addresses: Fix with net-tools' ifconfig that outputs ether, not HWaddr. ([f6df76e](https://www.github.com/scop/bash-completion/commit/f6df76e8cac6ae47b93c87d594d70dab211b860a)) +* _mac_addresses: Try ARP cache with "ip neigh" if arp is not available. ([87dede9](https://www.github.com/scop/bash-completion/commit/87dede96c0fe8961081310284bfe58972dd801c4)) +* wol: Try "ip addr" before ifconfig for finding out broadcast addresses. ([19ce232](https://www.github.com/scop/bash-completion/commit/19ce23282ca6c00b482ac8044b64d91dbb3b62e6)) +* _mac_addresses: Try local interfaces with "ip link" if ifconfig is N/A. ([b78ef32](https://www.github.com/scop/bash-completion/commit/b78ef321bedfdf8071627366de74451967846f98)) +* _ip_addresses: Try with "ip addr" if ifconfig is not available. ([aa516ac](https://www.github.com/scop/bash-completion/commit/aa516acdc537b14541cb16424d51af6403321705)) +* _available_interfaces: Without -a, try with "ip link" if ifconfig is N/A. ([3064e9d](https://www.github.com/scop/bash-completion/commit/3064e9d707404e5aa59bb8b643d02208fb0f9daa)) +* dnsspoof,filesnarf,macof,sshow,tcpkill,tcpnice,urlsnarf: Fix -i completion. ([7543e0b](https://www.github.com/scop/bash-completion/commit/7543e0baf812e24066b863b5d13fdb1efffc3428)) +* arpspoof,dsniff,ether-wake,nmap: Offer active interfaces only. ([9d15e25](https://www.github.com/scop/bash-completion/commit/9d15e25a9e527e2d310ba0e0501e26350998532a)) +* modinfo: Use ,, for lowercasing instead of tr in a subshell. ([06002d0](https://www.github.com/scop/bash-completion/commit/06002d04c7cbfe9ac7c92508b6dcb7323627d07a)) +* pydoc: New completion. ([5c8a002](https://www.github.com/scop/bash-completion/commit/5c8a002008bd2dfdb9196b57c368193a6e05b1e2)) +* pyflakes: New completion. ([a77d3d5](https://www.github.com/scop/bash-completion/commit/a77d3d550564198c11e2b4823a53979868262a48)) +* python, pydoc: Add module completion. ([0e8d34e](https://www.github.com/scop/bash-completion/commit/0e8d34e6bda72787b6b9833e042d3f55d73a4288)) +* pydoc: Complete on keywords and topics. ([44f1065](https://www.github.com/scop/bash-completion/commit/44f1065ada14dda97d3c0417b120207d460e0be0)) +* pylint: New completion. ([f1100ef](https://www.github.com/scop/bash-completion/commit/f1100ef25a69a9910882c5692926cab22c173496)) +* xrandr: Don't leak $i when completing --mode. ([d66fc76](https://www.github.com/scop/bash-completion/commit/d66fc76be6058098d98e07e049db92079268dc0f)) +* xrandr: Cleanups. ([a3d4266](https://www.github.com/scop/bash-completion/commit/a3d4266cab93e2dacf4fc058344f10a0e0860313)) +* xrandr: Avoid --mode completion error when --output is not given. ([225b395](https://www.github.com/scop/bash-completion/commit/225b395b494d8c4f2167429cc58256e5898d1d14)) +* xrandr --mode: Clean up one awk call. ([1e6a791](https://www.github.com/scop/bash-completion/commit/1e6a79196cc4942d24ff78d7955e4c295786e883)) +* xrandr: Use _parse_help. ([ae42c96](https://www.github.com/scop/bash-completion/commit/ae42c9675838fc92a7b77f71c0a4988c8e724822)) +* xrandr: Add bunch of option arg non-completions. ([ba50a54](https://www.github.com/scop/bash-completion/commit/ba50a546418d88cfc45653cb1e91b43764eb9a3b)) +* vipw: Add -R/--root arg completion. ([23a049a](https://www.github.com/scop/bash-completion/commit/23a049a801a6ce2c86e343710cc0245e003df0cb)) +* host: Complete with known hosts. ([eb0be65](https://www.github.com/scop/bash-completion/commit/eb0be65d630e348d8e644fb70d8e2a86b00e3bdc)) +* groupmems: Add -R/--root arg completion. ([250d5eb](https://www.github.com/scop/bash-completion/commit/250d5eb93256bec97be3f5a01a1344939928b978)) +* acpi,chpasswd,dmesg,gkrellm,groupmems,hwclock,lastlog,pwd,vipw: Complete options even without "-" given. ([452e938](https://www.github.com/scop/bash-completion/commit/452e938766c784ce6750f8a718cb90a84b2e9d7d)) +* ip: Remove some stale TODOs. ([06fd510](https://www.github.com/scop/bash-completion/commit/06fd510c44c17db856678e0d572c14b0cebb2e00)) +* ip: Improve addr show and link show completions. ([61fe8d1](https://www.github.com/scop/bash-completion/commit/61fe8d10a8e15285e2ad152017403e8bb609614b)) +* _available_interfaces: Try with "ip link" if ifconfig is N/A also with -a. ([eef7941](https://www.github.com/scop/bash-completion/commit/eef7941842f309491d52a9fef457a8fbb6a4e6a2)) +* make: Don't leak $mode. ([2758c4f](https://www.github.com/scop/bash-completion/commit/2758c4fd7eacafdfd27772e46ccd00731d36931d)) +* (testsuite) Fix pwd unit test. ([23406dc](https://www.github.com/scop/bash-completion/commit/23406dcf20f4718775e8556766be7d55a879a4be)) +* make: Make work in POSIX mode. ([c0818b0](https://www.github.com/scop/bash-completion/commit/c0818b005ab8056bd4bb0a1894bfcd7de148238e)) +* (testsuite) Make pydoc test more likely to work with our limited expect buffer size. ([0837ad0](https://www.github.com/scop/bash-completion/commit/0837ad07d93c62e2b6b9cb917239183d9fbda95a)) +* cpio: Cleanups. ([e1a0759](https://www.github.com/scop/bash-completion/commit/e1a075971d37ed563ad22cc5a1df548a677d67da)) +* cpio: Recognize pass thru when -p is bundled w/other options (RedHat: #912113). ([eb396b5](https://www.github.com/scop/bash-completion/commit/eb396b58a709201e61daf2e381abecb411863b2a)) +* vpnc: Use _parse_help instead of hardcoding options, add basic test case. ([e479610](https://www.github.com/scop/bash-completion/commit/e4796104bc81247bceb591164b227b3cd762c46f)) +* vpnc: Add bunch of option arg (non)completions. ([e7cd7ba](https://www.github.com/scop/bash-completion/commit/e7cd7ba7df96a5a2bc74693fdede77ca06349af0)) +* genisoimage: Use _parse_help instead of hardcoding options, add basic test case. ([e424ed3](https://www.github.com/scop/bash-completion/commit/e424ed3e52f90884377cb2384498b2f907aff1e9)) +* : Line continuation, whitespace, and compgen -W ... -- "$cur" quoting cleanups. ([6185297](https://www.github.com/scop/bash-completion/commit/6185297fc90e82c2788a8f3ea0fd42d54267c499)) +* file-roller: New completion. ([7a1aad7](https://www.github.com/scop/bash-completion/commit/7a1aad780e9f64ad213caed8aa71f45e12294e63)) +* strings: New completion. ([ad8d1f1](https://www.github.com/scop/bash-completion/commit/ad8d1f1a8f879e696956ce0bd7733ef5f3365a6b)) +* ss: New completion. ([12ae7eb](https://www.github.com/scop/bash-completion/commit/12ae7eb21451710492a8bc450e07f6c3bd79a4ec)) +* hexdump: New completion. ([552a2f2](https://www.github.com/scop/bash-completion/commit/552a2f2a94cf03ef6ee8d53ba8bad1dbb52af640)) +* xxd: New completion. ([e38e68f](https://www.github.com/scop/bash-completion/commit/e38e68f96cd7d9d1c973462368003e12661305f9)) +* hexdump: Actually install for hd as well. ([73d1f0f](https://www.github.com/scop/bash-completion/commit/73d1f0f16482b3261291454f37bd9e663fbafaa8)) +* udevadm: Deprecate ours, one is shipped in systemd >= 196 (RedHat: #919246). ([48158ee](https://www.github.com/scop/bash-completion/commit/48158ee3e454fe4f6baf30bc59884962aaf3ce8e)) +* Fix __ltrim_colon_completions() fail on parameter (\$1) containing a glob. ([e191799](https://www.github.com/scop/bash-completion/commit/e191799dea5b38272dba7e5efe60b3adf86311e5)) +* interdiff: New completion. ([796fbbd](https://www.github.com/scop/bash-completion/commit/796fbbdc86e10df67f4930597ce56f9fab5f9457)) +* koji: Complete on build targets when --target is given to wait-repo. ([2f2f127](https://www.github.com/scop/bash-completion/commit/2f2f1278c7ae535d1c3763370e22e7f4083a50e7)) +* lua: New completion. ([99153fb](https://www.github.com/scop/bash-completion/commit/99153fb1ef75b9beec2d85966883bf3e99d095ad)) +* luac: New completion. ([29f5a4a](https://www.github.com/scop/bash-completion/commit/29f5a4a5f4403f246e22fb8c2133e8696d2f0e41)) +* pkg-config: Try to complete --variable= if package name is already given. ([408cb08](https://www.github.com/scop/bash-completion/commit/408cb08051cf18404f89e3fb89c4924cc3fa04ea)) +* tar: Fix completing files inside *.tlz when J is explicitly given. ([d02d940](https://www.github.com/scop/bash-completion/commit/d02d94080d950768bfeb8c830a678da55549f824)) +* tar: Support *.tar.lz (Debian: #703599). ([beaba62](https://www.github.com/scop/bash-completion/commit/beaba62b346bc588d1f9466f338f64073ad2716f)) +* patch: New full featured completion. ([7afc973](https://www.github.com/scop/bash-completion/commit/7afc97366f0a931cb98bd151c5971d4c4c926e59)) +* unzip/zipinfo: Associate with more StarOffice extensions. ([f0a3147](https://www.github.com/scop/bash-completion/commit/f0a3147179ea06bdcd463e2d160df97255656e95)) +* jar: Reuse unzip's xspec (RedHat: #928253). ([3cb64ac](https://www.github.com/scop/bash-completion/commit/3cb64accaf281f6315baa7bced2c72e1eff9d12f)) +* cppcheck: Complete --include= with filenames. ([1a3967c](https://www.github.com/scop/bash-completion/commit/1a3967c8d4d8d9027040e00ecf0756dafaeb88ec)) +* Fix helper script to create changelogs ([4d096e0](https://www.github.com/scop/bash-completion/commit/4d096e0b873478c7b01c5019038c646b7184da60)) +* Releasing 2.1 ([3085c7e](https://www.github.com/scop/bash-completion/commit/3085c7e12179817a02a611016606391295c69942)) + +## 2.0 (2012-06-17) + +* sudo: Handle options (Alioth: #311414). ([91a61af](https://www.github.com/scop/bash-completion/commit/91a61afe59eeca58736e55745ae76ad6641a6a12)) +* sudo: Fix option list parsing ([6621f37](https://www.github.com/scop/bash-completion/commit/6621f37c5dc2cf59ba2c34ee038f5699418e643e)) +* sudoedit: New completion. ([d0a1495](https://www.github.com/scop/bash-completion/commit/d0a14954ab45cb79aba9bff44d5ba910eac7925d)) +* ssh-add: New completion. ([28f15fd](https://www.github.com/scop/bash-completion/commit/28f15fd05c28ee84e79ee2d5f17b5867e682efef)) +* pwd: New completion. ([6943138](https://www.github.com/scop/bash-completion/commit/694313874a8ef025c5bbbf2a57de058fb684e9b9)) +* _command_offset: Properly quote arguments of eval (Alioth: #313499). ([2e97527](https://www.github.com/scop/bash-completion/commit/2e975278c59de9ab6caa5ace65de4b49c6678e65)) +* Fix completion loading when a symlink is sourced, thanks to Jonathan Nieder ([318759c](https://www.github.com/scop/bash-completion/commit/318759c8497cfce3704bc1b97c41459a5be08f7b)) +* Revert "Fix completion loading when a symlink is sourced, thanks to Jonathan Nieder" ([2ad325d](https://www.github.com/scop/bash-completion/commit/2ad325d4afc4ef96aedc7b91c8e75502647c260d)) +* mount.linux: Add some new mount options intoduced in Linux 3.0-3.2 ([1cb1e31](https://www.github.com/scop/bash-completion/commit/1cb1e31e182b0503ea82f9f74c9b43fe91799844)) +* _modules: Ignore error messages. ([db53fc7](https://www.github.com/scop/bash-completion/commit/db53fc77a5349088b24830b490b16dfcc6bee540)) +* modprobe, modinfo, insmod: Move modprobe and modinfo completions to their own files. ([f67818e](https://www.github.com/scop/bash-completion/commit/f67818e023f9afbeef8698fdd3c08eb0f90ad468)) +* sbopkg: Use _parse_help. ([32e8f33](https://www.github.com/scop/bash-completion/commit/32e8f3301801c9ff86f9620ca135f83f71590e29)) +* sbopkg, slackpkg, slapt-{get,src}: Use shorter form of the check if file exists. ([3388314](https://www.github.com/scop/bash-completion/commit/33883145af5e3290105e2f784f84c7468617d5ee)) +* rmmod: Add option completions. ([47c49db](https://www.github.com/scop/bash-completion/commit/47c49dbfec80c43695e4c95c4cc1e5781c685d93)) +* testsuite/generate: Generate less linefeeds. ([068e422](https://www.github.com/scop/bash-completion/commit/068e422222dd862c33137b0d88eab7fe08d9e71e)) +* insmod: Install for insmod.static too. ([d02b4e1](https://www.github.com/scop/bash-completion/commit/d02b4e15e3d130d426bcee1a7b03cc72f6144c90)) +* mplayer: Add -monitoraspect arg completion. ([a90d7d8](https://www.github.com/scop/bash-completion/commit/a90d7d861a53fa7aee6be505678cd43fb578cafc)) +* mplayer: Add generic handling of options that take arguments. ([45c0886](https://www.github.com/scop/bash-completion/commit/45c0886accafd08272fa17c5daad85a1ee52cd56)) +* Workaround bash bug that fails to complete <, > ([6f3d650](https://www.github.com/scop/bash-completion/commit/6f3d650e2309feff4f3e80717409ebccb2d38362)) +* testsuite: Fix spurious modinfo and modprobe test failures on systems that have /lib and /lib64 dirs. ([d7a6fb1](https://www.github.com/scop/bash-completion/commit/d7a6fb1f47d5daafb555f09fb5d9bd544ae99ec6)) +* _filedir: Properly quote paths to avoid unexpected expansion. ([98f90eb](https://www.github.com/scop/bash-completion/commit/98f90ebdf8b7ccf49e7854640712af1ff4a47871)) +* Properly declare 'symlinks' dependencies ([ec7fe00](https://www.github.com/scop/bash-completion/commit/ec7fe0006632f2c008414bb3e8c84fa4862c962f)) +* pigz: Add -p/--processes arg completion. ([cff897e](https://www.github.com/scop/bash-completion/commit/cff897eda8886c93b5b8c0e939588af36983a5f4)) +* apt-get: add 'changelog' to completed commands ([ae98bfa](https://www.github.com/scop/bash-completion/commit/ae98bfa721ff9ff4cd9c64075d2eb7fe01d76828)) +* Really complete 'changelog' ([071ba93](https://www.github.com/scop/bash-completion/commit/071ba93a0b9b5db37dc7c5b4b2423507d8f6b741)) +* su: Add linux-specific completion ([d2aedc8](https://www.github.com/scop/bash-completion/commit/d2aedc83e143e7d506c8c5340dac4a820cc50076)) +* testsuite: Add basic su test case. ([f41d7e2](https://www.github.com/scop/bash-completion/commit/f41d7e2ff660fdf9a95490d4fb438eefa565e9d1)) +* su: Fix long option handling. ([e4fe946](https://www.github.com/scop/bash-completion/commit/e4fe946621d824fe04f5c8a8f4f774342b53df40)) +* su: Add --session-command arg completion. ([e7c4035](https://www.github.com/scop/bash-completion/commit/e7c4035089548efdf9a15fb96a289585b8b322d1)) +* su: Complete -s/--shell with shells instead of all files. ([91528b5](https://www.github.com/scop/bash-completion/commit/91528b527145bec711b4b3ea8c65335a6ed617b0)) +* vmstat: New completion. ([bed5694](https://www.github.com/scop/bash-completion/commit/bed56941110985446aed52302f437c50b8182524)) +* lyx: Remove simple completion, upstream has more complete one (Debian: #662203) ([a062777](https://www.github.com/scop/bash-completion/commit/a062777d4b9c7dc8a51d1e87c938b48fed810232)) +* insmod, modprobe: Don't hardcode path to modinfo (Alioth: #313569) ([199a63b](https://www.github.com/scop/bash-completion/commit/199a63bd4db2020c8d6aaad6723cf881c023c0ff)) +* man: --path option is supported on Darwin (Alioth: #313584) ([fb2d657](https://www.github.com/scop/bash-completion/commit/fb2d657fac6be93a1c4ffa76018d8042859e0a03)) +* man: Move variable declaration to the right place. ([39ac464](https://www.github.com/scop/bash-completion/commit/39ac4642bff9cd9813b8d4b2758b17fe945584cc)) +* testsuite/generate: Tweak linefeeds. ([1fc97c4](https://www.github.com/scop/bash-completion/commit/1fc97c47baf7453b6a27f5e0104c9d434e59acc1)) +* acpi: New completion. ([0ab693c](https://www.github.com/scop/bash-completion/commit/0ab693ca50206e46f23fccba52eeb8516e2e6fc9)) +* hwclock: New completion. ([3d7102b](https://www.github.com/scop/bash-completion/commit/3d7102b9a5b138091122bad601cc3c104df0ce8f)) +* feh: Update option argument completions. ([d2a3db0](https://www.github.com/scop/bash-completion/commit/d2a3db0b7a0cfc7e0da037a003873c19b8fc22a2)) +* fbi, feh: Complete more supported file formats. ([63574c8](https://www.github.com/scop/bash-completion/commit/63574c8f14fb813bea08e59e43a170ff0f4cf592)) +* fbgs: Add new options introduced in fbida-2.09. ([4710d1b](https://www.github.com/scop/bash-completion/commit/4710d1bf48f9fde1becfcc902aa1c91312a58a91)) +* cppcheck: Complete new --relative-paths option arguments ([587d268](https://www.github.com/scop/bash-completion/commit/587d26834ac7116afedfdad86f6cc7a931fbf57d)) +* ri: Rename ri_get_methods helper to add leading underscore ([8b3f19a](https://www.github.com/scop/bash-completion/commit/8b3f19a82e60c725f8588a91b1679dde4b1b1967)) +* _expand: Suppress unwanted bash error messages (Alioth: #313497) ([ccda61d](https://www.github.com/scop/bash-completion/commit/ccda61d928505abfa839a2c048e3b3d7f89d3a9e)) +* make: Add generic variable completion. ([f7240b8](https://www.github.com/scop/bash-completion/commit/f7240b82a4d45f03b741f11b771fae17d3c1c713)) +* man: Recognize 3gl as man page filename extension -- at least Mesa uses it. ([739c6d2](https://www.github.com/scop/bash-completion/commit/739c6d2833370e618fcdc37b5a72c15426313fae)) +* _realcommand: Try greadlink before readlink (Alioth: #313659). ([32f2239](https://www.github.com/scop/bash-completion/commit/32f223963a013e4875c999109c0a2fa8f9a0ecdf)) +* Comment spelling fix. ([f990d5e](https://www.github.com/scop/bash-completion/commit/f990d5e617954c57e73209dba8a8061f87d538a4)) +* Spelling fix. ([7532eda](https://www.github.com/scop/bash-completion/commit/7532eda90ff631611e003e9b51dca8a0e558e95c)) +* qiv: Add *.svg. ([e0dc594](https://www.github.com/scop/bash-completion/commit/e0dc594d2aabc5040ce0cf53bb73e14f60218025)) +* xmllint: Add *.svgz. ([b54aded](https://www.github.com/scop/bash-completion/commit/b54adedd4f158ac41ecd6a8c6cc7d8faf51dc069)) +* add xz compression extension for kernel modules ([67d30da](https://www.github.com/scop/bash-completion/commit/67d30da6b79cf7983058a1840bce215990094246)) +* autotools: Use MKDIR_P instead of mkdir_p (Alioth: #313671). ([f8ac6a5](https://www.github.com/scop/bash-completion/commit/f8ac6a5aeb287763341e4db2dacd1eb2c3cdecf6)) +* lbzip2: Add -n argument completion. ([d141f9c](https://www.github.com/scop/bash-completion/commit/d141f9c6ebd8659638de9d5de64e202ac1f450c0)) +* _tilde*: Escape tilde in [[ $1 == \~* ]] tests (RedHat: #817902). ([709d6e0](https://www.github.com/scop/bash-completion/commit/709d6e06902df7205280d0626995fc5b6abe6e89)) +* scp: Recognise symlinks to directories as directories (Debian: #666055). ([89acac9](https://www.github.com/scop/bash-completion/commit/89acac9910a27cc9428314e66c3bdbfc48c65f41)) diff --git a/CHANGES b/CHANGES deleted file mode 100644 index 7a26a1b..0000000 --- a/CHANGES +++ /dev/null @@ -1,3141 +0,0 @@ -bash-completion (2.11) - - [ Alexander Meshcheryakov ] - * _known_hosts_real: check that ruptime is present before calling - (#390) - - [ Andrew Gaul ] - * totem: reuse kaffeine completions (#372) - - [ Damien Nadé ] - * __reassemble_comp_words_by_ref: avoid triggering nounset on - indirect references - - [ Felix Lechner ] - * lintian: complete paths for Ubuntu's .ddeb and Debian's buildinfo - files (#397) - - [ Felix Yan ] - * ip: complete route add table arg - * ip: style fixes similar to ip-netns - * ip: add more completions for ip-rule - * ip: add support for netns (#391) - * ip: improve completion of route subcommands (#326) - - [ Hans-Christoph Steiner ] - * unzip, zipinfo: complete *.aar (#428) - - [ Jakub Jelen ] - * ssh: add new -Q completions in OpenSSH 8.2p1 (#400) - - [ Kevin Locke ] - * python: support executables with minor version (#389) - - [ Michal Suchánek ] - * insmod, modinfo, modprobe: support xz compressed modules (#401) - - [ Phan Duc Nhat Minh ] - * tshark: complete -r arg with all filenames (#422) - - [ Sebastian Jakubiak ] - * openssl: update -starttls completions (#403) - * _filedir*: update link to bug-bash discussion on -X (#404) - * test/python: add testcase for submodule completion - - [ Ville Skyttä ] - * Release 2.11 - * extra/make-changelog: check and output usage message - * pre-commit: anchor exclude patterns - * pytest: rewrite in bash, support toplevel funcs, avoid nondef ones - and classes - * test/xfreerdp: skip --help failure cases - * test/tshark: fix multiple -O completion with no http2 support - * test/ant: avoid complete-ant-cmd.pl interference with ANT_ARGS - * _xinetd_services: avoid nounset error on bash 4.2 - * pre-commit: upgrade isort to 5.1.4 - * pre-commit: upgrade pyupgrade to 2.7.2 - * pre-commit: add pyupgrade, run it - * test/ant: gitignore all target cache files - * _known_hosts_real: exclude Host negations - * pre-commit: upgrade isort to 5.0.7 - * pre-commit: update shellcheck-py URL - * test/inputrc: do not set print-completions-horizontally - * test/inputrc: comment typo fix - * pytest: complete async test class methods - * __get_cword_at_cursor_by_ref: fix regression on bash 4.2 - * test: upgrade markdownlint-cli to 0.23.2 - * _known_hosts_real: avoid errors in nounset mode on Ubuntu 14 and - 16 - * _longopt: exclude too many dashes, allow underscores, require ends - with alnum - * _included_ssh_config_files: support globs - * _known_hosts_real: prevent unwanted pathname expansion on host - entries - * test/shfmt: upgrade to 3.1.2, reformat with it - * test/_known_hosts_real: add explicit no globbing test case - * test: upgrade mypy to 0.782 - * CONTRIBUTING.md: add posix and nounset mode item - * test: upgrade mypy to 0.781 - * test: upgrade perltidy to 20200619 - * _known_hosts_real: fix completion of Host entries after a wildcard - etc - * _known_hosts_real: fix # handling in ssh configs - * test: upgrade flake8 to 3.8.3 - * test/xhost: multiple expected result handling fixes - * test/slapt-src: single expected result handling fixes - * test: partial hostname completion fixes - * test: simplify completion parsing - * test/dpkg-query: mark as xfail on non-Debian based systems - * .gitignore: clean up some no longer needed ignores - * test/lspci: skip -A arg test if lspci fails -A help, e.g. busybox - lspci - * test: regex escape our magic mark for completeness - * test: upgrade mypy to 0.780 - * test/_known_hosts_real: don't modify class scoped base expected - list - * test/_known_hosts_real: reset COMP_KNOWN_HOSTS_WITH_HOSTFILE - between tests - * test/_known_hosts_real: tolerate duplicates - * bash_completion: trivial cleanups - * gcc: avoid errors in nounset mode - * pytest: fix test class method completion with BSD awk - * man, mutt: avoid errors in nounset mode on Ubuntu 14 and 16 - * java, make: avoid errors in nounset mode on Ubuntu 14 and 16 - * README: document GNU make build requirement - * pytest: add test class method completion - * _known_hosts: avoid errors in nounset mode and no arguments - * bash_completion: fix array set checks with empty elements in them - * *: avoid more errors in nounset mode - * cfrun: fix $hostfile leak - * _command_offset, route: cleanups - * *: avoid more errors in nounset mode - * qemu: add -machine arg completion - * qemu, sbopkg: avoid unintentional globbing on option arg - completions - * test: enable shellcheck SC2035 - * *: drop support for bash 4.1 - * _init_completion: fix unassigned redirect completion in nounset - mode - * ip: route shfmt, arithmetic evaluation - * _filedir: avoid unbound variable error on Ubuntu 14 and 16 - * _pids, _pgids, _pnames: improve shfmt formatting - * scp, sftp, ssh: fix completion on options bundled with -4/-6 - * modprobe, tshark, _included_ssh_config_files: use [[ ]] instead of - [ ] - * test/runLint: warn about [ ] instead of [[ ]] use - * test: skip various tests if we don't get a useful usage message - * *: mark nounset mode as supported, issues with it are bugs now - * *: avoid more errors in nounset mode - * *: avoid more errors in nounset mode - * *: avoid more errors in nounset mode - * test/inputrc: comment and whitespace tweaks - * *: avoid more errors in nounset mode - * test/unit: sort files included in dist - * test/unit: include test_unit_known_hosts_real.py in dist - * bash_completion: line wrapping tweaks, NFC - * 7z: fix -o/-w attached arg completion - * postfix: try to arrange a fake tty so we can tickle the usage - message out - * _bashcomp_try_faketty: new function to try running command with a - fake tty - * mr: avoid herestrings, simplify command parsing - * test/mr: handle missing "clean" with skipif - * test: mark known non-ASCII issues with test suite as xfail - * dpkg-deb: add --raw-extract and -X arg completions - * test: add some dpkg-query test cases - * dpkg-deb: fix --show/-W completion - * test: upgrade markdownlint-cli to 0.23.1 - * *: use more arithmetic evaluation - * test: try harder to restore environment and cwd on failures - * *: use $ifs for storing/restoring $IFS - * test/irb: xfail options test if --help is not available - * test: upgrade flake8 to 3.8.1 - * test: pre-commit config cleanups, ordering - * test: upgrade pre-commit to 2.4.0+, drop shfmt kludge - * test: sync shfmt and shellcheck configs - * test: shfmt bashrc - * test: remove unused run-shellcheck, shellcheck is in pre-commit - now - * test: remove old test suite code no longer used \o/ - * test/_known_hosts_real: port remaining test cases to - pytest+pexpect - * test: remove more no longer needed old test suite code - * test/_known_hosts_real: port more test cases to pytest+pexpect - * test/_get_cword: port remaining test case to pytest+pexpect - * test: replace some echos with printfs - * test/_filedir: fix shutil.rmtree on Python < 3.6 - * test/_expand: port remaining test cases to pytest+pexpect - * test: drop some no longer needed old test suite code - * test/_filedir: port remaining test cases to pytest+pexpect - * test: run all Travis jobs on dist: bionic - * test: drop not needed sudo on Travis - * test/_filedir: port more test cases to pytest+pexpect - * test/__expand_tilde_by_ref: port remaining test cases to - pytest+pexpect - * test/_get_comp_words_by_ref: convert remaining test cases to - pytest+pexpect - * test: run pytest --verbose in docker - * lftp: use "bookmark list" command to list bookmarks - * test: drop some no longer needed old test suite code - * test/slapt-src: convert remaining test case to pytest+pexpect - * _xfunc: simplify - * apt-cache: avoid nonzero exit code from _apt_cache_packages - * test/slapt-get: convert remaining test case to pytest+pexpect - * test/secret-tool: add to test command list - * test/scp: port remaining test case to pytest+pexpect - * test/umount: convert remaining test case to pytest+pexpect - * secret-tool: new completion - * apt-get: complete build-dep with dirs - * travis: use golang 1.14 for shfmt - * *: run all shell code through shfmt -s - * pre-commit etc: add shfmt - * test: fix incorrect fixtures/shared/default xfails/expectations - * test: upgrade markdownlint to 0.23.0 - * nmap: simplify help scraping a bit, don't try to emit unnecessary - newlines - * test: prefix fake test commands with underscore - * test: port most umount test cases to pytest+pexpect - * test: add note about unescaped assert_complete single return - values - * editorconfig: apply yaml settings to .yaml too - * pre-commit: use local perlcritic hook - * *: doc and comment link updates - * pre-commit, *.md: add markdownlint, address findings - * README: clarify loading automatically on demand - * ssh-keygen: -O arg updates and improvements - * ssh-keygen: add -b arg completions according to specified -t - * ssh-keygen: option and arg completion updates for new versions - * _command: improve commentary - * reportbug, scp, sftp, svn: use compgen -c instead of _command - * find: fix -exec etc argument and its completion - * extra: trigger docker builds only on test-cmd-list.txt changes - * test: add script to maintain list of executables for full test - coverage - * test: run lint tests on Travis in a quickish separate first stage - * test/make: mark more cases as requiring command - * make: add bmake alias - * test: run pre-commit on host instead of docker - * test: add perlcritic to pre-commit, run on all perl - * *: remove some unused variables, thanks to shellcheck SC2034 - * *: various loop iteration improvements - * crontab: fix loop over already given args - * apt-cache: fix command mode handling - * doc: add loop variable naming guideline - * test: make at-point completion tests easier - * ssh, xsltproc: address shellcheck SC2006 - * scp: work around shellcheck SC1003 - * mutt: address shellchec SC2236 - * wget: address shellcheck SC2116 - * pytest: address shellcheck SC2002 - * bash_completion, java, tipc: for loop whitespace consistency - tweaks - * *: more arithmetic evaluation cleanups, thanks to shellcheck - SC2004 - * __reassemble_comp_words_by_ref, java: address and work around - shellcheck SC2102 - * test: enable parallel pre-commit shellcheck - * test: remove shellcheck severity filter, add explicit disables - instead - * doc: recommend arithmetic evaluation - * *: array subscript cleanups - * ssh-keygen: -s and -n completion improvements - * *: enable and address shellcheck SC2053 - * bash_completion, invoke-rc.d, svcadm: trivial cleanups - * *: replace various conditional expressions with arithmetic - evaluation - * carton: fix command parsing with BSD sed - * nmap: fix option parsing with BSD sed - * test/alias: port remaining test case to pytest+pexpect - * test: generalize complete at point test - * test/cd: fix test_dir_at_point for setups that repeat "trailer" - * pytest: add some option arg (non-)completions - * pytest: complete test classes - * pgrep, pkill: add --ns and --nslist arg completions - * test: run skipif and xfail commands without caring if they output - or not - * test: make it possible to not care whether command did output or - not - * test/xfreerdp: skip xfreerdp kbd test if kbd-list returns empty - * test: tolerate duplicates from compgen actions - * test: bump shellcheck severity to warning + some disables - * *: address shellcheck SC2046 - * test/lib/library.sh: address shellcheck SC2125 - * java, pkgadd, sysbench: address shellchec SC2124 - * scp: address shellcheck SC2089 and SC2090 - * _filedir_xspec: address shellcheck SC2140 - * rpm, ssh, umount.linux: address shellcheck SC2120 - * cvs, modprobe, sh: address shellcheck SC2209 - * mutt: address shellcheck SC2088 - * _upvar, _upvars, _variables, rpm: address shellcheck SC1083 - * test/run: address shellcheck SC2164 - * renice: address shellcheck SC2254 - * tipc: comment grammar and spelling fixes - * man, perl, route, tipc: address shellcheck SC2053 - * info, java: address shellcheck SC2153 - * quote_readline: fix $ret leak - * test: upgrade shellcheck to 0.7.1 - * test/printenv: xfail if --help doesn't contain options (e.g. - busybox) - * test/aptitude: require command where necessary - * _known_hosts_real, op: address shellcheck SC2184 - * test: don't run shellcheck on completions/.gitignore - * protoc: complete all --*_out without more specific handling with - dirs - * sysbench: add --test= deprecation TODO - * pkgadd: indentation fix - * chronyc, wvdial: address shellcheck SC2178 - * java, pkgadd, sysbench: address shellcheck SC2124 - * mplayer: address shellcheck SC1078 false positive - * smartctl: hush shellcheck SC2054 false positives - * *: address shellcheck SC2221 and SC2222 - * bash_completion: address shellcheck SC2220 - * crontab, wodim: silence shellcheck SC2191 and SC2192 - * aptitude: add some option arg (non)completions - * aptitude: parse options list from --help, hardcode less - * test/aptitude: add some test cases - * *: argument interation improvements - * *: whitespace tweaks - * apt-get etc: use _apt_cache_packages from apt-cache - * pre-commit: run most python checks on helpers/python too - * test/ldd: xfail if --help is not implemented - * test/printenv: require command for arg completion test - * printenv: indentation fixes - * test: upgrade mypy to 0.770 - * test: split dependencies requiring Python 3.6.1+ to requirements- - dev.txt - * git: trigger docker rebuild on pre-commit config change - * test: require openssl command for option argument tests - * test: move perltidy to pre-commit, run with --converge - * test: move shellcheck to pre-commit - * test: ignore flake8 messages that are in black's domain - * _xinetd_services: look up from $BASHCOMP_XINETDDIR, add some unit - tests - * printenv: new completion - * copyright: add 2020 - * test: fix CompletionResult.__eq__ UnboundLocalError - * test: run pre-commit in tools container - * test: shellcheck tweaks - * test: add isort to pre-commit, run it - * test: add flake8-bugbear - * test: install black for Python 3.6 too - * pre-commit: add config with black, flake8, and mypy - * test: drop redundant black args from docker runs - * *: python type hint fixes and improvements - * extra/make-changelog: run through black - * test/totem: add basic test case - * test/cd: remove unused import - * openssl: complete -writerand with filenames - * openssl: parse available options from $command -help - * openssl: support getting digest list from more recent openssl - versions - * nmap: handle options split on equals sign - * nmap: parse options from -h output - * test/cd: make dir_at_point produce better debuggable failures - * test/cd: convert remaining test case to pytest+pexpect - * test: remove some no longer needed old test suite code - * test/chown,sudo: parametrize special case test, improve xfail - targeting - * test/tsig-keygen: require command for test_options - * test/upgradepkg: port remaining test case to pytest+pexpect - * tsig-keygen: new completion - * test: host helper lint and usage fixes - * test: port some _known_hosts_real unit tests to pytest+pexpect - * test: remove some no longer needed tcl/expect code - * test: fix spurious hosts fixture failure without avahi-browse - installed - * test: port some scp test cases to pytest+pexpect - * test: port remaining finger, sftp, ssh, and xhost cases to - pytest+pexpect - * lilo: work around shellcheck false positive - * test/ipcalc: fix tests with busybox ipcalc - * chromium-browser, firefox: complete on *.txt (#379) - * README.md: add introduction - * ipcalc: new completion - * *: complete commands when prefixed with a backslash - * test/wol: don't fail MAC test if test system has /etc/ethers - entries - * test/dnssec-keygen: allow more alternatives in algorithm - completion - * lilo: don't complete on commented out labels - * lilo: honor -C when completing labels - * lilo: add -B and -E completions - - [ beantaxi ] - * Source user completion only if it's a file (#409) - - [ hugoziviani ] - * jarsigner: complete on *.apk too (#386) - * cryptsetup: add luksChangeKey arg completion (#380) - - -- Ville Skyttä <ville.skytta@iki.fi> Sat, 25 Jul 2020 11:25:09 +0300 - -bash-completion (2.10) - - [ Felix Lechner ] - * perltidy: associate *.t (#338) - - [ Gabriel F. T. Gomes ] - * perl: fix completion with space between option and argument - - [ Grisha Levit ] - * _variables: add TERM and LC_* completion (#353) - - [ Iñigo MartÃnez ] - * autotools: Replace pkgdatadir with datadir - * pkg-config: Relative paths - * pkg-config: generate Name from autotools PACKAGE - - [ Jakub Jelen ] - * ssh: option and argument completion updates (#332) - - [ MichaÅ‚ Górny ] - * test_arp: Skip if ARP tables are empty - * test_chromium_browser: Skip test_2 if 'chromium-browser --help' - fails - * test_rpm2tgz: Fix expected output - - [ Sebastian ] - * cppcheck: Add new standards to --std option. (#356) - - [ Tomasz N ] - * apt-get: fix pkg version completion if it contains a colon (#351) - - [ Ville Skyttä ] - * test: bump black to >=19.10b0 - * ssh, scp, sftp, ssh-copy-id, curl: improve identity file - completion - * update-rc.d: indentation fix - * update-rc.d: remove dead code - * screen: add serial device basic arg (non)completion - * screen: add //telnet completion - * test: add some trivial perl -E/-e cases - * perl: indentation fixes - * curl: make @filename completion do the right thing with dirs - * _filedir: avoid duplicate dirs internally, and a compgen -d call - for files - * _filedir: remove unused $x - * bash_completion.sh: shellcheck SC2086 fixes - * test: shellcheck config cleanups - * shellcheck: add some option arg (non)completions - * test: fix cpio users test in presence of usernames with whitespace - * test: python typing fixes - * test: add minimal mypy config - * .gitignore: mypy cache - * makepkg: fix option completion - * test: mark dcop and mr testcases requiring the cmd as such - * CONTRIBUTING: disable e-mail bug gateway due to spam - * carton: new completion - * op: direct command parsing stderr to /dev/null - * test: adjust java expectations based on whether jars can be listed - * valgrind: look tool names from lib/*-linux-gnu dirs too - * test: xfail locale-gen option completion if --help is not - available - * _sysvdirs: always return 0 - * java: don't assume jar is installed - * travis: test with Debian 10 - * wine: install for wine-development and wine-stable too - * travis: generate dist tarball on alpine - * dmypy: new completion - * test: add require_longopt xfail helper, use it - * test: mark more tests that parse command output as requiring - command - * sysctl: invoke completed sysctl instead of one from path to get - variables - * screen, smartctl, update-alternatives: _parse_help, drop hardcoded - option list - * lintian-info: _parse_help, add more option arg (non)completions - * gprof: _parse_usage, drop hardcoded option list - * test: fix retrieving command to test from request - * travis: pass NETWORK as env var, so we can actually use it - * test: xfail MAC address completion without networking - * test: ignore _makepkg_bootstrap in makepkg test env - * test: hush flake8-bugbear B010 - * test: don't sort expected completion lists under the hood - * test: add bunch of basic option parsing test cases - * test: always run tests which don't require tested command - * test: explodepkg and upgradepkg test fixes - * test: mark sbcl-mt xfail due to whitespace split issues - * _terms: search directly from various terminfo dirs - * _terms: combine and simplify somewhat - * pkg-get: fix $i leak - * pkgutil: fix $i leak - * test: portinstall/upgrade test case and setup fixes - * lvm pv*, vg*: parse help instead of hardcoding option list - * ipv6calc: parse help instead of hardcoding option list - * test: avoid some sed -r/-E runLint false positives - * test: use sh +* as ccache command test case - * java: make jar/zip listing work with unzip - * test: installpkg test fixes - * test: fix acroread fixture dir - * test: remove unnecessary returns after pytest.skip - * test: avoid gnome-mplayer core dump on Ubuntu 14 - * xvfb-run: new completion - * test: skip gssdp-discover --message-type when option not available - * test: expect failures for bc without --help useful with _longopt - * test: don't expect a .tox dir in fixture - * test: drop sourcing our no longer existing profile.d script - * tox: include -- in option completions - * tox: complete defaults after a -- - * gssdp-discover: new completion - * test: register our pytest markers to hush warnings from 4.5+ - * test: fix required pytest version - * ip: invoke the tool as $1 - * README: drop distro badges, link to Repology instead - * chromium-browser: add --proxy-server arg completion - * test: source our profile.d test env script in docker - * influx: new completion - * README: badge title tweaks - * tox: do simple parse on tox.ini if --listenvs* yields nothing - * test: add basic tox fixture - * man: fall back to _parse_usage for _parse_help - * test_wsimport: xfail options test on unparseable -help - * test: don't try to install black on Python < 3.6 - * pgrep: fix fallback to _parse_usage - * test: xfail unparseable mock and munin-node-configure --help cases - * test_pwdx: xfail more unparseable help cases - * build: make pytest executable configurable, look for pytest-3 too - * test: enforce minimum pytest version - * test: zopflipng flake8 fix - * test: xfail getent and pwdx option completions with unparseable - --help - * test: add more basic _parse_help use test cases - * test: add bunch of basic _parse_help use test cases - * .gitignore: add configure.lineno - * badblocks: fix $i leak - * postfix: option completion is expected to fail at the moment - * cal: try _parse_help before _parse_usage - * test: add bunch of basic _parse_usage use test cases - * chsh, pwck: try _parse_help before _parse_usage - * test: add basic autossh test - * test: convert more _filedir unit tests to pytest+pexpect - * test: flake8 fix - * test: convert bunch of _filedir unit tests to pytest+pexpect - * test: convert finger partial test case to pytest+pexpect - * README: add some badges, tweak existing - * test: port _variables unit tests to pytest+pexpect - * test: port compgen and quote tests to pytest+pexpect - * iconv, lz4, tipc, xsltproc: replace some seds with compgen -X - * test: disallow Alpine failure on Travis - * _pnames: adapt for busybox ps, rewrite in pure bash - * test: run our docker script in test containers by default - * test: use one Dockerfile for all dists - * test_ifup: accept short option completions too - * timeout: fallback to _parse_usage from _parse_help - * test_wget: test --s instead of --h - * test_lsusb: xfail with unparseable --help - * test: expect failures for various completions without useful - --help - * test: support xfail in our markers like skipif, use it a lot - * test: add Alpine Linux container, allow failures for now - * iconv: weed out ... from encoding completions - * test_iconv: add basic file completion test - * test_iconv: skip option completion if --help fails - * test_getconf: skip if -a doesn't output any POSIX_V* - * test_feh, test_makepkg: invoke grep as "command grep" - * test: generalize check whether we're being run in a container - * tar: simplify locating tarball from command line - * pkg_delete: don't limit to FreeBSD - * test: reformat test_chromium_browser.py source - * test: set up BASH_COMPLETION_COMPAT_DIR in bashrc (only) - * test: more thorough system location interference avoidance - * test: bashrc comment and whitespace tweaks - * build: makefile whitespace tweaks - * build: really reset return value before completions check - * build: simplify symlink setup - * tar: add missing bsdtar, gtar, and star symlinks - * README: use light gray badges for unknown versions - * README: link to cygwin package - - [ Wolf ] - * ri: hush some warnings - - [ andreabravetti ] - * unrar: complete on *.exe (#337) - - [ ezr ] - * chromium-browser: Add support for .mhtml files - - [ jerkey ] - * screen: complete first arg with serial devices - - [ marxin ] - * gcc: support new --completion option (#222) - - [ pcc ] - * unzip, zipinfo: complete *.aab (#340) - - [ versat ] - * cppcheck: Remove deprecated option 'posix' for '--std=' - - -- Ville Skyttä <ville.skytta@iki.fi> Thu, 05 Dec 2019 17:04:26 +0200 - -bash-completion (2.9) - - [ Antonio Terceiro ] - * dpkg-source: Add --before-build --after-build --commit, and - --print-format - - [ Gabriel F. T. Gomes ] - * xm: Deprecate completion for obsolete command (#284) - * _filedir_xspec: Fallback to suggesting all files if requested - (#260) - * tar: Support completions for zstd compression extensions (#255) - * dpkg: List held packages (#250) - * cvs: Add completion for the log command - - [ Guillaume Mella ] - * unzip, zipinfo: Associate with *.xar (eXist-db application - package) (#257) - - [ Igor Susman ] - * mplayer: Associate with *.w64 - - [ Jaak Ristioja ] - * okular: Added support for xz-compressed files. - - [ John Swinbank ] - * _xspecs: Declare as global on bash >= 4.2 - - [ Kevin Locke ] - * test: Increase expect pty to 160 columns - * test: avoid interrupting magic mark output - - [ Per Lundberg ] - * 7z: add .msi support - - [ Peter Wu ] - * tshark: speed up tshark -O completion - * tshark: fix completion of -Xlua_script option - * tshark: Support preferences (-o) completion with memoization - * test: fix misinterpretation of completion output in tests - * test: fix flake8 complaints about unused imports - * conftest: fix RemovedInPytest4Warning due to use of - node.get_marker - * chromium-browser: consider chrome and chromium as aliases - * tshark: support .gz and .cap files for -r expansion - * tshark: prevent a single-character file from breaking -G - completion - * tshark: update -T and -t completions - - [ Russell Davis ] - * man: Fix completion when failglob option is enabled (#225) - - [ Timo Taipalus ] - * mplayer: Add common supported module music formats - - [ Tomasz N ] - * _longopt: pick first long option on a line, not last - - [ Ville Skyttä ] - * *: avoid shellcheck SC1007 and SC1010 - * 7z: add some TODO notes on parsing "i" output for extensions - * ssh: make -o protocol completion less hardcoded - * ssh: make option completion case insensitive - * ssh: fix suboption completion with combined -*o - * xvnc4viewer: code cleanups - * doc/testing: remove lots of legacy info, add some new - * CONTRIBUTING: add upstream vs bash-completion considerations - * CONTRIBUTING: note runLint and run-shellcheck - * __parse_options, 7z: avoid herestrings - * arp, ccze, ifstat, inotifywait, makepkg: invoke sed with "command" - * shellcheck: disable bunch of warnings when in "-S warning" mode - * test: move default shell option from run-shellcheck to - .shellcheckrc - * test: make runLint search for herestrings - * tar, valgrind: avoid some herestrings - * travis: run shellcheck on bash_completion.sh.in too - * travis: fail on shellcheck errors - * make: quote eval array definitions to work around shellcheck - SC1036 bug - * test: add make -C test case - * *: shellcheck error fixes - * _included_ssh_config_files: store found included files in an array - * _included_ssh_config_files: doc grammar fixes - * test: add invoke-rc.d test case for not repeating already given - options - * ebtables: improve existing table arg parsing - * test: add script to run shellcheck, run it in Travis, allowing - failure for now - * iptables: improve existing table arg parsing - * test: shorten long gdb test core file name so tar doesn't croak on - it - * AUTHORS: remove unrelated project association from my entry - * apt-get: protect source against regex specials - * mypy, mysql, xmms: don't complete unknown split long option args - * synclient: remove unused local variable "split" - * test: adjust _get_comp_words_by_ref test to changed error output - * apt-cache: protect showsrc against regex specials - * test: improve tshark -O arg completion test - * tshark: ignore stderr when parsing -G, -L, and -h output - * *: error output consistency, use bash_completion prefix - * _upvar: deprecate in favor of _upvars - * *: add missing "ex: filetype=sh" - * phing: fix getting just a tab for options on CentOS 6 - * phing: don't complete -l with files - * various: apply file vs dir special cases also when invoked with - full path - * *: whitespace tweaks - * ssh: don't offer protocol v1 specific options if it's not - supported - * test: add some gdb non-core files - * _parse_help: look for long options somewhat more eagerly - * gdb: relax core filename pattern - * test/tools: fix exit status incrementation - * *: arithmetic expression related cleanups - * test/tools: run all tools, don't stop at first failure - * test: check for perltidy errors and warnings - * *: format Perl code with perltidy - * *: format Python code with black - * .dir-locals.el: use flycheck-sh-bash-args - * valgrind: look up tools from libexec dirs too - * *: make _parse_usage fallbacks more concise - * svn, svk, wget: use _iconv_charsets - * *: spelling fixes - * msynctool: code cleanups - * *: remove whitespace after redirections - * *: remove spaces immediately within $() - * bzip2: recognize *.tbz2 as bzipped - * modprobe: module parameter boolean values - * ping, tracepath: parse options primarily with _parse_help - * ulimit: new completion - * shellcheck: new completion - * dnssec-keygen: new completion - * modprobe: append = to module parameter completions - * test: include test_unit_longopt.py in dist - * test: add some _longopt unit tests - * _longopt: simplify regex, use printf instead of echo, drop - unnecessary sort - * nsupdate: new completion - * _longopt: don't complete --no-* with file/dirname arg - * copyright: add 2019 - * pytest: complete --pythonwarnings/-W arg - * python: make warning action list reusable - * test: use pytest-xdist - * extra: add git pre-push hook for triggering Docker Hub builds - * post-commit: trigger on test/requirements.txt too - * pytest: complete pytest-xdist --dist, --numprocesses, and - --rsyncdir - * test: remove no longer needed completion/*.exp - * xfreerdp: reinstate support for old versions with dash option - syntax - * test: rewrite "generate" in Python, fix trailing backslash in - EXTRA_DIST - * test: sort t/Makefile.am EXTRA_DIST in C locale - * ssh: support RemoteCommand and SyslogFacility options - * test: Expect failure for chown all users test as non-root - * test: Fix declare test case with bash 5.0 - * adb: Deprecate in favor of one shipped with the Android SDK - * xfreerdp: Update for more modern xfreerdp - * jsonschema: New completion - * test: Remove unnecessary ri xfail - * test: Clean up man tmp dir - * .gitignore: Add .python-version (for pyenv) - * test: Remove unnecessary autouse=True from fixtures - * ifstat: Make work with iproute2 version - * iperf, iperf3: Add some option arg (non-)completions - * test: Fix test generation wrt results checking improvements - * ifstat: New completion - * __parse_options: Avoid non-zero exit status - * test: Refactor/improve completion results checking - * test: Match Python's default locale unaware sort in bash setup - * test: Rename completion.line to .output - * test: Add man failglob test case - * test: Add pre_cmds support for completion fixture - * inotifywatch: New completion, common with inotifywait - * inotifywait: Fix -e completion with BSD sed - * inotifywait: Avoid some false positive event names - * test: extend _ip_addresses unit tests some - * _ip_addresses: Avoid completing ipv4 ones with -6 - * inotifywait: New completion - * test: Mark some xfails based on if in docker instead of in CI - * test: Skip ifup options test if it doesn't grok --help, not in CI - * test: Clean up and docker-ignore __pycache__ dirs - * build: Include test/t in dist tarball - * test/t: Avoid trailing backslash in Makefile.am's to appease - automake - * test: Remove some no longer used old test suite code - * _xspecs: Simplify bash version check - * chmod: Fix "-" completion - * sysctl: Treat -f as alias for -p/--load - * .gitignore: Add pytestdebug.log - * chmod: Fix file completion after modes starting with a dash - * _count_args: Add 3rd arg for treating option-like things as args - * test: Fix _count_args test_7 to test intended case - * pydocstyle: New completion - * Travis: Remove unused PYTEST env var - * doc: Note email issues gateway - * tcpdump: Various option and their arg completion updates - * test: Fix arp CI (non)expectations, remove redundant test case - * test: Be more consistent with "CI" env var examination and xfails - * arp: New completion, somewhat incomplete - * test: Expect failure in gkrellm if there's no X display - * doc: Update docs on generating simple tests - * doc: Some test dependency doc updates - * test: Add requirements.txt for installing dependencies - * grpck: Parse options with _parse_help, falling back to - _parse_usage - * grpck: Add --root/-R arg completion - * test suite: Ignore _scp_path_esc in env for ssh-copy-id - * ssh-copy-id: Add -i and -o arg (non-)completions - * tar: Clean up some redundant code - * cancel: Split long line - * cancel: Add some option arg (non-)completions - * locale-gen: New completion - * makepkg: Don't apply to other than Slackware makepkg - * test: Allow unknowns options in makepkg option completion - * makepkg: Use _parse_help instead of hardcoding option list - * mypy: New completion - * op: New completion - * hunspell: New completion - * xmllint: Improve --encode, --pretty, and --xpath arg - (non-)completions - * test: Remove leftover completion/ls.exp - * gcc: Add g++, gcc, gccgo, and gfortran *-[568] aliases - * perlcritic: New completion - * gnome-screenshot: New completion - * isort: New completion - * freeciv: Option and arg completion updates - * freeciv-gtk2: Install for freeciv and freeciv-gtk3, rename to - freeciv - * mplayer etc: Complete on *.crdownload partial downloads in - addition to *.part - * chromium-browser, google-chrome*: New non-xspec completion - * firefox etc: New non-xspec completion - * Merge branch 'master' into wip-pexpect - * nc: Add some more option (non-)completions - * test: Mark MANPATH without leading/trailing colons test an xfail - on CI CentOS 6 - * test: Remove kill, killall remnants - * test: Make case specific env entries shell code, not escaped - * Merge branch 'master' into wip-pexpect - * unzip, zipinfo: Associate with *.whl - * __load_completion: Avoid unnecessary lookups from nonexistent dirs - * Merge branch 'master' into wip-pexpect - * gcc: Add g++, gcc, gccgo, and gfortran *-7 aliases - * test: Use test_unit_* prefix for unit tests, to avoid name clashes - * test: Support setting cmd=None to require no command, for unit - tests - * test: Misc test suite fixes - * test: Fix jq and scrub skipif commands - * test: Don't require complete marker on test methods - * test: Add support for per-test env modifications - * test: Use more conventional Python file names for tests - * test: Sort completion results in Python for ease of use in Python - tests - * test: Allow __load_completion to fail - * test: chdir to fixtures dir in Python as well - * test: Mark xfreerdp as expected failure for now - * test: Replace + with Plus in test class names - * test: Implement load_completion_for using assert_bash_exec - * test: Add ability to selectively ignore diffs in environment - * test: Fixture reorganization - * test: Pass through $HOME and $DISPLAY to test bash - * test: Log pexpect interaction to $BASHCOMP_TEST_LOGFILE if set - * test: Rename BASHCOMP_* test env variables to BASHCOMP_TEST_* - * test: Add python3 test case - * test: Add class level skipif based on bash exec result - * test: Include command name in test class name, use numbered test - method names - * test: Fix some regressions introduced in recent test conversions - * test: Add support for running test case in a specified dir - * test: Add support for skipping individual tests based on shell - command status - * test: Make test base work with Python 3.3+ - * test: Add some iperf, iperf3 and xmodmap test cases - * xmodmap: Use _parse_help instead of hardcoded option list - * iperf: Improve client/server specific option parsing - * iperf: Install for iperf3 too - * iperf: Add g/G to --format completions - * xmodmap: Use _parse_help instead of hardcoded option list - * iperf: Improve client/server specific option parsing - * iperf: Install for iperf3 too - * iperf: Add g/G to --format completions - * test: Use /root/.local/bin/pytest on ubuntu14 by default - * test: Add generated test files to t/Makefile.am automatically - * test: Add new test files to EXTRA_DIST - * test: Use /root/.local/bin/pytest on centos6 by default - * test: Use make pytest docker executable env-configurable, default - pytest-3 - * test: Update generate for pytest+pexpect - * test: Convert majority of test cases to pytest+pexpect - * tox: Fall back to --listenvs for env list if --listenvs-all fails - * git-post-commit: Avoid some error trash when HEAD is not a - symbolic ref - * test: Add pylint-3 test case - * test: Limit number of pylint option completions - * pydoc, pylint: Determine python2/3 based on command basename only - * pylint: Bring -f/--format arg completion up to date with pylint - 1.9.2 - * pylint: Implement comma separated --confidence arg completion - * test: Fix buffer size option listing in run --help - * test: Bump expect's match_max to 20000 by default - * test: Run docker tests with --verbose - * _services: Try systemctl list-unit-files if systemctl list-units - fails - * extra/git-post-commit.sh: Add git post-commit Docker Hub trigger - hook - * gpgv: New completion - * pydoc, pylint: Skip module completion if current looks like a path - * travis: Run ubuntu14/bsd with no network - * travis: Split long lines in script - * test: Limit number of wget option completions to avoid unresolved - result - * test: Mark flake8 untested if it seems broken - * pylint: Option arg completion improvements - * tshark: Get available interfaces from -D output - * ngrep: Add "any" to -d arg completions - * fio: New completion - * test: Fix iwspy test case - * uscan: Use _parse_help instead of hardcoded option list - * urlsnarf: Add -p arg completion - * tracepath: Add -m and -p arg non-completions - * tracepath: Actually use our separate completion instead of - _known_hosts - * test: Skip jq option completion test if its --help doesn't list - them - * xdg-settings: Make help parsing work on BSD - * test: Support running with local BSD binaries, do it w/ ubuntu14 - in CI - * jq, sqlite3: Protect against negative array subscripts - * sudo: Improve long option arg handling - * sysctl: Recognize --pattern/-r and --load options - * test: Add sysctl option parsing test case - * sudo: Parse options from help/usage output, add some long option - support - * strace: Use _parse_help instead of hardcoded option list - * sshow: Add -p arg completion - * sqlite3: Add some option arg (non-)completions - * tune2fs: Update -o/-O argument lists - * jq: New completion - * reportbug: Run _parse_help and apt-cache more selectively - * querybts: Use _parse_help, not hardcoded option list, misc - improvements - * pyvenv: Support versioned 3.6-3.8 executables - * passwd: Try _parse_help before _parse_usage to parse options - * profile.d: Avoid tested variable values being confused as [ ] - operators - * cryptsetup: Add some option arg (non-)completions - * cryptsetup, nc, sh: Skip option args when counting arguments - * modinfo: Fall back to _parse_usage if _parse_help yields no - results - * mysql, mysqladmin: Complete --ssl-{ca,cert,key} option arg - * mysqladmin: Reuse --default-character-set completion from mysql - * modinfo: Use _parse_help instead of hardcoded option list - * minicom: Use _parse_help instead of hardcoded option list - * mplayer: Associate with *.S[3T]M, *.med, *.MED - * completions/Makefile.am: Use install-data-hook, not install-data- - local - * ifup etc: Add option and option argument completion - * _count_args: Add support for not counting specified option args - * ifquery: New ifup alias completion - * ngrep, tshark: Complete on *.pcapng too - * rpm: Complete --licensefiles with -q - * pytest: Rename from py.test to follow upstream recommended name - * README: Add instructions for overriding completions system wide - * README: Note $BASH_COMPLETION_USER_DIR - * test: Mark psql etc test cases untested if --help doesn't work - * aclocal, automake: Support versioned 1.16 executables - * __load_completion: Avoid bad array subscript on "commands" ending - with slash - * lzma: Use _parse_help instead of hardcoded option list - * test: Run perlcritic and flake8 on perl and python helpers in - Travis - * build: Improve cleanup of test/log and test/tmp dirs - * pkg-config: Complete on *.pc files - * build: Use AC_PROG_SED to locate sed - * build: Do cmake, pc, and profile variable replacements in Makefile - * README: Add Q/A on overriding a completion, modernize local - install answer - * json_xs: New completion - * chmod: New completion - * iperf, nc: Include IPv6 addresses in bind address completions - * links: Major rework, parse options from --help, add option arg - completion - * _ip_addresses: Add option to complete all/v4/v6 addresses, add - unit test - * wget: Remove nonexistent arg to _ip_addresses - * _filedir: Drop unnecessary evals - * iconv: Split charset completion to _iconv_charsets, add test case - * links: Install completion for links2 too - * xgamma: Comment spelling fix - * lftp: handle -s - * test: Skip scrub -p test when its --help doesn't list available - patterns - * ecryptfs-migrate-home: New completion - * scrub: New completion - * ether-wake: Install for etherwake as well - * *: Support completing arg of last bundled short option - * dselect: Parse options with _parse_help - * dhclient: Add some option arg (non-)completions - * dhclient: Parse options with _parse_usage - * chage, chpasswd: Add -R/--root arg completion - * reportbug: Add bunch of option arg (non-)completions - * .dir-locals.el: Set -O extglob for flycheck bash checks - * mount, umount: Deprecate on Linux in favor of util-linux >= 2.28 - ones - * _known_hosts_real: Reimplement known hosts file parsing in pure - bash - * test: Add comment line to fixtures/_known_hosts_real/known_hosts - * ssh: Complete all *File option args with _filedir - * README: Point Debian and openSUSE badges towards unstable and - Tumbleweed - * README: Link to various distro packages - * apt-get: Add -h/-v/-o non-completions - * apt-get: Sync option list with apt 1.5.1 - * apt-get: Simplify -t and friends completion, support Ubuntu - * apt-get: Add indextargets to list of suggested commands - * apt-get: Complete install package=versions - * ssh: Sync config option lists with OpenSSH 7.5p1, add some value - completions - * ssh: Sync query type list with OpenSSH 7.5p1 - * ssh: Order various switch cases closer to alphabetical - * completions/Makefile: Fix check-local in VPATH builds - - [ dmerge ] - * _filedir: Refactor to remove heredoc-dependent loop - - [ marxin ] - * gccgo: Add as a GCC completion target (#227) - - [ ovf ] - * xrandr: match the output name exactly for --mode - - -- Ville Skyttä <ville.skytta@iki.fi> Sat, 27 Apr 2019 11:50:12 +0300 - -bash-completion (2.8) - - [ Andrea Dari ] - * dpkg: Add -V/--verify arg completion - - [ Ben Wiederhake ] - * Add support for .lz4 extension to file-roller (#158) - - [ Eric A. Zarko ] - * unzip, zipinfo: Associate *.gar (#165) - - [ Gabriel F. T. Gomes ] - * openssl: Add completion for the genpkey, pkey, pkeyparam, and - pkeyutl commands - - [ Gonzalo TornarÃa ] - * test: run bash with --norc to avoid system bashrc - - [ Gábor Bernát ] - * tox: New completion (#163) - - [ Halt ] - * mplayer: Disable user config when parsing options - - [ Henry-Joseph Audéoud ] - * ebtables: new completion (#150) - - [ Jakub Jelen ] - * ssh,ssh-add,ssh-keygen: Complete pkcs11 options with *.so - - [ Kevin Pulo ] - * mkdir: Complete on files in addition to dirs - - [ Luca Capello ] - * dpkg-query: Fix -W/--show completion - - [ Mark Friedenbach ] - * Add support for .lzo extension (--lzop) to tar (#155) - - [ Martin d'Anjou ] - * java: Complete *.war - - [ Mateusz Piotrowski ] - * kldunload: Increase robustness of compgen filters (#185) - * kldunload: Show modules with digits - - [ MichaÅ‚ Górny ] - * lftp: Support ~/.local/... bookmark location (#144) - * test suite: Support overriding default match buffer size (#141) - - [ Pawel ] - * man: Don't use $MANPATH directly (#161) - - [ Uwe Storbeck ] - * dpkg: Complete --vextract on deb files - * dpkg: Fix man page section in comment - - [ Ville Skyttä ] - * make-changelog.py: Use python3 - * test: Fix getting username in non-login shells - * test/unit: Whitespace tweaks - * info, man, rsync: Defer _expand invocation - * _expand: Reuse __expand_tilde_by_ref and _tilde logic, clean up - * test: Add some _expand unit tests - * bzip2, gzip, and other compressors: Use _tilde instead of _expand - * test: Add assert_complete_homedir, use in dpkg and ls - * dd, find, gcc: Remove unnecessary tilde expansion - * dd: Omit space only when offering one completion ending with = - * __expand_tilde_by_ref: Eval tilde expansion only, simplify - * Bump copyright years to -2018 - * mkdir: Complete files without appending space - * __load_completion: Load "xspec" completions dynamically too - * __load_completion: Code cleanup - * _available_interfaces: Get rid of eval - * make: Pass script to sed as parameter instead of using process - substitution - * ccze: New completion - * *: Comma separated opt arg completion improvements - * test suite: Some more mplayer and mencoder coverage - * tox: Complete comma separated -e arguments - * xdg-mime,xdg-settings: Fix inclusion in tarball - * geoiplookup: New completion - * ping*,ssh,scp,sftp,tracepath6: Filter IPv4/IPv6 literal addresses - * _known_hosts_real: Add option to filter IPv4 and IPv6 addresses - * radvdump: New completion - * lsscsi: New completion - * python: Support completing dotted module hierarchies - * test/docker: Tweak work dir, add bash as default cmd - * test: Try to skip postconf variable test on broken postfix configs - altogether - * Revert "travis: Don't build local docker images, use vskytta/bash- - completion ones" - * test: Add "postconf -" test case - * test: Work around broken centos/fedora postfix config in non-IPv6 - setup - * travis: Don't build local docker images, use vskytta/bash- - completion ones - * pycodestyle: New completion - * flake8: Various option arg completion improvements - * perltidy: New completion - * lowriter,localc etc: Use corresponding oo* completions - * cryptsetup: Update option lists - * pv: New completion - * getconf: New completion - * nproc: New completion - * _known_hosts_real: Document -a better - * ssh: Add -J/ProxyJump completion - * ssh: Declare $prefix closer to use - * test: Ignore duplicates in find_unique_completion_pair list - * test: dpkg,ls,_tilde: Skip gracefully if no uniq user for - completion is found - * xdg-mime: New completion - * ssh-keygen: Add -E arg completion - * reportbug: Don't hardcode option lists, split option args at = - * reportbug: Add -A/--attach arg completion - * apt-get: Complete *.deb on install if argument contains a slash - * ri: Fix integrated ri 1.8 class completion - * test: Add files to test older ri with - * Whitespace - * test: Remove things moved to library.exp from bashrc - * test: Add some comments regarding bash init in library.exp - * xdg-settings: New completion - * tox: Remove spurious executable bits - * tox: Include ALL in -e completions - * tox: Avoid stderr spewage when -e invoked without tox.ini - * pylint: Invoke python3 to search for modules if command contains 3 - * pylint: Install for pylint-2 and pylint-3 too - * test suite: Add bunch of man and MANPATH test cases - * test suite: Make man test subject names less generic - * test suite: man cleanup - * rfkill: Rename to _rfkill to avoid conflict with util-linux >= - 2.31 - * test: Use prebuilt docker hub bash-completion images - * README.md: Whitespace cleanup - * iptables: Use invoked command instead of hardcoded "iptables" - * iptables: Avoid stderr trashing when invoked as non-root - * iptables: Parse options from --help output - * vpnc: Add some option argument (non)completions - * vpnc: Improve config completions - * test suite: Drop no longer needed fedoradev /usr/bin/which - workaround - * test suite: Skip fedoradev GPG checks at least for now - * lspci: New completion - * lsusb: New completion - * oggdec: New completion - * alias: Fix completion followed by = (#146) - * *: Protect shopt reset from non-default $IFS - * test suite: Limit amount of info and pinfo test output - * test suite: Add info and pinfo option test cases - * test suite: Add basic hid2hci and munin-node-configure test cases - * aptitude: Add keep to commands list (Debian: #867587) - * *: Protect _known_hosts_real from user input treated as options - * curl: Fix -x etc option argument hostname completion - * groupdel: Parse and handle long options - * aptitude-curses: Use aptitude completion - * test suite: Install aptitude in ubuntu14 container - * test suite: Enable wine in ubuntu14 - * xm: Don't leak args and commands environment variables - * uscan: Don't leak cword and words environment variables - * test suite: Add bunch of missing basic test cases - * ktutil: Don't leak i and command environment variables - * test suite: Limit amount of output from process name completion - * test suite: Limit number of screen -T completion matches - - [ j^ ] - * xine etc, ogg123, mplayer -audiofile: Associate with *.oga - - -- Ville Skyttä <ville.skytta@iki.fi> Sat, 17 Mar 2018 10:30:07 +0200 - -bash-completion (2.7) - - [ Eli Young ] - * Makefile: update default compatdir (#132) - - [ Ville Skyttä ] - * Make user completion file configurable, disable in tests - * test suite: Generalize xspec completion install check - * pyflakes: Remove redundant xspec completion - * test suite: Fix __expand_tilde_by_ref test expectation output - * pdfunite: New *.pdf completion - - -- Ville Skyttä <ville.skytta@iki.fi> Sat, 01 Jul 2017 14:08:43 +0300 - -bash-completion (2.6) - - [ Björn Kautler ] - * Add missing sidedoor to .gitignore (#114) - - [ Ville Skyttä ] - * test suite: Mark expected centos6 CI _filedir failures as such - * Expose version in BASH_COMPLETION_VERSINFO, use it in profile.d - script - * test suite: Skip an expected make test case failure in centos6 CI - * test suite: Fix ifdown and ifup CI test skipping - * test suite: Ignore env var pulled in by use of scp in tests - * test suite: If colon trim doesn't do anything, trim as usual - * tar: Comment spelling fixes - * test suite: Mark dpkg -L test case untested if no packages - installed - * test suite: Cosmetic tweaks - * dpkg: Fix dpkg -i home dir completion - * test suite: Improve ls home dir test descriptions - * python: Split module completion to separate helper - * micropython: New completion, aliased from python - * test suite: Add Python module completion test case - * python: Fix traceback avoidance on module completion error - * openssl: Parse available digests from dgst -h - * openssl: Add sha2 commands - * gm: New completion, commands only for now - * (test suite): Test screen -T completions - * (test suite): Set TERM to dumb, not dummy - * Revert "(test suite): Fix alias and cd cursor position tests" - * mplayer: Remove duplicate *.m4a and *.m4v associations - * mplayer, xine, etc: Associate *.mp4a and *.mp4v - * xine etc: Fix *.m4a association - * bind: Add option and argument (non-)completions - * _user_at_host: Set nospace only when completing username part - * _user_at_host: Append @ suffix to username part completions - * man: Don't check OSTYPE or GNU userland, just enable on all - systems - * (test suite): Set dcop result to untested if dcop server is not - running - * (test suite): Don't insist on loading all completions dynamically - * _configured_interfaces: Parse from /etc/network/interfaces.d/* on - Debian - * py.test: New completion - * oowriter: Associate with *.pdf - * Don't define BASH_COMPLETION_COMPAT_DIR - * ri: Add option and arg completions - * (test suite): Add our own dummy ri test fixture - * (test suite): Info test needs docs, don't exclude from CentOS - * (test suite): Fix CentOS 6 tcllib setup - * (test suite): Simplify renice test, fix with only one completion - * (test suite): Don't assume configured interfaces in CI setups - * Don't offer * as configured interface when there are none - * (test suite): Add basic CentOS 6 container for bash 4.1 coverage - * (test suite): Ignore runtime loaded env function changes - * (test suite): Add mailman bin dir to PATH for arch test - * arch: Parse options from --help - * (test suite): Load tested completions dynamically - * (test suite): Accept non-whitespace single word in - assert_complete_any - * (test suite): Avoid interference from user and system dirs (#87) - * (test suite): Install some things N/A in ubuntu14 to fedoradev - * (test suite): Add unrar to ubuntu14 container - * (test suite): Fix alias and cd cursor position tests - * (test suite): Add basic alpine test case - * alpine: Parse opts from -h output, add some opt arg completions - * (test suite): Install jshint globally in ubuntu14 - * (test suite): Add mailman bin dir to PATH for some mailman tools - * (test suite): Install jshint to ubuntu14 container with npm - * unshunt: Parse options from --help - * (test suite): Test lsof on ubuntu14 - * (test suite): Add basic hping3 test case - * (test suite): Add our ./configure to PATH to test it, test opts - * (test suite): Add bunch of packages to ubuntu14 container - * (test suite): Ensure /usr/(local/)games is in $PATH - * (test suite): Fix perl -d* test cases with no Devel::* installed - * (test suite): curl has lots of options, add more test prefix - * (test suite): Fix tar test case for ones having --owner-map - * (test suite): Unsupport various kill, renice cases if ps is N/A - * (test suite): Make chkconfig test behave better in container - * (test suite): Don't assume mounted filesystems in quota* tests - * newlist: Parse options from --help, add some arg non-completions - * (test suite): Delete trailing whitespace - * (test suite): Don't assume lists set up in newlist test cases - * (docker): Pull in missing fedoradev xvfb-run which dependency - * mr: Avoid stderr trash and test suite failure if man is N/A - * (test suite): Fix mmsitepass completion test - * tshark -G: Avoid stderr noise when running as superuser - * (docker): Run completion tests with xvfb-run, e.g. for gkrellm - * ssh-keygen: Make option parsing work with OpenSSH < 7 - * synclient, udevadm: Avoid use of posix char classes for awk - * test suite: Add WIP Fedora dev config - * Travis: Switch tests to docker, update to Ubuntu 14 - * xv: Associate with *.j2c, *.j2k, *.jp2, *.jpf, and *.jpg2 (Debian: - #859774) - * eog: Associate with *.j2c and *.jpg2 - * Bump copyright years - * xine etc: Associate uppercase *.WM[AV] - * mplayer: Associate *.weba (#112) - * xine etc: Associate *.webm and *.weba (#112) - - -- Ville Skyttä <ville.skytta@iki.fi> Tue, 27 Jun 2017 12:29:33 +0300 - -bash-completion (2.5) - - [ BartDeWaal ] - * Support for python gui source files (#91) - - [ Ben Webber ] - * mr: New completion - - [ Christian Kujau ] - * ssh-keygen: support ed25519 keys (#79) - - [ Dara Adib ] - * Add sidedoor to _ssh() completion (#106) - - [ George Kola ] - * .ipa is just a zip file and we should let unzip handle it (#71) - - [ Miroslav Å ustek ] - * ant: parse targets in imported buildfiles (#84) - - [ Reuben Thomas ] - * Add more tests for ccache - * ccache: fix completing compiler's flags - - [ Ville Skyttä ] - * test suite: Add java/javac non-completion fixture - * javac: Complete -cp like -classpath - * travis: Skip bluez and nis for now due to post-install script - issues - * test/config/*: Delete trailing whitespace - * (test suite): Avoid loading user's ~/.bash_completion, fixes #87 - * ip: Recognize a as alias for address and l for link - * ip: Recognize address in addition to addr - * mr: Disable "clean" test case, command N/A before mr 1.20141023 - * ssh-keygen: Parse switches with _parse_usage, not _parse_help - * mplayer: Associate with *.mjpg, *.mjpeg (Debian: #837779) - * dd: Sync completions with coreutils 8.24 - * travis: Add mr - * perl: Remove full path to cat in PERLDOC_PAGER call - * deja-dup: New completion - * CONTRIBUTING: Reorder sections - * *: Move indentation settings to .editorconfig - * make: Declare _make_target_extract_script like other functions - * Travis: zopfli is AWOL? - * *: Whitespace fixes - - [ Zearin ] - * Minor edits to README.md (mostly formatting) (#110) - - [ l3nticular ] - * Fix bug in 'make' completion when using BSD sed (#108) - - [ osu ] - * Add support for Include in ssh config (#70) (#80) - - -- Ville Skyttä <ville.skytta@iki.fi> Sat, 04 Feb 2017 18:07:27 +0200 - -bash-completion (2.4) - - [ Arash Esbati ] - * xetex, xelatex, luatex, lualatex: Associate with tex files - - [ Gene Pavlovsky ] - * Use shell globbing instead of ls to source files in compat dir - - [ Grisha Levit ] - * Support completing array variables and expansions - * Add tests for declare/typeset - * Better handling of typeset/declare - - [ Kylie McClain ] - * tar: silence --version's stderr output - - [ Paul M. Lambert ] - * Support pod document files for perldoc (#39) - - [ Richard Alpe ] - * tipc: fix missing last char in link name completion - * tipc: handle complete words without trailing space - * tipc: suppress tipc error messages - * tipc: use double brackets in if conditions - * tipc: make loop variables local - * tipc: remove unnecessary return values - * tipc: readd call to complete command - * tipc: use cur variable for flag completion - * tipc: add command prefix to link sed - * tipc: remove unnecessary function _tipc_get_val() - * tipc: use bash here string instead of echo - * tipc: merge functions into main - * tipc: add test framework - * tipc: add tipc completions - - [ Ville Skyttä ] - * Release 2.4 - * rpm: Offer --filetriggers with -q - * javadoc: Add bunch of option arg (non)completions - * lrzip: Add -m arg noncompletion - * pkg-get: Don't use hyphens in function names - * jarsigner: Add some option arg (non)completions - * pkg-get,pkgrm: Drop unnecessary _have calls - * *: Trivial cleanups - * *: Remove redundant return 0's - * pypy*: Add basic --jit arg completion - * pypy3: Alias to python - * hcitool,svcadm,tar: Spelling fixes - * Travis: Install more packages for more test coverage - * (test suite): Pass assert_complete_any for exact/only given arg - completed - * tipc: Invoke ls with "command" - * tipc: Indentation fix - * (test suite): Fix fallout from - fec077d555f112b9f455c45860f90a3b47392fcf - * (test suite): Remove Bash::Completion.3pm.gz from git, create on - the fly - * (test suite): Remove test/fixtures/_filedir/a"b from git, create - on the fly - * CONTRIBUTING: Note patch preferences if not using GitHub pull - requests - * python: Support -Q and -W arg completion without space - * apache2ctl, aspell, make: Don't hardcode completion generator - command - * mysql: Avoid --default-character-set error with failglob, fixes - #46 - * test suite: Add perldoc module+pod completion test case - * perl: Remove some duplicated code - * pushd: Use _cd completion for CDPATH support, closes #38 - * test suite: Add basic pushd test case - * abook: Parse long options from command including full path - * pyvenv: New completion - * chroot: New (generic long options) completion, see #38 - * Travis: First steps toward testing with OS X - * test suite: Add bashcomp_bash env var for better control on tested - bash - * aptitude: List packages using _apt_cache_packages, fixes #33 - * vncviewer: Cleanup shopt use, drop an eval - * make: Avoid a grep - * rpm: Fix --whatenhances arg completion - * aspell, minicom, mysql: Replace use of ls with printf - * cppcheck: Complete filenames too for --platform - * man: Prioritize MANPATH, simplify, add fallback e.g. for busybox, - fixes #28 - * aclocal: Install completion for 1.14 and 1.15, fixes #25 - * mpv: Don't install symlink for it, fixes #24 - * test suite: Add function and declare test cases - * CONTRIBUTING: Highlight request for test cases - - [ Wayne Scott ] - * The BitKeeper completion used the wrong set of commands - - -- Ville Skyttä <ville.skytta@iki.fi> Fri, 12 Aug 2016 22:43:27 +0300 - -bash-completion (2.3) - - [ Daniel Milde ] - * Completion for python zip archives - - [ Liuhua Wang ] - * lvm: pvcreate should be able to use all block devcices - * lvm: fix all commands that should get all PVs - - [ Ville Skyttä ] - * Release 2.3 - * make-changelog: Don't output "Merge pull request" entries - * make: Use <<< instead of printf + pipe - * gnokii: Use <<< instead of echo + pipe - * *: Use [:blank:] instead of $'\t ' tricks where appropriate, fixes - #19 - * test suite: Fix abook test case - * test suite: Don't insist on property completions if synclient -l - fails - * test suite: Tolerate "See 'man feh'" feh --help output - * test suite: Fix tar failure caused by previous tar change - * tar: Detect GNU/other from --version only once per session - * tar: Remove unused variable - * tar: Fix GNU tar help output parsing regex, fixes #15 - * test suite: Add tar xvf filename test case - * tar: Don't write to /tmp/jetel - * python: Simplify code - * python: Complete all files also after -m - * python: Don't offer options after -c - * python: Complete all files only if -c is before current word - * test suite: Add some python test cases - * unzip, zipinfo: Complete on *.pyz - * travis: configure and run completions syntax check - * make check: Test syntax of all completion files - * CONTRIBUTING.md: Ask for test cases - - -- Ville Skyttä <ville.skytta@iki.fi> Mon, 28 Mar 2016 18:32:47 +0300 - -bash-completion (2.2) - - [ Barry Warsaw ] - * _init_completion: Handle cword < 0 (LP: #1289597) - - [ Damien Nadé ] - * (testsuite) Use 'set' command posix behaviour when saving env - (Alioth: #314720) - * Added test/site.{bak,exp} to .gitignore - * _parse_help: Fix failglob failures (Alioth: #314707) - * _lvm: using a single-pattern case and invoking function according - to words[1] - * lvm: _lvm_count_args parameter must be quoted in order to failglob - not to complain - * gendiff: Quoting suffix pattern to avoid triggering failglob - - [ Dams Nadé ] - * ssh-add, ssh-keygen: -? needs to be quoted under failglob (Alioth: - #314709) - * Quote unset array element to avoid globbing interference (Alioth: - #314708) - - [ David Paleino ] - * Refactor bts and uscan, since they use common functions - * uscan: New completion, thanks to Federico Ceratto - * bts: New completion, thanks to Federico Ceratto. - - [ Guillaume Rousse ] - * complete on freerdp-specific known hosts list - * nmcli completion was integrated upstream - - [ Igor Murzov ] - * isql: Fix failglob failure - * ssh-add, ssh-keygen: -? needs to be quoted under failglob (take 2) - (Alioth: #314709) - * (testsuite): move testing of _linux_fstab() to umount.exp - * umount: Fix mount points escaping/unescaping with Bash-4.3 - * slapt-src: Handle --config=FILE option properly - * sbopkg, slapt-{get,src}: expand tilde in config file name - * slapt-{get,src}: Fix issue with sed not being able to handle some - characters - * slapt-src: split options from their arguments - * Quote _filedir arguments when appropriate to prevent failglob - failures - * psql: Tell psql to not load .psqlrc as it may change output format - (Alioth: #314636) - * testsuite: Add basic tests for portsnap and freebsd-update - * mplayer: -dvd-devices takes dvd devices, dirs and .iso files as - argument - * 7z: Improve completion - * f77, f95: Use the same completion as for g77, g95 if they are - links to gfortran - * aptitude: safe-upgrade accepts package name as parameters (Alioth: - #313638, Debian: 673235) - * _longopt: Run commands in C locale. - * make: Use only posix basic regexps with sed (Alioth: #314345) - * cppcheck: Add new --enable option argument and --library argument - completion - * dpkg: Suppress unwanted error messages (Debian: #706502) - * perl: -d/-dt option argument is optional (Alioth: #314242) - * Add config for cmake to bash-completion. - * kcov: Add new sort types, complete --replace-src-path arguments - * feh: Add new sort type - - [ Mathieu Parent ] - * Puppet: describe: update options list, accordind to 'puppet help - describe' - * Puppet: cert: update options list, accordind to 'puppet help cert' - * Puppet: apply: update options list, accordind to 'puppet help - apply' - * Puppet: agent: update options list, accordind to 'puppet help - agent' - * Puppet: puppet parser support - * Puppet: puppet -* doesn't imply 'puppet apply' - * Puppet: use puppet terminology - - [ Matthew Gamble ] - * Modify all usages of 'sed' to be run with command bash builtin - * Use command built-in to run sed to avoid any custom aliases - - [ Matthieu Crapet ] - * man: Use -w instead of --path - - [ Michael Gold ] - * profile.d: Avoid some warnings from shells in "nounset" mode - (Debian: #776160) - - [ Miroslav Lichvar ] - * chronyc: Update help text parsing - * chronyc: Add missing subcommands - * chronyc: Add -6 option - - [ Nevo Hed ] - * minicom: Recognize user ~/.minirc.* as config files - - [ Ondrej Oprala ] - * __get_cword: avoid $index < 0 (Alioth: #315107) - - [ Patrick Monnerat ] - * rpmbuild: Complete *.spec on --clean (RedHat: #1132959) - - [ Pavel Raiskup ] - * tar: rework the completion completely - - [ Peter Cordes ] - * upstart support for service completion - - [ Peter Dave Hello ] - * freebsd-update: New completion. - * portsnap: New completion. - - [ Peter Wu ] - * modprobe: fix params with multi-line descriptions - * gdb: support --args style completion (Alioth: #314664) - - [ Rainer Müller ] - * make: Fix basic regex for portability (Alioth: #314345) - - [ Raphaël Droz ] - * gnokii: New completion - - [ Rune Schjellerup Philosof (Olberd) ] - * dpkg: Add support in dpkg completion for .ddeb (LP: #568404) - - [ Shaun McCance ] - * xmllint, xmlwf, xsltproc: Complete on Mallard *.page files - - [ Stefano Rivera ] - * pypy: New completion identical to python (Alioth: #314501) - - [ Thilo Six ] - * Use more straightforward way to check bash version - * _mac_addresses: Use explicit C locale for ifconfig (Debian: - #704832). - - [ Tristan Wibberley ] - * make: Don't pick up variables when makefile is reloaded - * make: Offer hidden targets when it is clear that the user is - trying to complete one of them - * make: Fix detection of intermediate targets where make has changed - its database whitespace - * make: Add __BASH_MAKE_COMPLETION__ variable - * make: completion shouldn't be confused by the output of $(info - confuse: make) - - [ Uwe Kleine-König ] - * Don't complete hostnames found after Hostname in ~/.ssh/config - - [ Ville Skyttä ] - * Release 2.2 - * README.md: Note autoreconf need only in unprepared tarball - * make-changelog.py: Set myself in footer - * make-changelog.py: Fix footer line output - * make-changelog.py: flake8 fixes - * make-changelog.py: Make work with Python 3 - * README.md: More markdown tweaks - * README.md: Markdown tweaks - * zopflipng: New completion - * README.md: Not need for autoreconf, fixes #11 - * README: Expand troubleshooting section somewhat - * Merge pull request #9 from shaunix/master - * ssh: Extract duplicate code to _ssh_configfile - * Remove various comments related to bash versions we don't support - * travis: Install more packages for [xyz]* test coverage - * travis: Install more packages for [stuvw]* test coverage - * travis: Install more packages for [qr]* test coverage - * travis: Install more packages for [op]* test coverage - * travis: Install more packages for m* test coverage - * travis: Install more packages for [jkl]* test coverage - * Merge pull request #7 from ukleinek/master - * indent: Remove generic long option completion - * Update copyright year - * travis: Install more packages for [hi]* test coverage - * travis: Install more packages for [fg]* test coverage - * mysql: Fix --default-character-set completion with mariadb - * mysql, puppet: sed portability fixes - * gnokii, minicom: Use grep through "command" - * lint: Check for sed without "command" - * Merge pull request #2 from djmattyg007/avoid_sed_alias - * travis: Install more packages for [de]* test coverage - * travis: Install more packages for c* test coverage - * travis: Add note about (currently) N/A packages - * test suite: Mark unsupported look test case as such, not - unresolved - * test suite: Use unsupported instead of xfail for modinfo/modprobe - cases - * travis: Install more packages for [0-9][ab]* test coverage - * travis: Run tests with --all to get some more useful output - * test suite: Fix ssh partial hostname completion test - * README: Split contributing to separate CONTRIBUTING doc - * README: Convert to markdown - * Drop references to bash-completion-devel@lists.alioth.debian.org - * build system: Switch to xz compressed tarball - * aclocal, automake: Install for versioned 1.14 and 1.15 executables - * Update URLs and various instructions to GitHub - * README: Update POSIX spec link - * travis: Avoid Travis default ri, use distro one instead - * test suite: Make apt-get test less sensitive to available commands - * test suite: Output tool log on failure in CI - * Set up Travis - * test suite: Expect failure in modinfo/modprobe if there are no - modules - * test suite: Fix ssh-copy-id test on old setups with no identities - * cppcheck: Add native to --platform completions - * ssh: Avoid completing commands before hostname - * chronyc: Parse command args from help output - * chronyc: Wrap long lines - * Load completions also from $XDG_DATA_DIRS (RedHat: #1264094) - * (testsuite) Ignore files generated by complete-ant-cmd.pl - * scp, sftp: Complete -S on commands - * scp, sftp: Fix querying ssh options - * sftp: Add -l arg non-completion - * ssh-copy-id: Offer only *.pub to -i - * mpv: Remove mplayer-aliased completion - * __load_completion: New function, use in _completion_loader and - _xfunc - * modplug*: Associate *.oct and *.okt - * rpm: Add --whatenhances/recommends/suggests/supplements and - --recommends/supplements completions - * pgrep, pidof, pkill, pwdx, vmstat: Add support for procps-ng - * pdftotext: New completion - * checksec: New completion - * ssh: Complete HostbasedKeyTypes,HostKeyAlgorithms,KexAlgorithms - values - * ssh: Query ciphers and macs from ssh before hardcoded fallback - * ssh: Add -Q argument completion - * sysctl: Return early on --help, --version - * sysctl: Try parsing options from help before usage - * Document how to avoid command_not_found_handler interference - * eog: Complete on *.ppm (RedHat: #1090481) - * tar: Plug $line var leak - * tar: Style tweaks - * (testsuite) Add required "empty" dir for tar - * bsdtar, tar: Remove symlinks from git, have make create them - * jshint: New completion - * gnokii: Include and install it - * gnokii: Fix completions of options that are prefixes for others - * gnokii: Drop dead code - * (testsuite): Add basic gnokii test case - * gnokii: Various minor and cosmetic fixes - * _filedir: Avoid some unnecessary work with -d - * _filedir: Remove unused variable - * _filedir: Fix overquoted argument to compgen -d (RedHat: #1171396) - * 2015 - * Load user completions from $BASH_COMPLETION_USER_DIR/completions - * Revert "README: Don't hardcode /etc in cmake fallback dir" - * README: Don't hardcode /etc in cmake fallback dir - * README: Add cmake usage example - * README: Add autotools and cmake tips - * Drop reference to no longer used sysconf_DATA - * synclient: New completion - * tune2fs: Add missing return in -M arg completion - * reptyr: Rename file to _reptyr to avoid conflict with upstreamed - completion - * cppcheck: Option argument (non-)completion update - * dropuser: New completion - * createuser: New completion - * createdb, dropdb: Drop -o default, it does not appear to do - anything good here - * tshark: Simplify cut usage - * mcrypt: Simplify -m arg completion - * (testsuite): Add mcrypt -a and -m argument completion tests - * strings: Fix -T/--target arg completion with non-English locale - * chrome, firefox etc: Complete on *.pdf - * ccache: Add -o/--set-config arg name completion - * gphoto2: Replace tail with awk - * *: Invoke command to be completed, not its basename - * gphoto2: Fix split argument handing, and colon treatment in --port - args - * _completion_loader: Protect compgen from -* leakage (Debian: - #769399) - * Actually install the lz4 completion - * _pnames: Add -s for producing (possibly) truncated names (RedHat: - #744406) - * (testsuite) Add cd in dir without subdirs or CDPATH test case - * Protect various compgen invocations from -* leakage (Debian: - #766163) - * pigz, unpigz: Handle *.zz - * _completion_loader: Set empty command to _EmptycmD_ for cross - version compat - * Comment update - * rpmbuild: Complete *.spec on --nobuild - * mplayer, *xine: Complete on *.mts (Debian: #759219) - * ant: Support buildfile set in $ANT_ARGS (Alioth: #314735) - * (testsuite) Add ant -f <buildfile> test case - * ant: Don't offer more completions after options that exit - * 7z, adb: Trivial cleanups - * python(3): Add -X argument non-completion - * xsltproc. TODO fix for previous commit - * xmllint, xmlwf, xsltproc: Complete on *.dbk and *.docbook (Alioth: - #314770) - * xz: Complete -T/--threads argument - * (testsuite) Save shell variables when saving env (Alioth: #314720) - * adb: New completion - * modprobe: Try parsing help before using hardcoding option list - * (testsuite) Add vgcreate test case for _lvm_count_args with - failglob on - * _filedir_xspec: Fix with failglob on - * Various mostly array element unsetting fixes under failglob - * __reassemble_comp_words_by_ref: Make work with failglob on - (Alioth: #312741) - * _services: README in sysv init dir is not a service - * mpv: New completion alias + adjustments for mplayer (Debian: - #749115) - * (testsuite) Add puppet subcommand option test case - * puppet: Recognize some short options - * puppet: Parse most subcommand options from "help subcommand" - output - * puppet: Exit early on -h|-V|--version in addition to --help - * hostname: New completion - * nslookup: complete on hosts (Alioth: #314673) - * eog: Complete on *.pgm (RedHat: #1090481) - * pngfix: New completion - * qemu: Fix -balloon arg completion - * qemu: Apply completion to qemu-kvm/-system-i386/-system-x86_64 too - * xrandr: Use the invoked command internally, not hardcoded "xrandr" - * xrandr: Add (some) --setprovider* arg completion support - * profile.d: Don't return from a sourced script (Debian: #741657) - * FAQ: Clarify that we mean the bash man page for M-/ - * (testsuite) Avoid complete-ant-cmd.pl errors with our build.xml - * ri: Fix class completion with ri >= 3. - * ri: Fix colon handling in class completion. - * flake8: New completion - * pyflakes: New completion - * cal,chfn,chsh,dmesg,eject,hexdump,look,newgrp,renice,runuser,su,wr - ite: Deprecate on Linux in favor of util-linux ones (Debian: - #737672) - * testsuite: Add basic newgrp test case - * testsuite: Add basic test cases for deprecated completions - * _*: Install our deprecated completions too, try loading them - secondarily - * hwclock,ionice,rtcwake: Deprecate in favor of util-linux ones - (Debian: #737672) - * ssh-keygen: New completion - * Bump copyright years to 2014. - * jpegoptim: New completion - * ip: Add some addr, addrlabel, and route arg completions - * aptitude, dpkg: Replace some grep+cuts with awk - * gcc, lintian, make, pkgadd, slackpkg: grep -> "command grep" - (Debian: #734095) - * lintian: Replace some grep+cuts with awk - * (testsuite) Check for grep and ls invoked without "command", see - README - * lz4: New completion. - * optipng: New completion. - * cppcheck: Include - in --file-list completions. - * (testsuite): Limit wtf completions to A* to keep expect happier. - * wtf: Look for acronym db from /usr/share/games/bsdgames/acronyms - too. - * wtf: Don't offer -f if it was already specified. - * wtf: Hush stderr when db file doesn't exist. - * appdata-validate: New completion. - * timeout: New completion. - * _known_hosts_real: Exclude %h HostName entries (RedHat: #1015935). - * cc, c++: Check path to binary when finding out if it's gcc - (Alioth: #314417). - * cc, c++: Install minimal completion for non-gcc ones (Alioth: - #314417). - * abook, kldunload: Pre-expand \t instead of relying on sed - supporting it. - * dict: Trivial regex cleanup. - * _known_hosts_real: Pre-expand \t instead of relying on sed - supporting it (Alioth: #314393). - * zopfli: New completion. - * bzip2, gzip, lzma: Cleanups. - * Cosmetics. - * export, _variables: Do TZ= completion (Redhat: #994646). - * 2to3: New completion. - * file-roller: Reuse unzip's xspec. - * 7z: New completion. - * hcitool, rfcomm, ciptool, hciconfig: Don't leak $args. - * perl: Fix -dt: completion. - * perl*: Fix handling of relative paths in @INC. - * wget: Add --accept-regex/--reject-regex/--regex-type arg - (non)completions. - * wget: Drop incorrect -nv arg completion. - * wget: Stop completing after --help/--version. - * Clean up/compact various globs. - * cvs: Fix checkout -j non-completion. - * sh: Complete script arguments with all filenames (Alioth: - #314226). - * nmcli: Deprecate our completion, upstream has one in 0.9.8.0. - * Revert "nmcli completion was integrated upstream" - * Use == instead of =. - * cvs rm: Don't filter existing files with -f (RedHat: #949479). - * aclocal, automake: Install for *-1.10, *-1.12, and *-1.13 too. - - -- Ville Skyttä <ville.skytta@iki.fi> Thu, 03 Mar 2016 17:22:50 +0200 - -bash-completion (2.1) - - [ AllKind ] - * Fix __ltrim_colon_completions() fail on parameter (\$1) containing - a glob. - - [ Andreas Müller ] - * completions/Makefile.am: symlinks depends on $(DATA) to avoid race - conditions - - [ Christian von Roques ] - * Fix __reassemble_comp_words_by_ref for $COMP_CWORD == ${#COMP_WORDS[@]} - - [ David Paleino ] - * Fix helper script to create changelogs - - [ Guillaume Rousse ] - * New completions: nmcli, gphoto2 - * Improved completions: - - dsniff: add -p option completion - - dsniff: fix interface completion - - - [ Igor Murzov ] - * _command_offset: Restore compopts properly (Alioth: #313890) - * _parse_help, _parse_usage: Run commands in C locale. - * New completions: wget, zathura - * Improved completions: - - cppcheck: Add new standards to --std option. - - evince: Evince supports opening .pdf.xz files (Alioth: #313739). - - feh: Add new options introduced in feh-2.7. - - feh: Fix list of background styles. - - fusermount: Complete curlftpfs-mounts for "fusermount -u" (Debian: - #685377) - - kcov: Add new sort types (introduced in kcov-9). - - kcov: Complete arguments of --limits option. - - lvm: Fix typo in option name: s/continguous/contiguous/. - - make: Do not append space if target is a filepath. - - mount: Fix parsing /etc/fstab on *BSD. - - mount.linux: Add some new mount options intoduced in Linux 3.5 and 3.7 - - mount.linux: Add options completion for nfs and davfs. - - mount.linux: Clean up mount options, remove duplicates. - - mplayer: Add opus to the list of supported formats. - - mplayer: Add -subcp argument completion. - - opera: Handle options. - - slackpkg, slapt-get: Update the list of package sets. - - tar: Fix detection if the $prev is a tar file. - - valgrind: Add --soname-synonyms option arguments completion. - * Testsuite: - - _filedir: Remove the cruft from the a\$b->h unit test (Alioth: #313480) - - [ Jeroen Hoek ] - * Improved completions: - - unzip: Add support for OpenDocument formats. - - [ Ken Sharp ] - * Improved completions: - - wine: add .msi completion - - [ Martin Ueding ] - * Stylistic cleanup - - [ Tristan Wibberley ] - * Improved completions: - - make: incremental completion for make with compact display - - make: convert make completion to use smarter parser - - [ Ville Skyttä ] - * Avoid sourcing dirs in completion loader to avoid fd leaks (RedHat: #903540) - * Ignore colormake symlink. - * Line continuation, whitespace, and compgen -W ... -- "$cur" - quoting cleanups. - * _available_interfaces: Try with "ip link" if ifconfig is not available. - * _ip_addresses: Try with "ip addr" if ifconfig is not available. - * _known_hosts_real: Filter ruptime stdout error spewage (Alioth: #313893). - * _mac_addresses: Try local interfaces with "ip link" if ifconfig not - available. - * _mac_addresses: Try ARP cache with "ip neigh" if arp is not available. - * _mac_addresses: Fix with net-tools' ifconfig that outputs ether, not HWaddr. - * New completions: chronyc, eject, eog, file-roller, hexdump, interdiff, lua, - luac, luseradd, luserdel, lusermod, mussh, nc, ngrep, patch, pydoc, - pyflakes, pylint, ss, strings, tshark, wsimport, xxd - * Improved completions: - - acpi, chpasswd, dmesg, gkrellm, groupmems, hwclock, lastlog, pwd, vipw: - Complete options even without "-" given. - - arpspoof, dsniff, ether-wake, nmap: Offer active interfaces only. - - clzip, pdlzip, plzip: New lzip alias completions. - - colormake: New make alias completion (LP: #743208, Debian: #682557) - - cpio: Recognize pass thru when -p is bundled w/other options - (RedHat: #912113). - - cppcheck: Add --language/-x argument completion. - - cppcheck: Complete --include= with filenames. - - dnsspoof, filesnarf, macof, sshow, tcpkill, tcpnice, urlsnarf: Fix -i - completion. - - genisoimage: Use _parse_help instead of hardcoding options, add basic test - case. - - groupmems: Add -R/--root arg completion. - - hexdump: Actually install for hd as well. - - host: Complete with known hosts. - - ip: Improve addr show and link show completions. - - ip: Remove some stale TODOs. - - jar: Reuse unzip's xspec (RedHat: #928253). - - koji: Complete on build targets when --target is given to wait-repo. - - lv{create,resize,extend}, vg{create,reduce,extend,split}: Fix variable - leaks. - - lvm: Add _lvm prefix to helper functions. - - lvm: Take option args into account when counting args (RedHat: #860510). - - lvm volumes: Complete on /dev/mapper/* (RedHat: #851787). - - lzip: Do not append space after equal sign in long options. - - make: Convert internal variable names to lowercase, indentation fix. - - make: Don't leak $mode. - - make: Make work in POSIX mode. - - man: Add support for .lz man pages (RedHat: #839310). - - man: Don't expand man page extensions too early. - - man: Fix -P/--pager full path arg completion. - - modinfo: Use ,, for lowercasing instead of tr in a subshell. - - modprobe: Don't suggest installing already installed modules. - - ncftp: Add option completion. - - pkg-config: Try to complete --variable= if package name is already given. - - pydoc: Complete on keywords and topics. - - python, pydoc: Add module completion. - - scp: Treat strings with slash before colon or starting with [.~] as local. - - ssh: Add some -o and related arg completions. - - ssh: Add -O argument completion (Debian: #680652). - - tar: Don't take -I to mean bzip2. - - tar: Fix completing files inside *.tlz when J is explicitly given. - - tar: Simplify bzip patterns. - - tar: Support *.tar.lz (Debian: #703599). - - tar: Recognize taz and tb2 as compressed tarballs. - - tcpdump: Fix -z full path arg completion. - - unzip/zipinfo: Associate with more StarOffice extensions. - - useradd, userdel, usermod: Add -R/--root arg completion. - - useradd, usermod: Support comma separated -G/--groups arg completion. - - useradd: Fix -k, -K, and --home-dir argument completions. - - userdel: Add -h/--help non-completion. - - valgrind: Fix full path <command> arg completion. - - vgcreate: Add missing symlink. - - vipw: Add -R/--root arg completion. - - vpnc: Add bunch of option arg (non)completions. - - vpnc: Use _parse_help instead of hardcoding options, add basic test case. - - wget: Use == instead of =. - - wine: Fix extension glob to work on its own. - - wol: Try "ip addr" before ifconfig for finding out broadcast addresses. - - xrandr: Add bunch of option arg non-completions. - - xrandr: Use _parse_help. - - xrandr --mode: Clean up one awk call. - - xrandr: Avoid --mode completion error when --output is not given. - - xrandr: Don't leak $i when completing --mode. - * Deprecated completions: - - udevadm: one is shipped in systemd >= 196 (RedHat: #919246). - * Testsuite: - - Make pydoc test more likely to work with our limited expect buffer size. - - Fix pwd unit test - - [ Yann Rouillard ] - * New completions: pkgutil, pkgrm, pkgadd, pkg-get, svcadm. - - [ wonder.mice ] - * Fixed tilde expanding in _filedir_xspec - - -- David Paleino <d.paleino@gmail.com> Fri, 05 Apr 2013 12:05:15 +0200 - -bash-completion (2.0) - - [ Anthony Ramine ] - * Properly declare 'symlinks' dependencies - - [ David Paleino ] - * apt-get: add 'changelog' to completed commands - - [ Guillaume Rousse ] - * Add xz compression extension for kernel modules - - [ Igor Murzov ] - * sudo: Handle options (Alioth: #311414). - * sudoedit: New completion. - * _command_offset: Properly quote arguments of eval (Alioth: - #313499). - * mount.linux: Add some new mount options intoduced in Linux 3.0-3.2 - * _modules: Ignore error messages. - * modprobe, modinfo, insmod: Move modprobe and modinfo completions - to their own files. - * sbopkg: Use _parse_help. - * sbopkg, slackpkg, slapt-{get,src}: Use shorter form of the check - if file exists. - * _filedir: Properly quote paths to avoid unexpected expansion. - * su: Add linux-specific completion - * insmod, modprobe: Don't hardcode path to modinfo (Alioth: #313569) - * man: --path option is supported on Darwin (Alioth: #313584) - * man: Move variable declaration to the right place. - * feh: Update option argument completions. - * fbi, feh: Complete more supported file formats. - * fbgs: Add new options introduced in fbida-2.09. - * cppcheck: Complete new --relative-paths option arguments - * _expand: Suppress unwanted bash error messages (Alioth: #313497) - - [ Itaï BEN YAACOV ] - * scp: Recognise symlinks to directories as directories (Debian: - #666055). - - [ Jonathan Nieder ] - * ri: Rename ri_get_methods helper to add leading underscore - - [ Ville Skyttä ] - * rmmod: Add option completions. - * testsuite/generate: Generate less linefeeds. - * insmod: Install for insmod.static too. - * mplayer: Add -monitoraspect arg completion. - * mplayer: Add generic handling of options that take arguments. - * testsuite: Fix spurious modinfo and modprobe test failures on - systems that have /lib and /lib64 dirs. - * pigz: Add -p/--processes arg completion. - * testsuite: Add basic su test case. - * su: Fix long option handling. - * su: Add --session-command arg completion. - * su: Complete -s/--shell with shells instead of all files. - * lyx: Remove simple completion, upstream has more complete one - (Debian: #662203) - * testsuite/generate: Tweak linefeeds. - * make: Add generic variable completion. - * man: Recognize 3gl as man page filename extension -- at least Mesa - uses it. - * _realcommand: Try greadlink before readlink (Alioth: #313659). - * Comment spelling fix. - * qiv: Add *.svg. - * xmllint: Add *.svgz. - * autotools: Use MKDIR_P instead of mkdir_p (Alioth: #313671). - * lbzip2: Add -n argument completion. - * *_tilde*: Escape tilde in [[ $1 == \~* ]] tests (RedHat: #817902). - * New completions: - - acpi, hwclock, pwd, ssh-add, vmstat - - [ Sung Pae ] - * Workaround bash bug that fails to complete <, > - - -- David Paleino <d.paleino@gmail.com> Sun, 17 Jun 2012 20:01:36 +0200 - -bash-completion (1.99) - - * Hopefully the last 2.0 preview. - - [ David Paleino ] - * Correctly list purgeable packages for dpkg --listfiles and dpkg - --purge (Debian: #647684) - * Fix bash_completion paths in README (Debian: #647941) - - [ Florian Hubold ] - * xv: Add *.eps and *.ps to filename completions (Alioth: #313477) - - [ Igor Murzov ] - * Add and use _sysvdirs() function that sets correct SysV init - directory. - * cppcheck: Add new options introduced in cppcheck-1.52. - * cppcheck: Several ids separated by commas can be given for - --enable=. - * _known_hosts_real: Add some quotes (Alioth #313158) - * Merge completions/service into the bash_completion script. - * _modules: Follow symlinks in /lib/modules/$(uname -r) (Alioth: - #313461) - * mount, umount: Add linux-specific completions. - * mount: Don't suggest short options. - * pidof: Don't check OS type (Alioth #311403) - * removepkg: Make it possible to complete filenames. - * umount: Fix for completion of relative paths. - * upgradepkg: Support oldpackage%newpackage notation. - * wine: Complete all files after an .exe (Alioth #313131) - * New completions: - - htop, nethogs. - - [ Jan Kratochvil ] - * rpm: Treat -r as --root (RedHat: #759224). - - [ Raphaël Droz ] - * Added a word about compopt -o nospace in styleguide.txt. - * _ip_addresses: Make it locale agnostic. - - [ Ville Skyttä ] - * cc, c++: Install gcc completion if compiler looks like GCC - (Alioth: #311408). - * cppcheck: Offer header filename completions too. - * curl: Add bunch of new option argument completions. - * dequote: Use printf instead of echo (Alioth: #312163). - * dict: Speed up word completion with common use cases and large - word lists. - * dmesg: Adapt to versions returning long options. - * Document $split && return. - * _filedir, _tilde: Ignore compopt stderr for direct invocations in - unit tests. - * Include doc/ in dist tarball. - * _known_hosts_real: Handle more than two hostnames per known hosts - line (Debian: #647352). - * _known_hosts_real: Include hosts reported by ruptime (Alioth: - #313308). - * _known_hosts_real: Support > 1 files per *KnownHostsFile line - (Debian: #650514). - * lintian: Use <<< instead of echo and a pipe (Alioth: #312163). - * lrzip: -T no longer takes an argument since version 0.570. - * _mac_addresses: Grab addresses from FreeBSD's ifconfig -a output - too. - * make: Add -j/--jobs completion, complete up to number of CPUs * 2. - * _muttconffiles: Use printf instead of echo (Alioth: #312163). - * _parse_help, _parse_usage: If first arg is "-", read from stdin. - * rpm: Add --delsign completion, don't suggest --resign (identical - to --addsign). - * _variables: New function split from _init_completion. - * vi and friends: Fix /etc/ld.so.conf.d/* completion (Alioth: - #312409). - * New completions: - - plague-client, desktop-file-validate, valgrind, ccache, iperf, - koji, lzip, udevadm. - - -- David Paleino <d.paleino@gmail.com> Sat, 07 Jan 2012 23:52:36 +0100 - -bash-completion (1.90) - - * bash-completion 2 preview: dynamic loading of completions. - - [ David Paleino ] - * If _filedir 'ext' returns nothing, just fallback to generic file - completion. It is optional, and off by default. Patch by Clint Byrum - (Debian: #619014, LP: #533985) - * Fix __get_cword_at_cursor_by_ref: check for $index when completing with a - cword+1 argument already present (Debian: #622383) - * Layout change: everything is now in /usr/share/bash-completion/, rather - than in /etc/. - * Get rid of BASH_COMPLETION_DIR, BASH_COMPLETION_HELPERS_DIR, BASH_COMPLETION - * Fix autotools to use pkgdatadir instead of redefining datadir, get rid of - helpersdir. - * Implemented a blacklist for unwanted third-parties completions - * New completions: - - epdfview, lpr and lpq (Raphaël Droz), mysql (Raphaël Droz) - * Improved completions: - - ant: handle "extension-point" the same as "target" tag (Petr Kozelka, - Alioth: #313105) - - apt: add 'download' to subcommands (Debian: #625234, Ubuntu: #720541) - - aptitude: add 'versions' command (Debian: #604393) - - dpkg-query: use the 'dpkg' completion (Debian: #642526) - - lintian: remove --unpack-level (Debian: #623680) - - {shadow,coreutils}: fix broken _allowed_groups usage - - rrdtool: complete filenames after commands (Debian: #577933) - - sitecopy: fixed a bug with grep and brackets: use sitecopy -v to fetch - sites (Raphaël Droz). - - [ Freddy Vulto ] - * Improve __reassemble_comp_words_by_ref() (Alioth #313057) - * Testsuite: - - add -unsorted option to _get_hosts() - - [ Guillaume Rousse ] - * Use $() for subshell, instead of backquotes - * Use simple quotes for constant strings - * Drop -o filenames, as suggested by Ville - * New completions: puppet - - [ Igor Murzov ] - * Abort completion file loading earlier if required commands are not - available. - * docs: Improve tester's manual - * Make completions that use _command also work with file names - * _command_offset: Restore compopts used by called command. - * New completions: - - pkgtool, makepkg, rmp2tgz, slapt-get, slapt-src, slackpkg, kcov, feh, - xgamma, fbi, fbgs - * Improved completions: - - file: ddd few missing --exclude arguments completions - - host, nslookup: Remove completions for bind utils from bash_completion. - - {install,upgrade,explode}pkg: use -o plusdirs instead of -o dirnames - - makepkg: should complete filenames - - removepkg, upgradepkg, installpkg: add option completion - - xrandr: Add more option completions. - - overall clean up of different slackware-specific completions - * Testsuite: - - add basic tests for pkgtools, rpm2tgz, slapt, sbopkg, slackpkg - - fix broken tests for finger and xhost - - remove unused -expect-cmd-full option from assert_complete* - - [ Sergey V ] - * New completions: sbopkg - - [ Ville Skyttä ] - * Load completions in separate files dynamically, get rid of have() - * Drop unnecessary $USERLAND checks - * Try /usr/sbin before /sbin in have() - * Try both full path and basename completions for sudo etc (Alioth: #313065) - * Add _init_completion() for common completion initialization and generic - redirection handling - * Replace actual sysconfdir in bash_completion on install (Alioth: #313081) - * Drop support for bash < 4.1 - * Drop no longer needed _compopt_o_filenames() - * Drop no longer needed "type compopt" checks - * docs: Update "simply sourcing" instructions to match new layout, check - $PS1. - * Get rid of bash_completion self-parsing from _filedir_xspec - (RedHat: #479936). - * Provide profile.d hook for per user disabling of bash_completion - (Debian: #593835) - * New completions: - - a2x, arping, asciidoc, base64, cal, chrpath, cppcheck, curl, dmesg, - dot, file, gnome-mplayer, gprof, hddtemp, host, htpasswd, idn, ionice, - jps, lbunzip2, lbzip2, lbzcat, prelink, protoc, pwdx, pwgen, reptyr, - sum (RedHat: #717341), watch - - phing: reuse ant completion (Elan Ruusamäe, Alioth: #312910) - - pinfo: reuse info completion - * Improved completions: - - bluez, e2fsprogs, grpck, java (Mattias Ulbrich), passwd, pwck, route, - rsync, smartctl - - ant: improve -lib, -find/-s, and -D argument completions; rewrite build - target parsing in plain bash, add build file test case - - aspell: add --add-filter|--rem-filter completions; get --mode completions - from 'aspell modes' output - - bzip2, gzip, python, sysbench: quote command argument to _parse_help() - - chsh: use _allowed_users instead of plain compgen -u - - cksfv: add -g argument completion - - cpan2dist: don't hang if no package list files exist - - crontab: use /sys/fs/selinux and /selinux instead of /etc/selinux to - find out if SELinux is around - - cvs: (diff) parse options from cvs diff instead of plain diff; drop -o - default to fix CVS root completions; (commit) complete on entries - instead of default if COMP_CVS_REMOTE is not set; improve CVS - controlled file completions; add CVS controlled file completions for - admin and update; list "primary" command names first in mode switch; - recognize some additional commands and synonyms; add editors/watchers - completion; sort mode completions alphabetically - - freeciv: complete freeciv-* in addition to civclient/civserver - - gdb: improve filename completion - - gendiff: do file completion after output redirection - - getent: add gshadow to known databases; allow multiple completions from - same db, add option completion - - info: add option completion support - - ipsec (Tobias Brunner): drop uname check, add strongSwan specific - completion with fallback, complete connection names for 'up', 'down' and - other commands - - jar: complete on *.sar (JBoss service archive) - - java, javac: add -X* completions - - javadoc: implement -linkoffline two argument completion - - killall: activate completion on Darwin (Alioth: #312350) - - (la)tex (Ted Pavlic): add *.dbj to filename completions (RedHat: #678122) - - man: add option parsing and completion - - modplug*: add more extensions for files supported by libmodplug - - mutt: support tildes when recursively sourcing muttrc files - (Debian: #615134); expand tilde in mutt query command (Alioth: #312759) - - ntpdate: add some option argument (non)completions - - oo{writer,impress,calc,draw} (Matej Cepl): complete on LibreOffice - FlatXML extensions (RedHat: #692548) - - perldoc (Scott Bronson): override MANPAGER when generating perldoc - completions (RedHat: #689180); don't parse man page when we know it'll - produce no completions; use perldoc itself instead of man - - pgrep: add option and option argument completions - - rpm: make rpm --queryformat use more consistent; drop rpm query support - for rpm < 4.1 - - rpmbuild: add --buildpolicy completion - - rpmcheck: drop reference to undefined $files variable (Alioth: #313270) - - screen: add _terms() and -T completion; add commands completion - (Alioth: #312164, RedHat: #547852) - - _services: avoid bogus completions when init or xinetd dirs exist but are - empty; include systemd services - - smartctl: fix short alternative for --tolerance - - ssh, scp, sftp, ssh-copy-id: add some option argument (non)completions - - strace: don't append space for -e *= completions; don't try to extract - syscall names if they're not going to be used; rewrite arch specific - syscall extraction in plain bash - - svn*: don't suggest short options - - tar: fix completion of files inside *.tar.bz2 archives when [Ijy] is not - given; added option completions; improve tar *[cr]*f completions - (Debian: #618734) - - unzip: complete on *.sar (JBoss service archive) - - xmllint, xmlwf: complete on *.tld (tag library descriptor) - - xmlwf: add -v non-completion - - xmms: add some option argument completions - - xz: apply xz completion to pxz too; non-complete - --memlimit{,-compress,-decompress} - * Testsuite: - - add basic tests for gendiff, mdadm, puppet, xzdec, mii-diag, mii-tool, - grpck, passwd, pwck, samba, rdesktop, fusermount, tcpdump, l2ping, - ssh-copy-id, postfix, qemu, ldap*, medusa, mdtool, monodevelop, - msynctool, cfagent, lpr, lpq, mysql, nslookup, compare, conjure, - import, stream - - fix tests for ri - - fix get_hosts option docs. - - add test case for Debian: #622383. - - add chown foo: and :foo test cases, should complete files - (RedHat: #710714) - - -- David Paleino <d.paleino@gmail.com> Thu, 03 Nov 2011 09:53:55 +0000 - -bash-completion (1.3) - - [ Guillaume Rousse ] - * added pure-perl perldoc completion helper, using work from Aristotle - Pagaltzis (pagaltzis@gmx.de) - * added completions for xfreerdp and iscsiadm - * updated xm subcommands list - - [ David Paleino ] - * Fixed "service" completion, thanks to John Hedges (Debian: #586210) - * Complete on all files for mplayer's -dvd-device - * Fixed typo in openssl completion (Debian: #609552) - - [ Ville Skyttä ] - * Activate hping2 completion also for hping and hping3. - * Add badblocks, compgen, crontab, dumpe2fs, e2freefrag, e2label, ether-wake, - filefrag, gendiff, growisofs, iftop, ip (Debian: #600617), javaws, kid3, - lrzip, lsof, mktemp, portecle, POSIX sh, sha{,224,256,384,512}sum, - sysbench, tune2fs, xmodmap, and xrdb completions. - * Add *.gif (Alioth: #312512), *.m2t (Alioth: #312770), *.3gpp, *.3gpp2, - *.awb, and *.iso (Alioth: #311420) to mplayer filename completions. - * Add "short" tarball extensions to unxz, unlzma etc completions. - * Improve /etc/init.d/*, ipmitool, jar, java, javadoc, man, mencoder, mkdir, - mplayer, pack200, povray, python, rpmbuild, sqlite3, tar, wodim, and - general help parsing completions. - * Fix p4 and povray completions (Alioth: #312625). - * Add *.xsd, *.xsl, *.rng, *.wsdl, and *.jnlp to xmllint and xmlwf filename - completions, and *.gz versions of all of the supported ones for xmllint. - * Recognize rpm query mode based on the --file, --group, --package, and - --all long options (RedHat: #630328). - * Improve rpm query option completions. - * Drop bad kompare filename completion (Alioth: #312708). - * Make _filedir and _filedir_xspec complete uppercase versions of their - filename extension arguments in addition to exact case matches. - * IPv6 known hosts completion fixes (Alioth: #312695, RedHat: #630658). - * Fixes to completions for filenames containing tabs (RedHat: #629518). - * Add *.iso (Alioth: #311420), *.m2t and *.m2ts (Alioth: #312770) to - xine-based player filename completions. - * Add /etc/ethers to MAC address completion sources. - * Add *.gem and *.spkg to tar filename completions. - * Complete known hosts from avahi-browse only if $COMP_KNOWN_HOSTS_WITH_AVAHI - is non-empty (Alioth: #312691, RedHat: #630326). - * Improve relevance of many user/group completions, depending on context. - * Remove most "-o filenames" options to "complete", turn "-o filenames" on - dynamically when needed instead. - * Add/improve various autotools completions. - * Add *.apk to unzip and jar filename completions. - * Do not load bash_completion in profile.d script if progcomp is not enabled. - * Ignore muttrc source entries that are not files (Alioth: #312881). - * Re-enable postgresql database and user completion (Alioth: #312914, - Ubuntu: #164772). - * Add *.fdf to various PDF viewer completions. - - [ Freddy Vulto ] - * Added _tilde(), fix ~username completion (Alioth: #312613, Debian: #587095) - * Speed up `compopt' availability detection - * Fix _filedir `-o filenames' detection on bash-3 (Alioth: #312646) - * Fix __reassemble_comp_words_by_ref (Alioth #312740) - - [ Anton Khirnov ] - * Improve mplayer and mencoder completions. - - [ Paul Walmsley ] - * Add *.webm to mplayer file completions (Debian: #588079). - - [ Miklos Vajna ] - * Add *.amr to mplayer file completions (Alioth: #312634). - - [ Andrej Gelenberg ] - * Add *.part (partially downloaded) to mplayer and xine-based player - completions (Alioth: #312657). - - [ Stephen Gildea ] - * Fix false posives for non-option words in _parse_help (Alioth: #312750). - - [ Andrey G. Grozin ] - * Add *.fb2 to okular filename completions. - - -- David Paleino <d.paleino@gmail.com> Sun, 06 Feb 2011 19:03:46 +0100 - -bash-completion (1.2) - - [ David Paleino ] - * Don't use pidof in _known_hosts_real() to detect whether Avahi is - available, since it's not available on MacOS X. Thanks to Rainer - Müller <raimue@codingfarm.de> (bash-completion MacPorts maintainer) - * Fixed "freq" and "rate" completion for iwconfig - * contrib/munin-node fixed (Debian: #550943) - * contrib/dpkg fixed -W and --show completing on .?(u)deb's (Debian: #552109) - * contrib/aptitude: add @(add|remove)-user-tag - * Added munindoc completion to contrib/munin-node, thanks to Tom - Feiner (Debian: #553371) - * Added colordiff completion, same as diff - * contrib/cpio: added missing completions for -?, --help, --license, --usage, - --version and (-p) --to-stdout (Debian: #557436) - * Style policy: don't use fancy globbing in case labels - * Added .fdf completion to okular and evince - * Added .okular completion to okular (Debian: #545530) - * Added lintian completion - * Refreshed reportbug completion, added --from-buildd (Debian: #579471) - * Special-case "apt-get source" (Debian: #572000) - * Added lintian completion (Debian: #547361) - * contrib/dpkg: update completion to current API - * Styleguide: establish line wrapping and $() instead of `` - - [ Ville Skyttä ] - * Create bz2 dist tarball too. - * Include CHANGES in dist tarball. - * Include profile snippet in tarball, install it. - * Rename contrib/bluez-utils to contrib/bluez to follow bluez 4.x naming. - * Apply cardctl completion to pccardctl too. - * Apply pine completion to alpine too. - * Remove many unnecessary short option completions where long ones exist. - * Improve chsh, chgrp, chown, configure, curl, cvs, find, gkrellm, gzip, - iconv, lftp, look, lzma, make, man, mdadm, modprobe, mount, mplayer, - mysqladmin, perldoc, rsync, screen, service, scp, ssh, sshfs, unzip, - update-alternatives, vncviewer, wget, yp-tools, xine based players' and - general hostname completions. - * Add abook and wtf completion, based on work by Raphaël Droz. - * Add cvsps, dragon, fusermount, jarsigner, k3b, lftpget, modplug123, - pm-utils, rtcwake, pack200, unpack200, pbzip2, pbunzip2, pbzcat, pigz, - unpigz, and wol completions. - * Don't overwrite other host completions when completing from multiple - SSH known hosts files. - * Speed up installed rpm package completion on SUSE, based on work by - Marco Poletti (Alioth: #312021). - * Improve sourcing snippets from completion dirs. - * Drop support for bash < 3. The compatibility global variables $bashN, - $default, $dirnames, $filenames, $compopt, $nospace, $bashdefault, and - $plusdirs have been dropped too. 3rd party completions should switch - to using the complete/compgen features directly, and BASH_VERSINFO - for bash version checks. - * Protect various completions from unusual user input by not embedding the - input in external command arguments (Debian: #552631). - * Add /sbin to $PATH when invoking ifconfig and iwconfig. - * Combine dcop and qdbus completions into the latter. - * awk and sed usage portability fixes (Alioth: #311393, Debian: #501479). - * Fix leaking local variables from various completions. - * Turn on -o filenames in _filedir on bash >= 4. - * Deprecate modules completion, upstream modules >= 3.2.7 ships one. - * Protect grep invocations from user aliases (Alioth: #312143). - * Split sshfs completion from contrib/ssh into contrib/sshfs. - * Split mount and umount completion into contrib/mount. - * Split service completion into contrib/service. - * Split chown, chgrp, and id completions into contrib/coreutils. - * Split kill, look, and renice completions into contrib/util-linux. - * Split killall, pkill, pgrep and related completions into contrib/procps. - * Split ipsec completion into contrib/ipsec. - * Split ifup and ifdown completions into contrib/ifupdown. - * Do basic HTML file completion with Firefox and Chrome and friends, - and Epiphany. - * Do basic diff/patch completion with cdiff and kompare. - * Don't install mock completion by default, it's in upstream mock > 1.1.0. - * Do basic text editor completion with xemacs, sxemacs, kate, and kwrite. - * Do meta-command completion for aoss and padsp. - - [ Freddy Vulto ] - * Prevent root PATH expansion prolifering in _root_command (bash >= 4.1.4) - * Only complete xhost if (_)xhost is available. - * Added _get_comp_words_by_ref to replace both _get_cword & _get_pword. - Also additional variables `words' and `cword' can be returned. - * Added _upvar & _upvars helper functions to aid in passing variables - by reference. - * Make _filedir emulate `-o filenames' - * Fixed completion perl modules containing colons. - * Merged __get_cword3 & __get_cword4 to _get_cword. - * Added __expand_tilde_by_ref helper function. - * Added __ltrim_colon_completions to fix completions containing colons - * Improved mutt completion - * Added _get_pword helper function, thanks to Sung Pae (Alioth: #312030) - - [ Ted Stern ] - * Fix modules completion for "(default)" entries. - - [ Jeremie Lasalle Ratelle ] - * Fix rsync remote path completion (Alioth: #312173, Gentoo: #297818). - - [ Leonard Crestez ] - * Improve ssh -o suboption completion (Alioth: #312122). - * Fix NFS mounts completion (Alioth: #312285). - * Fix completion of usernames (Alioth: #311396, Debian: #511788). - * Fix chown test crashing on systems with no root group (Alioth: #312306). - * Fixed tests when BASH_COMPLETION or TESTDIR contain spaces. - * Fix mount handling of escapes (Alioth: #311410, Launchpad: #219971, - Debian: #511149). - * Cleanup scripts to run tests. Make runUnit and runCompletion use test/run. - Make it possible to run tests from any directory. - * Add a --debug-xtrace option to test/run using BASH_XTRACEFD from bash-4.1. - * Add a --timeout option to test/run to override the default expect timeout. - - [ Raphaël Droz ] - * Add xsltproc completion (Alioth: #311843). - - [ Adrian Friedli ] - * Add ipv6calc completion. - - [ Ildar Mulyukov ] - * Add showmount completion (Alioth: #312285). - - [ Neville Gao ] - * Fix mount completion error "bash: [: too many arguments" (Alioth #312381). - - [ Austin English ] - * Make lookup of wine file completions case insensitive. - - [ Igor Murzov ] - * Improve xz completion (Alioth: #312466). - - [ Mario Schwalbe ] - * Update find completion (Alioth: #312491, Launchpad: #570113). - - [ Mark van Rossum ] - * Add basic lyx completion. - - -- David Paleino <d.paleino@gmail.com> Wed, 16 Jun 2010 17:44:59 +0200 - -bash-completion (1.1) - - [ David Paleino ] - * Permit .gz files concatenation (Debian: #514377) - * Fix svk completion using $filenames instead of $default (Debian: #524961) - * Really add build-dep to aptitude's completion (Debian: #495883) - * Fix checks for GNUish userland, thanks to Robert Millan (Debian: #529510) - * Fix typo in .ass subtitles completion for mplayer (Debian: #531337) - * Fix regression on man(1) completion: also complete on local .3pm files - (Debian: #531343) - * Split mutt completion to contrib/mutt - * Split iconv completion to contrib/iconv - * Split dict completion to contrib/dict - * Split {update,invoke}-rc.d completions to contrib/sysv-rc - * Don't install _subversion anymore, upstream completion is better than - ours. Added to EXTRA_DIST in Makefile.am - * Split autorpm completion to contrib/autorpm - * Split jar completion to contrib/jar - * Split chkconfig completion to contrib/chkconfig - * Split chsh completion to contrib/chsh - * Split apt_build completion to contrib/apt-build - * Split aptitude-related completions to contrib/aptitude - * Split apt-cache and apt-get completions to contrib/apt - * Split rpm-related completions to contrib/rpm - * Split cvs-related completions to contrib/cvs - * Split man completion to contrib/man - * Split bash builtins completions to contrib/bash-builtins - * Split dpkg-related completions to contrib/dpkg (and re-enable usage - of grep-status if available) - * Split gcc completion to contrib/gcc - * Split dselect completion to contrib/dselect - * Split cardctl completion to contrib/cardctl - * Split pineaddr completion to contrib/pine - * Added avahi-discovered hosts to _known_hosts_real() (Debian: #518561) - * Added m4v completion to mplayer (Debian: #504213) - * Improve qemu completion (Debian: #534901) - * Added sshfs completion (shares the same as scp) (Debian: #545978) - * Fixed obvious brokenness (typos) in contrib/mdadm - * Clean [1.2.3.4]:port format in known_hosts, thanks to - Xuefer (Gentoo: #284563) - * Added --no-generate to "apt-cache pkgnames" calls, make it faster - on certain configurations (Debian: #547550) - * Split okular from evince filename extension completion, needed to add - okular-specific completions: xps, epub, odt, fb, mobi, g3 and chm. - Also, okular can read any of its formats also in .gz/.bz2 compressed - format, so change the regular expression to match this. - * Remove --with-suggests and --without-suggests from aptitude completion - * Patches from PLD Linux (thanks to Elan Ruusamäe): - - avoid sed pipe as ps itself can omit the headers - - improve service(8) completion, also look for "msg_usage" - - [ Ville Skyttä ] - * Split yum completion to contrib/_yum (no longer installed by default, the - intent is to move it to yum upstream soon). - * Split yum-arch completion into contrib/yum-arch, load completion only if - yum-arch is installed. - * Update list of yum commands and options. - * Add yum repolist, --enable/disablerepo, --disableexcludes, -d, -e, --color, - and --enable/disableplugin completions. - * Add chkconfig --override and resetpriorities completions. - * Split mplayer and friends completions to contrib/mplayer. - * Parse top level mplayer and friends option completions from -list-options. - * Fix dir-only completion for make to include only dirs, not files. - * Remove unused variable RELEASE. - * Improve aspell dictionary completion: don't hardcode data-dir, get - canonical dicts from "aspell dicts". - * Always use /etc/shells for chsh -s completion, don't complete on comment - lines in it. - * Fix rpm --whatrequires/--whatprovides completions with spaces and other - unusual characters, add filename based --whatrequires completions. - * Add modplugplay filename completion. - * Add more mod-like audio file extensions for xine-based players and timidity. - * Complete on plain alternatives like update-alternatives. - * Rename installed_alternatives() to _installed_alternatives(). - * Add /etc/pki/tls/openssl.cnf to list of default openssl config files, - search for default ones only if -config is not given. - * Use POSIX compliant arguments to tail in mkisofs completion. - * Protect various completions from unusual user input by not embedding the - input in external command arguments. - * Add _split_longopt() helper for improved handling of long options that - take arguments in both "--foo bar" and "--foo=bar" formats. - * Use _split_longopt to improve and clean up aspell, bluez-utils, chgrp, - chown, chkconfig, cpio, dpkg, heimdal, iptables, mailman, make, mc, - mii-diag, mii-tool, mkinitrd, pkg-config, postgresql, quota, reportbug, - samba, smartctl, yum, and generic long option completion (Alioth: #311398). - * Add chown --from and --reference value completions. - * Add chgrp --reference value completion. - * Do not assume all --foo= options take filenames in generic long option - completion, assume only that --*file*= does, and that --*dir*= takes dirs. - * Add make --old/new-file, --assume-old/new, --what-if value completions. - * Add smartctl -n/--nocheck completion, add more other value completions. - * Fix leaking $prev from cpio, dsniff, freeciv, gkrellm, mkinitrd, service, - and tcpdump completions. - * Split ant completion to contrib/ant, improve the built in one. - * Improve postfix completion. - * Improve samba completion. - * Split lilo completion to contrib/lilo. - * Split reportbug and querybts completions to contrib/reportbug. - * Remove debug output noise from quotaon completion. - * Split Linux wireless tools completion to contrib/wireless-tools. - * Add mock completion. - * Split FreeBSD kld(un)load completion to contrib/kldload. - * Split FreeBSD pkg_* completion to contrib/pkg_install. - * Split FreeBSD portupgrade and friends completion to contrib/portupgrade. - * Split Slackware pkgtools completion to contrib/pkgtools. - * Improve rpm group completion (displayed completions are still wrong). - * Change many completions to load in memory only if the completed commands - are available. - * Invoke the actual mplayer/mencoder command being completed (with full path) - to get various completions instead of simply "mplayer" or "mencoder". - * Associate OOXML/MS Office 2007 extensions with OpenOffice applications. - * Associate .tsv with oocalc. - * Add xmlwf completion. - * Associate *.po with poedit, gtranslator, kbabel, and lokalize. - * Add xz, xzcat, xzdec, and unxz completion. - * Add lzcat, lz*grep, lzless, lzmore, and unlzma completion. - * Load "modules" completion if /etc/profile.d/modules.sh exists even if - the "module" alias has not been defined (yet). - * Add *.ogv to xine-based players (Debian: #540033). - * Add $compopt (":" i.e. no-op with bash < 4, "compopt" with >= 4). - * Complete bzcat and zcat only on compressed files. - * Do not require a dot in bzcmp, bzdiff, bz*grep, zcmp, zdiff, z*grep, zless, - and zmore filename completions. - * Add xz and compress support and more tarball filename extensions to - rpmbuild -t*/--tarbuild completion. - * Don't hardcode path to lsmod. - * Fix sbcl file/dirname completion (Debian: #545743). - * Add /sbin to $PATH when invoking lspci and lsusb. - * Support .xz suffix in info page completions. - * Prevent rpm --define/-D completions from falling through. - * Add more common options to rpm option completions. - - [ Todd Zullinger ] - * Make yum complete on filenames after install, deplist, update and upgrade - when the following argument contains a slash. - - [ Mike Kelly ] - * Fix _filedir on bash 4. - * Add support for xz to tar completion. - * Fix _quote_readline on bash 4 (Debian: #544024). - - [ Guillaume Rousse ] - * Split mkinitrd completion to contrib/mkinitrd, improve it. - * Split smartctl completion to contrib/smartctl. - * Better ssh and sftp completion - * Better xhost completion - * Split _known_hosts completion in two parts, to avoid parsing command line - twice - * Added strace completion - * Added xm completion - * Added rpcdebug completion - * Added msynctool completion - * Added openldap completion - * Added ldapvi completion - * Added heimdal completion - * Added vpnc completion - * Added rpmcheck completion - * Added munin-node completion - * Added bluez-utils completion - * Added samba completion - * Added cfengine completion - * Added xmllint completion, contributed by Ville - * Added shadow completion, contributed by Ville - * Added repomanage completion, contributed by Ville - * Splitted and enhanced openssl completion - * Added rfkill, mdadm and resolvconf completions - - [ Raphaël Droz ] - * Add mount -L and -U completion. - - [ Philipp Weis ] - * Add .dvi.{gz,bz2} completion for evince/okular (Debian: #522656) - - [ Freddy Vulto ] - * Patched _known_hosts() to support multiple {Global,User}KnownHosts in SSH - config files, thanks to Thomas Nilsson (Alioth: #311595) (Debian: #524190) - * Fix leaking $i from info, man and python completions. - * Added setting COMP_KNOWN_HOSTS_WITH_HOSTFILE. _known_hosts_real() will add - hosts from HOSTFILE, unless COMP_KNOWN_HOSTS_WITH_HOSTFILE is set to an - empty value (Alioth: #311821) - * Quoted $cur to prevent globbing - thanks to Eric Blake (Alioth #311614) - * Fix leaking $muttcmd from mutt completion - * Fix completing multiple hosts (Debian: #535585) - - [ Michele Ballabio ] - - * Add more extensions to pkgtools completion. - - -- David Paleino <d.paleino@gmail.com> Sat, 03 Oct 2009 15:41:49 +0200 - -bash-completion (1.0) - - [ Guillaume Rousse ] - * Make bibtex complete on .aux files - * Add .xvid and .XVID to player completion - * Added cowsay/cowthink completion - * Added brctl completion - * Added cpan2dist completion - * Added qemu completion - * Added net-tools (mii-tool and mii-diag) completions - * Added minicom completion - * Added quota-tools completion - * Added rdesktop completion - * Added tightvncviewer completion - * Cleanup screen completion, and make it completes on options - - [ David Paleino ] - * Added .kar to Timidity completion. - * Fix killall completion, remove trailing ":" on certain process - names - * Fix man -l completing filenames (Debian: #497074) - * (Partly) fixed java classes completion (Debian: #496828). Look for - FIXME in source. - * Dump to /dev/null error message from look(1) with no arguments - (Debian: #495142) - * Set ssh as default for rsync (was rsh) (Debian: #492328) - * Added .oga, .ogv, .ogx to mplayer completion (Debian: #496162) - * Added .epub to unzip|zipinfo completion (Debian: #492476) - * Added ssh-copy-id completion (Debian: #491856) - * Moved ssh completion to separate file (Debian: #360628) - * Bogus completion when mounting subdirs fixed (Debian: #322238) - * Fix `apt-cache showsrc` completing only on source package names - (Debian: #361535) - * Fixed bugs with gdb completion: - - when an empty directory is in $PATH (thanks to Morita Sho) - (Debian: #497597) - - when a non-existing directory is in $PATH (Debian: #499780) - * Fix missing completion for "-n" and "-e" (we were using echo, now - using printf) (thanks to Morita Sho) (Debian: #498105) - * Fixed gpg completion: - - --@(export|@(?(l|nr|nrl)sign|edit)-key)) (Debian: #500316) - - -@(r|-recipient)) - * Fixed .cb[rz] completion for evince (Debian: #502885) - * Added gksudo, gksu, kdesudo completion - * Added apache2ctl completion - * Added gpg2 completion (Debian: #489927) - * Fixed mplayer -skin completion (Debian: #501473) - * Fixed errors with POSIX enabled (Debian: #502804) - * Fixed dpkg-source wrong exit() with return() (Debian: #) - * Added --schedule-only to aptitude's completion (Debian: #502664) - * Added build-dep to aptitude's completion (Debian: #495883) - * Added support for `-F configfile' to _known_hosts(), ssh, scp and - sftp, thanks to Freddy Vulto (Debian: #504141) - * Fixed sed quoting bug in _known_hosts(), thanks to Freddy Vulto - (Debian: #504650) - * Allow `Host(Name)' in ssh config file to be indented - * Allow `Host(Name)' in ssh config file to have trailing comment. - * Allow for comments in known_hosts files (Debian: #511789) - * Fixed perl -I/-x completion, thanks to Freddy Vulto - (Debian: #504547) - * README updated: explain how to use bash-completion correctly. - (Debian: #506560) - * TODO updated: the Alioth team is now upstream. - * Added qdbus completion, thanks to Terence Simpson (Ubuntu: #257903) - * Added monodevelop and mdtool completions. - * Split subversion-related completions to contrib/_subversion - (prefixed with _ to avoid file conflicts with upstream's one) - * Fixed completion of environment variables, thanks to Morita Sho - (Debian: #272660) - * Fix dpkg completion bug: it listed only non-Essential packages - (Debian: #511790) - * Fixed _dpkg_source completion (Debian: #503317) - * Added _parse_help() to try to parse options listed in $command - --help - * Fixed gzip completion to use _parse_help(), since the available - options vary with distributions - * Added to_review/ directory, where completions needing a review would - go. After it gets accepted, the completion would go into contrib/. - * Remove unused UNAME local variable in _info() (Debian: #501843) - * AUTHORS added - * Make _alias() use _get_cword - * Added .zip to jar completions (Debian: #521041) - * Merge from Gentoo: - - fix 'find' completion so that it properly completes on -?(i)whilename. - Patch by Ciaran McCreesh. - - use make -qp to parse the Makefile for us, so we get proper completion - on things like pattern rules. Patch by Mike Kelly <pioto@exherbo.org>. - - complete on gkrellm2 as well. Patch by Aaron Walker. - - fix CVS completion - * Merge from Ubuntu: - - consume error messages in configure completion (Ubuntu: #223882) - (Mika Fischer) - - quote $xspec in _filedir_xspec in case it is empty, which would - cause errors if there was no match under failglob. (Ubuntu: #194419) - (Mika Fischer) - * debian/links fixed (Debian: #494292) - * debian/control: - - fixed typo in the long description - - added Vcs-* fields - * debian/install: - - correctly install contrib/* under /etc/bash_completion.d/ - * debian/copyright updated - * extra/dh_bash-completion: - - updated to support a list of files in debian/<package>.bash-completion - (Debian: #512917) - - [ Ville Skyttä ] - * Added JPEG 2000 files to display completion, thanks to Bastien Nocera - (RedHat: #304771) - * Improved rpm macro completion. - * Added -E to rpm completion. - * Improved rpm backup file avoidance. - * Improved /var/log/rpmpkgs based rpm installed package completion. - * Improved performance of rpm -qa based rpm installed package completion. - * Improved features and performance of yum completion. - * Added support for p (POSIX) and x (x.org) man sections. - * Improved filename based man page completion. - * Added minimal sqlite3 completion. - * Improved getent completion (Ville Skyttä, Guillaume Rousse). - * (Re)fix gzip and bzip2 options completion. - * Improved svn filename completion (RedHat: #430059). - * Add lzma completion (Per Øyvind Karlsen, Ville Skyttä). - * Add .mp2 and .vdr to mplayer completion (RedHat: #444467). - * Add .mkv, .mp2 and .vdr to *xine completion (RedHat: #444467). - * Added lzop completion. - * Fix scp metacharacter escaping. - * Remove duplicate cpio completion, thanks to Freddy Vulto (Debian: #512823) - * Fix awk error in "modprobe -r /" completion (Debian: #512556). - * Expand ~foo to dir name more eagerly to avoid quoting issues. - * Fix -sourcepath handling in javadoc packages completion. - * Extract process name completion from _killall to _pnames, make it work - for others than Linux and FreeBSD. - * Fix process name completion with relative paths (RedHat: #484578). - * Use improved process name completion in pgrep in addition to killall. - * Enable pgrep and pkill completion if the commands are available, not just - on Linux and FreeBSD. - * Drop hg completion, an improved version is shipped with Mercurial - (contrib/bash_completion in the tarball). - * Make okular complete on same files as evince, thanks to Mary Ellen Foster - (RedHat: #486998). - * Apply ps2pdf completion to ps2pdf{12,13,14,wr} too. - * Simplify bash_completion.sh, return earlier in non-applicable environments. - * Remove obsolete --buildarch and --buildos rpm(build) completions. - * Add rpmbuild --target completion. - * Use "-profile help" to get mplayer and friends -profile completions. - * Fix local array initialization under bash 3.0, prevents "()" occurring in - file and dir name completions. - - [ Freddy Vulto ] - * Restored `_display()' completion for `display' by removing - completion-by-extension for `display' (Alioth#311429) - * Removed duplicate completion option `-borderwidth' for `display' - * Prevent completion dir from being sourced twice if - BASH_COMPLETION_DIR and BASH_COMPLETION_COMPAT_DIR are equal (Alioth#311433) - * Make `_mii-tool()' and `_mii-diag()' POSIX-compliant - * Fix _isql completion waiting for grep input if $ODBCINI not set; handle - whitespace in $ODBCINI. - * Split vncviewer completion in _tightvncviewer() and _xvnc4viewer() - Added _realcommand() global function. - - [ Jakob Unterwurzacher ] - * ps2pdf can run on .pdf files as well. (Debian: #516614, Ubuntu: #316943) - - [ Santiago M. Mola ] - * Add .ape to mplayer supported extensions (Alioth#311510). - - -- David Paleino <d.paleino@gmail.com> Wed, 25 Mar 2009 23:18:24 +0100 - -bash-completion (20080705) unstable; urgency=low - - [ David Paleino ] - * Added more completions to imagemagick (thanks to Nelson A. de - Oliveira) (Debian: #487786) - * Added xrandr completion (thanks to Anton Khirnov) (Debian: #487825) - * Improving _gdb completion: - - $filenames to $default (Debian: #463969) - - also show directory names (i.e. compgen -d) in COMPREPLY. - - added . to $PATH, to allow debugging "local" executables. - - do not complete Bash's builtins (thanks to Morita Sho) - - [ Luk Claes ] - * Remove use of ucf for /etc/bash-completion (Debian: #488171). - - -- Luk Claes <luk@debian.org> Sat, 05 Jul 2008 16:14:15 +0200 - -bash-completion (20080617.5) unstable; urgency=medium - - * Revert way of setting environment variables (Debian: #487774). - * Add equals sign to _get_cword for mutt_aliases (Debian: #482635). - * Enhance mlayer completion (Debian: #487826, #487838). - - -- Luk Claes <luk@debian.org> Tue, 24 Jun 2008 19:50:57 +0200 - -bash-completion (20080617.4) experimental; urgency=low - - [ David Paleino ] - * Merged Ubuntu changes: - - added quote(), quote_readline(), dequote() helper functions. - - added _remove_word() - - fixed _get_cword() - - refactored _filedir using quote_readline() - - refactored _filedir_xspec using quote_readline() - - fixed COMPREPLY's in _iwconfig - - fixed _cvs() - - _known_hosts(): use files from UserKnownHostsFile options in - addition to standard ones. - - fixed _command() to correctly prune the command line - - disabled completion of PostgreSQL users and databases (Ubuntu: #164772) - - fixed _java_packages() - - fixed _muttquery() - - added flv/FLV completion to mplayer - - added --installed to apt-cache - - only complete on filenames for aspell - - fixed code for exclusions compspecs - - added code to gracefully handle debug options (set +/-v) - - -- Luk Claes <luk@debian.org> Mon, 23 Jun 2008 19:25:25 +0200 - -bash-completion (20080617.3) unstable; urgency=low - - [ David Paleino ] - * Fixed IFS for filedir_xspec - Thanks to Stefan Lippers-Hollmann - (Debian: #487571) - - [ Luk Claes ] - * Install dh-bash-completion to ease installation of completions. - - -- Luk Claes <luk@debian.org> Mon, 23 Jun 2008 07:24:21 +0200 - -bash-completion (20080617.2) unstable; urgency=low - - [ David Paleino ] - * New upstream release - - provide a manpage for extra/dh_bash-completion - - fix semi-serious problem with _filedir() (Debian: #487449) - * debian/rules: - - added rule to generate dh_bash-completion's manpage - * debian/install, debian/dirs: - - installing dh_bash-completion into /usr/bin - * debian/control: - - new package dh-bash-completion - - [ Luk Claes ] - * Comment new package to make sure current fix gets in the archive first. - * Add compression completion for vi(m). - - -- Luk Claes <luk@debian.org> Sun, 22 Jun 2008 19:47:23 +0200 - -bash-completion (20080617.1) unstable; urgency=medium - - [ David Paleino ] - * Urgency set to medium because the package is currently unusable. - * New upstream sub-release - - fixed some typos here and there which prevented bash completions - at all (Debian: #487441). - - really closing Debian bug #455510. - - -- Luk Claes <luk@debian.org> Sun, 22 Jun 2008 00:22:53 +0200 - -bash-completion (20080617) unstable; urgency=low - - [ David Paleino ] - * New upstream release - - add more completions to aptitude (Debian: #432289) - - fixed UTF-8 problem with _get_cword(), thanks to - Andrei Paskevich (Debian: #472132) - - fixed autoremove completion, thanks to Flavio Visentin - (Debian: #474974) - - cmf and CMF added to playmidi completion (Debian: #365658) - - added rrdtool completion, thanks to Justin Pryzby (Debian: #428641) - - added OpenDocument completion for unzip/zipinfo (.od{f,g,p,s,t}) - (Debian: #472940) - - fixed escaping problems with job control (i.e. disown, jobs, bg, - fg): the argument is now surrounded by "" (Debian: #347316) - - make mkdir complete also on filenames (Debian: #376433) - - {bz,z}{cat,cmp,diff,egrep,fgrep,grep,less,more} now should complete - on all filenames, not just compressed archives (just commented out) - (Debian: #455510) - - fixes Perl completion (Debian: #470742) - - fixes get_cword -> _get_cword typo (Debian: #478596) - - fixes _get_cword() function to properly handle filenames with - whitespaces (Debian: #394636, #468254, #474094) - - added .pdf.bz2 completion to evince (Debian: #424736) - - added .svg completion to display (Debian: #441017) - - added .m2ts completion to mplayer (Debian: #480879) - - added extra/dh_bash-completion to ease future rewrite of bc. - * debian/copyright - now in a fancier machine-parsable format. - * debian/control: - - added myself to Uploaders - - debhelper Build-Depends updated to >= 6. - * debian/watch: - - improved current watch line regex - - added (commented out) probable future watch line - * debian/compat bumped to 6 - * debian/dirs, debian/install and debian/links added - * debian/rules: - - refactored to make use of debian/{dirs,install,links} - - [ Steve Kemp ] - * Applied patch to fix completion of umount command. - (Debian: #470539) - * Fixed the completion of Perl manpages. - (Debian: #404976) - * Added 'aif' to the filenames offed for completion for mplayer. - (Debian: #474517) - * Allow tsocks completion. - (Debian: #409423) - * Update mutt completion to handle local usernames. - (Debian: #416655) - * Update apt-get completion to include the flag "--no-install-recommends" - (Debian: #475242) - - -- Luk Claes <luk@debian.org> Sat, 21 Jun 2008 21:59:43 +0200 - -bash-completion (20060301-4) unstable; urgency=low - - * Add some fixes from Ubuntu: - * Fix completion of filenames with spaces (Debian: #468254). - * Fix parsing of SSH config files (Debian: #435117). - * Change priority to standard (Debian: #471666). - * Add some more completions for xine (Debian: #452083, #471249). - * Fix completion of gzip (Debian: #351913). - * Also use $HOSTFILE in hostname completion (Debian: #400380). - - -- Luk Claes <luk@debian.org> Sat, 22 Mar 2008 23:10:30 +0000 - -bash-completion (20060301-3) unstable; urgency=low - - * Fix kpdf completion (Debian: #468163, #413374). - * Fix completion of - or -- with _command (Debian: #415276). - * Add sux to the complete -u list (Debian: #466089). - * Add dvipdfm to the list of dvi programs (Debian: #396644). - * Add --purge-unused option completion for aptitude (Debian: #438471). - * Add divx extension completion for mplayer (Debian: #444294). - * Add pdf.gz completion for evince (Debian: #456887). - * Add --remove-all completion for update-alternatives (Debian: #269173). - - -- Luk Claes <luk@debian.org> Wed, 05 Mar 2008 22:57:27 +0100 - -bash-completion (20060301-2) unstable; urgency=low - - * Take over the package. - - -- Luk Claes <luk@debian.org> Wed, 27 Feb 2008 19:22:03 +0100 - -bash-completion (20060301-1) unstable; urgency=low - - * Upload to unstable. - - -- Matthias Klose <doko@debian.org> Sat, 09 Feb 2008 23:18:20 +0100 - -bash-completion (20060301-0ubuntu2) hardy; urgency=low - - * Replace bash (<< 3.1dfsg-9), handle upgrade in preinst. - * Exclude hashed hostnames from ssh host completion results. Debian: #428085. - * Fix: ifup/down don't really complete. Debian: #463756. - * Allow perl completion to complete filenames, complete -I and -x arguments. - Debian: #443394. - * Add find -wholename completion. Debian: #431220. - * Handle whitespaces in $HOME for _known_hosts() completion. Debian: #414821. - * dpkg -L: complete for removed-but-not-purged packages. Debian: #372156. - * Complete for apt-get autoremove. Debian: #433542, #443816, #445332. - * Update completion for mplayer (mka/flac). Debian: #340452. - * Add ping6/fping6 completion. Debian: #413170. - * Handle whitespace in paths for mount/umount completion. Debian: #367957. - * apt-get: Support --auto-remove. Ubuntu: #60666. - - -- Matthias Klose <doko@ubuntu.com> Sat, 09 Feb 2008 23:11:32 +0100 - -bash-completion (20060301-0ubuntu1) hardy; urgency=low - - * Initial release, split out from the bash package. - The software currently is unsupported upstream. - * Don't try to set a readonly variable. Ubuntu: #149527. - * Support purge in apt-get auto completion (Mathias Gug). Ubuntu: #151677. - * evince: Autocomplete on cbr/cbz/djvu files. Ubuntu: #156200, #175220. - Debian: #400678. - * kdvi: complete .*\.dvi\.(gz|bz2). Ubuntu: #128234. - * kpdf: Complete postscript files. Ubuntu: #162319. - * Make completion working in the middle of a word (Adam Simpkins). - Ubuntu: #139666. - - -- Matthias Klose <doko@ubuntu.com> Fri, 08 Feb 2008 16:46:34 +0100 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9c8292c..d19b5cd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,15 +28,23 @@ your completion to be usable without having bash-completion installed. It's nowhere near clear cut always what is the best place for the completion, upstream project or us. Even if it would seem to be upstream, not all upstreams are interested in shipping completions, or their install systems might not -easily support installing completion files properly. But give it some thought, -and ask if unsure. +easily support installing completion files properly. Or the projects might be +stagnant. But give it some thought, and ask if unsure. If you wish to contribute code to us, volunteering for long term maintainership -of your code within bash-completion is welcome. When exactly you will be asked -to do that depends on the case; don't be disappointed if it does or doesn't -happen instantly. +of your code within bash-completion is welcome, and stating willingness for +that goes a long way in getting your contribution accepted. There are a lot of +completions in bash-completion already, and chances are that existing +maintainers might not want to add completions they don't actively use +themselves into their maintenance workload. When exactly you will be asked to +join the project depends on the case; there are no real, consistent "rules" for +that. Don't be disappointed if it does or doesn't happen instantly. -Also, please bare the following coding guidelines in mind: +Also, please bear the following coding guidelines in mind: + +- See the related documents, [API and naming](doc/api-and-naming.md) and + [Coding style guide](doc/styleguide.md), for information about conventions to + follow related to those topics. - Do not use Perl, Ruby, Python etc. to do text processing unless the command for which you are writing the completion code implies the @@ -59,11 +67,11 @@ Also, please bare the following coding guidelines in mind: external programs, which are expensive to fork and execute, so do make full use of those: - `?(pattern-list)` - match zero or one occurrences of patterns - `*(pattern-list)` - match zero or more occurrences of patterns - `+(pattern-list)` - match one or more occurrences of patterns - `@(pattern-list)` - match exactly one of the given patterns - `!(pattern-list)` - match anything except one of the given patterns + - `?(pattern-list)` - match zero or one occurrences of patterns + - `*(pattern-list)` - match zero or more occurrences of patterns + - `+(pattern-list)` - match one or more occurrences of patterns + - `@(pattern-list)` - match exactly one of the given patterns + - `!(pattern-list)` - match anything except one of the given patterns - Following on from the last point, be sparing with the use of external processes whenever you can. Completion functions need to be @@ -100,23 +108,30 @@ Also, please bare the following coding guidelines in mind: - We want our completions to work in `posix` and `nounset` modes. - Unfortunately due to a bash < 5.1 bug, toggling POSIX mode interferes - with keybindings and should not be done. This rules out use of - process substitution which causes syntax errors in POSIX mode. + Unfortunately due to a bash < 5.1 bug, toggling POSIX mode + interferes with keybindings and should not be done. This rules out + use of process substitution which causes syntax errors in POSIX mode + of bash < 5.1. Instead of toggling `nounset` mode, make sure to test whether variables are set (e.g. with `[[ -v varname ]]`) or use default expansion (e.g. `${varname-}`). -- Prefer `compgen -W '...' -- $cur` over embedding `$cur` in external - command arguments (often e.g. sed, grep etc) unless there's a good - reason to embed it. Embedding user input in command lines can result - in syntax errors and other undesired behavior, or messy quoting - requirements when the input contains unusual characters. Good - reasons for embedding include functionality (if the thing does not - sanely work otherwise) or performance (if it makes a big difference - in speed), but all embedding cases should be documented with - rationale in comments in the code. +- Prefer `_comp_compgen_split -- "$(...)"` over embedding `$cur` in external + command arguments (often e.g. sed, grep etc) unless there's a good reason to + embed it. Embedding user input in command lines can result in syntax errors + and other undesired behavior, or messy quoting requirements when the input + contains unusual characters. Good reasons for embedding include + functionality (if the thing does not sanely work otherwise) or performance + (if it makes a big difference in speed), but all embedding cases should be + documented with rationale in comments in the code. + + Do not use `_comp_compgen -- -W "$(...)"` or `_comp_compgen -- -W '$(...)'` + but always use `_comp_compgen_split -- "$(...)"`. In the former case, when + the command output contains strings looking like shell expansions, the + expansions will be unexpectedly performed, which becomes a vulnerability. In + the latter case, checks by shellcheck and shfmt will not be performed inside + `'...'`. Also, `_comp_compgen_split` is `IFS`-safe. - When completing available options, offer only the most descriptive ones as completion results if there are multiple options that do the @@ -131,7 +146,7 @@ Also, please bare the following coding guidelines in mind: `--something` do the same thing and require an argument, offer only `--something` as a completion when completing option names starting with a dash, but do implement required argument processing for all - `-s`, `-S`, and `--something`. Note that GNU versions of various + `-s`, `-S`, and `--something`. Note that GNU versions of various standard commands tend to have long options while other userland implementations of the same commands may not have them, and it would be good to have the completions work for as many userlands as @@ -149,6 +164,17 @@ Also, please bare the following coding guidelines in mind: - Make small, incremental commits that do one thing. Don't cram unrelated changes into a single commit. +- We use [Conventional Commits](https://www.conventionalcommits.org/) + to format commit messages, with types and most other details from + [commitlint's config-conventional](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional). + `gitlint` in our pre-commit config checks commit messages for + conformance with these rules. + + It is important to do this correctly; commit types `fix` and `feat` + as well as any change marked as breaking affects what ends up in the + release notes, and what will the next bash-completion release's + (semantic) version be. + - If your code was written for a particular platform, try to make it portable to other platforms, so that everyone may enjoy it. If your code works only with the version of a binary on a particular @@ -181,6 +207,25 @@ Also, please bare the following coding guidelines in mind: - In addition to running the test suite, there are a few scripts in the test/ dir that catch some common issues, see and use for example runLint. +- Make sure you have Python 3.7 or later installed. This is required for + running the development tooling, linters etc. Rest of the development + Python dependencies are specified in `test/requirements-dev.txt` which + can be fed for example to `pip`: + + ```shell + python3 -m pip install -r test/requirements-dev.txt + ``` + +- Install pre-commit and set it up, see <https://pre-commit.com/>. + That'll run a bunch of linters and the like, the same as the + bash-completion CI does. Running it locally and fixing found issues before + commit/push/PR reduces some roundtrips with the review. + After installing it, enable it for stages we use it with like: + + ```shell + pre-commit install --hook-type pre-commit --hook-type commit-msg + ``` + - File bugs, enhancement, and pull requests at GitHub, <https://github.com/scop/bash-completion>. Sending them to the developers might work too, but is really strongly @@ -1,12 +1,12 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public @@ -56,7 +56,7 @@ patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. - GNU GENERAL PUBLIC LICENSE + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains @@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN @@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - END OF TERMS AND CONDITIONS + END OF TERMS AND CONDITIONS - How to Apply These Terms to Your New Programs + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it diff --git a/Makefile.am b/Makefile.am index 26f3c7c..27366b7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,7 +4,7 @@ pkgdata_DATA = bash_completion # Empty, but here just to get the compat dir created with install compatdir = $(sysconfdir)/bash_completion.d -compat_DATA = +compat_DATA = bash_completion.d/000_bash_completion_compat.bash profiledir = $(sysconfdir)/profile.d profile_DATA = bash_completion.sh @@ -28,10 +28,11 @@ cmakeconfig_DATA = bash-completion-config.cmake \ CLEANFILES = bash_completion.sh bash-completion.pc \ bash-completion-config.cmake bash-completion-config-version.cmake -EXTRA_DIST = CHANGES $(pkgdata_DATA) bash_completion.sh.in .dir-locals.el \ +EXTRA_DIST = CHANGELOG.md $(pkgdata_DATA) bash_completion.sh.in .dir-locals.el \ .editorconfig README.md CONTRIBUTING.md pyproject.toml .perltidyrc \ .shellcheckrc bash-completion.pc.in bash-completion-config.cmake.in \ - bash-completion-config-version.cmake.in setup-symlinks.sh + bash-completion-config-version.cmake.in setup-symlinks.sh \ + $(compat_DATA) install-data-hook: tmpfile=`mktemp $${TMPDIR:-/tmp}/bash_completion.XXXXXX` && \ @@ -1,6 +1,6 @@ # bash-completion -[![Build Status](https://travis-ci.org/scop/bash-completion.svg?branch=master)](https://travis-ci.org/scop/bash-completion) +[![CI](https://github.com/scop/bash-completion/actions/workflows/ci.yaml/badge.svg)](https://github.com/scop/bash-completion/actions/workflows/ci.yaml) ## Introduction @@ -17,7 +17,8 @@ list of operating system distributions, package names, and available versions. Depending on the package, you may still need to source it from either `/etc/bashrc` or `~/.bashrc` (or any -other file sourcing those). You can do this by simply using: +other file sourcing those). If you have _only_ bash >= 4.2 installed, you can +do this by simply using: ```shell # Use bash-completion, if available @@ -25,26 +26,28 @@ other file sourcing those). You can do this by simply using: . /usr/share/bash-completion/bash_completion ``` -(if you happen to have *only* bash >= 4.2 installed, see further if not) +If you have older bash versions in use, their loading of `bash_completion` +should be prevented. See further for more info. If you don't have the package readily available for your distribution, or you simply don't want to use one, you can install bash completion using the standard commands for GNU autotools packages: ```shell -autoreconf -i # if not installing from prepared release tarball +autoreconf -i # if not installing from prepared release tarball ./configure -make # GNU make required -make check # optional, requires python3 with pytest >= 3.6, pexpect -make install # as root +make # GNU make required +make check # optional +make install # as root +make installcheck # optional, requires python3 with pytest >= 3.6, pexpect ``` These commands install the completions and helpers, as well as a `profile.d` script that loads `bash_completion` where appropriate. If your system does not use the `profile.d` directory (usually below -`/etc`) mechanism—i.e. does not automatically source shell scripts in -it—you can source the `$sysconfdir/profile.d/bash_completion.sh` +`/etc`) mechanism (i.e., does not automatically source shell scripts in +it), you can source the `$sysconfdir/profile.d/bash_completion.sh` script in `/etc/bashrc` or `~/.bashrc`. The `profile.d` script provides a configuration file hook that can be @@ -73,10 +76,15 @@ fi If you find that a given function is producing errors or does not work as it should under certain circumstances when you attempt completion, -try running `set -v` or `set -x` prior to attempting the completion +try running `set -x` or `set -v` prior to attempting the completion again. This will produce useful debugging output that will aid us in fixing the problem if you are unable to do so yourself. Turn off the -trace output by running either `set +v` or `set +x`. +trace output by running either `set +x` or `set +v`. + +If you are filing an issue, please attach the generated debugging output +in `set -x` mode copy-pasted to a separate, attached file in the report. +Before doing so, be sure to review the output for anything you may not want +to share in public, and redact as appropriate. To debug dynamic loading of a completion, tracing needs to be turned on before the debugged completion is attempted the first time. The @@ -85,13 +93,7 @@ tracing on in it before doing anything else there. ## Known problems -1. There seems to be some issue with using the bash built-in `cd` within - Makefiles. When invoked as `/bin/sh` within `Makefile`s, bash seems - to have a problem changing directory via the `cd` command. A - work-around for this is to define `SHELL=/bin/bash` within your - `Makefile`. This is believed to be a bug in bash. - -2. Many of the completion functions assume GNU versions of the various +1. Many of the completion functions assume GNU versions of the various text utilities that they call (e.g. `grep`, `sed`, and `awk`). Your mileage may vary. @@ -111,11 +113,12 @@ A. No. Use `M-/` to (in the words of the bash man page) attempt file A. Install a local completion of your own appropriately for the desired command, and it will take precedence over the one shipped by us. See the - next answer for details where to install it, if you are doing it on per - user basis. If you want to do it system wide, you can install eagerly - loaded files in `compatdir` (see a couple of questions further down for - more info) and install a completion for the commands to override our - completion for in them. + next answer for details where to install it, if you are doing it on per user + basis. If you want to do it system wide, you can install eagerly loaded + files in `compatdir` (see a couple of questions further down for more + info. To get the path of `compatdir` for the current system, the output of + `pkg-config bash-completion --variable compatdir` can be used) and install a + completion for the commands to override our completion for in them. If you want to use bash's default completion instead of one of ours, something like this should work (where `$cmd` is the command to override @@ -137,20 +140,28 @@ A. Put them in the `completions` subdir of `$BASH_COMPLETION_USER_DIR` completion code for this package. Where should I put it to be sure that interactive bash shells will find it and source it?** -A. Install it in one of the directories pointed to by - bash-completion's `pkgconfig` file variables. There are two - alternatives: +A. [ Disclaimer: Here, how to make the completion code visible to + bash-completion is explained. We do not require always making the + completion code visible to bash-completion. In what condition the + completion code is installed should be determined at the author/maintainers' + own discretion. ] + + Install it in one of the directories pointed to by bash-completion's + `pkgconfig` file variables. There are two alternatives: - The recommended directory is `completionsdir`, which you can get with `pkg-config --variable=completionsdir bash-completion`. From this directory, completions are automatically loaded on demand based on invoked commands' names, so be sure to name your completion file accordingly, and to include (for example) symbolic links in case the file provides - completions for more than one command. - - The other directory (which only present for backwards compatibility) - is `compatdir` (get it with - `pkg-config --variable=compatdir bash-completion`) from which files - are loaded when `bash_completion` is loaded. + completions for more than one command. The completion filename for + command `foo` in this directory should be either `foo`, or `foo.bash`. + (Underscore prefixed `_foo` works too, but is reserved for + bash-completion internal use as a deprecation/fallback marker.) + - The other directory which is only present for backwards compatibility, + its usage is no longer recommended, is `compatdir` (get it with + `pkg-config --variable=compatdir bash-completion`). From this + directory, files are loaded eagerly when `bash_completion` is loaded. For packages using GNU autotools the installation can be handled for example like this in `configure.ac`: @@ -165,7 +176,7 @@ A. Install it in one of the directories pointed to by ```makefile bashcompdir = @bashcompdir@ - dist_bashcomp_DATA = # completion files go here + dist_bashcomp_DATA = your-completion-file # completion files go here ``` For cmake we ship the `bash-completion-config.cmake` and @@ -186,57 +197,27 @@ A. Install it in one of the directories pointed to by ${BASH_COMPLETION_COMPLETIONSDIR}) ``` -**Q. I use CVS in combination with passwordless SSH access to my remote - repository. How can I have the `cvs` command complete on remotely - checked-out files where relevant?** - -A. Define `$COMP_CVS_REMOTE`. Setting this to anything will result in - the behaviour you would like. - -**Q. When I'm running a `./configure` script and completion returns a list - of long options to me, some of these take a parameter, - e.g. `--this-option=DESCRIPTION`.** - - **Running `./configure --help` lists these descriptions, but - everything after the `=` is stripped when returning completions, so - I don't know what kind of data is expected as a given option's - parameter.** - - **Is there a way of getting `./configure` completion to return the - entire option string, so that I can see what kind of data is - required and then simply delete the descriptive text and add my own - data?** - -A. Define `$COMP_CONFIGURE_HINTS`. Setting this to anything will - result in the behaviour you would like. + In bash-completion >= 2.12, we search the data directory of + `bash-completion` under the installation prefix where the target command is + installed. When one can assume that the version of the target + bash-completion is 2.12 or higher, the completion script can actually be + installed to `$PREFIX/share/bash-completion/completions/` under the same + installation prefix as the target program installed under `$PREFIX/bin/` or + `$PREFIX/sbin/`. For the detailed search order, see also "Q. What is the + search order for the completion file of each target command?" below. -**Q. When doing tar completion on a file within a tar file like this:** + Example for `Makefile.am`: - ```shell - tar tzvf foo.tar.gz <Tab> + ```makefile + bashcompdir = $(datarootdir)/bash-completion/completions + dist_bashcomp_DATA = your-completion-file ``` - **the pathnames contained in the tar file are not displayed - correctly. The slashes are removed, and everything looks like it's - in a single directory. Why is this?** - -A. It's a choice we had to make. bash's programmable completion is - limited in how it handles the list of possible completions it - returns. - - Because the paths returned from within the tar file are likely not - existing paths on the file system, `-o dirnames` must be passed to - the `complete` built-in to make it treat them as such. However, - then bash will append a space when completing on directories during - pathname completion to the tar files themselves. + Example for `CMakeLists.txt`: - It's more important to have proper completion of paths to tar files - than it is to have completion for their contents, so this sacrifice - was made and `-o filenames` is used with complete instead. - - If you would rather have correct path completion for tar file - contents, define `$COMP_TAR_INTERNAL_PATHS` *before* sourcing - `bash_completion`. + ```cmake + install(FILES your-completion-file DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/bash-completion/completions") + ``` **Q. When completing on a symlink to a directory, bash does not append the trailing `/` and I have to hit <kbd><Tab></kbd> again. @@ -286,7 +267,7 @@ A. Probably because the database is being queried every time and this uses a You can make this faster by pregenerating the list of installed packages on the system. Make sure you have a readable file called - `/var/log/rpmpkgs`. It's generated by `/etc/cron.daily/rpm` on + `/var/log/rpmpkgs`. It's generated by `/etc/cron.daily/rpm` on some Red Hat and Mandrake and derivative Linux systems. If you don't have such a cron job, make one: @@ -302,13 +283,15 @@ A. Probably because the database is being queried every time and this uses a unless it detects that the database has changed since the file was created, in which case it will still use the database to ensure accuracy. -**Q. bash-completion interferes with my `command_not_found_handler` function!** +**Q. bash-completion interferes with my `command_not_found_handle` function + (or the other way around)!** -A. If your `command_not_found_handler` function is not intended to +A. If your `command_not_found_handle` function is not intended to address (possibly missing) commands invoked during bash programmable completion functions, you can account for this - by, for example, testing if the `$COMP_`\* variables are set and - taking appropriate bypass or other action. + in the function by, for example, testing if the `$COMP_LINE` + variable is set and taking appropriate action, typically returning + early and silently with success. **Q. Can tab completion be made even easier?** @@ -345,3 +328,28 @@ A. Absolutely not. zsh has an extremely sophisticated completion system that offers many features absent from the bash implementation. Its users often cannot resist pointing this out. More information can be found at <https://www.zsh.org/>. + +**Q. What is the search order for the completion file of each target command?** + +A. The completion files of commands are looked up by the shell function + `__load_completion`. Here, the search order in bash-completion >= 2.12 is + explained. + + 1. `BASH_COMPLETION_USER_DIR`. The subdirectory `completions` of each paths + in `BASH_COMPLETION_USER_DIR` separated by colons is considered for a + completion directory. + 2. The location of the main `bash_completion` file. The subdirectory + `completions` in the same directory as `bash_completion` is considered. + 3. The location of the target command. When the real location of the command + is in the directory `<prefix>/bin` or `<prefix>/sbin`, the directory + `<prefix>/share/bash-completion/completions` is considered. + 4. `XDG_DATA_DIRS` (or the system directories `/usr/local/share:/usr/share` + if empty). The subdirectory `bash-completion/completions` of each paths + in `XDG_DATA_DIRS` separated by colons is considered. + + The completion files of the name `<cmd>` or `<cmd>.bash`, where `<cmd>` is + the name of the target command, are searched in the above completion + directories in order. The file that is found first is used. When no + completion file is found in any completion directories in this process, the + completion files of the name `_<cmd>` is next searched in the completion + directories in order. diff --git a/bash_completion b/bash_completion index 1a7f563..e245cc5 100644 --- a/bash_completion +++ b/bash_completion @@ -23,12 +23,16 @@ # # https://github.com/scop/bash-completion -BASH_COMPLETION_VERSINFO=(2 11) +BASH_COMPLETION_VERSINFO=( + 2 # x-release-please-major + 12 # x-release-please-minor + 0 # x-release-please-patch +) if [[ $- == *v* ]]; then - BASH_COMPLETION_ORIGINAL_V_VALUE="-v" + _comp__init_original_set_v="-v" else - BASH_COMPLETION_ORIGINAL_V_VALUE="+v" + _comp__init_original_set_v="+v" fi if [[ ${BASH_COMPLETION_DEBUG-} ]]; then @@ -37,13 +41,60 @@ else set +v fi -# Blacklisted completions, causing problems with our code. -# -_blacklist_glob='@(acroread.sh)' - # Turn on extended globbing and programmable completion shopt -s extglob progcomp +# Declare a compatibility function name +# @param $1 Version of bash-completion where the deprecation occurred +# @param $2 Old function name +# @param $3 New function name +# @since 2.12 +_comp_deprecate_func() +{ + if (($# != 3)); then + printf 'bash_completion: %s: usage: %s DEPRECATION_VERSION OLD_NAME NEW_NAME\n' "$FUNCNAME" "$FUNCNAME" + return 2 + fi + if [[ $2 != [a-zA-Z_]*([a-zA-Z_0-9]) ]]; then + printf 'bash_completion: %s: %s\n' "$FUNCNAME" "\$2: invalid function name '$1'" >&2 + return 2 + elif [[ $3 != [a-zA-Z_]*([a-zA-Z_0-9]) ]]; then + printf 'bash_completion: %s: %s\n' "$FUNCNAME" "\$3: invalid function name '$2'" >&2 + return 2 + fi + eval -- "$2() { $3 \"\$@\"; }" +} + +# Declare a compatibility variable name. +# For bash 4.3+, a real name alias is created, allowing value changes to +# "apply through" when the variables are set later. For bash versions earlier +# than that, the operation is once-only; the value of the new variable +# (if it's unset) is set to that of the old (if set) at call time. +# +# @param $1 Version of bash-completion where the deprecation occurred +# @param $2 Old variable name +# @param $3 New variable name +# @since 2.12 +_comp_deprecate_var() +{ + if (($# != 3)); then + printf 'bash_completion: %s: usage: %s DEPRECATION_VERSION OLD_NAME NEW_NAME\n' "$FUNCNAME" "$FUNCNAME" + return 2 + fi + if [[ $2 != [a-zA-Z_]*([a-zA-Z_0-9]) ]]; then + printf 'bash_completion: %s: %s\n' "$FUNCNAME" "\$2: invalid variable name '$1'" >&2 + return 2 + elif [[ $3 != [a-zA-Z_]*([a-zA-Z_0-9]) ]]; then + printf 'bash_completion: %s: %s\n' "$FUNCNAME" "\$3: invalid variable name '$2'" >&2 + return 2 + fi + if ((BASH_VERSINFO[0] >= 5 || BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] >= 3)); then + eval "declare -gn $2=$3" + elif [[ -v $2 && ! -v $3 ]]; then + printf -v "$3" %s "$2" + fi +} + # A lot of the following one-liners were taken directly from the # completion examples provided with the bash 2.04 source distribution @@ -67,9 +118,6 @@ complete -A setopt set # shopt completes with shopt options complete -A shopt shopt -# helptopics -complete -A helptopic help - # unalias completes with aliases complete -a unalias @@ -83,7 +131,8 @@ complete -b builtin # Check if we're running on the given userland # @param $1 userland to check for -_userland() +# @since 2.12 +_comp_userland() { local userland=$(uname -s) [[ $userland == @(Linux|GNU/*) ]] && userland=GNU @@ -92,94 +141,135 @@ _userland() # This function sets correct SysV init directories # -_sysvdirs() +# @since 2.12 +_comp_sysvdirs() { sysvdirs=() [[ -d /etc/rc.d/init.d ]] && sysvdirs+=(/etc/rc.d/init.d) [[ -d /etc/init.d ]] && sysvdirs+=(/etc/init.d) # Slackware uses /etc/rc.d [[ -f /etc/slackware-version ]] && sysvdirs=(/etc/rc.d) - return 0 + ((${#sysvdirs[@]})) } # This function checks whether we have a given program on the system. # -_have() +# @since 2.12 +_comp_have_command() { # Completions for system administrator commands are installed as well in # case completion is attempted via `sudo command ...'. - PATH=$PATH:/usr/sbin:/sbin:/usr/local/sbin type $1 &>/dev/null -} - -# Backwards compatibility for compat completions that use have(). -# @deprecated should no longer be used; generally not needed with dynamically -# loaded completions, and _have is suitable for runtime use. -have() -{ - unset -v have - _have $1 && have=yes + PATH=$PATH:/usr/sbin:/sbin:/usr/local/sbin type "$1" &>/dev/null } # This function checks whether a given readline variable # is `on'. # -_rl_enabled() +# @since 2.12 +_comp_readline_variable_on() { - [[ "$(bind -v)" == *$1+([[:space:]])on* ]] + [[ $(bind -v) == *$1+([[:space:]])on* ]] } # This function shell-quotes the argument -quote() +# @param $1 String to be quoted +# @var[out] REPLY Resulting string +# @since 2.12 +_comp_quote() { - local quoted=${1//\'/\'\\\'\'} - printf "'%s'" "$quoted" + REPLY=\'${1//\'/\'\\\'\'}\' } -# @see _quote_readline_by_ref() -quote_readline() -{ - local ret - _quote_readline_by_ref "$1" ret - printf %s "$ret" -} # quote_readline() - -# This function shell-dequotes the argument -dequote() +# shellcheck disable=SC1003 +_comp_dequote__initialize() { - eval printf %s "$1" 2>/dev/null + unset -f "$FUNCNAME" + local regex_param='\$([_a-zA-Z][_a-zA-Z0-9]*|[-*@#?$!0-9_])|\$\{[!#]?([_a-zA-Z][_a-zA-Z0-9]*(\[([0-9]+|[*@])\])?|[-*@#?$!0-9_])\}' + local regex_quoted='\\.|'\''[^'\'']*'\''|\$?"([^\"$`!]|'$regex_param'|\\.)*"|\$'\''([^\'\'']|\\.)*'\''' + _comp_dequote__regex_safe_word='^([^\'\''"$`;&|<>()!]|'$regex_quoted'|'$regex_param')*$' +} +_comp_dequote__initialize + +# This function expands a word using `eval` in a safe way. This function can +# be typically used to get the expanded value of `${word[i]}` as +# `_comp_dequote "${word[i]}"`. When the word contains unquoted shell special +# characters, command substitutions, and other unsafe strings, the function +# call fails before applying `eval`. Otherwise, `eval` is applied to the +# string to generate the result. +# +# @param $1 String to be expanded. A safe word consists of the following +# sequence of substrings: +# +# - Shell non-special characters: [^\'"$`;&|<>()!]. +# - Parameter expansions of the forms $PARAM, ${!PARAM}, +# ${#PARAM}, ${NAME[INDEX]}, ${!NAME[INDEX]}, ${#NAME[INDEX]} +# where INDEX is an integer, `*` or `@`, NAME is a valid +# variable name [_a-zA-Z][_a-zA-Z0-9]*, and PARAM is NAME or a +# parameter [-*@#?$!0-9_]. +# - Quotes \?, '...', "...", $'...', and $"...". In the double +# quotations, parameter expansions are allowed. +# +# @var[out] REPLY Array that contains the expanded results. Multiple words or +# no words may be generated through pathname expansions. +# +# Note: This function allows parameter expansions as safe strings, which might +# cause unexpected results: +# +# * This allows execution of arbitrary commands through extra expansions of +# array subscripts in name references. For example, +# +# declare -n v='dummy[$(echo xxx >/dev/tty)]' +# echo "$v" # This line executes the command 'echo xxx'. +# _comp_dequote '"$v"' # This line also executes it. +# +# * This may change the internal state of the variable that has side effects. +# For example, the state of the random number generator of RANDOM can change: +# +# RANDOM=1234 # Set seed +# echo "$RANDOM" # This produces 30658. +# RANDOM=1234 # Reset seed +# _comp_dequote '"$RANDOM"' # This line changes the internal state. +# echo "$RANDOM" # This fails to reproduce 30658. +# +# We allow these parameter expansions as a part of safe strings assuming the +# referential transparency of the simple parameter expansions and the sane +# setup of the variables by the user or other frameworks that the user loads. +# @since 2.12 +_comp_dequote() +{ + REPLY=() # fallback value for unsafe word and failglob + [[ $1 =~ $_comp_dequote__regex_safe_word ]] || return 1 + eval "REPLY=($1)" 2>/dev/null # may produce failglob } -# Assign variable one scope above the caller -# Usage: local "$1" && _upvar $1 "value(s)" -# Param: $1 Variable name to assign value to -# Param: $* Value(s) to assign. If multiple values, an array is -# assigned, otherwise a single value is assigned. -# NOTE: For assigning multiple variables, use '_upvars'. Do NOT -# use multiple '_upvar' calls, since one '_upvar' call might -# reassign a variable to be used by another '_upvar' call. -# See: https://fvue.nl/wiki/Bash:_Passing_variables_by_reference -_upvar() -{ - echo "bash_completion: $FUNCNAME: deprecated function," \ - "use _upvars instead" >&2 - if unset -v "$1"; then # Unset & validate varname - if (($# == 2)); then - eval $1=\"\$2\" # Return single value - else - eval $1=\(\"\$"{@:2}"\"\) # Return array - fi +# Unset the given variables across a scope boundary. Useful for unshadowing +# global scoped variables. Note that simply calling unset on a local variable +# will not unshadow the global variable. Rather, the result will be a local +# variable in an unset state. +# Usage: local IFS='|'; _comp_unlocal IFS +# @param $* Variable names to be unset +# @since 2.12 +_comp_unlocal() +{ + if ((BASH_VERSINFO[0] >= 5)) && shopt -q localvar_unset; then + shopt -u localvar_unset + unset -v "$@" + shopt -s localvar_unset + else + unset -v "$@" fi } # Assign variables one scope above the caller # Usage: local varname [varname ...] && -# _upvars [-v varname value] | [-aN varname [value ...]] ... +# _comp_upvars [-v varname value] | [-aN varname [value ...]] ... # Available OPTIONS: # -aN Assign next N values to varname as array # -v Assign single value to varname -# Return: 1 if error occurs -# See: https://fvue.nl/wiki/Bash:_Passing_variables_by_reference -_upvars() +# @return 1 if error occurs +# @see https://fvue.nl/wiki/Bash:_Passing_variables_by_reference +# @since 2.12 +_comp_upvars() { if ! (($#)); then echo "bash_completion: $FUNCNAME: usage: $FUNCNAME" \ @@ -201,7 +291,8 @@ _upvars() return 1 } # Assign array of -aN elements - [[ "$2" ]] && unset -v "$2" && eval $2=\(\"\$"{@:3:${1#-a}}"\"\) && + # shellcheck disable=SC2015,SC2140 # TODO + [[ $2 ]] && unset -v "$2" && eval "$2"=\(\"\$"{@:3:${1#-a}}"\"\) && shift $((${1#-a} + 2)) || { echo bash_completion: \ "$FUNCNAME: \`$1${2+ }$2': missing argument(s)" \ @@ -211,7 +302,8 @@ _upvars() ;; -v) # Assign single value - [[ "$2" ]] && unset -v "$2" && eval $2=\"\$3\" && + # shellcheck disable=SC2015 # TODO + [[ $2 ]] && unset -v "$2" && eval "$2"=\"\$3\" && shift 3 || { echo "bash_completion: $FUNCNAME: $1:" \ "missing argument(s)" >&2 @@ -226,6 +318,482 @@ _upvars() done } +# Get the list of filenames that match with the specified glob pattern. +# This function does the globbing in a controlled environment, avoiding +# interference from user's shell options/settings or environment variables. +# @param $1 array_name Array name +# The array name should not start with an underscore "_", which is internally +# used. The array name should not be "GLOBIGNORE". +# @param $2 pattern Pattern string to be evaluated. +# This pattern string will be evaluated using "eval", so brace expansions, +# parameter expansions, command substitutions, and other expansions will be +# processed. The user-provided strings should not be directly specified to +# this argument. +# @return 0 if at least one path is generated, 1 if no path is generated, or 2 +# if the usage is incorrect. +# @since 2.12 +_comp_expand_glob() +{ + if (($# != 2)); then + printf 'bash-completion: %s: unexpected number of arguments\n' "$FUNCNAME" >&2 + printf 'usage: %s ARRAY_NAME PATTERN\n' "$FUNCNAME" >&2 + return 2 + elif [[ $1 == @(GLOBIGNORE|_*|*[^_a-zA-Z0-9]*|[0-9]*|'') ]]; then + printf 'bash-completion: %s: invalid array name "%s"\n' "$FUNCNAME" "$1" >&2 + return 2 + fi + + # Save and adjust the settings. + local _original_opts=$SHELLOPTS:$BASHOPTS + set +o noglob + shopt -s nullglob + shopt -u failglob dotglob + + # Also the user's GLOBIGNORE may affect the result of pathname expansions. + local GLOBIGNORE= + + eval -- "$1=()" # a fallback in case that the next line fails. + eval -- "$1=($2)" + + # Restore the settings. Note: Changing GLOBIGNORE affects the state of + # "shopt -q dotglob", so we need to explicitly restore the original state + # of "shopt -q dotglob". + _comp_unlocal GLOBIGNORE + if [[ :$_original_opts: == *:dotglob:* ]]; then + shopt -s dotglob + else + shopt -u dotglob + fi + [[ :$_original_opts: == *:nullglob:* ]] || shopt -u nullglob + [[ :$_original_opts: == *:failglob:* ]] && shopt -s failglob + [[ :$_original_opts: == *:noglob:* ]] && set -o noglob + eval "((\${#$1[@]}))" +} + +# Split a string and assign to an array. This function basically performs +# `IFS=<sep>; <array_name>=(<text>)` but properly handles saving/restoring the +# state of `IFS` and the shell option `noglob`. A naive splitting by +# `arr=(...)` suffers from unexpected IFS and pathname expansions, so one +# should prefer this function to such naive splitting. +# OPTIONS +# -a Append to the array +# -F sep Set a set of separator characters (used as IFS). The default +# separator is $' \t\n' +# -l The same as -F $'\n' +# @param $1 array_name The array name +# The array name should not start with an underscores "_", which is +# internally used. The array name should not be either "IFS" or +# "OPT{IND,ARG,ERR}". +# @param $2 text The string to split +# @return 2 when the usage is wrong, 0 when one or more completions are +# generated, or 1 when the execution succeeds but no candidates are +# generated. +# @since 2.12 +_comp_split() +{ + local _append="" IFS=$' \t\n' + + local OPTIND=1 OPTARG="" OPTERR=0 _opt + while getopts ':alF:' _opt "$@"; do + case $_opt in + a) _append=set ;; + l) IFS=$'\n' ;; + F) IFS=$OPTARG ;; + *) + echo "bash_completion: $FUNCNAME: usage error" >&2 + return 2 + ;; + esac + done + shift "$((OPTIND - 1))" + if (($# != 2)); then + printf '%s\n' "bash_completion: $FUNCNAME: unexpected number of arguments" >&2 + printf '%s\n' "usage: $FUNCNAME [-al] [-F SEP] ARRAY_NAME TEXT" >&2 + return 2 + elif [[ $1 == @(*[^_a-zA-Z0-9]*|[0-9]*|''|_*|IFS|OPTIND|OPTARG|OPTERR) ]]; then + printf '%s\n' "bash_completion: $FUNCNAME: invalid array name '$1'" >&2 + return 2 + fi + + local _original_opts=$SHELLOPTS + set -o noglob + + local _old_size _new_size + if [[ $_append ]]; then + eval "$1+=()" # in case $1 is unset + eval "_old_size=\${#$1[@]}" + eval "$1+=(\$2)" + else + _old_size=0 + eval "$1=(\$2)" + fi + eval "_new_size=\${#$1[@]}" + + [[ :$_original_opts: == *:noglob:* ]] || set +o noglob + ((_new_size > _old_size)) +} + +# Helper function for _comp_compgen +# @var[in] $? +# @var[in] _var +# @var[in] _append +# @return original $? +_comp_compgen__error_fallback() +{ + local _status=$? + if [[ $_append ]]; then + # make sure existence of variable + eval -- "$_var+=()" + else + eval -- "$_var=()" + fi + return "$_status" +} + +# Provide a common interface to generate completion candidates in COMPREPLY or +# in a specified array. +# OPTIONS +# -a Append to the array +# -v arr Store the results to the array ARR. The default is `COMPREPLY`. +# The array name should not start with an underscores "_", which is +# internally used. The array name should not be any of "cur", "IFS" +# or "OPT{IND,ARG,ERR}". +# -U var Unlocalize VAR before performing the assignments. This option can +# be specified multiple times to register multiple variables. This +# option is supposed to be used in implementing a generator (G1) when +# G1 defines a local variable name that does not start with `_`. In +# such a case, when the target variable specified to G1 by `-v VAR1` +# conflicts with the local variable, the assignment to the target +# variable fails to propagate outside G1. To avoid such a situation, +# G1 can call `_comp_compgen` with `-U VAR` to unlocalize `VAR` +# before accessing the target variable. For a builtin compgen call +# (i.e., _comp_compgen [options] -- options), VAR is unlocalized +# after calling the builtin `compgen` but before assigning results to +# the target array. For a generator call (i.e., _comp_compgen +# [options] G2 ...), VAR is unlocalized before calling the child +# generator function `_comp_compgen_G2`. +# -c cur Set a word used as a prefix to filter the completions. The default +# is ${cur-}. +# -R The same as -c ''. Use raw outputs without filtering. +# -C dir Evaluate compgen/generator in the specified directory. +# @var[in,opt] cur Used as the default value of a prefix to filter the +# completions. +# +# Usage #1: _comp_compgen [-alR|-F sep|-v arr|-c cur|-C dir] -- options... +# Call `compgen` with the specified arguments and store the results in the +# specified array. This function essentially performs arr=($(compgen args...)) +# but properly handles shell options, IFS, etc. using _comp_split. This +# function is equivalent to `_comp_split [-a] -l arr "$(IFS=sep; compgen +# args... -- cur)"`, but this pattern is frequent in the codebase and is good +# to separate out as a function for the possible future implementation change. +# OPTIONS +# -F sep Set a set of separator characters (used as IFS in evaluating +# `compgen'). The default separator is $' \t\n'. Note that this is +# not the set of separators to delimit output of `compgen', but the +# separators in evaluating the expansions of `-W '...'`, etc. The +# delimiter of the output of `compgen` is always a newline. +# -l The same as -F $'\n'. Use lines as words in evaluating compgen. +# @param $1... options Arguments that are passed to compgen (if $1 starts with +# a hyphen `-`). +# +# Note: References to positional parameters $1, $2, ... (such as -W '$1') +# will not work as expected because these reference the arguments of +# `_comp_compgen' instead of those of the caller function. When there are +# needs to reference them, save the arguments to an array and reference the +# array instead. +# +# Note: The array option `-V arr` in bash >= 5.3 should be instead specified +# as `-v arr` as a part of the `_comp_compgen` options. +# @return True (0) if at least one completion is generated, False (1) if no +# completion is generated, or 2 with an incorrect usage. +# +# Usage #2: _comp_compgen [-aR|-v arr|-c cur|-C dir|-i cmd|-x cmd] name args... +# Call the generator `_comp_compgen_NAME ARGS...` with the specified options. +# This provides a common interface to call the functions `_comp_compgen_NAME`, +# which produce completion candidates, with custom options [-alR|-v arr|-c +# cur]. The option `-F sep` is not used with this usage. +# OPTIONS +# -x cmd Call exported generator `_comp_xfunc_CMD_compgen_NAME` +# -i cmd Call internal generator `_comp_cmd_CMD__compgen_NAME` +# @param $1... name args Calls the function _comp_compgen_NAME with the +# specified ARGS (if $1 does not start with a hyphen `-`). The options +# [-alR|-v arr|-c cur] are inherited by the child calls of `_comp_compgen` +# inside `_comp_compgen_NAME` unless the child call `_comp_compgen` receives +# overriding options. +# @var[in,opt,internal] _comp_compgen__append +# @var[in,opt,internal] _comp_compgen__var +# @var[in,opt,internal] _comp_compgen__cur +# These variables are internally used to pass the effect of the options +# [-alR|-v arr|-c cur] to the child calls of `_comp_compgen` in +# `_comp_compgen_NAME`. +# @return Exit status of the generator. +# +# @remarks When no options are supplied to _comp_compgen, `_comp_compgen NAME +# args` is equivalent to the direct call `_comp_compgen_NAME args`. As the +# direct call is slightly more efficient, the direct call is preferred over +# calling it through `_comp_compgen`. +# +# @remarks Design `_comp_compgen_NAME`: a function that produce completions can +# be defined with the name _comp_compgen_NAME. The function is supposed to +# generate completions by calling `_comp_compgen`. To reflect the options +# specified to the outer calls of `_comp_compgen`, the function should not +# directly modify `COMPREPLY`. To add words, one can call +# +# _comp_compgen -- -W '"${words[@]}"' +# +# To directly add words without filtering by `cur`, one can call +# +# _comp_compgen -R -- -W '"${words[@]}"' +# +# or use the utility `_comp_compgen_set`: +# +# _comp_compgen_set "${words[@]}" +# +# Other nested calls of _comp_compgen can also be used. The function is +# supposed to replace the existing content of the array by default to allow the +# caller control whether to replace or append by the option `-a`. +# +# @since 2.12 +_comp_compgen() +{ + local _append= + local _var= + local _cur=${_comp_compgen__cur-${cur-}} + local _dir="" + local _ifs=$' \t\n' _has_ifs="" + local _icmd="" _xcmd="" + local -a _upvars=() + + local _old_nocasematch="" + if shopt -q nocasematch; then + _old_nocasematch=set + shopt -u nocasematch + fi + local OPTIND=1 OPTARG="" OPTERR=0 _opt + while getopts ':av:U:Rc:C:lF:i:x:' _opt "$@"; do + case $_opt in + a) _append=set ;; + v) + if [[ $OPTARG == @(*[^_a-zA-Z0-9]*|[0-9]*|''|_*|IFS|OPTIND|OPTARG|OPTERR|cur) ]]; then + printf 'bash_completion: %s: -v: invalid array name `%s'\''\n' "$FUNCNAME" "$OPTARG" >&2 + return 2 + fi + _var=$OPTARG + ;; + U) + if [[ $OPTARG == @(*[^_a-zA-Z0-9]*|[0-9]*|'') ]]; then + printf 'bash_completion: %s: -U: invalid variable name `%s'\''\n' "$FUNCNAME" "$OPTARG" >&2 + return 2 + elif [[ $OPTARG == @(_*|IFS|OPTIND|OPTARG|OPTERR|cur) ]]; then + printf 'bash_completion: %s: -U: unnecessary to mark `%s'\'' as upvar\n' "$FUNCNAME" "$OPTARG" >&2 + return 2 + fi + _upvars+=("$OPTARG") + ;; + c) _cur=$OPTARG ;; + R) _cur="" ;; + C) + if [[ ! $OPTARG ]]; then + printf 'bash_completion: %s: -C: invalid directory name `%s'\''\n' "$FUNCNAME" "$OPTARG" >&2 + return 2 + fi + _dir=$OPTARG + ;; + l) _has_ifs=set _ifs=$'\n' ;; + F) _has_ifs=set _ifs=$OPTARG ;; + [ix]) + if [[ ! $OPTARG ]]; then + printf 'bash_completion: %s: -%s: invalid command name `%s'\''\n' "$FUNCNAME" "$_opt" "$OPTARG" >&2 + return 2 + elif [[ $_icmd ]]; then + printf 'bash_completion: %s: -%s: `-i %s'\'' is already specified\n' "$FUNCNAME" "$_opt" "$_icmd" >&2 + return 2 + elif [[ $_xcmd ]]; then + printf 'bash_completion: %s: -%s: `-x %s'\'' is already specified\n' "$FUNCNAME" "$_opt" "$_xcmd" >&2 + return 2 + fi + ;;& + i) _icmd=$OPTARG ;; + x) _xcmd=$OPTARG ;; + *) + printf 'bash_completion: %s: usage error\n' "$FUNCNAME" >&2 + return 2 + ;; + esac + done + [[ $_old_nocasematch ]] && shopt -s nocasematch + shift "$((OPTIND - 1))" + if (($# == 0)); then + printf 'bash_completion: %s: unexpected number of arguments\n' "$FUNCNAME" >&2 + printf 'usage: %s [-alR|-F SEP|-v ARR|-c CUR] -- ARGS...' "$FUNCNAME" >&2 + return 2 + fi + if [[ ! $_var ]]; then + # Inherit _append and _var only when -v var is unspecified. + _var=${_comp_compgen__var-COMPREPLY} + [[ $_append ]] || _append=${_comp_compgen__append-} + fi + + if [[ $1 != -* ]]; then + # usage: _comp_compgen [options] NAME args + if [[ $_has_ifs ]]; then + printf 'bash_completion: %s: `-l'\'' and `-F sep'\'' are not supported for generators\n' "$FUNCNAME" >&2 + return 2 + fi + + local -a _generator + if [[ $_icmd ]]; then + _generator=("_comp_cmd_${_icmd//[^a-zA-Z0-9_]/_}__compgen_$1") + elif [[ $_xcmd ]]; then + _generator=(_comp_xfunc "$_xcmd" "compgen_$1") + else + _generator=("_comp_compgen_$1") + fi + if ! declare -F "${_generator[0]}" &>/dev/null; then + printf 'bash_completion: %s: unrecognized generator `%s'\'' (function %s not found)\n' "$FUNCNAME" "$1" "${_generator[0]}" >&2 + return 2 + fi + + ((${#_upvars[@]})) && _comp_unlocal "${_upvars[@]}" + + if [[ $_dir ]]; then + local _original_pwd=$PWD + local PWD=${PWD-} OLDPWD=${OLDPWD-} + # Note: We also redirect stdout because `cd` may output the target + # directory to stdout when CDPATH is set. + command cd -- "$_dir" &>/dev/null || + { + _comp_compgen__error_fallback + return + } + fi + + local _comp_compgen__append=$_append + local _comp_compgen__var=$_var + local _comp_compgen__cur=$_cur cur=$_cur + # Note: we use $1 as a part of a function name, and we use $2... as + # arguments to the function if any. + # shellcheck disable=SC2145 + "${_generator[@]}" "${@:2}" + local _status=$? + + # Go back to the original directory. + # Note: Failure of this line results in the change of the current + # directory visible to the user. We intentionally do not redirect + # stderr so that the error message appear in the terminal. + # shellcheck disable=SC2164 + [[ $_dir ]] && command cd -- "$_original_pwd" + + return "$_status" + fi + + # usage: _comp_compgen [options] -- [compgen_options] + if [[ $_icmd || $_xcmd ]]; then + printf 'bash_completion: %s: generator name is unspecified for `%s'\''\n' "$FUNCNAME" "${_icmd:+-i $_icmd}${_xcmd:+x $_xcmd}" >&2 + return 2 + fi + + # Note: $* in the below checks would be affected by uncontrolled IFS in + # bash >= 5.0, so we need to set IFS to the normal value. The behavior in + # bash < 5.0, where unquoted $* in conditional command did not honor IFS, + # was a bug. + # Note: Also, ${_cur:+-- "$_cur"} and ${_append:+-a} would be affected by + # uncontrolled IFS. + local IFS=$' \t\n' + # Note: extglob *\$?(\{)[0-9]* can be extremely slow when the string + # "${*:2:_nopt}" becomes longer, so we test \$[0-9] and \$\{[0-9] + # separately. + if [[ $* == *\$[0-9]* || $* == *\$\{[0-9]* ]]; then + printf 'bash_completion: %s: positional parameter $1, $2, ... do not work inside this function\n' "$FUNCNAME" >&2 + return 2 + fi + + local _result + _result=$( + if [[ $_dir ]]; then + # Note: We also redirect stdout because `cd` may output the target + # directory to stdout when CDPATH is set. + command cd -- "$_dir" &>/dev/null || return + fi + IFS=$_ifs compgen "$@" ${_cur:+-- "$_cur"} + ) || { + _comp_compgen__error_fallback + return + } + + ((${#_upvars[@]})) && _comp_unlocal "${_upvars[@]}" + _comp_split -l ${_append:+-a} "$_var" "$_result" +} + +# usage: _comp_compgen_set [words...] +# Reset COMPREPLY with the specified WORDS. If no arguments are specified, the +# array is cleared. +# +# When an array name is specified by `-v VAR` in a caller _comp_compgen, the +# array is reset instead of COMPREPLY. When the `-a` flag is specified in a +# caller _comp_compgen, the words are appended to the existing elements of the +# array instead of replacing the existing elements. This function ignores +# ${cur-} or the prefix specified by `-v CUR`. +# @return 0 if at least one completion is generated, or 1 otherwise. +# @since 2.12 +_comp_compgen_set() +{ + local _append=${_comp_compgen__append-} + local _var=${_comp_compgen__var-COMPREPLY} + eval -- "$_var${_append:++}=(\"\$@\")" + (($#)) +} + +# Simply split the text and generate completions. This function should be used +# instead of `_comp_compgen -- -W "$(command)"`, which is vulnerable because +# option -W evaluates the shell expansions included in the option argument. +# Options: +# -F sep Specify the separators. The default is $' \t\n' +# -l The same as -F $'\n' +# -X arg The same as the compgen option -X. +# -S arg The same as the compgen option -S. +# -P arg The same as the compgen option -P. +# -o arg The same as the compgen option -o. +# @param $1 String to split +# @return 0 if at least one completion is generated, or 1 otherwise. +# @since 2.12 +_comp_compgen_split() +{ + local _ifs=$' \t\n' + local -a _compgen_options=() + + local OPTIND=1 OPTARG="" OPTERR=0 _opt + while getopts ':lF:X:S:P:o:' _opt "$@"; do + case $_opt in + l) _ifs=$'\n' ;; + F) _ifs=$OPTARG ;; + [XSPo]) _compgen_options+=("-$_opt" "$OPTARG") ;; + *) + printf 'bash_completion: usage: %s [-l|-F sep] [--] str\n' "$FUNCNAME" >&2 + return 2 + ;; + esac + done + shift "$((OPTIND - 1))" + if (($# != 1)); then + printf 'bash_completion: %s: unexpected number of arguments.\n' "$FUNCNAME" >&2 + printf 'usage: %s [-l|-F sep] [--] str' "$FUNCNAME" >&2 + return 2 + fi + + local input=$1 IFS=$' \t\n' + _comp_compgen -F "$_ifs" -U input -- ${_compgen_options[@]+"${_compgen_options[@]}"} -W '$input' +} + +# Check if the argument looks like a path. +# @param $1 thing to check +# @return True (0) if it does, False (> 0) otherwise +# @since 2.12 +_comp_looks_like_path() +{ + [[ ${1-} == @(*/|[.~])* ]] +} + # Reassemble command line words, excluding specified characters from the # list of word completion separators (COMP_WORDBREAKS). # @param $1 chars Characters out of $COMP_WORDBREAKS which should @@ -235,9 +803,9 @@ _upvars() # @param $2 words Name of variable to return words to # @param $3 cword Name of variable to return cword to # -__reassemble_comp_words_by_ref() +_comp__reassemble_words() { - local exclude i j line ref + local exclude="" i j line ref # Exclude word separator characters? if [[ $1 ]]; then # Yes, exclude word separator characters; @@ -248,7 +816,7 @@ __reassemble_comp_words_by_ref() # Default to cword unchanged printf -v "$3" %s "$COMP_CWORD" # Are characters excluded which were former included? - if [[ -v exclude ]]; then + if [[ $exclude ]]; then # Yes, list of word completion separators has shrunk; line=$COMP_LINE # Re-assemble words to complete @@ -269,12 +837,16 @@ __reassemble_comp_words_by_ref() ((i == COMP_CWORD)) && printf -v "$3" %s "$j" # Remove optional whitespace + word separator from line copy line=${line#*"${COMP_WORDS[i]}"} + # Indicate next word if available, else end *both* while and + # for loop + if ((i < ${#COMP_WORDS[@]} - 1)); then + ((i++)) + else + break 2 + fi # Start new word if word separator in original line is # followed by whitespace. [[ $line == [[:blank:]]* ]] && ((j++)) - # Indicate next word if available, else end *both* while and - # for loop - ((i < ${#COMP_WORDS[@]} - 1)) && ((i++)) || break 2 done # Append word to current word ref="$2[$j]" @@ -291,7 +863,7 @@ __reassemble_comp_words_by_ref() printf -v "$2[i]" %s "${COMP_WORDS[i]}" done fi -} # __reassemble_comp_words_by_ref() +} # @param $1 exclude Characters out of $COMP_WORDBREAKS which should NOT be # considered word breaks. This is useful for things like scp where @@ -300,22 +872,22 @@ __reassemble_comp_words_by_ref() # @param $2 words Name of variable to return words to # @param $3 cword Name of variable to return cword to # @param $4 cur Name of variable to return current word to complete to -# @see __reassemble_comp_words_by_ref() -__get_cword_at_cursor_by_ref() +# @see _comp__reassemble_words() +_comp__get_cword_at_cursor() { local cword words=() - __reassemble_comp_words_by_ref "$1" words cword + _comp__reassemble_words "$1" words cword local i cur="" index=$COMP_POINT lead=${COMP_LINE:0:COMP_POINT} - # Cursor not at position 0 and not leaded by just space(s)? + # Cursor not at position 0 and not led by just space(s)? if [[ $index -gt 0 && ($lead && ${lead//[[:space:]]/}) ]]; then cur=$COMP_LINE for ((i = 0; i <= cword; ++i)); do # Current word fits in $cur, and $cur doesn't match cword? - while [[ ${#cur} -ge ${#words[i]} && \ + while [[ ${#cur} -ge ${#words[i]} && ${cur:0:${#words[i]}} != "${words[i]-}" ]]; do # Strip first character - cur="${cur:1}" + cur=${cur:1} # Decrease cursor position, staying >= 0 ((index > 0)) && ((index--)) done @@ -324,7 +896,7 @@ __get_cword_at_cursor_by_ref() if ((i < cword)); then # No, cword lies further; local old_size=${#cur} - cur="${cur#"${words[i]}"}" + cur=${cur#"${words[i]}"} local new_size=${#cur} ((index -= old_size - new_size)) fi @@ -335,8 +907,9 @@ __get_cword_at_cursor_by_ref() ((index < 0)) && index=0 fi - local "$2" "$3" "$4" && _upvars -a${#words[@]} $2 ${words+"${words[@]}"} \ - -v $3 "$cword" -v $4 "${cur:0:index}" + local IFS=$' \t\n' + local "$2" "$3" "$4" && _comp_upvars -a"${#words[@]}" "$2" ${words[@]+"${words[@]}"} \ + -v "$3" "$cword" -v "$4" "${cur:0:index}" } # Get the word to complete and optional previous words. @@ -345,7 +918,7 @@ __get_cword_at_cursor_by_ref() # (For example, if the line is "ls foobar", # and the cursor is here --------> ^ # Also one is able to cross over possible wordbreak characters. -# Usage: _get_comp_words_by_ref [OPTIONS] [VARNAMES] +# Usage: _comp_get_words [OPTIONS] [VARNAMES] # Available VARNAMES: # cur Return cur via $cur # prev Return prev via $prev @@ -364,16 +937,23 @@ __get_cword_at_cursor_by_ref() # # Example usage: # -# $ _get_comp_words_by_ref -n : cur prev +# $ _comp_get_words -n : cur prev # -_get_comp_words_by_ref() +# @since 2.12 +_comp_get_words() { - local exclude flag i OPTIND=1 + local exclude="" flag i OPTIND=1 local cur cword words=() - local upargs=() upvars=() vcur vcword vprev vwords + local upargs=() upvars=() vcur="" vcword="" vprev="" vwords="" while getopts "c:i:n:p:w:" flag "$@"; do case $flag in + [cipw]) + if [[ $OPTARG != [a-zA-Z_]*([a-zA-Z_0-9])?(\[*\]) ]]; then + echo "bash_completion: $FUNCNAME: -$flag: invalid variable name \`$OPTARG'" >&2 + return 1 + fi + ;;& c) vcur=$OPTARG ;; i) vcword=$OPTARG ;; n) exclude=$OPTARG ;; @@ -400,108 +980,44 @@ _get_comp_words_by_ref() ((OPTIND += 1)) done - __get_cword_at_cursor_by_ref "${exclude-}" words cword cur + _comp__get_cword_at_cursor "${exclude-}" words cword cur - [[ -v vcur ]] && { + [[ $vcur ]] && { upvars+=("$vcur") - upargs+=(-v $vcur "$cur") + upargs+=(-v "$vcur" "$cur") } - [[ -v vcword ]] && { + [[ $vcword ]] && { upvars+=("$vcword") - upargs+=(-v $vcword "$cword") + upargs+=(-v "$vcword" "$cword") } - [[ -v vprev && $cword -ge 1 ]] && { + [[ $vprev ]] && { + local value="" + ((cword >= 1)) && value=${words[cword - 1]} upvars+=("$vprev") - upargs+=(-v $vprev "${words[cword - 1]}") + upargs+=(-v "$vprev" "$value") } - [[ -v vwords ]] && { + [[ $vwords ]] && { + # Note: bash < 4.4 has a bug that all the elements are connected with + # ${v+"$@"} when IFS does not contain whitespace. + local IFS=$' \t\n' upvars+=("$vwords") - upargs+=(-a${#words[@]} $vwords ${words+"${words[@]}"}) + upargs+=(-a"${#words[@]}" "$vwords" ${words+"${words[@]}"}) } - ((${#upvars[@]})) && local "${upvars[@]}" && _upvars "${upargs[@]}" + ((${#upvars[@]})) && local "${upvars[@]}" && _comp_upvars "${upargs[@]}" } -# Get the word to complete. -# This is nicer than ${COMP_WORDS[COMP_CWORD]}, since it handles cases -# where the user is completing in the middle of a word. -# (For example, if the line is "ls foobar", -# and the cursor is here --------> ^ -# @param $1 string Characters out of $COMP_WORDBREAKS which should NOT be -# considered word breaks. This is useful for things like scp where -# we want to return host:path and not only path, so we would pass the -# colon (:) as $1 in this case. -# @param $2 integer Index number of word to return, negatively offset to the -# current word (default is 0, previous is 1), respecting the exclusions -# given at $1. For example, `_get_cword "=:" 1' returns the word left of -# the current word, respecting the exclusions "=:". -# @deprecated Use `_get_comp_words_by_ref cur' instead -# @see _get_comp_words_by_ref() -_get_cword() -{ - local LC_CTYPE=C - local cword words - __reassemble_comp_words_by_ref "${1-}" words cword - - # return previous word offset by $2 - if [[ ${2-} && ${2//[^0-9]/} ]]; then - printf "%s" "${words[cword - $2]}" - elif ((${#words[cword]} == 0 && COMP_POINT == ${#COMP_LINE})); then - : # nothing - else - local i - local cur="$COMP_LINE" - local index="$COMP_POINT" - for ((i = 0; i <= cword; ++i)); do - # Current word fits in $cur, and $cur doesn't match cword? - while [[ ${#cur} -ge ${#words[i]} && \ - ${cur:0:${#words[i]}} != "${words[i]}" ]]; do - # Strip first character - cur="${cur:1}" - # Decrease cursor position, staying >= 0 - ((index > 0)) && ((index--)) - done - - # Does found word match cword? - if ((i < cword)); then - # No, cword lies further; - local old_size="${#cur}" - cur="${cur#${words[i]}}" - local new_size="${#cur}" - ((index -= old_size - new_size)) - fi - done - - if [[ ${words[cword]:0:${#cur}} != "$cur" ]]; then - # We messed up! At least return the whole word so things - # keep working - printf "%s" "${words[cword]}" - else - printf "%s" "${cur:0:index}" - fi - fi -} # _get_cword() - -# Get word previous to the current word. -# This is a good alternative to `prev=${COMP_WORDS[COMP_CWORD-1]}' because bash4 -# will properly return the previous word with respect to any given exclusions to -# COMP_WORDBREAKS. -# @deprecated Use `_get_comp_words_by_ref cur prev' instead -# @see _get_comp_words_by_ref() +# Generate the specified items after left-trimming with the word-to-complete +# containing a colon (:). If the word-to-complete does not contain a colon, +# this generates the specified items without modifications. +# @param $@ items to generate +# @var[in] cur current word to complete +# +# @remarks In Bash, with a colon in COMP_WORDBREAKS, words containing colons +# are always completed as entire words if the word to complete contains a +# colon. This function fixes this behavior by removing the +# colon-containing-prefix from the items. # -_get_pword() -{ - if ((COMP_CWORD >= 1)); then - _get_cword "${@:-}" 1 - fi -} - -# If the word-to-complete contains a colon (:), left-trim COMPREPLY items with -# word-to-complete. -# With a colon in COMP_WORDBREAKS, words containing -# colons are always completed as entire words if the word to complete contains -# a colon. This function fixes this, by removing the colon-containing-prefix -# from COMPREPLY items. # The preferred solution is to remove the colon (:) from COMP_WORDBREAKS in # your .bashrc: # @@ -510,24 +1026,37 @@ _get_pword() # # See also: Bash FAQ - E13) Why does filename completion misbehave if a colon # appears in the filename? - https://tiswww.case.edu/php/chet/bash/FAQ +# +# @since 2.12 +_comp_compgen_ltrim_colon() +{ + (($#)) || return 0 + local -a _tmp + _tmp=("$@") + if [[ $cur == *:* && $COMP_WORDBREAKS == *:* ]]; then + # Remove colon-word prefix from items + local _colon_word=${cur%"${cur##*:}"} + _tmp=("${_tmp[@]#"$_colon_word"}") + fi + _comp_compgen_set "${_tmp[@]}" +} + +# If the word-to-complete contains a colon (:), left-trim COMPREPLY items with +# word-to-complete. +# # @param $1 current word to complete (cur) -# @modifies global array $COMPREPLY +# @var[in,out] COMPREPLY # -__ltrim_colon_completions() +# @since 2.12 +_comp_ltrim_colon_completions() { - if [[ $1 == *:* && $COMP_WORDBREAKS == *:* ]]; then - # Remove colon-word prefix from COMPREPLY items - local colon_word=${1%"${1##*:}"} - local i=${#COMPREPLY[*]} - while ((i-- > 0)); do - COMPREPLY[i]=${COMPREPLY[i]#"$colon_word"} - done - fi -} # __ltrim_colon_completions() + ((${#COMPREPLY[@]})) || return 0 + _comp_compgen -c "$1" ltrim_colon "${COMPREPLY[@]}" +} # This function quotes the argument in a way so that readline dequoting # results in the original argument. This is necessary for at least -# `compgen' which requires its arguments quoted/escaped: +# `compgen` which requires its arguments quoted/escaped: # # $ ls "a'b/" # c @@ -538,87 +1067,90 @@ __ltrim_colon_completions() # See also: # - https://lists.gnu.org/archive/html/bug-bash/2009-03/msg00155.html # - https://www.mail-archive.com/bash-completion-devel@lists.alioth.debian.org/msg01944.html -# @param $1 Argument to quote -# @param $2 Name of variable to return result to -_quote_readline_by_ref() +# @param $1 Argument to quote +# @var[out] REPLY Quoted result is stored in this variable +# @since 2.12 +# shellcheck disable=SC2178 # The assignment is not intended for the global "REPLY" +_comp_quote_compgen() { if [[ $1 == \'* ]]; then # Leave out first character - printf -v $2 %s "${1:1}" + REPLY=${1:1} else - printf -v $2 %q "$1" + printf -v REPLY %q "$1" + + # If result becomes quoted like this: $'string', re-evaluate in order + # to drop the additional quoting. See also: + # https://www.mail-archive.com/bash-completion-devel@lists.alioth.debian.org/msg01942.html + if [[ $REPLY == \$\'*\' ]]; then + local value=${REPLY:2:-1} # Strip beginning $' and ending '. + value=${value//'%'/%%} # Escape % for printf format. + # shellcheck disable=SC2059 + printf -v REPLY "$value" # Decode escape sequences of \.... + fi fi - - # If result becomes quoted like this: $'string', re-evaluate in order to - # drop the additional quoting. See also: - # https://www.mail-archive.com/bash-completion-devel@lists.alioth.debian.org/msg01942.html - [[ ${!2} == \$* ]] && eval $2=${!2} -} # _quote_readline_by_ref() +} # This function performs file and directory completion. It's better than # simply using 'compgen -f', because it honours spaces in filenames. # @param $1 If `-d', complete only on directories. Otherwise filter/pick only # completions with `.$1' and the uppercase version of it as file # extension. +# @return 0 if at least one completion is generated, or 1 otherwise. # -_filedir() +# @since 2.12 +_comp_compgen_filedir() { - local IFS=$'\n' - - _tilde "${cur-}" || return + _comp_compgen_tilde && return local -a toks - local reset arg=${1-} - - if [[ $arg == -d ]]; then - reset=$(shopt -po noglob) - set -o noglob - toks=($(compgen -d -- "${cur-}")) - IFS=' ' - $reset - IFS=$'\n' + local _arg=${1-} + + if [[ $_arg == -d ]]; then + _comp_compgen -v toks -- -d else - local quoted - _quote_readline_by_ref "${cur-}" quoted + local REPLY + _comp_quote_compgen "${cur-}" + local _quoted=$REPLY + _comp_unlocal REPLY + + # work around bash-4.2 where compgen -f "''" produces nothing. + [[ $_quoted == "''" ]] && _quoted="" # Munge xspec to contain uppercase version too # https://lists.gnu.org/archive/html/bug-bash/2010-09/msg00036.html # news://news.gmane.io/4C940E1C.1010304@case.edu - local xspec=${arg:+"!*.@($arg|${arg^^})"} plusdirs=() + local _xspec=${_arg:+"!*.@($_arg|${_arg^^})"} _plusdirs=() # Use plusdirs to get dir completions if we have a xspec; if we don't, # there's no need, dirs come along with other completions. Don't use # plusdirs quite yet if fallback is in use though, in order to not ruin # the fallback condition with the "plus" dirs. - local opts=(-f -X "$xspec") - [[ $xspec ]] && plusdirs=(-o plusdirs) - [[ ${COMP_FILEDIR_FALLBACK-} || -z ${plusdirs-} ]] || - opts+=("${plusdirs[@]}") - - reset=$(shopt -po noglob) - set -o noglob - toks+=($(compgen "${opts[@]}" -- $quoted)) - IFS=' ' - $reset - IFS=$'\n' + local _opts=(-f -X "$_xspec") + [[ $_xspec ]] && _plusdirs=(-o plusdirs) + [[ ${BASH_COMPLETION_FILEDIR_FALLBACK-} || ! ${_plusdirs-} ]] || + _opts+=("${_plusdirs[@]}") + + _comp_compgen -v toks -c "$_quoted" -- "${_opts[@]}" # Try without filter if it failed to produce anything and configured to - [[ -n ${COMP_FILEDIR_FALLBACK-} && -n $arg && ${#toks[@]} -lt 1 ]] && { - reset=$(shopt -po noglob) - set -o noglob - toks+=($(compgen -f ${plusdirs+"${plusdirs[@]}"} -- $quoted)) - IFS=' ' - $reset - IFS=$'\n' - } + [[ ${BASH_COMPLETION_FILEDIR_FALLBACK-} && + $_arg && ${#toks[@]} -lt 1 ]] && + _comp_compgen -av toks -c "$_quoted" -- \ + -f ${_plusdirs+"${_plusdirs[@]}"} fi if ((${#toks[@]} != 0)); then - # 2>/dev/null for direct invocation, e.g. in the _filedir unit test + # 2>/dev/null for direct invocation, e.g. in the _comp_compgen_filedir + # unit test compopt -o filenames 2>/dev/null - COMPREPLY+=("${toks[@]}") fi -} # _filedir() + + # Note: bash < 4.4 has a bug that all the elements are connected with + # ${v+"${a[@]}"} when IFS does not contain whitespace. + local IFS=$' \t\n' + _comp_compgen -U toks set ${toks[@]+"${toks[@]}"} +} # This function splits $cur=--foo=bar into $prev=--foo, $cur=bar, making it # easier to support both "--foo bar" and "--foo=bar" style completions. @@ -626,13 +1158,13 @@ _filedir() # this to be useful. # Returns 0 if current option was split, 1 otherwise. # -_split_longopt() +_comp__split_longopt() { if [[ $cur == --?*=* ]]; then # Cut also backslash before '=' in case it ended up there # for some reason. - prev="${cur%%?(\\)=*}" - cur="${cur#*=}" + prev=${cur%%?(\\)=*} + cur=${cur#*=} return 0 fi @@ -642,51 +1174,140 @@ _split_longopt() # Complete variables. # @return True (0) if variables were completed, # False (> 0) if not. -_variables() +# @since 2.12 +_comp_compgen_variables() { if [[ $cur =~ ^(\$(\{[!#]?)?)([A-Za-z0-9_]*)$ ]]; then # Completing $var / ${var / ${!var / ${#var if [[ $cur == '${'* ]]; then local arrs vars - vars=($(compgen -A variable -P ${BASH_REMATCH[1]} -S '}' -- ${BASH_REMATCH[3]})) - arrs=($(compgen -A arrayvar -P ${BASH_REMATCH[1]} -S '[' -- ${BASH_REMATCH[3]})) + _comp_compgen -v vars -c "${BASH_REMATCH[3]}" -- -A variable -P "${BASH_REMATCH[1]}" -S '}' + _comp_compgen -v arrs -c "${BASH_REMATCH[3]}" -- -A arrayvar -P "${BASH_REMATCH[1]}" -S '[' if ((${#vars[@]} == 1 && ${#arrs[@]} != 0)); then # Complete ${arr with ${array[ if there is only one match, and that match is an array variable compopt -o nospace - COMPREPLY+=(${arrs[*]}) + _comp_compgen -U vars -U arrs -R -- -W '"${arrs[@]}"' else # Complete ${var with ${variable} - COMPREPLY+=(${vars[*]}) + _comp_compgen -U vars -U arrs -R -- -W '"${vars[@]}"' fi else # Complete $var with $variable - COMPREPLY+=($(compgen -A variable -P '$' -- "${BASH_REMATCH[3]}")) + _comp_compgen -ac "${BASH_REMATCH[3]}" -- -A variable -P '$' fi return 0 elif [[ $cur =~ ^(\$\{[#!]?)([A-Za-z0-9_]*)\[([^]]*)$ ]]; then # Complete ${array[i with ${array[idx]} - local IFS=$'\n' - COMPREPLY+=($(compgen -W '$(printf %s\\n "${!'${BASH_REMATCH[2]}'[@]}")' \ - -P "${BASH_REMATCH[1]}${BASH_REMATCH[2]}[" -S ']}' -- "${BASH_REMATCH[3]}")) + local vars + _comp_compgen -v vars -c "${BASH_REMATCH[3]}" -- -W '"${!'"${BASH_REMATCH[2]}"'[@]}"' \ + -P "${BASH_REMATCH[1]}${BASH_REMATCH[2]}[" -S ']}' # Complete ${arr[@ and ${arr[* if [[ ${BASH_REMATCH[3]} == [@*] ]]; then - COMPREPLY+=("${BASH_REMATCH[1]}${BASH_REMATCH[2]}[${BASH_REMATCH[3]}]}") + vars+=("${BASH_REMATCH[1]}${BASH_REMATCH[2]}[${BASH_REMATCH[3]}]}") + fi + # array indexes may have colons + if ((${#vars[@]})); then + _comp_compgen -U vars -c "$cur" ltrim_colon "${vars[@]}" + else + _comp_compgen_set fi - __ltrim_colon_completions "$cur" # array indexes may have colons return 0 elif [[ $cur =~ ^\$\{[#!]?[A-Za-z0-9_]*\[.*\]$ ]]; then # Complete ${array[idx] with ${array[idx]} - COMPREPLY+=("$cur}") - __ltrim_colon_completions "$cur" + _comp_compgen -c "$cur" ltrim_colon "$cur}" return 0 + fi + return 1 +} + +# Complete a delimited value. +# +# Usage: [-k] DELIMITER COMPGEN_ARG... +# -k: do not filter out already present tokens in value +# @since 2.12 +_comp_delimited() +{ + local prefix="" delimiter=$1 deduplicate=set + shift + if [[ $delimiter == -k ]]; then + deduplicate="" + delimiter=$1 + shift + fi + [[ $cur == *"$delimiter"* ]] && prefix=${cur%"$delimiter"*}$delimiter + + if [[ $deduplicate ]]; then + # We could construct a -X pattern to feed to compgen, but that'd + # conflict with possibly already set -X in $@, as well as have + # glob char escaping issues to deal with. Do removals by hand instead. + _comp_compgen -R -- "$@" + local -a existing + _comp_split -F "$delimiter" existing "$cur" + # Do not remove the last from existing if it's not followed by the + # delimiter so we get space appended. + [[ ! $cur || $cur == *"$delimiter" ]] || unset -v "existing[${#existing[@]}-1]" + if ((${#COMPREPLY[@]})); then + local x i + for x in ${existing+"${existing[@]}"}; do + for i in "${!COMPREPLY[@]}"; do + if [[ $x == "${COMPREPLY[i]}" ]]; then + unset -v 'COMPREPLY[i]' + continue 2 # assume no dupes in COMPREPLY + fi + done + done + ((${#COMPREPLY[@]})) && + _comp_compgen -c "${cur##*"$delimiter"}" -- -W '"${COMPREPLY[@]}"' + fi else - case ${prev-} in - TZ) - cur=/usr/share/zoneinfo/$cur - _filedir + _comp_compgen -c "${cur##*"$delimiter"}" -- "$@" + fi + + # It would seem that in some specific cases we could avoid adding the + # prefix to all completions, thereby making the list of suggestions + # cleaner, and only adding it when there's exactly one completion. + # The cases where this opportunity has been observed involve having + # `show-all-if-ambiguous` on, but even that has cases where it fails + # and the last separator including everything before it is lost. + # https://github.com/scop/bash-completion/pull/913#issuecomment-1490140309 + local i + for i in "${!COMPREPLY[@]}"; do + COMPREPLY[i]="$prefix${COMPREPLY[i]}" + done + + [[ $delimiter != : ]] || _comp_ltrim_colon_completions "$cur" +} + +# Complete assignment of various known environment variables. +# +# The word to be completed is expected to contain the entire assignment, +# including the variable name and the "=". Some known variables are completed +# with colon separated values; for those to work, colon should not have been +# used to split words. See related parameters to _comp_initialize. +# +# @param $1 variable assignment to be completed +# @return True (0) if variable value completion was attempted, +# False (> 0) if not. +# @since 2.12 +_comp_variable_assignments() +{ + local cur=${1-} i + + if [[ $cur =~ ^([A-Za-z_][A-Za-z0-9_]*)=(.*)$ ]]; then + prev=${BASH_REMATCH[1]} + cur=${BASH_REMATCH[2]} + else + return 1 + fi + + case $prev in + TZ) + cur=/usr/share/zoneinfo/$cur + _comp_compgen_filedir + if ((${#COMPREPLY[@]})); then for i in "${!COMPREPLY[@]}"; do if [[ ${COMPREPLY[i]} == *.tab ]]; then - unset 'COMPREPLY[i]' + unset -v 'COMPREPLY[i]' continue elif [[ -d ${COMPREPLY[i]} ]]; then COMPREPLY[i]+=/ @@ -694,20 +1315,24 @@ _variables() fi COMPREPLY[i]=${COMPREPLY[i]#/usr/share/zoneinfo/} done - return 0 - ;; - TERM) - _terms - return 0 - ;; - LANG | LC_*) - COMPREPLY=($(compgen -W '$(locale -a 2>/dev/null)' \ - -- "$cur")) - return 0 - ;; - esac - fi - return 1 + fi + ;; + TERM) + _comp_compgen_terms + ;; + LANG | LC_*) + _comp_compgen_split -- "$(locale -a 2>/dev/null)" + ;; + LANGUAGE) + _comp_delimited : -W '$(locale -a 2>/dev/null)' + ;; + *) + _comp_compgen_variables && return 0 + _comp_compgen -a filedir + ;; + esac + + return 0 } # Initialize completion and deal with various general things: do file @@ -717,18 +1342,37 @@ _variables() # cur, prev, words, and cword are local, ditto split if you use -s. # # Options: -# -n EXCLUDE Passed to _get_comp_words_by_ref -n with redirection chars -# -e XSPEC Passed to _filedir as first arg for stderr redirections -# -o XSPEC Passed to _filedir as first arg for other output redirections -# -i XSPEC Passed to _filedir as first arg for stdin redirections -# -s Split long options with _split_longopt, implies -n = +# -n EXCLUDE Passed to _comp_get_words -n with redirection chars +# -e XSPEC Passed to _comp_compgen_filedir as first arg for stderr +# redirections +# -o XSPEC Passed to _comp_compgen_filedir as first arg for other output +# redirections +# -i XSPEC Passed to _comp_compgen_filedir as first arg for stdin +# redirections +# -s Split long options with _comp__split_longopt, implies -n = +# @param $1...$3 args Original arguments specified to the completion function. +# The first argument $1 is command name. The second +# argument $2 is the string before the cursor in the +# current word. The third argument $3 is the previous +# word. +# @var[out] cur Reconstructed current word +# @var[out] prev Reconstructed previous word +# @var[out] words Reconstructed words +# @var[out] cword Current word index in `words` +# @var[out] comp_args Original arguments specified to the completion +# function are saved in this array, if the arguments +# $1...$3 is specified. +# @var[out,opt] was_split When "-s" is specified, `"set"/""` is set depending +# on whether the split happened. # @return True (0) if completion needs further processing, # False (> 0) no further processing is necessary. # -_init_completion() +# @since 2.12 +_comp_initialize() { - local exclude="" flag outx errx inx OPTIND=1 + local exclude="" opt_split="" outx="" errx="" inx="" + local flag OPTIND=1 OPTARG="" OPTERR=0 while getopts "n:e:o:i:s" flag "$@"; do case $flag in n) exclude+=$OPTARG ;; @@ -736,8 +1380,9 @@ _init_completion() o) outx=$OPTARG ;; i) inx=$OPTARG ;; s) - split=false - exclude+== + opt_split="set" + was_split="" + exclude+="=" ;; *) echo "bash_completion: $FUNCNAME: usage error" >&2 @@ -745,13 +1390,15 @@ _init_completion() ;; esac done + shift "$((OPTIND - 1))" + (($#)) && comp_args=("$@") COMPREPLY=() - local redir="@(?([0-9])<|?([0-9&])>?(>)|>&)" - _get_comp_words_by_ref -n "$exclude<>&" cur prev words cword + local redir='@(?(+([0-9])|{[a-zA-Z_]*([a-zA-Z_0-9])})@(>?([>|&])|<?([>&])|<<?([-<]))|&>?(>))' + _comp_get_words -n "$exclude<>&" cur prev words cword # Complete variable names. - _variables && return 1 + _comp_compgen_variables && return 1 # Complete on files if current is a redirect possibly followed by a # filename, e.g. ">foo", or previous is a "bare" redirect, e.g. ">". @@ -770,8 +1417,9 @@ _init_completion() esac ;; esac - cur="${cur##$redir}" - _filedir $xspec + # shellcheck disable=SC2295 # redir is a pattern + cur=${cur##$redir} + _comp_compgen_filedir "$xspec" return 1 fi @@ -792,259 +1440,342 @@ _init_completion() ((cword <= 0)) && return 1 prev=${words[cword - 1]} - [[ ${split-} ]] && _split_longopt && split=true + [[ $opt_split ]] && _comp__split_longopt && was_split="set" return 0 } -# Helper function for _parse_help and _parse_usage. -__parse_options() +# Helper function for _comp_compgen_help and _comp_compgen_usage. +# Obtain the help output based on the arguments. +# @param $@ args Arguments specified to the caller. +# @var[out] _lines +# @return 2 if the usage is wrong, 1 if no output is obtained, or otherwise 0. +_comp_compgen_help__get_help_lines() +{ + local -a help_cmd + case ${1-} in + -) + if (($# > 1)); then + printf 'bash_completion: %s -: extra arguments for -\n' "${FUNCNAME[1]}" >&2 + printf 'usage: %s -\n' "${FUNCNAME[1]}" >&2 + printf 'usage: %s -c cmd args...\n' "${FUNCNAME[1]}" >&2 + printf 'usage: %s [-- args...]\n' "${FUNCNAME[1]}" >&2 + return 2 + fi + help_cmd=(exec cat) + ;; + -c) + if (($# < 2)); then + printf 'bash_completion: %s -c: no command is specified\n' "${FUNCNAME[1]}" >&2 + printf 'usage: %s -\n' "${FUNCNAME[1]}" >&2 + printf 'usage: %s -c cmd args...\n' "${FUNCNAME[1]}" >&2 + printf 'usage: %s [-- args...]\n' "${FUNCNAME[1]}" >&2 + return 2 + fi + help_cmd=("${@:2}") + ;; + --) shift 1 ;& + *) + local REPLY + _comp_dequote "${comp_args[0]-}" || REPLY=${comp_args[0]-} + help_cmd=("${REPLY:-false}" "$@") + ;; + esac + + local REPLY + _comp_split -l REPLY "$(LC_ALL=C "${help_cmd[@]}" 2>&1)" && + _lines=("${REPLY[@]}") +} + +# Helper function for _comp_compgen_help and _comp_compgen_usage. +# @var[in,out] options Add options +# @return True (0) if an option was found, False (> 0) otherwise +_comp_compgen_help__parse() { - local option option2 i IFS=$' \t\n,/|' + local option option2 i # Take first found long option, or first one (short) if not found. option= - local -a array=($1) - for i in "${array[@]}"; do - case "$i" in - ---*) break ;; - --?*) - option=$i - break - ;; - -?*) [[ $option ]] || option=$i ;; - *) break ;; - esac - done - [[ $option ]] || return 0 - - IFS=$' \t\n' # affects parsing of the regexps below... + local -a array + if _comp_split -F $' \t\n,/|' array "$1"; then + for i in "${array[@]}"; do + case "$i" in + ---*) break ;; + --?*) + option=$i + break + ;; + -?*) [[ $option ]] || option=$i ;; + *) break ;; + esac + done + fi + [[ $option ]] || return 1 # Expand --[no]foo to --foo and --nofoo etc if [[ $option =~ (\[((no|dont)-?)\]). ]]; then option2=${option/"${BASH_REMATCH[1]}"/} option2=${option2%%[<{().[]*} - printf '%s\n' "${option2/=*/=}" + options+=("${option2/=*/=}") option=${option/"${BASH_REMATCH[1]}"/"${BASH_REMATCH[2]}"} fi - option=${option%%[<{().[]*} - printf '%s\n' "${option/=*/=}" + [[ $option =~ ^([^=<{().[]|\.[A-Za-z0-9])+=? ]] && + options+=("$BASH_REMATCH") } -# Parse GNU style help output of the given command. -# @param $1 command; if "-", read from stdin and ignore rest of args -# @param $2 command options (default: --help) +# Parse GNU style help output of the given command and generate and store +# completions in an array. The help output is produced in the way depending on +# the usage: +# usage: _comp_compgen_help - # read from stdin +# usage: _comp_compgen_help -c cmd args... # run "cmd args..." +# usage: _comp_compgen_help [[--] args...] # run "${comp_args[0]} args..." +# When no arguments are specified, `--help` is assumed. # -_parse_help() -{ - eval local cmd="$(quote "$1")" - local line - { - case $cmd in - -) cat ;; - *) LC_ALL=C "$(dequote "$cmd")" ${2:---help} 2>&1 ;; - esac - } | - while read -r line; do - - [[ $line == *([[:blank:]])-* ]] || continue - # transform "-f FOO, --foo=FOO" to "-f , --foo=FOO" etc - while [[ $line =~ \ - ((^|[^-])-[A-Za-z0-9?][[:space:]]+)\[?[A-Z0-9]+([,_-]+[A-Z0-9]+)?(\.\.+)?\]? ]]; do - line=${line/"${BASH_REMATCH[0]}"/"${BASH_REMATCH[1]}"} - done - __parse_options "${line// or /, }" - +# @var[in] comp_args[0] +# @since 2.12 +_comp_compgen_help() +{ + (($#)) || set -- -- --help + + local -a _lines + _comp_compgen_help__get_help_lines "$@" || return "$?" + + local -a options=() + local _line + for _line in "${_lines[@]}"; do + [[ $_line == *([[:blank:]])-* ]] || continue + # transform "-f FOO, --foo=FOO" to "-f , --foo=FOO" etc + while [[ $_line =~ ((^|[^-])-[A-Za-z0-9?][[:space:]]+)\[?[A-Z0-9]+([,_-]+[A-Z0-9]+)?(\.\.+)?\]? ]]; do + _line=${_line/"${BASH_REMATCH[0]}"/"${BASH_REMATCH[1]}"} done + _comp_compgen_help__parse "${_line// or /, }" + done + ((${#options[@]})) || return 1 + + _comp_compgen -U options -- -W '"${options[@]}"' + return 0 } -# Parse BSD style usage output (options in brackets) of the given command. -# @param $1 command; if "-", read from stdin and ignore rest of args -# @param $2 command options (default: --usage) +# Parse BSD style usage output (options in brackets) of the given command. The +# help output is produced in the way depending on the usage: +# usage: _comp_compgen_usage - # read from stdin +# usage: _comp_compgen_usage -c cmd args... # run "cmd args..." +# usage: _comp_compgen_usage [[--] args...] # run "${comp_args[0]} args..." +# When no arguments are specified, `--usage` is assumed. # -_parse_usage() -{ - eval local cmd="$(quote "$1")" - local line match option i char - { - case $cmd in - -) cat ;; - *) LC_ALL=C "$(dequote "$cmd")" ${2:---usage} 2>&1 ;; - esac - } | - while read -r line; do - - while [[ $line =~ \[[[:space:]]*(-[^]]+)[[:space:]]*\] ]]; do - match=${BASH_REMATCH[0]} - option=${BASH_REMATCH[1]} - case $option in - -?(\[)+([a-zA-Z0-9?])) - # Treat as bundled short options - for ((i = 1; i < ${#option}; i++)); do - char=${option:i:1} - [[ $char != '[' ]] && printf '%s\n' -$char - done - ;; - *) - __parse_options "$option" - ;; - esac - line=${line#*"$match"} - done - +# @var[in] comp_args[0] +# @since 2.12 +_comp_compgen_usage() +{ + (($#)) || set -- -- --usage + + local -a _lines + _comp_compgen_help__get_help_lines "$@" || return "$?" + + local -a options=() + local _line _match _option _i _char + for _line in "${_lines[@]}"; do + while [[ $_line =~ \[[[:space:]]*(-[^]]+)[[:space:]]*\] ]]; do + _match=${BASH_REMATCH[0]} + _option=${BASH_REMATCH[1]} + case $_option in + -?(\[)+([a-zA-Z0-9?])) + # Treat as bundled short options + for ((_i = 1; _i < ${#_option}; _i++)); do + _char=${_option:_i:1} + [[ $_char != '[' ]] && options+=("-$_char") + done + ;; + *) + _comp_compgen_help__parse "$_option" + ;; + esac + _line=${_line#*"$_match"} done + done + ((${#options[@]})) || return 1 + + _comp_compgen -U options -- -W '"${options[@]}"' + return 0 } # This function completes on signal names (minus the SIG prefix) # @param $1 prefix -_signals() +# +# @since 2.12 +_comp_compgen_signals() { - local -a sigs=($(compgen -P "${1-}" -A signal "SIG${cur#${1-}}")) - COMPREPLY+=("${sigs[@]/#${1-}SIG/${1-}}") + local -a sigs + _comp_compgen -v sigs -c "SIG${cur#"${1-}"}" -- -A signal && + _comp_compgen -RU sigs -- -P "${1-}" -W '"${sigs[@]#SIG}"' } # This function completes on known mac addresses # -_mac_addresses() +# @since 2.12 +_comp_compgen_mac_addresses() { - local re='\([A-Fa-f0-9]\{2\}:\)\{5\}[A-Fa-f0-9]\{2\}' + local _re='\([A-Fa-f0-9]\{2\}:\)\{5\}[A-Fa-f0-9]\{2\}' local PATH="$PATH:/sbin:/usr/sbin" + local -a addresses # Local interfaces # - ifconfig on Linux: HWaddr or ether # - ifconfig on FreeBSD: ether # - ip link: link/ether - COMPREPLY+=($( + _comp_compgen -v addresses split -- "$( { - LC_ALL=C ifconfig -a || ip link show + LC_ALL=C ifconfig -a || ip -c=never link show || ip link show } 2>/dev/null | command sed -ne \ - "s/.*[[:space:]]HWaddr[[:space:]]\{1,\}\($re\)[[:space:]].*/\1/p" -ne \ - "s/.*[[:space:]]HWaddr[[:space:]]\{1,\}\($re\)[[:space:]]*$/\1/p" -ne \ - "s|.*[[:space:]]\(link/\)\{0,1\}ether[[:space:]]\{1,\}\($re\)[[:space:]].*|\2|p" -ne \ - "s|.*[[:space:]]\(link/\)\{0,1\}ether[[:space:]]\{1,\}\($re\)[[:space:]]*$|\2|p" - )) + "s/.*[[:space:]]HWaddr[[:space:]]\{1,\}\($_re\)[[:space:]].*/\1/p" -ne \ + "s/.*[[:space:]]HWaddr[[:space:]]\{1,\}\($_re\)[[:space:]]*$/\1/p" -ne \ + "s|.*[[:space:]]\(link/\)\{0,1\}ether[[:space:]]\{1,\}\($_re\)[[:space:]].*|\2|p" -ne \ + "s|.*[[:space:]]\(link/\)\{0,1\}ether[[:space:]]\{1,\}\($_re\)[[:space:]]*$|\2|p" + )" # ARP cache - COMPREPLY+=($({ - arp -an || ip neigh show - } 2>/dev/null | command sed -ne \ - "s/.*[[:space:]]\($re\)[[:space:]].*/\1/p" -ne \ - "s/.*[[:space:]]\($re\)[[:space:]]*$/\1/p")) + _comp_compgen -av addresses split -- "$( + { + arp -an || ip -c=never neigh show || ip neigh show + } 2>/dev/null | command sed -ne \ + "s/.*[[:space:]]\($_re\)[[:space:]].*/\1/p" -ne \ + "s/.*[[:space:]]\($_re\)[[:space:]]*$/\1/p" + )" # /etc/ethers - COMPREPLY+=($(command sed -ne \ - "s/^[[:space:]]*\($re\)[[:space:]].*/\1/p" /etc/ethers 2>/dev/null)) + _comp_compgen -av addresses split -- "$(command sed -ne \ + "s/^[[:space:]]*\($_re\)[[:space:]].*/\1/p" /etc/ethers 2>/dev/null)" - COMPREPLY=($(compgen -W '${COMPREPLY[@]}' -- "$cur")) - __ltrim_colon_completions "$cur" + _comp_compgen -U addresses ltrim_colon "${addresses[@]}" } # This function completes on configured network interfaces # -_configured_interfaces() +# @since 2.12 +_comp_compgen_configured_interfaces() { + local -a files if [[ -f /etc/debian_version ]]; then # Debian system - COMPREPLY=($(compgen -W "$(command sed -ne 's|^iface \([^ ]\{1,\}\).*$|\1|p' \ - /etc/network/interfaces /etc/network/interfaces.d/* 2>/dev/null)" \ - -- "$cur")) + _comp_expand_glob files '/etc/network/interfaces /etc/network/interfaces.d/*' || return 0 + _comp_compgen -U files split -- "$(command sed -ne \ + 's|^iface \([^ ]\{1,\}\).*$|\1|p' "${files[@]}" 2>/dev/null)" elif [[ -f /etc/SuSE-release ]]; then # SuSE system - COMPREPLY=($(compgen -W "$(printf '%s\n' \ - /etc/sysconfig/network/ifcfg-* | - command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')" -- "$cur")) + _comp_expand_glob files '/etc/sysconfig/network/ifcfg-*' || return 0 + _comp_compgen -U files split -- "$(printf '%s\n' "${files[@]}" | + command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')" elif [[ -f /etc/pld-release ]]; then # PLD Linux - COMPREPLY=($(compgen -W "$(command ls -B \ - /etc/sysconfig/interfaces | - command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')" -- "$cur")) + _comp_compgen -U files split -- "$(command ls -B /etc/sysconfig/interfaces | + command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')" else # Assume Red Hat - COMPREPLY=($(compgen -W "$(printf '%s\n' \ - /etc/sysconfig/network-scripts/ifcfg-* | - command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')" -- "$cur")) + _comp_expand_glob files '/etc/sysconfig/network-scripts/ifcfg-*' || return 0 + _comp_compgen -U files split -- "$(printf '%s\n' "${files[@]}" | + command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')" fi } # Local IP addresses. +# If producing IPv6 completions, `_comp_initialize` with `-n :`. +# # -4: IPv4 addresses only (default) # -6: IPv6 addresses only # -a: All addresses # -_ip_addresses() +# @since 2.12 +_comp_compgen_ip_addresses() { - local n + local _n case ${1-} in - -a) n='6\?' ;; - -6) n='6' ;; - *) n= ;; + -a) _n='6\{0,1\}' ;; + -6) _n='6' ;; + *) _n= ;; esac local PATH=$PATH:/sbin - local addrs=$({ - LC_ALL=C ifconfig -a || ip addr show + local addrs + _comp_compgen -v addrs split -- "$({ + LC_ALL=C ifconfig -a || ip -c=never addr show || ip addr show } 2>/dev/null | command sed -e 's/[[:space:]]addr:/ /' -ne \ - "s|.*inet${n}[[:space:]]\{1,\}\([^[:space:]/]*\).*|\1|p") - COMPREPLY+=($(compgen -W "$addrs" -- "${cur-}")) + "s|.*inet${_n}[[:space:]]\{1,\}\([^[:space:]/]*\).*|\1|p")" || + return + + if [[ ! $_n ]]; then + _comp_compgen -U addrs set "${addrs[@]}" + else + _comp_compgen -U addrs ltrim_colon "${addrs[@]}" + fi } -# This function completes on available kernels +# This function completes on available kernel versions # -_kernel_versions() +# @since 2.12 +_comp_compgen_kernel_versions() { - COMPREPLY=($(compgen -W '$(command ls /lib/modules)' -- "$cur")) + _comp_compgen_split -- "$(command ls /lib/modules)" } # This function completes on all available network interfaces # -a: restrict to active interfaces only # -w: restrict to wireless interfaces only # -_available_interfaces() +# @since 2.12 +_comp_compgen_available_interfaces() { local PATH=$PATH:/sbin - - COMPREPLY=($({ - if [[ ${1:-} == -w ]]; then + local generated + _comp_compgen -v generated split -- "$({ + if [[ ${1-} == -w ]]; then iwconfig - elif [[ ${1:-} == -a ]]; then - ifconfig || ip link show up + elif [[ ${1-} == -a ]]; then + ifconfig || ip -c=never link show up || ip link show up else - ifconfig -a || ip link show + ifconfig -a || ip -c=never link show || ip link show fi - } 2>/dev/null | awk \ - '/^[^ \t]/ { if ($1 ~ /^[0-9]+:/) { print $2 } else { print $1 } }')) - - COMPREPLY=($(compgen -W '${COMPREPLY[@]/%[[:punct:]]/}' -- "$cur")) + } 2>/dev/null | _comp_awk \ + '/^[^ \t]/ { if ($1 ~ /^[0-9]+:/) { print $2 } else { print $1 } }')" && + _comp_compgen -U generated set "${generated[@]}" } # Echo number of CPUs, falling back to 1 on failure. -_ncpus() +# @var[out] REPLY +# @return 0 if it successfully obtained the number of CPUs, or otherwise 1 +# @since 2.12 +_comp_get_ncpus() { local var=NPROCESSORS_ONLN - [[ $OSTYPE == *linux* ]] && var=_$var - local n=$(getconf $var 2>/dev/null) - printf %s ${n:-1} + [[ $OSTYPE == *@(linux|msys|cygwin)* ]] && var=_$var + if REPLY=$(getconf $var 2>/dev/null) && ((REPLY >= 1)); then + return 0 + else + REPLY=1 + return 1 + fi } # Perform tilde (~) completion -# @return True (0) if completion needs further processing, -# False (> 0) if tilde is followed by a valid username, completions -# are put in COMPREPLY and no further processing is necessary. -_tilde() +# @return False (1) if completion needs further processing, +# True (0) if tilde is followed by a valid username, completions are +# put in COMPREPLY and no further processing is necessary. +# @since 2.12 +_comp_compgen_tilde() { - local result=0 - if [[ ${1-} == \~* && $1 != */* ]]; then + if [[ ${cur-} == \~* && $cur != */* ]]; then # Try generate ~username completions - COMPREPLY=($(compgen -P '~' -u -- "${1#\~}")) - result=${#COMPREPLY[@]} - # 2>/dev/null for direct invocation, e.g. in the _tilde unit test - ((result > 0)) && compopt -o filenames 2>/dev/null + if _comp_compgen -c "${cur#\~}" -- -P '~' -u; then + # 2>/dev/null for direct invocation, e.g. in the + # _comp_compgen_tilde unit test + compopt -o filenames 2>/dev/null + return 0 + fi fi - return $result + return 1 } -# Expand variable starting with tilde (~) +# Expand string starting with tilde (~) # We want to expand ~foo/... to /home/foo/... to avoid problems when # word-to-complete starting with a tilde is fed to commands and ending up # quoted instead of expanded. @@ -1053,11 +1784,11 @@ _tilde() # a dollar sign variable ($) or asterisk (*) is not expanded. # Example usage: # -# $ v="~"; __expand_tilde_by_ref v; echo "$v" +# $ _comp_expand_tilde "~"; echo "$REPLY" # # Example output: # -# v output +# $1 REPLY # -------- ---------------- # ~ /home/user # ~foo/bar /home/foo/bar @@ -1065,17 +1796,22 @@ _tilde() # ~foo/a b /home/foo/a b # ~foo/* /home/foo/* # -# @param $1 Name of variable (not the value of the variable) to expand -__expand_tilde_by_ref() -{ - if [[ ${!1-} == \~* ]]; then - eval $1="$(printf ~%q "${!1#\~}")" +# @param $1 Value to expand +# @var[out] REPLY Expanded result +# @since 2.12 +_comp_expand_tilde() +{ + REPLY=$1 + if [[ $1 == \~* ]]; then + printf -v REPLY '~%q' "${1#\~}" + eval "REPLY=$REPLY" fi -} # __expand_tilde_by_ref() +} # This function expands tildes in pathnames # -_expand() +# @since 2.12 +_comp_expand() { # Expand ~username type directory specifications. We want to expand # ~foo/... to /home/foo/... to avoid problems when $cur starting with @@ -1083,58 +1819,67 @@ _expand() case ${cur-} in ~*/*) - __expand_tilde_by_ref cur + local REPLY + _comp_expand_tilde "$cur" + cur=$REPLY ;; ~*) - _tilde "$cur" || - eval COMPREPLY[0]="$(printf ~%q "${COMPREPLY[0]#\~}")" - return ${#COMPREPLY[@]} + _comp_compgen -v COMPREPLY tilde && + eval "COMPREPLY[0]=$(printf ~%q "${COMPREPLY[0]#\~}")" && + return 1 ;; esac + return 0 } # Process ID related functions. # for AIX and Solaris we use X/Open syntax, BSD for others. +# +# @since 2.12 if [[ $OSTYPE == *@(solaris|aix)* ]]; then # This function completes on process IDs. - _pids() + _comp_compgen_pids() { - COMPREPLY=($(compgen -W '$(command ps -efo pid | command sed 1d)' -- "$cur")) + _comp_compgen_split -- "$(command ps -efo pid | command sed 1d)" } - _pgids() + _comp_compgen_pgids() { - COMPREPLY=($(compgen -W '$(command ps -efo pgid | command sed 1d)' -- "$cur")) + _comp_compgen_split -- "$(command ps -efo pgid | command sed 1d)" } - _pnames() + _comp_compgen_pnames() { - COMPREPLY=($(compgen -X '<defunct>' -W '$(command ps -efo comm | \ - command sed -e 1d -e "s:.*/::" -e "s/^-//" | sort -u)' -- "$cur")) + _comp_compgen_split -X '<defunct>' -- "$(command ps -efo comm | + command sed -e 1d -e 's:.*/::' -e 's/^-//' | sort -u)" } else - _pids() + _comp_compgen_pids() { - COMPREPLY=($(compgen -W '$(command ps axo pid=)' -- "$cur")) + _comp_compgen_split -- "$(command ps ax -o pid=)" } - _pgids() + _comp_compgen_pgids() { - COMPREPLY=($(compgen -W '$(command ps axo pgid=)' -- "$cur")) + _comp_compgen_split -- "$(command ps ax -o pgid=)" } # @param $1 if -s, don't try to avoid truncated command names - _pnames() + _comp_compgen_pnames() { - local -a procs + local -a procs=() if [[ ${1-} == -s ]]; then - procs=($(command ps axo comm | command sed -e 1d)) + _comp_split procs "$(command ps ax -o comm | command sed -e 1d)" else - local line i=-1 ifs=$IFS - IFS=$'\n' - local -a psout=($(command ps axo command=)) - IFS=$ifs + # Some versions of ps don't support "command", but do "comm", e.g. + # some busybox ones. Fall back + local -a psout + _comp_split -l psout "$({ + command ps ax -o command= || command ps ax -o comm= + } 2>/dev/null)" + local line i=-1 for line in "${psout[@]}"; do if ((i == -1)); then - # First line, see if it has COMMAND column header. For example - # the busybox ps does that, i.e. doesn't respect axo command= + # First line, see if it has COMMAND column header. For + # example some busybox ps versions do that, i.e. don't + # respect command= if [[ $line =~ ^(.*[[:space:]])COMMAND([[:space:]]|$) ]]; then # It does; store its index. i=${#BASH_REMATCH[1]} @@ -1146,147 +1891,165 @@ else # line=${line:i} # take command starting from found index line=${line%% *} # trim arguments - procs+=($line) + [[ $line ]] && procs+=("$line") fi done if ((i == -1)); then - # Regular axo command= parsing + # Regular command= parsing for line in "${psout[@]}"; do if [[ $line =~ ^[[(](.+)[])]$ ]]; then - procs+=(${BASH_REMATCH[1]}) + procs+=("${BASH_REMATCH[1]}") else line=${line%% *} # trim arguments line=${line##@(*/|-)} # trim leading path and - - procs+=($line) + [[ $line ]] && procs+=("$line") fi done fi fi - COMPREPLY=($(compgen -X "<defunct>" -W '${procs[@]}' -- "$cur")) + ((${#procs[@]})) && + _comp_compgen -U procs -- -X "<defunct>" -W '"${procs[@]}"' } fi # This function completes on user IDs # -_uids() +# @since 2.12 +_comp_compgen_uids() { if type getent &>/dev/null; then - COMPREPLY=($(compgen -W '$(getent passwd | cut -d: -f3)' -- "$cur")) + _comp_compgen_split -- "$(getent passwd | cut -d: -f3)" elif type perl &>/dev/null; then - COMPREPLY=($(compgen -W '$(perl -e '"'"'while (($uid) = (getpwent)[2]) { print $uid . "\n" }'"'"')' -- "$cur")) + _comp_compgen_split -- "$(perl -e 'while (($uid) = (getpwent)[2]) { print $uid . "\n" }')" else # make do with /etc/passwd - COMPREPLY=($(compgen -W '$(cut -d: -f3 /etc/passwd)' -- "$cur")) + _comp_compgen_split -- "$(cut -d: -f3 /etc/passwd)" fi } # This function completes on group IDs # -_gids() +# @since 2.12 +_comp_compgen_gids() { if type getent &>/dev/null; then - COMPREPLY=($(compgen -W '$(getent group | cut -d: -f3)' -- "$cur")) + _comp_compgen_split -- "$(getent group | cut -d: -f3)" elif type perl &>/dev/null; then - COMPREPLY=($(compgen -W '$(perl -e '"'"'while (($gid) = (getgrent)[2]) { print $gid . "\n" }'"'"')' -- "$cur")) + _comp_compgen_split -- "$(perl -e 'while (($gid) = (getgrent)[2]) { print $gid . "\n" }')" else # make do with /etc/group - COMPREPLY=($(compgen -W '$(cut -d: -f3 /etc/group)' -- "$cur")) + _comp_compgen_split -- "$(cut -d: -f3 /etc/group)" fi } # Glob for matching various backup files. # -_backup_glob='@(#*#|*@(~|.@(bak|orig|rej|swp|dpkg*|rpm@(orig|new|save))))' +_comp_backup_glob='@(#*#|*@(~|.@(bak|orig|rej|swp|@(dpkg|ucf)-*|rpm@(orig|new|save))))' # Complete on xinetd services # -_xinetd_services() +# @since 2.12 +_comp_compgen_xinetd_services() { - local xinetddir=${BASHCOMP_XINETDDIR:-/etc/xinetd.d} + local xinetddir=${_comp__test_xinetd_dir:-/etc/xinetd.d} if [[ -d $xinetddir ]]; then - local IFS=$' \t\n' reset=$(shopt -p nullglob) - shopt -s nullglob - local -a svcs=($(printf '%s\n' $xinetddir/!($_backup_glob))) - $reset - ((!${#svcs[@]})) || - COMPREPLY+=($(compgen -W '${svcs[@]#$xinetddir/}' -- "${cur-}")) + local -a svcs + if _comp_expand_glob svcs '$xinetddir/!($_comp_backup_glob)'; then + _comp_compgen -U svcs -U xinetddir -- -W '"${svcs[@]#$xinetddir/}"' + fi fi } # This function completes on services # -_services() +# @since 2.12 +_comp_compgen_services() { local sysvdirs - _sysvdirs + _comp_sysvdirs || return 1 - local IFS=$' \t\n' reset=$(shopt -p nullglob) - shopt -s nullglob - COMPREPLY=( - $(printf '%s\n' ${sysvdirs[0]}/!($_backup_glob|functions|README))) - $reset + local services + _comp_expand_glob services '${sysvdirs[0]}/!($_comp_backup_glob|functions|README)' - COMPREPLY+=($({ + local _generated=$({ systemctl list-units --full --all || systemctl list-unit-files } 2>/dev/null | - awk '$1 ~ /\.service$/ { sub("\\.service$", "", $1); print $1 }')) + _comp_awk '$1 ~ /\.service$/ { sub("\\.service$", "", $1); print $1 }') + _comp_split -la services "$_generated" if [[ -x /sbin/upstart-udev-bridge ]]; then - COMPREPLY+=($(initctl list 2>/dev/null | cut -d' ' -f1)) + _comp_split -la services "$(initctl list 2>/dev/null | cut -d' ' -f1)" fi - COMPREPLY=($(compgen -W '${COMPREPLY[@]#${sysvdirs[0]}/}' -- "$cur")) + ((${#services[@]})) || return 1 + _comp_compgen -U services -U sysvdirs -- -W '"${services[@]#${sysvdirs[0]}/}"' } # This completes on a list of all available service scripts for the # 'service' command and/or the SysV init.d directory, followed by # that script's available commands +# This function is in the main bash_completion file rather than in a separate +# one, because we set it up eagerly as completer for scripts in sysv init dirs +# below. # -_service() +# @since 2.12 +_comp_complete_service() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return # don't complete past 2nd token ((cword > 2)) && return if [[ $cword -eq 1 && $prev == ?(*/)service ]]; then - _services - [[ -e /etc/mandrake-release ]] && _xinetd_services + _comp_compgen_services + [[ -e /etc/mandrake-release ]] && _comp_compgen_xinetd_services else local sysvdirs - _sysvdirs - COMPREPLY=($(compgen -W '`command sed -e "y/|/ /" \ - -ne "s/^.*\(U\|msg_u\)sage.*{\(.*\)}.*$/\2/p" \ - ${sysvdirs[0]}/${prev##*/} 2>/dev/null` start stop' -- "$cur")) + _comp_sysvdirs || return 1 + _comp_compgen_split -l -- "$(command sed -e 'y/|/ /' \ + -ne 's/^.*\(U\|msg_u\)sage.*{\(.*\)}.*$/\2/p' \ + "${sysvdirs[0]}/${prev##*/}" 2>/dev/null) start stop" fi } && - complete -F _service service -_sysvdirs -for svcdir in "${sysvdirs[@]}"; do - for svc in $svcdir/!($_backup_glob); do - [[ -x $svc ]] && complete -F _service $svc - done -done -unset svc svcdir sysvdirs + complete -F _comp_complete_service service -# This function completes on modules +_comp__init_set_up_service_completions() +{ + local sysvdirs svc svcdir svcs + _comp_sysvdirs && + for svcdir in "${sysvdirs[@]}"; do + if _comp_expand_glob svcs '"$svcdir"/!($_comp_backup_glob)'; then + for svc in "${svcs[@]}"; do + [[ -x $svc ]] && complete -F _comp_complete_service "$svc" + done + fi + done + unset -f "$FUNCNAME" +} +_comp__init_set_up_service_completions + +# This function completes on kernel modules +# @param $1 kernel version # -_modules() +# @since 2.12 +_comp_compgen_kernel_modules() { - local modpath - modpath=/lib/modules/$1 - COMPREPLY=($(compgen -W "$(command ls -RL $modpath 2>/dev/null | - command sed -ne 's/^\(.*\)\.k\{0,1\}o\(\.[gx]z\)\{0,1\}$/\1/p')" -- "$cur")) + local _modpath=/lib/modules/$1 + _comp_compgen_split -- "$(command ls -RL "$_modpath" 2>/dev/null | + command sed -ne 's/^\(.*\)\.k\{0,1\}o\(\.[gx]z\)\{0,1\}$/\1/p' \ + -e 's/^\(.*\)\.ko\.zst$/\1/p')" } -# This function completes on installed modules +# This function completes on inserted kernel modules +# @param $1 prefix to filter with, default $cur # -_installed_modules() +# @since 2.12 +_comp_compgen_inserted_kernel_modules() { - COMPREPLY=($(compgen -W "$(PATH="$PATH:/sbin" lsmod | - awk '{if (NR != 1) print $1}')" -- "$1")) + _comp_compgen -c "${1:-$cur}" split -- "$(PATH="$PATH:/sbin" lsmod | + _comp_awk '{if (NR != 1) print $1}')" } # This function completes on user or user:group format; as for chown and cpio. @@ -1296,7 +2059,9 @@ _installed_modules() # # @param $1 If -u, only return users/groups the user has access to in # context of current completion. -_usergroup() +# +# @since 2.12 +_comp_compgen_usergroups() { if [[ $cur == *\\\\* || $cur == *:*:* ]]; then # Give up early on if something seems horribly wrong. @@ -1305,27 +2070,26 @@ _usergroup() # Completing group after 'user\:gr<TAB>'. # Reply with a list of groups prefixed with 'user:', readline will # escape to the colon. - local prefix - prefix=${cur%%*([^:])} - prefix=${prefix//\\/} - local mycur="${cur#*[:]}" + local tmp if [[ ${1-} == -u ]]; then - _allowed_groups "$mycur" + _comp_compgen -v tmp -c "${cur#*:}" allowed_groups else - local IFS=$'\n' - COMPREPLY=($(compgen -g -- "$mycur")) + _comp_compgen -v tmp -c "${cur#*:}" -- -g + fi + if ((${#tmp[@]})); then + local _prefix=${cur%%*([^:])} + _prefix=${_prefix//\\/} + _comp_compgen -Rv tmp -- -P "$_prefix" -W '"${tmp[@]}"' + _comp_compgen -U tmp set "${tmp[@]}" fi - COMPREPLY=($(compgen -P "$prefix" -W "${COMPREPLY[@]}")) elif [[ $cur == *:* ]]; then # Completing group after 'user:gr<TAB>'. # Reply with a list of unprefixed groups since readline with split on : # and only replace the 'gr' part - local mycur="${cur#*:}" if [[ ${1-} == -u ]]; then - _allowed_groups "$mycur" + _comp_compgen -c "${cur#*:}" allowed_groups else - local IFS=$'\n' - COMPREPLY=($(compgen -g -- "$mycur")) + _comp_compgen -c "${cur#*:}" -- -g fi else # Completing a partial 'usernam<TAB>'. @@ -1334,168 +2098,274 @@ _usergroup() # slash. It's better to complete into 'chown username ' than 'chown # username\:'. if [[ ${1-} == -u ]]; then - _allowed_users "$cur" + _comp_compgen_allowed_users else - local IFS=$'\n' - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u fi fi } -_allowed_users() +# @since 2.12 +_comp_compgen_allowed_users() { - if _complete_as_root; then - local IFS=$'\n' - COMPREPLY=($(compgen -u -- "${1:-$cur}")) + if _comp_as_root; then + _comp_compgen -- -u else - local IFS=$'\n ' - COMPREPLY=($(compgen -W \ - "$(id -un 2>/dev/null || whoami 2>/dev/null)" -- "${1:-$cur}")) + _comp_compgen_split -- "$(id -un 2>/dev/null || whoami 2>/dev/null)" fi } -_allowed_groups() +# @since 2.12 +_comp_compgen_allowed_groups() { - if _complete_as_root; then - local IFS=$'\n' - COMPREPLY=($(compgen -g -- "$1")) + if _comp_as_root; then + _comp_compgen -- -g else - local IFS=$'\n ' - COMPREPLY=($(compgen -W \ - "$(id -Gn 2>/dev/null || groups 2>/dev/null)" -- "$1")) + _comp_compgen_split -- "$(id -Gn 2>/dev/null || groups 2>/dev/null)" fi } +# @since 2.12 +_comp_compgen_selinux_users() +{ + _comp_compgen_split -- "$(semanage user -nl 2>/dev/null | + _comp_awk '{ print $1 }')" +} + # This function completes on valid shells +# @param $1 chroot to search from # -_shells() -{ - local shell rest - while read -r shell rest; do - [[ $shell == /* && $shell == "$cur"* ]] && COMPREPLY+=($shell) - done 2>/dev/null </etc/shells +# @since 2.12 +_comp_compgen_shells() +{ + local -a shells=() + local _shell _rest + while read -r _shell _rest; do + [[ $_shell == /* ]] && shells+=("$_shell") + done 2>/dev/null <"${1-}"/etc/shells + _comp_compgen -U shells -- -W '"${shells[@]}"' } # This function completes on valid filesystem types # -_fstypes() +# @since 2.12 +_comp_compgen_fstypes() { - local fss + local _fss if [[ -e /proc/filesystems ]]; then # Linux - fss="$(cut -d$'\t' -f2 /proc/filesystems) - $(awk '! /\*/ { print $NF }' /etc/filesystems 2>/dev/null)" + _fss="$(cut -d$'\t' -f2 /proc/filesystems) + $(_comp_awk '! /\*/ { print $NF }' /etc/filesystems 2>/dev/null)" else # Generic - fss="$(awk '/^[ \t]*[^#]/ { print $3 }' /etc/fstab 2>/dev/null) - $(awk '/^[ \t]*[^#]/ { print $3 }' /etc/mnttab 2>/dev/null) - $(awk '/^[ \t]*[^#]/ { print $4 }' /etc/vfstab 2>/dev/null) - $(awk '{ print $1 }' /etc/dfs/fstypes 2>/dev/null) + _fss="$(_comp_awk '/^[ \t]*[^#]/ { print $3 }' /etc/fstab 2>/dev/null) + $(_comp_awk '/^[ \t]*[^#]/ { print $3 }' /etc/mnttab 2>/dev/null) + $(_comp_awk '/^[ \t]*[^#]/ { print $4 }' /etc/vfstab 2>/dev/null) + $(_comp_awk '{ print $1 }' /etc/dfs/fstypes 2>/dev/null) + $(lsvfs 2>/dev/null | _comp_awk '$1 !~ /^(Filesystem|[^a-zA-Z])/ { print $1 }') $([[ -d /etc/fs ]] && command ls /etc/fs)" fi - [[ -n $fss ]] && COMPREPLY+=($(compgen -W "$fss" -- "$cur")) + [[ $_fss ]] && _comp_compgen_split -- "$_fss" +} + +# Get absolute path to a file, with rudimentary canonicalization. +# No symlink resolution or existence checks are done; +# see `_comp_realcommand` for those. +# @param $1 The file +# @var[out] REPLY The path +# @since 2.12 +_comp_abspath() +{ + REPLY=$1 + case $REPLY in + /*) ;; + ../*) REPLY=$PWD/${REPLY:3} ;; + *) REPLY=$PWD/$REPLY ;; + esac + while [[ $REPLY == */./* ]]; do + REPLY=${REPLY//\/.\//\/} + done + REPLY=${REPLY//+(\/)/\/} } # Get real command. -# - arg: $1 Command -# - stdout: Filename of command in PATH with possible symbolic links resolved. -# Empty string if command not found. -# - return: True (0) if command found, False (> 0) if not. -_realcommand() -{ - type -P "$1" >/dev/null && { - if type -p realpath >/dev/null; then - realpath "$(type -P "$1")" - elif type -p greadlink >/dev/null; then - greadlink -f "$(type -P "$1")" - elif type -p readlink >/dev/null; then - readlink -f "$(type -P "$1")" - else - type -P "$1" - fi - } +# Command is the filename of command in PATH with possible symlinks resolved +# (if resolve tooling available), empty string if command not found. +# @param $1 Command +# @var[out] REPLY Resulting string +# @return True (0) if command found, False (> 0) if not. +# @since 2.12 +_comp_realcommand() +{ + REPLY="" + local file + file=$(type -P "$1") || return $? + if type -p realpath >/dev/null; then + REPLY=$(realpath "$file") + elif type -p greadlink >/dev/null; then + REPLY=$(greadlink -f "$file") + elif type -p readlink >/dev/null; then + REPLY=$(readlink -f "$file") + else + _comp_abspath "$file" + fi } -# This function returns the first argument, excluding options -# @param $1 chars Characters out of $COMP_WORDBREAKS which should -# NOT be considered word breaks. See __reassemble_comp_words_by_ref. -_get_first_arg() -{ - local i +# This function returns the position of the first argument, excluding options +# +# Options: +# -a GLOB Pattern of options that take an option argument +# +# @var[out] REPLY Position of the first argument before the current one being +# completed if any, or otherwise an empty string +# @return True (0) if any argument is found, False (> 0) otherwise. +# @since 2.12 +_comp_locate_first_arg() +{ + local has_optarg="" + local OPTIND=1 OPTARG="" OPTERR=0 _opt + while getopts ':a:' _opt "$@"; do + case $_opt in + a) has_optarg=$OPTARG ;; + *) + echo "bash_completion: $FUNCNAME: usage error" >&2 + return 2 + ;; + esac + done + shift "$((OPTIND - 1))" - arg= - for ((i = 1; i < COMP_CWORD; i++)); do - if [[ ${COMP_WORDS[i]} != -* ]]; then - arg=${COMP_WORDS[i]} + local i + REPLY= + for ((i = 1; i < cword; i++)); do + # shellcheck disable=SC2053 + if [[ $has_optarg && ${words[i]} == $has_optarg ]]; then + ((i++)) + elif [[ ${words[i]} != -?* ]]; then + REPLY=$i + return 0 + elif [[ ${words[i]} == -- ]]; then + ((i + 1 < cword)) && REPLY=$((i + 1)) && return 0 break fi done + return 1 } -# This function counts the number of args, excluding options -# @param $1 chars Characters out of $COMP_WORDBREAKS which should -# NOT be considered word breaks. See __reassemble_comp_words_by_ref. -# @param $2 glob Options whose following argument should not be counted -# @param $3 glob Options that should be counted as args -_count_args() +# This function returns the first argument, excluding options +# +# Options: +# -a GLOB Pattern of options that take an option argument +# +# @var[out] REPLY First argument before the current one being completed if any, +# or otherwise an empty string +# @return True (0) if any argument is found, False (> 0) otherwise. +# @since 2.12 +_comp_get_first_arg() { - local i cword words - __reassemble_comp_words_by_ref "${1-}" words cword + _comp_locate_first_arg "$@" && REPLY=${words[REPLY]} +} - args=1 +# This function counts the number of args, excluding options +# +# Options: +# -n CHARS Characters out of $COMP_WORDBREAKS which should +# NOT be considered word breaks. See +# _comp__reassemble_words. +# -a GLOB Options whose following argument should not be counted +# -i GLOB Options that should be counted as args +# +# @var[out] REPLY Return the number of arguments +# @since 2.12 +_comp_count_args() +{ + local has_optarg="" has_exclude="" exclude="" glob_include="" + local OPTIND=1 OPTARG="" OPTERR=0 _opt + while getopts ':a:n:i:' _opt "$@"; do + case $_opt in + a) has_optarg=$OPTARG ;; + n) has_exclude=set exclude+=$OPTARG ;; + i) glob_include=$OPTARG ;; + *) + echo "bash_completion: $FUNCNAME: usage error" >&2 + return 2 + ;; + esac + done + shift "$((OPTIND - 1))" + + if [[ $has_exclude ]]; then + local cword words + _comp__reassemble_words "$exclude<>&" words cword + fi + + local i + REPLY=1 for ((i = 1; i < cword; i++)); do # shellcheck disable=SC2053 - if [[ ${words[i]} != -* && ${words[i - 1]} != ${2-} || \ - ${words[i]} == ${3-} ]]; then - ((args++)) + if [[ $has_optarg && ${words[i]} == $has_optarg ]]; then + ((i++)) + elif [[ ${words[i]} != -?* || $glob_include && ${words[i]} == $glob_include ]]; then + ((REPLY++)) + elif [[ ${words[i]} == -- ]]; then + ((REPLY += cword - i - 1)) + break fi done } # This function completes on PCI IDs # -_pci_ids() +# @since 2.12 +_comp_compgen_pci_ids() { - COMPREPLY+=($(compgen -W \ - "$(PATH="$PATH:/sbin" lspci -n | awk '{print $3}')" -- "$cur")) + _comp_compgen_split -- "$(PATH="$PATH:/sbin" lspci -n | _comp_awk '{print $3}')" } # This function completes on USB IDs # -_usb_ids() +# @since 2.12 +_comp_compgen_usb_ids() { - COMPREPLY+=($(compgen -W \ - "$(PATH="$PATH:/sbin" lsusb | awk '{print $6}')" -- "$cur")) + _comp_compgen_split -- "$(PATH="$PATH:/sbin" lsusb | _comp_awk '{print $6}')" } # CD device names -_cd_devices() +# +# @since 2.12 +_comp_compgen_cd_devices() { - COMPREPLY+=($(compgen -f -d -X "!*/?([amrs])cd*" -- "${cur:-/dev/}")) + _comp_compgen -c "${cur:-/dev/}" -- -f -d -X "!*/?([amrs])cd!(c-*)" } # DVD device names -_dvd_devices() +# +# @since 2.12 +_comp_compgen_dvd_devices() { - COMPREPLY+=($(compgen -f -d -X "!*/?(r)dvd*" -- "${cur:-/dev/}")) + _comp_compgen -c "${cur:-/dev/}" -- -f -d -X "!*/?(r)dvd*" } # TERM environment variable values -_terms() +# +# @since 2.12 +_comp_compgen_terms() { - COMPREPLY+=($(compgen -W "$({ + _comp_compgen_split -- "$({ command sed -ne 's/^\([^[:space:]#|]\{2,\}\)|.*/\1/p' /etc/termcap { toe -a || toe - } | awk '{ print $1 }' - find /{etc,lib,usr/lib,usr/share}/terminfo/? -type f -maxdepth 1 | - awk -F/ '{ print $NF }' - } 2>/dev/null)" -- "$cur")) + } | _comp_awk '{ print $1 }' + _comp_expand_glob dirs '/{etc,lib,usr/lib,usr/share}/terminfo/?' && + find "${dirs[@]}" -type f -maxdepth 1 | + _comp_awk -F / '{ print $NF }' + } 2>/dev/null)" } -_bashcomp_try_faketty() +# @since 2.12 +_comp_try_faketty() { if type unbuffer &>/dev/null; then unbuffer -p "$@" @@ -1514,95 +2384,122 @@ _bashcomp_try_faketty() # This function provides simple user@host completion # -_user_at_host() +# @since 2.12 +_comp_complete_user_at_host() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return if [[ $cur == *@* ]]; then - _known_hosts_real "$cur" + _comp_compgen_known_hosts "$cur" else - COMPREPLY=($(compgen -u -S @ -- "$cur")) + _comp_compgen -- -u -S @ compopt -o nospace fi } -shopt -u hostcomplete && complete -F _user_at_host talk ytalk finger +shopt -u hostcomplete && complete -F _comp_complete_user_at_host talk ytalk finger # NOTE: Using this function as a helper function is deprecated. Use -# `_known_hosts_real' instead. -_known_hosts() -{ - local cur prev words cword - _init_completion -n : || return - - # NOTE: Using `_known_hosts' as a helper function and passing options - # to `_known_hosts' is deprecated: Use `_known_hosts_real' instead. - local options - [[ ${1-} == -a || ${2-} == -a ]] && options=-a - [[ ${1-} == -c || ${2-} == -c ]] && options+=" -c" - _known_hosts_real ${options-} -- "$cur" -} # _known_hosts() +# `_comp_compgen_known_hosts' instead. +# @since 2.12 +_comp_complete_known_hosts() +{ + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return + + # NOTE: Using `_known_hosts' (the old name of `_comp_complete_known_hosts') + # as a helper function and passing options to `_known_hosts' is + # deprecated: Use `_comp_compgen_known_hosts' instead. + local -a options=() + [[ ${1-} == -a || ${2-} == -a ]] && options+=(-a) + [[ ${1-} == -c || ${2-} == -c ]] && options+=(-c) + local IFS=$' \t\n' # Workaround for connected ${v+"$@"} in bash < 4.4 + _comp_compgen_known_hosts ${options[@]+"${options[@]}"} -- "$cur" +} # Helper function to locate ssh included files in configs # This function looks for the "Include" keyword in ssh config files and # includes them recursively, adding each result to the config variable. -_included_ssh_config_files() +_comp__included_ssh_config_files() { (($# < 1)) && echo "bash_completion: $FUNCNAME: missing mandatory argument CONFIG" >&2 - local configfile i f + local configfile i files f REPLY configfile=$1 - local reset=$(shopt -po noglob) - set -o noglob - local included=($(command sed -ne 's/^[[:blank:]]*[Ii][Nn][Cc][Ll][Uu][Dd][Ee][[:blank:]]\(.*\)$/\1/p' "${configfile}")) - $reset - - [[ ${included-} ]] || return - for i in "${included[@]}"; do - # Check the origin of $configfile to complete relative included paths on included - # files according to ssh_config(5): - # "[...] Files without absolute paths are assumed to be in ~/.ssh if included in a user - # configuration file or /etc/ssh if included from the system configuration file.[...]" - if ! [[ $i =~ ^\~.*|^\/.* ]]; then - if [[ $configfile =~ ^\/etc\/ssh.* ]]; then - i="/etc/ssh/$i" - else - i="$HOME/.ssh/$i" + # From man ssh_config: + # "Files without absolute paths are assumed to be in ~/.ssh if included + # in a user configuration file or /etc/ssh if included from the system + # configuration file." + # This behavior is not affected by the the including file location - + # if the system configuration file is included from the user's config, + # relative includes are still resolved in the user's ssh config directory. + local relative_include_base + if [[ $configfile == /etc/ssh* ]]; then + relative_include_base="/etc/ssh" + else + relative_include_base="$HOME/.ssh" + fi + + local depth=1 + local -a included + local -a include_files + included=("$configfile") + + # Max recursion depth per openssh's READCONF_MAX_DEPTH: + # https://github.com/openssh/openssh-portable/blob/5ec5504f1d328d5bfa64280cd617c3efec4f78f3/readconf.c#L2240 + local max_depth=16 + while ((${#included[@]} > 0 && depth++ < max_depth)); do + _comp_split include_files "$(command sed -ne 's/^[[:blank:]]*[Ii][Nn][Cc][Ll][Uu][Dd][Ee][[:blank:]]\(.*\)$/\1/p' "${included[@]}")" || return + included=() + for i in "${include_files[@]}"; do + if [[ $i != [~/]* ]]; then + i="${relative_include_base}/${i}" fi - fi - __expand_tilde_by_ref i - # In case the expanded variable contains multiple paths - set +o noglob - for f in $i; do - if [[ -r $f ]]; then - config+=("$f") - # The Included file is processed to look for Included files in itself - _included_ssh_config_files $f + _comp_expand_tilde "$i" + if _comp_expand_glob files '$REPLY'; then + # In case the expanded variable contains multiple paths + for f in "${files[@]}"; do + if [[ -r $f && ! -d $f ]]; then + config+=("$f") + included+=("$f") + fi + done fi done - $reset done -} # _included_ssh_config_files() +} -# Helper function for completing _known_hosts. +# Helper function for completing _comp_complete_known_hosts. # This function performs host completion based on ssh's config and known_hosts # files, as well as hostnames reported by avahi-browse if -# COMP_KNOWN_HOSTS_WITH_AVAHI is set to a non-empty value. Also hosts from -# HOSTFILE (compgen -A hostname) are added, unless -# COMP_KNOWN_HOSTS_WITH_HOSTFILE is set to an empty value. -# Usage: _known_hosts_real [OPTIONS] CWORD -# Options: -a Use aliases from ssh config files -# -c Use `:' suffix -# -F configfile Use `configfile' for configuration settings -# -p PREFIX Use PREFIX -# -4 Filter IPv6 addresses from results -# -6 Filter IPv4 addresses from results -# Return: Completions, starting with CWORD, are added to COMPREPLY[] -_known_hosts_real() -{ - local configfile flag prefix="" ifs=$IFS - local cur suffix="" aliases i host ipv4 ipv6 +# BASH_COMPLETION_KNOWN_HOSTS_WITH_AVAHI is set to a non-empty value. +# Also hosts from HOSTFILE (compgen -A hostname) are added, unless +# BASH_COMPLETION_KNOWN_HOSTS_WITH_HOSTFILE is set to an empty value. +# Usage: _comp_compgen_known_hosts [OPTIONS] CWORD +# Options: +# -a Use aliases from ssh config files +# -c Use `:' suffix +# -F configfile Use `configfile' for configuration settings +# -p PREFIX Use PREFIX +# -4 Filter IPv6 addresses from results +# -6 Filter IPv4 addresses from results +# @var[out] COMPREPLY Completions, starting with CWORD, are added +# @return True (0) if one or more completions are generated, or otherwise False +# (1). +# @since 2.12 +_comp_compgen_known_hosts() +{ + local known_hosts + _comp_compgen_known_hosts__impl "$@" || return "$?" + _comp_compgen -U known_hosts set "${known_hosts[@]}" +} +_comp_compgen_known_hosts__impl() +{ + known_hosts=() + + local configfile="" flag prefix="" + local cur suffix="" aliases="" i host ipv4="" ipv6="" local -a kh tmpkh=() khd=() config=() # TODO remove trailing %foo from entries @@ -1610,21 +2507,27 @@ _known_hosts_real() local OPTIND=1 while getopts "ac46F:p:" flag "$@"; do case $flag in - a) aliases='yes' ;; + a) aliases=set ;; c) suffix=':' ;; - F) configfile=$OPTARG ;; + F) + if [[ ! $OPTARG ]]; then + echo "bash_completion: $FUNCNAME: -F: an empty filename is specified" >&2 + return 2 + fi + configfile=$OPTARG + ;; p) prefix=$OPTARG ;; - 4) ipv4=1 ;; - 6) ipv6=1 ;; + 4) ipv4=set ;; + 6) ipv6=set ;; *) echo "bash_completion: $FUNCNAME: usage error" >&2 - return 1 + return 2 ;; esac done if (($# < OPTIND)); then echo "bash_completion: $FUNCNAME: missing mandatory argument CWORD" >&2 - return 1 + return 2 fi cur=${!OPTIND} ((OPTIND += 1)) @@ -1634,68 +2537,63 @@ _known_hosts_real() printf '%s ' ${!OPTIND} shift done)" >&2 - return 1 + return 2 fi [[ $cur == *@* ]] && prefix=$prefix${cur%@*}@ && cur=${cur#*@} kh=() # ssh config files - if [[ -v configfile ]]; then - [[ -r $configfile ]] && config+=("$configfile") + if [[ $configfile ]]; then + [[ -r $configfile && ! -d $configfile ]] && config+=("$configfile") else for i in /etc/ssh/ssh_config ~/.ssh/config ~/.ssh2/config; do - [[ -r $i ]] && config+=("$i") + [[ -r $i && ! -d $i ]] && config+=("$i") done fi - local reset=$(shopt -po noglob) - set -o noglob - # "Include" keyword in ssh config files if ((${#config[@]} > 0)); then for i in "${config[@]}"; do - _included_ssh_config_files "$i" + _comp__included_ssh_config_files "$i" done fi # Known hosts files from configs if ((${#config[@]} > 0)); then - local IFS=$'\n' # expand paths (if present) to global and user known hosts files # TODO(?): try to make known hosts files with more than one consecutive # spaces in their name work (watch out for ~ expansion # breakage! Alioth#311595) - tmpkh=($(awk 'sub("^[ \t]*([Gg][Ll][Oo][Bb][Aa][Ll]|[Uu][Ss][Ee][Rr])[Kk][Nn][Oo][Ww][Nn][Hh][Oo][Ss][Tt][Ss][Ff][Ii][Ll][Ee][ \t]+", "") { print $0 }' "${config[@]}" | sort -u)) - IFS=$ifs - fi - if ((${#tmpkh[@]} != 0)); then - local j - for i in "${tmpkh[@]}"; do - # First deal with quoted entries... - while [[ $i =~ ^([^\"]*)\"([^\"]*)\"(.*)$ ]]; do - i=${BASH_REMATCH[1]}${BASH_REMATCH[3]} - j=${BASH_REMATCH[2]} - __expand_tilde_by_ref j # Eval/expand possible `~' or `~user' - [[ -r $j ]] && kh+=("$j") - done - # ...and then the rest. - for j in $i; do - __expand_tilde_by_ref j # Eval/expand possible `~' or `~user' - [[ -r $j ]] && kh+=("$j") + if _comp_split -l tmpkh "$(_comp_awk 'sub("^[ \t]*([Gg][Ll][Oo][Bb][Aa][Ll]|[Uu][Ss][Ee][Rr])[Kk][Nn][Oo][Ww][Nn][Hh][Oo][Ss][Tt][Ss][Ff][Ii][Ll][Ee][ \t=]+", "") { print $0 }' "${config[@]}" | sort -u)"; then + local tmpkh2 j REPLY + for i in "${tmpkh[@]}"; do + # First deal with quoted entries... + while [[ $i =~ ^([^\"]*)\"([^\"]*)\"(.*)$ ]]; do + i=${BASH_REMATCH[1]}${BASH_REMATCH[3]} + _comp_expand_tilde "${BASH_REMATCH[2]}" # Eval/expand possible `~' or `~user' + [[ -r $REPLY ]] && kh+=("$REPLY") + done + # ...and then the rest. + _comp_split tmpkh2 "$i" || continue + for j in "${tmpkh2[@]}"; do + _comp_expand_tilde "$j" # Eval/expand possible `~' or `~user' + [[ -r $REPLY ]] && kh+=("$REPLY") + done done - done + fi fi - if [[ ! -v configfile ]]; then + if [[ ! $configfile ]]; then # Global and user known_hosts files for i in /etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts2 \ /etc/known_hosts /etc/known_hosts2 ~/.ssh/known_hosts \ ~/.ssh/known_hosts2; do - [[ -r $i ]] && kh+=("$i") + [[ -r $i && ! -d $i ]] && kh+=("$i") done for i in /etc/ssh2/knownhosts ~/.ssh2/hostkeys; do - [[ -d $i ]] && khd+=("$i"/*pub) + [[ -d $i ]] || continue + _comp_expand_glob tmpkh '"$i"/*.pub' && khd+=("${tmpkh[@]}") done fi @@ -1706,27 +2604,27 @@ _known_hosts_real() for i in "${kh[@]}"; do while read -ra tmpkh; do ((${#tmpkh[@]} == 0)) && continue - set -- "${tmpkh[@]}" # Skip entries starting with | (hashed) and # (comment) - [[ $1 == [\|\#]* ]] && continue + [[ ${tmpkh[0]} == [\|\#]* ]] && continue # Ignore leading @foo (markers) - [[ $1 == @* ]] && shift + local host_list=${tmpkh[0]} + [[ ${tmpkh[0]} == @* ]] && host_list=${tmpkh[1]-} # Split entry on commas - local IFS=, - for host in $1; do - # Skip hosts containing wildcards - [[ $host == *[*?]* ]] && continue - # Remove leading [ - host="${host#[}" - # Remove trailing ] + optional :port - host="${host%]?(:+([0-9]))}" - # Add host to candidates - COMPREPLY+=($host) - done - IFS=$ifs + local -a hosts + if _comp_split -F , hosts "$host_list"; then + for host in "${hosts[@]}"; do + # Skip hosts containing wildcards + [[ $host == *[*?]* ]] && continue + # Remove leading [ + host=${host#[} + # Remove trailing ] + optional :port + host=${host%]?(:+([0-9]))} + # Add host to candidates + [[ $host ]] && known_hosts+=("$host") + done + fi done <"$i" done - COMPREPLY=($(compgen -W '${COMPREPLY[@]}' -- "$cur")) fi if ((${#khd[@]} > 0)); then # Needs to look for files called @@ -1734,213 +2632,233 @@ _known_hosts_real() # dont fork any processes, because in a cluster environment, # there can be hundreds of hostkeys for i in "${khd[@]}"; do - if [[ $i == *key_22_$cur*.pub && -r $i ]]; then + if [[ $i == *key_22_*.pub && -r $i ]]; then host=${i/#*key_22_/} host=${host/%.pub/} - COMPREPLY+=($host) + [[ $host ]] && known_hosts+=("$host") fi done fi # apply suffix and prefix - for i in ${!COMPREPLY[*]}; do - COMPREPLY[i]=$prefix${COMPREPLY[i]}$suffix - done + ((${#known_hosts[@]})) && + _comp_compgen -v known_hosts -- -W '"${known_hosts[@]}"' -P "$prefix" -S "$suffix" fi # append any available aliases from ssh config files - if [[ ${#config[@]} -gt 0 && -v aliases ]]; then - local -a hosts=($(command sed -ne 's/^[[:blank:]]*[Hh][Oo][Ss][Tt][[:blank:]]\(.*\)$/\1/p' "${config[@]}")) - if ((${#hosts[@]} != 0)); then - COMPREPLY+=($(compgen -P "$prefix" \ - -S "$suffix" -W '${hosts[@]%%[*?%]*}' -X '\!*' -- "$cur")) + if [[ ${#config[@]} -gt 0 && $aliases ]]; then + local -a hosts + if _comp_split hosts "$(command sed -ne 's/^[[:blank:]]*[Hh][Oo][Ss][Tt][[:blank:]=]\{1,\}\(.*\)$/\1/p' "${config[@]}")"; then + _comp_compgen -av known_hosts -- -P "$prefix" \ + -S "$suffix" -W '"${hosts[@]%%[*?%]*}"' -X '@(\!*|)' fi fi # Add hosts reported by avahi-browse, if desired and it's available. - if [[ ${COMP_KNOWN_HOSTS_WITH_AVAHI-} ]] && + if [[ ${BASH_COMPLETION_KNOWN_HOSTS_WITH_AVAHI-} ]] && type avahi-browse &>/dev/null; then - # The original call to avahi-browse also had "-k", to avoid lookups - # into avahi's services DB. We don't need the name of the service, and - # if it contains ";", it may mistify the result. But on Gentoo (at - # least), -k wasn't available (even if mentioned in the manpage) some - # time ago, so... - COMPREPLY+=($(compgen -P "$prefix" -S "$suffix" -W \ - "$(avahi-browse -cpr _workstation._tcp 2>/dev/null | - awk -F';' '/^=/ { print $7 }' | sort -u)" -- "$cur")) + # Some old versions of avahi-browse reportedly didn't have -k + # (even if mentioned in the manpage); those we do not support any more. + local generated=$(avahi-browse -cprak 2>/dev/null | _comp_awk -F ';' \ + '/^=/ && $5 ~ /^_(ssh|workstation)\._tcp$/ { print $7 }' | + sort -u) + _comp_compgen -av known_hosts -- -P "$prefix" -S "$suffix" -W '$generated' fi # Add hosts reported by ruptime. if type ruptime &>/dev/null; then - COMPREPLY+=($(compgen -W \ - "$(ruptime 2>/dev/null | awk '!/^ruptime:/ { print $1 }')" \ - -- "$cur")) + local generated=$(ruptime 2>/dev/null | _comp_awk '!/^ruptime:/ { print $1 }') + _comp_compgen -av known_hosts -- -W '$generated' fi # Add results of normal hostname completion, unless - # `COMP_KNOWN_HOSTS_WITH_HOSTFILE' is set to an empty value. - if [[ -n ${COMP_KNOWN_HOSTS_WITH_HOSTFILE-1} ]]; then - COMPREPLY+=( - $(compgen -A hostname -P "$prefix" -S "$suffix" -- "$cur")) + # `BASH_COMPLETION_KNOWN_HOSTS_WITH_HOSTFILE' is set to an empty value. + if [[ ${BASH_COMPLETION_KNOWN_HOSTS_WITH_HOSTFILE-set} ]]; then + _comp_compgen -av known_hosts -- -A hostname -P "$prefix" -S "$suffix" fi - $reset + ((${#known_hosts[@]})) || return 1 - if [[ -v ipv4 ]]; then - COMPREPLY=("${COMPREPLY[@]/*:*$suffix/}") + if [[ $ipv4 ]]; then + known_hosts=("${known_hosts[@]/*:*$suffix/}") fi - if [[ -v ipv6 ]]; then - COMPREPLY=("${COMPREPLY[@]/+([0-9]).+([0-9]).+([0-9]).+([0-9])$suffix/}") + if [[ $ipv6 ]]; then + known_hosts=("${known_hosts[@]/+([0-9]).+([0-9]).+([0-9]).+([0-9])$suffix/}") fi - if [[ -v ipv4 || -v ipv6 ]]; then - for i in "${!COMPREPLY[@]}"; do - [[ ${COMPREPLY[i]} ]] || unset -v "COMPREPLY[i]" + if [[ $ipv4 || $ipv6 ]]; then + for i in "${!known_hosts[@]}"; do + [[ ${known_hosts[i]} ]] || unset -v 'known_hosts[i]' done fi + ((${#known_hosts[@]})) || return 1 - __ltrim_colon_completions "$prefix$cur" - -} # _known_hosts_real() -complete -F _known_hosts traceroute traceroute6 \ - fping fping6 telnet rsh rlogin ftp dig mtr ssh-installkeys showmount - -# This meta-cd function observes the CDPATH variable, so that cd additionally -# completes on directories under those specified in CDPATH. + _comp_compgen -v known_hosts -c "$prefix$cur" ltrim_colon "${known_hosts[@]}" +} +complete -F _comp_complete_known_hosts traceroute traceroute6 \ + fping fping6 telnet rsh rlogin ftp dig drill mtr ssh-installkeys showmount + +# Convert the word index in `words` to the index in `COMP_WORDS`. +# @param $1 Index in the array WORDS. +# @var[in,opt] words Words that contain reassmbled words. +# @var[in,opt] cword Current word index in WORDS. +# WORDS and CWORD, if any, are expected to be created by +# _comp__reassemble_words. # -_cd() +_comp__find_original_word() { - local cur prev words cword - _init_completion || return + REPLY=$1 - local IFS=$'\n' i j k + # If CWORD or WORDS are undefined, we return the first argument without any + # processing. + [[ -v cword && -v words ]] || return 0 - compopt -o filenames - - # Use standard dir completion if no CDPATH or parameter starts with /, - # ./ or ../ - if [[ -z ${CDPATH:-} || $cur == ?(.)?(.)/* ]]; then - _filedir -d - return - fi - - local -r mark_dirs=$(_rl_enabled mark-directories && echo y) - local -r mark_symdirs=$(_rl_enabled mark-symlinked-directories && echo y) - - # we have a CDPATH, so loop on its contents - for i in ${CDPATH//:/$'\n'}; do - # create an array of matched subdirs - k="${#COMPREPLY[@]}" - for j in $(compgen -d -- $i/$cur); do - if [[ ($mark_symdirs && -L $j || $mark_dirs && ! -L $j) && ! -d ${j#$i/} ]]; then - j+="/" - fi - COMPREPLY[k++]=${j#$i/} + local reassembled_offset=$1 i=0 j + for ((j = 0; j < reassembled_offset; j++)); do + local word=${words[j]} + while [[ $word && i -lt ${#COMP_WORDS[@]} && $word == *"${COMP_WORDS[i]}"* ]]; do + word=${word#*"${COMP_WORDS[i++]}"} done done - - _filedir -d - - if ((${#COMPREPLY[@]} == 1)); then - i=${COMPREPLY[0]} - if [[ $i == "$cur" && $i != "*/" ]]; then - COMPREPLY[0]="${i}/" - fi - fi - - return + REPLY=$i } -if shopt -q cdable_vars; then - complete -v -F _cd -o nospace cd pushd -else - complete -F _cd -o nospace cd pushd -fi - -# A _command_offset wrapper function for use when the offset is unknown. -# Only intended to be used as a completion function directly associated -# with a command, not to be invoked from within other completion functions. -# -_command() -{ - local offset i - - # find actual offset, as position of the first non-option - offset=1 - for ((i = 1; i <= COMP_CWORD; i++)); do - if [[ ${COMP_WORDS[i]} != -* ]]; then - offset=$i - break - fi - done - _command_offset $offset -} - # A meta-command completion function for commands like sudo(8), which need to # first complete on a command, then complete according to that command's own # completion definition. # -_command_offset() +# @since 2.12 +_comp_command_offset() { # rewrite current completion context before invoking # actual command completion + # obtain the word index in COMP_WORDS + local REPLY + _comp__find_original_word "$1" + local word_offset=$REPLY + + # make changes to COMP_* local. Note that bash-4.3..5.0 have a + # bug that `local -a arr=("${arr[@]}")` fails. We instead first + # assign the values of `COMP_WORDS` to another array `comp_words`. + local COMP_LINE=$COMP_LINE COMP_POINT=$COMP_POINT COMP_CWORD=$COMP_CWORD + local -a comp_words=("${COMP_WORDS[@]}") + local -a COMP_WORDS=("${comp_words[@]}") + # find new first word position, then # rewrite COMP_LINE and adjust COMP_POINT - local word_offset=$1 i j + local i tail for ((i = 0; i < word_offset; i++)); do - for ((j = 0; j <= ${#COMP_LINE}; j++)); do - [[ $COMP_LINE == "${COMP_WORDS[i]}"* ]] && break - COMP_LINE=${COMP_LINE:1} - ((COMP_POINT--)) - done - COMP_LINE=${COMP_LINE#"${COMP_WORDS[i]}"} - ((COMP_POINT -= ${#COMP_WORDS[i]})) + tail=${COMP_LINE#*"${COMP_WORDS[i]}"} + ((COMP_POINT -= ${#COMP_LINE} - ${#tail})) + COMP_LINE=$tail done # shift COMP_WORDS elements and adjust COMP_CWORD - for ((i = 0; i <= COMP_CWORD - word_offset; i++)); do - COMP_WORDS[i]=${COMP_WORDS[i + word_offset]} - done - for ((i; i <= COMP_CWORD; i++)); do - unset 'COMP_WORDS[i]' - done + COMP_WORDS=("${COMP_WORDS[@]:word_offset}") ((COMP_CWORD -= word_offset)) COMPREPLY=() local cur - _get_comp_words_by_ref cur + _comp_get_words cur if ((COMP_CWORD == 0)); then - local IFS=$'\n' - compopt -o filenames - COMPREPLY=($(compgen -d -c -- "$cur")) + _comp_compgen_commands else - local cmd=${COMP_WORDS[0]} compcmd=${COMP_WORDS[0]} - local cspec=$(complete -p $cmd 2>/dev/null) + _comp_dequote "${COMP_WORDS[0]}" || REPLY=${COMP_WORDS[0]} + local cmd=$REPLY compcmd=$REPLY + local cspec=$(complete -p "$cmd" 2>/dev/null) # If we have no completion for $cmd yet, see if we have for basename if [[ ! $cspec && $cmd == */* ]]; then - cspec=$(complete -p ${cmd##*/} 2>/dev/null) + cspec=$(complete -p "${cmd##*/}" 2>/dev/null) [[ $cspec ]] && compcmd=${cmd##*/} fi # If still nothing, just load it for the basename if [[ ! $cspec ]]; then compcmd=${cmd##*/} - _completion_loader $compcmd - cspec=$(complete -p $compcmd 2>/dev/null) + _comp_load -D -- "$compcmd" + cspec=$(complete -p "$compcmd" 2>/dev/null) fi - if [[ -n $cspec ]]; then - if [[ ${cspec#* -F } != "$cspec" ]]; then - # complete -F <function> + local retry_count=0 + while true; do # loop for the retry request by status 124 + local args original_cur=${comp_args[1]-$cur} + if ((${#COMP_WORDS[@]} >= 2)); then + args=("$cmd" "$original_cur" "${COMP_WORDS[-2]}") + else + args=("$cmd" "$original_cur") + fi + + if [[ ! $cspec ]]; then + if ((${#COMPREPLY[@]} == 0)); then + # XXX will probably never happen as long as completion loader loads + # *something* for every command thrown at it ($cspec != empty) + _comp_complete_minimal "${args[@]}" + fi + elif [[ $cspec == *\ -[CF]\ * ]]; then + if [[ $cspec == *' -F '* ]]; then + # complete -F <function> + + # get function name + local func=${cspec#* -F } + func=${func%% *} + $func "${args[@]}" + + # restart completion (once) if function exited with 124 + if (($? == 124 && retry_count++ == 0)); then + # Note: When the completion function returns 124, the + # state of COMPREPLY is discarded. + COMPREPLY=() - # get function name - local func=${cspec#*-F } - func=${func%% *} + cspec=$(complete -p "$compcmd" 2>/dev/null) - if ((${#COMP_WORDS[@]} >= 2)); then - $func $cmd "${COMP_WORDS[-1]}" "${COMP_WORDS[-2]}" + # Note: When completion spec is removed after 124, we + # do not generate any completions including the default + # ones. This is the behavior of the original Bash + # progcomp. + [[ $cspec ]] || break + + continue + fi else - $func $cmd "${COMP_WORDS[-1]}" + # complete -C <command> + + # get command name + local completer=${cspec#* -C \'} + + # completer commands are always single-quoted + if ! _comp_dequote "'$completer"; then + _minimal "${args[@]}" + break + fi + completer=${REPLY[0]} + + local -a suggestions + + local IFS=$' \t\n' + local reset_monitor=$(shopt -po monitor) reset_lastpipe=$(shopt -p lastpipe) reset_noglob=$(shopt -po noglob) + set +o monitor + shopt -s lastpipe + set -o noglob + + COMP_KEY="$COMP_KEY" COMP_LINE="$COMP_LINE" \ + COMP_POINT="$COMP_POINT" COMP_TYPE="$COMP_TYPE" \ + $completer "${args[@]}" | mapfile -t suggestions + + $reset_monitor + $reset_lastpipe + $reset_noglob + _comp_unlocal IFS + + local suggestion + local i=0 + COMPREPLY=() + for suggestion in "${suggestions[@]}"; do + COMPREPLY[i]+=${COMPREPLY[i]+$'\n'}$suggestion + + if [[ $suggestion != *\\ ]]; then + ((i++)) + fi + done fi # restore initial compopts @@ -1949,53 +2867,93 @@ _command_offset() # FIXME: should we take "+o opt" into account? cspec=${cspec#*-o } opt=${cspec%% *} - compopt -o $opt - cspec=${cspec#$opt} + compopt -o "$opt" + cspec=${cspec#"$opt"} done else cspec=${cspec#complete} - cspec=${cspec%%$compcmd} - COMPREPLY=($(eval compgen "$cspec" -- '$cur')) + cspec=${cspec%%@("$compcmd"|"'${compcmd//\'/\'\\\'\'}'")} + eval "_comp_compgen -- $cspec" fi - elif ((${#COMPREPLY[@]} == 0)); then - # XXX will probably never happen as long as completion loader loads - # *something* for every command thrown at it ($cspec != empty) - _minimal - fi + break + done fi } -complete -F _command aoss command "do" else eval exec ltrace nice nohup padsp \ + +# A _comp_command_offset wrapper function for use when the offset is unknown. +# Only intended to be used as a completion function directly associated +# with a command, not to be invoked from within other completion functions. +# +# @since 2.12 +_comp_command() +{ + # We unset the shell variable `words` locally to tell + # `_comp_command_offset` that the index is intended to be that in + # `COMP_WORDS` instead of `words`. + local words + unset -v words + + local offset i + + # find actual offset, as position of the first non-option + offset=1 + for ((i = 1; i <= COMP_CWORD; i++)); do + if [[ ${COMP_WORDS[i]} != -* ]]; then + offset=$i + break + fi + done + _comp_command_offset $offset +} +complete -F _comp_command aoss command "do" else eval exec ltrace nice nohup padsp \ "then" time tsocks vsound xargs -_root_command() +# @since 2.12 +_comp_root_command() { local PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin - local root_command=$1 - _command + local _comp_root_command=$1 + _comp_command } -complete -F _root_command fakeroot gksu gksudo kdesudo really +complete -F _comp_root_command fakeroot gksu gksudo kdesudo really # Return true if the completion should be treated as running as root -_complete_as_root() +# +# @since 2.12 +_comp_as_root() { - [[ $EUID -eq 0 || ${root_command:-} ]] + [[ $EUID -eq 0 || ${_comp_root_command-} ]] } -_longopt() +# Complete on available commands, subject to `no_empty_cmd_completion`. +# @return True (0) if one or more completions are generated, or otherwise False +# (1). Note that it returns 1 even when the completion generation is canceled +# by `shopt -s no_empty_cmd_completion`. +# +# @since 2.12 +_comp_compgen_commands() { - local cur prev words cword split - _init_completion -s || return + [[ ! ${cur-} ]] && shopt -q no_empty_cmd_completion && return 1 + # -o filenames for e.g. spaces in paths to and in command names + _comp_compgen -- -c -o plusdirs && compopt -o filenames +} + +# @since 2.12 +_comp_complete_longopt() +{ + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case "${prev,,}" in --help | --usage | --version) return ;; --!(no-*)dir*) - _filedir -d + _comp_compgen -a filedir -d return ;; --!(no-*)@(file|path)*) - _filedir + _comp_compgen -a filedir return ;; --+([-a-z0-9_])) @@ -2003,60 +2961,65 @@ _longopt() "s|.*$prev\[\{0,1\}=[<[]\{0,1\}\([-A-Za-z0-9_]\{1,\}\).*|\1|p") case ${argtype,,} in *dir*) - _filedir -d + _comp_compgen -a filedir -d return ;; *file* | *path*) - _filedir + _comp_compgen -a filedir return ;; esac ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W "$(LC_ALL=C $1 --help 2>&1 | + _comp_compgen_split -- "$(LC_ALL=C $1 --help 2>&1 | while read -r line; do [[ $line =~ --[A-Za-z0-9]+([-_][A-Za-z0-9]+)*=? ]] && - printf '%s\n' ${BASH_REMATCH[0]} - done)" -- "$cur")) + printf '%s\n' "${BASH_REMATCH[0]}" + done)" [[ ${COMPREPLY-} == *= ]] && compopt -o nospace elif [[ $1 == *@(rmdir|chroot) ]]; then - _filedir -d + _comp_compgen -a filedir -d else [[ $1 == *mkdir ]] && compopt -o nospace - _filedir + _comp_compgen -a filedir fi } # makeinfo and texi2dvi are defined elsewhere. -complete -F _longopt a2ps awk base64 bash bc bison cat chroot colordiff cp \ +complete -F _comp_complete_longopt \ + a2ps awk base64 bash bc bison cat chroot colordiff cp \ csplit cut date df diff dir du enscript env expand fmt fold gperf \ - grep grub head irb ld ldd less ln ls m4 md5sum mkdir mkfifo mknod \ + grep grub head irb ld ldd less ln ls m4 mkdir mkfifo mknod \ mv netstat nl nm objcopy objdump od paste pr ptx readelf rm rmdir \ - sed seq sha{,1,224,256,384,512}sum shar sort split strip sum tac tail tee \ + sed seq shar sort split strip sum tac tail tee \ texindex touch tr uname unexpand uniq units vdir wc who -declare -Ag _xspecs +# @since 2.12 +declare -Ag _comp_xspecs -_filedir_xspec() +# @since 2.12 +_comp_complete_filedir_xspec() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + _comp_compgen_filedir_xspec "$1" +} - _tilde "$cur" || return +# @since 2.12 +_comp_compgen_filedir_xspec() +{ + _comp_compgen_tilde && return - local IFS=$'\n' xspec=${_xspecs[${1##*/}]} tmp - local -a toks + local REPLY + _comp_quote_compgen "$cur" + local quoted=$REPLY - toks=($( - compgen -d -- "$(quote_readline "$cur")" | { - while read -r tmp; do - printf '%s\n' $tmp - done - } - )) + local xspec=${_comp_xspecs[${1##*/}]-${_xspecs[${1##*/}]-}} + local -a toks + _comp_compgen -v toks -c "$quoted" -- -d # Munge xspec to contain uppercase version too # https://lists.gnu.org/archive/html/bug-bash/2010-09/msg00036.html @@ -2069,198 +3032,318 @@ _filedir_xspec() fi xspec="$matchop($xspec|${xspec^^})" - toks+=($( - eval compgen -f -X "'!$xspec'" -- '$(quote_readline "$cur")' | { - while read -r tmp; do - [[ -n $tmp ]] && printf '%s\n' $tmp - done - } - )) + _comp_compgen -av toks -c "$quoted" -- -f -X "@(|!($xspec))" # Try without filter if it failed to produce anything and configured to - [[ -n ${COMP_FILEDIR_FALLBACK:-} && ${#toks[@]} -lt 1 ]] && { - local reset=$(shopt -po noglob) - set -o noglob - toks+=($(compgen -f -- "$(quote_readline "$cur")")) - IFS=' ' - $reset - IFS=$'\n' - } + [[ ${BASH_COMPLETION_FILEDIR_FALLBACK-} && ${#toks[@]} -lt 1 ]] && + _comp_compgen -av toks -c "$quoted" -- -f - if ((${#toks[@]} != 0)); then - compopt -o filenames - COMPREPLY=("${toks[@]}") - fi + ((${#toks[@]})) || return 1 + + compopt -o filenames + _comp_compgen -RU toks -- -W '"${toks[@]}"' } -_install_xspec() +_comp__init_install_xspec() { local xspec=$1 cmd shift for cmd in "$@"; do - _xspecs[$cmd]=$xspec + _comp_xspecs[$cmd]=$xspec done } # bzcmp, bzdiff, bz*grep, bzless, bzmore intentionally not here, see Debian: #455510 -_install_xspec '!*.?(t)bz?(2)' bunzip2 bzcat pbunzip2 pbzcat lbunzip2 lbzcat -_install_xspec '!*.@(zip|[aegjswx]ar|exe|pk3|wsz|zargo|xpi|s[tx][cdiw]|sx[gm]|o[dt][tspgfc]|od[bm]|oxt|epub|apk|aab|ipa|do[ct][xm]|p[op]t[mx]|xl[st][xm]|pyz|whl)' unzip zipinfo -_install_xspec '*.Z' compress znew +_comp__init_install_xspec '!*.?(t)bz?(2)' bunzip2 bzcat pbunzip2 pbzcat lbunzip2 lbzcat +_comp__init_install_xspec '!*.@(zip|[aegjkswx]ar|exe|pk3|wsz|zargo|xpi|s[tx][cdiw]|sx[gm]|o[dt][tspgfc]|od[bm]|oxt|?(o)xps|epub|cbz|apk|aab|ipa|do[ct][xm]|p[op]t[mx]|xl[st][xm]|pyz|whl|[Ff][Cc][Ss]td)' unzip zipinfo +_comp__init_install_xspec '*.Z' compress znew # zcmp, zdiff, z*grep, zless, zmore intentionally not here, see Debian: #455510 -_install_xspec '!*.@(Z|[gGd]z|t[ag]z)' gunzip zcat -_install_xspec '!*.@(Z|[gGdz]z|t[ag]z)' unpigz -_install_xspec '!*.Z' uncompress +_comp__init_install_xspec '!*.@(Z|[gGd]z|t[ag]z)' gunzip zcat +_comp__init_install_xspec '!*.@(Z|[gGdz]z|t[ag]z)' unpigz +_comp__init_install_xspec '!*.Z' uncompress # lzcmp, lzdiff intentionally not here, see Debian: #455510 -_install_xspec '!*.@(tlz|lzma)' lzcat lzegrep lzfgrep lzgrep lzless lzmore unlzma -_install_xspec '!*.@(?(t)xz|tlz|lzma)' unxz xzcat -_install_xspec '!*.lrz' lrunzip -_install_xspec '!*.@(gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx)' ee -_install_xspec '!*.@(gif|jp?(e)g|tif?(f)|png|p[bgp]m|bmp|x[bp]m|rle|rgb|pcx|fits|pm|svg)' qiv -_install_xspec '!*.@(gif|jp?(e)g?(2)|j2[ck]|jp[2f]|tif?(f)|png|p[bgp]m|bmp|x[bp]m|rle|rgb|pcx|fits|pm|?(e)ps)' xv -_install_xspec '!*.@(@(?(e)ps|?(E)PS|pdf|PDF)?(.gz|.GZ|.bz2|.BZ2|.Z))' gv ggv kghostview -_install_xspec '!*.@(dvi|DVI)?(.@(gz|Z|bz2))' xdvi kdvi -_install_xspec '!*.dvi' dvips dviselect dvitype dvipdf advi dvipdfm dvipdfmx -_install_xspec '!*.[pf]df' acroread gpdf xpdf -_install_xspec '!*.@(?(e)ps|pdf)' kpdf -_install_xspec '!*.@(okular|@(?(e|x)ps|?(E|X)PS|[pf]df|[PF]DF|dvi|DVI|cb[rz]|CB[RZ]|djv?(u)|DJV?(U)|dvi|DVI|gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx|GIF|JP?(E)G|MIFF|TIF?(F)|PN[GM]|P[BGP]M|BMP|XPM|ICO|XWD|TGA|PCX|epub|EPUB|odt|ODT|fb?(2)|FB?(2)|mobi|MOBI|g3|G3|chm|CHM)?(.?(gz|GZ|bz2|BZ2|xz|XZ)))' okular -_install_xspec '!*.pdf' epdfview pdfunite -_install_xspec '!*.@(cb[rz7t]|djv?(u)|?(e)ps|pdf)' zathura -_install_xspec '!*.@(?(e)ps|pdf)' ps2pdf ps2pdf12 ps2pdf13 ps2pdf14 ps2pdfwr -_install_xspec '!*.texi*' makeinfo texi2html -_install_xspec '!*.@(?(la)tex|texi|dtx|ins|ltx|dbj)' tex latex slitex jadetex pdfjadetex pdftex pdflatex texi2dvi xetex xelatex luatex lualatex -_install_xspec '!*.mp3' mpg123 mpg321 madplay -_install_xspec '!*@(.@(mp?(e)g|MP?(E)G|wm[av]|WM[AV]|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|fxm|FXM|viv|rm|ram|yuv|mov|MOV|qt|QT|web[am]|WEB[AM]|mp[234]|MP[234]|m?(p)4[av]|M?(P)4[AV]|mkv|MKV|og[agmv]|OG[AGMV]|t[ps]|T[PS]|m2t?(s)|M2T?(S)|mts|MTS|wav|WAV|flac|FLAC|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM)|+([0-9]).@(vdr|VDR))?(.@(crdownload|part))' xine aaxine fbxine -_install_xspec '!*@(.@(mp?(e)g|MP?(E)G|wm[av]|WM[AV]|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|fxm|FXM|viv|rm|ram|yuv|mov|MOV|qt|QT|web[am]|WEB[AM]|mp[234]|MP[234]|m?(p)4[av]|M?(P)4[AV]|mkv|MKV|og[agmv]|OG[AGMV]|t[ps]|T[PS]|m2t?(s)|M2T?(S)|mts|MTS|wav|WAV|flac|FLAC|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM|iso|ISO)|+([0-9]).@(vdr|VDR))?(.@(crdownload|part))' kaffeine dragon totem -_install_xspec '!*.@(avi|asf|wmv)' aviplay -_install_xspec '!*.@(rm?(j)|ra?(m)|smi?(l))' realplay -_install_xspec '!*.@(mpg|mpeg|avi|mov|qt)' xanim -_install_xspec '!*.@(og[ag]|m3u|flac|spx)' ogg123 -_install_xspec '!*.@(mp3|ogg|pls|m3u)' gqmpeg freeamp -_install_xspec '!*.fig' xfig -_install_xspec '!*.@(mid?(i)|cmf)' playmidi -_install_xspec '!*.@(mid?(i)|rmi|rcp|[gr]36|g18|mod|xm|it|x3m|s[3t]m|kar)' timidity -_install_xspec '!*.@(669|abc|am[fs]|d[bs]m|dmf|far|it|mdl|m[eo]d|mid?(i)|mt[2m]|oct|okt?(a)|p[st]m|s[3t]m|ult|umx|wav|xm)' modplugplay modplug123 -_install_xspec '*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)' vi vim gvim rvim view rview rgvim rgview gview emacs xemacs sxemacs kate kwrite -_install_xspec '!*.@(zip|z|gz|tgz)' bzme +_comp__init_install_xspec '!*.@(tlz|lzma)' lzcat lzegrep lzfgrep lzgrep lzless lzmore unlzma +_comp__init_install_xspec '!*.@(?(t)xz|tlz|lzma)' unxz xzcat +_comp__init_install_xspec '!*.lrz' lrunzip +_comp__init_install_xspec '!*.@(gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx)' ee +_comp__init_install_xspec '!*.@(gif|jp?(e)g|tif?(f)|png|p[bgp]m|bmp|x[bp]m|rle|rgb|pcx|fits|pm|svg)' qiv +_comp__init_install_xspec '!*.@(gif|jp?(e)g?(2)|j2[ck]|jp[2f]|tif?(f)|png|p[bgp]m|bmp|x[bp]m|rle|rgb|pcx|fits|pm|?(e)ps)' xv +_comp__init_install_xspec '!*.@(@(?(e)ps|?(E)PS|pdf|PDF)?(.gz|.GZ|.bz2|.BZ2|.Z))' gv ggv kghostview +_comp__init_install_xspec '!*.@(dvi|DVI)?(.@(gz|Z|bz2))' xdvi kdvi +_comp__init_install_xspec '!*.dvi' dvips dviselect dvitype dvipdf advi dvipdfm dvipdfmx +_comp__init_install_xspec '!*.[pf]df' acroread gpdf xpdf +_comp__init_install_xspec '!*.@(?(e)ps|pdf)' kpdf +_comp__init_install_xspec '!*.@(okular|@(?(e|x)ps|?(E|X)PS|[pf]df|[PF]DF|dvi|DVI|cb[rz]|CB[RZ]|djv?(u)|DJV?(U)|dvi|DVI|gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx|GIF|JP?(E)G|MIFF|TIF?(F)|PN[GM]|P[BGP]M|BMP|XPM|ICO|XWD|TGA|PCX|epub|EPUB|odt|ODT|fb?(2)|FB?(2)|mobi|MOBI|g3|G3|chm|CHM|md|markdown)?(.?(gz|GZ|bz2|BZ2|xz|XZ)))' okular +_comp__init_install_xspec '!*.pdf' epdfview pdfunite +_comp__init_install_xspec '!*.@(cb[rz7t]|djv?(u)|?(e)ps|pdf)' zathura +_comp__init_install_xspec '!*.@(?(e)ps|pdf)' ps2pdf ps2pdf12 ps2pdf13 ps2pdf14 ps2pdfwr +_comp__init_install_xspec '!*.texi*' makeinfo texi2html +_comp__init_install_xspec '!*.@(?(la)tex|texi|dtx|ins|ltx|dbj)' tex latex slitex jadetex pdfjadetex pdftex pdflatex texi2dvi xetex xelatex luatex lualatex +_comp__init_install_xspec '!*.mp3' mpg123 mpg321 madplay +_comp__init_install_xspec '!*@(.@(mp?(e)g|MP?(E)G|wm[av]|WM[AV]|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|fxm|FXM|viv|rm|ram|yuv|mov|MOV|qt|QT|web[am]|WEB[AM]|mp[234]|MP[234]|m?(p)4[av]|M?(P)4[AV]|mkv|MKV|og[agmv]|OG[AGMV]|t[ps]|T[PS]|m2t?(s)|M2T?(S)|mts|MTS|wav|WAV|flac|FLAC|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM)|+([0-9]).@(vdr|VDR))?(.@(crdownload|part))' xine aaxine cacaxine fbxine +_comp__init_install_xspec '!*@(.@(mp?(e)g|MP?(E)G|wm[av]|WM[AV]|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|fxm|FXM|viv|rm|ram|yuv|mov|MOV|qt|QT|web[am]|WEB[AM]|mp[234]|MP[234]|m?(p)4[av]|M?(P)4[AV]|mkv|MKV|og[agmv]|OG[AGMV]|opus|OPUS|t[ps]|T[PS]|m2t?(s)|M2T?(S)|mts|MTS|wav|WAV|flac|FLAC|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM|iso|ISO)|+([0-9]).@(vdr|VDR))?(.@(crdownload|part))' kaffeine dragon totem +_comp__init_install_xspec '!*.@(avi|asf|wmv)' aviplay +_comp__init_install_xspec '!*.@(rm?(j)|ra?(m)|smi?(l))' realplay +_comp__init_install_xspec '!*.@(mpg|mpeg|avi|mov|qt)' xanim +_comp__init_install_xspec '!*.@(og[ag]|m3u|flac|spx)' ogg123 +_comp__init_install_xspec '!*.@(mp3|ogg|pls|m3u)' gqmpeg freeamp +_comp__init_install_xspec '!*.fig' xfig +_comp__init_install_xspec '!*.@(mid?(i)|cmf)' playmidi +_comp__init_install_xspec '!*.@(mid?(i)|rmi|rcp|[gr]36|g18|mod|xm|it|x3m|s[3t]m|kar)' timidity +_comp__init_install_xspec '!*.@(669|abc|am[fs]|d[bs]m|dmf|far|it|mdl|m[eo]d|mid?(i)|mt[2m]|oct|okt?(a)|p[st]m|s[3t]m|ult|umx|wav|xm)' modplugplay modplug123 +_comp__init_install_xspec '*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)' vi vim gvim rvim view rview rgvim rgview gview emacs xemacs sxemacs kate kwrite +_comp__init_install_xspec '!*.@(zip|z|gz|tgz)' bzme # konqueror not here on purpose, it's more than a web/html browser -_install_xspec '!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))' netscape mozilla lynx galeon dillo elinks amaya epiphany -_install_xspec '!*.@(sxw|stw|sxg|sgl|doc?([mx])|dot?([mx])|rtf|txt|htm|html|?(f)odt|ott|odm|pdf)' oowriter lowriter -_install_xspec '!*.@(sxi|sti|pps?(x)|ppt?([mx])|pot?([mx])|?(f)odp|otp)' ooimpress loimpress -_install_xspec '!*.@(sxc|stc|xls?([bmx])|xlw|xlt?([mx])|[ct]sv|?(f)ods|ots)' oocalc localc -_install_xspec '!*.@(sxd|std|sda|sdd|?(f)odg|otg)' oodraw lodraw -_install_xspec '!*.@(sxm|smf|mml|odf)' oomath lomath -_install_xspec '!*.odb' oobase lobase -_install_xspec '!*.[rs]pm' rpm2cpio -_install_xspec '!*.aux' bibtex -_install_xspec '!*.po' poedit gtranslator kbabel lokalize -_install_xspec '!*.@([Pp][Rr][Gg]|[Cc][Ll][Pp])' harbour gharbour hbpp -_install_xspec '!*.[Hh][Rr][Bb]' hbrun -_install_xspec '!*.ly' lilypond ly2dvi -_install_xspec '!*.@(dif?(f)|?(d)patch)?(.@([gx]z|bz2|lzma))' cdiff -_install_xspec '!@(*.@(ks|jks|jceks|p12|pfx|bks|ubr|gkr|cer|crt|cert|p7b|pkipath|pem|p10|csr|crl)|cacerts)' portecle -_install_xspec '!*.@(mp[234c]|og[ag]|@(fl|a)ac|m4[abp]|spx|tta|w?(a)v|wma|aif?(f)|asf|ape)' kid3 kid3-qt -unset -f _install_xspec - -# Minimal completion to use as fallback in _completion_loader. -_minimal() -{ - local cur prev words cword split - _init_completion -s || return - $split && return - _filedir +_comp__init_install_xspec '!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))' netscape mozilla lynx galeon dillo elinks amaya epiphany +_comp__init_install_xspec '!*.@(sxw|stw|sxg|sgl|doc?([mx])|dot?([mx])|rtf|txt|htm|html|?(f)odt|ott|odm|pdf)' oowriter lowriter +_comp__init_install_xspec '!*.@(sxi|sti|pps?(x)|ppt?([mx])|pot?([mx])|?(f)odp|otp)' ooimpress loimpress +_comp__init_install_xspec '!*.@(sxc|stc|xls?([bmx])|xlw|xlt?([mx])|[ct]sv|?(f)ods|ots)' oocalc localc +_comp__init_install_xspec '!*.@(sxd|std|sda|sdd|?(f)odg|otg)' oodraw lodraw +_comp__init_install_xspec '!*.@(sxm|smf|mml|odf)' oomath lomath +_comp__init_install_xspec '!*.odb' oobase lobase +_comp__init_install_xspec '!*.[rs]pm' rpm2cpio +_comp__init_install_xspec '!*.aux' bibtex +_comp__init_install_xspec '!*.po' poedit gtranslator kbabel lokalize +_comp__init_install_xspec '!*.@([Pp][Rr][Gg]|[Cc][Ll][Pp])' harbour gharbour hbpp +_comp__init_install_xspec '!*.[Hh][Rr][Bb]' hbrun +_comp__init_install_xspec '!*.ly' lilypond ly2dvi +_comp__init_install_xspec '!*.@(dif?(f)|?(d)patch)?(.@([gx]z|bz2|lzma))' cdiff +_comp__init_install_xspec '!@(*.@(ks|jks|jceks|p12|pfx|bks|ubr|gkr|cer|crt|cert|p7b|pkipath|pem|p10|csr|crl)|cacerts)' portecle +_comp__init_install_xspec '!*.@(mp[234c]|og[ag]|@(fl|a)ac|m4[abp]|spx|tta|w?(a)v|wma|aif?(f)|asf|ape)' kid3 kid3-qt +unset -f _comp__init_install_xspec + +# Minimal completion to use as fallback in _comp_complete_load. +# TODO:API: rename per conventions +_comp_complete_minimal() +{ + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + compopt -o bashdefault -o default } # Complete the empty string to allow completion of '>', '>>', and '<' on < 4.3 # https://lists.gnu.org/archive/html/bug-bash/2012-01/msg00045.html -complete -F _minimal '' +complete -F _comp_complete_minimal '' -__load_completion() +# @since 2.12 +_comp_load() { - local -a dirs=(${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions) - local ifs=$IFS IFS=: dir cmd="${1##*/}" compfile - [[ -n $cmd ]] || return 1 - for dir in ${XDG_DATA_DIRS:-/usr/local/share:/usr/share}; do - dirs+=($dir/bash-completion/completions) + local flag_fallback_default="" IFS=$' \t\n' + local OPTIND=1 OPTARG="" OPTERR=0 opt + while getopts ':D' opt "$@"; do + case $opt in + D) flag_fallback_default=set ;; + *) + echo "bash_completion: $FUNCNAME: usage error" >&2 + return 2 + ;; + esac done - IFS=$ifs + shift "$((OPTIND - 1))" - if [[ $BASH_SOURCE == */* ]]; then - dirs+=("${BASH_SOURCE%/*}/completions") - else - dirs+=(./completions) - fi + local cmd=$1 cmdname=${1##*/} dir compfile + local -a paths + [[ $cmdname ]] || return 1 local backslash= if [[ $cmd == \\* ]]; then - cmd="${cmd:1}" + cmd=${cmd:1} # If we already have a completion for the "real" command, use it $(complete -p "$cmd" 2>/dev/null || echo false) "\\$cmd" && return 0 backslash=\\ fi - for dir in "${dirs[@]}"; do - [[ -d $dir ]] || continue - for compfile in "$cmd" "$cmd.bash" "_$cmd"; do - compfile="$dir/$compfile" - # Avoid trying to source dirs; https://bugzilla.redhat.com/903540 - if [[ -f $compfile ]] && . "$compfile" &>/dev/null; then - [[ $backslash ]] && $(complete -p "$cmd") "\\$cmd" - return 0 + # Resolve absolute path to $cmd + local REPLY pathcmd origcmd=$cmd + if pathcmd=$(type -P "$cmd"); then + _comp_abspath "$pathcmd" + cmd=$REPLY + fi + + local -a dirs=() + + # Lookup order: + # 1) From BASH_COMPLETION_USER_DIR (e.g. ~/.local/share/bash-completion): + # User installed completions. + if [[ ${BASH_COMPLETION_USER_DIR-} ]]; then + _comp_split -F : paths "$BASH_COMPLETION_USER_DIR" && + dirs+=("${paths[@]/%//completions}") + else + dirs=("${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion/completions") + fi + + # 2) From the location of bash_completion: Completions relative to the main + # script. This is primarily for run-in-place-from-git-clone setups, where + # we want to prefer in-tree completions over ones possibly coming with a + # system installed bash-completion. (Due to usual install layouts, this + # often hits the correct completions in system installations, too.) + if [[ $BASH_SOURCE == */* ]]; then + dirs+=("${BASH_SOURCE%/*}/completions") + else + dirs+=(./completions) + fi + + # 3) From bin directories extracted from the specified path to the command, + # the real path to the command, and $PATH + paths=() + [[ $cmd == /* ]] && paths+=("${cmd%/*}") + _comp_realcommand "$cmd" && paths+=("${REPLY%/*}") + _comp_split -aF : paths "$PATH" + for dir in "${paths[@]%/}"; do + [[ $dir == ?*/@(bin|sbin) ]] && + dirs+=("${dir%/*}/share/bash-completion/completions") + done + + # 4) From XDG_DATA_DIRS or system dirs (e.g. /usr/share, /usr/local/share): + # Completions in the system data dirs. + _comp_split -F : paths "${XDG_DATA_DIRS:-/usr/local/share:/usr/share}" && + dirs+=("${paths[@]/%//bash-completion/completions}") + + # Set up default $IFS in case loaded completions depend on it, + # as well as for $compspec invocation below. + local IFS=$' \t\n' + + # Look up and source + shift + local i prefix compspec + for prefix in "" _; do # Regular from all dirs first, then fallbacks + for i in ${!dirs[*]}; do + dir=${dirs[i]} + if [[ ! -d $dir ]]; then + unset -v 'dirs[i]' + continue fi + for compfile in "$prefix$cmdname" "$prefix$cmdname.bash"; do + compfile="$dir/$compfile" + # Avoid trying to source dirs as long as we support bash < 4.3 + # to avoid an fd leak; https://bugzilla.redhat.com/903540 + if [[ -d $compfile ]]; then + # Do not warn with . or .. (especially the former is common) + [[ $compfile == */.?(.) ]] || + echo "bash_completion: $compfile: is a directory" >&2 + elif [[ -e $compfile ]] && . "$compfile" "$cmd" "$@"; then + # At least $cmd is expected to have a completion set when + # we return successfully; see if it already does + if compspec=$(complete -p "$cmd" 2>/dev/null); then + # $cmd is the case in which we do backslash processing + [[ $backslash ]] && eval "$compspec \"\$backslash\$cmd\"" + # If invoked without path, that one should be set, too + # ...but let's not overwrite an existing one, if any + [[ $origcmd != */* ]] && + ! complete -p "$origcmd" &>/dev/null && + eval "$compspec \"\$origcmd\"" + return 0 + fi + # If not, see if we got one for $cmdname + if [[ $cmdname != "$cmd" ]] && compspec=$(complete -p "$cmdname" 2>/dev/null); then + # Use that for $cmd too, if we have a full path to it + [[ $cmd == /* ]] && eval "$compspec \"\$cmd\"" + return 0 + fi + # Nothing expected was set, continue lookup + fi + done done done # Look up simple "xspec" completions - [[ -v _xspecs[$cmd] ]] && - complete -F _filedir_xspec "$cmd" "$backslash$cmd" && return 0 + [[ -v _comp_xspecs[$cmdname] || -v _xspecs[$cmdname] ]] && + complete -F _comp_complete_filedir_xspec "$cmdname" "$backslash$cmdname" && return 0 + + if [[ $flag_fallback_default ]]; then + complete -F _comp_complete_minimal -- "$origcmd" && return 0 + fi return 1 } # set up dynamic completion loading -_completion_loader() +# @since 2.12 +_comp_complete_load() { # $1=_EmptycmD_ already for empty cmds in bash 4.3, set to it for earlier - local cmd="${1:-_EmptycmD_}" + local cmd=${1:-_EmptycmD_} - __load_completion "$cmd" && return 124 - - # Need to define *something*, otherwise there will be no completion at all. - complete -F _minimal -- "$cmd" && return 124 + # Pass -D to define *something*, or otherwise there will be no completion + # at all. + _comp_load -D -- "$cmd" && return 124 } && - complete -D -F _completion_loader + complete -D -F _comp_complete_load # Function for loading and calling functions from dynamically loaded # completion files that may not have been sourced yet. # @param $1 completion file to load function from in case it is missing -# @param $2... function and its arguments -_xfunc() -{ - set -- "$@" - local srcfile=$1 - shift - declare -F $1 &>/dev/null || __load_completion "$srcfile" - "$@" +# @param $2 the xfunc name. When it does not start with `_', +# `_comp_xfunc_${1//[^a-zA-Z0-9_]/_}_$2' is used for the actual name of the +# shell function. +# @param $3... if any, specifies the arguments that are passed to the xfunc. +# @since 2.12 +_comp_xfunc() +{ + local xfunc_name=$2 + [[ $xfunc_name == _* ]] || + xfunc_name=_comp_xfunc_${1//[^a-zA-Z0-9_]/_}_$xfunc_name + declare -F "$xfunc_name" &>/dev/null || _comp_load "$1" + "$xfunc_name" "${@:3}" } +# Call a POSIX-compatible awk. Solaris awk is not POSIX-compliant, but Solaris +# provides a POSIX-compatible version through /usr/xpg4/bin/awk. We switch the +# implementation to /usr/xpg4/bin/awk in Solaris if any. +# @since 2.12 +if [[ $OSTYPE == *solaris* && -x /usr/xpg4/bin/awk ]]; then + _comp_awk() + { + /usr/xpg4/bin/awk "$@" + } +else + _comp_awk() + { + command awk "$@" + } +fi + # source compat completion directory definitions -compat_dir=${BASH_COMPLETION_COMPAT_DIR:-/etc/bash_completion.d} -if [[ -d $compat_dir && -r $compat_dir && -x $compat_dir ]]; then - for i in "$compat_dir"/*; do - [[ ${i##*/} != @($_backup_glob|Makefile*|$_blacklist_glob) && -f \ - $i && -r $i ]] && . "$i" - done +_comp__init_compat_dirs=() +if [[ ${BASH_COMPLETION_COMPAT_DIR-} ]]; then + _comp__init_compat_dirs+=("$BASH_COMPLETION_COMPAT_DIR") +else + _comp__init_compat_dirs+=(/etc/bash_completion.d) + # Similarly as for the "completions" dir, look up from relative to + # bash_completion, primarily for installed-with-prefix and + # run-in-place-from-git-clone setups. Notably we do it after the system + # location here, in order to prefer in-tree variables and functions. + if [[ ${BASH_SOURCE%/*} == */share/bash-completion ]]; then + _comp__init_compat_dir=${BASH_SOURCE%/share/bash-completion/*}/etc/bash_completion.d + elif [[ $BASH_SOURCE == */* ]]; then + _comp__init_compat_dir="${BASH_SOURCE%/*}/bash_completion.d" + else + _comp__init_compat_dir=./bash_completion.d + fi + [[ ${_comp__init_compat_dirs[0]} == "$_comp__init_compat_dir" ]] || + _comp__init_compat_dirs+=("$_comp__init_compat_dir") fi -unset compat_dir i _blacklist_glob +for _comp__init_compat_dir in "${_comp__init_compat_dirs[@]}"; do + [[ -d $_comp__init_compat_dir && -r $_comp__init_compat_dir && -x $_comp__init_compat_dir ]] || continue + for _comp__init_file in "$_comp__init_compat_dir"/*; do + [[ ${_comp__init_file##*/} != @($_comp_backup_glob|Makefile*|${BASH_COMPLETION_COMPAT_IGNORE-}) && + -f $_comp__init_file && -r $_comp__init_file ]] && . "$_comp__init_file" + done +done +unset -v _comp__init_compat_dirs _comp__init_compat_dir _comp__init_file # source user completion file -user_completion=${BASH_COMPLETION_USER_FILE:-~/.bash_completion} -[[ ${BASH_SOURCE[0]} != "$user_completion" && -r $user_completion && -f $user_completion ]] && - . $user_completion -unset user_completion +# +# Remark: We explicitly check that $user_completion is not '/dev/null' since +# /dev/null may be a regular file in broken systems and can contain arbitrary +# garbages of suppressed command outputs. +_comp__init_user_file=${BASH_COMPLETION_USER_FILE:-~/.bash_completion} +[[ $_comp__init_user_file != "${BASH_SOURCE[0]}" && $_comp__init_user_file != /dev/null && -r $_comp__init_user_file && -f $_comp__init_user_file ]] && + . "$_comp__init_user_file" +unset -v _comp__init_user_file unset -f have -unset have +unset -v have -set $BASH_COMPLETION_ORIGINAL_V_VALUE -unset BASH_COMPLETION_ORIGINAL_V_VALUE +set $_comp__init_original_set_v +unset -v _comp__init_original_set_v # ex: filetype=sh diff --git a/bash_completion.d/000_bash_completion_compat.bash b/bash_completion.d/000_bash_completion_compat.bash new file mode 100644 index 0000000..480ffcc --- /dev/null +++ b/bash_completion.d/000_bash_completion_compat.bash @@ -0,0 +1,507 @@ +# Deprecated bash_completion functions and variables -*- shell-script -*- + +_comp_deprecate_func 2.12 _userland _comp_userland +_comp_deprecate_func 2.12 _sysvdirs _comp_sysvdirs +_comp_deprecate_func 2.12 _have _comp_have_command +_comp_deprecate_func 2.12 _rl_enabled _comp_readline_variable_on +_comp_deprecate_func 2.12 _command_offset _comp_command_offset +_comp_deprecate_func 2.12 _command _comp_command +_comp_deprecate_func 2.12 _root_command _comp_root_command +_comp_deprecate_func 2.12 _xfunc _comp_xfunc +_comp_deprecate_func 2.12 _upvars _comp_upvars +_comp_deprecate_func 2.12 _get_comp_words_by_ref _comp_get_words +_comp_deprecate_func 2.12 _known_hosts_real _comp_compgen_known_hosts +_comp_deprecate_func 2.12 __ltrim_colon_completions _comp_ltrim_colon_completions +_comp_deprecate_func 2.12 _variables _comp_compgen_variables +_comp_deprecate_func 2.12 _signals _comp_compgen_signals +_comp_deprecate_func 2.12 _mac_addresses _comp_compgen_mac_addresses +_comp_deprecate_func 2.12 _available_interfaces _comp_compgen_available_interfaces +_comp_deprecate_func 2.12 _configured_interfaces _comp_compgen_configured_interfaces +_comp_deprecate_func 2.12 _ip_addresses _comp_compgen_ip_addresses +_comp_deprecate_func 2.12 _kernel_versions _comp_compgen_kernel_versions +_comp_deprecate_func 2.12 _uids _comp_compgen_uids +_comp_deprecate_func 2.12 _gids _comp_compgen_gids +_comp_deprecate_func 2.12 _xinetd_services _comp_compgen_xinetd_services +_comp_deprecate_func 2.12 _services _comp_compgen_services +_comp_deprecate_func 2.12 _bashcomp_try_faketty _comp_try_faketty +_comp_deprecate_func 2.12 _expand _comp_expand +_comp_deprecate_func 2.12 _pids _comp_compgen_pids +_comp_deprecate_func 2.12 _pgids _comp_compgen_pgids +_comp_deprecate_func 2.12 _pnames _comp_compgen_pnames +_comp_deprecate_func 2.12 _modules _comp_compgen_kernel_modules +_comp_deprecate_func 2.12 _installed_modules _comp_compgen_inserted_kernel_modules +_comp_deprecate_func 2.12 _usergroup _comp_compgen_usergroups +_comp_deprecate_func 2.12 _complete_as_root _comp_as_root +_comp_deprecate_func 2.12 __load_completion _comp_load + +# completers +_comp_deprecate_func 2.12 _service _comp_complete_service +_comp_deprecate_func 2.12 _user_at_host _comp_complete_user_at_host +_comp_deprecate_func 2.12 _known_hosts _comp_complete_known_hosts +_comp_deprecate_func 2.12 _longopt _comp_complete_longopt +_comp_deprecate_func 2.12 _filedir_xspec _comp_complete_filedir_xspec +_comp_deprecate_func 2.12 _minimal _comp_complete_minimal + +_comp_deprecate_var 2.12 COMP_FILEDIR_FALLBACK BASH_COMPLETION_FILEDIR_FALLBACK +_comp_deprecate_var 2.12 COMP_KNOWN_HOSTS_WITH_AVAHI BASH_COMPLETION_KNOWN_HOSTS_WITH_AVAHI +_comp_deprecate_var 2.12 COMP_KNOWN_HOSTS_WITH_HOSTFILE BASH_COMPLETION_KNOWN_HOSTS_WITH_HOSTFILE + +# @deprecated 2.12 Use `_comp_xspecs` +declare -Ag _xspecs + +# Backwards compatibility for compat completions that use have(). +# @deprecated 1.90 should no longer be used; generally not needed with +# dynamically loaded completions, and _comp_have_command is suitable for +# runtime use. +# shellcheck disable=SC2317 # available at load time only +have() +{ + unset -v have + _comp_have_command "$1" && have=yes +} + +# This function shell-quotes the argument +# @deprecated 2.12 Use `_comp_quote` instead. Note that `_comp_quote` stores +# the results in the variable `REPLY` instead of writing them to stdout. +quote() +{ + local quoted=${1//\'/\'\\\'\'} + printf "'%s'" "$quoted" +} + +# @deprecated 2.12 Use `_comp_quote_compgen` +quote_readline() +{ + local REPLY + _comp_quote_compgen "$1" + printf %s "$REPLY" +} + +# This function is the same as `_comp_quote_compgen`, but receives the second +# argument specifying the variable name to store the result. +# @param $1 Argument to quote +# @param $2 Name of variable to return result to +# @deprecated 2.12 Use `_comp_quote_compgen "$1"` instead. Note that +# `_comp_quote_compgen` stores the result in a fixed variable `REPLY`. +_quote_readline_by_ref() +{ + [[ $2 == REPLY ]] || local REPLY + _comp_quote_compgen "$1" + [[ $2 == REPLY ]] || printf -v "$2" %s "$REPLY" +} + +# This function shell-dequotes the argument +# @deprecated 2.12 Use `_comp_dequote' instead. Note that `_comp_dequote` +# stores the results in the array `REPLY` instead of writing them to stdout. +dequote() +{ + local REPLY + _comp_dequote "$1" + local rc=$? + printf %s "$REPLY" + return $rc +} + +# Assign variable one scope above the caller +# Usage: local "$1" && _upvar $1 "value(s)" +# @param $1 Variable name to assign value to +# @param $* Value(s) to assign. If multiple values, an array is +# assigned, otherwise a single value is assigned. +# NOTE: For assigning multiple variables, use '_comp_upvars'. Do NOT +# use multiple '_upvar' calls, since one '_upvar' call might +# reassign a variable to be used by another '_upvar' call. +# @see https://fvue.nl/wiki/Bash:_Passing_variables_by_reference +# @deprecated 2.10 Use `_comp_upvars' instead +_upvar() +{ + echo "bash_completion: $FUNCNAME: deprecated function," \ + "use _comp_upvars instead" >&2 + if unset -v "$1"; then # Unset & validate varname + # shellcheck disable=SC2140 # TODO + if (($# == 2)); then + eval "$1"=\"\$2\" # Return single value + else + eval "$1"=\(\"\$"{@:2}"\"\) # Return array + fi + fi +} + +# Get the word to complete. +# This is nicer than ${COMP_WORDS[COMP_CWORD]}, since it handles cases +# where the user is completing in the middle of a word. +# (For example, if the line is "ls foobar", +# and the cursor is here --------> ^ +# @param $1 string Characters out of $COMP_WORDBREAKS which should NOT be +# considered word breaks. This is useful for things like scp where +# we want to return host:path and not only path, so we would pass the +# colon (:) as $1 in this case. +# @param $2 integer Index number of word to return, negatively offset to the +# current word (default is 0, previous is 1), respecting the exclusions +# given at $1. For example, `_get_cword "=:" 1' returns the word left of +# the current word, respecting the exclusions "=:". +# @deprecated 1.2 Use `_comp_get_words cur' instead +# @see _comp_get_words() +_get_cword() +{ + local LC_CTYPE=C + local cword words + _comp__reassemble_words "${1-}" words cword + + # return previous word offset by $2 + if [[ ${2-} && ${2//[^0-9]/} ]]; then + printf "%s" "${words[cword - $2]}" + elif ((${#words[cword]} == 0 && COMP_POINT == ${#COMP_LINE})); then + : # nothing + else + local i + local cur=$COMP_LINE + local index=$COMP_POINT + for ((i = 0; i <= cword; ++i)); do + # Current word fits in $cur, and $cur doesn't match cword? + while [[ ${#cur} -ge ${#words[i]} && + ${cur:0:${#words[i]}} != "${words[i]}" ]]; do + # Strip first character + cur=${cur:1} + # Decrease cursor position, staying >= 0 + ((index > 0)) && ((index--)) + done + + # Does found word match cword? + if ((i < cword)); then + # No, cword lies further; + local old_size=${#cur} + cur=${cur#"${words[i]}"} + local new_size=${#cur} + ((index -= old_size - new_size)) + fi + done + + if [[ ${words[cword]:0:${#cur}} != "$cur" ]]; then + # We messed up! At least return the whole word so things + # keep working + printf "%s" "${words[cword]}" + else + printf "%s" "${cur:0:index}" + fi + fi +} + +# Get word previous to the current word. +# This is a good alternative to `prev=${COMP_WORDS[COMP_CWORD-1]}' because bash4 +# will properly return the previous word with respect to any given exclusions to +# COMP_WORDBREAKS. +# @deprecated 1.2 Use `_comp_get_words cur prev' instead +# @see _comp_get_words() +# +_get_pword() +{ + if ((COMP_CWORD >= 1)); then + _get_cword "${@-}" 1 + fi +} + +# Get real command. +# @deprecated 2.12 Use `_comp_realcommand` instead. +# Note that `_comp_realcommand` stores the result in the variable `REPLY` +# instead of writing it to stdout. +_realcommand() +{ + local REPLY + _comp_realcommand "$1" + local rc=$? + printf "%s\n" "$REPLY" + return $rc +} + +# Initialize completion and deal with various general things: do file +# and variable completion where appropriate, and adjust prev, words, +# and cword as if no redirections exist so that completions do not +# need to deal with them. Before calling this function, make sure +# cur, prev, words, and cword are local, ditto split if you use -s. +# +# Options: +# -n EXCLUDE Passed to _comp_get_words -n with redirection chars +# -e XSPEC Passed to _filedir as first arg for stderr redirections +# -o XSPEC Passed to _filedir as first arg for other output redirections +# -i XSPEC Passed to _filedir as first arg for stdin redirections +# -s Split long options with _comp__split_longopt, implies -n = +# @var[out] cur Reconstructed current word +# @var[out] prev Reconstructed previous word +# @var[out] words Reconstructed words +# @var[out] cword Current word index in `words` +# @var[out,opt] split When "-s" is specified, `"true"/"false"` is set depending +# on whether the split happened. +# @return True (0) if completion needs further processing, +# False (> 0) no further processing is necessary. +# +# @deprecated 2.12 Use the new interface `_comp_initialize`. The new interface +# supports the same set of options. The new interface receives additional +# arguments $1 (command name), $2 (part of current word before the cursor), and +# $3 (previous word) that are specified to the completion function by Bash. +# When `-s` is specified, instead of variable `split`, the new interface sets +# variable `was_split` to the value "set"/"" when the split happened/not +# happened. +_init_completion() +{ + local was_split + _comp_initialize "$@" + local rc=$? + + # When -s is specified, convert "split={set,}" to "split={true,false}" + local flag OPTIND=1 OPTARG="" OPTERR=0 + while getopts "n:e:o:i:s" flag "$@"; do + case $flag in + [neoi]) ;; + s) + if [[ $was_split ]]; then + split=true + else + split=false + fi + break + ;; + esac + done + + return "$rc" +} + +# @deprecated 2.12 Use the variable `_comp_backup_glob` instead. This is the +# backward-compatibility name. +# shellcheck disable=SC2154 # defined in the main "bash_completion" +_backup_glob=$_comp_backup_glob + +# @deprecated 2.12 use `_comp_cmd_cd` instead. +_cd() +{ + declare -F _comp_cmd_cd &>/dev/null || __load_completion cd + _comp_cmd_cd "$@" +} + +# @deprecated 2.12 Use `_comp_command_offset` instead. Note that the new +# interface `_comp_command_offset` is changed to receive an index in +# `words` instead of that in `COMP_WORDS` as `_command_offset` did. +_command_offset() +{ + # We unset the shell variable `words` locally to tell + # `_comp_command_offset` that the index is intended to be that in + # `COMP_WORDS` instead of `words`. + local words + unset -v words + _comp_command_offset "$@" +} + +# @deprecated 2.12 Use `_comp_compgen -a filedir` +_filedir() +{ + _comp_compgen -a filedir "$@" +} + +# Perform tilde (~) completion +# @return True (0) if completion needs further processing, +# False (1) if tilde is followed by a valid username, completions are +# put in COMPREPLY and no further processing is necessary. +# @deprecated 2.12 Use `_comp_compgen -c CUR tilde [-d]`. Note that the exit +# status of `_comp_compgen_tilde` is flipped. It returns 0 when the tilde +# completions are attempted, or otherwise 1. +_tilde() +{ + ! _comp_compgen -c "$1" tilde +} + +# Helper function for _parse_help and _parse_usage. +# @return True (0) if an option was found, False (> 0) otherwise +# @deprecated 2.12 Use _comp_compgen_help__parse +__parse_options() +{ + local -a _options=() + _comp_compgen_help__parse "$1" + printf '%s\n' "${_options[@]}" +} + +# Parse GNU style help output of the given command. +# @param $1 command; if "-", read from stdin and ignore rest of args +# @param $2 command options (default: --help) +# @deprecated 2.12 Use `_comp_compgen_help`. `COMPREPLY=($(compgen -W +# '$(_parse_help "$1" ...)' -- "$cur"))` can be replaced with +# `_comp_compgen_help [-- ...]`. Also, `var=($(_parse_help "$1" ...))` can +# be replaced with `_comp_compgen -Rv var help [-- ...]`. +_parse_help() +{ + local -a args + if [[ $1 == - ]]; then + args=(-) + else + local REPLY opt IFS=$' \t\n' + _comp_dequote "$1" + _comp_split opt "${2:---help}" + args=(-c "$REPLY" ${opt[@]+"${opt[@]}"}) + fi + local -a REPLY=() + _comp_compgen -Rv REPLY help "${args[@]}" || return 1 + ((${#REPLY[@]})) && printf '%s\n' "${REPLY[@]}" + return 0 +} + +# Parse BSD style usage output (options in brackets) of the given command. +# @param $1 command; if "-", read from stdin and ignore rest of args +# @param $2 command options (default: --usage) +# @deprecated 2.12 Use `_comp_compgen_usage`. `COMPREPLY=($(compgen -W +# '$(_parse_usage "$1" ...)' -- "$cur"))` can be replaced with +# `_comp_compgen_usage [-- ...]`. `var=($(_parse_usage "$1" ...))` can be +# replaced with `_comp_compgen -Rv var usage [-- ...]`. +_parse_usage() +{ + local -a args + if [[ $1 == - ]]; then + args=(-) + else + local REPLY opt IFS=$' \t\n' + _comp_dequote "$1" + _comp_split opt "${2:---usage}" + args=(-c "$REPLY" ${opt[@]+"${opt[@]}"}) + fi + local -a REPLY=() + _comp_compgen -Rv REPLY usage "${args[@]}" || return 1 + ((${#REPLY[@]})) && printf '%s\n' "${REPLY[@]}" + return 0 +} + +# @deprecated 2.12 Use `_comp_get_ncpus`. +_ncpus() +{ + local REPLY + _comp_get_ncpus + printf %s "$REPLY" +} + +# Expand variable starting with tilde (~). +# We want to expand ~foo/... to /home/foo/... to avoid problems when +# word-to-complete starting with a tilde is fed to commands and ending up +# quoted instead of expanded. +# Only the first portion of the variable from the tilde up to the first slash +# (~../) is expanded. The remainder of the variable, containing for example +# a dollar sign variable ($) or asterisk (*) is not expanded. +# +# @deprecated 2.12 Use `_comp_expand_tilde`. The new function receives the +# value instead of a variable name as $1 and always returns the result to the +# variable `REPLY`. +__expand_tilde_by_ref() +{ + [[ ${1+set} ]] || return 0 + [[ $1 == REPLY ]] || local REPLY + _comp_expand_tilde "${!1-}" + # shellcheck disable=SC2059 + [[ $1 == REPLY ]] || printf -v "$1" "$REPLY" +} + +# @deprecated 2.12 Use `_comp_compgen -a cd_devices` +_cd_devices() +{ + _comp_compgen -a cd_devices +} + +# @deprecated 2.12 Use `_comp_compgen -a dvd_devices` +_dvd_devices() +{ + _comp_compgen -a dvd_devices +} + +# @deprecated 2.12 Use `_comp_compgen -a pci_ids` +_pci_ids() +{ + _comp_compgen -a pci_ids +} + +# @deprecated 2.12 Use `_comp_compgen -a usb_ids` +_usb_ids() +{ + _comp_compgen -a usb_ids +} + +# @deprecated 2.12 Use `_comp_compgen -a terms` +_terms() +{ + _comp_compgen -a terms +} + +# @deprecated 2.12 Use `_comp_compgen -c "${prefix:-$cur}" allowed_users` +_allowed_users() +{ + _comp_compgen -c "${1:-$cur}" allowed_users +} + +# @deprecated 2.12 Use `_comp_compgen -c "${prefix:-$cur}" allowed_groups` +_allowed_groups() +{ + _comp_compgen -c "${1:-$cur}" allowed_groups +} + +# @deprecated 2.12 Use `_comp_compgen -a shells` +_shells() +{ + _comp_compgen -a shells +} + +# @deprecated 2.12 Use `_comp_compgen -a fstypes` +_fstypes() +{ + _comp_compgen -a fstypes +} + +# This function returns the first argument, excluding options +# @deprecated 2.12 Use `_comp_get_first_arg`. Note that the new function +# `_comp_get_first_arg` operates on `words` and `cword` instead of `COMP_WORDS` +# and `COMP_CWORD`. The new function considers a command-line argument after +# `--` as an argument. The new function returns the result in variable `REPLY` +# instead of `arg`. +_get_first_arg() +{ + local i + + arg= + for ((i = 1; i < COMP_CWORD; i++)); do + if [[ ${COMP_WORDS[i]} != -* ]]; then + arg=${COMP_WORDS[i]} + break + fi + done +} + +# This function counts the number of args, excluding options +# @param $1 chars Characters out of $COMP_WORDBREAKS which should +# NOT be considered word breaks. See _comp__reassemble_words. +# @param $2 glob Options whose following argument should not be counted +# @param $3 glob Options that should be counted as args +# @var[out] args Return the number of arguments +# @deprecated 2.12 Use `_comp_count_args`. Note that the new function +# `_comp_count_args` returns the result in variable `REPLY` instead of `args`. +# In the new function, `-` is also counted as an argument. The new function +# counts all the arguments after `--`. +# shellcheck disable=SC2178 # assignments are not intended for global "args" +_count_args() +{ + local i cword words + _comp__reassemble_words "${1-}" words cword + + args=1 + for ((i = 1; i < cword; i++)); do + # shellcheck disable=SC2053 + if [[ ${words[i]} != -* && ${words[i - 1]} != ${2-} || + ${words[i]} == ${3-} ]]; then + ((args++)) + fi + done +} + +# @deprecated 2.12 Use `_comp_load -D -- CommandName` to load the completion, +# or use `_comp_complete_load` as a completion function specified to `complete +# -F`. +_completion_loader() +{ + # We call `_comp_complete_load` instead of `_comp_load -D` in case that + # `_completion_loader` is used without an argument or `_completion_loader` + # is specified to `complete -F` by a user. + _comp_complete_load "$@" +} +# ex: filetype=sh diff --git a/bash_completion.sh.in b/bash_completion.sh.in index b2a527e..a3bba6f 100644 --- a/bash_completion.sh.in +++ b/bash_completion.sh.in @@ -1,4 +1,4 @@ -# shellcheck shell=sh disable=SC1091,SC2039,SC2166 +# shellcheck shell=sh disable=SC1091,SC2166,SC2268,SC3028,SC3044,SC3054 # Check for interactive bash and that we haven't already been sourced. if [ "x${BASH_VERSION-}" != x -a "x${PS1-}" != x -a "x${BASH_COMPLETION_VERSINFO-}" = x ]; then diff --git a/completions/.gitignore b/completions/.gitignore index 5edc172..0837060 100644 --- a/completions/.gitignore +++ b/completions/.gitignore @@ -1,235 +1,351 @@ -7za -aclocal-1.1[0123456] -alpine -alternatives -animate -apropos -aptitude-curses -arm-koji -asciidoc.py -autoheader -automake-1.1[0123456] -autossh -autoupdate -bmake -bsdtar -btdownloadcurses.py -btdownloadgui.py -c++ -cc -cdrecord -chrome -chromium -ci -ciptool -civclient -civserver -clzip -co -colormake -compare -compgen -composite -conjure -cowthink -createdb -createuser -dcop -declare -dfutool -display -dpkg-deb -dpkg-query -dpkg-reconfigure -dropdb -dropuser -edquota -etherwake -f77 -f95 -filebucket -freeciv-gtk2 -freeciv-gtk3 -freeciv-sdl -freeciv-xaw -g++ -g++-[5678] -g4 -g77 -g95 -gcc-[5678] -gccgo -gccgo-[5678] -gcj -geoiplookup6 -gfortran -gfortran-[5678] -gkrellm2 -gmake -gmplayer -gnumake -google-chrome -google-chrome-stable -gpc -gpgv2 -gtar -hciattach -hciconfig -hd -host -hping -hping3 -iceweasel -identify -ifdown -ifquery -ifstatus -import -inotifywatch -insmod.static -iperf3 -javac -javadoc -kplayer -l2ping -lbzip2 -ldapadd -ldapcompare -ldapdelete -ldapmodify -ldapmodrdn -ldappasswd -ldapwhoami -links2 -lintian-info -lusermod -lvchange -lvcreate -lvdisplay -lvextend -lvmdiskscan -lvreduce -lvremove -lvrename -lvresize -lvs -lvscan -lz4c -mailsnarf -mdecrypt -mencoder -micropython -mkisofs -mogrify -montage -mozilla-firefox -mplayer2 -msgsnarf -muttng -ncal -pbzip2 -pccardctl -pdlzip -perldoc -phing -pigz -pinfo -ping6 -pkg_deinstall -pkg_info -pkill -plzip -pm-suspend -pm-suspend-hybrid -pmake -postalias -ppc-koji -puppetca -puppetd -puppetdoc -puppetmasterd -puppetqd -puppetrun -pvchange -pvcreate -pvdisplay -pvmove -pvremove -pvs -pvscan -pxz -py.test -py.test-[23] -pydoc3 -pylint-[23] -pytest-[23] -python2 -python2.7 -python3 -python3.[345678] -pypy -pypy3 -pyvenv-3.[45678] -qemu-kvm -qemu-system-i386 -qemu-system-x86_64 -quotacheck -quotaoff -quotaon -ralsh -rcsdiff -rdict -repquota -rfcomm -rlog -rpm2targz -rpm2txz -rpmbuild -rpmbuild-md5 -s390-koji -sbcl-mt -scp -sdptool -setquota -sftp -sidedoor -slogin -smbcacls -smbcquotas -smbget -smbpasswd -smbtar -smbtree -sparc-koji -spovray -star -stream -sudoedit -tightvncviewer -tracepath6 -typeset -vgcfgbackup -vgcfgrestore -vgchange -vgck -vgconvert -vgcreate -vgdisplay -vgexport -vgextend -vgimport -vgmerge -vgmknodes -vgreduce -vgremove -vgrename -vgs -vgscan -vgsplit -vigr -whatis -wine-development -wine-stable -xpovray -xvnc4viewer -ypcat +/7za +/7zr +/7zz +/7zzs +/aclocal-1.1[0123456] +/_airflow +/_allero +/alpine +/alternatives +/animate +/_ansible +/_ansible-config +/_ansible-console +/_ansible-doc +/_ansible-galaxy +/_ansible-inventory +/_ansible-playbook +/_ansible-pull +/_ansible-vault +/apropos +/aptitude-curses +/_arduino-cli +/arm-koji +/asciidoc.py +/autoheader +/automake-1.1[0123456] +/autossh +/autoupdate +/avahi-browse-domains +/b2sum +/_black +/_blackd +/bmake +/bsdtar +/btdownloadcurses.py +/btdownloadgui.py +/_buf +/c++ +/cc +/cdrecord +/_chezmoi +/chrome +/chromium +/ci +/_cilium +/ciptool +/civclient +/civserver +/_cloudquery +/clzip +/co +/colormake +/compare +/compgen +/composite +/_conda +/conjure +/_constellation +/_consul +/cowthink +/_crc +/createdb +/createuser +/_cz +/_datree +/dcop +/_deno +/dfutool +/_diesel +/display +/_docker +/dpkg-deb +/dpkg-query +/dpkg-reconfigure +/_dprint +/dropdb +/dropuser +/edquota +/etherwake +/f77 +/f95 +/filebucket +/firefox-esr +/_flask +/freeciv-gtk2 +/freeciv-gtk3 +/freeciv-sdl +/freeciv-xaw +/g++ +/g++-[5678] +/g4 +/g77 +/g95 +/_gaiad +/_gardenctl +/gcc-[5678] +/gccgo +/gccgo-[5678] +/gcj +/geoiplookup6 +/gfortran +/gfortran-[5678] +/_gh-label +/_git-bump +/gkrellm2 +/gmake +/gmplayer +/gnumake +/_go-licenses +/google-chrome +/google-chrome-stable +/_gopherjs +/_goreleaser +/gpc +/gpgv2 +/gssdp-device-sniffer +/gtar +/hciattach +/hciconfig +/hd +/_helm +/host +/hping +/hping3 +/_httpx +/_hugo +/iceweasel +/identify +/ifdown +/ifquery +/ifstatus +/_ignite +/import +/_infracost +/inotifywatch +/insmod.static +/iperf3 +/_istioctl +/javac +/javadoc +/_k3s +/_kn +/_kool +/kplayer +/_kratos +/_kubeadm +/_kubectl +/_kubescape +/l2ping +/lbzip2 +/ldapadd +/ldapcompare +/ldapdelete +/ldapmodify +/ldapmodrdn +/ldappasswd +/ldapwhoami +/_lefthook +/_linkerd +/links2 +/lintian-info +/lua5[0-4] +/lua5.[0-4] +/luac5[0-4] +/luac5.[0-4] +/lusermod +/lvchange +/lvcreate +/lvdisplay +/lvextend +/lvmdiskscan +/lvreduce +/lvremove +/lvrename +/lvresize +/lvs +/lvscan +/lz4c +/mailsnarf +/_mattermost +/md5sum +/mdecrypt +/mencoder +/_metalctl +/micropython +/_minikube +/_mise +/mkisofs +/_mmctl +/mogrify +/_moldy +/montage +/mozilla-firefox +/mplayer2 +/msgsnarf +/_multi-gitter +/muttng +/ncal +/neomutt +/_nfpm +/_nomad +/_npm +/_oc +/_okteto +/_op +/_ory +/_packer +/pbzip2 +/pccardctl +/pdlzip +/perldoc +/phing +/pigz +/pinfo +/ping4 +/ping6 +/_pip3 +/pkg_deinstall +/pkg_info +/pkgconf +/pkill +/plzip +/pm-suspend +/pm-suspend-hybrid +/pmake +/_polygon-edge +/postalias +/ppc-koji +/_pulumi +/puppetca +/puppetd +/puppetdoc +/puppetmasterd +/puppetqd +/puppetrun +/pushd +/pvchange +/pvcreate +/pvdisplay +/pvmove +/pvremove +/pvs +/pvscan +/_px +/pxz +/py.test +/py.test-[23] +/pydoc3 +/pylint-[23] +/pytest-[23] +/python2 +/python2.7 +/python3 +/python3.[3456789] +/python3.1[012] +/pypy +/pypy3 +/pyston +/pyston3 +/pyvenv-3.[456789] +/pyvenv-3.1[012] +/qemu-kvm +/qemu-system-i386 +/qemu-system-x86_64 +/_qrpc +/quotacheck +/quotaoff +/quotaon +/ralsh +/_random +/_rclone +/rcsdiff +/rdict +/repquota +/rfcomm +/rlog +/rpm2targz +/rpm2txz +/rpmbuild +/rpmbuild-md5 +/s390-koji +/sbcl-mt +/scp +/sdptool +/setquota +/sftp +/shasum +/sha1sum +/sha224sum +/sha384sum +/sha512sum +/sidedoor +/_skaffold +/slogin +/smbcacls +/smbcquotas +/smbget +/smbpasswd +/smbtar +/smbtree +/sparc-koji +/spovray +/_sshi +/_ssh-inscribe +/star +/_starship +/stream +/sudoedit +/_tanzu +/_tanzu-core +/_tendermint +/_terraform +/_tkn +/_tkn-pac +/tightvncviewer +/tracepath6 +/_trivy +/typeset +/_upctl +/_vacuum +/vgcfgbackup +/vgcfgrestore +/vgchange +/vgck +/vgconvert +/vgcreate +/vgdisplay +/vgexport +/vgextend +/vgimport +/vgmerge +/vgmknodes +/vgreduce +/vgremove +/vgrename +/vgs +/vgscan +/vgsplit +/vigr +/_virtctl +/_watchexec +/whatis +/wine-development +/wine-stable +/wine64 +/wine64-development +/wine64-stable +/xpovray +/xvnc4viewer +/ypcat +/_zitadel diff --git a/completions/2to3 b/completions/2to3 index 7c5b330..0a60e1f 100644 --- a/completions/2to3 +++ b/completions/2to3 @@ -1,39 +1,42 @@ # bash completion for 2to3 -*- shell-script -*- -_2to3() +_comp_cmd_2to3() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -h | --help | --add-suffix) return ;; -f | --fix | -x | --nofix) - COMPREPLY=($(compgen -W \ - "$($1 --list-fixes 2>/dev/null | command sed -e 1d)" -- "$cur")) + _comp_compgen_split -- "$( + "$1" --list-fixes 2>/dev/null | command sed -e 1d + )" return ;; -j | --processes) - COMPREPLY=($(compgen -W "{1..$(_ncpus)}" -- "$cur")) + local REPLY + _comp_get_ncpus + _comp_compgen -- -W "{1..$REPLY}" return ;; -o | --output-dir) - _filedir -d + _comp_compgen_filedir -d return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir py + _comp_compgen_filedir py } && - complete -F _2to3 2to3 + complete -F _comp_cmd_2to3 2to3 # ex: filetype=sh diff --git a/completions/7z b/completions/7z index a8acbc5..027f84b 100644 --- a/completions/7z +++ b/completions/7z @@ -1,21 +1,21 @@ # 7z(1) completion -*- shell-script -*- -_7z() +_comp_cmd_7z() { - local cur prev words cword - _init_completion -n = || return + local cur prev words cword comp_args + _comp_initialize -n = -- "$@" || return if ((cword == 1)); then - COMPREPLY=($(compgen -W 'a b d e l t u x' -- "$cur")) + _comp_compgen -- -W 'a b d e h i l rn t u x' return fi local mode - [[ ${words[1]} == [adu] ]] && mode=w || mode=r + [[ ${words[1]} == @(a|d|rn|u) ]] && mode=w || mode=r case $cur in -ao*) - COMPREPLY=($(compgen -P${cur:0:3} -W 'a s t u' -- "${cur:3}")) + _comp_compgen -c "${cur:3}" -- -P"${cur:0:3}" -W 'a s t u' return ;; -?(a)[ix]*) @@ -26,59 +26,48 @@ _7z() opt=${cur:0:2} cur=${cur:2} fi if [[ $cur != *[@\!]* ]]; then - COMPREPLY=($(compgen -P$opt -W '@ ! r@ r-@ r0@ r! r-! r0!' \ - -- "$cur")) + _comp_compgen -- -P"$opt" -W '@ ! r@ r-@ r0@ r! r-! r0!' elif [[ $cur == ?(r@(-|0|))@* ]]; then - local IFS=$' \t\n' reset=$(shopt -po noglob) - set -o noglob - COMPREPLY=($(compgen -P"${opt}${cur%%@*}@" -f -- "${cur#*@}")) - $reset + _comp_compgen -c "${cur#*@}" -- -P"${opt}${cur%%@*}@" -f compopt -o filenames fi return ;; -mhe=* | -mhc=* | -ms=* | -mt=*) - COMPREPLY=($(compgen -W 'on off' -- "${cur#*=}")) + _comp_compgen -c "${cur#*=}" -- -W 'on off' return ;; -mx=*) - COMPREPLY=($(compgen -W '0 1 3 5 7 9' -- "${cur#*=}")) + _comp_compgen -c "${cur#*=}" -- -W '0 1 3 5 7 9' return ;; -o* | -w?*) - local reset=$(shopt -po noglob) - set -o noglob compopt -o filenames - local ifs=$IFS IFS=$'\n' - COMPREPLY=($(compgen -d -P${cur:0:2} -S/ -- "${cur:2}")) - IFS=$ifs - $reset + _comp_compgen -c "${cur:2}" -- -d -P"${cur:0:2}" -S/ compopt -o nospace return ;; -r?*) - COMPREPLY=($(compgen -P${cur:0:2} -W '- 0' -- "${cur:2}")) + _comp_compgen -c "${cur:2}" -- -P"${cur:0:2}" -W '- 0' return ;; -scs*) - COMPREPLY=($(compgen -P${cur:0:4} -W 'UTF-8 WIN DOS' \ - -- "${cur:4}")) + _comp_compgen -c "${cur:4}" -- -P"${cur:0:4}" -W 'UTF-8 WIN DOS' return ;; -ssc?*) - COMPREPLY=($(compgen -P${cur:0:4} -W '-' -- "${cur:4}")) + _comp_compgen -c "${cur:4}" -- -P"${cur:0:4}" -W '-' return ;; -t*) if [[ $mode == w ]]; then - COMPREPLY=($(compgen -P${cur:0:2} -W '7z bzip2 gzip swfc - tar wim xz zip' -- "${cur:2}")) + _comp_compgen -c "${cur:2}" -- -P"${cur:0:2}" -W '7z bzip2 gzip + swfc tar wim xz zip' else - COMPREPLY=($(compgen -P${cur:0:2} -W '7z apm arj bzip2 cab - chm cpio cramfs deb dmg elf fat flv gzip hfs iso lzh lzma - lzma86 macho mbr mslz mub nsis ntfs pe ppmd rar rpm - squashfs swf swfc tar udf vhd wim xar xz z zip' \ - -- "${cur:2}")) + _comp_compgen -c "${cur:2}" -- -P"${cur:0:2}" -W '7z apm arj + bzip2 cab chm cpio cramfs deb dmg elf fat flv gzip hfs iso + lzh lzma lzma86 macho mbr mslz mub nsis ntfs pe ppmd rar + rpm squashfs swf swfc tar udf vhd wim xar xz z zip' fi return ;; @@ -88,18 +77,17 @@ _7z() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-ai -an -ao -ax -bd -i -m{x,s,f,he,hc,mt}= - -o -p -r -scs -sfx -si -slp -slt -so -ssc -t -u -v -w -x -y' \ - -- "$cur")) + _comp_compgen -- -W '-ai -an -ao -ax -bd -i -m{x,s,f,he,hc,mt}= + -o -p -r -scs -sfx -si -slp -slt -so -ssc -t -u -v -w -x -y' [[ ${COMPREPLY-} == -@(an|bd|sfx|si|slt|so|ssc|[rwy]) ]] || compopt -o nospace return fi - local args - _count_args = - if ((args == 2)); then - _filedir_xspec unzip + local REPLY + _comp_count_args + if ((REPLY == 2)); then + _comp_compgen_filedir_xspec unzip # TODO: parsing 7z i output? # - how to figure out if the format is input or output? # - find string Formats:, read until next empty line @@ -109,20 +97,20 @@ _7z() # - terminate on token containing anything [^a-z0-9] # (assumption: extensions are all lowercase) [[ $mode == w ]] && - _filedir '@(7z|bz2|swf|?(g)tar|?(t)[bglx]z|tb?(z)2|wim)' || - _filedir '@(7z|arj|bz2|cab|chm|cpio|deb|dmg|flv|gem|img|iso|lz[ah]|lzma?(86)|msi|pmd|[rx]ar|rpm|sw[fm]|?(g)tar|taz|?(t)[bglx]z|tb?(z)2|vhd|wim|Z)' + _comp_compgen -a filedir '@(7z|bz2|swf|?(g)tar|?(t)[bglx]z|tb?(z)2|wim)' || + _comp_compgen -a filedir '@(7z?(.001)|arj|bz2|cab|cb7|chm|cpio|deb|dmg|flv|gem|img|iso|lz[ah]|lzma?(86)|msi|pmd|[rx]ar|rpm|sw[fm]|?(g)tar|taz|?(t)[bglx]z|tb?(z)2|vhd|wim|Z)' else if [[ ${words[1]} == d ]]; then - local IFS=$'\n' - COMPREPLY=($(compgen -W "$(printf '%s\n' "$($1 l ${words[2]} \ - -slt 2>/dev/null | command sed -n '/^Path =/s/^Path = \(.*\)$/\1/p' \ - 2>/dev/null | tail -n+2)")" -- "$cur")) + _comp_compgen_split -l -- "$( + "$1" l "${words[2]}" -slt 2>/dev/null | command sed -n \ + '/^Path =/s/^Path = \(.*\)$/\1/p' 2>/dev/null | tail -n+2 + )" compopt -o filenames else - _filedir + _comp_compgen_filedir fi fi } && - complete -F _7z 7z 7za + complete -F _comp_cmd_7z 7z 7za 7zr 7zz 7zzs # ex: filetype=sh diff --git a/completions/Makefile.am b/completions/Makefile.am index 723b42f..8f11291 100644 --- a/completions/Makefile.am +++ b/completions/Makefile.am @@ -14,6 +14,7 @@ bashcomp_DATA = 2to3 \ apt-build \ apt-cache \ apt-get \ + apt-mark \ aptitude \ arch \ arp \ @@ -26,6 +27,7 @@ bashcomp_DATA = 2to3 \ autoreconf \ autorpm \ autoscan \ + avahi-browse \ avctrl \ badblocks \ bind \ @@ -36,10 +38,12 @@ bashcomp_DATA = 2to3 \ bzip2 \ _cal \ cancel \ + _cargo \ cardctl \ carton \ ccache \ ccze \ + cd \ cfagent \ cfrun \ chage \ @@ -75,6 +79,7 @@ bashcomp_DATA = 2to3 \ cvs \ cvsps \ dd \ + declare \ deja-dup \ desktop-file-validate \ dhclient \ @@ -113,11 +118,13 @@ bashcomp_DATA = 2to3 \ fio \ firefox \ flake8 \ + _flamegraph \ freebsd-update \ freeciv \ freeciv-server \ function \ fusermount \ + _gaiacli \ gcc \ gcl \ gdb \ @@ -127,12 +134,14 @@ bashcomp_DATA = 2to3 \ geoiplookup \ getconf \ getent \ + _gh \ gkrellm \ gm \ gnatmake \ gnokii \ gnome-mplayer \ gnome-screenshot \ + _golangci-lint \ gpasswd \ gpg \ gpg2 \ @@ -145,10 +154,13 @@ bashcomp_DATA = 2to3 \ groupmod \ growisofs \ grpck \ + _gsctl \ gssdp-discover \ gzip \ + hash \ hcitool \ hddtemp \ + help \ _hexdump \ hid2hci \ hostname \ @@ -196,13 +208,16 @@ bashcomp_DATA = 2to3 \ jshint \ json_xs \ jsonschema \ + _jungle \ k3b \ kcov \ + _keyring \ kill \ killall \ kldload \ kldunload \ koji \ + _kontena \ ktutil \ larch \ lastlog \ @@ -243,6 +258,7 @@ bashcomp_DATA = 2to3 \ mc \ mcrypt \ mdadm \ + _mdbook \ mdtool \ medusa \ mii-diag \ @@ -280,12 +296,13 @@ bashcomp_DATA = 2to3 \ ngrep \ nmap \ _nmcli \ + _nox \ nproc \ nslookup \ nsupdate \ ntpdate \ + _nvm \ oggdec \ - op \ openssl \ opera \ optipng \ @@ -293,6 +310,7 @@ bashcomp_DATA = 2to3 \ pack200 \ passwd \ patch \ + pdftoppm \ pdftotext \ perl \ perlcritic \ @@ -301,6 +319,8 @@ bashcomp_DATA = 2to3 \ pidof \ pine \ ping \ + _pip \ + _pipenv \ pkg-config \ pkg-get \ pkg_delete \ @@ -325,6 +345,7 @@ bashcomp_DATA = 2to3 \ prelink \ printenv \ protoc \ + ps \ psql \ puppet \ pv \ @@ -367,16 +388,19 @@ bashcomp_DATA = 2to3 \ rrdtool \ rsync \ _rtcwake \ + _ruff \ _runuser \ + _rustup \ sbcl \ sbopkg \ screen \ scrub \ secret-tool \ sh \ + sha256sum \ shellcheck \ sitecopy \ - slackpkg \ + _slackpkg \ slapt-get \ slapt-src \ smartctl \ @@ -388,6 +412,7 @@ bashcomp_DATA = 2to3 \ ssh-add \ ssh-copy-id \ ssh-keygen \ + ssh-keyscan \ sshfs \ sshmitm \ sshow \ @@ -410,8 +435,11 @@ bashcomp_DATA = 2to3 \ tcpnice \ timeout \ tipc \ + _tokio-console \ tox \ tracepath \ + tree \ + truncate \ tshark \ tsig-keygen \ tune2fs \ @@ -431,6 +459,7 @@ bashcomp_DATA = 2to3 \ userdel \ usermod \ valgrind \ + _vault \ vipw \ vmstat \ vncviewer \ @@ -448,6 +477,7 @@ bashcomp_DATA = 2to3 \ wvdial \ xdg-mime \ xdg-settings \ + xev \ xfreerdp \ xgamma \ xhost \ @@ -464,6 +494,7 @@ bashcomp_DATA = 2to3 \ xz \ xzdec \ ypmatch \ + _yq \ _yum \ yum-arch \ zopfli \ @@ -473,6 +504,9 @@ EXTRA_DIST = $(bashcomp_DATA) CLEANFILES = \ 7za \ + 7zr \ + 7zz \ + 7zzs \ aclocal-1.10 \ aclocal-1.11 \ aclocal-1.12 \ @@ -480,11 +514,23 @@ CLEANFILES = \ aclocal-1.14 \ aclocal-1.15 \ aclocal-1.16 \ + _airflow \ + _allero \ alpine \ alternatives \ animate \ + _ansible \ + _ansible-config \ + _ansible-console \ + _ansible-doc \ + _ansible-galaxy \ + _ansible-inventory \ + _ansible-playbook \ + _ansible-pull \ + _ansible-vault \ apropos \ aptitude-curses \ + _arduino-cli \ arm-koji \ asciidoc.py \ autoheader \ @@ -497,36 +543,52 @@ CLEANFILES = \ automake-1.16 \ autossh \ autoupdate \ + avahi-browse-domains \ + _black \ + _blackd \ bmake \ bsdtar \ btdownloadcurses.py \ btdownloadgui.py \ + _buf \ c++ \ cc \ cdrecord \ + _chezmoi \ chrome \ chromium \ ci \ + _cilium \ ciptool \ civclient \ civserver \ + _cloudquery \ clzip \ co \ colormake \ compare \ compgen \ composite \ + _conda \ conjure \ + _constellation \ + _consul \ cowthink \ + _crc \ createdb \ createuser \ + _cz \ + _datree \ dcop \ - declare \ + _deno \ dfutool \ + _diesel \ display \ + _docker \ dpkg-deb \ dpkg-query \ dpkg-reconfigure \ + _dprint \ dropdb \ dropuser \ edquota \ @@ -534,6 +596,8 @@ CLEANFILES = \ f77 \ f95 \ filebucket \ + firefox-esr \ + _flask \ freeciv-gtk2 \ freeciv-gtk3 \ freeciv-sdl \ @@ -546,6 +610,8 @@ CLEANFILES = \ g4 \ g77 \ g95 \ + _gaiad \ + _gardenctl \ gcc-5 \ gcc-6 \ gcc-7 \ @@ -562,33 +628,52 @@ CLEANFILES = \ gfortran-6 \ gfortran-7 \ gfortran-8 \ + _gh-label \ + _git-bump \ gkrellm2 \ gmake \ gmplayer \ gnumake \ + _go-licenses \ google-chrome \ google-chrome-stable \ + _gopherjs \ + _goreleaser \ gpc \ gpgv2 \ + gssdp-device-sniffer \ gtar \ hciattach \ hciconfig \ hd \ + _helm \ host \ hping \ hping3 \ + _httpx \ + _hugo \ iceweasel \ identify \ ifdown \ ifquery \ ifstatus \ + _ignite \ import \ + _infracost \ inotifywatch \ insmod.static \ iperf3 \ + _istioctl \ javac \ javadoc \ + _k3s \ + _kn \ + _kool \ kplayer \ + _kratos \ + _kubeadm \ + _kubectl \ + _kubescape \ l2ping \ lbzip2 \ ldapadd \ @@ -598,8 +683,30 @@ CLEANFILES = \ ldapmodrdn \ ldappasswd \ ldapwhoami \ + _lefthook \ + _linkerd \ links2 \ lintian-info \ + lua50 \ + lua5.0 \ + lua51 \ + lua5.1 \ + lua52 \ + lua5.2 \ + lua53 \ + lua5.3 \ + lua54 \ + lua5.4 \ + luac50 \ + luac5.0 \ + luac51 \ + luac5.1 \ + luac52 \ + luac5.2 \ + luac53 \ + luac5.3 \ + luac54 \ + luac5.4 \ lusermod \ lvchange \ lvcreate \ @@ -614,17 +721,34 @@ CLEANFILES = \ lvscan \ lz4c \ mailsnarf \ + _mattermost \ + md5sum \ mdecrypt \ mencoder \ + _metalctl \ micropython \ + _minikube \ + _mise \ mkisofs \ + _mmctl \ mogrify \ + _moldy \ montage \ mozilla-firefox \ mplayer2 \ msgsnarf \ + _multi-gitter \ muttng \ ncal \ + neomutt \ + _nfpm \ + _nomad \ + _npm \ + _oc \ + _okteto \ + _op \ + _ory \ + _packer \ pbzip2 \ pccardctl \ pdlzip \ @@ -632,22 +756,28 @@ CLEANFILES = \ phing \ pigz \ pinfo \ + ping4 \ ping6 \ + _pip3 \ pkg_deinstall \ pkg_info \ + pkgconf \ pkill \ plzip \ pm-suspend \ pm-suspend-hybrid \ pmake \ + _polygon-edge \ postalias \ ppc-koji \ + _pulumi \ puppetca \ puppetd \ puppetdoc \ puppetmasterd \ puppetqd \ puppetrun \ + pushd \ pvchange \ pvcreate \ pvdisplay \ @@ -655,6 +785,7 @@ CLEANFILES = \ pvremove \ pvs \ pvscan \ + _px \ pxz \ py.test \ py.test-2 \ @@ -664,6 +795,8 @@ CLEANFILES = \ pylint-3 \ pypy \ pypy3 \ + pyston \ + pyston3 \ pytest-2 \ pytest-3 \ python2 \ @@ -675,18 +808,29 @@ CLEANFILES = \ python3.6 \ python3.7 \ python3.8 \ + python3.9 \ + python3.10 \ + python3.11 \ + python3.12 \ pyvenv-3.4 \ pyvenv-3.5 \ pyvenv-3.6 \ pyvenv-3.7 \ pyvenv-3.8 \ + pyvenv-3.9 \ + pyvenv-3.10 \ + pyvenv-3.11 \ + pyvenv-3.12 \ qemu-kvm \ qemu-system-i386 \ qemu-system-x86_64 \ + _qrpc \ quotacheck \ quotaoff \ quotaon \ ralsh \ + _random \ + _rclone \ rcsdiff \ rdict \ repquota \ @@ -702,7 +846,13 @@ CLEANFILES = \ sdptool \ setquota \ sftp \ + shasum \ + sha1sum \ + sha224sum \ + sha384sum \ + sha512sum \ sidedoor \ + _skaffold \ slogin \ smbcacls \ smbcquotas \ @@ -712,12 +862,24 @@ CLEANFILES = \ smbtree \ sparc-koji \ spovray \ + _sshi \ + _ssh-inscribe \ star \ + _starship \ stream \ sudoedit \ + _tanzu \ + _tanzu-core \ + _tendermint \ + _terraform \ + _tkn \ + _tkn-pac \ tightvncviewer \ tracepath6 \ + _trivy \ typeset \ + _upctl \ + _vacuum \ vgcfgbackup \ vgcfgrestore \ vgchange \ @@ -737,14 +899,25 @@ CLEANFILES = \ vgscan \ vgsplit \ vigr \ + _virtctl \ + _watchexec \ whatis \ + wine-development \ + wine-stable \ + wine64 \ + wine64-development \ + wine64-stable \ xpovray \ xvnc4viewer \ - ypcat + ypcat \ + _zitadel symlinks: $(DATA) $(ss) 7z \ - 7za + 7za \ + 7zr \ + 7zz \ + 7zzs $(ss) aclocal \ aclocal-1.10 aclocal-1.11 aclocal-1.12 aclocal-1.13 \ aclocal-1.14 aclocal-1.15 aclocal-1.16 @@ -761,6 +934,8 @@ symlinks: $(DATA) autoheader $(ss) autoscan \ autoupdate + $(ss) avahi-browse \ + avahi-browse-domains $(ss) btdownloadheadless.py \ btdownloadcurses.py btdownloadgui.py $(ss) bzip2 \ @@ -769,6 +944,8 @@ symlinks: $(DATA) ncal $(ss) cardctl \ pccardctl + $(ss) cd \ + pushd $(ss) chromium-browser \ chrome chromium google-chrome google-chrome-stable $(ss) complete \ @@ -778,6 +955,8 @@ symlinks: $(DATA) mogrify montage stream $(ss) cowsay \ cowthink + $(ss) declare \ + typeset $(ss) dict \ rdict $(ss) dpkg \ @@ -787,13 +966,15 @@ symlinks: $(DATA) $(ss) filesnarf \ mailsnarf msgsnarf $(ss) firefox \ - iceweasel mozilla-firefox + firefox-esr iceweasel mozilla-firefox + $(ss) _flamegraph \ + _watchexec $(ss) freeciv \ civclient freeciv-gtk2 freeciv-gtk3 freeciv-sdl freeciv-xaw $(ss) freeciv-server \ civserver - $(ss) function \ - declare typeset + $(ss) _gaiacli \ + _gaiad _npm _tendermint $(ss) gcc \ c++ cc f77 f95 g++ g++-5 g++-6 g++-7 g++-8 g77 g95 gcc-5 \ gcc-6 gcc-7 gcc-8 gccgo gccgo-5 gccgo-6 gccgo-7 gccgo-8 gcj \ @@ -802,10 +983,74 @@ symlinks: $(DATA) mkisofs $(ss) geoiplookup \ geoiplookup6 + $(ss) _gh \ + _infracost $(ss) gkrellm \ gkrellm2 + $(ss) _golangci-lint \ + _allero \ + _arduino-cli \ + _buf \ + _chezmoi \ + _cilium \ + _cloudquery \ + _constellation \ + _crc \ + _datree \ + _docker \ + _gardenctl \ + _gh-label \ + _git-bump \ + _go-licenses \ + _gopherjs \ + _goreleaser \ + _helm \ + _hugo \ + _ignite \ + _istioctl \ + _k3s \ + _kn \ + _kool \ + _kratos \ + _kubeadm \ + _kubectl \ + _kubescape \ + _lefthook \ + _linkerd \ + _mattermost \ + _metalctl \ + _minikube \ + _mise \ + _mmctl \ + _moldy \ + _multi-gitter \ + _nfpm \ + _oc \ + _okteto \ + _op \ + _ory \ + _polygon-edge \ + _pulumi \ + _px \ + _qrpc \ + _random \ + _rclone \ + _skaffold \ + _sshi \ + _ssh-inscribe \ + _tanzu \ + _tanzu-core \ + _tkn \ + _tkn-pac \ + _trivy \ + _upctl \ + _vacuum \ + _virtctl \ + _zitadel $(ss) gpgv \ gpgv2 + $(ss) gssdp-discover \ + gssdp-device-sniffer $(ss) gzip \ pigz $(ss) hcitool \ @@ -835,6 +1080,12 @@ symlinks: $(DATA) links2 $(ss) lintian \ lintian-info + $(ss) lua \ + lua50 lua5.0 lua51 lua5.1 lua52 lua5.2 lua53 lua5.3 lua54 \ + lua5.4 + $(ss) luac \ + luac50 luac5.0 luac51 luac5.1 luac52 luac5.2 luac53 luac5.3 \ + luac54 luac5.4 $(ss) luseradd \ lusermod $(ss) lvm \ @@ -854,10 +1105,25 @@ symlinks: $(DATA) apropos whatis $(ss) mcrypt \ mdecrypt + $(ss) _mdbook \ + _deno _diesel _dprint _starship $(ss) mplayer \ gmplayer kplayer mencoder mplayer2 $(ss) mutt \ - muttng + muttng neomutt + $(ss) _nox \ + _airflow \ + _ansible \ + _ansible-config \ + _ansible-console \ + _ansible-doc \ + _ansible-galaxy \ + _ansible-inventory \ + _ansible-playbook \ + _ansible-pull \ + _ansible-vault \ + _conda \ + _cz $(ss) nslookup \ host $(ss) p4 \ @@ -867,7 +1133,13 @@ symlinks: $(DATA) $(ss) pine \ alpine $(ss) ping \ - ping6 + ping4 ping6 + $(ss) _pip \ + _pip3 + $(ss) _pipenv \ + _black _blackd _flask _httpx + $(ss) pkg-config \ + pkgconf $(ss) pkg_delete \ pkg_deinstall pkg_info $(ss) pgrep \ @@ -890,9 +1162,12 @@ symlinks: $(DATA) $(ss) pylint \ pylint-2 pylint-3 $(ss) python \ - micropython pypy pypy3 python2 python2.7 python3 python3.3 python3.4 python3.5 python3.6 python3.7 python3.8 + micropython pypy pypy3 pyston pyston3 python2 python2.7 \ + python3 python3.3 python3.4 python3.5 python3.6 python3.7 \ + python3.8 python3.9 python3.10 python3.11 python3.12 $(ss) pyvenv \ - pyvenv-3.4 pyvenv-3.5 pyvenv-3.6 pyvenv-3.7 pyvenv-3.8 + pyvenv-3.4 pyvenv-3.5 pyvenv-3.6 pyvenv-3.7 pyvenv-3.8 \ + pyvenv-3.9 pyvenv-3.10 pyvenv-3.11 pyvenv-3.12 $(ss) qdbus \ dcop $(ss) qemu \ @@ -909,6 +1184,8 @@ symlinks: $(DATA) smbcacls smbcquotas smbget smbpasswd smbtar smbtree $(ss) sbcl \ sbcl-mt + $(ss) sha256sum \ + b2sum md5sum shasum sha1sum sha224sum sha384sum sha512sum $(ss) ssh \ autossh scp sftp sidedoor slogin $(ss) sudo \ @@ -919,12 +1196,15 @@ symlinks: $(DATA) tracepath6 $(ss) update-alternatives \ alternatives + $(ss) _vault \ + _consul _nomad _packer _terraform $(ss) vipw \ vigr $(ss) vncviewer \ tightvncviewer xvnc4viewer $(ss) wine \ - wine-development wine-stable + wine-development wine-stable \ + wine64 wine64-development wine64-stable $(ss) wodim \ cdrecord $(ss) xz \ @@ -942,9 +1222,9 @@ install-data-hook: ss = $(SETUP_SYMLINKS) $(DESTDIR)$(bashcompdir) install-data-hook: symlinks check-local: - ret=0; \ + REPLY=0; \ for file in $(bashcomp_DATA); do \ $${bashcomp_bash:-$${BASH:-bash}} \ - -O extglob -n $(srcdir)/$$file || ret=$$?; \ + -O extglob -n $(srcdir)/$$file || REPLY=$$?; \ done; \ - exit $$ret + exit $$REPLY diff --git a/completions/_adb b/completions/_adb index e8ebab1..0189331 100644 --- a/completions/_adb +++ b/completions/_adb @@ -3,67 +3,67 @@ # Use of this file is deprecated. Upstream completion is available in # the Android SDK, use that instead. -_adb_command_usage() +_comp_cmd_adb__command_usage() { - COMPREPLY=($(compgen -W \ - '$("$1" help 2>&1 | command grep "^ *\(adb \)\? *$2 " \ - | command sed -e "s/[]|[]/\n/g" | _parse_help -)' -- "$cur")) + _comp_compgen_help - <<<"$("$1" help 2>&1 | + command sed -e "/^ *\(adb \)\{0,1\} *$2 /!d;s/[]|[]/\n/g")" } -_adb() +_comp_cmd_adb() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -s | -p | --algo | --key | --iv) return ;; -f) - _filedir + _comp_compgen_filedir return ;; esac - local cmd i + local cmd has_cmd="" i for ((i = 1; i < cword; i++)); do if [[ ${words[i]} != -* && ${words[i - 1]} != -[sp] ]]; then cmd="${words[i]}" + has_cmd=set break fi done - if [[ ! -v cmd ]]; then + if [[ ! $has_cmd ]]; then local tmp=() if [[ ! $cur || $cur == -* ]]; then - tmp+=($(compgen -W '$(_parse_help "$1" help)' -- "$cur")) + _comp_compgen -av tmp help -- help fi if [[ ! $cur || $cur != -* ]]; then - tmp+=($($1 help 2>&1 | awk '$1 == "adb" { print $2 }')) + _comp_split -a tmp "$("$1" help 2>&1 | _comp_awk '$1 == "adb" { print $2 }')" tmp+=(devices connect disconnect sideload) fi - COMPREPLY=($(compgen -W '${tmp[@]}' -- "$cur")) + ((${#tmp[@]})) && + _comp_compgen -- -W '"${tmp[@]}"' return fi # TODO: more and better command completions - _adb_command_usage "$1" $cmd + _comp_cmd_adb__command_usage "$1" "$cmd" case $cmd in push | restore | sideload) - _filedir + _comp_compgen -a filedir ;; forward) - COMPREPLY=($(compgen -W \ - '$("$1" help 2>&1 | command sed -ne "s/^ *adb *forward *-/-/p" | \ - _parse_help -)' -- "$cur")) + _comp_compgen_help - <<<"$("$1" help 2>&1 | + command sed -ne "s/^ *adb *forward *-/-/p")" ;; reboot) - COMPREPLY=($(compgen -W 'bootloader recovery' -- "$cur")) + _comp_compgen -- -W 'bootloader recovery' ;; esac } && - complete -F _adb adb + complete -F _comp_cmd_adb adb # ex: filetype=sh diff --git a/completions/_cal b/completions/_cal index 1eec267..3f8b3ca 100644 --- a/completions/_cal +++ b/completions/_cal @@ -3,15 +3,15 @@ # Use of this file is deprecated on Linux. Upstream completion is # available in util-linux >= 2.23, use that instead. -_cal() +_comp_cmd_cal() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -m) if [[ $OSTYPE == *bsd* ]]; then - COMPREPLY=($(compgen -W '{1..12}' -- "$cur")) + _comp_compgen -- -W '{1..12}' return fi ;; @@ -24,15 +24,14 @@ _cal() esac if [[ $cur == -* ]]; then - local opts=$(_parse_help "$1") - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage return fi - local args - _count_args - ((args == 1)) && COMPREPLY=($(compgen -W '{1..12}' -- "$cur")) + local REPLY + _comp_count_args + ((REPLY == 1)) && _comp_compgen -- -W '{1..12}' } && - complete -F _cal cal ncal + complete -F _comp_cmd_cal cal ncal # ex: filetype=sh diff --git a/completions/_cargo b/completions/_cargo new file mode 100644 index 0000000..257eb35 --- /dev/null +++ b/completions/_cargo @@ -0,0 +1,9 @@ +# 3rd party completion loader for cargo -*- shell-script -*- +# +# This serves as a fallback in case the completion is not installed otherwise. + +# shellcheck disable=SC2168 # "local" is ok, assume sourced by _comp_load +local rustup="${1%cargo}rustup" # use rustup from same dir +eval -- "$("$rustup" completions bash cargo 2>/dev/null)" + +# ex: filetype=sh diff --git a/completions/_chsh b/completions/_chsh index 8f8a807..4e243ba 100644 --- a/completions/_chsh +++ b/completions/_chsh @@ -1,31 +1,43 @@ # chsh(1) completion -*- shell-script -*- -# Use of this file is deprecated on Linux. Upstream completion is -# available in util-linux >= 2.23, use that instead. +# Use of this file is deprecated on Linux systems whose chsh is from +# util-linux. Upstream completion is in util-linux >= 2.23, use that instead. -_chsh() +_comp_cmd_chsh() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + + local word chroot="" has_chroot="" + for word in "${words[@]}"; do + if [[ $has_chroot ]]; then + chroot=$word + break + fi + [[ $word != -@(R|-root) ]] || has_chroot=set + done case $prev in --list-shells | --help | -v | --version) return ;; + -R | --root) + _comp_compgen_filedir -d + return + ;; -s | --shell) - _shells + _comp_compgen_shells "${chroot-}" return ;; esac if [[ $cur == -* ]]; then - local opts=$(_parse_help "$1") - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage else - _allowed_users + _comp_compgen_allowed_users fi } && - complete -F _chsh chsh + complete -F _comp_cmd_chsh chsh # ex: filetype=sh diff --git a/completions/_dmesg b/completions/_dmesg index 8306654..ad90fcc 100644 --- a/completions/_dmesg +++ b/completions/_dmesg @@ -3,31 +3,29 @@ # Use of this file is deprecated on Linux. Upstream completion is # available in util-linux >= 2.23, use that instead. -_dmesg() +_comp_cmd_dmesg() { [[ $OSTYPE == *solaris* ]] && return # no args there - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -h | --help | -V | --version | -s | --buffer-size | -M | -N) return ;; -f | --facility) - COMPREPLY=($(compgen -W 'kern user mail daemon auth syslog lpr - news' -- "$cur")) + _comp_compgen -- -W 'kern user mail daemon auth syslog lpr news' return ;; -l | --level | -n | --console-level) - COMPREPLY=($(compgen -W '{1..8}' -- "$cur")) + _comp_compgen -- -W '{1..8}' return ;; esac - local opts=$(_parse_help "$1") - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage } && - complete -F _dmesg dmesg + complete -F _comp_cmd_dmesg dmesg # ex: filetype=sh diff --git a/completions/_eject b/completions/_eject index 52168f7..76ae0f8 100644 --- a/completions/_eject +++ b/completions/_eject @@ -3,31 +3,31 @@ # Use of this file is deprecated on Linux. Upstream completion is # available in util-linux >= 2.23, use that instead. -_eject() +_comp_cmd_eject() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -h | --help | -V | --version | -c | --changerslot | -x | --cdspeed) return ;; -a | --auto | -i | --manualeject) - COMPREPLY=($(compgen -W 'on off' -- "$cur")) + _comp_compgen -- -W 'on off' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return elif [[ $prev == @(-d|--default) ]]; then return fi - _cd_devices - _dvd_devices + _comp_compgen_cd_devices + _comp_compgen -a dvd_devices } && - complete -F _eject eject + complete -F _comp_cmd_eject eject # ex: filetype=sh diff --git a/completions/_flamegraph b/completions/_flamegraph new file mode 100644 index 0000000..95c86c0 --- /dev/null +++ b/completions/_flamegraph @@ -0,0 +1,8 @@ +# 3rd party completion loader for commands emitting -*- shell-script -*- +# their completion using "$cmd --completions bash". +# +# This serves as a fallback in case the completion is not installed otherwise. + +eval -- "$("$1" --completions bash 2>/dev/null)" + +# ex: filetype=sh diff --git a/completions/_gaiacli b/completions/_gaiacli new file mode 100644 index 0000000..2f48598 --- /dev/null +++ b/completions/_gaiacli @@ -0,0 +1,8 @@ +# 3rd party completion loader for commands emitting -*- shell-script -*- +# their completion using "$cmd completion". +# +# This serves as a fallback in case the completion is not installed otherwise. + +eval -- "$("$1" completion 2>/dev/null)" + +# ex: filetype=sh diff --git a/completions/_gh b/completions/_gh new file mode 100644 index 0000000..8a0376d --- /dev/null +++ b/completions/_gh @@ -0,0 +1,8 @@ +# 3rd party completion loader for commands emitting -*- shell-script -*- +# their completion using "$cmd completion --shell bash". +# +# This serves as a fallback in case the completion is not installed otherwise. + +eval -- "$("$1" completion --shell bash 2>/dev/null)" + +# ex: filetype=sh diff --git a/completions/_golangci-lint b/completions/_golangci-lint new file mode 100644 index 0000000..40fc5c3 --- /dev/null +++ b/completions/_golangci-lint @@ -0,0 +1,9 @@ +# 3rd party completion loader for commands emitting -*- shell-script -*- +# their completion using "$cmd completion bash". +# For example, many Go programs using https://github.com/spf13/cobra do. +# +# This serves as a fallback in case the completion is not installed otherwise. + +eval -- "$("$1" completion bash 2>/dev/null)" + +# ex: filetype=sh diff --git a/completions/_gsctl b/completions/_gsctl new file mode 100644 index 0000000..3b1a040 --- /dev/null +++ b/completions/_gsctl @@ -0,0 +1,8 @@ +# 3rd party completion loader for commands emitting -*- shell-script -*- +# their completion using "$cmd completion bash --stdout". +# +# This serves as a fallback in case the completion is not installed otherwise. + +eval -- "$("$1" completion bash --stdout 2>/dev/null)" + +# ex: filetype=sh diff --git a/completions/_hexdump b/completions/_hexdump index 785f597..939cfa6 100644 --- a/completions/_hexdump +++ b/completions/_hexdump @@ -3,29 +3,28 @@ # Use of this file is deprecated on Linux. Upstream completion is # available in util-linux >= 2.23, use that instead. -_hexdump() +_comp_cmd_hexdump() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -V | -e | -n | -s) return ;; -f) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - local opts="$(_parse_help "$1")" - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage return fi - _filedir + _comp_compgen_filedir } && - complete -F _hexdump hexdump hd + complete -F _comp_cmd_hexdump hexdump hd # ex: filetype=sh diff --git a/completions/_hwclock b/completions/_hwclock index ef437a2..a0fd831 100644 --- a/completions/_hwclock +++ b/completions/_hwclock @@ -3,24 +3,24 @@ # Use of this file is deprecated. Upstream completion is available in # util-linux >= 2.23, use that instead. -_hwclock() +_comp_cmd_hwclock() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -h | --help | -V | --version | --date | --epoch) return ;; -f | --rtc | --adjfile) - _filedir + _comp_compgen_filedir return ;; esac - COMPREPLY=( - $(PATH="$PATH:/sbin" compgen -W '$(_parse_help "$1")' -- "$cur")) + local PATH=$PATH:/sbin + _comp_compgen_help } && - complete -F _hwclock hwclock + complete -F _comp_cmd_hwclock hwclock # ex: filetype=sh diff --git a/completions/_ionice b/completions/_ionice index b0d96a1..42fcd39 100644 --- a/completions/_ionice +++ b/completions/_ionice @@ -3,10 +3,10 @@ # Use of this file is deprecated. Upstream completion is available in # util-linux >= 2.23, use that instead. -_ionice() +_comp_cmd_ionice() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local offset=0 i for ((i = 1; i <= cword; i++)); do @@ -31,30 +31,30 @@ _ionice() done if ((offset > 0)); then - _command_offset $offset + _comp_command_offset $offset return fi case $prev in -c) - COMPREPLY=($(compgen -W '{0..3}' -- "$cur")) + _comp_compgen -- -W '{0..3}' return ;; -n) - COMPREPLY=($(compgen -W '{0..7}' -- "$cur")) + _comp_compgen -- -W '{0..7}' return ;; -p) - _pids + _comp_compgen_pids return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur")) + _comp_compgen_help -- -h return fi } && - complete -F _ionice ionice + complete -F _comp_cmd_ionice ionice # ex: filetype=sh diff --git a/completions/_jungle b/completions/_jungle new file mode 100644 index 0000000..f08ae91 --- /dev/null +++ b/completions/_jungle @@ -0,0 +1,16 @@ +# 3rd party completion loader for commands emitting -*- shell-script -*- +# their completion using "_${cmdname^^}_COMPLETE=source $cmd". +# This pattern is very similar to `completions/_pipenv`, but the value of the +# environment variable is slightly different. +# +# This serves as a fallback in case the completion is not installed otherwise. + +eval -- "$( + # shellcheck disable=SC2154 + ucname="${cmdname^^}" + ucname=${ucname//-/_} + export "_${ucname}_COMPLETE=source" + "$1" 2>/dev/null +)" + +# ex: filetype=sh diff --git a/completions/_keyring b/completions/_keyring new file mode 100644 index 0000000..4dcc58f --- /dev/null +++ b/completions/_keyring @@ -0,0 +1,9 @@ +# 3rd party completion loader for commands emitting -*- shell-script -*- +# their completion using "$cmd --print-completion bash". +# For example, many Python programs using https://github.com/iterative/shtab do. +# +# This serves as a fallback in case the completion is not installed otherwise. + +eval -- "$("$1" --print-completion bash 2>/dev/null)" + +# ex: filetype=sh diff --git a/completions/_kontena b/completions/_kontena new file mode 100644 index 0000000..94918fe --- /dev/null +++ b/completions/_kontena @@ -0,0 +1,14 @@ +# 3rd party completion loader for kontena -*- shell-script -*- +# +# This serves as a fallback in case the completion is not installed otherwise. + +# To avoid sourcing an empty string with `. "$(...)"` on failing to obtain the +# path, we assign the output to a variable `_comp_cmd_kontena__completion_path` +# and test it before sourcing. The variable is removed on successful loading +# but left on a failure for the debugging purpose. +_comp_cmd_kontena__completion_path=$("$1" whoami --bash-completion-path 2>/dev/null) && + [[ -r $_comp_cmd_kontena__completion_path ]] && + . "$_comp_cmd_kontena__completion_path" && + unset -v _comp_cmd_kontena__completion_path + +# ex: filetype=sh diff --git a/completions/_look b/completions/_look index 9788dec..20613ff 100644 --- a/completions/_look +++ b/completions/_look @@ -3,15 +3,15 @@ # Use of this file is deprecated on Linux. Upstream completion is # available in util-linux >= 2.23, use that instead. -_look() +_comp_cmd_look() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if ((cword == 1)); then - COMPREPLY=($(compgen -W '$(look "$cur" 2>/dev/null)' -- "$cur")) + _comp_compgen_split -- "$(look "$cur" 2>/dev/null)" fi } && - complete -F _look -o default look + complete -F _comp_cmd_look -o default look # ex: filetype=sh diff --git a/completions/_mdbook b/completions/_mdbook new file mode 100644 index 0000000..fe32688 --- /dev/null +++ b/completions/_mdbook @@ -0,0 +1,8 @@ +# 3rd party completion loader for commands emitting -*- shell-script -*- +# their completion using "$cmd completions bash". +# +# This serves as a fallback in case the completion is not installed otherwise. + +eval -- "$("$1" completions bash 2>/dev/null)" + +# ex: filetype=sh diff --git a/completions/_mock b/completions/_mock index b468148..df778a8 100644 --- a/completions/_mock +++ b/completions/_mock @@ -3,10 +3,10 @@ # Use of this file is deprecated. Upstream completion is available in # mock > 1.1.0, use that instead. -_mock() +_comp_cmd_mock() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return local plugins='tmpfs root_cache yum_cache bind_mount ccache' local cfgdir=/etc/mock count=0 i @@ -27,43 +27,45 @@ _mock() return ;; -r | --root) - COMPREPLY=($(compgen -W "$(command ls $cfgdir)" -- "$cur")) - COMPREPLY=(${COMPREPLY[@]/%.cfg/}) + _comp_compgen_split -- "$(command ls "$cfgdir")" && + COMPREPLY=("${COMPREPLY[@]/%.cfg/}") return ;; --configdir | --resultdir) - _filedir -d + _comp_compgen_filedir -d return ;; --spec) - _filedir spec + _comp_compgen_filedir spec return ;; --target) + # Case-insensitive BRE to match "compatible archs" + local regex_header='[cC][oO][mM][pP][aA][tT][iI][bB][lL][eE][[:space:]]\{1,\}[aA][rR][cC][hH][sS]' + # Yep, compatible archs, not compatible build archs # (e.g. ix86 chroot builds in x86_64 mock host) # This would actually depend on what the target root # can be used to build for... - COMPREPLY=($(compgen -W "$(command rpm --showrc | - command sed -ne 's/^\s*compatible\s\s*archs\s*:\s*\(.*\)/\1/i p')" \ - -- "$cur")) + _comp_compgen_split -- "$(command rpm --showrc | command sed -ne \ + "s/^[[:space:]]*${regex_header}[[:space:]]*:[[:space:]]*\(.*\)/\1/p")" return ;; --enable-plugin | --disable-plugin) - COMPREPLY=($(compgen -W "$plugins" -- "$cur")) + _comp_compgen -- -W "$plugins" return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - _filedir '@(?(no)src.r|s)pm' + _comp_compgen_filedir '@(?(no)src.r|s)pm' fi } && - complete -F _mock mock + complete -F _comp_cmd_mock mock # ex: filetype=sh diff --git a/completions/_modules b/completions/_modules index 4f7c4d4..830ddfe 100644 --- a/completions/_modules +++ b/completions/_modules @@ -19,67 +19,66 @@ # Test for existence of /etc/profile.d/modules.sh too because we may end up # being sourced before it and thus before the `module' alias has been defined. -[ -f /etc/profile.d/modules.sh ] || return 1 +[[ -f /etc/profile.d/modules.sh ]] || return 1 -_module_list() +_comp_cmd_module__compgen_list() { - local modules="$(command sed 's/:/ /g' <<<$LOADEDMODULES | sort)" - compgen -W "$modules" -- $1 + local modules="$(command sed 's/:/ /g' <<<"$LOADEDMODULES" | sort)" + _comp_compgen -- -W "$modules" } -_module_path() +_comp_cmd_module__compgen_path() { - local modules="$(command sed 's/:/ /g' <<<$MODULEPATH | sort)" - compgen -W "$modules" -- $1 + local modules="$(command sed 's/:/ /g' <<<"$MODULEPATH" | sort)" + _comp_compgen -- -W "$modules" } -_module_avail() +_comp_cmd_module__compgen_avail() { local modules="$( module avail 2>&1 | command grep -E -v '^(-|$)' | xargs printf '%s\n' | command sed -e 's/(default)//g' | sort )" - - compgen -W "$modules" -- $1 + _comp_compgen -- -W "$modules" } # A completion function for the module alias -_module() +_comp_cmd_module() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if ((cword == 1)); then # First parameter on line -- we expect it to be a mode selection local options options="$(module help 2>&1 | command grep -E '^[[:space:]]*\+' | - awk '{print $2}' | command sed -e 's/|/ /g' | sort)" + _comp_awk '{print $2}' | command sed -e 's/|/ /g' | sort)" - COMPREPLY=($(compgen -W "$options" -- "$cur")) + _comp_compgen -- -W "$options" elif ((cword == 2)); then case $prev in add | display | help | load | show | whatis) - COMPREPLY=($(_module_avail "$cur")) + _comp_cmd_module__compgen_avail ;; rm | switch | swap | unload | update) - COMPREPLY=($(_module_list "$cur")) + _comp_cmd_module__compgen_list ;; unuse) - COMPREPLY=($(_module_path "$cur")) + _comp_cmd_module__compgen_path ;; esac elif ((cword == 3)); then case ${words[1]} in swap | switch) - COMPREPLY=($(_module_avail "$cur")) + _comp_cmd_module__compgen_avail ;; esac fi } && - complete -F _module -o default module + complete -F _comp_cmd_module -o default module # ex: filetype=sh diff --git a/completions/_mount b/completions/_mount index 85f5490..ab385f1 100644 --- a/completions/_mount +++ b/completions/_mount @@ -14,16 +14,16 @@ fi # query the server for a list of all available exports and complete on # that instead. # -_mount() +_comp_cmd_mount() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return local sm host case $prev in -t | --types) - _fstypes + _comp_compgen_fstypes return ;; esac @@ -33,8 +33,9 @@ _mount() if [[ $cur == *:* ]]; then for sm in "$(type -P showmount)" {,/usr}/{,s}bin/showmount; do [[ -x $sm ]] || continue - COMPREPLY=($(compgen -W "$("$sm" -e ${cur%%:*} | - awk 'NR>1 {print $1}')" -- "${cur#*:}")) + _comp_compgen -c "${cur#*:}" split -- "$( + "$sm" -e ${cur%%:*} | _comp_awk 'NR>1 {print $1}' + )" return done fi @@ -42,24 +43,30 @@ _mount() if [[ $cur == //* ]]; then host=${cur#//} host=${host%%/*} - if [[ -n $host ]]; then - COMPREPLY=($(compgen -P "//$host" -W \ - "$(smbclient -d 0 -NL $host 2>/dev/null | + if [[ $host ]]; then + _comp_compgen -c "${cur#//"$host"}" split -P "//$host" -- "$( + smbclient -d 0 -NL "$host" 2>/dev/null | command sed -ne '/^[[:blank:]]*Sharename/,/^$/p' | - command sed -ne '3,$s|^[^A-Za-z]*\([^[:blank:]]*\).*$|/\1|p')" \ - -- "${cur#//$host}")) + command sed -ne '3,$s|^[^A-Za-z]*\([^[:blank:]]*\).*$|/\1|p' + )" fi elif [[ -r /etc/vfstab ]]; then # Solaris - COMPREPLY=($(compgen -W "$(awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}' /etc/vfstab)" -- "$cur")) + _comp_compgen_split -- "$( + _comp_awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}' /etc/vfstab + )" elif [[ ! -e /etc/fstab ]]; then # probably Cygwin - COMPREPLY=($(compgen -W "$($1 | awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}')" -- "$cur")) + _comp_compgen_split -- "$( + "$1" | _comp_awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}' + )" else # probably BSD - COMPREPLY=($(compgen -W "$(awk '! /^[ \t]*#/ {if ($2 ~ /\//) print $2}' /etc/fstab)" -- "$cur")) + _comp_compgen_split -- "$( + _comp_awk '! /^[ \t]*#/ {if ($2 ~ /\//) print $2}' /etc/fstab + )" fi } && - complete -F _mount -o default -o dirnames mount + complete -F _comp_cmd_mount -o default -o dirnames mount # ex: filetype=sh diff --git a/completions/_mount.linux b/completions/_mount.linux index f40865e..3d4c307 100644 --- a/completions/_mount.linux +++ b/completions/_mount.linux @@ -3,12 +3,12 @@ # Use of this file is deprecated on Linux. Upstream completion is # available in util-linux >= 2.28, use that instead. -_mount() +_comp_cmd_mount() { - local cur prev words cword - _init_completion -n =: || return + local cur prev words cword comp_args + _comp_initialize -n =: -- "$@" || return - local split=false + local split="" case "$prev" in -t | --types) # find /lib/modules/$(uname -r)/ -type f -path '*/fs/*.ko' -printf '%f\n' | cut -d. -f1 @@ -16,38 +16,33 @@ _mount() if [[ $cur == ?*,* ]]; then prev="${cur%,*}" cur="${cur##*,}" - split=true + split=set fi - COMPREPLY=($(compgen -W 'auto adfs affs autofs btrfs cifs coda - cramfs davfs debugfs devpts efs ext2 ext3 ext4 fuse hfs hfsplus - hpfs iso9660 jffs2 jfs minix msdos ncpfs nfs nfs4 ntfs ntfs-3g - proc qnx4 ramfs reiserfs romfs squashfs smbfs sysv tmpfs ubifs - udf ufs umsdos usbfs vfat xfs' -- "$cur")) - _fstypes - $split && COMPREPLY=(${COMPREPLY[@]/#/$prev,}) + _comp_compgen -- -W 'auto adfs affs autofs btrfs cifs coda cramfs + davfs debugfs devpts efs ext2 ext3 ext4 fuse hfs hfsplus hpfs + iso9660 jffs2 jfs minix msdos ncpfs nfs nfs4 ntfs ntfs-3g proc + qnx4 ramfs reiserfs romfs squashfs smbfs sysv tmpfs ubifs udf + ufs umsdos usbfs vfat xfs' + _comp_compgen -a fstypes + [[ $split ]] && ((${#COMPREPLY[@]})) && + _comp_compgen -Rv COMPREPLY -- -P "$prev," -W '"${COMPREPLY[@]}"' return ;; --bind | -B | --rbind | -R) - _filedir -d + _comp_compgen_filedir -d return ;; -p | --pass-fd) - COMPREPLY=($(compgen -W '{0..9}')) + _comp_compgen -R -- -W '{0..9}' compopt -o nospace return ;; -L) - COMPREPLY=($( - cd "/dev/disk/by-label/" 2>/dev/null || return - compgen -f -- "$cur" - )) + _comp_compgen -C "/dev/disk/by-label/" -- -f return ;; -U) - COMPREPLY=($( - cd "/dev/disk/by-uuid/" 2>/dev/null || return - compgen -f -- "$cur" - )) + _comp_compgen -C "/dev/disk/by-uuid/" -- -f return ;; -O | --test-opts) @@ -74,149 +69,152 @@ _mount() if [[ $cur == ?*,* ]]; then prev="${cur%,*}" cur="${cur##*,}" - split=true + split=set fi # no completion if $cur is opt=smth [[ $cur == *=* ]] && return # mount options - COMPREPLY=($(compgen -W 'loop {,a}sync {,no}atime {,no}auto + _comp_compgen -- -W 'loop {,a}sync {,no}atime {,no}auto {,fs,def,root}context= defaults {,no}dev {,no}diratime dirsync {,no}exec group {,no}iversion {,no}mand _netdev nofail {,no}relatime {,no}strictatime {,no}suid owner remount ro rw - {,no}user users' -- "$cur")) + {,no}user users' case "$fstype" in adfs | auto) - COMPREPLY+=($(compgen -W '{u,g}id= {own,oth}mask=' -- "$cur")) + _comp_compgen -a -- -W '{u,g}id= {own,oth}mask=' ;;& affs | auto) - COMPREPLY+=($(compgen -W '{u,g}id= set{u,g}id= mode= protect - usemp verbose prefix= volume= reserved= root= bs= - {,no,usr,grp}quota' -- "$cur")) + _comp_compgen -a -- -W '{u,g}id= set{u,g}id= mode= protect + usemp verbose prefix= volume= reserved= root= bs= + {,no,usr,grp}quota' ;;& btrfs | auto) - COMPREPLY+=($(compgen -W 'degraded subvol= subvolid= device= - nodatasum nodatacow nobarrier max_inline= alloc_start= - thread_pool= compress= compress-force= ssd noacl notreelog - flushoncommit metadata_ratio= {,no}space_cache clear_cache - user_subvol_rm_allowed autodefrag inode_cache' -- "$cur")) + _comp_compgen -a -- -W 'degraded subvol= subvolid= device= + nodatasum nodatacow nobarrier max_inline= alloc_start= + thread_pool= compress= compress-force= ssd noacl + notreelog flushoncommit metadata_ratio= + {,no}space_cache clear_cache user_subvol_rm_allowed + autodefrag inode_cache' ;;& cifs | auto) - COMPREPLY+=($(compgen -W 'user= password= credentials= {u,g}id= - force{u,g}id port= servern= netbiosname= {file,dir}_mode= - ip= domain= guest iocharset {,no}setuids {,no,dyn}perm - directio {,no}mapchars {,no}intr hard soft noacl nocase sec= - nobrl sfu {,no}serverino nounix nouser_xattr {r,w}size= - rwpidforward backup{u,g}id cache=' -- "$cur")) + _comp_compgen -a -- -W 'user= password= credentials= + {u,g}id= force{u,g}id port= servern= netbiosname= + {file,dir}_mode= ip= domain= guest iocharset + {,no}setuids {,no,dyn}perm directio {,no}mapchars + {,no}intr hard soft noacl nocase sec= nobrl sfu + {,no}serverino nounix nouser_xattr {r,w}size= + rwpidforward backup{u,g}id cache=' ;;& davfs | auto) - COMPREPLY+=($(compgen -W 'conf= {file,dir}_mode= {u,g}id= - username=' -- "$cur")) + _comp_compgen -a -- -W 'conf= {file,dir}_mode= {u,g}id= + username=' ;;& ext[2-4] | auto) - COMPREPLY+=($(compgen -W '{,no}acl bsddf minixdf check= debug - errors= {,no}grpid {bsd,sysv}groups {,no,usr,grp}quota - nobh nouid32 oldalloc orlov res{u,g}id= sb= - {,no}user_xattr' -- "$cur")) + _comp_compgen -a -- -W '{,no}acl bsddf minixdf check= debug + errors= {,no}grpid {bsd,sysv}groups {,no,usr,grp}quota + nobh nouid32 oldalloc orlov res{u,g}id= sb= + {,no}user_xattr' ;;& ext[34] | auto) - COMPREPLY+=($(compgen -W 'journal= journal_dev= norecovery - noload data= barrier= commit=' -- "$cur")) + _comp_compgen -a -- -W 'journal= journal_dev= norecovery + noload data= barrier= commit=' ;;& ext4 | auto) - COMPREPLY+=($(compgen -W 'journal_checksum journal_async_commit - nobarrier inode_readahead= stripe= {,no}delalloc abort - {max,min}_batch_time= journal_ioprio= {,no}auto_da_alloc - {,no}discard nouid32 resize {,no}block_validity - dioread_{,no}lock max_dir_size_kb= i_version' -- "$cur")) + _comp_compgen -a -- -W 'journal_checksum + journal_async_commit nobarrier inode_readahead= stripe= + {,no}delalloc abort {max,min}_batch_time= + journal_ioprio= {,no}auto_da_alloc {,no}discard nouid32 + resize {,no}block_validity dioread_{,no}lock + max_dir_size_kb= i_version' ;;& msdos | umsdos | vfat | auto) - COMPREPLY+=($(compgen -W 'blocksize= {u,g}id= {u,d,f}mask= - allow_utime= check= codepage= conv= cvf_format= cvf_option= - debug fat= iocharset= tz= quiet showexec sys_immutable flush - usefree {,no}dots dotsOK=' -- "$cur")) + _comp_compgen -a -- -W 'blocksize= {u,g}id= {u,d,f}mask= + allow_utime= check= codepage= conv= cvf_format= + cvf_option= debug fat= iocharset= tz= quiet showexec + sys_immutable flush usefree {,no}dots dotsOK=' ;;& vfat | auto) - COMPREPLY+=($(compgen -W 'uni_xlate posix nonumtail utf8 - shortname=' -- "$cur")) + _comp_compgen -a -- -W 'uni_xlate posix nonumtail utf8 + shortname=' ;;& iso9660 | auto) - COMPREPLY+=($(compgen -W 'norock nojoliet check= {u,g}id= map= - mode= unhide block= conv= cruft session= sbsector= - iocharset= utf8' -- "$cur")) + _comp_compgen -a -- -W 'norock nojoliet check= {u,g}id= + map= mode= unhide block= conv= cruft session= sbsector= + iocharset= utf8' ;;& jffs2 | auto) - COMPREPLY+=($(compgen -W 'compr= rp_size=' -- "$cur")) + _comp_compgen -a -- -W 'compr= rp_size=' ;;& jfs | auto) - COMPREPLY+=($(compgen -W 'iocharset= resize= {,no}integrity - errors= {,no,usr,grp}quota' -- "$cur")) + _comp_compgen -a -- -W 'iocharset= resize= {,no}integrity + errors= {,no,usr,grp}quota' ;;& nfs | nfs4 | auto) - COMPREPLY+=($(compgen -W 'soft hard timeo= retrans= {r,w}size= - {,no}ac acreg{min,max}= acdir{min,max}= actimeo= bg fg - retry= sec= {,no}sharecache {,no}resvport lookupcache= - proto= port= {,no}intr {,no}cto {,nfs}vers= ' -- "$cur")) + _comp_compgen -a -- -W 'soft hard timeo= retrans= {r,w}size= + {,no}ac acreg{min,max}= acdir{min,max}= actimeo= bg fg + retry= sec= {,no}sharecache {,no}resvport lookupcache= + proto= port= {,no}intr {,no}cto {,nfs}vers=' ;;& nfs | auto) - COMPREPLY+=($(compgen -W 'udp tcp rdma mount{port,proto,host}= - mountvers= namlen={,no}lock {,no}acl {,no}rdirplus - {,no}fsc' -- "$cur")) + _comp_compgen -a -- -W 'udp tcp rdma mount{port,proto,host}= + mountvers= namlen={,no}lock {,no}acl {,no}rdirplus + {,no}fsc' ;;& nfs4 | auto) - COMPREPLY+=($(compgen -W 'clientaddr= {,no}migration' \ - -- "$cur")) + _comp_compgen -a -- -W 'clientaddr= {,no}migration' ;;& ntfs-3g) - COMPREPLY+=($(compgen -W '{u,g}id= {u,f,d}mask= usermapping= - permissions inherit locale= force {,no}recover - ignore_case remove_hiberfile show_sys_files - hide_{hid,dot}_files windows_names allow_other max_read= - silent no_def_opts streams_interface= user_xattr efs_raw - {,no}compression debug no_detach' -- "$cur")) + _comp_compgen -a -- -W '{u,g}id= {u,f,d}mask= usermapping= + permissions inherit locale= force {,no}recover + ignore_case remove_hiberfile show_sys_files + hide_{hid,dot}_files windows_names allow_other + max_read= silent no_def_opts streams_interface= + user_xattr efs_raw {,no}compression debug no_detach' ;;& proc | auto) - COMPREPLY+=($(compgen -W '{u,g}id=' -- "$cur")) + _comp_compgen -a -- -W '{u,g}id=' ;;& reiserfs | auto) - COMPREPLY+=($(compgen -W 'conv hash= {,no_un}hashed_relocation - noborder nolog notail replayonly resize= user_xattr acl - barrier=' -- "$cur")) + _comp_compgen -a -- -W 'conv hash= + {,no_un}hashed_relocation noborder nolog notail + replayonly resize= user_xattr acl barrier=' ;;& tmpfs | auto) - COMPREPLY+=($(compgen -W 'size= nr_blocks= nr_inodes= mode= - {u,g}id= mpol=' -- "$cur")) + _comp_compgen -a -- -W 'size= nr_blocks= nr_inodes= mode= + {u,g}id= mpol=' ;;& udf | auto) - COMPREPLY+=($(compgen -W '{u,g}id= umask= unhide undelete - nostrict iocharset bs= novrs session= anchor= volume= - partition= lastblock= fileset= rootdir=' -- "$cur")) + _comp_compgen -a -- -W '{u,g}id= umask= unhide undelete + nostrict iocharset bs= novrs session= anchor= volume= + partition= lastblock= fileset= rootdir=' ;;& usbfs | auto) - COMPREPLY+=($(compgen -W 'dev{u,g}id= devmode= bus{u,g}id= - busmode= list{u,g}id= listmode=' -- "$cur")) + _comp_compgen -a -- -W 'dev{u,g}id= devmode= bus{u,g}id= + busmode= list{u,g}id= listmode=' ;;& xfs | auto) - COMPREPLY+=($(compgen -W 'allocsize= {,no}attr2 barrier dmapi - {,no}grpid {bsd,sysv}groups ihashsize= {,no}ikeep - inode{32,64} {,no}largeio logbufs= logbsize= logdev= - rtdev= mtpt= noalign norecovery nouuid osyncisosync - {u,g,p}qnoenforce {,u,usr,g,grp,p,prj}quota sunit= swidth= - swalloc' -- "$cur")) + _comp_compgen -a -- -W 'allocsize= {,no}attr2 barrier dmapi + {,no}grpid {bsd,sysv}groups ihashsize= {,no}ikeep + inode{32,64} {,no}largeio logbufs= logbsize= logdev= + rtdev= mtpt= noalign norecovery nouuid osyncisosync + {u,g,p}qnoenforce {,u,usr,g,grp,p,prj}quota sunit= + swidth= swalloc' ;;& esac # COMP_WORDBREAKS is a real pain in the ass - prev="${prev##*[$COMP_WORDBREAKS]}" - $split && COMPREPLY=(${COMPREPLY[@]/#/"$prev,"}) + prev="${prev##*["$COMP_WORDBREAKS"]}" + [[ $split ]] && ((${COMPREPLY[@]})) && + _comp_compgen -Rv COMPREPLY -- -P "$prev," -W '"${COMPREPLY[@]}"' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--version --help --verbose --all --fork - --fake --internal-only -l --no-mtab --no-canonicalize --pass-fd -s + _comp_compgen -- -W '--version --help --verbose --all --fork --fake + --internal-only -l --no-mtab --no-canonicalize --pass-fd -s --read-only --rw -L -U --types --test-opts --options --bind --rbind - --move' -- "$cur")) + --move' [[ ${COMPREPLY-} ]] && return fi @@ -227,8 +225,9 @@ _mount() if [[ $cur == *:* ]]; then for sm in "$(type -P showmount)" {,/usr}/{,s}bin/showmount; do [[ -x $sm ]] || continue - COMPREPLY=($(compgen -W "$("$sm" -e ${cur%%:*} | - awk 'NR>1 {print $1}')" -- "${cur#*:}")) + _comp_compgen -c "${cur#*:}" split -- "$( + "$sm" -e ${cur%%:*} | _comp_awk 'NR>1 {print $1}' + )" return done fi @@ -236,17 +235,17 @@ _mount() if [[ $cur == //* ]]; then host=${cur#//} host=${host%%/*} - if [[ -n $host ]]; then - COMPREPLY=($(compgen -P "//$host" -W \ - "$(smbclient -d 0 -NL $host 2>/dev/null | + if [[ $host ]]; then + _comp_compgen -c "${cur#//"$host"}" split -P "//$host" -- "$( + smbclient -d 0 -NL "$host" 2>/dev/null | command sed -ne '/^[[:blank:]]*Sharename/,/^$/p' | - command sed -ne '3,$s|^[^A-Za-z]*\([^[:blank:]]*\).*$|/\1|p')" \ - -- "${cur#//$host}")) + command sed -ne '3,$s|^[^A-Za-z]*\([^[:blank:]]*\).*$|/\1|p' + )" fi fi - _filedir + _comp_compgen -a filedir } && - complete -F _mount mount + complete -F _comp_cmd_mount mount # ex: filetype=sh diff --git a/completions/_newgrp b/completions/_newgrp index a2dc3ed..7e86672 100644 --- a/completions/_newgrp +++ b/completions/_newgrp @@ -3,17 +3,17 @@ # Use of this file is deprecated on Linux. Upstream completion is # available in util-linux >= 2.23, use that instead. -_newgrp() +_comp_cmd_newgrp() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == "-" ]]; then COMPREPLY=(-) else - _allowed_groups "$cur" + _comp_compgen_allowed_groups fi } && - complete -F _newgrp newgrp + complete -F _comp_cmd_newgrp newgrp # ex: filetype=sh diff --git a/completions/_nmcli b/completions/_nmcli index eac285b..835db99 100644 --- a/completions/_nmcli +++ b/completions/_nmcli @@ -3,83 +3,76 @@ # Use of this file is deprecated. Upstream completion is available in # NetworkManager >= 0.9.8.0, use that instead. -_nmcli_list() +_comp_cmd_nmcli__con_id() { - COMPREPLY=($(compgen -W '$1' -- "$cur")) + _comp_compgen_split -l -- "$(nmcli con list 2>/dev/null | + tail -n +2 | _comp_awk -F ' {2,}' '{print $1}')" } -_nmcli_con_id() +_comp_cmd_nmcli__con_uuid() { - local IFS=$'\n' - COMPREPLY=($(compgen -W "$(nmcli con list 2>/dev/null | - tail -n +2 | awk -F ' {2,}' '{print $1 }')" -- "$cur")) + _comp_compgen_split -- "$(nmcli con list 2>/dev/null | + tail -n +2 | _comp_awk -F ' {2,}' '{print $2}')" } -_nmcli_con_uuid() +_comp_cmd_nmcli__ap_ssid() { - COMPREPLY=($(compgen -W "$(nmcli con list 2>/dev/null | - tail -n +2 | awk -F ' {2,}' '{print $2}')" -- "$cur")) + _comp_compgen_split -l -- "$(nmcli dev wifi list 2>/dev/null | + tail -n +2 | _comp_awk -F ' {2,}' '{print $1}')" } -_nmcli_ap_ssid() +_comp_cmd_nmcli__ap_bssid() { - local IFS=$'\n' - COMPREPLY=($(compgen -W "$(nmcli dev wifi list 2>/dev/null | - tail -n +2 | awk -F ' {2,}' '{print $1}')" -- "$cur")) + _comp_compgen_split -- "$(nmcli dev wifi list 2>/dev/null | + tail -n +2 | _comp_awk -F ' {2,}' '{print $2}')" } -_nmcli_ab_bssid() +_comp_cmd_nmcli() { - COMPREPLY=($(compgen -W "$(nmcli dev wifi list 2>/dev/null | - tail -n +2 | awk -F ' {2,}' '{print $2}')" -- "$cur")) -} - -_nmcli() -{ - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -m | --mode) - COMPREPLY=($(compgen -W 'tabular multiline' -- "$cur")) + _comp_compgen -- -W 'tabular multiline' return ;; -f | --fields) - COMPREPLY=($(compgen -W 'all common' -- "$cur")) + _comp_compgen -- -W 'all common' return ;; -e | --escape) - _nmcli_list "yes no" + _comp_compgen -- -W "yes no" return ;; id) - _nmcli_con_id + _comp_cmd_nmcli__con_id return ;; uuid) - _nmcli_con_uuid + _comp_cmd_nmcli__con_uuid return ;; iface) - _available_interfaces + _comp_compgen_available_interfaces return ;; bssid) - _nmcli_ab_bssid + _comp_cmd_nmcli__ap_bssid return ;; wep-key-type) - _nmcli_list "key phrase" + _comp_compgen -- -W "key phrase" return ;; esac if ((cword == 1)); then if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--terse --pretty --mode --fields - --escape --version --help' -- "$cur")) + _comp_compgen -- -W '--terse --pretty --mode --fields --escape + --version --help' else - COMPREPLY=($(compgen -W "nm con dev" -- "$cur")) + _comp_compgen -- -W "nm con dev" fi else local object=${words[1]} @@ -89,71 +82,67 @@ _nmcli() nm) case $command in enable) - _nmcli_list "true false" + _comp_compgen -- -W "true false" return ;; sleep) - _nmcli_list "true false" + _comp_compgen -- -W "true false" return ;; wifi) - _nmcli_list "on off" + _comp_compgen -- -W "on off" return ;; wwan) - _nmcli_list "on off" + _comp_compgen -- -W "on off" return ;; wimax) - _nmcli_list "on off" + _comp_compgen -- -W "on off" return ;; esac - COMPREPLY=($(compgen -W 'status permissions enable sleep - wifi wwan wimax' -- "$cur")) + _comp_compgen -- -W 'status permissions enable sleep wifi wwan + wimax' ;; con) case $command in list) - COMPREPLY=($(compgen -W 'id uuid' -- "$cur")) + _comp_compgen -- -W 'id uuid' return ;; up) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--nowait --timeout' \ - -- "$cur")) + _comp_compgen -- -W '--nowait --timeout' else - COMPREPLY=($(compgen -W 'id uuid iface ap nsp' \ - -- "$cur")) + _comp_compgen -- -W 'id uuid iface ap nsp' fi return ;; down) - COMPREPLY=($(compgen -W 'id uuid' -- "$cur")) + _comp_compgen -- -W 'id uuid' return ;; delete) - COMPREPLY=($(compgen -W 'id uuid' -- "$cur")) + _comp_compgen -- -W 'id uuid' return ;; esac - COMPREPLY=($(compgen -W 'list status up down delete' \ - -- "$cur")) + _comp_compgen -- -W 'list status up down delete' ;; dev) case $command in list) - COMPREPLY=($(compgen -W 'iface' -- "$cur")) + _comp_compgen -- -W 'iface' return ;; disconnect) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--nowait --timeout' \ - -- "$cur")) + _comp_compgen -- -W '--nowait --timeout' else - COMPREPLY=($(compgen -W 'iface' -- "$cur")) + _comp_compgen -- -W 'iface' fi return ;; @@ -162,40 +151,37 @@ _nmcli() case $subcommand in list) - COMPREPLY=($(compgen -W 'iface bssid' \ - -- "$cur")) + _comp_compgen -- -W 'iface bssid' return ;; connect) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--private - --nowait --timeout' -- "$cur")) + _comp_compgen -- -W '--private --nowait + --timeout' else if [[ $prev == "connect" ]]; then - _nmcli_ap_ssid + _comp_cmd_nmcli__ap_ssid else - COMPREPLY=($(compgen -W 'password - wep-key-type iface bssid name' \ - -- "$cur")) + _comp_compgen -- -W 'password + wep-key-type iface bssid name' fi fi return ;; esac - COMPREPLY=($(compgen -W 'list connect' -- "$cur")) + _comp_compgen -- -W 'list connect' return ;; esac - COMPREPLY=($(compgen -W 'status list disconnect wifi' \ - -- "$cur")) + _comp_compgen -- -W 'status list disconnect wifi' ;; esac fi } && - complete -F _nmcli nmcli + complete -F _comp_cmd_nmcli nmcli # ex: filetype=sh diff --git a/completions/_nox b/completions/_nox new file mode 100644 index 0000000..40b8bb1 --- /dev/null +++ b/completions/_nox @@ -0,0 +1,13 @@ +# 3rd party completion loader for argcomplete commands -*- shell-script -*- +# sourced using no args to `register-python-argcomplete`. +# +# This serves as a fallback in case the completion is not installed otherwise. + +eval -- "$( + bin_path=$(type -P "$1" 2>/dev/null | command sed 's,/[^/]*$,,') + [[ $bin_path ]] && PATH=$bin_path${PATH:+:$PATH} + register-python-argcomplete --shell bash "$1" 2>/dev/null || + register-python-argcomplete3 --shell bash "$1" 2>/dev/null +)" + +# ex: filetype=sh diff --git a/completions/_nvm b/completions/_nvm new file mode 100644 index 0000000..e5c2a46 --- /dev/null +++ b/completions/_nvm @@ -0,0 +1,8 @@ +# 3rd party completion loader for nvm -*- shell-script -*- +# +# This serves as a fallback in case the completion is not installed otherwise. + +# shellcheck disable=SC1091 +[[ ${NVM_DIR-} && -r $NVM_DIR/bash_completion ]] && . "$NVM_DIR"/bash_completion + +# ex: filetype=sh diff --git a/completions/_pip b/completions/_pip new file mode 100644 index 0000000..4439aa7 --- /dev/null +++ b/completions/_pip @@ -0,0 +1,9 @@ +# 3rd party completion loader for commands emitting -*- shell-script -*- +# their completion using "$cmd completion --bash". For example, pip uses this +# form of dynamic completions. +# +# This serves as a fallback in case the completion is not installed otherwise. + +eval -- "$("$1" completion --bash 2>/dev/null)" + +# ex: filetype=sh diff --git a/completions/_pipenv b/completions/_pipenv new file mode 100644 index 0000000..e6d2df6 --- /dev/null +++ b/completions/_pipenv @@ -0,0 +1,15 @@ +# 3rd party completion loader for commands emitting -*- shell-script -*- +# their completion using "_${cmdname^^}_COMPLETE=bash_source $cmd". +# This pattern is used by programs built with https://click.palletsprojects.com +# +# This serves as a fallback in case the completion is not installed otherwise. + +eval -- "$( + # shellcheck disable=SC2154 + ucname="${cmdname^^}" + ucname=${ucname//-/_} + export "_${ucname}_COMPLETE=bash_source" + "$1" 2>/dev/null +)" + +# ex: filetype=sh diff --git a/completions/_renice b/completions/_renice index a416744..06811ed 100644 --- a/completions/_renice +++ b/completions/_renice @@ -3,10 +3,10 @@ # Use of this file is deprecated on Linux. Upstream completion is # available in util-linux >= 2.23, use that instead. -_renice() +_comp_cmd_renice() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local command=$1 curopt i=0 @@ -15,18 +15,18 @@ _renice() curopt=${words[cword - i]} case "$curopt" in -u) - _allowed_users + _comp_compgen_allowed_users ;; -g) - _pgids + _comp_compgen_pgids ;; -p | "$command") - _pids + _comp_compgen_pids ;; esac ((i++)) done } && - complete -F _renice renice + complete -F _comp_cmd_renice renice # ex: filetype=sh diff --git a/completions/_repomanage b/completions/_repomanage index ba0787e..3a7c5ad 100644 --- a/completions/_repomanage +++ b/completions/_repomanage @@ -3,22 +3,22 @@ # Use of this file is deprecated. Upstream completion is available in # yum-utils >= 1.1.24, use that instead. -_repomanage() +_comp_cmd_repomanage() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return [[ $prev == -@([hk]|-help|-keep) ]] && return - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - _filedir -d + _comp_compgen_filedir -d fi } && - complete -F _repomanage repomanage + complete -F _comp_cmd_repomanage repomanage # ex: filetype=sh diff --git a/completions/_reptyr b/completions/_reptyr index 01d61b2..266a545 100644 --- a/completions/_reptyr +++ b/completions/_reptyr @@ -3,10 +3,10 @@ # Use of this file is deprecated. Upstream completion is available in # reptyr > 0.6.2, use that instead. -_reptyr() +_comp_cmd_reptyr() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -l) @@ -15,12 +15,12 @@ _reptyr() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - [[ $prev != +([0-9]) ]] && _pids + [[ $prev != +([0-9]) ]] && _comp_compgen_pids } && - complete -F _reptyr reptyr + complete -F _comp_cmd_reptyr reptyr # ex: filetype=sh diff --git a/completions/_rfkill b/completions/_rfkill index 96a6c09..c4733e7 100644 --- a/completions/_rfkill +++ b/completions/_rfkill @@ -3,29 +3,28 @@ # Use of this file is deprecated on systems with util-linux >= 2.31, which # ships completion for the rfkill included with it. -_rfkill() +_comp_cmd_rfkill() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--version' -- "$cur")) + _comp_compgen -- -W '--version' else case $cword in 1) - COMPREPLY=($(compgen -W "help event list block unblock" \ - -- "$cur")) + _comp_compgen -- -W "help event list block unblock" ;; 2) if [[ $prev == block || $prev == unblock ]]; then - COMPREPLY=($(compgen -W "$($1 list | awk -F: \ - '/^[0-9]/ {print $1}') all wifi bluetooth uwb wimax \ - wwan gps" -- "$cur")) + _comp_compgen_split -- " + $("$1" list | _comp_awk -F : '/^[0-9]/ {print $1}') + all wifi bluetooth uwb wimax wwan gps" fi ;; esac fi } && - complete -F _rfkill rfkill + complete -F _comp_cmd_rfkill rfkill # ex: filetype=sh diff --git a/completions/_rtcwake b/completions/_rtcwake index 4ca452d..535079e 100644 --- a/completions/_rtcwake +++ b/completions/_rtcwake @@ -3,30 +3,30 @@ # Use of this file is deprecated. Upstream completion is available in # util-linux >= 2.23, use that instead. -_rtcwake() +_comp_cmd_rtcwake() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case "$prev" in --help | -h | --version | -V | --seconds | -s | --time | -t) return ;; --mode | -m) - COMPREPLY=($(compgen -W 'standby mem disk on no off' -- "$cur")) + _comp_compgen -- -W 'standby mem disk on no off' return ;; --device | -d) - COMPREPLY=($(command ls -d /dev/rtc?* 2>/dev/null)) - COMPREPLY=($(compgen -W '${COMPREPLY[@]#/dev/}' -- "$cur")) + _comp_expand_glob COMPREPLY '/dev/rtc?*' && + _comp_compgen -- -W '"${COMPREPLY[@]#/dev/}"' return ;; esac - $split && return + [[ $was_split ]] && return - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help } && - complete -F _rtcwake rtcwake + complete -F _comp_cmd_rtcwake rtcwake # ex: filetype=sh diff --git a/completions/_ruff b/completions/_ruff new file mode 100644 index 0000000..b5fd1a5 --- /dev/null +++ b/completions/_ruff @@ -0,0 +1,8 @@ +# 3rd party completion loader for commands emitting -*- shell-script -*- +# their completion using "$cmd generate-shell-completion bash". +# +# This serves as a fallback in case the completion is not installed otherwise. + +eval -- "$("$1" generate-shell-completion bash 2>/dev/null)" + +# ex: filetype=sh diff --git a/completions/_rustup b/completions/_rustup new file mode 100644 index 0000000..1bcf44d --- /dev/null +++ b/completions/_rustup @@ -0,0 +1,7 @@ +# 3rd party completion loader for rustup -*- shell-script -*- +# +# This serves as a fallback in case the completion is not installed otherwise. + +eval -- "$("$1" completions bash rustup 2>/dev/null)" + +# ex: filetype=sh diff --git a/completions/_slackpkg b/completions/_slackpkg new file mode 100644 index 0000000..f8f7810 --- /dev/null +++ b/completions/_slackpkg @@ -0,0 +1,111 @@ +# bash completion for slackpkg(8) -*- shell-script -*- +# options list is based on `grep '\-.*\=.*)' /usr/sbin/slackpkg | cut -f1 -d\)` + +# Use of this file is deprecated. +# Upstream completion is available in slackpkg >= 15.0.4, use that instead. + +_comp_cmd_slackpkg() +{ + local cur prev words cword comp_args + _comp_initialize -n = -- "$@" || return + + local split="" + if [[ $cur == -?*=* ]]; then + prev="${cur%%?(\\)=*}" + cur="${cur#*=}" + split=set + fi + + case "$prev" in + -delall | -checkmd5 | -checkgpg | -checksize | -postinst | -onoff | \ + -download_all | -dialog | -batch | -only_new_dotnew | \ + -use_includes | -spinning) + _comp_compgen -- -W 'on off' + return + ;; + -default_answer) + _comp_compgen -- -W 'yes no' + return + ;; + -dialog_maxargs | -mirror) + # argument required but no completions available + return + ;; + esac + + [[ $split ]] && return + + if [[ $cur == -* ]]; then + compopt -o nospace + _comp_compgen -- -W '-delall= -checkmd5= -checkgpg= -checksize= + -postinst= -onoff= -download_all= -dialog= -dialog_maxargs= -batch= + -only_new_dotnew= -use_includes= -spinning= -default_answer= + -mirror=' + return + fi + + local confdir="/etc/slackpkg" + local config="$confdir/slackpkg.conf" + + [[ -r $config ]] || return + . "$config" + + local i action + for ((i = 1; i < cword; i++)); do + if [[ ${words[i]} != -* ]]; then + action="${words[i]}" + break + fi + done + + case "$action" in + generate-template | search | file-search) + # argument required but no completions available + return + ;; + install-template | remove-template) + if [[ -e $confdir/templates ]]; then + _comp_compgen -C "$confdir/templates" -- -f -X \ + "!?*.template" && COMPREPLY=("${COMPREPLY[@]%.template}") + fi + return + ;; + remove) + _comp_compgen_filedir + _comp_compgen -a -- -W 'a ap d e f k kde kdei l n t tcl x xap xfce + y' + _comp_compgen -aC /var/log/packages -- -f + return + ;; + install | reinstall | upgrade | blacklist | download) + _comp_compgen_filedir + _comp_compgen -a -- -W 'a ap d e f k kde kdei l n t tcl x xap xfce + y' + _comp_compgen -a split -l -- "$( + cut -f 6 -d\ "${WORKDIR}/pkglist" 2>/dev/null + )" + return + ;; + info) + _comp_compgen_split "$( + cut -f 6 -d\ "${WORKDIR}/pkglist" 2>/dev/null + )" + return + ;; + update) + # we should complete the same as the next `list` + "gpg" + _comp_compgen -- -W 'gpg' + ;& + *) + _comp_compgen -a -- -W 'install reinstall upgrade remove blacklist + download update install-new upgrade-all clean-system new-config + check-updates help generate-template install-template + remove-template search file-search info' + return + ;; + esac + +} && + complete -F _comp_cmd_slackpkg slackpkg + +# ex: filetype=sh diff --git a/completions/_su b/completions/_su index 1a03c8f..3354447 100644 --- a/completions/_su +++ b/completions/_su @@ -8,34 +8,32 @@ if [[ $OSTYPE != *linux* ]]; then return fi -_su() +_comp_cmd_su() { # linux-specific completion - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case "$prev" in -s | --shell) - _shells + _comp_compgen_shells return ;; -c | --command | --session-command) - local IFS=$'\n' - compopt -o filenames - COMPREPLY=($(compgen -d -c -- "$cur")) + _comp_compgen_commands return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" --help)' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u } && - complete -F _su su + complete -F _comp_cmd_su su # ex: filetype=sh diff --git a/completions/_svn b/completions/_svn index 5d85c2b..862b62c 100644 --- a/completions/_svn +++ b/completions/_svn @@ -3,10 +3,10 @@ # Use of this file is deprecated. Upstream completion is available in # subversion >= 0.12.0, use that instead. -_svn() +_comp_cmd_svn() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local commands commands='add blame praise annotate ann cat checkout co cleanup commit \ @@ -18,28 +18,27 @@ _svn() if ((cword == 1)); then if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--version' -- "$cur")) + _comp_compgen -- -W '--version' else - COMPREPLY=($(compgen -W "$commands" -- "$cur")) + _comp_compgen -- -W "$commands" fi else case $prev in --config-dir) - _filedir -d + _comp_compgen_filedir -d return ;; -F | --file | --targets) - _filedir + _comp_compgen_filedir return ;; --encoding) - _xfunc iconv _iconv_charsets + _comp_compgen -x iconv charsets return ;; --editor-cmd | --diff-cmd | --diff3-cmd) - compopt -o filenames - COMPREPLY=($(compgen -c -- "$cur")) + _comp_compgen_commands return ;; esac @@ -194,17 +193,17 @@ _svn() esac options+=" --help --config-dir" - COMPREPLY=($(compgen -W "$options" -- "$cur")) + _comp_compgen -- -W "$options" else if [[ $command == @(help|[h?]) ]]; then - COMPREPLY=($(compgen -W "$commands" -- "$cur")) + _comp_compgen -- -W "$commands" else - _filedir + _comp_compgen_filedir fi fi fi } && - complete -F _svn svn + complete -F _comp_cmd_svn svn # ex: filetype=sh diff --git a/completions/_svnadmin b/completions/_svnadmin index 654fd3e..6b4a423 100644 --- a/completions/_svnadmin +++ b/completions/_svnadmin @@ -3,10 +3,10 @@ # Use of this file is deprecated. Upstream completion is available in # subversion >= 0.12.0, use that instead. -_svnadmin() +_comp_cmd_svnadmin() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local commands commands='create deltify dump help ? hotcopy list-dblogs list-unused-dblogs @@ -14,18 +14,18 @@ _svnadmin() if ((cword == 1)); then if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--version' -- "$cur")) + _comp_compgen -- -W '--version' else - COMPREPLY=($(compgen -W "$commands" -- "$cur")) + _comp_compgen -- -W "$commands" fi else case $prev in --config-dir) - _filedir -d + _comp_compgen_filedir -d return ;; --fs-type) - COMPREPLY=($(compgen -W 'fsfs bdb' -- "$cur")) + _comp_compgen -- -W 'fsfs bdb' return ;; esac @@ -62,17 +62,17 @@ _svnadmin() esac options+=" --help" - COMPREPLY=($(compgen -W "$options" -- "$cur")) + _comp_compgen -- -W "$options" else if [[ $command == @(help|[h?]) ]]; then - COMPREPLY=($(compgen -W "$commands" -- "$cur")) + _comp_compgen -- -W "$commands" else - _filedir + _comp_compgen_filedir fi fi fi } && - complete -F _svnadmin -o default svnadmin + complete -F _comp_cmd_svnadmin -o default svnadmin # ex: filetype=sh diff --git a/completions/_svnlook b/completions/_svnlook index 36188a5..f0c01df 100644 --- a/completions/_svnlook +++ b/completions/_svnlook @@ -3,10 +3,10 @@ # Use of this file is deprecated. Upstream completion is available in # subversion >= 0.12.0, use that instead. -_svnlook() +_comp_cmd_svnlook() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local commands commands='author cat changed date diff dirs-changed help ? h history info @@ -14,9 +14,9 @@ _svnlook() if ((cword == 1)); then if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--version' -- "$cur")) + _comp_compgen -- -W '--version' else - COMPREPLY=($(compgen -W "$commands" -- "$cur")) + _comp_compgen -- -W "$commands" fi else local command=${words[1]} @@ -47,17 +47,17 @@ _svnlook() esac options+=" --help" - COMPREPLY=($(compgen -W "$options" -- "$cur")) + _comp_compgen -- -W "$options" else if [[ $command == @(help|[h?]) ]]; then - COMPREPLY=($(compgen -W "$commands" -- "$cur")) + _comp_compgen -- -W "$commands" else - _filedir + _comp_compgen_filedir fi fi fi } && - complete -F _svnlook -o default svnlook + complete -F _comp_cmd_svnlook -o default svnlook # ex: filetype=sh diff --git a/completions/_tokio-console b/completions/_tokio-console new file mode 100644 index 0000000..c170044 --- /dev/null +++ b/completions/_tokio-console @@ -0,0 +1,8 @@ +# 3rd party completion loader for commands emitting -*- shell-script -*- +# their completion using "$cmd gen-completion bash". +# +# This serves as a fallback in case the completion is not installed otherwise. + +eval -- "$("$1" gen-completion bash 2>/dev/null)" + +# ex: filetype=sh diff --git a/completions/_udevadm b/completions/_udevadm index 19624be..6a3c351 100644 --- a/completions/_udevadm +++ b/completions/_udevadm @@ -3,75 +3,73 @@ # Use of this file is deprecated. Upstream completion is available in # systemd >= 196, use that instead. -_udevadm() +_comp_cmd_udevadm() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return - local i udevcmd + local i udevcmd="" has_udevcmd="" for ((i = 1; i < cword; i++)); do if [[ ${words[i]} != -* ]]; then udevcmd=${words[i]} + has_udevcmd=set break fi done case $prev in - --help | --version | --property | --children-max | --timeout | --seq-start | \ - --seq-end | --attr-match | --attr-nomatch | --parent-match | --property-match | \ - --tag-match | --subsystem-match | --subsystem-nomatch | --sysname-match | \ - --path) + --help | --version | --property | --children-max | --timeout | \ + --seq-start | --seq-end | --attr-match | --attr-nomatch | \ + --parent-match | --property-match | --tag-match | \ + --subsystem-match | --subsystem-nomatch | --sysname-match | --path) return ;; --log-priority) - COMPREPLY=($(compgen -W 'err info debug' -- "$cur")) + _comp_compgen -- -W 'err info debug' return ;; --query) - COMPREPLY=($(compgen -W 'name symlink path property all' \ - -- "$cur")) + _comp_compgen -- -W 'name symlink path property all' return ;; --name) - cur=${cur:=/dev/} - _filedir + _comp_compgen -c "${cur:-/dev/}" filedir return ;; --device-id-of-file | --exit-if-exists) - _filedir + _comp_compgen_filedir return ;; --action) - COMPREPLY=($(compgen -W 'add change remove' -- "$cur")) + _comp_compgen -- -W 'add change remove' return ;; --type) - COMPREPLY=($(compgen -W 'devices subsystems failed' -- "$cur")) + _comp_compgen -- -W 'devices subsystems failed' return ;; esac - $split && return + [[ $was_split ]] && return - if [[ ! -v udevcmd ]]; then + if [[ ! $has_udevcmd ]]; then case $cur in -*) - COMPREPLY=($(compgen -W '--help --version --debug' -- "$cur")) + _comp_compgen -- -W '--help --version --debug' ;; *) - COMPREPLY=($(compgen -W "$("$1" --help 2>/dev/null | - awk '/^[ \t]/ { print $1 }')" -- "$cur")) + _comp_compgen_split -- "$("$1" --help 2>/dev/null | + _comp_awk '/^[ \t]/ { print $1 }')" ;; esac return fi if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W \ - '$("$1" ${udevcmd-} --help 2>/dev/null | _parse_help -)' -- "$cur")) + _comp_compgen_help -- ${has_udevcmd:+"$udevcmd"} --help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _udevadm udevadm + complete -F _comp_cmd_udevadm udevadm # ex: filetype=sh diff --git a/completions/_umount b/completions/_umount index 36d5703..5a453a8 100644 --- a/completions/_umount +++ b/completions/_umount @@ -11,14 +11,13 @@ fi # umount(8) completion. This relies on the mount point being the third # space-delimited field in the output of mount(8) # -_umount() +_comp_cmd_umount() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - local IFS=$'\n' - COMPREPLY=($(compgen -W '$(mount | cut -d" " -f 3)' -- "$cur")) + _comp_compgen_split -l -- "$(mount | cut -d" " -f 3)" } && - complete -F _umount -o dirnames umount + complete -F _comp_cmd_umount -o dirnames umount # ex: filetype=sh diff --git a/completions/_umount.linux b/completions/_umount.linux index cf8a259..ca515c8 100644 --- a/completions/_umount.linux +++ b/completions/_umount.linux @@ -6,7 +6,7 @@ # Just like COMPREPLY=(`compgen -W "${COMPREPLY[*]}" -- "$cur"`), only better! # # This will correctly escape special characters in COMPREPLY. -_reply_compgen_array() +_comp_cmd_umount__reply_compgen_array() { # Create the argument for compgen -W by escaping twice. # @@ -15,8 +15,10 @@ _reply_compgen_array() # argument. local i wlist for i in ${!COMPREPLY[*]}; do - local q=$(quote "$(printf %q "${COMPREPLY[i]}")") - wlist+=$q$'\n' + local REPLY + printf -v REPLY %q "${COMPREPLY[i]}" + _comp_quote "$REPLY" + wlist+=$REPLY$'\n' done # We also have to add another round of escaping to $cur. @@ -25,16 +27,14 @@ _reply_compgen_array() ecur=${ecur//\'/\\\'} # Actually generate completions. - local ifs=$IFS - IFS=$'\n' eval 'COMPREPLY=(`compgen -W "$wlist" -- "${ecur}"`)' - IFS=$ifs + _comp_compgen -lc "${ecur}" -- -W "$wlist" } # Unescape strings in the linux fstab(5) format (with octal escapes). -__linux_fstab_unescape() +_comp_cmd_umount__linux_fstab_unescape() { - eval $1="'${!1//\'/\\047}'" - eval $1="'${!1/%\\/\\\\}'" + eval "$1='${!1//\'/\\047}'" + eval "$1='${!1/%\\/\\\\}'" eval "$1=$'${!1}'" } @@ -43,30 +43,25 @@ __linux_fstab_unescape() # Reads a file from stdin in the linux fstab(5) format; as used by /etc/fstab # and /proc/mounts. With 1st arg -L, look for entries by label. # shellcheck disable=SC2120 -_linux_fstab() +_comp_cmd_umount__linux_fstab() { COMPREPLY=() # Read and unescape values into COMPREPLY local fs_spec fs_file fs_other - local ifs="$IFS" while read -r fs_spec fs_file fs_other; do if [[ $fs_spec == [#]* ]]; then continue; fi if [[ ${1-} == -L ]]; then local fs_label=${fs_spec/#LABEL=/} if [[ $fs_label != "$fs_spec" ]]; then - __linux_fstab_unescape fs_label - IFS=$'\0' + _comp_cmd_umount__linux_fstab_unescape fs_label COMPREPLY+=("$fs_label") - IFS=$ifs fi else - __linux_fstab_unescape fs_spec - __linux_fstab_unescape fs_file - IFS=$'\0' + _comp_cmd_umount__linux_fstab_unescape fs_spec + _comp_cmd_umount__linux_fstab_unescape fs_file [[ $fs_spec == */* ]] && COMPREPLY+=("$fs_spec") [[ $fs_file == */* ]] && COMPREPLY+=("$fs_file") - IFS=$ifs fi done @@ -86,37 +81,37 @@ _linux_fstab() local i for i in ${!COMPREPLY[*]}; do [[ ${COMPREPLY[i]} == "$realcur"* ]] && - COMPREPLY+=($(cd "$dircur" 2>/dev/null && - compgen -f -d -P "$dircur" \ - -X "!${COMPREPLY[i]##"$dirrealcur"}" -- "$basecur")) + _comp_compgen -aC "$dircur" -c "$basecur" -- \ + -f -d -P "$dircur" -X "!${COMPREPLY[i]##"$dirrealcur"}" done fi fi - _reply_compgen_array + _comp_cmd_umount__reply_compgen_array } -_umount() +_comp_cmd_umount() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case "$prev" in -t) # FIXME: no<fstype> - local split=false + local split="" if [[ $cur == ?*,* ]]; then prev="${cur%,*}" cur="${cur##*,}" - split=true + split=set fi - COMPREPLY=($(compgen -W 'adfs affs autofs btrfs cifs coda - cramfs debugfs devpts efs ext2 ext3 ext4 fuse hfs hfsplus hpfs - iso9660 jfs minix msdos ncpfs nfs nfs4 ntfs ntfs-3g proc qnx4 - ramfs reiserfs romfs squashfs smbfs sysv tmpfs ubifs udf ufs - umsdos usbfs vfat xfs' -- "$cur")) - _fstypes - $split && COMPREPLY=(${COMPREPLY[@]/#/$prev,}) + _comp_compgen -- -W 'adfs affs autofs btrfs cifs coda cramfs + debugfs devpts efs ext2 ext3 ext4 fuse hfs hfsplus hpfs iso9660 + jfs minix msdos ncpfs nfs nfs4 ntfs ntfs-3g proc qnx4 ramfs + reiserfs romfs squashfs smbfs sysv tmpfs ubifs udf ufs umsdos + usbfs vfat xfs' + _comp_compgen -a fstypes + [[ $split ]] && ((${#COMPREPLY[@]})) && + _comp_compgen -Rv COMPREPLY -- -P "$prev," -W '"${COMPREPLY[@]}"' return ;; -O) @@ -126,20 +121,19 @@ _umount() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-V -h -v -n -r -d -i -a -t -O -f -l - --no-canonicalize --fake' -- "$cur")) + _comp_compgen -- -W '-V -h -v -n -r -d -i -a -t -O -f -l + --no-canonicalize --fake' [[ ${COMPREPLY-} ]] && return fi if [[ -r /proc/mounts ]]; then # Linux /proc/mounts is properly quoted. This is important when # unmounting usb devices with pretty names. - _linux_fstab </proc/mounts + _comp_cmd_umount__linux_fstab </proc/mounts else - local IFS=$'\n' - COMPREPLY=($(compgen -W '$(mount | cut -d" " -f 3)' -- "$cur")) + _comp_compgen_split -l -- "$(mount | cut -d" " -f 3)" fi } && - complete -F _umount -o dirnames umount + complete -F _comp_cmd_umount -o dirnames umount # ex: filetype=sh diff --git a/completions/_vault b/completions/_vault new file mode 100644 index 0000000..25abbc2 --- /dev/null +++ b/completions/_vault @@ -0,0 +1,8 @@ +# 3rd party completion loader for commands -*- shell-script -*- +# supporting their use of as a `complete -C` handler. +# +# This serves as a fallback in case the completion is not installed otherwise. + +type "$1" &>/dev/null && complete -C "\"$1\" 2>/dev/null" "$1" + +# ex: filetype=sh diff --git a/completions/_xm b/completions/_xm index 06b25d3..7577efd 100644 --- a/completions/_xm +++ b/completions/_xm @@ -4,26 +4,20 @@ # provided by upstream. It has been replaced with the 'xl' command, for # which upstream provides completion, use that instead. -_xen_domain_names() +_comp_cmd_xm__domain_names() { - COMPREPLY=($(compgen -W "$(xm list 2>/dev/null | - awk '!/Name|Domain-0/ { print $1 }')" -- "$cur")) + _comp_compgen_split -- "$(xm list 2>/dev/null | + _comp_awk '!/Name|Domain-0/ { print $1 }')" } -_xen_domain_ids() +_comp_cmd_xm() { - COMPREPLY=($(compgen -W "$(xm list 2>/dev/null | - awk '!/Name|Domain-0/ { print $2 }')" -- "$cur")) -} - -_xm() -{ - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - # TODO: _split_longopt + # TODO: split longopt - local args command commands options + local REPLY command commands options commands='console vncviewer create new delete destroy domid domname dump-core list mem-max mem-set migrate pause reboot rename reset @@ -37,7 +31,7 @@ _xm() resetpolicy getpolicy shell help' if ((cword == 1)); then - COMPREPLY=($(compgen -W "$commands" -- "$cur")) + _comp_compgen -- -W "$commands" else if [[ $cur == *=* ]]; then prev=${cur/=*/} @@ -78,140 +72,139 @@ _xm() -s --skipdtd -p --paused -c --console_autoconnect' ;; esac - COMPREPLY=($(compgen -W "$options" -- "$cur")) + _comp_compgen -- -W "$options" else case $command in - console | destroy | domname | domid | list | mem-set | mem-max | \ - pause | reboot | rename | shutdown | unpause | vcpu-list | vcpu-pin | \ - vcpu-set | block-list | network-list | vtpm-list) - _count_args - case $args in + console | destroy | domname | domid | list | mem-set | \ + mem-max | pause | reboot | rename | shutdown | unpause | \ + vcpu-list | vcpu-pin | vcpu-set | block-list | \ + network-list | vtpm-list) + _comp_count_args + case $REPLY in 2) - _xen_domain_names + _comp_cmd_xm__domain_names ;; esac ;; migrate) - _count_args - case $args in + _comp_count_args + case $REPLY in 2) - _xen_domain_names + _comp_cmd_xm__domain_names ;; 3) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" ;; esac ;; restore | dry-run | vnet-create) - _filedir + _comp_compgen_filedir ;; save) - _count_args - case $args in + _comp_count_args + case $REPLY in 2) - _xen_domain_names + _comp_cmd_xm__domain_names ;; 3) - _filedir + _comp_compgen_filedir ;; esac ;; sysrq) - _count_args - case $args in + _comp_count_args + case $REPLY in 2) - _xen_domain_names + _comp_cmd_xm__domain_names ;; 3) - COMPREPLY=($(compgen -W "r s e i u b" -- "$cur")) + _comp_compgen -- -W "r s e i u b" ;; esac ;; block-attach) - _count_args - case $args in + _comp_count_args + case $REPLY in 2) - _xen_domain_names + _comp_cmd_xm__domain_names ;; 3) - COMPREPLY=($(compgen -W "phy: file:" -- "$cur")) + _comp_compgen -- -W "phy: file:" ;; 5) - COMPREPLY=($(compgen -W "w r" -- "$cur")) + _comp_compgen -- -W "w r" ;; 6) - _xen_domain_names + _comp_cmd_xm__domain_names ;; esac ;; block-detach) - _count_args - case $args in + _comp_count_args + case $REPLY in 2) - _xen_domain_names + _comp_cmd_xm__domain_names ;; 3) - COMPREPLY=($(compgen -W "$(xm block-list $prev \ - 2>/dev/null | awk '!/Vdev/ { print $1 }')" \ - -- "$cur")) + _comp_compgen_split -- "$(xm block-list "$prev" \ + 2>/dev/null | _comp_awk '!/Vdev/ { print $1 }')" ;; esac ;; network-attach) - _count_args - case $args in + _comp_count_args + case $REPLY in 2) - _xen_domain_names + _comp_cmd_xm__domain_names ;; *) - COMPREPLY=($(compgen -W "script= ip= mac= bridge= - backend=" -- "$cur")) + _comp_compgen -- -W "script= ip= mac= bridge= + backend=" ;; esac ;; network-detach) - _count_args - case $args in + _comp_count_args + case $REPLY in 2) - _xen_domain_names + _comp_cmd_xm__domain_names ;; 3) - COMPREPLY=($(compgen -W "$(xm network-list $prev \ - 2>/dev/null | awk '!/Idx/ { print $1 }')" \ - -- "$cur")) + _comp_compgen_split -- "$(xm network-list "$prev" \ + 2>/dev/null | _comp_awk '!/Idx/ { print $1 }')" ;; esac ;; sched-credit) case $prev in -d) - _xen_domain_names + _comp_cmd_xm__domain_names return ;; esac ;; create) - _filedir - COMPREPLY+=( - $(compgen -W '$(command ls /etc/xen 2>/dev/null)' \ - -- "$cur")) + _comp_compgen_filedir + _comp_compgen -a split -- "$( + command ls /etc/xen 2>/dev/null + )" ;; new) case $prev in -f | -F | --defconfig | --config) - _filedir + _comp_compgen_filedir return ;; --path) - _filedir -d + _comp_compgen_filedir -d return ;; esac - _count_args - case $args in + _comp_count_args + case $REPLY in 2) - _xen_domain_names + _comp_cmd_xm__domain_names ;; esac ;; @@ -219,6 +212,6 @@ _xm() fi fi } && - complete -F _xm xm + complete -F _comp_cmd_xm xm # ex: filetype=sh diff --git a/completions/_yq b/completions/_yq new file mode 100644 index 0000000..c357bd9 --- /dev/null +++ b/completions/_yq @@ -0,0 +1,8 @@ +# 3rd party completion loader for commands emitting -*- shell-script -*- +# their completion using "$cmd shell-completion bash". +# +# This serves as a fallback in case the completion is not installed otherwise. + +eval -- "$("$1" shell-completion bash 2>/dev/null)" + +# ex: filetype=sh diff --git a/completions/_yum b/completions/_yum index 224ea25..2899cb3 100644 --- a/completions/_yum +++ b/completions/_yum @@ -3,72 +3,79 @@ # Use of this file is deprecated. Upstream completion is available in # yum > 3.2.25, use that instead. -_yum_list() +_comp_cmd_yum__list() { if [[ $1 == all ]]; then # Try to strip in between headings like "Available Packages" # This will obviously only work for English :P - COMPREPLY=($(yum -d 0 -C list $1 "$cur*" 2>/dev/null | - command sed -ne '/^Available /d' -e '/^Installed /d' -e '/^Updated /d' \ - -e 's/[[:space:]].*//p')) + _comp_split COMPREPLY "$(yum -d 0 -C list "$1" "$cur*" 2>/dev/null | + command sed -ne '/^Available /d' -e '/^Installed /d' \ + -e '/^Updated /d' -e 's/[[:space:]].*//p')" else # Drop first line (e.g. "Updated Packages") - COMPREPLY=($(yum -d 0 -C list $1 "$cur*" 2>/dev/null | - command sed -ne 1d -e 's/[[:space:]].*//p')) + _comp_split COMPREPLY "$(yum -d 0 -C list "$1" "$cur*" 2>/dev/null | + command sed -ne 1d -e 's/[[:space:]].*//p')" fi } -_yum_repolist() +_comp_cmd_yum__compgen_repolist() { # -d 0 causes repolist to output nothing as of yum 3.2.22: # http://yum.baseurl.org/ticket/83 # Drop first ("repo id repo name") and last ("repolist: ...") rows - yum --noplugins -C repolist $1 2>/dev/null | - command sed -ne '/^repo\s\s*id/d' -e '/^repolist:/d' -e 's/[[:space:]].*//p' + _comp_compgen_split -- "$( + yum --noplugins -C repolist "$1" 2>/dev/null | + command sed -ne '/^repo[[:space:]]\{1,\}id/d' -e '/^repolist:/d' \ + -e 's/[[:space:]].*//p' + )" } -_yum_plugins() +_comp_cmd_yum__compgen_plugins() { - command ls /usr/lib/yum-plugins/*.py{,c,o} 2>/dev/null | - command sed -ne 's|.*/\([^./]*\)\.py[co]\{0,1\}$|\1|p' | sort -u + local -a files + _comp_expand_glob files '/usr/lib/yum-plugins/*.py{,c,o}' || return + _comp_compgen -U files split -- "$( + printf '%s\n' "${files[@]}" | + command sed -ne 's|.*/\([^./]*\)\.py[co]\{0,1\}$|\1|p' | sort -u + )" } -_yum() +_comp_cmd_yum() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return - local special i - for ((i = 1; i < ${#words[@]} - 1; i++)); do + local special="" i + for ((i = 1; i < cword; i++)); do if [[ ${words[i]} == @(install|update|upgrade|remove|erase|deplist|info) ]]; then special=${words[i]} break fi done - if [[ -v special ]]; then + if [[ $special ]]; then # TODO: install|update|upgrade should not match *src.rpm - if [[ $cur == @(*/|[.~])* && \ + if [[ $cur == @(*/|[.~])* && $special == @(deplist|install|update|upgrade) ]]; then - _filedir rpm + _comp_compgen_filedir rpm return fi case $special in install) - _yum_list available + _comp_cmd_yum__list available return ;; deplist | info) - _yum_list all + _comp_cmd_yum__list all return ;; upgrade | update) - _yum_list updates + _comp_cmd_yum__list updates return ;; remove | erase) - # _rpm_installed_packages is not arch-qualified - _yum_list installed + # _comp_xfunc_rpm_installed_packages is not arch-qualified + _comp_cmd_yum__list installed return ;; esac @@ -76,44 +83,43 @@ _yum() case $prev in list) - COMPREPLY=($(compgen -W 'all available updates installed extras - obsoletes recent' -- "$cur")) + _comp_compgen -- -W 'all available updates installed extras + obsoletes recent' ;; clean) - COMPREPLY=($(compgen -W 'packages headers metadata cache dbcache - all' -- "$cur")) + _comp_compgen -- -W 'packages headers metadata cache dbcache all' ;; repolist) - COMPREPLY=($(compgen -W 'all enabled disabled' -- "$cur")) + _comp_compgen -- -W 'all enabled disabled' ;; localinstall | localupdate) # TODO: should not match *src.rpm - _filedir rpm + _comp_compgen_filedir rpm ;; -d | -e) - COMPREPLY=($(compgen -W '{0..10}' -- "$cur")) + _comp_compgen -- -W '{0..10}' ;; -c) - _filedir + _comp_compgen_filedir ;; --installroot) - _filedir -d + _comp_compgen_filedir -d ;; --enablerepo) - COMPREPLY=($(compgen -W '$(_yum_repolist disabled)' -- "$cur")) + _comp_cmd_yum__compgen_repolist disabled ;; --disablerepo) - COMPREPLY=($(compgen -W '$(_yum_repolist enabled)' -- "$cur")) + _comp_cmd_yum__compgen_repolist enabled ;; --disableexcludes) - COMPREPLY=($(compgen -W '$(_yum_repolist all) all main' \ - -- "$cur")) + _comp_cmd_yum__compgen_repolist all + _comp_compgen -a -- -W "all main" ;; --enableplugin | --disableplugin) - COMPREPLY=($(compgen -W '$(_yum_plugins)' -- "$cur")) + _comp_cmd_yum__compgen_plugins ;; --color) - COMPREPLY=($(compgen -W 'always auto never' -- "$cur")) + _comp_compgen -- -W 'always auto never' ;; -R | -x | --exclude) # argument required but no completions available @@ -124,21 +130,21 @@ _yum() return ;; *) - COMPREPLY=($(compgen -W 'install update check-update upgrade - remove erase list info provides whatprovides clean makecache - groupinstall groupupdate grouplist groupremove groupinfo - search shell resolvedep localinstall localupdate deplist - repolist help' -- "$cur")) + _comp_compgen -- -W 'install update check-update upgrade remove + erase list info provides whatprovides clean makecache + groupinstall groupupdate grouplist groupremove groupinfo search + shell resolvedep localinstall localupdate deplist repolist + help' ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _yum yum + complete -F _comp_cmd_yum yum # ex: filetype=sh diff --git a/completions/a2x b/completions/a2x index b59c786..ed1a206 100644 --- a/completions/a2x +++ b/completions/a2x @@ -1,39 +1,41 @@ # a2x(1) completion -*- shell-script -*- -_a2x() +_comp_cmd_a2x() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[aDd]*)' + # shellcheck disable=SC2254 case $prev in --attribute | --asciidoc-opts | --dblatex-opts | --fop-opts | --help | \ - --version | --xsltproc-opts | -!(-*)[ah]) + --version | --xsltproc-opts | -${noargopts}[ah]) return ;; - --destination-dir | --icons-dir | -!(-*)D) - _filedir -d + --destination-dir | --icons-dir | -${noargopts}D) + _comp_compgen_filedir -d return ;; - --doctype | -!(-*)d) - _xfunc asciidoc _asciidoc_doctype + --doctype | -${noargopts}d) + _comp_compgen -x asciidoc doctype return ;; --stylesheet) - _filedir css + _comp_compgen_filedir css return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" --help)' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir + _comp_compgen_filedir } && - complete -F _a2x a2x + complete -F _comp_cmd_a2x a2x # ex: filetype=sh diff --git a/completions/abook b/completions/abook index 42197d1..5e4c2f4 100644 --- a/completions/abook +++ b/completions/abook @@ -1,12 +1,12 @@ # abook(1) completion -*- shell-script -*- -_abook() +_comp_cmd_abook() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return # abook only takes options, tabbing after command name adds a single dash - [[ $cword -eq 1 && -z $cur ]] && + [[ $cword -eq 1 && ! $cur ]] && { compopt -o nospace COMPREPLY=("-") @@ -15,35 +15,33 @@ _abook() case $cur in -*) - _longopt "$1" + _comp_complete_longopt "$@" return ;; esac case $prev in --informat) - COMPREPLY=($(compgen -W "$($1 --formats | - command sed -n -e 's/^'$'\t''\([a-z]*\).*/\1/p' -e '/^$/q')" \ - -- "$cur")) + _comp_compgen_split -- "$("$1" --formats | + command sed -n -e 's/^'$'\t''\([a-z]*\).*/\1/p' -e '/^$/q')" ;; --outformat) - COMPREPLY=($(compgen -W "$($1 --formats | - command sed -n -e '/^$/,$s/^'$'\t''\([a-z]*\).*/\1/p')" \ - -- "$cur")) + _comp_compgen_split -- "$("$1" --formats | + command sed -n -e '/^$/,$s/^'$'\t''\([a-z]*\).*/\1/p')" ;; --infile) - COMPREPLY=($(compgen -W stdin -- "$cur")) - _filedir + _comp_compgen -- -W stdin + _comp_compgen -a filedir ;; --outfile) - COMPREPLY=($(compgen -W stdout -- "$cur")) - _filedir + _comp_compgen -- -W stdout + _comp_compgen -a filedir ;; --config | --datafile) - _filedir + _comp_compgen_filedir ;; esac } && - complete -F _abook abook + complete -F _comp_cmd_abook abook # ex: filetype=sh diff --git a/completions/aclocal b/completions/aclocal index 010862f..b23ff72 100644 --- a/completions/aclocal +++ b/completions/aclocal @@ -1,35 +1,35 @@ # aclocal(1) completion -*- shell-script -*- -_aclocal() +_comp_cmd_aclocal() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case "$prev" in --help | --print-ac-dir | --version) return ;; --acdir | -I) - _filedir -d + _comp_compgen_filedir -d return ;; --output) - _filedir + _comp_compgen_filedir return ;; --warnings | -W) local cats=(syntax unsupported) - COMPREPLY=($(compgen -W \ - '${cats[@]} ${cats[@]/#/no-} all none error' -- "$cur")) + _comp_compgen -- -W '"${cats[@]}" "${cats[@]/#/no-}" all none + error' return ;; esac - $split && return + [[ $was_split ]] && return - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace } && - complete -F _aclocal aclocal aclocal-1.1{0..6} + complete -F _comp_cmd_aclocal aclocal aclocal-1.1{0..6} # ex: filetype=sh diff --git a/completions/acpi b/completions/acpi index f2c38b2..3d131da 100644 --- a/completions/acpi +++ b/completions/acpi @@ -1,22 +1,24 @@ -# acpi(1) completion -*- shell-script -*- +# acpi(1) completion -*- shell-script -*- -_acpi() +_comp_cmd_acpi() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[d]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | -!(-*)[hv]) + --help | --version | -${noargopts}[hv]) return ;; - --directory | -!(-*)d) - _filedir -d + --directory | -${noargopts}d) + _comp_compgen_filedir -d return ;; esac - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help } && - complete -F _acpi acpi + complete -F _comp_cmd_acpi acpi # ex: filetype=sh diff --git a/completions/add_members b/completions/add_members index efa4f1e..d691884 100644 --- a/completions/add_members +++ b/completions/add_members @@ -1,31 +1,34 @@ # mailman add_members completion -*- shell-script -*- -_add_members() +_comp_cmd_add_members() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -r | -d | --regular-members-file | --digest-members-file) - _filedir + _comp_compgen_filedir return ;; -w | -a | --welcome-msg | --admin-notify) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + _comp_compgen -- -W 'y n' return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--regular-members-file --digest-members-file - --welcome-msg --admin-notify --help' -- "$cur")) + _comp_compgen -- -W '--regular-members-file --digest-members-file + --welcome-msg --admin-notify --help' else - _xfunc list_lists _mailman_lists + # Prefer `list_lists` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_xfunc list_lists mailman_lists fi } && - complete -F _add_members add_members + complete -F _comp_cmd_add_members add_members # ex: filetype=sh diff --git a/completions/alias b/completions/alias index 92211d8..9a0f3d2 100644 --- a/completions/alias +++ b/completions/alias @@ -1,20 +1,28 @@ # bash alias completion -*- shell-script -*- -_alias() +_comp_cmd_alias() { - local cur prev words cword - _init_completion -n = || return + local cur prev words cword comp_args + _comp_initialize -n = -- "$@" || return - case ${words[@]} in + case "${words[*]}" in + *" -p "*) + return + ;; *[^=]) - COMPREPLY=($(compgen -A alias -- "$cur")) + _comp_compgen -- -A alias ;; *=) - COMPREPLY=("$(alias ${cur%=} 2>/dev/null | command sed \ + COMPREPLY=("$(alias "${cur%=}" 2>/dev/null | command sed \ -e 's|^alias '"$cur"'\(.*\)$|\1|')") ;; esac + + if [[ $cur == -* ]]; then + _comp_compgen_usage -c help -s "$1" + ((${#COMPREPLY[*]} != 1)) || compopt +o nospace + fi } && - complete -F _alias -o nospace alias + complete -F _comp_cmd_alias -o nospace alias # ex: filetype=sh diff --git a/completions/ant b/completions/ant index 197c0e9..e4f9f29 100644 --- a/completions/ant +++ b/completions/ant @@ -1,6 +1,6 @@ # bash completion for ant and phing -*- shell-script -*- -_ant_parse_targets() +_comp_cmd_ant__targets() { local line basedir @@ -9,9 +9,9 @@ _ant_parse_targets() # parse buildfile for targets while read -rd '>' line; do if [[ $line =~ \<(target|extension-point)[[:space:]].*name=[\"\']([^\"\']+) ]]; then - targets+=" ${BASH_REMATCH[2]}" + REPLY+=("${BASH_REMATCH[2]}") fi - done <$1 + done <"$1" # parse imports while read -rd '>' line; do @@ -19,39 +19,39 @@ _ant_parse_targets() local imported_buildfile imported_buildfile="${basedir}/${BASH_REMATCH[1]}" if [[ -f $imported_buildfile ]]; then - _ant_parse_targets $imported_buildfile + "$FUNCNAME" "$imported_buildfile" fi fi - done <$1 + done <"$1" } -_ant() +_comp_cmd_ant() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -h | -help | --h | --help | -projecthelp | -p | -version | -diagnostics) return ;; -buildfile | -file | -f) - _filedir 'xml' + _comp_compgen_filedir 'xml' return ;; -logfile | -l) - [[ $1 != *phing || $prev != -l ]] && _filedir + [[ $1 != *phing || $prev != -l ]] && _comp_compgen_filedir return ;; -propertyfile) - _filedir properties + _comp_compgen_filedir properties return ;; -nice) - COMPREPLY=($(compgen -W '{1..10}' -- "$cur")) + _comp_compgen -- -W '{1..10}' return ;; -lib) - _filedir -d + _comp_compgen_filedir -d return ;; -logger | -listener | -inputhandler | -main | -find | -s) @@ -64,8 +64,7 @@ _ant() elif [[ $cur == -* ]]; then # The </dev/null prevents "phing -" weirdness/getting just a literal # tab displayed on complete on CentOS 6 with phing 2.6.1. - COMPREPLY=( - $(compgen -W '$(_parse_help "$1" -h </dev/null)' -- "$cur")) + _comp_compgen_help -- -h </dev/null else # available targets completion # find which buildfile to use @@ -77,6 +76,7 @@ _ant() fi done if ((i == cword)); then + local IFS=$' \t\n' for i in ${ANT_ARGS-}; do if [[ $prev == -@(?(build)file|f) ]]; then buildfile=$i @@ -87,16 +87,17 @@ _ant() fi [[ ! -f $buildfile ]] && return - local targets + local REPLY=() # fill targets - _ant_parse_targets $buildfile + _comp_cmd_ant__targets "$buildfile" - COMPREPLY=($(compgen -W '$targets' -- "$cur")) + _comp_compgen -- -W '"${REPLY[@]}"' fi } && - complete -F _ant ant phing -type complete-ant-cmd.pl &>/dev/null && - complete -C complete-ant-cmd.pl -F _ant ant || : + complete -F _comp_cmd_ant ant phing +if type complete-ant-cmd.pl &>/dev/null; then + complete -C complete-ant-cmd.pl -F _comp_cmd_ant ant +fi # ex: filetype=sh diff --git a/completions/apache2ctl b/completions/apache2ctl index 980b3c5..0807788 100644 --- a/completions/apache2ctl +++ b/completions/apache2ctl @@ -1,16 +1,16 @@ # apache2ctl(1) completion -*- shell-script -*- -_apache2ctl() +_comp_cmd_apache2ctl() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local APWORDS - APWORDS=$($1 2>&1 >/dev/null | awk 'NR<2 { print $3; exit }' | + APWORDS=$("$1" 2>&1 >/dev/null | _comp_awk 'NR<2 { print $3; exit }' | tr "|" " ") - COMPREPLY=($(compgen -W "$APWORDS" -- "$cur")) + _comp_compgen -- -W "$APWORDS" } && - complete -F _apache2ctl apache2ctl + complete -F _comp_cmd_apache2ctl apache2ctl # ex: filetype=sh diff --git a/completions/appdata-validate b/completions/appdata-validate index 03d8cc9..1b6149e 100644 --- a/completions/appdata-validate +++ b/completions/appdata-validate @@ -1,32 +1,31 @@ # appdata-validate(1) completion -*- shell-script -*- -_appdata_validate() +_comp_cmd_appdata_validate() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -h | --help | --version) return ;; --output-format) - COMPREPLY=($(compgen -W "$($1 --help | - command sed -ne 's/--output-format.*\[\(.*\)\]/\1/' -e 's/|/ /gp')" \ - -- "$cur")) + _comp_compgen_split -- "$("$1" --help | command sed -ne \ + 's/--output-format.*\[\(.*\)\]/\1/' -e 's/|/ /gp')" return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir appdata.xml + _comp_compgen_filedir appdata.xml } && - complete -F _appdata_validate appdata-validate + complete -F _comp_cmd_appdata_validate appdata-validate # ex: filetype=sh diff --git a/completions/apt-build b/completions/apt-build index 713f4c3..5327780 100644 --- a/completions/apt-build +++ b/completions/apt-build @@ -1,26 +1,25 @@ # Debian apt-build(1) completion -*- shell-script -*- -_apt_build() +_comp_cmd_apt_build() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - local special i - for ((i = 1; i < ${#words[@]} - 1; i++)); do + local special="" i + for ((i = 1; i < cword; i++)); do if [[ ${words[i]} == @(install|remove|source|info|clean) ]]; then special=${words[i]} break fi done - if [[ -v special ]]; then + if [[ $special ]]; then case $special in install | source | info) - COMPREPLY=($(_xfunc apt-cache _apt_cache_packages)) + _comp_compgen -x apt-cache packages ;; remove) - COMPREPLY=( - $(_xfunc dpkg _comp_dpkg_installed_packages "$cur")) + _comp_compgen -x dpkg installed_packages ;; esac return @@ -28,7 +27,7 @@ _apt_build() case $prev in --patch | --build-dir | --repository-dir) - _filedir + _comp_compgen_filedir return ;; -h | --help) @@ -37,18 +36,17 @@ _apt_build() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--help --show-upgraded -u --build-dir + _comp_compgen -- -W '--help --show-upgraded -u --build-dir --repository-dir --build-only --build-command --reinstall --rebuild --remove-builddep --no-wrapper --purge --patch --patch-strip -p - --yes -y --version -v --no-source' -- "$cur")) + --yes -y --version -v --no-source' else - COMPREPLY=($(compgen -W 'update upgrade install remove source - dist-upgrade world clean info clean-build update-repository' \ - -- "$cur")) + _comp_compgen -- -W 'update upgrade install remove source dist-upgrade + world clean info clean-build update-repository' fi } && - complete -F _apt_build apt-build + complete -F _comp_cmd_apt_build apt-build # ex: filetype=sh diff --git a/completions/apt-cache b/completions/apt-cache index 61aa07b..1f47d7d 100644 --- a/completions/apt-cache +++ b/completions/apt-cache @@ -1,32 +1,69 @@ # Debian apt-cache(8) completion -*- shell-script -*- # List APT binary packages +# @since 2.12 +_comp_xfunc_apt_cache_compgen_packages() +{ + _comp_cmd_apt_cache__compgen_packages apt-cache +} + +# List APT binary packages +# @param $1 Name of executable +_comp_cmd_apt_cache__compgen_packages() +{ + _comp_compgen_split -- "$("$1" --no-generate pkgnames "$cur" 2>/dev/null)" +} + +# List APT source packages +# @since 2.12 +_comp_xfunc_apt_cache_compgen_sources() +{ + _comp_cmd_apt_cache__compgen_sources apt-cache +} + +# List APT source packages +# @param $1 Name of executable +_comp_cmd_apt_cache__compgen_sources() +{ + _comp_compgen_split -- "$("$1" dumpavail | + _comp_awk '$1 == "Source:" { print $2 }' | sort -u)" +} + +# List APT binary packages +# @deprecated 2.12 _apt_cache_packages() { - apt-cache --no-generate pkgnames "$cur" 2>/dev/null || : + local packages + _comp_compgen -v packages -i apt-cache packages apt-cache && + printf '%s\n' "${packages[@]}" } # List APT source packages +# @deprecated 2.12 _apt_cache_sources() { - compgen -W "$(apt-cache dumpavail | - awk '$1 == "Source:" { print $2 }' | sort -u)" -- "$1" + local sources + _comp_compgen -v sources -c "$1" -i apt-cache sources apt-cache && + printf '%s\n' "${sources[@]}" } # List APT source packages +# @deprecated 2.12 _apt_cache_src_packages() { - compgen -W '$(_apt_cache_sources "$cur")' -- "$cur" + local sources + _comp_compgen -v sources -i apt-cache sources apt-cache && + printf '%s\n' "${sources[@]}" } -_apt_cache() +_comp_cmd_apt_cache() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - local special ispecial + local special="" ispecial if [[ $cur != show ]]; then - for ((ispecial = 1; ispecial < ${#words[@]} - 1; ispecial++)); do + for ((ispecial = 1; ispecial < ${#words[@]}; ispecial++)); do if [[ ${words[ispecial]} == @(add|depends|dotty|madison|policy|rdepends|show?(pkg|src|)) ]]; then special=${words[ispecial]} break @@ -34,27 +71,34 @@ _apt_cache() done fi - if [[ -v special && $ispecial -lt $cword ]]; then + if [[ $special && $ispecial -lt $cword ]]; then case $special in add) - _filedir + _comp_compgen_filedir ;; showsrc) - COMPREPLY=($(_apt_cache_sources "$cur")) + _comp_cmd_apt_cache__compgen_sources "$1" ;; *) - COMPREPLY=($(_apt_cache_packages)) + _comp_cmd_apt_cache__compgen_packages "$1" ;; esac return fi + local noargopts='!(-*|*[cps]*)' + # shellcheck disable=SC2254 case $prev in - --config-file | --pkg-cache | --src-cache | -!(-*)[cps]) - _filedir + --config-file | --pkg-cache | --src-cache | -${noargopts}[cps]) + _comp_compgen_filedir + return + ;; + --with-source) + _comp_compgen_filedir '@(deb|dsc|changes)' + _comp_compgen -a -- -f -o plusdirs -X '!?(*/)@(Sources|Packages)' return ;; search) @@ -65,21 +109,19 @@ _apt_cache() esac if [[ $cur == -* ]]; then - - COMPREPLY=($(compgen -W '-h -v -p -s -q -i -f -a -g -c -o --help - --version --pkg-cache --src-cache --quiet --important --full - --all-versions --no-all-versions --generate --no-generate - --names-only --all-names --recurse --config-file --option - --installed' -- "$cur")) - elif [[ ! -v special ]]; then - - COMPREPLY=($(compgen -W 'add gencaches show showpkg showsrc stats - dump dumpavail unmet search search depends rdepends pkgnames - dotty xvcg policy madison' -- "$cur")) - + _comp_compgen -- -W '--pkg-cache --src-cache --quiet --important + --no-pre-depends --no-depends --no-recommends --no-suggests + --no-conflicts --no-breaks --no-replaces --no-enhances --implicit + --full --all-versions --no-all-versions --generate --no-generate + --names-only --all-names --recurse --installed --with-source + --help --version --config-file --option' + elif [[ ! $special ]]; then + _comp_compgen -- -W 'gencaches showpkg stats showsrc dump dumpavail + unmet show search depends rdepends pkgnames dotty xvcg policy + madison' fi } && - complete -F _apt_cache apt-cache + complete -F _comp_cmd_apt_cache apt-cache # ex: filetype=sh diff --git a/completions/apt-get b/completions/apt-get index 4aee263..f59c62b 100644 --- a/completions/apt-get +++ b/completions/apt-get @@ -1,83 +1,93 @@ # Debian apt-get(8) completion -*- shell-script -*- -_apt_get() +# @since 2.12 +_comp_xfunc_apt_get_compgen_installed_packages() { - local cur prev words cword package - _init_completion -n ':=' || return + if [[ -f /etc/debian_version ]]; then + # Debian system + _comp_compgen -x dpkg installed_packages + else + # assume RPM based + _comp_compgen -x rpm installed_packages + fi +} - local special i - for ((i = 1; i < ${#words[@]} - 1; i++)); do - if [[ ${words[i]} == @(install|remove|autoremove|purge|source|build-dep|download|changelog) ]]; then +_comp_cmd_apt_get() +{ + local cur prev words cword comp_args package + _comp_initialize -n ':=' -- "$@" || return + + local special="" i + for ((i = 1; i < cword; i++)); do + if [[ ${words[i]} == @(install|remove|auto?(-)remove|purge|source|build-dep|download|changelog) ]]; then special=${words[i]} break fi done - if [[ -v special ]]; then + if [[ $special ]]; then case $special in - remove | autoremove | purge) - if [[ -f /etc/debian_version ]]; then - # Debian system - COMPREPLY=($( - _xfunc dpkg _comp_dpkg_installed_packages $cur - )) - else - # assume RPM based - _xfunc rpm _rpm_installed_packages - fi + remove | auto?(-)remove | purge) + _comp_xfunc_apt_get_compgen_installed_packages ;; source) - COMPREPLY=($(_xfunc apt-cache _apt_cache_packages) - $(compgen -W "$(apt-cache dumpavail | - awk '$1 == "Source:" { print $2 }' | sort -u)" -- "$cur")) + # Prefer `apt-cache` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen -x apt-cache packages + _comp_compgen -a split -- "$(apt-cache dumpavail | + _comp_awk '$1 == "Source:" { print $2 }' | sort -u)" ;; - install) - if [[ $cur == */* ]]; then - _filedir deb + install | reinstall) + if _comp_looks_like_path "$cur"; then + _comp_compgen_filedir deb return elif [[ $cur == *=* ]]; then package="${cur%%=*}" cur="${cur#*=}" - COMPREPLY=($(IFS=$'\n' compgen -W "$( + _comp_compgen_split -l -- "$( apt-cache --no-generate madison "$package" 2>/dev/null | while IFS=' |' read -r _ version _; do echo "$version" done - )" \ - -- "$cur")) - __ltrim_colon_completions "$cur" + )" + _comp_ltrim_colon_completions "$cur" return fi ;;& build-dep) - _filedir -d - [[ $cur != */* ]] || return + _comp_compgen_filedir -d + _comp_looks_like_path "$cur" && return ;;& *) - COMPREPLY+=($(_xfunc apt-cache _apt_cache_packages)) + _comp_compgen -ax apt-cache packages ;; esac return fi + local noargopts='!(-*|*[eoct]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | --option | -!(-*)[hvo]) + --error-on | --help | --version | --option | -${noargopts}[ehvo]) return ;; - --config-file | -!(-*)c) - _filedir + --config-file | -${noargopts}c) + _comp_compgen_filedir return ;; - --target-release | --default-release | -!(-*)t) - COMPREPLY=($(compgen -W "$(apt-cache policy | command sed -ne \ - 's/^ *release.*[ ,]o=\(Debian\|Ubuntu\),a=\(\w*\).*/\2/p')" \ - -- "$cur")) + --target-release | --default-release | -${noargopts}t) + # Prefer `apt-cache` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen_split -- "$(apt-cache policy | command sed -ne \ + 's/^ *release.*[ ,]o=\(Debian\|Ubuntu\),a=\(\w*\).*/\2/p')" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--no-install-recommends --install-suggests + _comp_compgen -- -W '--no-install-recommends --install-suggests --download-only --fix-broken --ignore-missing --fix-missing --no-download --quiet --simulate --just-print --dry-run --recon --no-act --yes --assume-yes --assume-no --no-show-upgraded @@ -89,16 +99,15 @@ _apt_get() --trivial-only --no-remove --auto-remove --autoremove --only-source --diff-only --dsc-only --tar-only --arch-only --indep-only --allow-unauthenticated --no-allow-insecure-repositories - --allow-releaseinfo-change --show-progress --with-source --help - --version --config-file --option' -- "$cur")) + --allow-releaseinfo-change --show-progress --with-source --error-on + --help --version --config-file --option' else - COMPREPLY=($(compgen -W 'update upgrade dist-upgrade - dselect-upgrade install remove purge source build-dep check - download clean autoclean autoremove changelog indextargets' \ - -- "$cur")) + _comp_compgen -- -W 'update upgrade dist-upgrade dselect-upgrade + install reinstall remove purge source build-dep satisfy check + download clean autoclean autoremove changelog indextargets' fi } && - complete -F _apt_get apt-get + complete -F _comp_cmd_apt_get apt-get # ex: filetype=sh diff --git a/completions/apt-mark b/completions/apt-mark new file mode 100644 index 0000000..7ef3f76 --- /dev/null +++ b/completions/apt-mark @@ -0,0 +1,64 @@ +# Debian apt-mark(8) completion -*- shell-script -*- + +_comp_cmd_apt_mark() +{ + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + + local special="" i + for ((i = 1; i < cword; i++)); do + if [[ ${words[i]} == @(auto|manual|minimize-manual|showauto|showmanual|hold|unhold|showhold|install|remove|deinstall|purge|showinstall|showremove|showpurge) ]]; then + special=${words[i]} + break + fi + done + + if [[ $special ]]; then + case $special in + auto | manual | unhold) + local -A showcmds=([auto]=manual [manual]=auto [unhold]=hold) + local showcmd=${showcmds[$special]} + _comp_compgen_split -- "$("$1" "show$showcmd" 2>/dev/null)" + return + ;; + minimize-manual) + return + ;; + *) + _comp_compgen -x apt-get installed_packages + ;; + esac + return + fi + + local noargopts='!(-*|*[ocf]*)' + # shellcheck disable=SC2254 + case $prev in + --help | --version | --option | -${noargopts}[hvo]) + return + ;; + --config-file | -${noargopts}c) + _comp_compgen_filedir conf + return + ;; + --file | -${noargopts}f) + _comp_compgen_filedir + return + ;; + esac + + [[ $was_split ]] && return + + if [[ $cur == -* ]]; then + _comp_compgen -- -W '--file= --help --version --config-file --option' + [[ ${COMPREPLY-} == *= ]] && compopt -o nospace + else + _comp_compgen -- -W 'auto manual minimize-manual showauto showmanual + hold unhold showhold install remove purge showinstall showremove + showpurge' + fi + +} && + complete -F _comp_cmd_apt_mark apt-mark + +# ex: filetype=sh diff --git a/completions/aptitude b/completions/aptitude index e5ea163..827395a 100644 --- a/completions/aptitude +++ b/completions/aptitude @@ -1,24 +1,11 @@ # Debian aptitude(1) completion -*- shell-script -*- -_have grep-status && { - _comp_dpkg_hold_packages() - { - grep-status -P -e "^$1" -a -FStatus 'hold' -n -s Package - } -} || { - _comp_dpkg_hold_packages() - { - command grep -B 2 'hold' /var/lib/dpkg/status | - awk "/Package: $1/ { print \$2 }" - } -} - -_aptitude() +_comp_cmd_aptitude() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - local special i + local special="" i for ((i = 1; i < ${#words[@]} - 1; i++)); do if [[ ${words[i]} == @(@(|re)install|@(|un)hold|@(|un)markauto|@(dist|full|safe)-upgrade|download|show|forbid-version|purge|remove|changelog|why@(|-not)|keep@(|-all)|build-dep|@(add|remove)-user-tag|versions) ]]; then special=${words[i]} @@ -26,65 +13,65 @@ _aptitude() fi done - if [[ -v special ]]; then + if [[ $special ]]; then case $special in install | hold | markauto | unmarkauto | dist-upgrade | full-upgrade | \ safe-upgrade | download | show | changelog | why | why-not | build-dep | \ add-user-tag | remove-user-tag | versions) - COMPREPLY=($(_xfunc apt-cache _apt_cache_packages)) + _comp_compgen -x apt-cache packages return ;; purge | remove | reinstall | forbid-version) - COMPREPLY=( - $(_xfunc dpkg _comp_dpkg_installed_packages "$cur")) + _comp_compgen -x dpkg installed_packages return ;; unhold) - COMPREPLY=($(_comp_dpkg_hold_packages "$cur")) + _comp_compgen -x dpkg held_packages return ;; esac fi + local noargopts='!(-*|*[SwFoOt]*)' + # shellcheck disable=SC2254 case $prev in # don't complete anything if these options are found autoclean | clean | forget-new | search | upgrade | update | keep-all) return ;; - -!(-*)S) - _filedir + -${noargopts}S) + _comp_compgen_filedir return ;; - --display-format | --width | -!(-*)[wFo]) + --display-format | --width | -${noargopts}[wFo]) return ;; - --sort | -!(-*)O) - COMPREPLY=($(compgen -W 'installsize installsizechange debsize - name priority version' -- "$cur")) + --sort | -${noargopts}O) + _comp_compgen -- -W 'installsize installsizechange debsize name + priority version' return ;; - --target-release | --default-release | -!(-*)t) - COMPREPLY=($(apt-cache policy | - command grep "release.o=Debian,a=$cur" | - command sed -e "s/.*a=\(\w*\).*/\1/" | uniq 2>/dev/null)) + --target-release | --default-release | -${noargopts}t) + _comp_compgen_split -l -- "$(apt-cache policy | + command sed -ne 's/.*release.o=Debian,a=\([_[:alnum:]]*\).*/\1/p')" return ;; esac if [[ $cur == -* ]]; then - local opts=" $($1 --help 2>&1 | command sed -e \ - 's/--with(out)-recommends/--without-recommends\n--with-recommends/' | - _parse_help - | tr '\n' ' ') " + _comp_compgen -R help - <<<"$("$1" --help 2>&1 | command sed -e \ + 's/--with(out)-recommends/--without-recommends\n--with-recommends/')" + ((${#COMPREPLY[@]})) || return 0 # Exclude some mutually exclusive options + local exclude_flags="" for i in "${words[@]}"; do - [[ $i == -u ]] && opts=${opts/ -i / } - [[ $i == -i ]] && opts=${opts/ -u / } + [[ $i == -u ]] && exclude_flags+=i + [[ $i == -i ]] && exclude_flags+=u done # Do known short -> long replacements; at least up to 0.8.12, --help # outputs mostly only short ones. - COMPREPLY=($opts) for i in "${!COMPREPLY[@]}"; do case ${COMPREPLY[i]} in -h) COMPREPLY[i]=--help ;; @@ -104,16 +91,17 @@ _aptitude() esac done - COMPREPLY=($(compgen -W '${COMPREPLY[@]}' -- "$cur")) + _comp_compgen -- -W '"${COMPREPLY[@]}"' \ + ${exclude_flags:+-X "-[$exclude_flags]"} else - COMPREPLY=($(compgen -W 'update upgrade safe-upgrade forget-new - clean autoclean install reinstall remove hold unhold purge markauto + _comp_compgen -- -W 'update upgrade safe-upgrade forget-new clean + autoclean install reinstall remove hold unhold purge markauto unmarkauto why why-not dist-upgrade full-upgrade download search show forbid-version changelog keep keep-all build-dep add-user-tag - remove-user-tag versions' -- "$cur")) + remove-user-tag versions' fi } && - complete -F _aptitude -o default aptitude aptitude-curses + complete -F _comp_cmd_aptitude -o default aptitude aptitude-curses # ex: filetype=sh diff --git a/completions/arch b/completions/arch index afeed05..7ca9738 100644 --- a/completions/arch +++ b/completions/arch @@ -2,27 +2,27 @@ # Try to detect whether this is the mailman "arch" to avoid installing # it for the coreutils/util-linux-ng one. -_have mailmanctl && - _arch() +_comp_have_command mailmanctl && + _comp_cmd_arch() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -w | -g | -d | --welcome-msg | --goodbye-msg | --digest) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + _comp_compgen -- -W 'y n' return ;; --file) - _filedir + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help else local args=$cword for ((i = 1; i < cword; i++)); do @@ -32,15 +32,18 @@ _have mailmanctl && done case $args in 1) - _xfunc list_lists _mailman_lists + # Prefer `list_lists` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen -x list_lists mailman_lists ;; 2) - _filedir + _comp_compgen_filedir ;; esac fi } && - complete -F _arch arch + complete -F _comp_cmd_arch arch # ex: filetype=sh diff --git a/completions/arp b/completions/arp index 922e800..3d1669a 100644 --- a/completions/arp +++ b/completions/arp @@ -1,43 +1,45 @@ -# arp(8) completion -*- shell-script -*- +# arp(8) completion -*- shell-script -*- -_arp() +_comp_cmd_arp() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[iApfHt]*)' + # shellcheck disable=SC2254 case $prev in - --device | -!(-*)i) - _available_interfaces -a + --device | -${noargopts}i) + _comp_compgen_available_interfaces -a return ;; - --protocol | -!(-*)[Ap]) + --protocol | -${noargopts}[Ap]) # TODO protocol/address family return ;; - --file | -!(-*)f) - _filedir + --file | -${noargopts}f) + _comp_compgen_filedir return ;; - --hw-type | -!(-*)[Ht]) + --hw-type | -${noargopts}[Ht]) # TODO: parse from --help output? - COMPREPLY=($(compgen -W 'ash ether ax25 netrom rose arcnet \ - dlci fddi hippi irda x25 eui64' -- "$cur")) + _comp_compgen -- -W 'ash ether ax25 netrom rose arcnet dlci fddi + hippi irda x25 eui64' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage return fi - local args - _count_args "" "@(--device|--protocol|--file|--hw-type|-!(-*)[iApfHt])" - case $args in + local REPLY + _comp_count_args -a "@(--device|--protocol|--file|--hw-type|-${noargopts}[iApfHt])" + case $REPLY in 1) local ips=$("$1" -an | command sed -ne \ 's/.*(\([0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}\)).*/\1/p') - COMPREPLY=($(compgen -W '$ips' -- "$cur")) + _comp_compgen -- -W '$ips' ;; 2) # TODO if -d mode: "pub"; if not -f mode: hw_addr @@ -54,6 +56,6 @@ _arp() ;; esac } && - complete -F _arp arp + complete -F _comp_cmd_arp arp # ex: filetype=sh diff --git a/completions/arping b/completions/arping index 57e1e19..c69fc2d 100644 --- a/completions/arping +++ b/completions/arping @@ -1,31 +1,31 @@ # arping(8) completion -*- shell-script -*- -_arping() +_comp_cmd_arping() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*c | -*w) return ;; -*I) - _available_interfaces -a + _comp_compgen_available_interfaces -a return ;; -*s) - _ip_addresses + _comp_compgen_ip_addresses return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur")) + _comp_compgen_help -- -h return fi - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" } && - complete -F _arping arping + complete -F _comp_cmd_arping arping # ex: filetype=sh diff --git a/completions/arpspoof b/completions/arpspoof index d1a1373..8939f2d 100644 --- a/completions/arpspoof +++ b/completions/arpspoof @@ -1,28 +1,28 @@ # arpspoof completion -*- shell-script -*- -_arpspoof() +_comp_cmd_arpspoof() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -i) - _available_interfaces -a + _comp_compgen_available_interfaces -a return ;; -t) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage else - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" fi } && - complete -F _arpspoof arpspoof + complete -F _comp_cmd_arpspoof arpspoof # ex: filetype=sh diff --git a/completions/asciidoc b/completions/asciidoc index 1ea4abf..7e77857 100644 --- a/completions/asciidoc +++ b/completions/asciidoc @@ -1,52 +1,60 @@ # asciidoc(1) completion -*- shell-script -*- +# @since 2.12 +_comp_xfunc_asciidoc_compgen_doctype() +{ + _comp_compgen -- -W 'article book manpage' +} + +# @deprecated 2.12 _asciidoc_doctype() { - COMPREPLY+=($(compgen -W 'article book manpage' -- "$cur")) + _comp_compgen -ax asciidoc doctype } -_asciidoc() +_comp_cmd_asciidoc() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[abfdo]*)' + # shellcheck disable=SC2254 case $prev in - --attribute | -!(-*)a) + --attribute | -${noargopts}a) return ;; - --backend | -!(-*)b) - COMPREPLY=($(compgen -W 'docbook html4 xhtml11' -- "$cur")) + --backend | -${noargopts}b) + _comp_compgen -- -W 'docbook html4 xhtml11' return ;; - --conf-file | -!(-*)f) - _filedir conf + --conf-file | -${noargopts}f) + _comp_compgen_filedir conf return ;; - --doctype | -!(-*)d) - _asciidoc_doctype + --doctype | -${noargopts}d) + _comp_xfunc_asciidoc_compgen_doctype return ;; - --help | -!(-*)h) - COMPREPLY=($(compgen -W 'manpage syntax topics' -- "$cur")) + --help | -${noargopts}h) + _comp_compgen -- -W 'manpage syntax topics' return ;; - --out-file | -!(-*)o) - _filedir + --out-file | -${noargopts}o) + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" "--help manpage")' \ - -- "$cur")) + _comp_compgen_help -- --help manpage [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir + _comp_compgen_filedir } && - complete -F _asciidoc asciidoc asciidoc.py + complete -F _comp_cmd_asciidoc asciidoc asciidoc.py # ex: filetype=sh diff --git a/completions/aspell b/completions/aspell index e080a07..89dae17 100644 --- a/completions/aspell +++ b/completions/aspell @@ -1,65 +1,66 @@ # bash completion for aspell -*- shell-script -*- -_aspell_dictionary() +_comp_cmd_aspell__dictionary() { - local datadir aspell=${1:-aspell} - datadir=$($aspell config data-dir 2>/dev/null || echo /usr/lib/aspell) + local datadir aspell=$1 + datadir=$("$aspell" config data-dir 2>/dev/null || echo /usr/lib/aspell) # First, get aliases (dicts dump does not list them) - COMPREPLY=($(printf '%s\n' $datadir/*.alias)) - COMPREPLY=("${COMPREPLY[@]%.alias}") - COMPREPLY=("${COMPREPLY[@]#$datadir/}") + if _comp_expand_glob COMPREPLY '"$datadir"/*.alias'; then + COMPREPLY=("${COMPREPLY[@]%.alias}") + COMPREPLY=("${COMPREPLY[@]#$datadir/}") + fi # Then, add the canonical dicts - COMPREPLY+=($($aspell dicts 2>/dev/null)) - COMPREPLY=($(compgen -X '\*' -W '${COMPREPLY[@]}' -- "$cur")) + _comp_split -a COMPREPLY "$("$aspell" dicts 2>/dev/null)" + ((${#COMPREPLY[@]})) && + _comp_compgen -- -X '\*' -W '"${COMPREPLY[@]}"' } -_aspell() +_comp_cmd_aspell() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -c | -p | check | --conf | --personal | --repl | --per-conf) - _filedir + _comp_compgen_filedir return ;; --conf-dir | --data-dir | --dict-dir | --home-dir | --local-data-dir | --prefix) - _filedir -d + _comp_compgen_filedir -d return ;; dump | create | merge) - COMPREPLY=($(compgen -W 'master personal repl' -- "$cur")) + _comp_compgen -- -W 'master personal repl' return ;; --mode) - COMPREPLY=($(compgen -W "$($1 modes 2>/dev/null | - awk '{ print $1 }')" -- "$cur")) + _comp_compgen_split -- "$("$1" modes 2>/dev/null | + _comp_awk '{ print $1 }')" return ;; --sug-mode) - COMPREPLY=($(compgen -W 'ultra fast normal bad-speller' \ - -- "$cur")) + _comp_compgen -- -W 'ultra fast normal bad-speller' return ;; --keymapping) - COMPREPLY=($(compgen -W 'aspell ispell' -- "$cur")) + _comp_compgen -- -W 'aspell ispell' return ;; -d | --master) - _aspell_dictionary "$1" + _comp_cmd_aspell__dictionary "$1" return ;; --add-filter | --rem-filter) - COMPREPLY=($(compgen -W "$($1 filters 2>/dev/null | - awk '{ print $1 }')" -- "$cur")) + _comp_compgen_split -- "$("$1" filters 2>/dev/null | + _comp_awk '{ print $1 }')" return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--conf= --conf-dir= --data-dir= --dict-dir= + _comp_compgen -- -W '--conf= --conf-dir= --data-dir= --dict-dir= --encoding= --add-filter= --rem-filter= --mode= --add-extra-dicts= --rem-extra-dicts= --home-dir= --ignore= --ignore-accents --dont-ignore-accents --ignore-case --dont-ignore-case @@ -76,13 +77,13 @@ _aspell() --add-tex-command= --rem-tex-command= --tex-check-comments --dont-tex-check-comments --add-tex-extension --rem-tex-extension --add-sgml-check= --rem-sgml-check= --add-sgml-extension - --rem-sgml-extension' -- "$cur")) + --rem-sgml-extension' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - COMPREPLY=($(compgen -W 'usage help check pipe list config soundslike - filter version dump create merge' -- "$cur")) + _comp_compgen -- -W 'usage help check pipe list config soundslike + filter version dump create merge' fi } && - complete -F _aspell aspell + complete -F _comp_cmd_aspell aspell # ex: filetype=sh diff --git a/completions/autoconf b/completions/autoconf index b51e797..ac27886 100644 --- a/completions/autoconf +++ b/completions/autoconf @@ -1,40 +1,40 @@ # autoconf(1) completion -*- shell-script -*- -_autoconf() +_comp_cmd_autoconf() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case "$prev" in --help | -h | --version | -V | --trace | -t) return ;; --output | -o) - _filedir + _comp_compgen_filedir return ;; --warnings | -W) local cats=(cross obsolete syntax) - COMPREPLY=($(compgen -W \ - '${cats[@]} ${cats[@]/#/no-} all none error' -- "$cur")) + _comp_compgen -- -W '"${cats[@]}" "${cats[@]/#/no-}" all none + error' return ;; --prepend-include | -B | --include | -I) - _filedir -d + _comp_compgen_filedir -d return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir '@(ac|in)' + _comp_compgen_filedir '@(ac|in)' } && - complete -F _autoconf autoconf + complete -F _comp_cmd_autoconf autoconf # ex: filetype=sh diff --git a/completions/automake b/completions/automake index 5fe5f4f..e20ab4f 100644 --- a/completions/automake +++ b/completions/automake @@ -1,9 +1,9 @@ # automake(1) completion -*- shell-script -*- -_automake() +_comp_cmd_automake() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case "$prev" in --help | --version) @@ -11,26 +11,26 @@ _automake() ;; --warnings | -W) local cats=(gnu obsolete override portability syntax unsupported) - COMPREPLY=($(compgen -W \ - '${cats[@]} ${cats[@]/#/no-} all none error' -- "$cur")) + _comp_compgen -- -W '"${cats[@]}" "${cats[@]/#/no-}" all none + error' return ;; --libdir) - _filedir -d + _comp_compgen_filedir -d return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir + _comp_compgen_filedir } && - complete -F _automake automake automake-1.1{0..6} + complete -F _comp_cmd_automake automake automake-1.1{0..6} # ex: filetype=sh diff --git a/completions/autoreconf b/completions/autoreconf index 9b0f0dc..ef43a5c 100644 --- a/completions/autoreconf +++ b/completions/autoreconf @@ -1,9 +1,9 @@ # autoreconf(1) completion -*- shell-script -*- -_autoreconf() +_comp_cmd_autoreconf() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case "$prev" in --help | -h | --version | -V) @@ -12,30 +12,30 @@ _autoreconf() --warnings | -W) local cats=(cross gnu obsolete override portability syntax unsupported) - COMPREPLY=($(compgen -W \ - '${cats[@]} ${cats[@]/#/no-} all none error' -- "$cur")) + _comp_compgen -- -W '"${cats[@]}" "${cats[@]/#/no-}" all none + error' return ;; --prepend-include | -B | --include | -I) - _filedir -d + _comp_compgen_filedir -d return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi if [[ $1 == *autoheader ]]; then - _filedir '@(ac|in)' + _comp_compgen_filedir '@(ac|in)' else - _filedir -d + _comp_compgen_filedir -d fi } && - complete -F _autoreconf autoreconf autoheader + complete -F _comp_cmd_autoreconf autoreconf autoheader # ex: filetype=sh diff --git a/completions/autorpm b/completions/autorpm index d55322a..3e67091 100644 --- a/completions/autorpm +++ b/completions/autorpm @@ -1,14 +1,14 @@ # autorpm(8) completion -*- shell-script -*- -_autorpm() +_comp_cmd_autorpm() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - COMPREPLY=($(compgen -W '--notty --debug --help --version auto add - fullinfo info help install list remove set' -- "$cur")) + _comp_compgen -- -W '--notty --debug --help --version auto add fullinfo + info help install list remove set' } && - complete -F _autorpm autorpm + complete -F _comp_cmd_autorpm autorpm # ex: filetype=sh diff --git a/completions/autoscan b/completions/autoscan index e007143..fe48b56 100644 --- a/completions/autoscan +++ b/completions/autoscan @@ -1,34 +1,36 @@ # autoscan(1) completion -*- shell-script -*- -_autoscan() +_comp_cmd_autoscan() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[BI]*)' + # shellcheck disable=SC2254 case "$prev" in - --help | --version | -!(-*)[hV]) + --help | --version | -${noargopts}[hV]) return ;; - --prepend-include | --include | -!(-*)[BI]) - _filedir -d + --prepend-include | --include | -${noargopts}[BI]) + _comp_compgen_filedir -d return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi if [[ $1 == *autoupdate ]]; then - _filedir '@(ac|in)' + _comp_compgen_filedir '@(ac|in)' else - _filedir -d + _comp_compgen_filedir -d fi } && - complete -F _autoscan autoscan autoupdate + complete -F _comp_cmd_autoscan autoscan autoupdate # ex: filetype=sh diff --git a/completions/avahi-browse b/completions/avahi-browse new file mode 100644 index 0000000..8e4ece7 --- /dev/null +++ b/completions/avahi-browse @@ -0,0 +1,42 @@ +# bash completion for avahi-browse(1) -*- shell-script -*- + +_comp_cmd_avahi_browse() +{ + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + + local noargopts='!(-*|*[D]*)' + # shellcheck disable=SC2254 + case $prev in + --domain | -${noargopts}D) + return + ;; + --help | --version | -${noargopts}[hV]*) + return + ;; + esac + + [[ $was_split ]] && return + + if [[ $cur == -* ]]; then + _comp_compgen_help + [[ ${COMPREPLY-} != *= ]] || compopt -o nospace + return + fi + + # Complete service types except with -a/-D/-b + [[ $1 != *-domains ]] || return + local word + for word in "${words[@]}"; do + case $word in + --all | --browse-domains | --dump-db | -${noargopts}[aDb]*) + return + ;; + esac + done + _comp_compgen_split -- "$("$1" --dump-db --no-db-lookup)" + +} && + complete -F _comp_cmd_avahi_browse avahi-browse avahi-browse-domains + +# ex: filetype=sh diff --git a/completions/avctrl b/completions/avctrl index 89c24e4..2bb2755 100644 --- a/completions/avctrl +++ b/completions/avctrl @@ -1,20 +1,20 @@ # avctrl completion -*- shell-script -*- -_avctrl() +_comp_cmd_avctrl() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--help --quiet' -- "$cur")) + _comp_compgen -- -W '--help --quiet' else - local args - _count_args - if ((args == 1)); then - COMPREPLY=($(compgen -W 'discover switch' -- "$cur")) + local REPLY + _comp_count_args + if ((REPLY == 1)); then + _comp_compgen -- -W 'discover switch' fi fi } && - complete -F _avctrl avctrl + complete -F _comp_cmd_avctrl avctrl # ex: filetype=sh diff --git a/completions/badblocks b/completions/badblocks index 29c4e00..14e4e05 100644 --- a/completions/badblocks +++ b/completions/badblocks @@ -1,29 +1,30 @@ # badblocks(8) completion -*- shell-script -*- -_badblocks() +_comp_cmd_badblocks() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*[bcedpt]) return ;; -*[io]) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then # Filter out -w (dangerous) and -X (internal use) - COMPREPLY=($(compgen -X -[wX] -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen -R usage + ((${#COMPREPLY[@]})) && + _comp_compgen -- -X '-[wX]' -W '"${COMPREPLY[@]}"' return fi - cur=${cur:=/dev/} - _filedir + _comp_compgen -c "${cur:-/dev/}" filedir } && - complete -F _badblocks badblocks + complete -F _comp_cmd_badblocks badblocks # ex: filetype=sh diff --git a/completions/bind b/completions/bind index 2ee428b..12d2343 100644 --- a/completions/bind +++ b/completions/bind @@ -1,36 +1,36 @@ # bash bind completion -*- shell-script -*- -_bind() +_comp_cmd_bind() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*[lpPsSvVrxX]) return ;; -*m) - COMPREPLY=($(compgen -W "emacs emacs-standard emacs-meta - emacs-ctlx vi vi-move vi-command vi-insert" -- "$cur")) + _comp_compgen -- -W "emacs emacs-standard emacs-meta emacs-ctlx vi + vi-move vi-command vi-insert" return ;; -*f) - _filedir + _comp_compgen_filedir return ;; -*[qu]) - COMPREPLY=($(compgen -W '$("$1" -l)' -- "$cur")) + _comp_compgen_split -- "$("$1" -l)" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage -c help -s "$1" return fi - COMPREPLY=($(compgen -A binding -- "$cur")) + _comp_compgen -- -A binding } && - complete -F _bind bind + complete -F _comp_cmd_bind bind # ex: filetype=sh diff --git a/completions/bk b/completions/bk index 4e4d140..e848c04 100644 --- a/completions/bk +++ b/completions/bk @@ -1,18 +1,18 @@ # BitKeeper completion -*- shell-script -*- # adapted from code by Bart Trojanowski <bart@jukie.net> -_bk() +_comp_cmd_bk() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local BKCMDS="$(bk help topics 2>/dev/null | - awk '/^ bk/ { print $2 }' | xargs printf '%s ')" + _comp_awk '/^ bk/ { print $2 }' | xargs printf '%s ')" - COMPREPLY=($(compgen -W "$BKCMDS" -- "$cur")) - _filedir + _comp_compgen -- -W "$BKCMDS" + _comp_compgen -a filedir } && - complete -F _bk bk + complete -F _comp_cmd_bk bk # ex: filetype=sh diff --git a/completions/brctl b/completions/brctl index 14569b6..0394fa5 100644 --- a/completions/brctl +++ b/completions/brctl @@ -1,40 +1,40 @@ # bash completion for brctl -*- shell-script -*- -_brctl() +_comp_cmd_brctl() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local command=${words[1]} case $cword in 1) - COMPREPLY=($(compgen -W "addbr delbr addif delif setageing + _comp_compgen -- -W "addbr delbr addif delif setageing setbridgeprio setfd sethello setmaxage setpathcost setportprio - show showmacs showstp stp" -- "$cur")) + show showmacs showstp stp" ;; 2) case $command in show) ;; *) - COMPREPLY=($(compgen -W "$($1 show | - awk 'NR>1 {print $1}')" -- "$cur")) + _comp_compgen_split -- "$("$1" show | + _comp_awk 'NR>1 {print $1}')" ;; esac ;; 3) case $command in addif | delif) - _configured_interfaces + _comp_compgen_configured_interfaces ;; stp) - COMPREPLY=($(compgen -W 'on off' -- "$cur")) + _comp_compgen -- -W 'on off' ;; esac ;; esac } && - complete -F _brctl -o default brctl + complete -F _comp_cmd_brctl -o default brctl # ex: filetype=sh diff --git a/completions/btdownloadheadless.py b/completions/btdownloadheadless.py index a470e53..f5b791e 100644 --- a/completions/btdownloadheadless.py +++ b/completions/btdownloadheadless.py @@ -1,32 +1,31 @@ # btdownloadheadless(1) completion -*- shell-script -*- -_btdownload() +_comp_cmd_btdownload() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --responsefile | --saveas) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--max_uploads --keepalive_interval + _comp_compgen -- -W '--max_uploads --keepalive_interval --download_slice_size --request_backlog --max_message_length --ip --minport --maxport --responsefile --url --saveas --timeout --timeout_check_interval --max_slice_length --max_rate_period --bind --upload_rate_fudge --display_interval --rerequest_interval --min_peers --http_timeout --max_initiate --max_allow_in --check_hashes --max_upload_rate --snub_time --spew - --rarest_first_cutoff --min_uploads --report_hash_failures' \ - -- "$cur")) + --rarest_first_cutoff --min_uploads --report_hash_failures' else - _filedir + _comp_compgen_filedir fi } && - complete -F _btdownload btdownloadheadless.py btdownloadcurses.py \ + complete -F _comp_cmd_btdownload btdownloadheadless.py btdownloadcurses.py \ btdownloadgui.py # ex: filetype=sh diff --git a/completions/bts b/completions/bts index d535d13..e4f8079 100644 --- a/completions/bts +++ b/completions/bts @@ -1,81 +1,85 @@ -# bts completion -*- shell-script -*- +# bts completion -*- shell-script -*- -# List bug numbers from bugs cache in ~/.devscripts_cache/bts -_cached_bugs() +# Generate bug numbers from bugs cache in ~/.devscripts_cache/bts +_comp_cmd_bts__compgen_cached_bugs() { - [[ -d $HOME/.devscripts_cache/bts ]] && - find $HOME/.devscripts_cache/bts -maxdepth 1 -name "${cur}[0-9]*.html" \ + [[ -d $HOME/.devscripts_cache/bts ]] || return 1 + local bugs=$( + find "$HOME/.devscripts_cache/bts" -maxdepth 1 \ + -name "${cur}[0-9]*.html" \ -printf "%f\n" | cut -d'.' -f1 + ) + _comp_compgen -RU bugs -- -W '$bugs' } -# List APT source packages prefixed with "src:" -_src_packages_with_prefix() +# Generate APT source packages prefixed with "src:" +_comp_cmd_bts__compgen_src_packages_with_prefix() { - ppn=${cur:4} # partial package name, after stripping "src:" - compgen -P "src:" -W '$(_xfunc apt-cache _apt_cache_sources "$ppn")' \ - -- "$ppn" + local _ppn=${cur:4} # partial package name, after stripping "src:" + local sources + _comp_compgen -v sources -c "$_ppn" -x apt-cache sources && + _comp_compgen -U sources -- -P "src:" -W '"${sources[@]}"' } -_bts() +_comp_cmd_bts() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in show | bugs) - COMPREPLY=($(compgen -W 'release-critical RC from: tag: - usertag:' -- "$cur") $(_cached_bugs) - $(_src_packages_with_prefix)) + _comp_compgen -- -W 'release-critical RC from: tag: usertag:' + _comp_compgen -ai bts cached_bugs + _comp_compgen -ai bts src_packages_with_prefix return ;; select) - COMPREPLY=($(compgen -W 'package: source: maintainer: submitter: + _comp_compgen -- -W 'package: source: maintainer: submitter: severity: status: tag: owner: correspondent: affects: bugs: - users: archive:' -- "$cur")) + users: archive:' return ;; status) - COMPREPLY=($(compgen -W 'file: fields: verbose' -- "$cur") - $(_cached_bugs)) + _comp_compgen -- -W 'file: fields: verbose' + _comp_compgen -ai bts cached_bugs return ;; block | unblock) - COMPREPLY=($(compgen -W 'by with' -- "$cur")) + _comp_compgen -- -W 'by with' return ;; severity) - COMPREPLY=($(compgen -W 'wishlist minor normal important serious - grave critical' -- "$cur")) + _comp_compgen -- -W 'wishlist minor normal important serious grave + critical' return ;; limit) - COMPREPLY=($(compgen -W 'submitter date subject msgid package - source tag severity owner affects archive' -- "$cur")) + _comp_compgen -- -W 'submitter date subject msgid package source + tag severity owner affects archive' return ;; clone | "done" | reopen | archive | unarchive | retitle | summary | submitter | found | notfound | fixed | notfixed | merge | forcemerge | unmerge | claim | unclaim | forwarded | notforwarded | owner | noowner | subscribe | unsubscribe | reportspam | spamreport | affects | usertag | usertags | reassign | tag | tags) - COMPREPLY=($(_cached_bugs)) + _comp_compgen -i bts cached_bugs return ;; package) - COMPREPLY=($(_xfunc apt-cache _apt_cache_packages)) + _comp_compgen -x apt-cache packages return ;; cache) - COMPREPLY=($(_xfunc apt-cache _apt_cache_packages) - $(_src_packages_with_prefix) - $(compgen -W 'from: release-critical RC' -- "$cur")) + _comp_compgen -x apt-cache packages + _comp_compgen -ai bts src_packages_with_prefix + _comp_compgen -a -- -W 'from: release-critical RC' return ;; cleancache) - COMPREPLY=($(_xfunc apt-cache _apt_cache_packages) - $(_src_packages_with_prefix) - $(compgen -W 'from: tag: usertag: ALL' -- "$cur")) + _comp_compgen -x apt-cache packages + _comp_compgen -ai bts src_packages_with_prefix + _comp_compgen -a -- -W 'from: tag: usertag: ALL' return ;; user) # non-predicible arguments - COMPREPLY=() return ;; :) @@ -83,30 +87,30 @@ _bts() # COMP_WORDS would be: "bts cleancache src : <partial_pkg_name>" pos=$((COMP_CWORD - 2)) if [[ $pos -gt 0 && ${COMP_WORDS[pos]} == "src" ]]; then - COMPREPLY=($(_xfunc apt-cache _apt_cache_src_packages)) + _comp_compgen -x apt-cache sources + return fi ;; esac - $split && return + [[ $was_split ]] && return - COMPREPLY=($(compgen -W '--offline --online --no-offline - --no-action --cache --no-cache --cache-mode --cache-delay --mbox - --mailreader --cc-addr --use-default-cc --no-use-default-cc - --sendmail --mutt --no-mutt --smtp-host --smtp-username - --smtp-helo --bts-server --force-refresh --no-force-refresh - --only-new --include-resolved --no-include-resolved --no-ack --ack - --interactive --force-interactive --no-interactive --quiet - --no-conf --noconf + _comp_compgen -- -W '--offline --online --no-offline --no-action --cache + --no-cache --cache-mode --cache-delay --mbox --mailreader --cc-addr + --use-default-cc --no-use-default-cc --sendmail --mutt --no-mutt + --smtp-host --smtp-username --smtp-helo --bts-server --force-refresh + --no-force-refresh --only-new --include-resolved --no-include-resolved + --no-ack --ack --interactive --force-interactive --no-interactive + --quiet --no-conf --noconf show bugs select status clone done reopen archive unarchive retitle summary submitter reassign found notfound fixed notfixed block unblock merge forcemerge unmerge tag tags affects user usertag usertags claim unclaim severity forwarded notforwarded package limit owner noowner subscribe unsubscribe reportspam spamreport cache cleancache version - help' -- "$cur")) + help' } && - complete -F _bts bts + complete -F _comp_cmd_bts bts # ex: filetype=sh diff --git a/completions/bzip2 b/completions/bzip2 index 40e50fe..0e5d98f 100644 --- a/completions/bzip2 +++ b/completions/bzip2 @@ -1,28 +1,32 @@ # bash completion for bzip2 -*- shell-script -*- -_bzip2() +_comp_cmd_bzip2() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[bpn]*)' + # shellcheck disable=SC2254 case $prev in - --help | -!(-*)[bhp]) + --help | -${noargopts}[bhp]) return ;; - -!(-*)n) - COMPREPLY=($(compgen -W "{1..$(_ncpus)}" -- "$cur")) + -${noargopts}n) + local REPLY + _comp_get_ncpus + _comp_compgen -- -W "{1..$REPLY}" return ;; esac if [[ $cur == -* ]]; then - local helpopts=$(_parse_help "$1") - COMPREPLY=($(compgen -W "${helpopts//#/} -2 -3 -4 -5 -6 -7 -8 -9" \ - -- "$cur")) + local helpopts + _comp_compgen -Rv helpopts help + _comp_compgen -- -W '${helpopts[*]//#/} -{2..9}' return fi - local IFS=$'\n' xspec="*.?(t)bz2" + local xspec="*.?(t)bz2" if [[ $prev == --* ]]; then [[ $prev == --@(decompress|list|test) ]] && xspec="!"$xspec @@ -32,11 +36,11 @@ _bzip2() [[ $prev == -*z* ]] && xspec= fi - _tilde "$cur" || return + _comp_compgen_tilde && return compopt -o filenames - COMPREPLY=($(compgen -f -X "$xspec" -- "$cur") $(compgen -d -- "$cur")) + _comp_compgen -- -f -X "$xspec" -o plusdirs } && - complete -F _bzip2 bzip2 pbzip2 lbzip2 + complete -F _comp_cmd_bzip2 bzip2 pbzip2 lbzip2 # ex: filetype=sh diff --git a/completions/cancel b/completions/cancel index 3e0c1d5..38571c5 100644 --- a/completions/cancel +++ b/completions/cancel @@ -1,27 +1,26 @@ # cancel(1) completion -*- shell-script -*- -_cancel() +_comp_cmd_cancel() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -h) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -U) return ;; -u) - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u return ;; esac - COMPREPLY=($(compgen -W \ - "$(lpstat 2>/dev/null | cut -d' ' -f1)" -- "$cur")) + _comp_compgen_split -- "$(lpstat 2>/dev/null | cut -d' ' -f1)" } && - complete -F _cancel cancel + complete -F _comp_cmd_cancel cancel # ex: filetype=sh diff --git a/completions/cardctl b/completions/cardctl index bb3a0db..222f7b1 100644 --- a/completions/cardctl +++ b/completions/cardctl @@ -1,15 +1,15 @@ # Linux cardctl(8) completion -*- shell-script -*- -_cardctl() +_comp_cmd_cardctl() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if ((cword == 1)); then - COMPREPLY=($(compgen -W 'status config ident suspend resume reset - eject insert scheme' -- "$cur")) + _comp_compgen -- -W 'status config ident suspend resume reset eject + insert scheme' fi } && - complete -F _cardctl cardctl pccardctl + complete -F _comp_cmd_cardctl cardctl pccardctl # ex: filetype=sh diff --git a/completions/carton b/completions/carton index 5d700c8..7f99c90 100644 --- a/completions/carton +++ b/completions/carton @@ -1,81 +1,95 @@ # carton(3pm) completion -*- shell-script -*- -_carton_commands() +_comp_cmd_carton__commands() { - local cmds=$("${1:-carton}" usage 2>&1 | + local cmds=$("$1" usage 2>&1 | command sed -ne '/.*command.* is one of/{n;p;q;}') - COMPREPLY+=($(IFS="$IFS," compgen -W "$cmds" -- "$cur")) + _comp_compgen -aF $' \t\n,' -- -W "$cmds" } -_carton_command_help() +_comp_cmd_carton__command_help() { - local help=$(PERLDOC_PAGER=cat PERLDOC=-otext "${1:-carton}" -h $2 2>&1) - COMPREPLY+=($(compgen -W '$help' -- "$cur")) + local help=$(PERLDOC_PAGER=cat PERLDOC=-otext "$1" -h "$2" 2>&1) + _comp_compgen -a -- -W '$help' } -_carton() +_comp_cmd_carton() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return - local i command + local i command="" has_command="" for ((i = 1; i < cword; i++)); do case ${words[i]} in -*) ;; *) command=${words[i]} + has_command=set break ;; esac done - if [[ ! -v command ]]; then - _carton_commands "$1" + if [[ ! $has_command ]]; then + _comp_cmd_carton__commands "$1" return fi case $prev in - --version | -v) - return - ;; - --help | -h) - [[ -n $command ]] || _carton_commands "$1" + --version | --help | -[vh]) return ;; --cpanfile) if [[ $command == install ]]; then - _filedir + _comp_compgen_filedir return fi ;; --path) if [[ $command == install ]]; then - _filedir -d + _comp_compgen_filedir -d return fi ;; --without) if [[ $command == install ]]; then local phases="configure build test runtime develop" - COMPREPLY+=($(compgen -W '$phases' -- "$cur")) + _comp_compgen -a -- -W '$phases' return fi ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then [[ $command == @(help|usage) ]] || COMPREPLY=(--help) - _carton_command_help "$1" $command + _comp_cmd_carton__command_help "$1" "$command" fi case $command in + exec) + # skip all the options --, -v, etc. and identify the command name + # position. + for ((i++; i < cword; i++)); do + case ${words[i]} in + --) + ((i++)) + break + ;; + -*) ;; + *) break ;; + esac + done + + _comp_command_offset "$i" + return + ;; show | update) : # TODO modules completion ;; esac } && - complete -F _carton carton + complete -F _comp_cmd_carton carton # ex: filetype=sh diff --git a/completions/ccache b/completions/ccache index 80c39de..fb3f3e4 100644 --- a/completions/ccache +++ b/completions/ccache @@ -1,38 +1,40 @@ # ccache(1) completion -*- shell-script -*- -_ccache() +_comp_cmd_ccache() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return local i - for ((i = 1; i <= COMP_CWORD; i++)); do - if [[ ${COMP_WORDS[i]} != -* ]]; then - _command_offset $i + for ((i = 1; i <= cword; i++)); do + if [[ ${words[i]} != -* ]]; then + _comp_command_offset $i return fi - [[ ${COMP_WORDS[i]} == -*[oFM] ]] && ((i++)) + [[ ${words[i]} == -*[oFM] ]] && ((i++)) done + local noargopts='!(-*|*[FMo]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | --max-files | --max-size | -!(-*)[hVFM]) + --help | --version | --max-files | --max-size | -${noargopts}[hVFM]) return ;; - --set-config | -!(-*)o) + --set-config | -${noargopts}o) if [[ $cur != *=* ]]; then - COMPREPLY=($(compgen -S = -W "$($1 -p 2>/dev/null | - awk '$3 = "=" { print $2 }')" -- "$cur")) + _comp_compgen_split -S = -- "$("$1" -p 2>/dev/null | + _comp_awk '$3 = "=" { print $2 }')" [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi return ;; esac - $split && return + [[ $was_split ]] && return - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace } && - complete -F _ccache ccache + complete -F _comp_cmd_ccache ccache # ex: filetype=sh diff --git a/completions/ccze b/completions/ccze index 35f4c3f..31602b0 100644 --- a/completions/ccze +++ b/completions/ccze @@ -1,44 +1,45 @@ # ccze(1) completion -*- shell-script -*- -_ccze() +_comp_cmd_ccze() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[acFmop]*)' + # shellcheck disable=SC2254 case $prev in -'?' | --help | --usage | -V | --version) return ;; - --argument | --color | -!(-*)[ac]) + --argument | --color | -${noargopts}[ac]) # TODO? return ;; - --rcfile | -!(-*)F) - _filedir + --rcfile | -${noargopts}F) + _comp_compgen_filedir return ;; - --mode | -!(-*)m) - COMPREPLY=($(compgen -W "curses ansi html" -- "$cur")) + --mode | -${noargopts}m) + _comp_compgen -- -W "curses ansi html" return ;; - --option | -!(-*)o) + --option | -${noargopts}o) local -a opts=(scroll wordcolor lookups transparent cssfile) - COMPREPLY=($(compgen -W '${opts[@]} ${opts[@]/#/no}' -- "$cur")) + _comp_compgen -- -W '"${opts[@]}" "${opts[@]/#/no}"' return ;; - --plugin | -!(-*)p) - COMPREPLY=($(compgen -W '$("$1" --list-plugins | command \ - sed -ne "s/^\([a-z0-9]\{1,\}\)[[:space:]]\{1,\}|.*/\1/p")' \ - -- "$cur")) + --plugin | -${noargopts}p) + _comp_compgen_split -- "$("$1" --list-plugins | command \ + sed -ne 's/^\([a-z0-9]\{1,\}\)[[:space:]]\{1,\}|.*/\1/p')" return ;; esac - $split && return + [[ $was_split ]] && return - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace } && - complete -F _ccze ccze + complete -F _comp_cmd_ccze ccze # ex: filetype=sh diff --git a/completions/cd b/completions/cd new file mode 100644 index 0000000..67dc3de --- /dev/null +++ b/completions/cd @@ -0,0 +1,59 @@ +# cd(1) completion -*- shell-script -*- + +# This meta-cd function observes the CDPATH variable, so that `cd` +# additionally completes on directories under those specified in CDPATH. +_comp_cmd_cd() +{ + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + + if [[ $cur == -* ]]; then + _comp_compgen_help -c help "$1" + compopt +o nospace + return + fi + + local i j k + + compopt -o filenames + + # Use standard dir completion if no CDPATH or parameter starts with /, + # ./ or ../ + if [[ ! ${CDPATH-} || $cur == ?(.)?(.)/* ]]; then + _comp_compgen_filedir -d + return + fi + + local mark_dirs="" mark_symdirs="" + _comp_readline_variable_on mark-directories && mark_dirs=set + _comp_readline_variable_on mark-symlinked-directories && mark_symdirs=set + + # we have a CDPATH, so loop on its contents + local paths dirs + _comp_split -F : paths "$CDPATH" + for i in "${paths[@]}"; do + # create an array of matched subdirs + k=${#COMPREPLY[@]} + _comp_compgen -v dirs -c "$i/$cur" -- -d + for j in "${dirs[@]}"; do + if [[ ($mark_symdirs && -L $j || $mark_dirs && ! -L $j) && ! -d ${j#"$i/"} ]]; then + j+="/" + fi + COMPREPLY[k++]=${j#"$i/"} + done + done + + _comp_compgen -a filedir -d + + if ((${#COMPREPLY[@]} == 1)); then + i=${COMPREPLY[0]} + if [[ $i == "$cur" && $i != "*/" ]]; then + COMPREPLY[0]="${i}/" + fi + fi +} +if shopt -q cdable_vars; then + complete -v -F _comp_cmd_cd -o nospace cd pushd +else + complete -F _comp_cmd_cd -o nospace cd pushd +fi diff --git a/completions/cfagent b/completions/cfagent index e7ba04d..113e417 100644 --- a/completions/cfagent +++ b/completions/cfagent @@ -1,21 +1,21 @@ # cfagent completion -*- shell-script -*- -_cfagent() +_comp_cmd_cfagent() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -f | --file) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help fi } && - complete -F _cfagent cfagent + complete -F _comp_cmd_cfagent cfagent # ex: filetype=sh diff --git a/completions/cfrun b/completions/cfrun index 72b6138..445bccd 100644 --- a/completions/cfrun +++ b/completions/cfrun @@ -1,9 +1,9 @@ # cfrun completion -*- shell-script -*- -_cfrun() +_comp_cmd_cfrun() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local i section=1 for ((i = 1; i < cword; i++)); do @@ -16,13 +16,13 @@ _cfrun() 1) case $prev in -f) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-f -h -d -S -T -v' -- "$cur")) + _comp_compgen -- -W '-f -h -d -S -T -v' else local hostfile=${CFINPUTS:-/var/lib/cfengine/inputs}/cfrun.hosts for ((i = 1; i < cword; i++)); do @@ -33,15 +33,15 @@ _cfrun() done [[ ! -f $hostfile ]] && return - COMPREPLY=($(compgen -W "$(command grep -v \ - -E '(=|^$|^#)' $hostfile)" -- "$cur")) + _comp_compgen_split -- "$(command grep -v -E '(=|^$|^#)' \ + "$hostfile")" fi ;; 2) - COMPREPLY=($(compgen -W '$(_parse_help cfagent)' -- "$cur")) + _comp_compgen_help -c cfagent --help ;; esac } && - complete -F _cfrun cfrun + complete -F _comp_cmd_cfrun cfrun # ex: filetype=sh diff --git a/completions/chage b/completions/chage index fcf87cd..f00433d 100644 --- a/completions/chage +++ b/completions/chage @@ -1,30 +1,32 @@ # chage(1) completion -*- shell-script -*- -_chage() +_comp_cmd_chage() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[dEImMWR]*)' + # shellcheck disable=SC2254 case $prev in --lastday | --expiredate | --help | --inactive | --mindays | --maxdays | \ - --warndays | -!(-*)[dEhImMW]) + --warndays | -${noargopts}[dEhImMW]) return ;; - --root | -!(-*)R) - _filedir -d + --root | -${noargopts}R) + _comp_compgen_filedir -d return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u } && - complete -F _chage chage + complete -F _comp_cmd_chage chage # ex: filetype=sh diff --git a/completions/change_pw b/completions/change_pw index 04837ea..819c082 100644 --- a/completions/change_pw +++ b/completions/change_pw @@ -1,25 +1,28 @@ # mailman change_pw completion -*- shell-script -*- -_change_pw() +_comp_cmd_change_pw() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -l | --listname) - _xfunc list_lists _mailman_lists + # Prefer `list_lists` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen -x list_lists mailman_lists return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--all --domain --listname --password --quiet - --help' -- "$cur")) + _comp_compgen -- -W '--all --domain --listname --password --quiet + --help' fi } && - complete -F _change_pw change_pw + complete -F _comp_cmd_change_pw change_pw # ex: filetype=sh diff --git a/completions/check_db b/completions/check_db index aaec99f..6480a11 100644 --- a/completions/check_db +++ b/completions/check_db @@ -1,17 +1,20 @@ # mailman check_db completion -*- shell-script -*- -_check_db() +_comp_cmd_check_db() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--all --verbose --help' -- "$cur")) + _comp_compgen -- -W '--all --verbose --help' else - _xfunc list_lists _mailman_lists + # Prefer `list_lists` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen -x list_lists mailman_lists fi } && - complete -F _check_db check_db + complete -F _comp_cmd_check_db check_db # ex: filetype=sh diff --git a/completions/check_perms b/completions/check_perms index 8ff276e..0ff1ffd 100644 --- a/completions/check_perms +++ b/completions/check_perms @@ -1,15 +1,15 @@ # mailman check_perms completion -*- shell-script -*- -_check_perms() +_comp_cmd_check_perms() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-f -v -h' -- "$cur")) + _comp_compgen -- -W '-f -v -h' fi } && - complete -F _check_perms check_perms + complete -F _comp_cmd_check_perms check_perms # ex: filetype=sh diff --git a/completions/checksec b/completions/checksec index fc2fef7..95e2dce 100644 --- a/completions/checksec +++ b/completions/checksec @@ -1,37 +1,48 @@ # bash completion for checksec -*- shell-script -*- -_checksec() +_comp_cmd_checksec() { - local cur prev words cword - _init_completion || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in --version | --help) return ;; --file | --fortify-file) - _filedir + _comp_compgen_filedir return ;; --dir) - _filedir -d + _comp_compgen_filedir -d return ;; --proc) - _pnames + _comp_compgen_pnames return ;; --proc-libs | --fortify-proc) - _pids + _comp_compgen_pids return ;; + --format) + _comp_compgen_split -- "$("$1" --help 2>/dev/null | + command sed -ne 's/[{,}]/ /g;s/^[[:space:]]*--format=//p')" + ;; + --output) + _comp_compgen_split -- "$("$1" --help 2>/dev/null | + command sed -ne 's/[{,}]/ /g;s/^[[:space:]]*--output=//p')" + ;; esac + [[ $was_split ]] && return + if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help + [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi } && - complete -F _checksec checksec + complete -F _comp_cmd_checksec checksec # ex: filetype=sh diff --git a/completions/chgrp b/completions/chgrp index 4793a45..1e19750 100644 --- a/completions/chgrp +++ b/completions/chgrp @@ -1,39 +1,39 @@ # chgrp(1) completion -*- shell-script -*- -_chgrp() +_comp_cmd_chgrp() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return cur=${cur//\\\\/} if [[ $prev == --reference ]]; then - _filedir + _comp_compgen_filedir return fi - $split && return + [[ $was_split ]] && return # options completion if [[ $cur == -* ]]; then - local w opts + local w opts="" for w in "${words[@]}"; do [[ $w == -@(R|-recursive) ]] && opts="-H -L -P" && break done - COMPREPLY=($(compgen -W '-c -h -f -R -v --changes --dereference + _comp_compgen -- -W '-c -h -f -R -v --changes --dereference --no-dereference --silent --quiet --reference --recursive --verbose - --help --version $opts' -- "$cur")) + --help --version $opts' return fi # first parameter on line or first since an option? if [[ $cword -eq 1 && $cur != -* || $prev == -* ]]; then - _allowed_groups "$cur" + _comp_compgen_allowed_groups else - _filedir + _comp_compgen_filedir fi } && - complete -F _chgrp chgrp + complete -F _comp_cmd_chgrp chgrp # ex: filetype=sh diff --git a/completions/chkconfig b/completions/chkconfig index 8ff6637..32c3392 100644 --- a/completions/chkconfig +++ b/completions/chkconfig @@ -1,37 +1,35 @@ # chkconfig(8) completion -*- shell-script -*- -_chkconfig() +_comp_cmd_chkconfig() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in --level=[1-6] | [1-6] | --list | --add | --del | --override) - _services - _xinetd_services + _comp_compgen_services + _comp_compgen -a xinetd_services return ;; --level) - COMPREPLY=($(compgen -W '{1..6}' -- "$cur")) + _comp_compgen -- -W '{1..6}' return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--list --add --del --override --level' \ - -- "$cur")) + _comp_compgen -- -W '--list --add --del --override --level' else if ((cword == 2 || cword == 4)); then - COMPREPLY=($(compgen -W 'on off reset resetpriorities' \ - -- "$cur")) + _comp_compgen -- -W 'on off reset resetpriorities' else - _services - _xinetd_services + _comp_compgen_services + _comp_compgen -a xinetd_services fi fi } && - complete -F _chkconfig chkconfig + complete -F _comp_cmd_chkconfig chkconfig # ex: filetype=sh diff --git a/completions/chmod b/completions/chmod index d3fc349..3dbc16f 100644 --- a/completions/chmod +++ b/completions/chmod @@ -1,41 +1,40 @@ # chmod(1) completion -*- shell-script -*- -_chmod() +_comp_cmd_chmod() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in --help | --version) return ;; --reference) - _filedir + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return # Adapted from coreutils 8.28 chmod man page local modearg="-@(@(+([rwxXst])|[ugo])|+([0-7]))" # shellcheck disable=SC2053 if [[ $cur == -* && $cur != $modearg ]]; then - local opts=$(_parse_help "$1") - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - local args - _count_args "" "" "$modearg" + local REPLY + _comp_count_args -i "$modearg" - case $args in + case $REPLY in 1) ;; # mode - *) _filedir ;; + *) _comp_compgen_filedir ;; esac } && - complete -F _chmod chmod + complete -F _comp_cmd_chmod chmod # ex: filetype=sh diff --git a/completions/chown b/completions/chown index 1d746b7..25d0d67 100644 --- a/completions/chown +++ b/completions/chown @@ -1,46 +1,46 @@ # chown(1) completion -*- shell-script -*- -_chown() +_comp_cmd_chown() { - local cur prev words cword split + local cur prev words cword was_split comp_args # Don't treat user:group as separate words. - _init_completion -s -n : || return + _comp_initialize -s -n : -- "$@" || return case "$prev" in --from) - _usergroup + _comp_compgen_usergroups return ;; --reference) - _filedir + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then # Complete -options - local w opts + local w opts="" for w in "${words[@]}"; do [[ $w == -@(R|-recursive) ]] && opts="-H -L -P" && break done - COMPREPLY=($(compgen -W '-c -h -f -R -v --changes --dereference + _comp_compgen -- -W '-c -h -f -R -v --changes --dereference --no-dereference --from --silent --quiet --reference --recursive - --verbose --help --version $opts' -- "$cur")) + --verbose --help --version $opts' else - local args + local REPLY - # The first argument is an usergroup; the rest are filedir. - _count_args : + # The first argument is a usergroup; the rest are filedir. + _comp_count_args - if ((args == 1)); then - _usergroup -u + if ((REPLY == 1)); then + _comp_compgen_usergroups -u else - _filedir + _comp_compgen_filedir fi fi } && - complete -F _chown chown + complete -F _comp_cmd_chown chown # ex: filetype=sh diff --git a/completions/chpasswd b/completions/chpasswd index 3abea99..996bff0 100644 --- a/completions/chpasswd +++ b/completions/chpasswd @@ -1,30 +1,31 @@ # chpasswd(8) completion -*- shell-script -*- -_chpasswd() +_comp_cmd_chpasswd() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[csR]*)' + # shellcheck disable=SC2254 case $prev in - --crypt | -!(-*)c) - COMPREPLY=($(compgen -W 'DES MD5 NONE SHA256 SHA512' \ - -- "$cur")) + --crypt | -${noargopts}c) + _comp_compgen -- -W 'DES MD5 NONE SHA256 SHA512' return ;; - --sha-rounds | -!(-*)s) + --sha-rounds | -${noargopts}s) return ;; - --root | -!(-*)R) - _filedir -d + --root | -${noargopts}R) + _comp_compgen_filedir -d return ;; esac - $split && return + [[ $was_split ]] && return - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace } && - complete -F _chpasswd chpasswd + complete -F _comp_cmd_chpasswd chpasswd # ex: filetype=sh diff --git a/completions/chromium-browser b/completions/chromium-browser index 9ee9896..2126ac6 100644 --- a/completions/chromium-browser +++ b/completions/chromium-browser @@ -1,50 +1,50 @@ # chromium-browser completion -*- shell-script -*- -_chromium_browser() +_comp_cmd_chromium_browser() { - local cur prev words cword split - _init_completion -s -n : || return + local cur prev words cword was_split comp_args + _comp_initialize -s -n : -- "$@" || return case $prev in --help | --app | --proxy-pac-url | -h) return ;; --user-data-dir) - _filedir -d + _comp_compgen_filedir -d return ;; --proxy-server) case $cur in *://*) local prefix="${cur%%://*}://" - _known_hosts_real -- "${cur#*://}" - COMPREPLY=("${COMPREPLY[@]/#/$prefix}") - __ltrim_colon_completions "$cur" + _comp_compgen_known_hosts -- "${cur#*://}" && + _comp_compgen -Rv COMPREPLY -- -P "$prefix" -W '"${COMPREPLY[@]}"' + _comp_ltrim_colon_completions "$cur" ;; *) compopt -o nospace - COMPREPLY=($(compgen -S :// -W 'http socks socks4 socks5' -- "$cur")) + _comp_compgen -- -S :// -W 'http socks socks4 socks5' ;; esac return ;; --password-store) - COMPREPLY=($(compgen -W 'basic gnome kwallet' -- "$cur")) + _comp_compgen -- -W 'basic gnome kwallet' return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir "@(?([mxs])htm?(l)|pdf|txt)" + _comp_compgen_filedir "@(?([mxs])htm?(l)|pdf|txt)" } && - complete -F _chromium_browser chromium-browser google-chrome \ + complete -F _comp_cmd_chromium_browser chromium-browser google-chrome \ google-chrome-stable chromium chrome # ex: filetype=sh diff --git a/completions/chronyc b/completions/chronyc index e6bb8e9..15a784b 100644 --- a/completions/chronyc +++ b/completions/chronyc @@ -1,34 +1,36 @@ # chronyc(1) completion -*- shell-script -*- -_chronyc_command_args() +_comp_cmd_chronyc__command_args() { local -a args - args=($(compgen -W "$($1 help 2>/dev/null | - awk '/^'$prev'\s[^ []/ { gsub("\\|", " ", $2); print $2 }')")) + _comp_split args "$("$1" help 2>/dev/null | + _comp_awk '/^'"$prev"'[ \t][^ []/ { gsub("\\|", " ", $2); print $2 }')" case $args in - \<address\>) _known_hosts_real -- "$cur" ;; + \<address\>) _comp_compgen_known_hosts -- "$cur" ;; \<*) ;; - *) COMPREPLY+=($(compgen -W '${args[@]}' -- "$cur")) ;; + *) ((${#args[@]})) && + _comp_compgen -a -- -W '"${args[@]}"' ;; esac } -_chronyc() +_comp_cmd_chronyc() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --help | -*p) return ;; -*h) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1") -6' -- "$cur")) + _comp_compgen_usage + _comp_compgen -a -- -W '-6' return fi @@ -40,22 +42,21 @@ _chronyc() case $args in 0) - COMPREPLY=($(compgen -W "$($1 help 2>/dev/null | - awk '!/(^ |: *$)/ { sub("\\|", " ", $1); print $1 }')" \ - -- "$cur")) + _comp_compgen_split -- "$("$1" help 2>/dev/null | + _comp_awk '!/(^ |: *$)/ { sub("\\|", " ", $1); print $1 }')" ;; 1) - _chronyc_command_args "$1" + _comp_cmd_chronyc__command_args "$1" if [[ ! ${COMPREPLY-} && $prev == sources?(tats) ]]; then - # [-v] not handled by _chronyc_command_args yet - COMPREPLY=($(compgen -W '-v' -- "$cur")) + # [-v] not handled by _comp_cmd_chronyc__command_args yet + _comp_compgen -- -W '-v' fi ;; 2) - [[ $prev == @(peer|server) ]] && _known_hosts_real -- "$cur" + [[ $prev == @(peer|server) ]] && _comp_compgen_known_hosts -- "$cur" ;; esac } && - complete -F _chronyc chronyc + complete -F _comp_cmd_chronyc chronyc # ex: filetype=sh diff --git a/completions/chrpath b/completions/chrpath index 2883967..c248a05 100644 --- a/completions/chrpath +++ b/completions/chrpath @@ -1,27 +1,29 @@ # chrpath(1) completion -*- shell-script -*- -_chrpath() +_comp_cmd_chrpath() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[r]*)' + # shellcheck disable=SC2254 case $prev in - --version | --help | -!(-*)[vh]) + --version | --help | -${noargopts}[vh]) return ;; - --replace | -!(-*)r) - _filedir -d + --replace | -${noargopts}r) + _comp_compgen_filedir -d return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - _filedir + _comp_compgen_filedir } && - complete -F _chrpath chrpath + complete -F _comp_cmd_chrpath chrpath # ex: filetype=sh diff --git a/completions/cksfv b/completions/cksfv index da404dd..406c8de 100644 --- a/completions/cksfv +++ b/completions/cksfv @@ -1,29 +1,29 @@ # cksfv completion by Chris <xris@forevermore.net> -*- shell-script -*- -_cksfv() +_comp_cmd_cksfv() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if ((cword == 1)); then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi case "$prev" in -*C | -*g) - _filedir -d + _comp_compgen_filedir -d return ;; -*f) - _filedir 'sfv' + _comp_compgen_filedir 'sfv' return ;; esac - _filedir + _comp_compgen_filedir } && - complete -F _cksfv cksfv + complete -F _comp_cmd_cksfv cksfv # ex: filetype=sh diff --git a/completions/cleanarch b/completions/cleanarch index 0f7d5f5..c34d038 100644 --- a/completions/cleanarch +++ b/completions/cleanarch @@ -1,16 +1,15 @@ # mailman cleanarch completion -*- shell-script -*- -_cleanarch() +_comp_cmd_cleanarch() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--status --dry-run --quiet --help' \ - -- "$cur")) + _comp_compgen -- -W '--status --dry-run --quiet --help' fi } && - complete -F _cleanarch cleanarch + complete -F _comp_cmd_cleanarch cleanarch # ex: filetype=sh diff --git a/completions/clisp b/completions/clisp index c4259a0..73bf8b2 100644 --- a/completions/clisp +++ b/completions/clisp @@ -2,21 +2,21 @@ # bash brogrammable completion for various Common Lisp implementations by # Nikodemus Siivola <nikodemus@random-state.net> -_clisp() +_comp_cmd_clisp() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return # completing an option (may or may not be separated by a space) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-h --help --version --license -B -K -M -m -L - -N -E -q --quiet --silent -w -I -ansi -traditional -p -C -norc -i - -c -l -o -x ' -- "$cur")) + _comp_compgen -- -W '-h --help --version --license -B -K -M -m -L -N -E + -q --quiet --silent -w -I -ansi -traditional -p -C -norc -i -c -l + -o -x ' else - _filedir + _comp_compgen_filedir fi } && - complete -F _clisp -o default clisp + complete -F _comp_cmd_clisp -o default clisp # ex: filetype=sh diff --git a/completions/clone_member b/completions/clone_member index a3ca2b3..01f87e6 100644 --- a/completions/clone_member +++ b/completions/clone_member @@ -1,25 +1,28 @@ # mailman clone_member completion -*- shell-script -*- -_clone_member() +_comp_cmd_clone_member() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -l | --listname) - _xfunc list_lists _mailman_lists + # Prefer `list_lists` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen -x list_lists mailman_lists return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--listname --remove --admin --quiet - --nomodify --help' -- "$cur")) + _comp_compgen -- -W '--listname --remove --admin --quiet --nomodify + --help' fi } && - complete -F _clone_member clone_member + complete -F _comp_cmd_clone_member clone_member # ex: filetype=sh diff --git a/completions/complete b/completions/complete index a57f366..74ae3f9 100644 --- a/completions/complete +++ b/completions/complete @@ -1,49 +1,49 @@ # bash complete completion -*- shell-script -*- -_complete() +_comp_cmd_complete() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*o) - COMPREPLY=($(compgen -W 'bashdefault default dirnames filenames - nospace plusdirs' -- "$cur")) + _comp_compgen -- -W 'bashdefault default dirnames filenames nospace + plusdirs' return ;; -*A) - COMPREPLY=($(compgen -W 'alias arrayvar binding builtin command + _comp_compgen -- -W 'alias arrayvar binding builtin command directory disabled enabled export file function group helptopic hostname job keyword running service setopt shopt signal - stopped user variable' -- "$cur")) + stopped user variable' return ;; -*C) - COMPREPLY=($(compgen -A command -- "$cur")) + _comp_compgen -- -A command return ;; -*F) - COMPREPLY=($(compgen -A function -- "$cur")) + _comp_compgen -- -A function return ;; -*p | -*r) - COMPREPLY=($(complete -p | command sed -e 's|.* ||')) - COMPREPLY=($(compgen -W '${COMPREPLY[@]}' -- "$cur")) + _comp_compgen_split -l -- "$(complete -p | command sed -e 's|.* ||')" return ;; esac if [[ $cur == -* ]]; then - # relevant options completion - local opts="-a -b -c -d -e -f -g -j -k -o -s -u -v -A -G -W -P -S -X" - [[ $1 != compgen ]] && opts+=" -F -C" - COMPREPLY=($(compgen -W "$opts" -- "$cur")) + local -a opts + _comp_compgen -v opts usage -c help -s "$1" + # -F, -C do not work the expected way with compgen + [[ $1 != *compgen ]] || opts=("${opts[@]//-[FC]/}") + _comp_compgen -- -W '"${opts[@]}"' -X '' else - COMPREPLY=($(compgen -A command -- "$cur")) + _comp_compgen -- -A command fi } && - complete -F _complete compgen complete + complete -F _comp_cmd_complete compgen complete # ex: filetype=sh diff --git a/completions/config_list b/completions/config_list index 1807e33..d75ef2e 100644 --- a/completions/config_list +++ b/completions/config_list @@ -1,27 +1,30 @@ # mailman config_list completion -*- shell-script -*- -_config_list() +_comp_cmd_config_list() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -i | -o | --inputfile | --outputfile) - _filedir + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--inputfile --outputfile --checkonly - --verbose --help' -- "$cur")) + _comp_compgen -- -W '--inputfile --outputfile --checkonly + --verbose --help' else - _xfunc list_lists _mailman_lists + # Prefer `list_lists` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_xfunc list_lists mailman_lists fi } && - complete -F _config_list config_list + complete -F _comp_cmd_config_list config_list # ex: filetype=sh diff --git a/completions/configure b/completions/configure index 3f59a01..a61a05d 100644 --- a/completions/configure +++ b/completions/configure @@ -1,9 +1,12 @@ # bash completion for configure -*- shell-script -*- -_configure() +_comp_deprecate_var 2.12 \ + COMP_CONFIGURE_HINTS BASH_COMPLETION_CMD_CONFIGURE_HINTS + +_comp_cmd_configure() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -h | --help | -V | --version | --program-prefix | --program-suffix | \ @@ -11,32 +14,32 @@ _configure() return ;; --*file) - _filedir + _comp_compgen_filedir return ;; --*prefix | --*dir) - _filedir -d + _comp_compgen_filedir -d return ;; esac - $split && return - - # if $COMP_CONFIGURE_HINTS is not null, then completions of the form - # --option=SETTING will include 'SETTING' as a contextual hint - [[ $cur != -* ]] && return + if [[ $was_split || $cur != -* ]]; then + _comp_compgen_filedir + return + fi - if [[ ${COMP_CONFIGURE_HINTS-} ]]; then - COMPREPLY=($(compgen -W "$($1 --help 2>&1 | - awk '/^ --[A-Za-z]/ { print $1; \ - if ($2 ~ /--[A-Za-z]/) print $2 }' | command sed -e 's/[[,].*//g')" \ - -- "$cur")) + # if $BASH_COMPLETION_CMD_CONFIGURE_HINTS is not null, then completions of + # the form --option=SETTING will include 'SETTING' as a contextual hint + if [[ ${BASH_COMPLETION_CMD_CONFIGURE_HINTS-} ]]; then + _comp_compgen_split -- "$("$1" --help 2>&1 | + _comp_awk '/^ --[A-Za-z]/ { print $1; \ + if ($2 ~ /--[A-Za-z]/) print $2 }' | command sed -e 's/[[,].*//g')" [[ ${COMPREPLY-} == *=* ]] && compopt -o nospace else - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _configure configure + complete -F _comp_cmd_configure configure # ex: filetype=sh diff --git a/completions/convert b/completions/convert index ef7baea..b01633b 100644 --- a/completions/convert +++ b/completions/convert @@ -1,125 +1,118 @@ # bash completion for ImageMagick -*- shell-script -*- -_ImageMagick() +_comp_cmd_convert__common_options() { case $prev in -channel) - COMPREPLY=($(compgen -W 'Red Green Blue Opacity Matte Cyan - Magenta Yellow Black' -- "$cur")) + _comp_compgen -- -W 'Red Green Blue Opacity Matte Cyan Magenta + Yellow Black' return ;; -colormap) - COMPREPLY=($(compgen -W 'shared private' -- "$cur")) + _comp_compgen -- -W 'shared private' return ;; -colorspace) - COMPREPLY=($(compgen -W 'GRAY OHTA RGB Transparent XYZ YCbCr YIQ - YPbPr YUV CMYK' -- "$cur")) + _comp_compgen -- -W 'GRAY OHTA RGB Transparent XYZ YCbCr YIQ YPbPr + YUV CMYK' return ;; -compose) - COMPREPLY=($(compgen -W 'Over In Out Atop Xor Plus Minus Add - Subtract Difference Multiply Bumpmap Copy CopyRed CopyGreen - CopyBlue CopyOpacity' -- "$cur")) + _comp_compgen -- -W 'Over In Out Atop Xor Plus Minus Add Subtract + Difference Multiply Bumpmap Copy CopyRed CopyGreen CopyBlue + CopyOpacity' return ;; -compress) - COMPREPLY=($(compgen -W 'None BZip Fax Group4 JPEG Lossless LZW - RLE Zip' -- "$cur")) + _comp_compgen -- -W 'None BZip Fax Group4 JPEG Lossless LZW RLE + Zip' return ;; -dispose) - COMPREPLY=($(compgen -W 'Undefined None Background Previous' \ - -- "$cur")) + _comp_compgen -- -W 'Undefined None Background Previous' return ;; -encoding) - COMPREPLY=($(compgen -W 'AdobeCustom AdobeExpert AdobeStandard + _comp_compgen -- -W 'AdobeCustom AdobeExpert AdobeStandard AppleRoman BIG5 GB2312 Latin2 None SJIScode Symbol Unicode - Wansung' -- "$cur")) + Wansung' return ;; -endian) - COMPREPLY=($(compgen -W 'MSB LSB' -- "$cur")) + _comp_compgen -- -W 'MSB LSB' return ;; -filter) - COMPREPLY=($(compgen -W 'Point Box Triangle Hermite Hanning - Hamming Blackman Gaussian Quadratic Cubic Catrom Mitchell - Lanczos Bessel Sinc' -- "$cur")) + _comp_compgen -- -W 'Point Box Triangle Hermite Hanning Hamming + Blackman Gaussian Quadratic Cubic Catrom Mitchell Lanczos + Bessel Sinc' return ;; -format) - COMPREPLY=($(compgen -W "$(convert -list format | awk \ - '/ [r-][w-][+-] / { sub("[*]$","",$1); print tolower($1) }')" \ - -- "$cur")) + _comp_compgen_split -- "$(convert -list format | _comp_awk \ + '/ [r-][w-][+-] / { sub("[*]$","",$1); print tolower($1) }')" return ;; -gravity) - COMPREPLY=($(compgen -W 'Northwest North NorthEast West Center - East SouthWest South SouthEast' -- "$cur")) + _comp_compgen -- -W 'Northwest North NorthEast West Center East + SouthWest South SouthEast' return ;; -intent) - COMPREPLY=($(compgen -W 'Absolute Perceptual Relative - Saturation' -- "$cur")) + _comp_compgen -- -W 'Absolute Perceptual Relative Saturation' return ;; -interlace) - COMPREPLY=($(compgen -W 'None Line Plane Partition' -- "$cur")) + _comp_compgen -- -W 'None Line Plane Partition' return ;; -limit) - COMPREPLY=($(compgen -W 'Disk File Map Memory' -- "$cur")) + _comp_compgen -- -W 'Disk File Map Memory' return ;; -list) - COMPREPLY=($(compgen -W 'Delegate Format Magic Module Resource - Type' -- "$cur")) + _comp_compgen -- -W 'Delegate Format Magic Module Resource Type' return ;; -map) - COMPREPLY=($(compgen -W 'best default gray red green blue' \ - -- "$cur")) - _filedir + _comp_compgen -- -W 'best default gray red green blue' + _comp_compgen -a filedir return ;; -noise) - COMPREPLY=($(compgen -W 'Uniform Gaussian Multiplicative - Impulse Laplacian Poisson' -- "$cur")) + _comp_compgen -- -W 'Uniform Gaussian Multiplicative Impulse + Laplacian Poisson' return ;; -preview) - COMPREPLY=($(compgen -W 'Rotate Shear Roll Hue Saturation - Brightness Gamma Spiff Dull Grayscale Quantize Despeckle - ReduceNoise AddNoise Sharpen Blur Treshold EdgeDetect Spread - Shade Raise Segment Solarize Swirl Implode Wave OilPaint - CharcoalDrawing JPEG' -- "$cur")) + _comp_compgen -- -W 'Rotate Shear Roll Hue Saturation Brightness + Gamma Spiff Dull Grayscale Quantize Despeckle ReduceNoise + AddNoise Sharpen Blur Threshold EdgeDetect Spread Shade Raise + Segment Solarize Swirl Implode Wave OilPaint CharcoalDrawing + JPEG' return ;; -mask | -profile | -texture | -tile | -write) - _filedir + _comp_compgen_filedir return ;; -type) - COMPREPLY=($(compgen -W 'Bilevel Grayscale Palette PaletteMatte + _comp_compgen -- -W 'Bilevel Grayscale Palette PaletteMatte TrueColor TrueColorMatte ColorSeparation ColorSeparationlMatte - Optimize' -- "$cur")) + Optimize' return ;; -units) - COMPREPLY=($(compgen -W 'Undefined PixelsPerInch - PixelsPerCentimeter' -- "$cur")) + _comp_compgen -- -W 'Undefined PixelsPerInch PixelsPerCentimeter' return ;; -virtual-pixel) - COMPREPLY=($(compgen -W 'Constant Edge mirror tile' -- "$cur")) + _comp_compgen -- -W 'Constant Edge mirror tile' return ;; -visual) - COMPREPLY=($(compgen -W 'StaticGray GrayScale StaticColor - PseudoColor TrueColor DirectColor defaut visualid' \ - -- "$cur")) + _comp_compgen -- -W 'StaticGray GrayScale StaticColor PseudoColor + TrueColor DirectColor default visualid' return ;; esac @@ -127,198 +120,197 @@ _ImageMagick() return 1 } -_convert() +_comp_cmd_convert() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - _ImageMagick && return + _comp_cmd_convert__common_options && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help elif [[ $cur == +* ]]; then - COMPREPLY=($(compgen -W '+adjoin +append +compress +contrast +debug - +dither +endian +gamma +label +map +mask +matte +negate +noise - +page +raise +render +write' -- "$cur")) + _comp_compgen -- -W '+adjoin +append +compress +contrast +debug +dither + +endian +gamma +label +map +mask +matte +negate +noise +page +raise + +render +write' else - _filedir + _comp_compgen_filedir fi } && - complete -F _convert convert + complete -F _comp_cmd_convert convert -_mogrify() +_comp_cmd_mogrify() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - _ImageMagick && return + _comp_cmd_convert__common_options && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help elif [[ $cur == +* ]]; then - COMPREPLY=($(compgen -W '+compress +contrast +debug +dither +endian - +gamma +label +map +mask +matte +negate +page +raise' -- "$cur")) + _comp_compgen -- -W '+compress +contrast +debug +dither +endian +gamma + +label +map +mask +matte +negate +page +raise' else - _filedir + _comp_compgen_filedir fi } && - complete -F _mogrify mogrify + complete -F _comp_cmd_mogrify mogrify -_display() +_comp_cmd_display() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - _ImageMagick && return + _comp_cmd_convert__common_options && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help elif [[ $cur == +* ]]; then - COMPREPLY=($(compgen -W '+compress +contrast +debug +dither +endian - +gamma +label +map +matte +negate +page +raise +write' -- "$cur")) + _comp_compgen -- -W '+compress +contrast +debug +dither +endian +gamma + +label +map +matte +negate +page +raise +write' else - _filedir + _comp_compgen_filedir fi } && - complete -F _display display + complete -F _comp_cmd_display display -_animate() +_comp_cmd_animate() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - _ImageMagick && return + _comp_cmd_convert__common_options && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help elif [[ $cur == +* ]]; then - COMPREPLY=($(compgen -W '+debug +dither +gamma +map +matte' \ - -- "$cur")) + _comp_compgen -- -W '+debug +dither +gamma +map +matte' else - _filedir + _comp_compgen_filedir fi } && - complete -F _animate animate + complete -F _comp_cmd_animate animate -_identify() +_comp_cmd_identify() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - _ImageMagick && return + _comp_cmd_convert__common_options && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help elif [[ $cur == +* ]]; then - COMPREPLY=($(compgen -W '+debug' -- "$cur")) + _comp_compgen -- -W '+debug' else - _filedir + _comp_compgen_filedir fi } && - complete -F _identify identify + complete -F _comp_cmd_identify identify -_montage() +_comp_cmd_montage() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - _ImageMagick && return + _comp_cmd_convert__common_options && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help elif [[ $cur == +* ]]; then - COMPREPLY=($(compgen -W '+adjoin +compress +debug +dither +endian - +gamma +label +matte +page' -- "$cur")) + _comp_compgen -- -W '+adjoin +compress +debug +dither +endian +gamma + +label +matte +page' else - _filedir + _comp_compgen_filedir fi } && - complete -F _montage montage + complete -F _comp_cmd_montage montage -_composite() +_comp_cmd_composite() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - _ImageMagick && return + _comp_cmd_convert__common_options && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help elif [[ $cur == +* ]]; then - COMPREPLY=($(compgen -W '+compress +debug +dither +endian +label - +matte +negate +page +write' -- "$cur")) + _comp_compgen -- -W '+compress +debug +dither +endian +label +matte + +negate +page +write' else - _filedir + _comp_compgen_filedir fi } && - complete -F _composite composite + complete -F _comp_cmd_composite composite -_compare() +_comp_cmd_compare() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - _ImageMagick && return + _comp_cmd_convert__common_options && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help elif [[ $cur == +* ]]; then - COMPREPLY=($(compgen -W '+debug' -- "$cur")) + _comp_compgen -- -W '+debug' else - _filedir + _comp_compgen_filedir fi } && - complete -F _compare compare + complete -F _comp_cmd_compare compare -_conjure() +_comp_cmd_conjure() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - _ImageMagick && return + _comp_cmd_convert__common_options && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help elif [[ $cur == +* ]]; then - COMPREPLY=($(compgen -W '+debug' -- "$cur")) + _comp_compgen -- -W '+debug' else - _filedir + _comp_compgen_filedir fi } && - complete -F _conjure conjure + complete -F _comp_cmd_conjure conjure -_import() +_comp_cmd_import() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - _ImageMagick && return + _comp_cmd_convert__common_options && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help elif [[ $cur == +* ]]; then - COMPREPLY=($(compgen -W '+debug' -- "$cur")) + _comp_compgen -- -W '+debug' else - _filedir + _comp_compgen_filedir fi } && - complete -F _import import + complete -F _comp_cmd_import import -_stream() +_comp_cmd_stream() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - _ImageMagick && return + _comp_cmd_convert__common_options && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help elif [[ $cur == +* ]]; then - COMPREPLY=($(compgen -W '+debug' -- "$cur")) + _comp_compgen -- -W '+debug' else - _filedir + _comp_compgen_filedir fi } && - complete -F _stream stream + complete -F _comp_cmd_stream stream # ex: filetype=sh diff --git a/completions/cowsay b/completions/cowsay index 6ba1d0f..ea1468c 100644 --- a/completions/cowsay +++ b/completions/cowsay @@ -1,23 +1,21 @@ # bash completion for cowsay -*- shell-script -*- -_cowsay() +_comp_cmd_cowsay() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -f) - COMPREPLY=($(compgen -W \ - '$(cowsay -l 2>/dev/null | tail -n +2)' -- "$cur")) + _comp_compgen_split -- "$(cowsay -l 2>/dev/null | tail -n +2)" return ;; esac # relevant options completion - COMPREPLY=($(compgen -W '-b -d -g -p -s -t -w -y -e -f -h -l -n -T -W' \ - -- "$cur")) + _comp_compgen -- -W '-b -d -g -p -s -t -w -y -e -f -h -l -n -T -W' } && - complete -F _cowsay -o default cowsay cowthink + complete -F _comp_cmd_cowsay -o default cowsay cowthink # ex: filetype=sh diff --git a/completions/cpan2dist b/completions/cpan2dist index b5e59da..e53933d 100644 --- a/completions/cpan2dist +++ b/completions/cpan2dist @@ -1,37 +1,37 @@ # bash completion for cpan2dist -*- shell-script -*- -_cpan2dist() +_comp_cmd_cpan2dist() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --format) # should remove ":" from COMP_WORDBREAKS, but doesn't work (?) - COMPREPLY=($(compgen -W '$(perl -MCPANPLUS::Dist -e \ - "print map { \"\$_\n\" } CPANPLUS::Dist->dist_types")' \ - -- "$cur")) + _comp_compgen_split -- "$(perl -MCPANPLUS::Dist -e \ + 'print map { "$_n" } CPANPLUS::Dist->dist_types')" return ;; --banlist | --ignorelist | --modulelist | --logfile) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help else local cpandirs=("$HOME/.cpanplus/" "$HOME/.cpan/source/modules/") - local packagelist + local dir packagelist= for dir in "${cpandirs[@]}"; do [[ -d $dir && -r "$dir/02packages.details.txt.gz" ]] && packagelist="$dir/02packages.details.txt.gz" done - [[ -v packagelist ]] && COMPREPLY=($(zgrep "^${cur//-/::}" \ - $packagelist 2>/dev/null | awk '{print $1}' | command sed -e 's/::/-/g')) + [[ $packagelist ]] && _comp_split COMPREPLY "$(zgrep "^${cur//-/::}" \ + "$packagelist" 2>/dev/null | _comp_awk '{print $1}' | + command sed -e 's/::/-/g')" fi } && - complete -F _cpan2dist -o default cpan2dist + complete -F _comp_cmd_cpan2dist -o default cpan2dist # ex: filetype=sh diff --git a/completions/cpio b/completions/cpio index d6fde0c..e7b70cd 100644 --- a/completions/cpio +++ b/completions/cpio @@ -1,78 +1,75 @@ # bash completion for cpio -*- shell-script -*- -_cpio() +_comp_cmd_cpio() { - local cur prev words cword split - _init_completion -s -n : || return + local cur prev words cword was_split comp_args + _comp_initialize -s -n : -- "$@" || return # --name value style option + local noargopts='!(-*|*[HEFIR]*)' + # shellcheck disable=SC2254 case $prev in - --format | -!(-*)H) - COMPREPLY=($(compgen -W \ - 'bin odc newc crc tar ustar hpbin hpodc' -- "$cur")) + --format | -${noargopts}H) + _comp_compgen -- -W 'bin odc newc crc tar ustar hpbin hpodc' return ;; - --file | --pattern-file | -!(-*)[EFI]) - _filedir + --file | --pattern-file | -${noargopts}[EFI]) + _comp_compgen_filedir return ;; - --owner | -!(-*)R) - _usergroup + --owner | -${noargopts}R) + _comp_compgen_usergroups return ;; --rsh-command) - compopt -o filenames - COMPREPLY=($(compgen -c -- "$cur")) + _comp_compgen_commands return ;; esac - $split && return + [[ $was_split ]] && return if ((cword == 1)); then - COMPREPLY=($(compgen -W '-o --create -i --extract -p --pass-through - -? --help --license --usage --version' -- "$cur")) + _comp_compgen -- -W '-o --create -i --extract -p --pass-through -? + --help --license --usage --version' else case ${words[1]} in -o | --create) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-0 -a -c -v -A -B -L -V -C -H -M - -O -F --file --format --message --null - --reset-access-time --verbose --dot --append - --block-size --dereference --io-size --quiet - --force-local --rsh-command --help --version' \ - -- "$cur")) + _comp_compgen -- -W '-0 -a -c -v -A -B -L -V -C -H -M -O -F + --file --format --message --null --reset-access-time + --verbose --dot --append --block-size --dereference + --io-size --quiet --force-local --rsh-command --help + --version' fi ;; -i | --extract) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-b -c -d -f -m -n -r -t -s -u -v - -B -S -V -C -E -H -M -R -I -F --file --make-directories + _comp_compgen -- -W '-b -c -d -f -m -n -r -t -s -u -v -B -S + -V -C -E -H -M -R -I -F --file --make-directories --nonmatching --preserve-modification-time --numeric-uid-gid --rename --list --swap-bytes --swap --dot --unconditional --verbose --block-size --swap-halfwords --io-size --pattern-file --format --owner --no-preserve-owner --message --force-local --no-absolute-filenames --sparse --only-verify-crc - --quiet --rsh-command --help --to-stdout --version' \ - -- "$cur")) + --quiet --rsh-command --help --to-stdout --version' fi ;; -p* | --pass-through) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-0 -a -d -l -m -u -v -L -V -R - --null --reset-access-time --make-directories --link - --quiet --preserve-modification-time --unconditional - --verbose --dot --dereference --owner - --no-preserve-owner --sparse --help --version' \ - -- "$cur")) + _comp_compgen -- -W '-0 -a -d -l -m -u -v -L -V -R --null + --reset-access-time --make-directories --link --quiet + --preserve-modification-time --unconditional --verbose + --dot --dereference --owner --no-preserve-owner + --sparse --help --version' else - _filedir -d + _comp_compgen_filedir -d fi ;; esac fi } && - complete -F _cpio cpio + complete -F _comp_cmd_cpio cpio # ex: filetype=sh diff --git a/completions/cppcheck b/completions/cppcheck index 8ea9571..5867fc7 100644 --- a/completions/cppcheck +++ b/completions/cppcheck @@ -1,14 +1,14 @@ # bash completion for cppcheck(1) -*- shell-script -*- -_cppcheck() +_comp_cmd_cppcheck() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in --append | --exitcode-suppressions | --rule-file | --config-excludes-file | \ --suppressions-list | --includes-file | --include | -i) - _filedir + _comp_compgen_filedir return ;; -D | -U | --rule | --suppress | --template | --max-configs | -h | --help | --version | \ @@ -17,75 +17,75 @@ _cppcheck() ;; --enable) # split comma-separated list - split=false + local split="" if [[ $cur == ?*,* ]]; then prev="${cur%,*}" cur="${cur##*,}" - split=true + split="set" fi - COMPREPLY=($(compgen -W 'all warning style performance - portability information unusedFunction missingInclude' \ - -- "$cur")) - $split && COMPREPLY=(${COMPREPLY[@]/#/"$prev,"}) + _comp_compgen -- -W 'all warning style performance portability + information unusedFunction missingInclude' && + [[ $split ]] && + _comp_compgen -Rv COMPREPLY -- -P "$prev," -W '"${COMPREPLY[@]}"' return ;; --error-exitcode) - COMPREPLY=($(compgen -W '{0..255}' -- "$cur")) + _comp_compgen -- -W '{0..255}' return ;; --file-list) - _filedir - [[ -z $cur || $cur == - ]] && COMPREPLY+=(-) + _comp_compgen_filedir + [[ ! $cur || $cur == - ]] && COMPREPLY+=(-) return ;; -I) - _filedir -d + _comp_compgen_filedir -d return ;; -j) - COMPREPLY=($(compgen -W "{2..$(_ncpus)}" -- "$cur")) + local REPLY + _comp_get_ncpus + _comp_compgen -- -W "{1..$REPLY}" return ;; --language | -x) - COMPREPLY=($(compgen -W 'c c++' -- "$cur")) + _comp_compgen -- -W 'c c++' return ;; --std) - COMPREPLY=($(compgen -W 'c89 c99 c11 c++03 c++11 c++14 c++17 - c++20' -- "$cur")) + _comp_compgen -- -W 'c89 c99 c11 c++03 c++11 c++14 c++17 c++20' return ;; --platform) - _filedir - COMPREPLY+=($(compgen -W 'unix32 unix64 win32A win32W win64 - native' -- "$cur")) + _comp_compgen_filedir + _comp_compgen -a -- -W 'unix32 unix64 win32A win32W win64 native' return ;; -rp | --relative-paths) - if $split; then # -rp without argument is allowed - _filedir -d + if [[ $was_split ]]; then # -rp without argument is allowed + _comp_compgen_filedir -d return fi ;; --library) - _filedir cfg + _comp_compgen_filedir cfg return ;; --xml-version) - COMPREPLY=($(compgen -W '1 2' -- "$cur")) + _comp_compgen -- -W '1 2' return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - _filedir '@([cht]pp|[cht]xx|cc|[ch]++|[ch])' + _comp_compgen_filedir '@([cht]pp|[cht]xx|cc|[ch]++|[ch])' fi } && - complete -F _cppcheck cppcheck + complete -F _comp_cmd_cppcheck cppcheck # ex: filetype=sh diff --git a/completions/crontab b/completions/crontab index cac7853..4f80347 100644 --- a/completions/crontab +++ b/completions/crontab @@ -1,13 +1,13 @@ # crontab(1) completion -*- shell-script -*- -_crontab() +_comp_cmd_crontab() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*u) - _allowed_users + _comp_compgen_allowed_users return ;; esac @@ -18,31 +18,31 @@ _crontab() local i for i in "${!words[@]}"; do - [[ ${words[i]} && $i -ne $cword ]] && unset "opts[${words[i]}]" + [[ ${words[i]} && $i -ne $cword ]] && unset -v "opts[${words[i]}]" case "${words[i]}" in -l) - unset 'opts[-r]' 'opts[-e]' 'opts[-i]' 'opts[-s]' + unset -v 'opts[-r]' 'opts[-e]' 'opts[-i]' 'opts[-s]' ;; -e) - unset 'opts[-l]' 'opts[-r]' 'opts[-i]' + unset -v 'opts[-l]' 'opts[-r]' 'opts[-i]' ;; -r) - unset 'opts[-l]' 'opts[-e]' + unset -v 'opts[-l]' 'opts[-e]' ;; -u) - unset 'opts[-i]' + unset -v 'opts[-i]' ;; esac done if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '${!opts[@]}' -- "$cur")) + _comp_compgen -- -W '"${!opts[@]}"' return fi # do filenames only if we did not have -l, -r, or -e - [[ ${words[*]} == *\ -[lre]* ]] || _filedir + [[ ${words[*]} == *\ -[lre]* ]] || _comp_compgen_filedir } && - complete -F _crontab crontab + complete -F _comp_cmd_crontab crontab # ex: filetype=sh diff --git a/completions/cryptsetup b/completions/cryptsetup index e73e165..9d23bfa 100644 --- a/completions/cryptsetup +++ b/completions/cryptsetup @@ -1,61 +1,52 @@ # bash completion for cryptsetup -*- shell-script -*- -_cryptsetup_name() +_comp_cmd_cryptsetup__name() { - COMPREPLY=($(compgen -X control -W '$(command ls /dev/mapper)' -- "$cur")) + _comp_compgen_split -X control -- "$(command ls /dev/mapper)" } -_cryptsetup_device() +_comp_cmd_cryptsetup__device() { - cur=${cur:=/dev/} - _filedir + _comp_compgen -c "${cur:-/dev/}" filedir } -_cryptsetup() +_comp_cmd_cryptsetup() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[cslSbopitTdM]*)' + # shellcheck disable=SC2254 case $prev in --help | --version | --cipher | --hash | --*-size | --key-slot | --size | --offset | \ - --skip | --iter-time | --timeout | --tries | -!(-*)[chslSbopitT]) + --skip | --iter-time | --timeout | --tries | -${noargopts}[chslSbopitT]) return ;; - --key-file | --master-key-file | --header-backup-file | -!(-*)d) - _filedir + --key-file | --master-key-file | --header-backup-file | -${noargopts}d) + _comp_compgen_filedir return ;; - --type | -!(-*)M) - COMPREPLY=($(compgen -W "luks plain loopaes tcrypt" -- "$cur")) + --type | -${noargopts}M) + _comp_compgen -- -W "luks plain loopaes tcrypt" return ;; esac - $split && return + [[ $was_split ]] && return - local arg - _get_first_arg - if [[ -z $arg ]]; then - if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) - [[ ${COMPREPLY-} == *= ]] && compopt -o nospace - else - COMPREPLY=($(compgen -W 'open close resize status benchmark - repair erase luksFormat luksAddKey luksRemoveKey luksChangeKey - luksKillSlot luksUUID isLuks luksDump tcryptDump luksSuspend - luksResume luksHeaderBackup luksHeaderRestore' -- "$cur")) - fi - else - local args - _count_args "" "-!(-*)[chslSbopitTdM]" + local REPLY + if _comp_get_first_arg; then + local arg=$REPLY + _comp_count_args -a "-${noargopts}[chslSbopitTdM]" + local args=$REPLY case $arg in open | create | luksOpen | loopaesOpen | tcryptOpen) case $args in 2) - _cryptsetup_device + _comp_cmd_cryptsetup__device ;; 3) - _cryptsetup_name + _comp_cmd_cryptsetup__name ;; esac ;; @@ -63,31 +54,31 @@ _cryptsetup() luksSuspend | luksResume) case $args in 2) - _cryptsetup_name + _comp_cmd_cryptsetup__name ;; esac ;; luksFormat | luksAddKey | luksRemoveKey | luksChangeKey) case $args in 2) - _cryptsetup_device + _comp_cmd_cryptsetup__device ;; 3) - _filedir + _comp_compgen_filedir ;; esac ;; luksKillSlot | luksDelKey | luksUUID | isLuks | luksDump) case $args in 2) - _cryptsetup_device + _comp_cmd_cryptsetup__device ;; esac ;; luksHeaderBackup | luksHeaderRestore) case $args in 2) - _cryptsetup_device + _comp_cmd_cryptsetup__device ;; 3) COMPREPLY=('--header-backup-file') @@ -95,9 +86,19 @@ _cryptsetup() esac ;; esac + else + if [[ $cur == -* ]]; then + _comp_compgen_help + [[ ${COMPREPLY-} == *= ]] && compopt -o nospace + else + _comp_compgen -- -W 'open close resize status benchmark repair + erase luksFormat luksAddKey luksRemoveKey luksChangeKey + luksKillSlot luksUUID isLuks luksDump tcryptDump luksSuspend + luksResume luksHeaderBackup luksHeaderRestore' + fi fi } && - complete -F _cryptsetup cryptsetup + complete -F _comp_cmd_cryptsetup cryptsetup # ex: filetype=sh diff --git a/completions/curl b/completions/curl index 6e84269..6cbbca4 100644 --- a/completions/curl +++ b/completions/curl @@ -1,48 +1,59 @@ # curl(1) completion -*- shell-script -*- -_curl() +_comp_cmd_curl() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return + local noargopts='!(-*|*[KbcDoTCFmQreYytzuAwEdHPxX]*)' + # shellcheck disable=SC2254 case $prev in - --ciphers | --connect-timeout | --continue-at | --form | --form-string | \ - --ftp-account | --ftp-alternative-to-user | --ftp-port | --header | --help | \ - --hostpubmd5 | --keepalive-time | --krb | --limit-rate | --local-port | \ - --mail-from | --mail-rcpt | --max-filesize | --max-redirs | --max-time | --pass | \ - --proto | --proto-redir | --proxy-user | --proxy1.0 | --quote | --range | \ - --request | --retry | --retry-delay | --retry-max-time | \ - --socks5-gssapi-service | --telnet-option | --tftp-blksize | --time-cond | \ - --url | --user | --user-agent | --version | --write-out | --resolve | --tlsuser | \ - --tlspassword | -!(-*)[CFPHhmQrXtzuAVw]) + --abstract-unix-socket | --alt-svc | --config | --cookie | \ + --cookie-jar | --dump-header | --egd-file | --etag-compare | \ + --etag-save | --hsts | --key | --libcurl | --netrc-file | \ + --output | --proxy-key | --random-file | --trace | --trace-ascii | \ + --unix-socket | --upload-file | -${noargopts}[KbcDoT]) + _comp_compgen_filedir return ;; - --config | --cookie | --cookie-jar | --dump-header | --egd-file | \ - --key | --libcurl | --output | --random-file | --upload-file | --trace | \ - --trace-ascii | --netrc-file | -!(-*)[KbcDoT]) - _filedir + --ciphers | --connect-timeout | --connect-to | --continue-at | \ + --curves | --data-raw | --doh-url | --expect100-timeout | --form | \ + --form-string | --ftp-account | --ftp-alternative-to-user | \ + --happy-eyeballs-timeout-ms | --hostpubmd5 | --keepalive-time | \ + --limit-rate | --local-port | --login-options | --mail-auth | \ + --mail-from | --mail-rcpt | --max-filesize | --max-redirs | \ + --max-time | --pass | --proto | --proto-default | --proto-redir | \ + --proxy-ciphers | --proxy-pass | --proxy-service-name | \ + --proxy-tls13-ciphers | --proxy-tlspassword | --proxy-tlsuser | \ + --proxy-user | --proxy1.0 | --quote | --range | --referer | \ + --resolve | --retry | --retry-delay | --retry-max-time | \ + --sasl-authzid | --service-name | --socks5-gssapi-service | \ + --speed-limit | --speed-time | --telnet-option | --tftp-blksize | \ + --time-cond | --tls13-ciphers | --tlspassword | --tlsuser | \ + --url | --user | --user-agent | --version | --write-out | \ + -${noargopts}[CFmQreYytzuAVw]) return ;; - --cacert | --cert | -!(-*)E) - _filedir '@(c?(e)rt|cer|pem|der)' + --cacert | --cert | --proxy-cacert | --proxy-cert | -${noargopts}E) + _comp_compgen_filedir '@(c?(e)rt|cer|pem|der)' return ;; - --capath) - _filedir -d + --capath | --output-dir | --proxy-capath) + _comp_compgen_filedir -d return ;; - --cert-type | --key-type) - COMPREPLY=($(compgen -W 'DER PEM ENG' -- "$cur")) + --cert-type | --key-type | --proxy-cert-type | --proxy-key-type) + _comp_compgen -- -W 'DER PEM ENG' return ;; - --crlfile) - _filedir crl + --crlfile | --proxy-crlfile) + _comp_compgen_filedir crl return ;; - --data | --data-ascii | --data-binary | --data-urlencode | -!(-*)d) + --data | --data-ascii | --data-binary | --data-urlencode | --header | \ + --proxy-header | -${noargopts}[dH]) if [[ $cur == \@* ]]; then - cur=${cur:1} - _filedir + _comp_compgen -c "${cur:1}" filedir if [[ ${#COMPREPLY[@]} -eq 1 && -d ${COMPREPLY[0]} ]]; then COMPREPLY[0]+=/ compopt -o nospace @@ -52,48 +63,100 @@ _curl() return ;; --delegation) - COMPREPLY=($(compgen -W 'none policy always' -- "$cur")) + _comp_compgen -- -W 'none policy always' + return + ;; + --dns-ipv[46]-addr) + _comp_compgen_ip_addresses -"${prev:9:1}" + return + ;; + --dns-servers | --noproxy) + _comp_compgen_known_hosts -- "${cur##*,}" + ((${#COMPREPLY[@]})) && + _comp_delimited , -W '"${COMPREPLY[@]}"' return ;; --engine) - COMPREPLY=($(compgen -W 'list' -- "$cur")) + local engines=$( + "$1" --engine list 2>/dev/null | + command grep "^[[:space:]]" + ) + _comp_compgen -- -W '$engines list' + return + ;; + --ftp-port | -${noargopts}P) + _comp_compgen_available_interfaces -a + _comp_compgen -a known_hosts -- "$cur" + _comp_compgen -a ip_addresses -a return ;; --ftp-method) - COMPREPLY=($(compgen -W 'multicwd nocwd singlecwd' -- "$cur")) + _comp_compgen -- -W 'multicwd nocwd singlecwd' return ;; --ftp-ssl-ccc-mode) - COMPREPLY=($(compgen -W 'active passive' -- "$cur")) + _comp_compgen -- -W 'active passive' return ;; --interface) - _available_interfaces -a + _comp_compgen_available_interfaces -a + return + ;; + --help | -${noargopts}h) + local x categories + if _comp_split categories "$("$1" --help non-existent-category 2>&1 | + _comp_awk '/^[ \t]/ {print $1}')"; then + for x in "${categories[@]}"; do + # Looks like an option? Likely no --help category support + [[ $x != -* ]] || return + done + _comp_compgen -- -W '"${categories[@]}"' + fi return ;; - --proxy | --socks4 | --socks4a | --socks5 | --socks5-hostname | -!(-*)x) - _known_hosts_real -- "$cur" + --krb) + _comp_compgen -- -W 'clear safe confidential private' + return + ;; + --pinnedpubkey | --proxy-pinnedpubkey) + _comp_compgen_filedir '@(pem|der|key)' + return + ;; + --preproxy | --proxy | --socks4 | --socks4a | --socks5 | \ + --socks5-hostname | -${noargopts}x) + _comp_compgen_known_hosts -- "$cur" return ;; --pubkey) - _xfunc ssh _ssh_identityfile pub + _comp_compgen -x ssh identityfile pub + return + ;; + --request | -${noargopts}X) + # TODO: these are valid for http(s) only + _comp_compgen -- -W 'GET HEAD POST PUT DELETE CONNECT OPTIONS TRACE + PATCH' return ;; --stderr) - COMPREPLY=($(compgen -W '-' -- "$cur")) - _filedir + _comp_compgen -- -W '-' + _comp_compgen -a filedir + return + ;; + --tls-max) + _comp_compgen -- -W 'default 1.0 1.1 1.2 1.3' return ;; - --tlsauthtype) - COMPREPLY=($(compgen -W 'SRP' -- "$cur")) + --tlsauthtype | --proxy-tlsauthtype) + _comp_compgen -- -W 'SRP' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help -- --help all + [[ ${COMPREPLY-} ]] || _comp_compgen_help fi } && - complete -F _curl curl + complete -F _comp_cmd_curl curl # ex: filetype=sh diff --git a/completions/cvs b/completions/cvs index ba1f062..5629dfe 100644 --- a/completions/cvs +++ b/completions/cvs @@ -1,58 +1,65 @@ # cvs(1) completion -*- shell-script -*- -_cvs_entries() +_comp_deprecate_var 2.12 \ + COMP_CVS_REMOTE BASH_COMPLETION_CMD_CVS_REMOTE + +# Usage: _comp_cmd_cvs__compgen_entries [base_path] +# @param[opt] $1 +# shellcheck disable=SC2120 +_comp_cmd_cvs__compgen_entries() { - local prefix=${cur%/*}/ IFS=$'\n' - [[ -e ${prefix:-}CVS/Entries ]] || prefix="" - entries=($(cut -d/ -f2 -s ${prefix:-}CVS/Entries 2>/dev/null)) - if [[ $entries ]]; then - entries=("${entries[@]/#/${prefix:-}}") + local base_path=${1-$cur} + local _prefix=${base_path%/*}/ + [[ -e ${_prefix-}CVS/Entries ]] || _prefix="" + _comp_compgen -c "${cur#"$_prefix"}" split -lP "$_prefix" -- "$(cut -d/ -f2 -s "${_prefix-}CVS/Entries" 2>/dev/null)" && compopt -o filenames - fi } -_cvs_modules() +_comp_cmd_cvs__modules() { - if [[ -n $prefix ]]; then - COMPREPLY=($(command ls -d ${cvsroot}/${prefix}/!(CVSROOT))) - else - COMPREPLY=($(command ls -d ${cvsroot}/!(CVSROOT))) - fi + _comp_expand_glob COMPREPLY '"$cvsroot${prefix:+/$prefix}"/!(CVSROOT)' } -_cvs_commands() +_comp_cmd_cvs__compgen_commands() { - cvs --help-commands 2>&1 | awk '/^( *|\t)/ { print $1 }' + _comp_compgen_split -- "$( + "$1" --help-commands 2>&1 | _comp_awk '/^( *|\t)/ { print $1 }' + )" } -_cvs_command_options() +_comp_cmd_cvs__compgen_command_options() { - COMPREPLY=($(compgen -W '$(_parse_help "$1" "--help $2")' -- "$cur")) + _comp_compgen_help -- --help "$2" } -_cvs_kflags() +_comp_cmd_cvs__compgen_kflags() { - COMPREPLY=($(compgen -W 'kv kvl k o b v' -- "$cur")) + _comp_compgen -- -W 'kv kvl k o b v' } -_cvs_roots() +# @since 2.12 +_comp_xfunc_cvs_compgen_roots() { - local -a cvsroots + local -a cvsroots=() [[ -v CVSROOT ]] && cvsroots=("$CVSROOT") - [[ -r ~/.cvspass ]] && cvsroots+=($(awk '{ print $2 }' ~/.cvspass)) - [[ -r CVS/Root ]] && mapfile -tO ${#cvsroots[@]} cvsroots <CVS/Root - COMPREPLY=($(compgen -W '${cvsroots[@]}' -- "$cur")) - __ltrim_colon_completions "$cur" + [[ -r ~/.cvspass ]] && _comp_split -a cvsroots "$(_comp_awk '{ print $2 }' ~/.cvspass)" + [[ -r CVS/Root ]] && mapfile -tO "${#cvsroots[@]}" cvsroots <CVS/Root + ((${#cvsroots[@]})) && + _comp_compgen -U cvsroots -- -W '"${cvsroots[@]}"' + _comp_ltrim_colon_completions "$cur" } -_cvs() +_comp_deprecate_func 2.12 _cvs_roots _comp_xfunc_cvs_compgen_roots + +_comp_cmd_cvs() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return - local count mode i cvsroot cvsroots pwd - local -a flags files entries changed newremoved + local count mode="" i cvsroot="" has_cvsroot="" pwd + local -a flags files entries + local noargopts='!(-*|*[d]*)' count=0 for i in "${words[@]}"; do ((count == cword)) && break @@ -60,15 +67,17 @@ _cvs() if [[ ${words[count]} == "${cvsroot-}" && ${mode-} == cvsroot ]]; then mode="" fi - if [[ ! -v mode ]]; then + if [[ ! $mode ]]; then + # shellcheck disable=SC2254 case $i in - --help | -!(-*)H) - COMPREPLY=($(compgen -W "$(_cvs_commands)" -- "$cur")) + --help | -${noargopts}H) + _comp_cmd_cvs__compgen_commands "$1" return ;; - -!(-*)d) + -${noargopts}d) mode=cvsroot cvsroot=${words[count + 1]} + has_cvsroot=set ;; add | ad | new) mode=add @@ -132,7 +141,7 @@ _cvs() ;; esac elif [[ $i == -* ]]; then - flags+=($i) + flags+=("$i") fi ((count++)) done @@ -145,32 +154,36 @@ _cvs() return ;; -*k) - _cvs_kflags + _comp_cmd_cvs__compgen_kflags return ;; esac if [[ $cur != -* ]]; then - _cvs_entries - [[ -z $cur ]] && files=(!(CVS)) || - files=($(command ls -d ${cur}* 2>/dev/null)) + _comp_compgen -Rv entries -i cvs entries "${cur-}" + if [[ ! $cur ]]; then + _comp_expand_glob files '!(CVS)' + else + _comp_expand_glob files '"${cur}"*' + fi local f for i in "${!files[@]}"; do if [[ ${files[i]} == ?(*/)CVS ]]; then - unset 'files[i]' - else + unset -v 'files[i]' + elif ((${#entries[@]})); then for f in "${entries[@]}"; do if [[ ${files[i]} == "$f" && ! -d $f ]]; then - unset 'files[i]' + unset -v 'files[i]' break fi done fi done - COMPREPLY=($(compgen -X "$_backup_glob" -W '${files[@]}' \ - -- "$cur")) + # shellcheck disable=SC2154 # global var _comp_backup_glob + ((${#files[@]})) && + _comp_compgen -- -X "$_comp_backup_glob" -W '"${files[@]}"' else - _cvs_command_options "$1" $mode + _comp_cmd_cvs__compgen_command_options "$1" "$mode" fi ;; admin) @@ -180,30 +193,28 @@ _cvs() return ;; -*t) - _filedir + _comp_compgen_filedir return ;; -*k) - _cvs_kflags + _comp_cmd_cvs__compgen_kflags return ;; esac if [[ $cur == -* ]]; then - _cvs_command_options "$1" $mode + _comp_cmd_cvs__compgen_command_options "$1" "$mode" else - _cvs_entries - COMPREPLY=($(compgen -W '${entries[@]}' -- "$cur")) + _comp_cmd_cvs__compgen_entries fi ;; annotate) [[ $prev == -[rD] ]] && return if [[ $cur == -* ]]; then - _cvs_command_options "$1" $mode + _comp_cmd_cvs__compgen_command_options "$1" "$mode" else - _cvs_entries - COMPREPLY=($(compgen -W '${entries[@]}' -- "$cur")) + _comp_cmd_cvs__compgen_entries fi ;; checkout) @@ -213,22 +224,21 @@ _cvs() return ;; -*d) - _filedir -d + _comp_compgen_filedir -d return ;; -*k) - _cvs_kflags + _comp_cmd_cvs__compgen_kflags return ;; esac if [[ $cur != -* ]]; then - [[ ! -v cvsroot ]] && cvsroot=${CVSROOT-} - COMPREPLY=($(cvs -d "$cvsroot" co -c 2>/dev/null | - awk '{print $1}')) - COMPREPLY=($(compgen -W '${COMPREPLY[@]}' -- "$cur")) + [[ ! $has_cvsroot ]] && cvsroot=${CVSROOT-} + _comp_compgen_split -- "$(cvs -d "$cvsroot" co -c 2>/dev/null | + _comp_awk '{print $1}')" else - _cvs_command_options "$1" $mode + _comp_cmd_cvs__compgen_command_options "$1" "$mode" fi ;; commit) @@ -238,51 +248,49 @@ _cvs() return ;; -*F) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur != -* ]]; then - # if $COMP_CVS_REMOTE is not null, 'cvs commit' will - # complete on remotely checked-out files (requires + # if $BASH_COMPLETION_CMD_CVS_REMOTE is not null, 'cvs commit' + # will complete on remotely checked-out files (requires # passwordless access to the remote repository - if [[ -n ${COMP_CVS_REMOTE:-} ]]; then + if [[ ${BASH_COMPLETION_CMD_CVS_REMOTE-} ]]; then # this is the least computationally intensive way found so # far, but other changes (something other than - # changed/removed/new) may be missing - changed=($(cvs -q diff --brief 2>&1 | - command sed -ne 's/^Files [^ ]* and \([^ ]*\) differ$/\1/p')) - newremoved=($(cvs -q diff --brief 2>&1 | - command sed -ne 's/^cvs diff: \([^ ]*\) .*, no comparison available$/\1/p')) - COMPREPLY=($(compgen -W '${changed[@]:-} \ - ${newremoved[@]:-}' -- "$cur")) + # changed/removed/new) may be missing. + _comp_compgen -a split -- "$(cvs -q diff --brief 2>&1 | + command sed -ne ' + # changed + s/^Files [^ ]* and \([^ ]*\) differ$/\1/p + # new/removed + s/^cvs diff: \([^ ]*\) .*, no comparison available$/\1/p + ')" else - _cvs_entries - COMPREPLY=($(compgen -W '${entries[@]}' -- "$cur")) + _comp_cmd_cvs__compgen_entries fi else - _cvs_command_options "$1" $mode + _comp_cmd_cvs__compgen_command_options "$1" "$mode" fi ;; cvsroot) - _cvs_roots + _comp_xfunc_cvs_compgen_roots ;; - diff | log) + diff | log | status) if [[ $cur == -* ]]; then - _cvs_command_options "$1" $mode + _comp_cmd_cvs__compgen_command_options "$1" "$mode" [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - _cvs_entries - COMPREPLY=($(compgen -W '${entries[@]:-}' -- "$cur")) + _comp_cmd_cvs__compgen_entries fi ;; editors | watchers) if [[ $cur == -* ]]; then - _cvs_command_options "$1" $mode + _comp_cmd_cvs__compgen_command_options "$1" "$mode" else - _cvs_entries - COMPREPLY=($(compgen -W '${entries[@]}' -- "$cur")) + _comp_cmd_cvs__compgen_entries fi ;; export) @@ -292,21 +300,21 @@ _cvs() return ;; -*d) - _filedir -d + _comp_compgen_filedir -d return ;; -*k) - _cvs_kflags + _comp_cmd_cvs__compgen_kflags return ;; esac if [[ $cur != -* ]]; then - [[ ! -v cvsroot ]] && cvsroot=${CVSROOT-} - COMPREPLY=($(cvs -d "$cvsroot" co -c | awk '{print $1}')) - COMPREPLY=($(compgen -W '${COMPREPLY[@]}' -- "$cur")) + [[ ! $has_cvsroot ]] && cvsroot=${CVSROOT-} + _comp_compgen_split -- "$(cvs -d "$cvsroot" co -c | + _comp_awk '{print $1}')" else - _cvs_command_options "$1" $mode + _comp_cmd_cvs__compgen_command_options "$1" "$mode" fi ;; import) @@ -316,39 +324,42 @@ _cvs() return ;; -*k) - _cvs_kflags + _comp_cmd_cvs__compgen_kflags return ;; esac if [[ $cur != -* ]]; then # starts with same algorithm as checkout - [[ ! -v cvsroot ]] && cvsroot=${CVSROOT-} + [[ ! $has_cvsroot ]] && cvsroot=${CVSROOT-} local prefix=${cur%/*} if [[ -r ${cvsroot}/${prefix} ]]; then - _cvs_modules - COMPREPLY=(${COMPREPLY[@]#$cvsroot}) - COMPREPLY=(${COMPREPLY[@]#\/}) + _comp_cmd_cvs__modules + COMPREPLY=("${COMPREPLY[@]#"$cvsroot"}") + COMPREPLY=("${COMPREPLY[@]#\/}") fi pwd=$(pwd) pwd=${pwd##*/} - COMPREPLY=($(compgen -W '${COMPREPLY[@]} $pwd' -- "$cur")) + [[ $pwd ]] && COMPREPLY+=("$pwd") + ((${#COMPREPLY[@]})) && + _comp_compgen -- -W '"${COMPREPLY[@]}"' else - _cvs_command_options "$1" $mode + _comp_cmd_cvs__compgen_command_options "$1" "$mode" fi ;; remove) if [[ $cur != -* ]]; then - _cvs_entries + _comp_compgen -Rv entries -i cvs entries "${cur-}" if [[ $prev != -f ]]; then # find out what files are missing for i in "${!entries[@]}"; do - [[ -r ${entries[i]} ]] && unset 'entries[i]' + [[ -r ${entries[i]} ]] && unset -v 'entries[i]' done fi - COMPREPLY=($(compgen -W '${entries[@]:-}' -- "$cur")) + ((${#entries[@]})) && + _comp_compgen -- -W '"${entries[@]}"' else - _cvs_command_options "$1" $mode + _comp_cmd_cvs__compgen_command_options "$1" "$mode" fi ;; update) @@ -358,41 +369,41 @@ _cvs() return ;; -*k) - _cvs_kflags + _comp_cmd_cvs__compgen_kflags return ;; esac if [[ $cur == -* ]]; then - _cvs_command_options "$1" $mode + _comp_cmd_cvs__compgen_command_options "$1" "$mode" else - _cvs_entries - COMPREPLY=($(compgen -W '${entries[@]}' -- "$cur")) + _comp_cmd_cvs__compgen_entries fi ;; "") case $prev in --*) ;; -*T) - _filedir -d + _comp_compgen_filedir -d return ;; -*[es]) return ;; -*z) - COMPREPLY=($(compgen -W '{1..9}' -- "$cur")) + _comp_compgen -- -W '{1..9}' return ;; esac - COMPREPLY=($(compgen -W '$(_cvs_commands) - $(_parse_help "$1" --help-options) --help --help-commands - --help-options --version' -- "$cur")) + _comp_compgen_help -- --help-options + _comp_compgen -a -i cvs commands "$1" + _comp_compgen -a -- -W \ + "--help --help-commands --help-options --version" ;; esac } && - complete -F _cvs cvs + complete -F _comp_cmd_cvs cvs # ex: filetype=sh diff --git a/completions/cvsps b/completions/cvsps index 4fdfefc..c9e6199 100644 --- a/completions/cvsps +++ b/completions/cvsps @@ -1,58 +1,58 @@ # bash completion for cvsps -*- shell-script -*- -_cvsps() +_comp_cmd_cvsps() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return case $prev in -h | -z | -f | -d | -l | --diff-opts | --debuglvl) return ;; -s) - COMPREPLY=($(compgen -W "$($1 2>/dev/null | - awk '/^PatchSet:?[ \t]/ { print $2 }')" -- "$cur")) + _comp_compgen_split -- "$("$1" 2>/dev/null | + _comp_awk '/^PatchSet:?[ \t]/ { print $2 }')" return ;; -a) - COMPREPLY=($(compgen -W "$($1 2>/dev/null | - awk '/^Author:[ \t]/ { print $2 }')" -- "$cur")) + _comp_compgen_split -- "$("$1" 2>/dev/null | + _comp_awk '/^Author:[ \t]/ { print $2 }')" return ;; -b) - COMPREPLY=($(compgen -W "$($1 2>/dev/null | - awk '/^Branch:[ \t]/ { print $2 }')" -- "$cur")) + _comp_compgen_split -- "$("$1" 2>/dev/null | + _comp_awk '/^Branch:[ \t]/ { print $2 }')" return ;; -r) - COMPREPLY=($(compgen -W "$($1 2>/dev/null | - awk '/^Tag:[ \t]+[^(]/ { print $2 }')" -- "$cur")) + _comp_compgen_split -- "$("$1" 2>/dev/null | + _comp_awk '/^Tag:[ \t]+[^(]/ { print $2 }')" return ;; -p) - _filedir -d + _comp_compgen_filedir -d return ;; --test-log) - _filedir + _comp_compgen_filedir return ;; -Z) - COMPREPLY=($(compgen -W '{1..9}' -- "$cur")) + _comp_compgen -- -W '{1..9}' return ;; --root) - _xfunc cvs _cvs_roots + _comp_compgen -x cvs roots return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur")) + _comp_compgen_help -- -h else - _xfunc cvs _cvs_roots + _comp_compgen -x cvs roots fi } && - complete -F _cvsps cvsps + complete -F _comp_cmd_cvsps cvsps # ex: filetype=sh diff --git a/completions/dd b/completions/dd index 04d876a..a9985b1 100644 --- a/completions/dd +++ b/completions/dd @@ -1,42 +1,39 @@ # bash completion for dd -*- shell-script -*- -_dd() +_comp_cmd_dd() { - local cur prev words cword - _init_completion -n = || return + local cur prev words cword comp_args + _comp_initialize -n = -- "$@" || return case $cur in if=* | of=*) - cur=${cur#*=} - _filedir + _comp_compgen -c "${cur#*=}" filedir return ;; conv=*) - cur=${cur#*=} - COMPREPLY=($(compgen -W 'ascii ebcdic ibm block unblock lcase - ucase sparse swab sync excl nocreat notrunc noerror fdatasync - fsync' -- "$cur")) + _comp_compgen -c "${cur#*=}" -- -W 'ascii ebcdic ibm block unblock + lcase ucase sparse swab sync excl nocreat notrunc noerror + fdatasync fsync' return ;; iflag=* | oflag=*) - cur=${cur#*=} - COMPREPLY=($(compgen -W 'append direct directory dsync sync - fullblock nonblock noatime nocache noctty nofollow count_bytes - skip_bytes seek_bytes' -- "$cur")) + _comp_compgen -c "${cur#*=}" -- -W 'append direct directory dsync + sync fullblock nonblock noatime nocache noctty nofollow + count_bytes skip_bytes seek_bytes' return ;; status=*) cur=${cur#*=} - COMPREPLY=($(compgen -W 'none noxfer progress' -- "$cur")) + _comp_compgen -- -W 'none noxfer progress' return ;; esac - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur") - $(compgen -W 'bs cbs conv count ibs if iflag obs of oflag - seek skip status' -S '=' -- "$cur")) + _comp_compgen_help + _comp_compgen -a -- -W 'bs cbs conv count ibs if iflag obs of oflag + seek skip status' -S '=' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace } && - complete -F _dd dd + complete -F _comp_cmd_dd dd # ex: filetype=sh diff --git a/completions/declare b/completions/declare new file mode 100644 index 0000000..128cb30 --- /dev/null +++ b/completions/declare @@ -0,0 +1,41 @@ +# bash declare completion -*- shell-script -*- + +_comp_cmd_declare() +{ + local cur prev words cword comp_args + _comp_initialize -n := -- "$@" || return + + if [[ $cur == [-+]* ]]; then + local opts + _comp_compgen -Rv opts usage -c help -s "$1" + # Most options also have a '+' form. + # We'll exclude the ones that don't with compgen. + opts+=("${opts[@]/-/+}") + _comp_compgen -- -W "${opts[*]}" -X '+[Ffgp]' + return + fi + + local i=1 + while [[ ${words[i]} == [-+]* ]]; do + case ${words[i]} in + -*[aA]*) + _comp_compgen -- -A arrayvar + return + ;; + -*[fF]*) + _comp_compgen -- -A function + return + ;; + esac + ((i++)) + done + if ((i > 1)); then + # There was at least one option and it was not one that limited + # operations to functions and array variables + _comp_variable_assignments "$cur" && return + _comp_compgen -- -A variable + fi +} && + complete -F _comp_cmd_declare declare typeset + +# ex: filetype=sh diff --git a/completions/deja-dup b/completions/deja-dup index 1854d6a..0b28928 100644 --- a/completions/deja-dup +++ b/completions/deja-dup @@ -1,32 +1,32 @@ # bash completion for deja-dup(1) -*- shell-script -*- -_deja_dup() +_comp_cmd_deja_dup() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -'?' | --help | --help-*) return ;; --restore) - _filedir + _comp_compgen_filedir return ;; --restore-missing) - _filedir -d + _comp_compgen_filedir -d return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" --help-all)' -- "$cur")) + _comp_compgen_help -- --help-all [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi } && - complete -F _deja_dup deja-dup + complete -F _comp_cmd_deja_dup deja-dup # ex: filetype=sh diff --git a/completions/desktop-file-validate b/completions/desktop-file-validate index 8f4e139..ef1fe9a 100644 --- a/completions/desktop-file-validate +++ b/completions/desktop-file-validate @@ -1,9 +1,9 @@ # desktop-file-validate completion -*- shell-script -*- -_desktop_file_validate() +_comp_cmd_desktop_file_validate() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --help) @@ -12,12 +12,12 @@ _desktop_file_validate() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - _filedir desktop + _comp_compgen_filedir desktop } && - complete -F _desktop_file_validate desktop-file-validate + complete -F _comp_cmd_desktop_file_validate desktop-file-validate # ex: filetype=sh diff --git a/completions/dhclient b/completions/dhclient index ce4b745..330a298 100644 --- a/completions/dhclient +++ b/completions/dhclient @@ -1,34 +1,34 @@ # bash completion for dhclient -*- shell-script -*- -_dhclient() +_comp_cmd_dhclient() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -p | -e) return ;; -D) - COMPREPLY=($(compgen -W 'LL LLT' -- "$cur")) + _comp_compgen -- -W 'LL LLT' return ;; -*f) - _filedir + _comp_compgen_filedir return ;; -s) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage else - _available_interfaces + _comp_compgen_available_interfaces fi } && - complete -F _dhclient dhclient + complete -F _comp_cmd_dhclient dhclient # ex: filetype=sh diff --git a/completions/dict b/completions/dict index f3426ff..f3b0cb6 100644 --- a/completions/dict +++ b/completions/dict @@ -1,47 +1,54 @@ # dict(1) completion -*- shell-script -*- -_dictdata() +_comp_cmd_dict__compgen_dictdata() { - dict $host $port $1 2>/dev/null | command sed -ne \ - 's/^[[:blank:]]\{1,\}\([^[:blank:]]*\).*$/\1/p' + # shellcheck disable=SC2086 + _comp_compgen_split -- "$( + "$@" 2>/dev/null | command sed -ne \ + 's/^[[:blank:]]\{1,\}\([^[:blank:]]*\).*$/\1/p' + )" } -_dict() +_comp_cmd_dict() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - local host port db i + local -a dict_command=("$1") + local host="" port="" db i + local noargopts='!(-*|*[hpdis]*)' for ((i = 1; i < cword; i++)); do + # shellcheck disable=SC2254 case ${words[i]} in - --host | -!(-*)h) + --host | -${noargopts}h) host=${words[++i]} - [[ -n $host ]] && host="-h $host" + [[ $host ]] && dict_command+=(-h "$host") ;; - --port | -!(-*)p) + --port | -${noargopts}p) port=${words[++i]} - [[ -n $port ]] && port="-p $port" + [[ $port ]] && dict_command+=(-p "$port") ;; - --database | -!(-*)d) + --database | -${noargopts}d) db=${words[++i]} - [[ -n $db ]] && host="-d $db" + [[ $db ]] && dict_command+=(-d "$db") ;; esac done if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi + # shellcheck disable=SC2254 case $prev in - --database | -info | -!(-*)[di]) - COMPREPLY=($(compgen -W '$(_dictdata -D)' -- "$cur")) + --database | -info | -${noargopts}[di]) + _comp_cmd_dict__compgen_dictdata "${dict_command[@]}" -D return ;; - --strategy | -!(-*)s) - COMPREPLY=($(compgen -W '$(_dictdata -S)' -- "$cur")) + --strategy | -${noargopts}s) + _comp_cmd_dict__compgen_dictdata "${dict_command[@]}" -S return ;; esac @@ -52,13 +59,14 @@ _dict() # it down with grep if $cur looks like something that's safe to embed # in a pattern instead. if [[ $cur == +([-A-Za-z0-9/.]) ]]; then - COMPREPLY=($(compgen -W \ - '$(command grep "^${cur//./\\.}" $dictfile)' -- "$cur")) + _comp_compgen_split -- "$( + command grep "^${cur//./\\.}" "$dictfile" + )" else - COMPREPLY=($(compgen -W '$(cat $dictfile)' -- "$cur")) + _comp_compgen_split -- "$(cat "$dictfile")" fi fi } && - complete -F _dict -o default dict rdict + complete -F _comp_cmd_dict -o default dict rdict # ex: filetype=sh diff --git a/completions/dmypy b/completions/dmypy index 5abe37d..7fab74f 100644 --- a/completions/dmypy +++ b/completions/dmypy @@ -1,48 +1,49 @@ # dmypy completion -*- shell-script -*- -_dmypy() +_comp_cmd_dmypy() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --help | --version | -[hV]) return ;; --status-file) - _filedir + _comp_compgen_filedir return ;; esac - local cmd i + local cmd="" has_cmd="" i for ((i = 1; i < cword; i++)); do if [[ ${words[i]} != -* && ${words[i - 1]} != --status-file ]]; then cmd=${words[i]} + has_cmd=set break fi done case ${cmd-} in check | run) - _filedir '@(py|pyi)' + _comp_compgen_filedir '@(py|pyi)' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - if [[ ! -v cmd ]]; then - local cmds=$($1 --help 2>&1 | - command sed -ne '/positional arguments/{p;n;p;q}' | + if [[ ! $has_cmd ]]; then + local cmds=$("$1" --help 2>&1 | + command sed -ne '/positional arguments/{p;n;p;q;}' | command sed -ne 's/{\(.*\)}/\1/p') - COMPREPLY=($(IFS="," compgen -W '$cmds' -- "$cur")) + _comp_compgen -F , -- -W '$cmds' return fi } && - complete -F _dmypy dmypy + complete -F _comp_cmd_dmypy dmypy # ex: filetype=sh diff --git a/completions/dnssec-keygen b/completions/dnssec-keygen index 3f68a68..9db55b5 100644 --- a/completions/dnssec-keygen +++ b/completions/dnssec-keygen @@ -1,48 +1,48 @@ # bash completion for dnssec-keygen(8) -*- shell-script -*- -_dnssec_keygen_optarg() +_comp_cmd_dnssec_keygen__optarg() { local args=$("$1" -h 2>&1 | command sed -e 's/|/ /g' -e 's/(.*//' \ - -ne '/^[[:space:]]*'$2'/,/^[[:space:]]*[(-]/p' | - command sed -e 's/^[[:space:]]*'$2'.*://' -e '/^[[:space:]]*-/d') - COMPREPLY+=($(compgen -W '$args' -- "$cur")) + -ne '/^[[:space:]]*'"$2"'/,/^[[:space:]]*[(-]/p' | + command sed -e 's/^[[:space:]]*'"$2"'.*://' -e '/^[[:space:]]*-/d') + _comp_compgen -a -- -W '$args' } -_dnssec_keygen() +_comp_cmd_dnssec_keygen() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -[hbEgLpsPARIDSi]) return ;; -K) - _filedir -d + _comp_compgen_filedir -d return ;; -[ancdfTtm]) - _dnssec_keygen_optarg "$1" $prev + _comp_cmd_dnssec_keygen__optarg "$1" "$prev" return ;; -r) - cur=${cur:=/dev/} - _filedir + _comp_compgen -c "${cur:-/dev/}" filedir return ;; -v) - COMPREPLY=($(compgen -W '{0..10}' -- "$cur")) + _comp_compgen -- -W '{0..10}' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" | \ - command sed -e "s/:\$//")' -- "$cur")) + _comp_compgen -R help + ((${#COMPREPLY[@]})) && + _comp_compgen -- -W '"${COMPREPLY[@]%:}"' return fi } && - complete -F _dnssec_keygen dnssec-keygen + complete -F _comp_cmd_dnssec_keygen dnssec-keygen # ex: filetype=sh diff --git a/completions/dnsspoof b/completions/dnsspoof index 86ade91..9117b72 100644 --- a/completions/dnsspoof +++ b/completions/dnsspoof @@ -1,26 +1,26 @@ # dnsspoof completion -*- shell-script -*- -_dnsspoof() +_comp_cmd_dnsspoof() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -i) - _available_interfaces -a + _comp_compgen_available_interfaces -a return ;; -f) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage fi } && - complete -F _dnsspoof dnsspoof + complete -F _comp_cmd_dnsspoof dnsspoof # ex: filetype=sh diff --git a/completions/dot b/completions/dot index 8122229..dcb8436 100644 --- a/completions/dot +++ b/completions/dot @@ -1,9 +1,9 @@ # dot(1) completion -*- shell-script -*- -_dot() +_comp_cmd_dot() { - local cur prev words cword - _init_completion -n := || return + local cur prev words cword comp_args + _comp_initialize -n := -- "$@" || return [[ $prev == -[V?] ]] && return @@ -12,34 +12,35 @@ _dot() return ;; -T*) - local langs=($("$1" -TNON_EXISTENT 2>&1 | - command sed -ne 's/.*one of://p')) - COMPREPLY=($(compgen -P -T -W '${langs[@]}' -- "${cur#-T}")) + # generate langs + _comp_compgen -c "${cur#-T}" split -P "-T" -- "$( + "$1" -TNON_EXISTENT 2>&1 | command sed -ne 's/.*one of://p' + )" return ;; -K*) - local layouts=($("$1" -KNON_EXISTENT 2>&1 | - command sed -ne 's/.*one of://p')) - COMPREPLY=($(compgen -P -K -W '${layouts[@]}' -- "${cur#-K}")) + # generate layouts + _comp_compgen -c "${cur#-K}" split -P "-K" -- "$( + "$1" -KNON_EXISTENT 2>&1 | command sed -ne 's/.*one of://p' + )" return ;; -o*) - cur=${cur#-o} - _filedir - COMPREPLY=($(compgen -P -o -W '${COMPREPLY[@]}' -- "$cur")) + _comp_compgen -c "${cur#-o}" filedir && + COMPREPLY=("${COMPREPLY[@]/#/-o}") return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-V -v -G -N -E -T -K -l -o -O -P -q -s -y -n - -n1 -n2 -x -Lg -LO -Ln -LU -LC -LT -m -c -?' -- "$cur")) + _comp_compgen -- -W '-V -v -G -N -E -T -K -l -o -O -P -q -s -y -n -n1 + -n2 -x -Lg -LO -Ln -LU -LC -LT -m -c -?' [[ ${COMPREPLY-} == -@([GNETKo]|L[nUCT]) ]] && compopt -o nospace return fi - _filedir dot + _comp_compgen_filedir '@(gv|dot)' } && - complete -F _dot dot + complete -F _comp_cmd_dot dot # ex: filetype=sh diff --git a/completions/dpkg b/completions/dpkg index 0b90b14..7ce5c19 100644 --- a/completions/dpkg +++ b/completions/dpkg @@ -1,43 +1,67 @@ -# This function is required by _dpkg and _dpkg-reconfigure -*- shell-script -*- +# dpkg(1) and related commands completion -*- shell-script -*- -_have grep-status && { - _comp_dpkg_installed_packages() - { - grep-status -P -e "^$1" -a -FStatus 'ok installed' -n -s Package - } -} || { - _comp_dpkg_installed_packages() - { - command grep -A 1 "Package: $1" /var/lib/dpkg/status 2>/dev/null | - command grep -B 1 -Ee "ok installed|half-installed|unpacked| \ - half-configured" \ - -Ee "^Essential: yes" | - awk "/Package: $1/ { print \$2 }" 2>/dev/null - } +# @since 2.12 +_comp_xfunc_dpkg_compgen_installed_packages() +{ + _comp_compgen_split -- "$( + grep-status -P -e "^${cur-}" -a \ + -FStatus 'ok installed' \ + -n -s Package 2>/dev/null || + _comp_awk -F '\n' -v RS="" " + index(\$1, \"Package: ${cur-}\") == 1 && + \$2 ~ /ok installed|half-installed|unpacked|half-configured|^Essential: yes/ { + print(substr(\$1, 10)); + }" /var/lib/dpkg/status 2>/dev/null + )" +} + +# @since 2.12 +_comp_xfunc_dpkg_compgen_purgeable_packages() +{ + _comp_compgen_split -- "$( + grep-status -P -e "^${cur-}" -a \ + -FStatus 'ok installed' -o -FStatus 'ok config-files' \ + -n -s Package 2>/dev/null || + _comp_awk -F '\n' -v RS="" " + index(\$1, \"Package: ${cur-}\") == 1 && + \$2 ~ /ok installed|half-installed|unpacked|half-configured|config-files|^Essential: yes/ { + print(substr(\$1, 10)); + }" /var/lib/dpkg/status 2>/dev/null + )" +} + +# @since 2.12 +_comp_xfunc_dpkg_compgen_held_packages() +{ + _comp_compgen_split -- "$( + dpkg --get-selections ${cur:+"$cur}"} | + _comp_awk '{for(i=2;i<=NF;i++){ if($i=="hold"){ print $1;break }}}' + )" } -_have grep-status && { - _comp_dpkg_purgeable_packages() - { - grep-status -P -e "^$1" -a -FStatus 'ok installed' -o -FStatus 'ok config-files' -n -s Package - } -} || { - _comp_dpkg_purgeable_packages() - { - command grep -A 1 "Package: $1" /var/lib/dpkg/status 2>/dev/null | - command grep -B 1 -Ee "ok installed|half-installed|unpacked| \ - half-configured|config-files" \ - -Ee "^Essential: yes" | - awk "/Package: $1/ { print \$2 }" 2>/dev/null - } +# @deprecated 2.12 use _comp_xfunc_dpkg_compgen_installed_packages instead +_comp_dpkg_installed_packages() +{ + local COMPREPLY=() cur="${1-}" + # shellcheck disable=SC2119 + _comp_xfunc_dpkg_compgen_installed_packages + printf "%s\n" "${COMPREPLY[@]}" +} +# @deprecated 2.12 use _comp_xfunc_dpkg_compgen_purgeable_packages instead +_comp_dpkg_purgeable_packages() +{ + local COMPREPLY=() cur="${1-}" + # shellcheck disable=SC2119 + _comp_xfunc_dpkg_compgen_purgeable_packages + printf "%s\n" "${COMPREPLY[@]}" } # Debian dpkg(1) completion # -_dpkg() +_comp_cmd_dpkg() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return local i=$cword @@ -48,79 +72,111 @@ _dpkg() done fi + local noargopts='!(-*|*[ciAIfexXbsplWSrVLPD]*)' + # shellcheck disable=SC2254 case $prev in --install | --unpack | --record-avail | --contents | --info | --fsys-tarfile | \ - --field | --control | --extract | --vextract | --raw-extract | -!(-*)[ciAIfexX]) - _filedir '?(u|d)deb' + --field | --control | --extract | --vextract | --raw-extract | -${noargopts}[ciAIfexX]) + _comp_compgen_filedir '?(u|d)deb' return ;; - --build | -!(-*)b) - _filedir -d + --build | --admindir | --instdir | --root | -${noargopts}b) + _comp_compgen_filedir -d return ;; - --status | --print-avail | --list | -!(-*)[spl]) - COMPREPLY=($(_xfunc apt-cache _apt_cache_packages)) + --status | --print-avail | --list | -${noargopts}[spl]) + _comp_compgen -x apt-cache packages return ;; - --show | -!(-*)W) + --show | -${noargopts}W) if [[ $1 == *dpkg-query ]]; then - COMPREPLY=($(_xfunc apt-cache _apt_cache_packages)) + _comp_compgen -x apt-cache packages else - _filedir '?(u|d)deb' + _comp_compgen_filedir '?(u|d)deb' fi return ;; - --search | -!(-*)S) - _filedir + --search | -${noargopts}S) + _comp_compgen_filedir + return + ;; + --remove | --verify | -${noargopts}[rV]) + _comp_xfunc_dpkg_compgen_installed_packages return ;; - --remove | --verify | -!(-*)[rV]) - COMPREPLY=($(_comp_dpkg_installed_packages "$cur")) + --listfiles | --purge | -${noargopts}[LP]) + _comp_xfunc_dpkg_compgen_purgeable_packages return ;; - --listfiles | --purge | -!(-*)[LP]) - COMPREPLY=($(_comp_dpkg_purgeable_packages "$cur")) + --debug | -${noargopts}D) + _comp_compgen -- -W 'help' + return + ;; + --ignore-depends) + local packages + _comp_compgen -v packages -c "${cur##*,}" -x apt-cache packages + _comp_delimited , -W '"${packages[@]}"' + return + ;; + --log) + _comp_compgen_filedir log + return + ;; + --path-exclude | --path-include) + return + ;; + --status-logger) + _comp_compgen_commands + return + ;; + --verify-format) + _comp_compgen -- -W 'rpm' return ;; esac - $split && return + [[ $was_split ]] && return - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help + for i in ${!COMPREPLY[*]}; do + # remove ones ending with a dash (known parse issue, hard to fix) + [[ ${COMPREPLY[i]} != *- ]] || unset -v 'COMPREPLY[i]' + done [[ ${COMPREPLY-} == *= ]] && compopt -o nospace } && - complete -F _dpkg dpkg dpkg-deb dpkg-query + complete -F _comp_cmd_dpkg dpkg dpkg-deb dpkg-query -# Debian GNU dpkg-reconfigure(8) completion -# -_dpkg_reconfigure() +_comp_cmd_dpkg_reconfigure() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local opt + local noargopts='!(-*|*[fp]*)' + # shellcheck disable=SC2254 case $prev in - --frontend | -!(-*)f) - opt=($(printf '%s\n' /usr/share/perl5/Debconf/FrontEnd/*)) - opt=(${opt[@]##*/}) - opt=(${opt[@]%.pm}) - COMPREPLY=($(compgen -W '${opt[@]}' -- "$cur")) + --frontend | -${noargopts}f) + if _comp_expand_glob opt '/usr/share/perl5/Debconf/FrontEnd/*'; then + opt=("${opt[@]##*/}") + opt=("${opt[@]%.pm}") + _comp_compgen -- -W '"${opt[@]}"' + fi return ;; - --priority | -!(-*)p) - COMPREPLY=($(compgen -W 'low medium high critical' -- "$cur")) + --priority | -${noargopts}p) + _comp_compgen -- -W 'low medium high critical' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--frontend --priority --all --unseen-only - --help --showold --force --terse' -- "$cur")) + _comp_compgen -- -W '--frontend --priority --all --unseen-only --help + --showold --force --terse' else - COMPREPLY=($(_comp_dpkg_installed_packages "$cur")) + _comp_xfunc_dpkg_compgen_installed_packages fi } && - complete -F _dpkg_reconfigure -o default dpkg-reconfigure + complete -F _comp_cmd_dpkg_reconfigure -o default dpkg-reconfigure # ex: filetype=sh diff --git a/completions/dpkg-source b/completions/dpkg-source index 05fa3a1..c9131b2 100644 --- a/completions/dpkg-source +++ b/completions/dpkg-source @@ -1,9 +1,9 @@ # Debian dpkg-source completion -*- shell-script -*- -_dpkg_source() +_comp_cmd_dpkg_source() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local options word action packopts unpackopts fields @@ -29,13 +29,11 @@ _dpkg_source() unpack) case $prev in -x) - _filedir -d - _filedir 'dsc' + _comp_compgen_filedir 'dsc' ;; *) - COMPREPLY=($(compgen -W "$unpackopts" -- "$cur")) - _filedir -d - _filedir + _comp_compgen -- -W "$unpackopts" + _comp_compgen -a filedir ;; esac return @@ -43,7 +41,7 @@ _dpkg_source() pack) case $prev in -b) - _filedir -d + _comp_compgen_filedir -d ;; -c | -l | -T | -i | -I) # -c: get controlfile @@ -52,12 +50,11 @@ _dpkg_source() # -i: <regexp> filter out files to ignore diffs of. # -I: filter out files when building tarballs. # return directory names and file names - _filedir -d - _filedir + _comp_compgen_filedir ;; -F) # -F: force change log format - COMPREPLY=($(command ls /usr/lib/dpkg/parsechangelog)) + _comp_compgen_split -- "$(command ls /usr/lib/dpkg/parsechangelog)" ;; -V) # -V: set a substitution variable @@ -72,27 +69,26 @@ _dpkg_source() # $cur contains a "=" COMPREPLY=() else - COMPREPLY=($(compgen -W "$fields" -- "$cur")) + _comp_compgen -- -W "$fields" fi ;; -U) # -U: remove a field # Suggest possible fieldnames - COMPREPLY=($(compgen -W "$fields" -- "$cur")) + _comp_compgen -- -W "$fields" ;; *) - COMPREPLY=($(compgen -W "$packopts $unpackopts" \ - -- "$cur")) + _comp_compgen -- -W '$packopts $unpackopts' ;; esac return ;; *) - COMPREPLY=($(compgen -W "$options" -- "$cur")) + _comp_compgen -- -W "$options" return ;; esac } && - complete -F _dpkg_source dpkg-source + complete -F _comp_cmd_dpkg_source dpkg-source # ex: filetype=sh diff --git a/completions/dselect b/completions/dselect index 4c18026..554ab21 100644 --- a/completions/dselect +++ b/completions/dselect @@ -1,29 +1,28 @@ # Debian Linux dselect(8) completion -*- shell-script -*- -_dselect() +_comp_cmd_dselect() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --admindir) - _filedir -d + _comp_compgen_filedir -d return ;; -D | -debug) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help else - COMPREPLY=($(compgen -W 'access update select install config remove - quit' -- "$cur")) + _comp_compgen -- -W 'access update select install config remove quit' fi } && - complete -F _dselect dselect + complete -F _comp_cmd_dselect dselect # ex: filetype=sh diff --git a/completions/dsniff b/completions/dsniff index 749c533..f09eac2 100644 --- a/completions/dsniff +++ b/completions/dsniff @@ -1,26 +1,27 @@ # dsniff completion -*- shell-script -*- -_dsniff() +_comp_cmd_dsniff() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -r | -w | -f | -p) - _filedir + _comp_compgen_filedir return ;; -i) - _available_interfaces -a + _comp_compgen_available_interfaces -a return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1") -r -w -p' -- "$cur")) + _comp_compgen_usage + _comp_compgen -a -- -W '-r -w -p' fi } && - complete -F _dsniff dsniff + complete -F _comp_cmd_dsniff dsniff # ex: filetype=sh diff --git a/completions/dumpdb b/completions/dumpdb index eb1927f..0390b4e 100644 --- a/completions/dumpdb +++ b/completions/dumpdb @@ -1,18 +1,17 @@ # mailman dumpdb completion -*- shell-script -*- -_dumpdb() +_comp_cmd_dumpdb() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--marshal --pickle --noprint --help' \ - -- "$cur")) + _comp_compgen -- -W '--marshal --pickle --noprint --help' else - _filedir + _comp_compgen_filedir fi } && - complete -F _dumpdb dumpdb + complete -F _comp_cmd_dumpdb dumpdb # ex: filetype=sh diff --git a/completions/dumpe2fs b/completions/dumpe2fs index 413a5bf..326564e 100644 --- a/completions/dumpe2fs +++ b/completions/dumpe2fs @@ -1,28 +1,27 @@ # dumpe2fs(8) completion -*- shell-script -*- -_dumpe2fs() +_comp_cmd_dumpe2fs() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*[oV]) return ;; -*i) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage return fi - cur=${cur:=/dev/} - _filedir + _comp_compgen -c "${cur:-/dev/}" filedir } && - complete -F _dumpe2fs dumpe2fs + complete -F _comp_cmd_dumpe2fs dumpe2fs # ex: filetype=sh diff --git a/completions/e2freefrag b/completions/e2freefrag index c89dc9c..7fa4841 100644 --- a/completions/e2freefrag +++ b/completions/e2freefrag @@ -1,9 +1,9 @@ # e2freefrag(8) completion -*- shell-script -*- -_e2freefrag() +_comp_cmd_e2freefrag() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -c | -h) @@ -12,13 +12,12 @@ _e2freefrag() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" -h)' -- "$cur")) + _comp_compgen_usage -- -h return fi - cur=${cur:=/dev/} - _filedir + _comp_compgen -c "${cur:-/dev/}" filedir } && - complete -F _e2freefrag e2freefrag + complete -F _comp_cmd_e2freefrag e2freefrag # ex: filetype=sh diff --git a/completions/e2label b/completions/e2label index ac8e4b5..456907c 100644 --- a/completions/e2label +++ b/completions/e2label @@ -1,15 +1,14 @@ # e2label(8) completion -*- shell-script -*- -_e2label() +_comp_cmd_e2label() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if ((cword == 1)); then - cur=${cur:=/dev/} - _filedir + _comp_compgen -c "${cur:-/dev/}" filedir fi } && - complete -F _e2label e2label + complete -F _comp_cmd_e2label e2label # ex: filetype=sh diff --git a/completions/ebtables b/completions/ebtables index de6bc54..24f3fe7 100644 --- a/completions/ebtables +++ b/completions/ebtables @@ -1,47 +1,49 @@ # bash completion for ebtables -*- shell-script -*- -_ebtables() +_comp_cmd_ebtables() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return - local table chain='s/^Bridge chain: \([^ ,]\{1,\}\).*$/\1/p' \ + local table="" chain='s/^Bridge chain: \([^ ,]\{1,\}\).*$/\1/p' \ targets='ACCEPT DROP CONTINUE RETURN' + local IFS=$' \t\n' # for ${table:+-t "$table"} [[ ${words[*]} =~ [[:space:]]-(t|-table=?)[[:space:]]*([^[:space:]]+) ]] && - table="-t ${BASH_REMATCH[2]}" + table=${BASH_REMATCH[2]} + local noargopts='!(-*|*[AIDPFXLZtj]*)' + # shellcheck disable=SC2254 case $prev in - -!(-*)[AIDPFXLZ]) - COMPREPLY=($(compgen -W '`"$1" $table -L 2>/dev/null | \ - command sed -ne "$chain"`' -- "$cur")) + -${noargopts}[AIDPFXLZ]) + _comp_compgen_split -- "$( + "$1" ${table:+-t "$table"} -L 2>/dev/null | + command sed -ne "$chain" + )" ;; - -!(-*)t) - COMPREPLY=($(compgen -W 'nat filter broute' -- "$cur")) + -${noargopts}t) + _comp_compgen -- -W 'nat filter broute' ;; - -!(-*)j) - if [[ $table == "-t filter" || -z $table ]]; then - COMPREPLY=($(compgen -W '$targets - $("$1" $table -L 2>/dev/null | \ - command sed -n -e "s/INPUT\|OUTPUT\|FORWARD//" \ - -e "$chain")' \ - -- "$cur")) - elif [[ $table == "-t nat" ]]; then - COMPREPLY=($(compgen -W '$targets - $("$1" $table -L 2>/dev/null | \ - command sed -n -e "s/OUTPUT|PREROUTING|POSTROUTING//" \ - -e "$chain")' \ - -- "$cur")) - elif [[ $table == "-t broute" ]]; then - COMPREPLY=($(compgen -W 'ACCEPT DROP - $("$1" $table -L 2>/dev/null | \ - command sed -n -e "s/BROUTING//" -e "$chain")' \ - -- "$cur")) + -${noargopts}j) + if [[ $table == "filter" || ! $table ]]; then + _comp_compgen -- -W '$targets' + _comp_compgen -a split -- "$("$1" ${table:+-t "$table"} -L \ + 2>/dev/null | command sed -n -e \ + "s/INPUT\|OUTPUT\|FORWARD//" -e "$chain")" + elif [[ $table == "nat" ]]; then + _comp_compgen -- -W '$targets' + _comp_compgen -a split -- "$("$1" -t "$table" -L 2>/dev/null | + command sed -n -e "s/OUTPUT|PREROUTING|POSTROUTING//" \ + -e "$chain")" + elif [[ $table == "broute" ]]; then + _comp_compgen -- -W 'ACCEPT DROP' + _comp_compgen -a split -- "$("$1" -t "$table" -L 2>/dev/null | + command sed -n -e "s/BROUTING//" -e "$chain")" fi ;; *) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--802_3-sap --802_3-type --among-dst + _comp_compgen -- -W '--802_3-sap --802_3-type --among-dst --among-dst-file --among-src --among-src-file --append --arp-gratuitous --arp-htype --arp-ip-dst --arp-ip-src --arp-mac-dst --arp-mac-src --arp-opcode --arp-ptype --arpreply-mac @@ -67,12 +69,12 @@ _ebtables() --stp-sender-prio --stp-type --table --to-destination --to-dst --to-source --to-src --ulog --ulog-cprange --ulog-nlgroup --ulog-prefix --ulog-qthreshold --version --vlan-encap --vlan-id - --vlan-prio --zero' -- "$cur")) + --vlan-prio --zero' fi ;; esac } && - complete -F _ebtables ebtables + complete -F _comp_cmd_ebtables ebtables # ex: filetype=sh diff --git a/completions/ecryptfs-migrate-home b/completions/ecryptfs-migrate-home index d2eeb38..7566d6b 100644 --- a/completions/ecryptfs-migrate-home +++ b/completions/ecryptfs-migrate-home @@ -1,22 +1,22 @@ # ecryptfs-migrate-home(8) completion -*- shell-script -*- -_ecryptfs_migrate_home() +_comp_cmd_ecryptfs_migrate_home() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --help) return ;; --user | -u) - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u return ;; esac - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help } && - complete -F _ecryptfs_migrate_home ecryptfs-migrate-home + complete -F _comp_cmd_ecryptfs_migrate_home ecryptfs-migrate-home # ex: filetype=sh diff --git a/completions/eog b/completions/eog index 2330e1a..14c448d 100644 --- a/completions/eog +++ b/completions/eog @@ -1,9 +1,9 @@ # eog(1) completion -*- shell-script -*- -_eog() +_comp_cmd_eog() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -'?' | --help | --help-all | --help-gtk) @@ -11,16 +11,16 @@ _eog() ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" --help-all)' -- "$cur")) + _comp_compgen_help -- --help-all [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir '@(ani|?(w)bmp|gif|ico|j2[ck]|jp[cefgx2]|jpeg|jpg2|pcx|p[gp]m|pn[gm]|ras|svg?(z)|tga|tif?(f)|x[bp]m)' + _comp_compgen_filedir '@(ani|avif|?(w)bmp|gif|hei[cf]|ico|j2[ck]|jp[cefgx2]|jpeg|jpg2|jxl|pcx|p[bgp]m|pn[gm]|ras|svg?(z)|tga|tif?(f)|webp|x[bp]m)' } && - complete -F _eog eog + complete -F _comp_cmd_eog eog # ex: filetype=sh diff --git a/completions/ether-wake b/completions/ether-wake index d952673..d2c7f83 100644 --- a/completions/ether-wake +++ b/completions/ether-wake @@ -1,13 +1,13 @@ # ether-wake(8) completion -*- shell-script -*- -_ether_wake() +_comp_cmd_ether_wake() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return case $prev in -i) - _available_interfaces -a + _comp_compgen_available_interfaces -a return ;; -p) @@ -16,12 +16,13 @@ _ether_wake() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -u) -V' -- "$cur")) + _comp_compgen_help -- -u + _comp_compgen -a -- -W '-V' return fi - _mac_addresses + _comp_compgen_mac_addresses } && - complete -F _ether_wake ether-wake etherwake + complete -F _comp_cmd_ether_wake ether-wake etherwake # ex: filetype=sh diff --git a/completions/evince b/completions/evince index 1c97dd9..49b67ac 100644 --- a/completions/evince +++ b/completions/evince @@ -1,32 +1,34 @@ # evince(1) completion -*- shell-script -*- -_evince() +_comp_cmd_evince() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[pil]*)' + # shellcheck disable=SC2254 case $prev in --help* | --sm-client-id | --class | --name | --screen | --gdk-debug | \ --gdk-no-debug | --gtk-module | --gtk-debug | --gtk-no-debug | --page-label | \ - --page-index | --find | --display | -!(-*)[hpil]) + --page-index | --find | --display | -${noargopts}[hpil]) return ;; --sm-client-state-file) - _filedir + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" --help-all)' -- "$cur")) + _comp_compgen_help -- --help-all [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir '@(@(?(e)ps|?(E)PS|[pf]df|[PF]DF|dvi|DVI)?(.gz|.GZ|.bz2|.BZ2|.xz|.XZ)|cb[rz]|djv?(u)|gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx)' + _comp_compgen_filedir '@(@(?(e)ps|?(E)PS|[pf]df|[PF]DF|dvi|DVI)?(.gz|.GZ|.bz2|.BZ2|.xz|.XZ)|cb[7rtz]|djv?(u)|tif?(f)|?(o)xps)' } && - complete -F _evince evince + complete -F _comp_cmd_evince evince # ex: filetype=sh diff --git a/completions/export b/completions/export index 8d82361..0f692c9 100644 --- a/completions/export +++ b/completions/export @@ -1,11 +1,11 @@ # bash export completion -*- shell-script -*- -_export() +_comp_cmd_export() { - local cur prev words cword - _init_completion -n = || return + local cur prev words cword comp_args + _comp_initialize -n := -- "$@" || return - local i action=variable remove=false + local i action=variable remove="" for ((i = 1; i < cword; i++)); do case ${words[i]} in -p) @@ -15,7 +15,7 @@ _export() action=function ;;& -*n*) - remove=true + remove=set ;; -*) continue @@ -25,41 +25,40 @@ _export() done if [[ $cur == *=* ]]; then - local ocur=$cur oprev=$prev - prev=${cur%%=*} cur=${cur#*=} - _variables && return - cur=$ocur prev=$oprev + _comp_variable_assignments "$cur" && return fi case $cur in *=) - local pval=$(quote "$(eval printf %s \"\$\{${cur%=}-\}\")") + local pname=${cur%=} + local REPLY + _comp_quote "${!pname-}" + local pval=$REPLY # Complete previous value if it's not empty. if [[ $pval != \'\' ]]; then COMPREPLY=("$pval") else - cur=${cur#*=} - _filedir + _comp_compgen -c "${cur#*=}" filedir fi ;; *=*) - cur=${cur#*=} - _filedir + _comp_compgen -c "${cur#*=}" filedir ;; *) if [[ $cword -eq 1 && $cur == -* ]]; then - COMPREPLY=($(compgen -W '-p $(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage -c help -s "$1" + _comp_compgen -a -- -W '-p' return fi local suffix="" - if ! $remove; then + if [[ ! $remove && $action != function ]]; then suffix="=" compopt -o nospace fi - COMPREPLY=($(compgen -A $action -S "$suffix" -- "$cur")) + _comp_compgen -- -A $action -S "$suffix" ;; esac } && - complete -F _export export + complete -F _comp_cmd_export export # ex: filetype=sh diff --git a/completions/faillog b/completions/faillog index c8b81bd..5343613 100644 --- a/completions/faillog +++ b/completions/faillog @@ -1,27 +1,29 @@ # faillog(8) completion -*- shell-script -*- -_faillog() +_comp_cmd_faillog() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[lmtu]*)' + # shellcheck disable=SC2254 case $prev in - --help | --lock-time | --maximum | --time | -!(-*)[hlmt]) + --help | --lock-time | --maximum | --time | -${noargopts}[hlmt]) return ;; - --user | -!(-*)u) - COMPREPLY=($(compgen -u -- "$cur")) + --user | -${noargopts}u) + _comp_compgen -- -u return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _faillog faillog + complete -F _comp_cmd_faillog faillog # ex: filetype=sh diff --git a/completions/fbgs b/completions/fbgs index 1947b87..66bcbbb 100644 --- a/completions/fbgs +++ b/completions/fbgs @@ -1,30 +1,29 @@ # bash completion for fbgs(1) -*- shell-script -*- -_fbgs() +_comp_cmd_fbgs() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case "$prev" in -f | --font) - local IFS=$'\n' - COMPREPLY=($(compgen -W '$(fc-list 2>/dev/null)' -- "$cur")) + _comp_compgen_split -l -- "$(fc-list 2>/dev/null)" return ;; -m | --mode) - COMPREPLY=($(compgen -W '$(command sed \ - -n "/^mode/{s/^mode \{1,\}\"\([^\"]\{1,\}\)\"/\1/g;p}" \ - /etc/fb.modes 2>/dev/null)' -- "$cur")) + _comp_compgen_split -- "$(command sed \ + -n '/^mode/{s/^mode \{1,\}"\([^"]\{1,\}\)"/\1/g;p}' \ + /etc/fb.modes 2>/dev/null)" return ;; -d | --device) - COMPREPLY=($(compgen -f -d -- "${cur:-/dev/}")) + _comp_compgen -c "${cur:-/dev/}" -- -f -d return ;; -fp | --firstpage | -lp | --lastpage | -r | --resolution | -s | --scroll | -t | \ --timeout) # expect integer value - COMPREPLY+=($(compgen -W '{0..9}')) + _comp_compgen -aR -- -W '{0..9}' compopt -o nospace return ;; @@ -35,16 +34,16 @@ _fbgs() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--bell --help --password -fp --firstpage - -lp --lastpage --color -l -xl -xxl --resolution --autozoom + _comp_compgen -- -W '--bell --help --password -fp --firstpage -lp + --lastpage --color -l -xl -xxl --resolution --autozoom --{,no}autoup --{,no}autodown --{,no}fitwidth --{,no}verbose --{,no}random --vt --scroll --timeout --{,no}once --gamma --font - --device --mode' -- "$cur")) + --device --mode' [[ ${COMPREPLY-} ]] && return fi - _filedir '?(e)ps|pdf' + _comp_compgen_filedir '?(e)ps|pdf' } && - complete -F _fbgs fbgs + complete -F _comp_cmd_fbgs fbgs # ex: filetype=sh diff --git a/completions/fbi b/completions/fbi index 455887a..275395e 100644 --- a/completions/fbi +++ b/completions/fbi @@ -1,32 +1,31 @@ # bash completion for fbi(1) -*- shell-script -*- -_fbi() +_comp_cmd_fbi() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case "$prev" in -l | --list) - _filedir + _comp_compgen_filedir return ;; -r | --resolution) - COMPREPLY+=($(compgen -W '{1..5}')) + _comp_compgen -aR -- -W '{1..5}' return ;; -f | --font) - local IFS=$'\n' - COMPREPLY=($(compgen -W '$(fc-list 2>/dev/null)' -- "$cur")) + _comp_compgen_split -l -- "$(fc-list 2>/dev/null)" return ;; -m | --mode) - COMPREPLY=($(compgen -W '$(command sed \ - -n "/^mode/{s/^mode \{1,\}\"\([^\"]\{1,\}\)\"/\1/g;p}" \ - /etc/fb.modes 2>/dev/null)' -- "$cur")) + _comp_compgen_split -- "$(command sed \ + -n '/^mode/{s/^mode \{1,\}"\([^"]\{1,\}\)"/\1/g;p}' \ + /etc/fb.modes 2>/dev/null)" return ;; -d | --device) - COMPREPLY=($(compgen -f -d -- "${cur:-/dev/}")) + _comp_compgen -c "${cur:-/dev/}" -- -f -d return ;; --cachemem | --blend | -T | --vt | -s | --scroll | -t | --timeout | -g | --gamma) @@ -36,19 +35,18 @@ _fbi() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--help --version --store --list --text - --autozoom --{,no}autoup --{,no}autodown --{,no}fitwidth - --{,no}verbose --{,no}random --{,no}comments --{,no}edit - --{,no}backup --{,no}preserve --{,no}readahead --cachemem --blend - --vt --scroll --timeout --{,no}once --resolution --gamma --font - --device --mode' -- "$cur")) + _comp_compgen -- -W '--help --version --store --list --text --autozoom + --{,no}autoup --{,no}autodown --{,no}fitwidth --{,no}verbose + --{,no}random --{,no}comments --{,no}edit --{,no}backup + --{,no}preserve --{,no}readahead --cachemem --blend --vt --scroll + --timeout --{,no}once --resolution --gamma --font --device --mode' [[ ${COMPREPLY-} ]] && return fi # FIXME: It is hard to determine correct supported extensions. # fbi can handle any format that imagemagick can plus some others - _filedir 'bmp|gif|jp?(e)g|pcd|png|p[pgb]m|tif?(f)|webp|xpm|xwd|?(e)ps|pdf|dvi|txt|svg?(z)|cdr|[ot]tf' + _comp_compgen_filedir 'bmp|gif|jp?(e)g|pcd|png|p[pgb]m|tif?(f)|webp|xpm|xwd|?(e)ps|pdf|dvi|txt|svg?(z)|cdr|[ot]tf' } && - complete -F _fbi fbi + complete -F _comp_cmd_fbi fbi # ex: filetype=sh diff --git a/completions/feh b/completions/feh index f1d4b18..3762574 100644 --- a/completions/feh +++ b/completions/feh @@ -1,110 +1,108 @@ # bash completion for feh(1) -*- shell-script -*- -_feh() +_comp_cmd_feh() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[foO|KCjeM@TSRHWEyJabgLD~^]*)' + # shellcheck disable=SC2254 case "$prev" in --image-bg | -B) - COMPREPLY=($(compgen -W 'checks white black' -- "$cur")) + _comp_compgen -- -W 'checks white black' return ;; - --filelist | --output | --output-only | --start-at | -!(-*)[foO\|]) - _filedir + --filelist | --output | --output-only | --start-at | -${noargopts}[foO\|]) + _comp_compgen_filedir return ;; - --caption-path | --fontpath | --output-dir | -!(-*)[KCj]) - _filedir -d + --caption-path | --fontpath | --output-dir | -${noargopts}[KCj]) + _comp_compgen_filedir -d return ;; - --font | --menu-font | --title-font | -!(-*)[eM@]) + --font | --menu-font | --title-font | -${noargopts}[eM@]) # expect string like "dejavu.ttf/12" if [[ $cur == */* ]]; then # expect integer value - COMPREPLY=($(compgen -P "$cur" -W '{0..9}')) + _comp_compgen -R -- -P "$cur" -W '{0..9}' compopt -o nospace return fi local font_path # font_path="$(imlib2-config --prefix 2>/dev/null)/share/imlib2/data/fonts" - # COMPREPLY=( $(cd "$font_path" 2>/dev/null; compgen -f \ - # -X "!*.@([tT][tT][fF])" -S / -- "$cur") ) + # _comp_compgen -C "$font_path" -- -f -X "!*.@([tT][tT][fF])" -S / for ((i = ${#words[@]} - 1; i > 0; i--)); do if [[ ${words[i]} == -@(C|-fontpath) ]]; then font_path="${words[i + 1]}" - COMPREPLY+=($( - cd "$font_path" 2>/dev/null - compgen -f \ - -X "!*.@([tT][tT][fF])" -S / -- "$cur" - )) + _comp_compgen -aC "$font_path" -- \ + -f -X "!*.@([tT][tT][fF])" -S / fi done compopt -o nospace return ;; - --theme | -!(-*)T) + --theme | -${noargopts}T) local conf_path=~/.config/feh/themes local theme_name theme_opts [[ -r $conf_path ]] || return - while read theme_name theme_opts; do + while read -r theme_name theme_opts; do if [[ $theme_name == '#'* || $theme_name == "" ]]; then continue fi - COMPREPLY+=($(compgen -W "$theme_name" -- "$cur")) + _comp_compgen -a -- -W "$theme_name" done <"$conf_path" return ;; - --sort | -!(-*)S) - COMPREPLY=($(compgen -W 'name filename mtime width height - pixels size format' -- "$cur")) + --sort | -${noargopts}S) + _comp_compgen -- -W 'name filename mtime width height pixels size + format' return ;; --reload | --limit-height | --limit-width | --thumb-height | --thumb-width | \ - --thumb-redraw | --magick-timeout | -!(-*)[RHWEyJ]) + --thumb-redraw | --magick-timeout | -${noargopts}[RHWEyJ]) # expect integer value - COMPREPLY+=($(compgen -W '{0..9}')) + _comp_compgen -aR -- -W '{0..9}' compopt -o nospace return ;; --zoom) # expect integer value or "max", "fill" - COMPREPLY=($(compgen -W 'max fill' -- "$cur")) + _comp_compgen -- -W 'max fill' if [[ ! $cur || ! ${COMPREPLY-} ]]; then - COMPREPLY+=($(compgen -W '{0..9}')) + _comp_compgen -aR -- -W '{0..9}' compopt -o nospace fi return ;; - --alpha | -!(-*)a) - COMPREPLY=($(compgen -W '{0..255}' -- "$cur")) + --alpha | -${noargopts}a) + _comp_compgen -- -W '{0..255}' return ;; - --bg | -!(-*)b) - _filedir - COMPREPLY+=($(compgen -W 'trans' -- "$cur")) + --bg | -${noargopts}b) + _comp_compgen_filedir + _comp_compgen -a -- -W 'trans' return ;; - --geometry | --max-dimension | --min-dimension | -!(-*)g) + --geometry | --max-dimension | --min-dimension | -${noargopts}g) # expect string like 640x480 if [[ $cur && $cur != *x* ]]; then COMPREPLY=(x) fi - COMPREPLY+=($(compgen -W "{0..9}")) + _comp_compgen -aR -- -W "{0..9}" compopt -o nospace return ;; --customlist | --index-info | --info | --slideshow-delay | --thumb-title | \ - --title | -!(-*)[LD~^]) + --title | -${noargopts}[LD~^]) # argument required but no completions available return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then # Some versions of feh just output "See 'man feh'" for --help :( - COMPREPLY=($(compgen -W '$(_parse_help "$1" --help)' -- "$cur")) + _comp_compgen_help if [[ ${COMPREPLY-} ]]; then [[ $COMPREPLY == *= ]] && compopt -o nospace return @@ -113,8 +111,8 @@ _feh() # FIXME: It is hard to determine correct supported extensions. # feh can handle any format that imagemagick can plus some others - _filedir 'xpm|tif?(f)|png|p[npgba]m|iff|?(i)lbm|jp?(e)g|jfi?(f)|gif|bmp|arg?(b)|tga|xcf|ani|ico|?(e)ps|pdf|dvi|txt|svg?(z)|cdr|[ot]tf' + _comp_compgen_filedir 'xpm|tif?(f)|png|p[npgba]m|iff|?(i)lbm|jp?(e)g|jfi?(f)|gif|bmp|arg?(b)|tga|xcf|ani|ico|?(e)ps|pdf|dvi|txt|svg?(z)|cdr|[ot]tf|ff?(.gz|.bz2)|webp|y4m|hei[cf]?(s)|avif?(s)' } && - complete -F _feh feh + complete -F _comp_cmd_feh feh # ex: filetype=sh diff --git a/completions/file b/completions/file index 21fbd16..7b07d40 100644 --- a/completions/file +++ b/completions/file @@ -1,32 +1,34 @@ # file(1) completion -*- shell-script -*- -_file() +_comp_cmd_file() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[Fmfe]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | --separator | -!(-*)[vF]) + --help | --version | --separator | -${noargopts}[vF]) return ;; - --magic-file | --files-from | -!(-*)[mf]) - _filedir + --magic-file | --files-from | -${noargopts}[mf]) + _comp_compgen_filedir return ;; - --exclude | -!(-*)e) - COMPREPLY=($(compgen -W 'apptype ascii cdf compress elf encoding - soft tar text tokens troff' -- "$cur")) + --exclude | -${noargopts}e) + _comp_compgen -- -W 'apptype ascii cdf compress elf encoding soft + tar text tokens troff' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - _filedir + _comp_compgen_filedir } && - complete -F _file file + complete -F _comp_cmd_file file # ex: filetype=sh diff --git a/completions/file-roller b/completions/file-roller index 1d223fd..cd745ac 100644 --- a/completions/file-roller +++ b/completions/file-roller @@ -1,42 +1,44 @@ # file-roller(1) completion -*- shell-script -*- -_file_roller() +_comp_cmd_file_roller() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return - local exts='@(7z|ace|alz|ar|arj|[bglx]z|bz2|tb?(z)2|cab|cb[rz]|iso?(9660)|Z|t[abglx]z|cpio|deb|rar|?(g)tar|gem|lh[az]|lz[4h]|?(t)lrz|lzma|lzo|wim|swm|rpm|sit|zoo)' + local exts='@(7z?(.001)|ace|alz|ar|arj|[bglx]z|bz2|tb?(z)2|cab|cb[rz]|iso?(9660)|Z|t[abglx]z|cpio|deb|rar|?(g)tar|gem|lh[az]|lz[4h]|?(t)lrz|lzma|lzo|wim|swm|rpm|sit|zoo|?(t)zst)' + local noargopts='!(-*|*[ae]*)' + # shellcheck disable=SC2254 case $prev in - --help | --help-all | --help-gtk | --help-sm-client | -!(-*)'?') + --help | --help-all | --help-gtk | --help-sm-client | -${noargopts}'?') return ;; --sm-client-state-file) - _filedir + _comp_compgen_filedir return ;; - --add-to | -!(-*)a) - _filedir_xspec unzip - _filedir "$exts" + --add-to | -${noargopts}a) + _comp_compgen_filedir_xspec unzip + _comp_compgen -a filedir "$exts" return ;; - --extract-to | --default-dir | -!(-*)e) - _filedir -d + --extract-to | --default-dir | -${noargopts}e) + _comp_compgen_filedir -d return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" --help-all)' -- "$cur")) + _comp_compgen_help -- --help-all [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir_xspec unzip - _filedir "$exts" + _comp_compgen_filedir_xspec unzip + _comp_compgen -a filedir "$exts" } && - complete -F _file_roller file-roller + complete -F _comp_cmd_file_roller file-roller # ex: filetype=sh diff --git a/completions/filefrag b/completions/filefrag index d26e8c8..6de8a19 100644 --- a/completions/filefrag +++ b/completions/filefrag @@ -1,17 +1,17 @@ # filefrag(8) completion -*- shell-script -*- -_filefrag() +_comp_cmd_filefrag() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage return fi - _filedir + _comp_compgen_filedir } && - complete -F _filefrag filefrag + complete -F _comp_cmd_filefrag filefrag # ex: filetype=sh diff --git a/completions/filesnarf b/completions/filesnarf index f959d80..d4c1cb0 100644 --- a/completions/filesnarf +++ b/completions/filesnarf @@ -1,22 +1,22 @@ # filesnarf etc completion -*- shell-script -*- -_snarf() +_comp_cmd_snarf() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -i) - _available_interfaces -a + _comp_compgen_available_interfaces -a return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage fi } && - complete -F _snarf filesnarf mailsnarf msgsnarf + complete -F _comp_cmd_snarf filesnarf mailsnarf msgsnarf # ex: filetype=sh diff --git a/completions/find b/completions/find index 64121ed..92c7fa8 100644 --- a/completions/find +++ b/completions/find @@ -2,53 +2,53 @@ # This makes heavy use of ksh style extended globs and contains Linux specific # code for completing the parameter to the -fstype option. -_find() +_comp_cmd_find() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local i - for i in ${!words[*]}; do + for ((i = 1; i < cword; i++)); do if [[ ${words[i]} == -@(exec|ok)?(dir) ]]; then - _command_offset $((i + 1)) + _comp_command_offset $((i + 1)) return fi done case $prev in -maxdepth | -mindepth) - COMPREPLY=($(compgen -W '{0..9}' -- "$cur")) + _comp_compgen -- -W '{0..9}' return ;; -newer | -anewer | -cnewer | -fls | -fprint | -fprint0 | -fprintf | -name | -[il]name | \ -ilname | -wholename | -[il]wholename | -samefile) - _filedir + _comp_compgen_filedir return ;; -fstype) - _fstypes + _comp_compgen_fstypes [[ $OSTYPE == *bsd* ]] && - COMPREPLY+=($(compgen -W 'local rdonly' -- "$cur")) + _comp_compgen -a -- -W 'local rdonly' return ;; -gid) - _gids + _comp_compgen_gids return ;; -group) - COMPREPLY=($(compgen -g -- "$cur" 2>/dev/null)) + _comp_compgen -- -g return ;; -xtype | -type) - COMPREPLY=($(compgen -W 'b c d p f l s' -- "$cur")) + _comp_compgen -- -W 'b c d p f l s' return ;; -uid) - _uids + _comp_compgen_uids return ;; -user) - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u return ;; -[acm]min | -[acm]time | -inum | -path | -ipath | -regex | -iregex | -links | -perm | \ @@ -57,35 +57,34 @@ _find() return ;; -regextype) - COMPREPLY=($(compgen -W 'emacs posix-awk posix-basic posix-egrep - posix-extended' -- "$cur")) + _comp_compgen -- -W 'emacs posix-awk posix-basic posix-egrep + posix-extended' return ;; esac - local i exprfound=false + local i exprfound="" # set exprfound to true if there is already an expression present for i in "${words[@]}"; do - [[ $i == [-\(\),\!]* ]] && exprfound=true && break + [[ $i == [-\(\),\!]* ]] && exprfound=set && break done # handle case where first parameter is not a dash option - if ! $exprfound && [[ $cur != [-\(\),\!]* ]]; then - _filedir -d + if [[ ! $exprfound && $cur != [-\(\),\!]* ]]; then + _comp_compgen_filedir -d return fi # complete using basic options - COMPREPLY=($(compgen -W '-daystart -depth -follow -help - -ignore_readdir_race -maxdepth -mindepth -mindepth -mount - -noignore_readdir_race -noleaf -regextype -version -warn -nowarn -xdev - -amin -anewer -atime -cmin -cnewer -ctime -empty -executable -false - -fstype -gid -group -ilname -iname -inum -ipath -iregex -iwholename - -links -lname -mmin -mtime -name -newer -nogroup -nouser -path -perm - -readable -regex -samefile -size -true -type -uid -used -user - -wholename -writable -xtype -context -delete -exec -execdir -fls - -fprint -fprint0 -fprintf -ls -ok -okdir -print -print0 -printf -prune - -quit' -- "$cur")) + _comp_compgen -- -W '-daystart -depth -follow -help -ignore_readdir_race + -maxdepth -mindepth -mindepth -mount -noignore_readdir_race -noleaf + -regextype -version -warn -nowarn -xdev -amin -anewer -atime -cmin + -cnewer -ctime -empty -executable -false -fstype -gid -group -ilname + -iname -inum -ipath -iregex -iwholename -links -lname -mmin -mtime + -name -newer -nogroup -nouser -path -perm -readable -regex -samefile + -size -true -type -uid -used -user -wholename -writable -xtype -context + -delete -exec -execdir -fls -fprint -fprint0 -fprintf -ls -ok -okdir + -print -print0 -printf -prune -quit' if ((${#COMPREPLY[@]} != 0)); then # this removes any options from the list of completions that have @@ -100,14 +99,14 @@ _find() for i in "${words[@]}"; do [[ $i && -v onlyonce["$i"] ]] || continue for j in "${!COMPREPLY[@]}"; do - [[ ${COMPREPLY[j]} == "$i" ]] && unset 'COMPREPLY[j]' + [[ ${COMPREPLY[j]} == "$i" ]] && unset -v 'COMPREPLY[j]' done done fi - _filedir + _comp_compgen -a filedir } && - complete -F _find find + complete -F _comp_cmd_find find # ex: filetype=sh diff --git a/completions/find_member b/completions/find_member index cf30c70..d2620e8 100644 --- a/completions/find_member +++ b/completions/find_member @@ -1,25 +1,27 @@ # mailman find_member completion -*- shell-script -*- -_find_member() +_comp_cmd_find_member() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -l | -x | --listname | --exclude) - _xfunc list_lists _mailman_lists + # Prefer `list_lists` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen -x list_lists mailman_lists return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--listname --exclude --owners --help' \ - -- "$cur")) + _comp_compgen -- -W '--listname --exclude --owners --help' fi } && - complete -F _find_member find_member + complete -F _comp_cmd_find_member find_member # ex: filetype=sh diff --git a/completions/fio b/completions/fio index f81a4da..7fbcdd4 100644 --- a/completions/fio +++ b/completions/fio @@ -1,90 +1,147 @@ # fio(1) completion -*- shell-script -*- -_fio() +_comp_cmd_fio__compgen_engines() { - local cur prev words cword split - _init_completion -s || return + _comp_compgen_split -l -- "$("$1" --enghelp 2>/dev/null | command sed -ne '/^[[:space:]]/p'))" +} +_comp_cmd_fio() +{ + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + + local REPLY case $prev in --help | --version) return ;; --debug) - local prefix= - [[ $cur == *,* ]] && prefix="${cur%,*}," - COMPREPLY=($(compgen -W "process file io mem blktrace verify - random parse diskutil job mutex profile time net rate compress - steadystate helperthread" -- "${cur##*,}")) - ((${#COMPREPLY[@]} == 1)) && COMPREPLY=(${COMPREPLY/#/$prefix}) + local opts=$("$1" --debug=help 2>/dev/null) + opts=${opts##*:} + _comp_delimited , -W "${opts//,/ }" return ;; --output-format) - COMPREPLY=($(compgen -W "terse json json+ normal" -- "$cur")) + _comp_compgen -- -W "terse json json+ normal" return ;; --terse-version) - COMPREPLY=($(compgen -W "2 3" -- "$cur")) + _comp_compgen -- -W "2 3 4 5" + return + ;; + --crctest) + _comp_compgen_split -- "$("$1" --crctest=nonexistent 2>/dev/null)" return ;; --cmdhelp) - # TODO more commands? - COMPREPLY=($(compgen -W "all" -- "$cur")) + _comp_compgen_split -- "$("$1" --cmdhelp=all 2>/dev/null | _comp_awk '{print $1}') all" return ;; --enghelp) - # TODO print ioengine help, or list available ioengines - # TODO engine,help arg + _comp_cmd_fio__compgen_engines "$1" return ;; --eta) - COMPREPLY=($(compgen -W "always never auto" -- "$cur")) + _comp_compgen -- -W "always never auto" return ;; --daemonize) - _filedir pid + _comp_compgen_filedir pid return ;; --client) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; --remote-config) - _filedir job + _comp_compgen_filedir '@(fio|job)' return ;; --idle-prof) - COMPREPLY=($(compgen -W "system percpu calibrate" -- "$cur")) + _comp_compgen -- -W "system percpu calibrate" return ;; --inflate-log) - _filedir log + _comp_compgen_filedir log return ;; --trigger-file) - _filedir + _comp_compgen_filedir return ;; --trigger | --trigger-remote) - compopt -o filenames - COMPREPLY=($(compgen -c -- "$cur")) + _comp_compgen_commands return ;; --aux-path) - _filedir -d + _comp_compgen_filedir -d return ;; + --ioengine) + _comp_cmd_fio__compgen_engines "$1" + return + ;; + --exec_postrun | --exec_prerun) + _comp_compgen_commands + return + ;; + --uid) + _comp_compgen_uids + return + ;; + --gid) + _comp_compgen_gids + return + ;; + --?*) + local -a cmdhelp + _comp_split -l cmdhelp "$("$1" --cmdhelp="${prev#--}" 2>/dev/null)" + case ${cmdhelp[*]-} in + *"showing closest match"*) + # ignore + ;; + *" type: boolean "* | *" type: empty or boolean "*) + _comp_compgen -- -W '0 1' + return + ;; + *" valid values:"*) + # For example, for --kb_base=: + # valid values: 1024 [...] + # : 1000 [...] + local line="" in_values="" + REPLY=() + for line in "${cmdhelp[@]}"; do + if [[ $in_values ]]; then + if [[ $line =~ ^[[:space:]]*:[[:space:]]*([^[:space:]]+) ]]; then + REPLY+=("${BASH_REMATCH[1]}") + else + break + fi + elif [[ $line =~ ^[[:space:]]*valid\ values:[[:space:]]*([^[:space:]]+) ]]; then + in_values=set + REPLY+=("${BASH_REMATCH[1]}") + fi + done + _comp_compgen -- -W '"${REPLY[@]}"' + return + ;; + esac + # else fallthrough + ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help + _comp_compgen -a split -- "$("$1" --cmdhelp=all 2>/dev/null | + _comp_awk '{printf "--%s=\n", $1}')" [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir job + _comp_compgen_filedir '@(fio|job)' } && - complete -F _fio fio + complete -F _comp_cmd_fio fio # ex: filetype=sh diff --git a/completions/firefox b/completions/firefox index 4656f8d..e84d644 100644 --- a/completions/firefox +++ b/completions/firefox @@ -1,46 +1,53 @@ # firefox completion -*- shell-script -*- -_firefox() +_comp_cmd_firefox() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return [[ $cur == -MOZ_LOG*=* ]] && prev=${cur%%=*} cur=${cur#*=} case $prev in --help | --version | --display | --UILocale | -MOZ_LOG | --new-window | --new-tab | \ --private-window | --window-size | --search | --start-debugger-server | \ - --recording | --debugger-args | -[hvPa]) + --recording | --debugger-args | -[hva]) + return + ;; + -P) + _comp_compgen_split -- "$( + _comp_awk -F = '$1 == "Name" { print $2 }' \ + ~/.mozilla/firefox/profiles.ini 2>/dev/null + )" return ;; --profile | --screenshot) - _filedir -d + _comp_compgen_filedir -d return ;; -MOZ_LOG_FILE) - _filedir log + _comp_compgen_filedir log return ;; - --recording-file) - _filedir + --recording-output | --recording-file) + _comp_compgen_filedir return ;; --debugger | -d) - COMPREPLY=($(compgen -c -- "$cur")) + _comp_compgen_commands return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir "@(?([xs])htm?(l)|pdf|txt)" + _comp_compgen_filedir "@(?([xs])htm?(l)|pdf|txt|svg)" } && - complete -F _firefox firefox mozilla-firefox iceweasel + complete -F _comp_cmd_firefox firefox firefox-esr iceweasel mozilla-firefox # ex: filetype=sh diff --git a/completions/flake8 b/completions/flake8 index 045c409..6889e86 100644 --- a/completions/flake8 +++ b/completions/flake8 @@ -1,42 +1,46 @@ # flake8 completion -*- shell-script -*- -_flake8() +_comp_cmd_flake8() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[j]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | -!(-*)h) + --help | --version | -${noargopts}h) return ;; --format) - COMPREPLY=($(compgen -W 'default pylint' -- "$cur")) + _comp_compgen -- -W 'default pylint' return ;; - --jobs | -!(-*)j) - COMPREPLY=($(compgen -W "auto {1..$(_ncpus)}" -- "$cur")) + --jobs | -${noargopts}j) + local REPLY + _comp_get_ncpus + _comp_compgen -- -W "auto {1..$REPLY}" return ;; --output-file | --append-config | --config) - _filedir + _comp_compgen_filedir return ;; --include-in-doctest | --exclude-from-doctest) - _filedir py + _comp_compgen_filedir py return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir py + _comp_compgen_filedir py } && - complete -F _flake8 flake8 + complete -F _comp_cmd_flake8 flake8 # ex: filetype=sh diff --git a/completions/freebsd-update b/completions/freebsd-update index d5be861..8ccc949 100644 --- a/completions/freebsd-update +++ b/completions/freebsd-update @@ -2,18 +2,18 @@ [[ $OSTYPE == *freebsd* ]] || return 1 -_freebsd_update() +_comp_cmd_freebsd_update() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -b | -d) - _filedir -d + _comp_compgen_filedir -d return ;; -f) - _filedir + _comp_compgen_filedir return ;; -k | -r | -s | -t) @@ -21,9 +21,8 @@ _freebsd_update() ;; esac - COMPREPLY=($(compgen -W "fetch cron upgrade install rollback IDS" -- \ - $cur)) + _comp_compgen -- -W 'fetch cron upgrade install rollback IDS' } && - complete -F _freebsd_update freebsd-update + complete -F _comp_cmd_freebsd_update freebsd-update # ex: filetype=sh diff --git a/completions/freeciv b/completions/freeciv index 01af311..2dedf37 100644 --- a/completions/freeciv +++ b/completions/freeciv @@ -1,41 +1,41 @@ # freeciv client completions -*- shell-script -*- -_freeciv() +_comp_cmd_freeciv() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --help | --version | --name | --port | -[hvnp]) return ;; --file | --log | --music | --read | --Sound | --tiles | -[flmrSt]) - _filedir + _comp_compgen_filedir return ;; --Announce | -A) - COMPREPLY=($(compgen -W 'IPv4 IPv6 none' -- "$cur")) + _comp_compgen -- -W 'IPv4 IPv6 none' return ;; --debug | -d) - COMPREPLY=($(compgen -W '{0..3}' -- "$cur")) + _comp_compgen -- -W '{0..3}' return ;; --Meta | --server | -[Ms]) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; --Plugin | -P) - COMPREPLY=($(compgen -W 'none esd sdl' -- "$cur")) + _comp_compgen -- -W 'none esd sdl' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help fi } && - complete -F _freeciv freeciv{,-{gtk{2,3},sdl,xaw}} civclient + complete -F _comp_cmd_freeciv freeciv{,-{gtk{2,3},sdl,xaw}} civclient # ex: filetype=sh diff --git a/completions/freeciv-server b/completions/freeciv-server index a34b5a2..fd91fa0 100644 --- a/completions/freeciv-server +++ b/completions/freeciv-server @@ -1,22 +1,22 @@ # freeciv-server completion -*- shell-script -*- -_civserver() +_comp_cmd_civserver() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -f | -g | -l | -r | --file | --log | --gamelog | --read) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help fi } && - complete -F _civserver civserver freeciv-server + complete -F _comp_cmd_civserver civserver freeciv-server # ex: filetype=sh diff --git a/completions/function b/completions/function index 6ae5271..218f0cf 100644 --- a/completions/function +++ b/completions/function @@ -1,37 +1,17 @@ # bash shell function completion -*- shell-script -*- -_function() +_comp_cmd_function() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - if [[ $1 == @(declare|typeset) ]]; then - if [[ $cur == [-+]* ]]; then - local opts - opts=($(_parse_usage "$1")) - # Most options also have a '+' form. We'll exclude the ones that don't with compgen. - opts+=(${opts[*]/-/+}) - COMPREPLY=($(compgen -W "${opts[*]}" -X '+[Ffgp]' -- "$cur")) - else - local i=1 - while [[ ${words[i]} == [-+]* ]]; do - if [[ ${words[i]} == -*[fF]* ]]; then - COMPREPLY=($(compgen -A function -- "$cur")) - return - fi - ((i++)) - done - if ((i > 1)); then - # There was at least one option and it was not one that limited operations to functions - COMPREPLY=($(compgen -A variable -- "$cur")) - fi - fi - elif ((cword == 1)); then - COMPREPLY=($(compgen -A function -- "$cur")) + if ((cword == 1)); then + _comp_compgen -- -A function else - COMPREPLY=("() $(type -- ${words[1]} | command sed -e 1,2d)") + local funcdef=$(type -- "${words[1]}" 2>/dev/null | command sed -e 1,2d) + COMPREPLY=("()${funcdef:+ $funcdef}") fi } && - complete -F _function function declare typeset + complete -F _comp_cmd_function function # ex: filetype=sh diff --git a/completions/fusermount b/completions/fusermount index 7e48922..4f85319 100644 --- a/completions/fusermount +++ b/completions/fusermount @@ -1,28 +1,27 @@ # fusermount completion -*- shell-script -*- -_fusermount() +_comp_cmd_fusermount() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*[hVo]) return ;; -*u) - COMPREPLY=($(compgen -W "$(awk \ - '{ if ($3 ~ /^fuse(\.|$)/) print $2 }' /etc/mtab \ - 2>/dev/null)" -- "$cur")) + _comp_compgen_split -- "$(_comp_awk \ + '{ if ($3 ~ /^fuse(\.|$)/) print $2 }' /etc/mtab 2>/dev/null)" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur")) + _comp_compgen_help -- -h else - _filedir -d + _comp_compgen_filedir -d fi } && - complete -F _fusermount fusermount + complete -F _comp_cmd_fusermount fusermount # ex: filetype=sh diff --git a/completions/gcc b/completions/gcc index fa95274..ed5bc9b 100644 --- a/completions/gcc +++ b/completions/gcc @@ -1,26 +1,26 @@ # gcc(1) completion -*- shell-script -*- -_gcc() +_comp_cmd_gcc() { - local cur prev prev2 words cword argument prefix prefix_length - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return # Test that GCC is recent enough and if not fallback to # parsing of --completion option. - if ! $1 --completion=" " 2>/dev/null; then + if ! "$1" --completion=" " 2>/dev/null; then if [[ $cur == -* ]]; then - local cc=$($1 -print-prog-name=cc1 2>/dev/null) + local cc=$("$1" -print-prog-name=cc1 2>/dev/null) [[ $cc ]] || return - COMPREPLY=($(compgen -W "$($cc --help 2>/dev/null | tr '\t' ' ' | - command sed -e '/^ *-/!d' -e 's/ *-\([^][ <>]*\).*/-\1/')" \ - -- "$cur")) + _comp_compgen_split -- "$("$cc" --help 2>/dev/null | tr '\t' ' ' | + command sed -e '/^ *-/!d' -e 's/ *-\([^][ <>]*\).*/-\1/')" [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - _filedir + _comp_compgen_filedir fi return fi + local prev2 argument="" prefix prefix_length # extract also for situations like: -fsanitize=add if ((cword > 2)); then prev2="${COMP_WORDS[cword - 2]}" @@ -44,32 +44,34 @@ _gcc() prefix="$prev " fi - if [[ ! -v argument ]]; then - _filedir + if [[ ! $argument ]]; then + _comp_compgen_filedir else # In situation like '-fsanitize=add' $cur is equal to last token. # Thus we need to strip the beginning of suggested option. prefix_length=$((${#prefix} + 1)) - local flags=$($1 --completion="$argument" | cut -c $prefix_length-) + local flags=$("$1" --completion="$argument" | cut -c $prefix_length-) [[ ${flags} == "=*" ]] && compopt -o nospace 2>/dev/null - COMPREPLY=($(compgen -W "$flags" -- "")) + _comp_compgen -R -- -W "$flags" fi } && - complete -F _gcc gcc{,-5,-6,-7,-8} g++{,-5,-6,-7,-8} g77 g95 \ + complete -F _comp_cmd_gcc gcc{,-5,-6,-7,-8} g++{,-5,-6,-7,-8} g77 g95 \ gccgo{,-5,-6,-7,-8} gcj gfortran{,-5,-6,-7,-8} gpc && + _comp_cmd_gcc__setup_cmd() { - cc --version 2>/dev/null | command grep -q GCC || - [[ $(_realcommand cc) == *gcc* ]] && - complete -F _gcc cc || complete -F _minimal cc - c++ --version 2>/dev/null | command grep -q GCC || - [[ $(_realcommand c++) == *g++* ]] && - complete -F _gcc c++ || complete -F _minimal c++ - f77 --version 2>/dev/null | command grep -q GCC || - [[ $(_realcommand f77) == *gfortran* ]] && - complete -F _gcc f77 || complete -F _minimal f77 - f95 --version 2>/dev/null | command grep -q GCC || - [[ $(_realcommand f95) == *gfortran* ]] && - complete -F _gcc f95 || complete -F _minimal f95 - } + local REPLY + _comp_realcommand "$1" + if [[ $REPLY == *$2* ]] || + "$1" --version 2>/dev/null | command grep -q GCC; then + complete -F _comp_cmd_gcc "$1" + else + complete -F _comp_complete_minimal "$1" + fi + } && + _comp_cmd_gcc__setup_cmd cc gcc && + _comp_cmd_gcc__setup_cmd c++ g++ && + _comp_cmd_gcc__setup_cmd f77 gfortran && + _comp_cmd_gcc__setup_cmd f95 gfortran && + unset -f _comp_cmd_gcc__setup_cmd # ex: filetype=sh diff --git a/completions/gcl b/completions/gcl index 73a18b2..7b98767 100644 --- a/completions/gcl +++ b/completions/gcl @@ -2,20 +2,20 @@ # bash programmable completion for various Common Lisp implementations by # Nikodemus Siivola <nikodemus@random-state.net> -_gcl() +_comp_cmd_gcl() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return # completing an option (may or may not be separated by a space) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-eval -load -f -batch -dir -libdir -compile - -o-file -c-file -h-file -data-file -system-p' -- "$cur")) + _comp_compgen -- -W '-eval -load -f -batch -dir -libdir -compile + -o-file -c-file -h-file -data-file -system-p' else - _filedir + _comp_compgen_filedir fi } && - complete -F _gcl -o default gcl + complete -F _comp_cmd_gcl -o default gcl # ex: filetype=sh diff --git a/completions/gdb b/completions/gdb index f78f8a5..e6a124f 100644 --- a/completions/gdb +++ b/completions/gdb @@ -1,47 +1,46 @@ # bash completion for gdb -*- shell-script -*- -_gdb() +_comp_cmd_gdb() { - local cur prev words cword i - _init_completion || return + local cur prev words cword comp_args i + _comp_initialize -- "$@" || return # gdb [options] --args executable-file [inferior-arguments ...] for ((i = 1; i < cword; i++)); do if [[ ${words[i]} == --args ]]; then - _command_offset $((i + 1)) + _comp_command_offset $((i + 1)) return $? fi done # gdb [options] [executable-file [core-file or process-id]] if ((cword == 1)); then - local IFS compopt -o filenames - if [[ $cur == */* ]]; then + if _comp_looks_like_path "$cur"; then # compgen -c works as expected if $cur contains any slashes. - IFS=$'\n' - COMPREPLY=($(PATH="$PATH:." compgen -d -c -- "$cur")) + local PATH="$PATH:." + _comp_compgen_commands else # otherwise compgen -c contains Bash's built-in commands, # functions and aliases. Thus we need to retrieve the program # names manually. - IFS=":" - local path_array=($( - command sed -e 's/:\{2,\}/:/g' -e 's/^://' -e 's/:$//' <<<"$PATH" - )) - IFS=$'\n' - COMPREPLY=($(compgen -d -W '$(find "${path_array[@]}" . \ - -mindepth 1 -maxdepth 1 -not -type d -executable \ - -printf "%f\\n" 2>/dev/null)' -- "$cur")) + local path_array + _comp_compgen -Rv path_array split -F : -X '' -S /. -- "$PATH" + _comp_compgen_split -o plusdirs -- "$( + # Note: ${v+"$@"} does not work with empty IFS in bash < 4.4 + IFS=$' \t\n' + find ${path_array[@]+"${path_array[@]}"} . -name . -o \ + -type d -prune -o -perm -u+x -print 2>/dev/null | + command sed 's|^.*/||' | sort -u + )" fi elif ((cword == 2)); then - COMPREPLY=($(compgen -W "$(command ps axo comm,pid | - awk '{if ($1 ~ /^'"${prev##*/}"'/) print $2}')" -- "$cur")) + _comp_compgen_split -- "$(command ps axo comm,pid | + _comp_awk '{if ($1 ~ /^'"${prev##*/}"'/) print $2}')" compopt -o filenames - COMPREPLY+=($(compgen -f -X '!?(*/)core?(.?*)' -o plusdirs \ - -- "$cur")) + _comp_compgen -a -- -f -X '!?(*/)core?(.?*)' -o plusdirs fi } && - complete -F _gdb gdb + complete -F _comp_cmd_gdb gdb # ex: filetype=sh diff --git a/completions/genaliases b/completions/genaliases index 5953b9e..0fec30d 100644 --- a/completions/genaliases +++ b/completions/genaliases @@ -1,15 +1,15 @@ # mailman genaliases completion -*- shell-script -*- -_genaliases() +_comp_cmd_genaliases() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--quiet --help' -- "$cur")) + _comp_compgen -- -W '--quiet --help' fi } && - complete -F _genaliases genaliases + complete -F _comp_cmd_genaliases genaliases # ex: filetype=sh diff --git a/completions/gendiff b/completions/gendiff index d37793f..9fea862 100644 --- a/completions/gendiff +++ b/completions/gendiff @@ -1,12 +1,12 @@ # gendiff(1) completion -*- shell-script -*- -_gendiff() +_comp_cmd_gendiff() { - local cur prev words cword - _init_completion -o '@(diff|patch)' || return + local cur prev words cword comp_args + _comp_initialize -o '@(diff|patch)' -- "$@" || return - ((cword == 1)) && _filedir -d + ((cword == 1)) && _comp_compgen_filedir -d } && - complete -F _gendiff gendiff + complete -F _comp_cmd_gendiff gendiff # ex: filetype=sh diff --git a/completions/genisoimage b/completions/genisoimage index dfa39c0..d54fdf6 100644 --- a/completions/genisoimage +++ b/completions/genisoimage @@ -1,38 +1,38 @@ # bash completion for mkisofs/genisoimage -*- shell-script -*- -_mkisofs() +_comp_cmd_mkisofs() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -o | -abstract | -biblio | -check-session | -copyright | -log-file | \ -root-info | -prep-boot | -*-list) - _filedir + _comp_compgen_filedir return ;; -*-charset) - COMPREPLY=($(compgen -W '$(mkisofs -input-charset \ - help 2>&1 | tail -n +3)' -- "$cur")) + _comp_compgen_split -- "$(mkisofs -input-charset help 2>&1 | + tail -n +3)" return ;; -uid) - _uids + _comp_compgen_uids return ;; -gid) - _gids + _comp_compgen_gids return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help else - _filedir + _comp_compgen_filedir fi } && - complete -F _mkisofs mkisofs genisoimage + complete -F _comp_cmd_mkisofs mkisofs genisoimage # ex: filetype=sh diff --git a/completions/geoiplookup b/completions/geoiplookup index c60be89..504c22a 100644 --- a/completions/geoiplookup +++ b/completions/geoiplookup @@ -1,33 +1,33 @@ # geoiplookup(1) completion -*- shell-script -*- -_geoiplookup() +_comp_cmd_geoiplookup() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -h | -'?' | -v) return ;; -d) - _filedir -d + _comp_compgen_filedir -d return ;; -f) - _filedir dat + _comp_compgen_filedir dat return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" -h)' -- "$cur")) + _comp_compgen_usage -- -h return fi local ipvx [[ $1 == *6 ]] && ipvx=-6 || ipvx=-4 - _known_hosts_real $ipvx -- "$cur" + _comp_compgen_known_hosts $ipvx -- "$cur" } && - complete -F _geoiplookup geoiplookup geoiplookup6 + complete -F _comp_cmd_geoiplookup geoiplookup geoiplookup6 # ex: filetype=sh diff --git a/completions/getconf b/completions/getconf index de1ad2d..230b0f4 100644 --- a/completions/getconf +++ b/completions/getconf @@ -1,32 +1,33 @@ # getconf(1) completion -*- shell-script -*- -_getconf() +_comp_cmd_getconf() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -a) - _filedir + _comp_compgen_filedir return ;; -v) - COMPREPLY=($(compgen -W \ - '$("$1" -a 2>/dev/null | awk "{ print \$1 }")' -- \ - "${cur:-POSIX_V}")) + _comp_compgen -c "${cur:-POSIX_V}" split -- "$( + "$1" -a 2>/dev/null | _comp_awk '{ print $1 }' + )" return ;; esac if [[ $prev == PATH_MAX ]]; then # TODO more path vars, better handling - _filedir + _comp_compgen_filedir elif [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-a -v' -- "$cur")) + _comp_compgen -- -W '-a -v' else - COMPREPLY=($(compgen -W \ - '$("$1" -a 2>/dev/null | awk "{ print \$1 }")' -- "$cur")) + _comp_compgen_split -- "$( + "$1" -a 2>/dev/null | _comp_awk '{ print $1 }' + )" fi } && - complete -F _getconf getconf + complete -F _comp_cmd_getconf getconf # ex: filetype=sh diff --git a/completions/getent b/completions/getent index 4c54a24..4310434 100644 --- a/completions/getent +++ b/completions/getent @@ -1,17 +1,19 @@ # bash completion for getent -*- shell-script -*- -_getent() +_comp_cmd_getent() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return - local i db + local noargopts='!(-*|*[s]*)' + local i db="" has_db="" for ((i = 1; i < cword; i++)); do + # shellcheck disable=SC2254 case ${words[i]} in - --version | --usage | --help | -!(-*)[V?]) + --version | --usage | --help | -${noargopts}[V?]) return ;; - --service | -!(-*)s) + --service | -${noargopts}s) ((i++)) ;; -*) ;; @@ -19,35 +21,35 @@ _getent() *) # First non-option value is the db db=${words[i]} + has_db=set break ;; esac done - case ${db-} in + case $db in passwd) - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u return ;; group) - COMPREPLY=($(compgen -g -- "$cur")) + _comp_compgen -- -g return ;; services) - COMPREPLY=($(compgen -s -- "$cur")) + _comp_compgen -- -s return ;; hosts) - COMPREPLY=($(compgen -A hostname -- "$cur")) + _comp_compgen -- -A hostname return ;; protocols | networks | ahosts | ahostsv4 | ahostsv6 | rpc) - COMPREPLY=($(compgen -W "$($1 $db | - awk '{ print $1 }')" -- "$cur")) + _comp_compgen_split -- "$("$1" "$db" | _comp_awk '{ print $1 }')" return ;; aliases | shadow | gshadow) - COMPREPLY=($(compgen -W "$($1 $db | cut -d: -f1)" -- "$cur")) + _comp_compgen_split -- "$("$1" "$db" | cut -d: -f1)" return ;; ethers | netgroup) @@ -55,23 +57,24 @@ _getent() ;; esac + # shellcheck disable=SC2254 case $prev in - -s | --service) + -${noargopts}s | --service) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace - elif [[ ! -v db ]]; then - COMPREPLY=($(compgen -W 'passwd group hosts services protocols - networks ahosts ahostsv4 ahostsv6 aliases ethers netgroup rpc - shadow gshadow' -- "$cur")) + elif [[ ! $has_db ]]; then + _comp_compgen -- -W 'passwd group hosts services protocols networks + ahosts ahostsv4 ahostsv6 aliases ethers netgroup rpc shadow + gshadow' fi } && - complete -F _getent getent + complete -F _comp_cmd_getent getent # ex: filetype=sh diff --git a/completions/gkrellm b/completions/gkrellm index c38c5ae..81781fb 100644 --- a/completions/gkrellm +++ b/completions/gkrellm @@ -1,25 +1,25 @@ # gkrellm(1) completion -*- shell-script -*- -_gkrellm() +_comp_cmd_gkrellm() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -t | --theme) - _filedir -d + _comp_compgen_filedir -d return ;; -p | --plugin) - _filedir so + _comp_compgen_filedir so return ;; -s | --server) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -l | --logfile) - _filedir + _comp_compgen_filedir return ;; -g | --geometry | -c | --config | -P | --port | -d | --debug-level) @@ -32,8 +32,8 @@ _gkrellm() ;; esac - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help } && - complete -F _gkrellm gkrellm gkrellm2 + complete -F _comp_cmd_gkrellm gkrellm gkrellm2 # ex: filetype=sh diff --git a/completions/gm b/completions/gm index b86c9cc..7dbaceb 100644 --- a/completions/gm +++ b/completions/gm @@ -1,21 +1,21 @@ # bash completion for gm(1) -*- shell-script -*- -_gm_commands() +_comp_cmd_gm__commands() { - COMPREPLY+=($(compgen -W '$("$1" help | - awk "/^ +[^ ]+ +- / { print \$1 }")' -- "$cur")) + _comp_compgen -a split -- "$("$1" help | + _comp_awk '/^ +[^ ]+ +- / { print $1 }')" } -_gm() +_comp_cmd_gm() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if ((cword == 1)); then - _gm_commands "$1" + _comp_cmd_gm__commands "$1" return elif [[ $cword -eq 2 && ${words[1]} == time ]]; then - _gm_commands "$1" + _comp_cmd_gm__commands "$1" return fi @@ -24,7 +24,7 @@ _gm() case $gmcmd in help) - [[ $prev == help ]] && _gm_commands "$1" + [[ $prev == help ]] && _comp_cmd_gm__commands "$1" return ;; version) @@ -32,9 +32,9 @@ _gm() ;; esac - # TODO... defer some commnds to the imagemagick "gm"less completions etc? + # TODO... defer some commands to the imagemagick "gm"less completions etc? compopt -o default } && - complete -F _gm gm + complete -F _comp_cmd_gm gm # ex: filetype=sh diff --git a/completions/gnatmake b/completions/gnatmake index 5f4b963..bbeccef 100644 --- a/completions/gnatmake +++ b/completions/gnatmake @@ -1,26 +1,26 @@ # Gnatmake completion -*- shell-script -*- # by Ralf_Schroth@t-online.de (Ralf Schroth) -_gnatmake() +_comp_cmd_gnatmake() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then # relevant (and less relevant ;-) )options completion - COMPREPLY=($(compgen -W '-a -c -f -i -j -k -m -M -n -o -q -s -v -z - -aL -A -aO -aI -I -I- -L -nostdinc -nostdlib -cargs -bargs -largs + _comp_compgen -- -W '-a -c -f -i -j -k -m -M -n -o -q -s -v -z -aL -A + -aO -aI -I -I- -L -nostdinc -nostdlib -cargs -bargs -largs -fstack-check -fno-inline -g -O1 -O0 -O2 -O3 -gnata -gnatA -gnatb -gnatc -gnatd -gnatD -gnate -gnatE -gnatf -gnatF -gnatg -gnatG -gnath -gnati -gnatk -gnatl -gnatL -gnatm -gnatn -gnato -gnatO -gnatp -gnatP -gnatq -gnatR -gnats -gnatt -gnatT -gnatu -gnatU -gnatv -gnatws -gnatwe -gnatwl -gnatwu -gnatW -gnatx -gnatX -gnaty - -gnatz -gnatZ -gnat83' -- "$cur")) + -gnatz -gnatZ -gnat83' else # source file completion - _filedir '@(adb|ads)' + _comp_compgen_filedir '@(adb|ads)' fi } && - complete -F _gnatmake gnatmake + complete -F _comp_cmd_gnatmake gnatmake # ex: filetype=sh diff --git a/completions/gnokii b/completions/gnokii index 039141a..21fb13c 100644 --- a/completions/gnokii +++ b/completions/gnokii @@ -1,19 +1,19 @@ # gnokii(1) completion -*- shell-script -*- -_gnokii_memory_type() +_comp_cmd_gnokii__memory_type() { # TODO: reduce the number of choices - COMPREPLY=($(compgen -W "IN OU SM ME MT" -- "$cur")) + _comp_compgen -- -W "IN OU SM ME MT" } -_gnokii() +_comp_cmd_gnokii() { - local cur prev words cword pprev tprev fprev - _init_completion || return + local cur prev words cword comp_args pprev tprev fprev + _comp_initialize -- "$@" || return case $prev in --config) - _filedir + _comp_compgen_filedir return ;; --phone) @@ -24,15 +24,13 @@ _gnokii() [[ -f $config_file ]] && break done [[ ! -f $config_file ]] && return - COMPREPLY=($(compgen -W \ - "$(command sed -n 's/^\[phone_\(.*\)\]/\1/p' $config_file)" \ - -- "$cur")) + _comp_compgen_split -- "$(command sed -n \ + 's/^\[phone_\(.*\)\]/\1/p' "$config_file")" return ;; --help) - COMPREPLY=($(compgen -W 'all monitor sms mms phonebook calendar - todo dial profile settings wap logo ringtone security file - other' -- "$cur")) + _comp_compgen -- -W 'all monitor sms mms phonebook calendar todo + dial profile settings wap logo ringtone security file other' return ;; --version | --shell | ping) @@ -41,15 +39,14 @@ _gnokii() # MONITOR --monitor) - COMPREPLY=($(compgen -W 'delay once' -- "$cur")) + _comp_compgen -- -W 'delay once' return ;; --getdisplaystatus | --displayoutput) return ;; --netmonitor) - COMPREPLY=($(compgen -W 'reset off field devel next nr' \ - -- "$cur")) + _comp_compgen -- -W 'reset off field devel next nr' return ;; @@ -59,13 +56,13 @@ _gnokii() return ;; --savesms) - COMPREPLY=($(compgen -W '--sender --smsc --smscno --folder - --location --sent --read --deliver --datetime' -- "$cur")) + _comp_compgen -- -W '--sender --smsc --smscno --folder --location + --sent --read --deliver --datetime' return ;; --memory-type | --memory | --getsms | --deletesms | --getmms | --deletemms | \ --getphonebook | --deletephonebook) - _gnokii_memory_type + _comp_cmd_gnokii__memory_type return ;; --getsmsc | --getcalendarnote | --deletecalendarnote | --gettodo | \ @@ -82,12 +79,12 @@ _gnokii() return ;; --writephonebook) - COMPREPLY=($(compgen -W '--overwrite --find-free --memory-type - --location --vcard --ldif' -- "$cur")) + _comp_compgen -- -W '--overwrite --find-free --memory-type + --location --vcard --ldif' return ;; --writecalendarnote | --writetodo) - _filedir vcf + _comp_compgen_filedir vcf return ;; @@ -97,7 +94,7 @@ _gnokii() return ;; --divert) - COMPREPLY=($(compgen -W '--op' -- "$cur")) + _comp_compgen -- -W '--op' return ;; @@ -112,7 +109,7 @@ _gnokii() # SETTINGS --reset) - COMPREPLY=($(compgen -W 'soft hard' -- "$cur")) + _comp_compgen -- -W 'soft hard' return ;; --setdatetime | --setalarm) @@ -131,12 +128,11 @@ _gnokii() # LOGOS --sendlogo) - COMPREPLY=($(compgen -W 'caller op picture' -- "$cur")) + _comp_compgen -- -W 'caller op picture' return ;; --setlogo | --getlogo) - COMPREPLY=($(compgen -W 'op startup caller dealer text' \ - -- "$cur")) + _comp_compgen -- -W 'op startup caller dealer text' return ;; --viewlogo) @@ -145,7 +141,7 @@ _gnokii() ;; --entersecuritycode) - COMPREPLY=($(compgen -W 'PIN PIN2 PUK PUK2 SEC' -- "$cur")) + _comp_compgen -- -W 'PIN PIN2 PUK PUK2 SEC' return ;; @@ -157,7 +153,7 @@ _gnokii() pprev=${words[cword - 2]} case $pprev in --setspeeddial) - _gnokii_memory_type + _comp_cmd_gnokii__memory_type return ;; --getsms | --deletesms | --getmms | --deletemms | --getphonebook | \ @@ -166,16 +162,15 @@ _gnokii() return ;; --gettodo | --getcalendarnote) - COMPREPLY=($(compgen -W '{1..9} end --vCal' -- "$cur")) + _comp_compgen -- -W '{1..9} end --vCal' return ;; --deletecalendarnote) - COMPREPLY=($(compgen -W '{1..9} end' -- "$cur")) + _comp_compgen -- -W '{1..9} end' return ;; --divert) - COMPREPLY=($(compgen -W 'register enable query disable - erasure' -- "$cur")) + _comp_compgen -- -W 'register enable query disable erasure' return ;; esac @@ -186,20 +181,20 @@ _gnokii() tprev=${words[cword - 3]} case $tprev in --deletesms | --deletemms) - COMPREPLY=($(compgen -W 'end' -- "$cur")) + _comp_compgen -- -W 'end' return ;; --getphonebook | --writetodo | --writecalendarnote) - COMPREPLY=($(compgen -W '{1..9} end' -- "$cur")) + _comp_compgen -- -W '{1..9} end' return ;; --gettodo | --getcalendarnote) [[ ${words[cword - 1]} == end ]] && - COMPREPLY=($(compgen -W '--vCal' -- "$cur")) + _comp_compgen -- -W '--vCal' return ;; --divert) - COMPREPLY=($(compgen -W '--type' -- "$cur")) + _comp_compgen -- -W '--type' return ;; esac @@ -210,28 +205,32 @@ _gnokii() fprev=${words[cword - 4]} case $fprev in --getphonebook) - COMPREPLY=($(compgen -W '--raw --vcard --ldif' -- "$cur")) + _comp_compgen -- -W '--raw --vcard --ldif' return ;; --divert) - COMPREPLY=($(compgen -W 'all busy noans outofreach notavail' \ - -- "$cur")) + _comp_compgen -- -W 'all busy noans outofreach notavail' return ;; esac fi - # safer to use LANG=C - local all_cmd="$(LANG=C _parse_help $1 "--help all")" - # these 2 below are allowed in combination with others - local main_cmd=$(command grep -v -- '--config\|--phone' <<<"$all_cmd") + local all_cmd + _comp_compgen -Rv all_cmd help -- --help all + # these 2 below are allowed in combination with others + local main_cmd + _comp_split -l main_cmd "$(printf '%s\n' "${all_cmd[@]}" | + command sed -e '/--config/d;/--phone/d;s/[][\(){}|^$*+?.]/\\&/g')" # don't provide main command completions if one is # already on the command line - [[ $COMP_LINE =~ $(tr ' ' '\b|' <<<$main_cmd) ]] && return + local IFS='|' + local regex_main_cmd="(${main_cmd[*]})($|[^_[:alnum:]])" + IFS=$' \t\n' + [[ $COMP_LINE =~ $regex_main_cmd ]] && return - COMPREPLY=($(compgen -W "$all_cmd" -- "$cur")) + _comp_compgen -- -W '"${all_cmd[@]}"' } && - complete -F _gnokii gnokii + complete -F _comp_cmd_gnokii gnokii # ex: filetype=sh diff --git a/completions/gnome-mplayer b/completions/gnome-mplayer index 32d93fc..86686fc 100644 --- a/completions/gnome-mplayer +++ b/completions/gnome-mplayer @@ -1,38 +1,38 @@ # gnome-mplayer(1) completion -*- shell-script -*- -_gnome_mplayer() +_comp_cmd_gnome_mplayer() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -'?' | --help | --help-all | --help-gtk) return ;; --showcontrols | --showsubtitles | --autostart) - COMPREPLY=($(compgen -w '0 1' -- "$cur")) + _comp_compgen -- -W '0 1' return ;; --subtitle) - _filedir '@(srt|sub|txt|utf|rar|mpsub|smi|js|ssa|ass)' + _comp_compgen_filedir '@(srt|sub|txt|utf|rar|mpsub|smi|js|ssa|ass)' return ;; --tvdriver) - COMPREPLY=($(compgen -W 'v4l v4l2' -- "$cur")) + _comp_compgen -- -W 'v4l v4l2' return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" --help-all)' -- "$cur")) + _comp_compgen_help -- --help-all [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir + _comp_compgen_filedir } && - complete -F _gnome_mplayer gnome-mplayer + complete -F _comp_cmd_gnome_mplayer gnome-mplayer # ex: filetype=sh diff --git a/completions/gnome-screenshot b/completions/gnome-screenshot index b3594d2..a884fa4 100644 --- a/completions/gnome-screenshot +++ b/completions/gnome-screenshot @@ -1,31 +1,33 @@ # gnome-screenshot(1) completion -*- shell-script -*- -_gnome_screenshot() +_comp_cmd_gnome_screenshot() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[def]*)' + # shellcheck disable=SC2254 case $prev in - --help | --help-* | --version | --delay | --display | -!(-*)[hd]) + --help | --help-* | --version | --delay | --display | -${noargopts}[hd]) return ;; - --border-effect | -!(-*)e) - COMPREPLY=($(compgen -W 'shadow border vintage none' -- "$cur")) + --border-effect | -${noargopts}e) + _comp_compgen -- -W 'shadow border vintage none' return ;; - --file | -!(-*)f) - _filedir '@(jp?(e)|pn)g' + --file | -${noargopts}f) + _comp_compgen_filedir '@(jp?(e)|pn)g' return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _gnome_screenshot gnome-screenshot + complete -F _comp_cmd_gnome_screenshot gnome-screenshot # ex: filetype=sh diff --git a/completions/gpasswd b/completions/gpasswd index f1f2200..db33c29 100644 --- a/completions/gpasswd +++ b/completions/gpasswd @@ -1,25 +1,27 @@ # gpasswd(1) completion -*- shell-script -*- -_gpasswd() +_comp_cmd_gpasswd() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[adAM]*)' + # shellcheck disable=SC2254 case $prev in - --add | --delete | --administrators | --members | -!(-*)[adAM]) - COMPREPLY=($(compgen -u -- "$cur")) + --add | --delete | --administrators | --members | -${noargopts}[adAM]) + _comp_compgen -- -u return ;; esac if [[ $cur == -* ]]; then # TODO: only -A and -M can be combined - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - COMPREPLY=($(compgen -g -- "$cur")) + _comp_compgen -- -g } && - complete -F _gpasswd gpasswd + complete -F _comp_cmd_gpasswd gpasswd # ex: filetype=sh diff --git a/completions/gpg b/completions/gpg index f0ca884..ca0d8e0 100644 --- a/completions/gpg +++ b/completions/gpg @@ -1,38 +1,53 @@ # bash completion for gpg -*- shell-script -*- -_gpg() +_comp_cmd_gpg() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[skKr]*)' + # shellcheck disable=SC2254 case $prev in - --sign | --clearsign | --decrypt-files | --load-extension | -!(-*)s) - _filedir + --sign | --clear-sign | --clearsign | --decrypt-files | \ + --load-extension | -${noargopts}s) + _comp_compgen_filedir return ;; - --export | --sign-key | --lsign-key | --nrsign-key | --nrlsign-key | --edit-key) + --list-keys | --list-public-keys | --locate-keys | \ + --locate-external-keys | --fingerprint | --delete-keys | \ + --delete-secret-and-public-keys | --export | --refresh-keys | \ + --search-keys | --edit-key | --sign-key | --lsign-key | \ + --nrsign-key | --nrlsign-key | --try-secret-key | -${noargopts}k) # return list of public keys - COMPREPLY=($(compgen -W "$($1 --list-keys 2>/dev/null | command sed -ne \ - 's@^pub.*/\([^ ]*\).*$@\1@p' -ne \ - 's@^.*\(<\([^>]*\)>\).*$@\2@p')" -- "$cur")) + _comp_compgen_split -- "$("$1" --list-keys 2>/dev/null | + command sed -ne \ + 's@^pub.*/\([^ ]*\).*$@\1@p' -ne \ + 's@^.*\(<\([^>]*\)>\).*$@\2@p')" return ;; - --recipient | -!(-*)r) - COMPREPLY=($(compgen -W "$($1 --list-keys 2>/dev/null | command sed -ne \ - 's@^.*<\([^>]*\)>.*$@\1@p')" -- "$cur")) + --list-secret-keys | --delete-secret-keys | --export-secret-keys | \ + --export-secret-subkeys | -${noargopts}K) + # return list of secret keys + _comp_compgen_split -- "$("$1" --list-secret-keys 2>/dev/null | + command sed -ne 's@^.*<\([^>]*\)>.*$@\1@p')" + return + ;; + --recipient | -${noargopts}r) + _comp_compgen_split -- "$("$1" --list-keys 2>/dev/null | + command sed -ne 's@^.*<\([^>]*\)>.*$@\1@p')" if [[ -e ~/.gnupg/gpg.conf ]]; then - COMPREPLY+=($(compgen -W "$(command sed -ne \ + _comp_compgen -a split -- "$(command sed -ne \ 's@^[ \t]*group[ \t][ \t]*\([^=]*\).*$@\1@p' \ - ~/.gnupg/gpg.conf)" -- "$cur")) + ~/.gnupg/gpg.conf)" fi return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$($1 --dump-options)' -- "$cur")) + _comp_compgen_split -- "$("$1" --dump-options)" fi } && - complete -F _gpg -o default gpg + complete -F _comp_cmd_gpg -o default gpg # ex: filetype=sh diff --git a/completions/gpg2 b/completions/gpg2 index cfa4023..fc54ff9 100644 --- a/completions/gpg2 +++ b/completions/gpg2 @@ -1,42 +1,47 @@ # gpg2(1) completion -*- shell-script -*- -_gpg2() +_comp_cmd_gpg2() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[sr]*)' + # shellcheck disable=SC2254 case $prev in --homedir) - _filedir -d + _comp_compgen_filedir -d return ;; - --sign | --clearsign | --options | --decrypt | -!(-*)s) - _filedir + --sign | --clearsign | --options | --decrypt | -${noargopts}s) + _comp_compgen_filedir return ;; - --export | --sign-key | --lsign-key | --nrsign-key | --nrlsign-key | --edit-key) + --export | --sign-key | --lsign-key | --nrsign-key | --nrlsign-key | \ + --edit-key | --delete-keys | --delete-secret-and-public-keys | \ + --locate-keys | --refresh-keys) # return list of public keys - COMPREPLY=($(compgen -W "$($1 --list-keys 2>/dev/null | command sed -ne \ - 's@^pub.*/\([^ ]*\).*$@\1@p' -ne \ - 's@^.*\(<\([^>]*\)>\).*$@\2@p')" -- "$cur")) + _comp_compgen_split -- "$("$1" --list-keys 2>/dev/null | + command sed -ne \ + 's@^pub.*/\([^ ]*\).*$@\1@p' -ne \ + 's@^.*\(<\([^>]*\)>\).*$@\2@p')" return ;; - --recipient | -!(-*)r) - COMPREPLY=($(compgen -W "$($1 --list-keys 2>/dev/null | - command sed -ne 's@^.*<\([^>]*\)>.*$@\1@p')" -- "$cur")) + --recipient | -${noargopts}r) + _comp_compgen_split -- "$("$1" --list-keys 2>/dev/null | + command sed -ne 's@^.*<\([^>]*\)>.*$@\1@p')" if [[ -e ~/.gnupg/gpg.conf ]]; then - COMPREPLY+=($(compgen -W "$(command sed -ne \ + _comp_compgen -a split -- "$(command sed -ne \ 's@^[ \t]*group[ \t][ \t]*\([^=]*\).*$@\1@p' \ - ~/.gnupg/gpg.conf)" -- "$cur")) + ~/.gnupg/gpg.conf)" fi return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$($1 --dump-options)' -- "$cur")) + _comp_compgen_split -- "$("$1" --dump-options)" fi } && - complete -F _gpg2 -o default gpg2 + complete -F _comp_cmd_gpg2 -o default gpg2 # ex: filetype=sh diff --git a/completions/gpgv b/completions/gpgv index 29315c9..7609a33 100644 --- a/completions/gpgv +++ b/completions/gpgv @@ -1,29 +1,30 @@ # gpgv(1) completion -*- shell-script -*- -_gpgv() +_comp_cmd_gpgv() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --help | --version | --weak-digest | --*-fd | -!(-*)[?h]*) return ;; --keyring) - _filedir "@(gpg|kbx)" + _comp_compgen_filedir "@(gpg|kbx)" return ;; --homedir) - _filedir -d + _comp_compgen_filedir -d return ;; esac - local args - _count_args "" "--@(weak-digest|*-fd|keyring|homedir)" + local REPLY + _comp_count_args -a "--@(weak-digest|*-fd|keyring|homedir)" + local args=$REPLY if [[ $cur == -* && $args -eq 1 ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi @@ -31,16 +32,16 @@ _gpgv() if [[ ${COMP_LINE,,} == *.@(asc|sig|sign)\ * ]]; then # Detached signature, only complete one arbitrary file arg and - if ((args == 2)); then - COMPREPLY=($(compgen -W '-' -- "$cur")) - _filedir + _comp_compgen -- -W '-' + _comp_compgen -a filedir fi else - _filedir gpg + _comp_compgen_filedir gpg fi else - _filedir "@(asc|gpg|sig|sign)" + _comp_compgen_filedir "@(asc|gpg|sig|sign)" fi } && - complete -F _gpgv gpgv gpgv2 + complete -F _comp_cmd_gpgv gpgv gpgv2 # ex: filetype=sh diff --git a/completions/gphoto2 b/completions/gphoto2 index cbf84c0..454ef61 100644 --- a/completions/gphoto2 +++ b/completions/gphoto2 @@ -1,55 +1,52 @@ # bash completion for gphoto2(1) -*- shell-script -*- -_gphoto2() +_comp_cmd_gphoto2() { - local cur prev words cword split - _init_completion -s -n : || return + local cur prev words cword was_split comp_args + _comp_initialize -s -n : -- "$@" || return case $prev in --debug-logfile) - _filedir + _comp_compgen_filedir return ;; --hook-script) - _filedir + _comp_compgen_filedir return ;; --filename) - _filedir + _comp_compgen_filedir return ;; -u | --upload-file) - _filedir + _comp_compgen_filedir return ;; --port) - COMPREPLY=($(compgen -W "$($1 --list-ports 2>/dev/null | - awk 'NR>3 { print $1 }')" -- "$cur")) - __ltrim_colon_completions "$cur" + _comp_compgen_split -- "$("$1" --list-ports 2>/dev/null | + _comp_awk 'NR>3 { print $1 }')" + _comp_ltrim_colon_completions "$cur" return ;; --camera) - local IFS=$'\n' - COMPREPLY=($(compgen -W "$($1 --list-cameras 2>/dev/null | - awk -F'"' 'NR>2 { print $2 }')" -- "$cur")) + _comp_compgen_split -l -- "$("$1" --list-cameras 2>/dev/null | + _comp_awk -F '"' 'NR>2 { print $2 }')" return ;; --get-config | --set-config | --set-config-index | --set-config-value) - COMPREPLY=($(compgen -W "$( - $1 --list-config 2>/dev/null - )" -- "$cur")) + _comp_compgen_split -- "$("$1" --list-config 2>/dev/null)" return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _gphoto2 gphoto2 + complete -F _comp_cmd_gphoto2 gphoto2 # ex: filetype=sh diff --git a/completions/gprof b/completions/gprof index 5a4ab2d..cb18633 100644 --- a/completions/gprof +++ b/completions/gprof @@ -1,56 +1,54 @@ # gprof(1) completion -*- shell-script -*- -_gprof() +_comp_cmd_gprof() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $cur in -A* | -C* | -J* | -p* | -P* | -q* | -Q* | -n* | -N* | -d*) return ;; -S*) - cur=${cur:2} - _filedir - COMPREPLY=("${COMPREPLY[@]/#/-S}") + _comp_compgen -c "${cur:2}" filedir + ((${#COMPREPLY[@]})) && COMPREPLY=("${COMPREPLY[@]/#/-S}") return ;; -O*) - cur=${cur:2} - COMPREPLY=($(compgen -P -O -W 'auto bsd 4.4bsd magic prof' \ - -- "$cur")) + _comp_compgen -c "${cur:2}" -- -P -O -W 'auto bsd 4.4bsd magic + prof' return ;; esac case $prev in -I | --directory-path) - _filedir -d + _comp_compgen_filedir -d return ;; -R | --file-ordering | --external-symbol-table) - _filedir + _comp_compgen_filedir return ;; -w | --width | -k | -m | --min-count | -h | --help | -e | -E | -f | -F) return ;; --file-format) - COMPREPLY=($(compgen -W 'auto bsd 4.4bsd magic prof' -- "$cur")) + _comp_compgen -- -W 'auto bsd 4.4bsd magic prof' return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir + _comp_compgen_filedir } && - complete -F _gprof gprof + complete -F _comp_cmd_gprof gprof # ex: filetype=sh diff --git a/completions/groupadd b/completions/groupadd index 5f67f29..fe4e600 100644 --- a/completions/groupadd +++ b/completions/groupadd @@ -1,26 +1,28 @@ # groupadd(8) completion -*- shell-script -*- -_groupadd() +_comp_cmd_groupadd() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return # TODO: if -o/--non-unique is given, could complete on existing gids # with -g/--gid + local noargopts='!(-*|*[gKp]*)' + # shellcheck disable=SC2254 case $prev in - --gid | --key | --password | -!(-*)[gKp]) + --gid | --key | --password | -${noargopts}[gKp]) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _groupadd groupadd + complete -F _comp_cmd_groupadd groupadd # ex: filetype=sh diff --git a/completions/groupdel b/completions/groupdel index 4d8ca7f..ab9fb29 100644 --- a/completions/groupdel +++ b/completions/groupdel @@ -1,27 +1,27 @@ # groupdel(8) completion -*- shell-script -*- -_groupdel() +_comp_cmd_groupdel() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -h | --help) return ;; -R | --root) - _filedir -d + _comp_compgen_filedir -d return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - COMPREPLY=($(compgen -g -- "$cur")) + _comp_compgen -- -g } && - complete -F _groupdel groupdel + complete -F _comp_cmd_groupdel groupdel # ex: filetype=sh diff --git a/completions/groupmems b/completions/groupmems index 2e89a5a..c884be2 100644 --- a/completions/groupmems +++ b/completions/groupmems @@ -1,27 +1,27 @@ # groupmems(8) completion -*- shell-script -*- -_groupmems() +_comp_cmd_groupmems() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -a | --add | -d | --delete) - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u return ;; -g | --group) - COMPREPLY=($(compgen -g -- "$cur")) + _comp_compgen -- -g return ;; -R | --root) - _filedir -d + _comp_compgen_filedir -d return ;; esac - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help } && - complete -F _groupmems groupmems + complete -F _comp_cmd_groupmems groupmems # ex: filetype=sh diff --git a/completions/groupmod b/completions/groupmod index 5516d31..3e8a352 100644 --- a/completions/groupmod +++ b/completions/groupmod @@ -1,29 +1,31 @@ # groupmod(8) completion -*- shell-script -*- -_groupmod() +_comp_cmd_groupmod() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return # TODO: if -o/--non-unique is given, could complete on existing gids # with -g/--gid + local noargopts='!(-*|*[gnp]*)' + # shellcheck disable=SC2254 case $prev in - --gid | --help | --new-name | --password | -!(-*)[ghnp]) + --gid | --help | --new-name | --password | -${noargopts}[ghnp]) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - COMPREPLY=($(compgen -g -- "$cur")) + _comp_compgen -- -g } && - complete -F _groupmod groupmod + complete -F _comp_cmd_groupmod groupmod # ex: filetype=sh diff --git a/completions/growisofs b/completions/growisofs index ee09fe6..1ea27c2 100644 --- a/completions/growisofs +++ b/completions/growisofs @@ -1,9 +1,9 @@ # growisofs(1) completion -*- shell-script -*- -_growisofs() +_comp_cmd_growisofs() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -version | -speed) @@ -11,14 +11,13 @@ _growisofs() ;; -Z | -M) compopt -o nospace - _dvd_devices + _comp_compgen_dvd_devices return ;; /?(r)dev/*) if [[ $cur == =* ]]; then # e.g. /dev/dvd=foo.iso, /dev/dvdrw=/dev/zero - cur="${cur#=}" - _filedir + _comp_compgen -c "${cur#=}" filedir return fi ;; @@ -26,14 +25,13 @@ _growisofs() if [[ $cur == -* ]]; then # TODO: mkisofs options - COMPREPLY=($(compgen -W '-dvd-compat -overburn -speed= -Z -M' \ - -- "$cur")) + _comp_compgen -- -W '-dvd-compat -overburn -speed= -Z -M' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir + _comp_compgen_filedir } && - complete -F _growisofs growisofs + complete -F _comp_cmd_growisofs growisofs # ex: filetype=sh diff --git a/completions/grpck b/completions/grpck index 0fadbed..e5ab485 100644 --- a/completions/grpck +++ b/completions/grpck @@ -1,25 +1,26 @@ # grpck(8) completion -*- shell-script -*- -_grpck() +_comp_cmd_grpck() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[R]*)' + # shellcheck disable=SC2254 case $prev in - --root | -!(-*)R) - _filedir + --root | -${noargopts}R) + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - local opts=$(_parse_help "$1") - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage return fi - _filedir + _comp_compgen_filedir } && - complete -F _grpck grpck + complete -F _comp_cmd_grpck grpck # ex: filetype=sh diff --git a/completions/gssdp-discover b/completions/gssdp-discover index 8454f52..3125912 100644 --- a/completions/gssdp-discover +++ b/completions/gssdp-discover @@ -1,34 +1,32 @@ -# bash completion for gssdp-discover -*- shell-script -*- +# bash completion for gssdp-discover/device-sniffer -*- shell-script -*- -_gssdp_discover() +_comp_cmd_gssdp_discover() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in --help | --target | --timeout | --rescan-interval | -[htnr]) return ;; --interface | -i) - _available_interfaces -a + _comp_compgen_available_interfaces -a return ;; --message-type | -m) - local types=$($1 --help 2>&1 | + [[ $1 == *gssdp-discover ]] || return + local types=$("$1" --help 2>&1 | command sed -ne 's/^.*--message-type=.*(\([^)]*\))$/\1/p') - COMPREPLY=($( - IFS+=, - compgen -W "$types" -- "$cur" - )) + _comp_compgen -F $' \t\n,' -- -W "$types" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _gssdp_discover gssdp-discover + complete -F _comp_cmd_gssdp_discover gssdp-discover gssdp-device-sniffer # ex: filetype=sh diff --git a/completions/gzip b/completions/gzip index 0144c3a..9a41eec 100644 --- a/completions/gzip +++ b/completions/gzip @@ -1,27 +1,33 @@ # bash completion for gzip -*- shell-script -*- -_gzip() +_comp_cmd_gzip() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[bSACIJp]*)' + # shellcheck disable=SC2254 case $prev in - --blocksize | --suffix | --help | --version | -!(-*)[bShV]) + --blocksize | --suffix | --help | --version | --alias | --comment | \ + --iterations | --maxsplits | -${noargopts}[bShVACIJ]) return ;; - --processes | -!(-*)p) - COMPREPLY=($(compgen -W "{1..$(_ncpus)}" -- "$cur")) + --processes | -${noargopts}p) + local REPLY + _comp_get_ncpus + _comp_compgen -- -W "{1..$REPLY}" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1") {-1..-9}' -- "$cur")) + _comp_compgen_help + _comp_compgen -a -- -W '-{1..9}' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - local IFS=$'\n' xspec="*.@(gz|t[ag]z)" + local xspec="*.@(gz|t[ag]z)" [[ ${1##*/} == pigz ]] && xspec="*.@([gz]z|t[ag]z)" if [[ $prev == --* ]]; then @@ -32,12 +38,11 @@ _gzip() [[ $prev == -*f* ]] && xspec= fi - _tilde "$cur" || return + _comp_compgen_tilde && return compopt -o filenames - COMPREPLY=($(compgen -f -X "$xspec" -- "$cur") - $(compgen -d -- "$cur")) + _comp_compgen -- -f -X "$xspec" -o plusdirs } && - complete -F _gzip gzip pigz + complete -F _comp_cmd_gzip gzip pigz # ex: filetype=sh diff --git a/completions/hash b/completions/hash new file mode 100644 index 0000000..4ea517b --- /dev/null +++ b/completions/hash @@ -0,0 +1,26 @@ +# hash completion -*- shell-script -*- + +_comp_cmd_hash() +{ + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + + local noargopts='!(*[p]*)' + # shellcheck disable=SC2254 + case $prev in + -${noargopts}p) + _comp_compgen_filedir + return + ;; + esac + + if [[ $cur == -* ]]; then + _comp_compgen_help -c help "$1" + return + fi + + _comp_compgen_commands +} && + complete -F _comp_cmd_hash hash + +# ex: filetype=sh diff --git a/completions/hcitool b/completions/hcitool index 58bf5a7..aacc108 100644 --- a/completions/hcitool +++ b/completions/hcitool @@ -1,178 +1,168 @@ # bash completion for bluez utils -*- shell-script -*- -_bluetooth_addresses() +_comp_cmd_hcitool__bluetooth_addresses() { - if [[ -n ${COMP_BLUETOOTH_SCAN:-} ]]; then - COMPREPLY+=($(compgen -W "$(hcitool scan | - awk '/^\t/{print $1}')" -- "$cur")) + if [[ ${COMP_BLUETOOTH_SCAN-} ]]; then + _comp_compgen -a split -- "$(hcitool scan | _comp_awk '/^\t/{print $1}')" fi } -_bluetooth_devices() +_comp_cmd_hcitool__bluetooth_devices() { - COMPREPLY+=($(compgen -W "$(hcitool dev | - awk '/^\t/{print $1}')" -- "$cur")) + _comp_compgen -a split -- "$(hcitool dev | _comp_awk '/^\t/{print $1}')" } -_bluetooth_services() +_comp_cmd_hcitool__bluetooth_services() { - COMPREPLY=($(compgen -W 'DID SP DUN LAN FAX OPUSH FTP HS HF HFAG SAP NAP - GN PANU HCRP HID CIP A2SRC A2SNK AVRCT AVRTG UDIUE UDITE SYNCML' \ - -- "$cur")) + _comp_compgen -- -W 'DID SP DUN LAN FAX OPUSH FTP HS HF HFAG SAP NAP + GN PANU HCRP HID CIP A2SRC A2SNK AVRCT AVRTG UDIUE UDITE SYNCML' } -_bluetooth_packet_types() +_comp_cmd_hcitool__bluetooth_packet_types() { - COMPREPLY=($(compgen -W 'DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3' \ - -- "$cur")) + _comp_compgen -- -W 'DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3' } -_hcitool() +_comp_cmd_hcitool() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -i) - _bluetooth_devices + _comp_cmd_hcitool__bluetooth_devices return ;; --role) - COMPREPLY=($(compgen -W 'm s' -- "$cur")) + _comp_compgen -- -W 'm s' return ;; --pkt-type) - _bluetooth_packet_types + _comp_cmd_hcitool__bluetooth_packet_types return ;; esac - $split && return + [[ $was_split ]] && return - local arg - _get_first_arg - if [[ -z $arg ]]; then - if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) - else - COMPREPLY=($(compgen -W 'dev inq scan name info spinq epinq cmd - con cc dc sr cpt rssi lq tpl afh lst auth enc key clkoff - clock' -- "$cur")) - fi - else - local args - case $arg in + local REPLY + if _comp_get_first_arg; then + case $REPLY in name | info | dc | rssi | lq | afh | auth | key | clkoff | lst) - _count_args - if ((args == 2)); then - _bluetooth_addresses + _comp_count_args + if ((REPLY == 2)); then + _comp_cmd_hcitool__bluetooth_addresses fi ;; cc) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--role --pkt-type' -- "$cur")) + _comp_compgen -- -W '--role --pkt-type' else - _count_args - if ((args == 2)); then - _bluetooth_addresses + _comp_count_args + if ((REPLY == 2)); then + _comp_cmd_hcitool__bluetooth_addresses fi fi ;; sr) - _count_args - if ((args == 2)); then - _bluetooth_addresses + _comp_count_args + if ((REPLY == 2)); then + _comp_cmd_hcitool__bluetooth_addresses else - COMPREPLY=($(compgen -W 'master slave' -- "$cur")) + _comp_compgen -- -W 'master slave' fi ;; cpt) - _count_args - if ((args == 2)); then - _bluetooth_addresses + _comp_count_args + if ((REPLY == 2)); then + _comp_cmd_hcitool__bluetooth_addresses else - _bluetooth_packet_types + _comp_cmd_hcitool__bluetooth_packet_types fi ;; tpl | enc | clock) - _count_args - if ((args == 2)); then - _bluetooth_addresses + _comp_count_args + if ((REPLY == 2)); then + _comp_cmd_hcitool__bluetooth_addresses else - COMPREPLY=($(compgen -W '0 1' -- "$cur")) + _comp_compgen -- -W '0 1' fi ;; esac + else + if [[ $cur == -* ]]; then + _comp_compgen_help + else + _comp_compgen -- -W 'dev inq scan name info spinq epinq cmd con cc + dc sr cpt rssi lq tpl afh lst auth enc key clkoff clock' + fi fi } && - complete -F _hcitool hcitool + complete -F _comp_cmd_hcitool hcitool -_sdptool() +_comp_cmd_sdptool() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in --bdaddr) - _bluetooth_addresses + _comp_cmd_hcitool__bluetooth_addresses return ;; esac - $split && return + [[ $was_split ]] && return - local arg - _get_first_arg - if [[ -z $arg ]]; then - if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) - else - COMPREPLY=($(compgen -W 'search browse records add del get - setattr setseq' -- "$cur")) - fi - else - case $arg in + local REPLY + if _comp_get_first_arg; then + case $REPLY in search) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--bdaddr --tree --raw --xml' \ - -- "$cur")) + _comp_compgen -- -W '--bdaddr --tree --raw --xml' else - _bluetooth_services + _comp_cmd_hcitool__bluetooth_services fi ;; browse | records) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--tree --raw --xml' -- "$cur")) + _comp_compgen -- -W '--tree --raw --xml' else - _bluetooth_addresses + _comp_cmd_hcitool__bluetooth_addresses fi ;; add) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--handle --channel' -- "$cur")) + _comp_compgen -- -W '--handle --channel' else - _bluetooth_services + _comp_cmd_hcitool__bluetooth_services fi ;; get) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--bdaddr --tree --raw --xml' \ - -- "$cur")) + _comp_compgen -- -W '--bdaddr --tree --raw --xml' fi ;; esac + else + if [[ $cur == -* ]]; then + _comp_compgen_help + else + _comp_compgen -- -W 'search browse records add del get setattr + setseq' + fi fi } && - complete -F _sdptool sdptool + complete -F _comp_cmd_sdptool sdptool -_l2ping() +_comp_cmd_l2ping() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -i) - _bluetooth_devices + _comp_cmd_hcitool__bluetooth_devices return ;; -s | -c | -t | -d) @@ -181,200 +171,193 @@ _l2ping() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage else - _bluetooth_addresses + _comp_cmd_hcitool__bluetooth_addresses fi } && - complete -F _l2ping l2ping + complete -F _comp_cmd_l2ping l2ping -_rfcomm() +_comp_cmd_rfcomm() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -f | --config) - _filedir + _comp_compgen_filedir return ;; -i) - _bluetooth_devices - _bluetooth_addresses + _comp_cmd_hcitool__bluetooth_devices + _comp_cmd_hcitool__bluetooth_addresses return ;; esac - local arg - _get_first_arg - if [[ -z $arg ]]; then - if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) - else - COMPREPLY=($(compgen -W 'show connect listen watch bind - release' -- "$cur")) - fi - else - local args - _count_args + local REPLY + if _comp_get_first_arg; then + local arg=$REPLY + _comp_count_args + local args=$REPLY if ((args == 2)); then - _bluetooth_devices + _comp_cmd_hcitool__bluetooth_devices else case $arg in connect | bind) if ((args == 3)); then - _bluetooth_addresses + _comp_cmd_hcitool__bluetooth_addresses fi ;; esac fi + else + if [[ $cur == -* ]]; then + _comp_compgen_help + else + _comp_compgen -- -W 'show connect listen watch bind release' + fi fi } && - complete -F _rfcomm rfcomm + complete -F _comp_cmd_rfcomm rfcomm -_ciptool() +_comp_cmd_ciptool() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -i) - _bluetooth_devices - _bluetooth_addresses + _comp_cmd_hcitool__bluetooth_devices + _comp_cmd_hcitool__bluetooth_addresses return ;; esac - local arg - _get_first_arg - if [[ -z $arg ]]; then - if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) - else - COMPREPLY=($(compgen -W 'show search connect release loopback' \ - -- "$cur")) - fi - else - local args - case $arg in + local REPLY + if _comp_get_first_arg; then + case $REPLY in connect | release | loopback) - _count_args - if ((args == 2)); then - _bluetooth_addresses + local REPLY + _comp_count_args + if ((REPLY == 2)); then + _comp_cmd_hcitool__bluetooth_addresses fi ;; esac + else + if [[ $cur == -* ]]; then + _comp_compgen_help + else + _comp_compgen -- -W 'show search connect release loopback' + fi fi } && - complete -F _ciptool ciptool + complete -F _comp_cmd_ciptool ciptool -_dfutool() +_comp_cmd_dfutool() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -d | --device) - _bluetooth_devices + _comp_cmd_hcitool__bluetooth_devices return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help else - local args - _count_args - case $args in + local REPLY + _comp_count_args + case $REPLY in 1) - COMPREPLY=($(compgen -W 'verify modify upgrade archive' \ - -- "$cur")) + _comp_compgen -- -W 'verify modify upgrade archive' ;; 2) - _filedir + _comp_compgen_filedir ;; esac fi } && - complete -F _dfutool dfutool + complete -F _comp_cmd_dfutool dfutool -_hciconfig() +_comp_cmd_hciconfig() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - local arg - _get_first_arg - if [[ -z $arg ]]; then - if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--help --all' -- "$cur")) - else - COMPREPLY=($(compgen -W 'up down reset rstat auth noauth encrypt - noencrypt secmgr nosecmgr piscan noscan iscan pscan ptype name - class voice iac inqmode inqdata inqtype inqparams pageparms - pageto afhmode aclmtu scomtu putkey delkey commands features - version revision lm' -- "$cur")) - fi - else - local args - case $arg in + local REPLY + if _comp_get_first_arg; then + case $REPLY in putkey | delkey) - _count_args - if ((args == 2)); then - _bluetooth_addresses + _comp_count_args + if ((REPLY == 2)); then + _comp_cmd_hcitool__bluetooth_addresses fi ;; lm) - _count_args - if ((args == 2)); then - COMPREPLY=($(compgen -W 'MASTER SLAVE NONE ACCEPT' \ - -- "$cur")) + _comp_count_args + if ((REPLY == 2)); then + _comp_compgen -- -W 'MASTER SLAVE NONE ACCEPT' fi ;; ptype) - _count_args - if ((args == 2)); then - _bluetooth_packet_types + _comp_count_args + if ((REPLY == 2)); then + _comp_cmd_hcitool__bluetooth_packet_types fi ;; esac + else + if [[ $cur == -* ]]; then + _comp_compgen -- -W '--help --all' + else + _comp_compgen -- -W 'up down reset rstat auth noauth encrypt + noencrypt secmgr nosecmgr piscan noscan iscan pscan ptype name + class voice iac inqmode inqdata inqtype inqparams pageparms + pageto afhmode aclmtu scomtu putkey delkey commands features + version revision lm' + fi fi } && - complete -F _hciconfig hciconfig + complete -F _comp_cmd_hciconfig hciconfig -_hciattach() +_comp_cmd_hciattach() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-n -p -t -b -s -l' -- "$cur")) + _comp_compgen -- -W '-n -p -t -b -s -l' else - local args - _count_args - case $args in + local REPLY + _comp_count_args + case $REPLY in 1) - COMPREPLY=($(printf '%s\n' /dev/tty*)) - COMPREPLY=($(compgen -W '${COMPREPLY[@]} - ${COMPREPLY[@]#/dev/}' -- "$cur")) + _comp_expand_glob COMPREPLY '/dev/tty*' && + _comp_compgen -- -W '"${COMPREPLY[@]}" + "${COMPREPLY[@]#/dev/}"' ;; 2) - COMPREPLY=($(compgen -W 'any ericsson digi xircom csr bboxes - swave bcsp 0x0105 0x080a 0x0160 0x0002' -- "$cur")) + _comp_compgen -- -W 'any ericsson digi xircom csr bboxes swave + bcsp 0x0105 0x080a 0x0160 0x0002' ;; 3) - COMPREPLY=($(compgen -W '9600 19200 38400 57600 115200 230400 - 460800 921600' -- "$cur")) + _comp_compgen -- -W '9600 19200 38400 57600 115200 230400 + 460800 921600' ;; 4) - COMPREPLY=($(compgen -W 'flow noflow' -- "$cur")) + _comp_compgen -- -W 'flow noflow' ;; 5) - _bluetooth_addresses + _comp_cmd_hcitool__bluetooth_addresses ;; esac fi } && - complete -F _hciattach hciattach + complete -F _comp_cmd_hciattach hciattach # ex: filetype=sh diff --git a/completions/hddtemp b/completions/hddtemp index 7b95f0e..7dbdec3 100644 --- a/completions/hddtemp +++ b/completions/hddtemp @@ -1,38 +1,40 @@ # hddtemp(8) completion -*- shell-script -*- -_hddtemp() +_comp_cmd_hddtemp() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[flupsS]*)' + # shellcheck disable=SC2254 case $prev in - --file | -!(-*)f) - _filedir db + --file | -${noargopts}f) + _comp_compgen_filedir db return ;; - --listen | -!(-*)l) - _ip_addresses + --listen | -${noargopts}l) + _comp_compgen_ip_addresses return ;; - --unit | -!(-*)u) - COMPREPLY=($(compgen -W 'C F' -- "$cur")) + --unit | -${noargopts}u) + _comp_compgen -- -W 'C F' return ;; - --port | --separator | --syslog | --version | --help | -!(-*)[psSvh?]) + --port | --separator | --syslog | --version | --help | -${noargopts}[psSvh?]) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1") --help' -- "$cur")) + _comp_compgen_help + _comp_compgen -a -- -W '--help' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - cur=${cur:=/dev/} - _filedir + _comp_compgen -c "${cur:-/dev/}" filedir fi } && - complete -F _hddtemp hddtemp + complete -F _comp_cmd_hddtemp hddtemp # ex: filetype=sh diff --git a/completions/help b/completions/help new file mode 100644 index 0000000..679ea9f --- /dev/null +++ b/completions/help @@ -0,0 +1,16 @@ +# bash completion for help -*- shell-script -*- + +_comp_cmd_help() +{ + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + + if [[ $cur == -* ]]; then + _comp_compgen_usage -c help -s "$1" + return + fi + + _comp_compgen -- -A helptopic + ((${#COMPREPLY[*]} != 1)) || printf -v "COMPREPLY[0]" %q "$COMPREPLY" +} && + complete -F _comp_cmd_help help diff --git a/completions/hid2hci b/completions/hid2hci index f33a495..161f560 100644 --- a/completions/hid2hci +++ b/completions/hid2hci @@ -1,15 +1,14 @@ # hid2hci completion -*- shell-script -*- -_hid2hci() +_comp_cmd_hid2hci() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--help --quiet -0 --tohci -1 --tohid' \ - -- "$cur")) + _comp_compgen -- -W '--help --quiet -0 --tohci -1 --tohid' fi } && - complete -F _hid2hci hid2hci + complete -F _comp_cmd_hid2hci hid2hci # ex: filetype=sh diff --git a/completions/hostname b/completions/hostname index ce1b32e..12b96dc 100644 --- a/completions/hostname +++ b/completions/hostname @@ -1,23 +1,25 @@ # hostname(1) completion -*- shell-script -*- -_hostname() +_comp_cmd_hostname() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[F]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | -!(-*)[hV]) + --help | --version | -${noargopts}[hV]) return ;; - --file | -!(-*)F) - _filedir + --file | -${noargopts}F) + _comp_compgen_filedir return ;; esac [[ $cur == -* ]] && - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage } && - complete -F _hostname hostname + complete -F _comp_cmd_hostname hostname # ex: filetype=sh diff --git a/completions/hping2 b/completions/hping2 index 666838b..66139a9 100644 --- a/completions/hping2 +++ b/completions/hping2 @@ -1,35 +1,38 @@ # bash completion for hping2 -*- shell-script -*- -_hping2() +_comp_cmd_hping2() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[IaoE]*)' + # shellcheck disable=SC2254 case $prev in - --interface | -!(-*)I) - _available_interfaces + --interface | -${noargopts}I) + _comp_compgen_available_interfaces return ;; - --spoof | -!(-*)a) - _known_hosts_real -- "$cur" + --spoof | -${noargopts}a) + _comp_compgen_known_hosts -- "$cur" return ;; - --tos | -!(-*)o) - COMPREPLY=($(compgen -W '02 04 08 10')) + --tos | -${noargopts}o) + # TODO: parse choices from `--tos help`? + _comp_compgen -- -W '02 04 08 10' return ;; - --file | -!(-*)E) - _filedir + --file | -${noargopts}E) + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help else - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" fi } && - complete -F _hping2 hping hping2 hping3 + complete -F _comp_cmd_hping2 hping hping2 hping3 # ex: filetype=sh diff --git a/completions/htop b/completions/htop index b4916d5..6a0f797 100644 --- a/completions/htop +++ b/completions/htop @@ -1,33 +1,35 @@ # htop(1) completion -*- shell-script -*- -_htop() +_comp_cmd_htop() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[sud]*)' + # shellcheck disable=SC2254 case "$prev" in - --sort-key | -!(-*)s) - COMPREPLY=($(compgen -W '$("$1" -s help)' -- "$cur")) + --sort-key | -${noargopts}s) + _comp_compgen_split -- "$("$1" -s help)" return ;; - --user | -!(-*)u) - COMPREPLY=($(compgen -u -- "$cur")) + --user | -${noargopts}u) + _comp_compgen -- -u return ;; - --delay | -!(-*)d) + --delay | -${noargopts}d) # argument required but no completions available return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" --help)' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi } && - complete -F _htop htop + complete -F _comp_cmd_htop htop # ex: filetype=sh diff --git a/completions/htpasswd b/completions/htpasswd index 527684b..dafd1d9 100644 --- a/completions/htpasswd +++ b/completions/htpasswd @@ -1,9 +1,9 @@ # htpasswd(1) completion -*- shell-script -*- -_htpasswd() +_comp_cmd_htpasswd() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local i o=0 # $o is index of first non-option argument for ((i = 1; i <= cword; i++)); do @@ -19,18 +19,17 @@ _htpasswd() if ((o == 0 || o == cword)); then if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi # Password file (first non-option argument) - _filedir + _comp_compgen_filedir elif ((o == cword - 1)); then # Username (second non-option argument) - COMPREPLY=($(compgen -W \ - '$(cut -d: -f1 "${words[o]}" 2>/dev/null)' -- "$cur")) + _comp_compgen_split -- "$(cut -d: -f1 "${words[o]}" 2>/dev/null)" fi } && - complete -F _htpasswd htpasswd + complete -F _comp_cmd_htpasswd htpasswd # ex: filetype=sh diff --git a/completions/hunspell b/completions/hunspell index 92b4fe8..28cb7df 100644 --- a/completions/hunspell +++ b/completions/hunspell @@ -1,43 +1,40 @@ # hunspell(1) completion -*- shell-script -*- -_hunspell() +_comp_cmd_hunspell() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --help | --version | -vv | -[hPv]) return ;; -d) - local IFS=$' \t\n' reset=$(shopt -p nullglob) - shopt -s nullglob - local -a dicts=(/usr/share/hunspell/*.dic - /usr/local/share/hunspell/*.dic) - dicts=("${dicts[@]##*/}") - dicts=("${dicts[@]%.dic}") - $reset - IFS=$'\n' - COMPREPLY=($(compgen -W '${dicts[@]}' -- "$cur")) + local -a dicts + if _comp_expand_glob dicts '/usr/share/hunspell/*.dic /usr/local/share/hunspell/*.dic'; then + dicts=("${dicts[@]##*/}") + dicts=("${dicts[@]%.dic}") + _comp_compgen -- -W '"${dicts[@]}"' + fi return ;; -i) - _xfunc iconv _iconv_charsets + _comp_compgen -x iconv charsets return ;; -p) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - _filedir + _comp_compgen_filedir } && - complete -F _hunspell hunspell + complete -F _comp_cmd_hunspell hunspell # ex: filetype=sh diff --git a/completions/iconv b/completions/iconv index 81ae01b..bbcbbdd 100644 --- a/completions/iconv +++ b/completions/iconv @@ -1,38 +1,52 @@ # iconv(1) completion -*- shell-script -*- +# @since 2.12 +_comp_xfunc_iconv_compgen_charsets() +{ + _comp_cmd_iconv__compgen_charsets iconv +} + +# @deprecated 2.12 use `_comp_xfunc_iconv_compgen_charsets` instead _iconv_charsets() { - COMPREPLY+=($(compgen -X ... -W '$(${1:-iconv} -l | \ - command sed -e "s@/*\$@@" -e "s/[,()]//g")' -- "$cur")) + _comp_compgen -ai iconv charsets "${1:-iconv}" +} + +_comp_cmd_iconv__compgen_charsets() +{ + _comp_compgen_split -X ... -- "$("$1" -l | + command sed -e 's@/*$@@' -e 's/[,()]//g')" } -_iconv() +_comp_cmd_iconv() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[fto]*)' + # shellcheck disable=SC2254 case $prev in --help | --usage | --version | --unicode-subst | --byte-subst | \ - --widechar-subst | -!(-*)[?V]) + --widechar-subst | -${noargopts}[?V]) return ;; - --from-code | --to-code | -!(-*)[ft]) - _iconv_charsets $1 + --from-code | --to-code | -${noargopts}[ft]) + _comp_cmd_iconv__compgen_charsets "$1" return ;; - --output | -!(-*)o) - _filedir + --output | -${noargopts}o) + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _iconv -o default iconv + complete -F _comp_cmd_iconv -o default iconv # ex: filetype=sh diff --git a/completions/id b/completions/id index a07e51d..e91ad61 100644 --- a/completions/id +++ b/completions/id @@ -1,18 +1,17 @@ # id(1) completion -*- shell-script -*- -_id() +_comp_cmd_id() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - local opts=$(_parse_help "$1") - [[ $opts ]] || opts="-G -g -u" # POSIX fallback - COMPREPLY=($(compgen -W "$opts" -- "$cur")) + _comp_compgen_help || + _comp_compgen -- -W '-G -g -u' # POSIX fallback else - COMPREPLY=($(compgen -u "$cur")) + _comp_compgen -- -u fi } && - complete -F _id id + complete -F _comp_cmd_id id # ex: filetype=sh diff --git a/completions/idn b/completions/idn index 8023f8f..1a61479 100644 --- a/completions/idn +++ b/completions/idn @@ -1,26 +1,28 @@ # idn(1) completion -*- shell-script -*- -_idn() +_comp_cmd_idn() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[p]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | -!(-*)[hV]) + --help | --version | -${noargopts}[hV]) return ;; - --profile | -!(-*)p) - COMPREPLY=($(compgen -W 'Nameprep iSCSI Nodeprep Resourceprep - trace SASLprep' -- "$cur")) + --profile | -${noargopts}p) + _comp_compgen -- -W 'Nameprep iSCSI Nodeprep Resourceprep trace + SASLprep' return ;; esac - if ! $split && [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + if [[ ! $was_split && $cur == -* ]]; then + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _idn idn + complete -F _comp_cmd_idn idn # ex: filetype=sh diff --git a/completions/ifstat b/completions/ifstat index 629786e..0f05199 100644 --- a/completions/ifstat +++ b/completions/ifstat @@ -1,43 +1,45 @@ # bash completion for ifstat(1) -*- shell-script -*- -_ifstat() +_comp_cmd_ifstat() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[idstx]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | --scan | --interval | -!(-*)[hvV]) + --help | --version | --scan | --interval | -${noargopts}[hvV]) return ;; - -!(-*)i) + -${noargopts}i) # TODO comma separated - _available_interfaces -a + _comp_compgen_available_interfaces -a return ;; - -!(-*)d) + -${noargopts}d) # iproute2: no completion (scan delay) # traditional: parse driver if ! { "$1" --help 2>&1 || : } | command grep -q -- '-d.*--scan'; then - COMPREPLY=($(compgen -W '$("$1" -v | command \ - sed -e "s/[,.]//g" -ne "s/^.*drivers://p")' -- "$cur")) + _comp_compgen_split -- "$("$1" -v | command sed -e 's/[,.]//g' \ + -ne 's/^.*drivers://p')" fi return ;; - --noupdate | -!(-*)s) + --noupdate | -${noargopts}s) # iproute2: pass through (skip history update) # traditional: hostnames (snmp) if ! { "$1" --help 2>&1 || : } | command grep -q -- '-s.*--noupdate'; then - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return fi ;; - -!(-*)t) + -${noargopts}t) # iproute2: no completion (interval) # traditional: pass through (add timestamp) ! { @@ -45,24 +47,22 @@ _ifstat() } | command grep -q -- '-t.*--interval' || return ;; - --extended | -!(-*)x) + --extended | -${noargopts}x) # iproute2: parse xstat types - COMPREPLY=($(compgen -W '$("$1" -x nonexistent-xstat 2>&1 | - awk "found { print \$1 } /supported xstats:/ { found=1 }")' \ - -- "$cur")) + _comp_compgen_split -- "$("$1" -x nonexistent-xstat 2>&1 | + _comp_awk 'found { print $1 } /supported xstats:/ { found=1 }')" return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - local opts=$(_parse_help "$1") - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi } && - complete -F _ifstat ifstat + complete -F _comp_cmd_ifstat ifstat # ex: filetype=sh diff --git a/completions/iftop b/completions/iftop index b73f4b6..d1635af 100644 --- a/completions/iftop +++ b/completions/iftop @@ -1,26 +1,26 @@ # iftop(8) completion -*- shell-script -*- -_iftop() +_comp_cmd_iftop() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -h | -f | -F | -m) return ;; -i) - _available_interfaces -a + _comp_compgen_available_interfaces -a return ;; -c) - _filedir + _comp_compgen_filedir return ;; esac - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur")) + _comp_compgen_help -- -h } && - complete -F _iftop iftop + complete -F _comp_cmd_iftop iftop # ex: filetype=sh diff --git a/completions/ifup b/completions/ifup index 5b35bfb..bfeee82 100644 --- a/completions/ifup +++ b/completions/ifup @@ -1,39 +1,40 @@ # Red Hat & Debian GNU/Linux if{up,down} completion -*- shell-script -*- -_userland GNU || return 1 +_comp_userland GNU || return 1 -_ifupdown() +_comp_cmd_ifupdown() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[Xoi]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | --allow | --exclude | --option | -!(-*)[hVXo]) + --help | --version | --allow | --exclude | --option | -${noargopts}[hVXo]) return ;; - --interfaces | -!(-*)i) - _filedir + --interfaces | -${noargopts}i) + _comp_compgen_filedir return ;; --state-dir) - _filedir -d + _comp_compgen_filedir -d return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - local args - _count_args "" "@(--allow|-i|--interfaces|--state-dir|-X|--exclude|-o)" + local REPLY + _comp_count_args -a "@(--allow|-i|--interfaces|--state-dir|-X|--exclude|-o)" - if ((args == 1)); then - _configured_interfaces - COMPREPLY=($(compgen -W '${COMPREPLY[@]}' -- "$cur")) + if ((REPLY == 1)); then + _comp_compgen_configured_interfaces fi } && - complete -F _ifupdown ifup ifdown ifquery ifstatus + complete -F _comp_cmd_ifupdown ifup ifdown ifquery ifstatus # ex: filetype=sh diff --git a/completions/influx b/completions/influx index e9362e7..89b90e7 100644 --- a/completions/influx +++ b/completions/influx @@ -1,35 +1,32 @@ # bash completion for influx(8) -*- shell-script -*- -_influx() +_comp_cmd_influx() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -version | -port | -database | -password | -username | -execute | -pps) return ;; -host) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -format | -precision | -consistency) - local args=$($1 --help 2>&1 | awk "\$1 == \"$prev\" { print \$2 }") - COMPREPLY=($( - IFS+="\"'|" - compgen -W "$args" -- "$cur" - )) + local args=$("$1" --help 2>&1 | _comp_awk "\$1 == \"$prev\" { print \$2 }") + _comp_compgen -F $' \t\n'"\"'|" -- -W "$args" return ;; -import | -path) - _filedir + _comp_compgen_filedir return ;; esac [[ $cur == -* ]] && - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help } && - complete -F _influx influx + complete -F _comp_cmd_influx influx # ex: filetype=sh diff --git a/completions/info b/completions/info index f50f842..3a13565 100644 --- a/completions/info +++ b/completions/info @@ -1,40 +1,42 @@ # bash completion for info -*- shell-script -*- -_info() +_comp_cmd_info() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return # default completion if parameter looks like a path if [[ $cur == @(*/|[.~])* ]]; then - _filedir + _comp_compgen_filedir return fi + local noargopts='!(-*|*[kndfor]*)' + # shellcheck disable=SC2254 case $prev in - --apropos | --index-search | --node | --help | --version | -!(-*)[knhv]) + --apropos | --index-search | --node | --help | --version | -${noargopts}[knhv]) return ;; - -!(-*)d) + -${noargopts}d) if [[ ${1##*/} == info ]]; then - _filedir -d + _comp_compgen_filedir -d return fi ;; --directory) - _filedir -d + _comp_compgen_filedir -d return ;; - --dribble | --file | --output | --restore | --raw-filename | --rcfile | -!(-*)[for]) - _filedir + --dribble | --file | --output | --restore | --raw-filename | --rcfile | -${noargopts}[for]) + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi @@ -47,28 +49,22 @@ _info() infopath=$INFOPATH fi - _expand || return - - infopath=$infopath: - if [[ -n $cur ]]; then - infopath="${infopath//://$cur* }" - else - infopath="${infopath//:// }" + _comp_split -F : infopath "$infopath" + if ((${#infopath[@]})); then + _comp_compgen -Rv infopath -- -S "/$cur*" -W '"${infopath[@]}"' + local IFS= + if _comp_expand_glob COMPREPLY '${infopath[@]}'; then + # weed out directory path names and paths to info pages (empty + # elements will be removed by the later `compgen -X ''`) + COMPREPLY=("${COMPREPLY[@]##*/?(:)}") + # strip suffix from info pages + COMPREPLY=("${COMPREPLY[@]%.@(gz|bz2|xz|lzma)}") + # weed out info dir file with -X 'dir' + _comp_compgen -c "${cur//\\\\/}" -- -W '"${COMPREPLY[@]%.*}"' -X '@(|dir)' + fi + _comp_unlocal IFS fi - - # redirect stderr for when path doesn't exist - COMPREPLY=($(eval command ls "$infopath" 2>/dev/null)) - # weed out directory path names and paths to info pages - COMPREPLY=(${COMPREPLY[@]##*/?(:)}) - # weed out info dir file - for i in ${!COMPREPLY[*]}; do - [[ ${COMPREPLY[i]} == dir ]] && unset "COMPREPLY[i]" - done - # strip suffix from info pages - COMPREPLY=(${COMPREPLY[@]%.@(gz|bz2|xz|lzma)}) - COMPREPLY=($(compgen -W '${COMPREPLY[@]%.*}' -- "${cur//\\\\/}")) - } && - complete -F _info info pinfo + complete -F _comp_cmd_info info pinfo # ex: filetype=sh diff --git a/completions/inject b/completions/inject index fad73a1..4b46921 100644 --- a/completions/inject +++ b/completions/inject @@ -1,26 +1,29 @@ # mailman inject completion -*- shell-script -*- -_inject() +_comp_cmd_inject() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -l | --listname) - _xfunc list_lists _mailman_lists + # Prefer `list_lists` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen -x list_lists mailman_lists return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--listname --queue --help' -- "$cur")) + _comp_compgen -- -W '--listname --queue --help' else - _filedir + _comp_compgen_filedir fi } && - complete -F _inject inject + complete -F _comp_cmd_inject inject # ex: filetype=sh diff --git a/completions/inotifywait b/completions/inotifywait index e5608fc..a069295 100644 --- a/completions/inotifywait +++ b/completions/inotifywait @@ -1,47 +1,48 @@ # bash completion for inotifywait(1) and inotifywatch(1) -*- shell-script -*- -_inotifywait_events() +_comp_cmd_inotifywait__events() { # Expecting line with "Events:", followed by ones starting with one # tab. Word following the tab is event name, others are line # wrapped explanations. - COMPREPLY+=($(compgen -W "$($1 --help 2>/dev/null | + _comp_compgen -a split -- "$("$1" --help 2>/dev/null | command sed -e '/^Events:/,/^[^'$'\t'']/!d' \ - -ne 's/^'$'\t''\([^ '$'\t'']\{1,\}\)[ '$'\t''].*/\1/p')" \ - -- "$cur")) + -ne 's/^'$'\t''\([^ '$'\t'']\{1,\}\)[ '$'\t''].*/\1/p')" } -_inotifywait() +_comp_cmd_inotifywait() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[oe]*)' + # shellcheck disable=SC2254 case $prev in - --help | --exclude | --excludei | --format | --timefmt | --timeout | -!(-*)[ht]) + --help | --exclude | --excludei | --include | --includei | --format | --timefmt | --timeout | -${noargopts}[ht]) return ;; - --fromfile | --outfile | -!(-*)o) - _filedir + --fromfile | --outfile | -${noargopts}o) + _comp_compgen_filedir return ;; - --event | -!(-*)e) - _inotifywait_events "$1" + --event | -${noargopts}e) + _comp_cmd_inotifywait__events "$1" return ;; --ascending | --descending) - COMPREPLY=($(compgen -W 'total' -- "$cur")) - _inotifywait_events "$1" + _comp_compgen -- -W 'total' + _comp_cmd_inotifywait__events "$1" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - _filedir + _comp_compgen_filedir } && - complete -F _inotifywait inotifywait inotifywatch + complete -F _comp_cmd_inotifywait inotifywait inotifywatch # ex: filetype=sh diff --git a/completions/insmod b/completions/insmod index a59e753..2c02f3f 100644 --- a/completions/insmod +++ b/completions/insmod @@ -1,18 +1,18 @@ # Linux insmod(8) completion -*- shell-script -*- -_insmod() +_comp_cmd_insmod() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return # do filename completion for first argument if ((cword == 1)); then - _filedir '@(?(k)o?(.[gx]z))' + _comp_compgen_filedir '@(?(k)o?(.[gx]z|.zst))' else # do module parameter completion - COMPREPLY=($(compgen -W "$(PATH="$PATH:/sbin" modinfo \ - -p ${words[1]} 2>/dev/null | cut -d: -f1)" -- "$cur")) + _comp_compgen_split -- "$(PATH="$PATH:/sbin" modinfo \ + -p "${words[1]}" 2>/dev/null | cut -d: -f1)" fi } && - complete -F _insmod insmod insmod.static + complete -F _comp_cmd_insmod insmod insmod.static # ex: filetype=sh diff --git a/completions/installpkg b/completions/installpkg index 7455eb1..71116b0 100644 --- a/completions/installpkg +++ b/completions/installpkg @@ -1,33 +1,33 @@ # Slackware Linux installpkg completion -*- shell-script -*- -_installpkg() +_comp_cmd_installpkg() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case "$prev" in --root) - _filedir -d + _comp_compgen_filedir -d return ;; --priority) - COMPREPLY=($(compgen -W 'ADD REC OPT SKP' -- "$cur")) + _comp_compgen -- -W 'ADD REC OPT SKP' return ;; --tagfile) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--warn --md5sum --root --infobox --terse - --menu --ask --priority --tagfile' -- "$cur")) + _comp_compgen -- -W '--warn --md5sum --root --infobox --terse --menu + --ask --priority --tagfile' return fi - _filedir 't[bglx]z' + _comp_compgen_filedir 't[bglx]z' } && - complete -F _installpkg installpkg + complete -F _comp_cmd_installpkg installpkg # ex: filetype=sh diff --git a/completions/interdiff b/completions/interdiff index 9933d15..6f56e33 100644 --- a/completions/interdiff +++ b/completions/interdiff @@ -1,20 +1,22 @@ # interdiff(1) completion -*- shell-script -*- -_interdiff() +_comp_cmd_interdiff() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[Upd]*)' + # shellcheck disable=SC2254 case $prev in - --unified | --strip-match | --drop-context | -!(-*)[Upd]) + --unified | --strip-match | --drop-context | -${noargopts}[Upd]) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi @@ -26,8 +28,8 @@ _interdiff() break fi done - _filedir "$exts" + _comp_compgen_filedir "$exts" } && - complete -F _interdiff interdiff + complete -F _comp_cmd_interdiff interdiff # ex: filetype=sh diff --git a/completions/invoke-rc.d b/completions/invoke-rc.d index 4a5045a..e5a66b6 100644 --- a/completions/invoke-rc.d +++ b/completions/invoke-rc.d @@ -2,37 +2,37 @@ # # Copyright (C) 2004 Servilio Afre Puentes <servilio@gmail.com> -_invoke_rc_d() +_comp_cmd_invoke_rc_d() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - local sysvdir services options valid_options + local sysvdir services options [[ -d /etc/rc.d/init.d ]] && sysvdir=/etc/rc.d/init.d || sysvdir=/etc/init.d - services=($(printf '%s ' $sysvdir/!(README*|*.sh|$_backup_glob))) - services=(${services[@]#$sysvdir/}) options=(--help --quiet --force --try-anyway --disclose-deny --query --no-fallback) if [[ $cword -eq 1 || $prev == --* ]]; then - valid_options=($( + # generate valid_options + _comp_compgen_split -- "$( tr " " "\n" <<<"${words[*]} ${options[*]}" | command sed -ne "/$(command sed 's/ /\\|/g' <<<"${options[*]}")/p" | sort | uniq -u - )) - COMPREPLY=($(compgen -W '${valid_options[@]} ${services[@]}' -- "$cur")) + )" + _comp_expand_glob services '"$sysvdir"/!(README*|*.sh|$_comp_backup_glob)' && + _comp_compgen -a -- -W '"${services[@]#"$sysvdir"/}"' elif [[ -x $sysvdir/$prev ]]; then - COMPREPLY=($(compgen -W '`command sed -e "y/|/ /" \ - -ne "s/^.*Usage:[ ]*[^ ]*[ ]*{*\([^}\"]*\).*$/\1/p" \ - $sysvdir/$prev`' -- "$cur")) + _comp_compgen_split -- "$(command sed -e 'y/|/ /' \ + -ne 's/^.*Usage:[ ]*[^ ]*[ ]*{*\([^}"]*\).*$/\1/p' \ + "$sysvdir/$prev")" else COMPREPLY=() fi } && - complete -F _invoke_rc_d invoke-rc.d + complete -F _comp_cmd_invoke_rc_d invoke-rc.d # ex: filetype=sh diff --git a/completions/ip b/completions/ip index 12ad9aa..511f206 100644 --- a/completions/ip +++ b/completions/ip @@ -1,58 +1,78 @@ # ip(8) completion -*- shell-script -*- -_iproute2_etc() +_comp_cmd_ip__iproute2_etc() { - COMPREPLY+=($(compgen -W \ - "$(awk '!/#/ { print $2 }' /etc/iproute2/$1 2>/dev/null)" \ - -- "$cur")) + _comp_compgen -a split -- "$(_comp_awk '!/#/ { print $2 }' "/etc/iproute2/$1" \ + 2>/dev/null)" } -_ip() +_comp_cmd_ip__netns() { - local cur prev words cword - _init_completion || return + _comp_compgen_split -- "$( + { + ${1-ip} -c=never netns list 2>/dev/null || ${1-ip} netns list + } | _comp_awk '{print $1}' + )" +} + +_comp_cmd_ip() +{ + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in - -V | -Version | -rc | -rcvbuf) + -V | -Version | -rc | -rcvbuf | -l | -loops) return ;; -f | -family) - COMPREPLY=($(compgen -W 'inet inet6 ipx dnet link' -- "$cur")) + _comp_compgen -- -W 'inet inet6 ipx dnet link' return ;; -b | -batch) - _filedir + _comp_compgen_filedir + return + ;; + -n | -netns) + _comp_cmd_ip__netns "$1" return ;; -force) - COMPREPLY=($(compgen -W '-batch' -- "$cur")) + _comp_compgen -- -W '-batch' return ;; esac - local subcword cmd subcmd="" - for ((subcword = 1; subcword < ${#words[@]} - 1; subcword++)); do + local subcword cmd="" has_cmd="" subcmd="" + for ((subcword = 1; subcword < cword; subcword++)); do [[ ${words[subcword]} == -b?(atch) ]] && return - [[ -v cmd ]] && subcmd=${words[subcword]} && break - [[ ${words[subcword]} != -* && \ - ${words[subcword - 1]} != -@(f?(amily)|rc?(vbuf)) ]] && - cmd=${words[subcword]} + [[ $has_cmd ]] && subcmd=${words[subcword]} && break + [[ ${words[subcword]} != -* && + ${words[subcword - 1]} != -@(f?(amily)|rc?(vbuf)) ]] && + cmd=${words[subcword]} has_cmd=set done - if [[ ! -v cmd ]]; then + if [[ ! $has_cmd ]]; then case $cur in -*) - local c="-Version -statistics -details -resolve -family - -oneline -timestamp -batch -rcvbuf" - ((cword == 1)) && c+=" -force" - COMPREPLY=($(compgen -W "$c" -- "$cur")) + _comp_compgen -a help - <<<"$( + ((cword == 1)) && printf '%s\n' -force + { + "$1" -c=never help || "$1" help + } 2>&1 | command sed -e \ + 's/[{|}=]/\n/g' -e \ + 's/\[\([^]]\{1,\}\)\]/\1/g' + )" ;; *) - COMPREPLY=($(compgen -W "help $($1 help 2>&1 | command sed -e \ - '/OBJECT := /,/}/!d' -e \ - 's/.*{//' -e \ - 's/}.*//' -e \ - 's/|//g')" -- "$cur")) + _comp_compgen_split -- "help $( + { + $1 -c=never help || $1 help + } 2>&1 | command sed -e \ + '/OBJECT := /,/}/!d' -e \ + 's/.*{//' -e \ + 's/}.*//' -e \ + 's/|//g' + )" ;; esac return @@ -69,26 +89,26 @@ _ip() delete) case $((cword - subcword)) in 1) - _available_interfaces + _comp_compgen_available_interfaces ;; 2) - COMPREPLY=($(compgen -W 'type' -- "$cur")) + _comp_compgen -- -W 'type' ;; 3) [[ $prev == type ]] && - COMPREPLY=($(compgen -W 'vlan veth vcan dummy - ifb macvlan can' -- "$cur")) + _comp_compgen -- -W 'vlan veth vcan dummy ifb + macvlan can' ;; esac ;; set) if ((cword - subcword == 1)); then - _available_interfaces + _comp_compgen_available_interfaces else case $prev in arp | dynamic | multicast | allmulticast | promisc | \ trailers) - COMPREPLY=($(compgen -W 'on off' -- "$cur")) + _comp_compgen -- -W 'on off' ;; txqueuelen | name | address | broadcast | mtu | netns | alias) ;; @@ -97,25 +117,24 @@ _ip() promisc trailers txqueuelen name address broadcast mtu netns alias" [[ $prev != @(up|down) ]] && c+=" up down" - COMPREPLY=($(compgen -W "$c" -- "$cur")) + _comp_compgen -- -W "$c" ;; esac fi ;; show) if ((cword == subcword + 1)); then - _available_interfaces - COMPREPLY+=($(compgen -W 'dev group up' -- "$cur")) + _comp_compgen_available_interfaces + _comp_compgen -a -- -W 'dev group up' elif [[ $prev == dev ]]; then - _available_interfaces + _comp_compgen_available_interfaces elif [[ $prev == group ]]; then - _iproute2_etc group + _comp_cmd_ip__iproute2_etc group fi ;; *) ((cword == subcword)) && - COMPREPLY=($(compgen -W 'help add delete set show' \ - -- "$cur")) + _comp_compgen -- -W 'help add delete set show' ;; esac ;; @@ -124,38 +143,38 @@ _ip() case $subcmd in add | change | replace) if [[ $prev == dev ]]; then - _available_interfaces + _comp_compgen_available_interfaces elif [[ $prev == scope ]]; then - _iproute2_etc rt_scopes + _comp_cmd_ip__iproute2_etc rt_scopes else : # TODO fi ;; del) if [[ $prev == dev ]]; then - _available_interfaces + _comp_compgen_available_interfaces elif [[ $prev == scope ]]; then - _iproute2_etc rt_scopes + _comp_cmd_ip__iproute2_etc rt_scopes else : # TODO fi ;; show | flush) if ((cword == subcword + 1)); then - _available_interfaces - COMPREPLY+=($(compgen -W 'dev scope to label dynamic + _comp_compgen_available_interfaces + _comp_compgen -a -- -W 'dev scope to label dynamic permanent tentative deprecated dadfailed temporary - primary secondary up' -- "$cur")) + primary secondary up' elif [[ $prev == dev ]]; then - _available_interfaces + _comp_compgen_available_interfaces elif [[ $prev == scope ]]; then - _iproute2_etc rt_scopes + _comp_cmd_ip__iproute2_etc rt_scopes fi ;; *) ((cword == subcword)) && - COMPREPLY=($(compgen -W 'help add change replace del - show flush' -- "$cur")) + _comp_compgen -- -W 'help add change replace del show + flush' ;; esac ;; @@ -164,15 +183,14 @@ _ip() case $subcmd in list | add | del | flush) if [[ $prev == dev ]]; then - _available_interfaces + _comp_compgen_available_interfaces else : # TODO fi ;; *) ((cword == subcword)) && - COMPREPLY=($(compgen -W 'help list add del flush' \ - -- "$cur")) + _comp_compgen -- -W 'help list add del flush' ;; esac ;; @@ -181,7 +199,7 @@ _ip() case $subcmd in list | flush) if [[ $prev == proto ]]; then - _iproute2_etc rt_protos + _comp_cmd_ip__iproute2_etc rt_protos else : # TODO fi @@ -189,25 +207,32 @@ _ip() get) # TODO ;; - a | add | d | del | change | append | r | replace | monitor) + a | add | d | del | change | append | r | replace) if [[ $prev == via ]]; then - COMPREPLY=($(compgen -W "$($1 r | command sed -ne \ - 's/.*via \([0-9.]*\).*/\1/p')" -- "$cur")) + _comp_compgen_split -- "$( + { + $1 -c=never r 2>/dev/null || $1 r + } | command sed -ne \ + 's/.*via \([0-9.]*\).*/\1/p' + )" elif [[ $prev == "$subcmd" ]]; then - COMPREPLY=($(compgen -W "table default \ - $($1 r | cut -d ' ' -f 1)" -- "$cur")) + _comp_compgen_split -- "table default $( + { + $1 -c=never r 2>/dev/null || $1 r + } | cut -d ' ' -f 1 + )" elif [[ $prev == dev ]]; then - _available_interfaces -a + _comp_compgen_available_interfaces -a elif [[ $prev == table ]]; then - COMPREPLY=($(compgen -W 'local main default' -- "$cur")) + _comp_compgen -- -W 'local main default' else - COMPREPLY=($(compgen -W 'via dev weight' -- "$cur")) + _comp_compgen -- -W 'via dev weight' fi ;; *) ((cword == subcword)) && - COMPREPLY=($(compgen -W 'help list flush get add del - change append replace monitor' -- "$cur")) + _comp_compgen -- -W 'help list flush get add del change + append replace' ;; esac ;; @@ -221,16 +246,16 @@ _ip() suppress_ifgroup | realms | nat | goto) ;; iif | oif) - _available_interfaces -a + _comp_compgen_available_interfaces -a ;; table | lookup) - COMPREPLY=($(compgen -W 'local main default' -- "$cur")) + _comp_compgen -- -W 'local main default' ;; *) - COMPREPLY=($(compgen -W 'from to tos dsfield fwmark - uidrange ipproto sport dport priority table lookup - protocol suppress_prefixlength suppress_ifgroup realms - nat goto iif oif not' -- "$cur")) + _comp_compgen -- -W 'from to tos dsfield fwmark + uidrange ipproto sport dport priority table + lookup protocol suppress_prefixlength + suppress_ifgroup realms nat goto iif oif not' ;; esac ;; @@ -238,14 +263,14 @@ _ip() if [[ $prev == protocol ]]; then : else - COMPREPLY=($(compgen -W 'protocol' -- "$cur")) + _comp_compgen -- -W 'protocol' fi ;; restore | show) ;; *) ((cword == subcword)) && - COMPREPLY=($(compgen -W 'help add del list flush save - restore show' -- "$cur")) + _comp_compgen -- -W 'help add del list flush save + restore show' ;; esac ;; @@ -260,8 +285,8 @@ _ip() ;; *) ((cword == subcword)) && - COMPREPLY=($(compgen -W 'help add del change replace - show flush' -- "$cur")) + _comp_compgen -- -W 'help add del change replace show + flush' ;; esac ;; @@ -276,8 +301,7 @@ _ip() ;; *) ((cword == subcword)) && - COMPREPLY=($(compgen -W 'help change show' \ - -- "$cur")) + _comp_compgen -- -W 'help change show' ;; esac ;; @@ -291,8 +315,7 @@ _ip() ;; *) ((cword == subcword)) && - COMPREPLY=($(compgen -W 'help add change del show prl - 6rd' -- "$cur")) + _comp_compgen -- -W 'help add change del show prl 6rd' ;; esac ;; @@ -304,16 +327,15 @@ _ip() ;; show) if [[ $cword -eq $subcword+1 || $prev == dev ]]; then - _available_interfaces - [[ $prev != dev ]] && - COMPREPLY=($(compgen -W '${COMPREPLY[@]} dev' \ - -- "$cur")) + _comp_compgen_available_interfaces + if [[ $prev != dev ]]; then + _comp_compgen -a -W dev + fi fi ;; *) ((cword == subcword)) && - COMPREPLY=($(compgen -W 'help add del show' \ - -- "$cur")) + _comp_compgen -- -W 'help add del show' ;; esac ;; @@ -325,7 +347,7 @@ _ip() ;; *) ((cword == subcword)) && - COMPREPLY=($(compgen -W 'help show' -- "$cur")) + _comp_compgen -- -W 'help show' ;; esac ;; @@ -335,7 +357,14 @@ _ip() all) ;; *) ((cword == subcword)) && - COMPREPLY=($(compgen -W 'help all' -- "$cur")) + _comp_compgen_split -- "help all $( + { + "$1" -c=never monitor help || "$1" monitor help + } 2>&1 | command sed -e \ + '/OBJECTS := /,/[^|]$/!d' -e \ + 's/OBJECTS := *//' -e \ + 's/|//g' + )" ;; esac ;; @@ -348,13 +377,12 @@ _ip() # TODO ;; delete | exec | pids | set) - [[ $prev == "$subcmd" ]] && - COMPREPLY=($(compgen -W "$($1 netns list)" -- "$cur")) + [[ $prev == "$subcmd" ]] && _comp_cmd_ip__netns "$1" ;; *) ((cword == subcword)) && - COMPREPLY=($(compgen -W 'help add delete exec - identify list list-id monitor pids set' -- "$cur")) + _comp_compgen -- -W 'help add delete exec identify list + list-id monitor pids set' ;; esac ;; @@ -366,13 +394,12 @@ _ip() ;; *) ((cword == subcword)) && - COMPREPLY=($(compgen -W 'state policy monitor' \ - -- "$cur")) + _comp_compgen -- -W 'state policy monitor' ;; esac ;; esac } && - complete -F _ip ip + complete -F _comp_cmd_ip ip # ex: filetype=sh diff --git a/completions/ipcalc b/completions/ipcalc index 5603c26..979a8c2 100644 --- a/completions/ipcalc +++ b/completions/ipcalc @@ -1,9 +1,9 @@ # ipcalc(1) completion -*- shell-script -*- -_ipcalc() +_comp_cmd_ipcalc() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --help | --version | --split | -[hs]) @@ -18,8 +18,8 @@ _ipcalc() done [[ $cur != -* ]] || - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help } && - complete -F _ipcalc ipcalc + complete -F _comp_cmd_ipcalc ipcalc # ex: filetype=sh diff --git a/completions/iperf b/completions/iperf index 6347fe0..0168814 100644 --- a/completions/iperf +++ b/completions/iperf @@ -1,69 +1,90 @@ # iperf(1) completion -*- shell-script -*- -_iperf() +_comp_cmd_iperf() { - local cur prev words cword split - _init_completion -s -n : || return + local cur prev words cword was_split comp_args + _comp_initialize -s -n : -- "$@" || return + local noargopts='!(-*|*[ilpwMXbntLPTZCkOSAfIoFBcxy]*)' + # shellcheck disable=SC2254 case $prev in --help | --version | --interval | --len | --port | --window | --mss | --bandwidth | \ --num | --time | --listenport | --parallel | --ttl | --linux-congestion | --omit | \ --congestion | --bytes | --blockcount | --cport | --set-mss | --flowlabel | \ - --title | --tos | --affinity | -!(-*)[hvilpwMbntLPTZCkOSA]) + --title | --tos | --affinity | --rcv-timeout | --server-bitrate-limit | \ + --idle-timeout | --time-skew-threshold | --xbind | --nstreams | --connect-timeout | \ + --bitrate | --pacing-timer | --fq-rate | --length | --dscp | --extra-data | \ + --username | -${noargopts}[hvilpwMXbntLPTZCkOSA]) return ;; - --format | -!(-*)f) - COMPREPLY=($(compgen -W 'k m g K M G' -- "$cur")) + --format | -${noargopts}f) + local formats=$( + "$1" --help 2>&1 | + command sed -ne 's/^.*--format .*\[\([a-zA-Z]\{1,\}\)\].*/\1/p' | + command sed -e 's/./& /g' + ) + _comp_compgen -- -W '$formats' return ;; - --output | --fileinput | -!(-*)[oF]) - _filedir + --pidfile | -${noargopts}I) + _comp_compgen_filedir pid return ;; - --bind | -!(-*)B) - _available_interfaces -a - _ip_addresses -a - __ltrim_colon_completions "$cur" + --output | --fileinput | --authorized-users-path | -${noargopts}[oF]) + _comp_compgen_filedir return ;; - --client | -!(-*)c) - _known_hosts_real -- "$cur" + --bind | -${noargopts}B) + _comp_compgen_available_interfaces -a + _comp_compgen -a ip_addresses -a return ;; - --reportexclude | -!(-*)x) - COMPREPLY=($(compgen -W 'C D M S V' -- "$cur")) + --bind-dev) + _comp_compgen_available_interfaces -a return ;; - --reportstyle | -!(-*)y) - COMPREPLY=($(compgen -W 'C' -- "$cur")) + --client | -${noargopts}c) + _comp_compgen_known_hosts -- "$cur" + return + ;; + --reportexclude | -${noargopts}x) + _comp_compgen -- -W 'C D M S V' + return + ;; + --reportstyle | -${noargopts}y) + _comp_compgen -- -W 'C' return ;; --logfile) - _filedir log + _comp_compgen_filedir log + return + ;; + --rsa-private-key-path | --rsa-public-key-path) + _comp_compgen_filedir pem return ;; esac - $split && return + [[ $was_split ]] && return # Filter mode specific options - local i filter=cat + local -a filter=(cat) + local i for i in "${words[@]}"; do case $i in -s | --server) - filter='command sed -e /^Client.specific/,/^\(Server.specific.*\)\?$/d' + filter=(command sed -e '/^Client.specific/,/^\(Server.specific.*\)\{0,1\}$/d') ;; -c | --client) - filter='command sed -e /^Server.specific/,/^\(Client.specific.*\)\?$/d' + filter=(command sed -e '/^Server.specific/,/^\(Client.specific.*\)\{0,1\}$/d') ;; esac done - [[ $filter != cat ]] && filter+=' -e /--client/d -e /--server/d' + [[ $filter != cat ]] && filter+=(-e '/--client/d' -e '/--server/d') - COMPREPLY=($(compgen -W \ - '$("$1" --help 2>&1 | $filter | _parse_help -)' -- "$cur")) + _comp_compgen_help - <<<"$("$1" --help 2>&1 | "${filter[@]}")" [[ ${COMPREPLY-} == *= ]] && compopt -o nospace } && - complete -F _iperf iperf iperf3 + complete -F _comp_cmd_iperf iperf iperf3 # ex: filetype=sh diff --git a/completions/ipmitool b/completions/ipmitool index 920287d..5d6c212 100644 --- a/completions/ipmitool +++ b/completions/ipmitool @@ -1,65 +1,61 @@ # bash completion for ipmitool -*- shell-script -*- -_ipmitool_singleline_help() +_comp_cmd_ipmitool__singleline_help() { - COMPREPLY=($(compgen -W "$($1 $2 2>&1 | - command sed -ne 's/[,\r]//g' -e 's/^.*[Cc]ommands://p')" -- "$cur")) + _comp_compgen_split -- "$("$1" "$2" 2>&1 | + command sed -ne 's/[,\r]//g' -e 's/^.*[Cc]ommands://p')" } -_ipmitool() +_comp_cmd_ipmitool() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*[hVpUekyPmbtBTl]) return ;; -*d) - COMPREPLY=($(compgen -W "$( - command ls -d /dev/ipmi* /dev/ipmi/* /dev/ipmidev/* \ - 2>/dev/null | command sed -ne 's/^[^0-9]*\([0-9]\{1,\}\)/\1/p' - )" \ - -- "$cur")) + local -a files + _comp_expand_glob files '/dev/ipmi* /dev/ipmi/* /dev/ipmidev/*' && + _comp_compgen -- -W '"${files[@]##*([^0-9])}"' -X '![0-9]*' return ;; -*I) - COMPREPLY=($(compgen -W "$($1 -h 2>&1 | + _comp_compgen_split -- "$("$1" -h 2>&1 | command sed -e '/^Interfaces:/,/^[[:space:]]*$/!d' \ - -ne 's/^[[:space:]]\{1,\}\([^[:space:]]\{1,\}\).*/\1/p')" \ - -- "$cur")) + -ne 's/^[[:space:]]\{1,\}\([^[:space:]]\{1,\}\).*/\1/p')" return ;; -*H) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -*[fSO]) - _filedir + _comp_compgen_filedir return ;; -*C) - COMPREPLY=($(compgen -W '{0..14}' -- "$cur")) + _comp_compgen -- -W '{0..14}' return ;; -*L) - COMPREPLY=($(compgen -W 'CALLBACK USER OPERATOR ADMINISTRATOR' \ - -- "$cur")) + _comp_compgen -- -W 'CALLBACK USER OPERATOR ADMINISTRATOR' return ;; -*A) - COMPREPLY=($(compgen -W 'NONE PASSWORD MD2 MD5 OEM' -- "$cur")) + _comp_compgen -- -W 'NONE PASSWORD MD2 MD5 OEM' return ;; -*o) - COMPREPLY=($(compgen -W "$($1 -o list 2>&1 | - awk '/^[ \t]+/ { print $1 }') list" -- "$cur")) + _comp_compgen_split -- "$("$1" -o list 2>&1 | + _comp_awk '/^[ \t]+/ { print $1 }') list" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur")) + _comp_compgen_help -- -h return fi @@ -68,16 +64,16 @@ _ipmitool() local cmds=(raw i2c spd lan chassis power event mc sdr sensor fru gendev sel pef sol tsol isol user channel session sunoem kontronoem picmg fwum firewall shell exec set hpm ekanalyzer) - local i c cmd subcmd - for ((i = 1; i < ${#words[@]} - 1; i++)); do - [[ -v cmd ]] && subcmd=${words[i]} && break + local i c cmd="" has_cmd="" subcmd + for ((i = 1; i < cword; i++)); do + [[ $has_cmd ]] && subcmd=${words[i]} && break for c in "${cmds[@]}"; do - [[ ${words[i]} == "$c" ]] && cmd=$c && break + [[ ${words[i]} == "$c" ]] && cmd=$c has_cmd=set && break done done - if [[ ! -v cmd ]]; then - COMPREPLY=($(compgen -W '${cmds[@]}' -- "$cur")) + if [[ ! $has_cmd ]]; then + _comp_compgen -- -W '"${cmds[@]}"' return fi @@ -87,13 +83,12 @@ _ipmitool() shell) ;; - \ - exec) - _filedir + exec) + _comp_compgen_filedir ;; chassis | power | kontronoem | fwum) - _ipmitool_singleline_help $1 $cmd + _comp_cmd_ipmitool__singleline_help "$1" "$cmd" ;; lan) @@ -102,15 +97,14 @@ _ipmitool() alert) [[ $prev == alert ]] && - COMPREPLY=($(compgen -W 'print set' -- "$cur")) + _comp_compgen -- -W 'print set' ;; stats) [[ $prev == stats ]] && - COMPREPLY=($(compgen -W 'print set' -- "$cur")) + _comp_compgen -- -W 'print set' ;; *) - COMPREPLY=($(compgen -W 'print set alert stats' \ - -- "$cur")) + _comp_compgen -- -W 'print set alert stats' ;; esac ;; @@ -120,25 +114,25 @@ _ipmitool() get | info | type | list | entity) ;; elist) - COMPREPLY=($(compgen -W 'all full compact event mclog fru - generic' -- "$cur")) + _comp_compgen -- -W 'all full compact event mclog fru + generic' ;; dump) - _filedir + _comp_compgen_filedir ;; fill) case $prev in fill) - COMPREPLY=($(compgen -W 'sensors file' -- "$cur")) + _comp_compgen -- -W 'sensors file' ;; file) - _filedir + _comp_compgen_filedir ;; esac ;; *) - COMPREPLY=($(compgen -W 'get info type list elist entity - dump fill' -- "$cur")) + _comp_compgen -- -W 'get info type list elist entity dump + fill' ;; esac ;; @@ -148,7 +142,7 @@ _ipmitool() list | get | thresh) ;; *) - COMPREPLY=($(compgen -W 'list get thresh' -- "$cur")) + _comp_compgen -- -W 'list get thresh' ;; esac ;; @@ -158,15 +152,15 @@ _ipmitool() info | clear | list | elist | delete) ;; add | save | writeraw | readraw) - _filedir + _comp_compgen_filedir ;; time) [[ $prev == time ]] && - COMPREPLY=($(compgen -W 'get set' -- "$cur")) + _comp_compgen -- -W 'get set' ;; *) - COMPREPLY=($(compgen -W 'info clear list elist delete add - get save writeraw readraw time' -- "$cur")) + _comp_compgen -- -W 'info clear list elist delete add get + save writeraw readraw time' ;; esac ;; @@ -177,23 +171,23 @@ _ipmitool() set) [[ $prev == set ]] && - COMPREPLY=($(compgen -W 'name password' -- "$cur")) + _comp_compgen -- -W 'name password' ;; *) - COMPREPLY=($(compgen -W 'summary list set disable enable - priv test' -- "$cur")) + _comp_compgen -- -W 'summary list set disable enable priv + test' ;; esac ;; set) [[ $prev == set ]] && - COMPREPLY=($(compgen -W 'hostname username password privlvl - authtype localaddr targetaddr port csv verbose' -- "$cur")) + _comp_compgen -- -W 'hostname username password privlvl + authtype localaddr targetaddr port csv verbose' ;; esac } && - complete -F _ipmitool ipmitool + complete -F _comp_cmd_ipmitool ipmitool # ex: filetype=sh diff --git a/completions/ipsec b/completions/ipsec index 4bc8cdf..6bd4ebf 100644 --- a/completions/ipsec +++ b/completions/ipsec @@ -3,87 +3,86 @@ # Complete ipsec.conf conn entries. # # Reads a file from stdin in the ipsec.conf(5) format. -_ipsec_connections() +_comp_cmd_ipsec__connections() { local keyword name while read -r keyword name; do if [[ $keyword == [#]* ]]; then continue; fi [[ $keyword == conn && $name != '%default' ]] && COMPREPLY+=("$name") done - COMPREPLY=($(compgen -W '${COMPREPLY[@]}' -- "$cur")) + ((${#COMPREPLY[@]})) && + _comp_compgen -- -W '"${COMPREPLY[@]}"' } -_ipsec_freeswan() +_comp_cmd_ipsec__freeswan() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if ((cword == 1)); then - COMPREPLY=($(compgen -W 'auto barf eroute klipsdebug look manual - pluto ranbits rsasigkey setup showdefaults showhostkey spi spigrp - tncfg whack' -- "$cur")) + _comp_compgen -- -W 'auto barf eroute klipsdebug look manual pluto + ranbits rsasigkey setup showdefaults showhostkey spi spigrp tncfg + whack' return fi case ${words[1]} in auto) - COMPREPLY=($(compgen -W '--asynchronous --up --add --delete - --replace --down --route --unroute --ready --status - --rereadsecrets' -- "$cur")) + _comp_compgen -- -W '--asynchronous --up --add --delete --replace + --down --route --unroute --ready --status --rereadsecrets' ;; manual) - COMPREPLY=($(compgen -W '--up --down --route --unroute --union' \ - -- "$cur")) + _comp_compgen -- -W '--up --down --route --unroute --union' ;; ranbits) - COMPREPLY=($(compgen -W '--quick --continuous --bytes' -- "$cur")) + _comp_compgen -- -W '--quick --continuous --bytes' ;; setup) - COMPREPLY=($(compgen -W '--start --stop --restart' -- "$cur")) + _comp_compgen -- -W '--start --stop --restart' ;; *) ;; esac } -_ipsec_strongswan() +_comp_cmd_ipsec__strongswan() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if ((cword == 1)); then - COMPREPLY=($(compgen -W 'down irdumm leases listaacerts listacerts - listalgs listall listcacerts listcainfos listcards listcerts - listcrls listgroups listocsp listocspcerts listpubkeys openac pki - pluto pool purgecerts purgecrls purgeike purgeocsp ready reload - rereadaacerts rereadacerts rereadall rereadcacerts rereadcrls - rereadgroups rereadocspcerts rereadsecrets restart route scdecrypt - scencrypt scepclient secrets start starter status statusall stop - stroke unroute uci up update version whack --confdir --copyright - --directory --help --version --versioncode' -- "$cur")) + _comp_compgen -- -W 'down irdumm leases listaacerts listacerts listalgs + listall listcacerts listcainfos listcards listcerts listcrls + listgroups listocsp listocspcerts listpubkeys openac pki pluto pool + purgecerts purgecrls purgeike purgeocsp ready reload rereadaacerts + rereadacerts rereadall rereadcacerts rereadcrls rereadgroups + rereadocspcerts rereadsecrets restart route scdecrypt scencrypt + scepclient secrets start starter status statusall stop stroke + unroute uci up update version whack --confdir --copyright + --directory --help --version --versioncode' return fi case ${words[1]} in down | route | status | statusall | unroute | up) local confdir=$(ipsec --confdir) - _ipsec_connections <"$confdir/ipsec.conf" + _comp_cmd_ipsec__connections <"$confdir/ipsec.conf" ;; list*) - COMPREPLY=($(compgen -W '--utc' -- "$cur")) + _comp_compgen -- -W '--utc' ;; restart | start) - COMPREPLY=($(compgen -W '--attach-gdb --auto-update --debug - --debug-all --debug-more --nofork' -- "$cur")) + _comp_compgen -- -W '--attach-gdb --auto-update --debug --debug-all + --debug-more --nofork' ;; pki) - COMPREPLY=($(compgen -W '--gen --issue --keyid --print --pub - --req --self --signcrl --verify' -- "$cur")) + _comp_compgen -- -W '--gen --issue --keyid --print --pub --req + --self --signcrl --verify' ;; pool) ;; irdumm) - _filedir 'rb' + _comp_compgen_filedir 'rb' ;; *) ;; @@ -92,10 +91,10 @@ _ipsec_strongswan() case "$(ipsec --version 2>/dev/null)" in *strongSwan*) - complete -F _ipsec_strongswan ipsec + complete -F _comp_cmd_ipsec__strongswan ipsec ;; *) - complete -F _ipsec_freeswan ipsec + complete -F _comp_cmd_ipsec__freeswan ipsec ;; esac diff --git a/completions/iptables b/completions/iptables index ffb905b..d0c0ec1 100644 --- a/completions/iptables +++ b/completions/iptables @@ -1,51 +1,55 @@ # bash completion for iptables -*- shell-script -*- -_iptables() +_comp_cmd_iptables() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return - local table chain='s/^Chain \([^ ]\{1,\}\).*$/\1/p' + local table="" chain='s/^Chain \([^ ]\{1,\}\).*$/\1/p' + local targets='ACCEPT DROP LOG ULOG REJECT' + local IFS=$' \t\n' # for ${table:+-t "$table"} [[ ${words[*]} =~ [[:space:]]-(t|-table=?)[[:space:]]*([^[:space:]]+) ]] && - table="-t ${BASH_REMATCH[2]}" + table=${BASH_REMATCH[2]} case $prev in -*[AIDRPFXLZ]) - COMPREPLY=($(compgen -W '`"$1" $table -nL 2>/dev/null | \ - command sed -ne "s/^Chain \([^ ]\{1,\}\).*$/\1/p"`' -- "$cur")) + _comp_compgen_split -- "$( + "$1" ${table:+-t "$table"} -nL 2>/dev/null | + command sed -ne 's/^Chain \([^ ]\{1,\}\).*$/\1/p' + )" ;; -*t) - COMPREPLY=($(compgen -W 'nat filter mangle' -- "$cur")) + _comp_compgen -- -W 'nat filter mangle' ;; -j) - if [[ $table == "-t filter" || -z $table ]]; then - COMPREPLY=($(compgen -W 'ACCEPT DROP LOG ULOG REJECT - `"$1" $table -nL 2>/dev/null | command sed -ne "$chain" \ - -e "s/INPUT|OUTPUT|FORWARD|PREROUTING|POSTROUTING//"`' -- \ - "$cur")) - elif [[ $table == "-t nat" ]]; then - COMPREPLY=($(compgen -W 'ACCEPT DROP LOG ULOG REJECT MIRROR SNAT - DNAT MASQUERADE `"$1" $table -nL 2>/dev/null | \ - command sed -ne "$chain" -e "s/OUTPUT|PREROUTING|POSTROUTING//"`' \ - -- "$cur")) - elif [[ $table == "-t mangle" ]]; then - COMPREPLY=($(compgen -W 'ACCEPT DROP LOG ULOG REJECT MARK TOS - `"$1" $table -nL 2>/dev/null | command sed -ne "$chain" \ - -e "s/INPUT|OUTPUT|FORWARD|PREROUTING|POSTROUTING//"`' -- \ - "$cur")) + if [[ $table == "filter" || ! $table ]]; then + _comp_compgen -- -W '$targets' + _comp_compgen -a split -- "$("$1" ${table:+-t "$table"} -nL \ + 2>/dev/null | command sed -ne "$chain" \ + -e 's/INPUT|OUTPUT|FORWARD|PREROUTING|POSTROUTING//')" + elif [[ $table == "nat" ]]; then + _comp_compgen -- -W '$targets MIRROR SNAT DNAT MASQUERADE' + _comp_compgen -a split -- "$("$1" -t "$table" -nL 2>/dev/null | + command sed -ne "$chain" \ + -e 's/OUTPUT|PREROUTING|POSTROUTING//')" + elif [[ $table == "mangle" ]]; then + _comp_compgen -- -W '$targets MARK TOS' + _comp_compgen -a split -- "$("$1" -t "$table" -nL 2>/dev/null | + command sed -ne "$chain" \ + -e 's/INPUT|OUTPUT|FORWARD|PREROUTING|POSTROUTING//')" fi ;; *) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$("$1" --help 2>&1 | - command sed -e "s/^\[\!\]//" | _parse_help -)' -- "$cur")) + _comp_compgen_help - <<<"$("$1" --help 2>&1 | + command sed -e "s/^\[\!\]//")" [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi ;; esac } && - complete -F _iptables iptables + complete -F _comp_cmd_iptables iptables # ex: filetype=sh diff --git a/completions/ipv6calc b/completions/ipv6calc index c452c15..7cf7d82 100644 --- a/completions/ipv6calc +++ b/completions/ipv6calc @@ -1,23 +1,24 @@ # ipv6calc completion -*- shell-script -*- -_ipv6calc() +_comp_cmd_ipv6calc() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[dIOA]*)' + # shellcheck disable=SC2254 case "$prev" in - --debug | -!(-*)d) + --debug | -${noargopts}d) return ;; - --in | --out | --action | -!(-*)[IOA]) + --in | --out | --action | -${noargopts}[IOA]) # With ipv6calc < 0.73.0, -m does nothing here, so use sed instead. - COMPREPLY=($(compgen -W "$($1 "$prev" -h 2>&1 | - command sed -ne 's/^[[:space:]]\{1,\}\([^[:space:]:]\{1,\}\)[[:space:]]*:.*/\1/p')" \ - -- "$cur")) + _comp_compgen_split -- "$("$1" "$prev" -h 2>&1 | + command sed -ne 's/^[[:space:]]\{1,\}\([^[:space:]:]\{1,\}\)[[:space:]]*:.*/\1/p')" return ;; --db-geoip | --db-ip2location-ipv4 | --db-ip2location-ipv6) - _filedir + _comp_compgen_filedir return ;; --printstart | --printend) @@ -25,14 +26,14 @@ _ipv6calc() ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$("$1" -h 2>&1 | - command sed -e "s/[][]//g" | _parse_help -)' -- "$cur")) + _comp_compgen_help - <<<"$("$1" -h 2>&1 | + command sed -e "s/[][]//g")" fi } && - complete -F _ipv6calc ipv6calc + complete -F _comp_cmd_ipv6calc ipv6calc # ex: filetype=sh diff --git a/completions/iscsiadm b/completions/iscsiadm index 7786ddc..84cc817 100644 --- a/completions/iscsiadm +++ b/completions/iscsiadm @@ -1,31 +1,32 @@ # iscsiadm(1) completion -*- shell-script -*- -_iscsiadm() +_comp_cmd_iscsiadm() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[motLU]*)' + # shellcheck disable=SC2254 case $prev in - --mode | -!(-*)m) - COMPREPLY=($(compgen -W 'discovery node session iface fw host' \ - -- "$cur")) + --mode | -${noargopts}m) + _comp_compgen -- -W 'discovery node session iface fw host' return ;; - --op | -!(-*)o) - COMPREPLY=($(compgen -W 'new delete update show' -- "$cur")) + --op | -${noargopts}o) + _comp_compgen -- -W 'new delete update show' return ;; - --type | -!(-*)t) - COMPREPLY=($(compgen -W 'sendtargets st slp isns fw' -- "$cur")) + --type | -${noargopts}t) + _comp_compgen -- -W 'sendtargets st slp isns fw' return ;; - --loginall | --logoutall | -!(-*)[LU]) - COMPREPLY=($(compgen -W 'all manual automatic' -- "$cur")) + --loginall | --logoutall | -${noargopts}[LU]) + _comp_compgen -- -W 'all manual automatic' return ;; esac - $split && return + [[ $was_split ]] && return local options if ((cword > 1)); then @@ -59,8 +60,8 @@ _iscsiadm() options='--mode' fi - COMPREPLY=($(compgen -W "$options" -- "$cur")) + _comp_compgen -- -W "$options" } && - complete -F _iscsiadm iscsiadm + complete -F _comp_cmd_iscsiadm iscsiadm # ex: filetype=sh diff --git a/completions/isort b/completions/isort index 2a84e25..a5c6dff 100644 --- a/completions/isort +++ b/completions/isort @@ -1,9 +1,9 @@ # isort completion -*- shell-script -*- -_isort() +_comp_cmd_isort() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --help | --add-import | --builtin | --future | --from-first | -ff | \ @@ -15,27 +15,29 @@ _isort() return ;; --jobs | -j) - COMPREPLY=($(compgen -W "{1..$(_ncpus)}" -- "$cur")) + local REPLY + _comp_get_ncpus + _comp_compgen -- -W "{1..$REPLY}" return ;; --multi-line | -m) - COMPREPLY=($(compgen -W '{0..5}' -- "$cur")) + _comp_compgen -- -W '{0..5}' return ;; --section-default | -sd) - COMPREPLY=($(compgen -W 'FUTURE STDLIB THIRDPARTY FIRSTPARTY - LOCALFOLDER' -- "$cur")) + _comp_compgen -- -W 'FUTURE STDLIB THIRDPARTY FIRSTPARTY + LOCALFOLDER' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - _filedir '@(py|pyi)' + _comp_compgen_filedir '@(py|pyi)' } && - complete -F _isort isort + complete -F _comp_cmd_isort isort # ex: filetype=sh diff --git a/completions/isql b/completions/isql index 4258c51..11dd654 100644 --- a/completions/isql +++ b/completions/isql @@ -1,14 +1,16 @@ # isql completion -*- shell-script -*- # by Victor Bogado da Silva Lins <victor@bogado.net> -_isql() +_comp_cmd_isql() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - [[ -f $ODBCINI ]] && - COMPREPLY=($(command grep "\[$cur" "$ODBCINI" | tr -d \[\])) + [[ -f ${ODBCINI-} ]] && + _comp_compgen_split -l -- "$( + command sed -n 's/\]//g;s/^\[//gp' "$ODBCINI" + )" } && - complete -F _isql isql + complete -F _comp_cmd_isql isql # ex: filetype=sh diff --git a/completions/iwconfig b/completions/iwconfig index aa8fbf3..7fbc985 100644 --- a/completions/iwconfig +++ b/completions/iwconfig @@ -1,90 +1,90 @@ # iwconfig completion -*- shell-script -*- -_iwconfig() +_comp_deprecate_var 2.12 \ + COMP_IWLIST_SCAN BASH_COMPLETION_CMD_IWCONFIG_SCAN + +_comp_cmd_iwconfig() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in mode) - COMPREPLY=($(compgen -W 'managed ad-hoc master repeater secondary - monitor' -- "$cur")) + _comp_compgen -- -W 'managed ad-hoc master repeater secondary + monitor' return ;; essid) - COMPREPLY=($(compgen -W 'on off any' -- "$cur")) - if [[ -n ${COMP_IWLIST_SCAN:-} ]]; then - COMPREPLY+=($(compgen -W \ - "$(iwlist ${words[1]} scan | - awk -F'\"' '/ESSID/ {print $2}')" -- "$cur")) + _comp_compgen -- -W 'on off any' + if [[ ${BASH_COMPLETION_CMD_IWCONFIG_SCAN-} ]]; then + _comp_compgen -a split -- "$(iwlist "${words[1]}" scan | + _comp_awk -F '\"' '/ESSID/ {print $2}')" fi return ;; nwid) - COMPREPLY=($(compgen -W 'on off' -- "$cur")) + _comp_compgen -- -W 'on off' return ;; channel) - COMPREPLY=($(compgen -W "$(iwlist ${words[1]} channel | - awk '/^[ \t]*Channel/ {print $2}')" -- "$cur")) + _comp_compgen_split -- "$(iwlist "${words[1]}" channel | + _comp_awk '/^[ \t]*Channel/ {print $2}')" return ;; freq) - COMPREPLY=($(compgen -W "$(iwlist ${words[1]} channel | - awk '/^[ \t]*Channel/ {print $4"G"}')" -- "$cur")) + _comp_compgen_split -- "$(iwlist "${words[1]}" channel | + _comp_awk '/^[ \t]*Channel/ {print $4"G"}')" return ;; ap) - COMPREPLY=($(compgen -W 'on off any' -- "$cur")) - if [[ -n ${COMP_IWLIST_SCAN:-} ]]; then - COMPREPLY+=($(compgen -W \ - "$(iwlist ${words[1]} scan | - awk -F ': ' '/Address/ {print $2}')" -- "$cur")) + _comp_compgen -- -W 'on off any' + if [[ ${BASH_COMPLETION_CMD_IWCONFIG_SCAN-} ]]; then + _comp_compgen -a split -- "$(iwlist "${words[1]}" scan | + _comp_awk -F ': ' '/Address/ {print $2}')" fi return ;; rate) - COMPREPLY=($(compgen -W 'auto fixed' -- "$cur")) - COMPREPLY+=($(compgen -W \ - "$(iwlist ${words[1]} rate | - awk '/^[ \t]*[0-9]/ {print $1"M"}')" -- "$cur")) + _comp_compgen -- -W 'auto fixed' + _comp_compgen -a split -- "$(iwlist "${words[1]}" rate | + _comp_awk '/^[ \t]*[0-9]/ {print $1"M"}')" return ;; rts | frag) - COMPREPLY=($(compgen -W 'auto fixed off' -- "$cur")) + _comp_compgen -- -W 'auto fixed off' return ;; key | enc) - COMPREPLY=($(compgen -W 'off on open restricted' -- "$cur")) + _comp_compgen -- -W 'off on open restricted' return ;; power) - COMPREPLY=($(compgen -W 'period timeout off on' -- "$cur")) + _comp_compgen -- -W 'period timeout off on' return ;; txpower) - COMPREPLY=($(compgen -W 'off on auto' -- "$cur")) + _comp_compgen -- -W 'off on auto' return ;; retry) - COMPREPLY=($(compgen -W 'limit lifetime' -- "$cur")) + _comp_compgen -- -W 'limit lifetime' return ;; esac if ((cword == 1)); then if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--help --version' -- "$cur")) + _comp_compgen -- -W '--help --version' else - _available_interfaces -w + _comp_compgen_available_interfaces -w fi else - COMPREPLY=($(compgen -W 'essid nwid mode freq channel sens mode ap - nick rate rts frag enc key power txpower commit' -- "$cur")) + _comp_compgen -- -W 'essid nwid mode freq channel sens mode ap nick + rate rts frag enc key power txpower commit' fi } && - complete -F _iwconfig iwconfig + complete -F _comp_cmd_iwconfig iwconfig # ex: filetype=sh diff --git a/completions/iwlist b/completions/iwlist index 16aa39c..efac3e6 100644 --- a/completions/iwlist +++ b/completions/iwlist @@ -1,22 +1,22 @@ # iwlist completion -*- shell-script -*- -_iwlist() +_comp_cmd_iwlist() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if ((cword == 1)); then if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--help --version' -- "$cur")) + _comp_compgen -- -W '--help --version' else - _available_interfaces -w + _comp_compgen_available_interfaces -w fi else - COMPREPLY=($(compgen -W 'scan scanning freq frequency channel rate - bit bitrate key enc encryption power txpower retry ap accesspoint - peers event' -- "$cur")) + _comp_compgen -- -W 'scan scanning freq frequency channel rate bit + bitrate key enc encryption power txpower retry ap accesspoint peers + event' fi } && - complete -F _iwlist iwlist + complete -F _comp_cmd_iwlist iwlist # ex: filetype=sh diff --git a/completions/iwpriv b/completions/iwpriv index 4e38246..518a22a 100644 --- a/completions/iwpriv +++ b/completions/iwpriv @@ -1,31 +1,31 @@ # iwpriv completion -*- shell-script -*- -_iwpriv() +_comp_cmd_iwpriv() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in roam) - COMPREPLY=($(compgen -W 'on off' -- "$cur")) + _comp_compgen -- -W 'on off' return ;; port) - COMPREPLY=($(compgen -W 'ad-hoc managed' -- "$cur")) + _comp_compgen -- -W 'ad-hoc managed' return ;; esac if ((cword == 1)); then if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--help --version' -- "$cur")) + _comp_compgen -- -W '--help --version' else - _available_interfaces -w + _comp_compgen_available_interfaces -w fi else - COMPREPLY=($(compgen -W '--all roam port' -- "$cur")) + _comp_compgen -- -W '--all roam port' fi } && - complete -F _iwpriv iwpriv + complete -F _comp_cmd_iwpriv iwpriv # ex: filetype=sh diff --git a/completions/iwspy b/completions/iwspy index 38b7868..e097d95 100644 --- a/completions/iwspy +++ b/completions/iwspy @@ -1,20 +1,20 @@ # iwspy completion -*- shell-script -*- -_iwspy() +_comp_cmd_iwspy() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if ((cword == 1)); then if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--help --version' -- "$cur")) + _comp_compgen -- -W '--help --version' else - _available_interfaces -w + _comp_compgen_available_interfaces -w fi else - COMPREPLY=($(compgen -W 'setthr getthr off' -- "$cur")) + _comp_compgen -- -W 'setthr getthr off' fi } && - complete -F _iwspy iwspy + complete -F _comp_cmd_iwspy iwspy # ex: filetype=sh diff --git a/completions/jar b/completions/jar index 2289491..d01a8a4 100644 --- a/completions/jar +++ b/completions/jar @@ -1,27 +1,27 @@ # jar(1) completion -*- shell-script -*- -_jar() +_comp_cmd_jar() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if ((cword == 1)); then - COMPREPLY=($(compgen -W 'c t x u' -- "$cur")) + _comp_compgen -- -W 'c t x u' return fi case ${words[1]} in *c*f) - _filedir + _comp_compgen_filedir ;; *f) - _filedir_xspec unzip + _comp_compgen_filedir_xspec unzip ;; *) - _filedir + _comp_compgen_filedir ;; esac } && - complete -F _jar jar + complete -F _comp_cmd_jar jar # ex: filetype=sh diff --git a/completions/jarsigner b/completions/jarsigner index 1f26c9c..ebc6cf8 100644 --- a/completions/jarsigner +++ b/completions/jarsigner @@ -1,14 +1,14 @@ # jarsigner(1) completion -*- shell-script -*- -_jarsigner() +_comp_cmd_jarsigner() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -keystore) - COMPREPLY=($(compgen -W 'NONE' -- "$cur")) - _filedir '@(jks|ks|p12|pfx)' + _comp_compgen -- -W 'NONE' + _comp_compgen -a filedir '@(jks|ks|p12|pfx)' return ;; -storepass | -keypass | -sigfile | -digestalg | -sigalg | -tsacert | -tsapolicyid | \ @@ -17,41 +17,40 @@ _jarsigner() return ;; -certchain | -tsa) - _filedir + _comp_compgen_filedir return ;; -storetype) - COMPREPLY=($(compgen -W 'JKS PKCS11 PKCS12' -- "$cur")) + _comp_compgen -- -W 'JKS PKCS11 PKCS12' return ;; -signedjar) - _filedir '@(jar|apk)' + _comp_compgen_filedir '@(jar|apk)' return ;; esac # Check if a jar was already given. - local i jar=false - for ((i = 1; i < ${#words[@]} - 1; i++)); do - if [[ ${words[i]} == *.@(jar|apk) && \ + local i jar="" + for ((i = 1; i < cword; i++)); do + if [[ ${words[i]} == *.@(jar|apk) && ${words[i - 1]} != -signedjar ]]; then - jar=true + jar=set break fi done - if ! $jar; then + if [[ ! $jar ]]; then if [[ $cur == -* ]]; then # Documented as "should not be used": -internalsf, -sectionsonly - COMPREPLY=($(compgen -W '-keystore -storepass -storetype - -keypass -sigfile -signedjar -digestalg -sigalg -verify - -verbose -certs -tsa -tsacert -altsigner -altsignerpath - -protected -providerName -providerClass -providerArg' \ - -- "$cur")) + _comp_compgen -- -W '-keystore -storepass -storetype -keypass + -sigfile -signedjar -digestalg -sigalg -verify -verbose -certs + -tsa -tsacert -altsigner -altsignerpath -protected + -providerName -providerClass -providerArg' fi - _filedir '@(jar|apk)' + _comp_compgen -a filedir '@(jar|apk)' fi } && - complete -F _jarsigner jarsigner + complete -F _comp_cmd_jarsigner jarsigner # ex: filetype=sh diff --git a/completions/java b/completions/java index d0f70ae..8ddcfaf 100644 --- a/completions/java +++ b/completions/java @@ -1,86 +1,93 @@ # bash completion for java, javac and javadoc -*- shell-script -*- # available path elements completion -_java_path() +_comp_cmd_java__classpath() { - cur=${cur##*:} - _filedir '@(jar|zip)' + _comp_compgen -c "${cur##*:}" filedir '@(jar|zip)' } # exact classpath determination -_java_find_classpath() +# @var[out] REPLY Array to store classpaths +# @return 0 if at least one element is generated, or otherwise 1 +_comp_cmd_java__find_classpath() { local i + REPLY= + # search first in current options for ((i = 1; i < cword; i++)); do if [[ ${words[i]} == -@(cp|classpath) ]]; then - classpath=${words[i + 1]} + REPLY=${words[i + 1]} break fi done - # default to environment - [[ ! -v classpath ]] && classpath=${CLASSPATH-} - - # default to current directory - [[ -z $classpath ]] && classpath=. + # fall back to environment, followed by current directory + _comp_split -F : REPLY "${REPLY:-${CLASSPATH:-.}}" } # exact sourcepath determination -_java_find_sourcepath() +# @var[out] REPLY Array to store sourcepaths +# @return 0 if at least one element is generated, or otherwise 1 +_comp_cmd_java__find_sourcepath() { local i + REPLY= + # search first in current options for ((i = 1; i < cword; i++)); do if [[ ${words[i]} == -sourcepath ]]; then - sourcepath=${words[i + 1]} + REPLY=${words[i + 1]} break fi done - # default to classpath - if [[ ! -v sourcepath ]]; then - local classpath - _java_find_classpath - sourcepath=$classpath + # fall back to classpath + if [[ ! $REPLY ]]; then + _comp_cmd_java__find_classpath + return fi + + _comp_split -F : REPLY "$REPLY" } # available classes completion -_java_classes() +_comp_cmd_java__classes() { - local classpath i + local REPLY i # find which classpath to use - _java_find_classpath + _comp_cmd_java__find_classpath + local -a classpaths=("${REPLY[@]}") + local -a classes=() # convert package syntax to path syntax - cur=${cur//.//} + local cur=${cur//.//} # parse each classpath element for classes - for i in ${classpath//:/ }; do + for i in "${classpaths[@]}"; do if [[ $i == *.@(jar|zip) && -r $i ]]; then if type zipinfo &>/dev/null; then - COMPREPLY+=($(zipinfo -1 "$i" "$cur*" 2>/dev/null | - command grep '^[^$]*\.class$')) + _comp_split -a classes "$(zipinfo -1 "$i" "$cur*" 2>/dev/null | + command grep '^[^$]*\.class$')" elif type unzip &>/dev/null; then # Last column, between entries consisting entirely of dashes - COMPREPLY+=($(unzip -lq "$i" "$cur*" 2>/dev/null | - awk '$NF ~ /^-+$/ { flag=!flag; next }; - flag && $NF ~ /^[^$]*\.class/ { print $NF }')) + _comp_split -a classes "$(unzip -lq "$i" "$cur*" 2>/dev/null | + _comp_awk '$NF ~ /^-+$/ { flag=!flag; next }; + flag && $NF ~ /^[^$]*\.class/ { print $NF }')" elif type jar &>/dev/null; then - COMPREPLY+=($(jar tf "$i" "$cur" | - command grep '^[^$]*\.class$')) + _comp_split -a classes "$(jar tf "$i" "$cur" | + command grep '^[^$]*\.class$')" fi elif [[ -d $i ]]; then - COMPREPLY+=( - $(compgen -d -- "$i/$cur" | command sed -e "s|^$i/\(.*\)|\1.|") - $(compgen -f -X '!*.class' -- "$i/$cur" | - command sed -e '/\$/d' -e "s|^$i/||") - ) - [[ ${COMPREPLY-} == *.class ]] || compopt -o nospace + local tmp + _comp_compgen -v tmp -c "$i/$cur" -- -d -S . + _comp_compgen -av tmp -c "$i/$cur" -- -f -X '!*.class' + ((${#tmp[@]})) && + _comp_compgen -av classes -- -X '*\$*' -W '"${tmp[@]#$i/}"' + [[ ${classes-} == *.class ]] || compopt -o nospace # FIXME: if we have foo.class and foo/, the completion # returns "foo/"... how to give precedence to files @@ -88,47 +95,50 @@ _java_classes() fi done - if ((${#COMPREPLY[@]} != 0)); then + if ((${#classes[@]} != 0)); then # remove class extension - COMPREPLY=(${COMPREPLY[@]%.class}) + classes=("${classes[@]%.class}") # convert path syntax to package syntax - COMPREPLY=(${COMPREPLY[@]//\//.}) + classes=("${classes[@]//\//.}") + _comp_compgen -U classes -- -W '"${classes[@]}"' fi } # available packages completion -_java_packages() +_comp_cmd_java__packages() { - local sourcepath i + local REPLY i files # find which sourcepath to use - _java_find_sourcepath + _comp_cmd_java__find_sourcepath || return 0 + local -a sourcepaths=("${REPLY[@]}") # convert package syntax to path syntax - cur=${cur//.//} + local cur=${cur//.//} # parse each sourcepath element for packages - for i in ${sourcepath//:/ }; do + for i in "${sourcepaths[@]}"; do if [[ -d $i ]]; then - COMPREPLY+=($(command ls -F -d $i/$cur* 2>/dev/null | - command sed -e 's|^'$i'/||')) + _comp_expand_glob files '"$i/$cur"*' || continue + _comp_split -la COMPREPLY "$( + command ls -F -d "${files[@]}" 2>/dev/null | + command sed -e 's|^'"$i"'/||' + )" fi done if ((${#COMPREPLY[@]} != 0)); then - # keep only packages - COMPREPLY=($(tr " " "\n" <<<"${COMPREPLY[@]}" | command grep "/$")) - # remove packages extension - COMPREPLY=(${COMPREPLY[@]%/}) + # keep only packages with the package suffix `/` being removed + _comp_split -l COMPREPLY "$(printf '%s\n' "${COMPREPLY[@]}" | command sed -n 's,/$,,p')" # convert path syntax to package syntax - cur="${COMPREPLY[*]//\//.}" + ((${#COMPREPLY[@]})) && COMPREPLY=("${COMPREPLY[@]//\//.}") fi } # java completion # -_java() +_comp_cmd_java() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return local i @@ -142,7 +152,7 @@ _java() ;; *) # once we've seen a class, just do filename completion - _filedir + _comp_compgen_filedir return ;; esac @@ -151,59 +161,55 @@ _java() case $cur in # standard option completions -verbose:*) - COMPREPLY=($(compgen -W 'class gc jni' -- "${cur#*:}")) + _comp_compgen -c "${cur#*:}" -- -W 'class gc jni' return ;; -javaagent:*) - cur=${cur#*:} - _filedir '@(jar|zip)' + _comp_compgen -c "${cur#*:}" filedir '@(jar|zip)' return ;; -agentpath:*) - cur=${cur#*:} - _filedir so + _comp_compgen -c "${cur#*:}" filedir so return ;; # various non-standard option completions -splash:*) - cur=${cur#*:} - _filedir '@(gif|jp?(e)g|png)' + _comp_compgen -c "${cur#*:}" filedir '@(gif|jp?(e)g|png)' return ;; -Xbootclasspath*:*) - _java_path + _comp_cmd_java__classpath return ;; -Xcheck:*) - COMPREPLY=($(compgen -W 'jni' -- "${cur#*:}")) + _comp_compgen -c "${cur#*:}" -- -W 'jni' return ;; -Xgc:*) - COMPREPLY=($(compgen -W 'singlecon gencon singlepar genpar' \ - -- "${cur#*:}")) + _comp_compgen -c "${cur#*:}" -- -W 'singlecon gencon singlepar + genpar' return ;; -Xgcprio:*) - COMPREPLY=($(compgen -W 'throughput pausetime deterministic' \ - -- "${cur#*:}")) + _comp_compgen -c "${cur#*:}" -- -W 'throughput pausetime + deterministic' return ;; -Xloggc:* | -Xverboselog:*) - cur=${cur#*:} - _filedir + _comp_compgen -c "${cur#*:}" filedir return ;; -Xshare:*) - COMPREPLY=($(compgen -W 'auto off on' -- "${cur#*:}")) + _comp_compgen -c "${cur#*:}" -- -W 'auto off on' return ;; -Xverbose:*) - COMPREPLY=($(compgen -W 'memory load jni cpuinfo codegen opt - gcpause gcreport' -- "${cur#*:}")) + _comp_compgen -c "${cur#*:}" -- -W 'memory load jni cpuinfo codegen + opt gcpause gcreport' return ;; -Xverify:*) - COMPREPLY=($(compgen -W 'all none remote' -- "${cur#*:}")) + _comp_compgen -c "${cur#*:}" -- -W 'all none remote' return ;; # the rest that we have no completions for @@ -214,39 +220,39 @@ _java() case $prev in -cp | -classpath) - _java_path + _comp_cmd_java__classpath return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help [[ $cur == -X* ]] && - COMPREPLY+=($(compgen -W '$(_parse_help "$1" -X)' -- "$cur")) + _comp_compgen -a help -- -X else if [[ $prev == -jar ]]; then # jar file completion - _filedir '[jw]ar' + _comp_compgen_filedir '[jw]ar' else # classes completion - _java_classes + _comp_cmd_java__classes fi fi [[ ${COMPREPLY-} == -*[:=] ]] && compopt -o nospace - __ltrim_colon_completions "$cur" + _comp_ltrim_colon_completions "$cur" } && - complete -F _java java + complete -F _comp_cmd_java java -_javadoc() +_comp_cmd_javadoc() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -overview | -helpfile) - _filedir '?(x)htm?(l)' + _comp_compgen_filedir '?(x)htm?(l)' return ;; -doclet | -exclude | -subpackages | -source | -locale | -encoding | -windowtitle | \ @@ -255,49 +261,49 @@ _javadoc() return ;; -stylesheetfile) - _filedir css + _comp_compgen_filedir css return ;; -d | -link | -linkoffline) - _filedir -d + _comp_compgen_filedir -d return ;; -classpath | -cp | -bootclasspath | -docletpath | -sourcepath | -extdirs | \ -excludedocfilessubdir) - _java_path + _comp_cmd_java__classpath return ;; esac # -linkoffline takes two arguments if [[ $cword -gt 2 && ${words[cword - 2]} == -linkoffline ]]; then - _filedir -d + _comp_compgen_filedir -d return fi if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help else # source files completion - _filedir java + _comp_compgen_filedir java # packages completion - _java_packages + _comp_cmd_java__packages fi } && - complete -F _javadoc javadoc + complete -F _comp_cmd_javadoc javadoc -_javac() +_comp_cmd_javac() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return case $prev in -d) - _filedir -d + _comp_compgen_filedir -d return ;; -cp | -classpath | -bootclasspath | -sourcepath | -extdirs) - _java_path + _comp_cmd_java__classpath return ;; esac @@ -311,23 +317,23 @@ _javac() # the others. local opts=$("$1" $helpopt 2>&1 | command sed -e 's/-g:none/-g:{none}/' -ne \ "s/^[[:space:]]*${cur%%:*}:{\([^}]\{1,\}\)}.*/\1/p") - COMPREPLY=($(compgen -W "${opts//,/ }" -- "${cur#*:}")) + _comp_compgen -c "${cur#*:}" -- -W "${opts//,/ }" return fi if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help [[ $cur == -X* ]] && - COMPREPLY+=($(compgen -W '$(_parse_help "$1" -X)' -- "$cur")) + _comp_compgen -a help -- -X else # source files completion - _filedir java + _comp_compgen_filedir java fi [[ ${COMPREPLY-} == -*[:=] ]] && compopt -o nospace - __ltrim_colon_completions "$cur" + _comp_ltrim_colon_completions "$cur" } && - complete -F _javac javac + complete -F _comp_cmd_javac javac # ex: filetype=sh diff --git a/completions/javaws b/completions/javaws index f42a1e5..cd6c848 100644 --- a/completions/javaws +++ b/completions/javaws @@ -1,20 +1,20 @@ # javaws(1) completion -*- shell-script -*- -_javaws() +_comp_cmd_javaws() { - local cur prev words cword - _init_completion -n = || return + local cur prev words cword comp_args + _comp_initialize -n = -- "$@" || return case $prev in -help | -license | -about | -viewer | -arg | -param | -property | -update | -umask) return ;; -basedir | -codebase) - _filedir -d + _comp_compgen_filedir -d return ;; -uninstall | -import) - _filedir jnlp + _comp_compgen_filedir jnlp return ;; esac @@ -22,13 +22,13 @@ _javaws() if [[ $cur == *= ]]; then return elif [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W "$(_parse_help "$1" -help) " -- "$cur")) + _comp_compgen_help -- -help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir jnlp + _comp_compgen_filedir jnlp } && - complete -F _javaws javaws + complete -F _comp_cmd_javaws javaws # ex: filetype=sh diff --git a/completions/jpegoptim b/completions/jpegoptim index c366972..7409854 100644 --- a/completions/jpegoptim +++ b/completions/jpegoptim @@ -1,38 +1,40 @@ # jpegoptim(1) completion -*- shell-script -*- -_jpegoptim() +_comp_cmd_jpegoptim() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[dmTS]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | -!(-*)[hV]*) + --help | --version | -${noargopts}[hV]*) return ;; - --dest | -!(-*)d) - _filedir -d + --dest | -${noargopts}d) + _comp_compgen_filedir -d return ;; - --max | --threshold | -!(-*)[mT]) - COMPREPLY=($(compgen -W '{0..100}' -- "$cur")) + --max | --threshold | -${noargopts}[mT]) + _comp_compgen -- -W '{0..100}' return ;; - --size | -!(-*)S) - COMPREPLY=($(compgen -W '{1..99}%' -- "$cur")) + --size | -${noargopts}S) + _comp_compgen -- -W '{1..99}%' return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir 'jp?(e)g' + _comp_compgen_filedir 'jp?(e)g' } && - complete -F _jpegoptim jpegoptim + complete -F _comp_cmd_jpegoptim jpegoptim # ex: filetype=sh diff --git a/completions/jps b/completions/jps index a451eec..324ba0e 100644 --- a/completions/jps +++ b/completions/jps @@ -1,9 +1,9 @@ # jps(1) completion -*- shell-script -*- -_jps() +_comp_cmd_jps() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -J* | -help) @@ -12,14 +12,14 @@ _jps() esac if [[ $cur == -* ]]; then - # Not using _parse_usage because output has [-help] which does not - # mean -h, -e, -l, -p... - COMPREPLY=($(compgen -W "-q -m -l -v -V -J -help" -- "$cur")) + # Not using _comp_compgen_usage because output has [-help] which does + # not mean -h, -e, -l, -p... + _comp_compgen -- -W "-q -m -l -v -V -J -help" [[ ${COMPREPLY-} == -J* ]] && compopt -o nospace else - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" fi } && - complete -F _jps jps + complete -F _comp_cmd_jps jps # ex: filetype=sh diff --git a/completions/jq b/completions/jq index 2d99c39..7021d2a 100644 --- a/completions/jq +++ b/completions/jq @@ -1,24 +1,26 @@ # jq(1) completion -*- shell-script -*- -_jq() +_comp_cmd_jq() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[fL]*)' + # shellcheck disable=SC2254 case $prev in --help | --version | --arg | --argjson | --slurpfile | --argfile) return ;; --indent) - COMPREPLY=($(compgen -W '{1..8}' -- "$cur")) + _comp_compgen -- -W '{1..8}' return ;; - --from-file | --run-tests | -!(-*)f) - _filedir + --from-file | --run-tests | -${noargopts}f) + _comp_compgen_filedir return ;; - -!(-*)L) - _filedir -d + -${noargopts}L) + _comp_compgen_filedir -d return ;; esac @@ -29,26 +31,49 @@ _jq() return ;; --slurpfile | --argfile) - _filedir json + _comp_compgen_filedir 'json?(l)' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + # Get jq's --help output and see whether it mentions --help + # jq's --help only shows some of its command-line options; some are not + # even listed in the man page! + local help_output=$("$1" --help 2>/dev/null) + + if [[ $help_output == *--help* ]]; then + # If the output of --help seems complete, use it + _comp_compgen_help - <<<"$help_output" + else + # Otherwise, use a hard-coded list of known flags, some of which do + # not appear in the output of --help as of jq 1.6. + _comp_compgen -- -W '--version --seq --stream --slurp --raw-input + --null-input --compact-output --tab --indent --color-output + -monochrome-output --ascii-output --unbuffered --sort-keys + --raw-output --join-output --from-file --exit-status --arg + --argjson --slurpfile --rawfile --argfile --args --jsonargs + --run-tests --help' + fi return fi - local args + local word + for word in "${words[@]}"; do + [[ $word != --?(json)args ]] || return + done + + local REPLY # TODO: DTRT with args taking 2 options - _count_args "" "@(--arg|--arg?(json|file)|--?(slurp|from-)file|--indent|--run-tests|-!(-*)[fL])" + # -f|--from-file are not counted here because they supply the filter + _comp_count_args -a "@(--arg|--arg?(json|file)|--slurpfile|--indent|--run-tests|-${noargopts}L)" # 1st arg is filter - ((args == 1)) && return + ((REPLY == 1)) && return # 2... are input files - _filedir json + _comp_compgen_filedir 'json?(l)' } && - complete -F _jq jq + complete -F _comp_cmd_jq jq # ex: filetype=sh diff --git a/completions/jshint b/completions/jshint index 3622cec..27a529e 100644 --- a/completions/jshint +++ b/completions/jshint @@ -1,38 +1,38 @@ # bash completion for jshint -*- shell-script -*- -_jshint() +_comp_cmd_jshint() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -v | --version | -h | --help | --exclude | --filename | -e | --extra-ext) return ;; -c | --config) - _filedir + _comp_compgen_filedir return ;; --reporter) - COMPREPLY=($(compgen -W "jslint checkstyle unix" -- "$cur")) + _comp_compgen -- -W "jslint checkstyle unix" return ;; --extract) - COMPREPLY=($(compgen -W "auto always never" -- "$cur")) + _comp_compgen -- -W "auto always never" return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir js + _comp_compgen_filedir js } && - complete -F _jshint jshint + complete -F _comp_cmd_jshint jshint # ex: filetype=sh diff --git a/completions/json_xs b/completions/json_xs index c93ba86..d894526 100644 --- a/completions/json_xs +++ b/completions/json_xs @@ -1,21 +1,20 @@ # json_xs completion -*- shell-script -*- -_json_xs() +_comp_cmd_json_xs() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*f) - COMPREPLY=($(compgen -W 'json cbor storable storable-file bencode - clzf eval yaml string none' -- "$cur")) + _comp_compgen -- -W 'json cbor storable storable-file bencode clzf + eval yaml string none' return ;; -*t) - COMPREPLY=($(compgen -W 'json json-utf-8 json-pretty - json-utf-16le json-utf-16be json-utf-32le json-utf-32be - cbor storable storable-file bencode clzf yaml dump dumper - string none' -- "$cur")) + _comp_compgen -- -W 'json json-utf-8 json-pretty json-utf-16le + json-utf-16be json-utf-32le json-utf-32be cbor storable + storable-file bencode clzf yaml dump dumper string none' return ;; -*e) @@ -23,9 +22,11 @@ _json_xs() ;; esac - [[ $cur == -* ]] && - COMPREPLY=($(compgen -W '$(_parse_usage "$1") -f' -- "$cur")) + if [[ $cur == -* ]]; then + _comp_compgen_usage + _comp_compgen -a -- -W '-f' + fi } && - complete -F _json_xs json_xs + complete -F _comp_cmd_json_xs json_xs # ex: filetype=sh diff --git a/completions/jsonschema b/completions/jsonschema index 8a36ed3..19a4439 100644 --- a/completions/jsonschema +++ b/completions/jsonschema @@ -1,30 +1,30 @@ # bash completion for jsonschema -*- shell-script -*- -_jsonschema() +_comp_cmd_jsonschema() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --help | --error-format | --validator | -[hFV]) return ;; --instance | -i) - _filedir json + _comp_compgen_filedir json return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - local args - _count_args "" "-*" - ((args == 1)) || return - _filedir '@(json|schema)' + local REPLY + _comp_count_args -a "-*" + ((REPLY == 1)) || return + _comp_compgen_filedir '@(json|schema)' } && - complete -F _jsonschema jsonschema + complete -F _comp_cmd_jsonschema jsonschema # ex: filetype=sh diff --git a/completions/k3b b/completions/k3b index 87d26cd..960e046 100644 --- a/completions/k3b +++ b/completions/k3b @@ -1,48 +1,48 @@ # bash completion for k3b -*- shell-script -*- -_k3b() +_comp_cmd_k3b() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --help* | --author | -v | --version | --license | --lang) return ;; --datacd | --audiocd | --videocd | --mixedcd | --emovixcd | --videodvd) - _filedir + _comp_compgen_filedir return ;; --copydvd | --formatdvd | --videodvdrip) - _dvd_devices + _comp_compgen_dvd_devices return ;; --copycd | --erasecd | --cddarip | --videocdrip) - _cd_devices - _dvd_devices + _comp_compgen_cd_devices + _comp_compgen -a dvd_devices return ;; --cdimage | --image) - _filedir '@(cue|iso|toc)' + _comp_compgen_filedir '@(cue|iso|toc)' return ;; --dvdimage) - _filedir iso + _comp_compgen_filedir iso return ;; --ao) - COMPREPLY=($(compgen -W 'alsa arts' -- "$cur")) + _comp_compgen -- -W 'alsa arts' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W "$(_parse_help "$1")" -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - _filedir + _comp_compgen_filedir fi } && - complete -F _k3b k3b + complete -F _comp_cmd_k3b k3b # ex: filetype=sh diff --git a/completions/kcov b/completions/kcov index 672967a..20a62f2 100644 --- a/completions/kcov +++ b/completions/kcov @@ -1,30 +1,28 @@ # kcov(1) completion -*- shell-script -*- -_kcov() +_comp_cmd_kcov() { - local cur prev words cword split - _init_completion -s -n : || return + local cur prev words cword was_split comp_args + _comp_initialize -s -n : -- "$@" || return case "$prev" in --pid | -p) - _pids + _comp_compgen_pids return ;; --sort-type | -s) - COMPREPLY=($(compgen -W 'filename percent reverse lines - uncovered' -- "$cur")) + _comp_compgen -- -W 'filename percent reverse lines uncovered' return ;; --include-path | --exclude-path) - _filedir + _comp_compgen_filedir return ;; --replace-src-path) if [[ $cur == ?*:* ]]; then - cur="${cur##*:}" - _filedir + _comp_compgen -c "${cur##*:}" filedir else - _filedir + _comp_compgen_filedir compopt -o nospace fi return @@ -33,12 +31,12 @@ _kcov() if [[ $cur == ?*,* ]]; then prev="${cur%,*}" cur="${cur##*,}" - COMPREPLY=($(compgen -W "{0..100}" -- "$cur")) + _comp_compgen -- -W "{0..100}" ((${#COMPREPLY[@]} == 1)) && - COMPREPLY=(${COMPREPLY/#/$prev,}) + _comp_compgen -Rv COMPREPLY -- -P "$prev," -W '"$COMPREPLY"' else - COMPREPLY=($(compgen -W "{0..100}" -- "$cur")) - ((${#COMPREPLY[@]} == 1)) && COMPREPLY=(${COMPREPLY/%/,}) + _comp_compgen -- -W "{0..100}" + ((${#COMPREPLY[@]} == 1)) && COMPREPLY=("${COMPREPLY/%/,}") compopt -o nospace fi return @@ -49,16 +47,16 @@ _kcov() ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" --help)' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir + _comp_compgen_filedir } && - complete -F _kcov kcov + complete -F _comp_cmd_kcov kcov # ex: filetype=sh diff --git a/completions/kill b/completions/kill index 25cddba..266ea13 100644 --- a/completions/kill +++ b/completions/kill @@ -1,29 +1,30 @@ # kill(1) completion -*- shell-script -*- -_kill() +_comp_cmd_kill() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -s) - _signals + _comp_compgen_signals return ;; - -l) + -l | -n) return ;; esac if [[ $cword -eq 1 && $cur == -* ]]; then # return list of available signals - _signals - - COMPREPLY+=($(compgen -W "-s -l" -- "$cur")) + _comp_compgen_signals - + _comp_compgen -a help -c help "$1" else - # return list of available PIDs - _pids + # return list of available PIDs and jobs + _comp_compgen_pids + _comp_compgen -ac "${cur#%}" -- -j -P % fi } && - complete -F _kill kill + complete -F _comp_cmd_kill kill # ex: filetype=sh diff --git a/completions/killall b/completions/killall index c7c0b0f..76f8759 100644 --- a/completions/killall +++ b/completions/killall @@ -2,35 +2,37 @@ [[ $OSTYPE == *@(linux|freebsd|darwin)* ]] || return 1 -_killall() +_comp_cmd_killall() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[Zoysu]*)' + # shellcheck disable=SC2254 case $prev in - --context | --older-than | --younger-than | --version | -!(-*)@([Zoy]|V*)) + --context | --older-than | --younger-than | --version | -${noargopts}@([Zoy]|V*)) return ;; - --signal | -!(-*)s) - _signals + --signal | -${noargopts}s) + _comp_compgen_signals return ;; - --user | -!(-*)u) - _allowed_users + --user | -${noargopts}u) + _comp_compgen_allowed_users return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) - ((cword == 1)) && _signals - + _comp_compgen_help + ((cword == 1)) && _comp_compgen -a signals - return fi - _pnames + _comp_compgen_pnames } && - complete -F _killall killall + complete -F _comp_cmd_killall killall # ex: filetype=sh diff --git a/completions/kldload b/completions/kldload index f511158..3c2396d 100644 --- a/completions/kldload +++ b/completions/kldload @@ -2,20 +2,31 @@ [[ $OSTYPE == *freebsd* ]] || return 1 -_kldload() +_comp_cmd_kldload() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - local moddir=/modules/ - [[ -d $moddir ]] || moddir=/boot/kernel/ + if _comp_looks_like_path "$cur"; then + _comp_compgen_filedir ko + return + fi - compopt -o filenames - COMPREPLY=($(compgen -f "$moddir$cur")) - COMPREPLY=(${COMPREPLY[@]#$moddir}) - COMPREPLY=(${COMPREPLY[@]%.ko}) + local moddirs modules i + if _comp_split -F ";" moddirs "$(kldconfig -r 2>/dev/null)"; then + compopt -o filenames + for i in "${moddirs[@]}"; do + _comp_compgen -v modules -c "$i/$cur" -- -f && + COMPREPLY+=("${modules[@]#$i/}") + done + ((${#COMPREPLY[@]})) && + COMPREPLY=("${COMPREPLY[@]%.ko}") + fi + + # also add dirs in current dir + _comp_compgen -a filedir -d } && - complete -F _kldload kldload + complete -F _comp_cmd_kldload kldload # ex: filetype=sh diff --git a/completions/kldunload b/completions/kldunload index 2e12282..180af36 100644 --- a/completions/kldunload +++ b/completions/kldunload @@ -2,14 +2,14 @@ [[ $OSTYPE == *freebsd* ]] || return 1 -_kldunload() +_comp_cmd_kldunload() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - COMPREPLY=($(compgen -W '$(kldstat)' -X 'kernel' -X '!*.ko' -- "$cur")) - COMPREPLY=(${COMPREPLY[@]%.ko}) + _comp_compgen_split -X '!*.ko' -- "$(kldstat)" && + COMPREPLY=("${COMPREPLY[@]%.ko}") } && - complete -F _kldunload kldunload + complete -F _comp_cmd_kldunload kldunload # ex: filetype=sh diff --git a/completions/koji b/completions/koji index 8efef9a..8ee4390 100644 --- a/completions/koji +++ b/completions/koji @@ -1,74 +1,76 @@ # koji completion -*- shell-script -*- -_koji_search() +_comp_cmd_koji__search() { - COMPREPLY+=($(compgen -W \ - '$("$1" -q search $2 "$cur*" 2>/dev/null)' -- "$cur")) + _comp_compgen -a split -- "$("$1" -q search "$2" "$cur*" 2>/dev/null)" } -_koji_build() +_comp_cmd_koji__build() { - _koji_search "$1" build + _comp_cmd_koji__search "$1" build } -_koji_package() +_comp_cmd_koji__package() { - _koji_search "$1" package + _comp_cmd_koji__search "$1" package } -_koji_user() +_comp_cmd_koji__user() { - _koji_search "$1" user + _comp_cmd_koji__search "$1" user } -_koji_tag() +_comp_cmd_koji__tag() { - COMPREPLY+=($(compgen -W '$("$1" -q list-tags 2>/dev/null)' -- "$cur")) + _comp_compgen -a split -- "$("$1" -q list-tags 2>/dev/null)" } -_koji_target() +_comp_cmd_koji__target() { - COMPREPLY+=($(compgen -W '$("$1" -q list-targets 2>/dev/null | - awk "{ print \$1 }")' -- "$cur")) + _comp_compgen -a split -- "$("$1" -q list-targets 2>/dev/null | + _comp_awk '{ print $1 }')" } -_koji() +_comp_cmd_koji() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return - local commandix command + local commandix command="" has_command="" for ((commandix = 1; commandix < cword; commandix++)); do if [[ ${words[commandix]} != -* ]]; then command=${words[commandix]} + has_command=set break fi done + local noargopts='!(-*|*[co]*)' + # shellcheck disable=SC2254 case $prev in - --help | --help-commands | -!(-*)h*) + --help | --help-commands | -${noargopts}h*) return ;; - --config | --keytab | -!(-*)[co]) - _filedir + --config | --keytab | -${noargopts}[co]) + _comp_compgen_filedir return ;; --runas | --user | --editor | --by) - _koji_user "$1" + _comp_cmd_koji__user "$1" return ;; --authtype) - COMPREPLY=($(compgen -W 'noauth ssl password kerberos' -- "$cur")) + _comp_compgen -- -W 'noauth ssl password kerberos' return ;; --topdir) - _filedir -d + _comp_compgen_filedir -d return ;; --type) case ${command-} in latest-pkg | list-tagged) - COMPREPLY=($(compgen -W 'maven' -- "$cur")) + _comp_compgen -- -W 'maven' ;; esac return @@ -76,39 +78,38 @@ _koji() --name) case ${command-} in list-targets) - _koji_target "$1" + _comp_cmd_koji__target "$1" ;; esac return ;; --owner) - _koji_user "$1" + _comp_cmd_koji__user "$1" return ;; --tag | --latestfrom) - _koji_tag "$1" + _comp_cmd_koji__tag "$1" return ;; --package) - _koji_package "$1" + _comp_cmd_koji__package "$1" return ;; --build) - _koji_build "$1" + _comp_cmd_koji__build "$1" return ;; --build-target) - _koji_target "$1" + _comp_cmd_koji__target "$1" return ;; esac - $split && return + [[ $was_split ]] && return - if [[ -v command ]]; then + if [[ $has_command ]]; then if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W \ - '$(_parse_help "$1" "$command --help")' -- "$cur")) + _comp_compgen_help -- "$command" --help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi @@ -123,108 +124,108 @@ _koji() build | maven-build | win-build) case $nth in 1) - _koji_target "$1" + _comp_cmd_koji__target "$1" ;; 2) - _filedir src.rpm + _comp_compgen_filedir src.rpm ;; esac ;; cancel) - _koji_build "$1" + _comp_cmd_koji__build "$1" ;; chain-build) case $nth in 1) - _koji_target "$1" + _comp_cmd_koji__target "$1" ;; esac ;; download-build) case $nth in 1) - _koji_build "$1" + _comp_cmd_koji__build "$1" ;; esac ;; import-comps) case $nth in 1) - _filedir xml + _comp_compgen_filedir xml ;; 2) - _koji_tag "$1" + _comp_cmd_koji__tag "$1" ;; esac ;; latest-by-tag) - _koji_package "$1" + _comp_cmd_koji__package "$1" ;; latest-pkg | list-groups | list-tag-inheritance | show-groups) case $nth in 1) - _koji_tag "$1" + _comp_cmd_koji__tag "$1" ;; esac ;; list-tagged) case $nth in 1) - _koji_tag "$1" + _comp_cmd_koji__tag "$1" ;; 2) - _koji_package "$1" + _comp_cmd_koji__package "$1" ;; esac ;; list-untagged) case $nth in 1) - _koji_package "$1" + _comp_cmd_koji__package "$1" ;; esac ;; move-pkg) case $nth in 1 | 2) - _koji_tag "$1" + _comp_cmd_koji__tag "$1" ;; *) - _koji_package "$1" + _comp_cmd_koji__package "$1" ;; esac ;; search) case $nth in 1) - COMPREPLY=($(compgen -W 'package build tag target - user host rpm' -- "$cur")) + _comp_compgen -- -W 'package build tag target user host + rpm' ;; esac ;; tag-pkg | untag-pkg) case $nth in 1) - _koji_tag "$1" + _comp_cmd_koji__tag "$1" ;; *) - _koji_package "$1" + _comp_cmd_koji__package "$1" ;; esac ;; taginfo) - _koji_tag "$1" + _comp_cmd_koji__tag "$1" ;; wait-repo) case $nth in 1) for ((i = commandix + 1; i < cword; i++)); do if [[ ${words[i]} == --target ]]; then - _koji_target "$1" + _comp_cmd_koji__target "$1" return fi done - _koji_tag "$1" + _comp_cmd_koji__tag "$1" ;; esac ;; @@ -233,13 +234,13 @@ _koji() fi if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace - elif [[ ! -v command ]]; then - COMPREPLY=($(compgen -W '$("$1" --help-commands 2>/dev/null | \ - awk "/^( +|\t)/ { print \$1 }")' -- "$cur")) + elif [[ ! $has_command ]]; then + _comp_compgen_split -- "$("$1" --help-commands 2>/dev/null | + _comp_awk '/^( +|\t)/ { print $1 }')" fi } && - complete -F _koji koji arm-koji ppc-koji s390-koji sparc-koji + complete -F _comp_cmd_koji koji arm-koji ppc-koji s390-koji sparc-koji # ex: filetype=sh diff --git a/completions/ktutil b/completions/ktutil index 6030a47..d25dafc 100644 --- a/completions/ktutil +++ b/completions/ktutil @@ -1,55 +1,54 @@ # ktutil completion -*- shell-script -*- -_heimdal_principals() +_comp_cmd_ktutil__heimdal_principals() { - COMPREPLY=($(compgen -W "$(kadmin -l dump 2>/dev/null | - awk '{print $1}')" -- "$cur")) + _comp_compgen_split -- "$(kadmin -l dump 2>/dev/null | + _comp_awk '{print $1}')" } -_heimdal_realms() +_comp_cmd_ktutil__heimdal_realms() { - COMPREPLY=($(compgen -W "$(kadmin -l dump 2>/dev/null | - awk '{print $1}' | awk -F@ '{print $2}')" -- "$cur")) + _comp_compgen_split -- "$(kadmin -l dump 2>/dev/null | + _comp_awk '{print $1}' | _comp_awk -F @ '{print $2}')" } -_heimdal_encodings() +_comp_cmd_ktutil__heimdal_encodings() { - COMPREPLY=($(compgen -W 'des-cbc-mcrc des-cbc-md4 des-cbc-md5 - des3-cbc-sha1 arcfour-hmac-md5 aes128-cts-hmac-sha1-96 - aes256-cts-hmac-sha1-96' -- "$cur")) + _comp_compgen -- -W 'des-cbc-mcrc des-cbc-md4 des-cbc-md5 des3-cbc-sha1 + arcfour-hmac-md5 aes128-cts-hmac-sha1-96 aes256-cts-hmac-sha1-96' } -_ktutil() +_comp_cmd_ktutil() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return local command commands i options case $prev in -p | --principal) - _heimdal_principals + _comp_cmd_ktutil__heimdal_principals return ;; -e | --enctype) - _heimdal_encodings + _comp_cmd_ktutil__heimdal_encodings return ;; -a | --admin-server) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -r | --realm) - _heimdal_realms + _comp_cmd_ktutil__heimdal_realms return ;; -s | -k | --srvtab | --keytab) - _filedir + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return commands='add change copy get list remove rename purge srvconvert srv2keytab srvcreate key2srvtab' @@ -97,24 +96,24 @@ _ktutil() options='-k --keytab -v --verbose --version -v --help' ;; esac - COMPREPLY=($(compgen -W "$options" -- "$cur")) + _comp_compgen -- -W "$options" else case ${command-} in copy) - _filedir + _comp_compgen_filedir ;; get) - _heimdal_principals + _comp_cmd_ktutil__heimdal_principals ;; rename) - _heimdal_principals + _comp_cmd_ktutil__heimdal_principals ;; *) - COMPREPLY=($(compgen -W "$commands" -- "$cur")) + _comp_compgen -- -W "$commands" ;; esac fi } && - complete -F _ktutil ktutil + complete -F _comp_cmd_ktutil ktutil # ex: filetype=sh diff --git a/completions/larch b/completions/larch index 7ed9ca2..0df7537 100644 --- a/completions/larch +++ b/completions/larch @@ -1,13 +1,13 @@ # larch(1) completion -*- shell-script -*- # by Alex Shinn <foof@synthcode.com> -_larch() +_comp_cmd_larch() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cword -eq 1 || $prev == -* ]]; then - COMPREPLY=($(compgen -W ' \ + _comp_compgen -- -W ' \ my-id my-default-archive register-archive whereis-archive archives \ init-tree tree-root tree-version set-tree-version inventory \ tagging-method tree-lint missing-tags add delete \ @@ -29,11 +29,10 @@ _larch() touched-files-prereqs patch-set-web update-distributions \ distribution-name notify my-notifier mail-new-categories \ mail-new-branches mail-new-versions mail-new-revisions \ - notify-library notify-browser push-new-revisions sendmail-mailx' \ - "$cur")) + notify-library notify-browser push-new-revisions sendmail-mailx' fi } && - complete -F _larch -o default larch + complete -F _comp_cmd_larch -o default larch # ex: filetype=sh diff --git a/completions/lastlog b/completions/lastlog index 214a174..8faf82b 100644 --- a/completions/lastlog +++ b/completions/lastlog @@ -1,25 +1,27 @@ # lastlog(8) completion -*- shell-script -*- -_lastlog() +_comp_cmd_lastlog() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[btu]*)' + # shellcheck disable=SC2254 case $prev in - --before | --help | --time | -!(-*)@([bt]|h*)) + --before | --help | --time | -${noargopts}@([bt]|h*)) return ;; - --user | -!(-*)u) - COMPREPLY=($(compgen -u -- "$cur")) + --user | -${noargopts}u) + _comp_compgen -- -u return ;; esac - $split && return + [[ $was_split ]] && return - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace } && - complete -F _lastlog lastlog + complete -F _comp_cmd_lastlog lastlog # ex: filetype=sh diff --git a/completions/ldapsearch b/completions/ldapsearch index 6dc415e..71c728e 100644 --- a/completions/ldapsearch +++ b/completions/ldapsearch @@ -1,231 +1,238 @@ # bash completion for openldap -*- shell-script -*- -_ldap_uris() +_comp_cmd_ldapsearch__ldap_uris() { - COMPREPLY=($(compgen -W 'ldap:// ldaps://' -- "$cur")) + _comp_compgen -- -W 'ldap:// ldaps://' } -_ldap_protocols() +_comp_cmd_ldapsearch__ldap_protocols() { - COMPREPLY=($(compgen -W '2 3' -- "$cur")) + _comp_compgen -- -W '2 3' } -_ldapsearch() +_comp_cmd_ldapsearch() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*h) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -*H) - _ldap_uris + _comp_cmd_ldapsearch__ldap_uris return ;; -*T) - _filedir -d + _comp_compgen_filedir -d return ;; -*[fy]) - _filedir + _comp_compgen_filedir return ;; -*s) - COMPREPLY=($(compgen -W 'base one sub children' -- "$cur")) + _comp_compgen -- -W 'base one sub children' return ;; -*a) - COMPREPLY=($(compgen -W 'never always search find' -- "$cur")) + _comp_compgen -- -W 'never always search find' return ;; -*P) - _ldap_protocols + _comp_cmd_ldapsearch__ldap_protocols return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1") -MM -ZZ' -- "$cur")) + _comp_compgen_help + _comp_compgen -a -- -W '-MM -ZZ' fi } && - complete -F _ldapsearch ldapsearch + complete -F _comp_cmd_ldapsearch ldapsearch -_ldapaddmodify() +_comp_cmd_ldapadd() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*h) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -*H) - _ldap_uris + _comp_cmd_ldapsearch__ldap_uris return ;; -*[Sfy]) - _filedir + _comp_compgen_filedir return ;; -*P) - _ldap_protocols + _comp_cmd_ldapsearch__ldap_protocols return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1") -MM -ZZ' -- "$cur")) + _comp_compgen_help + _comp_compgen -a -- -W '-MM -ZZ' fi } && - complete -F _ldapaddmodify ldapadd ldapmodify + complete -F _comp_cmd_ldapadd ldapadd ldapmodify -_ldapdelete() +_comp_cmd_ldapdelete() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*h) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -*H) - _ldap_uris + _comp_cmd_ldapsearch__ldap_uris return ;; -*[fy]) - _filedir + _comp_compgen_filedir return ;; -*P) - _ldap_protocols + _comp_cmd_ldapsearch__ldap_protocols return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1") -MM -ZZ' -- "$cur")) + _comp_compgen_help + _comp_compgen -a -- -W '-MM -ZZ' fi } && - complete -F _ldapdelete ldapdelete + complete -F _comp_cmd_ldapdelete ldapdelete -_ldapcompare() +_comp_cmd_ldapcompare() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*h) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -*H) - _ldap_uris + _comp_cmd_ldapsearch__ldap_uris return ;; -*y) - _filedir + _comp_compgen_filedir return ;; -*P) - _ldap_protocols + _comp_cmd_ldapsearch__ldap_protocols return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1") -MM -ZZ' -- "$cur")) + _comp_compgen_help + _comp_compgen -a -- -W '-MM -ZZ' fi } && - complete -F _ldapcompare ldapcompare + complete -F _comp_cmd_ldapcompare ldapcompare -_ldapmodrdn() +_comp_cmd_ldapmodrdn() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*h) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -*H) - _ldap_uris + _comp_cmd_ldapsearch__ldap_uris return ;; -*[fy]) - _filedir + _comp_compgen_filedir return ;; -*P) - _ldap_protocols + _comp_cmd_ldapsearch__ldap_protocols return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1") -ZZ -MM' -- "$cur")) + _comp_compgen_help + _comp_compgen -a -- -W '-ZZ -MM' fi } && - complete -F _ldapmodrdn ldapmodrdn + complete -F _comp_cmd_ldapmodrdn ldapmodrdn -_ldapwhoami() +_comp_cmd_ldapwhoami() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*h) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -*H) - _ldap_uris + _comp_cmd_ldapsearch__ldap_uris return ;; -*[fy]) - _filedir + _comp_compgen_filedir return ;; -*P) - _ldap_protocols + _comp_cmd_ldapsearch__ldap_protocols return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1") -MM -ZZ' -- "$cur")) + _comp_compgen_help + _comp_compgen -a -- -W '-MM -ZZ' fi } && - complete -F _ldapwhoami ldapwhoami + complete -F _comp_cmd_ldapwhoami ldapwhoami -_ldappasswd() +_comp_cmd_ldappasswd() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*h) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -*H) - _ldap_uris + _comp_cmd_ldapsearch__ldap_uris return ;; -*[tTy]) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1") -MM -ZZ' -- "$cur")) + _comp_compgen_help + _comp_compgen -a -- -W '-MM -ZZ' fi } && - complete -F _ldappasswd ldappasswd + complete -F _comp_cmd_ldappasswd ldappasswd # ex: filetype=sh diff --git a/completions/ldapvi b/completions/ldapvi index cb01ac8..d86cf55 100644 --- a/completions/ldapvi +++ b/completions/ldapvi @@ -1,51 +1,52 @@ # bash completion for ldapvi -*- shell-script -*- -_ldapvi() +_comp_cmd_ldapvi() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[Y]*)' + # shellcheck disable=SC2254 case $prev in - --host | -!(-*)h) - _known_hosts_real -- "$cur" + --host | -${noargopts}h) + _comp_compgen_known_hosts -- "$cur" return ;; - --sasl-mech | -!(-*)Y) - COMPREPLY=($(compgen -W 'EXTERNAL GSSAPI DIGEST-MD5 CRAM-MD5 - PLAIN ANONYMOUS' -- "$cur")) + --sasl-mech | -${noargopts}Y) + _comp_compgen -- -W 'EXTERNAL GSSAPI DIGEST-MD5 CRAM-MD5 PLAIN + ANONYMOUS' return ;; --bind) - COMPREPLY=($(compgen -W 'simple sasl' -- "$cur")) + _comp_compgen -- -W 'simple sasl' return ;; --bind-dialog) - COMPREPLY=($(compgen -W 'never auto always' -- "$cur")) + _comp_compgen -- -W 'never auto always' return ;; --scope) - COMPREPLY=($(compgen -W 'base one sub' -- "$cur")) + _comp_compgen -- -W 'base one sub' return ;; --deref) - COMPREPLY=($(compgen -W 'never searching finding always' \ - -- "$cur")) + _comp_compgen -- -W 'never searching finding always' return ;; --encoding) - COMPREPLY=($(compgen -W 'ASCII UTF-8 binary' -- "$cur")) + _comp_compgen -- -W 'ASCII UTF-8 binary' return ;; --tls) - COMPREPLY=($(compgen -W 'never allow try strict' -- "$cur")) + _comp_compgen -- -W 'never allow try strict' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help fi } && - complete -F _ldapvi ldapvi + complete -F _comp_cmd_ldapvi ldapvi # ex: filetype=sh diff --git a/completions/lftp b/completions/lftp index 72dedb4..16264cf 100644 --- a/completions/lftp +++ b/completions/lftp @@ -1,28 +1,30 @@ # lftp(1) completion -*- shell-script -*- -_lftp() +_comp_cmd_lftp() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[fceups]*)' + # shellcheck disable=SC2254 case $prev in - -!(-*)f) - _filedir + -${noargopts}f) + _comp_compgen_filedir return ;; - --help | --version | -!(-*)[chveups]) + --help | --version | -${noargopts}[chveups]) return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - COMPREPLY=($(compgen -W '$("$1" -c "bookmark list" 2>/dev/null)' -- "$cur")) - _known_hosts_real -- "$cur" + _comp_compgen_split -- "$("$1" -c "bookmark list" 2>/dev/null)" + _comp_compgen -a known_hosts -- "$cur" } && - complete -F _lftp lftp + complete -F _comp_cmd_lftp lftp # ex: filetype=sh diff --git a/completions/lftpget b/completions/lftpget index d21622e..a41ad0c 100644 --- a/completions/lftpget +++ b/completions/lftpget @@ -1,14 +1,14 @@ # lftpget(1) completion -*- shell-script -*- -_lftpget() +_comp_cmd_lftpget() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-c -d -v' -- "$cur")) + _comp_compgen -- -W '-c -d -v' fi } && - complete -F _lftpget lftpget + complete -F _comp_cmd_lftpget lftpget # ex: filetype=sh diff --git a/completions/lilo b/completions/lilo index af8539a..6df8566 100644 --- a/completions/lilo +++ b/completions/lilo @@ -1,66 +1,63 @@ # bash completion for lilo(8) -*- shell-script -*- -_lilo_labels() +_comp_cmd_lilo__labels() { - COMPREPLY=($(compgen -W "$(awk -F= '$1 ~ /^[ \t]*label$/ {print $2}' \ - ${1:-/etc/lilo.conf} 2>/dev/null | command sed -e 's/\"//g')" \ - -- "$cur")) + _comp_compgen_split -- "$(_comp_awk -F = '$1 ~ /^[ \t]*label$/ {print $2}' \ + "${1:-/etc/lilo.conf}" 2>/dev/null | command sed -e 's/\"//g')" } -_lilo() +_comp_cmd_lilo() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -C | -i | -m | -s | -S) - _filedir + _comp_compgen_filedir return ;; -r) - _filedir -d + _comp_compgen_filedir -d return ;; -I | -D | -R) # label completion - local i conf + local i conf="" for i in "${!words[@]}"; do if [[ ${words[i]} == -C ]]; then - conf=${words[i + 1]} + conf=${words[i + 1]-} break fi done - _lilo_labels $conf + _comp_cmd_lilo__labels "$conf" return ;; -A | -b | -M | -u | -U) # device completion - cur=${cur:=/dev/} - _filedir + _comp_compgen -c "${cur:-/dev/}" filedir return ;; -T) # topic completion - COMPREPLY=($(compgen -W 'help ChRul EBDA geom geom= table= - video' -- "$cur")) + _comp_compgen -- -W 'help ChRul EBDA geom geom= table= video' return ;; -B) - _filedir bmp + _comp_compgen_filedir bmp return ;; -E) - _filedir '@(bmp|dat)' + _comp_compgen_filedir '@(bmp|dat)' return ;; esac if [[ $cur == -* ]]; then # relevant options completion - COMPREPLY=($(compgen -W '-A -B -b -c -C -d -E -f -g -i -I -l -L -m -M - -p -P -q -r -R -s -S -t -T -u -U -v -V -w -x -z' -- "$cur")) + _comp_compgen -- -W '-A -B -b -c -C -d -E -f -g -i -I -l -L -m -M -p -P + -q -r -R -s -S -t -T -u -U -v -V -w -x -z' fi } && - complete -F _lilo lilo + complete -F _comp_cmd_lilo lilo # ex: filetype=sh diff --git a/completions/links b/completions/links index e0c28e2..989e9e0 100644 --- a/completions/links +++ b/completions/links @@ -1,17 +1,17 @@ # bash completion for links -*- shell-script -*- -_links() +_comp_cmd_links() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return case $prev in -html-t-text-color | -html-t-link-color) - COMPREPLY=($(compgen -W '{0..15}' -- "$cur")) + _comp_compgen -- -W '{0..15}' return ;; -http.fake-firefox | -html-[gt]-ignore-document-color) - COMPREPLY=($(compgen -W '0 1' -- "$cur")) + _comp_compgen -- -W '0 1' return ;; --help | -help | -mode | -display | -source | -dump | -width | -max-connections | \ @@ -23,78 +23,78 @@ _links() return ;; -lookup) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -driver) local drivers=$("$1" -driver foo 2>&1 | command sed -ne '$!d' -e '/^[a-z0-9, ]\{1,\}$/s/,/ /gp') [[ $drivers ]] || drivers='x svgalib fb directfb pmshell atheos' - COMPREPLY=($(compgen -W "$drivers" -- "$cur")) + _comp_compgen -- -W "$drivers" return ;; -codepage | -bookmarks-codepage | -http-assume-codepage) - _xfunc iconv _iconv_charsets + _comp_compgen -x iconv charsets return ;; -download-dir) - _filedir -d + _comp_compgen_filedir -d return ;; -bind-address) - _ip_addresses + _comp_compgen_ip_addresses return ;; -bind-address-ipv6) - _ip_addresses -6 - __ltrim_colon_completions "$cur" + _comp_compgen_ip_addresses -6 return ;; -async-dns | -download-utime | -aggressive-cache | -only-proxies | \ -http-bugs.* | -http.do-not-track | -ftp.use-* | -ftp.fast | -ftp.set-iptos | \ -smb.allow-hyperlinks-to-smb | -save-url-history | -dither-letters | \ -dither-images | -overwrite-instead-of-scroll | -html-*) - COMPREPLY=($(compgen -W '0 1' -- "$cur")) + _comp_compgen -- -W '0 1' return ;; -address-preference | -http.referer) - COMPREPLY=($(compgen -W '{0..4}' -- "$cur")) + _comp_compgen -- -W '{0..4}' return ;; -ssl-certificates | -display-optimize | -gamma-correction) - COMPREPLY=($(compgen -W '{0..2}' -- "$cur")) + _comp_compgen -- -W '{0..2}' return ;; -ssl.client-cert-key) - _filedir '@(key|pem)' + _comp_compgen_filedir '@(key|pem)' return ;; -ssl.client-cert-crt) - _filedir '@(c?(e)rt|cer|pem|der)' + _comp_compgen_filedir '@(c?(e)rt|cer|pem|der)' return ;; -bookmarks-file) - _filedir html + _comp_compgen_filedir html return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" | - command grep -vF -- "->")' -- "$cur")) + _comp_compgen -R help + ((${#COMPREPLY[@]})) && + _comp_compgen -- -W '"${COMPREPLY[@]}"' -X "->" return fi local dir for dir in .links .links2; do if [[ -r ~/$dir/links.his ]]; then - COMPREPLY+=($(compgen -W '$(cat ~/$dir/links.his)' -- "$cur")) - __ltrim_colon_completions "$cur" + _comp_compgen -a split -- "$(cat ~/$dir/links.his)" + _comp_ltrim_colon_completions "$cur" fi done - _filedir '@(htm|html)' + _comp_compgen -a filedir '@(htm|html)' } && - complete -F _links links links2 + complete -F _comp_cmd_links links links2 # ex: filetype=sh diff --git a/completions/lintian b/completions/lintian index 9343832..51402b2 100644 --- a/completions/lintian +++ b/completions/lintian @@ -1,74 +1,73 @@ # bash completion for lintian(1) and lintian-info(1) -*- shell-script -*- -_lintian_tags() +_comp_cmd_lintian__tags() { - local match search tags + local search tags check_files + _comp_expand_glob check_files '/usr/share/lintian/checks/*.desc' || return 0 - tags=$(awk '/^Tag/ { print $2 }' /usr/share/lintian/checks/*.desc) + tags=$(_comp_awk '/^Tag/ { print $2 }' "${check_files[@]}") if [[ $cur == *, ]]; then search=${cur//,/ } for item in $search; do - match=$(command grep -nE "^Tag: $item$" \ - /usr/share/lintian/checks/*.desc | cut -d: -f1) - tags=$(command sed -e "s/\<$item\>//g" <<<$tags) + tags=$(command sed -e "s/\<$item\>//g" <<<"$tags") done - COMPREPLY+=($(compgen -W "$tags")) + _comp_compgen -aR -- -W "$tags" elif [[ $cur == *,* ]]; then - COMPREPLY+=($(compgen -P "${cur%,*}," -W "$tags" -- "${cur##*,}")) + _comp_compgen -ac "${cur##*,}" -- -P "${cur%,*}," -W "$tags" else - COMPREPLY+=($(compgen -W "$tags" -- "$cur")) + _comp_compgen -a -- -W "$tags" fi } -_lintian_checks() +_comp_cmd_lintian__checks() { - local match search todisable checks + local match search todisable checks check_files + _comp_expand_glob check_files '/usr/share/lintian/checks/*.desc' || return 0 - checks=$(awk '/^(Check-Script|Abbrev)/ { print $2 }' \ - /usr/share/lintian/checks/*.desc) + checks=$(_comp_awk '/^(Check-Script|Abbrev)/ { print $2 }' \ + "${check_files[@]}") if [[ $cur == *, ]]; then search=${cur//,/ } for item in $search; do match=$(command grep -nE "^(Check-Script|Abbrev): $item$" \ - /usr/share/lintian/checks/*.desc | cut -d: -f1) - todisable=$(awk '/^(Check-Script|Abbrev)/ { print $2 }' $match) + "${check_files[@]}" | cut -d: -f1) + todisable=$(_comp_awk '/^(Check-Script|Abbrev)/ { print $2 }' "$match") for name in $todisable; do - checks=$(command sed -e "s/\<$name\>//g" <<<$checks) + checks=$(command sed -e "s/\<$name\>//g" <<<"$checks") done done - COMPREPLY+=($(compgen -W "$checks")) + _comp_compgen -aR -- -W "$checks" elif [[ $cur == *,* ]]; then - COMPREPLY+=($(compgen -P "${cur%,*}," -W "$checks" -- "${cur##*,}")) + _comp_compgen -ac "${cur##*,}" -- -P "${cur%,*}," -W "$checks" else - COMPREPLY+=($(compgen -W "$checks" -- "$cur")) + _comp_compgen -a -- -W "$checks" fi } -_lintian_infos() +_comp_cmd_lintian__infos() { - local match search infos + local search infos collection_files + _comp_expand_glob collection_files '/usr/share/lintian/collection/*.desc' || return 0 - infos=$(awk '/^Collector/ { print $2 }' \ - /usr/share/lintian/collection/*.desc) + infos=$(_comp_awk '/^Collector/ { print $2 }' \ + "${collection_files[@]}") if [[ $cur == *, ]]; then search=${cur//,/ } for item in $search; do - match=$(command grep -nE "^Collector: $item$" \ - /usr/share/lintian/collection/*.desc | cut -d: -f1) - infos=$(command sed -e "s/\<$item\>//g" <<<$infos) + infos=$(command sed -e "s/\<$item\>//g" <<<"$infos") done - COMPREPLY+=($(compgen -W "$infos")) + _comp_compgen -aR -- -W "$infos" elif [[ $cur == *,* ]]; then - COMPREPLY+=($(compgen -P "${cur%,*}," -W "$infos" -- "${cur##*,}")) + _comp_compgen -ac "${cur##*,}" -- -P "${cur%,*}," -W "$infos" else - COMPREPLY+=($(compgen -W "$infos" -- "$cur")) + _comp_compgen -a -- -W "$infos" fi } -_lintian() +_comp_cmd_lintian() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local lint_actions general_opts behaviour_opts configuration_opts @@ -86,36 +85,44 @@ _lintian() if [[ $prev == -* ]]; then case $prev in -C | --check-part | -X | --dont-check-part) - _lintian_checks + _comp_cmd_lintian__checks + return ;; -T | --tags | --suppress-tags) - _lintian_tags + _comp_cmd_lintian__tags + return ;; --tags-from-file | --suppress-tags-from-file | --cfg | -p | \ --packages-file) - _filedir + _comp_compgen_filedir + return ;; --lab | --archivedir | --dist | --root) - _filedir -d + _comp_compgen_filedir -d + return ;; --color) - COMPREPLY=($(compgen -W "never always auto html" -- "$cur")) + _comp_compgen -- -W "never always auto html" + return ;; -U | --unpack-info) - _lintian_infos + _comp_cmd_lintian__infos + return ;; --area | --section) - COMPREPLY=($(compgen -W "main contrib non-free" -- "$cur")) + _comp_compgen -- -W "main contrib non-free" + return + ;; + --arch) + return ;; - --arch) ;; - esac fi case "$cur" in --*) - COMPREPLY=($(compgen -W "$lint_actions $general_opts - $behaviour_opts $configuration_opts" -- "$cur")) + _comp_compgen -- -W "$lint_actions $general_opts $behaviour_opts + $configuration_opts" ;; *,) # If we're here, the user is trying to complete on @@ -123,54 +130,54 @@ _lintian() # Only few actions permit that, re-complete them now. case "$prev" in -C | --check-part | -X | --dont-check-part) - _lintian_checks + _comp_cmd_lintian__checks ;; -T | --tags | --suppress-tags) - _lintian_tags + _comp_cmd_lintian__tags ;; -U | --unpack-info) - _lintian_infos + _comp_cmd_lintian__infos ;; esac ;; *) # in Ubuntu, dbgsym packages end in .ddeb, lintian >= 2.57.0 groks - _filedir '@(?(u|d)deb|changes|dsc|buildinfo)' + _comp_compgen_filedir '@(?(u|d)deb|changes|dsc|buildinfo)' ;; esac return 0 } && - complete -F _lintian lintian + complete -F _comp_cmd_lintian lintian -_lintian_info() +_comp_cmd_lintian_info() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case "$prev" in --help | --profile) return ;; -t | --tags) - _lintian_tags + _comp_cmd_lintian__tags return ;; --include-dir) - _filedir -d + _comp_compgen_filedir -d return ;; esac case "$cur" in --*) - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help ;; *) - _filedir + _comp_compgen_filedir ;; esac return 0 } && - complete -F _lintian_info lintian-info + complete -F _comp_cmd_lintian_info lintian-info # ex: filetype=sh diff --git a/completions/lisp b/completions/lisp index 098567b..c236092 100644 --- a/completions/lisp +++ b/completions/lisp @@ -2,21 +2,20 @@ # bash programmable completion for various Common Lisp implementations by # Nikodemus Siivola <nikodemus@random-state.net> -_lisp() +_comp_cmd_lisp() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return # completing an option (may or may not be separated by a space) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-core -lib -batch -quit -edit -eval -init - -dynamic-space-size -hinit -noinit -nositeinit -load -slave' \ - -- "$cur")) + _comp_compgen -- -W '-core -lib -batch -quit -edit -eval -init + -dynamic-space-size -hinit -noinit -nositeinit -load -slave' else - _filedir + _comp_compgen_filedir fi } && - complete -F _lisp -o default lisp + complete -F _comp_cmd_lisp -o default lisp # ex: filetype=sh diff --git a/completions/list_admins b/completions/list_admins index 5708179..98452eb 100644 --- a/completions/list_admins +++ b/completions/list_admins @@ -1,17 +1,20 @@ # mailman list_admins completion -*- shell-script -*- -_list_admins() +_comp_cmd_list_admins() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--all-vhost --all --help' -- "$cur")) + _comp_compgen -- -W '--all-vhost --all --help' else - _xfunc list_lists _mailman_lists + # Prefer `list_lists` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen -x list_lists mailman_lists fi } && - complete -F _list_admins list_admins + complete -F _comp_cmd_list_admins list_admins # ex: filetype=sh diff --git a/completions/list_lists b/completions/list_lists index c5b9ba7..0ae00af 100644 --- a/completions/list_lists +++ b/completions/list_lists @@ -1,21 +1,25 @@ # mailman list_lists completion -*- shell-script -*- -_mailman_lists() +# @since 2.12 +_comp_xfunc_list_lists_compgen_mailman_lists() { - COMPREPLY=($(compgen -W '$(list_lists -b 2>/dev/null)' -- "$cur")) + _comp_compgen_split -- "$(list_lists -b 2>/dev/null)" } -_list_lists() +_comp_deprecate_func 2.12 _mailman_lists \ + _comp_xfunc_list_lists_compgen_mailman_lists + +_comp_cmd_list_lists() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--advertised --virtual-host-overview --bare - --help' -- "$cur")) + _comp_compgen -- -W '--advertised --virtual-host-overview --bare + --help' fi } && - complete -F _list_lists list_lists + complete -F _comp_cmd_list_lists list_lists # ex: filetype=sh diff --git a/completions/list_members b/completions/list_members index 639344c..a15a2cc 100644 --- a/completions/list_members +++ b/completions/list_members @@ -1,36 +1,38 @@ # mailman list_members completion -*- shell-script -*- -_list_members() +_comp_cmd_list_members() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -o | --output) - _filedir + _comp_compgen_filedir return ;; -d | --digest) - COMPREPLY=($(compgen -W 'mime plain' -- "$cur")) + _comp_compgen -- -W 'mime plain' return ;; -n | --nomail) - COMPREPLY=($(compgen -W 'byadmin byuser bybounce unknown' \ - -- "$cur")) + _comp_compgen -- -W 'byadmin byuser bybounce unknown' return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--output --regular --digest --nomail - --fullnames --preserve --help' -- "$cur")) + _comp_compgen -- -W '--output --regular --digest --nomail --fullnames + --preserve --help' else - _xfunc list_lists _mailman_lists + # Prefer `list_lists` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen -x list_lists mailman_lists fi } && - complete -F _list_members list_members + complete -F _comp_cmd_list_members list_members # ex: filetype=sh diff --git a/completions/list_owners b/completions/list_owners index 445be0b..6179176 100644 --- a/completions/list_owners +++ b/completions/list_owners @@ -1,18 +1,20 @@ # mailman list_owners completion -*- shell-script -*- -_list_owners() +_comp_cmd_list_owners() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--with-listnames --moderators --help' \ - -- "$cur")) + _comp_compgen -- -W '--with-listnames --moderators --help' else - _xfunc list_lists _mailman_lists + # Prefer `list_lists` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen -x list_lists mailman_lists fi } && - complete -F _list_owners list_owners + complete -F _comp_cmd_list_owners list_owners # ex: filetype=sh diff --git a/completions/locale-gen b/completions/locale-gen index 4068201..0ac8598 100644 --- a/completions/locale-gen +++ b/completions/locale-gen @@ -1,32 +1,32 @@ # locale-gen(8) completion -*- shell-script -*- -_locale_gen() +_comp_cmd_locale_gen() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in --help | -h) return ;; --aliases) - _filedir alias + _comp_compgen_filedir alias return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - COMPREPLY=($(compgen -W \ - '$(awk "{ print \$1 }" /usr/share/i18n/SUPPORTED 2>/dev/null)' \ - -- "$cur")) + _comp_compgen_split -- "$( + _comp_awk '{ print $1 }' /usr/share/i18n/SUPPORTED 2>/dev/null + )" } && - complete -F _locale_gen locale-gen + complete -F _comp_cmd_locale_gen locale-gen # ex: filetype=sh diff --git a/completions/lpq b/completions/lpq index 36729d2..d9c29bb 100644 --- a/completions/lpq +++ b/completions/lpq @@ -1,28 +1,28 @@ # lpq(1) completion -*- shell-script -*- -_lpq() +_comp_cmd_lpq() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -P) - COMPREPLY=($(compgen -W "$(lpstat -a 2>/dev/null | cut -d' ' -f1)" -- "$cur")) + _comp_compgen_split -- "$(lpstat -a 2>/dev/null | cut -d' ' -f1)" return ;; -U) - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u return ;; esac if [[ $cur == - ]]; then - COMPREPLY=($(compgen -W '-E -P -U -a -h -l' -- "$cur")) + _comp_compgen -- -W '-E -P -U -a -h -l' return fi - _filedir + _comp_compgen_filedir } && - complete -F _lpq lpq + complete -F _comp_cmd_lpq lpq # ex: filetype=sh diff --git a/completions/lpr b/completions/lpr index 554f053..746df28 100644 --- a/completions/lpr +++ b/completions/lpr @@ -1,33 +1,33 @@ # lpr(1) completion -*- shell-script -*- -_lpr() +_comp_cmd_lpr() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -P) - COMPREPLY=($(compgen -W "$(lpstat -a 2>/dev/null | cut -d' ' -f1)" -- "$cur")) + _comp_compgen_split -- "$(lpstat -a 2>/dev/null | cut -d' ' -f1)" return ;; -U) - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u return ;; -o) - COMPREPLY=($(compgen -W "media= landscape orientation-requested= sides= fitplot number-up= scaling= cpi= lpi= page-bottom= page-top= page-left= page-right=" -- "$cur")) + _comp_compgen -- -W "media= landscape orientation-requested= sides= fitplot number-up= scaling= cpi= lpi= page-bottom= page-top= page-left= page-right=" [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return ;; esac if [[ $cur == - ]]; then - COMPREPLY=($(compgen -W '-E -H -C -J -T -P -U -h -l -m -o -p -q -r' -- "$cur")) + _comp_compgen -- -W '-E -H -C -J -T -P -U -h -l -m -o -p -q -r' return fi - _filedir + _comp_compgen_filedir } && - complete -F _lpr lpr + complete -F _comp_cmd_lpr lpr # ex: filetype=sh diff --git a/completions/lrzip b/completions/lrzip index eb2904c..6f40be7 100644 --- a/completions/lrzip +++ b/completions/lrzip @@ -1,52 +1,56 @@ # lrzip(1) completion -*- shell-script -*- -_lrzip() +_comp_cmd_lrzip() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local xspec="*.lrz" + local noargopts='!(-*|*[SmwdoOLNp]*)' + # shellcheck disable=SC2254 case $prev in - -*@([wSm]|[Vh?]*)) + --help | --version | --suffix | --maxram | --window | \ + -${noargopts}@([Smw]|[h?V]*)) return ;; - -*d) + --decompress | -${noargopts}d) xspec="!"$xspec ;; - -*o) - _filedir + --outfile | -${noargopts}o) + _comp_compgen_filedir return ;; - -*O) - _filedir -d + --outdir | -${noargopts}O) + _comp_compgen_filedir -d return ;; - -*L) - COMPREPLY=($(compgen -W '{1..9}' -- "$cur")) + --level | -${noargopts}L) + _comp_compgen -- -W '{1..9}' return ;; - -*N) - COMPREPLY=($(compgen -W '{-20..19}' -- "$cur")) + --nice-level | -${noargopts}N) + _comp_compgen -- -W '{-20..19}' return ;; - -*p) - COMPREPLY=($(compgen -W "{1..$(_ncpus)}" -- "$cur")) + --threads | -${noargopts}p) + local REPLY + _comp_get_ncpus + _comp_compgen -- -W "{1..$REPLY}" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - _tilde "$cur" || return + _comp_compgen_tilde && return - local IFS=$'\n' compopt -o filenames - COMPREPLY=($(compgen -f -X "$xspec" -- "$cur") $(compgen -d -- "$cur")) + _comp_compgen -- -f -X "$xspec" -o plusdirs } && - complete -F _lrzip lrzip + complete -F _comp_cmd_lrzip lrzip # ex: filetype=sh diff --git a/completions/lsof b/completions/lsof index eb1e967..07559b3 100644 --- a/completions/lsof +++ b/completions/lsof @@ -1,56 +1,56 @@ # lsof(8) completion -*- shell-script -*- -_lsof() +_comp_cmd_lsof() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -'?' | -h | +c | -c | -d | -F | -i | +r | -r | -s | -S | -T) return ;; -A | -k | -m | +m | -o) - _filedir + _comp_compgen_filedir return ;; +d | +D) - _filedir -d + _comp_compgen_filedir -d return ;; -D) - COMPREPLY=($(compgen -W '? b i r u' -- "$cur")) + _comp_compgen -- -W '? b i r u' return ;; -f) - COMPREPLY=($(compgen -W 'c f g G n' -- "$cur")) + _comp_compgen -- -W 'c f g G n' return ;; -g) # TODO: handle ^foo exclusions, comma separated lists - _pgids + _comp_compgen_pgids return ;; -p) # TODO: handle ^foo exclusions, comma separated lists - _pids + _comp_compgen_pids return ;; -u) # TODO: handle ^foo exclusions, comma separated lists - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u return ;; esac if [[ $cur == [-+]* ]]; then - COMPREPLY=($(compgen -W '-h -a -A -b -c +c -C +d -d +D -D +f -f -F -g - -i -k -l +L -L +m -m +M -M -n -N -o -O -p -P +r -r -R -s -S -T -t - -u -U -v -V +w -w -x -X -z -Z' -- "$cur")) + _comp_compgen -- -W '-h -a -A -b -c +c -C +d -d +D -D +f -f -F -g -i -k + -l +L -L +m -m +M -M -n -N -o -O -p -P +r -r -R -s -S -T -t -u -U + -v -V +w -w -x -X -z -Z' return fi - _filedir + _comp_compgen_filedir } && - complete -F _lsof lsof + complete -F _comp_cmd_lsof lsof # ex: filetype=sh diff --git a/completions/lspci b/completions/lspci index d50783c..16d6195 100644 --- a/completions/lspci +++ b/completions/lspci @@ -1,41 +1,40 @@ # lspci(8) completion -*- shell-script -*- -_lspci() +_comp_cmd_lspci() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*[sDO]) return ;; -*i) - _filedir ids + _comp_compgen_filedir ids return ;; -*p) - _filedir pcimap + _comp_compgen_filedir pcimap return ;; -*A) - COMPREPLY+=($(compgen -W '$($1 -A help | command grep -vF :)' \ - -- "$cur")) + _comp_compgen_split -- "$("$1" -A help | command grep -vF :)" return ;; -*H) - COMPREPLY+=($(compgen -W "1 2" -- "$cur")) + _comp_compgen -- -W "1 2" return ;; -*F) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help fi } && - complete -F _lspci lspci + complete -F _comp_cmd_lspci lspci # ex: filetype=sh diff --git a/completions/lsscsi b/completions/lsscsi index bcbc430..6f417f5 100644 --- a/completions/lsscsi +++ b/completions/lsscsi @@ -1,27 +1,29 @@ # lsscsi(8) completion -*- shell-script -*- -_lsscsi() +_comp_cmd_lsscsi() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[y]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | -!(-*)[hV]*) + --help | --version | -${noargopts}[hV]*) return ;; - --sysfsroot | -!(-*)y) - _filedir -d + --sysfsroot | -${noargopts}y) + _comp_compgen_filedir -d return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _lsscsi lsscsi + complete -F _comp_cmd_lsscsi lsscsi # ex: filetype=sh diff --git a/completions/lsusb b/completions/lsusb index 63cff54..44c2625 100644 --- a/completions/lsusb +++ b/completions/lsusb @@ -1,20 +1,22 @@ # lsusb(8) completion -*- shell-script -*- -_lsusb() +_comp_cmd_lsusb() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[sD]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | -!(-*)@([sD]|[hV]*)) + --help | --version | -${noargopts}@([sD]|[hV]*)) return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help fi } && - complete -F _lsusb lsusb + complete -F _comp_cmd_lsusb lsusb # ex: filetype=sh diff --git a/completions/lua b/completions/lua index 3c4df90..a8904e0 100644 --- a/completions/lua +++ b/completions/lua @@ -1,9 +1,9 @@ # lua(1) completion -*- shell-script -*- -_lua() +_comp_cmd_lua() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -e | -l | -v | -) @@ -12,12 +12,12 @@ _lua() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W "$(_parse_help "$1")" -- "$cur")) + _comp_compgen_help return fi - _filedir 'l@(ua|?(ua)c)' + _comp_compgen_filedir 'l@(ua|?(ua)c)' } && - complete -F _lua lua + complete -F _comp_cmd_lua lua{,5{,.}{0..4}} # ex: filetype=sh diff --git a/completions/luac b/completions/luac index c763deb..3fef4be 100644 --- a/completions/luac +++ b/completions/luac @@ -1,27 +1,27 @@ # luac(1) completion -*- shell-script -*- -_luac() +_comp_cmd_luac() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -v | -) return ;; -o) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W "$(_parse_help "$1")" -- "$cur")) + _comp_compgen_help return fi - _filedir lua + _comp_compgen_filedir lua } && - complete -F _luac luac + complete -F _comp_cmd_luac luac{,5{,.}{0..4}} # ex: filetype=sh diff --git a/completions/luseradd b/completions/luseradd index 4d66385..255bc91 100644 --- a/completions/luseradd +++ b/completions/luseradd @@ -1,40 +1,42 @@ # luseradd(1) and lusermod(1) completion -*- shell-script -*- -_luseradd() +_comp_cmd_luseradd() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[culPpdksg]*)' + # shellcheck disable=SC2254 case $prev in --help | --usage | --gecos | --uid | --login | --plainpassword | --password | \ --commonname | --givenname | --surname | --roomnumber | --telephonenumber | \ - --homephone | -!(-*)@([culPp]|[?]*)) + --homephone | -${noargopts}@([culPp]|[?]*)) return ;; - --directory | --skeleton | -!(-*)[dk]) - _filedir -d + --directory | --skeleton | -${noargopts}[dk]) + _comp_compgen_filedir -d return ;; - --shell | -!(-*)s) - _shells + --shell | -${noargopts}s) + _comp_compgen_shells return ;; - --gid | -!(-*)g) - _gids + --gid | -${noargopts}g) + _comp_compgen_gids return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - [[ ${1##*/} == luseradd ]] || COMPREPLY=($(compgen -u -- "$cur")) + [[ ${1##*/} == luseradd ]] || _comp_compgen -- -u } && - complete -F _luseradd luseradd lusermod + complete -F _comp_cmd_luseradd luseradd lusermod # ex: filetype=sh diff --git a/completions/luserdel b/completions/luserdel index e36bda9..d36b256 100644 --- a/completions/luserdel +++ b/completions/luserdel @@ -1,9 +1,9 @@ # luserdel(1) completion -*- shell-script -*- -_luserdel() +_comp_cmd_luserdel() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --help | --usage | -!(-*)[?]*) @@ -12,12 +12,12 @@ _luserdel() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u } && - complete -F _luserdel luserdel + complete -F _comp_cmd_luserdel luserdel # ex: filetype=sh diff --git a/completions/lvm b/completions/lvm index e70ecc3..70581a7 100644 --- a/completions/lvm +++ b/completions/lvm @@ -1,56 +1,55 @@ # bash completion for lvm -*- shell-script -*- -_lvm_filedir() +_comp_cmd_lvm__filedir() { - cur=${cur:-/dev/} - _filedir + _comp_compgen -c "${cur:-/dev/}" filedir } -_lvm_volumegroups() +_comp_cmd_lvm__volumegroups() { - COMPREPLY=($(compgen -W "$(vgscan 2>/dev/null | - command sed -n -e 's|.*Found.*"\(.*\)".*$|\1|p')" -- "$cur")) + _comp_compgen_split -- "$(vgscan 2>/dev/null | + command sed -n -e 's|.*Found.*"\(.*\)".*$|\1|p')" } -_lvm_physicalvolumes_all() +_comp_cmd_lvm__physicalvolumes_all() { - COMPREPLY=($(compgen -W "$(pvscan 2>/dev/null | - command sed -n -e 's|^.*PV \([^ ]*\) .*|\1|p')" -- "$cur")) + _comp_compgen_split -- "$(pvscan 2>/dev/null | + command sed -n -e 's|^.*PV \([^ ]*\) .*|\1|p')" } -_lvm_physicalvolumes() +_comp_cmd_lvm__physicalvolumes() { - COMPREPLY=($(compgen -W "$(pvscan 2>/dev/null | - command sed -n -e 's|^.*PV \(.*\) VG.*$|\1|p')" -- "$cur")) + _comp_compgen_split -- "$(pvscan 2>/dev/null | + command sed -n -e 's|^.*PV \(.*\) VG.*$|\1|p')" } -_lvm_logicalvolumes() +_comp_cmd_lvm__logicalvolumes() { - COMPREPLY=($(compgen -W "$(lvscan 2>/dev/null | - command sed -n -e "s|^.*'\(.*\)'.*$|\1|p")" -- "$cur")) + _comp_compgen_split -- "$(lvscan 2>/dev/null | + command sed -n -e "s|^.*'\(.*\)'.*$|\1|p")" if [[ $cur == /dev/mapper/* ]]; then - _filedir + _comp_compgen -a filedir local i for i in "${!COMPREPLY[@]}"; do - [[ ${COMPREPLY[i]} == */control ]] && unset 'COMPREPLY[i]' + [[ ${COMPREPLY[i]} == */control ]] && unset -v 'COMPREPLY[i]' done fi } -_lvm_units() +_comp_cmd_lvm__units() { - COMPREPLY=($(compgen -W 'h s b k m g t H K M G T' -- "$cur")) + _comp_compgen -- -W 'h s b k m g t H K M G T' } -_lvm_sizes() +_comp_cmd_lvm__sizes() { - COMPREPLY=($(compgen -W 'k K m M g G t T' -- "$cur")) + _comp_compgen -- -W 'k K m M g G t T' } # @param $1 glob matching args known to take an argument -_lvm_count_args() +_comp_cmd_lvm__count_args() { - args=0 + REPLY=0 local offset=1 if [[ ${words[0]} == lvm ]]; then offset=2 @@ -59,791 +58,836 @@ _lvm_count_args() for ((i = offset; i < cword; i++)); do # shellcheck disable=SC2053 if [[ ${words[i]} != -* && $prev != $1 ]]; then - ((args++)) + ((REPLY++)) fi prev=${words[i]} done } -_lvmdiskscan() +_comp_cmd_lvmdiskscan() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help fi } && - complete -F _lvmdiskscan lvmdiskscan + complete -F _comp_cmd_lvmdiskscan lvmdiskscan -_pvscan() +_comp_cmd_pvscan() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help fi } && - complete -F _pvscan pvscan + complete -F _comp_cmd_pvscan pvscan -_pvs() +_comp_cmd_pvs() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[oO]*)' + # shellcheck disable=SC2254 case $prev in - --options | --sort | -!(-*)[oO]) - COMPREPLY=($(compgen -W 'pv_fmt pv_uuid pv_size pv_free pv_used - pv_name pv_attr pv_pe_count pv_pe_alloc_count' -- "$cur")) + --options | --sort | -${noargopts}[oO]) + _comp_compgen -- -W 'pv_fmt pv_uuid pv_size pv_free pv_used pv_name + pv_attr pv_pe_count pv_pe_alloc_count' return ;; --units) - _lvm_units + _comp_cmd_lvm__units return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_physicalvolumes_all + _comp_cmd_lvm__physicalvolumes_all fi } && - complete -F _pvs pvs + complete -F _comp_cmd_pvs pvs -_pvdisplay() +_comp_cmd_pvdisplay() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --units) - _lvm_units + _comp_cmd_lvm__units return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_physicalvolumes_all + _comp_cmd_lvm__physicalvolumes_all fi } && - complete -F _pvdisplay pvdisplay + complete -F _comp_cmd_pvdisplay pvdisplay -_pvchange() +_comp_cmd_pvchange() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[Ax]*)' + # shellcheck disable=SC2254 case $prev in - --autobackup | --allocatable | -!(-*)[Ax]) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + --autobackup | --allocatable | -${noargopts}[Ax]) + _comp_compgen -- -W 'y n' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_physicalvolumes_all + _comp_cmd_lvm__physicalvolumes_all fi } && - complete -F _pvchange pvchange + complete -F _comp_cmd_pvchange pvchange -_pvcreate() +_comp_cmd_pvcreate() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[M]*)' + # shellcheck disable=SC2254 case $prev in --restorefile) - _filedir + _comp_compgen_filedir return ;; - --metadatatype | -!(-*)M) - COMPREPLY=($(compgen -W '1 2' -- "$cur")) + --metadatatype | -${noargopts}M) + _comp_compgen -- -W '1 2' return ;; --metadatacopies) - COMPREPLY=($(compgen -W '0 1 2' -- "$cur")) + _comp_compgen -- -W '0 1 2' return ;; --metadatasize | --setphysicalvolumesize) - _lvm_sizes + _comp_cmd_lvm__sizes return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_filedir + _comp_cmd_lvm__filedir fi } && - complete -F _pvcreate pvcreate + complete -F _comp_cmd_pvcreate pvcreate -_pvmove() +_comp_cmd_pvmove() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[An]*)' + # shellcheck disable=SC2254 case $prev in - --autobackup | -!(-*)A) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + --autobackup | -${noargopts}A) + _comp_compgen -- -W 'y n' return ;; - --name | -!(-*)n) - _lvm_logicalvolumes + --name | -${noargopts}n) + _comp_cmd_lvm__logicalvolumes return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_physicalvolumes + _comp_cmd_lvm__physicalvolumes fi } && - complete -F _pvmove pvmove + complete -F _comp_cmd_pvmove pvmove -_pvremove() +_comp_cmd_pvremove() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_physicalvolumes_all + _comp_cmd_lvm__physicalvolumes_all fi } && - complete -F _pvremove pvremove + complete -F _comp_cmd_pvremove pvremove -_vgscan() +_comp_cmd_vgscan() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help fi } && - complete -F _vgscan vgscan + complete -F _comp_cmd_vgscan vgscan -_vgs() +_comp_cmd_vgs() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[oO]*)' + # shellcheck disable=SC2254 case $prev in - --options | --sort | -!(-*)[oO]) - COMPREPLY=($(compgen -W 'vg_fmt vg_uuid vg_name vg_attr vg_size - vg_free vg_sysid vg_extent_size vg_extent_count vg_free_count - max_lv max_pv pv_count lv_count snap_count vg_seqno' \ - -- "$cur")) + --options | --sort | -${noargopts}[oO]) + _comp_compgen -- -W 'vg_fmt vg_uuid vg_name vg_attr vg_size vg_free + vg_sysid vg_extent_size vg_extent_count vg_free_count max_lv + max_pv pv_count lv_count snap_count vg_seqno' return ;; --units) - _lvm_units + _comp_cmd_lvm__units return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_volumegroups + _comp_cmd_lvm__volumegroups fi } && - complete -F _vgs vgs + complete -F _comp_cmd_vgs vgs -_vgdisplay() +_comp_cmd_vgdisplay() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --units) - _lvm_units + _comp_cmd_lvm__units return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_volumegroups + _comp_cmd_lvm__volumegroups fi } && - complete -F _vgdisplay vgdisplay + complete -F _comp_cmd_vgdisplay vgdisplay -_vgchange() +_comp_cmd_vgchange() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[aAx]*)' + # shellcheck disable=SC2254 case $prev in - --available | --autobackup | --resizeable | -!(-*)[aAx]) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + --available | --autobackup | --resizeable | -${noargopts}[aAx]) + _comp_compgen -- -W 'y n' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_volumegroups + _comp_cmd_lvm__volumegroups fi } && - complete -F _vgchange vgchange + complete -F _comp_cmd_vgchange vgchange -_vgcreate() +_comp_cmd_vgcreate() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[AMs]*)' + # shellcheck disable=SC2254 case $prev in - --autobackup | -!(-*)A) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + --autobackup | -${noargopts}A) + _comp_compgen -- -W 'y n' return ;; - --metadatatype | -!(-*)M) - COMPREPLY=($(compgen -W '1 2' -- "$cur")) + --metadatatype | -${noargopts}M) + _comp_compgen -- -W '1 2' return ;; - --physicalextentsize | -!(-*)s) - _lvm_sizes + --physicalextentsize | -${noargopts}s) + _comp_cmd_lvm__sizes return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - local args - _lvm_count_args '@(-A|--autobackup|-M|--metadatatype|-s|--physicalextentsize)' - if ((args == 0)); then - _lvm_volumegroups + local REPLY + _comp_cmd_lvm__count_args '@(-A|--autobackup|-M|--metadatatype|-s|--physicalextentsize)' + if ((REPLY == 0)); then + _comp_cmd_lvm__volumegroups else - _lvm_physicalvolumes_all + _comp_cmd_lvm__physicalvolumes_all fi fi } && - complete -F _vgcreate vgcreate + complete -F _comp_cmd_vgcreate vgcreate -_vgremove() +_comp_cmd_vgremove() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_volumegroups + _comp_cmd_lvm__volumegroups fi } && - complete -F _vgremove vgremove + complete -F _comp_cmd_vgremove vgremove -_vgrename() +_comp_cmd_vgrename() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[A]*)' + # shellcheck disable=SC2254 case $prev in - --autobackup | -!(-*)A) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + --autobackup | -${noargopts}A) + _comp_compgen -- -W 'y n' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_volumegroups + _comp_cmd_lvm__volumegroups fi } && - complete -F _vgrename vgrename + complete -F _comp_cmd_vgrename vgrename -_vgreduce() +_comp_cmd_vgreduce() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[A]*)' + # shellcheck disable=SC2254 case $prev in - --autobackup | -!(-*)A) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + --autobackup | -${noargopts}A) + _comp_compgen -- -W 'y n' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - local args - _lvm_count_args '@(-A|--autobackup)' - if ((args == 0)); then - _lvm_volumegroups + local REPLY + _comp_cmd_lvm__count_args '@(-A|--autobackup)' + if ((REPLY == 0)); then + _comp_cmd_lvm__volumegroups else - _lvm_physicalvolumes + _comp_cmd_lvm__physicalvolumes fi fi } && - complete -F _vgreduce vgreduce + complete -F _comp_cmd_vgreduce vgreduce -_vgextend() +_comp_cmd_vgextend() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[AL]*)' + # shellcheck disable=SC2254 case $prev in - --autobackup | -!(-*)A) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + --autobackup | -${noargopts}A) + _comp_compgen -- -W 'y n' return ;; - --size | -!(-*)L) - _lvm_sizes + --size | -${noargopts}L) + _comp_cmd_lvm__sizes return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - local args - _lvm_count_args '@(-A|--autobackup|-L|--size)' - if ((args == 0)); then - _lvm_volumegroups + local REPLY + _comp_cmd_lvm__count_args '@(-A|--autobackup|-L|--size)' + if ((REPLY == 0)); then + _comp_cmd_lvm__volumegroups else - _lvm_physicalvolumes_all + _comp_cmd_lvm__physicalvolumes_all fi fi } && - complete -F _vgextend vgextend + complete -F _comp_cmd_vgextend vgextend -_vgport() +_comp_cmd_vgport() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_volumegroups + _comp_cmd_lvm__volumegroups fi } && - complete -F _vgport vgimport vgexport + complete -F _comp_cmd_vgport vgimport vgexport -_vgck() +_comp_cmd_vgck() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_volumegroups + _comp_cmd_lvm__volumegroups fi } && - complete -F _vgck vgck + complete -F _comp_cmd_vgck vgck -_vgconvert() +_comp_cmd_vgconvert() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[M]*)' + # shellcheck disable=SC2254 case $prev in - --metadatatype | -!(-*)M) - COMPREPLY=($(compgen -W '1 2' -- "$cur")) + --metadatatype | -${noargopts}M) + _comp_compgen -- -W '1 2' return ;; --metadatacopies) - COMPREPLY=($(compgen -W '0 1 2' -- "$cur")) + _comp_compgen -- -W '0 1 2' return ;; --metadatasize) - _lvm_sizes + _comp_cmd_lvm__sizes return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_volumegroups + _comp_cmd_lvm__volumegroups fi } && - complete -F _vgconvert vgconvert + complete -F _comp_cmd_vgconvert vgconvert -_vgcfgbackup() +_comp_cmd_vgcfgbackup() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[f]*)' + # shellcheck disable=SC2254 case $prev in - --file | -!(-*)f) - _filedir + --file | -${noargopts}f) + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_volumegroups + _comp_cmd_lvm__volumegroups fi } && - complete -F _vgcfgbackup vgcfgbackup + complete -F _comp_cmd_vgcfgbackup vgcfgbackup -_vgcfgrestore() +_comp_cmd_vgcfgrestore() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[fMn]*)' + # shellcheck disable=SC2254 case $prev in - --file | -!(-*)f) - _filedir + --file | -${noargopts}f) + _comp_compgen_filedir return ;; - --metadatatype | -!(-*)M) - COMPREPLY=($(compgen -W '1 2' -- "$cur")) + --metadatatype | -${noargopts}M) + _comp_compgen -- -W '1 2' return ;; - --name | -!(-*)n) - _lvm_volumegroups + --name | -${noargopts}n) + _comp_cmd_lvm__volumegroups return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_volumegroups + _comp_cmd_lvm__volumegroups fi } && - complete -F _vgcfgrestore vgcfgrestore + complete -F _comp_cmd_vgcfgrestore vgcfgrestore -_vgmerge() +_comp_cmd_vgmerge() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[A]*)' + # shellcheck disable=SC2254 case $prev in - --autobackup | -!(-*)A) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + --autobackup | -${noargopts}A) + _comp_compgen -- -W 'y n' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_volumegroups + _comp_cmd_lvm__volumegroups fi } && - complete -F _vgmerge vgmerge + complete -F _comp_cmd_vgmerge vgmerge -_vgsplit() +_comp_cmd_vgsplit() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[AM]*)' + # shellcheck disable=SC2254 case $prev in - --autobackup | -!(-*)A) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + --autobackup | -${noargopts}A) + _comp_compgen -- -W 'y n' return ;; - --metadatatype | -!(-*)M) - COMPREPLY=($(compgen -W '1 2' -- "$cur")) + --metadatatype | -${noargopts}M) + _comp_compgen -- -W '1 2' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - local args - _lvm_count_args '@(-A|--autobackup|-M|--metadatatype)' - if ((args == 0 || args == 1)); then - _lvm_volumegroups + local REPLY + _comp_cmd_lvm__count_args '@(-A|--autobackup|-M|--metadatatype)' + if ((REPLY < 2)); then + _comp_cmd_lvm__volumegroups else - _lvm_physicalvolumes + _comp_cmd_lvm__physicalvolumes fi fi } && - complete -F _vgsplit vgsplit + complete -F _comp_cmd_vgsplit vgsplit -_vgmknodes() +_comp_cmd_vgmknodes() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_volumegroups + _comp_cmd_lvm__volumegroups fi } && - complete -F _vgmknodes vgmknodes + complete -F _comp_cmd_vgmknodes vgmknodes -_lvscan() +_comp_cmd_lvscan() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help fi } && - complete -F _lvscan lvscan + complete -F _comp_cmd_lvscan lvscan -_lvs() +_comp_cmd_lvs() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[oO]*)' + # shellcheck disable=SC2254 case $prev in - --options | --sort | -!(-*)[oO]) - COMPREPLY=($(compgen -W 'lv_uuid lv_name lv_attr lv_minor lv_size + --options | --sort | -${noargopts}[oO]) + _comp_compgen -- -W 'lv_uuid lv_name lv_attr lv_minor lv_size seg_count origin snap_percent segtype stripes stripesize - chunksize seg_start seg_size' -- "$cur")) + chunksize seg_start seg_size' return ;; --units) - _lvm_units + _comp_cmd_lvm__units return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_logicalvolumes + _comp_cmd_lvm__logicalvolumes fi } && - complete -F _lvs lvs + complete -F _comp_cmd_lvs lvs -_lvdisplay() +_comp_cmd_lvdisplay() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --units) - _lvm_units + _comp_cmd_lvm__units return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_logicalvolumes + _comp_cmd_lvm__logicalvolumes fi } && - complete -F _lvdisplay lvdisplay + complete -F _comp_cmd_lvdisplay lvdisplay -_lvchange() +_comp_cmd_lvchange() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[aACMp]*)' + # shellcheck disable=SC2254 case $prev in - --available | --autobackup | --contiguous | --persistent | -!(-*)[aACM]) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + --available | --autobackup | --contiguous | --persistent | -${noargopts}[aACM]) + _comp_compgen -- -W 'y n' return ;; - --permission | -!(-*)p) - COMPREPLY=($(compgen -W 'r rw' -- "$cur")) + --permission | -${noargopts}p) + _comp_compgen -- -W 'r rw' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_logicalvolumes + _comp_cmd_lvm__logicalvolumes fi } && - complete -F _lvchange lvchange + complete -F _comp_cmd_lvchange lvchange -_lvcreate() +_comp_cmd_lvcreate() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[ACMZLpn]*)' + # shellcheck disable=SC2254 case $prev in - --autobackup | --contiguous | --persistent | --zero | -!(-*)[ACMZ]) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + --autobackup | --contiguous | --persistent | --zero | -${noargopts}[ACMZ]) + _comp_compgen -- -W 'y n' return ;; - --size | -!(-*)L) - _lvm_sizes + --size | -${noargopts}L) + _comp_cmd_lvm__sizes return ;; - --permission | -!(-*)p) - COMPREPLY=($(compgen -W 'r rw' -- "$cur")) + --permission | -${noargopts}p) + _comp_compgen -- -W 'r rw' return ;; - --name | -!(-*)n) - _lvm_logicalvolumes + --name | -${noargopts}n) + _comp_cmd_lvm__logicalvolumes return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - local args - _lvm_count_args '@(-A|-C|-M|-Z|--autobackup|--contiguous|--persistent|--zero|-L|--size|-p|--permission|-n|--name)' - if ((args == 0)); then - _lvm_volumegroups + local REPLY + _comp_cmd_lvm__count_args '@(-A|-C|-M|-Z|--autobackup|--contiguous|--persistent|--zero|-L|--size|-p|--permission|-n|--name)' + if ((REPLY == 0)); then + _comp_cmd_lvm__volumegroups else - _lvm_physicalvolumes + _comp_cmd_lvm__physicalvolumes fi fi } && - complete -F _lvcreate lvcreate + complete -F _comp_cmd_lvcreate lvcreate -_lvremove() +_comp_cmd_lvremove() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[A]*)' + # shellcheck disable=SC2254 case $prev in - --autobackup | -!(-*)A) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + --autobackup | -${noargopts}A) + _comp_compgen -- -W 'y n' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_logicalvolumes + _comp_cmd_lvm__logicalvolumes fi } && - complete -F _lvremove lvremove + complete -F _comp_cmd_lvremove lvremove -_lvrename() +_comp_cmd_lvrename() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[A]*)' + # shellcheck disable=SC2254 case $prev in - --autobackup | -!(-*)A) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + --autobackup | -${noargopts}A) + _comp_compgen -- -W 'y n' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_logicalvolumes + _comp_cmd_lvm__logicalvolumes fi } && - complete -F _lvrename lvrename + complete -F _comp_cmd_lvrename lvrename -_lvreduce() +_comp_cmd_lvreduce() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[AL]*)' + # shellcheck disable=SC2254 case $prev in - --autobackup | -!(-*)A) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + --autobackup | -${noargopts}A) + _comp_compgen -- -W 'y n' return ;; - --size | -!(-*)L) - _lvm_sizes + --size | -${noargopts}L) + _comp_cmd_lvm__sizes return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _lvm_logicalvolumes + _comp_cmd_lvm__logicalvolumes fi } && - complete -F _lvreduce lvreduce + complete -F _comp_cmd_lvreduce lvreduce -_lvresize() +_comp_cmd_lvresize() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[AL]*)' + # shellcheck disable=SC2254 case $prev in - --autobackup | -!(-*)A) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + --autobackup | -${noargopts}A) + _comp_compgen -- -W 'y n' return ;; - --size | -!(-*)L) - _lvm_sizes + --size | -${noargopts}L) + _comp_cmd_lvm__sizes return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - local args - _lvm_count_args '@(-A|--autobackup|-L|--size)' - if ((args == 0)); then - _lvm_logicalvolumes + local REPLY + _comp_cmd_lvm__count_args '@(-A|--autobackup|-L|--size)' + if ((REPLY == 0)); then + _comp_cmd_lvm__logicalvolumes else - _lvm_physicalvolumes + _comp_cmd_lvm__physicalvolumes fi fi } && - complete -F _lvresize lvresize + complete -F _comp_cmd_lvresize lvresize -_lvextend() +_comp_cmd_lvextend() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[AL]*)' + # shellcheck disable=SC2254 case $prev in - --autobackup | -!(-*)A) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + --autobackup | -${noargopts}A) + _comp_compgen -- -W 'y n' return ;; - --size | -!(-*)L) - _lvm_sizes + --size | -${noargopts}L) + _comp_cmd_lvm__sizes return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - local args - _lvm_count_args '@(-A|--autobackup|-L|--size)' - if ((args == 0)); then - _lvm_logicalvolumes + local REPLY + _comp_cmd_lvm__count_args '@(-A|--autobackup|-L|--size)' + if ((REPLY == 0)); then + _comp_cmd_lvm__logicalvolumes else - _lvm_physicalvolumes + _comp_cmd_lvm__physicalvolumes fi fi } && - complete -F _lvextend lvextend + complete -F _comp_cmd_lvextend lvextend -_lvm() +_comp_cmd_lvm() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if ((cword == 1)); then - COMPREPLY=($(compgen -W 'dumpconfig help lvchange lvcreate lvdisplay + _comp_compgen -- -W 'dumpconfig help lvchange lvcreate lvdisplay lvextend lvmchange lvmdiskscan lvmsadc lvmsar lvreduce lvremove lvrename lvresize lvs lvscan pvchange pvcreate pvdata pvdisplay pvmove pvremove pvresize pvs pvscan vgcfgbackup vgcfgrestore vgchange vgck vgconvert vgcreate vgdisplay vgexport vgextend vgimport vgmerge vgmknodes vgreduce vgremove vgrename vgs vgscan - vgsplit version' -- "$cur")) + vgsplit version' else case "${words[1]}" in pvchange | pvcreate | pvdisplay | pvmove | pvremove | pvresize | pvs | pvscan | \ @@ -851,11 +895,11 @@ _lvm() vgdisplay | vgexport | vgextend | vgimport | vgmerge | vgmknodes | vgreduce | \ vgremove | vgrename | vgs | vgscan | vgsplit | lvchange | lvcreate | lvdisplay | \ lvextend | lvreduce | lvremove | lvrename | lvresize | lvscan) - _${words[1]} + _comp_command_offset 1 ;; esac fi } && - complete -F _lvm lvm + complete -F _comp_cmd_lvm lvm # ex: filetype=sh diff --git a/completions/lz4 b/completions/lz4 index f297b5d..8e2a777 100644 --- a/completions/lz4 +++ b/completions/lz4 @@ -1,25 +1,27 @@ # lz4 completion -*- shell-script -*- -_lz4() +_comp_cmd_lz4() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -b) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -X '-*#*' -W \ - '$(_parse_help "$1" -h) -B{4..7} -i{1..9}' -- "$cur")) + _comp_compgen -R help -- -h + _comp_compgen -- -X '-*#*' -W \ + '${COMPREPLY+"${COMPREPLY[@]}"} -B{4..7} -i{1..9}' return fi - local args word xspec="*.?(t)lz4" - _count_args + local REPLY word xspec="*.?(t)lz4" + _comp_count_args + local args=$REPLY ((args > 2)) && return for word in "${words[@]}"; do @@ -41,12 +43,11 @@ _lz4() esac done - _tilde "$cur" || return + _comp_compgen_tilde && return - local IFS=$'\n' compopt -o filenames - COMPREPLY=($(compgen -f -X "$xspec" -- "$cur") $(compgen -d -- "$cur")) + _comp_compgen -- -f -X "$xspec" -o plusdirs } && - complete -F _lz4 lz4 lz4c + complete -F _comp_cmd_lz4 lz4 lz4c # ex: filetype=sh diff --git a/completions/lzip b/completions/lzip index 05f169c..cd33f60 100644 --- a/completions/lzip +++ b/completions/lzip @@ -1,47 +1,51 @@ # lzip(1) completion -*- shell-script -*- -_lzip() +_comp_cmd_lzip() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return - local decompress=false + local decompress="" + local noargopts='!(-*|*[bmsSBdno]*)' + # shellcheck disable=SC2254 case $prev in --help | --version | --member-size | --match-length | --dictionary-size | \ - --volume-size | --data-size | -!(-*)@([bmsSB]|[hV]*)) + --volume-size | --data-size | -${noargopts}@([bmsSB]|[hV]*)) return ;; - --decompress-!(-*)d) - decompress=true + --decompress | -${noargopts}d) + decompress=set ;; - --threads-!(-*)n) - COMPREPLY=($(compgen -W "{1..$(_ncpus)}" -- "$cur")) + --threads | -${noargopts}n) + local REPLY + _comp_get_ncpus + _comp_compgen -- -W "{1..$REPLY}" return ;; - --output-!(-*)o) - _filedir + --output | -${noargopts}o) + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1") {-1..-9}' -- "$cur")) + _comp_compgen_help + _comp_compgen -a -- -W '-{1..9}' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - if $decompress; then - _filedir lz + if [[ $decompress ]]; then + _comp_compgen_filedir lz return fi - local IFS=$'\n' compopt -o filenames - COMPREPLY=($(compgen -f -X "*.lz" -- "$cur") $(compgen -d -- "$cur")) + _comp_compgen -- -f -X "*.lz" -o plusdirs } && - complete -F _lzip clzip lzip pdlzip plzip + complete -F _comp_cmd_lzip clzip lzip pdlzip plzip # ex: filetype=sh diff --git a/completions/lzma b/completions/lzma index 34fba89..c1ae07d 100644 --- a/completions/lzma +++ b/completions/lzma @@ -1,20 +1,21 @@ # lzma(1) completion -*- shell-script -*- # by Per Øyvind Karlsen <peroyvind@mandriva.org> -_lzma() +_comp_cmd_lzma() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1") -{1..9}' -- "$cur")) + _comp_compgen_help + _comp_compgen -a -- -W '-{1..9}' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - local IFS=$'\n' xspec="*.@(lzma|tlz)" + local xspec="*.@(lzma|tlz)" if [[ $prev == --* ]]; then [[ $prev == --@(decompress|list|test) ]] && xspec="!"$xspec @@ -24,11 +25,11 @@ _lzma() [[ $prev == -*z* ]] && xspec= fi - _tilde "$cur" || return + _comp_compgen_tilde && return compopt -o filenames - COMPREPLY=($(compgen -f -X "$xspec" -- "$cur") $(compgen -d -- "$cur")) + _comp_compgen -- -f -X "$xspec" -o plusdirs } && - complete -F _lzma lzma + complete -F _comp_cmd_lzma lzma # ex: filetype=sh diff --git a/completions/lzop b/completions/lzop index 2642742..5cbd51f 100644 --- a/completions/lzop +++ b/completions/lzop @@ -1,32 +1,33 @@ # lzop(1) completion -*- shell-script -*- -_lzop() +_comp_cmd_lzop() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[oS]*)' + # shellcheck disable=SC2254 case $prev in - --output | -!(-*)o) - _filedir + --output | -${noargopts}o) + _comp_compgen_filedir return ;; --path) - _filedir -d + _comp_compgen_filedir -d return ;; - --suffix | -!(-*)S) + --suffix | -${noargopts}S) return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-1 -2 -3 -4 -5 -6 -7 -8 -9 -P + _comp_compgen -- -W '-{1..9} -P --fast --best --decompress --extract --test --list --ls --info --sysinfo --license --help --version --stdout --output --path --force --no-checksum --no-name --name --no-mode --no-time --suffix --keep --delete --crc32 --no-warn --ignore-warn --quiet --verbose - --no-stdin --filter --checksum --no-color --mono --color' \ - -- "$cur")) + --no-stdin --filter --checksum --no-color --mono --color' return fi @@ -48,12 +49,11 @@ _lzop() ;; esac - _tilde "$cur" || return + _comp_compgen_tilde && return - local IFS=$'\n' compopt -o filenames - COMPREPLY=($(compgen -f -X "$xspec" -- "$cur") $(compgen -d -- "$cur")) + _comp_compgen -- -f -X "$xspec" -o plusdirs } && - complete -F _lzop lzop + complete -F _comp_cmd_lzop lzop # ex: filetype=sh diff --git a/completions/macof b/completions/macof index ad29f58..408e446 100644 --- a/completions/macof +++ b/completions/macof @@ -1,22 +1,22 @@ # macof completion -*- shell-script -*- -_macof() +_comp_cmd_macof() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -i) - _available_interfaces -a + _comp_compgen_available_interfaces -a return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage fi } && - complete -F _macof macof + complete -F _comp_cmd_macof macof # ex: filetype=sh diff --git a/completions/mailmanctl b/completions/mailmanctl index 3bbc2f2..b29487a 100644 --- a/completions/mailmanctl +++ b/completions/mailmanctl @@ -1,18 +1,18 @@ # mailmanctl completion -*- shell-script -*- -_mailmanctl() +_comp_cmd_mailmanctl() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--no-restart --run-as-user - --stale-lock-cleanup --quiet --help' -- "$cur")) + _comp_compgen -- -W '--no-restart --run-as-user --stale-lock-cleanup + --quiet --help' else - COMPREPLY=($(compgen -W 'start stop restart reopen' -- "$cur")) + _comp_compgen -- -W 'start stop restart reopen' fi } && - complete -F _mailmanctl mailmanctl + complete -F _comp_cmd_mailmanctl mailmanctl # ex: filetype=sh diff --git a/completions/make b/completions/make index 96517c2..94e2b73 100644 --- a/completions/make +++ b/completions/make @@ -1,135 +1,128 @@ # bash completion for GNU make -*- shell-script -*- -_make_target_extract_script() +# Extract the valid target names starting with PREFIX from the output of +# `make -npq' +# @param mode If this is `-d', the directory names already specified in +# PREFIX are omitted in the output +# @param prefix Prefix of the target names +_comp_cmd_make__extract_targets() { - local mode="$1" - shift + local mode=$1 + local -x prefix=$2 - local prefix="$1" - local prefix_pat=$(command sed 's/[][\,.*^$(){}?+|/]/\\&/g' <<<"$prefix") - local basename=${prefix##*/} - local dirname_len=$((${#prefix} - ${#basename})) + # display mode, only output current path component to the next slash + local -x prefix_replace=$prefix + [[ $mode == -d && $prefix == */* ]] && + prefix_replace=${prefix##*/} - if [[ $mode == -d ]]; then - # display mode, only output current path component to the next slash - local output="\2" - else - # completion mode, output full path to the next slash - local output="\1\2" - fi - - cat <<EOF - 1,/^# * Make data base/ d; # skip any makefile output - /^# * Finished Make data base/,/^# * Make data base/{ - d; # skip any makefile output - } - /^# * Variables/,/^# * Files/ d; # skip until files section - /^# * Not a target/,/^$/ d; # skip not target blocks - /^${prefix_pat}/,/^$/! d; # skip anything user dont want - - # The stuff above here describes lines that are not - # explicit targets or not targets other than special ones - # The stuff below here decides whether an explicit target - # should be output. - - /^# * File is an intermediate prerequisite/ { - s/^.*$//;x; # unhold target - d; # delete line - } - - /^$/ { # end of target block - x; # unhold target - /^$/d; # dont print blanks - s|^\(.\{${dirname_len}\}\)\(.\{${#basename}\}[^:/]*/\{0,1\}\)[^:]*:.*$|${output}|p; - d; # hide any bugs - } - - # This pattern includes a literal tab character as \t is not a portable - # representation and fails with BSD sed - /^[^# :%]\{1,\}:/ { # found target block - /^\.PHONY:/ d; # special target - /^\.SUFFIXES:/ d; # special target - /^\.DEFAULT:/ d; # special target - /^\.PRECIOUS:/ d; # special target - /^\.INTERMEDIATE:/ d; # special target - /^\.SECONDARY:/ d; # special target - /^\.SECONDEXPANSION:/ d; # special target - /^\.DELETE_ON_ERROR:/ d; # special target - /^\.IGNORE:/ d; # special target - /^\.LOW_RESOLUTION_TIME:/ d; # special target - /^\.SILENT:/ d; # special target - /^\.EXPORT_ALL_VARIABLES:/ d; # special target - /^\.NOTPARALLEL:/ d; # special target - /^\.ONESHELL:/ d; # special target - /^\.POSIX:/ d; # special target - /^\.NOEXPORT:/ d; # special target - /^\.MAKE:/ d; # special target -EOF - - # don't complete with hidden targets unless we are doing a partial completion - if [[ -z ${prefix_pat} || ${prefix_pat} == */ ]]; then - cat <<EOF - /^${prefix_pat}[^a-zA-Z0-9]/d; # convention for hidden tgt -EOF - fi + _comp_awk -f "${BASH_SOURCE[0]%/*}/../helpers/make-extract-targets.awk" +} - cat <<EOF - h; # hold target - d; # delete line - } +# Truncate the non-unique filepaths in COMPREPLY to only generate unique +# directories or files. This function discards the files under subdirectories +# unless the path is unique under each subdirectory and instead generate the +# subdirectory path. For example, when there are two candidates, "abc/def" and +# "abc/xyz", we generate "abc/" instead of generating both candidates directly. +# When there is only one candidate "abc/def", we generate the full path +# "abc/def". +# +# @var[in] cur +# @var[in] mode +# @var[in,out] COMPREPLY +_comp_cmd_make__truncate_non_unique_paths() +{ + local prefix=$cur + [[ $mode == -d ]] && prefix= + if ((${#COMPREPLY[@]} > 0)); then + # collect the possible completions including the directory names in + # `paths' and count the number of children of each subdirectory in + # `nchild'. + local -A paths nchild + local target + for target in "${COMPREPLY[@]}"; do + local path=${target%/} + while [[ ! ${paths[$path]+set} ]] && + paths[$path]=set && + [[ $path == "$prefix"*/* ]]; do + path=${path%/*} + nchild[$path]=$((${nchild[$path]-0} + 1)) + done + done -EOF + COMPREPLY=() + local nreply=0 + for target in "${!paths[@]}"; do + # generate only the paths that do not have a unique child and whose + # all parent and ancestor directories have a unique child. + ((${nchild[$target]-0} == 1)) && continue + local path=$target + while [[ $path == "$prefix"*/* ]]; do + path=${path%/*} + ((${nchild[$path]-0} == 1)) || continue 2 + done + + # suffix `/' when the target path is a subdiretory, which has + # at least one child. + COMPREPLY[nreply++]=$target${nchild[$target]+/} + done + fi } -_make() +_comp_cmd_make() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return local makef makef_dir=("-C" ".") i + local noargopts='!(-*|*[foWICmEDVxj]*)' + # shellcheck disable=SC2254 case $prev in --file | --makefile | --old-file | --assume-old | --what-if | --new-file | \ - --assume-new | -!(-*)[foW]) - _filedir + --assume-new | -${noargopts}[foW]) + _comp_compgen_filedir return ;; - --include-dir | --directory | -!(-*)[ICm]) - _filedir -d + --include-dir | --directory | -${noargopts}[ICm]) + _comp_compgen_filedir -d return ;; - -!(-*)E) - COMPREPLY=($(compgen -v -- "$cur")) + -${noargopts}E) + _comp_compgen -- -v return ;; - --eval | -!(-*)[DVx]) + --eval | -${noargopts}[DVx]) return ;; - --jobs | -!(-*)j) - COMPREPLY=($(compgen -W "{1..$(($(_ncpus) * 2))}" -- "$cur")) + --jobs | -${noargopts}j) + local REPLY + _comp_get_ncpus + _comp_compgen -- -W "{1..$((REPLY * 2))}" return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - local opts="$(_parse_help "$1")" - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage [[ ${COMPREPLY-} == *= ]] && compopt -o nospace elif [[ $cur == *=* ]]; then prev=${cur%%=*} cur=${cur#*=} local diropt [[ ${prev,,} == *dir?(ectory) ]] && diropt=-d - _filedir $diropt + _comp_compgen_filedir $diropt else # before we check for makefiles, see if a path was specified # with -C/--directory for ((i = 1; i < ${#words[@]}; i++)); do - if [[ ${words[i]} == -@(C|-directory) ]]; then - # eval for tilde expansion - eval "makef_dir=( -C \"${words[i + 1]}\" )" + if [[ ${words[i]} == @(-${noargopts}C|--directory) ]]; then + # Expand tilde expansion + local REPLY + _comp_dequote "${words[i + 1]-}" && + [[ -d ${REPLY-} ]] && + makef_dir=(-C "$REPLY") break fi done @@ -137,25 +130,36 @@ _make() # before we scan for targets, see if a Makefile name was # specified with -f/--file/--makefile for ((i = 1; i < ${#words[@]}; i++)); do - if [[ ${words[i]} == -@(f|-?(make)file) ]]; then - # eval for tilde expansion - eval "makef=( -f \"${words[i + 1]}\" )" + if [[ ${words[i]} == @(-${noargopts}f|--?(make)file) ]]; then + # Expand tilde expansion + local REPLY + _comp_dequote "${words[i + 1]-}" && + [[ -f ${REPLY-} ]] && + makef=(-f "$REPLY") break fi done - # recognise that possible completions are only going to be displayed - # so only the base name is shown + # recognise that possible completions are only going to be displayed so + # only the base name is shown. + # + # Note: This is currently turned off because the test suite of + # bash-completion conflicts with it; it uses "set show-all-if-ambiguous + # on" (causing COMP_TYPE == 37) to retrieve the action completion + # results, and also the compact form with only the basenames is not + # essentially needed. To re-enable it, please uncomment the following + # if-statement. local mode=-- - if ((COMP_TYPE != 9)); then - mode=-d # display-only mode - fi + # if ((COMP_TYPE != 9 && COMP_TYPE != 37 && COMP_TYPE != 42)); then + # mode=-d # display-only mode + # fi - local IFS=$' \t\n' script=$(_make_target_extract_script $mode "$cur") - COMPREPLY=($(LC_ALL=C \ + _comp_split COMPREPLY "$(LC_ALL=C \ $1 -npq __BASH_MAKE_COMPLETION__=1 \ ${makef+"${makef[@]}"} "${makef_dir[@]}" .DEFAULT 2>/dev/null | - command sed -ne "$script")) + _comp_cmd_make__extract_targets "$mode" "$cur")" + + _comp_cmd_make__truncate_non_unique_paths if [[ $mode != -d ]]; then # Completion will occur if there is only one suggestion @@ -165,6 +169,6 @@ _make() fi } && - complete -F _make make gmake gnumake pmake colormake bmake + complete -F _comp_cmd_make make gmake gnumake pmake colormake bmake # ex: filetype=sh diff --git a/completions/makepkg b/completions/makepkg index 23ac784..f6bdc65 100644 --- a/completions/makepkg +++ b/completions/makepkg @@ -1,29 +1,27 @@ # makepkg completion -*- shell-script -*- # Slackware Linux variant -_makepkg_slackware() +_comp_cmd_makepkg__slackware() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case "$prev" in -l | --linkadd | -c | --chown) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + _comp_compgen -- -W 'y n' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W \ - '$($1 | command sed -e "s/^options://" | _parse_help -)' \ - -- "$cur")) + _comp_compgen_help - <<<"$("$1" | command sed -e "s/^options://")" return fi - _filedir + _comp_compgen_filedir } -_makepkg_bootstrap() +_comp_cmd_makepkg__bootstrap() { local fname help @@ -32,17 +30,17 @@ _makepkg_bootstrap() help=$("$1" --help 2>&1) case ${help,,} in *slackware*) - fname=_makepkg_slackware + fname=_comp_cmd_makepkg__slackware ;; *) - fname=_minimal + fname=_comp_complete_minimal ;; esac - unset -f _makepkg_bootstrap + unset -f "$FUNCNAME" complete -F $fname makepkg - $fname + $fname "$@" } && - complete -F _makepkg_bootstrap makepkg + complete -F _comp_cmd_makepkg__bootstrap makepkg # ex: filetype=sh diff --git a/completions/man b/completions/man index 81d06f5..b405f08 100644 --- a/completions/man +++ b/completions/man @@ -1,86 +1,95 @@ # man(1) completion -*- shell-script -*- -_man() +_comp_cmd_man() { - local cur prev words cword split - _init_completion -s -n : || return + local cur prev words cword was_split comp_args + _comp_initialize -s -n : -- "$@" || return - local comprsuffix=".@([glx]z|bz2|lzma|Z)" - local manext="@([0-9lnp]|[0-9][px]|man|3?(gl|pm))?($comprsuffix)" - local mansect="@([0-9lnp]|[0-9][px]|3?(gl|pm))" + local comprsuffix=".@([glx]z|bz2|lzma|Z|zst)" + local manext="@([0-9]*([a-z])|[lnp]|man)?($comprsuffix)" + local mansect="@([0-9]*([a-z])|[lnp])" + local noargopts='!(-*|*[ClMSsPpLmerRE]*)' + # shellcheck disable=SC2254 case $prev in - --config-file | -!(-*)C) - _filedir conf + --config-file | -${noargopts}C) + _comp_compgen_filedir conf return ;; - --local-file | -!(-*)l) - _filedir "$manext" + --local-file | -${noargopts}l) + _comp_compgen_filedir "$manext" return ;; - --manpath | -!(-*)M) - _filedir -d + --manpath | -${noargopts}M) + _comp_compgen_filedir -d return ;; - --pager | -!(-*)P) - compopt -o filenames - COMPREPLY=($(compgen -c -- "$cur")) + --sections | -${noargopts}[Ss]) + _comp_delimited : -W '{1..9}' return ;; - --preprocessor | -!(-*)p) - COMPREPLY=($(compgen -W 'e p t g r v' -- "$cur")) + --pager | -${noargopts}P) + _comp_compgen_commands + return + ;; + --preprocessor | -${noargopts}p) + _comp_compgen -- -W 'e p t g r v' return ;; --locale | --systems | --extension | --prompt | --recode | --encoding | \ - -!(-*)[LmerRE]) + -${noargopts}[LmerRE]) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - local opts=$(_parse_help "$1" -h) - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help -- -h || _comp_compgen_usage [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi # file based completion if parameter looks like a path - if [[ $cur == @(*/|[.~])* ]]; then - _filedir "$manext" + if _comp_looks_like_path "$cur"; then + _comp_compgen_filedir "$manext" return fi local manpath=$(manpath 2>/dev/null || command man -w 2>/dev/null) - [[ -z $manpath ]] && manpath="/usr/share/man:/usr/local/share/man" + if [[ ! $manpath ]]; then + # Note: Both "manpath" and "man -w" may be unavailable, in + # which case we determine the man paths based on the + # environment variable MANPATH. + manpath=:${MANPATH-}: + # Note: An empty path (represented by two consecutive colons + # or a preceding/trailing colon) represents the system man + # paths. + manpath=${manpath//::/':/usr/share/man:/usr/local/share/man:'} + manpath=${manpath:1:-1} + fi # determine manual section to search local sect # shellcheck disable=SC2053 [[ $prev == $mansect ]] && sect=$prev || sect='*' - _expand || return - - manpath=$manpath: - if [[ -n $cur ]]; then - manpath="${manpath//://*man$sect/$cur* } ${manpath//://*cat$sect/$cur* }" - else - manpath="${manpath//://*man$sect/ } ${manpath//://*cat$sect/ }" - fi - - local IFS=$' \t\n' reset=$(shopt -p failglob) - shopt -u failglob - # redirect stderr for when path doesn't exist - COMPREPLY=($(eval command ls "$manpath" 2>/dev/null)) - $reset + _comp_split -F : manpath "$manpath" + if ((${#manpath[@]})); then + local manfiles + _comp_compgen -Rv manfiles -- -S "/*man$sect/$cur*" -W '"${manpath[@]}"' + _comp_compgen -aRv manfiles -- -S "/*cat$sect/$cur*" -W '"${manpath[@]}"' - if ((${#COMPREPLY[@]} != 0)); then - # weed out directory path names and paths to man pages - COMPREPLY=(${COMPREPLY[@]##*/?(:)}) - # strip suffix from man pages - COMPREPLY=(${COMPREPLY[@]%$comprsuffix}) - COMPREPLY=($(compgen -W '${COMPREPLY[@]%.*}' -- "${cur//\\\\/}")) + local IFS= + if _comp_expand_glob COMPREPLY '${manfiles[@]}'; then + # weed out directory path names and paths to man pages (empty + # elements will be removed by the later `compgen -X ''`) + COMPREPLY=("${COMPREPLY[@]##*/?(:)}") + # strip suffix from man pages + COMPREPLY=("${COMPREPLY[@]%$comprsuffix}") + _comp_compgen -c "${cur//\\\\/}" -- -W '"${COMPREPLY[@]%.*}"' -X '' + fi + _comp_unlocal IFS fi # shellcheck disable=SC2053 @@ -88,14 +97,14 @@ _man() # File based completion for the rest, prepending ./ if needed # (man 1.6f needs that for man pages in current dir) local i start=${#COMPREPLY[@]} - _filedir "$manext" + _comp_compgen -a filedir "$manext" for ((i = start; i < ${#COMPREPLY[@]}; i++)); do [[ ${COMPREPLY[i]} == */* ]] || COMPREPLY[i]=./${COMPREPLY[i]} done fi - __ltrim_colon_completions "$cur" + _comp_ltrim_colon_completions "$cur" } && - complete -F _man man apropos whatis + complete -F _comp_cmd_man man apropos whatis # ex: filetype=sh diff --git a/completions/mc b/completions/mc index cf38821..5ea2423 100644 --- a/completions/mc +++ b/completions/mc @@ -1,29 +1,31 @@ # bash completion for mc -*- shell-script -*- -_mc() +_comp_cmd_mc() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[evlPCD]*)' + # shellcheck disable=SC2254 case $prev in - --edit | --view | --ftplog | --printwd | -!(-*)[evlP]) - _filedir + --edit | --view | --ftplog | --printwd | -${noargopts}[evlP]) + _comp_compgen_filedir return ;; - --help | --help-* | --version | --colors | --debuglevel | -!(-*)[hVCD]) + --help | --help-* | --version | --colors | --debuglevel | -${noargopts}[hVCD]) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" --help-all)' -- "$cur")) + _comp_compgen_help -- --help-all [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - _filedir -d + _comp_compgen_filedir -d fi } && - complete -F _mc mc + complete -F _comp_cmd_mc mc # ex: filetype=sh diff --git a/completions/mcrypt b/completions/mcrypt index 0c3ab5e..3135244 100644 --- a/completions/mcrypt +++ b/completions/mcrypt @@ -1,67 +1,65 @@ # mcrypt(1) completion -*- shell-script -*- # by Ariel Fermani <the_end@bbs.frc.utn.edu.ar> -_mcrypt() +_comp_cmd_mcrypt() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -g | --openpgp-z) - COMPREPLY=($(compgen -W '{0..9}' -- "$cur")) + _comp_compgen -- -W '{0..9}' return ;; -o | --keymode) - COMPREPLY=($(compgen -W '$($1 --list-keymodes 2>/dev/null )' \ - -- "$cur")) + _comp_compgen_split -- "$("$1" --list-keymodes 2>/dev/null)" return ;; -m | --mode) - COMPREPLY=($(compgen -W "$($1 --list 2>/dev/null | cut -d: -f2-)" \ - -- "$cur")) + _comp_compgen_split -- "$("$1" --list 2>/dev/null | cut -d: -f2-)" return ;; -a | --algorithm) - COMPREPLY=($(compgen -W "$($1 --list 2>/dev/null | - awk '{print $1}')" -- "$cur")) + _comp_compgen_split -- "$("$1" --list 2>/dev/null | + _comp_awk '{print $1}')" return ;; -h | --hash) - COMPREPLY=($(compgen -W '$($1 --list-hash 2>/dev/null | \ - command sed -e 1d)' -- "$cur")) + _comp_compgen_split -- "$("$1" --list-hash 2>/dev/null | + command sed -e 1d)" return ;; -k | -s | --key | --keysize) return ;; -f | -c | --keyfile | --config) - _filedir + _comp_compgen_filedir return ;; --algorithms-directory | --modes-directory) - _filedir -d + _comp_compgen_filedir -d return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help elif [[ ${words[0]} == mdecrypt ]]; then - _filedir nc + _comp_compgen_filedir nc else - local i decrypt=0 - for ((i = 1; i < ${#words[@]} - 1; i++)); do + local i decrypt="" + for ((i = 1; i < cword; i++)); do if [[ ${words[i]} == -@(d|-decrypt) ]]; then - _filedir nc - decrypt=1 + _comp_compgen_filedir nc + decrypt=set break fi done - if ((decrypt == 0)); then - _filedir + if [[ ! $decrypt ]]; then + _comp_compgen_filedir fi fi } && - complete -F _mcrypt mcrypt mdecrypt + complete -F _comp_cmd_mcrypt mcrypt mdecrypt # ex: filetype=sh diff --git a/completions/mdadm b/completions/mdadm index 37effd9..e67558d 100644 --- a/completions/mdadm +++ b/completions/mdadm @@ -1,16 +1,18 @@ # bash completion for mdadm -*- shell-script -*- -_mdadm_raid_level() +_comp_cmd_mdadm__raid_level() { - local mode + local mode="" + local i noargopts='!(-*|*[CB]*)' for ((i = 1; i < cword; i++)); do + # shellcheck disable=SC2254 case ${words[i]} in - -!(-*)C* | --create) + -${noargopts}C* | --create) mode=create break ;; - -!(-*)B* | --build) + -${noargopts}B* | --build) mode=build break ;; @@ -19,20 +21,19 @@ _mdadm_raid_level() case $mode in create) - COMPREPLY=($(compgen -W 'linear raid0 0 stripe raid1 1 mirror - raid4 4 raid5 5 raid6 6 raid10 10 multipath mp faulty' \ - -- "$cur")) + _comp_compgen -- -W 'linear raid0 0 stripe raid1 1 mirror raid4 4 + raid5 5 raid6 6 raid10 10 multipath mp faulty' ;; build) - COMPREPLY=($(compgen -W 'linear stripe raid0 0 raid1 multipath mp - faulty' -- "$cur")) + _comp_compgen -- -W 'linear stripe raid0 0 raid1 multipath mp + faulty' ;; esac } -_mdadm_raid_layout() +_comp_cmd_mdadm__raid_layout() { - local level + local i level="" for ((i = 1; i < cword; i++)); do if [[ ${words[i]} == -@(l|-level) ]]; then level=${words[i + 1]} @@ -42,108 +43,107 @@ _mdadm_raid_layout() case $level in raid5) - COMPREPLY=($(compgen -W 'left-asymmetric left-symmetric - right-asymmetric right-symmetric la ra ls rs' -- "$cur")) + _comp_compgen -- -W 'left-asymmetric left-symmetric + right-asymmetric right-symmetric la ra ls rs' ;; raid10) - COMPREPLY=($(compgen -W 'n o p' -- "$cur")) + _comp_compgen -- -W 'n o p' ;; faulty) - COMPREPLY=($(compgen -W 'write-transient wt read-transient rt + _comp_compgen -- -W 'write-transient wt read-transient rt write-persistent wp read-persistent rp write-all read-fixable - rf clear flush none' -- "$cur")) + rf clear flush none' ;; esac } -_mdadm_auto_flag() +_comp_cmd_mdadm__auto_flag() { - COMPREPLY=($(compgen -W 'no yes md mdp part p' -- "$cur")) + _comp_compgen -- -W 'no yes md mdp part p' } -_mdadm_update_flag() +_comp_cmd_mdadm__update_flag() { - COMPREPLY=($(compgen -W 'sparc2.2 summaries uuid name homehost resync - byteorder super-minor' -- "$cur")) + _comp_compgen -- -W 'sparc2.2 summaries uuid name homehost resync byteorder + super-minor' } -_mdadm() +_comp_cmd_mdadm() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[cblpaU]*)' + # shellcheck disable=SC2254 case $prev in - --config | --bitmap | --backup-file | -!(-*)[cb]) - _filedir + --config | --bitmap | --backup-file | -${noargopts}[cb]) + _comp_compgen_filedir return ;; - --level | -!(-*)l) - _mdadm_raid_level + --level | -${noargopts}l) + _comp_cmd_mdadm__raid_level return ;; - --layout | --parity | -!(-*)p) - _mdadm_raid_layout + --layout | --parity | -${noargopts}p) + _comp_cmd_mdadm__raid_layout return ;; - --auto | -!(-*)a) - _mdadm_auto_flag + --auto | -${noargopts}a) + _comp_cmd_mdadm__auto_flag return ;; - --update | -!(-*)U) - _mdadm_update_flag + --update | -${noargopts}U) + _comp_cmd_mdadm__update_flag return ;; esac - $split && return + [[ $was_split ]] && return local options='--help --help-options --version --verbose --quiet --brief --force --config= --scan --metadata= --homehost=' if [[ $cur == -* ]]; then if ((cword == 1)); then - COMPREPLY=($(compgen -W "$options --assemble --build --create - --monitor --grow" -- "$cur")) + _comp_compgen -- -W "$options --assemble --build --create --monitor + --grow" else + # shellcheck disable=SC2254 case ${words[cword - 1]} in - --assemble | -!(-*)A*) - COMPREPLY=($(compgen -W "$options --uuid= --super-minor= + --assemble | -${noargopts}A*) + _comp_compgen -- -W "$options --uuid= --super-minor= --name= --force --run --no-degraded --auto= --bitmap= - --backup-file= --update= --auto-update-homehost" \ - -- "$cur")) + --backup-file= --update= --auto-update-homehost" ;; - --build | --create | --grow | -!(-*)[BCG]*) - COMPREPLY=($(compgen -W "$options --raid-devices= + --build | --create | --grow | -${noargopts}[BCG]*) + _comp_compgen -- -W "$options --raid-devices= --spare-devices= --size= --chunk= --rounding= --level= --layout= --parity= --bitmap= --bitmap-chunk= --write-mostly --write-behind= --assume-clean - --backup-file= --name= --run --force --auto=" \ - -- "$cur")) + --backup-file= --name= --run --force --auto=" ;; - --follow | --monitor | -!(-*)F) - COMPREPLY=($(compgen -W "$options --mail --program - --alert --syslog --delay --daemonise --pid-file - --oneshot --test" -- "$cur")) + --follow | --monitor | -${noargopts}F) + _comp_compgen -- -W "$options --mail --program --alert + --syslog --delay --daemonise --pid-file --oneshot + --test" ;; /dev/* | --add | --fail | --remove) - COMPREPLY=($(compgen -W "$options --add --re-add - --remove --fail --set-faulty" -- "$cur")) + _comp_compgen -- -W "$options --add --re-add --remove + --fail --set-faulty" ;; *) - COMPREPLY=($(compgen -W "$options --query --detail - --examine --sparc2.2 --examine-bitmap --run --stop - --readonly --readwrite --zero-superblock --test" \ - -- "$cur")) + _comp_compgen -- -W "$options --query --detail --examine + --sparc2.2 --examine-bitmap --run --stop --readonly + --readwrite --zero-superblock --test" ;; esac fi [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - cur=${cur:=/dev/} - _filedir + _comp_compgen -c "${cur:-/dev/}" filedir fi } && - complete -F _mdadm mdadm + complete -F _comp_cmd_mdadm mdadm # ex: filetype=sh diff --git a/completions/mdtool b/completions/mdtool index 428e33b..cd179e5 100644 --- a/completions/mdtool +++ b/completions/mdtool @@ -1,32 +1,30 @@ # mdtool completion -*- shell-script -*- -_mdtool() +_comp_cmd_mdtool() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - local command i - - for ((i = 1; i < ${#words[@]} - 1; i++)); do + local command="" i + for ((i = 1; i < cword; i++)); do if [[ ${words[i]} == @(build|generate-makefiles|setup) ]]; then command=${words[i]} break fi done - if [[ -v command ]]; then + if [[ $command ]]; then case $command in "build") - COMPREPLY=($(compgen -W '--f --buildfile --p --project' \ - -S":" -- "$cur")) + _comp_compgen -- -W '--f --buildfile --p --project' -S":" # TODO: This does not work :( #if [[ "$prev" == *: ]]; then # case $prev in # @(--p:|--project:)) - # COMPREPLY=( $(compgen -f -G "*.mdp" -- "$cur") ) + # _comp_compgen -- -f -G "*.mdp" # ;; # @(--f:|--buildfile:)) - # COMPREPLY=( $(compgen -f -G "*.mdp" -G "*.mds" -- "$cur") ) + # _comp_compgen -- -f -G "*.mdp" -G "*.mds" # ;; # esac #fi @@ -34,29 +32,27 @@ _mdtool() ;; "generate-makefiles") compopt -o filenames - COMPREPLY=($(compgen -o filenames -G"*.mds" -- "$cur")) + _comp_compgen -- -o filenames -G"*.mds" if [[ $prev == *mds ]]; then - COMPREPLY=($(compgen -W '--simple-makefiles --s --d:' \ - -- "$cur")) + _comp_compgen -- -W '--simple-makefiles --s --d:' fi return ;; "setup") # TODO: at least return filenames after these options. - COMPREPLY=($(compgen -W 'install i uninstall u check-install - ci update up list l list-av la list-update lu rep-add ra + _comp_compgen -- -W 'install i uninstall u check-install ci + update up list l list-av la list-update lu rep-add ra rep-remove rr rep-update ru rep-list rl reg-update - reg-build rgu info rep-build rb pack p help h dump-file' \ - -- "$cur")) + reg-build rgu info rep-build rb pack p help h dump-file' return ;; esac fi - COMPREPLY=($(compgen -W 'gsetup build dbgen project-export - generate-makefiles gettext-update setup -q' -- "$cur")) + _comp_compgen -- -W 'gsetup build dbgen project-export generate-makefiles + gettext-update setup -q' } && - complete -F _mdtool mdtool + complete -F _comp_cmd_mdtool mdtool # ex: filetype=sh diff --git a/completions/medusa b/completions/medusa index 4512987..347879a 100644 --- a/completions/medusa +++ b/completions/medusa @@ -1,30 +1,30 @@ # bash completion for medusa -*- shell-script -*- -_medusa() +_comp_cmd_medusa() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*h) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -*[HUPCO]) - _filedir + _comp_compgen_filedir return ;; -*M) - COMPREPLY=($(compgen -W "$($1 -d | awk '/^ +\+/ {print $2}' | - command sed -e 's/\.mod$//')")) + _comp_compgen_split -- "$("$1" -d | _comp_awk '/^ +\+/ {print $2}' | + command sed -e 's/\.mod$//')" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help fi } && - complete -F _medusa medusa + complete -F _comp_cmd_medusa medusa # ex: filetype=sh diff --git a/completions/mii-diag b/completions/mii-diag index c433a7a..bf4938b 100644 --- a/completions/mii-diag +++ b/completions/mii-diag @@ -1,26 +1,26 @@ # mii-diag(8) completion -*- shell-script -*- -_mii_diag() +_comp_cmd_mii_diag() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -F | -A | --advertise | --fixed-speed) - COMPREPLY=($(compgen -W '100baseT4 100baseTx 100baseTx-FD - 100baseTx-HD 10baseT 10baseT-FD 10baseT-HD' -- "$cur")) + _comp_compgen -- -W '100baseT4 100baseTx 100baseTx-FD 100baseTx-HD + 10baseT 10baseT-FD 10baseT-HD' return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help else - _available_interfaces -a + _comp_compgen_available_interfaces -a fi } && - complete -F _mii_diag -o default mii-diag + complete -F _comp_cmd_mii_diag -o default mii-diag # ex: filetype=sh diff --git a/completions/mii-tool b/completions/mii-tool index 1b80202..b3e15ad 100644 --- a/completions/mii-tool +++ b/completions/mii-tool @@ -1,32 +1,34 @@ # mii-tool(8) completion -*- shell-script -*- -_mii_tool() +_comp_cmd_mii_tool() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[FA]*)' + # shellcheck disable=SC2254 case $prev in - --force | -!(-*)F) - COMPREPLY=($(compgen -W '100baseTx-FD 100baseTx-HD 10baseT-FD - 10baseT-HD' -- "$cur")) + --force | -${noargopts}F) + _comp_compgen -- -W '100baseTx-FD 100baseTx-HD 10baseT-FD + 10baseT-HD' return ;; - --advertise | -!(-*)A) - COMPREPLY=($(compgen -W '100baseT4 100baseTx-FD 100baseTx-HD - 10baseT-FD 10baseT-HD' -- "$cur")) + --advertise | -${noargopts}A) + _comp_compgen -- -W '100baseT4 100baseTx-FD 100baseTx-HD 10baseT-FD + 10baseT-HD' return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - _available_interfaces -a + _comp_compgen_available_interfaces -a fi } && - complete -F _mii_tool -o default mii-tool + complete -F _comp_cmd_mii_tool -o default mii-tool # ex: filetype=sh diff --git a/completions/minicom b/completions/minicom index 57510e9..752c22e 100644 --- a/completions/minicom +++ b/completions/minicom @@ -1,40 +1,40 @@ # bash completion for minicom -*- shell-script -*- -_minicom() +_comp_cmd_minicom() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[acSCp]*)' + # shellcheck disable=SC2254 case $prev in - --attrib | --color | -!(-*)[ac]) - COMPREPLY=($(compgen -W 'on off' -- "$cur")) + --attrib | --color | -${noargopts}[ac]) + _comp_compgen -- -W 'on off' return ;; - --script | --capturefile | -!(-*)[SC]) - _filedir + --script | --capturefile | -${noargopts}[SC]) + _comp_compgen_filedir return ;; - --ptty | -!(-*)p) - COMPREPLY=($(printf '%s\n' /dev/tty*)) - COMPREPLY=($(compgen -W '${COMPREPLY[@]} ${COMPREPLY[@]#/dev/}' \ - -- "$cur")) + --ptty | -${noargopts}p) + _comp_expand_glob COMPREPLY '/dev/tty*' && + _comp_compgen -- -W '"${COMPREPLY[@]}" "${COMPREPLY[@]#/dev/}"' return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - COMPREPLY=( - $(printf '%s\n' /etc/minirc.* /etc/minicom/minirc.* ~/.minirc.* | - command sed -e '/\*$/d' -e 's/^.*minirc\.//' | - command grep "^${cur}")) + local -a files + _comp_expand_glob files '{/etc/,/etc/minicom/,~/.}minirc.?*' && + _comp_compgen -- -W '"${files[@]##*minirc.}"' } && - complete -F _minicom -o default minicom + complete -F _comp_cmd_minicom -o default minicom # ex: filetype=sh diff --git a/completions/mkinitrd b/completions/mkinitrd index bcb7e07..4e11b0b 100644 --- a/completions/mkinitrd +++ b/completions/mkinitrd @@ -1,50 +1,49 @@ # bash completion for mkinitrd -*- shell-script -*- -_mkinitrd() +_comp_cmd_mkinitrd() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in --preload | --with | --builtin) - _modules + _comp_compgen_kernel_modules return ;; --fstab | --dsdt) - _filedir + _comp_compgen_filedir return ;; --net-dev) - _available_interfaces + _comp_compgen_available_interfaces return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--version --help -v -f --preload \ - --force-scsi-probe --omit-scsi-modules \ - --omit-ide-modules --image-version --force-raid-probe \ - --omit-raid-modules --with= --force-lvm-probe \ - --omit-lvm-modules --builtin --omit-dmraid --net-dev \ - --fstab --nocompress --dsdt --bootchart' -- "$cur")) + _comp_compgen -- -W '--version --help -v -f --preload + --force-scsi-probe --omit-scsi-modules --omit-ide-modules + --image-version --force-raid-probe --omit-raid-modules --with= + --force-lvm-probe --omit-lvm-modules --builtin --omit-dmraid + --net-dev --fstab --nocompress --dsdt --bootchart' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - local args - _count_args + local REPLY + _comp_count_args - case $args in + case $REPLY in 1) - _filedir + _comp_compgen_filedir ;; 2) - _kernel_versions + _comp_compgen_kernel_versions ;; esac fi } && - complete -F _mkinitrd mkinitrd + complete -F _comp_cmd_mkinitrd mkinitrd # ex: filetype=sh diff --git a/completions/mktemp b/completions/mktemp index e063810..a13542a 100644 --- a/completions/mktemp +++ b/completions/mktemp @@ -1,29 +1,30 @@ # mktemp(1) completion -*- shell-script -*- -_mktemp() +_comp_cmd_mktemp() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[p]*)' + # shellcheck disable=SC2254 case "$prev" in --help | --version | --suffix) return ;; - --tmpdir | -!(-*)p) - _filedir -d + --tmpdir | -${noargopts}p) + _comp_compgen_filedir -d return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - local opts=$(_parse_help "$1") - [[ $opts ]] || opts="-d -u -q -p -t" # non-GNU fallback - COMPREPLY=($(compgen -W "$opts" -- "$cur")) + _comp_compgen_help || + _comp_compgen -- -W '-d -u -q -p -t' # non-GNU fallback [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _mktemp mktemp + complete -F _comp_cmd_mktemp mktemp # ex: filetype=sh diff --git a/completions/mmsitepass b/completions/mmsitepass index 49daae6..dcf38c7 100644 --- a/completions/mmsitepass +++ b/completions/mmsitepass @@ -1,15 +1,15 @@ # mailman mmsitepass completion -*- shell-script -*- -_mmsitepass() +_comp_cmd_mmsitepass() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--listcreator --help' -- "$cur")) + _comp_compgen -- -W '--listcreator --help' fi } && - complete -F _mmsitepass mmsitepass + complete -F _comp_cmd_mmsitepass mmsitepass # ex: filetype=sh diff --git a/completions/modinfo b/completions/modinfo index 009bcf3..5c8d416 100644 --- a/completions/modinfo +++ b/completions/modinfo @@ -1,35 +1,41 @@ # Linux modinfo(8) completion -*- shell-script -*- -_modinfo() +_comp_cmd_modinfo() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[Fkb]*)' + # shellcheck disable=SC2254 case "$prev" in - --field | -!(-*)F) - COMPREPLY=($(compgen -W 'alias author depends description - filename firmware license parm srcversion staging vermagic - version' -- "${cur,,}")) + --field | -${noargopts}F) + _comp_compgen -c "${cur,,}" -- -W 'alias author depends description + filename firmware intree license name parm release_date + retpoline sig_hashalgo sig_key signat signer softdep srcversion + staging vermagic version' return ;; - --set-version | -!(-*)k) - _kernel_versions + --set-version | -${noargopts}k) + _comp_compgen_kernel_versions + return + ;; + --basedir | -${noargopts}b) + _comp_compgen_filedir -d return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - local opts=$(_parse_help "$1") - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi local i version=$(uname -r) for ((i = ${#words[@]} - 1; i > 0; i--)); do - if [[ ${words[i]} == -@(!(-*)k*|-set-version) ]]; then + if [[ ${words[i]} == -@(${noargopts}k*|-set-version) ]]; then version=${words[i + 1]} break fi @@ -37,11 +43,11 @@ _modinfo() # do filename completion if we're giving a path to a module if [[ $cur == @(*/|[.~])* ]]; then - _filedir '@(?(k)o?(.[gx]z))' + _comp_compgen_filedir '@(?(k)o?(.[gx]z|.zst))' else - _modules $version + _comp_compgen_kernel_modules "$version" fi } && - complete -F _modinfo modinfo + complete -F _comp_cmd_modinfo modinfo # ex: filetype=sh diff --git a/completions/modprobe b/completions/modprobe index 36cb588..242a282 100644 --- a/completions/modprobe +++ b/completions/modprobe @@ -1,40 +1,42 @@ # Linux modprobe(8) completion -*- shell-script -*- -_modprobe() +_comp_cmd_modprobe() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[CdtS]*)' + # shellcheck disable=SC2254 case "$prev" in - --help | --version | -!(-*)[hV]) + --help | --version | -${noargopts}[hV]) return ;; - --config | -!(-*)C) - _filedir + --config | -${noargopts}C) + _comp_compgen_filedir return ;; - --dirname | --type | -!(-*)[dt]) - _filedir -d + --dirname | --type | -${noargopts}[dt]) + _comp_compgen_filedir -d return ;; - --set-version | -!(-*)S) - _kernel_versions + --set-version | -${noargopts}S) + _comp_compgen_kernel_versions return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help if [[ ! ${COMPREPLY-} ]]; then - COMPREPLY=($(compgen -W '-a --all -b --use-blacklist -C --config + _comp_compgen -- -W '-a --all -b --use-blacklist -C --config -c --showconfig --dump-modversions -d --dirname --first-time --force-vermagic --force-modversion -f --force -i --ignore-install --ignore-remove -l --list -n --dry-run -q --quiet -R --resolve-alias -r --remove -S --set-version --show-depends -s --syslog -t --type -V --version -v - --verbose' -- "$cur")) + --verbose' fi [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return @@ -42,46 +44,47 @@ _modprobe() local i mode=insert module="" version=$(uname -r) for ((i = 1; i < cword; i++)); do + # shellcheck disable=SC2254 case "${words[i]}" in - --remove | -!(-*)r*) + --remove | -${noargopts}r*) mode=remove ;; - --list | -!(-*)l*) + --list | -${noargopts}l*) mode=list ;; --dump-modversions) mode="file" ;; - --set-version | -!(-*)S) + --set-version | -${noargopts}S) version=${words[i + 1]} # -S is not $prev and not $cur ;; - --config | --dirname | --type | -!(-*)[Cdt]) + --config | --dirname | --type | -${noargopts}[Cdt]) ((i++)) # skip option and its argument ;; -*) # skip all other options ;; *) - [[ -z $module ]] && module=${words[i]} + [[ ! $module ]] && module=${words[i]} ;; esac done case $mode in remove) - _installed_modules "$cur" + _comp_compgen_inserted_kernel_modules ;; list) # no completion available ;; file) - _filedir + _comp_compgen_filedir ;; insert) # do filename completion if we're giving a path to a module if [[ $cur == @(*/|[.~])* ]]; then - _filedir '@(?(k)o?(.[gx]z))' - elif [[ -n $module ]]; then + _comp_compgen_filedir '@(?(k)o?(.[gx]z|.zst))' + elif [[ $module ]]; then # do module parameter completion if [[ $cur == *=* ]]; then prev=${cur%%=*} @@ -90,24 +93,24 @@ _modprobe() command grep -q "^$prev:.*(bool)"; then local choices="on off" [[ $cur ]] && choices="1 0 y Y n N on off" - COMPREPLY=($(compgen -W "$choices" -- "$cur")) + _comp_compgen -- -W "$choices" fi else - COMPREPLY=($(compgen -S = -W "$(PATH="$PATH:/sbin" \ + _comp_compgen_split -S = -- "$(PATH="$PATH:/sbin" \ modinfo -p "$module" 2>/dev/null | - awk -F: '!/^[ \t]/ { print $1 }')" -- "$cur")) + _comp_awk -F : '!/^[ \t]/ { print $1 }')" [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi else - _modules $version + _comp_compgen_kernel_modules "$version" if [[ ${COMPREPLY-} ]]; then # filter out already installed modules local -a mods=("${COMPREPLY[@]}") - _installed_modules "$cur" + _comp_compgen_inserted_kernel_modules for i in "${!mods[@]}"; do for module in "${COMPREPLY[@]}"; do if [[ ${mods[i]} == "$module" ]]; then - unset 'mods[i]' + unset -v 'mods[i]' break fi done @@ -118,6 +121,6 @@ _modprobe() ;; esac } && - complete -F _modprobe modprobe + complete -F _comp_cmd_modprobe modprobe # ex: filetype=sh diff --git a/completions/monodevelop b/completions/monodevelop index 1c5b5ba..6e60bfe 100644 --- a/completions/monodevelop +++ b/completions/monodevelop @@ -1,19 +1,19 @@ # monodevelop completion -*- shell-script -*- -_monodevelop() +_comp_cmd_monodevelop() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur")) + _comp_compgen_help -- -h [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - _filedir + _comp_compgen_filedir fi } && - complete -F _monodevelop monodevelop + complete -F _comp_cmd_monodevelop monodevelop # ex: filetype=sh diff --git a/completions/mplayer b/completions/mplayer index d71ebb8..7ab096a 100644 --- a/completions/mplayer +++ b/completions/mplayer @@ -1,120 +1,120 @@ # mplayer(1) completion -*- shell-script -*- -_mplayer_options_list() +_comp_cmd_mplayer__options() { cur=${cur%\\} - COMPREPLY=($(compgen -W "$($1 -noconfig all $2 help 2>/dev/null | - command sed -e '/^Available/,/^$/!d' -e '/^Available/d' | awk '{print $1}' | - command sed -e 's/:$//' -e 's/^'${2#-}'$//' -e 's/<.*//')" -- "$cur")) + _comp_compgen_split -- "$("$1" -noconfig all "$2" help 2>/dev/null | + command sed -e '/^Available/,/^$/!d' -e '/^Available/d' | _comp_awk '{print $1}' | + command sed -e 's/:$//' -e 's/^'"${2#-}"'$//' -e 's/<.*//')" } -_mplayer() +_comp_cmd_mplayer() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return local cmd=${words[0]} i j k=0 case $prev in -[av][cfo] | -[av]fm | -vop | -fstype | -demuxer | -o[av]c | -of | -profile | \ -audio-demuxer | -sub-demuxer) - _mplayer_options_list $cmd $prev + _comp_cmd_mplayer__options "$cmd" "$prev" return ;; -show-profile) - _mplayer_options_list $cmd -profile + _comp_cmd_mplayer__options "$cmd" -profile return ;; -audiofile | -audio-file) - _filedir '@(mp3|mpg|og[ag]|w?(a)v|mid|flac|mka|ac3|ape)' + _comp_compgen_filedir '@(mp3|mpg|og[ag]|w?(a)v|mid|flac|mka|ac3|ape)' return ;; -font | -subfont) if [[ $prev == -font ]]; then - _filedir '@(desc|ttf)' + _comp_compgen_filedir '@(desc|ttf)' else - _filedir ttf + _comp_compgen_filedir ttf fi - local IFS=$'\n' - COMPREPLY+=($(compgen -W '$(fc-list 2>/dev/null)' -- "$cur")) + _comp_compgen -a split -l -- "$(fc-list 2>/dev/null)" return ;; -sub | -sub-file) - _filedir '@(srt|sub|txt|utf|rar|mpsub|smi|js|ssa|ass)' + _comp_compgen_filedir '@(srt|sub|txt|utf|rar|mpsub|smi|js|ssa|ass)' return ;; -vobsub) - _filedir '@(idx|ifo|sub)' - local IFS=$'\n' - COMPREPLY=($(for i in "${COMPREPLY[@]}"; do - if [[ -f $i && -r $i ]]; then - printf '%s\n' ${i%.*} - else - printf '%s\n' $i - fi - done)) + if _comp_compgen_filedir '@(idx|ifo|sub)'; then + for i in "${!COMPREPLY[@]}"; do + if [[ -f ${COMPREPLY[i]} && -r ${COMPREPLY[i]} ]]; then + COMPREPLY[i]=${COMPREPLY[i]%.*} + fi + done + fi return ;; -subcp | -msgcharset) local cp - cp=($(iconv --list 2>/dev/null | command sed -e "s@//@@;" 2>/dev/null)) - if [[ $cur == "${cur,,}" ]]; then - COMPREPLY=($(compgen -W '${cp[@],,}' -- "$cur")) - else - COMPREPLY=($(compgen -W '${cp[@]^^}' -- "$cur")) + if _comp_split cp "$(iconv --list 2>/dev/null | command sed -e "s@//@@;" 2>/dev/null)"; then + if [[ $cur == "${cur,,}" ]]; then + _comp_compgen -- -W '"${cp[@],,}"' + else + _comp_compgen -- -W '"${cp[@]^^}"' + fi fi return ;; -ifo) - _filedir ifo + _comp_compgen_filedir ifo return ;; -cuefile) - _filedir '@(bin|cue)' + _comp_compgen_filedir '@(bin|cue)' return ;; -skin) # if you don't have installed mplayer in /usr you # may want to set the MPLAYER_SKINS_DIR global variable local -a dirs - if [[ -n $MPLAYER_SKINS_DIR ]]; then - dirs=($MPLAYER_SKINS_DIR) + if [[ $MPLAYER_SKINS_DIR ]]; then + _comp_split dirs "$MPLAYER_SKINS_DIR" else dirs=(/usr/share/mplayer/skins /usr/local/share/mplayer/skins) fi - local IFS=$'\n' - for i in ~/.mplayer/skins "${dirs[@]}"; do - if [[ -d $i && -r $i ]]; then - for j in $(compgen -d -- $i/$cur); do - COMPREPLY[k++]=${j#$i/} - done - fi - done + if ((${#dirs[@]})); then + local -a subdirs + for i in ~/.mplayer/skins "${dirs[@]}"; do + if [[ -d $i && -r $i ]]; then + _comp_compgen -v subdirs -c "$i/$cur" -- -d + for j in "${subdirs[@]}"; do + COMPREPLY[k++]=${j#"$i/"} + done + fi + done + fi return ;; -cdrom-device) - _cd_devices - _dvd_devices + _comp_compgen_cd_devices + _comp_compgen -a dvd_devices return ;; -dvd-device) - _dvd_devices - _filedir iso + _comp_compgen_dvd_devices + _comp_compgen -a filedir iso return ;; -bluray-device) - _filedir -d + _comp_compgen_filedir -d return ;; -mixer | -dvdauth | -fb | -zrdev) - cur=${cur:=/dev/} - _filedir + _comp_compgen -c "${cur:-/dev/}" filedir return ;; -edl | -edlout | -lircconf | -menu-cfg | -playlist | -csslib | -dumpfile | \ -subfile | -aofile | -fbmodeconfig | -include | -o | -dvdkey | -passlogfile) - _filedir + _comp_compgen_filedir return ;; -autoq | -autosync | -loop | -menu-root | -speed | -sstep | -aid | -alang | \ @@ -136,124 +136,119 @@ _mplayer() return ;; -channels) - COMPREPLY=($(compgen -W '2 4 6 8' -- "$cur")) + _comp_compgen -- -W '2 4 6 8' return ;; -aspect | -monitoraspect) - COMPREPLY=($(compgen -W '1:1 3:2 4:3 5:4 14:9 14:10 16:9 16:10 - 2.35:1' -- "$cur")) - __ltrim_colon_completions "$cur" + _comp_compgen -- -W '1:1 3:2 4:3 5:4 14:9 14:10 16:9 16:10 2.35:1' + _comp_ltrim_colon_completions "$cur" return ;; -lavdopts) - COMPREPLY=($(compgen -W 'bitexact bug= debug= ec= er= fast gray - idct= lowres= sb= st= skiploopfilter= skipidct= skipframe= - threads= vismv= vstats' -- "$cur")) + _comp_compgen -- -W 'bitexact bug= debug= ec= er= fast gray idct= + lowres= sb= st= skiploopfilter= skipidct= skipframe= threads= + vismv= vstats' return ;; -lavcopts) - COMPREPLY=($(compgen -W 'vcodec= vqmin= vqscale= vqmax= mbqmin= - mbqmax= vqdiff= vmax_b_frames= vme= vhq v4mv keyint= - vb_strategy= vpass= aspect= vbitrate= vratetol= vrc_maxrate= - vrc_minrate= vrc_buf_size= vb_qfactor= vi_qfactor= vb_qoffset= - vi_qoffset= vqblur= vqcomp= vrc_eq= vrc_override= - vrc_init_cplx= vqsquish= vlelim= vcelim= vstrict= vdpart - vpsize= gray vfdct= idct= lumi_mask= dark_mask= tcplx_mask= - scplx_mask= naq ildct format= pred qpel precmp= cmp= subcmp= - predia= dia= trell last_pred= preme= subq= psnr mpeg_quant aic - umv' -- "$cur")) + _comp_compgen -- -W 'vcodec= vqmin= vqscale= vqmax= mbqmin= mbqmax= + vqdiff= vmax_b_frames= vme= vhq v4mv keyint= vb_strategy= + vpass= aspect= vbitrate= vratetol= vrc_maxrate= vrc_minrate= + vrc_buf_size= vb_qfactor= vi_qfactor= vb_qoffset= vi_qoffset= + vqblur= vqcomp= vrc_eq= vrc_override= vrc_init_cplx= vqsquish= + vlelim= vcelim= vstrict= vdpart vpsize= gray vfdct= idct= + lumi_mask= dark_mask= tcplx_mask= scplx_mask= naq ildct format= + pred qpel precmp= cmp= subcmp= predia= dia= trell last_pred= + preme= subq= psnr mpeg_quant aic umv' return ;; -ssf) - COMPREPLY=($(compgen -W 'lgb= cgb= ls= cs= chs= cvs=' -- "$cur")) + _comp_compgen -- -W 'lgb= cgb= ls= cs= chs= cvs=' return ;; -jpeg) - COMPREPLY=($(compgen -W 'noprogressive progressive nobaseline - baseline optimize= smooth= quality= outdir=' -- "$cur")) + _comp_compgen -- -W 'noprogressive progressive nobaseline baseline + optimize= smooth= quality= outdir=' return ;; -xvidopts) - COMPREPLY=($(compgen -W 'dr2 nodr2' -- "$cur")) + _comp_compgen -- -W 'dr2 nodr2' return ;; -xvidencopts) - COMPREPLY=($(compgen -W 'pass= bitrate= fixed_quant= me_quality= - 4mv rc_reaction_delay_factor= rc_averaging_period= rc_buffer= + _comp_compgen -- -W 'pass= bitrate= fixed_quant= me_quality= 4mv + rc_reaction_delay_factor= rc_averaging_period= rc_buffer= quant_range= min_key_interval= max_key_interval= mpeg_quant mod_quant lumi_mask hintedme hintfile debug keyframe_boost= - kfthreshold= kfreduction=' -- "$cur")) + kfthreshold= kfreduction=' return ;; -divx4opts) - COMPREPLY=($(compgen -W 'br= key= deinterlace q= min_quant= - max_quant= rc_period= rc_reaction_period= crispness= - rc_reaction_ratio= pass= vbrpass= help' -- "$cur")) + _comp_compgen -- -W 'br= key= deinterlace q= min_quant= max_quant= + rc_period= rc_reaction_period= crispness= rc_reaction_ratio= + pass= vbrpass= help' return ;; -info) - COMPREPLY=($(compgen -W 'name= artist= genre= subject= - copyright= srcform= comment= help' -- "$cur")) + _comp_compgen -- -W 'name= artist= genre= subject= copyright= + srcform= comment= help' return ;; -lameopts) - COMPREPLY=($(compgen -W 'vbr= abr cbr br= q= aq= ratio= vol= - mode= padding= fast preset= help' -- "$cur")) + _comp_compgen -- -W 'vbr= abr cbr br= q= aq= ratio= vol= mode= + padding= fast preset= help' return ;; -rawaudio) - COMPREPLY=($(compgen -W 'on channels= rate= samplesize= format=' \ - -- "$cur")) + _comp_compgen -- -W 'on channels= rate= samplesize= format=' return ;; -rawvideo) - COMPREPLY=($(compgen -W 'on fps= sqcif qcif cif 4cif pal ntsc w= - h= y420 yv12 yuy2 y8 format= size=' -- "$cur")) + _comp_compgen -- -W 'on fps= sqcif qcif cif 4cif pal ntsc w= h= + y420 yv12 yuy2 y8 format= size=' return ;; -aop) - COMPREPLY=($(compgen -W 'list= delay= format= fout= volume= mul= - softclip' -- "$cur")) + _comp_compgen -- -W 'list= delay= format= fout= volume= mul= + softclip' return ;; -dxr2) - COMPREPLY=($(compgen -W 'ar-mode= iec958-encoded iec958-decoded - mute ucode= 75ire bw color interlaced macrovision= norm= + _comp_compgen -- -W 'ar-mode= iec958-encoded iec958-decoded mute + ucode= 75ire bw color interlaced macrovision= norm= square-pixel ccir601-pixel cr-left= cr-right= cr-top= cr-bot= ck-rmin= ck-gmin= ck-bmin= ck-rmax= ck-gmax= ck-bmax= ck-r= ck-g= ck-b= ignore-cache= ol-osd= olh-cor= olw-cor= olx-cor= - oly-cor= overlay overlay-ratio= update-cache' -- "$cur")) + oly-cor= overlay overlay-ratio= update-cache' return ;; -tv) - COMPREPLY=($(compgen -W 'on noaudio driver= device= input= freq= + _comp_compgen -- -W 'on noaudio driver= device= input= freq= outfmt= width= height= buffersize= norm= channel= chanlist= audiorate= forceaudio alsa amode= forcechan= adevice= audioid= - volume= bass= treble= balance= fps= channels= immediatemode=' \ - -- "$cur")) + volume= bass= treble= balance= fps= channels= immediatemode=' return ;; -mf) - COMPREPLY=($(compgen -W 'on w= h= fps= type=' -- "$cur")) + _comp_compgen -- -W 'on w= h= fps= type=' return ;; -cdda) - COMPREPLY=($(compgen -W 'speed= paranoia= generic-dev= - sector-size= overlap= toc-bias toc-offset= skip noskip' \ - -- "$cur")) + _comp_compgen -- -W 'speed= paranoia= generic-dev= sector-size= + overlap= toc-bias toc-offset= skip noskip' return ;; -input) - COMPREPLY=($(compgen -W 'conf= ar-delay ar-rate keylist cmdlist - js-dev file' -- "$cur")) + _comp_compgen -- -W 'conf= ar-delay ar-rate keylist cmdlist js-dev + file' return ;; -af-adv) - COMPREPLY=($(compgen -W 'force= list=' -- "$cur")) + _comp_compgen -- -W 'force= list=' return ;; -noconfig) - COMPREPLY=($(compgen -W 'all gui system user' -- "$cur")) + _comp_compgen -- -W 'all gui system user' return ;; -*) @@ -271,17 +266,17 @@ _mplayer() case $cur in -*) - COMPREPLY=($(compgen -W '$($cmd -noconfig all -list-options 2>/dev/null | \ + _comp_compgen_split -- "$("$cmd" -noconfig all -list-options 2>/dev/null | command sed -ne "1,/^[[:space:]]*Name/d" \ -e "s/^[[:space:]]*/-/" -e "s/[[:space:]:].*//" \ - -e "/^-\(Total\|.*\*\)\{0,1\}$/!p")' -- "$cur")) + -e "/^-\(Total\|.*\*\)\{0,1\}$/!p")" ;; *) - _filedir '@(m?(j)p?(e)g|M?(J)P?(E)G|wm[av]|WM[AV]|avi|AVI|asf|ASF|vob|VOB|bin|BIN|dat|DAT|vcd|VCD|ps|PS|pes|PES|fl[iv]|FL[IV]|fxm|FXM|viv|VIV|rm?(j)|RM?(J)|ra?(m)|RA?(M)|yuv|YUV|mov|MOV|qt|QT|mp[234]|MP[234]|m?(p)4[av]|M?(P)4[AV]|og[gmavx]|OG[GMAVX]|w?(a)v|W?(A)V|dump|DUMP|mk[av]|MK[AV]|aac|AAC|m2v|M2V|dv|DV|rmvb|RMVB|mid|MID|t[ps]|T[PS]|3g[p2]|3gpp?(2)|mpc|MPC|flac|FLAC|vro|VRO|divx|DIVX|aif?(f)|AIF?(F)|m2t?(s)|M2T?(S)|mts|MTS|vdr|VDR|xvid|XVID|ape|APE|gif|GIF|nut|NUT|bik|BIK|web[am]|WEB[AM]|amr|AMR|awb|AWB|iso|ISO|opus|OPUS|m[eo]d|M[EO]D|xm|XM|it|IT|s[t3]m|S[T3]M|mtm|MTM|w64|W64)?(.@(crdownload|part))' + _comp_compgen_filedir '@(m?(j)p?(e)g|M?(J)P?(E)G|wm[av]|WM[AV]|avi|AVI|asf|ASF|vob|VOB|bin|BIN|dat|DAT|vcd|VCD|ps|PS|pes|PES|fl[iv]|FL[IV]|fxm|FXM|viv|VIV|rm?(j)|RM?(J)|ra?(m)|RA?(M)|yuv|YUV|mov|MOV|qt|QT|mp[234]|MP[234]|m?(p)4[av]|M?(P)4[AV]|og[gmavx]|OG[GMAVX]|w?(a)v|W?(A)V|dump|DUMP|mk[av]|MK[AV]|aac|AAC|m2v|M2V|dv|DV|rmvb|RMVB|mid|MID|t[ps]|T[PS]|3g[p2]|3gpp?(2)|mpc|MPC|flac|FLAC|vro|VRO|divx|DIVX|aif?(f)|AIF?(F)|m2t?(s)|M2T?(S)|mts|MTS|vdr|VDR|xvid|XVID|ape|APE|gif|GIF|nut|NUT|bik|BIK|web[am]|WEB[AM]|amr|AMR|awb|AWB|iso|ISO|opus|OPUS|m[eo]d|M[EO]D|xm|XM|it|IT|s[t3]m|S[T3]M|mtm|MTM|w64|W64)?(.@(crdownload|part))' ;; esac } && - complete -F _mplayer mplayer mplayer2 mencoder gmplayer kplayer + complete -F _comp_cmd_mplayer mplayer mplayer2 mencoder gmplayer kplayer # ex: filetype=sh diff --git a/completions/mr b/completions/mr index 930e3c9..660dfd8 100644 --- a/completions/mr +++ b/completions/mr @@ -1,59 +1,66 @@ # mr completion -*- shell-script -*- -_mr() +_comp_cmd_mr() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local help commands options help="$(PERLDOC_PAGER=cat PERLDOC=-otext "${1}" help 2>/dev/null)" commands="$( + # shellcheck disable=SC2030 printf %s "$help" | while read -r _ options cmd _; do [[ $options != "[options]" ]] || printf "%s\n" "$cmd" done )" # Split [online|offline] and remove `action` placeholder. - commands="${commands//@(action|[\[\|\]])/$'\n'}" + commands="${commands//@(action|[\[\|\]])/ }" # Add standard aliases. commands="${commands} ci co ls" + _comp_split commands "$commands" + local IFS='|' + local glob_commands="@(${commands[*]})" + _comp_unlocal IFS # Determine if user has entered an `mr` command. Used to block top-level # (option and command) completions. - local cmd i - for ((i = 1; i < ${#words[@]} - 1; i++)); do - if [[ $commands == *"${words[i]}"* ]]; then + local cmd has_cmd="" i + for ((i = 1; i < cword; i++)); do + # shellcheck disable=SC2053 + if [[ ${words[i]} == $glob_commands ]]; then cmd="${words[i]}" + has_cmd=set break fi done # Complete options for specific commands. - if [[ -v cmd ]]; then + if [[ $has_cmd ]]; then case $cmd in bootstrap) - _filedir + _comp_compgen_filedir # Also complete stdin (-) as a potential bootstrap source. - if [[ -z ${cur} || $cur == - ]] && [[ $prev != - ]]; then + if [[ ! ${cur} || $cur == - ]] && [[ $prev != - ]]; then COMPREPLY+=(-) fi return ;; clean) if [[ ${cur} == -* ]]; then - COMPREPLY=($(compgen -W '-f' -- "${cur}")) + _comp_compgen -- -W '-f' fi return ;; commit | ci | record) if [[ ${cur} == -* ]]; then - COMPREPLY=($(compgen -W '-m' -- "${cur}")) + _comp_compgen -- -W '-m' fi return ;; run) - COMPREPLY=($(compgen -c -- "${cur}")) + _comp_compgen_commands return ;; *) @@ -64,28 +71,28 @@ _mr() fi # Complete top-level options and commands. + local noargopts='!(-*|*[cd]*)' + # shellcheck disable=SC2254 case $prev in - --config | -!(-*)c) - _filedir + --config | -${noargopts}c) + _comp_compgen_filedir return ;; - --directory | -!(-*)d) - _filedir -d + --directory | -${noargopts}d) + _comp_compgen_filedir -d return ;; esac if [[ $cur == -* ]]; then - options="$(printf '%s\n' "$help" | _parse_help -)" - # Remove short options (all have compatible long options). - options="${options//-[a-z]$'\n'/}" - # Remove deprecated options. - options="${options//--path/}" - COMPREPLY=($(compgen -W "${options}" -- "${cur}")) + _comp_compgen -Rv options help - <<<"$help" + # -X '-[a-z]': Remove short options (all have compatible long options). + # -X '--path': Remove deprecated options. + _comp_compgen -- -W '"${options[@]}"' -X '@(-[a-z]|--path)' else - COMPREPLY=($(compgen -W "${commands}" -- "${cur}")) + _comp_compgen -- -W '"${commands[@]}"' fi } && - complete -F _mr mr + complete -F _comp_cmd_mr mr # ex: filetype=sh diff --git a/completions/msynctool b/completions/msynctool index 4de37f5..0348170 100644 --- a/completions/msynctool +++ b/completions/msynctool @@ -1,42 +1,38 @@ # bash completion for msynctool -*- shell-script -*- -_msynctool() +_comp_cmd_msynctool() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $words in --configure) - COMPREPLY=($(compgen -W "$($1 --showgroup \ - $prev | awk '/^Member/ {print $2}' | command sed \ - -e 's/:$//')" -- "$cur")) + _comp_compgen_split -- "$("$1" --showgroup "$prev" | + _comp_awk '/^Member/ {print $2}' | command sed -e 's/:$//')" return ;; --addmember) - COMPREPLY=($(compgen -W '$($1 --listplugins \ - | command sed -e 1d)' -- "$cur")) + _comp_compgen_split -- "$("$1" --listplugins | command sed -e 1d)" return ;; esac case $prev in --configure | --addgroup | --delgroup | --showgroup | --sync | --addmember) - COMPREPLY=($(compgen -W '$($1 --listgroups \ - | command sed -e 1d)' -- "$cur")) + _comp_compgen_split -- "$("$1" --listgroups | command sed -e 1d)" return ;; --showformats | --filter-objtype | --slow-sync) - COMPREPLY=($(compgen -W '$($1 --listobjects \ - | command sed -e 1d)' -- "$cur")) + _comp_compgen_split -- "$("$1" --listobjects | command sed -e 1d)" return ;; esac - COMPREPLY=($(compgen -W '--listgroups --listplugins --listobjects - --showformats --showgroup --sync --filter-objtype --slow-sync --wait - --multi --addgroup --delgroup --addmember --configure --manual - --configdir --conflict' -- "$cur")) + _comp_compgen -- -W '--listgroups --listplugins --listobjects --showformats + --showgroup --sync --filter-objtype --slow-sync --wait --multi + --addgroup --delgroup --addmember --configure --manual --configdir + --conflict' } && - complete -F _msynctool msynctool + complete -F _comp_cmd_msynctool msynctool # ex: filetype=sh diff --git a/completions/mtx b/completions/mtx index b5c270b..d04a0c1 100644 --- a/completions/mtx +++ b/completions/mtx @@ -1,10 +1,10 @@ # mtx completion -*- shell-script -*- # by Jon Middleton <jjm@ixtab.org.uk> -_mtx() +_comp_cmd_mtx() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local options tapes drives @@ -12,21 +12,21 @@ _mtx() inventory status load unload eepos first last next" tapes=$(mtx status 2>/dev/null | - awk '/Storage Element [0-9]+:Full/ { printf "%s ", $3 }') + _comp_awk '/Storage Element [0-9]+:Full/ { printf "%s ", $3 }') tapes=${tapes//:Full/} drives=$(mtx status 2>/dev/null | - awk '/Data Transfer Element [0-9]+:(Full|Empty)/ { printf "%s ", $4 }') + _comp_awk '/Data Transfer Element [0-9]+:(Full|Empty)/ { printf "%s ", $4 }') drives=${drives//:Full/} drives=${drives//:Empty/} if ((cword > 1)); then case $prev in load) - COMPREPLY=($(compgen -W "$tapes" -- "$cur")) + _comp_compgen -- -W "$tapes" ;; unload | first | last | next) - COMPREPLY=($(compgen -W "$drives" -- "$cur")) + _comp_compgen -- -W "$drives" ;; -f) true @@ -36,9 +36,9 @@ _mtx() ;; esac else - COMPREPLY=($(compgen -W "$options" -- "$cur")) + _comp_compgen -- -W "$options" fi } && - complete -F _mtx mtx + complete -F _comp_cmd_mtx mtx # ex: filetype=sh diff --git a/completions/munin-node-configure b/completions/munin-node-configure index 39d8d64..edfb4b9 100644 --- a/completions/munin-node-configure +++ b/completions/munin-node-configure @@ -1,33 +1,33 @@ # munin-node-configure completion -*- shell-script -*- -_munin_node_configure() +_comp_cmd_munin_node_configure() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --config) - _filedir + _comp_compgen_filedir return ;; --servicedir | --libdir) - _filedir -d + _comp_compgen_filedir -d return ;; --snmp) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; --snmpversion) - COMPREPLY=($(compgen -W '1 2c 3' -- "$cur")) + _comp_compgen -- -W '1 2c 3' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help fi } && - complete -F _munin_node_configure munin-node-configure + complete -F _comp_cmd_munin_node_configure munin-node-configure # ex: filetype=sh diff --git a/completions/munin-run b/completions/munin-run index 97e526a..c514a01 100644 --- a/completions/munin-run +++ b/completions/munin-run @@ -1,28 +1,27 @@ # munin-run completion -*- shell-script -*- -_munin_run() +_comp_cmd_munin_run() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --config | --sconffile) - _filedir + _comp_compgen_filedir return ;; --servicedir | --sconfdir) - _filedir -d + _comp_compgen_filedir -d return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help else - COMPREPLY=($(compgen -W \ - '$(command ls /etc/munin/plugins 2>/dev/null)' -- "$cur")) + _comp_compgen_split -- "$(command ls /etc/munin/plugins 2>/dev/null)" fi } && - complete -F _munin_run munin-run + complete -F _comp_cmd_munin_run munin-run # ex: filetype=sh diff --git a/completions/munin-update b/completions/munin-update index 8766eae..8ed8a1f 100644 --- a/completions/munin-update +++ b/completions/munin-update @@ -1,27 +1,27 @@ # munin-update completion -*- shell-script -*- -_munin_update() +_comp_cmd_munin_update() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --config) - _filedir + _comp_compgen_filedir return ;; --host) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--force-root --noforce-root --service --host + _comp_compgen -- -W '--force-root --noforce-root --service --host --config --help --debug --nodebug --fork --nofork --stdout - --nostdout --timeout' -- "$cur")) + --nostdout --timeout' fi } && - complete -F _munin_update munin-update + complete -F _comp_cmd_munin_update munin-update # ex: filetype=sh diff --git a/completions/munindoc b/completions/munindoc index 5c7644a..4a1b4c6 100644 --- a/completions/munindoc +++ b/completions/munindoc @@ -1,13 +1,12 @@ # munindoc completion -*- shell-script -*- -_munindoc() +_comp_cmd_munindoc() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - COMPREPLY=($(compgen -W \ - '$(command ls /usr/share/munin/plugins 2>/dev/null)' -- "$cur")) + _comp_compgen_split -- "$(command ls /usr/share/munin/plugins 2>/dev/null)" } && - complete -F _munindoc munindoc + complete -F _comp_cmd_munindoc munindoc # ex: filetype=sh diff --git a/completions/mussh b/completions/mussh index c2f7a52..e36affe 100644 --- a/completions/mussh +++ b/completions/mussh @@ -1,52 +1,52 @@ # mussh(1) completion -*- shell-script -*- -_mussh() +_comp_cmd_mussh() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --help | -V | -m | -t) return ;; -d) - COMPREPLY=($(compgen -W '{0..2}' -- "$cur")) + _comp_compgen -- -W '{0..2}' return ;; -v) - COMPREPLY=($(compgen -W '{0..3}' -- "$cur")) + _comp_compgen -- -W '{0..3}' return ;; -i | -H | -C) - _filedir + _comp_compgen_filedir return ;; -o | -po) - _xfunc ssh _ssh_options + _comp_compgen -x ssh options return ;; -l | -L) - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u return ;; -s) - _shells + _comp_compgen_shells return ;; -p | -h) - [[ $cur == *@* ]] && _user_at_host || _known_hosts_real -a -- "$cur" + [[ $cur == *@* ]] && _comp_complete_user_at_host "$@" || _comp_compgen_known_hosts -a -- "$cur" return ;; -c) compopt -o filenames - COMPREPLY+=($(compgen -c -- "$cur")) + _comp_compgen_commands return ;; esac [[ $cur != -* ]] || - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help } && - complete -F _mussh mussh + complete -F _comp_cmd_mussh mussh # ex: filetype=sh diff --git a/completions/mutt b/completions/mutt index 1161487..5ebf65a 100644 --- a/completions/mutt +++ b/completions/mutt @@ -4,157 +4,174 @@ # a "query" function to retrieve addresses, so that's what we use here. # @param $1 (cur) Current word to complete -_muttaddr() +_comp_cmd_mutt__addresses() { - _muttaliases "$1" - _muttquery "$1" + _comp_cmd_mutt__aliases "$1" + _comp_cmd_mutt__query "$1" - COMPREPLY+=($(compgen -u -- "$1")) + _comp_compgen -ac "$1" -- -u } # Find muttrc to use -# @output muttrc filename -_muttrc() +# @var[out] REPLY muttrc filename +_comp_cmd_mutt__get_muttrc() { + REPLY= # Search COMP_WORDS for '-F muttrc' or '-Fmuttrc' argument set -- "${words[@]}" while (($# > 0)); do if [[ $1 == -F* ]]; then if ((${#1} > 2)); then - muttrc="$(dequote "${1:2}")" + _comp_dequote "${1:2}" else shift - [[ $1 ]] && muttrc="$(dequote "$1")" + [[ ${1-} ]] && _comp_dequote "$1" fi break fi shift done - if [[ ! -v muttrc ]]; then + if [[ ! $REPLY ]]; then if [[ -f ~/.${muttcmd}rc ]]; then - muttrc=\~/.${muttcmd}rc + REPLY=\~/.${muttcmd}rc elif [[ -f ~/.${muttcmd}/${muttcmd}rc ]]; then - muttrc=\~/.${muttcmd}/${muttcmd}rc + REPLY=\~/.${muttcmd}/${muttcmd}rc fi fi - printf "%s" "${muttrc-}" } # Recursively build list of sourced config files -# @param $1 List of config files found so far -# @param $2 Config file to process -# @output List of config files -_muttconffiles() +# @param $1... Config file to process +# @var[out] REPLY List of config files +# @return 0 if any conffiles are generated, 1 if none is generated. +_comp_cmd_mutt__get_conffiles() { - local file sofar + local -a conffiles=() + local -A visited=() + local file + for file; do + _comp_dequote "$file" + _comp_cmd_mutt__get_conffiles__visit "$REPLY" + done + ((${#conffiles[@]})) || return 1 + REPLY=("${conffiles[@]}") +} +# Recursion function for _comp_cmd_mutt__get_conffiles +# @var[ref] conffiles List of config files found so far +# @var[ref] visited Dictionary of config files already visited +_comp_cmd_mutt__get_conffiles__visit() +{ + [[ -f $1 && ${visited[$1]-} != set ]] || return 0 + visited[$1]=set + conffiles+=("$1") + local -a newconffiles + _comp_split newconffiles "$(command sed -n 's|^source[[:space:]]\{1,\}\([^[:space:]]\{1,\}\).*$|\1|p' "$1")" || + return 0 - sofar=" $1 " - shift - while [[ ${1-} ]]; do - newconffiles=($(command sed -n 's|^source[[:space:]]\{1,\}\([^[:space:]]\{1,\}\).*$|\1|p' "$(eval printf %s $1)")) - for file in ${newconffiles+"${newconffiles[@]}"}; do - __expand_tilde_by_ref file - [[ ! -f $file || $sofar == *\ $file\ * ]] && continue - sofar+=" $file" - sofar=" $(eval _muttconffiles \"$sofar\" $file) " - done - shift + local file REPLY + for file in "${newconffiles[@]}"; do + _comp_expand_tilde "$file" + _comp_cmd_mutt__get_conffiles__visit "$REPLY" done - printf '%s\n' $sofar } # @param $1 (cur) Current word to complete -_muttaliases() +_comp_cmd_mutt__aliases() { - local cur=$1 muttrc muttcmd=${words[0]} + local cur=$1 muttrc muttcmd=${words[0]} REPLY local -a conffiles aliases - muttrc=$(_muttrc) - [[ -z $muttrc ]] && return + _comp_cmd_mutt__get_muttrc + muttrc=$REPLY + [[ ! $muttrc ]] && return - conffiles=($(eval _muttconffiles $muttrc $muttrc)) - # shellcheck disable=SC2046 - aliases=("$(command sed -n 's|^alias[[:space:]]\{1,\}\([^[:space:]]\{1,\}\).*$|\1|p' \ - $(eval echo "${conffiles[@]}"))") - COMPREPLY+=($(compgen -W "${aliases[*]}" -- "$cur")) + local REPLY + _comp_cmd_mutt__get_conffiles "$muttrc" || return 0 + conffiles=("${REPLY[@]}") + _comp_compgen -a split -- "$(command sed -n 's|^alias[[:space:]]\{1,\}\([^[:space:]]\{1,\}\).*$|\1|p' \ + "${conffiles[@]}")" } # @param $1 (cur) Current word to complete -_muttquery() +_comp_cmd_mutt__query() { - local cur=$1 querycmd muttcmd=${words[0]} - local -a queryresults - - querycmd="$($muttcmd -Q query_command 2>/dev/null | command sed -e 's|^query_command=\"\(.*\)\"$|\1|' -e 's|%s|'$cur'|')" - if [[ -z $cur || -z $querycmd ]]; then - queryresults=() - else - __expand_tilde_by_ref querycmd - queryresults=($($querycmd | - command sed -n '2,$s|^\([^[:space:]]\{1,\}\).*|\1|p')) + local cur=$1 + [[ $cur ]] || return 0 + local muttcmd=${words[0]} + + local querycmd="$("$muttcmd" -Q query_command 2>/dev/null | command sed -e 's|^query_command=\"\(.*\)\"$|\1|' -e 's|%s|'"$cur"'|')" + if [[ $querycmd ]]; then + local REPLY + _comp_expand_tilde "$querycmd" + querycmd=$REPLY + # generate queryresults: + # $querycmd is expected to be a command with arguments + _comp_compgen -a split -- "$($querycmd | + command sed -n '2,$s|^\([^[:space:]]\{1,\}\).*|\1|p')" fi - - COMPREPLY+=($(compgen -W "${queryresults[*]}" -- "$cur")) } # @param $1 (cur) Current word to complete -_muttfiledir() +_comp_cmd_mutt__filedir() { - local cur=$1 folder muttrc spoolfile muttcmd=${words[0]} - - muttrc=$(_muttrc) + local cur=$1 folder muttrc spoolfile muttcmd=${words[0]} REPLY + _comp_cmd_mutt__get_muttrc + muttrc=$REPLY if [[ $cur == [=+]* ]]; then - folder="$($muttcmd -F "$muttrc" -Q folder 2>/dev/null | command sed -e 's|^folder=\"\(.*\)\"$|\1|')" - : folder:=~/Mail + folder="$("$muttcmd" -F "$muttrc" -Q folder 2>/dev/null | command sed -e 's|^folder=\"\(.*\)\"$|\1|')" + [[ $folder ]] || folder=~/Mail # Match any file in $folder beginning with $cur # (minus the leading '=' sign). compopt -o filenames - COMPREPLY=($(compgen -f -- "$folder/${cur:1}")) - COMPREPLY=(${COMPREPLY[@]#$folder/}) + _comp_compgen -c "$folder/${cur:1}" -- -f + COMPREPLY=("${COMPREPLY[@]#"$folder"/}") return elif [[ $cur == !* ]]; then - spoolfile="$($muttcmd -F "$muttrc" -Q spoolfile 2>/dev/null | + spoolfile="$("$muttcmd" -F "$muttrc" -Q spoolfile 2>/dev/null | command sed -e 's|^spoolfile=\"\(.*\)\"$|\1|')" - [[ -n $spoolfile ]] && eval cur="${cur/^!/$spoolfile}" + if [[ $spoolfile ]]; then + _comp_dequote "\"$spoolfile\"" && spoolfile=$REPLY + cur=$spoolfile${cur:1} + fi fi - _filedir + _comp_compgen -c "$cur" filedir } -_mutt() +_comp_cmd_mutt() { - local cur prev words cword - _init_completion -n =+! || return + local cur prev words cword comp_args + _comp_initialize -n =+! -- "$@" || return case $cur in -*) - COMPREPLY=($(compgen -W '-A -a -b -c -e -f -F -H -i -m -n -p -Q -R -s - -v -x -y -z -Z -h' -- "$cur")) + _comp_compgen -- -W '-A -a -b -c -e -f -F -H -i -m -n -p -Q -R -s + -v -x -y -z -Z -h' return ;; *) case $prev in -*[afFHi]) - _muttfiledir "$cur" + _comp_cmd_mutt__filedir "$cur" return ;; -*A) - _muttaliases "$cur" + _comp_cmd_mutt__aliases "$cur" return ;; -*[emQshpRvyzZ]) return ;; *) - _muttaddr "$cur" + _comp_cmd_mutt__addresses "$cur" return ;; esac ;; esac } && - complete -F _mutt -o default mutt muttng + complete -F _comp_cmd_mutt -o default mutt muttng neomutt # ex: filetype=sh diff --git a/completions/mypy b/completions/mypy index 534d575..1c01ad4 100644 --- a/completions/mypy +++ b/completions/mypy @@ -1,57 +1,60 @@ # mypy completion -*- shell-script -*- -_mypy() +_comp_cmd_mypy() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return [[ $cword -gt 2 && ${words[cword - 2]} == --shadow-file ]] && prev=--shadow-file # hack; takes two args + local noargopts='!(-*|*[pcm]*)' + # shellcheck disable=SC2254 case $prev in --help | --version | --python-version | --platform | --always-true | \ - --always-false | --find-occurrences | --package | --command | -!(-*)[hVpc]) + --always-false | --@(dis|en)able-error-code | --find-occurrences | \ + --exclude | --package | --command | -${noargopts}[hVpc]) return ;; --config-file) - _filedir + _comp_compgen_filedir return ;; --follow-imports) - COMPREPLY=($(compgen -W 'normal silent skip error' -- "$cur")) + _comp_compgen -- -W 'normal silent skip error' return ;; --python-executable) - COMPREPLY=($(compgen -c -- "${cur:-py}")) + _comp_compgen -c "${cur:-py}" commands return ;; --*-dir | --*-report) - _filedir -d + _comp_compgen_filedir -d return ;; - --custom-typing | --module | -!(-*)m) - _xfunc python _python_modules + --custom-typing-module | --module | -${noargopts}m) + _comp_compgen -x python modules return ;; --shadow-file) - _filedir '@(py|pyi)' + _comp_compgen_filedir '@(py|pyi)' return ;; --junit-xml) - _filedir xml + _comp_compgen_filedir xml return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - _filedir '@(py|pyi)' + _comp_compgen_filedir '@(py|pyi)' } && - complete -F _mypy mypy + complete -F _comp_cmd_mypy mypy # ex: filetype=sh diff --git a/completions/mysql b/completions/mysql index 9363133..4ba049f 100644 --- a/completions/mysql +++ b/completions/mysql @@ -1,83 +1,94 @@ # mysql(1) completion -*- shell-script -*- -_mysql_character_sets() +# @since 2.12 +_comp_xfunc_mysql_compgen_character_sets() { - local IFS=$' \t\n' reset=$(shopt -p failglob) - shopt -u failglob - local -a charsets=(/usr/share/m{ariadb,ysql}/charsets/*.xml) - $reset + local -a charsets + _comp_expand_glob charsets '/usr/share/m{ariadb,ysql}/charsets/!(Index).xml' + charsets+=(utf8) charsets=("${charsets[@]##*/}") - charsets=("${charsets[@]%%?(Index|\*).xml}" utf8) - COMPREPLY+=($(compgen -W '${charsets[@]}' -- "$cur")) + charsets=("${charsets[@]%.xml}") + _comp_compgen -U charsets -- -W '"${charsets[@]}"' -X '' } -_mysql() +# @deprecated 2.12 +_mysql_character_sets() { - local cur prev words cword split - _init_completion -s || return + _comp_compgen -ax mysql character_sets "$@" +} +_comp_cmd_mysql() +{ + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + + # Prefer `mysqlshow` in the same dir as the command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + + local noargopts='!(-*|*[uDhSPeI]*)' + # shellcheck disable=SC2254 case $prev in - --user | -!(-*)u) - COMPREPLY=($(compgen -u -- "$cur")) + --user | -${noargopts}u) + _comp_compgen -- -u return ;; - --database | -!(-*)D) - COMPREPLY=($(compgen -W "$(mysqlshow 2>/dev/null | command sed -ne '2d' -e 's/^|.\([^|]*\)|.*/\1/p')" -- "$cur")) + --database | -${noargopts}D) + _comp_compgen_split -- "$(mysqlshow 2>/dev/null | + command sed -ne '2d' -e 's/^|.\([^|]*\)|.*/\1/p')" return ;; - --host | -!(-*)h) - _known_hosts_real -- "$cur" + --host | -${noargopts}h) + _comp_compgen_known_hosts -- "$cur" return ;; --default-character-set) - _mysql_character_sets + _comp_xfunc_mysql_compgen_character_sets return ;; --character-sets-dir | --ssl-capath) - _filedir -d + _comp_compgen_filedir -d return ;; - --socket | -!(-*)S) - _filedir sock + --socket | -${noargopts}S) + _comp_compgen_filedir sock return ;; --protocol) - COMPREPLY=($(compgen -W 'tcp socket pipe memory' -- "$cur")) + _comp_compgen -- -W 'tcp socket pipe memory' return ;; --defaults-file | --defaults-extra-file | --tee) - _filedir + _comp_compgen_filedir return ;; --ssl-ca | --ssl-cert) - _filedir '@(pem|cer|c?(e)rt)' + _comp_compgen_filedir '@(pem|cer|c?(e)rt)' return ;; --ssl-key) - _filedir '@(pem|key)' + _comp_compgen_filedir '@(pem|key)' return ;; --port | --set-variable | --ssl-cipher | --connect_timeout | \ --max_allowed_packet | --prompt | --net_buffer_length | --select_limit | \ --max_join_size | --server-arg | --debug | --delimiter | --execute | --pager | \ - -!(-*)[Pe]) + -${noargopts}[Pe]) return ;; - --help | --version | -!(-*)[?IV]) + --help | --version | -${noargopts}[?IV]) return ;; esac - $split && return + [[ $was_split ]] && return case $cur in --*) - local help=$(_parse_help "$1") - help+=" --skip-comments --skip-ssl" - - COMPREPLY=($(compgen -W "$help" -- "$cur")) + _comp_compgen_help + _comp_compgen -a -- -W '--skip-comments --skip-ssl' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return ;; @@ -90,10 +101,9 @@ _mysql() ;; esac - COMPREPLY=($(compgen -W \ - "$(mysqlshow 2>/dev/null | command sed -ne '2d' -e 's/^|.\([^|]*\)|.*/\1/p')" \ - -- "$cur")) + _comp_compgen_split -- "$(mysqlshow 2>/dev/null | + command sed -ne '2d' -e 's/^|.\([^|]*\)|.*/\1/p')" } && - complete -F _mysql mysql + complete -F _comp_cmd_mysql mysql # ex: filetype=sh diff --git a/completions/mysqladmin b/completions/mysqladmin index 5329534..af7d50f 100644 --- a/completions/mysqladmin +++ b/completions/mysqladmin @@ -1,63 +1,65 @@ # bash completion for mysqladmin -*- shell-script -*- -_mysqladmin() +_comp_cmd_mysqladmin() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[uhScPOiw]*)' + # shellcheck disable=SC2254 case $prev in - --user | -!(-*)u) - COMPREPLY=($(compgen -u -- "$cur")) + --user | -${noargopts}u) + _comp_compgen -- -u return ;; - --host | -!(-*)h) - _known_hosts_real -- "$cur" + --host | -${noargopts}h) + _comp_compgen_known_hosts -- "$cur" return ;; --character-sets-dir | --ssl-capath) - _filedir -d + _comp_compgen_filedir -d return ;; --default-character-set) - _xfunc mysql _mysql_character_sets + _comp_compgen -x mysql character_sets return ;; - --socket | -!(-*)S) - _filedir sock + --socket | -${noargopts}S) + _comp_compgen_filedir sock return ;; --defaults-file | --defaults-extra-file) - _filedir + _comp_compgen_filedir return ;; --ssl-ca | --ssl-cert) - _filedir '@(pem|cer|c?(e)rt)' + _comp_compgen_filedir '@(pem|cer|c?(e)rt)' return ;; --ssl-key) - _filedir '@(pem|key)' + _comp_compgen_filedir '@(pem|key)' return ;; --count | --port | --set-variable | --sleep | --ssl-cipher | --wait | \ - --connect_timeout | --shutdown_timeout | -!(-*)[cPOiw]) + --connect_timeout | --shutdown_timeout | -${noargopts}[cPOiw]) return ;; - --help | --version | -!(-*)[?V]) + --help | --version | -${noargopts}[?V]) return ;; esac - $split && return + [[ $was_split ]] && return - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help - COMPREPLY+=($(compgen -W 'create debug drop extended-status flush-hosts + _comp_compgen -a -- -W 'create debug drop extended-status flush-hosts flush-logs flush-status flush-tables flush-threads flush-privileges kill password old-password ping processlist reload refresh shutdown - status start-slave stop-slave variables version' -- "$cur")) + status start-slave stop-slave variables version' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace } && - complete -F _mysqladmin mysqladmin + complete -F _comp_cmd_mysqladmin mysqladmin # ex: filetype=sh diff --git a/completions/nc b/completions/nc index 6fb0994..22e297c 100644 --- a/completions/nc +++ b/completions/nc @@ -1,9 +1,9 @@ # nc(1) completion -*- shell-script -*- -_nc() +_comp_cmd_nc() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return case $prev in -*[hIiMmOPpqVWw]) @@ -11,41 +11,39 @@ _nc() ;; -*s) if [[ ${words[*]} == *-6* ]]; then - _ip_addresses -6 - __ltrim_colon_completions "$cur" + _comp_compgen_ip_addresses -6 else - _ip_addresses + _comp_compgen_ip_addresses fi return ;; -*T) - COMPREPLY=($(compgen -W 'critical inetcontrol lowcost lowdelay - netcontrol throughput reliability ef af{11..43} cs{0..7}' \ - -- "$cur")) + _comp_compgen -- -W 'critical inetcontrol lowcost lowdelay + netcontrol throughput reliability ef af{11..43} cs{0..7}' return ;; -*X) - COMPREPLY=($(compgen -W '4 5 connect' -- "$cur")) + _comp_compgen -- -W '4 5 connect' return ;; -*x) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur")) + _comp_compgen_help -- -h return fi # Complete 1st non-option arg only - local args - _count_args "" "-*[IiMmOPpqsTVWwXx]" - ((args == 1)) || return + local REPLY + _comp_count_args -n "" -a "-*[IiMmOPpqsTVWwXx]" + ((REPLY == 1)) || return - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" } && - complete -F _nc nc + complete -F _comp_cmd_nc nc # ex: filetype=sh diff --git a/completions/ncftp b/completions/ncftp index c3f2cf1..60218c1 100644 --- a/completions/ncftp +++ b/completions/ncftp @@ -1,9 +1,9 @@ # bash completion for ncftp -*- shell-script -*- -_ncftp() +_comp_cmd_ncftp() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -u | -p | -P | -j | -F) @@ -12,16 +12,16 @@ _ncftp() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur")) + _comp_compgen_help -- -h return fi if [[ $cword -eq 1 && -f ~/.ncftp/bookmarks ]]; then - COMPREPLY=($(compgen -W '$(command sed -ne "s/^\([^,]\{1,\}\),.*$/\1/p" \ - ~/.ncftp/bookmarks)' -- "$cur")) + _comp_compgen_split -- "$(command sed -ne \ + 's/^\([^,]\{1,\}\),.*$/\1/p' ~/.ncftp/bookmarks)" fi } && - complete -F _ncftp -o default ncftp + complete -F _comp_cmd_ncftp -o default ncftp # ex: filetype=sh diff --git a/completions/nethogs b/completions/nethogs index 5cd3650..c39a707 100644 --- a/completions/nethogs +++ b/completions/nethogs @@ -1,26 +1,26 @@ # bash completion for nethogs(8) -*- shell-script -*- -_nethogs() +_comp_cmd_nethogs() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case "$prev" in -d) # expect integer value - COMPREPLY+=($(compgen -W '{0..9}')) + _comp_compgen -aR -- -W '{0..9}' compopt -o nospace return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" -h)' -- "$cur")) + _comp_compgen_usage -- -h return fi - _available_interfaces -a + _comp_compgen_available_interfaces -a } && - complete -F _nethogs nethogs + complete -F _comp_cmd_nethogs nethogs # ex: filetype=sh diff --git a/completions/newlist b/completions/newlist index f1f6cf8..b4e6060 100644 --- a/completions/newlist +++ b/completions/newlist @@ -1,9 +1,9 @@ # mailman newlist completion -*- shell-script -*- -_newlist() +_comp_cmd_newlist() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -l | --language | -u | --urlhost | -e | --emailhost | --help) @@ -11,15 +11,18 @@ _newlist() ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - _xfunc list_lists _mailman_lists + # Prefer `list_lists` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen -x list_lists mailman_lists fi } && - complete -F _newlist newlist + complete -F _comp_cmd_newlist newlist # ex: filetype=sh diff --git a/completions/newusers b/completions/newusers index 890a5fc..28282f6 100644 --- a/completions/newusers +++ b/completions/newusers @@ -1,13 +1,13 @@ # newusers(8) completion -*- shell-script -*- -_newusers() +_comp_cmd_newusers() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -c | --crypt) - COMPREPLY=($(compgen -W 'DES MD5 NONE SHA256 SHA512' -- "$cur")) + _comp_compgen -- -W 'DES MD5 NONE SHA256 SHA512' return ;; -s | --sha-rounds) @@ -15,16 +15,16 @@ _newusers() ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir + _comp_compgen_filedir } && - complete -F _newusers newusers + complete -F _comp_cmd_newusers newusers # ex: filetype=sh diff --git a/completions/ngrep b/completions/ngrep index 7d16c8d..14f39a9 100644 --- a/completions/ngrep +++ b/completions/ngrep @@ -1,38 +1,38 @@ # ngrep(8) completion -*- shell-script -*- -_ngrep() +_comp_cmd_ngrep() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -h | -V | -n | -A | -s | -S | -c | -P) return ;; -I | -O) - _filedir 'pcap?(ng)' + _comp_compgen_filedir 'pcap?(ng)' return ;; -d) - _available_interfaces -a - COMPREPLY+=($(compgen -W 'any' -- "$cur")) + _comp_compgen_available_interfaces -a + _comp_compgen -a -- -W 'any' return ;; -W) - COMPREPLY=($(compgen -W 'normal byline single none' -- "$cur")) + _comp_compgen -- -W 'normal byline single none' return ;; -F) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur")) + _comp_compgen_help -- -h return fi } && - complete -F _ngrep ngrep + complete -F _comp_cmd_ngrep ngrep # ex: filetype=sh diff --git a/completions/nmap b/completions/nmap index 482148e..a3e691b 100644 --- a/completions/nmap +++ b/completions/nmap @@ -1,30 +1,30 @@ # bash completion for nmap -*- shell-script -*- -_nmap() +_comp_cmd_nmap() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -iL | -oN | -oX | -oS | -oG | ---excludefile | --resume | --stylesheet) - _filedir + _comp_compgen_filedir return ;; -oA | --datadir) - _filedir -d + _comp_compgen_filedir -d return ;; -e) - _available_interfaces -a + _comp_compgen_available_interfaces -a return ;; -b | --dns-servers) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then # strip everything following a :, inclusive @@ -35,7 +35,7 @@ _nmap() # expand --foo/bar to --foo --bar # strip everything following a non-option name or = char # TODO: should expand -T<0-5> to -T0 ... -T5 - COMPREPLY=($(compgen -W "$( + _comp_compgen_split -- "$( "$1" --help 2>&1 | command sed \ -e "s/:.*$//" \ -e "s/=.*$/=/" \ @@ -44,13 +44,12 @@ _nmap() -e "/^[[:space:]]*-[^-]/s/\/\([^-]\)/ -\1/g" \ -e "/^[[:space:]]*--/s/\/\([^-]\)/ --\1/g" \ -e "s/[^[:space:]a-zA-Z0-9=-].*$//" - )" \ - -- "$cur")) + )" [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" fi } && - complete -F _nmap nmap + complete -F _comp_cmd_nmap nmap # ex: filetype=sh diff --git a/completions/nproc b/completions/nproc index 50273f0..dc38944 100644 --- a/completions/nproc +++ b/completions/nproc @@ -1,9 +1,9 @@ # nproc(1) completion -*- shell-script -*- -_nproc() +_comp_cmd_nproc() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in --help | --version | --ignore) @@ -11,13 +11,13 @@ _nproc() ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _nproc nproc + complete -F _comp_cmd_nproc nproc # ex: filetype=sh diff --git a/completions/nslookup b/completions/nslookup index 3341b1f..b04b03a 100644 --- a/completions/nslookup +++ b/completions/nslookup @@ -1,32 +1,42 @@ # bash completion for nslookup -*- shell-script -*- -_bind_queryclass() +_comp_cmd_nslookup__queryclass() { - COMPREPLY+=($(compgen -W 'IN CH HS ANY' -- "$cur")) + _comp_compgen -a -- -W 'IN CH HS ANY' } -_bind_querytype() +_comp_cmd_nslookup__querytype() { # https://en.wikipedia.org/wiki/List_of_DNS_record_types - COMPREPLY+=($(compgen -W 'A AAAA AFSDB APL CERT CNAME DHCID DLV DNAME - DNSKEY DS HIP IPSECKEY KEY KX LOC MX NAPTR NS NSEC NSEC3 NSEC3PARAM PTR - RRSIG RP SIG SOA SPF SRV SSHFP TXT' -- "$cur")) + # Resource records + local -a types=( + A AAAA AFSDB APL CAA CDNSKEY CDS CERT CNAME CSYNC DHCID DLV DNAME + DNSKEY DS EUI48 EUI64 HINFO HIP IPSECKEY KEY KX LOC MX NAPTR NS NSEC + NSEC3 NSEC3PARAM OPENPGPKEY PTR RRSIG RP SIG SMIMEA SOA SRV SSHFP TA + TKEY TLSA TSIG TXT URI ZONEMD SVCB HTTPS + ) + # Other types/pseudo record types + types+=(AXFR IXFR OPT) + # Selected obsolete record types + types+=(SPF) + + _comp_compgen -a -- -W '"${types[@]}"' } -_nslookup() +_comp_cmd_nslookup() { - local cur prev words cword - _init_completion -n = || return + local cur prev words cword comp_args + _comp_initialize -n = -- "$@" || return case $cur in -class=* | -cl=*) cur=${cur#*=} - _bind_queryclass + _comp_cmd_nslookup__queryclass return ;; -querytype=* | -type=* | -q=* | -ty=*) cur=${cur#*=} - _bind_querytype + _comp_cmd_nslookup__querytype return ;; -?*=*) @@ -35,38 +45,38 @@ _nslookup() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-all -class= -debug -nodebug -d2 -nod2 - -domain= -search -nosearch -port= -querytype= -recurse -norecurse - -retry= -timeout= -vc -novc -fail -nofail' -- "$cur")) + _comp_compgen -- -W '-all -class= -debug -nodebug -d2 -nod2 -domain= + -search -nosearch -port= -querytype= -recurse -norecurse -retry= + -timeout= -vc -novc -fail -nofail' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - local args - _count_args = - if ((args <= 2)); then - _known_hosts_real -- "$cur" - [[ $args -eq 1 && $cur == @(|-) ]] && COMPREPLY+=(-) + local REPLY + _comp_count_args + if ((REPLY <= 2)); then + _comp_compgen_known_hosts -- "$cur" + [[ $REPLY -eq 1 && $cur == @(|-) ]] && COMPREPLY+=(-) fi } && - complete -F _nslookup nslookup + complete -F _comp_cmd_nslookup nslookup -_host() +_comp_cmd_host() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -c) - _bind_queryclass + _comp_cmd_nslookup__queryclass return ;; -t) - _bind_querytype + _comp_cmd_nslookup__querytype return ;; -m) - COMPREPLY=($(compgen -W 'trace record usage' -- "$cur")) + _comp_compgen -- -W 'trace record usage' return ;; -N | -R | -W) @@ -75,12 +85,21 @@ _host() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage return fi - _known_hosts_real -- "$cur" + local REPLY + _comp_count_args -a "-*[ctmNRW]" + if ((REPLY == 1)); then + _comp_compgen_known_hosts -- "$cur" + elif ((REPLY == 2)); then + local ipvx + [[ ${words[*]} =~ \ -[^\ ]*([46]) ]] && ipvx=-${BASH_REMATCH[1]} + # shellcheck disable=SC2086 + _comp_compgen_known_hosts ${ipvx-} -- "$cur" + fi } && - complete -F _host host + complete -F _comp_cmd_host host # ex: filetype=sh diff --git a/completions/nsupdate b/completions/nsupdate index 68df333..854e33c 100644 --- a/completions/nsupdate +++ b/completions/nsupdate @@ -1,27 +1,25 @@ # bash completion for nsupdate(1) -*- shell-script -*- -_nsupdate() +_comp_cmd_nsupdate() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*[VLprtu]) return ;; -*k) - _filedir key + _comp_compgen_filedir key return ;; -*R) - cur=${cur:=/dev/} - _filedir + _comp_compgen -c "${cur:-/dev/}" filedir return ;; -*y) if [[ $cur == h* ]]; then - COMPREPLY=($(compgen -W "hmac-{md5,sha{1,224,256,384,512}}" \ - -S : -- "$cur")) + _comp_comtpen -- -W "hmac-{md5,sha{1,224,256,384,512}}" -S : [[ ${COMPREPLY-} == *: ]] && compopt -o nospace fi return @@ -29,12 +27,12 @@ _nsupdate() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage return fi - _filedir + _comp_compgen_filedir } && - complete -F _nsupdate nsupdate + complete -F _comp_cmd_nsupdate nsupdate # ex: filetype=sh diff --git a/completions/ntpdate b/completions/ntpdate index f6ee8f5..5dab0a7 100644 --- a/completions/ntpdate +++ b/completions/ntpdate @@ -1,21 +1,21 @@ # bash completion for ntpdate -*- shell-script -*- -_ntpdate() +_comp_cmd_ntpdate() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*k) - _filedir + _comp_compgen_filedir return ;; -*U) - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u return ;; -*p) - COMPREPLY=($(compgen -W '{1..8}' -- "$cur")) + _comp_compgen -- -W '{1..8}' return ;; @@ -25,11 +25,11 @@ _ntpdate() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_help -- -h || _comp_compgen_usage else - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" fi } && - complete -F _ntpdate ntpdate + complete -F _comp_cmd_ntpdate ntpdate # ex: filetype=sh diff --git a/completions/oggdec b/completions/oggdec index 97bde20..a76ba49 100644 --- a/completions/oggdec +++ b/completions/oggdec @@ -1,38 +1,40 @@ # bash completion for oggdec(1) -*- shell-script -*- -_oggdec() +_comp_cmd_oggdec() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[beso]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | -!(-*)[hV]*) + --help | --version | -${noargopts}[hV]*) return ;; - --bits | -!(-*)b) - COMPREPLY=($(compgen -W "8 16" -- "$cur")) + --bits | -${noargopts}b) + _comp_compgen -- -W "8 16" return ;; - --endianness | --sign | -!(-*)[es]) - COMPREPLY=($(compgen -W "0 1" -- "$cur")) + --endianness | --sign | -${noargopts}[es]) + _comp_compgen -- -W "0 1" return ;; - --output | -!(-*)o) - _filedir wav + --output | -${noargopts}o) + _comp_compgen_filedir wav return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir ogg + _comp_compgen_filedir ogg } && - complete -F _oggdec oggdec + complete -F _comp_cmd_oggdec oggdec # ex: filetype=sh diff --git a/completions/op b/completions/op deleted file mode 100644 index 31d6475..0000000 --- a/completions/op +++ /dev/null @@ -1,59 +0,0 @@ -# op (1Password CLI) completion -*- shell-script -*- - -_op_commands() -{ - "$@" --help 2>/dev/null | - awk '/^(Available |Sub)commands/{flag=1;next}/^ /&&flag{print $1}' -} - -_op_command_options() -{ - case $cur in - -*) - for i in "${!words[@]}"; do - [[ ${words[i]} == -* || $i -eq 0 ]] && unset "words[i]" - done - COMPREPLY=($(compgen -W \ - '$(_parse_usage "$1" "${words[*]} --help") --help' -- "$cur")) - [[ ${COMPREPLY-} == *= ]] && compopt -o nospace - return 0 - ;; - esac - return 1 -} - -_op() -{ - local cur prev words cword split - _init_completion -s || return - - local command i - for ((i = 1; i < cword; i++)); do - case ${words[i]} in - --help | --version) return ;; - -*) ;; - *) - command=${words[i]} - break - ;; - esac - done - - if [[ ! -v command && $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) - [[ ${COMPREPLY-} == *= ]] && compopt -o nospace - return - fi - - [[ -v command ]] && _op_command_options "$1" && return - - if [[ ! -v command || $command == "$prev" ]]; then - COMPREPLY=($(compgen -W '$(_op_commands "$1" ${command-})' -- "$cur")) - [[ ${COMPREPLY-} ]] && return - fi - - # TODO specific command and subcommand completions -} && - complete -F _op op - -# ex: filetype=sh diff --git a/completions/openssl b/completions/openssl index dd77092..9dad715 100644 --- a/completions/openssl +++ b/completions/openssl @@ -1,52 +1,54 @@ # bash completion for openssl -*- shell-script -*- -_openssl_sections() +_comp_cmd_openssl__compgen_sections() { - local config f + local config="" _i _file # check if a specific configuration file is used - for ((i = 2; i < cword; i++)); do - if [[ ${words[i]} == -config ]]; then - config=${words[i + 1]} + for ((_i = 2; _i < cword; _i++)); do + if [[ ${words[_i]} == -config ]]; then + config=${words[_i + 1]} break fi done # if no config given, check some usual default locations - if [[ -z $config ]]; then - for f in /etc/ssl/openssl.cnf /etc/pki/tls/openssl.cnf \ + if [[ ! $config ]]; then + for _file in /etc/ssl/openssl.cnf /etc/pki/tls/openssl.cnf \ /usr/share/ssl/openssl.cnf; do - [[ -f $f ]] && config=$f && break + [[ -f $_file ]] && config=$_file && break done fi [[ ! -f $config ]] && return - COMPREPLY=($(compgen -W "$(awk '/\[.*\]/ {print $2}' $config)" -- "$cur")) + _comp_compgen -U config split -- "$(_comp_awk '/\[.*\]/ {print $2}' "$config")" } -_openssl_digests() +_comp_cmd_openssl__compgen_digests() { - "$1" dgst -h 2>&1 | - awk '/^-.*[ \t]to use the .* message digest algorithm/ { print $1 }' - local -a digests=($("$1" help 2>&1 | + [[ $cur == -* ]] || return + _comp_compgen_split -- "$( + "$1" dgst -h 2>&1 | + _comp_awk '/^-.*[ \t]to use the .* message digest algorithm/ { print $1 }' + )" + _comp_compgen -ac "${cur#-}" split -P "-" -- "$("$1" help 2>&1 | command sed -ne '/^Message Digest commands/,/^[[:space:]]*$/p' | - command sed -e 1d)) - printf "%s\n" "${digests[@]/#/-}" + command sed -e 1d)" } -_openssl() +_comp_cmd_openssl() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - local commands command options formats + local commands command formats commands='asn1parse ca ciphers crl crl2pkcs7 dgst dh dhparam dsa dsaparam ec ecparam enc engine errstr gendh gendsa genrsa nseq ocsp passwd pkcs12 pkcs7 pkcs8 prime rand req rsa rsautl s_client s_server s_time - sess_id smime speed spkac verify version x509 md2 md4 md5 rmd160 sha - sha1 aes-128-cbc aes-128-ecb aes-192-cbc aes-192-ecb aes-256-cbc + sess_id smime speed spkac storeutl verify version x509 md2 md4 md5 rmd160 + sha sha1 aes-128-cbc aes-128-ecb aes-192-cbc aes-192-ecb aes-256-cbc aes-256-ecb base64 bf bf-cbc bf-cfb bf-ecb bf-ofb camellia-128-cbc camellia-128-ecb camellia-192-cbc camellia-192-ecb camellia-256-cbc camellia-256-ecb cast cast-cbc cast5-cbc cast5-cfb cast5-ecb cast5-ofb @@ -56,7 +58,7 @@ _openssl() sha224 sha256 sha384 sha512 genpkey pkey pkeyparam pkeyutl' if ((cword == 1)); then - COMPREPLY=($(compgen -W "$commands" -- "$cur")) + _comp_compgen -- -W "$commands" else command=${words[1]} case $prev in @@ -65,15 +67,15 @@ _openssl() -out | -oid | -paramfile | -peerkey | -prvrify | -rand | -recip | -revoke | \ -sess_in | -sess_out | -spkac | -sigfile | -sign | -signkey | -signer | \ -signature | -ss_cert | -untrusted | -verify | -writerand) - _filedir + _comp_compgen_filedir return ;; -outdir | -CApath) - _filedir -d + _comp_compgen_filedir -d return ;; -name | -crlexts | -extensions) - _openssl_sections + _comp_cmd_openssl__compgen_sections return ;; -inform | -outform | -keyform | -certform | -CAform | -CAkeyform | -dkeyform | \ @@ -90,49 +92,48 @@ _openssl() formats+=" ENGINE" ;; esac - COMPREPLY=($(compgen -W "$formats" -- "$cur")) + _comp_compgen -- -W "$formats" return ;; -connect) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -starttls) - COMPREPLY=($(compgen -W ' - smtp pop3 imap ftp xmpp xmpp-server telnet irc mysql - postgres lmtp nntp sieve ldap - ' -- "$cur")) + _comp_compgen -- -W ' smtp pop3 imap ftp xmpp xmpp-server + telnet irc mysql postgres lmtp nntp sieve ldap' return ;; -cipher) - COMPREPLY=($(IFS=: compgen -W "$($1 ciphers)" -- "$cur")) + _comp_compgen_split -F : -- "$("$1" ciphers)" return ;; -kdf) - COMPREPLY=($(compgen -W 'TLS1-PRF HKDF' -- "$cur")) + _comp_compgen -- -W 'TLS1-PRF HKDF' return ;; esac if [[ $cur == -* ]]; then # possible options for the command - options=$(_parse_help "$1" "$command -help" 2>/dev/null) + _comp_compgen_help -- "$command" -help case $command in - dgst | req | x509) options+=" $(_openssl_digests $1)" ;; + dgst | req | x509) + _comp_compgen -a -i openssl digests "$1" + ;; esac - COMPREPLY=($(compgen -W "$options" -- "$cur")) else if [[ $command == speed ]]; then - COMPREPLY=($(compgen -W 'md2 mdc2 md5 hmac sha1 rmd160 - idea-cbc rc2-cbc rc5-cbc bf-cbc des-cbc des-ede3 rc4 - rsa512 rsa1024 rsa2048 rsa4096 dsa512 dsa1024 dsa2048 idea - rc2 des rsa blowfish' -- "$cur")) + _comp_compgen -- -W 'md2 mdc2 md5 hmac sha1 rmd160 idea-cbc + rc2-cbc rc5-cbc bf-cbc des-cbc des-ede3 rc4 rsa512 rsa1024 + rsa2048 rsa4096 dsa512 dsa1024 dsa2048 idea rc2 des rsa + blowfish' else - _filedir + _comp_compgen_filedir fi fi fi } && - complete -F _openssl -o default openssl + complete -F _comp_cmd_openssl -o default openssl # ex: filetype=sh diff --git a/completions/opera b/completions/opera index f2bc8c3..c9245e4 100644 --- a/completions/opera +++ b/completions/opera @@ -1,29 +1,28 @@ # opera(1) completion -*- shell-script -*- -_opera() +_comp_cmd_opera() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case "$prev" in ?(-)-widget | ?(-)-urllist | ?(-)-uiparserlog | ?(-)-uiwidgetsparserlog | \ ?(-)-profilinglog) - _filedir + _comp_compgen_filedir return ;; ?(-)-[psb]d) - _filedir -d + _comp_compgen_filedir -d return ;; ?(-)-remote) - COMPREPLY=($(compgen -W 'openURL\\( openFile\\( openM2\\( - openComposer\\( addBookmark\\( raise\\(\\) lower\\(\\)' \ - -- "$cur")) + _comp_compgen -- -W 'openURL\\( openFile\\( openM2\\( + openComposer\\( addBookmark\\( raise\\(\\) lower\\(\\)' [[ ${COMPREPLY-} == *\( ]] && compopt -o nospace return ;; ?(-)-windowname) - COMPREPLY=($(compgen -W 'first last opera{1..9}' -- "$cur")) + _comp_compgen -- -W 'first last opera{1..9}' return ;; ?(-)-geometry | ?(-)-window | ?(-)-display | ?(-)-urllistloadtimeout | \ @@ -35,13 +34,13 @@ _opera() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir '@(?([xX]|[sS])[hH][tT][mM]?([lL]))' + _comp_compgen_filedir '@(?([xX]|[sS])[hH][tT][mM]?([lL]))' } && - complete -F _opera opera + complete -F _comp_cmd_opera opera # ex: filetype=sh diff --git a/completions/optipng b/completions/optipng index 0f6b40e..a81ffa2 100644 --- a/completions/optipng +++ b/completions/optipng @@ -1,52 +1,51 @@ # optipng(1) completion -*- shell-script -*- -_optipng() +_comp_cmd_optipng() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -'?' | -h | --help | -f) return ;; -o) - COMPREPLY=($(compgen -W '{0..7}' -- "$cur")) + _comp_compgen -- -W '{0..7}' return ;; -out | -log) - _filedir + _comp_compgen_filedir return ;; -dir) - _filedir -d + _comp_compgen_filedir -d return ;; -i) - COMPREPLY=($(compgen -W '0 1' -- "$cur")) + _comp_compgen -- -W '0 1' return ;; -zc | -zm) - COMPREPLY=($(compgen -W '{1..9}' -- "$cur")) + _comp_compgen -- -W '{1..9}' return ;; -zw) - COMPREPLY=($(compgen -W '256 512 1k 2k 4k 8k 16k 32k' \ - -- "$cur")) + _comp_compgen -- -W '256 512 1k 2k 4k 8k 16k 32k' return ;; -strip) - COMPREPLY=($(compgen -W 'all' -- "$cur")) + _comp_compgen -- -W 'all' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - _filedir '@(png|bmp|gif|pnm|tif?(f))' + _comp_compgen_filedir '@(png|bmp|gif|pnm|tif?(f))' } && - complete -F _optipng optipng + complete -F _comp_cmd_optipng optipng # ex: filetype=sh diff --git a/completions/p4 b/completions/p4 index ed5f20c..5bcadf6 100644 --- a/completions/p4 +++ b/completions/p4 @@ -1,30 +1,29 @@ # Perforce completion -*- shell-script -*- # by Frank Cusack <frank@google.com> -_p4() +_comp_cmd_p4() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local p4commands p4filetypes # rename isn't really a command - p4commands="$(p4 help commands 2>/dev/null | awk 'NF>3 {print $1}')" + p4commands="$(p4 help commands 2>/dev/null | _comp_awk 'NF>3 {print $1}')" p4filetypes="ctext cxtext ktext kxtext ltext tempobj ubinary \ uresource uxbinary xbinary xltext xtempobj xtext \ text binary resource" if ((cword == 1)); then - COMPREPLY=($(compgen -W "$p4commands" -- "$cur")) + _comp_compgen -- -W "$p4commands" elif ((cword == 2)); then case $prev in help) - COMPREPLY=($(compgen -W "simple commands environment - filetypes jobview revisions usage views $p4commands" \ - -- "$cur")) + _comp_compgen -- -W "simple commands environment filetypes + jobview revisions usage views $p4commands" ;; admin) - COMPREPLY=($(compgen -W "checkpoint stop" -- "$cur")) + _comp_compgen -- -W "checkpoint stop" ;; *) ;; @@ -34,7 +33,7 @@ _p4() -t) case ${words[cword - 2]} in add | edit | reopen) - COMPREPLY=($(compgen -W "$p4filetypes" -- "$cur")) + _comp_compgen -- -W "$p4filetypes" ;; *) ;; @@ -46,6 +45,6 @@ _p4() fi } && - complete -F _p4 -o default p4 g4 + complete -F _comp_cmd_p4 -o default p4 g4 # ex: filetype=sh diff --git a/completions/pack200 b/completions/pack200 index 1a6ded7..a4abe92 100644 --- a/completions/pack200 +++ b/completions/pack200 @@ -1,74 +1,74 @@ # pack200(1) completion -*- shell-script -*- -_pack200() +_comp_cmd_pack200() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -S | --segment-limit | -P | --pass-file | -C | --class-attribute | \ - -F | --field-attribute | -M | --method-attribute | -D | --code-attribute | \ - '-?' | -h | --help | -V | --version | -J) + -F | --field-attribute | -M | --method-attribute | -D | \ + --code-attribute | '-?' | -h | --help | -V | --version | -J) return ;; -E | --effort) - COMPREPLY=($(compgen -W '{0..9}' -- "$cur")) + _comp_compgen -- -W '{0..9}' return ;; -H | --deflate-hint) - COMPREPLY=($(compgen -W 'true false keep' -- "$cur")) + _comp_compgen -- -W 'true false keep' return ;; -m | --modification-time) - COMPREPLY=($(compgen -W 'latest keep' -- "$cur")) + _comp_compgen -- -W 'latest keep' return ;; -U | --unknown-attribute) - COMPREPLY=($(compgen -W 'error strip pass' -- "$cur")) + _comp_compgen -- -W 'error strip pass' return ;; -f | --config-file) - _filedir properties + _comp_compgen_filedir properties return ;; -l | --log-file) - COMPREPLY=($(compgen -W '-' -- "$cur")) - _filedir log + _comp_compgen -- -W '-' + _comp_compgen -a filedir log return ;; -r | --repack) - _filedir jar + _comp_compgen_filedir jar return ;; esac - $split && return + [[ $was_split ]] && return # Check if a pack or a jar was already given. - local i pack=false jar=false - for ((i = 1; i < ${#words[@]} - 1; i++)); do + local i pack="" jar="" + for ((i = 1; i < cword; i++)); do case ${words[i]} in - *.pack | *.pack.gz) pack=true ;; - *.jar) jar=true ;; + *.pack | *.pack.gz) pack=set ;; + *.jar) jar=set ;; esac done - if ! $pack; then + if [[ ! $pack ]]; then if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--no-gzip --gzip --strip-debug + _comp_compgen -- -W '--no-gzip --gzip --strip-debug --no-keep-file-order --segment-limit= --effort= --deflate-hint= --modification-time= --pass-file= --unknown-attribute= --class-attribute= --field-attribute= --method-attribute= --code-attribute= --config-file= --verbose --quiet --log-file= - --help --version -J --repack' -- "$cur")) + --help --version -J --repack' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - _filedir 'pack?(.gz)' + _comp_compgen_filedir 'pack?(.gz)' fi - elif ! $jar; then - _filedir jar + elif [[ ! $jar ]]; then + _comp_compgen_filedir jar fi } && - complete -F _pack200 pack200 + complete -F _comp_cmd_pack200 pack200 # ex: filetype=sh diff --git a/completions/passwd b/completions/passwd index 652a41e..b34a1e7 100644 --- a/completions/passwd +++ b/completions/passwd @@ -1,24 +1,26 @@ # passwd(1) completion -*- shell-script -*- -_passwd() +_comp_cmd_passwd() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[nxwi]*)' + # shellcheck disable=SC2254 case $prev in - --minimum | --maximum | --warning | --inactive | --help | --usage | -!(-*)[nxwi?]) + --minimum | --maximum | --warning | --inactive | --help | --usage | \ + -${noargopts}[nxwi?]) return ;; esac if [[ $cur == -* ]]; then - local opts=$(_parse_help "$1") - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage return fi - _allowed_users + _comp_compgen_allowed_users } && - complete -F _passwd passwd + complete -F _comp_cmd_passwd passwd # ex: filetype=sh diff --git a/completions/patch b/completions/patch index e883d9c..bba184c 100644 --- a/completions/patch +++ b/completions/patch @@ -1,70 +1,71 @@ # patch(1) completion -*- shell-script -*- -_patch() +_comp_cmd_patch() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[pDBYzgFiorVd]*)' + # shellcheck disable=SC2254 case $prev in --strip | --ifdef | --prefix | --basename-prefix | --suffix | --get | \ - -!(-*)[pDBYzg]) + -${noargopts}[pDBYzg]) return ;; - --fuzz | -!(-*)F) - COMPREPLY=($(compgen -W '{0..3}' -- "$cur")) + --fuzz | -${noargopts}F) + _comp_compgen -- -W '{0..3}' return ;; - --input | -!(-*)i) - _filedir '@(?(d)patch|dif?(f))' + --input | -${noargopts}i) + _comp_compgen_filedir '@(?(d)patch|dif?(f))' return ;; - --output | --reject-file | -!(-*)[or]) + --output | --reject-file | -${noargopts}[or]) [[ ! $cur || $cur == - ]] && COMPREPLY=(-) - _filedir + _comp_compgen -a filedir return ;; --quoting-style) - COMPREPLY=($(compgen -W 'literal shell shell-always c escape' \ - -- "$cur")) + _comp_compgen -- -W 'literal shell shell-always c escape' return ;; - --version-control | -!(-*)V) - COMPREPLY=($(compgen -W 'simple numbered existing' -- "$cur")) + --version-control | -${noargopts}V) + _comp_compgen -- -W 'simple numbered existing' return ;; - --directory | -!(-*)d) - _filedir -d + --directory | -${noargopts}d) + _comp_compgen_filedir -d return ;; --reject-format) - COMPREPLY=($(compgen -W 'context unified' -- "$cur")) + _comp_compgen -- -W 'context unified' return ;; --read-only) - COMPREPLY=($(compgen -W 'ignore warn fail' -- "$cur")) + _comp_compgen -- -W 'ignore warn fail' return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - local args - _count_args - case $args in + local REPLY + _comp_count_args + case $REPLY in 1) - _filedir + _comp_compgen_filedir ;; 2) - _filedir '@(?(d)patch|dif?(f))' + _comp_compgen_filedir '@(?(d)patch|dif?(f))' ;; esac } && - complete -F _patch patch + complete -F _comp_cmd_patch patch # ex: filetype=sh diff --git a/completions/pdftoppm b/completions/pdftoppm new file mode 100644 index 0000000..ac97b41 --- /dev/null +++ b/completions/pdftoppm @@ -0,0 +1,35 @@ +# bash completion for pdftoppm(1) -*- shell-script -*- + +_comp_cmd_pdftoppm() +{ + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + + case $prev in + -[flrxyWH] | -r[xy] | -scale?(-to-[xy]) | -jpegopt | -[ou]pw) + return + ;; + -tiffcompression) + _comp_compgen -- -W 'none packbits jpeg lzw deflate' + return + ;; + -freetype | -aa | -aaVector) + _comp_compgen -- -W 'yes no' + return + ;; + -thinlinemode) + _comp_compgen -- -W 'none solid shape' + return + ;; + esac + + if [[ $cur == -* ]]; then + _comp_compgen_help + return + fi + + [[ $prev == *.pdf ]] || _comp_compgen_filedir pdf +} && + complete -F _comp_cmd_pdftoppm pdftoppm + +# ex: filetype=sh diff --git a/completions/pdftotext b/completions/pdftotext index a3501ba..a99fd40 100644 --- a/completions/pdftotext +++ b/completions/pdftotext @@ -1,39 +1,40 @@ # bash completion for pdftotext(1) -*- shell-script -*- -_pdftotext() +_comp_cmd_pdftotext() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in - -h | -help | --help | -'?' | -f | -l | -r | -x | -y | -W | -H | -fixed | -opw | -upw) + -h | -help | --help | -'?' | -f | -l | -r | -x | -y | -W | -H | \ + -fixed | -opw | -upw) return ;; -enc) - COMPREPLY=($(compgen -W '$("$1" -listenc 2>/dev/null | - command sed -e 1d)' -- "$cur")) + _comp_compgen_split -- "$("$1" -listenc 2>/dev/null | + command sed -e 1d)" return ;; -eol) - COMPREPLY=($(compgen -W "unix dos mac" -- "$cur")) + _comp_compgen -- -W "unix dos mac" return ;; esac if [[ $cur == -* && ${prev,,} != *.pdf ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi case ${prev,,} in - | *.txt) ;; *.pdf) - COMPREPLY=($(compgen -W '-' -- "$cur")) - _filedir txt + _comp_compgen -- -W '-' + _comp_compgen -a filedir txt ;; - *) _filedir pdf ;; + *) _comp_compgen_filedir pdf ;; esac } && - complete -F _pdftotext pdftotext + complete -F _comp_cmd_pdftotext pdftotext # ex: filetype=sh diff --git a/completions/perl b/completions/perl index 9823d73..9b82777 100644 --- a/completions/perl +++ b/completions/perl @@ -1,17 +1,16 @@ # bash completion for perl -*- shell-script -*- -_perl_helper() +_comp_cmd_perl__helper() { - COMPREPLY=($(compgen -P "$prefix" -W \ - "$(${2:-perl} ${BASH_SOURCE[0]%/*}/../helpers/perl $1 $cur)" \ - -- "$cur")) - [[ $1 == functions ]] || __ltrim_colon_completions "$prefix$cur" + _comp_compgen_split -P "$prefix" -- "$("${1:-perl}" \ + "${BASH_SOURCE[0]%/*}/../helpers/perl" "$2" "$cur")" + [[ $2 == functions ]] || _comp_ltrim_colon_completions "$prefix$cur" } -_perl() +_comp_cmd_perl() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return local prefix="" temp optPrefix optSuffix @@ -33,36 +32,35 @@ _perl() return ;; -*[Ix]) - local IFS=$'\n' compopt -o filenames - COMPREPLY=($(compgen -d $optPrefix $optSuffix -- "$cur")) + _comp_compgen -- -d "$optPrefix" $optSuffix return ;; -*[mM]) temp="${cur#-}" - prefix+="${cur%$temp}" + prefix+=${cur%"$temp"} cur="$temp" - _perl_helper modules $1 + _comp_cmd_perl__helper "$1" modules return ;; -*V) if [[ $cur == :* ]]; then temp="${cur##+(:)}" - prefix+="${cur%$temp}" - local IFS=$'\n' - COMPREPLY=($(compgen -P "$prefix" -W \ - '$($1 -MConfig -e "print join \"\\n\", - keys %Config::Config" 2>/dev/null)' -- "$temp")) - __ltrim_colon_completions "$prefix$temp" + prefix+=${cur%"$temp"} + _comp_compgen -c "$temp" split -lP "$prefix" -- "$( + "$1" -MConfig -e 'print join "\n", + keys %Config::Config' 2>/dev/null + )" + _comp_ltrim_colon_completions "$prefix$temp" fi return ;; -*d | -*dt) if [[ $cur == :* ]]; then temp="${cur#:}" - prefix="$prefix${cur%$temp}" + prefix=$prefix${cur%"$temp"} cur="Devel::$temp" - _perl_helper modules $1 + _comp_cmd_perl__helper "$1" modules fi ;; esac @@ -71,31 +69,31 @@ _perl() # `-E' options and their arguments, e.g. `perl -e "exit 2"', is # valid syntax. However, the argument is neither a filename nor a # directory, but one line of perl program, thus do not suggest - # _filedir completion. + # _comp_compgen_filedir completion. elif [[ $prev == -e ]] || [[ $prev == -E ]]; then return # Likewise, `-I' also accepts a space between option and argument # and it takes a directory as value. elif [[ $prev == -I ]]; then - local IFS=$'\n' compopt -o filenames - COMPREPLY=($(compgen -d ${optPrefix-} ${optSuffix-} -- "$cur")) + # shellcheck disable=SC2086 + _comp_compgen -- -d ${optPrefix-} ${optSuffix-} return elif [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-C -s -T -u -U -W -X -h -v -V -c -w -d -D -p - -n -a -F -l -0 -I -m -M -P -S -x -i -e' -- "$cur")) + _comp_compgen -- -W '-C -s -T -u -U -W -X -h -v -V -c -w -d -D -p -n -a + -F -l -0 -I -m -M -P -S -x -i -e' else - _filedir + _comp_compgen_filedir fi } && - complete -F _perl perl + complete -F _comp_cmd_perl perl -_perldoc() +_comp_cmd_perldoc() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return local prefix="" temp @@ -107,40 +105,39 @@ _perldoc() prefix=$prev fi - local perl="${1%doc}" - [[ $perl == "$1" ]] || ! type $perl &>/dev/null && perl= + # Prefer `perl` in the same dir in utility functions + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH case $prev in -*[hVnoMwL]) return ;; -*d) - _filedir + _comp_compgen_filedir return ;; -*f) - _perl_helper functions $perl + _comp_cmd_perl__helper "" functions return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur")) + _comp_compgen_help -- -h else # return available modules (unless it is clearly a file) if [[ $cur != @(*/|[.~])* ]]; then - _perl_helper perldocs $perl + _comp_cmd_perl__helper "" perldocs if [[ $cur == p* ]]; then - COMPREPLY+=($(compgen -W \ - '$(PERLDOC_PAGER=cat "$1" -u perl | \ - command sed -ne "/perl.*Perl overview/,/perlwin32/p" | \ - awk "\$NF=2 && \$1 ~ /^perl/ { print \$1 }")' \ - -- "$cur")) + _comp_compgen -a split -- "$(PERLDOC_PAGER=cat "$1" -u perl | + command sed -ne '/perl.*Perl overview/,/perlwin32/p' | + _comp_awk 'NF >= 2 && $1 ~ /^perl/ { print $1 }')" fi fi - _filedir 'p@([lm]|od)' + _comp_compgen -a filedir 'p@([lm]|od)' fi } && - complete -F _perldoc -o bashdefault perldoc + complete -F _comp_cmd_perldoc -o bashdefault perldoc # ex: filetype=sh diff --git a/completions/perlcritic b/completions/perlcritic index 7843549..d368203 100644 --- a/completions/perlcritic +++ b/completions/perlcritic @@ -1,9 +1,9 @@ # perlcritic(1) completion -*- shell-script -*- -_perlcritic() +_comp_cmd_perlcritic() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --help | --version | --top | --include | --exclude | --single-policy | \ @@ -11,41 +11,38 @@ _perlcritic() return ;; --severity) - COMPREPLY=($(compgen -W "{1..5} brutal cruel harsh stern gentle" \ - -- "$cur")) + _comp_compgen -- -W '{1..5} brutal cruel harsh stern gentle' return ;; --profile | -p) - _filedir perlcriticrc + _comp_compgen_filedir perlcriticrc return ;; --theme) - COMPREPLY=($(compgen -W '$("$1" --list-themes 2>/dev/null)' \ - -- "$cur")) + _comp_compgen_split -- "$("$1" --list-themes 2>/dev/null)" return ;; --profile-strictness) - COMPREPLY=($(compgen -W 'warn fatal quiet' -- "$cur")) + _comp_compgen -- -W 'warn fatal quiet' return ;; --verbose) - COMPREPLY=($(compgen -W '{1..11}' -- "$cur")) + _comp_compgen -- -W '{1..11}' return ;; --pager) - compopt -o filenames - COMPREPLY=($(compgen -c -- "$cur")) + _comp_compgen_commands return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage return fi - _filedir 'p[lm]' + _comp_compgen_filedir 'p[lm]' } && - complete -F _perlcritic perlcritic + complete -F _comp_cmd_perlcritic perlcritic # ex: filetype=sh diff --git a/completions/perltidy b/completions/perltidy index 4404cf8..5be5281 100644 --- a/completions/perltidy +++ b/completions/perltidy @@ -1,41 +1,49 @@ # perltidy(1) completion -*- shell-script -*- -_perltidy() +_comp_cmd_perltidy() { - local cur prev words cword - _init_completion -n = || return + local cur prev words cword comp_args + _comp_initialize -n = -- "$@" || return case $prev in -h | --help) return ;; -o) - _filedir + _comp_compgen_filedir return ;; esac case $cur in - -pro=*) - cur="${cur#*=}" - _filedir + -pro=* | --profile=*) + _comp_compgen -c "${cur#*=}" filedir return ;; - -ole=*) - COMPREPLY=($(compgen -W 'dos win mac unix' -- "${cur#*=}")) + -ole=* | --output-line-ending=*) + _comp_compgen -c "${cur#*=}" -- -W 'dos win mac unix' return ;; - -bt=* | -pt=* | -sbt=* | -bvt=* | -pvt=* | -sbvt=* | -bvtc=* | -pvtc=* | -sbvtc=* | \ - -cti=* | -kbl=* | -vt=*) - COMPREPLY=($(compgen -W '0 1 2' -- "${cur#*=}")) + -bt=* | --brace-tightness=* | -pt=* | --paren-tightness=* | \ + -sbt=* | --square-bracket-tightness=* | \ + -bvt=* | --brace-vertical-tightness=* | \ + -pvt=* | --paren-vertical-tightness=* | \ + -sbvt=* | --square-bracket-vertical-tightness=* | \ + -bvtc=* | --brace-vertical-tightness-closing=* | \ + -pvtc=* | --paren-vertical-tightness-closing=* | \ + -sbvtc=* | --square-bracket-vertical-tightness-closing=* | \ + -cti=* | --closing-token-indentation=* | \ + -kbl=* | --keep-old-blank-lines=* | \ + -vt=* | --vertical-tightness=*) + _comp_compgen -c "${cur#*=}" -- -W '0 1 2' return ;; - -vtc=*) - COMPREPLY=($(compgen -W '0 1' -- "${cur#*=}")) + -vtc=* | --vertical-tightness-closing=*) + _comp_compgen -c "${cur#*=}" -- -W '0 1' return ;; - -cab=*) - COMPREPLY=($(compgen -W '0 1 2 3' -- "${cur#*=}")) + -cab=* | --comma-arrow-breakpoints=*) + _comp_compgen -c "${cur#*=}" -- -W '0 1 2 3' return ;; -*=) @@ -44,12 +52,12 @@ _perltidy() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - _filedir 'p[lm]|t' + _comp_compgen_filedir 'p[lm]|t' fi } && - complete -F _perltidy perltidy + complete -F _comp_cmd_perltidy perltidy # ex: filetype=sh diff --git a/completions/pgrep b/completions/pgrep index 62dbb65..d4402f5 100644 --- a/completions/pgrep +++ b/completions/pgrep @@ -1,62 +1,60 @@ # pgrep(1) and pkill(1) completion -*- shell-script -*- -_pgrep() +_comp_cmd_pgrep() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[cdgJMNstTzFGPuU]*)' + # shellcheck disable=SC2254 case $prev in - --delimiter | --pgroup | --session | --terminal | -!(-*)[cdgJMNstTz]) + --delimiter | --pgroup | --session | --terminal | -${noargopts}[cdgJMNstTz]) return ;; --signal) - _signals + _comp_compgen_signals return ;; - --pidfile | -!(-*)F) - _filedir + --pidfile | -${noargopts}F) + _comp_compgen_filedir return ;; - --group | -!(-*)G) - _gids + --group | -${noargopts}G) + _comp_compgen_gids return ;; -j) - COMPREPLY=($(compgen -W 'any none' -- "$cur")) + _comp_compgen -- -W 'any none' return ;; - --parent | --ns | -!(-*)P) - _pids + --parent | --ns | -${noargopts}P) + _comp_compgen_pids return ;; - --euid | --uid | -!(-*)[uU]) - _uids + --euid | --uid | -${noargopts}[uU]) + _comp_compgen_uids return ;; --nslist) - local prefix= - [[ $cur == *,* ]] && prefix="${cur%,*}," - COMPREPLY=( - $(IFS="$IFS," compgen -W '$($1 --help 2>&1 | - command sed -ne "s/^[[:space:]]*Available namespaces://p")' \ - -- "${cur##*,}")) - ((${#COMPREPLY[@]} == 1)) && COMPREPLY=(${COMPREPLY/#/$prefix}) + _comp_compgen -c "${cur##*,}" split -F $' \t\n,' -- "$( + "$1" --help 2>&1 | + command sed -ne 's/^[[:space:]]*Available namespaces://p' + )" && + _comp_delimited , -W '"${COMPREPLY[@]}"' return ;; esac if [[ $cur == -* ]]; then - local help=$(_parse_help "$1") - [[ $help ]] || help='$("$1" --usage 2>&1 | - command sed -e "s/\[-signal\]//" -e "s/\[-SIGNAL\]//" | - _parse_usage -)' - COMPREPLY=($(compgen -W "$help" -- "$cur")) - [[ $cword -eq 1 && $1 == *pkill ]] && _signals - + _comp_compgen_help || + _comp_compgen_usage - <<<"$("$1" --usage 2>&1 | + command sed -e "s/\[-signal\]//" -e "s/\[-SIGNAL\]//")" + [[ $cword -eq 1 && $1 == *pkill ]] && _comp_compgen -a signals - return fi - _pnames -s + _comp_compgen_pnames -s } && - complete -F _pgrep pgrep pkill + complete -F _comp_cmd_pgrep pgrep pkill # ex: filetype=sh diff --git a/completions/pidof b/completions/pidof index a11b432..d413d6f 100644 --- a/completions/pidof +++ b/completions/pidof @@ -1,27 +1,29 @@ # pidof(8) completion -*- shell-script -*- -_pidof() +_comp_cmd_pidof() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[o]*)' + # shellcheck disable=SC2254 case $prev in - --help | -V | --version | -!(-*)[hV]*) + --help | -V | --version | -${noargopts}[hV]*) return ;; - --omit-pid | -!(-*)o) - _pids + --omit-pid | -${noargopts}o) + _comp_compgen_pids return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - _pnames + _comp_compgen_pnames } && - complete -F _pidof pidof + complete -F _comp_cmd_pidof pidof # ex: filetype=sh diff --git a/completions/pine b/completions/pine index 319c8d5..6844db0 100644 --- a/completions/pine +++ b/completions/pine @@ -1,32 +1,32 @@ # pine/alpine completion -*- shell-script -*- -_pine() +_comp_cmd_pine() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -help | -d | -f | -c | -I | -n | -url | -copy_pinerc | -copy_abook) return ;; - -attach | -attachlist | -attach_and_delete | -p | -P | -pinerc | -passfile | -x) - _filedir + -attach | -attachlist | -attach_and_delete | -p | -P | -pinerc | \ + -passfile | -x) + _comp_compgen_filedir return ;; -sort) - COMPREPLY=($(compgen -W 'arrival subject threaded orderedsubject - date from size score to cc' -- "$cur")) + _comp_compgen -- -W 'arrival subject threaded orderedsubject date + from size score to cc' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur")) + _comp_compgen_help -- -h else - COMPREPLY=($(compgen -W '$(awk "{print \$1}" ~/.addressbook \ - 2>/dev/null)' -- "$cur")) + _comp_compgen_split -- "$(_comp_awk '{print $1}' ~/.addressbook 2>/dev/null)" fi } && - complete -F _pine pine alpine + complete -F _comp_cmd_pine pine alpine # ex: filetype=sh diff --git a/completions/ping b/completions/ping index 446f026..44c0888 100644 --- a/completions/ping +++ b/completions/ping @@ -1,9 +1,9 @@ # ping(8) completion -*- shell-script -*- -_ping() +_comp_cmd_ping() { - local cur prev words cword - _init_completion -n = || return + local cur prev words cword comp_args + _comp_initialize -n = -- "$@" || return local ipvx @@ -12,21 +12,21 @@ _ping() return ;; -*I) - _available_interfaces -a + _comp_compgen_available_interfaces -a return ;; -*M) # Path MTU strategy in Linux, mask|time in FreeBSD local opts="do want dont" [[ $OSTYPE == *bsd* ]] && opts="mask time" - COMPREPLY=($(compgen -W '$opts' -- "$cur")) + _comp_compgen -- -W '$opts' return ;; -*N) if [[ $cur != *= ]]; then - COMPREPLY=($(compgen -W 'name ipv6 ipv6-global ipv6-sitelocal + _comp_compgen -- -W 'name ipv6 ipv6-global ipv6-sitelocal ipv6-linklocal ipv6-all ipv4 ipv4-all subject-ipv6= - subject-ipv4= subject-name= subject-fqdn=' -- "$cur")) + subject-ipv4= subject-name= subject-fqdn=' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi return @@ -34,19 +34,19 @@ _ping() -*Q) # TOS in Linux, "somewhat quiet" (no args) in FreeBSD if [[ $OSTYPE != *bsd* ]]; then - COMPREPLY=($(compgen -W '{0..7}' -- "$cur")) + _comp_compgen -- -W '{0..7}' return fi ;; -*S) # Socket sndbuf in Linux, source IP in FreeBSD - [[ $OSTYPE == *bsd* ]] && _ip_addresses + [[ $OSTYPE == *bsd* ]] && _comp_compgen_ip_addresses return ;; -*T) # Timestamp option in Linux, TTL in FreeBSD [[ $OSTYPE == *bsd* ]] || - COMPREPLY=($(compgen -W 'tsonly tsandaddr' -- "$cur")) + _comp_compgen -- -W 'tsonly tsandaddr' return ;; -*4*) @@ -58,14 +58,14 @@ _ping() esac if [[ $cur == -* ]]; then - local opts=$(_parse_help "$1") - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage return fi [[ $1 == *6 ]] && ipvx=-6 - _known_hosts_real ${ipvx-} -- "$cur" + [[ $1 == *4 ]] && ipvx=-4 + _comp_compgen_known_hosts ${ipvx-} -- "$cur" } && - complete -F _ping ping ping6 + complete -F _comp_cmd_ping ping ping4 ping6 # ex: filetype=sh diff --git a/completions/pkg-config b/completions/pkg-config index b9db167..489f477 100644 --- a/completions/pkg-config +++ b/completions/pkg-config @@ -1,9 +1,9 @@ # bash completion for pkgconfig -*- shell-script -*- -_pkg_config() +_comp_cmd_pkg_config() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in --define-variable | --atleast-version | --atleast-pkgconfig-version | \ @@ -15,9 +15,9 @@ _pkg_config() local word for word in "${words[@]:1}"; do if [[ $word != -* ]]; then - COMPREPLY=($(compgen -W \ - '$("$1" $word --print-variables 2>/dev/null)' \ - -- "$cur")) + _comp_compgen_split -- "$( + "$1" "$word" --print-variables 2>/dev/null + )" break fi done @@ -29,17 +29,17 @@ _pkg_config() ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - COMPREPLY=($(compgen -W "$($1 --list-all \ - 2>/dev/null | awk '{print $1}')" -- "$cur")) - _filedir pc + _comp_compgen_split -- "$("$1" --list-all 2>/dev/null | + _comp_awk '{print $1}')" + _comp_compgen -a filedir pc fi } && - complete -F _pkg_config pkg-config + complete -F _comp_cmd_pkg_config pkg-config pkgconf # ex: filetype=sh diff --git a/completions/pkg-get b/completions/pkg-get index 72bd0a0..a8ec1a8 100644 --- a/completions/pkg-get +++ b/completions/pkg-get @@ -2,10 +2,10 @@ # # Copyright 2006 Yann Rouillard <yann@opencsw.org> -_pkg_get_get_catalog_file() +_comp_cmd_pkg_get__catalog_file() { local url="$1" - local catalog_file i conffile + local i conffile for file in /etc/opt/csw/pkg-get.conf /opt/csw/etc/pkg-get.conf /etc/pkg-get.conf; do if [[ -f $file ]]; then @@ -15,19 +15,17 @@ _pkg_get_get_catalog_file() done conffile="${conffile:-/opt/csw/etc/pkg-get.conf}" - if [[ -z $url ]]; then - url=$(awk -F= ' $1=="url" { print $2 }' $conffile) + if [[ ! $url ]]; then + url=$(_comp_awk -F = ' $1=="url" { print $2 }' "$conffile") fi - catalog_file="${url##*//}" - catalog_file="${catalog_file%%/*}" - catalog_file="/var/pkg-get/catalog-$catalog_file" - - echo "$catalog_file" + REPLY="${url##*//}" + REPLY="${REPLY%%/*}" + REPLY="/var/pkg-get/catalog-$REPLY" } && - _pkg_get() + _comp_cmd_pkg_get() { - local cur prev file catalog_file url command + local cur prev file url command="" COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD - 1]}" @@ -46,27 +44,29 @@ _pkg_get_get_catalog_file() fi done - if [[ -v command ]]; then + if [[ $command ]]; then if [[ $command == @(-[Ddi]|describe|download|install) ]]; then - catalog_file=$(_pkg_get_get_catalog_file "$url") - if [[ -f $catalog_file ]]; then - local packages_list=$(awk ' $0 ~ /BEGIN PGP SIGNATURE/ { exit } $1 ~ /^Hash:/ || $1 ~ /^ *(-|#|$)/ { next } { print $1 }' $catalog_file) - COMPREPLY=($(compgen -W "${packages_list}" -- ${cur})) + local REPLY + _comp_cmd_pkg_get__catalog_file "$url" + if [[ -f $REPLY ]]; then + local packages_list=$(_comp_awk '$0 ~ /BEGIN PGP SIGNATURE/ { exit } $1 ~ /^Hash:/ || $1 ~ /^ *(-|#|$)/ { next } { print $1 }' "$REPLY") + _comp_compgen -- -W "${packages_list}" fi fi return fi if [[ ${cur} == -* ]]; then - local opts="-c -d -D -f -i -l -s -S -u -U -v" - COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + local -a opts=(-c -d -D -f -i -l -s -S -u -U -v) + _comp_compgen -- -W '"${opts[@]}"' return fi - local commands="available describe download install list \ - updatecatalog upgrade" - COMPREPLY=($(compgen -W "${commands}" -- ${cur})) + local -a commands=( + available describe download install list updatecatalog upgrade + ) + _comp_compgen -- -W '"${commands[@]}"' } && - complete -F _pkg_get pkg-get + complete -F _comp_cmd_pkg_get pkg-get # ex: filetype=sh diff --git a/completions/pkg_delete b/completions/pkg_delete index 2abb671..aecc8e8 100644 --- a/completions/pkg_delete +++ b/completions/pkg_delete @@ -1,18 +1,19 @@ # bash completion for *BSD package management tools -*- shell-script -*- -_pkg_delete() +_comp_cmd_pkg_delete() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local pkgdir=${PKG_DBDIR:-/var/db/pkg}/ [[ $prev == -o || $prev == -p || $prev == -W ]] && return - COMPREPLY=($(compgen -d -- "$pkgdir$cur")) - ((${#COMPREPLY[@]} == 0)) || COMPREPLY=(${COMPREPLY[@]#$pkgdir}) + _comp_compgen -c "$pkgdir$cur" -- -d + ((${#COMPREPLY[@]} == 0)) || COMPREPLY=("${COMPREPLY[@]#"$pkgdir"}") } && - complete -F _pkg_delete -o dirnames pkg_delete pkg_info pkg_deinstall + complete -F _comp_cmd_pkg_delete -o dirnames \ + pkg_delete pkg_info pkg_deinstall # ex: filetype=sh diff --git a/completions/pkgadd b/completions/pkgadd index 3f5b6a1..bdb9c42 100644 --- a/completions/pkgadd +++ b/completions/pkgadd @@ -2,10 +2,10 @@ # # Copyright 2006 Yann Rouillard <yann@opencsw.org> -_pkgadd() +_comp_cmd_pkgadd() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return # if a device directory was given # we must complete with the package @@ -23,40 +23,39 @@ _pkgadd() case $prev in -d) - _filedir pkg - _filedir -d + _comp_compgen_filedir pkg ;; -a | -r | -V) - _filedir + _comp_compgen_filedir ;; -k | -s | -R) - _filedir -d + _comp_compgen_filedir -d ;; -P | -x) ;; *) if [[ ${cur} == -* ]]; then - local opts="-a -A -d -k -n -M -P -r -R -s -v -V -x" - COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + local -a opts=(-a -A -d -k -n -M -P -r -R -s -v -V -x) + _comp_compgen -- -W '"${opts[@]}"' else - local pkginst_list + local -a pkginst_list if [[ -d $device ]]; then - local -a tmplist - for filedir in $(/bin/ls -1 $device); do - if [[ -d "$device/$filedir" ]] && [[ -f "$device/$filedir/pkginfo" ]]; then - tmplist+=(${tmplist[@]:-} "$filedir") - fi - done - pkginst_list="${tmplist[*]}" + if _comp_expand_glob pkginst_list '"$device"/*/pkginfo'; then + pkginst_list=("${pkginst_list[@]#"$device/"}") + pkginst_list=("${pkginst_list[@]%/pkginfo}") + fi else - pkginst_list="$(strings "$(dequote $device)" | - command grep ^PKG= | sort -u | cut -d= -f2)" + local REPLY + _comp_dequote "$device" + _comp_split -l pkginst_list "$(strings "${REPLY-}" | + command sed -n 's/^PKG=//p' | sort -u)" fi - COMPREPLY=($(compgen -W "$pkginst_list" -- ${cur})) + ((${#pkginst_list[@]})) && + _comp_compgen -- -W '"${pkginst_list[@]}"' fi ;; esac } && - complete -F _pkgadd pkgadd + complete -F _comp_cmd_pkgadd pkgadd # ex: filetype=sh diff --git a/completions/pkgrm b/completions/pkgrm index 2449d34..bb5327e 100644 --- a/completions/pkgrm +++ b/completions/pkgrm @@ -1,11 +1,11 @@ -# pkgrm completion -*- shell-script -*- +# pkgrm completion -*- shell-script -*- # # Copyright 2006 Yann Rouillard <yann@opencsw.org> -_pkgrm() +_comp_cmd_pkgrm() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return # if a spool directory was given # we must complete with the package @@ -24,23 +24,23 @@ _pkgrm() case $prev in -a | -V) - _filedir + _comp_compgen_filedir ;; -s | -R) - _filedir -d + _comp_compgen_filedir -d ;; -Y) ;; *) if [[ ${cur} == -* ]]; then local opts="-a -A -n -M -R -s -v -V -Y" - COMPREPLY=($(compgen -W "${opts}" -- ${cur})) + _comp_compgen -- -W "${opts}" else - COMPREPLY=($(compgen -W "$(/bin/ls -1 $spool)" -- ${cur})) + _comp_compgen_split -- "$(/bin/ls -1 "$spool")" fi ;; esac } && - complete -F _pkgrm pkgrm + complete -F _comp_cmd_pkgrm pkgrm # ex: filetype=sh diff --git a/completions/pkgtool b/completions/pkgtool index 951bae4..faf0130 100644 --- a/completions/pkgtool +++ b/completions/pkgtool @@ -1,13 +1,13 @@ # Slackware Linux pkgtool completion -*- shell-script -*- -_pkgtool() +_comp_cmd_pkgtool() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case "$prev" in --source_dir | --target_dir) - _filedir -d + _comp_compgen_filedir -d return ;; --sets) @@ -15,21 +15,20 @@ _pkgtool() return ;; --source_device) - COMPREPLY=($(compgen -f -d -- "${cur:-/dev/}")) + _comp_compgen -c "${cur:-/dev/}" -- -f -d return ;; --tagfile) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--sets --ignore-tagfiles --tagfile - --source-mounted --source_dir --target_dir --source_device' \ - -- "$cur")) + _comp_compgen -- -W '--sets --ignore-tagfiles --tagfile + --source-mounted --source_dir --target_dir --source_device' fi } && - complete -F _pkgtool pkgtool + complete -F _comp_cmd_pkgtool pkgtool # ex: filetype=sh diff --git a/completions/pkgutil b/completions/pkgutil index 91d8748..63dc400 100644 --- a/completions/pkgutil +++ b/completions/pkgutil @@ -1,7 +1,7 @@ -# pkgutil completion -*- shell-script -*- +# pkgutil completion -*- shell-script -*- # Copyright 2006 Yann Rouillard <yann@opencsw.org> -_pkgutil_url2catalog() +_comp_cmd_pkgutil__url2catalog() { local filename="$1" @@ -9,44 +9,50 @@ _pkgutil_url2catalog() filename="${filename//\//_}" filename="/var/opt/csw/pkgutil/catalog.${filename}_$(uname -p)_$(uname -r)" - echo "$filename" + REPLY=$filename } -_pkgutil() +_comp_cmd_pkgutil() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return - local command catalog_files configuration_files - declare -a configuration_files=("/opt/csw/etc/pkgutil.conf" "/etc/opt/csw/pkgutil.conf") - declare -a catalog_files=() + local command="" catalog_files configuration_files + local -a configuration_files=( + "/opt/csw/etc/pkgutil.conf" "/etc/opt/csw/pkgutil.conf") + local -a catalog_files=() - local i=$cword + local i=$cword REPLY while ((i-- > 1)); do if [[ ${words[i]} == -@(t|-temp) ]]; then local url="${words[i + 1]}" - local catalog=$(_pkgutil_url2catalog "$url") - catalog_files=("$catalog") + _comp_cmd_pkgutil__url2catalog "$url" + catalog_files=("$REPLY") elif [[ ${words[i]} == --config ]]; then - configuration_files=("$(dequote ${words[i + 1]})") + local REPLY + _comp_dequote "${words[i + 1]}" + [[ ${REPLY-} ]] && configuration_files=("$REPLY") elif [[ ${words[i]} == -@([iurdacUS]|-install|-upgrade|-remove|-download|-available|-compare|-catalog|-stream) ]]; then command="${words[i]}" fi done if [[ $prev == -@([WPR]|-workdir|-pkgdir|-rootpath) ]]; then - _filedir -d + _comp_compgen_filedir -d return fi if [[ $prev == -@(o|-output|-config) ]]; then - _filedir + _comp_compgen_filedir return fi if [[ $prev == -@(p|-param) ]]; then compopt -o nospace - COMPREPLY=($(compgen -W "mirror: pkgaddopts: pkgrmopts: wgetopts: use_gpg: use_md5: pkgliststyle: maxpkglist: noncsw: stop_on_hook_soft_error: exclude_pattern: gpg_homedir: root_path: deptree_filter_common: show_current: catalog_not_cached: catalog_update:" -- $cur)) + _comp_compgen -- -W 'mirror: pkgaddopts: pkgrmopts: wgetopts: use_gpg: + use_md5: pkgliststyle: maxpkglist: noncsw: stop_on_hook_soft_error: + exclude_pattern: gpg_homedir: root_path: deptree_filter_common: + show_current: catalog_not_cached: catalog_update:' return fi @@ -55,7 +61,8 @@ _pkgutil() # as a separator, borrowed from maven completion code which borrowed # it from darcs completion code :) local colonprefixes=${cur%"${cur##*:}"} - COMPREPLY=($(compgen -W "sparc:5.9 sparc:5.10 sparc:5.11 i386:5.9 i386:5.10 i386:5.11" -- $cur)) + _comp_compgen -- -W 'sparc:5.9 sparc:5.10 sparc:5.11 i386:5.9 i386:5.10 + i386:5.11' local i=${#COMPREPLY[*]} while ((i-- > 0)); do COMPREPLY[i]=${COMPREPLY[i]#"$colonprefixes"} @@ -63,33 +70,42 @@ _pkgutil() return fi - if [[ -v command && $cur != -* ]]; then + if [[ $command && $cur != -* ]]; then local mirrors mirror_url - mirrors=$(awk -F= ' $1 ~ /^ *mirror *$/ { print $2 }' "${configuration_files[@]}") + mirrors=$(_comp_awk -F = ' $1 ~ /^ *mirror *$/ { print $2 }' "${configuration_files[@]}") mirrors=${mirrors:-http://mirror.opencsw.org/opencsw/testing} for mirror_url in $mirrors; do - local catalog=$(_pkgutil_url2catalog "$mirror_url") - catalog_files=("${catalog_files[@]}" "$catalog") + _comp_cmd_pkgutil__url2catalog "$mirror_url" + catalog_files+=("$REPLY") done if [[ $command == -@([dius]|-download|-install|-upgrade|-stream) ]]; then - local packages_list=$(awk ' $0 ~ /BEGIN PGP SIGNATURE/ { exit } $1 ~ /^Hash:/ || $1 ~ /^ *(-|#|$)/ { next } { print $1 }' "${catalog_files[@]}") - COMPREPLY=($(compgen -W "${packages_list}" -- $cur)) + local packages_list=$(_comp_awk ' $0 ~ /BEGIN PGP SIGNATURE/ { exit } $1 ~ /^Hash:/ || $1 ~ /^ *(-|#|$)/ { next } { print $1 }' "${catalog_files[@]}") + _comp_compgen -- -W "${packages_list}" elif [[ $command == @(-r|--remove) ]]; then - local packages_list=$(pkginfo | awk ' $2 ~ /^CSW/ { printf ("%s|",$2) }') + local packages_list=$( + pkginfo | _comp_awk ' $2 ~ /^CSW/ { printf ("%s|",$2) }' + ) packages_list=${packages_list%|} packages_list=$(nawk " \$3 ~ /^$packages_list\$/ { print \$1 }" "${catalog_files[@]}") - COMPREPLY=($(compgen -W "${packages_list}" -- $cur)) + _comp_compgen -- -W "${packages_list}" fi return fi - local commands="-i --install -u --upgrade -r --remove -d --download -U --catalog -a --available --describe -c --compare -C --compare-diff -A --compare-avail -e --email -t --temp -x --exclude -W --workdir -P --pkgdir -R --rootpath --config -y --yes -f --force -n --nomod -N --nodeps -D --debug --trace -h --help -v --version -V --syscheck -l --list -L --listfile -F --findfile --deptree --extract -s --stream -o --output -T --target --single -p --param --parse --cleanup --catinfo" - COMPREPLY=($(compgen -W "${commands}" -- $cur)) + local -a commands=( + --install --upgrade --remove --download --catalog --available + --describe --compare --compare-diff --compare-avail --email --temp + --exclude --workdir --pkgdir --rootpath --config --yes --force --nomod + --nodeps --debug --trace --help --version --syscheck --list --listfile + --findfile --deptree --extract --stream --output --target --single + --param --parse --cleanup --catinfo + ) + _comp_compgen -- -W '"${commands[@]}"' } && - complete -F _pkgutil pkgutil + complete -F _comp_cmd_pkgutil pkgutil # ex: filetype=sh diff --git a/completions/plague-client b/completions/plague-client index 4e98206..cec0b6c 100644 --- a/completions/plague-client +++ b/completions/plague-client @@ -1,14 +1,14 @@ # bash completion for plague-client -*- shell-script -*- -_plague_client() +_comp_cmd_plague_client() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return ((cword == 1)) && - COMPREPLY=($(compgen -W 'build detail finish help is_paused kill list - list_builders pause requeue unpause update_builders' -- "$cur")) + _comp_compgen -- -W 'build detail finish help is_paused kill list + list_builders pause requeue unpause update_builders' } && - complete -F _plague_client plague-client + complete -F _comp_cmd_plague_client plague-client # ex: filetype=sh diff --git a/completions/pm-hibernate b/completions/pm-hibernate index ea3b0aa..26c304b 100644 --- a/completions/pm-hibernate +++ b/completions/pm-hibernate @@ -1,12 +1,13 @@ # bash completion for pm-utils -*- shell-script -*- -_pm_action() +_comp_cmd_pm_hibernate() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - COMPREPLY=($(compgen -W "--help $(_parse_help "$1")" -- "$cur")) + _comp_compgen_help + _comp_compgen -a -- -W '--help' } && - complete -F _pm_action pm-hibernate pm-suspend pm-suspend-hybrid + complete -F _comp_cmd_pm_hibernate pm-hibernate pm-suspend pm-suspend-hybrid # ex: filetype=sh diff --git a/completions/pm-is-supported b/completions/pm-is-supported index adc7fde..f909fe4 100644 --- a/completions/pm-is-supported +++ b/completions/pm-is-supported @@ -1,13 +1,12 @@ # pm-is-supported(1) completion -*- shell-script -*- -_pm_is_supported() +_comp_cmd_pm_is_supported() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - COMPREPLY=($(compgen -W '--help --suspend --hibernate --suspend-hybrid' \ - -- "$cur")) + _comp_compgen -- -W '--help --suspend --hibernate --suspend-hybrid' } && - complete -F _pm_is_supported pm-is-supported + complete -F _comp_cmd_pm_is_supported pm-is-supported # ex: filetype=sh diff --git a/completions/pm-powersave b/completions/pm-powersave index affb195..0db0ddc 100644 --- a/completions/pm-powersave +++ b/completions/pm-powersave @@ -1,12 +1,12 @@ # pm-powersave(8) completion -*- shell-script -*- -_pm_powersave() +_comp_cmd_pm_powersave() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - COMPREPLY=($(compgen -W "true false" -- "$cur")) + _comp_compgen -- -W "true false" } && - complete -F _pm_powersave pm-powersave + complete -F _comp_cmd_pm_powersave pm-powersave # ex: filetype=sh diff --git a/completions/pngfix b/completions/pngfix index 64b5481..d77d80b 100644 --- a/completions/pngfix +++ b/completions/pngfix @@ -1,36 +1,35 @@ # pngfix completion -*- shell-script -*- -_pngfix() +_comp_cmd_pngfix() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in --suffix | --prefix) return ;; --output) - _filedir + _comp_compgen_filedir return ;; --strip) - COMPREPLY=($(IFS='|' compgen -W '$("$1" --help 2>&1 | - command sed -ne "s/.*--strip=\[\([^]]*\)\].*/\1/p")' \ - -- "$cur")) + _comp_compgen_split -F '|' -- "$("$1" --help 2>&1 | + command sed -ne 's/.*--strip=\[\([^]]*\)\].*/\1/p')" return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir png + _comp_compgen_filedir png } && - complete -F _pngfix pngfix + complete -F _comp_cmd_pngfix pngfix # ex: filetype=sh diff --git a/completions/portinstall b/completions/portinstall index 8033740..dc1a933 100644 --- a/completions/portinstall +++ b/completions/portinstall @@ -1,31 +1,28 @@ # bash completion for FreeBSD portinstall -*- shell-script -*- -_portinstall() +_comp_cmd_portinstall() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - local portsdir indexfile - local -a COMPREPLY2 + [[ $prev == -l || $prev == -L || $prev == -o ]] && return - portsdir=${PORTSDIR:-/usr/ports}/ + local -x portsdir=${PORTSDIR:-/usr/ports}/ # First try INDEX-5 - indexfile=$portsdir/INDEX-5 + local indexfile=$portsdir/INDEX-5 # Then INDEX if INDEX-5 does not exist or system is not FreeBSD 5.x [[ ${OSTYPE%.*} == freebsd5 && -f $indexfile ]] || indexfile=$portsdir/INDEX + [[ -f $indexfile && -r $indexfile ]] || return - [[ $prev == -l || $prev == -L || $prev == -o ]] && return - - COMPREPLY=($(command grep -E "^$cur" 2>/dev/null <$indexfile | - cut -d'|' -f1)) - COMPREPLY2=($(command grep -E "^[^\|]+\|$portsdir$cur" 2>/dev/null \ - <$indexfile | cut -d'|' -f2)) - COMPREPLY2=(${COMPREPLY2[@]#$portsdir}) - COMPREPLY+=("${COMPREPLY2[@]}") + _comp_compgen_split -l -- "$(_comp_awk -F '|' ' + BEGIN { portsdir = ENVIRON["portsdir"]; len = length(portsdir) } + { print $1 } + substr($2, 1, len) == portsdir { print substr($2, len + 1) } + ' "$indexfile")" } && - complete -F _portinstall -o dirnames portinstall + complete -F _comp_cmd_portinstall -o dirnames portinstall # ex: filetype=sh diff --git a/completions/portsnap b/completions/portsnap index a2f0a93..a5f880c 100644 --- a/completions/portsnap +++ b/completions/portsnap @@ -2,24 +2,24 @@ [[ $OSTYPE == *freebsd* ]] || return 1 -_portsnap() +_comp_cmd_portsnap() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -d | -p) - _filedir -d + _comp_compgen_filedir -d return ;; -l | -f) - _filedir + _comp_compgen_filedir return ;; esac - COMPREPLY=($(compgen -W "fetch cron extract update" -- $cur)) + _comp_compgen -- -W "fetch cron extract update" } && - complete -F _portsnap portsnap + complete -F _comp_cmd_portsnap portsnap # ex: filetype=sh diff --git a/completions/portupgrade b/completions/portupgrade index ffe6305..1dc93c2 100644 --- a/completions/portupgrade +++ b/completions/portupgrade @@ -1,19 +1,19 @@ # bash completion for FreeBSD portupgrade -*- shell-script -*- -_portupgrade() +_comp_cmd_portupgrade() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return [[ $prev == -l || $prev == -L || $prev == -o ]] && return local pkgdir=${PKG_DBDIR:-/var/db/pkg}/ - COMPREPLY=($(compgen -d -- "$pkgdir$cur")) - COMPREPLY=(${COMPREPLY[@]#$pkgdir}) - COMPREPLY=(${COMPREPLY[@]%-*}) + _comp_compgen -c "$pkgdir$cur" -- -d + COMPREPLY=("${COMPREPLY[@]#"$pkgdir"}") + COMPREPLY=("${COMPREPLY[@]%-*}") } && - complete -F _portupgrade -o dirnames portupgrade + complete -F _comp_cmd_portupgrade -o dirnames portupgrade # ex: filetype=sh diff --git a/completions/postcat b/completions/postcat index a58b0e5..ac74e80 100644 --- a/completions/postcat +++ b/completions/postcat @@ -1,39 +1,34 @@ # postcat(1) completion -*- shell-script -*- -_postcat() +_comp_cmd_postcat() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -c) - _filedir -d + _comp_compgen_filedir -d return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage return fi - local idx qfile=0 + local idx qfile="" for idx in "${words[@]}"; do - [[ $idx == -q ]] && qfile=1 && break + [[ $idx == -q ]] && qfile=set && break done - if ((qfile == 1)); then - local len=${#cur} pval - for pval in $(mailq 2>/dev/null | - command sed -e '1d; $d; /^[^0-9A-Z]/d; /^$/d; s/[* !].*$//'); do - if [[ $cur == "${pval:0:len}" ]]; then - COMPREPLY+=($pval) - fi - done + if [[ $qfile ]]; then + _comp_compgen_split -- "$(mailq 2>/dev/null | + command sed -e '1d; $d; /^[^0-9A-Z]/d; /^$/d; s/[* !].*$//')" return fi - _filedir + _comp_compgen_filedir } && - complete -F _postcat postcat + complete -F _comp_cmd_postcat postcat # ex: filetype=sh diff --git a/completions/postconf b/completions/postconf index 4cb324c..ac1b21b 100644 --- a/completions/postconf +++ b/completions/postconf @@ -1,19 +1,19 @@ # postconf(1) completion -*- shell-script -*- -_postconf() +_comp_cmd_postconf() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local eqext case $prev in -b | -t) - _filedir + _comp_compgen_filedir return ;; -c) - _filedir -d + _comp_compgen_filedir -d return ;; -e) @@ -23,7 +23,7 @@ _postconf() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage return fi @@ -34,6 +34,6 @@ _postconf() fi done } && - complete -F _postconf postconf + complete -F _comp_cmd_postconf postconf # ex: filetype=sh diff --git a/completions/postfix b/completions/postfix index f960550..a05f71f 100644 --- a/completions/postfix +++ b/completions/postfix @@ -1,33 +1,29 @@ # postfix(1) completion -*- shell-script -*- -_postfix() +_comp_cmd_postfix() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -c) - _filedir -d + _comp_compgen_filedir -d return ;; -D) - COMPREPLY=($(compgen -W 'start' -- "$cur")) + _comp_compgen -- -W 'start' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($( - compgen -W \ - '$(_bashcomp_try_faketty "$1" --help 2>&1 | _parse_usage -)' \ - -- "$cur" - )) + _comp_compgen_usage -c _comp_try_faketty "$1" --help return fi - COMPREPLY=($(compgen -W 'check start stop abort flush reload status - set-permissions upgrade-configuration' -- "$cur")) + _comp_compgen -- -W 'check start stop abort flush reload status + set-permissions upgrade-configuration' } && - complete -F _postfix postfix + complete -F _comp_cmd_postfix postfix # ex: filetype=sh diff --git a/completions/postmap b/completions/postmap index 35c4ada..48e5d9f 100644 --- a/completions/postmap +++ b/completions/postmap @@ -1,13 +1,13 @@ # postalias(1) and postmap(1) completion -*- shell-script -*- -_postmap() +_comp_cmd_postmap() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -c) - _filedir -d + _comp_compgen_filedir -d return ;; -[dq]) @@ -16,13 +16,13 @@ _postmap() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage return fi if [[ $cur == *:* ]]; then compopt -o filenames - COMPREPLY=($(compgen -f -- "${cur#*:}")) + _comp_compgen -c "${cur#*:}" -- -f else local len=${#cur} pval for pval in $(/usr/sbin/postconf -m 2>/dev/null); do @@ -32,10 +32,10 @@ _postmap() done if [[ ! ${COMPREPLY-} ]]; then compopt -o filenames - COMPREPLY=($(compgen -f -- "$cur")) + _comp_compgen -- -f fi fi } && - complete -F _postmap postmap postalias + complete -F _comp_cmd_postmap postmap postalias # ex: filetype=sh diff --git a/completions/postsuper b/completions/postsuper index 559449a..d195ac7 100644 --- a/completions/postsuper +++ b/completions/postsuper @@ -1,56 +1,40 @@ # postsuper(1) completion -*- shell-script -*- -_postsuper() +_comp_cmd_postsuper() { - local cur prev words cword - _init_completion || return - - local pval len + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -c) - _filedir -d + _comp_compgen_filedir -d return ;; -[dr]) - len=${#cur} - for pval in ALL $(mailq 2>/dev/null | - command sed -e '1d; $d; /^[^0-9A-Z]/d; /^$/d; s/[* !].*$//'); do - if [[ $cur == "${pval:0:len}" ]]; then - COMPREPLY+=($pval) - fi - done + _comp_compgen_split -- "ALL $(mailq 2>/dev/null | + command sed -e '1d; $d; /^[^0-9A-Z]/d; /^$/d; s/[* !].*$//')" return ;; -h) - len=${#cur} - for pval in ALL $(mailq 2>/dev/null | - command sed -e '1d; $d; /^[^0-9A-Z]/d; /^$/d; s/[* ].*$//; /!$/d'); do - if [[ $cur == "${pval:0:len}" ]]; then - COMPREPLY+=($pval) - fi - done + _comp_compgen_split -- "ALL $(mailq 2>/dev/null | + command sed \ + -e '1d; $d; /^[^0-9A-Z]/d; /^$/d; s/[* ].*$//; /!$/d')" return ;; -H) - len=${#cur} - for pval in ALL $(mailq 2>/dev/null | - command sed -e '1d; $d; /^[^0-9A-Z]/d; /^$/d; /^[0-9A-Z]*[* ]/d; s/!.*$//'); do - if [[ $cur == "${pval:0:len}" ]]; then - COMPREPLY+=($pval) - fi - done + _comp_compgen_split -- "ALL $(mailq 2>/dev/null | command sed \ + -e '1d; $d; /^[^0-9A-Z]/d; /^$/d; /^[0-9A-Z]*[* ]/d; s/!.*$//')" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - COMPREPLY=($(compgen -W 'hold incoming active deferred' -- "$cur")) + _comp_compgen -- -W 'hold incoming active deferred' } && - complete -F _postsuper postsuper + complete -F _comp_cmd_postsuper postsuper # ex: filetype=sh diff --git a/completions/povray b/completions/povray index 56dfd94..868ff3e 100644 --- a/completions/povray +++ b/completions/povray @@ -1,22 +1,22 @@ # povray completion -*- shell-script -*- # by "David Necas (Yeti)" <yeti@physics.muni.cz> -_povray() +_comp_cmd_povray() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local povcur=$cur pfx oext defoext defoext=png # default output extension, if cannot be determined FIXME - _expand || return + _comp_expand || return case $povcur in [-+]I*) - cur="${povcur#[-+]I}" # to confuse _filedir + cur="${povcur#[-+]I}" # to confuse _comp_compgen_filedir pfx="${povcur%"$cur"}" - _filedir pov - COMPREPLY=(${COMPREPLY[@]/#/$pfx}) + _comp_compgen_filedir pov && + _comp_compgen -Rv COMPREPLY -- -P "$pfx" -W '"${COMPREPLY[@]}"' return ;; [-+]O*) @@ -31,34 +31,35 @@ _povray() *) oext=$defoext ;; esac # complete filename corresponding to previously specified +I - COMPREPLY=($( - IFS=$'\n' - command grep '^[-+]I' <<<"${words[*]}" - )) - COMPREPLY=(${COMPREPLY[@]#[-+]I}) - COMPREPLY=(${COMPREPLY[@]/%.pov/.$oext}) - cur="${povcur#[-+]O}" # to confuse _filedir + _comp_compgen -Rv COMPREPLY -- -X '![-+]I*' -W '"${words[@]}"' + _comp_compgen -Rv COMPREPLY -- -X '' -W '"${COMPREPLY[@]#[-+]I}"' + local i + for i in "${!COMPREPLY[@]}"; do + COMPREPLY[i]=${COMPREPLY[i]/%.pov/".$oext"} + done + cur="${povcur#[-+]O}" # to confuse _comp_compgen_filedir pfx="${povcur%"$cur"}" - _filedir $oext - COMPREPLY=(${COMPREPLY[@]/#/$pfx}) + _comp_compgen -a filedir "$oext" + ((${#COMPREPLY[@]})) && + _comp_compgen -Rv COMPREPLY -- -P "$pfx" -W '"${COMPREPLY[@]}"' return ;; *.ini\[ | *.ini\[*[^]]) # sections in .ini files cur="${povcur#*\[}" pfx="${povcur%\["$cur"}" # prefix == filename - [[ -r $pfx ]] || return - COMPREPLY=($(command sed -e 's/^[[:space:]]*\[\('"$cur"'[^]]*\]\).*$/\1/' \ - -e 't' -e 'd' -- "$pfx")) - # to prevent [bar] expand to nothing. can be done more easily? - COMPREPLY=("${COMPREPLY[@]/#/${pfx}[}") + [[ -f $pfx && -r $pfx ]] || return + _comp_compgen_split -l -- "$(command sed -ne \ + 's/^[[:space:]]*\[\([^]]*\]\).*$/\1/p' -- "$pfx")" && + # to prevent [bar] expand to nothing. can be done more easily? + _comp_compgen -Rv COMPREPLY -- -P "${pfx}[" -W '"${COMPREPLY[@]}"' return ;; *) - _filedir '@(ini|pov)' + _comp_compgen_filedir '@(ini|pov)' return ;; esac } && - complete -F _povray povray xpovray spovray + complete -F _comp_cmd_povray povray xpovray spovray # ex: filetype=sh diff --git a/completions/prelink b/completions/prelink index 1c39611..51b1cd9 100644 --- a/completions/prelink +++ b/completions/prelink @@ -1,42 +1,42 @@ # prelink(8) completion -*- shell-script -*- -_prelink() +_comp_cmd_prelink() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -'?' | --help | --usage | -V | --version | -r | --reloc-only) return ;; -b | --black-list | --dynamic-linker | --undo-output) - _filedir + _comp_compgen_filedir return ;; -c | --config-file) - _filedir conf + _comp_compgen_filedir conf return ;; -C | --cache) - _filedir cache + _comp_compgen_filedir cache return ;; --ld-library-path) - _filedir -d + _comp_compgen_filedir -d return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir + _comp_compgen_filedir } && - complete -F _prelink prelink + complete -F _comp_cmd_prelink prelink # ex: filetype=sh diff --git a/completions/printenv b/completions/printenv index 3553e83..5bd565f 100644 --- a/completions/printenv +++ b/completions/printenv @@ -1,9 +1,9 @@ # printenv(1) completion -*- shell-script -*- -_printenv() +_comp_cmd_printenv() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --help | --version) @@ -12,12 +12,12 @@ _printenv() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - COMPREPLY=($(compgen -v -- "$cur")) + _comp_compgen -- -v } && - complete -F _printenv printenv + complete -F _comp_cmd_printenv printenv # ex: filetype=sh diff --git a/completions/protoc b/completions/protoc index fdd77be..ac93e1c 100644 --- a/completions/protoc +++ b/completions/protoc @@ -1,63 +1,58 @@ # protoc completion -*- shell-script -*- -_protoc() +_comp_cmd_protoc() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in --version | -h | --help | --encode | --decode) return ;; --descriptor_set_out) - _filedir + _comp_compgen_filedir return ;; --error_format) - COMPREPLY=($(compgen -W 'gcc msvs' -- "$cur")) + _comp_compgen -- -W 'gcc msvs' return ;; --plugin) - if [[ $cur != *=* ]]; then - compopt -o filenames - COMPREPLY=($(compgen -c -- "$cur")) - fi + [[ $cur == *=* ]] || _comp_compgen_commands return ;; --proto_path | --*_out) - _filedir -d + _comp_compgen_filedir -d return ;; esac - $split && return + [[ $was_split ]] && return case $cur in -o*) - cur=${cur:2} - _filedir - COMPREPLY=("${COMPREPLY[@]/#/-o}") + _comp_compgen -c "${cur:2}" filedir + ((${#COMPREPLY[@]})) && COMPREPLY=("${COMPREPLY[@]/#/-o}") return ;; -I*) - cur=${cur:2} - _filedir -d - COMPREPLY=("${COMPREPLY[@]/#/-I}") + _comp_compgen -c "${cur:2}" filedir -d + ((${#COMPREPLY[@]})) && COMPREPLY=("${COMPREPLY[@]/#/-I}") return ;; -*) - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help local i for i in "${!COMPREPLY[@]}"; do - [[ ${COMPREPLY[i]} == -oFILE ]] && unset 'COMPREPLY[i]' + [[ ${COMPREPLY[i]} == -oFILE ]] && unset -v 'COMPREPLY[i]' done [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return ;; esac - _filedir proto + _comp_compgen_filedir proto } && - complete -F _protoc protoc + complete -F _comp_cmd_protoc protoc # ex: filetype=sh diff --git a/completions/ps b/completions/ps new file mode 100644 index 0000000..e816355 --- /dev/null +++ b/completions/ps @@ -0,0 +1,70 @@ +# bash completion for ps(1) -*- shell-script -*- + +_comp_cmd_ps() +{ + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + + case $prev in + --help) + _comp_compgen -- -W 'simple list output threads misc all' + return + ;; + --info | V | --version) + return + ;; + -C) + _comp_compgen_pnames + return + ;; + -[Gg] | --[Gg]roup) + _comp_compgen -- -g + return + ;; + ?(-)p | [^-]*p | --pid) + _comp_compgen_pids + return + ;; + --ppid) + _comp_compgen_pids # TODO: Only pids with children? + return + ;; + ?(-)q | [^-]*q | --quick-pid) + _comp_compgen_pids + return + ;; + -s | --sid) + # TODO + return + ;; + ?(-)t | [^-]*t | --tty) + _comp_expand_glob COMPREPLY '/dev/tty*' && + _comp_compgen -- -W '"${COMPREPLY[@]}" "${COMPREPLY[@]#/dev/}"' + return + ;; + ?(-)U | [^-]*U | -u | --[Uu]ser) + _comp_compgen -- -u + return + ;; + --format | ?(-)[Oo] | [^-]*[Oo]) + # TODO: This doesn't work well when there are multiple options for + # the non-first item (similarly to useradd --groups and others). + local labels=$("$1" L | _comp_awk '{ print $1 }') + _comp_delimited , -W '$labels' + return + ;; + esac + + if [[ $cur == -* ]]; then + # sed: strip single char dashless ", x," that trip _comp_compgen_help + _comp_compgen_help - <<<"$({ + "$1" --help + "$1" --help all + } 2>/dev/null | + command sed -e "s/, [A-Za-z],/,/")" || + _comp_compgen_usage + fi +} && + complete -F _comp_cmd_ps ps + +# ex: filetype=sh diff --git a/completions/psql b/completions/psql index 4bc6049..b05b3a4 100644 --- a/completions/psql +++ b/completions/psql @@ -1,97 +1,104 @@ # bash completion for Postgresql -*- shell-script -*- -_pg_databases() +_comp_cmd_psql__databases() { # -w was introduced in 8.4, https://launchpad.net/bugs/164772 # "Access privileges" in output may contain linefeeds, hence the NF > 1 - COMPREPLY=($(compgen -W "$(psql -XAtqwlF $'\t' 2>/dev/null | - awk 'NF > 1 { print $1 }')" -- "$cur")) + _comp_compgen_split -- "$(psql -XAtqwlF $'\t' 2>/dev/null | + _comp_awk 'NF > 1 { print $1 }')" } -_pg_users() +_comp_cmd_psql__users() { # -w was introduced in 8.4, https://launchpad.net/bugs/164772 - COMPREPLY=($(compgen -W "$(psql -XAtqwc 'select usename from pg_user' \ - template1 2>/dev/null)" -- "$cur")) - ((${#COMPREPLY[@]} == 0)) && COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen_split -- "$(psql -XAtqwc 'select usename from pg_user' \ + template1 2>/dev/null)" || + _comp_compgen -- -u } # createdb(1) completion # -_createdb() +_comp_cmd_createdb() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[hUOpDET]*)' + # shellcheck disable=SC2254 case $prev in - --host | -!(-*)h) - _known_hosts_real -- "$cur" + --host | -${noargopts}h) + _comp_compgen_known_hosts -- "$cur" return ;; - --username | --owner | -!(-*)[UO]) - _pg_users + --username | --owner | -${noargopts}[UO]) + _comp_cmd_psql__users return ;; - --help | --version | --port | --tablespace | --encoding | --template | -!(-*)[pDET]) + --help | --version | --port | --tablespace | --encoding | --template | \ + -${noargopts}[pDET]) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - _pg_databases + _comp_cmd_psql__databases fi } && - complete -F _createdb createdb + complete -F _comp_cmd_createdb createdb # createuser(1) completion # -_createuser() +_comp_cmd_createuser() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[pchU]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | --port | --connection-limit | -!(-*)[pc]) + --help | --version | --port | --connection-limit | -${noargopts}[pc]) return ;; - --host | -!(-*)h) - _known_hosts_real -- "$cur" + --host | -${noargopts}h) + _comp_compgen_known_hosts -- "$cur" return ;; - --username | -!(-*)U) - _pg_users + --username | -${noargopts}U) + _comp_cmd_psql__users return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _createuser createuser + complete -F _comp_cmd_createuser createuser # dropdb(1) completion # -_dropdb() +_comp_cmd_dropdb() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[hU]*)' + # shellcheck disable=SC2254 case $prev in - --host | -!(-*)h) - _known_hosts_real -- "$cur" + --host | -${noargopts}h) + _comp_compgen_known_hosts -- "$cur" return ;; - --username | -!(-*)U) - _pg_users + --username | -${noargopts}U) + _comp_cmd_psql__users return ;; --help | --version) @@ -99,90 +106,95 @@ _dropdb() ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - _pg_databases + _comp_cmd_psql__databases fi } && - complete -F _dropdb dropdb + complete -F _comp_cmd_dropdb dropdb # dropuser(1) completion # -_dropuser() +_comp_cmd_dropuser() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[phU]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | --port | -!(-*)p) + --help | --version | --port | -${noargopts}p) return ;; - --host | -!(-*)h) - _known_hosts_real -- "$cur" + --host | -${noargopts}h) + _comp_compgen_known_hosts -- "$cur" return ;; - --username | -!(-*)U) - _pg_users + --username | -${noargopts}U) + _comp_cmd_psql__users return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - _pg_users + _comp_cmd_psql__users fi } && - complete -F _dropuser dropuser + complete -F _comp_cmd_dropuser dropuser # psql(1) completion # -_psql() +_comp_cmd_psql() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[hUdofLcFpPRTv]*)' + # shellcheck disable=SC2254 case $prev in - --host | -!(-*)h) - _known_hosts_real -- "$cur" + --host | -${noargopts}h) + _comp_compgen_known_hosts -- "$cur" return ;; - --username | -!(-*)U) - _pg_users + --username | -${noargopts}U) + _comp_cmd_psql__users return ;; - --dbname | -!(-*)d) - _pg_databases + --dbname | -${noargopts}d) + _comp_cmd_psql__databases return ;; - --output | --file | --log-file | -!(-*)[ofL]) - _filedir + --output | --file | --log-file | -${noargopts}[ofL]) + _comp_compgen_filedir return ;; --help | --version | --command | --field-separator | --port | --pset | \ - --record-separator | --table-attr | --set | --variable | -!(-*)[?VcFpPRTv]) + --record-separator | --table-attr | --set | --variable | \ + -${noargopts}[?VcFpPRTv]) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then # return list of available options - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else # return list of available databases - _pg_databases + _comp_cmd_psql__databases fi } && - complete -F _psql psql + complete -F _comp_cmd_psql psql # ex: filetype=sh diff --git a/completions/puppet b/completions/puppet index e8767de..3a8f585 100644 --- a/completions/puppet +++ b/completions/puppet @@ -1,64 +1,70 @@ # bash completion for puppet -*- shell-script -*- -_puppet_logdest() +_comp_cmd_puppet__logdest() { - if [[ -z $cur ]]; then - COMPREPLY=($(compgen -W 'syslog console /' -- "$cur")) + if [[ ! $cur ]]; then + _comp_compgen -- -W 'syslog console /' else - COMPREPLY=($(compgen -W 'syslog console' -- "$cur")) - _filedir + _comp_compgen -- -W 'syslog console' + _comp_compgen -a filedir fi } -_puppet_digest() +_comp_cmd_puppet__digest() { - COMPREPLY=($(compgen -W 'MD5 MD2 SHA1 SHA256' -- "$cur")) + _comp_compgen -- -W 'MD5 MD2 SHA1 SHA256' } -_puppet_certs() +_comp_cmd_puppet__certs() { local puppetca="puppet cert" PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin type puppetca &>/dev/null && puppetca=puppetca if [[ $1 == --all ]]; then - cert_list=$($puppetca --list --all | command sed -e 's/^[+-]\{0,1\}\s*\(\S\+\)\s\+.*$/\1/') + cert_list=$( + $puppetca --list --all | + command sed -e 's/^[+-]\{0,1\}[[:space:]]*\([^[:space:]]\{1,\}\)[[:space:]]\{1,\}.*$/\1/' + ) else - cert_list=$($puppetca --list) + cert_list=$("$puppetca" --list) fi - COMPREPLY+=($(compgen -W "$cert_list" -- "$cur")) + _comp_compgen -a -- -W "$cert_list" } -_puppet_types() +_comp_cmd_puppet__types() { - puppet_types=$(puppet describe --list | command sed -e 's/^\(\S\{1,\}\).*$/\1/') - COMPREPLY+=($(compgen -W "$puppet_types" -- "$cur")) + puppet_types=$( + puppet describe --list | command sed -e 's/^\([^[:space:]]\{1,\}\).*$/\1/' + ) + _comp_compgen -a -- -W "$puppet_types" } -_puppet_references() +_comp_cmd_puppet__references() { local puppetdoc="puppet doc" PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin type puppetdoc &>/dev/null && puppetdoc=puppetdoc - puppet_doc_list=$($puppetdoc --list | command sed -e 's/^\(\S\{1,\}\).*$/\1/') - COMPREPLY+=($(compgen -W "$puppet_doc_list" -- "$cur")) + puppet_doc_list=$( + $puppetdoc --list | command sed -e 's/^\([^[:space:]]\{1,\}\).*$/\1/' + ) + _comp_compgen -a -- -W "$puppet_doc_list" } -_puppet_subcmd_opts() +_comp_cmd_puppet__subcmd_opts() { # puppet cmd help is somewhat slow, avoid if possible - [[ -z $cur || $cur == -* ]] && - COMPREPLY+=($(compgen -W \ - '$(_parse_usage "$1" "help $2")' -- "$cur")) + [[ ! $cur || $cur == -* ]] && + _comp_compgen -a usage -- help ${2:+"$2"} } -_puppet() +_comp_cmd_puppet() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - local subcommand action + local subcommand="" action case $prev in -h | --help | -V | --version) @@ -96,16 +102,16 @@ _puppet() ;; puppet) case ${words[1]} in - agent | apply | cert | describe | doc | filebucket | kick | master | parser | queue | resource) + agent | apply | cert | describe | doc | filebucket | kick | \ + master | parser | queue | resource) subcommand=${words[1]} ;; *.pp | *.rb) subcommand=apply ;; *) - COMPREPLY=($(compgen -W 'agent apply cert describe doc - filebucket kick master parser queue resource' \ - -- "$cur")) + _comp_compgen -- -W 'agent apply cert describe doc + filebucket kick master parser queue resource' return ;; esac @@ -116,33 +122,34 @@ _puppet() agent) case $prev in --certname) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; --digest) - _puppet_digest + _comp_cmd_puppet__digest return ;; --fqdn) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -l | --logdest) - _puppet_logdest + _comp_cmd_puppet__logdest return ;; --masterport) - COMPREPLY=($(compgen -W '8140' -- "$cur")) + _comp_compgen -- -W '8140' return ;; -w | --waitforcert) - COMPREPLY=($(compgen -W '0 15 30 60 120' -- "$cur")) + _comp_compgen -- -W '0 15 30 60 120' return ;; *) - _puppet_subcmd_opts "$1" $subcommand - # _parse_usage doesn't grok [-D|--daemonize|--no-daemonize] - COMPREPLY+=($(compgen -W '--no-daemonize' -- "$cur")) + _comp_cmd_puppet__subcmd_opts "$1" "$subcommand" + # _comp_compgen_usage doesn't grok + # [-D|--daemonize|--no-daemonize] + _comp_compgen -a -- -W '--no-daemonize' return ;; esac @@ -150,22 +157,22 @@ _puppet() apply) case $prev in --catalog) - COMPREPLY=($(compgen -W '-' -- "$cur")) - _filedir json + _comp_compgen -- -W '-' + _comp_compgen -a filedir json return ;; --execute) return ;; -l | --logdest) - _puppet_logdest + _comp_cmd_puppet__logdest return ;; *) if [[ $cur == -* ]]; then - _puppet_subcmd_opts "$1" $subcommand + _comp_cmd_puppet__subcmd_opts "$1" "$subcommand" else - _filedir + _comp_compgen_filedir fi return ;; @@ -174,35 +181,36 @@ _puppet() cert) case $prev in --digest) - _puppet_digest + _comp_cmd_puppet__digest return ;; *) action=$prev - COMPREPLY=($(compgen -W '--digest --debug --help --verbose --version' \ - -- "$cur")) + _comp_compgen -- -W '--digest --debug --help --verbose + --version' case $action in - fingerprint | list | verify | --fingerprint | --list | --verify) - COMPREPLY+=($(compgen -W '--all' -- "$cur")) - _puppet_certs --all + fingerprint | list | verify | --fingerprint | --list | \ + --verify) + _comp_compgen -a -- -W '--all' + _comp_cmd_puppet__certs --all return ;; generate | --generate) - _known_hosts_real -- "$cur" + _comp_compgen -a known_hosts -- "$cur" return ;; clean | print | revoke | --clean | --print | --revoke) - _puppet_certs --all + _comp_cmd_puppet__certs --all return ;; sign | --sign) - COMPREPLY+=($(compgen -W '--all' -- "$cur")) - _puppet_certs + _comp_compgen -a -- -W '--all' + _comp_cmd_puppet__certs return ;; *) - COMPREPLY+=($(compgen -W 'clean fingerprint generate - list print revoke sign verify reinventory' -- "$cur")) + _comp_compgen -a -- -W 'clean fingerprint generate + list print revoke sign verify reinventory' return ;; esac @@ -210,31 +218,31 @@ _puppet() esac ;; describe) - _puppet_subcmd_opts "$1" $subcommand + _comp_cmd_puppet__subcmd_opts "$1" "$subcommand" if [[ $cur != -* ]]; then - _puppet_types + _comp_cmd_puppet__types fi return ;; doc) case $prev in -o | --outputdir) - _filedir -d + _comp_compgen_filedir -d return ;; -m | --mode) - COMPREPLY=($(compgen -W 'text trac pdf rdoc' -- "$cur")) + _comp_compgen -- -W 'text trac pdf rdoc' return ;; -r | --reference) - _puppet_references + _comp_cmd_puppet__references return ;; *) if [[ $cur == -* ]]; then - _puppet_subcmd_opts "$1" $subcommand + _comp_cmd_puppet__subcmd_opts "$1" "$subcommand" else - _filedir + _comp_compgen_filedir fi return ;; @@ -243,20 +251,19 @@ _puppet() filebucket) case $prev in -s | --server) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -b | --bucket) - _filedir -d + _comp_compgen_filedir -d return ;; *) if [[ $cur == -* ]]; then - _puppet_subcmd_opts "$1" $subcommand + _comp_cmd_puppet__subcmd_opts "$1" "$subcommand" else - COMPREPLY=($(compgen -W 'backup get restore' \ - -- "$cur")) - _filedir + _comp_compgen -- -W 'backup get restore' + _comp_compgen -a filedir fi return ;; @@ -268,7 +275,7 @@ _puppet() return ;; --host) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -t | --tag) @@ -276,9 +283,9 @@ _puppet() ;; *) if [[ $cur == -* ]]; then - _puppet_subcmd_opts "$1" $subcommand + _comp_cmd_puppet__subcmd_opts "$1" "$subcommand" else - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" fi return ;; @@ -287,13 +294,14 @@ _puppet() master) case $prev in -l | --logdest) - _puppet_logdest + _comp_cmd_puppet__logdest return ;; *) - _puppet_subcmd_opts "$1" $subcommand - # _parse_usage doesn't grok [-D|--daemonize|--no-daemonize] - COMPREPLY+=($(compgen -W '--no-daemonize' -- "$cur")) + _comp_cmd_puppet__subcmd_opts "$1" "$subcommand" + # _comp_compgen_usage doesn't grok + # [-D|--daemonize|--no-daemonize] + _comp_compgen -a -- -W '--no-daemonize' return ;; esac @@ -302,11 +310,11 @@ _puppet() action=$prev case $action in validate) - _filedir pp + _comp_compgen_filedir pp return ;; *) - COMPREPLY=($(compgen -W 'validate' -- "$cur")) + _comp_compgen -- -W 'validate' return ;; esac @@ -314,25 +322,26 @@ _puppet() queue) case $prev in -l | --logdest) - _puppet_logdest + _comp_cmd_puppet__logdest return ;; *) if [[ $cur == -* ]]; then - _puppet_subcmd_opts "$1" $subcommand + _comp_cmd_puppet__subcmd_opts "$1" "$subcommand" else - _filedir + _comp_compgen_filedir fi return ;; esac ;; resource | *) - _puppet_subcmd_opts "$1" $subcommand + _comp_cmd_puppet__subcmd_opts "$1" ${subcommand:+"$subcommand"} return ;; esac } && - complete -F _puppet puppetmasterd puppetd puppetca ralsh puppetrun puppetqd filebucket puppetdoc puppet + complete -F _comp_cmd_puppet puppetmasterd puppetd puppetca ralsh \ + puppetrun puppetqd filebucket puppetdoc puppet # ex: filetype=sh diff --git a/completions/pv b/completions/pv index 99933f2..ab3f070 100644 --- a/completions/pv +++ b/completions/pv @@ -1,31 +1,34 @@ # pv(1) completion -*- shell-script -*- -_pv() +_comp_cmd_pv() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[VAFDiwHNLBRPd]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | --last-written | --format | --delay-start | --interval | \ - --width | --height | --name | --rate-limit | --buffer-size | -!(-*)[hVAFDiwHNLB]) + --help | --version | --last-written | --format | --delay-start | \ + --interval | --width | --height | --name | --rate-limit | \ + --buffer-size | -${noargopts}[hVAFDiwHNLB]) return ;; - --remote | -!(-*)R) - _pids + --remote | -${noargopts}R) + _comp_compgen_pids return ;; - --pidfile | --watchfd | -!(-*)[Pd]) - _filedir pid + --pidfile | --watchfd | -${noargopts}[Pd]) + _comp_compgen_filedir pid return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help else - _filedir + _comp_compgen_filedir fi } && - complete -F _pv pv + complete -F _comp_cmd_pv pv # ex: filetype=sh diff --git a/completions/pwck b/completions/pwck index fa07b0e..3e74ea5 100644 --- a/completions/pwck +++ b/completions/pwck @@ -1,18 +1,17 @@ # pwck(8) completion -*- shell-script -*- -_pwck() +_comp_cmd_pwck() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - local opts=$(_parse_help "$1") - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage return fi - _filedir + _comp_compgen_filedir } && - complete -F _pwck pwck + complete -F _comp_cmd_pwck pwck # ex: filetype=sh diff --git a/completions/pwd b/completions/pwd index b9c4fbc..159dacc 100644 --- a/completions/pwd +++ b/completions/pwd @@ -1,9 +1,9 @@ # pwd(1) completion -*- shell-script -*- -_pwd() +_comp_cmd_pwd() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --help | --version) @@ -11,10 +11,8 @@ _pwd() ;; esac - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) - [[ ${COMPREPLY-} ]] || - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage -c help -s "$1" } && - complete -F _pwd pwd + complete -F _comp_cmd_pwd pwd # ex: filetype=sh diff --git a/completions/pwdx b/completions/pwdx index 25a1a1e..ba460f2 100644 --- a/completions/pwdx +++ b/completions/pwdx @@ -1,9 +1,9 @@ # pwdx(1) completion -*- shell-script -*- -_pwdx() +_comp_cmd_pwdx() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -h | --help | -V | --version) @@ -12,13 +12,12 @@ _pwdx() esac if [[ $cur == -* ]]; then - local help='$(_parse_help "$1")' - [[ $help ]] || help=-V - COMPREPLY=($(compgen -W "$help" -- "$cur")) + _comp_compgen_help || + _comp_compgen -- -W '-V' else - _pids + _comp_compgen_pids fi } && - complete -F _pwdx pwdx + complete -F _comp_cmd_pwdx pwdx # ex: filetype=sh diff --git a/completions/pwgen b/completions/pwgen index 50d31d5..515ef1c 100644 --- a/completions/pwgen +++ b/completions/pwgen @@ -1,28 +1,30 @@ # pwgen(1) completion -*- shell-script -*- -_pwgen() +_comp_cmd_pwgen() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[NH]*)' + # shellcheck disable=SC2254 case $prev in - --num-passwords | --help | -!(-*)[Nh]) + --num-passwords | --help | -${noargopts}[Nh]) return ;; - --sha1 | -!(-*)H) - _filedir + --sha1 | -${noargopts}H) + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi } && - complete -F _pwgen pwgen + complete -F _comp_cmd_pwgen pwgen # ex: filetype=sh diff --git a/completions/pycodestyle b/completions/pycodestyle index dec6f37..c8912bb 100644 --- a/completions/pycodestyle +++ b/completions/pycodestyle @@ -1,34 +1,34 @@ # pycodestyle completion -*- shell-script -*- -_pycodestyle() +_comp_cmd_pycodestyle() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -h | --help | --version) return ;; --format) - COMPREPLY=($(compgen -W 'default pylint' -- "$cur")) + _comp_compgen -- -W 'default pylint' return ;; --config) - _filedir + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir py + _comp_compgen_filedir py } && - complete -F _pycodestyle pycodestyle + complete -F _comp_cmd_pycodestyle pycodestyle # ex: filetype=sh diff --git a/completions/pydoc b/completions/pydoc index e7b1178..2cf2987 100644 --- a/completions/pydoc +++ b/completions/pydoc @@ -1,42 +1,41 @@ # pydoc completion -*- shell-script -*- -_pydoc() +_comp_cmd_pydoc() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -k | -p) return ;; -w) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W \ - '$("$1" | command sed -e "s/^pydoc3\{0,1\} //" | _parse_help -)' \ - -- "$cur")) + _comp_compgen_help - <<<"$("$1" | command sed -e "s/^pydoc3\{0,1\} //")" return fi - COMPREPLY=($(compgen -W 'keywords topics modules' -- "$cur")) + _comp_compgen -- -W 'keywords topics modules' - if [[ $cur != @(.|*/)* ]]; then - local python=python - [[ ${1##*/} == *3* ]] && python=python3 - _xfunc python _python_modules $python + if ! _comp_looks_like_path "$cur"; then + # Prefer python in the same dir for resolving modules + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen -ax python modules fi # Note that we don't do "pydoc modules" as it is known to hang on - # some systems; _python_modules tends to work better and faster. - COMPREPLY+=($(compgen -W \ - '$($1 keywords topics | command sed -e /^Here/d)' -- "$cur")) + # some systems; _comp_xfunc_python_modules tends to work better and faster. + _comp_compgen -a split -- "$("$1" keywords topics | + command sed -e '/^Here/d')" - _filedir py + _comp_compgen -a filedir py } && - complete -F _pydoc pydoc pydoc3 + complete -F _comp_cmd_pydoc pydoc pydoc3 # ex: filetype=sh diff --git a/completions/pydocstyle b/completions/pydocstyle index acbf1ec..53f5690 100644 --- a/completions/pydocstyle +++ b/completions/pydocstyle @@ -1,35 +1,35 @@ # bash completion for pydocstyle -*- shell-script -*- -_pydocstyle() +_comp_cmd_pydocstyle() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in - --help | --version | --match | --ignore-decorators | --select | --ignore | \ - --add-select | --add-ignore | -!(-*)h) + --help | --version | --match | --ignore-decorators | --select | \ + --ignore | --add-select | --add-ignore | -!(-*)h) return ;; --config) - _filedir xml + _comp_compgen_filedir xml return ;; --convention) - COMPREPLY=($(compgen -W "pep257 numpy" -- "$cur")) + _comp_compgen -- -W "pep257 numpy" return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir py + _comp_compgen_filedir py } && - complete -F _pydocstyle pydocstyle + complete -F _comp_cmd_pydocstyle pydocstyle # ex: filetype=sh diff --git a/completions/pyflakes b/completions/pyflakes index 0a4e977..a53904e 100644 --- a/completions/pyflakes +++ b/completions/pyflakes @@ -1,9 +1,9 @@ # pyflakes(1) completion -*- shell-script -*- -_pyflakes() +_comp_cmd_pyflakes() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -h | --help | --version) @@ -12,12 +12,12 @@ _pyflakes() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - _filedir py + _comp_compgen_filedir py } && - complete -F _pyflakes pyflakes + complete -F _comp_cmd_pyflakes pyflakes # ex: filetype=sh diff --git a/completions/pylint b/completions/pylint index 8726f8b..84976d9 100644 --- a/completions/pylint +++ b/completions/pylint @@ -1,87 +1,119 @@ # pylint(1) completion -*- shell-script -*- -_pylint() +_comp_cmd_pylint__message_ids() { - local cur prev words cword split - _init_completion -s || return + local filter=p + [[ ${2-} ]] && filter="/^$2 messages/,/^$/p" + # 6: arbitrary, assumed no ids shorter than that + # TODO(scop): The fallback here is slow, maybe memoize whether + # --list-msgs-enabled worked (>= 2.4.0) and avoid unnecessary tries + # again later? + local msgs="$( + set -o pipefail + "$1" --list-msgs-enabled 2>/dev/null | + command sed -ne "$filter" | + command sed -ne 's/^[[:space:]]\{1,\}\([a-z-]\{6,\}\).*/\1/p' || + "$1" --list-msgs 2>/dev/null | + command sed -ne 's/^:\([a-z-]\{6,\}\).*/\1/p' + )" + _comp_delimited , -W "$msgs" +} + +_comp_cmd_pylint() +{ + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return local python=python [[ ${1##*/} == *3* ]] && python=python3 + local noargopts='!(-*|*[edisrjf]*)' + # shellcheck disable=SC2254 case $prev in - --version | --help | --long-help | --help-msg | --init-hook | --ignore | --enable | \ - --evaluation | --max-line-length | --max-module-lines | \ - --indent-string | --min-similarity-lines | --max-args | \ - --ignored-argument-names | --max-locals | --max-returns | --max-branchs | \ - --max-statements | --max-parents | --max-attributes | --min-public-methods | \ - --max-public-methods | --required-attributes | --bad-functions | \ - --module-rgx | --const-rgx | --class-rgx | --function-rgx | --method-rgx | \ - --attr-rgx | --argument-rgx | --variable-rgx | --inlinevar-rgx | --good-names | \ - --bad-names | --no-docstring-rgx | --dummy-variables-rgx | \ - --additional-builtins | --notes | --ignored-classes | --generated-members | \ + --version | --help | --long-help | --init-hook | \ + --ignore | --evaluation | --max-line-length | \ + --max-module-lines | --indent-string | --min-similarity-lines | \ + --max-args | --ignored-argument-names | --max-locals | \ + --max-returns | --max-branches | --max-statements | --max-parents | \ + --max-attributes | --min-public-methods | --max-public-methods | \ + --required-attributes | --bad-functions | --module-rgx | \ + --const-rgx | --class-rgx | --function-rgx | --method-rgx | \ + --attr-rgx | --argument-rgx | --variable-rgx | --inlinevar-rgx | \ + --good-names | --bad-names | --no-docstring-rgx | \ + --dummy-variables-rgx | --additional-builtins | --notes | \ + --ignored-classes | --generated-members | \ --overgeneral-exceptions | --ignore-iface-methods | \ --defining-attr-methods | --valid-classmethod-first-arg | \ - --valid-metaclass-classmethod-first-arg | -!(-*)[he]) + --valid-metaclass-classmethod-first-arg | -${noargopts}[h]) + return + ;; + --fail-on | --help-msg) + _comp_cmd_pylint__message_ids "$1" return ;; - --disable | -!(-*)d) - COMPREPLY=($(compgen -W 'all' -- "$cur")) + --enable | -${noargopts}e) + _comp_cmd_pylint__message_ids "$1" Disabled + return + ;; + --disable | -${noargopts}d) + _comp_cmd_pylint__message_ids "$1" Enabled + _comp_compgen -a -- -W 'all' return ;; --rcfile) - _filedir + _comp_compgen_filedir return ;; - --persistent | --include-ids | --symbols | --files-output | --reports | \ - --comment | --ignore-comments | --ignore-docstrings | --ignore-imports | \ - --init-import | --ignore-mixin-members | --zope | --suggestion-mode | \ - -!(-*)[isr]) - COMPREPLY=($(compgen -W 'yes no' -- "$cur")) + --persistent | --include-ids | --symbols | --files-output | \ + --reports | --comment | --ignore-comments | --ignore-docstrings | \ + --ignore-imports | --init-import | --ignore-mixin-members | \ + --zope | --suggestion-mode | -${noargopts}[isr]) + _comp_compgen -- -W 'yes no' return ;; --load-plugins | --deprecated-modules) - local prefix= - [[ $cur == *,* ]] && prefix="${cur%,*}," - cur="${cur##*,}" - _xfunc python _python_modules $python - ((${#COMPREPLY[@]} == 1)) && COMPREPLY=(${COMPREPLY/#/$prefix}) + _comp_compgen -c "${cur##*,}" -x python modules $python + ((${#COMPREPLY[@]})) && + _comp_delimited , -W '"${COMPREPLY[@]}"' return ;; - --jobs | -!(-*)j) - COMPREPLY=($(compgen -W "{1..$(_ncpus)}" -- "$cur")) + --jobs | -${noargopts}j) + local REPLY + _comp_get_ncpus + _comp_compgen -- -W "{1..$REPLY}" return ;; --confidence) local prefix= [[ $cur == *,* ]] && prefix="${cur%,*}," - COMPREPLY=($(compgen -W "HIGH INFERENCE INFERENCE_FAILURE - UNDEFINED" -- "${cur##*,}")) - ((${#COMPREPLY[@]} == 1)) && COMPREPLY=(${COMPREPLY/#/$prefix}) + _comp_compgen -c "${cur##*,}" -- -W "HIGH INFERENCE + INFERENCE_FAILURE UNDEFINED" + ((${#COMPREPLY[@]} == 1)) && + _comp_compgen -Rv COMPREPLY -- -P "$prefix" -W '"$COMPREPLY"' return ;; - --format | -!(-*)f) - COMPREPLY=($(compgen -W 'text parseable colorized json msvs' \ - -- "$cur")) + --format | -${noargopts}f) + _comp_compgen -- -W 'text parseable colorized json msvs' return ;; --import-graph | --ext-import-graph | --int-import-graph) - _filedir dot + _comp_compgen_filedir dot return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W \ - '$(_parse_help "$1" --long-help)' -- "$cur")) + _comp_compgen_help -- --long-help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - [[ $cur == @(.|*/)* ]] || _xfunc python _python_modules $python - _filedir py + _comp_compgen_set + _comp_looks_like_path "$cur" || _comp_compgen -x python modules $python + _comp_compgen -a filedir py } && - complete -F _pylint pylint pylint-2 pylint-3 + complete -F _comp_cmd_pylint pylint pylint-2 pylint-3 # ex: filetype=sh diff --git a/completions/pytest b/completions/pytest index 7457a84..9ed2575 100644 --- a/completions/pytest +++ b/completions/pytest @@ -1,134 +1,144 @@ # bash completion for pytest(1) -*- shell-script -*- -_pytest() +_comp_cmd_pytest__option_choice_args() { - local cur prev words cword split - _init_completion -s -n : || return + local modes=$("$1" "$2=bash-completion-nonexistent" 2>&1 | + command sed -e 's/[^[:space:][:alnum:]_-]\{1,\}//g' \ + -ne 's/.*choose from //p') + _comp_compgen -a -- -W '$modes' +} +_comp_cmd_pytest() +{ + local cur prev words cword was_split comp_args + _comp_initialize -s -n : -- "$@" || return + + local noargopts='!(-*|*[kmorpcWn]*)' + # shellcheck disable=SC2254 case $prev in - --help | --maxfail | --report | --junit-prefix | --doctest-glob | -!(-*)[hkmorp]) + --help | --maxfail | --report | --junit-prefix | --doctest-glob | \ + -${noargopts}[hkmorp]) return ;; --import-mode) - COMPREPLY=($(compgen -W "prepend append" -- "$cur")) + _comp_compgen -- -W "prepend append importlib" return ;; --capture) - COMPREPLY=($(compgen -W "fd sys no tee-sys" -- "$cur")) + _comp_compgen -- -W "fd sys no tee-sys" return ;; --lfnf | --last-failed-no-failures) - COMPREPLY=($(compgen -W "all none" -- "$cur")) + _comp_compgen -- -W "all none" return ;; --tb) - COMPREPLY=($(compgen -W "auto long short line native no" \ - -- "$cur")) + _comp_compgen -- -W 'auto long short line native no' return ;; --show-capture) - COMPREPLY=($(compgen -W "no stdout stderr log all" -- "$cur")) + _comp_compgen -- -W "no stdout stderr log all" return ;; --color) - COMPREPLY=($(compgen -W "yes no auto" -- "$cur")) + _comp_compgen -- -W "yes no auto" return ;; --pastebin) - COMPREPLY=($(compgen -W "failed all" -- "$cur")) + _comp_compgen -- -W "failed all" return ;; --junit-xml) - _filedir xml + _comp_compgen_filedir xml return ;; --result-log | --log-file) - _filedir log + _comp_compgen_filedir log return ;; - --ignore) - _filedir + --ignore | -${noargopts}c) + _comp_compgen_filedir return ;; --confcutdir | --basetemp | --rsyncdir | --rootdir) - _filedir -d + _comp_compgen_filedir -d return ;; --doctest-report) - COMPREPLY=($(compgen -W "none cdiff ndiff udiff only_first_failure" -- "$cur")) + _comp_compgen -- -W 'none cdiff ndiff udiff only_first_failure' return ;; --assert) - COMPREPLY=($(compgen -W "plain reinterp rewrite" -- "$cur")) + _comp_compgen -- -W "plain reinterp rewrite" return ;; --genscript) - _filedir py + _comp_compgen_filedir py return ;; - --pythonwarnings | -!(-*)W) - _xfunc python _python_warning_actions + --pythonwarnings | -${noargopts}W) + _comp_compgen -x python warning_actions return ;; - --numprocesses | -!(-*)n) - COMPREPLY=($(compgen -W "{1..$(_ncpus)} auto" -- "$cur")) + --numprocesses | -${noargopts}n) + local REPLY + _comp_get_ncpus + _comp_compgen -- -W "{1..$REPLY} auto" return ;; - --dist) - local modes=$("$1" --dist=nonexistent-distmode 2>&1 | - command sed -e 's/[^[:space:][:alnum:]-]\{1,\}//g' \ - -ne 's/.*choose from //p') - COMPREPLY=($(compgen -W '$modes' -- "$cur")) + --dist | --vcr-record?(-mode)) + _comp_cmd_pytest__option_choice_args "$1" "$prev" return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi if [[ $cur == *.py::*:* ]]; then local file=${cur/.py:*/.py} - local class=${cur#*.py::} in_class=false + local class=${cur#*.py::} in_class="" local line class=${class%%:*} while IFS= read -r line; do if [[ $line =~ ^class[[:space:]]+${class}[[:space:]:\(] ]]; then - in_class=true + in_class=set elif [[ $line =~ ^class[[:space:]] ]]; then - in_class=false + in_class="" fi - if $in_class && [[ $line =~ ^[[:space:]]+(async[[:space:]]+)?def[[:space:]]+(test_[A-Za-z0-9_]+) ]]; then - COMPREPLY+=(${BASH_REMATCH[2]}) + if [[ $in_class && $line =~ ^[[:space:]]+(async[[:space:]]+)?def[[:space:]]+(test_[A-Za-z0-9_]+) ]]; then + COMPREPLY+=("${BASH_REMATCH[2]}") fi done 2>/dev/null <"$file" ((!${#COMPREPLY[@]})) || - COMPREPLY=($(compgen -P "$file::$class::" -W '${COMPREPLY[@]}' \ - -- "${cur##*:?(:)}")) - __ltrim_colon_completions "$cur" + _comp_compgen -c "${cur##*:?(:)}" -- -P "$file::$class::" \ + -W '"${COMPREPLY[@]}"' + _comp_ltrim_colon_completions "$cur" return elif [[ $cur == *.py:* ]]; then local file="${cur/.py:*/.py}" line while IFS= read -r line; do if [[ $line =~ ^class[[:space:]]+(Test[A-Za-z0-9_]+) ]]; then - COMPREPLY+=(${BASH_REMATCH[1]}) + COMPREPLY+=("${BASH_REMATCH[1]}") elif [[ $line =~ ^(async[[:space:]]+)?def[[:space:]]+(test_[A-Za-z0-9_]+) ]]; then - COMPREPLY+=(${BASH_REMATCH[2]}) + COMPREPLY+=("${BASH_REMATCH[2]}") fi done 2>/dev/null <"$file" ((!${#COMPREPLY[@]})) || - COMPREPLY=($(compgen -P "$file::" -W '${COMPREPLY[@]}' \ - -- "${cur##*.py:?(:)}")) - __ltrim_colon_completions "$cur" + _comp_compgen -c "${cur##*.py:?(:)}" -- -P "$file::" \ + -W '"${COMPREPLY[@]}"' + _comp_ltrim_colon_completions "$cur" return fi - _filedir py + _comp_compgen_filedir py } && - complete -F _pytest pytest pytest-2 pytest-3 py.test py.test-2 py.test-3 + complete -F _comp_cmd_pytest \ + pytest pytest-2 pytest-3 py.test py.test-2 py.test-3 # ex: filetype=sh diff --git a/completions/python b/completions/python index d50c18f..5bf4b70 100644 --- a/completions/python +++ b/completions/python @@ -1,22 +1,42 @@ # bash completion for python -*- shell-script -*- +# @since 2.12 +_comp_xfunc_python_compgen_modules() +{ + local _python=python + [[ ${comp_args[0]##*/} == *3* ]] && _python=python3 + _comp_cmd_python__compgen_modules "$_python" +} + +# @deprecated 2.12 use `_comp_xfunc_python_compgen_modules` instead _python_modules() { - COMPREPLY+=($(compgen -W \ - "$(${1:-python} ${BASH_SOURCE[0]%/*}/../helpers/python $cur \ - 2>/dev/null)" -- "$cur")) + _comp_compgen -a -i python modules "${1:-python}" +} + +_comp_cmd_python__compgen_modules() +{ + _comp_compgen_split -- "$("$1" \ + "${BASH_SOURCE[0]%/*}/../helpers/python" "$cur" 2>/dev/null)" } +# @since 2.12 +_comp_xfunc_python_compgen_warning_actions() +{ + _comp_compgen -- -W "ignore default all module once error" \ + ${prefix:+-P "$prefix"} +} + +# @deprecated 2.12 use `_comp_xfunc_python_compgen_warning_actions` instead _python_warning_actions() { - COMPREPLY+=($(compgen -W "ignore default all module once error" \ - ${prefix:+-P "$prefix"} -- "$cur")) + _comp_compgen -a -i python warning_actions "${1:-python}" } -_python() +_comp_cmd_python() { - local cur prev words cword prefix - _init_completion || return + local cur prev words cword comp_args prefix + _comp_initialize -- "$@" || return case $cur in -[QWX]?*) @@ -26,42 +46,80 @@ _python() ;; esac + local noargopts='!(-*|*[cmQWX]*)' + + # if command, module, or script is already given by [-c command | -m module + # | script], complete all kind of files. + local i has_command="" + for ((i = 1; i < cword; i++)); do + # shellcheck disable=SC2254 + case ${words[i]} in + -${noargopts}[QWX]) + ((i++)) + ;; + -${noargopts}[cm]?*) + has_command=set + break + ;; + -- | -${noargopts}[cm]) + if ((i + 1 < cword)); then + has_command=set + break + fi + ;; + -*) ;; + *) + has_command=set + break + ;; + esac + done + if [[ $has_command ]]; then + _comp_compgen_filedir + return + fi + + # shellcheck disable=SC2254 case $prev in - --help | --version | -!(-*)[?hVcX]) + --help | --version | -${noargopts}[?hVc]) return ;; - -!(-*)m) - _python_modules "$1" + -${noargopts}m) + _comp_cmd_python__compgen_modules "$1" return ;; - -!(-*)Q) - COMPREPLY=($(compgen -W "old new warn warnall" -P "$prefix" \ - -- "$cur")) + -${noargopts}Q) + _comp_compgen -- -W 'old new warn warnall' -P "$prefix" return ;; - -!(-*)W) - _python_warning_actions + -${noargopts}W) + _comp_xfunc_python_compgen_warning_actions + return + ;; + -${noargopts}X) + _comp_compgen_split -- "$("$1" -h 2>&1 | + _comp_awk '$1 == "-X" && $2 ~ /:$/ { + sub(":$","",$2); sub("=.*","=",$2); print $2 + }')" + [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return ;; --jit) # TODO: quite a few others, parse from "--jit help" output? - COMPREPLY=($(compgen -W "help off" -- "$cur")) + _comp_compgen -- -W "help off" return ;; - !(?(*/)python*([0-9.])|?(*/)pypy*([0-9.])|-?)) - [[ $cword -lt 2 || ${words[cword - 2]} != -[QWX] ]] && _filedir - ;; esac - # if -c or -m is already given, complete all kind of files. - if [[ ${words[*]::cword} == *\ -[cm]\ * ]]; then - _filedir - elif [[ $cur != -* ]]; then - _filedir 'py?([cowz])' + if [[ $prev == -- || $cur != -* ]]; then + _comp_compgen_filedir '@(py?([cowz])|zip)' else - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur")) + _comp_compgen_help - <<<"$("$1" -h | + _comp_awk '{ sub("\\(-bb:","\n-bb "); print }')" fi } && - complete -F _python python python2 python2.7 python3 python3.{3..8} pypy pypy3 micropython + complete -F _comp_cmd_python \ + python python2 python2.7 python3 python3.{3..12} \ + pypy pypy3 pyston pyston3 micropython # ex: filetype=sh diff --git a/completions/pyvenv b/completions/pyvenv index 527a384..c7054df 100644 --- a/completions/pyvenv +++ b/completions/pyvenv @@ -1,9 +1,9 @@ # bash completion for pyvenv -*- shell-script -*- -_pyvenv() +_comp_cmd_pyvenv() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -h | --help) @@ -11,15 +11,15 @@ _pyvenv() ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - _longopt "$1" + _comp_complete_longopt "$@" return fi - _filedir -d + _comp_compgen_filedir -d } && - complete -F _pyvenv pyvenv pyvenv-3.{4..8} + complete -F _comp_cmd_pyvenv pyvenv pyvenv-3.{4..12} # ex: filetype=sh diff --git a/completions/qdbus b/completions/qdbus index 5b5a5e3..daf1065 100644 --- a/completions/qdbus +++ b/completions/qdbus @@ -1,14 +1,14 @@ # Qt qdbus, dcop completion -*- shell-script -*- -_qdbus() +_comp_cmd_qdbus() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - [[ -n $cur ]] && unset "words[$((${#words[@]} - 1))]" - COMPREPLY=($(compgen -W '$(command ${words[@]} 2>/dev/null | \ - command sed "s/(.*)//")' -- "$cur")) + _comp_compgen_split -- "$( + command "${words[@]::cword}" 2>/dev/null | command sed 's/(.*)//' + )" } && - complete -F _qdbus qdbus dcop + complete -F _comp_cmd_qdbus qdbus dcop # ex: filetype=sh diff --git a/completions/qemu b/completions/qemu index 8382981..c8bd741 100644 --- a/completions/qemu +++ b/completions/qemu @@ -1,108 +1,106 @@ # bash completion for qemu -*- shell-script -*- -_qemu() +_comp_cmd_qemu() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in - -fd[ab] | -hd[abcd] | -cdrom | -option-rom | -kernel | -initrd | -bootp | -pidfile | \ - -loadvm | -mtdblock | -sd | -pflash | -bios) - _filedir + -fd[ab] | -hd[abcd] | -cdrom | -option-rom | -kernel | -initrd | \ + -bootp | -pidfile | -loadvm | -mtdblock | -sd | -pflash | -bios) + _comp_compgen_filedir return ;; -tftp | -smb | -L | -chroot) - _filedir -d + _comp_compgen_filedir -d return ;; -boot) - COMPREPLY=($(compgen -W 'a c d n' -- "$cur")) + _comp_compgen -- -W 'a c d n' return ;; -k) - COMPREPLY=($(compgen -W 'ar de-ch es fo fr-ca hu ja mk no pt-br - sv da en-gb et fr fr-ch is lt nl pl ru th de en-us fi fr-be hr - it lv nl-be pt sl tr' -- "$cur")) + local -a keymaps + _comp_expand_glob keymaps '/usr/{local/,}share/qemu/keymaps/!(common|modifiers)' && + _comp_compgen -- -W '"${keymaps[@]##*/}"' return ;; -soundhw) - COMPREPLY=($(compgen -W "$($1 -soundhw help | awk \ - '/^[[:lower:]]/ {print $1}') all" -- "$cur")) + _comp_compgen_split -- "$("$1" -soundhw help | _comp_awk ' + function islower(s) { return length(s) > 0 && s == tolower(s); } + islower(substr($0, 1, 1)) {print $1}') all" return ;; -machine | -M) - COMPREPLY=($(compgen -W "$($1 $prev help | awk \ - '/^[[:lower:]]/ {print $1}')" -- "$cur")) + _comp_compgen_split -- "$("$1" "$prev" help | _comp_awk ' + function islower(s) { return length(s) > 0 && s == tolower(s); } + islower(substr($0, 1, 1)) {print $1}')" return ;; -cpu) - COMPREPLY=($(compgen -W "$($1 -cpu help | awk '{print $2}')" \ - -- "$cur")) + _comp_compgen_split -- "$("$1" -cpu help | _comp_awk '{print $2}')" return ;; -usbdevice) - COMPREPLY=($(compgen -W 'mouse tablet disk: host: serial: braille - net' -- "$cur")) + _comp_compgen -- -W 'mouse tablet disk: host: serial: braille net' return ;; -net) - COMPREPLY=($(compgen -W 'nic user tap socket vde none dump' \ - -- "$cur")) + _comp_compgen -- -W 'nic user tap socket vde none dump' return ;; -serial | -parallel | -monitor) - COMPREPLY=($(compgen -W 'vc pty none null /dev/ file: stdio pipe: - COM udp: tcp: telnet: unix: mon: braille' -- "$cur")) + _comp_compgen -- -W 'vc pty none null /dev/ file: stdio pipe: COM + udp: tcp: telnet: unix: mon: braille' return ;; -redir) - COMPREPLY=($(compgen -S":" -W 'tcp udp' -- "$cur")) + _comp_compgen -- -S":" -W 'tcp udp' return ;; -bt) - COMPREPLY=($(compgen -W 'hci vhci device' -- "$cur")) + _comp_compgen -- -W 'hci vhci device' return ;; -vga) - COMPREPLY=($(compgen -W 'cirrus std vmware xenfb none' -- "$cur")) + _comp_compgen -- -W 'cirrus std vmware xenfb none' return ;; -drive) - COMPREPLY=($(compgen -S"=" -W 'file if bus unit index media cyls - snapshot cache format serial addr' -- "$cur")) + _comp_compgen -- -S"=" -W 'file if bus unit index media cyls + snapshot cache format serial addr' return ;; -balloon) - COMPREPLY=($(compgen -W 'none virtio' -- "$cur")) + _comp_compgen -- -W 'none virtio' return ;; -smbios) - COMPREPLY=($(compgen -W 'file type' -- "$cur")) + _comp_compgen -- -W 'file type' return ;; -watchdog) - COMPREPLY=($(compgen -W "$($1 -watchdog help 2>&1 | - awk '{print $1}')" -- "$cur")) + _comp_compgen_split -- "$("$1" -watchdog help 2>&1 | + _comp_awk '{print $1}')" return ;; -watchdog-action) - COMPREPLY=($(compgen -W 'reset shutdown poweroff pause debug - none' -- "$cur")) + _comp_compgen -- -W 'reset shutdown poweroff pause debug none' return ;; -runas) - _allowed_users + _comp_compgen_allowed_users return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help) -fd{a,b} - -hd{a..d}' -- "$cur")) + _comp_compgen_help -- -help + _comp_compgen -a -- -W '-fd{a,b} -hd{a..d}' else - _filedir + _comp_compgen_filedir fi } && - complete -F _qemu qemu qemu-kvm qemu-system-i386 qemu-system-x86_64 + complete -F _comp_cmd_qemu qemu qemu-kvm qemu-system-i386 qemu-system-x86_64 # ex: filetype=sh diff --git a/completions/qrunner b/completions/qrunner index 3919ea2..cf54b68 100644 --- a/completions/qrunner +++ b/completions/qrunner @@ -1,18 +1,17 @@ # mailman qrunner completion -*- shell-script -*- -_qrunner() +_comp_cmd_qrunner() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--runner --once --list --verbose --subproc - --help' -- "$cur")) + _comp_compgen -- -W '--runner --once --list --verbose --subproc --help' fi } && - complete -F _qrunner qrunner + complete -F _comp_cmd_qrunner qrunner # ex: filetype=sh diff --git a/completions/querybts b/completions/querybts index edeba96..5b9f33a 100644 --- a/completions/querybts +++ b/completions/querybts @@ -1,40 +1,41 @@ # querybts completion -*- shell-script -*- -_querybts() +_comp_cmd_querybts() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[Bu]*)' + # shellcheck disable=SC2254 case $prev in - --bts | -!(-*)B) - COMPREPLY=($(compgen -W "debian guug kde mandrake help" \ - -- "$cur")) + --bts | -${noargopts}B) + _comp_compgen -- -W 'debian guug kde mandrake help' return ;; - --ui | --interface | -!(-*)u) - COMPREPLY=($(compgen -W "newt text gnome" -- "$cur")) + --ui | --interface | -${noargopts}u) + _comp_compgen -- -W "newt text gnome" return ;; --mbox-reader-cmd) - compopt -o filenames - COMPREPLY=($(compgen -c -- "$cur")) + _comp_compgen_commands return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - COMPREPLY=($(compgen -W 'wnpp boot-floppies kernel bugs.debian.org + _comp_compgen -- -W 'wnpp boot-floppies kernel bugs.debian.org cdimage.debian.org general installation-reports listarchives lists.debian.org mirrors nm.debian.org press project qa.debian.org release-notes security.debian.org tech-ctte upgrade-reports - www.debian.org $(_xfunc apt-cache _apt_cache_packages)' -- "$cur")) + www.debian.org' + _comp_compgen -ax apt-cache packages fi } && - complete -F _querybts querybts + complete -F _comp_cmd_querybts querybts # ex: filetype=sh diff --git a/completions/quota b/completions/quota index f5f9cc8..504284c 100644 --- a/completions/quota +++ b/completions/quota @@ -1,49 +1,47 @@ # bash completion for quota-tools -*- shell-script -*- -_user_or_group() +_comp_cmd_quota__user_or_group() { local i # complete on groups if -g was given for ((i = 1; i < cword; i++)); do if [[ ${words[i]} == -@(g|-group) ]]; then - COMPREPLY=($(compgen -g -- "$cur")) + _comp_compgen -- -g return fi done # otherwise complete on users - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u } -_quota_parse_help() +_comp_cmd_quota__parse_help() { - local opts=$(_parse_help "$1") - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage [[ ${COMPREPLY-} == *= ]] && compopt -o nospace } -_quota_formats() +_comp_cmd_quota__formats() { - COMPREPLY=($(compgen -W 'vfsold vfsv0 rpc xfs' -- "$cur")) + _comp_compgen -- -W 'vfsold vfsv0 rpc xfs' } -_filesystems() +_comp_cmd_quota__filesystems() { # Only list filesystems starting with "/", otherwise we also get #+ "binfmt_misc", "proc", "tmpfs", ... - COMPREPLY=($(compgen -W "$(awk '/^\// {print $1}' /etc/mtab)" \ - -- "$cur")) + _comp_compgen_split -- "$(_comp_awk '/^\// {print $1}' /etc/mtab)" } -_quota() +_comp_cmd_quota() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -F | --format) - _quota_formats + _comp_cmd_quota__formats return ;; -h | --help | -V | --version) @@ -51,28 +49,28 @@ _quota() ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - _quota_parse_help "$1" + _comp_cmd_quota__parse_help "$1" else - _user_or_group + _comp_cmd_quota__user_or_group fi } && - complete -F _quota -o default quota + complete -F _comp_cmd_quota -o default quota -_setquota() +_comp_cmd_setquota() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -F | --format) - _quota_formats + _comp_cmd_quota__formats return ;; -p | --prototype) - _user_or_group + _comp_cmd_quota__user_or_group return ;; -h | --help | -V | --version) @@ -80,43 +78,43 @@ _setquota() ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - _quota_parse_help "$1" + _comp_cmd_quota__parse_help "$1" else - local args - _count_args + local REPLY + _comp_count_args - case $args in + case $REPLY in 1) - _user_or_group + _comp_cmd_quota__user_or_group ;; 2) - _filesystems + _comp_cmd_quota__filesystems ;; esac fi } && - complete -F _setquota -o default setquota + complete -F _comp_cmd_setquota -o default setquota -_edquota() +_comp_cmd_edquota() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -F | --format) - _quota_formats + _comp_cmd_quota__formats return ;; -f | --filesystem) - _filesystems + _comp_cmd_quota__filesystems return ;; -p | --prototype) - _user_or_group + _comp_cmd_quota__user_or_group return ;; -h | --help | -V | --version) @@ -124,24 +122,24 @@ _edquota() ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - _quota_parse_help "$1" + _comp_cmd_quota__parse_help "$1" else - _user_or_group + _comp_cmd_quota__user_or_group fi } && - complete -F _edquota -o default edquota + complete -F _comp_cmd_edquota -o default edquota -_quotacheck() +_comp_cmd_quotacheck() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -F | --format) - _quota_formats + _comp_cmd_quota__formats return ;; -h | --help | -V | --version) @@ -149,28 +147,28 @@ _quotacheck() ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - _quota_parse_help "$1" + _comp_cmd_quota__parse_help "$1" else - _filesystems + _comp_cmd_quota__filesystems fi } && - complete -F _quotacheck -o default quotacheck repquota + complete -F _comp_cmd_quotacheck -o default quotacheck repquota -_quotaon() +_comp_cmd_quotaon() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -F | --format) - _quota_formats + _comp_cmd_quota__formats return ;; -x | --xfs-command) - COMPREPLY=($(compgen -W 'delete enforce' -- "$cur")) + _comp_compgen -- -W 'delete enforce' return ;; -h | --help | -V | --version) @@ -178,14 +176,14 @@ _quotaon() ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - _quota_parse_help "$1" + _comp_cmd_quota__parse_help "$1" else - _filesystems + _comp_cmd_quota__filesystems fi } && - complete -F _quotaon -o default quotaon quotaoff + complete -F _comp_cmd_quotaon -o default quotaon quotaoff # ex: filetype=sh diff --git a/completions/radvdump b/completions/radvdump index 850628f..74ce574 100644 --- a/completions/radvdump +++ b/completions/radvdump @@ -1,22 +1,22 @@ # radvdump(8) completion -*- shell-script -*- -_radvdump() +_comp_cmd_radvdump() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -h | --help | -v | --version) return ;; -d | --debug) - COMPREPLY=($(compgen -W '{1..4}' -- "$cur")) + _comp_compgen -- -W '{1..4}' return ;; esac - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help } && - complete -F _radvdump radvdump + complete -F _comp_cmd_radvdump radvdump # ex: filetype=sh diff --git a/completions/rcs b/completions/rcs index c04d89d..aab018e 100644 --- a/completions/rcs +++ b/completions/rcs @@ -1,9 +1,9 @@ # bash completion for rcs -*- shell-script -*- -_rcs() +_comp_cmd_rcs() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local file dir i @@ -13,7 +13,7 @@ _rcs() # deal with relative directory [[ $file == "$dir" ]] && dir=. - COMPREPLY=($(compgen -f -- "$dir/RCS/$file")) + _comp_compgen -c "$dir/RCS/$file" -- -f for i in ${!COMPREPLY[*]}; do file=${COMPREPLY[i]##*/} @@ -21,7 +21,7 @@ _rcs() COMPREPLY[i]=$dir$file done - COMPREPLY+=($(compgen -G "$dir/$file*,v")) + _comp_compgen -aR -- -G "$dir/$file*,v" for i in ${!COMPREPLY[*]}; do COMPREPLY[i]=${COMPREPLY[i]%,v} @@ -29,8 +29,8 @@ _rcs() # default to files if nothing returned and we're checking in. # otherwise, default to directories - [[ ${#COMPREPLY[@]} -eq 0 && $1 == *ci ]] && _filedir || _filedir -d + [[ ${#COMPREPLY[@]} -eq 0 && $1 == *ci ]] && _comp_compgen -a filedir || _comp_compgen -a filedir -d } && - complete -F _rcs ci co rlog rcs rcsdiff + complete -F _comp_cmd_rcs ci co rlog rcs rcsdiff # ex: filetype=sh diff --git a/completions/rdesktop b/completions/rdesktop index 54c1ae6..42d2ccb 100644 --- a/completions/rdesktop +++ b/completions/rdesktop @@ -1,39 +1,34 @@ # bash completion for rdesktop -*- shell-script -*- -_rdesktop() +_comp_cmd_rdesktop() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return case $prev in -*k) - COMPREPLY=($(command ls \ - /usr/share/rdesktop/keymaps 2>/dev/null | - command grep -E -v '(common|modifiers)')) - COMPREPLY+=($(command ls $HOME/.rdesktop/keymaps 2>/dev/null)) - COMPREPLY+=($(command ls ./keymaps 2>/dev/null)) - COMPREPLY=($(compgen -W '${COMPREPLY[@]}' -- "$cur")) + _comp_expand_glob COMPREPLY '/usr/share/rdesktop/keymaps/!(*@(common|modifiers)*) {"$HOME/.rdesktop",.}/keymaps/*' && + _comp_compgen -- -W '"${COMPREPLY[@]}"' return ;; -*a) - COMPREPLY=($(compgen -W '8 15 16 24' -- "$cur")) + _comp_compgen -- -W '8 15 16 24' return ;; -*x) - COMPREPLY=($(compgen -W 'broadband modem lan' -- "$cur")) + _comp_compgen -- -W 'broadband modem lan' return ;; -*r) case $cur in sound:*) - COMPREPLY=($(compgen -W 'local off remote' \ - -- "${cur#sound:}")) + _comp_compgen -c "${cur#sound:}" -- -W 'local off remote' ;; *:*) ;; *) - COMPREPLY=($(compgen -W 'comport: disk: lptport: - printer: sound: lspci scard' -- "$cur")) + _comp_compgen -- -W 'comport: disk: lptport: printer: + sound: lspci scard' [[ ${COMPREPLY-} == *: ]] && compopt -o nospace ;; esac @@ -45,13 +40,15 @@ _rdesktop() esac if [[ $cur == -* ]]; then - local opts=($(_parse_help "$1")) - COMPREPLY=($(compgen -W '${opts[@]%:}' -- "$cur")) + local -a opts + _comp_compgen -Rv opts help + ((${#opts[@]})) && + _comp_compgen -- -W '"${opts[@]%:}"' else - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" fi } && - complete -F _rdesktop rdesktop + complete -F _comp_cmd_rdesktop rdesktop # ex: filetype=sh diff --git a/completions/remove_members b/completions/remove_members index db7ad0b..4689b03 100644 --- a/completions/remove_members +++ b/completions/remove_members @@ -1,27 +1,30 @@ # mailman remove_members completion -*- shell-script -*- -_remove_members() +_comp_cmd_remove_members() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -f | --file) - _filedir + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--file --all --fromall --nouserack - --noadminack --help' -- "$cur")) + _comp_compgen -- -W '--file --all --fromall --nouserack --noadminack + --help' else - _xfunc list_lists _mailman_lists + # Prefer `list_lists` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen -x list_lists mailman_lists fi } && - complete -F _remove_members remove_members + complete -F _comp_cmd_remove_members remove_members # ex: filetype=sh diff --git a/completions/removepkg b/completions/removepkg index a56beb0..73b632b 100644 --- a/completions/removepkg +++ b/completions/removepkg @@ -1,25 +1,22 @@ # Slackware Linux removepkg completion -*- shell-script -*- -_removepkg() +_comp_cmd_removepkg() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-copy -keep -preserve -warn' -- "$cur")) + _comp_compgen -- -W '-copy -keep -preserve -warn' return fi - if [[ $cur == */* ]]; then - _filedir + if _comp_looks_like_path "$cur"; then + _comp_compgen_filedir return fi local root=${ROOT:-/} - COMPREPLY=($( - cd "$root/var/log/packages" 2>/dev/null || return 1 - compgen -f -- "$cur" - )) + _comp_compgen -C "$root/var/log/packages" -- -f } && - complete -F _removepkg removepkg + complete -F _comp_cmd_removepkg removepkg # ex: filetype=sh diff --git a/completions/reportbug b/completions/reportbug index 69b12e9..30c4647 100644 --- a/completions/reportbug +++ b/completions/reportbug @@ -1,96 +1,76 @@ # bash completion for (Debian) reportbug -*- shell-script -*- -_reportbug() +_comp_cmd_reportbug() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[CefKHPsoiATjVuQtBS]*)' + # shellcheck disable=SC2254 case $prev in - --class | --header | --pseudo-header | --mirror | --list-cc | --subject | \ - --http_proxy | --proxy | --email | --realname | --smtpuser | --smtppasswd | \ - --replyto | --reply-to | --justification | --package-version | --body | \ - --body-file | --timeout | --max-attachment-size | --envelope-from | \ - -!(-*)[CHPsjV]) + --class | --header | --pseudo-header | --mirror | --list-cc | \ + --subject | --http_proxy | --proxy | --email | --realname | \ + --smtpuser | --smtppasswd | --replyto | --reply-to | \ + --justification | --package-version | --body | --body-file | \ + --timeout | --max-attachment-size | --envelope-from | \ + -${noargopts}[CHPsjV]) return ;; --filename | --include | --mta | --output | --attach | -[fioA]) - _filedir + _comp_compgen_filedir return ;; - --keyid | -!(-*)K) - COMPREPLY=($(compgen -W '$(IFS=: ; \ - gpg --list-keys --with-colons 2>/dev/null \ - | while read -ra row ; do - [[ "${row[0]}" == [ps]ub && ${row[11]} == *s* ]] && \ - printf "%s\n" "${row[4]}" - done)' -- "$cur")) + --keyid | -${noargopts}K) + _comp_compgen_split -- "$( + IFS=: + gpg --list-keys --with-colons 2>/dev/null | + while read -ra row; do + [[ ${row[0]} == [ps]ub && ${row[11]} == *s* ]] && + printf '%s\n' "${row[4]}" + done + )" return ;; - --bts | -!(-*)B) - COMPREPLY=($(compgen -W "debian guug kde mandrake help" -- \ - "$cur")) + --tag | --ui | --interface | --type | --bts | --severity | --mode | -${noargopts}[TutBS]) + _comp_compgen_split -- "$("$1" "$prev" help 2>&1 | + command sed -ne '/^[[:space:]]/p')" return ;; - --editor | --mua | --mbox-reader-cmd | -!(-*)e) - compopt -o filenames - COMPREPLY=($(compgen -c -- "$cur")) - return - ;; - --mode) - COMPREPLY=($(compgen -W "novice standard expert" -- "$cur")) - return - ;; - --severity | -!(-*)S) - COMPREPLY=($(compgen -W "grave serious important normal minor - wishlist" -- "$cur")) - return - ;; - --ui | --interface | -!(-*)u) - COMPREPLY=($(compgen -W "newt text gnome" -- "$cur")) - return - ;; - --type | -!(-*)t) - COMPREPLY=($(compgen -W "gnats debbugs" -- "$cur")) - return - ;; - --tag | -!(-*)T) - COMPREPLY=($(compgen -W "none woody potato sarge sarge-ignore - etch etch-ignore lenny lenny-ignore sid experimental confirmed - d-i fixed fixed-in-experimental fixed-upstream help l10n - moreinfo patch pending security unreproducible upstream wontfix - ipv6 lfs" -- "$cur")) + --editor | --mua | --mbox-reader-cmd | -${noargopts}e) + _comp_compgen_commands return ;; --from-buildd) - COMPREPLY=($(compgen -S "_" -W '$(apt-cache dumpavail | \ - command grep "^Source: $cur" | sort -u | cut -f2 -d" ")')) + _comp_compgen_split -S "_" -- "$(apt-cache dumpavail | + _comp_awk -F ' ' '$1 == "Source:" && !uniq[$2]++ { print $2 }')" return ;; --smtphost) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; --draftpath) - _filedir -d + _comp_compgen_filedir -d return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == -*= ]] && compopt -o nospace return fi - COMPREPLY=($(compgen -W 'wnpp boot-floppies kernel bugs.debian.org + _comp_compgen -- -W 'wnpp boot-floppies kernel bugs.debian.org cdimage.debian.org general installation-reports listarchives lists.debian.org mirrors nm.debian.org press project qa.debian.org release-notes security.debian.org tech-ctte upgrade-reports - www.debian.org $(_xfunc apt-cache _apt_cache_packages)' -- "$cur")) - _filedir + www.debian.org' + _comp_compgen -ax apt-cache packages + _comp_compgen -a filedir } && - complete -F _reportbug reportbug + complete -F _comp_cmd_reportbug reportbug # ex: filetype=sh diff --git a/completions/resolvconf b/completions/resolvconf index b407488..4389fa8 100644 --- a/completions/resolvconf +++ b/completions/resolvconf @@ -1,21 +1,21 @@ # bash completion for resolvconf -*- shell-script -*- -_resolvconf() +_comp_cmd_resolvconf() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -a | -d) - _available_interfaces + _comp_compgen_available_interfaces return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-a -d -u' -- "$cur")) + _comp_compgen -- -W '-a -d -u' fi } && - complete -F _resolvconf resolvconf + complete -F _comp_cmd_resolvconf resolvconf # ex: filetype=sh diff --git a/completions/ri b/completions/ri index 9c34b27..514bf6d 100644 --- a/completions/ri +++ b/completions/ri @@ -1,110 +1,116 @@ # ri completion for Ruby documentation -*- shell-script -*- # by Ian Macdonald <ian@caliban.org> -_ri_get_methods() +# @var[in] ri_version +# @var[in] prefix +# @var[in] classes +_comp_cmd_ri__compgen_methods() { - local regex + local _regex + local IFS=$' \t\n' # needed for ${classes[@]+"${classes[@]}"} in bash-5.2 + local _methods if [[ $ri_version == integrated ]]; then - if [[ -z $separator ]]; then - regex="(Instance|Class)" + if [[ ! $separator ]]; then + _regex="(Instance|Class)" elif [[ $separator == "#" ]]; then - regex=Instance + _regex=Instance else - regex=Class + _regex=Class fi - COMPREPLY+=( - "$(ri "${classes[@]}" 2>/dev/null | ruby -ane \ - 'if /^'"$regex"' methods:/.../^------------------|^$/ and \ + _comp_split -la _methods \ + "$(ri ${classes[@]+"${classes[@]}"} 2>/dev/null | ruby -ane \ + 'if /^'"$_regex"' methods:/.../^------------------|^$/ and \ /^ / then print $_.split(/, |,$/).grep(/^[^\[]*$/).join("\n"); \ - end' 2>/dev/null | sort -u)") + end' 2>/dev/null | sort -u)" else # older versions of ri didn't distinguish between class/module and # instance methods - COMPREPLY+=( - "$(ruby -W0 $ri_path "${classes[@]}" 2>/dev/null | ruby -ane \ + _comp_split -la _methods \ + "$(ruby -W0 "$ri_path" ${classes[@]+"${classes[@]}"} 2>/dev/null | ruby -ane \ 'if /^-/.../^-/ and ! /^-/ and ! /^ +(class|module): / then \ print $_.split(/, |,$| +/).grep(/^[^\[]*$/).join("\n"); \ - end' | sort -u)") - fi - COMPREPLY=($(compgen $prefix -W '${COMPREPLY[@]}' -- $method)) + end' | sort -u)" + fi && + _comp_compgen -- -P "$prefix" -W '"${_methods[@]}"' } # needs at least Ruby 1.8.0 in order to use -W0 -_ri() +_comp_cmd_ri() { - local cur prev words cword split - _init_completion -s -n : || return + local cur prev words cword was_split comp_args + _comp_initialize -s -n : -- "$@" || return + local noargopts='!(-*|*[wfd]*)' + # shellcheck disable=SC2254 case $prev in - --help | --width | -!(-*)[hw]) + --help | --width | -${noargopts}[hw]) return ;; - --format | -!(-*)f) - COMPREPLY=($(compgen -W 'ansi bs html rdoc' -- "$cur")) + --format | -${noargopts}f) + _comp_compgen -- -W 'ansi bs html rdoc' return ;; - --doc-dir | -!(-*)d) - _filedir -d + --doc-dir | -${noargopts}d) + _comp_compgen_filedir -d return ;; --dump) - _filedir ri + _comp_compgen_filedir ri return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - local class method prefix ri_path ri_version ri_major separator IFS + local class method prefix="" ri_path ri_version ri_major="" separator local -a classes ri_path=$(type -p ri) # which version of ri are we using? # -W0 is required here to stop warnings from older versions of ri # from being captured when used with Ruby 1.8.1 and later - ri_version="$(ruby -W0 $ri_path -v 2>&1)" || ri_version=integrated + ri_version="$(ruby -W0 "$ri_path" -v 2>&1)" || ri_version=integrated [[ $ri_version != "${ri_version%200*}" ]] && ri_version=integrated [[ $ri_version =~ ri[[:space:]]v?([0-9]+) ]] && ri_major=${BASH_REMATCH[1]} # need to also split on commas - IFS=$', \n\t' if [[ $cur == [A-Z]*[#.]* ]]; then [[ $cur == *#* ]] && separator=# || separator=. # we're completing on class and method - class=${cur%$separator*} - method=${cur#*$separator} - classes=($class) - prefix="-P $class$separator" - _ri_get_methods + class=${cur%"$separator"*} + method=${cur#*"$separator"} + _comp_split -F $', \n\t' classes "$class" + prefix=$class$separator + _comp_compgen -c "$method" -i ri methods return fi if [[ $ri_version == integrated ]]; then # integrated ri from Ruby 1.9 - classes=($(ri -c 2>/dev/null | ruby -ne 'if /^\s*$/..$stdin.eof then \ - if /^ +[A-Z]/ then print; end; end' 2>/dev/null)) + _comp_split -F $', \n\t' classes \ + "$(ri -c 2>/dev/null | ruby -ne 'if /^\s*$/..$stdin.eof then \ + if /^ +[A-Z]/ then print; end; end' 2>/dev/null)" elif [[ $ri_major && $ri_major -ge 3 ]]; then - classes=($(ri -l 2>/dev/null)) + _comp_split -F $', \n\t' classes "$(ri -l 2>/dev/null)" elif [[ $ri_version == "ri 1.8a" ]]; then - classes=($(ruby -W0 $ri_path | + _comp_split -F $', \n\t' classes "$(ruby -W0 "$ri_path" | ruby -ne 'if /^'"'"'ri'"'"' has/..$stdin.eof then \ - if /^ .*[A-Z]/ then print; end; end')) + if /^ .*[A-Z]/ then print; end; end')" else - classes=($(ruby -W0 $ri_path | + _comp_split -F $', \n\t' classes "$(ruby -W0 "$ri_path" | ruby -ne 'if /^I have/..$stdin.eof then \ - if /^ .*[A-Z]/ then print; end; end')) - fi - - COMPREPLY=($(compgen -W '${classes[@]}' -- "$cur")) - __ltrim_colon_completions "$cur" + if /^ .*[A-Z]/ then print; end; end')" + fi && + _comp_compgen -- -W '"${classes[@]}"' + _comp_ltrim_colon_completions "$cur" if [[ $cur == [A-Z]* ]]; then # we're completing on class or module alone @@ -112,9 +118,8 @@ _ri() fi # we're completing on methods - method=$cur - _ri_get_methods + _comp_cmd_ri__compgen_methods } && - complete -F _ri ri + complete -F _comp_cmd_ri ri # ex: filetype=sh diff --git a/completions/rmlist b/completions/rmlist index 0cc473a..f3aca06 100644 --- a/completions/rmlist +++ b/completions/rmlist @@ -1,17 +1,20 @@ # mailman rmlist completion -*- shell-script -*- -_rmlist() +_comp_cmd_rmlist() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--archives --help' -- "$cur")) + _comp_compgen -- -W '--archives --help' else - _xfunc list_lists _mailman_lists + # Prefer `list_lists` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen -x list_lists mailman_lists fi } && - complete -F _rmlist rmlist + complete -F _comp_cmd_rmlist rmlist # ex: filetype=sh diff --git a/completions/rmmod b/completions/rmmod index 7ec29e6..a57a206 100644 --- a/completions/rmmod +++ b/completions/rmmod @@ -1,10 +1,10 @@ # Linux rmmod(8) completion. -*- shell-script -*- # This completes on a list of all currently installed kernel modules. -_rmmod() +_comp_cmd_rmmod() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -h | --help | -V | --version) @@ -13,12 +13,12 @@ _rmmod() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - _installed_modules "$cur" + _comp_compgen_inserted_kernel_modules } && - complete -F _rmmod rmmod + complete -F _comp_cmd_rmmod rmmod # ex: filetype=sh diff --git a/completions/route b/completions/route index f9b3196..3351415 100644 --- a/completions/route +++ b/completions/route @@ -2,13 +2,13 @@ [[ $OSTYPE == *linux* ]] || return 1 -_route() +_comp_cmd_route() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $prev == dev ]]; then - _available_interfaces + _comp_compgen_available_interfaces return fi @@ -16,15 +16,16 @@ _route() local opt found i for opt in add del -host -net netmask metric mss window irtt reject mod \ dyn reinstate dev default gw; do - found=false - for ((i = 1; i < ${#words[@]} - 1; i++)); do - [[ ${words[i]} == "$opt" ]] && found=true && break + found="" + for ((i = 1; i < cword; i++)); do + [[ ${words[i]} == "$opt" ]] && found=set && break done - $found || COMPREPLY+=("$opt") + [[ $found ]] || COMPREPLY+=("$opt") done - COMPREPLY=($(compgen -W '"${COMPREPLY[@]}"' -- "$cur")) + ((${#COMPREPLY[@]})) && + _comp_compgen -- -W '"${COMPREPLY[@]}"' } && - complete -F _route route + complete -F _comp_cmd_route route # ex: filetype=sh diff --git a/completions/rpcdebug b/completions/rpcdebug index 6e2b88c..59778d9 100644 --- a/completions/rpcdebug +++ b/completions/rpcdebug @@ -1,46 +1,47 @@ # bash completion for rpcdebug -*- shell-script -*- -_rpcdebug_flags() +_comp_cmd_rpcdebug__flags() { local i module for ((i = 1; i < ${#words[@]}; i++)); do if [[ ${words[i]} == -m ]]; then - module=${words[i + 1]} + module=${words[i + 1]-} break fi done - if [[ -n $module ]]; then - COMPREPLY=($(compgen -W "$(rpcdebug -vh 2>&1 | - command sed -ne 's/^'$module'[[:space:]]\{1,\}//p')" -- "$cur")) + if [[ $module ]]; then + _comp_compgen_split -- "$(rpcdebug -vh 2>&1 | + command sed -ne 's/^'"$module"'[[:space:]]\{1,\}//p')" fi } -_rpcdebug() +_comp_cmd_rpcdebug() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*s) - _rpcdebug_flags + _comp_cmd_rpcdebug__flags return ;; -*c) - _rpcdebug_flags + _comp_cmd_rpcdebug__flags return ;; -*m) - COMPREPLY=($(compgen -W 'rpc nfs nfsd nlm' -- "$cur")) + _comp_compgen -- -W 'rpc nfs nfsd nlm' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" -h) -s -c' -- "$cur")) + _comp_compgen_usage -- -h + _comp_compgen -a -- -W '-s -c' fi } && - complete -F _rpcdebug rpcdebug + complete -F _comp_cmd_rpcdebug rpcdebug # ex: filetype=sh diff --git a/completions/rpm b/completions/rpm index 8299a37..b6cafa5 100644 --- a/completions/rpm +++ b/completions/rpm @@ -2,99 +2,114 @@ # helper functions -_rpm_installed_packages() +# @since 2.12 +_comp_xfunc_rpm_compgen_installed_packages() { - if [[ -r /var/log/rpmpkgs && \ + _comp_cmd_rpm__compgen_installed_packages rpm +} + +_comp_cmd_rpm__compgen_installed_packages() +{ + if [[ -r /var/log/rpmpkgs && /var/log/rpmpkgs -nt /var/lib/rpm/Packages ]]; then # using RHL 7.2 or later - this is quicker than querying the DB - COMPREPLY=($(compgen -W "$(command sed -ne \ + _comp_compgen_split -- "$(command sed -ne \ 's|^\([^[:space:]]\{1,\}\)-[^[:space:]-]\{1,\}-[^[:space:]-]\{1,\}\.rpm$|\1|p' \ - /var/log/rpmpkgs)" -- "$cur")) + /var/log/rpmpkgs)" elif type rpmqpack &>/dev/null; then # SUSE's rpmqpack is faster than rpm -qa - COMPREPLY=($(compgen -W '$(rpmqpack)' -- "$cur")) + _comp_compgen_split -- "$(rpmqpack)" else - COMPREPLY=($(${1:-rpm} -qa --nodigest --nosignature \ - --queryformat='%{NAME} ' "$cur*" 2>/dev/null)) + _comp_compgen_split -- "$("${1:-rpm}" -qa --nodigest --nosignature \ + --queryformat='%{NAME} ' "$cur*" 2>/dev/null)" fi } -_rpm_groups() +_comp_deprecate_func 2.12 _rpm_installed_packages \ + _comp_xfunc_rpm_compgen_installed_packages + +_comp_cmd_rpm__groups() { - local IFS=$'\n' - COMPREPLY=($(compgen -W "$(${1:-rpm} -qa --nodigest --nosignature \ - --queryformat='%{GROUP}\n' 2>/dev/null)" -- "$cur")) + _comp_compgen_split -l -- "$("${1:-rpm}" -qa --nodigest --nosignature \ + --queryformat='%{GROUP}\n' 2>/dev/null)" } -_rpm_macros() +_comp_cmd_rpm__macros() { # get a list of macros - COMPREPLY=($(compgen -W "$(${1:-rpm} --showrc | command sed -ne \ - 's/^-\{0,1\}[0-9]\{1,\}[:=][[:space:]]\{1,\}\([^[:space:](]\{3,\}\).*/%\1/p')" \ - -- "$cur")) + _comp_compgen_split -- "$("${1:-rpm}" --showrc | command sed -ne \ + 's/^-\{0,1\}[0-9]\{1,\}[:=][[:space:]]\{1,\}\([^[:space:](]\{3,\}\).*/%\1/p')" } -_rpm_buildarchs() +# shellcheck disable=SC2120 +_comp_cmd_rpm__buildarchs() { - COMPREPLY=($(compgen -W "$(${1:-rpm} --showrc | command sed -ne \ - 's/^\s*compatible\s\s*build\s\s*archs\s*:\s*\(.*\)/\1/ p')" \ - -- "$cur")) + # Case-insensitive BRE to match "compatible build archs" + local regex_header='[cC][oO][mM][pP][aA][tT][iI][bB][lL][eE][[:space:]]\{1,\}[bB][uU][iI][lL][dD][[:space:]]\{1,\}[aA][rR][cC][hH][sS]' + _comp_compgen_split -- "$("${1:-rpm}" --showrc | command sed -ne \ + "s/^[[:space:]]*${regex_header}[[:space:]]*:[[:space:]]*\(.*\)/\1/p")" +} + +# shellcheck disable=SC2120 +_comp_cmd_rpm__configdir() +{ + cfgdir=$("${1:-rpm}" --eval '%{_rpmconfigdir}' 2>/dev/null) } # rpm(8) completion # -_rpm() +_comp_cmd_rpm() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return if ((cword == 1)); then # first parameter on line case $cur in --*) - COMPREPLY=($(compgen -W '--help --version --initdb - --checksig --addsign --delsign --rebuilddb --showrc - --setperms --setugids --eval --install --upgrade --query - --freshen --erase --verify --querytags --import' \ - -- "$cur")) + _comp_compgen -- -W '--help --version --initdb --checksig + --addsign --delsign --rebuilddb --showrc --setperms + --setugids --eval --install --upgrade --query --freshen + --erase --verify --querytags --import' ;; *) - COMPREPLY=($(compgen -W '-e -E -F -i -q -t -U -V' -- "$cur")) + _comp_compgen -- -W '-e -E -F -i -q -t -U -V' ;; esac return fi + local noargopts='!(-*|*[rED]*)' + # shellcheck disable=SC2254 case $prev in - --dbpath | --excludepath | --prefix | --relocate | --root | -!(-*)r) - _filedir -d + --dbpath | --excludepath | --prefix | --relocate | --root | -${noargopts}r) + _comp_compgen_filedir -d return ;; - --eval | -!(-*)E) - _rpm_macros $1 + --eval | -${noargopts}E) + _comp_cmd_rpm__macros "$1" return ;; --pipe) - compopt -o filenames - COMPREPLY=($(compgen -c -- "$cur")) + _comp_compgen_commands return ;; --rcfile) - _filedir + _comp_compgen_filedir return ;; --specfile) # complete on .spec files - _filedir spec + _comp_compgen_filedir spec return ;; --whatenhances | --whatprovides | --whatrecommends | --whatrequires | \ --whatsuggests | --whatsupplements) - if [[ $cur == */* ]]; then - _filedir + if _comp_looks_like_path "$cur"; then + _comp_compgen_filedir else # complete on capabilities - local IFS=$'\n' fmt + local fmt case $prev in *enhances) fmt="%{ENHANCENAME}" ;; *provides) fmt="%{PROVIDENAME}" ;; @@ -103,176 +118,181 @@ _rpm() *suggests) fmt="%{SUGGESTNAME}" ;; *supplements) fmt="%{SUPPLEMENTNAME}" ;; esac - COMPREPLY=($(compgen -W "$($1 -qa --nodigest --nosignature \ - --queryformat=\"$fmt\\n\" 2>/dev/null | - command grep -vF '(none)')" -- "$cur")) + _comp_compgen_split -l -- "$("$1" -qa --nodigest \ + --nosignature --queryformat="\"$fmt\\n\"" 2>/dev/null | + command grep -vF '(none)')" fi return ;; - --define | --fileid | --hdrid | --pkgid | -!(-*)D) + --define | --fileid | --hdrid | --pkgid | -${noargopts}D) # argument required but no completions available return ;; esac - $split && return + [[ $was_split ]] && return # options common to all modes - local opts="--define= --eval= --macros= --nodigest --nosignature --rcfile= - --quiet --pipe --verbose" + local -a opts=( + --define= --eval= --macros= --nodigest --nosignature --rcfile= --quiet + --pipe --verbose + ) case ${words[1]} in -[iFU]* | --install | --freshen | --upgrade) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W "$opts --percent --force --test - --replacepkgs --replacefiles --root --excludedocs --includedocs - --noscripts --ignorearch --dbpath --prefix= --ignoreos --nodeps - --allfiles --ftpproxy --ftpport --justdb --httpproxy --httpport - --noorder --relocate= --badreloc --notriggers --excludepath= - --ignoresize --oldpackage --queryformat --repackage - --nosuggests" -- "$cur")) + _comp_compgen -- -W '"${opts[@]}" --percent --force --test + --replacepkgs --replacefiles --root --excludedocs + --includedocs --noscripts --ignorearch --dbpath --prefix= + --ignoreos --nodeps --allfiles --ftpproxy --ftpport + --justdb --httpproxy --httpport --noorder --relocate= + --badreloc --notriggers --excludepath= --ignoresize + --oldpackage --queryformat --repackage --nosuggests' else - _filedir '[rs]pm' + _comp_compgen_filedir '[rs]pm' fi ;; -e | --erase) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W "$opts --allmatches --noscripts - --notriggers --nodeps --test --repackage" -- "$cur")) + _comp_compgen -- -W '"${opts[@]}" --allmatches --noscripts + --notriggers --nodeps --test --repackage' else - _rpm_installed_packages $1 + _comp_cmd_rpm__compgen_installed_packages "$1" fi ;; -q* | --query) # options common to all query types - opts+=" --changelog --configfiles --conflicts --docfiles --dump + opts+=( + --changelog --configfiles --conflicts --docfiles --dump --enhances --filesbypkg --filecaps --fileclass --filecolor --fileprovide --filerequire --filesbypkg --info --list --obsoletes --pipe --provides --queryformat= --requires --scripts --suggests --triggers --xml --recommends - --supplements --filetriggers --licensefiles" + --supplements --filetriggers --licensefiles + ) if [[ ${words[*]} == *\ -@(*([^ -])f|-file )* ]]; then # -qf completion if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W "$opts --dbpath --fscontext - --last --root --state" -- "$cur")) + _comp_compgen -- -W '"${opts[@]}" --dbpath --fscontext + --last --root --state' else - _filedir + _comp_compgen_filedir fi elif [[ ${words[*]} == *\ -@(*([^ -])g|-group )* ]]; then # -qg completion - _rpm_groups $1 + _comp_cmd_rpm__groups "$1" elif [[ ${words[*]} == *\ -@(*([^ -])p|-package )* ]]; then # -qp; uninstalled package completion if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W "$opts --ftpport --ftpproxy - --httpport --httpproxy --nomanifest" -- "$cur")) + _comp_compgen -- -W '"${opts[@]}" --ftpport --ftpproxy + --httpport --httpproxy --nomanifest' else - _filedir '[rs]pm' + _comp_compgen_filedir '[rs]pm' fi else # -q; installed package completion if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W "$opts --all --file --fileid + _comp_compgen -- -W '"${opts[@]}" --all --file --fileid --dbpath --fscontext --ftswalk --group --hdrid --last --package --pkgid --root= --specfile --state --triggeredby --whatenhances --whatprovides --whatrecommends --whatrequires --whatsuggests - --whatsupplements" \ - -- "$cur")) + --whatsupplements' elif [[ ${words[*]} != *\ -@(*([^ -])a|-all )* ]]; then - _rpm_installed_packages $1 + _comp_cmd_rpm__compgen_installed_packages "$1" fi fi ;; -K* | --checksig) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W "$opts --nopgp --nogpg --nomd5" \ - -- "$cur")) + _comp_compgen -- -W '"${opts[@]}" --nopgp --nogpg --nomd5' else - _filedir '[rs]pm' + _comp_compgen_filedir '[rs]pm' fi ;; -[Vy]* | --verify) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W "$opts --root= --dbpath --nodeps + _comp_compgen -- -W '"${opts[@]}" --root= --dbpath --nodeps --nogroup --nolinkto --nomode --nomtime --nordev --nouser --nofiles --noscripts --nomd5 --querytags --specfile --whatenhances --whatprovides --whatrecommends - --whatrequires --whatsuggests --whatsupplements" \ - -- "$cur")) + --whatrequires --whatsuggests --whatsupplements' # check whether we're doing file completion elif [[ ${words[*]} == *\ -@(*([^ -])f|-file )* ]]; then - _filedir + _comp_compgen_filedir elif [[ ${words[*]} == *\ -@(*([^ -])g|-group )* ]]; then - _rpm_groups $1 + _comp_cmd_rpm__groups "$1" elif [[ ${words[*]} == *\ -@(*([^ -])p|-package )* ]]; then - _filedir '[rs]pm' + _comp_compgen_filedir '[rs]pm' else - _rpm_installed_packages $1 + _comp_cmd_rpm__compgen_installed_packages "$1" fi ;; --resign | --addsign | --delsign) - _filedir '[rs]pm' + _comp_compgen_filedir '[rs]pm' ;; --setperms | --setgids) - _rpm_installed_packages $1 + _comp_cmd_rpm__compgen_installed_packages "$1" ;; --import | --dbpath | --root) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--import --dbpath --root=' \ - -- "$cur")) + _comp_compgen -- -W '--import --dbpath --root=' else - _filedir + _comp_compgen_filedir fi ;; esac [[ ${COMPREPLY-} == *= ]] && compopt -o nospace } && - complete -F _rpm rpm + complete -F _comp_cmd_rpm rpm -_rpmbuild() +_comp_cmd_rpmbuild() { - local cur prev words cword split - _init_completion -s || return - - local rpm="${1%build*}" - [[ $rpm == "$1" ]] || ! type $rpm &>/dev/null && rpm= + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[rED]*)' + # shellcheck disable=SC2119,SC2254 case $prev in - --buildroot | --root | --dbpath | -!(-*)r) - _filedir -d + --buildroot | --root | --dbpath | -${noargopts}r) + _comp_compgen_filedir -d return ;; + --target | --eval | -${noargopts}E | --buildpolicy) + # Prefer `rpm` in the same dir in utility functions + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + ;;& --target) - _rpm_buildarchs $rpm + _comp_cmd_rpm__buildarchs return ;; - --eval | -!(-*)E) - _rpm_macros $rpm + --eval | -${noargopts}E) + _comp_cmd_rpm__macros return ;; --macros | --rcfile) - _filedir + _comp_compgen_filedir return ;; --buildpolicy) - local cfgdir=$($rpm --eval '%{_rpmconfigdir}' 2>/dev/null) + local cfgdir + _comp_cmd_rpm__configdir if [[ $cfgdir ]]; then - COMPREPLY=($(compgen -W "$(command ls $cfgdir 2>/dev/null | - command sed -ne 's/^brp-//p')" -- "$cur")) + _comp_compgen_split -- "$(command ls "$cfgdir" 2>/dev/null | + command sed -ne 's/^brp-//p')" fi ;; - --define | --with | --without | -!(-*)D) + --define | --with | --without | -${noargopts}D) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W "$(_parse_help "$1")" -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi @@ -295,8 +315,8 @@ _rpmbuild() ;; esac done - [[ -n $ext ]] && _filedir $ext + [[ $ext ]] && _comp_compgen_filedir "$ext" } && - complete -F _rpmbuild rpmbuild rpmbuild-md5 + complete -F _comp_cmd_rpmbuild rpmbuild rpmbuild-md5 # ex: filetype=sh diff --git a/completions/rpm2tgz b/completions/rpm2tgz index 5ddcfd5..552a3a1 100644 --- a/completions/rpm2tgz +++ b/completions/rpm2tgz @@ -1,17 +1,17 @@ # Slackware rpm2tgz completion -*- shell-script -*- -_rpm2tgz() +_comp_cmd_rpm2tgz() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-s -S -n -r -d -c' -- "$cur")) + _comp_compgen -- -W '-s -S -n -r -d -c' return fi - _filedir "rpm" + _comp_compgen_filedir "rpm" } && - complete -F _rpm2tgz rpm2tgz rpm2txz rpm2targz + complete -F _comp_cmd_rpm2tgz rpm2tgz rpm2txz rpm2targz # ex: filetype=sh diff --git a/completions/rpmcheck b/completions/rpmcheck index cf4ed95..d7d0348 100644 --- a/completions/rpmcheck +++ b/completions/rpmcheck @@ -1,24 +1,24 @@ # bash completion for rpmcheck -*- shell-script -*- -_rpmcheck() +_comp_cmd_rpmcheck() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -base) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-explain -failures -successes -dump - -dump-all -base -help -compressed-input' -- "$cur")) + _comp_compgen -- -W '-explain -failures -successes -dump -dump-all + -base -help -compressed-input' else - _filedir + _comp_compgen_filedir fi } && - complete -F _rpmcheck rpmcheck + complete -F _comp_cmd_rpmcheck rpmcheck # ex: filetype=sh diff --git a/completions/rrdtool b/completions/rrdtool index dcb9ce6..8f85687 100644 --- a/completions/rrdtool +++ b/completions/rrdtool @@ -1,17 +1,17 @@ # bash completion for rrdtool -*- shell-script -*- -_rrdtool() +_comp_cmd_rrdtool() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if ((${#words[@]} == 2)); then - COMPREPLY=($(compgen -W 'create update updatev graph dump restore - last lastupdate first info fetch tune resize xport' -- "$cur")) + _comp_compgen -- -W 'create update updatev graph dump restore last + lastupdate first info fetch tune resize xport' else - _filedir rrd + _comp_compgen_filedir rrd fi } && - complete -F _rrdtool rrdtool + complete -F _comp_cmd_rrdtool rrdtool # ex: filetype=sh diff --git a/completions/rsync b/completions/rsync index 0bf5389..f471b46 100644 --- a/completions/rsync +++ b/completions/rsync @@ -1,67 +1,75 @@ # bash completion for rsync -*- shell-script -*- -_rsync() +_comp_cmd_rsync() { - local cur prev words cword split - _init_completion -s -n : || return + local cur prev words cword was_split comp_args + _comp_initialize -s -n : -- "$@" || return + local noargopts='!(-*|*[Te]*)' + # shellcheck disable=SC2254 case $prev in - --config | --password-file | --include-from | --exclude-from | --files-from | \ - --log-file | --write-batch | --only-write-batch | --read-batch) + --config | --password-file | --include-from | --exclude-from | \ + --files-from | --log-file | --write-batch | --only-write-batch | \ + --read-batch) compopt +o nospace - _filedir + _comp_compgen_filedir return ;; - --temp-dir | --compare-dest | --backup-dir | --partial-dir | --copy-dest | \ - --link-dest | -!(-*)T) + --temp-dir | --compare-dest | --backup-dir | --partial-dir | \ + --copy-dest | --link-dest | -${noargopts}T) compopt +o nospace - _filedir -d + _comp_compgen_filedir -d return ;; - --rsh | -!(-*)e) + --rsh | -${noargopts}e) compopt +o nospace - COMPREPLY=($(compgen -W 'rsh ssh' -- "$cur")) + _comp_compgen -- -W 'rsh ssh' return ;; --compress-level) compopt +o nospace - COMPREPLY=($(compgen -W '{1..9}' -- "$cur")) + _comp_compgen -- -W '{1..9}' + return + ;; + --info) + _comp_delimited , -W ' + backup{,0} + copy{,0} + del{,0} + flist{,0,1,2} + misc{,0,1,2} + mount{,0} + name{,0,1,2} + nonreg{,0,1} + progress{,0,1,2} + remove{,0} + skip{,0,1,2} + stats{,0,1,2,3} + symsafe{,0} + all{,0,1,2,3,4} + none + help + ' return ;; esac - $split && return + [[ $was_split ]] && return - _expand || return + _comp_expand || return case $cur in -*) - COMPREPLY=($(compgen -W '--verbose --quiet --no-motd --checksum - --archive --recursive --relative --no-implied-dirs - --backup --backup-dir= --suffix= --update --inplace --append - --append-verify --dirs --old-dirs --links --copy-links - --copy-unsafe-links --safe-links --copy-dirlinks - --keep-dirlinks --hard-links --perms --executability --chmod= - --acls --xattrs --owner --group --devices --copy-devices - --specials --times --omit-dir-times --super --fake-super - --sparse --dry-run --whole-file --no-whole-file - --one-file-system --block-size= --rsh= --rsync-path= - --existing --ignore-existing --remove-source-files --delete - --delete-before --delete-during --delete-delay --delete-after - --delete-excluded --ignore-errors --force --max-delete= - --max-size= --min-size= --partial --partial-dir= - --delay-updates --prune-empty-dirs --numeric-ids --timeout= - --contimeout= --ignore-times --size-only --modify-window= - --temp-dir= --fuzzy --compare-dest= --copy-dest= --link-dest= - --compress --compress-level= --skip-compress= --cvs-exclude - --filter= --exclude= --exclude-from= --include= --include-from= - --files-from= --from0 --protect-args --address= --port= - --sockopts= --blocking-io --no-blocking-io --stats - --8-bit-output --human-readable --progress --itemize-changes - --out-format= --log-file= --log-file-format= --password-file= - --list-only --bwlimit= --write-batch= --only-write-batch= - --read-batch= --protocol= --iconv= --ipv4 --ipv6 --version - --help --daemon --config= --no-detach' -- "$cur")) + local tmp + # Account for the fact that older rsync versions (before cba00be6, + # meaning before v3.2.0) contain the following unusual line in + # --help: + # "(-h) --help show this help (-h is --help only if used alone)" + _comp_compgen -Rv tmp help - <<<"$("$1" --help 2>&1 | command sed -e 's/^([^)]*)//')" + + _comp_compgen -- -W '"${tmp[@]}" + --daemon --old-d{,irs} + --no-{blocking-io,detach,whole-file,inc-recursive,i-r}' -X '--no-OPTION' [[ ${COMPREPLY-} == *= ]] || compopt +o nospace ;; *:*) @@ -73,14 +81,14 @@ _rsync() break fi done - [[ $shell == ssh ]] && _xfunc ssh _scp_remote_files + [[ $shell == ssh ]] && _comp_compgen -x scp remote_files ;; *) - _known_hosts_real -c -a -- "$cur" - _xfunc ssh _scp_local_files + _comp_compgen_known_hosts -c -a -- "$cur" + _comp_compgen -ax scp local_files ;; esac } && - complete -F _rsync -o nospace rsync + complete -F _comp_cmd_rsync -o nospace rsync # ex: filetype=sh diff --git a/completions/sbcl b/completions/sbcl index 22a93e4..f74f841 100644 --- a/completions/sbcl +++ b/completions/sbcl @@ -2,20 +2,20 @@ # bash programmable completion for various Common Lisp implementations by # Nikodemus Siivola <nikodemus@random-state.net> -_sbcl() +_comp_cmd_sbcl() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return # completing an option (may or may not be separated by a space) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--core --noinform --help --version - --sysinit --userinit --eval --noprint --disable-debugger - --end-runtime-options --end-toplevel-options ' -- "$cur")) + _comp_compgen -- -W '--core --noinform --help --version --sysinit + --userinit --eval --noprint --disable-debugger + --end-runtime-options --end-toplevel-options' else - _filedir + _comp_compgen_filedir fi } && - complete -F _sbcl sbcl sbcl-mt + complete -F _comp_cmd_sbcl sbcl sbcl-mt # ex: filetype=sh diff --git a/completions/sbopkg b/completions/sbopkg index 16bd58f..a2fc5a6 100644 --- a/completions/sbopkg +++ b/completions/sbopkg @@ -1,31 +1,30 @@ # bash completion for sbopkg(8) -*- shell-script -*- -_sbopkg() +_comp_cmd_sbopkg() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur")) + _comp_compgen_help -- -h [[ ${COMPREPLY-} ]] && return fi case "$prev" in -e) - COMPREPLY=($(compgen -W 'ask continue stop' -- "$cur")) + _comp_compgen -- -W 'ask continue stop' return ;; -f) - _filedir + _comp_compgen_filedir return ;; -d) - _filedir -d + _comp_compgen_filedir -d return ;; -V) - COMPREPLY=($(compgen -W "? - $(sbopkg -V '?' 2>&1 | cut -s -f1)" -- "$cur")) + _comp_compgen_split -- "? $(sbopkg -V '?' 2>&1 | cut -s -f1)" return ;; -i | -b) ;; @@ -35,20 +34,20 @@ _sbopkg() ;; esac - local i config + local i REPLY config config="/etc/sbopkg/sbopkg.conf" - for ((i = ${#words[@]} - 1; i > 0; i--)); do + for ((i = ${#words[@]} - 2; i > 0; i--)); do if [[ ${words[i]} == -f ]]; then - config="${words[i + 1]}" - __expand_tilde_by_ref config + _comp_expand_tilde "${words[i + 1]}" + config=$REPLY break fi done - [[ -r $config ]] || return - . $config + [[ -f $config && -r $config ]] || return + . "$config" - for ((i = 1; i < ${#words[@]}; i++)); do + for ((i = 1; i < ${#words[@]} - 1; i++)); do case "${words[i]}" in -V) REPO_NAME="${words[i + 1]%%/*}" @@ -59,15 +58,13 @@ _sbopkg() ;; esac done - [[ -r $REPO_ROOT/$REPO_NAME/$REPO_BRANCH/SLACKBUILDS.TXT ]] || return + local file=${REPO_ROOT-}/${REPO_NAME-}/${REPO_BRANCH-}/SLACKBUILDS.TXT + [[ -f $file && -r $file ]] || return - COMPREPLY=($(command sed -ne "/^SLACKBUILD NAME: $cur/{s/^SLACKBUILD NAME: //;p}" \ - $REPO_ROOT/$REPO_NAME/$REPO_BRANCH/SLACKBUILDS.TXT) - $( - cd $QUEUEDIR - compgen -f -X "!*.sqf" -- "$cur" - )) + _comp_compgen_split -l -- "$(command sed -ne "s/^SLACKBUILD NAME: //p" \ + "$file")" + _comp_compgen -aC "$QUEUEDIR" -- -f -X "!*.sqf" } && - complete -F _sbopkg sbopkg + complete -F _comp_cmd_sbopkg sbopkg # ex: filetype=sh diff --git a/completions/screen b/completions/screen index 651ca2c..ab4b7dd 100644 --- a/completions/screen +++ b/completions/screen @@ -1,12 +1,13 @@ # bash completion for screen -*- shell-script -*- -_screen_sessions() +_comp_cmd_screen__sessions() { - local sessions=($(command screen -ls | command sed -ne \ - 's|^\t\{1,\}\([0-9]\{1,\}\.[^\t]\{1,\}\).*'"$1"'.*$|\1|p')) + local -a sessions + _comp_split sessions "$(command screen -ls | command sed -ne \ + 's|^\t\{1,\}\([0-9]\{1,\}\.[^\t]\{1,\}\).*'"$1"'.*$|\1|p')" || return if [[ $cur == +([0-9])?(.*) ]]; then # Complete sessions including pid prefixes - COMPREPLY=($(compgen -W '${sessions[@]}' -- "$cur")) + _comp_compgen -- -W '"${sessions[@]}"' else # Create unique completions, dropping pids where possible local -A res @@ -17,26 +18,22 @@ _screen_sessions() for i in "${!res[@]}"; do [[ ${res[i]} == \ *\ * ]] && tmp+=" ${res[i]}" || tmp+=" $i" done - COMPREPLY=($(compgen -W '$tmp' -- "$cur")) + _comp_compgen -- -W '$tmp' fi } && - _screen() + _comp_cmd_screen() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if ((cword == 1)); then if [[ $cur == /dev* ]]; then - COMPREPLY=($(compgen -W "$( - shopt -s nullglob - printf '%s\n' \ - /dev/serial/by-id/* /dev/ttyUSB* /dev/ttyACM* 2>/dev/null - )" \ - -- "$cur")) + _comp_expand_glob COMPREPLY '/dev/serial/*/* /dev/ttyUSB* /dev/ttyACM*' && + _comp_compgen -- -W '"${COMPREPLY[@]}"' return fi if [[ $cur == //* ]]; then - COMPREPLY=($(compgen -W '//telnet' -- "$cur")) + _comp_compgen -- -W '//telnet' return fi fi @@ -44,14 +41,14 @@ _screen_sessions() case ${words[1]} in /dev*) if ((cword == 2)); then - COMPREPLY=($(compgen -W '110 300 600 1200 2400 4800 9600 \ - 14400 19200 38400 57600 115200 128000 256000' -- "$cur")) + _comp_compgen -- -W '110 300 600 1200 2400 4800 9600 14400 + 19200 38400 57600 115200 128000 256000' # TODO more, comma separated options fi return ;; //telnet) - ((cword == 2)) && _known_hosts_real -- "$cur" + ((cword == 2)) && _comp_compgen_known_hosts -- "$cur" return ;; esac @@ -59,7 +56,7 @@ _screen_sessions() if ((cword > 2)); then case ${words[cword - 2]} in -*[dD]) - _screen_sessions + _comp_cmd_screen__sessions return ;; esac @@ -77,36 +74,36 @@ _screen_sessions() ;; esac - _command_offset $i + _comp_command_offset $i return done case $prev in -*[rR]) # list detached - _screen_sessions 'Detached' + _comp_cmd_screen__sessions 'Detached' return ;; -*[dD]) # list attached - _screen_sessions 'Attached' + _comp_cmd_screen__sessions 'Attached' return ;; -*x) # list both - _screen_sessions + _comp_cmd_screen__sessions return ;; -*s) - _shells + _comp_compgen_shells return ;; -*c) - _filedir + _comp_compgen_filedir return ;; -T) - _terms + _comp_compgen_terms return ;; -*[ehpSt]) @@ -115,9 +112,9 @@ _screen_sessions() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help fi } && - complete -F _screen screen + complete -F _comp_cmd_screen screen # ex: filetype=sh diff --git a/completions/scrub b/completions/scrub index bbb37be..f989211 100644 --- a/completions/scrub +++ b/completions/scrub @@ -1,36 +1,38 @@ # scrub(1) completion -*- shell-script -*- -_scrub() +_comp_cmd_scrub() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[bsDpX]*)' + # shellcheck disable=SC2254 case $prev in - --version | --help | --blocksize | --device-size | --dirent | -!(-*)[vhbsD]) + --version | --help | --blocksize | --device-size | --dirent | \ + -${noargopts}[vhbsD]) return ;; - --pattern | -!(-*)p) - COMPREPLY=($(compgen -W '$("$1" --help 2>&1 | - awk "/^Available/{flag=1;next}/^ /&&flag{print \$1}")' \ - -- "$cur")) + --pattern | -${noargopts}p) + _comp_compgen_split -- "$("$1" --help 2>&1 | + _comp_awk '/^Available/{flag=1;next}/^ /&&flag{print $1}')" return ;; - --freespace | -!(-*)X) - _filedir -d + --freespace | -${noargopts}X) + _comp_compgen_filedir -d return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir + _comp_compgen_filedir } && - complete -F _scrub scrub + complete -F _comp_cmd_scrub scrub # ex: filetype=sh diff --git a/completions/secret-tool b/completions/secret-tool index 5462fc0..e8aafd8 100644 --- a/completions/secret-tool +++ b/completions/secret-tool @@ -1,50 +1,50 @@ # bash completion for secret-tool(1) -*- shell-script -*- -_secret_tool() +_comp_cmd_secret_tool() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return - $split && return + [[ $was_split ]] && return local -i i - local mode word + local mode="" has_mode="" word for i in ${!words[*]}; do if [[ $i -gt 0 && ${words[i]} != -* ]]; then - ((i != cword)) && mode=${words[i]} + ((i != cword)) && mode=${words[i]} has_mode=set break fi done - if [[ ! -v mode ]]; then - local -a modes - modes=($("$1" nonexistent-mode 2>&1 | + if [[ ! $has_mode ]]; then + # generate modes + _comp_compgen_split -- "$("$1" nonexistent-mode 2>&1 | while read -r first second third rest; do if [[ $first == "${1##*/}" ]]; then printf "%s\n" "$second" elif [[ $first == usage: && $second == "${1##*/}" ]]; then printf "%s\n" "$third" fi - done)) - COMPREPLY=($(compgen -W '${modes[@]}' -- "$cur")) + done)" return fi case $mode in store) if [[ ${words[*]} != *\ --label[\ =]* ]]; then - COMPREPLY=($(compgen -W "--label=" -- "$cur")) + _comp_compgen -- -W "--label=" [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi ;; search) local -A opts=([--all]="" [--unlock]="") for word in "${words[@]:2}"; do - [[ $word ]] && unset opts["$word"] + [[ $word ]] && unset -v 'opts[$word]' done - COMPREPLY=($(compgen -W '${opts[@]}' -- "$cur")) + ((${#opts[@]})) && + _comp_compgen -- -W '"${!opts[@]}"' ;; esac } && - complete -F _secret_tool secret-tool + complete -F _comp_cmd_secret_tool secret-tool # ex: filetype=sh diff --git a/completions/sh b/completions/sh index 5624ffa..5581bcc 100644 --- a/completions/sh +++ b/completions/sh @@ -1,36 +1,35 @@ # POSIX sh(1) completion -*- shell-script -*- -_sh() +_comp_cmd_sh() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -c) return ;; -o | +o) - COMPREPLY=($(compgen -W 'allexport errexit ignoreeof monitor - noclobber noglob noexec nolog notify nounset verbose vi - xtrace' -- "$cur")) + _comp_compgen -- -W 'allexport errexit ignoreeof monitor noclobber + noglob noexec nolog notify nounset verbose vi xtrace' return ;; esac local opts="-a -b -C -e -f -h -i -m -n -o -u -v -x" if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W "$opts -c -s" -- "$cur")) + _comp_compgen -- -W "$opts -c -s" return elif [[ $cur == +* ]]; then - COMPREPLY=($(compgen -W "${opts//-/+}" -- "$cur")) + _comp_compgen -- -W "${opts//-/+}" return fi - local args ext= - _count_args "" "@(-c|[-+]o)" - ((args == 1)) && ext="sh" - _filedir $ext + local REPLY ext= + _comp_count_args -a "@(-c|[-+]o)" + ((REPLY == 1)) && ext="sh" + _comp_compgen_filedir $ext } && - complete -F _sh sh + complete -F _comp_cmd_sh sh # ex: filetype=sh diff --git a/completions/sha256sum b/completions/sha256sum new file mode 100644 index 0000000..adef1cd --- /dev/null +++ b/completions/sha256sum @@ -0,0 +1,38 @@ +# bash completion for sha256(1) and friends -*- shell-script -*- + +_comp_cmd_sha256sum() +{ + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + + case $prev in + -h | --help | --version) + return + ;; + esac + + [[ $was_split ]] && return + + if [[ $cur == -* ]]; then + _comp_complete_longopt "$@" + return + fi + + local sumtype=${1##*/} + sumtype=${sumtype%sum} + + local opt + for opt in "${words[@]}"; do + if [[ $opt == -@(c|-check) ]]; then + _comp_compgen_filedir "$sumtype" + return + fi + done + + local files + _comp_compgen -v files filedir && + _comp_compgen -- -X "*.$sumtype" -W '"${files[@]}"' +} && + complete -F _comp_cmd_sha256sum b2sum md5sum sha{,1,224,256,384,512}sum + +# ex: filetype=sh diff --git a/completions/shellcheck b/completions/shellcheck index 6421d7b..dc14c07 100644 --- a/completions/shellcheck +++ b/completions/shellcheck @@ -1,63 +1,65 @@ # bash completion for shellcheck(1) -*- shell-script -*- -_shellcheck_optarg() +_comp_cmd_shellcheck__optarg() { local args=$("$1" --help 2>&1 | - command sed -e 's/,/ /g' -ne 's/^.*'$2'\>.*(\([^)]*\)).*/\1/p') - COMPREPLY+=($(compgen -W '$args' -- "$cur")) + command sed -e 's/,/ /g' -ne 's/^.*'"$2"'\>.*(\([^)]*\)).*/\1/p') + _comp_compgen -a -- -W '$args' } -_shellcheck() +_comp_cmd_shellcheck() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[eifCsoPW]*)' + # shellcheck disable=SC2254 case $prev in - --version | -!(-*)V*) + --version | -${noargopts}V*) return ;; - --exclude | --include | -!(-*)[ei]) + --exclude | --include | -${noargopts}[ei]) return ;; - --format | -!(-*)f) + --format | -${noargopts}f) local args=$("$1" --format=nonexistent-format /dev/null 2>&1 | command sed -ne '/^Supported formats/,//p' | command sed -ne '/^[[:space:]]/p') - COMPREPLY=($(compgen -W '$args' -- "$cur")) + _comp_compgen -- -W '$args' return ;; - --color | -!(-*)C) - _shellcheck_optarg "$1" --color + --color | -${noargopts}C) + _comp_cmd_shellcheck__optarg "$1" --color return ;; - --shell | -!(-*)s) - _shellcheck_optarg "$1" --shell + --shell | -${noargopts}s) + _comp_cmd_shellcheck__optarg "$1" --shell return ;; - --enable | -!(-*)o) - COMPREPLY=($(compgen -W 'all' -- "$cur")) # TODO others? + --enable | -${noargopts}o) + _comp_compgen -- -W 'all' # TODO others? return ;; - --source-path | -!(-*)P) - _filedir -d - COMPREPLY+=($(compgen -W 'SCRIPTDIR' -- "$cur")) + --source-path | -${noargopts}P) + _comp_compgen_filedir -d + _comp_compgen -a -- -W 'SCRIPTDIR' return ;; - --wiki-link-count | -!(-*)W) + --wiki-link-count | -${noargopts}W) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir + _comp_compgen_filedir } && - complete -F _shellcheck shellcheck + complete -F _comp_cmd_shellcheck shellcheck # ex: filetype=sh diff --git a/completions/sitecopy b/completions/sitecopy index 8515687..87e8775 100644 --- a/completions/sitecopy +++ b/completions/sitecopy @@ -3,31 +3,33 @@ # 2011 Raphaël Droz <raphael.droz+floss@gmail.com> # License: GNU GPL v2 or later -_sitecopy() +_comp_cmd_sitecopy() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[dgrp]*)' + # shellcheck disable=SC2254 case $prev in - --debug | -!(-*)d) - COMPREPLY=($(compgen -W "socket files rcfile ftp http httpbody - rsh sftp xml xmlparse cleartext" -- "$cur")) + --debug | -${noargopts}d) + _comp_compgen -- -W 'socket files rcfile ftp http httpbody rsh sftp + xml xmlparse cleartext' compopt -o nospace return ;; - --logfile | --rcfile | -!(-*)[gr]) - _filedir + --logfile | --rcfile | -${noargopts}[gr]) + _comp_compgen_filedir return ;; - --storepath | -!(-*)p) - _filedir -d + --storepath | -${noargopts}p) + _comp_compgen_filedir -d return ;; esac case $cur in --*) - COMPREPLY=($(compgen -W "$(_parse_help $1)" -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return ;; @@ -41,10 +43,10 @@ _sitecopy() esac if [[ -r ~/.sitecopyrc ]]; then - COMPREPLY=($(compgen -W "$($1 -v | - command sed -n '/^Site:/s/Site: //p')" -- "$cur")) + _comp_compgen_split -- "$("$1" -v | + command sed -n '/^Site:/s/Site: //p')" fi } && - complete -F _sitecopy -o default sitecopy + complete -F _comp_cmd_sitecopy -o default sitecopy # ex: filetype=sh diff --git a/completions/slackpkg b/completions/slackpkg deleted file mode 100644 index 1d87928..0000000 --- a/completions/slackpkg +++ /dev/null @@ -1,112 +0,0 @@ -# bash completion for slackpkg(8) -*- shell-script -*- -# options list is based on `grep '\-.*\=.*)' /usr/sbin/slackpkg | cut -f1 -d\)` - -_slackpkg() -{ - local cur prev words cword - _init_completion -n = || return - - local split=false - if [[ $cur == -?*=* ]]; then - prev="${cur%%?(\\)=*}" - cur="${cur#*=}" - split=true - fi - - case "$prev" in - -delall | -checkmd5 | -checkgpg | -checksize | -postinst | -onoff | -download_all | \ - -dialog | -batch | -only_new_dotnew | -use_includes | -spinning) - COMPREPLY=($(compgen -W 'on off' -- "$cur")) - return - ;; - -default_answer) - COMPREPLY=($(compgen -W 'yes no' -- "$cur")) - return - ;; - -dialog_maxargs | -mirror) - # argument required but no completions available - return - ;; - esac - - $split && return - - if [[ $cur == -* ]]; then - compopt -o nospace - COMPREPLY=($(compgen -W '-delall= -checkmd5= -checkgpg= - -checksize= -postinst= -onoff= -download_all= -dialog= - -dialog_maxargs= -batch= -only_new_dotnew= -use_includes= - -spinning= -default_answer= -mirror=' -- "$cur")) - return - fi - - local confdir="/etc/slackpkg" - local config="$confdir/slackpkg.conf" - - [[ -r $config ]] || return - . "$config" - - local i action - for ((i = 1; i < ${#words[@]}; i++)); do - if [[ ${words[i]} != -* ]]; then - action="${words[i]}" - break - fi - done - - case "$action" in - generate-template | search | file-search) - # argument required but no completions available - return - ;; - install-template | remove-template) - if [[ -e $confdir/templates ]]; then - COMPREPLY=($( - cd "$confdir/templates" - compgen -f -X "!*.template" -- "$cur" - )) - COMPREPLY=(${COMPREPLY[@]%.template}) - fi - return - ;; - remove) - _filedir - COMPREPLY+=($(compgen -W 'a ap d e f k kde kdei l n t tcl x - xap xfce y' -- "$cur")) - COMPREPLY+=($( - cd /var/log/packages - compgen -f -- "$cur" - )) - return - ;; - install | reinstall | upgrade | blacklist | download) - _filedir - COMPREPLY+=($(compgen -W 'a ap d e f k kde kdei l n t tcl x - xap xfce y' -- "$cur")) - COMPREPLY+=($(cut -f 6 -d\ "${WORKDIR}/pkglist" 2>/dev/null | - command grep "^$cur")) - return - ;; - info) - COMPREPLY=($(cut -f 6 -d\ "${WORKDIR}/pkglist" 2>/dev/null | - command grep "^$cur")) - return - ;; - update) - # we should complete the same as the next `list` + "gpg" - COMPREPLY=($(compgen -W 'gpg' -- "$cur")) - ;& - *) - COMPREPLY+=($(compgen -W 'install reinstall upgrade remove - blacklist download update install-new upgrade-all - clean-system new-config check-updates help generate-template - install-template remove-template search file-search info' -- \ - "$cur")) - return - ;; - esac - -} && - complete -F _slackpkg slackpkg - -# ex: filetype=sh diff --git a/completions/slapt-get b/completions/slapt-get index 14c2dbe..1dc09e0 100644 --- a/completions/slapt-get +++ b/completions/slapt-get @@ -1,13 +1,13 @@ # slapt-get(8) completion -*- shell-script -*- -_slapt_get() +_comp_cmd_slapt_get() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case "$prev" in --config | -c) - _filedir + _comp_compgen_filedir return ;; --retry | --search) @@ -17,7 +17,7 @@ _slapt_get() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" --help)' -- "$cur")) + _comp_compgen_help if [[ ${COMPREPLY-} ]]; then [[ $COMPREPLY == *= ]] && compopt -o nospace return @@ -25,7 +25,8 @@ _slapt_get() fi local i t - # search for last action (--install|--install-set|--remove|--show|--filelist) + # search for last action + # (--install|--install-set|--remove|--show|--filelist) for ((i = ${#words[@]} - 1; i > 0; i--)); do if [[ ${words[i]} == --show ]]; then t="all" @@ -46,8 +47,9 @@ _slapt_get() # search for config for ((i = ${#words[@]} - 1; i > 0; i--)); do if [[ ${words[i]} == -@(c|-config) ]]; then - config="${words[i + 1]}" - __expand_tilde_by_ref config + local REPLY + _comp_expand_tilde "${words[i + 1]-}" + config=$REPLY break fi done @@ -58,29 +60,29 @@ _slapt_get() # slapt-get will fail to search for "^name-version" # it can search for names only local name=${cur%%-*} - COMPREPLY=($(LC_ALL=C "$1" -c "$config" --search "^$name" \ - 2>/dev/null | LC_ALL=C command sed -ne "/^$cur/{s/ .*$//;p}")) + _comp_compgen_split -l -- "$( + LC_ALL=C "$1" -c "$config" --search "^$name" 2>/dev/null | + LC_ALL=C command sed -ne "/^$cur/{s/ .*$//;p;}" + )" return ;; avl) # --install|-i| - COMPREPLY=($(LC_ALL=C "$1" -c "$config" --available \ - 2>/dev/null | LC_ALL=C command sed -ne "/^$cur/{s/ .*$//;p}")) + _comp_compgen_split -l -- "$( + LC_ALL=C "$1" -c "$config" --available 2>/dev/null | + LC_ALL=C command sed -ne "/^$cur/{s/ .*$//;p;}" + )" return ;; ins) # --remove|--filelist - COMPREPLY=($( - cd /var/log/packages - compgen -f -- "$cur" - )) + _comp_compgen -C /var/log/packages -- -f return ;; set) # --install-set - COMPREPLY=($(compgen -W 'a ap d e f k kde kdei l n t tcl x - xap xfce y' -- "$cur")) + _comp_compgen -- -W 'a ap d e f k kde kdei l n t tcl x xap xfce y' return ;; esac } && - complete -F _slapt_get slapt-get + complete -F _comp_cmd_slapt_get slapt-get # ex: filetype=sh diff --git a/completions/slapt-src b/completions/slapt-src index 1e3828c..cdf00c2 100644 --- a/completions/slapt-src +++ b/completions/slapt-src @@ -1,13 +1,13 @@ # slapt-src(8) completion -*- shell-script -*- -_slapt_src() +_comp_cmd_slapt_src() { - local cur prev words cword split - _init_completion -s -n : || return + local cur prev words cword was_split comp_args + _comp_initialize -s -n : -- "$@" || return case "$prev" in --config | -c) - _filedir + _comp_compgen_filedir return ;; --search | -s | --postprocess | -p) @@ -16,17 +16,17 @@ _slapt_src() ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" --help)' -- "$cur")) + _comp_compgen_help if [[ ${COMPREPLY-} ]]; then [[ $COMPREPLY == *= ]] && compopt -o nospace return fi fi - local i t + local i t="" # search for last action (-i|-w|-b|-f) for ((i = ${#words[@]} - 1; i > 0; i--)); do if [[ ${words[i]} == -@([iwfb]|-install|-show|-build|-fetch) ]]; then @@ -42,8 +42,9 @@ _slapt_src() # search for config for ((i = ${#words[@]} - 1; i > 0; i--)); do if [[ ${words[i]} == -@(c|-config) ]]; then - config="${words[i + 1]}" - __expand_tilde_by_ref config + local REPLY + _comp_expand_tilde "${words[i + 1]-}" + config=$REPLY break fi if [[ ${words[i]} == --config=?* ]]; then @@ -55,14 +56,19 @@ _slapt_src() if [[ $cur == *:* ]]; then local name=${cur%:*} - COMPREPLY=($(LC_ALL=C "$1" --config "$config" --search "^$name" \ - 2>/dev/null | LC_ALL=C command sed -ne \ - "/^$cur/{s/^$name:\([^ ]*\) .*$/\1/;p}")) + _comp_compgen_split -l -- "$( + LC_ALL=C + "$1" --config "$config" --search "^$name" 2>/dev/null | + command sed -ne "/^$cur/{s/^$name:\([^ ]*\) .*$/\1/;p;}" + )" else - COMPREPLY=($(LC_ALL=C "$1" --config "$config" --search "^$cur" \ - 2>/dev/null | LC_ALL=C command sed -ne "/^$cur/{s/ .*$//;p}")) + _comp_compgen_split -l -- "$( + LC_ALL=C + "$1" --config "$config" --search "^$cur" 2>/dev/null | + command sed -ne "/^$cur/{s/ .*$//;p;}" + )" fi } && - complete -F _slapt_src slapt-src + complete -F _comp_cmd_slapt_src slapt-src # ex: filetype=sh diff --git a/completions/smartctl b/completions/smartctl index ee45a7c..376ceb8 100644 --- a/completions/smartctl +++ b/completions/smartctl @@ -1,26 +1,17 @@ # bash completion for smartctl(8) -*- shell-script -*- -_smartctl_quietmode() -{ - COMPREPLY=($(compgen -W 'errorsonly silent noserial' -- "$cur")) -} -_smartctl_device() +_comp_cmd_smartctl__device() { case $cur in areca* | 3ware* | megaraid* | cciss*) - # shellcheck disable=SC2054 - COMPREPLY+=(${cur%%,*},{0..31}) - COMPREPLY=($(compgen -W '"${COMPREPLY[@]}"' -- "$cur")) + _comp_compgen -- -W '${cur%%,*},{0..31}' ;; hpt*) - # shellcheck disable=SC2054 - COMPREPLY+=(hpt,{1..4}/{1..8} hpt,{1..4}/{1..8}/{1..5}) - COMPREPLY=($(compgen -W '"${COMPREPLY[@]}"' -- "$cur")) + _comp_compgen -- -W 'hpt,{1..4}/{1..8} hpt,{1..4}/{1..8}/{1..5}' ;; *) - COMPREPLY=($(compgen -W "ata scsi sat usbcypress usbjmicron - usbsunplus marvell areca 3ware hpt megaraid cciss auto test" \ - -- "$cur")) + _comp_compgen -- -W 'ata scsi sat usbcypress usbjmicron usbsunplus + marvell areca 3ware hpt megaraid cciss auto test' case "${COMPREPLY[@]}" in areca | 3ware | hpt | megaraid | cciss) compopt -o nospace @@ -29,137 +20,101 @@ _smartctl_device() ;; esac } -_smartctl_tolerance() -{ - COMPREPLY=($(compgen -W 'normal conservative permissive verypermissive' \ - -- "$cur")) -} -_smartctl_badsum() -{ - COMPREPLY=($(compgen -W 'warn exit ignore' -- "$cur")) -} -_smartctl_report() -{ - COMPREPLY=($(compgen -W 'ioctl ataioctl scsiioctl' -- "$cur")) -} -_smartctl_powermode() -{ - COMPREPLY=($(compgen -W 'never sleep standby idle' -- "$cur")) -} -_smartctl_feature() -{ - COMPREPLY=($(compgen -W 'on off' -- "$cur")) -} -_smartctl_log() -{ - COMPREPLY=($(compgen -W 'error selftest selective directory background - sasphy sasphy,reset sataphy sataphy,reset scttemp scttempsts - scttemphist scterc gplog smartlog xerror xselftest' -- "$cur")) -} -_smartctl_vendorattribute() -{ - COMPREPLY=($(compgen -W 'help 9,minutes 9,seconds 9,halfminutes 9,temp - 192,emergencyretractcyclect 193,loadunload 194,10xCelsius 194,unknown - 198,offlinescanuncsectorct 200,writeerrorcount 201,detectedtacount - 220,temp' -- "$cur")) -} -_smartctl_firmwarebug() -{ - COMPREPLY=($(compgen -W 'none samsung samsung2 samsung3 swapid' \ - -- "$cur")) -} -_smartctl_presets() -{ - COMPREPLY=($(compgen -W 'use ignore show showall' -- "$cur")) -} -_smartctl_test() +_comp_cmd_smartctl__test() { [[ $cur == @(pending|scttempint|vendor), ]] && return - COMPREPLY=($(compgen -W 'offline short long conveyance select, - select,redo select,next afterselect,on afterselect,off pending, - scttempint, vendor,' -- "$cur")) + _comp_compgen -- -W 'offline short long conveyance select, select,redo + select,next afterselect,on afterselect,off pending, scttempint, + vendor,' [[ ${COMPREPLY-} == *, ]] && compopt -o nospace } -_smartctl_drivedb() +_comp_cmd_smartctl__drivedb() { local prefix= if [[ $cur == +* ]]; then prefix=+ cur="${cur#+}" fi - _filedir h - [[ -n $prefix ]] && COMPREPLY=("${COMPREPLY[@]/#/$prefix}") + _comp_compgen_filedir h && [[ $prefix ]] && + _comp_compgen -Rv COMPREPLY -- -P "$prefix" -W '"${COMPREPLY[@]}"' } -_smartctl() +_comp_cmd_smartctl() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[qdTbrnsoSlvFPBt]*)' + # shellcheck disable=SC2254 case $prev in - --quietmode | -!(-*)q) - _smartctl_quietmode + --quietmode | -${noargopts}q) + _comp_compgen -- -W 'errorsonly silent noserial' + return ;; - --device | -!(-*)d) - _smartctl_device + --device | -${noargopts}d) + _comp_cmd_smartctl__device return ;; - --tolerance | -!(-*)T) - _smartctl_tolerance + --tolerance | -${noargopts}T) + _comp_compgen -- -W 'normal conservative permissive verypermissive' return ;; - --badsum | -!(-*)b) - _smartctl_badsum + --badsum | -${noargopts}b) + _comp_compgen -- -W 'warn exit ignore' return ;; - --report | -!(-*)r) - _smartctl_report + --report | -${noargopts}r) + _comp_compgen -- -W 'ioctl ataioctl scsiioctl' return ;; - --nocheck | -!(-*)n) - _smartctl_powermode + --nocheck | -${noargopts}n) + _comp_compgen -- -W 'never sleep standby idle' return ;; - --smart | --offlineauto | --saveauto | -!(-*)[soS]) - _smartctl_feature + --smart | --offlineauto | --saveauto | -${noargopts}[soS]) + _comp_compgen -- -W 'on off' return ;; - --log | -!(-*)l) - _smartctl_log + --log | -${noargopts}l) + _comp_compgen -- -W 'error selftest selective directory background + sasphy sasphy,reset sataphy sataphy,reset scttemp scttempsts + scttemphist scterc gplog smartlog xerror xselftest' return ;; - --vendorattribute | -!(-*)v) - _smartctl_vendorattribute + --vendorattribute | -${noargopts}v) + _comp_compgen -- -W 'help 9,minutes 9,seconds 9,halfminutes 9,temp + 192,emergencyretractcyclect 193,loadunload 194,10xCelsius + 194,unknown 198,offlinescanuncsectorct 200,writeerrorcount + 201,detectedtacount 220,temp' return ;; - --firmwarebug | -!(-*)F) - _smartctl_firmwarebug + --firmwarebug | -${noargopts}F) + _comp_compgen -- -W 'none samsung samsung2 samsung3 swapid' return ;; - --presets | -!(-*)P) - _smartctl_presets + --presets | -${noargopts}P) + _comp_compgen -- -W 'use ignore show showall' return ;; - --drivedb | -!(-*)B) - _smartctl_drivedb + --drivedb | -${noargopts}B) + _comp_cmd_smartctl__drivedb return ;; - --test | -!(-*)t) - _smartctl_test + --test | -${noargopts}t) + _comp_cmd_smartctl__test return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - cur=${cur:=/dev/} - _filedir + _comp_compgen -c "${cur:-/dev/}" filedir fi } && - complete -F _smartctl smartctl + complete -F _comp_cmd_smartctl smartctl # ex: filetype=sh diff --git a/completions/smbclient b/completions/smbclient index cea2107..bd2deeb 100644 --- a/completions/smbclient +++ b/completions/smbclient @@ -1,242 +1,248 @@ # bash completion for samba -*- shell-script -*- -_samba_resolve_order() +_comp_cmd_smbclient__resolve_order() { - COMPREPLY=($(compgen -W 'lmhosts host wins bcast' -- "$cur")) + _comp_compgen -- -W 'lmhosts host wins bcast' } -_samba_domains() +_comp_cmd_smbclient__domains() { - if [[ -n ${COMP_SAMBA_SCAN:-} ]]; then - COMPREPLY=($(compgen -W '$(smbtree -N -D)' -- "$cur")) + if [[ ${BASH_COMPLETION_CMD_SMBTREE_SCAN-${COMP_SAMBA_SCAN-}} ]]; then + _comp_compgen_split -- "$(smbtree -N -D)" fi } -_samba_hosts() +_comp_cmd_smbclient__hosts() { - if [[ -n ${COMP_SAMBA_SCAN:-} ]]; then - COMPREPLY=($(compgen -W "$( - smbtree -N -S | - command sed -ne 's/^[[:space:]]*\\\\*\([^[:space:]]*\).*/\1/p' - )" -- "$cur")) + if [[ ${BASH_COMPLETION_CMD_SMBTREE_SCAN-${COMP_SAMBA_SCAN-}} ]]; then + _comp_compgen_split -- "$(smbtree -N -S | + command sed -ne 's/^[[:space:]]*\\\\*\([^[:space:]]*\).*/\1/p')" fi } -_samba_debuglevel() +_comp_cmd_smbclient__debuglevel() { - COMPREPLY=($(compgen -W '{0..10}' -- "$cur")) + _comp_compgen -- -W '{0..10}' } -_samba_sockopts() +_comp_cmd_smbclient__sockopts() { - COMPREPLY=($(compgen -W 'SO_KEEPALIVE SO_REUSEADDR SO_BROADCAST - TCP_NODELAY IPTOS_LOWDELAY IPTOS_THROUGHPUT SO_SNDBUF SO_RCVBUF - SO_SNDLOWAT SO_RCVLOWAT' -- "$cur")) + _comp_compgen -- -W 'SO_KEEPALIVE SO_REUSEADDR SO_BROADCAST TCP_NODELAY + IPTOS_LOWDELAY IPTOS_THROUGHPUT SO_SNDBUF SO_RCVBUF SO_SNDLOWAT + SO_RCVLOWAT' } -_samba_signing() +_comp_cmd_smbclient__signing() { - COMPREPLY=($(compgen -W 'on off required' -- "$cur")) + _comp_compgen -- -W 'on off required' } -_smbclient() +_comp_cmd_smbclient() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[RtsAlDOTWdLSpMIbUniTcm]*)' + # shellcheck disable=SC2254 case $prev in - --name-resolve | -!(-*)R) - _samba_resolve_order + --name-resolve | -${noargopts}R) + _comp_cmd_smbclient__resolve_order return ;; - -!(-*)t) - COMPREPLY=($(compgen -W 'SJIS EUC JIS7 JIS8 JUNET HEX CAP' \ - -- "$cur")) + -${noargopts}t) + _comp_compgen -- -W 'SJIS EUC JIS7 JIS8 JUNET HEX CAP' return ;; - --configfile | --authentication-file | -!(-*)[sA]) - _filedir + --configfile | --authentication-file | -${noargopts}[sA]) + _comp_compgen_filedir return ;; - --log-basename | --directory | -!(-*)[lD]) - _filedir -d + --log-basename | --directory | -${noargopts}[lD]) + _comp_compgen_filedir -d return ;; - --socket-options | -!(-*)O) - _samba_sockopts + --socket-options | -${noargopts}O) + _comp_cmd_smbclient__sockopts return ;; - -!(-*)T) - COMPREPLY=($(compgen -W 'c x I X F b g q r N a' -- "$cur")) + -${noargopts}T) + _comp_compgen -- -W 'c x I X F b g q r N a' return ;; - --workgroup | -!(-*)W) - _samba_domains + --workgroup | -${noargopts}W) + _comp_cmd_smbclient__domains return ;; - --debuglevel | -!(-*)d) - _samba_debuglevel + --debuglevel | -${noargopts}d) + _comp_cmd_smbclient__debuglevel return ;; - --list | -!(-*)L) - _samba_hosts + --list | -${noargopts}L) + _comp_cmd_smbclient__hosts return ;; - --signing | -!(-*)S) - _samba_signing + --signing | -${noargopts}S) + _comp_cmd_smbclient__signing return ;; - --port | --message | --ip-address | --send-buffer | --user | --netbiosname | \ - --scope | --tar | --command | --max-protocol | -!(-*)[pMIbUniTcm]) + --port | --message | --ip-address | --send-buffer | --user | \ + --netbiosname | --scope | --tar | --command | --max-protocol | \ + -${noargopts}[pMIbUniTcm]) return ;; - --help | --version | -!(-*)[?V]) + --help | --version | -${noargopts}[?V]) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _smbclient smbclient + complete -F _comp_cmd_smbclient smbclient -_smbget() +_comp_cmd_smbget() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[ofdwupb]*)' + # shellcheck disable=SC2254 case $prev in - --outputfile | --rcfile | -!(-*)[of]) - _filedir + --outputfile | --rcfile | -${noargopts}[of]) + _comp_compgen_filedir return ;; - --debuglevel | -!(-*)d) - _samba_debuglevel + --debuglevel | -${noargopts}d) + _comp_cmd_smbclient__debuglevel return ;; - --workgroup | -!(-*)w) - _samba_domains + --workgroup | -${noargopts}w) + _comp_cmd_smbclient__domains return ;; - --username | --password | --blocksize | -!(-*)[upb]) + --username | --password | --blocksize | -${noargopts}[upb]) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _smbget smbget + complete -F _comp_cmd_smbget smbget -_smbcacls() +_comp_cmd_smbcacls() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[AsldOWDMaSCGniU]*)' + # shellcheck disable=SC2254 case $prev in - --configfile | --authentication-file | -!(-*)[As]) - _filedir + --configfile | --authentication-file | -${noargopts}[As]) + _comp_compgen_filedir return ;; - --log-basename | -!(-*)l) - _filedir -d + --log-basename | -${noargopts}l) + _comp_compgen_filedir -d return ;; - --debuglevel | -!(-*)d) - _samba_debuglevel + --debuglevel | -${noargopts}d) + _comp_cmd_smbclient__debuglevel return ;; --signing) - _samba_signing + _comp_cmd_smbclient__signing return ;; - --socket-options | -!(-*)O) - _samba_sockopts + --socket-options | -${noargopts}O) + _comp_cmd_smbclient__sockopts return ;; - --workgroup | -!(-*)W) - _samba_domains + --workgroup | -${noargopts}W) + _comp_cmd_smbclient__domains return ;; - --help | --usage | --delete | --modify | --add | --set | --chown | --chgrp | \ - --netbiosname | --scope | --user | -!(-*)[?DMaSCGniU]) + --help | --usage | --delete | --modify | --add | --set | --chown | \ + --chgrp | --netbiosname | --scope | --user | -${noargopts}[?DMaSCGniU]) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _smbcacls smbcacls + complete -F _comp_cmd_smbcacls smbcacls -_smbcquotas() +_comp_cmd_smbcquotas() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[sAldUuS]*)' + # shellcheck disable=SC2254 case $prev in - --configfile | --authentication-file | -!(-*)[sA]) - _filedir + --configfile | --authentication-file | -${noargopts}[sA]) + _comp_compgen_filedir return ;; - --log-basename | -!(-*)l) - _filedir -d + --log-basename | -${noargopts}l) + _comp_compgen_filedir -d return ;; - --debuglevel | -!(-*)d) - _samba_debuglevel + --debuglevel | -${noargopts}d) + _comp_cmd_smbclient__debuglevel return ;; --signing) - _samba_signing + _comp_cmd_smbclient__signing return ;; - --help | --usage | --user | --set | -!(-*)[?UuS]) + --help | --usage | --user | --set | -${noargopts}[?UuS]) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _smbcquotas smbcquotas + complete -F _comp_cmd_smbcquotas smbcquotas -_smbpasswd() +_comp_cmd_smbpasswd() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*r) - _samba_hosts + _comp_cmd_smbclient__hosts return ;; -*R) - _samba_resolve_order + _comp_cmd_smbclient__resolve_order return ;; -*c) - _filedir + _comp_compgen_filedir return ;; -*D) - _samba_debuglevel + _comp_cmd_smbclient__debuglevel return ;; -*[Uhw]) @@ -245,31 +251,31 @@ _smbpasswd() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur")) + _comp_compgen_help -- -h fi } && - complete -F _smbpasswd smbpasswd + complete -F _comp_cmd_smbpasswd smbpasswd -_smbtar() +_comp_cmd_smbtar() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*[rt]) - _filedir tar + _comp_compgen_filedir tar return ;; -*s) - _samba_hosts + _comp_cmd_smbclient__hosts return ;; -*l) - _samba_debuglevel + _comp_cmd_smbclient__debuglevel return ;; -*N) - _filedir + _comp_compgen_filedir return ;; -*[pxbdu]) @@ -278,45 +284,47 @@ _smbtar() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help fi } && - complete -F _smbtar smbtar + complete -F _comp_cmd_smbtar smbtar -_smbtree() +_comp_cmd_smbtree() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[sAldSU]*)' + # shellcheck disable=SC2254 case $prev in - --configfile | --authentication-file | -!(-*)[sA]) - _filedir + --configfile | --authentication-file | -${noargopts}[sA]) + _comp_compgen_filedir return ;; - --log-basename | -!(-*)l) - _filedir -d + --log-basename | -${noargopts}l) + _comp_compgen_filedir -d return ;; - --debuglevel | -!(-*)d) - _samba_debuglevel + --debuglevel | -${noargopts}d) + _comp_cmd_smbclient__debuglevel return ;; - --signing | -!(-*)S) - _samba_signing + --signing | -${noargopts}S) + _comp_cmd_smbclient__signing return ;; - --help | --usage | --user | -!(-*)[?U]) + --help | --usage | --user | -${noargopts}[?U]) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _smbtree smbtree + complete -F _comp_cmd_smbtree smbtree # ex: filetype=sh diff --git a/completions/snownews b/completions/snownews index 5b585d9..a767a6c 100644 --- a/completions/snownews +++ b/completions/snownews @@ -1,15 +1,15 @@ # snownews(1) completion -*- shell-script -*- -_snownews() +_comp_cmd_snownews() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then # return list of available options - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help fi } && - complete -F _snownews snownews + complete -F _comp_cmd_snownews snownews # ex: filetype=sh diff --git a/completions/sqlite3 b/completions/sqlite3 index 26d38a1..d1393bf 100644 --- a/completions/sqlite3 +++ b/completions/sqlite3 @@ -1,24 +1,23 @@ # sqlite3(1) completion -*- shell-script -*- -_sqlite3() +_comp_cmd_sqlite3() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local dbexts='@(sqlite?(3)|?(s?(3))db)' case $prev in - -help | -version | -lookaside | -mmap | -newline | -nullvalue | -pagecache | \ - -scratch | -separator | *.$dbexts) + -help | -version | -lookaside | -maxsize | -mmap | -newline | \ + -nullvalue | -pagecache | -scratch | -separator | -vfs | *.$dbexts) return ;; -init) - _filedir + _comp_compgen_filedir return ;; -cmd) - compopt -o filenames - COMPREPLY=($(compgen -c -- "$cur")) + _comp_compgen_commands return ;; esac @@ -27,12 +26,12 @@ _sqlite3() return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help return fi - _filedir "$dbexts" + _comp_compgen_filedir "$dbexts" } && - complete -F _sqlite3 sqlite3 + complete -F _comp_cmd_sqlite3 sqlite3 # ex: filetype=sh diff --git a/completions/ss b/completions/ss index 4a27d51..e383fe5 100644 --- a/completions/ss +++ b/completions/ss @@ -1,41 +1,43 @@ # ss(8) completion -*- shell-script -*- -_ss() +_comp_cmd_ss() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[fADF]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | -!(-*)[hV]) + --help | --version | -${noargopts}[hV]) return ;; - --family | -!(-*)f) - COMPREPLY=($(compgen -W 'unix inet inet6 link netlink' \ - -- "$cur")) + --family | -${noargopts}f) + _comp_compgen -- -W 'unix inet inet6 link netlink' return ;; - --query | -!(-*)A) - local prefix= - [[ $cur == *,* ]] && prefix="${cur%,*}," - COMPREPLY=($(compgen -W '$("$1" --help | \ - command sed -e "s/|/ /g" -ne "s/.*QUERY := {\([^}]*\)}.*/\1/p")' \ - -- "${cur##*,}")) - ((${#COMPREPLY[@]} == 1)) && COMPREPLY=(${COMPREPLY/#/$prefix}) + --query | -${noargopts}A) + local queries=$("$1" --help | + command sed -e 's/|/ /g' -ne 's/.*QUERY := {\([^}]*\)}.*/\1/p') + _comp_delimited , -W '$queries' return ;; - --diag | --filter | -!(-*)[DF]) - _filedir + --diag | --filter | -${noargopts}[DF]) + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace + elif [[ $prev == state ]]; then + _comp_compgen -- -W 'all connected synchronized bucket big established + syn-sent syn-recv fin-wait-{1,2} time-wait closed close-wait + last-ack listening closing' fi } && - complete -F _ss ss + complete -F _comp_cmd_ss ss # ex: filetype=sh diff --git a/completions/ssh b/completions/ssh index 907c039..386fd25 100644 --- a/completions/ssh +++ b/completions/ssh @@ -1,195 +1,229 @@ # ssh(1) completion -*- shell-script -*- -_ssh_queries() +_comp_cmd_ssh__compgen_queries() { - COMPREPLY+=($(compgen -W \ - "cipher cipher-auth help mac kex key key-cert key-plain key-sig - protocol-version compression sig - ciphers macs kexalgorithms pubkeyacceptedkeytypes - hostkeyalgorithms hostbasedkeytypes hostbasedacceptedkeytypes" \ - -- "${cur,,}")) + local -a queries + _comp_compgen -v queries -i ssh query "$1" help || + queries=(cipher cipher-auth mac kex key key-cert key-plain key-sig + protocol-version compression sig ciphers macs kexalgorithms + pubkeyacceptedkeytypes hostkeyalgorithms hostbasedkeytypes + hostbasedacceptedkeytypes) + _comp_compgen -c "${cur,,}" -U queries -- -W '"${queries[@]}" help' } +# @since 2.12 +_comp_xfunc_ssh_compgen_query() +{ + _comp_cmd_ssh__compgen_query ssh "$1" +} + +# @deprecated 2.12 use _comp_xfunc_ssh_compgen_query _ssh_query() { - ${1:-ssh} -Q $2 2>/dev/null + local -a queries=() + _comp_compgen -v queries -i ssh query "${1:-ssh}" "$2" && + printf "%s\n" "${queries[@]}" } -_ssh_ciphers() +_comp_cmd_ssh__compgen_query() { - local ciphers='$(_ssh_query "$1" cipher)' - [[ $ciphers ]] || ciphers="3des-cbc aes128-cbc aes192-cbc aes256-cbc - aes128-ctr aes192-ctr aes256-ctr arcfour128 arcfour256 arcfour - blowfish-cbc cast128-cbc" - COMPREPLY+=($(compgen -W "$ciphers" -- "$cur")) + _comp_compgen_split -- "$("$1" -Q "$2" 2>/dev/null)" } -_ssh_macs() +_comp_cmd_ssh__compgen_ciphers() { - local macs='$(_ssh_query "$1" mac)' - [[ $macs ]] || macs="hmac-md5 hmac-sha1 umac-64@openssh.com hmac-ripemd160 - hmac-sha1-96 hmac-md5-96" - COMPREPLY+=($(compgen -W "$macs" -- "$cur")) + local -a queries + _comp_compgen -v queries -i ssh query "$1" cipher || + queries=(3des-cbc aes128-cbc aes192-cbc aes256-cbc aes128-ctr + aes192-ctr aes256-ctr arcfour128 arcfour256 arcfour blowfish-cbc + cast128-cbc) + _comp_compgen -U queries -- -W '"${queries[@]}"' } -_ssh_options() +_comp_cmd_ssh__compgen_macs() { - local opts=( - AddKeysToAgent AddressFamily BatchMode BindAddress CanonicalDomains - CanonicalizeFallbackLocal CanonicalizeHostname CanonicalizeMaxDots - CanonicalizePermittedCNAMEs CASignatureAlgorithms CertificateFile - ChallengeResponseAuthentication CheckHostIP Ciphers ClearAllForwardings - Compression ConnectionAttempts ConnectTimeout ControlMaster ControlPath - ControlPersist DynamicForward EnableSSHKeysign EscapeChar - ExitOnForwardFailure FingerprintHash ForwardAgent ForwardX11 - ForwardX11Timeout ForwardX11Trusted GatewayPorts GlobalKnownHostsFile - GSSAPIAuthentication GSSAPIClientIdentity GSSAPIDelegateCredentials - GSSAPIKeyExchange GSSAPIRenewalForcesRekey GSSAPIServerIdentity - GSSAPITrustDns HashKnownHosts Host HostbasedAuthentication - HostbasedKeyTypes HostKeyAlgorithms HostKeyAlias HostName + local -a queries + _comp_compgen -v queries -i ssh query "$1" mac || + queries=(hmac-md5 hmac-sha1 umac-64@openssh.com hmac-ripemd160 + hmac-sha1-96 hmac-md5-96) + _comp_compgen -U queries -- -W '"${queries[@]}"' +} + +# @since 2.12 +_comp_xfunc_ssh_compgen_options() +{ + # curl --silent https://raw.githubusercontent.com/openssh/openssh-portable/master/ssh_config.5 | _comp_awk '$1==".It" && $2=="Cm" && $3!="Host" && $3!="Match" {print " "$3}' | sort + local _opts=( + AddKeysToAgent AddressFamily BatchMode BindAddress BindInterface + CanonicalDomains CanonicalizeFallbackLocal CanonicalizeHostname + CanonicalizeMaxDots CanonicalizePermittedCNAMEs CASignatureAlgorithms + CertificateFile ChallengeResponseAuthentication CheckHostIP Ciphers + ClearAllForwardings Compression ConnectionAttempts ConnectTimeout + ControlMaster ControlPath ControlPersist DynamicForward + EnableSSHKeysign EscapeChar ExitOnForwardFailure FingerprintHash + ForwardAgent ForwardX11 ForwardX11Timeout ForwardX11Trusted + GatewayPorts GlobalKnownHostsFile GSSAPIAuthentication + GSSAPIDelegateCredentials HashKnownHosts HostbasedAuthentication + HostbasedKeyTypes HostKeyAlgorithms HostKeyAlias Hostname IdentitiesOnly IdentityAgent IdentityFile IgnoreUnknown Include IPQoS KbdInteractiveAuthentication KbdInteractiveDevices KexAlgorithms LocalCommand LocalForward LogLevel MACs NoHostAuthenticationForLocalhost NumberOfPasswordPrompts PasswordAuthentication PermitLocalCommand PKCS11Provider Port PreferredAuthentications ProxyCommand ProxyJump ProxyUseFdpass - PubkeyAcceptedKeyTypes PubkeyAuthentication RekeyLimit RemoteCommand - RemoteForward RequestTTY RevokedHostKeys SendEnv ServerAliveCountMax - ServerAliveInterval SmartcardDevice StreamLocalBindMask - StreamLocalBindUnlink StrictHostKeyChecking SyslogFacility TCPKeepAlive - Tunnel TunnelDevice UpdateHostKeys UsePrivilegedPort User - UserKnownHostsFile VerifyHostKeyDNS VisualHostKey XAuthLocation) - local protocols=$(_ssh_query "$1" protocol-version) - if [[ -z $protocols || $protocols == *1* ]]; then - opts+=(Cipher CompressionLevel Protocol RhostsRSAAuthentication + PubkeyAcceptedAlgorithms PubkeyAuthentication RekeyLimit RemoteCommand + RemoteForward RequestTTY RequiredRSASize RevokedHostKeys + SecurityKeyProvider SendEnv ServerAliveCountMax ServerAliveInterval + SetEnv StreamLocalBindMask StreamLocalBindUnlink StrictHostKeyChecking + SyslogFacility TCPKeepAlive Tunnel TunnelDevice UpdateHostKeys User + UserKnownHostsFile VerifyHostKeyDNS VisualHostKey XAuthLocation + ) + # Selected old ones + _opts+=( + GSSAPIKeyExchange GSSAPIRenewalForcesRekey GSSAPIServerIdentity + GSSAPITrustDns PubkeyAcceptedKeyTypes SmartcardDevice UsePrivilegedPort + ) + local -a protocols + _comp_compgen -v protocols -i ssh query ssh protocol-version + if [[ ${protocols[*]-} == *1* ]]; then + _opts+=(Cipher CompressionLevel Protocol RhostsRSAAuthentication RSAAuthentication) fi + _comp_unlocal protocols compopt -o nospace - local IFS=$' \t\n' reset=$(shopt -p nocasematch) - shopt -s nocasematch - local option - COMPREPLY=($(for option in "${opts[@]}"; do - [[ $option == "$cur"* ]] && printf '%s=\n' "$option" - done)) - $reset + _comp_compgen_split -l -- "$( + shopt -s nocasematch + local option + for option in "${_opts[@]}"; do + [[ $option == "$cur"* ]] && printf '%s=\n' "$option" + done + )" } +_comp_deprecate_func 2.12 _ssh_options _comp_xfunc_ssh_compgen_options + # Complete a ssh suboption (like ForwardAgent=y<tab>) -# Two parameters: the string to complete including the equal sign, and -# the ssh executable to invoke (optional). +# @param $1 the ssh executable to invoke +# @param $2 the string to complete including the equal sign # Not all suboptions are completed. # Doesn't handle comma-separated lists. -_ssh_suboption() +_comp_cmd_ssh__compgen_suboption() { # Split into subopt and subval - local prev=${1%%=*} cur=${1#*=} + local _prev=${2%%=*} cur=${2#*=} - case ${prev,,} in + case ${_prev,,} in batchmode | canonicaldomains | canonicalizefallbacklocal | \ challengeresponseauthentication | checkhostip | \ - clearallforwardings | controlpersist | compression | enablesshkeysign | \ - exitonforwardfailure | forwardagent | forwardx11 | forwardx11trusted | \ - gatewayports | gssapiauthentication | gssapikeyexchange | \ - gssapidelegatecredentials | gssapirenewalforcesrekey | gssapitrustdns | \ - hashknownhosts | hostbasedauthentication | identitiesonly | \ - kbdinteractiveauthentication | kbdinteractivedevices | \ - nohostauthenticationforlocalhost | passwordauthentication | permitlocalcommand | \ - proxyusefdpass | pubkeyauthentication | rhostsrsaauthentication | \ + clearallforwardings | controlpersist | compression | \ + enablesshkeysign | exitonforwardfailure | forwardagent | \ + forwardx11 | forwardx11trusted | gatewayports | \ + gssapiauthentication | gssapikeyexchange | \ + gssapidelegatecredentials | gssapirenewalforcesrekey | \ + gssapitrustdns | hashknownhosts | hostbasedauthentication | \ + identitiesonly | kbdinteractiveauthentication | \ + kbdinteractivedevices | nohostauthenticationforlocalhost | \ + passwordauthentication | permitlocalcommand | proxyusefdpass | \ + pubkeyauthentication | rhostsrsaauthentication | \ rsaauthentication | streamlocalbindunlink | \ tcpkeepalive | useprivilegedport | visualhostkey) - COMPREPLY=($(compgen -W 'yes no' -- "$cur")) + _comp_compgen -- -W 'yes no' ;; addkeystoagent) - COMPREPLY=($(compgen -W 'yes ask confirm no' -- "$cur")) + _comp_compgen -- -W 'yes ask confirm no' ;; addressfamily) - COMPREPLY=($(compgen -W 'any inet inet6' -- "$cur")) + _comp_compgen -- -W 'any inet inet6' ;; bindaddress) - _ip_addresses + _comp_compgen_ip_addresses ;; canonicalizehostname) - COMPREPLY=($(compgen -W 'yes no always' -- "$cur")) + _comp_compgen -- -W 'yes no always' ;; identityfile) - _ssh_identityfile + _comp_xfunc_ssh_compgen_identityfile ;; - *file | identityagent | include | controlpath | revokedhostkeys | xauthlocation) - _filedir + *file | identityagent | include | controlpath | revokedhostkeys | \ + xauthlocation) + _comp_compgen_filedir ;; casignaturealgorithms) - COMPREPLY=($(compgen -W '$(_ssh_query "$2" sig)' -- "$cur")) + _comp_cmd_ssh__compgen_query "$1" sig ;; cipher) - COMPREPLY=($(compgen -W 'blowfish des 3des' -- "$cur")) + _comp_compgen -- -W 'blowfish des 3des' ;; ciphers) - _ssh_ciphers "$2" + _comp_cmd_ssh__compgen_ciphers "$1" ;; controlmaster) - COMPREPLY=($(compgen -W 'yes ask auto autoask no' -- "$cur")) + _comp_compgen -- -W 'yes ask auto autoask no' ;; compressionlevel) - COMPREPLY=($(compgen -W '{1..9}' -- "$cur")) + _comp_compgen -- -W '{1..9}' ;; fingerprinthash) - COMPREPLY=($(compgen -W 'md5 sha256' -- "$cur")) + _comp_compgen -- -W 'md5 sha256' ;; ipqos) - COMPREPLY=($(compgen -W 'af1{1..4} af2{2..3} af3{1..3} af4{1..3} - cs{0..7} ef lowdelay throughput reliability' -- "$cur")) + _comp_compgen -- -W 'af1{1..4} af2{2..3} af3{1..3} af4{1..3} + cs{0..7} ef lowdelay throughput reliability' ;; hostbasedkeytypes | hostkeyalgorithms) - COMPREPLY=($(compgen -W '$(_ssh_query "$2" key)' -- "$cur")) + _comp_cmd_ssh__compgen_query "$1" key ;; kexalgorithms) - COMPREPLY=($(compgen -W '$(_ssh_query "$2" kex)' -- "$cur")) + _comp_cmd_ssh__compgen_query "$1" kex ;; loglevel) - COMPREPLY=($(compgen -W 'QUIET FATAL ERROR INFO VERBOSE DEBUG{,1,2,3}' -- "$cur")) + _comp_compgen -- -W 'QUIET FATAL ERROR INFO VERBOSE DEBUG{,1,2,3}' ;; macs) - _ssh_macs "$2" + _comp_cmd_ssh__compgen_macs "$1" ;; pkcs11provider) - _filedir so + _comp_compgen_filedir so ;; preferredauthentications) - COMPREPLY=($(compgen -W 'gssapi-with-mic host-based publickey - keyboard-interactive password' -- "$cur")) + _comp_compgen -- -W 'gssapi-with-mic host-based publickey + keyboard-interactive password' ;; protocol) - local protocols=($(_ssh_query "$2" protocol-version)) - [[ $protocols ]] || protocols=(1 2) + local -a protocols + _comp_compgen -v protocols -i ssh query "$1" protocol-version + [[ ${protocols-} ]] || protocols=(1 2) if ((${#protocols[@]} > 1)); then - COMPREPLY=($(compgen -W '${protocols[@]}' -- "$cur")) + _comp_compgen -- -W '"${protocols[@]}"' fi ;; proxyjump) - _known_hosts_real -a ${configfile:+-F "$configfile"} -- "$cur" + _comp_compgen_known_hosts -a ${configfile:+-F "$configfile"} -- "$cur" ;; proxycommand | remotecommand | localcommand) - COMPREPLY=($(compgen -c -- "$cur")) + _comp_compgen_commands ;; - pubkeyacceptedkeytypes) - COMPREPLY=($(compgen -W '$(_ssh_query "$2" key)' -- "$cur")) + pubkeyacceptedalgorithms | pubkeyacceptedkeytypes) + _comp_cmd_ssh__compgen_query "$1" key ;; requesttty) - COMPREPLY=($(compgen -W 'no yes force auto' -- "$cur")) + _comp_compgen -- -W 'no yes force auto' + ;; + requiredrsasize) + _comp_compgen -- -W '1024 2048 3072 4096 7680 15360' ;; stricthostkeychecking) - COMPREPLY=($(compgen -W 'accept-new ask no off' -- "$cur")) + _comp_compgen -- -W 'accept-new ask no off' ;; syslogfacility) - COMPREPLY=($(compgen -W 'DAEMON USER AUTH LOCAL{0..7}' -- "$cur")) + _comp_compgen -- -W 'DAEMON USER AUTH LOCAL{0..7}' ;; tunnel) - COMPREPLY=($(compgen -W 'yes no point-to-point ethernet' \ - -- "$cur")) + _comp_compgen -- -W 'yes no point-to-point ethernet' ;; updatehostkeys | verifyhostkeydns) - COMPREPLY=($(compgen -W 'yes no ask' -- "$cur")) + _comp_compgen -- -W 'yes no ask' ;; esac return 0 @@ -198,28 +232,46 @@ _ssh_suboption() # Try to complete -o SubOptions= # # Returns 0 if the completion was handled or non-zero otherwise. -_ssh_suboption_check() +# @since 2.12 +_comp_xfunc_ssh_compgen_suboption_check() +{ + _comp_cmd_ssh__compgen_suboption_check ssh +} + +# @param $1 the ssh executable to invoke +_comp_cmd_ssh__compgen_suboption_check() { # Get prev and cur words without splitting on = - local cureq=$(_get_cword :=) preveq=$(_get_pword :=) - if [[ $cureq == *=* && $preveq == -*o ]]; then - _ssh_suboption $cureq "$1" + local cur prev + _comp_get_words -n := cur prev + if [[ $cur == *=* && $prev == -*o ]]; then + _comp_unlocal prev + _comp_cmd_ssh__compgen_suboption "$1" "$cur" return $? fi return 1 } +# @deprecated 2.12 use `_comp_xfunc_ssh_compgen_suboption_check` instead +_ssh_suboption_check() +{ + _comp_cmd_ssh__compgen_suboption_check "${1:-ssh}" +} + # Search COMP_WORDS for '-F configfile' or '-Fconfigfile' argument -_ssh_configfile() +# @var[out] configfile Found configfile, if any +_comp_cmd_ssh__configfile() { + configfile="" set -- "${words[@]}" while (($# > 0)); do if [[ $1 == -F* ]]; then + local REPLY if ((${#1} > 2)); then - configfile="$(dequote "${1:2}")" + _comp_dequote "${1:2}" && configfile=$REPLY else shift - [[ ${1-} ]] && configfile="$(dequote "$1")" + [[ ${1-} ]] && _comp_dequote "$1" && configfile=$REPLY fi break fi @@ -228,79 +280,86 @@ _ssh_configfile() } # With $1 set, look for public key files, else private +# @since 2.12 # shellcheck disable=SC2120 -_ssh_identityfile() +_comp_xfunc_ssh_compgen_identityfile() { - [[ -z $cur && -d ~/.ssh ]] && cur=~/.ssh/id - _filedir - if ((${#COMPREPLY[@]} > 0)); then - COMPREPLY=($(compgen -W '${COMPREPLY[@]}' \ - -X "${1:+!}*.pub" -- "$cur")) - fi + local cur=$cur tmp + [[ ! $cur && -d ~/.ssh ]] && cur=~/.ssh/id + _comp_compgen -v tmp -c "$cur" filedir && + _comp_compgen -U tmp -- -W '"${tmp[@]}"' -X "${1:+!}*.pub" } -_ssh() +_comp_deprecate_func 2.12 _ssh_identityfile _comp_xfunc_ssh_compgen_identityfile + +_comp_cmd_ssh() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return local configfile - _ssh_configfile + _comp_cmd_ssh__configfile - _ssh_suboption_check "$1" && return + _comp_cmd_ssh__compgen_suboption_check "$1" && return local ipvx + # Keep cases sorted the same they're in ssh's usage message + # (but do group ones with same arg completion) case $prev in + -*B) + _comp_compgen_available_interfaces -a + return + ;; -*b) - _ip_addresses + _comp_compgen_ip_addresses return ;; -*c) - _ssh_ciphers "$1" + _comp_cmd_ssh__compgen_ciphers "$1" return ;; -*[DeLpRW]) return ;; -*[EFS]) - _filedir + _comp_compgen_filedir return ;; - -*i) - _ssh_identityfile + -*I) + _comp_compgen_filedir so return ;; - -*I) - _filedir so + -*i) + _comp_xfunc_ssh_compgen_identityfile return ;; -*J) - _known_hosts_real -a ${configfile:+-F "$configfile"} -- "$cur" + _comp_compgen_known_hosts -a ${configfile:+-F "$configfile"} -- "$cur" return ;; -*l) - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u return ;; -*m) - _ssh_macs "$1" + _comp_cmd_ssh__compgen_macs "$1" return ;; -*O) - COMPREPLY=($(compgen -W 'check forward cancel exit stop' -- "$cur")) + _comp_compgen -- -W 'check forward cancel exit stop' return ;; -*o) - _ssh_options "$1" + _comp_xfunc_ssh_compgen_options "$1" return ;; -*Q) - _ssh_queries "$1" + _comp_cmd_ssh__compgen_queries "$1" return ;; -*w) - _available_interfaces + _comp_compgen_available_interfaces return ;; -*4*) @@ -312,67 +371,71 @@ _ssh() esac if [[ $cur == -F* ]]; then - cur=${cur#-F} - _filedir + _comp_compgen -c "${cur#-F}" filedir # Prefix completions with '-F' COMPREPLY=("${COMPREPLY[@]/#/-F}") - cur=-F$cur # Restore cur elif [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage else - _known_hosts_real ${ipvx-} -a ${configfile:+-F "$configfile"} -- "$cur" - - local args - _count_args - if ((args > 1)); then + local REPLY + # Keep glob sort in sync with cases above + _comp_count_args -n "=" -a "-*[BbcDeLpRWEFSIiJlmOoQw]" + if ((REPLY > 1)); then compopt -o filenames - COMPREPLY+=($(compgen -c -- "$cur")) + _comp_compgen_commands + else + _comp_compgen_known_hosts ${ipvx-} -a ${configfile:+-F "$configfile"} \ + -- "$cur" fi fi } && - shopt -u hostcomplete && complete -F _ssh ssh slogin autossh sidedoor + shopt -u hostcomplete && + complete -F _comp_cmd_ssh ssh slogin autossh sidedoor # sftp(1) completion # -_sftp() +_comp_cmd_sftp() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local configfile - _ssh_configfile + _comp_cmd_ssh__configfile - _ssh_suboption_check && return + # Prefer `ssh` from same dir for resolving options, etc + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH - local ipvx + _comp_xfunc_ssh_compgen_suboption_check && return + + local ipvx= case $prev in -*[BDlPRs]) return ;; -*[bF]) - _filedir + _comp_compgen_filedir return ;; -*i) - _ssh_identityfile + _comp_xfunc_ssh_compgen_identityfile return ;; -*c) - _ssh_ciphers + _comp_cmd_ssh__compgen_ciphers return ;; -*J) - _known_hosts_real -a ${configfile:+-F "$configfile"} -- "$cur" + _comp_compgen_known_hosts -a ${configfile:+-F "$configfile"} -- "$cur" return ;; -*o) - _ssh_options + _comp_xfunc_ssh_compgen_options return ;; -*S) - compopt -o filenames - COMPREPLY=($(compgen -c -- "$cur")) + _comp_compgen_commands return ;; -*4*) @@ -384,100 +447,119 @@ _sftp() esac if [[ $cur == -F* ]]; then - cur=${cur#-F} - _filedir + _comp_compgen -c "${cur#-F}" filedir # Prefix completions with '-F' COMPREPLY=("${COMPREPLY[@]/#/-F}") - cur=-F$cur # Restore cur elif [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage else - _known_hosts_real ${ipvx-} -a ${configfile:+-F "$configfile"} -- "$cur" + _comp_compgen_known_hosts ${ipvx:+"$ipvx"} -a ${configfile:+-F "$configfile"} -- "$cur" fi } && - shopt -u hostcomplete && complete -F _sftp sftp + shopt -u hostcomplete && complete -F _comp_cmd_sftp sftp # things we want to backslash escape in scp paths # shellcheck disable=SC2089 -_scp_path_esc='[][(){}<>"'"'"',:;^&!$=?`\\|[:space:]]' +_comp_cmd_scp__path_esc='[][(){}<>"'"'"',:;^&!$=?`\\|[:space:]]' # Complete remote files with ssh. If the first arg is -d, complete on dirs # only. Returns paths escaped with three backslashes. +# @since 2.12 # shellcheck disable=SC2120 -_scp_remote_files() +_comp_xfunc_scp_compgen_remote_files() { - local IFS=$'\n' - # remove backslash escape from the first colon cur=${cur/\\:/:} - local userhost=${cur%%?(\\):*} - local path=${cur#*:} + local _userhost=${cur%%?(\\):*} + local _path=${cur#*:} # unescape (3 backslashes to 1 for chars we escaped) # shellcheck disable=SC2090 - path=$(command sed -e 's/\\\\\\\('$_scp_path_esc'\)/\\\1/g' <<<"$path") + _path=$(command sed -e 's/\\\\\\\('"$_comp_cmd_scp__path_esc"'\)/\\\1/g' <<<"$_path") # default to home dir of specified user on remote host - if [[ -z $path ]]; then - path=$(ssh -o 'Batchmode yes' $userhost pwd 2>/dev/null) + if [[ ! $_path ]]; then + _path=$(ssh -o 'Batchmode yes' "$_userhost" pwd 2>/dev/null) fi - local files - if [[ $1 == -d ]]; then + local _files + if [[ ${1-} == -d ]]; then # escape problematic characters; remove non-dirs # shellcheck disable=SC2090 - files=$(ssh -o 'Batchmode yes' $userhost \ - command ls -aF1dL "$path*" 2>/dev/null | - command sed -e 's/'$_scp_path_esc'/\\\\\\&/g' -e '/[^\/]$/d') + _files=$(ssh -o 'Batchmode yes' "$_userhost" \ + command ls -aF1dL "$_path*" 2>/dev/null | + command sed -e 's/'"$_comp_cmd_scp__path_esc"'/\\\\\\&/g' -e '/[^\/]$/d') else # escape problematic characters; remove executables, aliases, pipes # and sockets; add space at end of file names # shellcheck disable=SC2090 - files=$(ssh -o 'Batchmode yes' $userhost \ - command ls -aF1dL "$path*" 2>/dev/null | - command sed -e 's/'$_scp_path_esc'/\\\\\\&/g' -e 's/[*@|=]$//g' \ + _files=$(ssh -o 'Batchmode yes' "$_userhost" \ + command ls -aF1dL "$_path*" 2>/dev/null | + command sed -e 's/'"$_comp_cmd_scp__path_esc"'/\\\\\\&/g' -e 's/[*@|=]$//g' \ -e 's/[^\/]$/& /g') fi - COMPREPLY+=($files) + _comp_compgen_split -l -- "$_files" } -# This approach is used instead of _filedir to get a space appended -# after local file/dir completions, and -o nospace retained for others. -# If first arg is -d, complete on directory names only. The next arg is -# an optional prefix to add to returned completions. -_scp_local_files() +# @deprecated 2.12 use `_comp_compgen -ax ssh remote_files` instead +_scp_remote_files() { - local IFS=$'\n' + _comp_compgen -ax scp remote_files +} - local dirsonly=false +# This approach is used instead of _comp_compgen_filedir to get a space +# appended after local file/dir completions, and -o nospace retained for +# others. If first arg is -d, complete on directory names only. The next arg +# is an optional prefix to add to returned completions. +# @since 2.12 +_comp_xfunc_scp_compgen_local_files() +{ + local _dirsonly="" if [[ ${1-} == -d ]]; then - dirsonly=true + _dirsonly=set shift fi - if $dirsonly; then - COMPREPLY+=($(command ls -aF1dL $cur* 2>/dev/null | - command sed -e "s/$_scp_path_esc/\\\\&/g" -e '/[^\/]$/d' -e "s/^/${1-}/")) + local files + _comp_expand_glob files '"$cur"*' || return 0 + if [[ $_dirsonly ]]; then + _comp_compgen -U files split -l -- "$( + command ls -aF1dL "${files[@]}" 2>/dev/null | + command sed -e "s/$_comp_cmd_scp__path_esc/\\\\&/g" \ + -e '/[^\/]$/d' -e "s/^/${1-}/" + )" else - COMPREPLY+=($(command ls -aF1dL $cur* 2>/dev/null | - command sed -e "s/$_scp_path_esc/\\\\&/g" -e 's/[*@|=]$//g' \ - -e 's/[^\/]$/& /g' -e "s/^/${1-}/")) + _comp_compgen -U files split -l -- "$( + command ls -aF1dL "${files[@]}" 2>/dev/null | + command sed -e "s/$_comp_cmd_scp__path_esc/\\\\&/g" \ + -e 's/[*@|=]$//g' -e 's/[^\/]$/& /g' -e "s/^/${1-}/" + )" fi } +# @deprecated 2.12 +_scp_local_files() +{ + _comp_compgen -ax scp local_files "$@" +} + # scp(1) completion # -_scp() +_comp_cmd_scp() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return local configfile - _ssh_configfile + _comp_cmd_ssh__configfile - _ssh_suboption_check && { - COMPREPLY=("${COMPREPLY[@]/%/ }") + # Prefer `ssh` from same dir for resolving options, remote files, etc + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + + _comp_xfunc_ssh_compgen_suboption_check && { + ((${#COMPREPLY[@]})) && COMPREPLY=("${COMPREPLY[@]/%/ }") return } @@ -485,34 +567,34 @@ _scp() case $prev in -*c) - _ssh_ciphers + _comp_cmd_ssh__compgen_ciphers COMPREPLY=("${COMPREPLY[@]/%/ }") return ;; -*F) - _filedir + _comp_compgen_filedir compopt +o nospace return ;; -*i) - _ssh_identityfile + _comp_xfunc_ssh_compgen_identityfile compopt +o nospace return ;; -*J) - _known_hosts_real -a ${configfile:+-F "$configfile"} -- "$cur" + _comp_compgen_known_hosts -a ${configfile:+-F "$configfile"} -- "$cur" return ;; -*[lP]) return ;; -*o) - _ssh_options + _comp_xfunc_ssh_compgen_options return ;; -*S) - compopt +o nospace -o filenames - COMPREPLY=($(compgen -c -- "$cur")) + compopt +o nospace + _comp_compgen_commands return ;; -*4*) @@ -523,12 +605,12 @@ _scp() ;; esac - _expand || return + _comp_expand || return case $cur in !(*:*)/* | [.~]*) ;; # looks like a path *:*) - _scp_remote_files + _comp_xfunc_scp_compgen_remote_files return ;; esac @@ -541,23 +623,21 @@ _scp() else case $cur in -*) - COMPREPLY=($(compgen -W '$(_parse_usage "${words[0]}")' \ - -- "$cur")) + _comp_compgen_usage COMPREPLY=("${COMPREPLY[@]/%/ }") return ;; - */* | [.~]*) - # not a known host, pass through - ;; *) - _known_hosts_real ${ipvx-} -c -a \ - ${configfile:+-F "$configfile"} -- "$cur" + if ! _comp_looks_like_path "$cur"; then + _comp_compgen_known_hosts ${ipvx-} -c -a \ + ${configfile:+-F "$configfile"} -- "$cur" + fi ;; esac fi - _scp_local_files "${prefix-}" + _comp_compgen -ax scp local_files "${prefix-}" } && - complete -F _scp -o nospace scp + complete -F _comp_cmd_scp -o nospace scp # ex: filetype=sh diff --git a/completions/ssh-add b/completions/ssh-add index d8f7492..23c73e0 100644 --- a/completions/ssh-add +++ b/completions/ssh-add @@ -1,35 +1,35 @@ # ssh-add(1) completion -*- shell-script -*- -_ssh_add() +_comp_cmd_ssh_add() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*E) - COMPREPLY=($(compgen -W 'md5 sha256' -- "$cur")) + _comp_compgen -- -W 'md5 sha256' return ;; -*t) return ;; -*T) - _filedir + _comp_compgen_filedir return ;; -*[se]) - _filedir so + _comp_compgen_filedir so return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" "-\?")' -- "$cur")) + _comp_compgen_help -- '-?' return fi - _filedir + _comp_compgen_filedir } && - complete -F _ssh_add ssh-add + complete -F _comp_cmd_ssh_add ssh-add # ex: filetype=sh diff --git a/completions/ssh-copy-id b/completions/ssh-copy-id index f628194..52aa9d7 100644 --- a/completions/ssh-copy-id +++ b/completions/ssh-copy-id @@ -1,32 +1,36 @@ # ssh-copy-id(1) completion -*- shell-script -*- -_ssh_copy_id() +_comp_cmd_ssh_copy_id() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return - _xfunc ssh _ssh_suboption_check "$1" && return + # Prefer `ssh` from same dir for resolving options, etc + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + + _comp_compgen -x ssh suboption_check && return case $prev in -i) - _xfunc ssh _ssh_identityfile pub + _comp_compgen -x ssh identityfile pub return ;; -p) return ;; -o) - _xfunc ssh _ssh_options + _comp_compgen -x ssh options return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1" --help)' -- "$cur")) + _comp_compgen_usage -- --help else - _known_hosts_real -a -- "$cur" + _comp_compgen_known_hosts -a -- "$cur" fi } && - complete -F _ssh_copy_id ssh-copy-id + complete -F _comp_cmd_ssh_copy_id ssh-copy-id # ex: filetype=sh diff --git a/completions/ssh-keygen b/completions/ssh-keygen index 0e629a5..3f9d175 100644 --- a/completions/ssh-keygen +++ b/completions/ssh-keygen @@ -1,16 +1,16 @@ # ssh-keygen(1) completion -*- shell-script -*- -_ssh_keygen() +_comp_cmd_ssh_keygen() { - local cur prev words cword - _init_completion -n := || return + local cur prev words cword comp_args + _comp_initialize -n := -- "$@" || return case $prev in -*[aCIJjMNPSVWz]) return ;; -*b) - local -a sizes + local -a sizes=() case "${words[*]}" in *" -t dsa"?( *)) sizes=(1024) @@ -22,102 +22,110 @@ _ssh_keygen() sizes=(1024 2048 3072 4096) ;; esac - COMPREPLY=($(compgen -W '${sizes[@]}' -- "$cur")) + ((${#sizes[@]})) && + _comp_compgen -- -W '"${sizes[@]}"' return ;; -*E) - COMPREPLY=($(compgen -W 'md5 sha256' -- "$cur")) + _comp_compgen -- -W 'md5 sha256' return ;; -*[FR]) # TODO: trim this down to actual entries in known hosts files - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; -*[Dw]) - _filedir so + _comp_compgen_filedir so return ;; -*[fGKsT]) - _filedir + _comp_compgen_filedir return ;; -*m) - COMPREPLY=($(compgen -W 'PEM PKCS8 RFC4716' -- "$cur")) + _comp_compgen -- -W 'PEM PKCS8 RFC4716' return ;; -*n) [[ ${words[*]} != *\ -*Y\ * ]] || return - local prefix= - [[ $cur == *,* ]] && prefix="${cur%,*}," if [[ ${words[*]} == *\ -*h\ * ]]; then - _known_hosts_real -- "${cur##*,}" + _comp_compgen_known_hosts -- "${cur##*,}" + ((${#COMPREPLY[@]})) && + _comp_delimited , -W '"${COMPREPLY[@]}"' else - COMPREPLY=($(compgen -u -- "${cur##*,}")) + _comp_delimited , -u fi - ((${#COMPREPLY[@]} == 1)) && COMPREPLY=(${COMPREPLY/#/$prefix}) return ;; -*O) if [[ $cur != *=* ]]; then - COMPREPLY=($(compgen -W ' - clear critical: extension: force-command= + _comp_compgen -- -W 'clear critical: extension: force-command= no-agent-forwarding no-port-forwarding no-pty no-user-rc no-x11-forwarding permit-agent-forwarding permit-port-forwarding permit-pty permit-user-rc permit-X11-forwarding no-touch-required source-address= + verify-required lines= start-line= checkpoint= memory= start= generator= - application challenge= device resident user - write-attestation-path - ' -- "$cur")) + application= challenge= device= no-touch-required resident + user= write-attestation=' + [[ ${COMPREPLY-} == *[:=] ]] && compopt -o nospace - __ltrim_colon_completions "$cur" + _comp_ltrim_colon_completions "$cur" else case $cur in force-command=*) compopt -o filenames - COMPREPLY=($(compgen -c -- "${cur#*=}")) + _comp_compgen -c "${cur#*=}" commands + ;; + checkpoint=* | challenge=* | write-attestation=*) + _comp_compgen -c "${cur#*=}" filedir + ;; + application=*([^:=])) + _comp_compgen -c "${cur#*=}" -- -W "ssh:" + compopt -o nospace ;; - checkpoint=* | challenge=*) - cur=${cur#*=} - _filedir + user=*) + _comp_compgen -c "${cur#*=}" -- -u ;; esac fi return ;; -*r) - [[ ${words[*]} != *\ -*Y\ * ]] || _filedir + [[ ${words[*]} != *\ -*Y\ * ]] || _comp_compgen_filedir return ;; -*t) - local protocols=$(_xfunc ssh _ssh_query "$1" protocol-version) + # Prefer `ssh` from same dir for resolving options, etc + local pathcmd protocols + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen -v protocols -x ssh query protocol-version local types='dsa ecdsa ecdsa-sk ed25519 ed25519-sk rsa' - if [[ $protocols == *1* ]]; then + if [[ ${protocols[*]} == *1* ]]; then types+=' rsa1' fi - COMPREPLY=($(compgen -W "$types" -- "$cur")) + _comp_compgen -- -W "$types" return ;; -*Y) - COMPREPLY=($(compgen -W 'find-principals check-novalidate sign - verify' -- "$cur")) + _comp_compgen -- -W 'find-principals check-novalidate sign verify' return ;; esac + _comp_compgen_set if [[ $cur == -* ]]; then - local opts=$(_parse_usage "$1" "-?") - [[ -z $opts ]] && opts=$(_parse_help "$1" "-?") # OpenSSH < 7 - COMPREPLY=($(compgen -W "$opts" -- "$cur")) + _comp_compgen_usage -- "-?" || + _comp_compgen_help -- "-?" # OpenSSH < 7 fi if [[ ${words[*]} == *\ -*s\ * ]]; then - _filedir pub + _comp_compgen -a filedir pub fi } && - complete -F _ssh_keygen ssh-keygen + complete -F _comp_cmd_ssh_keygen ssh-keygen # ex: filetype=sh diff --git a/completions/ssh-keyscan b/completions/ssh-keyscan new file mode 100644 index 0000000..f5e4364 --- /dev/null +++ b/completions/ssh-keyscan @@ -0,0 +1,39 @@ +# ssh-keyscan(1) completion -*- shell-script -*- + +_comp_cmd_ssh_keyscan() +{ + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + + local ipvx + + case $prev in + -*4*) + ipvx=-4 + ;; + -*6*) + ipvx=-6 + ;; + -*f) + _comp_compgen_filedir + return + ;; + -*p | -*T) + return + ;; + -*t) + _comp_delimited , -W "dsa ecdsa ed25519 rsa" + return + ;; + esac + + if [[ $cur == -* ]]; then + _comp_compgen_usage + return + fi + + _comp_compgen_known_hosts ${ipvx-} -- "$cur" +} && + complete -F _comp_cmd_ssh_keyscan ssh-keyscan + +# ex: filetype=sh diff --git a/completions/sshfs b/completions/sshfs index 223d029..4b3f388 100644 --- a/completions/sshfs +++ b/completions/sshfs @@ -1,23 +1,23 @@ # sshfs(1) completion -*- shell-script -*- -_sshfs() +_comp_cmd_sshfs() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return - _expand || return + _comp_expand || return if [[ $cur == *:* ]]; then - _xfunc ssh _scp_remote_files -d + _comp_compgen -x scp remote_files -d # unlike scp and rsync, sshfs works with 1 backslash instead of 3 COMPREPLY=("${COMPREPLY[@]//\\\\\\/\\}") return fi - [[ $cur == @(*/|[.~])* ]] || _known_hosts_real -c -a -- "$cur" + [[ $cur == @(*/|[.~])* ]] || _comp_compgen_known_hosts -c -a -- "$cur" - _xfunc ssh _scp_local_files -d + _comp_compgen -ax scp local_files -d } && - complete -F _sshfs -o nospace sshfs + complete -F _comp_cmd_sshfs -o nospace sshfs # ex: filetype=sh diff --git a/completions/sshmitm b/completions/sshmitm index ee893e5..136d2f9 100644 --- a/completions/sshmitm +++ b/completions/sshmitm @@ -1,17 +1,17 @@ # sshmitm completion -*- shell-script -*- -_sshmitm() +_comp_cmd_sshmitm() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage else - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" fi } && - complete -F _sshmitm sshmitm + complete -F _comp_cmd_sshmitm sshmitm # ex: filetype=sh diff --git a/completions/sshow b/completions/sshow index 917444e..0d21bbb 100644 --- a/completions/sshow +++ b/completions/sshow @@ -1,26 +1,26 @@ # sshow completion -*- shell-script -*- -_sshow() +_comp_cmd_sshow() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*i) - _available_interfaces -a + _comp_compgen_available_interfaces -a return ;; -*p) - _filedir pcap + _comp_compgen_filedir pcap return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage fi } && - complete -F _sshow sshow + complete -F _comp_cmd_sshow sshow # ex: filetype=sh diff --git a/completions/strace b/completions/strace index 2b46ce8..917f64d 100644 --- a/completions/strace +++ b/completions/strace @@ -1,9 +1,9 @@ # bash completion for strace -*- shell-script -*- -_strace() +_comp_cmd_strace() { - local cur prev words cword - _init_completion -n = || return + local cur prev words cword comp_args + _comp_initialize -n = -- "$@" || return # check if we're still completing strace local offset=0 i @@ -22,7 +22,7 @@ _strace() done if ((offset > 0)); then - _command_offset $offset + _comp_command_offset $offset else case $prev in @@ -38,11 +38,11 @@ _strace() local define syscall rest local -A syscalls while read -r define syscall rest; do - [[ $define == "#define" && \ - $syscall =~ ^__NR_(.+) ]] && - syscalls[${BASH_REMATCH[1]}]=1 + [[ $define == "#define" && + $syscall =~ ^__NR_(.+) ]] && + syscalls[${BASH_REMATCH[1]}]=set done 2>/dev/null </usr/include/asm/unistd.h - if [[ ! $syscalls ]]; then + if ((${#syscalls[@]} == 0)); then local unistd arch=$(command uname -m) if [[ $arch == *86 ]]; then unistd=/usr/include/asm/unistd_32.h @@ -50,50 +50,50 @@ _strace() unistd=/usr/include/asm/unistd_64.h fi while read -r define syscall rest; do - [[ $define == "#define" && \ - $syscall =~ ^__NR_(.+) ]] && - syscalls[${BASH_REMATCH[1]}]=1 + [[ $define == "#define" && + $syscall =~ ^__NR_(.+) ]] && + syscalls[${BASH_REMATCH[1]}]=set done 2>/dev/null <$unistd fi - COMPREPLY=($(compgen -W '${!syscalls[@]} file - process network signal ipc desc all none' \ - -- "$cur")) + _comp_compgen -- -W \ + '${syscalls[@]+"${!syscalls[@]}"} file process + network signal ipc desc all none' return ;; esac else compopt -o nospace - COMPREPLY=($(compgen -S"=" -W 'trace abbrev verbose raw - signal read write' -- "$cur")) + _comp_compgen -- -S"=" -W 'trace abbrev verbose raw signal + read write' fi return ;; -*o) - _filedir + _comp_compgen_filedir return ;; -*p) - _pids + _comp_compgen_pids return ;; -*S) - COMPREPLY=($(compgen -W 'time calls name nothing' -- "$cur")) + _comp_compgen -- -W 'time calls name nothing' return ;; -*u) - _allowed_users + _comp_compgen_allowed_users return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur")) + _comp_compgen_help -- -h else - COMPREPLY=($(compgen -c -- "$cur")) + _comp_compgen_commands fi fi } && - complete -F _strace -o default strace + complete -F _comp_cmd_strace -o default strace # ex: filetype=sh diff --git a/completions/strings b/completions/strings index 059f557..45f0e60 100644 --- a/completions/strings +++ b/completions/strings @@ -1,45 +1,50 @@ # strings(1) completion -*- shell-script -*- -_strings() +_comp_cmd_strings() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[nstTe]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | --bytes | -!(-*)[hvVn]) + --help | --version | --bytes | --output-separator | -arch | \ + -${noargopts}[hvVns]) return ;; - --radix | -!(-*)t) - COMPREPLY=($(compgen -W 'o d x' -- "$cur")) + --radix | -${noargopts}t) + _comp_compgen -- -W 'o d x' return ;; - --target | -!(-*)T) - COMPREPLY=($(compgen -W '$(LC_ALL=C "$1" --help 2>/dev/null | \ - command sed -ne "s/: supported targets: \(.*\)/\1/p")' \ - -- "$cur")) + --target | -${noargopts}T) + _comp_compgen_split -- "$(LC_ALL=C "$1" --help 2>/dev/null | + command sed -ne 's/: supported targets: \(.*\)/\1/p')" return ;; - --encoding | -!(-*)e) - COMPREPLY=($(compgen -W 's S b l B L' -- "$cur")) + --encoding | -${noargopts}e) + _comp_compgen_split -F , -- "$(LC_ALL=C "$1" --help 2>/dev/null | + command sed -ne 's/.*--encoding={\([^}]*\)}.*/\1/p')" return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + # macOS: ... [-t format] [-number] [-n number] ... + _comp_compgen_help || + _comp_compgen_usage - <<<"$("$1" --help 2>&1 | + command sed -e "s/\[-number\]//")" [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return elif [[ $cur == @* ]]; then - cur=${cur:1} - _filedir + _comp_compgen -c "${cur:1}" filedir COMPREPLY=("${COMPREPLY[@]/#/@}") return fi - _filedir + _comp_compgen_filedir } && - complete -F _strings strings + complete -F _comp_cmd_strings strings # ex: filetype=sh diff --git a/completions/sudo b/completions/sudo index c9a806b..2cfcf84 100644 --- a/completions/sudo +++ b/completions/sudo @@ -1,56 +1,58 @@ # bash completion for sudo(8) -*- shell-script -*- -_sudo() +_comp_cmd_sudo() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return local i mode=normal [[ $1 == *sudoedit ]] && mode=edit + local noargopts='!(-*|*[uUgCp]*)' [[ $mode == normal ]] && for ((i = 1; i <= cword; i++)); do if [[ ${words[i]} != -* ]]; then local PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin - local root_command=${words[i]} - _command_offset $i + local _comp_root_command=$1 + _comp_command_offset $i return fi - if [[ ${words[i]} == -@(!(-*)e*|-edit) ]]; then + # shellcheck disable=SC2254 + if [[ ${words[i]} == -@(${noargopts}e*|-edit) ]]; then mode=edit break fi - [[ ${words[i]} == \ - -@(user|other-user|group|close-from|prompt|!(-*)[uUgCp]) ]] && + # shellcheck disable=SC2254 + [[ ${words[i]} == @(--@(user|other-user|group|close-from|prompt)|-${noargopts}[uUgCp]) ]] && ((i++)) done + # shellcheck disable=SC2254 case "$prev" in - --user | --other-user | -!(-*)[uU]) - COMPREPLY=($(compgen -u -- "$cur")) + --user | --other-user | -${noargopts}[uU]) + _comp_compgen -- -u return ;; - --group | -!(-*)g) - COMPREPLY=($(compgen -g -- "$cur")) + --group | -${noargopts}g) + _comp_compgen -- -g return ;; - --close-from | --prompt | -!(-*)[Cp]) + --close-from | --prompt | -${noargopts}[Cp]) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - local opts=$(_parse_help "$1") - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi if [[ $mode == edit ]]; then - _filedir + _comp_compgen_filedir fi } && - complete -F _sudo sudo sudoedit + complete -F _comp_cmd_sudo sudo sudoedit # ex: filetype=sh diff --git a/completions/svcadm b/completions/svcadm index 5269c7b..8505457 100644 --- a/completions/svcadm +++ b/completions/svcadm @@ -11,25 +11,25 @@ # but to not clutter the interface with all completions, we will only # cut every completion alternative at the next slash. # -# For example, if the user types <nothing><tab>, we will propose for svc://foo/bar/bar/baz -# the following completion: foo/, bar/ and baz +# For example, if the user types <nothing><tab>, we will propose +# for svc://foo/bar/bar/baz the following completion: foo/, bar/ and baz # If the user types <b><tab>, we will propose: bar/ and baz # If the user types <bar/><tab>, we will propose: bar/bar/ and bar/baz # -# By default, the function proproses only abbreviated completions except if the user already -# began to type svc:. In that case we will propose only the complete FMRI beginning with the -# pattern +# By default, the function proproses only abbreviated completions except if the +# user already began to type svc:. In that case we will propose only the +# complete FMRI beginning with the pattern # -_smf_complete_fmri() +_comp_cmd_svcadm__fmri() { local cur="$1" prefix="$2" local cur_prefix fmri fmri_list="" - local exact_mode pattern + local exact_mode="" pattern if [[ $cur == $prefix* ]]; then [[ $cur == "$prefix" ]] && cur+="/" pattern="$cur*" - exact_mode=1 + exact_mode=set else pattern="$prefix*/$cur*" fi @@ -38,22 +38,22 @@ _smf_complete_fmri() for fmri in $(svcs -H -o FMRI "$pattern" 2>/dev/null); do local fmri_part_list fmri_part - if [[ -z $exact_mode ]]; then - fmri=${fmri#$prefix/} + if [[ ! $exact_mode ]]; then + fmri=${fmri#"$prefix/"} - # we generate all possibles abbrevations for the FMRI + # we generate all possibles abbreviations for the FMRI # no need to have a generic loop as we will have a finite # number of components - local ifs="$IFS" - IFS="/" - set -- $fmri - IFS=$ifs - case $# in - 1) fmri_part_list=" $1" ;; - 2) fmri_part_list=" $2 $1/$2" ;; - 3) fmri_part_list=" $3 $2/$3 $1/$2/$3" ;; - 4) fmri_part_list=" $4 $3/$4 $2/$3/$4 $1/$2/$3/$4" ;; - esac + local -a tmp + if _comp_split -F / tmp "$fmri"; then + set -- "${tmp[@]}" + case $# in + 1) fmri_part_list=" $1" ;; + 2) fmri_part_list=" $2 $1/$2" ;; + 3) fmri_part_list=" $3 $2/$3 $1/$2/$3" ;; + 4) fmri_part_list=" $4 $3/$4 $2/$3/$4 $1/$2/$3/$4" ;; + esac + fi else fmri_part_list="$fmri" fi @@ -62,14 +62,14 @@ _smf_complete_fmri() # we cut them at the first slash for fmri_part in $fmri_part_list; do [[ $fmri_part == $cur* ]] || continue - local first_part=${fmri_part#$cur_prefix} + local first_part=${fmri_part#"$cur_prefix"} first_part=$cur_prefix${first_part%%/*} [[ $first_part != "$fmri_part" ]] && first_part+="/" fmri_list+=" $first_part" done done - COMPREPLY=($fmri_list) + _comp_split COMPREPLY "$fmri_list" # here we want to detect if there only one completion proposed and that # it ends with a slash. That means the users will still have to complete @@ -83,7 +83,7 @@ _smf_complete_fmri() ((i--)) done if ((i == 0)); then - _smf_complete_fmri "${COMPREPLY[0]}" "$prefix" + _comp_cmd_svcadm__fmri "${COMPREPLY[0]}" "$prefix" return fi fi @@ -98,53 +98,54 @@ _smf_complete_fmri() done } -_svcadm() +_comp_cmd_svcadm() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return local command_list="enable disable restart refresh clear mark milestone" - local command i + local command="" i for ((i = 1; i < cword; i++)); do if [[ ${words[i]} == @(enable|disable|restart|refresh|clear|mark|milestone) ]]; then command=${words[i]} + break fi done - if [[ ! -v command ]]; then + if [[ ! $command ]]; then if [[ ${cur} == -* ]]; then - COMPREPLY=($(compgen -W "-v" -- ${cur})) + _comp_compgen -- -W "-v" else - COMPREPLY=($(compgen -W "$command_list" -- ${cur})) + _comp_compgen -- -W "$command_list" fi else if [[ ${cur} == -* ]]; then case "$command" in enable) - COMPREPLY=($(compgen -W "-r -s -t" -- ${cur})) + _comp_compgen -- -W "-r -s -t" ;; disable) - COMPREPLY=($(compgen -W "-s -t" -- ${cur})) + _comp_compgen -- -W "-s -t" ;; mark) - COMPREPLY=($(compgen -W "-I -t" -- ${cur})) + _comp_compgen -- -W "-I -t" ;; milestone) - COMPREPLY=($(compgen -W "-d" -- ${cur})) + _comp_compgen -- -W "-d" ;; esac else - if [[ $command == "mark" ]] && [[ $prev != @(degraded|maintenance) ]]; then - COMPREPLY=($(compgen -W "degraded maintenance" -- ${cur})) + if [[ $command == "mark" && $prev != @(degraded|maintenance) ]]; then + _comp_compgen -- -W "degraded maintenance" elif [[ $command == "milestone" ]]; then - _smf_complete_fmri "${cur}" "svc:/milestone" + _comp_cmd_svcadm__fmri "${cur}" "svc:/milestone" else - _smf_complete_fmri "${cur}" "svc:" + _comp_cmd_svcadm__fmri "${cur}" "svc:" fi fi fi } && - complete -F _svcadm svcadm + complete -F _comp_cmd_svcadm svcadm # ex: filetype=sh diff --git a/completions/svk b/completions/svk index 9079df1..cfa6ede 100644 --- a/completions/svk +++ b/completions/svk @@ -1,9 +1,9 @@ # svk(1) completion -*- shell-script -*- -_svk() +_comp_cmd_svk() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local commands options command @@ -16,18 +16,18 @@ _svk() if ((cword == 1)); then if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--version' -- "$cur")) + _comp_compgen -- -W '--version' else - COMPREPLY=($(compgen -W "$commands" -- "$cur")) + _comp_compgen -- -W "$commands" fi else case $prev in -F | --file | --targets) - _filedir + _comp_compgen_filedir return ;; --encoding) - _xfunc iconv _iconv_charsets + _comp_compgen -x iconv charsets return ;; esac @@ -172,26 +172,24 @@ _svk() esac options+=" --help -h" - COMPREPLY=($(compgen -W "$options" -- "$cur")) + _comp_compgen -- -W "$options" else case $command in help | h | \?) - COMPREPLY=($(compgen -W "$commands environment commands - intro" -- "$cur")) + _comp_compgen -- -W "$commands environment commands intro" ;; admin) - COMPREPLY=($(compgen -W 'help deltify dump hotcopy - list-dblogs list-unused-dblogs load lstxns recover - rmtxns setlog verify rmcache' -- "$cur")) + _comp_compgen -- -W 'help deltify dump hotcopy list-dblogs + list-unused-dblogs load lstxns recover rmtxns setlog + verify rmcache' ;; patch) - COMPREPLY=($(compgen -W '--ls --list --cat --view - --regen --regenerate --up --update --apply --rm - --delete' -- "$cur")) + _comp_compgen -- -W '--ls --list --cat --view --regen + --regenerate --up --update --apply --rm --delete' ;; sync) - COMPREPLY=($(compgen -W "$($1 mirror --list \ - 2>/dev/null | awk '/^\//{print $1}')" -- "$cur")) + _comp_compgen_split -- "$("$1" mirror --list \ + 2>/dev/null | _comp_awk '/^\//{print $1}')" ;; co | checkout | push | pull) if [[ $cur == //*/* ]]; then @@ -199,16 +197,16 @@ _svk() else path=// fi - COMPREPLY=($(compgen -W "$($1 list $path 2>/dev/null | - command sed -e 's|\(.*\)|'$path'\1|')" -- "$cur")) + _comp_compgen_split -- "$("$1" list "$path" 2>/dev/null | + command sed -e 's|\(.*\)|'"$path"'\1|')" ;; *) - _filedir + _comp_compgen_filedir ;; esac fi fi } && - complete -F _svk svk + complete -F _comp_cmd_svk svk # ex: filetype=sh diff --git a/completions/sync_members b/completions/sync_members index 397f8b0..e8c07a7 100644 --- a/completions/sync_members +++ b/completions/sync_members @@ -1,31 +1,34 @@ # mailman sync_members completion -*- shell-script -*- -_sync_members() +_comp_cmd_sync_members() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -w | -g | -d | --welcome-msg | --goodbye-msg | --digest) - COMPREPLY=($(compgen -W 'y n' -- "$cur")) + _comp_compgen -- -W 'y n' return ;; --file) - _filedir + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--no-change --welcome-msg --goodbye-msg - --digest --notifyadmin --file --help' -- "$cur")) + _comp_compgen -- -W '--no-change --welcome-msg --goodbye-msg --digest + --notifyadmin --file --help' else - _xfunc list_lists _mailman_lists + # Prefer `list_lists` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen -x list_lists mailman_lists fi } && - complete -F _sync_members sync_members + complete -F _comp_cmd_sync_members sync_members # ex: filetype=sh diff --git a/completions/synclient b/completions/synclient index c4a0d42..12a7d54 100644 --- a/completions/synclient +++ b/completions/synclient @@ -1,9 +1,9 @@ # bash completion for synclient(1) -*- shell-script -*- -_synclient() +_comp_cmd_synclient() { - local cur prev words cword - _init_completion -n = || return + local cur prev words cword comp_args + _comp_initialize -n = -- "$@" || return case $prev in -\? | -h | -V) @@ -12,13 +12,13 @@ _synclient() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage elif [[ $cur != *=?* ]]; then - COMPREPLY=($(compgen -S = -W '$($1 -l 2>/dev/null | \ - awk "/^[ \t]/ { print \$1 }")' -- "$cur")) + _comp_compgen_split -S = -- "$("$1" -l 2>/dev/null | + _comp_awk '/^[ \t]/ { print $1 }')" compopt -o nospace fi } && - complete -F _synclient synclient + complete -F _comp_cmd_synclient synclient # ex: filetype=sh diff --git a/completions/sysbench b/completions/sysbench index 0af7cc3..7f9e87e 100644 --- a/completions/sysbench +++ b/completions/sysbench @@ -1,9 +1,9 @@ # bash completion for sysbench -*- shell-script -*- -_sysbench() +_comp_cmd_sysbench() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in --num-threads | --max-requests | --max-time | --thread-stack-size | \ @@ -11,122 +11,121 @@ _sysbench() return ;; --init-rng | --debug | --validate) - COMPREPLY=($(compgen -W 'on off' -- "$cur")) + _comp_compgen -- -W 'on off' return ;; --test) - COMPREPLY=($(compgen -W 'fileio cpu memory threads mutex oltp' \ - -- "$cur")) + _comp_compgen -- -W 'fileio cpu memory threads mutex oltp' return ;; --cpu-max-prime) return ;; --file-test-mode) - COMPREPLY=($(compgen -W 'seqwr seqrewr seqrd rndrd rndwr rndrw' \ - -- "$cur")) + _comp_compgen -- -W 'seqwr seqrewr seqrd rndrd rndwr rndrw' return ;; --file-io-mode) - COMPREPLY=($(compgen -W 'sync async fastmmap slowmmap' -- "$cur")) + _comp_compgen -- -W 'sync async fastmmap slowmmap' return ;; --file-extra-flags) - COMPREPLY=($(compgen -W 'sync dsync direct' -- "$cur")) + _comp_compgen -- -W 'sync dsync direct' return ;; --file-fsync-all | --file-fsync-end) - COMPREPLY=($(compgen -W 'on off' -- "$cur")) + _comp_compgen -- -W 'on off' return ;; --file-fsync-mode) - COMPREPLY=($(compgen -W 'fsync fdatasync' -- "$cur")) + _comp_compgen -- -W 'fsync fdatasync' return ;; --memory-scope) - COMPREPLY=($(compgen -W 'global local' -- "$cur")) + _comp_compgen -- -W 'global local' return ;; --memory-hugetlb) - COMPREPLY=($(compgen -W 'on off' -- "$cur")) + _comp_compgen -- -W 'on off' return ;; --memory-oper) - COMPREPLY=($(compgen -W 'read write none' -- "$cur")) + _comp_compgen -- -W 'read write none' return ;; --memory-access-mode) - COMPREPLY=($(compgen -W 'seq rnd' -- "$cur")) + _comp_compgen -- -W 'seq rnd' return ;; --oltp-test-mode) - COMPREPLY=($(compgen -W 'simple complex nontrx sp' -- "$cur")) + _comp_compgen -- -W 'simple complex nontrx sp' return ;; --oltp-read-only | --oltp-skip-trx | --oltp-quto-inc | --mysql-ssl) - COMPREPLY=($(compgen -W 'on off' -- "$cur")) + _comp_compgen -- -W 'on off' return ;; --oltp-nontrx-mode) - COMPREPLY=($(compgen -W 'select update_key update_nokey insert - delete' -- "$cur")) + _comp_compgen -- -W 'select update_key update_nokey insert delete' return ;; --oltp-dist-type) - COMPREPLY=($(compgen -W 'uniform gaussian special' -- "$cur")) + _comp_compgen -- -W 'uniform gaussian special' return ;; --db-driver) - COMPREPLY=($(compgen -W "$($1 --test=oltp help 2>/dev/null | + _comp_compgen_split -- "$("$1" --test=oltp help 2>/dev/null | command sed -e '/^.*database drivers:/,/^$/!d' \ - -ne 's/^ *\([^ ]*\) .*/\1/p')" -- "$cur")) + -ne 's/^ *\([^ ]*\) .*/\1/p')" return ;; --db-ps-mode) - COMPREPLY=($(compgen -W 'auto disable' -- "$cur")) + _comp_compgen -- -W 'auto disable' return ;; --mysql-socket) - _filedir sock + _comp_compgen_filedir sock return ;; --mysql-table-engine) - COMPREPLY=($(compgen -W 'myisam innodb bdb heap ndbcluster - federated' -- "$cur")) + _comp_compgen -- -W 'myisam innodb bdb heap ndbcluster federated' return ;; --mysql-engine-trx) - COMPREPLY=($(compgen -W 'yes no auto' -- "$cur")) + _comp_compgen -- -W 'yes no auto' return ;; --*) - $split && return + [[ $was_split ]] && return ;; esac # find out which test we're running - local i test + local i test="" has_test="" for ((i = 1; i < ${#words[@]} - 1; i++)); do # TODO --test= is deprecated, bare test name preferred - if [[ ${words[i]} == --test* ]]; then + if [[ ${words[i]} == --test=* ]]; then test=${words[i]#*=} + has_test=set break fi done - local opts=$(_parse_help "$1") - if [[ -v test ]]; then - local help=($(_parse_help "$1" "--test=$test help")) - opts="${opts/--test=/} ${help[*]} prepare run cleanup help version" + local opts + _comp_compgen -v opts help + if [[ $has_test ]]; then + opts=("${opts[@]/#--test=/}") + _comp_compgen -aRv opts help -- --test="$test" help + opts+=(prepare run cleanup help version) fi - if [[ $cur == -* || ! -v test ]]; then - COMPREPLY=($(compgen -W "$opts" -- "$cur")) + if [[ $cur == -* || ! $has_test ]]; then + _comp_compgen -- -W '"${opts[@]}"' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - COMPREPLY=($(compgen -W "prepare run cleanup help version" -- "$cur")) + _comp_compgen -- -W "prepare run cleanup help version" fi } && - complete -F _sysbench sysbench + complete -F _comp_cmd_sysbench sysbench # ex: filetype=sh diff --git a/completions/sysctl b/completions/sysctl index 005452d..4062a7f 100644 --- a/completions/sysctl +++ b/completions/sysctl @@ -1,31 +1,33 @@ # bash completion for sysctl -*- shell-script -*- -_sysctl() +_comp_cmd_sysctl() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[rpf]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | --pattern | -!(-*)[hVr]) + --help | --version | --pattern | -${noargopts}[hVr]) return ;; - --load | -!(-*)[pf]) - _filedir conf + --load | -${noargopts}[pf]) + _comp_compgen_filedir conf return ;; esac if [[ $cur == -* ]]; then - local opts="$(_parse_help "$1")" - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage else local suffix= [[ $prev == -w ]] && suffix="=" - COMPREPLY=($(compgen -S "$suffix" -W \ - "$(PATH="$PATH:/sbin" $1 -N -a 2>/dev/null)" -- "$cur")) + _comp_compgen_split -S "$suffix" -- "$( + PATH="$PATH:/sbin" $1 -N -a 2>/dev/null + )" [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _sysctl sysctl + complete -F _comp_cmd_sysctl sysctl # ex: filetype=sh diff --git a/completions/tar b/completions/tar index 04b7fc0..83a4073 100644 --- a/completions/tar +++ b/completions/tar @@ -12,15 +12,15 @@ # # We rather advice the 'tar -czf /tmp/archive.tar -T patterns.txt' format of # arguments. Though, if user starts the 'first' tar argument without leading -# dash, we treat the command line apropriately. +# dash, we treat the command line appropriately. # # # long/short options origin # ------------------------- # # For GNU tar, everything is parsed from `tar --help` output so not so much -# per-distribution work should be needed. The _parse_help does not seem to be -# good enough so parsed here directly. +# per-distribution work should be needed. The _comp_compgen_help does not seem +# to be good enough so parsed here directly. # # # FIXME: --starting-file (-K) (should be matched for extraction only) @@ -37,8 +37,29 @@ # - mode option should be advised only once # - format option should be advised only once # ... +# +# Tar files vs internal paths +# =========================== +# +# bash's programmable completion is limited in how it handles the list of +# possible completions it returns. +# +# Because the paths returned from within the tar file are likely not existing +# paths on the file system, `-o dirnames` must be passed to the `complete` +# built-in to make it treat them as such. However, then bash will append a +# space when completing on directories during pathname completion to the tar +# files themselves. +# +# It's more important to have proper completion of paths to tar files than it +# is to have completion for their contents, so this sacrifice was made and +# `-o filenames` is used with complete instead by default. Setting the +# `$BASH_COMPLETION_CMD_TAR_INTERNAL_PATHS` environment variable to a non-null +# value *before sourcing* this completion toggles that the other way around. -__gtar_parse_help_opt() +_comp_deprecate_var 2.12 \ + COMP_TAR_INTERNAL_PATHS BASH_COMPLETION_CMD_TAR_INTERNAL_PATHS + +_comp_cmd_gtar__parse_help_opt() { local opttype arg opt separator optvar opttype=long @@ -77,35 +98,36 @@ __gtar_parse_help_opt() eval "$optvar=\"\$$optvar$separator\"\"$opt\"" } -__gtar_parse_help_line() +_comp_cmd_gtar__parse_help_line() { local i - - for i in $1; do - case "$i" in - # regular options - --* | -*) - __gtar_parse_help_opt "$i" "$2" - ;; - - # end once there is single non-option word - *) - break - ;; - esac - done + local -a tmp + while read -ra tmp; do + for i in "${tmp[@]}"; do + case "$i" in + # regular options + --* | -*) + _comp_cmd_gtar__parse_help_opt "$i" "$2" + ;; + + # end once there is single non-option word + *) + break + ;; + esac + done + done <<<"$1" } -__gnu_tar_parse_help() +_comp_cmd_gtar__parse_help() { local str line arg - while IFS= read line; do + while IFS= read -r line; do # Ok, this requires some comment probably. The GNU help output prints # options on lines beginning with spaces. After that, there is one # or more options separated by ', ' separator string. We are matching # like this then: ^<spaces>(<separator>?<option>)+<whatever>$ - if [[ $line =~ \ - ^[[:blank:]]{1,10}(((,[[:blank:]])?(--?([\]\[a-zA-Z0-9?=-]+))(,[[:space:]])?)+).*$ ]]; then + if [[ $line =~ ^[[:blank:]]{1,10}(((,[[:blank:]])?(--?([\]\[a-zA-Z0-9?=-]+))(,[[:space:]])?)+).*$ ]]; then line=${BASH_REMATCH[1]} str="${line//,/ }" @@ -116,10 +138,10 @@ __gnu_tar_parse_help() # variable may contain e.g. '-X, --XXX[=NAME], -XXX2[=NAME]'. arg=none if [[ $line =~ --[A-Za-z0-9-]+(\[?)= ]]; then - [[ -n ${BASH_REMATCH[1]} ]] && arg=opt || arg=req + [[ ${BASH_REMATCH[1]} ]] && arg=opt || arg=req fi - __gtar_parse_help_line "$str" "$arg" + _comp_cmd_gtar__parse_help_line "$str" "$arg" fi done <<<"$(tar --help)" @@ -130,59 +152,55 @@ __gnu_tar_parse_help() } # Hack: parse --warning keywords from tar's error output -__gtar_parse_warnings() +_comp_cmd_gtar__parse_warnings() { - local line - LC_ALL=C tar --warning= 2>&1 | while IFS= read line; do + local -a warnings=() + local lines line + _comp_split -l lines "$(LC_ALL=C exec tar --warning= 2>&1)" + for line in "${line[@]}"; do if [[ $line =~ ^[[:blank:]]*-[[:blank:]]*[\`\']([a-zA-Z0-9-]+)\'$ ]]; then - echo "${BASH_REMATCH[1]} no-${BASH_REMATCH[1]}" + warnings+=("${BASH_REMATCH[1]}" "no-${BASH_REMATCH[1]}") fi done + _comp_compgen -- -W '"${warnings[@]}"' } -# Helper to obtain last character of string. -__tar_last_char() -{ - echo "${1:$((${#1} - 1))}" -} - -__tar_parse_old_opt() +_comp_cmd_tar__parse_old_opt() { local first_word char # current word is the first word - [[ $cword -eq 1 && -n $cur && ${cur:0:1} != '-' ]] && - old_opt_progress=1 + [[ $cword -eq 1 && $cur && ${cur:0:1} != '-' ]] && + old_opt_progress=set # check that first argument does not begin with "-" first_word=${words[1]} - [[ -n $first_word && ${first_word:0:1} != "-" ]] && - old_opt_used=1 + [[ $first_word && ${first_word:0:1} != "-" ]] && + old_opt_used=set # parse the old option (if present) contents to allow later code expect # corresponding arguments - if ((old_opt_used == 1)); then + if [[ $old_opt_used ]]; then char=${first_word:0:1} - while [[ -n $char ]]; do - if __tar_is_argreq "$char"; then + while [[ $char ]]; do + if _comp_cmd_tar__is_argreq "$char"; then old_opt_parsed+=("$char") fi - first_word=${first_word##$char} + first_word=${first_word##"$char"} char=${first_word:0:1} done fi } # Make the analysis of whole command line. -__tar_preparse_cmdline() +_comp_cmd_tar__preparse_cmdline() { - local first_arg i modes="ctxurdA" + local first_arg=set i modes="ctxurdA" shift # progname - __tar_parse_old_opt + _comp_cmd_tar__parse_old_opt - first_arg=1 for i in "$@"; do case "$i" in --delete | --test-label) @@ -201,36 +219,36 @@ __tar_preparse_cmdline() ;; *[$modes]*) # Only the first arg may be "MODE" without leading dash - if ((first_arg == 1)); then + if [[ $first_arg ]]; then tar_mode=${i//[^$modes]/} tar_mode=${tar_mode:0:1} tar_mode_arg=$i fi ;; esac - first_arg=0 + first_arg="" done } # Generate completions for -f/--file. -__tar_file_option() +_comp_cmd_tar__file_option() { local ext="$1" case "$tar_mode" in c) # no need to advise user to re-write existing tarball - _filedir -d + _comp_compgen_filedir -d ;; *) - _filedir "$ext" + _comp_compgen_filedir "$ext" ;; esac } # Returns truth if option requires argument. No equal sign must be pasted. # Accepts option in format: 'c', '-c', '--create' -__tar_is_argreq() +_comp_cmd_tar__is_argreq() { local opt opt=$1 @@ -250,14 +268,14 @@ __tar_is_argreq() } # Called only for short parameter -__tar_complete_mode() +_comp_cmd_tar__mode() { local short_modes rawopt generated \ allshort_raw_unused allshort_raw \ filler i short_modes="ctx" - [[ ! -v basic_tar ]] && short_modes="ctxurdA" + [[ ! $basic_tar ]] && short_modes="ctxurdA" # Remove prefix when needed rawopt=${cur#-} @@ -270,25 +288,25 @@ __tar_complete_mode() # when user passed something like 'tar cf' do not put the '-' before filler= - if [[ -z $cur && ! -v basic_tar ]]; then + if [[ ! $cur && ! $basic_tar ]]; then filler=- fi generated="" for ((i = 0; 1; i++)); do local c="${short_modes:i:1}" - [[ -z $c ]] && break + [[ ! $c ]] && break generated+=" $filler$cur$c" done - COMPREPLY=($(compgen -W "$generated")) + _comp_compgen -R -- -W "$generated" return 0 fi # The last short option requires argument, like '-cf<TAB>'. Cut the # completion here to enforce argument processing. - if ((old_opt_progress == 0)) && - __tar_is_argreq "$(__tar_last_char "$cur")"; then + if [[ ! $old_opt_progress ]] && + _comp_cmd_tar__is_argreq "${cur: -1}"; then COMPREPLY=("$cur") && return 0 fi @@ -300,25 +318,25 @@ __tar_complete_mode() generated= for ((i = 0; 1; i++)); do local c="${allshort_raw_unused:i:1}" - [[ -z $c ]] && break + [[ ! $c ]] && break generated+=" $cur$c" done - COMPREPLY=($(compgen -W "$generated")) + _comp_compgen -R -- -W "$generated" return 0 } -__gtar_complete_lopts() +_comp_cmd_tar__gnu_long_options() { local rv - COMPREPLY=($(compgen -W "$long_opts" -- "$cur")) + _comp_compgen -- -W "$long_opts" rv=$? [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return $rv } -__gtar_complete_sopts() +_comp_cmd_tar__gnu_short_options() { local generated short_mode_opts i c short_mode_opts="ctxurdA" @@ -326,52 +344,51 @@ __gtar_complete_sopts() for ((i = 0; 1; i++)); do c="${allshort_raw_unused:i:1}" - [[ -z $c ]] && break + [[ ! $c ]] && break generated+=" $cur$c" done - COMPREPLY=($(compgen -W "$generated" -- "$cur")) + _comp_compgen -- -W "$generated" } -__tar_try_mode() +_comp_cmd_tar__try_mode() { case "$cur" in --*) # posix tar does not support long opts - [[ -v basic_tar ]] && return 0 - __gtar_complete_lopts + [[ $basic_tar ]] && return 0 + _comp_cmd_tar__gnu_long_options return $? ;; -*) - # posix tar does not support short optios - [[ -v basic_tar ]] && return 0 + # posix tar does not support short options + [[ $basic_tar ]] && return 0 - __tar_complete_mode && return 0 + _comp_cmd_tar__mode && return 0 ;; *) if [[ $cword -eq 1 || $tar_mode == none ]]; then - __tar_complete_mode && return 0 + _comp_cmd_tar__mode && return 0 fi ;; esac return 1 } -__tar_adjust_PREV_from_old_option() +_comp_cmd_tar__adjust_PREV_from_old_option() { # deal with old style arguments here # $ tar cfTC # expects this sequence of arguments: # $ tar cfTC ARCHIVE_FILE PATTERNS_FILE CHANGE_DIR - if ((old_opt_used == 1 && cword > 1 && \ - cword < ${#old_opt_parsed[@]} + 2)); then + if [[ $old_opt_used ]] && ((cword > 1 && cword < ${#old_opt_parsed[@]} + 2)); then # make e.g. 'C' option from 'cffCT' prev="-${old_opt_parsed[cword - 2]}" fi } -__tar_extract_like_mode() +_comp_cmd_tar__extract_like_mode() { local i for i in x d t delete; do @@ -380,14 +397,15 @@ __tar_extract_like_mode() return 1 } -__tar_try_list_archive() +_comp_cmd_tar__try_list_archive() { - local tarball tarbin untar i + local tarball="" tarbin untar i - __tar_extract_like_mode || return 1 + _comp_cmd_tar__extract_like_mode || return 1 # This all is just to approach directory completion from "virtual" - # directory structure in tarball (for which the _filedir is unusable) + # directory structure in tarball (for which the _comp_compgen_filedir is + # unusable) set -- "${words[@]}" tarbin=$1 @@ -400,29 +418,39 @@ __tar_try_list_archive() break fi done - if [[ -n $tarball ]]; then - local IFS=$'\n' - COMPREPLY=($(compgen -o filenames -W "$( + if [[ $tarball ]]; then + _comp_compgen -c "$(printf %q "$cur")" split -lo filenames -- "$( $tarbin $untar "$tarball" 2>/dev/null | - while read line; do - printf "%q\n" "$(printf %q"\n" "$line")" + while read -r line; do + printf "%q\n" "$line" done - )" -- "$(printf "%q\n" "$cur")")) + )" return 0 fi } -__tar_cleanup_prev() +_comp_cmd_tar__cleanup_prev() { if [[ $prev =~ ^-[a-zA-Z0-9?]*$ ]]; then # transform '-caf' ~> '-f' - prev="-$(__tar_last_char "$prev")" + prev="-${prev: -1}" fi } -__tar_detect_ext() +_comp_cmd_tar__detect_ext() { - local tars='@(@(tar|gem|spkg)?(.@(Z|[bgx]z|bz2|lz?(ma|o)|zst))|t@([abglx]z|b?(z)2|zst))' + local tars='@(@(tar|spkg)?(.@(Z|[bgx]z|bz2|lz?(ma|o)|zst))|t@([abglx]z|b?(z)2|zst)|cbt|gem|xbps)' + if [[ ${COMP_WORDS[0]} == ?(*/)bsdtar ]]; then + # https://github.com/libarchive/libarchive/wiki/LibarchiveFormats + tars=${tars/%\)/|pax|cpio|iso|zip|@(j|x)ar|mtree|a|7z|warc} + if _comp_cmd_tar__extract_like_mode; then + # read only + tars+="|l@(ha|zh)|rar|cab)" + else + # write only + tars+="|shar)" + fi + fi ext="$tars" case "$tar_mode_arg" in @@ -430,7 +458,7 @@ __tar_detect_ext() # Should never happen? ;; ?(-)*[cr]*f) - ext='@(tar|gem|spkg)' + ext='@(tar|gem|spkg|cbt|xpbs)' case ${words[1]} in *a*) ext="$tars" ;; *z*) ext='t?(ar.)gz' ;; @@ -443,24 +471,24 @@ __tar_detect_ext() # Pass through using defaults above ;; *[Zz]*f) - ext='@(@(t?(ar.)|gem.|spkg.)@(gz|Z)|taz)' + ext='@(@(t?(ar.)|spkg.)@(gz|Z)|taz)' ;; *[jy]*f) - ext='@(@(t?(ar.)|gem.)bz?(2)|spkg|tb2)' + ext='@(t?(ar.)bz?(2)|spkg|tb2)' ;; *[J]*f) - ext='@(@(tar|gem|spkg).@(lzma|xz)|t[lx]z)' + ext='@(@(tar|spkg).@(lzma|xz)|t[lx]z)' ;; esac } -_gtar() +_comp_cmd_tar__gnu() { - local long_opts short_opts \ + local long_opts short_opts basic_tar="" \ long_arg_none="" long_arg_opt="" long_arg_req="" \ short_arg_none="" short_arg_opt="" short_arg_req="" \ - tar_mode tar_mode_arg old_opt_progress=0 \ - old_opt_used=0 old_opt_parsed=() + tar_mode tar_mode_arg old_opt_progress="" \ + old_opt_used="" old_opt_parsed=() # Main mode, e.g. -x or -c (extract/creation) local tar_mode=none @@ -469,81 +497,93 @@ _gtar() # FIXME: handle long options local tar_mode_arg= - if [[ -v BASHCOMP_TAR_OPT_DEBUG ]]; then + if [[ -v _comp_cmd_tar__debug ]]; then set -x - PS4='$BASH_SOURCE:$LINENO: ' + local PS4='$BASH_SOURCE:$LINENO: ' fi - local cur prev words cword split + local cur prev words cword was_split comp_args - _init_completion -s || return + _comp_initialize -s -- "$@" || return # Fill the {long,short}_{opts,arg*} - __gnu_tar_parse_help + _comp_cmd_gtar__parse_help - __tar_preparse_cmdline "${words[@]}" + _comp_cmd_tar__preparse_cmdline "${words[@]}" local ext - __tar_detect_ext + _comp_cmd_tar__detect_ext while true; do # just-for-easy-break while, not looping - __tar_adjust_PREV_from_old_option - __tar_posix_prev_handle && break - __tar_cleanup_prev + _comp_cmd_tar__adjust_PREV_from_old_option + _comp_cmd_tar__posix_prev_handle && break + _comp_cmd_tar__cleanup_prev # Handle all options *REQUIRING* argument. Optional arguments are up to # user (TODO: is there any sane way to deal with this?). This case # statement successes only if there already is PREV. + local noargopts='!(-*|*[TXgCFIfH]*)' + # shellcheck disable=SC2254 case $prev in - --directory | -!(-*)C) - _filedir -d + --add-file | --exclude | --exclude-ignore | \ + --exclude-ignore-recursive | --exclude-tag | \ + --exclude-tag-all | --exclude-tag-under | --files-from | \ + --exclude-from | --listed-incremental | --group-map | \ + --mtime | --owner-map | --volno-file | --newer | \ + --after-date | --index-file | -${noargopts}[TXg]) + _comp_compgen_filedir + break + ;; + --directory | -${noargopts}C) + _comp_compgen_filedir -d + break + ;; + --hole-detection) + _comp_compgen -- -W 'raw seek' + break + ;; + --to-command | --info-script | --new-volume-script | \ + --rmt-command | --rsh-command | --use-compress-program | \ + -${noargopts}[FI]) + _comp_compgen_commands break ;; --atime-preserve) - COMPREPLY=($(compgen -W 'replace system' -- "$cur")) + _comp_compgen -- -W 'replace system' break ;; --group) - COMPREPLY=($(compgen -g -- "$cur")) + _comp_compgen -- -g break ;; --owner) - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u break ;; - --info-script | --new-volume-script | --rmt-command | --rsh-command | \ - --use-compress-program | -!(-*)[FI]) - compopt -o filenames - COMPREPLY=($(compgen -c -- "$cur")) + --sort) + _comp_compgen -- -W 'none name inode' break ;; - --volno-file | --add-file | --files-from | --exclude-from | \ - --index-file | --listed-incremental | -!(-*)[TXg]) - _filedir + --file | -${noargopts}f) + _comp_cmd_tar__file_option "$ext" break ;; - --format | -!(-*)H) - COMPREPLY=($(compgen -W 'gnu oldgnu pax posix ustar v7' \ - -- "$cur")) + --format | -${noargopts}H) + _comp_compgen -- -W 'gnu oldgnu pax posix ustar v7' break ;; --quoting-style) - COMPREPLY=($(compgen -W 'literal shell shell-always c c-maybe - escape locale clocale' -- "$cur")) + _comp_compgen -- -W 'literal shell shell-always shell-escape + shell-escape-always c c-maybe escape locale clocale' break ;; --totals) - COMPREPLY=($(compgen -W 'SIGHUP SIGQUIT SIGINT SIGUSR1 SIGUSR2' \ - -- "$cur")) + _comp_compgen -- -W 'SIGHUP SIGQUIT SIGINT SIGUSR1 SIGUSR2' break ;; --warning) - COMPREPLY=($(compgen -W "$(__gtar_parse_warnings)" -- "$cur")) - break - ;; - --file | -!(-*)f) - __tar_file_option "$ext" + _comp_cmd_gtar__parse_warnings break ;; --*) @@ -557,12 +597,12 @@ _gtar() # if there is some unknown option with '=', for example # (literally) user does --nonexistent=<TAB>, we do not want # continue also - $split && break + [[ $was_split ]] && break # Most probably, when code goes here, the PREV variable contains # some string from "$long_arg_none" and we want continue. ;; - -!(-*)[a-zA-Z0-9?]) + -${noargopts}[a-zA-Z0-9?]) # argument required but no completion yet [[ $short_arg_req =~ ${prev##-} ]] && break ;; @@ -578,17 +618,17 @@ _gtar() # Handle the main operational mode of tar. We should do it as soon as # possible. - __tar_try_mode && break + _comp_cmd_tar__try_mode && break # handle others case "$cur" in --*) - __gtar_complete_lopts + _comp_cmd_tar__gnu_long_options break ;; -*) # called only if it is *not* first parameter - __gtar_complete_sopts + _comp_cmd_tar__gnu_short_options break ;; esac @@ -597,27 +637,26 @@ _gtar() # was truth - the 'break' statement would have been already called ((cword == 1)) && break - __tar_try_list_archive && break + _comp_cmd_tar__try_list_archive && break # file completion on relevant files if [[ $tar_mode != none ]]; then - _filedir + _comp_compgen_filedir fi break done # just-for-easy-break while - if [[ -v BASHCOMP_TAR_OPT_DEBUG ]]; then + if [[ -v _comp_cmd_tar__debug ]]; then set +x - unset PS4 fi } -__tar_posix_prev_handle() +_comp_cmd_tar__posix_prev_handle() { case "$prev" in -f) - __tar_file_option "$ext" + _comp_cmd_tar__file_option "$ext" return 0 ;; -b) @@ -628,13 +667,13 @@ __tar_posix_prev_handle() return 1 } -_posix_tar() +_comp_cmd_tar__posix() { - local long_opts short_opts basic_tar \ + local long_opts short_opts basic_tar=set \ long_arg_none="" long_arg_opt long_arg_req="" \ short_arg_none short_arg_opt short_arg_req \ - tar_mode tar_mode_arg old_opt_progress=0 \ - old_opt_used=1 old_opt_parsed=() + tar_mode tar_mode_arg old_opt_progress="" \ + old_opt_used=set old_opt_parsed=() # Main mode, e.g. -x or -c (extract/creation) local tar_mode=none @@ -642,11 +681,10 @@ _posix_tar() # The mode argument, e.g. -cpf or -c local tar_mode_arg= - local cur prev words cword split + local cur prev words cword was_split comp_args - _init_completion -s || return + _comp_initialize -s -- "$@" || return - basic_tar=yes tar_mode=none # relatively compatible modes are {c,t,x} @@ -655,57 +693,57 @@ _posix_tar() short_arg_none="wmv" short_opts="$short_arg_req$short_arg_none" - __tar_preparse_cmdline "${words[@]}" + _comp_cmd_tar__preparse_cmdline "${words[@]}" local ext - __tar_detect_ext + _comp_cmd_tar__detect_ext - __tar_adjust_PREV_from_old_option + _comp_cmd_tar__adjust_PREV_from_old_option - __tar_posix_prev_handle && return + _comp_cmd_tar__posix_prev_handle && return - __tar_try_mode && return + _comp_cmd_tar__try_mode && return - __tar_try_list_archive && return + _comp_cmd_tar__try_list_archive && return # file completion on relevant files - _filedir + _comp_compgen_filedir } -_tar() +_comp_cmd_tar() { local cmd=${COMP_WORDS[0]} func line - line="$($cmd --version 2>/dev/null)" + line="$("$cmd" --version 2>/dev/null)" case "$line" in *GNU*) - func=_gtar + func=_comp_cmd_tar__gnu ;; *) - func=_posix_tar + func=_comp_cmd_tar__posix ;; esac $func "$@" # Install real completion for subsequent completions - if [[ ${COMP_TAR_INTERNAL_PATHS-} ]]; then + if [[ ${BASH_COMPLETION_CMD_TAR_INTERNAL_PATHS-} ]]; then complete -F $func -o dirnames tar else complete -F $func tar fi - unset -f _tar + unset -f "$FUNCNAME" } -if [[ ${COMP_TAR_INTERNAL_PATHS-} ]]; then - complete -F _tar -o dirnames tar - complete -F _gtar -o dirnames gtar - complete -F _posix_tar -o dirnames bsdtar - complete -F _posix_tar -o dirnames star +if [[ ${BASH_COMPLETION_CMD_TAR_INTERNAL_PATHS-} ]]; then + complete -F _comp_cmd_tar -o dirnames tar + complete -F _comp_cmd_tar__gnu -o dirnames gtar + complete -F _comp_cmd_tar__posix -o dirnames bsdtar + complete -F _comp_cmd_tar__posix -o dirnames star else - complete -F _tar tar - complete -F _gtar gtar - complete -F _posix_tar bsdtar - complete -F _posix_tar star + complete -F _comp_cmd_tar tar + complete -F _comp_cmd_tar__gnu gtar + complete -F _comp_cmd_tar__posix bsdtar + complete -F _comp_cmd_tar__posix star fi # ex: filetype=sh diff --git a/completions/tcpdump b/completions/tcpdump index 9a7c2e9..f09dc6f 100644 --- a/completions/tcpdump +++ b/completions/tcpdump @@ -1,64 +1,64 @@ # bash completion for tcpdump -*- shell-script -*- -_tcpdump() +_comp_cmd_tcpdump() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[rwFVimTzZBcCDEGMsWyjQ]*)' + # shellcheck disable=SC2254 case $prev in - -!(-*)[rwFV]) - _filedir + -${noargopts}[rwFV]) + _comp_compgen_filedir return ;; - --interface | -!(-*)i) - _available_interfaces -a + --interface | -${noargopts}i) + _comp_compgen_available_interfaces -a return ;; - -!(-*)m) - _filedir mib + -${noargopts}m) + _comp_compgen_filedir mib return ;; - -!(-*)T) - COMPREPLY=($(compgen -W 'aodv carp cnfp lmp pgm pgm_zmtp1 radius - resp rpc rtcp rtp rtcp snmp tftp vat vxlan wb zmtp1' \ - -- "$cur")) + -${noargopts}T) + _comp_compgen -- -W 'aodv carp cnfp lmp pgm pgm_zmtp1 radius resp + rpc rtcp rtp rtcp snmp tftp vat vxlan wb zmtp1' return ;; - -!(-*)z) - compopt -o filenames - COMPREPLY=($(compgen -c -- "$cur")) + -${noargopts}z) + _comp_compgen_commands return ;; - --relinquish-privileges | -!(-*)Z) - _allowed_users + --relinquish-privileges | -${noargopts}Z) + _comp_compgen_allowed_users return ;; - -!(-*)[BcCDEGMsWy]) + -${noargopts}[BcCDEGMsWy]) return ;; - --time-stamp-type | -!(-*)j) - COMPREPLY=($(compgen -W 'host host_lowprec host_hiprec adapter - adapter_unsynced' -- "$cur")) + --time-stamp-type | -${noargopts}j) + _comp_compgen -- -W 'host host_lowprec host_hiprec adapter + adapter_unsynced' return ;; - --direction | -!(-*)Q) - COMPREPLY=($(compgen -W 'in out inout' -- "$cur")) + --direction | -${noargopts}Q) + _comp_compgen -- -W 'in out inout' return ;; --time-stamp-precision) - COMPREPLY=($(compgen -W 'micro nano' -- "$cur")) + _comp_compgen -- -W 'micro nano' return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _tcpdump tcpdump + complete -F _comp_cmd_tcpdump tcpdump # ex: filetype=sh diff --git a/completions/tcpkill b/completions/tcpkill index 189d928..87bf51a 100644 --- a/completions/tcpkill +++ b/completions/tcpkill @@ -1,22 +1,22 @@ # tcpkill completion -*- shell-script -*- -_tcpkill() +_comp_cmd_tcpkill() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*i) - _available_interfaces -a + _comp_compgen_available_interfaces -a return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-i -1 -2 -3 -4 -5 -6 -7 -8 -9' -- "$cur")) + _comp_compgen -- -W '-i -1 -2 -3 -4 -5 -6 -7 -8 -9' fi } && - complete -F _tcpkill tcpkill + complete -F _comp_cmd_tcpkill tcpkill # ex: filetype=sh diff --git a/completions/tcpnice b/completions/tcpnice index c6a94d6..b33d7db 100644 --- a/completions/tcpnice +++ b/completions/tcpnice @@ -1,22 +1,22 @@ # tcpnice completion -*- shell-script -*- -_tcpnice() +_comp_cmd_tcpnice() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*i) - _available_interfaces -a + _comp_compgen_available_interfaces -a return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage fi } && - complete -F _tcpnice tcpnice + complete -F _comp_cmd_tcpnice tcpnice # ex: filetype=sh diff --git a/completions/timeout b/completions/timeout index 32ff2e3..f5115d2 100644 --- a/completions/timeout +++ b/completions/timeout @@ -1,39 +1,38 @@ # timeout(1) completion -*- shell-script -*- -_timeout() +_comp_cmd_timeout() { - local cur prev words cword split i found=false - _init_completion -s || return + local cur prev words cword was_split comp_args i + _comp_initialize -s -- "$@" || return - for ((i = 1; i <= COMP_CWORD; i++)); do - if [[ ${COMP_WORDS[i]} != -* && ${COMP_WORDS[i - 1]} != = ]]; then - if $found; then - _command_offset $i - return - fi - found=true + local noargopts='!(-*|*[ks]*)' + for ((i = 1; i < cword; i++)); do + if [[ ${words[i]} != -* ]]; then + _comp_command_offset "$((i + 1))" + return fi - [[ ${COMP_WORDS[i]} == -@(-kill-after|-signal|!(-*)[ks]) ]] && ((i++)) + # shellcheck disable=SC2254 + [[ ${words[i]} == -@(-kill-after|-signal|${noargopts}[ks]) ]] && ((i++)) done + # shellcheck disable=SC2254 case $prev in - --help | --version | --kill-after | -!(-*)k) + --help | --version | --kill-after | -${noargopts}k) return ;; - --signal | -!(-*)s) - _signals + --signal | -${noargopts}s) + _comp_compgen_signals return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - local opts=$(_parse_help "$1") - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _timeout timeout + complete -F _comp_cmd_timeout timeout # ex: filetype=sh diff --git a/completions/tipc b/completions/tipc index 44ade36..11d35a6 100644 --- a/completions/tipc +++ b/completions/tipc @@ -1,26 +1,26 @@ # tipc(8) completion -*- shell-script -*- -_tipc_media() +_comp_cmd_tipc__media() { local optind=$1 if ((cword == optind)); then - COMPREPLY=($(compgen -W 'media' -- $cur)) + _comp_compgen -- -W 'media' return 0 elif ((cword == optind + 1)); then - COMPREPLY=($(compgen -W 'udp eth ib' -- $cur)) + _comp_compgen -- -W 'udp eth ib' return 0 fi return 1 } -_tipc_bearer() +_comp_cmd_tipc__bearer() { local optind=$1 - local media i + local media="" i - if _tipc_media $optind; then + if _comp_cmd_tipc__media "$optind"; then return fi @@ -33,52 +33,54 @@ _tipc_bearer() if ((cword == optind + 2)); then case "$media" in "udp") - COMPREPLY=($(compgen -W 'name' -- $cur)) + _comp_compgen -- -W 'name' ;; "eth" | "ib") - COMPREPLY=($(compgen -W 'device' -- $cur)) + _comp_compgen -- -W 'device' ;; esac elif ((cword == optind + 3)); then case "$media" in "udp") - local names=$(tipc bearer list 2>/dev/null | awk -F: '/^udp:/ {print $2}') - COMPREPLY=($(compgen -W '$names' -- $cur)) + local names=$( + tipc bearer list 2>/dev/null | _comp_awk -F : '/^udp:/ {print $2}' + ) + _comp_compgen -- -W '$names' ;; "eth") local interfaces=$(command ls /sys/class/net/) - COMPREPLY=($(compgen -W '$interfaces' -- $cur)) + _comp_compgen -- -W '$interfaces' ;; esac fi } -_tipc_link_opts() +_comp_cmd_tipc__link_opts() { - COMPREPLY=($(compgen -W 'priority tolerance window' -- $cur)) + _comp_compgen -- -W 'priority tolerance window' } -_tipc_link() +_comp_cmd_tipc__link() { local optind=$1 local filter=$2 if ((cword == optind)); then - COMPREPLY=($(compgen -W 'link' -- $cur)) + _comp_compgen -- -W 'link' elif ((cword == optind + 1)); then # awk drops link state and last trailing : local links=$(tipc link list 2>/dev/null | - awk '{print substr($1, 0, length($1))}') + _comp_awk '{print substr($1, 0, length($1))}') local -a exclude [[ $filter == peers ]] && exclude=(-X broadcast-link) - COMPREPLY=($(compgen "${exclude[@]}" -W '$links' -- $cur)) + _comp_compgen -- "${exclude[@]}" -W '$links' fi } -_tipc() +_comp_cmd_tipc() { - local cur prev words cword optind i p - _init_completion || return + local cur prev words cword comp_args optind i p + _comp_initialize -- "$@" || return optind=1 COMPREPLY=() @@ -86,13 +88,13 @@ _tipc() # Flags can be placed anywhere in the commandline case "$cur" in -*) - COMPREPLY=($(compgen -W '-h --help' -- $cur)) + _comp_compgen -- -W '-h --help' return ;; esac if ((cword == 1)); then - COMPREPLY=($(compgen -W 'bearer link media nametable node socket' -- $cur)) + _comp_compgen -- -W 'bearer link media nametable node socket' return fi @@ -101,17 +103,17 @@ _tipc() ((optind++)) if ((cword == optind)); then - COMPREPLY=($(compgen -W 'enable disable set get list' -- $cur)) + _comp_compgen -- -W 'enable disable set get list' return fi case "${words[optind]}" in enable) - local media params + local media="" params ((optind++)) if ((cword < optind + 4)); then - _tipc_bearer $optind + _comp_cmd_tipc__bearer $optind return fi @@ -122,20 +124,20 @@ _tipc() done case "$media" in "udp") - declare -a params=("localip" "localport" "remoteip" + local -a params=("localip" "localport" "remoteip" "remoteport" "domain" "priority") ;; "eth" | "ib") - declare -a params=("domain" "priority") + local -a params=("domain" "priority") ;; *) return ;; esac - # If the previous word was a known parameter, we assume a value for - # that key. Note that this would break if the user attempts to use - # a known key as value. + # If the previous word was a known parameter, we assume a + # value for that key. Note that this would break if the + # user attempts to use a known key as value. for i in "${params[@]}"; do if [[ $prev == "$i" ]]; then return @@ -151,29 +153,29 @@ _tipc() done done - COMPREPLY=($(compgen -W '${params[@]}' -- $cur)) + _comp_compgen -- -W '"${params[@]}"' -X '' ;; disable) ((optind++)) - _tipc_bearer $optind + _comp_cmd_tipc__bearer $optind ;; get) ((optind++)) if ((cword == optind)); then - _tipc_link_opts + _comp_cmd_tipc__link_opts elif ((cword >= optind + 1)); then - _tipc_bearer $((optind + 1)) + _comp_cmd_tipc__bearer $((optind + 1)) fi ;; set) ((optind++)) if ((cword == optind)); then - _tipc_link_opts + _comp_cmd_tipc__link_opts elif ((cword >= optind + 2)); then - _tipc_bearer $((optind + 2)) + _comp_cmd_tipc__bearer $((optind + 2)) fi ;; esac @@ -182,7 +184,7 @@ _tipc() ((optind++)) if ((cword == optind)); then - COMPREPLY=($(compgen -W 'get set list statistics' -- $cur)) + _comp_compgen -- -W 'get set list statistics' return fi @@ -191,31 +193,31 @@ _tipc() ((optind++)) if ((cword == optind)); then - _tipc_link_opts + _comp_cmd_tipc__link_opts elif ((cword >= optind + 1)); then - _tipc_link $((optind + 1)) "peers" + _comp_cmd_tipc__link $((optind + 1)) "peers" fi ;; set) ((optind++)) if ((cword == optind)); then - _tipc_link_opts + _comp_cmd_tipc__link_opts elif ((cword >= optind + 2)); then - _tipc_link $((optind + 2)) "peers" + _comp_cmd_tipc__link $((optind + 2)) "peers" fi ;; statistics) ((optind++)) if ((cword == optind)); then - COMPREPLY=($(compgen -W 'show reset' -- $cur)) + _comp_compgen -- -W 'show reset' return fi case "${words[optind]}" in show | reset) - _tipc_link $((optind + 1)) + _comp_cmd_tipc__link $((optind + 1)) ;; esac ;; @@ -225,7 +227,7 @@ _tipc() ((optind++)) if ((cword == optind)); then - COMPREPLY=($(compgen -W 'get set list' -- $cur)) + _comp_compgen -- -W 'get set list' return fi @@ -234,18 +236,18 @@ _tipc() ((optind++)) if ((cword == optind)); then - _tipc_link_opts + _comp_cmd_tipc__link_opts elif ((cword >= optind + 1)); then - _tipc_media $((optind + 1)) + _comp_cmd_tipc__media $((optind + 1)) fi ;; set) ((optind++)) if ((cword == optind)); then - _tipc_link_opts + _comp_cmd_tipc__link_opts elif ((cword >= optind + 2)); then - _tipc_media $((optind + 2)) + _comp_cmd_tipc__media $((optind + 2)) fi ;; esac @@ -254,14 +256,14 @@ _tipc() ((optind++)) if ((cword == optind)); then - COMPREPLY=($(compgen -W 'show' -- $cur)) + _comp_compgen -- -W 'show' fi ;; node) ((optind++)) if ((cword == optind)); then - COMPREPLY=($(compgen -W 'list get set' -- $cur)) + _comp_compgen -- -W 'list get set' return fi @@ -270,7 +272,7 @@ _tipc() ((optind++)) if ((cword == optind)); then - COMPREPLY=($(compgen -W 'address netid' -- $cur)) + _comp_compgen -- -W 'address netid' fi ;; esac @@ -279,11 +281,11 @@ _tipc() ((optind++)) if ((cword == optind)); then - COMPREPLY=($(compgen -W 'list' -- $cur)) + _comp_compgen -- -W 'list' fi ;; esac } && - complete -F _tipc tipc + complete -F _comp_cmd_tipc tipc # ex: filetype=sh diff --git a/completions/tox b/completions/tox index 0ea656e..b4b88bd 100644 --- a/completions/tox +++ b/completions/tox @@ -1,9 +1,9 @@ # tox completion -*- shell-script -*- -_tox() +_comp_cmd_tox() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return # Complete defaults following a "--" if [[ "${words[*]:0:cword} " == *\ --\ * && $cur != -- ]]; then @@ -11,19 +11,22 @@ _tox() return fi + local noargopts='!(-*|*[nice]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | --num | --index-url | --hashseed | --force-dep | -!(-*)[hni]) + --help | --version | --num | --index-url | --hashseed | --force-dep | \ + -${noargopts}[hni]) return ;; - -!(-*)c) - _filedir ini + -${noargopts}c) + _comp_compgen_filedir ini return ;; --installpkg | --result-json | --workdir) - _filedir + _comp_compgen_filedir return ;; - -!(-*)e) + -${noargopts}e) local envs=$( { "$1" --listenvs-all || "$1" --listenvs @@ -33,19 +36,17 @@ _tox() command sed -e 's/,/ /g' -ne 's/^envlist[[:space:]]*=//p' \ tox.ini 2>/dev/null ) - local prefix="" - [[ $cur == *,* ]] && prefix="${cur%,*}," - COMPREPLY=($(compgen -X '*[{}]*' -W "$envs ALL" -- "${cur##*,}")) - ((${#COMPREPLY[@]} == 1)) && COMPREPLY=(${COMPREPLY/#/$prefix}) + _comp_delimited , -X '*[{}]*' -W "$envs ALL" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1") --' -- "$cur")) + _comp_compgen_help + _comp_compgen -a -- -W '--' return fi } && - complete -F _tox tox + complete -F _comp_cmd_tox tox # ex: filetype=sh diff --git a/completions/tracepath b/completions/tracepath index 176534f..d8269bd 100644 --- a/completions/tracepath +++ b/completions/tracepath @@ -1,9 +1,9 @@ # tracepath(8) completion -*- shell-script -*- -_tracepath() +_comp_cmd_tracepath() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*[lmp]) @@ -12,15 +12,14 @@ _tracepath() esac if [[ $cur == -* ]]; then - local opts=$(_parse_help "$1") - COMPREPLY=($(compgen -W '${opts:-$(_parse_usage "$1")}' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage return fi local ipvx [[ $1 == *6 ]] && ipvx=-6 - _known_hosts_real ${ipvx-} -- "$cur" + _comp_compgen_known_hosts ${ipvx-} -- "$cur" } && - complete -F _tracepath tracepath tracepath6 + complete -F _comp_cmd_tracepath tracepath tracepath6 # ex: filetype=sh diff --git a/completions/tree b/completions/tree new file mode 100644 index 0000000..d274137 --- /dev/null +++ b/completions/tree @@ -0,0 +1,46 @@ +# tree(1) completion -*- shell-script -*- + +_comp_cmd_tree() +{ + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + + local noargopts='!(-*|*[LPIHTo]*)' + # shellcheck disable=SC2254 + case $prev in + -${noargopts}[LPIHT] | --filelimit | --timefmt | --help | --version) + return + ;; + --charset) + _comp_compgen -x iconv charsets + return + ;; + -${noargopts}o) + _comp_compgen_filedir + return + ;; + --sort) + _comp_compgen -- -W "name version size mtime ctime" + return + ;; + esac + + [[ $was_split ]] && return + + if [[ $cur == -* ]]; then + _comp_compgen_help + return + fi + + # Note: bash-4.2 has a bug with [[ ${arr[*]} == *text* ]], so we + # assign ${words[*]} in a temporary variable "line". + local line="${words[*]}" + if [[ $line == *\ --fromfile\ * ]]; then + _comp_compgen_filedir + else + _comp_compgen_filedir -d + fi +} && + complete -F _comp_cmd_tree tree + +# ex: filetype=sh diff --git a/completions/truncate b/completions/truncate new file mode 100644 index 0000000..94534a2 --- /dev/null +++ b/completions/truncate @@ -0,0 +1,32 @@ +# truncate(1) completion -*- shell-script -*- + +_comp_cmd_truncate() +{ + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + + local noargopts='!(-*|*[sr]*)' + # shellcheck disable=SC2254 + case $prev in + -${noargopts}s | --size | --help | --version) + return + ;; + -${noargopts}r | --reference) + _comp_compgen_filedir + return + ;; + esac + + [[ $was_split ]] && return + + if [[ $cur == -* ]]; then + _comp_compgen_help + [[ ${COMPREPLY-} == *= ]] && compopt -o nospace + return + fi + + _comp_compgen_filedir +} && + complete -F _comp_cmd_truncate truncate + +# ex: filetype=sh diff --git a/completions/tshark b/completions/tshark index 396fbcb..249670f 100644 --- a/completions/tshark +++ b/completions/tshark @@ -1,9 +1,9 @@ # tshark(1) completion -*- shell-script -*- -_tshark() +_comp_cmd_tshark() { - local cur prev words cword prefix - _init_completion -n : || return + local cur prev words cword comp_args prefix + _comp_initialize -n : -- "$@" || return case $cur in -o*) @@ -20,15 +20,14 @@ _tshark() ;; -o*) if [[ $cur == *:* ]]; then - cur=${cur#*:} - _filedir + _comp_compgen -c "${cur#*:}" filedir else - [[ -v _tshark_prefs ]] || - _tshark_prefs="$("$1" -G defaultprefs 2>/dev/null | command sed -ne 's/^#\{0,1\}\([a-z0-9_.-]\{1,\}:\).*/\1/p' | + [[ -v _comp_cmd_tshark__prefs ]] || + _comp_cmd_tshark__prefs="$("$1" -G defaultprefs 2>/dev/null | command sed -ne 's/^#\{0,1\}\([a-z0-9_.-]\{1,\}:\).*/\1/p' | tr '\n' ' ')" : ${prefix:=} - COMPREPLY=($(compgen -P "$prefix" -W "$_tshark_prefs" \ - -- "${cur:${#prefix}}")) + _comp_compgen -c "${cur:${#prefix}}" -- -P "$prefix" \ + -W "$_comp_cmd_tshark__prefs" [[ ${COMPREPLY-} == *: ]] && compopt -o nospace fi return @@ -37,8 +36,7 @@ _tshark() return ;; -*i) - COMPREPLY=($(compgen -W \ - "$("$1" -D 2>/dev/null | awk '{print $2}')" -- "$cur")) + _comp_compgen_split -- "$("$1" -D 2>/dev/null | _comp_awk '{print $2}')" return ;; -*y) @@ -49,88 +47,81 @@ _tshark() break fi done - COMPREPLY=($(compgen -W "$("$1" $opts -L 2>/dev/null | - awk '/^ / { print $1 }')" -- "$cur")) + # shellcheck disable=SC2086 + _comp_compgen_split -- "$("$1" $opts -L 2>/dev/null | + _comp_awk '/^ / { print $1 }')" return ;; -*[ab]) - COMPREPLY=($(compgen -W 'duration: filesize: files:' -- "$cur")) + _comp_compgen -- -W 'duration: filesize: files:' [[ ${COMPREPLY-} == *: ]] && compopt -o nospace return ;; -*[rH]) # -r accepts a lot of different file types - _filedir + _comp_compgen_filedir return ;; -*w) - _filedir + _comp_compgen_filedir [[ $cur == @(|-) ]] && COMPREPLY+=(-) return ;; -*F) - COMPREPLY=($(compgen -W "$("$1" -F 2>&1 | - awk '/^ / { print $1 }')" -- "$cur")) + _comp_compgen_split -- "$("$1" -F 2>&1 | _comp_awk '/^ / { print $1 }')" return ;; -*O) - local prefix= - [[ $cur == *,* ]] && prefix="${cur%,*}," - [[ -v _tshark_protocols ]] || - _tshark_protocols="$("$1" -G protocols 2>/dev/null | + [[ -v _comp_cmd_tshark__protocols ]] || + _comp_cmd_tshark__protocols="$("$1" -G protocols 2>/dev/null | cut -f 3 | tr '\n' ' ')" - COMPREPLY=($(compgen -W "$_tshark_protocols" -- "${cur##*,}")) - ((${#COMPREPLY[@]} == 1)) && COMPREPLY=(${COMPREPLY/#/$prefix}) + _comp_delimited , -W "$_comp_cmd_tshark__protocols" return ;; -*T) - # Parse from: tshark -T . 2>&1 | awk -F \" '/^\t*"/ { print $2 }' - COMPREPLY=($(compgen -W \ - 'pdml ps psml json jsonraw ek tabs text fields' -- "$cur")) + # Parse from: tshark -T . 2>&1 | _comp_awk -F \" '/^\t*"/ { print $2 }' + _comp_compgen -- -W 'pdml ps psml json jsonraw ek tabs text fields' return ;; -*t) - # Parse from: tshark -t . 2>&1 | awk -F \" '/^\t*"/ { print $2 }' - COMPREPLY=($(compgen -W \ - 'a ad adoy d dd e r u ud udoy' -- "$cur")) + # Parse from: tshark -t . 2>&1 | _comp_awk -F \" '/^\t*"/ { print $2 }' + _comp_compgen -- -W 'a ad adoy d dd e r u ud udoy' return ;; -*u) # TODO: could be parsed from "-u ." output - COMPREPLY=($(compgen -W 's hms' -- "$cur")) + _comp_compgen -- -W 's hms' return ;; -*W) - COMPREPLY=($(compgen -W 'n' -- "$cur")) + _comp_compgen -- -W 'n' return ;; -*X) if [[ ${cur:${#prefix}} == lua_script:* ]]; then - cur=${cur#*:} - _filedir lua + _comp_compgen -c "${cur#*:}" filedir lua else - COMPREPLY=($(compgen -P "$prefix" -W 'lua_script:' -- \ - "${cur:${#prefix}}")) + _comp_compgen -c "${cur:${#prefix}}" -- -P "$prefix" \ + -W 'lua_script:' [[ ${COMPREPLY-} == *: ]] && compopt -o nospace fi return ;; -*G) - COMPREPLY=($(compgen -W "$("$1" -G \? 2>/dev/null | - awk '/^[ \t]*-G / \ - { sub("^[[]","",$2); sub("[]]$","",$2); print $2 }')" \ - -- "$cur")) + _comp_compgen_split -- "$("$1" -G \? 2>/dev/null | + _comp_awk '/^[ \t]*-G / { + sub("^[[]","",$2); sub("[]]$","",$2); print $2 + }')" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h 2>/dev/null)' \ - -- "$cur")) + _comp_compgen_help -- -h return fi } && - complete -F _tshark tshark + complete -F _comp_cmd_tshark tshark # ex: filetype=sh diff --git a/completions/tsig-keygen b/completions/tsig-keygen index 017e9d8..01fabe8 100644 --- a/completions/tsig-keygen +++ b/completions/tsig-keygen @@ -1,28 +1,28 @@ # tsig-keygen(8) completion -*- shell-script -*- -_tsig_keygen() +_comp_cmd_tsig_keygen() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -h) return ;; -a) - COMPREPLY=($(compgen -W 'hmac-{md5,sha{1,224,256,384,512}}' -- "$cur")) + _comp_compgen -- -W 'hmac-{md5,sha{1,224,256,384,512}}' return ;; -r) - COMPREPLY=($(compgen -W keyboard -- "$cur")) - _filedir + _comp_compgen -- -W keyboard + _comp_compgen -a filedir return ;; esac [[ $cur != -* ]] || - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help } && - complete -F _tsig_keygen tsig-keygen + complete -F _comp_cmd_tsig_keygen tsig-keygen # ex: filetype=sh diff --git a/completions/tune2fs b/completions/tune2fs index 66d629c..6d62aa2 100644 --- a/completions/tune2fs +++ b/completions/tune2fs @@ -1,32 +1,32 @@ # tune2fs(8) completion -*- shell-script -*- -_tune2fs() +_comp_cmd_tune2fs() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*[cCEiJLmrT]) return ;; -*e) - COMPREPLY=($(compgen -W 'continue remount-ro panic' -- "$cur")) + _comp_compgen -- -W 'continue remount-ro panic' return ;; -*g) - _gids - COMPREPLY=($(compgen -g -W '${COMPREPLY[@]}' -- "$cur")) + _comp_compgen_gids + _comp_compgen -a -- -g return ;; -*M) - _filedir -d + _comp_compgen_filedir -d return ;; -*o) local -a opts=(^debug ^bsdgroups ^user_xattr ^acl ^uid16 ^journal_data ^journal_data_ordered ^journal_data_writeback ^nobarrier ^block_validity ^discard ^nodelalloc) - COMPREPLY=($(compgen -W '${opts[@]} ${opts[@]#^}' -- "$cur")) + _comp_compgen -- -W '"${opts[@]}" "${opts[@]#^}"' return ;; -*O) @@ -34,28 +34,27 @@ _tune2fs() ^filetype ^flex_bg ^has_journal ^huge_file ^large_file ^metadata_csum ^mmp ^project ^quota ^read-only ^resize_inode ^sparse_super ^uninit_bg) - COMPREPLY=($(compgen -W '${opts[@]} ${opts[@]#^}' -- "$cur")) + _comp_compgen -- -W '"${opts[@]}" "${opts[@]#^}"' return ;; -*u) - _uids - COMPREPLY=($(compgen -u -W '${COMPREPLY[@]}' -- "$cur")) + _comp_compgen_uids + _comp_compgen -a -- -u return ;; -*U) - COMPREPLY=($(compgen -W 'clear random time' -- "$cur")) + _comp_compgen -- -W 'clear random time' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage return fi - cur=${cur:=/dev/} - _filedir + _comp_compgen -c "${cur:-/dev/}" filedir } && - complete -F _tune2fs tune2fs + complete -F _comp_cmd_tune2fs tune2fs # ex: filetype=sh diff --git a/completions/ulimit b/completions/ulimit index e596bf7..9f6f13b 100644 --- a/completions/ulimit +++ b/completions/ulimit @@ -1,16 +1,16 @@ # bash completion for ulimit -*- shell-script -*- -_ulimit() +_comp_cmd_ulimit() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return # TODO combined option support (-aH, -Sc etc) - local mode + local mode= case $prev in -a) - COMPREPLY=($(compgen -W "-S -H" -- "$cur")) + _comp_compgen -- -W "-S -H" return ;; -[SH]) ;; @@ -20,23 +20,20 @@ _ulimit() ;; esac - if [[ ! -v mode ]]; then + if [[ ! $mode ]]; then local word for word in "${words[@]}"; do [[ $word == -*a* ]] && return done if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage -c help -s "$1" return fi fi - local args - _count_args - ((args == 1)) && - COMPREPLY=($(compgen -W "soft hard unlimited" -- "$cur")) + [[ ${mode-} ]] && _comp_compgen -- -W "soft hard unlimited" } && - complete -F _ulimit ulimit + complete -F _comp_cmd_ulimit ulimit # ex: filetype=sh diff --git a/completions/unace b/completions/unace index 7d6bd42..da647b8 100644 --- a/completions/unace +++ b/completions/unace @@ -1,20 +1,20 @@ # unace(1) completion -*- shell-script -*- -_unace() +_comp_cmd_unace() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-c -c- -f -f- -o -o- -p -y -y-' -- "$cur")) + _comp_compgen -- -W '-c -c- -f -f- -o -o- -p -y -y-' else if ((cword == 1)); then - COMPREPLY=($(compgen -W 'e l t v x' -- "$cur")) + _comp_compgen -- -W 'e l t v x' else - _filedir ace + _comp_compgen_filedir '@(ace|cba)' fi fi } && - complete -F _unace unace + complete -F _comp_cmd_unace unace # ex: filetype=sh diff --git a/completions/unpack200 b/completions/unpack200 index 8814259..3724f37 100644 --- a/completions/unpack200 +++ b/completions/unpack200 @@ -1,48 +1,50 @@ # unpack200(1) completion -*- shell-script -*- -_unpack200() +_comp_cmd_unpack200() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[Hl]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | -!(-*)[?hVJ]) + --help | --version | -${noargopts}[?hVJ]) return ;; - --deflate-hint | -!(-*)H) - COMPREPLY=($(compgen -W 'true false keep' -- "$cur")) + --deflate-hint | -${noargopts}H) + _comp_compgen -- -W 'true false keep' return ;; - --log-file | -!(-*)l) - COMPREPLY=($(compgen -W '-' -- "$cur")) - _filedir log + --log-file | -${noargopts}l) + _comp_compgen -- -W '-' + _comp_compgen -a filedir log return ;; esac - $split && return + [[ $was_split ]] && return # Check if a pack or a jar was already given. - local word pack=false jar=false + local word pack="" jar="" for word in "${words[@]:1}"; do case $word in - *.pack | *.pack.gz) pack=true ;; - *.jar) jar=true ;; + *.pack | *.pack.gz) pack=set ;; + *.jar) jar=set ;; esac done - if ! $pack; then + if [[ ! $pack ]]; then if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--deflate-hint= --remove-pack-file - --verbose --quiet --log-file= --help --version' -- "$cur")) + _comp_compgen -- -W '--deflate-hint= --remove-pack-file --verbose + --quiet --log-file= --help --version' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace else - _filedir 'pack?(.gz)' + _comp_compgen_filedir 'pack?(.gz)' fi - elif ! $jar; then - _filedir jar + elif [[ ! $jar ]]; then + _comp_compgen_filedir jar fi } && - complete -F _unpack200 unpack200 + complete -F _comp_cmd_unpack200 unpack200 # ex: filetype=sh diff --git a/completions/unrar b/completions/unrar index 4cbac8f..f3d4549 100644 --- a/completions/unrar +++ b/completions/unrar @@ -1,23 +1,23 @@ # unrar(1) completion -*- shell-script -*- -_unrar() +_comp_cmd_unrar() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-ad -ap -av- -c- -cfg- -cl -cu -dh -ep -f - -idp -ierr -inul -kb -o+ -o- -ow -p -p- -r -ta -tb -tn -to -u -v - -ver -vp -x -x@ -y' -- "$cur")) + _comp_compgen -- -W '-ad -ap -av- -c- -cfg- -cl -cu -dh -ep -f -idp + -ierr -inul -kb -o+ -o- -ow -p -p- -r -ta -tb -tn -to -u -v -ver + -vp -x -x@ -y' else if ((cword == 1)); then - COMPREPLY=($(compgen -W 'e l lb lt p t v vb vt x' -- "$cur")) + _comp_compgen -- -W 'e l lb lt p t v vb vt x' else - _filedir '@(rar|exe)' + _comp_compgen_filedir '@(rar|exe|cbr)' fi fi } && - complete -F _unrar unrar + complete -F _comp_cmd_unrar unrar # ex: filetype=sh diff --git a/completions/unshunt b/completions/unshunt index 95a1601..0486d1f 100644 --- a/completions/unshunt +++ b/completions/unshunt @@ -1,17 +1,17 @@ # mailman unshunt completion -*- shell-script -*- -_unshunt() +_comp_cmd_unshunt() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help else - _filedir -d + _comp_compgen_filedir -d fi } && - complete -F _unshunt unshunt + complete -F _comp_cmd_unshunt unshunt # ex: filetype=sh diff --git a/completions/update-alternatives b/completions/update-alternatives index 25d2ce6..0d678fc 100644 --- a/completions/update-alternatives +++ b/completions/update-alternatives @@ -1,8 +1,8 @@ # bash completion for update-alternatives -*- shell-script -*- -_installed_alternatives() +_comp_cmd_update_alternatives__installed() { - local admindir + local i admindir # find the admin dir for i in alternatives dpkg/alternatives rpm/alternatives; do [[ -d /var/lib/$i ]] && admindir=/var/lib/$i && break @@ -13,17 +13,17 @@ _installed_alternatives() break fi done - COMPREPLY=($(compgen -W '$(command ls $admindir)' -- "$cur")) + [[ -d $admindir ]] && _comp_compgen_split -- "$(command ls "$admindir")" } -_update_alternatives() +_comp_cmd_update_alternatives() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --altdir | --admindir) - _filedir -d + _comp_compgen_filedir -d return ;; --help | --usage | --version) @@ -31,7 +31,7 @@ _update_alternatives() ;; esac - local mode args i + local mode="" args i # find which mode to use and how many real args used so far for ((i = 1; i < cword; i++)); do @@ -46,10 +46,10 @@ _update_alternatives() --install) case $args in 1 | 3) - _filedir + _comp_compgen_filedir ;; 2) - _installed_alternatives + _comp_cmd_update_alternatives__installed ;; 4) # priority - no completions @@ -57,13 +57,13 @@ _update_alternatives() *) case $((args % 4)) in 0 | 2) - _filedir + _comp_compgen_filedir ;; 1) - COMPREPLY=($(compgen -W '--slave' -- "$cur")) + _comp_compgen -- -W '--slave' ;; 3) - _installed_alternatives + _comp_cmd_update_alternatives__installed ;; esac ;; @@ -72,21 +72,21 @@ _update_alternatives() --remove | --set) case $args in 1) - _installed_alternatives + _comp_cmd_update_alternatives__installed ;; 2) - _filedir + _comp_compgen_filedir ;; esac ;; --auto | --remove-all | --display | --config) - _installed_alternatives + _comp_cmd_update_alternatives__installed ;; *) - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help ;; esac } && - complete -F _update_alternatives update-alternatives alternatives + complete -F _comp_cmd_update_alternatives update-alternatives alternatives # ex: filetype=sh diff --git a/completions/update-rc.d b/completions/update-rc.d index 9b281d5..a5040d4 100644 --- a/completions/update-rc.d +++ b/completions/update-rc.d @@ -2,57 +2,57 @@ # # Copyright (C) 2004 Servilio Afre Puentes <servilio@gmail.com> -_update_rc_d() +_comp_cmd_update_rc_d() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local sysvdir services options [[ -d /etc/rc.d/init.d ]] && sysvdir=/etc/rc.d/init.d || sysvdir=/etc/init.d - services=($(printf '%s ' $sysvdir/!(README*|*.sh|$_backup_glob))) - services=(${services[@]#$sysvdir/}) + _comp_expand_glob services '"$sysvdir"/!(README*|*.sh|$_comp_backup_glob)' && + services=("${services[@]#$sysvdir/}") options=(-f -n) if [[ $cword -eq 1 || $prev == -* ]]; then - COMPREPLY=($(compgen -W '${options[@]} ${services[@]}' \ - -X '$(tr " " "|" <<<${words[@]})' -- "$cur")) - elif [[ $prev == ?($(tr " " "|" <<<"${services[*]}")) ]]; then - COMPREPLY=($(compgen -W 'remove defaults start stop' -- "$cur")) + _comp_compgen -- -W '"${options[@]}" ${services[@]+"${services[@]}"}' \ + -X '$(tr " " "|" <<<${words[@]})' + elif ((${#services[@]})) && [[ $prev == ?($(tr " " "|" <<<"${services[*]}")) ]]; then + _comp_compgen -- -W 'remove defaults start stop' elif [[ $prev == defaults && $cur == [0-9] ]]; then COMPREPLY=(0 1 2 3 4 5 6 7 8 9) elif [[ $prev == defaults && $cur == [sk]?([0-9]) ]]; then COMPREPLY=(0 1 2 3 4 5 6 7 8 9) - elif [[ $prev == defaults && -z $cur ]]; then + elif [[ $prev == defaults && ! $cur ]]; then COMPREPLY=(0 1 2 3 4 5 6 7 8 9 s k) elif [[ $prev == ?(start|stop) ]]; then - if [[ $cur == [0-9] || -z $cur ]]; then + if [[ $cur == [0-9] || ! $cur ]]; then COMPREPLY=(0 1 2 3 4 5 6 7 8 9) elif [[ $cur == [0-9][0-9] ]]; then - COMPREPLY=($cur) + COMPREPLY=("$cur") else COMPREPLY=() fi elif [[ $prev == ?([0-9][0-9]|[0-6S]) ]]; then - if [[ -z $cur ]]; then + if [[ ! $cur ]]; then if [[ $prev == [0-9][0-9] ]]; then COMPREPLY=(0 1 2 3 4 5 6 S) else COMPREPLY=(0 1 2 3 4 5 6 S .) fi elif [[ $cur == [0-6S.] ]]; then - COMPREPLY=($cur) + COMPREPLY=("$cur") else COMPREPLY=() fi elif [[ $prev == "." ]]; then - COMPREPLY=($(compgen -W "start stop" -- "$cur")) + _comp_compgen -- -W "start stop" else COMPREPLY=() fi } && - complete -F _update_rc_d update-rc.d + complete -F _comp_cmd_update_rc_d update-rc.d # ex: filetype=sh diff --git a/completions/upgradepkg b/completions/upgradepkg index d3ce608..f359e9a 100644 --- a/completions/upgradepkg +++ b/completions/upgradepkg @@ -1,30 +1,28 @@ # Slackware Linux upgradepkg completion -*- shell-script -*- -_upgradepkg() +_comp_cmd_upgradepkg() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--dry-run --install-new --reinstall - --verbose' -- "$cur")) + _comp_compgen -- -W '--dry-run --install-new --reinstall --verbose' return fi if [[ $cur == ?*%* ]]; then prev="${cur%%?(\\)%*}" cur="${cur#*%}" - local nofiles IFS=$'\n' + local nofiles="" compopt -o filenames - COMPREPLY=($(compgen -P "$prev%" -f -X "!*.@(t[bgxl]z)" -- "$cur")) - [[ ${COMPREPLY-} ]] || nofiles=1 - COMPREPLY+=($(compgen -P "$prev%" -S '/' -d -- "$cur")) - [[ -v nofiles ]] && compopt -o nospace + _comp_compgen -- -P "$prev%" -f -X "!*.@(t[bgxl]z)" || nofiles=set + _comp_compgen -a -- -P "$prev%" -S '/' -d + [[ $nofiles ]] && compopt -o nospace return fi - _filedir 't[bglx]z' + _comp_compgen_filedir 't[bglx]z' } && - complete -F _upgradepkg upgradepkg + complete -F _comp_cmd_upgradepkg upgradepkg # ex: filetype=sh diff --git a/completions/urlsnarf b/completions/urlsnarf index e327076..6ac58a4 100644 --- a/completions/urlsnarf +++ b/completions/urlsnarf @@ -1,26 +1,26 @@ # urlsnarf completion -*- shell-script -*- -_urlsnarf() +_comp_cmd_urlsnarf() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*i) - _available_interfaces -a + _comp_compgen_available_interfaces -a return ;; -*p) - _filedir pcap + _comp_compgen_filedir pcap return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage fi } && - complete -F _urlsnarf urlsnarf + complete -F _comp_cmd_urlsnarf urlsnarf # ex: filetype=sh diff --git a/completions/uscan b/completions/uscan index 441bae3..e82f625 100644 --- a/completions/uscan +++ b/completions/uscan @@ -1,33 +1,34 @@ -# uscan completion -*- shell-script -*- +# uscan completion -*- shell-script -*- -_uscan() +_comp_cmd_uscan() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in --package) - COMPREPLY=($(_xfunc apt-cache _apt_cache_src_packages)) + _comp_compgen -x apt-cache sources return ;; --watchfile) - _filedir + _comp_compgen_filedir return ;; --destdir) - _filedir -d + _comp_compgen_filedir -d return ;; - --timeout | --upstream-version | --download-version | --check-dirname-level | --check-dirname-regex) + --timeout | --upstream-version | --download-version | \ + --check-dirname-level | --check-dirname-regex) COMPREPLY=() return ;; esac - $split && return + [[ $was_split ]] && return - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help } && - complete -F _uscan uscan + complete -F _comp_cmd_uscan uscan # ex: filetype=sh diff --git a/completions/useradd b/completions/useradd index ceeca91..6c0bef1 100644 --- a/completions/useradd +++ b/completions/useradd @@ -1,46 +1,57 @@ # useradd(8) completion -*- shell-script -*- -_useradd() +_comp_cmd_useradd() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return # TODO: if -o/--non-unique is given, could complete on existing uids # with -u/--uid + local word chroot="" has_chroot="" + for word in "${words[@]}"; do + if [[ $has_chroot ]]; then + chroot=$word + break + fi + [[ $word != -@(R|-root) ]] || has_chroot=set + done + + local noargopts='!(-*|*[cefKpubdkRgGZs]*)' + # shellcheck disable=SC2254 case $prev in - --comment | --help | --expiredate | --inactive | --key | --password | --uid | \ - --selinux-user | -!(-*)[chefKpuZ]) + --comment | --help | --expiredate | --inactive | --key | --password | \ + --uid | -${noargopts}[chefKpu]) + return + ;; + --base-dir | --home-dir | --skel | --root | -${noargopts}[bdkR]) + _comp_compgen_filedir -d return ;; - --base-dir | --home-dir | --skel | --root | -!(-*)[bdkR]) - _filedir -d + --gid | -${noargopts}g) + _comp_compgen_gids + _comp_compgen -a -- -g return ;; - --gid | -!(-*)g) - _gids - COMPREPLY=($(compgen -W '${COMPREPLY[@]} $(compgen -g)' \ - -- "$cur")) + --groups | -${noargopts}G) + _comp_delimited , -g return ;; - --groups | -!(-*)G) - local prefix= - [[ $cur == *,* ]] && prefix="${cur%,*}," - COMPREPLY=($(compgen -g -- "${cur##*,}")) - ((${#COMPREPLY[@]} == 1)) && COMPREPLY=(${COMPREPLY/#/$prefix}) + --selinux-user | -${noargopts}Z) + _comp_compgen_selinux_users return ;; - --shell | -!(-*)s) - _shells + --shell | -${noargopts}s) + _comp_compgen_shells "${chroot-}" return ;; esac - $split && return + [[ $was_split ]] && return [[ $cur == -* ]] && - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help } && - complete -F _useradd useradd + complete -F _comp_cmd_useradd useradd # ex: filetype=sh diff --git a/completions/userdel b/completions/userdel index ed98447..e95da5c 100644 --- a/completions/userdel +++ b/completions/userdel @@ -1,27 +1,29 @@ # userdel(8) completion -*- shell-script -*- -_userdel() +_comp_cmd_userdel() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[R]*)' + # shellcheck disable=SC2254 case $prev in - --help | -!(-*)h) + --help | -${noargopts}h) return ;; - --root | -!(-*)R) - _filedir -d + --root | -${noargopts}R) + _comp_compgen_filedir -d return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u } && - complete -F _userdel userdel + complete -F _comp_cmd_userdel userdel # ex: filetype=sh diff --git a/completions/usermod b/completions/usermod index 77ab33c..797e536 100644 --- a/completions/usermod +++ b/completions/usermod @@ -1,51 +1,62 @@ # usermod(8) completion -*- shell-script -*- -_usermod() +_comp_cmd_usermod() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return # TODO: if -o/--non-unique is given, could complete on existing uids # with -u/--uid + local word chroot="" has_chroot="" + for word in "${words[@]}"; do + if [[ $has_chroot ]]; then + chroot=$word + break + fi + [[ $word != -@(R|-root) ]] || has_chroot=set + done + + local noargopts='!(-*|*[cdeflpugGRZs]*)' + # shellcheck disable=SC2254 case $prev in - --comment | --home | --expiredate | --inactive | --help | --login | --password | \ - --uid | --selinux-user | -!(-*)[cdefhlpuZ]) + --comment | --home | --expiredate | --inactive | --help | --login | \ + --password | --uid | -${noargopts}[cdefhlpu]) + return + ;; + --gid | -${noargopts}g) + _comp_compgen_gids + _comp_compgen -a -- -g return ;; - --gid | -!(-*)g) - _gids - COMPREPLY=($(compgen -W '${COMPREPLY[@]} $(compgen -g)' \ - -- "$cur")) + --groups | -${noargopts}G) + _comp_delimited , -g return ;; - --groups | -!(-*)G) - local prefix= - [[ $cur == *,* ]] && prefix="${cur%,*}," - COMPREPLY=($(compgen -g -- "${cur##*,}")) - ((${#COMPREPLY[@]} == 1)) && COMPREPLY=(${COMPREPLY/#/$prefix}) + --root | -${noargopts}R) + _comp_compgen_filedir -d return ;; - --root | -!(-*)R) - _filedir -d + --selinux-user | -${noargopts}Z) + _comp_compgen_selinux_users return ;; - --shell | -!(-*)s) - _shells + --shell | -${noargopts}s) + _comp_compgen_shells "${chroot-}" return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then # TODO: -U/--unlock, -p/--password, -L/--lock mutually exclusive - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - COMPREPLY=($(compgen -u -- "$cur")) + _comp_compgen -- -u } && - complete -F _usermod usermod + complete -F _comp_cmd_usermod usermod # ex: filetype=sh diff --git a/completions/valgrind b/completions/valgrind index f541161..7043aa3 100644 --- a/completions/valgrind +++ b/completions/valgrind @@ -1,22 +1,19 @@ # valgrind(1) completion -*- shell-script -*- -_valgrind() +_comp_cmd_valgrind() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return local i - # Note: intentionally using COMP_WORDS and COMP_CWORD instead of - # words and cword here due to splitting on = causing index differences - # (_command_offset assumes the former). - for ((i = 1; i <= COMP_CWORD; i++)); do - if [[ ${COMP_WORDS[i]} != @([-=])* && ${COMP_WORDS[i - 1]} != = ]]; then - _command_offset $i + for ((i = 1; i <= cword; i++)); do + if [[ ${words[i]} != @([-=])* ]]; then + _comp_command_offset $i return fi done - local word tool + local word tool="" for word in "${words[@]:1}"; do if [[ $word == --tool=?* ]]; then tool=$word @@ -31,81 +28,83 @@ _valgrind() --tool) # Tools seem to be named e.g. like memcheck-amd64-linux from which # we want to grab memcheck. - COMPREPLY=($(compgen -W '$( - for f in /usr{,/local}/lib{,64,exec}{/*-linux-gnu,}/valgrind/* - do - [[ $f != *.so && -x $f && $f =~ ^.*/(.*)-[^-]+-[^-]+ ]] && - printf "%s\n" "${BASH_REMATCH[1]}" - done)' -- "$cur")) + local -a files + if _comp_expand_glob files '/usr{,/local}/lib{,64,exec}{/*-linux-gnu,}/valgrind/*'; then + _comp_compgen_split -- "$( + for f in "${files[@]}"; do + [[ $f != *.so && -x $f && $f =~ ^.*/(.*)-[^-]+-[^-]+ ]] && + printf '%s\n' "${BASH_REMATCH[1]}" + done + )" + fi return ;; --sim-hints) - COMPREPLY=($(compgen -W 'lax-ioctls enable-outer' -- "$cur")) + _comp_compgen -- -W 'lax-ioctls enable-outer' return ;; --soname-synonyms) - COMPREPLY=($(compgen -W 'somalloc' -S = -- "$cur")) + _comp_compgen -- -W 'somalloc' -S = [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return ;; --kernel-variant) - COMPREPLY=($(compgen -W 'bproc' -- "$cur")) + _comp_compgen -- -W 'bproc' return ;; # callgrind: --callgrind-out-file) - _filedir + _comp_compgen_filedir return ;; # exp-dhat: --sort-by) - COMPREPLY=($(compgen -W 'max-bytes-live tot-bytes-allocd - max-blocks-live' -- "$cur")) + _comp_compgen -- -W 'max-bytes-live tot-bytes-allocd + max-blocks-live' return ;; # massif: --time-unit) - COMPREPLY=($(compgen -W 'i ms B' -- "$cur")) + _comp_compgen -- -W 'i ms B' return ;; # generic cases parsed from --help output --+([-A-Za-z0-9_])) - local value=$($1 --help-debug ${tool-} 2>/dev/null | - command sed -ne "s|^[[:blank:]]*$prev=\([^[:blank:]]\{1,\}\).*|\1|p") + # shellcheck disable=SC2086 + local value=$("$1" --help-debug $tool 2>/dev/null | + command sed \ + -ne "s|^[[:blank:]]*$prev=\([^[:blank:]]\{1,\}\).*|\1|p") case $value in \<file*\>) - _filedir + _comp_compgen_filedir return ;; \<command\>) - compopt -o filenames - COMPREPLY=($(compgen -c -- "$cur")) + _comp_compgen_commands return ;; \<+([0-9])..+([0-9])\>) - COMPREPLY=($(compgen -W "{${value:1:${#value}-2}}" \ - -- "$cur")) + _comp_compgen -- -W "{${value:1:${#value}-2}}" return ;; # "yes", "yes|no", etc (but not "string", "STR", # "hint1,hint2,...") yes | +([-a-z0-9])\|+([-a-z0-9\|])) - COMPREPLY=($(IFS='|' compgen -W '$value' -- "$cur")) + _comp_compgen -F '|' -- -W '$value' return ;; esac ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" "--help ${tool-}")' \ - -- "$cur")) + _comp_compgen_help -- --help ${tool:+"$tool"} [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi } && - complete -F _valgrind valgrind + complete -F _comp_cmd_valgrind valgrind # ex: filetype=sh diff --git a/completions/vipw b/completions/vipw index b3a7415..bfaa48a 100644 --- a/completions/vipw +++ b/completions/vipw @@ -1,22 +1,24 @@ # vipw(8) and vigr completion -*- shell-script -*- -_vipw() +_comp_cmd_vipw() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[R]*)' + # shellcheck disable=SC2254 case $prev in - --help | -!(-*)h) + --help | -${noargopts}h) return ;; - --root | -!(-*)R) - _filedir -d + --root | -${noargopts}R | -d) + _comp_compgen_filedir -d return ;; esac - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage } && - complete -F _vipw vipw vigr + complete -F _comp_cmd_vipw vipw vigr # ex: filetype=sh diff --git a/completions/vmstat b/completions/vmstat index e36934a..36f9bb8 100644 --- a/completions/vmstat +++ b/completions/vmstat @@ -1,27 +1,29 @@ # vmstat(8) completion -*- shell-script -*- -_vmstat() +_comp_cmd_vmstat() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local noargopts='!(-*|*[cMNnwpS]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | --partition | -!(-*)[hVcMNnwp]) + --help | --version | --partition | -${noargopts}[hVcMNnwp]) return ;; - --unit | -!(-*)S) + --unit | -${noargopts}S) [[ $OSTYPE == *linux* ]] && - COMPREPLY=($(compgen -W 'k K m M' -- "$cur")) + _comp_compgen -- -W 'k K m M' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} ]] || - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage fi } && - complete -F _vmstat vmstat + complete -F _comp_cmd_vmstat vmstat # ex: filetype=sh diff --git a/completions/vncviewer b/completions/vncviewer index ba55226..17dd7da 100644 --- a/completions/vncviewer +++ b/completions/vncviewer @@ -1,74 +1,74 @@ # bash completion for vncviewer -*- shell-script -*- -_vncviewer_bootstrap() +_comp_cmd_vncviewer__bootstrap() { - local fname - case $(_realcommand vncviewer) in - *xvnc4viewer) fname=_xvnc4viewer ;; - *tightvncviewer) fname=_tightvncviewer ;; - *) fname=_known_hosts ;; + local fname REPLY + _comp_realcommand vncviewer + case $REPLY in + *xvnc4viewer) fname=_comp_cmd_xvnc4viewer ;; + *tightvncviewer) fname=_comp_cmd_tightvncviewer ;; + *) fname=_comp_complete_known_hosts ;; esac # Install real completion for subsequent completions complete -F $fname vncviewer - $fname # Generate completions once for now - unset -f _vncviewer_bootstrap + $fname "$@" # Generate completions once for now + unset -f "$FUNCNAME" } && - complete -F _vncviewer_bootstrap vncviewer + complete -F _comp_cmd_vncviewer__bootstrap vncviewer -_tightvncviewer() +_comp_cmd_tightvncviewer() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -passwd) - _filedir + _comp_compgen_filedir return ;; -encodings) - COMPREPLY=($(compgen -W 'copyrect tight hextile zlib corre rre - raw' -- "$cur")) + _comp_compgen -- -W 'copyrect tight hextile zlib corre rre raw' return ;; -via) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-help -listen -via -shared -noshared - -viewonly -fullscreen -noraiseonbeep -passwd -encodings -bgr233 - -owncmap -truecolour -truecolor -depth -compresslevel -quality - -nojpeg -nocursorshape -x11cursor' -- "$cur")) + _comp_compgen -- -W '-help -listen -via -shared -noshared -viewonly + -fullscreen -noraiseonbeep -passwd -encodings -bgr233 -owncmap + -truecolour -truecolor -depth -compresslevel -quality -nojpeg + -nocursorshape -x11cursor' else - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" fi } && - complete -F _tightvncviewer tightvncviewer + complete -F _comp_cmd_tightvncviewer tightvncviewer # NOTE: - VNC Viewer options are case insensitive. # Preferred case is taken from -help. -_xvnc4viewer() +_comp_cmd_xvnc4viewer() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return # Both single dash (-) and double dash (--) are allowed as option prefix local opt=${prev/#--/-} case ${opt,,} in # -passwd, -PasswordFile -passwd | -passwordfile) - _filedir + _comp_compgen_filedir return ;; -preferredencoding) - COMPREPLY=($(compgen -W 'zrle hextile raw' -- "$cur")) + _comp_compgen -- -W 'zrle hextile raw' return ;; -via) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; esac @@ -83,17 +83,17 @@ _xvnc4viewer() WMDecorationWidth ZlibLevel) [[ $cur == --* ]] && dash=-- || dash=- - local IFS=$' \t\n' reset=$(shopt -p nocasematch) - shopt -s nocasematch - local option - COMPREPLY=($(for option in "${options[@]}"; do - [[ $dash$option == "$cur"* ]] && printf '%s\n' $dash$option - done)) - $reset + _comp_split COMPREPLY "$( + shopt -s nocasematch + local option + for option in "${options[@]}"; do + [[ $dash$option == "$cur"* ]] && printf '%s\n' "$dash$option" + done + )" else - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" fi } && - complete -F _xvnc4viewer xvnc4viewer + complete -F _comp_cmd_xvnc4viewer xvnc4viewer # ex: filetype=sh diff --git a/completions/vpnc b/completions/vpnc index bbdb8ee..79ffff3 100644 --- a/completions/vpnc +++ b/completions/vpnc @@ -1,82 +1,78 @@ # bash completion for vpnc -*- shell-script -*- -_vpnc() +_comp_cmd_vpnc() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in - --help | --long-help | --version | --id | --username | --domain | --ifname | \ - --application-version | --local-addr | --local-port | --udp-port | --dpd-idle | \ - --target-network | --ifmtu) + --help | --long-help | --version | --id | --username | --domain | \ + --ifname | --application-version | --local-addr | --local-port | \ + --udp-port | --dpd-idle | --target-network | --ifmtu) return ;; --gateway) - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" return ;; --vendor) - COMPREPLY=($(compgen -W 'cisco netscreen' -- "$cur")) + _comp_compgen -- -W 'cisco netscreen' return ;; --natt-mode) - COMPREPLY=($(compgen -W 'natt none force-natt cisco-udp' \ - -- "$cur")) + _comp_compgen -- -W 'natt none force-natt cisco-udp' return ;; --script | --pid-file | --ca-file) - _filedir + _comp_compgen_filedir return ;; --dh) - COMPREPLY=($(compgen -W 'dh1 dh2 dh5' -- "$cur")) + _comp_compgen -- -W 'dh1 dh2 dh5' return ;; --pfs) - COMPREPLY=($(compgen -W 'nopfs dh1 dh2 dh5 server' -- "$cur")) + _comp_compgen -- -W 'nopfs dh1 dh2 dh5 server' return ;; --ifmode) - COMPREPLY=($(compgen -W 'tun tap' -- "$cur")) + _comp_compgen -- -W 'tun tap' return ;; --debug) - COMPREPLY=($(compgen -W '0 1 2 3 99' -- "$cur")) + _comp_compgen -- -W '0 1 2 3 99' return ;; --auth-mode) - COMPREPLY=($(compgen -W 'psk cert hybrid' -- "$cur")) + _comp_compgen -- -W 'psk cert hybrid' return ;; --ca-dir) - _filedir -d + _comp_compgen_filedir -d return ;; --password-helper) - compopt -o filenames - COMPREPLY=($(compgen -c -- "$cur")) + _comp_compgen_commands return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" --long-help)' -- "$cur")) - elif [[ $cur == */* ]]; then + _comp_compgen_help -- --long-help + elif _comp_looks_like_path "$cur"; then # explicit filename - _filedir conf + _comp_compgen_filedir conf else # config name, /etc/vpnc/<name>.conf - local IFS=$' \t\n' reset=$(shopt -p nullglob) - shopt -s nullglob - local -a configs=(/etc/vpnc/*.conf) - configs=("${configs[@]##*/}") - configs=("${configs[@]%.conf}") - $reset - IFS=$'\n' - compopt -o filenames - COMPREPLY=($(compgen -W '${configs[@]}' -- "$cur")) + local -a configs + if _comp_expand_glob configs '/etc/vpnc/*.conf'; then + configs=("${configs[@]##*/}") + configs=("${configs[@]%.conf}") + compopt -o filenames + _comp_compgen -- -W '"${configs[@]}"' + fi fi } && - complete -F _vpnc vpnc + complete -F _comp_cmd_vpnc vpnc # ex: filetype=sh diff --git a/completions/watch b/completions/watch index efc0a98..443bed3 100644 --- a/completions/watch +++ b/completions/watch @@ -1,19 +1,21 @@ # watch(1) completion -*- shell-script -*- -[[ $OSTYPE == *linux* ]] || return 1 +[[ $OSTYPE == *@(linux|darwin)* ]] || return 1 -_watch() +_comp_cmd_watch() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return local offset=0 i + local noargopts='!(-*|*[dn]*)' + # shellcheck disable=SC2254 for ((i = 1; i <= cword; i++)); do case ${words[i]} in - --help | --version | -!(-*)h) + --help | --version | -${noargopts}h) return ;; - --interval | -!(-*)n) + --interval | -${noargopts}n) ((i++)) continue ;; @@ -26,29 +28,30 @@ _watch() done if ((offset > 0)); then - _command_offset $offset + _comp_command_offset $offset return fi + # shellcheck disable=SC2254 case $prev in - --differences | -!(-*)d) + --differences | -${noargopts}d) [[ $cur != -* ]] && - COMPREPLY=($(compgen -W 'cumulative' -- "$cur")) + _comp_compgen -- -W 'cumulative' return ;; - --interval | -!(-*)n) + --interval | -${noargopts}n) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi } && - complete -F _watch watch + complete -F _comp_cmd_watch watch # ex: filetype=sh diff --git a/completions/webmitm b/completions/webmitm index 549c5ef..df6faa2 100644 --- a/completions/webmitm +++ b/completions/webmitm @@ -1,17 +1,17 @@ # webmitm completion -*- shell-script -*- -_webmitm() +_comp_cmd_webmitm() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_usage else - _known_hosts_real -- "$cur" + _comp_compgen_known_hosts -- "$cur" fi } && - complete -F _webmitm webmitm + complete -F _comp_cmd_webmitm webmitm # ex: filetype=sh diff --git a/completions/wget b/completions/wget index d6a2fe9..fcc59aa 100644 --- a/completions/wget +++ b/completions/wget @@ -1,24 +1,26 @@ # wget(1) completion -*- shell-script -*- -_wget() +_comp_cmd_wget() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[DPoaOitTwlQeBUARIX]*)' + # shellcheck disable=SC2254 case $prev in - --version | --help | -!(-*)[hV]) + --version | --help | -${noargopts}[hV]) return ;; --progress) - COMPREPLY=($(compgen -W 'bar dot' -- "$cur")) + _comp_compgen -- -W 'bar dot' return ;; --bind-address) - _ip_addresses + _comp_compgen_ip_addresses return ;; - --domains | --exclude-domains | -!(-*)D) - _known_hosts_real -- "$cur" + --domains | --exclude-domains | -${noargopts}D) + _comp_compgen_known_hosts -- "$cur" return ;; --restrict-file-names) @@ -47,84 +49,87 @@ _wget() local lastopt=${cur/*,/} prevopt= [[ $cur == *,* ]] && prevopt=${cur%,*}, - COMPREPLY=($(compgen -P "$prevopt" -X "@($excludes_str)" \ - -W 'unix windows nocontrol ascii lowercase uppercase' \ - -- "$lastopt")) + _comp_compgen -c "$lastopt" -- -P "$prevopt" \ + -X "@($excludes_str)" \ + -W 'unix windows nocontrol ascii lowercase uppercase' # +o nospace when no more valid option is possible (= append a space) - local opt_as_arr=(${COMPREPLY[0]//,/ }) + local -a opt_as_arr + _comp_split -F $', \t\n' opt_as_arr "${COMPREPLY[0]}" ((${#opt_as_arr[@]} < 4)) && compopt -o nospace return ;; --prefer-family) - COMPREPLY=($(compgen -W 'IPv4 IPv6 none' -- "$cur")) + _comp_compgen -- -W 'IPv4 IPv6 none' return ;; - --directory-prefix | --ca-directory | --warc-tempdir | -!(-*)P) - _filedir -d + --directory-prefix | --ca-directory | --warc-tempdir | -${noargopts}P) + _comp_compgen_filedir -d return ;; - --output-file | --append-output | --config | --load-cookies | --save-cookies | \ - --post-file | --certificate | --ca-certificate | --private-key | \ - --random-file | --egd-file | --warc-file | --warc-dedup | -!(-*)[oa]) - _filedir + --output-file | --append-output | --config | --load-cookies | \ + --save-cookies | --post-file | --certificate | --ca-certificate | \ + --private-key | --random-file | --egd-file | --warc-file | \ + --warc-dedup | -${noargopts}[oa]) + _comp_compgen_filedir return ;; - --output-document | --input-file | -!(-*)[Oi]) - _filedir && [[ $cur == - || -z $cur ]] && COMPREPLY+=(-) + --output-document | --input-file | -${noargopts}[Oi]) + _comp_compgen_filedir && [[ $cur == - || ! $cur ]] && COMPREPLY+=(-) return ;; --secure-protocol) - COMPREPLY=($(compgen -W 'auto SSLv2 SSLv3 TLSv1' -- "$cur")) + _comp_compgen -- -W 'auto SSLv2 SSLv3 TLSv1' return ;; --certificate-type | --private-key-type) - COMPREPLY=($(compgen -W 'PEM DER' -- "$cur")) + _comp_compgen -- -W 'PEM DER' return ;; --follow-tags | --ignore-tags) local lastopt=${cur/*,/} prevopt= [[ $cur == *,* ]] && prevopt=${cur%,*}, - COMPREPLY=($(compgen -P "$prevopt" -W 'a abbr acronym address - applet area b base basefont bdo big blockquote body br button - caption center cite code col colgroup dd del dir div dfn dl dt - em fieldset font form frame frameset h6 head hr html i iframe - img input ins isindex kbd label legend li link map menu meta - noframes noscript object ol optgroup option p param pre q s - samp script select small span strike strong style sub sup table - tbody td textarea tfoot th thead title tr tt u ul var xmp' \ - -- "$lastopt")) - return - ;; - --tries | --timeout | --dns-timeout | --connect-timeout | --read-timeout | \ - --wait | --waitretry | --cut-dirs | --max-redirect | --level | -!(-*)[tTwl]) + _comp_compgen -c "$lastopt" -- -P "$prevopt" -W 'a abbr acronym + address applet area b base basefont bdo big blockquote body br + button caption center cite code col colgroup dd del dir div dfn + dl dt em fieldset font form frame frameset h6 head hr html i + iframe img input ins isindex kbd label legend li link map menu + meta noframes noscript object ol optgroup option p param pre q + s samp script select small span strike strong style sub sup + table tbody td textarea tfoot th thead title tr tt u ul var + xmp' + return + ;; + --tries | --timeout | --dns-timeout | --connect-timeout | \ + --read-timeout | --wait | --waitretry | --cut-dirs | \ + --max-redirect | --level | -${noargopts}[tTwl]) # expect integer number - COMPREPLY+=($(compgen -P "$cur" -W "{0..9}")) + _comp_compgen -aR -- -P "$cur" -W "{0..9}" compopt -o nospace return ;; - --quota | --limit-rate | --warc-max-size | -!(-*)Q) + --quota | --limit-rate | --warc-max-size | -${noargopts}Q) # expect size if [[ $cur == *[km] ]]; then - COMPREPLY=($(compgen -W "$cur")) + _comp_compgen -R -- -W "$cur" elif [[ $cur ]]; then - COMPREPLY=($(compgen -P "$cur" -W "{0..9} k m")) + _comp_compgen -R -- -P "$cur" -W "{0..9} k m" compopt -o nospace else - COMPREPLY=($(compgen -W "{0..9}")) + _comp_compgen -R -- -W "{0..9}" compopt -o nospace fi return ;; --user | --http-user | --proxy-user | --ftp-user) - COMPREPLY=($(compgen -W "$(command sed -n \ + _comp_compgen_split -- "$(command sed -n \ '/^login/s/^[[:blank:]]*login[[:blank:]]//p' ~/.netrc \ - 2>/dev/null)" -- "$cur")) + 2>/dev/null)" return ;; --header) - COMPREPLY=($(compgen -W 'Accept Accept-Charset Accept-Encoding + _comp_compgen -- -W 'Accept Accept-Charset Accept-Encoding Accept-Language Accept-Ranges Age Allow Authorization Cache-Control Connection Content-Encoding Content-Language Content-Length Content-Location Content-MD5 Content-Range @@ -133,42 +138,43 @@ _wget() Last-Modified Location Max-Forwards Pragma Proxy-Authenticate Proxy-Authorization Range Referer Retry-After Server TE Trailer Transfer-Encoding Upgrade User-Agent Vary Via Warning - WWW-Authenticate' -- "$cur")) + WWW-Authenticate' compopt -o nospace return ;; --local-encoding | --remote-encoding) - type -P xauth &>/dev/null && _xfunc iconv _iconv_charsets + type -P xauth &>/dev/null && _comp_compgen -x iconv charsets return ;; - --execute | -!(-*)e) + --execute | -${noargopts}e) return # TODO base=STR ;; --report-speed) - COMPREPLY=($(compgen -W 'bits' -- "$cur")) + _comp_compgen -- -W 'bits' return ;; --regex-type) - COMPREPLY=($(compgen -W 'posix' -- "$cur")) + _comp_compgen -- -W 'posix' return ;; - --base | --password | --ftp-password | --http-password | --proxy-password | \ - --default-page | --referer | --user-agent | --post-data | --warc-header | \ - --accept | --reject | --accept-regex | --reject-regex | --include-directories | \ - --exclude-directories | -!(-*)[BUARIX]) + --base | --password | --ftp-password | --http-password | \ + --proxy-password | --default-page | --referer | --user-agent | \ + --post-data | --warc-header | --accept | --reject | \ + --accept-regex | --reject-regex | --include-directories | \ + --exclude-directories | -${noargopts}[BUARIX]) # argument required but no completions available return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _wget wget + complete -F _comp_cmd_wget wget # ex: filetype=sh diff --git a/completions/wine b/completions/wine index 429fede..239f44b 100644 --- a/completions/wine +++ b/completions/wine @@ -1,20 +1,26 @@ # bash completion for wine(1) -*- shell-script -*- -_wine() +_comp_cmd_wine() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + + case $prev in + --help | --version) + return + ;; + esac if ((cword == 1)); then if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--help --version' -- "$cur")) + _comp_compgen -- -W '--help --version' [[ ${COMPREPLY-} ]] && return fi - _filedir '@([eE][xX][eE]?(.[sS][oO])|[cC][oO][mM]|[sS][cC][rR]|[mM][sS][iI])' + _comp_compgen_filedir '@([eE][xX][eE]?(.[sS][oO])|[cC][oO][mM]|[sS][cC][rR]|[mM][sS][iI])' else - _filedir + _comp_compgen_filedir fi } && - complete -F _wine wine wine-development wine-stable + complete -F _comp_cmd_wine wine{,64}{,-development,-stable} # ex: filetype=sh diff --git a/completions/withlist b/completions/withlist index 4142471..f687511 100644 --- a/completions/withlist +++ b/completions/withlist @@ -1,18 +1,20 @@ # mailman withlist completion -*- shell-script -*- -_withlist() +_comp_cmd_withlist() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--lock --interactive --run --all --quiet - --help' -- "$cur")) + _comp_compgen -- -W '--lock --interactive --run --all --quiet --help' else - _xfunc list_lists _mailman_lists + # Prefer `list_lists` in the same dir as command + local pathcmd + pathcmd=$(type -P "$1") && local PATH=${pathcmd%/*}:$PATH + _comp_compgen -x list_lists mailman_lists fi } && - complete -F _withlist withlist + complete -F _comp_cmd_withlist withlist # ex: filetype=sh diff --git a/completions/wodim b/completions/wodim index b308291..095fa0d 100644 --- a/completions/wodim +++ b/completions/wodim @@ -1,9 +1,9 @@ # bash completion for cdrecord/wodim -*- shell-script -*- -_cdrecord() +_comp_cmd_wodim() { - local cur prev words cword - _init_completion -n = || return + local cur prev words cword comp_args + _comp_initialize -n = -- "$@" || return local generic_options track_options track_mode @@ -13,11 +13,11 @@ _cdrecord() cur=${cur#*=} case $prev in textfile | cuefile | msifile) - _filedir + _comp_compgen_filedir ;; blank) - COMPREPLY=($(compgen -W 'help all fast track unreserve trtail - unclose session' -- "$cur")) + _comp_compgen -- -W 'help all fast track unreserve trtail + unclose session' ;; driveropts) if [[ $cur == *=* ]]; then @@ -25,30 +25,29 @@ _cdrecord() cur=${cur#*=} case $prev in varirec) - COMPREPLY=($(compgen -W "-2 -1 0 1 2" -- "$cur")) + _comp_compgen -- -W "-2 -1 0 1 2" ;; gigarec) - COMPREPLY=($(compgen -W "0.6 0.7 0.8 1.0 1.2 1.3 - 1.4" -- "$cur")) + _comp_compgen -- -W "0.6 0.7 0.8 1.0 1.2 1.3 1.4" ;; tattoofile) - _filedir + _comp_compgen_filedir ;; esac else - COMPREPLY=($(compgen -W 'burnfree noburnfree varirec= - gigarec= audiomaster forcespeed noforcespeed speedread + _comp_compgen -- -W 'burnfree noburnfree varirec= gigarec= + audiomaster forcespeed noforcespeed speedread nospeedread singlesession nosinglesession hidecdr - nohidecdr tattooinfo tattoofile=' -- "$cur")) + nohidecdr tattooinfo tattoofile=' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi ;; driver) - COMPREPLY=($(compgen -W "$($1 driver=help 2>&1 | - awk 'NR > 1 { print $1 }') help" -- "$cur")) + _comp_compgen_split -- "$("$1" driver=help 2>&1 | + _comp_awk 'NR > 1 { print $1 }') help" ;; minbuf) - COMPREPLY=($(compgen -W '{25..95}' -- "$cur")) + _comp_compgen -- -W '{25..95}' ;; esac return @@ -66,15 +65,15 @@ _cdrecord() -isosize -pad -nopad -shorttrack -noshorttrack -preemp -nopreemp -copy -nocopy -scms "isrc=" "index=" "padsize=" "pregap=" "tsize=") # look if previous was either a file or a track option - track_mode=0 + track_mode="" if ((cword > 1)); then if [[ -f $prev ]]; then - track_mode=1 + track_mode=set else local opt for opt in "${track_options[@]}"; do if [[ $opt == "$prev" ]]; then - track_mode=1 + track_mode=set break fi done @@ -82,15 +81,15 @@ _cdrecord() fi # files are always eligible completion - _filedir + _comp_compgen_filedir # track options are always available - COMPREPLY+=($(compgen -W '${track_options[@]}' -- "$cur")) + _comp_compgen -a -- -W '"${track_options[@]}"' # general options are no more available after file or track option - if ((track_mode == 0)); then - COMPREPLY+=($(compgen -W '${generic_options[@]}' -- "$cur")) + if [[ ! $track_mode ]]; then + _comp_compgen -a -- -W '"${generic_options[@]}"' fi [[ ${COMPREPLY-} == *= ]] && compopt -o nospace } && - complete -F _cdrecord cdrecord wodim + complete -F _comp_cmd_wodim wodim cdrecord # ex: filetype=sh diff --git a/completions/wol b/completions/wol index eada070..7e409a1 100644 --- a/completions/wol +++ b/completions/wol @@ -1,42 +1,45 @@ # wol(1) completion -*- shell-script -*- -_wol() +_comp_cmd_wol() { - local cur prev words cword split - _init_completion -s -n : || return + local cur prev words cword was_split comp_args + _comp_initialize -s -n : -- "$@" || return + local noargopts='!(-*|*[pwhif]*)' + # shellcheck disable=SC2254 case $prev in - --version | --help | --port | --passwd | --wait | -!(-*)[Vpw]) + --version | --help | --port | --passwd | --wait | -${noargopts}[Vpw]) return ;; - --host | --ipaddr | -!(-*)[hi]) + --host | --ipaddr | -${noargopts}[hi]) # Broadcast addresses local PATH=$PATH:/sbin - COMPREPLY=($({ - ip addr show || ifconfig -a + _comp_compgen_split -- "$({ + ip -c=never addr show || ip addr show || ifconfig -a } 2>/dev/null | - command sed -ne 's/.*[[:space:]]Bcast:\([^[:space:]]*\).*/\1/p' -ne \ - 's/.*inet.*[[:space:]]brd[[:space:]]\([^[:space:]]*\).*/\1/p' -ne \ - 's/.*[[:space:]]broadcast[[:space:]]\{1,\}\([^[:space:]]*\).*/\1/p')) - _known_hosts_real -- "$cur" + command sed \ + -ne 's/.*[[:space:]]Bcast:\([^[:space:]]*\).*/\1/p' \ + -ne 's/.*inet.*[[:space:]]brd[[:space:]]\([^[:space:]]*\).*/\1/p' \ + -ne 's/.*[[:space:]]broadcast[[:space:]]\{1,\}\([^[:space:]]*\).*/\1/p')" + _comp_compgen -a known_hosts -- "$cur" return ;; - --file | -!(-*)f) - _filedir + --file | -${noargopts}f) + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _mac_addresses + _comp_compgen_mac_addresses } && - complete -F _wol wol + complete -F _comp_cmd_wol wol # ex: filetype=sh diff --git a/completions/wsimport b/completions/wsimport index d5bec9f..cee8c09 100644 --- a/completions/wsimport +++ b/completions/wsimport @@ -1,48 +1,48 @@ # wsimport(1) completion -*- shell-script -*- -_wsimport() +_comp_cmd_wsimport() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return case $prev in -help | -version | -B | -p | -wsdllocation) return ;; -b) - _filedir '@(xml|xjb)' + _comp_compgen_filedir '@(xml|xjb)' return ;; -catalog) - _filedir '@(xml|soc|catalog)' + _comp_compgen_filedir '@(xml|soc|catalog)' return ;; -d | –s) - _filedir -d + _comp_compgen_filedir -d return ;; -target) - COMPREPLY=($(compgen -W '2.0 2.1 2.2' -- "$cur")) + _comp_compgen -- -W '2.0 2.1 2.2' return ;; -clientjar) - _filedir jar + _comp_compgen_filedir jar return ;; esac if [[ $cur == -httpproxy:* ]]; then - _known_hosts_real -- "${cur#-httpproxy:}" + _comp_compgen_known_hosts -- "${cur#-httpproxy:}" return elif [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help [[ ${COMPREPLY-} == *: ]] && compopt -o nospace - __ltrim_colon_completions "$cur" + _comp_ltrim_colon_completions "$cur" return fi - _filedir wsdl + _comp_compgen_filedir wsdl } && - complete -F _wsimport wsimport + complete -F _comp_cmd_wsimport wsimport # ex: filetype=sh diff --git a/completions/wtf b/completions/wtf index 27fc10a..c565c56 100644 --- a/completions/wtf +++ b/completions/wtf @@ -1,42 +1,45 @@ # wtf completion -*- shell-script -*- # Raphael Droz, 25/09/2009 -_wtf() +_comp_cmd_wtf() { - local cur prev words cword addf - _init_completion || return + local cur prev words cword comp_args addf + _comp_initialize -- "$@" || return - [[ $prev == -f ]] && _filedir && return + [[ $prev == -f ]] && _comp_compgen_filedir && return [[ ${words[*]} == *\ -f* ]] && addf= || addf=-f if [[ $cur == -* ]]; then - COMPREPLY=($addf) + COMPREPLY=(${addf:+"$addf"}) return fi - local db + local db="" has_db="" set -- "${words[@]}" while (($# > 0)); do if [[ $1 == -f ]]; then shift - db=$1 + if (($# > 0)); then + db=$1 + has_db=set + fi break fi shift done - if [[ ! -v db ]]; then + if [[ ! $has_db ]]; then local f for f in "${ACRONYMDB-}" /usr/share/misc/acronyms \ /usr/share/games/bsdgames/acronyms; do - [[ -f $f ]] && db="$f" && break + [[ -f $f ]] && db="$f" has_db=set && break done - [[ -v db ]] || return + [[ $has_db ]] || return fi - COMPREPLY=($(compgen -W "$(cut -f 1 -s $db* 2>/dev/null) $addf" \ - -- "${cur^^}")) + _comp_compgen -c "${cur^^}" split \ + -- "$(cut -f 1 -s "$db"* 2>/dev/null) $addf" } && - complete -F _wtf wtf + complete -F _comp_cmd_wtf wtf # ex: filetype=sh diff --git a/completions/wvdial b/completions/wvdial index 8667400..bdadeac 100644 --- a/completions/wvdial +++ b/completions/wvdial @@ -1,24 +1,24 @@ # bash completion for wvdial -*- shell-script -*- -_wvdial() +_comp_cmd_wvdial() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in --config) - _filedir + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return local config i IFS=$'\n' case $cur in -*) - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace ;; *) @@ -33,14 +33,14 @@ _wvdial() done # parse config files for sections and # remove default section - COMPREPLY=($(command sed -ne "s|^\[Dialer \($cur.*\)\]$|\1|p" $config \ - 2>/dev/null | command grep -v '^Defaults$')) + _comp_compgen_split -l -X 'Defaults' -- "$(command sed -ne \ + 's/^\[Dialer \(.*\)\]$/\1/p' "$config" 2>/dev/null)" # escape spaces - COMPREPLY=(${COMPREPLY[@]// /\\ }) + COMPREPLY=("${COMPREPLY[@]// /\\ }") ;; esac } && - complete -F _wvdial wvdial + complete -F _comp_cmd_wvdial wvdial # ex: filetype=sh diff --git a/completions/xdg-mime b/completions/xdg-mime index 74c26c4..db97034 100644 --- a/completions/xdg-mime +++ b/completions/xdg-mime @@ -1,74 +1,85 @@ # xdg-mime(1) completion -*- shell-script -*- -_xdg_mime_mimetype() +_comp_cmd_xdg_mime__mimetype() { - COMPREPLY+=($(compgen -S / -W 'application audio font image message model - multipart text video' -- "$cur")) - [[ ${COMPREPLY-} == */ ]] && compopt -o nospace + local d i + local -a arr + for d in /usr/share/mime /usr/local/share/mime; do + _comp_compgen -v arr -C "$d" -- -f -o plusdirs -X "!*.xml" || continue + for i in "${!arr[@]}"; do + case ${arr[i]} in + packages*) unset -v "arr[i]" ;; # not a MIME type dir + *.xml) arr[i]=${arr[i]%.xml} ;; + */*) ;; + *) arr[i]+=/ ;; + esac + done + ((${#arr[@]})) && + COMPREPLY+=("${arr[@]}") + done + [[ ${COMPREPLY-} != */ ]] || compopt -o nospace } -_xdg_mime() +_comp_cmd_xdg_mime() { - local cur prev words cword - _init_completion || return - - local args - _count_args + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + local REPLY + _comp_count_args + local args=$REPLY if ((args == 1)); then if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--help --manual --version' -- "$cur")) + _comp_compgen -- -W '--help --manual --version' return fi - COMPREPLY=($(compgen -W \ - 'query default install uninstall' -- "$cur")) + _comp_compgen -- -W 'query default install uninstall' return fi case ${words[1]} in query) if ((args == 2)); then - COMPREPLY=($(compgen -W 'filetype default' -- "$cur")) + _comp_compgen -- -W 'filetype default' return fi - case ${words[2]} in # TODO and args == 3 (takes only one arg!) - filetype) _filedir ;; - default) _xdg_mime_mimetype ;; + ((args == 3)) || return + case ${words[2]} in + filetype) _comp_compgen_filedir ;; + default) _comp_cmd_xdg_mime__mimetype ;; esac ;; default) if ((args == 2)); then - local IFS=$' \t\n' reset=$(shopt -p nullglob) - shopt -s nullglob - local -a desktops=(/usr/share/applications/*.desktop) - desktops=("${desktops[@]##*/}") - $reset - IFS=$'\n' - COMPREPLY=($(compgen -W '${desktops[@]}' -- "$cur")) + local -a desktops + if _comp_expand_glob desktops '/usr/share/applications/*.desktop'; then + desktops=("${desktops[@]##*/}") + _comp_compgen -- -W '"${desktops[@]}"' + fi else - _xdg_mime_mimetype + _comp_cmd_xdg_mime__mimetype fi ;; install) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--mode --novendor' -- "$cur")) + _comp_compgen -- -W '--mode --novendor' elif [[ $prev == --mode ]]; then - COMPREPLY=($(compgen -W 'user system' -- "$cur")) + _comp_compgen -- -W 'user system' else - _filedir xml + _comp_compgen_filedir xml fi ;; uninstall) if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '--mode' -- "$cur")) + _comp_compgen -- -W '--mode' elif [[ $prev == --mode ]]; then - COMPREPLY=($(compgen -W 'user system' -- "$cur")) + _comp_compgen -- -W 'user system' else - _filedir xml + _comp_compgen_filedir xml fi ;; esac } && - complete -F _xdg_mime xdg-mime + complete -F _comp_cmd_xdg_mime xdg-mime # ex: filetype=sh diff --git a/completions/xdg-settings b/completions/xdg-settings index abd9246..df03222 100644 --- a/completions/xdg-settings +++ b/completions/xdg-settings @@ -1,9 +1,9 @@ # xdg-settings completion -*- shell-script -*- -_xdg_settings() +_comp_cmd_xdg_settings() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --help | --list | --manual | --version) @@ -12,20 +12,18 @@ _xdg_settings() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$("$1" --help | - tr "{|" "\n" | _parse_help -)' -- "$cur")) + _comp_compgen_help - <<<"$("$1" --help | tr '{|' '\n')" return fi - local args - _count_args - if ((args == 1)); then - COMPREPLY=($(compgen -W "get check set" -- "$cur")) - elif ((args == 2)); then - COMPREPLY=($(compgen -W \ - '$("$1" --list | awk "!/^Known/ { print \$1 }")' -- "$cur")) + local REPLY + _comp_count_args + if ((REPLY == 1)); then + _comp_compgen -- -W "get check set" + elif ((REPLY == 2)); then + _comp_compgen_split -- "$("$1" --list | _comp_awk '!/^Known/ { print $1 }')" fi } && - complete -F _xdg_settings xdg-settings + complete -F _comp_cmd_xdg_settings xdg-settings # ex: filetype=sh diff --git a/completions/xev b/completions/xev new file mode 100644 index 0000000..78df177 --- /dev/null +++ b/completions/xev @@ -0,0 +1,31 @@ +# xev(1) completion -*- shell-script -*- + +_comp_cmd_xev() +{ + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + + case $prev in + -display | -geometry | -bw | -id | -name) + return + ;; + -bs) + _comp_compgen -- -W 'NotUseful WhenMapped Always' + return + ;; + -event) + _comp_compgen -- -W 'keyboard mouse expose visibility structure + substructure focus property colormap owner_grab_button randr + button' + return + ;; + esac + + if [[ $cur == -* ]]; then + _comp_compgen_help + return + fi +} && + complete -F _comp_cmd_xev xev + +# ex: filetype=sh diff --git a/completions/xfreerdp b/completions/xfreerdp index f17414f..66b42ad 100644 --- a/completions/xfreerdp +++ b/completions/xfreerdp @@ -1,67 +1,78 @@ # xfreerdp completion -*- shell-script -*- -_xfreerdp() +_comp_cmd_xfreerdp() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return - case $prev in # old/dash syntax + case $prev in -k) - COMPREPLY=($(compgen -W '$("$1" --kbd-list | - awk "/^0x/ { print \$1 }")' -- "$cur")) + _comp_compgen_split -- "$("$1" --kbd-list | + _comp_awk '/^0x/ { print $1 }')" return ;; -a) - COMPREPLY=($(compgen -W '8 15 16 24 32' -- "$cur")) + _comp_compgen -- -W '8 15 16 24 32' return ;; -x) - COMPREPLY=($(compgen -W 'broadband modem lan' -- "$cur")) + _comp_compgen -- -W 'broadband modem lan' return ;; --plugin) - COMPREPLY=($(compgen -W 'cliprdr rdpsnd rdpdr' -- "$cur")) + _comp_compgen -- -W 'cliprdr rdpsnd rdpdr' + return + ;; + /help | /version | -h | --help | --version) return ;; esac - case $cur in # new/slash syntax + case $cur in /kbd:*) - COMPREPLY=($(compgen -W '$("$1" /kbd-list | - awk "/^0x/ { print \$1 }")' -- "${cur#/kbd:}")) + local kbd_list + kbd_list=$("$1" /kbd-list 2>/dev/null) || + kbd_list=$("$1" /list:kbd 2>/dev/null) + _comp_compgen -c "${cur#/kbd:}" split -- "$( + _comp_awk '/^0x/ { print $1 }' <<<"$kbd_list" + )" return ;; /bpp:*) - COMPREPLY=($(compgen -W '8 15 16 24 32' -- "${cur#/bpp:}")) + _comp_compgen -c "${cur#/bpp:}" -- -W '8 15 16 24 32' return ;; - /*:* | /help | /version | -h | --help | --version) + /*:*) return ;; esac if [[ $cur == /* ]]; then - COMPREPLY=($(compgen -W '$("$1" --help | - awk "\$1 ~ /^\\// && \$1 !~ /^.(flag\$|option:)/ { sub(\":.*\",\":\",\$1); print \$1 }")' \ - -- "$cur")) + _comp_compgen_filedir rdp + _comp_compgen -a split -- "$( + "$1" --help | _comp_awk '$1 ~ /^\// && $1 !~ /^.(flag$|option:)/ { + sub(":.*",":",$1); print $1 }' + )" [[ ${COMPREPLY-} == *: ]] && compopt -o nospace elif [[ $cur == [+-]* ]]; then local char=${cur:0:1} - local help="$($1 --help)" + local help="$("$1" --help)" if [[ $help == */help* ]]; then # new/slash syntax - COMPREPLY=($(compgen -W '$(awk " - \$1 ~ /^[+-]/ && \$1 !~ /^.toggle\$/ { sub(\"^.\",\"$char\",\$1); print \$1 } - " <<<"$help")' -- "$cur")) + _comp_compgen_split -- "$(_comp_awk '$1 ~ /^[+-]/ && $1 !~ /^.toggle$/ { + sub("^.","'"$char"'",$1); print $1 }' <<<"$help")" else # old/dash syntax - COMPREPLY=($(_parse_help - <<<"$help")) - COMPREPLY=($(compgen -W '${COMPREPLY[@]%:}' -- "$cur")) + _comp_compgen -R help - <<<"$help" + ((${#COMPREPLY[@]})) && + _comp_compgen -- -W '"${COMPREPLY[@]%:}"' fi else - COMPREPLY=($(compgen -W "$(awk '{print $1}' ~/.freerdp/known_hosts \ - 2>/dev/null)" -- "$cur")) + _comp_compgen_filedir rdp + _comp_compgen -a split -- "$( + _comp_awk '{print $1}' ~/.freerdp/known_hosts 2>/dev/null + )" fi } && - complete -F _xfreerdp xfreerdp + complete -F _comp_cmd_xfreerdp xfreerdp # ex: filetype=sh diff --git a/completions/xgamma b/completions/xgamma index 8d77ba3..2a0c409 100644 --- a/completions/xgamma +++ b/completions/xgamma @@ -1,15 +1,15 @@ # bash completion for xgamma(1) -*- shell-script -*- -_xgamma() +_comp_cmd_xgamma() { - local cur prev words cword - _init_completion -n : || return + local cur prev words cword comp_args + _comp_initialize -n : -- "$@" || return case "$prev" in -screen) local screens=$(xrandr --query 2>/dev/null | command sed -n \ '/^Screen /s|^Screen \{1,\}\(.*\):.*$|\1|p' 2>/dev/null) - COMPREPLY=($(compgen -W "$screens" -- "$cur")) + _comp_compgen -- -W "$screens" return ;; -gamma | -rgamma | -ggamma | -bgamma) @@ -17,7 +17,7 @@ _xgamma() if [[ $cur && $cur != *.* ]]; then COMPREPLY=(.) fi - COMPREPLY+=($(compgen -W "{0..9}")) + _comp_compgen -aR -- -W "{0..9}" compopt -o nospace return ;; @@ -26,18 +26,17 @@ _xgamma() if [[ $cur == :* && $cur != :*.* ]]; then # FIXME: where to get local display numbers? local display=${cur#:} - COMPREPLY=($(compgen -W "${display:-0}.")) + _comp_compgen -R -- -W "${display:-0}." compopt -o nospace elif [[ $cur == :*.* ]]; then # local screen numbers local t screens=$(xrandr --query 2>/dev/null | command sed -ne \ '/^Screen /s|^Screen \{1,\}\(.*\):.*$|\1|p' 2>/dev/null) t="${cur#:}" - COMPREPLY=($(compgen -P "${t%.*}." -W "$screens" -- \ - "${cur##*.}")) + _comp_compgen -c "${cur##*.}" -- -P "${t%.*}." -W '$screens' elif [[ $cur != *:* ]]; then # complete hostnames - _known_hosts_real -c -- "$cur" + _comp_compgen_known_hosts -c -- "$cur" if [[ ! $cur ]]; then COMPREPLY+=(:) fi @@ -49,13 +48,13 @@ _xgamma() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help if [[ ${COMPREPLY-} ]]; then [[ $COMPREPLY == *= ]] && compopt -o nospace return fi fi } && - complete -F _xgamma xgamma + complete -F _comp_cmd_xgamma xgamma # ex: filetype=sh diff --git a/completions/xhost b/completions/xhost index 648ae4f..9491030 100644 --- a/completions/xhost +++ b/completions/xhost @@ -1,16 +1,16 @@ # xhost(1) completion -*- shell-script -*- -_xhost() +_comp_cmd_xhost() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $cur in - +*) _known_hosts_real -p+ -- "${cur:1}" ;; - -*) _known_hosts_real -p- -- "${cur:1}" ;; - *) _known_hosts_real -- "$cur" ;; + +*) _comp_compgen_known_hosts -p+ -- "${cur:1}" ;; + -*) _comp_compgen_known_hosts -p- -- "${cur:1}" ;; + *) _comp_compgen_known_hosts -- "$cur" ;; esac } && - complete -F _xhost xhost + complete -F _comp_cmd_xhost xhost # ex: filetype=sh diff --git a/completions/xmllint b/completions/xmllint index a6ef38f..57445bb 100644 --- a/completions/xmllint +++ b/completions/xmllint @@ -1,13 +1,13 @@ # bash completion for xmllint(1) -*- shell-script -*- -_xmllint() +_comp_cmd_xmllint() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -o | --output) - _filedir + _comp_compgen_filedir return ;; --path | --dtdvalidfpi | --maxmem | --pattern | --xpath) @@ -15,39 +15,39 @@ _xmllint() return ;; --dtdvalid) - _filedir 'dtd?(.gz)' + _comp_compgen_filedir 'dtd?(.gz)' return ;; --relaxng) - _filedir 'rng?(.gz)' + _comp_compgen_filedir 'rng?(.gz)' return ;; --schema) - _filedir 'xsd?(.gz)' + _comp_compgen_filedir 'xsd?(.gz)' return ;; --schematron) - _filedir 'sch?(.gz)' + _comp_compgen_filedir 'sch?(.gz)' return ;; --encode) - _xfunc iconv _iconv_charsets + _comp_compgen -x iconv charsets return ;; --pretty) - COMPREPLY=($(compgen -W '{0..2}' -- "$cur")) + _comp_compgen -- -W '{0..2}' return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help COMPREPLY=("${COMPREPLY[@]%:}") return fi - _filedir '@(*ml|htm|svg?(z)|xs[dl]|rng|wsdl|jnlp|tld|dbk|docbook|page)?(.gz)' + _comp_compgen_filedir '@(*ml|htm|svg?(z)|xs[dl]|rng|wsdl|jnlp|tld|dbk|docbook|page)?(.gz)' } && - complete -F _xmllint xmllint + complete -F _comp_cmd_xmllint xmllint # ex: filetype=sh diff --git a/completions/xmlwf b/completions/xmlwf index b397af9..d047ee1 100644 --- a/completions/xmlwf +++ b/completions/xmlwf @@ -1,32 +1,31 @@ # bash completion for xmlwf(1) -*- shell-script -*- -_xmlwf() +_comp_cmd_xmlwf() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -*d) - _filedir -d + _comp_compgen_filedir -d return ;; -*e) - COMPREPLY=($(compgen -W 'US-ASCII UTF-8 UTF-16 ISO-8859-1' \ - -- "$cur")) + _comp_compgen -- -W 'US-ASCII UTF-8 UTF-16 ISO-8859-1' return ;; - -*v) + -*[abv]) return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_usage "$1")' -- "$cur")) + _comp_compgen_help || _comp_compgen_usage return fi - _filedir '@(*ml|htm|svg|xs[dl]|rng|wsdl|jnlp|tld|dbk|docbook|page)' + _comp_compgen_filedir '@(*ml|htm|svg|xs[dl]|rng|wsdl|jnlp|tld|dbk|docbook|page)' } && - complete -F _xmlwf xmlwf + complete -F _comp_cmd_xmlwf xmlwf # ex: filetype=sh diff --git a/completions/xmms b/completions/xmms index af4aefe..49bc381 100644 --- a/completions/xmms +++ b/completions/xmms @@ -1,29 +1,31 @@ # bash completion for xmms -*- shell-script -*- -_xmms() +_comp_cmd_xmms() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[SRA]*)' + # shellcheck disable=SC2254 case $prev in - --help | --version | -!(-*)[hv]) + --help | --version | -${noargopts}[hv]) return ;; - --toggle-shuffle | --toggle-repeat | --toggle-advance | -!(-*)[SRA]) - COMPREPLY=($(compgen -W 'on off' -- "$cur")) + --toggle-shuffle | --toggle-repeat | --toggle-advance | -${noargopts}[SRA]) + _comp_compgen -- -W 'on off' return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help else - _filedir '@(mp[23]|ogg|wav|pls|m3u|xm|mod|s[3t]m|it|mtm|ult|flac)' + _comp_compgen_filedir '@(mp[23]|ogg|wav|pls|m3u|xm|mod|s[3t]m|it|mtm|ult|flac)' fi } && - complete -F _xmms xmms + complete -F _comp_cmd_xmms xmms # ex: filetype=sh diff --git a/completions/xmodmap b/completions/xmodmap index 7cfa230..f8d2957 100644 --- a/completions/xmodmap +++ b/completions/xmodmap @@ -1,9 +1,9 @@ # xmodmap(1) completion -*- shell-script -*- -_xmodmap() +_comp_cmd_xmodmap() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -display | -e) @@ -12,12 +12,12 @@ _xmodmap() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -help)' -- "$cur")) + _comp_compgen_help -- -help return fi - _filedir + _comp_compgen_filedir } && - complete -F _xmodmap xmodmap + complete -F _comp_cmd_xmodmap xmodmap # ex: filetype=sh diff --git a/completions/xrandr b/completions/xrandr index 16704e3..c071ab4 100644 --- a/completions/xrandr +++ b/completions/xrandr @@ -1,63 +1,178 @@ # bash completion for xrandr -*- shell-script -*- -_xrandr() +_comp_cmd_xrandr__compgen_outputs() { - local cur prev words cword - _init_completion || return + _comp_compgen_split -- "$("$1" -q 2>/dev/null | _comp_awk '/connected/ {print $1}')" +} + +_comp_cmd_xrandr__compgen_monitors() +{ + _comp_compgen_split -- "$( + "$1" --listmonitors 2>/dev/null | + command sed -ne 's/.* [0-9]*: [+\*]*\([^ ]*\).*/\1/p' + )" +} + +_comp_cmd_xrandr__compgen_providers() +{ + _comp_compgen_split -- "$("$1" --listproviders 2>/dev/null | + command sed -ne "s/.*cap:.*$2.* name:\([^ ]*\).*/\1/p")" +} + +_comp_cmd_xrandr__compgen_modes() +{ + _comp_compgen_split -- "$( + "$1" -q 2>/dev/null | command sed \ + -e "1,/^$2 / d" \ + -e '/connected/,$ d' \ + -e '/^[[:space:]]*h: / d' \ + -e '/^[[:space:]]*v: / d' \ + -e 's/\([^[:space:]]\)[[:space:]].*/\1/' + )" +} + +_comp_cmd_xrandr__compgen_all_modes() +{ + _comp_compgen_split -- "$( + "$1" -q 2>/dev/null | command sed \ + -e '/^[^[:space:]].*/ d' \ + -e '/^[[:space:]]*h: / d' \ + -e '/^[[:space:]]*v: / d' \ + -e 's/[[:space:]]*\([^[:space:]]*\)[[:space:]].*/\1/' + )" +} + +_comp_cmd_xrandr() +{ + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + + local i output has_output="" + for ((i = cword - 1; i > 0; i--)); do + if [[ ${words[i]} == --output ]]; then + output=${words[i + 1]} + has_output=set + break + fi + done case "$prev" in - -display | -d | -help | -s | --size | -r | --rate | --refresh | --screen | --fb | --fbmm | \ - --dpi | --pos | --set | --scale | --transform | --crtc | --panning | --gamma | \ - --newmode | --rmmode | --addmode | --delmode) + -display | -d | -s | --size | -r | --rate | --refresh | --screen | \ + --fb | --fbmm | --pos | --set | --scale | --transform | --crtc | \ + --panning | --gamma | --newmode | --rmmode | --setmonitor) + return + ;; + --output | --addmode | --delmode | --dpi) + _comp_cmd_xrandr__compgen_outputs "$1" return ;; - --output | --left-of | --right-of | --above | --below | --same-as) - local outputs=$("$1" | awk '/connected/ {print $1}') - COMPREPLY=($(compgen -W "$outputs" -- "$cur")) + --left-of | --right-of | --above | --below | --same-as) + if [[ $has_output ]]; then + _comp_cmd_xrandr__compgen_outputs "$1" + fi return ;; --mode) - local i output - for ((i = 1; i < cword; i++)); do - if [[ ${words[i]} == --output ]]; then - output=${words[i + 1]} - break - fi - done - if [[ -v output ]]; then - local modes=$("$1" | command sed -e "1,/^$output / d" \ - -e "/connected/,$ d" \ - -e "s/\([^[:space:]]\)[[:space:]].*/\1/") - COMPREPLY=($(compgen -W "$modes" -- "$cur")) + if [[ $has_output ]]; then + _comp_cmd_xrandr__compgen_modes "$1" "$output" fi return ;; -o | --orientation) - COMPREPLY=($(compgen -W 'normal inverted left right 0 1 2 3' -- \ - "$cur")) + _comp_compgen -- -W 'normal inverted left right 0 1 2 3' return ;; --reflect) - COMPREPLY=($(compgen -W 'normal x y xy' -- "$cur")) + if [[ $has_output ]]; then + _comp_compgen -- -W 'normal x y xy' + fi return ;; --rotate) - COMPREPLY=($(compgen -W 'normal inverted left right' -- "$cur")) + if [[ $has_output ]]; then + _comp_compgen -- -W 'normal inverted left right' + fi return ;; - --setprovideroutputsource | --setprovideroffloadsink) - local providers=$("$1" --listproviders 2>/dev/null | - command sed -ne 's/.* name:\([^ ]*\).*/\1/p') - COMPREPLY=($(compgen -W "$providers" -- "$cur")) - # TODO 2nd arg needed, is that a provider as well? + --filter) + if [[ $has_output ]]; then + _comp_compgen -- -W 'bilinear nearest' + fi + return + ;; + --setprovideroutputsource) + _comp_cmd_xrandr__compgen_providers "$1" "Sink Output" + return + ;; + --setprovideroffloadsink) + _comp_cmd_xrandr__compgen_providers "$1" "Source Offload" + return + ;; + --delmonitor) + _comp_cmd_xrandr__compgen_monitors "$1" return ;; esac - COMPREPLY=($(compgen -W '$("$1" -help 2>&1 | - command sed -e "s/ or / /g" -e "s/<[^>]*>]//g" | _parse_help -)' \ - -- "$cur")) + # second arguments + if ((cword >= 2)); then + case "${words[cword - 2]}" in + --set) + return + ;; + --addmode) + _comp_cmd_xrandr__compgen_all_modes "$1" + return + ;; + --delmode) + _comp_cmd_xrandr__compgen_modes "$1" "${words[cword - 1]}" + return + ;; + --setmonitor) + _comp_compgen -- -W 'auto' + return + ;; + --setprovideroutputsource) + _comp_cmd_xrandr__compgen_providers "$1" "Source Output" + _comp_compgen -a -- -W "0x0" + return + ;; + --setprovideroffloadsink) + _comp_cmd_xrandr__compgen_providers "$1" "Sink Offload" + _comp_compgen -a -- -W "0x0" + return + ;; + esac + fi + + # third arguments + if ((cword >= 3)); then + case "${words[cword - 3]}" in + --setmonitor) + _comp_compgen -c "${cur##*,}" -i xrandr outputs "$1" + _comp_compgen -ac "${cur##*,}" -- -W "none" + _comp_delimited , -W '"${COMPREPLY[@]}"' + return + ;; + esac + fi + + local options + if [[ $has_output ]]; then + _comp_compgen -v options help - <<<"$( + "$1" --help 2>/dev/null | + command sed -e 's/ or /\n /g' -e 's/<[^>]*>]//g' + )" + else + # if no output is specified, remove per-output options + _comp_compgen -v options help - <<<"$( + "$1" --help 2>/dev/null | + command sed -e '/^ -/!d' -e 's/ or /\n /g' -e 's/<[^>]*>]//g' + )" + fi + + _comp_compgen -- -W '"${options[@]}"' } && - complete -F _xrandr xrandr + complete -F _comp_cmd_xrandr xrandr # ex: filetype=sh diff --git a/completions/xrdb b/completions/xrdb index f46f90b..0bd2598 100644 --- a/completions/xrdb +++ b/completions/xrdb @@ -1,27 +1,27 @@ # xrdb(1) completion -*- shell-script -*- -_xrdb() +_comp_cmd_xrdb() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -backup | -display | -help) return ;; -cpp | -edit) - _filedir + _comp_compgen_filedir return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help return fi - _filedir + _comp_compgen_filedir } && - complete -F _xrdb xrdb + complete -F _comp_cmd_xrdb xrdb # ex: filetype=sh diff --git a/completions/xsltproc b/completions/xsltproc index 4cb7071..5d75596 100644 --- a/completions/xsltproc +++ b/completions/xsltproc @@ -1,13 +1,13 @@ # xsltproc(1) completion -*- shell-script -*- -_xsltproc() +_comp_cmd_xsltproc() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in --output | -o) - _filedir + _comp_compgen_filedir return ;; # TODO : number only @@ -16,8 +16,8 @@ _xsltproc() ;; --encoding) # some aliases removed - COMPREPLY=($(compgen -X '@(UTF[1378]|8859|ISO[0-9_])*' \ - -W "$(iconv -l | command sed -e 's/\/.*//')" -- "$cur")) + local encodings=$(iconv -l | command sed -e 's/\/.*//') + _comp_compgen -- -X '@(UTF[1378]|8859|ISO[0-9_])*' -W '$encodings' return ;; --param | --stringparam) @@ -25,25 +25,25 @@ _xsltproc() ;; # not really like --writesubtree --path) - _filedir -d + _comp_compgen_filedir -d return ;; --writesubtree) - _filedir -d + _comp_compgen_filedir -d return ;; esac - [[ $cword -gt 2 && $(_get_cword '' 2) == --?(string)param ]] && return + [[ $cword -gt 2 && ${words[cword - 2]} == --?(string)param ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help COMPREPLY=("${COMPREPLY[@]%:}") else # TODO: 1st file xsl|xslt, 2nd XML - _filedir '@(xsl|xslt|xml|dbk|docbook|page)' + _comp_compgen_filedir '@(xsl|xslt|xml|dbk|docbook|page)' fi } && - complete -F _xsltproc xsltproc + complete -F _comp_cmd_xsltproc xsltproc # ex: filetype=sh diff --git a/completions/xvfb-run b/completions/xvfb-run index ed2788a..9ae1fc8 100644 --- a/completions/xvfb-run +++ b/completions/xvfb-run @@ -1,36 +1,39 @@ # bash completion for xvfb-run -*- shell-script -*- -_xvfb_run() +_comp_cmd_xvfb_run() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*[npsef]*)' local i - for ((i = 1; i <= COMP_CWORD; i++)); do - if [[ ${COMP_WORDS[i]} != -* ]]; then - _command_offset $i + for ((i = 1; i <= cword; i++)); do + if [[ ${words[i]} != -* ]]; then + _comp_command_offset $i return fi - [[ ${COMP_WORDS[i]} == -!(-*)[npsef] ]] && ((i++)) + # shellcheck disable=SC2254 + [[ ${words[i]} == -${noargopts}[npsef] ]] && ((i++)) done + # shellcheck disable=SC2254 case $prev in - --help | --server-num | --xauth-protocol | --server-args | -!(-*)[hnps]) + --help | --server-num | --xauth-protocol | --server-args | -${noargopts}[hnps]) return ;; - --error-file | --auth-file | -!(-*)[ef]) - _filedir + --error-file | --auth-file | -${noargopts}[ef]) + _comp_compgen_filedir return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace fi } && - complete -F _xvfb_run xvfb-run + complete -F _comp_cmd_xvfb_run xvfb-run # ex: filetype=sh diff --git a/completions/xxd b/completions/xxd index a470bb0..b9facde 100644 --- a/completions/xxd +++ b/completions/xxd @@ -1,23 +1,24 @@ # xxd(1) completion -*- shell-script -*- -_xxd() +_comp_cmd_xxd() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in - -h | -help | -c | -cols | -g | -groupsize | -l | -len | -s | -seek | -v | -version) + -h | -help | -c | -cols | -g | -groupsize | -l | -len | -s | -seek | \ + -v | -version) return ;; esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" -h)' -- "$cur")) + _comp_compgen_help -- -h return fi - _filedir + _comp_compgen_filedir } && - complete -F _xxd xxd + complete -F _comp_cmd_xxd xxd # ex: filetype=sh diff --git a/completions/xz b/completions/xz index 73958c5..8d6c53b 100644 --- a/completions/xz +++ b/completions/xz @@ -1,56 +1,59 @@ # xz(1) completion -*- shell-script -*- -_xz() +_comp_cmd_xz() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return local xspec="*.@(xz|lzma|txz|tlz)" + local noargopts='!(-*|*[CFTMS]*)' + # shellcheck disable=SC2254 case $prev in - --decompress | --list | --test | -!(-*)[dlt]*) + --decompress | --list | --test | -${noargopts}[dlt]*) xspec="!"$xspec ;; --files | --files0) - _filedir + _comp_compgen_filedir return ;; - --check | -!(-*)C) - COMPREPLY=($(compgen -W 'crc32 crc64 sha256 none' -- "$cur")) + --check | -${noargopts}C) + _comp_compgen -- -W 'crc32 crc64 sha256 none' return ;; - --format | -!(-*)F) - COMPREPLY=($(compgen -W 'auto xz lzma raw' -- "$cur")) + --format | -${noargopts}F) + _comp_compgen -- -W 'auto xz lzma raw' return ;; - --threads | -!(-*)T) - COMPREPLY=($(compgen -W "{0..$(_ncpus)}" -- "$cur")) + --threads | -${noargopts}T) + local REPLY + _comp_get_ncpus + _comp_compgen -- -W "{0..$REPLY}" return ;; --memlimit | --memlimit-compress | --memlimit-decompress | --memory | \ - --suffix | --delta | --lzma1 | --lzma2 | -!(-*)[MS]) + --suffix | --delta | --lzma1 | --lzma2 | -${noargopts}[MS]) return ;; - --help | --long-help | --version | --info-memory | -!(-*)[hHV]) + --help | --long-help | --version | --info-memory | -${noargopts}[hHV]) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1" --long-help) {-1..-9}' \ - -- "$cur")) + _comp_compgen_help -- --long-help + _comp_compgen -a -- -W '{-1..-9}' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _tilde "$cur" || return + _comp_compgen_tilde && return - local IFS=$'\n' compopt -o filenames - COMPREPLY=($(compgen -f -X "$xspec" -- "$cur") $(compgen -d -- "$cur")) + _comp_compgen -- -f -X "$xspec" -o plusdirs } && - complete -F _xz xz pxz + complete -F _comp_cmd_xz xz pxz # ex: filetype=sh diff --git a/completions/xzdec b/completions/xzdec index 993bd2b..21ee6ec 100644 --- a/completions/xzdec +++ b/completions/xzdec @@ -1,29 +1,31 @@ # xzdec(1) completion -*- shell-script -*- -_xzdec() +_comp_cmd_xzdec() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return + local noargopts='!(-*|*M*)' + # shellcheck disable=SC2254 case $prev in - --memory | -!(-*)M) + --memory | -${noargopts}M) return ;; - --help | --version | -!(-*)[hV]) + --help | --version | -${noargopts}[hV]) return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '$(_parse_help "$1")' -- "$cur")) + _comp_compgen_help [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi - _filedir xz # no lzma support here as of xz 4.999.9beta + _comp_compgen_filedir xz # no lzma support here as of xz 4.999.9beta } && - complete -F _xzdec xzdec + complete -F _comp_cmd_xzdec xzdec # ex: filetype=sh diff --git a/completions/ypmatch b/completions/ypmatch index 13249f0..db5a233 100644 --- a/completions/ypmatch +++ b/completions/ypmatch @@ -1,9 +1,9 @@ # bash completion for yp-tools -*- shell-script -*- -_ypmatch() +_comp_cmd_ypmatch() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return local map cmd=${1##*/} @@ -12,15 +12,12 @@ _ypmatch() if [[ $cmd == ypmatch && $cword -eq 1 && ${#words[@]} -eq 3 ]]; then map=${words[2]} - COMPREPLY=($(compgen -W '$(ypcat $map 2>/dev/null | \ - cut -d':' -f 1)' -- "$cur")) + _comp_compgen_split -- "$(ypcat "$map" 2>/dev/null | cut -d':' -f 1)" else [[ $cmd == ypmatch && $cword -ne 2 ]] && return - COMPREPLY=($(compgen -W \ - '$(printf "%s\n" $(ypcat -x 2>/dev/null | \ - cut -d"\"" -f 2))' -- "$cur")) + _comp_compgen_split -- "$(ypcat -x 2>/dev/null | cut -d'"' -f 2)" fi } && - complete -F _ypmatch ypmatch ypcat + complete -F _comp_cmd_ypmatch ypmatch ypcat # ex: filetype=sh diff --git a/completions/yum-arch b/completions/yum-arch index 883c77e..070d020 100644 --- a/completions/yum-arch +++ b/completions/yum-arch @@ -1,16 +1,16 @@ # yum-arch(8) completion -*- shell-script -*- -_yum_arch() +_comp_cmd_yum_arch() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W '-d -v -vv -n -c -z -s -l -q' -- "$cur")) + _comp_compgen -- -W '-d -v -vv -n -c -z -s -l -q' else - _filedir -d + _comp_compgen_filedir -d fi } && - complete -F _yum_arch yum-arch + complete -F _comp_cmd_yum_arch yum-arch # ex: filetype=sh diff --git a/completions/zopfli b/completions/zopfli index 8c02885..49d5305 100644 --- a/completions/zopfli +++ b/completions/zopfli @@ -1,9 +1,9 @@ # bash completion for zopfli -*- shell-script -*- -_zopfli() +_comp_cmd_zopfli() { - local cur prev words cword - _init_completion || return + local cur prev words cword comp_args + _comp_initialize -- "$@" || return case $prev in -h) @@ -12,18 +12,19 @@ _zopfli() esac if [[ $cur == -* ]]; then - COMPREPLY=($(compgen -W \ - '$(_parse_help "$1" -h | command sed -e "s/#$//")' -- "$cur")) + _comp_compgen -R help -- -h + ((${#COMPREPLY[@]})) && + _comp_compgen -- -W '"${COMPREPLY[@]%#}"' [[ ${COMPREPLY-} == --i ]] && compopt -o nospace return fi - _tilde "$cur" || return + _comp_compgen_tilde && return - local IFS=$'\n' xspec="*.@(gz|t[ag]z)" + local xspec="*.@(gz|t[ag]z)" compopt -o filenames - COMPREPLY=($(compgen -f -X "$xspec" -- "$cur") $(compgen -d -- "$cur")) + _comp_compgen -- -f -X "$xspec" -o plusdirs } && - complete -F _zopfli zopfli + complete -F _comp_cmd_zopfli zopfli # ex: filetype=sh diff --git a/completions/zopflipng b/completions/zopflipng index 4526cd9..76a0c30 100644 --- a/completions/zopflipng +++ b/completions/zopflipng @@ -1,39 +1,40 @@ # bash completion for zopflipng -*- shell-script -*- -_zopflipng() +_comp_cmd_zopflipng() { - local cur prev words cword split - _init_completion -s || return + local cur prev words cword was_split comp_args + _comp_initialize -s -- "$@" || return case $prev in -h | --help) return ;; --splitting) - COMPREPLY=($(compgen -W '{0..3}' -- "$cur")) + _comp_compgen -- -W '{0..3}' return ;; esac - $split && return + [[ $was_split ]] && return if [[ $cur == -* ]]; then - COMPREPLY=($(_parse_help "$1" -h)) - COMPREPLY=($(compgen -W '${COMPREPLY[@]%:}' -- "$cur")) + _comp_compgen -R help -- -h + ((${#COMPREPLY[@]})) && + _comp_compgen -- -W '"${COMPREPLY[@]%:}"' [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi if [[ ${words[*]} != *\ --prefix=* ]]; then # 2 png args only if --prefix not given - local args - _count_args - ((args < 3)) && _filedir png + local REPLY + _comp_count_args + ((REPLY < 3)) && _comp_compgen_filedir png else # otherwise arbitrary number of png args - _filedir png + _comp_compgen_filedir png fi } && - complete -F _zopflipng zopflipng + complete -F _comp_cmd_zopflipng zopflipng # ex: filetype=sh diff --git a/configure.ac b/configure.ac index 9f1abc2..83a6f12 100644 --- a/configure.ac +++ b/configure.ac @@ -1,11 +1,14 @@ AC_PREREQ([2.60]) -AC_INIT([bash-completion], [2.11]) -AM_INIT_AUTOMAKE([foreign dist-xz no-dist-gzip -Wall -Wno-portability -Werror]) +AC_INIT([bash-completion], [2.12.0]) dnl x-release-please-version +dnl tar-pax for portable UTF-8 handling +AM_INIT_AUTOMAKE([ + foreign dist-xz no-dist-gzip tar-pax -Wall -Wno-portability -Werror +]) AC_PROG_LN_S AC_PROG_MKDIR_P AC_PROG_SED AC_ARG_WITH([pytest],[ --with-pytest=executable],[PYTEST="$withval"]) -if test -z "$PYTEST"; then +if test "x$PYTEST" = x; then AC_CHECK_PROGS([PYTEST],[pytest pytest-3],[pytest]) fi AC_CONFIG_FILES([ @@ -14,6 +17,8 @@ completions/Makefile doc/Makefile helpers/Makefile test/Makefile +test/fallback/Makefile +test/fallback/completions/Makefile test/t/Makefile test/t/unit/Makefile ]) diff --git a/doc/Makefile.am b/doc/Makefile.am index 6930b9c..8bac9e8 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,8 +1,4 @@ EXTRA_DIST = \ - bash_completion.txt \ - bashrc \ - inputrc \ - main.txt \ - makeHtml.sh \ - styleguide.txt \ - testing.txt + configuration.md \ + styleguide.md \ + testing.md diff --git a/doc/api-and-naming.md b/doc/api-and-naming.md new file mode 100644 index 0000000..59b2c36 --- /dev/null +++ b/doc/api-and-naming.md @@ -0,0 +1,232 @@ +# API and naming + +## General API conventions + +Most of the functions in bash-completion generate completions and directly +inject them to the `COMPREPLY` array variable, as required for completions to +work. + +Most other functions make use of "output" variables, i.e. assign values to +them. The name of an output variable should be basically in lowercase. +Consult the commentary before each function in the source to find out the +specific names. `local`izing output variables before invoking a function that +populates them is the caller's responsibility. Note that if calling multiple +functions that assign output to the same variable during one completion +function run, each result should be copied to another variable between the +calls to avoid it possibly being overwritten and lost on the next call. Also, +the variables should also be ensured to be clear before each call that +references the value, variable name, or their existence, typically by `unset +-v`ing them when multiple such calls are used, to avoid them interfering with +each other. + +The most common output variable is named `REPLY`. The use of the uppercase is +unconventional, but this choice of the name is intended to be consistent with +the value substitutions `${| func; }`, which is originally supported by mksh +and will be supported by Bash >= 5.3. The value substitutions are replaced by +the contents of the output variable `REPLY` set by `func`. Although we cannot +currently assume Bash 5.3 in the codebase, but we can switch to the value +substitutions at the point Bash <= 5.2 disappear from the market. + +Everything in fallback completion files (ones starting with an underscore) +is considered private and is to be named accordingly. Fallback files are not +intended to be explicitly used with `_comp_xfunc`, and completion files having +precedence over them may have a different API. + +## Availability + +All public API functions and variables are marked with a `@since VERSION` +comment, where `VERSION` is the bash-completion version the thing was +introduced in. + +Similarly, deprecated functions and variables are either marked with a +`@deprecated VERSION ...` comment, or deprecated using the +`_comp_deprecate_func VERSION OLD_NAME NEW_NAME` function. +`VERSION` in both cases is the bash-completion version the thing was +deprecated in. + +## Naming + +Due to its nature, bash-completion adds a number of functions and variables in +the shell's environment. + +| | `bash_completion` | `completions/*` | +|:------------------------------------|:--------------------|:--------------------------------------------------------------------------------------| +| public configuration variables | `BASH_COMPLETION_*` | `BASH_COMPLETION_CMD_${Command^^}_${Config^^}` | +| private non-local variables | `_comp__*` | `_comp_cmd_${Command}__${Data}` | +| private non-local mutable variables | `_comp__*_mut_*` | `_comp_cmd_${Command}__mut_${Data}` | +| exporter function local variables | `_*` (not `_comp*`) | `_*` (not `_comp*`) | +| public/exported functions | `_comp_*` | `_comp_xfunc_${Command}_${Utility}` (functions for use with `_comp_xfunc`) | +| - completers (for `complete -F`) | `_comp_complete_*` | `_comp_cmd_${Command}` | +| - generators | `_comp_compgen_*` | `_comp_xfunc_${Command}_compgen_${Name}` (generators for use with `_comp_compgen -x`) | +| private/internal functions | `_comp__*` | `_comp_cmd_${Command}__${Utility}` (utility functions) | +| - generators | | `_comp_cmd_${Command}__compgen_${Name}` (generators for use with `_comp_compgen -i`) | + +`${Command}` refers to a command name (with characters not allowed in POSIX +function or variable names replaced by an underscore), `${Config}` the name of +a configurable thing, `^^` means uppercase, `${Data}` is an identifier for the +data contained in the variable, and `${Utility}` describes the typical usage of +the function. + +Variables and functions affecting multiple completions are usually defined +in the main `bash_completion` file and do not require any additional files to +be sourced. Variables and functions in command specific completion files in +`completions/*` follow a slightly different naming scheme; they include +`cmd` in their name as well as the name of the command. + +Public configuration variables are shell ones that affect the runtime behavior +of various completions. As a rule of thumb, we lean towards not providing +customizability but rather strive to provide great completion behavior out of +the box. But there are some, see [configuration](configuration.md). + +Variables and functions whose name contains a double underscore (`__`) anywhere +in their name are private implementation details, not part of the stable API, +and not intended to be used outside of their defining context. Internally, the +double underscores serve as privacy scope delimiters; there can be more than one +pair of them in a name, and functions and variables are intended to reference +and call other functions and variables within that scope, one level deep, +sharing a common prefix. For example, a function named `_comp_foo` is "allowed" +to access `_comp_foo__*` where `*` does not contain any double underscores, +i.e. it should not access `_comp_foo__something__*` despite the common prefix. + +Private non-local variables are considered readonly by default. When a +completion function needs to change variables for e.g. caching purposes, the +variables should contain the infix `*_mut_*` anywhere in their names. This is +needed to tell the test framework to allow these variables changing. +Nevertheless, the completion results should be consistent among different calls +and unaffected by the state of the cache variables when it is called. + +Internal local variables of functions that "export" their results using a +variable name that is passed in start with an underscore and do not start with +`_comp`. The variable names that are passed in for this purpose must not start +with an underscore. + +Functions with names prefixed with `_comp_xfunc_` are intended to be used +through the `_comp_xfunc` function from files other than the one they are +defined in. From the same file they can be used directly using their complete +name. + +Function names start with an underscore in order to avoid them being +included in completions of command names. (Except naturally when a command +starting with an underscore is being completed.) The underscore prefix does +not have anything to do with whether the thing is considered public or +private in the API, nor anything else really. + +The `BASH_COMPLETION_` prefix provides a namespace and makes it clear what +these variables relate to. The `_comp` in other names serves a similar purpose, +but because these are used a lot in the code (unlike the public configuration +variables), using something shorter is beneficial. We hope and believe this is +distinctive and clash free enough. + +It is known that a lot of functions and variables in the tree do not follow +these naming rules yet. Things introduced after version 2.11 should, and we are +evaluating our options for handling older ones. + +## Exported functions (xfunc) + +Exported functions (xfunc) are the functions defined in completion files for +specific commands but exposed to other completion files. The xfuncs have the +name `_comp_xfunc_CMD_NAME` where `CMD` is the name of the associated command, +and `NAME` is the name of the utility. The other functions defined in specific +completion files are considered private and should not be called outside the +file. + +The xfuncs can be called by `_comp_xfunc CMD NAME ARGS` from external files. +The xfuncs are supposed to be directly called as `_comp_xfunc_CMD_NAME ARGS` +from the same file where they are defined, or if they wrap a `_comp_cmd_NAME__*` +function, that one should be called directly instead. + +Note: The name `xfunc` was initially the name of a utility function, `_xfunc`, +to call "eXternal FUNCtions" that are defined in other completion files. The +concept is later extended to also mean "eXported". + +## Generator functions + +The generator functions, which have names of the form `_comp_compgen_NAME`, are +used to generate completion candidates. A generator function is supposed to be +called by `_comp_compgen [OPTS] NAME ARGS` where `OPTS = -aRl|-v var|-c cur|-C +dir|-F sep` are the options to modify the behavior (see the code comment of +`_comp_compgen` for details). When there are no `opts`, the generator function +is supposed to be directly called as `_comp_compgen_NAME ARGS`. The result is +stored in the target variable (which is `COMPREPLY` by default but can be +specified by `-v var` in `OPTS`). + +### Implementing a generator function + +To implement a generator function, one should generate completion candidates by +calling `_comp_compgen` or other generators. + +To avoid conflicts with the options specified to `_comp_compgen`, one should +not directly modify or reference the target variable. When post-filtering is +needed, store them in a local array, filter them, and finally append them by +`_comp_compgen -- -W '"${_arr[@]}"'`. To split the output of commands and +append the results to the target variable, use `_comp_compgen_split -- "$(cmd +...)"` instead of using `_comp_split COMPREPLY "$(cmd ...)"`. + +A generator function should replace the existing content of the variable by +default. When the appending behavior is favored, the caller should specify it +through `_comp_compgen -a NAME`. The generator function do not need to process +it because internal `_comp_compgen` calls automatically reflects the option +`-a` specified to the outer calls of `_comp_compgen`. + +The exit status is implementation-defined. + +- The `_comp_compgen -- COMPGEN_ARGS` returns whether there is at least one + completion. This is useful when one wants to reuse the array content with + `"${tmp[@]}"` avoiding `nounset` error. +- Some use other rules for the exit status. E.g., `help` and `usage` return + whether there were options *before* filtering by cur. This is used for + `_comp_compgen_help || _comp_compgen_usage`. + +Whether to clear the target variable on runtime error (when `-a` is not +specified in `OPTS`) is implementation-defined. On the other hand, the +generator function should not leave any side effects in the target variable on +usage error. Note that the target variable might be cleared by the internal +calls of `_comp_compgen`. To explicitly clear the target variable, +`_comp_compgen_set` can be called without arguments. + +Exported generators are defined with the names `_comp_xfunc_CMD_compgen_NAME` +and called by `_comp_compgen [opts] -x CMD NAME args`. Internal generators are +defined with the names `_comp_cmd_CMD__compgen_NAME` and called by +`_comp_compgen [opts] -i CMD NAME args`. + +#### Local variables of generator and `_comp_compgen -U var` + +A generator should basically define local variables with the names starting +with `_`. However, a generator sometimes needs to use local variable names +that do not start with `_`. When the child generator call with a variable name +(such as `local var; _comp_compgen -v var`) is used within the generator, the +local variable can unexpectedly mask a local variable of the upper call. + +For example, the following call fails to obtain the result of generator +`mygen1` because the array `arr` is masked by the same name of a local variable +in `_comp_compgen_mygen1`. + +```bash +# generator with a problem +_comp_compgen_mygen1() +{ + local -a arr=(1 2 3) + _comp_compgen -av arr -- -W '4 5 6' + _comp_compgen_set "${arr[@]/#p}" +} + +_comp_compgen -v arr mygen1 # fails to get the result in array `arr` +``` + +To avoid this, a generator that defines a local variable with its name not +starting with `_` can use the option `-U var` to unlocalize the variable on +assigning the final result. + +```bash +# properly designed generator +_comp_compgen_mygen1() +{ + local -a arr=(1 2 3) + _comp_compgen -av arr -- -W '4 5 6' + _comp_compgen -U arr set "${arr[@]/#p}" +} +``` + +To avoid unexpected unlocalization of previous-scope variables, a generator +should specify `-U var` to a child generator (that attempts to store results to +the current target variable) at most once. diff --git a/doc/bash_completion.txt b/doc/bash_completion.txt deleted file mode 100644 index e67f98b..0000000 --- a/doc/bash_completion.txt +++ /dev/null @@ -1,66 +0,0 @@ -Bash completion -=============== - -Configuration files -------------------- - -*$BASH_COMPLETION_USER_FILE*:: - Sourced late by bash_completion, pretty much after everything else. - Use this file for example to load additional completions, and to remove - and override ones installed by bash_completion. Defaults to - `~/.bash_completion` if unset or null. - -*$XDG_CONFIG_HOME/bash_completion*:: - Sourced by the bash_completion.sh profile.d script. This file is - suitable for definitions of all `COMP_*` environment variables - below. If `$XDG_CONFIG_HOME` is unset or null, `~/.config` is - used instead of it. - -Environment variables ---------------------- - -*BASH_COMPLETION_COMPAT_DIR*:: - Directory for pre-dynamic loading era (pre-2.0) backwards compatibility - completion files that are loaded eagerly from `bash_completion` when it is - loaded. If unset or null, the default compatibility directory to use is - `/etc/bash_completion.d`. - -*COMP_CONFIGURE_HINTS*:: - If set and not null, `configure` completion will return the entire option - string (e.g. `--this-option=DESCRIPTION`) so one can see what kind of data - is required and then simply delete the descriptive text and add one's own - data. If unset or null (default), `configure` completion will strip - everything after the '=' when returning completions. - -*COMP_CVS_REMOTE*:: - If set and not null, `cvs commit` completion will try to complete on - remotely checked-out files. This requires passwordless access to the - remote repository. Default is unset. - -*COMP_FILEDIR_FALLBACK*:: - If set and not null, completions that look for filenames based on their - "extensions" will fall back to suggesting all files if there are none - matching the sought ones. - -*COMP_IWLIST_SCAN*:: - If set and not null, `iwconfig` completion will try to complete on - available wireless networks identifiers. Default is unset. - -*COMP_KNOWN_HOSTS_WITH_HOSTFILE*:: - If set and not null (default), known hosts completion will complement - hostnames from ssh's known_hosts files with hostnames taken from the file - specified by the HOSTFILE shell variable (compgen -A hostname). If null, - known hosts completion will omit hostnames from HOSTFILE. Omitting - hostnames from HOSTFILE is useful if HOSTFILE contains many entries for - local web development or ad-blocking. - -*COMP_KNOWN_HOSTS_WITH_AVAHI*:: - If set and not null, known hosts completion will try to use `avahi-browse` - for additional completions. This may be a slow operation in some setups. - Default is unset. - -*COMP_TAR_INTERNAL_PATHS*:: - If set and not null *before* sourcing bash_completion, `tar` completion - will do correct path completion for tar file contents. If unset or null, - `tar' completion will do correct completion for paths to tar files. See - also README. diff --git a/doc/bashrc b/doc/bashrc deleted file mode 120000 index e22ec0e..0000000 --- a/doc/bashrc +++ /dev/null @@ -1 +0,0 @@ -../test/config/bashrc
\ No newline at end of file diff --git a/doc/configuration.md b/doc/configuration.md new file mode 100644 index 0000000..186ac9a --- /dev/null +++ b/doc/configuration.md @@ -0,0 +1,149 @@ +# Configuration + +## Files + +### `$BASH_COMPLETION_USER_FILE` + +Sourced late by `bash_completion`, pretty much after everything else. +Use this file for example to load additional completions, and to remove +and override ones installed by bash_completion. Defaults to +`~/.bash_completion` if unset or null. + +Available since version 2.7. + +### `$XDG_CONFIG_HOME/bash_completion` + +Sourced by the `bash_completion.sh` `profile.d` script. This file is +suitable for definitions of all `COMP*` shell variables below. +If `$XDG_CONFIG_HOME` is unset or null,`~/.config` is +used instead of it. + +Available since version 1.90. + +## Shell variables + +### `BASH_COMPLETION_COMPAT_DIR` + +Directory for pre-dynamic loading era (pre-2.0) and other backwards +compatibility completion files that are loaded eagerly from `bash_completion` +when it is loaded. If unset or null, the default compatibility directories to +use are `/etc/bash_completion.d`, and `bash_completion.d` relative to +`bash_completion` location. + +Available since version 1.1. + +### `BASH_COMPLETION_FILEDIR_FALLBACK` + +If set and not null, completions that look for filenames based on their +"extensions" will fall back to suggesting all files if there are none +matching the sought ones. + +Available since version 2.12. +Deprecated alias: `COMP_FILEDIR_FALLBACK` + +### `BASH_COMPLETION_KNOWN_HOSTS_WITH_AVAHI` + +If set and not null, known hosts completion will try to use `avahi-browse` +for additional completions. This may be a slow operation in some setups. +Default is unset. + +Available since version 2.12. +Deprecated alias: `COMP_KNOWN_HOSTS_WITH_AVAHI` + +### `BASH_COMPLETION_KNOWN_HOSTS_WITH_HOSTFILE` + +If set and not null (default), known hosts completion will complement +hostnames from ssh's known_hosts files with hostnames taken from the file +specified by the `HOSTFILE` shell variable (`compgen -A hostname`). If null, +known hosts completion will omit hostnames from `HOSTFILE`. Omitting +hostnames from `HOSTFILE` is useful if `HOSTFILE` contains many entries for +local web development or ad-blocking. + +Available since version 2.12. +Deprecated alias: `COMP_KNOWN_HOSTS_WITH_HOSTFILE` + +### `BASH_COMPLETION_COMPAT_IGNORE` + +Files in `BASH_COMPLETION_COMPAT_DIR` (the compat dir) to ignore, specified by +a glob pattern. The completion files in the compat dir whose basename matches +with this pattern will not be sourced by `bash_completion` at its load time. +This variable can be used to suppress the problematic completions. Note that +backup files and Makefiles in the compat dir are by default ignored regardless +of this setting. + +One example is `acroread.sh` which is installed by some versions of Adobe +Reader, overrides `_filedir` with an incompatible version, and causes +various problems. To recover this `_filedir`, another completion file +`redefine_filedir` had been placed in the compat dir, which could also +cause another incompatibility when the user uses their own version of +bash-completion instead of the systemwide version. To suppress these files +one can set the following value: + +```bash +export BASH_COMPLETION_COMPAT_IGNORE='@(acroread.sh|redefine_filedir)' +``` + +- <https://bugzilla.redhat.com/677446> +- <http://forums.adobe.com/thread/745833> +- <https://bugzilla.redhat.com/show_bug.cgi?id=1171396#c27> +- <https://github.com/scop/bash-completion/pull/667> + +Available since version 2.12. + +### `BASH_COMPLETION_CMD_CONFIGURE_HINTS` + +If set and not null, `configure` completion will return the entire option +string (e.g. `--this-option=DESCRIPTION`) so one can see what kind of data +is required and then simply delete the descriptive text and add one's own +data. If unset or null (default), `configure` completion will strip +everything after the `=` when returning completions. + +Available since version 2.12. +Deprecated alias: `COMP_CONFIGURE_HINTS` + +### `BASH_COMPLETION_CMD_CVS_REMOTE` + +If set and not null, `cvs commit` completion will try to complete on +remotely checked-out files. This requires passwordless access to the +remote repository. Default is unset. + +Available since version 2.12. +Deprecated alias: `COMP_CVS_REMOTE` + +### `BASH_COMPLETION_CMD_IWCONFIG_SCAN` + +If set and not null, `iwconfig` completion will try to complete on +available wireless networks identifiers. Default is unset. + +Available since version 2.12. +Deprecated alias: `COMP_IWLIST_SCAN` + +### `BASH_COMPLETION_CMD_SMBTREE_SCAN` + +If set and not null, various samba related tool completions perform +a network scan to complete domains and hosts. Default is unset. + +Available since version 2.12. +Deprecated alias: `COMP_SAMBA_SCAN` + +### `BASH_COMPLETION_CMD_TAR_INTERNAL_PATHS` + +If set and not null _before sourcing_ the `tar` completion, it will do +correct path completion for tar file _contents_. If unset or null, +_paths to_ tar files will be correctly completed. Unfortunately we do not +have a way to make both Just Work properly at the moment. We consider it +more important to have proper completion of paths to tar files than it is +to have completion for their contents, so the default is unset. + +Available since version 2.12. +Deprecated alias: `COMP_TAR_INTERNAL_PATHS` + +## Shell options + +### `no_empty_cmd_completion` + +If on, completions producing command names do not do anything if the command to +be completed is empty. This can be useful on systems where generating the +entire list of commands takes a long time. + +Available since version 2.12. diff --git a/doc/inputrc b/doc/inputrc deleted file mode 120000 index b6f22e6..0000000 --- a/doc/inputrc +++ /dev/null @@ -1 +0,0 @@ -../test/config/inputrc
\ No newline at end of file diff --git a/doc/main.txt b/doc/main.txt deleted file mode 100644 index d8a3076..0000000 --- a/doc/main.txt +++ /dev/null @@ -1,18 +0,0 @@ -Bash-completion -=============== -Freddy Vulto (FVu) -v1.0, Mar 2009 - -Preface -======= -Bash completion extends bashs standard completion behavior to achieve -complex command lines with just a few keystrokes. This project was -conceived to produce programmable completion routines for the most -common Linux/UNIX commands, reducing the amount of typing sysadmins -and programmers need to do on a daily basis. - -// include::intro.txt[] -include::bash_completion.txt[] - -include::styleguide.txt[] -include::testing.txt[] diff --git a/doc/makeHtml.sh b/doc/makeHtml.sh deleted file mode 100755 index 79780eb..0000000 --- a/doc/makeHtml.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -eu - -[ -d html~ ] || mkdir html~ -a2x -D html~ -d book -f xhtml --asciidoc-opts="--unsafe" main.txt diff --git a/doc/styleguide.md b/doc/styleguide.md new file mode 100644 index 0000000..46c4b4d --- /dev/null +++ b/doc/styleguide.md @@ -0,0 +1,232 @@ +# Coding style guide + +## Introduction + +This document attempts to explain the basic styles and patterns that +are used in the bash completion. New code should try to conform to +these standards so that it is as easy to maintain as existing code. +Of course every rule has an exception, but it's important to know +the rules nonetheless! + +This is particularly directed at people new to the bash completion +codebase, who are in the process of getting their code reviewed. +Before getting a review, please read over this document and make +sure your code conforms to the recommendations here. + +## Indentation + +Indent step should be 4 spaces, no tabs. + +## Globbing in case labels + +Avoid "fancy" globbing in case labels, just use traditional style when +possible. For example, do `--foo|--bar)` instead of `--@(foo|bar))`. +Rationale: the former is easier to read, often easier to grep, and +doesn't confuse editors as bad as the latter, and is concise enough. + +## `[[ ]]` vs `[ ]` + +Always use `[[ ]]` instead of `[ ]`. Rationale: the former is less error +prone, more featureful, and slightly faster. + +## `$x` and `! $x` vs `-n $x` and `-z $x` + +Use `[[ $x ]]` and `[[ ! $x ]]` instead of `[[ -n $x ]]` and `[[ -z $x ]]`, +and similarly with the `test` builtin. +Rationale: no strong technical reasons to prefer either style, but the former +is subjectively slightly more readable and it was traditionally more common in +the codebase before this style item was standardized. + +## Line wrapping + +Try to wrap lines at 79 characters. Never go past this limit, unless +you absolutely need to (example: a long sed regular expression, or the +like). This also holds true for the documentation and the testsuite. +Other files, like ChangeLog, or COPYING, are exempt from this rule. + +## `$( )` vs backticks + +When you need to do some code substitution in your completion script, +you _MUST_ use the `$(...)` construct, rather than backticks. The former +is preferable because anyone, with any keyboard layout, is able to +type it. Backticks aren't always available, without doing strange +key combinations. + +## `-o filenames` + +As a rule of thumb, do not use `complete -o filenames`. Doing it makes +it take effect for all completions from the affected function, which +may break things if some completions from the function must not be +escaped as filenames. Instead, use `compopt -o filenames` to turn on +`-o filenames` behavior dynamically when returning completions that +need that kind of processing (e.g. file and command names). The +`_filedir` and `_filedir_xspec` helpers do this automatically whenever +they return some completions. + +## `[[ ${COMPREPLY-} == *= ]] && compopt -o nospace` + +The above is functionally a shorthand for: + +```bash +if [[ ${#COMPREPLY[@]} -eq 1 && ${COMPREPLY[0]} == *= ]]; then + compopt -o nospace +fi +``` + +It is used to ensure that long options' name won't get a space +appended after the equal sign. Calling `compopt -o nospace` makes sense +in case completion actually occurs: when only one completion is +available in `COMPREPLY`. + +## `[[ $was_split ]] && return` + +Should be used in completions using the `-s` flag of `_comp_initialize`, +or other similar cases where `_comp__split_longopt` has been invoked, after +`$prev` has been managed but before `$cur` is considered. If `$cur` of the +form `--foo=bar` was split into `prev=--foo` and `cur=bar`, and the `$prev` +block did not process the option argument completion, it makes sense to return +immediately after the $prev block because`--foo` obviously +takes an argument and the remainder of the completion function is +unlikely to provide meaningful results for the required argument. +Think of this as a catch-all for unknown options requiring an +argument. + +Note that even when using this, options that are known to require an +argument but for which we don't have argument completion should be +explicitly handled (non-completed) in the `$prev` handling block because +`--foo=bar` options can often be written without the equals sign, and in +that case the long option splitting does not occur. + +## Use arithmetic evaluation + +When dealing with numeric data, take advantage of arithmetic evaluation. +In essence, use `(( ... ))` whenever it can replace `[[ ... ]]` because the +syntax is more readable; no need for `$`-prefixes, numeric comparison etc +operators are more familiar and easier on the eye. + +## Array subscript access + +Array subscripts are arithmetic expressions, take advantage of that. +E.g. write `${foo[bar]}`, not `${foo[$bar]}`, and similarly `${foo[bar+1]}` +vs `${foo[((bar+1))]}` or `${foo[$((bar+1))]}`, `${foo[--i]}` vs +`${foo[((--i))]}`. + +## Loop variable names + +Use `i`, `j`, `k` for loop-local indices; `n` and `m` for lengths; some other +descriptive name typically based on array name but in singular when looping +over actual values. If an index or value is to be accessed later on instead of +being just locally for looping, use a more descriptive and specific name for +it. + +## Function and variable names + +See [API and naming](api-and-naming.md). + +## Quoting of words + +To avoid unexpected word splitting and pathname expansions, an argument of +commands needs to be properly quoted when it contains shell expansions such as +`$var`, `$(cmd)`, and `$((expr))`. + +When one intentionally wants word splitting and pathname expansions, one should +consider using the utility functions provided by bash-completion. To safely +split a string without being affected by non-standard `IFS` and pathname +expansions, use the shell function `_comp_split`. To safely obtain filenames +by pathname expansions without being affected by `failglob`, etc., use the +shell function `_comp_expand_glob`. Note that `_comp_expand_glob` should be +always used for the pathname patterns even if the pattern does not contain +shell expansions. + +In the following contexts, the quoting to suppress word splitting and pathname +expansions are not needed. + +- The right-hand sides of variable assignments ... `v=WORD` (e.g. `v=$var`) +- The arguments of conditional commands ... `[[ WORD ]]` (e.g. `[[ $var ]]`) +- The argument specified to `case` statement ... `case WORD in foo) ;; esac` + (e.g. `case $var in foo) ;; esac`) + +In bash-completion, we do not quote them by default. However, there are +exceptions where the quoting is still needed for other reasons. + +- When the word *directly* contains shell special characters (space, tab, + newline, or a character from ``;|&()<>\\$`'"#!~{``), these characters need to + be quoted. The "*directly*" means that the special characters produced by + shell expansions are excluded here. For example, when one wants to include a + whitespace as a part of the value of the word, the right-hand side can be + quoted as `v="a b"`. +- An empty word (i.e., the word whose value is an empty string) is specified by + `""`. The right-hand side of an assignment technically can be an empty + string as `var=`, but we still use `var=""` there because `shellcheck` + suggests that e.g. `var= cmd` is confusing with `var=cmd`. +- `$*` and `${array[*]}` need to be always quoted because they can be affected + by the word splitting in bash <= 4.2 even in the above contexts. +- In the following contexts, double-quoting of shell expansions is needed + unless the result of expansions is intentionally treated as glob patterns or + regular expressions. + - The right-hand sides of `==`, `!=`, and `=~` in the conditional commands + ... `[[ word == "$var" ]]` + - The case patterns ... `case word in "$var") ;; esac` + +Note: Here strings `cat <<<$var` are also supposed to be safe against word +splitting and pathname expansions without quoting, but bash <= 4.3 has a bug +[1], so they need to be quoted for as long as we support bash 4.3. + +- [koalaman/shellcheck#1009 (comment)](https://github.com/koalaman/shellcheck/issues/1009#issuecomment-488395630) + +There are also preferences on the type of quoting, which are though not too +strict. We prefer to use double quotes over single quotes by default. When +the value contains `$`, `` ` ``, `\`, and `"`, we can use single quotes to +avoid backslash escaping or use the one that minimizes the use of backslash +escaping. When the value contains control characters such as a tab and a +newline, we do not directly include them but we use backslash escape sequences +such as `\t` and `\n` in the escape string `$'...'`. + +### `patsub_replacement` for array elements + +There is a subtlety in quoting of the array expansions with a pattern +replacement when `shopt -s patsub_replacement` (Bash >= 5.2) is +enabled (which is the default of Bash >= 5.2). + +For example, the array expansions with a pattern replacement may be +used to add a prefix to every element in an array: + +```bash +# problem in bash >= 5.2 +arr=("${arr[@]/#/$prefix}") +``` + +However, this has the problem. The characters `&` contained in +`$prefix`, if any, will be replaced with the matched string. The +unexpected `patsub_replacement` may be suppressed by quoting the +replacement as + +```bash +# problem with bash <= 4.2 or "shopt -s compat42" +arr=("${arr[@]/#/"$prefix"}") +``` + +However, this has another problem in bash < 4.3 or when `shopt -s +compat42` is turned on. The inner double quotations are treated +literally so that the `PREFIX` instead of ``"PREFIX"` is prefixed to +elements. To avoid this situation, the outer double quotations might +be removed, but this has even another problem of the pathname +expansions and `IFS`. + +Specifically for prefixing and suffixing, we may instead use +`_comp_compgen -- -P prefix` and `_comp_compgen -- -S suffix`. + +```bash +# solution for prefixing +_comp_compgen -Rv arr -- -P "$prefix" -W '"${arr[@]}"' +``` + +In a general case, one needs to modify each array element in a loop, +where only the replacement is quoted. + +```bash +# general solution +for i in "${!arr[@]}"; do + arr[i]=${arr[i]//pat/"$rep"} +done +``` diff --git a/doc/styleguide.txt b/doc/styleguide.txt deleted file mode 100644 index 2251e77..0000000 --- a/doc/styleguide.txt +++ /dev/null @@ -1,134 +0,0 @@ -Coding Style Guide -================== - -Introduction ------------- -This document attempts to explain the basic styles and patterns that -are used in the bash completion. New code should try to conform to -these standards so that it is as easy to maintain as existing code. -Of course every rule has an exception, but it's important to know -the rules nonetheless! - -This is particularly directed at people new to the bash completion -codebase, who are in the process of getting their code reviewed. -Before getting a review, please read over this document and make -sure your code conforms to the recommendations here. - -Indentation ------------ -Indent step should be 4 spaces, no tabs. - -Globbing in case labels ------------------------ - -Avoid "fancy" globbing in case labels, just use traditional style when -possible. For example, do "--foo|--bar)" instead of "--@(foo|bar))". -Rationale: the former is easier to read, often easier to grep, and -doesn't confuse editors as bad as the latter, and is concise enough. - -[[ ]] vs [ ] ----------------- - -Always use [[ ]] instead of [ ]. Rationale: the former is less error -prone, more featureful, and slightly faster. - -Line wrapping -------------- - -Try to wrap lines at 79 characters. Never go past this limit, unless -you absolutely need to (example: a long sed regular expression, or the -like). This also holds true for the documentation and the testsuite. -Other files, like ChangeLog, or COPYING, are exempt from this rule. - -$(...) vs \`...` ----------------- - -When you need to do some code substitution in your completion script, -you *MUST* use the $(...) construct, rather than the \`...`. The former -is preferable because anyone, with any keyboard layout, is able to -type it. Backticks aren't always available, without doing strange -key combinations. - --o filenames ------------- - -As a rule of thumb, do not use "complete -o filenames". Doing it makes -it take effect for all completions from the affected function, which -may break things if some completions from the function must not be -escaped as filenames. Instead, use "compopt -o filenames" to turn on -"-o filenames" behavior dynamically when returning completions that -need that kind of processing (e.g. file and command names). The -_filedir and _filedir_xspec helpers do this automatically whenever -they return some completions. - -[[ ${COMPREPLY-} == *= ]] && compopt -o nospace ------------------------------------------------- - -The above is functionally a shorthand for: ----- -if [[ ${#COMPREPLY[@]} -eq 1 && ${COMPREPLY[0]} == *= ]]; then - compopt -o nospace -fi ----- -It is used to ensure that long options' name won't get a space -appended after the equal sign. Calling compopt -o nospace makes sense -in case completion actually occurs: when only one completion is -available in COMPREPLY. - -$split && return ----------------- - -Should be used in completions using the -s flag of _init_completion, -or other similar cases where _split_longopt has been invoked, after -$prev has been managed but before $cur is considered. If $cur of the -form --foo=bar was split into $prev=--foo and $cur=bar and the $prev -block did not process the option argument completion, it makes sense -to return immediately after the $prev block because --foo obviously -takes an argument and the remainder of the completion function is -unlikely to provide meaningful results for the required argument. -Think of this as a catch-all for unknown options requiring an -argument. - -Note that even when using this, options that are known to require an -argument but for which we don't have argument completion should be -explicitly handled (non-completed) in the $prev handling block because ---foo=bar options can often be written without the equals sign, and in -that case the long option splitting does not occur. - -Use arithmetic evaluation -------------------------- - -When dealing with numeric data, take advantage of arithmetic evaluation. -In essence, use (( ... )) whenever it can replace [[ ... ]] because the -syntax is more readable; no need for $-prefixes, numeric comparison etc -operators are more familiar and easier on the eye. - -Array subscript access ----------------------- - -Array subscripts are arithmetic expressions, take advantage of that. -E.g. write ${foo[bar]}, not ${foo[$bar]}, and similarly ${foo[bar+1]} -vs ${foo[((bar+1))]} or ${foo[$((bar+1))]}, ${foo[--i]} vs ${foo[((--i))]}. - -Loop variable names -------------------- - -Use i, j, k for loop-local indices; n and m for lengths; some other descriptive -name typically based on array name but in singular when looping over actual -values. If an index or value is to be accessed later on instead of being just -locally for looping, use a more descriptive and specific name for it. - -///////////////////////////////////////// -case/esac vs if ---------------- - -quoting -------- - -awk vs cut for simple cases ---------------------------- - -variable and function naming ----------------------------- - -///////////////////////////////////////// diff --git a/doc/testing.md b/doc/testing.md new file mode 100644 index 0000000..99db290 --- /dev/null +++ b/doc/testing.md @@ -0,0 +1,80 @@ +# Automated testing + +## Introduction + +The bash-completion package contains an automated test suite. Running the +tests should help verifying that bash-completion works as expected. The tests +are also very helpful in uncovering software regressions at an early stage. + +The test suite is written in Python, using [pytest](https://pytest.org/) +and [pexpect](https://pexpect.readthedocs.io/). + +## Coding style + +For the Python part, all of it is checked and formatted using +[Ruff](https://docs.astral.sh/ruff/). + +## Installing dependencies + +Installing dependencies should be easy using your local package manager or +`pip`. Python 3.6 or newer is required, and the rest of the Python package +dependencies are specified in the `test/requirements.txt` file. If using `pip`, +this file can be fed directly to it, e.g. like: + +```shell +python3 -m pip install -r test/requirements.txt +``` + +### Debian/Ubuntu + +On Debian/Ubuntu you can use `apt-get`: + +```shell +sudo apt-get install python3-pytest python3-pexpect +``` + +This should also install the necessary dependencies. Only Debian testing +(buster) and Ubuntu 18.10 (cosmic) and later have an appropriate version +of pytest in the repositories. + +### Fedora/RHEL/CentOS + +On Fedora and RHEL/CentOS (with EPEL) you can try `yum` or `dnf`: + +```shell +sudo yum install python3-pytest python3-pexpect +``` + +This should also install the necessary dependencies. At time of writing, only +Fedora 29 comes with recent enough pytest. + +## Structure + +Tests are in the `t/` subdirectory, with `t/test_*.py` being completion +tests, and `t/unit/test_unit_*.py` unit tests. + +## Running the tests + +Tests are run by calling `pytest` on the desired test directories or +individual files, for example in the project root directory: + +```shell +pytest test/t +``` + +See `test/docker/entrypoint.sh` for how and what we run and test in CI. + +### Specifying bash binary + +The test suite standard uses `bash` as found in `$PATH`. Export the +`bashcomp_bash` environment variable with a path to another bash executable if +you want to test against something else. + +## Maintenance + +### Adding a completion test + +You can run `cd test && ./generate cmd` to add a test for the `cmd` +command. Additional arguments will be passed to the first generated test case. +This will add the `test/t/test_cmd.py` file with a very basic test, and add it +to `test/t/Makefile.am`. Add additional tests to the generated file. diff --git a/doc/testing.txt b/doc/testing.txt deleted file mode 100644 index 3ec7c97..0000000 --- a/doc/testing.txt +++ /dev/null @@ -1,112 +0,0 @@ -Automated testing -================= - -Introduction ------------- -The bash-completion package contains an automated test suite. Running the -tests should help verifying that bash-completion works as expected. The tests -are also very helpful in uncovering software regressions at an early stage. - -The test suite is written in Python, using https://pytest.org/[pytest] -and https://pexpect.readthedocs.io/[pexpect]. - - -Coding Style Guide ------------------- - -For the Python part, all of it is formatted using -https://github.com/ambv/black[Black], and we also run -https://flake8.pycqa.org/[Flake8] on it. - - -Installing dependencies ------------------------ - -Installing dependencies should be easy using your local package manager or -`pip`. Python 3.4 or newer is required, and the rest of the Python package -dependencies are specified in the `test/requirements.txt` file. If using `pip`, -this file can be fed directly to it, e.g. like: ------------------------------------- -pip install -r test/requirements.txt ------------------------------------- - - -Debian/Ubuntu -~~~~~~~~~~~~~ - -On Debian/Ubuntu you can use `apt-get`: -------------- -sudo apt-get install python3-pytest python3-pexpect -------------- -This should also install the necessary dependencies. Only Debian testing -(buster) and Ubuntu 18.10 (cosmic) and later have an appropriate version -of pytest in the repositories. - -Fedora/RHEL/CentOS -~~~~~~~~~~~~~~~~~~ - -On Fedora and RHEL/CentOS (with EPEL) you can try `yum` or `dnf`: -------------- -sudo yum install python3-pytest python3-pexpect -------------- -This should also install the necessary dependencies. At time of writing, only -Fedora 29 comes with recent enough pytest. - - - -Structure ---------- - -Tests are in the `t/` subdirectory, with `t/test_\*.py` being completion -tests, and `t/unit/test_unit_\*.py` unit tests. - - -Running the tests ------------------ - -Tests are run by calling `pytest` on the desired test directories or -individual files, for example in the project root directory: ------------------------ -pytest test/t ------------------------ - -See `test/docker/docker-script.sh` for how and what we run and test in CI. - - -Specifying bash binary -~~~~~~~~~~~~~~~~~~~~~~ - -The test suite standard uses `bash` as found in PATH. Export the -`bashcomp_bash` environment variable with a path to another bash executable if -you want to test against something else. - - -Maintenance ------------ - - -Adding a completion test -~~~~~~~~~~~~~~~~~~~~~~~~ - -You can run `cd test && ./generate cmd` to add a test for the `cmd` -command. Additional arguments will be passed to the first generated test case. -This will add the `test/t/test_cmd.py` file with a very basic test, and add it -to `test/t/Makefile.am`. Add additional tests to the generated file. - -Rationale ---------- - - -Naming conventions -~~~~~~~~~~~~~~~~~~ - -Test suite or testsuite -^^^^^^^^^^^^^^^^^^^^^^^ -The primary Wikipedia page is called -https://en.wikipedia.org/wiki/Test_suite[test suite] and not testsuite, so -that's what this document sticks to. - -script/generate -^^^^^^^^^^^^^^^ -The name and location of this code generation script come from Ruby on Rails' -https://en.wikibooks.org/wiki/Ruby_on_Rails/Tools/Generators[script/generate]. diff --git a/extra/git-post-commit.sh b/extra/git-post-commit.sh deleted file mode 100755 index e74c294..0000000 --- a/extra/git-post-commit.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -e - -# Post-commit hook for triggering bash-completion Docker Hub test image -# builds at https://hub.docker.com/r/vskytta/bash-completion/ -# -# To enable: ln -s ../../extra/git-post-commit.sh .git/hooks/post-commit -# -# The bash-completion.docker-hub-trigger-url config option must be set to -# the full Docker Hub build trigger URL to hit. - -url=$(git config bash-completion.docker-hub-trigger-url) - -test "$(git symbolic-ref --short HEAD 2>/dev/null)" = master - -git diff-tree -r --name-only --no-commit-id HEAD | - grep -qxE 'test/test-cmd-list\.txt' - -curl \ - --silent --show-error \ - --max-time 30 \ - --header Content-Type:application/json \ - --data '{"build":true}' \ - $url >/dev/null diff --git a/extra/git-pre-push.sh b/extra/git-pre-push.sh deleted file mode 100755 index 52d990e..0000000 --- a/extra/git-pre-push.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh -e - -# Pre-push hook for triggering bash-completion Docker Hub test image -# builds at https://hub.docker.com/r/vskytta/bash-completion/ -# -# To enable: ln -s ../../extra/git-pre-push.sh .git/hooks/pre-push -# -# The bash-completion.docker-hub-trigger-url config option must be set to -# the full Docker Hub build trigger URL to hit. - -url=$(git config bash-completion.docker-hub-trigger-url) || exit 0 - -branch=master -files="test/test-cmd-list\.txt" - -trigger=false -z40=0000000000000000000000000000000000000000 - -while read local_ref local_sha remote_ref remote_sha; do - case $remote_ref in */$branch) ;; *) continue ;; esac - [ $local_sha != $z40 ] || continue # delete not handled (yet?) - if [ $remote_sha = $z40 ]; then - list_files="git ls-tree -r --name-only $local_sha" - else - list_files="git diff --name-only $remote_sha..$local_sha" - fi - ! $list_files | grep -qEx $files || { - trigger=true - break - } -done - -if $trigger; then - cat <<EOF | at -M now - sleep 15 - curl \ - --silent --show-error \ - --max-time 30 \ - --header Content-Type:application/json \ - --data '{"build":true}' \ - $url 2>&1 \ - | logger -e --tag bash-completion-pre-push -EOF -fi diff --git a/extra/make-changelog.py b/extra/make-changelog.py deleted file mode 100755 index c66b704..0000000 --- a/extra/make-changelog.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/python3 - -import sys -from collections import defaultdict -from email.utils import formatdate -from textwrap import wrap -from typing import Dict, List - -import git - -repo = git.Repo(".") -changelog = defaultdict(list) # type: Dict[str, List[str]] - -if len(sys.argv) != 2: - print("Usage: %s SINCE-TAG" % __file__, file=sys.stderr) - sys.exit(2) - -for id in repo.iter_commits("%s..HEAD" % sys.argv[1]): - commit = repo.commit(id) - if not commit.summary.startswith("Merge pull request "): - changelog[commit.author.name].append(commit.summary) - -print("bash-completion (X.Y)") -print("") - -for author in sorted(changelog.keys()): - print(" [ %s ]" % author) - for log in changelog[author]: - print( - "\n".join( - wrap(log, initial_indent=" * ", subsequent_indent=" ") - ) - ) - print("") - -print( - " -- Ville Skyttä <ville.skytta@iki.fi> %s" % formatdate(localtime=True) -) diff --git a/helpers/Makefile.am b/helpers/Makefile.am index 2a0a18d..fb3c0c8 100644 --- a/helpers/Makefile.am +++ b/helpers/Makefile.am @@ -1,4 +1,4 @@ helpersdir = $(datadir)/$(PACKAGE)/helpers -helpers_DATA = perl python +helpers_DATA = perl python make-extract-targets.awk EXTRA_DIST = $(helpers_DATA) diff --git a/helpers/make-extract-targets.awk b/helpers/make-extract-targets.awk new file mode 100644 index 0000000..b0ce10e --- /dev/null +++ b/helpers/make-extract-targets.awk @@ -0,0 +1,93 @@ +# helper AWK script for GNU make -*- awk -*- + +# This AWK script is used by the function `_comp_cmd_make__extract_targets` in +# `completions/make`. This script receives the output of `make -npq' as the +# input file or stdin and outputs the list of targets matching the prefix. +# +# @env prefix Specifies the prefix to match. +# @env prefix_replace Specifies the string that replaces the prefix in the +# output. This is used when we want to omit the directory name in showing +# the list of the completions. +# + +BEGIN { + prefix = ENVIRON["prefix"]; + prefix_replace = ENVIRON["prefix_replace"]; + is_target_block = 0; + target = ""; +} + +function starts_with(str, prefix) { + return substr(str, 1, length(prefix)) == prefix; +} + +# skip any makefile outputs +NR == 1, /^# +Make data base/ { next; } +/^# +Finished Make data base/,/^# +Make data base/ { next; } + +# skip until files section +/^# +Variables/, /^# +Files/ { next; } + +# skip not-target blocks +/^# +Not a target/, /^$/ { next; } + +# The stuff above here describes lines that are not +# explicit targets or not targets other than special ones +# The stuff below here decides whether an explicit target +# should be output. + +# only process the targets the user wants. +starts_with($0, prefix) { is_target_block = 1; } +is_target_block == 0 { next; } + +/^# +File is an intermediate prerequisite/ { # cancel the block + is_target_block = 0; + target = ""; + next; +} + +# end of target block +/^$/ { + is_target_block = 0; + if (target != "") { + print target; + target = ""; + } + next; +} + +# found target block +/^[^#\t:%]+:/ { + # special targets + if (/^\.PHONY:/ ) next; + if (/^\.SUFFIXES:/ ) next; + if (/^\.DEFAULT:/ ) next; + if (/^\.PRECIOUS:/ ) next; + if (/^\.INTERMEDIATE:/ ) next; + if (/^\.SECONDARY:/ ) next; + if (/^\.SECONDEXPANSION:/ ) next; + if (/^\.DELETE_ON_ERROR:/ ) next; + if (/^\.IGNORE:/ ) next; + if (/^\.LOW_RESOLUTION_TIME:/ ) next; + if (/^\.SILENT:/ ) next; + if (/^\.EXPORT_ALL_VARIABLES:/) next; + if (/^\.NOTPARALLEL:/ ) next; + if (/^\.ONESHELL:/ ) next; + if (/^\.POSIX:/ ) next; + if (/^\.NOEXPORT:/ ) next; + if (/^\.MAKE:/ ) next; + + # dont complete with hidden targets unless we are doing a partial completion + if (prefix == "" || prefix ~ /\/$/) + if (substr($0, length(prefix) + 1, 1) ~ /[^a-zA-Z0-9]/) + next; + + target = $0; + sub(/:.*/, "", target); + if (prefix_replace != prefix) + target = prefix_replace substr(target, 1 + length(prefix)); + + next; +} + +# ex: filetype=awk diff --git a/helpers/python b/helpers/python index a74387f..b6c4d5e 100644 --- a/helpers/python +++ b/helpers/python @@ -11,4 +11,4 @@ else: walker = pkgutil.iter_modules for mod in walker(): - print(mod[1]) # noqa: E211 + print(mod[1]) diff --git a/pyproject.toml b/pyproject.toml index 2581528..83d0112 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,28 @@ -[tool.black] +[tool.ruff] line-length = 79 -target-version = ["py34", "py35", "py36", "py37", "py38"] +target-version = "py37" +lint.select = ["E", "F", "B"] +lint.ignore = [ + # https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules + # (keep order of ignores here same as ^there for maintainability) + "W191", + "E111", + "E114", + "E117", + "D206", + "D300", + "Q000", + "Q001", + "Q002", + "Q003", + "COM812", + "COM819", + "ISC001", + "ISC002", + "E501", +] +fix = true + +[tool.ruff.lint.isort] +known-first-party = ["conftest"] +known-third-party = ["pexpect", "pytest"] diff --git a/setup-symlinks.sh b/setup-symlinks.sh index 806de81..1ad8c2c 100755 --- a/setup-symlinks.sh +++ b/setup-symlinks.sh @@ -1,8 +1,8 @@ #!/bin/sh -eu -targetdir="$1" +targetdir=$1 shift -target="$1" +target=$1 shift for file in "$@"; do diff --git a/.dockerignore b/test/.dockerignore index 61f2dc9..61f2dc9 100644 --- a/.dockerignore +++ b/test/.dockerignore diff --git a/test/.gitignore b/test/.gitignore deleted file mode 100644 index c428b94..0000000 --- a/test/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -tmp/ -pytestdebug.log diff --git a/test/Makefile.am b/test/Makefile.am index 591c8f7..aaf32e0 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,14 +1,8 @@ -SUBDIRS = t +SUBDIRS = fallback t EXTRA_DIST = config \ fixtures \ setup.cfg -all: - $(MKDIR_P) tmp - CLEANFILES = \ fixtures/make/extra_makefile - -clean-local: - $(RM) -rf tmp diff --git a/test/config/bashrc b/test/config/bashrc index 141dddc..dcb8aac 100644 --- a/test/config/bashrc +++ b/test/config/bashrc @@ -33,20 +33,26 @@ export BASH_COMPLETION_USER_FILE=/dev/null # ...and avoid stuff in BASH_COMPLETION_USER_DIR and system install locations # overriding in-tree completions. Setting the user dir would otherwise suffice, # but simple xspec completions are only installed if a separate one is not -# found in any completion dirs. Therefore we also point the "system" dirs to -# locations that should not yield valid completions and helpers paths either. -export BASH_COMPLETION_USER_DIR=$( - cd "$SRCDIR/.." || exit 1 - pwd -) -# /var/empty isn't necessarily actually always empty :P -export BASH_COMPLETION_COMPAT_DIR=/var/empty/bash_completion.d +# found in *any* completion dirs, and we want to use our "shadow" completion +# dir with which we cause loading of our in-tree fallback completions +# instead of possibly (system-)installed upstream ones. +export BASH_COMPLETION_USER_DIR="$SRCDIRABS/fallback" +export BASH_COMPLETION_COMPAT_DIR="$SRCDIRABS/../bash_completion.d" export XDG_DATA_DIRS=/var/empty # Make sure default settings are in effect unset -v \ + BASH_COMPLETION_CMD_CONFIGURE_HINTS \ + BASH_COMPLETION_CMD_CVS_REMOTE \ + BASH_COMPLETION_CMD_IWCONFIG_SCAN \ + BASH_COMPLETION_CMD_TAR_INTERNAL_PATHS \ + BASH_COMPLETION_COMPAT_IGNORE \ + BASH_COMPLETION_FILEDIR_FALLBACK \ + BASH_COMPLETION_KNOWN_HOSTS_WITH_HOSTFILE \ COMP_CONFIGURE_HINTS \ COMP_CVS_REMOTE \ + COMP_FILEDIR_FALLBACK \ + COMP_IWLIST_SCAN \ COMP_KNOWN_HOSTS_WITH_HOSTFILE \ COMP_TAR_INTERNAL_PATHS @@ -56,6 +62,24 @@ add_comp_wordbreak_char() [[ "${COMP_WORDBREAKS//[^$1]/}" ]] || COMP_WORDBREAKS+=$1 } +_comp__test_get_env() +{ + ( + # Do not output the state of test variables "_comp__test_+([0-9])_*" + # and internal mutable variables "_comp_*_mut_*". + local IFS=$' \t\n' + # shellcheck disable=SC2046 + unset -v $(compgen -W '"${!_comp_@}"' -X '!_comp_@(_test_+([0-9])_*|*_mut_*)') + _comp_unlocal IFS + + set -o posix + set + ) + declare -F + shopt -p + set -o +} + # Local variables: # mode: shell-script # End: diff --git a/test/docker/Dockerfile b/test/docker/Dockerfile deleted file mode 100644 index 200f918..0000000 --- a/test/docker/Dockerfile +++ /dev/null @@ -1,6 +0,0 @@ -ARG DIST -FROM vskytta/bash-completion:$DIST - -WORKDIR /work -COPY . . -CMD ["test/docker/docker-script.sh"] diff --git a/test/docker/alpine/Dockerfile b/test/docker/alpine/Dockerfile new file mode 100644 index 0000000..e4d9f3b --- /dev/null +++ b/test/docker/alpine/Dockerfile @@ -0,0 +1,23 @@ +FROM alpine + +RUN apk add --no-cache \ + autoconf \ + automake \ + bash \ + gcc \ + make \ + musl-dev \ + py3-pexpect \ + py3-pytest-xdist \ + tar \ + xvfb \ + xvfb-run \ + xz + +# test-cmd-list.txt is just a cache buster here +ADD test-cmd-list.txt \ + docker/alpine/install-packages.sh \ + /tmp/ + +RUN /tmp/install-packages.sh \ + && rm -r /tmp/* diff --git a/test/docker/alpine/install-packages.sh b/test/docker/alpine/install-packages.sh new file mode 100755 index 0000000..7865703 --- /dev/null +++ b/test/docker/alpine/install-packages.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -xeuo pipefail + +cd "${TMPDIR:-/tmp}" + +apk upgrade + +# Nothing much here, at least yet. Useful this way already in order to +# test some very base executables, as well as ones that come from +# busybox. Don't lose that if adding stuff here! + +# An arbitrary package containing an init script or the like for +# testing service completion. +apk add nginx-openrc diff --git a/test/docker/centos7/Dockerfile b/test/docker/centos7/Dockerfile new file mode 100644 index 0000000..c0611e7 --- /dev/null +++ b/test/docker/centos7/Dockerfile @@ -0,0 +1,27 @@ +FROM centos:7 + +RUN set -x \ + && sed -i -e /tsflags=nodocs/d /etc/yum.conf \ + && yum -y install \ + https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \ + && yum -y upgrade \ + && yum -y install \ + /usr/bin/autoconf \ + /usr/bin/automake \ + /usr/bin/make \ + # /usr/bin/which: https://bugzilla.redhat.com/show_bug.cgi?id=1443357 \ + /usr/bin/which \ + /usr/bin/xvfb-run \ + python36-pexpect + +ADD test-cmd-list.txt \ + requirements.txt \ + docker/centos7/install-packages.sh \ + /tmp/ + +RUN set -x \ + && pip3 install --prefix /usr/local -Ir /tmp/requirements.txt + +RUN /tmp/install-packages.sh </tmp/test-cmd-list.txt \ + && yum -Cy clean all \ + && rm -r /tmp/* /root/.cache/pip /var/lib/yum/history/* /var/lib/yum/yumdb/* diff --git a/test/docker/centos7/install-packages.sh b/test/docker/centos7/install-packages.sh new file mode 100755 index 0000000..7373c00 --- /dev/null +++ b/test/docker/centos7/install-packages.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -xeuo pipefail + +shopt -s extglob + +cd "${TMPDIR:-/tmp}" + +while read -r file; do + case $file in + mock | */mock) printf "%s\n" mock ;; + /*) printf "%s\n" "$file" ;; + *) printf "%s\n" {/usr,}/{,s}bin/"$file" ;; + esac +done | + xargs yum -y install diff --git a/test/docker/debian10/Dockerfile b/test/docker/debian10/Dockerfile new file mode 100644 index 0000000..1a19fa3 --- /dev/null +++ b/test/docker/debian10/Dockerfile @@ -0,0 +1,20 @@ +FROM debian:10 + +RUN export DEBIAN_FRONTEND=noninteractive \ + && apt-get update \ + && apt-get -y upgrade \ + && apt-get -y --no-install-recommends install \ + autoconf \ + automake \ + make \ + python3-pexpect \ + python3-pytest-xdist \ + xvfb xauth \ + && ln -s $(bash -c "type -P pytest-3") /usr/local/bin/pytest + +ADD test-cmd-list.txt \ + docker/debian10/install-packages.sh \ + /tmp/ + +RUN /tmp/install-packages.sh </tmp/test-cmd-list.txt \ + && rm -r /tmp/* /var/lib/apt/lists/* diff --git a/test/docker/debian10/install-packages.sh b/test/docker/debian10/install-packages.sh new file mode 100755 index 0000000..20d6556 --- /dev/null +++ b/test/docker/debian10/install-packages.sh @@ -0,0 +1,113 @@ +#!/bin/bash +set -xeuo pipefail + +cd "${TMPDIR:-/tmp}" + +shopt -s extglob +export DEBIAN_FRONTEND=noninteractive + +dpkg --add-architecture i386 # for wine + +apt-get update +apt-get -y upgrade + +apt-get -y --no-install-recommends install \ + apt-file \ + software-properties-common + +apt-add-repository contrib +apt-add-repository non-free + +apt-get -y --no-install-recommends install \ + npm + +npm install -g jshint +npm cache clean --force + +apt-file update + +excluded=$( + cat <<\EOF +arping +bcron +bison++ +fuse +gdb-minimal +gnat-7 +ifupdown +inetutils-ping +lpr +lprng +make-guile +netscript-2.4 +ntpsec-ntpdate +openresolv +pkg-config +strongswan-starter +sudo-ldap +systemd-cron +EOF +) + +# https://github.com/moby/moby/issues/1297 +echo "resolvconf resolvconf/linkify-resolvconf boolean false" | + debconf-set-selections + +# Work around https://bugs.debian.org/1040925 +apt-get -y --no-install-recommends install \ + ca-certificates-java + +while read -r file; do + case $file in + /*) printf "%s\n" "$file" ;; + *) printf "%s\n" {/usr,}/{,s}bin/"$file" ;; + esac +done | + apt-file -lFf search - | + grep -vF "$excluded" | + xargs apt-get -y --no-install-recommends install + +# Required but not pulled in by dependencies: +apt-get -y --no-install-recommends install \ + postgresql-client + +# Build some *BSD tools for testing + +apt-get -y --no-install-recommends install \ + build-essential + +install -dm 755 /usr/local/lib/bsd-bin +apt-get -y --no-install-recommends install bison libbsd-dev subversion + +svn co https://svn.freebsd.org/base/release/11.1.0/usr.bin/sed bsd-sed +cd bsd-sed +sed -i -e 's,^__FBSDID.*,#include <bsd/bsd.h>,' ./*.c +cc -O2 -g -Wall -Wno-unused-const-variable -D_GNU_SOURCE ./*.c \ + -lbsd -o /usr/local/lib/bsd-bin/sed +cd .. +rm -r bsd-sed + +svn co https://svn.freebsd.org/base/release/11.1.0/contrib/one-true-awk +cd one-true-awk +sed -i -e /^__FBSDID/d ./*.c +make YACC="bison -d -y" +install a.out /usr/local/lib/bsd-bin/awk +cd .. +rm -r one-true-awk + +# Install slapt-get and slapt-src + +cd / +curl --fail https://software.jaos.org/slackpacks/slackware64-14.2/slapt-get/slapt-get-0.11.3-x86_64-1.txz | + tar xvJ +bash -x install/doinst.sh +mkdir -p var/lib/pkgtools/packages # 0.11.3 --available empty without this dir +rm -r install +curl --fail https://software.jaos.org/slackpacks/slackware64-14.2/slapt-src/slapt-src-0.3.6-x86_64-1.txz | + tar xvJ +bash -x install/doinst.sh +rm -r install +cp -a usr/lib64/* usr/lib/ +ln -s libcrypto.so.1.1 usr/lib/x86_64-linux-gnu/libcrypto.so.1 +rm -r usr/lib64 +cd - diff --git a/test/docker/docker-script.sh b/test/docker/docker-script.sh deleted file mode 100755 index b3f351f..0000000 --- a/test/docker/docker-script.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -ex - -if [ "$BSD" ]; then - PATH=/usr/local/lib/bsd-bin:$PATH - export PATH -fi - -export bashcomp_bash=bash -env - -autoreconf -i -./configure -make -j - -xvfb-run make distcheck \ - PYTESTFLAGS="--verbose --numprocesses=auto --dist=loadfile" diff --git a/test/docker/entrypoint.sh b/test/docker/entrypoint.sh new file mode 100755 index 0000000..c647782 --- /dev/null +++ b/test/docker/entrypoint.sh @@ -0,0 +1,22 @@ +#!/bin/sh -eux +# shellcheck shell=sh + +if [ "${BSD-}" ]; then + PATH=/usr/local/lib/bsd-bin:$PATH + export PATH +fi + +export bashcomp_bash=bash +env + +oldpwd=$(pwd) +cp -a . /work +cd /work + +autoreconf -i +./configure +make -j + +xvfb-run make distcheck \ + PYTESTFLAGS="${PYTESTFLAGS---verbose -p no:cacheprovider --numprocesses=auto --dist=loadfile}" +cp -p bash-completion-*.tar.* "$oldpwd/" diff --git a/test/docker/fedoradev/Dockerfile b/test/docker/fedoradev/Dockerfile new file mode 100644 index 0000000..7919ac2 --- /dev/null +++ b/test/docker/fedoradev/Dockerfile @@ -0,0 +1,22 @@ +FROM fedora:rawhide + +RUN echo install_weak_deps=False >> /etc/dnf/dnf.conf \ + && sed -i -e /tsflags=nodocs/d /etc/dnf/dnf.conf \ + && dnf -y --refresh upgrade \ + && dnf -y install \ + /usr/bin/autoconf \ + /usr/bin/automake \ + /usr/bin/make \ + /usr/bin/xvfb-run \ + /usr/bin/pytest-3 \ + python3-pexpect \ + python3-pytest-xdist \ + && ln -s $(type -P pytest-3) /usr/local/bin/pytest + +ADD test-cmd-list.txt \ + docker/fedoradev/install-packages.sh \ + /tmp/ + +RUN /tmp/install-packages.sh </tmp/test-cmd-list.txt \ + && dnf -Cy clean all \ + && rm -r /tmp/* /var/lib/dnf/history.sqlite* /var/lib/dnf/repos/* diff --git a/test/docker/fedoradev/install-packages.sh b/test/docker/fedoradev/install-packages.sh new file mode 100755 index 0000000..70d143c --- /dev/null +++ b/test/docker/fedoradev/install-packages.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -xeuo pipefail + +shopt -s extglob + +cd "${TMPDIR:-/tmp}" + +# upgrade: base image contains vim-minimal, newer vim-* which +# implicitly conflicts with it (typically vim.1.gz) may be in +# repository and pulled in further down, causing install to fail as +# -minimal won't be updated otherwise. +dnf --refresh -y upgrade + +dnf -y install /usr/bin/xargs + +while read -r file; do + case $file in + /*) printf "%s\n" "$file" ;; + *) printf "%s\n" {/usr,}/{,s}bin/"$file" ;; + esac +done | + xargs dnf --skip-broken -y install +# --skip-broken: avoid failing on not found packages. Also prevents actually +# broken packages from failing the install which is not what we want, but +# there doesn't seem to be way to cleanly just skip the not found ones. diff --git a/test/docker/ubuntu14/Dockerfile b/test/docker/ubuntu14/Dockerfile new file mode 100644 index 0000000..6a8a1d5 --- /dev/null +++ b/test/docker/ubuntu14/Dockerfile @@ -0,0 +1,24 @@ +FROM ubuntu:14.04 + +RUN export DEBIAN_FRONTEND=noninteractive \ + && apt-get update \ + && apt-get -y upgrade \ + && apt-get -y --no-install-recommends install \ + autoconf \ + automake \ + make \ + software-properties-common \ + xvfb \ + && python3.4 -c "import urllib.request; urllib.request.urlretrieve('https://github.com/pyston/pyston/releases/download/pyston_2.3.1/pyston_2.3.1_portable_v2.tar.gz', '/tmp/pyston.tar.gz')" \ + && tar xCf /usr/local /tmp/pyston.tar.gz --strip-components=1 + +ADD test-cmd-list.txt \ + requirements.txt \ + docker/ubuntu14/install-packages.sh \ + /tmp/ + +RUN set -x \ + && pyston3 -m pip install -Ir /tmp/requirements.txt + +RUN /tmp/install-packages.sh </tmp/test-cmd-list.txt \ + && rm -r /tmp/* /root/.cache/pip /var/lib/apt/lists/* diff --git a/test/docker/ubuntu14/install-packages.sh b/test/docker/ubuntu14/install-packages.sh new file mode 100755 index 0000000..c0e3c9c --- /dev/null +++ b/test/docker/ubuntu14/install-packages.sh @@ -0,0 +1,69 @@ +#!/bin/bash +set -xeuo pipefail + +cd "${TMPDIR:-/tmp}" + +shopt -s extglob +export DEBIAN_FRONTEND=noninteractive + +dpkg --add-architecture i386 # for wine + +apt-get update +apt-get -y upgrade + +apt-get -y --no-install-recommends install \ + apt-file \ + software-properties-common + +apt-add-repository multiverse + +apt-file update + +excluded=$( + cat <<\EOF +arping +bcron-run +bison++ +evince-gtk +gdb-minimal +gnat-4.6 +gnuspool +heimdal +inetutils-ping +knot-dnsutils +knot-host +lpr +lprng +mariadb-client-5.5 +mariadb-client-core-5.5 +mplayer2 +mysql-client-5.5 +mysql-client-core-5.5 +netscript-2.4 +openresolv +percona-xtradb-cluster-client-5.5 +postgres-xc-client +python3.5-venv +strongswan-starter +sudo-ldap +xserver-xorg-input-synaptics-lts-utopic +xserver-xorg-input-synaptics-lts-vivid +xserver-xorg-input-synaptics-lts-wily +xserver-xorg-input-synaptics-lts-xenial +EOF +) + +while read -r file; do + case $file in + /*) printf "%s\n" "$file" ;; + *) printf "%s\n" {/usr,}/{,s}bin/"$file" ;; + esac +done | + apt-file -lFf search - | + grep -vF "$excluded" | + xargs apt-get -y --no-install-recommends install + +# Required but not pulled in by dependencies: +apt-get -y --no-install-recommends install \ + libwww-perl \ + postgresql-client diff --git a/test/fallback/Makefile.am b/test/fallback/Makefile.am new file mode 100644 index 0000000..096a196 --- /dev/null +++ b/test/fallback/Makefile.am @@ -0,0 +1,7 @@ +SUBDIRS = completions + +EXTRA_DIST = \ + update-fallback-links + +update: + ./update-fallback-links diff --git a/test/fallback/completions/Makefile.am b/test/fallback/completions/Makefile.am new file mode 100644 index 0000000..8efc9cc --- /dev/null +++ b/test/fallback/completions/Makefile.am @@ -0,0 +1,53 @@ +EXTRA_DIST = \ + adb \ + cal \ + cargo \ + chfn \ + chsh \ + dmesg \ + eject \ + flamegraph \ + gaiacli \ + gh \ + golangci-lint \ + gsctl \ + hexdump \ + hwclock \ + ionice \ + jungle \ + keyring \ + kontena \ + look \ + mdbook \ + mock \ + modules \ + mount \ + mount.linux \ + newgrp \ + nmcli \ + nox \ + nvm \ + pip \ + pipenv \ + renice \ + repomanage \ + reptyr \ + rfkill \ + rtcwake \ + ruff \ + runuser \ + rustup \ + slackpkg \ + su \ + svn \ + svnadmin \ + svnlook \ + tokio-console \ + udevadm \ + umount \ + umount.linux \ + vault \ + write \ + xm \ + yq \ + yum diff --git a/test/fallback/completions/README.md b/test/fallback/completions/README.md new file mode 100644 index 0000000..020e4b2 --- /dev/null +++ b/test/fallback/completions/README.md @@ -0,0 +1,8 @@ +# test/fallback/completions + +This directory should contain a non-underscore prefixed symlink to +corresponding underscore prefixed, fallback completions we have in the tree. + +The test suite sets up loading of completions so that this dir is preferred +over system install locations, in order to test our fallback in-tree +completions over possibly installed non-fallback out-of-tree ones. diff --git a/test/fallback/completions/adb b/test/fallback/completions/adb new file mode 120000 index 0000000..66ed7eb --- /dev/null +++ b/test/fallback/completions/adb @@ -0,0 +1 @@ +../../../completions/_adb
\ No newline at end of file diff --git a/test/fallback/completions/cal b/test/fallback/completions/cal new file mode 120000 index 0000000..733c95d --- /dev/null +++ b/test/fallback/completions/cal @@ -0,0 +1 @@ +../../../completions/_cal
\ No newline at end of file diff --git a/test/fallback/completions/cargo b/test/fallback/completions/cargo new file mode 120000 index 0000000..cdc7c30 --- /dev/null +++ b/test/fallback/completions/cargo @@ -0,0 +1 @@ +../../../completions/_cargo
\ No newline at end of file diff --git a/test/fallback/completions/chfn b/test/fallback/completions/chfn new file mode 120000 index 0000000..dc7726d --- /dev/null +++ b/test/fallback/completions/chfn @@ -0,0 +1 @@ +../../../completions/_chfn
\ No newline at end of file diff --git a/test/fallback/completions/chsh b/test/fallback/completions/chsh new file mode 120000 index 0000000..e99eb81 --- /dev/null +++ b/test/fallback/completions/chsh @@ -0,0 +1 @@ +../../../completions/_chsh
\ No newline at end of file diff --git a/test/fallback/completions/dmesg b/test/fallback/completions/dmesg new file mode 120000 index 0000000..b41aa72 --- /dev/null +++ b/test/fallback/completions/dmesg @@ -0,0 +1 @@ +../../../completions/_dmesg
\ No newline at end of file diff --git a/test/fallback/completions/eject b/test/fallback/completions/eject new file mode 120000 index 0000000..1992645 --- /dev/null +++ b/test/fallback/completions/eject @@ -0,0 +1 @@ +../../../completions/_eject
\ No newline at end of file diff --git a/test/fallback/completions/flamegraph b/test/fallback/completions/flamegraph new file mode 120000 index 0000000..3b06327 --- /dev/null +++ b/test/fallback/completions/flamegraph @@ -0,0 +1 @@ +../../../completions/_flamegraph
\ No newline at end of file diff --git a/test/fallback/completions/gaiacli b/test/fallback/completions/gaiacli new file mode 120000 index 0000000..4b13535 --- /dev/null +++ b/test/fallback/completions/gaiacli @@ -0,0 +1 @@ +../../../completions/_gaiacli
\ No newline at end of file diff --git a/test/fallback/completions/gh b/test/fallback/completions/gh new file mode 120000 index 0000000..823628f --- /dev/null +++ b/test/fallback/completions/gh @@ -0,0 +1 @@ +../../../completions/_gh
\ No newline at end of file diff --git a/test/fallback/completions/golangci-lint b/test/fallback/completions/golangci-lint new file mode 120000 index 0000000..b0fa4ef --- /dev/null +++ b/test/fallback/completions/golangci-lint @@ -0,0 +1 @@ +../../../completions/_golangci-lint
\ No newline at end of file diff --git a/test/fallback/completions/gsctl b/test/fallback/completions/gsctl new file mode 120000 index 0000000..e351e86 --- /dev/null +++ b/test/fallback/completions/gsctl @@ -0,0 +1 @@ +../../../completions/_gsctl
\ No newline at end of file diff --git a/test/fallback/completions/hexdump b/test/fallback/completions/hexdump new file mode 120000 index 0000000..90708a0 --- /dev/null +++ b/test/fallback/completions/hexdump @@ -0,0 +1 @@ +../../../completions/_hexdump
\ No newline at end of file diff --git a/test/fallback/completions/hwclock b/test/fallback/completions/hwclock new file mode 120000 index 0000000..7cb778e --- /dev/null +++ b/test/fallback/completions/hwclock @@ -0,0 +1 @@ +../../../completions/_hwclock
\ No newline at end of file diff --git a/test/fallback/completions/ionice b/test/fallback/completions/ionice new file mode 120000 index 0000000..4861309 --- /dev/null +++ b/test/fallback/completions/ionice @@ -0,0 +1 @@ +../../../completions/_ionice
\ No newline at end of file diff --git a/test/fallback/completions/jungle b/test/fallback/completions/jungle new file mode 120000 index 0000000..e9069c2 --- /dev/null +++ b/test/fallback/completions/jungle @@ -0,0 +1 @@ +../../../completions/_jungle
\ No newline at end of file diff --git a/test/fallback/completions/keyring b/test/fallback/completions/keyring new file mode 120000 index 0000000..354980b --- /dev/null +++ b/test/fallback/completions/keyring @@ -0,0 +1 @@ +../../../completions/_keyring
\ No newline at end of file diff --git a/test/fallback/completions/kontena b/test/fallback/completions/kontena new file mode 120000 index 0000000..ceeb17d --- /dev/null +++ b/test/fallback/completions/kontena @@ -0,0 +1 @@ +../../../completions/_kontena
\ No newline at end of file diff --git a/test/fallback/completions/look b/test/fallback/completions/look new file mode 120000 index 0000000..f59ed26 --- /dev/null +++ b/test/fallback/completions/look @@ -0,0 +1 @@ +../../../completions/_look
\ No newline at end of file diff --git a/test/fallback/completions/mdbook b/test/fallback/completions/mdbook new file mode 120000 index 0000000..70a0f1d --- /dev/null +++ b/test/fallback/completions/mdbook @@ -0,0 +1 @@ +../../../completions/_mdbook
\ No newline at end of file diff --git a/test/fallback/completions/mock b/test/fallback/completions/mock new file mode 120000 index 0000000..9a7a69a --- /dev/null +++ b/test/fallback/completions/mock @@ -0,0 +1 @@ +../../../completions/_mock
\ No newline at end of file diff --git a/test/fallback/completions/modules b/test/fallback/completions/modules new file mode 120000 index 0000000..c3fa5e2 --- /dev/null +++ b/test/fallback/completions/modules @@ -0,0 +1 @@ +../../../completions/_modules
\ No newline at end of file diff --git a/test/fallback/completions/mount b/test/fallback/completions/mount new file mode 120000 index 0000000..84a65f1 --- /dev/null +++ b/test/fallback/completions/mount @@ -0,0 +1 @@ +../../../completions/_mount
\ No newline at end of file diff --git a/test/fallback/completions/mount.linux b/test/fallback/completions/mount.linux new file mode 120000 index 0000000..216ae8a --- /dev/null +++ b/test/fallback/completions/mount.linux @@ -0,0 +1 @@ +../../../completions/_mount.linux
\ No newline at end of file diff --git a/test/fallback/completions/newgrp b/test/fallback/completions/newgrp new file mode 120000 index 0000000..cab15d0 --- /dev/null +++ b/test/fallback/completions/newgrp @@ -0,0 +1 @@ +../../../completions/_newgrp
\ No newline at end of file diff --git a/test/fallback/completions/nmcli b/test/fallback/completions/nmcli new file mode 120000 index 0000000..0400cca --- /dev/null +++ b/test/fallback/completions/nmcli @@ -0,0 +1 @@ +../../../completions/_nmcli
\ No newline at end of file diff --git a/test/fallback/completions/nox b/test/fallback/completions/nox new file mode 120000 index 0000000..1ff4f70 --- /dev/null +++ b/test/fallback/completions/nox @@ -0,0 +1 @@ +../../../completions/_nox
\ No newline at end of file diff --git a/test/fallback/completions/nvm b/test/fallback/completions/nvm new file mode 120000 index 0000000..bcaccbb --- /dev/null +++ b/test/fallback/completions/nvm @@ -0,0 +1 @@ +../../../completions/_nvm
\ No newline at end of file diff --git a/test/fallback/completions/pip b/test/fallback/completions/pip new file mode 120000 index 0000000..5fb8a9c --- /dev/null +++ b/test/fallback/completions/pip @@ -0,0 +1 @@ +../../../completions/_pip
\ No newline at end of file diff --git a/test/fallback/completions/pipenv b/test/fallback/completions/pipenv new file mode 120000 index 0000000..faa7ea3 --- /dev/null +++ b/test/fallback/completions/pipenv @@ -0,0 +1 @@ +../../../completions/_pipenv
\ No newline at end of file diff --git a/test/fallback/completions/renice b/test/fallback/completions/renice new file mode 120000 index 0000000..4a62179 --- /dev/null +++ b/test/fallback/completions/renice @@ -0,0 +1 @@ +../../../completions/_renice
\ No newline at end of file diff --git a/test/fallback/completions/repomanage b/test/fallback/completions/repomanage new file mode 120000 index 0000000..b6feb30 --- /dev/null +++ b/test/fallback/completions/repomanage @@ -0,0 +1 @@ +../../../completions/_repomanage
\ No newline at end of file diff --git a/test/fallback/completions/reptyr b/test/fallback/completions/reptyr new file mode 120000 index 0000000..d67c4b5 --- /dev/null +++ b/test/fallback/completions/reptyr @@ -0,0 +1 @@ +../../../completions/_reptyr
\ No newline at end of file diff --git a/test/fallback/completions/rfkill b/test/fallback/completions/rfkill new file mode 120000 index 0000000..6c3c8f6 --- /dev/null +++ b/test/fallback/completions/rfkill @@ -0,0 +1 @@ +../../../completions/_rfkill
\ No newline at end of file diff --git a/test/fallback/completions/rtcwake b/test/fallback/completions/rtcwake new file mode 120000 index 0000000..244c7f1 --- /dev/null +++ b/test/fallback/completions/rtcwake @@ -0,0 +1 @@ +../../../completions/_rtcwake
\ No newline at end of file diff --git a/test/fallback/completions/ruff b/test/fallback/completions/ruff new file mode 120000 index 0000000..2d6104b --- /dev/null +++ b/test/fallback/completions/ruff @@ -0,0 +1 @@ +../../../completions/_ruff
\ No newline at end of file diff --git a/test/fallback/completions/runuser b/test/fallback/completions/runuser new file mode 120000 index 0000000..c3e3422 --- /dev/null +++ b/test/fallback/completions/runuser @@ -0,0 +1 @@ +../../../completions/_runuser
\ No newline at end of file diff --git a/test/fallback/completions/rustup b/test/fallback/completions/rustup new file mode 120000 index 0000000..18b256a --- /dev/null +++ b/test/fallback/completions/rustup @@ -0,0 +1 @@ +../../../completions/_rustup
\ No newline at end of file diff --git a/test/fallback/completions/slackpkg b/test/fallback/completions/slackpkg new file mode 120000 index 0000000..990071a --- /dev/null +++ b/test/fallback/completions/slackpkg @@ -0,0 +1 @@ +../../../completions/_slackpkg
\ No newline at end of file diff --git a/test/fallback/completions/su b/test/fallback/completions/su new file mode 120000 index 0000000..9e972cd --- /dev/null +++ b/test/fallback/completions/su @@ -0,0 +1 @@ +../../../completions/_su
\ No newline at end of file diff --git a/test/fallback/completions/svn b/test/fallback/completions/svn new file mode 120000 index 0000000..0bf5b7f --- /dev/null +++ b/test/fallback/completions/svn @@ -0,0 +1 @@ +../../../completions/_svn
\ No newline at end of file diff --git a/test/fallback/completions/svnadmin b/test/fallback/completions/svnadmin new file mode 120000 index 0000000..90ce5ef --- /dev/null +++ b/test/fallback/completions/svnadmin @@ -0,0 +1 @@ +../../../completions/_svnadmin
\ No newline at end of file diff --git a/test/fallback/completions/svnlook b/test/fallback/completions/svnlook new file mode 120000 index 0000000..efad3dc --- /dev/null +++ b/test/fallback/completions/svnlook @@ -0,0 +1 @@ +../../../completions/_svnlook
\ No newline at end of file diff --git a/test/fallback/completions/tokio-console b/test/fallback/completions/tokio-console new file mode 120000 index 0000000..1fb8249 --- /dev/null +++ b/test/fallback/completions/tokio-console @@ -0,0 +1 @@ +../../../completions/_tokio-console
\ No newline at end of file diff --git a/test/fallback/completions/udevadm b/test/fallback/completions/udevadm new file mode 120000 index 0000000..2498b90 --- /dev/null +++ b/test/fallback/completions/udevadm @@ -0,0 +1 @@ +../../../completions/_udevadm
\ No newline at end of file diff --git a/test/fallback/completions/umount b/test/fallback/completions/umount new file mode 120000 index 0000000..77f661e --- /dev/null +++ b/test/fallback/completions/umount @@ -0,0 +1 @@ +../../../completions/_umount
\ No newline at end of file diff --git a/test/fallback/completions/umount.linux b/test/fallback/completions/umount.linux new file mode 120000 index 0000000..6066bd8 --- /dev/null +++ b/test/fallback/completions/umount.linux @@ -0,0 +1 @@ +../../../completions/_umount.linux
\ No newline at end of file diff --git a/test/fallback/completions/vault b/test/fallback/completions/vault new file mode 120000 index 0000000..abd0ad2 --- /dev/null +++ b/test/fallback/completions/vault @@ -0,0 +1 @@ +../../../completions/_vault
\ No newline at end of file diff --git a/test/fallback/completions/write b/test/fallback/completions/write new file mode 120000 index 0000000..e4d2f2c --- /dev/null +++ b/test/fallback/completions/write @@ -0,0 +1 @@ +../../../completions/_write
\ No newline at end of file diff --git a/test/fallback/completions/xm b/test/fallback/completions/xm new file mode 120000 index 0000000..1fb8840 --- /dev/null +++ b/test/fallback/completions/xm @@ -0,0 +1 @@ +../../../completions/_xm
\ No newline at end of file diff --git a/test/fallback/completions/yq b/test/fallback/completions/yq new file mode 120000 index 0000000..9ea0a28 --- /dev/null +++ b/test/fallback/completions/yq @@ -0,0 +1 @@ +../../../completions/_yq
\ No newline at end of file diff --git a/test/fallback/completions/yum b/test/fallback/completions/yum new file mode 120000 index 0000000..cd8a7ed --- /dev/null +++ b/test/fallback/completions/yum @@ -0,0 +1 @@ +../../../completions/_yum
\ No newline at end of file diff --git a/test/fallback/update-fallback-links b/test/fallback/update-fallback-links new file mode 100755 index 0000000..5da1bcb --- /dev/null +++ b/test/fallback/update-fallback-links @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -euo pipefail + +is_tracked_by_git() +{ + git ls-files --error-unmatch "$1" &>/dev/null +} + +cd "$(dirname "$0")/completions" +for f in *; do + if [[ -L $f ]] && is_tracked_by_git "$f"; then + git rm -f "$f" + fi +done +for f in ../../../completions/_*; do + if is_tracked_by_git "$f"; then + ln -sf "$f" "${f##*/_}" + git add --verbose "${f##*/_}" + fi +done diff --git a/test/fixtures/7z/hello.7z.001 b/test/fixtures/7z/hello.7z.001 Binary files differnew file mode 100644 index 0000000..029e36f --- /dev/null +++ b/test/fixtures/7z/hello.7z.001 diff --git a/test/fixtures/7z/hello.7z.002 b/test/fixtures/7z/hello.7z.002 Binary files differnew file mode 100644 index 0000000..9d8d081 --- /dev/null +++ b/test/fixtures/7z/hello.7z.002 diff --git a/test/fixtures/_command_offset/completer b/test/fixtures/_command_offset/completer new file mode 100755 index 0000000..8253e6d --- /dev/null +++ b/test/fixtures/_command_offset/completer @@ -0,0 +1,30 @@ +#!/bin/sh + +case "${2-}" in + b|ba|bar) + echo bar + ;; + cont1*) + echo cont10 + echo cont11\\ + ;; + f|fo|foo) + echo foo + ;; + l) + echo line\\ + echo two + echo long + ;; + li*) + echo line\\ + echo two + ;; + lo*) + echo long + ;; + *) + echo bar + echo foo + ;; +esac diff --git a/test/fixtures/_comp_compgen/completions/compgen-cmd1 b/test/fixtures/_comp_compgen/completions/compgen-cmd1 new file mode 100644 index 0000000..70199ba --- /dev/null +++ b/test/fixtures/_comp_compgen/completions/compgen-cmd1 @@ -0,0 +1,19 @@ +# Dummy completion file for _comp_compgen tests -*- shell-script -*- + +_comp_xfunc_compgen_cmd1_compgen_generator1() { + _comp_compgen -- -W '5foo 6bar 7baz' +} + +_comp_cmd_compgen_cmd1__compgen_generator2() { + _comp_compgen -- -W '5abc 6def 7ghi' +} + +_comp_cmd_compgen_cmd1() { + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + _comp_compgen -- -W '012 123 234' + _comp_compgen -ai compgen-cmd1 generator2 +} && + complete -F _comp_cmd_compgen_cmd1 compgen-cmd1 + +# ex: filetype=sh diff --git a/test/fixtures/_comp_compgen/completions/compgen-cmd2 b/test/fixtures/_comp_compgen/completions/compgen-cmd2 new file mode 100644 index 0000000..6b6255f --- /dev/null +++ b/test/fixtures/_comp_compgen/completions/compgen-cmd2 @@ -0,0 +1,11 @@ +# Dummy completion file for _comp_compgen tests -*- shell-script -*- + +_comp_cmd_compgen_cmd2() { + local cur prev words cword comp_args + _comp_initialize -- "$@" || return + _comp_compgen -- -W '012 123 234' + _comp_compgen -ax compgen-cmd1 generator1 +} && + complete -F _comp_cmd_compgen_cmd2 compgen-cmd2 + +# ex: filetype=sh diff --git a/test/fixtures/_comp_load/bin/cmd1 b/test/fixtures/_comp_load/bin/cmd1 new file mode 120000 index 0000000..5e6359b --- /dev/null +++ b/test/fixtures/_comp_load/bin/cmd1 @@ -0,0 +1 @@ +../prefix1/bin/cmd1
\ No newline at end of file diff --git a/test/fixtures/_comp_load/bin/cmd2 b/test/fixtures/_comp_load/bin/cmd2 new file mode 120000 index 0000000..933265d --- /dev/null +++ b/test/fixtures/_comp_load/bin/cmd2 @@ -0,0 +1 @@ +../prefix1/sbin/cmd2
\ No newline at end of file diff --git a/test/fixtures/_comp_load/prefix1/bin/cmd1 b/test/fixtures/_comp_load/prefix1/bin/cmd1 new file mode 100755 index 0000000..8125fcf --- /dev/null +++ b/test/fixtures/_comp_load/prefix1/bin/cmd1 @@ -0,0 +1 @@ +echo cmd1 diff --git a/test/fixtures/_comp_load/prefix1/bin/sh b/test/fixtures/_comp_load/prefix1/bin/sh new file mode 100755 index 0000000..5bc7d46 --- /dev/null +++ b/test/fixtures/_comp_load/prefix1/bin/sh @@ -0,0 +1 @@ +echo sh diff --git a/test/fixtures/_comp_load/prefix1/sbin/cmd2 b/test/fixtures/_comp_load/prefix1/sbin/cmd2 new file mode 100755 index 0000000..8fed03c --- /dev/null +++ b/test/fixtures/_comp_load/prefix1/sbin/cmd2 @@ -0,0 +1 @@ +echo cmd2 diff --git a/test/fixtures/_comp_load/prefix1/share/bash-completion/completions/cmd1 b/test/fixtures/_comp_load/prefix1/share/bash-completion/completions/cmd1 new file mode 100644 index 0000000..378a6e3 --- /dev/null +++ b/test/fixtures/_comp_load/prefix1/share/bash-completion/completions/cmd1 @@ -0,0 +1,2 @@ +echo 'cmd1: sourced from prefix1' +complete -C true "$1" diff --git a/test/fixtures/_comp_load/prefix1/share/bash-completion/completions/cmd2 b/test/fixtures/_comp_load/prefix1/share/bash-completion/completions/cmd2 new file mode 100644 index 0000000..167ad62 --- /dev/null +++ b/test/fixtures/_comp_load/prefix1/share/bash-completion/completions/cmd2 @@ -0,0 +1,2 @@ +echo 'cmd2: sourced from prefix1' +complete -C true "$1" diff --git a/test/fixtures/_comp_load/prefix1/share/bash-completion/completions/sh b/test/fixtures/_comp_load/prefix1/share/bash-completion/completions/sh new file mode 100644 index 0000000..18fe79e --- /dev/null +++ b/test/fixtures/_comp_load/prefix1/share/bash-completion/completions/sh @@ -0,0 +1 @@ +echo 'sh: sourced from prefix1' diff --git a/test/fixtures/_comp_load/userdir1/completions/cmd1 b/test/fixtures/_comp_load/userdir1/completions/cmd1 new file mode 100644 index 0000000..b26bf1f --- /dev/null +++ b/test/fixtures/_comp_load/userdir1/completions/cmd1 @@ -0,0 +1,2 @@ +echo 'cmd1: sourced from userdir1' +complete -C true "$1" diff --git a/test/fixtures/_comp_load/userdir2/completions/cmd2 b/test/fixtures/_comp_load/userdir2/completions/cmd2 new file mode 100644 index 0000000..667989b --- /dev/null +++ b/test/fixtures/_comp_load/userdir2/completions/cmd2 @@ -0,0 +1,2 @@ +echo 'cmd2: sourced from userdir2' +complete -C true "$1" diff --git a/test/fixtures/_comp_xfunc/completions/xfunc-test1 b/test/fixtures/_comp_xfunc/completions/xfunc-test1 new file mode 100644 index 0000000..50a35c0 --- /dev/null +++ b/test/fixtures/_comp_xfunc/completions/xfunc-test1 @@ -0,0 +1,12 @@ +# Dummy completion file for _comp_xfunc tests -*- shell-script -*- + +if declare -F _comp_xfunc_xfunc_test1_utility1 &>/dev/null; then + echo "_comp_xfunc_xfunc_test1_utility1 is already defined" + return 1 +fi + +_comp_xfunc_xfunc_test1_utility1() { + printf 'util1[' + printf '<%s>' "$@" + printf ']\n' +} diff --git a/test/fixtures/_comp_xfunc/completions/xfunc-test2 b/test/fixtures/_comp_xfunc/completions/xfunc-test2 new file mode 100644 index 0000000..ff847b3 --- /dev/null +++ b/test/fixtures/_comp_xfunc/completions/xfunc-test2 @@ -0,0 +1,12 @@ +# Dummy completion file for _comp_xfunc tests -*- shell-script -*- + +if declare -F _comp_xfunc_non_standard_name &>/dev/null; then + echo "_comp_xfunc_non_standard_name is already defined" + return 1 +fi + +_comp_xfunc_non_standard_name() { + printf 'util2[' + printf '<%s>' "$@" + printf ']\n' +} diff --git a/test/fixtures/_known_hosts_real/.ssh/config_asterisk_1 b/test/fixtures/_known_hosts/.ssh/config_asterisk_1 index fc09eb0..fc09eb0 100644 --- a/test/fixtures/_known_hosts_real/.ssh/config_asterisk_1 +++ b/test/fixtures/_known_hosts/.ssh/config_asterisk_1 diff --git a/test/fixtures/_known_hosts_real/.ssh/config_asterisk_2 b/test/fixtures/_known_hosts/.ssh/config_asterisk_2 index 42243ad..42243ad 100644 --- a/test/fixtures/_known_hosts_real/.ssh/config_asterisk_2 +++ b/test/fixtures/_known_hosts/.ssh/config_asterisk_2 diff --git a/test/fixtures/_known_hosts_real/.ssh/config_question_mark b/test/fixtures/_known_hosts/.ssh/config_question_mark index 08e1201..08e1201 100644 --- a/test/fixtures/_known_hosts_real/.ssh/config_question_mark +++ b/test/fixtures/_known_hosts/.ssh/config_question_mark diff --git a/test/fixtures/_known_hosts_real/.ssh/config_relative_path b/test/fixtures/_known_hosts/.ssh/config_relative_path index a7ad4d1..a7ad4d1 100644 --- a/test/fixtures/_known_hosts_real/.ssh/config_relative_path +++ b/test/fixtures/_known_hosts/.ssh/config_relative_path diff --git a/test/fixtures/_known_hosts/config b/test/fixtures/_known_hosts/config new file mode 100644 index 0000000..fad532b --- /dev/null +++ b/test/fixtures/_known_hosts/config @@ -0,0 +1,9 @@ + UserKnownHostsFile _known_hosts/known_hosts + + # Unindented +Host * + IPQoS none +Host gee* jar?this-part-we-do-not-complete-at-least-yet + HostName %h.example.com + # Indented, with = separator + Host = hus%%eth0 !negated #not-a-comment diff --git a/test/fixtures/_known_hosts_real/config_full_path b/test/fixtures/_known_hosts/config_full_path index a91649b..a91649b 100644 --- a/test/fixtures/_known_hosts_real/config_full_path +++ b/test/fixtures/_known_hosts/config_full_path diff --git a/test/fixtures/_known_hosts_real/config_include b/test/fixtures/_known_hosts/config_include index a1ae763..d68b0d8 100644 --- a/test/fixtures/_known_hosts_real/config_include +++ b/test/fixtures/_known_hosts/config_include @@ -1,7 +1,9 @@ -#$HOME set to fixtures/_known_hosts_real in unit test +#$HOME set to fixtures/_known_hosts in unit test # Include with full path (recursive one) Include ~/config_full_path # Include with relative path Include config_relative_path # Include with wildcards, and more than one on same row Include config_asterisk* config_?uestion_mark +# Include a directory name. This is a misconfiguration, but ssh ignores it without errors. +Include ../../_known_hosts diff --git a/test/fixtures/_known_hosts_real/config_include_recursion b/test/fixtures/_known_hosts/config_include_recursion index 2777069..2777069 100644 --- a/test/fixtures/_known_hosts_real/config_include_recursion +++ b/test/fixtures/_known_hosts/config_include_recursion diff --git a/test/fixtures/_known_hosts/config_tilde b/test/fixtures/_known_hosts/config_tilde new file mode 100644 index 0000000..93e495b --- /dev/null +++ b/test/fixtures/_known_hosts/config_tilde @@ -0,0 +1,4 @@ +# With quotes and tilde, and = +UserKnownHostsFile = "~/_known_hosts/known_hosts2" +# Without quotes, with tilde, and another on the same line +UserKnownHostsFile ~/_known_hosts/known_hosts3 _known_hosts/known_hosts4 diff --git a/test/fixtures/_known_hosts_real/gee-filename-canary b/test/fixtures/_known_hosts/gee-filename-canary index e69de29..e69de29 100644 --- a/test/fixtures/_known_hosts_real/gee-filename-canary +++ b/test/fixtures/_known_hosts/gee-filename-canary diff --git a/test/fixtures/_known_hosts_real/known_hosts b/test/fixtures/_known_hosts/known_hosts index 646b5b6..646b5b6 100644 --- a/test/fixtures/_known_hosts_real/known_hosts +++ b/test/fixtures/_known_hosts/known_hosts diff --git a/test/fixtures/_known_hosts_real/known_hosts2 b/test/fixtures/_known_hosts/known_hosts2 index 2eb4d4f..2eb4d4f 100644 --- a/test/fixtures/_known_hosts_real/known_hosts2 +++ b/test/fixtures/_known_hosts/known_hosts2 diff --git a/test/fixtures/_known_hosts_real/known_hosts3 b/test/fixtures/_known_hosts/known_hosts3 index 2bdf67a..2bdf67a 100644 --- a/test/fixtures/_known_hosts_real/known_hosts3 +++ b/test/fixtures/_known_hosts/known_hosts3 diff --git a/test/fixtures/_known_hosts_real/known_hosts4 b/test/fixtures/_known_hosts/known_hosts4 index 8510665..8510665 100644 --- a/test/fixtures/_known_hosts_real/known_hosts4 +++ b/test/fixtures/_known_hosts/known_hosts4 diff --git a/test/fixtures/_known_hosts/localhost_config b/test/fixtures/_known_hosts/localhost_config new file mode 100644 index 0000000..3c6a209 --- /dev/null +++ b/test/fixtures/_known_hosts/localhost_config @@ -0,0 +1 @@ +UserKnownHostsFile _known_hosts/localhost_hosts diff --git a/test/fixtures/_known_hosts_real/localhost_hosts b/test/fixtures/_known_hosts/localhost_hosts index ff752c2..ff752c2 100644 --- a/test/fixtures/_known_hosts_real/localhost_hosts +++ b/test/fixtures/_known_hosts/localhost_hosts diff --git a/test/fixtures/_known_hosts/spaced conf b/test/fixtures/_known_hosts/spaced conf new file mode 100644 index 0000000..ac0891e --- /dev/null +++ b/test/fixtures/_known_hosts/spaced conf @@ -0,0 +1,8 @@ + + # Unindented +Host gee + UserKnownHostsFile "_known_hosts/spaced known_hosts" + + # Indented + Host hus #not-a-comment + UserKnownHostsFile "_known_hosts/known_hosts2" diff --git a/test/fixtures/_known_hosts_real/spaced known_hosts b/test/fixtures/_known_hosts/spaced known_hosts index d54a04d..d54a04d 100644 --- a/test/fixtures/_known_hosts_real/spaced known_hosts +++ b/test/fixtures/_known_hosts/spaced known_hosts diff --git a/test/fixtures/_known_hosts_real/config b/test/fixtures/_known_hosts_real/config deleted file mode 100644 index fe3fb54..0000000 --- a/test/fixtures/_known_hosts_real/config +++ /dev/null @@ -1,7 +0,0 @@ - UserKnownHostsFile _known_hosts_real/known_hosts - - # Unindented -Host gee* jar?this-part-we-do-not-complete-at-least-yet - HostName %h.example.com - # Indented - Host hus%%eth0 !negated #not-a-comment diff --git a/test/fixtures/_known_hosts_real/config_tilde b/test/fixtures/_known_hosts_real/config_tilde deleted file mode 100644 index 4181aaf..0000000 --- a/test/fixtures/_known_hosts_real/config_tilde +++ /dev/null @@ -1,4 +0,0 @@ -# With quotes and tilde -UserKnownHostsFile "~/_known_hosts_real/known_hosts2" -# Without quotes, with tilde, and another on the same line -UserKnownHostsFile ~/_known_hosts_real/known_hosts3 _known_hosts_real/known_hosts4 diff --git a/test/fixtures/_known_hosts_real/localhost_config b/test/fixtures/_known_hosts_real/localhost_config deleted file mode 100644 index 30b6623..0000000 --- a/test/fixtures/_known_hosts_real/localhost_config +++ /dev/null @@ -1 +0,0 @@ -UserKnownHostsFile _known_hosts_real/localhost_hosts diff --git a/test/fixtures/_known_hosts_real/spaced conf b/test/fixtures/_known_hosts_real/spaced conf deleted file mode 100644 index 566b92c..0000000 --- a/test/fixtures/_known_hosts_real/spaced conf +++ /dev/null @@ -1,8 +0,0 @@ - - # Unindented -Host gee - UserKnownHostsFile "_known_hosts_real/spaced known_hosts" - - # Indented - Host hus #not-a-comment - UserKnownHostsFile "_known_hosts_real/known_hosts2" diff --git a/test/fixtures/ant/.gitignore b/test/fixtures/ant/.gitignore index 3a08258..3e28307 100644 --- a/test/fixtures/ant/.gitignore +++ b/test/fixtures/ant/.gitignore @@ -1 +1 @@ -.ant-targets-*.xml +/.ant-targets-*.xml diff --git a/test/fixtures/ant/imported-build.xml b/test/fixtures/ant/imported-build.xml index 0cc438f..df6a5f3 100644 --- a/test/fixtures/ant/imported-build.xml +++ b/test/fixtures/ant/imported-build.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<project default="imported-build" name="bash-completion"> +<project default="imported-build" name="bash-completion-imported"> <target name="imported-build"> <!-- ... --> </target> diff --git a/test/fixtures/evince/.BMP b/test/fixtures/apt-mark/example.conf index e69de29..e69de29 100644 --- a/test/fixtures/evince/.BMP +++ b/test/fixtures/apt-mark/example.conf diff --git a/test/fixtures/evince/.CBR b/test/fixtures/bsdtar/test.pax index e69de29..e69de29 100644 --- a/test/fixtures/evince/.CBR +++ b/test/fixtures/bsdtar/test.pax diff --git a/test/fixtures/evince/.CBZ b/test/fixtures/bsdtar/test.rar index e69de29..e69de29 100644 --- a/test/fixtures/evince/.CBZ +++ b/test/fixtures/bsdtar/test.rar diff --git a/test/fixtures/evince/.DJV b/test/fixtures/bsdtar/test.shar index e69de29..e69de29 100644 --- a/test/fixtures/evince/.DJV +++ b/test/fixtures/bsdtar/test.shar diff --git a/test/fixtures/evince/.DJVU b/test/fixtures/dot/test1.gv index e69de29..e69de29 100644 --- a/test/fixtures/evince/.DJVU +++ b/test/fixtures/dot/test1.gv diff --git a/test/fixtures/evince/.DVI b/test/fixtures/dot/test2.dot index e69de29..e69de29 100644 --- a/test/fixtures/evince/.DVI +++ b/test/fixtures/dot/test2.dot diff --git a/test/fixtures/evince/.DVI.gz b/test/fixtures/evince/.DVI.gz deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.DVI.gz +++ /dev/null diff --git a/test/fixtures/evince/.EPS b/test/fixtures/evince/.EPS deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.EPS +++ /dev/null diff --git a/test/fixtures/evince/.EPS.BZ2 b/test/fixtures/evince/.EPS.BZ2 deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.EPS.BZ2 +++ /dev/null diff --git a/test/fixtures/evince/.EPS.GZ b/test/fixtures/evince/.EPS.GZ deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.EPS.GZ +++ /dev/null diff --git a/test/fixtures/evince/.EPS.bz2 b/test/fixtures/evince/.EPS.bz2 deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.EPS.bz2 +++ /dev/null diff --git a/test/fixtures/evince/.EPS.gz b/test/fixtures/evince/.EPS.gz deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.EPS.gz +++ /dev/null diff --git a/test/fixtures/evince/.GIF b/test/fixtures/evince/.GIF deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.GIF +++ /dev/null diff --git a/test/fixtures/evince/.ICO b/test/fixtures/evince/.ICO deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.ICO +++ /dev/null diff --git a/test/fixtures/evince/.JPEG b/test/fixtures/evince/.JPEG deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.JPEG +++ /dev/null diff --git a/test/fixtures/evince/.JPG b/test/fixtures/evince/.JPG deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.JPG +++ /dev/null diff --git a/test/fixtures/evince/.MIFF b/test/fixtures/evince/.MIFF deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.MIFF +++ /dev/null diff --git a/test/fixtures/evince/.PBM b/test/fixtures/evince/.PBM deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.PBM +++ /dev/null diff --git a/test/fixtures/evince/.PCX b/test/fixtures/evince/.PCX deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.PCX +++ /dev/null diff --git a/test/fixtures/evince/.PDF b/test/fixtures/evince/.PDF deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.PDF +++ /dev/null diff --git a/test/fixtures/evince/.PDF.BZ2 b/test/fixtures/evince/.PDF.BZ2 deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.PDF.BZ2 +++ /dev/null diff --git a/test/fixtures/evince/.PDF.GZ b/test/fixtures/evince/.PDF.GZ deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.PDF.GZ +++ /dev/null diff --git a/test/fixtures/evince/.PDF.bz2 b/test/fixtures/evince/.PDF.bz2 deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.PDF.bz2 +++ /dev/null diff --git a/test/fixtures/evince/.PDF.gz b/test/fixtures/evince/.PDF.gz deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.PDF.gz +++ /dev/null diff --git a/test/fixtures/evince/.PGM b/test/fixtures/evince/.PGM deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.PGM +++ /dev/null diff --git a/test/fixtures/evince/.PNG b/test/fixtures/evince/.PNG deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.PNG +++ /dev/null diff --git a/test/fixtures/evince/.PNM b/test/fixtures/evince/.PNM deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.PNM +++ /dev/null diff --git a/test/fixtures/evince/.PPM b/test/fixtures/evince/.PPM deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.PPM +++ /dev/null diff --git a/test/fixtures/evince/.PS b/test/fixtures/evince/.PS deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.PS +++ /dev/null diff --git a/test/fixtures/evince/.PS.BZ2 b/test/fixtures/evince/.PS.BZ2 deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.PS.BZ2 +++ /dev/null diff --git a/test/fixtures/evince/.PS.GZ b/test/fixtures/evince/.PS.GZ deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.PS.GZ +++ /dev/null diff --git a/test/fixtures/evince/.PS.bz2 b/test/fixtures/evince/.PS.bz2 deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.PS.bz2 +++ /dev/null diff --git a/test/fixtures/evince/.PS.gz b/test/fixtures/evince/.PS.gz deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.PS.gz +++ /dev/null diff --git a/test/fixtures/evince/.TGA b/test/fixtures/evince/.TGA deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.TGA +++ /dev/null diff --git a/test/fixtures/evince/.TIF b/test/fixtures/evince/.TIF deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.TIF +++ /dev/null diff --git a/test/fixtures/evince/.TIFF b/test/fixtures/evince/.TIFF deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.TIFF +++ /dev/null diff --git a/test/fixtures/evince/.XPM b/test/fixtures/evince/.XPM deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.XPM +++ /dev/null diff --git a/test/fixtures/evince/.XWD b/test/fixtures/evince/.XWD deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.XWD +++ /dev/null diff --git a/test/fixtures/evince/.bmp b/test/fixtures/evince/.bmp deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.bmp +++ /dev/null diff --git a/test/fixtures/evince/.cbr b/test/fixtures/evince/.cbr deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.cbr +++ /dev/null diff --git a/test/fixtures/evince/.cbz b/test/fixtures/evince/.cbz deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.cbz +++ /dev/null diff --git a/test/fixtures/evince/.djv b/test/fixtures/evince/.djv deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.djv +++ /dev/null diff --git a/test/fixtures/evince/.djvu b/test/fixtures/evince/.djvu deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.djvu +++ /dev/null diff --git a/test/fixtures/evince/.dvi b/test/fixtures/evince/.dvi deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.dvi +++ /dev/null diff --git a/test/fixtures/evince/.dvi.BZ2 b/test/fixtures/evince/.dvi.BZ2 deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.dvi.BZ2 +++ /dev/null diff --git a/test/fixtures/evince/.dvi.GZ b/test/fixtures/evince/.dvi.GZ deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.dvi.GZ +++ /dev/null diff --git a/test/fixtures/evince/.dvi.bz2 b/test/fixtures/evince/.dvi.bz2 deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.dvi.bz2 +++ /dev/null diff --git a/test/fixtures/evince/.dvi.gz b/test/fixtures/evince/.dvi.gz deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.dvi.gz +++ /dev/null diff --git a/test/fixtures/evince/.eps b/test/fixtures/evince/.eps deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.eps +++ /dev/null diff --git a/test/fixtures/evince/.eps.BZ2 b/test/fixtures/evince/.eps.BZ2 deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.eps.BZ2 +++ /dev/null diff --git a/test/fixtures/evince/.eps.GZ b/test/fixtures/evince/.eps.GZ deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.eps.GZ +++ /dev/null diff --git a/test/fixtures/evince/.eps.bz2 b/test/fixtures/evince/.eps.bz2 deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.eps.bz2 +++ /dev/null diff --git a/test/fixtures/evince/.eps.gz b/test/fixtures/evince/.eps.gz deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.eps.gz +++ /dev/null diff --git a/test/fixtures/evince/.gif b/test/fixtures/evince/.gif deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.gif +++ /dev/null diff --git a/test/fixtures/evince/.ico b/test/fixtures/evince/.ico deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.ico +++ /dev/null diff --git a/test/fixtures/evince/.jpeg b/test/fixtures/evince/.jpeg deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.jpeg +++ /dev/null diff --git a/test/fixtures/evince/.jpg b/test/fixtures/evince/.jpg deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.jpg +++ /dev/null diff --git a/test/fixtures/evince/.miff b/test/fixtures/evince/.miff deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.miff +++ /dev/null diff --git a/test/fixtures/evince/.pbm b/test/fixtures/evince/.pbm deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.pbm +++ /dev/null diff --git a/test/fixtures/evince/.pcx b/test/fixtures/evince/.pcx deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.pcx +++ /dev/null diff --git a/test/fixtures/evince/.pdf b/test/fixtures/evince/.pdf deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.pdf +++ /dev/null diff --git a/test/fixtures/evince/.pdf.BZ2 b/test/fixtures/evince/.pdf.BZ2 deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.pdf.BZ2 +++ /dev/null diff --git a/test/fixtures/evince/.pdf.GZ b/test/fixtures/evince/.pdf.GZ deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.pdf.GZ +++ /dev/null diff --git a/test/fixtures/evince/.pdf.bz2 b/test/fixtures/evince/.pdf.bz2 deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.pdf.bz2 +++ /dev/null diff --git a/test/fixtures/evince/.pdf.gz b/test/fixtures/evince/.pdf.gz deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.pdf.gz +++ /dev/null diff --git a/test/fixtures/evince/.pgm b/test/fixtures/evince/.pgm deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.pgm +++ /dev/null diff --git a/test/fixtures/evince/.png b/test/fixtures/evince/.png deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.png +++ /dev/null diff --git a/test/fixtures/evince/.pnm b/test/fixtures/evince/.pnm deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.pnm +++ /dev/null diff --git a/test/fixtures/evince/.ppm b/test/fixtures/evince/.ppm deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.ppm +++ /dev/null diff --git a/test/fixtures/evince/.ps b/test/fixtures/evince/.ps deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.ps +++ /dev/null diff --git a/test/fixtures/evince/.ps.BZ2 b/test/fixtures/evince/.ps.BZ2 deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.ps.BZ2 +++ /dev/null diff --git a/test/fixtures/evince/.ps.GZ b/test/fixtures/evince/.ps.GZ deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.ps.GZ +++ /dev/null diff --git a/test/fixtures/evince/.ps.bz2 b/test/fixtures/evince/.ps.bz2 deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.ps.bz2 +++ /dev/null diff --git a/test/fixtures/evince/.ps.gz b/test/fixtures/evince/.ps.gz deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.ps.gz +++ /dev/null diff --git a/test/fixtures/evince/.tga b/test/fixtures/evince/.tga deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.tga +++ /dev/null diff --git a/test/fixtures/evince/.tif b/test/fixtures/evince/.tif deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.tif +++ /dev/null diff --git a/test/fixtures/evince/.tiff b/test/fixtures/evince/.tiff deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.tiff +++ /dev/null diff --git a/test/fixtures/evince/.txt b/test/fixtures/evince/.txt deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.txt +++ /dev/null diff --git a/test/fixtures/evince/.xpm b/test/fixtures/evince/.xpm deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.xpm +++ /dev/null diff --git a/test/fixtures/evince/.xwd b/test/fixtures/evince/.xwd deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/.xwd +++ /dev/null diff --git a/test/fixtures/evince/foo/.gitignore b/test/fixtures/evince/foo/.gitignore deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/evince/foo/.gitignore +++ /dev/null diff --git a/test/fixtures/kdvi/.DVI b/test/fixtures/kdvi/.DVI deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kdvi/.DVI +++ /dev/null diff --git a/test/fixtures/kdvi/.DVI.Z b/test/fixtures/kdvi/.DVI.Z deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kdvi/.DVI.Z +++ /dev/null diff --git a/test/fixtures/kdvi/.DVI.bz2 b/test/fixtures/kdvi/.DVI.bz2 deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kdvi/.DVI.bz2 +++ /dev/null diff --git a/test/fixtures/kdvi/.DVI.gz b/test/fixtures/kdvi/.DVI.gz deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kdvi/.DVI.gz +++ /dev/null diff --git a/test/fixtures/kdvi/.dvi b/test/fixtures/kdvi/.dvi deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kdvi/.dvi +++ /dev/null diff --git a/test/fixtures/kdvi/.dvi.Z b/test/fixtures/kdvi/.dvi.Z deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kdvi/.dvi.Z +++ /dev/null diff --git a/test/fixtures/kdvi/.dvi.bz2 b/test/fixtures/kdvi/.dvi.bz2 deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kdvi/.dvi.bz2 +++ /dev/null diff --git a/test/fixtures/kdvi/.dvi.gz b/test/fixtures/kdvi/.dvi.gz deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kdvi/.dvi.gz +++ /dev/null diff --git a/test/fixtures/kdvi/.txt b/test/fixtures/kdvi/.txt deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kdvi/.txt +++ /dev/null diff --git a/test/fixtures/kdvi/foo/.gitignore b/test/fixtures/kdvi/foo/.gitignore deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kdvi/foo/.gitignore +++ /dev/null diff --git a/test/fixtures/kpdf/.EPS b/test/fixtures/kpdf/.EPS deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kpdf/.EPS +++ /dev/null diff --git a/test/fixtures/kpdf/.PDF b/test/fixtures/kpdf/.PDF deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kpdf/.PDF +++ /dev/null diff --git a/test/fixtures/kpdf/.PS b/test/fixtures/kpdf/.PS deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kpdf/.PS +++ /dev/null diff --git a/test/fixtures/kpdf/.eps b/test/fixtures/kpdf/.eps deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kpdf/.eps +++ /dev/null diff --git a/test/fixtures/kpdf/.pdf b/test/fixtures/kpdf/.pdf deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kpdf/.pdf +++ /dev/null diff --git a/test/fixtures/kpdf/.ps b/test/fixtures/kpdf/.ps deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kpdf/.ps +++ /dev/null diff --git a/test/fixtures/kpdf/.txt b/test/fixtures/kpdf/.txt deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kpdf/.txt +++ /dev/null diff --git a/test/fixtures/kpdf/foo/.gitignore b/test/fixtures/kpdf/foo/.gitignore deleted file mode 100644 index e69de29..0000000 --- a/test/fixtures/kpdf/foo/.gitignore +++ /dev/null diff --git a/test/fixtures/make/.gitignore b/test/fixtures/make/.gitignore index 3d1325c..a9b67f8 100644 --- a/test/fixtures/make/.gitignore +++ b/test/fixtures/make/.gitignore @@ -1 +1 @@ -extra_makefile +/extra_makefile diff --git a/test/fixtures/make/test2/Makefile b/test/fixtures/make/test2/Makefile new file mode 100644 index 0000000..835b514 --- /dev/null +++ b/test/fixtures/make/test2/Makefile @@ -0,0 +1,23 @@ +# makefile + +all: abc/xyz +.PHONY: abc/xyz +abc/xyz 123/xaa 123/xbb: + mkdir -p $(@:/%=) + date > $@ + +sub1test/bar/alpha sub1test/bar/beta: + mkdir -p $(@:/%=) + date > $@ + +sub2test/bar/alpha: + mkdir -p $(@:/%=) + date > $@ + +sub3test/bar/alpha sub3test/foo/alpha: + mkdir -p $(@:/%=) + date > $@ + +sub4test/bar/alpha sub4test/bar/beta sub4test2/foo/gamma: + mkdir -p $(@:/%=) + date > $@ diff --git a/test/fixtures/man/man3/bash-completion-zstd-testcase.3head.zst b/test/fixtures/man/man3/bash-completion-zstd-testcase.3head.zst Binary files differnew file mode 100644 index 0000000..e58c09d --- /dev/null +++ b/test/fixtures/man/man3/bash-completion-zstd-testcase.3head.zst diff --git a/test/fixtures/pkgtools/ports/.gitignore b/test/fixtures/pkgtools/ports/.gitignore index 71d2c0c..7925953 100644 --- a/test/fixtures/pkgtools/ports/.gitignore +++ b/test/fixtures/pkgtools/ports/.gitignore @@ -1,2 +1,2 @@ -INDEX -INDEX-5 +/INDEX +/INDEX-5 diff --git a/test/fixtures/evince/.DVI.BZ2 b/test/fixtures/python/bar.txt index e69de29..e69de29 100644 --- a/test/fixtures/evince/.DVI.BZ2 +++ b/test/fixtures/python/bar.txt diff --git a/test/fixtures/evince/.DVI.GZ b/test/fixtures/python/foo.py index e69de29..e69de29 100644 --- a/test/fixtures/evince/.DVI.GZ +++ b/test/fixtures/python/foo.py diff --git a/test/fixtures/evince/.DVI.bz2 b/test/fixtures/sha256sum/foo index e69de29..e69de29 100644 --- a/test/fixtures/evince/.DVI.bz2 +++ b/test/fixtures/sha256sum/foo diff --git a/test/fixtures/sha256sum/foo.sha256 b/test/fixtures/sha256sum/foo.sha256 new file mode 100644 index 0000000..26d55dc --- /dev/null +++ b/test/fixtures/sha256sum/foo.sha256 @@ -0,0 +1 @@ +e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 foo diff --git a/test/fixtures/shells/etc/shells b/test/fixtures/shells/etc/shells new file mode 100644 index 0000000..0d979db --- /dev/null +++ b/test/fixtures/shells/etc/shells @@ -0,0 +1,2 @@ +# /etc/shells: valid login shells +/bash/completion/canary diff --git a/test/fixtures/xrandr/xrandr b/test/fixtures/xrandr/xrandr new file mode 100755 index 0000000..a4693b5 --- /dev/null +++ b/test/fixtures/xrandr/xrandr @@ -0,0 +1,207 @@ +#!/bin/sh + +if [ "$1" = --help ]; then + + # xrandr 1.5.1 help + cat <<EOF +usage: xrandr [options] + where options are: + --display <display> or -d <display> + --help + -o <normal,inverted,left,right,0,1,2,3> + or --orientation <normal,inverted,left,right,0,1,2,3> + -q or --query + -s <size>/<width>x<height> or --size <size>/<width>x<height> + -r <rate> or --rate <rate> or --refresh <rate> + -v or --version + -x (reflect in x) + -y (reflect in y) + --screen <screen> + --verbose + --current + --dryrun + --nograb + --prop or --properties + --fb <width>x<height> + --fbmm <width>x<height> + --dpi <dpi>/<output> + --output <output> + --auto + --mode <mode> + --preferred + --pos <x>x<y> + --rate <rate> or --refresh <rate> + --reflect normal,x,y,xy + --rotate normal,inverted,left,right + --left-of <output> + --right-of <output> + --above <output> + --below <output> + --same-as <output> + --set <property> <value> + --scale <x>[x<y>] + --scale-from <w>x<h> + --transform <a>,<b>,<c>,<d>,<e>,<f>,<g>,<h>,<i> + --filter nearest,bilinear + --off + --crtc <crtc> + --panning <w>x<h>[+<x>+<y>[/<track:w>x<h>+<x>+<y>[/<border:l>/<t>/<r>/<b>]]] + --gamma <r>[:<g>:<b>] + --brightness <value> + --primary + --noprimary + --newmode <name> <clock MHz> + <hdisp> <hsync-start> <hsync-end> <htotal> + <vdisp> <vsync-start> <vsync-end> <vtotal> + [flags...] + Valid flags: +HSync -HSync +VSync -VSync + +CSync -CSync CSync Interlace DoubleScan + --rmmode <name> + --addmode <output> <name> + --delmode <output> <name> + --listproviders + --setprovideroutputsource <prov-xid> <source-xid> + --setprovideroffloadsink <prov-xid> <sink-xid> + --listmonitors + --listactivemonitors + --setmonitor <name> {auto|<w>/<mmw>x<h>/<mmh>+<x>+<y>} {none|<output>,<output>,...} + --delmonitor <name> +EOF + +elif + [ "$1" = --listmonitors ] +then + + cat <<EOF +Monitors: 2 + 0: +*eDP-1-1 1920/344x1080/193+0+1080 eDP-1-1 + 1: +HDMI-0 1920/477x1080/268+0+0 HDMI-0 +EOF + +elif + [ "$1" = --listproviders ] +then + + cat <<EOF +Providers: number : 2 +Provider 0: id: 0x1b8 cap: 0x1, Source Output crtcs: 4 outputs: 5 associated providers: 1 name:NVIDIA-0 +Provider 1: id: 0x1fe cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 3 outputs: 1 associated providers: 1 name:modesetting +EOF + +else + + cat <<EOF +Screen 0: minimum 8 x 8, current 1920 x 2160, maximum 32767 x 32767 +DP-0 disconnected (normal left inverted right x axis y axis) +DP-1 disconnected (normal left inverted right x axis y axis) +DP-2 disconnected (normal left inverted right x axis y axis) +DP-3 disconnected (normal left inverted right x axis y axis) +HDMI-0 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 477mm x 268mm + 1920x1080 60.00*+ 59.94 50.00 + 1680x1050 59.95 + 1600x900 60.00 + 1440x900 59.89 + 1280x1024 75.02 60.02 + 1280x800 59.81 + 1280x720 60.00 59.94 50.00 + 1152x864 75.00 + 1024x768 75.03 70.07 60.00 + 800x600 75.00 72.19 60.32 56.25 + 720x576 50.00 + 720x480 59.94 + 640x480 75.00 72.81 59.94 +eDP-1-1 connected primary 1920x1080+0+1080 (normal left inverted right x axis y axis) 344mm x 193mm + 1920x1080 144.00*+ 60.01 59.97 59.96 59.93 + 1680x1050 59.95 59.88 + 1400x1050 74.76 59.98 + 1600x900 59.99 59.94 59.95 59.82 + 1280x1024 85.02 75.02 60.02 + 1400x900 59.96 59.88 + 1280x960 85.00 60.00 + 1440x810 60.00 59.97 + 1368x768 59.88 59.85 + 1280x800 59.99 59.97 59.81 59.91 + 1152x864 75.00 + 1280x720 60.00 59.99 59.86 59.74 + 1024x768 85.00 75.05 60.04 85.00 75.03 70.07 60.00 + 1024x768i 86.96 + 960x720 85.00 75.00 60.00 + 928x696 75.00 60.05 + 896x672 75.05 60.01 + 1024x576 59.95 59.96 59.90 59.82 + 960x600 59.93 60.00 + 832x624 74.55 + 960x540 59.96 59.99 59.63 59.82 + 800x600 85.00 75.00 70.00 65.00 60.00 85.14 72.19 75.00 60.32 56.25 + 840x525 60.01 59.88 + 864x486 59.92 59.57 + 700x525 74.76 59.98 + 800x450 59.95 59.82 + 640x512 85.02 75.02 60.02 + 700x450 59.96 59.88 + 640x480 85.09 60.00 85.01 72.81 75.00 59.94 + 720x405 59.51 58.99 + 720x400 85.04 + 684x384 59.88 59.85 + 640x400 59.88 59.98 85.08 + 576x432 75.00 + 640x360 59.86 59.83 59.84 59.32 + 640x350 85.08 + 512x384 85.00 75.03 70.07 60.00 + 512x384i 87.06 + 512x288 60.00 59.92 + 416x312 74.66 + 480x270 59.63 59.82 + 400x300 85.27 72.19 75.12 60.32 56.34 + 432x243 59.92 59.57 + 320x240 85.18 72.81 75.00 60.05 + 360x202 59.51 59.13 + 360x200 85.04 + 320x200 85.27 + 320x180 59.84 59.32 + 320x175 85.27 + 1680x1050 (0x1c5) 146.250MHz -HSync +VSync + h: width 1680 start 1784 end 1960 total 2240 skew 0 clock 65.29KHz + v: height 1050 start 1053 end 1059 total 1089 clock 59.95Hz + 1280x1024 (0x1c8) 135.000MHz +HSync +VSync + h: width 1280 start 1296 end 1440 total 1688 skew 0 clock 79.98KHz + v: height 1024 start 1025 end 1028 total 1066 clock 75.02Hz + 1280x1024 (0x1c9) 108.000MHz +HSync +VSync + h: width 1280 start 1328 end 1440 total 1688 skew 0 clock 63.98KHz + v: height 1024 start 1025 end 1028 total 1066 clock 60.02Hz + 1280x800 (0x1ca) 83.500MHz -HSync +VSync + h: width 1280 start 1352 end 1480 total 1680 skew 0 clock 49.70KHz + v: height 800 start 803 end 809 total 831 clock 59.81Hz + 1152x864 (0x1ce) 108.000MHz +HSync +VSync + h: width 1152 start 1216 end 1344 total 1600 skew 0 clock 67.50KHz + v: height 864 start 865 end 868 total 900 clock 75.00Hz + 1024x768 (0x1cf) 78.750MHz +HSync +VSync + h: width 1024 start 1040 end 1136 total 1312 skew 0 clock 60.02KHz + v: height 768 start 769 end 772 total 800 clock 75.03Hz + 1024x768 (0x1d0) 75.000MHz -HSync -VSync + h: width 1024 start 1048 end 1184 total 1328 skew 0 clock 56.48KHz + v: height 768 start 771 end 777 total 806 clock 70.07Hz + 1024x768 (0x1d1) 65.000MHz -HSync -VSync + h: width 1024 start 1048 end 1184 total 1344 skew 0 clock 48.36KHz + v: height 768 start 771 end 777 total 806 clock 60.00Hz + 800x600 (0x1d3) 50.000MHz +HSync +VSync + h: width 800 start 856 end 976 total 1040 skew 0 clock 48.08KHz + v: height 600 start 637 end 643 total 666 clock 72.19Hz + 800x600 (0x1d2) 49.500MHz +HSync +VSync + h: width 800 start 816 end 896 total 1056 skew 0 clock 46.88KHz + v: height 600 start 601 end 604 total 625 clock 75.00Hz + 800x600 (0x1d4) 40.000MHz +HSync +VSync + h: width 800 start 840 end 968 total 1056 skew 0 clock 37.88KHz + v: height 600 start 601 end 605 total 628 clock 60.32Hz + 800x600 (0x1d5) 36.000MHz +HSync +VSync + h: width 800 start 824 end 896 total 1024 skew 0 clock 35.16KHz + v: height 600 start 601 end 603 total 625 clock 56.25Hz + 640x480 (0x1d8) 31.500MHz -HSync -VSync + h: width 640 start 656 end 720 total 840 skew 0 clock 37.50KHz + v: height 480 start 481 end 484 total 500 clock 75.00Hz + 640x480 (0x1da) 25.175MHz -HSync -VSync + h: width 640 start 656 end 752 total 800 skew 0 clock 31.47KHz + v: height 480 start 490 end 492 total 525 clock 59.94Hz +EOF + +fi diff --git a/test/generate b/test/generate index 59f525b..ef0967d 100755 --- a/test/generate +++ b/test/generate @@ -30,7 +30,7 @@ import pytest %s class Test%s: @pytest.mark.complete("%s %s") - def test_1(self, completion): + def test_basic(self, completion): assert completion""" % (marker, name, cmd, args), file=f, diff --git a/test/requirements-dev.txt b/test/requirements-dev.txt index f34f10f..7051ab7 100644 --- a/test/requirements-dev.txt +++ b/test/requirements-dev.txt @@ -1,4 +1,6 @@ -# Python >= 3.6.1 required here +# Python >= 3.7 required here + -r requirements.txt -black==19.10b0 -pre-commit>=2.4.0 + +mypy==1.8.0 +ruff==0.2.2 diff --git a/test/requirements.txt b/test/requirements.txt index df56f4e..ae9fe94 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -1,5 +1,5 @@ -# Python >= 3.4 required here +# Python >= 3.6 required here + pexpect>=4 pytest>=3.6 -pytest-xdist -typing;python_version<"3.5" + pytest-xdist diff --git a/test/runLint b/test/runLint index 95c3887..550995d 100755 --- a/test/runLint +++ b/test/runLint @@ -1,51 +1,72 @@ -#!/bin/bash -u +#!/usr/bin/env bash +set -u gitgrep() { local out=$(git grep -I -P -n "$1" | grep -E '^(bash_completion|completions/|test/)' | grep -Ev "^test/runLint\>${filter_out:+|$filter_out}") - if [ -n "$out" ]; then + if [[ $out ]]; then printf '***** %s\n' "$2" printf '%s\n\n' "$out" fi } -unset CDPATH -cd $(dirname "$0")/.. +unset -v CDPATH +if ! cd "$(dirname "$0")/.."; then + echo 'test/runLint: failed to cd into the working tree of bash-completion' >&2 + exit 1 +fi -cmdstart='(^|[[:space:]]|\()' +cmdstart='(^|[[:space:];&|]|\()' filter_out= -gitgrep $cmdstart"awk\b.*-F([[:space:]]|[[:space:]]*[\"'][^\"']{2,})" \ - 'awk with -F char or -F ERE, use -Fchar instead (Solaris)' +# Note: Since we started to use _comp_awk, we do not have care about the small +# feature set of Solaris awk anymore. -gitgrep $cmdstart"awk\b.*\[:[a-z]*:\]" \ - 'awk with POSIX character class not supported in mawk (Debian/Ubuntu)' +gitgrep "${cmdstart}(_comp_)?awk\b.*\[:[a-z]*:\]" \ + 'awk with POSIX character class not supported in mawk-1.3.3-20090705 (Debian/Ubuntu)' -gitgrep $cmdstart'sed\b.*\\[?+]' \ +gitgrep "$cmdstart"'sed\b.*\\[?+]' \ 'sed with ? or +, use POSIX BRE instead (\{m,n\})' -gitgrep $cmdstart'sed\b.*\\\|' \ +gitgrep "$cmdstart"'sed\b.*\\\|' \ "sed with \|, use POSIX BRE (possibly multiple sed invocations) or another tool instead" # TODO: really nonportable? appears to work fine in Linux, FreeBSD, Solaris #gitgrep $cmdstart'sed\b.*;' \ # 'sed with ;, use multiple -e options instead (POSIX?) (false positives?)' -gitgrep $cmdstart'sed\b.*[[:space:]]-[^[:space:]]*[rE]' \ +gitgrep "$cmdstart"'sed\b.*[[:space:]]-[^[:space:]]*[rE]' \ 'sed with -r or -E, drop and use POSIX BRE instead' -gitgrep $cmdstart'[ef]grep\b' \ +gitgrep "$cmdstart"'[ef]grep\b' \ '[ef]grep, use grep -[EF] instead (historical/deprecated)' # TODO: $ in sed subexpression used as an anchor (POSIX BRE optional, not in # Solaris/FreeBSD) -gitgrep '(?<!command)'$cmdstart'(grep|ls|sed)(\s|$)' \ - 'invoke grep, ls, and sed through "command", e.g. "command grep"' +gitgrep '(?<!command)'"$cmdstart"'(grep|ls|sed|cd)(\s|$)' \ + 'invoke grep, ls, sed, and cd through "command", e.g. "command grep"' + +gitgrep '(?<!command)'"$cmdstart"'awk(\s|$)' \ + 'invoke awk through "_comp_awk"' + +#------------------------------------------------------------------------------ +# Bash pitfalls/styles/compatibilities (which are not detected by shellcheck) gitgrep '<<<' 'herestrings use temp files, use some other way' filter_out='^(test/|bash_completion\.sh)' gitgrep ' \[ ' \ 'use [[ ]] instead of [ ]' + +gitgrep "$cmdstart"'unset [^-]' 'Explicitly specify "unset -v/-f"' + +gitgrep "$cmdstart"'((set|shopt)\s+[+-][a-z]+\s+posix\b|(local\s+)?POSIXLY_CORRECT\b)' \ + 'fiddling with posix mode breaks keybindings with some bash versions' + +gitgrep '\$\{([^{}\n]|\{.*\})+/([^{}\n]|\{.*\})+/([^{}"\n]|\{.*\})*\$.*\}' \ + '$rep of ${var/pat/$rep} needs to be double-quoted for shopt -s patsub_replacement (bash >= 5.2) [see Sec. of patsub_replacement in doc/styleguide.md]' + +gitgrep '"([^"\n]|\\.)*\$\{([^{}\n]|\{.*\})+/([^{}\n]|\{.*\})+/([^{}"\n]|\{.*\})*"([^{}"\n]|\{.*\})*\$.*\}' \ + '$rep of "${var/pat/"$rep"}" should not be quoted for bash-4.2 or shopt -s compat42 (bash >= 4.3) [see Sec. of patsub_replacement in doc/styleguide.md]' diff --git a/test/setup.cfg b/test/setup.cfg index 6abd7d3..a377a59 100644 --- a/test/setup.cfg +++ b/test/setup.cfg @@ -5,14 +5,7 @@ markers = complete [mypy] -python_version = 3.4 -ignore_missing_imports = true - -[isort] -known_first_party = conftest -known_third_party = pexpect,pytest -profile = black -line_length = 79 - -[flake8] -extend-ignore = D202,E203,E501 +python_version = 3.6 +mypy_path = $MYPY_CONFIG_FILE_DIR/t +show_error_codes = true +enable_error_code = ignore-without-code,redundant-self,truthy-iterable diff --git a/test/t/Makefile.am b/test/t/Makefile.am index 801841f..5a59969 100644 --- a/test/t/Makefile.am +++ b/test/t/Makefile.am @@ -21,6 +21,7 @@ EXTRA_DIST = \ test_apt_build.py \ test_apt_cache.py \ test_apt_get.py \ + test_apt_mark.py \ test_aptitude.py \ test_arch.py \ test_arp.py \ @@ -36,8 +37,10 @@ EXTRA_DIST = \ test_autoscan.py \ test_autossh.py \ test_autoupdate.py \ + test_avahi_browse.py \ test_avctrl.py \ test_awk.py \ + test_b2sum.py \ test_badblocks.py \ test_base64.py \ test_bash.py \ @@ -47,6 +50,7 @@ EXTRA_DIST = \ test_bk.py \ test_bmake.py \ test_brctl.py \ + test_bsdtar.py \ test_btdownloadcurses_py.py \ test_btdownloadgui_py.py \ test_btdownloadheadless_py.py \ @@ -214,13 +218,16 @@ EXTRA_DIST = \ test_growisofs.py \ test_grpck.py \ test_grub.py \ + test_gssdp_device_sniffer.py \ test_gssdp_discover.py \ test_gzip.py \ + test_hash.py \ test_hciattach.py \ test_hciconfig.py \ test_hcitool.py \ test_hddtemp.py \ test_head.py \ + test_help.py \ test_hexdump.py \ test_hid2hci.py \ test_host.py \ @@ -253,6 +260,7 @@ EXTRA_DIST = \ test_ip.py \ test_ipcalc.py \ test_iperf.py \ + test_iperf3.py \ test_ipmitool.py \ test_ipsec.py \ test_iptables.py \ @@ -395,6 +403,7 @@ EXTRA_DIST = \ test_mysqladmin.py \ test_nc.py \ test_ncftp.py \ + test_neomutt.py \ test_nethogs.py \ test_netstat.py \ test_newgrp.py \ @@ -413,7 +422,6 @@ EXTRA_DIST = \ test_objdump.py \ test_od.py \ test_oggdec.py \ - test_op.py \ test_openssl.py \ test_opera.py \ test_optipng.py \ @@ -422,6 +430,7 @@ EXTRA_DIST = \ test_passwd.py \ test_paste.py \ test_patch.py \ + test_pdftoppm.py \ test_pdftotext.py \ test_perl.py \ test_perlcritic.py \ @@ -439,6 +448,7 @@ EXTRA_DIST = \ test_pkg_get.py \ test_pkg_info.py \ test_pkgadd.py \ + test_pkgconf.py \ test_pkgrm.py \ test_pkgtool.py \ test_pkgutil.py \ @@ -461,6 +471,7 @@ EXTRA_DIST = \ test_prelink.py \ test_printenv.py \ test_protoc.py \ + test_ps.py \ test_psql.py \ test_ptx.py \ test_puppet.py \ @@ -483,11 +494,13 @@ EXTRA_DIST = \ test_pyflakes.py \ test_pylint.py \ test_pylint_3.py \ + test_pyston.py \ test_pytest.py \ test_python.py \ test_python3.py \ test_pyvenv.py \ test_qemu.py \ + test_qemu_system_x86_64.py \ test_qrunner.py \ test_querybts.py \ test_quota.py \ @@ -540,6 +553,10 @@ EXTRA_DIST = \ test_sftp.py \ test_sh.py \ test_sha1sum.py \ + test_sha224sum.py \ + test_sha256sum.py \ + test_sha384sum.py \ + test_sha512sum.py \ test_shar.py \ test_shellcheck.py \ test_sitecopy.py \ @@ -564,6 +581,7 @@ EXTRA_DIST = \ test_ssh_add.py \ test_ssh_copy_id.py \ test_ssh_keygen.py \ + test_ssh_keyscan.py \ test_sshfs.py \ test_sshmitm.py \ test_sshow.py \ @@ -600,6 +618,8 @@ EXTRA_DIST = \ test_tox.py \ test_tr.py \ test_tracepath.py \ + test_tree.py \ + test_truncate.py \ test_tshark.py \ test_tsig_keygen.py \ test_tune2fs.py \ @@ -663,6 +683,7 @@ EXTRA_DIST = \ test_wvdial.py \ test_xdg_mime.py \ test_xdg_settings.py \ + test_xev.py \ test_xfreerdp.py \ test_xgamma.py \ test_xhost.py \ @@ -691,8 +712,14 @@ all: PYTEST = @PYTEST@ -check-local: - $(PYTEST) $(PYTESTFLAGS) $(srcdir) +# Some tests require completions/ symlinks to be in place, which would be a +# chore to achieve in the build dir with VPATH builds (well not the symlinks, +# but the "main" files they target), e.g. "make distcheck". Therefore we test +# the installed tree instead, which isn't a bad idea in the first place. +installcheck-local: + ABS_TOP_BUILDDIR="$(abs_top_builddir)" \ + BASH_COMPLETION_TEST_BASH_COMPLETION="$(DESTDIR)/$(pkgdatadir)/bash_completion" \ + $(PYTEST) $(PYTESTFLAGS) $(srcdir) clean-local: $(RM) -R __pycache__ diff --git a/test/t/conftest.py b/test/t/conftest.py index 5c1603d..874ef1c 100644 --- a/test/t/conftest.py +++ b/test/t/conftest.py @@ -2,15 +2,32 @@ import difflib import os import re import shlex +import shutil import subprocess +import sys +import tempfile import time -from typing import Callable, Iterable, Iterator, List, Optional, Tuple - -import pexpect +from enum import Enum +from pathlib import Path +from types import TracebackType +from typing import ( + Callable, + Dict, + Iterable, + Iterator, + List, + Optional, + TextIO, + Tuple, + Type, +) + +import pexpect # type: ignore[import] import pytest PS1 = "/@" -MAGIC_MARK = "__MaGiC-maRKz!__" +MAGIC_MARK = "__MaGiC-maRKz-NEtXZVZfKC__" +MAGIC_MARK2 = "Re8SCgEdfN" def find_unique_completion_pair( @@ -115,8 +132,8 @@ def _avahi_hosts(bash: pexpect.spawn) -> List[str]: def known_hosts(bash: pexpect.spawn) -> List[str]: output = assert_bash_exec( bash, - '_known_hosts_real ""; ' - r'printf "%s\n" "${COMPREPLY[@]}"; unset COMPREPLY', + '_comp_compgen_known_hosts ""; ' + r'printf "%s\n" "${COMPREPLY[@]}"; unset -v COMPREPLY', want_output=True, ) return sorted(set(output.split())) @@ -127,7 +144,9 @@ def user_home(bash: pexpect.spawn) -> Tuple[str, str]: user = assert_bash_exec( bash, 'id -un 2>/dev/null || echo "$USER"', want_output=True ).strip() - home = assert_bash_exec(bash, 'echo "$HOME"', want_output=True).strip() + # We used to echo $HOME here, but we expect that it will be consistent with + # ~user as far as bash is concerned which may not hold. + home = assert_bash_exec(bash, "echo ~%s" % user, want_output=True).strip() return (user, home) @@ -167,107 +186,175 @@ def partialize( @pytest.fixture(scope="class") def bash(request) -> pexpect.spawn: + logfile: Optional[TextIO] = None + histfile = None + tmpdir = None + bash = None + + if os.environ.get("BASH_COMPLETION_TEST_LOGFILE"): + logfile = open(os.environ["BASH_COMPLETION_TEST_LOGFILE"], "w") + elif os.environ.get("CI"): + logfile = sys.stdout - logfile = None - if os.environ.get("BASHCOMP_TEST_LOGFILE"): - logfile = open(os.environ["BASHCOMP_TEST_LOGFILE"], "w") testdir = os.path.abspath( os.path.join(os.path.dirname(__file__), os.pardir) ) - env = os.environ.copy() - env.update( - dict( - SRCDIR=testdir, # TODO needed at least by bashrc - SRCDIRABS=testdir, # TODO needed? - PS1=PS1, - INPUTRC="%s/config/inputrc" % testdir, - TERM="dumb", - LC_COLLATE="C", # to match Python's default locale unaware sort - ) - ) - fixturesdir = os.path.join(testdir, "fixtures") - os.chdir(fixturesdir) - - # Start bash - bash = pexpect.spawn( - "%s --norc" % os.environ.get("BASHCOMP_TEST_BASH", "bash"), - maxread=os.environ.get("BASHCOMP_TEST_PEXPECT_MAXREAD", 20000), - logfile=logfile, - cwd=fixturesdir, - env=env, - encoding="utf-8", # TODO? or native or...? - # FIXME: Tests shouldn't depend on dimensions, but it's difficult to - # expect robustly enough for Bash to wrap lines anywhere (e.g. inside - # MAGIC_MARK). Increase window width to reduce wrapping. - dimensions=(24, 160), - # TODO? codec_errors="replace", + # Create an empty temporary file for HISTFILE. + # + # To prevent the tested Bash processes from writing to the user's + # history file or any other files, we prepare an empty temporary + # file for each test. + # + # - Note that HISTFILE=/dev/null may not work. It results in the + # removal of the device /dev/null and the creation of a regular + # file at /dev/null when the number of commands reach + # HISTFILESIZE due to a bug in bash 4.3. This causes execution of + # garbage through BASH_COMPLETION_USER_FILE=/dev/null. + # - Note also that "unset -v HISTFILE" in "test/config/bashrc" was not + # adopted because "test/config/bashrc" is loaded after the + # history is read from the history file. + # + histfile = tempfile.NamedTemporaryFile( + prefix="bash-completion-test_", delete=False ) - bash.expect_exact(PS1) - # Load bashrc and bash_completion - assert_bash_exec(bash, "source '%s/config/bashrc'" % testdir) - assert_bash_exec(bash, "source '%s/../bash_completion'" % testdir) - - # Use command name from marker if set, or grab from test filename - cmd = None # type: Optional[str] - cmd_found = False - marker = request.node.get_closest_marker("bashcomp") - if marker: - cmd = marker.kwargs.get("cmd") - cmd_found = "cmd" in marker.kwargs - # Run pre-test commands, early so they're usable in skipif - for pre_cmd in marker.kwargs.get("pre_cmds", []): - assert_bash_exec(bash, pre_cmd) - # Process skip and xfail conditions - skipif = marker.kwargs.get("skipif") - if skipif: - try: - assert_bash_exec(bash, skipif, want_output=None) - except AssertionError: - pass - else: - bash.close() - pytest.skip(skipif) - xfail = marker.kwargs.get("xfail") - if xfail: - try: - assert_bash_exec(bash, xfail, want_output=None) - except AssertionError: - pass - else: - pytest.xfail(xfail) - if not cmd_found: - match = re.search( - r"^test_(.+)\.py$", os.path.basename(str(request.fspath)) + try: + # release the file handle so that Bash can open the file. + histfile.close() + + env = os.environ.copy() + env.update( + dict( + SRCDIR=testdir, # TODO needed at least by bashrc + SRCDIRABS=testdir, + PS1=PS1, + INPUTRC="%s/config/inputrc" % testdir, + TERM="dumb", + LC_COLLATE="C", # to match Python's default locale unaware sort + HISTFILE=histfile.name, + ) + ) + + marker = request.node.get_closest_marker("bashcomp") + + # Set up the current working directory + cwd = None + if marker: + if "cwd" in marker.kwargs and marker.kwargs.get("cwd") is not None: + cwd = os.path.join( + testdir, "fixtures", marker.kwargs.get("cwd") + ) + elif "temp_cwd" in marker.kwargs and marker.kwargs.get("temp_cwd"): + tmpdir = tempfile.TemporaryDirectory( + prefix="bash-completion-test_" + ) + cwd = tmpdir.name + if cwd is None: + cwd = os.path.join(testdir, "fixtures") + os.chdir(cwd) + + # Start bash + bash = pexpect.spawn( + "%s --norc" % os.environ.get("BASH_COMPLETION_TEST_BASH", "bash"), + maxread=os.environ.get( + "BASH_COMPLETION_TEST_PEXPECT_MAXREAD", 20000 + ), + logfile=logfile, + cwd=cwd, + env=env, + encoding="utf-8", # TODO? or native or...? + # FIXME: Tests shouldn't depend on dimensions, but it's difficult to + # expect robustly enough for Bash to wrap lines anywhere (e.g. inside + # MAGIC_MARK). Increase window width to reduce wrapping. + dimensions=(24, 240), + # TODO? codec_errors="replace", ) - if match: - cmd = match.group(1) - - request.cls.cmd = cmd - - if (cmd_found and cmd is None) or is_testable(bash, cmd): - before_env = get_env(bash) - yield bash - # Not exactly sure why, but some errors leave bash in state where - # getting the env here would fail and trash our test output. So - # reset to a good state first (Ctrl+C, expect prompt). - bash.sendintr() bash.expect_exact(PS1) - diff_env( - before_env, - get_env(bash), - marker.kwargs.get("ignore_env") if marker else "", + + # Load bashrc and bash_completion + bash_completion = os.environ.get( + "BASH_COMPLETION_TEST_BASH_COMPLETION", + "%s/../bash_completion" % testdir, ) + assert_bash_exec(bash, "source '%s/config/bashrc'" % testdir) + assert_bash_exec(bash, "source '%s'" % bash_completion) + + # Use command name from marker if set, or grab from test filename + cmd = None # type: Optional[str] + cmd_found = False + if marker: + cmd = marker.kwargs.get("cmd") + cmd_found = "cmd" in marker.kwargs + # Run pre-test commands, early so they're usable in skipif + for pre_cmd in marker.kwargs.get("pre_cmds", []): + assert_bash_exec(bash, pre_cmd, want_output=None) + # Process skip and xfail conditions + skipif = marker.kwargs.get("skipif") + if skipif: + try: + assert_bash_exec(bash, skipif, want_output=None) + except AssertionError: + pass + else: + bash.close() + bash = None + pytest.skip(skipif) + xfail = marker.kwargs.get("xfail") + if xfail: + try: + assert_bash_exec(bash, xfail, want_output=None) + except AssertionError: + pass + else: + pytest.xfail(xfail) + if not cmd_found: + match = re.search( + r"^test_(.+)\.py$", os.path.basename(str(request.fspath)) + ) + if match: + cmd = match.group(1) + if ( + marker + and marker.kwargs + and marker.kwargs.get("require_cmd", False) + ): + if not is_bash_type(bash, cmd): + pytest.skip("Command not found") + + request.cls.cmd = cmd + + if (cmd_found and cmd is None) or is_testable(bash, cmd): + before_env = get_env(bash) + yield bash + # Not exactly sure why, but some errors leave bash in state where + # getting the env here would fail and trash our test output. So + # reset to a good state first (Ctrl+C, expect prompt). + bash.sendintr() + bash.expect_exact(PS1) + diff_env( + before_env, + get_env(bash), + marker.kwargs.get("ignore_env") if marker else "", + ) - if marker: - for post_cmd in marker.kwargs.get("post_cmds", []): - assert_bash_exec(bash, post_cmd) + if marker: + for post_cmd in marker.kwargs.get("post_cmds", []): + assert_bash_exec(bash, post_cmd, want_output=None) - # Clean up - bash.close() - if logfile: - logfile.close() + finally: + # Clean up + if bash: + bash.close() + if tmpdir: + tmpdir.cleanup() + if histfile: + try: + os.remove(histfile.name) + except OSError: + pass + if logfile and logfile != sys.stdout: + logfile.close() def is_testable(bash: pexpect.spawn, cmd: Optional[str]) -> bool: @@ -292,9 +379,9 @@ def is_bash_type(bash: pexpect.spawn, cmd: Optional[str]) -> bool: def load_completion_for(bash: pexpect.spawn, cmd: str) -> bool: try: - # Allow __load_completion to fail so we can test completions + # Allow _comp_load to fail so we can test completions # that are directly loaded in bash_completion without a separate file. - assert_bash_exec(bash, "__load_completion %s || :" % cmd) + assert_bash_exec(bash, "_comp_load %s || :" % cmd) assert_bash_exec(bash, "complete -p %s &>/dev/null" % cmd) except AssertionError: return False @@ -341,27 +428,301 @@ def assert_bash_exec( if output: assert want_output, ( 'Unexpected output from "%s": exit status=%s, output="%s"' - % (cmd, status, output) + % ( + cmd, + status, + output, + ) ) else: assert not want_output, ( 'Expected output from "%s": exit status=%s, output="%s"' - % (cmd, status, output) + % ( + cmd, + status, + output, + ) ) return output +class bash_env_saved: + counter: int = 0 + + class saved_state(Enum): + ChangesDetected = 1 + ChangesIgnored = 2 + + def __init__(self, bash: pexpect.spawn, sendintr: bool = False): + bash_env_saved.counter += 1 + self.prefix: str = "_comp__test_%d" % bash_env_saved.counter + + self.bash = bash + self.cwd_changed: bool = False + self.saved_set: Dict[str, bash_env_saved.saved_state] = {} + self.saved_shopt: Dict[str, bash_env_saved.saved_state] = {} + self.saved_variables: Dict[str, bash_env_saved.saved_state] = {} + self.sendintr = sendintr + + self.noexcept: bool = False + self.captured_error: Optional[Exception] = None + + def __enter__(self): + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_value: Optional[BaseException], + exc_traceback: Optional[TracebackType], + ) -> None: + self._restore_env() + return None + + def _safe_sendintr(self): + try: + self.bash.sendintr() + self.bash.expect_exact(PS1) + except Exception as e: + if self.noexcept: + self.captured_error = e + else: + raise + + def _safe_exec(self, cmd: str): + try: + self.bash.sendline(cmd) + self.bash.expect_exact(cmd) + self.bash.expect_exact("\r\n" + PS1) + except Exception as e: + if self.noexcept: + self._safe_sendintr() + self.captured_error = e + else: + raise + + def _safe_assert(self, cmd: str): + try: + assert_bash_exec(self.bash, cmd, want_output=None) + except Exception as e: + if self.noexcept: + self._safe_sendintr() + self.captured_error = e + else: + raise + + def _copy_variable(self, src_var: str, dst_var: str): + self._safe_exec( + "if [[ ${%s+set} ]]; then %s=${%s}; else unset -v %s; fi" + % (src_var, dst_var, src_var, dst_var), + ) + + def _unset_variable(self, varname: str): + self._safe_exec("unset -v %s" % varname) + + def _save_cwd(self): + if not self.cwd_changed: + self.cwd_changed = True + self._copy_variable("PWD", "%s_OLDPWD" % self.prefix) + + def _check_set(self, name: str): + if self.saved_set[name] != bash_env_saved.saved_state.ChangesDetected: + return + self._safe_assert( + '[[ $(shopt -po %s) == "${%s_NEWSHOPT_%s}" ]]' + % (name, self.prefix, name), + ) + + def _unprotect_set(self, name: str): + if name not in self.saved_set: + self.saved_set[name] = bash_env_saved.saved_state.ChangesDetected + self._safe_exec( + "%s_OLDSHOPT_%s=$(shopt -po %s || true)" + % (self.prefix, name, name), + ) + else: + self._check_set(name) + + def _protect_set(self, name: str): + self._safe_exec( + "%s_NEWSHOPT_%s=$(shopt -po %s || true)" + % (self.prefix, name, name), + ) + + def _check_shopt(self, name: str): + if ( + self.saved_shopt[name] + != bash_env_saved.saved_state.ChangesDetected + ): + return + self._safe_assert( + '[[ $(shopt -p %s) == "${%s_NEWSHOPT_%s}" ]]' + % (name, self.prefix, name), + ) + + def _unprotect_shopt(self, name: str): + if name not in self.saved_shopt: + self.saved_shopt[name] = bash_env_saved.saved_state.ChangesDetected + self._safe_exec( + "%s_OLDSHOPT_%s=$(shopt -p %s || true)" + % (self.prefix, name, name), + ) + else: + self._check_shopt(name) + + def _protect_shopt(self, name: str): + self._safe_exec( + "%s_NEWSHOPT_%s=$(shopt -p %s || true)" + % (self.prefix, name, name), + ) + + def _check_variable(self, varname: str): + if ( + self.saved_variables[varname] + != bash_env_saved.saved_state.ChangesDetected + ): + return + try: + self._safe_assert( + '[[ ${%s-%s} == "${%s_NEWVAR_%s-%s}" ]]' + % (varname, MAGIC_MARK2, self.prefix, varname, MAGIC_MARK2), + ) + except Exception: + self._copy_variable( + "%s_NEWVAR_%s" % (self.prefix, varname), varname + ) + raise + else: + if self.noexcept and self.captured_error: + self._copy_variable( + "%s_NEWVAR_%s" % (self.prefix, varname), varname + ) + + def _unprotect_variable(self, varname: str): + if varname not in self.saved_variables: + self.saved_variables[ + varname + ] = bash_env_saved.saved_state.ChangesDetected + self._copy_variable( + varname, "%s_OLDVAR_%s" % (self.prefix, varname) + ) + else: + self._check_variable(varname) + + def _protect_variable(self, varname: str): + self._copy_variable(varname, "%s_NEWVAR_%s" % (self.prefix, varname)) + + def _restore_env(self): + self.noexcept = True + + if self.sendintr: + self._safe_sendintr() + + # We first go back to the original directory before restoring + # variables because "cd" affects "OLDPWD". + if self.cwd_changed: + self._unprotect_variable("OLDPWD") + self._safe_exec('command cd -- "$%s_OLDPWD"' % self.prefix) + self._protect_variable("OLDPWD") + self._unset_variable("%s_OLDPWD" % self.prefix) + self.cwd_changed = False + + for varname in self.saved_variables: + self._check_variable(varname) + self._copy_variable( + "%s_OLDVAR_%s" % (self.prefix, varname), varname + ) + self._unset_variable("%s_OLDVAR_%s" % (self.prefix, varname)) + self._unset_variable("%s_NEWVAR_%s" % (self.prefix, varname)) + self.saved_variables = {} + + for name in self.saved_shopt: + self._check_shopt(name) + self._safe_exec('eval "$%s_OLDSHOPT_%s"' % (self.prefix, name)) + self._unset_variable("%s_OLDSHOPT_%s" % (self.prefix, name)) + self._unset_variable("%s_NEWSHOPT_%s" % (self.prefix, name)) + self.saved_shopt = {} + + for name in self.saved_set: + self._check_set(name) + self._safe_exec('eval "$%s_OLDSHOPT_%s"' % (self.prefix, name)) + self._unset_variable("%s_OLDSHOPT_%s" % (self.prefix, name)) + self._unset_variable("%s_NEWSHOPT_%s" % (self.prefix, name)) + self.saved_set = {} + + self.noexcept = False + if self.captured_error: + raise self.captured_error + + def chdir(self, path: str): + self._save_cwd() + self.cwd_changed = True + self._unprotect_variable("OLDPWD") + self._safe_exec("command cd -- %s" % shlex.quote(path)) + self._protect_variable("OLDPWD") + + def set(self, name: str, value: bool): + self._unprotect_set(name) + if value: + self._safe_exec("set -u %s" % name) + else: + self._safe_exec("set +o %s" % name) + self._protect_set(name) + + def save_set(self, name: str): + self._unprotect_set(name) + self.saved_set[name] = bash_env_saved.saved_state.ChangesIgnored + + def shopt(self, name: str, value: bool): + self._unprotect_shopt(name) + if value: + self._safe_exec("shopt -s %s" % name) + else: + self._safe_exec("shopt -u %s" % name) + self._protect_shopt(name) + + def save_shopt(self, name: str): + self._unprotect_shopt(name) + self.saved_shopt[name] = bash_env_saved.saved_state.ChangesIgnored + + def write_variable(self, varname: str, new_value: str, quote: bool = True): + if quote: + new_value = shlex.quote(new_value) + self._unprotect_variable(varname) + self._safe_exec("%s=%s" % (varname, new_value)) + self._protect_variable(varname) + + def save_variable(self, varname: str): + self._unprotect_variable(varname) + self.saved_variables[ + varname + ] = bash_env_saved.saved_state.ChangesIgnored + + # TODO: We may restore the "export" attribute as well though it is + # not currently tested in "diff_env" + def write_env(self, envname: str, new_value: str, quote: bool = True): + if quote: + new_value = shlex.quote(new_value) + self._unprotect_variable(envname) + self._safe_exec("export %s=%s" % (envname, new_value)) + self._protect_variable(envname) + + def get_env(bash: pexpect.spawn) -> List[str]: - return ( - assert_bash_exec( + return [ + x + for x in assert_bash_exec( bash, - "{ (set -o posix ; set); declare -F; shopt -p; set -o; }", + "_comp__test_get_env", want_output=True, ) .strip() .splitlines() - ) + # Sometimes there are empty lines in the output due to unknown + # reasons, e.g. in GitHub Actions' macos-latest OS. Filter them out. + if x + ] def diff_env(before: List[str], after: List[str], ignore: str): @@ -371,7 +732,11 @@ def diff_env(before: List[str], after: List[str], ignore: str): # Remove unified diff markers: if not re.search(r"^(---|\+\+\+|@@ )", x) # Ignore variables expected to change: - and not re.search("^[-+](_|PPID|BASH_REMATCH|OLDPWD)=", x) + and not re.search( + r"^[-+](_|PPID|BASH_REMATCH|(BASH_)?LINENO)=", + x, + re.ASCII, + ) # Ignore likely completion functions added by us: and not re.search(r"^\+declare -f _.+", x) # ...and additional specified things: @@ -455,73 +820,72 @@ def assert_complete( pass else: pytest.xfail(xfail) - cwd = kwargs.get("cwd") - if cwd: - assert_bash_exec(bash, "cd '%s'" % cwd) - env_prefix = "_BASHCOMP_TEST_" - env = kwargs.get("env", {}) - if env: - # Back up environment and apply new one - assert_bash_exec( - bash, - " ".join('%s%s="${%s-}"' % (env_prefix, k, k) for k in env.keys()), - ) - assert_bash_exec( - bash, - "export %s" % " ".join("%s=%s" % (k, v) for k, v in env.items()), - ) - try: - bash.send(cmd + "\t") + + with bash_env_saved(bash, sendintr=True) as bash_env: + cwd = kwargs.get("cwd") + if cwd: + bash_env.chdir(str(cwd)) + + for k, v in kwargs.get("env", {}).items(): + bash_env.write_env(k, v, quote=False) + + for k, v in kwargs.get("shopt", {}).items(): + bash_env.shopt(k, v) + + input_cmd = cmd + rendered_cmd = kwargs.get("rendered_cmd", cmd) + re_MAGIC_MARK = re.escape(MAGIC_MARK) + + trail = kwargs.get("trail") + if trail: + # \002 = ^B = cursor left + input_cmd += trail + "\002" * len(trail) + rendered_cmd += trail + "\b" * len(trail) + + # After reading the results, something weird happens. For most test + # setups, as expected (pun intended!), MAGIC_MARK follows as + # is. But for some others (e.g. CentOS 6, Ubuntu 14 test + # containers), we get MAGIC_MARK one character a time, followed + # each time by trail and the corresponding number of \b's. Don't + # know why, but accept it until/if someone finds out. Or just be + # fine with it indefinitely, the visible and practical end result + # on a terminal is the same anyway. + maybe_trail = "(%s%s)?" % (re.escape(trail), "\b" * len(trail)) + re_MAGIC_MARK = "".join( + re.escape(x) + maybe_trail for x in MAGIC_MARK + ) + + bash.send(input_cmd + "\t") # Sleep a bit if requested, to avoid `.*` matching too early time.sleep(kwargs.get("sleep_after_tab", 0)) - bash.expect_exact(cmd) + bash.expect_exact(rendered_cmd) bash.send(MAGIC_MARK) got = bash.expect( [ # 0: multiple lines, result in .before - r"\r\n" + re.escape(PS1 + cmd) + ".*" + re.escape(MAGIC_MARK), + r"\r\n" + re.escape(PS1 + rendered_cmd) + ".*" + re_MAGIC_MARK, # 1: no completion - r"^" + re.escape(MAGIC_MARK), + r"^" + re_MAGIC_MARK, # 2: on same line, result in .match - r"^([^\r]+)%s$" % re.escape(MAGIC_MARK), + r"^([^\r]+)%s$" % re_MAGIC_MARK, + # 3: error messages + r"^([^\r].*)%s$" % re_MAGIC_MARK, pexpect.EOF, pexpect.TIMEOUT, ] ) if got == 0: - output = bash.before - if output.endswith(MAGIC_MARK): - output = bash.before[: -len(MAGIC_MARK)] - result = CompletionResult(output) + output = re.sub(re_MAGIC_MARK + "$", "", bash.before) + return CompletionResult(output) elif got == 2: output = bash.match.group(1) - result = CompletionResult(output) + return CompletionResult(output) + elif got == 3: + output = bash.match.group(1) + raise AssertionError("Unexpected output: [%s]" % output) else: # TODO: warn about EOF/TIMEOUT? - result = CompletionResult() - finally: - bash.sendintr() - bash.expect_exact(PS1) - if env: - # Restore environment, and clean up backup - # TODO: Test with declare -p if a var was set, backup only if yes, and - # similarly restore only backed up vars. Should remove some need - # for ignore_env. - assert_bash_exec( - bash, - "export %s" - % " ".join( - '%s="$%s%s"' % (k, env_prefix, k) for k in env.keys() - ), - ) - assert_bash_exec( - bash, - "unset -v %s" - % " ".join("%s%s" % (env_prefix, k) for k in env.keys()), - ) - if cwd: - assert_bash_exec(bash, "cd - >/dev/null") - return result + return CompletionResult() @pytest.fixture @@ -530,7 +894,7 @@ def completion(request, bash: pexpect.spawn) -> CompletionResult: if not marker: return CompletionResult() for pre_cmd in marker.kwargs.get("pre_cmds", []): - assert_bash_exec(bash, pre_cmd) + assert_bash_exec(bash, pre_cmd, want_output=None) cmd = getattr(request.cls, "cmd", None) if marker.kwargs.get("require_longopt"): # longopt completions require both command presence and that it @@ -539,66 +903,18 @@ def completion(request, bash: pexpect.spawn) -> CompletionResult: marker.kwargs["require_cmd"] = True if "xfail" not in marker.kwargs: marker.kwargs["xfail"] = ( + # --help is required to exit with zero in order to not get a + # positive for cases where it errors out with a message like + # "foo: unrecognized option '--help'" "! %s --help &>/dev/null || " "! %s --help 2>&1 | command grep -qF -- --help" ) % ((cmd,) * 2) if marker.kwargs.get("require_cmd") and not is_bash_type(bash, cmd): pytest.skip("Command not found") - if "trail" in marker.kwargs: - return assert_complete_at_point( - bash, cmd=marker.args[0], trail=marker.kwargs["trail"] - ) - return assert_complete(bash, marker.args[0], **marker.kwargs) -def assert_complete_at_point( - bash: pexpect.spawn, cmd: str, trail: str -) -> CompletionResult: - # TODO: merge to assert_complete - fullcmd = "%s%s%s" % ( - cmd, - trail, - "\002" * len(trail), - ) # \002 = ^B = cursor left - bash.send(fullcmd + "\t") - bash.send(MAGIC_MARK) - bash.expect_exact(fullcmd.replace("\002", "\b")) - - got = bash.expect_exact( - [ - # 0: multiple lines, result in .before - PS1 + fullcmd.replace("\002", "\b"), - # 1: no completion - MAGIC_MARK, - pexpect.EOF, - pexpect.TIMEOUT, - ] - ) - if got == 0: - output = bash.before - result = CompletionResult(output) - - # At this point, something weird happens. For most test setups, as - # expected (pun intended!), MAGIC_MARK follows as is. But for some - # others (e.g. CentOS 6, Ubuntu 14 test containers), we get MAGIC_MARK - # one character a time, followed each time by trail and the corresponding - # number of \b's. Don't know why, but accept it until/if someone finds out. - # Or just be fine with it indefinitely, the visible and practical end - # result on a terminal is the same anyway. - repeat = "(%s%s)?" % (re.escape(trail), "\b" * len(trail)) - fullexpected = "".join( - "%s%s" % (re.escape(x), repeat) for x in MAGIC_MARK - ) - bash.expect(fullexpected) - else: - # TODO: warn about EOF/TIMEOUT? - result = CompletionResult() - - return result - - def in_container() -> bool: try: container = subprocess.check_output( @@ -624,6 +940,56 @@ def in_container() -> bool: return False +def prepare_fixture_dir( + request, files: Iterable[str], dirs: Iterable[str] +) -> Tuple[Path, List[str], List[str]]: + """ + Fixture to prepare a test dir with dummy contents on the fly. + + Tests that contain filenames differing only by case should use this to + prepare a dir on the fly rather than including their fixtures in git and + the tarball. This is to work better with case insensitive file systems. + """ + tempdir = Path(tempfile.mkdtemp(prefix="bash-completion-fixture-dir")) + request.addfinalizer(lambda: shutil.rmtree(str(tempdir))) + + old_cwd = os.getcwd() + try: + os.chdir(tempdir) + new_files, new_dirs = create_dummy_filedirs(files, dirs) + finally: + os.chdir(old_cwd) + + return tempdir, new_files, new_dirs + + +def create_dummy_filedirs( + files: Iterable[str], dirs: Iterable[str] +) -> Tuple[List[str], List[str]]: + """ + Create dummy files and directories on the fly in the current directory. + + Tests that contain filenames differing only by case should use this to + prepare a dir on the fly rather than including their fixtures in git and + the tarball. This is to work better with case insensitive file systems. + """ + new_files = [] + new_dirs = [] + + for dir_ in dirs: + path = Path(dir_) + if not path.exists(): + path.mkdir() + new_dirs.append(dir_) + for file_ in files: + path = Path(file_) + if not path.exists(): + path.touch() + new_files.append(file_) + + return sorted(new_files), sorted(new_dirs) + + class TestUnitBase: def _test_unit( self, func, bash, comp_words, comp_cword, comp_line, comp_point, arg="" diff --git a/test/t/test_2to3.py b/test/t/test_2to3.py index 4bce44e..1fc14e7 100644 --- a/test/t/test_2to3.py +++ b/test/t/test_2to3.py @@ -6,6 +6,6 @@ class Test2to3: def test_1(self, completion): assert completion - @pytest.mark.complete("2to3 -", require_cmd=True, require_longopt=True) + @pytest.mark.complete("2to3 -", require_longopt=True) def test_2(self, completion): assert completion diff --git a/test/t/test_7z.py b/test/t/test_7z.py index d4308d9..67681a5 100644 --- a/test/t/test_7z.py +++ b/test/t/test_7z.py @@ -17,7 +17,7 @@ class Test7z: @pytest.mark.complete("7z x ", cwd="7z") def test_4(self, completion): - assert completion == "a.7z" + assert completion == "a.7z hello.7z.001".split() @pytest.mark.complete("7z d a.7z ", cwd="7z", require_cmd=True) def test_5(self, completion): @@ -25,7 +25,9 @@ class Test7z: @pytest.mark.complete("7z a -air@", cwd="7z") def test_6(self, completion): - assert completion == sorted("-air@a.7z -air@f.txt".split()) + assert completion == sorted( + "-air@a.7z -air@hello.7z.001 -air@hello.7z.002 -air@f.txt".split() + ) @pytest.mark.complete("7z a -o") def test_7(self, completion): diff --git a/test/t/test_alias.py b/test/t/test_alias.py index cc592a8..0a9eb3b 100644 --- a/test/t/test_alias.py +++ b/test/t/test_alias.py @@ -19,3 +19,11 @@ class TestAlias: @pytest.mark.complete("alias ", trail="foo") def test_alias_at_point(self, completion): assert completion == "bar foo".split() + + @pytest.mark.complete("alias -") + def test_options(self, completion): + assert completion + + @pytest.mark.complete("alias -p ") + def test_p(self, completion): + assert not completion diff --git a/test/t/test_ant.py b/test/t/test_ant.py index 94acea1..de4c414 100644 --- a/test/t/test_ant.py +++ b/test/t/test_ant.py @@ -3,28 +3,43 @@ import pytest from conftest import assert_bash_exec -@pytest.mark.bashcomp(ignore_env=r"^\+ANT_ARGS=") +@pytest.mark.bashcomp( + ignore_env=r"^\+ANT_ARGS=", + temp_cwd=True, + pre_cmds=('cp "$SRCDIRABS"/fixtures/ant/*.xml .',), +) class TestAnt: + @pytest.fixture(scope="class") + def has_complete_ant_cmd_pl(self, bash): + output = assert_bash_exec(bash, "complete -p ant", want_output=True) + return "complete-ant-cmd.pl" in output + @pytest.mark.complete("ant -", require_cmd=True) def test_1(self, completion): assert completion - @pytest.mark.complete("ant ", cwd="ant") + @pytest.mark.complete("ant ") def test_2(self, completion): assert completion == "bashcomp clean init realclean".split() - @pytest.mark.complete("ant -f build-with-import.xml ", cwd="ant") - def test_3(self, completion): - assert completion == "build-with-import imported-build".split() + @pytest.mark.complete("ant -f build-with-import.xml ") + def test_3(self, completion, has_complete_ant_cmd_pl): + if has_complete_ant_cmd_pl: + # Some versions of complete-ant-cmd.pl add "import-project-name." + # prefix to imported targets, just check that the ones we add + # are there. + assert all( + x in completion + for x in "build-with-import imported-build".split() + ) + else: + assert completion == "build-with-import imported-build".split() - @pytest.mark.complete( - "ant ", cwd="ant", env=dict(ANT_ARGS="'-f named-build.xml'") - ) - def test_4(self, bash, completion): - output = assert_bash_exec(bash, "complete -p ant", want_output=True) - if "complete-ant-cmd.pl" in output: + @pytest.mark.complete("ant ", env=dict(ANT_ARGS="'-f named-build.xml'")) + def test_4(self, bash, completion, has_complete_ant_cmd_pl): + if has_complete_ant_cmd_pl: # Some versions of complete-ant-cmd.pl don't treat ANT_ARGS right; - # in those cases we get the correct completion produced by _ant + # in those cases we get the correct completion produced by us # plus whatever complete-ant-cmd.pl was able to get from build.xml assert "named-build" in completion else: diff --git a/test/t/test_apt_mark.py b/test/t/test_apt_mark.py new file mode 100644 index 0000000..541dbe5 --- /dev/null +++ b/test/t/test_apt_mark.py @@ -0,0 +1,39 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="apt-mark") +class TestAptMark: + @pytest.mark.complete("apt-mark ") + def test_1(self, completion): + assert all( + x in completion + for x in ( + "auto manual remove showinstall showremove " + "hold minimize-manual showauto showmanual unhold install " + "purge showhold showpurge" + ).split() + ) + + @pytest.mark.complete("apt-mark minimize-manual ") + def test_2(self, completion): + assert not completion + + @pytest.mark.complete("apt-mark --file=", cwd="dpkg") + def test_3(self, completion): + assert ( + completion + == "bash-completion-test-nonsubject.txt bash-completion-test-subject.deb".split() + ) + + @pytest.mark.complete("apt-mark --config-file ", cwd="apt-mark") + def test_4(self, completion): + assert completion == "example.conf" + + @pytest.mark.complete("apt-mark --option ") + def test_5(self, completion): + assert not completion + + @pytest.mark.complete("apt-mark --dont-fail-in-unset-mode") + def test_unknown_option(self, completion): + # Just see that it does not error out + pass diff --git a/test/t/test_arp.py b/test/t/test_arp.py index cd038bd..f8a9543 100644 --- a/test/t/test_arp.py +++ b/test/t/test_arp.py @@ -3,7 +3,7 @@ import pytest class TestArp: @pytest.mark.complete( - "arp ", require_cmd=True, skipif='test -z "$(arp 2>/dev/null)"' + "arp ", require_cmd=True, skipif='test ! "$(arp 2>/dev/null)"' ) def test_1(self, completion): assert completion diff --git a/test/t/test_arpspoof.py b/test/t/test_arpspoof.py index 74c09a4..c02f5c4 100644 --- a/test/t/test_arpspoof.py +++ b/test/t/test_arpspoof.py @@ -5,8 +5,13 @@ class TestArpspoof: @pytest.mark.complete( "arpspoof -", require_cmd=True, - # May require privileges even for outputting the usage message - skipif="arpspoof 2>&1 | command grep -qF libnet_open_link", + # May require privileges or network interfaces available even for + # outputting the usage message. Unfortunately --help provokes a + # non-zero exit status so we cannot test for that. + skipif=( + "arpspoof 2>&1 | " + "command grep -qE 'libnet_(open_link|select_device)'" + ), ) def test_1(self, completion): assert completion diff --git a/test/t/test_avahi_browse.py b/test/t/test_avahi_browse.py new file mode 100644 index 0000000..2c3cf0d --- /dev/null +++ b/test/t/test_avahi_browse.py @@ -0,0 +1,27 @@ +import pytest + + +@pytest.mark.bashcomp( + cmd="avahi-browse", +) +class TestAvahiBrowse: + @pytest.mark.complete("avahi-browse --", require_cmd=True) + def test_options(self, completion): + assert completion + + @pytest.mark.complete( + "avahi-browse _", + require_cmd=True, + xfail='test ! "$(avahi-browse --dump-db 2>/dev/null)"', + ) + def test_service_types(self, completion): + assert completion + + @pytest.mark.complete("avahi-browse -a _") + def test_no_service_type_with_a(self, completion): + assert not completion + + @pytest.mark.complete("avahi-browse --dont-fail-in-unset-mode") + def test_unknown_option(self, completion): + # Just see that it does not error out + pass diff --git a/test/t/test_b2sum.py b/test/t/test_b2sum.py new file mode 100644 index 0000000..b184457 --- /dev/null +++ b/test/t/test_b2sum.py @@ -0,0 +1,11 @@ +import pytest + + +class TestB2sum: + @pytest.mark.complete("b2sum ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("b2sum --", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_bsdtar.py b/test/t/test_bsdtar.py new file mode 100644 index 0000000..ec3acd1 --- /dev/null +++ b/test/t/test_bsdtar.py @@ -0,0 +1,11 @@ +import pytest + + +class TestBsdtar: + @pytest.mark.complete("bsdtar xf bsdtar/") + def test_readable_archives(self, completion): + assert completion == "test.pax test.rar".split() + + @pytest.mark.complete("bsdtar uf bsdtar/") + def test_writable_archives(self, completion): + assert completion == "test.pax test.shar".split() diff --git a/test/t/test_cd.py b/test/t/test_cd.py index 5b7789a..7243b93 100644 --- a/test/t/test_cd.py +++ b/test/t/test_cd.py @@ -7,11 +7,11 @@ class TestCd: def test_1(self, completion): assert completion == ["bar bar.d/", "foo.d/"] - @pytest.mark.complete("cd fo", env=dict(CDPATH="shared/default")) + @pytest.mark.complete("cd foo", env=dict(CDPATH="shared/default")) def test_2(self, completion): - assert completion == "o.d/" + assert completion == ".d/" - @pytest.mark.complete("cd fo") + @pytest.mark.complete("cd foo") def test_3(self, completion): assert not completion @@ -24,3 +24,7 @@ class TestCd: @pytest.mark.complete("cd shared/default/", trail="foo") def test_dir_at_point(self, completion): assert completion == ["bar bar.d/", "foo.d/"] + + @pytest.mark.complete("cd -") + def test_options(self, completion): + assert completion diff --git a/test/t/test_chmod.py b/test/t/test_chmod.py index 3838b55..e1a7119 100644 --- a/test/t/test_chmod.py +++ b/test/t/test_chmod.py @@ -2,7 +2,6 @@ import pytest class TestChmod: - # No completion here until mode completion is implemented @pytest.mark.complete("chmod ") def test_1(self, completion): diff --git a/test/t/test_chown.py b/test/t/test_chown.py index 9643f3e..ee81346 100644 --- a/test/t/test_chown.py +++ b/test/t/test_chown.py @@ -8,7 +8,7 @@ from conftest import assert_complete @pytest.mark.bashcomp( pre_cmds=( # Fake root command to get all users/groups completed at least for now - "root_command=sudo", + "_comp_root_command=sudo", ) ) class TestChown: diff --git a/test/t/test_chsh.py b/test/t/test_chsh.py index fe1c7f6..c2d8344 100644 --- a/test/t/test_chsh.py +++ b/test/t/test_chsh.py @@ -1,3 +1,5 @@ +import os + import pytest @@ -7,9 +9,16 @@ class TestChsh: assert completion @pytest.mark.complete("chsh -s ") - def test_2(self, completion): - assert completion + def test_shells(self, completion): + if os.path.exists("/etc/shells"): + assert completion + else: + assert not completion @pytest.mark.complete("chsh -", require_cmd=True) def test_3(self, completion): assert completion + + @pytest.mark.complete("chsh --root shells -s ") + def test_chroot_shells(self, completion): + assert completion == "/bash/completion/canary" diff --git a/test/t/test_configure.py b/test/t/test_configure.py index 0fc6117..c3b3393 100644 --- a/test/t/test_configure.py +++ b/test/t/test_configure.py @@ -15,3 +15,11 @@ class TestConfigure: @pytest.mark.complete("configure --prefix ") def test_2(self, completion): assert completion + + @pytest.mark.complete("configure --unknown-option-with-split=") + def test_unknown_split_filedir_fallback(self, completion): + assert "shared/" in completion + + @pytest.mark.complete("configure --unknown-option ") + def test_unknown_filedir_fallback(self, completion): + assert "shared/" in completion diff --git a/test/t/test_convert.py b/test/t/test_convert.py index c903ea0..b355c7a 100644 --- a/test/t/test_convert.py +++ b/test/t/test_convert.py @@ -6,7 +6,7 @@ class TestConvert: def test_1(self, completion): assert completion - @pytest.mark.complete("convert -format ") + @pytest.mark.complete("convert -format ", require_cmd=True) def test_2(self, completion): assert completion diff --git a/test/t/test_cpan2dist.py b/test/t/test_cpan2dist.py index 1ab5de1..ff64dbd 100644 --- a/test/t/test_cpan2dist.py +++ b/test/t/test_cpan2dist.py @@ -2,8 +2,6 @@ import pytest class TestCpan2dist: - @pytest.mark.complete( - "cpan2dist -", require_cmd=True, require_longopt=True - ) + @pytest.mark.complete("cpan2dist -", require_longopt=True) def test_1(self, completion): assert completion diff --git a/test/t/test_createdb.py b/test/t/test_createdb.py index 030338a..6ac255a 100644 --- a/test/t/test_createdb.py +++ b/test/t/test_createdb.py @@ -2,7 +2,6 @@ import pytest class TestCreatedb: - # --help can fail due to missing package dependencies, e.g. on Ubuntu 14 @pytest.mark.complete( "createdb -", require_cmd=True, xfail="! createdb --help &>/dev/null" diff --git a/test/t/test_createuser.py b/test/t/test_createuser.py index ea8d0e3..f3b1c67 100644 --- a/test/t/test_createuser.py +++ b/test/t/test_createuser.py @@ -2,7 +2,6 @@ import pytest class TestCreateuser: - # --help can fail due to missing package dependencies, e.g. on Ubuntu 14 @pytest.mark.complete( "createuser -", xfail="! createuser --help &>/dev/null" diff --git a/test/t/test_csplit.py b/test/t/test_csplit.py index 609c7e5..f1ead89 100644 --- a/test/t/test_csplit.py +++ b/test/t/test_csplit.py @@ -6,6 +6,6 @@ class TestCsplit: def test_1(self, completion): assert completion - @pytest.mark.complete("csplit -", require_cmd=True) + @pytest.mark.complete("csplit -", require_longopt=True) def test_options(self, completion): assert completion diff --git a/test/t/test_curl.py b/test/t/test_curl.py index 63e969f..07050e9 100644 --- a/test/t/test_curl.py +++ b/test/t/test_curl.py @@ -26,3 +26,20 @@ class TestCurl: def test_data_atfile_dir(self, completion): assert completion == "d/" assert not completion.endswith(" ") + + @pytest.mark.complete("curl --dont-fail-in-unset-mode") + def test_unknown_option(self, completion): + # Just see that it does not error out + pass + + @pytest.mark.complete("curl --data-bina", require_cmd=True) + def test_help_all_option(self, completion): + """ + The option used as a canary here is one that should be available + in all curl versions. It should be only listed in `--help all` output + for curl versions that have their help output split to multiple + categories (i.e. ones that support `--help all` to get the complete + list), as well as the basic `--help` output for earlier versions that + do not have that. + """ + assert completion diff --git a/test/t/test_cvs.py b/test/t/test_cvs.py index 97361e9..6d2deb3 100644 --- a/test/t/test_cvs.py +++ b/test/t/test_cvs.py @@ -18,3 +18,23 @@ class TestCvs: @pytest.mark.complete("cvs -", require_cmd=True) def test_4(self, completion): assert completion + + @pytest.mark.complete("cvs update -AdP foo/", cwd="cvs") + def test_5(self, completion): + assert completion == "bar" + + @pytest.mark.complete("cvs log -v foo/", cwd="cvs") + def test_6(self, completion): + assert completion == "bar" + + @pytest.mark.complete("cvs diff foo/", cwd="cvs") + def test_7(self, completion): + assert completion == "bar" + + @pytest.mark.complete("cvs status -v foo/", cwd="cvs") + def test_8(self, completion): + assert completion == "bar" + + @pytest.mark.complete("cvs status foo/", cwd="cvs") + def test_9(self, completion): + assert completion == "bar" diff --git a/test/t/test_cvsps.py b/test/t/test_cvsps.py index 4039893..2095832 100644 --- a/test/t/test_cvsps.py +++ b/test/t/test_cvsps.py @@ -1,7 +1,10 @@ import pytest -@pytest.mark.bashcomp(pre_cmds=("HOME=$PWD/cvs",)) +@pytest.mark.bashcomp( + pre_cmds=("HOME=$PWD/cvs",), + ignore_env=r"^[+-]COMP_CVS_REMOTE=", +) class TestCvsps: @pytest.mark.complete("cvsps -", require_cmd=True) def test_1(self, completion): diff --git a/test/t/test_date.py b/test/t/test_date.py index 57d61b8..f0f93b6 100644 --- a/test/t/test_date.py +++ b/test/t/test_date.py @@ -6,6 +6,6 @@ class TestDate: def test_1(self, completion): assert completion - @pytest.mark.complete("date -", require_cmd=True) + @pytest.mark.complete("date -", require_longopt=True) def test_options(self, completion): assert completion diff --git a/test/t/test_dcop.py b/test/t/test_dcop.py index 5c3c04d..3e6d363 100644 --- a/test/t/test_dcop.py +++ b/test/t/test_dcop.py @@ -2,6 +2,8 @@ import pytest class TestDcop: - @pytest.mark.complete("dcop ", require_cmd=True) + @pytest.mark.complete( + "dcop ", require_cmd=True, skipif="! dcop &>/dev/null" + ) def test_1(self, completion): assert completion diff --git a/test/t/test_dd.py b/test/t/test_dd.py index e082faa..c0978f3 100644 --- a/test/t/test_dd.py +++ b/test/t/test_dd.py @@ -2,13 +2,7 @@ import pytest class TestDd: - @pytest.mark.complete( - "dd --", - xfail=( - "! dd --help &>/dev/null || " - "! dd --help 2>&1 | command grep -qF -- --help" - ), - ) + @pytest.mark.complete("dd --", require_longopt=True) def test_1(self, completion): assert completion diff --git a/test/t/test_declare.py b/test/t/test_declare.py index a61d926..924eef0 100644 --- a/test/t/test_declare.py +++ b/test/t/test_declare.py @@ -15,6 +15,18 @@ class TestDeclare: # bash 5.0 has BASH_ARGV0 too assert all(x in completion for x in "BASH_ARGC BASH_ARGV".split()) - @pytest.mark.complete("declare -f _parse_") + @pytest.mark.complete("declare -f _comp_comp") def test_4(self, completion): - assert "_parse_help" in completion + assert "_comp_compgen" in completion + + @pytest.mark.complete("declare -a BASH_VERS") + def test_arrayvar(self, completion): + assert "INFO" in completion + + @pytest.mark.complete("declare -f BASH_VERS") + def test_no_arrayvar_for_f(self, completion): + assert "INFO" not in completion + + @pytest.mark.complete("declare -i BASH_VERS") + def test_no_arrayvar_for_i(self, completion): + assert "INFO" not in completion diff --git a/test/t/test_dict.py b/test/t/test_dict.py index 99c4a21..64adb54 100644 --- a/test/t/test_dict.py +++ b/test/t/test_dict.py @@ -1,3 +1,5 @@ +import os + import pytest @@ -5,3 +7,25 @@ class TestDict: @pytest.mark.complete("dict -", require_cmd=True) def test_1(self, completion): assert completion + + @pytest.mark.xfail( + os.environ.get("NETWORK") == "none", + reason="The database list is unavailable without network", + ) + @pytest.mark.complete("dict --database ", require_cmd=True) + def test_database(self, completion): + # Ensure the directory name "_comp_load/" not generated because + # filenames in the current dictory (i.e., test/fixtures) are generated + # by "-o default" when "_comp_cmd_dict" fails to generate any + # completions. + assert completion and "_comp_load/" not in completion + + @pytest.mark.xfail( + os.environ.get("NETWORK") == "none", + reason="The database list is unavailable without network", + ) + @pytest.mark.complete( + "dict -h dict.org --database ", require_cmd=True, env=dict(IFS="") + ) + def test_database_IFS(self, completion): + assert completion and "_comp_load/" not in completion diff --git a/test/t/test_dmesg.py b/test/t/test_dmesg.py index a081fb6..e1001b0 100644 --- a/test/t/test_dmesg.py +++ b/test/t/test_dmesg.py @@ -1,7 +1,12 @@ +import sys + import pytest class TestDmesg: @pytest.mark.complete("dmesg -", require_cmd=True) def test_1(self, completion): - assert completion + if sys.platform == "darwin": + assert not completion # takes no options + else: + assert completion diff --git a/test/t/test_dmypy.py b/test/t/test_dmypy.py index 4c031dd..6253d91 100644 --- a/test/t/test_dmypy.py +++ b/test/t/test_dmypy.py @@ -9,6 +9,6 @@ class TestDmypy: assert "help" in completion assert not any("," in x for x in completion) - @pytest.mark.complete("dmypy -", require_cmd=True, require_longopt=True) + @pytest.mark.complete("dmypy -", require_longopt=True) def test_options(self, completion): assert "--help" in completion diff --git a/test/t/test_dot.py b/test/t/test_dot.py index a4aa674..733555c 100644 --- a/test/t/test_dot.py +++ b/test/t/test_dot.py @@ -5,3 +5,11 @@ class TestDot: @pytest.mark.complete("dot ") def test_1(self, completion): assert completion + + @pytest.mark.complete("dot t", cwd="dot") + def test_2(self, completion): + assert completion == ["test1.gv", "test2.dot"] + + @pytest.mark.complete("dot test1", cwd="dot") + def test_3(self, completion): + assert completion == ".gv" diff --git a/test/t/test_dpkg.py b/test/t/test_dpkg.py index eb1228b..ce6a047 100644 --- a/test/t/test_dpkg.py +++ b/test/t/test_dpkg.py @@ -6,10 +6,18 @@ class TestDpkg: def test_1(self, completion): assert completion - @pytest.mark.complete("dpkg -L ", xfail='test -z "$(dpkg -l 2>/dev/null)"') + @pytest.mark.complete("dpkg -L ", xfail='test ! "$(dpkg -l 2>/dev/null)"') def test_2(self, completion): assert completion @pytest.mark.complete("dpkg -i ~") def test_3(self, completion): assert completion + + @pytest.mark.complete("dpkg -i dpkg/") + def test_i_deb(self, completion): + assert completion == "bash-completion-test-subject.deb" + + @pytest.mark.complete("dpkg -") + def test_no_trailing_dash_options(self, completion): + assert not any(x.endswith("-") for x in completion) diff --git a/test/t/test_dpkg_query.py b/test/t/test_dpkg_query.py index 37c5621..743d668 100644 --- a/test/t/test_dpkg_query.py +++ b/test/t/test_dpkg_query.py @@ -3,7 +3,7 @@ import os.path import pytest -@pytest.mark.bashcomp(cmd="dpkg-query",) +@pytest.mark.bashcomp(cmd="dpkg-query") class TestDpkgQuery: @pytest.mark.complete("dpkg-query --", require_cmd=True) def test_options(self, completion): @@ -13,6 +13,10 @@ class TestDpkgQuery: not os.path.exists("/etc/debian_version"), reason="Likely fails on systems not based on Debian", ) - @pytest.mark.complete("dpkg-query -W dpk", require_cmd=True) + @pytest.mark.complete( + "dpkg-query -W dpk", + require_cmd=True, + xfail="! apt-cache show &>/dev/null", # empty cache? + ) def test_show(self, completion): assert "dpkg" in completion diff --git a/test/t/test_dropdb.py b/test/t/test_dropdb.py index 2f65857..f75979a 100644 --- a/test/t/test_dropdb.py +++ b/test/t/test_dropdb.py @@ -2,7 +2,6 @@ import pytest class TestDropdb: - # --help can fail due to missing package dependencies, e.g. on Ubuntu 14 @pytest.mark.complete( "dropdb -", require_cmd=True, xfail="! dropdb --help &>/dev/null" diff --git a/test/t/test_evince.py b/test/t/test_evince.py index 9e9245d..f89e97c 100644 --- a/test/t/test_evince.py +++ b/test/t/test_evince.py @@ -1,22 +1,32 @@ import pytest +from conftest import assert_complete, create_dummy_filedirs + +@pytest.mark.bashcomp(temp_cwd=True) class TestEvince: - @pytest.mark.complete("evince ", cwd="evince") - def test_1(self, completion): - # .txt should not be here - assert completion == sorted( - "foo/ .bmp .BMP .cbr .CBR .cbz .CBZ .djv .DJV .djvu .DJVU .dvi " - ".DVI .dvi.bz2 .dvi.BZ2 .DVI.bz2 .DVI.BZ2 .dvi.gz .dvi.GZ " - ".DVI.gz .DVI.GZ .eps .EPS .eps.bz2 .eps.BZ2 .EPS.bz2 .EPS.BZ2 " - ".eps.gz .eps.GZ .EPS.gz .EPS.GZ .gif .GIF .ico .ICO .jpeg " - ".JPEG .jpg .JPG .miff .MIFF .pbm .PBM .pcx .PCX .pdf .PDF " - ".pdf.bz2 .pdf.BZ2 .PDF.bz2 .PDF.BZ2 .pdf.gz .pdf.GZ .PDF.gz " - ".PDF.GZ .pgm .PGM .png .PNG .pnm .PNM .ppm .PPM .ps .PS " - ".ps.bz2 .ps.BZ2 .PS.bz2 .PS.BZ2 .ps.gz .ps.GZ .PS.gz .PS.GZ " - ".tga .TGA .tif .TIF .tiff .TIFF .xpm .XPM .xwd .XWD".split() + def test_1(self, bash): + files, dirs = create_dummy_filedirs( + ( + ".cb7 .CB7 .cbr .CBR .cbt .CBT .cbz .CBZ .djv .DJV .djvu " + ".DJVU .dvi .DVI .dvi.bz2 .dvi.BZ2 .DVI.bz2 .DVI.BZ2 .dvi.gz " + ".dvi.GZ .DVI.gz .DVI.GZ .eps .EPS .eps.bz2 .eps.BZ2 .EPS.bz2 " + ".EPS.BZ2 .eps.gz .eps.GZ .EPS.gz .EPS.GZ .oxps .OXPS .pdf " + ".PDF .pdf.bz2 .pdf.BZ2 .PDF.bz2 .PDF.BZ2 .pdf.gz .pdf.GZ " + ".PDF.gz .PDF.GZ .ps .PS .ps.bz2 .ps.BZ2 .PS.bz2 .PS.BZ2 " + ".ps.gz .ps.GZ .PS.gz .PS.GZ .tif .TIF .tiff .TIFF .txt .TXT " + ".xps .XPS" + ).split(), + "foo".split(), ) + completion = assert_complete(bash, "evince ") + assert completion == [ + x + for x in sorted(files + ["%s/" % d for d in dirs]) + if x.lower() != ".txt" + ] + @pytest.mark.complete("evince -", require_cmd=True) def test_2(self, completion): assert completion diff --git a/test/t/test_export.py b/test/t/test_export.py index 8738913..8abb564 100644 --- a/test/t/test_export.py +++ b/test/t/test_export.py @@ -1,5 +1,7 @@ import pytest +from conftest import assert_bash_exec + class TestExport: @pytest.mark.complete("export BASH") @@ -22,10 +24,9 @@ class TestExport: def test_5(self, completion): assert completion == ["foo", "foo.d/"] - @pytest.mark.complete("export -fn _ex") + @pytest.mark.complete("export -fn _comp_cmd_ex") def test_6(self, completion): - assert "_expand" in completion - assert "_export" in completion + assert completion == "port" @pytest.mark.complete(r"export FOO=$BASH") def test_7(self, completion): @@ -34,3 +35,13 @@ class TestExport: @pytest.mark.complete("export -", require_cmd=True) def test_8(self, completion): assert completion + + @pytest.fixture(scope="class") + def export_f_canary(self, request, bash): + assert_bash_exec(bash, "_comp__test_export_f_canary() { return; }") + + @pytest.mark.complete("export -f _comp__test_export_f_canar") + def test_no_equals_sign_for_function(self, completion, export_f_canary): + assert completion + assert "=" not in "".join(completion) + assert completion.endswith(" ") diff --git a/test/t/test_finger.py b/test/t/test_finger.py index d765fdd..4aca977 100644 --- a/test/t/test_finger.py +++ b/test/t/test_finger.py @@ -26,8 +26,8 @@ class TestFinger: def test_partial_hostname(self, bash, known_hosts): first_char, partial_hosts = partialize(bash, known_hosts) user = "test" - completion = assert_complete(bash, "finger %s@%s" % (user, first_char)) + completion = assert_complete(bash, f"finger {user}@{first_char}") if len(completion) == 1: assert completion == partial_hosts[0][1:] else: - assert completion == ["%s@%s" % (user, x) for x in partial_hosts] + assert completion == [f"{user}@{x}" for x in partial_hosts] diff --git a/test/t/test_fio.py b/test/t/test_fio.py index 0f6eba7..dadb5ac 100644 --- a/test/t/test_fio.py +++ b/test/t/test_fio.py @@ -10,6 +10,44 @@ class TestFio: def test_2(self, completion): assert completion - @pytest.mark.complete("fio --debug=foo,") + @pytest.mark.complete("fio --debug=foo,", require_cmd=True) def test_3(self, completion): assert completion + + @pytest.mark.complete("fio --ioengin", require_cmd=True) + def test_cmdhelp_all(self, completion): + """Test we got a "known present" option from --cmdhelp=all.""" + assert completion == "e=" or "e" in completion + + @pytest.mark.complete("fio --ioengine=", require_cmd=True) + def test_enghelp(self, completion): + """Test --enghelp parsing.""" + assert completion + + @pytest.mark.complete("fio --unlink=", require_cmd=True) + def test_cmdhelp_boolean(self, completion): + """Test --cmdhelp=COMMAND boolean parsing.""" + assert completion == "0 1".split() + + @pytest.mark.complete("fio --kb_base=", require_cmd=True) + def test_cmdhelp_valid_values(self, completion): + """Test --cmdhelp=COMMAND valid values parsing.""" + # We expect kb_base args to be stable, no additions/removals. + assert completion == "1000 1024".split() + + @pytest.mark.complete("fio --non_exist3nt_option=", require_cmd=True) + def test_cmdhelp_nonexistent(self, completion): + """Test --cmdhelp=COMMAND errors out gracefully.""" + assert not completion + + @pytest.mark.complete( + "fio --crctest=", + require_cmd=True, + xfail="! fio --help 2>&1 | command grep -q -- --crctest", + ) + def test_crctest(self, completion): + assert "sha1" in completion + + @pytest.mark.complete("fio --debug=", require_cmd=True) + def test_debug(self, completion): + assert "process" in completion diff --git a/test/t/test_firefox.py b/test/t/test_firefox.py index 2e05255..619318c 100644 --- a/test/t/test_firefox.py +++ b/test/t/test_firefox.py @@ -6,7 +6,12 @@ class TestFirefox: def test_1(self, completion): assert completion - @pytest.mark.complete("firefox -", require_cmd=True) + # --help test: running as root in GH actions container croaks: + # Running Firefox as root in a regular user's session is not supported. + # ($HOME is /github/home which is owned by uid 1001.) + @pytest.mark.complete( + "firefox -", require_cmd=True, xfail="! firefox --help &>/dev/null" + ) def test_2(self, completion): assert completion assert not completion.endswith(" ") diff --git a/test/t/test_function.py b/test/t/test_function.py index 4401f02..ce74780 100644 --- a/test/t/test_function.py +++ b/test/t/test_function.py @@ -1,7 +1,19 @@ import pytest +from conftest import assert_bash_exec, assert_complete + +@pytest.mark.bashcomp(ignore_env=r"^\+declare -f fn$") class TestFunction: @pytest.mark.complete("function _parse_") def test_1(self, completion): assert completion + + @pytest.mark.complete("function non_existent_function ") + def test_2(self, completion): + assert completion == "()" + + def test_3(self, bash): + assert_bash_exec(bash, "fn() { echo; }") + completion = assert_complete(bash, "function fn ") + assert completion == "() { ^J echo^J}" diff --git a/test/t/test_gdb.py b/test/t/test_gdb.py index 2ad12c4..9f038f8 100644 --- a/test/t/test_gdb.py +++ b/test/t/test_gdb.py @@ -12,3 +12,13 @@ class TestGdb: "core core.12345 " "core.weston.1000.deadbeef.5308.1555362132000000".split() ) + + @pytest.mark.complete("gdb aw") + def test_3(self, completion): + """Check that the completion can generate command names""" + assert completion == ["k"] or "awk" in completion + + @pytest.mark.complete("gdb built") + def test_4(self, completion): + """Check that the completion does not generate builtin names""" + assert not (completion == ["in"] or "builtin" in completion) diff --git a/test/t/test_getconf.py b/test/t/test_getconf.py index c80c803..e9578e7 100644 --- a/test/t/test_getconf.py +++ b/test/t/test_getconf.py @@ -2,7 +2,7 @@ import pytest class TestGetconf: - @pytest.mark.complete("getconf P") + @pytest.mark.complete("getconf P", skipif="! getconf -a &>/dev/null") def test_1(self, completion): assert completion diff --git a/test/t/test_grep.py b/test/t/test_grep.py index a249122..ded7fb5 100644 --- a/test/t/test_grep.py +++ b/test/t/test_grep.py @@ -11,6 +11,16 @@ class TestGrep: """ Test --no-*dir isn't restricted to dirs only. - Not really a grep option, but tests _longopt. + Not really a grep option, but tests _comp_complete_longopt. """ assert completion == "foo foo.d/".split() + + @pytest.mark.complete("grep TZ ", cwd="shared/default") + def test_no_variable_assignment_confusion(self, completion): + """ + Test TZ doesn't trigger known variable value assignment completion. + + Not really a grep specific, but good to test somewhere. + Refs https://github.com/scop/bash-completion/issues/457 + """ + assert "foo" in completion diff --git a/test/t/test_gssdp_device_sniffer.py b/test/t/test_gssdp_device_sniffer.py new file mode 100644 index 0000000..be05d0d --- /dev/null +++ b/test/t/test_gssdp_device_sniffer.py @@ -0,0 +1,14 @@ +import pytest + + +@pytest.mark.bashcomp( + cmd="gssdp-device-sniffer", +) +class TestGssdpDeviceSniffer: + @pytest.mark.complete("gssdp-device-sniffer ") + def test_basic(self, completion): + assert not completion + + @pytest.mark.complete("gssdp-device-sniffer -", require_cmd=True) + def test_options(self, completion): + assert "--help" in completion diff --git a/test/t/test_hash.py b/test/t/test_hash.py new file mode 100644 index 0000000..2a1bf0c --- /dev/null +++ b/test/t/test_hash.py @@ -0,0 +1,11 @@ +import pytest + + +class TestHash: + @pytest.mark.complete("hash ", require_cmd=True) + def test_basic(self, completion): + assert completion + + @pytest.mark.complete("hash -", require_cmd=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_help.py b/test/t/test_help.py new file mode 100644 index 0000000..b056c55 --- /dev/null +++ b/test/t/test_help.py @@ -0,0 +1,21 @@ +import pytest + + +class TestHelp: + @pytest.mark.complete("help ") + def test_basic(self, completion): + assert "help" in completion + + @pytest.mark.complete("help -") + def test_options(self, completion): + assert completion + + @pytest.mark.complete( + r"help \(", + skipif="! compgen -A helptopic | grep -qxF '(( ... ))'", # bash 4.2 + ) + def test_parens(self, completion): + # Assumption: an item like "(( ... ))" exists in the output + assert any( + x.startswith(r"\(") and x.endswith(r"\)\)") for x in completion + ) diff --git a/test/t/test_info.py b/test/t/test_info.py index e12d900..2fdbcca 100644 --- a/test/t/test_info.py +++ b/test/t/test_info.py @@ -10,3 +10,11 @@ class TestInfo: @pytest.mark.complete("info -", require_cmd=True) def test_2(self, completion): assert completion + + @pytest.mark.complete( + "info nonexistent-na", + env=dict(INFOPATH="'$(echo malicious code >/dev/tty)'"), + ) + def test_infopath_code_injection(self, completion): + # no completion, no space appended + assert not completion diff --git a/test/t/test_installpkg.py b/test/t/test_installpkg.py index e665f52..0ae4840 100644 --- a/test/t/test_installpkg.py +++ b/test/t/test_installpkg.py @@ -12,7 +12,8 @@ class TestInstallpkg: @pytest.mark.complete("installpkg --") def test_2(self, completion): assert ( - completion == "--ask --infobox --md5sum --menu " + completion + == "--ask --infobox --md5sum --menu " "--priority --root --tagfile --terse --warn".split() ) diff --git a/test/t/test_invoke_rc_d.py b/test/t/test_invoke_rc_d.py index 61e2987..5ef768c 100644 --- a/test/t/test_invoke_rc_d.py +++ b/test/t/test_invoke_rc_d.py @@ -1,8 +1,14 @@ +import sys + import pytest @pytest.mark.bashcomp(cmd="invoke-rc.d") class TestInvokeRcD: + @pytest.mark.xfail( + sys.platform == "darwin", + reason="Service completion not available on macOS", + ) @pytest.mark.complete("invoke-rc.d ") def test_1(self, completion): assert completion @@ -10,5 +16,6 @@ class TestInvokeRcD: @pytest.mark.complete("invoke-rc.d --no-fallback --") def test_2(self, completion): """Test already specified option is not offered.""" - assert completion + if sys.platform != "darwin": # no service completion + assert completion assert "--no-fallback" not in completion diff --git a/test/t/test_ip.py b/test/t/test_ip.py index 320647f..0be088c 100644 --- a/test/t/test_ip.py +++ b/test/t/test_ip.py @@ -10,6 +10,19 @@ class TestIp: def test_2(self, completion): assert completion - @pytest.mark.complete("ip route replace ") + @pytest.mark.complete("ip route replace ", require_cmd=True) def test_r_r(self, completion): assert completion + + @pytest.mark.complete( + "ip monitor ", + require_cmd=True, + skipif="ip monitor help 2>/dev/null; (( $? != 255 ))", + ) + def test_monitor(self, completion): + assert "neigh" in completion + assert "all" in completion + + @pytest.mark.complete("ip -", require_cmd=True) + def test_options(self, completion): + assert "-family" in completion diff --git a/test/t/test_iperf.py b/test/t/test_iperf.py index c38e954..0b67001 100644 --- a/test/t/test_iperf.py +++ b/test/t/test_iperf.py @@ -22,3 +22,8 @@ class TestIperf: @pytest.mark.complete("iperf -", require_cmd=True) def test_5(self, completion): assert completion + + @pytest.mark.complete("iperf --format ", require_cmd=True) + def test_format(self, completion): + # 2.0.5 has only up to m/M, later may have g/G, t/T, ... + assert all(x in completion for x in "k m K M".split()) diff --git a/test/t/test_iperf3.py b/test/t/test_iperf3.py index 15f3a03..35070c1 100644 --- a/test/t/test_iperf3.py +++ b/test/t/test_iperf3.py @@ -18,3 +18,8 @@ class TestIperf3: @pytest.mark.complete("iperf3 --server --", require_cmd=True) def test_4(self, completion): assert "--daemon" in completion + + @pytest.mark.complete("iperf3 --format ", require_cmd=True) + def test_format(self, completion): + # 3.0.7 has only up to m/M, later may have g/G, t/T, ... + assert all(x in completion for x in "k m K M".split()) diff --git a/test/t/test_isort.py b/test/t/test_isort.py index b142d1c..1c86b84 100644 --- a/test/t/test_isort.py +++ b/test/t/test_isort.py @@ -6,6 +6,6 @@ class TestIsort: def test_1(self, completion): assert completion - @pytest.mark.complete("isort -", require_cmd=True, require_longopt=True) + @pytest.mark.complete("isort -", require_longopt=True) def test_2(self, completion): assert completion diff --git a/test/t/test_java.py b/test/t/test_java.py index ce0f773..03f1520 100644 --- a/test/t/test_java.py +++ b/test/t/test_java.py @@ -1,6 +1,6 @@ import pytest -from conftest import is_bash_type +from conftest import is_bash_type, assert_bash_exec, bash_env_saved @pytest.mark.bashcomp( @@ -47,3 +47,46 @@ class TestJava: @pytest.mark.complete("java -jar java/") def test_6(self, completion): assert completion == "a/ bashcomp.jar bashcomp.war".split() + + @pytest.mark.complete("javadoc -sourcepath java/a:java/a/c ") + def test_sourcepath_1(self, completion): + """sourcepath should be split by `:`""" + assert completion == "c" + + @pytest.mark.complete("javadoc -sourcepath java/?:java/x ") + def test_sourcepath_2(self, completion): + """pathname expansion should not happen after splitting the argument by + `:`""" + assert not completion + + @pytest.mark.complete("javadoc -sourcepath java/a ") + def test_packages_1(self, completion): + assert completion == "c" + + @pytest.mark.complete("javadoc -sourcepath java/a x") + def test_packages_2(self, completion): + assert not completion + + @pytest.mark.complete( + "javadoc -sourcepath java/a x", shopt=dict(failglob=True) + ) + def test_packages_3(self, completion): + assert not completion + + @pytest.mark.complete("javadoc -sourcepath java/a ", env=dict(IFS="a")) + def test_packages_4(self, completion): + assert completion == "c" + + def test_packages_5(self, bash): + """_comp_cmd_java__packages should not modify the outerscope `cur`""" + with bash_env_saved(bash) as bash_env: + bash_env.write_variable("cur", "a.b.c") + assert_bash_exec( + bash, + "_comp_test_f() { local cword=3 words=(javadoc -sourcepath java/a a.b.c); COMPREPLY+=(); _comp_cmd_java__packages; }; _comp_test_f", + ) + + @pytest.mark.complete("javadoc -sourcepath java a.") + def test_packages_6(self, completion): + """A period in package names should not be converted to slash.""" + assert completion == "c" diff --git a/test/t/test_javaws.py b/test/t/test_javaws.py index 596c735..4d033c3 100644 --- a/test/t/test_javaws.py +++ b/test/t/test_javaws.py @@ -6,6 +6,12 @@ class TestJavaws: def test_1(self, completion): assert completion - @pytest.mark.complete("javaws -", require_cmd=True) + @pytest.mark.complete( + "javaws -", + require_cmd=True, + xfail=( + "! (javaws -help 2>&1 || :) | " "command grep -q -- '[[:space:]]-'" + ), + ) def test_2(self, completion): assert completion diff --git a/test/t/test_jq.py b/test/t/test_jq.py index 4701414..ca4d0e0 100644 --- a/test/t/test_jq.py +++ b/test/t/test_jq.py @@ -28,3 +28,11 @@ class TestJq: @pytest.mark.complete("jq --slurpfile foo ") def test_6(self, completion): assert completion + + @pytest.mark.complete("jq --args ") + def test_no_completion_after_args(self, completion): + assert not completion + + @pytest.mark.complete("jq --jsonargs foo ") + def test_no_completion_after_jsonargs(self, completion): + assert not completion diff --git a/test/t/test_jsonschema.py b/test/t/test_jsonschema.py index 6027f5d..5f43435 100644 --- a/test/t/test_jsonschema.py +++ b/test/t/test_jsonschema.py @@ -6,8 +6,6 @@ class TestJsonschema: def test_1(self, completion): assert completion - @pytest.mark.complete( - "jsonschema -", require_cmd=True, require_longopt=True - ) + @pytest.mark.complete("jsonschema -", require_longopt=True) def test_2(self, completion): assert completion diff --git a/test/t/test_kdvi.py b/test/t/test_kdvi.py index c2ab011..114e024 100644 --- a/test/t/test_kdvi.py +++ b/test/t/test_kdvi.py @@ -1,10 +1,22 @@ import pytest +from conftest import assert_complete, create_dummy_filedirs + +@pytest.mark.bashcomp(temp_cwd=True) class TestKdvi: - @pytest.mark.complete("kdvi ", cwd="kdvi") - def test_1(self, completion): - assert completion == sorted( - "foo/ .dvi .DVI .dvi.bz2 .DVI.bz2 .dvi.gz " - ".DVI.gz .dvi.Z .DVI.Z".split() + def test_1(self, bash): + files, dirs = create_dummy_filedirs( + ( + ".dvi .DVI .dvi.bz2 .DVI.bz2 .dvi.gz .DVI.gz .dvi.Z .DVI.Z " + ".txt" + ).split(), + "foo".split(), ) + + completion = assert_complete(bash, "kdvi ") + assert completion == [ + x + for x in sorted(files + ["%s/" % d for d in dirs]) + if x.lower() != ".txt" + ] diff --git a/test/t/test_kill.py b/test/t/test_kill.py index 9699435..9233c00 100644 --- a/test/t/test_kill.py +++ b/test/t/test_kill.py @@ -13,3 +13,7 @@ class TestKill: @pytest.mark.complete("kill -") def test_3(self, completion): assert all("-%s" % x in completion for x in "l s ABRT USR1".split()) + + @pytest.mark.complete("kill %", pre_cmds=("bash -c 'sleep 5' &",)) + def test_jobs(self, bash, completion): + assert "bash" in completion diff --git a/test/t/test_killall.py b/test/t/test_killall.py index 4b67d96..96eab8a 100644 --- a/test/t/test_killall.py +++ b/test/t/test_killall.py @@ -2,7 +2,6 @@ import pytest class TestKillall: - # "p": Assume our process name completion runs ps and at least it is shown @pytest.mark.complete("killall p") def test_1(self, completion): diff --git a/test/t/test_kpdf.py b/test/t/test_kpdf.py index 68b36fe..b7e658f 100644 --- a/test/t/test_kpdf.py +++ b/test/t/test_kpdf.py @@ -1,7 +1,19 @@ import pytest +from conftest import assert_complete, create_dummy_filedirs + +@pytest.mark.bashcomp(temp_cwd=True) class TestKpdf: - @pytest.mark.complete("kpdf ", cwd="kpdf") - def test_1(self, completion): - assert completion == sorted("foo/ .eps .ps .EPS .PS .pdf .PDF".split()) + def test_1(self, bash): + files, dirs = create_dummy_filedirs( + ".eps .EPS .pdf .PDF .ps .PS .txt".split(), + "foo".split(), + ) + + completion = assert_complete(bash, "kpdf ") + assert completion == [ + x + for x in sorted(files + ["%s/" % d for d in dirs]) + if x.lower() != ".txt" + ] diff --git a/test/t/test_ld.py b/test/t/test_ld.py index f6a16bb..004692e 100644 --- a/test/t/test_ld.py +++ b/test/t/test_ld.py @@ -6,6 +6,6 @@ class TestLd: def test_1(self, completion): assert completion - @pytest.mark.complete("ld -", require_cmd=True) + @pytest.mark.complete("ld -", require_longopt=True) def test_options(self, completion): assert completion diff --git a/test/t/test_lrzip.py b/test/t/test_lrzip.py index d61ee9d..dbc3939 100644 --- a/test/t/test_lrzip.py +++ b/test/t/test_lrzip.py @@ -13,3 +13,12 @@ class TestLrzip: @pytest.mark.complete("lrzip -", require_cmd=True) def test_3(self, completion): assert completion + + @pytest.mark.complete( + "lrzip --", + # require_longopt not applicable, useful --help may give nonzero exit + require_cmd=True, + xfail=("! { lrzip --help 2>&1 || :; } | command grep -qF -- --help"), + ) + def test_longopt(self, completion): + assert completion diff --git a/test/t/test_ls.py b/test/t/test_ls.py index 8abcb59..f91ee6b 100644 --- a/test/t/test_ls.py +++ b/test/t/test_ls.py @@ -24,7 +24,7 @@ class TestLs: assert_bash_exec( bash, "for u in $(compgen -u); do " - "eval test -d ~$u || echo $u; unset u; done", + "eval test -d ~$u || echo $u; unset -v u; done", want_output=True, ) .strip() diff --git a/test/t/test_lvm.py b/test/t/test_lvm.py index ea25b97..82f1aa4 100644 --- a/test/t/test_lvm.py +++ b/test/t/test_lvm.py @@ -5,3 +5,11 @@ class TestLvm: @pytest.mark.complete("lvm pv") def test_1(self, completion): assert completion + + @pytest.mark.complete( + "lvm lvcreate --", + require_cmd=True, + xfail="! lvm lvcreate --help &>/dev/null", + ) + def test_subcommand_options(self, completion): + assert completion diff --git a/test/t/test_make.py b/test/t/test_make.py index 19861b0..34fc7e5 100644 --- a/test/t/test_make.py +++ b/test/t/test_make.py @@ -2,6 +2,8 @@ import os import pytest +from conftest import assert_complete + class TestMake: @pytest.mark.complete("make -f Ma", cwd="make") @@ -12,12 +14,12 @@ class TestMake: def test_2(self, bash, completion): """Hidden targets.""" assert completion == ".cache/ .test_passes".split() - os.remove("%s/make/%s" % (bash.cwd, "extra_makefile")) + os.remove(f"{bash.cwd}/make/extra_makefile") @pytest.mark.complete("make .cache/", cwd="make", require_cmd=True) def test_3(self, bash, completion): - assert completion == "1 2".split() - os.remove("%s/make/%s" % (bash.cwd, "extra_makefile")) + assert completion == ".cache/1 .cache/2".split() + os.remove(f"{bash.cwd}/make/extra_makefile") @pytest.mark.complete("make ", cwd="shared/empty_dir") def test_4(self, completion): @@ -30,18 +32,58 @@ class TestMake: @pytest.mark.complete("make ", cwd="make", require_cmd=True) def test_6(self, bash, completion): assert completion == "all clean extra_makefile install sample".split() - os.remove("%s/make/%s" % (bash.cwd, "extra_makefile")) + os.remove(f"{bash.cwd}/make/extra_makefile") @pytest.mark.complete("make .cache/.", cwd="make", require_cmd=True) def test_7(self, bash, completion): - assert completion == ".1 .2".split() - os.remove("%s/make/%s" % (bash.cwd, "extra_makefile")) + assert completion == ".cache/.1 .cache/.2".split() + os.remove(f"{bash.cwd}/make/extra_makefile") @pytest.mark.complete("make -C make ", require_cmd=True) def test_8(self, bash, completion): assert completion == "all clean extra_makefile install sample".split() - os.remove("%s/make/%s" % (bash.cwd, "extra_makefile")) + os.remove(f"{bash.cwd}/make/extra_makefile") + + @pytest.mark.complete("make -nC make ", require_cmd=True) + def test_8n(self, bash, completion): + assert completion == "all clean extra_makefile install sample".split() + os.remove(f"{bash.cwd}/make/extra_makefile") @pytest.mark.complete("make -", require_cmd=True) def test_9(self, completion): assert completion + + +@pytest.mark.bashcomp(require_cmd=True, cwd="make/test2") +class TestMake2: + def test_github_issue_544_1(self, bash): + completion = assert_complete(bash, "make ab") + assert completion == "c/xyz" + + def test_github_issue_544_2(self, bash): + completion = assert_complete(bash, "make 1") + assert completion == "23/" + + def test_github_issue_544_3(self, bash): + completion = assert_complete(bash, "make 123/") + assert completion == ["123/xaa", "123/xbb"] + + def test_github_issue_544_4(self, bash): + completion = assert_complete(bash, "make 123/xa") + assert completion == "a" + + def test_subdir_1(self, bash): + completion = assert_complete(bash, "make sub1") + assert completion == "test/bar/" + + def test_subdir_2(self, bash): + completion = assert_complete(bash, "make sub2") + assert completion == "test/bar/alpha" + + def test_subdir_3(self, bash): + completion = assert_complete(bash, "make sub3") + assert completion == "test/" + + def test_subdir_4(self, bash): + completion = assert_complete(bash, "make sub4") + assert completion == "sub4test/bar/ sub4test2/foo/gamma".split() diff --git a/test/t/test_makepkg.py b/test/t/test_makepkg.py index f643a29..ad37762 100644 --- a/test/t/test_makepkg.py +++ b/test/t/test_makepkg.py @@ -2,7 +2,7 @@ import pytest @pytest.mark.bashcomp( - ignore_env=r"^-declare -f _makepkg_bootstrap$", + ignore_env=r"^-declare -f _comp_cmd_makepkg__bootstrap$", xfail="! makepkg --help 2>&1 | command grep -qiF slackware", ) class TestMakepkg: diff --git a/test/t/test_man.py b/test/t/test_man.py index 1ff9f84..081b8fc 100644 --- a/test/t/test_man.py +++ b/test/t/test_man.py @@ -1,13 +1,17 @@ import pytest -from conftest import assert_bash_exec +from conftest import ( + assert_bash_exec, + assert_complete, + is_bash_type, + prepare_fixture_dir, +) @pytest.mark.bashcomp( - ignore_env=r"^[+-]((BASHOPTS|MANPATH)=|shopt -. failglob)" + ignore_env=r"^[+-]((BASHOPTS|MANPATH|manpath)=|shopt -. failglob)" ) class TestMan: - manpath = "$PWD/man" assumed_present = "man" @@ -20,13 +24,12 @@ class TestMan: else: pytest.skip("Cygwin doesn't like paths with colons") return - assert_bash_exec(bash, "mkdir -p $TESTDIR/../tmp/man/man3") - assert_bash_exec( - bash, "touch $TESTDIR/../tmp/man/man3/Bash::Completion.3pm.gz" - ) - request.addfinalizer( - lambda: assert_bash_exec(bash, "rm -r $TESTDIR/../tmp/man") + tmpdir, _, _ = prepare_fixture_dir( + request, + files=["man/man3/Bash::Completion.3pm.gz"], + dirs=["man", "man/man3"], ) + return tmpdir @pytest.mark.complete( "man bash-completion-testcas", @@ -96,20 +99,60 @@ class TestMan: "man %s" % assumed_present, require_cmd=True, cwd="shared/empty_dir", - pre_cmds=("shopt -s failglob",), + shopt=dict(failglob=True), ) def test_9(self, bash, completion): assert self.assumed_present in completion - assert_bash_exec(bash, "shopt -u failglob") - @pytest.mark.complete( - "man Bash::C", - require_cmd=True, - env=dict(MANPATH="%s:../tmp/man" % manpath), - ) - def test_10(self, bash, colonpath, completion): + def test_10(self, request, bash, colonpath): + if not is_bash_type(bash, "man"): + pytest.skip("Command not found") + completion = assert_complete( + bash, + "man Bash::C", + env=dict(MANPATH="%s:%s/man" % (TestMan.manpath, colonpath)), + ) assert completion == "ompletion" @pytest.mark.complete("man -", require_cmd=True) def test_11(self, completion): assert completion + + @pytest.mark.complete("man -S 1", require_cmd=True) + def test_delimited_first(self, completion): + # just appends space + assert not completion + assert completion.endswith(" ") + + @pytest.mark.complete("man -S 1:", require_cmd=True) + def test_delimited_after_delimiter(self, completion): + assert completion + assert "1" not in completion + + @pytest.mark.complete("man -S 1:2", require_cmd=True) + def test_delimited_later(self, completion): + # just appends space + assert not completion + assert completion.endswith(" ") + + @pytest.mark.complete("man -S 1:1", require_cmd=True) + def test_delimited_deduplication(self, completion): + # no completion, no space appended + assert not completion + assert not completion.endswith(" ") + + @pytest.mark.complete( + "man bash-completion-zstd-testcas", + env=dict(MANPATH=manpath), + require_cmd=True, + ) + def test_zstd_arbitrary_sectsuffix(self, completion): + assert completion == "e" + + @pytest.mark.complete( + "man bash-completion-testcas", + env=dict(MANPATH="'$(echo malicious code >/dev/tty)'"), + ) + def test_manpath_code_injection(self, completion): + # no completion, no space appended + assert not completion diff --git a/test/t/test_md5sum.py b/test/t/test_md5sum.py index 0a3286a..e1568a1 100644 --- a/test/t/test_md5sum.py +++ b/test/t/test_md5sum.py @@ -6,6 +6,6 @@ class TestMd5sum: def test_1(self, completion): assert completion - @pytest.mark.complete("md5sum -", require_longopt=True) + @pytest.mark.complete("md5sum --", require_longopt=True) def test_options(self, completion): assert completion diff --git a/test/t/test_munindoc.py b/test/t/test_munindoc.py index eea13ca..38c7d52 100644 --- a/test/t/test_munindoc.py +++ b/test/t/test_munindoc.py @@ -2,7 +2,6 @@ import pytest class TestMunindoc: - # Assume at least munin* available # require_cmd is not strictly correct here, but... @pytest.mark.complete("munindoc m", require_cmd=True) diff --git a/test/t/test_mutt.py b/test/t/test_mutt.py index 0c4074f..e5b6387 100644 --- a/test/t/test_mutt.py +++ b/test/t/test_mutt.py @@ -5,6 +5,13 @@ from conftest import assert_bash_exec @pytest.mark.bashcomp(pre_cmds=("HOME=$PWD/mutt",)) class TestMutt: + @pytest.fixture(scope="class") + def functions(self, bash): + assert_bash_exec( + bash, + '_comp_test__muttconffiles() { local REPLY; _comp_cmd_mutt__get_conffiles "$@" && printf "%s\\n" "${REPLY[@]}"; }', + ) + @pytest.mark.complete("mutt -") def test_1(self, completion): assert completion @@ -17,17 +24,17 @@ class TestMutt: def test_3(self, completion): assert completion == "a1 a2".split() - def test_4(self, bash): + def test_4(self, bash, functions): got = ( assert_bash_exec( bash, - '_muttconffiles "$HOME/muttrc" "$HOME/muttrc"', + '_comp_test__muttconffiles "$HOME/muttrc" "$HOME/muttrc"', want_output=True, ) .strip() .split() ) assert got == [ - "%s/mutt/%s" % (bash.cwd, x) + f"{bash.cwd}/mutt/{x}" for x in ("muttrc", "bar/muttrc_b", "foo/muttrc_f") ] diff --git a/test/t/test_mypy.py b/test/t/test_mypy.py index 11628c1..9d5f16b 100644 --- a/test/t/test_mypy.py +++ b/test/t/test_mypy.py @@ -6,7 +6,7 @@ class TestMypy: def test_1(self, completion): assert completion - @pytest.mark.complete("mypy --", require_cmd=True, require_longopt=True) + @pytest.mark.complete("mypy --", require_longopt=True) def test_2(self, completion): assert completion diff --git a/test/t/test_neomutt.py b/test/t/test_neomutt.py new file mode 100644 index 0000000..36657fe --- /dev/null +++ b/test/t/test_neomutt.py @@ -0,0 +1,7 @@ +import pytest + + +class TestNeomutt: + @pytest.mark.complete("neomutt -") + def test_1(self, completion): + assert completion diff --git a/test/t/test_nmap.py b/test/t/test_nmap.py index 9aff8b2..76aa989 100644 --- a/test/t/test_nmap.py +++ b/test/t/test_nmap.py @@ -7,7 +7,7 @@ class TestNmap: @pytest.fixture(scope="class") def functions(self, request, bash): assert_bash_exec(bash, "_mock_nmap() { cat nmap/nmap-h.txt; }") - assert_bash_exec(bash, "complete -F _nmap _mock_nmap") + assert_bash_exec(bash, "complete -F _comp_cmd_nmap _mock_nmap") @pytest.mark.complete("nmap --v", require_cmd=True) def test_live_options(self, completion): diff --git a/test/t/test_nproc.py b/test/t/test_nproc.py index 66a49ac..29f208b 100644 --- a/test/t/test_nproc.py +++ b/test/t/test_nproc.py @@ -6,12 +6,6 @@ class TestNproc: def test_1(self, completion): assert not completion - @pytest.mark.complete( - "nproc --", - xfail=( - "! nproc --help &>/dev/null || " - "! nproc --help 2>&1 | command grep -qF -- --help" - ), - ) + @pytest.mark.complete("nproc --", require_longopt=True) def test_2(self, completion): assert completion diff --git a/test/t/test_op.py b/test/t/test_op.py deleted file mode 100644 index 662cde5..0000000 --- a/test/t/test_op.py +++ /dev/null @@ -1,11 +0,0 @@ -import pytest - - -class TestOp: - @pytest.mark.complete("op ", require_cmd=True) - def test_1(self, completion): - assert completion - - @pytest.mark.complete("op --", require_cmd=True) - def test_2(self, completion): - assert completion diff --git a/test/t/test_pdftoppm.py b/test/t/test_pdftoppm.py new file mode 100644 index 0000000..2a1a4c6 --- /dev/null +++ b/test/t/test_pdftoppm.py @@ -0,0 +1,11 @@ +import pytest + + +class TestPdftoppm: + @pytest.mark.complete("pdftoppm ") + def test_files(self, completion): + assert completion + + @pytest.mark.complete("pdftoppm -", require_cmd=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_pgrep.py b/test/t/test_pgrep.py index 9a998ed..db3dfdd 100644 --- a/test/t/test_pgrep.py +++ b/test/t/test_pgrep.py @@ -2,7 +2,6 @@ import pytest class TestPgrep: - # "p": Assume that our process name completion runs ps @pytest.mark.complete("pgrep p") def test_1(self, completion): @@ -32,4 +31,3 @@ class TestPgrep: ) def test_nslist_after_comma(self, completion): assert completion - assert not any("," in x for x in completion) diff --git a/test/t/test_pidof.py b/test/t/test_pidof.py index c33a4d3..de77298 100644 --- a/test/t/test_pidof.py +++ b/test/t/test_pidof.py @@ -2,7 +2,6 @@ import pytest class TestPidof: - # "p": Assume that our process name completion runs ps @pytest.mark.complete("pidof p") def test_1(self, completion): diff --git a/test/t/test_pkg_config.py b/test/t/test_pkg_config.py index 81e02ca..14f9c86 100644 --- a/test/t/test_pkg_config.py +++ b/test/t/test_pkg_config.py @@ -1,3 +1,5 @@ +import os + import pytest @@ -10,3 +12,11 @@ class TestPkgConfig: @pytest.mark.complete("pkg-config -", require_cmd=True) def test_2(self, completion): assert completion + + @pytest.mark.complete( + "pkg-config %s/bash-completion.pc --variable=" + % os.getenv("ABS_TOP_BUILDDIR", "../.."), + require_cmd=True, + ) + def test_variable(self, completion): + assert "completionsdir" in completion diff --git a/test/t/test_pkgconf.py b/test/t/test_pkgconf.py new file mode 100644 index 0000000..1466a89 --- /dev/null +++ b/test/t/test_pkgconf.py @@ -0,0 +1,22 @@ +import os + +import pytest + + +@pytest.mark.bashcomp(cmd="pkgconf") +class TestPkgconf: + @pytest.mark.complete("pkgconf ") + def test_1(self, completion): + assert completion + + @pytest.mark.complete("pkgconf -", require_cmd=True) + def test_2(self, completion): + assert completion + + @pytest.mark.complete( + "pkgconf %s/bash-completion.pc --variable=" + % os.getenv("ABS_TOP_BUILDDIR", "../.."), + require_cmd=True, + ) + def test_variable(self, completion): + assert "completionsdir" in completion diff --git a/test/t/test_portinstall.py b/test/t/test_portinstall.py index eb2118e..73a21be 100644 --- a/test/t/test_portinstall.py +++ b/test/t/test_portinstall.py @@ -3,22 +3,19 @@ import pytest from conftest import assert_bash_exec -@pytest.mark.bashcomp(ignore_env=r"^[+-]PORTSDIR=") +@pytest.mark.bashcomp(ignore_env=r"^[+-]PORTSDIR=", temp_cwd=True) class TestPortinstall: @pytest.fixture(scope="class") def portsdir(self, request, bash): - assert_bash_exec(bash, "PORTSDIR=$PWD/../tmp") + assert_bash_exec(bash, "PORTSDIR=$PWD") assert_bash_exec( bash, "command sed -e s,PORTSDIR,$PORTSDIR,g " - "pkgtools/ports/INDEX.dist >$PORTSDIR/INDEX", - ) - assert_bash_exec(bash, "cp $PORTSDIR/INDEX $PORTSDIR/INDEX-5") - request.addfinalizer( - lambda: assert_bash_exec(bash, "rm $PORTSDIR/INDEX{,-5}") + '"$SRCDIRABS"/fixtures/pkgtools/ports/INDEX.dist >INDEX', ) + assert_bash_exec(bash, "cp INDEX INDEX-5") - @pytest.mark.complete("portinstall ", env=dict(PORTSDIR="$PWD/../tmp")) + @pytest.mark.complete("portinstall ", env=dict(PORTSDIR="$PWD")) def test_1(self, completion, portsdir): assert ( completion diff --git a/test/t/test_pr.py b/test/t/test_pr.py index c790a86..23fa767 100644 --- a/test/t/test_pr.py +++ b/test/t/test_pr.py @@ -6,6 +6,6 @@ class TestPr: def test_1(self, completion): assert completion - @pytest.mark.complete("pr -", require_cmd=True) + @pytest.mark.complete("pr -", require_longopt=True) def test_options(self, completion): assert completion diff --git a/test/t/test_printenv.py b/test/t/test_printenv.py index 540c4f6..8384ec0 100644 --- a/test/t/test_printenv.py +++ b/test/t/test_printenv.py @@ -13,7 +13,7 @@ class TestPrintenv: @pytest.mark.complete( "printenv -", require_cmd=True, - xfail="! printenv --help 2>&1 | command grep -qF -- ' -'", + xfail="! printenv --help 2>&1 | command grep -q '^[[:space:]]*-'", ) def test_options(self, completion): assert completion diff --git a/test/t/test_ps.py b/test/t/test_ps.py new file mode 100644 index 0000000..a6bfec1 --- /dev/null +++ b/test/t/test_ps.py @@ -0,0 +1,50 @@ +import pytest + + +def is_int(s): + try: + int(s) + except ValueError: + return False + else: + return True + + +class TestPs: + @pytest.mark.complete("ps -", require_cmd=True) + def test_1(self, completion): + assert completion + + @pytest.mark.complete("ps --help ") + def test_2(self, completion): + assert completion == [ + "all", + "list", + "misc", + "output", + "simple", + "threads", + ] + + @pytest.mark.complete("ps --help all ") + def test_3(self, completion): + assert not completion + + @pytest.mark.complete("ps --version ") + def test_4(self, completion): + assert not completion + + @pytest.mark.complete("ps --pid ") + def test_5(self, completion): + assert completion + assert all(map(is_int, completion)) + + @pytest.mark.complete("ps --format ", require_cmd=True) + def test_6(self, completion): + assert completion + assert all(map(lambda c: not c.startswith(("-", ",")), completion)) + + @pytest.mark.complete("ps --format user,", require_cmd=True) + def test_7(self, completion): + assert completion + assert all(map(lambda c: not c.startswith(("-", ",")), completion)) diff --git a/test/t/test_psql.py b/test/t/test_psql.py index ffd6c05..73abc4b 100644 --- a/test/t/test_psql.py +++ b/test/t/test_psql.py @@ -2,7 +2,6 @@ import pytest class TestPsql: - # --help can fail due to missing package dependencies, e.g. on Ubuntu 14 @pytest.mark.complete( "psql -", require_cmd=True, xfail="! psql --help &>/dev/null" diff --git a/test/t/test_pushd.py b/test/t/test_pushd.py index 290e1d1..5b115d3 100644 --- a/test/t/test_pushd.py +++ b/test/t/test_pushd.py @@ -5,3 +5,7 @@ class TestPushd: @pytest.mark.complete("pushd ") def test_1(self, completion): assert completion + + @pytest.mark.complete("pushd -") + def test_options(self, completion): + assert completion diff --git a/test/t/test_pydocstyle.py b/test/t/test_pydocstyle.py index 1f44320..028a3c0 100644 --- a/test/t/test_pydocstyle.py +++ b/test/t/test_pydocstyle.py @@ -6,8 +6,6 @@ class TestPydocstyle: def test_1(self, completion): assert completion - @pytest.mark.complete( - "pydocstyle -", require_cmd=True, require_longopt=True - ) + @pytest.mark.complete("pydocstyle -", require_longopt=True) def test_2(self, completion): assert completion diff --git a/test/t/test_pylint.py b/test/t/test_pylint.py index 43a4c43..76c7778 100644 --- a/test/t/test_pylint.py +++ b/test/t/test_pylint.py @@ -2,10 +2,22 @@ import pytest class TestPylint: - @pytest.mark.complete("pylint --v", require_cmd=True, require_longopt=True) + @pytest.mark.complete("pylint --v", require_longopt=True) def test_1(self, completion): assert completion @pytest.mark.complete("pylint --confidence=HIGH,") def test_2(self, completion): assert completion + + @pytest.mark.complete("pylint --help-msg=", require_longopt=True) + def test_all_message_ids(self, completion): + assert any("-" in x for x in completion) + + @pytest.mark.complete("pylint --disable=", require_longopt=True) + def test_enabled_message_ids(self, completion): + assert any("-" in x for x in completion) + + @pytest.mark.complete("pylint --enable=foo,", require_longopt=True) + def test_disabled_message_ids(self, completion): + assert any("-" in x for x in completion) diff --git a/test/t/test_pyston.py b/test/t/test_pyston.py new file mode 100644 index 0000000..3c23f31 --- /dev/null +++ b/test/t/test_pyston.py @@ -0,0 +1,19 @@ +import pytest + + +class TestPyston: + @pytest.mark.complete("pyston ") + def test_basic(self, completion): + assert completion + + @pytest.mark.complete("pyston -", require_cmd=True) + def test_options(self, completion): + assert completion + + @pytest.mark.complete( + "pyston -b", + require_cmd=True, + skipif="! pyston -h | command grep -qwF -- -bb", + ) + def test_bb(self, completion): + assert "-bb" in completion diff --git a/test/t/test_pytest.py b/test/t/test_pytest.py index e70c7a5..dededc2 100644 --- a/test/t/test_pytest.py +++ b/test/t/test_pytest.py @@ -8,7 +8,7 @@ class TestPytest: def test_1(self, completion): assert completion - @pytest.mark.complete("pytest -") + @pytest.mark.complete("pytest -", require_cmd=True) def test_2(self, completion): assert completion diff --git a/test/t/test_python.py b/test/t/test_python.py index 5308dcb..bcc566b 100644 --- a/test/t/test_python.py +++ b/test/t/test_python.py @@ -37,3 +37,50 @@ class TestPython: @pytest.mark.complete("python -m json.", require_cmd=True) def test_9(self, completion): assert "json.tool" in completion + + @pytest.mark.complete( + "python -b", + require_cmd=True, + skipif="! python -h | command grep -qwF -- -bb", + ) + def test_bb(self, completion): + assert "-bb" in completion + + @pytest.mark.complete("python foo ", cwd="python") + def test_script_arg(self, completion): + assert "bar.txt" in completion + + @pytest.mark.complete("python -- foo ", cwd="python") + def test_script_arg_with_double_hyphen(self, completion): + assert "bar.txt" in completion + + @pytest.mark.complete("python -m foo bar -p ", cwd="python") + def test_module_arg(self, completion): + assert "bar.txt" in completion + + @pytest.mark.complete("python foo bar -p ", cwd="python") + def test_script_arg_after_option(self, completion): + assert "bar.txt" in completion + + @pytest.mark.complete("python -- foo bar -p ", cwd="python") + def test_script_arg_after_option_with_double_hyphen(self, completion): + assert "bar.txt" in completion + + @pytest.mark.complete("python -m foo bar -p ", cwd="python") + def test_module_arg_after_option(self, completion): + assert "bar.txt" in completion + + @pytest.mark.complete("python -mfoo bar -p ", cwd="python") + def test_module_arg_after_option_with_connected_m_arg(self, completion): + assert "bar.txt" in completion + + @pytest.mark.complete("python -- ", cwd="python") + def test_script_name(self, completion): + assert "bar.txt" not in completion + + @pytest.mark.complete("python -W -mfoo ", cwd="python") + def test_script_name_with_fake_m_arg(self, completion): + """In this case, -mfoo looks like an option to specify the module, but + it should not be treated as the module name because it is an option + argument to -W.""" + assert "bar.txt" not in completion diff --git a/test/t/test_python3.py b/test/t/test_python3.py index a4f6d96..179f90c 100644 --- a/test/t/test_python3.py +++ b/test/t/test_python3.py @@ -34,6 +34,10 @@ class TestPython3: def test_8(self, completion): assert completion - @pytest.mark.complete("python3 -m json.", require_cmd=True) - def test_9(self, completion): - assert "json.tool" in completion + @pytest.mark.complete( + "python3 -b", + require_cmd=True, + skipif="! python3 -h | command grep -qwF -- -bb", + ) + def test_bb(self, completion): + assert "-bb" in completion diff --git a/test/t/test_qemu.py b/test/t/test_qemu.py index 129c0b4..0dd0a2a 100644 --- a/test/t/test_qemu.py +++ b/test/t/test_qemu.py @@ -9,3 +9,7 @@ class TestQemu: @pytest.mark.complete("qemu -", require_cmd=True) def test_2(self, completion): assert completion + + @pytest.mark.complete("qemu -k ", require_cmd=True) + def test_keymaps(self, completion): + assert any(x.lower().startswith("en") for x in completion) diff --git a/test/t/test_qemu_system_x86_64.py b/test/t/test_qemu_system_x86_64.py new file mode 100644 index 0000000..c9e8052 --- /dev/null +++ b/test/t/test_qemu_system_x86_64.py @@ -0,0 +1,16 @@ +import pytest + + +@pytest.mark.bashcomp(cmd="qemu-system-x86_64") +class TestQemuSystemX8664: + @pytest.mark.complete("qemu-system-x86_64 ") + def test_basic(self, completion): + assert completion + + @pytest.mark.complete("qemu-system-x86_64 -", require_cmd=True) + def test_options(self, completion): + assert completion + + @pytest.mark.complete("qemu-system-x86_64 -k ", require_cmd=True) + def test_keymaps(self, completion): + assert any(x.lower().startswith("en") for x in completion) diff --git a/test/t/test_reportbug.py b/test/t/test_reportbug.py index 2c57b56..9347adf 100644 --- a/test/t/test_reportbug.py +++ b/test/t/test_reportbug.py @@ -5,3 +5,7 @@ class TestReportbug: @pytest.mark.complete("reportbug --m", require_cmd=True) def test_1(self, completion): assert completion + + @pytest.mark.complete("reportbug --bts=", require_cmd=True) + def test_bts(self, completion): + assert "default" in completion diff --git a/test/t/test_rmdir.py b/test/t/test_rmdir.py index b981677..19b5ea4 100644 --- a/test/t/test_rmdir.py +++ b/test/t/test_rmdir.py @@ -11,6 +11,6 @@ class TestRmdir: """Should complete dirs only, also when invoked using full path.""" assert completion == ["bar bar.d/", "foo.d/"] - @pytest.mark.complete("rmdir -", require_cmd=True) + @pytest.mark.complete("rmdir -", require_longopt=True) def test_options(self, completion): assert completion diff --git a/test/t/test_rpm.py b/test/t/test_rpm.py index e6f7198..2f1567b 100644 --- a/test/t/test_rpm.py +++ b/test/t/test_rpm.py @@ -6,7 +6,7 @@ class TestRpm: def test_1(self, completion): assert completion - @pytest.mark.complete("rpm -q ", skipif='test -z "$(rpm -qa 2>/dev/null)"') + @pytest.mark.complete("rpm -q ", skipif='test ! "$(rpm -qa 2>/dev/null)"') def test_2(self, completion): assert completion diff --git a/test/t/test_rsync.py b/test/t/test_rsync.py index d54ce6f..0f98dcc 100644 --- a/test/t/test_rsync.py +++ b/test/t/test_rsync.py @@ -1,7 +1,7 @@ import pytest -@pytest.mark.bashcomp(ignore_env=r"^[+-]_scp_path_esc=") +@pytest.mark.bashcomp(ignore_env=r"^[+-]_comp_cmd_scp__path_esc=") class TestRsync: @pytest.mark.complete("rsync ") def test_1(self, completion): @@ -14,3 +14,7 @@ class TestRsync: @pytest.mark.complete("rsync --rsh=") def test_3(self, completion): assert completion == "rsh ssh".split() + + @pytest.mark.complete("rsync --", require_cmd=True) + def test_4(self, completion): + assert "--help" in completion diff --git a/test/t/test_scp.py b/test/t/test_scp.py index 66b8da2..3bd06ee 100644 --- a/test/t/test_scp.py +++ b/test/t/test_scp.py @@ -76,4 +76,22 @@ class TestScp: Connection to it must open sufficiently quickly for the ConnectTimeout and sleep_after_tab settings. """ - assert completion == "%s:%s/" % (LIVE_HOST, live_pwd) + assert completion == f"{LIVE_HOST}:{live_pwd}/" + + @pytest.mark.complete("scp -o Foo=") + def test_option_arg(self, completion): + assert not completion # and no errors either + + @pytest.mark.complete( + "scp hostname-not-expected-to-exist-in-known-hosts:", + shopt=dict(nullglob=True), + ) + def test_remote_path_with_nullglob(self, completion): + assert not completion + + @pytest.mark.complete( + "scp hostname-not-expected-to-exist-in-known-hosts:", + shopt=dict(failglob=True), + ) + def test_remote_path_with_failglob(self, completion): + assert not completion diff --git a/test/t/test_secret_tool.py b/test/t/test_secret_tool.py index cbfc0cb..7791446 100644 --- a/test/t/test_secret_tool.py +++ b/test/t/test_secret_tool.py @@ -1,7 +1,7 @@ import pytest -@pytest.mark.bashcomp(cmd="secret-tool",) +@pytest.mark.bashcomp(cmd="secret-tool") class TestSecretTool: @pytest.mark.complete("secret-tool ", require_cmd=True) def test_modes(self, completion): @@ -9,4 +9,4 @@ class TestSecretTool: @pytest.mark.complete("secret-tool search ") def test_no_complete(self, completion): - assert not completion + assert completion == "--all --unlock".split() diff --git a/test/t/test_service.py b/test/t/test_service.py index 7ce4312..8e7fb05 100644 --- a/test/t/test_service.py +++ b/test/t/test_service.py @@ -1,7 +1,13 @@ +import sys + import pytest class TestService: + @pytest.mark.xfail( + sys.platform == "darwin", + reason="Service completion not available on macOS", + ) @pytest.mark.complete("service ") def test_1(self, completion): assert completion diff --git a/test/t/test_sha224sum.py b/test/t/test_sha224sum.py new file mode 100644 index 0000000..c6b6138 --- /dev/null +++ b/test/t/test_sha224sum.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSha224sum: + @pytest.mark.complete("sha224sum --", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_sha256sum.py b/test/t/test_sha256sum.py new file mode 100644 index 0000000..c8df94c --- /dev/null +++ b/test/t/test_sha256sum.py @@ -0,0 +1,15 @@ +import pytest + + +class TestSha256sum: + @pytest.mark.complete("sha256sum --", require_longopt=True) + def test_options(self, completion): + assert completion + + @pytest.mark.complete("sha256sum ", cwd="sha256sum") + def test_summing(self, completion): + assert completion == "foo" + + @pytest.mark.complete("sha256sum -c ", cwd="sha256sum") + def test_checking(self, completion): + assert completion == "foo.sha256" diff --git a/test/t/test_sha384sum.py b/test/t/test_sha384sum.py new file mode 100644 index 0000000..903ee8c --- /dev/null +++ b/test/t/test_sha384sum.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSha384sum: + @pytest.mark.complete("sha384sum --", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_sha512sum.py b/test/t/test_sha512sum.py new file mode 100644 index 0000000..746e64e --- /dev/null +++ b/test/t/test_sha512sum.py @@ -0,0 +1,7 @@ +import pytest + + +class TestSha512sum: + @pytest.mark.complete("sha512sum --", require_longopt=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_ssh.py b/test/t/test_ssh.py index 8e95819..f714d99 100644 --- a/test/t/test_ssh.py +++ b/test/t/test_ssh.py @@ -10,8 +10,12 @@ class TestSsh: @pytest.mark.complete("ssh -F config ls", cwd="ssh") def test_2(self, completion): - """Should complete both commands and hostname.""" - assert all(x in completion for x in "ls ls_known_host".split()) + """ + Should not complete commands when host is not specified. + + Test sanity assumes there are commands starting with `ls`. + """ + assert completion == "_known_host" @pytest.mark.complete("ssh bash", cwd="ssh") def test_3(self, completion): @@ -58,3 +62,8 @@ class TestSsh: def test_protocol_option_bundling(self, bash, protocol): completion = assert_complete(bash, "ssh -%sF ssh/" % protocol) assert "config" in completion + + @pytest.mark.complete("ssh -F config -o ForwardX11=yes ls", cwd="ssh") + def test_options_with_args_and_arg_counting(self, completion): + """Options with arguments should not confuse arg counting.""" + assert completion == "_known_host" diff --git a/test/t/test_ssh_add.py b/test/t/test_ssh_add.py index 7e49372..cec12c7 100644 --- a/test/t/test_ssh_add.py +++ b/test/t/test_ssh_add.py @@ -15,3 +15,23 @@ class TestSshAdd: ) def test_2(self, completion): assert completion + + @pytest.mark.complete( + "ssh-add -", + require_cmd=True, + xfail="ssh-add --help 2>&1 | " + "command grep -qiF 'Could not open a connection'", + shopt=dict(failglob=True), + ) + def test_2_failglob(self, completion): + assert completion + + @pytest.mark.complete( + "ssh-add -", + require_cmd=True, + xfail="ssh-add --help 2>&1 | " + "command grep -qiF 'Could not open a connection'", + shopt=dict(nullglob=True), + ) + def test_2_nullglob(self, completion): + assert completion diff --git a/test/t/test_ssh_copy_id.py b/test/t/test_ssh_copy_id.py index e38e901..327ee7c 100644 --- a/test/t/test_ssh_copy_id.py +++ b/test/t/test_ssh_copy_id.py @@ -8,7 +8,7 @@ import pytest # identities are found. Try to make sure there is at least one. "HOME=$PWD/ssh-copy-id", ), - ignore_env=r"^[+-]_scp_path_esc=", + ignore_env=r"^[+-]_comp_cmd_scp__path_esc=", ) class TestSshCopyId: @pytest.mark.complete("ssh-copy-id -", require_cmd=True) diff --git a/test/t/test_ssh_keygen.py b/test/t/test_ssh_keygen.py index b773ab4..cc6ff4e 100644 --- a/test/t/test_ssh_keygen.py +++ b/test/t/test_ssh_keygen.py @@ -7,6 +7,18 @@ class TestSshKeygen: def test_1(self, completion): assert completion + @pytest.mark.complete( + "ssh-keygen -", require_cmd=True, shopt=dict(failglob=True) + ) + def test_1_failglob(self, completion): + assert completion + + @pytest.mark.complete( + "ssh-keygen -", require_cmd=True, shopt=dict(nullglob=True) + ) + def test_1_nullglob(self, completion): + assert completion + @pytest.mark.complete("ssh-keygen -s foo_key ssh-copy-id/.ssh/") def test_filedir_pub_at_end_of_s(self, completion): assert completion @@ -15,13 +27,11 @@ class TestSshKeygen: @pytest.mark.complete("ssh-keygen -s foo_key -n foo,") def test_usernames_for_n(self, completion): assert completion - assert not any("," in x for x in completion) # TODO check that these are usernames @pytest.mark.complete("ssh-keygen -s foo_key -h -n foo,") def test_host_for_h_n(self, completion): assert completion - assert not any("," in x for x in completion) # TODO check that these are hostnames @pytest.mark.complete("ssh-keygen -Y foo -n ") @@ -57,3 +67,19 @@ class TestSshKeygen: @pytest.mark.complete("ssh-keygen -O unknown=") def test_O_unknown(self, completion): assert not completion + + @pytest.mark.complete("ssh-keygen -O application=") + def test_O_application(self, completion): + assert completion == "ssh:" + + @pytest.mark.complete("ssh-keygen -O application=s") + def test_O_application_s(self, completion): + assert completion == "sh:" + + @pytest.mark.complete("ssh-keygen -O application=ssh:") + def test_O_application_ssh_colon(self, completion): + assert not completion + + @pytest.mark.complete("ssh-keygen -O application=nonexistent") + def test_O_application_nonexistent(self, completion): + assert not completion diff --git a/test/t/test_ssh_keyscan.py b/test/t/test_ssh_keyscan.py new file mode 100644 index 0000000..ee65832 --- /dev/null +++ b/test/t/test_ssh_keyscan.py @@ -0,0 +1,19 @@ +import pytest + + +@pytest.mark.bashcomp( + cmd="ssh-keyscan", +) +class TestSshKeyscan: + @pytest.mark.complete("ssh-keyscan ") + def test_basic(self, completion): + assert completion + + @pytest.mark.complete("ssh-keyscan -", require_cmd=True) + def test_options(self, completion): + assert completion + + @pytest.mark.complete("ssh-keyscan -t rsa,", require_cmd=True) + def test_type_delimited(self, completion): + assert completion + assert "rsa" not in completion diff --git a/test/t/test_sshfs.py b/test/t/test_sshfs.py index 44daed3..cb4189b 100644 --- a/test/t/test_sshfs.py +++ b/test/t/test_sshfs.py @@ -1,7 +1,7 @@ import pytest -@pytest.mark.bashcomp(ignore_env=r"^[+-]_scp_path_esc=") +@pytest.mark.bashcomp(ignore_env=r"^[+-]_comp_cmd_scp__path_esc=") class TestSshfs: @pytest.mark.complete("sshfs ./") def test_1(self, completion): diff --git a/test/t/test_su.py b/test/t/test_su.py index 9aa064d..d71d6e1 100644 --- a/test/t/test_su.py +++ b/test/t/test_su.py @@ -6,6 +6,8 @@ class TestSu: def test_1(self, completion): assert completion - @pytest.mark.complete("su -", require_cmd=True) + @pytest.mark.complete( + "su -", require_cmd=True, skipif="[[ $OSTYPE != *linux* ]]" + ) def test_2(self, completion): assert completion diff --git a/test/t/test_sudo.py b/test/t/test_sudo.py index a349466..a7d67de 100644 --- a/test/t/test_sudo.py +++ b/test/t/test_sudo.py @@ -1,6 +1,6 @@ import pytest -from conftest import assert_complete +from conftest import assert_bash_exec, assert_complete class TestSudo: @@ -8,9 +8,9 @@ class TestSudo: def test_1(self, completion): assert completion - @pytest.mark.complete("sudo cd fo", cwd="shared/default") + @pytest.mark.complete("sudo cd foo", cwd="shared/default") def test_2(self, completion): - assert completion == "o.d/" + assert completion == ".d/" assert not completion.endswith(" ") @pytest.mark.complete("sudo sh share") @@ -81,3 +81,7 @@ class TestSudo: part, _ = part_full_group completion = assert_complete(bash, "sudo chown foo:bar:%s" % part) assert not completion + + def test_12(self, bash): + assert_complete(bash, 'sudo "/tmp/aaa bbb" ') + assert_bash_exec(bash, "! complete -p aaa", want_output=None) diff --git a/test/t/test_sum.py b/test/t/test_sum.py index bfb2cf4..2060370 100644 --- a/test/t/test_sum.py +++ b/test/t/test_sum.py @@ -6,6 +6,6 @@ class TestSum: def test_1(self, completion): assert completion - @pytest.mark.complete("sum -", require_longopt=True) + @pytest.mark.complete("sum --", require_longopt=True) def test_options(self, completion): assert completion diff --git a/test/t/test_synclient.py b/test/t/test_synclient.py index 8a31a65..8ce66f6 100644 --- a/test/t/test_synclient.py +++ b/test/t/test_synclient.py @@ -2,7 +2,6 @@ import pytest class TestSynclient: - # synclient -l may error out with e.g. # "Couldn't find synaptics properties. No synaptics driver loaded?" @pytest.mark.complete( diff --git a/test/t/test_tar.py b/test/t/test_tar.py index 4518d0b..2616446 100644 --- a/test/t/test_tar.py +++ b/test/t/test_tar.py @@ -5,7 +5,7 @@ import pytest from conftest import assert_bash_exec -@pytest.mark.bashcomp(ignore_env=r"^-declare -f _tar$") +@pytest.mark.bashcomp(ignore_env=r"^-declare -f _comp_cmd_tar$") class TestTar: @pytest.fixture(scope="class") def gnu_tar(self, bash): @@ -13,8 +13,8 @@ class TestTar: if not re.search(r"\bGNU ", got): pytest.skip("Not GNU tar") - @pytest.mark.complete("tar ") - def test_1(self, completion): + @pytest.mark.complete("tar ", shopt=dict(failglob=True)) + def test_1(self, bash, completion): assert completion # Test "f" when mode is not as first option diff --git a/test/t/test_time.py b/test/t/test_time.py index 231f14e..f2049d5 100644 --- a/test/t/test_time.py +++ b/test/t/test_time.py @@ -4,9 +4,15 @@ import pytest class TestTime: - @pytest.mark.complete("time set") - def test_1(self, completion): - assert completion + @pytest.mark.complete("time _comp_delimite", cwd="shared/empty_dir") + def test_command(self, completion): + """ + Test completion of commands. + + We use a function of ours as the test subject, as that's guaranteed + to be available, and do not rely on anything in particular in $PATH. + """ + assert completion == "d" or "_comp_delimited" in completion @pytest.mark.complete("time -p find -typ") def test_2(self, completion): diff --git a/test/t/test_tox.py b/test/t/test_tox.py index f012a03..b101b9b 100644 --- a/test/t/test_tox.py +++ b/test/t/test_tox.py @@ -2,7 +2,7 @@ import pytest class TestTox: - @pytest.mark.complete("tox -") + @pytest.mark.complete("tox -", require_cmd=True) def test_1(self, completion): assert completion @@ -12,7 +12,7 @@ class TestTox: @pytest.mark.complete("tox -e foo,", cwd="tox") def test_3(self, completion): - assert all(x in completion for x in "py37 ALL".split()) + assert all("foo," + x in completion for x in "py37 ALL".split()) @pytest.mark.complete("tox -e foo -- ", cwd="tox") def test_default_after_dashdash(self, completion): diff --git a/test/t/test_tree.py b/test/t/test_tree.py new file mode 100644 index 0000000..214e415 --- /dev/null +++ b/test/t/test_tree.py @@ -0,0 +1,23 @@ +import pytest + + +class TestTree: + @pytest.mark.complete("tree ", cwd="shared/default") + def test_basic(self, completion): + assert completion == ["bar bar.d/", "foo.d/"] + + @pytest.mark.complete("tree --fromfile ", cwd="shared/default") + def test_fromfile(self, completion): + assert completion == ["bar", "bar bar.d/", "foo", "foo.d/"] + + @pytest.mark.complete( + "tree -", + require_cmd=True, + xfail="! tree --help 2>&1 | command grep -qF -- ' -'", + ) + def test_options(self, completion): + assert completion + + @pytest.mark.complete("tree --sort=", require_cmd=True) + def test_equals_sign_split(self, completion): + assert completion diff --git a/test/t/test_truncate.py b/test/t/test_truncate.py new file mode 100644 index 0000000..b50baac --- /dev/null +++ b/test/t/test_truncate.py @@ -0,0 +1,11 @@ +import pytest + + +class TestTruncate: + @pytest.mark.complete("truncate ") + def test_basic(self, completion): + assert completion + + @pytest.mark.complete("truncate -", require_cmd=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_tshark.py b/test/t/test_tshark.py index f49533e..d44e62d 100644 --- a/test/t/test_tshark.py +++ b/test/t/test_tshark.py @@ -1,7 +1,7 @@ import pytest -@pytest.mark.bashcomp(ignore_env=r"^\+_tshark_pr(ef|otocol)s=") +@pytest.mark.bashcomp(ignore_env=r"^\+_comp_cmd_tshark__pr(ef|otocol)s=") class TestTshark: @pytest.mark.complete("tshark -", require_cmd=True) def test_1(self, completion): @@ -14,7 +14,7 @@ class TestTshark: @pytest.mark.complete("tshark -O foo,htt", require_cmd=True) def test_3(self, completion): # p: one completion only; http: e.g. http and http2 - assert completion == "p" or "http" in completion + assert completion == "p" or "foo,http" in completion @pytest.mark.complete("tshark -o tcp", require_cmd=True) def test_4(self, completion): diff --git a/test/t/test_ulimit.py b/test/t/test_ulimit.py index 3ab974c..271b6ce 100644 --- a/test/t/test_ulimit.py +++ b/test/t/test_ulimit.py @@ -1,10 +1,12 @@ import pytest +from conftest import assert_complete + class TestUlimit: @pytest.mark.complete("ulimit ") def test_1(self, completion): - assert completion + assert not completion @pytest.mark.complete("ulimit -", require_cmd=True) def test_2(self, completion): @@ -33,3 +35,13 @@ class TestUlimit: def test_7(self, completion): """Test modes are NOT completed with -a given somewhere.""" assert not completion + + @pytest.mark.parametrize("flag", ["-S", "-H"]) + def test_no_special_values_after_soft_or_hard(self, bash, flag): + completion = assert_complete(bash, "ulimit %s " % flag) + assert not completion + + @pytest.mark.complete("ulimit -c 0 -n ") + def test_special_not_just_first(self, completion): + """Test we offer limit values not only for the first option.""" + assert completion diff --git a/test/t/test_umount.py b/test/t/test_umount.py index 2baf0da..de18835 100644 --- a/test/t/test_umount.py +++ b/test/t/test_umount.py @@ -1,3 +1,5 @@ +import sys + import pytest from conftest import assert_bash_exec @@ -11,12 +13,14 @@ class TestUmount: (correctly) uses absolute paths. So we create a custom completion which reads from a file in our text fixture instead. """ + if sys.platform != "linux": + pytest.skip("Linux specific") assert_bash_exec(bash, "unset COMPREPLY cur; unset -f _mnt_completion") assert_bash_exec( bash, "_mnt_completion() { " - "local cur=$(_get_cword); " - "_linux_fstab $(_get_pword) < mount/test-fstab; " + "local cur prev;_comp_get_words cur prev; " + '_comp_cmd_umount__linux_fstab "$prev" < mount/test-fstab; ' "} && complete -F _mnt_completion _mnt", ) request.addfinalizer( @@ -75,9 +79,10 @@ class TestUmount: def test_mnt_label_quote(self, completion, dummy_mnt): assert completion == r"ian-it\'s\ awesome" + @pytest.mark.skipif(sys.platform != "linux", reason="Linux specific") def test_linux_fstab_unescape(self, bash): assert_bash_exec(bash, r"var=one\'two\\040three\\") - assert_bash_exec(bash, "__linux_fstab_unescape var") + assert_bash_exec(bash, "_comp_cmd_umount__linux_fstab_unescape var") output = assert_bash_exec( bash, r'printf "%s\n" "$var"', want_output=True ) diff --git a/test/t/test_upgradepkg.py b/test/t/test_upgradepkg.py index 87fe8e4..8411333 100644 --- a/test/t/test_upgradepkg.py +++ b/test/t/test_upgradepkg.py @@ -12,8 +12,8 @@ class TestUpgradepkg: @pytest.mark.complete("upgradepkg --") def test_2(self, completion): assert ( - completion == "--dry-run --install-new --reinstall " - "--verbose".split() + completion + == "--dry-run --install-new --reinstall --verbose".split() ) @pytest.mark.complete("upgradepkg ", cwd="slackware/home") diff --git a/test/t/test_useradd.py b/test/t/test_useradd.py index 5cbf6ce..2eddede 100644 --- a/test/t/test_useradd.py +++ b/test/t/test_useradd.py @@ -9,3 +9,7 @@ class TestUseradd: @pytest.mark.complete("useradd -", require_cmd=True) def test_2(self, completion): assert completion + + @pytest.mark.complete("useradd -R shells --shell=") + def test_chroot_shells(self, completion): + assert completion == "/bash/completion/canary" diff --git a/test/t/test_usermod.py b/test/t/test_usermod.py index ef3dd5a..61c99a0 100644 --- a/test/t/test_usermod.py +++ b/test/t/test_usermod.py @@ -9,3 +9,7 @@ class TestUsermod: @pytest.mark.complete("usermod -", require_cmd=True) def test_2(self, completion): assert completion + + @pytest.mark.complete("useradd --root shells -s ") + def test_chroot_shells(self, completion): + assert completion == "/bash/completion/canary" diff --git a/test/t/test_valgrind.py b/test/t/test_valgrind.py index 0553b55..dbe7028 100644 --- a/test/t/test_valgrind.py +++ b/test/t/test_valgrind.py @@ -4,7 +4,6 @@ import pytest class TestValgrind: - # b: Assume we have at least bash that starts with b in PATH @pytest.mark.complete("valgrind b") def test_1(self, completion): diff --git a/test/t/test_vipw.py b/test/t/test_vipw.py index 07b454b..b78fcbd 100644 --- a/test/t/test_vipw.py +++ b/test/t/test_vipw.py @@ -1,7 +1,12 @@ +import sys + import pytest class TestVipw: @pytest.mark.complete("vipw -", require_cmd=True) def test_1(self, completion): - assert completion + if sys.platform == "darwin": + assert not completion # takes no options + else: + assert completion diff --git a/test/t/test_vncviewer.py b/test/t/test_vncviewer.py index 9e2f148..643d98d 100644 --- a/test/t/test_vncviewer.py +++ b/test/t/test_vncviewer.py @@ -1,7 +1,9 @@ import pytest -@pytest.mark.bashcomp(ignore_env=r"^-declare -f _vncviewer_bootstrap$") +@pytest.mark.bashcomp( + ignore_env=r"^-declare -f _comp_cmd_vncviewer__bootstrap$" +) class TestVncviewer: @pytest.mark.complete("vncviewer ") def test_1(self, completion): diff --git a/test/t/test_who.py b/test/t/test_who.py index 9131ac7..69b93c9 100644 --- a/test/t/test_who.py +++ b/test/t/test_who.py @@ -2,8 +2,6 @@ import pytest class TestWho: - @pytest.mark.complete( - "who --", require_cmd=True, xfail="! who --help &>/dev/null" - ) + @pytest.mark.complete("who --", require_longopt=True) def test_1(self, completion): assert completion diff --git a/test/t/test_wine.py b/test/t/test_wine.py index d0e5698..e18ea1c 100644 --- a/test/t/test_wine.py +++ b/test/t/test_wine.py @@ -9,3 +9,7 @@ class TestWine: @pytest.mark.complete("wine notepad ", cwd="shared/default") def test_2(self, completion): assert completion == ["bar", "bar bar.d/", "foo", "foo.d/"] + + @pytest.mark.complete("wine --help ") + def test_no_complete_after_help(self, completion): + assert not completion diff --git a/test/t/test_xdg_mime.py b/test/t/test_xdg_mime.py index 432be06..b91e75a 100644 --- a/test/t/test_xdg_mime.py +++ b/test/t/test_xdg_mime.py @@ -19,10 +19,14 @@ class TestXdgMime: def test_4(self, completion): assert completion - @pytest.mark.complete("xdg-mime default foo.desktop ") + @pytest.mark.complete("xdg-mime default foo.desktop ", require_cmd=True) def test_5(self, completion): assert completion @pytest.mark.complete("xdg-mime install --mode ") def test_6(self, completion): assert completion + + @pytest.mark.complete("xdg-mime query filetype foo ") + def test_filetype_one_arg(self, completion): + assert not completion diff --git a/test/t/test_xev.py b/test/t/test_xev.py new file mode 100644 index 0000000..3ced4e0 --- /dev/null +++ b/test/t/test_xev.py @@ -0,0 +1,11 @@ +import pytest + + +class TestXev: + @pytest.mark.complete("xev ") + def test_basic(self, completion): + assert not completion + + @pytest.mark.complete("xev -", require_cmd=True) + def test_options(self, completion): + assert completion diff --git a/test/t/test_xfreerdp.py b/test/t/test_xfreerdp.py index 5616271..3dce4ad 100644 --- a/test/t/test_xfreerdp.py +++ b/test/t/test_xfreerdp.py @@ -42,7 +42,7 @@ class TestXfreerdp: @pytest.mark.complete( "xfreerdp /kbd:", require_cmd=True, - skipif='test -z "$(xfreerdp /kbd-list 2>/dev/null)"', + skipif='test ! "$(xfreerdp /kbd-list 2>/dev/null)"', ) def test_4(self, bash, completion, help_success, slash_syntax): assert completion @@ -58,3 +58,7 @@ class TestXfreerdp: @pytest.mark.complete("xfreerdp --help ", require_cmd=True) def test_7(self, completion): assert not completion + + @pytest.mark.complete("xfreerdp ./") + def test_rdp_files(self, completion): + assert completion # just dirs for now in the fixture, but that'll do diff --git a/test/t/test_xhost.py b/test/t/test_xhost.py index bb2df82..b704b9c 100644 --- a/test/t/test_xhost.py +++ b/test/t/test_xhost.py @@ -8,15 +8,13 @@ class TestXhost: @pytest.mark.parametrize("prefix", ["+", "-", ""]) def test_hosts(self, bash, hosts, prefix): completion = assert_complete(bash, "xhost %s" % prefix) - assert completion == ["%s%s" % (prefix, x) for x in hosts] + assert completion == [f"{prefix}{x}" for x in hosts] @pytest.mark.parametrize("prefix", ["+", "-", ""]) def test_partial_hosts(self, bash, hosts, prefix): first_char, partial_hosts = partialize(bash, hosts) - completion = assert_complete(bash, "xhost %s%s" % (prefix, first_char)) + completion = assert_complete(bash, f"xhost {prefix}{first_char}") if len(completion) == 1: assert completion == partial_hosts[0][1:] else: - assert completion == sorted( - "%s%s" % (prefix, x) for x in partial_hosts - ) + assert completion == sorted(f"{prefix}{x}" for x in partial_hosts) diff --git a/test/t/test_xmlwf.py b/test/t/test_xmlwf.py index 901f78a..eab9894 100644 --- a/test/t/test_xmlwf.py +++ b/test/t/test_xmlwf.py @@ -9,3 +9,7 @@ class TestXmlwf: @pytest.mark.complete("xmlwf -", require_cmd=True) def test_2(self, completion): assert completion + + @pytest.mark.complete("xmlwf -sa ") + def test_no_arg_to_a(self, completion): + assert not completion diff --git a/test/t/test_xrandr.py b/test/t/test_xrandr.py index e766922..8d8a6bc 100644 --- a/test/t/test_xrandr.py +++ b/test/t/test_xrandr.py @@ -1,15 +1,122 @@ import pytest +ENV = dict(PATH="$PWD/xrandr:$PATH") +OUTPUTS = sorted("DP-0 DP-1 DP-2 DP-3 eDP-1-1 HDMI-0".split()) + +@pytest.mark.bashcomp(pre_cmds=("PATH=$PATH:$PWD/xrandr",)) class TestXrandr: @pytest.mark.complete("xrandr ", require_cmd=True) - def test_1(self, completion): + def test_no_args(self, completion): assert completion - @pytest.mark.complete("xrandr --mode ") - def test_2(self, completion): - assert not completion - @pytest.mark.complete("xrandr -", require_cmd=True) - def test_3(self, completion): + def test_single_dash(self, completion): assert completion + + @pytest.mark.complete("xrandr --output ", env=ENV) + def test_output(self, completion): + assert completion == OUTPUTS + + @pytest.mark.complete("xrandr --output HDMI-0 --left-of ", env=ENV) + def test_output_left_of(self, completion): + assert completion == OUTPUTS + + @pytest.mark.complete("xrandr --output HDMI-0 --reflect ", env=ENV) + def test_output_reflect(self, completion): + assert completion == sorted("normal x y xy".split()) + + @pytest.mark.complete("xrandr --reflect ", require_cmd=True) + def test_output_reflect_nooutput(self, completion): + assert not completion + + @pytest.mark.complete("xrandr --output HDMI-0 --rotate ", env=ENV) + def test_output_rotate(self, completion): + assert completion == sorted("normal inverted left right".split()) + + @pytest.mark.complete("xrandr --rotate ", require_cmd=True) + def test_output_rotate_nooutput(self, completion): + assert not completion + + @pytest.mark.complete("xrandr --output HDMI-0 --filter ", env=ENV) + def test_output_filter(self, completion): + assert completion == sorted("bilinear nearest".split()) + + @pytest.mark.complete("xrandr --output HDMI-0 --mode ", env=ENV) + def test_output_mode(self, completion): + assert completion == sorted( + "1024x768 1280x1024 1280x800 1600x900 1920x1080 720x480 " + "800x600 1152x864 1280x720 1440x900 1680x1050 640x480 720x576".split() + ) + + @pytest.mark.complete("xrandr --mode ", require_cmd=True) + def test_output_mode_nooutput(self, completion): + assert not completion + + @pytest.mark.complete("xrandr --addmode ", env=ENV) + def test_addmode_first(self, completion): + assert completion == OUTPUTS + + @pytest.mark.complete("xrandr --addmode HDMI-0 ", env=ENV) + def test_addmode_second(self, completion): + assert completion == sorted( + "1024x576 1280x800 1440x900 320x200 432x243 640x350 700x450 800x450 928x696 " + "1024x768 1280x960 1600x900 320x240 480x270 640x360 700x525 800x600 960x540 " + "1024x768i 1368x768 1680x1050 360x200 512x288 640x400 720x400 832x624 960x600 " + "1152x864 1400x1050 1920x1080 360x202 512x384 640x480 720x405 840x525 960x720 " + "1280x1024 1400x900 320x175 400x300 512x384i 640x512 720x480 864x486 " + "1280x720 1440x810 320x180 416x312 576x432 684x384 720x576 896x672".split() + ) + + @pytest.mark.complete("xrandr --delmode ", env=ENV) + def test_delmode_first(self, completion): + assert completion == OUTPUTS + + @pytest.mark.complete("xrandr --delmode HDMI-0 ", env=ENV) + def test_delmode_second(self, completion): + assert completion == sorted( + "1024x768 1280x1024 1280x800 1600x900 1920x1080 720x480 " + "800x600 1152x864 1280x720 1440x900 1680x1050 640x480 720x576".split() + ) + + @pytest.mark.complete("xrandr --dpi ", env=ENV) + def test_dpi(self, completion): + assert completion == OUTPUTS + + @pytest.mark.complete("xrandr -o ", env=ENV) + def test_orientation(self, completion): + assert completion == sorted( + "normal inverted left right 0 1 2 3".split() + ) + + @pytest.mark.complete("xrandr --setmonitor testmonitor ", env=ENV) + def test_setmonitor_second(self, completion): + assert completion == sorted("auto".split()) + + @pytest.mark.complete("xrandr --setmonitor testmonitor auto ", env=ENV) + def test_setmonitor_third(self, completion): + assert completion == OUTPUTS + ["none"] + + @pytest.mark.complete("xrandr --delmonitor ", env=ENV) + def test_delmonitor(self, completion): + assert completion == sorted("eDP-1-1 HDMI-0".split()) + + @pytest.mark.complete("xrandr --setprovideroutputsource ", env=ENV) + def test_setprovideroutputsource_first(self, completion): + assert completion == sorted("modesetting".split()) + + @pytest.mark.complete( + "xrandr --setprovideroutputsource modesetting ", env=ENV + ) + def test_setprovideroutputsource_second(self, completion): + assert completion == sorted("0x0 modesetting NVIDIA-0".split()) + + @pytest.mark.complete("xrandr --setprovideroffloadsink ", env=ENV) + def test_setprovideroffloadsink_first(self, completion): + assert completion == sorted("modesetting".split()) + + @pytest.mark.complete( + "xrandr --setprovideroffloadsink modesetting ", env=ENV + ) + def test_setprovideroffloadsink_second(self, completion): + assert completion == sorted("0x0 modesetting".split()) diff --git a/test/t/test_xz.py b/test/t/test_xz.py index f226d02..8ecb1a0 100644 --- a/test/t/test_xz.py +++ b/test/t/test_xz.py @@ -9,8 +9,9 @@ class TestXz: @pytest.mark.complete("xz -d xz/") def test_2(self, completion): assert ( - completion == "a/ bashcomp.lzma bashcomp.tar.xz " - "bashcomp.tlz bashcomp.xz".split() + completion + == "a/ bashcomp.lzma bashcomp.tar.xz bashcomp.tlz " + "bashcomp.xz".split() ) @pytest.mark.complete("xz xz/") diff --git a/test/t/unit/Makefile.am b/test/t/unit/Makefile.am index 3eb652a..54722de 100644 --- a/test/t/unit/Makefile.am +++ b/test/t/unit/Makefile.am @@ -1,21 +1,38 @@ EXTRA_DIST = \ + test_unit_abspath.py \ + test_unit_command_offset.py \ + test_unit_compgen.py \ + test_unit_compgen_commands.py \ test_unit_count_args.py \ + test_unit_delimited.py \ + test_unit_deprecate_func.py \ + test_unit_dequote.py \ test_unit_expand.py \ - test_unit_expand_tilde_by_ref.py \ + test_unit_expand_glob.py \ + test_unit_expand_tilde.py \ test_unit_filedir.py \ test_unit_find_unique_completion_pair.py \ - test_unit_get_comp_words_by_ref.py \ + test_unit_get_first_arg.py \ test_unit_get_cword.py \ - test_unit_init_completion.py \ + test_unit_get_words.py \ + test_unit_initialize.py \ test_unit_ip_addresses.py \ - test_unit_known_hosts_real.py \ + test_unit_known_hosts.py \ test_unit_longopt.py \ + test_unit_looks_like_path.py \ test_unit_parse_help.py \ test_unit_parse_usage.py \ + test_unit_pgids.py \ + test_unit_pids.py \ + test_unit_pnames.py \ test_unit_quote.py \ - test_unit_quote_readline.py \ + test_unit_quote_compgen.py \ + test_unit_realcommand.py \ + test_unit_split.py \ test_unit_tilde.py \ + test_unit_unlocal.py \ test_unit_variables.py \ + test_unit_xfunc.py \ test_unit_xinetd_services.py all: diff --git a/test/t/unit/test_unit_abspath.py b/test/t/unit/test_unit_abspath.py new file mode 100644 index 0000000..97d506c --- /dev/null +++ b/test/t/unit/test_unit_abspath.py @@ -0,0 +1,67 @@ +import pytest + +from conftest import assert_bash_exec + + +@pytest.mark.bashcomp( + cmd=None, cwd="shared", ignore_env=r"^\+declare -f __tester$" +) +class TestUnitAbsPath: + @pytest.fixture + def functions(self, bash): + assert_bash_exec( + bash, + ( + "__tester() { " + "local REPLY; " + '_comp_abspath "$1"; ' + 'printf %s "$REPLY"; ' + "}" + ), + ) + + def test_non_pollution(self, bash): + """Test environment non-pollution, detected at teardown.""" + assert_bash_exec( + bash, + "foo() { local REPLY=; _comp_abspath bar; }; foo; unset -f foo", + want_output=None, + ) + + def test_absolute(self, bash, functions): + output = assert_bash_exec( + bash, + "__tester /foo/bar", + want_output=True, + want_newline=False, + ) + assert output.strip() == "/foo/bar" + + def test_relative(self, bash, functions): + output = assert_bash_exec( + bash, + "__tester foo/bar", + want_output=True, + want_newline=False, + ) + assert output.strip().endswith("/shared/foo/bar") + + def test_cwd(self, bash, functions): + output = assert_bash_exec( + bash, + "__tester ./foo/./bar", + want_output=True, + want_newline=False, + ) + assert output.strip().endswith("/shared/foo/bar") + + def test_parent(self, bash, functions): + output = assert_bash_exec( + bash, + "__tester ../shared/foo/bar", + want_output=True, + want_newline=False, + ) + assert output.strip().endswith( + "/shared/foo/bar" + ) and not output.strip().endswith("../shared/foo/bar") diff --git a/test/t/unit/test_unit_command_offset.py b/test/t/unit/test_unit_command_offset.py new file mode 100644 index 0000000..0e32c1f --- /dev/null +++ b/test/t/unit/test_unit_command_offset.py @@ -0,0 +1,144 @@ +from shlex import quote + +import pytest + +from conftest import assert_bash_exec, assert_complete, bash_env_saved + + +def join(words): + """Return a shell-escaped string from *words*.""" + return " ".join(quote(word) for word in words) + + +@pytest.mark.bashcomp( + cmd=None, + cwd="_command_offset", + ignore_env=r"^[+-](COMPREPLY|REPLY)=", +) +class TestUnitCommandOffset: + wordlist = sorted(["foo", "bar"]) + + @pytest.fixture(scope="class") + def functions(self, bash): + assert_bash_exec( + bash, + "_cmd1() { _comp_command_offset 1; }; complete -F _cmd1 cmd1; " + "complete -F _comp_command meta; " + "_compfunc() { COMPREPLY=(%s); }" % join(self.wordlist), + ) + + completions = [ + 'complete -F _compfunc "${COMP_WORDS[0]}"', + 'complete -W %s "${COMP_WORDS[0]}"' % quote(join(self.wordlist)), + 'COMPREPLY=(dummy); complete -r "${COMP_WORDS[0]}"', + "COMPREPLY+=(${#COMPREPLY[@]})", + ] + for idx, comp in enumerate(completions, 2): + assert_bash_exec( + bash, + "_cmd%(idx)s() { %(comp)s && return 124; }; " + "complete -F _cmd%(idx)s cmd%(idx)s" + % {"idx": idx, "comp": comp}, + ) + + assert_bash_exec( + bash, "complete -W %s 'cmd!'" % quote(join(self.wordlist)) + ) + assert_bash_exec(bash, 'complete -W \'"$word1" "$word2"\' cmd6') + + assert_bash_exec(bash, "complete -C ./completer cmd7") + + def test_1(self, bash, functions): + assert_complete(bash, 'cmd1 "/tmp/aaa bbb" ') + assert_bash_exec(bash, "! complete -p aaa", want_output=None) + + @pytest.mark.parametrize( + "cmd,expected_completion", + [ + ("cmd2", wordlist), + ("cmd3", wordlist), + ("cmd4", []), + ("cmd5", ["0"]), + ], + ) + def test_2(self, bash, functions, cmd, expected_completion): + """Test meta-completion for completion functions that signal that + completion should be retried (i.e. change compspec and return 124). + + cmd2: The case when the completion spec is overwritten by the one that + contains "-F func" + + cmd3: The case when the completion spec is overwritten by the one + without "-F func". + + cmd4: The case when the completion spec is removed, in which we expect + no completions. This mimics the behavior of Bash's progcomp for the + exit status 124. + + cmd5: The case when the completion spec is unchanged. The retry should + be attempted at most once to avoid infinite loops. COMPREPLY should be + cleared before the retry. + """ + assert assert_complete(bash, "meta %s " % cmd) == expected_completion + + @pytest.mark.parametrize( + "cmd,expected_completion", + [ + ("cmd7 ", wordlist), + ("cmd7 l", ["line\\^Jtwo", "long"]), + ("cmd7 lo", ["ng"]), + ("cmd7 line", ["\\^Jtwo"]), + ("cmd7 cont1", ["cont10", "cont11\\"]), + ], + ) + def test_3(self, bash, functions, cmd, expected_completion): + got = assert_complete(bash, f"cmd1 {cmd}") + assert got == assert_complete(bash, cmd) + assert got == expected_completion + + def test_cmd_quoted(self, bash, functions): + assert assert_complete(bash, "meta 'cmd2' ") == self.wordlist + + def test_cmd_specialchar(self, bash, functions): + assert assert_complete(bash, "meta 'cmd!' ") == self.wordlist + + def test_space(self, bash, functions): + with bash_env_saved(bash) as bash_env: + bash_env.write_variable("word1", "a b c") + bash_env.write_variable("word2", "d e f") + assert assert_complete(bash, "meta cmd6 ") == ["a b c", "d e f"] + + @pytest.fixture(scope="class") + def find_original_word_functions(self, bash): + assert_bash_exec( + bash, + "_comp_test_reassemble() {" + " local IFS=$' \\t\\n' REPLY;" + ' COMP_LINE=$1; _comp_split COMP_WORDS "$2"; COMP_CWORD=$((${#COMP_WORDS[@]}-1));' + " _comp__reassemble_words = words cword;" + "}", + ) + assert_bash_exec( + bash, + "_comp_test_1() {" + ' local COMP_WORDS COMP_LINE COMP_CWORD words cword REPLY; _comp_test_reassemble "$1" "$2";' + ' _comp__find_original_word "$3";' + ' echo "$REPLY";' + "}", + ) + + def test_find_original_word_1(self, bash, find_original_word_functions): + result = assert_bash_exec( + bash, + '_comp_test_1 "sudo su do su do abc" "sudo su do su do abc" 3', + want_output=True, + ).strip() + assert result == "3" + + def test_find_original_word_2(self, bash, find_original_word_functions): + result = assert_bash_exec( + bash, + '_comp_test_1 "sudo --prefix=su su do abc" "sudo --prefix = su su do abc" 2', + want_output=True, + ).strip() + assert result == "4" diff --git a/test/t/unit/test_unit_compgen.py b/test/t/unit/test_unit_compgen.py new file mode 100644 index 0000000..cfdec8e --- /dev/null +++ b/test/t/unit/test_unit_compgen.py @@ -0,0 +1,173 @@ +import pytest +import re + +from conftest import assert_bash_exec, bash_env_saved, assert_complete + + +@pytest.mark.bashcomp(cmd=None) +class TestUtilCompgen: + @pytest.fixture + def functions(self, bash): + assert_bash_exec( + bash, + "_comp__test_dump() { ((${#arr[@]})) && printf '<%s>' \"${arr[@]}\"; echo; }", + ) + assert_bash_exec( + bash, + '_comp__test_compgen() { local -a arr=(00); _comp_compgen -v arr "$@"; _comp__test_dump; }', + ) + assert_bash_exec( + bash, + '_comp__test_words() { local -a input=("${@:1:$#-1}"); _comp__test_compgen -c "${@:$#}" -- -W \'${input[@]+"${input[@]}"}\'; }', + ) + assert_bash_exec( + bash, + '_comp__test_words_ifs() { local input=$2; _comp__test_compgen -F "$1" -c "${@:$#}" -- -W \'$input\'; }', + ) + + assert_bash_exec( + bash, + '_comp_cmd_fc() { _comp_compgen -c "$(_get_cword)" -C _filedir filedir; }; ' + "complete -F _comp_cmd_fc fc; " + "complete -F _comp_cmd_fc -o filenames fc2", + ) + assert_bash_exec( + bash, + '_comp_cmd_fcd() { _comp_compgen -c "$(_get_cword)" -C _filedir filedir -d; }; ' + "complete -F _comp_cmd_fcd fcd", + ) + + # test_8_option_U + assert_bash_exec( + bash, + "_comp_compgen_gen8() { local -a arr=(x y z); _comp_compgen -U arr -- -W '\"${arr[@]}\"'; }", + ) + + # test_9_inherit_a + assert_bash_exec( + bash, + '_comp_compgen_gen9sub() { local -a gen=(00); _comp_compgen -v gen -- -W 11; _comp_compgen_set "${gen[@]}"; }; ' + "_comp_compgen_gen9() { _comp_compgen_gen9sub; _comp_compgen -a gen9sub; }", + ) + + def test_1_basic(self, bash, functions): + output = assert_bash_exec( + bash, "_comp__test_words 12 34 56 ''", want_output=True + ) + assert output.strip() == "<12><34><56>" + + def test_2_space(self, bash, functions): + output = assert_bash_exec( + bash, + "_comp__test_words $'a b' $'c d\\t' ' e ' $'\\tf\\t' ''", + want_output=True, + ) + assert output.strip() == "<a b><c d\t>< e ><\tf\t>" + + def test_2_IFS(self, bash, functions): + with bash_env_saved(bash) as bash_env: + bash_env.write_variable("IFS", "34") + output = assert_bash_exec( + bash, "_comp__test_words 12 34 56 ''", want_output=True + ) + assert output.strip() == "<12><34><56>" + + def test_3_glob(self, bash, functions): + output = assert_bash_exec( + bash, + "_comp__test_words '*' '[a-z]*' '[a][b][c]' ''", + want_output=True, + ) + assert output.strip() == "<*><[a-z]*><[a][b][c]>" + + def test_3_failglob(self, bash, functions): + with bash_env_saved(bash) as bash_env: + bash_env.shopt("failglob", True) + output = assert_bash_exec( + bash, + "_comp__test_words '*' '[a-z]*' '[a][b][c]' ''", + want_output=True, + ) + assert output.strip() == "<*><[a-z]*><[a][b][c]>" + + def test_3_nullglob(self, bash, functions): + with bash_env_saved(bash) as bash_env: + bash_env.shopt("nullglob", True) + output = assert_bash_exec( + bash, + "_comp__test_words '*' '[a-z]*' '[a][b][c]' ''", + want_output=True, + ) + assert output.strip() == "<*><[a-z]*><[a][b][c]>" + + def test_4_empty(self, bash, functions): + output = assert_bash_exec( + bash, "_comp__test_words ''", want_output=True + ) + assert output.strip() == "" + + def test_5_option_F(self, bash, functions): + output = assert_bash_exec( + bash, + "_comp__test_words_ifs '25' ' 123 456 555 ' ''", + want_output=True, + ) + assert output.strip() == "< 1><3 4><6 >< >" + + def test_6_option_C_1(self, bash, functions): + output = assert_bash_exec( + bash, + "_comp__test_compgen -c a -C _filedir filedir", + want_output=True, + ) + set1 = set(re.findall(r"<[^<>]*>", output.strip())) + assert set1 == {"<a b>", "<a$b>", "<a&b>", "<a'b>", "<ab>", "<aé>"} + + def test_6_option_C_2(self, bash, functions): + output = assert_bash_exec( + bash, + "_comp__test_compgen -c b -C _filedir -- -d", + want_output=True, + ) + assert output.strip() == "<brackets>" + + @pytest.mark.parametrize("funcname", "fc fc2".split()) + def test_6_option_C_3(self, bash, functions, funcname): + completion = assert_complete(bash, "%s _filedir ab/" % funcname) + assert completion == "e" + + @pytest.mark.complete(r"fcd a\ ") + def test_6_option_C_4(self, functions, completion): + # Note: we are not in the original directory that "b" exists, so Bash + # will not suffix a slash to the directory name. + assert completion == "b" + + def test_7_icmd(self, bash, functions): + with bash_env_saved(bash) as bash_env: + bash_env.write_variable( + "BASH_COMPLETION_USER_DIR", "$PWD/_comp_compgen", quote=False + ) + + completions = assert_complete(bash, "compgen-cmd1 '") + assert completions == ["012", "123", "234", "5abc", "6def", "7ghi"] + + def test_7_xcmd(self, bash, functions): + with bash_env_saved(bash) as bash_env: + bash_env.write_variable( + "BASH_COMPLETION_USER_DIR", "$PWD/_comp_compgen", quote=False + ) + + completions = assert_complete(bash, "compgen-cmd2 '") + assert completions == ["012", "123", "234", "5foo", "6bar", "7baz"] + + def test_8_option_U(self, bash, functions): + output = assert_bash_exec( + bash, "_comp__test_compgen gen8", want_output=True + ) + assert output.strip() == "<x><y><z>" + + def test_9_inherit_a(self, bash, functions): + output = assert_bash_exec( + bash, "_comp__test_compgen gen9", want_output=True + ) + assert output.strip() == "<11><11>" diff --git a/test/t/unit/test_unit_compgen_commands.py b/test/t/unit/test_unit_compgen_commands.py new file mode 100644 index 0000000..d866239 --- /dev/null +++ b/test/t/unit/test_unit_compgen_commands.py @@ -0,0 +1,47 @@ +import pytest + +from conftest import assert_bash_exec, assert_complete, bash_env_saved + + +@pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+COMPREPLY=") +class TestUtilCompgenCommands: + @pytest.fixture(scope="class") + def functions(self, request, bash): + assert_bash_exec( + bash, + r"_comp_compgen_commands__test() {" + r" local COMPREPLY=() cur=${1-};" + r" _comp_compgen_commands;" + r' printf "%s\n" "${COMPREPLY[@]-}";' + r"}", + ) + assert_bash_exec( + bash, + "_comp_cmd_ccc() {" + " local cur;" + " _comp_get_words cur;" + " unset -v COMPREPLY;" + " _comp_compgen_commands;" + "}; complete -F _comp_cmd_ccc ccc", + ) + + def test_basic(self, bash, functions): + output = assert_bash_exec( + bash, "_comp_compgen_commands__test sh", want_output=True + ) + assert output.strip() + + @pytest.mark.parametrize( + "shopt_no_empty,result_empty", ((True, True), (False, False)) + ) + def test_empty(self, bash, functions, shopt_no_empty, result_empty): + with bash_env_saved(bash) as bash_env: + bash_env.shopt("no_empty_cmd_completion", shopt_no_empty) + output = assert_bash_exec( + bash, "_comp_compgen_commands__test", want_output=True + ) + assert (output.strip() == "") == result_empty + + def test_spaces(self, bash, functions): + completion = assert_complete(bash, "ccc shared/default/bar") + assert completion == r"\ bar.d/" diff --git a/test/t/unit/test_unit_compgen_split.py b/test/t/unit/test_unit_compgen_split.py new file mode 100644 index 0000000..935ea2a --- /dev/null +++ b/test/t/unit/test_unit_compgen_split.py @@ -0,0 +1,102 @@ +import pytest + +from conftest import assert_bash_exec + + +@pytest.mark.bashcomp(cmd=None) +class TestUtilCompgenSplit: + @pytest.fixture + def functions(self, bash): + assert_bash_exec( + bash, + "_comp__test_dump() { ((${#arr[@]})) && printf '<%s>' \"${arr[@]}\"; echo; }", + ) + assert_bash_exec( + bash, + '_comp__test_compgen() { local -a arr=(00); _comp_compgen -v arr "$@"; _comp__test_dump; }', + ) + + assert_bash_exec( + bash, + "_comp__test_cmd1() { echo foo bar; echo baz; }", + ) + assert_bash_exec( + bash, + '_comp__test_attack() { echo "\\$(echo should_not_run >&2)"; }', + ) + + def test_1_basic(self, bash, functions): + output = assert_bash_exec( + bash, + '_comp__test_compgen split -- "$(_comp__test_cmd1)"', + want_output=True, + ) + assert output.strip() == "<foo><bar><baz>" + + def test_2_attack(self, bash, functions): + output = assert_bash_exec( + bash, + '_comp__test_compgen split -- "$(_comp__test_attack)"', + want_output=True, + ) + assert output.strip() == "<$(echo><should_not_run><>&2)>" + + def test_3_sep1(self, bash, functions): + output = assert_bash_exec( + bash, + '_comp__test_compgen split -l -- "$(_comp__test_cmd1)"', + want_output=True, + ) + assert output.strip() == "<foo bar><baz>" + + def test_3_sep2(self, bash, functions): + output = assert_bash_exec( + bash, + "_comp__test_compgen split -F $'b\\n' -- \"$(_comp__test_cmd1)\"", + want_output=True, + ) + assert output.strip() == "<foo ><ar><az>" + + def test_4_optionX(self, bash, functions): + output = assert_bash_exec( + bash, + '_comp__test_compgen split -X bar -- "$(_comp__test_cmd1)"', + want_output=True, + ) + assert output.strip() == "<foo><baz>" + + def test_4_optionS(self, bash, functions): + output = assert_bash_exec( + bash, + '_comp__test_compgen split -S .txt -- "$(_comp__test_cmd1)"', + want_output=True, + ) + assert output.strip() == "<foo.txt><bar.txt><baz.txt>" + + def test_4_optionP(self, bash, functions): + output = assert_bash_exec( + bash, + '_comp__test_compgen split -P /tmp/ -- "$(_comp__test_cmd1)"', + want_output=True, + ) + assert output.strip() == "</tmp/foo></tmp/bar></tmp/baz>" + + def test_4_optionPS(self, bash, functions): + output = assert_bash_exec( + bash, + '_comp__test_compgen split -P [ -S ] -- "$(_comp__test_cmd1)"', + want_output=True, + ) + assert output.strip() == "<[foo]><[bar]><[baz]>" + + def test_5_empty(self, bash, functions): + output = assert_bash_exec( + bash, '_comp__test_compgen split -- ""', want_output=True + ) + assert output.strip() == "" + + def test_5_empty2(self, bash, functions): + output = assert_bash_exec( + bash, '_comp__test_compgen split -- " "', want_output=True + ) + assert output.strip() == "" diff --git a/test/t/unit/test_unit_count_args.py b/test/t/unit/test_unit_count_args.py index 56bce2c..7b018e4 100644 --- a/test/t/unit/test_unit_count_args.py +++ b/test/t/unit/test_unit_count_args.py @@ -4,63 +4,167 @@ from conftest import TestUnitBase, assert_bash_exec @pytest.mark.bashcomp( - cmd=None, ignore_env=r"^[+-](args|COMP_(WORDS|CWORD|LINE|POINT))=" + cmd=None, + ignore_env=r"^[+-](REPLY|cword|words|COMP_(WORDS|CWORD|LINE|POINT))=", ) class TestUnitCountArgs(TestUnitBase): + @pytest.fixture + def functions(self, bash): + assert_bash_exec( + bash, + '_comp__test_unit() { local -a words=(); local cword REPLY=""; _comp__reassemble_words "<>&" words cword; _comp_count_args "$@"; echo "$REPLY"; }', + ) + def _test(self, *args, **kwargs): - return self._test_unit("_count_args %s; echo $args", *args, **kwargs) + return self._test_unit("_comp__test_unit %s", *args, **kwargs) def test_1(self, bash): - assert_bash_exec(bash, "COMP_CWORD= _count_args >/dev/null") + assert_bash_exec( + bash, + 'COMP_LINE= COMP_POINT=0 COMP_WORDS=() COMP_CWORD=; _comp_count_args -n ""', + ) - def test_2(self, bash): + def test_2(self, bash, functions): """a b| should set args to 1""" output = self._test(bash, "(a b)", 1, "a b", 3) assert output == "1" - def test_3(self, bash): + def test_3(self, bash, functions): """a b|c should set args to 1""" output = self._test(bash, "(a bc)", 1, "a bc", 3) assert output == "1" - def test_4(self, bash): + def test_4(self, bash, functions): """a b c| should set args to 2""" output = self._test(bash, "(a b c)", 2, "a b c", 4) assert output == "2" - def test_5(self, bash): + def test_5(self, bash, functions): """a b| c should set args to 1""" output = self._test(bash, "(a b c)", 1, "a b c", 3) assert output == "1" - def test_6(self, bash): + def test_6(self, bash, functions): """a b -c| d should set args to 2""" output = self._test(bash, "(a b -c d)", 2, "a b -c d", 6) assert output == "2" - def test_7(self, bash): + def test_7(self, bash, functions): """a b -c d e| with -c arg excluded should set args to 2""" output = self._test( - bash, "(a b -c d e)", 4, "a b -c d e", 10, arg='"" "@(-c|--foo)"' + bash, "(a b -c d e)", 4, "a b -c d e", 10, arg='-a "@(-c|--foo)"' ) assert output == "2" - def test_8(self, bash): + def test_8(self, bash, functions): """a -b -c d e| with -c arg excluded - and -b included should set args to 1""" + and -b included should set args to 1""" output = self._test( bash, "(a -b -c d e)", 4, "a -b -c d e", 11, - arg='"" "@(-c|--foo)" "-[b]"', + arg='-a "@(-c|--foo)" -i "-[b]"', ) assert output == "2" - def test_9(self, bash): + def test_9(self, bash, functions): """a -b -c d e| with -b included should set args to 3""" output = self._test( - bash, "(a -b -c d e)", 4, "a -b -c d e", 11, arg='"" "" "-b"' + bash, "(a -b -c d e)", 4, "a -b -c d e", 11, arg='-i "-b"' + ) + assert output == "3" + + def test_10_single_hyphen_1(self, bash): + """- should be counted as an argument representing stdout/stdin""" + output = self._test(bash, "(a -b - c -d e)", 5, "a -b - c -d e", 12) + assert output == "3" + + def test_10_single_hyphen_2(self, bash): + """- in an option argument should be skipped""" + output = self._test( + bash, "(a -b - c - e)", 5, "a -b - c - e", 11, arg='-a "-b"' + ) + assert output == "3" + + def test_11_double_hyphen_1(self, bash): + """all the words after -- should be counted""" + output = self._test( + bash, "(a -b -- -c -d e)", 5, "a -b -- -c -d e", 14 ) assert output == "3" + + def test_11_double_hyphen_2(self, bash): + """all the words after -- should be counted""" + output = self._test(bash, "(a b -- -c -d e)", 5, "a b -- -c -d e", 13) + assert output == "4" + + def test_12_exclude_optarg_1(self, bash): + """an option argument should be skipped even if it matches the argument pattern""" + output = self._test( + bash, "(a -o -x b c)", 4, "a -o -x b c", 10, arg='-a "-o" -i "-x"' + ) + assert output == "2" + + def test_12_exclude_optarg_2(self, bash): + """an option argument should be skipped even if it matches the argument pattern""" + output = self._test( + bash, + "(a -o -x -x c)", + 4, + "a -o -x -x c", + 11, + arg='-a "-o" -i "-x"', + ) + assert output == "2" + + def test_12_exclude_optarg_3(self, bash): + """an option argument should be skipped even if it matches the argument pattern""" + output = self._test( + bash, + "(a -o -x -y c)", + 4, + "a -o -x -y c", + 11, + arg='-a "-o" -i "-x"', + ) + assert output == "1" + + def test_13_plus_option_optarg(self, bash): + """When +o is specified to be an option taking an option argument, it should not be counted as an argument""" + output = self._test( + bash, "(a +o b c)", 3, "a +o b c", 7, arg='-a "+o"' + ) + assert output == "1" + + def test_14_no_optarg_chain_1(self, bash): + """an option argument should not take another option argument""" + output = self._test( + bash, "(a -o -o -o -o c)", 5, "a -o -o -o -o c", 14, arg='-a "-o"' + ) + assert output == "1" + + def test_14_no_optarg_chain_2(self, bash): + """an option argument should not take another option argument""" + output = self._test( + bash, + "(a -o -o b -o -o c)", + 6, + "a -o -o b -o -o c", + 16, + arg='-a "-o"', + ) + assert output == "2" + + def test_15_double_hyphen_optarg(self, bash): + """-- should lose its meaning when it is an option argument""" + output = self._test( + bash, "(a -o -- -b -c d)", 5, "a -o -- -b -c d", 14, arg='-a "-o"' + ) + assert output == "1" + + def test_16_empty_word(self, bash): + """An empty word should not take an option argument""" + output = self._test(bash, "(a '' x '' y d)", 5, "a x y d", 8) + assert output == "5" diff --git a/test/t/unit/test_unit_delimited.py b/test/t/unit/test_unit_delimited.py new file mode 100644 index 0000000..e20dcd1 --- /dev/null +++ b/test/t/unit/test_unit_delimited.py @@ -0,0 +1,42 @@ +import pytest + +from conftest import assert_bash_exec + + +@pytest.mark.bashcomp(cmd=None) +class TestUnitDelimited: + @pytest.fixture(scope="class") + def functions(self, request, bash): + assert_bash_exec( + bash, + "_comp_cmd_test_delim() {" + " local cur prev words cword comp_args;" + " _comp_get_words cur;" + " _comp_delimited , -W 'alpha beta bravo';" + "};" + "complete -F _comp_cmd_test_delim test_delim", + ) + + @pytest.mark.complete("test_delim --opt=a") + def test_1(self, functions, completion): + assert completion == ["lpha"] + + @pytest.mark.complete("test_delim --opt=b") + def test_2(self, functions, completion): + assert completion == ["beta", "bravo"] + + @pytest.mark.complete("test_delim --opt=alpha,b") + def test_3(self, functions, completion): + assert completion == ["alpha,beta", "alpha,bravo"] + + @pytest.mark.complete("test_delim --opt=alpha,be") + def test_4(self, functions, completion): + assert completion == ["ta"] + + @pytest.mark.complete("test_delim --opt=beta,a") + def test_5(self, functions, completion): + assert completion == ["lpha"] + + @pytest.mark.complete("test_delim --opt=c") + def test_6(self, functions, completion): + assert not completion diff --git a/test/t/unit/test_unit_deprecate_func.py b/test/t/unit/test_unit_deprecate_func.py new file mode 100644 index 0000000..c825e8c --- /dev/null +++ b/test/t/unit/test_unit_deprecate_func.py @@ -0,0 +1,15 @@ +import pytest + +from conftest import assert_bash_exec + + +@pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+declare -f func[12]$") +class TestUnitDeprecateFunc: + def test_1(self, bash): + assert_bash_exec( + bash, + 'func1() { echo "func1($*)"; }; ' + "_comp_deprecate_func 2.12 func2 func1", + ) + output = assert_bash_exec(bash, "func2 1 2 3", want_output=True) + assert output.strip() == "func1(1 2 3)" diff --git a/test/t/unit/test_unit_dequote.py b/test/t/unit/test_unit_dequote.py new file mode 100644 index 0000000..0ac814d --- /dev/null +++ b/test/t/unit/test_unit_dequote.py @@ -0,0 +1,161 @@ +import pytest + +from conftest import assert_bash_exec, bash_env_saved + + +@pytest.mark.bashcomp( + cmd=None, + cwd="_filedir", + ignore_env=r"^\+declare -f __tester$", +) +class TestDequote: + def test_1_char(self, bash): + assert_bash_exec( + bash, + '__tester() { local REPLY=dummy v=var;_comp_dequote "$1";local ext=$?;((${#REPLY[@]}))&&printf \'<%s>\' "${REPLY[@]}";echo;return $ext;}', + ) + output = assert_bash_exec(bash, "__tester a", want_output=True) + assert output.strip() == "<a>" + + def test_2_str(self, bash): + output = assert_bash_exec(bash, "__tester abc", want_output=True) + assert output.strip() == "<abc>" + + def test_3_null(self, bash): + output = assert_bash_exec(bash, "__tester ''", want_output=True) + assert output.strip() == "" + + def test_4_empty(self, bash): + output = assert_bash_exec(bash, "__tester \"''\"", want_output=True) + assert output.strip() == "<>" + + def test_5_brace(self, bash): + output = assert_bash_exec(bash, "__tester 'a{1..3}'", want_output=True) + assert output.strip() == "<a1><a2><a3>" + + def test_6_glob(self, bash): + output = assert_bash_exec(bash, "__tester 'a?b'", want_output=True) + assert output.strip() == "<a b><a$b><a&b><a'b>" + + def test_7_quote_1(self, bash): + output = assert_bash_exec( + bash, "__tester '\"a\"'\\'b\\'\\$\\'c\\'", want_output=True + ) + assert output.strip() == "<abc>" + + def test_7_quote_2(self, bash): + output = assert_bash_exec( + bash, "__tester '\\\"\\'\\''\\$\\`'", want_output=True + ) + assert output.strip() == "<\"'$`>" + + def test_7_quote_3(self, bash): + output = assert_bash_exec( + bash, "__tester \\$\\'a\\\\tb\\'", want_output=True + ) + assert output.strip() == "<a\tb>" + + def test_7_quote_4(self, bash): + output = assert_bash_exec( + bash, '__tester \'"abc\\"def"\'', want_output=True + ) + assert output.strip() == '<abc"def>' + + def test_7_quote_5(self, bash): + output = assert_bash_exec( + bash, "__tester \\'abc\\'\\\\\\'\\'def\\'", want_output=True + ) + assert output.strip() == "<abc'def>" + + def test_8_param_1(self, bash): + output = assert_bash_exec(bash, "__tester '$v'", want_output=True) + assert output.strip() == "<var>" + + def test_8_param_2(self, bash): + output = assert_bash_exec(bash, "__tester '${v}'", want_output=True) + assert output.strip() == "<var>" + + def test_8_param_3(self, bash): + output = assert_bash_exec(bash, "__tester '${#v}'", want_output=True) + assert output.strip() == "<3>" + + def test_8_param_4(self, bash): + output = assert_bash_exec(bash, "__tester '${v[0]}'", want_output=True) + assert output.strip() == "<var>" + + def test_9_qparam_1(self, bash): + output = assert_bash_exec(bash, "__tester '\"$v\"'", want_output=True) + assert output.strip() == "<var>" + + def test_9_qparam_2(self, bash): + output = assert_bash_exec( + bash, "__tester '\"${v[@]}\"'", want_output=True + ) + assert output.strip() == "<var>" + + def test_10_pparam_1(self, bash): + output = assert_bash_exec(bash, "__tester '$?'", want_output=True) + assert output.strip() == "<0>" + + def test_10_pparam_2(self, bash): + output = assert_bash_exec(bash, "__tester '${#1}'", want_output=True) + assert output.strip() == "<5>" # The string `${#1}` is five characters + + def test_unsafe_1(self, bash): + output = assert_bash_exec( + bash, "! __tester '$(echo hello >&2)'", want_output=True + ) + assert output.strip() == "" + + def test_unsafe_2(self, bash): + output = assert_bash_exec( + bash, "! __tester '|echo hello >&2'", want_output=True + ) + assert output.strip() == "" + + def test_unsafe_3(self, bash): + output = assert_bash_exec( + bash, "! __tester '>| important_file.txt'", want_output=True + ) + assert output.strip() == "" + + def test_unsafe_4(self, bash): + output = assert_bash_exec( + bash, "! __tester '`echo hello >&2`'", want_output=True + ) + assert output.strip() == "" + + def test_glob_default(self, bash): + with bash_env_saved(bash) as bash_env: + bash_env.shopt("failglob", False) + bash_env.shopt("nullglob", False) + output = assert_bash_exec( + bash, "__tester 'non-existent-*.txt'", want_output=True + ) + assert output.strip() == "<non-existent-*.txt>" + + def test_glob_noglob(self, bash): + with bash_env_saved(bash) as bash_env: + bash_env.set("noglob", True) + output = assert_bash_exec( + bash, + "__tester 'non-existent-*.txt'", + want_output=True, + ) + assert output.strip() == "<non-existent-*.txt>" + + def test_glob_failglob(self, bash): + with bash_env_saved(bash) as bash_env: + bash_env.shopt("failglob", True) + output = assert_bash_exec( + bash, "! __tester 'non-existent-*.txt'", want_output=True + ) + assert output.strip() == "" + + def test_glob_nullglob(self, bash): + with bash_env_saved(bash) as bash_env: + bash_env.shopt("nullglob", True) + output = assert_bash_exec( + bash, "__tester 'non-existent-*.txt'", want_output=True + ) + assert output.strip() == "" diff --git a/test/t/unit/test_unit_expand.py b/test/t/unit/test_unit_expand.py index d2a3ebc..0be6c52 100644 --- a/test/t/unit/test_unit_expand.py +++ b/test/t/unit/test_unit_expand.py @@ -1,31 +1,42 @@ import pytest -from conftest import assert_bash_exec +from conftest import assert_bash_exec, bash_env_saved @pytest.mark.bashcomp(cmd=None, ignore_env=r"^[+-](cur|COMPREPLY)=") class TestUnitExpand: def test_1(self, bash): - assert_bash_exec(bash, "_expand >/dev/null") + assert_bash_exec(bash, "_comp_expand >/dev/null") def test_2(self, bash): """Test environment non-pollution, detected at teardown.""" - assert_bash_exec(bash, "foo() { _expand; }; foo; unset foo") + assert_bash_exec(bash, "foo() { _comp_expand; }; foo; unset -f foo") def test_user_home_compreply(self, bash, user_home): user, home = user_home output = assert_bash_exec( bash, - r'cur="~%s"; _expand; printf "%%s\n" "$COMPREPLY"' % user, + r'cur="~%s"; _comp_expand; printf "%%s\n" "$COMPREPLY"' % user, want_output=True, ) assert output.strip() == home + def test_user_home_compreply_failglob(self, bash, user_home): + user, home = user_home + with bash_env_saved(bash) as bash_env: + bash_env.shopt("failglob", True) + output = assert_bash_exec( + bash, + r'cur="~%s"; _comp_expand; printf "%%s\n" "$COMPREPLY"' % user, + want_output=True, + ) + assert output.strip() == home + def test_user_home_cur(self, bash, user_home): user, home = user_home output = assert_bash_exec( bash, - r'cur="~%s/a"; _expand; printf "%%s\n" "$cur"' % user, + r'cur="~%s/a"; _comp_expand; printf "%%s\n" "$cur"' % user, want_output=True, ) assert output.strip() == "%s/a" % home diff --git a/test/t/unit/test_unit_expand_glob.py b/test/t/unit/test_unit_expand_glob.py new file mode 100644 index 0000000..64d04a7 --- /dev/null +++ b/test/t/unit/test_unit_expand_glob.py @@ -0,0 +1,83 @@ +import pytest + +from conftest import assert_bash_exec, bash_env_saved + + +@pytest.mark.bashcomp( + cmd=None, + cwd="_filedir", + ignore_env=r"^\+declare -f (dump_array|__tester)$", +) +class TestExpandGlob: + @pytest.fixture(scope="class") + def functions(self, bash): + assert_bash_exec( + bash, + "dump_array() { ((${#arr[@]})) && printf '<%s>' \"${arr[@]}\"; echo; }", + ) + assert_bash_exec( + bash, + '__tester() { local LC_ALL= LC_COLLATE=C arr; _comp_expand_glob arr "$@";dump_array; }', + ) + + def test_match_all(self, bash, functions): + output = assert_bash_exec(bash, "__tester '*'", want_output=True) + assert output.strip() == "<a b><a$b><a&b><a'b><ab><aé><brackets><ext>" + + def test_match_pattern(self, bash, functions): + output = assert_bash_exec(bash, "__tester 'a*'", want_output=True) + assert output.strip() == "<a b><a$b><a&b><a'b><ab><aé>" + + def test_match_unmatched(self, bash, functions): + output = assert_bash_exec( + bash, "__tester 'unmatched-*'", want_output=True + ) + assert output.strip() == "" + + def test_match_multiple_words(self, bash, functions): + output = assert_bash_exec(bash, "__tester 'b* e*'", want_output=True) + assert output.strip() == "<brackets><ext>" + + def test_match_brace_expansion(self, bash, functions): + output = assert_bash_exec( + bash, "__tester 'brac{ket,unmatched}*'", want_output=True + ) + assert output.strip() == "<brackets>" + + def test_protect_from_noglob(self, bash, functions): + with bash_env_saved(bash, functions) as bash_env: + bash_env.set("noglob", True) + output = assert_bash_exec(bash, "__tester 'a*'", want_output=True) + assert output.strip() == "<a b><a$b><a&b><a'b><ab><aé>" + + def test_protect_from_failglob(self, bash, functions): + with bash_env_saved(bash) as bash_env: + bash_env.shopt("failglob", True) + output = assert_bash_exec( + bash, "__tester 'unmatched-*'", want_output=True + ) + assert output.strip() == "" + + def test_protect_from_nullglob(self, bash, functions): + with bash_env_saved(bash) as bash_env: + bash_env.shopt("nullglob", False) + output = assert_bash_exec( + bash, "__tester 'unmatched-*'", want_output=True + ) + assert output.strip() == "" + + def test_protect_from_dotglob(self, bash, functions): + with bash_env_saved(bash) as bash_env: + bash_env.shopt("dotglob", True) + output = assert_bash_exec( + bash, "__tester 'ext/foo/*'", want_output=True + ) + assert output.strip() == "" + + def test_protect_from_GLOBIGNORE(self, bash, functions): + with bash_env_saved(bash) as bash_env: + # Note: dotglob is changed by GLOBIGNORE + bash_env.save_shopt("dotglob") + bash_env.write_variable("GLOBIGNORE", "*") + output = assert_bash_exec(bash, "__tester 'a*'", want_output=True) + assert output.strip() == "<a b><a$b><a&b><a'b><ab><aé>" diff --git a/test/t/unit/test_unit_expand_tilde_by_ref.py b/test/t/unit/test_unit_expand_tilde.py index 17bdedf..3552fd6 100644 --- a/test/t/unit/test_unit_expand_tilde_by_ref.py +++ b/test/t/unit/test_unit_expand_tilde.py @@ -3,16 +3,27 @@ import pytest from conftest import assert_bash_exec -@pytest.mark.bashcomp(cmd=None, ignore_env=r"^[+-]var=") -class TestUnitExpandTildeByRef: +@pytest.mark.bashcomp(cmd=None) +class TestUnitExpandTilde: def test_1(self, bash): + """The old interface `__expand_tilde_by_ref` should not fail when it is + called without arguments""" assert_bash_exec(bash, "__expand_tilde_by_ref >/dev/null") def test_2(self, bash): """Test environment non-pollution, detected at teardown.""" assert_bash_exec( bash, - '_x() { local aa="~"; __expand_tilde_by_ref aa; }; _x; unset _x', + '_x() { local REPLY; _comp_expand_tilde "~"; }; _x; unset -f _x', + ) + + @pytest.fixture(scope="class") + def functions(self, bash): + # $HOME tinkering: protect against $HOME != ~user; our "home" is the + # latter but plain_tilde follows $HOME + assert_bash_exec( + bash, + '_comp__test_unit() { local REPLY HOME=$1; _comp_expand_tilde "$2"; printf "%s\\n" "$REPLY"; }', ) @pytest.mark.parametrize("plain_tilde", (True, False)) @@ -28,19 +39,21 @@ class TestUnitExpandTildeByRef: ("/a;echo hello", True), ), ) - def test_expand(self, bash, user_home, plain_tilde, suffix_expanded): + def test_expand( + self, bash, user_home, plain_tilde, suffix_expanded, functions + ): user, home = user_home suffix, expanded = suffix_expanded + home2 = home if plain_tilde: user = "" if not suffix or not expanded: - home = "~" + home2 = "~" elif not expanded: - home = "~%s" % user + home2 = "~%s" % user output = assert_bash_exec( bash, - r'var="~%s%s"; __expand_tilde_by_ref var; printf "%%s\n" "$var"' - % (user, suffix), + r'_comp__test_unit "%s" "~%s%s"' % (home, user, suffix), want_output=True, ) - assert output.strip() == "%s%s" % (home, suffix.replace(r"\$", "$"),) + assert output.strip() == "%s%s" % (home2, suffix.replace(r"\$", "$")) diff --git a/test/t/unit/test_unit_filedir.py b/test/t/unit/test_unit_filedir.py index b847efc..07ae2f3 100644 --- a/test/t/unit/test_unit_filedir.py +++ b/test/t/unit/test_unit_filedir.py @@ -15,18 +15,18 @@ class TestUnitFiledir: def functions(self, request, bash): assert_bash_exec( bash, - "_f() { local cur=$(_get_cword); unset COMPREPLY; _filedir; }; " + "_f() { local cur;_comp_get_words cur; unset -v COMPREPLY; _comp_compgen_filedir; }; " "complete -F _f f; " "complete -F _f -o filenames f2", ) assert_bash_exec( bash, - "_g() { local cur=$(_get_cword); unset COMPREPLY; _filedir e1; }; " + "_g() { local cur;_comp_get_words cur; unset -v COMPREPLY; _comp_compgen_filedir e1; }; " "complete -F _g g", ) assert_bash_exec( bash, - "_fd() { local cur=$(_get_cword); unset COMPREPLY; _filedir -d; };" + "_fd() { local cur;_comp_get_words cur; unset -v COMPREPLY; _comp_compgen_filedir -d; };" "complete -F _fd fd", ) @@ -59,7 +59,7 @@ class TestUnitFiledir: return lc_ctype def test_1(self, bash): - assert_bash_exec(bash, "_filedir >/dev/null") + assert_bash_exec(bash, "_comp_compgen_filedir >/dev/null") @pytest.mark.parametrize("funcname", "f f2".split()) def test_2(self, bash, functions, funcname): @@ -196,7 +196,7 @@ class TestUnitFiledir: @pytest.mark.parametrize("funcname", "f f2".split()) def test_22(self, bash, functions, funcname, non_windows_testdir): completion = assert_complete( - bash, r"%s '%s/a\b/" % (funcname, non_windows_testdir) + bash, rf"{funcname} '{non_windows_testdir}/a\b/" ) assert completion == "g'" diff --git a/test/t/unit/test_unit_get_cword.py b/test/t/unit/test_unit_get_cword.py index 0b56d16..d2bb526 100644 --- a/test/t/unit/test_unit_get_cword.py +++ b/test/t/unit/test_unit_get_cword.py @@ -1,11 +1,12 @@ -import pexpect +import pexpect # type: ignore[import] import pytest from conftest import PS1, TestUnitBase, assert_bash_exec @pytest.mark.bashcomp( - cmd=None, ignore_env=r"^[+-](COMP_(WORDS|CWORD|LINE|POINT)|_scp_path_esc)=" + cmd=None, + ignore_env=r"^[+-](COMP_(WORDS|CWORD|LINE|POINT)|_comp_cmd_scp__path_esc)=", ) class TestUnitGetCword(TestUnitBase): def _test(self, *args, **kwargs): @@ -49,12 +50,12 @@ class TestUnitGetCword(TestUnitBase): assert output == r"b\ c" def test_8(self, bash): - r"""a b\| c should return b\ """ + r"""a b\| c should return b\ """ # fmt: skip output = self._test(bash, r"(a 'b\ c')", 1, r"a b\ c", 4) assert output == "b\\" def test_9(self, bash): - r"""a "b\| should return "b\ """ + r"""a "b\| should return "b\ """ # fmt: skip output = self._test(bash, "(a '\"b\\')", 1, r"a \"b\\", 5) assert output == '"b\\' @@ -103,7 +104,7 @@ class TestUnitGetCword(TestUnitBase): a -n| should return -n This test makes sure `_get_cword' doesn't use `echo' to return its - value, because -n might be interpreted by `echo' and thus woud not + value, because -n might be interpreted by `echo' and thus would not be returned. """ output = self._test(bash, "(a -n)", 1, "a -n", 4) @@ -152,3 +153,12 @@ class TestUnitGetCword(TestUnitBase): ] ) assert got == 1 + + def test_25(self, bash): + """ + a b c:| with trailing whitespace after the caret (no more words) and + with WORDBREAKS -= : should return c: + """ + assert_bash_exec(bash, "add_comp_wordbreak_char :") + output = self._test(bash, "(a b c :)", 3, "a b c: ", 6, arg=":") + assert output == "c:" diff --git a/test/t/unit/test_unit_get_first_arg.py b/test/t/unit/test_unit_get_first_arg.py new file mode 100644 index 0000000..415e217 --- /dev/null +++ b/test/t/unit/test_unit_get_first_arg.py @@ -0,0 +1,90 @@ +import pytest + +from conftest import assert_bash_exec + + +@pytest.mark.bashcomp(cmd=None) +class TestUnitGetFirstArg: + @pytest.fixture(scope="class") + def functions(self, bash): + assert_bash_exec( + bash, + '_comp__test_unit() { local -a "words=$1"; local cword=$2 REPLY=; shift 2; _comp_get_first_arg "$@" && printf "%s\\n" "$REPLY"; return 0; }', + ) + + def _test(self, bash, words, cword, args=""): + return assert_bash_exec( + bash, + '_comp__test_unit "%s" %d %s' % (words, cword, args), + want_output=None, + ).strip() + + def test_1(self, bash, functions): + assert_bash_exec(bash, "_comp__test_unit '()' 0") + + def test_2(self, bash, functions): + output = self._test(bash, "(a b)", 2) + assert output == "b" + + def test_3(self, bash, functions): + output = self._test(bash, "(a bc)", 2) + assert output == "bc" + + def test_4(self, bash, functions): + output = self._test(bash, "(a b c)", 2) + assert output == "b" + + def test_5(self, bash, functions): + """Neither of the current word and the command name should be picked + as the first argument""" + output = self._test(bash, "(a b c)", 1) + assert output == "" + + def test_6(self, bash, functions): + """Options starting with - should not be picked as the first + argument""" + output = self._test(bash, "(a -b -c d e)", 4) + assert output == "d" + + def test_7_single_hyphen(self, bash, functions): + """- should be counted as an argument representing stdout/stdin""" + output = self._test(bash, "(a -b - c -d e)", 5) + assert output == "-" + + def test_8_double_hyphen_1(self, bash, functions): + """any word after -- should be picked""" + output = self._test(bash, "(a -b -- -c -d e)", 5) + assert output == "-c" + + def test_8_double_hyphen_2(self, bash, functions): + """any word after -- should be picked only without any preceding argument""" + output = self._test(bash, "(a b -- -c -d e)", 5) + assert output == "b" + + def test_9_skip_optarg_1(self, bash, functions): + output = self._test(bash, "(a -b -c d e f)", 5, '-a "@(-c|--foo)"') + assert output == "e" + + def test_9_skip_optarg_2(self, bash, functions): + output = self._test(bash, "(a -b --foo d e f)", 5, '-a "@(-c|--foo)"') + assert output == "e" + + def test_9_skip_optarg_3(self, bash): + output = self._test(bash, "(a -b - c d e)", 5, '-a "-b"') + assert output == "c" + + def test_9_skip_optarg_4(self, bash): + output = self._test(bash, "(a -b -c d e f)", 5, '-a "-[bc]"') + assert output == "d" + + def test_9_skip_optarg_5(self, bash): + output = self._test(bash, "(a +o b c d)", 4, '-a "+o"') + assert output == "c" + + def test_9_skip_optarg_6(self, bash): + output = self._test(bash, "(a -o -o -o -o b c)", 6, '-a "-o"') + assert output == "b" + + def test_9_skip_optarg_7(self, bash): + output = self._test(bash, "(a -o -- -b -c d e)", 6, '-a "-o"') + assert output == "d" diff --git a/test/t/unit/test_unit_get_comp_words_by_ref.py b/test/t/unit/test_unit_get_words.py index b6498fa..63c4034 100644 --- a/test/t/unit/test_unit_get_comp_words_by_ref.py +++ b/test/t/unit/test_unit_get_words.py @@ -11,10 +11,10 @@ class TestUnitGetCompWordsByRef(TestUnitBase): def _test(self, bash, *args, **kwargs): assert_bash_exec(bash, "unset cur prev") output = self._test_unit( - "_get_comp_words_by_ref %s cur prev; echo $cur,${prev-}", + "_comp_get_words %s cur prev; echo $cur,${prev-}", bash, *args, - **kwargs + **kwargs, ) return output.strip() @@ -22,7 +22,7 @@ class TestUnitGetCompWordsByRef(TestUnitBase): assert_bash_exec( bash, "COMP_WORDS=() COMP_CWORD= COMP_POINT= COMP_LINE= " - "_get_comp_words_by_ref cur >/dev/null", + "_comp_get_words cur >/dev/null", ) def test_2(self, bash): @@ -41,12 +41,12 @@ class TestUnitGetCompWordsByRef(TestUnitBase): assert output == "," def test_5(self, bash): - """|a """ + """|a """ # fmt: skip output = self._test(bash, "(a)", 0, "a ", 0) assert output == "," def test_6(self, bash): - """ | a """ + """ | a """ # fmt: skip output = self._test(bash, "(a)", 0, " a ", 1) assert output.strip() == "," @@ -134,9 +134,9 @@ class TestUnitGetCompWordsByRef(TestUnitBase): def test_23(self, bash): """a -n| - This test makes sure `_get_cword' doesn't use `echo' to return its - value, because -n might be interpreted by `echo' and thus woud not - be returned. + This test makes sure `_comp_get_words' doesn't use `echo' to + return its value, because -n might be interpreted by `echo' + and thus would not be returned. """ output = self._test(bash, "(a -n)", 1, "a -n", 4) assert output == "-n,a" @@ -175,7 +175,7 @@ class TestUnitGetCompWordsByRef(TestUnitBase): """a b| to all vars""" assert_bash_exec(bash, "unset words cword cur prev") output = self._test_unit( - "_get_comp_words_by_ref words cword cur prev%s; " + "_comp_get_words words cword cur prev%s; " 'echo "${words[@]}",$cword,$cur,$prev', bash, "(a b)", @@ -189,7 +189,7 @@ class TestUnitGetCompWordsByRef(TestUnitBase): """a b| to alternate vars""" assert_bash_exec(bash, "unset words2 cword2 cur2 prev2") output = self._test_unit( - "_get_comp_words_by_ref -w words2 -i cword2 -c cur2 -p prev2%s; " + "_comp_get_words -w words2 -i cword2 -c cur2 -p prev2%s; " 'echo $cur2,$prev2,"${words2[@]}",$cword2', bash, "(a b)", @@ -204,7 +204,7 @@ class TestUnitGetCompWordsByRef(TestUnitBase): """a b : c| with wordbreaks -= :""" assert_bash_exec(bash, "unset words") output = self._test_unit( - '_get_comp_words_by_ref -n : words%s; echo "${words[@]}"', + '_comp_get_words -n : words%s; echo "${words[@]}"', bash, "(a b : c)", 3, @@ -217,7 +217,7 @@ class TestUnitGetCompWordsByRef(TestUnitBase): """a b: c| with wordbreaks -= :""" assert_bash_exec(bash, "unset words") output = self._test_unit( - '_get_comp_words_by_ref -n : words%s; echo "${words[@]}"', + '_comp_get_words -n : words%s; echo "${words[@]}"', bash, "(a b : c)", 3, @@ -230,7 +230,7 @@ class TestUnitGetCompWordsByRef(TestUnitBase): """a b :c| with wordbreaks -= :""" assert_bash_exec(bash, "unset words") output = self._test_unit( - '_get_comp_words_by_ref -n : words%s; echo "${words[@]}"', + '_comp_get_words -n : words%s; echo "${words[@]}"', bash, "(a b : c)", 3, @@ -243,7 +243,7 @@ class TestUnitGetCompWordsByRef(TestUnitBase): r"""a b\ :c| with wordbreaks -= :""" assert_bash_exec(bash, "unset words") output = self._test_unit( - '_get_comp_words_by_ref -n : words%s; echo "${words[@]}"', + '_comp_get_words -n : words%s; echo "${words[@]}"', bash, "(a 'b ' : c)", 3, @@ -255,6 +255,6 @@ class TestUnitGetCompWordsByRef(TestUnitBase): def test_unknown_arg_error(self, bash): with pytest.raises(AssertionError) as ex: _ = assert_bash_exec( - bash, "_get_comp_words_by_ref dummy", want_output=True + bash, "_comp_get_words dummy", want_output=True ) ex.match("dummy.* unknown argument") diff --git a/test/t/unit/test_unit_init_completion.py b/test/t/unit/test_unit_init_completion.py deleted file mode 100644 index 64a5a79..0000000 --- a/test/t/unit/test_unit_init_completion.py +++ /dev/null @@ -1,34 +0,0 @@ -import pytest - -from conftest import TestUnitBase, assert_bash_exec, assert_complete - - -@pytest.mark.bashcomp( - cmd=None, - ignore_env=r"^[+-](COMP(_(WORDS|CWORD|LINE|POINT)|REPLY)|" - r"cur|cword|words)=", -) -class TestUnitInitCompletion(TestUnitBase): - def test_1(self, bash): - """Test environment non-pollution, detected at teardown.""" - assert_bash_exec( - bash, - "foo() { " - "local cur prev words cword " - "COMP_WORDS=() COMP_CWORD=0 COMP_LINE= COMP_POINT=0; " - "_init_completion; }; " - "foo; unset foo", - ) - - def test_2(self, bash): - output = self._test_unit( - "_init_completion %s; echo $cur,${prev-}", bash, "(a)", 0, "a", 0 - ) - assert output == "," - - @pytest.mark.parametrize("redirect", "> >> 2> < &>".split()) - def test_redirect(self, bash, redirect): - completion = assert_complete( - bash, "%s " % redirect, cwd="shared/default" - ) - assert all(x in completion for x in "foo bar".split()) diff --git a/test/t/unit/test_unit_initialize.py b/test/t/unit/test_unit_initialize.py new file mode 100644 index 0000000..63fddee --- /dev/null +++ b/test/t/unit/test_unit_initialize.py @@ -0,0 +1,66 @@ +import pytest + +from conftest import TestUnitBase, assert_bash_exec, assert_complete + + +@pytest.mark.bashcomp( + cmd=None, + ignore_env=r"^[+-](COMP(_(WORDS|CWORD|LINE|POINT)|REPLY)|" + r"cur|prev|cword|words)=|^\+declare -f _cmd1$", +) +class TestUnitInitCompletion(TestUnitBase): + def test_1(self, bash): + """Test environment non-pollution, detected at teardown.""" + assert_bash_exec( + bash, + "foo() { " + "local cur prev words cword comp_args " + "COMP_WORDS=() COMP_CWORD=0 COMP_LINE= COMP_POINT=0; " + "_comp_initialize; }; " + "foo; unset -f foo", + ) + + def test_2(self, bash): + output = self._test_unit( + "_comp_initialize %s; echo $cur,${prev-}", bash, "(a)", 0, "a", 0 + ) + assert output == "," + + @pytest.mark.parametrize("redirect", "> >> 2> < &>".split()) + def test_redirect(self, bash, redirect): + completion = assert_complete( + bash, "%s " % redirect, cwd="shared/default" + ) + assert all(x in completion for x in "foo bar".split()) + + @pytest.fixture(scope="class") + def cmd1_empty_completion_setup(self, bash): + assert_bash_exec( + bash, + '_cmd1() { local cur prev words cword comp_args; _comp_initialize -- "$@"; } && ' + "complete -F _cmd1 cmd1", + ) + + @pytest.mark.parametrize("redirect", "> >> 2> {fd1}> < &> &>> >|".split()) + def test_redirect_2(self, bash, cmd1_empty_completion_setup, redirect): + # Note: Bash 4.3 and below cannot properly extract the redirection ">|" + if redirect == ">|": + skipif = "((BASH_VERSINFO[0] * 100 + BASH_VERSINFO[1] < 404))" + try: + assert_bash_exec(bash, skipif, want_output=None) + except AssertionError: + pass + else: + pytest.skip(skipif) + + completion = assert_complete( + bash, "cmd1 %s f" % redirect, cwd="shared/default" + ) + assert "foo" in completion + + @pytest.mark.parametrize("redirect", "> >> 2> < &>".split()) + def test_redirect_3(self, bash, redirect): + completion = assert_complete( + bash, "cmd1 %sf" % redirect, cwd="shared/default" + ) + assert "foo" in completion diff --git a/test/t/unit/test_unit_ip_addresses.py b/test/t/unit/test_unit_ip_addresses.py index 8120c88..37f3b0e 100644 --- a/test/t/unit/test_unit_ip_addresses.py +++ b/test/t/unit/test_unit_ip_addresses.py @@ -9,41 +9,41 @@ class TestUnitIpAddresses: def functions(self, request, bash): assert_bash_exec( bash, - "_ia() { local cur=$(_get_cword);unset COMPREPLY;" - "_ip_addresses; }", + "_ia() { local cur;_comp_get_words cur;" + "unset -v COMPREPLY;_comp_compgen_ip_addresses; }", ) assert_bash_exec(bash, "complete -F _ia ia") assert_bash_exec( bash, - "_iaa() { local cur=$(_get_cword);unset COMPREPLY;" - "_ip_addresses -a; }", + "_iaa() { local cur;_comp_get_words cur;" + "unset -v COMPREPLY;_comp_compgen_ip_addresses -a; }", ) assert_bash_exec(bash, "complete -F _iaa iaa") assert_bash_exec( bash, - " _ia6() { local cur=$(_get_cword);unset COMPREPLY;" - "_ip_addresses -6; }", + " _ia6() { local cur;_comp_get_words cur;" + "unset -v COMPREPLY;_comp_compgen_ip_addresses -6; }", ) assert_bash_exec(bash, "complete -F _ia6 ia6") def test_1(self, bash): - assert_bash_exec(bash, "_ip_addresses") + assert_bash_exec(bash, "_comp_compgen_ip_addresses") @pytest.mark.complete("iaa ") def test_2(self, functions, completion): - """_ip_addresses -a should complete ip addresses.""" + """_comp_compgen_ip_addresses -a should complete ip addresses.""" assert completion assert all("." in x or ":" in x for x in completion) @pytest.mark.complete("ia ") def test_3(self, functions, completion): - """_ip_addresses should complete ipv4 addresses.""" + """_comp_compgen_ip_addresses should complete ipv4 addresses.""" assert completion assert all("." in x for x in completion) @pytest.mark.xfail(in_container(), reason="Probably fails in a container") @pytest.mark.complete("ia6 ") def test_4(self, functions, completion): - """_ip_addresses -6 should complete ipv6 addresses.""" + """_comp_compgen_ip_addresses -6 should complete ipv6 addresses.""" assert completion assert all(":" in x for x in completion) diff --git a/test/t/unit/test_unit_known_hosts_real.py b/test/t/unit/test_unit_known_hosts.py index ac5205e..b0f715b 100644 --- a/test/t/unit/test_unit_known_hosts_real.py +++ b/test/t/unit/test_unit_known_hosts.py @@ -2,14 +2,14 @@ from itertools import chain import pytest -from conftest import assert_bash_exec +from conftest import assert_bash_exec, bash_env_saved @pytest.mark.bashcomp( cmd=None, - ignore_env="^[+-](COMP(REPLY|_KNOWN_HOSTS_WITH_HOSTFILE)|OLDHOME)=", + ignore_env="^[+-](COMPREPLY|BASH_COMPLETION_KNOWN_HOSTS_WITH_HOSTFILE)=", ) -class TestUnitKnownHostsReal: +class TestUnitCompgenKnownHosts: @pytest.mark.parametrize( "prefix,colon_flag,hostfile", [("", "", True), ("", "", False), ("user@", "c", True)], @@ -21,9 +21,9 @@ class TestUnitKnownHostsReal: "%s%s%s" % (prefix, x, ":" if colon_flag else "") for x in chain( hosts if hostfile else avahi_hosts, - # fixtures/_known_hosts_real/config + # fixtures/_known_hosts/config "gee hus jar #not-a-comment".split(), - # fixtures/_known_hosts_real/known_hosts + # fixtures/_known_hosts/known_hosts ( "doo", "ike", @@ -43,14 +43,14 @@ class TestUnitKnownHostsReal: ) assert_bash_exec( bash, - "unset -v COMP_KNOWN_HOSTS_WITH_HOSTFILE" + "unset -v BASH_COMPLETION_KNOWN_HOSTS_WITH_HOSTFILE" if hostfile - else "COMP_KNOWN_HOSTS_WITH_HOSTFILE=", + else "BASH_COMPLETION_KNOWN_HOSTS_WITH_HOSTFILE=", ) output = assert_bash_exec( bash, - "_known_hosts_real -a%sF _known_hosts_real/config '%s'; " - r'printf "%%s\n" "${COMPREPLY[@]}"; unset COMPREPLY' + "_comp_compgen_known_hosts -a%sF _known_hosts/config '%s'; " + r'printf "%%s\n" "${COMPREPLY[@]}"; unset -v COMPREPLY' % (colon_flag, prefix), want_output=True, ) @@ -66,12 +66,13 @@ class TestUnitKnownHostsReal: ) def test_ip_filtering(self, bash, family, result): assert_bash_exec( - bash, "unset -v COMPREPLY COMP_KNOWN_HOSTS_WITH_HOSTFILE" + bash, + "unset -v COMPREPLY BASH_COMPLETION_KNOWN_HOSTS_WITH_HOSTFILE", ) output = assert_bash_exec( bash, - "COMP_KNOWN_HOSTS_WITH_HOSTFILE= " - "_known_hosts_real -%sF _known_hosts_real/localhost_config ''; " + "BASH_COMPLETION_KNOWN_HOSTS_WITH_HOSTFILE= " + "_comp_compgen_known_hosts -%sF _known_hosts/localhost_config ''; " r'printf "%%s\n" "${COMPREPLY[@]}"' % family, want_output=True, ) @@ -79,17 +80,17 @@ class TestUnitKnownHostsReal: def test_consecutive_spaces(self, bash, hosts): expected = hosts.copy() - # fixtures/_known_hosts_real/spaced conf + # fixtures/_known_hosts/spaced conf expected.extend("gee hus #not-a-comment".split()) - # fixtures/_known_hosts_real/known_hosts2 + # fixtures/_known_hosts/known_hosts2 expected.extend("two two2 two3 two4".split()) # fixtures/_known_hosts_/spaced known_hosts expected.extend("doo ike".split()) output = assert_bash_exec( bash, - "unset -v COMPREPLY COMP_KNOWN_HOSTS_WITH_HOSTFILE; " - "_known_hosts_real -aF '_known_hosts_real/spaced conf' ''; " + "unset -v COMPREPLY BASH_COMPLETION_KNOWN_HOSTS_WITH_HOSTFILE; " + "_comp_compgen_known_hosts -aF '_known_hosts/spaced conf' ''; " r'printf "%s\n" "${COMPREPLY[@]}"', want_output=True, ) @@ -97,62 +98,58 @@ class TestUnitKnownHostsReal: def test_files_starting_with_tilde(self, bash, hosts): expected = hosts.copy() - # fixtures/_known_hosts_real/known_hosts2 + # fixtures/_known_hosts/known_hosts2 expected.extend("two two2 two3 two4".split()) - # fixtures/_known_hosts_real/known_hosts3 + # fixtures/_known_hosts/known_hosts3 expected.append("three") - # fixtures/_known_hosts_real/known_hosts4 + # fixtures/_known_hosts/known_hosts4 expected.append("four") - assert_bash_exec(bash, 'OLDHOME="$HOME"; HOME="%s"' % bash.cwd) - output = assert_bash_exec( - bash, - "unset -v COMPREPLY COMP_KNOWN_HOSTS_WITH_HOSTFILE; " - "_known_hosts_real -aF _known_hosts_real/config_tilde ''; " - r'printf "%s\n" "${COMPREPLY[@]}"', - want_output=True, - ) - assert_bash_exec(bash, 'HOME="$OLDHOME"') + with bash_env_saved(bash) as bash_env: + bash_env.write_variable("HOME", bash.cwd) + output = assert_bash_exec( + bash, + "unset -v COMPREPLY BASH_COMPLETION_KNOWN_HOSTS_WITH_HOSTFILE;" + " _comp_compgen_known_hosts -aF _known_hosts/config_tilde ''; " + r'printf "%s\n" "${COMPREPLY[@]}"', + want_output=True, + ) + assert sorted(set(output.strip().split())) == sorted(expected) def test_included_configs(self, bash, hosts): expected = hosts.copy() - # fixtures/_known_hosts_real/config_include_recursion + # fixtures/_known_hosts/config_include_recursion expected.append("recursion") - # fixtures/_known_hosts_real/.ssh/config_relative_path + # fixtures/_known_hosts/.ssh/config_relative_path expected.append("relative_path") - # fixtures/_known_hosts_real/.ssh/config_asterisk_* + # fixtures/_known_hosts/.ssh/config_asterisk_* expected.extend("asterisk_1 asterisk_2".split()) - # fixtures/_known_hosts_real/.ssh/config_question_mark + # fixtures/_known_hosts/.ssh/config_question_mark expected.append("question_mark") - assert_bash_exec( - bash, 'OLDHOME="$HOME"; HOME="%s/_known_hosts_real"' % bash.cwd - ) - output = assert_bash_exec( - bash, - "unset -v COMPREPLY COMP_KNOWN_HOSTS_WITH_HOSTFILE; " - "_known_hosts_real -aF _known_hosts_real/config_include ''; " - r'printf "%s\n" "${COMPREPLY[@]}"', - want_output=True, - ) - assert_bash_exec(bash, 'HOME="$OLDHOME"') + with bash_env_saved(bash) as bash_env: + bash_env.write_variable("HOME", "%s/_known_hosts" % bash.cwd) + output = assert_bash_exec( + bash, + "unset -v COMPREPLY BASH_COMPLETION_KNOWN_HOSTS_WITH_HOSTFILE;" + " _comp_compgen_known_hosts -aF _known_hosts/config_include ''; " + r'printf "%s\n" "${COMPREPLY[@]}"', + want_output=True, + ) assert sorted(set(output.strip().split())) == sorted(expected) def test_no_globbing(self, bash): - assert_bash_exec( - bash, 'OLDHOME="$HOME"; HOME="%s/_known_hosts_real"' % bash.cwd - ) - output = assert_bash_exec( - bash, - "cd _known_hosts_real; " - "unset -v COMPREPLY COMP_KNOWN_HOSTS_WITH_HOSTFILE; " - "_known_hosts_real -aF config ''; " - r'printf "%s\n" "${COMPREPLY[@]}"; ' - "cd - &>/dev/null", - want_output=True, - ) - assert_bash_exec(bash, 'HOME="$OLDHOME"') + with bash_env_saved(bash) as bash_env: + bash_env.write_variable("HOME", "%s/_known_hosts" % bash.cwd) + bash_env.chdir("_known_hosts") + output = assert_bash_exec( + bash, + "unset -v COMPREPLY BASH_COMPLETION_KNOWN_HOSTS_WITH_HOSTFILE;" + " _comp_compgen_known_hosts -aF config ''; " + r'printf "%s\n" "${COMPREPLY[@]}"', + want_output=True, + ) completion = sorted(set(output.strip().split())) assert "gee" in completion assert "gee-filename-canary" not in completion diff --git a/test/t/unit/test_unit_load_completion.py b/test/t/unit/test_unit_load_completion.py new file mode 100644 index 0000000..6272e5b --- /dev/null +++ b/test/t/unit/test_unit_load_completion.py @@ -0,0 +1,94 @@ +import pytest + +from conftest import assert_bash_exec, bash_env_saved + + +@pytest.mark.bashcomp(cmd=None, cwd="_comp_load") +class TestLoadCompletion: + def test_userdir_1(self, bash): + with bash_env_saved(bash) as bash_env: + bash_env.write_variable( + "BASH_COMPLETION_USER_DIR", + "$PWD/userdir1:$PWD/userdir2:$BASH_COMPLETION_USER_DIR", + quote=False, + ) + bash_env.write_variable( + "PATH", "$PWD/prefix1/bin:$PWD/prefix1/sbin", quote=False + ) + output = assert_bash_exec( + bash, "_comp_load cmd1", want_output=True + ) + assert output.strip() == "cmd1: sourced from userdir1" + output = assert_bash_exec( + bash, "_comp_load cmd2", want_output=True + ) + assert output.strip() == "cmd2: sourced from userdir2" + + def test_PATH_1(self, bash): + with bash_env_saved(bash) as bash_env: + bash_env.write_variable( + "PATH", "$PWD/prefix1/bin:$PWD/prefix1/sbin", quote=False + ) + output = assert_bash_exec( + bash, "_comp_load cmd1", want_output=True + ) + assert output.strip() == "cmd1: sourced from prefix1" + output = assert_bash_exec( + bash, "_comp_load cmd2", want_output=True + ) + assert output.strip() == "cmd2: sourced from prefix1" + output = assert_bash_exec( + bash, "complete -p cmd2", want_output=True + ) + assert " cmd2" in output + output = assert_bash_exec( + bash, 'complete -p "$PWD/prefix1/sbin/cmd2"', want_output=True + ) + assert "/prefix1/sbin/cmd2" in output + + def test_cmd_path_1(self, bash): + assert_bash_exec(bash, "complete -r cmd1 || :", want_output=None) + output = assert_bash_exec( + bash, "_comp_load prefix1/bin/cmd1", want_output=True + ) + assert output.strip() == "cmd1: sourced from prefix1" + output = assert_bash_exec( + bash, 'complete -p "$PWD/prefix1/bin/cmd1"', want_output=True + ) + assert "/prefix1/bin/cmd1" in output + assert_bash_exec(bash, "! complete -p cmd1", want_output=None) + output = assert_bash_exec( + bash, "_comp_load prefix1/sbin/cmd2", want_output=True + ) + assert output.strip() == "cmd2: sourced from prefix1" + output = assert_bash_exec( + bash, "_comp_load bin/cmd1", want_output=True + ) + assert output.strip() == "cmd1: sourced from prefix1" + output = assert_bash_exec( + bash, "_comp_load bin/cmd2", want_output=True + ) + assert output.strip() == "cmd2: sourced from prefix1" + + def test_cmd_path_2(self, bash): + with bash_env_saved(bash) as bash_env: + bash_env.write_variable("PATH", "$PWD/bin:$PATH", quote=False) + output = assert_bash_exec( + bash, "_comp_load cmd1", want_output=True + ) + assert output.strip() == "cmd1: sourced from prefix1" + output = assert_bash_exec( + bash, "_comp_load cmd2", want_output=True + ) + assert output.strip() == "cmd2: sourced from prefix1" + + def test_cmd_intree_precedence(self, bash): + """ + Test in-tree, i.e. completions/$cmd relative to the main script + has precedence over location derived from PATH. + """ + with bash_env_saved(bash) as bash_env: + bash_env.write_variable("PATH", "$PWD/prefix1/bin", quote=False) + # The in-tree `sh` completion should be loaded here, + # and cause no output, unlike our `$PWD/prefix1/bin/sh` canary. + assert_bash_exec(bash, "_comp_load sh", want_output=False) diff --git a/test/t/unit/test_unit_longopt.py b/test/t/unit/test_unit_longopt.py index c5488e3..ab823d4 100644 --- a/test/t/unit/test_unit_longopt.py +++ b/test/t/unit/test_unit_longopt.py @@ -10,9 +10,9 @@ class TestUnitLongopt: @pytest.fixture(scope="class") def functions(self, request, bash): assert_bash_exec(bash, "_grephelp() { cat _longopt/grep--help.txt; }") - assert_bash_exec(bash, "complete -F _longopt _grephelp") + assert_bash_exec(bash, "complete -F _comp_complete_longopt _grephelp") assert_bash_exec(bash, "_various() { cat _longopt/various.txt; }") - assert_bash_exec(bash, "complete -F _longopt _various") + assert_bash_exec(bash, "complete -F _comp_complete_longopt _various") @pytest.mark.complete("_grephelp --") def test_1(self, functions, completion): diff --git a/test/t/unit/test_unit_looks_like_path.py b/test/t/unit/test_unit_looks_like_path.py new file mode 100644 index 0000000..3e86b48 --- /dev/null +++ b/test/t/unit/test_unit_looks_like_path.py @@ -0,0 +1,33 @@ +import shlex + +import pytest + +from conftest import TestUnitBase, assert_bash_exec + + +@pytest.mark.bashcomp(cmd=None) +class TestUnitQuote(TestUnitBase): + @pytest.mark.parametrize( + "thing_looks_like", + ( + ("", False), + ("foo", False), + ("/foo", True), + ("foo/", True), + ("foo/bar", True), + (".", True), + ("../", True), + ("~", True), + ("~foo", True), + ), + ) + def test_1(self, bash, thing_looks_like): + thing, looks_like = thing_looks_like + output = assert_bash_exec( + bash, + f"_comp_looks_like_path {shlex.quote(thing)}; printf %s $?", + want_output=True, + want_newline=False, + ) + is_zero = output.strip() == "0" + assert (looks_like and is_zero) or (not looks_like and not is_zero) diff --git a/test/t/unit/test_unit_parse_help.py b/test/t/unit/test_unit_parse_help.py index 4a02155..1a46f3f 100644 --- a/test/t/unit/test_unit_parse_help.py +++ b/test/t/unit/test_unit_parse_help.py @@ -2,29 +2,29 @@ import pytest -from conftest import assert_bash_exec +from conftest import assert_bash_exec, bash_env_saved @pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+declare -f fn$") class TestUnitParseHelp: def test_1(self, bash): assert_bash_exec(bash, "fn() { echo; }") - output = assert_bash_exec(bash, "_parse_help fn") + output = assert_bash_exec(bash, "_parse_help fn; (($? == 1))") assert not output def test_2(self, bash): assert_bash_exec(bash, "fn() { echo 'no dashes here'; }") - output = assert_bash_exec(bash, "_parse_help fn") + output = assert_bash_exec(bash, "_parse_help fn; (($? == 1))") assert not output def test_3(self, bash): assert_bash_exec(bash, "fn() { echo 'internal-dash'; }") - output = assert_bash_exec(bash, "_parse_help fn") + output = assert_bash_exec(bash, "_parse_help fn; (($? == 1))") assert not output def test_4(self, bash): assert_bash_exec(bash, "fn() { echo 'no -leading-dashes'; }") - output = assert_bash_exec(bash, "_parse_help fn") + output = assert_bash_exec(bash, "_parse_help fn; (($? == 1))") assert not output def test_5(self, bash): @@ -94,6 +94,20 @@ class TestUnitParseHelp: output = assert_bash_exec(bash, "_parse_help fn", want_output=True) assert output.split() == "--foo".split() + def test_17_failglob(self, bash): + assert_bash_exec(bash, "fn() { echo '--foo[=bar]'; }") + with bash_env_saved(bash) as bash_env: + bash_env.shopt("failglob", True) + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--foo".split() + + def test_17_nullglob(self, bash): + assert_bash_exec(bash, "fn() { echo '--foo[=bar]'; }") + with bash_env_saved(bash) as bash_env: + bash_env.shopt("nullglob", True) + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--foo".split() + def test_18(self, bash): assert_bash_exec(bash, "fn() { echo '--foo=<bar>'; }") output = assert_bash_exec(bash, "_parse_help fn", want_output=True) @@ -144,6 +158,13 @@ class TestUnitParseHelp: output = assert_bash_exec(bash, "_parse_help fn", want_output=True) assert output.split() == "--foo".split() + def test_27_middle_dot(self, bash): + """We do not want to include the period at the end of the sentence but + want to include dots connecting names.""" + assert_bash_exec(bash, "fn() { echo '--foo.bar.'; }") + output = assert_bash_exec(bash, "_parse_help fn", want_output=True) + assert output.split() == "--foo.bar".split() + def test_28(self, bash): assert_bash_exec(bash, "fn() { echo '-f or --foo'; }") output = assert_bash_exec(bash, "_parse_help fn", want_output=True) @@ -161,7 +182,7 @@ class TestUnitParseHelp: assert_bash_exec( bash, r"fn() { printf '%s\n' $'----\n---foo\n----- bar'; }" ) - output = assert_bash_exec(bash, "_parse_help fn") + output = assert_bash_exec(bash, "_parse_help fn; (($? == 1))") assert not output def test_31(self, bash): @@ -181,3 +202,33 @@ class TestUnitParseHelp: ) output = assert_bash_exec(bash, "_parse_help fn", want_output=True) assert output.split() == "--exclude=".split() + + def test_custom_helpopt1(self, bash): + assert_bash_exec(bash, "fn() { [[ $1 == -h ]] && echo '-option'; }") + output = assert_bash_exec(bash, "_parse_help fn -h", want_output=True) + assert output.split() == "-option".split() + + def test_custom_helpopt2(self, bash): + assert_bash_exec(bash, "fn() { [[ $1 == '-?' ]] && echo '-option'; }") + output = assert_bash_exec( + bash, "_parse_help fn '-?'", want_output=True + ) + assert output.split() == "-option".split() + + def test_custom_helpopt2_failglob(self, bash): + assert_bash_exec(bash, "fn() { [[ $1 == '-?' ]] && echo '-option'; }") + with bash_env_saved(bash) as bash_env: + bash_env.shopt("failglob", True) + output = assert_bash_exec( + bash, "_parse_help fn '-?'", want_output=True + ) + assert output.split() == "-option".split() + + def test_custom_helpopt2_nullglob(self, bash): + assert_bash_exec(bash, "fn() { [[ $1 == '-?' ]] && echo '-option'; }") + with bash_env_saved(bash) as bash_env: + bash_env.shopt("nullglob", True) + output = assert_bash_exec( + bash, "_parse_help fn '-?'", want_output=True + ) + assert output.split() == "-option".split() diff --git a/test/t/unit/test_unit_parse_usage.py b/test/t/unit/test_unit_parse_usage.py index f0cb711..0106922 100644 --- a/test/t/unit/test_unit_parse_usage.py +++ b/test/t/unit/test_unit_parse_usage.py @@ -1,18 +1,18 @@ import pytest -from conftest import assert_bash_exec +from conftest import assert_bash_exec, bash_env_saved @pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+declare -f fn$") class TestUnitParseUsage: def test_1(self, bash): assert_bash_exec(bash, "fn() { echo; }") - output = assert_bash_exec(bash, "_parse_usage fn") + output = assert_bash_exec(bash, "_parse_usage fn; (($? == 1))") assert not output def test_2(self, bash): assert_bash_exec(bash, "fn() { echo 'no dashes here'; }") - output = assert_bash_exec(bash, "_parse_usage fn") + output = assert_bash_exec(bash, "_parse_usage fn; (($? == 1))") assert not output def test_3(self, bash): @@ -59,7 +59,7 @@ class TestUnitParseUsage: assert_bash_exec( bash, "fn() { echo ----; echo ---foo; echo '----- bar'; }" ) - output = assert_bash_exec(bash, "_parse_usage fn") + output = assert_bash_exec(bash, "_parse_usage fn; (($? == 1))") assert not output def test_12(self, bash): @@ -67,3 +67,41 @@ class TestUnitParseUsage: bash, "echo '[-duh]' | _parse_usage -", want_output=True ) assert output.split() == "-d -u -h".split() + + def test_custom_helpopt1(self, bash): + assert_bash_exec( + bash, "fn() { [[ $1 == -h ]] && echo 'fn [-option]'; true; }" + ) + output = assert_bash_exec(bash, "_parse_usage fn -h", want_output=True) + assert output.split() == "-o -p -t -i -o -n".split() + + def test_custom_helpopt2(self, bash): + assert_bash_exec( + bash, "fn() { [[ $1 == '-?' ]] && echo 'fn [-option]'; }" + ) + output = assert_bash_exec( + bash, "_parse_usage fn '-?'", want_output=True + ) + assert output.split() == "-o -p -t -i -o -n".split() + + def test_custom_helpopt2_failglob(self, bash): + assert_bash_exec( + bash, "fn() { [[ $1 == '-?' ]] && echo 'fn [-option]'; }" + ) + with bash_env_saved(bash) as bash_env: + bash_env.shopt("failglob", True) + output = assert_bash_exec( + bash, "_parse_usage fn '-?'", want_output=True + ) + assert output.split() == "-o -p -t -i -o -n".split() + + def test_custom_helpopt2_nullglob(self, bash): + assert_bash_exec( + bash, "fn() { [[ $1 == '-?' ]] && echo 'fn [-option]'; }" + ) + with bash_env_saved(bash) as bash_env: + bash_env.shopt("nullglob", True) + output = assert_bash_exec( + bash, "_parse_usage fn '-?'", want_output=True + ) + assert output.split() == "-o -p -t -i -o -n".split() diff --git a/test/t/unit/test_unit_pgids.py b/test/t/unit/test_unit_pgids.py new file mode 100644 index 0000000..05019ec --- /dev/null +++ b/test/t/unit/test_unit_pgids.py @@ -0,0 +1,34 @@ +import os + +import pytest + +from conftest import assert_bash_exec, bash_env_saved + + +@pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+(COMPREPLY|cur)=") +class TestUnitPgids: + def test_smoke(self, bash): + with bash_env_saved(bash) as bash_env: + bash_env.write_variable("cur", "") + assert_bash_exec(bash, "_comp_compgen_pgids >/dev/null") + + def test_non_pollution(self, bash): + """Test environment non-pollution, detected at teardown.""" + assert_bash_exec( + bash, + "foo() { local cur=; _comp_compgen_pgids; }; foo; unset -f foo", + ) + + def test_ints(self, bash): + """Test that we get something sensible, and only int'y strings.""" + with bash_env_saved(bash) as bash_env: + bash_env.write_variable("cur", "") + completion = assert_bash_exec( + bash, + r'_comp_compgen_pgids; printf "%s\n" "${COMPREPLY[@]}"', + want_output=True, + ).split() + assert completion + if hasattr(os, "getpgid"): + assert str(os.getpgid(0)) in completion + assert all(x.isdigit() for x in completion) diff --git a/test/t/unit/test_unit_pids.py b/test/t/unit/test_unit_pids.py new file mode 100644 index 0000000..3681c8c --- /dev/null +++ b/test/t/unit/test_unit_pids.py @@ -0,0 +1,34 @@ +import os + +import pytest + +from conftest import assert_bash_exec, bash_env_saved + + +@pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+COMPREPLY=") +class TestUnitPids: + def test_smoke(self, bash): + with bash_env_saved(bash) as bash_env: + bash_env.write_variable("cur", "") + assert_bash_exec(bash, "_comp_compgen_pids >/dev/null") + + def test_non_pollution(self, bash): + """Test environment non-pollution, detected at teardown.""" + assert_bash_exec( + bash, + "foo() { local cur=; _comp_compgen_pids; }; foo; unset -f foo", + ) + + def test_ints(self, bash): + """Test that we get something sensible, and only int'y strings.""" + with bash_env_saved(bash) as bash_env: + bash_env.write_variable("cur", "") + completion = assert_bash_exec( + bash, + r'_comp_compgen_pids; printf "%s\n" "${COMPREPLY[@]}"', + want_output=True, + ).split() + assert completion + if hasattr(os, "getpid"): + assert str(os.getpid()) in completion + assert all(x.isdigit() for x in completion) diff --git a/test/t/unit/test_unit_pnames.py b/test/t/unit/test_unit_pnames.py new file mode 100644 index 0000000..e0819e5 --- /dev/null +++ b/test/t/unit/test_unit_pnames.py @@ -0,0 +1,29 @@ +import pytest + +from conftest import assert_bash_exec, bash_env_saved + + +@pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+COMPREPLY=") +class TestUnitPnames: + def test_smoke(self, bash): + with bash_env_saved(bash) as bash_env: + bash_env.write_variable("cur", "") + assert_bash_exec(bash, "_comp_compgen_pnames >/dev/null") + + def test_non_pollution(self, bash): + """Test environment non-pollution, detected at teardown.""" + assert_bash_exec( + bash, + "foo() { local cur=; _comp_compgen_pnames; }; foo; unset -f foo", + ) + + def test_something(self, bash): + """Test that we get something.""" + with bash_env_saved(bash) as bash_env: + bash_env.write_variable("cur", "") + completion = assert_bash_exec( + bash, + r'_comp_compgen_pids; printf "%s\n" "${COMPREPLY[@]}"', + want_output=True, + ).split() + assert completion diff --git a/test/t/unit/test_unit_quote.py b/test/t/unit/test_unit_quote.py index b280bd6..3508782 100644 --- a/test/t/unit/test_unit_quote.py +++ b/test/t/unit/test_unit_quote.py @@ -3,34 +3,41 @@ import pytest from conftest import TestUnitBase, assert_bash_exec -@pytest.mark.bashcomp(cmd=None) +@pytest.mark.bashcomp( + cmd=None, + ignore_env=r"^\+declare -f __tester$", +) class TestUnitQuote(TestUnitBase): def test_1(self, bash): + assert_bash_exec( + bash, + '__tester() { local REPLY; _comp_quote "$1"; printf %s "$REPLY"; }', + ) output = assert_bash_exec( - bash, 'quote "a b"', want_output=True, want_newline=False + bash, '__tester "a b"', want_output=True, want_newline=False ) assert output.strip() == "'a b'" def test_2(self, bash): output = assert_bash_exec( - bash, 'quote "a b"', want_output=True, want_newline=False + bash, '__tester "a b"', want_output=True, want_newline=False ) assert output.strip() == "'a b'" def test_3(self, bash): output = assert_bash_exec( - bash, 'quote " a "', want_output=True, want_newline=False + bash, '__tester " a "', want_output=True, want_newline=False ) assert output.strip() == "' a '" def test_4(self, bash): output = assert_bash_exec( - bash, "quote \"a'b'c\"", want_output=True, want_newline=False + bash, "__tester \"a'b'c\"", want_output=True, want_newline=False ) assert output.strip() == r"'a'\''b'\''c'" def test_5(self, bash): output = assert_bash_exec( - bash, 'quote "a\'"', want_output=True, want_newline=False + bash, '__tester "a\'"', want_output=True, want_newline=False ) assert output.strip() == r"'a'\'''" diff --git a/test/t/unit/test_unit_quote_compgen.py b/test/t/unit/test_unit_quote_compgen.py new file mode 100644 index 0000000..faf23fe --- /dev/null +++ b/test/t/unit/test_unit_quote_compgen.py @@ -0,0 +1,173 @@ +import os + +import pytest + +from conftest import assert_bash_exec, assert_complete, bash_env_saved + + +@pytest.mark.bashcomp(cmd=None, temp_cwd=True) +class TestUnitQuoteCompgen: + @pytest.fixture(scope="class") + def functions(self, bash): + assert_bash_exec( + bash, + '_comp__test_quote_compgen() { local REPLY; _comp_quote_compgen "$1"; printf %s "$REPLY"; }', + ) + + @pytest.mark.parametrize( + "funcname", "_comp__test_quote_compgen quote_readline".split() + ) + def test_exec(self, bash, functions, funcname): + assert_bash_exec(bash, "%s '' >/dev/null" % funcname) + + @pytest.mark.parametrize( + "funcname", "_comp__test_quote_compgen quote_readline".split() + ) + def test_env_non_pollution(self, bash, functions, funcname): + """Test environment non-pollution, detected at teardown.""" + assert_bash_exec( + bash, "foo() { %s meh >/dev/null; }; foo; unset -f foo" % funcname + ) + + @pytest.mark.parametrize( + "funcname", "_comp__test_quote_compgen quote_readline".split() + ) + def test_1(self, bash, functions, funcname): + output = assert_bash_exec( + bash, "%s '';echo" % funcname, want_output=True + ) + assert output.strip() == "''" + + @pytest.mark.parametrize( + "funcname", "_comp__test_quote_compgen quote_readline".split() + ) + def test_2(self, bash, functions, funcname): + output = assert_bash_exec( + bash, "%s foo;echo" % funcname, want_output=True + ) + assert output.strip() == "foo" + + @pytest.mark.parametrize( + "funcname", "_comp__test_quote_compgen quote_readline".split() + ) + def test_3(self, bash, functions, funcname): + output = assert_bash_exec( + bash, '%s foo\\"bar;echo' % funcname, want_output=True + ) + assert output.strip() == 'foo\\"bar' + + @pytest.mark.parametrize( + "funcname", "_comp__test_quote_compgen quote_readline".split() + ) + def test_4(self, bash, functions, funcname): + output = assert_bash_exec( + bash, "%s '$(echo x >&2)';echo" % funcname, want_output=True + ) + assert output.strip() == "\\$\\(echo\\ x\\ \\>\\&2\\)" + + def test_github_issue_189_1(self, bash, functions): + """Test error messages on a certain command line + + Reported at https://github.com/scop/bash-completion/issues/189 + + Syntax error messages should not be shown by completion on the + following line: + + $ ls -- '${[TAB] + $ rm -- '${[TAB] + + """ + assert_bash_exec(bash, "_comp__test_quote_compgen $'\\'${' >/dev/null") + + def test_github_issue_492_1(self, bash, functions): + """Test unintended code execution on a certain command line + + Reported at https://github.com/scop/bash-completion/pull/492 + + Arbitrary commands could be unintendedly executed by + _comp_quote_compgen. In the following example, the command "touch + 1.txt" would be unintendedly created before the fix. The file "1.txt" + should not be created by completion on the following line: + + $ echo '$(touch file.txt)[TAB] + + """ + assert_bash_exec( + bash, "_comp__test_quote_compgen $'\\'$(touch 1.txt)' >/dev/null" + ) + assert not os.path.exists("./1.txt") + + def test_github_issue_492_2(self, bash, functions): + """Test the file clear by unintended redirection on a certain command line + + Reported at https://github.com/scop/bash-completion/pull/492 + + The file "1.0" should not be created by completion on the following + line: + + $ awk '$1 > 1.0[TAB] + + """ + assert_bash_exec( + bash, "_comp__test_quote_compgen $'\\'$1 > 1.0' >/dev/null" + ) + assert not os.path.exists("./1.0") + + def test_github_issue_492_3(self, bash, functions): + """Test code execution through unintended pathname expansions + + When there is a file named "quote=$(COMMAND)" (for + _comp_compgen_filedir) or "REPLY=$(COMMAND)" (for _comp_quote_compgen), + the completion of the word '$* results in the execution of COMMAND. + + $ echo '$*[TAB] + + """ + os.mkdir("./REPLY=$(echo injected >&2)") + assert_bash_exec(bash, "_comp__test_quote_compgen $'\\'$*' >/dev/null") + + def test_github_issue_492_4(self, bash, functions): + """Test error messages through unintended pathname expansions + + When "shopt -s failglob" is set by the user, the completion of the word + containing glob character and special characters (e.g. TAB) results in + the failure of pathname expansions. + + $ shopt -s failglob + $ echo a\\ b*[TAB] + + """ + with bash_env_saved(bash) as bash_env: + bash_env.shopt("failglob", True) + assert_bash_exec( + bash, "_comp__test_quote_compgen $'a\\\\\\tb*' >/dev/null" + ) + + def test_github_issue_526_1(self, bash): + r"""Regression tests for unprocessed escape sequences after quotes + + Ref [1] https://github.com/scop/bash-completion/pull/492#discussion_r637213822 + Ref [2] https://github.com/scop/bash-completion/pull/526 + + The escape sequences in the local variable of "value" in + "_comp_quote_compgen" needs to be unescaped by passing it to printf as + the format string. This causes a problem in the following case [where + the spaces after "alpha\" is a TAB character inserted in the command + string by "C-v TAB"]: + + $ echo alpha\ b[TAB] + + """ + os.mkdir("./alpha\tbeta") + assert ( + assert_complete( + # Remark on "rendered_cmd": Bash aligns the last character 'b' + # in the rendered cmd to an "8 x n" boundary using spaces. + # Here, the command string is assumed to start from column 2 + # because the width of PS1 (conftest.PS1 = '/@') is 2, + bash, + "echo alpha\\\026\tb", + rendered_cmd="echo alpha\\ b", + ) + == "eta/" + ) diff --git a/test/t/unit/test_unit_quote_readline.py b/test/t/unit/test_unit_quote_readline.py deleted file mode 100644 index e2b437e..0000000 --- a/test/t/unit/test_unit_quote_readline.py +++ /dev/null @@ -1,15 +0,0 @@ -import pytest - -from conftest import assert_bash_exec - - -@pytest.mark.bashcomp(cmd=None) -class TestUnitQuoteReadline: - def test_exec(self, bash): - assert_bash_exec(bash, "quote_readline '' >/dev/null") - - def test_env_non_pollution(self, bash): - """Test environment non-pollution, detected at teardown.""" - assert_bash_exec( - bash, "foo() { quote_readline meh >/dev/null; }; foo; unset foo" - ) diff --git a/test/t/unit/test_unit_realcommand.py b/test/t/unit/test_unit_realcommand.py new file mode 100644 index 0000000..4eb7b73 --- /dev/null +++ b/test/t/unit/test_unit_realcommand.py @@ -0,0 +1,90 @@ +import pytest + +from conftest import assert_bash_exec, bash_env_saved + + +@pytest.mark.bashcomp( + cmd=None, cwd="shared", ignore_env=r"^\+declare -f __tester$" +) +class TestUnitRealCommand: + @pytest.fixture + def functions(self, bash): + assert_bash_exec( + bash, + ( + "__tester() { " + "local REPLY rc; " + '_comp_realcommand "$1"; ' + "rc=$?; " + 'printf %s "$REPLY"; ' + "return $rc; " + "}" + ), + ) + + def test_non_pollution(self, bash): + """Test environment non-pollution, detected at teardown.""" + assert_bash_exec( + bash, + "foo() { local REPLY=; _comp_realcommand bar; }; foo; unset -f foo", + want_output=None, + ) + + def test_basename(self, bash, functions): + with bash_env_saved(bash) as bash_env: + bash_env.write_variable("PATH", "$PWD/bin:$PATH", quote=False) + output = assert_bash_exec( + bash, + "__tester arp", + want_output=True, + want_newline=False, + ) + assert output.strip().endswith("/shared/bin/arp") + + def test_basename_nonexistent(self, bash, functions): + filename = "non-existent-file-for-bash-completion-tests" + skipif = "! type -P %s" % filename + try: + assert_bash_exec(bash, skipif, want_output=None) + except AssertionError: + pytest.skipif(skipif) + output = assert_bash_exec( + bash, + "! __tester %s" % filename, + want_output=False, + ) + assert output.strip() == "" + + def test_relative(self, bash, functions): + output = assert_bash_exec( + bash, + "__tester bin/arp", + want_output=True, + want_newline=False, + ) + assert output.strip().endswith("/shared/bin/arp") + + def test_relative_nonexistent(self, bash, functions): + output = assert_bash_exec( + bash, + "! __tester bin/non-existent", + want_output=False, + ) + assert output.strip() == "" + + def test_absolute(self, bash, functions): + output = assert_bash_exec( + bash, + '__tester "$PWD/bin/arp"', + want_output=True, + want_newline=False, + ) + assert output.strip().endswith("/shared/bin/arp") + + def test_absolute_nonexistent(self, bash, functions): + output = assert_bash_exec( + bash, + '! __tester "$PWD/bin/non-existent"', + want_output=False, + ) + assert output.strip() == "" diff --git a/test/t/unit/test_unit_split.py b/test/t/unit/test_unit_split.py new file mode 100644 index 0000000..d1f228e --- /dev/null +++ b/test/t/unit/test_unit_split.py @@ -0,0 +1,90 @@ +import pytest + +from conftest import assert_bash_exec, bash_env_saved + + +@pytest.mark.bashcomp( + cmd=None, ignore_env=r"^\+declare -f (dump_array|__tester)$" +) +class TestUtilSplit: + @pytest.fixture + def functions(self, bash): + assert_bash_exec( + bash, "dump_array() { printf '<%s>' \"${arr[@]}\"; echo; }" + ) + assert_bash_exec( + bash, + '__tester() { local -a arr=(00); _comp_split "${@:1:$#-1}" arr "${@:$#}"; dump_array; }', + ) + + def test_1(self, bash, functions): + output = assert_bash_exec( + bash, "__tester '12 34 56'", want_output=True + ) + assert output.strip() == "<12><34><56>" + + def test_2(self, bash, functions): + output = assert_bash_exec( + bash, "__tester $'12\\n34\\n56'", want_output=True + ) + assert output.strip() == "<12><34><56>" + + def test_3(self, bash, functions): + output = assert_bash_exec( + bash, "__tester '12:34:56'", want_output=True + ) + assert output.strip() == "<12:34:56>" + + def test_option_F_1(self, bash, functions): + output = assert_bash_exec( + bash, "__tester -F : '12:34:56'", want_output=True + ) + assert output.strip() == "<12><34><56>" + + def test_option_F_2(self, bash, functions): + output = assert_bash_exec( + bash, "__tester -F : '12 34 56'", want_output=True + ) + assert output.strip() == "<12 34 56>" + + def test_option_l_1(self, bash, functions): + output = assert_bash_exec( + bash, "__tester -l $'12\\n34\\n56'", want_output=True + ) + assert output.strip() == "<12><34><56>" + + def test_option_l_2(self, bash, functions): + output = assert_bash_exec( + bash, "__tester -l '12 34 56'", want_output=True + ) + assert output.strip() == "<12 34 56>" + + def test_option_a_1(self, bash, functions): + output = assert_bash_exec( + bash, "__tester -aF : '12:34:56'", want_output=True + ) + assert output.strip() == "<00><12><34><56>" + + def test_protect_from_failglob(self, bash, functions): + with bash_env_saved(bash) as bash_env: + bash_env.shopt("failglob", True) + output = assert_bash_exec( + bash, "__tester -F '*' '12*34*56'", want_output=True + ) + assert output.strip() == "<12><34><56>" + + def test_protect_from_nullglob(self, bash, functions): + with bash_env_saved(bash) as bash_env: + bash_env.shopt("nullglob", True) + output = assert_bash_exec( + bash, "__tester -F '*' '12*34*56'", want_output=True + ) + assert output.strip() == "<12><34><56>" + + def test_protect_from_IFS(self, bash, functions): + with bash_env_saved(bash) as bash_env: + bash_env.write_variable("IFS", "34") + output = assert_bash_exec( + bash, "__tester '12 34 56'", want_output=True + ) + assert output.strip() == "<12><34><56>" diff --git a/test/t/unit/test_unit_tilde.py b/test/t/unit/test_unit_tilde.py index 35a4e4c..fae0dd6 100644 --- a/test/t/unit/test_unit_tilde.py +++ b/test/t/unit/test_unit_tilde.py @@ -6,23 +6,24 @@ from conftest import assert_bash_exec @pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+COMPREPLY=") class TestUnitTilde: def test_1(self, bash): - assert_bash_exec(bash, "_tilde >/dev/null") + assert_bash_exec(bash, "! _comp_compgen_tilde >/dev/null") def test_2(self, bash): """Test environment non-pollution, detected at teardown.""" assert_bash_exec( - bash, 'foo() { local aa="~"; _tilde "$aa"; }; foo; unset foo' + bash, + 'foo() { local aa="~"; _comp_compgen -c "$aa" tilde; }; foo; unset -f foo', ) def test_3(self, bash): """Test for https://bugs.debian.org/766163""" - assert_bash_exec(bash, "_tilde ~-o") + assert_bash_exec(bash, "! _comp_compgen -c ~-o tilde") def _test_part_full(self, bash, part, full): res = ( assert_bash_exec( bash, - '_tilde "~%s"; echo "${COMPREPLY[@]}"' % part, + '_comp_compgen -c "~%s" tilde; echo "${COMPREPLY[@]}"' % part, want_output=True, ) .strip() diff --git a/test/t/unit/test_unit_unlocal.py b/test/t/unit/test_unit_unlocal.py new file mode 100644 index 0000000..be5ec56 --- /dev/null +++ b/test/t/unit/test_unit_unlocal.py @@ -0,0 +1,18 @@ +import pytest + +from conftest import assert_bash_exec + + +@pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+(VAR=|declare -f foo)") +class TestUnlocal: + def test_1(self, bash): + cmd = ( + "foo() { " + "local VAR=inner; " + "_comp_unlocal VAR; " + "echo $VAR; " + "}; " + "VAR=outer; foo; " + ) + res = assert_bash_exec(bash, cmd, want_output=True).strip() + assert res == "outer" diff --git a/test/t/unit/test_unit_variables.py b/test/t/unit/test_unit_variables.py index d62bc4a..f15d249 100644 --- a/test/t/unit/test_unit_variables.py +++ b/test/t/unit/test_unit_variables.py @@ -11,7 +11,7 @@ class TestUnitVariables: assert_bash_exec( bash, "unset assoc2 && declare -A assoc2=([idx1]=1 [idx2]=2)" ) - assert_bash_exec(bash, "unset ${!___v*} && declare ___var=''") + assert_bash_exec(bash, 'unset ${!___v*} && declare ___var=""') request.addfinalizer( lambda: assert_bash_exec(bash, "unset ___var assoc1 assoc2") ) @@ -28,6 +28,10 @@ class TestUnitVariables: def test_multiple_array_indexes(self, functions, completion): assert completion == "${assoc2[idx1]} ${assoc2[idx2]}".split() + @pytest.mark.complete(": ${assoc2[", shopt=dict(failglob=True)) + def test_multiple_array_indexes_failglob(self, functions, completion): + assert completion == "${assoc2[idx1]} ${assoc2[idx2]}".split() + @pytest.mark.complete(": ${assoc1[bogus]") def test_closing_curly_after_square(self, functions, completion): assert completion == "}" diff --git a/test/t/unit/test_unit_xfunc.py b/test/t/unit/test_unit_xfunc.py new file mode 100644 index 0000000..3fb3a72 --- /dev/null +++ b/test/t/unit/test_unit_xfunc.py @@ -0,0 +1,71 @@ +import pytest + +from conftest import assert_bash_exec, bash_env_saved + + +@pytest.mark.bashcomp(cmd=None) +class TestUnitXfunc: + def test_1(self, bash): + with bash_env_saved(bash) as bash_env: + bash_env.write_variable( + "BASH_COMPLETION_USER_DIR", "$PWD/_comp_xfunc", quote=False + ) + + # test precondition + assert_bash_exec( + bash, + "! declare -F _comp_xfunc_xfunc_test1_utility1 &>/dev/null", + ) + + # first invocation (completion/xfunc-test1 is sourced) + output = assert_bash_exec( + bash, + "_comp_xfunc xfunc-test1 utility1 'a b' cde fgh", + want_output=True, + ) + assert output.strip() == "util1[<a b><cde><fgh>]" + + # test precondition + assert_bash_exec( + bash, "declare -F _comp_xfunc_xfunc_test1_utility1 &>/dev/null" + ) + + # second invocation (completion/xfunc-test1 is not sourced) + output = assert_bash_exec( + bash, + "_comp_xfunc xfunc-test1 utility1 'a b' cde fgh", + want_output=True, + ) + assert output.strip() == "util1[<a b><cde><fgh>]" + + def test_2(self, bash): + with bash_env_saved(bash) as bash_env: + bash_env.write_variable( + "BASH_COMPLETION_USER_DIR", "$PWD/_comp_xfunc", quote=False + ) + + # test precondition + assert_bash_exec( + bash, "! declare -F _comp_xfunc_non_standard_name &>/dev/null" + ) + + # first invocation (completion/xfunc-test2 is sourced) + output = assert_bash_exec( + bash, + "_comp_xfunc xfunc-test2 _comp_xfunc_non_standard_name 'a b' cde fgh", + want_output=True, + ) + assert output.strip() == "util2[<a b><cde><fgh>]" + + # test precondition + assert_bash_exec( + bash, "declare -F _comp_xfunc_non_standard_name &>/dev/null" + ) + + # second invocation (completion/xfunc-test2 is not sourced) + output = assert_bash_exec( + bash, + "_comp_xfunc xfunc-test2 _comp_xfunc_non_standard_name 'a b' cde fgh", + want_output=True, + ) + assert output.strip() == "util2[<a b><cde><fgh>]" diff --git a/test/t/unit/test_unit_xinetd_services.py b/test/t/unit/test_unit_xinetd_services.py index 7a90cb7..a9e33a9 100644 --- a/test/t/unit/test_unit_xinetd_services.py +++ b/test/t/unit/test_unit_xinetd_services.py @@ -6,17 +6,19 @@ from conftest import assert_bash_exec @pytest.mark.bashcomp(cmd=None, ignore_env=r"^\+COMPREPLY=") class TestUnitXinetdServices: def test_direct(self, bash): - assert_bash_exec(bash, "_xinetd_services >/dev/null") + assert_bash_exec(bash, "_comp_compgen_xinetd_services >/dev/null") def test_env_non_pollution(self, bash): """Test environment non-pollution, detected at teardown.""" - assert_bash_exec(bash, "foo() { _xinetd_services; }; foo; unset foo") + assert_bash_exec( + bash, "foo() { _comp_compgen_xinetd_services; }; foo; unset -f foo" + ) def test_basic(self, bash): output = assert_bash_exec( bash, - "foo() { local BASHCOMP_XINETDDIR=$PWD/shared/bin;unset COMPREPLY; " - '_xinetd_services; printf "%s\\n" "${COMPREPLY[@]}"; }; foo; unset foo', + "foo() { local _comp__test_xinetd_dir=$PWD/shared/bin; unset -v COMPREPLY; " + '_comp_compgen_xinetd_services; printf "%s\\n" "${COMPREPLY[@]}"; }; foo; unset -f foo', want_output=True, ) assert sorted(output.split()) == ["arp", "ifconfig"] diff --git a/test/test-cmd-list.txt b/test/test-cmd-list.txt index eb8398e..5dda3e0 100644 --- a/test/test-cmd-list.txt +++ b/test/test-cmd-list.txt @@ -5,107 +5,54 @@ a2x abook aclocal acpi -acroread adb -add_members -alias alpine -animate ant -apache2ctl appdata-validate -apt-build apt-cache -apt-get aptitude arch arp arping arpspoof asciidoc -aspell -autoconf -autoheader automake -autoreconf -autorpm autoscan autossh -autoupdate -avctrl +avahi-browse awk +b2sum badblocks base64 bash bc -/bin/chroot bind -/bin/rmdir bison -bk bmake -brctl -bsdtar -btdownloadcurses.py -btdownloadgui.py -btdownloadheadless.py -bts -bzip2 -c++ cal -cancel -cardctl carton cat -cc ccache ccze -cd -cdrecord cfagent -cfrun chage -change_pw -check_db -check_perms checksec -chfn -chgrp -chkconfig chmod -chown chpasswd -chromium-browser chronyc chroot chrpath chsh -ci -ciptool civclient civserver cksfv -cleanarch -clisp -clone_member -co colordiff -compare -compgen -complete -composite -config_list configure -conjure convert -cowsay cp cpan2dist -cpio cppcheck createdb -createuser -crontab cryptsetup csplit curl @@ -119,7 +66,6 @@ declare deja-dup desktop-file-validate df -dfutool dhclient dict diff @@ -127,80 +73,47 @@ dir display dmesg dmypy -dnssec-keygen dnsspoof -dot dpkg dpkg-deb dpkg-query -dpkg-reconfigure -dpkg-source dropdb -dropuser dselect -dsniff du -dumpdb dumpe2fs e2freefrag -e2label -ebtables ecryptfs-migrate-home eject enscript env eog -etherwake ether-wake evince expand -explodepkg export faillog -fbgs -fbi feh file filefrag -file-roller filesnarf -find -find_member -finger fio firefox flake8 fmt fold -freebsd-update freeciv freeciv-server -function fusermount -g++ -g4 -g77 -gcc -gcj -gcl -gdb -genaliases -gendiff genisoimage geoiplookup -getconf getent gkrellm gm -gmplayer -gnatmake gnokii gnome-mplayer gnome-screenshot gpasswd -gpc gperf -gpg gpg2 gpgv gphoto2 @@ -210,125 +123,71 @@ groupadd groupdel groupmems groupmod -growisofs grpck grub +gssdp-device-sniffer gssdp-discover gzip -hciattach -hciconfig +hash hcitool -hddtemp head hexdump -hid2hci host hostname hping2 -hping3 htop htpasswd hunspell hwclock iconv -id identify idn -ifdown ifstat iftop ifup -import influx info -inject inotifywait inotifywatch -insmod -installpkg interdiff -invoke-rc.d ionice ip ipcalc iperf iperf3 ipmitool -ipsec iptables ipv6calc irb -iscsiadm isort -isql -iwconfig -iwlist -iwpriv -iwspy -jar -jarsigner java -javac -javadoc javaws jpegoptim -jps -jq jshint jsonschema -json_xs k3b kcov -kdvi -kill killall -kldload -kldunload koji -kpdf -kplayer -ktutil l2ping -larch lastlog ld -ldapadd -ldapcompare -ldapdelete -ldapmodrdn -ldappasswd -ldapsearch ldapvi -ldapwhoami ldd less lftp -lftpget -lilo links -lintian lintian-info -lisp -list_admins -list_lists -list_members -list_owners ln locale-gen -look -lpq -lpr lrzip ls -lsof lspci lsscsi -lsusb lua luac luseradd luserdel -lusermod lvchange lvcreate lvdisplay @@ -343,11 +202,8 @@ lvs lvscan lz4 lzip -lzma -lzop m4 macof -mailmanctl mailsnarf make makepkg @@ -355,9 +211,6 @@ man mc mcrypt md5sum -mdadm -mdecrypt -mdtool medusa mencoder mii-diag @@ -365,63 +218,44 @@ mii-tool minicom mkdir mkfifo -mkinitrd -mkisofs mknod -mktemp -mmsitepass mock modinfo -modprobe -module -mogrify monodevelop -montage -mount mplayer mr msgsnarf -msynctool -mtx -munindoc munin-node-configure munin-run +munindoc mussh mutt -muttng mv mypy -mysql mysqladmin nc ncftp nethogs netstat -newgrp newlist newusers ngrep nl nm nmap -nmcli nproc -nslookup nsupdate ntpdate objcopy -objdump od oggdec -op openssl opera optipng -p4 -pack200 passwd paste patch +pdftoppm pdftotext perl perlcritic @@ -433,38 +267,23 @@ pidof pine pinfo ping -pkgadd pkg-config -pkg_deinstall -pkg_delete -pkg-get -pkg_info +pkgadd +pkgconf pkgrm -pkgtool -pkgutil pkill -plague-client -pm-hibernate -pm-is-supported -pm-powersave pngfix -portinstall -portsnap -portupgrade postcat postconf postfix postmap -postsuper -povray pr prelink printenv protoc +ps psql ptx -puppet -pushd pv pvchange pvcreate @@ -483,67 +302,47 @@ pydocstyle pyflakes pylint pylint-3 +pyston pytest python python3 -pyvenv qemu -qrunner +qemu-system-x86_64 querybts quota quotacheck quotaon radvdump -rcs -rcsdiff rdesktop rdict readelf -readonly -remove_members -removepkg -renice repomanage reportbug reptyr -resolvconf -rfcomm -rfkill ri -rlog rm rmdir -rmlist rmmod -route -rpcdebug rpm -rpm2tgz rpmbuild -rrdtool rsync rtcwake -runuser -sbcl -sbcl-mt sbopkg -scp screen scrub -sdptool secret-tool sed seq -service -set setquota sftp -sh sha1sum +sha224sum +sha256sum +sha384sum +sha512sum shar shellcheck sitecopy -slackpkg slapt-get slapt-src smartctl @@ -557,67 +356,48 @@ smbtree snownews sort split -spovray sqlite3 ss ssh ssh-add ssh-copy-id -sshfs ssh-keygen +ssh-keyscan sshmitm sshow strace -stream strings strip su sudo sum -svcadm -svk -svn -svnadmin -svnlook synclient -sync_members sysbench sysctl tac tail -tar tcpdump -tcpkill tcpnice tee texindex -tightvncviewer -time timeout -tipc -totem touch tox tr tracepath +tree +truncate tshark tsig-keygen tune2fs udevadm ulimit -umount -unace uname unexpand uniq units -unpack200 -unrar -unset unshunt update-alternatives -update-rc.d -upgradepkg urlsnarf uscan useradd @@ -643,45 +423,36 @@ vgrename vgs vgscan vgsplit -vi vipw vmstat -vncviewer vpnc watch wc webmitm wget who -wine -withlist -wodim wol -write wsimport wtf wvdial xdg-mime xdg-settings +xev xfreerdp xgamma -xm xmllint xmlwf xmms xmodmap -xpovray xrandr xrdb xsltproc xvfb-run -xvnc4viewer xxd xz xzdec ypcat ypmatch yum -yum-arch zopfli zopflipng diff --git a/test/update-test-cmd-list b/test/update-test-cmd-list index 115ae16..20224b4 100755 --- a/test/update-test-cmd-list +++ b/test/update-test-cmd-list @@ -1,4 +1,5 @@ -#!/bin/bash -eu +#!/usr/bin/env bash +set -eu mydir=$( cd "$(dirname "$0")" @@ -7,7 +8,7 @@ mydir=$( cat "$mydir"/t/test_*.py | tr -d '\n' | - grep -Eo '@pytest.mark.complete(\([^)]*\))' | - sed -ne 's/^[^"]*"\\\?\([^_][^[:space:]"]*\)[[:space:]"].*/\1/p' | - sort -u \ + grep -Eo '@pytest.mark.complete\(([^)]*\<require_(cmd|longopt) *= *True\>[^)]*)\)' | + sed -ne 's/^[^"]*"\\\{0,1\}\([^_][^[:space:]"]*\)[[:space:]"].*/\1/p' | + LC_ALL=C sort -u \ >"$mydir"/test-cmd-list.txt diff --git a/version.txt b/version.txt new file mode 100644 index 0000000..d8b6989 --- /dev/null +++ b/version.txt @@ -0,0 +1 @@ +2.12.0 |