1 ;;; pcmpl-ack.el --- completion for ack and ag -*- lexical-binding: t; -*-
3 ;; Copyright (C) 2012-2015 Free Software Foundation, Inc.
5 ;; Author: Leo Liu <sdl.web@gmail.com>
6 ;; Keywords: tools, processes, convenience
8 ;; URL: https://github.com/leoliu/ack-el
10 ;; This program is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation, either version 3 of the License, or
13 ;; (at your option) any later version.
15 ;; This program is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
25 ;; Provide pcompletion support for the cli tool `ack' which can be
26 ;; downloaded from http://beyondgrep.com.
29 ;; (autoload 'pcomplete/ack "pcmpl-ack")
30 ;; (autoload 'pcomplete/ag "pcmpl-ack")
33 ;; - To complete short options type '-' first
34 ;; - To complete long options type '--' first
35 ;; - Color name completion is supported following
36 ;; --color-filename=, --color-match= and --color-lineno=
37 ;; - Type completion is supported following --type=
43 (defcustom pcmpl-ack-program
44 (file-name-nondirectory (or (executable-find "ack-grep")
45 (executable-find "ack")
47 "Name of the ack program."
51 (defvar pcmpl-ack-color-options
75 "Color names for the `ack' command.")
77 (defun pcmpl-ack-run (buffer &rest args)
78 "Run ack with ARGS and send the output to BUFFER."
80 (apply 'call-process (or pcmpl-ack-program "ack") nil buffer nil args)
83 (defun pcmpl-ack-short-options ()
84 "Short options for the `ack' command."
87 (when (zerop (pcmpl-ack-run t "--help"))
88 (goto-char (point-min))
89 (while (re-search-forward "^ -\\([^-]\\)" nil t)
90 (push (match-string 1) options))
91 (mapconcat 'identity (nreverse options) "")))))
93 (defun pcmpl-ack-long-options (&optional arg)
94 "Long options for the `ack' command."
97 (when (zerop (pcmpl-ack-run t (or arg "--help")))
98 (goto-char (point-min))
99 (while (re-search-forward
100 "\\(?: ?\\|, \\)\\(--\\(\\[no\\]\\)?\\([[:alnum:]-]+=?\\)\\)"
102 (if (not (match-string 2))
103 (push (match-string 1) options)
104 (push (concat "--" (match-string 3)) options)
105 (push (concat "--no" (match-string 3)) options)))
106 (nreverse options)))))
108 (defun pcmpl-ack-type-options ()
109 "A list of types for the `ack' command."
110 (pcmpl-ack-long-options "--help-types"))
113 (defun pcomplete/ack ()
114 "Completion for the `ack' command.
115 Start an argument with `-' to complete short options and `--' for
119 (if (pcomplete-match "^-" 0)
121 ((pcomplete-match "^--color-\\w+=\\(\\S-*\\)" 0)
122 (pcomplete-here* pcmpl-ack-color-options
123 (pcomplete-match-string 1 0) t))
124 ((pcomplete-match "^--\\(?:no\\)?ignore-dir=\\(\\S-*\\)" 0)
125 (pcomplete-here* (pcomplete-dirs)
126 (pcomplete-match-string 1 0) t))
127 ((pcomplete-match "^--type=\\(\\S-*\\)" 0)
128 (pcomplete-here* (mapcar (lambda (type-option)
129 (substring type-option 2))
130 (pcmpl-ack-type-options))
131 (pcomplete-match-string 1 0) t))
132 ((pcomplete-match "^--" 0)
133 (pcomplete-here* (append (pcmpl-ack-long-options)
134 (pcmpl-ack-type-options))))
135 (t (pcomplete-opt (pcmpl-ack-short-options))))
136 (pcomplete-here* (pcomplete-dirs-or-entries)))))
139 (defalias 'pcomplete/ack-grep 'pcomplete/ack)
141 (defvar pcmpl-ack-ag-options nil)
143 (defun pcmpl-ack-ag-options ()
144 (or pcmpl-ack-ag-options
145 (setq pcmpl-ack-ag-options
147 (when (zerop (call-process "ag" nil t nil "--help"))
149 (goto-char (point-min))
150 (while (re-search-forward "^ +\\(-[a-zA-Z]\\) " nil t)
151 (push (match-string 1) short))
152 (goto-char (point-min))
153 (while (re-search-forward
154 "^ +\\(?:-[a-zA-Z] \\)?\\(--\\(\\[no\\]\\)?[^ \t\n]+\\) "
158 (replace-match "" nil nil nil 2)
159 (push (match-string 1) long)
160 (replace-match "no" nil nil nil 2)
161 (push (match-string 1) long))
162 (push (match-string 1) long)))
163 (list (cons 'short (nreverse short))
164 (cons 'long (nreverse long)))))))))
167 (defun pcomplete/ag ()
168 "Completion for the `ag' command."
170 (if (pcomplete-match "^-" 0)
171 (pcomplete-here* (cdr (assq (if (pcomplete-match "^--" 0) 'long 'short)
172 (pcmpl-ack-ag-options))))
173 (pcomplete-here* (pcomplete-dirs-or-entries)))))
176 ;;; pcmpl-ack.el ends here