# Suggested method of creating an end user editable variable with newcommand

I am trying to create a document template that would be used by many people where the end users can control certain values but most of the template style can be controlled centrally. Imagine a (simplified) directory structure that looks something like this:

.
├── latex
│   ├── front_pages.tex
│   ├── packages.tex
│   └── preamble.tex
├── Makefile
├── src
│   └── user_config.tex
├── sty
│   └── department_thesis.sty
└── user_thesis.tex


The idea is to have the template have distinct end user editable files (user_config.tex) and the rest be the centrally controlled "template" files (the whole thing is going to be used as a Git submodule) that the end user should never have to touch. If I want the end user to be able to control certain things though inputs in user_config.tex is there a "best" or most "LaTeX-ic" way of doing this by creating end user accessible variables with \newcommand?

For example, if I want to define a command in department_thesis.sty that the end user will then use as a "variable" in user_config.tex that will then actually get used in front_pages.tex what are people's suggestions on how to best do this?

Would it be something like

# department_thesis.sty


.

# user_config.tex
\AuthorFirstName{Graduate} % End user puts in their name here


.

# front_pages.tex
...
\authorfirstname % Here it is actually being used
...


Or is it better style to think in the mindset of setters/getters?

# department_thesis.sty


.

# user_config.tex
\SetAuthorFirstName{Graduate} % End user puts in their name here


.

# front_pages.tex
...
\AuthorFirstName % Here it is actually being used
...


Or is none of this a good way of thinking about the problem of wanting an end user to have control over certain values while being able to control the rest of the document's style centrally?

• In general I prefer key-value syntax for such things. So the user get a command \templatesetup{firstname=Matthew, lastname= Feickert,...} Such a setup is easy to use and easy to extend. – Ulrike Fischer Jun 8 '18 at 20:12

I made the following for my handin-package. The code in the answer is different as according to the edits:

Edit 1: \@macroname@noerror now will now not give an error when default value is not set.

Edit 2: Code behaves identically, but added comments and removed some repetitions for compactness. Also added an example usecase of the generated \ifset@ macro.

I suspect that printing the command name to the page might be unwanted behaviour. To remove this just remove the line that contains the comment %<- Print command name to page.. Furthermore: read the comments. Everything is explained in some detail :)

\documentclass{article}
\begin{document}
%%% Usage:
%%%\settable{text}
%%% The text you enter would be a macro:
%%%: \settable{hello}
%%%:  if now \@hello is called,
%%%:  a warning is displayed with
%%%:  the text "\hello not set"
%%%: \hello{world}
%%%: if now \@hello is called, it prints "world"
%%%: \@hello@noerror gives the returning
%%%: content and empty without error if no content set.
\makeatletter
\let\ea = \expandafter
\newcommand{\settable}[2][\@nil]{
%%% example call \settable[actionIfNotSet(default action)]{macroName}
%%% i.e. #1: is what to do if called and not set and
%%% #2 is the macroname
%
%------ Example case ------%
% The comments assume that someone called
% \settable[world]{hello}
%------ Code ------%
%
% First define the \hello command. The code below
% is equivalent to
% \def\hello##1{
%   \def\@hello{##1}
%   \def\@hello@noerror{##1}
% }
\ea\def\csname #2\ea\endcsname##1{
\ea\def\csname @#2\endcsname{##1}
\ea\def\csname @#2@noerror\endcsname{##1}
\ea\def\csname isset@#2\endcsname{1}%<- Used by \ifset@hello. Explained below:
}
% Now \hello is a callable macro.
%
% Next: create the command to check if \hello is defined.
% usage: \ifset@hello{User has set the macro}{User has not set the macro}
% Below is equivalent to
% \def\ifset@hello##1##2{
% \ifcsname isset@hello\endcsname% <- if the macro \isset@hello exists. \isset@hello is defined when \hello is called
%   ##1%
% \else
%   ##2%
% \fi
% }
\ea\def\csname ifset@#2\endcsname##1##2{
\ifcsname isset@#2\endcsname%
##1%
\else
##2%
\fi
}
% Now, make a macro to hold the default value and
% define it to be the given optional argument (\@nil by default, "world" in the
% example). The code below is equivalent (in the example case)
% to \def\default@hello{world}
\ea\def\csname default@#2\endcsname{#1}%
% Check if optional argument is given (e.g. if it is equal to \@nil)
\ifx#1\@nil\relax
% If no default value given, then set e.g. \@hello@noerror to be an empty value.
% The very first version of this answer would not have the below line.
\ea\def\csname @#2@noerror\endcsname{}%
% Also, if the opt arg is not given we define the default behaviour,
% \default@hello in the example case
% to print a console warning, as well as printing the macro name to the page
\ea\def\csname default@#2\endcsname{
{\@latex@warning{\@backslashchar #2 not given}}% <- Console warning
\textbackslash #2% <- Print command name to page.
}
\else
% If default value given, then set the \@hello@noerror to that value.
% Since "world" was given as optional in the example case, this will be
% the same as \def\@hello@noerror{world}
\ea\def\csname @#2@noerror\endcsname{#1}%
\fi

% We now define the usage macro \@hello:
\ea\def\csname @#2\endcsname{
\csname default@#2\endcsname
}
}
\settable{hello}
% A summary of generated macros
\ifset@hello{     %<-  Prints "User did not set hello"
User did set hello
}{
User did not set hello
}
\@hello@noerror   %<- Empty value. Does nothing extra by default.
\@hello           %<- Gives warning message "\hello not given", and prints "\hello" on page.
\hello{world}     %<- Sets \@hello and \@hello@noerror to "world"
\ifset@hello{     %<- Prints "User did set hello"
User did set hello
}{
User did not set hello
}
\@hello           %<- Prints "world"
\@hello@noerror   %<- Prints "world"
\end{document}

• This is extremely nice and does essentially exactly what I wanted. Thank you. Do I have your permission to use the above code snippet in this thesis template project (licence BSD-3-Clause) if I properly attribute it to you and link to your handin package? – Matthew Feickert Jun 8 '18 at 20:27
• Sure! Go ahead! I'd love if you'd link to it somewhere, but no pressure :) – Andreas Storvik Strauman Jun 8 '18 at 20:31
• It's originally distributed with the LPPL-1.3c-Licence :) – Andreas Storvik Strauman Jun 8 '18 at 20:37
• Ah, so if I try to use the noerror behavior in the example above I get an Undefined control sequence. Any thoughts on why (I'm using TeX Live 2017 and LuaLaTeX)? ! Undefined control sequence. \@hello@noerror ->\@nil – Matthew Feickert Jun 9 '18 at 20:32
• @MatthewFeickert That happens if the default value is \@nil. You can either remove the \@nil from the default optional argument or use \settable[]{commandname}. No error is intended as no warning shown to the user, heh. Misnamed I guess :) – Andreas Storvik Strauman Jun 10 '18 at 10:19