+(defun counsel-directory-parent (dir)
+ "Return the directory parent of directory DIR."
+ (concat (file-name-nondirectory
+ (directory-file-name dir)) "/"))
+
+(defun counsel-string-compose (prefix str)
+ "Make PREFIX the display prefix of STR though text properties."
+ (let ((str (copy-sequence str)))
+ (put-text-property
+ 0 1 'display
+ (concat prefix (substring str 0 1))
+ str)
+ str))
+
+;;;###autoload
+(defun counsel-load-library ()
+ "Load a selected the Emacs Lisp library.
+The libraries are offered from `load-path'."
+ (interactive)
+ (let ((dirs load-path)
+ (suffix (concat (regexp-opt '(".el" ".el.gz") t) "\\'"))
+ (cands (make-hash-table :test #'equal))
+ short-name
+ old-val
+ dir-parent
+ res)
+ (dolist (dir dirs)
+ (when (file-directory-p dir)
+ (dolist (file (file-name-all-completions "" dir))
+ (when (string-match suffix file)
+ (unless (string-match "pkg.elc?$" file)
+ (setq short-name (substring file 0 (match-beginning 0)))
+ (if (setq old-val (gethash short-name cands))
+ (progn
+ ;; assume going up directory once will resolve name clash
+ (setq dir-parent (counsel-directory-parent (cdr old-val)))
+ (puthash short-name
+ (cons
+ (counsel-string-compose dir-parent (car old-val))
+ (cdr old-val))
+ cands)
+ (setq dir-parent (counsel-directory-parent dir))
+ (puthash (concat dir-parent short-name)
+ (cons
+ (propertize
+ (counsel-string-compose
+ dir-parent short-name)
+ 'full-name (expand-file-name file dir))
+ dir)
+ cands))
+ (puthash short-name
+ (cons (propertize
+ short-name
+ 'full-name (expand-file-name file dir))
+ dir) cands)))))))
+ (maphash (lambda (_k v) (push (car v) res)) cands)
+ (ivy-read "Load library: " (nreverse res)
+ :action (lambda (x)
+ (load-library
+ (get-text-property 0 'full-name x)))
+ :keymap counsel-describe-map)))
+
+(defun counsel--gg-candidates (regex)
+ "Return git grep candidates for REGEX."
+ (counsel--gg-count regex)
+ (let* ((default-directory counsel--git-grep-dir)
+ (counsel-gg-process " *counsel-gg*")
+ (proc (get-process counsel-gg-process))
+ (buff (get-buffer counsel-gg-process)))
+ (when proc
+ (delete-process proc))
+ (when buff
+ (kill-buffer buff))
+ (setq proc (start-process-shell-command
+ counsel-gg-process
+ counsel-gg-process
+ (format "git --no-pager grep --full-name -n --no-color -i -e %S | head -n 200"
+ regex)))
+ (set-process-sentinel
+ proc
+ #'counsel--gg-sentinel)))
+
+(defun counsel--gg-sentinel (process event)
+ (if (string= event "finished\n")
+ (progn
+ (with-current-buffer (process-buffer process)
+ (setq ivy--all-candidates (split-string (buffer-string) "\n" t))
+ (setq ivy--old-cands ivy--all-candidates))
+ (unless (eq ivy--full-length -1)
+ (ivy--insert-minibuffer
+ (ivy--format ivy--all-candidates))))
+ (if (string= event "exited abnormally with code 1\n")
+ (message "Error"))))
+
+(defun counsel--gg-count (regex &optional no-async)
+ "Quickly and asynchronously count the amount of git grep REGEX matches.
+When NO-ASYNC is non-nil, do it synchronously."
+ (let ((default-directory counsel--git-grep-dir)
+ (cmd (format "git grep -i -c '%s' | sed 's/.*:\\(.*\\)/\\1/g' | awk '{s+=$1} END {print s}'"
+ regex))
+ (counsel-ggc-process " *counsel-gg-count*"))
+ (if no-async
+ (string-to-number (shell-command-to-string cmd))
+ (let ((proc (get-process counsel-ggc-process))
+ (buff (get-buffer counsel-ggc-process)))
+ (when proc
+ (delete-process proc))
+ (when buff
+ (kill-buffer buff))
+ (setq proc (start-process-shell-command
+ counsel-ggc-process
+ counsel-ggc-process
+ cmd))
+ (set-process-sentinel
+ proc
+ #'(lambda (process event)
+ (when (string= event "finished\n")
+ (with-current-buffer (process-buffer process)
+ (setq ivy--full-length (string-to-number (buffer-string))))
+ (ivy--insert-minibuffer
+ (ivy--format ivy--all-candidates)))))))))
+
+(defun counsel--M-x-transformer (cmd)
+ "Add a binding to CMD if it's bound in the current window.
+CMD is a command name."
+ (let ((binding (substitute-command-keys (format "\\[%s]" cmd))))
+ (setq binding (replace-regexp-in-string "C-x 6" "<f2>" binding))
+ (if (string-match "^M-x" binding)
+ cmd
+ (format "%s (%s)" cmd
+ (propertize binding 'face 'font-lock-keyword-face)))))
+
+(defvar smex-initialized-p)
+(defvar smex-ido-cache)
+(declare-function smex-initialize "ext:smex")
+(declare-function smex-detect-new-commands "ext:smex")
+(declare-function smex-update "ext:smex")
+(declare-function smex-rank "ext:smex")
+(declare-function package-installed-p "package")
+
+;;;###autoload
+(defun counsel-M-x (&optional initial-input)
+ "Ivy version of `execute-extended-command'.
+Optional INITIAL-INPUT is the initial input in the minibuffer."
+ (interactive)
+ (unless initial-input
+ (setq initial-input (cdr (assoc this-command
+ ivy-initial-inputs-alist))))
+ (let* ((store ivy-format-function)
+ (ivy-format-function
+ (lambda (cands)
+ (funcall
+ store
+ (with-selected-window (ivy-state-window ivy-last)
+ (mapcar #'counsel--M-x-transformer cands)))))
+ (cands obarray)
+ (pred 'commandp)
+ (sort t))
+ (when (or (featurep 'smex)
+ (package-installed-p 'smex))
+ (require 'smex)
+ (unless smex-initialized-p
+ (smex-initialize))
+ (smex-detect-new-commands)
+ (smex-update)
+ (setq cands smex-ido-cache)
+ (setq pred nil)
+ (setq sort nil))
+ (ivy-read "M-x " cands
+ :predicate pred
+ :require-match t
+ :history 'extended-command-history
+ :action
+ (lambda (cmd)
+ (when (featurep 'smex)
+ (smex-rank (intern cmd)))
+ (let ((prefix-arg current-prefix-arg))
+ (command-execute (intern cmd) 'record)))
+ :sort sort
+ :keymap counsel-describe-map
+ :initial-input initial-input)))
+
+(declare-function powerline-reset "ext:powerline")
+
+(defun counsel--load-theme-action (x)
+ "Disable current themes and load theme X."
+ (condition-case nil
+ (progn
+ (mapc #'disable-theme custom-enabled-themes)
+ (load-theme (intern x))
+ (when (fboundp 'powerline-reset)
+ (powerline-reset)))
+ (error "Problem loading theme %s" x)))
+
+;;;###autoload
+(defun counsel-load-theme ()
+ "Forward to `load-theme'.
+Usable with `ivy-resume', `ivy-next-line-and-call' and
+`ivy-previous-line-and-call'."
+ (interactive)
+ (ivy-read "Load custom theme: "
+ (mapcar 'symbol-name
+ (custom-available-themes))
+ :action #'counsel--load-theme-action))
+
+