-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
edit-list.el
145 lines (119 loc) · 4.88 KB
/
edit-list.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
;;; edit-list.el --- edit a single list
;; Copyright (C) 2008 Michael Olson
;; Author: Michael Olson <mwolson@gnu.org>
;; Date: Mon 31-Mar-2008
;; Version: 0.3
;; URL: http://mwolson.org/static/dist/elisp/edit-list.el
;; This file is not part of GNU Emacs.
;; This program 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 2 of the License, or
;; (at your option) any later version.
;;
;; This program 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; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; So you've just added an incorrect entry to auto-mode-alist and want
;; to fix it quickly. `M-x edit-list RET auto-mode-alist RET' to the
;; rescue. Make your changes and hit either `C-x C-s' or `C-c C-c'
;; when done. Or just kill the buffer if you change your mind.
;;; History:
;; 0.3:
;;
;; - Grab list name at point.
;;
;; - Limit completions to lists.
;;
;; - Set buffer-modified-p to nil when buffer is ready for user edits.
;;
;; - Handle edge case where argument passed to `edit-list' is an
;; unbound symbol.
;; 0.2: Add completion for symbols, header, footer, and (require 'pp).
;; 0.1: Initial release.
;;; Contributors:
;; rubikitch (rubikitch AT ruby-lang.org) provided a solution for
;; completing symbol names.
;; Rupert Swarbrick (rswarbrick AT gmail.com) provided the initial
;; implementations for defaulting to the list name at point and
;; limiting the completions to names of lists.
;;; Code:
(require 'pp)
(defgroup edit-list nil
"Options controlling the behavior of Edit List Mode.
Edit List mode allows the editing of a single list in a buffer."
:group 'convenience)
(defcustom edit-list-completing-read-function 'completing-read
"Function to use for completing read in `edit-list'."
:type 'function
:group 'edit-list)
(defvar edit-list-mode-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-c C-c") 'edit-list-done)
(define-key map (kbd "C-x C-s") 'edit-list-done)
map))
(defvar edit-list-list-name nil
"Name of list currently being edited.")
(make-variable-buffer-local 'edit-list-list-name)
(define-derived-mode edit-list-mode emacs-lisp-mode "Edit-List"
"Major mode to edit a single list.
\\{edit-list-mode-map}")
(defun edit-list-read-list-name (prompt)
"Read the name of a list from the user."
(let ((sym (cond ((fboundp 'symbol-nearest-point) ; thingatpt+.el
(symbol-nearest-point))
((fboundp 'symbol-at-point) ; thingatpt.el
(symbol-at-point))
(t nil))))
(unless (and (boundp sym) (consp (symbol-value sym)))
(setq sym nil))
(intern-soft (funcall edit-list-completing-read-function
prompt obarray
(lambda (x)
(and (boundp x)
(symbol-value x)
(consp (symbol-value x))))
t
(and sym (symbol-name sym))))))
(defun edit-list (list-name)
"Edit a list called LIST-NAME interactively."
(interactive (list (edit-list-read-list-name "Edit list: ")))
(unless (and list-name (symbolp list-name))
(error "Given list name is not a symbol"))
(unless (boundp list-name)
(error "Given symbol is not bound"))
(let ((list-val (symbol-value list-name)))
(unless (consp list-val)
(error "Given symbol does not contain a list"))
(let ((buffer (generate-new-buffer (format "*Edit-List: %s*" list-name))))
(with-current-buffer buffer
(edit-list-mode)
(setq edit-list-list-name list-name)
(let ((print-escape-newlines pp-escape-newlines)
(print-quoted t))
(prin1 list-val (current-buffer)))
(pp-buffer)
(setq buffer-undo-list nil)
(set-buffer-modified-p nil))
(switch-to-buffer buffer)
(message "Make changes and hit `C-c C-c' when done"))))
(defun edit-list-done ()
"Save the given buffer back to the original list.
This finishes the work begun by `edit-list'."
(interactive)
(unless (and edit-list-list-name (symbolp edit-list-list-name)
(derived-mode-p 'edit-list-mode))
(error "This is not an Edit-List buffer"))
(goto-char (point-min))
(let ((name edit-list-list-name))
(set name (read (current-buffer)))
(kill-buffer (current-buffer))
(message "Saved changes to list `%s'" name)))
(provide 'edit-list)
;; edit-list.el ends here