sbase

suckless unix tools
git clone git://git.2f30.org/sbase.git
Log | Files | Refs | README | LICENSE

commit ff97891daddbade2811c44d4be6d7023549daf2d
parent 2404eb5b6b9dadf4da11ef149d5cc7cca4014fd6
Author: Connor Lane Smith <cls@lubutu.com>
Date:   Wed Jun  8 21:30:33 +0100

add fold
Diffstat:
Makefile | 3+++
TODO | 2--
fold.1 | 25+++++++++++++++++++++++++
fold.c | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ls.c | 2+-
util.h | 2++
wc.c | 2+-
7 files changed, 131 insertions(+), 4 deletions(-)
diff --git a/Makefile b/Makefile @@ -18,6 +18,7 @@ SRC = \ dirname.c \ echo.c \ false.c \ + fold.c \ grep.c \ head.c \ ln.c \ @@ -70,7 +71,9 @@ install: all @cd $(DESTDIR)$(MANPREFIX)/man1 && chmod 644 $(MAN) uninstall: + @echo removing executables from $(DESTDIR)$(PREFIX)/bin @cd $(DESTDIR)$(PREFIX)/bin && rm -f $(BIN) + @echo removing manual pages from $(DESTDIR)$(MANPREFIX)/man1 @cd $(DESTDIR)$(MANPREFIX)/man1 && rm -f $(MAN) dist: clean diff --git a/TODO b/TODO @@ -11,8 +11,6 @@ cut [-bcfs] [-d delim] list [file...] diff [-ru] file1 file2 -fold [-bs] [-w width] [file...] - id [-gnru] [user] kill [-s signal] [pid...] diff --git a/fold.1 b/fold.1 @@ -0,0 +1,25 @@ +.TH FOLD 1 sbase\-VERSION +.SH NAME +fold \- wrap lines to width +.SH SYNOPSIS +.B fold +.RB [ \-bs ] +.RB [ \-w +.IR width ] +.RI [ file ...] +.SH DESCRIPTION +.B fold +reads each file in sequence and prints its lines, broken such that no line +exceeds 80 characters. If no file is given, fold reads from stdin. +.SH OPTIONS +.TP +.B \-b +counts bytes rather than columns. +.TP +.B \-s +breaks only at spaces. +.TP +.BI \-w " width" +uses +.I width +columns instead of 80. diff --git a/fold.c b/fold.c @@ -0,0 +1,99 @@ +/* See LICENSE file for copyright and license details. */ +#include <ctype.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include "text.h" +#include "util.h" + +static void fold(FILE *, const char *, long); +static void foldline(const char *, long); + +static bool bflag = false; +static bool sflag = false; + +int +main(int argc, char *argv[]) +{ + char c, *end; + long width = 80; + FILE *fp; + + while((c = getopt(argc, argv, "bsw:")) != -1) + switch(c) { + case 'b': + bflag = true; + break; + case 's': + sflag = true; + break; + case 'w': + width = strtol(optarg, &end, 0); + if(*end != '\0') + eprintf("%s: not a number\n", optarg); + break; + default: + exit(EXIT_FAILURE); + } + if(optind == argc) + fold(stdin, "<stdin>", width); + else for(; optind < argc; optind++) { + if(!(fp = fopen(argv[optind], "r"))) + eprintf("fopen %s:", argv[optind]); + fold(fp, argv[optind], width); + fclose(fp); + } + return EXIT_SUCCESS; +} + +void +fold(FILE *fp, const char *str, long width) +{ + char *buf = NULL; + size_t size = 0; + + while(afgets(&buf, &size, fp)) + foldline(buf, width); + free(buf); +} + +void +foldline(const char *str, long width) +{ + bool space; + long col, i, j, n; + + for(i = n = 0; str[i] && str[i] != '\n'; i = n) { + space = false; + for(j = i, col = 0; str[j] && col <= width; j++) { + if(!UTF8_POINT(str[j]) && !bflag) + continue; + if(sflag && isspace(str[j])) { + space = true; + n = j+1; + } + else if(!space) + n = j; + + if(!bflag && iscntrl(str[j])) + switch(str[j]) { + case '\b': + col--; + break; + case '\r': + col = 0; + break; + case '\t': + col += (col+1) % 8; + break; + } + else + col++; + } + if(fwrite(&str[i], 1, n-i, stdout) != n-i) + eprintf("<stdout>: write error:"); + if(str[n]) + putchar('\n'); + } +} diff --git a/ls.c b/ls.c @@ -210,7 +210,7 @@ output(Entry *ent) fmt = "%b %d %H:%M"; strftime(buf, sizeof buf, fmt, localtime(&ent->mtime)); - printf("%s %2d %s %s %6lu %s %s", mode, ent->nlink, pw->pw_name, + printf("%s %2ld %s %s %6lu %s %s", mode, (long)ent->nlink, pw->pw_name, gr->gr_name, (unsigned long)ent->size, buf, ent->name); if(S_ISLNK(ent->mode)) { if((len = readlink(ent->name, buf, sizeof buf)) == -1) diff --git a/util.h b/util.h @@ -1,5 +1,7 @@ /* See LICENSE file for copyright and license details. */ +#define UTF8_POINT(c) (((c) & 0xc0) != 0x80) + char *agetcwd(void); void enmasse(int, char **, int (*)(const char *, const char *)); void eprintf(const char *, ...); diff --git a/wc.c b/wc.c @@ -75,7 +75,7 @@ wc(FILE *fp, const char *str) long nc = 0, nl = 0, nw = 0; while((c = fgetc(fp)) != EOF) { - if(cmode != 'm' || (c & 0xc0) != 0x80) /* utf8 */ + if(cmode != 'm' || UTF8_POINT(c)) nc++; if(c == '\n') nl++;