Kalan's Blog

Kalan 頭像照片,在淡水拍攝,淺藍背景

四零二曜日電子報上線啦!訂閱訂起來

本部落主要是關於前端、軟體開發以及我在日本的生活,也會寫一些對時事的觀察和雜感
本部落格支援 RSS feed(全文章內容),可點擊下方 RSS 連結或透過第三方服務設定。若技術文章裡有程式碼語法等特殊樣式,仍建議至原網站瀏覽以獲得最佳體驗。

目前主題 亮色

我會把一些不成文的筆記或是最近的生活雜感放在短筆記,如果有興趣的話可以來看看唷!

我如何用 VSCodeVim 提升開發效率

大概在 2021 年初左右,開始使用了 Vim for VSCode。

原因很簡單,換了 HHKB 鍵盤之後沒有方向鍵(小拇指要抵著 fn),所以編輯文字時很自然地想要避免方向鍵的使用次數,另外就是 HHKB 的鍵位 control 鍵落在 Caplock 上面,要按 control 也比較方便。在這些外在因素影響之下我開始學習 Vim,發現搭配 VSCode 真的蠻好用的,在這邊分享一些心得跟技巧給有興趣的大家。如果對 HHKB 鍵盤有興趣的話可以另外參考我之前寫的文章 - 無接點靜電容鍵盤 HHKB HYBIRD Type-S 使用心得

VSCodeVim

VSCodeVim 是 VSCode 的擴充套件,讓開發者可以在 VSCode 裡頭使用 Vim 鍵位跟綁定來操作。單用 Vim 的話需要花很多時間調整設定,而且我也不想跳脫 VSCode 生態圈,因此直接搭配 VSCode 用起來比較順手。這也是我為什麼不推薦單用 Vim 的原因,雖說工具只是輔助,但 VSCode 提供的導航、終端機整合、擴充套件、自動補全等等,都能有效提升開發效率。

這個套件跟 VSCode 的整合很好,可以自行設定快捷鍵來綁定 VSCode 裡面的功能,以下分享幾個我常用的設定。與其說是 Vim 的教學,比較像是分享我都怎麼用這個套件與其他功能整合。

另外,本篇文章只是單純推薦 Vim 與 VSCodeVim 的搭配,沒有強迫推銷 vim,也不會強求每個開發者都必須使用 vim 開發。

(本篇文章有大量 gif 檔案,目前尚無圖片放大功能,如果圖片過小需要請讀者另行打開分頁觀看)

Go to definition

在追原始碼的時候常常會一邊看函數一邊看實作,透過 gdgf 這兩個綁定可以讓我在 normal mode 的情況下不用另外移動滑鼠也能追實作,或是直接用 preview 的方式看一下型別,非常方便。

gd

Merge Conflict

在合併 Pull Request 時如果發生衝突時,右上角會出現幾個選項來幫助解決 conflict,可以選擇 incoming、current 或是 both。也是一樣,為了讓整個操作停留在鍵盤上,我會另外用快捷鍵去設定。

conflict

複製 GitHub 上檔案的 URL

假設我在 VSCode 當中找到某個檔案實作,想要分享給其他成員,這時如果還要去 GitHub 慢慢點的話就太麻煩了,在 gitlens 套件中其實已經有整合相關的功能(gitlens.copyRemoteFileUrlFrom),因此可以用快捷鍵來綁定。也可以直接開啟瀏覽器讓自己馬上跳到 GitHub 的分頁。

gitlen-copy

快速 prettify 程式碼

我把 format document 這個 action 綁定到 normal mode 的 ff 上面,因此只要按下兩下 f 就可以馬上 prettify 檔案相當方便,當然也可以直接開啟 format on save 即可。

Git Blame

雖然在 GitHub 上也有 Blame 的功能很方便,不過能夠在 VSCode 裡面完成當然是最好。這個功能在 gitlens 已經有了,因此我們只要把快捷鍵綁上去就可以了。像這樣子,我可以用鍵盤追特定的程式碼,慢慢 blame 直到找到兇手為止。(我是用自己的專案當作範例,如果是多人協作專案應該會更方便)

blame

用 finder 打開檔案(revealFileInOS)

有時候想直接跳到該檔案的路徑做調整時還蠻方便的,一樣綁定到 vim 的快捷鍵當中。

reveal

將 2 個 Tab 分別放在左右(或上下)

如果有 27 寸外接螢幕的話,有時候一起寫 HTML、CSS 時將 Tab 分別放在左、右半部會比較方便看,要切換時也比較方便。在 VSCodeVim 裡面可以用 :vs 或是 :sp 來做到。另外可以透過 <C-w>+方向鍵 來切換左右分頁。

split

有興趣的話可以參考下面這份 json 檔案,每個人都有自己喜歡的按法,可以根據自己的需求修改。

"vim.normalModeKeyBindings": [
    {
      "before": [
        "g", "l"
      ],
      "commands": [
        "cmake.build"
      ]
    },
    {
      "before": [
        "<leader>",
        "q"
      ],
      "commands": [
        "workbench.action.openRecent"
      ]
    },
    {
      "before": [
        "g",
        "f"
      ],
      "commands": [
        "editor.action.peekDefinition"
      ]
    },
    {
      "before": [
        "g",
        "n"
      ],
      "commands": [
        "cmake.build"
      ]
    },
    {
      "before": [
        "<leader>",
        "<leader>",
        "c"
      ],
      "commands": [
        "merge-conflict.accept.current"
      ]
    },
    {
      "before": [
        "<leader>",
        "o"
      ],
      "commands": [
        "gitlens.openFileOnRemoteFrom"
      ]
    },
    {
      "before": [
        "<leader>",
        "<leader>",
        "i"
      ],
      "commands": [
        "merge-conflict.accept.incoming"
      ]
    },
    {
      "before": [
        "<leader>",
        "<leader>",
        "b"
      ],
      "commands": [
        "merge-conflict.accept.both"
      ]
    },
    {
      "before": [
        "<leader>",
        "s"
      ],
      "commands": [
        "workbench.action.quickOpenTerm"
      ]
    },
    {
      "before": [
        "<leader>",
        "c"
      ],
      "commands": [
        "gitlens.copyRemoteFileUrlFrom"
      ]
    },
    {
      "before": [
        "<leader>",
        "b"
      ],
      "commands": [
        "gitlens.toggleFileBlame"
      ]
    },
    {
      "before": [
        "<leader>",
        "p"
      ],
      "commands": [
        "gitlens.openBlamePriorToChange"
      ]
    },
    {
      "before": [
        "<leader>",
        "a"
      ],
      "commands": [
        "workbench.view.explorer"
      ]
    },
    {
      "before": [
        "<leader>",
        "<leader>",
        "r"
      ],
      "commands": [
        "revealFileInOS"
      ]
    },
    {
      "before": [
        "f",
        "f"
      ],
      "commands": [
        "editor.action.formatDocument"
      ]
    },
    {
      "before": [
        "+",
        "+"
      ],
      "commands": [
        "workbench.action.increaseViewSize"
      ]
    },
    {
      "before": [
        "-",
        "-"
      ],
      "commands": [
        "workbench.action.decreaseViewSize"
      ]
    }
 ]

其他常用的技巧

  • vit vat 選取所有 tag block:可以直接選到標籤包起來的區塊,例如被 <div> 包起來的地方
    • 延伸出去就是 cit dit 等等都可以用,分別對應到修改內容跟刪除內容。
  • dst 把外面的 tag 移除:前端常常遇到外面包了一層 div 當 wrapper 但突然不想要了,可以用這個操作移除掉。
  • cstt 修改標籤,例如從 p 改成 div:這個是我最愛的操作,修改起來非常快。 change-tag
  • .:重複上一個動作
  • yssb:將文字區塊用 () 包起來
  • yiw ciw:刪除一個單字
  • cs"':將 " 取代為 '
  • dgn:刪除到搜尋的字元

其他 vim 的技巧就不一一贅述,另外 VSCodeVim 也支援 recording,遇到比較複雜的操作可以先用 recording 記錄後再執行,減少 keystroke。

上一篇

從前端視角看 SwiftUI

下一篇

Coinhive 挖礦事件

如果覺得這篇文章對你有幫助的話,可以考慮到下面的連結請我喝一杯 ☕️ 可以讓我平凡的一天變得閃閃發光 ✨

Buy me a coffee