• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..31-Dec-2021-

api/H31-Dec-2021-10,2106,752

eval/H31-Dec-2021-23,68617,647

event/H31-Dec-2021-2,4141,786

generators/H31-Dec-2021-2,1921,866

lib/H31-Dec-2021-1,9761,316

lua/H31-Dec-2021-5,6894,363

msgpack_rpc/H31-Dec-2021-1,6831,338

os/H03-May-2022-7,6275,436

po/H07-May-2022-222,640168,525

testdir/H03-May-2022-82,80872,551

tui/H31-Dec-2021-5,3682,524

viml/parser/H31-Dec-2021-3,7172,904

README.mdH A D31-Dec-202112.9 KiB413312

arabic.cH A D31-Dec-202127.1 KiB1,053915

arabic.hH A D31-Dec-2021374 1711

ascii.hH A D31-Dec-20214.9 KiB190128

assert.hH A D31-Dec-20215.7 KiB17083

aucmd.cH A D31-Dec-20213.4 KiB12391

aucmd.hH A D31-Dec-2021167 127

auevents.luaH A D31-Dec-20217.4 KiB144141

autocmd.cH A D31-Dec-202159.4 KiB2,0861,453

autocmd.hH A D31-Dec-20213.2 KiB8254

buffer.cH A D31-Dec-2021166.5 KiB5,6153,911

buffer.hH A D31-Dec-20214.5 KiB13795

buffer_defs.hH A D31-Dec-202158.7 KiB1,474914

buffer_updates.cH A D31-Dec-202112.4 KiB411296

buffer_updates.hH A D31-Dec-2021238 128

change.cH A D31-Dec-202159.8 KiB1,8661,279

change.hH A D31-Dec-2021233 128

channel.cH A D31-Dec-202124.2 KiB920718

channel.hH A D31-Dec-20212.9 KiB151121

charset.cH A D31-Dec-202145.2 KiB1,7101,068

charset.hH A D31-Dec-20211.7 KiB5733

context.cH A D31-Dec-20219.6 KiB386256

context.hH A D31-Dec-20211.1 KiB4838

cursor.cH A D31-Dec-202113.7 KiB525337

cursor.hH A D31-Dec-2021194 138

cursor_shape.cH A D31-Dec-202111.8 KiB365303

cursor_shape.hH A D31-Dec-20212.5 KiB6251

debugger.cH A D31-Dec-202122.7 KiB838675

debugger.hH A D31-Dec-2021210 128

decoration.cH A D31-Dec-202113.8 KiB475395

decoration.hH A D31-Dec-20212.2 KiB10380

diff.cH A D31-Dec-202184.7 KiB3,1602,211

diff.hH A D31-Dec-2021474 1812

digraph.cH A D31-Dec-202147.7 KiB1,9741,805

digraph.hH A D31-Dec-2021208 118

edit.cH A D31-Dec-2021272.3 KiB9,4296,690

edit.hH A D31-Dec-20211.7 KiB5335

eval.cH A D31-Dec-2021311.8 KiB11,3568,435

eval.hH A D31-Dec-20217.1 KiB269204

eval.luaH A D31-Dec-202113.3 KiB432414

ex_cmds.cH A D31-Dec-2021186.3 KiB6,1724,397

ex_cmds.hH A D31-Dec-20211.4 KiB3827

ex_cmds.luaH A D31-Dec-202173.1 KiB3,3433,330

ex_cmds2.cH A D31-Dec-202187.8 KiB3,1982,402

ex_cmds2.hH A D31-Dec-20211.8 KiB4834

ex_cmds_defs.hH A D31-Dec-202110.8 KiB233167

ex_docmd.cH A D31-Dec-2021270.3 KiB10,1547,734

ex_docmd.hH A D31-Dec-20211.2 KiB3828

ex_eval.cH A D31-Dec-202168.8 KiB2,1111,226

ex_eval.hH A D31-Dec-20213.2 KiB8551

ex_getln.cH A D31-Dec-2021193.8 KiB6,7064,959

ex_getln.hH A D31-Dec-20212.1 KiB6552

ex_session.cH A D31-Dec-202131.6 KiB1,107799

ex_session.hH A D31-Dec-2021218 148

extmark.cH A D31-Dec-202123.5 KiB718534

extmark.hH A D31-Dec-20211.5 KiB8666

extmark_defs.hH A D31-Dec-20211 KiB4328

file_search.cH A D31-Dec-202151.4 KiB1,6951,055

file_search.hH A D31-Dec-2021480 1812

fileio.cH A D31-Dec-2021172.6 KiB5,7674,077

fileio.hH A D31-Dec-2021831 2518

fold.cH A D31-Dec-202195.9 KiB3,3462,175

fold.hH A D31-Dec-2021803 3118

func_attr.hH A D31-Dec-20217 KiB254161

garray.cH A D31-Dec-20215.3 KiB228124

garray.hH A D31-Dec-20212.3 KiB7447

getchar.cH A D31-Dec-2021132.5 KiB4,5853,096

getchar.hH A D31-Dec-20212.1 KiB7545

gettext.hH A D31-Dec-2021780 2923

globals.hH A D31-Dec-202148.1 KiB1,051598

grid_defs.hH A D31-Dec-20213.8 KiB11545

hardcopy.cH A D31-Dec-202190.6 KiB3,1872,338

hardcopy.hH A D31-Dec-20211.8 KiB8564

hashtab.cH A D31-Dec-202113.4 KiB452243

hashtab.hH A D31-Dec-20213.2 KiB9839

highlight.cH A D31-Dec-202127.9 KiB980774

highlight.hH A D31-Dec-2021578 2317

highlight_defs.hH A D31-Dec-20216.2 KiB211186

iconv.hH A D31-Dec-2021364 2115

if_cscope.cH A D31-Dec-202154 KiB2,0781,507

if_cscope.hH A D31-Dec-2021260 118

if_cscope_defs.hH A D31-Dec-20211.8 KiB6544

indent.cH A D31-Dec-202121.8 KiB783557

indent.hH A D31-Dec-2021472 1611

indent_c.cH A D31-Dec-2021109.6 KiB3,7162,333

indent_c.hH A D31-Dec-2021179 107

keymap.cH A D31-Dec-202132.8 KiB996760

keymap.hH A D31-Dec-202117.8 KiB486307

log.cH A D31-Dec-20218.9 KiB336249

log.hH A D31-Dec-20212.4 KiB9173

macros.hH A D31-Dec-20217.2 KiB230135

main.cH A D31-Dec-202159.2 KiB1,9991,482

main.hH A D31-Dec-20211.7 KiB4834

map.cH A D31-Dec-20215.6 KiB201171

map.hH A D31-Dec-20212.8 KiB9471

map_defs.hH A D31-Dec-2021218 138

mark.cH A D31-Dec-202146.4 KiB1,6751,202

mark.hH A D31-Dec-20213.2 KiB12498

mark_defs.hH A D31-Dec-20211.3 KiB4922

marktree.cH A D31-Dec-202131.8 KiB1,193943

marktree.hH A D31-Dec-20211.7 KiB8860

math.cH A D31-Dec-2021741 4031

math.hH A D31-Dec-2021140 86

mbyte.cH A D31-Dec-202174.9 KiB2,6841,879

mbyte.hH A D31-Dec-20212.4 KiB8956

memfile.cH A D31-Dec-202128.8 KiB958610

memfile.hH A D31-Dec-2021505 1712

memfile_defs.hH A D31-Dec-20214.5 KiB10853

memline.cH A D31-Dec-2021132.2 KiB4,3232,905

memline.hH A D31-Dec-2021276 129

memline_defs.hH A D31-Dec-20212.7 KiB7340

memory.cH A D31-Dec-202118.8 KiB713406

memory.hH A D31-Dec-20211.4 KiB5532

menu.cH A D31-Dec-202143 KiB1,6611,212

menu.hH A D31-Dec-2021954 3218

message.cH A D31-Dec-202199.2 KiB3,7292,627

message.hH A D31-Dec-20212.1 KiB7744

misc1.cH A D31-Dec-202127 KiB1,062717

misc1.hH A D31-Dec-2021520 1813

mouse.cH A D31-Dec-202122.3 KiB779568

mouse.hH A D31-Dec-20211.7 KiB5034

move.cH A D31-Dec-202167.2 KiB2,3011,687

move.hH A D31-Dec-2021185 128

normal.cH A D31-Dec-2021241.1 KiB8,4276,087

normal.hH A D31-Dec-20213.5 KiB8455

ops.cH A D31-Dec-2021190.1 KiB6,4574,726

ops.hH A D31-Dec-20214.8 KiB12995

option.cH A D31-Dec-2021238 KiB8,0316,291

option.hH A D31-Dec-20211.1 KiB3121

option_defs.hH A D31-Dec-202135 KiB909821

options.luaH A D31-Dec-202188.4 KiB2,9322,892

os_unix.cH A D31-Dec-20211.6 KiB7662

os_unix.hH A D31-Dec-2021222 118

path.cH A D31-Dec-202167.9 KiB2,4161,606

path.hH A D31-Dec-20211.9 KiB4333

plines.cH A D31-Dec-202113.3 KiB511324

plines.hH A D31-Dec-2021171 107

popupmnu.cH A D31-Dec-202127.8 KiB945717

popupmnu.hH A D31-Dec-2021588 2317

pos.hH A D31-Dec-2021891 4421

profile.cH A D31-Dec-20217.5 KiB292145

profile.hH A D31-Dec-2021306 1812

quickfix.cH A D31-Dec-2021199.7 KiB7,1525,240

quickfix.hH A D31-Dec-2021297 1510

rbuffer.cH A D31-Dec-20215.8 KiB228162

rbuffer.hH A D31-Dec-20213.2 KiB9244

regexp.cH A D31-Dec-2021212.7 KiB7,4785,639

regexp.hH A D31-Dec-2021728 2516

regexp_defs.hH A D31-Dec-20214.8 KiB16990

regexp_nfa.cH A D31-Dec-2021188.4 KiB6,8435,338

runtime.cH A D31-Dec-202138.6 KiB1,253926

runtime.hH A D31-Dec-20211.1 KiB4028

screen.cH A D31-Dec-2021243.1 KiB7,8895,750

screen.hH A D31-Dec-20212.3 KiB6939

search.cH A D31-Dec-2021159.7 KiB5,4844,040

search.hH A D31-Dec-20213.8 KiB10173

sha256.cH A D31-Dec-202110.5 KiB352275

sha256.hH A D31-Dec-2021428 2216

shada.cH A D31-Dec-2021149.5 KiB4,2263,517

shada.hH A D31-Dec-2021561 1914

sign.cH A D31-Dec-202155.3 KiB2,0951,577

sign.hH A D31-Dec-2021253 1510

sign_defs.hH A D31-Dec-20211.5 KiB5838

spell.cH A D31-Dec-2021220.2 KiB7,3335,171

spell.hH A D31-Dec-2021275 1511

spell_defs.hH A D31-Dec-202113.1 KiB295187

spellfile.cH A D31-Dec-2021183.9 KiB5,8894,163

spellfile.hH A D31-Dec-2021267 1410

state.cH A D31-Dec-20215.3 KiB205156

state.hH A D31-Dec-2021409 2114

strings.cH A D31-Dec-202144.8 KiB1,4671,037

strings.hH A D31-Dec-2021866 3218

syntax.cH A D31-Dec-2021274.6 KiB8,7656,498

syntax.hH A D31-Dec-20211.7 KiB4636

syntax_defs.hH A D31-Dec-20212.5 KiB7046

tag.cH A D31-Dec-2021103.2 KiB3,4952,523

tag.hH A D31-Dec-20211.9 KiB5537

terminal.cH A D31-Dec-202142.5 KiB1,5951,249

terminal.hH A D31-Dec-2021655 2721

types.hH A D31-Dec-2021823 3617

ugrid.cH A D31-Dec-20212.2 KiB10382

ugrid.hH A D31-Dec-2021734 3929

ui.cH A D31-Dec-202114.2 KiB610509

ui.hH A D31-Dec-20211.4 KiB8065

ui_bridge.cH A D31-Dec-20216.8 KiB224186

ui_bridge.hH A D31-Dec-20211.3 KiB4630

ui_compositor.cH A D31-Dec-202120.5 KiB669527

ui_compositor.hH A D31-Dec-2021227 118

undo.cH A D31-Dec-202191.8 KiB3,2352,274

undo.hH A D31-Dec-2021200 118

undo_defs.hH A D31-Dec-20212.8 KiB8467

version.cH A D31-Dec-202124.9 KiB2,3332,193

version.hH A D31-Dec-2021938 3317

vim.hH A D31-Dec-20219.7 KiB318195

window.cH A D31-Dec-2021191.3 KiB7,1805,242

window.hH A D31-Dec-20211.3 KiB3924

README.md

1Nvim core
2=========
3
4Module-specific details are documented at the top of each module (`terminal.c`,
5`screen.c`, …).
6
7See `:help dev` for guidelines.
8
9Filename conventions
10--------------------
11
12The source files use extensions to hint about their purpose.
13
14- `*.c`, `*.generated.c` - full C files, with all includes, etc.
15- `*.c.h` - parametrized C files, contain all necessary includes, but require
16  defining macros before actually using. Example: `typval_encode.c.h`
17- `*.h` - full headers, with all includes. Does *not* apply to `*.generated.h`.
18- `*.h.generated.h` - exported functions’ declarations.
19- `*.c.generated.h` - static functions’ declarations.
20
21Logs
22----
23
24Low-level log messages sink to `$NVIM_LOG_FILE`.
25
26UI events are logged at DEBUG level (`DEBUG_LOG_LEVEL`).
27
28    rm -rf build/
29    make CMAKE_EXTRA_FLAGS="-DMIN_LOG_LEVEL=0"
30
31Use `LOG_CALLSTACK()` (Linux only) to log the current stacktrace. To log to an
32alternate file (e.g. stderr) use `LOG_CALLSTACK_TO_FILE(FILE*)`. Requires
33`-no-pie` ([ref](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=860394#15)):
34
35    rm -rf build/
36    make CMAKE_EXTRA_FLAGS="-DMIN_LOG_LEVEL=0 -DCMAKE_C_FLAGS=-no-pie"
37
38Many log messages have a shared prefix, such as "UI" or "RPC". Use the shell to
39filter the log, e.g. at DEBUG level you might want to exclude UI messages:
40
41    tail -F ~/.cache/nvim/log | cat -v | stdbuf -o0 grep -v UI | stdbuf -o0 tee -a log
42
43Build with ASAN
44---------------
45
46Building Nvim with Clang sanitizers (Address Sanitizer: ASan, Undefined
47Behavior Sanitizer: UBSan, Memory Sanitizer: MSan, Thread Sanitizer: TSan) is
48a good way to catch undefined behavior, leaks and other errors as soon as they
49happen.  It's significantly faster than Valgrind.
50
51Requires clang 3.4 or later, and `llvm-symbolizer` must be in `$PATH`:
52
53    clang --version
54
55Build Nvim with sanitizer instrumentation (choose one):
56
57    CC=clang make CMAKE_EXTRA_FLAGS="-DCLANG_ASAN_UBSAN=ON"
58    CC=clang make CMAKE_EXTRA_FLAGS="-DCLANG_MSAN=ON"
59    CC=clang make CMAKE_EXTRA_FLAGS="-DCLANG_TSAN=ON"
60
61Create a directory to store logs:
62
63    mkdir -p "$HOME/logs"
64
65Configure the sanitizer(s) via these environment variables:
66
67    # Change to detect_leaks=1 to detect memory leaks (slower).
68    export ASAN_OPTIONS="detect_leaks=0:log_path=$HOME/logs/asan"
69    # Show backtraces in the logs.
70    export UBSAN_OPTIONS=print_stacktrace=1
71    export MSAN_OPTIONS="log_path=${HOME}/logs/tsan"
72    export TSAN_OPTIONS="log_path=${HOME}/logs/tsan"
73
74Logs will be written to `${HOME}/logs/*san.PID` then.
75
76For more information: https://github.com/google/sanitizers/wiki/SanitizerCommonFlags
77
78Debug: Performance
79------------------
80
81### Profiling (easy)
82
83For debugging performance bottlenecks in any code, there is a simple (and very
84effective) approach:
85
861. Run the slow code in a loop.
872. Break execution ~5 times and save the stacktrace.
883. The cause of the bottleneck will (almost always) appear in most of the stacktraces.
89
90### Profiling (fancy)
91
92For more advanced profiling, consider `perf` + `flamegraph`.
93
94### USDT profiling (powerful)
95
96Or you can use USDT probes via `NVIM_PROBE` ([#12036](https://github.com/neovim/neovim/pull/12036)).
97
98> USDT is basically a way to define stable probe points in userland binaries.
99> The benefit of bcc is the ability to define logic to go along with the probe
100> points.
101
102Tools:
103- bpftrace provides an awk-like language to the kernel bytecode, BPF.
104- BCC provides a subset of C. Provides more complex logic than bpftrace, but takes a bit more effort.
105
106Example using bpftrace to track slow vim functions, and print out any files
107that were opened during the trace. At the end, it prints a histogram of
108function timing:
109
110    #!/usr/bin/env bpftrace
111
112    BEGIN {
113      @depth = -1;
114    }
115
116    tracepoint:sched:sched_process_fork /@pidmap[args->parent_pid]/ {
117      @pidmap[args->child_pid] = 1;
118    }
119
120    tracepoint:sched:sched_process_exit /@pidmap[args->pid]/ {
121      delete(@pidmap[args->pid]);
122    }
123
124    usdt:build/bin/nvim:neovim:eval__call_func__entry {
125        @pidmap[pid] = 1;
126        @depth++;
127        @funcentry[@depth] = nsecs;
128    }
129
130    usdt:build/bin/nvim:neovim:eval__call_func__return {
131        $func = str(arg0);
132        $msecs = (nsecs - @funcentry[@depth]) / 1000000;
133
134        @time_histo = hist($msecs);
135
136        if ($msecs >= 1000) {
137          printf("%u ms for %s\n", $msecs, $func);
138          print(@files);
139        }
140
141        clear(@files);
142        delete(@funcentry[@depth]);
143        @depth--;
144    }
145
146    tracepoint:syscalls:sys_enter_open,
147    tracepoint:syscalls:sys_enter_openat {
148      if (@pidmap[pid] == 1 && @depth >= 0) {
149        @files[str(args->filename)] = count();
150      }
151    }
152
153    END {
154      clear(@depth);
155    }
156
157    $ sudo bpftrace funcslower.bt
158    1527 ms for Slower
159    @files[/usr/lib/libstdc++.so.6]: 2
160    @files[/etc/fish/config.fish]: 2
161    <snip>
162
163    ^C
164    @time_histo:
165    [0]                71430 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
166    [1]                  346 |                                                    |
167    [2, 4)               208 |                                                    |
168    [4, 8)                91 |                                                    |
169    [8, 16)               22 |                                                    |
170    [16, 32)              85 |                                                    |
171    [32, 64)               7 |                                                    |
172    [64, 128)              0 |                                                    |
173    [128, 256)             0 |                                                    |
174    [256, 512)             6 |                                                    |
175    [512, 1K)              1 |                                                    |
176    [1K, 2K)               5 |                                                    |
177
178Debug: TUI
179----------
180
181### TUI troubleshoot
182
183Nvim logs its internal terminfo state at 'verbose' level 3.  This makes it
184possible to see exactly what terminfo values Nvim is using on any system.
185
186    nvim -V3log
187
188### TUI trace
189
190The ancient `script` command is still the "state of the art" for tracing
191terminal behavior. The libvterm `vterm-dump` utility formats the result for
192human-readability.
193
194Record a Nvim terminal session and format it with `vterm-dump`:
195
196    script foo
197    ./build/bin/nvim -u NONE
198    # Exit the script session with CTRL-d
199
200    # Use `vterm-dump` utility to format the result.
201    ./.deps/usr/bin/vterm-dump foo > bar
202
203Then you can compare `bar` with another session, to debug TUI behavior.
204
205### TUI redraw
206
207Set the 'writedelay' option to see where and when the UI is painted.
208
209    :set writedelay=1
210
211### Terminal reference
212
213- `man terminfo`
214- http://bazaar.launchpad.net/~libvterm/libvterm/trunk/view/head:/doc/seqs.txt
215- http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
216
217Nvim lifecycle
218--------------
219
220Following describes how Nvim processes input.
221
222Consider a typical Vim-like editing session:
223
22401. Vim displays the welcome screen
22502. User types: `:`
22603. Vim enters command-line mode
22704. User types: `edit README.txt<CR>`
22805. Vim opens the file and returns to normal mode
22906. User types: `G`
23007. Vim navigates to the end of the file
23109. User types: `5`
23210. Vim enters count-pending mode
23311. User types: `d`
23412. Vim enters operator-pending mode
23513. User types: `w`
23614. Vim deletes 5 words
23715. User types: `g`
23816. Vim enters the "g command mode"
23917. User types: `g`
24018. Vim goes to the beginning of the file
24119. User types: `i`
24220. Vim enters insert mode
24321. User types: `word<ESC>`
24422. Vim inserts "word" at the beginning and returns to normal mode
245
246Note that we split user actions into sequences of inputs that change the state
247of the editor. While there's no documentation about a "g command mode" (step
24816), internally it is implemented similarly to "operator-pending mode".
249
250From this we can see that Vim has the behavior of an input-driven state machine
251(more specifically, a pushdown automaton since it requires a stack for
252transitioning back from states). Assuming each state has a callback responsible
253for handling keys, this pseudocode represents the main program loop:
254
255```py
256def state_enter(state_callback, data):
257  do
258    key = readkey()                 # read a key from the user
259  while state_callback(data, key)   # invoke the callback for the current state
260```
261
262That is, each state is entered by calling `state_enter` and passing a
263state-specific callback and data. Here is a high-level pseudocode for a program
264that implements something like the workflow described above:
265
266```py
267def main()
268  state_enter(normal_state, {}):
269
270def normal_state(data, key):
271  if key == ':':
272    state_enter(command_line_state, {})
273  elif key == 'i':
274    state_enter(insert_state, {})
275  elif key == 'd':
276    state_enter(delete_operator_state, {})
277  elif key == 'g':
278    state_enter(g_command_state, {})
279  elif is_number(key):
280    state_enter(get_operator_count_state, {'count': key})
281  elif key == 'G'
282    jump_to_eof()
283  return true
284
285def command_line_state(data, key):
286  if key == '<cr>':
287    if data['input']:
288      execute_ex_command(data['input'])
289    return false
290  elif key == '<esc>'
291    return false
292
293  if not data['input']:
294    data['input'] = ''
295
296  data['input'] += key
297  return true
298
299def delete_operator_state(data, key):
300  count = data['count'] or 1
301  if key == 'w':
302    delete_word(count)
303  elif key == '$':
304    delete_to_eol(count)
305  return false  # return to normal mode
306
307def g_command_state(data, key):
308  if key == 'g':
309    go_top()
310  elif key == 'v':
311    reselect()
312  return false  # return to normal mode
313
314def get_operator_count_state(data, key):
315  if is_number(key):
316    data['count'] += key
317    return true
318  unshift_key(key)  # return key to the input buffer
319  state_enter(delete_operator_state, data)
320  return false
321
322def insert_state(data, key):
323  if key == '<esc>':
324    return false  # exit insert mode
325  self_insert(key)
326  return true
327```
328
329The above gives an idea of how Nvim is organized internally. Some states like
330the `g_command_state` or `get_operator_count_state` do not have a dedicated
331`state_enter` callback, but are implicitly embedded into other states (this
332will change later as we continue the refactoring effort). To start reading the
333actual code, here's the recommended order:
334
3351. `state_enter()` function (state.c). This is the actual program loop,
336   note that a `VimState` structure is used, which contains function pointers
337   for the callback and state data.
3382. `main()` function (main.c). After all startup, `normal_enter` is called
339   at the end of function to enter normal mode.
3403. `normal_enter()` function (normal.c) is a small wrapper for setting
341   up the NormalState structure and calling `state_enter`.
3424. `normal_check()` function (normal.c) is called before each iteration of
343   normal mode.
3445. `normal_execute()` function (normal.c) is called when a key is read in normal
345   mode.
346
347The basic structure described for normal mode in 3, 4 and 5 is used for other
348modes managed by the `state_enter` loop:
349
350- command-line mode: `command_line_{enter,check,execute}()`(`ex_getln.c`)
351- insert mode: `insert_{enter,check,execute}()`(`edit.c`)
352- terminal mode: `terminal_{enter,execute}()`(`terminal.c`)
353
354Async event support
355-------------------
356
357One of the features Nvim added is the support for handling arbitrary
358asynchronous events, which can include:
359
360- RPC requests
361- job control callbacks
362- timers
363
364Nvim implements this functionality by entering another event loop while
365waiting for characters, so instead of:
366
367```py
368def state_enter(state_callback, data):
369  do
370    key = readkey()                 # read a key from the user
371  while state_callback(data, key)   # invoke the callback for the current state
372```
373
374Nvim program loop is more like:
375
376```py
377def state_enter(state_callback, data):
378  do
379    event = read_next_event()       # read an event from the operating system
380  while state_callback(data, event) # invoke the callback for the current state
381```
382
383where `event` is something the operating system delivers to us, including (but
384not limited to) user input. The `read_next_event()` part is internally
385implemented by libuv, the platform layer used by Nvim.
386
387Since Nvim inherited its code from Vim, the states are not prepared to receive
388"arbitrary events", so we use a special key to represent those (When a state
389receives an "arbitrary event", it normally doesn't do anything other update the
390screen).
391
392Main loop
393---------
394
395The `Loop` structure (which describes `main_loop`) abstracts multiple queues
396into one loop:
397
398    uv_loop_t uv;
399    MultiQueue *events;
400    MultiQueue *thread_events;
401    MultiQueue *fast_events;
402
403`loop_poll_events` checks `Loop.uv` and `Loop.fast_events` whenever Nvim is
404idle, and also at `os_breakcheck` intervals.
405
406MultiQueue is cool because you can attach throw-away "child queues" trivially.
407For example `do_os_system()` does this (for every spawned process!) to
408automatically route events onto the `main_loop`:
409
410    Process *proc = &uvproc.process;
411    MultiQueue *events = multiqueue_new_child(main_loop.events);
412    proc->events = events;
413