From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Noam Postavsky Newsgroups: gmane.emacs.bugs Subject: bug#16301: 24.3.50; [Feature] Split add-change-log-entry to make it reusable Date: Tue, 16 Jul 2019 19:47:35 -0400 Message-ID: <87ims1zgmg.fsf@gmail.com> References: <87bnzyv7aj.fsf@hati.baby-gnu.org> <874l415jl3.fsf@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="17376"; mail-complaints-to="usenet@blaine.gmane.org" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.2.90 (gnu/linux) Cc: 16301@debbugs.gnu.org To: Daniel Dehennin Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Wed Jul 17 01:48:13 2019 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1hnXB5-0004NM-UM for geb-bug-gnu-emacs@m.gmane.org; Wed, 17 Jul 2019 01:48:13 +0200 Original-Received: from localhost ([::1]:52944 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hnXB4-0004yR-Vz for geb-bug-gnu-emacs@m.gmane.org; Tue, 16 Jul 2019 19:48:10 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:37273) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hnXAz-0004ux-Eu for bug-gnu-emacs@gnu.org; Tue, 16 Jul 2019 19:48:08 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hnXAw-0006dV-La for bug-gnu-emacs@gnu.org; Tue, 16 Jul 2019 19:48:05 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:42520) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hnXAw-0006dK-BX for bug-gnu-emacs@gnu.org; Tue, 16 Jul 2019 19:48:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1hnXAw-00043N-9U for bug-gnu-emacs@gnu.org; Tue, 16 Jul 2019 19:48:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Noam Postavsky Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 16 Jul 2019 23:48:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 16301 X-GNU-PR-Package: emacs Original-Received: via spool by 16301-submit@debbugs.gnu.org id=B16301.156332087215566 (code B ref 16301); Tue, 16 Jul 2019 23:48:02 +0000 Original-Received: (at 16301) by debbugs.gnu.org; 16 Jul 2019 23:47:52 +0000 Original-Received: from localhost ([127.0.0.1]:51341 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1hnXAl-00042u-B1 for submit@debbugs.gnu.org; Tue, 16 Jul 2019 19:47:52 -0400 Original-Received: from mail-io1-f48.google.com ([209.85.166.48]:42256) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1hnXAd-00042X-DY; Tue, 16 Jul 2019 19:47:45 -0400 Original-Received: by mail-io1-f48.google.com with SMTP id e20so12534365iob.9; Tue, 16 Jul 2019 16:47:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version; bh=/XTpW+DUMc89+uS4AaNM0RjWN/Yupy+UOHMOBnb516M=; b=pnaGlk5r/OYa0d64JOcPlB6pGq7IPUcvVDRlv5BLWF2xCNyUfjuJKBKtypxpDESSab AuHi3FPlLs98/JxYI3EglA9vA7HMb/56mMT/0BdheJyhroLFc3ifZLPiYkI3wOLrUU40 +XnQ5ki8sqzWe4O9bsZ+WUbV2CkvxvfbUEsdoBrVqM/NsKK0DM9FjlrTUluEe6Wm4T7S NrvxZd++uTdWKnWVnCj8pulpfG+oiE9IxeRrjl+V+FybV9Pp2eMlkyxgkaVUlUG0ewY4 xOq4+tvse34WIazYyD+R1JIueNPC4eMUZfbExNM61N1uF6Ky2QHK5BEAk88e/qLkhU9i Q0tg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version; bh=/XTpW+DUMc89+uS4AaNM0RjWN/Yupy+UOHMOBnb516M=; b=Xa3JMoO23jT2D4LUjTXwqY68ImFRVHnQmJ9MXhbe6jTUNg27DNtOfc/epuWU+fFKJc Yjl/ts182b9VbjSr+N4447A0Xog6kUIQEWHFn169b5kCgh+O4p/l6a9fmeRaODSnXZlU HL5s3rg92xmeBsQM2Tky4jTB878j7cJ80nMviypYXJlAMBZU4LndEYYoj6WPxWjE9WUZ VogroW+qzNNOCuYouq50cjD0y8H0tGTSlb1R+TgPUxId/V+TFljXhwdmWabnQ0ifWHm6 ICsXSlF0FFkynBYzIJRa445p/hpYmKpT98aw16kC2b1KGxO9YPOkUwDyT9bvp2zkxv3L PWew== X-Gm-Message-State: APjAAAU9xNK7N7saeHck3TNxQAauIlwz8JWNxvtq9cJmPodukeuyMTB3 a6Az1Hlg79f5nVbvBWPB0P4e2dpn X-Google-Smtp-Source: APXvYqwxfpXKj1FV14Kq0/TFj/ycXEP1Y8dK/T1kIqLNa7rU7uJ1+mNAX0LQ/5E+88hDig7rDhfG5Q== X-Received: by 2002:a05:6602:114:: with SMTP id s20mr32019013iot.122.1563320857554; Tue, 16 Jul 2019 16:47:37 -0700 (PDT) Original-Received: from minid (cbl-45-2-119-34.yyz.frontiernetworks.ca. [45.2.119.34]) by smtp.gmail.com with ESMTPSA id c14sm17495961ioa.22.2019.07.16.16.47.36 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 16 Jul 2019 16:47:36 -0700 (PDT) In-Reply-To: <874l415jl3.fsf@gmail.com> (Noam Postavsky's message of "Thu, 04 Jul 2019 21:57:44 -0400") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.51.188.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:163216 Archived-At: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable tags 16301 + patch quit >> I propose to split the =E2=80=9Cadd-change-log-entry=E2=80=9D function t= o make parts >> usable by third parties. > > I've started working on this, patch attached below. It's not entirely > baked, but I thought I'd post it now to let people know about it. I've made enough progress that this should be usable by now. One problem I noticed is that add-log-current-defun returns "foo" for lines like (require 'foo) Which is usually not wanted. So we might try to make add-log-current-defun a bit more discriminating, although missing definitions might be more annoying than false positives. --=-=-= Content-Type: text/plain Content-Disposition: attachment; filename=0001-Improved-ChangeLog-generation-for-vc-log-Bug-16301.patch Content-Description: patch >From 74f28ab974fd1690381f0a4f3e47f95c8ab83ce0 Mon Sep 17 00:00:00 2001 From: Noam Postavsky Date: Thu, 4 Jul 2019 20:32:39 -0400 Subject: [PATCH] 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-generate-changelog-from-diff): New command. (log-edit-mode-map): Bind it to C-c C-w. (log-edit-mode): Set it as `fill-paragraph-function'. * doc/emacs/maintaining.texi (Types of Log File, Log Buffer): Document it. * etc/NEWS: Announce it. * test/lisp/vc/log-edit-tests.el (log-edit-fill-entry): New test. --- doc/emacs/maintaining.texi | 13 ++++- etc/NEWS | 4 ++ lisp/vc/add-log.el | 36 ++++++++++++ lisp/vc/diff-mode.el | 127 +++++++++++++++++++++++++++++++++++++++-- lisp/vc/log-edit.el | 67 ++++++++++++++++++++++ test/lisp/vc/log-edit-tests.el | 90 +++++++++++++++++++++++++++++ 6 files changed, 331 insertions(+), 6 deletions(-) create mode 100644 test/lisp/vc/log-edit-tests.el diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index 4986c11103..da500338a9 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -396,8 +396,9 @@ Types of Log File for each change just once, then put it into both logs. You can write the entry in @file{ChangeLog}, then copy it to the log buffer with @kbd{C-c C-a} when committing the change (@pxref{Log Buffer}). Or you -can write the entry in the log buffer while committing the change, and -later use the @kbd{C-x v a} command to copy it to @file{ChangeLog} +can write the entry in the log buffer while committing the change +(with the help of @kbd{C-c C-w}), and later use the @kbd{C-x v a} +command to copy it to @file{ChangeLog} @iftex (@pxref{Change Logs and VC,,,emacs-xtra, Specialized Emacs Features}). @end iftex @@ -677,6 +678,14 @@ Log Buffer started editing (@pxref{Old Revisions}), type @kbd{C-c C-d} (@code{log-edit-show-diff}). +@kindex C-c C-w @r{(Log Edit mode)} +@findex log-edit-generate-changelog + To help generate ChangeLog entries, type @kbd{C-c C-w} +(@code{log-edit-generate-changelog}), to generate skeleton ChangeLog +entries, listing all changed file and function names based on the diff +of the VC fileset. Consecutive entries left empty will be combined by +@kbd{C-q} (@code{fill-paragraph}). + @kindex C-c C-a @r{(Log Edit mode)} @findex log-edit-insert-changelog If the VC fileset includes one or more @file{ChangeLog} files diff --git a/etc/NEWS b/etc/NEWS index 06d5e93d02..f7b4f041f4 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -649,6 +649,10 @@ The default value is 'find-dired-sort-by-filename'. ** Change Logs and VC ++++ +*** New command 'log-edit-generate-changelog', bound to C-c C-w. +This generates ChangeLog entries from the VC fileset diff. + *** Recording ChangeLog entries doesn't require an actual file. If a ChangeLog file doesn't exist, and if the new variable 'add-log-dont-create-changelog-file' is non-nil (which is the diff --git a/lisp/vc/add-log.el b/lisp/vc/add-log.el index f9efd44c5c..df665887f1 100644 --- a/lisp/vc/add-log.el +++ b/lisp/vc/add-log.el @@ -36,6 +36,8 @@ ;;; Code: +(eval-when-compile (require 'cl-lib)) + (defgroup change-log nil "Change log maintenance." :group 'tools @@ -309,6 +311,40 @@ change-log-search-file-name (re-search-forward change-log-file-names-re nil t) (match-string-no-properties 2)))))) +(defconst change-log-unindented-file-names-re "^[*] \\([^ ,:([\n]+\\)") + +(defun change-log-read-entries (&optional end) + "Read ChangeLog entries at point until END. +Move point to the end of entries that were read. Return a list +in the same form as `diff-add-log-current-defuns'." + (cl-loop while (and (or (not end) (< (point) end)) + (looking-at change-log-unindented-file-names-re)) + do (goto-char (match-end 0)) + collect (cons (match-string-no-properties 1) + (change-log-read-defuns end)))) + +(defvar change-log-tag-re) ; add-log.el +(defun change-log-read-defuns (&optional end) + "Read ChangeLog formatted function names at point until END. +Move point to the end of names read and return the function names +as a list of strings." + (cl-loop while (and (skip-chars-forward ":\n[:blank:]" end) + (or (not end) (< (point) end)) + (looking-at change-log-tag-re)) + do (goto-char (match-end 0)) + nconc (split-string (match-string-no-properties 1) + ",[[:blank:]]*" t) + finally do (skip-chars-backward "\n[:blank:]"))) + +(defun change-log-insert-entries (changelogs) + "Format and insert CHANGELOGS into current buffer. +CHANGELOGS is a list in the form returned by +`diff-add-log-current-defuns'." + (cl-loop for (file . defuns) in changelogs do + (insert "* " file " ") + (cl-loop for def in defuns + do (insert "(" def "):\n")))) + (defun change-log-find-file () "Visit the file for the change under point." (interactive) diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index 0d5dc0e1c0..2397d43e16 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -54,6 +54,7 @@ ;;; Code: (eval-when-compile (require 'cl-lib)) +(eval-when-compile (require 'subr-x)) (autoload 'vc-find-revision "vc") (autoload 'vc-find-revision-no-save "vc") @@ -1773,15 +1774,22 @@ diff-find-approx-text (defsubst diff-xor (a b) (if a (if (not b) a) b)) (defun diff-find-source-location (&optional other-file reverse noprompt) - "Find out (BUF LINE-OFFSET POS SRC DST SWITCHED). + "Find current diff location within the source file. +OTHER-FILE, if non-nil, means to look at the diff's name and line + numbers for the old file. Furthermore, use `diff-vc-revisions' + if it's available. If `diff-jump-to-old-file' is non-nil, the + sense of this parameter is reversed. If the prefix argument is + 8 or more, `diff-jump-to-old-file' is set to OTHER-FILE. +REVERSE, if non-nil, switches the sense of SRC and DST (see below). +NOPROMPT, if non-nil, means not to prompt the user. +Return a list (BUF LINE-OFFSET (BEG . END) SRC DST SWITCHED). BUF is the buffer corresponding to the source file. LINE-OFFSET is the offset between the expected and actual positions of the text of the hunk or nil if the text was not found. -POS is a pair (BEG . END) indicating the position of the text in the buffer. +\(BEG . END) is a pair indicating the position of the text in the buffer. SRC and DST are the two variants of text as returned by `diff-hunk-text'. SRC is the variant that was found in the buffer. -SWITCHED is non-nil if the patch is already applied. -NOPROMPT, if non-nil, means not to prompt the user." +SWITCHED is non-nil if the patch is already applied." (save-excursion (let* ((other (diff-xor other-file diff-jump-to-old-file)) (char-offset (- (point) (diff-beginning-of-hunk t))) @@ -2210,6 +2218,117 @@ diff-undo (let ((inhibit-read-only t)) (undo arg))) +(defun diff-add-log-current-defuns () + "Return an alist of defun names for the current diff. +The elements of the alist are of the form (FILE . (DEFUN...)), +where DEFUN... is a list of function names found in FILE." + (save-excursion + (goto-char (point-min)) + (let ((defuns nil) + (hunk-end nil) + (hunk-mismatch-files nil) + (make-defun-context-follower + (lambda (goline) + (let ((eodefun nil) + (defname nil)) + (list + (lambda () ;; Check for end of current defun. + (when (and eodefun + (funcall goline) + (>= (point) eodefun)) + (setq defname nil) + (setq eodefun nil))) + (lambda (&optional get-current) ;; Check for new defun. + (if get-current + defname + (when-let* ((def (and (not eodefun) + (funcall goline) + (add-log-current-defun))) + (eof (save-excursion (end-of-defun) (point)))) + (setq eodefun eof) + (setq defname def))))))))) + (while + ;; Might need to skip over file headers between diff + ;; hunks (e.g., "diff --git ..." etc). + (re-search-forward diff-hunk-header-re nil t) + (setq hunk-end (save-excursion (diff-end-of-hunk))) + (pcase-let* ((filename (substring-no-properties (diff-find-file-name))) + (=lines 0) + (+lines 0) + (-lines 0) + (`(,buf ,line-offset (,beg . ,_end) + (,old-text . ,_old-offset) + (,new-text . ,_new-offset) + ,applied) + ;; Try to use the vc integration of + ;; `diff-find-source-location', unless it + ;; would look for non-existent files like + ;; /dev/null. + (diff-find-source-location + (not (equal "/dev/null" + (car (diff-hunk-file-names t)))))) + (other-buf nil) + (goto-otherbuf + ;; If APPLIED, we have NEW-TEXT in BUF, so we + ;; need to a buffer with OLD-TEXT to follow + ;; -lines. + (lambda () + (if other-buf (set-buffer other-buf) + (set-buffer (generate-new-buffer " *diff-other-text*")) + (insert (if applied old-text new-text)) + (funcall (buffer-local-value 'major-mode buf)) + (setq other-buf (current-buffer))) + (goto-char (point-min)) + (forward-line (+ =lines -1 + (if applied -lines +lines))))) + (gotobuf (lambda () + (set-buffer buf) + (goto-char beg) + (forward-line (+ =lines -1 + (if applied +lines -lines))))) + (`(,=ck-eodefun ,=ck-defun) + (funcall make-defun-context-follower gotobuf)) + (`(,-ck-eodefun ,-ck-defun) + (funcall make-defun-context-follower + (if applied goto-otherbuf gotobuf))) + (`(,+ck-eodefun ,+ck-defun) + (funcall make-defun-context-follower + (if applied gotobuf goto-otherbuf)))) + (unless (eql line-offset 0) + (cl-pushnew filename hunk-mismatch-files :test #'equal)) + (unwind-protect + (while (progn (forward-line) + (< (point) hunk-end)) + (let ((patch-char (char-after))) + (pcase patch-char + (?+ (cl-incf +lines)) + (?- (cl-incf -lines)) + (?\s (cl-incf =lines))) + (save-current-buffer + (funcall =ck-eodefun) + (funcall +ck-eodefun) + (funcall -ck-eodefun) + (when-let* ((def (cond + ((eq patch-char ?\s) + ;; Just updating context defun. + (ignore (funcall =ck-defun))) + ;; + or - in existing defun. + ((funcall =ck-defun t)) + ;; Check added or removed defun. + (t (funcall (if (eq ?+ patch-char) + +ck-defun -ck-defun)))))) + (cl-pushnew def (alist-get filename defuns + nil nil #'equal) + :test #'equal))))) + (when (buffer-live-p other-buf) + (kill-buffer other-buf))))) + (when hunk-mismatch-files + (message "Diff didn't match for %s." + (mapconcat #'identity hunk-mismatch-files ", "))) + (dolist (file-defuns defuns) + (cl-callf nreverse (cdr file-defuns))) + (nreverse defuns)))) + (defun diff-add-change-log-entries-other-window () "Iterate through the current diff and create ChangeLog entries. I.e. like `add-change-log-entry-other-window' but applied to all hunks." diff --git a/lisp/vc/log-edit.el b/lisp/vc/log-edit.el index 91e18c1ec5..f375e10d79 100644 --- a/lisp/vc/log-edit.el +++ b/lisp/vc/log-edit.el @@ -54,6 +54,7 @@ cvs-buffer (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,55 @@ log-edit-mode (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." + (cl-loop for def in func-names do + (when (> (+ (current-column) (string-width def)) fill-column) + (insert (if (memq (char-before) '(?\n ?\s)) + "\n" ")\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 normally, but don't pick up indentation. + do (let ((fill-indent-according-to-mode t)) + (fill-region (progn (goto-char beg) (line-beginning-position)) + (if defuns-beg (match-beginning 0) 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 +772,27 @@ log-edit-add-field (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 diff --git a/test/lisp/vc/log-edit-tests.el b/test/lisp/vc/log-edit-tests.el new file mode 100644 index 0000000000..e48ad4f610 --- /dev/null +++ b/test/lisp/vc/log-edit-tests.el @@ -0,0 +1,90 @@ +;;; log-edit-tests.el --- Unit tests for log-edit.el -*- lexical-binding: t; -*- + +;; Copyright (C) 2019 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. + +;; GNU Emacs 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 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs 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. If not, see . + +;;; Commentary: + +;; Unit tests for lisp/vc/log-edit.el. + +;;; Code: + +(require 'log-edit) +(require 'ert) + +(ert-deftest log-edit-fill-entry () + (with-temp-buffer + (insert "\ +* dir/file.ext (fun1): +\(fun2): +\(fun3): +* file2.txt (fun4): +\(fun5): +\(fun6): +\(fun7): Some prose. +\(fun8): A longer description of a complicated change.\ + Spread over a couple of sentencences.\ + Long enough to be filled for several lines. +\(fun9): Etc.") + (goto-char (point-min)) + (let ((fill-column 72)) (log-edit-fill-entry)) + (should (equal (buffer-string) "\ +* dir/file.ext (fun1, fun2, fun3): +* file2.txt (fun4, fun5, fun6, fun7): Some prose. +\(fun8): A longer description of a complicated change. Spread over a +couple of sentencences. Long enough to be filled for several lines. +\(fun9): Etc.")) + (let ((fill-column 20)) (log-edit-fill-entry)) + (should (equal (buffer-string) "\ +* dir/file.ext (fun1) +\(fun2, fun3): +* file2.txt (fun4) +\(fun5, fun6, fun7): +Some prose. +\(fun8): A longer +description of a +complicated change. +Spread over a couple +of sentencences. +Long enough to be +filled for several +lines. +\(fun9): Etc.")) + (let ((fill-column 40)) (log-edit-fill-entry)) + (should (equal (buffer-string) "\ +* dir/file.ext (fun1, fun2, fun3): +* file2.txt (fun4, fun5, fun6, fun7): +Some prose. +\(fun8): A longer description of a +complicated change. Spread over a +couple of sentencences. Long enough to +be filled for several lines. +\(fun9): Etc.")))) + +(ert-deftest log-edit-fill-entry-trailing-prose () + (with-temp-buffer + (insert "\ +* dir/file.ext (fun1): A longer description of a complicated change.\ + Spread over a couple of sentencences.\ + Long enough to be filled for several lines.") + (let ((fill-column 72)) (log-edit-fill-entry)) + (should (equal (buffer-string) "\ +* dir/file.ext (fun1): A longer description of a complicated change. +Spread over a couple of sentencences. Long enough to be filled for +several lines.")))) + +;;; log-edit-tests.el ends here -- 2.11.0 --=-=-=--