Thanks to visit codestin.com
Credit goes to GitHub.com

Skip to content

Conversation

@oldium
Copy link
Contributor

@oldium oldium commented Feb 19, 2025

The spaces are not handled well in bash completion, the offered result needs to be escaped. Fix parsing the word list and add quotation around suggestions with spaces. See here for the discussion.

The spaces are not handled well in bash completion, the offered result
needs to be escaped. Fix parsing the word list and add quotation around
suggestions with spaces. See [here][1] for the details.

[1]: https://stackoverflow.com/a/40944195/7080036

Signed-off-by: Oldřich Jedlička <[email protected]>
@shadowspawn
Copy link
Member

What is an example of this being a problem with yargs completion? (Did you encounter this?)

I understand the theoretical problem, but I am not sure when it would come up in practice.

@oldium
Copy link
Contributor Author

oldium commented Feb 19, 2025

What is an example of this being a problem with yargs completion? (Did you encounter this?)

Yes, with https://github.com/firecow/gitlab-ci-local. When you want yargs to auto-complete the job name, which has a space in the name (which is usual), it simply does not work. It is expected to actually have spaces in the arguments.

Just compare the following. Before patch gitlab-ci-local build-deb<TAB> becomes gitlab-ci-local build-debian: [debian-11] (two separate arguments, the <TAB> needs to be pressed multiple times to get the full name). With the patch it becomes gitlab-ci-local "build-debian: [debian-11]". First one does not work, second one works.

I understand the theoretical problem, but I am not sure when it would come up in practice.

Well, that is not a theoretical problem, that is an actual problem 😉 After all, that is why I investigated it and prepared a fix. 😊

@oldium
Copy link
Contributor Author

oldium commented Feb 19, 2025

This is how the empty-arguments completion looks like with all GitLab jobs enabled:

$ gitlab-ci-local <TAB>
[centos-10]       [debian-11]       [debian-13]       [fedora-40]       [fedora-42]       [ubuntu-2404]     build-debian:     env-vars          generate-patches
[centos-9]        [debian-12]       [fedora-39]       [fedora-41]       [fedora-43]       [ubuntu-2410]     build-fedora:     fetch-source      upload

This is how it looks like with my patch:

$ gitlab-ci-local <TAB>
"build-debian: [debian-11]"    "build-debian: [ubuntu-2404]"  "build-fedora: [centos-9]"     "build-fedora: [fedora-41]"    env-vars                       upload
"build-debian: [debian-12]"    "build-debian: [ubuntu-2410]"  "build-fedora: [fedora-39]"    "build-fedora: [fedora-42]"    fetch-source
"build-debian: [debian-13]"    "build-fedora: [centos-10]"    "build-fedora: [fedora-40]"    "build-fedora: [fedora-43]"    generate-patches

That is completely different result. The first code completions are actually unusable.

@oldium
Copy link
Contributor Author

oldium commented Feb 19, 2025

Funny part is that in both cases the suggestions provided by gitlab-ci-local are exactly the same, so the actual problem is really provisioning the completions to bash.

@bcoe
Copy link
Member

bcoe commented Apr 9, 2025

@oldium I find it slightly alarming how much more complicated this makes the bash logic (since it's hard to QA this throughly). Are we sure awk and mapfile will be broadly available?

What if someone has bash installed in an environment like alpine, that's really bare bones?

@oldium
Copy link
Contributor Author

oldium commented Apr 9, 2025

@oldium I find it slightly alarming how much more complicated this makes the bash logic (since it's hard to QA this throughly). Are we sure awk and mapfile will be broadly available?

What if someone has bash installed in an environment like alpine, that's really bare bones?

mapfile is Bash built-in command, so there should be no issue. I checked bash on latest Alpine Docker image and mapfile is available.

$ mapfile --help
mapfile: mapfile [-d delim] [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
    Read lines from the standard input into an indexed array variable.

    Read lines from the standard input into the indexed array variable ARRAY, or
    from file descriptor FD if the -u option is supplied.  The variable MAPFILE
    is the default ARRAY.
...

awk is a standard tool and Alpine has it as part of busybox tool and supports the used syntax. I made a few tests on Docker Alpine image (after installing apk add --no-cache bash):

$ echo test me | awk '/ / { print "\""$0"\"" } /^[^ ]+$/ { print $0 }'
"test me"
$ echo testme | awk '/ / { print "\""$0"\"" } /^[^ ]+$/ { print $0 }'
testme

The awk tool is defined in POSIX standard IEEE Std 1003.1, so it should be part of any compliant operating system.

Copy link
Member

@bcoe bcoe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks for the contribution.

@bcoe bcoe merged commit 83b7788 into yargs:main Apr 10, 2025
6 checks passed
@bcoe
Copy link
Member

bcoe commented Apr 10, 2025

@oldium give [email protected] a try (it requires newer versions of Node.js).

@oldium
Copy link
Contributor Author

oldium commented Apr 13, 2025

@bcoe Works as expected. I re-compiled gitlab-ci-local from source with updated yargs@next (18.0.0-candidate.3)

$ gitlab-ci-local --completion
###-begin-gitlab-ci-local-completions-###
#
# yargs command completion script
#
# Installation: /home/oldium/bin/gitlab-ci-local completion >> ~/.bashrc
#    or /home/oldium/bin/gitlab-ci-local completion >> ~/.bash_profile on OSX.
#
_gitlab-ci-local_yargs_completions()
{
    local cur_word args type_list

    cur_word="${COMP_WORDS[COMP_CWORD]}"
    args=("${COMP_WORDS[@]}")

    # ask yargs to generate completions.
    # see https://stackoverflow.com/a/40944195/7080036 for the spaces-handling awk
    mapfile -t type_list < <(/home/oldium/bin/gitlab-ci-local --get-yargs-completions "${args[@]}")
    mapfile -t COMPREPLY < <(compgen -W "$( printf '%q ' "${type_list[@]}" )" -- "${cur_word}" |
        awk '/ / { print "\""$0"\"" } /^[^ ]+$/ { print $0 }')

    # if no match was found, fall back to filename completion
    if [ ${#COMPREPLY[@]} -eq 0 ]; then
      COMPREPLY=()
    fi

    return 0
}
complete -o bashdefault -o default -F _gitlab-ci-local_yargs_completions gitlab-ci-local
###-end-gitlab-ci-local-completions-###
$ gitlab-ci-local <TAB>
.git/                                   .gitlab-ci-local-variables.yml
... <redacted>
$ source <(gitlab-ci-local --completion)
$ gitlab-ci-local <TAB>
"build: [debian,debian-11]"    "build: [debian,ubuntu-2410]"  "build: [fedora,fedora-40]"    fetch-source                   upload-debian
"build: [debian,debian-12]"    "build: [fedora,centos-10]"    "build: [fedora,fedora-41]"    generate-patches
"build: [debian,debian-13]"    "build: [fedora,centos-9]"     "build: [fedora,fedora-42]"    prepare
"build: [debian,ubuntu-2404]"  "build: [fedora,fedora-39]"    "build: [fedora,fedora-43]"    upload

renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Jun 1, 2025
| datasource | package | from   | to     |
| ---------- | ------- | ------ | ------ |
| npm        | yargs   | 17.7.2 | 18.0.0 |


## [v18.0.0](https://github.com/yargs/yargs/blob/HEAD/CHANGELOG.md#1800-2025-05-26)

##### ⚠ BREAKING CHANGES

-   command names are not derived from modules passed to `command`.
-   singleton usage of yargs yargs.foo, yargs().argv, has been removed.
-   minimum node.js versions now `^20.19.0 || ^22.12.0 || >=23`.
-   yargs is now ESM first

##### Features

-   commandDir now works with ESM files ([#2461](yargs/yargs#2461)) ([27eec18](yargs/yargs@27eec18))
-   **locale:** adds hebrew translation ([#2357](yargs/yargs#2357)) ([4266485](yargs/yargs@4266485))
-   yargs is now ESM first ([d90af45](yargs/yargs@d90af45))
-   **zsh:** Add default completion as fallback ([#2331](yargs/yargs#2331)) ([e02c91b](yargs/yargs@e02c91b))

##### Bug Fixes

-   addDirectory do not support absolute command dir ([#2465](yargs/yargs#2465)) ([3a40a78](yargs/yargs@3a40a78))
-   allows ESM modules commands to be extensible using visit option ([#2468](yargs/yargs#2468)) ([200e1aa](yargs/yargs@200e1aa))
-   **browser:** fix shims so that yargs continues working in browser context ([#2457](yargs/yargs#2457)) ([4ae5f57](yargs/yargs@4ae5f57))
-   **build:** address problems with typescript compilation ([#2445](yargs/yargs#2445)) ([8d72fb3](yargs/yargs@8d72fb3))
-   coerce should play well with parser configuration ([#2308](yargs/yargs#2308)) ([8343c66](yargs/yargs@8343c66))
-   **deps:** update dependency yargs-parser to v22 ([#2470](yargs/yargs#2470)) ([639130d](yargs/yargs@639130d))
-   exit after async handler done ([#2313](yargs/yargs#2313)) ([e326cde](yargs/yargs@e326cde))
-   handle spaces in bash completion ([#2452](yargs/yargs#2452)) ([83b7788](yargs/yargs@83b7788))
-   parser-configuration should work well with generated completion script ([#2332](yargs/yargs#2332)) ([888db19](yargs/yargs@888db19))
-   propagate Dictionary including undefined in value type ([#2393](yargs/yargs#2393)) ([2b2f7f5](yargs/yargs@2b2f7f5))
-   **zsh:** completion no longer requires double tab when using autoloaded ([0dd8fe4](yargs/yargs@0dd8fe4))

##### Code Refactoring

-   command names are not derived from modules passed to `command`. ([d90af45](yargs/yargs@d90af45))
-   singleton usage of yargs yargs.foo, yargs().argv, has been removed. ([d90af45](yargs/yargs@d90af45))

##### Build System

-   minimum node.js versions now `^20.19.0 || ^22.12.0 || &gt;=23`. ([d90af45](yargs/yargs@d90af45))
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Jun 6, 2025
| datasource | package | from   | to     |
| ---------- | ------- | ------ | ------ |
| npm        | yargs   | 17.7.2 | 18.0.0 |


## [v18.0.0](https://github.com/yargs/yargs/blob/HEAD/CHANGELOG.md#1800-2025-05-26)

##### ⚠ BREAKING CHANGES

-   command names are not derived from modules passed to `command`.
-   singleton usage of yargs yargs.foo, yargs().argv, has been removed.
-   minimum node.js versions now `^20.19.0 || ^22.12.0 || >=23`.
-   yargs is now ESM first

##### Features

-   commandDir now works with ESM files ([#2461](yargs/yargs#2461)) ([27eec18](yargs/yargs@27eec18))
-   **locale:** adds hebrew translation ([#2357](yargs/yargs#2357)) ([4266485](yargs/yargs@4266485))
-   yargs is now ESM first ([d90af45](yargs/yargs@d90af45))
-   **zsh:** Add default completion as fallback ([#2331](yargs/yargs#2331)) ([e02c91b](yargs/yargs@e02c91b))

##### Bug Fixes

-   addDirectory do not support absolute command dir ([#2465](yargs/yargs#2465)) ([3a40a78](yargs/yargs@3a40a78))
-   allows ESM modules commands to be extensible using visit option ([#2468](yargs/yargs#2468)) ([200e1aa](yargs/yargs@200e1aa))
-   **browser:** fix shims so that yargs continues working in browser context ([#2457](yargs/yargs#2457)) ([4ae5f57](yargs/yargs@4ae5f57))
-   **build:** address problems with typescript compilation ([#2445](yargs/yargs#2445)) ([8d72fb3](yargs/yargs@8d72fb3))
-   coerce should play well with parser configuration ([#2308](yargs/yargs#2308)) ([8343c66](yargs/yargs@8343c66))
-   **deps:** update dependency yargs-parser to v22 ([#2470](yargs/yargs#2470)) ([639130d](yargs/yargs@639130d))
-   exit after async handler done ([#2313](yargs/yargs#2313)) ([e326cde](yargs/yargs@e326cde))
-   handle spaces in bash completion ([#2452](yargs/yargs#2452)) ([83b7788](yargs/yargs@83b7788))
-   parser-configuration should work well with generated completion script ([#2332](yargs/yargs#2332)) ([888db19](yargs/yargs@888db19))
-   propagate Dictionary including undefined in value type ([#2393](yargs/yargs#2393)) ([2b2f7f5](yargs/yargs@2b2f7f5))
-   **zsh:** completion no longer requires double tab when using autoloaded ([0dd8fe4](yargs/yargs@0dd8fe4))

##### Code Refactoring

-   command names are not derived from modules passed to `command`. ([d90af45](yargs/yargs@d90af45))
-   singleton usage of yargs yargs.foo, yargs().argv, has been removed. ([d90af45](yargs/yargs@d90af45))

##### Build System

-   minimum node.js versions now `^20.19.0 || ^22.12.0 || &gt;=23`. ([d90af45](yargs/yargs@d90af45))
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Jun 8, 2025
| datasource | package | from   | to     |
| ---------- | ------- | ------ | ------ |
| npm        | yargs   | 17.7.2 | 18.0.0 |


## [v18.0.0](https://github.com/yargs/yargs/blob/HEAD/CHANGELOG.md#1800-2025-05-26)

##### ⚠ BREAKING CHANGES

-   command names are not derived from modules passed to `command`.
-   singleton usage of yargs yargs.foo, yargs().argv, has been removed.
-   minimum node.js versions now `^20.19.0 || ^22.12.0 || >=23`.
-   yargs is now ESM first

##### Features

-   commandDir now works with ESM files ([#2461](yargs/yargs#2461)) ([27eec18](yargs/yargs@27eec18))
-   **locale:** adds hebrew translation ([#2357](yargs/yargs#2357)) ([4266485](yargs/yargs@4266485))
-   yargs is now ESM first ([d90af45](yargs/yargs@d90af45))
-   **zsh:** Add default completion as fallback ([#2331](yargs/yargs#2331)) ([e02c91b](yargs/yargs@e02c91b))

##### Bug Fixes

-   addDirectory do not support absolute command dir ([#2465](yargs/yargs#2465)) ([3a40a78](yargs/yargs@3a40a78))
-   allows ESM modules commands to be extensible using visit option ([#2468](yargs/yargs#2468)) ([200e1aa](yargs/yargs@200e1aa))
-   **browser:** fix shims so that yargs continues working in browser context ([#2457](yargs/yargs#2457)) ([4ae5f57](yargs/yargs@4ae5f57))
-   **build:** address problems with typescript compilation ([#2445](yargs/yargs#2445)) ([8d72fb3](yargs/yargs@8d72fb3))
-   coerce should play well with parser configuration ([#2308](yargs/yargs#2308)) ([8343c66](yargs/yargs@8343c66))
-   **deps:** update dependency yargs-parser to v22 ([#2470](yargs/yargs#2470)) ([639130d](yargs/yargs@639130d))
-   exit after async handler done ([#2313](yargs/yargs#2313)) ([e326cde](yargs/yargs@e326cde))
-   handle spaces in bash completion ([#2452](yargs/yargs#2452)) ([83b7788](yargs/yargs@83b7788))
-   parser-configuration should work well with generated completion script ([#2332](yargs/yargs#2332)) ([888db19](yargs/yargs@888db19))
-   propagate Dictionary including undefined in value type ([#2393](yargs/yargs#2393)) ([2b2f7f5](yargs/yargs@2b2f7f5))
-   **zsh:** completion no longer requires double tab when using autoloaded ([0dd8fe4](yargs/yargs@0dd8fe4))

##### Code Refactoring

-   command names are not derived from modules passed to `command`. ([d90af45](yargs/yargs@d90af45))
-   singleton usage of yargs yargs.foo, yargs().argv, has been removed. ([d90af45](yargs/yargs@d90af45))

##### Build System

-   minimum node.js versions now `^20.19.0 || ^22.12.0 || &gt;=23`. ([d90af45](yargs/yargs@d90af45))
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Jun 14, 2025
| datasource | package | from   | to     |
| ---------- | ------- | ------ | ------ |
| npm        | yargs   | 17.7.2 | 18.0.0 |


## [v18.0.0](https://github.com/yargs/yargs/blob/HEAD/CHANGELOG.md#1800-2025-05-26)

##### ⚠ BREAKING CHANGES

-   command names are not derived from modules passed to `command`.
-   singleton usage of yargs yargs.foo, yargs().argv, has been removed.
-   minimum node.js versions now `^20.19.0 || ^22.12.0 || >=23`.
-   yargs is now ESM first

##### Features

-   commandDir now works with ESM files ([#2461](yargs/yargs#2461)) ([27eec18](yargs/yargs@27eec18))
-   **locale:** adds hebrew translation ([#2357](yargs/yargs#2357)) ([4266485](yargs/yargs@4266485))
-   yargs is now ESM first ([d90af45](yargs/yargs@d90af45))
-   **zsh:** Add default completion as fallback ([#2331](yargs/yargs#2331)) ([e02c91b](yargs/yargs@e02c91b))

##### Bug Fixes

-   addDirectory do not support absolute command dir ([#2465](yargs/yargs#2465)) ([3a40a78](yargs/yargs@3a40a78))
-   allows ESM modules commands to be extensible using visit option ([#2468](yargs/yargs#2468)) ([200e1aa](yargs/yargs@200e1aa))
-   **browser:** fix shims so that yargs continues working in browser context ([#2457](yargs/yargs#2457)) ([4ae5f57](yargs/yargs@4ae5f57))
-   **build:** address problems with typescript compilation ([#2445](yargs/yargs#2445)) ([8d72fb3](yargs/yargs@8d72fb3))
-   coerce should play well with parser configuration ([#2308](yargs/yargs#2308)) ([8343c66](yargs/yargs@8343c66))
-   **deps:** update dependency yargs-parser to v22 ([#2470](yargs/yargs#2470)) ([639130d](yargs/yargs@639130d))
-   exit after async handler done ([#2313](yargs/yargs#2313)) ([e326cde](yargs/yargs@e326cde))
-   handle spaces in bash completion ([#2452](yargs/yargs#2452)) ([83b7788](yargs/yargs@83b7788))
-   parser-configuration should work well with generated completion script ([#2332](yargs/yargs#2332)) ([888db19](yargs/yargs@888db19))
-   propagate Dictionary including undefined in value type ([#2393](yargs/yargs#2393)) ([2b2f7f5](yargs/yargs@2b2f7f5))
-   **zsh:** completion no longer requires double tab when using autoloaded ([0dd8fe4](yargs/yargs@0dd8fe4))

##### Code Refactoring

-   command names are not derived from modules passed to `command`. ([d90af45](yargs/yargs@d90af45))
-   singleton usage of yargs yargs.foo, yargs().argv, has been removed. ([d90af45](yargs/yargs@d90af45))

##### Build System

-   minimum node.js versions now `^20.19.0 || ^22.12.0 || &gt;=23`. ([d90af45](yargs/yargs@d90af45))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants