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.

  • 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
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

  • I knew it would be easy in ltx3 – daleif Feb 12 '18 at 15:03
  • Was working on a answer, but wanted to wait until you replied: outstanding! (+1) – caverac Feb 12 '18 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. – Václav Pavlík Feb 12 '18 at 15:45
  • @VáclavPavlík Waiting for the students to complete their Calculus test. Doing LaTeX is much funner. ;-) – egreg Feb 12 '18 at 15:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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