3 % By egreg, http://tex.stackexchange.com/questions/40404/parsing-latex-to-output-number-of-arguments-for-each-command-defined
5 % Defining commands like this
6 % \newcommand{\xaa}{abc}
7 % \newcommand*{\xab}[1]{abc}
8 % \newcommand{\xac}[2][cccc]{abc}
9 % \renewcommand{\phi}{\varphi}
10 % \newenvironment{xad}{}{}
11 % \newenvironment{xae}[1]{}{}
12 % \newenvironment{xaf}[2][sss]{}{}
13 % results in this output in myfile.cmd:
16 % command,\xac ,1,1,cccc
18 % environment,xad,0,0,
19 % environment,xae,1,0,
20 % environment,xaf,1,1,sss
21 % The fields in the output are:
22 % (command|environment),name,n-required-args,n-optional-args,default
23 % Extraneous whitespace occurs in <name> and should be filtered out.
25 % Define the command that will start the working; we'll redefine \newcommand
26 % so that \newcommand{\xac}[2][cccc]{abc} will execute
28 % \command_check:w { \command_check_newcommand:w }{ command } {\xab}
30 % #1 = \newcommand|\renewcommand|\newenvironment|\renewenvironment (in new form)
31 % #2 = command|environment
33 % #4 = the argument to \newcommand
34 % #5 = the number of arguments
35 % #6 = the possible optional argument
37 % We check if the last argument is missing and take the appropriate action
38 \NewDocumentCommand{ \command_check:w
}{m m s m O
{0} o
}
41 { \tl_gset:Nn
\g_command_check_star_tl { *
} \bool_gset_true:N
\g_command_check_star_bool }
42 { \tl_gset:Nn
\g_command_check_star_tl { } \bool_gset_false:N
\g_command_check_star_bool }
44 { \command_check_noopt:nnnn
{#1} {#2} {#4} {#5} }
45 { \command_check_opt:nnnnn
{#1} {#2} {#4} {#5} {#6} }
47 % \StartSaveCommands sets up the checks, first by creating aliases for the kernel commands
48 % and then redefining them as explained above
49 \NewDocumentCommand{\StartSaveCommands}{}
51 \cs_set_eq:NN
\command_check_newcommand:w
\newcommand
52 \cs_set_eq:NN
\command_check_renewcommand:w
\renewcommand
53 \cs_set_eq:NN
\command_check_newenvironment:w
\newenvironment
54 \cs_set_eq:NN
\command_check_renewenvironment:w
\renewenvironment
55 \cs_set:Npn
\newcommand { \command_check:w
{\command_check_newcommand:w
}{command
} }
56 \cs_set:Npn
\renewcommand { \command_check:w
{\command_check_renewcommand:w
}{command
} }
57 \cs_set:Npn
\newenvironment { \command_check:w
{\command_check_newenvironment:w
}{environment
} }
58 \cs_set:Npn
\renewenvironment { \command_check:w
{\command_check_renewenvironment:w
}{environment
} }
60 % \StopSaveCommands restores the kernel commands
61 \NewDocumentCommand{\StopSaveCommands}{}
63 \cs_set_eq:NN
\newcommand \command_check_newcommand:w
64 \cs_set_eq:NN
\renewcommand \command_check_renewcommand:w
65 \cs_set_eq:NN
\newenvironment \command_check_newenvironment:w
66 \cs_set_eq:NN
\renewenvironment \command_check_renewenvironment:w
68 % \WriteSaveCommands will take care of writing out the list of commands
69 % with their number of arguments
70 \NewDocumentCommand{\WriteSaveCommands}{}
72 \iow_open:Nn
\g_command_check_write { \jobname.cmd
}
73 \seq_map_inline:Nn
\g_command_check_seq {\iow_now:Nx
\g_command_check_write { #
#1 } }
75 % Allocate a write stream
76 \iow_new:N
\g_command_check_write
77 % If there's no optional argument, say \newcommand{\xab}[1]{aaa},
78 % we want to write out "command,\xab ,1,0", so we store that
79 % string into an item appended to the sequence \g_command_check_seq
80 \cs_new:Npn
\command_check_noopt:nnnn
#1 #2 #3 #4
82 \seq_gput_right:Nx
\g_command_check_seq
85 \tl_to_str:n
{#3}\bool_if:NT
\g_command_check_star_bool{*
}
88 \exp_after:wN
#1 \g_command_check_star_tl {#3} [#4]
90 % If there's an optional argument, say \newcommand{\xac}[2][cccc]{abc},
91 % we want to write out "command,\xac,1,1[cccc]; everything as before,
92 % but we decrease by 1 the number of stated arguments
93 \cs_new:Npn
\command_check_opt:nnnnn
#1 #2 #3 #4 #5
95 \seq_gput_right:Nx
\g_command_check_seq
97 #2 \bool_if:NT
\g_command_check_star_bool {*
},
\tl_to_str:n
{#3} ,
98 \int_to_arabic:n
{#4-
1} ,
1,
\tl_to_str:n
{#5}
100 \exp_after:wN
#1 \g_command_check_star_tl {#3}[#4][#5]
102 % Allocate the sequence, the token list variable and the boolean
103 \seq_new:N
\g_command_check_seq
104 \tl_new:N
\g_command_check_star_tl
105 \bool_new:N
\g_command_check_star_bool