title: How to autocomplete a bash commandline with file paths?
body: <h1>Context</h1>
  
  <p>I am creating a shell program which is a command line tool. I want to create my own auto-completion for this tool.</p>
  
  <p>I want to do two different things (maybe should I post two questions):</p>
  
  <ul>
  <li>for the options <code>--install</code> and <code>-i</code>, I want to auto-complete on file paths, like the <code>ls</code> command do.</li>
  <li>for the options <code>--unit-test</code> and <code>-t</code>, I want to auto-complete on file paths from a particular directory which I can get running <code>my_app --directory</code>.</li>
  </ul>
  
  <p><strong><code>my_app_autocomplete</code> file</strong></p>
  
  <pre><code>__my_app_autocomplete()
  {
      local cur prev opts
      COMPREPLY=()
      cur="${COMP_WORDS[COMP_CWORD]}"
      prev="${COMP_WORDS[COMP_CWORD-1]}"
      opts="--help -h --install -i --run -r --rebuild -rb --show-running-containers -ps --stop -s --remove -rm --logs -l --bash -b --sass -css --unit-tests -t"
      containers="nginx php mysql mongo node"
      sass="watch"
  
      # By default, autocomplete with options
      if [[ ${prev} == my_app ]] ; then
          COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
          return 0
      fi
      # By default, autocomplete with options
      if [[ ${cur} == -* ]] ; then
          COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
          return 0
      fi
      # For --install and -i options, autocomplete with folder
      if [ ${prev} == --install ] || [ ${prev} == -i ] ; then
          COMPREPLY=( $(compgen -d -- ${cur}) )
          return 0
      fi
      # For --stop --remove --logs and --bash, autocomplete with containers
      if [ ${prev} == --stop ] || [ ${prev} == -s ] || [ ${prev} == --remove ] || [ ${prev} == -rm ] || [ ${prev} == --logs ] || [ ${prev} == -l ] || [ ${prev} == --bash ] || [ ${prev} == -b ] ; then
          COMPREPLY=( $(compgen -W "${containers}" -- ${cur}) )
          return 0
      fi
      # For --sass and -css, complete with sass options
      if [ ${prev} == --sass ] || [ ${prev} == -css ] ; then
          COMPREPLY=( $(compgen -W "${sass}" -- ${cur}) )
          return 0
      fi
      # For --unit-tests and -t, complete with relative to my_app folder paths
      if [ ${prev} == --unit-tests ] || [ ${prev} == -t ] ; then
          COMPREPLY=( $(compgen -d -- ${cur}) )
          return 0
      fi
  }
  complete -F __my_app_autocomplete my_app
  </code></pre>
  
  <h1>Problem</h1>
  
  <p>I struggle on a particular point: auto-complete file paths.</p>
  
  <p>I don't understand <code>compgen</code> options and how to do things with it. Maybe I could try to run a subcommand but I don't know the syntax and I can't find any useful information except <a href="http://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html" rel="nofollow noreferrer">man of bash - Programmable completion builtins</a> which does not give much information about <code>compgen</code>.</p>
  
  <p>In this case, when I do:</p>
  
  <pre><code>user@computer:~$ my_app --install D[TAB][TAB]
  </code></pre>
  
  <p>I would like:</p>
  
  <pre><code>user@computer:~$ my_app --install Documents/
  </code></pre>
  
  <p>I obtain:</p>
  
  <pre><code>user@computer:~$ myapp --install Documents 
  </code></pre>
  
  <p>with a blank space at the end of the line, which is a problem because I have to erase it and add a <code>/</code> to be able to redo <code>[TAB][TAB]</code> to auto-complete for sub-directories.</p>
  
  <h1>Investigations</h1>
  
  <h2>-o nospace</h2>
  
  <p>With the option <code>-o nospace</code> applied on <code>complete</code> as:</p>
  
  <pre><code>complete -o nospace -F __my_app_autocomplete my_app
  </code></pre>
  
  <p>the behavior is:</p>
  
  <pre><code>user@computer:~$ myapp --i[TAB][TAB]
  user@computer:~$ myapp --install
  </code></pre>
  
  <p>without space.</p>
  
  <pre><code>user@computer:~$ myapp --install D[TAB][TAB]
  user@computer:~$ myapp --install Documents
  </code></pre>
  
  <p>without space.</p>
  
  <p><strong>Problems:</strong></p>
  
  <ul>
  <li>It removes spaces for all options, forcing me to manually add a space after those that aren't file paths (like <code>--install</code>)</li>
  <li>I have to add <code>/</code> to navigate into sub directories</li>
  </ul>
  
  <h2>-o filenames</h2>
  
  <p>With the option <code>-o filenames</code> applied on <code>complete</code> as:</p>
  
  <pre><code>complete -o filenames -F __my_app_autocomplete my_app
  </code></pre>
  
  <p>the behavior is:</p>
  
  <pre><code>user@computer:~$ myapp --i[TAB][TAB]
  user@computer:~$ myapp --install
  </code></pre>
  
  <p>with a space</p>
  
  <pre><code>user@computer:~$ myapp --install D[TAB][TAB]
  user@computer:~$ myapp --install Documents/
  </code></pre>
  
  <p>with a <code>/</code> and without space if it's a directory</p>
  
  <pre><code>user@computer:~$ myapp --install f[TAB][TAB]
  user@computer:~$ myapp --install file 
  </code></pre>
  
  <p>with a space if it's a file</p>
  
  <p>It seems to set paths only for completion not defined in an list of words, so it does not affect other completions, I think it's the first part of what I need.</p>
  
  <h2>From a particular directory</h2>
  
  <p>I will open another question to avoid mixing things: <a href="https://stackoverflow.com/questions/44453510/how-to-autocomplete-a-bash-commandline-with-file-paths-from-a-specific-directory">How to autocomplete a bash commandline with file paths from a specific directory without displaying this directory?</a></p>