%D \module
%D   [     file=t-vim,
%D      version=2011.03.06,
%D        title=\CONTEXT\ User Module,
%D     subtitle=Vim 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 / Vim syntax highlighting}

\startmodule[vim]
\usemodule[filter]

% I use the experimental namespaces defined in t-filter.
\pushcatcodetable
\setcatcodetable\externalfiltermodulecatcodes

% Colors are specified in hex; in MkII the hex mode needs to be activated. 
\doifmode\s!mkii
    {\setupcolor[hex]}

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

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

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

\installparameterhandler \vimtyping::namespace \vimtyping::id
\installsetuphandler     \vimtyping::namespace \vimtyping::id

    

\def\definevimtyping
  {\dodoubleargument\vimtyping::define}

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

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

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

\stoptexdefinition

\startsetups vimtyping::setup

  \edef\vimtyping::name{\currentexternalfilter}
  \edef\vimalternative::name{\externalfilterparameter\c!alternative}
  
  \let\SYN\vimsyntax
  \def\NL{\strut}% 

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

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

 \setuplinenumbering
   [\vimtyping::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\vimtyping::linenumber}

\startsetups vimtyping::setup_line_number_mkii
\doif{\externalfilterparameter\c!numbering}\v!yes
    {% setuplinenumbering resets \linenumber. So we save the value of linenumber and
     % revert it back.
     \vimtyping::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=\vimtyping::linenumber}
\stopsetups

\doifmodeelse{vimtest}
  {\def\vimtyping::script_name{2context.vim}}
  {\def\vimtyping::script_name{kpse:2context.vim}}

\def\vimtyping::filter_command
  {vim -u NONE % don't read global config file
       -e % run in ex mode
       -s % silent
       -C % set compatible
       -n % no swap file
       -c "set tabstop=\externalfilterparameter\c!tab" %
       -c "syntax on" %
       -c "set syntax=\externalfilterparameter\c!syntax" %
       -c "let contextstartline=\externalfilterparameter\c!start" %
       -c "let  contextstopline=\externalfilterparameter\c!stop" %
       -c "source \vimtyping::script_name" %
       -c "qa" %
       \externalfilterinputfile\space
       \externalfilteroutputfile}

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

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

\def\startvimalternative
    {\dosingleargument\vimalternative::start}

\def\vimalternative::start[#1]%
    {\pushmacro\vimalternative::name
     \edef\vimalternative::name{#1}}

\def\stopvimalternative
    {\popmacro\vimalternative::name}

\def\setvimsyntax
    {\doquadrupleargument\vimalternative::set_syntax}

\starttexdefinition vimalternative::set_syntax [#1][#2][#3][#4]
    % #1 = name
    % #2 = color
    % #3 = style
    % #4 = command
    \def\dodosetupvimsyntax##1%
        {\doifsomething{#2}
         % we check if color exists; otherwise ConTeXt gives a warning on stdout
         % which is very distracting
              {\definecolor[\vimalternative::namespace\vimalternative::name##1color_name] [#2]
               \getparameters[\vimalternative::namespace\vimalternative::name##1]
                             [\c!color={\vimalternative::namespace\vimalternative::name##1color_name}]}
        \getparameters[\vimalternative::namespace\vimalternative::name##1]
                      [\c!style=#3,
                       \c!command=#4]}
    \processcommalist[#1]\dodosetupvimsyntax
\stoptexdefinition


\starttexdefinition vimsyntax [#1]#2
    % #1 = style 
    % #2 = content
    \dostartattributes{\vimalternative::namespace\vimalternative::name Normal}\c!style\c!color\empty
        \dostartattributes{\vimalternative::namespace\vimalternative::name #1}\c!style\c!color\empty
            \getvalue{\vimalternative::namespace\vimalternative::name#1\c!command}{#2}
        \dostopattributes
    \dostopattributes
\stoptexdefinition

% \startvimalternative[pscolor]
% 
%   \definesyntax 
%     [Normal]
%     [color=\externalfilterparameter\c!color,
%      style=\tttf,
%      command=]
% 
% \stopvimalternative

\startvimalternative[pscolor]
  \setvimsyntax [Normal]    [\externalfilterparameter\c!color][\tttf]

  \setvimsyntax 
    [Constant,Character,Boolean,Float]  
    [h=007068]      

  \setvimsyntax [Number]    [h=907000]

  \setvimsyntax
    [Identifier, Function]
    [h=a030a0]      

  \setvimsyntax 
    [Statement,Conditional,Repeat,Label,Operator,Keyword,Exception] 
    [h=2060a8]      

  \setvimsyntax 
    [PreProc, Include, Define, Macro, PreCondit] 
    [h=009030]

  \setvimsyntax 
    [Type,StorageClass, Structure, Typedef]      
    [h=0850a0]      

  \setvimsyntax [Special]   [h=907000]
  \setvimsyntax [SpecialKey][h=1050a0]

  \setvimsyntax
    [Tag, Delmiter]

  \setvimsyntax 
    [Comment, SpecialComment]
    [h=606000]

  \setvimsyntax
    [Debug,Ignore]

  \setvimsyntax [Todo]      [h=e0e090]
  \setvimsyntax [Error]     [h=c03000]
  \setvimsyntax [Underlined][h=6a5acd][][\underbar]

\stopvimalternative

%TODO
%   \setvimsyntax [id] [bg=, fc=, style=, command=] == \localframed[options]
\startvimalternative[blackandwhite]
  \setvimsyntax [Normal]    [\externalfilterparameter\c!color][\tttf]

  \setvimsyntax 
    [Constant,Character,Boolean,Float,Number,Identifier,Function]  

  \setvimsyntax 
    [Statement,Conditional,Repeat,Label,Operator,Keyword,Exception] 
    [][][\bold]

  \setvimsyntax 
    [PreProc, Include, Define, Macro, PreCondit] 
    [][][\bold]

  \setvimsyntax 
    [Type,StorageClass, Structure, Typedef]      
    [][][\bold]

  \setvimsyntax [Special, SpecialKey]

  \setvimsyntax [Tag, Delmiter]

  \setvimsyntax 
    [Comment, SpecialComment]
    [][][\italic]

  \setvimsyntax
    [Debug,Ignore]

  \setvimsyntax [Todo]      [][][\inframed]
  \setvimsyntax [Error]     [][][\overstrike]
  \setvimsyntax [Underlined][][][\underbar]

\stopvimalternative

\setupvimtyping
  [\c!tab=4,
   \c!start=1,
   \c!stop=0,
   \c!syntax=context,
   \c!alternative=pscolor,
   \c!before=,
   \c!after=,
   \c!filtercommand=\vimtyping::filter_command,
   \c!continue=yes,
   \c!read=\v!yes,
   \c!readcommand=\vimtyping::read_command,
   \c!output=\externalfilterbasefile.vimout,
   \c!setups=vimtyping::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=\tfx,
   \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\currentvimtyping  {\vimtyping::name}

\popcatcodetable

\stopmodule

