GNU bug report logs - #56685
OBOE in string-truncate-left?

Previous Next

Package: emacs;

Reported by: Stefan Kangas <stefan <at> marxist.se>

Date: Thu, 21 Jul 2022 22:11:02 UTC

Severity: normal

Fixed in version 29.1

Done: Lars Ingebrigtsen <larsi <at> gnus.org>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 56685 in the body.
You can then email your comments to 56685 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#56685; Package emacs. (Thu, 21 Jul 2022 22:11:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Stefan Kangas <stefan <at> marxist.se>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Thu, 21 Jul 2022 22:11:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Stefan Kangas <stefan <at> marxist.se>
To: bug-gnu-emacs <at> gnu.org
Subject: OBOE in string-truncate-left?
Date: Thu, 21 Jul 2022 17:10:36 -0500
Try evaluating:

    (length (string-truncate-left "longstring" 8))
    => 9

But the docstring says "Truncate STRING to LENGTH".
This seems like a bug.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#56685; Package emacs. (Fri, 22 Jul 2022 10:27:01 GMT) Full text and rfc822 format available.

Message #8 received at 56685 <at> debbugs.gnu.org (full text, mbox):

From: Stephen Berman <stephen.berman <at> gmx.net>
To: Stefan Kangas <stefan <at> marxist.se>
Cc: 56685 <at> debbugs.gnu.org
Subject: Re: bug#56685: OBOE in string-truncate-left?
Date: Fri, 22 Jul 2022 12:26:09 +0200
[Message part 1 (text/plain, inline)]
On Thu, 21 Jul 2022 17:10:36 -0500 Stefan Kangas <stefan <at> marxist.se> wrote:

> Try evaluating:
>
>     (length (string-truncate-left "longstring" 8))
>     => 9
>
> But the docstring says "Truncate STRING to LENGTH".
> This seems like a bug.

Yes, and I also think it's counterintuitive that LENGTH includes the
length of "...".  Worse, if STRING is short enough, the resulting string
(with "...") can be longer than LENGTH:

(string-truncate-left "band" 3)
"...d"
(string-truncate-left "band" 2)
"...d"
(string-truncate-left "band" 1)
"...d"
(string-truncate-left "and" 2)
"...d"
(string-truncate-left "and" 1)
"...d"

Note that with the last two examples, the result is longer than the
original string, contradicting the meaning of truncation.  I think
LENGTH should mean just the numbers of characters in STRING after
truncation (excluding "..."), and if the result with the prefix "..." is
not shorter than the original string, there should be no truncation.
The following patch does this.

[Message part 2 (text/x-patch, inline)]
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index 5037ae47e8..6eefd5d141 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -107,12 +107,13 @@ 'string-reverse

 ;;;###autoload
 (defun string-truncate-left (string length)
-  "Truncate STRING to LENGTH, replacing initial surplus with \"...\"."
+  "Return STRING's last LENGTH characters prefixed with \"...\".
+If the resulting string with the prefix is not shorter than the
+original length of STRING, return STRING unchanged."
   (let ((strlen (length string)))
-    (if (<= strlen length)
+    (if (<= strlen (+ length 3))
 	string
-      (setq length (max 0 (- length 3)))
-      (concat "..." (substring string (max 0 (- strlen 1 length)))))))
+      (concat "..." (substring string (max 0 (- strlen length)))))))

 (defsubst string-blank-p (string)
   "Check whether STRING is either empty or only whitespace.
[Message part 3 (text/plain, inline)]
--
Steve Berman

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#56685; Package emacs. (Fri, 22 Jul 2022 11:32:02 GMT) Full text and rfc822 format available.

Message #11 received at 56685 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Stephen Berman <stephen.berman <at> gmx.net>
Cc: stefan <at> marxist.se, 56685 <at> debbugs.gnu.org
Subject: Re: bug#56685: OBOE in string-truncate-left?
Date: Fri, 22 Jul 2022 14:31:03 +0300
> Cc: 56685 <at> debbugs.gnu.org
> From: Stephen Berman <stephen.berman <at> gmx.net>
> Date: Fri, 22 Jul 2022 12:26:09 +0200
> 
> Yes, and I also think it's counterintuitive that LENGTH includes the
> length of "...".  Worse, if STRING is short enough, the resulting string
> (with "...") can be longer than LENGTH:
> 
> (string-truncate-left "band" 3)
> "...d"
> (string-truncate-left "band" 2)
> "...d"
> (string-truncate-left "band" 1)
> "...d"
> (string-truncate-left "and" 2)
> "...d"
> (string-truncate-left "and" 1)
> "...d"

The above calls make no sense to me: since it is known up front that
the function will prepend "...", what else does the caller expect from
such calls?

> Note that with the last two examples, the result is longer than the
> original string, contradicting the meaning of truncation.

The function truncates STRING, not the result it returns.  So I see no
contradiction here.  And again, what would you do instead?  Because
this:

>  (defun string-truncate-left (string length)
> -  "Truncate STRING to LENGTH, replacing initial surplus with \"...\"."
> +  "Return STRING's last LENGTH characters prefixed with \"...\".
> +If the resulting string with the prefix is not shorter than the
> +original length of STRING, return STRING unchanged."

again makes no sense to me: you have forcibly prevented any Lisp
program from truncating STRING because you personally don't like the
result in these cases.  But the fact that you don't like it doesn't
yet mean it isn't a valid use case.  If your applications don't want
truncation in those case, it is easy to provide a trivial wrapper
around string-truncate-left.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#56685; Package emacs. (Fri, 22 Jul 2022 12:36:01 GMT) Full text and rfc822 format available.

Message #14 received at 56685 <at> debbugs.gnu.org (full text, mbox):

From: Stephen Berman <stephen.berman <at> gmx.net>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: stefan <at> marxist.se, 56685 <at> debbugs.gnu.org
Subject: Re: bug#56685: OBOE in string-truncate-left?
Date: Fri, 22 Jul 2022 14:35:02 +0200
On Fri, 22 Jul 2022 14:31:03 +0300 Eli Zaretskii <eliz <at> gnu.org> wrote:

>> Cc: 56685 <at> debbugs.gnu.org
>> From: Stephen Berman <stephen.berman <at> gmx.net>
>> Date: Fri, 22 Jul 2022 12:26:09 +0200
>>
>> Yes, and I also think it's counterintuitive that LENGTH includes the
>> length of "...".  Worse, if STRING is short enough, the resulting string
>> (with "...") can be longer than LENGTH:
>>
>> (string-truncate-left "band" 3)
>> "...d"
>> (string-truncate-left "band" 2)
>> "...d"
>> (string-truncate-left "band" 1)
>> "...d"
>> (string-truncate-left "and" 2)
>> "...d"
>> (string-truncate-left "and" 1)
>> "...d"
>
> The above calls make no sense to me: since it is known up front that
> the function will prepend "...", what else does the caller expect from
> such calls?
>
>> Note that with the last two examples, the result is longer than the
>> original string, contradicting the meaning of truncation.
>
> The function truncates STRING, not the result it returns.  So I see no
> contradiction here.  And again, what would you do instead?  Because
> this:
>
>>  (defun string-truncate-left (string length)
>> -  "Truncate STRING to LENGTH, replacing initial surplus with \"...\"."
>> +  "Return STRING's last LENGTH characters prefixed with \"...\".
>> +If the resulting string with the prefix is not shorter than the
>> +original length of STRING, return STRING unchanged."
>
> again makes no sense to me: you have forcibly prevented any Lisp
> program from truncating STRING because you personally don't like the
> result in these cases.  But the fact that you don't like it doesn't
> yet mean it isn't a valid use case.  If your applications don't want
> truncation in those case, it is easy to provide a trivial wrapper
> around string-truncate-left.

Currently, the result of applying string-truncate-left to STRING can be
a string just as long as STRING but beginning with "..." instead of the
first three letters of STRING.  What is a valid use case for that?

Steve Berman




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#56685; Package emacs. (Fri, 22 Jul 2022 13:34:02 GMT) Full text and rfc822 format available.

Message #17 received at 56685 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Stephen Berman <stephen.berman <at> gmx.net>
Cc: stefan <at> marxist.se, 56685 <at> debbugs.gnu.org
Subject: Re: bug#56685: OBOE in string-truncate-left?
Date: Fri, 22 Jul 2022 16:33:07 +0300
> From: Stephen Berman <stephen.berman <at> gmx.net>
> Cc: stefan <at> marxist.se,  56685 <at> debbugs.gnu.org
> Date: Fri, 22 Jul 2022 14:35:02 +0200
> 
> Currently, the result of applying string-truncate-left to STRING can be
> a string just as long as STRING but beginning with "..." instead of the
> first three letters of STRING.  What is a valid use case for that?

When STRING is part of a longer string.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#56685; Package emacs. (Fri, 22 Jul 2022 15:24:02 GMT) Full text and rfc822 format available.

Message #20 received at 56685 <at> debbugs.gnu.org (full text, mbox):

From: Stephen Berman <stephen.berman <at> gmx.net>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: stefan <at> marxist.se, 56685 <at> debbugs.gnu.org
Subject: Re: bug#56685: OBOE in string-truncate-left?
Date: Fri, 22 Jul 2022 17:23:27 +0200
On Fri, 22 Jul 2022 16:33:07 +0300 Eli Zaretskii <eliz <at> gnu.org> wrote:

>> From: Stephen Berman <stephen.berman <at> gmx.net>
>> Cc: stefan <at> marxist.se,  56685 <at> debbugs.gnu.org
>> Date: Fri, 22 Jul 2022 14:35:02 +0200
>>
>> Currently, the result of applying string-truncate-left to STRING can be
>> a string just as long as STRING but beginning with "..." instead of the
>> first three letters of STRING.  What is a valid use case for that?
>
> When STRING is part of a longer string.

I don't see why that is relevant, and one of the few uses of
string-truncate-left in the Emacs sources seems to confirm my doubt,
namely, in gnus-shorten-url, which results in displaying
e.g. "cvs.savannah.gnu.org...emacs.svg?view=log" instead of
"https://cvs.savannah.gnu.org/viewvc/emacs/emacs/etc/images/icons/hicolor/scalable/apps/emacs.svg?view=log".
But if the too-long string is
"https://cvs.savannah.gnu.org/viewv/emacs/emacs/1/", then with the
current string-truncate-left gnus-shorten-url "shortens" it to
"cvs.savannah.gnu.org...ewv/emacs/emacs/1/".  AFAICS replacing the three
characters "/vi" by "..." here just loses information.  Can you show a
specific case where such a length-preserving substitution is preferable?

Steve Berman




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#56685; Package emacs. (Sat, 23 Jul 2022 06:59:02 GMT) Full text and rfc822 format available.

Message #23 received at 56685 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Stephen Berman <stephen.berman <at> gmx.net>
Cc: Eli Zaretskii <eliz <at> gnu.org>, stefan <at> marxist.se, 56685 <at> debbugs.gnu.org
Subject: Re: bug#56685: OBOE in string-truncate-left?
Date: Sat, 23 Jul 2022 08:58:35 +0200
Stephen Berman <stephen.berman <at> gmx.net> writes:

> But if the too-long string is
> "https://cvs.savannah.gnu.org/viewv/emacs/emacs/1/", then with the
> current string-truncate-left gnus-shorten-url "shortens" it to
> "cvs.savannah.gnu.org...ewv/emacs/emacs/1/".  AFAICS replacing the three
> characters "/vi" by "..." here just loses information.

What's the parameters when that happens?  I get:

(gnus-shorten-url "https://cvs.savannah.gnu.org/viewv/emacs/emacs/1/" 41)
=> "cvs.savannah.gnu.org/viewv/emacs/emacs/1/"

(gnus-shorten-url "https://cvs.savannah.gnu.org/viewv/emacs/emacs/1/" 40)
=> "cvs.savannah.gnu.org...wv/emacs/emacs/1/"

Anyway, I think the examples show that this function isn't very useful
if LENGTH is very small -- it really does want to add "..." to signal
that some shortening has happened, and that may make the string longer.
But just returning "d" for (string-truncate-left "and" 1) isn't correct
either.

I've now fixed the originally reported off-by-one error when shortening,
and documented the quirks of the function in Emacs 29.





bug marked as fixed in version 29.1, send any further explanations to 56685 <at> debbugs.gnu.org and Stefan Kangas <stefan <at> marxist.se> Request was from Lars Ingebrigtsen <larsi <at> gnus.org> to control <at> debbugs.gnu.org. (Sat, 23 Jul 2022 06:59:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#56685; Package emacs. (Sat, 23 Jul 2022 08:53:02 GMT) Full text and rfc822 format available.

Message #28 received at 56685 <at> debbugs.gnu.org (full text, mbox):

From: Stephen Berman <stephen.berman <at> gmx.net>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: Eli Zaretskii <eliz <at> gnu.org>, stefan <at> marxist.se, 56685 <at> debbugs.gnu.org
Subject: Re: bug#56685: OBOE in string-truncate-left?
Date: Sat, 23 Jul 2022 10:51:58 +0200
On Sat, 23 Jul 2022 08:58:35 +0200 Lars Ingebrigtsen <larsi <at> gnus.org> wrote:

> Stephen Berman <stephen.berman <at> gmx.net> writes:
>
>> But if the too-long string is
>> "https://cvs.savannah.gnu.org/viewv/emacs/emacs/1/", then with the
>> current string-truncate-left gnus-shorten-url "shortens" it to
>> "cvs.savannah.gnu.org...ewv/emacs/emacs/1/".  AFAICS replacing the three
>> characters "/vi" by "..." here just loses information.
>
> What's the parameters when that happens?  I get:
>
> (gnus-shorten-url "https://cvs.savannah.gnu.org/viewv/emacs/emacs/1/" 41)
> => "cvs.savannah.gnu.org/viewv/emacs/emacs/1/"
>
> (gnus-shorten-url "https://cvs.savannah.gnu.org/viewv/emacs/emacs/1/" 40)
> => "cvs.savannah.gnu.org...wv/emacs/emacs/1/"

Same here; in my example, I used 40 since that's what
gnus-summary-browse-url (the caller of gnus-shorten-url) uses.

> Anyway, I think the examples show that this function isn't very useful
> if LENGTH is very small -- it really does want to add "..." to signal
> that some shortening has happened, and that may make the string longer.
> But just returning "d" for (string-truncate-left "and" 1) isn't correct
> either.

Yes.  My main motivation for proposing to omit truncation (and prefixing
with "...") of too-short lines was for using string-truncate-left in a
loop over differently sized input strings, but of course that can be
handled by suitable code in the loop.

> I've now fixed the originally reported off-by-one error when shortening,
> and documented the quirks of the function in Emacs 29.

Thanks, the doc string makes sense to me now.

Steve Berman




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Sat, 20 Aug 2022 11:24:11 GMT) Full text and rfc822 format available.

This bug report was last modified 2 years and 300 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.