123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208open!Core_kernelopen!ImportmoduleQ=structincludeQletadd_hook="add-hook"|>Symbol.internandafter_load_functions="after-load-functions"|>Symbol.internandafter_revert="after-revert-hook"|>Symbol.internandafter_save_hook="after-save-hook"|>Symbol.internandbefore_save_hook="before-save-hook"|>Symbol.internandkill_buffer_hook="kill-buffer-hook"|>Symbol.internandpost_command_hook="post-command-hook"|>Symbol.internandremove_hook="remove-hook"|>Symbol.internandrun_hooks="run-hooks"|>Symbol.internandstart="start"|>Symbol.internandwindow="window"|>Symbol.internandwindow_configuration_change_hook="window-configuration-change-hook"|>Symbol.internandwindow_scroll_functions="window-scroll-functions"|>Symbol.internendmoduleF=structopen!Funcallopen!Value.Typeletadd_hook=Q.add_hook<:Symbol.type_@->Symbol.type_@->bool@->bool@->returnnilandremove_hook=Q.remove_hook<:Symbol.type_@->Symbol.type_@->bool@->returnnilandrun_hooks=Q.run_hooks<:Symbol.type_@->returnnilendtypefile={file:string}[@@derivingsexp_of]typenormal=unit[@@derivingsexp_of]typewindow={window:Window.t;start:Position.t}[@@derivingsexp_of]moduleHook_type=structtype'at=|File:filet|Normal:normalt|Window:windowt[@@derivingsexp_of]endtype'at={var:Function.tlistVar.t;hook_type:'aHook_type.t}[@@derivingfields]letsymbolt=t.var.symbolletvalue_exnt=Current_buffer.value_exnt.varletsexp_of_t_t=[%message""~symbol:(symbolt:Symbol.t)~hook_type:(t.hook_type:_Hook_type.t)~value:(value_exnt:Function.tlist)];;letcreatesymbol~hook_type={var={symbol;type_=Value.Type.(listFunction.type_)};hook_type};;moduleFunction=structtype'at={symbol:Symbol.t;hook_type:'aHook_type.t}[@@derivingsexp_of]moduleReturns=structtype_t=|Returns:unitValue.Type.t->unitt|Returns_unit_deferred:unitAsync.Deferred.tt[@@derivingsexp_of]letto_defun_returns:typea.at->aDefun.Returns.t=function|Returnst->Returnst|Returns_unit_deferred->Returns_unit_deferred;;endletdefun(typeab)symbolhere?docstring~(hook_type:aHook_type.t)(returns:bReturns.t)(f:a->b)=lethandle_result=function|Ok()->()|Errorerr->Echo_area.message_s[%message"Error in hook"~_:(symbol:Symbol.t)~_:(err:Error.t)]inlettry_with(f:unit->b):b=matchreturnswith|Returns(_:unitValue.Type.t)->Or_error.try_withf|>handle_result|Returns_unit_deferred->letopenAsyncinDeferred.Or_error.try_withf~extract_exn:true>>|handle_resultinDefun.defunsymbolhere?docstring(returns|>Returns.to_defun_returns)(matchhook_typewith|Normal->letopenDefun.Let_syntaxinlet%map_open()=return()intry_withf|Window->letopenDefun.Let_syntaxinlet%map_open()=return()andwindow=requiredQ.windowWindow.type_andstart=requiredQ.startPosition.type_intry_with(fun()->f{window;start})|File->letopenDefun.Let_syntaxinlet%map_open()=return()andfile=requiredQ.fileValue.Type.stringintry_with(fun()->f{file}));;letcreatesymbolhere?docstring~hook_typereturnsf=defunsymbolhere?docstring~hook_typereturnsf;{symbol;hook_type};;letcreate_with_selfsymbolhere?docstring~hook_typereturnsf=letself={symbol;hook_type}indefunsymbolhere?docstring~hook_typereturns(fself);self;;letsymbolt=t.symbolendmoduleWhere=structtypet=|End|Start[@@derivingsexp_of]endletadd?(buffer_local=false)?(where=Where.Start)tfunction_=F.add_hook(t|>symbol)(Function.symbolfunction_)(matchwherewith|End->true|Start->false)buffer_local;;letremove?(buffer_local=false)tfunction_=F.remove_hook(t|>symbol)(Function.symbolfunction_)buffer_local;;letcleart=Current_buffer.set_valuet.var[]letrunt=F.run_hooks(t|>symbol)letafter_load=createQ.after_load_functions~hook_type:Fileletafter_revert=createQ.after_revert~hook_type:Normalletafter_save=createQ.after_save_hook~hook_type:Normalletbefore_save=createQ.before_save_hook~hook_type:Normalletkill_buffer=createQ.kill_buffer_hook~hook_type:Normalletafter_load_once=letcounter=ref0infunf->incrcounter;lethook_function_ref=refNoneinlethook_function=Function.create(Symbol.intern(concat["ecaml-after-load-";!counter|>Int.to_string]))[%here]~hook_type:File(ReturnsValue.Type.unit)(funfile->removeafter_load(Option.value_exn!hook_function_ref);ffile)inhook_function_ref:=Somehook_function;addafter_loadhook_function;;letwindow_configuration_change=createQ.window_configuration_change_hook~hook_type:Normal;;letwindow_scroll_functions=createQ.window_scroll_functions~hook_type:Windowletpost_command=createQ.post_command_hook~hook_type:Normalletmajor_mode_hookmajor_mode=letmode_name=major_mode|>Major_mode.symbol|>Symbol.nameincreate(mode_name^"-hook"|>Symbol.intern)~hook_type:Normal;;