-module(ghtml@watcher). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/ghtml/watcher.gleam"). -export([get_mtime/1, get_all_mtimes/1, process_single_file/1, start_watching/1]). -export_type([watcher_message/0, watcher_state/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC(false). -type watcher_message() :: {init, gleam@erlang@process:subject(watcher_message())} | check | stop. -type watcher_state() :: {watcher_state, binary(), gleam@dict:dict(binary(), integer()), gleam@option:option(gleam@erlang@process:subject(watcher_message()))}. -file("src/ghtml/watcher.gleam", 53). ?DOC(false). -spec get_mtime(binary()) -> {ok, integer()} | {error, nil}. get_mtime(Path) -> case simplifile_erl:file_info(Path) of {ok, Info} -> {ok, erlang:element(10, Info)}; {error, _} -> {error, nil} end. -file("src/ghtml/watcher.gleam", 61). ?DOC(false). -spec get_all_mtimes(binary()) -> gleam@dict:dict(binary(), integer()). get_all_mtimes(Root) -> _pipe = ghtml@scanner:find_ghtml_files(Root), _pipe@1 = gleam@list:filter_map(_pipe, fun(Path) -> case get_mtime(Path) of {ok, Mtime} -> {ok, {Path, Mtime}}; {error, _} -> {error, nil} end end), maps:from_list(_pipe@1). -file("src/ghtml/watcher.gleam", 117). ?DOC(false). -spec schedule_check(gleam@erlang@process:subject(watcher_message())) -> nil. schedule_check(Subject) -> gleam@erlang@process:send_after(Subject, 500, check), nil. -file("src/ghtml/watcher.gleam", 180). ?DOC(false). -spec process_single_file(binary()) -> nil. process_single_file(Source_path) -> Output_path = ghtml@scanner:to_output_path(Source_path), case simplifile:read(Source_path) of {ok, Content} -> Hash = ghtml@cache:hash_content(Content), case ghtml@parser:parse(Content) of {ok, Template} -> Gleam_code = ghtml@codegen:generate( Template, Source_path, Hash ), case simplifile:write(Output_path, Gleam_code) of {ok, _} -> gleam_stdlib:println( <<" Generated: "/utf8, Output_path/binary>> ); {error, E} -> gleam_stdlib:println( <<" Error writing: "/utf8, (gleam@string:inspect(E))/binary>> ) end; {error, Errors} -> gleam_stdlib:println(<<" Parse errors:"/utf8>>), gleam@list:each( Errors, fun(E@1) -> gleam_stdlib:println( <<<<<<" Line "/utf8, (erlang:integer_to_binary( erlang:element( 2, erlang:element( 2, erlang:element(2, E@1) ) ) ))/binary>>/binary, ": "/utf8>>/binary, (erlang:element(3, E@1))/binary>> ) end ) end; {error, E@2} -> gleam_stdlib:println( <<" Error reading: "/utf8, (gleam@string:inspect(E@2))/binary>> ) end. -file("src/ghtml/watcher.gleam", 124). ?DOC(false). -spec check_for_changes(watcher_state()) -> watcher_state(). check_for_changes(State) -> Current_files = ghtml@scanner:find_ghtml_files(erlang:element(2, State)), Current_mtimes = get_all_mtimes(erlang:element(2, State)), gleam@list:each( Current_files, fun(Path) -> Should_process = case gleam_stdlib:map_get( erlang:element(3, State), Path ) of {error, _} -> gleam_stdlib:println(<<"New file: "/utf8, Path/binary>>), true; {ok, Old_mtime} -> case gleam_stdlib:map_get(Current_mtimes, Path) of {ok, New_mtime} when New_mtime =/= Old_mtime -> gleam_stdlib:println( <<"Modified: "/utf8, Path/binary>> ), true; _ -> false end end, case Should_process of true -> process_single_file(Path); false -> nil end end ), _pipe = maps:keys(erlang:element(3, State)), gleam@list:each( _pipe, fun(Old_path) -> case gleam@list:contains(Current_files, Old_path) of false -> gleam_stdlib:println(<<"Deleted: "/utf8, Old_path/binary>>), Gleam_path = ghtml@scanner:to_output_path(Old_path), case simplifile_erl:delete(Gleam_path) of {ok, _} -> gleam_stdlib:println( <<" Removed: "/utf8, Gleam_path/binary>> ); {error, _} -> nil end; true -> nil end end ), case erlang:element(4, State) of {some, Subject} -> schedule_check(Subject); none -> nil end, {watcher_state, erlang:element(2, State), Current_mtimes, erlang:element(4, State)}. -file("src/ghtml/watcher.gleam", 97). ?DOC(false). -spec handle_message(watcher_state(), watcher_message()) -> gleam@otp@actor:next(watcher_state(), watcher_message()). handle_message(State, Message) -> case Message of stop -> gleam@otp@actor:stop(); {init, Subject} -> New_state = {watcher_state, erlang:element(2, State), erlang:element(3, State), {some, Subject}}, schedule_check(Subject), gleam@otp@actor:continue(New_state); check -> New_state@1 = check_for_changes(State), gleam@otp@actor:continue(New_state@1) end. -file("src/ghtml/watcher.gleam", 74). ?DOC(false). -spec start_watching(binary()) -> gleam@erlang@process:subject(watcher_message()). start_watching(Root) -> Initial_mtimes = get_all_mtimes(Root), Initial_state = {watcher_state, Root, Initial_mtimes, none}, Started@1 = case begin _pipe = gleam@otp@actor:new(Initial_state), _pipe@1 = gleam@otp@actor:on_message(_pipe, fun handle_message/2), gleam@otp@actor:start(_pipe@1) end of {ok, Started} -> Started; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"ghtml/watcher"/utf8>>, function => <<"start_watching"/utf8>>, line => 79, value => _assert_fail, start => 2214, 'end' => 2326, pattern_start => 2225, pattern_end => 2236}) end, Actor_subject = erlang:element(3, Started@1), gleam@erlang@process:send(Actor_subject, {init, Actor_subject}), gleam_stdlib:println(<<"Watching for changes... (Ctrl+C to stop)"/utf8>>), gleam_stdlib:println(<<""/utf8>>), Actor_subject.