2016-11-21 10:23:27 +02:00
|
|
|
/*
|
|
|
|
Author: Samoylov Eugene aka Helius (ghelius@gmail.com)
|
|
|
|
BUGS and TODO:
|
|
|
|
-- add echo_off feature
|
|
|
|
-- rewrite history for use more than 256 byte buffer
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "microrl.h"
|
|
|
|
#ifdef _USE_LIBC_STDIO
|
|
|
|
#include <stdio.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//#define DBG(...) fprintf(stderr, "\033[33m");fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\033[0m");
|
|
|
|
|
|
|
|
char * prompt_default = _PROMPT_DEFAULT;
|
|
|
|
|
|
|
|
#ifdef _USE_HISTORY
|
|
|
|
|
|
|
|
#ifdef _HISTORY_DEBUG
|
|
|
|
//*****************************************************************************
|
|
|
|
// print buffer content on screen
|
|
|
|
static void print_hist (ring_history_t * pThis)
|
|
|
|
{
|
|
|
|
printf ("\n");
|
|
|
|
for (int i = 0; i < _RING_HISTORY_LEN; i++) {
|
|
|
|
if (i == pThis->begin)
|
|
|
|
printf ("b");
|
|
|
|
else
|
|
|
|
printf (" ");
|
|
|
|
}
|
|
|
|
printf ("\n");
|
|
|
|
for (int i = 0; i < _RING_HISTORY_LEN; i++) {
|
|
|
|
if (isalpha(pThis->ring_buf[i]))
|
|
|
|
printf ("%c", pThis->ring_buf[i]);
|
|
|
|
else
|
|
|
|
printf ("%d", pThis->ring_buf[i]);
|
|
|
|
}
|
|
|
|
printf ("\n");
|
|
|
|
for (int i = 0; i < _RING_HISTORY_LEN; i++) {
|
|
|
|
if (i == pThis->end)
|
|
|
|
printf ("e");
|
|
|
|
else
|
|
|
|
printf (" ");
|
|
|
|
}
|
|
|
|
printf ("\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
// remove older message from ring buffer
|
|
|
|
static void hist_erase_older (ring_history_t * pThis)
|
|
|
|
{
|
|
|
|
int new_pos = pThis->begin + pThis->ring_buf [pThis->begin] + 1;
|
|
|
|
if (new_pos >= _RING_HISTORY_LEN)
|
|
|
|
new_pos = new_pos - _RING_HISTORY_LEN;
|
|
|
|
|
|
|
|
pThis->begin = new_pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
// check space for new line, remove older while not space
|
|
|
|
static int hist_is_space_for_new (ring_history_t * pThis, int len)
|
|
|
|
{
|
|
|
|
if (pThis->ring_buf [pThis->begin] == 0)
|
|
|
|
return true;
|
|
|
|
if (pThis->end >= pThis->begin) {
|
|
|
|
if (_RING_HISTORY_LEN - pThis->end + pThis->begin - 1 > len)
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
if (pThis->begin - pThis->end - 1> len)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
// put line to ring buffer
|
|
|
|
static void hist_save_line (ring_history_t * pThis, char * line, int len)
|
|
|
|
{
|
|
|
|
if (len > _RING_HISTORY_LEN - 2)
|
|
|
|
return;
|
|
|
|
while (!hist_is_space_for_new (pThis, len)) {
|
|
|
|
hist_erase_older (pThis);
|
|
|
|
}
|
|
|
|
// if it's first line
|
|
|
|
if (pThis->ring_buf [pThis->begin] == 0)
|
|
|
|
pThis->ring_buf [pThis->begin] = len;
|
|
|
|
|
|
|
|
// store line
|
|
|
|
if (len < _RING_HISTORY_LEN-pThis->end-1)
|
|
|
|
memcpy (pThis->ring_buf + pThis->end + 1, line, len);
|
|
|
|
else {
|
|
|
|
int part_len = _RING_HISTORY_LEN-pThis->end-1;
|
|
|
|
memcpy (pThis->ring_buf + pThis->end + 1, line, part_len);
|
|
|
|
memcpy (pThis->ring_buf, line + part_len, len - part_len);
|
|
|
|
}
|
|
|
|
pThis->ring_buf [pThis->end] = len;
|
|
|
|
pThis->end = pThis->end + len + 1;
|
|
|
|
if (pThis->end >= _RING_HISTORY_LEN)
|
|
|
|
pThis->end -= _RING_HISTORY_LEN;
|
|
|
|
pThis->ring_buf [pThis->end] = 0;
|
|
|
|
pThis->cur = 0;
|
|
|
|
#ifdef _HISTORY_DEBUG
|
|
|
|
print_hist (pThis);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
// copy saved line to 'line' and return size of line
|
|
|
|
static int hist_restore_line (ring_history_t * pThis, char * line, int dir)
|
|
|
|
{
|
|
|
|
int cnt = 0;
|
|
|
|
// count history record
|
|
|
|
int header = pThis->begin;
|
|
|
|
while (pThis->ring_buf [header] != 0) {
|
|
|
|
header += pThis->ring_buf [header] + 1;
|
|
|
|
if (header >= _RING_HISTORY_LEN)
|
|
|
|
header -= _RING_HISTORY_LEN;
|
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dir == _HIST_UP) {
|
|
|
|
if (cnt >= pThis->cur) {
|
|
|
|
int header = pThis->begin;
|
|
|
|
int j = 0;
|
|
|
|
// found record for 'pThis->cur' index
|
|
|
|
while ((pThis->ring_buf [header] != 0) && (cnt - j -1 != pThis->cur)) {
|
|
|
|
header += pThis->ring_buf [header] + 1;
|
|
|
|
if (header >= _RING_HISTORY_LEN)
|
|
|
|
header -= _RING_HISTORY_LEN;
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
if (pThis->ring_buf[header]) {
|
|
|
|
pThis->cur++;
|
|
|
|
// obtain saved line
|
|
|
|
if (pThis->ring_buf [header] + header < _RING_HISTORY_LEN) {
|
|
|
|
memset (line, 0, _COMMAND_LINE_LEN);
|
|
|
|
memcpy (line, pThis->ring_buf + header + 1, pThis->ring_buf[header]);
|
|
|
|
} else {
|
|
|
|
int part0 = _RING_HISTORY_LEN - header - 1;
|
|
|
|
memset (line, 0, _COMMAND_LINE_LEN);
|
|
|
|
memcpy (line, pThis->ring_buf + header + 1, part0);
|
|
|
|
memcpy (line + part0, pThis->ring_buf, pThis->ring_buf[header] - part0);
|
|
|
|
}
|
|
|
|
return pThis->ring_buf[header];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (pThis->cur > 0) {
|
|
|
|
pThis->cur--;
|
|
|
|
int header = pThis->begin;
|
|
|
|
int j = 0;
|
|
|
|
|
|
|
|
while ((pThis->ring_buf [header] != 0) && (cnt - j != pThis->cur)) {
|
|
|
|
header += pThis->ring_buf [header] + 1;
|
|
|
|
if (header >= _RING_HISTORY_LEN)
|
|
|
|
header -= _RING_HISTORY_LEN;
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
if (pThis->ring_buf [header] + header < _RING_HISTORY_LEN) {
|
|
|
|
memcpy (line, pThis->ring_buf + header + 1, pThis->ring_buf[header]);
|
|
|
|
} else {
|
|
|
|
int part0 = _RING_HISTORY_LEN - header - 1;
|
|
|
|
memcpy (line, pThis->ring_buf + header + 1, part0);
|
|
|
|
memcpy (line + part0, pThis->ring_buf, pThis->ring_buf[header] - part0);
|
|
|
|
}
|
|
|
|
return pThis->ring_buf[header];
|
|
|
|
} else {
|
|
|
|
/* empty line */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
// split cmdline to tkn array and return nmb of token
|
|
|
|
static int split (microrl_t * pThis, int limit, char const ** tkn_arr)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
int ind = 0;
|
|
|
|
while (1) {
|
|
|
|
// go to the first whitespace (zerro for us)
|
|
|
|
while ((pThis->cmdline [ind] == '\0') && (ind < limit)) {
|
|
|
|
ind++;
|
|
|
|
}
|
|
|
|
if (!(ind < limit)) return i;
|
|
|
|
tkn_arr[i++] = pThis->cmdline + ind;
|
|
|
|
if (i >= _COMMAND_TOKEN_NMB) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
// go to the first NOT whitespace (not zerro for us)
|
|
|
|
while ((pThis->cmdline [ind] != '\0') && (ind < limit)) {
|
|
|
|
ind++;
|
|
|
|
}
|
|
|
|
if (!(ind < limit)) return i;
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
inline static void print_prompt (microrl_t * pThis)
|
|
|
|
{
|
|
|
|
pThis->print (pThis->prompt_str);
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
inline static void terminal_backspace (microrl_t * pThis)
|
|
|
|
{
|
|
|
|
pThis->print ("\033[D \033[D");
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
inline static void terminal_newline (microrl_t * pThis)
|
|
|
|
{
|
|
|
|
pThis->print (ENDL);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _USE_LIBC_STDIO
|
|
|
|
//*****************************************************************************
|
|
|
|
// convert 16 bit value to string
|
|
|
|
// 0 value not supported!!! just make empty string
|
|
|
|
// Returns pointer to a buffer tail
|
|
|
|
static char *u16bit_to_str (unsigned int nmb, char * buf)
|
|
|
|
{
|
|
|
|
char tmp_str [6] = {0,};
|
|
|
|
int i = 0, j;
|
|
|
|
if (nmb <= 0xFFFF) {
|
|
|
|
while (nmb > 0) {
|
|
|
|
tmp_str[i++] = (nmb % 10) + '0';
|
|
|
|
nmb /=10;
|
|
|
|
}
|
|
|
|
for (j = 0; j < i; ++j)
|
|
|
|
*(buf++) = tmp_str [i-j-1];
|
|
|
|
}
|
|
|
|
*buf = '\0';
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
// set cursor at position from begin cmdline (after prompt) + offset
|
|
|
|
static void terminal_move_cursor (microrl_t * pThis, int offset)
|
|
|
|
{
|
|
|
|
char str[16] = {0,};
|
|
|
|
#ifdef _USE_LIBC_STDIO
|
|
|
|
if (offset > 0) {
|
|
|
|
snprintf (str, 16, "\033[%dC", offset);
|
|
|
|
} else if (offset < 0) {
|
|
|
|
snprintf (str, 16, "\033[%dD", -(offset));
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
char *endstr;
|
|
|
|
strcpy (str, "\033[");
|
|
|
|
if (offset > 0) {
|
|
|
|
endstr = u16bit_to_str (offset, str+2);
|
|
|
|
strcpy (endstr, "C");
|
|
|
|
} else if (offset < 0) {
|
|
|
|
endstr = u16bit_to_str (-(offset), str+2);
|
|
|
|
strcpy (endstr, "D");
|
|
|
|
} else
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
pThis->print (str);
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
static void terminal_reset_cursor (microrl_t * pThis)
|
|
|
|
{
|
|
|
|
char str[16];
|
|
|
|
#ifdef _USE_LIBC_STDIO
|
|
|
|
snprintf (str, 16, "\033[%dD\033[%dC", \
|
|
|
|
_COMMAND_LINE_LEN + _PROMPT_LEN + 2, _PROMPT_LEN);
|
|
|
|
|
|
|
|
#else
|
|
|
|
char *endstr;
|
|
|
|
strcpy (str, "\033[");
|
|
|
|
endstr = u16bit_to_str ( _COMMAND_LINE_LEN + _PROMPT_LEN + 2,str+2);
|
|
|
|
strcpy (endstr, "D\033["); endstr += 3;
|
|
|
|
endstr = u16bit_to_str (_PROMPT_LEN, endstr);
|
|
|
|
strcpy (endstr, "C");
|
|
|
|
#endif
|
|
|
|
pThis->print (str);
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
// print cmdline to screen, replace '\0' to wihitespace
|
|
|
|
static void terminal_print_line (microrl_t * pThis, int pos, int cursor)
|
|
|
|
{
|
|
|
|
pThis->print ("\033[K"); // delete all from cursor to end
|
|
|
|
|
|
|
|
char nch [] = {0,0};
|
|
|
|
int i;
|
|
|
|
for (i = pos; i < pThis->cmdlen; i++) {
|
|
|
|
nch [0] = pThis->cmdline [i];
|
|
|
|
if (nch[0] == '\0')
|
|
|
|
nch[0] = ' ';
|
|
|
|
pThis->print (nch);
|
|
|
|
}
|
|
|
|
|
|
|
|
terminal_reset_cursor (pThis);
|
|
|
|
terminal_move_cursor (pThis, cursor);
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
void microrl_init (microrl_t * pThis, void (*print) (const char *))
|
|
|
|
{
|
|
|
|
memset(pThis->cmdline, 0, _COMMAND_LINE_LEN);
|
|
|
|
#ifdef _USE_HISTORY
|
|
|
|
memset(pThis->ring_hist.ring_buf, 0, _RING_HISTORY_LEN);
|
|
|
|
pThis->ring_hist.begin = 0;
|
|
|
|
pThis->ring_hist.end = 0;
|
|
|
|
pThis->ring_hist.cur = 0;
|
|
|
|
#endif
|
|
|
|
pThis->cmdlen =0;
|
|
|
|
pThis->cursor = 0;
|
|
|
|
pThis->execute = NULL;
|
|
|
|
pThis->get_completion = NULL;
|
|
|
|
#ifdef _USE_CTLR_C
|
|
|
|
pThis->sigint = NULL;
|
|
|
|
#endif
|
|
|
|
pThis->prompt_str = prompt_default;
|
|
|
|
pThis->print = print;
|
|
|
|
#ifdef _ENABLE_INIT_PROMPT
|
|
|
|
print_prompt (pThis);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
void microrl_set_complete_callback (microrl_t * pThis, char ** (*get_completion)(int, const char* const*))
|
|
|
|
{
|
|
|
|
pThis->get_completion = get_completion;
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
void microrl_set_execute_callback (microrl_t * pThis, int (*execute)(int, const char* const*))
|
|
|
|
{
|
|
|
|
pThis->execute = execute;
|
|
|
|
}
|
|
|
|
#ifdef _USE_CTLR_C
|
|
|
|
//*****************************************************************************
|
|
|
|
void microrl_set_sigint_callback (microrl_t * pThis, void (*sigintf)(void))
|
|
|
|
{
|
|
|
|
pThis->sigint = sigintf;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef _USE_ESC_SEQ
|
|
|
|
static void hist_search (microrl_t * pThis, int dir)
|
|
|
|
{
|
|
|
|
int len = hist_restore_line (&pThis->ring_hist, pThis->cmdline, dir);
|
|
|
|
if (len >= 0) {
|
|
|
|
pThis->cursor = pThis->cmdlen = len;
|
|
|
|
terminal_reset_cursor (pThis);
|
|
|
|
terminal_print_line (pThis, 0, pThis->cursor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
// handling escape sequences
|
|
|
|
static int escape_process (microrl_t * pThis, char ch)
|
|
|
|
{
|
|
|
|
if (ch == '[') {
|
|
|
|
pThis->escape_seq = _ESC_BRACKET;
|
|
|
|
return 0;
|
|
|
|
} else if (pThis->escape_seq == _ESC_BRACKET) {
|
|
|
|
if (ch == 'A') {
|
|
|
|
#ifdef _USE_HISTORY
|
|
|
|
hist_search (pThis, _HIST_UP);
|
|
|
|
#endif
|
|
|
|
return 1;
|
|
|
|
} else if (ch == 'B') {
|
|
|
|
#ifdef _USE_HISTORY
|
|
|
|
hist_search (pThis, _HIST_DOWN);
|
|
|
|
#endif
|
|
|
|
return 1;
|
|
|
|
} else if (ch == 'C') {
|
|
|
|
if (pThis->cursor < pThis->cmdlen) {
|
|
|
|
terminal_move_cursor (pThis, 1);
|
|
|
|
pThis->cursor++;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
} else if (ch == 'D') {
|
|
|
|
if (pThis->cursor > 0) {
|
|
|
|
terminal_move_cursor (pThis, -1);
|
|
|
|
pThis->cursor--;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
} else if (ch == '7') {
|
|
|
|
pThis->escape_seq = _ESC_HOME;
|
|
|
|
return 0;
|
|
|
|
} else if (ch == '8') {
|
|
|
|
pThis->escape_seq = _ESC_END;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else if (ch == '~') {
|
|
|
|
if (pThis->escape_seq == _ESC_HOME) {
|
|
|
|
terminal_reset_cursor (pThis);
|
|
|
|
pThis->cursor = 0;
|
|
|
|
return 1;
|
|
|
|
} else if (pThis->escape_seq == _ESC_END) {
|
|
|
|
terminal_move_cursor (pThis, pThis->cmdlen-pThis->cursor);
|
|
|
|
pThis->cursor = pThis->cmdlen;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* unknown escape sequence, stop */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
// insert len char of text at cursor position
|
|
|
|
static int microrl_insert_text (microrl_t * pThis, char * text, int len)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
if (pThis->cmdlen + len < _COMMAND_LINE_LEN) {
|
|
|
|
memmove (pThis->cmdline + pThis->cursor + len,
|
|
|
|
pThis->cmdline + pThis->cursor,
|
|
|
|
pThis->cmdlen - pThis->cursor);
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
pThis->cmdline [pThis->cursor + i] = text [i];
|
|
|
|
if (pThis->cmdline [pThis->cursor + i] == ' ') {
|
|
|
|
pThis->cmdline [pThis->cursor + i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pThis->cursor += len;
|
|
|
|
pThis->cmdlen += len;
|
|
|
|
pThis->cmdline [pThis->cmdlen] = '\0';
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
// remove one char at cursor
|
|
|
|
static void microrl_backspace (microrl_t * pThis)
|
|
|
|
{
|
|
|
|
if (pThis->cursor > 0) {
|
|
|
|
terminal_backspace (pThis);
|
|
|
|
memmove (pThis->cmdline + pThis->cursor-1,
|
|
|
|
pThis->cmdline + pThis->cursor,
|
|
|
|
pThis->cmdlen-pThis->cursor+1);
|
|
|
|
pThis->cursor--;
|
|
|
|
pThis->cmdline [pThis->cmdlen] = '\0';
|
|
|
|
pThis->cmdlen--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _USE_COMPLETE
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
static int common_len (char ** arr)
|
|
|
|
{
|
2016-11-21 10:26:55 +02:00
|
|
|
unsigned int i;
|
|
|
|
unsigned int j;
|
2016-11-21 10:23:27 +02:00
|
|
|
char *shortest = arr[0];
|
2016-11-21 10:26:55 +02:00
|
|
|
unsigned int shortlen = strlen(shortest);
|
2016-11-21 10:23:27 +02:00
|
|
|
|
|
|
|
for (i = 0; arr[i] != NULL; ++i)
|
|
|
|
if (strlen(arr[i]) < shortlen) {
|
|
|
|
shortest = arr[i];
|
|
|
|
shortlen = strlen(shortest);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < shortlen; ++i)
|
|
|
|
for (j = 0; arr[j] != 0; ++j)
|
|
|
|
if (shortest[i] != arr[j][i])
|
|
|
|
return i;
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
static void microrl_get_complite (microrl_t * pThis)
|
|
|
|
{
|
|
|
|
char const * tkn_arr[_COMMAND_TOKEN_NMB];
|
|
|
|
char ** compl_token;
|
|
|
|
|
|
|
|
if (pThis->get_completion == NULL) // callback was not set
|
|
|
|
return;
|
|
|
|
|
|
|
|
int status = split (pThis, pThis->cursor, tkn_arr);
|
|
|
|
if (pThis->cmdline[pThis->cursor-1] == '\0')
|
|
|
|
tkn_arr[status++] = "";
|
|
|
|
compl_token = pThis->get_completion (status, tkn_arr);
|
|
|
|
if (compl_token[0] != NULL) {
|
|
|
|
int i = 0;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if (compl_token[1] == NULL) {
|
|
|
|
len = strlen (compl_token[0]);
|
|
|
|
} else {
|
|
|
|
len = common_len (compl_token);
|
|
|
|
terminal_newline (pThis);
|
|
|
|
while (compl_token [i] != NULL) {
|
|
|
|
pThis->print (compl_token[i]);
|
|
|
|
pThis->print (" ");
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
terminal_newline (pThis);
|
|
|
|
print_prompt (pThis);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (len) {
|
|
|
|
microrl_insert_text (pThis, compl_token[0] + strlen(tkn_arr[status-1]),
|
|
|
|
len - strlen(tkn_arr[status-1]));
|
|
|
|
if (compl_token[1] == NULL)
|
|
|
|
microrl_insert_text (pThis, " ", 1);
|
|
|
|
}
|
|
|
|
terminal_reset_cursor (pThis);
|
|
|
|
terminal_print_line (pThis, 0, pThis->cursor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
void new_line_handler(microrl_t * pThis){
|
|
|
|
char const * tkn_arr [_COMMAND_TOKEN_NMB];
|
|
|
|
int status;
|
|
|
|
|
|
|
|
terminal_newline (pThis);
|
|
|
|
#ifdef _USE_HISTORY
|
|
|
|
if (pThis->cmdlen > 0)
|
|
|
|
hist_save_line (&pThis->ring_hist, pThis->cmdline, pThis->cmdlen);
|
|
|
|
#endif
|
|
|
|
status = split (pThis, pThis->cmdlen, tkn_arr);
|
|
|
|
if (status == -1){
|
|
|
|
// pThis->print ("ERROR: Max token amount exseed\n");
|
|
|
|
pThis->print ("ERROR:too many tokens");
|
|
|
|
pThis->print (ENDL);
|
|
|
|
}
|
|
|
|
if ((status > 0) && (pThis->execute != NULL))
|
|
|
|
pThis->execute (status, tkn_arr);
|
|
|
|
print_prompt (pThis);
|
|
|
|
pThis->cmdlen = 0;
|
|
|
|
pThis->cursor = 0;
|
|
|
|
memset(pThis->cmdline, 0, _COMMAND_LINE_LEN);
|
|
|
|
#ifdef _USE_HISTORY
|
|
|
|
pThis->ring_hist.cur = 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
|
|
|
|
|
|
void microrl_insert_char (microrl_t * pThis, int ch)
|
|
|
|
{
|
|
|
|
#ifdef _USE_ESC_SEQ
|
|
|
|
if (pThis->escape) {
|
|
|
|
if (escape_process(pThis, ch))
|
|
|
|
pThis->escape = 0;
|
|
|
|
} else {
|
|
|
|
#endif
|
|
|
|
switch (ch) {
|
|
|
|
//-----------------------------------------------------
|
|
|
|
#ifdef _ENDL_CR
|
|
|
|
case KEY_CR:
|
|
|
|
new_line_handler(pThis);
|
|
|
|
break;
|
|
|
|
case KEY_LF:
|
|
|
|
break;
|
|
|
|
#elif defined(_ENDL_CRLF)
|
|
|
|
case KEY_CR:
|
|
|
|
pThis->tmpch = KEY_CR;
|
|
|
|
break;
|
|
|
|
case KEY_LF:
|
|
|
|
if (pThis->tmpch == KEY_CR)
|
|
|
|
new_line_handler(pThis);
|
|
|
|
break;
|
|
|
|
#elif defined(_ENDL_LFCR)
|
|
|
|
case KEY_LF:
|
|
|
|
pThis->tmpch = KEY_LF;
|
|
|
|
break;
|
|
|
|
case KEY_CR:
|
|
|
|
if (pThis->tmpch == KEY_LF)
|
|
|
|
new_line_handler(pThis);
|
|
|
|
break;
|
|
|
|
#else
|
|
|
|
case KEY_CR:
|
|
|
|
break;
|
|
|
|
case KEY_LF:
|
|
|
|
new_line_handler(pThis);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
//-----------------------------------------------------
|
|
|
|
#ifdef _USE_COMPLETE
|
|
|
|
case KEY_HT:
|
|
|
|
microrl_get_complite (pThis);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
//-----------------------------------------------------
|
|
|
|
case KEY_ESC:
|
|
|
|
#ifdef _USE_ESC_SEQ
|
|
|
|
pThis->escape = 1;
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
//-----------------------------------------------------
|
|
|
|
case KEY_NAK: // ^U
|
|
|
|
while (pThis->cursor > 0) {
|
|
|
|
microrl_backspace (pThis);
|
|
|
|
}
|
|
|
|
terminal_print_line (pThis, 0, pThis->cursor);
|
|
|
|
break;
|
|
|
|
//-----------------------------------------------------
|
|
|
|
case KEY_VT: // ^K
|
|
|
|
pThis->print ("\033[K");
|
|
|
|
pThis->cmdlen = pThis->cursor;
|
|
|
|
break;
|
|
|
|
//-----------------------------------------------------
|
|
|
|
case KEY_ENQ: // ^E
|
|
|
|
terminal_move_cursor (pThis, pThis->cmdlen-pThis->cursor);
|
|
|
|
pThis->cursor = pThis->cmdlen;
|
|
|
|
break;
|
|
|
|
//-----------------------------------------------------
|
|
|
|
case KEY_SOH: // ^A
|
|
|
|
terminal_reset_cursor (pThis);
|
|
|
|
pThis->cursor = 0;
|
|
|
|
break;
|
|
|
|
//-----------------------------------------------------
|
|
|
|
case KEY_ACK: // ^F
|
|
|
|
if (pThis->cursor < pThis->cmdlen) {
|
|
|
|
terminal_move_cursor (pThis, 1);
|
|
|
|
pThis->cursor++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
//-----------------------------------------------------
|
|
|
|
case KEY_STX: // ^B
|
|
|
|
if (pThis->cursor) {
|
|
|
|
terminal_move_cursor (pThis, -1);
|
|
|
|
pThis->cursor--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
//-----------------------------------------------------
|
|
|
|
case KEY_DLE: //^P
|
|
|
|
#ifdef _USE_HISTORY
|
|
|
|
hist_search (pThis, _HIST_UP);
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
//-----------------------------------------------------
|
|
|
|
case KEY_SO: //^N
|
|
|
|
#ifdef _USE_HISTORY
|
|
|
|
hist_search (pThis, _HIST_DOWN);
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
//-----------------------------------------------------
|
|
|
|
case KEY_DEL: // Backspace
|
|
|
|
case KEY_BS: // ^U
|
|
|
|
microrl_backspace (pThis);
|
|
|
|
terminal_print_line (pThis, pThis->cursor, pThis->cursor);
|
|
|
|
break;
|
|
|
|
#ifdef _USE_CTLR_C
|
|
|
|
case KEY_ETX:
|
|
|
|
if (pThis->sigint != NULL)
|
|
|
|
pThis->sigint();
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
//-----------------------------------------------------
|
|
|
|
default:
|
|
|
|
if (((ch == ' ') && (pThis->cmdlen == 0)) || IS_CONTROL_CHAR(ch))
|
|
|
|
break;
|
|
|
|
if (microrl_insert_text (pThis, (char*)&ch, 1))
|
|
|
|
terminal_print_line (pThis, pThis->cursor-1, pThis->cursor);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#ifdef _USE_ESC_SEQ
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|