11

I want to create a macro that dynamically returns the current chapter, section, subsection (etc.) I'm in. I've created a macro called \getCurrentSectionNumber that does this, but it lacks the ability to figure out how many levels deep it is and shorten/lengthen the result accordingly. This macro should essentially return the full numbering text of the most recent subsection, section, or chapter where it was invoked.

This macro should produce the following text at the given places.

  • A: "1"
  • B: "1.1"
  • C: "1.1.1"
  • D: "1.1.2"
  • E: "1.2"
  • F: "1.2.1"
  • G: "1.2.2"

Note that at A, it prints "1.??" because there is no section defined at that point. Locations C, D, F, and G all omit the subsection.

Example:

\documentclass{report}
\usepackage{etoolbox}


\newcommand\getcurrentref[1]{%
 \ifnumequal{\value{#1}}{0}
  {??}
  {\the\value{#1}}%
} 
\newcommand{\getCurrentSectionNumber}{\getcurrentref{chapter}.\getcurrentref{section}}


\begin{document}

\chapter{My Example}
A: Current number is \getCurrentSectionNumber

\section{Section One-point-One}
    B: Current number is \getCurrentSectionNumber
    \subsection{subsection one-point-one-point-one}
        C: Current number is \getCurrentSectionNumber
    \subsection{subsection one-point-one-point-two}
        D: Current number is \getCurrentSectionNumber
\section{Section Two}
    E: Current number is \getCurrentSectionNumber
    \subsection{subsection one-point-two-point-one}
        F: Current number is \getCurrentSectionNumber
    \subsection{subsection one-point-two-point-two}
        G: Current number is \getCurrentSectionNumber

\end{document}

Example's Output:

output of the example code given above

Any help would be appreciated. Thanks!

4 Answers 4

12

You mean something like this? We simply use the fact that the "lower" section number is always 0 when that sectioning level is not used at the moment.

\documentclass{report}

\makeatletter
\newcommand{\getCurrentSectionNumber}{%
  \ifnum\c@section=0 %
  \thechapter
  \else
  \ifnum\c@subsection=0 %
  \thesection
  \else
  \ifnum\c@subsubsection=0 %
  \thesubsection
  \else
  \thesubsubsection
  \fi
  \fi
  \fi
}

\makeatother

\begin{document}

\chapter{My Example}
A: Current number is \getCurrentSectionNumber %1

\section{Section One-point-One}
    B: Current number is \getCurrentSectionNumber % 1.1
    \subsection{subsection one-point-one-point-one}
        C: Current number is \getCurrentSectionNumber % 1.1.1
    \subsection{subsection one-point-one-point-two}
        D: Current number is \getCurrentSectionNumber % 1.1.2
\section{Section Two}
    E: Current number is \getCurrentSectionNumber % 1.2
    \subsection{subsection one-point-two-point-one}
        F: Current number is \getCurrentSectionNumber % 1.2.1
    \subsection{subsection one-point-two-point-two}
        G: Current number is \getCurrentSectionNumber % 1.2.2

\end{document}
0
5

You have to examine each counter from top down and stop when you reach one that has the value zero.

\documentclass{book}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\getCurrentSectionNumber}{}
 {
  \jvri_get_current:
 }
% the list of examined counters
\clist_const:Nn \c_jvri_counters_clist 
 {
  chapter,section,subsection,subsubsection,paragraph,subparagraph
 }

% for storing the previous counter name
\tl_new:N \l_jvri_previous_tl

\cs_new_protected:Npn \jvri_get_current:
 {
  \tl_set:Nn \l_jvri_previous_tl { part } % for safety
  \clist_map_inline:Nn \c_jvri_counters_clist
   {
    \int_compare:nTF { \arabic{##1} = 0 }
     {% if the counter is zero, break and use the former \the<counter>
      \clist_map_break:n { \use:c { the \l_jvri_previous_tl } }
     }
     {% store the counter's name
      \tl_set:Nn \l_jvri_previous_tl { ##1 }
     }
   }
 }
\ExplSyntaxOff

\begin{document}

Zero: \getCurrentSectionNumber (will have no output)

\chapter{My Example}
A: Current number is \getCurrentSectionNumber

\section{Section One-point-One}
B: Current number is \getCurrentSectionNumber

\subsection{subsection one-point-one-point-one}
C: Current number is \getCurrentSectionNumber

\subsection{subsection one-point-one-point-two}
D: Current number is \getCurrentSectionNumber

\section{Section Two}
E: Current number is \getCurrentSectionNumber

\subsection{subsection one-point-two-point-one}
F: Current number is \getCurrentSectionNumber

\subsection{subsection one-point-two-point-two}
G: Current number is \getCurrentSectionNumber

\chapter{Again}
H: Current number is \getCurrentSectionNumber

\end{document}

This is easily extendable to manage also lower levels.

You'll see that after “Zero:” there will be nothing; it can be added a check whether the final sequence is empty.

enter image description here

enter image description here

4

Here is another way compared to the good answer from tohecz, using simply the fact that the label command refers to the last sectioning command called.

\documentclass{book}

\usepackage[hidelinks]{hyperref}
\newcounter{GN}
\setcounter{GN}{0}
\newcommand{\GetNumber}[0]{\stepcounter{GN}\label{GN:\theGN}\ref{GN:\theGN}}

\begin{document}

\chapter{Foo}
Current number is: \GetNumber
\section{Bar}
Current number is: \GetNumber
\subsection{Baz}
Current number is: \GetNumber
\subsection{Baz2}
Current number is: \GetNumber
\section{Bar2}
Current number is: \GetNumber

\end{document}

And here the output:

Output

EDIT Here is an improved version of my MWE to show the robustness of the method to the equation and float.

\documentclass{book}

\usepackage{float}
\usepackage[hidelinks]{hyperref}
\newcounter{GN}
\setcounter{GN}{0}
\newcommand{\GetNumber}[0]{\stepcounter{GN}\label{GN:\theGN}\ref{GN:\theGN}}

\begin{document}

\chapter{Foo}
Current number is: \GetNumber
\section{Bar}
Current number is: \GetNumber
\subsection{Baz}

\begin{equation}c=a+b\end{equation}

\noindent
Current number is: \GetNumber
\subsection{Baz2}

\begin{figure}[H]
\caption{Figure to test the robustness}
\end{figure}

Current number is: \GetNumber
\section{Bar2}
Current number is: \GetNumber

\end{document}

and here is its output, however as pointed out by tohecz and egreg in the comments, this solution works only if you call \GetNumber out of an environment where a counter has been refstepped.

Output2

5
  • even if you have \section{SECT}\begin{equation}c=a+b\end{equation}\GetNumber ?
    – yo'
    Commented Oct 29, 2013 at 23:32
  • @tohecz Yes, have a look at this answer for some more explanations. In short: the \label command, if not in a float or an equation will look for the previous section (or sub and so on) command.
    – Ludovic C.
    Commented Oct 29, 2013 at 23:35
  • 1
    \begin{theorem}Current number is: \GetNumber\end{theorem}, of course with \usepackage{amsthm}\newtheorem{theorem}{Theorem}. The same problem, even simpler: \begin{enumerate}\item X\item Current number is: \GetNumber\end{enumerate}.
    – yo'
    Commented Oct 29, 2013 at 23:41
  • 1
    The problem in the answer you link is different, since most often it's supposed that all other than sectioning commands call \refstepcounter inside a group. However, I would never place \label anywhere else than just after (or inside) the think I want to cross-ref.
    – yo'
    Commented Oct 29, 2013 at 23:44
  • 3
    The problem is if \getCurrentNumber is inside an environment where a counter has been “refstepped”.
    – egreg
    Commented Oct 29, 2013 at 23:44
1

If you are able to retrieve the current sectioning level (lets call it \currsecnumdepth), you could also use plain old \ifcase:

\newcommand*{\getCurrentSectionNumber}{\ifcase\currsecnumdepth\thechapter\or\thesection
\or\thesubsection\or\thesubsubsection\or\theparagraph\or\thesubparagraph\fi}

In the following example, I provided a (admittedly unpleasent) way to make sure that the premise of my above sentence holds:

\documentclass{report}

\makeatletter
\newcount\currsecnumdepth
%verbose from the standard classes, except line 4
\renewcommand{\chapter}{\if@openright\cleardoublepage\else\clearpage\fi
                        \thispagestyle{plain}%
                        \global\@topnum\z@
                        \global\currsecnumdepth\z@
                        \@afterindentfalse
                        \secdef\@chapter\@schapter}
%verbose from latex.ltx, except line 2
\renewcommand{\@startsection}[6]{%
  \global\currsecnumdepth=#2
  \if@noskipsec \leavevmode \fi
  \par
  \@tempskipa #4\relax
  \@afterindenttrue
  \ifdim \@tempskipa <\z@
    \@tempskipa -\@tempskipa \@afterindentfalse
  \fi
  \if@nobreak
    \everypar{}%
  \else
    \addpenalty\@secpenalty\addvspace\@tempskipa
  \fi
  \@ifstar
    {\@ssect{#3}{#4}{#5}{#6}}%
    {\@dblarg{\@sect{#1}{#2}{#3}{#4}{#5}{#6}}}}
\makeatother

\newcommand*{\getCurrentSectionNumber}{\ifcase\currsecnumdepth\thechapter\or\thesection
\or\thesubsection\or\thesubsubsection\or\theparagraph\or\thesubparagraph\fi}

\begin{document}

\chapter{My Example}
A: Current number is \getCurrentSectionNumber

\section{Section One-point-One}
    B: Current number is \getCurrentSectionNumber
    \subsection{subsection one-point-one-point-one}
        C: Current number is \getCurrentSectionNumber
    \subsection{subsection one-point-one-point-two}
        D: Current number is \getCurrentSectionNumber
\section{Section Two}
    E: Current number is \getCurrentSectionNumber
    \subsection{subsection one-point-two-point-one}
        F: Current number is \getCurrentSectionNumber
    \subsection{subsection one-point-two-point-two}
        G: Current number is \getCurrentSectionNumber

\end{document}

currsecnmb demo

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .