1547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland/* fold.c - fold text 2547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland * 3547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland * Copyright 2014 Samuel Holland <samuel@sholland.net> 4547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland * 5547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/fold.html 6547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland 742cc29c7883c852462c6c740c72eff06bca8acccHyejin KimUSE_FOLD(NEWTOY(fold, "bsuw#<1", TOYFLAG_USR|TOYFLAG_BIN)) 8547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland 9547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Hollandconfig FOLD 10547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland bool "fold" 11547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland default n 12547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland help 13aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland usage: fold [-bsu] [-w WIDTH] [FILE...] 14547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland 157bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley Folds (wraps) or unfolds ascii text by adding or removing newlines. 16aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland Default line width is 80 columns for folding and infinite for unfolding. 17547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland 187bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley -b Fold based on bytes instead of columns 197bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley -s Fold/unfold at whitespace boundaries if possible 207bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley -u Unfold text (and refold if -w is given) 217bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley -w Set lines to WIDTH columns or bytes 22547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland*/ 23547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland 24547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland#define FOR_fold 25547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland#include "toys.h" 26547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland 27547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel HollandGLOBALS( 28aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland int width; 29547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland) 30547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland 317bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley// wcwidth mbrtowc 32547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Hollandvoid do_fold(int fd, char *name) 33547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland{ 347bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley int bufsz, len = 0, maxlen; 35547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland 367bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley if (toys.optflags & FLAG_w) maxlen = TT.width; 377bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley else if (toys.optflags & FLAG_u) maxlen = 0; 387bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley else maxlen = 80; 39547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland 40aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland while ((bufsz = read(fd, toybuf, sizeof(toybuf))) > 0) { 417bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley char *buf = toybuf; 427bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley int pos = 0, split = -1; 43547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland 44aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland while (pos < bufsz) { 45aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland switch (buf[pos]) { 46547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland case '\n': 477bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley // print everything but the \n, then move on to the next buffer 48aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland if ((toys.optflags & FLAG_u) && buf[pos-1] != '\n' 49aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland && buf[pos+1] != '\n') { 50aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland xwrite(1, buf, pos); 51aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland bufsz -= pos + 1; 52aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland buf += pos + 1; 53aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland pos = 0; 54aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland split = -1; 557bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley // reset len, FLAG_b or not; just print multiple lines at once 567bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley } else len = 0; 57aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland break; 58547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland case '\b': 597bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley // len cannot be negative; not allowed to wrap after backspace 60547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland if (toys.optflags & FLAG_b) len++; 61547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland else if (len > 0) len--; 62aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland break; 63547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland case '\r': 647bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley // not allowed to wrap after carriage return 65547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland if (toys.optflags & FLAG_b) len++; 66547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland else len = 0; 67aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland break; 68547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland case '\t': 697bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley // round to 8, but we add one after falling through 707bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley // (because of whitespace, but it also takes care of FLAG_b) 717bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley if (!(toys.optflags & FLAG_b)) len = (len & ~7) + 7; 72547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland case ' ': 73aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland split = pos; 74547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland default: 75547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland len++; 76547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland } 77547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland 787bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley // we don't want to double up \n; not allowed to wrap before \b 79aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland if (maxlen > 0 && len >= maxlen && buf[pos+1] != '\n' && buf[pos+1] != '\b') { 80aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland if (!(toys.optflags & FLAG_s) || split < 0) split = pos; 81aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland xwrite(1, buf, split + 1); 82aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland xputc('\n'); 83aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland bufsz -= split + 1; 84aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland buf += split + 1; 85aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland len = pos = 0; 86aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland split = -1; 877bcaf03f1506d338cde2f6d1b953d6ba6e5a7ea7Rob Landley } else pos++; 88547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland } 89aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland xwrite(1, buf, bufsz); 90547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland } 91aac4222dd8dcce3e7a782111ac7d7d9d0bfb2972Samuel Holland xputc('\n'); 92547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland} 93547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland 94547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Hollandvoid fold_main(void) 95547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland{ 96547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland loopfiles(toys.optargs, do_fold); 97547c8d980bb5ae37f8002aead4e155cc5554dfcaSamuel Holland} 98