Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Why I get the error below if I use the

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

conditional (defined into classicthesis.sty) you try to comment it, you don't have any error?

\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}

Error

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
share|improve this question
    
It is not related to the source of your problem, but when I read your code, I think you need to read RequirePackage versus usepackage. :-) –  cyanide-based food Sep 25 '12 at 20:16
    
Also not related directly, but I get the feeling you are trying to create something pretty complex without really understanding a lot of crucial TeX concepts. There's a lot of code in this question, and it's almost all not related to the issue. –  Joseph Wright Sep 25 '12 at 20:19

2 Answers 2

up vote 8 down vote accepted

Your problem is a class beginners issue: you've tokenized your input using the conditional. Your set up is pretty hard to read, but the relevant part is

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

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

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

\bool_new:N \g_has_run_bool

The key problem can be seen if we cut it down to

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

What happens here is that TeX reads all of the argument to \ifthenelse with the currently active catcodes: those of a normal LaTeX document. It does not matter that you set \ExplSyntaxOn as \bool_new:N has already been read with _ as a 'subscript' character. Thus TeX sees \bool followed by the tokens _, n, e, : and N.

You should never try to change the catcode of material 'inside' an argument: you always define 'outside'. That could be done by first creating the commands

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

or by using a TeX conditional, which do not absorb arguments

\makeatletter
\if@parts
  % Code here
\fi
share|improve this answer
    
Another possibility is to put all that code in a file myinputs.tex and say \ifthenelse{\boolean{@parts}}{\input{myinputs}}{}. OTOH, it's quite difficult to understand why that code should be loaded only when parts are enabled. –  egreg Sep 25 '12 at 21:56
    
@egreg the parts boolean is only an example that I have used to have one boolean already setted –  FormlessCloud Sep 25 '12 at 23:22

you need \makeatletter ... \makeatother for the code which has a @

share|improve this answer
    
But I have that error also if I put that code in a .sty file –  FormlessCloud Sep 25 '12 at 20:15
2  
The @parts is buried inside \ifthenelse, so \makeatletter is irrelevant. –  egreg Sep 25 '12 at 21:06

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.