Custom bash tab completion showing possible completions, but not actually completing input

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
3
down vote

favorite












I have tried very hard to figure this one out before actually posting here, but I can't seem to find any other examples of people solving this particular issue.



I am running Ubuntu 17.10



I have written a custom function to handle tab completion for one of my scripts. The intention is that when I type in the name of my script and hit [TAB] that it list all of the files in /opt/use that end in ".use" (without displaying the ".use" or the leading path). I seem to have made that work so far.



The files in /opt/use are as follows:



blender-2.79.use
chrome.use
clarisse-3.6.use
unity-2017.3.0p2.use


The code for the function and the completion is:



_use () 
files=( `compgen -f -X "!*.use" /opt/use/` )
output=()
for file in "$files[@]"; do
fileBaseName=`basename $file .use`
output+=("$fileBaseName")
done
COMPREPLY=( $output[@] )

complete -F _use use


Please don't judge me too harshly, I'm a graphic artist, not a programmer. :)



Also, my "use" script is actually an alias for the following command:



source /opt/scripts/use.sh


Now when I type:



use[SPACE][TAB][TAB]


I successfully get a list of the files in /opt/use that end in ".use".



So far so good. For example, I type "use[SPACE][TAB][TAB]", this is what it looks like:



bvz@bvz-xps15-linux:~$ use 
blender-2.79 chrome clarisse-3.6 unity-2017.3.0p2


My first question is why I have to hit [TAB] twice? The first time just beeps. The second time it shows me my options. That isn't an issue for me, I just wonder if it is a clue as to my problem, which is this:



If I type enough letters to be completely unique, the tab completion does not actually "complete" the line. It just leaves the entry exactly as I typed it and re-shows me the list of files in /opt/use. So, for example, if I type:



use clar[TAB][TAB]


instead of filling out the line to read:



use clarisse-3.6


which is what I would expect (and what I am after) it leaves the line as:



use clar


and shows me underneath the full list of possible completions. Here is a sample:



bvz@bvz-xps15-linux:~$ use clar[TAB][TAB]
blender-2.79 chrome clarisse-3.6 unity-2017.3.0p2
bvz@bvz-xps15-linux:~$ use clar


Notice how it didn't actually complete the line to read "clarisse-3.6" even though that is the only possible completion.



Can anyone enlighten me as to what I have done wrong? Also, if this is a duplicate I apologize. I have looked around for several days but can't find any examples where someone has even run into this issue, much less solved it.



Thanks







share|improve this question


















  • 1




    Your function is not making any use of the partial word being completed, which should be in $COMP_WORDS[$COMP_CWORD].
    – muru
    Feb 1 at 3:49











  • So, I should filter my results to only show those that match what was typed? I.e. I would use something like: word="$COMP_WORDS[$COMP_CWORD]" and then only add to my output array those elements that start with $word?
    – bvz
    Feb 1 at 4:47











  • That, in fact was what I needed to do! Thanks for your help. If you wan to put your comment in the form of an answer, I will accept that as the solution. Thanks again!
    – bvz
    Feb 1 at 4:53






  • 1




    It would be better if you posted how you fixed the function using that as an answer!
    – muru
    Feb 1 at 5:03










  • I did edit my post above. Should I post it as a separate answer? Thanks again for your help. This had me spinning for a few days!
    – bvz
    Feb 1 at 5:04














up vote
3
down vote

favorite












I have tried very hard to figure this one out before actually posting here, but I can't seem to find any other examples of people solving this particular issue.



I am running Ubuntu 17.10



I have written a custom function to handle tab completion for one of my scripts. The intention is that when I type in the name of my script and hit [TAB] that it list all of the files in /opt/use that end in ".use" (without displaying the ".use" or the leading path). I seem to have made that work so far.



The files in /opt/use are as follows:



blender-2.79.use
chrome.use
clarisse-3.6.use
unity-2017.3.0p2.use


The code for the function and the completion is:



_use () 
files=( `compgen -f -X "!*.use" /opt/use/` )
output=()
for file in "$files[@]"; do
fileBaseName=`basename $file .use`
output+=("$fileBaseName")
done
COMPREPLY=( $output[@] )

complete -F _use use


Please don't judge me too harshly, I'm a graphic artist, not a programmer. :)



Also, my "use" script is actually an alias for the following command:



source /opt/scripts/use.sh


Now when I type:



use[SPACE][TAB][TAB]


I successfully get a list of the files in /opt/use that end in ".use".



So far so good. For example, I type "use[SPACE][TAB][TAB]", this is what it looks like:



bvz@bvz-xps15-linux:~$ use 
blender-2.79 chrome clarisse-3.6 unity-2017.3.0p2


My first question is why I have to hit [TAB] twice? The first time just beeps. The second time it shows me my options. That isn't an issue for me, I just wonder if it is a clue as to my problem, which is this:



If I type enough letters to be completely unique, the tab completion does not actually "complete" the line. It just leaves the entry exactly as I typed it and re-shows me the list of files in /opt/use. So, for example, if I type:



use clar[TAB][TAB]


instead of filling out the line to read:



use clarisse-3.6


which is what I would expect (and what I am after) it leaves the line as:



use clar


and shows me underneath the full list of possible completions. Here is a sample:



bvz@bvz-xps15-linux:~$ use clar[TAB][TAB]
blender-2.79 chrome clarisse-3.6 unity-2017.3.0p2
bvz@bvz-xps15-linux:~$ use clar


Notice how it didn't actually complete the line to read "clarisse-3.6" even though that is the only possible completion.



Can anyone enlighten me as to what I have done wrong? Also, if this is a duplicate I apologize. I have looked around for several days but can't find any examples where someone has even run into this issue, much less solved it.



Thanks







share|improve this question


















  • 1




    Your function is not making any use of the partial word being completed, which should be in $COMP_WORDS[$COMP_CWORD].
    – muru
    Feb 1 at 3:49











  • So, I should filter my results to only show those that match what was typed? I.e. I would use something like: word="$COMP_WORDS[$COMP_CWORD]" and then only add to my output array those elements that start with $word?
    – bvz
    Feb 1 at 4:47











  • That, in fact was what I needed to do! Thanks for your help. If you wan to put your comment in the form of an answer, I will accept that as the solution. Thanks again!
    – bvz
    Feb 1 at 4:53






  • 1




    It would be better if you posted how you fixed the function using that as an answer!
    – muru
    Feb 1 at 5:03










  • I did edit my post above. Should I post it as a separate answer? Thanks again for your help. This had me spinning for a few days!
    – bvz
    Feb 1 at 5:04












up vote
3
down vote

favorite









up vote
3
down vote

favorite











I have tried very hard to figure this one out before actually posting here, but I can't seem to find any other examples of people solving this particular issue.



I am running Ubuntu 17.10



I have written a custom function to handle tab completion for one of my scripts. The intention is that when I type in the name of my script and hit [TAB] that it list all of the files in /opt/use that end in ".use" (without displaying the ".use" or the leading path). I seem to have made that work so far.



The files in /opt/use are as follows:



blender-2.79.use
chrome.use
clarisse-3.6.use
unity-2017.3.0p2.use


The code for the function and the completion is:



_use () 
files=( `compgen -f -X "!*.use" /opt/use/` )
output=()
for file in "$files[@]"; do
fileBaseName=`basename $file .use`
output+=("$fileBaseName")
done
COMPREPLY=( $output[@] )

complete -F _use use


Please don't judge me too harshly, I'm a graphic artist, not a programmer. :)



Also, my "use" script is actually an alias for the following command:



source /opt/scripts/use.sh


Now when I type:



use[SPACE][TAB][TAB]


I successfully get a list of the files in /opt/use that end in ".use".



So far so good. For example, I type "use[SPACE][TAB][TAB]", this is what it looks like:



bvz@bvz-xps15-linux:~$ use 
blender-2.79 chrome clarisse-3.6 unity-2017.3.0p2


My first question is why I have to hit [TAB] twice? The first time just beeps. The second time it shows me my options. That isn't an issue for me, I just wonder if it is a clue as to my problem, which is this:



If I type enough letters to be completely unique, the tab completion does not actually "complete" the line. It just leaves the entry exactly as I typed it and re-shows me the list of files in /opt/use. So, for example, if I type:



use clar[TAB][TAB]


instead of filling out the line to read:



use clarisse-3.6


which is what I would expect (and what I am after) it leaves the line as:



use clar


and shows me underneath the full list of possible completions. Here is a sample:



bvz@bvz-xps15-linux:~$ use clar[TAB][TAB]
blender-2.79 chrome clarisse-3.6 unity-2017.3.0p2
bvz@bvz-xps15-linux:~$ use clar


Notice how it didn't actually complete the line to read "clarisse-3.6" even though that is the only possible completion.



Can anyone enlighten me as to what I have done wrong? Also, if this is a duplicate I apologize. I have looked around for several days but can't find any examples where someone has even run into this issue, much less solved it.



Thanks







share|improve this question














I have tried very hard to figure this one out before actually posting here, but I can't seem to find any other examples of people solving this particular issue.



I am running Ubuntu 17.10



I have written a custom function to handle tab completion for one of my scripts. The intention is that when I type in the name of my script and hit [TAB] that it list all of the files in /opt/use that end in ".use" (without displaying the ".use" or the leading path). I seem to have made that work so far.



The files in /opt/use are as follows:



blender-2.79.use
chrome.use
clarisse-3.6.use
unity-2017.3.0p2.use


The code for the function and the completion is:



_use () 
files=( `compgen -f -X "!*.use" /opt/use/` )
output=()
for file in "$files[@]"; do
fileBaseName=`basename $file .use`
output+=("$fileBaseName")
done
COMPREPLY=( $output[@] )

complete -F _use use


Please don't judge me too harshly, I'm a graphic artist, not a programmer. :)



Also, my "use" script is actually an alias for the following command:



source /opt/scripts/use.sh


Now when I type:



use[SPACE][TAB][TAB]


I successfully get a list of the files in /opt/use that end in ".use".



So far so good. For example, I type "use[SPACE][TAB][TAB]", this is what it looks like:



bvz@bvz-xps15-linux:~$ use 
blender-2.79 chrome clarisse-3.6 unity-2017.3.0p2


My first question is why I have to hit [TAB] twice? The first time just beeps. The second time it shows me my options. That isn't an issue for me, I just wonder if it is a clue as to my problem, which is this:



If I type enough letters to be completely unique, the tab completion does not actually "complete" the line. It just leaves the entry exactly as I typed it and re-shows me the list of files in /opt/use. So, for example, if I type:



use clar[TAB][TAB]


instead of filling out the line to read:



use clarisse-3.6


which is what I would expect (and what I am after) it leaves the line as:



use clar


and shows me underneath the full list of possible completions. Here is a sample:



bvz@bvz-xps15-linux:~$ use clar[TAB][TAB]
blender-2.79 chrome clarisse-3.6 unity-2017.3.0p2
bvz@bvz-xps15-linux:~$ use clar


Notice how it didn't actually complete the line to read "clarisse-3.6" even though that is the only possible completion.



Can anyone enlighten me as to what I have done wrong? Also, if this is a duplicate I apologize. I have looked around for several days but can't find any examples where someone has even run into this issue, much less solved it.



Thanks









share|improve this question













share|improve this question




share|improve this question








edited Feb 12 at 9:20









GAD3R

22.4k154894




22.4k154894










asked Feb 1 at 3:46









bvz

1464




1464







  • 1




    Your function is not making any use of the partial word being completed, which should be in $COMP_WORDS[$COMP_CWORD].
    – muru
    Feb 1 at 3:49











  • So, I should filter my results to only show those that match what was typed? I.e. I would use something like: word="$COMP_WORDS[$COMP_CWORD]" and then only add to my output array those elements that start with $word?
    – bvz
    Feb 1 at 4:47











  • That, in fact was what I needed to do! Thanks for your help. If you wan to put your comment in the form of an answer, I will accept that as the solution. Thanks again!
    – bvz
    Feb 1 at 4:53






  • 1




    It would be better if you posted how you fixed the function using that as an answer!
    – muru
    Feb 1 at 5:03










  • I did edit my post above. Should I post it as a separate answer? Thanks again for your help. This had me spinning for a few days!
    – bvz
    Feb 1 at 5:04












  • 1




    Your function is not making any use of the partial word being completed, which should be in $COMP_WORDS[$COMP_CWORD].
    – muru
    Feb 1 at 3:49











  • So, I should filter my results to only show those that match what was typed? I.e. I would use something like: word="$COMP_WORDS[$COMP_CWORD]" and then only add to my output array those elements that start with $word?
    – bvz
    Feb 1 at 4:47











  • That, in fact was what I needed to do! Thanks for your help. If you wan to put your comment in the form of an answer, I will accept that as the solution. Thanks again!
    – bvz
    Feb 1 at 4:53






  • 1




    It would be better if you posted how you fixed the function using that as an answer!
    – muru
    Feb 1 at 5:03










  • I did edit my post above. Should I post it as a separate answer? Thanks again for your help. This had me spinning for a few days!
    – bvz
    Feb 1 at 5:04







1




1




Your function is not making any use of the partial word being completed, which should be in $COMP_WORDS[$COMP_CWORD].
– muru
Feb 1 at 3:49





Your function is not making any use of the partial word being completed, which should be in $COMP_WORDS[$COMP_CWORD].
– muru
Feb 1 at 3:49













So, I should filter my results to only show those that match what was typed? I.e. I would use something like: word="$COMP_WORDS[$COMP_CWORD]" and then only add to my output array those elements that start with $word?
– bvz
Feb 1 at 4:47





So, I should filter my results to only show those that match what was typed? I.e. I would use something like: word="$COMP_WORDS[$COMP_CWORD]" and then only add to my output array those elements that start with $word?
– bvz
Feb 1 at 4:47













That, in fact was what I needed to do! Thanks for your help. If you wan to put your comment in the form of an answer, I will accept that as the solution. Thanks again!
– bvz
Feb 1 at 4:53




That, in fact was what I needed to do! Thanks for your help. If you wan to put your comment in the form of an answer, I will accept that as the solution. Thanks again!
– bvz
Feb 1 at 4:53




1




1




It would be better if you posted how you fixed the function using that as an answer!
– muru
Feb 1 at 5:03




It would be better if you posted how you fixed the function using that as an answer!
– muru
Feb 1 at 5:03












I did edit my post above. Should I post it as a separate answer? Thanks again for your help. This had me spinning for a few days!
– bvz
Feb 1 at 5:04




I did edit my post above. Should I post it as a separate answer? Thanks again for your help. This had me spinning for a few days!
– bvz
Feb 1 at 5:04










2 Answers
2






active

oldest

votes

















up vote
3
down vote













Thanks to Muru for pointing me to the solution.



Apparently my issue was that every time my function was called it always returned the full list of possible matches. I needed to only return those possible completions that match what the user has typed so far. Once I return only a single item, then bash will auto-complete the rest of the line.



This is the function that works. Before adding each possible completion, I do a quick check to see if the completion starts with the word that was typed originally. I do this using regular expressions. I also had to test to see if they haven't entered anything yet - in which case I always return everything.



I also changed it to make some more variables "local".



_use () 
local word="$COMP_WORDS[$COMP_CWORD]"
local files=( `compgen -f -X "!*.use" /opt/use/` )
local output=()
for file in "$files[@]"; do
fileBaseName=`basename $file .use`
if [[ $fileBaseName =~ ^$word.* ]]





share|improve this answer



























    up vote
    1
    down vote













    Now that I have had some time to consider this, I think the completion function can be simplified to:



    _use () 
    local word="$COMP_WORDS[$COMP_CWORD]"
    local IFS=$'n'
    COMPREPLY=( $(find /opt/use/ -type f -name "$word*.use" -exec basename -as .use +) )



    Assuming your basename is new enough to support -a, otherwise do -exec basename .use ; instead.






    share|improve this answer




















      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: false,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );








       

      draft saved


      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f421132%2fcustom-bash-tab-completion-showing-possible-completions-but-not-actually-comple%23new-answer', 'question_page');

      );

      Post as a guest






























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      3
      down vote













      Thanks to Muru for pointing me to the solution.



      Apparently my issue was that every time my function was called it always returned the full list of possible matches. I needed to only return those possible completions that match what the user has typed so far. Once I return only a single item, then bash will auto-complete the rest of the line.



      This is the function that works. Before adding each possible completion, I do a quick check to see if the completion starts with the word that was typed originally. I do this using regular expressions. I also had to test to see if they haven't entered anything yet - in which case I always return everything.



      I also changed it to make some more variables "local".



      _use () 
      local word="$COMP_WORDS[$COMP_CWORD]"
      local files=( `compgen -f -X "!*.use" /opt/use/` )
      local output=()
      for file in "$files[@]"; do
      fileBaseName=`basename $file .use`
      if [[ $fileBaseName =~ ^$word.* ]]





      share|improve this answer
























        up vote
        3
        down vote













        Thanks to Muru for pointing me to the solution.



        Apparently my issue was that every time my function was called it always returned the full list of possible matches. I needed to only return those possible completions that match what the user has typed so far. Once I return only a single item, then bash will auto-complete the rest of the line.



        This is the function that works. Before adding each possible completion, I do a quick check to see if the completion starts with the word that was typed originally. I do this using regular expressions. I also had to test to see if they haven't entered anything yet - in which case I always return everything.



        I also changed it to make some more variables "local".



        _use () 
        local word="$COMP_WORDS[$COMP_CWORD]"
        local files=( `compgen -f -X "!*.use" /opt/use/` )
        local output=()
        for file in "$files[@]"; do
        fileBaseName=`basename $file .use`
        if [[ $fileBaseName =~ ^$word.* ]]





        share|improve this answer






















          up vote
          3
          down vote










          up vote
          3
          down vote









          Thanks to Muru for pointing me to the solution.



          Apparently my issue was that every time my function was called it always returned the full list of possible matches. I needed to only return those possible completions that match what the user has typed so far. Once I return only a single item, then bash will auto-complete the rest of the line.



          This is the function that works. Before adding each possible completion, I do a quick check to see if the completion starts with the word that was typed originally. I do this using regular expressions. I also had to test to see if they haven't entered anything yet - in which case I always return everything.



          I also changed it to make some more variables "local".



          _use () 
          local word="$COMP_WORDS[$COMP_CWORD]"
          local files=( `compgen -f -X "!*.use" /opt/use/` )
          local output=()
          for file in "$files[@]"; do
          fileBaseName=`basename $file .use`
          if [[ $fileBaseName =~ ^$word.* ]]





          share|improve this answer












          Thanks to Muru for pointing me to the solution.



          Apparently my issue was that every time my function was called it always returned the full list of possible matches. I needed to only return those possible completions that match what the user has typed so far. Once I return only a single item, then bash will auto-complete the rest of the line.



          This is the function that works. Before adding each possible completion, I do a quick check to see if the completion starts with the word that was typed originally. I do this using regular expressions. I also had to test to see if they haven't entered anything yet - in which case I always return everything.



          I also changed it to make some more variables "local".



          _use () 
          local word="$COMP_WORDS[$COMP_CWORD]"
          local files=( `compgen -f -X "!*.use" /opt/use/` )
          local output=()
          for file in "$files[@]"; do
          fileBaseName=`basename $file .use`
          if [[ $fileBaseName =~ ^$word.* ]]






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Feb 1 at 5:17









          bvz

          1464




          1464






















              up vote
              1
              down vote













              Now that I have had some time to consider this, I think the completion function can be simplified to:



              _use () 
              local word="$COMP_WORDS[$COMP_CWORD]"
              local IFS=$'n'
              COMPREPLY=( $(find /opt/use/ -type f -name "$word*.use" -exec basename -as .use +) )



              Assuming your basename is new enough to support -a, otherwise do -exec basename .use ; instead.






              share|improve this answer
























                up vote
                1
                down vote













                Now that I have had some time to consider this, I think the completion function can be simplified to:



                _use () 
                local word="$COMP_WORDS[$COMP_CWORD]"
                local IFS=$'n'
                COMPREPLY=( $(find /opt/use/ -type f -name "$word*.use" -exec basename -as .use +) )



                Assuming your basename is new enough to support -a, otherwise do -exec basename .use ; instead.






                share|improve this answer






















                  up vote
                  1
                  down vote










                  up vote
                  1
                  down vote









                  Now that I have had some time to consider this, I think the completion function can be simplified to:



                  _use () 
                  local word="$COMP_WORDS[$COMP_CWORD]"
                  local IFS=$'n'
                  COMPREPLY=( $(find /opt/use/ -type f -name "$word*.use" -exec basename -as .use +) )



                  Assuming your basename is new enough to support -a, otherwise do -exec basename .use ; instead.






                  share|improve this answer












                  Now that I have had some time to consider this, I think the completion function can be simplified to:



                  _use () 
                  local word="$COMP_WORDS[$COMP_CWORD]"
                  local IFS=$'n'
                  COMPREPLY=( $(find /opt/use/ -type f -name "$word*.use" -exec basename -as .use +) )



                  Assuming your basename is new enough to support -a, otherwise do -exec basename .use ; instead.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Feb 2 at 8:25









                  muru

                  33.5k577143




                  33.5k577143






















                       

                      draft saved


                      draft discarded


























                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f421132%2fcustom-bash-tab-completion-showing-possible-completions-but-not-actually-comple%23new-answer', 'question_page');

                      );

                      Post as a guest













































































                      Popular posts from this blog

                      How to check contact read email or not when send email to Individual?

                      Bahrain

                      Postfix configuration issue with fips on centos 7; mailgun relay