Start work on completion for ssh kitten

This commit is contained in:
Kovid Goyal 2021-06-25 10:48:58 +05:30
parent bd67899943
commit ec420b8012
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 74 additions and 14 deletions

65
kittens/ssh/completion.py Normal file
View File

@ -0,0 +1,65 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net>
import os
import subprocess
from typing import Dict, Iterator, Tuple
from kitty.types import run_once
def iter_known_hosts() -> Iterator[str]:
try:
f = open(os.path.expanduser('~/.ssh/config'))
except OSError:
pass
else:
for line in f:
parts = line.split()
if parts and parts[0] == 'Host' and len(parts) > 1:
yield parts[1]
try:
f = open(os.path.expanduser('~/.ssh/known_hosts'))
except OSError:
pass
else:
for line in f:
parts = line.split()
if parts:
yield parts[0]
@run_once
def known_hosts() -> Tuple[str, ...]:
return tuple(iter_known_hosts())
@run_once
def ssh_options() -> Dict[str, str]:
stderr = subprocess.Popen(['ssh'], stderr=subprocess.PIPE).stderr
assert stderr is not None
raw = stderr.read().decode('utf-8')
ans: Dict[str, str] = {}
pos = 0
while True:
pos = raw.find('[', pos)
if pos < 0:
break
num = 1
epos = pos
while num > 0:
epos += 1
if raw[epos] not in '[]':
continue
num += 1 if raw[epos] == '[' else -1
q = raw[pos+1:epos]
pos = epos
if len(q) < 2 or q[0] != '-':
continue
if ' ' in q:
opt, desc = q.split(' ', 1)
ans[opt[1:]] = desc
else:
ans.update(dict.fromkeys(q[1:], ''))
return ans

View File

@ -3,12 +3,12 @@
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
import os
import re
import shlex
import subprocess
import sys
from contextlib import suppress
from typing import List, NoReturn, Optional, Set, Tuple
from .completion import ssh_options
from kitty.utils import SSHConnectionData
@ -129,20 +129,15 @@ os.execlp(shell_path, shell_name)
def get_ssh_cli() -> Tuple[Set[str], Set[str]]:
other_ssh_args: List[str] = []
boolean_ssh_args: List[str] = []
stderr = subprocess.Popen(['ssh'], stderr=subprocess.PIPE).stderr
assert stderr is not None
raw = stderr.read().decode('utf-8')
for m in re.finditer(r'\[(.+?)\]', raw):
q = m.group(1)
if len(q) < 2 or q[0] != '-':
continue
if ' ' in q:
other_ssh_args.append(q[1])
other_ssh_args: Set[str] = set()
boolean_ssh_args: Set[str] = set()
for k, v in ssh_options().items():
k = '-' + k
if v:
other_ssh_args.add(k)
else:
boolean_ssh_args.extend(q[1:])
return set('-' + x for x in boolean_ssh_args), set('-' + x for x in other_ssh_args)
boolean_ssh_args.add(k)
return boolean_ssh_args, other_ssh_args
def get_connection_data(args: List[str]) -> Optional[SSHConnectionData]: