pretty code

顯示具有 VIM 標籤的文章。 顯示所有文章
顯示具有 VIM 標籤的文章。 顯示所有文章

2025年7月15日 星期二

好久沒看 Vim 的書了

最近都在連工作站測試,放假除了出去外,有想法都會進工作站試個幾局XD

原本下班前覺得妥當的東西,剛剛連回去看的結果居然不如預期?

無奈之下,還是先 dump fsdb 好了,根據我星期日的測試,雖然因為缺少 license 無法開啟,但還是可以透過 fsdb2vcd 得到 VCD 檔案,如果我們又無聊的透過 vcd2fsdb,這個 fsdb 就可以解除封印,不過不排除是我星期日測太多眼花了XD

唯一可以確定的是 VCD 轉 fsdb 就沒有 license 問題。

目前網路上找的到的解釋就是下面這張圖,感覺很像 Synopsys 會做的事XD



不知不覺小老婆演唱會也過去好幾個星期了,這次雖然準時登入還是搶不到票,不過我喜歡的歌演唱會也不會唱就是了!

現在有點懷疑是否真的要用 VCS 才能順利跑成功?

我果然還是太嫩了?以為憑我 SW 的經驗可以無往不利?

幸好之前投資 Vim 的點數沒有白費,不需要找阿卡拉重置點數!

如果這一年多來沒有投資 Vim,我估計我跑過的測試應該會少 1/3 以上!

很多時候要改一堆東西,Vim 不熟都很難搞定XD

2025/07/15 更新

成也蕭何,敗也蕭何。

就是對自己的 Vim 技巧太有信心,沒想到居然少給了某個 hard macro 電,還好同事有幫忙看到,不然我應該找不出來,該段 code 看了至少 10 次以上有。

這告訴我們一件事,EDA 工具已經告訴我們哪個訊號有問題,第一件事一定是去檢查那根訊號,而不是把整段 code 又看一次。

另外,fsdb2vcd 有點愚蠢,從上班轉到下班回到家遠端連線都還沒轉完,那還不如直接 dump VCD 都沒那麼慢!

EDA 工作每件事都很花時間,還是盡量不要犯蠢較好,不過好像很難避免?

這應該不是什麼 SOP 可以解決的!

我能想到的就是可以用程式檢查的就寫在 Testbench 內檢查,越早出錯越早離開越好。

$display 想看的訊號,如果可以用程式產生 $display 的檢查語法,還是要利用程式來產生,才不會像我一樣敗在那個 bit。

force 的訊號,同理可證。

2025年7月10日 星期四

Linux + Vim 真是絕配

想要得到一份兩個目錄下的檔案內容差異又不想包含 soft-link,Google 一下可以知道 diff 就有這樣的選項可以使用。

diff -r --no-dereference

為什麼要排除 soft-link?假設路徑中前後各有一個 soft-link,則比較出來的差異數量會膨脹成 4 倍。

排除了重複的資料後,diff 結果可以很容易的再用 sed 切出我們要的內容,也就是不同目錄的差異檔案清單。

如果我們把查詢出來的清單再加工成另一份清單,簡單加上一個 Vim Function,我們就可以快速的隨時瀏覽該檔案的差異項目。

diff -r --no dereference Dir1 Dir2 > diff.log
cat diff.log | sed -En 's/diff -r --no-dereference (.*) (.*)/gvim -d \1 \2/p' > diff_file_list.txt

function! CallExternalCmd()
    let l:line = getline(".")
    execute ":!" . l:line
endfunction

這是我在工作站沒有 WinMerge 這樣的軟體情況下,能夠想出的最佳解法。

當然最佳解一定是在工作站安裝 WinMerge 類似的軟體,雖然在 Linux 上 command line 才是王道,如果偶爾也有 GUI 可用,那也是個不錯的休閒時光XD

2025年7月1日 星期二

沒事多讀規格書

原本我以為 timescale 是可以細到針對個別 Verilog 設定XD

昨天在 2005 規格書好像沒有看到?可能是跟我邊分心連到工作站做事有關,不過卻意外多知道一個函數 $printtimescale( ),可以印出目前檔案的 timescale 設定。

今天突然想到,自己寫個 Testbench 來驗證不就好了!

於是我對 Verilog 又多懂了一點點…

今日重點

01. $printtimescale 可以印出目前 timescale。
02. 看起來所有檔案只能用同一個,後面會覆蓋前面(待確認?)。


2025/07/02 更新

下午因為硬碟空間不足,苦等原本測試未果,無法繼續下一個測試。

乾脆跟 Google AI 對談,順便切磋一下彼此對 EDA 軟體心得,後來順口問了一句有關 `timescale 的想法,居然發現 AI 給的例子完美證明了 `timescale 是可以對個別 module 做設定。

我本來的例子由於是 include,因此會原地展開,才會有我後者取代前者的結論。

下面是 AI 給的例子,因為是個別編譯,故分別保留各自的 `timescale。


雖然我昨天又看了一次規格書,實在看不出這樣的結論?

不過,我跟 AI 都一致認為這樣容易產生 bug,最好的方式還是有一個統一的 include 檔案,大家才能都用同樣的設定。

2025年6月30日 星期一

傻強傻的呀

我果然是傻強無誤。

最近使用 Vim 開啟 System Verilog 檔案時,不知道是否是工作站的版本過舊,遇到這種檔案,都無法顯示出 file type,導致語法顏色一片慘白!為了自己方便,設了一個 map 快速鍵,只是每次都要按還是有點麻煩。

今天終於受不了了,打電話詢問 IT 是否可以更新 Vim 版本,一問之下,才知道目前 Server 已經有 8.1X 的版本。

不過號稱對 Vim 略懂略懂的我,一時之間也不知道為什麼在設了 Path 之後,開啟的還是原本的 Vim 7.X 版本,明明 Path 印出來已經是在第一順位?另外一個問題則是目前的 .vimrc 居然不能用在 8.1X 的版本,會爆出一堆 chdir 之類的系統函數找不到?

就在思考 Vim 是否有什麼設定要設時,熊熊想到,我應該自己設 event 就好,這樣就不用麻煩 IT。

不管是 BufRead、BufReadPost 或是 BufEnter 應該都可以達到自動化的目的。

改天有空在來解決使用 Vim 8.1X 的問題,畢竟在工作站上,Shell 直接開啟 Vim 還是比較符合我的工作習慣,在 Windows 我反而習慣直接開啟 gVim。

我是個很容易適應工作環境的人,有什麼就用什麼,不過我到現在從來不會想用 Mac 就是XD

2025年6月26日 星期四

Gatesim 終於可以 compile 成功了

坦白說,我一直很不喜歡 Synopsys!

尤其最近的一個工作項目是要跑他提供的 IP Testbench。

大部分情況下,我們從客戶那拿到的 input 都是 netlist,所以,IP 相關的文件會提到如何做客戶 design 的 gatesim!(實際上,他文件寫的對我解決問題都沒幫助!)

雖然我們客戶某些 rtl 資料夾不想給我們,但因為那本來就跟 netlist 無關,故不給好像也還合理?

但是當使用 NCVerilog 編譯的時候,連 Synopsys 自己 Testbench 的相關檔案編譯都會有錯誤,這我實在是不能接受!

我能接受你只給 vcs 的 Testbench,但既然你有 option 可以選擇,理論上你應該要測試過沒問題才對?

但從昨天中午拿到客戶最後給的 C code 檔案後,我都一直在解決編譯的錯誤,直到今天晚上 10 點左右,我才順利跑起 simulation!

雖然這兩天大部分的時間都在跟我同事看他 Testbench 的問題,即使扣掉開會及上課的時間,我應該至少也花了 4 ~ 5 個小時有,真的是浪費我的生命XD

拿這些時間多寫幾個 Vim functions 來幫助我工作不是更好嗎?

不如歸去呀XD

2025/06/27 更新

果然如我預期,早上上班登入工作站看到的結果是失敗。

此時第一件事一定是 dump waveform,優先檢查的是 clock 和 reset。

不過,Synopsys 提供的 define 打開就會報錯!還好這個錯誤是可以 Google 到的,只是 LD_PATH 設定的問題,不過,我自己得先補一個 NCVerilog 參數。

但在我一時還找不到 LD_PATH 該設的正確路徑時,為了不浪費中午的時間,於是自己寫一個 initial block 直接 dump VCD 最快,只要硬碟不要爆掉就好XD

稍微看了一下似乎沒看到異常的訊號?

下午只好又繼續翻閱各個文件。

晚上回家連回公司時,忽然想到何不試試 JTAG protocol?

雖然最簡單的 REVISION_CHECK 可以通過,但其他都會報錯,暫時還想不到解法,不過我應該會往自己有修改過的 Verilog 檔案去下手檢查?

2025/06/28 更新

雖然本來就有打算放假連回公司繼續測試,但每測試一次就要等一陣子,實在緩不濟急。

還好,據我多年 coding 經驗,EDA 只要還是由軟體人所開發,我大概就能知道他們是如何設計的?

雖然我可以無腦的複製一份最上層的資料夾再做另一個測試,但是很多 file_list 路徑都要修改,當然這也不是什麼太困難的事,但最麻煩的是我的工作站空間已經不足,我連 dump VCD 都不夠了,雖然我可以 dump fsdb,但不知為何似乎是 license 原因,我無法開啟 fsdb 檔案,故我還是需要 VCD 比較實在。

為了不浪費空間,而我的多個測試也不需要更動 Testbench 內容,最多只是調整 test script 參數。

最好的方式就是只複製 test script、test script 裡面用到的檔案(比如說直接透過 command line 傳給 xrun 的,非 file_list)、幾個 include 檔案(位在測試路徑下的,這些才是動態產生的,原本就在 Testbench 那包的,大部分都不需要修改,故用同一份即可),這些就是我最低限度的檔案,只複製這幾個檔案,我隨時可以長出好幾個測試,這樣更能加速我驗證收斂問題。

現在能限制我的就只剩下 NCVerilog license 個數了!

但我家只有 2 個呀XD 

2025年6月24日 星期二

詠春三板斧

一代宗師的武術界曾提到這樣一句話:詠春來來去去就是那三板斧!

今天不知為何在工作時想到這句話?

突然發現,其實我現在的工作每天也是只有用到三板斧XD

我目前工作的三板斧為:Vim、grep、sed。

Vim 不用多說,我自己就寫了一堆 Vim script functions,即使不算自己的 Vim function,我每天用到的 Vim 功能至少就 10 個以上起跳XD

不誇張的說,沒有 Vim,我大概沒辦法工作了!

其次是 grep,很多時候我要解決的問題或是完成手上的工作,說穿了就是在一堆資料中找東東!有了 grep 的幫助,真的節省我很多時間。

最後則是 sed,grep 找到的資料透過 sed 可以輕易的切出任何我要的片段,只要下對 regex,大概事情就完成一半了XD

如果硬要加上第四板斧,我想這道板斧應該就是 find 指令無誤!

Linux 與 Vim 的世界就是這樣的樸實無華,每天都能發現新玩意?

就像是我請教我主管問題一樣,不管何時都是如沐春風!

2025年6月22日 星期日

Vim Regex Pattern by Google Gemini

底下是 Gmini 整理的。 

Vim Regex Pattern 詳細跳脫規則

Vim 的正規表達式語法非常強大,但它的轉義規則與 Perl 或 Python 等語言的標準正規表達式略有不同,尤其是在處理特殊字符時。Vim 將某些特殊字符分為 "魔法" (magic) 和 "非魔法" (nomagic) 兩種模式。

你可以使用不同的前綴來控制正規表達式的魔法模式:

  • \M: 設定為 全魔法 (very magic) 模式。所有的特殊字符都視為魔法,不需要額外轉義。這是最像 Perl/PCRE 的模式。
  • \m: 設定為 魔法 (magic) 模式 (Vim 預設)。大部分特殊字符是魔法的,少數需要轉義。
  • \v: 設定為 極魔法 (very magic) 模式。所有的特殊字符都視為魔法,不需要額外轉義。這是最推薦使用的模式,因為它與常見的正規表達式引擎行為最接近,減少了混淆。
  • \V: 設定為 非魔法 (very nomagic) 模式。所有的特殊字符都視為普通字符,需要轉義才能具備特殊含義。

推薦:始終使用 \v 開頭的正規表達式,它讓你的模式更直觀。

使用 \v (極魔法) 時的常用特殊字符和其含義:

字符說明範例 (\v)匹配範例
.匹配任何單個字符 (換行符除外)\v.imVim, aim
*匹配前一個項目 0 次或多次\vgo*dgod, good, gooood
+匹配前一個項目 1 次或多次\vgo+dgood, gooood (不匹配 god)
?匹配前一個項目 0 次或 1 次\vcolou?rcolor, 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\sworldhello world
\S匹配任何非空白字符\v\S+word, abc
\d匹配任何數字字符 ([0-9])\v\d{3}123, 456
\D匹配任何非數字字符\v\Da, !
\w匹配任何單字字符 (字母、數字、底線)\v\w+variable_name, 123
\W匹配任何非單字字符\v\W!, @
\( \)普通括號 (分組)\v(abc)匹配 abc 並捕獲
`\`普通豎線 (或)`\vabc\
\{ \}普通花括號 (量詞)\vabc\{匹配 abc{
\+普通加號\v1\+11+1
\?普通問號\vwhat\?what?
\.普通點號\vfile\.txtfile.txt
\[ \]普通方括號\v\[bracket\][bracket]

關於轉義 (Escaping):

  • 當使用 \v (very magic) 模式時,幾乎所有你希望作為字面意義匹配的特殊字符,都需要在其前面加上一個反斜槓 \ 進行轉義。 這包括 . * + ? | ( ) [ ] { } ^ $ \ 等。
  • 反斜槓本身 (\) 在正規表達式中也是特殊字符,所以如果你要匹配字面意義上的反斜槓,你需要寫 \\

例外 (通常不需要轉義的字面字符,除非在特定上下文中):

  • 字母和數字通常不需要轉義。
  • 逗號 ,、破折號 -、等號 = 等非正規表達式特殊字符在模式中通常不需要轉義。

總結

在 Vim Script 中使用正規表達式時,為了清晰和與其他語言習慣保持一致,強烈建議在模式字串的開頭加上 \v (very magic)。這樣,你就只需要記住那些本身就具有特殊意義的字符(如 . * ( [ 等)需要用 \ 來轉義,如果想讓它們作為字面字符匹配。

第一次覺得 AI 有幫助

昨天快篩一條線後,今天終於回了父母家一趟,所以放假這兩天其實都沒什麼在碰 Vim!

晚上回來後,想說來替 Vim 加一個功能好了XD


但是很多時候,我們好奇的是這根訊號它又被穿到哪個 module or cell 了!

如果是 cell 那還好辦,畢竟 pin 不會太多。

假設是另一個 module 或是 hard macro,此時 pin 的個數便會很多,甚至在一頁內都看不到 instantiation 的地方?

雖然可以用搜尋的方式找到分號,接著找右大括號,然後用 % 跳到左大括號,如此一來,我們就可以看到 instantiation 的 module name or cell name 了!

不過,如果可以比照 module 一樣處理,工作當然更方便。

可惜,這次用 Google 搜尋 Vim script 關鍵字都不順利,Vim help 又不好閱讀,於是直接詢問 Gemimi,想不到比我用 Google 快?

結論就是我又可以豐富我的 vimrc 了XD


2025/06/23 更新

今天去辦公室馬上拿真實的 netlist 來測試,果然還不錯,除了要稍微修改 regex 外,畢竟,真實的 netlist pin 很多,我原本的假設不一定成立!

不過,重點還是 [".", "(", ")"] 這 3 個字元是否存在於 hightlight 那行,假設有任一個存在,我就當作是 instantiation 語法!

目前使用的感想還行XD

2025年6月4日 星期三

每天都對 Vim 有新的體悟

Vim 用到現在,只差覺得摺疊沒那麼好用?

今天忘記要查甚麼資料,試了一下 set foldmethod=indent,想要看一個整體的感覺比較方便,一試之下,好像還可以?

尤其我的 code 一向很注重整齊,現在設成 default 後,打開自己的 code 感覺清爽多了!


只恨自己沒有早一點用 Vim,不然生活應該會更開心XD

2025/06/05 更新

zA 打開所有折疊
zM 關掉所有折疊

如果折疊不如預期,可以下 set sw=2 來幫助折疊更多。

2025年6月3日 星期二

Vim profile test


從前幾天買的書中學到一招,可以觀察 Vim script 的函數執行時間。

目前不確定 SELF TIME 有沒有包含 count 的?

2025/06/03 晚上更新

回家又做了一次,順便記錄一下相關指令。

:profile start xxx.log
:profile func *
:profile file *


這次抓的是詳細的資料圖,可以看出最花時間的是往回找 module 的那個 execute 指令。

問題就是出在 search 而非是那個 redraw 清理下面狀態列的指令。

2025年5月30日 星期五

又上天龍


Vim script 細節雖然大概都知道了,手上也有謎版 PDF 以及英文電子書了,難得再次來到天龍國的天瓏書局,不買真的說不過去,於是我又多砍了幾棵樹了XD

通識課這本我其實只想看其中的兩頁,不過嗎,書本不嫌少,知識不嫌多,還是需要一些東東來傍身?

絕世武功動輒都要練個好幾十年,但是現代人欠缺的就是時間呀XD

2025/06/01 更新

原來上面中間那一本已經有第 2 版的英文電子書了,剛試閱了一下,出版社還很貼心的附上連結,只要傳給他購買證明,出版社便會寄給你免費的 PDF 電子書,那還等什麼XD

於是我的 Vim 藏書加上這本,已經來到 6 本之多!剛好 3 本電子書 + 3 本紙本書XD


2025/06/04 更新

原來外國人也會嘴砲,到現在都還沒收到 PDF 電子書,感覺不好XD

2025年5月27日 星期二

Vim vtags

雖然經過這一年的洗禮,我已經習慣了 Vim,也把自己購買放在公司專用的 UltraEdit 移除了。

即便上星期寫了一個 trace variable 並顯示位於哪個 module 的 Vim function,想要好好在 netlist 中 trace variable 還是很痛苦,沒有 EDA 可用就是這麼辛苦XD

今天看到一個 vtags 的小玩意,想說是不是能幫助我看一些東西?沒想到這個東西不能在 Windows 上執行,還好我有 WSL2 環境,果然在 Linux 就可以順利執行。

可惜,手上的 netlist 過於龐大,vtags 會讓 Vim 當機,故我也沒看到他的廬山真面目!

回家試了一下,左邊是 <Space> + v,右下是在 module 那行執行 mt 的結果,看起來似乎跟我的 netlist_treeview 差不多意思,看的都是 hierarchy 的結果,並非我想的訊號追蹤?


還有像 ORFS 裡面的 jpeg_encoder 因為 yosys 綜合後,會用到很多 escaped identifier,故 vtags 也無法支援。


難道,我又要自己寫 tool 了嗎?這可是一件大工程呀!

另一個可以嘗試的方向是 GNU global,看起來只要找到 plugin,就可以處理 verilog 的專案?

2025/05/27 再次更新

原來是我耍笨,看起來可以用來追蹤訊號,詳此處

拿它來改出我要的工具?

2025年5月17日 星期六

不枉費我放假幾個小時的努力

在一個 netlist 中,想要追蹤一個信號是件很痛苦的事XD

如果是可以開啟 EDA 的環境,比如說透過 Tessent Visualizer,只要準備好相關 library,滑鼠點擊幾下,就可以看到來龍去脈。

但很多時候,我可能只有 Vim 可用。

之前為了這種情況,寫了一個 map 自動將某個 module code 複製起來,使用 tab 開啟複製到新分頁,這樣查詢時就不會過頭,避免已經跳到別的 module 而不自知。

早上出門前突然想到,是否可以在按下 n 跳下一個位置時,顯示目前位置所在的 module name 以及行號呢?

下午回家洗完澡後,扣掉晚上吃飯時間,大概也寫了 3 ~ 4 個小時有吧?

終於在剛剛完成了,雖然只有不到 100 行 code,但卻遭遇到很多問題。

比如在 statusline 顯示變數,怎樣用 regex subgroup 切出我要的 module name,還有如果 map key 還是用 n 會一直進入無限遞迴的問題,以及針對 statusline 的修改即使是對的,但還是會報錯,必須重新出去 Vim 再進入一次才會正常的問題等等。

真的是得來不易呀,也不知道是否真能有點幫助?

但不得不說,完成的那一瞬間,爽度真是一百分有XD

2025年5月16日 星期五

好像會又好像都不會

Vim script 寫到現在,有時候會覺得好像自己什麼都不會XD

早上因為一直咳嗽,很早就起來了,想要為自己的 Netrw 加一個功能,加到剛剛都還不成功。

快要上班了,只好先用 patch 搞定,留下 echom debug 訊息,之後有空再來尋求正規解法XD

2025/05/17 更新

目前先用個變數記住 current buffer number,每次進到我的 Netrw,只要現在 buffer number 跟之前不一樣就可以放心的砍下去,好像還可以。

至於遇到 C:\..\ 這樣的路徑,也就是一直按 - 鍵,已經切到根目錄的情況,多一道檢查手續的 patch,好像也還行,暫時先這樣解決吧。

現在只差到底是否要針對 Windows 與 Linux 區分目錄符號?感覺說明看起來是不用?

目前我的 .vimrc 可以用在 

Windows gVim
Windos Git Bash
工作站 Vim

嚴格來說,也可以用在不管是公司還是家裡電腦的 WSL2 Unbuntu,但是因為工作站 Vim 版本比較舊,我的 Netrw 一些函數無法呼叫,只好還是用 Vim 內建的 Netrw。

我也懶得再去區分了XD

2025年5月12日 星期一

Vim tabline

看懂別人的 Vim plugin 有個好處,便是可以隨時把別人的 code 加到自己的 .vimrc 中!

當然,正規作法還是 follow Vim 的哲學,讓 plugin 可以 lazy loading,這樣才不會影響 Vim 啟動速度。

不過,我需要的都是小功能,加到自己的 .vimrc 還是比較方便XD

加了 tabline 後,好像已經快要沒有可以加的了?

tabline 原來只是個字串,但我們需要同時對所有 tab page 設定,格式就像下面那張圖的 command line 字串,其中 #TabLineSel# 表示目前 active 的 tab page。


之前一直不知道為啥 Windows Git Bash 會有問題,就在剛剛終於頓悟了,原來 Git Bash 中也放了一個 Vim,故我同時執行了原本的 Netrw 和我自己的,難怪每次切回 File Viewer 總是會報什麼 modifiable = off 的錯誤。


2025/05/15 更新

原來我還少設了一個 #TabLineFill#,難怪這個語法顏色怎樣都設不成功XD


2025/05/17 更新

雖然 Vim tab 不是這樣用的,但我還是習慣一個 tab 一個檔案。

不管是以前還是現在,我很少用分割視窗,可能我不喜歡使用太大螢幕的關係吧?

總之,適合自己的工作模式才是最好的,不用管別人怎樣界定。

這也正凸顯出 Vim 的過人之處,哪邊不好用就可以動手修改,難怪我會對他愛不釋手XD

2025年5月4日 星期日

我的第一版 netrw

終於有個樣子了,現在只剩下幾個問題
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

2025年4月27日 星期日

My simple netrw plugin

自己寫 Netrw 果然還是有點勉強XD


上面是一個簡單針對 BufEnter Event 的函數。

為了讓他像是一個檔案總管,其實還有很多事要做。

比如說:

set nu!
set nowrap
針對檔案總管顯示顏色
原本使用者設定的 vimrc 裡面的東西要回復

族繁不及備載

至少開始有點感覺了…

2025年4月26日 星期六

快速 parsing 檔案

以前需要臨時對檔案 parsing,一般來說我都會選擇 C 語言,因為這是唯一一個我不需要 google 就可以寫完的程式。

年紀大了還要編譯有點懶,再加上需要做這件事的時候,往往還需要搭配 regex。思來想去,想用一個簡單一點,語法好記的語言,於是便決定以後就用 Tcl 了。

bash script 好是好,但是速度有點慢,不知道是不是我剛沒寫好的關係?

set input "c:\\Vim\\vim91\\autoload\\netrw.vim"

set infile [open $input r]
fconfigure $infile -encoding utf-8

set func_pattern {^fun(\s|!)+ (.*)\s*\(.*}
set end_func_pattern {^endfun}

while {[gets $infile line] >= 0} {
    if {[regexp $func_pattern $line >= null f_name]} {

    } elseif {[regexp $end_func_pattern $line]} {
    
    } elseif {[string first "winrestview" $line] != -1} {
    
    }
}

剛剛希望找到 Netrw 所有呼叫 winrestview 回復 cursor position 的地方,很可惜,確認了幾個地方,但都不是對的地方,我到現在還找不到開啟右邊視窗後,回到原本 Netrw 瀏覽視窗的地方,到底是哪個函數破壞了我自己回存 position 的意圖?


我甚至把所有的 winrestview 都註解了,還是解不掉這個行為,我開始懷疑我的方向錯了?

2025/04/26 晚上更新


想要把之前註解掉的語句回復,使用上面 Tcl 語法,遇到 UTF-8 編碼,還是有少數幾句會有問題,這個問題先記錄起來,以後有空再回來確認。

後來想到可以使用巨集來回復,只要先設定 set nowrapscan,不要讓搜尋從頭開始,這樣就可以設定下面巨集了。ˊ

01. / winrestview 先 trigger search
02. gg 回到第一列
03. qq 開始記錄
04. n^x<ESC>j
05. q 停止紀錄
06. 100@q 執行 100 次巨集,數字要比所有的 winrestview 次數還要多。

04 巨集最重要的是最後面的 j 也就是跳到下一列,這樣按下 n 才會往下一個 winrestview 前進。

2025/04/27 更新

既然 Vim 巨集這麼好用,今天一口氣在每個函數入口加上 echom function_name 的功能,但居然都不是呼叫 winrestview 的函數被觸發而是 s:NetrwInsureWinVars。

現在只能猜測是 Netrw 有去動 buffer 或是什麼我不知道的東西?

有時在想,自己寫一個 directory explorer plugin 會不會比較簡單?

2025年4月17日 星期四

Declare function in Vim script

簡單來說,除了 map 指令呼叫的函數以外,我們都可以用 s: 來宣告函數是屬於 script 的,map 會用到的就是要用 <SID>


至於我們要如何來 debug 我們寫的 Vim script 呢?

下斷點等太進階,C 語言的 print 大法簡單好用。

使用 echom 印出訊息,使用 :messages 看訊息,簡單搞定。

又或是先將 code 寫在獨立的檔案,使用 :source 直接執行,確定沒問題後再移植到 .vimrc

官方建議將函數寫在 .vim/autoload 裡面而不是寫在 .vimrc,這樣的好處是不影響啟動速度,缺點是第一次用相關函數時需等待載入。

2025年4月16日 星期三

Vim 最後一哩路

陸續搞定了 netrw 的一些功能,寫了幾個函數來幫忙,終於對 Vim script 有點感覺了。


雖然回復 cursor 的方法還有點鳥,但目前找不到適合的 event 來監聽,只好勉強先用 Vimresized 頂著先,壞處就是要一個 count 來計算何時該清空變數。


總之,開啟檔案到右邊視窗會觸發第一次,關閉右邊視窗又會觸發第二次,所以當 count == 2 時,我才能放心清空此變數。

現在大概只差寫 Plugin 的經驗了XD

2025/04/17 更新


早上又多檢查了 winnr 的個數,避免開到第三個 Window 後,汙染了原本的 s:MK_sv 變數。

另外,Vimresized 之所以能成功的原因是因為當開了右邊的分割視窗後,此時原本的視窗左邊會長出 scrollbar,故才會有此 Event 的發生。

如果我們去調整 guioption,讓它永遠為空,Vimresized Event 就不再發生了,故我原本的 patch 就不起作用了。

2025/04/18 更新

原來也可以設定 g:netrw_fastbrowse = 2,這樣就不會每次重新抓取目錄列表而導致游標跑掉(離開原本開啟檔案那列),但第一次因為 Buffer 沒有東西,故還是會重刷。

用這個的好處是我可以設定 set guioptions-=L,強制左邊不會有 scrollbar,看起來比較好看。

如果用我原來的 BackToNetrwWindow,則是不能設定沒有左邊 scollbar,不然 Vimresized Event 會失效。

真是有一好沒兩好。

2025/05/12 更新

最後,還是用了自己寫的 netrw,除了工作站無法修改外,公司及家裡的電腦目前都是用自己的 netrw,還是自己的狗糧最好吃XD