%%%------------------------------------------------------------------- %% @doc Entry point invoked by Openbox as the pipe menu command. %% %% Tries the running daemon's Unix socket first for an instant, %% pre-rendered response; if the daemon isn't reachable, falls back to %% scanning, parsing and rendering inline so the menu still works. %% @end %%%------------------------------------------------------------------- -module(xdg_pipe_menu_cli). -export([main/1]). -define(CONNECT_TIMEOUT_MS, 200). -define(RECV_TIMEOUT_MS, 1000). main(_Args) -> Menu = case from_daemon() of {ok, Bin} -> Bin; error -> xdg_pipe_menu_cache:build(xdg_pipe_menu_scanner:data_dirs()) end, io:put_chars(Menu). from_daemon() -> Path = xdg_pipe_menu_socket:socket_path(), case gen_tcp:connect({local, Path}, 0, [binary, {active, false}], ?CONNECT_TIMEOUT_MS) of {ok, Socket} -> Result = recv_all(Socket, []), gen_tcp:close(Socket), Result; {error, _Reason} -> error end. recv_all(Socket, Acc) -> case gen_tcp:recv(Socket, 0, ?RECV_TIMEOUT_MS) of {ok, Data} -> recv_all(Socket, [Data | Acc]); {error, closed} -> {ok, iolist_to_binary(lists:reverse(Acc))}; {error, _Reason} -> error end.