# How do I access the width of text from the preamble?

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.

• 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 4 '13 at 2:11
• If you want (need?) to use \textwidth, why not just use it rather than use \testlength? – Werner Oct 4 '13 at 2: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 4 '13 at 4: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 4 '13 at 4: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 4 '13 at 4:42

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

after two runs.