標籤:

有啥辦法能讓listings去檢查源代碼是不是和tex文件里一樣,而不是直接把那幾行input進來?

我覺得複製粘貼一遍問題不大。倒是源代碼改了,tex文件不改,結果就錯了,這個比較麻煩。


強烈建議 @劉海洋 的一般方法。

LaTeX 可以藉助 verbatim 宏包來比較每一行,大概是下面這樣子。

documentclass{article}

usepackage{verbatim}

makeatletter

% 參數 #1 是外部源文件行號,#2 是文件名稱。

ewenvironment{cmpcode}[2]{%
egingroup@verbatimfrenchspacing@vobeyspaces
IfFileExists{#2}{%
openinverbatim@in@stream@filef@und
elax
skip@beginline{#1}%
letverbatim@processlineverbatim@compareline
}{%
@latex@error{No file #2.}@ehd
}%
verbatim@start
}{%
closeinverbatim@in@stream
endverbatim
}
defskip@beginline#1{%
scr@lineno=#1
elax
count@=scr@lineno
loop
ifnum count@ &> @ne

eadverbatim@in@stream to@tempa
advancecount@m@ne

epeat
}

ewcountscr@lineno
defverbatim@compareline{%
egingroup
edef@tempa{ heverbatim@line}%
endlinecharm@ne

eadverbatim@in@stream to@tempb
ifx@tempa@tempb
else
oks@expandafter{@tempb}%
verbatim@mismatcherror
fi
endgroup
advancescr@lineno@ne
verbatim@printline
}
defverbatim@mismatcherror{%
@latex@error{%
Line mismatch! MessageBreak
* LaTeX line ( heinputlineno): heverbatim@lineMessageBreak
* source line ( hescr@lineno): he oks@
}@ehd
}
defverbatim@printline{ heverbatim@linepar}

makeatother

egin{document}

egin{cmpcode}{1}{jobname.tex}
documentclass{article}

usepackage{verbatim}

makeatletter
end{cmpcode}

end{document}

不是很複雜。

如果還要 listings 包的高亮效果,可能需要處理兩遍。第一遍是比較和把源文件輸出到外部輔助文件,第二遍再把輔助文件 lstinputlisting 進來。

pdfTeX 由於有原語 pdfmdfivesum(LuaTeX 可以藉助 pdftexcmds 宏包的 pdf@filemdfivesum),所以也可以把要比較的代碼輸出到兩個小文件中,再通過文件的 pdfmdfivesum 來比較。


顯示文件還是用

lstinputlisting[linerange={5-10}]{foo.c}

這種東西,別用 TeX 搞奇怪的功能。TeX 是排版軟體,不是 diff,不是版本管理軟體,不是回歸測試軟體。

你要檢查 C 文件 foo.c 的第 5 行到第 10 行行號變了沒有。這是個與 TeX 無關的問題。你可以用任何腳本或者 C 代碼來檢查,也可以藉助版本管理工具,具體做法不重要,但都比寫 TeX 代碼舒心。

現在來說一個更有價值的辦法,就是直接從源代碼中抽取需要的部分顯示。簡單的辦法就是,在注釋中做標記。比如說我們規定

// &<&<&&>&>

表示一個名為 foo 的代碼塊。現在寫一個 python3 腳本

#! /usr/bin/env python3
import sys
import re
if len(sys.argv) != 4:
print("Usage: %s src dst label" % sys.argv[0])
exit(0)
_, src_name, dst_name, label = sys.argv
with open(src_name) as src, open(dst_name, "w") as dst:
match = False
for line in src:
if re.match(r"^//s*&<&<&&>&>", line):
break
if match:
dst.write(line)

就行了。


推薦閱讀:

TeX Live 2015 有哪些值得關注的新特性?
如何從零開始,入門 LaTeX?
有沒有和writelatex(現在叫overleaf)一樣好用的本地tex IDE?如果沒有,為什麼沒有?
LaTeX 怎麼讓第二頁的頁碼變為 1,封面不標頁碼?
如何在Latex中畫這種根樹圖形?

TAG:LaTeX |