終端機

Nvim 的 :help 頁面,產生自 原始碼,並使用 tree-sitter-vimdoc 解析器。


終端機模擬器 terminal-emulator
Nvim 內嵌了一個基於 libvterm 的 VT220/xterm 終端機模擬器。終端機以特殊的 'buftype' 呈現,當從連線程式收到資料時會非同步更新。
終端機緩衝區的行為與一般緩衝區類似,除了:
'modifiable' 為啟用時,可以編輯行,但不能刪除。
'scrollback' 控制保留多少行。
如果游標在最後一行,輸出會被追蹤("tailed")。
'modified' 是預設值。你可以設定 'nomodified' 來避免關閉終端機緩衝區時出現警告。
'bufhidden' 預設為 "hide"。
有多種方式可以建立終端機緩衝區:
執行 `:terminal` 指令。
呼叫 nvim_open_term()termopen() 函數。
編輯 "term://" 緩衝區。範例:
:edit term://bash
:vsplit term://top
注意: 若要從自動指令 (autocmd) 開啟 "term://" 緩衝區,需要使用 autocmd-nested 修飾符。
autocmd VimEnter * ++nested split term://sh
(這裡僅供參考;請改用 `:terminal`)。
當終端機啟動時,緩衝區內容會更新,並且緩衝區會以 term://{cwd}//{pid}:{cmd} 的形式命名。此命名方式會被 `:mksession` 用來還原終端機緩衝區(藉由重新啟動 {cmd})。
終端機環境的初始化方式與 jobstart-env 中相同。
要傳送輸入,使用 iIaA:startinsert 進入 終端機模式。在此模式下,除了 <C-\> 之外的所有按鍵都會被傳送到基礎程式。如果按下 <C-\>,則會傳送下一個按鍵,除非它是 <C-N><C-O>。使用 <C-\><C-N> 返回一般模式。 CTRL-\_CTRL-N 使用 <C-\><C-O> 執行一個一般模式指令,然後返回終端機模式。 t_CTRL-\_CTRL-O
終端機模式會強制使用這些區域選項:
終端機模式有自己的 `:tnoremap` 映射命名空間,可用於自動化任何終端機互動。
<Esc> 映射為退出終端機模式:
:tnoremap <Esc> <C-\><C-n>
在終端機模式中模擬 i_CTRL-R
:tnoremap <expr> <C-R> '<C-\><C-N>"'.nr2char(getchar()).'pi'
使用 ALT+{h,j,k,l} 從任何模式導覽視窗:
: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
你也可以建立類似於終端機模式映射的選單,但你必須使用 `:tlmenu` 而不是 `:tmenu`
滑鼠輸入有以下行為:
如果程式已啟用滑鼠事件,對應的事件將會轉發給程式。
如果滑鼠事件被禁用(預設),終端機焦點將會遺失,並且事件將會像在一般緩衝區中一樣被處理。
如果點擊了另一個視窗,終端機焦點將會遺失,並且 nvim 將會跳到點擊的視窗。
如果在滑鼠位於另一個視窗時使用滑鼠滾輪,終端機將不會失去焦點,並且懸停的視窗將會滾動。
終端機會為某些選項設定區域預設值,這可能與你的全域設定不同。
'list' 被禁用。
'wrap' 被禁用。
你可以使用 TermOpen 自動指令來變更預設值:
au TermOpen * setlocal list
終端機顏色
{g,b}:terminal_color_x 變數控制終端機的調色盤,其中 x 是介於 0 和 15 之間(包含)的顏色索引。這些變數會在 TermOpen 期間讀取。該值必須是顏色名稱或十六進位字串。範例:
let g:terminal_color_4 = '#ff0000'
let g:terminal_color_5 = 'green'
僅適用於 RGB UI(請參閱 'termguicolors');對於 256 色終端機,顏色索引會直接轉發。
編輯器高亮(語法高亮高亮群組 等)具有更高的優先順序:它會在終端機顏色解析後套用。
在 :terminal 緩衝區中執行的應用程式可以傳送請求,Nvim 會透過 TermRequest 事件公開這些請求。
OSC 7:變更工作目錄 terminal-osc7
為了處理從 :terminal 程序發出的 OSC 7,以下程式碼將會使用 :cd 切換到請求中指示的目錄。
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
})
若要試用,請選取上述程式碼,並使用 :'<,'>lua 執行它,然後在 :terminal 緩衝區中執行以下指令:
printf "\033]7;file://./foo/bar\033\\"
OSC 52:寫入系統剪貼簿 terminal-osc52
在 :terminal 緩衝區中的應用程式可以透過發出 OSC 52 序列來寫入系統剪貼簿。範例:
printf '\033]52;;%s\033\\' "$(echo -n 'Hello world' | base64)"
Nvim 會使用已設定的 剪貼簿 提供者來寫入系統剪貼簿。不支援使用 OSC 52 從系統剪貼簿讀取,因為這會允許 :terminal 中的任何任意程式讀取使用者的剪貼簿。
從 :terminal 緩衝區傳送的 OSC 52 序列不會發出 TermRequest 事件。該事件會由 Nvim 直接處理,並且不會轉發給外掛程式。

狀態變數 terminal-status

終端機緩衝區會維護一些緩衝區區域變數和選項。這些值會在 TermOpen 之前初始化,因此你可以在區域 'statusline' 中使用它們。範例:
:autocmd TermOpen * setlocal statusline=%{b:term_title}
b:term_title 終端機標題(使用者可寫入),通常顯示在圖形終端機模擬器的視窗標題或標籤標題中。終端機程式可以透過發出跳脫序列來設定此標題。
'channel' 終端機 PTY 工作 ID。可以與 chansend() 一起使用,將輸入傳送至終端機。
TermClose 事件會在 v:event 的 "status" 欄位中提供終端機工作的結束代碼。例如,以下自動指令會將終端機的結束代碼輸出到 `:messages`
autocmd TermClose * echom 'Terminal exited with status '..v:event.status
使用 jobwait() 來檢查終端機工作是否已完成。
let running = jobwait([&channel], 0)[0] == -1

:Termdebug 外掛程式 terminal-debug

終端機除錯外掛程式可以用來使用 gdb 除錯程式,並在 Vim 視窗中檢視原始程式碼。由於這完全包含在 Vim 內部,因此也可以透過 SSH 連線遠端運作。
開始
termdebug-starting
使用以下指令載入外掛程式:
packadd termdebug
vimrc 檔案載入外掛程式時,請新增 "!" 屬性:
packadd! termdebug
:Termdebug
若要開始除錯,請使用 :Termdebug:TermdebugCommand,後面接上指令名稱。例如:
:Termdebug vim
這會開啟兩個視窗:
gdb 視窗:一個執行 "gdb vim" 的終端機視窗。你可以在這裡直接與 gdb 互動。
程式視窗:一個用於執行程式的終端機視窗。當在 gdb 中使用 "run" 時,程式的 I/O 將會在此視窗中發生,因此它不會干擾 gdb 的控制。
目前視窗用於顯示原始程式碼。當 gdb 暫停時,原始程式碼檔案位置將會顯示(如果可能)。會使用一個符號來強調目前位置,並使用高亮群組 debugPC。
如果目前視窗中的緩衝區被修改,則會開啟另一個視窗來顯示目前的 gdb 位置。
將焦點放在執行程式的終端機上以與之互動。這與在終端機視窗中執行的任何指令相同。
當除錯器結束時(通常是透過在 gdb 視窗中輸入 "quit"),兩個開啟的視窗會關閉。
一次只能有一個除錯器處於活動狀態。 :TermdebugCommand
如果你想給要除錯的指令提供特定的指令,你可以使用 :TermdebugCommand 指令,後面接上指令名稱和額外參數。
:TermdebugCommand vim --clean -c ':set nu'
:Termdebug:TermdebugCommand 都支援可選的 "!" 驚嘆號參數,以便立即啟動指令,而無需在 gdb 視窗中暫停(並且游標將會位於除錯的視窗中)。例如:
:TermdebugCommand! vim --clean
若要將 gdb 附加到已在執行的可執行檔或使用核心檔案,請傳遞額外參數。例如:
:Termdebug vim core
:Termdebug vim 98343
如果沒有提供任何參數,你將會在 gdb 視窗中結束,你需要在其中指定要使用哪個指令來執行,例如使用 gdb 的 file 指令。
範例會期
termdebug-example
在 Vim 的 "src" 目錄中啟動,並建置 Vim:
% make
啟動 Vim:
% ./vim
載入 termdebug 外掛程式並開始除錯 Vim:
:packadd termdebug
:Termdebug vim
你現在應該有三個視窗:原始碼 - 你開始 gdb 的地方 - 你可以在這裡輸入 gdb 指令;程式 - 執行的程式將會使用此視窗。
將焦點放在 gdb 視窗上,並輸入:
break ex_help
run
Vim 將會在程式視窗中開始執行。將焦點放在那裡,並輸入:
:help gui
Gdb 將會執行到 ex_help 中斷點。原始碼視窗現在會顯示 ex_cmds.c 檔案。一個紅色的 "1 " 標記將會出現在設定中斷點的 signcolumn 中。除錯器停止的行會被高亮顯示。你現在可以逐步執行程式。你會看到高亮顯示隨著除錯器執行一行原始程式碼而移動。
執行 ":Next" 幾次,直到 for 迴圈被高亮顯示。將游標放在 "eap->arg" 的末尾,然後呼叫 ":Eval"。你會看到這個顯示出來:
"eap->arg": 0x555555e68855 "gui"
這樣您就可以檢查區域變數的值。您也可以將焦點放在 gdb 視窗上,並使用 "print" 命令,例如:
print *eap
如果滑鼠指標移動正常,當滑鼠停留在可被 gdb 評估的文字上時,Vim 也會顯示提示框。您也可以使用 "K" 映射,它會使用 Nvim 浮動視窗來顯示結果。
現在回到原始碼視窗,將游標放在 for 迴圈後的第一行,然後輸入
:Break
您會看到一個 "1" 標記出現,這表示新的斷點。現在執行 ":Cont" 命令,程式碼將會執行到斷點處。
您可以在 gdb 視窗中輸入更進階的命令。例如,輸入
watch curbuf
現在執行 ":Cont"(或在 gdb 視窗中輸入 "cont")。程式將會繼續執行,直到 "curbuf" 的值改變,這發生在 do_ecmd() 函式中。若要再次移除這個監看點,請在 gdb 視窗中輸入
delete 3
您可以在 gdb 視窗中輸入以下指令來查看堆疊:
where
透過堆疊框架移動,例如使用:
frame 3
原始碼視窗將會顯示程式碼,並指出呼叫較深層級函式的位置。
單步執行程式碼
termdebug-單步執行
將焦點放在 gdb 視窗,以便在那裡輸入指令。一些常用的指令有:
CTRL-C 中斷程式
next 執行目前行並在下一行停止
step 執行目前行並在下一個敘述停止,進入函式
until 執行直到超過目前游標行,或超過指定位置,或目前的堆疊框架返回
finish 執行直到離開目前函式
where 顯示堆疊
frame N 前往第 N 個堆疊框架
continue 繼續執行
:Run :Arguments 在顯示原始碼的視窗中,可以使用這些命令來控制 gdb::Run [args] 使用 [args] 或先前的參數來執行程式。:Arguments {args} 設定下一次 :Run 的參數。
:Break 在游標位置設定斷點:Break {position} 在指定位置設定斷點 :Tbreak 在游標位置設定臨時斷點:Tbreak {position} 在指定位置設定臨時斷點 :Clear 刪除游標位置的斷點
:Step 執行 gdb 的 "step" 命令 :Over 執行 gdb 的 "next" 命令 (:Next 是 Vim 命令) :Until 執行 gdb 的 "until" 命令 :Finish 執行 gdb 的 "finish" 命令 :Continue 執行 gdb 的 "continue" 命令 :Stop 中斷程式
如果 gdb 停在原始碼行,且目前沒有視窗顯示原始碼,將會為原始碼建立一個新的視窗。如果原始碼視窗中的緩衝區已修改且無法捨棄,也會發生這種情況。
Gdb 會為每個斷點指定一個數字。在 Vim 中,這個數字會顯示在符號欄中,並以紅色背景顯示。您可以使用這些 gdb 命令:
info break 列出斷點
delete N 刪除斷點 N。如果游標位於斷點所在的行,您也可以使用 :Clear 命令,或使用「清除斷點」的右鍵選單項目。
檢查變數
termdebug-variables :Evaluate :Evaluate 評估游標下的表達式 K 相同 (請參閱 termdebug_map_K 來停用) :Evaluate {expr} 評估 {expr} :'<,'>Evaluate 評估視覺選取的文字
這類似於在 gdb 視窗中使用 "print"。您通常可以將 :Evaluate 縮短為 :Ev。結果會顯示在浮動視窗中。您可以再次執行 :Evaluate (或 K) 來將游標移動到這個視窗。
瀏覽堆疊框架
termdebug-frames :Frame :Up :Down :Frame [frame] 選取框架 [frame],可以是框架編號、位址或函式名稱 (預設:目前框架)。 :Up [count] 向上移動 [count] 個框架 (預設:1;呼叫目前的框架)。 + 相同 (請參閱 termdebug_map_plus 來停用)。 :Down [count] 向下移動 [count] 個框架 (預設:1;由目前的框架呼叫)。 - 相同 (請參閱 termdebug_map_minus 來停用)。
其他命令
termdebug-命令
:Gdb 跳至 gdb 視窗 :Program 跳至執行中程式的視窗 :Source 跳至顯示原始碼的視窗,如果沒有則建立一個 :Asm 跳至顯示反組譯碼的視窗,如果沒有則建立一個 :Var 跳至顯示區域變數和引數的視窗,如果沒有則建立一個。當程式停止時,此視窗會更新。
事件
termdebug-事件
可以使用四個自動命令:
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 在開始除錯之前。如果除錯器已經在執行中,或無法執行除錯器命令,則不會觸發此事件。TermdebugStartPost
TermdebugStartPost 在除錯初始化後。如果將 "!" 驚嘆號傳遞給 :Termdebug:TermdebugCommand,則會在 gdb 中執行提供的命令之前觸發此事件。TermdebugStopPre
TermdebugStopPre 在除錯結束之前,當 gdb 終止時,最有可能是在 gdb 視窗中發出 "quit" 命令之後。TermdebugStopPost
TermdebugStopPost 在除錯結束之後,gdb 相關視窗會關閉、除錯緩衝區會清除,且會還原除錯之前的狀態。
自訂
termdebug-自訂 g:termdebug_config 過去,使用幾個全域變數來進行設定。這些變數已過時,建議使用 g:termdebug_config 字典。當 g:termdebug_config 存在時,將不會使用其他全域變數。建議從一個空的字典開始:
let g:termdebug_config = {}
然後您可以將條目添加到字典中,如下所述。為了完整起見,會提及已過時的全域變數名稱。如果您要切換使用 g:termdebug_config,您可以找到舊的變數名稱並接管該值,然後刪除已過時的變數。
提示模式
termdebug-提示
在 MS-Windows 上,gdb 將會在 'buftype' 設定為 "prompt" 的緩衝區中執行。運作方式略有不同:
在輸入命令時,gdb 視窗將會處於插入模式。使用 <Esc> 進入普通模式,然後您可以在緩衝區中移動、複製/貼上等。使用任何開始插入模式的命令 (例如 ai) 回到編輯 gdb 命令。
會開啟一個單獨的 :terminal 視窗來執行除錯的程式。
termdebug_use_prompt
提示模式可以使用:
let g:termdebug_config['use_prompt'] = 1
如果沒有 g:termdebug_config,您可以使用:
let g:termdebug_use_prompt = 1
映射
termdebug 外掛程式啟用一些預設映射。一旦 termdebug 工作階段結束,所有這些映射都會重設為其原始值。
termdebug_map_K termdebug-映射 K 鍵通常會映射到 :Evaluate,除非已經存在 K 的緩衝區本機 (:map-local) 映射。如果您不想要這樣,請使用:
let g:termdebug_config['map_K'] = 0
如果沒有 g:termdebug_config,您可以使用:
let g:termdebug_map_K = 0
termdebug_map_minus
- 鍵通常會映射到 :Down,除非已經存在 - 鍵的緩衝區本機映射。如果您不想要這樣,請使用:
let g:termdebug_config['map_minus'] = 0
termdebug_map_plus
+ 鍵通常會映射到 :Up,除非已經存在 + 鍵的緩衝區本機映射。如果您不想要這樣,請使用:
let g:termdebug_config['map_plus'] = 0
termdebug_disasm_window
如果您希望預設顯示反組譯碼視窗,請將 "disasm_window" 旗標設為 1。"disasm_window_height" 條目可以用來設定視窗高度:
let g:termdebug_config['disasm_window'] = 1
let g:termdebug_config['disasm_window_height'] = 15
如果沒有 g:termdebug_config,您可以使用:
let g:termdebug_disasm_window = 15
任何大於 1 的值都會將反組譯碼視窗的高度設定為該值。如果目前視窗有足夠的水平空間,它會被垂直分割,且反組譯碼視窗會與原始碼視窗並排顯示 (且不會使用高度選項)。
termdebug_variables_window
如果您希望預設顯示變數視窗,請將 "variables_window" 旗標設為 1。"variables_window_height" 條目可以用來設定視窗高度:
let g:termdebug_config['variables_window'] = 1
let g:termdebug_config['variables_window_height'] = 15
如果沒有 g:termdebug_config,您可以使用:
let g:termdebug_variables_window = 15
任何大於 1 的值都會將變數視窗的高度設定為該值。如果目前視窗有足夠的水平空間,它會被垂直分割,且變數視窗會與原始碼視窗並排顯示 (且不會使用高度選項)。
通訊
termdebug-通訊
還有另一個隱藏的緩衝區,用於 Vim 與 gdb 通訊。緩衝區名稱為 "gdb communication"。請勿刪除此緩衝區,它會使除錯器失效。
Gdb 有一些奇怪的行為,外掛程式會盡力解決這個問題。例如,在 gdb 視窗中輸入 "continue" 後,可以使用 CTRL-C 中斷正在執行的程式。但在使用 MI 命令 "-exec-continue" 後,按下 CTRL-C 不會中斷。因此,您會看到 :Continue 命令使用 "continue",而不是使用通訊通道。
GDB 命令
g:termdebugger
若要變更 gdb 命令的名稱,請在叫用 :Termdebug 之前,設定 g:termdebug_config 中的 "debugger" 條目或 "g:termdebugger" 變數:
let g:termdebug_config['command'] = "mygdb"
如果沒有 g:termdebug_config,您可以使用:
let g:termdebugger = "mygdb"
如果命令需要引數,請使用清單:
let g:termdebug_config['command'] = ['rr', 'replay', '--']
如果沒有 g:termdebug_config,您可以使用:
let g:termdebugger = ['rr', 'replay', '--']
如果您是滑鼠使用者,您也可以使用右鍵點擊來定義映射,將其對應到其中一個終端命令,例如評估游標下的變數:
nnoremap <RightMouse> :Evaluate<CR>
或設定/取消設定斷點:
nnoremap <RightMouse> :Break<CR>
會加入幾個引數,讓 gdb 更適合除錯。如果您想要修改它們,請新增一個函式來篩選引數清單:
let g:termdebug_config['command_filter'] = MyDebugFilter
如果您不希望新增引數,但需要設定 "pty",請使用函式來新增必要的引數:
let g:termdebug_config['command_add_args'] = MyAddArguments
函式將會使用到目前為止的引數清單和第二個引數 (pty 的名稱) 呼叫。gdb-版本
只有完全與 gdb 相容的除錯器才能使用。Vim 使用 GDB/MI 介面。"new-ui" 命令需要 gdb 7.12 或更新版本。如果您收到此錯誤:「未定義的命令:「new-ui」。請嘗試「help」。」,則表示您的 gdb 版本太舊。
色彩
hl-debugPC hl-debugBreakpoint 符號的顏色可以使用這些 highlight 群組調整:
debugPC 目前位置
debugBreakpoint 斷點
預設值為,當 背景 為 "light" 時:hi debugPC term=reverse ctermbg=lightblue guibg=lightblue hi debugBreakpoint term=reverse ctermbg=red guibg=red
背景 為 "dark" 時:hi debugPC term=reverse ctermbg=darkblue guibg=darkblue hi debugBreakpoint term=reverse ctermbg=red guibg=red
快捷鍵
termdebug_shortcuts
您可以使用 TermDebugSendCommand() 函式定義自己的快捷鍵 (映射),以便在任何視窗中控制 gdb。範例:
map ,w :call TermDebugSendCommand('where')<CR>
參數是 gdb 命令。
快顯選單
termdebug_popup
預設情況下,Termdebug 外掛程式會將 滑鼠模式 設定為 "popup_setpos",並將這些項目新增至快顯選單:設定斷點 :Break 清除斷點 :Clear 評估 :Evaluate。如果您不想要此功能,請使用以下方式停用:
let g:termdebug_config['popup'] = 0
如果沒有 g:termdebug_config,您可以使用:
let g:termdebug_popup = 0
變更預設符號
termdebug_signs
Termdebug 在符號欄中使用斷點 ID 的十六進位數字來表示斷點。如果它大於 "0xFF",則會顯示為 "F+",因為我們實際上只有兩個螢幕儲存格用於符號。
如果您想要自訂斷點符號
let g:termdebug_config['sign'] = '>>'
如果還沒有 g:terminal_config,您可以使用
let g:termdebug_config = {'sign': '>>'}
之後,斷點將在符號欄中顯示為 >>
Vim 視窗寬度
termdebug_wide
若要在偵錯開始時變更 Vim 視窗的寬度並使用垂直分割
let g:termdebug_config['wide'] = 163
如果沒有 g:termdebug_config,您可以使用:
let g:termdebug_wide = 163
這將在使用 :Termdebug 時將 欄數 設定為 163。退出偵錯程式時,該值將恢復。
如果已設定寬值且 欄數 已經是更大的值,則將使用垂直分割,而不修改 欄數
將寬值設定為 1 以使用垂直分割,而永遠不變更 欄數。當 Vim 無法調整終端機大小時,這很有用。
主要
命令索引
快速參考