groff
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Groff] developers only?


From: Larry McVoy
Subject: Re: [Groff] developers only?
Date: Wed, 30 Mar 2005 13:09:40 -0800
User-agent: Mutt/1.5.6+20040907i

On Wed, Mar 30, 2005 at 10:47:43PM +0200, Jorgen Grahn wrote:
> On Wed Mar 30 21:01:52 2005, address@hidden wrote:
> > On Wednesday 30 March 2005 7:49 pm, Otavio Exel wrote:
> > > Otavio Exel wrote:
> > > > How do I get groff to split but don't join?
> > >
> > > being a software developer myself, I must admit I've never had the
> > > "guts" to try to understand groff macros; this was the first time and I
> > > liked it (except for the mandatory leading dot, of course);
> > 
> > Why "of course"?  Placing a period in the first column on a line is a 
> > fairly 
> > natural choice to discriminate between mark up code and running text -- in 
> > English text at least, and presumably the majority of, if not all Western 
> > European languages, it would be most unnatural to begin a line with a 
> > period, 
> > or indeed any of the punctuation characters which normally appear only at 
> > the 
> > end of sentences.
> 
> Well, if one interprets what Otavio says as "requests and macro
> calls must be at the start of lines", it makes sense to me. It
> .I is
> a bit hard to swallow, if you come from e.g. a TeX background where
> the markup doesn't disturb the flow of the text as much. People who have
> complained about this include my hacker colleague, the UTP authors (IIRC)
> and my kid brother
> .ft CW
> ;-)

Coming from a version control background I happen to love the roff requests
because they have a natural tendency to break things up.  When people 
create really long lines and version control them then small changes tend
to conflict more.

And here's a little script that I use to try and format things so that
each sentence starts on a new line.  It works pretty well but patches are
welcome.


#!/usr/bin/perl -w

# These are the (%d) instances on which we will NOT break.
# The fact that the value matches is not used and it doesn't always match.
%spelled = (
        'one', 1,
        'percent', 1,
        'one-half', 1.5,
        'two', 2,
        'three', 3,
        'five', 5,
        'six', 6,
        'ten', 10,
        'twelve', 12,
        'fifteen', 15,
        'twenty-four', 24,
        'thirty', 30,
        'sixty', 60,
        'ninety', 90,
);

@words = ();
while (1) {
        unless (defined($_ = <>)) {
                &flush;
                exit 0;
        }
        next if &blocks;
        # Markups cause a break.
        if (/^[\.<]/) {
                &flush;
                print;
                next;
        }
        # Blank lines cause a break.
        if (/^$/) {
                &flush;
                print "\n";
                next;
        }
        foreach $w (split(/\s+/, $_)) {
                &flush if $w =~ /\(\\/;
                &flush if $w =~ /^\([ivx]+\)$/;
                &flush if $w =~ /^\([a-z]\)$/;
                if ($w =~ /^\(\d\d\)$/ || $w =~ /^\(\d\)$/) {
                        if (($#words == -1) ||
                            !defined($spelled{$words[$#words]})) {
                                &flush;
                        }
                }
                push(@words, $w);
        }
}

# Handle all the various troff blocks
# .CS/.CE       code
# .DS/.DE       display
# .FS/.FE       footnotes
# .GS/.GE       graphical block (Unix/Windows)
# .TS/.TE       table
# .WS/.WE       windows graphical
# .ig\n/..
# .\" Preformatted ==>
# .\" <== Preformatted 
sub blocks
{
        return 0 unless /^\.([CDFGTW])S/ || /^\.(ig)/ ||
            /^\.\\" (Preformatted) ==>/;
        &flush;
        $c = $1;
        print;
        while (defined($_ = <>)) {
                print;
                return 1 if $c eq "ig" && /^\.\./;
                return 1 if $c eq "Preformatted" && /^\.\\" <== Preformatted/;
                return 1 if /^\.$c/ && /^..E\s*$/;
        }
        exit 0;
}

sub flush
{
        my($w, @line);

        return unless ($#words > -1);
        @line = ();
        for ($i = 0; $i <= $#words; ++$i) {
                $w = $words[$i];
                push(@line, $w);
                if (($w =~ /[\.\!\?]$/) && &should_break($w)) {
                        &fmt(@line);
                        @line = ();
                        next;
                }
                if ($w =~ /;$/) {
                        $next = $words[$i + 1];
                        unless ($i < $#words && 
                            ($next eq "or" || $next eq "and")) {
                                &fmt(@line);
                                @line = ();
                        }
                }
        }
        if ($#line != -1) {
                &fmt(@line);
        }
        @words = ();
}

sub fmt
{
        my($w, $len);

        $len = 0;
        foreach $w (@_) {
                if (($len > 0) && ($len + length($w) > 65)) {
                        print "\n";
                        $len = 0;
                }
                if ($len) {
                        print " ";
                        $len++;
                }
                print $w;
                $len += length($w);
        }
        print "\n" if $len;
}

# Don't break on "K." in "Donald K. Someone".
# Don't break on Mr. | Ms.
sub should_break
{
        my($w) = $_[0];

        return 0 if $w =~ /^.\.$/;
        return 0 if $w =~ /^mr\.$/i;
        return 0 if $w =~ /^ms\.$/i;
        return 1;
}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]