[Tex/LaTex] Typesetting hashtags with natural syntax

catcodesenvironmentsmacros

I'm using an online conversation in my document and I've made an environment to use for it. The thing is, there are many #hashtags in each post (that I'd like to color appropriately). To make it more readable, I want to make # an active character and take everything from the usage to either the next hash (#) or a space.

Help me, I'm #lost.

Help me, I'm #lost!

Best ever #tex #latex #plain_text

What? #confused#lost#savingspace

I suppose a regular expression that would match a hashtag could be as simple as #[\-_A-Za-z], so the complement would denote a break.

The 'either-or' aspect as too much to get my head around when trying to figure this out, but that's the ideal. I just decided to make # active. But when you think about it, there's no way you can have a macro argument for this. You don't have any characters with the appropriate catcode (6). So, use a different character, right? Unfortunately this doesn't work:

\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.

How can I get the behavior I want?

I'm more than open to expl3 answers 🙂

Best Answer

enter image description here

\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}