From e9a17f94c4244e809223245e7063ef8c0613b57f Mon Sep 17 00:00:00 2001 From: Andreas Gerler Date: Tue, 14 Jan 2014 11:05:18 +0100 Subject: [PATCH] added ace-jump-mode Signed-off-by: Andreas Gerler --- ace-jump-mode.el | 1106 ++++++++++++++++++++++++++++++++++ ace-jump-mode.elc | Bin 0 -> 47322 bytes cl-lib-0.3.el => cl-lib.el | 0 cl-lib-0.3.elc => cl-lib.elc | Bin init.el | 3 + 5 files changed, 1109 insertions(+) create mode 100644 ace-jump-mode.el create mode 100644 ace-jump-mode.elc rename cl-lib-0.3.el => cl-lib.el (100%) rename cl-lib-0.3.elc => cl-lib.elc (100%) diff --git a/ace-jump-mode.el b/ace-jump-mode.el new file mode 100644 index 00000000..43a938ed --- /dev/null +++ b/ace-jump-mode.el @@ -0,0 +1,1106 @@ +;;; ace-jump-mode.el --- a quick cursor location minor mode for emacs -*- coding: utf-8-unix -*- + +;; Copyright (C) 2012 Free Software Foundation, Inc. + +;; Author : winterTTr +;; URL : https://github.com/winterTTr/ace-jump-mode/ +;; Version : 2.0.RC +;; Keywords : motion, location, cursor + +;; This file is part of GNU Emacs. + +;; GNU Emacs 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 of the License, or +;; (at your option) any later version. + +;; GNU Emacs 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. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;;; INTRODUCTION +;; + +;; What's this? +;; +;; It is a minor mode for Emacs. It can help you to move your cursor +;; to ANY position in emacs by using only 3 times key press. + +;; Where does ace jump mode come from ? +;; +;; I firstly see such kind of moving style is in a vim plugin called +;; EasyMotion. It really attract me a lot. So I decide to write +;; one for Emacs and MAKE IT BETTER. +;; +;; So I want to thank to : +;; Bartlomiej P. for his PreciseJump +;; Kim Silkebækken for his EasyMotion + + +;; What's ace-jump-mode ? +;; +;; ace-jump-mode is an fast/direct cursor location minor mode. It will +;; create the N-Branch search tree internal and marks all the possible +;; position with predefined keys in within the whole emacs view. +;; Allowing you to move to the character/word/line almost directly. +;; + +;;; Usage +;; +;; Add the following code to your init file, of course you can select +;; the key that you prefer to. +;; ---------------------------------------------------------- +;; ;; +;; ;; ace jump mode major function +;; ;; +;; (add-to-list 'load-path "/full/path/where/ace-jump-mode.el/in/") +;; (autoload +;; 'ace-jump-mode +;; "ace-jump-mode" +;; "Emacs quick move minor mode" +;; t) +;; ;; you can select the key you prefer to +;; (define-key global-map (kbd "C-c SPC") 'ace-jump-mode) +;; +;; ;; +;; ;; enable a more powerful jump back function from ace jump mode +;; ;; +;; (autoload +;; 'ace-jump-mode-pop-mark +;; "ace-jump-mode" +;; "Ace jump back:-)" +;; t) +;; (eval-after-load "ace-jump-mode" +;; '(ace-jump-mode-enable-mark-sync)) +;; (define-key global-map (kbd "C-x SPC") 'ace-jump-mode-pop-mark) +;; +;; ;;If you use viper mode : +;; (define-key viper-vi-global-user-map (kbd "SPC") 'ace-jump-mode) +;; ;;If you use evil +;; (define-key evil-normal-state-map (kbd "SPC") 'ace-jump-mode) +;; ---------------------------------------------------------- + +;;; For more information +;; Intro Doc: https://github.com/winterTTr/ace-jump-mode/wiki +;; FAQ : https://github.com/winterTTr/ace-jump-mode/wiki/AceJump-FAQ + +;;; Code: + +(require 'cl) + +;;;; ============================================ +;;;; Utilities for ace-jump-mode +;;;; ============================================ + +;; --------------------- +;; aj-position +;; --------------------- + +;; make a position in a visual area +(defstruct aj-position offset visual-area) + +(defmacro aj-position-buffer (aj-pos) + "Get the buffer object from `aj-position'." + `(aj-visual-area-buffer (aj-position-visual-area ,aj-pos))) + +(defmacro aj-position-window (aj-pos) + "Get the window object from `aj-position'." + `(aj-visual-area-window (aj-position-visual-area ,aj-pos))) + +(defmacro aj-position-frame (aj-pos) + "Get the frame object from `aj-position'." + `(aj-visual-area-frame (aj-position-visual-area ,aj-pos))) + +(defmacro aj-position-recover-buffer (aj-pos) + "Get the recover-buffer object from `aj-position'." + `(aj-visual-area-recover-buffer (aj-position-visual-area ,aj-pos))) + + + +;; --------------------- +;; aj-visual-area +;; --------------------- + +;; a record for all the possible visual area +;; a visual area is a window that showing some buffer in some frame. +(defstruct aj-visual-area buffer window frame recover-buffer) + + +;; --------------------- +;; a FIFO queue implementation +;; --------------------- +(defstruct aj-queue head tail) + +(defun aj-queue-push (item q) + "enqueue" + (let ( (head (aj-queue-head q) ) + (tail (aj-queue-tail q) ) + (c (list item) ) ) + (cond + ((null (aj-queue-head q)) + (setf (aj-queue-head q) c) + (setf (aj-queue-tail q) c)) + (t + (setf (cdr (aj-queue-tail q)) c) + (setf (aj-queue-tail q) c))))) + +(defun aj-queue-pop (q) + "dequeue" + (if (null (aj-queue-head q)) + (error "[AceJump] Interal Error: Empty queue")) + + (let ((ret (aj-queue-head q))) + (if (eq ret (aj-queue-tail q)) + ;; only one item left + (progn + (setf (aj-queue-head q) nil) + (setf (aj-queue-tail q) nil)) + ;; multi item left, move forward the head + (setf (aj-queue-head q) (cdr ret))) + (car ret))) + + + +;;; main code start here + +;; register as a minor mode +(or (assq 'ace-jump-mode minor-mode-alist) + (nconc minor-mode-alist + (list '(ace-jump-mode ace-jump-mode)))) + +;; custoize variable +(defvar ace-jump-word-mode-use-query-char t + "If we need to ask for the query char before enter `ace-jump-word-mode'") + +(defvar ace-jump-mode-case-fold case-fold-search + "If non-nil, the ace-jump mode will ignore case. + +The default value is set to the same as `case-fold-search'.") + +(defvar ace-jump-mode-mark-ring nil + "The list that is used to store the history for jump back.") + +(defvar ace-jump-mode-mark-ring-max 100 + "The max length of `ace-jump-mode-mark-ring'") + + +(defvar ace-jump-mode-gray-background t + "By default, when there is more than one candidate, the ace +jump mode will gray the background and then mark the possible +candidate position. Set this to nil means do not gray +background.") + +(defvar ace-jump-mode-scope 'global + "Define what is the scope that ace-jump-mode works. + +Now, there three kind of values for this: +1. 'global : ace jump can work across any window and frame, this is also the default. +2. 'frame : ace jump will work for the all windows in current frame. +3. 'window : ace jump will only work on current window only. + This is the same behavior for 1.0 version.") + +(defvar ace-jump-mode-detect-punc t + "When this is non-nil, the ace jump word mode will detect the +char that is not alpha or number. Then, if the query char is a +printable punctuaction, we will use char mode to start the ace +jump mode. If it is nil, an error will come up when +non-alpha-number is given under word mode.") + + +(defvar ace-jump-mode-submode-list + '(ace-jump-word-mode + ace-jump-char-mode + ace-jump-line-mode) + "*The mode list when start ace jump mode. +The sequence is the calling sequence when give prefix argument. + +Such as: + If you use the default sequence, which is + '(ace-jump-word-mode + ace-jump-char-mode + ace-jump-line-mode) +and using key to start up ace jump mode, such as 'C-c SPC', +then the usage to start each mode is as below: + + C-c SPC ==> ace-jump-word-mode + C-u C-c SPC ==> ace-jump-char-mode + C-u C-u C-c SPC ==> ace-jump-line-mode + +Currently, the valid submode is: + `ace-jump-word-mode' + `ace-jump-char-mode' + `ace-jump-line-mode' + +") + +(defvar ace-jump-mode-move-keys + (nconc (loop for i from ?a to ?z collect i) + (loop for i from ?A to ?Z collect i)) + "*The keys that used to move when enter AceJump mode. +Each key should only an printable character, whose name will +fill each possible location. + +If you want your own moving keys, you can custom that as follow, +for example, you only want to use lower case character: +\(setq ace-jump-mode-move-keys (loop for i from ?a to ?z collect i)) ") + + +;;; some internal variable for ace jump +(defvar ace-jump-mode nil + "AceJump minor mode.") +(defvar ace-jump-background-overlay-list nil + "Background overlay which will grey all the display.") +(defvar ace-jump-search-tree nil + "N-branch Search tree. Every leaf node holds the overlay that +is used to highlight the target positions.") +(defvar ace-jump-query-char nil + "Save the query char used between internal mode.") +(defvar ace-jump-current-mode nil + "Save the current mode. +See `ace-jump-mode-submode-list' for possible value.") + +(defvar ace-jump-recover-visual-area-list nil + "Save the ace jump aj-visual-area structure list. + +Sometimes, the different window may display the same buffer. For +this case, we need to create a indirect buffer for them to make +ace jump overlay can work across the differnt window with the +same buffer. When ace jump ends, we need to recover the window to +its original buffer.") +(defvar ace-jump-sync-emacs-mark-ring nil + "When this variable is not-nil, everytime `ace-jump-mode-pop-mark' is called, +ace jump will try to remove the same mark from buffer local mark +ring and global-mark-ring, which help you to sync the mark +information between emacs and ace jump. + +Note, never try to set this variable manually, this is for ace +jump internal use. If you want to change it, use +`ace-jump-mode-enable-mark-sync' or +`ace-jump-mode-disable-mark-sync'.") + +(defgroup ace-jump nil + "ace jump group" + :group 'convenience) + +;;; define the face +(defface ace-jump-face-background + '((t (:foreground "gray40"))) + "Face for background of AceJump motion" + :group 'ace-jump) + + +(defface ace-jump-face-foreground + '((((class color)) (:foreground "red")) + (((background dark)) (:foreground "gray100")) + (((background light)) (:foreground "gray0")) + (t (:foreground "gray100"))) + "Face for foreground of AceJump motion" + :group 'ace-jump) + + +(defvar ace-jump-mode-before-jump-hook nil + "Function(s) to call just before moving the cursor to a selected match") + +(defvar ace-jump-mode-end-hook nil + "Function(s) to call when ace-jump-mode is going to end up") + +(defvar ace-jump-allow-invisible nil + "Control if ace-jump should select the invisible char as candidate. +Normally, the ace jump mark cannot be seen if the target character is invisible. +So default to be nil, which will not include those invisible character as candidate.") + + +(defun ace-jump-char-category ( query-char ) + "Detect the type of the char. +For the ascii table, refer to http://www.asciitable.com/ + +There is four possible return value: +1. 'digit: the number character +2. 'alpha: A-Z and a-z +3. 'punc : all the printable punctuaiton +4. 'other: all the others" + (cond + ;; digit + ((and (>= query-char #x30) (<= query-char #x39)) + 'digit) + ((or + ;; capital letter + (and (>= query-char #x41) (<= query-char #x5A)) + ;; lowercase letter + (and (>= query-char #x61) (<= query-char #x7A))) + 'alpha) + ((or + ;; tab + (equal query-char #x9) + ;; punc before digit + (and (>= query-char #x20) (<= query-char #x2F)) + ;; punc after digit before capital letter + (and (>= query-char #x3A) (<= query-char #x40)) + ;; punc after capital letter before lowercase letter + (and (>= query-char #x5B) (<= query-char #x60)) + ;; punc after lowercase letter + (and (>= query-char #x7B) (<= query-char #x7E))) + 'punc) + (t + 'other))) + + +(defun ace-jump-search-candidate (re-query-string visual-area-list) + "Search the RE-QUERY-STRING in current view, and return the candidate position list. +RE-QUERY-STRING should be an valid regex used for `search-forward-regexp'. + +You can control whether use the case sensitive or not by `ace-jump-mode-case-fold'. + +Every possible `match-beginning' will be collected. +The returned value is a list of `aj-position' record." + (loop for va in visual-area-list + append (let* ((current-window (aj-visual-area-window va)) + (start-point (window-start current-window)) + (end-point (window-end current-window t))) + (with-selected-window current-window + (save-excursion + (goto-char start-point) + (let ((case-fold-search ace-jump-mode-case-fold)) + (loop while (re-search-forward re-query-string nil t) + until (or + (> (point) end-point) + (eobp)) + if (or ace-jump-allow-invisible (not (invisible-p (match-beginning 0)))) + collect (make-aj-position :offset (match-beginning 0) + :visual-area va) + ;; when we use "^" to search line mode, + ;; re-search-backward will not move one + ;; char after search success, as line + ;; begin is not a valid visible char. + ;; We need to help it to move forward. + do (if (string-equal re-query-string "^") + (goto-char (1+ (match-beginning 0))))))))))) + +(defun ace-jump-tree-breadth-first-construct (total-leaf-node max-child-node) + "Constrct the search tree, each item in the tree is a cons cell. +The (car tree-node) is the type, which should be only 'branch or 'leaf. +The (cdr tree-node) is data stored in a leaf when type is 'leaf, +while a child node list when type is 'branch" + (let ((left-leaf-node (- total-leaf-node 1)) + (q (make-aj-queue)) + (node nil) + (root (cons 'leaf nil)) ) + ;; we push the node into queue and make candidate-sum -1, so + ;; create the start condition for the while loop + (aj-queue-push root q) + (while (> left-leaf-node 0) + (setq node (aj-queue-pop q)) + ;; when a node is picked up from stack, it will be changed to a + ;; branch node, we lose a leaft node + (setf (car node) 'branch) + ;; so we need to add the sum of leaf nodes that we wish to create + (setq left-leaf-node (1+ left-leaf-node)) + (if (<= left-leaf-node max-child-node) + ;; current child can fill the left leaf + (progn + (setf (cdr node) + (loop for i from 1 to left-leaf-node + collect (cons 'leaf nil))) + ;; so this should be the last action for while + (setq left-leaf-node 0)) + ;; the child can not cover the left leaf + (progn + ;; fill as much as possible. Push them to queue, so it have + ;; the oppotunity to become 'branch node if necessary + (setf (cdr node) + (loop for i from 1 to max-child-node + collect (let ((n (cons 'leaf nil))) + (aj-queue-push n q) + n))) + (setq left-leaf-node (- left-leaf-node max-child-node))))) + ;; return the root node + root)) + +(defun ace-jump-tree-preorder-traverse (tree &optional leaf-func branch-func) + "we move over tree via preorder, and call BRANCH-FUNC on each branch +node and call LEAF-FUNC on each leaf node" + ;; use stack to do preorder traverse + (let ((s (list tree))) + (while (not (null s)) + ;; pick up one from stack + (let ((node (car s))) + ;; update stack + (setq s (cdr s)) + (cond + ((eq (car node) 'branch) + ;; a branch node + (when branch-func + (funcall branch-func node)) + ;; push all child node into stack + (setq s (append (cdr node) s))) + ((eq (car node) 'leaf) + (when leaf-func + (funcall leaf-func node))) + (t + (message "[AceJump] Internal Error: invalid tree node type"))))))) + + +(defun ace-jump-populate-overlay-to-search-tree (tree candidate-list) + "Populate the overlay to search tree, every leaf will give one overlay" + + (lexical-let* (;; create the locally dynamic variable for the following function + (position-list candidate-list) + + ;; make the function to create overlay for each leaf node, + ;; here we only create each overlay for each candidate + ;; position, , but leave the 'display property to be empty, + ;; which will be fill in "update-overlay" function + (func-create-overlay (lambda (node) + (let* ((p (car position-list)) + (offset (aj-position-offset p)) + (va (aj-position-visual-area p)) + (w (aj-visual-area-window va)) + (b (aj-visual-area-buffer va)) + ;; create one char overlay + (ol (make-overlay offset (1+ offset) b))) + ;; update leaf node to remember the ol + (setf (cdr node) ol) + (overlay-put ol 'face 'ace-jump-face-foreground) + ;; associate the aj-position data with overlay + ;; so that we can use it to do the final jump + (overlay-put ol 'aj-data p) + ;; next candidate node + (setq position-list (cdr position-list)))))) + (ace-jump-tree-preorder-traverse tree func-create-overlay) + tree)) + + +(defun ace-jump-delete-overlay-in-search-tree (tree) + "Delete all the overlay in search tree leaf node" + (let ((func-delete-overlay (lambda (node) + (delete-overlay (cdr node)) + (setf (cdr node) nil)))) + (ace-jump-tree-preorder-traverse tree func-delete-overlay))) + +(defun ace-jump-buffer-substring (pos) + "Get the char under the POS, which is aj-position structure." + (let* ((w (aj-position-window pos)) + (offset (aj-position-offset pos))) + (with-selected-window w + (buffer-substring offset (1+ offset))))) + +(defun ace-jump-update-overlay-in-search-tree (tree keys) + "Update overlay 'display property using each name in keys" + (lexical-let* (;; create dynamic variable for following function + (key ?\0) + ;; populdate each leaf node to be the specific key, + ;; this only update 'display' property of overlay, + ;; so that user can see the key from screen and select + (func-update-overlay + (lambda (node) + (let ((ol (cdr node))) + (overlay-put + ol + 'display + (concat (make-string 1 key) + (let* ((pos (overlay-get ol 'aj-data)) + (subs (ace-jump-buffer-substring pos))) + (cond + ;; when tab, we use more space to prevent screen + ;; from messing up + ((string-equal subs "\t") + (make-string (1- tab-width) ? )) + ;; when enter, we need to add one more enter + ;; to make the screen not change + ((string-equal subs "\n") + "\n") + (t + ""))))))))) + (loop for k in keys + for n in (cdr tree) + do (progn + ;; update "key" variable so that the function can use + ;; the correct context + (setq key k) + (if (eq (car n) 'branch) + (ace-jump-tree-preorder-traverse n + func-update-overlay) + (funcall func-update-overlay n)))))) + + + +(defun ace-jump-list-visual-area() + "Based on `ace-jump-mode-scope', search the possible buffers that is showing now." + (cond + ((eq ace-jump-mode-scope 'global) + (loop for f in (frame-list) + append (loop for w in (window-list f) + collect (make-aj-visual-area :buffer (window-buffer w) + :window w + :frame f)))) + ((eq ace-jump-mode-scope 'frame) + (loop for w in (window-list (selected-frame)) + collect (make-aj-visual-area :buffer (window-buffer w) + :window w + :frame (selected-frame)))) + ((eq ace-jump-mode-scope 'window) + (list + (make-aj-visual-area :buffer (current-buffer) + :window (selected-window) + :frame (selected-frame)))) + (t + (error "[AceJump] Invalid ace-jump-mode-scope, please check your configuration")))) + + +(defun ace-jump-mode-make-indirect-buffer (visual-area-list) + "When the differnt window show the same buffer. The overlay +cannot work for same buffer at the same time. So the indirect +buffer need to create to make overlay can work correctly. + +VISUAL-AREA-LIST is aj-visual-area list. This function will +return the structure list for those make a indirect buffer. + +Side affect: All the created indirect buffer will show in its +relevant window." + (loop for va in visual-area-list + ;; check if the current visual-area (va) has the same buffer with + ;; the previous ones (vai) + if (loop for vai in visual-area-list + ;; stop at itself, don't need to find the ones behind it (va) + until (eq vai va) + ;; if the buffer is same, return those(vai) before + ;; it(va) so that we know the some visual area has + ;; the same buffer with current one (va) + if (eq (aj-visual-area-buffer va) + (aj-visual-area-buffer vai)) + collect vai) + ;; if indeed the same one find, we need create an indirect buffer + ;; to current visual area(va) + collect (with-selected-window (aj-visual-area-window va) + ;; store the orignal buffer + (setf (aj-visual-area-recover-buffer va) + (aj-visual-area-buffer va)) + ;; create indirect buffer to use as working buffer + (setf (aj-visual-area-buffer va) + (clone-indirect-buffer nil nil)) + ;; update window to the indirect buffer + (let ((ws (window-start))) + (set-window-buffer (aj-visual-area-window va) + (aj-visual-area-buffer va)) + (set-window-start + (aj-visual-area-window va) + ws)) + va))) + + +(defun ace-jump-do( re-query-string ) + "The main function to start the AceJump mode. +QUERY-STRING should be a valid regexp string, which finally pass to `search-forward-regexp'. + +You can constrol whether use the case sensitive via `ace-jump-mode-case-fold'. +" + ;; we check the move key to make it valid, cause it can be customized by user + (if (or (null ace-jump-mode-move-keys) + (< (length ace-jump-mode-move-keys) 2) + (not (every #'characterp ace-jump-mode-move-keys))) + (error "[AceJump] Invalid move keys: check ace-jump-mode-move-keys")) + ;; search candidate position + (let* ((visual-area-list (ace-jump-list-visual-area)) + (candidate-list (ace-jump-search-candidate re-query-string visual-area-list))) + (cond + ;; cannot find any one + ((null candidate-list) + (setq ace-jump-current-mode nil) + (error "[AceJump] No one found")) + ;; we only find one, so move to it directly + ((eq (cdr candidate-list) nil) + (ace-jump-push-mark) + (run-hooks 'ace-jump-mode-before-jump-hook) + (ace-jump-jump-to (car candidate-list)) + (message "[AceJump] One candidate, move to it directly") + (run-hooks 'ace-jump-mode-end-hook)) + ;; more than one, we need to enter AceJump mode + (t + ;; make indirect buffer for those windows that show the same buffer + (setq ace-jump-recover-visual-area-list + (ace-jump-mode-make-indirect-buffer visual-area-list)) + ;; create background for each visual area + (if ace-jump-mode-gray-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 ace-jump-mode-move-keys))) + (ace-jump-populate-overlay-to-search-tree ace-jump-search-tree + candidate-list) + (ace-jump-update-overlay-in-search-tree ace-jump-search-tree + ace-jump-mode-move-keys) + + ;; do minor mode configuration + (cond + ((eq ace-jump-current-mode 'ace-jump-char-mode) + (setq ace-jump-mode " AceJump - Char")) + ((eq ace-jump-current-mode 'ace-jump-word-mode) + (setq ace-jump-mode " AceJump - Word")) + ((eq ace-jump-current-mode 'ace-jump-line-mode) + (setq ace-jump-mode " AceJump - Line")) + (t + (setq ace-jump-mode " AceJump"))) + (force-mode-line-update) + + + ;; override the local key map + (setq overriding-local-map + (let ( (map (make-keymap)) ) + (dolist (key-code ace-jump-mode-move-keys) + (define-key map (make-string 1 key-code) 'ace-jump-move)) + (define-key map (kbd "C-c C-c") 'ace-jump-quick-exchange) + (define-key map [t] 'ace-jump-done) + map)) + + (add-hook 'mouse-leave-buffer-hook 'ace-jump-done) + (add-hook 'kbd-macro-termination-hook 'ace-jump-done))))) + + +(defun ace-jump-jump-to (position) + "Jump to the POSITION, which is a `aj-position' structure storing the position information" + (let ((offset (aj-position-offset position)) + (frame (aj-position-frame position)) + (window (aj-position-window position)) + (buffer (aj-position-buffer position))) + ;; focus to the frame + (if (and (frame-live-p frame) + (not (eq frame (selected-frame)))) + (select-frame-set-input-focus (window-frame window))) + + ;; select the correct window + (if (and (window-live-p window) + (not (eq window (selected-window)))) + (select-window window)) + + ;; swith to buffer + (if (and (buffer-live-p buffer) + (not (eq buffer (window-buffer window)))) + (switch-to-buffer buffer)) + ;; move to correct position + + (if (and (buffer-live-p buffer) + (eq (current-buffer) buffer)) + (goto-char offset)))) + +(defun ace-jump-push-mark () + "Push the current position information onto the `ace-jump-mode-mark-ring'." + ;; add mark to the emacs basic push mark + (push-mark (point) t) + ;; we also push the mark on the `ace-jump-mode-mark-ring', which has + ;; more information for better jump back + (let ((pos (make-aj-position :offset (point) + :visual-area (make-aj-visual-area :buffer (current-buffer) + :window (selected-window) + :frame (selected-frame))))) + (setq ace-jump-mode-mark-ring (cons pos ace-jump-mode-mark-ring))) + ;; when exeed the max count, discard the last one + (if (> (length ace-jump-mode-mark-ring) ace-jump-mode-mark-ring-max) + (setcdr (nthcdr (1- ace-jump-mode-mark-ring-max) ace-jump-mode-mark-ring) nil))) + + +;;;###autoload +(defun ace-jump-mode-pop-mark () + "Pop up a postion from `ace-jump-mode-mark-ring', and jump back to that position" + (interactive) + ;; we jump over the killed buffer position + (while (and ace-jump-mode-mark-ring + (not (buffer-live-p (aj-position-buffer + (car ace-jump-mode-mark-ring))))) + (setq ace-jump-mode-mark-ring (cdr ace-jump-mode-mark-ring))) + + (if (null ace-jump-mode-mark-ring) + ;; no valid history exist + (error "[AceJump] No more history")) + + (if ace-jump-sync-emacs-mark-ring + (let ((p (car ace-jump-mode-mark-ring))) + ;; if we are jump back in the current buffer, that means we + ;; only need to sync the buffer local mark-ring + (if (eq (current-buffer) (aj-position-buffer p)) + (if (equal (aj-position-offset p) (marker-position (mark-marker))) + ;; if the current marker is the same as where we need + ;; to jump back, we do the same as pop-mark actually, + ;; copy implementation from pop-mark, cannot use it + ;; directly, as there is advice on it + (when mark-ring + (setq mark-ring (nconc mark-ring (list (copy-marker (mark-marker))))) + (set-marker (mark-marker) (+ 0 (car mark-ring)) (current-buffer)) + (move-marker (car mark-ring) nil) + (setq mark-ring (cdr mark-ring)) + (deactivate-mark)) + + ;; But if there is other marker put before the wanted destination, the following scenario + ;; + ;; +---+---+---+---+ +---+---+---+---+ + ;; Mark Ring | 2 | 3 | 4 | 5 | | 2 | 4 | 5 | 3 | + ;; +---+---+---+---+ +---+---+---+---+ + ;; +---+ +---+ + ;; Marker | 1 | | 1 | <-- Maker (not changed) + ;; +---+ +---+ + ;; +---+ +---+ + ;; Cursor | X | Pop up AJ mark 3 | 3 | <-- Cursor position + ;; +---+ +---+ + ;; +---+---+---+ +---+---+---+ + ;; AJ Ring | 3 | 4 | 5 | | 4 | 5 | 3 | + ;; +---+---+---+ +---+---+---+ + ;; + ;; So what we need to do, is put the found mark in mark-ring to the end + (lexical-let ((po (aj-position-offset p))) + (setq mark-ring + (ace-jump-move-first-to-end-if mark-ring + (lambda (x) + (equal (marker-position x) po)))))) + + + ;; when we jump back to another buffer, do as the + ;; pop-global-mark does. But we move the marker with the + ;; same target buffer to the end, not always the first one + (lexical-let ((pb (aj-position-buffer p))) + (setq global-mark-ring + (ace-jump-move-first-to-end-if global-mark-ring + (lambda (x) + (eq (marker-buffer x) pb)))))))) + + + ;; move the first element to the end of the ring + (ace-jump-jump-to (car ace-jump-mode-mark-ring)) + (setq ace-jump-mode-mark-ring (nconc (cdr ace-jump-mode-mark-ring) + (list (car ace-jump-mode-mark-ring))))) + +(defun ace-jump-quick-exchange () + "The function that we can use to quick exhange the current mode between +word-mode and char-mode" + (interactive) + (cond + ((eq ace-jump-current-mode 'ace-jump-char-mode) + (if ace-jump-query-char + ;; ace-jump-done will clean the query char, so we need to save it + (let ((query-char ace-jump-query-char)) + (ace-jump-done) + (ace-jump-word-mode query-char)))) + ((eq ace-jump-current-mode 'ace-jump-word-mode) + (if ace-jump-query-char + ;; ace-jump-done will clean the query char, so we need to save it + (let ((query-char ace-jump-query-char)) + (ace-jump-done) + ;; restore the flag + (ace-jump-char-mode query-char)))) + ((eq ace-jump-current-mode 'ace-jump-line-mode) + nil) + (t + nil))) + + + + +;;;###autoload +(defun ace-jump-char-mode (query-char) + "AceJump char mode" + (interactive (list (read-char "Query Char:"))) + + ;; We should prevent recursion call this function. This can happen + ;; when you trigger the key for ace jump again when already in ace + ;; jump mode. So we stop the previous one first. + (if ace-jump-current-mode (ace-jump-done)) + + (if (eq (ace-jump-char-category query-char) 'other) + (error "[AceJump] Non-printable character")) + + ;; others : digit , alpha, punc + (setq ace-jump-query-char query-char) + (setq ace-jump-current-mode 'ace-jump-char-mode) + (ace-jump-do (regexp-quote (make-string 1 query-char)))) + + +;;;###autoload +(defun ace-jump-word-mode (head-char) + "AceJump word mode. +You can set `ace-jump-word-mode-use-query-char' to nil to prevent +asking for a head char, that will mark all the word in current +buffer." + (interactive (list (if ace-jump-word-mode-use-query-char + (read-char "Head Char:") + nil))) + + ;; We should prevent recursion call this function. This can happen + ;; when you trigger the key for ace jump again when already in ace + ;; jump mode. So we stop the previous one first. + (if ace-jump-current-mode (ace-jump-done)) + + (cond + ((null head-char) + ;; \< - start of word + ;; \sw - word constituent + (ace-jump-do "\\<\\sw")) + ((memq (ace-jump-char-category head-char) + '(digit alpha)) + (setq ace-jump-query-char head-char) + (setq ace-jump-current-mode 'ace-jump-word-mode) + (ace-jump-do (concat "\\<" (make-string 1 head-char)))) + ((eq (ace-jump-char-category head-char) + 'punc) + ;; we do not query punctuation under word mode + (if (null ace-jump-mode-detect-punc) + (error "[AceJump] Not a valid word constituent")) + ;; we will use char mode to continue search + (setq ace-jump-query-char head-char) + (setq ace-jump-current-mode 'ace-jump-char-mode) + (ace-jump-do (regexp-quote (make-string 1 head-char)))) + (t + (error "[AceJump] Non-printable character")))) + + +;;;###autoload +(defun ace-jump-line-mode () + "AceJump line mode. +Marked each no empty line and move there" + (interactive) + + ;; We should prevent recursion call this function. This can happen + ;; when you trigger the key for ace jump again when already in ace + ;; jump mode. So we stop the previous one first. + (if ace-jump-current-mode (ace-jump-done)) + + (setq ace-jump-current-mode 'ace-jump-line-mode) + (ace-jump-do "^")) + +;;;###autoload +(defun ace-jump-mode(&optional prefix) + "AceJump mode is a minor mode for you to quick jump to a +position in the curret view. + There is three submode now: + `ace-jump-char-mode' + `ace-jump-word-mode' + `ace-jump-line-mode' + +You can specify the sequence about which mode should enter +by customize `ace-jump-mode-submode-list'. + +If you do not want to query char for word mode, you can change +`ace-jump-word-mode-use-query-char' to nil. + +If you don't like the default move keys, you can change it by +setting `ace-jump-mode-move-keys'. + +You can constrol whether use the case sensitive via +`ace-jump-mode-case-fold'. +" + (interactive "p") + (let ((index (/ prefix 4)) + (submode-list-length (length ace-jump-mode-submode-list))) + (if (< index 0) + (error "[AceJump] Invalid prefix command")) + (if (>= index submode-list-length) + (setq index (1- submode-list-length))) + (call-interactively (nth index ace-jump-mode-submode-list)))) + +(defun ace-jump-move () + "move cursor based on user input" + (interactive) + (let* ((index (let ((ret (position (aref (this-command-keys) 0) + ace-jump-mode-move-keys))) + (if ret ret (length ace-jump-mode-move-keys)))) + (node (nth index (cdr ace-jump-search-tree)))) + (cond + ;; we do not find key in search tree. This can happen, for + ;; example, when there is only three selections in screen + ;; (totally five move-keys), but user press the forth move key + ((null node) + (message "No such position candidate.") + (ace-jump-done)) + ;; this is a branch node, which means there need further + ;; selection + ((eq (car node) 'branch) + (let ((old-tree ace-jump-search-tree)) + ;; we use sub tree in next move, create a new root node + ;; whose child is the sub tree nodes + (setq ace-jump-search-tree (cons 'branch (cdr node))) + (ace-jump-update-overlay-in-search-tree ace-jump-search-tree + ace-jump-mode-move-keys) + + ;; this is important, we need remove the subtree first before + ;; do delete, we set the child nodes to nil + (setf (cdr node) nil) + (ace-jump-delete-overlay-in-search-tree old-tree))) + ;; if the node is leaf node, this is the final one + ((eq (car node) 'leaf) + ;; need to save aj data, as `ace-jump-done' will clean it + (let ((aj-data (overlay-get (cdr node) 'aj-data))) + (ace-jump-done) + (ace-jump-push-mark) + (run-hooks 'ace-jump-mode-before-jump-hook) + (ace-jump-jump-to aj-data)) + (run-hooks 'ace-jump-mode-end-hook)) + (t + (ace-jump-done) + (error "[AceJump] Internal error: tree node type is invalid"))))) + + + +(defun ace-jump-done() + "stop AceJump motion" + (interactive) + ;; clear the status flag + (setq ace-jump-query-char nil) + (setq ace-jump-current-mode nil) + + ;; clean the status line + (setq ace-jump-mode nil) + (force-mode-line-update) + + ;; delete background overlay + (loop for ol in ace-jump-background-overlay-list + do (delete-overlay ol)) + (setq ace-jump-background-overlay-list nil) + + + ;; we clean the indirect buffer + (loop for va in ace-jump-recover-visual-area-list + do (with-selected-window (aj-visual-area-window va) + (let ((fake-buffer (aj-visual-area-buffer va)) + (original-buffer (aj-visual-area-recover-buffer va))) + ;; recover display buffer + (set-window-buffer (aj-visual-area-window va) + original-buffer) + ;; update visual area, which we need to use it to do the + ;; final jump, and as well, save in history + (setf (aj-visual-area-buffer va) original-buffer) + (setf (aj-visual-area-recover-buffer va) nil) + ;; kill indirect buffer + (ace-jump-kill-buffer fake-buffer)))) + + ;; delete overlays in search tree + (ace-jump-delete-overlay-in-search-tree ace-jump-search-tree) + (setq ace-jump-search-tree nil) + + (setq overriding-local-map nil) + + (remove-hook 'mouse-leave-buffer-hook 'ace-jump-done) + (remove-hook 'kbd-macro-termination-hook 'ace-jump-done)) + +(defun ace-jump-kill-buffer(buffer) + "Utility function to kill buffer for ace jump mode. +We also need to handle the buffer which has clients on it" + (if (and (boundp 'server-buffer-clients) + server-buffer-clients) + (server-buffer-done buffer t)) + (kill-buffer buffer)) + +;;;; ============================================ +;;;; advice to sync emacs mark ring +;;;; ============================================ + +(defun ace-jump-move-to-end-if ( l pred ) + "Move all the element in a list to the end of list if it make +the PRED to return non-nil. + +PRED is a function object which can pass to funcall and accept +one argument, which will be every element in the list. +Such as : (lambda (x) (equal x 1)) " + (let (true-list false-list) + (loop for e in l + do (if (funcall pred e) + (setq true-list (cons e true-list)) + (setq false-list (cons e false-list)))) + (nconc (nreverse false-list) + (and true-list (nreverse true-list))))) + +(defun ace-jump-move-first-to-end-if (l pred) + "Only move the first found one to the end of list" + (lexical-let ((pred pred) + found) + (ace-jump-move-to-end-if l + (lambda (x) + (if found + nil + (setq found (funcall pred x))))))) + + + +(defadvice pop-mark (before ace-jump-pop-mark-advice) + "When `pop-mark' is called to jump back, this advice will sync the mark ring. +Move the same position to the end of `ace-jump-mode-mark-ring'." + (lexical-let ((mp (mark t)) + (cb (current-buffer))) + (if mp + (setq ace-jump-mode-mark-ring + (ace-jump-move-first-to-end-if ace-jump-mode-mark-ring + (lambda (x) + (and (equal (aj-position-offset x) mp) + (eq (aj-position-buffer x) cb)))))))) + + +(defadvice pop-global-mark (before ace-jump-pop-global-mark-advice) + "When `pop-global-mark' is called to jump back, this advice will sync the mark ring. +Move the aj-position with the same buffer to the end of `ace-jump-mode-mark-ring'." + (interactive) + ;; find the one that will be jump to + (let ((index global-mark-ring)) + ;; refer to the implementation of `pop-global-mark' + (while (and index (not (marker-buffer (car index)))) + (setq index (cdr index))) + (if index + ;; find the mark + (lexical-let ((mb (marker-buffer (car index)))) + (setq ace-jump-mode-mark-ring + (ace-jump-move-to-end-if ace-jump-mode-mark-ring + (lambda (x) + (eq (aj-position-buffer x) mb)))))))) + + +(defun ace-jump-mode-enable-mark-sync () + "Enable the sync funciton between ace jump mode mark ring and emacs mark ring. + +1. This function will enable the advice which activate on +`pop-mark' and `pop-global-mark'. These advice will remove the +same marker from `ace-jump-mode-mark-ring' when user use +`pop-mark' or `global-pop-mark' to jump back. + +2. Set variable `ace-jump-sync-emacs-mark-ring' to t, which will +sync mark information with emacs mark ring. " + (ad-enable-advice 'pop-mark 'before 'ace-jump-pop-mark-advice) + (ad-activate 'pop-mark) + (ad-enable-advice 'pop-global-mark 'before 'ace-jump-pop-global-mark-advice) + (ad-activate 'pop-global-mark) + (setq ace-jump-sync-emacs-mark-ring t)) + +(defun ace-jump-mode-disable-mark-sync () + "Disable the sync funciton between ace jump mode mark ring and emacs mark ring. + +1. This function will diable the advice which activate on +`pop-mark' and `pop-global-mark'. These advice will remove the +same marker from `ace-jump-mode-mark-ring' when user use +`pop-mark' or `global-pop-mark' to jump back. + +2. Set variable `ace-jump-sync-emacs-mark-ring' to nil, which +will stop synchronizing mark information with emacs mark ring. " + (ad-disable-advice 'pop-mark 'before 'ace-jump-pop-mark-advice) + (ad-activate 'pop-mark) + (ad-disable-advice 'pop-global-mark 'before 'ace-jump-pop-global-mark-advice) + (ad-activate 'pop-global-mark) + (setq ace-jump-sync-emacs-mark-ring nil)) + + +(provide 'ace-jump-mode) + +;;; ace-jump-mode.el ends here + +;; Local Variables: +;; byte-compile-warnings: (not cl-functions) +;; End: diff --git a/ace-jump-mode.elc b/ace-jump-mode.elc new file mode 100644 index 0000000000000000000000000000000000000000..6ad44280010a62cdd88a44789a7665d337f3c9c8 GIT binary patch literal 47322 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 TKNQY+#$)|y?kts{mD2wQC;iga literal 0 HcmV?d00001 diff --git a/cl-lib-0.3.el b/cl-lib.el similarity index 100% rename from cl-lib-0.3.el rename to cl-lib.el diff --git a/cl-lib-0.3.elc b/cl-lib.elc similarity index 100% rename from cl-lib-0.3.elc rename to cl-lib.elc diff --git a/init.el b/init.el index e98c9983..248da8b5 100644 --- a/init.el +++ b/init.el @@ -27,6 +27,9 @@ load-path)) (require 'htmlize ) +(require 'ace-jump-mode) +(define-key global-map (kbd "C-c SPC") 'ace-jump-mode) + (ido-mode t) (setq ido-enable-prefix nil ido-enable-flex-matching t -- 2.47.3