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.

In an attempt to make it possible to outline much of my document by adding new parts to it, but without making parts that I have not written anything on show up in the compiled document, I have defined five macros based on a macro from Hiding section titles when the section is empty:

\newcommand{\showpart}[2]{%
    \ifstrequal{ #2}{ }{}{\part{#1} #2}%
}
\newcommand{\showchapter}[2]{%
    \ifstrequal{ #2}{ }{}{\chapter{#1} #2}%
}
\newcommand{\showsection}[2]{%
    \ifstrequal{ #2}{ }{}{\section{#1} #2}%
}
\newcommand{\showsubsection}[2]{%
    \ifstrequal{ #2}{ }{}{\subsection{#1} #2}%
}
\newcommand{\showsubsubsection}[2]{%
    \ifstrequal{ #2}{ }{}{\subsubsection{#1} #2}%
}

and now I'm using them all over my source file instead of the normal \part, \chapter, \section, \subsection and \subsubsection. I've also added \usepackage{etoolbox} in the preamble in order to get the ifstrequal macro. However, all the parts that I have not started to write anything on still show up in the compiled document. What am I doing wrong?

share|improve this question
2  
The commands work for me. You probably have some extra spaces somewhere. Can you show us how you use the macros? –  Caramdir May 3 '12 at 22:35
add comment

1 Answer

up vote 13 down vote accepted

The issue you seem to have is that you have empty lines in the second argument of you \showxxxx macros. This empty lines cause a paragraph break, i.e. a \par is added. This means you have to test for three different things: argument is completely empty, argument is a space, argument is a space plus \par. You can do this using the following code:

\documentclass{article}

\makeatletter
\newcommand{\showsection}[2]{%
    \begingroup
    \def\@tempa{#2}%
    \def\@tempb{ \par}%
    \ifcase0%
       \ifx\@tempa\@empty 1\else
       \ifx\@tempa\space  1\else
       \ifx\@tempa\@tempb 1\fi\fi\fi
    \relax
       \endgroup
       \section{#1} #2%
    \else
       \endgroup
    \fi
}
\makeatother

\begin{document}

\showsection{test1}{
    Some text
}

\showsection{test2}{}

\showsection{test3}{
}

\showsection{test4}{

}

\end{document}

If you need this for multiple different sectioning commands, I would turn this into a general macro and not copy the code for every command.

\makeatletter
\newcommand{\showsectioning}[3]{%
    \begingroup
    \def\@tempa{#3}%
    \def\@tempb{ \par}%
    \ifcase0%
       \ifx\@tempa\@empty 1\else
       \ifx\@tempa\space  1\else
       \ifx\@tempa\@tempb 1\fi\fi\fi
    \relax
       \endgroup
       #1{#2} #3%
    \else
       \endgroup
    \fi
}
\makeatother
\newcommand\showsection{\showsectioning\section}
\newcommand\showsubsection{\showsectioning\subsection}
\newcommand\showsubsubsection{\showsectioning\subsubsection}
\newcommand\showchapter{\showsectioning\chapter}
\newcommand\showpart{\showsectioning\part}

Alternative better solution

As you want to also ignore higher sectioning commands with only empty lower sectioning commands the above solution is not reasonable. (If you would have posted a normal usage example it would have been better.) You would have to check for a lot of combinations. I would recommend a different approach. Instead of reading the whole (sub-..)section as macro argument, which is anyway very inefficient, you could have the \show... macros look ahead and check if there is anything else except \par or another \show... macro. If this macro is a lower sectioning macro, remember the current one using a buffer and repeat as long you either find some content or a higher \show... macro. Programming something like this within the power of TeX, but an advanced topic.

Here my suggested solution inclusive example/test code:

\documentclass{article}

\newcommand{\showpart}{%
    \showsectioning{1}\part
}
\newcommand{\showchapter}{%
    \showsectioning{2}\chapter
}
\newcommand{\showsection}{%
    \showsectioning{3}\section
}
\newcommand{\showsubsection}{%
    \showsectioning{4}\subsection
}
\newcommand{\showsubsubsection}{%
    \showsectioning{5}\subsubsection
}
\makeatletter
\expandafter\let\csname showsectioning@buffer@1\endcsname\@empty
\expandafter\let\csname showsectioning@buffer@2\endcsname\@empty
\expandafter\let\csname showsectioning@buffer@3\endcsname\@empty
\expandafter\let\csname showsectioning@buffer@4\endcsname\@empty
\expandafter\let\csname showsectioning@buffer@5\endcsname\@empty
\chardef\showsectioning@highestlevel=0\relax
\newcommand{\showsectioning}[3]{%
    \@ifnextchar\par{%
        \@firstoftwo{\showsectioning{#1}{#2}{#3}}%
    }{%
        \@showsectioning{#1}{#2}{#3}%
    }%
}
% Own macro for efficiency
% The next token is in \@let@token
\newcommand{\@showsectioning}[3]{%
        % Store highest level
        \ifnum\showsectioning@highestlevel=0
            \chardef\showsectioning@highestlevel=#1\relax
        \fi
        % Store number of next sectioning macro (0 = no sectioning macro)
        \chardef\showsectioning@number=0%
            \ifx\@let@token\showpart 1\else
            \ifx\@let@token\showchapter 2\else
            \ifx\@let@token\showsection 3\else
            \ifx\@let@token\showsubsection 4\else
            \ifx\@let@token\showsubsubsection 5\fi
            \fi\fi\fi\fi\relax
        \ifcase0%
            \ifnum#1<\showsectioning@number 1\else
            \ifnum\showsectioning@number>\showsectioning@highestlevel 2\else
            \ifnum\showsectioning@number>0 3\else
            \ifx\@let@token\end 3\fi
            \fi\fi\fi
        \relax% case 0
            % Some content found
            % Pasting and clearing all buffers
            \@tempcnta=\showsectioning@highestlevel
            \loop
                \csname showsectioning@buffer@\number\@tempcnta\endcsname
                \global\expandafter\let\csname showsectioning@buffer@\number\@tempcnta\endcsname\@empty
                \advance\@tempcnta\@ne
                \ifnum\@tempcnta<6
            \repeat
            #2{#3}%
        \or% case 1
            % Lower sectioning command found, buffering current level
            \global\@namedef{showsectioning@buffer@#1}{#2{#3}}%
        \or% case 2
            % Higher sectioning command found, but still a lower one than the highest level
            % Clearing all buffers up to this level
            \@tempcnta=\showsectioning@number
            \loop
                \global\expandafter\let\csname showsectioning@buffer@\number\@tempcnta\endcsname\@empty
                \advance\@tempcnta\@ne
                \ifnum\@tempcnta<6
            \repeat
        \else% case 3
            % Some end delimiter found (\end, \show... command of higher level)
            % Therefore no content, clearing all buffers
            \@tempcnta=\showsectioning@highestlevel
            \loop
                \global\expandafter\let\csname showsectioning@buffer@\number\@tempcnta\endcsname\@empty
                \advance\@tempcnta\@ne
                \ifnum\@tempcnta<6
            \repeat
        \fi
}
\makeatother

\begin{document}

\showsection{Not empty}
test
\showsection{empty}



\showsection{Not empty again}

Hello

\showsection{With empty subsection}

\showsubsection{empty subsection}

\showsection{With non empty subsection}

\showsubsection{Non empty subsection}
Not empty


\showsection{With empty subsection and empty subsubsection}

\showsubsection{empty subsection}

\showsubsubsection{empty subsubsection}

\showsection{Not empty, but with empty subsection}
Stuff

\showsubsection{empty subsection}

\showsection{With \texttt{\string\empty}}
\empty

\showsection{With \texttt{\string\relax}}
\relax


\showsection{Multiple levels 1}
\showsubsection{Multiple levels 1a}
\showsubsection{Multiple levels 1b}
\showsubsubsection{Multiple levels 1bI}
\showsubsubsection{Multiple levels 1bII}
\showsubsection{Multiple levels 1c}
    test

\showsection{trailing}

\end{document}
share|improve this answer
    
Okay, I'm new to LaTeX so I didn't fully understand everything you did. Why do you use \makeatletter in this case? Isn't it possible to just define tempa and tempb without the @ symbol? –  StrawberryFieldsForever May 3 '12 at 22:57
    
@StrawberryFieldsForever: The \makeatletter enables @ in macro names. You can use \tempa and \tempb as well, but \@tempa and \@tempb already exists and are of often used. Then you need \@empty which however also exists as \empty, so you really don't need \makeatletter if you don't want to use it. –  Martin Scharrer May 3 '12 at 23:00
    
Hm, this macro doesn't seem to work if the section has an empty subsection, for example: \showsection{Section name}{ \showsubsection{Subsection name}{ } } –  StrawberryFieldsForever May 3 '12 at 23:22
    
@StrawberryFieldsForever: Ah, I see. No it doesn't work when there is extra content in it. This whole concept is rather unusual. You won't be able to test for all possible scenarios and combinations. A different approach I posted in my update is better suited. –  Martin Scharrer May 4 '12 at 10:47
    
I tried you implementation but it still doesn't seem to work. I may have implemented it incorrectly, though. However, I think I will remove the macros and just use the normal commands, bescause now my preamble looks like a total mess... :P Thanks for the help, I may create a sty file for the macros and try to make it work later on. –  StrawberryFieldsForever May 6 '12 at 11:16
show 1 more comment

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.