feature: support visual selection annotations #108

Open
opened 2026-09-14 09:29:07 -05:00 by TimoSutterer · 3 comments
TimoSutterer commented 2026-09-14 09:29:07 -05:00 (Migrated from github.com)

Did you check the docs?

  • I have read all the haunt.nvim docs

Annotations in haunt.nvim are currently attached to a single line. Sometimes an annotation describes a larger piece of code rather than one specific line, such as a function, conditional, query, or implementation block.

In those cases, attaching the annotation to one line does not make it clear which part of the code the note refers to.

Describe the solution you'd like

I'd like to be able to visually select a range of code and attach a single annotation to that selection.

For example, calling annotate() from Visual mode could create an annotation whose range corresponds to the current selection, while calling it from Normal mode would keep the existing single-line behavior.

A range annotation could behave similarly to an existing bookmark:

  • the sign and annotation text could remain on the first line of the range
  • the selected range could optionally be highlighted
  • navigation and pickers could jump to the start of the range
  • editing, deleting, or toggling the annotation while the cursor is inside the range could operate on that annotation
  • the range should continue to track the selected code as the buffer is edited, similar to how single-line bookmarks are currently tracked

I'd be happy with linewise Visual selections as the scope. Blockwise and characterwise selections could remain unsupported.

Describe alternatives/other solutions you've considered

The current workaround is to attach the annotation to the first or most relevant line of the block, but this loses information about the extent of the code the annotation refers to.

Additional context

haunt.nvim already uses extmarks to keep bookmark positions synchronized as the buffer changes. Neovim extmarks can also represent ranges, so this seems like it could build on the existing tracking mechanism rather than requiring a completely separate system.

For persistence, this could potentially be backwards-compatible by keeping the existing (starting) line and adding optional range information such as end_line. Existing bookmarks without range information would remain normal single-line bookmarks.

This would also make haunt annotations more useful as context for integrations such as Sidekick, since an annotation could identify the actual region of code it describes instead of only a single line.

### Did you check the docs? - [x] I have read all the haunt.nvim docs ### Is your feature request related to a problem? Please describe. Annotations in haunt.nvim are currently attached to a single line. Sometimes an annotation describes a larger piece of code rather than one specific line, such as a function, conditional, query, or implementation block. In those cases, attaching the annotation to one line does not make it clear which part of the code the note refers to. ### Describe the solution you'd like I'd like to be able to visually select a range of code and attach a single annotation to that selection. For example, calling annotate() from Visual mode could create an annotation whose range corresponds to the current selection, while calling it from Normal mode would keep the existing single-line behavior. A range annotation could behave similarly to an existing bookmark: - the sign and annotation text could remain on the first line of the range - the selected range could optionally be highlighted - navigation and pickers could jump to the start of the range - editing, deleting, or toggling the annotation while the cursor is inside the range could operate on that annotation - the range should continue to track the selected code as the buffer is edited, similar to how single-line bookmarks are currently tracked I'd be happy with linewise Visual selections as the scope. Blockwise and characterwise selections could remain unsupported. ### Describe alternatives/other solutions you've considered The current workaround is to attach the annotation to the first or most relevant line of the block, but this loses information about the extent of the code the annotation refers to. ### Additional context haunt.nvim already uses extmarks to keep bookmark positions synchronized as the buffer changes. Neovim extmarks can also represent ranges, so this seems like it could build on the existing tracking mechanism rather than requiring a completely separate system. For persistence, this could potentially be backwards-compatible by keeping the existing (starting) `line` and adding optional range information such as `end_line`. Existing bookmarks without range information would remain normal single-line bookmarks. This would also make haunt annotations more useful as context for integrations such as Sidekick, since an annotation could identify the actual region of code it describes instead of only a single line.
Owner

@TimoSutterer
Thanks for the extremely detailed ticket! I agree that we should only do linewise, but we should also support the other x modes, and just get the line numbers. I think this would be nice for visual mode to still work.

How do you think this should display? like a:
-

(for example) Sort of thing with border characters? I think thats the main thing i am immediately confused about with

Do you see the primary use case of this being used with AI agents?
What made you want to open this issue? Why were one line annotations not enough? (just curious, i think its a good addition anyhow)

I dont think that I will be able to get to this until next next weekend, but i think its definitely worth doing!

@TimoSutterer Thanks for the extremely detailed ticket! I agree that we should only do linewise, but we should also support the other `x` modes, and just get the line numbers. I think this would be nice for visual mode to still work. How do you think this should display? like a: -| | | -| (for example) Sort of thing with border characters? I think thats the main thing i am immediately confused about with Do you see the primary use case of this being used with AI agents? What made you want to open this issue? Why were one line annotations not enough? (just curious, i think its a good addition anyhow) I dont think that I will be able to get to this until next next weekend, but i think its definitely worth doing!
TimoSutterer commented 2026-09-18 04:46:46 -05:00 (Migrated from github.com)

Thanks a lot for looking into this so quickly, I really appreciate it!

Supporting the other visual modes and just using the first and last selected line sounds like a good idea to me.

My main use case would be selecting part of a longer function and attaching a comment specifically to that part. For example, if lines 40-52 should be extracted into a helper function, having the range makes the intent much clearer than attaching the comment to just line 40. This becomes especially useful when passing the annotations to an AI agent, where it could turn into something very explicit like:

@/foo.py :L40-L52 - "extract this into a helper function"

More generally, I think this is useful whenever an annotation describes a region rather than a single line: a conditional block, a query fragment, a group of assertions, a sequence of statements, etc.

I originally got the idea while playing around with review.nvim and found the multi-line comments useful pretty much right away. For displaying the range in haunt.nvim, something subtle in the gutter, similar to how gitsigns.nvim marks changed lines, could be nice. For example, roughly:

👻  first line of the range
│   second line
│   third line
╰   last line

The downside of using the gutter is that if haunt.nvim and gitsigns.nvim both have a sign on the same line, one of them can be hidden depending on priority. This already happens with haunt.nvim's current ghost sign though, so it wouldn't be a completely new issue introduced by ranges. And users can simply work around it by allowing multiple sign columns, for example with signcolumn=auto:2.

Also, no rush on this at all. I'm already very glad you're interested in implementing it :)

Thanks a lot for looking into this so quickly, I really appreciate it! Supporting the other visual modes and just using the first and last selected line sounds like a good idea to me. My main use case would be selecting part of a longer function and attaching a comment specifically to that part. For example, if lines 40-52 should be extracted into a helper function, having the range makes the intent much clearer than attaching the comment to just line 40. This becomes especially useful when passing the annotations to an AI agent, where it could turn into something very explicit like: `@/foo.py :L40-L52 - "extract this into a helper function"` More generally, I think this is useful whenever an annotation describes a region rather than a single line: a conditional block, a query fragment, a group of assertions, a sequence of statements, etc. I originally got the idea while playing around with [review.nvim](https://github.com/georgeguimaraes/review.nvim) and found the multi-line comments useful pretty much right away. For displaying the range in `haunt.nvim`, something subtle in the gutter, similar to how [gitsigns.nvim](https://github.com/lewis6991/gitsigns.nvim) marks changed lines, could be nice. For example, roughly: ```text 👻 first line of the range │ second line │ third line ╰ last line ``` The downside of using the gutter is that if `haunt.nvim` and `gitsigns.nvim` both have a sign on the same line, one of them can be hidden depending on priority. This already happens with `haunt.nvim`'s current ghost sign though, so it wouldn't be a completely new issue introduced by ranges. And users can simply work around it by allowing multiple sign columns, for example with `signcolumn=auto:2`. Also, no rush on this at all. I'm already very glad you're interested in implementing it :)
Owner

The feature branch for new feature can be tracked here: #127

will merge into that branch slowly as I implement the feature

The feature branch for new feature can be tracked here: #127 will merge into that branch slowly as I implement the feature
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
noe.trevino/haunt.nvim#108
No description provided.