From 5c3644ef2e24ca38c24bbb4c93ca5ce2075c9320 Mon Sep 17 00:00:00 2001 From: Samuel Dionne-Riel Date: Sun, 23 Jan 2022 01:36:21 -0500 Subject: [PATCH 1/5] saturn: Also include DATA_HOME > $XDG_DATA_DIRS defines the preference-ordered set of base > directories to search for data files in addition to the > $XDG_DATA_HOME base directory. The directories in > $XDG_DATA_DIRS should be seperated with a colon ':'. *in addition to the DATA_HOME base directory*. --- saturn/main.fnl | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/saturn/main.fnl b/saturn/main.fnl index 1120ca3..b123b42 100644 --- a/saturn/main.fnl +++ b/saturn/main.fnl @@ -94,7 +94,12 @@ (local path { :absolute? (fn [str] (= (str:sub 1 1) "/")) + :concat (fn [...] (table.concat [...] "/")) }) +(local search-path { + :concat (fn [...] (table.concat [...] ":")) + }) + (local Gtk lgi.Gtk) (local GdkPixbuf lgi.GdkPixbuf) @@ -154,9 +159,30 @@ (tset vals "IconImage" (find-icon vals.Icon))) vals)) +(fn current-user-home [] + "Returns current user's home directory." + (-> (posix.unistd.getuid) + (posix.pwd.getpwuid) + (. :pw_dir))) + +(fn xdg-data-home [] + "Provides XDG_DATA_HOME or its default fallback value" + (local data-home (os.getenv "XDG_DATA_HOME")) + (if data-home + data-home + (path.concat (current-user-home) ".local/share/"))) + +(fn xdg-data-dirs [] + "Provides all data-dirs as a colon-separated string." + ;; Expected to be used with gmatch as a generator. + (search-path.concat + (xdg-data-home) + (os.getenv "XDG_DATA_DIRS") + )) + (fn all-apps [] (var apps-table {}) - (each [path (string.gmatch (os.getenv "XDG_DATA_DIRS") "[^:]*")] + (each [path (string.gmatch (xdg-data-dirs) "[^:]*")] (let [apps (.. path "/applications/")] (when (lfs.attributes apps) (each [f (lfs.dir apps)] From 168f4c5793b72f2484237befab5fc583f02609db Mon Sep 17 00:00:00 2001 From: Samuel Dionne-Riel Date: Tue, 25 Jan 2022 00:42:04 -0500 Subject: [PATCH 2/5] saturn: Add penlight as a dependency --- saturn/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/saturn/default.nix b/saturn/default.nix index 83a936a..bb93aa0 100644 --- a/saturn/default.nix +++ b/saturn/default.nix @@ -44,6 +44,7 @@ let fennel = fetchurl { lgi luafilesystem luaposix + penlight readline ]); in stdenv.mkDerivation { From 4f82010ab09d29be8b41178786c617294e0218b2 Mon Sep 17 00:00:00 2001 From: Samuel Dionne-Riel Date: Tue, 25 Jan 2022 00:42:25 -0500 Subject: [PATCH 3/5] saturn: Add desktop file ID to properties --- saturn/main.fnl | 1 + 1 file changed, 1 insertion(+) diff --git a/saturn/main.fnl b/saturn/main.fnl index b123b42..c30c47e 100644 --- a/saturn/main.fnl +++ b/saturn/main.fnl @@ -157,6 +157,7 @@ vals (. parsed "Desktop Entry")] (when vals.Icon (tset vals "IconImage" (find-icon vals.Icon))) + (tset vals "ID" (f:sub 0 -9)) vals)) (fn current-user-home [] From 3574f3930ff7679c3d73eb2e17f020359955ace3 Mon Sep 17 00:00:00 2001 From: Samuel Dionne-Riel Date: Tue, 25 Jan 2022 00:45:31 -0500 Subject: [PATCH 4/5] saturn: Provide data-dirs as List And use the right priority --- saturn/main.fnl | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/saturn/main.fnl b/saturn/main.fnl index c30c47e..f694723 100644 --- a/saturn/main.fnl +++ b/saturn/main.fnl @@ -89,6 +89,8 @@ (local lfs (require :lfs)) (local inifile (require :inifile)) +(local List (require "pl.List")) +(local stringx (require "pl.stringx")) (local inspect (require :inspect)) (local posix (require :posix)) @@ -174,16 +176,20 @@ (path.concat (current-user-home) ".local/share/"))) (fn xdg-data-dirs [] - "Provides all data-dirs as a colon-separated string." + "Provides all data-dirs as a List. Most important first." ;; Expected to be used with gmatch as a generator. - (search-path.concat - (xdg-data-home) - (os.getenv "XDG_DATA_DIRS") - )) + (let [dirs (List)] + (dirs:append (xdg-data-home)) + (dirs:extend (stringx.split (os.getenv "XDG_DATA_DIRS") ":")) + dirs + )) (fn all-apps [] (var apps-table {}) - (each [path (string.gmatch (xdg-data-dirs) "[^:]*")] + ;; Reversing the data dirs gives priority to the first elements. + ;; This means conflicting `.desktop` files (or: desktop file ID) are given + ;; priority to the first elements by "simply" reading it last. + (each [path (List.iter (List.reverse (xdg-data-dirs)))] (let [apps (.. path "/applications/")] (when (lfs.attributes apps) (each [f (lfs.dir apps)] From 8af2a7de4584ea757d5d39b4d02bbb21edfe6aa4 Mon Sep 17 00:00:00 2001 From: Samuel Dionne-Riel Date: Tue, 25 Jan 2022 00:47:00 -0500 Subject: [PATCH 5/5] saturn: Sort apps by name All of this done through using Lists from penlight --- saturn/main.fnl | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/saturn/main.fnl b/saturn/main.fnl index f694723..60de954 100644 --- a/saturn/main.fnl +++ b/saturn/main.fnl @@ -91,6 +91,7 @@ (local inifile (require :inifile)) (local List (require "pl.List")) (local stringx (require "pl.stringx")) +(local tablex (require "pl.tablex")) (local inspect (require :inspect)) (local posix (require :posix)) @@ -185,19 +186,26 @@ )) (fn all-apps [] + ;; Each desktop entry representing an application is identified + ;; by its desktop file ID, which is based on its filename. + ;; — https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#desktop-file-id + "Provides apps in a List, sorted by name" (var apps-table {}) ;; Reversing the data dirs gives priority to the first elements. ;; This means conflicting `.desktop` files (or: desktop file ID) are given ;; priority to the first elements by "simply" reading it last. (each [path (List.iter (List.reverse (xdg-data-dirs)))] - (let [apps (.. path "/applications/")] - (when (lfs.attributes apps) - (each [f (lfs.dir apps)] + (let [apps-dir (.. path "/applications/")] + (when (lfs.attributes apps-dir) + (each [f (lfs.dir apps-dir)] (when (= (f:sub -8) ".desktop") - (let [attrs (read-desktop-file (.. apps f))] + (let [attrs (read-desktop-file (.. apps-dir f))] (when (not attrs.NoDisplay) - (tset apps-table attrs.Name attrs)))))))) - apps-table) + (tset apps-table attrs.ID attrs)))))))) + ;; We have a table indexed by IDs, we don't care about the indexing. + ;; Make a List and sort it by name. + (List.sort (List (tablex.values apps-table)) + (fn [a b] (< (string.upper a.Name) (string.upper b.Name))))) ;; Exec entries in desktop files may contain %u %f and other characters ;; in which the launcher is supposed to interpolate filenames/urls etc. @@ -266,7 +274,7 @@ :row_spacing 5 }) scrolled-window (Gtk.ScrolledWindow {})] - (each [_ app (pairs (all-apps))] + (each [app (List.iter (all-apps))] (grid:insert (button-for app) -1)) (scrolled-window:add grid) (window:add scrolled-window))