4

How can I define an environment that would treat each word or group as an argument of a function?

I am writing a handbook that contains calculator entries, which I would like to typeset as buttons. So far, I am typesetting the buttons with tikz, but repeating the same command over and over again makes the code unreadable even if the command is just one letter long.

The tikz command is taken from here

\usepackage{tikz}
\usetikzlibrary{shadows}
\newcommand*\x[1]{% keystroke
  \tikz[baseline=(key.base)]
  \node[draw, fill=white,
        drop shadow={shadow xshift=0.25ex,shadow yshift=-0.25ex,fill=black,opacity=0.75},
        rectangle, rounded corners=2pt, inner sep=2pt,
        line width=0.5pt, font=\normalsize\sffamily
       ](key) {#1\strut};
}

I use it, e.g., as

\begin{quote}
  \x{(}\x{4}\x{EXP}\x{2}\x{)}\x{$\div$}\x{(}\x{3}\x{EXP}\x{4}\x{)}\x{=}
\end{quote}

which creates a mess. I would much rather have an environment

\newenvironment{calc}{%
  % the wanted definitions for my commands here
  \begin{quote}
}{%
  \end{quote}
}

that would take separate words or groups

\begin{calc}
  ( 4 EXP 2 ) {$\div$} ( 3 EXP 4 ) =
\end{calc}

and produced the same result.

typeset buttons

I have found that very similar behaviour can be achieved for tables using \catcode here but I was not able to make it work for my case.

1
  • First you could use the environ package to collect the contents to a macro. Then you just need to split that on spaces or similar, there is probably an answer somewhere on the site as to how to do that.
    – daleif
    Commented Feb 12, 2018 at 14:46

1 Answer 1

5

Split first at \\, then at spaces:

\documentclass[11pt,a4paper]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{environ,xparse}
\usepackage{tikz}
\usepackage{newunicodechar}

\usepackage{lipsum}

\usetikzlibrary{shadows}

\newunicodechar{÷}{\ensuremath{\div}}

\newcommand*\keystroke[1]{%
  \tikz[baseline=(key.base)]
    \node[%
      draw,
      fill=white,
      drop shadow={shadow xshift=0.25ex,shadow yshift=-0.25ex,fill=black,opacity=0.75},
      rectangle,
      rounded corners=2pt,
      inner sep=1pt,
      line width=0.5pt,
      font=\scriptsize\sffamily
    ](key) {#1\strut}
  ;
}

\ExplSyntaxOn
\NewEnviron{calculator}
 {
  \begin{quote}
  \pavlik_calculator:V \BODY
  \end{quote}
 }
\cs_new_protected:Nn \pavlik_calculator:n
 {
  \seq_set_split:Nnn \l_tmpa_seq { \\ } { #1 }
  \seq_map_function:NN \l_tmpa_seq \pavlik_calculator_line:n
 }
\cs_generate_variant:Nn \pavlik_calculator:n { V }
\cs_new_protected:Nn \pavlik_calculator_line:n
 {
  \seq_set_split:Nnn \l_tmpb_seq { ~ } { #1 }
  \seq_map_function:NN \l_tmpb_seq \keystroke
  \par
 }
\ExplSyntaxOff

\begin{document}

\lipsum*[3]
\begin{calculator}
  ( 4 EXP 2 ) ÷ ( 3 EXP 4 ) = \\
  ( SIN PI )
\end{calculator}
\lipsum[4]

\end{document}

enter image description here

4
  • I knew it would be easy in ltx3
    – daleif
    Commented Feb 12, 2018 at 15:03
  • Was working on a answer, but wanted to wait until you replied: outstanding! (+1)
    – caverac
    Commented Feb 12, 2018 at 15:11
  • It works even with spaces if I surround the text with {}. It is a privilege to see your work. And you replied so fast as well. Thanks a lot. Commented Feb 12, 2018 at 15:45
  • @VáclavPavlík Waiting for the students to complete their Calculus test. Doing LaTeX is much funner. ;-)
    – egreg
    Commented Feb 12, 2018 at 15:47

You must log in to answer this question.

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