Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file highlight_nw.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311(* Yoann Padioleau
*
* Copyright (C) 2010 Facebook
* Copyright (C) 2015, 2018 Yoann Padioleau
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation, with the
* special exception on linking described in file license.txt.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file
* license.txt for more details.
*)openCommonmoduleT=Lexer_nwmoduleTH=Token_helpers_nwmoduleF=Ast_fuzzyopenHighlight_code(*****************************************************************************)(* Prelude *)(*****************************************************************************)(*****************************************************************************)(* Helpers *)(*****************************************************************************)letspan_newlinexs=xs+>Common2.split_when(function|T.TCommentNewline_->true|_->false)lettag_all_tok_with~tagcategxs=xs|>List.iter(funtok->letinfo=TH.info_of_toktokintaginfocateg)lettag_all_tok_trees_with~tagcategtrees=letxs=F.toks_of_treestreesinxs|>List.iter(funinfo->taginfocateg)(*****************************************************************************)(* Code highlighter *)(*****************************************************************************)(* The idea of the code below is to visit the program either through its
* AST or its list of tokens. The tokens are easier for tagging keywords,
* number and basic entities. The AST is better for other things.
*)letvisit_program~tag_hook_prefs(trees,toks)=letalready_tagged=Hashtbl.create101inlettag=(funiicateg->tag_hookiicateg;Hashtbl.replacealready_taggediitrue)in(* -------------------------------------------------------------------- *)(* toks phase 1 (sequence of tokens) *)(* -------------------------------------------------------------------- *)letrecaux_toksxs=matchxswith|[]->()(* pad-specific: *)|T.TComment(ii)::T.TCommentNewline(_ii2)::T.TComment(ii3)::T.TCommentNewline(_ii4)::T.TComment(ii5)::xs->lets=Parse_info.str_of_infoiiinlets5=Parse_info.str_of_infoii5in(match()with|_whens=~"^%\\*\\*\\*\\*"&&s5=~"^%\\*\\*\\*\\*"->tagiiCommentEstet;tagii5CommentEstet;tagii3CommentSection0|_whens=~"^%------"&&s5=~"^%------"->tagiiCommentEstet;tagii5CommentEstet;tagii3CommentSection1|_whens=~"^%####"&&s5=~"^%####"->tagiiCommentEstet;tagii5CommentEstet;tagii3CommentSection2|_->());aux_toksxs(* syncweb-specific: *)|T.TSymbol("#",_ii)::T.TWord("include",ii2)::xs->tagii2Include;aux_toksxs(* specific to texinfo *)|T.TSymbol("@",_)::T.TWord(s,ii)::xs->letcateg_opt=(matchswith|"title"->SomeCommentSection0|"chapter"->SomeCommentSection0|"section"->SomeCommentSection1|"subsection"->SomeCommentSection2|"subsubsection"->SomeCommentSection3|"c"->SomeComment(* don't want to polluate my view with indexing "aspect" *)|"cindex"->tagiiComment;SomeComment|_->None)in(matchcateg_optwith|None->tagiiKeyword;aux_toksxs|Somecateg->let(before,_,_)=span_newlinexsintag_all_tok_with~tagcategbefore;(* repass on tokens, in case there are nested tex commands *)aux_toksxs)(* specific to web TeX source: ex: @* \[24] Getting the next token. *)|T.TSymbol("@*",_)::T.TCommentSpace_::T.TSymbol("\\",_)::T.TSymbol("[",ii1)::T.TNumber(_,iinum)::T.TSymbol("]",ii2)::T.TCommentSpace_::xs->let(before,_,_)=span_newlinexsin[ii1;iinum;ii2]|>List.iter(funii->tagiiCommentSection0);tag_all_tok_with~tagCommentSection0before;(* repass on tokens, in case there are nested tex commands *)aux_toksxs(* less: \item TWord => purple? or maybe purple until end of line *)|_x::xs->aux_toksxsinlettoks'=toks|>Common.exclude(function(* needed ? *)(* | T.TCommentSpace _ -> true *)|_->false)inaux_tokstoks';(* -------------------------------------------------------------------- *)(* AST phase 1 *)(* -------------------------------------------------------------------- *)trees|>F.mk_visitor{F.default_visitorwithF.ktrees=(fun(k,_v)trees->matchtreeswith(* \xxx{...} *)|F.Tok(s,_)::F.Braces(_,brace_trees,_)::_->letcateg_opt=matchswith|("\\chapter"|"\\chapter*")->SomeCommentSection0|"\\section"->SomeCommentSection1|"\\subsection"->SomeCommentSection2|"\\subsubsection"->SomeCommentSection3|"\\label"->Some(LabelDef)|"\\ref"->Some(LabelDef)|"\\cite"->Some(LabelDef)(* principia-specific: *)|"\\book"->Some(LabelDef)|"\\begin"|"\\end"->SomeKeywordExn(* TODO *)|"\\input"|"\\usepackage"|"\\bibliography"->SomeIncludeFilePath|"\\url"|"\\furl"->SomeEmbededUrl|_whens=~"^\\"->Some(ParameterUse)|_->Noneincateg_opt|>Common.do_option(funcateg->tag_all_tok_trees_with~tagcategbrace_trees;);ktrees(* \xxx[...]{...} *)|F.Tok(s,_)::F.Bracket(_,params,_)::F.Braces(_,body,_)::_->ifs=~"^\\"thenbegintag_all_tok_trees_with~tag(ParameterUse)params;tag_all_tok_trees_with~tag(ParameterUse)body;end;ktrees(* {...}{...} *)|F.Braces(_,brace_trees1,_)::F.Braces(_,brace_trees2,_)::_->tag_all_tok_trees_with~tag(ParameterUse)brace_trees1;tag_all_tok_trees_with~tag(ParameterUse)brace_trees2;ktrees(* {\xxx ... } *)|F.Braces(_,(F.Tok(s,_)::brace_trees),_)::_->letcateg_opt=matchswith|"\\em"->SomeCommentWordImportantNotion|_->Noneincateg_opt|>Common.do_option(funcateg->tag_all_tok_trees_with~tagcategbrace_trees;);ktrees|_->ktrees);};(* -------------------------------------------------------------------- *)(* toks phase 2 (individual tokens) *)(* -------------------------------------------------------------------- *)toks|>List.iter(funtok->matchtokwith|T.TCommentii->ifnot(Hashtbl.memalready_taggedii)thenlets=Parse_info.str_of_infoii|>String.lowercase_asciiin(matchswith|_whens=~"^%todo:"->tagiiBadSmell|_->tagiiCommentImportance0)|T.TCommentSpace_ii->()|T.TCommentNewline_ii->()|T.TCommand(s,ii)->letcateg=(matchswith|swhens=~"^if"->KeywordConditional|swhens=~".*true$"->Boolean|swhens=~".*false$"->Boolean|"fi"->KeywordConditional|"input"|"usepackage"->Include|"appendix"->CommentSection0|_->Keyword)intagiicateg|T.TWord(s,ii)->(matchswith|"TODO"->tagiiBadSmell|_->())(* noweb-specific: (obviously) *)|T.TBeginNowebChunkii|T.TEndNowebChunkii->tagiiKeywordExn(* TODO *)|T.TNowebChunkStr(_,ii)->tagiiEmbededCode|T.TNowebCode(_,ii)->tagiiEmbededCode|T.TNowebCodeLink(_,ii)->tagii(LabelDef)(* TODO *)|T.TNowebChunkName(_,ii)->tagiiKeywordObject(* TODO *)|T.TBeginVerbatimii|T.TEndVerbatimii->tagiiKeyword|T.TVerbatimLine(_,ii)->tagiiVerbatim(* syncweb-specific: *)|T.TFootnote(c,ii)->(matchcwith|'t'->tagiiBadSmell|'n'->tagiiComment|'l'->tagiiCommentImportance1|_->failwith(spf"syncweb \\x special macro not recognized:%c"c))|T.TNumber(_,ii)|T.TUnit(_,ii)->ifnot(Hashtbl.memalready_taggedii)thentagiiNumber|T.TSymbol(s,ii)->(matchswith|"&"|"\\\\"->tagiiPunctuation|_->())|T.TOBraceii|T.TCBraceii|T.TOBracketii|T.TCBracketii->tagiiPunctuation|T.TUnknownii->tagiiError|T.EOF_ii->());(* -------------------------------------------------------------------- *)(* AST phase 2 *)()