\documentclass{article} \def\version{1.2} %% Copyright 2013 Steven B. Segletes % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3c or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Steven B. Segletes. % % V1.1 -Typographical corrections to docs. % -Missing % added on line 356 % V1.2 -Now works with \l and \aa national symbols. % -Replaced all occurrences of \roman with \romannumeral\value % -Found two lines needing a trailing % % -Added a trailing space following invocations of \catcode % \usepackage{titlecaps} \usepackage{needspace} \parskip 1em \parindent 0em \newcommand\rl{\rule{1em}{0in}} \def\tcp{\textsf{titlecaps}} \def\QL{\titlecap{quirks, tricks, and limitations}} \usepackage{verbatimbox} \let\vb\verb \def\bs{$\backslash$} \reversemarginpar \marginparwidth 1.6in \newcommand\margtt[1]{\marginpar{\hfill\ttfamily#1}} \newcommand\margcmd[1]{\marginpar{\hfill\ttfamily\char'134#1}} \begin{document} \begin{center} \LARGE The {\tcp} Package\\ \rule{0em}{.7em}\small Routines for setting rich-text input into Titling Caps\\ \rule{0em}{2.7em}\large Steven B. Segletes\\ steven.b.segletes.civ@mail.mil\\ \rule{0em}{1.7em}\today\\ v\version \end{center} \Addlcwords{for a is but and with of in as the etc on to if} \section{\titlecap{description and commands}} The {\tcp} package is intended to be used to convert lower-cased text into titling caps, wherein the first letter of every word is capitalized, except for words designated to remain in lower case, for example prepositions and conjunctions. While this function has been performed elsewhere, for example in the \textsf{stringstrings} package, it is here significantly enhanced. The \textsf{stringstrings} implementation of titling caps is particularly limited because of its slow speed (I criticize \textsf{stringstrings} because I wrote it). Furthermore, that implementation only works on textual expressions, which do not contain any font-modification commands. In contrast, the {\tcp} package is set up to work in conjunction with font-modification commands that change the family, series, or shape of the font. Likewise, it will work with the fontsize changing commands (\vb|\tiny|, \vb|\scriptsize|\ldots\SoftSpace\vb|\Huge|) embedded in the argument. It is also, unlike the \textsf{stringstrings} version, able to screen out most punctuation when deciding whether a word is predesignated as lower case. Furthermore, it looks for symbols that might signify the beginning of a new text ``group'', such as (, [, \{, `, and -, and thereafter titles the word that follows, even though the first alphabetic letter is not technically at the lead of the ``word.'' The primary commands that have been implemented in this package are the following:\\ \itshape \rl\vb|\titlecap[|option\vb|]{|rich text\vb|}|\\ \rl\vb|\Addlcwords{|designated lower-case space-separated word list\vb|}|\\ \rl\vb|\Resetlcwords|\\ \upshape In addition, the following auxiliary commands are also available:\\ \itshape \rl\vb|\textnc{|text\verb|}|\\ \rl\vb|\def\converttilde{|\textup{T} or \textup{F}\vb|}|\\ \rl\vb|\noatinsidetc|\\ \rl\vb|\usestringstringsnames| % (addlcwords,resetlcwords,addlcword,capitalizetitle,getargs) \upshape ~\\ The \vb|\titlecap| command\margcmd{titlecap} is the primary contribution of this package. It will (within constraints) capitalize the first letter of each word in the argument. The primary constraint under which it operates is the existence of a predefined lower-cased word list that is set by the user, using the \verb|\Addlcwords| command\margcmd{Addlcwords}. These predefined lower-cased words are passed as an argument to \verb|\Addlcwords| in a space-separated list. Subsequent invocations add to the existing list of predefined lower-cased words. The user may clear the list of predefined lower-cased words through the issuance of the \verb|\Resetlcwords| command\margcmd{Resetlcwords}. When \verb|\titlecap| is invoked, it first breaks the argument into individual pieces that constitute ``words.'' Note, however, that these ``words'' may include punctuation and text formatting commands interspersed with the actual text. This is an essential challenge to overcome. After breaking the argument into words, \verb|\titlecap| will attempt to match each word of the argument to the list of predesignated lower-cased words. In order to assist this process, the command (temporarily) screens out text-formatting commands and punctuation marks from the argument, so that their presence does not inhibit a word match with the lower-cased word list (see {\QL} for exceptions). It flags matches, so that these matching words will not later be titled. The command will then reconstitute the ``words'' of the argument with their punctuation and font-changing commands intact. In the default invocation, \verb|\titlecap| will capitalize the first word of the argument, even if that word is on the lower-cased word list. This default may be overridden with the command's optional argument. Employing anything other than a capital ``P'' will treat the first word of the argument like any other word, meaning it will be title-capped only if it does not appear on the predesignated lower-cased word list. The algorithm that searches the ``words'' of the argument character by character, in order to titlecap the first letter of a word, is, generally speaking, able to process only textual content. However, special provisions have been enacted to handle the following text-formatting commands within the argument of \verb|\titlecap|: \begin{minipage}{\textwidth} \rl \begin{tabular}{llll} \verb|\textup| & \verb|\upshape| & \verb|\tiny| & \verb|\Huge|\\ \verb|\textit| & \verb|\itshape| & \verb|\scriptsize| & \verb|\textnc|\footnote{This command is introduced by this package.}\\ \verb|\textsc| & \verb|\scshape| & \verb|\footnotesize|&\\ \verb|\textsl| & \verb|\slshape| & \verb|\small|&\\ \verb|\textmd| & \verb|\mdseries| & \verb|\normalsize|&\\ \verb|\textbf| & \verb|\bfseries| & \verb|\large|&\\ \verb|\textrm| & \verb|\rmfamily| & \verb|\Large|&\\ \verb|\textsf| & \verb|\sffamily| & \verb|\LARGE|&\\ \verb|\texttt| & \verb|\ttfamily| & \verb|\huge|&\\ \end{tabular} \end{minipage} Other macros can generally be handled in the argument to \verb|\titlecap| only if they expand to textual content. \needspace{3\baselineskip} Once the first word of the argument has been titled ``by force'' (or not, with the use of the optional argument), the command proceeds through each word, deciding whether or not to title the word, based on the lower-cased word flag that has previously been set. The {\tcp} package can notably handle the titling of strings containing both diacritical marks found in various languages (such as \`o, \'o, \^o, \"o, \~o, \=o, \.o, \u o, \v o, \H o, \t{oo}, \c o, \d o, and \b o), as well as national symbols (such as \oe, \ae, \aa, \l, and \o). While punctuation had been earlier screened out in order to search for predefined lower-cased words, that is a slightly different problem from that of figuring out how to titlecap a punctuated word not on the lower-cased list. While many punctuation marks trail a word and are, therefore, not a problem, several punctuation marks lead a word, or indicate a group separator, even in the absence of whitespace. \verb|\titlecap| must make sure that these sorts of punctuation marks do not inhibit the capitalization of the subsequent letter. To this end, \verb|\titlecap| looks for instances of the following five characters: -, (, [, \{, and `, and flags the next character for possible capitalization (unless the word had been previously identified as predefined lower-cased [see {\QL}]). \section{\QL} While {\tcp} has been set up to run with certain embedded size and font-changing commands, it will not, in general, work with macros in the argument, unless the macros expand directly to a text string. The {\tcp} package is designed to screen out punctuation when searching for words that are pre-designated as lower-cased. So, for example, the word (\textit{if}) or \textit{``if''} or [\textit{if} or \textit{if,} will all be found to match \textit{if} when it is predesignated as lower cased. However, {\tcp} cannot screen out the curly braces \verb|\{| and \verb|\}| from the punctuation list. Thus, \{if\} will be capitalized as \{If\} by \tcp. A workaround is detailed in each of the next two paragraphs. To prevent a word from being titled (to force it into lower case), it can be immediately preceded by a \verb|\relax|. In this way, the \verb|\relax| is titled, rather than the following word. This method can be used to for one-time exceptions to titling, or to overcome the curly-brace problem described above, as in \verb|\{\relax if\}|. The package introduces a command, \verb|\textnc|\margcmd{textnc} (standing for ``text no-change''). If used outside of the \verb|\titlecap| argument, it is defined as \verb|\def\textnc#1{#1}| and so is leaves the argument intact. Inside of the \verb|\titlecap| argument, however, it forces its argument to be independently considered as text, regardless of any surrounding punctuation or other characters. Thus, this approach may also be used to address the curly-brace issue as \verb|\{\textnc{if}\}|. In this case, ``if'' would be titled if it is not on the lower-cased word list, but left in lower case if it were on the lower-cased word list. The \verb|\textnc| command is useful in a number of ways inside the argument to \verb|\titlecap|, but always to signify its argument is to be treated as a block of text, independently evaluated for its predesignated lower-cased content. If a separator like, let's say, a left paren, is used without whitespace, in the fashion of ``\verb|a(b)|,'' then neither \verb|a| nor \verb|b| could possibly be detected as lower-cased words, since the ``word'' without punctuation would be \verb|ab|, which is neither \verb|a| nor is it \verb|b|. For individual instances or exceptions, the insertion of a \verb|\relax| prior to ``\verb|a|'' or ``\verb|b|'' would prevent titling of these terms. Alternately, the word ``\verb|ab|'' could be added to the predesignated lower-cased words list, in which case, ``\verb|a(b)|'' would be preserved in lower case. A third (and perhaps preferred) method is the use of the \verb|\textnc{}| construct, which is introduced solely for the purpose of designating embedded text as a separate word grouping. Thus, \verb|\textnc{a}(\textnc{b})| as an argument to \verb|\titlecap| would guarantee that both ``\verb|a|'' and ``\verb|b|'' would be independently examined for their presence in the lower-cased word list, irrespective of any surrounding punctuation. In this paragraph, the letters ``\verb|a|'' and ``\verb|b|'' have been used for simplicity, but could actually represent words or groups of words. By \LaTeX{} convention, expansion of the construct ``\vb|very \large big|'' will associate the \vb|\large| as the first letter of \vb|big|, rather than as the last letter of \vb|very|. Unfortunately, leaving it that way will screw up the titling of \vb|big|. Thus, when adapting the use of fontsize changes to the {\tcp} package, the prior space is unskipped, and a space is added after the fontsize change invocation, so that the fontsize change command is at the end of the prior word, rather than at the beginning of the next word. The one adverse side effect to this approach is that a space \textbf{will} appear after a fontsize command, even if one is not desired (for example, changing font size just prior to punctuation). One can either issue a \vb|\unskip| following the fontsize change to back-gobble the newly introduced space, or else place the fontsize change following the punctuation. While \vb|\uppercase| will not work within the argument of a \vb|\titlecap|, it was found that enclosing part of the argument in double braces \margtt{\char'173\char'173~\char'175\char'175}will produce upper case for that double-enclosed text. Thus,\\ \rl\vb|\titlecap{This is a {{v\"ery}} big test}|\\ will produce \titlecap{This is a {{v\"ery}} big test}. The implementation to make the fontsize change commands work within the arguments of \vb|\titlecap| required the use of \vb|\makeatletter| within \vb|\titlecap| itself (which is revoked with a \vb|\makeatother| upon exit from \vb|\titlecap|). If that is not considered a ``good practice'' for your situation, then you can disable this feature with the command \vb|\noatintc|\margcmd{noatintc}. However, it is likely, at that point, that the fontsize changing commands as arguments will break the \vb|\titlecap| command. Except in the case of the various \vb|\text|\textit{xx}\vb|{}| commands, for which special provision has been made, and for the double-brace quirk mentioned above, the argument of \vb|\titlecap| should not contain braces used as group delimiters, for example, in the fashion of:\\ \rl\vb|\titlecap{this is a {\itshape test of|\\ \rl\rl\vb|the} emergency broadcast system}|\\ It may not break the code, but will likely not produce a desired result. If groupings must be placed in the argument, using \verb|\textnc{}| to condition the argument is recommended. Thus,\\ \rl\vb|\titlecap{this is a \textnc{\itshape test of|\\ \rl\rl\vb|the} emergency broadcast system}|\\ will result in ``% \titlecap{this is a \textnc{\itshape test of the} emergency broadcast system}'' (of course, in this case, a \vb|\textit{}| would have worked directly, without a problem). There should be no direct use or need to nest \vb|\titlecap| commands. However, if it is absolutely necessary, the embedded invocation of \verb|\titlecap| should be expressed as\\ \rl\verb|\titlecap{...\titlecap\textnc{...}...}|. \section{\titlecap{auxiliary commands}} In addition to the primary commands offered by this package, there are several auxiliary commands. As described in the section {\QL}, the \verb|\textnc|\margcmd{textnc} command was introduced when additional grouping must occur inside the argument of a \verb|\titlecap| command. The command \verb|\textnc| will itself make no changes to its argument, but will force \verb|\titlecap| to independtly evaluate the \verb|\textnc| argument for its lower-cased content, regardless of any surrounding punctuation or text. The command may only be \textit{needed} within an argument to \verb|\titlecap|. However, if your application requires its invocation outside of a \verb|\titlecap| argument, it will merely output the argument without any modification. By default, the {\tcp} package treats hardspaces ($\sim$) as characters and not white space. This default treatment can be changed by setting the following parameter: \verb|\def\converttilde{T}|\margcmd{converttilde}. Following that invocation, hardspaces in the argument of \verb|\titlecap| should be indistinguishable from white space. The command \verb|\noatinsidetc|\margcmd{noatinsidetc} was briefly described in {\QL}. Its invocation will prevent the \verb|\titlecap| command from employing the \verb|\makeatletter| command, if this is considered bad practice for your setting. However, its invocation will likely make the {\tcp} package unable to process fontsize command changes. The last of these auxiliary commands is \verb|\usestringstringsnames|\margcmd{usestringstringsnames}. This command will redefine certain command names previously defined by the \textsf{stringstrings} package to instead use the corresponding commands of the {\tcp} package, in essence redirecting the \textsf{stringstrings} invocation to the current package. The redirected commands include the following (note: see the \textsf{stringstrings} package documentation for command arguments and options):\\ \rl\verb|\addlcwords|\\ \rl\verb|\resetlcwords|\\ \rl\verb|\addlcword|\\ \rl\verb|\getargs|\\ \rl\verb|\capitalizetitle|\\ If this command is invoked without the prior loading of the \textsf{stringstrings} package, these commands will still be enabled for subsequent use. Because the {\tcp} package produces output which can include font changes and other material that cannot be placed into an \verb|\edef|, the output of the quiet version of the newly redirected \verb|\capitalizetitle[q]| produces a \verb|\def\thestring{}| rather than an \verb|\edef\thestring{}|. \section{Acknowledgements} I would like to acknowledge the assistance of David Carlisle who, through the \textsf{tex.stackexchange} website, assisted with both the string parsing and punctuation screening techniques of this package: \verb|http://tex.stackexchange.com/questions/101604/parsing-strings|\\ \verb|-containing-diacritical-marks-macros| \verb|http://tex.stackexchange.com/questions/105735/ignoring|\\ \verb|-punctuation-during-comparison| I would also like to thank Prof. Enrico Gregorio for his discovery of several bugs in the package and suggestions for fixes: \verb|http://tex.stackexchange.com/questions/225434/|\\ \verb|how-to-workaround-conflict-between-greek-and-titlecaps| \clearpage \section{\titlecap{a \ttfamily\bs titlecap \rmfamily demonstration for beginners,\\ expressed in \texttt{\bs titlecap}}} \Resetlcwords \Addlcwords{for a is but and with of in as the etc on to if} %\noatinsidetc \titlecap{% %{ to know that none of the words typed in this paragraph were initially upper cased might be of interest to you. it is done to demonstrate the behavioral features of this package. first, you should know the words that i have pre-designated as lower case. they are: ``for a is but and with of in as the etc on to if.'' you can define your own list. note that punctuation, like the period following the word ``if'' did not mess up the search for lower case (nor did the quotation marks just now). punctuation which is screened out of the lower-cased word search pattern include . , : ; ( ) [ ] ? ! ` ' however, I cannot screen text braces; \{for example in\} is titled, versus (for example in), since the braces are not screened out in the search for pre-designated lower-case words like for and in. However, \texttt{\bs textnc} provides a workaround: \{\textnc{for example in}\}. titlecap will consider capitalizing following a (, [, \{, or - symbol, such as (abc-def). you can use your text\textit{\relax xx} commands, like i just did here with the prior xx, but if you want the argument of that command to not be titled, you either need, in this example, to add \textit{xx} to the lowercase word list, which you can see i did not. instead, i put ``\bs relax~xx'' as the argument, so that, in essence, the \bs relax was capitalized, not the x. Or you could use \texttt{\bs textnc}. here i demonstrate that text boldface, \textbf{as in the \bs textbf command}, also works fine, as do \texttt{texttt}, \textsl{textsl}, \textsc{textsc}, \textsf{textsf}, \textit{etc}. titlecap will work on diacritical marks, such as \"apfel, \c cacao \textit{etc.}, \scriptsize fontsize \LARGE changing commands\normalsize\unskip, as well as national symbols such as \o laf, \ae gis, \oe dipus, \aa ngstrom, and \l ucky. the method will work with some things in math mode, capitalizing symbols if there is a leading space, $x^2$ can become $ x^2$, and it can process but it will not capitalize the greek symbols, such as $\alpha$, and will choke on most macros, if they are not direct character expansions. additionally, \textsf{titlecaps} also works with font changing declarations, for example, \bs itshape\bs sffamily. \itshape\sffamily you can see that it works fine. likewise, any subsequent \bs textxx command will, upon completion, return the font to its prior state, such as this \textbf{textbf of some text}. you can see that i have returned to the prior font, which was italic sans-serif. now I will return to upright roman\upshape\rmfamily. a condition that will not behave well is inner braces, such as \ttfamily \bs titlecap\{blah \{inner brace material\} blah-blah\}. \rmfamily see the section on quirks and limitations for a workaround involving \texttt{\bs textnc}. titlecap will always capitalize the first word of the argument (\textbf{even if it is on the lower-case word list}), unless \texttt{\bs titlecap} is invoked with an optional argument that is anything other than a capital p. in that case, the first word will be titled \textit{unless} it is on the lowercase word list. for example, i will do a \bs titlecap[\relax s]\{\relax a~big~man\} and get ``\titlecap[s]\textnc{a big man}'' with the ``a'' not titled. i hope this package is useful to you, but as far as using \textsf{titlecaps} on such large paragraphs\ldots \textbf{do not try this at home!}} \section{Code Listing} \verbatiminput{titlecaps.sty} \end{document}