1 ;;; pcmpl-x.el --- completion for miscellaneous tools -*- lexical-binding: t; -*-
3 ;; Copyright (C) 2013-2016 Free Software Foundation, Inc.
5 ;; Author: Leo Liu <sdl.web@gmail.com>
6 ;; Keywords: processes, tools, convenience
9 ;; This file is part of GNU Emacs.
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.
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.
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/>.
26 (eval-when-compile (require 'cl-lib))
30 ;;;; tlmgr - http://www.tug.org/texlive/tlmgr.html
32 (defcustom pcmpl-x-tlmgr-program "tlmgr"
33 "Name of the tlmgr program."
38 (defvar pcmpl-x-tlmgr-common-options
45 "--persistent-downloads"
46 "--no-persistent-downloads"
47 "--no-execute-actions"
52 (defvar pcmpl-x-tlmgr-actions
61 ("repository" ("list" "add" "remove" "set"))
78 ("conf" ("texmf" "tlmgr"))
80 ("a4" "letter" "xdvi" "pdftex" "dvips" "dvipdfmx" "dvipdfm" "context")
82 (unless (member (pcomplete-arg 1) '("a4" "letter"))
83 (pcomplete-here* '("paper"))
84 (pcomplete-here* '("a4" "letter")))))
85 ("platform" ("list" "add" "remove"))
86 ("print-platform" ("collections" "schemes"))
87 ("arch" ("list" "add" "remove"))
88 ("print-arch" ("collections" "schemes"))
89 ("info" ("collections" "schemes"))
92 ("check" ("files" "depends" "executes" "runfiles" "all"))
93 ("path" ("add" "remove"))
94 ("postaction" ("install" "remove") ("shortcut" "fileassoc" "script"))
96 ("generate" ("language"
102 (defvar pcmpl-x-tlmgr-options-cache (make-hash-table :size 31 :test 'equal))
104 (defun pcmpl-x-tlmgr-action-options (action)
105 "Get the list of long options for ACTION."
106 (if (eq (gethash action pcmpl-x-tlmgr-options-cache 'missing) 'missing)
109 (call-process pcmpl-x-tlmgr-program nil t nil action "-h"))
110 (goto-char (point-min))
113 (cl-loop while (re-search-forward
114 "^[ \t]+\\(--[[:alnum:]-]+=?\\)"
116 collect (match-string 1)))
117 pcmpl-x-tlmgr-options-cache)
118 (pcmpl-x-tlmgr-action-options action)))
119 (gethash action pcmpl-x-tlmgr-options-cache)))
122 (defun pcomplete/tlmgr ()
123 "Completion for the `tlmgr' command."
124 (while (pcomplete-match "^--" 0)
125 (pcomplete-here* pcmpl-x-tlmgr-common-options)
126 (unless (or (pcomplete-match "^--" 0)
127 (all-completions (pcomplete-arg 0) pcmpl-x-tlmgr-actions))
128 (pcomplete-here* (pcomplete-dirs-or-entries))))
129 (pcomplete-here* pcmpl-x-tlmgr-actions)
130 (let ((action (substring-no-properties (pcomplete-arg 1))))
132 (if (pcomplete-match "^--" 0)
133 (pcomplete-here* (pcmpl-x-tlmgr-action-options action))
134 (dolist (completions (cdr (assoc action pcmpl-x-tlmgr-actions)))
135 (cond ((functionp completions)
136 (funcall completions))
137 ((all-completions (pcomplete-arg 0) completions)
138 (pcomplete-here* completions))
139 (t (pcomplete-here* (pcomplete-dirs-or-entries)))))
140 (unless (pcomplete-match "^--" 0)
141 (pcomplete-here* (pcomplete-dirs-or-entries)))))))
144 ;;;; ack - http://betterthangrep.com
147 ;; - To complete short options type '-' first
148 ;; - To complete long options type '--' first
149 ;; - Color name completion is supported following
150 ;; --color-filename=, --color-match= and --color-lineno=
151 ;; - Type completion is supported following --type=
153 (defcustom pcmpl-x-ack-program
154 (file-name-nondirectory (or (executable-find "ack-grep")
155 (executable-find "ack")
157 "Name of the ack program."
162 (defvar pcmpl-x-ack-color-options
186 "Color names for the `ack' command.")
188 (defun pcmpl-x-ack-run (buffer &rest args)
189 "Run ack with ARGS and send the output to BUFFER."
191 (apply 'call-process (or pcmpl-x-ack-program "ack") nil buffer nil args)
194 (defun pcmpl-x-ack-short-options ()
195 "Short options for the `ack' command."
198 (when (zerop (pcmpl-x-ack-run t "--help"))
199 (goto-char (point-min))
200 (while (re-search-forward "^ -\\([^-]\\)" nil t)
201 (push (match-string 1) options))
202 (mapconcat 'identity (nreverse options) "")))))
204 (defun pcmpl-x-ack-long-options (&optional arg)
205 "Long options for the `ack' command."
208 (when (zerop (pcmpl-x-ack-run t (or arg "--help")))
209 (goto-char (point-min))
210 (while (re-search-forward
211 "\\(?: ?\\|, \\)\\(--\\(\\[no\\]\\)?\\([[:alnum:]-]+=?\\)\\)"
213 (if (not (match-string 2))
214 (push (match-string 1) options)
215 (push (concat "--" (match-string 3)) options)
216 (push (concat "--no" (match-string 3)) options)))
217 (nreverse options)))))
219 (defun pcmpl-x-ack-type-options ()
220 "A list of types for the `ack' command."
221 (pcmpl-x-ack-long-options "--help-types"))
224 (defun pcomplete/ack ()
225 "Completion for the `ack' command.
226 Start an argument with `-' to complete short options and `--' for
230 (if (pcomplete-match "^-" 0)
232 ((pcomplete-match "^--color-\\w+=\\(\\S-*\\)" 0)
233 (pcomplete-here* pcmpl-x-ack-color-options
234 (pcomplete-match-string 1 0) t))
235 ((pcomplete-match "^--\\(?:no\\)?ignore-dir=\\(\\S-*\\)" 0)
236 (pcomplete-here* (pcomplete-dirs)
237 (pcomplete-match-string 1 0) t))
238 ((pcomplete-match "^--type=\\(\\S-*\\)" 0)
239 (pcomplete-here* (mapcar (lambda (type-option)
240 (substring type-option 2))
241 (pcmpl-x-ack-type-options))
242 (pcomplete-match-string 1 0) t))
243 ((pcomplete-match "^--" 0)
244 (pcomplete-here* (append (pcmpl-x-ack-long-options)
245 (pcmpl-x-ack-type-options))))
246 (t (pcomplete-opt (pcmpl-x-ack-short-options))))
247 (pcomplete-here* (pcomplete-dirs-or-entries)))))
250 (defalias 'pcomplete/ack-grep 'pcomplete/ack)
253 ;;;; the_silver_search - https://github.com/ggreer/the_silver_searcher
255 (defvar pcmpl-x-ag-options nil)
257 (defun pcmpl-x-ag-options ()
258 (or pcmpl-x-ag-options
259 (setq pcmpl-x-ag-options
261 (when (zerop (call-process "ag" nil t nil "--help"))
263 (goto-char (point-min))
264 (while (re-search-forward "^ +\\(-[a-zA-Z]\\) " nil t)
265 (push (match-string 1) short))
266 (goto-char (point-min))
267 (while (re-search-forward
268 "^ +\\(?:-[a-zA-Z] \\)?\\(--\\(\\[no\\]\\)?[^ \t\n]+\\) "
272 (replace-match "" nil nil nil 2)
273 (push (match-string 1) long)
274 (replace-match "no" nil nil nil 2)
275 (push (match-string 1) long))
276 (push (match-string 1) long)))
277 (list (cons 'short (nreverse short))
278 (cons 'long (nreverse long)))))))))
281 (defun pcomplete/ag ()
282 "Completion for the `ag' command."
284 (if (pcomplete-match "^-" 0)
285 (pcomplete-here* (cdr (assq (if (pcomplete-match "^--" 0) 'long 'short)
286 (pcmpl-x-ag-options))))
287 (pcomplete-here* (pcomplete-dirs-or-entries)))))
290 ;;; pcmpl-x.el ends here