]> code.delx.au - gnu-emacs-elpa/commitdiff
Merge commit '8d38a898f23b3105c5d098f0cfb6c3383547e394' from avy
authorOleh Krehel <ohwoeowho@gmail.com>
Thu, 25 Jun 2015 10:09:34 +0000 (12:09 +0200)
committerOleh Krehel <ohwoeowho@gmail.com>
Thu, 25 Jun 2015 10:09:34 +0000 (12:09 +0200)
1  2 
packages/avy/Makefile
packages/avy/README.md
packages/avy/avy.el
packages/avy/doc/Changelog.org
packages/avy/targets/avy-init.el

diff --combined packages/avy/Makefile
index 6e00ec314210920a6fc6e1eafe20476d2049891c,9303c7cf2a86776d9b7543549f7b0b5ca1d9f736..9303c7cf2a86776d9b7543549f7b0b5ca1d9f736
@@@ -5,7 -5,7 +5,7 @@@ LOAD = -l avy.el -l avy-test.e
  
  .PHONY: all test clean
  
- all: test
+ all: compile test
  
  test:
        $(emacs) -batch $(LOAD) -f ert-run-tests-batch-and-exit
diff --combined packages/avy/README.md
index 147998614a951e838e04cd1f3c514d56c0ab6568,9df0ce2fda3df84c6806c46007b3d7f70ec2bb95..9df0ce2fda3df84c6806c46007b3d7f70ec2bb95
@@@ -13,12 -13,12 +13,12 @@@ You can bind some of these useful comma
  > Input one char, jump to it with a tree.
  
  ```elisp
- (global-set-key (kbd "π") 'avy-goto-char)
+ (global-set-key (kbd "C-:") 'avy-goto-char)
  ```
  
- After <kbd>πb</kbd>:
+ After <kbd>C-: b</kbd>:
  
- ![avy-goto-char](http://oremacs.com/download/avi-goto-char.png)
+ ![avy-goto-char](https://raw.githubusercontent.com/wiki/nloyola/avy/images/avy-goto-char.png)
  
  ### `avy-goto-char-2`
  
@@@ -93,6 -93,8 +93,8 @@@ It will bind, for example, `avy-isearch
  
  See the comprehensive custom variable list on [the defcustom wiki page](https://github.com/abo-abo/avy/wiki/defcustom).
  
+ See how to write your own avy commands on [the custom-commands wiki page](https://github.com/abo-abo/avy/wiki/custom-commands).
  ## Contributing
  
  ### Copyright Assignment
diff --combined packages/avy/avy.el
index ce48da52e4de8f76bde758d9ea3bef9103544eac,a8a6a2524e742a972427d0ed19c067298f85679b..a8a6a2524e742a972427d0ed19c067298f85679b
--- 2/avy.el
@@@ -4,7 -4,7 +4,7 @@@
  
  ;; Author: Oleh Krehel <ohwoeowho@gmail.com>
  ;; URL: https://github.com/abo-abo/avy
- ;; Version: 0.2.1
+ ;; Version: 0.3.0
  ;; Package-Requires: ((emacs "24.1") (cl-lib "0.5"))
  ;; Keywords: point, location
  
                       (const avy-move-line))
            :value-type (repeat :tag "Keys" character)))
  
- (defcustom avy-style 'pre
+ (defcustom avy-style 'at-full
    "The default method of displaying the overlays.
  Use `avy-styles-alist' to customize this per-command."
    :type '(choice
            (const :tag "Pre" pre)
            (const :tag "At" at)
            (const :tag "At Full" at-full)
-           (const :tag "Post" post)))
+           (const :tag "Post" post)
+           (const :tag "De Bruijn" de-bruijn)))
  
  (defcustom avy-styles-alist nil
    "Alist of avy-jump commands to the style for each command.
@@@ -129,6 -130,15 +130,15 @@@ When nil, punctuation chars will not b
  \"[!-/:-@[-`{-~]\" will match all printable punctuation chars."
    :type 'regexp)
  
+ (defcustom avy-ignored-modes '(image-mode doc-view-mode pdf-view-mode)
+   "List of modes to ignore when searching for candidates.
+ Typically, these modes don't use the text representation.")
+ (defvar avy-translate-char-function #'identity
+   "Function to translate user input key into another key.
+ For example, to make SPC do the same as ?a, use
+ \(lambda (c) (if (= c 32) ?a c)).")
  (defface avy-lead-face-0
    '((t (:foreground "white" :background "#4f57f9")))
    "Face used for first non-terminating leading chars.")
      '((t (:foreground "white" :background "gray")))
    "Face used for matched leading chars.")
  
+ (defface avy-lead-face-2
+     '((t (:foreground "white" :background "#f86bf3")))
+   "Face used for leading chars.")
  (defface avy-lead-face
    '((t (:foreground "white" :background "#e52b50")))
    "Face used for the leading chars.")
    '((t (:foreground "gray40")))
    "Face for whole window background during selection.")
  
+ (defconst avy-lead-faces '(avy-lead-face
+                            avy-lead-face-0
+                            avy-lead-face-2
+                            avy-lead-face
+                            avy-lead-face-0
+                            avy-lead-face-2)
+   "Face sequence for `avy--overlay-at-full'.")
  ;;* Internals
  ;;** Tree
  (defmacro avy-multipop (lst n)
          (nthcdr (1- ,n) (prog1 ,lst (setq ,lst (nthcdr ,n ,lst))))
          nil))))
  
+ (defun avy--de-bruijn (keys n)
+   "De Bruijn sequence for alphabet KEYS and subsequences of length N."
+   (let* ((k (length keys))
+          (a (make-list (* n k) 0))
+          sequence)
+     (cl-labels ((db (T p)
+                   (if (> T n)
+                       (if (eq (% n p) 0)
+                           (setq sequence
+                                 (append sequence
+                                         (cl-subseq a 1 (1+ p)))))
+                     (setf (nth T a) (nth (- T p) a))
+                     (db (1+ T) p)
+                     (cl-loop for j from (1+ (nth (- T p) a)) to (1- k) do
+                              (setf (nth T a) j)
+                              (db (1+ T) T)))))
+       (db 1 1)
+       (mapcar (lambda (n)
+                 (nth n keys))
+               sequence))))
+ (defun avy--path-alist-1 (lst seq-len keys)
+   "Build a De Bruin sequence from LST.
+ SEQ-LEN is how many elements of KEYS it takes to identify a match."
+   (let ((db-seq (avy--de-bruijn keys seq-len))
+         prev-pos prev-seq prev-win path-alist)
+     ;; The De Bruijn seq is cyclic, so append the seq-len - 1 first chars to
+     ;; the end.
+     (setq db-seq (nconc db-seq (cl-subseq db-seq 0 (1- seq-len))))
+     (cl-labels ((subseq-and-pop ()
+                   (when (nth (1- seq-len) db-seq)
+                     (prog1 (cl-subseq db-seq 0 seq-len)
+                       (pop db-seq)))))
+       (while lst
+         (let* ((cur (car lst))
+                (pos (cond
+                       ;; ace-window has matches of the form (pos . wnd)
+                       ((integerp (car cur)) (car cur))
+                       ;; avy-jump have form ((start . end) . wnd)
+                       ((consp (car cur)) (caar cur))
+                       (t (error "Unexpected match representation: %s" cur))))
+                (win (cdr cur))
+                (path (if prev-pos
+                          (let ((diff (if (eq win prev-win)
+                                          (- pos prev-pos)
+                                        0)))
+                            (when (and (> diff 0) (< diff seq-len))
+                              (while (and (nth (1- seq-len) db-seq)
+                                          (not
+                                           (eq 0 (cl-search
+                                                  (cl-subseq prev-seq diff)
+                                                  (cl-subseq db-seq 0 seq-len)))))
+                                (pop db-seq)))
+                            (subseq-and-pop))
+                        (subseq-and-pop))))
+           (if (not path)
+               (setq lst nil
+                     path-alist nil)
+             (push (cons path (car lst)) path-alist)
+             (setq prev-pos pos
+                   prev-seq path
+                   prev-win win
+                   lst (cdr lst))))))
+     (nreverse path-alist)))
  (defun avy-tree (lst keys)
    "Coerce LST into a balanced tree.
  The degree of the tree is the length of KEYS.
@@@ -237,7 -324,7 +324,7 @@@ multiple DISPLAY-FN invokations.
                          (push (cons path leaf) avy--leafs)))
          (dolist (x avy--leafs)
            (funcall display-fn (car x) (cdr x))))
-       (let ((char (read-char))
+       (let ((char (funcall avy-translate-char-function (read-char)))
              branch)
          (funcall cleanup-fn)
          (if (setq branch (assoc char tree))
                      (concat avy-current-path (string char))))
            (funcall avy-handler-function char))))))
  
+ (defun avy-read-de-bruijn (lst keys)
+   "Select from LST dispatching on KEYS."
+   ;; 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
+   ;; partially overlapping matches, not all subsequences may be usable, so it's
+   ;; possible that the path-len must be incremented, e.g., if we're matching
+   ;; for x and a buffer contains xaxbxcx only every second subsequence is
+   ;; usable for the four matches.
+   (let* ((path-len (ceiling (log (length lst) (length keys))))
+          (alist (avy--path-alist-1 lst path-len keys)))
+     (while (not alist)
+       (cl-incf path-len)
+       (setq alist (avy--path-alist-1 lst path-len keys)))
+     (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 (funcall avy-translate-char-function (read-char))))
+           (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))))
  ;;** Rest
  (defun avy-window-list ()
    "Return a list of windows depending on `avy-all-windows'."
                              avy-all-windows)))
       (dolist (wnd (avy-window-list))
         (with-selected-window wnd
-          (unless (memq major-mode '(image-mode doc-view-mode))
+          (unless (memq major-mode avy-ignored-modes)
             ,@body)))))
  
  (defmacro avy--with-avy-keys (command &rest body)
@@@ -295,7 -416,11 +416,11 @@@ POS is either a position or (BEG . END)
          ((eq x 'exit))
  
          (t
-          (select-window (cdr x))
+          (let* ((window (cdr x))
+                 (frame (window-frame window)))
+            (unless (equal frame (selected-frame))
+              (select-frame-set-input-focus frame))
+            (select-window window))
           (let ((pt (car x)))
             (when (consp pt)
               (setq pt (car pt)))
@@@ -314,9 -439,12 +439,12 @@@ Use OVERLAY-FN to visualize the decisio
           (t
            (avy--make-backgrounds
             (avy-window-list))
-           (avy-read (avy-tree candidates avy-keys)
-                     overlay-fn
-                     #'avy--remove-leading-chars)))
+           (if (eq avy-style 'de-bruijn)
+               (avy-read-de-bruijn
+                candidates avy-keys)
+             (avy-read (avy-tree candidates avy-keys)
+                       overlay-fn
+                       #'avy--remove-leading-chars))))
      (avy--done)))
  
  (defvar avy--overlays-back nil
@@@ -453,19 -581,32 +581,32 @@@ LEAF is normally ((BEG . END) . WND).
           (beg (if (consp (car leaf))
                    (caar leaf)
                  (car leaf)))
-          (wnd (cdr leaf)))
-     (when (or avy-highlight-first (> (length str) 1))
-       (set-text-properties 0 1 '(face avy-lead-face-0) str))
+          (wnd (cdr leaf))
+          oov)
+     (dotimes (i len)
+       (set-text-properties (- len i 1) (- len i)
+                            `(face ,(nth i avy-lead-faces))
+                            str))
+     (when (eq avy-style 'de-bruijn)
+       (setq str (concat
+                  (propertize avy-current-path
+                              'face 'avy-lead-face-1)
+                  str))
+       (setq len (length str)))
      (with-selected-window wnd
        (save-excursion
          (goto-char beg)
-         (when (cl-some (lambda (o)
-                          (and (eq (overlay-get o 'category) 'avy)
-                               (eq (overlay-get o 'window) wnd)))
-                        (overlays-in (point) (min (+ (point) len)
-                                                  (line-end-position))))
-           (setq str (substring str 0 1))
-           (setq len 1))
+         (when (setq oov
+                     (delq nil
+                           (mapcar
+                            (lambda (o)
+                              (and (eq (overlay-get o 'category) 'avy)
+                                   (eq (overlay-get o 'window) wnd)
+                                   (overlay-start o)))
+                            (overlays-in (point) (min (+ (point) len)
+                                                      (line-end-position))))))
+           (setq len (- (apply #'min oov) beg))
+           (setq str (substring str 0 len)))
          (let ((other-ov (cl-find-if
                           (lambda (o)
                             (and (eq (overlay-get o 'category) 'avy)
@@@ -537,6 -678,7 +678,7 @@@ LEAF is normally ((BEG . END) . WND).
      (at #'avy--overlay-at)
      (at-full 'avy--overlay-at-full)
      (post #'avy--overlay-post)
+     (de-bruijn #'avy--overlay-at-full)
      (t (error "Unexpected style %S" style))))
  
  (defun avy--generic-jump (regex window-flip style)
@@@ -567,6 -709,20 +709,20 @@@ The window scope is determined by `avy-
       arg
       avy-style)))
  
+ ;;;###autoload
+ (defun avy-goto-char-in-line (char)
+   "Jump to the currently visible CHAR in the current line."
+   (interactive (list (read-char "char: ")))
+   (let ((avy-all-windows nil))
+     (avy--with-avy-keys avy-goto-char
+       (avy--goto
+        (avy--process
+         (save-restriction
+           (narrow-to-region (line-beginning-position)
+                             (line-end-position))
+           (avy--regex-candidates (regexp-quote (string char))))
+         (avy--style-fn avy-style))))))
  ;;;###autoload
  (defun avy-goto-char-2 (char1 char2 &optional arg)
    "Jump to the currently visible CHAR1 followed by CHAR2.
@@@ -589,7 -745,7 +745,7 @@@ The window scope is determined by `avy-
              (avy--regex-candidates isearch-string))
             (avy-background nil)
             (candidate
-             (avy--process candidates #'avy--overlay-post)))
+             (avy--process candidates (avy--style-fn avy-style))))
        (isearch-done)
        (avy--goto candidate))))
  
@@@ -613,7 -769,7 +769,7 @@@ The window scope is determined by `avy-
                           "\\.")
                          ((and avy-word-punc-regexp
                                (string-match avy-word-punc-regexp str))
-                          str)
+                          (regexp-quote str))
                          (t
                           (concat
                            "\\b"
@@@ -778,13 -934,14 +934,14 @@@ The window scope is determined by `avy-
    (interactive "P")
    (let ((c1 (read-char "char 1: "))
          (c2 (read-char "char 2: " nil avy-timeout-seconds)))
-     (avy--generic-jump
-      (regexp-quote
-       (if c2
-           (string c1 c2)
-         (string c1)))
-      arg
-      avy-style)))
+     (avy--with-avy-keys avy-goto-char-timer
+       (avy--generic-jump
+        (regexp-quote
+         (if c2
+             (string c1 c2)
+           (string c1)))
+        arg
+        avy-style))))
  
  (define-obsolete-variable-alias
      'avy-goto-char-style 'avy-style "0.1.0"
index 0000000000000000000000000000000000000000,7dbcdf10721e38662eb74955cb51373e2e76b2c6..7dbcdf10721e38662eb74955cb51373e2e76b2c6
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,211 +1,211 @@@
+ * 0.3.0
+ ** Fixes
+ *** Candidate window reversal
+ See [[https://github.com/abo-abo/avy/issues/27][#27]].
+ *** Jumping to newlines with =at-full= style
+ See [[https://github.com/abo-abo/avy/issues/5][#5]].
+ *** Stop =at-full= style from shifting text sometimes
+ See [[https://github.com/abo-abo/avy/issues/5][#5]].
+ *** Fix =at-full= interaction with tabs
+ When at a tab, visualize it using =tab-width= spaces.
+ See [[https://github.com/abo-abo/avy/issues/43][#43]].
+ *** Fix overlay issue when the same buffer is in two windows
+ See [[https://github.com/abo-abo/avy/issues/47][#47]] and http://debbugs.gnu.org/cgi/bugreport.cgi?bug=20607.
+ *** Quote punctuation chars
+ See [[https://github.com/abo-abo/avy/issues/63][#63]].
+ *** Update screenshot for =avy-goto-char= in README.md
+ Use ~C-:~ as the new suggested binding instead of the pi char.
+ See [[https://github.com/abo-abo/avy/issues/64][#64]].
+ ** New Features
+ *** =avy-goto-line= can now break into =goto-line=
+ Just enter a digit and you'll be transferred into =goto-line= prompt
+ with that digit already entered.  This means that you can just bind
+ ~M-g g~ to =avy-goto-line= without losing anything.
+ See [[https://github.com/abo-abo/avy/issues/29][#29]].
+ *** =avy-goto-line= now works with all kinds of overlay styles
+ Any of the following do something different now:
+ #+begin_src elisp
+ (setq avy-styles-alist
+       '((avy-goto-line . post)))
+ (setq avy-styles-alist
+       '((avy-goto-line . at)))
+ (setq avy-styles-alist
+       '((avy-goto-line . at-full)))
+ (setq avy-styles-alist
+       '((avy-goto-line . pre)))
+ #+end_src
+ See [[https://github.com/abo-abo/ace-link/issues/17][#17]].
+ *** New defcustom =avy-case-fold-search=
+ Non-nil when searches should ignore case, so e.g. =avy-goto-char= "b"
+ will match both "b" and "B". On by default. Use this to turn off this
+ behavior:
+ #+begin_src elisp
+ (setq avy-case-fold-search nil)
+ #+end_src
+ See [[https://github.com/abo-abo/avy/issues/34][#34]].
+ *** New command =avy-goto-word-or-subword-1=
+ Enter one char, and select a visible word or subword that starts with
+ it, depending on =subword-mode=. Move the point there.
+ See [[https://github.com/abo-abo/avy/issues/33][#33]].
+ *** =avy-move-line= should remove empty line after original one is moved
+ See [[https://github.com/abo-abo/avy/issues/40][#40]].
+ *** =avy-move-line= now takes a prefix arg
+ Use e.g. ~M-3~ before =avy-move-line= to move 3 lines at once.
+ *** Most commands can be used non-interactively
+ Example:
+ #+begin_src elisp
+ (defun avy-goto-lp ()
+   (interactive)
+   (avy-goto-char ?\())
+ #+end_src
+ This command only goes to the "(" character. This is actually very
+ similar to [[http://oremacs.com/lispy/#lispy-ace-paren][=lispy-ace-paren=]], except the implementation is only one
+ line.
+ See [[https://github.com/abo-abo/avy/issues/44][#44]].
+ *** (almost) all defcustoms are explained on the wiki
+ See [[https://github.com/abo-abo/avy/wiki/defcustom][the defcustom wiki page]].
+ *** Allow all operations to work across frames
+ You have to customize =avy-all-windows= for this. By default, it's set
+ to work on all windows on the current frame.
+ To make it work only on the current window, use:
+ #+begin_src elisp
+ (setq avy-all-windows nil)
+ #+end_src
+ To make it work on all frames, use:
+ #+begin_src elisp
+ (setq avy-all-windows 'all-frames)
+ #+end_src
+ *** New command =avy-goto-char-in-line=
+ This is =avy-goto-char= reduced only to the current line. Few
+ candidates means very short decision chars path.
+ See [[https://github.com/abo-abo/avy/issues/49][#49]].
+ *** New overlay style =de-bruijn=
+ How to use it:
+ #+begin_src elisp
+ (setq avy-style 'de-bruijn)
+ #+end_src
+ What it does: when your leading chars are clumped up together, it's
+ impossible to overlay the decision path without shifting the buffer
+ text a bit. For example, with the word "buffer", you =avy-goto-char= "b", and:
+ - the path for the first "f" is "aj"
+ - the path for the second "f" is "ak"
+ It's not possible to overlay 4 characters over "ff" in "buffer". But
+ to with =de-bruijn= style, which results in the path being "aj" and
+ "jk". It's possible to overlay "ajk" just fine.
+ Pros and cons of =de-bruijn= over other styles:
+ - a pro is that it's possible to display the full decision path for
+   clumped up chars, which is truncated for other styles
+ - a con is that the decision path is of the same length (e.g. 2 or 3)
+   for all candidates, while with other styles it's possible to have a
+   few candidets with a shorter path.
+ See [[https://github.com/abo-abo/avy/issues/51][#51]] and [[https://github.com/abo-abo/avy/issues/5][#5]].
+ *** New defcustom =avy-ignored-modes=
+ This is meant for visual modes like =doc-view-mode= or =image-mode=
+ that can have a huge number of chars in a single window. Which results
+ in a huge number of candidates even in other windows.
+ Current setting:
+ #+begin_src elisp
+ (setq avy-ignored-modes '(image-mode doc-view-mode pdf-view-mode))
+ #+end_src
+ See [[https://github.com/abo-abo/avy/issues/57][#57]].
+ *** New tutorial on writing custom commands
+ See the [[https://github.com/abo-abo/avy/wiki/custom-commands][the custom-commands wiki page]] and [[https://github.com/abo-abo/avy/issues/55][#55]].
+ *** New face setup
+ New variable =avy-lead-faces= will determine the faces used to color
+ the current decision depth you're in.  For example, if to select a
+ particular candidate you need to press "abc":
+ - "a" will be highlighted with a face that corresponds to depth 3
+ - "b" will be highlighted with a face that corresponds to depth 2
+ - "c" will be highlighted with a face that corresponds to depth 1
+ But if another candidate needs "ef":
+ - "e" will be highlighted with a face that corresponds to depth 2
+ - "f" will be highlighted with a face that corresponds to depth 1
+ See [[https://github.com/abo-abo/avy/issues/53][#53]].
+ *** New variable =avy-translate-char-function=
+ You can use this, for example, to interpret one character as another in =avy-keys=.
+ Example:
+ #+begin_src elisp
+ (setq avy-translate-char-function
+           (lambda (c) (if (= c 32) ?a c)))
+ #+end_src
+ This will translate ~SPC~ (32) into ~a~. So you can press either ~a~ or ~SPC~ to mean "a".
+ *** =avy-isearch= works for different styles
+ See [[https://github.com/abo-abo/avy/issues/61][#61]].
+ *** Switch the default style from =pre= to =at-full=
+ I've come to like =at-full= more than =pre= over time. The difference
+ is that =pre= hides no chars in your buffer, while =at-full= doesn't
+ shift text.
+ Use this to restore the previous default behavior:
+ #+begin_src elisp
+ (setq avy-style 'pre)
+ #+end_src
+ * trunk
+ ** Fixes
+ *** =avy-goto-char-timer= obeys =avy-styles-alist=
index 21dd0aba2902c6b76c0efd644dc49a090cea112d,9ce46bb7d13648306589d68dd6a7d2870687ce7d..9ce46bb7d13648306589d68dd6a7d2870687ce7d
  (add-to-list 'load-path default-directory)
  (mapc #'byte-compile-file '("avy.el"))
  (require 'avy)
- (require 'checkdoc)
- (with-current-buffer (find-file "avy.el")
-   (checkdoc-current-buffer t))
+ (if (fboundp 'checkdoc-file)
+     (checkdoc-file "avy.el")
+   (require 'checkdoc)
+   (with-current-buffer (find-file "avy.el")
+     (checkdoc-current-buffer t)))
  (global-set-key (kbd "C-c j") 'avy-goto-char)
  (global-set-key (kbd "C-'") 'avy-goto-char-2)