changeset 5766:182d01410b8d

Add mode-require-final-newline from GNU. Thanks GNU. lisp/ChangeLog: 2013-09-15 Mats Lidell <matsl@cxemacs.org> * files.el (mode-require-final-newline): Variable synced from GNU. Thank you GNU. Allows modes to control final newlines. (require-final-newline): Add action on visiting and visiting or saving in sync with GNU. * text-mode.el (text-mode): Use mode-require-final-newline. man/ChangeLog: 2013-09-15 Mats Lidell <matsl@xemacs.org> * xemacs/files.texi (Saving): New variable mode-require-final-newline. Update info for require-final-newline. tests/ChangeLog: 2013-09-15 Mats Lidell <matsl@xemacs.org> * automated/files-tests.el: New file. Test new states in require-final-newline and new variable mode-require-final-newline.
author Mats Lidell <mats.lidell@cag.se>
date Mon, 16 Sep 2013 00:00:12 +0200
parents e88d026f3917
children 4e69b24a2301
files lisp/ChangeLog lisp/files.el lisp/text-mode.el man/ChangeLog man/xemacs/files.texi tests/ChangeLog tests/automated/files-tests.el
diffstat 7 files changed, 206 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Sun Sep 15 23:50:20 2013 +0900
+++ b/lisp/ChangeLog	Mon Sep 16 00:00:12 2013 +0200
@@ -1,3 +1,11 @@
+2013-09-15  Mats Lidell  <matsl@cxemacs.org>
+
+	* files.el (mode-require-final-newline): Variable synced from
+	GNU. Thank you GNU. Allows modes to control final newlines.
+	(require-final-newline): Add action on visiting and visiting or
+	saving in sync with GNU.
+	* text-mode.el (text-mode): Use mode-require-final-newline.
+
 2013-09-10  Stephen J. Turnbull  <stephen@xemacs.org>
 
 	* fontconfig.el (fc-name-parse-known-problem-attributes): New.
--- a/lisp/files.el	Sun Sep 15 23:50:20 2013 +0900
+++ b/lisp/files.el	Mon Sep 16 00:00:12 2013 +0200
@@ -1,6 +1,6 @@
 ;;; files.el --- file input and output commands for XEmacs.
 
-;; Copyright (C) 1985-1987, 1992-1995, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1987, 1992-1995, 1997, 2013 Free Software Foundation, Inc.
 ;; Copyright (C) 1995 Sun Microsystems.
 ;; Copyright (C) 2001, 2002, 2003 Ben Wing.
 
@@ -297,13 +297,46 @@
   :group 'backup)
 
 (defcustom require-final-newline nil
-  "*Value of t says silently ensure a file ends in a newline when it is saved.
-Non-nil but not t says ask user whether to add a newline when there isn't one.
-nil means don't add newlines."
-  :type '(choice (const :tag "Off" nil)
-		 (const :tag "Add" t)
-		 (sexp :tag "Ask" :format "%t\n" ask))
-  :group 'editing-basics)
+  "Whether to add a newline automatically at the end of the file.
+
+A value of t means do this only when the file is about to be saved.
+A value of `visit' means do this right after the file is visited.
+A value of `visit-save' means do it at both of those times.
+Any other non-nil value means ask user whether to add a newline, when saving.
+A value of nil means don't add newlines.
+
+Certain major modes set this locally to the value obtained
+from `mode-require-final-newline'."
+  :type '(choice (const :tag "When visiting" visit)
+		 (const :tag "When saving" t)
+		 (const :tag "When visiting or saving" visit-save)
+		 (const :tag "Don't add newlines" nil)
+		 (other :tag "Ask each time" ask))
+  :group 'editing-basics
+  :version "21.5.35")
+
+(defcustom mode-require-final-newline t
+  "Whether to add a newline at end of file, in certain major modes.
+Those modes set `require-final-newline' to this value when you enable them.
+They do so because they are often used for files that are supposed
+to end in newlines, and the question is how to arrange that.
+
+A value of t means do this only when the file is about to be saved.
+A value of `visit' means do this right after the file is visited.
+A value of `visit-save' means do it at both of those times.
+Any other non-nil value means ask user whether to add a newline, when saving.
+
+A value of nil means do not add newlines.  That is a risky choice in this
+variable since this value is used for modes for files that ought to have
+final newlines.  So if you set this to nil, you must explicitly check and
+add a final newline, whenever you save a file that really needs one."
+  :type '(choice (const :tag "When visiting" visit)
+		 (const :tag "When saving" t)
+		 (const :tag "When visiting or saving" visit-save)
+		 (const :tag "Don't add newlines" nil)
+		 (other :tag "Ask each time" ask))
+  :group 'editing-basics
+  :version "21.5.35")
 
 (defcustom auto-save-default t
   "*Non-nil says by default do auto-saving of every file-visiting buffer."
@@ -1576,6 +1609,16 @@
 ;     (when view-read-only
 ;       (and-boundp 'view-mode (view-mode-disable)))
     (normal-mode t)
+    ;; If requested, add a newline at the end of the file.
+    (and (memq require-final-newline '(visit visit-save))
+	 (> (point-max) (point-min))
+	 (/= (char-after (1- (point-max))) ?\n)
+	 (not (and (eq selective-display t)
+		   (= (char-after (1- (point-max))) ?\r)))
+	 (not buffer-read-only)
+	 (save-excursion
+	   (goto-char (point-max))
+	   (ignore-errors (insert "\n"))))
     (when (and buffer-read-only
 	       view-read-only
 	       (not (eq (get major-mode 'mode-class) 'special)))
@@ -2833,6 +2876,7 @@
 		   (not (and (eq selective-display t)
 			     (eq (char-after (1- (point-max))) ?\r)))
 		   (or (eq require-final-newline t)
+		       (eq require-final-newline 'visit-save)
 		       (and require-final-newline
 			    (y-or-n-p
 			     (format "Buffer %s does not end in newline.  Add one? "
--- a/lisp/text-mode.el	Sun Sep 15 23:50:20 2013 +0900
+++ b/lisp/text-mode.el	Mon Sep 16 00:00:12 2013 +0200
@@ -1,6 +1,6 @@
 ;;; text-mode.el --- text mode, and its idiosyncratic commands.
 
-;; Copyright (C) 1985, 1992, 1994, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1992, 1994, 1997, 2013 Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: wp, dumped
@@ -83,6 +83,8 @@
   (setq paragraph-start (concat page-delimiter "\\|[ \t]*$"))
   (make-local-variable 'paragraph-separate)
   (setq paragraph-separate paragraph-start)
+  (set (make-local-variable 'require-final-newline)
+       mode-require-final-newline)
   (setq mode-name "Text")
   (setq major-mode 'text-mode)
   (run-hooks 'text-mode-hook))
--- a/man/ChangeLog	Sun Sep 15 23:50:20 2013 +0900
+++ b/man/ChangeLog	Mon Sep 16 00:00:12 2013 +0200
@@ -1,3 +1,8 @@
+2013-09-15  Mats Lidell  <matsl@xemacs.org>
+
+	* xemacs/files.texi (Saving): New variable
+	mode-require-final-newline. Update info for require-final-newline.
+
 2013-06-25  Jerry James  <james@xemacs.org>
 
 	* Makefile.in: New file, so we can replace @MAKEINFO@.
--- a/man/xemacs/files.texi	Sun Sep 15 23:50:20 2013 +0900
+++ b/man/xemacs/files.texi	Mon Sep 16 00:00:12 2013 +0200
@@ -400,9 +400,24 @@
 @xref{Interlocking,, Simultaneous Editing}.
 
 @vindex require-final-newline
-  If the variable @code{require-final-newline} is non-@code{nil}, Emacs
-puts a newline at the end of any file that doesn't already end in one,
-every time a file is saved or written.
+  If the value of the variable @code{require-final-newline} is
+@code{t}, saving or writing a file silently puts a newline at the end
+if there isn't already one there.  If the value is @code{visit}, Emacs
+adds a newline at the end of any file that doesn't have one, just
+after it visits the file.  (This marks the buffer as modified, and you
+can undo it.)  If the value is @code{visit-save}, Emacs adds such
+newlines both on visiting and on saving.  If the value is @code{nil},
+Emacs leaves the end of the file unchanged; any other non-@code{nil}
+value means to asks you whether to add a newline.  The default is
+@code{nil}.
+
+@vindex mode-require-final-newline
+  Some major modes are designed for specific kinds of files that are
+always supposed to end in newlines.  Such major modes set the variable
+@code{require-final-newline} to the value of
+@code{mode-require-final-newline}, which defaults to @code{t}.  By
+setting the latter variable, you can control how these modes handle
+final newlines.
 
 @vindex write-file-hooks
 @vindex after-save-hook
--- a/tests/ChangeLog	Sun Sep 15 23:50:20 2013 +0900
+++ b/tests/ChangeLog	Mon Sep 16 00:00:12 2013 +0200
@@ -1,3 +1,8 @@
+2013-09-15  Mats Lidell  <matsl@xemacs.org>
+
+	* automated/files-tests.el: New file. Test new states in
+	require-final-newline and new variable mode-require-final-newline.
+
 2013-09-10  Stephen J. Turnbull  <stephen@xemacs.org>
 
 	* automated/process-tests.el: Should work on all POSIX systems.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/automated/files-tests.el	Mon Sep 16 00:00:12 2013 +0200
@@ -0,0 +1,115 @@
+;; Copyright (C) 2013 Free Software Foundation, Inc.
+
+;; Author: Mats Lidell <matsl@xemacs.org>
+;; Maintainer: 
+;; Created: 2013
+;; Keywords: tests
+
+;; This file is part of XEmacs.
+
+;; XEmacs 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.
+
+;; XEmacs 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 XEmacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Synched up with: Not in FSF.
+
+;;; Commentary:
+
+;; Test tag support.
+;; See test-harness.el for instructions on how to run these tests.
+
+(require 'test-harness)
+
+;; Require a newline on save
+(let ((test-file-name (make-temp-file "files-tests"))
+      (require-final-newline t))
+  (find-file test-file-name)
+  (erase-buffer)
+  (insert "no newline")
+  (Silence-Message (save-buffer 0))
+  (Assert (equal (buffer-string) "no newline\n"))
+  (kill-buffer nil)
+  (delete-file test-file-name))
+
+;; Don't require a newline on save
+(let ((test-file-name (make-temp-file "files-tests"))
+      (require-final-newline nil))
+  (find-file test-file-name)
+  (erase-buffer)
+  (insert "no newline")
+  (Silence-Message (save-buffer 0))
+  (Assert (equal (buffer-string) "no newline"))
+  (kill-buffer nil)
+  (delete-file test-file-name))
+
+;; Require a newline on visit (not on save)
+;; Answer query when saving with both no and yes.
+(let ((test-file-name (make-temp-file "files-tests"))
+      (require-final-newline nil))
+  (find-file test-file-name)
+  (erase-buffer)
+  (insert "no newline")
+  (Silence-Message (save-buffer 0))
+  (kill-buffer nil)
+  (let ((require-final-newline 'visit))
+    (find-file test-file-name)
+    (Assert (equal (buffer-string) "no newline\n"))
+
+    ;; Answer no
+    (erase-buffer)
+    (insert "no newline")
+    (flet ((y-or-n-p (prompt) nil)) 
+      (Silence-Message (save-buffer 0)))
+    (Assert (equal (buffer-string) "no newline"))
+
+    ;; Answer yes
+    (erase-buffer)
+    (insert "no newline")
+    (flet ((y-or-n-p (prompt) t)) 
+      (Silence-Message (save-buffer 0)))
+    (Assert (equal (buffer-string) "no newline\n")))
+
+  (kill-buffer nil)
+  (delete-file test-file-name))
+
+;; Require a newline on visit and save
+(let ((test-file-name (make-temp-file "files-tests"))
+      (require-final-newline nil))
+  (find-file test-file-name)
+  (erase-buffer)
+  (insert "no newline")
+  (Silence-Message (save-buffer 0))
+  (kill-buffer nil)
+  (let ((require-final-newline 'visit-save))
+    (find-file test-file-name)
+    (Assert (equal (buffer-string) "no newline\n"))
+    (erase-buffer)
+    (insert "no newline")
+    (Silence-Message (save-buffer 0))
+    (Assert (equal (buffer-string) "no newline\n")))
+  (kill-buffer nil)
+  (delete-file test-file-name))
+
+;; mode-require-final-newline is respected by text-mode
+(let ((test-file-name (make-temp-file "files-tests"))
+      (require-final-newline nil)
+      (mode-require-final-newline t))
+  (Assert (equal require-final-newline nil))
+  (find-file test-file-name)
+  (erase-buffer)
+  (text-mode)
+  (Assert (equal require-final-newline t))
+  (insert "no newline")
+  (Silence-Message (save-buffer 0))
+  (Assert (equal (buffer-string) "no newline\n"))
+  (kill-buffer nil)
+  (delete-file test-file-name))