romkatv / zsh4humans

A turnkey configuration for Zsh
MIT License
1.81k stars 116 forks source link

SSH completion from SSH config files partially working #285

Closed arrrgi closed 11 months ago

arrrgi commented 11 months ago

Hey @romkatv

It's been a hot minute since I raised my last issue about sourcing GRC correctly. Thanks for your help on that one.

I'm unsure if this is a bug or intended behaviour but I noticed that when I attempt to tab out a completion after type 'ssh ' I don't see any of the hosts in my SSH config files, instead, fzf is giving me a list of users and a few host names from .ssh/known_hosts.

My assumption is that the completion is expecting SSH targets to be specified in the form user@hostname or user@ip address

FWIW, here is an example of a typical SSH config I use.

$cat ~/.ssh/config

Include config.d/personal.conf

Host *
  ConnectTimeout 10
  ControlMaster auto
  ControlPath ~/.ssh/%r@%h:%p
  ControlPersist 720
  EscapeChar `
  HashKnownHosts no
  IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"
  PreferredAuthentications publickey
  SendEnv LANG LC_*
$cat ~/.ssh/config.d/personal.conf

Host server
  HostName 10.0.0.2
  User admin
  ForwardAgent yes

Is this the expected behaviour?

Is there any options or a particular zstyle completion override I can use?

~I noticed that with zsh4humans that *ssh is aliased to z4h ssh "$@" which leads me to believe that zsh4humans is responsible for the completions, rather than any provided my OS (Darwin)~

arrrgi commented 11 months ago

Adding to this. I have tried to get this working as an approximation this with:

# Partially complete solution for SSH config host completions
zstyle -e ':completion:*:ssh:*' hosts "${(f)$(awk "/^Host / {print \$2}" ~/.ssh/config.d/personal.conf 2>/dev/null)}"
zstyle -e ':completion:*:ssh:*' users "${(f)$(awk -F: '$3 >= 1000 && $3 < 65534 {print $1}' /etc/passwd 2>/dev/null)}"

This is less than ideal though as it now returns only the hosts from my SSH config files

I've seen a couple of other solutions like this:

zstyle -e ':completion:*:hosts' hosts 'reply=(
  ${=${${(f)"$(cat {/etc/ssh_,~/.ssh/known_}hosts(|2)(N) 2>/dev/null)"}%%[#| ]*}//,/ }
  ${=${(f)"$(cat /etc/hosts(|)(N) <<(ypcat hosts 2>/dev/null))"}%%\#*}
  ${=${${${${(@M)${(f)"$(cat ~/.ssh/config 2>/dev/null)"}:#Host *}#Host }:#*\**}:#*\?*}}
)'
zstyle ':completion:*:(scp|rsync):*' tag-order 'hosts:-host hosts:-domain:domain hosts:-ipaddr:ip\ address *'
zstyle ':completion:*:(scp|rsync):*' group-order users files all-files hosts-domain hosts-host hosts-ipaddr
zstyle ':completion:*:ssh:*' tag-order users 'hosts:-host hosts:-domain:domain hosts:-ipaddr:ip\ address *'
zstyle ':completion:*:ssh:*' group-order hosts-domain hosts-host users hosts-ipaddr
zstyle ':completion:*:(ssh|scp|rsync):*:hosts-host' ignored-patterns '*.*' loopback localhost
zstyle ':completion:*:(ssh|scp|rsync):*:hosts-domain' ignored-patterns '<->.<->.<->.<->' '^*.*' '*@*'
zstyle ':completion:*:(ssh|scp|rsync):*:hosts-ipaddr' ignored-patterns '^<->.<->.<->.<->' '127.0.0.<->'

Though I do not properly comprehend what this achieves and I'm reluctant to just copy/paste from other people's dotfiles without understanding the effects/impact.

Ideally, the working solution would:

  1. First return a list of hosts from any SSH config files in ~/.ssh/config and ~/.ssh/config.d/*
  2. Concatenate the hosts found in ~/.ssh/known_hosts file
  3. Concatenate the hosts found in /etc/hosts
  4. Support the alternate form of user@host as the last preference or where the Host entry in the SSH config doesn't specify a username

Thoughts?

romkatv commented 11 months ago

Have you seen this? That's all I have for ssh completion.

arrrgi commented 11 months ago

Thanks. I can't believe I missed that. I think that is sufficient enough for the convenience factor it provides. Will that include Hosts from included config files from the parent config?

arrrgi commented 11 months ago

Thanks. I can't believe I missed that. I think that is sufficient enough for the convenience factor it provides. Will that include Hosts from included config files from the parent config?

Tested. Yes it does. Closing and thanks!!