Add desktop integration interface function; implement Linux version

This commit is contained in:
Craig Everett 2020-01-11 22:06:11 +09:00
parent 894edbe39e
commit 6c1ff3562b
49 changed files with 150 additions and 30 deletions

View File

@ -1 +1 @@
0.8.0 0.9.0

View File

@ -1,6 +1,6 @@
{application,zx, {application,zx,
[{description,"An Erlang development tool and Zomp user client"}, [{description,"An Erlang development tool and Zomp user client"},
{vsn,"0.8.0"}, {vsn,"0.9.0"},
{applications,[stdlib,kernel]}, {applications,[stdlib,kernel]},
{modules,[zx,zx_auth,zx_conn,zx_conn_sup,zx_daemon,zx_key, {modules,[zx,zx_auth,zx_conn,zx_conn_sup,zx_daemon,zx_key,
zx_lib,zx_local,zx_net,zx_peer,zx_peer_man, zx_lib,zx_local,zx_net,zx_peer,zx_peer_man,

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -24,7 +24,7 @@
%%% @end %%% @end
-module(zx). -module(zx).
-vsn("0.8.0"). -vsn("0.9.0").
-behavior(application). -behavior(application).
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").
@ -35,7 +35,7 @@
-export([run/2, not_done/1, done/1, -export([run/2, not_done/1, done/1,
subscribe/1, unsubscribe/0, subscribe/1, unsubscribe/0,
list/0, list/1, list/2, list/3, latest/1, list/0, list/1, list/2, list/3, latest/1,
list_type/2, list_type_ar/1, describe/1, describe_plural/1, list_type/2, list_type_ar/1, describe/1, describe_plural/1, integrate/1,
stop/0, silent_stop/0]). stop/0, silent_stop/0]).
-export([start/2, stop/1]). -export([start/2, stop/1]).
@ -63,7 +63,7 @@
Minor :: non_neg_integer() | z, Minor :: non_neg_integer() | z,
Patch :: non_neg_integer() | z}. Patch :: non_neg_integer() | z}.
-type host() :: {string() | inet:ip_address(), inet:port_number()}. -type host() :: {string() | inet:ip_address(), inet:port_number()}.
-type key() :: term(). % Srsly. This is what public_key:der_decode/2 returns. -type key() :: term(). % wtf? This is what public_key:der_decode/2 returns
-type key_data() :: {Name :: key_name(), -type key_data() :: {Name :: key_name(),
Public :: none | key_bin(), Public :: none | key_bin(),
Private :: none | key_bin()}. Private :: none | key_bin()}.
@ -133,7 +133,7 @@ do(["run", PackageString | ArgV]) ->
not_done(run(PackageString, ArgV)); not_done(run(PackageString, ArgV));
do(["integrate", "desktop", PackageString]) -> do(["integrate", "desktop", PackageString]) ->
ok = zx_daemon:connect(), ok = zx_daemon:connect(),
done(zx_local:integrate(PackageString)); done(integrate0(PackageString));
do(["list", "realms"]) -> do(["list", "realms"]) ->
done(zx_local:list_realms()); done(zx_local:list_realms());
do(["list", "packages", Realm]) -> do(["list", "packages", Realm]) ->
@ -669,6 +669,126 @@ describe_plural(PackageIDs) ->
{ok, [Description || {_, {ok, Description}} <- Descriptions]}. {ok, [Description || {_, {ok, Description}} <- Descriptions]}.
-spec integrate(PackageString) -> zx:outcome()
when PackageString :: string().
integrate0(PackageString) ->
case zx_lib:package_id(PackageString) of
{ok, PackageID} -> integrate(PackageID);
Error -> Error
end.
integrate(PackageID) ->
case resolve_version(PackageID) of
{fetch, FetchID} -> integrate2(PackageID, FetchID);
{installed, InstalledID} -> integrate3(PackageID, InstalledID);
Error -> Error
end.
integrate2(PackageID, FetchID) ->
case fetch(FetchID) of
ok -> integrate3(PackageID, FetchID);
Error -> Error
end.
integrate3(PackageID, InstalledID) ->
Dir = zx_lib:ppath(lib, InstalledID),
{ok, Meta} = zx_lib:read_project_meta(Dir),
case maps:get(type, Meta) of
gui -> integrate4(PackageID, InstalledID, Meta);
Type -> {error, {bad_app_type, Type}}
end.
integrate4(PackageID, InstalledID, Meta) ->
case os:type() of
{unix, linux} ->
integrate_linux(PackageID, InstalledID, Meta);
% {win32, nt} ->
Other ->
Message = "Sorry! This command is not yet supported on ~p.",
ok = tell(error, Message, [Other]),
{error, "Feature unsupported on this platform."}
end.
integrate_linux(PackageID, InstalledID, Meta) ->
XDG_DESKTOP_DIR = discover_xdg_desktop(),
case filelib:is_dir(XDG_DESKTOP_DIR) of
true -> integrate_linux(PackageID, InstalledID, Meta, XDG_DESKTOP_DIR);
false -> {error, "No desktop directory defined by XDG."}
end.
integrate_linux(PackageID, InstalledID, Meta, XDG_DESKTOP_DIR) ->
IconPath = place_icon(InstalledID),
Name = element(2, InstalledID),
Title =
case maps:get(name, Meta) of
"" -> Name;
N -> N
end,
{ok, PackageString} = zx_lib:package_string(PackageID),
Version = element(3, PackageID),
{ok, VersionString} = zx_lib:version_to_string(Version),
Exec = "zx run " ++ PackageString,
Launcher = filename:join(XDG_DESKTOP_DIR, Name ++ ".desktop"),
Entry =
["[Desktop Entry]\n",
"Encoding=UTF-8\n",
"Version=", VersionString, "\n",
"Exec=", Exec, "\n",
"Name=", Title, "\n",
"Comment=", Title, "\n",
"Type=Application\n",
"Terminal=false\n",
"Icon=", IconPath, "\n"],
ok = file:write_file(Launcher, unicode:characters_to_list(Entry)),
_ = os:cmd("chmod +x " ++ Launcher),
ok.
place_icon({Realm, Name, Version}) ->
InstallDir = zx_lib:path(lib, Realm, Name, Version),
VarDir = zx_lib:path(var, Realm, Name),
Icon = "launcher.png",
IconSource = filename:join(InstallDir, Icon),
IconPath = filename:join(VarDir, Icon),
{ok, _} =
case filelib:is_regular(IconSource) of
true ->
file:copy(IconSource, IconPath);
false ->
ZxVersionS = os:getenv("ZX_VERSION"),
{ok, ZxVersion} = zx_lib:string_to_version(ZxVersionS),
ZxDir = zx_lib:path(lib, "otpr", "zx", ZxVersion),
ZxIconPath = filename:join(ZxDir, Icon),
ok = filelib:ensure_dir(IconPath),
file:copy(ZxIconPath, IconPath)
end,
IconPath.
discover_xdg_desktop() ->
XDG_UserDirsConf =
case os:getenv("XDG_CONFIG_HOME") of
false -> filename:join(os:getenv("HOME"), ".config/user-dirs.dirs");
"" -> filename:join(os:getenv("HOME"), ".config/user-dirs.dirs");
D -> filename:join(D, "user-dirs.dirs")
end,
{ok, Bits} = file:read_file(XDG_UserDirsConf),
Segments = string:split(unicode:characters_to_list(Bits), "\n", all),
search_xdg(Segments).
search_xdg(["XDG_DESKTOP_DIR=" ++ Value | _]) ->
filename:join(os:getenv("HOME"), filename:basename(string:trim(Value, both, "\"")));
search_xdg([_ | Rest]) ->
search_xdg(Rest);
search_xdg([]) ->
filename:join(os:getenv("HOME"), "Desktop").
%%% Execution of application %%% Execution of application
-spec run(PackageString, RunArgs) -> zx:outcome() -spec run(PackageString, RunArgs) -> zx:outcome()
@ -723,20 +843,20 @@ tuplize(String, Acc) ->
run2(FuzzyID, RunArgs) -> run2(FuzzyID, RunArgs) ->
case resolve_version(FuzzyID) of case resolve_version(FuzzyID) of
{installed, PackageID} -> run3(PackageID, RunArgs); {fetch, PackageID} -> run3(PackageID, RunArgs);
{fetch, PackageID} -> run3_maybe(PackageID, RunArgs); {installed, PackageID} -> run4(PackageID, RunArgs);
Error -> Error
end.
run3_maybe(PackageID, RunArgs) ->
case fetch(PackageID) of
ok -> run3(PackageID, RunArgs);
Error -> Error Error -> Error
end. end.
run3(PackageID, RunArgs) -> run3(PackageID, RunArgs) ->
case fetch(PackageID) of
ok -> run4(PackageID, RunArgs);
Error -> Error
end.
run4(PackageID, RunArgs) ->
Dir = zx_lib:ppath(lib, PackageID), Dir = zx_lib:ppath(lib, PackageID),
{ok, Meta} = zx_lib:read_project_meta(Dir), {ok, Meta} = zx_lib:read_project_meta(Dir),
Type = maps:get(type, Meta), Type = maps:get(type, Meta),
@ -999,7 +1119,7 @@ usage_user() ->
" zx import realm RealmFile~n" " zx import realm RealmFile~n"
" zx drop realm Realm~n" " zx drop realm Realm~n"
" zx add mirror [Address [Port]]~n" " zx add mirror [Address [Port]]~n"
" zx drop mirror [Address [Port]]~n~n" " zx drop mirror [Address [Port]]~n"
" zx --version~n~n". " zx --version~n~n".
usage_dev() -> usage_dev() ->

View File

@ -9,7 +9,7 @@
%%% @end %%% @end
-module(zx_auth). -module(zx_auth).
-vsn("0.8.0"). -vsn("0.9.0").
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0"). -license("GPL-3.0").

View File

@ -7,7 +7,7 @@
%%% @end %%% @end
-module(zx_conn). -module(zx_conn).
-vsn("0.8.0"). -vsn("0.9.0").
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0"). -license("GPL-3.0").

View File

@ -5,7 +5,7 @@
%%% @end %%% @end
-module(zx_conn_sup). -module(zx_conn_sup).
-vsn("0.8.0"). -vsn("0.9.0").
-behavior(supervisor). -behavior(supervisor).
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").

View File

@ -138,7 +138,7 @@
%%% @end %%% @end
-module(zx_daemon). -module(zx_daemon).
-vsn("0.8.0"). -vsn("0.9.0").
-behavior(gen_server). -behavior(gen_server).
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").

View File

@ -8,7 +8,7 @@
%%% @end %%% @end
-module(zx_key). -module(zx_key).
-vsn("0.8.0"). -vsn("0.9.0").
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0"). -license("GPL-3.0").

View File

@ -10,7 +10,7 @@
%%% @end %%% @end
-module(zx_lib). -module(zx_lib).
-vsn("0.8.0"). -vsn("0.9.0").
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0"). -license("GPL-3.0").

View File

@ -6,7 +6,7 @@
%%% @end %%% @end
-module(zx_local). -module(zx_local).
-vsn("0.8.0"). -vsn("0.9.0").
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0"). -license("GPL-3.0").

View File

@ -5,7 +5,7 @@
%%% @end %%% @end
-module(zx_net). -module(zx_net).
-vsn("0.8.0"). -vsn("0.9.0").
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0"). -license("GPL-3.0").

View File

@ -8,7 +8,7 @@
%%% @end %%% @end
-module(zx_peer). -module(zx_peer).
-vsn("0.8.0"). -vsn("0.9.0").
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0"). -license("GPL-3.0").

View File

@ -9,7 +9,7 @@
%%% @end %%% @end
-module(zx_peer_man). -module(zx_peer_man).
-vsn("0.8.0"). -vsn("0.9.0").
-behavior(gen_server). -behavior(gen_server).
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").

View File

@ -6,7 +6,7 @@
%%% @end %%% @end
-module(zx_peer_sup). -module(zx_peer_sup).
-vsn("0.8.0"). -vsn("0.9.0").
-behaviour(supervisor). -behaviour(supervisor).
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").

View File

@ -10,7 +10,7 @@
%%% @end %%% @end
-module(zx_peers). -module(zx_peers).
-vsn("0.8.0"). -vsn("0.9.0").
-behavior(supervisor). -behavior(supervisor).
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").

View File

@ -5,7 +5,7 @@
%%% @end %%% @end
-module(zx_proxy). -module(zx_proxy).
-vsn("0.8.0"). -vsn("0.9.0").
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0"). -license("GPL-3.0").

View File

@ -5,7 +5,7 @@
%%% @end %%% @end
-module(zx_sup). -module(zx_sup).
-vsn("0.8.0"). -vsn("0.9.0").
-behavior(supervisor). -behavior(supervisor).
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").

View File

@ -6,7 +6,7 @@
%%% @end %%% @end
-module(zx_tty). -module(zx_tty).
-vsn("0.8.0"). -vsn("0.9.0").
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0"). -license("GPL-3.0").

View File

@ -5,7 +5,7 @@
%%% @end %%% @end
-module(zx_userconf). -module(zx_userconf).
-vsn("0.8.0"). -vsn("0.9.0").
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0"). -license("GPL-3.0").

View File

@ -7,7 +7,7 @@
%%% @end %%% @end
-module(zx_zsp). -module(zx_zsp).
-vsn("0.8.0"). -vsn("0.9.0").
-author("Craig Everett <zxq9@zxq9.com>"). -author("Craig Everett <zxq9@zxq9.com>").
-copyright("Craig Everett <zxq9@zxq9.com>"). -copyright("Craig Everett <zxq9@zxq9.com>").
-license("GPL-3.0"). -license("GPL-3.0").

View File

@ -9,7 +9,7 @@
{license,"MIT"}. {license,"MIT"}.
{modules,[]}. {modules,[]}.
{name,"zx"}. {name,"zx"}.
{package_id,{"otpr","zx",{0,8,0}}}. {package_id,{"otpr","zx",{0,9,0}}}.
{prefix,"zx_"}. {prefix,"zx_"}.
{repo_url,"https://gitlab.com/zxq9/zx"}. {repo_url,"https://gitlab.com/zxq9/zx"}.
{tags,["tools","package manager","erlang"]}. {tags,["tools","package manager","erlang"]}.