8 #define BUF_SIZE 1024*1024
12 static char g_memory[1024*1024];
13 static int g_memory_index = 0;
15 void * alloc(int num, int size) {
16 void * result = g_memory + g_memory_index;
17 for (int i = 0; i < num*size; i++)
18 g_memory[g_memory_index+i] = 0;
19 g_memory_index += num*size;
23 #define NEW(TYPE) ((TYPE *)alloc(1, sizeof(TYPE)))
24 #define NEWARR(TYPE, NUM) ((TYPE *)alloc(NUM, sizeof(TYPE)))
32 #include <sys/ioctl.h>
37 /* reads from keypress, doesn't echo */
40 struct termios oldattr, newattr;
42 tcgetattr( STDIN_FILENO, &oldattr );
44 newattr.c_lflag &= ~( ICANON | ECHO ); // no ECHO for echo(?)
45 tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
47 tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
54 struct termios oldattr, newattr;
55 tcgetattr( STDIN_FILENO, &oldattr );
57 newattr.c_lflag &= ~( ICANON | ECHO );
58 tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
60 tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
75 void vt100Escape(const char * str, ...) {
79 printf("%c", ASCII_ESC);
83 void vt100ClearScreen() { vt100Escape("[2J"); }
84 void vt100CursorHome() { vt100Escape("[H"); }
85 void vt100CursorPos(int v, int h) { vt100Escape("[%d;%dH", v, h); }
86 void vt100SaveCursor() { vt100Escape("7"); }
87 void vt100RestoreCursor() { vt100Escape("8"); }
88 void vt100EnableAlternateBuffer() { vt100Escape("[?1049h"); }
89 void vt100DisableAlternateBuffer() { vt100Escape("[?1049l"); }
90 void vt100EnableNegative() { vt100Escape("[7m"); }
91 void vt100DisableNegative() { vt100Escape("[27m"); }
92 void vt100ShowCursor() { vt100Escape("[?25h"); }
93 void vt100HideCursor() { vt100Escape("[?25l"); }
94 void vt100GetScreenSize(int * v, int * h) {
96 CONSOLE_SCREEN_BUFFER_INFO csbi;
97 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
98 *h = csbi.srWindow.Right - csbi.srWindow.Left + 1;
99 *v = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
102 ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
110 typedef enum NodeKind {
125 const char *NK_STRINGS[NK_COUNT] = {
138 typedef struct Node Node;
144 Node *next, *prev, *parent, *child;
147 Node *NodeGetChild(Node *n, unsigned int index) {
148 if (index >= n->childCount)
151 Node *result = n->child;
152 for (int i = 0; i < index; i++)
153 result = result->next;
157 void NodeAppend(Node *n1, Node *n2) {
158 if (n1->childCount == 0) {
162 Node *lastChild = NodeGetChild(n1, n1->childCount-1);
164 lastChild->next = n2;
165 n2->prev = lastChild;
172 void NodeInsert(Node *n1, Node *n2, unsigned int index) {
173 if (index >= n1->childCount-1) {
178 Node *insertAfter = NodeGetChild(n1, index);
179 Node *insertBefore = NodeGetChild(n1, index+1);
181 insertAfter->next = n2;
182 insertBefore->prev = n2;
183 n2->prev = insertAfter;
184 n2->next = insertBefore;
189 Node *NodeRemove(Node *n1, Node *n2) {
193 Node *prev = n2->prev;
194 Node *next = n2->next;
201 n2->prev = n2->next = n2->parent = NULL;
214 void NodeDraw(Node *n, Node *selected) {
215 static int indent = 0;
216 #define INDENT for (int i = 0; i < indent; i++) printf(" ");
218 vt100DisableNegative();
219 if (n == selected) vt100EnableNegative();
222 case NK_Func: { printf("fn %s ", n->data); NodeDraw(NodeGetChild(n, 0), selected); printf("\n"); INDENT NodeDraw(NodeGetChild(n, 1), selected); break; }
224 case NK_ArgList: { printf("("); for (int i = 0; i < n->childCount; i++) { if (i != 0) printf(" "); NodeDraw(NodeGetChild(n, i), selected); } printf(")"); break; }
225 case NK_Var: { printf("var %s", n->data); break; }
226 case NK_Body: { printf("{\n"); indent++; for (int i = 0; i < n->childCount; i++) { INDENT NodeDraw(NodeGetChild(n, i), selected); printf("\n"); } indent--; INDENT printf("}\n"); break; }
227 case NK_If: { printf("if "); NodeDraw(NodeGetChild(n, 0), selected); printf("\n"); INDENT NodeDraw(NodeGetChild(n, 1), selected); break; }
228 case NK_Num: { printf("%s", n->data); break; }
229 case NK_Str: { printf("'%s'", n->data); break; }
230 case NK_Call: { printf("call %s ", n->data); NodeDraw(NodeGetChild(n, 0), selected); break; }
231 case NK_Op: { if (n->childCount <= 1) printf("%s ", n->data); for (int i = 0; i < n->childCount; i++) { if (i != 0) printf(" %s ", n->data); NodeDraw(NodeGetChild(n, i), selected); } break; }
234 vt100DisableNegative();
240 #define KEY_BACKSPACE1 8
241 #define KEY_BACKSPACE2 127
267 const char *IN_STRINGS[IN_COUNT] = {
295 case ' ': return IN_SPACE;
296 case 'd': return IN_D;
298 case 'h': return IN_H;
299 case 'j': return IN_J;
300 case 'k': return IN_K;
301 case 'l': return IN_L;
303 case 'f': return IN_F;
304 case 'v': return IN_V;
305 case 'i': return IN_I;
306 case 'n': return IN_N;
307 case 's': return IN_S;
308 case 'c': return IN_C;
309 case 'o': return IN_O;
311 case 'q': return IN_Quit;
316 typedef enum InputAction {
338 const char *IA_STRINGS[IA_COUNT] = {
358 void DrawInfo(InputAction actions[NK_COUNT][IN_COUNT], NodeKind nk) {
360 vt100GetScreenSize(&v, &h);
364 vt100CursorPos(line++, h-30);
365 printf("%s:", NK_STRINGS[nk]);
367 for (int i = 0; i < IN_COUNT; i++) {
368 InputAction action = actions[nk][i];
369 if (action != IA_None) {
370 vt100CursorPos(line++, h-30);
371 printf("%s %s", IN_STRINGS[i], IA_STRINGS[action]);
376 Node *GetNode(InputAction actions[NK_COUNT][IN_COUNT]) {
377 Node *result = NEW(Node); result->kind = NK_Body;
387 } mode = Mode_Normal;
393 DrawInfo(actions, n->kind);
395 if (mode == Mode_Editing) {
397 char *s = (char*)n->data;
398 int slen = strlen(s);
400 if (c == KEY_BACKSPACE1 || c == KEY_BACKSPACE2) {
406 else if (slen < STR_SIZE) {
410 else if (mode == Mode_Normal) {
416 action = actions[n->kind][in];
418 #define NA(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NodeAppend(PARENT, NAME);
419 #define NS(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NAME->data = NEWARR(char, STR_SIZE); NodeAppend(PARENT, NAME);
422 case IA_StartEditing: { mode = Mode_Editing; break; }
423 case IA_Delete: { n = NodeRemove(n->parent, n); break; }
425 case IA_MoveLeft: { if (n->prev != NULL) n = n->prev; break; }
426 case IA_MoveDown: { if (n->child != NULL) n = n->child; break; }
427 case IA_MoveUp: { if (n->parent != NULL) n = n->parent; break; }
428 case IA_MoveRight: { if (n->next != NULL) n = n->next; break; }
430 case IA_AddFunc: { NS(n1, n, NK_Func) NA(n2, n1, NK_ArgList) NA(n3, n1, NK_Body) n = n1; mode = Mode_Editing; break; }
431 case IA_AddVar: { NS(n1, n, NK_Var) n = n1; mode = Mode_Editing; break; }
432 case IA_AddIf: { NA(n1, n, NK_If) NA(n2, n1, NK_ExprList) NA(n3, n1, NK_Body) n = n1; break; }
433 case IA_AddNum: { NS(n1, n, NK_Num) n = n1; mode = Mode_Editing; break; }
434 case IA_AddStr: { NS(n1, n, NK_Str) n = n1; mode = Mode_Editing; break; }
435 case IA_AddCall: { NS(n1, n, NK_Call) NA(n2, n1, NK_ExprList) n = n1; mode = Mode_Editing; break; }
436 case IA_AddOp: { NS(n1, n, NK_Op) n = n1; mode = Mode_Editing; break; }
450 static InputAction actions[NK_COUNT][IN_COUNT];
452 for (int i = 0; i < NK_COUNT; i++) {
453 actions[i][IN_H] = IA_MoveLeft;
454 actions[i][IN_J] = IA_MoveUp;
455 actions[i][IN_K] = IA_MoveDown;
456 actions[i][IN_L] = IA_MoveRight;
459 actions[NK_Func][IN_D] = IA_Delete;
460 actions[NK_Func][IN_SPACE] = IA_StartEditing;
462 actions[NK_ArgList][IN_V] = IA_AddVar;
464 actions[NK_ExprList][IN_V] = IA_AddVar;
465 actions[NK_ExprList][IN_I] = IA_AddIf;
466 actions[NK_ExprList][IN_N] = IA_AddNum;
467 actions[NK_ExprList][IN_S] = IA_AddStr;
468 actions[NK_ExprList][IN_C] = IA_AddCall;
469 actions[NK_ExprList][IN_O] = IA_AddOp;
471 actions[NK_Var][IN_D] = IA_Delete;
472 actions[NK_Var][IN_SPACE] = IA_StartEditing;
474 actions[NK_Body][IN_F] = IA_AddFunc;
475 actions[NK_Body][IN_V] = IA_AddVar;
476 actions[NK_Body][IN_I] = IA_AddIf;
477 actions[NK_Body][IN_N] = IA_AddNum;
478 actions[NK_Body][IN_S] = IA_AddStr;
479 actions[NK_Body][IN_C] = IA_AddCall;
480 actions[NK_Body][IN_O] = IA_AddOp;
482 actions[NK_If][IN_D] = IA_Delete;
484 actions[NK_Num][IN_D] = IA_Delete;
485 actions[NK_Num][IN_SPACE] = IA_StartEditing;
487 actions[NK_Call][IN_D] = IA_Delete;
488 actions[NK_Call][IN_SPACE] = IA_StartEditing;
490 actions[NK_Op][IN_D] = IA_Delete;
491 actions[NK_Op][IN_SPACE] = IA_StartEditing;
492 actions[NK_Op][IN_V] = IA_AddVar;
493 actions[NK_Op][IN_I] = IA_AddIf;
494 actions[NK_Op][IN_N] = IA_AddNum;
495 actions[NK_Op][IN_S] = IA_AddStr;
496 actions[NK_Op][IN_C] = IA_AddCall;
497 actions[NK_Op][IN_O] = IA_AddOp;
500 vt100EnableAlternateBuffer();
503 Node *n = GetNode(actions);
505 vt100DisableAlternateBuffer();
509 vt100GetScreenSize(&v, &h);
510 printf("Screen Size: %d | %d\n", v, h);