# -*- mode: Perl -*-
# /=====================================================================\ #
# |  OmniBus.cls                                                        | #
# | Implementation for LaTeXML                                          | #
# |=====================================================================| #
# | Part of LaTeXML:                                                    | #
# |  Public domain software, produced as part of work done by the       | #
# |  United States Government & not subject to copyright in the US.     | #
# |---------------------------------------------------------------------| #
# | Thanks to Catalin David <c.david@jacobs-university.de>              | #
# | of the arXMLiv group for initial implementation                     | #
# |    http://arxmliv.kwarc.info/                                       | #
# | Released to the Public Domain                                       | #
# |---------------------------------------------------------------------| #
# | Bruce Miller <bruce.miller@nist.gov>                        #_#     | #
# | http://dlmf.nist.gov/LaTeXML/                              (o o)    | #
# \=========================================================ooo==U==ooo=/ #
package LaTeXML::Package::Pool;
use strict;
use warnings;
use LaTeXML::Package;

#======================================================================
# This is the OmniBus class file.
# It is a stand-in for class files for which we have no binding.
# It attempts to define in fairly generic fashion most of the frontmatter
# commands that are commonly encountered.
# Of course having the "wrong" things defined
# or the right things defined wrongly may lead to other errors.
# But we're betting that we come out ahead.
#======================================================================

LoadClass('article');
ProcessOptions();

# Various common things often defined or included by unique classes
# \institute,, \inst  from inst_support
RequirePackage('inst_support');
RequirePackage('epsf');
# One of the graphics|graphicx packages are often included, leading to undefined \includegraphics
# However, they have different parameter patterns! But, graphicx seems to be included
# by random cls files by over 10 to 1, so we'll just load graphicx and hope for the best.
# The alternative would be to write a version that sniffed the arguments...
RequirePackage('graphicx');

# natbib is also often used, but reportedly clashes with cite.sty
# We'll autoload natbib if it hasn't already been loaded, and if any of its obvious macros are used.
foreach my $trigger (qw(citet citep citealt citealp citenum citeauthor citefullauthor
  citeyear citeyearpar citeauthoryear setcitestyle bibpunct)) {
  DefAutoload($trigger, 'natbib.sty.ltxml'); }
Let('\lx@OmniBus@saved@bibitem', '\bibitem');
# Another hacky autoload: Recognize \bibitem[\protect\citeauthoryear...
# when it would otherwise be too late to fix.
DefPrimitive('\lx@late@usepackage Semiverbatim', sub { RequirePackage(ToString($_[1])); });
DefMacro('\bibitem',
'\@ifnext@n{[\protect\citeauthoryear}{\lx@late@usepackage{natbib}\bibitem}{\lx@OmniBus@saved@bibitem}');
DefEnvironment('{frontmatter}', '#body');
DefEnvironment('{mainmatter}',  '#body');
DefEnvironment('{backmatter}',  '#body');

DefMacro('\shorttitle{}',  '\@add@frontmatter{ltx:toctitle}{#1}');
DefMacro('\shortauthor{}', '');
DefRegister('\titlerunning',  Tokens());
DefRegister('\authorrunning', Tokens());
Let('\runningauthor', '\authorrunning');
Let('\runauthor',     '\authorrunning');

DefMacro('\runningtitle{}', Tokens());
Let('\runninghead', '\runningtitle');
DefMacro('\shortauthor{}',  Tokens());
DefMacro('\authors{}',      Tokens());
DefMacro('\shortauthors{}', Tokens());

DefConstructor('\@@@email{}{}', "^ <ltx:contact role='#2'>#1</ltx:contact>");
DefMacro('\email{}', '\@add@to@frontmatter{ltx:creator}{\@@@email{#1}{email}}');
Let('\emailaddr', '\email');
DefMacro('\ead{}[]',   '\@add@to@frontmatter{ltx:creator}{\@@@email{#1}{#2}}');
DefMacro('\emailname', 'E-mail');
DefMacro('\speaker{}', '\@add@frontmatter{ltx:creator}[role=speaker]{\@personname{#1}}');

# like from aas
DefConstructor('\@@@affiliation{}', "^ <ltx:contact role='affiliation'>#1</ltx:contact>");
DefMacro('\affil{}', '\@add@to@frontmatter{ltx:creator}{\@@@affiliation{#1}}');
DefMacro('\altaffilmark{}', sub {
    my ($gullet, $marks) = @_;
    map { (T_CS('\@altaffilmark'), T_BEGIN, @$_, T_END) } SplitTokens($marks, T_OTHER(',')); });
DefConstructor('\@altaffilmark{}',
  "<ltx:note role='affiliationmark' mark='#1'/> ");
DefConstructor('\altaffiltext{}{}',
  "<ltx:note role='affiliationtext' mark='#1'>#2</ltx:note>");

DefConstructor('\@@@address{}', "^ <ltx:contact role='address'>#1</ltx:contact>");
DefMacro('\address[]{}',   '\@add@to@frontmatter{ltx:creator}{\@@@address{#2}}');
DefMacro('\affiliation{}', '\@add@to@frontmatter{ltx:creator}{\@@@affiliation{#1}}');

# Comes as both macro with arg, and environment! w/ or w/o "s"!
DefMacro('\keyword{}',  '\@add@frontmatter{ltx:keywords}{#1}');
DefMacro('\keywords{}', '\@add@frontmatter{ltx:keywords}{#1}');
DefMacro('\kword{}',    '\@add@frontmatter{ltx:keywords}{#1}');
# {keyword}, {keywords}
DefEnvironment('{keywords}', '',
  afterDigest => sub {
    my $frontmatter = LookupValue('frontmatter');
    push(@{ $$frontmatter{'ltx:classification'} },
      ['ltx:classification', { scheme => 'keywords' }, @LaTeXML::LIST]);
    return; });
# Extend to be callable as \keywords{} or \begin{keywords}...
# Probably want to use this trick more often?
DefMacro('\keywords', sub {
    my ($gullet) = @_;
    ($gullet->ifNext(T_BEGIN)
      ? (T_CS('\keywords@onearg'))
      : (T_CS('\g@addto@macro'), T_CS('\@startsection@hook'), T_CS('\maybe@end@keywords'),
        T_CS('\begin{keywords}'))); });
DefMacro('\keywords@onearg{}', '\begin{keywords}#1\end{keywords}\let\endkeywords\relax');
DefMacroI('\maybe@end@keywords', undef, '\endkeywords');

DefMacro('\classification{}', '\@add@frontmatter{ltx:classification}{#1}');
DefMacro('\pacs{}',           '\@add@frontmatter{ltx:classification}[scheme=pacs]{#1}');
# \doi{doi} might be frontmatter, or just a \url-like thing.  So, let's guess!
DefMacro('\doi{}',
  '\if@in@preamble{\@add@frontmatter{ltx:classification}[scheme=doi]{#1}'
    . '\else\lx@doi{#1}\fi');
DefConstructor('\lx@doi{}', '<ltx:ref href="https:/doi.org/#1">#1</ltx:ref>');

for my $env (qw(conjecture proposition lemma corollary example definition)) {
  my $beginenv = "\\begin{$env}";
  DefMacroI(T_CS($beginenv), undef, sub {
      RequirePackage('amsthm');
      return Tokenize("\\newtheorem{theorem}{Theorem}[section]
  \\newtheorem{conjecture}[theorem]{Conjecture}
  \\newtheorem{proposition}[theorem]{Proposition}
  \\newtheorem{lemma}[theorem]{Lemma}
  \\newtheorem{corollary}[theorem]{Corollary}
  \\newtheorem{example}[theorem]{Example}
  \\newtheorem{definition}[theorem]{Definition}
  $beginenv")->unlist; }); }

# \abstracts
Let('\abst', '\abstract');
# \editors

# Seems to come in different spellings and often misused!
DefConstructor('\acknowledgments', "<ltx:acknowledgements name='#name'>",
  properties => sub { (name => Digest(T_CS('\acknowledgmentsname'))); });
DefConstructor('\endacknowledgments', "</ltx:acknowledgements>");
Tag("ltx:acknowledgements", autoClose => 1);

DefMacro('\acknowledgmentsname', 'Acknowledgements');
Let('\acknowledgements',      '\acknowledgments');
Let('\endacknowledgements',   '\endacknowledgments');
Let('\theacknowledgments',    '\acknowledgments');
Let('\endtheacknowledgments', '\endacknowledgments');

DefMacro('\received{}',     '\@add@frontmatter{ltx:date}[role=received]{#1}');
DefMacro('\revised{}',      '\@add@frontmatter{ltx:date}[role=revised]{#1}');
DefMacro('\accepted{}',     '\@add@frontmatter{ltx:date}[role=accepted]{#1}');
DefMacro('\pubyear',        '\@add@frontmatter{ltx:date}[role=publication]{#1}');
DefMacro('\preprint{}',     '\@add@frontmatter{ltx:note}[role=preprint]{#1}');
DefMacro('\communicated{}', '\@add@frontmatter{ltx:date}[role=communicated]{#1}');
DefMacro('\dedicated{}',    '\@add@frontmatter{ltx:note}[role=dedicated]{#1}');
DefMacro('\presented{}',    '\@add@frontmatter{ltx:date}[role=presented]{#1}');
DefMacro('\articletype{}',  '\@add@frontmatter{ltx:note}[role=articletype]{#1}');
DefMacro('\issue{}',        '\@add@frontmatter{ltx:note}[role=issue]{#1}');
DefMacro('\journal{}',      '\@add@frontmatter{ltx:note}[role=journal]{#1}');
DefMacro('\volume',         '\@add@frontmatter{ltx:note}[role=volume]{#1}');
DefMacro('\pubyear',        '\@add@frontmatter{ltx:date}[role=publication]{#1}');

# work as environment or not...
DefConstructor('\references',
  "<ltx:bibliography xml:id='#id' "
    . "bibstyle='#bibstyle' citestyle='#citestyle' sort='#sort'>"
    . "<ltx:title font='#titlefont' _force_font='true'>#title</ltx:title>"
    . "<ltx:biblist>",
  beforeDigest => sub { beforeDigestBibliography(); },
  afterDigest  => sub { beginBibliography($_[1]); }
);

DefConstructor('\endreferences',
  "</ltx:biblist></ltx:bibliography>");

Let('\reference', '\bibitem');

DefMacro('\comment{}', '');
1;
