123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342(*********************************************************************************)(* Stog *)(* *)(* Copyright (C) 2012-2015 INRIA All rights reserved. *)(* Author: Maxence Guesdon, INRIA Saclay *)(* *)(* This program is free software; you can redistribute it and/or modify *)(* it under the terms of the GNU General Public License as *)(* published by the Free Software Foundation, version 3 of the License. *)(* *)(* This program 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 *)(* GNU General Public License for more details. *)(* *)(* You should have received a copy of the GNU General Public *)(* License along with this program; if not, write to the Free Software *)(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)(* 02111-1307 USA *)(* *)(* As a special exception, you have permission to link this program *)(* with the OCaml compiler and distribute executables, as long as you *)(* follow the requirements of the GNU GPL in regard to all of the *)(* software in the executable aside from the OCaml compiler. *)(* *)(* Contact: Maxence.Guesdon@inria.fr *)(* *)(*********************************************************************************)openStog.Types;;letoutput_dir=ref"stog-output";;letsite_url=refNone;;lettmpl_dirs=ref[];;letmod_dirs=ref[];;letuse_cache=reftrue;;letdepcut=reffalse;;letlocal=reffalse;;letstog_defs=ref[];;letlang=refNone;;letdefault_lang_to_set=refNone;;letplugins=ref[];;letpackages=ref[];;letonly_doc=refNone;;letpublish_only=refNone;;typemode=Generate|Serverletmode=refGenerateletadd_stog_defs=matchStog_base.Misc.split_strings[':']with[]->()|[name]->stog_defs:=!stog_defs@[(("",name),Xtmpl.Rewrite.atts_empty,[])]|name::q->letcontents=Xtmpl.Rewrite.from_string(String.concat":"q)instog_defs:=!stog_defs@[(("",name),Xtmpl.Rewrite.atts_empty,contents)]letset_stog_optionsstog=letstog={stogwithStog.Types.stog_outdir=!output_dir}inletstog=match!site_url,!localwithNone,false->stog|None,true->letd=ifFilename.is_relativestog.stog_outdirthenFilename.concat(Sys.getcwd())stog.stog_outdirelsestog.stog_outdirinleturl="file://"^dinleturl=Stog.Url.of_stringurlin{stogwithStog.Types.stog_base_url=url}|Somes,false->{stogwithStog.Types.stog_base_url=s}|Some_,true->failwith"Please choose --local or --site-url but not both"inletstog={stogwithstog_tmpl_dirs=List.rev(stog.stog_tmpl_dirs@!tmpl_dirs)}inletstog={stogwithstog_mod_dirs=List.rev(stog.stog_mod_dirs@!mod_dirs)}inletstog=match!langwithNone->stog|Somes->{stogwithStog.Types.stog_lang=Somes}inletstog={stogwithStog.Types.stog_depcut=!depcut}inletstog={stogwithStog.Types.stog_defs=stog.stog_defs@!stog_defs}inletstog=match!publish_onlywithNone->stog|_->{stogwithstog_publish_only=!publish_only;}in(* add default template directory if there is at least one
other template directory, so that the default one is
not polluted by template files automatically created when missing. *)letstog=matchstog.stog_tmpl_dirswith[]->stog|dirs->{stogwithstog_tmpl_dirs=dirs@[List.hdStog.Install.Sites.templates]}instog;;letrun_from_dirsdirs=tryletstog=Stog.Init.from_dirs~set_fields:set_stog_optionsdirsinletmodules=Stog.Init.init_modulesstoginletonly_docs=match!only_docwithNone->None|Somes->Some[s]inmatch!Stog.Server_mode.server_modewithNone->Stog.Engine.generate~use_cache:!use_cache?only_docsstogmodules|Some(`Singlef)->letread_stog()=Stog.Init.from_dirs~set_fields:set_stog_optionsdirsinfread_stogstog|_->assertfalsewithStog.Types.Path_trie.Already_presentl->letmsg="Path already present: "^(String.concat"/"l)infailwithmsg;;letrun_from_filesfiles=tryletstog=Stog.Init.from_files~set_fields:set_stog_optionsfilesinletmodules=Stog.Init.init_modulesstoginmatch!Stog.Server_mode.server_modewithNone->Stog.Engine.generate~use_cache:false~gen_cache:falsestogmodules|Some(`Singlef)->letread_stog()=Stog.Init.from_files~set_fields:set_stog_optionsfilesinfread_stogstog|_->assertfalsewithStog.Types.Path_trie.Already_presentl->letmsg="Path already present: "^(String.concat"/"l)infailwithmsg;;letoptions=["-version",Arg.Unit(fun()->print_endline(Printf.sprintf"%s"(Stog.Version.number()));exit0)," print version and exit";"-D",Arg.SetStog.Config.debug," debug mode";"--verbose-level",Arg.StringStog.Log.set_level_of_string,(Printf.sprintf"<%s> set verbose level"(String.concat"|"(List.mapLogs.level_to_stringLogs.([None;SomeApp;SomeError;SomeWarning;SomeInfo;SomeDebug]))));"-d",Arg.Set_stringoutput_dir,"<dir> set output directory instead of "^!output_dir;"--site-url",Arg.String(funs->site_url:=Some(Stog.Url.of_strings)),"<s> use <s> as site url instead of the one specified in the input stog";"--local",Arg.Setlocal," set site-url as file://<destination directory>";"--tmpl",Arg.String(funs->tmpl_dirs:=s::!tmpl_dirs),"<dir> add <dir> as template directory";"--mods",Arg.String(funs->mod_dirs:=s::!mod_dirs),"<dir> add <dir> as module directory";"--lang",Arg.String(funs->lang:=Somes),"<s> generate pages for language <s>";"--default-lang",Arg.String(funs->default_lang_to_set:=Somes),"<lang> use <lang> as default language (dates, ...); default is \"en\"";"--plugin",Arg.String(funs->plugins:=!plugins@[s]),"<file> load plugin (ocaml object file)";"--package",Arg.String(funs->packages:=!packages@[s]),"<pkg[,pkg2[,...]]> load package (a plugin loaded with ocamlfind)";"--only",Arg.String(funs->use_cache:=false;only_doc:=Somes),"<doc-id> generate only the page for the given document; imply --nocache";"--nocache",Arg.Clearuse_cache," do not use cache to prevent computing unmodified documents";"--depcut",Arg.Setdepcut," use only 1 level of dependency when getting cached documents";"--stog-ocaml-session",Arg.Set_stringStog.Ocaml.stog_ocaml_session,"<command> use <command> as stog-ocaml-session program";"--def",Arg.Stringadd_stog_def,"name:contents add a global rule name with the given contents";"--publish-only",Arg.String(funs->publish_only:=Some(Stog.Filter.filter_of_strings)),"<filter> only keep documents verifying the given condition";"--hackcmxs",Arg.SetStog.Dyn.hack_cmxs," when a package to load depends on .cmxa or .cmx file, try to build .cmxs.\n\n *** Server options ***";"--http",Arg.Set_stringStog.Server_mode.http_url,"<url> set url of server, used to know port and host to listen on\n\t\t"^"(default is "^(!Stog.Server_mode.http_url)^")";"--ws",Arg.Set_stringStog.Server_mode.ws_url,"<url> set websocket url of server, used to know port and host to listen on\n\t\t"^"(default is "^(!Stog.Server_mode.ws_url)^")";"--pub-http",Arg.String(funs->Stog.Server_mode.pub_http_url:=Somes),"<url> set public url of server (default is same as --http)";"--pub-ws",Arg.String(funs->Stog.Server_mode.pub_ws_url:=Somes),"<url> set public url of websocket server (default is same as --ws)";];;letusage?(with_options=true)()=Printf.sprintf"Usage: %s [options] <directory>\n or %s [options] <files>%s"Sys.argv.(0)Sys.argv.(0)(ifwith_optionsthen"\nwhere options are:"else"");;letfile_kindfile=try(Unix.statfile).Unix.st_kindwithUnix.Unix_error(e,s1,s2)->failwith(Printf.sprintf"%s: %s %s"(Unix.error_messagee)s1s2);;letpp_header~pp_hppf(l,h)=matchlwith|Logs.App->beginmatchhwith|None->()|Someh->Fmt.pfppf"[%a] "Fmt.(styledLogs_fmt.app_stylestring)hend|Logs.Error->pp_hppfLogs_fmt.err_style(matchhwithNone->"ERROR"|Someh->h)|Logs.Warning->pp_hppfLogs_fmt.warn_style(matchhwithNone->"WARNING"|Someh->h)|Logs.Info->pp_hppfLogs_fmt.info_style(matchhwithNone->"INFO"|Someh->h)|Logs.Debug->pp_hppfLogs_fmt.debug_style(matchhwithNone->"DEBUG"|Someh->h)letpp_header=letpp_hppfstyleh=Fmt.pfppf"[%a]"Fmt.(styledstylestring)hinpp_header~pp_hletreporterppf=letreportsrclevel~overkmsgf=letk_=over();k()inletwith_lochtagskppffmt=letloc=matchtagswith|None->None|Sometags->Logs.Tag.findStog.Log.loc_tagtagsinletloc=matchlocwith|None->""|Somel->Printf.sprintf"%s:"(Xtmpl.Xml.string_of_locl)inifloc=""thenFormat.kfprintfkppf("%a@["^^fmt^^"@]@.")pp_header(level,h)elseFormat.kfprintfkppf("%a%s@.@["^^fmt^^"@]@.")pp_header(level,h)locinmsgf@@fun?header?tagsfmt->with_locheadertagskppffmtin{Logs.report=report}letmain()=Logs.set_level(SomeLogs.Warning);letremain=ref[]intryArg.parse(Arg.alignoptions)(funs->remain:=s::!remain)(usage());Fmt_tty.setup_std_outputs();Logs.set_reporter(reporter(Format.std_formatter));Stog.Dyn.load_packages!packages;Stog.Dyn.check_files_have_extension!plugins;Stog.Dyn.load_files!plugins;beginmatch!default_lang_to_setwithNone->()|Someabbrev->Stog.Intl.set_default_langabbrevend;match!Stog.Server_mode.server_modewithSome(`Multif)->f(List.rev!remain)|_->beginmatchList.rev!remainwith[]->failwith(usage~with_options:false())|h::q->letk=file_kindhinList.iter(funf->iffile_kindf<>kthenfailwith(usage~with_options:false()))q;matchkwithUnix.S_REG->run_from_files(h::q)|Unix.S_DIR->run_from_dirs(h::q)|_->failwith("Invalid file type for "^h)end;leterr=Logs.err_count()inletwarn=Logs.warn_count()inbeginmatcherr,warnwith0,0->()|_,_->letmsg=Printf.sprintf"%d error%s, %d warning%s"err(iferr>1then"s"else"")warn(ifwarn>1then"s"else"")inprerr_endlinemsg;end;exiterrwithewhen!Stog.Config.debug->raisee|Stog.Engine.Cant_open_cache_filecache_file->Stog.Log.err~fatal:1(funm->m"Could open cache file %S@. You should run stog once with --nocache"cache_file)|Xtmpl.Rewrite.Errore->Stog.Log.err~fatal:1(funm->m"%s"(Xtmpl.Rewrite.string_of_errore))|Stog.Error.Errore->Stog.Log.err~fatal:1(funm->m"%s"(Stog.Error.string_of_errore))|Failures|Sys_errors->Stog.Log.err~fatal:1(funm->m"%s"s)|e->Stog.Log.err~fatal:1(funm->m"%s"(Printexc.to_stringe));;let()=main()