[Tex/LaTex] Modular LaTeX document preambles and class files

document-classesdocument-configurationpackagespreamble

I have been debating whether or not to ask this question as I don't intend to create an overly broad unanswerable, or solely opinion based question, but I have decided that there are probably some techniques that will adequately answer this question.

I am looking for approaches I can use to organize my code to simplify or clean up my class file or document preamble. Below is some example snippets and organization from my cls file. I have tried to keep as much of this customization and configuration in the cls file rather than in a complex document preamble as I want the cls file to be a template that requrires minimal customizations in constantly changing main files that would contain a preamble.

Because it's all in my cls file (which I fear is on its way to an unmanageable length). When I branch off to a new project I would like to be able start from the same class file, and just prune out and modify what is relevant. One of the primary motivations is to prevent duplication when some global concepts always need to be updated, while other customizations definitely need to be stand alone. Since \input{} seems to very nicely let me use ../.. to navigate to where I would prefer to store individual config files (except across drives)

One of the few aspects of my document preamble is the configuration of newcommands, renewcommands, and files loaded and configured for glossaries which are all loaded in distinct files

\input{../src/private/my-newcommands}
\input{../src/private/config-glossary}  % Glossaries must be loaded before amsmath

so using this concept can the cls file be modularized and compartmentalized?

I had created some (what I had been describing as) config files that contained specific package loads and modifications for common tasks such as math, fonts, header/footer, titles, bibliography, formatting modifications, etc. But transporting some variable definitions, commands, environments, and packages (such as hyperref, cleveref, amsmath, etc) don’t seem to work when sorted into discrete tex files that are called using input or include is inside the cls file.

I can't provide a MWE for this as it seems irreproducible depending on what I put in these external tex files. For example, the color definitions and includes worked fine when grabbed with \input{} Should these by sty files instead for this to be possible?

Because a tex installation on linux has different rules about where a cls or sty file can be placed to be read, I will detail that this question is being asked with MikTex on windows in mind, but I am certainly open to comments about parallel organization structures on linux. For interests sake, one of the reasons that my cls file gets so complicated is my documents must be compatible with both xelatex and tex4ht.

Organizational example – I can't guarantee that any of this will run as I have not pruned this file with this intention, just tried to include some examples of content that I keep in my cls file:

    %_________________________________________________________________________________________________________________________________________
    %
    % C L A S S   F I L E   S E T T I N G S    
    %_________________________________________________________________________________________________________________________________________

    \NeedsTeXFormat{LaTeX2e}
    \ProvidesClass{EngBird_Template}[2013/10/01 

    %http://tex.stackexchange.com/questions/24542/create-list-of-all-external-files-used-by-master-latex-document
    %\RequirePackage{snapshot}


    \LoadClass[12pt, twoside, letterpaper]{report}  %oneside

    %\RequirePackage{standalone}
    \RequirePackage{letltxmacro}
    %\RequirePackage{Sweave}
%
%_________________________________________________________________________________________________________________________________________

% TODO List
% Try an organize in small modular components
% Fix bolds in section hierarchy titles   
%==========================================================================================================================================
% PACKAGES REQUIRED FOR CONFIGURING REPORT  - PAGE MARGINS AND LINE SPACING
%==========================================================================================================================================
%
    \RequirePackage[letterpaper,includehead,
        left=3.25cm,right=2.54cm,top=2.54cm,
        headheight=1.5cm,headheight=0.0cm,
        bottom=2.54cm,footskip=1.0cm
        %hmargin=3cm,vmargin=3.75cm %only used to get rid of a overfull \hbox warning.
        ]{geometry}

    \RequirePackage{parskip}
    \RequirePackage{setspace}

    % CONFIGURE PAGE SPACING AND HYPHEN RESTRICTION CRITERION   
    \pagestyle{plain} % options: empty , plain , fancy
    \onehalfspacing
    \righthyphenmin=6
    \lefthyphenmin=6

    %http://tex.stackexchange.com/questions/11707/how-to-force-output-to-a-left-or-right-page
    %\cleardoublepage
    \RequirePackage{emptypage}  %http://tex.stackexchange.com/questions/21629/avoiding-page-numbers-in-empty-pages
        \newcommand*{\cleartoleftpage}{%
          \clearpage
            \if@twoside
            \ifodd\c@page
              \hbox{}\newpage
              \if@twocolumn
                \hbox{}\newpage
              \fi
            \fi
          \fi
        }
%
%_________________________________________________________________________________________________________________________________________


%=========================================================================================================================================
% PACKAGES REQUIRED CREATING CUSTOM COLORS
%=========================================================================================================================================

    \ifdefined\HCode
    %   \RequirePackage[html]{tex4ht}
        \RequirePackage[dvips]{xcolor}
    \else
        \RequirePackage{xcolor}%color %\PassOptionsToPackage{dvipsnames}{xcolor}
    \fi


    \definecolor{Crimson}{rgb}{0.6471, 0.1098, 0.1882}
    \definecolor{chaptergrey}{rgb}{0.6,0,0}
    \definecolor{halfgray}{gray}{0.55} % chapter numbers will be semi transparent .5 .55 .6 .0
    \definecolor{webgreen}{rgb}{0,.5,0}
    \definecolor{webbrown}{rgb}{.6,0,0}
    \definecolor{Maroon}{cmyk}{0, 0.87, 0.68, 0.32}
    \definecolor{RoyalBlue}{cmyk}{1, 0.50, 0, 0}
    \definecolor{Black}{cmyk}{0, 0, 0, 0}
%_________________________________________________________________________________________________________________________________________
%=========================================================================================================================================
%   SNIPPETS FROM http://zoonek.free.fr/LaTeX/ TO IMPROVE FORMATTING AND APPEARENCE  
%   See also ftp://ftp.tex.ac.uk/tex-archive/documentation/MemoirChapStyles/MemoirChapStyles.pdf
%   http://tex.stackexchange.com/questions/73421/how-to-create-specific-chapter-style-in-book-documentclass
%=========================================================================================================================================

%http://zoonek.free.fr/LaTeX/LaTeX_samples_chapter/0.html
\def\thickhrulefill{\leavevmode \leaders \hrule height 1ex  \hfill \kern \z@}

\def\@makechapterhead#1{%
    %\vspace*{50\p@}%
    %\vspace*{6\p@}%
    {\parindent \z@ \centering \reset@font
        \singlespacing
        \thickhrulefill\quad
        \scshape \@chapapp{} \thechapter
        \quad \thickhrulefill
        \par\nobreak
        \vspace*{6\p@}%
        \interlinepenalty\@M
        \hrule
        \vspace*{6\p@}%
        %\fontsize{19}{6}
        \Large 
        \bfseries #1\par\nobreak
        \par
        \vspace*{6\p@}%
        \hrule
        \vskip 20\p@
        %\vskip 100\p@
    }}

    \def\@makeschapterhead#1{%
        %\vspace*{50\p@}%
        % \vspace*{6\p@}%
        {\parindent \z@ \centering \reset@font
            \singlespacing
            \thickhrulefill
            \par\nobreak
            \vspace*{6\p@}%
            \interlinepenalty\@M
            \hrule
            \vspace*{6\p@}%
            %\fontsize{19}{6}
            \Large 
            \bfseries #1\par\nobreak
            \par
            \vspace*{6\p@}%
            \hrule
            \vskip 20\p@
            %\vskip 100\p@
        }}

% some definitions
\def\year#1{\gdef\@year{#1}}                    % specified in coverpage.tex
\def\month#1{\gdef\@month{#1}}              % specified in coverpage.tex

\newcommand{\maketitlepage}
{ 
    \singlespacing
    \thispagestyle{empty}
    \vspace*{\fill} \vspace{2cm} \begin{center}
        \Huge \textcolor{Crimson}{\textit{\MyTitle}} \normalsize \\ \sc \vspace{2cm}
        \vspace*{1.0cm}
        \normalsize
        by \\
        \vspace*{1.0cm}
        \large {\textit{\@author}} \normalsize \\ \sc \vspace{1cm}

        \normalsize \vspace*{2.0cm}

        etc \\

    \end{center} \vspace*{\fill}
}
%=========================================================================================================================================

%=========================================================================================================================================
% Special einvironment modifications
%=========================================================================================================================================

%http://tex.stackexchange.com/questions/17887/prevent-abstract-environment-to-reset-pagenumbering
% either use notitlepage in the \LoadClass or this
\renewenvironment{abstract}{%
  \if@twocolumn
    \section*{\abstractname}%
  \else
    %\small
    \begin{center}%
      {\bfseries \abstractname\vspace{-.5em}\vspace{\z@}}%
    \end{center}%
    \quotation
  \fi}
  {\if@twocolumn\else\endquotation\fi}

%_________________________________________________________________________________________________________________________________________


%=========================================================================================================================================
%  E Q U A T I O N  C A P T I O N  S E T U P 
%=========================================================================================================================================

\DeclareCaptionType{mycapequ}[][List of equations]
\captionsetup[mycapequ]{labelformat=empty}

This class file is loaded in by the main latex document setup as follows:

%=============================================================================
%   P R E A M B L E
%=============================================================================
%______________________________________________________________________________________
%
% Setup the document class and enable a package to read preamble and files externally    %______________________________________________________________________________________
\documentclass{EngBird_Template}  

%----------------------------------------------------------------------
% Create a listing in the log of all files needed to process this document
\listfiles
\synctex=1 % turn synctex on automatically to sync between pdf viewer
%\setupbackend[export=yes]  % should be using with ConTeXt 
%\setupbackend     [export=example.xml, css=example.css]
%----------------------------------------------------------------------

\input{../src/private/my-newcommands} 
\input{../src/private/config-glossary}  % Glossaries must be loaded before amsmath

\renewcommand{\bibname}{References}   %\nocite{*}       % list all refs in database, cited or not

\begin{document}
    \ifdefined\HCode    \renewcommand{\textregistered}{\special{t4ht@+\string&{35}xAE{59}}x}    \else   \fi
    \input{../src/logical_contents}
\end{document}

Update

I think it might be worth mentioning that the modular spirit of this question could be applied to extend to workarounds for the texmf directory structure in an age of network computing. People like me use numerous computers and collaborate with others and as such absolute path names don't always work out great, and relative paths can be equally problematic. As a LaTeX user and enthusiast, but certainly not a developer, I find that my own code for customizations (in class and sty files) are not easily made portable, but also accessible to multiple projects, on multiple platforms, for multiple users.

Best Answer

I'm not sure I fully understood the setup of your class file, the ways you load various packages, and the ways new macros are defined (or existing ones are redefined). For sure, don't load packages -- typically in files with extension .sty -- via an \input statement. Instead, use \usepackage directives. If for no other reason, you should do so because \usepackage offers some protection against loading the same package twice (or more frequently...) with incompatible options. Similarly, you may want to rename the files you currently load via \input statements to have extension .sty, so that they can (should?) be loaded via \usepackage statements.

Separately, have you implemented document class-level options which let you decide at run time which packages should, or should not, be loaded?