branch: externals/compat commit c5b7ee9376a760db436d6699c5e9de7963892316 Author: Daniel Mendler <m...@daniel-mendler.de> Commit: Daniel Mendler <m...@daniel-mendler.de>
compat-29: Provide string-lines implementation from Emacs 29 --- NEWS.org | 5 +++++ compat-28.el | 5 ----- compat-29.el | 29 +++++++++++++++++++++++++++++ compat-tests.el | 42 ++++++++++++++++++++++-------------------- compat.texi | 31 ++++++++++++++++++++----------- 5 files changed, 76 insertions(+), 36 deletions(-) diff --git a/NEWS.org b/NEWS.org index 8db740ed87..b4a66b301c 100644 --- a/NEWS.org +++ b/NEWS.org @@ -1,5 +1,10 @@ #+title: compat.el - Changelog +* Development + +- compat-29: Replace ~string-lines~ with version from Emacs 29, support optional + KEEP-NEWLINES argument. + * Release of "Compat" Version 29.1.3.0 - compat-25: Add ~hash-table-empty-p~. diff --git a/compat-28.el b/compat-28.el index 76dfe37e3d..f068240d64 100644 --- a/compat-28.el +++ b/compat-28.el @@ -390,11 +390,6 @@ removed." (fill-region (point-min) (point-max))) (buffer-string))) -(compat-defun string-lines (string &optional omit-nulls) ;; <compat-tests:string-lines> - "Split STRING into a list of lines. -If OMIT-NULLS, empty lines will be removed from the results." - (split-string string "\n" omit-nulls)) - (compat-defun string-pad (string length &optional padding start) ;; <compat-tests:string-pad> "Pad STRING to LENGTH using PADDING. If PADDING is nil, the space character is used. If not nil, it diff --git a/compat-29.el b/compat-29.el index 6612612ea3..821d28319c 100644 --- a/compat-29.el +++ b/compat-29.el @@ -170,6 +170,35 @@ This function does not move point. Also see `line-end-position'." ;;;; Defined in subr.el +(compat-defun string-lines (string &optional omit-nulls keep-newlines) + "Handle additional KEEP-NEWLINES argument." + :extended "28.1" + (if (equal string "") + (if omit-nulls + nil + (list "")) + (let ((lines nil) + (start 0)) + (while (< start (length string)) + (let ((newline (string-search "\n" string start))) + (if newline + (progn + (when (or (not omit-nulls) + (not (= start newline))) + (let ((line (substring string start + (if keep-newlines + (1+ newline) + newline)))) + (when (not (and keep-newlines omit-nulls + (equal line "\n"))) + (push line lines)))) + (setq start (1+ newline))) + (if (zerop start) + (push string lines) + (push (substring string start) lines)) + (setq start (length string))))) + (nreverse lines)))) + (compat-defun readablep (object) ;; <compat-tests:readablep> "Say whether OBJECT has a readable syntax. This means that OBJECT can be printed out and then read back diff --git a/compat-tests.el b/compat-tests.el index 14f8c79a20..c26c29496f 100644 --- a/compat-tests.el +++ b/compat-tests.el @@ -1802,17 +1802,24 @@ (ert-deftest string-lines () (should-equal '("a" "b" "c") (string-lines "a\nb\nc")) - ;; FIXME: Behavior changed on Emacs 30 - (compat-tests--if (< emacs-major-version 29) + (should-equal '("a" "b" "c") (string-lines "a\nb\nc\n" t)) + (should-equal '("a" "b" "c") (string-lines "a\nb\n\nc\n" t)) + (should-equal '("abc" "bcd" "cde") (string-lines "abc\nbcd\ncde")) + (should-equal '(" abc" " bcd " "cde ") (string-lines " abc\n bcd \ncde ")) + + ;; NOTE: Behavior for trailing newline was different on Emacs 28 + (compat-tests--if (= emacs-major-version 28) (should-equal '("a" "b" "c" "") (string-lines "a\nb\nc\n")) (should-equal '("a" "b" "c") (string-lines "a\nb\nc\n")) (should-equal '("a\n" "\n" "b\n" "c\n") (string-lines "a\n\nb\nc\n" nil t)) (should-equal '("a\n" "b\n" "c\n") (string-lines "a\n\nb\nc\n" t t)) (should-equal '("a\n" "b\n" "c\n") (string-lines "a\nb\nc\n" nil t))) - (should-equal '("a" "b" "c") (string-lines "a\nb\nc\n" t)) - (should-equal '("a" "b" "c") (string-lines "a\nb\n\nc\n" t)) - (should-equal '("abc" "bcd" "cde") (string-lines "abc\nbcd\ncde")) - (should-equal '(" abc" " bcd " "cde ") (string-lines " abc\n bcd \ncde "))) + + ;; Compatibility function provides the Emacs 29 behavior regarding trailing newlines + (should-equal '("a" "b" "c") (compat-call string-lines "a\nb\nc\n")) + (should-equal '("a\n" "\n" "b\n" "c\n") (compat-call string-lines "a\n\nb\nc\n" nil t)) + (should-equal '("a\n" "b\n" "c\n") (compat-call string-lines "a\n\nb\nc\n" t t)) + (should-equal '("a\n" "b\n" "c\n") (compat-call string-lines "a\nb\nc\n" nil t))) (ert-deftest string-pad () (should-equal "a " (string-pad "a" 4)) @@ -1984,12 +1991,10 @@ ;; The `make-string' calls with three arguments have been replaced ;; here with the result of their evaluation, to avoid issues with ;; older versions of Emacs that only support two arguments. - (should-equal 5 - (string-search (make-string 2 130) - ;; Per (concat "helló" (make-string 5 130 t) "bár") - "hellóbár")) - (should-equal 5 - (string-search (make-string 2 127) + (should-equal 5 (string-search (make-string 2 130) + ;; Per (concat "helló" (make-string 5 130 t) "bár") + "hellóbár")) + (should-equal 5 (string-search (make-string 2 127) ;; Per (concat "helló" (make-string 5 127 t) "bár") "hellóbár")) (should-equal 1 (string-search "\377" "a\377ø")) @@ -2027,15 +2032,13 @@ (should-not (string-search "\303\270" "\370")) (should-not (string-search (compat-tests--string-to-multibyte "\303\270") "\370")) (should-not (string-search "\303\270" (compat-tests--string-to-multibyte "\370"))) - (should-not - (string-search (compat-tests--string-to-multibyte "\303\270") - (compat-tests--string-to-multibyte "\370"))) + (should-not (string-search (compat-tests--string-to-multibyte "\303\270") + (compat-tests--string-to-multibyte "\370"))) (should-not (string-search "\370" "\303\270")) (should-not (string-search (compat-tests--string-to-multibyte "\370") "\303\270")) (should-not (string-search "\370" (compat-tests--string-to-multibyte "\303\270"))) - (should-not - (string-search (compat-tests--string-to-multibyte "\370") - (compat-tests--string-to-multibyte "\303\270"))) + (should-not (string-search (compat-tests--string-to-multibyte "\370") + (compat-tests--string-to-multibyte "\303\270"))) (should-equal 3 (string-search "\303\270" "foo\303\270")) (when (version<= "27" emacs-version) ;; FIXME The commit a1f76adfb03c23bb4242928e8efe6193c301f0c1 in @@ -2043,8 +2046,7 @@ ;; raw bytes. The compatibility functions should updated to ;; backport this behaviour. (should-equal 2 (string-search (compat-tests--string-to-multibyte "\377") "ab\377c")) - (should-equal 2 - (string-search (compat-tests--string-to-multibyte "o\303\270") + (should-equal 2 (string-search (compat-tests--string-to-multibyte "o\303\270") "foo\303\270")))) (ert-deftest string-replace () diff --git a/compat.texi b/compat.texi index b30c234ecf..94508fa3c2 100644 --- a/compat.texi +++ b/compat.texi @@ -483,7 +483,7 @@ arguments, @var{objects}. @subsection Extended Definitions These functions must be called explicitly via @code{compat-call}, -since their calling convention or behavior was extended: +since their calling convention or behavior was extended in Emacs 25.1: @defun compat-call@ sort sequence predicate This function sorts @var{sequence} stably. Note that this function @@ -884,7 +884,7 @@ size, modes, inode-number and device-number. @subsection Extended Definitions These functions must be called explicitly via @code{compat-call}, -since their calling convention or behavior was extended: +since their calling convention or behavior was extended in Emacs 26.1: @defun compat-call@ assoc key alist &optional testfn This function returns the first association for @var{key} in @@ -1316,7 +1316,7 @@ function signals an error. @subsection Extended Definitions These functions must be called explicitly via @code{compat-call}, -since their calling convention or behavior was extended: +since their calling convention or behavior was extended in Emacs 27.1: @c based on lispref/windows.texi @defun compat-call@ recenter &optional count redisplay @@ -1782,14 +1782,12 @@ will not be shortened. @end defun @c copied from lispref/strings.texi -@defun string-lines string &optional omit-nulls keep-newlines +@defun string-lines string &optional omit-nulls Split @var{string} into a list of strings on newline boundaries. If the optional argument @var{omit-nulls} is non-@code{nil}, remove empty -lines from the results. If the optional argument @var{keep-newlines} -is non-@code{nil}, don't remove the trailing newlines from the result -strings. - -@xref{Creating Strings,,,elisp}. +lines from the results. Note that this function returns trailing +newlines on Emacs 28, use @code{compat-call string-lines} instead if +you want consistent behavior. @end defun @c copied from lispref/strings.texi @@ -2023,7 +2021,7 @@ If native compilation is not available, this function always returns @subsection Extended Definitions These functions must be called explicitly via @code{compat-call}, -since their calling convention or behavior was extended: +since their calling convention or behavior was extended in Emacs 28.1: @defun compat-call@ string-width string &optional from to This function returns the width in columns of the string @var{string}, @@ -2809,7 +2807,18 @@ This is comparable to @code{and-let*}. @subsection Extended Definitions These functions must be called explicitly via @code{compat-call}, -since their calling convention or behavior was extended: +since their calling convention or behavior was extended in Emacs 29.1: + +@c copied from lispref/strings.texi +@defun compat-call@ string-lines string &optional omit-nulls keep-newlines +Split @var{string} into a list of strings on newline boundaries. If +the optional argument @var{omit-nulls} is non-@code{nil}, remove empty +lines from the results. If the optional argument @var{keep-newlines} +is non-@code{nil}, don't remove the trailing newlines from the result +strings. + +@xref{Creating Strings,,,elisp}. +@end defun @c copied from lispref/keymaps.texi @defun compat-call@ define-key