📄 cmdedit.c
字号:
} } /* Did we find exactly one match? */ if (!matches || num_matches > 1) { char *tmp1; beep(); if (!matches) return; /* not found */ /* sort */ qsort(matches, num_matches, sizeof(char *), match_compare); /* find minimal match */ tmp = bb_xstrdup(matches[0]); for (tmp1 = tmp; *tmp1; tmp1++) for (len_found = 1; len_found < num_matches; len_found++) if (matches[len_found][(tmp1 - tmp)] != *tmp1) { *tmp1 = 0; break; } if (*tmp == 0) { /* have unique */ free(tmp); return; } } else { /* one match */ tmp = matches[0]; /* for next completion current found */ *lastWasTab = FALSE; } len_found = strlen(tmp); /* have space to placed match? */ if ((len_found - strlen(matchBuf) + len) < BUFSIZ) { /* before word for match */ command_ps[cursor - recalc_pos] = 0; /* save tail line */ strcpy(matchBuf, command_ps + cursor); /* add match */ strcat(command_ps, tmp); /* add tail */ strcat(command_ps, matchBuf); /* back to begin word for match */ input_backward(recalc_pos); /* new pos */ recalc_pos = cursor + len_found; /* new len */ len = strlen(command_ps); /* write out the matched command */ redraw(cmdedit_y, len - recalc_pos); } if (tmp != matches[0]) free(tmp); } else { /* Ok -- the last char was a TAB. Since they * just hit TAB again, print a list of all the * available choices... */ if (matches && num_matches > 0) { int sav_cursor = cursor; /* change goto_new_line() */ /* Go to the next line */ goto_new_line(); showfiles(matches, num_matches); redraw(0, len - sav_cursor); } }}#endif /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */#if MAX_HISTORY >= 1static void get_previous_history(void){ if(command_ps[0] != 0 || history[cur_history] == 0) { free(history[cur_history]); history[cur_history] = bb_xstrdup(command_ps); } cur_history--;}static int get_next_history(void){ int ch = cur_history; if (ch < n_history) { get_previous_history(); /* save the current history line */ return (cur_history = ch+1); } else { beep(); return 0; }}#ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORYextern void load_history ( const char *fromfile ){ FILE *fp; int hi; /* cleanup old */ for(hi = n_history; hi > 0; ) { hi--; free ( history [hi] ); } if (( fp = fopen ( fromfile, "r" ))) { for ( hi = 0; hi < MAX_HISTORY; ) { char * hl = bb_get_chomped_line_from_file(fp); int l; if(!hl) break; l = strlen(hl); if(l >= BUFSIZ) hl[BUFSIZ-1] = 0; if(l == 0 || hl[0] == ' ') { free(hl); continue; } history [hi++] = hl; } fclose ( fp ); } cur_history = n_history = hi;}extern void save_history ( const char *tofile ){ FILE *fp = fopen ( tofile, "w" ); if ( fp ) { int i; for ( i = 0; i < n_history; i++ ) { fprintf(fp, "%s\n", history [i]); } fclose ( fp ); }}#endif#endifenum { ESC = 27, DEL = 127,};/* * This function is used to grab a character buffer * from the input file descriptor and allows you to * a string with full command editing (sort of like * a mini readline). * * The following standard commands are not implemented: * ESC-b -- Move back one word * ESC-f -- Move forward one word * ESC-d -- Delete back one word * ESC-h -- Delete forward one word * CTL-t -- Transpose two characters * * Furthermore, the "vi" command editing keys are not implemented. * */int cmdedit_read_input(char *prompt, char command[BUFSIZ]){ int break_out = 0; int lastWasTab = FALSE; unsigned char c = 0; /* prepare before init handlers */ cmdedit_y = 0; /* quasireal y, not true work if line > xt*yt */ len = 0; command_ps = command; getTermSettings(0, (void *) &initial_settings); memcpy(&new_settings, &initial_settings, sizeof(struct termios)); new_settings.c_lflag &= ~ICANON; /* unbuffered input */ /* Turn off echoing and CTRL-C, so we can trap it */ new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG); /* Hmm, in linux c_cc[] not parsed if set ~ICANON */ new_settings.c_cc[VMIN] = 1; new_settings.c_cc[VTIME] = 0; /* Turn off CTRL-C, so we can trap it */# ifndef _POSIX_VDISABLE# define _POSIX_VDISABLE '\0'# endif new_settings.c_cc[VINTR] = _POSIX_VDISABLE; command[0] = 0; setTermSettings(0, (void *) &new_settings); handlers_sets |= SET_RESET_TERM; /* Now initialize things */ cmdedit_init(); /* Print out the command prompt */ parse_prompt(prompt); while (1) { fflush(stdout); /* buffered out to fast */ if (safe_read(0, &c, 1) < 1) /* if we can't read input then exit */ goto prepare_to_die; switch (c) { case '\n': case '\r': /* Enter */ goto_new_line(); break_out = 1; break; case 1: /* Control-a -- Beginning of line */ input_backward(cursor); break; case 2: /* Control-b -- Move back one character */ input_backward(1); break; case 3: /* Control-c -- stop gathering input */ goto_new_line();#ifndef CONFIG_ASH command[0] = 0; len = 0; lastWasTab = FALSE; put_prompt();#else len = 0; break_out = -1; /* to control traps */#endif break; case 4: /* Control-d -- Delete one character, or exit * if the len=0 and no chars to delete */ if (len == 0) {prepare_to_die:#if !defined(CONFIG_ASH) printf("exit"); goto_new_line(); /* cmdedit_reset_term() called in atexit */ exit(EXIT_SUCCESS);#else /* to control stopped jobs */ len = break_out = -1; break;#endif } else { input_delete(); } break; case 5: /* Control-e -- End of line */ input_end(); break; case 6: /* Control-f -- Move forward one character */ input_forward(); break; case '\b': case DEL: /* Control-h and DEL */ input_backspace(); break; case '\t':#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION input_tab(&lastWasTab);#endif break; case 11: /* Control-k -- clear to end of line */ *(command + cursor) = 0; len = cursor; printf("\033[J"); break; case 12: /* Control-l -- clear screen */ printf("\033[H"); redraw(0, len-cursor); break;#if MAX_HISTORY >= 1 case 14: /* Control-n -- Get next command in history */ if (get_next_history()) goto rewrite_line; break; case 16: /* Control-p -- Get previous command from history */ if (cur_history > 0) { get_previous_history(); goto rewrite_line; } else { beep(); } break;#endif case 21: /* Control-U -- Clear line before cursor */ if (cursor) { strcpy(command, command + cursor); redraw(cmdedit_y, len -= cursor); } break; case 23: /* Control-W -- Remove the last word */ while (cursor > 0 && isspace(command[cursor-1])) input_backspace(); while (cursor > 0 &&!isspace(command[cursor-1])) input_backspace(); break; case ESC:{ /* escape sequence follows */ if (safe_read(0, &c, 1) < 1) goto prepare_to_die; /* different vt100 emulations */ if (c == '[' || c == 'O') { if (safe_read(0, &c, 1) < 1) goto prepare_to_die; } if (c >= '1' && c <= '9') { unsigned char dummy; if (safe_read(0, &dummy, 1) < 1) goto prepare_to_die; if(dummy != '~') c = 0; } switch (c) {#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION case '\t': /* Alt-Tab */ input_tab(&lastWasTab); break;#endif#if MAX_HISTORY >= 1 case 'A': /* Up Arrow -- Get previous command from history */ if (cur_history > 0) { get_previous_history(); goto rewrite_line; } else { beep(); } break; case 'B': /* Down Arrow -- Get next command in history */ if (!get_next_history()) break; /* Rewrite the line with the selected history item */rewrite_line: /* change command */ len = strlen(strcpy(command, history[cur_history])); /* redraw and go to end line */ redraw(cmdedit_y, 0); break;#endif case 'C': /* Right Arrow -- Move forward one character */ input_forward(); break; case 'D': /* Left Arrow -- Move back one character */ input_backward(1); break; case '3': /* Delete */ input_delete(); break; case '1': case 'H': /* <Home> */ input_backward(cursor); break; case '4': case 'F': /* <End> */ input_end(); break; default: c = 0; beep(); } break; } default: /* If it's regular input, do the normal thing */#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT /* Control-V -- Add non-printable symbol */ if (c == 22) { if (safe_read(0, &c, 1) < 1) goto prepare_to_die; if (c == 0) { beep(); break; } } else#endif if (!Isprint(c)) /* Skip non-printable characters */ break; if (len >= (BUFSIZ - 2)) /* Need to leave space for enter */ break; len++; if (cursor == (len - 1)) { /* Append if at the end of the line */ *(command + cursor) = c; *(command + cursor + 1) = 0; cmdedit_set_out_char(0); } else { /* Insert otherwise */ int sc = cursor; memmove(command + sc + 1, command + sc, len - sc); *(command + sc) = c; sc++; /* rewrite from cursor */ input_end(); /* to prev x pos + 1 */ input_backward(cursor - sc); } break; } if (break_out) /* Enter is the command terminator, no more input. */ break; if (c != '\t') lastWasTab = FALSE; } setTermSettings(0, (void *) &initial_settings); handlers_sets &= ~SET_RESET_TERM;#if MAX_HISTORY >= 1 /* Handle command history log */ /* cleanup may be saved current command line */ if (len> 0) { /* no put empty line */ int i = n_history; free(history[MAX_HISTORY]); history[MAX_HISTORY] = 0; /* After max history, remove the oldest command */ if (i >= MAX_HISTORY) { free(history[0]); for(i = 0; i < (MAX_HISTORY-1); i++) history[i] = history[i+1]; } history[i++] = bb_xstrdup(command); cur_history = i; n_history = i;#if defined(CONFIG_FEATURE_SH_FANCY_PROMPT) num_ok_lines++;#endif }#else /* MAX_HISTORY < 1 */#if defined(CONFIG_FEATURE_SH_FANCY_PROMPT) if (len > 0) { /* no put empty line */ num_ok_lines++; }#endif#endif /* MAX_HISTORY >= 1 */ if (break_out > 0) { command[len++] = '\n'; /* set '\n' */ command[len] = 0; }#if defined(CONFIG_FEATURE_CLEAN_UP) && defined(CONFIG_FEATURE_COMMAND_TAB_COMPLETION) input_tab(0); /* strong free */#endif#if defined(CONFIG_FEATURE_SH_FANCY_PROMPT) free(cmdedit_prompt);#endif cmdedit_reset_term(); return len;}#endif /* CONFIG_FEATURE_COMMAND_EDITING */#ifdef TESTconst char *bb_applet_name = "debug stuff usage";#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT#include <locale.h>#endifint main(int argc, char **argv){ char buff[BUFSIZ]; char *prompt =#if defined(CONFIG_FEATURE_SH_FANCY_PROMPT) "\\[\\033[32;1m\\]\\u@\\[\\x1b[33;1m\\]\\h:\\\[\\033[34;1m\\]\\w\\[\\033[35;1m\\] \\\!\\[\\e[36;1m\\]\\$ \\[\\E[0m\\]";#else "% ";#endif#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT setlocale(LC_ALL, "");#endif while(1) { int l; l = cmdedit_read_input(prompt, buff); if(l > 0 && buff[l-1] == '\n') { buff[l-1] = 0; printf("*** cmdedit_read_input() returned line =%s=\n", buff); } else { break; } } printf("*** cmdedit_read_input() detect ^D\n"); return 0;}#endif /* TEST */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -