Have *_with_cwd work with the ssh kitten to open new windows auto-logged into the remote server at the current remote working directory

This commit is contained in:
Kovid Goyal 2022-03-15 19:59:16 +05:30
parent a216f6bd46
commit ce1e22ac95
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 63 additions and 5 deletions

View File

@ -27,6 +27,13 @@ rc files:
So you can now type just ``s hostname`` to connect.
If you define a mapping in :file:`kitty.conf` such as::
map f1 new_window_with_cwd
Then, pressing :kbd:`F1` will open a new window automatically logged
into the same server using the ssh kitten, at the same directory.
The ssh kitten can be configured using the :file:`~/.config/kitty/ssh.conf`
file where you can specify environment variables to set on the remote server
and files to copy from your local machine to the remote server. Let's see a

View File

@ -68,7 +68,10 @@ no-title
setting functionality instead.
no-cwd
Turn off reporting
Turn off reporting the current working directory. This is used to allow
:ref:`action-new_window_with_cwd` and similar to open windows logged
into remote machines using the :doc:`ssh kitten <kitten/ssh>`
automatically with the same working directory as the current window.
no-prompt-mark
Turn off marking of prompts. This disables jumping to prompt, browsing

View File

@ -42,6 +42,27 @@ from .copy import CopyInstruction
from .options.types import Options as SSHOptions
from .options.utils import DELETE_ENV_VAR
def is_kitten_cmdline(q: List[str]) -> bool:
if len(q) < 4:
return False
if os.path.basename(q[0]).lower() != 'kitty':
return False
return q[1:3] == ['+kitten', 'ssh'] or q[1:4] == ['+', 'kitten', 'ssh']
def set_cwd_in_cmdline(cwd: str, argv: List[str]) -> None:
for i, arg in enumerate(tuple(argv)):
if arg.startswith('--kitten=cwd'):
argv[i] = f'--kitten=cwd={cwd}'
return
elif i > 0 and argv[i-1] == '--kitten' and (arg.startswith('cwd=') or arg.startswith('cwd ')):
argv[i] = cwd
return
idx = argv.index('ssh')
argv.insert(idx + 1, f'--kitten=cwd={cwd}')
# See https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html
quote_pat = re.compile('([\\`"\n])')

View File

@ -201,7 +201,7 @@ class Child:
self.argv = list(argv)
if cwd_from is not None:
try:
cwd = cwd_from.cwd_of_child or cwd
cwd = cwd_from.modify_argv_for_launch_with_cwd(self.argv) or cwd
except Exception as err:
log_error(f'Failed to read cwd of {cwd_from} with error: {err}')
else:

View File

@ -936,3 +936,12 @@ def cleanup_ssh_control_masters() -> None:
for x in files:
with suppress(OSError):
os.remove(x)
def path_from_osc7_url(url: str) -> str:
if url.startswith('kitty-shell-cwd://'):
return '/' + url.split('/', 3)[-1]
if url.startswith('file://'):
from urllib.parse import urlparse
return urlparse(url).path
return ''

View File

@ -20,7 +20,7 @@ from typing import (
from .child import ProcessDesc
from .cli_stub import CLIOptions
from .config import build_ansi_color_table
from .constants import appname, is_macos, wakeup
from .constants import appname, is_macos, shell_path, wakeup
from .fast_data_types import (
BGIMAGE_PROGRAM, BLIT_PROGRAM, CELL_BG_PROGRAM, CELL_FG_PROGRAM,
CELL_PROGRAM, CELL_SPECIAL_PROGRAM, CURSOR_BEAM, CURSOR_BLOCK,
@ -46,8 +46,8 @@ from .types import MouseEvent, WindowGeometry, ac
from .typing import BossType, ChildType, EdgeLiteral, TabType, TypedDict
from .utils import (
get_primary_selection, kitty_ansi_sanitizer_pat, load_shaders, log_error,
open_cmd, open_url, parse_color_set, resolve_custom_file, sanitize_title,
set_primary_selection
open_cmd, open_url, parse_color_set, path_from_osc7_url,
resolve_custom_file, sanitize_title, set_primary_selection
)
MatchPatternType = Union[Pattern[str], Tuple[Pattern[str], Optional[Pattern[str]]]]
@ -323,6 +323,7 @@ def cmd_output(screen: Screen, which: CommandOutput = CommandOutput.last_run, as
def process_remote_print(msg: str) -> str:
from base64 import standard_b64decode
from .cli import green
text = standard_b64decode(msg).decode('utf-8', 'replace')
return text.replace('\x1b', green(r'\e')).replace('\a', green(r'\a')).replace('\0', green(r'\0'))
@ -1138,6 +1139,23 @@ class Window:
def cwd_of_child(self) -> Optional[str]:
return self.child.foreground_cwd or self.child.current_cwd
def modify_argv_for_launch_with_cwd(self, argv: List[str]) -> str:
if argv[0] != shell_path or not self.screen.last_reported_cwd:
return self.cwd_of_child or ''
from kittens.ssh.main import is_kitten_cmdline, set_cwd_in_cmdline
ssh_kitten_cmdline: List[str] = []
for p in self.child.foreground_processes:
q = list(p['cmdline'] or ())
if is_kitten_cmdline(q):
ssh_kitten_cmdline = q
break
if ssh_kitten_cmdline:
cwd = path_from_osc7_url(self.screen.last_reported_cwd)
if cwd:
set_cwd_in_cmdline(path_from_osc7_url(self.screen.last_reported_cwd), ssh_kitten_cmdline)
argv[:] = ssh_kitten_cmdline
return self.cwd_of_child or ''
def pipe_data(self, text: str, has_wrap_markers: bool = False) -> PipeData:
text = text or ''
if has_wrap_markers: