+ (if (eq last-command 'yank)
+ (progn
+ (setq ivy-completion-end (point))
+ (setq ivy-completion-beg
+ (save-excursion
+ (search-backward (car kill-ring))
+ (point))))
+ (setq ivy-completion-beg (point))
+ (setq ivy-completion-end (point)))
+ (let ((candidates (cl-remove-if
+ (lambda (s)
+ (or (< (length s) 3)
+ (string-match "\\`[\n[:blank:]]+\\'" s)))
+ (delete-dups kill-ring))))
+ (let ((ivy-format-function #'counsel--yank-pop-format-function)
+ (ivy-height 5))
+ (ivy-read "kill-ring: " candidates
+ :action 'counsel-yank-pop-action
+ :caller 'counsel-yank-pop))))
+
+;;** `counsel-imenu'
+(defvar imenu-auto-rescan)
+(declare-function imenu--subalist-p "imenu")
+(declare-function imenu--make-index-alist "imenu")
+
+(defun counsel-imenu-get-candidates-from (alist &optional prefix)
+ "Create a list of (key . value) from ALIST.
+PREFIX is used to create the key."
+ (cl-mapcan (lambda (elm)
+ (if (imenu--subalist-p elm)
+ (counsel-imenu-get-candidates-from
+ (cl-loop for (e . v) in (cdr elm) collect
+ (cons e (if (integerp v) (copy-marker v) v)))
+ ;; pass the prefix to next recursive call
+ (concat prefix (if prefix ".") (car elm)))
+ (let ((key (concat prefix (if prefix ".") (car elm))))
+ (list (cons key
+ ;; create a imenu candidate here
+ (cons key (if (overlayp (cdr elm))
+ (overlay-start (cdr elm))
+ (cdr elm))))))))
+ alist))
+
+;;;###autoload
+(defun counsel-imenu ()
+ "Jump to a buffer position indexed by imenu."
+ (interactive)
+ (unless (featurep 'imenu)
+ (require 'imenu nil t))
+ (let* ((imenu-auto-rescan t)
+ (items (imenu--make-index-alist t))
+ (items (delete (assoc "*Rescan*" items) items)))
+ (ivy-read "imenu items:" (counsel-imenu-get-candidates-from items)
+ :preselect (thing-at-point 'symbol)
+ :require-match t
+ :action (lambda (candidate)
+ (with-ivy-window
+ ;; In org-mode, (imenu candidate) will expand child node
+ ;; after jump to the candidate position
+ (imenu candidate)))
+ :caller 'counsel-imenu)))
+
+;;** `counsel-list-processes'
+(defun counsel-list-processes-action-delete (x)
+ (delete-process x)
+ (setf (ivy-state-collection ivy-last)
+ (setq ivy--all-candidates
+ (delete x ivy--all-candidates))))
+
+(defun counsel-list-processes-action-switch (x)
+ (let* ((proc (get-process x))
+ (buf (and proc (process-buffer proc))))
+ (if buf
+ (switch-to-buffer buf)
+ (message "Process %s doesn't have a buffer" x))))
+
+;;;###autoload
+(defun counsel-list-processes ()
+ "Offer completion for `process-list'
+The default action deletes the selected process.
+An extra action allows to switch to the process buffer."
+ (interactive)
+ (list-processes--refresh)
+ (ivy-read "Process: " (mapcar #'process-name (process-list))
+ :require-match t
+ :action
+ '(1
+ ("o" counsel-list-processes-action-delete "kill")
+ ("s" counsel-list-processes-action-switch "switch"))
+ :caller 'counsel-list-processes))
+
+;;** `counsel-ace-link'
+(defun counsel-ace-link ()
+ "Use Ivy completion for `ace-link'."
+ (interactive)
+ (let (collection action)
+ (cond ((eq major-mode 'Info-mode)
+ (setq collection 'ace-link--info-collect)
+ (setq action 'ace-link--info-action))
+ ((eq major-mode 'help-mode)
+ (setq collection 'ace-link--help-collect)
+ (setq action 'ace-link--help-action))
+ ((eq major-mode 'woman-mode)
+ (setq collection 'ace-link--woman-collect)
+ (setq action 'ace-link--woman-action))
+ ((eq major-mode 'eww-mode)
+ (setq collection 'ace-link--eww-collect)
+ (setq action 'ace-link--eww-action))
+ ((eq major-mode 'compilation-mode)
+ (setq collection 'ace-link--eww-collect)
+ (setq action 'ace-link--compilation-action))
+ ((eq major-mode 'org-mode)
+ (setq collection 'ace-link--org-collect)
+ (setq action 'ace-link--org-action)))
+ (if (null collection)
+ (error "%S is not supported" major-mode)
+ (ivy-read "Ace-Link: " (funcall collection)
+ :action action
+ :require-match t
+ :caller 'counsel-ace-link))))
+
+;;* Misc OS
+;;** `counsel-rhythmbox'
+(defvar helm-rhythmbox-library)
+(declare-function helm-rhythmbox-load-library "ext:helm-rhythmbox")
+(declare-function dbus-call-method "dbus")
+(declare-function dbus-get-property "dbus")
+(declare-function helm-rhythmbox-song-uri "ext:helm-rhythmbox")
+(declare-function helm-rhythmbox-candidates "ext:helm-rhythmbox")
+
+(defun counsel-rhythmbox-enqueue-song (song)
+ "Let Rhythmbox enqueue SONG."
+ (let ((service "org.gnome.Rhythmbox3")
+ (path "/org/gnome/Rhythmbox3/PlayQueue")
+ (interface "org.gnome.Rhythmbox3.PlayQueue"))
+ (dbus-call-method :session service path interface
+ "AddToQueue" (helm-rhythmbox-song-uri song))))
+
+(defvar counsel-rhythmbox-history nil
+ "History for `counsel-rhythmbox'.")
+
+(defun counsel-rhythmbox-current-song ()
+ "Return the currently playing song title."
+ (ignore-errors
+ (let* ((entry (dbus-get-property
+ :session
+ "org.mpris.MediaPlayer2.rhythmbox"
+ "/org/mpris/MediaPlayer2"
+ "org.mpris.MediaPlayer2.Player"
+ "Metadata"))
+ (artist (caar (cadr (assoc "xesam:artist" entry))))
+ (album (cl-caadr (assoc "xesam:album" entry)))
+ (title (cl-caadr (assoc "xesam:title" entry))))
+ (format "%s - %s - %s" artist album title))))
+
+;;;###autoload
+(defun counsel-rhythmbox ()
+ "Choose a song from the Rhythmbox library to play or enqueue."
+ (interactive)
+ (unless (require 'helm-rhythmbox nil t)
+ (error "Please install `helm-rhythmbox'"))
+ (unless helm-rhythmbox-library
+ (helm-rhythmbox-load-library)
+ (while (null helm-rhythmbox-library)
+ (sit-for 0.1)))
+ (ivy-read "Rhythmbox: "
+ (helm-rhythmbox-candidates)
+ :history 'counsel-rhythmbox-history
+ :preselect (counsel-rhythmbox-current-song)
+ :action
+ '(1
+ ("p" helm-rhythmbox-play-song "Play song")
+ ("e" counsel-rhythmbox-enqueue-song "Enqueue song"))
+ :caller 'counsel-rhythmbox))
+;;** `counsel-linux-app'
+(defvar counsel-linux-apps-alist nil
+ "List of data located in /usr/share/applications.")
+
+(defvar counsel-linux-apps-faulty nil
+ "List of faulty data located in /usr/share/applications.")
+
+(defun counsel-linux-apps-list ()
+ (let ((files
+ (delete
+ ".." (delete
+ "." (file-expand-wildcards "/usr/share/applications/*.desktop")))))
+ (dolist (file (cl-set-difference files (append (mapcar 'car counsel-linux-apps-alist)
+ counsel-linux-apps-faulty)
+ :test 'equal))
+ (with-temp-buffer
+ (insert-file-contents (expand-file-name file "/usr/share/applications"))
+ (let (name comment exec)
+ (goto-char (point-min))
+ (if (re-search-forward "^Name *= *\\(.*\\)$" nil t)
+ (setq name (match-string 1))
+ (error "File %s has no Name" file))
+ (goto-char (point-min))
+ (when (re-search-forward "^Comment *= *\\(.*\\)$" nil t)
+ (setq comment (match-string 1)))
+ (goto-char (point-min))
+ (when (re-search-forward "^Exec *= *\\(.*\\)$" nil t)
+ (setq exec (match-string 1)))
+ (if (and exec (not (equal exec "")))
+ (add-to-list
+ 'counsel-linux-apps-alist
+ (cons (format "% -45s: %s%s"
+ (propertize exec 'face 'font-lock-builtin-face)
+ name
+ (if comment
+ (concat " - " comment)
+ ""))
+ file))
+ (add-to-list 'counsel-linux-apps-faulty file))))))
+ counsel-linux-apps-alist)
+
+(defun counsel-linux-app-action-default (desktop-shortcut)
+ "Launch DESKTOP-SHORTCUT."
+ (call-process-shell-command
+ (format "gtk-launch %s" (file-name-nondirectory desktop-shortcut))))
+
+(defun counsel-linux-app-action-file (desktop-shortcut)
+ "Launch DESKTOP-SHORTCUT with a selected file."
+ (let* ((entry (rassoc desktop-shortcut counsel-linux-apps-alist))
+ (short-name (and entry
+ (string-match "\\([^ ]*\\) " (car entry))
+ (match-string 1 (car entry))))
+ (file (and short-name
+ (read-file-name
+ (format "Run %s on: " short-name)))))
+ (if file
+ (call-process-shell-command
+ (format "gtk-launch %s %s"
+ (file-name-nondirectory desktop-shortcut)
+ file))
+ (user-error "cancelled"))))
+
+(ivy-set-actions
+ 'counsel-linux-app
+ '(("f" counsel-linux-app-action-file "run on a file")))
+
+;;;###autoload
+(defun counsel-linux-app ()
+ "Launch a Linux desktop application, similar to Alt-<F2>."
+ (interactive)
+ (ivy-read "Run a command: " (counsel-linux-apps-list)
+ :action #'counsel-linux-app-action-default
+ :caller 'counsel-linux-app))
+
+;;** `counsel-mode'
+(defvar counsel-mode-map
+ (let ((map (make-sparse-keymap)))
+ (dolist (binding
+ '((execute-extended-command . counsel-M-x)
+ (describe-bindings . counsel-descbinds)
+ (describe-function . counsel-describe-function)
+ (describe-variable . counsel-describe-variable)
+ (find-file . counsel-find-file)
+ (imenu . counsel-imenu)
+ (load-library . counsel-load-library)
+ (load-theme . counsel-load-theme)
+ (yank-pop . counsel-yank-pop)))
+ (define-key map (vector 'remap (car binding)) (cdr binding)))
+ map)
+ "Map for `counsel-mode'. Remaps built-in functions to counsel
+replacements.")
+
+(defcustom counsel-mode-override-describe-bindings nil
+ "Whether to override `describe-bindings' when `counsel-mode' is
+active."
+ :group 'ivy
+ :type 'boolean)
+
+;;;###autoload
+(define-minor-mode counsel-mode
+ "Toggle Counsel mode on or off.
+Turn Counsel mode on if ARG is positive, off otherwise. Counsel
+mode remaps built-in emacs functions that have counsel
+replacements. "
+ :group 'ivy
+ :global t
+ :keymap counsel-mode-map
+ :lighter " counsel"
+ (if counsel-mode
+ (when (and (fboundp 'advice-add)
+ counsel-mode-override-describe-bindings)
+ (advice-add #'describe-bindings :override #'counsel-descbinds))
+ (when (fboundp 'advice-remove)
+ (advice-remove #'describe-bindings #'counsel-descbinds))))