From 53cf1b1c1c3f0c2b5067afccc2976b99a574a089 Mon Sep 17 00:00:00 2001 From: tim Date: Wed, 14 May 1997 15:30:41 +0000 Subject: Initial revision --- history/history.1 | 234 ------------------------------------- history/history.c | 341 ------------------------------------------------------ 2 files changed, 575 deletions(-) delete mode 100644 history/history.1 delete mode 100644 history/history.c (limited to 'history') diff --git a/history/history.1 b/history/history.1 deleted file mode 100644 index 18ed28f..0000000 --- a/history/history.1 +++ /dev/null @@ -1,234 +0,0 @@ -.\" history.1 -.\"------- -.\" See rc.1 for man page portability notes. -.\"------- -.\" Dd distance to space vertically before a "display" -.\" These are what n/troff use for interparagraph distance -.\"------- -.if t .nr Dd .4v -.if n .nr Dd 1v -.\"------- -.\" Ds begin a display, indented .5 inches from the surrounding text. -.\" -.\" Note that uses of Ds and De may NOT be nested. -.\"------- -.de Ds -.\" .RS \\$1 -.sp \\n(Ddu -.in +0.5i -.nf -.. -.\"------- -.\" De end a display (no trailing vertical spacing) -.\"------- -.de De -.fi -.in -.\" .RE -.. -.\"------- -.\" I stole the Xf macro from the -man macros on my machine (originally -.\" "}S", I renamed it so that it won't conflict). -.\"------- -.\" Set Cf to the name of the constant width font. -.\" It will be "C" or "(CW", typically. -.\" NOTEZ BIEN the lines defining Cf must have no trailing white space: -.\"------- -.if t .ds Cf C -.if n .ds Cf R -.\"------- -.\" Rc - Alternate Roman and Courier -.\"------- -.de Rc -.Xf R \\*(Cf \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Ic - Alternate Italic and Courier -.\"------- -.de Ic -.Xf I \\*(Cf \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Bc - Alternate Bold and Courier -.\"------- -.de Bc -.Xf B \\*(Cf \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Cr - Alternate Courier and Roman -.\"------- -.de Cr -.Xf \\*(Cf R \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Ci - Alternate Courier and Italic -.\"------- -.de Ci -.Xf \\*(Cf I \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Cb - Alternate Courier and Bold -.\"------- -.de Cb -.Xf \\*(Cf B \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" -.. -.\"------- -.\" Xf - Alternate fonts -.\" -.\" \$1 - first font -.\" \$2 - second font -.\" \$3 - desired word with embedded font changes, built up by recursion -.\" \$4 - text for first font -.\" \$5 - \$9 - remaining args -.\" -.\" Every time we are called: -.\" -.\" If there is something in \$4 -.\" then Call ourself with the fonts switched, -.\" with a new word made of the current word (\$3) and \$4 -.\" rendered in the first font, -.\" and with the remaining args following \$4. -.\" else We are done recursing. \$3 holds the desired output -.\" word. We emit \$3, change to Roman font, and restore -.\" the point size to the default. -.\" fi -.\" -.\" Use Xi to add a little bit of space after italic text. -.\"------- -.de Xf -.ds Xi -.\"------- -.\" I used to test for the italic font both by its font position -.\" and its name. Now just test by its name. -.\" -.\" .if "\\$1"2" .if !"\\$5"" .ds Xi \^ -.\"------- -.if "\\$1"I" .if !"\\$5"" .ds Xi \^ -.\"------- -.\" This is my original code to deal with the recursion. -.\" Evidently some nroffs can't deal with it. -.\"------- -.\" .ie !"\\$4"" \{\ -.\" . Xf \\$2 \\$1 "\\$3\\f\\$1\\$4\\*(Xi" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" -.\" .\} -.\" .el \{\\$3 -.\" . ft R \" Restore the default font, since we don't know -.\" . \" what the last font change was. -.\" . ps 10 \" Restore the default point size, since it might -.\" . \" have been changed by an argument to this macro. -.\" .\} -.\"------- -.\" Here is more portable (though less pretty) code to deal with -.\" the recursion. -.\"------- -.if !"\\$4"" .Xf \\$2 \\$1 "\\$3\\f\\$1\\$4\\*(Xi" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" -.if "\\$4"" \\$3\fR\s10 -.. -.TH HISTORY 1 "30 July 1991" -.SH NAME -\-, \-\|\-, \-p, \-\|\-p \- shell history programs -.SH SYNOPSIS -.B \- -.RI [ pattern ...] -.RI [ substitution ...] -.SH DESCRIPTION -This set of programs provides a crude history mechanism for the shell -.IR rc (1). -It is based on the v8 UNIX programs -.IR = , -.IR == , -etc. -.PP -The program -.RI `` \- '' -runs the shell on the command it is requested to find. -The program -.RI `` \-\|\- '' -edits that command first. -The programs -.RI `` \-p '' -and -.RI `` \-\|\-p '' -are similar, except that they print the final command on their standard -output instead of running the shell. -.PP -The commands work by looking for a file -named by the environment variable -.Cr $history , -and by searching for previous commands in this file. -Old commands can be edited, -or simply re-executed according to the rules below: -.PP -A command is searched for by examining the lines in -.Cr $history -in reverse order. -Lines which contain a previous invocation of the history -program itself are ignored. -If one or more -.I pattern -is supplied on the command line, -then the patterns are used as a means of -limiting the search. -Patterns match any substring of a previous command, -and if more than one pattern is present then all patterns must be -matched before a command is selected. -.PP -Substitutions may also be specified on the command line. -These have the syntax: -.Ds -.Ic old : new -.De -.PP -(Note that the -.I old -pattern is used as a search-limiting pattern also.) -Substitutions happen on the first match. -.PP -Finally, a command may be edited in a crude line-mode fashion: -The line to be edited is printed out, and below it the user -supplies modifications to the command: -.TP -.B any character -Replaces the character above. -.TP -.B space or tab -Skips over the above character(s). -.TP -.B # -Deletes one character. -.TP -.B % -Replaces one character with a space. -.TP -.B ^ -Inserts the rest of the typed line just before the character. -.TP -.B $ -Deletes the rest of the line from that character on, and replaces -it with the rest of the typed line. -.TP -.B + -Appends the rest of the typed line. -.TP -.B \- -Backs up to a previous command satisfying the same matching -constraints. -.TP -.B end of file -If an end-of-file is read from the keyboard by the editor, -it aborts with exit status 1 and does not produce any output. -.SH EXAMPLES -The history programs work best when their output is reinterpreted by -the shell using an -.Cr eval -command. -This can be achieved by writing a shell function to perform the -reinterpretation: -.Ds -.Cr "fn - -- {" -.Cr " comm = \`{$0^p $*}" -.Cr " if (! ~ $#comm 0) {" -.Cr " echo $comm >[1=2]" -.Cr " eval $comm" -.Cr " }" -.Cr "}" diff --git a/history/history.c b/history/history.c deleted file mode 100644 index e6aa29d..0000000 --- a/history/history.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - history.c -- primitive history mechanism - - Paul Haahr & Byron Rakitzis, July 1991. - - This program mimics the att v8 = and == history programs. - The edit() algorithm was adapted from a similar program - that Boyd Roberts wrote, but otherwise all the code has - been written from scratch. - - edit() was subsequently redone by Hugh Redelmeier in order - to correctly deal with tab characters in the source line. - - BUGS: - There is an implicit assumption that commands are no - more than 1k characters long. -*/ - -#include -#include -#include - -static char *id = "@(#) history.c 8/91"; - -#undef FALSE -#undef TRUE -typedef enum { FALSE, TRUE } bool; - -#define CHUNKSIZE 65536 - -static struct { - char *old, *new; -} *replace; - -static char **search, *progname, *history; -static char me; /* typically ':' or '-' */ -static bool editit = FALSE, printit = FALSE; -static int nreplace = 0, nsearch = 0; -static FILE *fp; - -static void *ealloc(size_t n) { - void *p = (void *) malloc(n); - if (p == NULL) { - perror("malloc"); - exit(1); - } - return p; -} - -static void *erealloc(void *p, size_t n) { - p = (void *) realloc(p, n); - if (p == NULL) { - perror("realloc"); - exit(1); - } - return p; -} - -static char *newstr() { - return ealloc((size_t)1024); -} - -static char *basename(char *s) { - char *t = strrchr(s, '/'); - return (t == NULL) ? s : t + 1; -} - -/* stupid O(n^2) substring matching routine */ - -static char *isin(char *target, char *pattern) { - size_t plen = strlen(pattern); - size_t tlen = strlen(target); - for (; tlen >= plen; target++, --tlen) - if (strncmp(target, pattern, plen) == 0) - return target; - return NULL; -} - -/* replace the first match in the string with "new" */ -static char *sub(char *s, char *old, char *new) { - char *t, *u; - - t = isin(s, old); - u = newstr(); - - *t = '\0'; - while (*old != '\0') - old++, t++; - strcpy(u, s); - strcat(u, new); - strcat(u, t); - return u; -} - -static char *edit(char *s) { - char *final, *f, *end; - int col; - bool ins; - -start: - fprintf(stderr, "%s\n", s); - f = final = newstr(); - end = s + strlen(s); - col = 0; - ins = FALSE; - - for (;; col++) { - int c = getchar(); - - if (c == me && col == 0) { - int peekc = getchar(); - if (peekc == '\n') - return NULL; - ungetc(peekc, stdin); - } - if (c == '\n') { - if (col == 0) - return s; - - while (s < end) /* copy remainder of string */ - *f++ = *s++; - *f = '\0'; - s = final; - goto start; - } else if (ins || s>=end) { - /* col need not be accurate -- tabs need not be interpreted */ - *f++ = c; - } else { - switch (c) { - case '+': - while (s < end) - *f++ = *s++; - *f = '\0'; - continue; - case '%': - c = ' '; - /* FALLTHROUGH */ - default: - *f++ = c; - break; - case EOF: - exit(1); - /* NOTREACHED */ - case ' ': - if (*s == '\t') { - int oldcol = col; - - for (;; col++) { - int peekc; - - if ((col&07) == 07) { - *f++ = '\t'; /* we spaced past a tab */ - break; - } - peekc = getchar(); - if (peekc != ' ') { - ungetc(peekc, stdin); - if (peekc != '\n') { - /* we spaced partially into a tab */ - do { - *f++ = ' '; - oldcol++; - } while (oldcol <= col); - } - break; - } - } - } else { - *f++ = *s; - } - break; - case '#': - break; - case '$': - end = s; /* truncate s */ - continue; /* skip incrementing s */ - case '^': - ins = TRUE; - continue; /* skip incrementing s */ - case '\t': - for (;; col++) { - if ((*f++ = s 0) { - count += nread; - if (size - count == 0) - buf = erealloc(buf, size *= 4); - } - if (nread == -1) { - perror(history); - exit(1); - } - *last = buf + count; - return buf; -} - -static char *getcommand() { - char *s, *t; - static char *hist = NULL, *last; - - if (hist == NULL) { - hist = readhistoryfile(&last); - *--last = '\0'; /* trim final newline */ - } - -again: s = last; - if (s < hist) - return NULL; - while (*--s != '\n') - if (s <= hist) { - last = hist - 1; - return hist; - } - *s = '\0'; - last = s++; - - /* - * if the command contains the "me" character at the start of the line - * or after any of [`{|()@] then try again - */ - - for (t = s; *t != '\0'; t++) - if (*t == me) { - char *u = t - 1; - while (u >= s && (*u == ' ' || *u == '\t')) - --u; - if (u < s) - goto again; - switch (*u) { - case '`': case '@': - case '(': case ')': - case '{': case '|': - goto again; - default: - break; - } - } - return s; -} - -int main(int argc, char **argv) { - int i; - char *s; - - s = progname = basename(argv[0]); - me = *s++; - if (*s == me) { - s++; - editit = TRUE; - } - if (*s == 'p') { - s++; - printit = TRUE; - } -/* Nahh... - if (*s != '\0') { - fprintf(stderr, "\"%s\": bad name for history program\n", progname); - exit(1); - } -*/ - - if (argc > 1) { - replace = ealloc((argc - 1) * sizeof *replace); - search = ealloc((argc - 1) * sizeof *search); - } - for (i = 1; i < argc; i++) - if ((s = strchr(argv[i], ':')) == NULL) - search[nsearch++] = argv[i]; - else { - *(char *)s = '\0'; /* do we confuse ps too much? */ - replace[nreplace].old = argv[i]; - replace[nreplace].new = s + 1; - nreplace++; - } - -next: s = getcommand(); - if (s == NULL) { - fprintf(stderr, "command not matched\n"); - return 1; - } - for (i = 0; i < nsearch; i++) - if (!isin(s, search[i])) - goto next; - for (i = 0; i < nreplace; i++) - if (!isin(s, replace[i].old)) - goto next; - else - s = sub(s, replace[i].old, replace[i].new); - if (editit) { - s = edit(s); - if (s == NULL) - goto next; - } - fseek(fp, 0, 2); /* 2 == end of file. i.e., append command to $history */ - fprintf(fp, "%s\n", s); - fclose(fp); - if (printit) - printf("%s\n", s); - else { - char *shell = getenv("SHELL"); - - if (!editit) - fprintf(stderr, "%s\n", s); - if (shell == NULL) - shell = "/bin/sh"; - execl(shell, basename(shell), "-c", s, NULL); - perror(shell); - exit(1); - } - return 0; -} -- cgit v1.2.3