感覺真的是快多了,有點好奇它的原理?
改天有空再來研究研究。

底下是 Gmini 整理的。
Vim 的正規表達式語法非常強大,但它的轉義規則與 Perl 或 Python 等語言的標準正規表達式略有不同,尤其是在處理特殊字符時。Vim 將某些特殊字符分為 "魔法" (magic) 和 "非魔法" (nomagic) 兩種模式。
你可以使用不同的前綴來控制正規表達式的魔法模式:
\M: 設定為 全魔法 (very magic) 模式。所有的特殊字符都視為魔法,不需要額外轉義。這是最像 Perl/PCRE 的模式。\m: 設定為 魔法 (magic) 模式 (Vim 預設)。大部分特殊字符是魔法的,少數需要轉義。\v: 設定為 極魔法 (very magic) 模式。所有的特殊字符都視為魔法,不需要額外轉義。這是最推薦使用的模式,因為它與常見的正規表達式引擎行為最接近,減少了混淆。\V: 設定為 非魔法 (very nomagic) 模式。所有的特殊字符都視為普通字符,需要轉義才能具備特殊含義。推薦:始終使用 \v 開頭的正規表達式,它讓你的模式更直觀。
\v (極魔法) 時的常用特殊字符和其含義:| 字符 | 說明 | 範例 (\v) | 匹配範例 |
|---|---|---|---|
. | 匹配任何單個字符 (換行符除外) | \v.im | Vim, aim |
* | 匹配前一個項目 0 次或多次 | \vgo*d | god, good, gooood |
+ | 匹配前一個項目 1 次或多次 | \vgo+d | good, gooood (不匹配 god) |
? | 匹配前一個項目 0 次或 1 次 | \vcolou?r | color, colour |
{n} | 精確匹配前一個項目 n 次 | \va{3} | aaa |
{n,} | 匹配前一個項目至少 n 次 | \va{2,} | aa, aaa, aaaa |
{n,m} | 匹配前一個項目 n 到 m 次 (包含) | \va{2,4} | aa, aaa, aaaa |
() | 分組,創建子匹配 | \v(ab)+ | ab, abab |
| ` | ` | 或 (OR) 邏輯 | `\v(cat |
[] | 字符集,匹配方括號內的任何一個字符 | \v[abc] | a, b, c |
[^] | 負向字符集,匹配方括號內之外的任何一個字符 | \v[^aeiou] | 匹配任何非元音字母 |
^ | 匹配行的開頭 (當它是模式的第一個字符時) | \v^The | 匹配以 "The" 開頭的行 |
$ | 匹配行的結尾 (當它是模式的最後一個字符時) | \vend$ | 匹配以 "end" 結尾的行 |
\b | 匹配單字邊界 (word boundary) | \v\bword\b | 精確匹配單字 "word" |
\< | 匹配單字的開頭 | \v\<word | 匹配 "word" 在單字開頭 |
\> | 匹配單字的結尾 | \vword\> | 匹配 "word" 在單字結尾 |
\s | 匹配任何空白字符 (space, tab, newline, etc.) | \vhello\sworld | hello world |
\S | 匹配任何非空白字符 | \v\S+ | word, abc |
\d | 匹配任何數字字符 ([0-9]) | \v\d{3} | 123, 456 |
\D | 匹配任何非數字字符 | \v\D | a, ! |
\w | 匹配任何單字字符 (字母、數字、底線) | \v\w+ | variable_name, 123 |
\W | 匹配任何非單字字符 | \v\W | !, @ |
\( \) | 普通括號 (分組) | \v(abc) | 匹配 abc 並捕獲 |
| `\ | ` | 普通豎線 (或) | `\vabc\ |
\{ \} | 普通花括號 (量詞) | \vabc\{ | 匹配 abc{ |
\+ | 普通加號 | \v1\+1 | 1+1 |
\? | 普通問號 | \vwhat\? | what? |
\. | 普通點號 | \vfile\.txt | file.txt |
\[ \] | 普通方括號 | \v\[bracket\] | [bracket] |
\v (very magic) 模式時,幾乎所有你希望作為字面意義匹配的特殊字符,都需要在其前面加上一個反斜槓 \ 進行轉義。 這包括 . * + ? | ( ) [ ] { } ^ $ \ 等。\) 在正規表達式中也是特殊字符,所以如果你要匹配字面意義上的反斜槓,你需要寫 \\。例外 (通常不需要轉義的字面字符,除非在特定上下文中):
,、破折號 -、等號 = 等非正規表達式特殊字符在模式中通常不需要轉義。總結
在 Vim Script 中使用正規表達式時,為了清晰和與其他語言習慣保持一致,強烈建議在模式字串的開頭加上 \v (very magic)。這樣,你就只需要記住那些本身就具有特殊意義的字符(如 . * ( [ 等)需要用 \ 來轉義,如果想讓它們作為字面字符匹配。
終於有個樣子了,現在只剩下幾個問題
01. 沒有比較好的方法去禁止編輯,map key 不只影響 netrw 的 filetype,可能我的理解還是有誤。
02. statusline 不知為何沒有生效。
" for my file explorer
augroup explorer_group
autocmd!
autocmd BufEnter * call s:MK_Browse("")
"autocmd FileType netrw nnoremap :q :q!
autocmd FileType netrw nnoremap <CR> :call <SID>MK_Enter_Browse(<SID>GetCurrNetrwFile())<CR>
"autocmd FileType netrw nnoremap i <ESC>
"autocmd FileType netrw nnoremap I <ESC>
"autocmd FileType netrw nnoremap a <ESC>
"autocmd FileType netrw nnoremap A <ESC>
"autocmd FileType netrw nnoremap x <ESC>
"autocmd FileType netrw nnoremap s <ESC>
"autocmd FileType netrw nnoremap y <ESC>
"autocmd FileType netrw nnoremap p <ESC>
augroup END
function! <SID>MK_Enter_Browse(name)
if isdirectory(a:name)
let l:dir = a:name
if has('win32')
let l:dir = substitute(dir, "/", "\\", "")
endif
execute ":e! " . l:dir
else
let g:MK_curr = getcwd()
let g:MK_sv = winsaveview()
execute ":tabe " . a:name
endif
endfunction
function! s:MK_Browse(dir)
" get current directory
let curr = expand("%:p")
if a:dir != ""
let curr = a:dir
endif
" not directory, do nothing
if !isdirectory(curr)
execute ":set nocursorline"
return
endif
" change folder for later using
if getcwd() != curr
call chdir(curr)
endif
" set up some options
execute ":set filetype=netrw"
execute ":setlocal nonumber"
execute ":setlocal nowrap"
execute ":setlocal cursorline"
execute ":setlocal buftype=nowrite"
" delete original path structure
normal! dG
let f_list = readdir(curr, 1)
let n = 1
" save paths
let files = []
let folders = []
call add(folders, "../")
call add(folders, "./")
for f in f_list
if f == ".swp" || f == "_.swp"
continue
endif
let s = f
if isdirectory(f)
let s = s . "/"
call add(folders, s)
else
call add(files, s)
endif
endfor
" add folders
for f in folders
call setline(n, f)
let n = n + 1
endfor
" add files
for f in files
call setline(n, f)
let n = n + 1
endfor
" restore previous position
if exists("g:MK_sv")
if g:MK_curr == getcwd()
call winrestview(g:MK_sv)
unlet g:MK_sv
endif
endif
" statusline
call s:SetStatusLine()
endfunction