bmrk 0.4.0

A fast TUI for directory navigation and bookmark management
# Key Bindings

Complete reference of all keyboard shortcuts in bmrk.

## Tree Navigation Mode

Default mode when bmrk launches.

### Movement

| Key        | Action             |
|------------|--------------------|
| `j` or `↓` | Move down one item |
| `k` or `↑` | Move up one item   |

### Directory Operations

| Key         | Action                                                                   |
|-------------|--------------------------------------------------------------------------|
| `l` or `→`  | Expand directory (show subdirectories)                                   |
| `h` or `←`  | Collapse expanded directory; if already collapsed, move to parent. On the root row itself, always goes straight to the parent directory in one press (there's nothing above the root to reveal by collapsing) |
| `Enter`     | Change root to selected directory                                        |
| `u`         | Go to parent directory (change root) — configurable: `go_to_parent`     |
| `Backspace` | Go back (undo last navigation) — configurable: `go_back`                |

### Other Actions

| Key   | Action                              |
|-------|-------------------------------------|
| `/`   | Enter search mode — configurable: `search`  |
| `Tab` | Enter quick jump mode (see [Quick Jump Mode](#quick-jump-mode)) |
| `m`   | Create bookmark — configurable: `create_bookmark` |
| `'`   | Open bookmark selection — configurable: `select_bookmark` |
| `d`   | Open disk/drive selection — configurable: `select_disk` |
| `c`   | Copy the selected item's full path to the system clipboard — configurable: `copy_path` |

### Exit

| Key   | Action                                        |
|-------|-----------------------------------------------|
| `q`       | Exit and cd to selected directory — configurable: `quit` |
| `Esc`     | Exit without directory change — configurable: `exit` |
| `Shift+Q` | Force quit without output, from any mode (search, quick jump, disk selection, bookmark creation/selection). Not configurable — checked as a literal uppercase `Q` before any mode-specific handling, so it always wins regardless of the `quit`/`exit` bindings in `config.toml`. |

## Search Mode

After pressing `/`:

### Input

| Key             | Action                           |
|-----------------|----------------------------------|
| Type characters | Add to search query              |
| `Backspace`     | Remove last character            |
| `Enter`         | Execute search and show results  |
| `Esc`           | Cancel search (exit search mode) |

### Fuzzy Search

Start the query with `/` to enable fuzzy matching:

```
src        Normal search — finds folders and files whose name contains "src"
/srch      Fuzzy search — finds "search", "src", "scratch", etc.
```

Results are ranked by relevance score.

### Search Results Navigation

After executing a search:

| Key        | Action                                        |
|------------|-----------------------------------------------|
| `Tab`      | Switch focus between tree and results         |
| `j` or `↓` | Navigate down in results                      |
| `k` or `↑` | Navigate up in results                        |
| `/`        | Filter the current results (see below)        |
| `Enter`    | Jump to selected result in tree               |
| `q`        | Exit and cd to selected result's directory    |
| `Esc`      | Close results and exit search mode            |

### Filtering Results

While focused on results, press `/` to open a filter input that narrows the list to results
whose **full path** contains the typed text (case-insensitive). This is an in-memory filter over
what the search **already found** — it never starts a new disk scan, so it can only ever hide
rows, never reveal matches the search did not collect (results are capped, see
`MAX_DIR_RESULTS` / `MAX_FILE_RESULTS` in `search.rs`).

| Key             | Action                                                        |
|-----------------|--------------------------------------------------------------|
| Type characters | Narrow the results (matches anywhere in the path)            |
| `Backspace`     | Delete a character and re-widen; on an empty filter, leave the filter input |
| `↑` / `↓`       | Move the selection while still typing the filter             |
| `Tab`           | Keep the filter applied and return to result navigation      |
| `Enter`         | Jump to the selected (filtered) result in the tree           |
| `Esc`           | Clear the filter and restore the full result list           |

Mirrors the bookmark filter sub-mode. `q` is an ordinary character while the filter caret is
showing (it types into the filter) — press `Tab` or `Enter` first to reach the normal
"quit with selected result" binding. Switching focus back to the tree (`Tab` from result
navigation) also leaves the filter input; the filter string is kept, so returning to the results
shows the same narrowed list. Running a new search clears the filter.

Since the tree stays directory-only, selecting a file result (`Enter` or `q`) jumps to/selects
its **containing folder** rather than the file itself. File results only ever come from the
background disk scan — unlike folder hits, which can appear instantly if already loaded, a file
hit always appears a beat later, once the scan reaches it.

## Quick Jump Mode

After pressing `Tab` in Tree Navigation Mode (only when no search results panel is open —
if results are showing, `Tab` still switches focus between tree and results as described above).

Type a folder name and the cursor jumps straight to the first matching folder, expanding
whatever is in the way to reveal it — no results list, no fuzzy scoring, just type and jump.

- **Scope**: the entire subtree of the current root, not just the folders currently on screen.
- **Matching**: case-insensitive **prefix** match on folder name only (files are never matched).
- **Ordering**: the shallowest match wins when several folders share a prefix at different depths.
- **Source**: folders already loaded into memory (instant) are checked first; if none match, a
  background scan of the disk kicks in automatically after a short pause in typing.
- **Multiple matches**: typing always jumps to one folder (the shallowest match), but every match
  found for the current prefix — up to 20 — is kept in a list. When there's more than one, the
  bar shows a `(i/N, Shift+Tab)` hint next to it; press `Shift+Tab` to cycle forward through the
  rest, wrapping back to the first after the last. Type more characters to narrow down instead,
  or switch to `/` search to see and pick between all of them.
- **Narrowing scope**: once a folder is matched, press `/` to lock the search to that folder's
  subtree — e.g. type `src`, press `/`, type `compon` to land on `src/components` without risking
  a match from somewhere else in the tree. The folder is physically expanded in the tree at that
  point, and the bar keeps growing instead of clearing (`⇥ src` → `⇥ src/` → `⇥ src/compon`), so
  it always shows the full path built up so far. `/` does nothing if pressed before anything has
  matched yet. `Backspace` right at a `/` boundary (nothing typed yet in the new segment) undoes
  it: pops back to the previous segment, re-collapses the folder — unless it was already expanded
  before `Tab` was pressed, in which case it's left open — and moves the selection back onto it.
  `Esc` still cancels the *entire* session and restores the pre-`Tab` state regardless of how many
  times `/` was pressed.

| Key             | Action                                                          |
|-----------------|------------------------------------------------------------------|
| Type characters | Add to the jump buffer; jumps automatically on a match           |
| `Backspace`     | Remove last character and re-jump; at a `/` boundary, undo that segment instead (see above) |
| `Shift+Tab`     | Cycle to the next known match (wraps around); stays in quick jump |
| `/`             | Lock the search to the currently matched folder's subtree and expand it |
| `Esc`           | **Cancel** — restores the tree exactly as it was before `Tab` was pressed (selection, and any folder that was only expanded during this session, collapsed back down) |
| `Tab` or `Enter`| **Confirm** — exits quick jump; the selection and any auto-expanded folders stay as they are |
| `↑` / `↓`       | **Confirm** — exits quick jump and moves the selection as usual  |

Note: `j`/`k` are treated as ordinary letters while quick jump is active (so folders named
e.g. `kubernetes` or `jazz` stay reachable) — only the arrow keys exit the mode.

`Esc` is the only exit that undoes the session; a second `Tab`, `Enter`, or an arrow key all
treat wherever the session landed as confirmed — matching how manually expanding folders with
`l` already behaves.

If the current buffer has no match anywhere (yet), the indicator bar is shown in a different
color; keep typing or backspace to recover. Every keystroke is always accepted into the buffer,
even with no match — it never gets silently rejected.

Each match is auto-expanded down to the target folder, and — like manually expanding folders
with `l` — that expansion is not undone when the match moves to a different folder or when
quick jump exits. Typing through several different matches can leave a trail of expanded
folders behind; this is expected.

## Bookmark Creation Mode

After pressing `m`:

| Key             | Action                                         |
|-----------------|------------------------------------------------|
| Type characters | Add to bookmark name                           |
| `Backspace`     | Remove last character                          |
| `Enter`         | Save bookmark                                  |
| `Esc`           | Cancel bookmark creation                       |

Naming rules: no path separators (`/`, `\`), null bytes, or control characters; max 255 characters;
cannot match a Windows reserved device name (`CON`, `COM1`, etc.). Otherwise permissive — `.`, `..`,
`-`, and names with spaces or dots are all valid.

## Bookmark Selection Mode

After pressing `'`:

### Navigation Mode (Default)

| Key        | Action                                              |
|------------|-----------------------------------------------------|
| `j` or `↓` | Move selection down                                 |
| `k` or `↑` | Move selection up                                   |
| `Enter`    | Jump to selected bookmark                           |
| `q`        | Exit and cd to selected bookmark                    |
| `d`        | Mark bookmark for deletion (press twice to confirm) |
| `Tab`      | Switch to filter mode                               |
| `Esc`      | Close bookmark selection                            |

### Filter Mode

| Key             | Action                                     |
|-----------------|--------------------------------------------|
| Type characters | Filter bookmarks by name or path           |
| `Backspace`     | Remove last character from filter          |
| `Tab`           | Switch back to navigation mode             |
| `Enter`         | Jump to selected bookmark                  |
| `Esc`           | Close bookmark selection                   |

### Deletion Workflow

Two-phase deletion prevents accidental removal:

1. Press `d` once → bookmark marked with `[DEL]` prefix
2. Press `d` again → bookmark deleted
3. Navigate with `j`/`k` → mark cleared (cancels deletion)

## Disk Selection Mode

After pressing `d` in tree mode:

| Key        | Action                                  |
|------------|------------------------------------------|
| `j` or `↓` | Move selection down                     |
| `k` or `↑` | Move selection up                       |
| `Enter`    | Navigate to selected disk root          |
| `q`        | Exit bmrk and cd to selected disk root  |
| `Esc`      | Close without navigating                |

## Mouse Bindings

Mouse behaviour adapts to the active panel.

### Tree Mode

| Action       | Effect                         |
|--------------|--------------------------------|
| Click        | Select item under cursor       |
| Double-click | Expand/collapse directory      |
| Scroll wheel | Navigate tree up/down          |

### Bookmark Selection (`'`)

| Action       | Effect                              |
|--------------|-------------------------------------|
| Click        | Select bookmark under cursor        |
| Double-click | Navigate to the selected bookmark   |
| Scroll wheel | Navigate bookmark list              |

### Disk Selection (`d`)

| Action       | Effect                              |
|--------------|-------------------------------------|
| Click        | Select disk under cursor            |
| Double-click | Navigate to selected disk root      |
| Scroll wheel | Navigate disk list                  |

In all modes the view uses **minimal scrolling** — it only shifts when the selection leaves
the visible area. This means a single click followed by a double-click always lands on the
same row.

## Context-Specific Behavior

### `exit` key (`Esc` by default)

| Context              | Action                         |
|----------------------|--------------------------------|
| Tree mode            | Exit bmrk without output       |
| Quick jump mode      | Exit quick jump                |
| Search input mode    | Cancel search                  |
| Search results       | Close results panel            |
| Bookmark creation    | Cancel creation                |
| Bookmark selection   | Close selection panel          |
| Disk selection       | Close disk panel               |

### `Enter` Key

| Context              | Action                                  |
|----------------------|-----------------------------------------|
| Tree mode, directory | Change root to directory                |
| Quick jump mode      | Exit quick jump (no further action)     |
| Search input mode    | Execute search                          |
| Search results       | Jump to selected result in tree         |
| Bookmark creation    | Save bookmark                           |
| Bookmark selection   | Jump to selected bookmark               |
| Disk selection       | Navigate to selected disk root          |

### `quit` key (`q` by default)

| Context              | Action                                     |
|----------------------|--------------------------------------------|
| Tree mode            | Exit and cd to selected directory          |
| Search results       | Exit and cd to selected result's directory |
| Bookmark selection (navigation mode) | Exit and cd to selected bookmark |
| Disk selection       | Exit and cd to selected disk root          |

`quit` does not exit when bookmark filter mode is active — typed text goes to the filter instead.

## Keybinding Customization

All major keys can be remapped in the `[keybindings]` section of `config.toml`:

```toml
[keybindings]
search          = ["/"]
create_bookmark = ["m"]
select_bookmark = ["'"]
select_disk     = ["d"]
go_to_parent    = ["u"]          # Go to parent directory
copy_path       = ["c"]          # Copy the selected item's full path
go_back         = ["Backspace"]  # Go back (undo last navigation)
quit            = ["q"]          # Exit and output selected path (triggers cd in shell)
exit            = ["Esc"]        # Exit without output / cancel current mode
```

Each field accepts a list — multiple keys can trigger the same action:

```toml
go_back = ["Backspace", "b"]   # Backspace or b to go back
quit    = ["q", "Q"]           # Both q and Q quit with output
```

Keys not remappable: `j`/`k` (move up/down), `h`/`l` (collapse/expand), `Enter`, `Tab`, arrow keys, and `d` (deletion inside bookmark selection). Inside Quick Jump Mode specifically, `/` (narrow) and `Shift+Tab` (cycle) are also fixed — they're read as literal key codes, not through the `search`/other keybinding config, so remapping `search` elsewhere does not change what narrows quick jump. `Shift+Q` (force quit) is likewise fixed — it's checked as a literal `KeyCode::Char('Q')` before any keybinding config is consulted, from any mode.

## Quick Reference Card

### Tree Navigation

```
Movement:    j/k (down/up)   l (expand)   h (collapse/parent)   u (back)
Other:       / (search)   Tab (quick jump)   m (bookmark)   ' (bookmarks)   d (disks)   c (copy path)
Exit:        q (exit+cd)   Esc (exit)   Enter (enter dir)   Shift+Q (force quit, any mode)
```

### Quick Jump

```
Input:       type name (jumps automatically)   Backspace (delete)
Multi-match: Shift+Tab (cycle, wraps around)
Narrow:      / (scope + expand current match)   Backspace at / (undo segment)
Cancel:      Esc (restore pre-Tab state)
Confirm:     Tab/Enter (exit)   ↑/↓ (exit + move)
```

### Search

```
Input:       type query   Backspace (delete)   Enter (search)   Esc (cancel)
Results:     j/k (nav)   Enter (jump)   q (exit+cd)   Tab (focus)   Esc (close)
```

### Bookmarks

```
Create:      m   type name   Enter (save)   Esc (cancel)
Select:      '   j/k (nav)   Enter (jump)   q (exit+cd)   Tab (filter)   d d (delete)
```

### Disks

```
Open:        d   j/k (nav)   Enter (switch root)   q (exit+cd)   Esc (close)
```