Scripting

如何防止在 Texmaker 更改時使用 fswatch 自動編譯循環?

  • May 16, 2021

在檢查了這個問題和未接受的答案後,我嘗試對其進行測試。首先,我使用以下命令測試了推薦的命令:

fswatch -o report.tex | xargs -n1 -I{} pdflatex report.tex

這導致了一個無限的編譯循環,我認為它的效率有點低,此外,它沒有創建一個足夠長的機會視窗來訪問 PDF。因此,我嘗試使用文件中的 TexMaker 中的命令來調試為什麼會fswatch產生無限編譯循環:ctrl+s``report.tex

fswatch -o report.tex | xargs -n1 -I{} echo "hello world"
hello world
hello world

在那裡我觀察到ctrl+s/ 保存report.tex觸發器的兩個檢測到的變化fswatch。此外,我f6在 TexMaker 中的命令以及命令上對其進行了測試pdflatex report.tex,並觀察fswatch到兩次嘗試都檢測到 3 個更改:

fswatch -o report.tex | xargs -n1 -I{} echo "hello world"
hello world
hello world
hello world

後者似乎足以導致無限編譯循環。因此,我想問一下,report.tex當從 TexMaker 保存更改時,如何確保編譯一次?

我認為可能導致有效答案的子問題可能如下所列,但我沒有找到令人滿意的答案:

  • 例如, fswatch 是否有一個參數可以忽略n-miliseconds對下一個或下一個的更改n-changes?在我看來,文件的那部分3.2.3 Numeric Event Flags似乎fswatch 允許使用n-th事件標誌。然而,我還沒有成功地實現傳遞這樣一個參數來禁止編譯。
  • 或者我是否可以將參數傳遞給pdflatex報告以將編譯時檢測到的三個更改減少report.tex到零更改?
  • TexMaker 是否可以選擇report.tex在保存時將更改量從 2 減少到 1 ctrl+s

fswatch根據不同的作業系統使用不同的後端。讓我們假設整體行為是相同的。

fswatch在我的 Linux 系統上,使用(和 option )的嘗試-x給出PlatformSpecific的事件無助於區分讀取事件、寫入事件、打開事件和關閉事件以及許多其他可能的事件(請注意,Linux 的inotify甚至可以區分兩種類型的關閉事件,一種在沒有變化之後,一種在變化之後,這將有助於進一步)。這也是您獲得多個事件的原因。

從原始碼讀取將觸發編譯嘗試,其中將再次讀取此原始碼。循環創建。

這就是你所有問題的原因。您應該僅在寫入事件時觸發,並且僅在文件停止寫入時觸發,但fswatch將所有這些事件都視為PlatformSpecific。您需要(a)可以區分事件的工具,或者進行定期民意調查以比較日期或內容(我相信最後一部分是從 OP 的連結中接受的答案)。

您可以fswatch--one-eventxargs與 OP 連結的已接受答案結合的情況下使用模式,因此fswatch不會無限期地再次觸發,而是等待pdftex完成。當然,這樣做時您必須處理競爭條件,以防您錯過兩者之間的事件。

結論:不要試圖讓一切適應fswatchfswatch用更合適的工具來改變。


Linux 上的替代方法範例(因為這是與特定作業系統相關的,並且 OP 沒有說明我將使用此範例的作業系統)。

inotifywait具有監視寫入的正確選項,並且實際上只有寫入結束(因此不是 MODIFY 事件,而只有 CLOSE_WRITE 事件)。當文件實際被移動、刪除和替換時,可能還有其他事情需要檢查和適應,但我並沒有試圖弄清楚所有細節。所以:

inotifywait -m -e CLOSE_WRITE report.tex | xargs -n1 -I{} pdflatex report.tex

將是一個好的開始。

要提供事件循環:

inotifywait -m -r -e CLOSE_WRITE somedir | while read -r dir events filename; do
   if [ "$filename" != "${filename%.tex}" ]; then
       pdflatex "$dir/$filename"
   fi
done

可能是一個好的開始。除了…

唉,當然有一些警告,從包含空格或特殊字元的文件名開始。可以進一步解決它們,例如在輸出--format中似乎接受\0的情況(我認為這--csv還不夠),但是 shell 無法在讀取循環中處理這個問題。使用inotify工具而不是inotifywait命令的非 shell 工具遲早會更適合(例如:https ://pypi.org/project/inotify/ )。

引用自:https://unix.stackexchange.com/questions/649922