mirror of
https://git.savannah.gnu.org/git/coreutils.git
synced 2025-09-10 07:59:52 +02:00
fmt: accept new --goal=WIDTH (-g) option
Accept -g for BSD/Plan9 compatibility. * NEWS (New features): Mention it. * tests/fmt/goal-option: New test. * tests/fmt/long-line: Rename from tests/fmt-long-line. * tests/fmt/base: Rename from tests/misc/fmt. * doc/coreutils.texi: Document it. * src/fmt.c (main): Accept the new option (check_for_goals): new function to implement the operands Based on BSD's and Plan-9's fmt programs.
This commit is contained in:
4
NEWS
4
NEWS
@@ -2,6 +2,10 @@ GNU coreutils NEWS -*- outline -*-
|
||||
|
||||
* Noteworthy changes in release ?.? (????-??-??) [?]
|
||||
|
||||
** New features
|
||||
|
||||
fmt now accepts the --goal=WIDTH (-g) option.
|
||||
|
||||
** Changes in behavior
|
||||
|
||||
cp --attributes-only no longer truncates any existing destination file,
|
||||
|
||||
@@ -2203,9 +2203,15 @@ 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).
|
||||
|
||||
@itemx -g @var{goal}
|
||||
@itemx --goal=@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}
|
||||
|
||||
32
src/fmt.c
32
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. */
|
||||
@@ -201,7 +201,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 +286,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 +309,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 +321,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]);
|
||||
@@ -344,7 +347,7 @@ main (int argc, char **argv)
|
||||
argc--;
|
||||
}
|
||||
|
||||
while ((optchar = getopt_long (argc, argv, "0123456789cstuw:p:",
|
||||
while ((optchar = getopt_long (argc, argv, "0123456789cstuw:p:g:",
|
||||
long_options, NULL))
|
||||
!= -1)
|
||||
switch (optchar)
|
||||
@@ -376,6 +379,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 +405,22 @@ 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 (optind == argc)
|
||||
fmt (stdin);
|
||||
@@ -924,7 +946,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)
|
||||
{
|
||||
|
||||
@@ -140,6 +140,9 @@ TESTS = \
|
||||
chgrp/no-x \
|
||||
chgrp/posix-H \
|
||||
chgrp/recurse \
|
||||
fmt/base \
|
||||
fmt/long-line \
|
||||
fmt/goal-option \
|
||||
misc/env \
|
||||
misc/ptx \
|
||||
misc/test \
|
||||
@@ -188,8 +191,6 @@ TESTS = \
|
||||
misc/expr \
|
||||
misc/factor \
|
||||
misc/false-status \
|
||||
misc/fmt \
|
||||
misc/fmt-long-line \
|
||||
misc/fold \
|
||||
misc/groups-dash \
|
||||
misc/groups-version \
|
||||
|
||||
56
tests/fmt/goal-option
Executable file
56
tests/fmt/goal-option
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/bin/sh
|
||||
# Exercise the fmt -g option.
|
||||
|
||||
# Copyright (C) 2012 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
. "${srcdir=.}/init.sh"; path_prepend_ ../src
|
||||
print_ver_ fmt
|
||||
|
||||
cat <<\_EOF_ > base || fail=1
|
||||
|
||||
@command{fmt} prefers breaking lines at the end of a sentence, and tries to
|
||||
avoid line breaks after the first word of a sentence or before the last word
|
||||
of a sentence. A @dfn{sentence break} is defined as either the end of a
|
||||
paragraph or a word ending in any of @samp{.?!}, followed by two spaces or end
|
||||
of line, ignoring any intervening parentheses or quotes. Like @TeX{},
|
||||
@command{fmt} reads entire ''paragraphs'' before choosing line breaks; the
|
||||
algorithm is a variant of that given by
|
||||
Donald E. Knuth and Michael F. Plass
|
||||
in ''Breaking Paragraphs Into Lines'',
|
||||
@cite{Software---Practice & Experience}
|
||||
@b{11}, 11 (November 1981), 1119--1184.
|
||||
_EOF_
|
||||
|
||||
fmt -g 60 -w 72 base > out || fail=1
|
||||
|
||||
cat <<\_EOF_ > exp
|
||||
|
||||
@command{fmt} prefers breaking lines at the end of a sentence,
|
||||
and tries to avoid line breaks after the first word of a sentence
|
||||
or before the last word of a sentence. A @dfn{sentence break}
|
||||
is defined as either the end of a paragraph or a word ending
|
||||
in any of @samp{.?!}, followed by two spaces or end of line,
|
||||
ignoring any intervening parentheses or quotes. Like @TeX{},
|
||||
@command{fmt} reads entire ''paragraphs'' before choosing line
|
||||
breaks; the algorithm is a variant of that given by Donald
|
||||
E. Knuth and Michael F. Plass in ''Breaking Paragraphs Into
|
||||
Lines'', @cite{Software---Practice & Experience} @b{11}, 11
|
||||
(November 1981), 1119--1184.
|
||||
_EOF_
|
||||
|
||||
compare exp out || fail=1
|
||||
|
||||
Exit $fail
|
||||
Reference in New Issue
Block a user