rishi kant
rishi kant

Reputation: 1255

How to extend bash completion in other directory?

I'm learning about bash completion. I'm able to list the content of only current directory. Here is my code:

   _foo()
   {
       local cur prev opts
       COMPREPLY=()
       cur="${COMP_WORDS[COMP_CWORD]}"
       prev="${COMP_WORDS[COMP_CWORD-1]}"

       opts="push pull"
       OUTPUT=" $(ls) "

      case "${prev}" in
          push)
              COMPREPLY=( $(compgen -W "--in --out" -- ${cur}) )
              return 0
              ;;
          --in)
              COMPREPLY=( $(compgen -W "$OUTPUT" -- ${cur}) )
              return 0
              ;;
      esac

        COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
        return 0
  }
  complete -F _foo foo

It's output is:

$ foo push --in[TAB]
file1.txt file2.txt foo  ;; content of pwd

But when I do this:

$ foo push --in ~[TAB]

It's not working. So I want to know how to do bash completion in different directory (not only in pwd)? Thanks.

Upvotes: 2

Views: 559

Answers (1)

Bertrand Martel
Bertrand Martel

Reputation: 45513

You can use -f to match filenames :

#!/bin/bash
_foo()    {
       local cur prev opts
       COMPREPLY=()
       cur="${COMP_WORDS[COMP_CWORD]}"
       prev="${COMP_WORDS[COMP_CWORD-1]}"
       opts="push pull"

       case "${prev}" in
          push)
              COMPREPLY=( $(compgen -W "--in --out" -- ${cur}) )
              return 0
              ;;
          --in)
              COMPREPLY=( $(compgen -f ${cur}) )
              return 0
              ;;
      esac

      COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
      return 0   
}

complete -F _foo foo

However it seems that it doesn't work for ~ alone but $ foo push --in ~/[TAB] works and all other directories This solution wont include slash to look for file in directory : $ foo push --in /etc[TAB] will give foo push --in /etc and not foo push --in /etc/

The following post solves that problem using default mode :
Getting compgen to include slashes on directories when looking for files

default

Use Readline’s default filename completion if the compspec generates no matches.

So you can use :

#!/bin/bash
_foo()
   {
       local cur prev opts
       COMPREPLY=()
       cur="${COMP_WORDS[COMP_CWORD]}"
       prev="${COMP_WORDS[COMP_CWORD-1]}"

       opts="push pull"
       OUTPUT=" $(ls) "

      case "${prev}" in
          push)
              COMPREPLY=( $(compgen -W "--in --out" -- ${cur}) )
              return 0
              ;;
          --in)
              COMPREPLY=()
              return 0
              ;;
          --port)
              COMPREPLY=("")
              return 0
              ;;
      esac

        COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
        return 0
  }
  complete -o default -F _foo foo

Or setting to default mode when you need to like this post : https://unix.stackexchange.com/a/149398/146783

Upvotes: 2

Related Questions