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.

Václav Pavlík
  • 1,353
  • 11
  • 18
  • 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 Feb 12 '18 at 14:46

1 Answers1

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

egreg
  • 1,121,712