mui 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +13 -8
- data/CHANGELOG.md +99 -0
- data/README.md +309 -6
- data/docs/_config.yml +56 -0
- data/docs/configuration.md +301 -0
- data/docs/getting-started.md +140 -0
- data/docs/index.md +55 -0
- data/docs/jobs.md +297 -0
- data/docs/keybindings.md +229 -0
- data/docs/plugins.md +285 -0
- data/docs/syntax-highlighting.md +149 -0
- data/lib/mui/command_completer.rb +11 -2
- data/lib/mui/command_history.rb +89 -0
- data/lib/mui/command_line.rb +32 -2
- data/lib/mui/command_registry.rb +21 -2
- data/lib/mui/config.rb +3 -1
- data/lib/mui/editor.rb +78 -2
- data/lib/mui/handler_result.rb +13 -7
- data/lib/mui/highlighters/search_highlighter.rb +2 -1
- data/lib/mui/highlighters/syntax_highlighter.rb +3 -1
- data/lib/mui/key_handler/base.rb +87 -0
- data/lib/mui/key_handler/command_mode.rb +68 -0
- data/lib/mui/key_handler/insert_mode.rb +10 -41
- data/lib/mui/key_handler/normal_mode.rb +24 -51
- data/lib/mui/key_handler/operators/paste_operator.rb +9 -3
- data/lib/mui/key_handler/search_mode.rb +10 -7
- data/lib/mui/key_handler/visual_mode.rb +15 -10
- data/lib/mui/key_notation_parser.rb +152 -0
- data/lib/mui/key_sequence.rb +67 -0
- data/lib/mui/key_sequence_buffer.rb +85 -0
- data/lib/mui/key_sequence_handler.rb +163 -0
- data/lib/mui/key_sequence_matcher.rb +79 -0
- data/lib/mui/line_renderer.rb +52 -1
- data/lib/mui/mode_manager.rb +3 -2
- data/lib/mui/screen.rb +24 -6
- data/lib/mui/search_state.rb +61 -28
- data/lib/mui/syntax/language_detector.rb +33 -1
- data/lib/mui/syntax/lexers/css_lexer.rb +121 -0
- data/lib/mui/syntax/lexers/go_lexer.rb +205 -0
- data/lib/mui/syntax/lexers/html_lexer.rb +118 -0
- data/lib/mui/syntax/lexers/javascript_lexer.rb +197 -0
- data/lib/mui/syntax/lexers/markdown_lexer.rb +210 -0
- data/lib/mui/syntax/lexers/rust_lexer.rb +148 -0
- data/lib/mui/syntax/lexers/typescript_lexer.rb +203 -0
- data/lib/mui/terminal_adapter/curses.rb +13 -11
- data/lib/mui/version.rb +1 -1
- data/lib/mui/window.rb +83 -40
- data/lib/mui/window_manager.rb +7 -0
- data/lib/mui/wrap_cache.rb +40 -0
- data/lib/mui/wrap_helper.rb +84 -0
- data/lib/mui.rb +15 -0
- metadata +26 -3
data/docs/jobs.md
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Jobs
|
|
3
|
+
layout: default
|
|
4
|
+
nav_order: 6
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Asynchronous Jobs
|
|
8
|
+
{: .no_toc }
|
|
9
|
+
|
|
10
|
+
## Table of contents
|
|
11
|
+
{: .no_toc .text-delta }
|
|
12
|
+
|
|
13
|
+
1. TOC
|
|
14
|
+
{:toc}
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Overview
|
|
19
|
+
|
|
20
|
+
Mui's job system allows plugins to run background tasks without blocking the editor. This is essential for:
|
|
21
|
+
|
|
22
|
+
- Running tests
|
|
23
|
+
- Executing linters/formatters
|
|
24
|
+
- Making HTTP requests
|
|
25
|
+
- Any long-running operation
|
|
26
|
+
|
|
27
|
+
## Running Async Ruby Code
|
|
28
|
+
|
|
29
|
+
Use `ctx.run_async` to execute Ruby code in a background thread:
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
command :slow_task do |ctx|
|
|
33
|
+
ctx.set_message("Starting task...")
|
|
34
|
+
|
|
35
|
+
ctx.run_async do
|
|
36
|
+
# This runs in a background thread
|
|
37
|
+
sleep 5 # Simulate slow operation
|
|
38
|
+
"Task completed!"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### With Callback
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
command :fetch_data do |ctx|
|
|
47
|
+
ctx.run_async(on_complete: ->(result) {
|
|
48
|
+
ctx.set_message("Result: #{result}")
|
|
49
|
+
}) do
|
|
50
|
+
# Perform async work
|
|
51
|
+
fetch_from_api
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Running Shell Commands
|
|
59
|
+
|
|
60
|
+
Use `ctx.run_shell_command` for external processes:
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
command :run_tests do |ctx|
|
|
64
|
+
ctx.set_message("Running tests...")
|
|
65
|
+
|
|
66
|
+
ctx.run_shell_command("bundle exec rake test") do |result|
|
|
67
|
+
if result[:success]
|
|
68
|
+
ctx.open_scratch_buffer("[Test Results]", result[:stdout])
|
|
69
|
+
ctx.set_message("Tests passed!")
|
|
70
|
+
else
|
|
71
|
+
ctx.open_scratch_buffer("[Test Errors]", result[:stderr])
|
|
72
|
+
ctx.set_error("Tests failed!")
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Result Object
|
|
79
|
+
|
|
80
|
+
The callback receives a hash with:
|
|
81
|
+
|
|
82
|
+
| Key | Description |
|
|
83
|
+
|-----|-------------|
|
|
84
|
+
| `:success` | Boolean indicating exit status |
|
|
85
|
+
| `:stdout` | Standard output as string |
|
|
86
|
+
| `:stderr` | Standard error as string |
|
|
87
|
+
| `:exit_status` | Process exit code |
|
|
88
|
+
|
|
89
|
+
### Example: Linter
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
command :lint do |ctx|
|
|
93
|
+
file = ctx.buffer.file_path
|
|
94
|
+
|
|
95
|
+
ctx.run_shell_command("rubocop #{file}") do |result|
|
|
96
|
+
if result[:success]
|
|
97
|
+
ctx.set_message("No lint errors!")
|
|
98
|
+
else
|
|
99
|
+
ctx.open_scratch_buffer("[Lint Results]", result[:stdout])
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Job Management
|
|
108
|
+
|
|
109
|
+
### Checking Job Status
|
|
110
|
+
|
|
111
|
+
```ruby
|
|
112
|
+
command :status do |ctx|
|
|
113
|
+
if ctx.jobs_running?
|
|
114
|
+
ctx.set_message("Jobs are running...")
|
|
115
|
+
else
|
|
116
|
+
ctx.set_message("No active jobs")
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Cancelling Jobs
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
command :start_job do |ctx|
|
|
125
|
+
job_id = ctx.run_async do
|
|
126
|
+
# Long running task
|
|
127
|
+
loop do
|
|
128
|
+
sleep 1
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Store job_id for later cancellation
|
|
133
|
+
@current_job = job_id
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
command :cancel_job do |ctx|
|
|
137
|
+
if @current_job
|
|
138
|
+
ctx.cancel_job(@current_job)
|
|
139
|
+
ctx.set_message("Job cancelled")
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Scratch Buffers
|
|
147
|
+
|
|
148
|
+
Display job results in a scratch buffer:
|
|
149
|
+
|
|
150
|
+
```ruby
|
|
151
|
+
ctx.open_scratch_buffer(name, content)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
- Opens in a horizontal split
|
|
155
|
+
- Buffer is read-only
|
|
156
|
+
- Subsequent calls with same name update existing buffer
|
|
157
|
+
|
|
158
|
+
### Example: Test Runner
|
|
159
|
+
|
|
160
|
+
```ruby
|
|
161
|
+
command :test do |ctx|
|
|
162
|
+
ctx.run_shell_command("rake test") do |result|
|
|
163
|
+
output = []
|
|
164
|
+
output << "=== Test Results ==="
|
|
165
|
+
output << ""
|
|
166
|
+
output << result[:stdout]
|
|
167
|
+
|
|
168
|
+
if result[:stderr].length > 0
|
|
169
|
+
output << ""
|
|
170
|
+
output << "=== Errors ==="
|
|
171
|
+
output << result[:stderr]
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
output << ""
|
|
175
|
+
output << "Exit status: #{result[:exit_status]}"
|
|
176
|
+
|
|
177
|
+
ctx.open_scratch_buffer("[Test Output]", output.join("\n"))
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Job Events
|
|
185
|
+
|
|
186
|
+
React to job lifecycle with autocmd:
|
|
187
|
+
|
|
188
|
+
```ruby
|
|
189
|
+
autocmd :JobStarted do |ctx|
|
|
190
|
+
ctx.set_message("Job started")
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
autocmd :JobCompleted do |ctx|
|
|
194
|
+
ctx.set_message("Job completed successfully")
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
autocmd :JobFailed do |ctx|
|
|
198
|
+
ctx.set_error("Job failed!")
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
autocmd :JobCancelled do |ctx|
|
|
202
|
+
ctx.set_message("Job was cancelled")
|
|
203
|
+
end
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Complete Example: Build Plugin
|
|
209
|
+
|
|
210
|
+
```ruby
|
|
211
|
+
class BuildPlugin < Mui::Plugin
|
|
212
|
+
name :build
|
|
213
|
+
version "1.0.0"
|
|
214
|
+
description "Build and test runner"
|
|
215
|
+
|
|
216
|
+
def setup
|
|
217
|
+
command :build do |ctx|
|
|
218
|
+
run_build(ctx)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
command :test do |ctx|
|
|
222
|
+
run_tests(ctx)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
command :check do |ctx|
|
|
226
|
+
run_build(ctx)
|
|
227
|
+
run_tests(ctx)
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
keymap :normal, "<Leader>b" do |ctx|
|
|
231
|
+
run_build(ctx)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
keymap :normal, "<Leader>t" do |ctx|
|
|
235
|
+
run_tests(ctx)
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
autocmd :JobCompleted do |ctx|
|
|
239
|
+
# Could trigger notifications, update status line, etc.
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
private
|
|
244
|
+
|
|
245
|
+
def run_build(ctx)
|
|
246
|
+
ctx.set_message("Building...")
|
|
247
|
+
|
|
248
|
+
ctx.run_shell_command("make build") do |result|
|
|
249
|
+
if result[:success]
|
|
250
|
+
ctx.set_message("Build succeeded!")
|
|
251
|
+
else
|
|
252
|
+
ctx.open_scratch_buffer("[Build Errors]", result[:stderr])
|
|
253
|
+
ctx.set_error("Build failed!")
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def run_tests(ctx)
|
|
259
|
+
ctx.set_message("Running tests...")
|
|
260
|
+
|
|
261
|
+
ctx.run_shell_command("make test") do |result|
|
|
262
|
+
ctx.open_scratch_buffer("[Test Results]", result[:stdout])
|
|
263
|
+
|
|
264
|
+
if result[:success]
|
|
265
|
+
ctx.set_message("All tests passed!")
|
|
266
|
+
else
|
|
267
|
+
ctx.set_error("Tests failed!")
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## Interactive Commands
|
|
277
|
+
|
|
278
|
+
For commands that require user interaction (like fzf), use `run_interactive_command`:
|
|
279
|
+
|
|
280
|
+
```ruby
|
|
281
|
+
command :find_file do |ctx|
|
|
282
|
+
unless ctx.command_exists?("fzf")
|
|
283
|
+
ctx.set_error("fzf is not installed")
|
|
284
|
+
return
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# This temporarily exits curses mode
|
|
288
|
+
result = ctx.run_interactive_command("find . -type f | fzf")
|
|
289
|
+
|
|
290
|
+
if result && !result.empty?
|
|
291
|
+
ctx.editor.execute_command("e #{result.strip}")
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
{: .note }
|
|
297
|
+
`run_interactive_command` blocks and waits for the command to complete. Use this only for interactive CLI tools that require terminal access.
|
data/docs/keybindings.md
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Key Bindings
|
|
3
|
+
layout: default
|
|
4
|
+
nav_order: 3
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Key Bindings
|
|
8
|
+
{: .no_toc }
|
|
9
|
+
|
|
10
|
+
## Table of contents
|
|
11
|
+
{: .no_toc .text-delta }
|
|
12
|
+
|
|
13
|
+
1. TOC
|
|
14
|
+
{:toc}
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Normal Mode
|
|
19
|
+
|
|
20
|
+
### Cursor Movement
|
|
21
|
+
|
|
22
|
+
| Key | Action |
|
|
23
|
+
|-----|--------|
|
|
24
|
+
| `h` | Move left |
|
|
25
|
+
| `j` | Move down |
|
|
26
|
+
| `k` | Move up |
|
|
27
|
+
| `l` | Move right |
|
|
28
|
+
| `0` | Move to line start |
|
|
29
|
+
| `^` | Move to first non-blank character |
|
|
30
|
+
| `$` | Move to line end |
|
|
31
|
+
|
|
32
|
+
### Word Movement
|
|
33
|
+
|
|
34
|
+
| Key | Action |
|
|
35
|
+
|-----|--------|
|
|
36
|
+
| `w` | Move to next word start |
|
|
37
|
+
| `b` | Move to previous word start |
|
|
38
|
+
| `e` | Move to word end |
|
|
39
|
+
|
|
40
|
+
### File Movement
|
|
41
|
+
|
|
42
|
+
| Key | Action |
|
|
43
|
+
|-----|--------|
|
|
44
|
+
| `gg` | Go to first line |
|
|
45
|
+
| `G` | Go to last line |
|
|
46
|
+
| `:{number}` | Go to line number |
|
|
47
|
+
|
|
48
|
+
### Character Search
|
|
49
|
+
|
|
50
|
+
| Key | Action |
|
|
51
|
+
|-----|--------|
|
|
52
|
+
| `f{char}` | Find character forward (on character) |
|
|
53
|
+
| `F{char}` | Find character backward (on character) |
|
|
54
|
+
| `t{char}` | Find character forward (before character) |
|
|
55
|
+
| `T{char}` | Find character backward (after character) |
|
|
56
|
+
|
|
57
|
+
### Search
|
|
58
|
+
|
|
59
|
+
| Key | Action |
|
|
60
|
+
|-----|--------|
|
|
61
|
+
| `/pattern` | Search forward |
|
|
62
|
+
| `?pattern` | Search backward |
|
|
63
|
+
| `n` | Next match |
|
|
64
|
+
| `N` | Previous match |
|
|
65
|
+
| `*` | Search word under cursor (forward) |
|
|
66
|
+
| `#` | Search word under cursor (backward) |
|
|
67
|
+
|
|
68
|
+
### Entering Insert Mode
|
|
69
|
+
|
|
70
|
+
| Key | Action |
|
|
71
|
+
|-----|--------|
|
|
72
|
+
| `i` | Insert before cursor |
|
|
73
|
+
| `a` | Append after cursor |
|
|
74
|
+
| `I` | Insert at line start |
|
|
75
|
+
| `A` | Append at line end |
|
|
76
|
+
| `o` | Open line below |
|
|
77
|
+
| `O` | Open line above |
|
|
78
|
+
|
|
79
|
+
### Operators
|
|
80
|
+
|
|
81
|
+
Operators can be combined with motions (e.g., `dw` = delete word).
|
|
82
|
+
|
|
83
|
+
| Key | Action |
|
|
84
|
+
|-----|--------|
|
|
85
|
+
| `d` | Delete |
|
|
86
|
+
| `c` | Change (delete and enter Insert mode) |
|
|
87
|
+
| `y` | Yank (copy) |
|
|
88
|
+
|
|
89
|
+
### Common Operations
|
|
90
|
+
|
|
91
|
+
| Key | Action |
|
|
92
|
+
|-----|--------|
|
|
93
|
+
| `dd` | Delete line |
|
|
94
|
+
| `cc` | Change line |
|
|
95
|
+
| `yy` | Yank line |
|
|
96
|
+
| `x` | Delete character at cursor |
|
|
97
|
+
| `p` | Paste after cursor |
|
|
98
|
+
| `P` | Paste before cursor |
|
|
99
|
+
| `u` | Undo |
|
|
100
|
+
| `Ctrl-r` | Redo |
|
|
101
|
+
|
|
102
|
+
### Visual Mode
|
|
103
|
+
|
|
104
|
+
| Key | Action |
|
|
105
|
+
|-----|--------|
|
|
106
|
+
| `v` | Enter Visual mode |
|
|
107
|
+
| `V` | Enter Visual Line mode |
|
|
108
|
+
| `gv` | Reselect last visual selection |
|
|
109
|
+
|
|
110
|
+
### Tabs and Windows
|
|
111
|
+
|
|
112
|
+
| Key | Action |
|
|
113
|
+
|-----|--------|
|
|
114
|
+
| `gt` | Go to next tab |
|
|
115
|
+
| `gT` | Go to previous tab |
|
|
116
|
+
| `Ctrl-w h` | Go to left window |
|
|
117
|
+
| `Ctrl-w j` | Go to below window |
|
|
118
|
+
| `Ctrl-w k` | Go to above window |
|
|
119
|
+
| `Ctrl-w l` | Go to right window |
|
|
120
|
+
| `Ctrl-w w` | Cycle to next window |
|
|
121
|
+
| `Ctrl-w c` | Close current window |
|
|
122
|
+
| `Ctrl-w o` | Close all other windows |
|
|
123
|
+
|
|
124
|
+
### Registers
|
|
125
|
+
|
|
126
|
+
| Key | Action |
|
|
127
|
+
|-----|--------|
|
|
128
|
+
| `"a` - `"z` | Use named register |
|
|
129
|
+
| `""` | Use unnamed register |
|
|
130
|
+
| `"0` | Use yank register |
|
|
131
|
+
| `"1` - `"9` | Use delete history |
|
|
132
|
+
| `"_` | Use black hole register (discard) |
|
|
133
|
+
|
|
134
|
+
Example: `"ayy` yanks line to register `a`, `"ap` pastes from register `a`.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Insert Mode
|
|
139
|
+
|
|
140
|
+
| Key | Action |
|
|
141
|
+
|-----|--------|
|
|
142
|
+
| `Esc` | Return to Normal mode |
|
|
143
|
+
| `Ctrl-n` | Next completion candidate |
|
|
144
|
+
| `Ctrl-p` | Previous completion candidate |
|
|
145
|
+
| `Tab` | Accept completion |
|
|
146
|
+
| Arrow keys | Move cursor |
|
|
147
|
+
| `Backspace` | Delete character before cursor |
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Visual Mode
|
|
152
|
+
|
|
153
|
+
| Key | Action |
|
|
154
|
+
|-----|--------|
|
|
155
|
+
| `Esc` | Return to Normal mode |
|
|
156
|
+
| `d` | Delete selection |
|
|
157
|
+
| `c` | Change selection |
|
|
158
|
+
| `y` | Yank selection |
|
|
159
|
+
| `>` | Indent selection |
|
|
160
|
+
| `<` | Unindent selection |
|
|
161
|
+
| `*` | Search for selected text (forward) |
|
|
162
|
+
| `#` | Search for selected text (backward) |
|
|
163
|
+
| All motion keys | Extend selection |
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Command Mode
|
|
168
|
+
|
|
169
|
+
Enter with `:` from Normal mode.
|
|
170
|
+
|
|
171
|
+
### File Commands
|
|
172
|
+
|
|
173
|
+
| Command | Action |
|
|
174
|
+
|---------|--------|
|
|
175
|
+
| `:w` | Save file |
|
|
176
|
+
| `:w filename` | Save as filename |
|
|
177
|
+
| `:q` | Quit |
|
|
178
|
+
| `:q!` | Force quit |
|
|
179
|
+
| `:wq` | Save and quit |
|
|
180
|
+
| `:e filename` | Open file |
|
|
181
|
+
|
|
182
|
+
### Window Commands
|
|
183
|
+
|
|
184
|
+
| Command | Action |
|
|
185
|
+
|---------|--------|
|
|
186
|
+
| `:sp [filename]` | Horizontal split |
|
|
187
|
+
| `:vs [filename]` | Vertical split |
|
|
188
|
+
| `:close` | Close window |
|
|
189
|
+
| `:only` | Close all other windows |
|
|
190
|
+
|
|
191
|
+
### Tab Commands
|
|
192
|
+
|
|
193
|
+
| Command | Action |
|
|
194
|
+
|---------|--------|
|
|
195
|
+
| `:tabnew [filename]` | New tab |
|
|
196
|
+
| `:tabclose` | Close tab |
|
|
197
|
+
| `:tabnext` | Next tab |
|
|
198
|
+
| `:tabprev` | Previous tab |
|
|
199
|
+
| `:tabfirst` | First tab |
|
|
200
|
+
| `:tablast` | Last tab |
|
|
201
|
+
| `:tabmove N` | Move tab to position N |
|
|
202
|
+
|
|
203
|
+
### Shell Commands
|
|
204
|
+
|
|
205
|
+
| Command | Action |
|
|
206
|
+
|---------|--------|
|
|
207
|
+
| `:!cmd` | Run shell command |
|
|
208
|
+
|
|
209
|
+
### Navigation
|
|
210
|
+
|
|
211
|
+
| Command | Action |
|
|
212
|
+
|---------|--------|
|
|
213
|
+
| `:{number}` | Go to line number |
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Search Mode
|
|
218
|
+
|
|
219
|
+
Enter with `/` or `?` from Normal mode.
|
|
220
|
+
|
|
221
|
+
| Key | Action |
|
|
222
|
+
|-----|--------|
|
|
223
|
+
| `Enter` | Execute search |
|
|
224
|
+
| `Esc` | Cancel search |
|
|
225
|
+
| `Tab` | Cycle through completion |
|
|
226
|
+
| `Shift-Tab` | Cycle backward |
|
|
227
|
+
| `Backspace` | Delete character |
|
|
228
|
+
|
|
229
|
+
Search supports regular expressions.
|