diff options
author | Noam Postavsky <npostavs@gmail.com> | 2019-07-04 20:32:39 -0400 |
---|---|---|
committer | Noam Postavsky <npostavs@gmail.com> | 2019-08-03 20:14:52 -0400 |
commit | 01661f33c11654d1fe5fe1013332db2500b7f449 (patch) | |
tree | d46bd831f134d495373c8eb389c11f95d7c6028a /lisp/vc/log-edit.el | |
parent | 2d47483e815979d0ae0edd6f878b7fbb85fd72fa (diff) | |
download | emacs-01661f33c11654d1fe5fe1013332db2500b7f449.tar.gz emacs-01661f33c11654d1fe5fe1013332db2500b7f449.tar.bz2 emacs-01661f33c11654d1fe5fe1013332db2500b7f449.zip |
Improved ChangeLog generation for vc log (Bug#16301)
* lisp/vc/diff-mode.el (diff-find-source-location): Fix docstring.
* lisp/vc/add-log.el (change-log-unindented-file-names-re)
(change-log-read-entries, change-log-read-defuns)
(change-log-insert-entries):
* lisp/vc/diff-mode.el (diff-add-log-current-defuns):
* lisp/vc/log-edit.el (log-edit--insert-filled-defuns)
(log-edit-fill-entry): New functions.
(log-edit-mode): Set `log-edit-fill-entry' as
`fill-paragraph-function'.
(log-edit-generate-changelog-from-diff): New command.
(log-edit-mode-map): Bind it to C-c C-w.
* doc/emacs/maintaining.texi (Types of Log File, Log Buffer):
* CONTRIBUTE: Document it.
* etc/NEWS: Announce it.
* test/lisp/vc/log-edit-tests.el (log-edit-fill-entry)
(log-edit-fill-entry-joining): New tests.
Diffstat (limited to 'lisp/vc/log-edit.el')
-rw-r--r-- | lisp/vc/log-edit.el | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/lisp/vc/log-edit.el b/lisp/vc/log-edit.el index 91e18c1ec5c..8d47d66ac38 100644 --- a/lisp/vc/log-edit.el +++ b/lisp/vc/log-edit.el @@ -54,6 +54,7 @@ (easy-mmode-defmap log-edit-mode-map '(("\C-c\C-c" . log-edit-done) ("\C-c\C-a" . log-edit-insert-changelog) + ("\C-c\C-w" . log-edit-generate-changelog-from-diff) ("\C-c\C-d" . log-edit-show-diff) ("\C-c\C-f" . log-edit-show-files) ("\C-c\C-k" . log-edit-kill-buffer) @@ -488,10 +489,63 @@ commands (under C-x v for VC, for example). (set (make-local-variable 'font-lock-defaults) '(log-edit-font-lock-keywords t)) (setq-local jit-lock-contextually t) ;For the "first line is summary". + (setq-local fill-paragraph-function #'log-edit-fill-entry) (make-local-variable 'log-edit-comment-ring-index) (add-hook 'kill-buffer-hook 'log-edit-remember-comment nil t) (hack-dir-local-variables-non-file-buffer)) +(defun log-edit--insert-filled-defuns (func-names) + "Insert FUNC-NAMES, following ChangeLog formatting." + (if (not func-names) + (insert ":") + (unless (or (memq (char-before) '(?\n ?\s)) + (> (current-column) fill-column)) + (insert " ")) + (cl-loop for first-fun = t then nil + for def in func-names do + (when (> (+ (current-column) (string-width def)) fill-column) + (unless first-fun + (insert ")")) + (insert "\n")) + (insert (if (memq (char-before) '(?\n ?\s)) + "(" ", ") + def)) + (insert "):"))) + +(defun log-edit-fill-entry (&optional justify) + "Like \\[fill-paragraph], but handle ChangeLog entries. +Consecutive function entries without prose (i.e., lines of the +form \"(FUNCTION):\") will be combined into \"(FUNC1, FUNC2):\" +according to `fill-column'." + (save-excursion + (pcase-let ((`(,beg ,end) (log-edit-changelog-paragraph))) + (if (= beg end) + ;; Not a ChangeLog entry, fill as normal. + nil + (cl-callf copy-marker end) + (goto-char beg) + (cl-loop + for defuns-beg = + (and (< beg end) + (re-search-forward + (concat "\\(?1:" change-log-unindented-file-names-re + "\\)\\|^\\(?1:\\)(") + end t) + (copy-marker (match-end 1))) + ;; Fill prose between log entries. + do (let ((fill-indent-according-to-mode t) + (end (if defuns-beg (match-beginning 0) end)) + (beg (progn (goto-char beg) (line-beginning-position)))) + (when (<= (line-end-position) end) + (fill-region beg end justify))) + while defuns-beg + for defuns = (progn (goto-char defuns-beg) + (change-log-read-defuns end)) + do (progn (delete-region defuns-beg (point)) + (log-edit--insert-filled-defuns defuns) + (setq beg (point)))) + t)))) + (defun log-edit-hide-buf (&optional buf where) (when (setq buf (get-buffer (or buf log-edit-files-buf))) ;; FIXME: Should use something like `quit-windows-on' here, but @@ -726,6 +780,27 @@ to build the Fixes: header.") (replace-match (concat " " value) t t nil 1) (insert field ": " value "\n" (if (looking-at "\n") "" "\n")))) +(declare-function diff-add-log-current-defuns "diff-mode" ()) + +(defun log-edit-generate-changelog-from-diff () + "Insert a log message by looking at the current diff. +This command will generate a ChangeLog entries listing the +functions. You can then add a description where needed, and use +\\[fill-paragraph] to join consecutive function names." + (interactive) + (let* ((diff-buf nil) + ;; Unfortunately, `log-edit-show-diff' doesn't have a NO-SHOW + ;; option, so we try to work around it via display-buffer + ;; machinery. + (display-buffer-overriding-action + `(,(lambda (buf alist) + (setq diff-buf buf) + (display-buffer-no-window buf alist)) + . ((allow-no-window . t))))) + (change-log-insert-entries + (with-current-buffer (progn (log-edit-show-diff) diff-buf) + (diff-add-log-current-defuns))))) + (defun log-edit-insert-changelog (&optional use-first) "Insert a log message by looking at the ChangeLog. The idea is to write your ChangeLog entries first, and then use this |