You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/Advanced-Features.md
+112Lines changed: 112 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -84,6 +84,118 @@ ds + ... = delete via search df + .. = delete via 2-char find
84
84
85
85
---
86
86
87
+
## Selection Handlers
88
+
89
+
During label selection, special keys can trigger **selection handlers** — registered actions that modify the selection flow. Three built-in handlers ship with SmartMotion.
90
+
91
+
### Select First / Select Last
92
+
93
+
Press `<CR>` during label selection to instantly select the first target. This bridges the gap between SmartMotion's label-based selection and vanilla Vim behavior.
94
+
95
+
Search motions like `f`, `t`, and `s` always require reading and pressing a label, even when you want the closest match. Unlike `dww` (repeat the motion key) or flow state (`jj`), there's no quick shortcut for "just give me the first one."
96
+
97
+
```
98
+
fa<CR> jump to the first "a" (vanilla f behavior)
99
+
ta<CR> jump to just before the first "a" (vanilla t behavior)
100
+
sa<CR> jump to the first "a" search match
101
+
dw<CR> delete to the first word target
102
+
```
103
+
104
+
`select_last` does the inverse — selects the furthest target. Not mapped by default; add it to your config:
105
+
106
+
```lua
107
+
selection_keys= {
108
+
["<CR>"] ="select_first",
109
+
["<S-CR>"] ="select_last",
110
+
}
111
+
```
112
+
113
+
### Toggle Hint Position
114
+
115
+
Flips hint labels between the start and end of each target. Useful when a hint overlaps text you're trying to read. Not mapped by default:
116
+
117
+
```lua
118
+
selection_keys= {
119
+
["<CR>"] ="select_first",
120
+
["<M-h>"] ="toggle_hint_position",
121
+
}
122
+
```
123
+
124
+
Press the toggle key during label selection — hints re-render at the opposite end of each target. Press it again to flip back. Then pick your label as usual.
125
+
126
+
### Pipeline-Modifying Handlers
127
+
128
+
Some selection handlers can re-run the entire motion pipeline during label selection.
129
+
This lets you change the search context without cancelling and re-triggering the motion.
130
+
131
+
**Built-in pipeline-modifying handlers:**
132
+
133
+
-`toggle_direction` (`<M-d>`) — Flip between forward and backward search. Press during
134
+
`w` labels to switch to backward words, or during `s` results to search the other direction.
135
+
136
+
-`toggle_multi_window` (`<M-w>`) — Toggle between single-window and multi-window target
137
+
collection. Expand a word motion to show targets across all visible windows.
138
+
139
+
-`expand_search_scope` (`<M-e>`) — Double the search scope (max_lines). Press multiple
140
+
times to progressively expand. Useful when the target you want is just outside the
141
+
initial scope.
142
+
143
+
**How it works:** When these handlers are triggered, the plugin:
144
+
1. Resets targets and labels
145
+
2. Re-runs the pipeline with the modified `motion_state`
146
+
3. Regenerates and renders new hint labels
147
+
4. Returns to the selection loop for your next keypress
148
+
149
+
If the re-run produces no targets (e.g., toggling direction when nothing is behind the
150
+
cursor), the motion cancels gracefully.
151
+
152
+
### Relationship to Other Shortcuts
153
+
154
+
SmartMotion has several ways to "skip" or modify label selection:
155
+
156
+
| Method | How | Best for |
157
+
|--------|-----|----------|
158
+
|**Flow state**| Press motion key quickly after a previous motion | Chaining motions (`w` → `w` → `j`) |
159
+
|**Repeat motion key**| Press motion key during labels (`dww`) | Acting on cursor target |
160
+
|**Select first target**| Press `<CR>` during labels | Picking the closest match |
161
+
|**Toggle hint position**| Press configured key during labels | Reading obscured text |
162
+
|**Toggle direction**| Press `<M-d>` during labels | Flipping search direction |
163
+
|**Toggle multi-window**| Press `<M-w>` during labels | Expanding to all windows |
164
+
|**Expand search scope**| Press `<M-e>` during labels | Reaching further targets |
165
+
166
+
All coexist. Selection handlers are checked after the motion-key-repeat check, so `dww` still works as expected.
167
+
168
+
### Configuration
169
+
170
+
Enabled by default with four mappings. The `selection_keys` config maps keys to registered handlers:
171
+
172
+
```lua
173
+
-- Default
174
+
selection_keys= {
175
+
["<CR>"] ="select_first",
176
+
["<M-d>"] ="toggle_direction",
177
+
["<M-w>"] ="toggle_multi_window",
178
+
["<M-e>"] ="expand_search_scope",
179
+
}
180
+
181
+
-- Full example
182
+
selection_keys= {
183
+
["<CR>"] ="select_first",
184
+
["<S-CR>"] ="select_last",
185
+
["<M-h>"] ="toggle_hint_position",
186
+
["<M-d>"] ="toggle_direction",
187
+
["<M-w>"] ="toggle_multi_window",
188
+
["<M-e>"] ="expand_search_scope",
189
+
}
190
+
191
+
-- Disable
192
+
selection_keys=false
193
+
```
194
+
195
+
See **[Configuration: Selection Keys](Configuration.md#selection-keys)** for details.
196
+
197
+
---
198
+
87
199
## Operator-Pending Mode
88
200
89
201
SmartMotion motions work with **any vim operator**.
|`expand_search_scope`|`<M-e>`| re-runs | Doubles the search scope (max_lines) |
491
+
492
+
Add others as needed:
493
+
494
+
```lua
495
+
selection_keys= {
496
+
["<CR>"] ="select_first",
497
+
["<S-CR>"] ="select_last",
498
+
["<M-h>"] ="toggle_hint_position",
499
+
["<M-d>"] ="toggle_direction",
500
+
["<M-w>"] ="toggle_multi_window",
501
+
["<M-e>"] ="expand_search_scope",
502
+
}
503
+
```
504
+
505
+
### Examples
506
+
507
+
```
508
+
fa<CR> jump to the first "a" (same as vanilla f)
509
+
sa<CR> jump to the first "a" match
510
+
dw<CR> delete to the first word target
511
+
w<M-h> toggle hints to end-of-word, then pick a label
512
+
w<M-d> flip to backward words, then pick a label
513
+
s<M-w> toggle multi-window search, then pick a label
514
+
w<M-e> double the search scope, then pick a label
515
+
```
516
+
517
+
### Handler Return Values
518
+
519
+
Handlers return a value that controls the selection flow:
520
+
521
+
-**`true`** — accept the selection and exit (like `select_first`, `select_last`)
522
+
-**`false`** — stay in the selection loop and wait for the next keypress (like `toggle_hint_position`)
523
+
-**`"rerun"`** — re-run the full pipeline with modified state, then return to selection (like `toggle_direction`, `toggle_multi_window`, `expand_search_scope`)
524
+
525
+
### Disable
526
+
527
+
```lua
528
+
selection_keys=false
529
+
```
530
+
531
+
### Custom Handlers
532
+
533
+
Selection handlers are registered modules, just like collectors, extractors, and actions:
0 commit comments