Add command to update buffer.

The new commands poporg-update and poporg-update-and-save allow you to update
the original buffer while keeping the poporg buffer; the latter also saves the
original buffer.
master
Joe Rabinoff 9 years ago
parent d4d8b3e620
commit 667f976565
  1. 18
      README.org
  2. 158
      poporg.el

@ -59,7 +59,7 @@ Hopefully =poporg-dwim= will do what you expect in most situations. It uses the
buffer's syntax table for parsing, so it should adapt well to most modes
(including sextuple-quoted strings in Python). If you run =poporg-dwim= in the
vicinity of a grayed-out region that you are editing in another buffer, it pops
to that buffer. It has the following caveats:
to that buffer. It has the following limitations:
1. It does not understand empty strings.
2. It cannot deal very well with comments with ending delimiters.
@ -82,10 +82,18 @@ the middle lines, depending on whether the =*= character is matched by
You will probably want to customize =poporg-edit-hook=, since that is where the
major mode of the edit buffer is set. The minor mode =poporg-mode= is activated
in the edit buffer. It has one keybinding by default, which remaps =save-buffer=
(C-x C-s) to =poporg-edit-exit=. You can add additional keybindings to
=poporg-mode-map=. To save an edit, from the editing buffer run =poporg-edit-exit=
or =poporg-dwim=; to abort the edit simply kill the buffer.
in the edit buffer. It contains the following keybindings by default:
| Command | Keybinding | Description |
|------------------------+------------+-----------------------------------|
| *poporg-edit-exit* | =C-x C-s= | Save edit and kill poporg buffer |
| *poporg-update* | =C-c C-c= | Save edit and keep poporg buffer |
| *poporg-update-and-save* | =C-c C-s= | Save edit and keep poporg buffer; |
| | | then save original buffer |
|------------------------+------------+-----------------------------------|
You can add additional keybindings to =poporg-mode-map=. To abort the edit simply
kill the buffer.
** History

@ -101,6 +101,8 @@ By default this hook enables `org-mode'."
(defvar poporg-mode-map
(let ((map (make-sparse-keymap)))
(define-key map [remap save-buffer] 'poporg-edit-exit)
(define-key map (kbd "C-c C-c") 'poporg-update)
(define-key map (kbd "C-c C-s") 'poporg-update-and-save)
map)
"Keys used in `poporg-mode' buffers.")
@ -134,8 +136,7 @@ Dynamically bound variable.")
Dynamically bound variable.")
(defvar poporg-pre-window-configuration nil
"Variable to store the window configuration from before poporg buffer was
opened.")
"Variable to store the original window configuration.")
;; * Functions
@ -269,23 +270,24 @@ onto the first line. Delete trailing whitespace from blank lines if
(let ((cur-buf (current-buffer))
(prefix-no-ws (poporg-chomp-end prefix)))
(with-current-buffer buf
(goto-char (point-min))
(while (not (eobp))
(let* ((s (point))
(char-at (char-after s))
e)
(forward-line 1)
(setq e (point))
(with-current-buffer cur-buf
(if no-first
(setq no-first nil)
(if (and poporg-delete-trailing-whitespace
(or (null char-at) (= char-at ?\n)))
;; strip whitespace from prefix for blank lines
(unless (eq poporg-delete-trailing-whitespace 'all)
(insert prefix-no-ws))
(insert prefix)))
(poporg-insert-substring buf s e)))))))
(save-excursion
(goto-char (point-min))
(while (not (eobp))
(let* ((s (point))
(char-at (char-after s))
e)
(forward-line 1)
(setq e (point))
(with-current-buffer cur-buf
(if no-first
(setq no-first nil)
(if (and poporg-delete-trailing-whitespace
(or (null char-at) (= char-at ?\n)))
;; strip whitespace from prefix for blank lines
(unless (eq poporg-delete-trailing-whitespace 'all)
(insert prefix-no-ws))
(insert prefix)))
(poporg-insert-substring buf s e))))))))
;; *** find string or comment
@ -447,12 +449,12 @@ END are markers."
(set-marker (make-marker) end2)
prefix)))
(defun poporg-insert-comment-lines (buf start end prefix)
(defun poporg-insert-comment-lines (buf start end prefix overlay)
"Insert the contents of BUF as comments in the current buffer.
Replace the region from START to END and prepend PREFIX onto each line. Append
a trailing newline if necessary. Uses `poporg-insert-with-prefix' to do the
work."
work. Move OVERLAY to the newly-inserted region."
(poporg-insert-with-prefix buf start end prefix)
;; For our purposes, comments always comprise entire lines, so insert a
;; trailing newline if necessary.
@ -460,7 +462,8 @@ work."
(save-excursion
(goto-char (point-max))
(and (char-before) (not (= (char-before) ?\n)))))
(insert "\n")))
(insert "\n"))
(move-overlay overlay start (point)))
;; *** insert from string
@ -538,28 +541,33 @@ this function has the same usage as `poporg-get-comment-lines')."
(set-marker (make-marker) end)
prefix)))
(defun poporg-insert-string-lines (buf start end prefix)
(defun poporg-insert-string-lines (buf start end prefix overlay)
"Insert the contents of BUF into a string in the current buffer.
Replace the string between START and END and prepend PREFIX onto each interior
line. Skip delimiters on both sides. Uses `poporg-insert-with-prefix' to do
the work."
(save-excursion
(goto-char start)
(skip-syntax-forward "\"|")
(setq start (point)))
(save-excursion
(goto-char end)
(skip-syntax-backward "\"|")
(setq end (point)))
(poporg-insert-with-prefix buf start end prefix 'no-first-line)
;; if the buffer is terminated by a newline, need to prepend the prefix before
;; the closing delimiter
(when (with-current-buffer buf
(save-excursion
(goto-char (point-max))
(= (char-before) ?\n)))
(insert prefix)))
the work. Move OVERLAY to the newly-inserted region."
(let ((start-mark (set-marker (make-marker) start))
(end-mark (set-marker (make-marker) end)))
(save-excursion
(goto-char start)
(skip-syntax-forward "\"|")
(setq start (point)))
(save-excursion
(goto-char end)
(skip-syntax-backward "\"|")
(setq end (point)))
(poporg-insert-with-prefix buf start end prefix 'no-first-line)
;; if the buffer is terminated by a newline, need to prepend the prefix before
;; the closing delimiter
(when (with-current-buffer buf
(save-excursion
(goto-char (point-max))
(= (char-before) ?\n)))
(insert prefix))
(move-overlay overlay
(marker-position start-mark)
(marker-position end-mark))))
;; *** insert from region
@ -597,13 +605,15 @@ and END are the same as the passed arguments."
(set-marker (make-marker) end)
prefix)))))
(defun poporg-insert-region-lines (buf start end prefix)
(defun poporg-insert-region-lines (buf start end prefix overlay)
"Insert the contents of BUF into the current buffer.
Replace the region between START and END and prepend PREFIX onto each line.
This simply runs `poporg-insert-with-prefix'."
This simply runs `poporg-insert-with-prefix'. Move OVERLAY to the
newly-inserted region."
;; don't have to do anything special
(poporg-insert-with-prefix buf start end prefix))
(poporg-insert-with-prefix buf start end prefix)
(move-overlay overlay start (point)))
;; ** make text mode buffer
@ -633,10 +643,21 @@ buffer instead."
;; Initialize a popup edit buffer.
(pop-to-buffer edit-buffer)
(goto-char poporg-new-point)
(set-buffer-modified-p nil)
;; Don't allow undoing the initial buffer insertions.
(buffer-disable-undo)
(buffer-enable-undo)
;; Save buffer contents to a temporary file so the undo command knows
;; whether the contents have modified or not. This could potentially have
;; other uses later on.
(let ((buf-name (buffer-name)))
(set-visited-file-name (make-temp-file "poporg-"))
(rename-buffer buf-name t))
(let ((require-final-newline nil)) (save-buffer))
;; This is mainly to hide the `save-buffer' message
(message
(substitute-command-keys
"poporg: type \\<poporg-mode-map>\\[poporg-edit-exit] when done"))
;;(set-buffer-modified-p nil)
;; Save data and possibly activate hooks.
(unless poporg-data
(push 'poporg-kill-buffer-query kill-buffer-query-functions)
@ -673,6 +694,8 @@ buffer instead."
(defun poporg-kill-buffer-routine ()
"Cleanup an edit buffer whenever killed."
;; Delete the temporary file
(ignore-errors (set-buffer-modified-p nil) (delete-file (buffer-file-name)))
(let ((entry (assq (current-buffer) poporg-data)))
(when entry
(let* ((overlay (cadr entry))
@ -718,9 +741,13 @@ edit that instead."
(user-error "Nothing to edit!"))))))))
;;;###autoload
(defun poporg-edit-exit ()
"Exit the edit buffer, replacing the original region."
(interactive)
(defun poporg-update (with-save)
"Update the contents of the original buffer.
If prefix argument WITH-SAVE is non-nil, save the original buffer too.
Also update the overlay."
(interactive "P")
(let* ((edit-buffer (current-buffer))
(entry (assq edit-buffer poporg-data))
(overlay (cadr entry))
@ -728,13 +755,10 @@ edit that instead."
(prefix (caddr entry))
(type (nth 3 entry))
(poporg-orig-point (point))
poporg-new-point
(inserter (intern (concat "poporg-insert-"
(symbol-name type) "-lines"))))
(unless buffer
(error "Not an edit buffer or original buffer vanished"))
(with-demoted-errors "Edit hook error: %S"
(run-hooks 'poporg-edit-exit-hook))
(when (buffer-modified-p)
;; Move everything back in place.
;; Allow the inserter to edit the region.
@ -743,8 +767,38 @@ edit that instead."
(let* ((start (overlay-start overlay))
(end (overlay-end overlay)))
(with-current-buffer buffer
(funcall inserter edit-buffer start end prefix))
(set-buffer-modified-p nil)))
;; This updates the overlay
(funcall inserter edit-buffer start end prefix overlay))
;; This is only used to mark the buffer as saved at this tamestamp, so
;; undo knows at what stage the buffer is unmodified
(let ((require-final-newline nil)) (save-buffer))
;; This is manily to hide the `save-buffer' message
(message "poporg: original buffer updated"))
(overlay-put overlay 'intangible t)
(overlay-put overlay 'read-only t))
(with-current-buffer buffer (undo-boundary))
(when with-save (with-current-buffer buffer (save-buffer)))))
;;;###autoload
(defun poporg-update-and-save ()
"Update and save the original buffer; update the region."
(interactive)
(poporg-update t))
;;;###autoload
(defun poporg-edit-exit ()
"Exit the edit buffer, replacing the original region."
(interactive)
(let* ((edit-buffer (current-buffer))
(entry (assq edit-buffer poporg-data))
(overlay (cadr entry))
(buffer (when overlay (overlay-buffer overlay)))
poporg-new-point)
(unless buffer
(error "Not an edit buffer or original buffer vanished"))
(poporg-update nil)
(with-demoted-errors "Edit hook error: %S"
(run-hooks 'poporg-edit-exit-hook))
;; Killing the buffer triggers a cleanup through the kill hook.
(kill-buffer edit-buffer)
(set-window-configuration poporg-pre-window-configuration)

Loading…
Cancel
Save