📄 lineedit.c
字号:
/* lineedit.c: * This code supports the monitor's command line editing capability and * command history log. The command line editing is a subset of KSH's * vi-mode editing. * * This code includes a few suggestions/fixed from Martin Carroll. * * General notice: * This code is part of a boot-monitor package developed as a generic base * platform for embedded system designs. As such, it is likely to be * distributed to various projects beyond the control of the original * author. Please notify the author of any enhancements made or bugs found * so that all may benefit from the changes. In addition, notification back * to the author will allow the new user to pick up changes that may have * been made by other users after this version of the code was distributed. * * Note1: the majority of this code was edited with 4-space tabs. * Note2: as more and more contributions are accepted, the term "author" * is becoming a mis-representation of credit. * * Original author: Ed Sutter * Email: esutter@lucent.com * Phone: 908-582-2351 */#include "config.h"#if INCLUDE_LINEEDIT#include "ctype.h"#include "genlib.h"#include "stddefs.h"#include "cli.h"#define MAXLINESIZE CMDLINESIZE#define HISTLINESIZE MAXLINESIZE#define HMAX 16#define ESC 0x1B#define CTLC 0x03#define BACKSPACE 0x08#define CMD 100#define EDIT 101#define EDIT1 102#define INSERT 103#define NEXT 104#define PREV 105#define NEITHER 106#define EDITFILELINE 1#define EDITCMDLINE 2static int stridx; /* store index */static int shwidx; /* show index */static int srchidx; /* search index */static int lastsize; /* size of last command */static char curChar; /* latest input character */static char *curPos; /* current position on command line */static char *startOfLine; /* start of command line */static int lineLen; /* length of line */static int lMode; /* present mode of entry */static char cmdhistory[HMAX+1][HISTLINESIZE];/* array for command history */static void ledit(), lcmd(), showprev(), ldelete(), linsert(), lerase();static void gotobegin(), gotoend(), backup(), shownext(), linsertbs();static void delete_to_end(), delete_something();static void historysearch(void), ledit1(void);static char *lineeditor();/* line_edit() & file_line_edit(): * These two functions are simply front-ends to the lineeditor() * function. The line_edit() function is called by the command line * interface and file_line_edit() is called by the flash file editor * to provide a convenient single line editor when modifying a file. */char *line_edit(char *line_to_edit){ return(lineeditor(line_to_edit,EDITCMDLINE));}char *file_line_edit(char *line_to_edit){ return(lineeditor(line_to_edit,EDITFILELINE));}/* lineeditor(): * This function is fed a pointer to a command line. * It sets up a command line editor for that particular line. * The line is modified in place so, if successful, the function * returns the same pointer but with its contents modified based * on the editor commands executed. * If failure, the function returns (char *)0. */static char *lineeditor(char *line_to_edit,int type){ lMode = CMD; startOfLine = line_to_edit; curPos = line_to_edit; while(*curPos != ESC) curPos++; *curPos = 0; /* Remove the escape character from the line */ lineLen = (ulong)curPos - (ulong)startOfLine; if (lineLen > 0) { curPos--; puts(" \b\b"); } else puts(" \b"); lastsize = 0; shwidx = stridx; srchidx = stridx; while(1) { curChar = getchar(); switch(curChar) { case ESC: if (lMode != CMD) { lMode = CMD; continue; } else { putchar('\n'); return((char *)0); } case '\r': case '\n': putchar('\n'); if (lineLen == 0) return((char *)0); *(char *)(startOfLine + lineLen) = '\0'; return(startOfLine); case CTLC: putchar('\n'); *startOfLine = 0; lineLen = 0; return((char *)0); } switch(lMode) { case CMD: lcmd(type); if (lMode == NEITHER) return((char *)0); break; case INSERT: linsert(); break; case EDIT1: ledit1(); break; case EDIT: ledit(); break; } if (lineLen >= MAXLINESIZE) { printf("line overflow\n"); return((char *)0); } }}static voidledit(void){ int len; if (curChar == '\b') curPos--; else *curPos++ = curChar; len = (curPos - startOfLine); /* line may get longer than original */ if (len > lineLen) lineLen = len; putchar(curChar); switch(lMode) { case EDIT1: lMode = CMD; break; }}static voidledit1(void){ *curPos = curChar; putchar(curChar); putchar('\b'); lMode = CMD;}static voidlcmd(int type){ switch(curChar) { case '0': gotobegin(); return; case '$': gotoend(); return; case 'A': gotoend(); putchar(*curPos++); lMode = INSERT; return; case 'a': if (curPos != startOfLine) putchar(*curPos++); lMode = INSERT; return; case 'i': lMode = INSERT; return; case 'D': delete_to_end(); return; case 'd': delete_something(); return; case 'c': delete_something(); lMode = INSERT; return; case 'x': ldelete(); return; case ' ': case 'l': if (curPos < startOfLine+lineLen-1) { putchar(*curPos); curPos++; } return; case '\b': case 'h': if (curPos > startOfLine) { putchar('\b'); curPos--; } return; case 'r': lMode = EDIT1; return; case 'R': lMode = EDIT; return; } /* The remaining commands should only be processed if we are editing * a command line. For editing a line in a file, the commands that * relate to command line history are not applicable and should be * blocked. */ if (type == EDITCMDLINE) { switch(curChar) { case '/': putchar('/'); historysearch(); return; case '+': case 'j': shownext(); return; case '-': case 'k': showprev(); return; } } /* Beep to indicate an error. */ putchar(0x07);}static voidlinsert(){ char string[MAXLINESIZE]; if (curChar == BACKSPACE) { linsertbs(); return; } if (!isprint(curChar)) return; putchar(curChar); puts(curPos); backup((int)strlen(curPos)); strncpy(string,curPos,MAXLINESIZE-1); *curPos++ = curChar; strcpy(curPos,string); lineLen++;}/* linsertbs(): * Handle the backspace when in 'INSERT' mode. */static voidlinsertbs(){ char *eol, *now; int cnt; if (curPos == startOfLine) return; backup(1); curPos--; cnt = 0; eol = startOfLine + lineLen - 1; now = curPos; while(curPos <= eol) { *curPos = *(curPos+1); curPos++; cnt++; } putbytes(now,cnt-1); putchar(' '); backup((int)cnt); curPos = now; lineLen--;}static voiddelete_something(){ char *eol, *now, C, *new; int cnt; C = getchar(); if (C == 'w') { /* word */ now = curPos; eol = startOfLine + lineLen -1; while (curPos <= eol) { if (*curPos == ' ') break; curPos++; } if (curPos < eol) { new = curPos; strcpy(now,new); cnt = strlen(now); putbytes(now,cnt); curPos = now + cnt; while(curPos <= eol) { putchar(' '); curPos++; cnt++; } backup(cnt); } else { curPos = now; delete_to_end(); return; } curPos = now; lineLen = strlen(startOfLine); } else if (C == 'f') { /* find */ C = getchar(); now = curPos; eol = startOfLine + lineLen -1; while (curPos <= eol) { if (*curPos == C) break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -