aboutsummaryrefslogtreecommitdiff
path: root/src/xdg_pipe_menu_cli.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/xdg_pipe_menu_cli.erl')
-rw-r--r--src/xdg_pipe_menu_cli.erl41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/xdg_pipe_menu_cli.erl b/src/xdg_pipe_menu_cli.erl
new file mode 100644
index 0000000..aa2f98a
--- /dev/null
+++ b/src/xdg_pipe_menu_cli.erl
@@ -0,0 +1,41 @@
+%%%-------------------------------------------------------------------
+%% @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.