diff options
Diffstat (limited to 'runtime/doc/terminal.txt')
-rw-r--r-- | runtime/doc/terminal.txt | 633 |
1 files changed, 633 insertions, 0 deletions
diff --git a/runtime/doc/terminal.txt b/runtime/doc/terminal.txt new file mode 100644 index 0000000000..5d8dd484f9 --- /dev/null +++ b/runtime/doc/terminal.txt @@ -0,0 +1,633 @@ +*terminal.txt* Nvim + + + NVIM REFERENCE MANUAL by Thiago de Arruda + + +Terminal emulator *terminal* *terminal-emulator* + +Nvim embeds a VT220/xterm terminal emulator based on libvterm. The terminal is +presented as a special 'buftype', asynchronously updated as data is received +from the connected program. + +Terminal buffers behave like normal buffers, except: +- With 'modifiable', lines can be edited but not deleted. +- 'scrollback' controls how many lines are kept. +- Output is followed ("tailed") if cursor is on the last line. +- 'modified' is the default. You can set 'nomodified' to avoid a warning when + closing the terminal buffer. +- 'bufhidden' defaults to "hide". + + Type |gO| to see the table of contents. + +============================================================================== +Start *terminal-start* + +There are several ways to create a terminal buffer: + +- Run the |:terminal| command. +- Call the |nvim_open_term()| or |termopen()| function. +- Edit a "term://" buffer. Examples: >vim + :edit term://bash + :vsplit term://top + +< Note: To open a "term://" buffer from an autocmd, the |autocmd-nested| + modifier is required. >vim + autocmd VimEnter * ++nested split term://sh +< (This is only mentioned for reference; use |:terminal| instead.) + +When the terminal starts, the buffer contents are updated and the buffer is +named in the form of `term://{cwd}//{pid}:{cmd}`. This naming scheme is used +by |:mksession| to restore a terminal buffer (by restarting the {cmd}). + +The terminal environment is initialized as in |jobstart-env|. + +============================================================================== +Input *terminal-input* + +To send input, enter |Terminal-mode| with |i|, |I|, |a|, |A| or +|:startinsert|. In this mode all keys except <C-\> are sent to the underlying +program. If <C-\> is pressed, the next key is sent unless it is <C-N> or <C-O>. +Use <C-\><C-N> to return to normal mode. |CTRL-\_CTRL-N| +Use <C-\><C-O> to execute one normal mode command and then return to terminal +mode. *t_CTRL-\_CTRL-O* + +Terminal-mode forces these local options: + + 'cursorlineopt' = number + 'nocursorcolumn' + 'scrolloff' = 0 + 'sidescrolloff' = 0 + +Terminal-mode has its own |:tnoremap| namespace for mappings, this can be used +to automate any terminal interaction. + +To map <Esc> to exit terminal-mode: >vim + :tnoremap <Esc> <C-\><C-n> + +To simulate |i_CTRL-R| in terminal-mode: >vim + :tnoremap <expr> <C-R> '<C-\><C-N>"'.nr2char(getchar()).'pi' + +To use `ALT+{h,j,k,l}` to navigate windows from any mode: >vim + :tnoremap <A-h> <C-\><C-N><C-w>h + :tnoremap <A-j> <C-\><C-N><C-w>j + :tnoremap <A-k> <C-\><C-N><C-w>k + :tnoremap <A-l> <C-\><C-N><C-w>l + :inoremap <A-h> <C-\><C-N><C-w>h + :inoremap <A-j> <C-\><C-N><C-w>j + :inoremap <A-k> <C-\><C-N><C-w>k + :inoremap <A-l> <C-\><C-N><C-w>l + :nnoremap <A-h> <C-w>h + :nnoremap <A-j> <C-w>j + :nnoremap <A-k> <C-w>k + :nnoremap <A-l> <C-w>l + +You can also create menus similar to terminal mode mappings, but you have to +use |:tlmenu| instead of |:tmenu|. + +Mouse input has the following behavior: + +- If the program has enabled mouse events, the corresponding events will be + forwarded to the program. +- If mouse events are disabled (the default), terminal focus will be lost and + the event will be processed as in a normal buffer. +- If another window is clicked, terminal focus will be lost and nvim will jump + to the clicked window +- If the mouse wheel is used while the mouse is positioned in another window, + the terminal won't lose focus and the hovered window will be scrolled. + +============================================================================== +Configuration *terminal-config* + +Options: 'modified', 'scrollback' +Events: |TermOpen|, |TermEnter|, |TermLeave|, |TermClose| +Highlight groups: |hl-TermCursor|, |hl-TermCursorNC| + +Terminal sets local defaults for some options, which may differ from your +global configuration. + +- 'list' is disabled +- 'wrap' is disabled + +You can change the defaults with a TermOpen autocommand: >vim + au TermOpen * setlocal list + +TERMINAL COLORS ~ + +The `{g,b}:terminal_color_x` variables control the terminal color palette, +where `x` is the color index between 0 and 15 inclusive. The variables are +read during |TermOpen|. The value must be a color name or hexadecimal string. +Example: >vim + let g:terminal_color_4 = '#ff0000' + let g:terminal_color_5 = 'green' +Only works for RGB UIs (see 'termguicolors'); for 256-color terminals the +color index is just forwarded. + +Editor highlighting (|syntax-highlighting|, |highlight-groups|, etc.) has +higher precedence: it is applied after terminal colors are resolved. + +------------------------------------------------------------------------------ +EVENTS *terminal-events* + +Applications running in a :terminal buffer can send requests, which Nvim +exposes via the |TermRequest| event. + +OSC 7: change working directory *terminal-osc7* + +To handle OSC 7 emitted from :terminal processes, this code will :cd to the +directory indicated in the request. >lua + + vim.api.nvim_create_autocmd({ 'TermRequest' }, { + desc = 'Handles OSC 7 dir change requests', + callback = function(ev) + if string.sub(vim.v.termrequest, 1, 4) == '\x1b]7;' then + local dir = string.gsub(vim.v.termrequest, '\x1b]7;file://[^/]*', '') + if vim.fn.isdirectory(dir) == 0 then + vim.notify('invalid dir: '..dir) + return + end + vim.api.nvim_buf_set_var(ev.buf, 'osc7_dir', dir) + if vim.o.autochdir and vim.api.nvim_get_current_buf() == ev.buf then + vim.cmd.cd(dir) + end + end + end + }) + vim.api.nvim_create_autocmd({ 'BufEnter', 'WinEnter', 'DirChanged' }, { + callback = function(ev) + if vim.b.osc7_dir and vim.fn.isdirectory(vim.b.osc7_dir) == 1 then + vim.cmd.cd(vim.b.osc7_dir) + end + end + }) + +To try it out, select the above code and source it with `:'<,'>lua`, then run +this command in a :terminal buffer: > + + printf "\033]7;file://./foo/bar\033\\" + +OSC 52: write to system clipboard *terminal-osc52* + +Applications in the :terminal buffer can write to the system clipboard by +emitting an OSC 52 sequence. Example: > + + printf '\033]52;;%s\033\\' "$(echo -n 'Hello world' | base64)" + +Nvim uses the configured |clipboard| provider to write to the system +clipboard. Reading from the system clipboard with OSC 52 is not supported, as +this would allow any arbitrary program in the :terminal to read the user's +clipboard. + +OSC 52 sequences sent from the :terminal buffer do not emit a |TermRequest| +event. The event is handled directly by Nvim and is not forwarded to plugins. + +============================================================================== +Status Variables *terminal-status* + +Terminal buffers maintain some buffer-local variables and options. The values +are initialized before TermOpen, so you can use them in a local 'statusline'. +Example: >vim + :autocmd TermOpen * setlocal statusline=%{b:term_title} + +- *b:term_title* Terminal title (user-writable), typically displayed in the + window title or tab title of a graphical terminal emulator. Terminal + programs can set this by emitting an escape sequence. +- |'channel'| Terminal PTY |job-id|. Can be used with |chansend()| to send + input to the terminal. +- The |TermClose| event gives the terminal job exit code in the |v:event| + "status" field. For example, this autocommand outputs the terminal's exit + code to |:messages|: >vim + autocmd TermClose * echom 'Terminal exited with status '..v:event.status + +Use |jobwait()| to check if the terminal job has finished: >vim + let running = jobwait([&channel], 0)[0] == -1 + +============================================================================== +:Termdebug plugin *terminal-debug* + +The Terminal debugging plugin can be used to debug a program with gdb and view +the source code in a Vim window. Since this is completely contained inside +Vim this also works remotely over an ssh connection. + +Starting ~ + *termdebug-starting* +Load the plugin with this command: >vim + packadd termdebug +When loading the plugin from the |vimrc| file, add the "!" attribute: >vim + packadd! termdebug +< *:Termdebug* +To start debugging use `:Termdebug` or `:TermdebugCommand` followed by the +command name, for example: >vim + :Termdebug vim + +This opens two windows: + +gdb window A terminal window in which "gdb vim" is executed. Here you + can directly interact with gdb. + +program window A terminal window for the executed program. When "run" is + used in gdb the program I/O will happen in this window, so + that it does not interfere with controlling gdb. + +The current window is used to show the source code. When gdb pauses the +source file location will be displayed, if possible. A sign is used to +highlight the current position, using highlight group debugPC. + +If the buffer in the current window is modified, another window will be opened +to display the current gdb position. + +Focus the terminal of the executed program to interact with it. This works +the same as any command running in a terminal window. + +When the debugger ends, typically by typing "quit" in the gdb window, the two +opened windows are closed. + +Only one debugger can be active at a time. + *:TermdebugCommand* +If you want to give specific commands to the command being debugged, you can +use the `:TermdebugCommand` command followed by the command name and +additional parameters. >vim + :TermdebugCommand vim --clean -c ':set nu' + +Both the `:Termdebug` and `:TermdebugCommand` support an optional "!" bang +argument to start the command right away, without pausing at the gdb window +(and cursor will be in the debugged window). For example: >vim + :TermdebugCommand! vim --clean + +To attach gdb to an already running executable or use a core file, pass extra +arguments. E.g.: >vim + :Termdebug vim core + :Termdebug vim 98343 + +If no argument is given, you'll end up in a gdb window, in which you need to +specify which command to run using e.g. the gdb `file` command. + + +Example session ~ + *termdebug-example* +Start in the Vim "src" directory and build Vim: > + % make +Start Vim: > + % ./vim +Load the termdebug plugin and start debugging Vim: >vim + :packadd termdebug + :Termdebug vim +You should now have three windows: + source - where you started + gdb - you can type gdb commands here + program - the executed program will use this window + +Put focus on the gdb window and type: > + break ex_help + run +Vim will start running in the program window. Put focus there and type: >vim + :help gui +Gdb will run into the ex_help breakpoint. The source window now shows the +ex_cmds.c file. A red "1 " marker will appear in the signcolumn where the +breakpoint was set. The line where the debugger stopped is highlighted. You +can now step through the program. You will see the highlighting move as the +debugger executes a line of source code. + +Run ":Next" a few times until the for loop is highlighted. Put the cursor on +the end of "eap->arg", then call ":Eval". You will see this displayed: + "eap->arg": 0x555555e68855 "gui" ~ +This way you can inspect the value of local variables. You can also focus the +gdb window and use a "print" command, e.g.: > + print *eap +If mouse pointer movements are working, Vim will also show a balloon when the +mouse rests on text that can be evaluated by gdb. +You can also use the "K" mapping that will either use Nvim floating windows +to show the results. + +Now go back to the source window and put the cursor on the first line after +the for loop, then type: > + :Break +You will see a "1" marker appear, this indicates the new breakpoint. Now +run ":Cont" command and the code until the breakpoint will be executed. + +You can type more advanced commands in the gdb window. For example, type: > + watch curbuf +Now run ":Cont" (or type "cont" in the gdb window). Execution +will now continue until the value of "curbuf" changes, which is in do_ecmd(). +To remove this watchpoint again type in the gdb window: > + delete 3 + +You can see the stack by typing in the gdb window: > + where +Move through the stack frames, e.g. with: > + frame 3 +The source window will show the code, at the point where the call was made to +a deeper level. + + +Stepping through code ~ + *termdebug-stepping* +Put focus on the gdb window to type commands there. Some common ones are: +- CTRL-C interrupt the program +- next execute the current line and stop at the next line +- step execute the current line and stop at the next statement, + entering functions +- until execute until past the current cursor line or past a specified + position or the current stack frame returns +- finish execute until leaving the current function +- where show the stack +- frame N go to the Nth stack frame +- continue continue execution + + *:Run* *:Arguments* +In the window showing the source code these commands can be used to control +gdb: + `:Run` [args] run the program with [args] or the previous arguments + `:Arguments` {args} set arguments for the next `:Run` + + *:Break* set a breakpoint at the cursor position + :Break {position} + set a breakpoint at the specified position + *:Tbreak* set a temporary breakpoint at the cursor position + :Tbreak {position} + set a temporary breakpoint at the specified position + *:Clear* delete the breakpoint at the cursor position + + *:Step* execute the gdb "step" command + *:Over* execute the gdb "next" command (`:Next` is a Vim command) + *:Until* execute the gdb "until" command + *:Finish* execute the gdb "finish" command + *:Continue* execute the gdb "continue" command + *:Stop* interrupt the program + +If gdb stops at a source line and there is no window currently showing the +source code, a new window will be created for the source code. This also +happens if the buffer in the source code window has been modified and can't be +abandoned. + +Gdb gives each breakpoint a number. In Vim the number shows up in the sign +column, with a red background. You can use these gdb commands: +- info break list breakpoints +- delete N delete breakpoint N +You can also use the `:Clear` command if the cursor is in the line with the +breakpoint, or use the "Clear breakpoint" right-click menu entry. + + +Inspecting variables ~ + *termdebug-variables* *:Evaluate* + `:Evaluate` evaluate the expression under the cursor + `K` same (see |termdebug_map_K| to disable) + `:Evaluate` {expr} evaluate {expr} + `:'<,'>Evaluate` evaluate the Visually selected text + +This is similar to using "print" in the gdb window. +You can usually shorten `:Evaluate` to `:Ev`. +The result is displayed in a floating window. +You can move the cursor to this window by running `:Evaluate` (or `K`) again. + + +Navigating stack frames ~ + *termdebug-frames* *:Frame* *:Up* *:Down* + `:Frame` [frame] select frame [frame], which is a frame number, + address, or function name (default: current frame) + `:Up` [count] go up [count] frames (default: 1; the frame that + called the current) + `+` same (see |termdebug_map_plus| to disable) + `:Down` [count] go down [count] frames (default: 1; the frame called + by the current) + `-` same (see |termdebug_map_minus| to disable) + + +Other commands ~ + *termdebug-commands* + *:Gdb* jump to the gdb window + *:Program* jump to the window with the running program + *:Source* jump to the window with the source code, create it if there + isn't one + *:Asm* jump to the window with the disassembly, create it if there + isn't one + *:Var* jump to the window with the local and argument variables, + create it if there isn't one. This window updates whenever the + program is stopped + +Events ~ + *termdebug-events* +Four autocommands can be used: >vim + au User TermdebugStartPre echomsg 'debugging starting' + au User TermdebugStartPost echomsg 'debugging started' + au User TermdebugStopPre echomsg 'debugging stopping' + au User TermdebugStopPost echomsg 'debugging stopped' +< + *TermdebugStartPre* +TermdebugStartPre Before starting debugging. + Not triggered if the debugger is already + running or the debugger command cannot be + executed. + *TermdebugStartPost* +TermdebugStartPost After debugging has initialized. + If a "!" bang is passed to `:Termdebug` or + `:TermdebugCommand` the event is triggered + before running the provided command in gdb. + *TermdebugStopPre* +TermdebugStopPre Before debugging ends, when gdb is terminated, + most likely after issuing a "quit" command in + the gdb window. + *TermdebugStopPost* +TermdebugStopPost After debugging has ended, gdb-related windows + are closed, debug buffers wiped out and + the state before the debugging was restored. + + +Customizing ~ + *termdebug-customizing* *g:termdebug_config* +In the past several global variables were used for configuration. These are +deprecated and using the g:termdebug_config dictionary is preferred. When +g:termdebug_config exists the other global variables will NOT be used. +The recommended way is to start with an empty dictionary: >vim + let g:termdebug_config = {} + +Then you can add entries to the dictionary as mentioned below. The +deprecated global variable names are mentioned for completeness. If you are +switching over to using g:termdebug_config you can find the old variable name +and take over the value, then delete the deprecated variable. + + +Prompt mode ~ + *termdebug-prompt* +When on MS-Windows, gdb will run in a buffer with 'buftype' set to "prompt". +This works slightly differently: +- The gdb window will be in Insert mode while typing commands. Go to Normal + mode with <Esc>, then you can move around in the buffer, copy/paste, etc. + Go back to editing the gdb command with any command that starts Insert mode, + such as `a` or `i`. +- A separate :terminal window will be opened to run the debugged program in. + + *termdebug_use_prompt* +Prompt mode can be used with: >vim + let g:termdebug_config['use_prompt'] = 1 +If there is no g:termdebug_config you can use: >vim + let g:termdebug_use_prompt = 1 +< +Mappings ~ +The termdebug plugin enables a few default mappings. All those mappings +are reset to their original values once the termdebug session concludes. + + *termdebug_map_K* *termdebug-mappings* +The K key is normally mapped to |:Evaluate| unless a buffer local (|:map-local|) +mapping to K already exists. If you do not want this use: >vim + let g:termdebug_config['map_K'] = 0 +If there is no g:termdebug_config you can use: >vim + let g:termdebug_map_K = 0 +< + *termdebug_map_minus* +The - key is normally mapped to |:Down| unless a buffer local mapping to the - +key already exists. If you do not want this use: >vim + let g:termdebug_config['map_minus'] = 0 +< + *termdebug_map_plus* +The + key is normally mapped to |:Up| unless a buffer local mapping to the + +key already exists. If you do not want this use: >vim + let g:termdebug_config['map_plus'] = 0 +< + *termdebug_disasm_window* +If you want the Asm window shown by default, set the "disasm_window" flag to +1. The "disasm_window_height" entry can be used to set the window height: >vim + let g:termdebug_config['disasm_window'] = 1 + let g:termdebug_config['disasm_window_height'] = 15 +If there is no g:termdebug_config you can use: >vim + let g:termdebug_disasm_window = 15 +Any value greater than 1 will set the Asm window height to that value. +If the current window has enough horizontal space, it will be vertically split +and the Asm window will be shown side by side with the source code window (and +the height option won't be used). + + *termdebug_variables_window* +If you want the Var window shown by default, set the "variables_window" flag +to 1. The "variables_window_height" entry can be used to set the window +height: >vim + let g:termdebug_config['variables_window'] = 1 + let g:termdebug_config['variables_window_height'] = 15 +If there is no g:termdebug_config you can use: >vim + let g:termdebug_variables_window = 15 +Any value greater than 1 will set the Var window height to that value. +If the current window has enough horizontal space, it will be vertically split +and the Var window will be shown side by side with the source code window (and +the height options won't be used). + +Communication ~ + *termdebug-communication* +There is another, hidden, buffer, which is used for Vim to communicate with +gdb. The buffer name is "gdb communication". Do not delete this buffer, it +will break the debugger. + +Gdb has some weird behavior, the plugin does its best to work around that. +For example, after typing "continue" in the gdb window a CTRL-C can be used to +interrupt the running program. But after using the MI command +"-exec-continue" pressing CTRL-C does not interrupt. Therefore you will see +"continue" being used for the `:Continue` command, instead of using the +communication channel. + + +GDB command ~ + *g:termdebugger* +To change the name of the gdb command, set "debugger" entry in +g:termdebug_config or the "g:termdebugger" variable before invoking +`:Termdebug`: >vim + let g:termdebug_config['command'] = "mygdb" +If there is no g:termdebug_config you can use: >vim + let g:termdebugger = "mygdb" + +If the command needs an argument use a List: >vim + let g:termdebug_config['command'] = ['rr', 'replay', '--'] +If there is no g:termdebug_config you can use: >vim + let g:termdebugger = ['rr', 'replay', '--'] + +If you are a mouse person, you can also define a mapping using your right +click to one of the terminal command like evaluate the variable under the +cursor: >vim + nnoremap <RightMouse> :Evaluate<CR> +or set/unset a breakpoint: >vim + nnoremap <RightMouse> :Break<CR> + + +Several arguments will be added to make gdb work well for the debugger. +If you want to modify them, add a function to filter the argument list: >vim + let g:termdebug_config['command_filter'] = MyDebugFilter + +If you do not want the arguments to be added, but you do need to set the +"pty", use a function to add the necessary arguments: >vim + let g:termdebug_config['command_add_args'] = MyAddArguments +The function will be called with the list of arguments so far, and a second +argument that is the name of the pty. + *gdb-version* +Only debuggers fully compatible with gdb will work. Vim uses the GDB/MI +interface. The "new-ui" command requires gdb version 7.12 or later. If you +get this error: + Undefined command: "new-ui". Try "help".~ +Then your gdb is too old. + + +Colors ~ + *hl-debugPC* *hl-debugBreakpoint* +The color of the signs can be adjusted with these highlight groups: +- debugPC the current position +- debugBreakpoint a breakpoint + +The defaults are, when 'background' is "light": + hi debugPC term=reverse ctermbg=lightblue guibg=lightblue + hi debugBreakpoint term=reverse ctermbg=red guibg=red + +When 'background' is "dark": + hi debugPC term=reverse ctermbg=darkblue guibg=darkblue + hi debugBreakpoint term=reverse ctermbg=red guibg=red + + +Shortcuts ~ + *termdebug_shortcuts* +You can define your own shortcuts (mappings) to control gdb, that can work in +any window, using the TermDebugSendCommand() function. Example: >vim + map ,w :call TermDebugSendCommand('where')<CR> +The argument is the gdb command. + + +Popup menu ~ + *termdebug_popup* +By default the Termdebug plugin sets 'mousemodel' to "popup_setpos" and adds +these entries to the popup menu: + Set breakpoint `:Break` + Clear breakpoint `:Clear` + Evaluate `:Evaluate` +If you don't want this then disable it with: >vim + let g:termdebug_config['popup'] = 0 +If there is no g:termdebug_config you can use: >vim + let g:termdebug_popup = 0 + + +Change default signs ~ + *termdebug_signs* +Termdebug uses the hex number of the breakpoint ID in the signcolumn to +represent breakpoints. if it is greater than "0xFF", then it will be displayed +as "F+", due to we really only have two screen cells for the sign. + +If you want to customize the breakpoint signs: >vim + let g:termdebug_config['sign'] = '>>' +If there is no g:terminal_config yet you can use: >vim + let g:termdebug_config = {'sign': '>>'} + +After this, breakpoints will be displayed as `>>` in the signcolumn. + + +Vim window width ~ + *termdebug_wide* +To change the width of the Vim window when debugging starts and use a vertical +split: >vim + let g:termdebug_config['wide'] = 163 +If there is no g:termdebug_config you can use: >vim + let g:termdebug_wide = 163 + +This will set 'columns' to 163 when `:Termdebug` is used. The value is +restored when quitting the debugger. + +If the wide value is set and 'columns' is already a greater value, then a +vertical split will be used without modifying 'columns'. + +Set the wide value to 1 to use a vertical split without ever changing +'columns'. This is useful when the terminal can't be resized by Vim. + + + vim:tw=78:ts=8:noet:ft=help:norl: |