1

I am writing a paper in which I still haven't made all the stylistic choices. That is I haven't decided which long words I want to abbreviate and how I want to abbreviate them, if the author of the paper is a "me", a "we", a "the author" or the "authors" etc. So what I want to do is define a few keywords that will be reused many times.

I want to at the top of my document do something along the lines of \newcommand{\auth}{we} and whenever I write \auth{} in my document the word "we" should show up. Now, the more seasoned of you will notice that what I am describing here will actually do what I want it to so on to the real question.

What I really want to do is link a word in the english dictionary to a command and when passing an argument to that command being able to slightly change its output. So for instance if I define \auth{} to spit out "we" I want \auth{upper} to spit out "We" instead. I would also like to be able to get possessive forms from it such as "Ours" and "ours" by calling \auth{upper, possessive}, \auth{possessive} or something similar. What would be the best way to achieve this? Can I create a dictionary of sorts or what do you recommend?

Many thanks!

2

Well, I've tried. BTW, it only works in LuaLaTeX:

%!TEX program = lualatex
\documentclass{article}
\usepackage{polyglossia}
\usepackage{luacode}
\begin{luacode*}
dofile(kpse.find_file("l-lpeg.lua"))
dofile(kpse.find_file("util-sto.lua"))
dofile(kpse.find_file("util-prs.lua"))
Pronouns = {
    ["formal"] = {
        ["possessive"] = "ours",
        ["nominative"] = "we",
        ["oblique"] = "us"
    },
    ["informal"] = {
        ["possessive"] = "mine",
        ["nominative"] = "I",
        ["oblique"] = "me"
    }
}
function Auth(keywords)
    local dummy = utilities.parsers.settings_to_array(keywords)
    for i,v in ipairs(dummy) do
        if Pronouns[dummy[i]] ~= nil then result = Pronouns[dummy[i]] end
    end
    for i,v in ipairs(dummy) do
        if result[dummy[i]] ~= nil then result = result[dummy[i]] end
    end
    return result
end
function Upper(string)
    return unicode.utf8.upper(unicode.utf8.sub(string,1,1))..unicode.utf8.sub(string,2,utf8.len(string))
end
\end{luacode*}
\def\auth#1{\directlua{tex.print(Auth("#1"))}}
\def\Auth#1{\directlua{tex.print(Upper(Auth("#1")))}}
\begin{document}
\auth{oblique,informal} \Auth{formal,possessive}
\end{document}
2

This was surprisingly complex, but here is a solution working with any TeX*

\begingroup
\catcode`!=11 % for private macros
\endlinechar=-1
\catcode`\^^M=12 \catcode`\^^?=12\relax
\gdef\!stop{^^?}
\gdef\!fi{\fi}
\newtoks\!before \newtoks\!after

% some convenient shorthands
\gdef\!csnm#1{\csname#1\endcsname} 
\gdef\!ecsnm#1#2{\expandafter#1\csname#2\endcsname}

% the main command sets up the catcodes for reading in
% the definitions of the second argument
\gdef\newvarcommand#1{
  \begingroup\catcode`\^^M=12 \catcode`\^^?=12\relax
  {\escapechar=-1 \xdef\!name{\string#1}}
  \!ecsnm\newtoks{toks:\!name}
  \gdef#1##1{
    {\escapechar=-1 \xdef\!name{\string#1}}
    \begingroup
    \!processnextkey##1,^^?,
    \!ecsnm\the{toks:\!name}
    \!result
    \endgroup
  }
  \!newvarcommand
}

% for each modifier in the argument, set the corresponding
% conditional true
\gdef\!processnextkey#1,{\def\arg{#1}
  \ifx\!stop\arg\else
    \ifx\empty\arg\def\!key{default}\else\def\!key{#1}\fi
    \!ecsnm\ifx{ifkey:\!name:\!key}\relax
      \errmessage{Unknown key \!key\space for command \!name}
    \else\!csnm{key:\!name:\!key true}\fi
  \expandafter\!processnextkey\fi
}

% here we read the argument line by line
\gdef\!newvarcommand#1{\!getnext#1^^M^^?^^M}
\gdef\!getnext#1^^M{\def\arg{#1} 
  \ifx\!stop\arg\endgroup\else
  \ifx\empty\arg\else\!parse#1^^M\fi
  \expandafter\!getnext\fi
}

% for each entry, new conditionals are created to test whether a
% modifier is present or not, and a token list containing the
% conditionals and the word to be printed is appended to the
% token list read by the command to be defined
\gdef\!parse#1:#2^^M{\!before={}\!after={}\def\arg{#1}
  \ifx\empty\arg
    {\globaldefs=1 \!ecsnm\newif{ifkey:\!name:default}}
    \!before=\expandafter{\csname ifkey:\!name:default\endcsname}
    \!after=\expandafter{\!fi}
  \else\!setupnextkey#1,^^?,\fi
  \edef\!addtoks{\!ecsnm\the{toks:\!name}
    \the\!before\def\noexpand\!result{#2}\the\!after}
  \global\!csnm{toks:\!name}=\expandafter{\!addtoks}
}

% creating \newifs for each modifier
\gdef\!setupnextkey#1,{\def\arg{#1}
  \ifx\!stop\arg\else
    {\globaldefs=1 \!ecsnm\newif{ifkey:\!name:#1}}
    \!before=\expandafter{\the\expandafter\expandafter
      \expandafter\!before\!csnm{ifkey:\!name:#1}}
    \!after=\expandafter{\the\expandafter\!after\!fi}
  \expandafter\!setupnextkey\fi
}
\endgroup

You can then define your "dictionary" as follows:

\newvarcommand\auth{
  :we
  upper:We
  possessive:ours
  upper,possessive:Ours
}

In each line, you write the comma-separated words that you want to use as arguments, and then after a colon the word that should appear. The default value can be specified with either :val or default:val. Important: The entries should occur in the order of increasing number of specifiers (i.e., you should have all one-word entries first, then the ones with two comma-separated words, then three and so on), otherwise you might get incorrect results.

\auth{} \auth{default} % these two are the same, "we"
\auth{upper} % "We"
\auth{possessive} % "ours"
\auth{upper,possessive} \auth{possessive,upper} % both "Ours"
\auth{lower} % this gives an "Unknown key" error

Let me explain for the upper,possessive:Ours line how the code works. Basically when the line is read, it first creates conditionals \ifkey:auth:upper and \ifkey:auth:possessive. Then, a token list

\ifkey:auth:upper
  \ifkey:auth:possessive
    \def\!result{Ours}
  \fi
\fi

is constructed and appended to a token list named \toks:auth. If you use \auth{upper,possessive}, the arguments are read and the corresponding conditionals \ifkey:auth:upper and ifkey:auth:possessive are set to true, the toks:auth token list is unpacked and \!result is printed.


*It assumes a non-outer \newif though, like in LaTeX, but for plain TeX some adaptations would be necessary.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.