日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【neovim 技巧系列】quickfix 与文本处理

發布時間:2024/5/8 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【neovim 技巧系列】quickfix 与文本处理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

quickfix 與文本處理

本文最新發布在 github 上,不保證 CSDN 上的內容最新。

大部分內容整理自:Advanced Vim topics, tips and tricks (by Mark McDonnell)

global

命令功能
:global/pattern/excmd對滿足 pattern 的行文本進行 excmd 操作
:g/^foo/d 等價于 :g/^foo/norm dd刪除 foo 開頭的行(g = global,d = delete)
:g!/^foo/d刪除不是 foo 開頭的行
:g/foo/norm @q | update1對含 foo 的行執行 @q 宏,并更新文本2
:g/^/exe "norm \<s-j>"每兩行進行合并3

內置的 vimgrep

項目全局替換說明
:vimgrep /pattern/[gjf] path_to_fileg 一行內匹配所有(不使用表示一行只匹配第一次出現的);j 不顯示第一個匹配的內容;f 啟用模糊查詢
:vimgrep /pattern/[gjf] %在當前文件中搜索:% 表示當前文件路徑
:vimgrep /pattern/[gjf] **/*在當前項目中搜索
:vimgrep /ssh/j `find . -type f -name 'tmux*'使用 `` 來獲取外部程序的結果:調用 find 程序來搜索文件名
:vimgrep /<C-r>// *<C-r>/ 快捷鍵表示 / 寄存器(查詢模式的寄存器);在當前目錄的第一層文件下搜索 / 寄存器的內容
  • vimgrep 是全局(唯一)的,每次調用的結果替換上一次的結果;使用 copen 打開 quickfix 窗口,使用 cnext 跳轉下一個,cNext 跳轉上一個
  • lvimgrep 是局部的(l 表示 location),每個 buffer 都可以有一個;lopen、lnext、lNext 在不同的 buffer 中獨立地工作;幾乎所有的 vimgrep
    都有一個相應的 lvimgrep 版本
  • vimgrepadd、lvimgrepadd 使用方式與 vimgrep 也相同,表示不覆蓋上一次結果,而是添加到上一次結果
  • cex[pr] expr 和 lex expr 用于計算 expr 的值,并把結果放到 quickfix:
    • :cexpr system('grep -n xyz *') 調用 grep 程序的結果
    • :cexpr getline(1, '$') 當前 buffer 全文
    • :cex [] 清空 quickfix

外部的 grep

命令功能
:set grepprg查詢當前 grep 程序;默認為 grep -n $* /dev/null
:set grepprg=rg\ --vimgrep | :set grepformat=%f:%l:%c:%m,%f:%l:%m設置為 rg
:silent! noautocmd grep pattern % | copen不彈出搜索結果,并打開 quickfix,打開文件時不運行 autocmd
:set grepprg=ag\ --nogroup\ --nocolor\ --skip-vcs-ignores設置為 ag
:<range>!grep foo只留下含 foo 的行(刪除不含 foo 的行)
:<range>!grep -v foo只留下不含 foo 的行(刪除含 foo 的行)

和 vimgrep 系列類似,grep 為全局 quickfix,局部的為 lgrep,全局增加的為 grepadd,局部增加的為 lgrepadd。

telescope

許多插件提供將插件的搜索結果發送至 quickfix。這里介紹最常見的 telescope 的搜索功能。

首先啟用歷史記錄快捷鍵:

-- 更多可設置快捷鍵的功能見 `:help telescope.actions` local action = require 'telescope.actions' local mappings = {i = { -- insert mode-- 上翻/下翻歷史搜索記錄:所有功能共享歷史搜索記錄["<C-Down>"] = action.cycle_history_next,["<C-Up>"] = action.cycle_history_prev,},n = { -- normal mode["t"] = action.toggle_all, -- 反選所有["T"] = action.drop_all, -- 取消所有["d"] = action.delete_buffer,-- `<C-q>` clear + send all to quickfix-- `<A-q>` clear + send the selected to quickfix-- `a` add the selected to quickfix-- `A` add all to quickfix["a"] = action.add_selected_to_qflist,["A"] = action.add_to_qflist,} } require'telescope'.setup {defaults = {mappings = mappings,}, }

然后設置常見的一些快捷鍵來快速打開功能對話框:

nnoremap ,f <cmd>Telescope find_files<cr> nnoremap ,l <cmd>Telescope live_grep<cr> nnoremap ,g <cmd>Telescope grep_string<cr> nnoremap ,b <cmd>Telescope buffers<cr> nnoremap ,d <cmd>Telescope diagnostics<cr> nnoremap ,q <cmd>Telescope quickfix<cr> nnoremap ,Q <cmd>Telescope quickfixhistory<cr>

Normal 模式中按 ,g 會在當前項目中搜索當前光標下的內容,彈出 telescope 對話框之后4

  • 按 <Ctrl-q> 將所有內容發送至 quickfix
  • 或者按 <Tab>/<Shift-Tab> 多選,按 <Alt-q> 把選擇的內容發送至 quickfix

對 quickfix 處理內容常常使用 cdo(見下文)。此外 telescope 可直接操作已有的 quickfix:

  • 按 ,q 在 telescope 中打開 quickfix
  • 基于已有的 quickfix 創建新的 quickfix,見上述發送至 quickfix 的兩種步驟(這相當于從 quickfix 列表中減少條目)
  • 映射 action.add_selected_to_qflist 和 action.add_to_qflist 等函數提供了添加新項至 quickfix 列表的功能
  • 按 ,Q 可查看和轉到歷史 quickfix 列表

live_grep 和 grep_string 使用的是 telescope.defaults.vimgrep_arguments,默認為 rg 且進行了一些配置,所以:

  • 直接支持正則而無需額外轉義,注意這使用了 Rust regex 庫的正則語法
  • 開啟了 smart-case,輸入小寫字母時會查詢該字母的大小寫,而輸入大寫則只查詢大寫
  • 如果你想使用其他搜索程序,可以自行配置 defaults = { vimgrep_arguments = { ... }, mappings = mappings, }

更多功能見 telescope 的幫助文檔。

處理搜索結果

通常 vimgrep 和 grep 用于搜索內容,并通過 copen/lopen 把搜索結果(文件路徑、位置信息、內容)放置于 quickfix。

然后使用 <c|l>[f]do 進行文本處理,區別在于:

  • cdo vs ldo:全局操作 vs 局部(當前 buffer)操作
  • cdo vs cfdo:全部操作 vs 對每個文件只操作一次

例子:

  • :cdo s/pat/replacement/ 把 pat 換成 replacement
  • :cdo undo 撤銷修改
  • :silent! noautocmd cdo ... | update 執行操作文件時不運行 autocmd,并寫入操作,整個過程不顯示消息
    • silent! 忽略中途打印的消息(mes 也看不到),! 表示連錯誤消息也忽略
    • noautocmd 可以加快操作,因為無需運行自動命令
    • update 相當于 :write,但僅發生在文件修改之后寫入(:w 無論有沒有修改文件都會寫入)
    • 建議至少使用 :cdo ... | update 形式,因為基于未保存的緩沖區修改可能引發數據競爭,如果需要撤銷,使用 :cdo undo | update 即可
  • :cfdo %s/foo/bar/g 對每個文件進行一次批量替換
    • 相比于 cdo,這減少了替換后寫入的次數(每個文件最多只需寫入一次),因此有時可以避免多次修改造成的意外/動態修改
    • 可以想象成,對 quickfix 列出的文件進行全局替換(嗯,類似于下面使用的 :argdo)
    • :cfdo %s/foo/bar/g 對每個文件進行一次批量替換
      • 每個文件內的所有 foo 被替換成 bar
      • % 寄存器訪問當前文件名,對于每次更新了的緩沖區,% 都會以新的文件名更新寄存器
      • 注意 :cfdo s/foo/bar/ 表示對每個文件第一次出現的那個 foo 替換成 bar
      • 注意 :cfdo s/foo/bar/g 表示對每個文件第一個出現在 quickfix 的那行的所有 foo 替換成 bar

do 系列還有 tabdo / windo / bufdo / argdo,使用方式類似,只是應用的范圍不同。

args

:args 主要作為 buffers 的子集。在眾多打開的文件 (buffers) 中,選擇其中一部分文件執行操作:

  • :args *.md 打開所有 md 文件(注意,這搜索當前目錄下的一級路徑,如果需要遞歸,使用 :args **/*.md)
    • :args <Tab> 可以選擇 buffer
    • :args `fd ...` 根據 fd 搜索結果打開文件
    • :args ... 每次執行這個操作意味著創建新的列表(所以不需要刪除列表)
  • :args 查看待操作的文件列表(注意不帶任何參數)
  • :argadd、:argdelete、:argdedupe 對文件進行增加、刪除、去重
  • :argdo 對這些文件進行操作(具體例子與 :cdo 差不多)

可以看到,args 并不需要 quickfix,而是基于文件操作,所以自然可以實現文件替換 :argdo %s/foo/bar/g。

Cfilter

對于 quickfix,篩選是常見操作。vim 內置一個插件來處理,完整的基本過程是:

:vimgrep /vim/ **/* :packadd cfilter :Cfilter /\.md$/

這里打開一個 quickfix,加載 cfilter 插件,然后使用

  • :Cfilter /pat/ 篩選滿足搜索模式的條目
  • :Cfilter! /pat/ 篩選不滿足搜索模式的條目
  • colder 前一個 quickfix,cnewer 后一個 quickfix
  • :Lfilter 應用于 location list (quickfix 的 buffer 局部版本)
    • lolder / lnewer 前/后一個 location list

對于簡單的篩選,這已經足夠。唯一不足的是,似乎沒有內置的條目刪除命令。

nvim-bqf

除了上述的 telescope 之外,你還可以使用 nvim-bqf 插件來增強 quickfix 的預覽、刪除、篩選操作5,通常的步驟:

  • 通過 <Tab> 和 <S-Tab> 選擇/反選一條或幾條
  • zn 或 zN 將選中或沒選中的條目創建新的 quickfix
  • 然后使用 <c|l>[f]do 對新的 quickfix 進行批量處理。

    在預覽方面,可搭配 nvim-treesitter 提供高亮。

    在篩選方便,可搭配 fzf 提供模糊查詢6

    • zf 調出 fzf
    • <Tab> 進行選擇/反選
      • 在 visual mode 下可使用 <Tab> 多條選擇/反選
      • 使用 '<Tab> 對光標所在的文件的所有條目進行選擇/反選
      • 使用 z<Tab> 清除所有選擇
    • zn 把選中的條目創建新的 quickfix
      • zN 把未選中的條目創建新的 quickfix
    -- 安裝 nvim-bqf use {'kevinhwang91/nvim-bqf', ft = 'qf'}-- optional use {'junegunn/fzf', run = function() vim.fn['fzf#install']() end }-- optional, highly recommended use {'nvim-treesitter/nvim-treesitter', run = ':TSUpdate'}

    在支持 lsp 的許多地方也會使用到 quickfix:

    • vim.diagnostic.setqflist、vim.diagnostic.setloclist
    • vim.lsp.buf.references()
    • vim.lsp.buf.document_symbol()
    • vim.lsp.buf.incoming_calls()
    • vim.lsp.buf.outgoing_calls()

    所以 nvim-bqf 還算一個相對通用的插件。使用 telescope 還是 nvim-bqf 來管理 quickfix 完全是個人偏好。

    自動化文本處理

    nvim 完全可以當做命令行工具使用,所以對它進行自動化測試不麻煩。

    以下操作對目錄下的 md 文件進行文本替換并直接寫入源文件,查看 diff,然后撤銷寫入。

    nvim -u NONE --headless\+":args *.md:args:silent! argdo %s/a/.../ge | update"\+":!git diff:silent! argdo undo | update"\+":qa" [a.md] aa.md b.md :!git diff diff --git a/a.md b/a.md index 705a2d7..a2db5c9 100644 --- a/a.md +++ b/a.md @@ -1,2 +1,2 @@ -abc -aed +...bc +...ed diff --git a/b.md b/b.md index 4075523..86a1d9c 100644 --- a/b.md +++ b/b.md @@ -1,2 +1,2 @@ -aqwa -ppa +...qw... +pp...
  • 注意:表格中的 \| 實際只需要輸入 |。 ??

  • norm 表示模擬 norm 模式下操作 ??

  • execute 用于計算 Ex 命令的值,比如涉及控制鍵 ??

  • 使用 <Ctrl-/> 和 ? 顯示對話框在 Insert/Normal 模式下的快捷鍵映射。 ??

  • 增加到 quickfix 可使用 vim 內置的 vimgrepadd / lvimgrepadd / grepadd / lgrepadd 命令。 ??

  • telescope 的搜索框直接支持模糊查詢和預覽,所以可以完全無需 nvim-bqf + fzf。 ??

  • 總結

    以上是生活随笔為你收集整理的【neovim 技巧系列】quickfix 与文本处理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。