diff --git a/kittens/ssh/main.py b/kittens/ssh/main.py index 6e3ecbbe0..cf6b1ca26 100644 --- a/kittens/ssh/main.py +++ b/kittens/ssh/main.py @@ -358,6 +358,15 @@ def get_connection_data(args: List[str], cwd: str = '', extra_args: Tuple[str, . host_name = arg if not host_name: return None + if host_name.startswith('ssh://'): + from urllib.parse import urlparse + purl = urlparse(host_name) + if purl.hostname: + host_name = purl.hostname + if purl.username: + host_name = f'{purl.username}@{host_name}' + if port is None and purl.port: + port = purl.port if identity_file: if not os.path.isabs(identity_file): identity_file = os.path.expanduser(identity_file) @@ -466,7 +475,7 @@ def wrap_bootstrap_script(sh_script: str, interpreter: str) -> List[str]: def get_remote_command( - remote_args: List[str], ssh_opts: SSHOptions, hostname: str = 'localhost', cli_hostname: str = '', cli_uname: str = '', + remote_args: List[str], ssh_opts: SSHOptions, cli_hostname: str = '', cli_uname: str = '', echo_on: bool = True, request_data: bool = False ) -> Tuple[List[str], Dict[str, str], str]: interpreter = ssh_opts.interpreter @@ -579,13 +588,13 @@ def run_ssh(ssh_args: List[str], server_args: List[str], found_extra_args: Tuple if hostname.startswith('ssh://'): from urllib.parse import urlparse purl = urlparse(hostname) - hostname_for_match = purl.hostname or hostname + hostname_for_match = purl.hostname or hostname[6:].split('/', 1)[0] uname = purl.username or uname elif '@' in hostname and hostname[0] != '@': uname, hostname_for_match = hostname.split('@', 1) else: hostname_for_match = hostname - hostname_for_match = hostname.split('@', 1)[-1].split(':', 1)[0] + hostname_for_match = hostname_for_match.split('@', 1)[-1].split(':', 1)[0] overrides = [] pat = re.compile(r'^([a-zA-Z0-9_]+)[ \t]*=') for i, a in enumerate(found_extra_args): @@ -617,7 +626,7 @@ def run_ssh(ssh_args: List[str], server_args: List[str], found_extra_args: Tuple need_to_request_data = False with restore_terminal_state() as echo_on: rcmd, replacements, shm_name = get_remote_command( - remote_args, host_opts, hostname, hostname_for_match, uname, echo_on, request_data=need_to_request_data) + remote_args, host_opts, hostname_for_match, uname, echo_on, request_data=need_to_request_data) cmd += rcmd try: p = subprocess.Popen(cmd) diff --git a/kitty/boss.py b/kitty/boss.py index 6dbb31c4a..60cc54bc6 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -1346,7 +1346,7 @@ class Boss: # the system less before macOS 12.3 barfs up OSC codes, so sanitize them ourselves sentinel = os.path.join(cache_dir(), 'less-is-new-enough') if not os.path.exists(sentinel): - if less_version() >= 581: + if less_version(cmd[0]) >= 581: open(sentinel, 'w').close() else: bdata = re.sub(br'\x1b\].*?\x1b\\', b'', bdata) diff --git a/kitty/rc/scroll_window.py b/kitty/rc/scroll_window.py index dcf63aa72..5f633c932 100644 --- a/kitty/rc/scroll_window.py +++ b/kitty/rc/scroll_window.py @@ -41,7 +41,7 @@ class ScrollWindow(RemoteCommand): pages = 'p' in amt unscroll = 'u' in amt mult = -1 if amt.endswith('-') and not unscroll else 1 - q = int(amt.rstrip('+-pu')) + q = int(amt.rstrip('+-plu')) amount = q * mult, 'p' if pages else ('u' if unscroll else 'l') return {'match': opts.match, 'amount': amount} diff --git a/kitty/utils.py b/kitty/utils.py index e93378e28..15cbcfe44 100644 --- a/kitty/utils.py +++ b/kitty/utils.py @@ -953,7 +953,7 @@ def macos_version() -> Tuple[int, ...]: return tuple(map(int, platform.mac_ver()[0].split('.'))) -@run_once +@lru_cache(maxsize=2) def less_version(less_exe: str = 'less') -> int: import subprocess o = subprocess.check_output([less_exe, '-V'], stderr=subprocess.STDOUT).decode() diff --git a/kitty_tests/ssh.py b/kitty_tests/ssh.py index 426e703c2..919a9d362 100644 --- a/kitty_tests/ssh.py +++ b/kitty_tests/ssh.py @@ -55,6 +55,7 @@ print(' '.join(map(str, buf)))'''), lines=13, cols=77) t('ssh un@ip -i ident -p34', host='un@ip', port=34, identity_file='ident') t('ssh un@ip -iident -p34', host='un@ip', port=34, identity_file='ident') t('ssh -p 33 main', port=33) + t('ssh -p 34 ssh://un@ip:33/', host='un@ip', port=34) t('ssh --kitten=one -p 12 --kitten two -ix main', identity_file='x', port=12, extra_args=(('--kitten', 'one'), ('--kitten', 'two'))) self.assertTrue(runtime_dir()) diff --git a/shell-integration/bash/kitty.bash b/shell-integration/bash/kitty.bash index 9df08f86a..2fa1c0f81 100644 --- a/shell-integration/bash/kitty.bash +++ b/shell-integration/bash/kitty.bash @@ -157,7 +157,7 @@ _ksi_main() { # command like cd /test && cat. PS0 is evaluated before cd is run. if [[ "${_ksi_prompt[last_reported_cwd]}" != "$PWD" ]]; then _ksi_prompt[last_reported_cwd]="$PWD"; - builtin printf "\e]7;kitty-shell-cwd://%s%s\a" "$HOST" "$PWD" + builtin printf "\e]7;kitty-shell-cwd://%s%s\a" "$HOSTNAME" "$PWD" fi fi } diff --git a/shell-integration/ssh/bootstrap-utils.sh b/shell-integration/ssh/bootstrap-utils.sh index 90f1e4412..ad7b91e15 100644 --- a/shell-integration/ssh/bootstrap-utils.sh +++ b/shell-integration/ssh/bootstrap-utils.sh @@ -15,7 +15,6 @@ mv_files_and_dirs() { cd "$cwd" } - compile_terminfo() { tname=".terminfo" # Ensure the 78 dir is present @@ -40,7 +39,6 @@ compile_terminfo() { fi } - parse_passwd_record() { printf "%s" "$(command grep -o '[^:]*$')" } @@ -152,7 +150,7 @@ execute_sh_with_posix_env() { command "$login_shell" -l -c ":" > /dev/null 2> /dev/null && return [ -z "$shell_integration_dir" ] && die "Could not read data over tty ssh kitten cannot function" sh_dir="$shell_integration_dir/sh" - command mkdir -p "$sh_dir" || die "Creating $sh_dir failed" + command mkdir -p "$sh_dir" || die "Creating directory $sh_dir failed" sh_script="$sh_dir/login_shell_env.sh" # Source /etc/profile, ~/.profile, and then check and source ENV printf "%s" '