📄 shell.c
字号:
cmd = cmd_list[i];
if( strstr( cmd->name, name ) == cmd->name )
{
/* Found match */
if( strcmp( cmd->name, name ) == 0 )
{
/* Exact match */
if(len)
*len = strlen( cmd->name );
cmd_found = cmd;
break;
}
if( cmd_found )
{
/* Got one already */
UINT32 t;
/* Determine the common characters */
for( t=0; cmd_found->name[t] == cmd->name[t]; t++ );
if(len)
*len = MIN(t, *len);
if(ambivalent)
*ambivalent = TRUE;
}
else
{
if( strlen(name) > 1 ) /* Min 2 char for autocompletion */
{
cmd_found = cmd;
if(len)
*len = strlen(cmd->name);
}
}
}
}
/* Hack in order to handle case insensitivity of
* Microsoft SDB commands.
*/
if( strlen( name ) == 1 )
{
*name = ch;
}
return cmd_found;
}
/************************************************************************
*
* shell_print_dot
* Description :
* -------------
*
* Print dot on screen
*
* Return values :
* ---------------
*
* void
*
************************************************************************/
bool
shell_print_dot(
UINT32 *count )
{
return SHELL_PUTS( ( (++(*count) % 40) == 0 ) ? ".\n" : "." );
}
/************************************************************************
*
* shell_setmore
* Description :
* -------------
*
* Enable/disable 'more' control from shell_puts and shell_putc
*
* Return values :
* ---------------
*
* None
*
************************************************************************/
void
shell_setmore(
bool enable_more )
{
more = enable_more;
linenum = 0;
indent_prev = 0;
}
/************************************************************************
*
* shell_puts
* Description :
* -------------
*
* Print string to stdout
*
* Return values :
* ---------------
*
* TRUE -> Ctrl^C was pressed
*
************************************************************************/
bool
shell_puts(
char *string,
UINT32 indent )
{
UINT32 count, len;
UINT32 first_newline;
bool nl;
char ch;
bool rc;
UINT32 linemax, linewidth;
#if 0
linemax = getenv( "linemax" );
linewidth = getenv( "linewidth" );
#else
linemax = MON_DEF_LINEMAX - 1; /* Space for 'Press Ctrl-c ... message */
linewidth = MON_DEF_LINEWIDTH;
#endif
if( linewidth <= indent ) /* This is an error */
return TRUE;
while( *string != '\0' )
{
if( linenum == linemax )
{
/* Print 'press any key...' message */
PUTS( DEFAULT_PORT, continue_msg );
while( !GETCHAR( DEFAULT_PORT, &ch ) );
/* Remove 'press any key...' message */
len = strlen( continue_msg );
moveleft( len );
for(count=0; count<len; count++)
{
PUTCHAR( DEFAULT_PORT, ' ' );
}
moveleft( len );
if( ch == CTRL_C )
{
linenum = 1; /* Keep last line */
ctrl_c_flag = TRUE;
return TRUE;
}
else
{
linenum =
( (ch == CR) || (ch == LF) ) ?
linemax - 1 :
1; /* Keep last line */
indent_prev = 0;
}
}
/* Indent */
if( indent )
{
if (indent < indent_prev)
indent = indent_prev;
count = indent - indent_prev;
indent_prev += count;
}
else
count = 0;
while(count--)
{
PUTCHAR( DEFAULT_PORT, ' ' );
}
first_newline = strcspn( string, "\n" );
count = ( first_newline + indent <= linewidth ) ?
first_newline + 1 :
linewidth - indent;
while( count-- && (*string != '\0') )
{
nl = (*string == '\n');
PUTCHAR( DEFAULT_PORT, *(string++) );
indent_prev++;
if(nl)
{
indent_prev = 0;
if( more )
linenum++;
}
}
if( (*string != '\0') && (!nl) )
{
PUTCHAR( DEFAULT_PORT, '\n' );
indent_prev = 0;
if( more )
linenum++;
}
}
rc = GETCHAR_CTRLC( DEFAULT_PORT );
if( rc )
ctrl_c_flag = TRUE;
return rc;
}
/************************************************************************
*
* shell_putc
* Description :
* -------------
*
* Print char to stdout
*
* Return values :
* ---------------
*
* TRUE -> Ctrl^C was pressed
*
************************************************************************/
bool
shell_putc(
char ch,
UINT32 indent )
{
char s[2];
s[0] = ch;
s[1] = '\0';
return shell_puts( s, indent );
}
/************************************************************************
*
* shell_get_line
* Description :
* -------------
*
* Get command line with handling of special characters
*
* Return values :
* ---------------
*
* FALSE -> Ctrl^C was pressed
*
************************************************************************/
bool
shell_get_line(
char *line, /* Line buffer */
UINT32 maxchars, /* Max number of chars not counting terminating '\0' */
bool first_line, /* TRUE -> First line (ie not a \CR continuation) */
bool full, /* TRUE -> Handle command stack and autocompletion */
t_shell_line_buf *buf ) /* Command stack (only used if full == TRUE) */
{
UINT32 cursor, eol;
char ch;
UINT32 slash_count;
bool line_shift, line_done;
UINT32 len;
t_cmd *cmd;
UINT32 current_from_buf;
if( start )
{
/* Use $start as the first command line */
strcpy( line, "$start" );
return TRUE;
}
*line = '\0';
cursor = 0;
eol = 0;
line_done = FALSE;
line_shift = FALSE;
if( full && !buf ) /* Should not happen */
return FALSE;
if( full )
current_from_buf = buf->free;
while( !line_done && !line_shift )
{
receive( &ch );
switch( ch )
{
case CR :
case LF :
/* End line unless last characters were an
* odd number of '\' chars, in which
* case input continues on new line.
*/
for( slash_count = 0;
(eol - slash_count > 0) &&
(line[eol - slash_count - 1] == '\\');
slash_count++ )
{
;
}
if( (slash_count % 2) == 1 )
line_shift = TRUE;
else
line_done = TRUE;
break;
case CTRL_C :
/* Cancel line */
return FALSE;
case CTRL_A :
/* Move cursor to the far left */
moveleft( cursor );
cursor = 0;
break;
case CTRL_E :
/* Move cursor to the far right */
moveright( line, cursor, eol - cursor );
cursor = eol;
break;
case CTRL_B :
/* ^B or left arrow : Move cursor left */
if( cursor > 0 )
{
moveleft(1);
cursor--;
}
break;
case CTRL_F :
/* ^F or right arrow : Move cursor right */
if( cursor < eol )
{
moveright(line, cursor, 1);
cursor++;
}
break;
case CTRL_D :
/* Delete character after cursor */
if( cursor < eol )
{
delete_char( line, &cursor, &eol );
}
break;
case CTRL_H : /* Same as DEL */
case DEL :
/* Delete character at cursor */
if( cursor > 0 )
{
moveleft(1);
cursor--;
delete_char(line, &cursor, &eol );
}
break;
case CTRL_K :
/* Delete everything after cursor */
delete_from_cursor(cursor, &eol);
line[eol] = '\0';
break;
case CTRL_U :
/* Delete line */
delete_line( &cursor, &eol );
line[eol] = '\0';
break;
case CTRL_P :
/* Previous command in command stack (first line only) */
if( full && first_line &&
get_previous( buf, ¤t_from_buf, line ) )
{
/* Delete line */
delete_line( &cursor, &eol );
/* Update settings and print line */
cursor = eol = strlen( line );
printf( line );
}
break;
case CTRL_N :
/* Next command in command stack (first line only) */
if( full && first_line &&
get_next( buf, ¤t_from_buf, line ) )
{
/* Delete line */
delete_line( &cursor, &eol );
/* Update settings and print line */
cursor = eol = strlen( line );
printf( line );
}
break;
case TAB :
/* Command line completion (first line only) */
if( full && first_line )
{
cmd = shell_lookup_cmd( line, NULL, &len,
command_list, command_count );
if( cmd )
{
/* Delete old line */
delete_line( &cursor, &eol );
/* Insert new line */
strncpy( line, cmd->name, len );
line[len] = '\0';
cursor = len;
eol = len;
/* Print line */
printf( line );
}
}
break;
default :
if( isprint(ch) && (eol < MIN(maxchars, max_line_len )) )
insert_char( line, &cursor, &eol, ch );
break;
}
}
if( line_shift )
{
print_prompt( PROMPT_TARGET_TERMINAL, PROMPT_TEXT_CONT );
eol--; /* Remove '\' */
return shell_get_line( &line[eol], maxchars - eol, FALSE, full, buf );
}
return TRUE;
}
/************************************************************************
* Implementation : Static functions
************************************************************************/
/************************************************************************
* print_prompt
************************************************************************/
static void
print_prompt(
UINT32 target,
UINT32 text )
{
char *s;
if( text == PROMPT_TEXT_ENV )
{
if( !env_get( "prompt", &s, NULL, 0 ) )
s = DEFAULT_PROMPT;
}
else
{
s = "\n?";
}
if( target == PROMPT_TARGET_DISPLAY )
{
DISP_STR( s );
}
else
{
printf( s );
printf( (text == PROMPT_TEXT_ENV) ? "> " : " " );
max_line_len = SHELL_MAX_LINE_LEN - strlen(s) - 2;
}
}
/************************************************************************
* receive
************************************************************************/
static void
receive(
char *ch )
{
t_rcv_state state = STATE_RCV_START;
while( state != STATE_RCV_DONE )
{
while( !GETCHAR( DEFAULT_PORT, ch ) );
switch( state )
{
case STATE_RCV_START :
if ( *ch == ESC ) state = STATE_RCV_ESC;
else if( *(unsigned char *)ch == CSI ) state = STATE_RCV_CSI;
else state = STATE_RCV_DONE;
break;
case STATE_RCV_ESC :
if( *ch == '[' ) state = STATE_RCV_BRACKET;
else state = STATE_RCV_START;
break;
case STATE_RCV_CSI :
case STATE_RCV_BRACKET :
state = STATE_RCV_DONE;
switch( *ch )
{
case 'A':
*ch = CTRL_P; break;
case 'B':
*ch = CTRL_N; break;
case 'C':
*ch = CTRL_F; break;
case 'D':
*ch = CTRL_B; break;
default :
state = STATE_RCV_START;
}
break;
default :
break;
}
}
}
/************************************************************************
* moveleft
************************************************************************/
static void
moveleft(
UINT32 count )
{
while( count-- )
{
PUTCHAR( DEFAULT_PORT, '\b' );
}
}
/************************************************************************
* moveright
************************************************************************/
static void
moveright(
char *line,
UINT32 cursor,
UINT32 count )
{
while( count-- )
{
PUTCHAR( DEFAULT_PORT, line[cursor++] );
}
}
/************************************************************************
* get_previous
************************************************************************/
static bool
get_previous(
t_shell_line_buf *buf,
UINT32 *current_from_buf,
char *line )
{
if( buf->first == BUFFER_NU )
return FALSE;
if( *current_from_buf == buf->first )
return FALSE;
/* Move backward */
DECWRAP(*current_from_buf, BUFFERSIZE);
do
{
DECWRAP(*current_from_buf, BUFFERSIZE);
}
while( (buf->data[*current_from_buf] != '\0') &&
(*current_from_buf != buf->first) );
if( *current_from_buf != buf->first )
{
/* One too far, so move increase by 1 */
INCWRAP(*current_from_buf, BUFFERSIZE);
}
copybuf( line, buf->data, *current_from_buf, BUFFERSIZE );
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -