1 ;;; tinyxreg.el --- Restore points and window configuration with X-popup
3 ;; This file is not part of Emacs
7 ;; Copyright (C) 1995-2007 Jari Aalto
10 ;; Maintainer: Jari Aalto
12 ;; To get information on this program, call M-x tinyxreg-version.
13 ;; Look at the code with folding.el.
17 ;; This program is free software; you can redistribute it and/or modify it
18 ;; under the terms of the GNU General Public License as published by the Free
19 ;; Software Foundation; either version 2 of the License, or (at your option)
22 ;; This program is distributed in the hope that it will be useful, but
23 ;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27 ;; You should have received a copy of the GNU General Public License
28 ;; along with program; see the file COPYING. If not, write to the
29 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
30 ;; Boston, MA 02110-1301, USA.
32 ;; Visit <http://www.gnu.org/copyleft/gpl.html> for more information
39 ;; ....................................................... &t-install ...
40 ;; Put this file on your Emacs-Lisp load path, add following into your
41 ;; ~/.emacs startup file.
43 ;; (when window-system
44 ;; (global-set-key "\C-x/" 'tinyxreg-point-to-register)
45 ;; (global-set-key "\C-x\\" 'tinyxreg-remove-register)
46 ;; ;; The non-graphical "jump" is at C-x j
47 ;; (global-set-key "\C-cj" 'tinyxreg-jump-to-register)
48 ;; (require 'tinyxreg))
50 ;; Or use autoload, preferfed, because your emacs starts up faster.
52 ;; (when window-system
53 ;; (global-set-key "\C-x/" 'tinyxreg-point-to-register)
54 ;; (global-set-key "\C-x\\" 'tinyxreg-remove-register)
55 ;; (global-set-key "\C-cj" 'tinyxreg-jump-to-register)
56 ;; (autoload 'tinyxreg-jump-to-register "tinyxreg" "" t)
57 ;; (autoload 'tinyxreg-jump-to-register-mouse "tinyxreg" "" t)
58 ;; (autoload 'tinyxreg-point-to-register "tinyxreg" "" t)
59 ;; (autoload 'tinyxreg-point-to-register-mouse "tinyxreg" "" t)
60 ;; (autoload 'tinyxreg-remove-reg "tinyxreg" "" t)
61 ;; (autoload 'tinyxreg-trash "tinyxreg" "" t))
63 ;; If you have any questions or comments, use this function
65 ;; M-x tinyxreg-submit-bug-report
70 ;; ..................................................... &t-commentary ...
76 ;; There was a post in comp.emacs by <cpg@cs.utexas.edu> Carlos Puchol
78 ;; I find that my life would be remarkably eased if only I could
79 ;; "jump" to the marks from a menu. Please, let me know if i can
80 ;; implement this myself through some sort of macro or something.
82 ;; It was an interesteing idea and some sketching was flying in the air.
83 ;; The original plan wasn't to write any serious code; just tossing
84 ;; around some experiments with of functions.
85 ;; As a result it soon become a complete package and after a while
86 ;; a properly packaged set.
88 ;; Overview of features
90 ;; o Store points and window configurations to registers.
91 ;; o Use popup to pick register associated with the file. In short
92 ;; this package offers graphical user interface for the the
93 ;; C-x j "jump to register".
95 ;; Register update note
97 ;; If you wonder why some of the registers disappear from the popup
98 ;; while you were sure you just stored some point to them, the reason
99 ;; is that If you kill some buffer, or reload it again with
100 ;; find-alternate-file that means that the register reference "dies".
101 ;; That's why the main function tinyxreg-jump-to-register calls a
102 ;; house keeping function tinyxreg-update to make sure you can't
103 ;; select invalid registers. So, trust the poup: it tells what
104 ;; registes are available.
112 ;;{{{ setup: libraries
115 (eval-when-compile (ti::package-use-dynamic-compilation))
117 (ti::package-defgroup-tiny TinyXreg tinyxreg-: tools
118 "Restoring points/win cfg stroed in reg. via X-popup
121 o Store points and window configurations to registers.
122 o Use popup to pick register associated with the file. In short
123 this package offers graphical user interface for the the
124 C-x j \"jump to register\".")
129 (defcustom tinyxreg-:load-hook nil
130 "*Hook that is run when package is loaded."
135 ;;{{{ setup: public, user configurable
137 (defcustom tinyxreg-:x-coord 170
138 "*Default menu coordinate."
142 (defcustom tinyxreg-:y-coord 170
143 "*Default menu coordinate."
147 (defcustom tinyxreg-:description-func 'tinyxreg-description
148 "*Function to return popup description string.
149 Function should accept two arguments: REGISTER and WINDOW-ARG"
153 (defcustom tinyxreg-:title "Register list"
158 (defcustom tinyxreg-:buffer-fmt "%-20s"
159 "*Format for filename.
160 Filename length reserved for default popup description.
162 Note: The entries itself are stored in this form, so changing this
163 affects only new entries."
164 :type '(string :tag "Format string")
167 (defcustom tinyxreg-:wcfg-fmt '(concat "\177 Win " bn)
168 "*Lisp form to for window configuration.
169 This is the Window config FORM that is evaled when
170 the description is put into the list. You can use variable BN
171 to refer current buffer name.
173 Remember that list will be sorted later, so you may want to have
174 common beginning for all win cfg registers."
175 :type '(sexp :tag "Lisp form")
181 (defvar tinyxreg-:preg nil
182 "Hold point markers.")
184 (defvar tinyxreg-:wreg nil
185 "Hold window markers.")
190 ;;; ....................................................... &v-version ...
192 ;;;###autoload (autoload 'tinyxreg-version "tinyxreg" "Display commentary." t)
195 (ti::macrof-version-bug-report
199 "$Id: tinyxreg.el,v 2.43 2007/05/06 23:15:20 jaalto Exp $"
200 '(tinyxreg-:version-id
206 tinyxreg-:description-func
209 tinyxreg-:wcfg-fmt)))
214 ;;; ----------------------------------------------------------------------
216 (defun tinyxreg-event ()
218 (ti::compat-make-fake-event tinyxreg-:x-coord tinyxreg-:y-coord))
220 ;;; ----------------------------------------------------------------------
222 (defun tinyxreg-list ()
223 "Return register list, point list + window list."
224 (let* ((ptr tinyxreg-:wreg)
225 (list (copy-sequence tinyxreg-:preg)))
231 ;;; ----------------------------------------------------------------------
233 (defun tinyxreg-install-default-key-bindings ()
234 "Install default key bindings."
236 ;; There is no other good use for these
237 (global-set-key "\C-x/" 'tinyxreg-point-to-register)
238 (global-set-key "\C-x\\" 'tinyxreg-remove-register)
239 ;; The "C-c j" is like C-x j , but showing the popup
240 (global-set-key "\C-cj" 'tinyxreg-jump-to-register)
241 ;; C-x is so easy to reach with left hand... and free
242 (global-set-key [(control c) (mouse-1)] 'tinyxreg-jump-to-register-mouse)
243 (global-set-key [(control c) (shift mouse-1)] 'tinyxreg-point-to-register-mouse)
244 (when (interactive-p)
245 (message "TinyXreg: Register Keys bound ok.")))
247 ;;; ----------------------------------------------------------------------
250 (defun tinyxreg-remove-reg (char &optional arg)
251 "Remove register CHAR from stored window and point lists.
252 ARG suggests looking in window list."
253 (interactive "cRemove register: \nP")
254 (let* ((ptr (if arg tinyxreg-:wreg tinyxreg-:preg))
256 (when (setq elt (rassq char ptr))
258 (setq tinyxreg-:wreg (delete elt tinyxreg-:wreg))
259 (setq tinyxreg-:preg (delete elt tinyxreg-:preg))))))
261 ;;; ----------------------------------------------------------------------
263 (defun tinyxreg-update ()
264 "Kill all registers from lists that are not alive any more.
265 Eg. marker dies if you revert the buffer; kill and load it again."
266 (let* ((ptr tinyxreg-:preg)
269 ;; We simple copy valid elements to another list
272 (if (ti::register-live-p reg)
274 (setq tinyxreg-:preg list)
275 (setq ptr tinyxreg-:wreg)))
277 ;;; ----------------------------------------------------------------------
280 (defun tinyxreg-trash ()
281 "Empties both window and point caches."
283 (setq tinyxreg-:preg nil tinyxreg-:wreg nil)
285 (message "TinyXreg: Register lists trashed.")))
287 ;;; ----------------------------------------------------------------------
289 (defun tinyxreg-kill-reg (char)
290 "Kill register CHAR from all lists."
291 (tinyxreg-remove-reg char nil)
292 (tinyxreg-remove-reg char 'window))
294 ;;; ----------------------------------------------------------------------
296 (defun tinyxreg-add-reg (char arg &optional desc)
297 "Store register CHAR to window or point list.
298 ARG tells to store to window list. DESC is string to use."
299 (let* ((desc (if (stringp desc)
301 (char-to-string char)))
302 (data (cons desc char)))
304 (push data tinyxreg-:wreg)
305 (push data tinyxreg-:preg))))
310 ;; ----------------------------------------------------------------------
311 ;;; So that you call this from mouse
313 (defun tinyxreg-description (register &optional arg)
314 "Return description text for popup list.
315 REGISTER is stored register and if ARG is non-nil the register
316 contains window configuration."
317 (let* ((bn (file-name-nondirectory (buffer-name)))
318 (cfg tinyxreg-:wcfg-fmt))
319 (format (concat tinyxreg-:buffer-fmt " %4s %s")
321 ;; the 177 should print nice block
322 ;; so that sorting puts cfg entries last
328 (count-lines (point-min-marker) (line-beginning-position))))
329 (char-to-string register))))
331 ;;; ----------------------------------------------------------------------
334 (defun tinyxreg-point-to-register-mouse (event)
335 "Call `tinyxreg-point-to-register' using mouse EVENT."
337 ;; - User using "flying" mouse paste mode? See var mouse-yank-at-point
338 ;; - If he is, then move cursor visually to mouse point first.
339 (if (null mouse-yank-at-point)
340 (mouse-set-point event))
341 (call-interactively 'tinyxreg-point-to-register))
343 ;;; ----------------------------------------------------------------------
344 ;;; based on register.el::point-to-register
347 (defun tinyxreg-point-to-register (char &optional arg)
348 "Store point to CHAR and to X-popup list.
349 With prefix ARG, store current frame configuration. VERBOSE enables
352 Use \\[tinyxreg-point-to-register] to go to that location or restore the
360 "TinyXreg: Store Window cfg to register: " )
362 "TinyXreg: Store point to register: "))))
363 (setq CHAR (ti::read-char-safe-until msg))
364 ;; Show where it got stored.
365 (message (concat msg (char-to-string CHAR)))
368 (let* ((dfunc tinyxreg-:description-func)
370 (setq desc ;get the popup description
372 (funcall dfunc char arg)
374 (tinyxreg-remove-reg char arg)
375 (tinyxreg-add-reg char arg desc)
376 (set-register ;; Now the normal emacs thing
380 (current-frame-configuration)))))
385 ;;; ----------------------------------------------------------------------
388 (defun tinyxreg-remove-register ()
389 "Remove register from popup list.
390 See `tinyxreg-jump-to-register-mouse' for more."
392 (tinyxreg-jump-to-register-mouse nil 'remove))
394 ;;; ----------------------------------------------------------------------
395 ;;; - for calling from keybord
398 (defun tinyxreg-jump-to-register (&optional remove)
399 "Call `tinyxreg-jump-to-register-mouse' with REMOVE."
401 (tinyxreg-jump-to-register-mouse nil remove))
403 ;;; ----------------------------------------------------------------------
406 (defun tinyxreg-jump-to-register-mouse (event &optional remove verb)
407 "Displays list of registers using mouse EVENT.
408 Restore register or optionally REMOVE register from X-list.
412 REMOVE flag, if non-nil, remove register.
413 VERB flag, Allow verbose messages."
415 (let* ((event (or event
416 (ti::compat-make-fake-event
417 tinyxreg-:x-coord tinyxreg-:y-coord)))
418 (title (interactive-p))
424 (tinyxreg-update) ;update register list
425 (setq ref-list (tinyxreg-list)
426 list (mapcar 'car ref-list))
428 ((null (ti::compat-window-system))
429 (message "TinyXreg: sorry, Requires X to use X-popup"))
432 (message "TinyXreg: sorry, both register lists are empty.")))
434 (setq data (ti::compat-popup list event nil title))
437 (message "TinyXreg: register not selected."))
438 (setq char (cdr-safe (assoc data ref-list)))
441 ;; Remove from both lists
442 (tinyxreg-kill-reg char)
446 (concat "TinyXreg: register ["
447 (char-to-string char) "] removed"))
448 ;; too fast otw when you move mouse..
451 (jump-to-register char nil))))))))
456 (run-hooks 'tinyxreg-:load-hook)
458 ;;; tinyxreg.el ends here