3

My basic question (I think) is: How do I use \let together with \csname ... \endcsname. So basically I'm trying to get this to work:

\newcommand{\setcolwidth}[2]{
    \expandafter\newlength\csname col#1\endcsname
    \expandafter\let\csname col#1\endcsname\dimexpr#2
}

The background

I created a grid layout. This works similar to a table with a lot more functions. The basic idea can be taken from my example (at the bottom).

My problem

As you can see in the image, my grid layout is not correct. The columns are too long.

enter image description here

What I think is happening

I am setting the widths of my columns. This does something like \@namedef{col1}{.5\textwidth}.

I'm not very familar with how TeX is working but I think it this is "expanding" the command. Im my imagination this means replacing the \@nameuse{col1} with .5\textwidth.

I am using the \@nameuse{...} inside a minipage environment. This means that the \textwidth will be changed. So when TeX is simply replacing my own command by the \textwidth this will use the \textwidth of the minipage. But I want to have the \textwidth outside of the minipage.

My solution

I was looking around in the web to find a solution. If I got everything correct, the \let command will save the real value of the width because it is executing the argument. So I was trying to use \@namelet but I did not find out how it is working. There are nearly no examples on google or on stackexchange.

The next thing I found is the \csname ... \endcsname so now I'm trying to use this. But I don't know how those commands are working or why my example is not working.

Example code

\documentclass{article}

\usepackage{calc}

\makeatletter
% \setcolwidth{column number}{width}
\newcommand{\setcolwidth}[2]{
    \@namedef{col#1}{#2}
}
% \colwidth{column number} -> width of column
\newcommand{\colwidth}[1]{
    \dimexpr\@nameuse{col#1}
}
\makeatother

% separator
\newlength{\colsep}
\setlength{\colsep}{1em}

% only for demonstration
\newcommand{\showwidths}{%
    \noindent%
    \rule{\colwidth{1}}{4pt}%
    \rule{\colsep}{1pt}%
    \rule{\colwidth{2}}{4pt}%
    \newline
}

% initialize columns
\setcolwidth{1}{.5\textwidth}
\setcolwidth{2}{.5\textwidth}

\begin{document}
    % for demonstration only
    \showwidths
    % the (stripped down) grid layout
    \begin{minipage}{\colwidth{1}+\colwidth{2}+\colsep}
        \parbox{\colwidth{1}}{Text in column 1, text in column 1}%
        \hspace{\colsep}%
        \parbox{\colwidth{2}}{Text in column 2, text in column 2}%
    \end{minipage}
    % for demonstration only
    \showwidths
\end{document}

Additional Notes

I do not want to change the minipage to a \parbox. I know that a \parbox is not changing the \textwidth. I am doing a lot more in my own gridlayout environment. I need to have a minipage.

Also I do not care if the \setcolwidth command uses the \csname ... \endcsname or the \@namelet commands. I just like the opportunity to learn something about \csname ... \endcsname and some "deeper" TeX coding.

I don't know if it is important but I am using XeTeX for compiling.

3
  • 1
    \let is not the right command to store a dimension. Mar 5, 2019 at 10:44
  • 1
    Why don't you use real length to store the column width instead of using macros? Mar 5, 2019 at 10:50
  • @UlrikeFischer thank you for your comment. I did not know how to use \setlength together with a non fixed name. I thought there only is \setlength{\length}{<value>}. In addition I thought \let is the "more general way" so you have to use \let if you want a non fixed name. As I said I'm not really familiar with TeX programming.
    – miile7
    Mar 5, 2019 at 11:16

1 Answer 1

3

Use \setlength for setting a length, not \let.

\documentclass{article}
\usepackage{calc}

\makeatletter
\newcommand{\setcolwidth}[2]{%
  \@ifundefined{col#1}{\expandafter\newlength\csname col#1\endcsname}{}%
  \expandafter\setlength\csname col#1\endcsname{\dimexpr#2\relax}%
}
\newcommand{\colwidth}[1]{\csname col#1\endcsname}
\makeatother

\newlength{\colsep}
\setlength{\colsep}{1em}

% only for demonstration
\newcommand{\showwidths}{%
    \noindent
    \rule{\colwidth{1}}{4pt}%
    \rule{\colsep}{1pt}%
    \rule{\colwidth{2}}{4pt}%
}

% initialize columns
\setcolwidth{1}{.5\textwidth}
\setcolwidth{2}{.5\textwidth}

\begin{document}

% for demonstration only
\showwidths

% the (stripped down) grid layout
\noindent
\begin{minipage}{\colwidth{1}+\colwidth{2}+\colsep}
  \parbox{\colwidth{1}}{Text in column 1, text in column 1}%
  \hspace{\colsep}%
  \parbox{\colwidth{2}}{Text in column 2, text in column 2}%
\end{minipage}

% for demonstration only
\showwidths

\end{document}

enter image description here

1
  • 1
    Thank you very much. That works perfectly. Also thank you for adding the \@ifundefined, I didn't even think about that.
    – miile7
    Mar 5, 2019 at 11:14

You must log in to answer this question.

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