neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

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: