Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve counsel-ibuffer #1569

Merged
merged 3 commits into from
May 14, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 97 additions & 104 deletions counsel.el
Original file line number Diff line number Diff line change
Expand Up @@ -4410,35 +4410,76 @@ a symbol and how to search for them."
(push (symbol-name symbol) cands))))
(delete "" cands)))

;;** `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)
(describe-face . counsel-describe-face)
(list-faces-display . counsel-faces)
(find-file . counsel-find-file)
(find-library . counsel-find-library)
(imenu . counsel-imenu)
(load-library . counsel-load-library)
(load-theme . counsel-load-theme)
(yank-pop . counsel-yank-pop)
(info-lookup-symbol . counsel-info-lookup-symbol)
(pop-to-mark-command . counsel-mark-ring)
(bookmark-jump . counsel-bookmark)))
(define-key map (vector 'remap (car binding)) (cdr binding)))
map)
"Map for `counsel-mode'.
Remaps built-in functions to counsel replacements.")
;;** `counsel-ibuffer'
(defvar counsel-ibuffer--buffer-name nil
"Name of the buffer to use for `counsel-ibuffer'.")

(defcustom counsel-mode-override-describe-bindings nil
"Whether to override `describe-bindings' when `counsel-mode' is active."
:group 'ivy
:type 'boolean)
;;;###autoload
(defun counsel-ibuffer (&optional name)
"Use ibuffer to switch to another buffer.
NAME specifies the name of the buffer (defaults to \"*Ibuffer*\")."
(interactive)
(setq counsel-ibuffer--buffer-name (or name "*Ibuffer*"))
(ivy-read "Switch to buffer: " (counsel-ibuffer--get-buffers)
:history 'counsel-ibuffer-history
:action #'counsel-ibuffer-visit-buffer
:caller 'counsel-ibuffer))

(declare-function ibuffer-update "ibuffer")
(declare-function ibuffer-current-buffer "ibuffer")
(declare-function ibuffer-forward-line "ibuffer")
(defvar ibuffer-movement-cycle)

(defun counsel-ibuffer--get-buffers ()
"Return list of buffer-related lines in Ibuffer as strings."
(let ((oldbuf (get-buffer counsel-ibuffer--buffer-name)))
(unless oldbuf
;; Avoid messing with the user's precious window/frame configuration.
(save-window-excursion
(let ((display-buffer-overriding-action
'(display-buffer-same-window (inhibit-same-window . nil))))
(ibuffer nil counsel-ibuffer--buffer-name nil t))))
(with-current-buffer counsel-ibuffer--buffer-name
(when oldbuf
;; Forcibly update possibly stale existing buffer.
(ibuffer-update nil t))
(goto-char (point-min))
(let ((ibuffer-movement-cycle nil)
entries)
(while (not (eobp))
(ibuffer-forward-line 1 t)
(let ((buf (ibuffer-current-buffer)))
;; We are only interested in buffers we can actually visit.
;; This filters out headings and other unusable entries.
(when (buffer-live-p buf)
(push (cons (buffer-substring-no-properties
(line-beginning-position)
(line-end-position))
buf)
entries))))
(nreverse entries)))))

(defun counsel-ibuffer-visit-buffer (x)
"Switch to buffer of candidate X."
(switch-to-buffer (cdr x)))

(defun counsel-ibuffer-visit-buffer-other-window (x)
"Switch to buffer of candidate X in another window."
(switch-to-buffer-other-window (cdr x)))

(define-obsolete-function-alias 'counsel-ibuffer-visit-vanilla-ibuffer
'counsel-ibuffer-visit-ibuffer "0.11.0")

(defun counsel-ibuffer-visit-ibuffer (_)
"Switch to Ibuffer buffer."
(switch-to-buffer counsel-ibuffer--buffer-name))

(ivy-set-actions
'counsel-ibuffer
'(("j" counsel-ibuffer-visit-buffer-other-window "other window")
("v" counsel-ibuffer-visit-ibuffer "switch to Ibuffer")))

;;** `counsel-switch-to-shell-buffer'
(defun counsel-list-buffers-with-mode (mode)
"Return names of buffers with `major-mode' `eq' to MODE."
(let (bufs)
Expand Down Expand Up @@ -4474,6 +4515,35 @@ the buffer."
(select-window window-of-buffer-visible)
(switch-to-buffer buffer))))))

;;** `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)
(describe-face . counsel-describe-face)
(list-faces-display . counsel-faces)
(find-file . counsel-find-file)
(find-library . counsel-find-library)
(imenu . counsel-imenu)
(load-library . counsel-load-library)
(load-theme . counsel-load-theme)
(yank-pop . counsel-yank-pop)
(info-lookup-symbol . counsel-info-lookup-symbol)
(pop-to-mark-command . counsel-mark-ring)
(bookmark-jump . counsel-bookmark)))
(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.
Expand All @@ -4494,83 +4564,6 @@ replacements. "
(when (fboundp 'advice-remove)
(advice-remove #'describe-bindings #'counsel-descbinds))))

;;** `counsel-ibuffer'
(defvar counsel-ibuffer--buffer-name nil
"Name of the buffer to use for `counsel-ibuffer'.")

;;;###autoload
(defun counsel-ibuffer (&optional name)
"Use ibuffer to switch to another buffer.
NAME specifies the name of the buffer (defaults to \"*Ibuffer*\")."
(interactive)
(setq counsel-ibuffer--buffer-name (or name "*Ibuffer*"))
(let ((entries (counsel-ibuffer--get-buffers)))
(ivy-read "Switch to buffer: "
entries
:history 'counsel-ibuffer-history
:action 'counsel-ibuffer-visit-buffer
:caller 'counsel-ibuffer)))

(declare-function ibuffer-update "ibuffer")
(declare-function ibuffer-current-buffer "ibuffer")
(declare-function ibuffer-forward-line "ibuffer")
(defvar ibuffer-movement-cycle)

(defun counsel-ibuffer--get-buffers ()
"Get buffers listed in ibuffer."
(let* ((ibuffer-buf (get-buffer counsel-ibuffer--buffer-name))
(new-ibuffer-p (not ibuffer-buf))
(ibuffer-movement-cycle t)
entries)
(when new-ibuffer-p
(ibuffer nil counsel-ibuffer--buffer-name)
(setq ibuffer-buf (current-buffer))
(quit-window))
(with-current-buffer ibuffer-buf
;; ibuffer might not be up to date in case we use an existing buffer.
(unless new-ibuffer-p
(ibuffer-update nil t))
(goto-char (point-min))
;; `ibuffer-forward-line` wraps around, we guard against it by
;; using the point of the first entry and make sure we abort as
;; soon as we encounter it for the second time.
(let ((first-point 0))
(while (> (point) first-point)
(let ((current-buf (ibuffer-current-buffer)))
;; We are only interested in buffers we can actually visit.
;; This filters out headings and other unusable entries.
(when (buffer-live-p current-buf)
(push
(cons
(buffer-substring-no-properties
(line-beginning-position)
(line-end-position))
current-buf)
entries)
;; Remember point of the first entry as we will wrap
;; around to it.
(when (= first-point 0)
(setq first-point (point)))))
(ibuffer-forward-line 1 t))))
(nreverse entries)))

(defun counsel-ibuffer-visit-buffer (x)
"Switch to buffer of candidate X."
(switch-to-buffer (cdr x)))

(defun counsel-ibuffer-visit-buffer-other-window (x)
"Switch to buffer of candidate X in other window."
(switch-to-buffer-other-window (cdr x)))

(defun counsel-ibuffer-visit-vanilla-ibuffer (_)
"Switch to vanilla ibuffer."
(switch-to-buffer counsel-ibuffer--buffer-name))

(ivy-set-actions
'counsel-ibuffer
'(("j" counsel-ibuffer-visit-buffer-other-window "other window")
("v" counsel-ibuffer-visit-vanilla-ibuffer "open vanilla ibuffer")))

(provide 'counsel)

;;; counsel.el ends here