├── README.md └── ace-jump-buffer.el /README.md: -------------------------------------------------------------------------------- 1 | [![MELPA](http://melpa.org/packages/ace-jump-buffer-badge.svg)](http://melpa.org/#/ace-jump-buffer) 2 | [![MELPA Stable](http://stable.melpa.org/packages/ace-jump-buffer-badge.svg)](http://stable.melpa.org/#/ace-jump-buffer) 3 | 4 | ## Ace Jump Buffer 5 | 6 | `ace-jump-buffer` is an extension for 7 | [`avy`](https://github.com/abo-abo/avy) and the native `bs` buffer 8 | menu that lets you hop to Emacs buffers in 2-3 key strokes. 9 | 10 | Alternately, you might be interested in this package’s spiritual 11 | successor - 12 | [`frog-jump-buffer`](https://github.com/waymondo/frog-jump-buffer) - 13 | which is a newer, similar package that is more performant and 14 | flexible. 15 | 16 | ### Installation 17 | 18 | Install from [MELPA](melpa.milkbox.net) with `package-install ace-jump-buffer`, or drop `ace-jump-buffer.el`, `avy.el`, and [`dash.el`](https://github.com/magnars/dash.el) into your load path. 19 | 20 | ### Commands 21 | 22 | #### `(ace-jump-buffer)` 23 | Open the buffer menu and go to the selected buffer in the current window. 24 | 25 | #### `(ace-jump-buffer-with-configuration)` 26 | Select a `bs-configuration`, then show its buffer menu and go to the selected buffer. 27 | 28 | #### `(ace-jump-buffer-other-window)` 29 | Open the buffer menu and go to the selected buffer in other window. 30 | 31 | #### `(ace-jump-buffer-in-one-window)` 32 | Open the buffer menu and go to the selected buffer in full window. 33 | 34 | #### `(ace-jump-same-mode-buffers)` 35 | Show a menu of buffers of the same mode as the current buffer. 36 | 37 | #### `(ace-jump-persp-buffers)` 38 | Show a menu of buffers in the current perspective (`persp-mode` required.). 39 | 40 | #### `(ace-jump-projectile-buffers)` 41 | Show a menu of buffers in the current project (`projectile` required.). 42 | 43 | ### Variables 44 | 45 | #### `ajb-max-window-height` 46 | The max window height for the buffer menu. The default is 20. 47 | 48 | #### `ajb-sort-function` 49 | The function for sorting buffers in the menu. Options: 50 | 51 | * `nil`: Use the default `(buffer-list)` ordering [default] 52 | * `'bs--sort-by-recentf` 53 | * `'bs--sort-by-name` 54 | * `'bs--sort-by-size` 55 | * `'bs--sort-by-filename` 56 | * `'bs--sort-by-mode` 57 | 58 | #### `ajb-bs-configuration` 59 | The `bs` configuration to use when displaying the menu with 60 | `ace-jump-buffer`. Options: 61 | 62 | * `"all"`: Show all buffers [default] 63 | * `"persp"`: If you use 64 | [`perspective`](https://github.com/nex3/perspective-el) or [`persp-mode`](https://github.com/Bad-ptr/persp-mode.el), you may set 65 | this to scope the buffer list to your current perspective. 66 | * `"projectile"`: If you use 67 | [`projectile`](https://github.com/bbatsov/projectile), you may set 68 | this to scope the buffer list to your current project. 69 | 70 | #### `ajb-style` 71 | The method of displaying the overlays for `ace-jump-buffer`. 72 | Defaults to `'at-full` which is the default value of `avy`. 73 | 74 | ### Macro 75 | 76 | `(make-ace-jump-buffer-function)` takes two variables: a string name and the body of a buffer rejection filter function. 77 | 78 | For example, if you wanted an `ace-jump-buffer` function for pulling up your `*shell-mode*` buffers: 79 | 80 | ``` elisp 81 | (make-ace-jump-buffer-function "shell" 82 | (with-current-buffer buffer 83 | (not (eq major-mode 'shell-mode)))) 84 | ``` 85 | 86 | This would create a `bs-configurations` option named "shell" and a callable defun named `(ace-jump-shell-buffers)`. 87 | 88 | ### Changelog 89 | 90 | *0.4* - Changed the internal jumping library from `ace-jump-mode` to 91 | `avy`. `ajb-home-row-keys` was depreciated as the default `avy-keys` 92 | are set to the lower-cased home-row keys. 93 | 94 | *0.3* - Introduced a macro for easily making custom `ace-jump-buffer` 95 | filters and interactive functions 96 | -------------------------------------------------------------------------------- /ace-jump-buffer.el: -------------------------------------------------------------------------------- 1 | ;;; ace-jump-buffer.el --- fast buffer switching extension to `avy' -*- lexical-binding: t -*- 2 | ;; 3 | ;; Copyright 2013-2015 Justin Talbott 4 | ;; 5 | ;; Author: Justin Talbott 6 | ;; URL: https://github.com/waymondo/ace-jump-buffer 7 | ;; Version: 0.4.1 8 | ;; Package-Requires: ((avy "0.4.0") (dash "2.4.0")) 9 | ;; License: GNU General Public License version 3, or (at your option) any later version 10 | 11 | ;;; Commentary: 12 | ;; 13 | ;; (require 'ace-jump-buffer) 14 | ;; then bind `ace-jump-buffer' to something useful 15 | ;; 16 | ;;; Code: 17 | 18 | (require 'bs) 19 | (require 'avy) 20 | (require 'recentf) 21 | (require 'dash) 22 | 23 | (defgroup ace-jump-buffer nil 24 | "Fast buffer switching extension to `avy'." 25 | :version "0.4.0" 26 | :link '(url-link "https://github.com/waymondo/ace-jump-buffer") 27 | :group 'convenience) 28 | 29 | (defcustom ajb-max-window-height 20 30 | "Maximal window height of Ace Jump Buffer Selection Menu." 31 | :group 'ace-jump-buffer 32 | :type 'integer) 33 | 34 | (defcustom ajb-sort-function nil 35 | "The `bs-sort-function' function used when displaying `ace-jump-buffer'." 36 | :group 'ace-jump-buffer 37 | :type '(radio (const :tag "No custom sorting" nil) 38 | (function-item bs--sort-by-recentf) 39 | (function-item bs--sort-by-name) 40 | (function-item bs--sort-by-size) 41 | (function-item bs--sort-by-filename) 42 | (function-item bs--sort-by-mode) 43 | (function :tag "Other function"))) 44 | 45 | (defcustom ajb-bs-configuration "all" 46 | "The `bs-configuration' used when displaying `ace-jump-buffer'." 47 | :group 'ace-jump-buffer) 48 | 49 | (defface ajb-face '((t :background unspecified :foreground unspecified)) 50 | "Customizable face to use within the `ace-jump-buffer' menu. The default is unspecified." 51 | :group 'ace-jump-buffer) 52 | 53 | (defcustom ajb-style 'at-full 54 | "The default method of displaying the overlays for `ace-jump-buffer'." 55 | :type '(choice 56 | (const :tag "Pre" pre) 57 | (const :tag "At" at) 58 | (const :tag "At Full" at-full) 59 | (const :tag "Post" post) 60 | (const :tag "De Bruijn" de-bruijn) 61 | (const :tag "Words" words))) 62 | 63 | ;; interval settings 64 | (defvar ajb/showing nil) 65 | (defvar ajb/other-window nil) 66 | (defvar ajb/in-one-window nil) 67 | (defvar ajb/configuration-history nil) 68 | 69 | ;; settings for a barebones `bs' switcher 70 | (defvar ajb/bs-attributes-list '(("" 2 2 left " ") 71 | ("" 1 1 left bs--get-marked-string) 72 | ("" 1 1 left " ") 73 | ("Buffer" bs--get-name-length 10 left bs--get-name))) 74 | 75 | (defun ajb/bs--show-header--around (oldfun) 76 | "Don't show the `bs' header when doing `ace-jump-buffer'." 77 | (unless ajb/showing (funcall oldfun))) 78 | 79 | (advice-add 'bs--show-header :around 'ajb/bs--show-header--around) 80 | 81 | (defun ajb/bs-set-configuration--after (name) 82 | "Set `bs-buffer-sort-function' to the value of `ajb-sort-function'." 83 | (when ajb/showing (setq bs-buffer-sort-function ajb-sort-function))) 84 | 85 | (advice-add 'bs-set-configuration :after 'ajb/bs-set-configuration--after) 86 | 87 | (defun bs--sort-by-recentf (b1 b2) 88 | "Sort function for comparing buffers `B1' and `B2' by recentf order." 89 | (let ((b1-index (-elem-index (buffer-file-name b1) recentf-list)) 90 | (b2-index (-elem-index (buffer-file-name b2) recentf-list))) 91 | (when (and b1-index b2-index (< b1-index b2-index)) t))) 92 | 93 | (defun ajb/select-buffer () 94 | "On the end of ace jump, select the buffer at the current line." 95 | (when (string-match (buffer-name) "*buffer-selection*") 96 | (if ajb/other-window (bs-select-other-window) 97 | (if ajb/in-one-window (bs-select-in-one-window) 98 | (bs-select))))) 99 | 100 | (defun ajb/kill-bs-menu () 101 | "Exit and kill the `bs' window on an invalid character." 102 | (bs-kill) 103 | (when (get-buffer "*buffer-selection*") 104 | (kill-buffer "*buffer-selection*"))) 105 | 106 | (defun ajb/exit (_char) 107 | "Exit and kill the `bs' window on an invalid character, throw done message." 108 | (ajb/kill-bs-menu) 109 | (throw 'done nil)) 110 | 111 | (defun ajb/goto-line-and-buffer () 112 | "Goto visible line below the cursor and visit the associated buffer." 113 | (interactive) 114 | (let ((avy-all-windows nil) 115 | (r (avy--line 116 | nil (line-beginning-position 1) 117 | (window-end (selected-window) t)))) 118 | (if (or (stringp r) (not r)) 119 | (ajb/kill-bs-menu) 120 | (unless (eq r t) 121 | (avy-action-goto r) 122 | (ajb/select-buffer))))) 123 | 124 | ;;;###autoload 125 | (defun ace-jump-buffer () 126 | "Quickly hop to buffer with `avy'." 127 | (interactive) 128 | (let ((avy-background nil) 129 | (avy-all-windows nil) 130 | (bs-attributes-list ajb/bs-attributes-list) 131 | (avy-handler-function 'ajb/exit) 132 | (avy-style ajb-style) 133 | (ajb/showing t)) 134 | (save-excursion 135 | (bs--show-with-configuration ajb-bs-configuration) 136 | (set (make-local-variable 'bs-header-lines-length) 0) 137 | (set (make-local-variable 'bs-max-window-height) ajb-max-window-height) 138 | (face-remap-add-relative 'default 'ajb-face) 139 | (goto-char (point-min)) 140 | (bs--set-window-height) 141 | (ajb/goto-line-and-buffer)))) 142 | 143 | ;;;###autoload 144 | (defun ace-jump-buffer-other-window () 145 | "Quickly hop to buffer with `avy' in other window." 146 | (interactive) 147 | (let ((ajb/other-window t)) 148 | (ace-jump-buffer))) 149 | 150 | ;;;###autoload 151 | (defun ace-jump-buffer-in-one-window () 152 | "Quickly hop to buffer with `avy' in one window." 153 | (interactive) 154 | (let ((ajb/in-one-window t)) 155 | (ace-jump-buffer))) 156 | 157 | ;;;###autoload 158 | (defun ace-jump-buffer-with-configuration () 159 | "Quickly hop to buffer with `avy' with selected configuration." 160 | (interactive) 161 | (let* ((name (completing-read "Ace jump buffer with configuration: " 162 | (--map (car it) bs-configurations) nil t nil 163 | 'ajb/configuration-history 164 | (car ajb/configuration-history))) 165 | (ajb-bs-configuration name)) 166 | (ace-jump-buffer))) 167 | 168 | ;;;###autoload 169 | (defmacro make-ace-jump-buffer-function (name &rest buffer-list-reject-filter) 170 | "Create a `bs-configuration' and interactive defun using `NAME'. 171 | 172 | It will displays buffers that don't get rejected by the body of 173 | `BUFFER-LIST-REJECT-FILTER'." 174 | (declare (indent 1)) 175 | (let ((filter-defun-name (intern (format "ajb/filter-%s-buffers" name))) 176 | (defun-name (intern (format "ace-jump-%s-buffers" name)))) 177 | `(progn 178 | (defun ,filter-defun-name (buffer) 179 | ,@buffer-list-reject-filter) 180 | (defun ,defun-name () 181 | (interactive) 182 | (let ((ajb-bs-configuration ,name)) 183 | (ace-jump-buffer))) 184 | (add-to-list 'bs-configurations 185 | '(,name nil nil nil ,filter-defun-name nil))))) 186 | 187 | (make-ace-jump-buffer-function "same-mode" 188 | (let ((current-mode major-mode)) 189 | (with-current-buffer buffer 190 | (not (eq major-mode current-mode))))) 191 | 192 | (when (require 'perspective nil 'noerror) 193 | (make-ace-jump-buffer-function "persp" 194 | (with-current-buffer buffer 195 | (not (member buffer (persp-buffers persp-curr)))))) 196 | 197 | (when (require 'persp-mode nil 'noerror) 198 | (make-ace-jump-buffer-function "persp" 199 | (with-current-buffer buffer 200 | (not (memq buffer (persp-buffer-list)))))) 201 | 202 | (when (require 'projectile nil 'noerror) 203 | (make-ace-jump-buffer-function "projectile" 204 | (let ((project-root (projectile-project-root))) 205 | (with-current-buffer buffer 206 | (not (projectile-project-buffer-p buffer project-root)))))) 207 | 208 | (provide 'ace-jump-buffer) 209 | ;;; ace-jump-buffer.el ends here 210 | --------------------------------------------------------------------------------