# Patch 2016 xparse to support k-type argument

As per Xparse's new e-type argument (replacement for k-type argument), support for xparse's k_ argument type is no longer available as of TeXLive 2016 and thus have stuck to TeXLive 2015 so far. I have numerous macros that are defined using the older k_ arguments, so wondering if there is an easy patch that I can apply so that I can use the new version of xparse and still have the k_ macros work.

I am willing to discard the k_ and use the new e_ but don't like the idea of changing all the macros at once and then having to debug where things went wrong. If I have a single (patched) version of xparse that supports both argument types, the transition will be a lot easier. Also, in case I run into some issue with TeXLive versions newer than 2015, I need to be able to revert back to TeXLive 2015 until I resolve any issues.

The solution I have below is too cumbersome due to the number of macros involved. Having a patch would allow me to use both as I transition to using the e_ argument types, and only revert to the solution below should I run into issues with newer versions.

## MWE

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

\makeatletter
%%  https://tex.stackexchange.com/questions/96570/automatically-determine-which-texlive-version-is-being-used
\def\getversion{\expandafter\get@version\pdftexbanner\@nil}
\def\get@version#1201#2)#3\@nil{\def\TeXLiveVersion{201#2}}
\makeatother
\getversion

\ifnum\TeXLiveVersion<2016
\NewDocumentCommand\MyMacro{k_}{%
\IfNoValueTF{#1}{%
\mathbf{A}
}{%
A_{\textcolor{red}{#1}}
}%
}
\else
\NewDocumentCommand\MyMacro{e_}{%
\MyMacroProcess#1%
}
\NewDocumentCommand\MyMacroProcess{m}{%
\IfNoValueTF{#1}{%
\mathbf{A}
}{%
A_{\textcolor{red}{#1}}
}%
}
\fi

\begin{document}

With a subscript: $\MyMacro_{\pi}$

Without any subscript: $\MyMacro$

\end{document}

• you don't really want to test the version of texlive, rather the version of xparse eg \@ifpackagelater{xparse}{2017/02/10}{this}{that} – David Carlisle Mar 6 '17 at 22:02
• @DavidCarlisle: Yep, that would be a better test. However, I think the k_ option type was dropped before 2017-02-10. – Peter Grill Mar 6 '17 at 22:06
• I realize the feature was marked as experimental, and I don't question the team had the right to drop it. However, a transition period would have been useful. A version of xparse could have been released with both argument types and a warning issued for usages of the k-type. Later, the feature could have been removed completely. – gigabytes Mar 6 '17 at 22:34
• @Manuel Yes but the internals have changed (to support # in optional args, for example): see my answer here! – Joseph Wright Mar 7 '17 at 9:26
• @gigabytes One issue with any 'transition' period is that people don't update their code until it breaks! – Joseph Wright Mar 7 '17 at 9:27

With the current xparse release (2017/12/16), the following will re-add the k-type argument:

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

\ExplSyntaxOn

\tl_if_exist:NF \c_novalue_tl
{ \tl_const:Nx \c_novalue_tl { \c__xparse_no_value_tl } }
\cs_if_exist:NF \__xparse_single_char_check:n
{ \cs_set_eq:NN \__xparse_single_char_check:n \__xparse_single_token_check:n }
{
\cs_set_protected:Npn \__xparse_tmp:w #1
{
\cs_new_protected:Npn \__xparse_normalize_type_k:w ##1
{ \__xparse_normalize_type_K:w ##1 {#1} }
}
\exp_args:No \__xparse_tmp:w { \c_novalue_tl }
\cs_new_protected:Npn \__xparse_normalize_type_K:w #1#2
{
\__xparse_single_char_check:n {#1}
\tl_put_right:Nn \l__xparse_arg_spec_tl { K #1 {#2} }
\tl_put_right:Nn \l__xparse_last_delimiters_tl {#1}
\bool_set_false:N \l__xparse_grab_expandably_bool
\__xparse_normalize_arg_spec_loop:n
}
{
\__xparse_flush_m_args:
\tl_put_right:Nn \l__xparse_signature_tl { #1 }
\__xparse_prepare_signature:N
}
\cs_new_protected:Npn \__xparse_grab_K:w #1#2 \__xparse_run_code:
{
\__xparse_grab_K:NnNn #1 {#2}
\cs_set_protected_nopar:Npn
{ _ignore_spaces }
}
\cs_new_protected:Npn \__xparse_grab_K_long:w #1#2 \__xparse_run_code:
{
\__xparse_grab_K:NnNn #1 {#2}
\cs_set_protected:Npn
{ _ignore_spaces }
}
\cs_new_protected:Npn \__xparse_grab_K_trailing:w #1#2 \__xparse_run_code:
{
\__xparse_grab_K:NnNn #1 {#2}
\cs_set_protected_nopar:Npn
{ }
}
\cs_new_protected:Npn \__xparse_grab_K_long_trailing:w #1#2 \__xparse_run_code:
{
\__xparse_grab_K:NnNn #1 {#2}
\cs_set_protected:Npn
{ }
}
\cs_new_protected:Npn \__xparse_grab_K:NnNn #1#2#3#4
{
\tl_set:Nn \l__xparse_signature_tl {#2}
\exp_after:wN #3 \l__xparse_fn_tl ##1
{
}
\use:c { peek_meaning_remove #4 :NTF } #1
{ \l__xparse_fn_tl }
{
}
}
}
\ExplSyntaxOff
%
\NewDocumentCommand\MyMacro{k_}{%
\IfNoValueTF{#1}{%
\mathbf{A}%
}{%
A_{\textcolor{red}{#1}}%
}%
}

\begin{document}

With a subscript: $\MyMacro_{\pi}$

Without any subscript: $\MyMacro$

\end{document}


I have raised the transition question with the team, and will either update the answer here on the next release (if required) or arrange for k-type to have some (limited) transitional support. Note though that this entire area is still very much in flux!

• I am waiting for the e type paramater to be taken off the experimental tag before replacing the older k_ and t_ arg types that I have used in numerous macros. – Peter Grill Dec 29 '17 at 10:28
• @PeterGrill That may never happen: the whole point of xparse is to allow some experimentation. What I can say is we won't be going back to k. – Joseph Wright Dec 29 '17 at 10:38
• @PeterGrill We have a whole question of what to do with the non-LaTeX2e-like ideas: they work but do they encourage the wrong approaches (see the g-type for example). – Joseph Wright Dec 29 '17 at 10:39
• So, I guess I might as well stick to the k_ type then. – Peter Grill Dec 29 '17 at 18:48
• I agree with the g type macro possible leasing to problems. But, I actually found a good use of the g type parameter. When I add a new mandatory parameter to a macro, I initalyy use the g type so that I can easliy detect older uses of it until I get around to updating all uses of the macro. Then chnage the g to an m. – Peter Grill Dec 29 '17 at 18:48

For the simple case where it is used with a single token e and k are more or less the same so if you just make \IfNoValue a little less fussy abut the difference between {-NoValue-} and -NoValue- then you can alias k to e if it's not already defined so your MWE drops down to:

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

\makeatletter
\ExplSyntaxOn
\ifx\__xparse_normalize_type_k:w\undefined
\def\__xparse_normalize_type_k:w{\__xparse_normalize_type_e:w}
\let\xIfNoValueTF\IfNoValueTF
\def\IfNoValueTF#1{\expandafter\xIfNoValueTF\expandafter{\@car#1.\@nil}}
\fi
\ExplSyntaxOff

\NewDocumentCommand\MyMacro{k_}{%
\IfNoValueTF{#1}{%
\mathbf{A}%
}{%
A_{\textcolor{red}{#1}}%
}%
}

\begin{document}

With a subscript: $\MyMacro_{\pi}$

Without any subscript: $\MyMacro$

\end{document}

• Clearly Joseph's answer is the more complete fix but I'll leave this one here for the "one line" case which might be easier to understand than the full k implementation. (But you should accept Joseph's answer:-) – David Carlisle Mar 7 '17 at 9:35
• FYI, This works fine in the MWE, but it did not work in my actual use case. I guess my usage must be more than just the basic case. – Peter Grill Mar 20 '17 at 5:58