#include "arena_alloc.h" #include "context.h" #include "gapbuffer.h" #include "interp.h" #include "mprintf.h" #include "self.h" #include "strbuf.h" #include #include #include #include #include #include #include #include #include #include #include #include #define LINE_INIT_MAX 40 #define PROMPT "$ " void* wmalloc (void* ctx, size_t size) { (void)ctx; return malloc (size); } void* wrealloc (void* ctx, void* mem, size_t old, size_t new) { (void)ctx, (void)old; return realloc (mem, new); } void wfree (void* ctx, void* mem) { (void)ctx; free (mem); } void* warena_malloc (void* ctx, size_t size) { struct arena* a = ctx; return arena_malloc (a, size); } void* warena_realloc (void* ctx, void* mem, size_t old, size_t new) { struct arena* a = ctx; return arena_realloc (a, mem, old, new); } void warena_free (void* ctx, void* mem) { (void)ctx, (void)mem; } struct edit_line { struct gapbuffer gb; size_t cursor; }; static void exec_line (const char* line) { struct list_node_link* tokens = NULL; tokenize (&tokens, line); if (tokens != NULL) parse_and_execute (tokens); } void app_main (void) { e_pid = get_exec_pid (); e_pgid = get_procgroup (e_pid); struct edit_line edit_line; const char* render = NULL; while (interp_is_running ()) { gapbuffer_init (&warena_malloc, &arena, &edit_line.gb, LINE_INIT_MAX); edit_line.cursor = 0; mprintf (PROMPT); uint8_t ch = 0; for (;;) { mail_receive (&ch, 1); if (ch == '\n') break; gapbuffer_move (&edit_line.gb, edit_line.cursor); switch (ch) { case '\b': if (edit_line.cursor > 0) { edit_line.cursor--; gapbuffer_backspace (&edit_line.gb); mprintf (ANSIQ_CUR_LEFT (1)); char* tail = gapbuffer_string_at (&warena_malloc, &arena, &edit_line.gb, edit_line.cursor); mprintf ("%s" ANSIQ_SCR_CLR2LEND, tail); int move_back = strlen (tail); if (move_back > 0) mprintf (ANSIQ_DYN_CUR_LEFT, move_back); } break; case KB_DELETE: if (edit_line.cursor < gapbuffer_length (&edit_line.gb)) { edit_line.gb.gap_end++; char* tail = gapbuffer_string_at (&warena_malloc, &arena, &edit_line.gb, edit_line.cursor); mprintf ("%s" ANSIQ_SCR_CLR2LEND, tail); int move_back = strlen (tail); if (move_back > 0) mprintf (ANSIQ_DYN_CUR_LEFT, move_back); } break; case KB_LEFT: if (edit_line.cursor > 0) { edit_line.cursor--; mprintf (ANSIQ_CUR_LEFT (1)); } break; case KB_RIGHT: if (edit_line.cursor < gapbuffer_length (&edit_line.gb)) { edit_line.cursor++; mprintf (ANSIQ_CUR_RIGHT (1)); } break; default: if (isprint (ch)) { gapbuffer_insert (&warena_realloc, &arena, &edit_line.gb, ch); edit_line.cursor++; if (edit_line.cursor == gapbuffer_length (&edit_line.gb)) { mprintf ("%c", ch); } else { char* tail = gapbuffer_string_at (&warena_malloc, &arena, &edit_line.gb, edit_line.cursor - 1); size_t move_back = strlen (tail) - 1; mprintf ("%s" ANSIQ_DYN_CUR_LEFT, tail, move_back); } } break; } } mprintf ("\n"); render = gapbuffer_get_string (&warena_malloc, &arena, &edit_line.gb); if (render != NULL) exec_line (render); gapbuffer_fini (&warena_free, &arena, &edit_line.gb); arena_reset (&arena); } arena_destroy (&arena); }