Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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?

share|improve this question
add comment

2 Answers

up vote 3 down vote accepted

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

share|improve this answer
1  
I was thinking of adding a lpeg based solution, but your solution is cleaner. –  Aditya Mar 17 '12 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 '12 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 '12 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 '12 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 '12 at 15:15
add comment
\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

share|improve this answer
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 '12 at 11:21
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.