5

I have a macro which contains some text:

\textmacro{This is some text.}

Normally, when compiled, it should just print text, like this:

This is some text.

Sometimes, the text contains “①”and “②”, such as this:

\textmacro{①  This is some text. ② This is some other text.}

When that happens, I need it to only print the text appearing between “①”and “②”, like this:

This is some text.

How can I make the macro print the text between “①” and “②” in #1, if those symbols appear, otherwise, to just print all of the text?

2 Answers 2

3

You want a ConTeXt answer, right? Whenever I catch myself thinking "I know how to do this in an ordinary programming language", I shunt the text I want to operate on into LuaTeX. Taking the template from the wiki:

% First, the Lua function that will process the string
\startluacode
    -- remember, using the userdata namespace prevents conflicts
    userdata = userdata or {}

    function userdata.printBetweenMarks(str, m1, m2)
        -- default delimiters
        m1 = m1 or '①'
        m2 = m2 or '②'

        match_pattern = string.format('%s(.*)%s', m1, m2)
        str = string.match(str, match_pattern) or str
        context(str)
    end
\stopluacode

% Secondly, the ConTeXt command that passes the string to the Lua function.

\def\textmacro#1%
    {\ctxlua{userdata.printBetweenMarks([===[#1]===])}}
    % Note that Lua sees the text as-is, so we have to wrap it in string
    % delimiters ourselves.
    % [=*[ is Lua's double-bracket string delimiter style; this way, the
    % code only fails if the text contains ']===]'.

EDIT: removed a print() statement I had used for debugging

5
  • 1
    I was thinking of adding a lpeg based solution, but your solution is cleaner.
    – Aditya
    Mar 17, 2012 at 23:25
  • 1
    Thanks! Add your solution anyway, perhaps, if you feel like it? There's More Than One Way To Do It, after all; and lpeg scales in complexity better than string.match; and reading your answer will help me improve my woeful lpeg knowledge/understanding. ;-)
    – Esteis
    Mar 17, 2012 at 23:39
  • Can userdata.printBetweenMarks([===[#1]===])} be placed within another \startlua and \stoplua? I tried placing it there, but just get errors.
    – Village
    Apr 3, 2012 at 5:36
  • @Village: that gives errors because you can't use #1 when you're not defining a TeX macro. (In my example, \ctxlua was part of a macro definition.) Things that will work: userdata.printBetweenMarks([=[① mystring ②]=]) (more on strings in Lua; and userdata.printBetweenMarks(str), where str is a variable containing the string you want to work on. Read this tutorial on LuaTeX for more info.
    – Esteis
    Apr 4, 2012 at 15:09
  • Three snippets that may help you: (1) \ctxlua{str = "mystring"} (or 'mystring', [[mystring]], [=[mystring]=], etc.); (2) \def\savestring#1{\ctxlua{str = "#1"}} followed by \savestring{asdf}; and (3) \def\passStringToFunction{\ctxlua{myfunction("#1")}}.
    – Esteis
    Apr 4, 2012 at 15:15
12
\documentclass{article}
\makeatletter
\def\textmacro#1{\expandafter\@textmacro#1①②\@nil}
\def\@textmacro#1①#2②#3\@nil{%
  \ifx\relax#2\relax#1\else#2\fi}
\makeatother
\begin{document}
\textmacro{This is some text.}\par
\textmacro{①  This is some text. ② This is some other text.}\par
\textmacro{This is some text ①  This is some other text. ② This is some text.}
\end{document}

enter image description here

1
  • 1
    Notice that if one uses this with pdflatex and \usepackage[utf8]{inputenc}, the second example fails because of the \expandafter. +1 anyway. :)
    – egreg
    Mar 17, 2012 at 11:21

You must log in to answer this question.

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