Managing trailing characters using zsh autoloaded completion











up vote
2
down vote

favorite












I'm trying to create an autoloaded completion file for zsh. To do so, I've added a _myprog file in a folder that is in my fpath.



This file goes roughly like this:



#compdef myprog
_myprog () {
local cmd
if (( CURRENT > 2)); then
cmd=${words[2]}
curcontext="${curcontext%:*:*}:myprog-$cmd"
(( CURRENT-- ))
shift words
case "${cmd}" in
list|ls)
_arguments : "--limit[Max depth]" "--folders[Print flat list of folders]"
_describe -t commands "myprog list" subcommands
;;
insert)
_arguments : "--force[Overwrite file]" "--append[Append to existing data]"
_describe -t commands "myprog insert" subcommands
_myprog_complete_folders
;;
esac
else
local -a subcommands
subcommands=(
"insert:Insert a new file"
"list:List existing files"
)
_describe -t command 'myprog' subcommands
_arguments : "--yes[Assume yes]"
_myprog_complete_files
fi
}

_myprog_complete_files () {
_values 'files' $(myprog ls)
}

_myprog_complete_folders () {
_values 'folders' $(myprog ls --folders)
}

_myprog


So, my program has two scenarios where I want auto-completion:




  1. When used without subcommand, I'd like to specify a path in a remote location. This is done by the function _myprog_complete_files thanks to the _value function. The file list is provided by running myprog ls, which prints each remote file on a new line.


  2. When inserting a new remote file, I'd like to be able to autocomplete the folders name, which is done in the function _myprog_complete_folders using _value too, but this time the folder list is generated using myprog ls --folder instead, which only prints folders.



So far so good... Excepted that zsh is inserting a space after the folder name when I'm using <tab><tab> to have the value list displayed and I'm trying to type the file name after the folder name.



For example:



$ myprog insert web<tab><tab><tab>
-- folders --
web/ web/foo/ web/bar/


is supposed to select web/foo and it effectively does so and autocomplete to myprog insert web/foo/  but notice the trailing space! So if I'm trying to type directly the name of the file I want to insert once I've selected the folder I wanted using <tab>, say I want to call it baz, I'm ending up with myprog insert web/foo/ baz which is not my goal at all.



I've tried browsing through the zsh doc, without success.
I've for example tried to set zstyle ':completion::complete:myprog-insert:' add-space false to no avail, both in my .zshrc and in my _myprog file. I couldn't even see a difference when having it set or not.



I'm guessing I must be missing something, since it seems to be a desirable feature to be able to type directly after autocompletion in order to specify a parameter or so.










share|improve this question









New contributor




Lery is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
























    up vote
    2
    down vote

    favorite












    I'm trying to create an autoloaded completion file for zsh. To do so, I've added a _myprog file in a folder that is in my fpath.



    This file goes roughly like this:



    #compdef myprog
    _myprog () {
    local cmd
    if (( CURRENT > 2)); then
    cmd=${words[2]}
    curcontext="${curcontext%:*:*}:myprog-$cmd"
    (( CURRENT-- ))
    shift words
    case "${cmd}" in
    list|ls)
    _arguments : "--limit[Max depth]" "--folders[Print flat list of folders]"
    _describe -t commands "myprog list" subcommands
    ;;
    insert)
    _arguments : "--force[Overwrite file]" "--append[Append to existing data]"
    _describe -t commands "myprog insert" subcommands
    _myprog_complete_folders
    ;;
    esac
    else
    local -a subcommands
    subcommands=(
    "insert:Insert a new file"
    "list:List existing files"
    )
    _describe -t command 'myprog' subcommands
    _arguments : "--yes[Assume yes]"
    _myprog_complete_files
    fi
    }

    _myprog_complete_files () {
    _values 'files' $(myprog ls)
    }

    _myprog_complete_folders () {
    _values 'folders' $(myprog ls --folders)
    }

    _myprog


    So, my program has two scenarios where I want auto-completion:




    1. When used without subcommand, I'd like to specify a path in a remote location. This is done by the function _myprog_complete_files thanks to the _value function. The file list is provided by running myprog ls, which prints each remote file on a new line.


    2. When inserting a new remote file, I'd like to be able to autocomplete the folders name, which is done in the function _myprog_complete_folders using _value too, but this time the folder list is generated using myprog ls --folder instead, which only prints folders.



    So far so good... Excepted that zsh is inserting a space after the folder name when I'm using <tab><tab> to have the value list displayed and I'm trying to type the file name after the folder name.



    For example:



    $ myprog insert web<tab><tab><tab>
    -- folders --
    web/ web/foo/ web/bar/


    is supposed to select web/foo and it effectively does so and autocomplete to myprog insert web/foo/  but notice the trailing space! So if I'm trying to type directly the name of the file I want to insert once I've selected the folder I wanted using <tab>, say I want to call it baz, I'm ending up with myprog insert web/foo/ baz which is not my goal at all.



    I've tried browsing through the zsh doc, without success.
    I've for example tried to set zstyle ':completion::complete:myprog-insert:' add-space false to no avail, both in my .zshrc and in my _myprog file. I couldn't even see a difference when having it set or not.



    I'm guessing I must be missing something, since it seems to be a desirable feature to be able to type directly after autocompletion in order to specify a parameter or so.










    share|improve this question









    New contributor




    Lery is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.






















      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      I'm trying to create an autoloaded completion file for zsh. To do so, I've added a _myprog file in a folder that is in my fpath.



      This file goes roughly like this:



      #compdef myprog
      _myprog () {
      local cmd
      if (( CURRENT > 2)); then
      cmd=${words[2]}
      curcontext="${curcontext%:*:*}:myprog-$cmd"
      (( CURRENT-- ))
      shift words
      case "${cmd}" in
      list|ls)
      _arguments : "--limit[Max depth]" "--folders[Print flat list of folders]"
      _describe -t commands "myprog list" subcommands
      ;;
      insert)
      _arguments : "--force[Overwrite file]" "--append[Append to existing data]"
      _describe -t commands "myprog insert" subcommands
      _myprog_complete_folders
      ;;
      esac
      else
      local -a subcommands
      subcommands=(
      "insert:Insert a new file"
      "list:List existing files"
      )
      _describe -t command 'myprog' subcommands
      _arguments : "--yes[Assume yes]"
      _myprog_complete_files
      fi
      }

      _myprog_complete_files () {
      _values 'files' $(myprog ls)
      }

      _myprog_complete_folders () {
      _values 'folders' $(myprog ls --folders)
      }

      _myprog


      So, my program has two scenarios where I want auto-completion:




      1. When used without subcommand, I'd like to specify a path in a remote location. This is done by the function _myprog_complete_files thanks to the _value function. The file list is provided by running myprog ls, which prints each remote file on a new line.


      2. When inserting a new remote file, I'd like to be able to autocomplete the folders name, which is done in the function _myprog_complete_folders using _value too, but this time the folder list is generated using myprog ls --folder instead, which only prints folders.



      So far so good... Excepted that zsh is inserting a space after the folder name when I'm using <tab><tab> to have the value list displayed and I'm trying to type the file name after the folder name.



      For example:



      $ myprog insert web<tab><tab><tab>
      -- folders --
      web/ web/foo/ web/bar/


      is supposed to select web/foo and it effectively does so and autocomplete to myprog insert web/foo/  but notice the trailing space! So if I'm trying to type directly the name of the file I want to insert once I've selected the folder I wanted using <tab>, say I want to call it baz, I'm ending up with myprog insert web/foo/ baz which is not my goal at all.



      I've tried browsing through the zsh doc, without success.
      I've for example tried to set zstyle ':completion::complete:myprog-insert:' add-space false to no avail, both in my .zshrc and in my _myprog file. I couldn't even see a difference when having it set or not.



      I'm guessing I must be missing something, since it seems to be a desirable feature to be able to type directly after autocompletion in order to specify a parameter or so.










      share|improve this question









      New contributor




      Lery is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      I'm trying to create an autoloaded completion file for zsh. To do so, I've added a _myprog file in a folder that is in my fpath.



      This file goes roughly like this:



      #compdef myprog
      _myprog () {
      local cmd
      if (( CURRENT > 2)); then
      cmd=${words[2]}
      curcontext="${curcontext%:*:*}:myprog-$cmd"
      (( CURRENT-- ))
      shift words
      case "${cmd}" in
      list|ls)
      _arguments : "--limit[Max depth]" "--folders[Print flat list of folders]"
      _describe -t commands "myprog list" subcommands
      ;;
      insert)
      _arguments : "--force[Overwrite file]" "--append[Append to existing data]"
      _describe -t commands "myprog insert" subcommands
      _myprog_complete_folders
      ;;
      esac
      else
      local -a subcommands
      subcommands=(
      "insert:Insert a new file"
      "list:List existing files"
      )
      _describe -t command 'myprog' subcommands
      _arguments : "--yes[Assume yes]"
      _myprog_complete_files
      fi
      }

      _myprog_complete_files () {
      _values 'files' $(myprog ls)
      }

      _myprog_complete_folders () {
      _values 'folders' $(myprog ls --folders)
      }

      _myprog


      So, my program has two scenarios where I want auto-completion:




      1. When used without subcommand, I'd like to specify a path in a remote location. This is done by the function _myprog_complete_files thanks to the _value function. The file list is provided by running myprog ls, which prints each remote file on a new line.


      2. When inserting a new remote file, I'd like to be able to autocomplete the folders name, which is done in the function _myprog_complete_folders using _value too, but this time the folder list is generated using myprog ls --folder instead, which only prints folders.



      So far so good... Excepted that zsh is inserting a space after the folder name when I'm using <tab><tab> to have the value list displayed and I'm trying to type the file name after the folder name.



      For example:



      $ myprog insert web<tab><tab><tab>
      -- folders --
      web/ web/foo/ web/bar/


      is supposed to select web/foo and it effectively does so and autocomplete to myprog insert web/foo/  but notice the trailing space! So if I'm trying to type directly the name of the file I want to insert once I've selected the folder I wanted using <tab>, say I want to call it baz, I'm ending up with myprog insert web/foo/ baz which is not my goal at all.



      I've tried browsing through the zsh doc, without success.
      I've for example tried to set zstyle ':completion::complete:myprog-insert:' add-space false to no avail, both in my .zshrc and in my _myprog file. I couldn't even see a difference when having it set or not.



      I'm guessing I must be missing something, since it seems to be a desirable feature to be able to type directly after autocompletion in order to specify a parameter or so.







      zsh autocomplete






      share|improve this question









      New contributor




      Lery is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      Lery is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited Nov 17 at 19:59





















      New contributor




      Lery is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked Nov 16 at 19:55









      Lery

      1134




      1134




      New contributor




      Lery is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Lery is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Lery is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          2
          down vote



          accepted










          The add-space code in $fpath[-1]/_expand does not appear to be involved with your completion via _values; this can be checked by setting add-space to false everywhere, or by calling _complete_debug and seeing what code the completion went through:



          % bindkey -M viins "^t" _complete_debug
          % foo
          Trace output left in /tmp/zsh438foo2 (up-history to view)


          One solution is to use the -s ... feature of _values, which can optionally insert a separator that is normally used to join multiple values, and then to disable that feature if the separator has been used:



          #compdef foo
          local curcontext="$curcontext" state line

          choices=(aaa bbb ccc)

          _arguments '1:dir:->folders' && return 0

          case "$state" in
          folders)
          if ! compset -P '*/'; then
          _values -s / folders $choices
          fi
          ;;
          esac


          Which on a foo atab should append a slash, and then since / now appears the compset test should prevent additional completions.






          share|improve this answer























          • While this is effectively not the ideal way to do it, since it keeps trying to complete after typing stuff, it does effectively solve my problem. I tried using -S (which didn't work) but didn't try using -s, since it refused the empty separator... I should have tried using slashes directly (they were currently in my _values already, so I had to remove the trailing slashes for this method to work.)
            – Lery
            2 days ago






          • 1




            @Lery figured it out, compset can look for the / and based on that disable completion
            – thrig
            2 days ago











          Your Answer








          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "106"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });






          Lery is a new contributor. Be nice, and check out our Code of Conduct.










           

          draft saved


          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f482231%2fmanaging-trailing-characters-using-zsh-autoloaded-completion%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          2
          down vote



          accepted










          The add-space code in $fpath[-1]/_expand does not appear to be involved with your completion via _values; this can be checked by setting add-space to false everywhere, or by calling _complete_debug and seeing what code the completion went through:



          % bindkey -M viins "^t" _complete_debug
          % foo
          Trace output left in /tmp/zsh438foo2 (up-history to view)


          One solution is to use the -s ... feature of _values, which can optionally insert a separator that is normally used to join multiple values, and then to disable that feature if the separator has been used:



          #compdef foo
          local curcontext="$curcontext" state line

          choices=(aaa bbb ccc)

          _arguments '1:dir:->folders' && return 0

          case "$state" in
          folders)
          if ! compset -P '*/'; then
          _values -s / folders $choices
          fi
          ;;
          esac


          Which on a foo atab should append a slash, and then since / now appears the compset test should prevent additional completions.






          share|improve this answer























          • While this is effectively not the ideal way to do it, since it keeps trying to complete after typing stuff, it does effectively solve my problem. I tried using -S (which didn't work) but didn't try using -s, since it refused the empty separator... I should have tried using slashes directly (they were currently in my _values already, so I had to remove the trailing slashes for this method to work.)
            – Lery
            2 days ago






          • 1




            @Lery figured it out, compset can look for the / and based on that disable completion
            – thrig
            2 days ago















          up vote
          2
          down vote



          accepted










          The add-space code in $fpath[-1]/_expand does not appear to be involved with your completion via _values; this can be checked by setting add-space to false everywhere, or by calling _complete_debug and seeing what code the completion went through:



          % bindkey -M viins "^t" _complete_debug
          % foo
          Trace output left in /tmp/zsh438foo2 (up-history to view)


          One solution is to use the -s ... feature of _values, which can optionally insert a separator that is normally used to join multiple values, and then to disable that feature if the separator has been used:



          #compdef foo
          local curcontext="$curcontext" state line

          choices=(aaa bbb ccc)

          _arguments '1:dir:->folders' && return 0

          case "$state" in
          folders)
          if ! compset -P '*/'; then
          _values -s / folders $choices
          fi
          ;;
          esac


          Which on a foo atab should append a slash, and then since / now appears the compset test should prevent additional completions.






          share|improve this answer























          • While this is effectively not the ideal way to do it, since it keeps trying to complete after typing stuff, it does effectively solve my problem. I tried using -S (which didn't work) but didn't try using -s, since it refused the empty separator... I should have tried using slashes directly (they were currently in my _values already, so I had to remove the trailing slashes for this method to work.)
            – Lery
            2 days ago






          • 1




            @Lery figured it out, compset can look for the / and based on that disable completion
            – thrig
            2 days ago













          up vote
          2
          down vote



          accepted







          up vote
          2
          down vote



          accepted






          The add-space code in $fpath[-1]/_expand does not appear to be involved with your completion via _values; this can be checked by setting add-space to false everywhere, or by calling _complete_debug and seeing what code the completion went through:



          % bindkey -M viins "^t" _complete_debug
          % foo
          Trace output left in /tmp/zsh438foo2 (up-history to view)


          One solution is to use the -s ... feature of _values, which can optionally insert a separator that is normally used to join multiple values, and then to disable that feature if the separator has been used:



          #compdef foo
          local curcontext="$curcontext" state line

          choices=(aaa bbb ccc)

          _arguments '1:dir:->folders' && return 0

          case "$state" in
          folders)
          if ! compset -P '*/'; then
          _values -s / folders $choices
          fi
          ;;
          esac


          Which on a foo atab should append a slash, and then since / now appears the compset test should prevent additional completions.






          share|improve this answer














          The add-space code in $fpath[-1]/_expand does not appear to be involved with your completion via _values; this can be checked by setting add-space to false everywhere, or by calling _complete_debug and seeing what code the completion went through:



          % bindkey -M viins "^t" _complete_debug
          % foo
          Trace output left in /tmp/zsh438foo2 (up-history to view)


          One solution is to use the -s ... feature of _values, which can optionally insert a separator that is normally used to join multiple values, and then to disable that feature if the separator has been used:



          #compdef foo
          local curcontext="$curcontext" state line

          choices=(aaa bbb ccc)

          _arguments '1:dir:->folders' && return 0

          case "$state" in
          folders)
          if ! compset -P '*/'; then
          _values -s / folders $choices
          fi
          ;;
          esac


          Which on a foo atab should append a slash, and then since / now appears the compset test should prevent additional completions.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 2 days ago

























          answered Nov 17 at 15:31









          thrig

          23.6k12955




          23.6k12955












          • While this is effectively not the ideal way to do it, since it keeps trying to complete after typing stuff, it does effectively solve my problem. I tried using -S (which didn't work) but didn't try using -s, since it refused the empty separator... I should have tried using slashes directly (they were currently in my _values already, so I had to remove the trailing slashes for this method to work.)
            – Lery
            2 days ago






          • 1




            @Lery figured it out, compset can look for the / and based on that disable completion
            – thrig
            2 days ago


















          • While this is effectively not the ideal way to do it, since it keeps trying to complete after typing stuff, it does effectively solve my problem. I tried using -S (which didn't work) but didn't try using -s, since it refused the empty separator... I should have tried using slashes directly (they were currently in my _values already, so I had to remove the trailing slashes for this method to work.)
            – Lery
            2 days ago






          • 1




            @Lery figured it out, compset can look for the / and based on that disable completion
            – thrig
            2 days ago
















          While this is effectively not the ideal way to do it, since it keeps trying to complete after typing stuff, it does effectively solve my problem. I tried using -S (which didn't work) but didn't try using -s, since it refused the empty separator... I should have tried using slashes directly (they were currently in my _values already, so I had to remove the trailing slashes for this method to work.)
          – Lery
          2 days ago




          While this is effectively not the ideal way to do it, since it keeps trying to complete after typing stuff, it does effectively solve my problem. I tried using -S (which didn't work) but didn't try using -s, since it refused the empty separator... I should have tried using slashes directly (they were currently in my _values already, so I had to remove the trailing slashes for this method to work.)
          – Lery
          2 days ago




          1




          1




          @Lery figured it out, compset can look for the / and based on that disable completion
          – thrig
          2 days ago




          @Lery figured it out, compset can look for the / and based on that disable completion
          – thrig
          2 days ago










          Lery is a new contributor. Be nice, and check out our Code of Conduct.










           

          draft saved


          draft discarded


















          Lery is a new contributor. Be nice, and check out our Code of Conduct.













          Lery is a new contributor. Be nice, and check out our Code of Conduct.












          Lery is a new contributor. Be nice, and check out our Code of Conduct.















           


          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f482231%2fmanaging-trailing-characters-using-zsh-autoloaded-completion%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Morgemoulin

          Scott Moir

          Souastre