# How to Use Visual Mode (v/V) to Create Range Comments in tuicr

> Master tuicr's visual mode with v/V to create range comments effortlessly. Highlight lines and add comments to selected code ranges for clearer feedback.

- Repository: [Almog Gavra/tuicr](https://github.com/agavra/tuicr)
- Tags: how-to-guide
- Published: 2026-08-07

---

**Press `v` or `V` in tuicr's diff view to enter visual mode, navigate to select the desired lines, then press `c` to attach a single comment to the entire highlighted range.**

tuicr is a terminal-based code review tool that enables attaching comments to specific line ranges using a Vim-inspired **visual selection** workflow. The repository `agavra/tuicr` implements this through a dedicated Visual Select mode, allowing reviewers to highlight contiguous diff blocks before commenting. Mastering how to create range comments in tuicr streamlines the review process by letting you address multi-line logic or context-dependent issues in a single annotation.

## Entering Visual Mode

To begin creating a range comment, you must first activate visual mode using either character-wise or line-wise selection.

### Character-wise Selection with `v`

Press **`v`** to enter character-wise visual mode. This key maps to `Action::EnterVisualMode` in [`src/input/keybindings.rs`](https://github.com/agavra/tuicr/blob/main/src/input/keybindings.rs)【🔗 src/input/keybindings.rs#L220-L222】, initializing a selection at the current cursor position.

### Line-wise Selection with `V`

Press **`V`** (shift+v) for line-wise visual mode. While this triggers the same `EnterVisualMode` action, it treats the entire current line as the initial selection unit, making it ideal for selecting complete code blocks.

## Expanding the Selection

Once in visual mode, navigation keys move the cursor while simultaneously updating the active `VisualSelection`. The selection state is stored in `App.visual_selection: Option<VisualSelection>` as defined in [`src/app/mod.rs`](https://github.com/agavra/tuicr/blob/main/src/app/mod.rs)【🔗 src/app/mod.rs#L206-L218】.

Valid navigation keys include:

- `h`, `j`, `k`, `l` or arrow keys for single-step movement
- `Ctrl-d` and `Ctrl-u` for half-page jumps
- Page up/down for larger movements

As you navigate, the `head` of the `VisualSelection` follows the cursor while the `anchor` remains fixed, effectively growing or shrinking the selected range. This update logic resides in `src/app/visual.rs::move_cursor`, which is invoked from the main event loop.

## Creating the Range Comment

With your target range highlighted:

1. Press **`c`** to trigger `Action::AddLineComment`. When a visual selection exists, tuicr creates a line-range comment covering every line between the anchor and head of the selection.
2. Type your comment text. The application automatically enters comment input mode (handled by `map_comment_mode` in [`src/input/keybindings.rs`](https://github.com/agavra/tuicr/blob/main/src/input/keybindings.rs)).
3. Press **Enter** to submit the comment.

The comment construction logic executes in [`src/app/visual.rs`](https://github.com/agavra/tuicr/blob/main/src/app/visual.rs)【🔗 src/app/visual.rs#L54-L63】, specifically within the `add_range_comment` method invoked via `App::save_comment`. The resulting comment attaches to every line in the selected span.

## Canceling the Selection

To abort a visual selection without creating a comment, press **Esc**. This clears `InputMode::VisualSelect` in [`src/handler.rs`](https://github.com/agavra/tuicr/blob/main/src/handler.rs), removing the active selection and returning the application to normal mode.

## Visual Rendering and State Management

The selected range renders in the diff view via `render_visual_selection` in [`src/ui/diff_view.rs`](https://github.com/agavra/tuicr/blob/main/src/ui/diff_view.rs), providing immediate visual feedback through highlighting. Because the selection persists as part of the core `App` state in [`src/app/mod.rs`](https://github.com/agavra/tuicr/blob/main/src/app/mod.rs), this functionality works consistently across all supported VCS backends including Git, Mercurial, and Jujutsu.

## Programmatic Workflow Example

The following Rust pseudocode demonstrates the complete visual selection workflow using tuicr's internal key handling:

```rust
// Enter visual mode (v for character-wise, V for line-wise)
app.handle_key(KeyEvent::new(KeyCode::Char('v'), KeyModifiers::NONE));

// Expand selection downward three lines
app.handle_key(KeyEvent::new(KeyCode::Char('j'), KeyModifiers::NONE));
app.handle_key(KeyEvent::new(KeyCode::Char('j'), KeyModifiers::NONE));
app.handle_key(KeyEvent::new(KeyCode::Char('j'), KeyModifiers::NONE));

// Initiate range comment creation
app.handle_key(KeyEvent::new(KeyCode::Char('c'), KeyModifiers::NONE));

// Type comment text
for ch in "Fix is bad".chars() {
    app.handle_key(KeyEvent::new(KeyCode::Char(ch), KeyModifiers::NONE));
}

// Submit the comment
app.handle_key(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE));

```

To cancel the selection programmatically:

```rust
app.handle_key(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE));

```

## Summary

- Press **`v`** or **`V`** to enter visual mode and initialize a selection at the current cursor position.
- Use navigation keys (`h`/`j`/`k`/`l`, arrows, or page keys) to expand the selection range stored in `App.visual_selection`.
- Press **`c`** to create a line-range comment covering the selected anchor-to-head span.
- Submit with **Enter** or abort with **Esc** to clear `InputMode::VisualSelect`.
- The implementation spans [`src/input/keybindings.rs`](https://github.com/agavra/tuicr/blob/main/src/input/keybindings.rs), [`src/app/visual.rs`](https://github.com/agavra/tuicr/blob/main/src/app/visual.rs), and [`src/handler.rs`](https://github.com/agavra/tuicr/blob/main/src/handler.rs), with rendering handled by [`src/ui/diff_view.rs`](https://github.com/agavra/tuicr/blob/main/src/ui/diff_view.rs).

## Frequently Asked Questions

### What is the difference between `v` and `V` in tuicr?

Both keys activate visual mode, but **`v`** initiates character-wise selection while **`V`** initiates line-wise selection. For creating range comments, `V` is typically more efficient because it selects entire lines of code immediately, whereas `v` allows finer-grained character positioning.

### Can I create a file-wide comment using visual mode?

Yes. Press **`C`** (uppercase) instead of `c` to create a file-wide comment. This action bypasses the visual selection mechanism and attaches the comment to the entire file rather than a specific line range.

### Where does tuicr store the visual selection state?

The visual selection is stored in the `App` struct as `visual_selection: Option<VisualSelection>`, defined in [`src/app/mod.rs`](https://github.com/agavra/tuicr/blob/main/src/app/mod.rs). The `VisualSelection` struct maintains both the anchor (starting point) and head (current cursor position) coordinates to define the exact range for commenting.

### How do I know which lines are selected?

The selected range is highlighted in the terminal UI by `render_visual_selection` in [`src/ui/diff_view.rs`](https://github.com/agavra/tuicr/blob/main/src/ui/diff_view.rs). This visual feedback clearly indicates exactly which lines will receive the comment when you press `c`, ensuring you comment on the intended code block.