我在文档中使用在线对话,并创建了一个环境供其使用。问题是,许多每篇帖子中的 #hashtags(我想适当着色)。为了使其更具可读性,我想创建#
一个活动字符,并将所有内容从用法转移到下一个井号 ( #
) 或空格。
救救我,我#迷失了。
救救我,我#迷失了!
有史以来最好的 #tex #latex #plain_text
什么?#困惑#迷失#节省空间
我认为与主题标签匹配的正则表达式可以像一样简单#[\-_A-Za-z]
,因此补语表示中断。
当我试图弄清楚这一点时,‘非此即彼’的方面太多了,我无法理解,但这是理想的。我只是决定让它活跃起来#
。但当你考虑它时,你不可能为此设置宏参数。你没有任何具有适当 catcode (6) 的字符。所以,使用不同的字符,对吗?不幸的是,这不起作用:
\documentclass{article}
\usepackage{xcolor}
\begin{document}
\newcommand\maketag[1]{\textcolor{cyan}{\##1}}
\newenvironment{post}[2]{%
#1 said on #2:\quote
\catcode`"=6
\catcode`\#=13
\def\#""1 {\maketag{""1}}%
}{%
\catcode`"=12 % edit: wasn't needed at all..
\catcode`\#=6 % #late_night_mistakes
\endquote
}
\begin{post}{Sean Allred}{yesterday}
#hello
\end{post}
\end{document}
ERROR: Undefined control sequence. --- TeX said --- l.16 # hello --- HELP --- TeX encountered an unknown command name. You probably misspelled the name. If this message occurs when a LaTeX command is being processed, the command is probably in the wrong place---for example, the error can be produced by an \item command that's not inside a list-making environment. The error can also be caused by a missing \documentclass command.
我怎样才能获得我想要的行为?
我非常乐意expl3
回答:)
答案1
\documentclass{article}
\usepackage{xcolor}
\usepackage[T1]{fontenc}
\begin{document}
\def\hashtag{%
\textcolor{cyan}{\#}%
\begingroup
\color{red}%
\xhashtag}
\def\xhashtag{\futurelet\tmp\xxhashtag}
\def\xyhashtag#1{\xhashtag}
\def\xxhashtag{%
\ifcat a\noexpand\tmp
\tmp\expandafter\xyhashtag
\else
\endgroup
\fi}
\newenvironment{post}[2]{%
#1 said on #2:\quote
\catcode`\#\active
\catcode`\-11 %
\catcode`\_11 %
\lccode`\~`\#%
\lowercase{\let~}\hashtag
}{%
\endquote
}
\begin{post}{Sean Allred}{yesterday}
Help me, I'm #lost.
Help me, I'm #lost!
Best ever #tex #latex #plain_text
What? #confused#lost#saving-space
\end{post}
\end{document}
答案2
至少有几种方法可以做到这一点:更改 catcode 或使用\lowercase
“技巧”。既然您已经开始使用 catcode,我会坚持使用这种方法。您需要记住的是,当您这样做时,您正在对材料进行标记\newenviroment
。因此,您需要更改 catcode前定义:
\documentclass{article}
\newcommand\maketag[1]{\##1}
\catcode`\"=6 %
\catcode`\#=\active
\newenvironment{post}{%
\def#""1 {\maketag{""1}}%
\catcode`\#=\active
\quote
}{%
\endquote
}
\catcode`\"=12 %
\catcode`\#=6 %
\begin{document}
\begin{post}
#hello
\end{post}
\end{document}
请注意,在环境中,我们只需要更改 catcode"
:我们需要定义具有"
参数 char,但没有读环境。这里只有环境#
有特殊处理。还请注意,由于环境形成组,因此无需担心重置\endpost
宏中的 catcode(环境结束参数)。
相比之下,该\lowercase
方法如下
\documentclass{article}
\newcommand\maketag[1]{\##1}
\newenvironment{post}{%
\begingroup
\lccode`\~=\#
\lowercase{%
\endgroup
\def~##1}{\maketag{##1}}%
\catcode`\#=\active
\quote
}{%
\endquote
}
\begin{document}
\begin{post}
#hello
\end{post}
\end{document}
在这里,我不必处理 catcode,只需#
在环境中使其处于活动状态即可。这里的想法是~
无论如何都是活动的,因此我可以将其小写为 a #
(保持活动状态),同时使用“正常”#
来设置定义。
顺便说一句,请注意,在这两种情况下,我们都需要将参数 char 加倍,因为#1
(标准 catcodes)指的是环境本身的任何参数。我不明白你为什么要[2]
为此设置参数,所以我放弃了它!
答案3
可随意定制(但当然比较慢):
\documentclass{article}
\usepackage{xcolor,environ,xparse,l3regex}
\ExplSyntaxOn
\NewDocumentEnvironment{post}{mm}
{
\char_set_catcode_other:N \# % change the catcode not to confuse \innerpost
\char_set_catcode_other:N \_
#1~said~on~#2\tl_to_str:n {:}\quote
\innerpost % absorb the contents
}
{
\endinnerpost\endquote
}
\NewEnviron{innerpost}
{
\regex_replace_all:nnN
{ \#([[:word:]\-]*) }
{ \c{texttt}\cB\{\c{coloredhash}\1\cE\} }
\BODY
\BODY
}
\ExplSyntaxOff
\newcommand\coloredhash{\textcolor{cyan}{\#}}
\begin{document}
\begin{post}{Sean Allred}{yesterday}
Help me, I'm #lost.
Help me, I'm #lost!
Best ever #tex #latex #plain_text
What? #confused#lost#saving-space
\end{post}
\end{document}
进一步定制的示例,假设您想要接受主题标签中的重音字符,则\usepackage[utf8]{inputenc}
只需将搜索正则表达式更改为
{ \#((\c[LA][^\~]|\_|\-)*) }
它匹配字母、活动字符(~ 除外)、连字符和下划线的任意组合。
基于的解决方案\ifcat
将需要更多的测试。
答案4
这段简短的代码在环境中设置了“#”为活动状态,并定义#
为(在这种情况下)等于\#
(检查方便的函数\char_set_active:Npn
或\char_set_eq:NN
)。
\documentclass{scrartcl}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentEnvironment { post } { }
{ \quote \char_set_active_eq:NN \# \# }
{ \endquote }
\ExplSyntaxOff
\begin{document}
\begin{post}
#hello
\end{post}
\end{document}
现在,更深层次的问题是如何处理“参数”。一种选择是吞下标记,直到找到非字母(最终由 David 回答)。另一种选择是l3regex
(egreg 采取了类似的方法)。在这种情况下,由于_
是非字母(下标),因此这不会处理#something_like_this
,但您可以随时更改 catcode。
\documentclass{scrartcl}
\usepackage[T1]{fontenc}
\usepackage{environ,l3regex,xparse,xcolor}
\ExplSyntaxOn
\NewEnviron { post }
{
\tl_set:No \l_tmpa_tl { \BODY }
\regex_replace_all:nnN
{ (\#)([\w\-]+) } { \c{textcolor}\cB\{cyan\cE\}\cB\{\c{\#}\2\cE\} }
\l_tmpa_tl
\tl_use:N \l_tmpa_tl
}
\ExplSyntaxOff
\begin{document}
\begin{post}
#hello #ratata And not a hashtag, and a
#hashtag#another#another with #hyphens-but
(\string_ doesn't work)
\end{post}
\end{document}