menukeys icon indicating copy to clipboard operation
menukeys copied to clipboard

Provide the ability to typeset commands such as \menu{File>} and \menu{>Exit}

Open nplatis opened this issue 12 years ago • 4 comments

One feature I would like to suggest concerns menus: I would like to be able to write \menu{File>} and \menu{>Exit} and those items to be drawn correspondingly just as the pieces of \menu{File>Exit} would be drawn. Currently, both of these are drawn as single items, like \menu{File} and \menu{Exit}.

Of course, if you implement this, then also \menu{>Settings>} should be possible and drawn accordingly.

All the above will let us differentiate the menu, the commands, and the intermediate commands.

nplatis avatar Jun 28 '13 09:06 nplatis

Thanks for this request. At the moment it is possible to access the single style by additional macros:

\documentclass[parskip=full]{scrartcl}

\usepackage{menukeys}

\makeatletter
% it is necessary to define the style
\def\desiredstyle{menus}% replace 'menus' with your preferred style
% now one can define additional macros to access the single element styles
% single elements
\newcommand\menusingle[1]{%
    \def\CurrentMenuElement{#1}% define the element to typeset as the the macro argument
    \def\tw@current@color@theme{% define the color theme
        \csname tw@style@\desiredstyle @color@theme\endcsname
    }%
    \@nameuse{tw@style@\desiredstyle @single}% typeset the \CurrentMenuElement, i.e. the argument
}
% first elements
\newcommand\menufirst[1]{%
    \def\CurrentMenuElement{#1}%
    \def\tw@current@color@theme{\csname tw@style@\desiredstyle @color@theme\endcsname}%
    \@nameuse{tw@style@\desiredstyle @first}%
}
% middle elements
\newcommand\menumid[1]{%
    \def\CurrentMenuElement{#1}%
    \def\tw@current@color@theme{\csname tw@style@\desiredstyle @color@theme\endcsname}%
    \@nameuse{tw@style@\desiredstyle @mid}%
}
% last elements
\newcommand\menulast[1]{%
    \def\CurrentMenuElement{#1}%
    \def\tw@current@color@theme{\csname tw@style@\desiredstyle @color@theme\endcsname}%
    \@nameuse{tw@style@\desiredstyle @last}%
}
% create a macro for the separator
\newcommand{\menusep}{%
    \hspace{-0.2em}\hspace{0em plus 0.1em minus 0.05em}%
}
\makeatother

\begin{document}
    \menu{First>Mid>Mid>Last}

    \menusingle{Single}

    \menufirst{First}

    \menumid{Mid}

    \menulast{Last}

    In case of sequences some manual adjustmens are necessary:
    \menumid{Mid}\menusep\menulast{Last}
\end{document}

I’ll keep this request in mind for one of the next versions, but I’m busy at the moment so it probably takes some time …

tweh avatar Jun 28 '13 10:06 tweh

I already have an idea how this could be implemented. I'd add an option to specify how empty fields should be treated. Some key with the choices:

  • ignore-empty=none parse with the current rules (default behaviour)

  • ignore-empty=ends ignore empty fields on both ends (so ignore an empty first and last field), while still printing the separators

  • ignore-empty=all ignore all empty fields, while still printing the separators

  • ignore-empty=first only ignore the first field if it's empty

  • ignore-empty=last only ignore the last field if it's empty

Adding these rules to the current loop would be easy, and it would allow the syntax \menu{File>} as requested.

Skillmon avatar Nov 06 '20 15:11 Skillmon

But will this work, I have in mind that \seq_seq ignores empty elements by default, thus Menu>Item> would led to the same sequence as Menu>Item

tweh avatar Nov 06 '20 16:11 tweh

@tweh proof-of-concept (the following uses pgfkeys but of course could be implemented with other key=value interfaces), showing that the planned implementation works (this doesn't implement ignore-empty=all, since many things are potentially subject to changes, this isn't meant as the final implementation, just a quick and dirty adaptation).

\documentclass[]{article}

\usepackage{menukeys}

\makeatletter
\newif\iftw@mk@ignorefirst
\newif\iftw@mk@ignorelast
\pgfqkeys{/menukeys}
  {%
    ignore-empty/.is choice,
    ignore-empty/.cd,
                 none/.code  = \tw@mk@ignorefirstfalse \tw@mk@ignorelastfalse ,
                 first/.code = \tw@mk@ignorefirsttrue  \tw@mk@ignorelastfalse ,
                 last/.code  = \tw@mk@ignorefirstfalse \tw@mk@ignorelasttrue  ,
                 ends/.code  = \tw@mk@ignorefirsttrue  \tw@mk@ignorelasttrue  ,
  }
\ExplSyntaxOn
\cs_new_eq:NN \tw@mk@ifemptyT \tl_if_empty:nT
\ExplSyntaxOff
\renewcommand\tw@define@menu@macro[4]{%
   \ifcsundef{tw@style@#4@sep}{%
      \tw@mk@error{Can't define menu macro \string#2\space,\MessageBreak
      because the style '#4' is not available!}
   }{%
      \csdef{tw@parse@menu@list@\expandafter\@gobble\string#2}##1{%
         \def\CurrentMenuElement{##1}%
         \tw@mk@iflastindris
          {%
            \ifnum\tw@mk@indrisnr=\@ne
                \@nameuse{tw@style@#4@single}%
            \else
              \@nameuse{tw@style@#4@sep}%
              \iftw@mk@ignorelast
                % will gobble \else so last is used if element is non-empty
                \tw@mk@ifemptyT{##1}%
              \else
                \@nameuse{tw@style@#4@last}%
              \fi
            \fi
          }
          {%
            \ifnum\tw@mk@indrisnr=\@ne
              \iftw@mk@ignorefirst
                % will gobble \else so first is used if element is non-empty
                \tw@mk@ifemptyT{##1}%
              \else
                \@nameuse{tw@style@#4@first}%
              \fi
            \else
               \@nameuse{tw@style@#4@sep}\@nameuse{tw@style@#4@mid}%
            \fi
          }%
      }%
      #1 #2 { +O{#3} +m }{%
         \leavevmode%
         {\def\tw@current@color@theme{\csname tw@style@#4@color@theme\endcsname}%
         \@nameuse{tw@style@#4@pre}%
         \tw@mk@test@input@sep{##1}{%
            \edef\tw@menu@list{\detokenize{##2}}\edef\tw@mk@tempa{\@backslashchar}%
         }{%
            \edef\tw@menu@list{\unexpanded{##2}}\edef\tw@mk@tempa{\tw@mk@trimspaces{##1}}%
         }%
         {\letcs{\tw@mk@tempb}{tw@parse@menu@list@\expandafter\@gobble\string#2}%
         \tw@mk@expanded{\tw@mk@indrisloop{\tw@mk@tempa}}\tw@menu@list\tw@mk@tempb}%
         \@nameuse{tw@style@#4@post}}%
      }%
   }%
}

% we have to redefine \menu for the changes to apply
\renewmenumacro\menu[>]{menus}

\newcommand\menukeyssetup{\pgfqkeys{/menukeys}}
\makeatother

\begin{document}
\menu{>File>}

\menukeyssetup{ignore-empty=first}
\menu{>File>}

\menukeyssetup{ignore-empty=last}
\menu{>File>}

\menukeyssetup{ignore-empty=ends}
\menu{>File>}
\end{document}

Skillmon avatar Nov 06 '20 19:11 Skillmon