ifthenelse 条件和宏

ifthenelse 条件和宏

为什么我使用

\ifthenelse{\boolean{@parts}}%
{%
}{}

条件(定义为classicthesis.sty)您尝试对其进行评论,没有任何错误?

\documentclass[11pt]{scrreprt}

\usepackage[parts]{classicthesis}

\usepackage{expl3}

\ExplSyntaxOn

\newcommand{\useifmybooltrue}{

\RequirePackage{siunitx}
\RequirePackage{booktabs}
\RequirePackage{xparse}
\RequirePackage{environ}
\RequirePackage{geometry}

\bool_new:N \g_has_run_bool
\tl_new:N \l_aw_text_tl
\int_new:N \l_aw_tot_int
\int_new:N \g_aw_tot_alph_int
\int_new:N \g_wid_space_int
\int_new:N \g_space_int
\fp_new:N \g_rat_space_int
\fp_new:N \g_aw_avg_width_fp
\dim_new:N \myalphabetwidth
\dim_new:N \mytextwidth
\makeatletter
\input{\jobname.aux}
\tl_const:Nx \c_aw_the_alphabet_tl {abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,.;?()!' \token_to_str:N :}

% this can be changed to an evironment or renamed or whatever
\NewDocumentCommand {\avgwidthstart} {}
  {
    \aw_avg_width:w
  }

\NewDocumentCommand {\avgwidthend}{}{}

% Here is the environment version, using just "text" as a name is probably a bad idea.
\NewEnviron{textcount}
{
  \expandafter\avgwidthstart\BODY\avgwidthend
}

\cs_new:Npn \aw_avg_width:w #1 \avgwidthend
  {
    % if first run, then generate variables to be used
    \bool_if:NF \g_has_run_bool
      {
        \tl_map_inline:Nn \c_aw_the_alphabet_tl
        {
          \int_new:c {g_##1_int}
          \fp_new:c {g_rat_##1_fp}
          \fp_new:c {g_wid_##1_fp}
        }
      }
    \tl_set:Nn \l_aw_text_tl {#1}

    % this can be used rather than the preceding line to take capital 
    % letters into account, but is Slooooooow
    %\tl_set:Nx \l_aw_text_tl {\tl_expandable_lowercase:n {#1}}

    \int_set:Nn \l_aw_tot_int {\tl_count:N \l_aw_text_tl}
    \tl_map_function:NN \c_aw_the_alphabet_tl \aw_get_counts:n
    \deal_with_spaces:n {#1}
    \tl_map_function:NN \c_aw_the_alphabet_tl \aw_calc_ratios:n
    \tl_map_function:NN \c_aw_the_alphabet_tl \aw_calc_avg_width:n
    \fp_gset_eq:NN \g_aw_avg_width_fp \l_tmpa_fp
    \fp_zero:N \l_tmpa_fp

    % the dimension \myalphabetwidth gives the width of the alphabet based on your character freq,
    % can be accessed by \the\myalphabetwidth
    \dim_gset:Nn \myalphabetwidth {\fp_to_dim:n {\fp_eval:n {61*\g_aw_avg_width_fp}}}

    % the dimension \mytextwidth gives the recommended \textwidth based on 66 chars per line.
    % can be accessed by \the\mytextwidth
    \dim_gset:Nn \mytextwidth {\fp_to_dim:n {\fp_eval:n {66*\g_aw_avg_width_fp}}}
    \protected@write\@mainaux{}{\mytextwidth=\the\mytextwidth}
    \bool_gset_true:N \g_has_run_bool

    % and lastly print the content
    #1
  }

\makeatother

\cs_new:Npn \aw_get_counts:n #1
  {
    % make a temporary token list from the document body 
    \tl_set_eq:NN \l_tmpb_tl \l_aw_text_tl
    % remove all occurrences of the character
    \tl_remove_all:Nn \l_tmpb_tl {#1}
    % add to appropriate int the number of occurrences of that character in current block
    \int_set:Nn \l_tmpa_int {\int_eval:n{\l_aw_tot_int -\tl_count:N \l_tmpb_tl}}
    % add to appropriate int the number of occurrences of that character in current block
    \int_gadd:cn {g_#1_int} {\l_tmpa_int}
    % add this to the total
    \int_gadd:Nn \g_aw_tot_alph_int {\l_tmpa_int}
  }

\cs_new:Npn \deal_with_spaces:n #1
  {
    \tl_set:Nn \l_tmpa_tl {#1}
    % rescan body with spaces as characters
    \tl_set_rescan:Nnn \l_tmpb_tl {\char_set_catcode_letter:N \ }{#1}
    % find number of new characters introduced.  add to number of spaces and alph chars
    \int_set:Nn \l_tmpa_int {\tl_count:N \l_tmpb_tl -\tl_count:N \l_tmpa_tl}
    \int_gadd:Nn \g_space_int {\l_tmpa_int}
    \int_gadd:Nn \g_aw_tot_alph_int {\l_tmpa_int}
    % since this comes after the rest of chars are dealt with, tot_alph is final total
    \fp_set:Nn \g_rat_space_fp {\g_space_int/\g_aw_tot_alph_int}
    % get width of space and use it.  obviously space is stretchable, so i'll assume
    % that the expansions and contractions cancel one another over large text.  is this
    % a terrible assumption???
    \hbox_set:Nn \l_tmpa_box {\ }
    \fp_gset:Nn \g_wid_space_fp {\dim_to_fp:n {\box_wd:N \l_tmpa_box}}
    \fp_add:Nn \l_tmpa_fp {\g_wid_space_fp*\g_rat_space_fp}
  }

\cs_new:Npn \aw_calc_ratios:n #1
  {
    % divide number of occurrences of char by total alphabetic chars
    \fp_gset:cn {g_rat_#1_fp}{{\int_use:c {g_#1_int}}/\g_aw_tot_alph_int}
  }

\cs_new:Npn \aw_calc_avg_width:n #1
  {
    % only need to find char widths once
    \bool_if:NF \g_has_run_bool
      {
        % find width of char box
        \hbox_set:Nn \l_tmpa_box {#1}
        \fp_gset:cn {g_wid_#1_fp}{\dim_to_fp:n {\box_wd:N \l_tmpa_box}}
      }
    % multiply it by char frequency and add to avg width
    \fp_add:Nn \l_tmpa_fp {{\fp_use:c {g_wid_#1_fp}}*{\fp_use:c {g_rat_#1_fp}}}
  }
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This part is just for fun. Delete it and the showtable command from the document if
% it isn't wanted
\tl_new:N \l_aw_tab_rows_tl
\seq_new:N \g_aw_the_alphabet_seq

\NewDocumentCommand {\showtable}{}
    {
      \clearpage
      \thispagestyle{empty}
      \newgeometry{top=2cm,bottom=2cm,left=2cm,right=2cm,heightrounded}
      \aw_make_table:
      \restoregeometry
    }

\cs_generate_variant:Nn \seq_set_split:Nnn {NnV}
\cs_new:Npn \aw_make_table:
    {
      \thispagestyle{empty}
      \seq_set_split:NnV \g_aw_the_alphabet_seq {} \c_aw_the_alphabet_tl
      \seq_map_function:NN \g_aw_the_alphabet_seq \aw_generate_row:n
    \begin{table}
        \centering
        \small
        \sisetup{round-mode = places,round-precision = 5,output-decimal-marker={,},table-format = 3.5}
      \begin{tabular}{lll}
        \toprule
        {Average\,\texttt{\textbackslash textwidth}}&{Average\,character\,width}&{Average\,alphabet\,width}\\
        \midrule
        \the\mytextwidth&\fp_eval:n {round(\g_aw_avg_width_fp,5)}pt&\the\myalphabetwidth\\
        \bottomrule
      \end{tabular}\par
    \end{table}
        \vfil
        \small
      \begin{center}
        Characters\,=\,\fp_eval:n {\g_aw_tot_alph_int}
      \end{center}
        \[%
        \mathrm{Line\,of\,types}=\frac{\fp_eval:n {\g_aw_tot_alph_int}\cdot\fp_eval:n {round(\g_aw_avg_width_fp,5)}\mathrm{pt}}%
                                             {\mathrm{\the\mytextwidth}}%
                                       =\fp_eval:n {round(\g_aw_tot_alph_int*{round(\g_aw_avg_width_fp,5)}/\mytextwidth,5)}
        \]
        \vfil
    \begin{table}
        \centering
        \small
        \sisetup{round-mode = places,round-precision = 5,output-decimal-marker={,},table-format = 3.5}
      \begin{tabular}{cS}
        \toprule
        {Letter}&{Actual}\\
        \midrule
        \textvisiblespace&\fp_eval:n {\g_rat_space_fp*100}\%\\
        \tl_use:N \l_aw_tab_rows_tl
        \bottomrule
      \end{tabular}\par
    \end{table}
    }

\cs_new:Npn \aw_generate_row:n #1
    {
       \tl_put_right:Nn \l_aw_tab_rows_tl {#1&}
       \tl_put_right:Nx \l_aw_tab_rows_tl {\fp_eval:n {100*{\fp_use:c {g_rat_#1_fp}}}\%}
       \tl_put_right:Nn \l_aw_tab_rows_tl {\\}
    }
}
\ExplSyntaxOff
\ifthenelse{\boolean{@parts}}{\useifmybooltrue}

\begin{document}

\avgwidthstart
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla eu purus eros. Aenean scelerisque fermentum nisi, ut tincidunt est viverra ac. Proin diam eros, ultrices sit amet aliquam at, accumsan sit amet magna. Integer nec nunc tincidunt metus scelerisque lacinia quis eget diam. Sed quis purus eros. Phasellus molestie dolor placerat lectus imperdiet tincidunt. Praesent aliquet metus eu elit ornare viverra. Ut nulla elit, convallis id adipiscing facilisis, laoreet et eros.
\avgwidthend

\end{document}

错误

Undefined control sequence }{}

! Undefined control sequence.
<argument> ...etry} \par \ExplSyntaxOn \par \bool
_new:N \g _has_run_bool \t...
l.208 }{}
^^M
The control sequence at the end of the top line

答案1

您的问题是课堂初学者的问题:您使用条件标记了您的输入。您的设置很难阅读,但相关部分是

\ifthenelse{\boolean{@parts}}%
{%

\RequirePackage{siunitx}
\RequirePackage{booktabs}
\RequirePackage{xparse}
\RequirePackage{environ}
\RequirePackage{geometry}

% **********************************************************
\ExplSyntaxOn
% **********************************************************

\bool_new:N \g_has_run_bool

如果我们将其简化为

\ifthenelse{\boolean{@parts}}%
{%
\ExplSyntaxOn
\bool_new:N \g_has_run_bool

这里发生的事情是 TeX 使用当前活动的 catcode 读取所有参数:即正常 LaTeX 文档的 catcode。设置为\ifthenelse并不重要,因为已经将其读取为“下标”字符。因此 TeX 看到后面跟着标记、、和。\ExplSyntaxOn\bool_new:N_\bool_ne:N

您永远不应尝试更改参数“内部”材料的 catcode:您始终定义“外部”。这可以通过首先创建命令来完成

\usepackage{expl3}
\ExplSyntaxOn
\newcommand { \useifmybooltrue } {
  % Code here
}
\ExplSyntaxOff
\ifthenelse{\boolean{@parts}}{\useifmybooltrue}...

或者使用 TeX 条件,它不吸收参数

\makeatletter
\if@parts
  % Code here
\fi

答案2

你需要\makeatletter ... \makeatother的代码有一个@

相关内容