我如何重新定义我的宏来接受字符代码而不是字符?

我如何重新定义我的宏来接受字符代码而不是字符?

我最近发过这个答案如何突出显示紧跟等号的所有形式为 [0-9][A-Za-z0-9]* 的单词?。它可以工作,但是存在(大量)代码重复的问题。

我目前拥有的

更具体地说,我必须使用以下形式

\lst@DefSaveDef{`<char>}\jubobs@<char>{\jubobs@<char>\foo}

不少于52次,用于<char>-AZ- az供参考,\lst@DefSaveDef是一个listings内部宏,其语法如下:

\lst@DefSaveDef{<charcode>}<some-macro>{<replacement-text>}

使用我的新认识\expandafter,我设法通过定义一个以字母作为参数并执行与上面所示相同的操作的宏来稍微减少代码:

\makeatletter
\newcommand\addtoletterdef[1]
{%
  \expandafter\expandafter\expandafter\lst@DefSaveDef%
  \expandafter\expandafter\expandafter{%
  \expandafter\expandafter\expandafter`%
  \expandafter\expandafter\expandafter#1%
  \expandafter\expandafter\expandafter}%
  \expandafter\csname jubobs@#1\expandafter\endcsname%
  \expandafter{\csname jubobs@#1\endcsname\foo}%
}
\makeatother

但是,这对减少代码重复并没有太大帮助:我仍然需要调用\addtoletterdef52 次……;...(

我想要的是

我想定义一个类似于我的宏\addtoletterdef,但它接受的是字符代码而不是字符。这样,就可以轻松循环遍历字符代码 65 到 90 (AZ) 和 97 到 122 (az),并执行所有这 52 个操作,而不会出现任何代码重复。

我觉得答案在于使用\begingroup\lccode诡计但这个技巧对我来说太新了,我还远远没有掌握它。

我如何重新定义\addtoletterdef以接受字符代码而不是字符?


梅威瑟:

\documentclass{article}

\usepackage{listings}

% dummy macro
\def\foo{foo}

\makeatletter
\newcommand\addtoletterdef[1]
{%
  \expandafter\expandafter\expandafter\lst@DefSaveDef%
  \expandafter\expandafter\expandafter{%
  \expandafter\expandafter\expandafter`%
  \expandafter\expandafter\expandafter#1%
  \expandafter\expandafter\expandafter}%
  \expandafter\csname jubobs@#1\expandafter\endcsname%
  \expandafter{\csname jubobs@#1\endcsname\foo}%
}
\makeatother

\lstdefinestyle{mycode}
{
  language=C,
  SelectCharTable=
      \addtoletterdef{A}
      % ...
      \addtoletterdef{Z}
      \addtoletterdef{a}
      % ...
      \addtoletterdef{z}
}

\begin{document}
\begin{lstlisting}[style=mycode]
a1 = 6.12234Z
a2 = Z1324124
\end{lstlisting}
\end{document}

答案1

您可以\lstdefine分部分构建,并将其添加到令牌寄存器中:

\documentclass{article}

\usepackage{xcolor}
\usepackage{textcomp}
\usepackage{listings}

\makeatletter

\newif\iffirstchar\firstchartrue
\newif\ifstartedbyadigit
\newif\ifprecededbyequalsign

\newcommand\processletter
{%
  \ifnum\lst@mode=\lst@Pmode%
    \iffirstchar%
        \global\startedbyadigitfalse%
      \fi
      \global\firstcharfalse%
    \fi
}

\newcommand\processdigit
{%
  \ifnum\lst@mode=\lst@Pmode%
      \iffirstchar%
        \global\startedbyadigittrue%
      \fi
      \global\firstcharfalse%
  \fi
}

\lst@AddToHook{OutputOther}%
{%
  \lst@IfLastOtherOneOf{=}
    {\global\precededbyequalsigntrue}
    {}%
}

\lst@AddToHook{Output}%
{%
  \ifprecededbyequalsign%
      \ifstartedbyadigit%
        \def\lst@thestyle{\color{Numbers}}%
      \fi
    \fi
  \global\firstchartrue%
  \global\startedbyadigitfalse%
  \global\precededbyequalsignfalse%
}


\definecolor{Code}{RGB}{0,0,0}
\definecolor{Keywords}{RGB}{255,0,0}
\definecolor{Strings}{RGB}{255,0,255}
\definecolor{Comments}{RGB}{0,0,255}
\definecolor{Numbers}{RGB}{255,128,0}

\newtoks\jubo@toks
\jubo@toks={
  language=C,
  commentstyle=\color{Comments}\slshape,
  stringstyle=\color{Strings},
  keywordstyle={\color{Keywords}\bfseries},
  alsoletter=0123456789,
  SelectCharTable=%
}
\def\add@savedef#1#2{%
  \begingroup\lccode`?=#1\relax
  \lowercase{\endgroup
  \edef\@temp{%
    \noexpand\lst@DefSaveDef{\number#1}%
    \expandafter\noexpand\csname lsts@?\endcsname{%
      \expandafter\noexpand\csname lsts@?\endcsname\noexpand#2}%
  }}%
  \jubo@toks=\expandafter{\the\expandafter\jubo@toks\@temp}%
}
\count@=`0
\loop
  \add@savedef\count@\processdigit
  \ifnum\count@<`9
  \advance\count@\@ne
\repeat
\count@=`A
\loop
  \add@savedef\count@\processletter
  \ifnum\count@<`Z
  \advance\count@\@ne
\repeat
\count@=`a
\loop
  \add@savedef\count@\processletter
  \ifnum\count@<`z
  \advance\count@\@ne
\repeat
%\showthe\jubo@toks % for debugging
\begingroup\edef\x{\endgroup
  \noexpand\lstdefinestyle{mycode}{\the\jubo@toks}
}\x

\makeatother

\begin{document}

\begin{lstlisting}[style=mycode]
int main ()
{
    printf("foo 3a a3")
    //this is an example
    a1 = 0;
    a2 = a1;
    a3 = 16hxFF;
    a4 = 16 + a1;
    // sanity check
    a5 =+ 16hFF /* 16hFF is not highlighted because not it's
                   immediately preceded by an equal sign */
    return 0;
}
\end{lstlisting}

\end{document}

在此处输入图片描述

\jubo@toks只是为了检查,这是第 6 步之前的值

language=C, commentstyle=\color {Comments}\slshape , stringstyle=\color {Str
ings}, keywordstyle={\color {Keywords}\bfseries }, alsoletter=0123456789, Selec
tCharTable=\lst@DefSaveDef {48}\lsts@0 {\lsts@0 \processdigit }\lst@DefSaveDef 
{49}\lsts@1 {\lsts@1 \processdigit }\lst@DefSaveDef {50}\lsts@2 {\lsts@2 \proce
ssdigit }\lst@DefSaveDef {51}\lsts@3 {\lsts@3 \processdigit }\lst@DefSaveDef {5
2}\lsts@4 {\lsts@4 \processdigit }\lst@DefSaveDef {53}\lsts@5 {\lsts@5 \process
digit }\lst@DefSaveDef {54}\lsts@6 {\lsts@6 \processdigit }\lst@DefSaveDef {55}
\lsts@7 {\lsts@7 \processdigit }\lst@DefSaveDef {56}\lsts@8 {\lsts@8 \processdi
git }\lst@DefSaveDef {57}\lsts@9 {\lsts@9 \processdigit }\lst@DefSaveDef {65}\l
sts@A {\lsts@A \processletter }\lst@DefSaveDef {66}\lsts@B {\lsts@B \processlet
ter }\lst@DefSaveDef {67}\lsts@C {\lsts@C \processletter }\lst@DefSaveDef {68}\
lsts@D {\lsts@D \processletter }\lst@DefSaveDef {69}\lsts@E {\lsts@E \processle
tter }\lst@DefSaveDef {70}\lsts@F {\lsts@F \processletter }\lst@DefSaveDef {71}
\lsts@G {\lsts@G \processletter }\lst@DefSaveDef {72}\lsts@H {\lsts@H \processl
etter }\lst@DefSaveDef {73}\lsts@I {\lsts@I \processletter }\lst@DefSaveDef {74
}\lsts@J {\lsts@J \processletter }\lst@DefSaveDef {75}\lsts@K {\lsts@K \process
letter }\lst@DefSaveDef {76}\lsts@L {\lsts@L \processletter }\lst@DefSaveDef {7
7}\lsts@M {\lsts@M \processletter }\lst@DefSaveDef {78}\lsts@N {\lsts@N \proces
sletter }\lst@DefSaveDef {79}\lsts@O {\lsts@O \processletter }\lst@DefSaveDef {
80}\lsts@P {\lsts@P \processletter }\lst@DefSaveDef {81}\lsts@Q {\lsts@Q \proce
ssletter }\lst@DefSaveDef {82}\lsts@R {\lsts@R \processletter }\lst@DefSaveDef 
{83}\lsts@S {\lsts@S \processletter }\lst@DefSaveDef {84}\lsts@T {\lsts@T \proc
essletter }\lst@DefSaveDef {85}\lsts@U {\lsts@U \processletter }\lst@DefSaveDef
 {86}\lsts@V {\lsts@V \processletter }\lst@DefSaveDef {87}\lsts@W {\lsts@W \pro
cessletter }\lst@DefSaveDef {88}\lsts@X {\lsts@X \processletter }\lst@DefSaveDe
f {89}\lsts@Y {\lsts@Y \processletter }\lst@DefSaveDef {90}\lsts@Z {\lsts@Z \pr
ocessletter }\lst@DefSaveDef {97}\lsts@a {\lsts@a \processletter }\lst@DefSaveD
ef {98}\lsts@b {\lsts@b \processletter }\lst@DefSaveDef {99}\lsts@c {\lsts@c \p
rocessletter }\lst@DefSaveDef {100}\lsts@d {\lsts@d \processletter }\lst@DefSav
eDef {101}\lsts@e {\lsts@e \processletter }\lst@DefSaveDef {102}\lsts@f {\lsts@
f \processletter }\lst@DefSaveDef {103}\lsts@g {\lsts@g \processletter }\lst@De
fSaveDef {104}\lsts@h {\lsts@h \processletter }\lst@DefSaveDef {105}\lsts@i {\l
sts@i \processletter }\lst@DefSaveDef {106}\lsts@j {\lsts@j \processletter }\ls
t@DefSaveDef {107}\lsts@k {\lsts@k \processletter }\lst@DefSaveDef {108}\lsts@l
 {\lsts@l \processletter }\lst@DefSaveDef {109}\lsts@m {\lsts@m \processletter 
}\lst@DefSaveDef {110}\lsts@n {\lsts@n \processletter }\lst@DefSaveDef {111}\ls
ts@o {\lsts@o \processletter }\lst@DefSaveDef {112}\lsts@p {\lsts@p \processlet
ter }\lst@DefSaveDef {113}\lsts@q {\lsts@q \processletter }\lst@DefSaveDef {114
}\lsts@r {\lsts@r \processletter }\lst@DefSaveDef {115}\lsts@s {\lsts@s \proces
sletter }\lst@DefSaveDef {116}\lsts@t {\lsts@t \processletter }\lst@DefSaveDef 
{117}\lsts@u {\lsts@u \processletter }\lst@DefSaveDef {118}\lsts@v {\lsts@v \pr
ocessletter }\lst@DefSaveDef {119}\lsts@w {\lsts@w \processletter }\lst@DefSave
Def {120}\lsts@x {\lsts@x \processletter }\lst@DefSaveDef {121}\lsts@y {\lsts@y
 \processletter }\lst@DefSaveDef {122}\lsts@z {\lsts@z \processletter }.

答案2

egreg研究中的循环绝对值得回答,但您也可以使用现有工具:

循环列表

代码复制了所有设置你的意见,然后它用来\xintApplyInline进行循环(不可扩展,它会经过这里;否则可以使用可\xintApplyUnbraced扩展地准备全部材料,然后再将其重新注入到标记流中,但这里不需要)。

\expandafter更新:我现在才注意到从原帖复制粘贴的内容中有一些多余的内容\addtoletterdef。人们之所以没有注意到它们,是因为\csname使用时宏是有意义的,\relax因此第二级的\expandafter无论如何都没有造成任何不良影响。(并且我还删除了一些不必要的%

\documentclass{article}
\usepackage{xinttools}% for expandable and non-expandable loops
\usepackage{listings}
\usepackage{xcolor}
\usepackage{textcomp}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% TAKEN OVER VERBATIM https://tex.stackexchange.com/a/164297/4686
%% (and egreg's answer)

\definecolor{Code}{rgb}{0,0,0}
\definecolor{Keywords}{rgb}{255,0,0}
\definecolor{Strings}{rgb}{255,0,255}
\definecolor{Comments}{rgb}{0,0,255}
\definecolor{Numbers}{rgb}{255,128,0}

\makeatletter

\newif\iffirstchar\firstchartrue
\newif\ifstartedbyadigit
\newif\ifprecededbyequalsign

\lst@AddToHook{OutputOther}%
{%
  \lst@IfLastOtherOneOf{=}
    {\global\precededbyequalsigntrue}
    {}%
}

\lst@AddToHook{Output}%
{%
  \ifprecededbyequalsign
      \ifstartedbyadigit
        \def\lst@thestyle{\color{orange}}%
      \fi
    \fi
  \global\firstchartrue
  \global\startedbyadigitfalse
  \global\precededbyequalsignfalse
}

\newcommand\processletter
{%
  \ifnum\lst@mode=\lst@Pmode
    \iffirstchar%
        \global\startedbyadigitfalse
      \fi
      \global\firstcharfalse
    \fi
}
\newcommand\processdigit
{%
  \ifnum\lst@mode=\lst@Pmode
      \iffirstchar
        \global\startedbyadigittrue
      \fi
      \global\firstcharfalse
  \fi
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% \addtoletterdef. Some \expandafter's removed!!

\newcommand\addtoletterdef[2]
{%
  \expandafter\lst@DefSaveDef
  \expandafter{%
  \expandafter`%
  \expandafter#2%
  \expandafter}%
  \csname jubobs@#2\expandafter\endcsname
  \expandafter{\csname jubobs@#2\endcsname #1}%
}
\makeatother

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% USE OF \xintApplyUnbraced to loop over letters or digits

\lstdefinestyle{mycode}
{
  language=C,
  commentstyle=\color{Comments}\slshape,
  stringstyle=\color{Strings},
  keywordstyle={\color{Keywords}\bfseries},
  alsoletter=0123456789,
  SelectCharTable=%
      \xintApplyInline{\addtoletterdef\processdigit}{0123456789}%
      \xintApplyInline{\addtoletterdef\processletter}
      {abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ}%
}

%% this is it!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\begin{document}\thispagestyle{empty}
\begin{lstlisting}[style=mycode]
int main ()
{
    printf("foo 3a a3")
    //this is an example
    a1 = 0;
    a2 = a1;
    a3 = 16hxFF;
    a4 = 16 + a1;
    // sanity check
    a5 =+ 16hFF /* 16hFF is not highlighted because not it's
                   immediately preceded by an equal sign */
    return 0;
}
\end{lstlisting}
\end{document}

相关内容