📄 hist.c
字号:
/************************************************************* * File: mon/hist.c * Purpose: Part of core Monitor * Author: Phil Bunce (pjb@carmel.com) * Revision History: * 970304 Start of revision history * 971002 Made some functions static * 971002 Fixed probs with ^N and ^P past end/beginning of history * 980331 changed getchar to GETCHAR for imon95 */#include <stdio.h>#include <termio.h>#include <string.h>#include <mon.h>#ifdef PMCC#define GETCHAR getchar#endif#define H_PREV CNTRL('P')#define H_NEXT CNTRL('N')#define H_FORW CNTRL('F')#define H_BACK CNTRL('B')#define H_BEGIN CNTRL('A')#define H_END CNTRL('E')#define H_DELETE CNTRL('D')char *hist[HISTMAX]; /* array of old commands */int histi; /* index to hist[], indicates next slot */int histo; /* index to hist[], indicates oldest entry */int histr; /* index to hist[], used while walking back with H_PREV */int histno; /* current history number */int column; /* current column number */char *gethistn(),*gethists();static left(), right(), backspace(), putstr(); /* 971002 */void addhist(),addchar();/************************************************************** histinit() * initialize history mechanism*/histinit(){histno = 1;}/************************************************************** get_cmd(p) * get a line from stdin using lineedit and history*/get_cmd(p)char *p;{int c,oc,v,i;char *q,buf[20],*t;ioctl_cbreak(STDIN);*p = 0;histr = histi;column = 0;for (;;) { c = GETCHAR(); if (c == H_PREV) { if (histr != histo) { right(p,strlen(p)-column); backspace(column); histr = decmod(histr,HISTMAX); strcpy(p,hist[histr]); putstr(p); } } else if (c == H_NEXT) { if (histr != histi) { right(p,strlen(p)-column); backspace(column); histr = incmod(histr,HISTMAX); if (histr == histi) *p = 0; else strcpy(p,hist[histr]); putstr(p); } } else if (c == H_FORW) right(p,1); else if (c == H_BACK) left(1); else if (c == H_BEGIN) left(column); else if (c == H_END) right(p,strlen(&p[column])); else if (c == H_DELETE) { oc = column; strdchr(&p[column]); putstr(&p[column]); putstr(" "); left(strlen(&p[oc])+1); } else if (c == '\b') { left(1); oc = column; strdchr(&p[column]); putstr(&p[column]); putstr(" "); left(strlen(&p[oc])+1); } else if (c == '\n' || c == '\r') { putstr("\n"); break; } else addchar(p,c); }/* do C-shell history subs */if (q = findbang(p)) { getword(buf,q); strdchr(buf); /* delete the bang */ if (!strempty(buf)) { for (i=strlen(buf)+1;i>0;i--) strdchr(q); if (strequ(buf,"!")) { /* repeat last cmd */ stristr(q,hist[decmod(histi,HISTMAX)]); printf("%s\n",p); } else if (atob(&v,buf,10)) { /* hist# */ if (t = gethistn(v)) { stristr(q,t); printf("%s\n",p); } else printf("%s: Event not found.\n",buf); } else { /* hist string */ if (t = gethists(buf)) { stristr(q,t); printf("%s\n",p); } else printf("%s: Event not found.\n",buf); } } }addhist(p);ioctl_restore(STDIN);}/************************************************************** void addchar(p,c) * add char to line, updates 'column'*/void addchar(p,c)char *p;int c;{int oc;if (strlen(p) > LINESZ-40) return;oc = column;strichr(&p[column],c);putstr(&p[column]);left(strlen(&p[oc])-1);}Optdesc hi_opts[] = { {"[cnt]","display command history"}, {"cnt","list cnt lines of command history"}, {0}};/************************************************************** dohi() * The hi command*/dohi(ac,av)int ac;char *av[];{int i,n,siz,l;if(ac == 2) { if(!get_rsa(&siz,av[1])) return(1); }else { if (!atob(&siz,getMonEnv("moresz"),10)) { printf("%s: bad moresz value\n",getMonEnv("moresz")); return(1); } }ioctl_cbreak(STDIN);l = siz;i = decmod(histi,HISTMAX);n = histno-1;while (i != decmod(histo,HISTMAX)) { sprintf(prnbuf,"%5d %s",n,hist[i]); if (more(prnbuf,&l,(ac>1)?0:siz)) break; i = decmod(i,HISTMAX); n--; }return(0);}/************************************************************** static backspace(n) * distructive backspace, updates 'column'*/static backspace(n)int n;{for (;n>0 && column > 0;n--) { printf("\b \b"); column--; }}/************************************************************** static right(p,n) * move the cursor n places right, updates global 'column'*/static right(p,n)char *p;int n;{int len;len = strlen(p);for (;n>0 && column < len;n--) { putchar(p[column]); column++; }}/************************************************************** static left(n) * move the cursor n places left, updating global 'column'*/static left(n)int n;{for (;n>0 && column > 0;n--) { putchar('\b'); column--; }}/************************************************************** char *gethistn(n) * return ptr to hist entry n*/char *gethistn(n)int n;{int m,d;if (n < (histno - HISTMAX) || n > histno) return(0);m = histi;d = histno - n;for (;d>0;d--) m = decmod(m,HISTMAX);return(hist[m]);}/************************************************************** char *gethists(p) * use strbequ to return ptr to matching hist string*/char *gethists(p)char *p;{int i;i = decmod(histi,HISTMAX);while (i != decmod(histo,HISTMAX)) { if (hist[i] == 0) break; if (strbequ(hist[i],p)) return(hist[i]); i = decmod(i,HISTMAX); }return(0);}/************************************************************** void addhist(p) * add command line to history*/void addhist(p)char *p;{int i;/* discard empty lines */if (strempty(p)) return;/* discard dup lines if adjacent */i = decmod(histi,HISTMAX);if (hist[i] != 0) { if (strequ(p,hist[i])) return; }/* make space if input has reached output */if (incmod(histi,HISTMAX) == histo) { if (hist[histo] != 0) free(hist[histo]); hist[histo] = 0; histo = incmod(histo,HISTMAX); }hist[histi] = (char *)malloc(strlen(p)+1);if (hist[histi] == 0) { printf("addhist: out of memory\n"); return; }strcpy(hist[histi],p);histi = incmod(histi,HISTMAX);histno++;}/************************************************************** static putstr(p) * print string and update global 'column'*/static putstr(p)char *p;{int i;for (i=0;p[i] != 0;i++) { if (!noecho) putchar(p[i]); if (noecho && xvwmode && p[i] == '\n') putchar('\n'); if (p[i] == '\n') column = 0; else column++; }}/************************************************************** char *findbang(p)* Find the bang character (!). Skips stuff inside quotes.*/char *findbang(p)char *p;{int quote;for (;*p;p++) { if (*p == '\'' || *p == '"') { quote = *p; p++; while (*p && *p != quote) p++; } else if (*p == '!') return(p); }return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -