% % This is strings.sty, by Charles Duan. % % Provides internal commands for doing substring comparisons. % % % Tests whether the first string is a prefix for the second string. Takes four % arguments: prefix, string, true-command, false-command. \ProvidesFile{strings}[2004/10/09 String tests] % % Eats two \fi, places two \fi, and then places your argument. This is for % jumping out of a nested conditional by pure expansion. \def\@skipafi#1#2\fi{\fi#1} \def\@eatafi#1#2\fi{#1} % \let\str@mark\relax \let\str@stop\relax \def\str@test{\str@stop} \newcommand*\@ifprefix[2]{% \edef\str@act{\noexpand\in@{\noexpand\@nil#1}{\noexpand\@nil#2}}\str@act \ifin@\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi } \newcommand*\@ifsuffix[2]{% \edef\str@act{\noexpand\in@{#1\noexpand\@nil}{#2\noexpand\@nil}}\str@act \ifin@\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi } \newtoks\str@a \def\str@ua{\the\str@a} \newtoks\str@b \def\str@ub{\the\str@b} \newtoks\str@c \def\str@uc{\the\str@c} % % Splits the second string into two parts, based on the first string. If the % first string is not found in the second string, then the second string is % passed wholesale to the first argument, and the second argument is empty. % Takes three parameters: the splitting string, the string to be split, and the % command to be run with two parameters. \newcommand*\@split[3]{% \str@a{#1}\str@b{#2}\str@c{#3}% \let\str@act\relax \edef\str@act{% \def\str@act####1\str@ua####2\str@stop{% \noexpand\ifx\noexpand\@split####2% \def\str@act{\str@uc{\str@ub}{}}% \noexpand\else \def\str@act{% \noexpand\@@split{\str@uc}{####1}% ####2\str@stop }% \noexpand\fi \str@act }% \str@act\str@ub\str@mark\str@ua\noexpand\@split\str@stop }% \str@act } \def\@@split#1#2#3\str@mark#4\str@stop{#1{#2}{#3}} % % Determines if a string is empty. Takes three arguments: the string to test, % the true value, and the false value. \newcommand*\@ifempty[1]{% \ifx\@ifempty#1\@ifempty \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi } \newcommand*\@ifnotempty[1]{% \ifx\@ifempty#1\@ifempty \expandafter\@gobble \else \expandafter\@firstofone \fi } % % Splits off a prefix from a string. Arguments are the prefix string, the test % string, and the command to be run if the prefix is found. \def\chop@prefix#1#2#3{% \let\str@act\relax \toks@{#3}% \edef\str@act{% \def\str@act####1\str@mark#1####2\str@mark####3\str@stop{% \noexpand\@ifempty{####1}{\the\toks@{####2}}{}% }% \str@act\str@mark#2\str@mark#1\str@mark\str@stop }% \str@act } % % Iterates through a string, separating out words. The given command is run on % each word. Words are defined as strings of characters with letter catcodes. % First argument is the sentence. Second is the command (which is assumed to % take one argument). Third is the command applied on punctuation, applied to % each piece of punctuation. % % Spaces are automatically placed in the stream (because it's so easy to eat % them as necessary). % % Although this function uses \def and such, in theory it should work inside an % \edef... % \def\process@words#1#2#3#4{% \str@proc@wds#2#3#4#1 \str@test% Ending token is \str@test } \def\str@proc@wds#1#2#3#4 #5{% \@ifnotempty{#4}{\str@proc@wd#1#2#3\str@mark#4\str@test}% \ifx\str@test#5\else #3% \@skipafi{\str@proc@wds#1#2#3#5}% \fi } \def\str@ifltr#1{% \ifcat a#1\expandafter\@firstoftwo\else \ifcat1#1\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi {% \ifnum9<1#1 \@skipafi{\expandafter\@firstoftwo}% \else\@skipafi{\expandafter\@secondoftwo}\fi }{% \expandafter\@secondoftwo }% \fi } \def\str@proc@wd#1#2#3#4\str@mark#5{% \ifx\str@test#5% \@ifnotempty{#4}{#1{#4}}% \else \str@ifltr{#5}{% \@skipafi{\str@proc@wd#1#2#3#4#5\str@mark}% }{% \@ifnotempty{#4}{#1{#4}}% #2{#5}% \@skipafi{\str@proc@wd#1#2#3\str@mark}% } \fi } % Chops space off of a string. Fully expandable. \newcommand*{\chop@space}[1]{% \@ifnotempty{#1}{\str@chopspc#1\str@test\str@test\str@stop}% } \edef\str@chopspc#1#2\str@test#3\str@stop{% \noexpand\ifx\noexpand\str@test#1\noexpand\else \noexpand\str@chopspc@#1#2\str@mark\space\str@mark\str@stop \noexpand\fi } \errorcontextlines=1000 \edef\str@chopspc@#1 \str@mark#2\str@stop{% \noexpand\@ifempty{#2}{\noexpand\str@chopspc@@#1}{% \noexpand\str@chopspc@#1\str@mark\space\str@mark\str@stop }% } \def\str@chopspc@@#1\str@mark{#1} % % Splits a string against a substring and runs the given function on each of the % pieces. \def\full@split#1#2#3{\@split{#1}{#2}{\str@fsp{#1}{#3}}} \def\str@fsp#1#2#3#4{#2{#3}\@ifempty{#4}{}{\full@split{#1}{#4}{#2}}} % % Tests whether a string is a single character. If it is zero characters, this % function treats it as false. \def\@ifonechar#1{\@ifempty{#1}{\@secondoftwo}{\@ifonechar@#1\str@stop}} \def\@ifonechar@#1#2\str@stop{\@ifempty{#2}} \endinput