+ to go backwards in history until I see something
45 | ;; interesting. Then I press " 'face 'italic)
167 | (propertize (int-to-string
168 | (backup-walker-get-version (nth (1+ index) suffixes)))
169 | 'face 'font-lock-keyword-face)
170 | ", ")
171 | "")
172 | (when backup-walker-minor-mode
173 | " quit"))
237 | (setq major-mode 'backups-mode)
238 | (setq mode-name "Backups-list")
239 | (run-hooks 'backups-mode-hook))
240 |
241 | (define-minor-mode view-backup-mode ()
242 | "Minor mode for viewing a single backup file"
243 | " Backup-file"
244 | '(("q" . (lambda () (interactive) (bm-kill-popup-buffer backups-mode-data-alist)))
245 | ("d" . diff-with-current)
246 | ("r" . (lambda () (interactive) (princ bm-revert-message)))
247 | ("R" . (lambda () (interactive) (bm-revert-backup-from-file (bm-get-original-file backups-mode-data-alist)
248 | (buffer-file-name)
249 | backups-mode-data-alist))))
250 | :init-value nil)
251 |
252 | (define-minor-mode diff-backup-mode ()
253 | "Minor mode for viewing a backup diff"
254 | ""
255 | '(("q" . (lambda () (interactive) (bm-kill-popup-buffer backups-mode-data-alist)))
256 | ("1" . (lambda () (interactive) (view-backup-from-diff (cdr (assoc :first-file-name backups-mode-data-alist)))))
257 | ("2" . (lambda () (interactive) (view-backup-from-diff (cdr (assoc :second-file-name backups-mode-data-alist))))))
258 | :init-value nil)
259 |
260 | ;;; backups-mode private methods
261 | (defun bm-get-file-name-from-index (index)
262 | (bm-get-file-name (nth index (bm-get-backups backups-mode-data-alist))))
263 |
264 | (defun bm-get-index-number (line-number)
265 | (- line-number 2))
266 |
267 | (defun bm-get-line-number (index)
268 | (+ index 2))
269 |
270 | ;;; backups-mode commands
271 |
272 | ;; view commands
273 | (defun view-backup ()
274 | "View a single backup file in a popup window.
275 | If you choose to view the current version of the file,
276 | this will close backups-mode and move the user back to the current file."
277 | (interactive)
278 | (let ((index (bm-get-index-number (line-number-at-pos))))
279 | (cond ((zerop index)
280 | (princ bm-current-file-message))
281 | ((and (> index 0) (< index (length (bm-get-backups backups-mode-data-alist))))
282 | (bm-open-file-read-only (bm-get-file-name-from-index index)))
283 | (t (princ bm-no-file-message)))))
284 |
285 | (defun view-backup-from-diff (filename)
286 | "View a single backup file"
287 | (interactive)
288 | (let ((original-file (bm-get-original-file backups-mode-data-alist)))
289 | (if (equal filename original-file)
290 | (princ bm-current-file-message)
291 | (bm-open-file-read-only filename))))
292 |
293 | (defun bm-open-file-read-only (filename)
294 | (setq ro-buffer (find-file-noselect filename))
295 | (setq current-config (current-window-configuration))
296 | (let* ((orig-data (copy-alist backups-mode-data-alist)))
297 | (bm-switch-to-window ro-buffer 'backups-minor-mode-p)
298 | (view-backup-mode t)
299 | (bm-rename-buffer filename orig-data)
300 | (setq backups-mode-data-alist orig-data)
301 | (setq header-line-format (format "
quit"))))
302 |
303 |
304 | ;; revert commands
305 | (defun revert-backup ()
306 | "Save the current file as a version then replace it with
307 | the chosen backup."
308 | (interactive)
309 | (let ((index (bm-get-index-number (line-number-at-pos))))
310 | (cond ((zerop index)
311 | (princ "Cannot revert current buffer"))
312 | ((and (> index 0) (< index (length (bm-get-backups backups-mode-data-alist))))
313 | (bm-revert-backup-from-file (bm-get-original-file backups-mode-data-alist)
314 | (bm-get-file-name-from-index index)
315 | backups-mode-data-alist))
316 | (t (princ bm-no-file-message)))))
317 |
318 | (defun bm-revert-backup-from-file (orig-file-name backup-file-name data)
319 | (let* ((temp-backup-file-name (concat backup-file-name "#temp#"))
320 | (orig-buffer-name (buffer-name (get-file-buffer orig-file-name))))
321 | ;; using a temp file is necessary since saving the buffer may delete the backup file before it can be restored
322 | (bm-kill-all-buffers data)
323 | (copy-file backup-file-name temp-backup-file-name t)
324 | (when orig-buffer-name
325 | (switch-to-buffer orig-buffer-name)
326 | (save-buffer) ;; first, save the buffer. This is so the current changes become a saved version
327 | (save-version) ;; save a version of the current buffer
328 | (kill-buffer)) ;; kill the original buffer
329 | (copy-file temp-backup-file-name orig-file-name t) ;; move the temp file to become the current file
330 | (delete-file temp-backup-file-name)
331 | (find-file orig-file-name)))
332 |
333 | ;; diff commands
334 | (defun diff-version ()
335 | "Diff two versions of the file."
336 | (interactive)
337 | (let* ((line-number (line-number-at-pos))
338 | (index (bm-get-index-number line-number))
339 | (orig-buffer-name (buffer-name (get-file-buffer (bm-get-original-file backups-mode-data-alist)))))
340 | (if (and (>= index 0) (< index (length (bm-get-backups backups-mode-data-alist))))
341 | (progn
342 | (cond ((eq first-diff-index index)
343 | (beginning-of-line)
344 | (delete-char 1)
345 | (insert " ")
346 | (setq first-diff-index nil)
347 | (beginning-of-line))
348 | (first-diff-index
349 | (goto-line (bm-get-line-number first-diff-index))
350 | (delete-char 1)
351 | (insert " ")
352 | (goto-line line-number)
353 | (progn
354 | (when (and
355 | (zerop first-diff-index)
356 | (get-buffer orig-buffer-name)
357 | (buffer-modified-p (get-buffer orig-buffer-name)))
358 | (let ((backups-mode-buffer-name (buffer-name)))
359 | (switch-to-buffer orig-buffer-name)
360 | (save-buffer)
361 | (switch-to-buffer backups-mode-buffer-name)))
362 | (let ((first-file-name (bm-get-file-name-from-index first-diff-index))
363 | (second-file-name (bm-get-file-name-from-index index)))
364 | (setq first-diff-index nil)
365 | (set-buffer-modified-p nil)
366 | (bm-diff-files first-file-name second-file-name))))
367 | (t
368 | (setq first-diff-index index)
369 | (beginning-of-line)
370 | (insert "d")
371 | (delete-char 1)
372 | (forward-line)))
373 | (set-buffer-modified-p nil))
374 | (princ bm-no-file-message))) )
375 |
376 | (defun diff-with-current ()
377 | "diff the current backup buffer with the current version of the file"
378 | (interactive)
379 | (let ((first-file-name (bm-get-original-file backups-mode-data-alist))
380 | (second-file-name (buffer-file-name)))
381 | (bm-diff-files first-file-name second-file-name)))
382 |
383 | (defun bm-diff-files (first-file-name second-file-name)
384 | (setq diff-buffer (diff-no-select first-file-name second-file-name))
385 | (setq current-config (current-window-configuration))
386 | (with-current-buffer diff-buffer
387 | (diff-backup-mode t)) ;; must set minor mode before switching to diff buffer
388 | (let* ((orig-data (copy-alist backups-mode-data-alist)))
389 | (bm-switch-to-window diff-buffer 'backups-minor-mode-p)
390 | (push `(:first-file-name . ,first-file-name) orig-data)
391 | (push `(:second-file-name . ,second-file-name) orig-data)
392 | (setq backups-mode-data-alist orig-data)
393 | (setq header-line-format "
quit, <1> view first, <2> view second")))
394 |
395 |
396 | ;; deletion
397 | (defun mark-backup-for-purge ()
398 | "mark backups for batch deletion"
399 | (interactive)
400 | (let ((index (bm-get-index-number (line-number-at-pos)))
401 | (marked (bm-get-marked-for-purging backups-mode-data-alist)))
402 | (cond ((zerop index)
403 | (princ "Cannot mark the current file for purging"))
404 | ((and (>= index 0) (< index (length (bm-get-backups backups-mode-data-alist))))
405 | (if (memq index marked)
406 | (progn
407 | (beginning-of-line)
408 | (delete-char 1)
409 | (insert " ")
410 | (setcdr (assq :marked-for-purging backups-mode-data-alist)
411 | (delq index marked))
412 | (beginning-of-line))
413 | (progn
414 | (beginning-of-line)
415 | (insert "p")
416 | (delete-char 1)
417 | (setcdr (assq :marked-for-purging backups-mode-data-alist)
418 | (push index marked))
419 | (forward-line)))
420 | (set-buffer-modified-p nil))
421 | (t
422 | (princ bm-no-file-message)))))
423 |
424 | (defun purge-backups ()
425 | "Purge (delete) backups"
426 | (interactive)
427 | (let ((marked (bm-get-marked-for-purging backups-mode-data-alist)))
428 | (cond ((zerop (length marked))
429 | (princ "No backups marked to purge"))
430 | ((y-or-n-p "Purge the marked backups")
431 | (mapc
432 | (lambda (index)
433 | (let* ((file-name (bm-get-file-name-from-index index))
434 | (buf (get-file-buffer file-name)))
435 | (when (buffer-live-p buf)
436 | (kill-buffer buf))
437 | (delete-file file-name)))
438 | marked)
439 | (list-backups-from-file (bm-get-original-file backups-mode-data-alist)
440 | :data backups-mode-data-alist)))))
441 |
442 | ;; also require lewang's backup-walker if it exists
443 | ;; use the most up-to-date version first
444 | ;; fallback to a bundled version
445 | (or (require 'backup-walker nil 'noerror)
446 | (let ((load-path
447 | (cons (expand-file-name "fallback"
448 | (file-name-directory load-file-name))
449 | load-path)))
450 | (require 'backup-walker)))
451 |
452 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
453 | ;;; backups-mode.el ends here
454 |
--------------------------------------------------------------------------------
/bm-utilities.el:
--------------------------------------------------------------------------------
1 |
2 | ;; functions common to both backups-mode and backup-walker
3 | (defun bm-kill-all-buffers (data)
4 | (let* ((minor-buffers (bm-other-buffers 'backups-minor-mode-p))
5 | (backups-buffer (cdr (assq :backups-buffer data)))
6 | (walking-buffer (cdr (assq :walking-buffer data)))
7 | (first-config (bm-get-first-config data)))
8 |
9 | ;; first, cleanup all minor mode open buffers
10 | (bm-kill-open-buffers minor-buffers)
11 |
12 | ;; then, cleanup the backups-buffer
13 | (when (buffer-live-p backups-buffer)
14 | (kill-buffer backups-buffer))
15 |
16 | ;; then, cleanup the backup-walker buffer
17 | (when (buffer-live-p walking-buffer)
18 | (kill-buffer walking-buffer))
19 |
20 | ;; finally, reset the window configuration
21 | (set-window-configuration
22 | (bm-get-first-config data))))
23 |
24 | (defun bm-kill-open-buffers (buffers)
25 | (mapc (lambda (buffer)
26 | (when (buffer-live-p buffer)
27 | (kill-buffer buffer)))
28 | buffers))
29 |
30 | (defun bm-kill-popup-buffer (data)
31 | (let ((second-config (bm-get-second-config data))
32 | others)
33 | (kill-buffer)
34 | (setq others (bm-other-buffers 'backups-minor-mode-p))
35 | (if others
36 | (switch-to-buffer (car others))
37 | (set-window-configuration second-config))))
38 |
39 | (defun bm-other-buffers (pred)
40 | (filter (lambda (buf)
41 | (with-current-buffer buf
42 | (funcall pred)))
43 | (buffer-list)))
44 |
45 | (defun bm-switch-to-window (buffer-or-name pred)
46 | (let ((similar-window (get-window-with-predicate (make-backups-window-p pred)))
47 | (window-count (length (window-list)))
48 | width
49 | height)
50 | (if (and similar-window (window-live-p similar-window))
51 | (select-window similar-window)
52 | (if (>= window-count 4)
53 | (other-window 1) ;; don't split if 4+ windows exist
54 | (progn
55 | (select-window (get-largest-window))
56 | (setq width (window-width))
57 | (setq height (window-height))
58 | (split-window nil nil
59 | (> (/ width height) 2.1))))) ;; heuristic to popup vertically or horizontally
60 | (switch-to-buffer buffer-or-name)))
61 |
62 | (defun backups-major-mode-p ()
63 | (and (or (eq major-mode 'backups-mode)
64 | (eq major-mode 'backup-walker-mode))
65 | (not diff-backup-mode)))
66 |
67 | (defun backups-minor-mode-p ()
68 | (or diff-backup-mode
69 | view-backup-mode
70 | backup-walker-minor-mode))
71 |
72 | (defun make-backups-window-p (pred)
73 | (lexical-let ((pred pred))
74 | (lambda (window)
75 | (set-buffer (window-buffer window))
76 | (funcall pred))))
77 |
78 | ;;; list-backups helper methods
79 | (defun bm-backup-files (original-file)
80 | (let* ((backup-file (file-name-sans-versions
81 | (make-backup-file-name (expand-file-name original-file))))
82 | (backup-directory (file-name-directory backup-file)))
83 | (mapcar
84 | (lambda (f) (concat backup-directory f))
85 | (file-name-all-completions
86 | (file-name-nondirectory backup-file)
87 | backup-directory))))
88 |
89 | (defun bm-get-sorted-backups (original-file backup-files-function)
90 | (flet ((file-sort-p (file-name1 file-name2)
91 | (let ((version1 (bm-make-version-number file-name1))
92 | (version2 (bm-make-version-number file-name2)))
93 | (> version1 version2))))
94 | (mapcar 'bm-make-file
95 | (cons original-file (sort
96 | (funcall backup-files-function original-file)
97 | 'file-sort-p)))))
98 |
99 | (defun bm-make-version-number (file-name)
100 | (let ((try-version-index (string-match "~[0-9]+~$" file-name)))
101 | (when try-version-index
102 | (bm-full-version-number file-name try-version-index))))
103 |
104 | (defun bm-full-version-number (file-name start &optional number-str)
105 | (let* ((number-str (or number-str ""))
106 | (number (string-to-number number-str)))
107 | (if (< start (length file-name))
108 | (let ((current-char (substring file-name (+ 1 start) (+ 2 start))))
109 | (cond ((equal current-char "0") (bm-full-version-number file-name (+ 1 start) (concat number-str current-char)))
110 | ((equal (string-to-number current-char) 0) number)
111 | (t (bm-full-version-number file-name (+ 1 start) (concat number-str current-char)))))
112 | number)))
113 |
114 | ;;; file structure methods
115 | (defun bm-make-file (file-name)
116 | (flet ((make-last-modified-date
117 | (file-name)
118 | (let ((last-modified-date
119 | (shell-command-to-string
120 | (funcall last-modified-date-command-function file-name))))
121 | (when (not (equal (car (split-string last-modified-date)) unknown-last-modified-date))
122 | last-modified-date))))
123 | (list
124 | (bm-make-version-number file-name)
125 | (make-last-modified-date file-name)
126 | file-name)))
127 |
128 | (defun bm-get-version (file)
129 | (nth 0 file))
130 |
131 | (defun bm-get-last-modified-date (file)
132 | (nth 1 file))
133 |
134 | (defun bm-get-file-name (file)
135 | (nth 2 file))
136 |
137 | ;; data-alist helper methods
138 | (defun bm-get-original-file (data)
139 | (cdr (assq :original-file data)))
140 |
141 | (defun bm-get-backups (data)
142 | (cdr (assq :backups data)))
143 |
144 | (defun bm-get-marked-for-purging (data)
145 | (cdr (assq :marked-for-purging data)))
146 |
147 | (defun bm-get-first-config (data)
148 | (cdr (assq :first-config data)))
149 |
150 | (defun bm-get-second-config (data)
151 | (cdr (assq :second-config data)))
152 |
153 | ;; generic helper functions
154 | (defun filter (condp lst)
155 | (delq nil
156 | (mapcar (lambda (x) (and (funcall condp x) x)) lst)))
157 |
158 | (defun diff-no-select (old new &optional switches no-async)
159 | (save-window-excursion
160 | (ediff old new switches))
161 | ;; (get-buffer-create "*Diff*")
162 | )
163 |
164 | (defun bm-rename-buffer (filename data)
165 | (rename-buffer (concat (file-name-nondirectory (bm-get-original-file data))
166 | " "
167 | (number-to-string (bm-make-version-number filename)))))
168 |
169 | ;;; variables common to both backups-mode and backup-walker
170 | ;; minor mode variables
171 | (defvar backup-walker-minor-mode nil "non-nil if backup walker minor mode is enabled")
172 | (make-variable-buffer-local 'backup-walker-minor-mode)
173 |
174 | (defvar view-backup-mode nil "non-nil if viewing a backup from backups-mode")
175 | (make-variable-buffer-local 'view-backup-mode)
176 |
177 | (defvar diff-backup-mode nil "non-nil if diffing a backup from backups-mode")
178 | (make-variable-buffer-local 'diff-backup-mode)
179 |
180 | ;; common string literals
181 | (defvar bm-revert-message "Use a capital R to revert")
182 | (defvar bm-current-file-message "Cannot view the current file in read-only mode")
183 | (defvar bm-no-file-message "No file on this line")
184 |
--------------------------------------------------------------------------------
/fallback/.nosearch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chadbraunduin/backups-mode/4b591badf7b12905a2da8c822899283eb583bd57/fallback/.nosearch
--------------------------------------------------------------------------------
/fallback/backup-walker.el:
--------------------------------------------------------------------------------
1 | ;;; backup-walker.el --- quickly traverse all backups of a file
2 |
3 | ;; this file is not part of Emacs
4 |
5 | ;; Copyright (C) 2011 Le Wang
6 | ;; Author: Le Wang
7 | ;; Maintainer: Chad Braun-Duin
8 | ;; Description: quickly traverse all backups of a file
9 |
10 | ;; Created: Wed Sep 7 19:38:05 2011 (+0800)
11 | ;; Version: 2.0
12 | ;; Last-Updated: Web Oct 12 22:54 2011 (+0800)
13 | ;; By: Chad Braun-Duin
14 | ;; URL: https://github.com/chadbraunduin/backups-mode
15 | ;; Keywords: backup
16 | ;; Compatibility: Emacs 23+
17 |
18 | ;;; Installation:
19 |
20 | ;;
21 | ;; add to ~/.emacs.el
22 | ;;
23 | ;; (require 'backup-walker)
24 | ;;
25 | ;; This installation is unnecessary if you've already put this version of
26 | ;; backup-walker.el and bm-utilities.el in your emacs load-path and have
27 | ;; required and started backups-mode
28 |
29 | ;;; Commentary (from lewang):
30 |
31 | ;; I never delete backups. They are versioned in their own directory, happy
32 | ;; and safe. My fingers skip to C-x C-s whenever I pause to think about
33 | ;; anything. Even when I'm working with VCS, I save far more often than I
34 | ;; commit.
35 | ;;
36 | ;; This package helps me traverse those backups if I'm looking for something.
37 | ;;
38 | ;; The typical workflow is:
39 | ;;
40 | ;; 1) I'm in a buffer and realize I need to check some backups.
41 | ;;
42 | ;; C-cw
43 | ;;
44 | ;; 2) I press
and kill all open backups.
50 | ;;
51 | ;; 4) the end.
52 | ;;
53 | ;; Additionally, note that all the diff-mode facilities are available in the
54 | ;; `backup-walker' buffer.
55 | ;;
56 |
57 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
58 | ;;
59 | ;; This program is free software; you can redistribute it and/or
60 | ;; modify it under the terms of the GNU General Public License as
61 | ;; published by the Free Software Foundation; either version 3, or
62 | ;; (at your option) any later version.
63 | ;;
64 | ;; This program is distributed in the hope that it will be useful,
65 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
66 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
67 | ;; General Public License for more details.
68 | ;;
69 | ;; You should have received a copy of the GNU General Public License
70 | ;; along with this program; see the file COPYING. If not, write to
71 | ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
72 | ;; Floor, Boston, MA 02110-1301, USA.
73 | ;;
74 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
75 |
76 | ;;; Code:
77 |
78 | (provide 'backup-walker)
79 | (load "bm-utilities.el")
80 |
81 | (eval-when-compile (require 'cl))
82 | (eval-and-compile (require 'diff))
83 |
84 | (defun backups-mode-p ()
85 | (fboundp 'backups-mode-start))
86 |
87 | (defvar backup-walker-ro-map (make-sparse-keymap))
88 | (define-key backup-walker-ro-map [(n)] 'backup-walker-next)
89 | (define-key backup-walker-ro-map [(p)] 'backup-walker-previous)
90 | (define-key backup-walker-ro-map [(q)] 'backup-walker-quit)
91 | (define-key backup-walker-ro-map [(return)] 'backup-walker-show-file-in-other-window)
92 | (when (backups-mode-p)
93 | (define-key backup-walker-ro-map [(b)] (lambda ()
94 | (interactive)
95 | (list-backups-from-file
96 | (cdr (assq :original-file backup-walker-data-alist))
97 | :data backup-walker-data-alist))))
98 |
99 | (define-derived-mode backup-walker-mode diff-mode "Diff backup-walker"
100 | "major mode for traversing versioned backups. Use
101 | `backup-walker-start' as entry point."
102 | (run-hooks 'view-mode-hook) ; diff-mode sets up this hook to
103 | ; remove its read-only overrides.
104 | (add-to-list 'minor-mode-overriding-map-alist `(buffer-read-only . ,backup-walker-ro-map)))
105 |
106 |
107 | (defun backup-walker-minor-mode (&optional arg)
108 | "purposefully made non-interactive, because this mode should only be used by code"
109 | (setq arg (cond ((or (null arg)
110 | (eq arg 'toggle))
111 | (if backup-walker-minor-mode
112 | nil
113 | t))
114 | ((> arg 0)
115 | t)
116 | ((<= arg 0)
117 | nil)))
118 | (setq backup-walker-minor-mode arg)
119 | (force-mode-line-update)
120 | (if backup-walker-minor-mode
121 | (let ((index (cdr (assq :index backup-walker-data-alist)))
122 | (suffixes (cdr (assq :backup-suffix-list backup-walker-data-alist))))
123 | (setq header-line-format (backup-walker-get-key-help-common index suffixes (concat "viewing " (propertize (int-to-string
124 | (backup-walker-get-version
125 | (nth index suffixes)))
126 | 'face 'font-lock-keyword-face)
127 | ", ")))
128 | (add-to-list 'minor-mode-overriding-map-alist `(buffer-read-only . ,backup-walker-ro-map))
129 | (when (backups-mode-p)
130 | (define-key backup-walker-ro-map "r" (lambda () (interactive) (princ bm-revert-message)))
131 | (define-key backup-walker-ro-map "R" (lambda () (interactive)
132 | (bm-revert-backup-from-file (cdr (assq :original-file backup-walker-data-alist))
133 | (buffer-file-name)
134 | backup-walker-data-alist)))))
135 | (setq header-line-format nil)
136 | (delq `(buffer-read-only . ,backup-walker-ro-map) minor-mode-overriding-map-alist))
137 | backup-walker-minor-mode)
138 |
139 | (add-minor-mode 'backup-walker-minor-mode " walker" nil nil nil)
140 |
141 | (defvar backup-walker-data-alist nil "")
142 | (make-variable-buffer-local 'backup-walker-data-alist)
143 |
144 | (defsubst backup-walker-get-version (fn &optional start)
145 | "return version number given backup"
146 | (if start
147 | (string-to-int
148 | (substring fn
149 | (string-match "[[:digit:]]+" fn start)
150 | (match-end 0)))
151 | (backup-walker-get-version fn (length (file-name-sans-versions fn)))))
152 |
153 | (defsubst backup-walker-get-key-help-common (index suffixes current-file-string)
154 | (concat
155 | (if (eq index 0)
156 | (if (eq major-mode 'backup-walker-mode)
157 | (concat (propertize "current" 'face 'font-lock-keyword-face)
158 | ", ")
159 | "")
160 | (concat (propertize "
" 'face 'italic)
175 | " quit"))
176 |
177 | ;; TODO: We can actually compute the correct new point by diffing and
178 | ;; interpreting results. So far, it seems overkill.
179 | (defsubst backup-walker-move (index-cons index suffixes new-index)
180 | "internal function used by backup-walker-{next,previous}"
181 | (cond
182 | ((eq major-mode 'backup-walker-mode)
183 | (setcdr index-cons new-index)
184 | (backup-walker-refresh))
185 | (backup-walker-minor-mode
186 | (let* ((prefix (cdr (assq :backup-prefix backup-walker-data-alist)))
187 | (file-name (concat prefix (nth new-index suffixes)))
188 | (alist (copy-alist backup-walker-data-alist))
189 | (buf (find-file-noselect file-name)))
190 | (setcdr (assq :index alist) new-index)
191 | (with-current-buffer buf
192 | (setq backup-walker-data-alist alist)
193 | (backup-walker-minor-mode 1))
194 | (switch-to-buffer buf)
195 | (bm-rename-buffer file-name backup-walker-data-alist)))))
196 |
197 | (defun backup-walker-get-sorted-backups (filename)
198 | "Return version sorted list of backups of the form:
199 | (prefix (list of suffixes))"
200 | ;; `make-backup-file-name' will get us the right directory for
201 | ;; ordinary or numeric backups. It might create a directory for
202 | ;; backups as a side-effect, according to `backup-directory-alist'.
203 | (let* ((filename (file-name-sans-versions
204 | (make-backup-file-name (expand-file-name filename))))
205 | (file (file-name-nondirectory filename))
206 | (dir (file-name-directory filename))
207 | (comp (file-name-all-completions file dir))
208 | (prefix-len (length file)))
209 | (cons filename (mapcar
210 | (lambda (f)
211 | (substring (cdr f) prefix-len))
212 | (sort
213 | (mapcar (lambda (f)
214 | (cons (backup-walker-get-version f prefix-len)
215 | f))
216 | comp)
217 | (lambda (f1 f2)
218 | (not (< (car f1) (car f2)))))))))
219 |
220 |
221 | (defun backup-walker-refresh ()
222 | (let* ((index (cdr (assq :index backup-walker-data-alist)))
223 | (suffixes (cdr (assq :backup-suffix-list backup-walker-data-alist)))
224 | (prefix (cdr (assq :backup-prefix backup-walker-data-alist)))
225 | (right-file (concat prefix (nth index suffixes)))
226 | (right-version (format "%i" (backup-walker-get-version right-file)))
227 | diff-buf left-file left-version)
228 | ;; (debug)
229 | (if (eq index 0)
230 | (setq left-file (cdr (assq :original-file backup-walker-data-alist))
231 | left-version "orig")
232 | (setq left-file (concat prefix (nth (1- index) suffixes))
233 | left-version (format "%i" (backup-walker-get-version left-file))))
234 | (setq diff-buf (diff-no-select left-file right-file nil 'noasync))
235 | ;; (debug)
236 | (setq buffer-read-only nil)
237 | (delete-region (point-min) (point-max))
238 | (insert-buffer-substring diff-buf)
239 | (goto-char (point-min))
240 | (set-buffer-modified-p nil)
241 | (setq buffer-read-only t)
242 | (force-mode-line-update)
243 | (setq header-line-format
244 | (concat (when (backups-mode-p)
245 | " backups-mode, ")
246 | (backup-walker-get-key-help-common index
247 | suffixes
248 | (concat (propertize "