Don't format lines that look like troff requests, for
compatibility with old fmt(1). New option -n permits formatting of lines beginning with a dot character. PR: bin/31392 MFC after: 3 days
This commit is contained in:
parent
b9c35b6942
commit
deba245176
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=89268
@ -42,7 +42,7 @@
|
|||||||
.Nd simple text formatter
|
.Nd simple text formatter
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm fmt
|
.Nm fmt
|
||||||
.Op Fl cmps
|
.Op Fl cmnps
|
||||||
.Op Fl d Ar chars
|
.Op Fl d Ar chars
|
||||||
.Op Fl l Ar num
|
.Op Fl l Ar num
|
||||||
.Op Fl t Ar num
|
.Op Fl t Ar num
|
||||||
@ -88,6 +88,14 @@ In this case, most of the other
|
|||||||
options are ignored; no splitting or joining of lines is done.
|
options are ignored; no splitting or joining of lines is done.
|
||||||
.It Fl m
|
.It Fl m
|
||||||
Try to format mail header lines contained in the input sensibly.
|
Try to format mail header lines contained in the input sensibly.
|
||||||
|
.It Fl n
|
||||||
|
Format lines beginning with a
|
||||||
|
.Ql \&.
|
||||||
|
(dot) character.
|
||||||
|
Normally,
|
||||||
|
.Nm
|
||||||
|
does not fill these lines, for compatibility with
|
||||||
|
.Xr nroff 1 .
|
||||||
.It Fl p
|
.It Fl p
|
||||||
Allow indented paragraphs.
|
Allow indented paragraphs.
|
||||||
Without the
|
Without the
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
* preceded by a non-blank non-message-header line, is
|
* preceded by a non-blank non-message-header line, is
|
||||||
* taken to start a new paragraph, which also contains
|
* taken to start a new paragraph, which also contains
|
||||||
* any subsequent lines with non-empty leading whitespace.
|
* any subsequent lines with non-empty leading whitespace.
|
||||||
|
* Unless the `-n' option is given, lines beginning with
|
||||||
|
* a . (dot) are not formatted.
|
||||||
* 3. The "everything else" is split into words; a word
|
* 3. The "everything else" is split into words; a word
|
||||||
* includes its trailing whitespace, and a word at the
|
* includes its trailing whitespace, and a word at the
|
||||||
* end of a line is deemed to be followed by a single
|
* end of a line is deemed to be followed by a single
|
||||||
@ -222,6 +224,7 @@ static int tab_width=8; /* Number of spaces per tab stop */
|
|||||||
static size_t output_tab_width=8; /* Ditto, when squashing leading spaces */
|
static size_t output_tab_width=8; /* Ditto, when squashing leading spaces */
|
||||||
static const char *sentence_enders=".?!"; /* Double-space after these */
|
static const char *sentence_enders=".?!"; /* Double-space after these */
|
||||||
static int grok_mail_headers=0; /* treat embedded mail headers magically? */
|
static int grok_mail_headers=0; /* treat embedded mail headers magically? */
|
||||||
|
static int format_troff=0; /* Format troff? */
|
||||||
|
|
||||||
static int n_errors=0; /* Number of failed files. Return on exit. */
|
static int n_errors=0; /* Number of failed files. Return on exit. */
|
||||||
static char *output_buffer=0; /* Output line will be built here */
|
static char *output_buffer=0; /* Output line will be built here */
|
||||||
@ -257,10 +260,11 @@ main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
/* 1. Grok parameters. */
|
/* 1. Grok parameters. */
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "0123456789cd:hl:mpst:w:")) != -1)
|
while ((ch = getopt(argc, argv, "0123456789cd:hl:mnpst:w:")) != -1)
|
||||||
switch(ch) {
|
switch(ch) {
|
||||||
case 'c':
|
case 'c':
|
||||||
centerP = 1;
|
centerP = 1;
|
||||||
|
format_troff = 1;
|
||||||
continue;
|
continue;
|
||||||
case 'd':
|
case 'd':
|
||||||
sentence_enders = optarg;
|
sentence_enders = optarg;
|
||||||
@ -272,6 +276,9 @@ main(int argc, char *argv[]) {
|
|||||||
case 'm':
|
case 'm':
|
||||||
grok_mail_headers = 1;
|
grok_mail_headers = 1;
|
||||||
continue;
|
continue;
|
||||||
|
case 'n':
|
||||||
|
format_troff = 1;
|
||||||
|
continue;
|
||||||
case 'p':
|
case 'p':
|
||||||
allow_indented_paragraphs = 1;
|
allow_indented_paragraphs = 1;
|
||||||
continue;
|
continue;
|
||||||
@ -307,6 +314,7 @@ main(int argc, char *argv[]) {
|
|||||||
" -d <chars> double-space after <chars> at line end\n"
|
" -d <chars> double-space after <chars> at line end\n"
|
||||||
" -l <n> turn each <n> spaces at start of line into a tab\n"
|
" -l <n> turn each <n> spaces at start of line into a tab\n"
|
||||||
" -m try to make sure mail header lines stay separate\n"
|
" -m try to make sure mail header lines stay separate\n"
|
||||||
|
" -n format lines beginning with a dot\n"
|
||||||
" -p allow indented paragraphs\n"
|
" -p allow indented paragraphs\n"
|
||||||
" -s coalesce whitespace inside lines\n"
|
" -s coalesce whitespace inside lines\n"
|
||||||
" -t <n> have tabs every <n> columns\n"
|
" -t <n> have tabs every <n> columns\n"
|
||||||
@ -395,6 +403,7 @@ process_stream(FILE *stream, const char *name) {
|
|||||||
}
|
}
|
||||||
/* We need a new paragraph if and only if:
|
/* We need a new paragraph if and only if:
|
||||||
* this line is blank,
|
* this line is blank,
|
||||||
|
* OR it's a troff request (and we don't format troff),
|
||||||
* OR it's a mail header,
|
* OR it's a mail header,
|
||||||
* OR it's not a mail header AND the last line was one,
|
* OR it's not a mail header AND the last line was one,
|
||||||
* OR the indentation has changed
|
* OR the indentation has changed
|
||||||
@ -402,6 +411,7 @@ process_stream(FILE *stream, const char *name) {
|
|||||||
* AND this isn't the second line of an indented paragraph.
|
* AND this isn't the second line of an indented paragraph.
|
||||||
*/
|
*/
|
||||||
if ( length==0
|
if ( length==0
|
||||||
|
|| (line[0]=='.' && !format_troff)
|
||||||
|| header_type==hdr_Header
|
|| header_type==hdr_Header
|
||||||
|| (header_type==hdr_NonHeader && prev_header_type>hdr_NonHeader)
|
|| (header_type==hdr_NonHeader && prev_header_type>hdr_NonHeader)
|
||||||
|| (np!=last_indent
|
|| (np!=last_indent
|
||||||
@ -412,8 +422,11 @@ process_stream(FILE *stream, const char *name) {
|
|||||||
first_indent = np;
|
first_indent = np;
|
||||||
last_indent = np;
|
last_indent = np;
|
||||||
if (header_type==hdr_Header) last_indent=2; /* for cont. lines */
|
if (header_type==hdr_Header) last_indent=2; /* for cont. lines */
|
||||||
if (length==0) {
|
if (length==0 || (line[0]=='.' && !format_troff)) {
|
||||||
putchar('\n');
|
if (length==0)
|
||||||
|
putchar('\n');
|
||||||
|
else
|
||||||
|
printf("%.*s\n", (int)length, line);
|
||||||
prev_header_type=hdr_ParagraphStart;
|
prev_header_type=hdr_ParagraphStart;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -594,11 +607,13 @@ get_line(FILE *stream, size_t *lengthp) {
|
|||||||
size_t len=0;
|
size_t len=0;
|
||||||
int ch;
|
int ch;
|
||||||
size_t spaces_pending=0;
|
size_t spaces_pending=0;
|
||||||
|
int troff=0;
|
||||||
|
|
||||||
if (buf==NULL) { length=100; buf=XMALLOC(length); }
|
if (buf==NULL) { length=100; buf=XMALLOC(length); }
|
||||||
while ((ch=getc(stream)) != '\n' && ch != EOF) {
|
while ((ch=getc(stream)) != '\n' && ch != EOF) {
|
||||||
|
if (len+spaces_pending==0 && ch=='.' && !format_troff) troff=1;
|
||||||
if (ch==' ') ++spaces_pending;
|
if (ch==' ') ++spaces_pending;
|
||||||
else if (isprint(ch)) {
|
else if (troff || isprint(ch)) {
|
||||||
while (len+spaces_pending >= length) {
|
while (len+spaces_pending >= length) {
|
||||||
length*=2; buf=xrealloc(buf, length);
|
length*=2; buf=xrealloc(buf, length);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user