5

I've got some macros that I want to set up in my preamble. The problem is that they need to know what the width of a typical line of text will be in the document.

If I do something like,

%% Everything set up correctly
\documentclass{article}
\usepackage[margin=1in,showframe]{geometry}
\setlength{\parindent}{0pt}

\newlength{\testlength}
\setlength{\testlength}{\textwidth}
\newcommand{\myrule}{\rule{\testlength}{4pt}}

\usepackage{lipsum}
\begin{document}

\myrule

\lipsum[1-10]

\end{document}

Then \myrule has the correct width.

But if I do something like

%% FAIL
\documentclass{article}
\usepackage[margin=1in,showframe,twocolumn]{geometry}
\setlength{\parindent}{0pt}

\newlength{\testlength}
\setlength{\testlength}{\textwidth}
\newcommand{\myrule}{\rule{\testlength}{4pt}}

\usepackage{lipsum}
\begin{document}

\myrule

\lipsum[1-10]

\end{document}

I don't get the desired result.

I might be inclined to set the width of my macro as

\setlength{\testlength}{\linewidth}

or

\setlength{\testlength}{\columnwidth}

But both of these fail to get the correct length (apart from the fact that \linewidth, as I understand it, shouldn't really make too much sense in the preamble).

How can my macro know from within the preamble what the proper textwidth should be?

I should note that I'm not particularly concerned about what happens if, let's say, the macro is called from within a multicols environment from the multicol package. In other words, the macro should have an absolute length, not a length relative to a particular environment.

Ludovic C.
  • 8,888
A.Ellett
  • 50,533
  • The \textwidth is correct in both cases; it isn’t different after all (see Difference between \textwidth, \linewidth and \hsize). If you want to use \linewidth or \columnwidth though, you may use \AtBeginDocument{\setlength{\testlength}{\linewidth}}. – Qrrbrbirlbel Oct 04 '13 at 02:11
  • 1
    If you want (need?) to use \textwidth, why not just use it rather than use \testlength? – Werner Oct 04 '13 at 02:14
  • @Qrrbrbirlbel \AtBeginDocument almost seems to do the trick. I've got to think through my real document to see where that approach will create what I want. – A.Ellett Oct 04 '13 at 04:36
  • @Werner You're suggestion would work if I want my macro to be permanently tied to the text width regardless of what document I want to build. This macro is tied to a private package I'm building. I wish to allow myself to set parameters once the package is loaded. After that, the parameters should be fixed for the rest of the document. – A.Ellett Oct 04 '13 at 04:39
  • @Qrrbrbirlbel I'm aware of the particular link. That's where I'm getting frustrated because I need certain parameters to be set before I start the document. Some of the parameters should be reading information such as \textwidth to set up other values. But, in the preamble \textwidth is not necessary correctly set yet. Your suggestion works if I rethink how and when I set things through a call to \AtBeginDocument. Though it would be ideal if I didn't have to do that. – A.Ellett Oct 04 '13 at 04:42
  • The hook \@begindocumenthook is "First In, First Out", so if you delay \AtBeginDocument{\setlength{\testlength}{\columnwidth}} just before \begin{document} you shouldn't have any problem, because at that point the page parameters will have been set. If etoolbox is loaded, some package could exploit \AtEndPreamble, so just do it yourself too and put the declaration above in \AtEndPreamble. But, as Werner says, why don't you simply use \columnwidth? – egreg Oct 04 '13 at 21:03
  • @egreg I'll think about a possible new question related to this. Perhaps I'm thinking about the structure I'm trying to build incorrectly. Currently, though I don't want to hardwire the \columnwidth into the macro and thus was using an intermediary length to set some basic structural dimensions. Perhaps you or Qrrbrbirlbel could post your comments as answers since they do resolve the matter as it currently stands. – A.Ellett Oct 04 '13 at 21:59
  • @Qrrbrbirlbel Perhaps you would consider making your comment into an answer? – A.Ellett Oct 04 '13 at 21:59

1 Answers1

1

You could write the length you're interested in to the aux file and retrieve it the next time round:

\documentclass{article}
\usepackage[margin=1in,showframe,twocolumn]{geometry}
\setlength{\parindent}{0pt}

\newlength{\testlength}

\makeatletter
\def\getlength{\immediate\write\@mainaux{\noexpand\global\noexpand\testlength=\the\linewidth}}
\makeatother

\newcommand{\myrule}{\rule{\testlength}{4pt}}

\usepackage{lipsum}
\begin{document}

\getlength
\myrule

\lipsum[1-10]

\end{document}

yields

croped version of TeXed sample

after two runs.

Jonathan
  • 2,310