# Use \let with \csname

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.

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}


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.

• \let is not the right command to store a dimension. Mar 5 '19 at 10:44
• Why don't you use real length to store the column width instead of using macros? Mar 5 '19 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. Mar 5 '19 at 11:16

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}


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