-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathncla.el
166 lines (131 loc) · 5.71 KB
/
ncla.el
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
;;; ncla.el --- Non Counsel Linux App (Launcher) -*- lexical-binding: t -*-
;; Author: Linas Vidziunas <[email protected]>
;; Maintainer: Linas Vidziunas <[email protected]>
;; Created: 2021
;; Version: 0.10
;; Package-Requires: ((emacs "26.1"))
;; Homepage: https://github.com/LinasVidziunas/NCLA
;;; Code:
;; change the path to desktop file directory if necessary
;; should consider using xdg as https://github.com/LinasVidziunas/app-launcher/blob/main/app-launcher.el
(defvar ncla-desktop-file-paths
(directory-files "/usr/share/applications/" t (regexp-quote ".desktop"))
"Contains all *.desktop files")
(defvar ncla-include-terminal-applications nil
"If non-nil value, Terminal=true applications will be included in the list")
(defvar ncla--cached-applications nil
"Cached list of applications. Used by ncla--get-applictions")
(defvar ncla--cached-timestamp nil
"Time at when the last cache happened. Used by ncla--get-applications")
(defvar ncla-cache-timeout 5
"Time in seconds for the cache timeout")
;;;###autoload
(defun ncla ()
"Open NCLA in an interactive minibuffer"
(interactive)
(setq applications (ncla--get-applications ncla-desktop-file-paths))
(let (name exec)
(setq name
(let ((completion-extra-properties '(:annotation-function ncla--annotation-function)))
(completing-read "Start application: " applications)))
(setq exec (ncla--get-exec-by-app-name name))
(start-process-shell-command name nil exec)))
(defun ncla--get-comment-by-app-name (application-name)
"Returns the comment of an application by appplication name from the cached application list"
(cdr (assoc "comment" (assoc application-name ncla--cached-applications))))
(defun ncla--get-exec-by-app-name (application-name)
"Returns the exec command of an application by application name from the cached application list"
(ncla--process-exec-cmd (cdr (assoc "exec" (assoc application-name ncla--cached-applications)))))
(defun ncla--get-genericname-by-app-name (application-name)
"Returns the GenericName of an application by application name from the cached application list"
(let (genericname)
(setq genericname (assoc "genericname" (assoc application-name ncla--cached-applications)))
(when (cdr genericname)
;; convert list to string
(format "%s" (cdr (assoc "genericname" (assoc application-name ncla--cached-applications)))))))
(defun ncla--process-exec-cmd (preprocessed-cmd)
"Processes cmd and returns it"
;; split string by white space
(setq preprocessed-cmd
(split-string preprocessed-cmd " " t))
(let (cmd)
(dolist (element preprocessed-cmd cmd)
;; remove elements that start with the % symbol
(if (not (string-match-p "%" (substring element 0 1)))
(if cmd
(setq cmd (format "%s %s" cmd element))
(setq cmd element))))))
(defun ncla--parse-desktop-file (file-path)
(let (name exec comment terminal genericname)
(catch 'done
(dolist (line (split-string
(with-temp-buffer
(insert-file-contents file-path)
(buffer-substring-no-properties
(point-min)
(point-max))) "\n" t))
(when (and (string-match-p "^Name=" line)
(not name))
(setq name (substring line 5 (length line))))
(when (and (string-match-p "^Exec=" line)
(not exec))
(setq exec (substring line 5 (length line))))
(when (and (string-match-p "^Terminal=" line)
(not terminal))
(setq terminal (substring line 9 (length line))))
(when (and (string-match-p "^Comment=" line)
(not comment))
(setq comment (substring line 8 (length line))))
(when (and (string-match-p "GenericName=" line)
(not genericname))
(setq genericname (substring line 12 (length line))))
(when (and (and (and (and name exec) comment) terminal) genericname)
(throw 'done 'done))))
;; Don't include applications with "Terminal=true",
;; except when ncla-include-terminal-applications is set to a non-nil value
(when (or (or (not terminal)
(string-match-p terminal "false"))
ncla-include-terminal-applications)
;; needs to have name and execuatble command
(when (and name exec)
(list name
(cons "exec" exec)
(cons "comment" comment)
(cons "genericname" genericname))))))
(defun ncla--get-applications (desktop-file-paths)
"Returns list with a list of application name and command"
(let (applications)
(if (or (not ncla--cached-applications)
(and ncla--cached-timestamp
(time-less-p (time-add ncla--cached-timestamp ncla-cache-timeout) (current-time))))
(progn
(dolist (file-path desktop-file-paths)
(let (application)
(setq application (ncla--parse-desktop-file file-path))
(when application
(setq applications (cons (ncla--parse-desktop-file file-path) applications)))))
(setq ncla--cached-timestamp (current-time)))
(setq applications ncla--cached-applications))
(setq ncla--cached-applications applications)))
(defun ncla--annotation-function (cand-name)
"Default function to annotate the completion choices."
(let (comment genericname return-string)
(setq comment (ncla--get-comment-by-app-name cand-name))
(setq genericname (ncla--get-genericname-by-app-name cand-name))
(when comment
(setq return-string
(concat
return-string
;; hardcoded values should be replaced
;; should probably learn elisp :)
(propertize " " 'display '(space :align-to (+ left 40)))
(propertize comment 'face '(:foreground "grey")))))
(when genericname
(setq return-string
(concat
return-string
;; hardcoded values should be replaced
(propertize " " 'display '(space :align-to (- right-fringe 20)))
(propertize genericname 'face'(:foreground "red")))))))
(provide 'ncla)
;;; ncla.el ends here