diff options
Diffstat (limited to 'src/xdg_pipe_menu_cache.erl')
| -rw-r--r-- | src/xdg_pipe_menu_cache.erl | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/src/xdg_pipe_menu_cache.erl b/src/xdg_pipe_menu_cache.erl new file mode 100644 index 0000000..0e10fea --- /dev/null +++ b/src/xdg_pipe_menu_cache.erl @@ -0,0 +1,56 @@ +%%%------------------------------------------------------------------- +%% @doc Caches the rendered Openbox pipe menu in memory. +%% +%% Holds the last-rendered menu binary so socket clients get an +%% instant response. `invalidate/0' synchronously rescans the XDG +%% application directories, reparses every `.desktop' file and +%% re-renders the menu, replacing the cached binary. +%% @end +%%%------------------------------------------------------------------- + +-module(xdg_pipe_menu_cache). + +-behaviour(gen_server). + +-export([start_link/0, get_menu/0, invalidate/0, build/1]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2]). + +-spec start_link() -> {ok, pid()}. +start_link() -> + gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). + +-spec get_menu() -> binary(). +get_menu() -> + gen_server:call(?MODULE, get_menu). + +-spec invalidate() -> ok. +invalidate() -> + gen_server:cast(?MODULE, invalidate). + +%% Pure pipeline: explicit dirs in, rendered menu binary out. Kept +%% side-effect-free (besides reading the filesystem) and exported so +%% it can be unit tested directly and reused by the CLI client's +%% no-daemon fallback, without going through the gen_server at all. +-spec build([file:filename_all()]) -> binary(). +build(Dirs) -> + Files = xdg_pipe_menu_scanner:find_desktop_files(Dirs), + Entries = lists:filtermap(fun parse/1, Files), + xdg_pipe_menu_renderer:render(Entries). + +parse(File) -> + case xdg_pipe_menu_desktop_entry:parse_file(File) of + {ok, Entry} -> {true, Entry}; + {error, _} -> false + end. + +init([]) -> + {ok, build(xdg_pipe_menu_scanner:data_dirs())}. + +handle_call(get_menu, _From, Menu) -> + {reply, Menu, Menu}. + +handle_cast(invalidate, _Menu) -> + {noreply, build(xdg_pipe_menu_scanner:data_dirs())}. + +handle_info(_Info, State) -> + {noreply, State}. |
