使用自然语法排版主题标签

使用自然语法排版主题标签

我在文档中使用在线对话,并创建了一个环境供其使用。问题是,许多每篇帖子中的 #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}

相关内容