Improvements to experimental line editor
This commit is contained in:
parent
b7c642c273
commit
b25aa946e5
132
apps/sh.c
132
apps/sh.c
|
@ -119,7 +119,7 @@ void gethost() {
|
||||||
memcpy(_hostname, buf.nodename, len+1);
|
memcpy(_hostname, buf.nodename, len+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_extended_ps(char * format) {
|
void print_extended_ps(char * format, char * buffer, int * display_width) {
|
||||||
/* Get the time */
|
/* Get the time */
|
||||||
struct tm * timeinfo;
|
struct tm * timeinfo;
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
|
@ -151,12 +151,25 @@ void print_extended_ps(char * format) {
|
||||||
sprintf(ret, "%d ", last_ret);
|
sprintf(ret, "%d ", last_ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t offset = 0;
|
||||||
|
int is_visible = 1;
|
||||||
|
*display_width = 0;
|
||||||
|
|
||||||
while (*format) {
|
while (*format) {
|
||||||
if (*format == '\\') {
|
if (*format == '\\') {
|
||||||
format++;
|
format++;
|
||||||
switch (*format) {
|
switch (*format) {
|
||||||
case '\\':
|
case '\\':
|
||||||
putchar(*format);
|
buffer[offset++] = *format;
|
||||||
|
(*display_width) += is_visible ? 1 : 0;
|
||||||
|
format++;
|
||||||
|
break;
|
||||||
|
case '[':
|
||||||
|
is_visible = 0;
|
||||||
|
format++;
|
||||||
|
break;
|
||||||
|
case ']':
|
||||||
|
is_visible = 1;
|
||||||
format++;
|
format++;
|
||||||
break;
|
break;
|
||||||
case '0':
|
case '0':
|
||||||
|
@ -180,56 +193,93 @@ void print_extended_ps(char * format) {
|
||||||
format++;
|
format++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
putchar(i);
|
buffer[offset++] = i;
|
||||||
|
(*display_width) += is_visible ? 1 : 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
putchar('\033');
|
buffer[offset++] = '\033';
|
||||||
|
(*display_width) += is_visible ? 1 : 0;
|
||||||
format++;
|
format++;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
printf("%s", date_buffer);
|
{
|
||||||
|
int size = sprintf(buffer+offset, "%s", date_buffer);
|
||||||
|
offset += size;
|
||||||
|
(*display_width) += is_visible ? size : 0;
|
||||||
|
}
|
||||||
format++;
|
format++;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
printf("%s", time_buffer);
|
{
|
||||||
|
int size = sprintf(buffer+offset, "%s", time_buffer);
|
||||||
|
offset += size;
|
||||||
|
(*display_width) += is_visible ? size : 0;
|
||||||
|
}
|
||||||
format++;
|
format++;
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
printf("%s", _hostname);
|
{
|
||||||
|
int size = sprintf(buffer+offset, "%s", _hostname);
|
||||||
|
offset += size;
|
||||||
|
(*display_width) += is_visible ? size : 0;
|
||||||
|
}
|
||||||
format++;
|
format++;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
printf("%s", username);
|
{
|
||||||
|
int size = sprintf(buffer+offset, "%s", username);
|
||||||
|
offset += size;
|
||||||
|
(*display_width) += is_visible ? size : 0;
|
||||||
|
}
|
||||||
format++;
|
format++;
|
||||||
break;
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
printf("%s", _cwd);
|
{
|
||||||
|
int size = sprintf(buffer+offset, "%s", _cwd);
|
||||||
|
offset += size;
|
||||||
|
(*display_width) += is_visible ? size : 0;
|
||||||
|
}
|
||||||
format++;
|
format++;
|
||||||
break;
|
break;
|
||||||
case '$':
|
case '$':
|
||||||
putchar(getuid() == 0 ? '#' : '$');
|
buffer[offset++] = (getuid() == 0 ? '#' : '$');
|
||||||
|
(*display_width) += is_visible ? 1 : 0;
|
||||||
format++;
|
format++;
|
||||||
break;
|
break;
|
||||||
case 'U': /* prompt color string */
|
case 'U': /* prompt color string */
|
||||||
printf("%s", getuid() == 0 ? "\033[1;38;5;196m" : "\033[1;38;5;47m");
|
{
|
||||||
|
int size = sprintf(buffer+offset, "%s", getuid() == 0 ? "\033[1;38;5;196m" : "\033[1;38;5;47m");
|
||||||
|
offset += size;
|
||||||
|
/* Does not affect size */
|
||||||
|
}
|
||||||
format++;
|
format++;
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
printf("%s", ret);
|
{
|
||||||
|
int size = sprintf(buffer+offset, "%s", ret);
|
||||||
|
offset += size;
|
||||||
|
(*display_width) += is_visible ? size : 0;
|
||||||
|
}
|
||||||
format++;
|
format++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("\\%c", *format);
|
{
|
||||||
|
int size = sprintf(buffer+offset, "\\%c", *format);
|
||||||
|
offset += size;
|
||||||
|
(*display_width) += is_visible ? size : 0;
|
||||||
|
}
|
||||||
format++;
|
format++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
putchar(*format);
|
buffer[offset++] = *format;
|
||||||
|
(*display_width) += is_visible ? 1 : 0;
|
||||||
format++;
|
format++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buffer[offset] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FALLBACK_PS1 "\\u@\\h \\w\\$ "
|
#define FALLBACK_PS1 "\\u@\\h \\w\\$ "
|
||||||
|
@ -237,7 +287,10 @@ void print_extended_ps(char * format) {
|
||||||
/* Draw the user prompt */
|
/* Draw the user prompt */
|
||||||
void draw_prompt(void) {
|
void draw_prompt(void) {
|
||||||
char * ps1 = getenv("PS1");
|
char * ps1 = getenv("PS1");
|
||||||
print_extended_ps(ps1 ? ps1 : FALLBACK_PS1);
|
char buf[1024];
|
||||||
|
int display_width;
|
||||||
|
print_extended_ps(ps1 ? ps1 : FALLBACK_PS1, buf, &display_width);
|
||||||
|
fprintf(stdout, "%s", buf);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,7 +312,10 @@ void redraw_prompt_func(rline_context_t * context) {
|
||||||
void draw_prompt_c() {
|
void draw_prompt_c() {
|
||||||
char * ps2 = getenv("PS2");
|
char * ps2 = getenv("PS2");
|
||||||
if (ps2) {
|
if (ps2) {
|
||||||
print_extended_ps(ps2);
|
char buf[1024];
|
||||||
|
int display_width;
|
||||||
|
print_extended_ps(ps2, buf, &display_width);
|
||||||
|
fprintf(stdout, "%s", buf);
|
||||||
} else {
|
} else {
|
||||||
printf("> ");
|
printf("> ");
|
||||||
}
|
}
|
||||||
|
@ -512,21 +568,41 @@ void add_argument(list_t * argv, char * buf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_entry(char * buffer) {
|
int read_entry(char * buffer) {
|
||||||
rline_callbacks_t callbacks = {
|
if (experimental_rline) {
|
||||||
tab_complete_func, redraw_prompt_func, NULL,
|
char lprompt[1024], rprompt[1024];
|
||||||
NULL, NULL, NULL, NULL, NULL
|
int lwidth, rwidth;
|
||||||
};
|
|
||||||
int buffer_size = experimental_rline ? rline_experimental(buffer, LINE_LEN) : rline((char *)buffer, LINE_LEN, &callbacks);
|
char * ps1 = getenv("PS1_LEFT");
|
||||||
return buffer_size;
|
print_extended_ps(ps1 ? ps1 : FALLBACK_PS1, lprompt, &lwidth);
|
||||||
|
|
||||||
|
char * ps1r = getenv("PS1_RIGHT");
|
||||||
|
print_extended_ps(ps1r ? ps1r : "", rprompt, &rwidth);
|
||||||
|
|
||||||
|
rline_exp_set_prompts(lprompt, rprompt, lwidth, rwidth);
|
||||||
|
rline_exp_set_shell_commands(shell_commands, shell_commands_len);
|
||||||
|
rline_exp_set_tab_complete_func(tab_complete_func);
|
||||||
|
return rline_experimental(buffer, LINE_LEN);
|
||||||
|
} else {
|
||||||
|
rline_callbacks_t callbacks = {
|
||||||
|
tab_complete_func, redraw_prompt_func, NULL,
|
||||||
|
NULL, NULL, NULL, NULL, NULL
|
||||||
|
};
|
||||||
|
return rline((char *)buffer, LINE_LEN, &callbacks);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_entry_continued(char * buffer) {
|
int read_entry_continued(char * buffer) {
|
||||||
rline_callbacks_t callbacks = {
|
if (experimental_rline) {
|
||||||
tab_complete_func, redraw_prompt_func_c, NULL,
|
rline_exp_set_prompts("> ", "", 2, 0);
|
||||||
NULL, NULL, NULL, NULL, NULL
|
rline_exp_set_shell_commands(shell_commands, shell_commands_len);
|
||||||
};
|
return rline_experimental(buffer, LINE_LEN);
|
||||||
int buffer_size = experimental_rline ? rline_experimental(buffer, LINE_LEN) : rline((char *)buffer, LINE_LEN, &callbacks);
|
} else {
|
||||||
return buffer_size;
|
rline_callbacks_t callbacks = {
|
||||||
|
tab_complete_func, redraw_prompt_func_c, NULL,
|
||||||
|
NULL, NULL, NULL, NULL, NULL
|
||||||
|
};
|
||||||
|
return rline((char *)buffer, LINE_LEN, &callbacks);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int variable_char(uint8_t c) {
|
int variable_char(uint8_t c) {
|
||||||
|
|
|
@ -1 +1,6 @@
|
||||||
|
export PS1_TITLE="\\[\\e]1;\\u@\\h:\\w\\007\\e]2;\\u@\\h:\\w\\007\\]"
|
||||||
|
export PS1_RIGHT="\\[\\e[1m\\e[38;5;59m\\][\\[\\e[38;5;173m\\]\\d \\[\\e[38;5;167m\\]\\t\\[\\e[38;5;59m\\]] "
|
||||||
|
export PS1_LEFT="${PS1_TITLE}\\[\\e[1m\\e[38;5;221m\\]\\u\\[\\e[38;5;59m\\]@\\[\\e[38;5;81m\\]\\h \\[\\e[38;5;167m\\]\\r\\[\\e[0m\\]\\w\\U\\\$\\[\\e[0m\\] "
|
||||||
|
# Old prompt
|
||||||
export PS1="\\e]1;\\u@\\h:\\w\\007\\e]2;\\u@\\h:\\w\\007\\e[1m\\e[s\\e[400C\\e[16D\\e[1m\\e[38;5;59m[\\e[38;5;173m\\d \\e[38;5;167m\\t\\e[38;5;59m]\\e[u\\e[38;5;221m\\u\\e[38;5;59m@\\e[38;5;81m\\h \\e[38;5;167m\\r\\e[0m\\w\\U\\\$\\e[0m "
|
export PS1="\\e]1;\\u@\\h:\\w\\007\\e]2;\\u@\\h:\\w\\007\\e[1m\\e[s\\e[400C\\e[16D\\e[1m\\e[38;5;59m[\\e[38;5;173m\\d \\e[38;5;167m\\t\\e[38;5;59m]\\e[u\\e[38;5;221m\\u\\e[38;5;59m@\\e[38;5;81m\\h \\e[38;5;167m\\r\\e[0m\\w\\U\\\$\\e[0m "
|
||||||
|
export RLINE_THEME="sunsmoke"
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <toaru/rline.h>
|
||||||
|
|
||||||
extern int rline_experimental(char * buffer, int buf_size);
|
extern int rline_experimental(char * buffer, int buf_size);
|
||||||
|
extern int rline_exp_set_prompts(char * left, char * right, int left_width, int right_width);
|
||||||
|
extern int rline_exp_set_shell_commands(char ** cmds, int len);
|
||||||
|
extern int rline_exp_set_tab_complete_func(rline_callback_t func);
|
||||||
|
|
243
lib/rline_exp.c
243
lib/rline_exp.c
|
@ -26,6 +26,8 @@
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include <toaru/rline.h>
|
||||||
|
|
||||||
#define ENTER_KEY '\n'
|
#define ENTER_KEY '\n'
|
||||||
#define BACKSPACE_KEY 0x08
|
#define BACKSPACE_KEY 0x08
|
||||||
#define DELETE_KEY 0x7F
|
#define DELETE_KEY 0x7F
|
||||||
|
@ -45,9 +47,11 @@ typedef struct {
|
||||||
|
|
||||||
line_t * the_line = NULL;
|
line_t * the_line = NULL;
|
||||||
|
|
||||||
|
static int loading = 0;
|
||||||
static int column = 0;
|
static int column = 0;
|
||||||
static int offset = 0;
|
static int offset = 0;
|
||||||
static int width = 0;
|
static int width = 0;
|
||||||
|
static int buf_size_max = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Need to make prompt configurable.
|
* TODO: Need to make prompt configurable.
|
||||||
|
@ -61,6 +65,30 @@ static char * prompt = "> ";
|
||||||
static int prompt_right_width = 4;
|
static int prompt_right_width = 4;
|
||||||
static char * prompt_right = " :) ";
|
static char * prompt_right = " :) ";
|
||||||
|
|
||||||
|
static char ** shell_commands = {0};
|
||||||
|
static int shell_commands_len = 0;
|
||||||
|
|
||||||
|
int rline_exp_set_shell_commands(char ** cmds, int len) {
|
||||||
|
shell_commands = cmds;
|
||||||
|
shell_commands_len = len;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rline_exp_set_prompts(char * left, char * right, int left_width, int right_width) {
|
||||||
|
prompt = left;
|
||||||
|
prompt_right = right;
|
||||||
|
prompt_width = left_width;
|
||||||
|
prompt_right_width = right_width;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rline_callback_t tab_complete_func = NULL;
|
||||||
|
|
||||||
|
int rline_exp_set_tab_complete_func(rline_callback_t func) {
|
||||||
|
tab_complete_func = func;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int to_eight(uint32_t codepoint, char * out) {
|
static int to_eight(uint32_t codepoint, char * out) {
|
||||||
memset(out, 0x00, 7);
|
memset(out, 0x00, 7);
|
||||||
|
|
||||||
|
@ -193,9 +221,36 @@ static const char * COLOR_SELECTFG = "@0";
|
||||||
static const char * COLOR_RED = "@1";
|
static const char * COLOR_RED = "@1";
|
||||||
static const char * COLOR_GREEN = "@2";
|
static const char * COLOR_GREEN = "@2";
|
||||||
|
|
||||||
static void load_colorscheme_sunsmoke(void) {
|
void rline_exp_load_colorscheme_default(void) {
|
||||||
|
COLOR_FG = "@9";
|
||||||
|
COLOR_BG = "@9";
|
||||||
|
COLOR_ALT_FG = "@5";
|
||||||
|
COLOR_ALT_BG = "@9";
|
||||||
|
COLOR_NUMBER_FG = "@3";
|
||||||
|
COLOR_NUMBER_BG = "@9";
|
||||||
|
COLOR_STATUS_FG = "@7";
|
||||||
|
COLOR_STATUS_BG = "@4";
|
||||||
|
COLOR_TABBAR_BG = "@4";
|
||||||
|
COLOR_TAB_BG = "@4";
|
||||||
|
COLOR_KEYWORD = "@4";
|
||||||
|
COLOR_STRING = "@2";
|
||||||
|
COLOR_COMMENT = "@5";
|
||||||
|
COLOR_TYPE = "@3";
|
||||||
|
COLOR_PRAGMA = "@1";
|
||||||
|
COLOR_NUMERAL = "@1";
|
||||||
|
COLOR_ERROR_FG = "@7";
|
||||||
|
COLOR_ERROR_BG = "@1";
|
||||||
|
COLOR_SEARCH_FG = "@0";
|
||||||
|
COLOR_SEARCH_BG = "@3";
|
||||||
|
COLOR_SELECTBG = "@7";
|
||||||
|
COLOR_SELECTFG = "@0";
|
||||||
|
COLOR_RED = "@1";
|
||||||
|
COLOR_GREEN = "@2";
|
||||||
|
}
|
||||||
|
|
||||||
|
void rline_exp_load_colorscheme_sunsmoke(void) {
|
||||||
COLOR_FG = "2;230;230;230";
|
COLOR_FG = "2;230;230;230";
|
||||||
COLOR_BG = "2;31;31;31";
|
COLOR_BG = "@9";
|
||||||
COLOR_ALT_FG = "2;122;122;122";
|
COLOR_ALT_FG = "2;122;122;122";
|
||||||
COLOR_ALT_BG = "2;46;43;46";
|
COLOR_ALT_BG = "2;46;43;46";
|
||||||
COLOR_NUMBER_FG = "2;150;139;57";
|
COLOR_NUMBER_FG = "2;150;139;57";
|
||||||
|
@ -249,6 +304,15 @@ static char * syn_sh_keywords[] = {
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int variable_char(uint8_t c) {
|
||||||
|
if (c >= 'A' && c <= 'Z') return 1;
|
||||||
|
if (c >= 'a' && c <= 'z') return 1;
|
||||||
|
if (c >= '0' && c <= '9') return 1;
|
||||||
|
if (c == '_') return 1;
|
||||||
|
if (c == '?') return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int syn_sh_extended(line_t * line, int i, int c, int last, int * out_left) {
|
static int syn_sh_extended(line_t * line, int i, int c, int last, int * out_left) {
|
||||||
(void)last;
|
(void)last;
|
||||||
|
|
||||||
|
@ -274,6 +338,23 @@ static int syn_sh_extended(line_t * line, int i, int c, int last, int * out_left
|
||||||
return FLAG_STRING;
|
return FLAG_STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (line->text[i].codepoint == '$' && last != '\\') {
|
||||||
|
if (i < line->actual - 1 && line->text[i+1].codepoint == '{') {
|
||||||
|
int j = i + 2;
|
||||||
|
for (; j < line->actual+1; ++j) {
|
||||||
|
if (line->text[j].codepoint == '}') break;
|
||||||
|
}
|
||||||
|
*out_left = (j - i);
|
||||||
|
return FLAG_NUMERAL;
|
||||||
|
}
|
||||||
|
int j = i + 1;
|
||||||
|
for (; j < line->actual + 1; ++j) {
|
||||||
|
if (!variable_char(line->text[j].codepoint)) break;
|
||||||
|
}
|
||||||
|
*out_left = (j - i) - 1;
|
||||||
|
return FLAG_NUMERAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (line->text[i].codepoint == '"') {
|
if (line->text[i].codepoint == '"') {
|
||||||
int last = 0;
|
int last = 0;
|
||||||
for (int j = i+1; j < line->actual + 1; ++j) {
|
for (int j = i+1; j < line->actual + 1; ++j) {
|
||||||
|
@ -590,6 +671,15 @@ static void recalculate_syntax(line_t * line) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int s = 0; s < shell_commands_len; ++s) {
|
||||||
|
int c = check_line(line, i, shell_commands[s], last);
|
||||||
|
if (c == 1) {
|
||||||
|
left = strlen(shell_commands[s])-1;
|
||||||
|
state = FLAG_KEYWORD;
|
||||||
|
goto _continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_continue:
|
_continue:
|
||||||
line->text[i].flags = state;
|
line->text[i].flags = state;
|
||||||
}
|
}
|
||||||
|
@ -625,12 +715,22 @@ static line_t * line_insert(line_t * line, char_t c, int offset) {
|
||||||
/* There is one new character in the line */
|
/* There is one new character in the line */
|
||||||
line->actual += 1;
|
line->actual += 1;
|
||||||
|
|
||||||
recalculate_syntax(line);
|
if (!loading) {
|
||||||
|
recalculate_syntax(line);
|
||||||
|
}
|
||||||
|
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void get_size(void) {
|
||||||
|
struct winsize w;
|
||||||
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||||
|
width = w.ws_col - prompt_right_width;
|
||||||
|
}
|
||||||
|
|
||||||
static void place_cursor_actual(void) {
|
static void place_cursor_actual(void) {
|
||||||
|
get_size();
|
||||||
|
|
||||||
int x = prompt_width + 1 - offset;
|
int x = prompt_width + 1 - offset;
|
||||||
for (int i = 0; i < column; ++i) {
|
for (int i = 0; i < column; ++i) {
|
||||||
char_t * c = &the_line->text[i];
|
char_t * c = &the_line->text[i];
|
||||||
|
@ -670,7 +770,9 @@ static void line_delete(line_t * line, int offset) {
|
||||||
/* The line is one character shorter */
|
/* The line is one character shorter */
|
||||||
line->actual -= 1;
|
line->actual -= 1;
|
||||||
|
|
||||||
recalculate_syntax(line);
|
if (!loading) {
|
||||||
|
recalculate_syntax(line);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void delete_at_cursor(void) {
|
static void delete_at_cursor(void) {
|
||||||
|
@ -683,6 +785,22 @@ static void delete_at_cursor(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void delete_word(void) {
|
||||||
|
if (!the_line->actual) return;
|
||||||
|
if (!column) return;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (column > 0) {
|
||||||
|
line_delete(the_line, column);
|
||||||
|
column--;
|
||||||
|
if (offset > 0) offset--;
|
||||||
|
}
|
||||||
|
} while (column && the_line->text[column-1].codepoint != ' ');
|
||||||
|
|
||||||
|
render_line();
|
||||||
|
place_cursor_actual();
|
||||||
|
}
|
||||||
|
|
||||||
static void insert_char(uint32_t c) {
|
static void insert_char(uint32_t c) {
|
||||||
char_t _c;
|
char_t _c;
|
||||||
_c.codepoint = c;
|
_c.codepoint = c;
|
||||||
|
@ -692,8 +810,10 @@ static void insert_char(uint32_t c) {
|
||||||
the_line = line_insert(the_line, _c, column);
|
the_line = line_insert(the_line, _c, column);
|
||||||
|
|
||||||
column++;
|
column++;
|
||||||
render_line();
|
if (!loading) {
|
||||||
place_cursor_actual();
|
render_line();
|
||||||
|
place_cursor_actual();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cursor_left(void) {
|
static void cursor_left(void) {
|
||||||
|
@ -707,11 +827,28 @@ static void cursor_right(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void word_left(void) {
|
static void word_left(void) {
|
||||||
/* TODO */
|
if (column == 0) return;
|
||||||
|
column--;
|
||||||
|
while (column && the_line->text[column].codepoint == ' ') {
|
||||||
|
column--;
|
||||||
|
}
|
||||||
|
while (column > 0) {
|
||||||
|
if (the_line->text[column-1].codepoint == ' ') break;
|
||||||
|
column--;
|
||||||
|
}
|
||||||
|
place_cursor_actual();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void word_right(void) {
|
static void word_right(void) {
|
||||||
/* TODO */
|
/* TODO */
|
||||||
|
while (column < the_line->actual && the_line->text[column].codepoint == ' ') {
|
||||||
|
column++;
|
||||||
|
}
|
||||||
|
while (column < the_line->actual) {
|
||||||
|
column++;
|
||||||
|
if (the_line->text[column].codepoint == ' ') break;
|
||||||
|
}
|
||||||
|
place_cursor_actual();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cursor_home(void) {
|
static void cursor_home(void) {
|
||||||
|
@ -833,6 +970,12 @@ static void set_buffered(void) {
|
||||||
tcsetattr(STDOUT_FILENO, TCSAFLUSH, &old);
|
tcsetattr(STDOUT_FILENO, TCSAFLUSH, &old);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int tabbed;
|
||||||
|
|
||||||
|
static void dummy_redraw(rline_context_t * context) {
|
||||||
|
/* Do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
static int read_line(void) {
|
static int read_line(void) {
|
||||||
int cin;
|
int cin;
|
||||||
uint32_t c;
|
uint32_t c;
|
||||||
|
@ -846,6 +989,7 @@ static int read_line(void) {
|
||||||
while ((cin = getc(stdin))) {
|
while ((cin = getc(stdin))) {
|
||||||
if (!decode(&istate, &c, cin)) {
|
if (!decode(&istate, &c, cin)) {
|
||||||
if (timeout == 0) {
|
if (timeout == 0) {
|
||||||
|
if (c != '\t') tabbed = 0;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '\033':
|
case '\033':
|
||||||
if (timeout == 0) {
|
if (timeout == 0) {
|
||||||
|
@ -853,6 +997,27 @@ static int read_line(void) {
|
||||||
timeout++;
|
timeout++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
the_line->actual = 0;
|
||||||
|
set_colors(COLOR_ALT_FG, COLOR_ALT_BG);
|
||||||
|
printf("^C");
|
||||||
|
printf("\033[0m");
|
||||||
|
return 1;
|
||||||
|
case 4:
|
||||||
|
if (column == 0 && the_line->actual == 0) {
|
||||||
|
for (char *_c = "exit"; *_c; ++_c) {
|
||||||
|
insert_char(*_c);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
if (column < the_line->actual) {
|
||||||
|
line_delete(the_line, column+1);
|
||||||
|
if (offset > 0) offset--;
|
||||||
|
render_line();
|
||||||
|
place_cursor_actual();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case DELETE_KEY:
|
case DELETE_KEY:
|
||||||
case BACKSPACE_KEY:
|
case BACKSPACE_KEY:
|
||||||
delete_at_cursor();
|
delete_at_cursor();
|
||||||
|
@ -860,6 +1025,8 @@ static int read_line(void) {
|
||||||
case ENTER_KEY:
|
case ENTER_KEY:
|
||||||
/* Print buffer */
|
/* Print buffer */
|
||||||
return 1;
|
return 1;
|
||||||
|
case 23:
|
||||||
|
delete_word();
|
||||||
break;
|
break;
|
||||||
case 12: /* ^L - Repaint the whole screen */
|
case 12: /* ^L - Repaint the whole screen */
|
||||||
printf("\033[2J\033[H");
|
printf("\033[2J\033[H");
|
||||||
|
@ -868,6 +1035,55 @@ static int read_line(void) {
|
||||||
break;
|
break;
|
||||||
case '\t':
|
case '\t':
|
||||||
/* Tab complet e*/
|
/* Tab complet e*/
|
||||||
|
if (tab_complete_func) {
|
||||||
|
rline_context_t context = {0};
|
||||||
|
context.buffer = malloc(buf_size_max); /* TODO */
|
||||||
|
memset(context.buffer,0,buf_size_max);
|
||||||
|
unsigned int off = 0;
|
||||||
|
for (int j = 0; j < the_line->actual; j++) {
|
||||||
|
if (j == column) {
|
||||||
|
context.offset = off;
|
||||||
|
}
|
||||||
|
char_t c = the_line->text[j];
|
||||||
|
off += to_eight(c.codepoint, &context.buffer[off]);
|
||||||
|
}
|
||||||
|
if (column == the_line->actual) context.offset = off;
|
||||||
|
context.tabbed = tabbed;
|
||||||
|
rline_callbacks_t tmp = {0};
|
||||||
|
tmp.redraw_prompt = dummy_redraw;
|
||||||
|
context.callbacks = &tmp;
|
||||||
|
context.collected = off;
|
||||||
|
context.buffer[off] = '\0';
|
||||||
|
context.requested = 1024;
|
||||||
|
printf("\033[0m");
|
||||||
|
tab_complete_func(&context);
|
||||||
|
/* Now convert back */
|
||||||
|
loading = 1;
|
||||||
|
int final_column = 0;
|
||||||
|
the_line->actual = 0;
|
||||||
|
column = 0;
|
||||||
|
istate = 0;
|
||||||
|
for (int i = 0; i < context.collected; ++i) {
|
||||||
|
if (i == context.offset) {
|
||||||
|
final_column = column;
|
||||||
|
}
|
||||||
|
if (!decode(&istate, &c, context.buffer[i])) {
|
||||||
|
insert_char(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (context.offset == context.collected) {
|
||||||
|
column = the_line->actual;
|
||||||
|
} else {
|
||||||
|
column = final_column;
|
||||||
|
}
|
||||||
|
|
||||||
|
tabbed = context.tabbed;
|
||||||
|
|
||||||
|
loading = 0;
|
||||||
|
recalculate_syntax(the_line);
|
||||||
|
render_line();
|
||||||
|
place_cursor_actual();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
insert_char(c);
|
insert_char(c);
|
||||||
|
@ -888,15 +1104,18 @@ static int read_line(void) {
|
||||||
int rline_experimental(char * buffer, int buf_size) {
|
int rline_experimental(char * buffer, int buf_size) {
|
||||||
get_initial_termios();
|
get_initial_termios();
|
||||||
set_unbuffered();
|
set_unbuffered();
|
||||||
|
get_size();
|
||||||
struct winsize w;
|
|
||||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
|
||||||
width = w.ws_col - prompt_right_width;
|
|
||||||
|
|
||||||
column = 0;
|
column = 0;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
buf_size_max = buf_size;
|
||||||
|
|
||||||
load_colorscheme_sunsmoke();
|
char * theme = getenv("RLINE_THEME");
|
||||||
|
if (theme && !strcmp(theme,"sunsmoke")) { /* TODO bring back theme tables */
|
||||||
|
rline_exp_load_colorscheme_sunsmoke();
|
||||||
|
} else {
|
||||||
|
rline_exp_load_colorscheme_default();
|
||||||
|
}
|
||||||
|
|
||||||
the_line = line_create();
|
the_line = line_create();
|
||||||
read_line();
|
read_line();
|
||||||
|
|
|
@ -25,7 +25,7 @@ class Classifier(object):
|
||||||
'<toaru/graphics.h>': (None, '-ltoaru_graphics', []),
|
'<toaru/graphics.h>': (None, '-ltoaru_graphics', []),
|
||||||
'<toaru/drawstring.h>': (None, '-ltoaru_drawstring', ['<toaru/graphics.h>']),
|
'<toaru/drawstring.h>': (None, '-ltoaru_drawstring', ['<toaru/graphics.h>']),
|
||||||
'<toaru/rline.h>': (None, '-ltoaru_rline', ['<toaru/kbd.h>']),
|
'<toaru/rline.h>': (None, '-ltoaru_rline', ['<toaru/kbd.h>']),
|
||||||
'<toaru/rline_exp.h>': (None, '-ltoaru_rline_exp', ['<toaru/kbd.h>']),
|
'<toaru/rline_exp.h>': (None, '-ltoaru_rline_exp', ['<toaru/rline.h>']),
|
||||||
'<toaru/confreader.h>': (None, '-ltoaru_confreader', ['<toaru/hashmap.h>']),
|
'<toaru/confreader.h>': (None, '-ltoaru_confreader', ['<toaru/hashmap.h>']),
|
||||||
'<toaru/yutani.h>': (None, '-ltoaru_yutani', ['<toaru/kbd.h>', '<toaru/list.h>', '<toaru/pex.h>', '<toaru/graphics.h>', '<toaru/hashmap.h>']),
|
'<toaru/yutani.h>': (None, '-ltoaru_yutani', ['<toaru/kbd.h>', '<toaru/list.h>', '<toaru/pex.h>', '<toaru/graphics.h>', '<toaru/hashmap.h>']),
|
||||||
'<toaru/decorations.h>': (None, '-ltoaru_decorations', ['<toaru/menu.h>', '<toaru/sdf.h>', '<toaru/graphics.h>', '<toaru/yutani.h>']),
|
'<toaru/decorations.h>': (None, '-ltoaru_decorations', ['<toaru/menu.h>', '<toaru/sdf.h>', '<toaru/graphics.h>', '<toaru/yutani.h>']),
|
||||||
|
|
Loading…
Reference in New Issue