mirror of
https://github.com/troglobit/editline.git
synced 2025-05-06 04:21:24 +08:00
added simple multiline support
This commit is contained in:
parent
13f8d5f69c
commit
d3109109c4
181
src/editline.c
181
src/editline.c
@ -113,6 +113,9 @@ static int Searching = 0;
|
|||||||
static const char *(*search_move)(void);
|
static const char *(*search_move)(void);
|
||||||
static const char *old_prompt = NULL;
|
static const char *old_prompt = NULL;
|
||||||
static rl_vcpfunc_t *line_handler = NULL;
|
static rl_vcpfunc_t *line_handler = NULL;
|
||||||
|
static char *line_up = "\x1b[A";
|
||||||
|
static char *line_down = "\x1b[B";
|
||||||
|
int prompt_len = 0;
|
||||||
|
|
||||||
int el_no_echo = 0; /* e.g., under Emacs */
|
int el_no_echo = 0; /* e.g., under Emacs */
|
||||||
int el_no_hist = 0;
|
int el_no_hist = 0;
|
||||||
@ -206,8 +209,12 @@ static void tty_show(unsigned char c)
|
|||||||
|
|
||||||
static void tty_string(char *p)
|
static void tty_string(char *p)
|
||||||
{
|
{
|
||||||
while (*p)
|
int i = rl_point + prompt_len + 1;
|
||||||
|
while (*p) {
|
||||||
tty_show(*p++);
|
tty_show(*p++);
|
||||||
|
if ((i++) % tty_cols == 0)
|
||||||
|
tty_put('\n');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tty_push(int c)
|
static void tty_push(int c)
|
||||||
@ -304,33 +311,90 @@ void el_print_columns(int ac, char **av)
|
|||||||
if (j + skip < ac) {
|
if (j + skip < ac) {
|
||||||
while (++len < colwidth)
|
while (++len < colwidth)
|
||||||
tty_put(' ');
|
tty_put(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tty_puts(NEWLINE);
|
tty_puts(NEWLINE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reposition(void)
|
static void reposition(int key)
|
||||||
{
|
{
|
||||||
int i;
|
int i = 0;
|
||||||
|
int len_with_prompt = prompt_len + rl_end;
|
||||||
|
int n = len_with_prompt / tty_cols; // determine the number of lines
|
||||||
|
|
||||||
tty_put('\r');
|
tty_put('\r');
|
||||||
tty_puts(rl_prompt);
|
|
||||||
for (i = 0; i < rl_point; i++)
|
if (n > 0) {
|
||||||
|
int line;
|
||||||
|
if (key == CTL('A') || key == CTL('E') || key == rl_kill)
|
||||||
|
line = (prompt_len + old_point) / tty_cols; // determine num of current line
|
||||||
|
else
|
||||||
|
line = len_with_prompt / tty_cols;
|
||||||
|
|
||||||
|
if (key == CTL('E')) { // move to end of line(s)
|
||||||
|
for(int k = line; k < n; k++)
|
||||||
|
tty_puts(line_down);
|
||||||
|
i = rl_point - (len_with_prompt % tty_cols); // determine reminder of last line and redraw only it
|
||||||
|
} else {
|
||||||
|
for(int k = line; k > 0; k--) // CTRL-A, CTRL-U, insert (end, middle), remove (end, middle)
|
||||||
|
tty_puts(line_up); // redraw characters until changed data
|
||||||
|
tty_puts(rl_prompt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (n == 0) {
|
||||||
|
tty_puts(rl_prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i; i < rl_point; i++) {
|
||||||
tty_show(rl_line_buffer[i]);
|
tty_show(rl_line_buffer[i]);
|
||||||
|
if ((i + prompt_len + 1) % tty_cols == 0) { // move to the next line
|
||||||
|
tty_put('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void itoa(int val, char* buf)
|
||||||
|
{
|
||||||
|
int digits = 0;
|
||||||
|
int temp = val;
|
||||||
|
while (temp != 0) {
|
||||||
|
temp = temp / 10;
|
||||||
|
++digits;
|
||||||
|
}
|
||||||
|
*(buf+digits) = 'C';
|
||||||
|
int i = 5; digits--;
|
||||||
|
for(; val && i ; --i, val /= 10) {
|
||||||
|
*(buf+digits) = "0123456789"[val % 10];
|
||||||
|
digits--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void move_cursor_forward(int columns)
|
||||||
|
{
|
||||||
|
char buf[12] = {0};
|
||||||
|
const char* line_forward = "\x1b[";
|
||||||
|
strcpy(buf, line_forward);
|
||||||
|
itoa(columns, buf+2);
|
||||||
|
tty_puts(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void left(el_status_t Change)
|
static void left(el_status_t Change)
|
||||||
{
|
{
|
||||||
if (rl_point) {
|
if (rl_point) {
|
||||||
tty_back();
|
if ((rl_point + prompt_len) % tty_cols == 0) {
|
||||||
if (ISMETA(rl_line_buffer[rl_point - 1])) {
|
tty_puts(line_up);
|
||||||
if (rl_meta_chars) {
|
move_cursor_forward(tty_cols);
|
||||||
tty_back();
|
} else {
|
||||||
tty_back();
|
tty_back();
|
||||||
}
|
}
|
||||||
} else if (ISCTL(rl_line_buffer[rl_point - 1])) {
|
if (ISMETA(rl_line_buffer[rl_point - 1])) {
|
||||||
|
if (rl_meta_chars) {
|
||||||
|
tty_back();
|
||||||
|
tty_back();
|
||||||
|
}
|
||||||
|
} else if (ISCTL(rl_line_buffer[rl_point - 1])) {
|
||||||
tty_back();
|
tty_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -341,7 +405,10 @@ static void left(el_status_t Change)
|
|||||||
|
|
||||||
static void right(el_status_t Change)
|
static void right(el_status_t Change)
|
||||||
{
|
{
|
||||||
tty_show(rl_line_buffer[rl_point]);
|
if ((rl_point + prompt_len + 1) % tty_cols == 0)
|
||||||
|
tty_put('\n');
|
||||||
|
else
|
||||||
|
tty_show(rl_line_buffer[rl_point]);
|
||||||
|
|
||||||
if (Change == CSmove)
|
if (Change == CSmove)
|
||||||
rl_point++;
|
rl_point++;
|
||||||
@ -382,23 +449,23 @@ static el_status_t do_forward(el_status_t move)
|
|||||||
do {
|
do {
|
||||||
p = &rl_line_buffer[rl_point];
|
p = &rl_line_buffer[rl_point];
|
||||||
|
|
||||||
/* Skip leading whitespace, like FSF Readline */
|
/* Skip leading whitespace, like FSF Readline */
|
||||||
for ( ; rl_point < rl_end && (p[0] == ' ' || !is_alpha_num(p[0])); rl_point++, p++) {
|
for ( ; rl_point < rl_end && (p[0] == ' ' || !is_alpha_num(p[0])); rl_point++, p++) {
|
||||||
if (move == CSmove)
|
if (move == CSmove)
|
||||||
right(CSstay);
|
right(CSstay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip to end of word, if inside a word. */
|
/* Skip to end of word, if inside a word. */
|
||||||
for (; rl_point < rl_end && is_alpha_num(p[0]); rl_point++, p++) {
|
for (; rl_point < rl_end && is_alpha_num(p[0]); rl_point++, p++) {
|
||||||
if (move == CSmove)
|
if (move == CSmove)
|
||||||
right(CSstay);
|
right(CSstay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip to next word, or skip leading white space if outside a word. */
|
/* Skip to next word, or skip leading white space if outside a word. */
|
||||||
for ( ; rl_point < rl_end && (p[0] == ' ' || !is_alpha_num(p[0])); rl_point++, p++) {
|
for ( ; rl_point < rl_end && (p[0] == ' ' || !is_alpha_num(p[0])); rl_point++, p++) {
|
||||||
if (move == CSmove)
|
if (move == CSmove)
|
||||||
right(CSstay);
|
right(CSstay);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rl_point == rl_end)
|
if (rl_point == rl_end)
|
||||||
break;
|
break;
|
||||||
@ -424,7 +491,7 @@ static el_status_t do_case(el_case_t type)
|
|||||||
end = rl_end;
|
end = rl_end;
|
||||||
|
|
||||||
for (i = rl_point, p = &rl_line_buffer[i]; rl_point < end; p++) {
|
for (i = rl_point, p = &rl_line_buffer[i]; rl_point < end; p++) {
|
||||||
if ((type == TOupper) || (type == TOcapitalize && rl_point == i)) {
|
if ((type == TOupper) || (type == TOcapitalize && rl_point == i)) {
|
||||||
if (islower(*p))
|
if (islower(*p))
|
||||||
*p = toupper(*p);
|
*p = toupper(*p);
|
||||||
} else if (isupper(*p)) {
|
} else if (isupper(*p)) {
|
||||||
@ -460,33 +527,54 @@ static void ceol(void)
|
|||||||
|
|
||||||
while (rl_point < 0) {
|
while (rl_point < 0) {
|
||||||
tty_put(' ');
|
tty_put(' ');
|
||||||
rl_point++;
|
rl_point++;
|
||||||
extras++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = rl_point, p = &rl_line_buffer[i]; i <= rl_end; i++, p++) {
|
for (i = rl_point, p = &rl_line_buffer[i]; i <= rl_end; i++, p++) {
|
||||||
tty_put(' ');
|
if ((i + prompt_len + 1) % tty_cols == 0){
|
||||||
|
tty_put(' ');
|
||||||
|
tty_put('\n');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tty_put(' ');
|
||||||
if (ISMETA(*p)) {
|
if (ISMETA(*p)) {
|
||||||
if (rl_meta_chars) {
|
if (rl_meta_chars) {
|
||||||
tty_put(' ');
|
tty_put(' ');
|
||||||
tty_put(' ');
|
tty_put(' ');
|
||||||
extras += 2;
|
extras += 2;
|
||||||
}
|
}
|
||||||
} else if (ISCTL(*p)) {
|
} else if (ISCTL(*p)) {
|
||||||
tty_put(' ');
|
tty_put(' ');
|
||||||
extras++;
|
extras++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i += extras; i > rl_point; i--)
|
for (i += extras; i > rl_point; i--) {
|
||||||
tty_back();
|
if ((i + prompt_len) % tty_cols == 0) {
|
||||||
|
tty_puts(line_up);
|
||||||
|
move_cursor_forward(tty_cols);
|
||||||
|
} else {
|
||||||
|
tty_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_line(void)
|
static void clear_line(void)
|
||||||
{
|
{
|
||||||
|
int n = (rl_point + prompt_len) / tty_cols;
|
||||||
rl_point = -(int)strlen(rl_prompt);
|
rl_point = -(int)strlen(rl_prompt);
|
||||||
tty_put('\r');
|
|
||||||
|
if (n > 0) {
|
||||||
|
for(int k = 0; k < n; k++)
|
||||||
|
tty_puts(line_up);
|
||||||
|
tty_put('\r');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tty_put('\r');
|
||||||
|
}
|
||||||
|
|
||||||
ceol();
|
ceol();
|
||||||
|
|
||||||
rl_point = 0;
|
rl_point = 0;
|
||||||
rl_end = 0;
|
rl_end = 0;
|
||||||
rl_line_buffer[0] = '\0';
|
rl_line_buffer[0] = '\0';
|
||||||
@ -501,7 +589,7 @@ static el_status_t insert_string(const char *p)
|
|||||||
|
|
||||||
len = strlen(p);
|
len = strlen(p);
|
||||||
if (rl_end + len >= Length) {
|
if (rl_end + len >= Length) {
|
||||||
line = malloc(sizeof(char) * (Length + len + MEM_INC));
|
line = malloc(sizeof(char) * (Length + len + MEM_INC));
|
||||||
if (!line)
|
if (!line)
|
||||||
return CSstay;
|
return CSstay;
|
||||||
|
|
||||||
@ -538,14 +626,15 @@ int rl_insert_text(const char *text)
|
|||||||
|
|
||||||
static el_status_t redisplay(int cls)
|
static el_status_t redisplay(int cls)
|
||||||
{
|
{
|
||||||
if (cls && rl_point == 0 && rl_end == 0)
|
if (cls)
|
||||||
tty_puts(CLEAR);
|
tty_puts(CLEAR);
|
||||||
else
|
else
|
||||||
tty_puts("\r\e[K");
|
tty_puts("\r\e[K");
|
||||||
|
|
||||||
tty_puts(rl_prompt);
|
tty_puts(rl_prompt);
|
||||||
|
rl_point = 0;
|
||||||
tty_string(rl_line_buffer);
|
tty_string(rl_line_buffer);
|
||||||
|
rl_point = rl_end;
|
||||||
return CSmove;
|
return CSmove;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,7 +674,7 @@ static el_status_t do_insert_hist(const char *p)
|
|||||||
clear_line();
|
clear_line();
|
||||||
|
|
||||||
rl_point = 0;
|
rl_point = 0;
|
||||||
reposition();
|
reposition(-1);
|
||||||
rl_end = 0;
|
rl_end = 0;
|
||||||
|
|
||||||
return insert_string(p);
|
return insert_string(p);
|
||||||
@ -792,6 +881,7 @@ static el_status_t delete_string(int count)
|
|||||||
for (p = &rl_line_buffer[rl_point], i = rl_end - (rl_point + count) + 1; --i >= 0; p++)
|
for (p = &rl_line_buffer[rl_point], i = rl_end - (rl_point + count) + 1; --i >= 0; p++)
|
||||||
p[0] = p[count];
|
p[0] = p[count];
|
||||||
ceol();
|
ceol();
|
||||||
|
|
||||||
rl_end -= count;
|
rl_end -= count;
|
||||||
tty_string(&rl_line_buffer[rl_point]);
|
tty_string(&rl_line_buffer[rl_point]);
|
||||||
|
|
||||||
@ -832,7 +922,7 @@ static el_status_t kill_line(void)
|
|||||||
if (Repeat < rl_point) {
|
if (Repeat < rl_point) {
|
||||||
i = rl_point;
|
i = rl_point;
|
||||||
rl_point = Repeat;
|
rl_point = Repeat;
|
||||||
reposition();
|
reposition(-1);
|
||||||
delete_string(i - rl_point);
|
delete_string(i - rl_point);
|
||||||
} else if (Repeat > rl_point) {
|
} else if (Repeat > rl_point) {
|
||||||
right(CSmove);
|
right(CSmove);
|
||||||
@ -1059,8 +1149,9 @@ static el_status_t tty_special(int c)
|
|||||||
|
|
||||||
if (c == rl_kill) {
|
if (c == rl_kill) {
|
||||||
if (rl_point != 0) {
|
if (rl_point != 0) {
|
||||||
|
old_point = rl_point;
|
||||||
rl_point = 0;
|
rl_point = 0;
|
||||||
reposition();
|
reposition(c);
|
||||||
}
|
}
|
||||||
Repeat = NO_ARG;
|
Repeat = NO_ARG;
|
||||||
|
|
||||||
@ -1095,7 +1186,7 @@ static char *editinput(int complete)
|
|||||||
return (char *)"";
|
return (char *)"";
|
||||||
|
|
||||||
case CSmove:
|
case CSmove:
|
||||||
reposition();
|
reposition(c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CSdispatch:
|
case CSdispatch:
|
||||||
@ -1110,7 +1201,7 @@ static char *editinput(int complete)
|
|||||||
return (char *)"";
|
return (char *)"";
|
||||||
|
|
||||||
case CSmove:
|
case CSmove:
|
||||||
reposition();
|
reposition(c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CSdispatch:
|
case CSdispatch:
|
||||||
@ -1334,6 +1425,8 @@ static int el_prep(const char *prompt)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
rl_prompt = prompt ? prompt : NILSTR;
|
rl_prompt = prompt ? prompt : NILSTR;
|
||||||
|
prompt_len = strlen(rl_prompt);
|
||||||
|
|
||||||
if (el_no_echo) {
|
if (el_no_echo) {
|
||||||
int old = el_no_echo;
|
int old = el_no_echo;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user