GeneralDefine commands inside a command

LaTeX specific issues not fitting into one of the other forums of this category.
Post Reply
kmcbest
Posts: 2
Joined: Tue Nov 10, 2009 4:33 pm

Define commands inside a command

Post by kmcbest »

Hi, I want to define a command that takes a comma separated list and define (by \newcommand) several commands. That is, if I execute \createcommands{1,2,3,4,5,6,7,8}, the comma separated numbers are extracted (inside a \@for loop) and go to define eight new commands, as if I state them like this:

Code: Select all

\newcommand\chupleft{\fontfamily{ptm}\selectfont 1}
\newcommand\chupcenter{\fontfamily{ptm}\selectfont 2}
\newcommand\chupright{\fontfamily{ptm}\selectfont 3}
...
\newcommand\chlowerright{\fontfamily{ptm}\selectfont 8}
So I proposed to do like this (minimal example)

Code: Select all

\documentclass[12pt]{article}
\usepackage{color,ifthen}
\newcommand*\mchar{\fontfamily{ptm}\fontsize{24}{24}\selectfont\color{red}}
\newcounter{cname}\setcounter{cname}{0}
\makeatletter
\newcommand\createcommands[1]{%
	\@for\@myarg:=#1\do{
		\stepcounter{cname}
		\ifthenelse{\arabic{cname}=1}{\newcommand\chupleft{\mchar \@myarg}}{}
		\ifthenelse{\arabic{cname}=2}{\newcommand\chupcenter{\mchar \@myarg}}{}
		\ifthenelse{\arabic{cname}=3}{\newcommand\chupright{\mchar \@myarg}}{}
		\ifthenelse{\arabic{cname}=4}{\newcommand\chleft{\mchar \@myarg}}{}
		\ifthenelse{\arabic{cname}=5}{\newcommand\chright{\mchar \@myarg}}{}
		\ifthenelse{\arabic{cname}=6}{\newcommand\chlowerleft{\mchar \@myarg}}{}
		\ifthenelse{\arabic{cname}=7}{\newcommand\chlowercenter{\mchar \@myarg}}{}
		\ifthenelse{\arabic{cname}=8}{\newcommand\chlowerright{\mchar \@myarg}}{}
	}
}

\makeatother

\begin{document}
\createcommands{1,2,3,4,5,6,7,8}
% 1,2,3,4,5,6,7,8 are in fact eight border characters to make a framed text box, so they can be anything, 'a,b,c,d,e,f,g,h', etc. That's why I set up a counter `cname' and did silly ifthenelse comparisons.
\chupleft
\end{document}
Once compile, I got \chupleft as undefined sequence.

Code: Select all

! Undefined control sequence.
\@myarg ->\@nil

l.24 \chupleft

?
So apparently the \chupleft is defined but then seemingly goes out of scope, how can I have them preserved and use after \begin{document}? Thanks.

BTW, I've used another approach with package `tokenizer' and had similar result. I've read about some topics on variable expansion (\expandafter, \csname, \endcsname) without success.

Please instruct, thanks!
Last edited by kmcbest on Wed Nov 11, 2009 12:25 pm, edited 1 time in total.

Recommended reading 2024:

LaTeXguide.org • LaTeX-Cookbook.net • TikZ.org

NEW: TikZ book now 40% off at Amazon.com for a short time.

phi
Posts: 577
Joined: Tue Oct 21, 2008 8:10 pm

Define commands inside a command

Post by phi »

What you want is possible, of course, for example with the etoolbox package:

Code: Select all

% untested
\usepackage{etoolbox}
\csdef{mycmd1}{\chupleft}
\csdef{mycmd2}{\chupcenter}
% ...
\def\do#1{%
  \expandafter\expandafter\expandafter
  \newcommand
  \csname mycmd#1\endcsname{%
    \mchar #1%
  }%
}
\docsvlist{1,2,3}
However, if you only have this fixed set of commands, why don't you just define all of them right away?
kmcbest
Posts: 2
Joined: Tue Nov 10, 2009 4:33 pm

Define commands inside a command

Post by kmcbest »

I want easily change them. That is, from \createcommands{1,2,3,4,5,6,7,8} \createcommands{a,b,c,d,e,f,g,h} etc, if there are defined in eight different commands, changing them requires moving the cursor, pressing backspace/delete many times. Any I want to write a sty package for this, and a command can only take 9 parameters, I want these 8 characters to be one parameter instead of eight.

Your approach still doesn't work, after \docsvlist{1,2,3}, if I state \chupleft, it's still an undefined command, what I want is \chupleft to be available after execution of \docsvlist. Is it possible?

*Resolved* using etextools and \fortoksloop command

Code: Select all

\newcounter{cname}
\setcounter{cname}{0}
\newcommand\crcmd[1]{
	\fortoksloop{#1}\do{%
		\stepcounter{cname}
		\expandafter\newcommand\csname char\roman{cname}\endcsname{\mchar ##1}%
	}
}
\begin{document}
\crcmd{abcdefgh}
\chari\charii\chariii\chariv\charv\charvi\charvii\charviii
\end{document}
Post Reply