diff --git a/bshell/CMakeLists.txt b/bshell/CMakeLists.txt index a1f2233..496fad6 100644 --- a/bshell/CMakeLists.txt +++ b/bshell/CMakeLists.txt @@ -1,6 +1,4 @@ -set(source_dirs - ast compile parse parse/lex parse/syntax - runtime format command cmdlets aliases) +set(source_dirs) if (bshell_interactive EQUAL 1) message(STATUS "Interactive support: Enabled") diff --git a/bshell/frontend.c b/bshell/frontend.c index a9c57b2..519e27a 100644 --- a/bshell/frontend.c +++ b/bshell/frontend.c @@ -10,7 +10,12 @@ #include #if BSHELL_INTERACTIVE == 1 -#include "line-ed/line-ed.h" +#include +#include +#include +#include +#include +#include #endif #define FRONTEND_FLAG_SET(f, flag) \ @@ -230,13 +235,27 @@ enum bshell_status frontend_eval_file( enum bshell_status frontend_repl(struct frontend_ctx *ctx) { #if BSHELL_INTERACTIVE - struct line_ed *ed = line_ed_create(); + bshell_line_ed_core *ed_core = bshell_line_ed_core_create(); + bshell_line_ed_highlight *ed_highlight + = bshell_line_ed_highlight_create(); + bshell_line_ed_syntax *ed_syntax = bshell_line_ed_syntax_create(); + bshell_line_ed_shell_integration *ed_shell + = bshell_line_ed_shell_integration_create(ctx->ctx_rt); + bshell_line_ed *ed = bshell_line_ed_create(); + bshell_line_ed_add_plugin(ed, ed_core); + bshell_line_ed_add_plugin(ed, ed_highlight); + bshell_line_ed_add_plugin(ed, ed_syntax); + bshell_line_ed_add_plugin(ed, ed_shell); - struct bshell_line_source *linesrc = line_ed_to_line_source(ed); + struct bshell_line_source *linesrc = bshell_line_ed_get_line_source(ed); ctx->ctx_status = eval(ctx, linesrc, EVAL_PRINT_RESULT); - line_ed_destroy(ed); + bshell_line_ed_unref(ed); + bshell_line_ed_plugin_unref(ed_shell); + bshell_line_ed_plugin_unref(ed_syntax); + bshell_line_ed_plugin_unref(ed_highlight); + bshell_line_ed_plugin_unref(ed_core); return ctx->ctx_status; #else diff --git a/bshell/line-ed/buffer.c b/bshell/line-ed/buffer.c deleted file mode 100644 index c0748d5..0000000 --- a/bshell/line-ed/buffer.c +++ /dev/null @@ -1,43 +0,0 @@ -#include "buffer.h" - -#include "line-ed.h" - -#include - -const fx_wchar *line_start(struct line_ed *ed, size_t y) -{ - const fx_wchar *line = ed->l_buf; - - for (size_t i = 0; i < y; i++) { - line += fx_wstrcspn(line, L"\n"); - - if (*line == '\n') { - line++; - } - } - - return line; -} - -size_t line_length(struct line_ed *ed, size_t y) -{ - const fx_wchar *line = ed->l_buf; - - for (size_t i = 0; i < y; i++) { - line += fx_wstrcspn(line, L"\n"); - if (*line == '\n') { - line++; - } - } - - if (*line == '\0') { - return 0; - } - - size_t len = fx_wstrcspn(line, L"\n"); - if (line[len] == '\n') { - len++; - } - - return len; -} diff --git a/bshell/line-ed/buffer.h b/bshell/line-ed/buffer.h deleted file mode 100644 index a77af4c..0000000 --- a/bshell/line-ed/buffer.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef LINE_ED_BUFFER_H_ -#define LINE_ED_BUFFER_H_ - -#include -#include - -struct line_ed; - -/* returns a pointer to the start of the line based on the given `y` - * coordinate */ -extern const fx_wchar *line_start(struct line_ed *ed, size_t y); -/* returns the length of the line based on the given `y` coordinate. - * for any line other than the last line in the buffer, this length - * INCLUDES the trailing linefeed. */ -extern size_t line_length(struct line_ed *ed, size_t y); - -#endif diff --git a/bshell/line-ed/cursor.c b/bshell/line-ed/cursor.c deleted file mode 100644 index 70a644d..0000000 --- a/bshell/line-ed/cursor.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "line-ed.h" -#include "cursor.h" -#include "prompt.h" - -void line_ed_coords_to_physical_coords( - struct line_ed *ed, size_t x, size_t y, size_t *out_x, size_t *out_y) -{ - size_t prompt_len = 0; - if (ed->l_cursor_y == 0) { - prompt_len = prompt_length(ed, PROMPT_MAIN); - } else if (ed->l_cursor_y <= ed->l_continuations) { - prompt_len = prompt_length(ed, PROMPT_CONT); - } - - if (y == 0) { - x += prompt_len; - } - - if (out_x) { - *out_x = x; - } - - if (out_y) { - *out_y = y; - } -} diff --git a/bshell/line-ed/cursor.h b/bshell/line-ed/cursor.h deleted file mode 100644 index 3d8a4b4..0000000 --- a/bshell/line-ed/cursor.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef LINE_ED_CURSOR_H_ -#define LINE_ED_CURSOR_H_ - -struct line_ed; - -extern void line_ed_coords_to_physical_coords( - struct line_ed *ed, size_t x, size_t y, size_t *out_x, size_t *out_y); - -#endif diff --git a/bshell/line-ed/history.c b/bshell/line-ed/history.c deleted file mode 100644 index c70bf22..0000000 --- a/bshell/line-ed/history.c +++ /dev/null @@ -1,87 +0,0 @@ -#include "../misc.h" -#include "line-ed.h" - -#include -#include - -void alloc_empty_history_entry(struct line_ed *ed) -{ - fx_value *str_v = fx_array_get_ref( - ed->l_history, - fx_array_get_size(ed->l_history) - 1); - fx_string *str = NULL; - fx_value_get_object(str_v, &str); - if (!str || fx_string_get_size(str, FX_STRLEN_NORMAL) > 0) { - str = fx_string_create(); - fx_array_push_back(ed->l_history, FX_VALUE_OBJECT(str)); - fx_string_unref(str); - } - - ed->l_history_pos = fx_array_get_size(ed->l_history) - 1; -} - -void save_buf_to_history(struct line_ed *ed) -{ - fx_value *cur_v = fx_array_get_ref(ed->l_history, ed->l_history_pos); - fx_string *cur = NULL; - fx_value_get_object(cur_v, &cur); - fx_string_clear(cur); - fx_string_append_wstr(cur, ed->l_buf); -} - -void append_buf_to_history(struct line_ed *ed) -{ - fx_value *cur_v = fx_array_get_ref(ed->l_history, ed->l_history_pos); - fx_string *cur = NULL; - fx_value_get_object(cur_v, &cur); - char s[] = {'\n', 0}; - fx_string_append_cstr(cur, s); - fx_string_append_wstr(cur, ed->l_buf); -} - -void load_buf_from_history(struct line_ed *ed) -{ - fx_value *cur_v = fx_array_get_ref(ed->l_history, ed->l_history_pos); - fx_string *cur = NULL; - fx_value_get_object(cur_v, &cur); - size_t len = MIN( - (size_t)(ed->l_buf_end - ed->l_buf - 1), - fx_string_get_size(cur, FX_STRLEN_CODEPOINTS)); - - const char *src = fx_string_get_cstr(cur); - for (size_t i = 0; i < len; i++) { - fx_wchar ch_src = fx_wchar_utf8_codepoint_decode(src); - ed->l_buf[i] = ch_src; - src += fx_wchar_utf8_codepoint_stride(src); - } - - ed->l_buf[len] = '\0'; - - unsigned int x = 0, y = 0; - for (size_t i = 0; ed->l_buf[i]; i++) { - if (ed->l_buf[i] == '\n') { - x = 0; - y++; - } else { - x++; - } - } - - ed->l_buf_ptr = ed->l_buf + len; - ed->l_line_end = ed->l_buf_ptr; - ed->l_cursor_x = x; - ed->l_cursor_y = y; -} - -const char *last_history_line(struct line_ed *ed) -{ - size_t nlines = fx_array_get_size(ed->l_history); - if (nlines < 2) { - return NULL; - } - - fx_value *last_v = fx_array_get_ref(ed->l_history, nlines - 2); - fx_string *last = NULL; - fx_value_get_object(last_v, &last); - return fx_string_get_cstr(last); -} diff --git a/bshell/line-ed/history.h b/bshell/line-ed/history.h deleted file mode 100644 index d166aa2..0000000 --- a/bshell/line-ed/history.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef LINE_ED_HISTORY_H_ -#define LINE_ED_HISTORY_H_ - -struct line_ed; - -extern void alloc_empty_history_entry(struct line_ed *ed); -extern void save_buf_to_history(struct line_ed *ed); -extern void append_buf_to_history(struct line_ed *ed); -extern void load_buf_from_history(struct line_ed *ed); -extern const char *last_history_line(struct line_ed *ed); - -#endif diff --git a/bshell/line-ed/hook.c b/bshell/line-ed/hook.c deleted file mode 100644 index cb8e8f4..0000000 --- a/bshell/line-ed/hook.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "hook.h" - -#include "line-ed.h" - -void line_ed_add_hook(struct line_ed *ed, struct line_ed_hook *hook) -{ - fx_queue_push_back(&ed->l_hooks, &hook->hook_entry); -} - -void line_ed_remove_hook(struct line_ed *ed, struct line_ed_hook *hook) -{ - fx_queue_delete(&ed->l_hooks, &hook->hook_entry); -} - -void hook_keypress(struct line_ed *ed, fx_keycode key) -{ - fx_queue_entry *entry = fx_queue_first(&ed->l_hooks); - while (entry) { - struct line_ed_hook *hook - = fx_unbox(struct line_ed_hook, entry, hook_entry); - if (hook->hook_keypress) { - hook->hook_keypress(ed, hook, key); - } - - entry = fx_queue_next(entry); - } -} - -void hook_buffer_modified(struct line_ed *ed) -{ - fx_queue_entry *entry = fx_queue_first(&ed->l_hooks); - while (entry) { - struct line_ed_hook *hook - = fx_unbox(struct line_ed_hook, entry, hook_entry); - if (hook->hook_buffer_modified) { - hook->hook_buffer_modified(ed, hook); - } - - entry = fx_queue_next(entry); - } -} diff --git a/bshell/line-ed/hook.h b/bshell/line-ed/hook.h deleted file mode 100644 index 613344a..0000000 --- a/bshell/line-ed/hook.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef LINE_ED_HOOK_H_ -#define LINE_ED_HOOK_H_ - -#include - -enum hook_id { - HOOK_KEYPRESS, - HOOK_BEFORE_PAINT, -}; - -struct line_ed; - -extern void hook_keypress(struct line_ed *ed, fx_keycode key); -extern void hook_buffer_modified(struct line_ed *ed); - -#endif diff --git a/bshell/line-ed/input.c b/bshell/line-ed/input.c deleted file mode 100644 index 3ea9624..0000000 --- a/bshell/line-ed/input.c +++ /dev/null @@ -1,232 +0,0 @@ -#include "buffer.h" -#include "cursor.h" -#include "history.h" -#include "hook.h" -#include "line-ed.h" -#include "prompt.h" -#include "refresh.h" - -#include - -void put_char(struct line_ed *ed, fx_wchar c) -{ - if (ed->l_buf_ptr > ed->l_line_end + 1) { - return; - } - - struct refresh_state state = { - .r_prev_cursor_x = ed->l_cursor_x, - .r_prev_cursor_y = ed->l_cursor_y, - }; - - size_t prev_cursor = ed->l_buf_ptr - ed->l_buf; - - fx_wchar *dest = ed->l_buf_ptr; - size_t len = (ed->l_line_end - ed->l_buf_ptr + 1) * sizeof *dest; - - if (dest < ed->l_line_end) { - memmove(dest + 1, dest, len); - } - - ed->l_cursor_x++; - ed->l_line_end++; - ed->l_buf_ptr++; - *dest = c; - - if (ed->l_buf_ptr == ed->l_line_end) { - *ed->l_buf_ptr = '\0'; - } - - hook_buffer_modified(ed); - - put_refresh(ed, &state); -} - -static void backspace_simple(struct line_ed *ed) -{ - if (ed->l_buf_ptr == ed->l_buf) { - return; - } - - struct refresh_state state = { - .r_prev_cursor_x = ed->l_cursor_x, - .r_prev_cursor_y = ed->l_cursor_y, - }; - - size_t prev_cursor = ed->l_buf_ptr - ed->l_buf; - - fx_wchar *dest = ed->l_buf_ptr; - size_t len = (ed->l_line_end - ed->l_buf_ptr + 1) * sizeof *dest; - memmove(dest - 1, dest, len); - - ed->l_cursor_x--; - ed->l_line_end--; - ed->l_buf_ptr--; - - hook_buffer_modified(ed); - - backspace_simple_refresh(ed, &state); -} - -static void backspace_nl(struct line_ed *ed) -{ - size_t prev_line_len = line_length(ed, ed->l_cursor_y - 1); - - struct refresh_state state = { - .r_prev_cursor_x = ed->l_cursor_x, - .r_prev_cursor_y = ed->l_cursor_y, - .r_prev_line_len = prev_line_len, - }; - - fx_wchar *dest = ed->l_buf_ptr; - size_t len = (ed->l_line_end - ed->l_buf_ptr + 1) * sizeof *dest; - memmove(dest - 1, dest, len); - - ed->l_cursor_x = prev_line_len - 1; - ed->l_cursor_y--; - ed->l_buf_ptr--; - ed->l_line_end--; - - hook_buffer_modified(ed); - - backspace_nl_refresh(ed, &state); -} - -void backspace(struct line_ed *ed) -{ - if (ed->l_buf_ptr == ed->l_buf) { - return; - } - - if (ed->l_cursor_x == 0 && ed->l_cursor_y <= ed->l_continuations) { - return; - } - - if (ed->l_cursor_x == 0 && ed->l_cursor_y > 0) { - backspace_nl(ed); - } else { - backspace_simple(ed); - } -} - -void cursor_left(struct line_ed *ed) -{ - if (ed->l_cursor_x != 0) { - // fputs("\010", stdout); - fx_tty_move_cursor_x(ed->l_tty, FX_TTY_POS_CURSOR, -1); - fflush(stdout); - ed->l_cursor_x--; - ed->l_buf_ptr--; - return; - } - - if (ed->l_cursor_y <= ed->l_continuations - || ed->l_buf_ptr <= ed->l_buf) { - return; - } - - ed->l_cursor_y--; - ed->l_buf_ptr--; - size_t prompt_len = 0; - if (ed->l_cursor_y == 0) { - prompt_len = prompt_length(ed, PROMPT_MAIN); - } - - size_t len = line_length(ed, ed->l_cursor_y); - ed->l_cursor_x = len - 1; - - // printf("\033[A\033[%dG", len + prompt_len); - fx_tty_move_cursor_y(ed->l_tty, FX_TTY_POS_CURSOR, -1); - fx_tty_move_cursor_x( - ed->l_tty, - FX_TTY_POS_START, - (int)(len + prompt_len)); - - fflush(stdout); -} - -void cursor_right(struct line_ed *ed) -{ - if (ed->l_buf_ptr >= ed->l_line_end) { - return; - } - - if (*ed->l_buf_ptr != '\n') { - ed->l_cursor_x++; - ed->l_buf_ptr++; - // fputs("\033[C", stdout); - fx_tty_move_cursor_x(ed->l_tty, FX_TTY_POS_CURSOR, 1); - fflush(stdout); - return; - } - - if (ed->l_buf_ptr >= ed->l_line_end) { - return; - } - - ed->l_cursor_y++; - ed->l_cursor_x = 0; - ed->l_buf_ptr++; - - // printf("\033[B\033[G"); - fx_tty_move_cursor_y(ed->l_tty, FX_TTY_POS_CURSOR, 1); - fx_tty_move_cursor_x(ed->l_tty, FX_TTY_POS_START, 0); - fflush(stdout); -} - -void arrow_up(struct line_ed *ed) -{ - if (ed->l_history_pos == 0) { - return; - } - - if (ed->l_cursor_y > 0) { - // printf("\033[%uA", ed->l_cursor_y); - fx_tty_move_cursor_y( - ed->l_tty, - FX_TTY_POS_CURSOR, - (long long)ed->l_cursor_y); - } - - // printf("\033[%zuG\033[J", prompt_length(ed, PROMPT_MAIN) + 1); - fx_tty_move_cursor_x( - ed->l_tty, - FX_TTY_POS_START, - (long long)prompt_length(ed, PROMPT_MAIN)); - fx_tty_clear(ed->l_tty, FX_TTY_CLEAR_SCREEN | FX_TTY_CLEAR_FROM_CURSOR); - - save_buf_to_history(ed); - ed->l_history_pos--; - load_buf_from_history(ed); - - print_buffer(ed); - fflush(stdout); -} - -void arrow_down(struct line_ed *ed) -{ - if (ed->l_history_pos == fx_array_get_size(ed->l_history) - 1) { - return; - } - - if (ed->l_cursor_y > 0) { - // printf("\033[%uA", ed->l_cursor_y); - fx_tty_move_cursor_y( - ed->l_tty, - FX_TTY_POS_CURSOR, - (int)ed->l_cursor_y); - } - - // printf("\033[%zuG\033[J", prompt_length(ed, PROMPT_MAIN) + 1); - fx_tty_move_cursor_x( - ed->l_tty, - FX_TTY_POS_START, - prompt_length(ed, PROMPT_MAIN) + 1); - - save_buf_to_history(ed); - ed->l_history_pos++; - load_buf_from_history(ed); - - print_buffer(ed); - fflush(stdout); -} diff --git a/bshell/line-ed/input.h b/bshell/line-ed/input.h deleted file mode 100644 index 26b8255..0000000 --- a/bshell/line-ed/input.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef LINE_ED_INPUT_H_ -#define LINE_ED_INPUT_H_ - -#include - -struct line_ed; - -extern void put_char(struct line_ed *ed, fx_wchar c); -extern void backspace(struct line_ed *ed); -extern void cursor_left(struct line_ed *ed); -extern void cursor_right(struct line_ed *ed); -extern void arrow_up(struct line_ed *ed); -extern void arrow_down(struct line_ed *ed); - -#endif diff --git a/bshell/line-ed/line-ed.c b/bshell/line-ed/line-ed.c deleted file mode 100644 index f2687c4..0000000 --- a/bshell/line-ed/line-ed.c +++ /dev/null @@ -1,302 +0,0 @@ -#include "line-ed.h" - -#include "history.h" -#include "hook.h" -#include "input.h" -#include "prompt.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#define LINE_ED_FROM_LEX_SOURCE(p) \ - ((struct line_ed *)((char *)p \ - - offsetof(struct line_ed, l_line_source))) - -static enum bshell_status readline( - struct bshell_line_source *src, - fx_stringstream *out) -{ - struct line_ed *ed = LINE_ED_FROM_LEX_SOURCE(src); - - long r = line_ed_readline(ed, out); - line_ed_set_scope_type(ed, NULL); - - if (r < 0) { - return BSHELL_ERR_EOF; - } - - return BSHELL_SUCCESS; -} - -struct line_ed *line_ed_create(void) -{ - struct line_ed *out = malloc(sizeof *out); - if (!out) { - return NULL; - } - - memset(out, 0x0, sizeof *out); - - out->l_buf = malloc(LINE_MAX); - if (!out->l_buf) { - free(out); - return NULL; - } - - out->l_history = fx_array_create(); - if (!out->l_history) { - free(out->l_buf); - free(out); - return NULL; - } - - out->l_tty = fx_stdtty; - out->l_buf_end = out->l_buf + LINE_MAX; - out->l_buf_ptr = out->l_buf; - out->l_line_end = out->l_buf; - - out->l_prompt[PROMPT_MAIN] = ">>> "; - out->l_prompt[PROMPT_CONT] = "> "; - - out->l_line_source.s_readline = readline; - - return out; -} - -void line_ed_destroy(struct line_ed *ed) -{ - fx_array_unref(ed->l_history); - free(ed->l_buf); - free(ed); -} - -void line_ed_set_flags(struct line_ed *ed, enum line_ed_flags flags) -{ - ed->l_flags |= flags; -} - -void line_ed_set_scope_type(struct line_ed *ed, const char *scope_type) -{ - ed->l_scope_type = scope_type; -} - -static void clear_buffer(struct line_ed *ed) -{ - memset(ed->l_buf, 0x0, ed->l_buf_end - ed->l_buf); - - ed->l_buf_ptr = ed->l_buf; - ed->l_line_end = ed->l_buf; - - ed->l_cursor_x = 0; - ed->l_cursor_y = 0; - - ed->l_continuations = 0; -} - -static void convert_continuation_feeds(fx_wchar *s, size_t max) -{ - fx_wchar *end = s + max; - size_t len = fx_wstrlen(s); - - while (1) { - size_t r = fx_wstrcspn(s, L"\\"); - if (s + r > end) { - break; - } - - s += r; - len -= r; - - if (*s == '\0') { - break; - } - - if (*(s + 1) != '\n') { - s++; - continue; - } - - memmove(s, s + 1, len); - s += 1; - } -} - -static void remove_continuation_feeds(fx_wchar *s, size_t max) -{ - fx_wchar *end = s + max; - size_t len = fx_wstrlen(s); - - while (1) { - size_t r = fx_wstrcspn(s, L"\\"); - if (s + r > end) { - break; - } - - s += r; - len -= r; - - if (*s == '\0') { - break; - } - - if (*(s + 1) != '\n') { - s++; - continue; - } - - memmove(s, s + 2, len); - s += 2; - } -} - -static bool input_is_empty(struct line_ed *ed) -{ - const fx_wchar *p = ed->l_buf; - while (p < ed->l_line_end) { - if (!fx_wchar_is_space(*p)) { - return false; - } - } - - return true; -} - -size_t line_ed_readline(struct line_ed *ed, fx_stringstream *out) -{ - clear_buffer(ed); - - bool append_history = false; - size_t append_to_index = (size_t)-1; - if (!ed->l_scope_type) { - alloc_empty_history_entry(ed); - } else { - append_history = true; - append_to_index = ed->l_history_pos; - } - - fx_tty *tty = ed->l_tty; - fx_tty_set_mode(tty, FX_TTY_RAW); - show_prompt(ed); - - for (int i = 0; ed->l_buf[i]; i++) { - if (ed->l_buf[i] == '\n') { - fputc('\r', stdout); - } - - fx_stream_write_char(fx_stdout, ed->l_buf[i]); - } - fflush(stdout); - - bool end = false; - bool eof = false; - - while (!end) { - fx_keycode key = fx_tty_read_key(tty); - hook_keypress(ed, key); - - if (key == FX_TTY_CTRL_KEY('d')) { - if (!input_is_empty(ed)) { - continue; - } - - eof = true; - break; - } - - if (key & FX_MOD_CTRL) { - continue; - } - - switch (key) { - case FX_KEY_RETURN: - fx_tty_reset_vmode(tty); - if (ed->l_line_end > ed->l_buf - && *(ed->l_line_end - 1) != '\\') { - end = true; - break; - } - - if (input_is_empty(ed)) { - fputc('\r', stdout); - fputc('\n', stdout); - clear_buffer(ed); - show_prompt(ed); - break; - } - - *ed->l_line_end = '\n'; - ed->l_line_end++; - ed->l_buf_ptr = ed->l_line_end; - - ed->l_cursor_x = 0; - ed->l_cursor_y++; - ed->l_continuations++; - fputc('\r', stdout); - fputc('\n', stdout); - // fputs("\033[G\n", stdout); - show_prompt(ed); - break; - case FX_KEY_BACKSPACE: - backspace(ed); - break; - case FX_KEY_ARROW_LEFT: - cursor_left(ed); - break; - case FX_KEY_ARROW_RIGHT: - cursor_right(ed); - break; - case FX_KEY_ARROW_UP: - arrow_up(ed); - break; - case FX_KEY_ARROW_DOWN: - arrow_down(ed); - break; - default: - if (fx_wchar_is_graph(key) || key == ' ') { - put_char(ed, key); - } - break; - } - } - - fx_tty_set_mode(tty, FX_TTY_CANONICAL); - fputc('\n', stdout); - - if (*ed->l_buf == '\0') { - return eof ? -1 : 0; - } - - if (append_history) { - ed->l_history_pos = append_to_index; - append_buf_to_history(ed); - } else { - ed->l_history_pos = fx_array_get_size(ed->l_history) - 1; - - const char *last = last_history_line(ed); - if (!last || fx_wastrcmp(last, ed->l_buf) != 0) { - save_buf_to_history(ed); - } - } - - size_t sz = ed->l_line_end - ed->l_buf + 1; - - if ((ed->l_flags & LINE_ED_REMOVE_CONTINUATIONS) - == LINE_ED_REMOVE_CONTINUATIONS) { - remove_continuation_feeds(ed->l_buf, sz); - } else if ( - (ed->l_flags & LINE_ED_CONVERT_CONTINUATIONS) - == LINE_ED_CONVERT_CONTINUATIONS) { - convert_continuation_feeds(ed->l_buf, sz); - } - - fx_stream_write_wstr(out, ed->l_buf, NULL); - fx_stream_write_char(out, '\n'); - - return sz; -} diff --git a/bshell/line-ed/line-ed.h b/bshell/line-ed/line-ed.h deleted file mode 100644 index 211900e..0000000 --- a/bshell/line-ed/line-ed.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef LINE_ED_H_ -#define LINE_ED_H_ - -#define LINE_MAX 4096 - -#include -#include -#include -#include -#include - -struct s_tty; -struct fx_tty_vmode; - -struct line_ed; - -struct line_ed_hook { - void (*hook_keypress)( - struct line_ed *, - struct line_ed_hook *, - fx_keycode); - void (*hook_buffer_modified)(struct line_ed *, struct line_ed_hook *); - fx_queue_entry hook_entry; -}; - -enum line_ed_flags { - /* always reprint an entire line when a character is added/deleted. - * without this flag, only the modified character any subsequent - * characters are reprinted. */ - LINE_ED_FULL_REPRINT = 0x01u, - - /* keep line continuation (backslash-newline) tokens in the output - * buffer (default behaviour) */ - LINE_ED_KEEP_CONTINUATIONS = 0x00u, - /* convert line continuation tokens in the output buffer to simple - * linefeeds. */ - LINE_ED_CONVERT_CONTINUATIONS = 0x02u, - /* remove line continuation tokens from the output buffer, so that all - * chars are on a single line */ - LINE_ED_REMOVE_CONTINUATIONS = 0x06u, -}; - -struct line_ed { - enum line_ed_flags l_flags; - - /* array of basic prompt strings */ - const char *l_prompt[2]; - /* input buffer, pointer to the buffer cell that corresponds to - * the current cursor position, and pointer to the byte AFTER the last - * usable byte in the buffer */ - fx_wchar *l_buf, *l_buf_ptr, *l_buf_end; - /* pointer to the byte AFTER the last byte of the user's input */ - fx_wchar *l_line_end; - /* 2-dimensional coordinates of the current cursor position. - * this does NOT include any prompts that are visible on the terminal */ - size_t l_cursor_x, l_cursor_y; - /* the number of line continuations that have been inputted */ - unsigned int l_continuations; - - struct bshell_line_source l_line_source; - - /* pointer to tty interface */ - fx_tty *l_tty; - - /* the lexical scope that we are currently in. - * this is provided by components further up the input pipeline, - * for example, when we are inside a string or if-statement. */ - const char *l_scope_type; - - /* array of previously entered commands */ - fx_array *l_history; - /* index of the currently selected history entry */ - size_t l_history_pos; - - /* list of defined highlight ranges */ - fx_queue l_hl_ranges; - /* list of installed hooks */ - fx_queue l_hooks; -}; - -extern struct line_ed *line_ed_create(void); -extern void line_ed_destroy(struct line_ed *ed); -extern void line_ed_set_flags(struct line_ed *ed, enum line_ed_flags flags); -extern void line_ed_set_scope_type(struct line_ed *ed, const char *scope_type); - -extern void line_ed_put_highlight( - struct line_ed *ed, - unsigned long start_x, - unsigned long start_y, - unsigned long end_x, - unsigned long end_y, - const struct fx_tty_vmode *vmode); -extern void line_ed_clear_highlights(struct line_ed *ed); -extern void line_ed_print_highlights(struct line_ed *ed); - -extern void line_ed_add_hook(struct line_ed *ed, struct line_ed_hook *hook); -extern void line_ed_remove_hook(struct line_ed *ed, struct line_ed_hook *hook); - -extern size_t line_ed_readline(struct line_ed *ed, fx_stringstream *out); - -static inline struct bshell_line_source *line_ed_to_line_source( - struct line_ed *ed) -{ - return &ed->l_line_source; -} - -#endif diff --git a/bshell/line-ed/prompt.c b/bshell/line-ed/prompt.c deleted file mode 100644 index 963109c..0000000 --- a/bshell/line-ed/prompt.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include "line-ed.h" -#include "prompt.h" - -void show_prompt(struct line_ed *ed) -{ - int type = PROMPT_MAIN; - if (ed->l_scope_type) { - type = PROMPT_CONT; - - /* this is a temporary solution to show the current - * scope type, until prompts are implemented properly. */ - fputs(ed->l_scope_type, stdout); - } - - if (ed->l_continuations > 0) { - type = PROMPT_CONT; - } - - fputs(ed->l_prompt[type], stdout); - fflush(stdout); -} - -size_t prompt_length(struct line_ed *ed, int prompt_id) -{ - return strlen(ed->l_prompt[prompt_id]); -} diff --git a/bshell/line-ed/prompt.h b/bshell/line-ed/prompt.h deleted file mode 100644 index eb135e3..0000000 --- a/bshell/line-ed/prompt.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef LINE_ED_PROMPT_H_ -#define LINE_ED_PROMPT_H_ - -#define PROMPT_MAIN 0 -#define PROMPT_CONT 1 - -struct line_ed; - -extern void show_prompt(struct line_ed *ed); -extern size_t prompt_length(struct line_ed *ed, int prompt_id); - -#endif diff --git a/bshell/line-ed/refresh.c b/bshell/line-ed/refresh.c deleted file mode 100644 index fc87419..0000000 --- a/bshell/line-ed/refresh.c +++ /dev/null @@ -1,266 +0,0 @@ -#include "refresh.h" - -#include "buffer.h" -#include "cursor.h" -#include "line-ed.h" - -#include -#include -#include -#include - -/* prints the provided string to the terminal, applying any relevant highlight - * ranges. this function prints all characters in `s` until it encounters a null - * char (\0) or linefeed (\n). - * - * the (x, y) coordinates provided should be the data coordinates of the - * first character in `s`. - */ -void print_text(struct line_ed *ed, size_t x, size_t y, const fx_wchar *s) -{ - fx_tty *tty = ed->l_tty; - - for (size_t i = 0; s[i] != '\n' && s[i] != '\0'; i++) { - fx_stream_write_char(fx_stdout, s[i]); - } -} - -void print_buffer(struct line_ed *ed) -{ - const fx_wchar *line_buf = ed->l_buf; - size_t line_len = fx_wstrcspn(line_buf, L"\n"); - - unsigned int y = 0; - - while (1) { - print_text(ed, 0, y, line_buf); - - line_buf += line_len; - if (*line_buf == '\n') { - line_buf++; - } - - if (*line_buf == '\0') { - break; - } - - y++; - line_len = fx_wstrcspn(line_buf, L"\n"); - - fputc('\r', stdout); - fputc('\n', stdout); - } -} - -/* this function is called after a character is inserted into the line_ed - *buffer. the function performs the following steps: - * 1. get a pointer to the start of the line that was modified. - * 2. determine the first character in the line that needs to be redrawn. - * this may result in an append, a partial reprint, or a full reprint. - * 3. re-print the relevant portion of the buffer: - * for an append (a character added to the end of the line): - * * write the inserted char to the terminal. - * * done. - * for a partial reprint: - * * clear all printed chars from the logical cursor position to - *the end of the line. - * * print the portion of the line corresponding to the cleared - *section. - * * move the physical (terminal) cursor backwards until its - *position matches the logical (line_ed) cursor. for a full reprint: - * * same as a partial reprint except that, rather than reprinting - * from the logical cursor position, the entire line is - *reprinted. - */ -void put_refresh(struct line_ed *ed, struct refresh_state *state) -{ - /* get the data for the line that is being refreshed */ - const fx_wchar *line_buf = line_start(ed, ed->l_cursor_y); - size_t line_len = fx_wstrcspn(line_buf, L"\n"); - - /* the index of the first char in line_buf that needs to be reprinted */ - size_t start_x = state->r_prev_cursor_x; - - /* the distance between the first char to be reprinted and the end - * of the line. - * the physical cursor will be moved back by this amount after the - * line is reprinted. */ - long cursor_rdelta = (long)(line_len - start_x); - - if (ed->l_flags & LINE_ED_FULL_REPRINT) { - if (start_x) { - // fprintf(stdout, "\033[%uD", start_x); - fx_tty_move_cursor_x( - ed->l_tty, - FX_TTY_POS_CURSOR, - -(long long)start_x); - } - - start_x = 0; - } - - print_text(ed, start_x, ed->l_cursor_y, line_buf + start_x); - - /* decrement the rdelta (move the cursor back one fewer cells), - * so that the physical cursor will be placed AFTER the character that - * was just inserted. */ - cursor_rdelta--; - fx_tty_move_cursor_x(ed->l_tty, FX_TTY_POS_CURSOR, -cursor_rdelta); - -#if 0 - for (unsigned int i = 0; i < cursor_rdelta; i++) { - fputs("\010", stdout); - } -#endif - - fflush(stdout); -} - -/* this function is called after a character is removed from the line_ed buffer. - * IF the character was a linefeed. - * - * this is separate from backspace_simple_refresh because, in this situation, - * the cursor position depends on the length of the previous line before - * the linefeed was deleted, and we have to reprint every line following the - * two that were combined. - */ -void backspace_nl_refresh(struct line_ed *ed, struct refresh_state *state) -{ - /* get the data for the line that is being refreshed. - * relative to where the cursor was before the linefeed was deleted, - * this is the PREVIOUS line. */ - const fx_wchar *line_buf = line_start(ed, ed->l_cursor_y); - size_t line_len = fx_wstrcspn(line_buf, L"\n"); - - /* the index of the first char in line_buf that needs to be reprinted. - * subtract one to account for the linefeed that has since been deleted. - */ - size_t start_x = state->r_prev_line_len - 1; - - /* the column to move the physical cursor to after it has been moved - * to the previous line. - * NOTE that this number includes the length of the prompt! - * we add 1 to start_x to ensure that the cursor is moved to the cell - * AFTER the last char of the line. */ - size_t new_x; - line_ed_coords_to_physical_coords( - ed, - start_x + 1, - ed->l_cursor_y, - &new_x, - NULL); - - /* the physical cursor is currently at the beginning of the line that - * has just been moved up. from here, clear this line and the rest - * from the screen. */ - // fputs("\033[J", stdout); - fx_tty_clear(ed->l_tty, FX_TTY_CLEAR_SCREEN | FX_TTY_CLEAR_FROM_CURSOR); - - if (ed->l_flags & LINE_ED_FULL_REPRINT) { - /* next, move the physical cursor up and to the beginning of the - * previous line */ - size_t tmp_x; - line_ed_coords_to_physical_coords( - ed, - 0, - ed->l_cursor_y, - &tmp_x, - NULL); - fx_tty_move_cursor_y(ed->l_tty, FX_TTY_POS_CURSOR, -1); - fx_tty_move_cursor_x(ed->l_tty, FX_TTY_POS_START, tmp_x); - // fprintf(stdout, "\033[A\033[%uG", tmp_x + 1); - start_x = 0; - } else { - /* next, move the physical cursor up and to the end of the - * previous line */ - // fprintf(stdout, "\033[A\033[%uG", new_x); - fx_tty_move_cursor_y(ed->l_tty, FX_TTY_POS_CURSOR, -1); - fx_tty_move_cursor_x(ed->l_tty, FX_TTY_POS_START, new_x); - } - - /* now reprint all of the buffer lines, starting with the first of the - * two lines that were concatenated. */ - size_t ydiff = 0; - while (1) { - print_text( - ed, - start_x, - ed->l_cursor_y + ydiff, - line_buf + start_x); - - line_buf += line_len + 1; - line_len = fx_wstrcspn(line_buf, L"\n"); - start_x = 0; - - if (*line_buf == '\0') { - break; - } - - fputc('\r', stdout); - fputc('\n', stdout); - ydiff++; - } - - /* finally, move the cursor BACK to the point where the two lines - * were concatenated. */ - if (ydiff) { - // fprintf(stdout, "\033[%uA", ydiff); - fx_tty_move_cursor_y(ed->l_tty, FX_TTY_POS_CURSOR, ydiff); - } - - // fprintf(stdout, "\033[%uG", new_x); - fx_tty_move_cursor_x(ed->l_tty, FX_TTY_POS_START, new_x); - fflush(stdout); -} - -/* this function is called after a character is removed from the line_ed buffer. - * IF the character was not a linefeed. - */ -void backspace_simple_refresh(struct line_ed *ed, struct refresh_state *state) -{ - /* get the data for the line that is being refreshed */ - const fx_wchar *line_buf = line_start(ed, ed->l_cursor_y); - size_t line_len = fx_wstrcspn(line_buf, L"\n"); - - /* the index of the first char in line_buf that needs to be reprinted */ - size_t start_x = ed->l_cursor_x; - // get_data_cursor_position(ed, &start_x, NULL); - - /* the distance between the first char to be reprinted and the end - * of the line. - * the physical cursor will be moved back by this amount after the - * line is reprinted. */ - long long cursor_rdelta = (long long)(line_len - start_x); - - if (ed->l_flags & LINE_ED_FULL_REPRINT) { - if (start_x) { - // fprintf(stdout, "\033[%uD", start_x); - fx_tty_move_cursor_x( - ed->l_tty, - FX_TTY_POS_CURSOR, - -(long long)start_x); - } - - start_x = 0; - } - - // fputc('\010', stdout); - fx_tty_move_cursor_x(ed->l_tty, FX_TTY_POS_CURSOR, -1); - print_text(ed, start_x, ed->l_cursor_y, line_buf + start_x); - fputc(' ', stdout); - - /* increment the rdelta (move the cursor back one more cell), so - * that the cursor will appear to move back one cell (to accord with - * the fact that backspace was just pressed) */ - cursor_rdelta++; - - fx_tty_move_cursor_x(ed->l_tty, FX_TTY_POS_CURSOR, -cursor_rdelta); - -#if 0 - for (unsigned int i = 0; i < cursor_rdelta; i++) { - fputs("\010", stdout); - } -#endif - - fflush(stdout); -} diff --git a/bshell/line-ed/refresh.h b/bshell/line-ed/refresh.h deleted file mode 100644 index df380c5..0000000 --- a/bshell/line-ed/refresh.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef LINE_ED_REFRESH_H_ -#define LINE_ED_REFRESH_H_ - -#include -#include - -struct line_ed; - -struct refresh_state { - /* cursor position before the update was performed (excluding the - * prompt) */ - size_t r_prev_cursor_x, r_prev_cursor_y; - /* when a backspace results in two separate lines being combined, - * this property contains the length of the first of the two combined - * lines BEFORE the concotenation was performed */ - size_t r_prev_line_len; -}; - -extern void print_text( - struct line_ed *ed, - size_t x, - size_t y, - const fx_wchar *s); -extern void print_buffer(struct line_ed *ed); -extern void put_refresh(struct line_ed *ed, struct refresh_state *state); -extern void backspace_nl_refresh( - struct line_ed *ed, - struct refresh_state *state); -extern void backspace_simple_refresh( - struct line_ed *ed, - struct refresh_state *state); - -#endif diff --git a/bshell/main.c b/bshell/main.c index 4e968da..4ba4639 100644 --- a/bshell/main.c +++ b/bshell/main.c @@ -4,6 +4,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -20,6 +24,7 @@ enum { OPT_PRINT_LEX, OPT_PRINT_AST, OPT_PRINT_BYTECODE, + OPT_NO_PROFILE, ARG_SCRIPT_FILE, }; @@ -70,6 +75,57 @@ static enum frontend_flags collect_frontend_flags(const fx_arglist *opt) return result; } +static void new_line_ed(void) +{ + bshell_line_ed_core *ed_core = bshell_line_ed_core_create(); + bshell_line_ed_highlight *ed_highlight + = bshell_line_ed_highlight_create(); + bshell_line_ed_syntax *ed_syntax = bshell_line_ed_syntax_create(); + bshell_line_ed *ed = bshell_line_ed_create(); + bshell_line_ed_add_plugin(ed, ed_core); + bshell_line_ed_add_plugin(ed, ed_highlight); + bshell_line_ed_add_plugin(ed, ed_syntax); + fx_string *line = fx_string_create(); + + while (1) { + fx_string_clear(line); + enum bshell_status status = bshell_line_ed_readline(ed, line); + printf("read line: '%s'\n", fx_string_get_cstr(line)); + } + + fx_string_unref(line); + bshell_line_ed_unref(ed); +} + +static enum bshell_status load_profile(struct frontend_ctx *ctx) +{ + enum bshell_status status = BSHELL_SUCCESS; + fx_path *config_base_dir = fx_path_get_system(FX_PATH_CONFIG); + fx_path *profile_path = fx_path_join_list( + 3, + &FX_VALUE_OBJECT(config_base_dir), + &FX_CSTR("bshell"), + &FX_CSTR("profile.bshell")); + fx_path_unref(config_base_dir); + + if (fx_path_is_file(profile_path)) { + status = frontend_eval_file( + ctx, + NULL, + fx_path_get_cstr(profile_path)); + + if (status != BSHELL_SUCCESS) { + fprintf(stderr, + "%s: cannot evaluate '%s': %s\n", + exec_name, + fx_path_get_cstr(profile_path), + bshell_status_get_description(status)); + } + } + fx_path_unref(profile_path); + return status; +} + static int bshell( const fx_command *self, const fx_arglist *opt, @@ -84,29 +140,11 @@ static int bshell( frontend_init(&ctx, flags); enum bshell_status status = BSHELL_SUCCESS; - fx_path *config_base_dir = fx_path_get_system(FX_PATH_CONFIG); - fx_path *profile_path = fx_path_join_list( - 3, - &FX_VALUE_OBJECT(config_base_dir), - &FX_CSTR("bshell"), - &FX_CSTR("profile.bshell")); - fx_path_unref(config_base_dir); - - if (fx_path_is_file(profile_path)) { - status = frontend_eval_file( - &ctx, - NULL, - fx_path_get_cstr(profile_path)); - - if (status != BSHELL_SUCCESS) { - fprintf(stderr, - "%s: cannot evaluate '%s': %s\n", - exec_name, - fx_path_get_cstr(profile_path), - bshell_status_get_description(status)); - } +#if 1 + if (!fx_arglist_get_count(opt, OPT_NO_PROFILE, FX_COMMAND_INVALID_ID)) { + status = load_profile(&ctx); } - fx_path_unref(profile_path); +#endif size_t nr_input_files = fx_arglist_get_count( opt, @@ -198,6 +236,12 @@ FX_COMMAND(CMD_ROOT, FX_COMMAND_INVALID_ID) FX_OPTION_DESC("Print bytecode generated from shell input."); } + FX_COMMAND_OPTION(OPT_NO_PROFILE) + { + FX_OPTION_LONG_NAME("no-profile"); + FX_OPTION_DESC("Don't load the current user's profile script."); + } + FX_COMMAND_ARG(ARG_SCRIPT_FILE) { FX_ARG_DESC("Script file to evaluate.");