3

This is a follow-up question to my previous one on using special characters in user-defined commands. I have extended the command \Char{} to take an optional parameter for a fixed with. \Char{} is supposed to work in text mode and math mode.

The MWE

\documentclass{article}

\usepackage{lmodern}
\usepackage{xparse}
\usepackage{relsize}
\usepackage{amssymb}

\ExplSyntaxOn

\NewDocumentCommand \Char { o m } 
{
  \IfNoValueTF {#1}
  {
    \str_case_x:nnF { \tl_to_str:n {#2} }
    {
      {              } { \mbox{$\varepsilon$}           }
      { ##           } { \mbox{\texttt{\#}}             }
      { \c_tilde_str } { \mbox{\textscale{.87}{$\Box$}} }
    }
    { \mbox{\texttt{#2}} }
  }
  {
    \str_case_x:nnF { \tl_to_str:n {#2} }
    {
      {              } { \makebox[#1]{$\varepsilon$}           }
      { ##           } { \makebox[#1]{\texttt{\#}}             }
      { \c_tilde_str } { \makebox[#1]{\textscale{.87}{$\Box$}} }
    }
    { \makebox[#1]{\texttt{#2}} }
  }
}

\ExplSyntaxOff

\begin{document}

\Char{}\Char{~}\Char{#}\Char{x}
$\Char{}\Char{~}\Char{#}\Char{x}$
\Char[1em]{}\Char[1em]{~}\Char[1em]{#}\Char[1em]{x}
$\Char[1em]{}\Char[1em]{~}\Char[1em]{#}\Char[1em]{x}$

\end{document}

produces the desired result

desired result

However, is there a better way to implement this functionality based on expl3?

Bernard
  • 271,350
Matthias
  • 1,956
  • 1
    LaTeX3 is still not “complete” regarding document commands, so many things are still not done yet. – Manuel Nov 14 '17 at 11:51
  • @Manuel Does this mean I should leave the implementation as it is for now accepting the mixture of LaTeX3 and LaTeX2e? – Matthias Nov 14 '17 at 11:54
  • 2
    Yes. Only may be reduce duplication of code (e.g., only have one \str_case rather than having two of them, and may be moving \texttt out of the cases if possible, i.e., \makebox{\texttt{\str_case .. }}). – Manuel Nov 14 '17 at 11:57
  • 2
    it depends if you want to optimise run time or optimise your developer time, I'd consider using O{\width} instead of o and then you don't need the IfNoValue test you can just use the \makebox form always as \makebox[\width]{zzz} is the same as \mbox{\zzz} just marginally less efficient. but it would halve the size of your definition and save you checking the two halves were in sync as you add more cases. – David Carlisle Nov 14 '17 at 12:24

2 Answers2

5

You can use this as a starter:

\documentclass{article}

\usepackage{lmodern}
\usepackage{xparse}
\usepackage{relsize}
\usepackage{amssymb}

\ExplSyntaxOn

\NewDocumentCommand \Char { o m } 
{
    \IfNoValueTF { #1 } { \makebox } { \makebox [#1] }
    {
    \str_case_x:nnF { \tl_to_str:n {#2} }
    {
      {              } { $\varepsilon$           }
      { ##           } { \texttt{\#}             }
      { \c_tilde_str } { \textscale{.87}{$\Box$} }
    }
    { \texttt{#2} }
  }
}

\ExplSyntaxOff

\begin{document}

\Char{}\Char{~}\Char{#}\Char{x}
$\Char{}\Char{~}\Char{#}\Char{x}$
\Char[1em]{}\Char[1em]{~}\Char[1em]{#}\Char[1em]{x}
$\Char[1em]{}\Char[1em]{~}\Char[1em]{#}\Char[1em]{x}$

\end{document}
TeXnician
  • 33,589
5

Using the fact that \makebox[\width]{...} is a slightly slower version of \mbox{...}, we can trade a bit of efficiency with avoidance of code duplication.

\documentclass{article}

\usepackage{lmodern}
\usepackage{xparse}
\usepackage{relsize}
\usepackage{amssymb}

\ExplSyntaxOn

\NewDocumentCommand \Char { O{\width} m }
 {
  \str_case_x:nnF { \tl_to_str:n {#2} }
   {
    {              } { \makebox[#1]{$\varepsilon$}           }
    { ##           } { \makebox[#1]{\texttt{\#}}             }
    { \c_tilde_str } { \makebox[#1]{\textscale{.87}{$\Box$}} }
   }
   { \makebox[#1]{\texttt{#2}} }
 }

\ExplSyntaxOff

\begin{document}

\Char{}\Char{~}\Char{#}\Char{x}
$\Char{}\Char{~}\Char{#}\Char{x}$
\Char[1em]{}\Char[1em]{~}\Char[1em]{#}\Char[1em]{x}
$\Char[1em]{}\Char[1em]{~}\Char[1em]{#}\Char[1em]{x}$

\end{document}

enter image description here

egreg
  • 1,121,712