[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] master d81f079 54/68: Remove dependency on ace-jump-mode
From: |
Oleh Krehel |
Subject: |
[elpa] master d81f079 54/68: Remove dependency on ace-jump-mode |
Date: |
Sat, 21 Mar 2015 19:07:06 +0000 |
branch: master
commit d81f079ba5fd26886d067a518a83611876f5b877
Author: Oleh Krehel <address@hidden>
Commit: Oleh Krehel <address@hidden>
Remove dependency on ace-jump-mode
* avy.el: Add sub-package for building a completion tree.
* avy-test.el: Add.
* Makefile: Add.
* ace-window.el (ace-jump-mode): Don't require.
(avy): Require.
(aw-leading-char-face): Update.
(aw-background-face): New defface.
(aw-list-visual-area): Rename to `aw-window-list'. It returns simple
windows now, instead of visual area structs.
(aw-overlays-lead): New defvar.
(aw-overlays-back): New defvar.
(ace-window-mode): Use own minor mode, instead of `ace-jump-mode'.
(aw--done): Update.
(aw--lead-overlay): New defun.
(aw--make-leading-chars): New defun.
(aw--remove-leading-chars): New defun.
(aw--make-backgrounds): New defun.
(aw-select): Simplify.
(ace-window): Update doc.
(aw-visual-area<): Rename to `aw-window<'. It deals with simple windows
now.
---
Makefile | 14 +++
ace-window.el | 301 +++++++++++++++++++++++++++++----------------------------
avy-test.el | 42 ++++++++
avy.el | 82 ++++++++++++++++
4 files changed, 291 insertions(+), 148 deletions(-)
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..4f0a640
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,14 @@
+EMACS = emacs
+# EMACS = emacs-24.3
+
+LOAD = -l avy.el -l avy-test.el
+
+.PHONY: all test clean
+
+all: test
+
+test:
+ $(EMACS) -batch $(LOAD) -f ert-run-tests-batch-and-exit
+
+clean:
+ rm -f *.elc
diff --git a/ace-window.el b/ace-window.el
index a648cdd..a09f4a4 100644
--- a/ace-window.el
+++ b/ace-window.el
@@ -1,12 +1,11 @@
-;;; ace-window.el --- Quickly switch windows using `ace-jump-mode'. -*-
lexical-binding: t -*-
+;;; ace-window.el --- Quickly switch windows. -*- lexical-binding: t -*-
-;; Copyright (C) 2014 Oleh Krehel
+;; Copyright (C) 2014-2015 Oleh Krehel
;; Author: Oleh Krehel <address@hidden>
;; URL: https://github.com/abo-abo/ace-window
-;; Version: 0.7.0
-;; Package-Requires: ((ace-jump-mode "2.0"))
-;; Keywords: cursor, window, location
+;; Version: 0.8.0
+;; Keywords: window, location
;; This file is not part of GNU Emacs
@@ -25,15 +24,11 @@
;;; Commentary:
;;
-;; This package uses `ace-jump-mode' machinery to switch between
-;; windows.
-;;
;; The main function, `ace-window' is meant to replace `other-window'.
;; If fact, when there are only two windows present, `other-window' is
;; called. If there are more, each window will have its first
;; character highlighted. Pressing that character will switch to that
-;; window. Note that unlike `ace-jump-mode', the point position will
-;; not be changed: only current window focus changes.
+;; window.
;;
;; To setup this package, just add to your .emacs:
;;
@@ -60,7 +55,7 @@
;; deleted instead.
;;; Code:
-(require 'ace-jump-mode)
+(require 'avy)
;;* Customization
(defgroup ace-window nil
@@ -91,9 +86,16 @@ Use M-0 `ace-window' to toggle this value."
:type 'boolean)
(defface aw-leading-char-face
- '((t (:inherit ace-jump-face-foreground)))
+ '((((class color)) (:foreground "red"))
+ (((background dark)) (:foreground "gray100"))
+ (((background light)) (:foreground "gray0"))
+ (t (:foreground "gray100" :underline nil)))
"Face for each window's leading char.")
+(defface aw-background-face
+ '((t (:foreground "gray40")))
+ "Face for whole window background during selection.")
+
;;* Implementation
(defun aw-ignored-p (window)
"Return t if WINDOW should be ignored."
@@ -101,148 +103,151 @@ Use M-0 `ace-window' to toggle this value."
(member (buffer-name (window-buffer window))
aw-ignored-buffers)))
-(defun aw-list-visual-area ()
- "Forward to `ace-jump-list-visual-area', removing invisible frames."
- (cl-remove-if
- (lambda (x)
- (let ((f (aj-visual-area-frame x)))
- (or (not (and (frame-live-p f)
- (frame-visible-p f)))
- (string= "initial_terminal" (terminal-name f))
- (aw-ignored-p (aj-visual-area-window x)))))
- (ace-jump-list-visual-area)))
+(defun aw-window-list ()
+ "Return the list of interesting windows."
+ (sort
+ (cl-remove-if
+ (lambda (w)
+ (let ((f (window-frame w))
+ (b (window-buffer w)))
+ (or (not (and (frame-live-p f)
+ (frame-visible-p f)))
+ (string= "initial_terminal" (terminal-name f))
+ (aw-ignored-p w)
+ (with-current-buffer b
+ (and buffer-read-only
+ (= 0 (buffer-size b)))))))
+ (cl-case aw-scope
+ (global
+ (cl-mapcan #'window-list (frame-list)))
+ (frame
+ (window-list))
+ (t
+ (error "Invalid `aw-scope': %S" aw-scope))))
+ 'aw-window<))
-(defun aw--done ()
- "Clean up ace-jump overlays."
- ;; clean up mode line
- (setq ace-jump-current-mode nil)
- (setq ace-jump-mode nil)
- (force-mode-line-update)
+(defvar aw-overlays-lead nil
+ "Hold overlays for leading chars.")
- ;; delete background overlay
- (loop for ol in ace-jump-background-overlay-list
- do (delete-overlay ol))
- (setq ace-jump-background-overlay-list nil)
+(defvar aw-overlays-back nil
+ "Hold overlays for when `aw-background' is t.")
- ;; delete overlays in search tree
- (when ace-jump-search-tree
- (ace-jump-delete-overlay-in-search-tree ace-jump-search-tree)
- (setq ace-jump-search-tree nil)))
+(defvar ace-window-mode nil
+ "Minor mode during the selection process.")
+
+;; register minor mode
+(or (assq 'ace-window-mode minor-mode-alist)
+ (nconc minor-mode-alist
+ (list '(ace-window-mode ace-window-mode))))
+
+(defun aw--done ()
+ "Clean up mode line and overlays."
+ ;; mode line
+ (setq ace-window-mode nil)
+ (force-mode-line-update)
+ ;; background
+ (mapc #'delete-overlay aw-overlays-back)
+ (setq aw-overlays-back nil)
+ (aw--remove-leading-chars))
+
+(defun aw--lead-overlay (char pt wnd)
+ "Create an overlay with CHAR at PT in WND."
+ (let* ((ol (make-overlay pt (1+ pt) (window-buffer wnd)))
+ (old-str (with-selected-window wnd
+ (buffer-substring pt (1+ pt))))
+ (new-str
+ (format "%c%s"
+ char
+ (cond
+ ((string-equal old-str "\t")
+ (make-string (1- tab-width) ?\ ))
+ ((string-equal old-str "\n")
+ "\n")
+ (t
+ (make-string
+ (max 0 (1- (string-width old-str)))
+ ?\ ))))))
+ (overlay-put ol 'face 'aw-leading-char-face)
+ (overlay-put ol 'window wnd)
+ (overlay-put ol 'display new-str)
+ (push ol aw-overlays-lead)))
+
+(defun aw--make-leading-chars (tree &optional char)
+ "Create leading char overlays for TREE.
+CHAR is used to store the overlay char in the recursion."
+ (dolist (br tree)
+ (if (integerp (cadr br))
+ (aw--lead-overlay (or char (car br)) (cadr br) (cddr br))
+ (aw--make-leading-chars (cdr br) (or char (car br))))))
+
+(defun aw--remove-leading-chars ()
+ "Remove leading char overlays."
+ (mapc #'delete-overlay aw-overlays-lead)
+ (setq aw-overlays-lead nil))
+
+(defun aw--make-backgrounds (wnd-list)
+ "Create a dim background overlay for each window on WND-LIST."
+ (when aw-background
+ (setq aw-overlays-back
+ (mapcar (lambda (w)
+ (let ((ol (make-overlay
+ (window-start w)
+ (window-end w)
+ (window-buffer w))))
+ (overlay-put ol 'face 'aw-background-face)
+ ol))
+ wnd-list))))
(defun aw-select (mode-line)
"Return a selected other window.
Amend MODE-LINE to the mode line for the duration of the selection."
- (let* ((start-window (selected-window))
- (ace-jump-mode-scope aw-scope)
- (next-window-scope
- (cl-case aw-scope
- ('global 'visible)
- ('frame 'frame)))
- (visual-area-list
- (cl-remove-if
- (lambda (va)
- (let ((b (aj-visual-area-buffer va))
- (w (aj-visual-area-window va)))
- (or (with-current-buffer b
- (and buffer-read-only
- (= 0 (buffer-size b))))
- (aw-ignored-p w))))
- (sort (aw-list-visual-area) 'aw-visual-area<))))
- (cl-case (length visual-area-list)
- (0)
+ (let ((start-window (selected-window))
+ (next-window-scope (cl-case aw-scope
+ ('global 'visible)
+ ('frame 'frame)))
+ (wnd-list (aw-window-list))
+ final-window)
+ (cl-case (length wnd-list)
+ (0
+ start-window)
(1
- (select-window (aj-visual-area-window (car visual-area-list))))
+ (car wnd-list))
(2
- (select-window
- (next-window nil nil next-window-scope))
- (while (aw-ignored-p (selected-window))
- (select-window
- (next-window nil nil next-window-scope))))
+ (setq final-window (next-window nil nil next-window-scope))
+ (while (and (aw-ignored-p final-window)
+ (not (equal final-window start-window)))
+ (setq final-window (next-window final-window nil next-window-scope)))
+ final-window)
(t
- (let ((candidate-list
- (mapcar (lambda (va)
- (let ((b (aj-visual-area-buffer va)))
- ;; ace-jump-mode can't jump if the buffer is empty
- (when (= 0 (buffer-size b))
- (with-current-buffer b
- (insert " "))))
- (make-aj-position
- :offset
- (aw-offset (aj-visual-area-window va))
- :visual-area va))
- visual-area-list)))
- ;; create background for each visual area
- (if aw-background
- (setq ace-jump-background-overlay-list
- (loop for va in visual-area-list
- collect (let* ((w (aj-visual-area-window va))
- (b (aj-visual-area-buffer va))
- (ol (make-overlay (window-start w)
- (window-end w)
- b)))
- (overlay-put ol 'face
'ace-jump-face-background)
- ol))))
- ;; construct search tree and populate overlay into tree
- (setq ace-jump-search-tree
- (ace-jump-tree-breadth-first-construct
- (length candidate-list)
- (length aw-keys)))
- (let ((s (list ace-jump-search-tree)))
- (while s
- (let ((node (pop s)))
- (cond
- ((eq (car node) 'branch)
- ;; push all child node into stack
- (setq s (append (cdr node) s)))
- ((eq (car node) 'leaf)
- (let* ((p (pop candidate-list))
- (o (aj-position-offset p))
- (ol (make-overlay
- o (1+ o)
- (aj-position-buffer p))))
- ;; update leaf node to remember the ol
- (setf (cdr node) ol)
- (overlay-put ol 'face 'aw-leading-char-face)
- (overlay-put ol 'window (aj-position-window p))
- (overlay-put ol 'aj-data p)))
- (t
- (message "Failure in traversal"))))))
- (ace-jump-update-overlay-in-search-tree
- ace-jump-search-tree aw-keys)
- (setq ace-jump-mode mode-line)
+ (let* ((candidate-list
+ (mapcar (lambda (wnd)
+ ;; can't jump if the buffer is empty
+ (with-current-buffer (window-buffer wnd)
+ (when (= 0 (buffer-size))
+ (insert " ")))
+ (cons (aw-offset wnd) wnd))
+ wnd-list))
+ (avy-tree (avy-read candidate-list
+ aw-keys)))
+ (aw--make-backgrounds wnd-list)
+ (setq ace-window-mode mode-line)
(force-mode-line-update)
;; turn off helm transient map
(remove-hook 'post-command-hook 'helm--maybe-update-keymap)
- (unwind-protect
- (let (node)
- (catch 'done
- (while t
- (setq node (cl-position (read-char) aw-keys))
- (when node
- (setq node (nth node (cdr ace-jump-search-tree))))
- (cond ((null node)
- (message "No such position candidate.")
- (throw 'done nil))
-
- ((eq (car node) 'branch)
- (let ((old-tree ace-jump-search-tree))
- (setq ace-jump-search-tree
- (cons 'branch (cdr node)))
- (ace-jump-update-overlay-in-search-tree
- ace-jump-search-tree aw-keys)
- (setf (cdr node) nil)
- (ace-jump-delete-overlay-in-search-tree
old-tree)))
-
- ((eq (car node) 'leaf)
- (let ((aj-data (overlay-get (cdr node) 'aj-data)))
- (select-window (aj-position-window aj-data)))
- (throw 'done t))
-
- (t
- (error "[AceJump] Internal error: tree node type is
invalid"))))))
- (aw--done)))))
- (prog1 (selected-window)
- (select-window start-window))))
+ (or (catch 'done
+ (unwind-protect
+ (while avy-tree
+ (aw--make-leading-chars avy-tree)
+ (let ((char (read-char))
+ branch)
+ (aw--remove-leading-chars)
+ (if (setq branch (assoc char avy-tree))
+ (when (windowp (cdr (setq avy-tree (cdr branch))))
+ (throw 'done (cdr avy-tree)))
+ (message "No such position candidate.")
+ (throw 'done nil))))
+ (aw--done)))
+ start-window))))))
;;* Interactive
;;;###autoload
@@ -276,7 +281,7 @@ Amend MODE-LINE to the mode line for the duration of the
selection."
;;;###autoload
(defun ace-window (arg)
- "Select a window with function `ace-jump-mode'.
+ "Select a window.
Perform an action based on ARG described below.
By default, behaves like extended `other-window'.
@@ -299,14 +304,14 @@ window."
(t (ace-select-window))))
;;* Utility
-(defun aw-visual-area< (va1 va2)
- "Return true if visual area VA1 is less than VA2.
+(defun aw-window< (wnd1 wnd2)
+ "Return true if WND1 is less than WND2.
This is determined by their respective window coordinates.
Windows are numbered top down, left to right."
- (let ((f1 (aj-visual-area-frame va1))
- (f2 (aj-visual-area-frame va2))
- (e1 (window-edges (aj-visual-area-window va1)))
- (e2 (window-edges (aj-visual-area-window va2))))
+ (let ((f1 (window-frame wnd1))
+ (f2 (window-frame wnd2))
+ (e1 (window-edges wnd1))
+ (e2 (window-edges wnd2)))
(cond ((string< (frame-parameter f1 'window-id)
(frame-parameter f2 'window-id))
t)
diff --git a/avy-test.el b/avy-test.el
new file mode 100644
index 0000000..e9a0d2f
--- /dev/null
+++ b/avy-test.el
@@ -0,0 +1,42 @@
+(require 'ert)
+(require 'avy)
+
+(ert-deftest avy-subdiv ()
+ (should
+ (equal (avy-subdiv 5 4)
+ '(1 1 1 2)))
+ (should
+ (equal (avy-subdiv 10 4)
+ '(1 1 4 4)))
+ (should
+ (equal (avy-subdiv 16 4)
+ '(4 4 4 4)))
+ (should
+ (equal (avy-subdiv 17 4)
+ '(4 4 4 5)))
+ (should
+ (equal (avy-subdiv 27 4)
+ '(4 4 4 15)))
+ (should
+ (equal (avy-subdiv 50 4)
+ '(4 14 16 16)))
+ (should
+ (equal (avy-subdiv 65 4)
+ '(16 16 16 17))))
+
+(ert-deftest avy-read ()
+ (should
+ (equal
+ (avy-read '(0 1 2 3 4 5 6 7 8 9 10)
+ '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
+ '((97 . 0)
+ (115 . 1)
+ (100 . 2)
+ (102 . 3)
+ (103 . 4)
+ (104 . 5)
+ (106 . 6)
+ (107 . 7)
+ (108 (97 . 8)
+ (115 . 9)
+ (100 . 10))))))
diff --git a/avy.el b/avy.el
new file mode 100644
index 0000000..9ee4cce
--- /dev/null
+++ b/avy.el
@@ -0,0 +1,82 @@
+;;; avy.el --- set-based completion -*- lexical-binding: t -*-
+
+;; Copyright (C) 2015 Oleh Krehel
+
+;; Author: Oleh Krehel <address@hidden>
+;; Version: 0.1.0
+;; Keywords: completion
+
+;; This file is not part of GNU Emacs
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; For a full copy of the GNU General Public License
+;; see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Given a LIST and KEYS, `avy-read' will build a balanced tree of
+;; degree B, where B is the length of KEYS.
+;;
+;; The corresponding member of KEYS is placed in each internal node of
+;; the tree. The leafs are the members of LIST. They can be obtained
+;; in the original order by traversing the tree depth-first.
+
+;;; Code:
+
+(defmacro avy-multipop (lst n)
+ "Remove LST's first N elements and return them."
+ `(if (<= (length ,lst) ,n)
+ (prog1 ,lst
+ (setq ,lst nil))
+ (prog1 ,lst
+ (setcdr
+ (nthcdr (1- ,n) (prog1 ,lst (setq ,lst (nthcdr ,n ,lst))))
+ nil))))
+
+(defun avy-read (lst keys)
+ "Coerce LST into a balanced tree.
+The degree of the tree is the length of KEYS.
+KEYS are placed appropriately on internal nodes."
+ (let ((len (length keys)))
+ (cl-labels
+ ((rd (ls)
+ (let ((ln (length ls)))
+ (if (< ln len)
+ (cl-pairlis keys ls)
+ (let ((ks (copy-sequence keys))
+ res)
+ (dolist (s (avy-subdiv ln len))
+ (push (cons (pop ks)
+ (if (eq s 1)
+ (pop ls)
+ (rd (avy-multipop ls s))))
+ res))
+ (nreverse res))))))
+ (rd lst))))
+
+(defun avy-subdiv (n b)
+ "Distribute N in B terms in a balanced way."
+ (let* ((p (1- (floor (log n b))))
+ (x1 (expt b p))
+ (x2 (* b x1))
+ (delta (- n x2))
+ (n2 (/ delta (- x2 x1)))
+ (n1 (- b n2 1)))
+ (append
+ (make-list n1 x1)
+ (list
+ (- n (* n1 x1) (* n2 x2)))
+ (make-list n2 x2))))
+
+(provide 'avy)
+
+;;; avy.el ends here
- [elpa] master 8b5f10a 53/68: Update outlines, (continued)
- [elpa] master 8b5f10a 53/68: Update outlines, Oleh Krehel, 2015/03/21
- [elpa] master d7cafcb 56/68: avy-jump.el: add example commands using avy, Oleh Krehel, 2015/03/21
- [elpa] master fcc64ab 59/68: avy-jump.el (avi--regex-candidates): Add optional bounds, Oleh Krehel, 2015/03/21
- [elpa] master d932090 60/68: avy-jump.el (avi--overlay): Fix bug, Oleh Krehel, 2015/03/21
- [elpa] master f0050fb 62/68: avy.el (avy-read): Give a more precise error, Oleh Krehel, 2015/03/21
- [elpa] master 4e5ca87 58/68: avy-jump.el: Major update, Oleh Krehel, 2015/03/21
- [elpa] master ee0fa60 64/68: Add show keys on mode line feature., Oleh Krehel, 2015/03/21
- [elpa] master 30abc92 61/68: avy-jump.el (avi-goto-word-0): Simplify, Oleh Krehel, 2015/03/21
- [elpa] master a3d4817 63/68: Allow switching to the previous window, Oleh Krehel, 2015/03/21
- [elpa] master b83b941 65/68: Add `ace-window-display-mode' minor mode, Oleh Krehel, 2015/03/21
- [elpa] master d81f079 54/68: Remove dependency on ace-jump-mode,
Oleh Krehel <=
- [elpa] master 2580bf9 67/68: ace-window.el (aw-mode-line-face): Inherit from mode-line-buffer-id, Oleh Krehel, 2015/03/21
- [elpa] master 22a3145 66/68: Make sure not to extend `mode-line-format' twice, Oleh Krehel, 2015/03/21
- [elpa] master b11606c 68/68: Add 'packages/ace-window/' from commit '2580bf9bd7f66ed4e923a125ee8efcc4b6a043e0', Oleh Krehel, 2015/03/21