For De Bruin, don't build a tree

* avy.el (avy--group-by): Remove.
(avy--path-alist-to-tree): Remove.
(avy-tree-de-bruijn): Remove.
(avy-read-de-bruijn): New defun.
(avy--process): Update.

Instead of building a tree (from a flat sequence) and traversing it,
just use the flat sequence.  This has the advantage of candidates being
in proper buffer-sequential order.

Re #51
Re #5
This commit is contained in:
Oleh Krehel 2015-05-26 15:40:21 +02:00
parent 27b98bb730
commit 55c77c5eb8

73
avy.el
View File

@ -223,40 +223,8 @@ SEQ-LEN is how many elements of KEYS it takes to identify a match."
lst (cdr lst)))))) lst (cdr lst))))))
(nreverse path-alist))) (nreverse path-alist)))
(defun avy--group-by (fn seq) (defun avy-read-de-bruijn (lst keys)
"Apply FN to each element of SEQ. "Select from LST dispatching on KEYS."
Separate the elements of SEQ into an alist using the results as
keys. Keys are compared using `equal'."
(let (alist)
(while seq
(let* ((el (pop seq))
(r (funcall fn el))
(entry (assoc r alist)))
(if entry
(setcdr entry (cons el (cdr entry)))
(push (list r el) alist))))
alist))
(defun avy--path-alist-to-tree (p-alist)
"Convert P-ALIST to the format of `avy-tree'."
(if (> (length (caar p-alist)) 1)
(mapcar (lambda (x)
(setcdr x (avy--path-alist-to-tree
(mapcar (lambda (c)
(cons (cdar c) (cdr c)))
(cdr x))))
x)
(avy--group-by #'caar p-alist))
(mapcar (lambda (x)
(cons (caar x)
(cons 'leaf (cdr x))))
p-alist)))
(defun avy-tree-de-bruijn (lst keys)
"Coerse LST into a tree.
The degree of the tree is the length of KEYS.
KEYS are placed on the internal nodes according to De Bruijn sequences.
LST elements should be of the form ((BEG . END) WND)."
;; In theory, the De Bruijn sequence B(k,n) has k^n subsequences of length n ;; In theory, the De Bruijn sequence B(k,n) has k^n subsequences of length n
;; (the path length) usable as paths, thus that's the lower bound. Due to ;; (the path length) usable as paths, thus that's the lower bound. Due to
;; partially overlapping matches, not all subsequences may be usable, so it's ;; partially overlapping matches, not all subsequences may be usable, so it's
@ -264,11 +232,31 @@ LST elements should be of the form ((BEG . END) WND)."
;; for x and a buffer contains xaxbxcx only every second subsequence is ;; for x and a buffer contains xaxbxcx only every second subsequence is
;; usable for the four matches. ;; usable for the four matches.
(let* ((path-len (ceiling (log (length lst) (length keys)))) (let* ((path-len (ceiling (log (length lst) (length keys))))
(path-alist (avy--path-alist-1 lst path-len keys))) (alist (avy--path-alist-1 lst path-len keys)))
(while (not path-alist) (while (not alist)
(cl-incf path-len) (cl-incf path-len)
(setq path-alist (avy--path-alist-1 lst path-len keys))) (setq alist (avy--path-alist-1 lst path-len keys)))
(avy--path-alist-to-tree path-alist))) (let* ((len (length (caar alist)))
(i 0))
(setq avy-current-path "")
(while (< i len)
(dolist (x (reverse alist))
(avy--overlay-at-full (reverse (car x)) (cdr x)))
(let ((char (read-char))
branch)
(avy--remove-leading-chars)
(setq alist
(delq nil
(mapcar (lambda (x)
(when (eq (caar x) char)
(cons (cdr (car x)) (cdr x))))
alist)))
(setq avy-current-path
(concat avy-current-path (string char)))
(cl-incf i)
(unless alist
(funcall avy-handler-function char))))
(cdar alist))))
(defun avy-tree (lst keys) (defun avy-tree (lst keys)
"Coerce LST into a balanced tree. "Coerce LST into a balanced tree.
@ -427,11 +415,12 @@ Use OVERLAY-FN to visualize the decision overlay."
(t (t
(avy--make-backgrounds (avy--make-backgrounds
(avy-window-list)) (avy-window-list))
(avy-read (if (eq avy-style 'de-bruijn) (if (eq avy-style 'de-bruijn)
(avy-tree-de-bruijn candidates avy-keys) (avy-read-de-bruijn
(avy-tree candidates avy-keys)) candidates avy-keys)
(avy-read (avy-tree candidates avy-keys)
overlay-fn overlay-fn
#'avy--remove-leading-chars))) #'avy--remove-leading-chars))))
(avy--done))) (avy--done)))
(defvar avy--overlays-back nil (defvar avy--overlays-back nil