首頁 > 軟體

命令列中的 vi 模式

2020-06-16 16:36:53

命令列中修改已經輸入的命令比較麻煩,如果你不知道一些快捷鍵的話,只能使用方向鍵一個一個字元地移動到目標位置進行修改,對於比較複雜且過長的命令來說,效率不高。

以下資訊來自 bash 的 man 頁面:

$ man bash
# ...

   Commands for Moving
       beginning-of-line (C-a)
              Move to the start of the current line.
       end-of-line (C-e)
              Move to the end of the line.
       forward-char (C-f)
              Move forward a character.
       backward-char (C-b)
              Move back a character.
       forward-word (M-f)
              Move  forward  to  the end of the next word.  Words are composed of alphanu-
              meric characters (letters and digits).
       backward-word (M-b)
              Move back to the start of the current or previous word.  Words are  composed
              of alphanumeric characters (letters and digits).
       clear-screen (C-l)
              Clear the screen leaving the current line at the top of the screen.  With an
              argument, refresh the current line without clearing the screen.
       redraw-current-line
              Refresh the current line.

# ...

可看到 bash 本身提供了一些有用的快捷鍵可在命令中快速導航,

  • control + a 定位到行首(start)
  • control + e 定位到行末(end)
  • control + f 向前移動一個單詞(forward)
  • control + b 向後移動一個單詞(back)

移動游標,大部分情況下,我覺得記住這四個可以滿足日常需求。

除了移動游標,還有一些編輯的快捷鍵,在 man 頁面中 Killing and Yanking 部分,

# ...

   Killing and Yanking
       kill-line (C-k)
              Kill the text from point to the end of the line.
       backward-kill-line (C-x Rubout)
              Kill backward to the beginning of the line.
       unix-line-discard (C-u)
              Kill  backward  from point to the beginning of the line.  The killed text is
              saved on the kill-ring.
       kill-whole-line
              Kill all characters on the current line, no matter where point is.
       kill-word (M-d)
              Kill from point to the end of the current word, or if between words, to  the
              end  of  the  next word.  Word boundaries are the same as those used by for-
              ward-word.
       backward-kill-word (M-Rubout)
              Kill the word behind point.  Word boundaries are the same as those  used  by
              backward-word.
       unix-word-rubout (C-w)
              Kill  the  word  behind  point,  using  white space as a word boundary.  The
              killed text is saved on the kill-ring.
       unix-filename-rubout
              Kill the word behind point, using white space and the slash character as the
              word boundaries.  The killed text is saved on the kill-ring.
       delete-horizontal-space (M-)
              Delete all spaces and tabs around point.
       kill-region
              Kill the text in the current region.
       copy-region-as-kill
              Copy the text in the region to the kill buffer.
       copy-backward-word
              Copy  the word before point to the kill buffer.  The word boundaries are the
              same as backward-word.
       copy-forward-word
              Copy the word following point to the kill buffer.  The word  boundaries  are
              the same as forward-word.
       yank (C-y)
              Yank the top of the kill ring into the buffer at point.
       yank-pop (M-y)
              Rotate  the  kill  ring, and yank the new top.  Only works following yank or
              yank-pop.

# ...

其中這一個我最常用:

  • control + u 刪除當前游標位置到行首的內容,配合著 control + e 把游標定位到行末再使用該命令,可實現清空整行的效果

除了這些快捷鍵,其實命令列還有個 vi 模式,該模式下的表現和在 vi 編輯器裡一樣,對於 vi 使用者來說,進入這種模式後,編輯和修改命令就顯得十分得心應手了。

開啟 vi 模式

不同 shell 中開啟的命令不一樣,我比較偏好 fish,因為它的自動補全真的好用到無以復加。

執行 fish_vi_key_bindings 即可進入 vi 模式。

$ fish_vi_key_bindings

執行 fish_default_key_bindings 回到預設。

$ fish_default_key_bindings

命令列的 vi 模式演示

如果需要一直開始,可以組態檔中新增上述命令。

$ vi ~/.config/fish/config.fish

# 其他程式碼
fish_vi_key_bindings

選擇合適的主題

你可能需要一個可以在命令提示行中顯示當前 vi 狀態的主題。

推薦 fish 搭配 omf 使用 omf 中的主題

fish 有預設的 vi 狀態展示,和主題很不搭配。

fish 預設的 vi 狀態展示

需要手動去掉,組態檔中新增如下指令碼:

function fish_mode_prompt; end

修正 fish 中的自動補全

如果發現 vi 模式下, fish 的自動補全快捷鍵 control + f 不能用了,可在組態檔中新增如下指令碼來修復這個快捷鍵:

function fish_user_key_bindings
    for mode in insert default visual
        bind -M $mode cf forward-char
    end
end

IT145.com E-mail:sddin#qq.com