2

I know about \newcommand[<arg_num>]{#1 ... #n} to define a simple macro with up to nine arguments. (More if you link multiple newcommands together)

I recently started to look at xparse for some additional features such as multiple optional arguments, as well as keyval -- which works as I want it to, as long as each option is just one keyword.

What I would ultimately like to have is a way to address certain options by name and assign values and strings like so:

\MyCommand[
    opt1="this is val1",
    opt4="this is val4",
    optN="this is valN"
]{argument1}

Or maybe even:

\MyCommand{
    arg1="this is val1",
    arg4="this is val4",
    argN="this is valN"
}

(I know that "this is val" is not LaTeX syntax, maybe {this is val}?)

I am still fairly new to LaTeX, and I am not sure how to properly search for this. So I hope someone here can point me in the right direction.

1

You can have multiple "keywords" assigned to each option as long as entries with commas are enclosed in braces {...}. Also, you'll have to stick to alphabetic characters for the option names:

enter image description here

\documentclass{article}

\usepackage{xkeyval}

\makeatletter
% ========= KEY DEFINITIONS =========
\define@cmdkey{mycmd}[mycmd@]{argA}{}% Creates \mycmd@argA
\define@cmdkey{mycmd}[mycmd@]{argB}{}% Creates \mycmd@argB
\define@cmdkey{mycmd}[mycmd@]{argC}{}% Creates \mycmd@argC
\define@cmdkey{mycmd}[mycmd@]{argD}{}% Creates \mycmd@argD
% ========= KEY DEFAULTS =========
\setkeys{mycmd}{
  argA = ARG-A,
  argB = arg-B,
  argC = ARG-c,
  argD = A R G - D}%
\newcommand{\MyCommand}[1]{%
  \begingroup%
  \setkeys{mycmd}{#1}% Set new keys
  Argument 1/2/3/4: \mycmd@argA /\mycmd@argB /\mycmd@argC /\mycmd@argD
  \endgroup%
}
\makeatother

\begin{document}

\MyCommand{}

\MyCommand{
  argB = BbBbBb,% Change from default
  argC = CcCcC cCcCc CcCcC% Multiple words
}

\MyCommand{
  argA = {AaAaA, aAaAa},% Multiple words separated by comma
  argD = "DdDdD dDdDd"% Multiple words in quotes
}

\end{document}

Reference: How to create a command with key values?

3

You may do this kind of thing with l3keys from interface3.pdf. Here is an example:

\documentclass[a4paper,12pt]{article}
\usepackage{lmodern}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{expl3}
\usepackage{xparse}

\ExplSyntaxOn

\bool_new:N \g_my_bool
\tl_new:N \g_some_tl
\tl_new:N \g_other_tl

\keys_define:nn { mymodule }
  {
    choiceKey .choice:,
    choiceKey / firstChoice .code:n = {
      \tl_gset:Nn \g_some_tl { whatever~you~want } },
    choiceKey / secondChoice .code:n = {
       \tl_gset:Nn \g_some_tl { with~commas,~too } },
    choiceKey / thirdChoice .code:n = {
       \tl_gset:Nn \g_some_tl { blah! } },
    choiceKey .initial:n = { thirdChoice },

    booleanKey .bool_gset:N = \g_my_bool,
    % Value used when the key is passed with no value
    booleanKey .default:n = { true },
    booleanKey .initial:n = { false },

    tokenListKey .tl_gset:N = \g_other_tl,
    tokenListKey .initial:n = { some~default }
  }

\cs_new:Nn \__mymodule_print_result:
  {
    Choice~key:~``\g_some_tl'' \\
    Boolean~key:~\bool_if:NTF \g_my_bool { set } { unset } \\
    Token~list~key:~``\g_other_tl''
  }

\NewDocumentCommand \MyModuleSetup { m }
  {
    \keys_set:nn { mymodule } {#1}
  }

\NewDocumentCommand \MyModulePrintResult { }
  {
    \__mymodule_print_result:
  }

\ExplSyntaxOff

\begin{document}
\setlength{\parindent}{0pt}%
%
\MyModulePrintResult            % Work with the default (“initial”) values

\bigskip
\MyModuleSetup{
  choiceKey=secondChoice,
  booleanKey=true,              % “=true“ may be omitted because of the
                                % “booleanKey .default:n = { true }” above
  tokenListKey={Yes, you may put commas in there. Outer braces, if any, are
    automatically removed. }    % The space following the period is part of
                                % the value
  }%
\MyModulePrintResult            % Work with the values just set
\end{document}

Screenshot of the rendered example

  • Thank you for your answer. Werners answer fit my use-case better and is closer to the syntax I am comfortable with, that is why I accepted it. But I will definitely keep this in mind for the future and I will probably use this as I get into more advanced LaTeX. – omnesia Jun 22 '18 at 6:40
  • Okay... since your question mentioned xparse, I thought you were looking for a LaTeX3-ish way of parsing the key/value mapping. Anyway, l3keys from interface3.pdf is very convenient and powerful in my opinion; it's probably a good idea to read its documentation, or at least skim through it, when you have some time. :) [starts p. 166 in the current version] – frougon Jun 22 '18 at 7:26
1

This?

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand \kvargcommand { +m +m }
 {
  \omnesia_kvargcommand:nn { #1 } { #2 }
 }
\cs_new_protected:Npn \omnesia_kvargcommand:nn #1 #2
 {
  \group_begin:
  \keys_set:nn { omnesia / kvargcommand } { #1 }
  \cs_set:Npn \omnesia_action:nnnnnnnnn ##1 ##2 ##3 ##4 ##5 ##6 ##7 ##8 ##9 { #2 }
  \cs_set:Npn \opt ##1 { \tl_use:c { l_omnesia_arg_ \int_to_roman:n {##1} _tl } }
  \tl_set:Nx \l_tmpa_tl
   {
    \exp_not:N \omnesia_action:nnnnnnnnn
     { \exp_not:V \l_omnesia_arg_i_tl    }
     { \exp_not:V \l_omnesia_arg_ii_tl   }
     { \exp_not:V \l_omnesia_arg_iii_tl  }
     { \exp_not:V \l_omnesia_arg_iv_tl   }
     { \exp_not:V \l_omnesia_arg_v_tl    }
     { \exp_not:V \l_omnesia_arg_vi_tl   }
     { \exp_not:V \l_omnesia_arg_vii_tl  }
     { \exp_not:V \l_omnesia_arg_viii_tl }
     { \exp_not:V \l_omnesia_arg_ix_tl   }
   }
  \tl_use:N \l_tmpa_tl
  \group_end:
 }
\keys_define:nn { omnesia / kvargcommand }
 {
  opt1 .tl_set:N = \l_omnesia_arg_i_tl    ,
  opt2 .tl_set:N = \l_omnesia_arg_ii_tl   ,
  opt3 .tl_set:N = \l_omnesia_arg_iii_tl  ,
  opt4 .tl_set:N = \l_omnesia_arg_iv_tl   ,
  opt5 .tl_set:N = \l_omnesia_arg_v_tl    ,
  opt6 .tl_set:N = \l_omnesia_arg_vi_tl   ,
  opt7 .tl_set:N = \l_omnesia_arg_vii_tl  ,
  opt8 .tl_set:N = \l_omnesia_arg_viii_tl ,
  opt9 .tl_set:N = \l_omnesia_arg_ix_tl   ,
 }

\ExplSyntaxOff

\begin{document}

\kvargcommand{
  opt1 = this is val1,
  opt4 = this is val4,
  opt7 = this is val7,
  opt6 = {this is val6, that contains a comma, so it has to be enclosed in braces},
}
{do something with one [#1] and four [\opt4] and seven [\opt7], the special case six [[#6]]
 and also some empty ones by default like (\opt2) and (#3), as you can see you can use \texttt{\string\opt} or just normal arguments}

\end{document}
  • Thank you for your answer. I accepted Werners answer as it seemed simpler and sufficed for what I needed to do. – omnesia Jun 22 '18 at 6:42
  • I still don't know for sure what you wanted. If you wanted to use #1 or \opt1 as arguments. – Manuel Jun 22 '18 at 6:43
  • Maybe the mention of \newcommand[<arg_num>]{#1 ... #n} was a little misleading. I wanted to address the arguments by name, meaning e.g. \opt1. But I was also not really sure what would be possible at all. – omnesia Jun 22 '18 at 6:55
  • Okey, I will update the answer anyways. – Manuel Jun 22 '18 at 6:56
  • Now you can use \opt1 in the same way as #1, both options possible. – Manuel Jun 22 '18 at 7:01

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.