%D \module
%D   [     file=t-syntax-highlight,
%D      version=2011.06.14,
%D        title=\CONTEXT\ User Module,
%D     subtitle=Code syntax highlighting,
%D       author=Aditya Mahajan,
%D         date=\currentdate,
%D    copyright=Aditya Mahajan,
%D        email=adityam <at> umich <dot> edu,
%D      license=Simplified BSD License]

\writestatus{loading}{ConTeXt User Module / Code syntax highlighting}

\startmodule    [syntax-highlight]
\usemodule      [syntax-groups]
\usemodule      [filter]
\usemodule      [module-catcodes]

\unprotectmodulecatcodes

\startinterface all
  \setinterfaceconstant {syntax}          {syntax} 
\stopinterface

%D Name space

\def\syntaxhighlighting::id          {syntaxhighlighting}
\def\syntaxhighlighting::namespace   {@@@@\syntaxhighlighting::id}
\def\syntaxhighlighting::name        {}

\installparameterhandler \syntaxhighlighting::namespace \syntaxhighlighting::id
\installsetuphandler     \syntaxhighlighting::namespace \syntaxhighlighting::id

\def\definesyntaxhighlighting
  {\dodoubleargument\syntaxhighlighting::define}

\starttexdefinition syntaxhighlighting::define [#1][#2]
    \getparameters[\syntaxhighlighting::namespace#1][\s!parent=\syntaxhighlighting::namespace,#2]

    \edef\syntaxhighlighting::name{#1}
    \doifmode\s!mkiv{\setups{syntaxhighlighting::setup_line_number_mkiv}}

    \defineexternalfilter[#1][\s!parent=\syntaxhighlighting::namespace#1]
    \setvalue{type#1file}{\getvalue{process#1file}}

\stoptexdefinition

\startsetups syntaxhighlighting::setup

  \edef\syntaxhighlighting::name{\currentexternalfilter}
  \edef\colorscheme::name{\externalfilterparameter\c!alternative}
  
  \let\SYN\syntaxgroup
  \let\\\textbackslash
  \let\{\textbraceleft
  \let\}\textbraceright

  \def\tab##1%
      {\dorecurse{##1}{\space}}%
  
  \doifmode\s!mkii{\setups{syntaxhighlighting::setup_line_number_mkii}}%
  
  \doifinset{\externalfilterparameter\c!option}{\v!packed}
      {\setupwhitespace[\v!none,\v!flexible]}%
  
  \setcatcodetable\externalfilter::minimal_catcodes
  \activatespacehandler{\syntaxhighlighting::namespace\externalfilterparameter\c!space}
\stopsetups

\startsetups syntaxhighlighting::setup_line_number_mkiv
 \definelinenumbering [#1]

 \setuplinenumbering
   [\syntaxhighlighting::name]
   [\c!conversion=\externalfilterparameter\c!numberconversion,
        \c!start=\externalfilterparameter{\c!number\c!start},
         \c!step=\externalfilterparameter{\c!number\c!step},
        \c!method=\externalfilterparameter{\c!number\c!method},
      \c!location=\externalfilterparameter{\c!number\c!location},
         \c!style=\externalfilterparameter\c!numberstyle,
         \c!color=\externalfilterparameter\c!numbercolor,
         \c!width=\externalfilterparameter{\c!number\c!width},
          \c!left=\externalfilterparameter{\c!number\c!left},
         \c!right=\externalfilterparameter{\c!number\c!right},
       \c!command=\externalfilterparameter\c!numbercommand,
      \c!distance=\externalfilterparameter{\c!number\c!distance},
         \c!align=\externalfilterparameter{\c!number\c!align},
   ]
\stopsetups

\doifmode\s!mkii
    {\newcount\syntaxhighlighting::linenumber}

\startsetups syntaxhighlighting::setup_line_number_mkii
\doif{\externalfilterparameter\c!numbering}\v!yes
    {% setuplinenumbering resets \linenumber. So we save the value of linenumber and
     % revert it back.
     \syntaxhighlighting::linenumber=\linenumber

     \setuplinenumbering
       [\c!conversion=\externalfilterparameter\c!numberconversion,
            \c!start=\externalfilterparameter{\c!number\c!start},
             \c!step=\externalfilterparameter{\c!number\c!step},
            \c!method=\externalfilterparameter{\c!number\c!method},
          \c!location=\externalfilterparameter{\c!number\c!location},
             \c!style=\externalfilterparameter\c!numberstyle,
             \c!color=\externalfilterparameter\c!numbercolor,
             \c!width=\externalfilterparameter{\c!number\c!width},
              \c!left=\externalfilterparameter{\c!number\c!left},
             \c!right=\externalfilterparameter{\c!number\c!right},
           \c!command=\externalfilterparameter\c!numbercommand,
          \c!distance=\externalfilterparameter{\c!number\c!distance},
             \c!align=\externalfilterparameter{\c!number\c!align},
       ]

    \linenumber=\syntaxhighlighting::linenumber}
\stopsetups

\startmode [\s!mkiv]
\starttexdefinition syntaxhighlighting::read_command #1
   \doifelse{\externalfilterparameter\c!numbering}\v!yes
       {\startlinenumbering
          [\syntaxhighlighting::name]
          [\c!continue=\externalfilterparameter{\c!number\c!continue}]
            \ReadFile{#1}
        \stoplinenumbering}
       {\ReadFile{#1}}
\stoptexdefinition
\stopmode

\startmode [\s!mkii]
\starttexdefinition syntaxhighlighting::read_command #1
    \doifelse{\externalfilterparameter\c!numbering}\v!yes
        {\doifelse{\externalfilterparameter{\c!number\c!continue}}\v!yes
            {\startlinenumbering[\v!continue]}
            {\startlinenumbering}
            \syntaxhighlighting::read_command_aux{#1}
        \stoplinenumbering}
        {\syntaxhighlighting::read_command_aux{#1}}
\stoptexdefinition

\starttexdefinition syntaxhighlighting::read_command_aux #1
    % In the filter module, style=something does not work in MkII. 
    % So, we explicitly add the global style before reading the file.
    % 
    \dostartattributes{\syntaxhighlighting::namespace}\c!style\c!color
    \dostartattributes{\syntaxhighlighting::namespace\syntaxhighlighting::name}\c!style\c!color
      \ReadFile{#1}
    \dostopattributes
    \dostopattributes
\stoptexdefinition
\stopmode


\setupsyntaxhighlighting
  [\c!tab=4,
   \c!space=\v!off,
   \c!lines=\v!split,
   \c!start=1,
   \c!stop=0,
   % \c!syntax=context,
   \c!alternative=pscolor,
   \c!before=\blank,
   \c!after=\blank,
   \c!style=\tttf,
   \c!color=,
   \c!filtercommand=echo, % placeholder
   \c!continue=yes,
   \c!read=\v!yes,
   \c!readcommand=\syntaxhighlighting::read_command,
   \c!output=\externalfilterinputfile, % placeholder
   \c!setups=syntaxhighlighting::setup,
   \c!option=\v!packed, % Could be a list
   \s!parent=\externalfilter::namespace,
   % Numbering options
   \c!numbering=\v!no,
   \c!number\c!start=1,
   \c!number\c!step=1,
   \c!number\c!continue=\v!no,
   \c!numberconversion=\v!numbers,
   \c!number\c!method=\v!first,
   \c!number\c!location=\v!left,
   \c!numberstyle=\ttx,
   \c!numbercolor=,
   \c!number\c!width=2em,
   \c!number\c!left=,
   \c!number\c!right=,
   \c!number\c!command=,
   \c!number\c!distance=0.5em,
   \c!number\c!align=\v!flushright,
  ]

\def\currentsyntaxhighlighting  {\syntaxhighlighting::name}

% Space handler
%
% The space handing code for MkII and MkIV is not consistent. So, we provide our
% own versions.

\setvalue{\syntaxhighlighting::namespace ::\c!lines ::\v!split}{\hskip}
\setvalue {\syntaxhighlighting::namespace ::\c!lines ::\v!fixed}{\dontleavehmode\kern}

% default
\setvalue{\syntaxhighlighting::namespace ::\c!lines ::}{\hskip}

\def\syntaxhighlighting::split%
    {\getvalue{\syntaxhighlighting::namespace ::\c!lines ::\externalfilterparameter\c!lines}}

% Visible space
\installspacehandler {\syntaxhighlighting::namespace\v!on}
  {\obeyspaces
   \unexpanded\def\obeyedspace
      {\syntaxhighlighting::split\zeropoint\relax
       \hbox{\normalcontrolspace}%
       \syntaxhighlighting::split\zeropoint\relax}}%

% Invisible space
\installspacehandler {\syntaxhighlighting::namespace\v!off}
  {\obeyspaces
   \unexpanded\def\obeyedspace
      {\syntaxhighlighting::split\interwordspace\relax}}

% Default
\installspacehandler {\syntaxhighlighting::namespace}
  {\activatespacehandler {\syntaxhighlighting::namespace\v!off}}

\protectmodulecatcodes

\stopmodule

