GNU bug report logs - #11044
RFE: fmt goal width

Previous Next

Package: coreutils;

Reported by: Bruce Korb <bruce.korb <at> gmail.com>

Date: Mon, 19 Mar 2012 19:18:02 UTC

Severity: wishlist

Tags: patch

To reply to this bug, email your comments to 11044 AT debbugs.gnu.org.

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-coreutils <at> gnu.org:
bug#11044; Package coreutils. (Mon, 19 Mar 2012 19:18:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Bruce Korb <bruce.korb <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-coreutils <at> gnu.org. (Mon, 19 Mar 2012 19:18:02 GMT) Full text and rfc822 format available.

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

From: Bruce Korb <bruce.korb <at> gmail.com>
To: bug-coreutils <at> gnu.org
Subject: bug & RFE
Date: Mon, 19 Mar 2012 11:46:39 -0700
Hi,

The web bug:  the symlink to coreutils.html from index.html is missing

The RFE:  I'd like to be able to have a consistent, well-understood
line length from the fmt command:
‘--width=width’
   Fill output lines up to width characters (default 75). fmt initially
   tries to make lines about 7% shorter than this, to give it room to
   balance line lengths.

That is very nice and all, but that's not what other implementations do.
BSD uses "goal" and "maximum" to specify the fuzz and "-w" says "no fuzz".
So how about an option to specify a goal with the default goal being 93%
of "-w"?  Then I can just test to see if "-g" is accepted and use it.

Thank you!




Information forwarded to bug-coreutils <at> gnu.org:
bug#11044; Package coreutils. (Mon, 19 Mar 2012 20:05:02 GMT) Full text and rfc822 format available.

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

From: Eric Blake <eblake <at> redhat.com>
To: Bruce Korb <bruce.korb <at> gmail.com>
Cc: 11044 <at> debbugs.gnu.org
Subject: Re: bug#11044: bug & RFE
Date: Mon, 19 Mar 2012 13:34:05 -0600
[Message part 1 (text/plain, inline)]
On 03/19/2012 12:46 PM, Bruce Korb wrote:
> Hi,
> 
> The web bug:  the symlink to coreutils.html from index.html is missing

Aargh.  This was my fault, due to a recent complaint about the
coreutils.en.html symlink not working.  I had applied this commit:

> update to latest symlink conventions
> 
> Per https://www.gnu.org/server/standards/README.webmastering.html,
> index.html is automatically created, and any link that looks like
> a translation of html can no longer be created via .symlinks, but
> must instead be done via redirections.

since according to that web page:

> As a special case, if a page with the directory's name exists, and index.html does not exist, a link will be made from index.html to the main page.

But maybe that only happens on directories where a .symlinks file
exists, and the fact that I removed .symlinks for coreutils.en.html
broke the index.html linking?

At any rate, I'll quickly fix that by re-adding .symlinks.

As for fmt, I'll let others chime in; it's the sort of thing where a
patch speaks louder than requests.

-- 
Eric Blake   eblake <at> redhat.com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

[signature.asc (application/pgp-signature, attachment)]

Information forwarded to bug-coreutils <at> gnu.org:
bug#11044; Package coreutils. (Mon, 19 Mar 2012 20:31:01 GMT) Full text and rfc822 format available.

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

From: Bruce Korb <bruce.korb <at> gmail.com>
To: Eric Blake <eblake <at> redhat.com>
Cc: 11044 <at> debbugs.gnu.org
Subject: Re: bug#11044: bug & RFE
Date: Mon, 19 Mar 2012 13:00:01 -0700
Hi Eric,

On Mon, Mar 19, 2012 at 12:34 PM, Eric Blake <eblake <at> redhat.com> wrote:
> As for fmt, I'll let others chime in; it's the sort of thing where a
> patch speaks louder than requests.

A "patch, please" reply is completely fine.  Going to the trouble of
making a patch
wherein the patch is not considered is not quite so fine.  I guess I
should make it
clearer:

  would you-all accept a patch that added a "-g" option to set the goal
  column as opposed to deriving it by multiplying the width by 0.93 ?

It would permit results consistent with BSD and Plan-9 flavors of fmt.

Thanks !




Information forwarded to bug-coreutils <at> gnu.org:
bug#11044; Package coreutils. (Mon, 19 Mar 2012 21:12:01 GMT) Full text and rfc822 format available.

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

From: Eric Blake <eblake <at> redhat.com>
To: Bruce Korb <bruce.korb <at> gmail.com>
Cc: 11044 <at> debbugs.gnu.org
Subject: Re: bug#11044: bug & RFE
Date: Mon, 19 Mar 2012 14:41:04 -0600
[Message part 1 (text/plain, inline)]
retitle 11044 RFE: fmt goal width
thanks

On 03/19/2012 02:00 PM, Bruce Korb wrote:
> Hi Eric,
> 
> On Mon, Mar 19, 2012 at 12:34 PM, Eric Blake <eblake <at> redhat.com> wrote:
>> As for fmt, I'll let others chime in; it's the sort of thing where a
>> patch speaks louder than requests.
> 
> A "patch, please" reply is completely fine.  Going to the trouble of
> making a patch
> wherein the patch is not considered is not quite so fine.  I guess I
> should make it
> clearer:
> 
>   would you-all accept a patch that added a "-g" option to set the goal
>   column as opposed to deriving it by multiplying the width by 0.93 ?

Yes - I would welcome such a patch, on the grounds of supporting a use
case currently possible in other existing implementations.  According to
http://www.manpagez.com/man/1/fmt/, there is no 'g' option, but BSD 'fmt
60 70' would operate like your proposed 'fmt -g 60 -w 70'.  In fact, it
might even be worth to teach GNU fmt about a non-option numeric argument
being treated as --width rather than as a file name.

-- 
Eric Blake   eblake <at> redhat.com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

[signature.asc (application/pgp-signature, attachment)]

Changed bug title to 'RFE: fmt goal width' from 'bug & RFE' Request was from Eric Blake <eblake <at> redhat.com> to control <at> debbugs.gnu.org. (Mon, 19 Mar 2012 21:12:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-coreutils <at> gnu.org:
bug#11044; Package coreutils. (Mon, 19 Mar 2012 21:38:02 GMT) Full text and rfc822 format available.

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

From: Bruce Korb <bruce.korb <at> gmail.com>
To: Eric Blake <eblake <at> redhat.com>
Cc: 11044 <at> debbugs.gnu.org
Subject: Re: bug#11044: bug & RFE
Date: Mon, 19 Mar 2012 14:06:34 -0700
Hi Eric,

On Mon, Mar 19, 2012 at 1:41 PM, Eric Blake <eblake <at> redhat.com> wrote:
>>   would you-all accept a patch that added a "-g" option to set the goal
>>   column as opposed to deriving it by multiplying the width by 0.93 ?
>
> Yes - I would welcome such a patch, on the grounds of supporting a use
> case currently possible in other existing implementations.  According to
> http://www.manpagez.com/man/1/fmt/, there is no 'g' option, but BSD 'fmt
> 60 70' would operate like your proposed 'fmt -g 60 -w 70'.  In fact, it
> might even be worth to teach GNU fmt about a non-option numeric argument
> being treated as --width rather than as a file name.

I thought about that and decided to not suggest it.  I don't like
conflating something
that is, in essence, a configurable setting with real operands.  I'd
prefer to suggest
"-g" to our BSD friends.  :)

Were it to be implemented in GNU's fmt, you would have to pass two tests:

1. does it match a file name?  If not,
2. is the first (or second) operand a number? (decimal only, or hex/octal, too?)

"Icky"




Information forwarded to bug-coreutils <at> gnu.org:
bug#11044; Package coreutils. (Mon, 19 Mar 2012 23:37:01 GMT) Full text and rfc822 format available.

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

From: Bruce Korb <bruce.korb <at> gmail.com>
To: 11044 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>, coreutils <at> gnu.org
Subject: RFE: -g <goal> for fmt(1) command
Date: Mon, 19 Mar 2012 16:05:51 -0700
[Message part 1 (text/plain, inline)]

[9999-current.diff (text/x-patch, attachment)]

Information forwarded to bug-coreutils <at> gnu.org:
bug#11044; Package coreutils. (Tue, 20 Mar 2012 00:39:01 GMT) Full text and rfc822 format available.

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

From: Bruce Korb <bruce.korb <at> gmail.com>
To: Eric Blake <eblake <at> redhat.com>
Cc: 11044 <at> debbugs.gnu.org
Subject: Re: bug#11044: bug & RFE
Date: Mon, 19 Mar 2012 17:07:39 -0700
The "T" crossings and "I" dottings ... I did the icky thing anyway.


diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 835c245..a9dabc4
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -2133,7 +2133,7 @@ These commands reformat the contents of files.
 a given number of characters (75 by default).  Synopsis:

 @example
-fmt [@var{option}]@dots{} [@var{file}]@dots{}
+fmt [@var{option}]@dots{} [@var{goal} [@var{width}]] [@var{file}]@dots{}
 @end example

 @command{fmt} reads from the specified @var{file} arguments (or standard
@@ -2144,6 +2144,13 @@ preserved in the output; successive input lines with different
 indentation are not joined; tabs are expanded on input and introduced on
 output.

+@var{goal} and @var{width} are only recognized if neither
+@var{-g}/@var{--goal} nor @var{-w}/@var{--width} have been specified; and if
+the strings represent numbers; and if the numbers do not exceed about 2,500;
+and if these strings do not match existing file names.  If @var{goal} is
+provided but @var{width} not, then @var{width} will be set to @var{goal}
+plus 10.
+
 @cindex line-breaking
 @cindex sentences and line-breaking
 @cindex Knuth, Donald E.
@@ -2203,9 +2210,16 @@ between sentences to two spaces.
 @opindex -@var{width}
 @opindex -w
 @opindex --width
-Fill output lines up to @var{width} characters (default 75).  @command{fmt}
-initially tries to make lines about 7% shorter than this, to give it
-room to balance line lengths.
+Fill output lines up to @var{width} characters (default 75).
+
+@item -@var{goal}
+@itemx -g @var{goal}
+@itemx --goal=@var{goal}
+@opindex -@var{goal}
+@opindex -g
+@opindex --goal
+@command{fmt} initially tries to make lines @var{goal} characters wide.
+By default, this is 7% shorter than @var{width}.

 @item -p @var{prefix}
 @itemx --prefix=@var{prefix}




Information forwarded to bug-coreutils <at> gnu.org:
bug#11044; Package coreutils. (Fri, 30 Mar 2012 00:14:02 GMT) Full text and rfc822 format available.

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

From: Bruce Korb <bkorb <at> gnu.org>
To: coreutils <at> gnu.org
Cc: 11044 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>
Subject: Fwd: [PATCH] fmt: optionalize line width goal
Date: Thu, 29 Mar 2012 16:41:35 -0700
PING ????

-------- Original Message --------
Subject: [PATCH] fmt: optionalize line width goal
Date: Tue, 20 Mar 2012 08:29:53 -0700

BSD's implementation allows a goal specification and has a different
default goal width computation anyway.  This change adds a "-g" option
and allows the first two numeric operands to represent the goal width
and actual line width.

* src/fmt.c (main): implement the new option
(check_for_goals): new function to implement the operands
Based on BSD's and Plan-9's fmt programs.
---
 THANKS.in          |    3 ++
 doc/coreutils.texi |   23 +++++++++++--
 src/fmt.c          |   88 +++++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 106 insertions(+), 8 deletions(-)

diff --git a/THANKS.in b/THANKS.in
index d23f7b3..9a525c4 100644
--- a/THANKS.in
+++ b/THANKS.in
@@ -11,6 +11,8 @@ note to the bug-report mailing list (as seen at end of e.g., cp --help).
 ## is used to generate the THANKS file.  Note that numerous people listed
 ## here would have been listed as commit authors if we had been using git
 ## for version control when they contributed.
+##
+## Well, not completely true.  It misses sometimes.

 ???                                 kytek <at> cybercomm.net
 A Costa                             agcosta <at> gis.net
@@ -97,6 +99,7 @@ Brian M. Carlson                    sandals <at> crustytoothpaste.ath.cx
 Brian Silverman                     bsilverman <at> conceptxdesign.com
 Brian Youmans                       3diff <at> gnu.org
 Britton Leo Kerin                   fsblk <at> aurora.uaf.edu
+Bruce Korb                          bkorb <at> gnu.org
 Bruce Robertson                     brucer <at> theodolite.dyndns.org
 Carl Johnson                        carlj <at> cjlinux.home.org
 Carl Lowenstein                     cdl <at> mpl.UCSD.EDU
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 835c245..91ca957 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -2133,7 +2133,7 @@ These commands reformat the contents of files.
 a given number of characters (75 by default).  Synopsis:

 @example
-fmt [@var{option}]@dots{} [@var{file}]@dots{}
+fmt [@var{option}]@dots{} [@var{goal} [@var{width}]] [@var{file}]@dots{}
 @end example

 @command{fmt} reads from the specified @var{file} arguments (or standard
@@ -2144,6 +2144,13 @@ preserved in the output; successive input lines with different
 indentation are not joined; tabs are expanded on input and introduced on
 output.

+@var{goal} and @var{width} are only recognized if neither
+@var{-g}/@var{--goal} nor @var{-w}/@var{--width} have been specified; and if
+the strings represent numbers; and if the numbers do not exceed about 2,500;
+and if these strings do not match existing file names.  If @var{GOAL} is
+provided but @var{width} not, then @var{width} will be set to @var{goal}
+plus 10.
+
 @cindex line-breaking
 @cindex sentences and line-breaking
 @cindex Knuth, Donald E.
@@ -2203,9 +2210,17 @@ between sentences to two spaces.
 @opindex -@var{width}
 @opindex -w
 @opindex --width
-Fill output lines up to @var{width} characters (default 75).  @command{fmt}
-initially tries to make lines about 7% shorter than this, to give it
-room to balance line lengths.
+Fill output lines up to @var{width} characters (default 75 or @var{goal} plus 10,
+if @var{goal} is provided).
+
+@item -@var{goal}
+@itemx -g @var{goal}
+@itemx --goal=@var{goal}
+@opindex -@var{goal}
+@opindex -g
+@opindex --goal
+@command{fmt} initially tries to make lines @var{goal} characters wide.
+By default, this is 7% shorter than @var{width}.

 @item -p @var{prefix}
 @itemx --prefix=@var{prefix}
diff --git a/src/fmt.c b/src/fmt.c
index 89d13a6..95ae149 100644
--- a/src/fmt.c
+++ b/src/fmt.c
@@ -68,7 +68,7 @@ typedef long int COST;
 #define SQR(n)		((n) * (n))
 #define EQUIV(n)	SQR ((COST) (n))

-/* Cost of a filled line n chars longer or shorter than best_width.  */
+/* Cost of a filled line n chars longer or shorter than goal_width.  */
 #define SHORT_COST(n)	EQUIV ((n) * 10)

 /* Cost of the difference between adjacent filled lines.  */
@@ -167,6 +167,7 @@ static void put_paragraph (WORD *finish);
 static void put_line (WORD *w, int indent);
 static void put_word (WORD *w);
 static void put_space (int space);
+static void check_for_goals (char ** argv);

 /* Option values.  */

@@ -201,7 +202,7 @@ static int prefix_lead_space;
 static int prefix_length;

 /* The preferred width of text lines, set to LEEWAY % less than max_width.  */
-static int best_width;
+static int goal_width;

 /* Dynamic variables.  */

@@ -286,6 +287,7 @@ Mandatory arguments to long options are mandatory for short options too.\n\
   -t, --tagged-paragraph    indentation of first line different from second\n\
   -u, --uniform-spacing     one space between words, two after sentences\n\
   -w, --width=WIDTH         maximum line width (default of 75 columns)\n\
+  -g, --goal=WIDTH          goal width (default of 93% of width)\n\
 "), stdout);
       fputs (HELP_OPTION_DESCRIPTION, stdout);
       fputs (VERSION_OPTION_DESCRIPTION, stdout);
@@ -308,6 +310,7 @@ static struct option const long_options[] =
   {"tagged-paragraph", no_argument, NULL, 't'},
   {"uniform-spacing", no_argument, NULL, 'u'},
   {"width", required_argument, NULL, 'w'},
+  {"goal", required_argument, NULL, 'g'},
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
   {NULL, 0, NULL, 0},
@@ -319,6 +322,7 @@ main (int argc, char **argv)
   int optchar;
   bool ok = true;
   char const *max_width_option = NULL;
+  char const *goal_width_option = NULL;

   initialize_main (&argc, &argv);
   set_program_name (argv[0]);
@@ -376,6 +380,10 @@ main (int argc, char **argv)
         max_width_option = optarg;
         break;

+      case 'g':
+        goal_width_option = optarg;
+        break;
+
       case 'p':
         set_prefix (optarg);
         break;
@@ -398,7 +406,25 @@ main (int argc, char **argv)
       max_width = tmp;
     }

-  best_width = max_width * (2 * (100 - LEEWAY) + 1) / 200;
+  if (goal_width_option)
+    {
+      /* Limit goal_width to max_width.  */
+      unsigned long int tmp;
+      if (! (xstrtoul (goal_width_option, NULL, 10, &tmp, "") == LONGINT_OK
+             && tmp <= max_width))
+        error (EXIT_FAILURE, 0, _("invalid width: %s"),
+               quote (goal_width_option));
+      goal_width = tmp;
+      if (max_width_option == NULL)
+        max_width = goal_width + 10;
+    }
+  else
+    {
+      goal_width = max_width * (2 * (100 - LEEWAY) + 1) / 200;
+    }
+
+  if ((max_width_option == NULL) && (goal_width_option == NULL))
+    check_for_goals (argv);

   if (optind == argc)
     fmt (stdin);
@@ -435,6 +461,53 @@ main (int argc, char **argv)
   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
 }

+/* Check the first two operands for being numbers without a file by that name.
+   If there are no such files and the numbers are not too big, then accept
+   them as -g and -w options, respectively.  */
+
+static void
+check_for_goals (char ** argv)
+{
+  unsigned long v;
+
+  /* see if the first operand is a number.  That means there is no file
+     by that name and the operand fully translates to a number.  */
+  char * num = argv[optind];
+  if ((num == NULL) || access (num, R_OK))
+    return;
+  errno = 0;
+  v = strtoul (num, &num, 0);
+  if ((errno == 0) && (*num == '\0') && (v > 0) && (v < MAXCHARS/2))
+    goal_width = v;
+  else
+    return;
+  optind++;
+
+  /* see if the second operand is a number.  That means there is no file
+     by that name and the operand fully translates to a number.  */
+  num = argv[optind];
+  if ((num == NULL) || access (num, R_OK))
+    {
+      max_width = goal_width + 10;
+      return;
+    }
+  errno = 0;
+  v = strtoul (num, &num, 0);
+  if ((errno == 0) && (*num == '\0') && (v > 0) && (v < MAXCHARS/2))
+    {
+      max_width = v;
+      if (goal_width > max_width)
+        error (EXIT_FAILURE, 0, _("goal exceeds width:  %u > %u"),
+               goal_width, max_width);
+    }
+  else
+    {
+      max_width = goal_width + 10;
+      return;
+    }
+  optind++;
+}
+
 /* Trim space from the front and back of the string P, yielding the prefix,
    and record the lengths of the prefix and the space trimmed.  */

@@ -924,7 +997,7 @@ line_cost (WORD *next, int len)

   if (next == word_limit)
     return 0;
-  n = best_width - len;
+  n = goal_width - len;
   cost = SHORT_COST (n);
   if (next->next_break != word_limit)
     {
@@ -1010,3 +1083,10 @@ put_space (int space)
       out_column++;
     }
 }
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "gnu"
+ * indent-tabs-mode: nil
+ * End:
+ * end of fmt.c */
-- 
1.7.7





Information forwarded to bug-coreutils <at> gnu.org:
bug#11044; Package coreutils. (Fri, 30 Mar 2012 21:38:02 GMT) Full text and rfc822 format available.

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

From: Bruce Korb <bruce.korb <at> gmail.com>
To: Eric Blake <eblake <at> redhat.com>
Cc: 11044 <at> debbugs.gnu.org, Bruce Korb <bruce.korb <at> gmail.com>
Subject: Re: bug#11044: bug & RFE
Date: Fri, 30 Mar 2012 14:37:15 -0700
Hi Eric,

I guess nobody is listening.

BSD's implementation allows a goal specification and has a different
default goal width computation anyway.  This change adds a "-g" option
and allows the first two numeric operands to represent the goal width
and actual line width.

* src/fmt.c (main): implement the new option
(check_for_goals): new function to implement the operands
Based on BSD's and Plan-9's fmt programs.
---
 THANKS.in          |    3 ++
 doc/coreutils.texi |   23 +++++++++++--
 src/fmt.c          |   88 +++++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 106 insertions(+), 8 deletions(-)

diff --git a/THANKS.in b/THANKS.in
index d23f7b3..9a525c4 100644
--- a/THANKS.in
+++ b/THANKS.in
@@ -97,6 +99,7 @@ Brian M. Carlson                    sandals <at> crustytoothpaste.ath.cx
 Brian Silverman                     bsilverman <at> conceptxdesign.com
 Brian Youmans                       3diff <at> gnu.org
 Britton Leo Kerin                   fsblk <at> aurora.uaf.edu
+Bruce Korb                          bkorb <at> gnu.org
 Bruce Robertson                     brucer <at> theodolite.dyndns.org
 Carl Johnson                        carlj <at> cjlinux.home.org
 Carl Lowenstein                     cdl <at> mpl.UCSD.EDU
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 835c245..91ca957 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -2133,7 +2133,7 @@ These commands reformat the contents of files.
 a given number of characters (75 by default).  Synopsis:

 @example
-fmt [@var{option}]@dots{} [@var{file}]@dots{}
+fmt [@var{option}]@dots{} [@var{goal} [@var{width}]] [@var{file}]@dots{}
 @end example

 @command{fmt} reads from the specified @var{file} arguments (or standard
@@ -2144,6 +2144,13 @@ preserved in the output; successive input lines with different
 indentation are not joined; tabs are expanded on input and introduced on
 output.

+@var{goal} and @var{width} are only recognized if neither
+@var{-g}/@var{--goal} nor @var{-w}/@var{--width} have been specified; and if
+the strings represent numbers; and if the numbers do not exceed about 2,500;
+and if these strings do not match existing file names.  If @var{GOAL} is
+provided but @var{width} not, then @var{width} will be set to @var{goal}
+plus 10.
+
 @cindex line-breaking
 @cindex sentences and line-breaking
 @cindex Knuth, Donald E.
@@ -2203,9 +2210,17 @@ between sentences to two spaces.
 @opindex -@var{width}
 @opindex -w
 @opindex --width
-Fill output lines up to @var{width} characters (default 75).  @command{fmt}
-initially tries to make lines about 7% shorter than this, to give it
-room to balance line lengths.
+Fill output lines up to @var{width} characters (default 75 or @var{goal} plus 10,
+if @var{goal} is provided).
+
+@item -@var{goal}
+@itemx -g @var{goal}
+@itemx --goal=@var{goal}
+@opindex -@var{goal}
+@opindex -g
+@opindex --goal
+@command{fmt} initially tries to make lines @var{goal} characters wide.
+By default, this is 7% shorter than @var{width}.

 @item -p @var{prefix}
 @itemx --prefix=@var{prefix}
diff --git a/src/fmt.c b/src/fmt.c
index 89d13a6..95ae149 100644
--- a/src/fmt.c
+++ b/src/fmt.c
@@ -68,7 +68,7 @@ typedef long int COST;
 #define SQR(n)        ((n) * (n))
 #define EQUIV(n)    SQR ((COST) (n))

-/* Cost of a filled line n chars longer or shorter than best_width.  */
+/* Cost of a filled line n chars longer or shorter than goal_width.  */
 #define SHORT_COST(n)    EQUIV ((n) * 10)

 /* Cost of the difference between adjacent filled lines.  */
@@ -167,6 +167,7 @@ static void put_paragraph (WORD *finish);
 static void put_line (WORD *w, int indent);
 static void put_word (WORD *w);
 static void put_space (int space);
+static void check_for_goals (char ** argv);

 /* Option values.  */

@@ -201,7 +202,7 @@ static int prefix_lead_space;
 static int prefix_length;

 /* The preferred width of text lines, set to LEEWAY % less than max_width.  */
-static int best_width;
+static int goal_width;

 /* Dynamic variables.  */

@@ -286,6 +287,7 @@ Mandatory arguments to long options are mandatory for short options too.\n\
   -t, --tagged-paragraph    indentation of first line different from second\n\
   -u, --uniform-spacing     one space between words, two after sentences\n\
   -w, --width=WIDTH         maximum line width (default of 75 columns)\n\
+  -g, --goal=WIDTH          goal width (default of 93% of width)\n\
 "), stdout);
       fputs (HELP_OPTION_DESCRIPTION, stdout);
       fputs (VERSION_OPTION_DESCRIPTION, stdout);
@@ -308,6 +310,7 @@ static struct option const long_options[] =
   {"tagged-paragraph", no_argument, NULL, 't'},
   {"uniform-spacing", no_argument, NULL, 'u'},
   {"width", required_argument, NULL, 'w'},
+  {"goal", required_argument, NULL, 'g'},
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
   {NULL, 0, NULL, 0},
@@ -319,6 +322,7 @@ main (int argc, char **argv)
   int optchar;
   bool ok = true;
   char const *max_width_option = NULL;
+  char const *goal_width_option = NULL;

   initialize_main (&argc, &argv);
   set_program_name (argv[0]);
@@ -376,6 +380,10 @@ main (int argc, char **argv)
         max_width_option = optarg;
         break;

+      case 'g':
+        goal_width_option = optarg;
+        break;
+
       case 'p':
         set_prefix (optarg);
         break;
@@ -398,7 +406,25 @@ main (int argc, char **argv)
       max_width = tmp;
     }

-  best_width = max_width * (2 * (100 - LEEWAY) + 1) / 200;
+  if (goal_width_option)
+    {
+      /* Limit goal_width to max_width.  */
+      unsigned long int tmp;
+      if (! (xstrtoul (goal_width_option, NULL, 10, &tmp, "") == LONGINT_OK
+             && tmp <= max_width))
+        error (EXIT_FAILURE, 0, _("invalid width: %s"),
+               quote (goal_width_option));
+      goal_width = tmp;
+      if (max_width_option == NULL)
+        max_width = goal_width + 10;
+    }
+  else
+    {
+      goal_width = max_width * (2 * (100 - LEEWAY) + 1) / 200;
+    }
+
+  if ((max_width_option == NULL) && (goal_width_option == NULL))
+    check_for_goals (argv);

   if (optind == argc)
     fmt (stdin);
@@ -435,6 +461,53 @@ main (int argc, char **argv)
   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
 }

+/* Check the first two operands for being numbers without a file by that name.
+   If there are no such files and the numbers are not too big, then accept
+   them as -g and -w options, respectively.  */
+
+static void
+check_for_goals (char ** argv)
+{
+  unsigned long v;
+
+  /* see if the first operand is a number.  That means there is no file
+     by that name and the operand fully translates to a number.  */
+  char * num = argv[optind];
+  if ((num == NULL) || access (num, R_OK))
+    return;
+  errno = 0;
+  v = strtoul (num, &num, 0);
+  if ((errno == 0) && (*num == '\0') && (v > 0) && (v < MAXCHARS/2))
+    goal_width = v;
+  else
+    return;
+  optind++;
+
+  /* see if the second operand is a number.  That means there is no file
+     by that name and the operand fully translates to a number.  */
+  num = argv[optind];
+  if ((num == NULL) || access (num, R_OK))
+    {
+      max_width = goal_width + 10;
+      return;
+    }
+  errno = 0;
+  v = strtoul (num, &num, 0);
+  if ((errno == 0) && (*num == '\0') && (v > 0) && (v < MAXCHARS/2))
+    {
+      max_width = v;
+      if (goal_width > max_width)
+        error (EXIT_FAILURE, 0, _("goal exceeds width:  %u > %u"),
+               goal_width, max_width);
+    }
+  else
+    {
+      max_width = goal_width + 10;
+      return;
+    }
+  optind++;
+}
+
 /* Trim space from the front and back of the string P, yielding the prefix,
    and record the lengths of the prefix and the space trimmed.  */

@@ -924,7 +997,7 @@ line_cost (WORD *next, int len)

   if (next == word_limit)
     return 0;
-  n = best_width - len;
+  n = goal_width - len;
   cost = SHORT_COST (n);
   if (next->next_break != word_limit)
     {
@@ -1010,3 +1083,10 @@ put_space (int space)
       out_column++;
     }
 }
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "gnu"
+ * indent-tabs-mode: nil
+ * End:
+ * end of fmt.c */
-- 
1.7.7




Information forwarded to bug-coreutils <at> gnu.org:
bug#11044; Package coreutils. (Thu, 05 Apr 2012 09:24:01 GMT) Full text and rfc822 format available.

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

From: Jim Meyering <jim <at> meyering.net>
To: Bruce Korb <bruce.korb <at> gmail.com>
Cc: 11044 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>
Subject: Re: bug#11044: bug & RFE
Date: Thu, 05 Apr 2012 11:22:41 +0200
Hi Bruce,

Thanks for the patch.
[your subject also says "bug".
 Is there a bug fix somewhere in this patch? ]

Bruce Korb wrote:
> I guess nobody is listening.

If no one replies after a few days, it's best to presume
that your message requires more than casual feedback, and
that those inclined to provide feedback have not found time.

> BSD's implementation allows a goal specification and has a different
> default goal width computation anyway.  This change adds a "-g" option
> and allows the first two numeric operands to represent the goal width
> and actual line width.
>
> * src/fmt.c (main): implement the new option
> (check_for_goals): new function to implement the operands
> Based on BSD's and Plan-9's fmt programs.

...
> diff --git a/doc/coreutils.texi b/doc/coreutils.texi
> index 835c245..91ca957 100644
> --- a/doc/coreutils.texi
> +++ b/doc/coreutils.texi
> @@ -2133,7 +2133,7 @@ These commands reformat the contents of files.
>  a given number of characters (75 by default).  Synopsis:
>
>  @example
> -fmt [@var{option}]@dots{} [@var{file}]@dots{}
> +fmt [@var{option}]@dots{} [@var{goal} [@var{width}]] [@var{file}]@dots{}
>  @end example
>
>  @command{fmt} reads from the specified @var{file} arguments (or standard
> @@ -2144,6 +2144,13 @@ preserved in the output; successive input lines with different
>  indentation are not joined; tabs are expanded on input and introduced on
>  output.
>
> +@var{goal} and @var{width} are only recognized if neither
> +@var{-g}/@var{--goal} nor @var{-w}/@var{--width} have been specified; and if
> +the strings represent numbers; and if the numbers do not exceed about 2,500;
> +and if these strings do not match existing file names.  If @var{GOAL} is
> +provided but @var{width} not, then @var{width} will be set to @var{goal}
> +plus 10.

The number of conditions in the above description is a red flag.

Adding a new goal-specifying option sounds fine,
but the part that makes fmt interpret the first two arguments
as non-file-names when they happen to be numeric is dubious,
even though it's limited to when those numbers do not name files.
With that, when someone writes "fmt 1" to process their file named 1,
your modified fmt would work fine, but if somehow they run that command
in a directory without that file, fmt would act differently.
The current fmt would complain about "file not found",
while with the proposed change, it would use 1 as the goal-specifying
number and read from stdin.  That seems too surprising.

Putting it another way, with the *BSD version, "fmt 72 72" is equivalent
to "fmt -w72", most of the time.  But when run in a directory containing
a file named 72, it uses that file as input, instead.

IMHO, it is best not to emulate such an interface.




Information forwarded to bug-coreutils <at> gnu.org:
bug#11044; Package coreutils. (Thu, 05 Apr 2012 14:19:02 GMT) Full text and rfc822 format available.

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

From: Bruce Korb <bruce.korb <at> gmail.com>
To: Jim Meyering <jim <at> meyering.net>
Cc: 11044 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>
Subject: Re: bug#11044: only an RFE now (was bug & RFE)
Date: Thu, 5 Apr 2012 07:16:57 -0700
Hi Jim,

The bug was the sym link issue on the web site, since corrected.

On Thu, Apr 5, 2012 at 2:22 AM, Jim Meyering <jim <at> meyering.net> wrote:
> If no one replies after a few days, it's best to presume
> that your message requires more than casual feedback, and
> that those inclined to provide feedback have not found time.

Sorry.  I was getting antsy because days were becoming weeks.

> The number of conditions in the above description is a red flag.

I didn't really like the maybe-its-a-number-maybe-a-file thingy either.
I did it because someone asked me to make it more BSD compatible.
I chose to then add that compatibility rather than go extra review rounds.
Oh, well.  The number of conditions was to avoid a "fmt 72" problem
when there was a file named "72".  BSD (and Plan9?) is less careful.

> Adding a new goal-specifying option sounds fine,

I'll strip down the patch.

> IMHO, it is best not to emulate such an interface.

Let's not get into vehement agreement on this and just agree to agree.

> - the fmt patch is incomplete (no doc, news, tests)

No news and no tests, but the doc was there.

Cheers - Bruce




Severity set to 'wishlist' from 'normal' Request was from Assaf Gordon <assafgordon <at> gmail.com> to control <at> debbugs.gnu.org. (Tue, 16 Oct 2018 16:21:02 GMT) Full text and rfc822 format available.

Added tag(s) patch. Request was from Assaf Gordon <assafgordon <at> gmail.com> to control <at> debbugs.gnu.org. (Tue, 16 Oct 2018 16:21:02 GMT) Full text and rfc822 format available.

This bug report was last modified 6 years and 250 days ago.

Previous Next


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