misc fixes to LM
[light-and-matter.git] / learn-cmd-syntax.sty
blob3dbf4ab066fe719510081d02322ba0877ac1e3dd
1 \usepackage{xparse}
2 \ExplSyntaxOn
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:
14 % command,\xaa ,0,0,
15 % command,\xab *,1,0,
16 % command,\xac ,1,1,cccc
17 % command,\phi ,0,0,
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
32 % #3 = the possible *
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}
40 \IfBooleanTF{#3}
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 }
43 \IfNoValueTF{#6}
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
84 #2 ,
85 \tl_to_str:n{#3}\bool_if:NT\g_command_check_star_bool{*}
86 , #4, 0,
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
106 \ExplSyntaxOff