📄 readline.c
字号:
/*
===============================================================================
| COPYRIGHT (C) 2003-2007 RSGuru, All rights reserved.
| SUMMARY:
| General facility for reading lines of input.
|
|
| LICENSE INFORMATION
| RS-RTOS is free software; you can redistribute it and/or modify it under
| terms of the GNU General Public License as published by the
| Free Software Foundation; either version 2, or (at your option) any
| later version.
|
| RS-RTOS is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
| General Public License for more details.
|
| You should have received a copy of the GNU General Public License
| along with RS-RTOS; see file COPYING. If not, write to the Free Software
| Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
| As a special exception, including RS-RTOS header files in a file,
| instantiating RS-RTOS generics or templates, or linking other files
| with RS-RTOS objects to produce an executable application, does not
| by itself cause the resulting executable application to be covered
| by the GNU General Public License. This exception does not
| however invalidate any other reasons why the executable file might be
| covered by the GNU Public License.
|
|
| DESCRIPTION:
| See http://www.RS-RTOS.org for documentation, latest information, license
| and contact details.
| email:ruanhaishen@gmail.com
|
|
| AUTHOR & LOG:
| Haishen Ruan <ruanhaishen@gmail.com>:
| 31 Aug 2006, Created it.
|
|
=============================================================================*/
/*===========================================================================*/
#include "inc/kapi.h"
#include "lib/inc/readline.h"
/* redefine some useful and maybe missing utilities to avoid conflicts */
#define puts (rl->io.puts)
#define putc(c) \
do { \
if (ISALPHA(c)) rl->io.putc(c); \
} while (0)
#define getc (rl->io.getc)
#define echo (rl->options & RS_OPT_ECHO)
#define LOOP_INIT(elm) \
((elm)->next = (elm));
#define LOOP_INSERT(looplm, elm) \
do { \
(elm)->next = (looplm)->next; \
(looplm)->next = (elm); \
} while (0)
#define LOOP_NEXT(elm) \
((elm)->next);
#define LOOP_DOEACH(var, looplm) \
(var) = (looplm); \
do {
#define LOOP_DOEND(var, looplm) \
(var) = LOOP_NEXT(var); \
} while ((var) != (looplm));
#ifndef whitespace
#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
#endif
#ifndef wordend
#define wordend(c) (((c) == ' ') || ((c) == '\0'))
#endif
#ifndef trim_left
#define trim_left(_line) \
do { \
while (whitespace(*(_line))) (_line)++; \
} while (0)
#endif
enum {
RL_INCMD_NULL,
RL_INCMD_HELP,
RL_INCMD_BACK,
RL_INCMD_TOP,
RL_INCMD_QUIT
};
enum {
RL_OK,
RL_AMBIGUITY,
RL_MATCH_NULL,
RL_MATCH_ENTIRE,
RL_MATCH_PART
};
#define E 0x00 /* Even parity. */
#define O 0x80 /* Odd parity. */
#define PARITY(c) (char_type[c] & O)
#define ALPHA 0x40 /* Alpha or underscore. */
#define ISALPHA(c) 1//(char_type[c] & ALPHA)
#define CCLASSMASK 0x3f
#define CCLASS(c) (char_type[c] & CCLASSMASK)
#define BS BACKSPACE
#define CC CONTROL
#define CR RETURN
#define NA ORDINARY | ALPHA
#define NL NEWLINE
#define NO ORDINARY
#define TB TAB
#define VT VTAB
static u_char const char_type[] = {
E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul - bel */
O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */
O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */
E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */
O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */
E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */
E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */
O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */
O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */
E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */
E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */
O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */
E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */
O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */
O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */
E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */
/*
* Meta chars; should be settable per character set;
* for now, treat them all as normal characters.
*/
NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA,
};
#undef BS
#undef CC
#undef CR
#undef NA
#undef NL
#undef NO
#undef TB
#undef VT
/*
* execute the given command by calling callback with appropriate
* arguments */
static void readline_exec(
readline_t __p_* rl,
readline_cmd_t __p_* cmd,
char __p_* line
)
{
char *argv[RSI_MAX_ARGS];
int argc = 0;
/* Cut into arguments */
argv[argc++] = cmd->name;
while (*line && argc < RSI_MAX_ARGS - 1) {
trim_left(line);
if (*line == 0)
break;
argv[argc++] = line;
while (*line && !whitespace(*line))
line++;
if (*line == 0)
break;
*line++ = 0;
}
argv[argc] = (char*)rl;
/* Call command function if present. */
if (cmd->handle) {
cmd->handle(argc, &argv[0]);
}
}
/* start a new line */
static void readline_newline(readline_t __p_* rl)
{
readline_cmd_t __p_* cmd;
/* Display start of new line. */
puts(rl->prompt);
cmd = rl->root_cmd;
while (cmd->parent != NULL)
cmd = cmd->parent;
while (cmd != rl->root_cmd) {
puts(cmd->name);
putc('>');
cmd = cmd->child;
}
rl->index = 0;
putc(' ');
}
static int readline_match(char __p_* name, char __p_* __p_* line)
{
char __p_* _line;
int match;
_line = *line;
trim_left(_line);
if (*_line != '\0') {
while (*name && *name == *_line) {
name++;
_line++;
}
if (*_line == 0 ||
whitespace(*_line))
{
if (*name == 0)
match = RL_MATCH_ENTIRE;
else
match = RL_MATCH_PART;
} else {
match = RL_MATCH_NULL;
}
}
trim_left(_line);
*line = _line;
return match;
}
static int readline_lookup(
readline_cmd_t __p_* __p_* cmd,
char __p_* __p_* line
)
{
readline_cmd_t __p_* _cmd;
readline_cmd_t __p_* _found;
char __p_* _line;
int match;
_found = NULL;
LOOP_DOEACH(_cmd, *cmd)
_line = *line;
match = readline_match(_cmd->name, &_line);
if (match == RL_MATCH_ENTIRE) {
/* match */
_found = _cmd;
break;
}
/* See if match partially. */
else if (match == RL_MATCH_PART) {
if (_found != NULL)
return RL_AMBIGUITY;
/* save command */
_found = _cmd;
}
LOOP_DOEND(_cmd, *cmd)
if (_found != NULL) {
*cmd = _found;
}
else {
/* Not match. */
*cmd = NULL;
return RL_MATCH_NULL;
}
*line = _line;
return RL_OK;
}
/* Display command help info. */
void readline_help(
readline_t __p_* rl,
readline_cmd_t __p_* cmd,
unsigned int space)
{
unsigned int i;
/* Show command name. */
puts(cmd->name);
for (i = strlen(cmd->name); i < space; i++)
putc(' ');
puts(": ");
if(cmd->help)
puts(cmd->help);
else
puts("<No help available>");
putc('\n');
}
/* Display all loop commands help info. */
void readline_dohelp(readline_t __p_* rl, readline_cmd_t __p_* cmd)
{
readline_cmd_t __p_* _cmd;
unsigned int len = 0;
/* Find the maximum length. */
LOOP_DOEACH(_cmd, cmd)
if (len < strlen(_cmd->name))
len = strlen(_cmd->name);
LOOP_DOEND(_cmd, cmd)
len += 2;
/* Display command help string. */
LOOP_DOEACH(_cmd, cmd)
readline_help(rl, _cmd, len);
LOOP_DOEND(_cmd, cmd)
}
/* Function inner command help info. */
void readline_inhelp(readline_t __p_* rl)
{
puts("? Display help on given or available commands.\n");
puts(". Goes back one command level.\n");
puts(".. Goes back top command level.\n");
puts("<TAB> Auto-completion.\n");
puts("<CR> Execute command line.\n");
puts("CTRL-P Recall previous input line.\n");
puts("CTRL-N Recall next input line.\n");
puts("quit Quit command.\n");
}
static int readline_search(
readline_cmd_t __p_* __p_* cmd,
char __p_* __p_* line
)
{
readline_cmd_t __p_* _cmd;
char __p_* _line;
int match;
_cmd = *cmd;
_line = *line;
for (;;) {
match = readline_lookup(&_cmd, &_line);
/* See if command found. */
if (match != RL_OK) {
/* Not match. */
break;
}
/* Since.
* command has found. */
if (*_line == '\0' ||
(*_line == '?' &&
wordend(*(_line+1))))
{
break;
}
if (_cmd->child == NULL)
break;
_cmd = _cmd->child;
}
*cmd = _cmd;
*line = _line;
return match;
}
static int readline_incmd(char __p_* line)
{
int incmd = RL_INCMD_NULL;
if (line[0] == '?')
{
line += 1;
incmd = RL_INCMD_HELP;
}
else if (line[0] == '.' &&
line[1] == '.')
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -