]> code.delx.au - gnu-emacs/blob - lisp/pcmpl-x.el
* pcmpl-x.el (pcmpl-x-ag-options): Handle `[no]' in long options.
[gnu-emacs] / lisp / pcmpl-x.el
1 ;;; pcmpl-x.el --- completion for miscellaneous tools -*- lexical-binding: t; -*-
2
3 ;; Copyright (C) 2013 Free Software Foundation, Inc.
4
5 ;; Author: Leo Liu <sdl.web@gmail.com>
6 ;; Keywords: processes, tools, convenience
7 ;; Package: pcomplete
8
9 ;; This file is part of GNU Emacs.
10
11 ;; GNU Emacs is free software: you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation, either version 3 of the License, or
14 ;; (at your option) any later version.
15
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
23
24 ;;; Code:
25
26 (eval-when-compile (require 'cl-lib))
27 (require 'pcomplete)
28
29
30 ;;;; tlmgr - http://www.tug.org/texlive/tlmgr.html
31
32 (defcustom pcmpl-x-tlmgr-program "tlmgr"
33 "Name of the tlmgr program."
34 :type 'file
35 :group 'pcomplete)
36
37 (defvar pcmpl-x-tlmgr-common-options
38 '("--repository"
39 "--gui"
40 "--gui-lang"
41 "--machine-readable"
42 "--package-logfile"
43 "--pause"
44 "--persistent-downloads"
45 "--no-persistent-downloads"
46 "--no-execute-actions"
47 "--debug-translation"
48 "--help"
49 "--version"))
50
51 (defvar pcmpl-x-tlmgr-actions
52 '(("help")
53 ("version")
54 ("gui")
55 ("install")
56 ("update")
57 ("backup")
58 ("restore")
59 ("remove")
60 ("repository" ("list" "add" "remove" "set"))
61 ("candidates")
62 ("option" ("show"
63 "showall"
64 "repository"
65 "formats"
66 "postcode"
67 "docfiles"
68 "srcfiles"
69 "backupdir"
70 "autobackup"
71 "sys_bin"
72 "sys_man"
73 "sys_info"
74 "desktop_integration"
75 "fileassocs"
76 "multiuser"))
77 ("conf" ("texmf" "tlmgr"))
78 ("paper"
79 ("a4" "letter" "xdvi" "pdftex" "dvips" "dvipdfmx" "dvipdfm" "context")
80 (lambda ()
81 (unless (member (pcomplete-arg 1) '("a4" "letter"))
82 (pcomplete-here* '("paper"))
83 (pcomplete-here* '("a4" "letter")))))
84 ("platform" ("list" "add" "remove"))
85 ("print-platform" ("collections" "schemes"))
86 ("arch" ("list" "add" "remove"))
87 ("print-arch" ("collections" "schemes"))
88 ("info" ("collections" "schemes"))
89 ("search")
90 ("dump-tlpdb")
91 ("check" ("files" "depends" "executes" "runfiles" "all"))
92 ("path" ("add" "remove"))
93 ("postaction" ("install" "remove") ("shortcut" "fileassoc" "script"))
94 ("uninstall")
95 ("generate" ("language"
96 "language.dat"
97 "language.def"
98 "language.dat.lua"
99 "fmtutil"))))
100
101 (defvar pcmpl-x-tlmgr-options-cache (make-hash-table :size 31 :test 'equal))
102
103 (defun pcmpl-x-tlmgr-action-options (action)
104 "Get the list of long options for ACTION."
105 (if (eq (gethash action pcmpl-x-tlmgr-options-cache 'missing) 'missing)
106 (with-temp-buffer
107 (when (zerop
108 (call-process pcmpl-x-tlmgr-program nil t nil action "-h"))
109 (goto-char (point-min))
110 (puthash action
111 (cons "--help"
112 (cl-loop while (re-search-forward
113 "^[ \t]+\\(--[[:alnum:]-]+=?\\)"
114 nil t)
115 collect (match-string 1)))
116 pcmpl-x-tlmgr-options-cache)
117 (pcmpl-x-tlmgr-action-options action)))
118 (gethash action pcmpl-x-tlmgr-options-cache)))
119
120 ;;;###autoload
121 (defun pcomplete/tlmgr ()
122 "Completion for the `tlmgr' command."
123 (while (pcomplete-match "^--" 0)
124 (pcomplete-here* pcmpl-x-tlmgr-common-options)
125 (unless (or (pcomplete-match "^--" 0)
126 (all-completions (pcomplete-arg 0) pcmpl-x-tlmgr-actions))
127 (pcomplete-here* (pcomplete-dirs-or-entries))))
128 (pcomplete-here* pcmpl-x-tlmgr-actions)
129 (let ((action (substring-no-properties (pcomplete-arg 1))))
130 (while t
131 (if (pcomplete-match "^--" 0)
132 (pcomplete-here* (pcmpl-x-tlmgr-action-options action))
133 (dolist (completions (cdr (assoc action pcmpl-x-tlmgr-actions)))
134 (cond ((functionp completions)
135 (funcall completions))
136 ((all-completions (pcomplete-arg 0) completions)
137 (pcomplete-here* completions))
138 (t (pcomplete-here* (pcomplete-dirs-or-entries)))))
139 (unless (pcomplete-match "^--" 0)
140 (pcomplete-here* (pcomplete-dirs-or-entries)))))))
141
142
143 ;;;; ack - http://betterthangrep.com
144
145 ;; Usage:
146 ;; - To complete short options type '-' first
147 ;; - To complete long options type '--' first
148 ;; - Color name completion is supported following
149 ;; --color-filename=, --color-match= and --color-lineno=
150 ;; - Type completion is supported following --type=
151
152 (defcustom pcmpl-x-ack-program
153 (file-name-nondirectory (or (executable-find "ack-grep")
154 (executable-find "ack")
155 "ack"))
156 "Name of the ack program."
157 :type 'file
158 :group 'pcomplete)
159
160 (defvar pcmpl-x-ack-color-options
161 '("clear"
162 "reset"
163 "dark"
164 "bold"
165 "underline"
166 "underscore"
167 "blink"
168 "reverse"
169 "concealed"
170 "black"
171 "red"
172 "green"
173 "yellow"
174 "blue"
175 "magenta"
176 "on_black"
177 "on_red"
178 "on_green"
179 "on_yellow"
180 "on_blue"
181 "on_magenta"
182 "on_cyan"
183 "on_white")
184 "Color names for the `ack' command.")
185
186 (defun pcmpl-x-ack-run (buffer &rest args)
187 "Run ack with ARGS and send the output to BUFFER."
188 (condition-case nil
189 (apply 'call-process (or pcmpl-x-ack-program "ack") nil buffer nil args)
190 (file-error -1)))
191
192 (defun pcmpl-x-ack-short-options ()
193 "Short options for the `ack' command."
194 (with-temp-buffer
195 (let (options)
196 (when (zerop (pcmpl-x-ack-run t "--help"))
197 (goto-char (point-min))
198 (while (re-search-forward "^ -\\([^-]\\)" nil t)
199 (push (match-string 1) options))
200 (mapconcat 'identity (nreverse options) "")))))
201
202 (defun pcmpl-x-ack-long-options (&optional arg)
203 "Long options for the `ack' command."
204 (with-temp-buffer
205 (let (options)
206 (when (zerop (pcmpl-x-ack-run t (or arg "--help")))
207 (goto-char (point-min))
208 (while (re-search-forward
209 "\\(?: ?\\|, \\)\\(--\\(\\[no\\]\\)?\\([[:alnum:]-]+=?\\)\\)"
210 nil t)
211 (if (not (match-string 2))
212 (push (match-string 1) options)
213 (push (concat "--" (match-string 3)) options)
214 (push (concat "--no" (match-string 3)) options)))
215 (nreverse options)))))
216
217 (defun pcmpl-x-ack-type-options ()
218 "A list of types for the `ack' command."
219 (pcmpl-x-ack-long-options "--help-types"))
220
221 ;;;###autoload
222 (defun pcomplete/ack ()
223 "Completion for the `ack' command.
224 Start an argument with '-' to complete short options and '--' for
225 long options."
226 ;; No space after =
227 (while t
228 (if (pcomplete-match "^-" 0)
229 (cond
230 ((pcomplete-match "^--color-\\w+=\\(\\S-*\\)" 0)
231 (pcomplete-here* pcmpl-x-ack-color-options
232 (pcomplete-match-string 1 0) t))
233 ((pcomplete-match "^--\\(?:no\\)?ignore-dir=\\(\\S-*\\)" 0)
234 (pcomplete-here* (pcomplete-dirs)
235 (pcomplete-match-string 1 0) t))
236 ((pcomplete-match "^--type=\\(\\S-*\\)" 0)
237 (pcomplete-here* (mapcar (lambda (type-option)
238 (substring type-option 2))
239 (pcmpl-x-ack-type-options))
240 (pcomplete-match-string 1 0) t))
241 ((pcomplete-match "^--" 0)
242 (pcomplete-here* (append (pcmpl-x-ack-long-options)
243 (pcmpl-x-ack-type-options))))
244 (t (pcomplete-opt (pcmpl-x-ack-short-options))))
245 (pcomplete-here* (pcomplete-dirs-or-entries)))))
246
247 ;;;###autoload
248 (defalias 'pcomplete/ack-grep 'pcomplete/ack)
249
250
251 ;;;; the_silver_search - https://github.com/ggreer/the_silver_searcher
252
253 (defvar pcmpl-x-ag-options nil)
254
255 (defun pcmpl-x-ag-options ()
256 (or pcmpl-x-ag-options
257 (setq pcmpl-x-ag-options
258 (with-temp-buffer
259 (when (zerop (call-process "ag" nil t nil "--help"))
260 (let (short long)
261 (goto-char (point-min))
262 (while (re-search-forward "^ +\\(-[a-zA-Z]\\) " nil t)
263 (push (match-string 1) short))
264 (goto-char (point-min))
265 (while (re-search-forward
266 "^ +\\(?:-[a-zA-Z] \\)?\\(--\\(\\[no\\]\\)?[^ \t\n]+\\) "
267 nil t)
268 (if (match-string 2)
269 (progn
270 (replace-match "" nil nil nil 2)
271 (push (match-string 1) long)
272 (replace-match "no" nil nil nil 2)
273 (push (match-string 1) long))
274 (push (match-string 1) long)))
275 (list (cons 'short (nreverse short))
276 (cons 'long (nreverse long)))))))))
277
278 ;;;###autoload
279 (defun pcomplete/ag ()
280 "Completion for the `ag' command."
281 (while t
282 (if (pcomplete-match "^-" 0)
283 (pcomplete-here* (cdr (assq (if (pcomplete-match "^--" 0) 'long 'short)
284 (pcmpl-x-ag-options))))
285 (pcomplete-here* (pcomplete-dirs-or-entries)))))
286
287 (provide 'pcmpl-x)
288 ;;; pcmpl-x.el ends here