aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crates/atuin-client/src/database.rs13
-rw-r--r--crates/atuin/src/command/client/search/engines.rs4
-rw-r--r--crates/atuin/src/command/client/search/interactive.rs93
-rw-r--r--crates/atuin/src/command/client/search/keybindings/actions.rs6
-rw-r--r--crates/atuin/src/command/client/search/keybindings/conditions.rs15
-rw-r--r--crates/atuin/src/command/client/search/keybindings/defaults.rs10
-rw-r--r--crates/atuin/src/command/client/search/keybindings/keymap.rs1
-rw-r--r--docs/docs/configuration/advanced-key-binding.md3
-rw-r--r--docs/docs/configuration/config.md15
-rw-r--r--docs/docs/configuration/key-binding.md21
-rw-r--r--docs/docs/guide/advanced-usage.md49
-rw-r--r--docs/docs/guide/basic-usage.md2
-rw-r--r--docs/mkdocs.yml1
13 files changed, 206 insertions, 27 deletions
diff --git a/crates/atuin-client/src/database.rs b/crates/atuin-client/src/database.rs
index 28d6c0f0..7aa095f7 100644
--- a/crates/atuin-client/src/database.rs
+++ b/crates/atuin-client/src/database.rs
@@ -32,6 +32,7 @@ use super::{
settings::{FilterMode, SearchMode, Settings},
};
+#[derive(Clone)]
pub struct Context {
pub session: String,
pub cwd: String,
@@ -72,6 +73,18 @@ pub async fn current_context() -> eyre::Result<Context> {
})
}
+impl Context {
+ pub fn from_history(entry: &History) -> Self {
+ Context {
+ session: entry.session.to_string(),
+ cwd: entry.cwd.to_string(),
+ hostname: entry.hostname.to_string(),
+ host_id: String::new(),
+ git_root: utils::in_git_repo(entry.cwd.as_str()),
+ }
+ }
+}
+
fn get_session_start_time(session_id: &str) -> Option<i64> {
if let Ok(uuid) = Uuid::parse_str(session_id)
&& let Some(timestamp) = uuid.get_timestamp()
diff --git a/crates/atuin/src/command/client/search/engines.rs b/crates/atuin/src/command/client/search/engines.rs
index 95d6658b..5c53817e 100644
--- a/crates/atuin/src/command/client/search/engines.rs
+++ b/crates/atuin/src/command/client/search/engines.rs
@@ -1,7 +1,7 @@
use async_trait::async_trait;
use atuin_client::{
database::{Context, Database},
- history::History,
+ history::{History, HistoryId},
settings::{FilterMode, SearchMode, Settings},
};
use eyre::Result;
@@ -22,6 +22,7 @@ pub struct SearchState {
pub input: Cursor,
pub filter_mode: FilterMode,
pub context: Context,
+ pub custom_context: Option<HistoryId>,
}
impl SearchState {
@@ -44,6 +45,7 @@ impl SearchState {
fn filter_mode_available(&self, mode: FilterMode, settings: &Settings) -> bool {
match mode {
+ FilterMode::Global | FilterMode::SessionPreload => self.custom_context.is_none(),
FilterMode::Workspace => settings.workspaces && self.context.git_root.is_some(),
_ => true,
}
diff --git a/crates/atuin/src/command/client/search/interactive.rs b/crates/atuin/src/command/client/search/interactive.rs
index b5186706..c6a6064a 100644
--- a/crates/atuin/src/command/client/search/interactive.rs
+++ b/crates/atuin/src/command/client/search/interactive.rs
@@ -16,10 +16,11 @@ use super::{
history_list::{HistoryList, ListState},
};
use atuin_client::{
- database::{Database, current_context},
+ database::{Context, Database, current_context},
history::{History, HistoryId, HistoryStats, store::HistoryStore},
settings::{
- CursorStyle, ExitMode, KeymapMode, PreviewStrategy, SearchMode, Settings, UiColumn,
+ CursorStyle, ExitMode, FilterMode, KeymapMode, PreviewStrategy, SearchMode, Settings,
+ UiColumn,
},
};
@@ -59,6 +60,7 @@ pub enum InputAction {
ReturnQuery,
Continue,
Redraw,
+ SwitchContext(Option<usize>),
}
#[derive(Clone)]
@@ -304,6 +306,7 @@ impl State {
selected_index: self.results_state.selected(),
results_len: self.results_len,
original_input_empty: self.original_input_empty,
+ has_context: self.search.custom_context.is_some(),
};
// Convert KeyEvent to SingleKey
@@ -657,6 +660,10 @@ impl State {
self.engine = engines::engine(self.search_mode);
InputAction::Continue
}
+ Action::SwitchContext => {
+ InputAction::SwitchContext(Some(self.results_state.selected()))
+ }
+ Action::ClearContext => InputAction::SwitchContext(None),
Action::ToggleTab => {
self.tab_index = (self.tab_index + 1) % TAB_TITLES.len();
InputAction::Continue
@@ -916,6 +923,11 @@ impl State {
Compactness::Ultracompact => {
if self.switched_search_mode {
format!("S{}>", self.search_mode.as_str().chars().next().unwrap())
+ } else if self.search.custom_context.is_some() {
+ format!(
+ "C{}>",
+ self.search.filter_mode.as_str().chars().next().unwrap()
+ )
} else {
format!(
"{}> ",
@@ -1166,6 +1178,8 @@ impl State {
fn build_input(&self, style: StyleState, prefix_width: u16) -> Paragraph<'_> {
let (pref, mode) = if self.switched_search_mode {
(" SRCH:", self.search_mode.as_str())
+ } else if self.search.custom_context.is_some() {
+ (" CTX:", self.search.filter_mode.as_str())
} else {
("", self.search.filter_mode.as_str())
};
@@ -1372,7 +1386,7 @@ pub async fn history(
let update_needed = tokio::spawn(async move { settings2.needs_update().await }).fuse();
tokio::pin!(update_needed);
- let context = current_context().await?;
+ let initial_context = current_context().await?;
let history_count = db.history_count(false).await?;
let search_mode = if settings.shell_up_key_binding {
@@ -1382,6 +1396,10 @@ pub async fn history(
} else {
settings.search_mode
};
+ let default_filter_mode = settings
+ .filter_mode_shell_up_key_binding
+ .filter(|_| settings.shell_up_key_binding)
+ .unwrap_or_else(|| settings.default_filter_mode(initial_context.git_root.is_some()));
let mut app = State {
history_count,
results_state: ListState::default(),
@@ -1397,11 +1415,9 @@ pub async fn history(
keymaps: KeymapSet::from_settings(settings),
search: SearchState {
input,
- filter_mode: settings
- .filter_mode_shell_up_key_binding
- .filter(|_| settings.shell_up_key_binding)
- .unwrap_or_else(|| settings.default_filter_mode(context.git_root.is_some())),
- context,
+ filter_mode: default_filter_mode,
+ context: initial_context.clone(),
+ custom_context: None,
},
engine: engines::engine(search_mode),
results_len: 0,
@@ -1448,6 +1464,7 @@ pub async fn history(
let initial_input = app.search.input.as_str().to_owned();
let initial_filter_mode = app.search.filter_mode;
let initial_search_mode = app.search_mode;
+ let initial_custom_context = app.search.custom_context.clone();
let event_ready = tokio::task::spawn_blocking(|| event::poll(Duration::from_millis(250)));
@@ -1479,6 +1496,19 @@ pub async fn history(
app.tab_index = 0;
},
+ InputAction::SwitchContext(index) => {
+ if let Some(index) = index && let Some(entry) = results.get(index) {
+ app.search.custom_context = Some(entry.id.clone());
+ app.search.context = Context::from_history(entry);
+ app.search.filter_mode = FilterMode::Session;
+ app.search.input = Cursor::from(String::new());
+ app.results_state = ListState::default();
+ } else {
+ app.search.custom_context = None;
+ app.search.context = initial_context.clone();
+ app.search.filter_mode = default_filter_mode;
+ }
+ },
InputAction::Redraw => {
terminal.clear()?;
terminal.draw(|f| app.draw(f, &results, stats.clone(), inspecting.as_ref(), settings, theme))?;
@@ -1504,10 +1534,23 @@ pub async fn history(
if initial_input != app.search.input.as_str()
|| initial_filter_mode != app.search.filter_mode
|| initial_search_mode != app.search_mode
+ || initial_custom_context != app.search.custom_context
{
results = app.query_results(&mut db, settings.smart_sort).await?;
}
+ // In custom context mode, when no filter is applied, highlight the entry which was used
+ // to enter the context when changing modes. This helps to find your way around.
+ if app.search.custom_context.is_some()
+ && app.search.input.as_str().is_empty()
+ && (initial_custom_context != app.search.custom_context
+ || initial_filter_mode != app.search.filter_mode)
+ && let Some(history_id) = app.search.custom_context.clone()
+ && let Some(pos) = results.iter().position(|entry| entry.id == history_id)
+ {
+ app.results_state.select(pos);
+ }
+
let inspecting_id = app.inspecting_state.clone().current;
// If inspecting ID is not the current inspecting History, update it.
match inspecting_id {
@@ -1600,7 +1643,10 @@ pub async fn history(
// * out of bounds -> usually implies no selected entry so we return the input
Ok(app.search.input.into_inner())
}
- InputAction::Continue | InputAction::Redraw | InputAction::Delete(_) => {
+ InputAction::Continue
+ | InputAction::Redraw
+ | InputAction::Delete(_)
+ | InputAction::SwitchContext(_) => {
unreachable!("should have been handled!")
}
}
@@ -1827,6 +1873,7 @@ mod tests {
host_id: String::new(),
git_root: None,
},
+ custom_context: None,
},
engine: engines::engine(SearchMode::Fuzzy),
now: Box::new(OffsetDateTime::now_utc),
@@ -1881,6 +1928,7 @@ mod tests {
host_id: String::new(),
git_root: None,
},
+ custom_context: None,
},
engine: engines::engine(SearchMode::Fuzzy),
now: Box::new(OffsetDateTime::now_utc),
@@ -1999,6 +2047,7 @@ mod tests {
host_id: String::new(),
git_root: None,
},
+ custom_context: None,
},
engine: engines::engine(SearchMode::Fuzzy),
now: Box::new(OffsetDateTime::now_utc),
@@ -2057,6 +2106,7 @@ mod tests {
host_id: String::new(),
git_root: None,
},
+ custom_context: None,
},
engine: engines::engine(SearchMode::Fuzzy),
now: Box::new(OffsetDateTime::now_utc),
@@ -2111,6 +2161,7 @@ mod tests {
host_id: String::new(),
git_root: None,
},
+ custom_context: None,
},
engine: engines::engine(SearchMode::Fuzzy),
now: Box::new(OffsetDateTime::now_utc),
@@ -2161,6 +2212,7 @@ mod tests {
host_id: String::new(),
git_root: None,
},
+ custom_context: None,
},
engine: engines::engine(SearchMode::Fuzzy),
now: Box::new(OffsetDateTime::now_utc),
@@ -2220,6 +2272,7 @@ mod tests {
host_id: String::new(),
git_root: None,
},
+ custom_context: None,
},
engine: engines::engine(SearchMode::Fuzzy),
now: Box::new(OffsetDateTime::now_utc),
@@ -2280,6 +2333,7 @@ mod tests {
host_id: String::new(),
git_root: None,
},
+ custom_context: None,
},
engine: engines::engine(SearchMode::Fuzzy),
now: Box::new(OffsetDateTime::now_utc),
@@ -2490,6 +2544,26 @@ mod tests {
}
#[test]
+ fn execute_switch_context() {
+ use crate::command::client::search::keybindings::Action;
+
+ let mut state = make_executor_state(100, 7);
+ let settings = Settings::utc();
+ let result = state.execute_action(&Action::SwitchContext, &settings);
+ assert!(matches!(result, super::InputAction::SwitchContext(Some(7))));
+ }
+
+ #[test]
+ fn execute_clear_context() {
+ use crate::command::client::search::keybindings::Action;
+
+ let mut state = make_executor_state(100, 7);
+ let settings = Settings::utc();
+ let result = state.execute_action(&Action::ClearContext, &settings);
+ assert!(matches!(result, super::InputAction::SwitchContext(None)));
+ }
+
+ #[test]
fn execute_noop() {
use crate::command::client::search::keybindings::Action;
@@ -2638,6 +2712,7 @@ mod tests {
host_id: String::new(),
git_root: None,
},
+ custom_context: None,
},
engine: engines::engine(SearchMode::Fuzzy),
now: Box::new(OffsetDateTime::now_utc),
diff --git a/crates/atuin/src/command/client/search/keybindings/actions.rs b/crates/atuin/src/command/client/search/keybindings/actions.rs
index fae811d6..66e2709e 100644
--- a/crates/atuin/src/command/client/search/keybindings/actions.rs
+++ b/crates/atuin/src/command/client/search/keybindings/actions.rs
@@ -52,6 +52,8 @@ pub enum Action {
Redraw,
CycleFilterMode,
CycleSearchMode,
+ SwitchContext,
+ ClearContext,
ToggleTab,
// Mode changes
@@ -129,6 +131,8 @@ impl Action {
"redraw" => Ok(Action::Redraw),
"cycle-filter-mode" => Ok(Action::CycleFilterMode),
"cycle-search-mode" => Ok(Action::CycleSearchMode),
+ "switch-context" => Ok(Action::SwitchContext),
+ "clear-context" => Ok(Action::ClearContext),
"toggle-tab" => Ok(Action::ToggleTab),
"vim-enter-normal" => Ok(Action::VimEnterNormal),
@@ -193,6 +197,8 @@ impl Action {
Action::Redraw => "redraw".to_string(),
Action::CycleFilterMode => "cycle-filter-mode".to_string(),
Action::CycleSearchMode => "cycle-search-mode".to_string(),
+ Action::SwitchContext => "switch-context".to_string(),
+ Action::ClearContext => "clear-context".to_string(),
Action::ToggleTab => "toggle-tab".to_string(),
Action::VimEnterNormal => "vim-enter-normal".to_string(),
diff --git a/crates/atuin/src/command/client/search/keybindings/conditions.rs b/crates/atuin/src/command/client/search/keybindings/conditions.rs
index bc485713..d460d7d4 100644
--- a/crates/atuin/src/command/client/search/keybindings/conditions.rs
+++ b/crates/atuin/src/command/client/search/keybindings/conditions.rs
@@ -13,6 +13,7 @@ pub enum ConditionAtom {
ListAtStart,
NoResults,
HasResults,
+ HasContext,
}
/// Boolean expression tree over condition atoms.
@@ -49,6 +50,8 @@ pub struct EvalContext {
pub results_len: usize,
/// Whether the original input (query passed to the TUI) was empty.
pub original_input_empty: bool,
+ /// Whether we use a search context of a command from the history.
+ pub has_context: bool,
}
// ---------------------------------------------------------------------------
@@ -69,6 +72,7 @@ impl ConditionAtom {
ConditionAtom::ListAtStart => ctx.results_len == 0 || ctx.selected_index == 0,
ConditionAtom::NoResults => ctx.results_len == 0,
ConditionAtom::HasResults => ctx.results_len > 0,
+ ConditionAtom::HasContext => ctx.has_context,
}
}
@@ -83,6 +87,7 @@ impl ConditionAtom {
"list-at-start" => Ok(ConditionAtom::ListAtStart),
"no-results" => Ok(ConditionAtom::NoResults),
"has-results" => Ok(ConditionAtom::HasResults),
+ "has-context" => Ok(ConditionAtom::HasContext),
_ => Err(format!("unknown condition: {s}")),
}
}
@@ -98,6 +103,7 @@ impl ConditionAtom {
ConditionAtom::ListAtStart => "list-at-start",
ConditionAtom::NoResults => "no-results",
ConditionAtom::HasResults => "has-results",
+ ConditionAtom::HasContext => "has-context",
}
}
}
@@ -394,6 +400,7 @@ mod tests {
selected_index: selected,
results_len: len,
original_input_empty,
+ has_context: false,
}
}
@@ -457,6 +464,14 @@ mod tests {
}
#[test]
+ fn atom_has_context() {
+ let mut context = ctx(0, 0, 0, 0, 0);
+ assert!(!ConditionAtom::HasContext.evaluate(&context));
+ context.has_context = true;
+ assert!(ConditionAtom::HasContext.evaluate(&context));
+ }
+
+ #[test]
fn atom_parse_round_trip() {
let conditions = [
"cursor-at-start",
diff --git a/crates/atuin/src/command/client/search/keybindings/defaults.rs b/crates/atuin/src/command/client/search/keybindings/defaults.rs
index 64dca691..f19bf377 100644
--- a/crates/atuin/src/command/client/search/keybindings/defaults.rs
+++ b/crates/atuin/src/command/client/search/keybindings/defaults.rs
@@ -405,6 +405,13 @@ pub fn default_prefix_keymap() -> Keymap {
km.bind(key("d"), Action::Delete);
km.bind(key("a"), Action::CursorStart);
+ km.bind_conditional(
+ key("c"),
+ vec![
+ KeyRule::when(ConditionAtom::HasContext, Action::ClearContext),
+ KeyRule::always(Action::SwitchContext),
+ ],
+ );
km
}
@@ -530,6 +537,7 @@ mod tests {
selected_index: selected,
results_len: len,
original_input_empty: false,
+ has_context: false,
}
}
@@ -1250,6 +1258,7 @@ mod tests {
selected_index: 0,
results_len: 10,
original_input_empty: true,
+ has_context: false,
};
assert_eq!(
set.emacs.resolve(&key("esc"), &ctx_original_empty),
@@ -1265,6 +1274,7 @@ mod tests {
selected_index: 0,
results_len: 10,
original_input_empty: false,
+ has_context: false,
};
assert_eq!(
set.emacs.resolve(&key("esc"), &ctx_original_not_empty),
diff --git a/crates/atuin/src/command/client/search/keybindings/keymap.rs b/crates/atuin/src/command/client/search/keybindings/keymap.rs
index bbf034b2..8c7fcfa8 100644
--- a/crates/atuin/src/command/client/search/keybindings/keymap.rs
+++ b/crates/atuin/src/command/client/search/keybindings/keymap.rs
@@ -127,6 +127,7 @@ mod tests {
selected_index: selected,
results_len: len,
original_input_empty: false,
+ has_context: false,
}
}
diff --git a/docs/docs/configuration/advanced-key-binding.md b/docs/docs/configuration/advanced-key-binding.md
index 1fe9c1e4..7f73b5d6 100644
--- a/docs/docs/configuration/advanced-key-binding.md
+++ b/docs/docs/configuration/advanced-key-binding.md
@@ -206,6 +206,8 @@ Note: `select-next` and `select-previous` respect the `invert` setting. When `in
| `cycle-filter-mode` | Cycle through filter modes (global, host, session, directory) |
| `cycle-search-mode` | Cycle through search modes (fuzzy, prefix, fulltext, skim) |
| `toggle-tab` | Toggle between the search tab and inspector tab |
+| `switch-context` | Switch to the [context](../guide/advanced-usage.md#context-switch) of the currently selected command |
+| `clear-context` | Return to the initial [context](../guide/advanced-usage.md#context-switch) |
The difference between `accept` and `return-selection`: `accept` runs the command immediately when the TUI closes, while `return-selection` places it on your command line for further editing before you press enter. The `enter_accept` setting controls which of these the default `enter` key uses.
@@ -251,6 +253,7 @@ Conditions let a single key do different things depending on the current state.
| `list-at-end` | The selection is at the last entry |
| `no-results` | The search returned zero results |
| `has-results` | The search returned at least one result |
+| `has-context` | The context comes from a previously selected command (`switch-context`) |
### Boolean expressions
diff --git a/docs/docs/configuration/config.md b/docs/docs/configuration/config.md
index 49e29a79..31980ed1 100644
--- a/docs/docs/configuration/config.md
+++ b/docs/docs/configuration/config.md
@@ -139,13 +139,14 @@ Default: `global`
The default filter to use when searching
-| Mode | Description |
-| ---------------- | ------------------------------------------------------------ |
-| global (default) | Search history from all hosts, all sessions, all directories |
-| host | Search history just from this host |
-| session | Search history just from the current session |
-| directory | Search history just from the current directory (global) |
-| workspace | Search history just from the current git repository (>17.0) |
+| Mode | Description |
+|------------------|--------------------------------------------------------------------------------------|
+| global (default) | Search from the full history |
+| host | Search history from this host |
+| session | Search history from the current session |
+| directory | Search history from the current directory |
+| workspace | Search history from the current git repository |
+| session-preload | Search from the current session and the global history from before the session start |
Filter modes can still be toggled via ctrl-r
diff --git a/docs/docs/configuration/key-binding.md b/docs/docs/configuration/key-binding.md
index f292999f..942a2400 100644
--- a/docs/docs/configuration/key-binding.md
+++ b/docs/docs/configuration/key-binding.md
@@ -202,31 +202,32 @@ $env.config = (
## Atuin UI shortcuts
| Shortcut | Action |
-| ----------------------------------------- | ----------------------------------------------------------------------------- |
-| enter | Execute selected item |
+|-------------------------------------------|-------------------------------------------------------------------------------|
+| enter | Execute selected item |
| tab | Select item and edit |
| ctrl + r | Cycle through filter modes |
| ctrl + s | Cycle through search modes |
| alt + 1 to alt + 9 | Select item by the number located near it |
| ctrl + c / ctrl + d / ctrl + g / esc | Return original |
| ctrl + y | Copy selected item to clipboard |
-| ctrl + ← / alt + b | Move the cursor to the previous word |
-| ctrl + → / alt + f | Move the cursor to the next word |
-| ctrl + b / ← | Move the cursor to the left |
-| ctrl + f / → | Move the cursor to the right |
+| ctrl + ← / alt + b | Move the cursor to the previous word |
+| ctrl + → / alt + f | Move the cursor to the next word |
+| ctrl + b / ← | Move the cursor to the left |
+| ctrl + f / → | Move the cursor to the right |
| ctrl + a / home | Move the cursor to the start of the line |
| ctrl + e / end | Move the cursor to the end of the line |
| ctrl + backspace / ctrl + alt + backspace | Remove the previous word / remove the word just before the cursor |
| ctrl + delete / ctrl + alt + delete | Remove the next word or the word just after the cursor |
| ctrl + w | Remove the word before the cursor even if it spans across the word boundaries |
| ctrl + u | Clear the current line |
-| ctrl + n / ctrl + j / ↑ | Select the next item on the list |
-| ctrl + p / ctrl + k / ↓ | Select the previous item on the list |
+| ctrl + n / ctrl + j / ↑ | Select the next item on the list |
+| ctrl + p / ctrl + k / ↓ | Select the previous item on the list |
| ctrl + o | Open the [inspector](#inspector) |
| page down | Scroll search results one page down |
| page up | Scroll search results one page up |
-| ↓ (with no entry selected) | Return original or return query depending on [settings](config.md#exit_mode) |
-| ↓ | Select the next item on the list |
+| ↓ (with no entry selected) | Return original or return query depending on [settings](config.md#exit_mode) |
+| ↓ | Select the next item on the list |
+| ctrl + a, c | Switch to the context of the currently selected command / return to default |
### Vim mode
diff --git a/docs/docs/guide/advanced-usage.md b/docs/docs/guide/advanced-usage.md
new file mode 100644
index 00000000..0d5a1359
--- /dev/null
+++ b/docs/docs/guide/advanced-usage.md
@@ -0,0 +1,49 @@
+# Advanced Usage
+
+Atuin offers you several options to help navigate through the results.
+
+## Filter mode
+
+The command history can be filtered in different ways, letting you narrow the search scope.
+
+You can cycle through the different modes by pressing **ctrl-r**.
+
+The available modes are:
+
+| Mode | Description |
+|------------------|--------------------------------------------------------------------------------------|
+| global (default) | Search from the full history |
+| host | Search history from this host |
+| session | Search history from the current session |
+| directory | Search history from the current directory |
+| workspace | Search history from the current git repository |
+| session-preload | Search from the current session and the global history from before the session start |
+
+See the [`filter_mode` config reference](../configuration/config.md#filter_mode) for more details.
+
+## Search mode
+
+Atuin offers different modes to interpret your search query.
+
+You can cycle through the different modes by pressing **ctrl-s**.
+
+The available modes are:
+
+| Mode | Description |
+|-----------------|----------------------------------------------------------------------------------------------------------------|
+| fuzzy (default) | Search for commands in a fuzzy way, similar to the [fzf syntax](https://github.com/junegunn/fzf#search-syntax) |
+| prefix | Commands that start with your query |
+| fulltext | Commands that contain your query as a substring |
+| skim | Search for commands using the [skim syntax](https://github.com/lotabout/skim#search-syntax) |
+
+See the [`search_mode` config reference](../configuration/config.md#search_mode) for more details.
+
+## Context switch
+
+Atuin uses the current context (host, session, directory) to filter the history when you use a filter mode other than *global*.
+
+You can switch this context to the one of the currently selected command by pressing **ctrl-a** then **c**.
+
+This will set the filter mode to *session* and clear the search query, which will show you all the commands executed in the same shell session.
+
+Pressing this key combination again will return to the initial context. You can customize this behavior by setting [custom key bindings](../configuration/advanced-key-binding.md) to the `switch-context` and `clear-context` commands. `switch-context` can be called several times to navigate through multiple command contexts, while `clear-context` will always return to the initial context.
diff --git a/docs/docs/guide/basic-usage.md b/docs/docs/guide/basic-usage.md
index 0b40a0aa..f6df1c94 100644
--- a/docs/docs/guide/basic-usage.md
+++ b/docs/docs/guide/basic-usage.md
@@ -26,6 +26,8 @@ While searching in the TUI, you can adjust the "filter mode" by repeatedly press
3. The current directory only
4. The current shell session only
+See the [advanced usage](advanced-usage.md) page for more options.
+
## Common config adjustment
For a full set of config values, please see the [config reference page](../configuration/config.md).
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
index 1cbbf30d..4ca51c60 100644
--- a/docs/mkdocs.yml
+++ b/docs/mkdocs.yml
@@ -63,6 +63,7 @@ nav:
- Setting up sync: guide/sync.md
- Import existing history: guide/import.md
- Basic usage: guide/basic-usage.md
+ - Advanced usage: guide/advanced-usage.md
- Deleting history: guide/delete-history.md
- Syncing dotfiles: guide/dotfiles.md
- Theming: guide/theming.md