11

Not a duplicate:
I'm not looking for a way to complete directory names or execute scripts from a fixed directory. The issue I'm trying to solve is to get completion for the current directory without pressing /


I want zsh to tab-complete . to ./ like bash.

With bash I'm used to press .TABTAB to see all files in the current working directory since it first completes to ./ and then shows all content in that directory. Reason for my desire to avoid / at all cost is that / is way harder on my german keyboard than TAB since it's either with 2 fingers with shift or far away on numpad and I'd rather switch back to bash than type a /. What I'd like to achieve, in other words what bash does:

$ .               <TAB>
$ ./              <TAB>
foo.sh   somedir/
$ ./              <F><TAB>
$ ./foo.sh        <ENTER>

Using zsh / oh-my-zsh when I hit .TAB I get . (dot space) which is not useful at all for me.

  • Using zstyle ':completion:*' special-dirs true with setopt auto_cd (which is oh-my-zsh default) gives me the even less useful option for ../ on top, so I turned that off already. I'm happy with completion of cd.
  • There is no . on $PATH and it should stay that way. Though I wouldn't mind completion of e.g. f<TAB> to ./foo.sh for example.

How can I teach zsh to complete . to ./ or even better to local directory content right away? Or is there another way to work with local script files in an efficient way that does not involve /?

4
  • 1
    Possible duplicate of zsh autocomplete directory
    – Sparhawk
    Commented Jul 15, 2019 at 10:40
  • 2
    @Sparhawk No, not really my issue or a solution to it.
    – zapl
    Commented Jul 15, 2019 at 10:45
  • in bash you are getting foo.sh as one if suggestion is because that's executable otherwise that is out. you can check the code of bash-completion to see what is does and maybe you can simulate the same in zsh Commented Feb 6, 2020 at 15:43
  • @αғsнιη the issue is not that zsh won't complete executables once you're at ./, it's that it doesn't get there from . - There's surely a simple regex rules one can put somewhere that triggers for exactly the string .?
    – zapl
    Commented Feb 6, 2020 at 19:05

2 Answers 2

3
+50

Great challenge! Try this on the commandline, if it works add it to ~/.zshrc

bindkey '^I' dotcomplete
zle -N dotcomplete
function dotcomplete() {                                        
  if [[ $BUFFER =~ ^'\.'$ ]]; then
    BUFFER='./'
    CURSOR=2
    zle list-choices
  else
    zle expand-or-complete
  fi
}                    

It adds a function which runs every time you press TAB (^I). If the the line you've currently typed only contains a dot (^=beginning of line, '\.' =super-escape the dot, $=end of line), then replace that dot with a ./ then continue with the normal completion.

It doesn't exactly do what you ask, which is to treat the dot as the current directory. But it will save you they keystrokes you want to save.

1
  • 1
    This works great! Changed regex to if [[ $BUFFER =~ ^'\.'$ ]]; then ($ at the end) so it doesn't act on ./foo<TAB>. Also had to add the line zle -N dotcomplete to my .zshrc.
    – zapl
    Commented Feb 12, 2020 at 14:33
1

given your f<TAB> option/workaround, I present:

$ function f(){ local x=$1; shift; ./"$x" "$@"; }
$ f foo<TAB>

notice the space after f in that last line

2
  • Nice. While I don't have that f<TAB> workaround, this still works because f<SPACE><TAB> suggests local directory files and selecting one will correctly execute it. A little odd to remember f (or whatever name that function gets) though.
    – zapl
    Commented Feb 12, 2020 at 14:18
  • yes, I only used 'f' because you had it, but perhaps 'x' ("execute") would be better
    – Gedge
    Commented Feb 13, 2020 at 11:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .