2

I need a Latex makro that recognizes the following syntax:

!!! note
       Custom text: This is a Admonition note in Markdown.

Is it possible to have a macro with the name !!! ? Or is there any other work around?

When I tried the makro didn't work:

\newcommand{!!!}{Latex Makro Text} 

% my document text
!!! 

The exclamation marks have not been replaced with "Latex Makro Text"

Thanks for your help!

Fabio

Contex:

I want to parse Markdown files with pandoc to PDF.

I build a latex Template and I use the Admonition Plugin to highlight warnings or notes. I want to my Latex Template to recognize the Admonition Syntax and style it appropriately. I am not very experienced with Latex.

1

3 Answers 3

4

(There must be a way to achieve your objective by making ! an "active" character and making it check if it's followed by exactly two more ! characters; if that's the case, make LaTeX print out a warning message; if it's not, simply put the exclamation mark token(s) back in the stream.)

Here's a LuaLaTeX solution, which scans the input stream for instances of !!! and replaces with them a suitably chosen warning message.

enter image description here

On the syntax to be used inside the string.gsub Lua function: Because Lua uses \ as an escape characters, it's necessary to type \\ to generate a (single) backslash.

\documentclass{article}

\usepackage{luacode,xcolor}
\begin{luacode}
  function triplebang ( s )
    return ( string.gsub ( s , '!!!', 
       '\\par\\bigskip\\noindent\\textcolor{red}{!!! ' ..
       'This is an admonition note. !!!}\\par\\bigskip ' ) ) 
  end
\end{luacode}
\AtBeginDocument{\directlua{luatexbase.add_to_callback (
   "process_input_buffer", triplebang, "triplebang" ) }}

\begin{document}
hello world!!!hello world!!hello world!hello world!!!hello world
\end{document}
5

I don't think this will be of much use anyway.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\tl_new:N \l_fabio_three_exclam_note_tl
\cs_new_protected:Npn \fabio_three_exclam:w
 {
  \peek_charcode_remove:NTF { ! }
   { \__fabio_three_exclam_aux:w }
   { ! }
 }
\cs_new_protected:Npn \__fabio_three_exclam_aux:w
 {
  \peek_charcode_remove:NTF { ! }
   { \tl_use:N \l_fabio_three_exclam_note_tl }
   { !! }
 }
\char_set_active_eq:NN ! \fabio_three_exclam:w
\char_set_catcode_active:N !

\NewDocumentCommand{\setnotetext}{m}
 {
  \tl_set:Nn \l_fabio_three_exclam_note_tl { #1 }
 }
\ExplSyntaxOff

\setnotetext{This is a Admonition note in Markdown.}

\begin{document}

This is silly! Really!! Well, it works.

!!!

Some text.

\end{document}

enter image description here

3
  • thanks for the help! in our company the user documentation is in markdown. For the web-view we use the admonition extension but some costumers also want a PDF version of the documentation. So we want to convert our existing files (with admonition) to PDF. Therefore we use pandoc and a custom Latex template Commented Nov 29, 2016 at 22:32
  • Wow the latex3 \char_set_active_eq:NN ! \fabio_three_exclam:w makes the code a lot more reasonable than the old method of lowercasing ~. I guess that \char_set_active_eq:NN must automatically check for commands of the form \theinputcommand_aux and apply itself to those too? Commented Nov 30, 2016 at 0:12
  • @HoodChatham The function \char_set_active:NN is an abstraction of the \lowercase trick, ending with \let~. There is no check to do.
    – egreg
    Commented Nov 30, 2016 at 7:01
3

(Please take this answer for a moot / rather "academical" thing.)

If you need to do without Lua-extensions, you can make ! an active character which causes TeX to "look" at the meaning of the next token via \futurelet (or via \let and \afterassignment which would require you to write things down in a way where \let gets all the optional spaces which it discards according to the TeXbook).

If the meaning of the next token equals the meaning of an active character, you can (without loosing braces) have TeX catch that next token as an undelimited argument and then by means of macros that internally use active ! as argument delimiter have TeX check if that token really is an active ! and not some control sequence or active non-!-character \let equal to active !.

\documentclass{article}
\usepackage{color}%

\makeatletter
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@Exchange[2]{#2#1}%
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
%% (\romannumeral expansion was introduced by me in order to overcome the
%% concerns and worries about improperly balanced \if..\else..\fi constructs.)
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
  \UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
\newcommand\UDtempa{}
\begingroup
\renewcommand\UDtempa[1]{%
  \endgroup
  %%-----------------------------------------------------------------------------
  %% Check whether brace-balanced argument starts with an active !
  %%.............................................................................
  %% \UD@CheckWhetherLeadingExclam{<Argument which is to be checked>}%
  %%                              {<Tokens to be delivered in case <argument
  %%                                which is to be checked>'s 1st token is an
  %%                                active exclamation mark>}%
  %%                              {<Tokens to be delivered in case <argument
  %%                                which is to be checked>'s 1st token is not
  %%                                an active exclamation mark>}%
  \newcommand\UD@CheckWhetherLeadingExclam[1]{%
    \romannumeral0\UD@CheckWhetherNull{##1}%
    {\expandafter\expandafter\UD@firstoftwo{ }{}\UD@secondoftwo}%
    {\expandafter\UD@secondoftwo\string{\UD@CheckWhetherLeadingExclamB.##1#1}{}}%
  }%
  \newcommand\UD@CheckWhetherLeadingExclamB{}%
  \long\def\UD@CheckWhetherLeadingExclamB##1#1{%
    \expandafter\UD@CheckWhetherNull\expandafter{\UD@secondoftwo##1{}}%
    {\UD@Exchange{\UD@firstoftwo}}{\UD@Exchange{\UD@secondoftwo}}%
    {\UD@Exchange{ }{\expandafter\expandafter\expandafter\expandafter
     \expandafter\expandafter\expandafter}\expandafter\expandafter
     \expandafter}\expandafter\UD@secondoftwo\expandafter{\string}%
  }%
  \newcommand#1{\futurelet\UDtempa\@ChkSecondExclam}%
  \newcommand\@ChkSecondExclam{%
    \ifx\UDtempa#1\expandafter\UD@firstoftwo\else\expandafter\UD@secondoftwo\fi
    {\@ChkThirdExclam}%
    {!}%
  }%
  \newcommand\@ChkThirdExclam[1]{%
    \UD@CheckWhetherLeadingExclam{##1}{\futurelet\UDtempa\@FinishChkThirdExclam}{!!}%
  }%
  \newcommand\@FinishChkThirdExclam{%
    \ifx\UDtempa#1\expandafter\UD@firstoftwo\else\expandafter\UD@secondoftwo\fi
    {\@gobbleactiveexclam}{!!}%
  }%
  \newcommand\@gobbleactiveexclam[1]{%
     \UD@CheckWhetherLeadingExclam{##1}{%
        \par\bigskip
        \noindent\textcolor{red}{\mbox{!!! This is an admonition note. !!!}}%
        \par\bigskip
     }{!!!}%
  }%
}%
\catcode`\!=13
\UDtempa{!}%<-this does the \endgroup
\makeatother

\begin{document}

\catcode`\!=13

hello world!!!hello world!!hello world!hello world!!!hello world

\bigskip

\let\misleading=!

hello world!\misleading!hello world!!hello world!hello world\misleading!\misleading hello world

\bigskip

But there is the edge case of a token \verb|\let| equal to active \verb|!| being trailed by two active \verb|!| :

hello world \misleading!!

\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .