On 23/09/2025 18:00, Bruno Haible wrote:
Hi Pádraig,

Thanks for answering. So, we have the multibyte problem and the
newline-included problem.

Pádraig Brady wrote:
The code seems to follow the man page and includes the \n in the char count.
Note fold -w does not count the newline which is what I'd expect.

I ran this test case with various 'fmt' implementations:

$ echo 'Hello world' | fmt -w 11
Hello
world
$ echo 'Hello world' | fmt -w 12
Hello world

The minimum -w option that produces a single line:

GNU              12
macOS, FreeBSD   11
NetBSD           11   (-g 10 -w 11)
OpenBSD          11
AIX, Solaris     12

So, the BSD implementations don't count the newline.
The attached aligns the -w interpretation with fold(1), and BSD fmt(1).

Not closing this bug until we get full multi-byte support.

cheers,
Padraig
From 83390333864b79b9885c22c9c6e9a776c52eeed2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <[email protected]>
Date: Wed, 7 Jan 2026 17:15:28 +0000
Subject: [PATCH] fmt: interpret -w as an inclusive maximum

This aligns with `fold -w` and BSD `fmt` implementations.

* src/fmt.c (fmt_paragraph): Check len <= max_width.
* tests/fmt/width.sh: Add a new test.
* tests/local.mk: Reference the new test.
* NEWS: Mention the change in behavior.
Addresses part of https://bugs.gnu.org/79497
---
 NEWS               |  3 +++
 src/fmt.c          |  2 +-
 tests/fmt/width.sh | 40 ++++++++++++++++++++++++++++++++++++++++
 tests/local.mk     |  1 +
 4 files changed, 45 insertions(+), 1 deletion(-)
 create mode 100755 tests/fmt/width.sh

diff --git a/NEWS b/NEWS
index eb9c5e2c4..240edc562 100644
--- a/NEWS
+++ b/NEWS
@@ -53,6 +53,9 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 ** Changes in behavior
 
+  'fmt' -w,--width no longer includes '\n' in the width of a line.
+  I.e., the specified width is interpreted to be an _inclusive_ maximum.
+
   'ptx' -t is no longer a no-op, and now sets the default width to 100 columns.
 
   'timeout' now honors ignored signals and will not propagate them.  E.g.,
diff --git a/src/fmt.c b/src/fmt.c
index 127e7ba4b..ae689ec28 100644
--- a/src/fmt.c
+++ b/src/fmt.c
@@ -908,7 +908,7 @@ fmt_paragraph (void)
 
           len += (w - 1)->space + w->length;	/* w > start >= word */
         }
-      while (len < max_width);
+      while (len <= max_width);
       start->best_cost = best + base_cost (start);
     }
 
diff --git a/tests/fmt/width.sh b/tests/fmt/width.sh
new file mode 100755
index 000000000..981ca9666
--- /dev/null
+++ b/tests/fmt/width.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+# Exercise the fmt -w option.
+
+# Copyright (C) 2026 Free Software Foundation, Inc.
+
+# This program 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.
+
+# This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ fmt
+
+# Ensure width is max display width.
+# Before v9.10, width incorrectly included the \n character
+printf 'aa bb cc dd ee' | fmt -w 8 > out || fail=1
+cat <<\_EOF_ > exp || framework_failure_
+aa bb cc
+dd ee
+_EOF_
+compare exp out || fail=1
+
+printf 'aa bb cc dd ee' | fmt -w 7 > out || fail=1
+cat <<\_EOF_ > exp || framework_failure_
+aa
+bb cc
+dd ee
+_EOF_
+compare exp out || fail=1
+
+
+Exit $fail
diff --git a/tests/local.mk b/tests/local.mk
index 5547a3f9a..58301bec3 100644
--- a/tests/local.mk
+++ b/tests/local.mk
@@ -251,6 +251,7 @@ all_tests =					\
   tests/fmt/goal-option.sh			\
   tests/fmt/long-line.sh			\
   tests/fmt/non-space.sh			\
+  tests/fmt/width.sh				\
   tests/misc/echo.sh				\
   tests/env/env.sh				\
   tests/env/env-signal-handler.sh		\
-- 
2.52.0

Reply via email to