1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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.
|