星期一, 3月 29, 2010

latex 半自動 WYSIWYM

之前寫過的 iwatch 可以讓我寫 latex 的時候不用一直手動 make,然後只要編譯完用 foxit 顯示文件就可以了,但是這樣的效果差強人意,因為 foxit 沒辦法自動 reload,我只好每次 make 完就 kill 然後重開一個 foxit,心血來潮之下找到了 xpdf,他可以開一個 remote xpdf 像是一個 server ,然後 xpdf -remote preview -reload 就可以讓這個remote server 重新讀取 pdf!!
這樣的組合真是太完美了,搭配 iwatch,可以用我寫的 script:
#!/bin/bash
REMOTE=preview
TEX=sample.tex
PDF=$(basename $TEX .tex).pdf
xpdf -remote $REMOTE $PDF &                                                                                    
id=$!
while ./iwatch -e modify $TEX
do
    make
    xpdf -remote $REMOTE -reload &
    id=$!
done

這樣每次儲存以後,會自動編譯,然後在現有 xpdf 更新畫面!在我的桌面上執行起來像這樣:下面是 vim 上面是 xpdf,因為用 xmonad 剛好可以分成上下來顯示。

星期二, 3月 23, 2010

git diff 自訂 hunk header (function line, function name...)

GNU diff 有一個參數是 -F RE,  --show-function-line=RE 可以在 diff 的時候用來顯示內容屬於哪個區塊,提供除了檔案行數以外的位置辨認。
對於 C,  C++, HTML, java.... 一些常見的語言有內建的辨識語法來抓出 function name,但如果是自訂格式的檔案的話就比需要自己寫,詳情可以參考 man gitattribues,這邊大概紀錄一下作法..

先設定指定的類別用的語法, ~/.gitconfig :
[diff "are"]
    xfuncname = "^#[0-9]+$"
然後在 project 的根目錄或是有放那些檔案的目錄下加一個 .gitattributes (跟 .gitignore 一樣, 有與上層繼承的關係),裡面寫:
*.are diff=are
這樣就可以了, git diff 的一個區段結果會長這樣:

@@ -6,4 +6,4 @@ #103
 3
 4
 5
-6
+7
會找出最近一個符合的字串放在行數後面,這樣如果只看 diff 的話也會比較清楚這個 patch 到底做了什麼。不過要記得,如果 match 到的字串有在 diff 的上下文(context)出現,就不會顯示在 header,所以 header 上的提示不一定是正確的(當然 context number 可以用 -U 設定,不過如果 > 0 就是有可能有這種情況)。

星期六, 3月 13, 2010

inotify - 讓 kernel 幫你監控檔案

自從 Linux Kernel 2.6.13,linux 就提供了 inotify 的 API 讓使用者以 event 的方式監控檔案。這顯然比傳統 busy checking 的方式有效率多了,除了用的是 kernel space 的 memory 以外幾乎沒有理由不用這麼好用的機制了吧!
inotify 提供監控的事件可以在 manual 裡找到 (man inotify) 在這邊就不贅述。使用上其實也很簡單,首先呼叫 inotify_init() 取得一個 file descriptor,將來只要讀這個 fd (block/non-block) 就可以取得 event,可以視為一個 event queue,然後把想要監控的檔案、訊息透過 inotify_add_watch 就可以加入監控的列表。接下來只要讀取剛剛取得的 fd 就可以了。需要注意的地方是,如果監控的目標是 directory,那 read 用的 buffer 以及 size 必須包含檔案名稱的大小然後一起 read,不然會有 EINVAL 的錯誤。

以前就聽過看過這東西,這次會翻出來是因為我正在用 latex 寫一篇文章但每次都要 compile/make 實在很麻煩(雖然說 vim 可以設 key binding 來直接 make 可是還是懶了點)於是就寫了一個等某個 inotify event 的小程式,有一個叫做 inotify-tools 的工具包裡面有 inotifywait 但是他只能針對某個存在的 file 進行監控,而 vim 在寫檔時會移動/刪除原本的檔案,造成監控中斷,所以我只好另外寫了這個 tool 對於目前的 WD 內特定的 filename 的某些特定 event 做等待。也就是說我監控的對象是這個 directory 但是我只 care 某個特定檔案發生的某些 event。

以下是我寫的 iwatch, 以 MIT License 釋出。
http://moon.cse.yzu.edu.tw/~s961449/iwatch.c


應用在我上面提到的自動編譯 latex, 可以用這個  bash script:
#!/bin/bash
id=0
while iwatch -e modify proposal.tex
do
kill -KILL $id
make
acroread proposal.pdf &
id=$!
done
執行這個 script 會監控目標 .tex 發現更變以後自動重新 make, 然後打開 pdf viewer,這邊是用 acroread,也可以用 foxit (比較快)。