home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / unix / question / 14859 < prev    next >
Encoding:
Internet Message Format  |  1992-12-21  |  13.6 KB

  1. Xref: sparky comp.unix.questions:14859 comp.sources.wanted:5455 comp.editors:3089
  2. Newsgroups: comp.unix.questions,comp.sources.wanted,comp.editors
  3. Path: sparky!uunet!nwnexus!osiris
  4. From: David Ruggiero <osiris@halcyon.com>
  5. Subject: SUMMARY: What do *you* use to format mail text?
  6. Message-ID: <1992Dec21.170313.14176@nwnexus.WA.COM>
  7. Followup-To: comp.unix.questions
  8. Originator: osiris@halcyon.com
  9. Keywords: mail format script
  10. Sender: sso@nwnexus.WA.COM (System Security Officer)
  11. Reply-To: osiris@halcyon.halcyon.com (David Ruggiero)
  12. Organization: [none - why fight entropy?]
  13. Date: Mon, 21 Dec 1992 17:03:13 GMT
  14. Lines: 505
  15.  
  16.  
  17. I had asked the question (in several newsgroups) about scripts people
  18. use to format their incoming/outgoing mail text, including evening out
  19. line lengths and adding indent characters. Several people responded: a
  20. few were quite unhelpful, suggesting I use emacs (sorry), long series
  21. of arcane vi commands (that's what I'm trying to get away from!), or
  22. fmt(1) (despite the clear statement in my post that fmt couldn't do
  23. what I needed).
  24.  
  25. Many, however, were very knowledgable and provided scripts of various
  26. degrees of capability and complexity to get the job done. Thanks to
  27. all five of you recognized below...using these routines, I find I
  28. can now waste my time on the net much more efficiently. :)
  29.  
  30. David Ruggiero (osiris@halcyon.com)
  31.  
  32. ------insert_#1-----------------------------------------------------------
  33. {I'll actually start by completely countering what I said above and give
  34. this nifty vi command string to format one line at a time. Simple and
  35. effective and fast.   - jdr}
  36.  
  37.  
  38.   From: galway@chtm.eece.unm.edu (Denis McKeon)
  39.   Newsgroups: comp.unix.questions
  40.   
  41.   While '!fmt' does a nice job for large blocks, I find I prefer to work
  42.   a line at a time (possibly repeated for paragraphs):
  43.   
  44.       map + J074lBhr
  45.   
  46.   This joins lines and then splits them between words left of column 74. 
  47.   Inter-sentence spacing is unaffected.  The solution doesn't depend on
  48.   anything external to 'vi' - you could use it within a 'vi' clone under
  49.   DOS, for instance.  There is no fork overhead (which was a bigger
  50.   problem when I was running Unix on an 8088 in a DEC Rainbow). Since
  51.   David said he was using vi, he could add this to his .exrc file or
  52.   EXINIT environment variable.  Your mileage may vary.
  53.  
  54. ------insert_#2---------------------------------------------------------- 
  55. {Now a short but effective script that uses nroff to do the dirty work.
  56. This is slower, but it works and can be customized to your particular
  57. needs. This is a great lesson in using existing tools rather that writing
  58. your own!      - jdr}
  59.  
  60.  
  61.   From: Ray A. Jones <ray@camco1.celestial.com>
  62.   
  63.   Among other "map" items in my .exrc file, I have
  64.   
  65.   map OS mz}bmx:'z,'x!xfmt
  66.        ^^^ 
  67.         |  Function key F4
  68.   When I want to reformat a paragraph, I put the cursor on the first character
  69.   of the paragraph and press F4.  If you want to use it that way, replace OS
  70.   with whatever key or function key you want.
  71.   
  72.   {This is the "xfmt" script, referenced above:}
  73.   
  74.   echo "" >/tmp/.xy
  75.   echo ".na
  76.   .nh
  77.   .ll 6.5i" >/tmp/xx
  78.   cat - >>/tmp/xx
  79.   nroff /tmp/xx|sed -e "/^$/d" |cat - /tmp/.xy
  80.   rm /tmp/xx /tmp/.xy
  81.   
  82. ------insert_#3-----------------------------------------------------------
  83. {A good suggestion for a good reference.    - jdr}
  84.  
  85.   From: kkress@phent.UUCP (Kenneth R. Kress)
  86.   Subject: Mail formatting scripts
  87.   
  88.    In "Sed & Awk" by Dale Dougherty (O'Reilly & Associates, Inc.)
  89.    such a script is described. It uses nawk (which I don't have) and is
  90.    too long for me to want to type in. If you can get your hands on the
  91.    book, look at "adj" in the Miscellany of Scripts chapter (in my edition,
  92.    p. 329-336).
  93.  
  94. -----insert_#4------------------------------------------------------------
  95. {A highly customizable perl script ('reform') that works well.    - jdr}
  96.  
  97.   From: lwall@netlabs.com <Larry Wall>
  98.   
  99.   #!/usr/bin/perl
  100.   # Usage: reform [-lNUM] [-rNUM] [-iNUM] [-sNUM] [files]
  101.  
  102.   # Set default values for left margin, right margin, indent
  103.   # and paragraph spacing.
  104.   $l = 0;
  105.   $r = 0;
  106.   $i = 0;
  107.   $s = 1;
  108.   
  109.   # Process any switches.
  110.   while ($ARGV[0] =~ /^-/) {
  111.       $_ = shift;
  112.       /^-(l|r|i|s)(\d+)/ && (eval "\$$1 = \$2", next);
  113.       die "Unrecognized switch: $_\n";
  114.   }
  115.   
  116.   # Calculate format strings.
  117.   $r = $l + 65 unless $r;
  118.   $r -= $l;                       # make $r relative to $l
  119.   die "Margins too close\n" if $l + $i >= $r;
  120.   
  121.   $LEFT = ' ' x $l;
  122.   $INDENT = ' ' x $i;
  123.   $RIGHT1 = '^' . '<' x ($r - 1 - $i);
  124.   $RIGHT2 = '^' . '<' x ($r - 1);
  125.   $SPACING = "\n" x $s;
  126.   
  127.   # Define a format at run time.
  128.   $form = <<"End of Format Definition";
  129.   format STDOUT =
  130.   $LEFT$INDENT$RIGHT1
  131.   \$_
  132.   $LEFT$RIGHT2~~
  133.   \$_
  134.   $SPACING.
  135.   End of Format Definition
  136.   
  137.   print $form if $debugging;
  138.   eval $form;
  139.   
  140.   # Set paragraph mode on input.
  141.   $/ = '';
  142.   
  143.   # For each paragraph...
  144.   while (<>) {
  145.       s/\s+/ /g;                      # Canonicalize white space.
  146.       s/ $//;                         # Trim final space.
  147.       s/([Ia-z0-9][)'"]*[.!?][)'"]*) /$1  /g; # Fix sentence ends.
  148.       write;                          # Spit out new paragraph.
  149.   }
  150. -----insert_#5 (long)--------------------------------------------------------
  151. {Finally, a full-blown C program. Enjoy!    - jdr}
  152.  
  153. From: amos shapir <amos@CS.HUJI.AC.IL>
  154. Here is the whole package, man pages included:
  155.  
  156. --Cut-here-------X---------------X---------------X---------------X----
  157. #!/bin/sh
  158. # This is a shell archive (shar 3.32)
  159. # made 12/20/1992 06:54 UTC by amos@hal
  160. # Source directory /a/falafel/home/phd/amos/misc/adj
  161. #
  162. # existing files WILL be overwritten
  163. #
  164. # This shar contains:
  165. # length  mode       name
  166. # ------ ---------- ------------------------------------------
  167. #    685 -rw-r--r-- adj.txt
  168. #   1164 -rw-r--r-- adj.6
  169. #   3395 -rw-r--r-- adj.c
  170. #    316 -rw-r--r-- ctr.6
  171. #    271 -rw-r--r-- ctr.c
  172. #
  173. if touch 2>&1 | fgrep 'amc' > /dev/null
  174.  then TOUCH=touch
  175.  else TOUCH=true
  176. fi
  177. # ============= adj.txt ==============
  178. echo "x - extracting adj.txt (Text)"
  179. sed 's/^X//' << 'SHAR_EOF' > adj.txt &&
  180. X                    Have    you    ever
  181. X                 wished  you had  something
  182. X              to  replace  nroff?   Something
  183. X            small, fast  and versatile,  yet at
  184. X           the same time  flexible and powerful?
  185. X          Well, your troubles are over.  'Adj' is
  186. X          not  as powerful  as nroff  or TeX,  but
  187. X          it's ok for small portions of text, (and
  188. X          much  more  useful than  4BSD's  'fmt').
  189. X          Combined  with  the  trivial  centering
  190. X           filter 'ctr',  it can do  fancy stuff
  191. X            like  this  text.   This  text  was
  192. X                  produced by the command:
  193. X
  194. Xadj -w 19,26,31,35,37,39,40,40,40,39,37,35,31,26,19 | ctr -w 60
  195. SHAR_EOF
  196. $TOUCH -am 1025141788 adj.txt &&
  197. chmod 0644 adj.txt ||
  198. echo "restore of adj.txt failed"
  199. set `wc -c adj.txt`;Wc_c=$1
  200. if test "$Wc_c" != "685"; then
  201.     echo original size 685, current size $Wc_c
  202. fi
  203. # ============= adj.6 ==============
  204. echo "x - extracting adj.6 (Text)"
  205. sed 's/^X//' << 'SHAR_EOF' > adj.6 &&
  206. X.TH ADJ 6 Local
  207. X.UC 4
  208. X.SH NAME
  209. Xadj \- fill and adjust text lines
  210. X.SH SYNOPSIS
  211. X.B adj
  212. X[
  213. X.B \-h
  214. X] [
  215. X.B \-n
  216. X] [
  217. X.B \-p
  218. X] [
  219. X.B \-w
  220. X.I n1,...
  221. X] [ file ]
  222. X.SH DESCRIPTION
  223. X.I Adj
  224. Xcopies the given file (standard input if none is given) to the standard output,
  225. Xfilling lines and adjusting the right margin. Indentation and empty lines
  226. Xare preserved.
  227. X.PP
  228. XNormally, words (uninterrupted sequences of non-blank characters) are not
  229. Xbroken, unless the
  230. X.B \-h
  231. X(hyphen) flag is given.
  232. X.PP
  233. XThe
  234. X.B \-n
  235. X(no adjust) prevents
  236. X.I adj
  237. Xfrom adjusting the right margin.
  238. X.PP
  239. XIf the 
  240. X.B \-p
  241. X(paragraph) option is specified, indentation is preserved only on
  242. Xthe first line of a paragraph, assuming paragraphs are separated by empty lines.
  243. X.PP
  244. XThe
  245. X.B \-w
  246. X.I n
  247. X(width) option sets the line width to
  248. X.I n
  249. X(default 65).
  250. XWhen given as
  251. X.B \-w
  252. X.I n1,n2,...
  253. X(a comma-separated sequence of numbers) the output lines will be
  254. X.I "n1, n2"
  255. Xetc. characters long, respectively.
  256. XWhen the sequence is exhausted, it is restarted.
  257. X.SH "SEE ALSO"
  258. Xctr(6)
  259. X.SH BUGS
  260. X.B \-n
  261. Xdoes not break words intelligently.
  262. X.PP
  263. XChange of indentation is done ungracefully.
  264. X.PP
  265. XThere's probably a better way tp specify line lengths.
  266. SHAR_EOF
  267. $TOUCH -am 0319114087 adj.6 &&
  268. chmod 0644 adj.6 ||
  269. echo "restore of adj.6 failed"
  270. set `wc -c adj.6`;Wc_c=$1
  271. if test "$Wc_c" != "1164"; then
  272.     echo original size 1164, current size $Wc_c
  273. fi
  274. # ============= adj.c ==============
  275. echo "x - extracting adj.c (Text)"
  276. sed 's/^X//' << 'SHAR_EOF' > adj.c &&
  277. X/*
  278. X * Trivial line-fill filter
  279. X * white space at col 1 and empty lines
  280. X * are preserved.
  281. X * flags: -n - dont adjust right margin
  282. X *      -w {n} line is {n} chars wide
  283. X *      -w {n1,n2,...} line is cyclically n1, n2... chars wide
  284. X *      -h - break words with a hyphen
  285. X *      -p - indent only 1st line of a paragraph
  286. X */
  287. X#define MAXB 1024
  288. X#define MAXW 100    /* words in a line */
  289. X#define NLL  50        /* line lengths vector size */
  290. X#define EOF  (-1)
  291. X/* flags */
  292. X#define NOADJ 01    /* no adjust */
  293. X#define HYPHN 02    /* hyphenate */
  294. X#define PARAG 04    /* indent 1 line */
  295. X#define UNBUF 010    /* unbuffered */
  296. Xint ll[NLL] = { 65 };    /* line lengths */
  297. Xint nll;        /* current line length index */
  298. Xint nw;        /* current no. of words */
  299. Xint ind;    /* current indentation */
  300. Xstatic char buf[MAXB];
  301. Xmain(argc, argv)
  302. X    char **argv;
  303. X{
  304. X    register char *pb, *pw, *pe;
  305. X    register c, flags, nl;
  306. X
  307. X    flags = 0;
  308. X    while(--argc > 0)
  309. X        if(**++argv == '-')
  310. X            switch(argv[0][1]) {
  311. X            case 'n':
  312. X                flags = NOADJ;
  313. X                break;
  314. X            case 'h':
  315. X                flags = HYPHN;
  316. X                break;
  317. X            case 'p':
  318. X                flags |= PARAG;
  319. X                break;
  320. X            case 'w':
  321. X                --argc;
  322. X                pb = *++argv;
  323. X                nl=0;
  324. X                do {
  325. X                    for(ll[nl]=0; *pb>='0' && *pb<='9'; pb++)
  326. X                        ll[nl] = ll[nl]*10+*pb-'0';
  327. X                    nl++;
  328. X                }while(*pb++);
  329. X                break;
  330. X            }
  331. X        else {
  332. X            close(0);
  333. X            open(*argv, 0, 0);
  334. X        }
  335. X/*
  336. X * When processing, buf looks like this:
  337. X * buf                 pw pb      pe
  338. X * v----+-+----+-+----+v+-v-------v+
  339. X * |word| |word| |word| |wo        |
  340. X * +----+-+----+-+----+-+----------+
  341. X * nw counts full words, nl empty lines.
  342. X */
  343. X    nl = 2;
  344. X    pb = pw = buf-1;
  345. X    while((c = getchar()) != EOF) {
  346. X        if(c==' ' || c=='\t' || c=='\n') {
  347. X            if(pb>=buf && *pb!=' ') {
  348. X                /* end of a sentence */
  349. X                if(!(flags&HYPHN) &&
  350. X                  (*pb=='.' || *pb=='!' || *pb=='?'))
  351. X                    *++pb = '\037';
  352. X                *++pb = ' ';
  353. X                nw++;
  354. X                pw = pb;    /* word marker in buf */
  355. X            }
  356. X            if(c == '\n') {
  357. X                if(++nl > 1) {    /* end of paragraph */
  358. X                    if(nw > 0) {
  359. X                        putline(pb, NOADJ);
  360. X                        pb = pw = buf-1;
  361. X                        nw = 0;
  362. X                    }
  363. X                    putchar('\n');
  364. X                    ind = 0;
  365. X                }
  366. X            } else if(nl > 1) {
  367. X                if(c == '\t')
  368. X                    ind = (ind/8+1)*8;
  369. X                else
  370. X                    ind++;
  371. X            }
  372. X        } else if(c>' ' && c<0177) {
  373. X            *++pb = c;
  374. X            if(nl) {
  375. X                nl = 0;
  376. X                pe = &buf[ll[nll]-ind];
  377. X            }
  378. X        }
  379. X        if(pb >= pe) {    /* line overflow */
  380. X            if(*pe == '\037') {    /* that's the only case pb>pe */
  381. X                *pe = *pb--;
  382. X                pw = pe;
  383. X            }
  384. X            if((flags&HYPHN) && pb-pw>2) {    /* insert hyphen */
  385. X                *++pb = pe[-1];
  386. X                pe[-1] = '-';
  387. X                *++pb = c;
  388. X                pw = pe;
  389. X                nw++;
  390. X            } else if(nw == 0) {    /* insert blank */
  391. X                *++pb = c;
  392. X                pw = pe;
  393. X                nw++;
  394. X            }
  395. X            putline(pw, flags);
  396. X            for(pe=buf, ++pw; pw<=pb; )
  397. X                *pe++ = *pw++;
  398. X            pb = pe-1;
  399. X            pw = buf-1;
  400. X            pe = &buf[ll[nll]-ind];
  401. X            nw = 0;
  402. X        }
  403. X    }
  404. X    if(nw > 0)
  405. X        putline(pb, NOADJ);
  406. X    return(0);
  407. X}
  408. X
  409. X/*
  410. X * adjust & print line
  411. X */
  412. Xputline(pw, flags)
  413. X    register char *pw;
  414. X{
  415. X    register char *pb;
  416. X    register i, n, b, m;
  417. X
  418. X    for(i=ind; i>=8; i-=8)
  419. X        putchar('\t');
  420. X    for(; i>0; i--)
  421. X        putchar(' ');
  422. X    n = nw-1;
  423. X    if(pw[-1] == '\037')    /* end of sentence at end of line */
  424. X        --pw;
  425. X    b = buf+ll[nll]-ind-pw;    /* no. of blanks to distribute */
  426. X    m = n/2;
  427. X    for(pb=buf; pb<pw; pb++) {
  428. X        putchar(*pb == '\037' ? ' ' : *pb);
  429. X        if(!(flags&NOADJ) && *pb==' ') {
  430. X            m += b;
  431. X            for(i=m/n; i>0; i--)
  432. X                putchar(' ');
  433. X            m %= n;
  434. X        }
  435. X    }
  436. X    putchar('\n');
  437. X    /* cyclic increment line lengths vector */
  438. X    if(ll[++nll] == 0)
  439. X        nll = 0;
  440. X    if(flags&PARAG)
  441. X        ind = 0;
  442. X}
  443. SHAR_EOF
  444. $TOUCH -am 0527174191 adj.c &&
  445. chmod 0644 adj.c ||
  446. echo "restore of adj.c failed"
  447. set `wc -c adj.c`;Wc_c=$1
  448. if test "$Wc_c" != "3395"; then
  449.     echo original size 3395, current size $Wc_c
  450. fi
  451. # ============= ctr.6 ==============
  452. echo "x - extracting ctr.6 (Text)"
  453. sed 's/^X//' << 'SHAR_EOF' > ctr.6 &&
  454. X.TH CTR 6 Local
  455. X.UC 4
  456. X.SH NAME
  457. Xctr \- center text lines
  458. X.SH SYNOPSIS
  459. X.B ctr
  460. X[
  461. X.B \-w
  462. X.I n
  463. X]
  464. X.SH DESCRIPTION
  465. X.I Ctr
  466. Xcopies its standard input to its standard output,
  467. Xcentering text in the output lines.
  468. X.PP
  469. XThe
  470. X.B \-w
  471. X.I n
  472. X(width) option sets the output line width to
  473. X.I n
  474. X(default 65).
  475. X.SH "SEE ALSO"
  476. Xadj(6)
  477. X.SH BUGS
  478. SHAR_EOF
  479. $TOUCH -am 0318144287 ctr.6 &&
  480. chmod 0644 ctr.6 ||
  481. echo "restore of ctr.6 failed"
  482. set `wc -c ctr.6`;Wc_c=$1
  483. if test "$Wc_c" != "316"; then
  484.     echo original size 316, current size $Wc_c
  485. fi
  486. # ============= ctr.c ==============
  487. echo "x - extracting ctr.c (Text)"
  488. sed 's/^X//' << 'SHAR_EOF' > ctr.c &&
  489. X#define NULL ((char *)0)
  490. Xmain(argc, argv)
  491. X    char **argv;
  492. X{
  493. X    static int ll = 65;    /* line length */
  494. X    static buf[100];
  495. X
  496. X    if(argc > 1 && **++argv == '-' && argv[0][1] == 'w')
  497. X            ll = atoi(*++argv);
  498. X    while(gets(buf) != NULL)
  499. X        printf("%*s%s\n", (ll-strlen(buf))/2, "", buf);
  500. X}
  501. SHAR_EOF
  502. $TOUCH -am 0318150987 ctr.c &&
  503. chmod 0644 ctr.c ||
  504. echo "restore of ctr.c failed"
  505. set `wc -c ctr.c`;Wc_c=$1
  506. if test "$Wc_c" != "271"; then
  507.     echo original size 271, current size $Wc_c
  508. fi
  509. exit 0
  510.  
  511. --Cut-here-------X---------------X---------------X---------------X----
  512.  
  513. -----end of all inserts----
  514.  
  515. Hope these help others...again, thanks to those who took the time and trouble
  516. to respond.
  517.  
  518.  
  519. -- 
  520. David Ruggiero  (jdavid@halcyon.com)       Seattle, WA: Home of the Moss People
  521.