
\ProvidesPackage{coffeexelatex}

% ==========================================================================================================
% USEFUL PACKAGES
% ----------------------------------------------------------------------------------------------------------
\usepackage{fontspec}
\usepackage{polyglossia}
\setdefaultlanguage{english}
\usepackage{fixltx2e}
\usepackage{hyperref}
\usepackage[usenames,dvipsnames,svgnames,table]{xcolor}
\usepackage[abspath]{currfile}
\usepackage{currfile-abspath}
\usepackage{xltxtra}
\usepackage{verbatim}
\usepackage{xstring}
% \usepackage{catchfile}
\usepackage{actcodes} % for `\MakeOther`
\usepackage{etoolbox} % for \newtoggle` etc; see http://tex.stackexchange.com/a/5896/28067
\usepackage{catchfile}
% \input binhex
% turn a character into its Unicode hexadecimal CID:
% \newcounter{x}
% \setcounter{x}{`\ろ}\nhex{2}{\thex}
% \usepackage{geometry}
% \usepackage{fp}
% \usepackage{fltpoint}

% ##########################################################################################################
\makeatletter

% ==========================================================================================================
% LOGOS
% ----------------------------------------------------------------------------------------------------------
% works with EB Garamond 12 Regular:
\newcommand{\CXLTXlong}{\textit{C\kern-0.05emoff\kern-0.05eme\kern-0.05eme\kern-0.05em}\XeLaTeX}

% \makeatletter
\usepackage{relsize}%

% fix the annoyingly narrow limit to largest allowed font size:
\renewcommand\RSlargest{9999pt}%
\renewcommand\RSsmallest{1pt}%

% works with LaTeX standard font (CM):
\DeclareRobustCommand{\CXLTXstandard}{%
{\raisebox{-0.1em}{\relsize{2}C}\kern-.75em\raisebox{0.2em}{{\relsize{-2}X}}}%
\hspace{0.1em}L{\kern-.36em\raisebox{0.25em}{\relsize{-0.5}{T}}}\kern-.28emX}

% works with EB Garamond 12 Regular and `relsize{8}`:
\DeclareRobustCommand{\CXLTXebgaramondBig}{%
{\raisebox{-0.1em}{\relsize{1.5}C}\kern-.58em\raisebox{0.12em}{{\relsize{-2}X}}}%
\hspace{0.05em}L{\kern-.36em\raisebox{0.16em}{\relsize{-0.5}{T}}}\kern-.17emX}

% works with EB Garamond 12 Regular in standard text size:
\DeclareRobustCommand{\CXLTXebgaramondSmall}{%
{\raisebox{-0.1em}{\relsize{1.5}C}\kern-.58em\raisebox{0.12em}{{\relsize{-1.5}X}}}%
\hspace{0.05em}L{\kern-.36em\raisebox{0.25em}{\relsize{-0.5}{T}}}\kern-.1emX}

% declare default logo to be used:
% \def\CXLTX{\CXLTXstandard}
\def\CXLTX{\CXLTXebgaramondSmall}
% \makeatother


% ==========================================================================================================
% ACCESS POINTS
% ----------------------------------------------------------------------------------------------------------
% These commands define (1) the routes to the `coffeexelatex/src/main.js` JavaScript module, (2) the routes
% to the temporary files that capture `stdout` and `stderr` of command line invocations, and (3) the host
% name and port where the CXLTX server is listening.
%
% The route setup here works in case you want to compile one of the examples from the CXLTX distro
% from within their respective directories. In the general case, you will have to adjust the path so NodeJS
% knows where to find the script; use something along the lines of
%
%     \renewcommand{\CXLTXcliRoute}{route/to/main}
%
% in your `.tex` document to do that.
%
\getpwd % necessary to set `currfile`'s `\thepwd`
\newcommand{\CXLTXcliRoute}{../../lib/cli}
\newcommand{\CXLTXtempOutRoute}{/tmp/CXLTXtempout.tex}
\newcommand{\CXLTXtempErrRoute}{/tmp/CXLTXtemperr.tex}
\newcommand{\CXLTXhost}{localhost:8910}
\newcommand{\CXLTXparameterSplitter}{,}
\edef\CXLTXtexRoute{\currfileabsdir\jobname}




% ==========================================================================================================
% HELPERS
% ----------------------------------------------------------------------------------------------------------
% Prints out errors.
% Notice you'll get into difficulties should stdout or stderr contain ANSI color codes; that'd remain to be
% fixed.
\newcommand{\CXLTXshowOutputAndErrors}{%
  \CXLTXifFileEmpty{\CXLTXtempOutRoute}%
    {}%
    % {\input{\CXLTXtempOutRoute}}
    {%\auxc{\input{\CXLTXtempOutRoute}}%
    \CXLTXwrapOutput{\input{\CXLTXtempOutRoute}\unskip}}%
  \CXLTXifFileEmpty{\CXLTXtempErrRoute}%
    {}%
    {{\color{red}Errors have occurred: %
      \verbatiminput{\CXLTXtempErrRoute}\unskip}}}

% ----------------------------------------------------------------------------------------------------------
% Check whether file is empty; thx to https://groups.google.com/forum/#!topic/comp.text.tex/bzsDBa4_Ooc
%
% \makeatletter
\newcommand*\CXLTXifFileEmpty[3]{%
    \openin\@inputcheck#1 %
    \ifeof\@inputcheck
        #2\relax
    \else
        \read\@inputcheck to \reserved@a
        \ifeof\@inputcheck
            % \typeout{#1 empty}%
            #2\relax
        \else
            #3\relax
        \fi
    \fi
    \closein\@inputcheck
}


% ==========================================================================================================
% REMOTE COMMAND OUTPUT WRAPPING
% ----------------------------------------------------------------------------------------------------------
\newtoggle{CXLTXwrapOutputToggle}
\toggletrue{CXLTXwrapOutputToggle}
% \togglefalse{CXLTXwrapOutputToggle}

\newcommand{\CXLTXwrapOutput}[1]{%
  \iftoggle{CXLTXwrapOutputToggle}{%
    \begingroup%
      \CXLTXprefix%
        #1%
        \CXLTXsuffix%
      \endgroup%
  }{% else
    #1}}
\def\CXLTXprefix{\color{DarkGreen}}
\def\CXLTXsuffix{}

% ==========================================================================================================
% CORE COMMANDS (CL/RCI)
% ----------------------------------------------------------------------------------------------------------
\newcommand{\exec}[1]{%
  % \def\CXLTXlastCommand{#1 > "\CXLTXtempOutRoute" 2> "\CXLTXtempErrRoute"}%
  \def\CXLTXlastCommand{#1 > "\CXLTXtempOutRoute"}%
  \auxc{* CXLTX command: \CXLTXlastCommand}%
  % \immediate\write18{\CXLTXlastCommand}\input{\CXLTXtempOutRoute}}
  \immediate\write18{\CXLTXlastCommand}\CXLTXwrapOutput{\input{\CXLTXtempOutRoute}\unskip}}

% ----------------------------------------------------------------------------------------------------------
\newcommand{\execdebug}[1]{%
  \def\CXLTXlastCommand{#1 > "\CXLTXtempOutRoute" 2> "\CXLTXtempErrRoute"}%
  \auxc{* CXLTX command: \CXLTXlastCommand}%
  \immediate\write18{\CXLTXlastCommand}%
  % \auxc{* CXLTX result: \verbatiminput{\CXLTXtempOutRoute}}%
  \CXLTXshowOutputAndErrors}

% ----------------------------------------------------------------------------------------------------------
\newcommand{\execCatch}[1]{%
  \def\CXLTXlastCommand{#1 > "\CXLTXtempOutRoute" 2> "\CXLTXtempErrRoute"}%
  \auxc{* CXLTX command: \CXLTXlastCommand}%
  \immediate\write18{\CXLTXlastCommand}%
  % \CatchFileDef{\cxltxR}{/tmp/CXLTXtempout.tex}{}% !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  % \auxc{* CXLTX result: \verbatiminput{\CXLTXtempOutRoute}}%
  % \CXLTXshowOutputAndErrors
  }

% ----------------------------------------------------------------------------------------------------------
% \def\cxltxRead{\CatchFileEdef{\cxltxR}{/tmp/CXLTXtempout.tex}{}}
% thx to Joseph Wright @ http://tex.stackexchange.com/a/214123/28067 for suggesting `\@@input`.
\newcommand{\cxltxR}{\@@input /tmp/CXLTXtempout}


% ----------------------------------------------------------------------------------------------------------
\newcommand{\evaljs}[1]{\execdebug{node -p "#1"}}
\newcommand{\evalcs}[1]{\execdebug{coffee -e "console.log #1"}}

% ----------------------------------------------------------------------------------------------------------
% A simplified CXLTX invocation with `\nodeRun` takes two parameters:
%
% * the name of the method to execute;
% * a list of comma-separated arguments.
%
% The route to the dispatcher will be taken from the `\CXLTXcliRoute` macro.
%
\newcommand{\nodeRun}[3][\CXLTXparameterSplitter]{%
  \exec{node "\CXLTXcliRoute" "\currfileabsdir" "#1" "#2" "#3"}}


% ==========================================================================================================
% CORE COMMANDS (H/RCI)
% ----------------------------------------------------------------------------------------------------------
% This is a sad code duplication of `\CXLTX@urlescape`; i've tried every conceivable trick i knew but
% couldn't find a way to make it work short of the one below. The reader is invited to improve on this
% unsatisfactory solution.
%
% Arguments:
%   #1: parameter splitter (optional)
%   #2: command
%   #3: parameter
%
\newcommand{\nodeCurl}[3][\CXLTXparameterSplitter]{%
  \begingroup%
  \CXLTX@urlescape{#3}%
  \let\three=\urlescapecurrent%
  \StrSubstitute{\CXLTXtexRoute}{\%}{\%25}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{/}{\%2F}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{\&}{\%26}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{ }{\%20}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{\$}{\%24}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{+}{\%2b}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{,}{\%2c}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{:}{\%3a}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{;}{\%3b}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{?}{\%3f}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{@}{\%40}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{"}{\%22}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{<}{\%3c}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{>}{\%3e}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{\#}{\%23}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{\{}{\%7b}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{\}}{\%7d}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{|}{\%7c}[\CXLTX@texRouteEscaped]%
  \StrSubstitute{\CXLTX@texRouteEscaped}{'}{\%27}[\CXLTX@texRouteEscaped]%
  \execCatch{curl --silent --show-error \CXLTXhost /\CXLTX@texRouteEscaped/#1/#2/\three}%
  % \auxc{\CXLTX@texRouteEscaped}
  \endgroup%
  % \cxltxRead%
  % \cxltxR%
  % \@@input /tmp/CXLTXtempout%
  }

% ----------------------------------------------------------------------------------------------------------
\newcommand{\node}{\nodeCurl}


% ==========================================================================================================
% URL ENVIRONMENT
% ----------------------------------------------------------------------------------------------------------
% To make writing out URLs in TeX a bit easier, we define the `\begin{URL} ... \end{URL}` environment:
% To avoid a name clash with the `hyperref` package, we use `URL` instead of `url`.
\newenvironment{URL}%
  % ........................................................................................................
  {\begingroup%
  % \endlinechar=-1
  \MakeOther\~
  \MakeOther\&
  \MakeOther\#
  % \catcode`\_=12 % ???
  \catcode`\%=12
  \catcode`\$=12
  \catcode`\^=12
  \catcode`\~=12
  }{\endgroup}

  % These are not going to work:
  % \catcode`\&=12
  % \catcode`\#=12
  % \catcode`\{=12
  % \catcode`\}=12
  % \catcode`\`=12
  % ... more critical characters ...

% ==========================================================================================================
% WRITING TO THE `.AUX` FILE
% ----------------------------------------------------------------------------------------------------------
% The `\aux*{}` commands write a line to the `*.aux` file to enable messaging between LaTeX and
% NodeJS outside of command execution. Lines produced by `\auxc{}` start with a `% ` (percent, blank) so
% they will be ignored by LaTeX. Lines produced by `\auxcs{}` start with a `% coffee ` (percent, blank,
% literal 'coffee', blank) and will be parsed as CoffeeScript.
%
% Observe that if the argument to one of the `\aux*{}` commands should include newlines, then TeX will
% 'fold' those lines back into a single line, so your CoffeeScript code should be written as though on a
% single line. To clarify, always end list elements and object name / value pairs with a comma. This will
% cause a syntax error:
%
%     \auxcs{
%       "we are on page": \thepage
%       "just a value": 43 }
%
% but this is OK:
%
%     \auxcs{
%       "we are on page": \thepage,
%       "just a value": 43 }
%
% The CXLTX macro has a variable `@aux` that contains all the values transported via the `*.aux`
% file. When you put an unnamed POD literal inside an `\auxcs{}` command, its name / value pairs will be
% used to populate the `@aux` variable.
%
% The `\auxpod{}` command takes two arguments, a name and a CoffeeScript object / 'plain old dictionary'
% (POD) literal. It simplifies the creation of namespaces in `@aux`, so instead of
%
%     \auxcs{ foo: \{ bar: 'baz' \} }
%
% you can simply write
%
%     \auxpod{foo}{ bar: 'baz' }
%
% to effectively do `@aux[ 'foo' ] = { bar: 'baz' }`. Note that we currently simply overwrite existing
% entries in `@aux` instead of updating them; this may change in the future. The `\auxgeo{}` command
% is a real-world example for `\auxpod{}` usage.
%
% thx to http://tex.stackexchange.com/a/115933/28067 for the `\write\@auxout` part.
% \makeatletter
\catcode`\%=11
\newcommand{\aux}[1]{\immediate\write\@auxout{#1}}
\newcommand{\auxc}[1]{\immediate\write\@auxout{% #1}}
\newcommand{\auxcs}[1]{\immediate\write\@auxout{% coffee #1}}
\newcommand{\auxpod}[2]{\immediate\write\@auxout{% coffee #1: \{ #2 \}}}
\catcode`\%=14
% \makeatother

% ----------------------------------------------------------------------------------------------------------
% The `\auxgeo` command may be called after `\begin{document}`; it writes a number of raw layout dimensions
% into the `*.aux` file that are then converted to convenient millimeters. Note there is currently no
% way to handle intermittent document format changes; as it stands, `auxgeo{}` will only work as intended
% when the layout stays the same for all pages where its data is requested.
%
% Not that in order to use this command, you must have `\usepackage{geometry}` in your preamble. We can't do
% that for you since you likely will want to set your own page layout options.
%
\newcommand*\getlength[1]{\number#1}
\newcommand{\auxgeo}{\auxpod{geometry}{
  % top:            \the\top,
  % left:           \the\left,
  % inner:          \the\inner,
  % right:          \the\right,
  % outer:          \the\outer,
  % bottom:         \the\bottom,
  % width:          \the\width,
  % height:         \the\height,
  paperwidth:     \getlength{\paperwidth},
  paperheight:    \getlength{\paperheight},
  textwidth:      \getlength{\textwidth},
  textheight:     \getlength{\textheight},
  headheight:     \getlength{\headheight},
  headsep:        \getlength{\headsep},
  footskip:       \getlength{\footskip},
  marginparsep:   \getlength{\marginparsep},
  marginparwidth: \getlength{\marginparwidth},
  voffset:        \getlength{\voffset},
  topmargin:      \getlength{\topmargin},
  }}


% ==========================================================================================================
% Escaping URLs
% ----------------------------------------------------------------------------------------------------------
% The `\urlescape` command escapes a string so it can be safely used as an argument e.g. to the command line
% `curl` command. The characters deemed as 'unsafe' here have been gleaned from
% http://perishablepress.com/stop-using-unsafe-characters-in-urls/; in practice the list could probably be
% shortened somewhat.
%
% NB: the first version of `\urlescape` did not coöperate all too well with `\write18` (because `\write`);
% it has been replaced by the version further down.
%
% thx to http://tex.stackexchange.com/a/153217/28067 for this beautiful solution
% % \makeatletter
% \newcommand{\@CXLTX@urlescapestep}[2]{%
%   \expandafter\StrSubstitute\expandafter{\x}{#1}{#2}[\x]%
%   }
% \newcommand{\urlescape}[1]{{%
%   \noexpandarg % suppress expansions made by xstring
%   \StrSubstitute{#1}{\%}{\%25}[\x]% first step
%   \@CXLTX@urlescapestep{/}{\%2F}%
%   \@CXLTX@urlescapestep{\&}{\%26}%
%   \@CXLTX@urlescapestep{ }{\%20}%
%   \@CXLTX@urlescapestep{\$}{\%24}%
%   \@CXLTX@urlescapestep{+}{\%2b}%
%   \@CXLTX@urlescapestep{,}{\%2c}%
%   \@CXLTX@urlescapestep{:}{\%3a}%
%   \@CXLTX@urlescapestep{;}{\%3b}%
%   \@CXLTX@urlescapestep{?}{\%3f}%
%   \@CXLTX@urlescapestep{@}{\%40}%
%   \@CXLTX@urlescapestep{"}{\%22}%
%   \@CXLTX@urlescapestep{<}{\%3c}%
%   \@CXLTX@urlescapestep{>}{\%3e}%
%   \@CXLTX@urlescapestep{\#}{\%23}%
%   \@CXLTX@urlescapestep{\{}{\%7b}%
%   \@CXLTX@urlescapestep{\}}{\%7d}%
%   \@CXLTX@urlescapestep{|}{\%7c}%
%   \@CXLTX@urlescapestep{\^}{\%5e}%
%   \@CXLTX@urlescapestep{\~}{\%7e}%
%   \@CXLTX@urlescapestep{[}{\%5b}%
%   \@CXLTX@urlescapestep{]}{\%5d}%
%   \@CXLTX@urlescapestep{\`}{\%60}%
%   \x}}
% % \makeatother
% ..........................................................................................................
% alternative implementation of `\urlescape` as per
% http://tex.stackexchange.com/a/153539/28067
%
% In the following group endlines do not produce spaces
% and `%' becomes a printable character
\newcommand{\CXLTX@urlescapestep}[2]{%
  \expandafter\StrSubstitute\expandafter{\x}{#1}{#2}[\x]%
  }
\begingroup
\endlinechar=-1
\catcode`\%=12
\MakeOther\`
\gdef\CXLTX@urlescape#1{{
  \noexpandarg
  \StrSubstitute{#1}{%}{%25}[\x]
  \CXLTX@urlescapestep{/}{%2F}
  \CXLTX@urlescapestep{\&}{%26}
  \CXLTX@urlescapestep{ }{%20}
  \CXLTX@urlescapestep{\$}{%24}
  \CXLTX@urlescapestep{+}{%2b}
  \CXLTX@urlescapestep{,}{%2c}
  \CXLTX@urlescapestep{:}{%3a}
  \CXLTX@urlescapestep{;}{%3b}
  \CXLTX@urlescapestep{?}{%3f}
  \CXLTX@urlescapestep{@}{%40}
  \CXLTX@urlescapestep{"}{%22}
  \CXLTX@urlescapestep{<}{%3c}
  \CXLTX@urlescapestep{>}{%3e}
  \CXLTX@urlescapestep{\#}{%23}
  \CXLTX@urlescapestep{\{}{%7b}
  \CXLTX@urlescapestep{\}}{%7d}
  \CXLTX@urlescapestep{|}{%7c}
  \CXLTX@urlescapestep{\^}{%5e}
  \CXLTX@urlescapestep{\~}{%7e}
  \CXLTX@urlescapestep{[}{%5b}
  \CXLTX@urlescapestep{]}{%5d}
  \CXLTX@urlescapestep{`}{%60}
  \CXLTX@urlescapestep{'}{%27}
  \global\let\urlescapecurrent=\x}}
\endgroup


% ##########################################################################################################
\makeatother



