channel.txt (10280B)
1 *channel.txt* Nvim 2 3 4 NVIM REFERENCE MANUAL by Thiago de Arruda 5 6 7 Nvim asynchronous IO *channel* 8 9 Type |gO| to see the table of contents. 10 11 ============================================================================== 12 1. Introduction *channel-intro* 13 14 Channels are Nvim's way of communicating with external processes. 15 16 There are several ways to open a channel: 17 18 1. Through stdin/stdout when `nvim` is started with `--headless` and a startup 19 script or `--cmd` command opens the stdio channel using |stdioopen()|. 20 2. Through stdin, stdout and stderr of a process spawned by |jobstart()|. 21 3. Through the PTY master end opened with `jobstart(…, {'pty': v:true})`. 22 4. By connecting to a TCP/IP socket or named pipe with |sockconnect()|. 23 5. By another process connecting to a socket listened to by Nvim. This only 24 supports RPC channels, see |rpc-connecting|. 25 26 Channels support multiple modes or protocols. In the most basic 27 mode of operation, raw bytes are read and written to the channel. 28 The |RPC| protocol, based on the msgpack-rpc standard, enables nvim and the 29 process at the other end to send remote calls and events to each other. 30 The builtin |terminal-emulator| is also implemented on top of PTY channels. 31 32 Channel Id *channel-id* 33 34 Each channel is identified by an integer id, unique for the life of the 35 current Nvim session. Functions like |stdioopen()| return channel ids; 36 functions like |chansend()| consume channel ids. 37 38 ============================================================================== 39 2. Reading and writing raw bytes *channel-bytes* 40 41 Channels opened by Vimscript functions operate with raw bytes by default. For 42 a job channel using RPC, bytes can still be read over its stderr. Similarly, 43 only bytes can be written to Nvim's own stderr. 44 45 *channel-callback* 46 - on_stdout({chan-id}, {data}, {name}) *on_stdout* 47 - on_stderr({chan-id}, {data}, {name}) *on_stderr* 48 - on_stdin({chan-id}, {data}, {name}) *on_stdin* 49 - on_data({chan-id}, {data}, {name}) *on_data* 50 51 Scripts can react to channel activity (received data) via callback 52 functions assigned to the `on_stdout`, `on_stderr`, `on_stdin`, or 53 `on_data` option keys. Callbacks should be fast: avoid potentially 54 slow/expensive work. 55 56 Parameters: ~ 57 - {chan-id} Channel handle. |channel-id| 58 - {data} Raw data (|readfile()|-style list of strings) read from 59 the channel. EOF is a single-item list: `['']`. First and 60 last items may be partial lines! |channel-lines| 61 - {name} Stream name (string) like "stdout", so the same function 62 can handle multiple streams. Event names depend on how the 63 channel was opened and in what mode/protocol. 64 65 *channel-buffered* 66 The callback is invoked immediately as data is available, where 67 a single-item list `['']` indicates EOF (stream closed). Alternatively 68 set the `stdout_buffered`, `stderr_buffered`, `stdin_buffered`, or 69 `data_buffered` option keys to invoke the callback only after all output 70 was gathered and the stream was closed. 71 *E5210* 72 If a buffering mode is used without a callback, the data is saved in the 73 stream {name} key of the options dict. It is an error if the key exists. 74 75 *channel-lines* 76 Stream event handlers receive data as it becomes available from the OS, 77 thus the first and last items in the {data} list may be partial lines. 78 Empty string completes the previous partial line. Examples (not including 79 the final `['']` emitted at EOF): 80 - `foobar` may arrive as `['fo'], ['obar']` 81 - `foo\nbar` may arrive as 82 - `['foo','bar']` 83 - or `['foo',''], ['bar']` 84 - or `['foo'], ['','bar']` 85 - or `['fo'], ['o','bar']` 86 87 There are two ways to deal with this: 88 - 1. To wait for the entire output, use |channel-buffered| mode. 89 - 2. To read line-by-line, use the following code: >vim 90 let s:lines = [''] 91 func! s:on_event(job_id, data, event) dict 92 let eof = (a:data == ['']) 93 " Complete the previous line. 94 let s:lines[-1] .= a:data[0] 95 " Append (last item may be a partial line, until EOF). 96 call extend(s:lines, a:data[1:]) 97 endf 98 < 99 100 If the callback functions are |Dictionary-function|s, |self| refers to the 101 options dictionary containing the callbacks. |Partial|s can also be used as 102 callbacks. 103 104 Data can be sent to the channel using the |chansend()| function. Here is a 105 simple example, echoing some data through a cat-process: 106 >vim 107 function! s:OnEvent(id, data, event) dict 108 let str = join(a:data, "\n") 109 echomsg str 110 endfunction 111 let id = jobstart(['cat'], {'on_stdout': function('s:OnEvent') } ) 112 call chansend(id, "hello!") 113 < 114 115 Here is an example of setting a buffer to the result of grep, but only after 116 all data has been processed: 117 >vim 118 function! s:OnEvent(id, data, event) dict 119 call nvim_buf_set_lines(2, 0, -1, v:true, a:data) 120 endfunction 121 let id = jobstart(['grep', '^[0-9]'], { 'on_stdout': function('s:OnEvent'), 122 \ 'stdout_buffered':v:true } ) 123 124 call chansend(id, "stuff\n10 PRINT \"NVIM\"\nxx") 125 " no output is received, buffer is empty 126 127 call chansend(id, "xx\n20 GOTO 10\nzz\n") 128 call chanclose(id, 'stdin') 129 " now buffer has result 130 < 131 For additional examples with jobs, see |job-control|. 132 133 *channel-pty* 134 Special case: PTY channels opened with `jobstart(..., {'pty': v:true})` do not 135 preprocess ANSI escape sequences, these will be sent raw to the callback. 136 However, change of PTY size can be signaled to the slave using |jobresize()|. 137 See also |terminal-emulator|. 138 139 Terminal characteristics (termios) for |:terminal| and PTY channels are copied 140 from the host TTY, or if Nvim is |--headless| it uses default values: >vim 141 :echo system('nvim --headless +"te stty -a" +"sleep 1" +"1,/^$/print" +q') 142 143 ============================================================================== 144 3. Communicating with msgpack RPC *channel-rpc* 145 146 When channels are opened with the `rpc` option set to true, the channel can be 147 used for remote method calls in both directions, see |msgpack-rpc|. Note that 148 rpc channels are implicitly trusted and the process at the other end can 149 invoke any |API| function! 150 151 ============================================================================== 152 4. Standard IO channel *channel-stdio* 153 154 Nvim uses stdin/stdout to interact with the user over the terminal interface 155 (TUI). If Nvim is |--headless| the TUI is not started and stdin/stdout can be 156 used as a channel. See also |--embed|. 157 158 Call |stdioopen()| during |startup| to open the stdio channel as |channel-id| 1. 159 Nvim's stderr is always available as |v:stderr|, a write-only bytes channel. 160 161 Example: >vim 162 func! OnEvent(id, data, event) 163 if a:data == [""] 164 quit 165 end 166 call chansend(a:id, map(a:data, {i,v -> toupper(v)})) 167 endfunc 168 call stdioopen({'on_stdin': 'OnEvent'}) 169 < 170 Put this in `uppercase.vim` and run: >bash 171 nvim --headless --cmd "source uppercase.vim" 172 173 ============================================================================== 174 5. Using a prompt buffer *prompt-buffer* 175 176 Prompt buffers provide a "prompt" interface: they are like regular buffers, 177 except only the last section of the buffer is editable, and the user can 178 "submit" the prompt by hitting Enter. Useful for implementing: 179 180 - chat UI 181 - REPL or shell plugins 182 - advanced "picker" plugins 183 184 A prompt buffer is created by setting 'buftype' to "prompt". You would 185 normally only do that in a newly created buffer: >vim 186 187 :set buftype=prompt 188 189 The user can edit and input text at the end of the buffer. Pressing Enter in 190 the input section invokes the |prompt_setcallback()| callback, which is 191 typically expected to process the prompt and show results by appending to the 192 buffer. To input multiline text, use *Shift-<Enter>* to add a new line without 193 submitting the prompt, or just |put| or |paste| multiline text. 194 195 Only the section starting with the mark |':| of the buffer (after the prompt) 196 is editable. The rest of the buffer is not modifiable with Normal mode 197 commands, though it can be modified by functions such as |append()|. Using 198 other commands may mess up the buffer. 199 200 After setting `buftype=prompt`: 201 - Nvim unsets the 'comments' option. 202 - Nvim does not automatically start Insert mode (use `:startinsert` if you 203 want to enter Insert mode) 204 205 The prompt prefix defaults to "% ", but can be set with |prompt_setprompt()|. 206 You can get the effective prompt prefix for with |prompt_getprompt()|. 207 208 The user can go to Normal mode and navigate through the buffer. This can be 209 useful to see older output or copy text. 210 211 By default during prompt insert-mode, the CTRL-W key can be used to start 212 a window command, such as CTRL-W w to switch to the next window. (Use 213 Shift-CTRL-W to delete a word). When leaving the window Insert mode will be 214 stopped. When coming back to the prompt window Insert mode will be restored. 215 216 Any command that starts Insert mode, such as "a", "i", "A" and "I", will move 217 the cursor to the last line. "A" will move to the end of the line, "I" to the 218 start of the line. 219 220 Example: start a shell in the background and prompt for the next shell 221 command, displaying shell output above the prompt: >lua 222 223 local shell_job 224 225 -- Handles a line of user input. 226 local function on_submit(text) 227 -- Send the text to the shell with Enter appended. 228 vim.api.nvim_chan_send(shell_job, text .. "\n") 229 end 230 231 -- Handles output from the shell. 232 local function on_output(_, msg, _) 233 -- Add shell output above the prompt. 234 local input_start = vim.api.nvim_buf_get_mark(0, ":")[1] 235 vim.fn.append(input_start - 1, msg) 236 end 237 238 -- Handles the shell exit. 239 local function on_exit(_, _, _) 240 vim.cmd("quit!") 241 end 242 243 -- Start a shell in the background. 244 shell_job = vim.fn.jobstart({ "/bin/sh" }, { 245 on_stdout = on_output, 246 on_stderr = on_output, 247 on_exit = on_exit, 248 }) 249 250 vim.cmd("new") 251 vim.bo.buftype = "prompt" 252 local buf = vim.api.nvim_get_current_buf() 253 vim.fn.prompt_setcallback(buf, on_submit) 254 vim.fn.prompt_setprompt(buf, "shell command: ") 255 256 -- Start accepting shell commands. 257 vim.cmd("startinsert") 258 < 259 260 vim:tw=78:ts=8:et:sw=4:ft=help:norl: