gnu-emacs-sources
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: edit-list.el v0.1


From: Rupert Swarbrick
Subject: Re: edit-list.el v0.1
Date: Mon, 31 Mar 2008 07:51:19 -0500
User-agent: Pan/0.132 (Waxed in Black)

On Sun, 30 Mar 2008 21:53:47 -0700, Michael Olson wrote:

> 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.
> 

That's really cool! I'll definitely be using it. But I thought I'd really 
like completion in the minibuffer, so I've added it (cribbing some ideas 
from strings.el)

Hope this is interesting (and indeed works!)

;;; Edit List mode (modified, Rupert Swarbrick)

;; Utility function.
(defun read-any-something (grand-list
                           predicate
                           prompt
                           &optional default-value transform)
  "Use completing-read to get a match from GRAND-LIST matching
PREDICATE. Use PROMPT as the minibuffer prompt. DEFAULT-VALUE is
a default value to use for the minibuffer match and TRANSFORM (if
non-nil) is applied to the match afterwards. Heavily based on
Drew Adams's read-any-variable from strings.el"
  (let ((enable-recursive-minibuffers t))
    ;; We want default-value to be set to a string "pretending" to be
    ;; default-value so that it makes sense in the minibuffer.
    (when default-value
      (setf default-value (format "%s" default-value)))
    
    (funcall (if transform
                 transform (lambda (x) x))
             (completing-read prompt
                              grand-list
                              predicate
                              t
                              nil
                              'minibuffer-history
                              default-value ; might be nil
                              t))))

(defun read-any-list (prompt &optional allow-nil)
  "Use completing-read to get a list from the currently defined
symbols with prompt PROMPT. If allow-nil, then we also return
symbols whose value is nil (which can be taken to be a list - or
not)."
  (let ((match
         (cond ((fboundp 'symbol-nearest-point) (symbol-nearest-point))
               ((fboundp 'symbol-at-point) (symbol-at-point))
               (t nil))))
    (unless (listp match)
      (setf match nil))

    (read-any-something obarray
                        (lambda (x)
                          (and (symbolp x)
                               (boundp x)
                               (or allow-nil (symbol-value x))
                               (listp (symbol-value x))))
                        prompt
                        match
                        #'intern-soft)))
  

(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 (list-name)
  "Edit a list called LIST-NAME interactively."
  (interactive (list (read-any-list "List to edit: ")))

  (unless (and list-name (symbolp list-name))
    (error "Given list name [%s] is not a symbol" list-name))
  (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))
      (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)))

;; EOF: edit list mode


reply via email to

[Prev in Thread] Current Thread [Next in Thread]