branch: master
commit f0426613062ba8305ebac41672d853a95cd9bbca
Author: Justin Burkett <[email protected]>
Commit: Oleh Krehel <[email protected]>

    Guard calls to external programs with helpful message
    
    * counsel.el (counsel-require-program): Add
    (counsel-git): Add guard
    (counsel-git-grep): Add guard
    (counsel--async-time): Add guard
    (counsel-find-file-as-root): Add guard
    (counsel-emacs-url-p): Add guard
    (counsel-locate-cmd-default): Add guard
    (counsel-locate-cmd-noregex): Add guard
    (counsel-locate-cmd-mdfind): Add guard
    (counsel-locate-cmd-es): Add guard
    (counsel-dpkg): Add guard
    (counsel-rpm): Add guard
    (counsel-file-jump): Add guard
    (counsel-dired-jump): Add guard
    (counsel-ag): Add guard
    (counsel-rg): Add guard
    (counsel-grep): Add guard
    (counsel-recoll): Add guard
    
    Fixes #1076
---
 counsel.el | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/counsel.el b/counsel.el
index a101d1b..5aa0564 100644
--- a/counsel.el
+++ b/counsel.el
@@ -86,6 +86,13 @@
      str)
     str))
 
+(defun counsel-require-program (program)
+  "Check system for PROGRAM, printing error if unfound."
+  (when (and (stringp program)
+             (not (string= program ""))
+             (not (executable-find program)))
+    (user-error "Required program \"%s\" not found in your path" program)))
+
 ;;* Async Utility
 (defvar counsel--async-time nil
   "Store the time when a new process was started.
@@ -991,6 +998,7 @@ BUFFER defaults to the current one."
 (defun counsel-git (&optional initial-input)
   "Find file in the current Git repository."
   (interactive)
+  (counsel-require-program (car (split-string counsel-git-cmd)))
   (setq counsel--git-dir (locate-dominating-file
                           default-directory ".git"))
   (ivy-set-prompt 'counsel-git counsel-prompt-function)
@@ -1168,6 +1176,7 @@ INITIAL-INPUT can be given as the initial minibuffer 
input."
                (delete-dups counsel-git-grep-cmd-history))))
       (t
        (setq counsel-git-grep-cmd counsel-git-grep-cmd-default)))
+    (counsel-require-program (car (split-string counsel-git-grep-cmd)))
     (setq counsel--git-grep-dir
           (if proj
               (car proj)
@@ -1484,6 +1493,7 @@ TREE is the selected candidate."
 
 (defun counsel-find-file-as-root (x)
   "Find file X with root privileges."
+  (counsel-require-program counsel-root-command)
   (let* ((host (file-remote-p x 'host))
          (file-name (format "/%s:%s:%s"
                             counsel-root-command
@@ -1596,6 +1606,7 @@ When INITIAL-INPUT is non-nil, use it in the minibuffer 
during completion."
 
 (defun counsel-github-url-p ()
   "Return a Github issue URL at point."
+  (counsel-require-program "git")
   (let ((url (counsel-at-git-issue-p)))
     (when url
       (let ((origin (shell-command-to-string
@@ -1615,6 +1626,7 @@ When INITIAL-INPUT is non-nil, use it in the minibuffer 
during completion."
 
 (defun counsel-emacs-url-p ()
   "Return a Debbugs issue URL at point."
+  (counsel-require-program "git")
   (let ((url (counsel-at-git-issue-p)))
     (when url
       (let ((origin (shell-command-to-string
@@ -1697,20 +1709,24 @@ string - the full shell command to run."
 
 (defun counsel-locate-cmd-default (input)
   "Return a shell command based on INPUT."
+  (counsel-require-program "locate")
   (format "locate -i --regex '%s'"
           (counsel-unquote-regex-parens
            (ivy--regex input))))
 
 (defun counsel-locate-cmd-noregex (input)
   "Return a shell command based on INPUT."
+  (counsel-require-program "locate")
   (format "locate -i '%s'" input))
 
 (defun counsel-locate-cmd-mdfind (input)
   "Return a shell command based on INPUT."
+  (counsel-require-program "mdfind")
   (format "mdfind -name '%s'" input))
 
 (defun counsel-locate-cmd-es (input)
   "Return a shell command based on INPUT."
+  (counsel-require-program "es.exe")
   (format "es.exe -i -r %s"
           (counsel-unquote-regex-parens
            (ivy--regex input t))))
@@ -1744,6 +1760,7 @@ INITIAL-INPUT can be given as the initial minibuffer 
input."
 (defun counsel-dpkg ()
   "Call the \"dpkg\" shell command."
   (interactive)
+  (counsel-require-program "dpkg")
   (let ((cands (mapcar
                 (lambda (x)
                   (let ((y (split-string x "  +")))
@@ -1764,6 +1781,7 @@ INITIAL-INPUT can be given as the initial minibuffer 
input."
 (defun counsel-rpm ()
   "Call the \"rpm\" shell command."
   (interactive)
+  (counsel-require-program "rpm")
   (let ((cands (mapcar
                 (lambda (x)
                   (let ((y (split-string x "|")))
@@ -1791,6 +1809,7 @@ INITIAL-DIRECTORY, if non-nil, is used as the root 
directory for search."
    (list nil
          (when current-prefix-arg
            (read-directory-name "From directory: "))))
+  (counsel-require-program "find")
   (let* ((default-directory (or initial-directory default-directory)))
     (ivy-read "Find file: "
               (split-string
@@ -1820,6 +1839,7 @@ INITIAL-DIRECTORY, if non-nil, is used as the root 
directory for search."
    (list nil
          (when current-prefix-arg
            (read-directory-name "From directory: "))))
+  (counsel-require-program "find")
   (let* ((default-directory (or initial-directory default-directory)))
     (ivy-read "Directory: "
               (split-string
@@ -1908,6 +1928,7 @@ INITIAL-DIRECTORY, if non-nil, is used as the root 
directory for search.
 EXTRA-AG-ARGS string, if non-nil, is appended to `counsel-ag-base-command'.
 AG-PROMPT, if non-nil, is passed as `ivy-read' prompt argument."
   (interactive)
+  (counsel-require-program (car (split-string counsel-ag-base-command)))
   (when current-prefix-arg
     (setq initial-directory
           (or initial-directory
@@ -1999,6 +2020,7 @@ RG-PROMPT, if non-nil, is passed as `ivy-read' prompt 
argument."
            (read-directory-name (concat
                                  (car (split-string counsel-rg-base-command))
                                  " in directory: ")))))
+  (counsel-require-program (car (split-string counsel-rg-base-command)))
   (ivy-set-prompt 'counsel-rg counsel-prompt-function)
   (setq counsel--git-grep-dir (or initial-directory default-directory))
   (ivy-read (or rg-prompt (car (split-string counsel-rg-base-command)))
@@ -2082,6 +2104,7 @@ RG-PROMPT, if non-nil, is passed as `ivy-read' prompt 
argument."
 (defun counsel-grep ()
   "Grep for a string in the current file."
   (interactive)
+  (counsel-require-program (car (split-string counsel-grep-base-command)))
   (setq counsel-grep-last-line nil)
   (setq counsel--git-grep-dir (buffer-file-name))
   (let ((init-point (point))
@@ -2165,6 +2188,7 @@ You'll be given a list of files that match.
 Selecting a file will launch `swiper' for that file.
 INITIAL-INPUT can be given as the initial minibuffer input."
   (interactive)
+  (counsel-require-program "recoll")
   (ivy-read "recoll: " 'counsel-recoll-function
             :initial-input initial-input
             :dynamic-collection t

Reply via email to