
一些程式編輯器和 IDE 以不同的方式突出顯示合法和非法變數名稱。我希望listings
能夠輕鬆地允許進行此類語法檢查和突出顯示,但至少目前還沒有。我的長期目標是實現一個相容的解決方案,listings
但目前,我正在研究問題的一個非常簡化的版本。
我想解析僅由字元和空格標記組成的標記流中的第一個單字。這是必須要做的一個又一個令牌不過,因為我必須對每個令牌執行一些檢查。為此,我使用遞歸巨集來解析流,將其保存在\Word
巨集中,直到.
遇到令牌。在那個階段,我會\Word
以某種方式進行處理,例如將其列印成紅色。我定義一個單字作為不受任何空間標記中斷的字元標記序列。
問題:我.
在這裡只使用令牌,因為我無法弄清楚應該在程式碼中更改什麼,以便.
在流中遇到下一個空格令牌(而不是令牌)時停止遞歸。用控制空間 ( \
)代替.
似乎無法解決問題。我應該在我的程式碼中更改什麼?
我喜歡使用低階 TeX 命令進行解析的解決方案,但我也對 LaTeX2e 和 LaTeX3 替代方案感興趣。
編輯:如果我似乎正在移動球門柱,我很抱歉,但我必須通過添加“逐個令牌”要求來澄清我的問題,這可能會使一些已經發布的答案無效。
\documentclass{article}
\usepackage{xcolor}
\def\ParseWordandPrint#1{%
\if #1.%
\textcolor{red}{\Word}\ %
\else
\edef\Word{\Word#1}
\expandafter\ParseWordandPrint
\fi%
}
\def\InitParseWordandPrint#1{%
\def\Word{}
\ParseWordandPrint#1%
}
\begin{document}
\InitParseWordandPrint Hello.World
\end{document}
答案1
根據您編輯的問題取消刪除此內容。
使用空格分隔的參數可以更容易一次性抓住這個詞,並且然後逐個字母地迭代該字母。 (作為一個例子,我在這裡檢查它們是字母,最後一個例子產生
illegal character 0
illegal character 1
要逐個字元地迭代,停在一個空格處,您傾向於使用\futurelet
(或等效的\@ifnextchar
),但在您要排版的單字中這並不是那麼好,因為很難不破壞字母間的字距和連字。所以先抓住這個字比較容易。
\documentclass{article}
\usepackage{xcolor}
\def\InitParseWordandPrint#1 {\check#1\relax\textcolor{red}{#1} }
\def\check#1{%
\ifx\relax#1%
\else
\ifcat a#1%
\else
\typeout{illegal character #1}%
\fi
\expandafter\check
\fi}
\begin{document}
\InitParseWordandPrint Hello World
\InitParseWordandPrint World
Hello World
\InitParseWordandPrint W0r1d
\end{document}
答案2
TeX\def
提供分隔參數文字。因此,在這種情況下,您可以使用空格作為分隔符號:
\documentclass{article}
\usepackage{xcolor}
\def\ParseWordandPrint#1{%
\if #1.%
\textcolor{red}{\Word}\ %
\else%
\edef\Word{\Word#1}%
\expandafter\ParseWordandPrint%
\fi%
}
\def\InitParseWordandPrint#1{%
\def\Word{}%
\ParseWordandPrint#1%
}
\def\highlightfirst#1 {\textcolor{red}{#1} }
\begin{document}
\InitParseWordandPrint Hello.World
\highlightfirst Hello World.
\end{document}
答案3
使用 LaTeX3 非常簡單:
\documentclass{article}
\usepackage{xparse,xcolor}
\ExplSyntaxOn
\NewDocumentCommand{\printfirstwordincolor}{ O{red} m }
{
\jubobs_pfwr:nn { #1 } { #2 }
}
\seq_new:N \l_jubobs_words_seq
\tl_new:N \l_jubobs_first_word_tl
\cs_new_protected:Npn \jubobs_pfwr:nn #1 #2
{
% split the input at spaces
\seq_set_split:Nnn \l_jubobs_words_seq { ~ } { #2 }
% pop off the leftmost item
\seq_pop_left:NN \l_jubobs_words_seq \l_jubobs_first_word_tl
% print the first item in the chosen color
\textcolor{#1}{ \l_jubobs_first_word_tl } ~ %
% print the other items adding spaces between them
\seq_use:Nn \l_jubobs_words_seq { ~ }
}
\ExplSyntaxOff
\begin{document}
\printfirstwordincolor{Hello World}
\printfirstwordincolor[green]{Addio mondo crudele}
\end{document}
如果您也想按令牌處理輸入令牌,則可以對已儲存的項目進行對應。假設您想將每個“d”大寫:
\documentclass{article}
\usepackage{xparse,xcolor}
\ExplSyntaxOn
\NewDocumentCommand{\printfirstwordincolor}{ O{red} m }
{
\jubobs_pfwc:nn { #1 } { #2 }
}
\seq_new:N \l_jubobs_words_seq
\tl_new:N \l_jubobs_first_word_tl
\bool_new:N \l_jubobs_first_item_bool
\cs_new_protected:Npn \jubobs_pfwc:nn #1 #2
{
\seq_set_split:Nnn \l_jubobs_words_seq { ~ } { #2 }
\seq_pop_left:NN \l_jubobs_words_seq \l_jubobs_first_word_tl
\textcolor{#1}{ \l_jubobs_first_word_tl } ~ %
\seq_use:Nn \l_jubobs_words_seq { ~ }
}
\NewDocumentCommand{\printfirstwordincolorandcapitalizeD} { O{red} m }
{
\jubobs_pfwcacd:nn { #1 } { #2 }
}
\cs_new_protected:Npn \jubobs_pfwcacd:nn #1 #2
{
\seq_set_split:Nnn \l_jubobs_words_seq { ~ } { #2 }
\leavevmode
\bool_set_true:N \l_jubobs_first_item_bool
\seq_map_inline:Nn \l_jubobs_words_seq
{
\bool_if:NT \l_jubobs_first_item_bool
{ \c_group_begin_token \color{#1} }
\tl_map_inline:nn { ##1 }
{
\peek_charcode_remove:NT d { D } ####1
}
\bool_if:NT \l_jubobs_first_item_bool
{ \c_group_end_token \bool_set_false:N \l_jubobs_first_item_bool }
\c_space_tl
}
\unskip
}
\ExplSyntaxOff
\begin{document}
\printfirstwordincolor{Hello World}
\printfirstwordincolorandcapitalizeD[blue]{Addio mondo crudele}
\end{document}