6

I would like to create a NewDocumentCommand that would take optional arguments like font color (blue, red), font size (12pt, 18pt, maybe large, huge), and font style (bold, italic, maybe bold+italic). How to set up keyword options like bold and italic?

I have put together the following code, based on @egreg's answer to 338364/xparse-processor-with-multiple-arguments. I was able to get the color and font size to work, using color keywords from the xcolor package and font size in pt, but I'm not sure how best to go about setting optional keywords for the font style (say bf for bold, it for italic). I'm thinking of perhaps conditioning with \IfValueT, but before I experiment I'd welcome pointers. Naturally it would be nice if this command could take math and color it and all that, but if that's too greedy, I'll settle for something that works with text.

\documentclass{article}
\usepackage{xparse,xcolor}
\usepackage{verbatim}

\ExplSyntaxOn

\keys_define:nn { mystyle }
{
  color .tl_set:N = \l__mystyle_color_tl,
  size  .tl_set:N = \l__mystyle_size_tl,
  skip  .tl_set:N = \l__mystyle_skip_tl,
  color .initial:n = red,
  size  .initial:n = 12pt,
  skip  .initial:n = 14.5pt,
}
\NewDocumentCommand{\stress}{O{}m}
{
  \group_begin:
  \keys_set:nn { mystyle } { #1 }
  \clist_map_inline:nn { #2 }
  {
    \mystyle:VVVn
    \l__mystyle_color_tl
    \l__mystyle_size_tl
    \l__mystyle_skip_tl
    {##1}
  }
  \group_end:
}
\cs_new_protected:Nn \mystyle:nnnn
{
  \color{#1}\fontsize{#2}{#3}\selectfont#4
}
\cs_generate_variant:Nn \mystyle:nnnn { VVV }
\ExplSyntaxOff

\begin{document}

\stress{emphasize this sentence with default values}

\stress[color=green,size=18pt]{emphasize this sentence with custom values}

\stress[color=blue,size=10pt,skip=50pt]{\textit{emphasize this sentence with custom values}}

Could I modify the command to:

\verb|\stress[style=it]{blabla}| to select italic, 

\verb|\stress[style=bf]{blabla}| to select bold,

\verb|\stress[style=bfit]{blabla}| to select bold+italic

or even \verb|\stress[style=bf+it]{blabla}| to combine styles...

\end{document}

(the skip argument does not appear to work, but I suspect it's an easy fix for someone who knows what they're doing! maybe some sort of leavemode missing...)

enter image description here

2

1 Answer 1

4

You want to define a .choice: key.

\RequirePackage{fix-cm}
\documentclass{article}
\usepackage{xcolor}
\usepackage{verbatim}

\ExplSyntaxOn

\tl_new:N \l__mystyle_style_tl

\keys_define:nn { mystyle }
 {
  color .tl_set:N = \l__mystyle_color_tl,
  size  .tl_set:N = \l__mystyle_size_tl,
  skip  .tl_set:N = \l__mystyle_skip_tl,

  style .choice:,
  style/it .code:n = \tl_set:Nn \l__mystyle_style_tl { \itshape },
  style/bf .code:n = \tl_set:Nn \l__mystyle_style_tl { \bfseries },
  style/bfit .code:n = \tl_set:Nn \l__mystyle_style_tl { \bfseries\itshape },
  style/unknown .code:n = \tl_set:Nn \l__mystyle_style_tl { #1 },

  color .initial:n = red!75,
  size  .initial:n = 12pt,
  skip  .initial:n = 14.5pt,
 }
\NewDocumentCommand{\stress}{O{}m}
 {
  \group_begin:
  \keys_set:nn { mystyle } { #1 }
  \mystyle:VVVVn
    \l__mystyle_color_tl
    \l__mystyle_size_tl
    \l__mystyle_skip_tl
    \l__mystyle_style_tl
    {#2}
  \group_end:
 }
\cs_new_protected:Nn \mystyle:nnnnn
 {
  \leavevmode\color{#1}\fontsize{#2}{#3}#4\selectfont#5
 }
\cs_generate_variant:Nn \mystyle:nnnnn { VVVV }

\ExplSyntaxOff

\begin{document}

\stress{emphasize this sentence with default values}

\stress[color=green!60!red,size=18pt]{emphasize this sentence with custom values}

\stress[color=blue!80,size=10pt,skip=50pt,style=it]{emphasize this sentence with custom values}

\stress[style=it]{blabla}

\stress[style=bf]{blabla}

\stress[style=bfit]{blabla}

\stress[style=\scshape]{blabla}

\end{document}

You need to define in advance the possible combination, but it's possible to do something also for other styles, expressed with the usual font commands.

I added a \leavevmode before \color in order to avoid possible unwanted effects.

enter image description here

4
  • Thanks egreg! I expected that setting skip=50pt would increase the line spacing, but it doesn't. I may be misunderstanding what the second argument of \fontsize{#2}{#3} does. Do I need to explicitly set \setlength{\baselineskip}{#3} inside the command?
    – PatrickT
    Mar 18, 2023 at 20:31
  • Also the command cannot take commas, e.g. `\stress[style=it]{blabla, blabla}' doesn't work properly, which is something that had stomped me when I was experimenting here: pastebin.com/6kcJ5pWc
    – PatrickT
    Mar 18, 2023 at 20:32
  • @PatrickT I left the \clist_map_inline:nn you had, thinking you had something else in mind. The line spacing is increased, but only locally. You can't have different line spacing in the same paragraph. If these objects have to form a paragraph by themselves, then you have to tell it explicitly.
    – egreg
    Mar 18, 2023 at 21:13
  • Thank you egreg! I copy-pasted code without understanding much of it. I didn't know what \clist_map_inline:nn was for. The edit fixes problems with commas, thanks! If I set skip=50pt, should I or should I not expect the paragraph to have a greater line spacing between lines in the same paragraph? Here's the code you just edited with a long line, but the spacing is the same irrepsective of the skip argument: pastebin.com/5XKPdsh8
    – PatrickT
    Mar 19, 2023 at 4:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .