summaryrefslogtreecommitdiffstats
path: root/zellij-utils
diff options
context:
space:
mode:
authormsirringhaus <50315401+msirringhaus@users.noreply.github.com>2022-07-18 10:54:23 +0200
committerGitHub <noreply@github.com>2022-07-18 10:54:23 +0200
commitbae1548495b1b0f0e30d55db0197d087f5520167 (patch)
treeb3985d122e8db444e21e21d80a8fbb0aea8a9522 /zellij-utils
parentdd08fec5709ee7d8906cba8eecf773fd4bf5e5a7 (diff)
feat(terminal): search panes (#1521)
* WIP: First draft of searching in panes. * Add ability to highlight search-results in viewport and move forwards/backwards * Clear search results when leaving search * Search newly scrolled in lines and have live-search when entering search-term * search_forward/backward() now doesn't get the needle again, since we already know it * Use red and yellow from theme. No idea if we should introduce new 'search'-colors * Implement moving the viewport for searches outside the current one. * Implement hacky case-insensitivity (ASCII only at the moment) * Implement wrap-search and prepare infrastructure for whole-word search * Add a bunch of tests and an embarrasing amount of bugfixes * Remember search selection when toggling case-sensitivity (if possible) * New tab integration tests and make search work with floating panes * Make highlights work with resize (not keeping the active-selection in most cases) * Switch the search-algo a bit in order to make multi-line search work * Don't forget active selection when nothing more is found, reflow found selections and scroll correctly * Make all search-related function calls in plugin-pane No-ops * Activate whole word search (ASCII only) * Run cargo fmt * Make clippy happy * Remove unneeded transferred_rows_count * Remove boilerplate and use macro instead * Add explanatory comments * Move search-related functions into SearchResults impl and try to remove duplicate code * Move clearing of search-results upon mode-switch to appropriate place * Jump to the first occurence while typing (EnterSearch), if none is found in the current viewport * Always show needle and also show search modifiers in pane title * Integration tests now use correct InputMode, so we can test the pane title when doing searches * Move no-op implementation of search-functions from plugin-pane to pane-trait * Move SearchResult to its own file * Try to clean up search_row() a bit * Make clippy happy * fix: various typos (#1553) Because they were wrong. * flake.lock: Update (#1554) Flake lock file updates: • Updated input 'crate2nix': 'github:kolloch/crate2nix/805cdaf084c859c2ea0c084b74f4527b0483f6aa' (2022-06-17) → 'github:kolloch/crate2nix/91f333aca414ee346bc5bdea76fe9938f73a15f9' (2022-07-01) • Updated input 'flake-utils': 'github:numtide/flake-utils/1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1' (2022-05-30) → 'github:numtide/flake-utils/bee6a7250dd1b01844a2de7e02e4df7d8a0a206c' (2022-06-24) • Updated input 'nixpkgs': 'github:nixos/nixpkgs/3d7435c638baffaa826b85459df0fff47f12317d' (2022-06-16) → 'github:nixos/nixpkgs/0ea7a8f1b939d74e5df8af9a8f7342097cdf69eb' (2022-07-02) • Updated input 'rust-overlay': 'github:oxalica/rust-overlay/da04f39d50ad2844e97a44015048c2510ca06c2f' (2022-06-18) → 'github:oxalica/rust-overlay/bbba5e73a21c8c67d5fe1d4d8b3fde60ab6946cd' (2022-07-03) * fix: fallback to default values when terminal rows/cols are 0 (#1552) * fix: fallback to default values when terminal rows/cols = 0 * increase retry_pause for failing test * e2e: load fixtures with cat * use variable for fixture path * docs(changelog): fix 0 rows or cols crash * fix(ci): clippy (#1559) Install `cargo-make` explicitly in the workflow, even tough it should be cached from the previous steps. There are some corner cases in which gh messes the caching up and can't access it. * add(nix): add `compact-bar` to the flake outputs (#1560) The compact bar wasn't an output yet. * refactor(crates): move shared contents from zellij tile to zellij utils (#1541) * zellij-tile: Move `data` to zellij-utils The rationale behind this is that all components of zellij access the data structures defined in this module, as they define some of the most basic types in the application. However, so far zellij-tile is treated like a separate crate from the rest of the program in that it is the only one that doesn't have access to `zellij-utils`, which contains a lot of other data structures used throughout zellij. This poses issues as discussed in https://github.com/zellij-org/zellij/pull/1242 and is one of the reasons why the keybindings in the status bar default plugin can't be updated dynamically. It is also the main reason for why the keybindings are currently passed to the plugin as strings: The plugins only have access to `zellij-tile`, but since this is a dependency of `zellij-utils`, it can't import `zellij-utils` to access the keybindings. Other weird side-effect are that in some places `server` and `client` have to access the `zellij-tile` contents "through" `zellij-utils`, as in `use zellij_utils::zellij_tile::prelude::*`. By moving these central data structures to one common shared crate (`zellij-utils`), `zellij-tile` will be enabled to import `zellij-utils` like `screen` and `client` already do. This will, next to other things, allow dropping a lot of `std::fmt::Fmt` impls needed to convert core data structures into strings and as a consequence, a lot of string parsing in the first place. * utils: Integrate new `data` module, bump rust ver Integrates the `data` module that was previously part of `zellij-tile` to allow sharing the contained data structures between all components of zellij. This allows `zellij-tile` to use `utils` as a dependency. However, since `tile` is build against the wasm target, it cannot include all of `zellij-utils`, since a lot of dependencies there cannot compile with `wasm` as target (Examples include: termwiz, log4rs, async-std). Thus we make all the dependencies that cannot compile against `wasm` optional and introduce a new feature `full` that will compile the crate with all dependencies. Along with this, modify `lib.rs` to include most of the data structures only when compiling against the `full` feature. This makes the compiles of `zellij-tile` lighter, as it doesn't include all of `utils`. As a side effect, due to the dependency notation for the optional dependencies (See https://doc.rust-lang.org/cargo/reference/features.html#optional-dependencies), we bump the rust toolchain version to 1.60.0. * tile: Import `data` from zellij-utils Add `zellij-utils` as a dependency to `zellij-tile` and allow us access to the `data` module defined there. Update the re-export in the `prelude` such that from all of the plugins points of view *absolutely nothing changes*. * utils: Fix `data` module dependency Since the `data` module has been migrated from `zellij-tile` to `zellij-utils`, we import it from `zellij-utils` directly now. Also unify the imports for the `data` module members: We import all of the through `data::` now, not through a mixture of `data::` and `prelude::`. * client: Fix `data` module dependency Since the `data` module has been migrated from `zellij-tile` to `zellij-utils`, we import it from `zellij-utils` directly now. Also unify the imports for the `data` module members: We import all of the through `data::` now, not through a mixture of `data::` and `prelude::`. Add the "full" feature flag to the `zellij-utils` dependency so it includes all the components we need. * server: Fix `data` module dependency Since the `data` module has been migrated from `zellij-tile` to `zellij-utils`, we import it from `zellij-utils` directly now. Also unify the imports for the `data` module members: We import all of the through `data::` now, not through a mixture of `data::` and `prelude::`. Add the "full" feature flag to the `zellij-utils` dependency so it includes all the components we need. * tests: Fix `data` module dependency Since the `data` module has been migrated from `zellij-tile` to `zellij-utils`, we import it from `zellij-utils` directly now. * utils: Remove "full" feature in favor of conditional compilation using `target_family`. Replace the rust 1.60 method of specifying optional dependencies based on features and optionally include the dependencies only when not building for wasm instead. (I.e. `cfg(not(target_family = "wasm"))`) * cargo: Update module dependencies since `client`, `server` and `tile` now all depend on `utils` only. * docs(changelog): crate refactor * fix: typo (#1567) * feat(terminal): sixel support (#1557) * work * work * work * work * work * more work * work * work * work * hack around stdin repeater * refactor(sixel): rename sixel structs * feat(sixel): render text above images * fix(sixel): reap images once they're past the end of the scrollbuffer * fix(sixel): display images in the middle of the line * fix(sixel): render crash * fix(sixel): react to SIGWINCH * fix(sixel): behave properly in alternate screen mode * fix(sixel): reap images on terminal reset * feat(sixel): handle DECSDM * fix(terminal): properly respond to XTSMGRAPHICS and device attributes with Sixel * Add comment * fix(sixel): hack for unknown event overflow until we fix the api * feat(input): query terminal for all OSC 4 colors and respond to them in a buggy way * fix(sixel): do not render corrupted image * feat(input): improve STDIN queries * fix(client): mistake in clear terminal attributes string * fix(ansi): report correct number of supported color registers * fix(sixel): reap images that are completely covered * style(comment): fix name * test(sixel): infra * test(sixel): cases and fixes * fix(sixel): forward dcs bytes to sixel parser * refactor(client): ansi stdin parser * refactor(output): cleanup * some refactorings * fix test * refactor(grid): sixel-grid / sixel-image-store * refactor(grid): grid debug method * refactor(grid): move various logic to sixel.rs * refactor(grid): remove unused methods * fix(sixel): work with multiple users * refactor(pane): remove unused z_index * style(fmt): prepend unused variable * style(fmt): rustfmt * fix(tests): various apis * chore(dependencies): use published version of sixel crates * style(fmt): rustfmt * style(fmt): rustfmt * style(lint): make clippy happy * style(lint): make clippy happy... again * style(lint): make clippy happy... again (chapter 2) * style(comment): remove unused * fix(colors): export COLORTERM and respond to XTVERSION * fix(test): color register count * fix(stdin): adjust STDIN sleep times * docs(changelog): sixel support * flake.lock: Update (#1575) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * fix(ci): add new rust toolchain location to action (#1576) * rust-toolchain: Update (#1578) Co-authored-by: a-kenji <a-kenji@users.noreply.github.com> * chore(nix): hide `nix` directory (#1579) * chore(gblame): add move to git-blame-ignore-revs This is not relevant for `git blame` messages. * chore(docs): add more matrix links (#1581) * fix: add usage comment to fish shell auto-start snippet (#1574) (#1583) * docs(changelog): add usage comment to fish script * Refactor match session name (#1582) * docs(changelog): refactor get session name (#1582) * fix(cli): let the exit message be different when detaching (#1573) * Let the exit message be different when detaching This patch changes the exit message printed to the user, so the user does not get the impression that they fat-fingered an "exit" instead of what was intended (a detach). For this, the InputHandler::exit() function was refactored, to get the reason as a parameter. As this function is not pub, this is considered okay. Signed-off-by: Matthias Beyer <mail@beyermatthias.de> * Change detach message This patch changes the detach message to be more in line with the other messages zellij displays to the user. Signed-off-by: Matthias Beyer <mail@beyermatthias.de> * docs(changelog): detach message * perf(terminal): better responsiveness (#1585) * performance(pty): only buffer terminal bytes when screen thread is backed up * style(fmt): rustfmt * docs(changelog): performance improvement * style(fmt): rustfmt * fix(search): adjust foreground color for better readability * style(fmt): rustfmt * test(e2e): update snapshots from SCROLL to SEARCH * Rename search directions to up/down * Rename search-functions in tests as well * Move all search-related functions out of grid.rs and into search.rs and reuse as much as possible * Fix bug where searches that fall on the line-ending are highlighting the whole line * Silence clippy on what I think is a false-positive * fix(terminal): persist cursor hide/show through alternate screen (#1586) * fix(terminal): persist cursor hide/show through alternate screen * style(fmt): rustfmt * style(clippy): make clippy happy * docs(changelog): cursor show/hide alternate screen fix * fix(editor): handle editor/visual/configured editor with arguments (#1587) * fix(editor): handle editor/visual/configured editor with arguments * style(fmt): rustfmt * docs(changelog): editor with arguments * fix(ci): quoting issues (#1589) * fix(mouse): avoid forwarding click events on pane border (#1584) * if left click is on pane border do not forward to application * properly handle frames * fix comment * fix another comment * add tests, fix edge case * docs(changelog): mouse click on pane frame fix * flake.lock: Update (#1592) Flake lock file updates: • Updated input 'crate2nix': 'github:kolloch/crate2nix/2d20dec4ae330f39b0bebeb8eb4a201b58d2b82c' (2022-07-09) → 'github:kolloch/crate2nix/45d97c7ce62c3d53954743057ceb32e483c31acd' (2022-07-12) • Updated input 'nixpkgs': 'github:nixos/nixpkgs/b39924fc7764c08ae3b51beef9a3518c414cdb7d' (2022-07-08) → 'github:nixos/nixpkgs/4a01ca36d6bfc133bc617e661916a81327c9bbc8' (2022-07-14) • Updated input 'rust-overlay': 'github:oxalica/rust-overlay/3dfc78e42a285caaf83633224a42e7fb7dde191b' (2022-07-10) → 'github:oxalica/rust-overlay/2cd36d4aef875867ee1d7963541ccb3ae50b358c' (2022-07-16) Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * fix(search): clear search when entering input in non-search-mode * fix(search): handle searching in updating viewport Co-authored-by: Martin Sirringhaus <> Co-authored-by: a-kenji <aks.kenji@protonmail.com> Co-authored-by: Thomas Linford <tlinford@users.noreply.github.com> Co-authored-by: Aram Drevekenin <aram@poor.dev> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: a-kenji <a-kenji@users.noreply.github.com> Co-authored-by: Tassilo Horn <tsdh@gnu.org> Co-authored-by: Jae-Heon Ji <32578710+jaeheonji@users.noreply.github.com> Co-authored-by: Matthias Beyer <mail@beyermatthias.de>
Diffstat (limited to 'zellij-utils')
-rw-r--r--zellij-utils/assets/config/default.yaml84
-rw-r--r--zellij-utils/src/data.rs8
-rw-r--r--zellij-utils/src/errors.rs6
-rw-r--r--zellij-utils/src/input/actions.rs19
-rw-r--r--zellij-utils/src/input/keybinds.rs1
-rw-r--r--zellij-utils/src/input/mod.rs12
6 files changed, 130 insertions, 0 deletions
diff --git a/zellij-utils/assets/config/default.yaml b/zellij-utils/assets/config/default.yaml
index caff98a7e..2aecc6d83 100644
--- a/zellij-utils/assets/config/default.yaml
+++ b/zellij-utils/assets/config/default.yaml
@@ -324,6 +324,90 @@ keybinds:
# uncomment this and adjust key if using copy_on_select=false
# - action: [Copy: ]
# key: [ Alt: 'c']
+ - action: [SwitchToMode: EnterSearch, SearchInput: [0],]
+ key: [Char: 's']
+ entersearch:
+ - action: [SwitchToMode: Search,]
+ key: [Char: "\n"]
+ - action: [SearchInput: [27], SwitchToMode: Scroll,]
+ key: [Ctrl: 'c', Esc]
+ - action: [NewPane: ,]
+ key: [ Alt: 'n',]
+ - action: [MoveFocusOrTab: Left,]
+ key: [ Alt: 'h', Alt: Left]
+ - action: [MoveFocusOrTab: Right,]
+ key: [ Alt: 'l', Alt: Right]
+ - action: [MoveFocus: Down,]
+ key: [ Alt: 'j', Alt: Down]
+ - action: [MoveFocus: Up,]
+ key: [ Alt: 'k', Alt: Up]
+ - action: [Resize: Increase,]
+ key: [ Alt: '=']
+ - action: [Resize: Increase,]
+ key: [ Alt: '+']
+ - action: [Resize: Decrease,]
+ key: [ Alt: '-']
+ search:
+ - action: [SwitchToMode: Normal,]
+ key: [Ctrl: 's', Char: ' ', Char: "\n", Esc]
+ - action: [SwitchToMode: Tab,]
+ key: [Ctrl: 't',]
+ - action: [SwitchToMode: Locked,]
+ key: [Ctrl: 'g',]
+ - action: [SwitchToMode: Pane,]
+ key: [Ctrl: 'p',]
+ - action: [SwitchToMode: Move,]
+ key: [Ctrl: 'h',]
+ - action: [SwitchToMode: Tmux,]
+ key: [Ctrl: 'b',]
+ - action: [SwitchToMode: Session,]
+ key: [Ctrl: 'o',]
+ - action: [SwitchToMode: Resize,]
+ key: [Ctrl: 'n',]
+ - action: [ScrollToBottom, SwitchToMode: Normal,]
+ key: [Ctrl: 'c',]
+ - action: [Quit,]
+ key: [Ctrl: 'q',]
+ - action: [ScrollDown,]
+ key: [Char: 'j', Down,]
+ - action: [ScrollUp,]
+ key: [Char: 'k', Up,]
+ - action: [PageScrollDown,]
+ key: [Ctrl: 'f', PageDown, Right, Char: 'l',]
+ - action: [PageScrollUp,]
+ key: [Ctrl: 'b', PageUp, Left, Char: 'h',]
+ - action: [HalfPageScrollDown,]
+ key: [Char: 'd',]
+ - action: [HalfPageScrollUp,]
+ key: [Char: 'u',]
+ - action: [NewPane: ,]
+ key: [ Alt: 'n',]
+ - action: [MoveFocusOrTab: Left,]
+ key: [ Alt: 'h', Alt: Left] # The Alt: Left etc. variants are temporary hacks and will be removed in the future - please do not rely on them!
+ - action: [MoveFocusOrTab: Right,]
+ key: [ Alt: 'l', Alt: Right]
+ - action: [MoveFocus: Down,]
+ key: [ Alt: 'j', Alt: Down]
+ - action: [MoveFocus: Up,]
+ key: [ Alt: 'k', Alt: Up]
+ - action: [Resize: Increase,]
+ key: [ Alt: '=']
+ - action: [Resize: Increase,]
+ key: [ Alt: '+']
+ - action: [Resize: Decrease,]
+ key: [ Alt: '-']
+ - action: [SwitchToMode: EnterSearch, SearchInput: [0],]
+ key: [Char: 's']
+ - action: [Search: Down]
+ key: [Char: 'n']
+ - action: [Search: Up]
+ key: [Char: 'p']
+ - action: [SearchToggleOption: CaseSensitivity]
+ key: [Char: 'c']
+ - action: [SearchToggleOption: Wrap]
+ key: [Char: 'w']
+ - action: [SearchToggleOption: WholeWord]
+ key: [Char: 'o']
renametab:
- action: [SwitchToMode: Normal,]
key: [Char: "\n", Ctrl: 'c', Esc]
diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs
index c50ef4790..82ed5da9e 100644
--- a/zellij-utils/src/data.rs
+++ b/zellij-utils/src/data.rs
@@ -120,6 +120,12 @@ pub enum InputMode {
/// `Scroll` mode allows scrolling up and down within a pane.
#[serde(alias = "scroll")]
Scroll,
+ /// `EnterSearch` mode allows for typing in the needle for a search in the scroll buffer of a pane.
+ #[serde(alias = "entersearch")]
+ EnterSearch,
+ /// `Search` mode allows for searching a term in a pane (superset of `Scroll`).
+ #[serde(alias = "search")]
+ Search,
/// `RenameTab` mode allows assigning a new name to a tab.
#[serde(alias = "renametab")]
RenameTab,
@@ -179,6 +185,8 @@ impl FromStr for InputMode {
"pane" => Ok(InputMode::Pane),
"tab" => Ok(InputMode::Tab),
"scroll" => Ok(InputMode::Scroll),
+ "search" => Ok(InputMode::Search),
+ "entersearch" => Ok(InputMode::EnterSearch),
"renametab" => Ok(InputMode::RenameTab),
"session" => Ok(InputMode::Session),
"move" => Ok(InputMode::Move),
diff --git a/zellij-utils/src/errors.rs b/zellij-utils/src/errors.rs
index d7a4ba8ae..0e18bb9e5 100644
--- a/zellij-utils/src/errors.rs
+++ b/zellij-utils/src/errors.rs
@@ -291,6 +291,12 @@ pub enum ScreenContext {
RemoveOverlay,
ConfirmPrompt,
DenyPrompt,
+ UpdateSearch,
+ SearchDown,
+ SearchUp,
+ SearchToggleCaseSensitivity,
+ SearchToggleWholeWord,
+ SearchToggleWrap,
}
/// Stack call representations corresponding to the different types of [`PtyInstruction`]s.
diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs
index 0550792df..17778c4e9 100644
--- a/zellij-utils/src/input/actions.rs
+++ b/zellij-utils/src/input/actions.rs
@@ -27,6 +27,19 @@ pub enum ResizeDirection {
Decrease,
}
+#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
+pub enum SearchDirection {
+ Down,
+ Up,
+}
+
+#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
+pub enum SearchOption {
+ CaseSensitivity,
+ WholeWord,
+ Wrap,
+}
+
// As these actions are bound to the default config, please
// do take care when refactoring - or renaming.
// They might need to be adjusted in the default config
@@ -121,6 +134,12 @@ pub enum Action {
Deny,
/// Confirm an action that invokes a prompt automatically
SkipConfirm(Box<Action>),
+ /// Search for String
+ SearchInput(Vec<u8>),
+ /// Search for something
+ Search(SearchDirection),
+ /// Toggle case sensitivity of search
+ SearchToggleOption(SearchOption),
}
impl From<OnForceClose> for Action {
diff --git a/zellij-utils/src/input/keybinds.rs b/zellij-utils/src/input/keybinds.rs
index af5616969..9f948f898 100644
--- a/zellij-utils/src/input/keybinds.rs
+++ b/zellij-utils/src/input/keybinds.rs
@@ -213,6 +213,7 @@ impl Keybinds {
},
InputMode::RenameTab => mode_keybind_or_action(Action::TabNameInput(raw_bytes)),
InputMode::RenamePane => mode_keybind_or_action(Action::PaneNameInput(raw_bytes)),
+ InputMode::EnterSearch => mode_keybind_or_action(Action::SearchInput(raw_bytes)),
_ => mode_keybind_or_action(Action::NoOp),
}
}
diff --git a/zellij-utils/src/input/mod.rs b/zellij-utils/src/input/mod.rs
index 84ae1e366..268a4e2c8 100644
--- a/zellij-utils/src/input/mod.rs
+++ b/zellij-utils/src/input/mod.rs
@@ -59,6 +59,18 @@ pub fn get_mode_info(mode: InputMode, style: Style, capabilities: PluginCapabili
"e".to_string(),
"Edit Scrollback in Default Editor".to_string(),
),
+ ("s".to_string(), "Enter search term".to_string()),
+ ],
+ InputMode::EnterSearch => vec![("Enter".to_string(), "when done".to_string())],
+ InputMode::Search => vec![
+ ("↓↑".to_string(), "Scroll".to_string()),
+ ("PgUp/PgDn".to_string(), "Scroll Page".to_string()),
+ ("u/d".to_string(), "Scroll Half Page".to_string()),
+ ("n".to_string(), "Search down".to_string()),
+ ("p".to_string(), "Search up".to_string()),
+ ("c".to_string(), "Case sensitivity".to_string()),
+ ("w".to_string(), "Wrap".to_string()),
+ ("o".to_string(), "Whole words".to_string()),
],
InputMode::RenameTab => vec![("Enter".to_string(), "when done".to_string())],
InputMode::RenamePane => vec![("Enter".to_string(), "when done".to_string())],