Introduction
Introduction Statistics Contact Development Disclaimer Help
added fmt as well - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
commit 78a6c092e93295e60ed4cba344117a34b586d7da
parent e70375948b9e9afebde07fb294abf5f039f19d44
Author: [email protected] <unknown>
Date: Thu, 27 May 2010 13:02:29 +0100
added fmt as well
Diffstat:
M Makefile | 4 ++--
A fmt/Makefile | 10 ++++++++++
A fmt/fmt.1 | 90 +++++++++++++++++++++++++++++…
A fmt/fmt.c | 241 +++++++++++++++++++++++++++++…
4 files changed, 343 insertions(+), 2 deletions(-)
---
diff --git a/Makefile b/Makefile
@@ -3,8 +3,8 @@
include config.mk
SUBDIRS = lib9 yacc awk basename bc cal cat cleanname date dc du echo ed \
- factor fortune freq getflags grep hoc ls mk mkdir mtime primes rc r…
- sha1sum sed seq sleep sort tail tee test touch tr troff uniq
+ factor fortune fmt freq getflags grep hoc ls mk mkdir mtime primes \
+ rc read sha1sum sed seq sleep sort tail tee test touch tr troff uniq
all:
@echo 9base build options:
diff --git a/fmt/Makefile b/fmt/Makefile
@@ -0,0 +1,10 @@
+# fmt - fmt unix port from plan9
+# Depends on ../lib9
+
+TARG = fmt
+
+include ../std.mk
+
+pre-uninstall:
+
+post-install:
diff --git a/fmt/fmt.1 b/fmt/fmt.1
@@ -0,0 +1,90 @@
+.TH FMT 1
+.SH NAME
+fmt, htmlfmt \- simple text formatters
+.SH SYNOPSIS
+.B fmt
+[
+.I option ...
+]
+[
+.I file ...
+]
+.PP
+.B htmlfmt
+[
+.B -a
+] [
+.B -c
+.I charset
+] [
+.B -u
+.I url
+] [
+.I file ...
+]
+.SH DESCRIPTION
+.I Fmt
+copies the given
+.I files
+(standard input by default)
+to its standard output, filling and indenting lines.
+The options are
+.TP
+.BI -l " n
+Output line length is
+.IR n ,
+including indent (default 70).
+.TP
+.BI -w " n
+A synonym for
+.BR -l .
+.TP
+.BI -i " n
+Indent
+.I n
+spaces (default 0).
+.TP
+.BI -j
+Do not join short lines: only fold long lines.
+.PP
+Empty lines and initial white space in input lines are preserved.
+Empty lines are inserted between input files.
+.PP
+.I Fmt
+is idempotent: it leaves already formatted text unchanged.
+.PP
+.I Htmlfmt
+performs a similar service, but accepts as input text formatted with
+HTML tags.
+It accepts
+.IR fmt 's
+.B -l
+and
+.B -w
+flags and also:
+.TP
+.BI -a
+Normally
+.I htmlfmt
+suppresses the contents of form fields and anchors (URLs and image files); thi…
+causes it to print them, in square brackets.
+.TP
+.BI -c " charset
+change the default character set from iso-8859-1 to
+.IR charset .
+This is the character set assumed if there isn't one
+specified by the html itself in a <meta> directive.
+.TP
+.BI -u " url
+Use
+.I url
+as the base URL for the document when displaying anchors; sets
+.BI -a .
+.SH SOURCE
+.B \*9/src/cmd/fmt.c
+.PP
+.B \*9/src/cmd/htmlfmt
+.SH BUGS
+.I Htmlfmt
+makes no attempt to render the two-dimensional geometry of tables;
+it just treats the table entries as plain, to-be-formatted text.
diff --git a/fmt/fmt.c b/fmt/fmt.c
@@ -0,0 +1,241 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ctype.h>
+
+/*
+ * block up paragraphs, possibly with indentation
+ */
+
+int extraindent = 0; /* how many spaces to indent all lines */
+int indent = 0; /* current value of indent, before extr…
+int length = 70; /* how many columns per output line */
+int join = 1; /* can lines be joined? */
+int maxtab = 8;
+Biobuf bin;
+Biobuf bout;
+
+typedef struct Word Word;
+struct Word{
+ int bol;
+ int indent;
+ char text[1];
+};
+
+void fmt(void);
+
+void
+usage(void)
+{
+ fprint(2, "usage: %s [-j] [-i indent] [-l length] [file...]\n", argv0);
+ exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+ int i, f;
+ char *s, *err;
+
+ ARGBEGIN{
+ case 'i':
+ extraindent = atoi(EARGF(usage()));
+ break;
+ case 'j':
+ join = 0;
+ break;
+ case 'w':
+ case 'l':
+ length = atoi(EARGF(usage()));
+ break;
+ default:
+ usage();
+ }ARGEND
+
+ if(length <= indent){
+ fprint(2, "%s: line length<=indentation\n", argv0);
+ exits("length");
+ }
+
+ s=getenv("tabstop");
+ if(s!=nil && atoi(s)>0)
+ maxtab=atoi(s);
+ err = nil;
+ Binit(&bout, 1, OWRITE);
+ if(argc <= 0){
+ Binit(&bin, 0, OREAD);
+ fmt();
+ }else{
+ for(i=0; i<argc; i++){
+ f = open(argv[i], OREAD);
+ if(f < 0){
+ fprint(2, "%s: can't open %s: %r\n", argv0, ar…
+ err = "open";
+ }else{
+ Binit(&bin, f, OREAD);
+ fmt();
+ Bterm(&bin);
+ if(i != argc-1)
+ Bputc(&bout, '\n');
+ }
+ }
+ }
+ exits(err);
+}
+
+int
+indentof(char **linep)
+{
+ int i, ind;
+ char *line;
+
+ ind = 0;
+ line = *linep;
+ for(i=0; line[i]; i++)
+ switch(line[i]){
+ default:
+ *linep = line;
+ return ind;
+ case ' ':
+ ind++;
+ break;
+ case '\t':
+ ind += maxtab;
+ ind -= ind%maxtab;
+ break;
+ }
+
+ /* plain white space doesn't change the indent */
+ *linep = "";
+ return indent;
+}
+
+Word**
+addword(Word **words, int *nwordp, char *s, int l, int indent, int bol)
+{
+ Word *w;
+
+ w = malloc(sizeof(Word)+l+1);
+ memmove(w->text, s, l);
+ w->text[l] = '\0';
+ w->indent = indent;
+ w->bol = bol;
+ words = realloc(words, (*nwordp+1)*sizeof(Word*));
+ words[(*nwordp)++] = w;
+ return words;
+}
+
+Word**
+parseline(char *line, Word **words, int *nwordp)
+{
+ int ind, l, bol;
+
+ ind = indentof(&line);
+ indent = ind;
+ bol = 1;
+ for(;;){
+ /* find next word */
+ while(*line==' ' || *line=='\t')
+ line++;
+ if(*line == '\0'){
+ if(bol)
+ return addword(words, nwordp, "", 0, -1, bol);
+ break;
+ }
+ /* how long is this word? */
+ for(l=0; line[l]; l++)
+ if(line[l]==' ' || line[l]=='\t')
+ break;
+ words = addword(words, nwordp, line, l, indent, bol);
+ bol = 0;
+ line += l;
+ }
+ return words;
+}
+
+void
+printindent(int w)
+{
+ while(w >= maxtab){
+ Bputc(&bout, '\t');
+ w -= maxtab;
+ }
+ while(w > 0){
+ Bputc(&bout, ' ');
+ w--;
+ }
+}
+
+/* give extra space if word ends with period, etc. */
+int
+nspaceafter(char *s)
+{
+ int n;
+
+ n = strlen(s);
+ if(n < 2)
+ return 1;
+ if(isupper((uchar)s[0]) && n < 4)
+ return 1;
+ if(strchr(".!?", s[n-1]) != nil)
+ return 2;
+ return 1;
+}
+
+
+void
+printwords(Word **w, int nw)
+{
+ int i, j, n, col, nsp;
+
+ /* one output line per loop */
+ for(i=0; i<nw; ){
+ /* if it's a blank line, print it */
+ if(w[i]->indent == -1){
+ Bputc(&bout, '\n');
+ if(++i == nw) /* out of words */
+ break;
+ }
+ /* emit leading indent */
+ col = extraindent+w[i]->indent;
+ printindent(col);
+ /* emit words until overflow; always emit at least one word */
+ for(n=0;; n++){
+ Bprint(&bout, "%s", w[i]->text);
+ col += utflen(w[i]->text);
+ if(++i == nw)
+ break; /* out of words */
+ if(w[i]->indent != w[i-1]->indent)
+ break; /* indent change */
+ nsp = nspaceafter(w[i-1]->text);
+ if(col+nsp+utflen(w[i]->text) > extraindent+length)
+ break; /* fold line */
+ if(!join && w[i]->bol)
+ break;
+ for(j=0; j<nsp; j++)
+ Bputc(&bout, ' '); /* emit space; anoth…
+ col += nsp;
+ }
+ /* emit newline */
+ Bputc(&bout, '\n');
+ }
+}
+
+void
+fmt(void)
+{
+ char *s;
+ int i, nw;
+ Word **w;
+
+ nw = 0;
+ w = nil;
+ while((s = Brdstr(&bin, '\n', 1)) != nil){
+ w = parseline(s, w, &nw);
+ free(s);
+ }
+ printwords(w, nw);
+ for(i=0; i<nw; i++)
+ free(w[i]);
+ free(w);
+}
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.