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

Search scrollback #189

Open
1 of 4 tasks
mitchellh opened this issue Jul 6, 2023 · 57 comments
Open
1 of 4 tasks

Search scrollback #189

mitchellh opened this issue Jul 6, 2023 · 57 comments
Assignees
Labels
gui GUI or app issue regardless of platform (i.e. Swift, GTK)

Comments

@mitchellh
Copy link
Contributor

mitchellh commented Jul 6, 2023

A major missing feature is the ability to search scrollback, i.e. cmd+f on Mac, ctrl+F on Linux. This issue can be implemented in multiple steps, not just one giant PR:

  • Core search functionality in src/terminal (Naive search internals (core only) #2885)
  • Make core search work simultaneously to PageList read/write to allow multi-threading
  • Implement multi-threaded search, including data modeling for notifications of matches
  • Search UI, glue in apprt

We can also support search only in certain modes as long as the apprt glue is all there for someone to come along and finish it up. For example, only macOS, Linux+GTK, etc.

@amadeus
Copy link
Collaborator

amadeus commented Jul 7, 2023

Would be cool to fake what terminal emulator in vim does -- where you can pause the existing session ctrl+w N, and move around the buffer with vim commands for searching and highlighting, then press i to return back into the session. Here's an example video (not saying the commands should be the same to pull this off, just using that as an example):

CleanShot.2023-07-07.at.00.09.42.mp4

@andrewrk
Copy link
Collaborator

Looking forward to this feature - I missed it yesterday when I had a lot of output from a command and wanted to search for the word "fail".

@vancluever
Copy link
Collaborator

vancluever commented Nov 22, 2023

Kitty has a a pretty novel approach here that I've actually really enjoyed - ctrl+shift+h actually sends the scrollback to a pager (e.g. less). I've found this much less confusing in comparison to others (like iTerm's).

This also lets you take advantage of the pager's features and can be tailored to a certain user's preference without minimal load on our side.

@gpanders
Copy link
Member

Kitty has a a pretty novel approach here that I've actually really enjoyed - ctrl+shift+h actually sends the scrollback to a pager (e.g. less). I've found this much less confusing in comparison to others (like iTerm's).

FYI Ghostty has this too, bound to Cmd-Shift-J on macOS and Ctrl-Shift-J on Linux.

It works slightly differently than Kitty in that it puts the temp file path to the captured scrollback on the command line rather than opening it in a pager directly.

@benwaffle
Copy link
Collaborator

Once we have search, searching via regex would be really nice to have. I've been finding myself search for exit [^0] a lot recently.

@mattpolzin
Copy link
Collaborator

Kitty has a a pretty novel approach here that I've actually really enjoyed - ctrl+shift+h actually sends the scrollback to a pager (e.g. less). I've found this much less confusing in comparison to others (like iTerm's).

FYI Ghostty has this too, bound to Cmd-Shift-J on macOS and Ctrl-Shift-J on Linux.

It works slightly differently than Kitty in that it puts the temp file path to the captured scrollback on the command line rather than opening it in a pager directly.

One nice thing about Kitty's implementation is you can even use it as a program is actively running and potentially still outputting text; new text doesn't automatically get fed into your pager but you don't need to wait until a command finishes to use the pager functionality.

I'm not immediately sure if that would be equivalent in behavior to

  1. Pause current execution
  2. Send to background
  3. Open ghostty's scrollback file in pager
  4. On quit, bring task to foreground if still running

@pjz
Copy link
Collaborator

pjz commented Jan 24, 2024

I'm used to screen/tmux behavior here: ctrl-A,[ puts you into 'scrollback mode' where you can then use the keyboard (vi-keys) to scroll up and down, and then even hilight some text and put it into a clipboard where you can then paste it with ctrl-A,].

I don't think it updates the buffer while scrolling, though... but I don't see why it couldn't just extend it downward.

@yankcrime
Copy link
Member

yankcrime commented Feb 1, 2024

Personally I'd rather this stuck to OS-native conventions for search functionality as well as look and feel. I don't think implementation-specific idiosyncrasies are a good idea since a lot of folks will have differing preferences and expectations.

The implementation along the lines of what's provided by Terminal.app or iTerm would be fine since that easily lets you search the scrollback buffer in a way that doesn't affect any additional output.

@andrewrk
Copy link
Collaborator

andrewrk commented Feb 1, 2024

Some prior art:

image

It... suffices.

@peteschaffner
Copy link
Collaborator

@qwerasd205 Are you working on this now? I'd be happy to help out on the macOS UI front.

(I mentioned this in Discord but just surfacing it here too since I rarely check over there.)

@qwerasd205
Copy link
Collaborator

I am working on laying some groundwork for this with a basic implementation of the search functionality - focused mainly on proper threading for the search and creating a good interface for the UI code to talk to with minimal coupling, so that in the future we can improve the performance of the search (if necessary) by changing the algorithm and/or data structures used for the searching. I'll open a draft PR once I've got the first "technically functioning" version of the code.

Right now it's in too early of a state to really create UI for.

@ferdinandyb
Copy link
Collaborator

Personally, "native" in a terminal means "vi-like" to me :) I also think kitty's approach is pretty flexible and can probably be used along side a more classic ctrl-f as well. I also quite like contour's vim-like normal mode tbh.

But why I actually wanted to comment is related to generic search, but a bit more specific: sometimes you actually see what you need on screen, but want to quickly copy/paste/execute it without a mouse. Back when I was using kitty I used hints a lot, and in tmux I use tmux-butler. Behind the scenes these use cases could be regex-searches constrained to the currently visible text, although obviously the UI would be quite different. Imho especially quickly opening links in the browser and copying paths to the prompt without a mouse is really useful.

@sluongng
Copy link

I wanted to file a feature request for something like Kitty Hints like @ferdinandyb mentioned.
https://sw.kovidgoyal.net/kitty/kittens/hints/

However, after a bit of searching, I figured this issue is a prerequisite for such a hinting system.

@andrewrk
Copy link
Collaborator

More prior art:

image

Konsole has a pretty decent implementation if you want something to draw inspiration from.

@rmacklin
Copy link

Re:

I wanted to file a feature request for something like Kitty Hints like @ferdinandyb mentioned. https://sw.kovidgoyal.net/kitty/kittens/hints/

However, after a bit of searching, I figured this issue is a prerequisite for such a hinting system.

Mitchell confirmed on Discord that this issue isn't a prerequisite for a "hints" feature - so I've gone ahead and created a separate issue to specifically discuss that feature request:

@qwerasd205
Copy link
Collaborator

qwerasd205 commented Jul 29, 2024

I am working on laying some groundwork for this with a basic implementation of the search functionality - focused mainly on proper threading for the search and creating a good interface for the UI code to talk to with minimal coupling, so that in the future we can improve the performance of the search (if necessary) by changing the algorithm and/or data structures used for the searching. I'll open a draft PR once I've got the first "technically functioning" version of the code.

Right now it's in too early of a state to really create UI for.

I got sidetracked from this shortly after starting work on it, but to summarize the architecture I landed on for the search thread:

Search Thread

Data

  • Search results: Doubly linked list of spans represented by pairs of pins
  • Active area search results: Separate results list for content in the active area, since it needs to be repopulated whenever the active area's content changes (dirty tracking logic could be added in the future if necessary)
  • Search pattern: Struct containing info used to perform the search (in my prototype it's just a string and a flag for whether to be case insensitive)

Messages

  • Search pattern updated; if new pattern is different from old pattern, reset search results, and if currently mid-search, reset search back to start (either top or bottom of scrollback, depending on which direction the search is performed in)
  • Begin search; start searching, intermittently yielding to the event loop. In my prototype I use a line iterator. If no iterator exists, create a new one, take a line from it, apply the pattern, add any results to the results list, notify the surface - if the iterator is out, we're done searching, notify the surface of this fact - then check the mailbox again.
  • Stop search; self explanatory.
  • Active area updated; if not currently searching, do nothing - otherwise throw out current active area results list, apply the search pattern to all lines in the active area, update the results list, notify the surface.

Whenever the surface is notified of new search results, it updates its display accordingly, reading from the results list should be thread safe.

@sethgrid
Copy link

I just did a full grep of my file system looking for a breadcrumbs and then found out I can't search through my results. I was able to cmd+a cmd+c tab to vscode and cmd+p and then cmd+f. I am constantly using cmd+f on my terminal :(

@AdrielVelazquez
Copy link

AdrielVelazquez commented Dec 28, 2024

I wanted to provide some recipes for people waiting for this

Searching by piping to fzf

cat <ctri + shift + j> | fzf
cat /tmp/lxFj1l2gJE_1KUpyQWkPWQ/history.txt | fzf  (example command)

Searching via Neovim

Make sure that the default for xdg-open (linux) or open (mac) is set to nvim or whatever code editor you use

Example in NixOs

  xdg.mime.enable = true;
  xdg.mimeApps.enable = true;
  xdg.mimeApps.defaultApplications = {
    "text/plain" = [ "nvim.desktop" ];
  };

Then create a new keybinding in ghostty

keybind = ctrl+f=write_scrollback_file:open

Using ZSH (Janky)

This is essentially just looking for the most recent history file. Sometimes the most recent output isn't there since it's dependent on calls to write_scrollback_file. And that's not a simple binary you can call.

        function jank_scrollback_search() {
          # Find all files named history.txt in /tmp
          local files=$(find /tmp -name "history.txt" -print0 | xargs -0 stat -c '%Y %n' | sort -rn | head -n 1 | awk '{print $2}')

          if [[ -z "$files" ]]; then
            echo "No history.txt files found in /tmp" >&2
            return 1
          fi
          local trimmed_files=$(echo "$files" | tr -d ' \n')

          cat $trimmed_files | fzf
        }

        zle -N jank_scrollback_search

        # Bind the widget to Ctrl+f
        bindkey '^f' jank_scrollback_search

@elCarlosSantiago
Copy link

I've setup my new ghostty terminal and am really enjoying it. Unfortunately, wont be daily driving it until this functionality is ready. Key part of my workflow

@Tenzer
Copy link

Tenzer commented Dec 28, 2024

To elaborate on the earlier comment, a workaround for this currently exists in that you can bind keys to open an editor with all the text from the current terminal in it, which can then be searched through.

The default keybinds related to this are:

  • super+shift+j: write_scrollback_file:paste
  • super+alt+shift+j: write_scrollback_file:open

The documentation for write_scrollback_file can be found here: https://ghostty.org/docs/config/keybind/reference#write_scrollback_file.

One slight downside with these, as they are now, is that they only write contents outside the visible area to the temporary file, so they don't help if you want your search to also include what is currently shown.

If you want that included, you instead want to add a keybind that use the related write_screen_file method, as it includes all the contents in the tab.

I personally find write_screen_file more useful than write_scrollback_file so I have overridden the above mentioned keybinds to use that instead:

keybind = super+shift+j=write_screen_file:paste
keybind = super+alt+shift+j=write_screen_file:open

This allows me to press super+alt+shift+j which then opens the default editor for .txt files (at least on macOS) with the contents of the terminal, which can then be searched through.

@tednaleid
Copy link

tednaleid commented Dec 29, 2024

for the workarounds, is there any way to script the calls to write_scrollback_file and write_screen_file or can they only be triggered via keybinds?

Currently, if I add this keybinding for writing the name of the screen file to the terminal:

keybind = super+shift+k=write_screen_file:paste

Then, I can manually type (on a Mac):

cat <cmd + shift + k> | fzf

If there were some way to trigger those actions without having to press the keybinding, I could do something like:

cat <(ghostty --run-action write_screen_file:paste) | fzf

and assign that to a script/alias

That'd give me almost all the scrollback searchability I need

@xzbdmw
Copy link

xzbdmw commented Dec 29, 2024

and assign that to a script/alias

see #3708 (comment)
I wish ghostty could somehow preserve escape sequence colors so I can use :term cat something in nvim.

@msharran
Copy link

msharran commented Dec 29, 2024

I find this feature in kitty very useful rather than using cmd+f. I have tried both and this was practically useful for me. (Genuinely want to understand how others feel about this also)

When my unit test output is very long, i just open the last command output in LESS and troubleshoot.

If the cmd's output I am looking for is few prompts before, in kitty, I would navigate to it using keyboard shortcuts (ghostty can also do this) and right click holding kitty_mod to open in LESS. (See here)

In ghostty, it would be useful to redirect write_selection_file output to any program's STDIN.

Like

keybind = "super+shift+w>s=write_selection_file | less"

@marianposaceanu
Copy link

Based on the previous comments - I'm currently using this on macOS:

keybind = super+f=write_screen_file:open

This way it won't stop me from using Ghostty as a daily driver.

@DontEatOreo
Copy link

DontEatOreo commented Dec 29, 2024

I'm surprised copy isn't an option. Wouldn't this partially solve the issue since you can just quickly take a "snap," go to another window, manually paste the path, and open it in your editor?

For example, right now, if you have a TUI program or you're in an interactive state, the only option you can use is open, since paste will cause an interaction

I'm personally rooting for #189 (comment). This seems like one of the nicest implementations for such feature

Since this reply will ping a lot of people, I might as well just ask: Is there any workaround to still use open but to give it a custom program instead of it grabbing the default text editor?

@xzbdmw
Copy link

xzbdmw commented Dec 30, 2024

I'm surprised copy isn't an option.

FYI you can use cmd+a + cmd+c to copy all the text.

@Stono
Copy link

Stono commented Dec 30, 2024

I've setup my new ghostty terminal and am really enjoying it. Unfortunately, wont be daily driving it until this functionality is ready. Key part of my workflow

Yeah I second this. I've really being enjoying Ghostty but found the inability to do cmd+f pretty debilitating in my day to day workflow. It's like the only missing piece of the puzzle for me! I'm kinda sad to have to go back to iterm for now!

@jdx
Copy link

jdx commented Dec 30, 2024

this issue is the most thumbed several times over. There are likely hundreds of people subscribed to it. It's not helpful to post messages here simply saying it "doesn't fit your workflow". @mitchellh knows this is necessary. He'll work on it when he can I'm certain. Let's try to keep the discussion to helpful information.

@Stono
Copy link

Stono commented Dec 30, 2024

I was actually, primarily, complimenting the awesome terminal this is because it quite literally is almost perfect and I'm quite excited by that. As the issue has been open for 18 months I perhaps wrongly made an assumption that it probably wasn't moving forward (at least any time soon) so was just adding my perspective to it.

I'm sorry for sharing my experience with Ghostty and I'm sorry you took such offence to that mistake. It's such a shame GitHub (and tech in general) is so hostile these days, people just seem to assume the worst in each other.

Merry Christmas!

@jdx
Copy link

jdx commented Dec 30, 2024

I apologize if that came across as hostile, it was not meant to, nor what is it targeted at you since you're not the only one in recent days to have done this. My goal is simply to keep the discussion here helpful since it has a lot of eyeballs on it and we don't want to add to the noise.

@Stono
Copy link

Stono commented Dec 30, 2024

That is completely fair, and I understand - thanks. 🤝

@eaverdeja
Copy link

keybind = super+f=write_screen_file:open

Did anyone manage to get this to open in vim/nvim? I have nvim as my default editor on MacOS, but for some reason ghostty still opens the buffer in the default MacOS text edit.

@martensson
Copy link

keybind = super+f=write_screen_file:open

Did anyone manage to get this to open in vim/nvim? I have nvim as my default editor on MacOS, but for some reason ghostty still opens the buffer in the default MacOS text edit.

It uses the default editor of MacOS, not your $EDITOR. There is an OS setting to modify it globally from the default (need to Google it), but probably better to change it to MacVim rather than a CLI-tool in this case.

@eaverdeja
Copy link

Thanks @martensson ! I got it to work with Neovide by setting the default editor via Launch Services:

 defaults write com.apple.LaunchServices/com.apple.launchservices.secure LSHandlers -array-add '{
    LSHandlerContentType = "public.plain-text";
    LSHandlerRoleAll = "com.neovide.neovide";
}'

@elCarlosSantiago
Copy link

elCarlosSantiago commented Dec 30, 2024

Thanks @martensson ! I got it to work with Neovide by setting the default editor via Launch Services:

 defaults write com.apple.LaunchServices/com.apple.launchservices.secure LSHandlers -array-add '{
    LSHandlerContentType = "public.plain-text";
    LSHandlerRoleAll = "com.neovide.neovide";
}'

Great solution, officially daily driving it now. Here's the command for vscode, can be done for any editor.

 defaults write com.apple.LaunchServices/com.apple.launchservices.secure LSHandlers -array-add
'{
    LSHandlerContentType = "public.plain-text";
    LSHandlerRoleAll = "com.microsoft.VSCode";
}'

@justyn
Copy link

justyn commented Dec 31, 2024

Regarding the implementation of search in Ghostty.

Different terminals have different approaches to search. For example, Wezterm has both Copy Mode and Quick Select Mode.

I personally would really value something that emulated my (Lazy)Vim configuration - not just basic Vim motions but custom textobjects, seeking with flash.nvim etc. Obviously I can get part of the way there with write_selection_file but it is a bit clunky and doesn't update with new output.

Given that it would be bloated for Ghostty implement all the different approaches, could it instead hand over to an external tool for the search? That would allow experimentation and innovation in this area without affecting Ghostty's code.

Perhaps there is something more streamlined than dumping the scrollback to a file then opening it in an editor... I haven't figured out the mechanics (a pointer? an emulated file?). Or is write_scrollback_file the only reasonable way it can be done?

@zxt-tzx
Copy link

zxt-tzx commented Dec 31, 2024

Thanks @martensson ! I got it to work with Neovide by setting the default editor via Launch Services:

 defaults write com.apple.LaunchServices/com.apple.launchservices.secure LSHandlers -array-add '{
    LSHandlerContentType = "public.plain-text";
    LSHandlerRoleAll = "com.neovide.neovide";
}'

Great solution, officially daily driving it now. Here's the command for vscode, can be done for any editor.

 defaults write com.apple.LaunchServices/com.apple.launchservices.secure LSHandlers -array-add
'{
    LSHandlerContentType = "public.plain-text";
    LSHandlerRoleAll = "com.microsoft.VSCode";
}'

not sure if this applies more generally, but I needed to restart my Mac for this to take effect. thanks for the suggestion!

@github-cloud-cd
Copy link

On MacOS the defaults command requires you to log out and back in for it to take effect. A reboot will also work.

@rmacklin
Copy link

rmacklin commented Dec 31, 2024

Regarding the implementation of search in Ghostty.

Different terminals have different approaches to search. For example, Wezterm has both Copy Mode and Quick Select Mode.

For quick select mode, there is a feature request here (the title is based on the analogous feature in kitty):

@Stono
Copy link

Stono commented Dec 31, 2024

For some reason I couldn't get the commands above to work, but duti from brew helped:

brew install duti
duti -s com.microsoft.VSCode public.plain-text all

I didn't need to log back in for this either.

If you need to find the plist identifier for your desired app, do:

/usr/libexec/PlistBuddy -c 'Print CFBundleIdentifier' /Applications/Visual\ Studio\ Code.app/Contents/Info.plist

I failed to get it to open anything not installed as an Application though (for example i have nvim installed via brew).

jhthorsen added a commit to jhthorsen/dotfiles that referenced this issue Jan 1, 2025
ghostty-org/ghostty#189

It would be very nice if "open" took a parameter, so I could open
"something" in ex. neovim. Could be as simple as:

  keybind = super+comma=open_config:myprogram.sh
  keybind = super+alt+shift+j=write_scrollback_file:open:myprogram.sh

Where "myprogram.sh" would take the file as `$1`. I guess one problem is
that where would "myprogram.sh" run? Maybe in an overlay? It can't run
in the same terminal, since there might be another program already
running there. Ex. tail, less, bat, ...

What I really like:

- Resizing splits feels a lot nicer than wezterm
- Changing the font-size feels a lot nicer than wezterm

...still going to use wezterm for now though.
@mmerickel
Copy link

As a new user coming from iterm+tmux and trying to use ghostty as a replacement the main hangup I've run into is around scrollback management. With tmux I can use ctrl-a-[ to enter a scrollback mode where I can use ? and / to search the scrollback, as well as hjkl to navigate, ctrl-u to page up and ctrl-d to page down, and space to start a selection, and enter to finish a selection, copying it to the clipboard. I think something like this would require a new scope for key-bindings like scrollback alongside the current all and global scopes.

I would really love this modal capability in ghostty with the added benefit that whatever y'all do would also work well with the mouse where tmux tends to struggle.

advincze added a commit to advincze/dotfiles that referenced this issue Jan 3, 2025
@escluse
Copy link

escluse commented Jan 3, 2025

Great solution, officially daily driving it now. Here's the command for vscode, can be done for any editor.

 defaults write com.apple.LaunchServices/com.apple.launchservices.secure LSHandlers -array-add
'{
    LSHandlerContentType = "public.plain-text";
    LSHandlerRoleAll = "com.microsoft.VSCode";
}'

not sure if this applies more generally, but I needed to restart my Mac for this to take effect. thanks for the suggestion!

You can do this using Finder:

1/ select "Get Info" on any .txt, etc. file
2/ change the "Open With" default to any macOS Application

However, this doesn't work for $EDITOR and it's not worth creating a .app wrapper bundle given that it launches an entirely new instance.

@m4saurabh
Copy link

I like the way kitty does it, it exposes the scrollback buffer and you pipe that to any program, like less and more importantly neovim so you can move around with vim bindings without creating a subpar version of them.

@tmccombs
Copy link

tmccombs commented Jan 5, 2025

FWIW, wezterm has a feature similar to kitty's which allows you to send the buffer to an external program. But also has it's own search and navigation modes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
gui GUI or app issue regardless of platform (i.e. Swift, GTK)
Projects
None yet
Development

No branches or pull requests