------------------------------------------------------------
revno: 384
committer: Stefan Monnier <monn...@iro.umontreal.ca>
branch nick: elpa
timestamp: Sun 2013-04-07 14:34:51 -0400
message:
  Add jumpc.
added:
  packages/jumpc/
  packages/jumpc/jumpc.el
=== added directory 'packages/jumpc'
=== added file 'packages/jumpc/jumpc.el'
--- a/packages/jumpc/jumpc.el   1970-01-01 00:00:00 +0000
+++ b/packages/jumpc/jumpc.el   2013-04-07 18:34:51 +0000
@@ -0,0 +1,221 @@
+;;; jumpc.el --- jump to previous insertion points  -*- coding: utf-8; 
lexical-binding: t -*-
+
+;; Copyright (C) 2013  Free Software Foundation, Inc.
+
+;; Author: Ivan Kanis <ban...@kanis.fr>
+;; Version: 2.0
+
+;; 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 <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This implements the jump cursor feature found in vim.
+
+;; A jump is added every time you insert a character on a different
+;; line.
+
+;; Jumps are remembered in a jump list.  With the C-o and C-i
+;; command you can go to cursor positions before older jumps, and back
+;; again.  Thus you can move up and down the list.
+
+;; Jumps are read and saved in the same configuration file as vim so
+;; you can switch back and forth between the two editors
+
+;;;; THANKS:
+
+;; Bram Moolenaar for writing a fine editor and helping needy children
+;; in Uganda
+
+;; Stefan Monnier for telling me how to add C-i binding
+
+;; Ted Zlatanov for suggesting to use less agressive key bindings
+
+;;;; BUGS:
+
+;;;; INSTALLATION:
+
+;; put this file somewhere in your load path then put the put the
+;; following in your .emacs:
+;;
+;; (require 'jumpc)
+;; (jumpc)
+;;
+;; Then either:
+;;
+;; (jumpc-bind-vim-key)
+;;
+;; Or:
+;;
+;; (global-set-key (kbd "<f8>") 'jumpc-jump-backward)
+;; (global-set-key (kbd "<f9>") 'jumpc-jump-forward)
+;;
+;; The first will bind C-i and C-o just like vim.  The second bind
+;; function keys 8 and 9. Of course you can pick any keys you like.  If
+;; you use Emacs on a console you will have to pick the second form as
+;; C-i and TAB are the same thing.
+;;
+;; If you use autoload you don't need to require the file
+
+;;;; TODO
+
+;; search for TODO within the file
+
+;; Add rotate jump list feature in vim
+;;   defined as JUMPLIST_ROTATE in mark.c
+;;     "If last used entry is not at the top, put it at the top by
+;;     rotating the stack until it is (the newer entries will be at
+;;     the bottom). Keep one entry (the last used one) at the top."
+
+;; Add a bit of looseness.  For example do not add jump points within
+;; three lines of the last one.
+
+;; Add jump list displaying each jump with the file and line in the
+;; file.  Clicking on a line takes you to the jump location.
+
+;; Add more commands that will insert jump.  Vim does: "'", "`", "G",
+;; "/", "?", "n", "N", "%", "(", ")", "[[", "]]", "{", "}", ":s",
+;; ":tag", "L", "M", "H"
+
+;; Remove files that do not exist when reading and writing from
+;; configuration file
+
+;;;; VERSION
+
+;; version 1
+
+;; version 2
+;;  - remove debugging message
+;;  - insert a jump moves the index back to top of list
+;;  - insert jumps goes back to top of list
+
+;;; Code:
+
+(defvar jumpc-file "~/.viminfo"
+  "File where jump information is written.")
+
+(defvar jumpc-list nil
+  "List of filenames and position to jump to.")
+
+(defvar jumpc-index 0
+  "Index of jump, 0 is the newest entry.")
+
+(defun jumpc-read-list ()
+  "Read jump list from file."
+  (when (file-exists-p jumpc-file)
+    (with-temp-buffer
+      (insert-file-contents jumpc-file)
+      (goto-char (point-min))
+      (when (re-search-forward "# Jumplist (newest first):" nil t)
+        (while (re-search-forward
+                "-'  \\([0-9]*\\)  \\([0-9]*\\)  \\(.*\\)" nil t)
+          (add-to-list 'jumpc-list
+                       (list (string-to-number (match-string 1))
+                             (string-to-number (match-string 2))
+                             (expand-file-name (match-string 3)))
+                       jumpc-list)))))
+  jumpc-list)
+
+(defun jumpc-write-list ()
+  "Write jump list to file."
+  (let (bgn end)
+    (find-file jumpc-file)
+    (goto-char (point-min))
+    (setq bgn (re-search-forward "# Jumplist (newest first):" nil t))
+    (if bgn
+        (progn
+          (setq end (re-search-forward "^$"))
+          (delete-region bgn end))
+      ;; looks like the entry doesn't exist, tack it at the end
+      (goto-char (point-max))
+      (insert "# Jumplist (newest first):"))
+    (insert "\n")
+    (dolist (line jumpc-list)
+      (insert (format "-'  %d  %d  %s\n"
+                      (nth 0 line) (nth 1 line)
+                      (abbreviate-file-name (nth 2 line)))))
+    (save-buffer)))
+
+(defun jumpc-jump-backward ()
+  "Jump backward in list of jumps."
+  (interactive)
+  (jumpc-jump 1))
+
+(defun jumpc-jump-forward ()
+  "Jump forward in list of jumps."
+  (interactive)
+  (jumpc-jump -1))
+
+;; TODO make it interactive with COUNT as argument
+(defun jumpc-jump (count)
+  "Jump COUNT from current index."
+  (let ((length (length jumpc-list)) file-name)
+    ;; first backward motion adds current point in the list
+    (when (and (> count 0) (= jumpc-index 0))
+      (jumpc-insert))
+    (setq jumpc-index (+ jumpc-index count))
+    ;; fix index if it's out of boundary
+    (cond
+     ((< jumpc-index 0)
+      (setq jumpc-index 0))
+     ((> jumpc-index length)
+      (setq jumpc-index length))
+     (t
+      (setq file-name (nth 2 (nth jumpc-index jumpc-list)))
+      (if (file-exists-p file-name)
+          (progn
+            (find-file file-name)
+            (goto-char (point-min))
+            (forward-line (1- (nth 0 (nth jumpc-index jumpc-list))))
+            (move-to-column (nth 0 (nth jumpc-index jumpc-list))))
+        ;; TODO I guess the right thing(tm) would be to remove the
+        ;; entry from the list
+        (message "File %s disappeared!" file-name))))))
+
+(defun jumpc-insert ()
+  "Insert jump location."
+  ;; It means we are going back to the top of the list
+  (setq jumpc-index 0)
+  (when buffer-file-name
+    (when (not (= (line-number-at-pos) (nth 0 (car jumpc-list))))
+      (setq jumpc-list
+            (cons (list (line-number-at-pos) (current-column) buffer-file-name)
+                  jumpc-list)))))
+
+(defun jumpc-bind-vim-key ()
+  "Bind keys just like vim."
+  (global-set-key (kbd "C-o") 'jumpc-jump-backward)
+  (define-key input-decode-map [?\C-i] [control-i])
+  (global-set-key [control-i] 'jumpc-jump-forward))
+
+;;;###autoload
+(defun jumpc ()
+  "Initialize jump cursor."
+  (interactive)
+  (setq jumpc-list (jumpc-read-list))
+  (defadvice self-insert-command
+    (after jumpc-insert activate)
+    "Insert jump position after insertion."
+    (jumpc-insert))
+  (add-hook 'kill-emacs-hook 'jumpc-write-list))
+
+
+;; vi:et:sw=4:ts=4:
+;; Local Variables:
+;; compile-command: "make"
+;; End:
+
+(provide 'jumpc)
+;;; jumpc.el ends here

Reply via email to