Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Shell integration #3948

Closed
kovidgoyal opened this issue Aug 18, 2021 · 151 comments
Closed

[RFC] Shell integration #3948

kovidgoyal opened this issue Aug 18, 2021 · 151 comments

Comments

@kovidgoyal
Copy link
Owner

kovidgoyal commented Aug 18, 2021

I just finished working on shell integration for kitty. Before releasing, I'd like some testing/feedback from the community.

In brief, shell integration enables features such as:

  • Open the output of the last command in a pager such as less
    (ctrl+shift+g)

  • Jump to the previous/next prompt in the scrollback
    (ctrl+shit+z/ctrl+shift+x)

  • Click with the mouse anywhere in the current command to move the cursor there

  • The current working directory or the command being executed are automatically
    displayed in the kitty window titlebar/tab title.

  • The text cursor is changed to a bar when editing commands at the shell prompt

  • Glitch free window resizing even with complex prompts. Achieved by erasing
    the prompt on resize and allowing the shell to redraw it cleanly.

  • Sophisticated completion for the kitty command in the shell

  • When using confirm on quit windows that contain a shell sitting at the prompt doing nothing are optionally ignored (if you use negative numbers for confirm_on_quit)

It's currently implemented for the zsh, fish and bash shells.

It works by installing hooks into the shell that inform kitty of changes
in the shell state, via escape codes allowing kitty to know various
things about the shell such as the
location of the prompt, the command being run, etc. kitty then uses this
information to enable the above features.

What I would like is:

  1. Testing, especially if you already use some kind of fancy prompt
    setup, does the integration work with it/break it?

  2. Comments on how well the functionality works/how useful it is

Details on how it works and how to configure it are in
docs/shell-integration.rst

To try it out use a nightly build of kitty

curl -L https://github.com/kovidgoyal/kitty/raw/master/docs/installer.sh | sh /dev/stdin \
    installer=nightly dest=/some/other/location

or build from source.

Running it should automatically enable shell integration if you use one
of the supported shells. To turn it off simply set

shell_integration disabled

in kitty.conf

Note that shell integration for bash only will write three lines at the end of your
.bashrc. These are safe to remove at any time, and will have no
effect unless you are running kitty with shell integration enabled. This is needed because bash is the only shell that provides no way for the invoking program to inject code into it robustly.

Thanks, and enjoy!

@mcarans
Copy link

mcarans commented Aug 18, 2021

This is great news!

I built kitty and ran. I found that when I launch it from the default terminal, mouse positioning doesn't work, but when I launch it from DomTerm, it does. It seems it needs the scripts DomTerm sources to make the cursor posiioning work (at least in my bash setup).

For copy paste with the mouse, I understand this is how to do it: https://sw.kovidgoyal.net/kitty/overview/#mouse-features
"Selecting text automatically copies it to the primary clipboard (on platforms with a primary clipboard).

You can middle click to paste from the primary clipboard (on platforms with a primary clipboard)."
Is there something I need to set to turn the above on, because it doesn't seem to work for me?

It appears kitty attempts to write to .bashrc every time it opens. I suggest documenting the shell integration lines needed and letting users decide if they want to add them to their .bashrc or not.

@kovidgoyal
Copy link
Owner Author

https://sw.kovidgoyal.net/kitty/conf/#opt-kitty.copy_on_select

@fladson
Copy link
Contributor

fladson commented Aug 19, 2021

Thanks for providing this integration. I did some minor testing and the open last output in less is great, I just wish we could copy things without the mouse in less, but I am assuming we can change the pager to something else, like we currently have for the scrollback.

Some other feedback, all done based on fc528941 macos build with /usr/local/bin/python3.9 setup.py and running ./kitty/launcher/kitty --config NONE

  • ctrl+shift+x is not working for me, I tested on zsh and bash, ctrl+shit+z is fine.
  • the prompt re-drawing is still not working for powerlevel10k

Screenshot 2021-08-19 at 15 24 34

I am not sure what I should do to test this, in this case, I just increased the font size a few times. - "Click with the mouse anywhere in the current command to move the cursor there" is not working for me

@kovidgoyal
Copy link
Owner Author

kovidgoyal commented Aug 19, 2021 via email

@page-down
Copy link
Contributor

I can confirm that all integration functions works fine under fish shell and zsh on macOS.

Click with the mouse anywhere in the current command to move the cursor there

If clicking the mouse fails to move the cursor, please note the new mouse_map default configuration.

mouse_map left click ungrabbed mouse_handle_click selection link prompt

However, although it functions properly, I notice that the latency is high, taking several hundred milliseconds from mouse click to cursor position update. May I ask if this is normal?

Also, with the fish shell, when creating the second tab, the bell icon appears in the first tab, which is annoying.

kitty_shell_integration_fish_shell_bell

This does not appear under zsh, and returns to normal after turning off prompt integration with fish shell. (shell_integration no-prompt-mark)

@kovidgoyal
Copy link
Owner Author

kovidgoyal commented Aug 20, 2021 via email

@chipaca
Copy link
Contributor

chipaca commented Aug 20, 2021

I built a fresh kitty, and I got the BEGIN_KITTY_SHELL_INTEGRATION block in my .bashrc as expected.

  • Ctrl+Shift+g works (huzzah!)
  • C+S+z/C+S+x don't seem to do anything
  • clicking with the mouse does nothing
  • I changed my .bashrc so it wouldn't try to set the terminal title, and it does not show the current directory: now a new terminal's title is always just bash, and then after I execute a command it stays saying the previous command.
    The titles do update as expected, but sometimes they show the wrong command. The message about HISTCONTROL wasn't visible anywhere until I ran kitty from a terminal.
    Doing tput reset; do-something-slow leaves the title as bash until do-something-slow finishes. (but C+S+g obviates the need for the reset; I just need to update my muscle memory)
  • the text cursor is not changed to a bar

all the above on Ubuntu 20.04.

@kovidgoyal
Copy link
Owner Author

post a minimal bashrc and bash version, so I can debug. All of the above work fine in bash
for me, with bash 5.1.8

@chipaca
Copy link
Contributor

chipaca commented Aug 20, 2021

bash says it is version 5.0.17(1)-release (x86_64-pc-linux-gnu).

I started kitty like so: env - PATH=$PATH HOME=$HOME DISPLAY=$DISPLAY kitty --config NONE bash --norc

With this, the terminal title was set to bash, as expected. I then sourced kitty.bash and the terminal title became the current working directory, and my cursor became a bar (should it always be a bar?).
The cursor moves with clicks, and the terminal title behaviour seems reasonable. I'll work on getting a minimal reproducing bashrc tomorrow (need to sleep now). Looking at the PS1 you get in this, I think my PROMPT_COMMAND setting PS1 is what's breaking at least the title thing. Dunno about the cursor movement / change.
C+S+z/x still do nothing.

@page-down
Copy link
Contributor

... the bell icon appears in the first tab ...

Doesn't happen for me, can you post a minimal fish config to recreate?

Never mind, this is a personal configuration issue.

However, I have found a minor problem. ​When running kitty for the first time, the configuration folder does not yet exist because the fish shell has never been run, so an error will be raised.

$ mv ~/.config/fish /tmp/
$ kitty --config=NONE -o shell=/usr/local/bin/fish
Traceback (most recent call last):
...
FileNotFoundError: [Errno 2] No such file or directory: '/Users/me/.config/fish/completions/tmpkxmlt3px.tmp'

For configuration file modifications, I personally suggest that it should be explicitly confirmed by the user for the first time and show the file path and the content to be inserted (or symlink).

(Just prompt like the quit confirmation. )

Since my configuration has its own structure, I don't want to be silently modified every time I start kitty with kitty --config=NONE.

File that already existed: ~/.config/fish/conf.d/kitty.fish(regular file) , were replaced with symlink, resulting in file loss.


I can confirm that everything listed works fine under macOS.

version:

  • macOS 11.5.2
  • bash 5.1.8
  • zsh 5.8
  • fish 3.3.1

@kovidgoyal
Copy link
Owner Author

kovidgoyal commented Aug 20, 2021 via email

@kovidgoyal
Copy link
Owner Author

kovidgoyal commented Aug 20, 2021 via email

@chipaca
Copy link
Contributor

chipaca commented Aug 20, 2021

OK, I sat own and went through the shell integration script, and pulled the necessary bits into my .bashrc.
Everything works, except the C+S+x/C+S+z combos.
Just to be sure I'm not misunderstanding: C+S+h to open the scrollback, and within it C+S+z/C+S+x should move me between prompts, right? I also tried outside of the C+S+h scrollback pager in case I was misunderstanding but that didn't work either.

@kovidgoyal
Copy link
Owner Author

kovidgoyal commented Aug 20, 2021 via email

@page-down
Copy link
Contributor

Click on prompt command to move the cursor is very useful. Thank you very much.

Is it possible to delete the selected text?

I currently use the following custom kitten to delete, although it's not perfect. I need to click first, then go forward and select the text to be deleted, then execute it.

from typing import List
from kitty.boss import Boss
from kittens.tui.handler import result_handler

def main(args):
    pass

@result_handler(type_of_input='selection', no_ui=True)
def handle_result(args: List[str], text: str, target_window_id: int, boss: Boss) -> None:
    w = boss.window_id_map.get(target_window_id)
    if w is not None and w.screen.cursor_at_prompt():
        lines = w.screen.text_for_selection()
        n = len(text or (lines and len(lines) == 1 and lines[0]))
        if n > 0:
            w.send_text('normal', '\x7f' * n)  # Backspace * n

Why does the second parameter return None even though the selection is already there? (with @result_handler(type_of_input='selection'))

How to output debug log when no_ui is True?

@kovidgoyal
Copy link
Owner Author

kovidgoyal commented Aug 20, 2021 via email

@page-down
Copy link
Contributor

  • When using confirm on quit windows that contain a shell sitting at the prompt doing nothing are ignored

In my own opinion, the purpose of confirm_os_window_close is to protect the current working environment from being accidentally closed (lost). And the current changes have taken away its core capabilities.

A tab that doesn't execute any programs, a tab or OS window that has been laid out and has multiple paths open, still has its own value. Just like any other tab-enabled browser or editor software, it doesn't do anything, but it's there when you need it.

I would like to use the shell integration features while retaining the ability to prevent OS windows or tabs with multiple window from closing accidentally. Maybe make this new feature as a new auto mode, but still keep the previous mode configurable. Thanks.

@kovidgoyal
Copy link
Owner Author

There are no changes to confirm_on_quit, you have to use negative values
to trigger ignoring of windows sitting at prompts.

@page-down
Copy link
Contributor

Sorry, I just saw the latest changes. The above feedback is for code that is a few dozen hours old.

Confirm that the positive integer value reverts to its original behavior.

@kovidgoyal
Copy link
Owner Author

No worries, I like to avoid making backwards incompatible changes as much as possible. Thus the use of negative numbers, see #3960 for discussion.

@kovidgoyal kovidgoyal pinned this issue Aug 21, 2021
@saulrh
Copy link

saulrh commented Aug 24, 2021

It looks like this might be clobbering $status inside prompts on fish. Impact should be relatively low because most fish prompts use $pipestatus, which survives; I only noticed it because I randomly popped starship off my backlog a few days ago and happened to be running a very recent kitty when I tried it.

Versions of stuff:

saul@enki ~> kitty --version
kitty 0.23.1 created by Kovid Goyal
saul@enki ~> starship --version
starship 0.56.0
branch:
commit_hash:
build_time:2021-08-23 01:48:13 -07:00
build_env:rustc 1.53.0 (53cb7b09b 2021-06-17),stable-x86_64-unknown-linux-gnu (default)

I observe correct behavior when I preserve $status by saving it at the start of kitty's injected fish_prompt and restoring it right before invoking _ksi_original_fish_prompt. Turning off shell integrations also fixes it.

@kovidgoyal
Copy link
Owner Author

There should be no problem with saving and restoring it. Since you
already have the code, post a patch or a PR and I will merge.

@kovidgoyal
Copy link
Owner Author

I went ahead and implemented it: 72e15d8

havent tested it with starship but I verified that the value of $status is preserved before clling _ksi_original_fish_prompt

@saulrh
Copy link

saulrh commented Aug 25, 2021

Can confirm fix, just pulled new kitty and tested with starship. Sorry I didn't get a patch in; I'd been using funced to mess with the prompt functions live so didn't actually have one ready to go, lol. Thanks for the quick fix! 👍

github.com/kovidgoyal/kitty [git master][$⇡][py v2.7.18]
➜ /bin/false
github.com/kovidgoyal/kitty [git master][$⇡][py v2.7.18]
✗ /bin/true
github.com/kovidgoyal/kitty [git master][$⇡][py v2.7.18]
➜

@chipaca
Copy link
Contributor

chipaca commented Sep 1, 2021

Would it be reasonable to ask that, when shell integration is enabled, get-text --extent take a new value of (say) last-command that gets the text you'd get with ctrl+shift+g?

@kovidgoyal
Copy link
Owner Author

kovidgoyal commented Dec 16, 2021 via email

@nertpinx
Copy link
Contributor

Oh wow!
Using no-cursor works as expected, just for anyone reading this it is shell-integration (without the "s") ;)
The other thing works when I do:
map <key> launch --stdin-source=@last_cmd_output --type=background xclip -i or my script for just using the last line.
Thanks for such a swift response, it made me go through the config options again and to be amazed one more time by seeing that I can solve more of my "feature requests".

@romkatv
Copy link
Contributor

romkatv commented Dec 20, 2021

Thank you for implementing shell integration in Kitty. I love it! Now, whenever someone complains that their zsh prompt gets messed up when resizing a terminal window, I tell them to try Kitty.

As promised, here is my attempt to avoid having to modify zshrc. f6e0eb4

This approach won't enable shell integration in the following cases:

  • If you manually run zsh in an existing interactive shell.
    • Perhaps because your login shell is fish but occasionally you want something more POSIX-y.
    • Perhaps because you need to create a temporary session with different environment variables.
    • Perhaps because you are running sudo -E zsh to create an interactive privileged shell.
  • If you SSH to a remote host with zsh as login shell.
  • If you have tmux as login shell and configure it to start zsh.
    • The problem here isn't that tmux won't propagate OSC 133. Kitty's integration script won't run at all.
  • A variation of the above: If you have zsh as login shell and have this at the top of ~/.zshrc:
    if [[ -z ${TMUX+X}${ZSH_SCRIPT+X}${ZSH_EXECUTION_STRING+X} ]]; then
      exec tmux
    fi

Many users will bump into one or more of these. For shell integration to be useful, it needs to work reliably.


I've implemented integration with Kitty in my zsh config. This config is public and has a few users other than myself. My integration doesn't suffer from the downsides listed above. However, since there is no mechanism to opt out from Kitty's native zsh integration, my users will have extra initialization code injected into their shells when/if Kitty's new release enables shell integration. At best it'll make their shell slower [1].

What do you recommend I do? One option would be to detect Kitty's native integration and print a warning asking the user to disable it. Is there a better alternative?

Ideally Kitty's integration would be so good that I could disable my own implementation if I detect Kitty's. In practice this seems like a difficult goal to achieve. For example, for Kitty's integration to work over SSH it'll need to do rather invasive things. Improving Kitty's integration is obviously a valuable thing to do [2]; at the same time, it would be great if shells could opt out if they have the means to implement things better. Kitty's integration has to work with all shell configs, while a specific shell config has to solve a more specific, and often easier, problem.


When running script /dev/null, Kitty is unable to detect the current working directory. iTerm2 and Apple Terminal can, provided that the shell cooperates. iTerm2 shell integration allows shell to report its current working directory via OSC 1337. Apple Terminal parses the shell-supplied terminal title and infers the current directory from it. The latter is not as reliable as the former but works most of the time.

It would be great if Kitty had something like this. I think it already has a DCS with "kitty", so perhaps piggyback on that? On the other hand, impelementing OSC 1337 will allow shells to provide just one integration for multiple terminals rather than a custom integration for each.


[1] I benchmarked with zsh-bench the effect of Kitty's native shell integration on top of my zsh config. The machine is MacBook Pro M1 (2021).

% git clone https://github.com/romkatv/zsh-bench.git ~/zsh-bench
% sudo ~/zsh-bench/zsh-bench --isolation user --iters 64 -- zsh4humans-no-tmux zsh4humans-no-tmux-kitty

==> setting up user zsh-bench with zsh4humans-no-tmux ...
==> benchmarking login shell of user zsh-bench ...
creates_tty=0
has_compsys=1
has_syntax_highlighting=1
has_autosuggestions=1
has_git_prompt=0
first_prompt_lag_ms=16.647
first_command_lag_ms=49.967
command_lag_ms=3.599
input_lag_ms=7.338
exit_time_ms=14.993

==> setting up user zsh-bench with zsh4humans-no-tmux-kitty ...
==> benchmarking login shell of user zsh-bench ...
creates_tty=0
has_compsys=1
has_syntax_highlighting=1
has_autosuggestions=1
has_git_prompt=0
first_prompt_lag_ms=19.130
first_command_lag_ms=56.813
command_lag_ms=5.660
input_lag_ms=6.096
exit_time_ms=17.124

When starting a new shell, Kitty's native integration delays the first prompt by 2.5ms and the first command by 6.8ms. Afterwards it adds 2.1ms delay on every command.

This may not sound like a lot but you start noticing lag on every command when it reaches 10ms or so. With a terminal as fast as Kitty the threshold might be even lower. The delay of 2.1ms eats 21% of the whole latency budget.

[2] I sent out #4377 with a few small improvements to zsh integration.

@kovidgoyal
Copy link
Owner Author

kovidgoyal commented Dec 20, 2021 via email

@romkatv
Copy link
Contributor

romkatv commented Dec 20, 2021

This is deliberate.

Just to make sure I understand what you mean by deliberate.

Suppose my login shell is zsh. I open a new tab. The shell in it gets shell integration automatically. I run zsh to create a new temporary interactive shell in which I'm going to export CLAGS, LDFLAGS, etc., and do some compiling. This shell does not get shell integration.

Is this intended? If I send you a PR that makes both of these shells have shell integration, will you reject it because it's deliberate that only the first shell has integration?

Simply set shell_integration disabled in kitty.conf and kitty will not try to inject anything into the shell's environment at all. There isn't currently a good way to disable this other than in kitty.conf.

You are writing a terminal and you would like its users to have good experience by default regardless of which shell config they use. I'm writing a shell config and I would like its users to have good experience by default regardless of which terminal they use. In order for Kitty users to have good experience you first attempted to modify their shell configs from the terminal. You didn't like doing it and neither would I. Now the table has turned: I need to modify a terminal's config from shell. Feels awful.

I'm not sure what would be a good mechanism for this. Perhaps a sentinel file in the filesystem or some other mechanism.

The PR I sent you incidentally adds a way for a shell to opt-out with only a minor performance cost. Users can put unset KITTY_SHELL_INTEGRATION in ~/.zshenv. Would you consider this a supported opt-out mechanism?

The canonical way to report working directory is OSC 7 not OSC 1337. However, I am not a fan of this See some discussion here: https://gitlab.freedesktop.org/terminal-wg/specifications/-/issues/20

Thanks for that link! I already have support for OSC 7 but I thought only VTE understood it. The discussion thread says that Terminal.app does too. I've enabled it and can confirm that it works!

kitty simply gets the working directory of the foreground process from the kernel and uses that. Works very well in practice.

This works as long as the process the user considers foreground is in the same session as the original process spawned by Kitty. script /dev/null results in a process tree like this:

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    0  9557  9557  9557 pts/0    14586 Ss       0   0:00 zsh
 9557 14586 14586  9557 pts/0    14586 S+       0   0:00  \_ script /dev/null
14586 14587 14587 14587 pts/1    14592 Ss       0   0:00      \_ zsh -i

From the user's point of view, zsh -i with PID 14587 is the foreground process. It has a different session id from the original shell, so Kitty won't look at it. Kitty will think zsh with PID 9557 is the foreground process.

Just throwing the idea out there: An escape code for reporting the TTY that the user considers in the foreground. I could send it from zsh quite easily. Then Kitty could use the same algorithm it does now (get the foreground process), but with the right session.

PRs are most welcome.

Cool! I'll send you another PR after the first is dealt with.

@kovidgoyal
Copy link
Owner Author

kovidgoyal commented Dec 20, 2021 via email

@romkatv
Copy link
Contributor

romkatv commented Dec 20, 2021

Seems easier for whatever process is trying to take over the tty to call tcsetpgrp() then both the kernel and kitty will know what the foreground PG is.

Each process belongs to a group. Each group belongs to a session. Each session may have one controlling terminal (or zero). Each terminal may be a controlling terminal of one session (or zero).

When Kitty is looking for a foreground process, it goes like this: TTY => session => foreground group => group leader. Note that kitty's TTY is always the controlling terminal of the final process.

When I run script, it creates another session, with another controlling terminal. Zsh process that I, as a user, consider foreground, is a leader of the foreground group of the new session and it has the new TTY as controlling terminal. I cannot use tcsetpgrp(kitty_tty, zsh_gid) because zsh process group doesn't belong to Kitty's session.

@kovidgoyal
Copy link
Owner Author

kovidgoyal commented Dec 20, 2021 via email

@romkatv
Copy link
Contributor

romkatv commented Dec 20, 2021

What is it that you are hoping to achieve by creating a new process group via script?

I use script for its intended purpose -- to log my session. Script achieves this by creating a TTY. The side effect of creating a TTY is the creation of a new session. There is no other way, is there?

It is correct behavior for the terminal to ignore the working directory of a new process group that is not freground on the tty device the terminal controls.

It depends on what you mean by "correct" and "ignore". iTerm and Terminal.app pick up the current directory from script. They display it in the title and use it when I open a new tab. Maybe it's incorrect but I like it.

Note that, in your scenario you have one process that is foreground on the tty

That's right.

and another that is not foreground but that it still outputting to the terminal.

That's not right. Only processes from the foreground group can write to the TTY. If any other process attempts it, it'll get killed with SIGTTOU.

script is a leader of the foreground group of Kitty's TTY. It's the only process reading and writing to Kitty's TTY. zsh is the leader of the foreground group of script's TTY. scripts reads Kitty's TTY and forwards it to its own so that zsh can read it from script's TTY. It also forwards data the other way. Everything it forwards, it also writes to a file -- this is the reason I'm running it in the first place. This file allows me to replay a session. I often do it at slower speed when optimizing drawing of shell UI.

@kovidgoyal
Copy link
Owner Author

kovidgoyal commented Dec 20, 2021 via email

@romkatv
Copy link
Contributor

romkatv commented Dec 20, 2021

Use something that both creates a new tty and also updates its working directory when the cwd of the child process changes.

At least on Linux this cannot be done. I don't know BSDs and macOS well enough to say whether it can be done there.

The problem arises in the following situation. Suppose I run fancy-script, which is just like regular script but it also monitors cwd of the foreground process of its TTY and changes its own cwd to match. Suppose it spawns shell for me and I run this script in it:

mount ... /mnt/blah
cd /mnt/blah
sleep 1
cd /
umount /mnt/blah

The last command will most likely fail with "target is busy" because fancy-script won't cd out of /mnt/blah fast enough.

Yeah it works in this case and fails in the case I outlined before, of opening an editor and doing a cd in it. Pick your poison.

Hence the idea: Add an OSC that would allow shell to tell the terminal which TTY is the foreground one. Are there cases where it won't work?

P.S.

I actually have a workaround that I use with Kitty but it's rather ugly. Within script I create directory /tmp/script-cwd-$PID where $PID is the PID of script and then cd into it. script just sits in that directory. When I ask Kitty to open a new tab in the same current directory, my shell will end up in /tmp/script-cwd-$PID. The shell will recognize it as a "trampoline" directory, extract PID, resolve PID => session => foreground group => group leader => cwd, and finally cd into the directory I want.

@romkatv
Copy link
Contributor

romkatv commented Dec 20, 2021

I don't know BSDs and macOS well enough to say whether it can be done there.

OK, it cannot be done anywhere with file permissions. The parent process is not guaranteed to have permissions to cd.

@kovidgoyal
Copy link
Owner Author

kovidgoyal commented Dec 20, 2021 via email

@kovidgoyal
Copy link
Owner Author

And as for session recording, kitty already has --dump-bytes that records half of it (the data received over the tty). It should not be hard to extend it to implement script and scriptreplay robustly. Though I dont know why one would want to repay a terminal session for anything other than debug purposes.

@romkatv
Copy link
Contributor

romkatv commented Dec 20, 2021

It suffers from the same limitation as OSC 7. Basically every program you run has to be aware of it

The difference between the proposed protocol and OSC 7 is that very few programs need to be aware of it. Only those that proxy data between TTYs: script, screen, tmux and unbuffer. Maybe I've missed one. [1] Each of these will need to send the name of the inner TTY to the parent TTY on start. Doing it just in tmux will likely cover the vast majority of cases where currently the terminal's idea of a foreground process doesn't match the user's idea.

  1. parent suspends child for whatever reason (say user presses ctrl-z or equivalent)

It's a good point that SIGSTOP would cause issues.

Pressing Ctrl-Z or equivalent won't do it. Ctrl-Z is a shell binding. If you press it while running script, ^Z will go all the way to the child shell that runs under script. That shell can decide what to do with it. So to break the new protocol one would have to manually send SIGSTOP to script. Anyone who does that (why?) probably knows what they are doing.

As far as the parent process not being able to cd for permissions, that is an extreme corner case, and not worth worrying about, IMO.

I agree. The other issue is more severe because it'll break user programs. It would suck if programs that doesn't even use a terminal would fail when executed under script or tmux.

And as for session recording, kitty already has --dump-bytes that records half of it (the data received over the tty).

That's good to know. I might use it for other purposes.

To be completely honest, I was a bit coy about my use case with script. It is a real use case and I do use script for recording sessions and replaying them at slow speed (zsh-bench also uses script under the hood) but my main use case is tmux. Tmux is much more complex than script, so I focused on the latter. It's much easier to understand: no client-server architecture, no IPC, no daemon, no multiplexing.

[1] Maybe ssh could make use of this protocol too, but to solve a different problem. Protocols such as OSC 7 have an issue with ssh when data from the remote machine starts flowing into the local TTY but the TTY doesn't know it's remote. If ssh could notify the parent TTY that now a "remote" TTY is in the foreground, that could help.

@kovidgoyal
Copy link
Owner Author

:) script is more compelling use case to me than tmux. It is one of the kitty goals to make terminal multiplexers obsolete. My views on it are well known, and I wont repeat them here. In any case, if you wish to continue this discussion please do so in a separate discussion post, as this is straying far form the topic of this issue.

I do agree that your proposal is better than OSC 7 (although I think you have sadly underestimated the number of multiplexers out there, I am personally aware of at least 3-4 more).

@romkatv
Copy link
Contributor

romkatv commented Dec 20, 2021

:) script is more compelling use case to me than tmux.

I'm well aware 😁

I do agree that your proposal is better than OSC 7 (although I think you have sadly underestimated the number of multiplexers out there, I am personally aware of at least 3-4 more).

If even you know fewer than a dozen TTY proxies (some of which are multiplexers), the number must be small (compared to the number of all programs that people run in a TTY, that is).

In any case, if you wish to continue this discussion please do so in a separate discussion post, as this is straying far form the topic of this issue.

Fair enough. Let's end this discussion then. I won't be opening an issue for it. It was just a random idea.

Going back to the real topic of this issue, I'm working on improving zsh integration in Kitty. Will send a PR within a day or two.

@romkatv
Copy link
Contributor

romkatv commented Dec 22, 2021

I'm working on improving zsh integration in Kitty. Will send a PR within a day or two.

Sent #4386.

This approach won't enable shell integration in the following cases: [...]

There is one more case, which might be the most common.

Zsh users (and perhaps other shell users although I'm less familiar with their practices) often apply rc file changes to the current shell with exec zsh or exec $SHELL. This will disable automatic shell integration.

I understand that it is your intention to turn off shell integration whenever users create a new shell but I cannot help but think it'll be very confusing. Sometimes prompt title will update, sometimes it won't. Sometimes cursor shape will change based on keymap and sometimes it wont. Sometimes key shortcuts that depend on shell integration will work and sometimes they won't. It's not going to be easy for users to figure out the exact conditions under which features work or don't work, and what they can do to make them either either consistently work or consistently not work. The thought that exec zsh has this effect is unlikely to come naturally. It'll be an entirely unique effect of this command.

@kovidgoyal
Copy link
Owner Author

Closing as this has now been released

@kovidgoyal
Copy link
Owner Author

For bash users: I have now implemented shell integration for bash without the need to modify .bashrc. Please test using the nightly build. For an overview of how it works, see
https://github.com/kovidgoyal/kitty/blob/master/docs/shell-integration.rst#how-it-works

@akinomyoga
Copy link
Contributor

.. tab:: bash

    For bash, kitty starts bash in POSIX mode, using the environment variable
    ``ENV`` to load the shell integrtion script. This prevents bash from
    loading any startup files itself. The loading of the startup files is done
    by the integration script, after disabling POSIX mode. From the
    perspective of those scripts there should be no difference to running
    vanilla bash.

Great! I think this is still nice, but this doesn't work for the child Bash sessions started by the command bash. So, the users who would like to continue to use the shell-integration also in the child Bash sessions can optionally source the shell-integration script in their .bashrc.

@kovidgoyal
Copy link
Owner Author

Yes, just as with the other shells, if you want integration in
subshells/containers/etc., you have to set it up manually, as documented
in https://sw.kovidgoyal.net/kitty/shell-integration

@carnotweat
Copy link

I have no kitty.app but ~/.nix-profile/bin/kitt@
Do I have to build from source?
Nixos

@kovidgoyal
Copy link
Owner Author

this was released over a year ago. Use the official kitty binaries if your distro kitty package is out of date.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests