10 #define BUF_SIZE 1024*1024
14 static char g_memory[1024*1024];
15 static int g_memory_index = 0;
17 void * alloc(int num, int size) {
18 void * result = g_memory + g_memory_index;
19 for (int i = 0; i < num*size; i++)
20 g_memory[g_memory_index+i] = 0;
21 g_memory_index += num*size;
25 #define NEW(TYPE) ((TYPE *)alloc(1, sizeof(TYPE)))
26 #define NEWARR(TYPE, NUM) ((TYPE *)alloc(NUM, sizeof(TYPE)))
34 #include <sys/ioctl.h>
39 /* reads from keypress, doesn't echo */
42 struct termios oldattr, newattr;
44 tcgetattr( STDIN_FILENO, &oldattr );
46 newattr.c_lflag &= ~( ICANON | ECHO ); // no ECHO for echo(?)
47 tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
49 tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
56 struct termios oldattr, newattr;
57 tcgetattr( STDIN_FILENO, &oldattr );
59 newattr.c_lflag &= ~( ICANON | ECHO );
60 tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
62 tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
77 void vt100Escape(const char * str, ...) {
81 printf("%c", ASCII_ESC);
85 void vt100ClearScreen() { vt100Escape("[2J"); }
86 void vt100CursorHome() { vt100Escape("[H"); }
87 void vt100CursorPos(int v, int h) { vt100Escape("[%d;%dH", v, h); }
88 void vt100SaveCursor() { vt100Escape("7"); }
89 void vt100RestoreCursor() { vt100Escape("8"); }
90 void vt100EnableAlternateBuffer() { vt100Escape("[?1049h"); }
91 void vt100DisableAlternateBuffer() { vt100Escape("[?1049l"); }
92 void vt100EnableNegative() { vt100Escape("[7m"); }
93 void vt100DisableNegative() { vt100Escape("[27m"); }
94 void vt100ShowCursor() { vt100Escape("[?25h"); }
95 void vt100HideCursor() { vt100Escape("[?25l"); }
96 void vt100GetScreenSize(int * v, int * h) {
98 CONSOLE_SCREEN_BUFFER_INFO csbi;
99 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
100 *h = csbi.srWindow.Right - csbi.srWindow.Left + 1;
101 *v = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
104 ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
112 typedef enum NodeKind {
131 const char *NK_STRINGS[NK_COUNT] = {
148 typedef struct Node Node;
154 Node *next, *prev, *parent, *child;
157 Node *NodeGetChild(Node *n, unsigned int index) {
158 if (index >= n->childCount)
161 Node *result = n->child;
162 for (int i = 0; i < index; i++)
163 result = result->next;
167 void NodeAppend(Node *n1, Node *n2) {
168 if (n1->childCount == 0) {
172 Node *lastChild = NodeGetChild(n1, n1->childCount-1);
174 lastChild->next = n2;
175 n2->prev = lastChild;
182 void NodeInsert(Node *n1, Node *n2, unsigned int index) {
183 if (index >= n1->childCount-1) {
188 Node *insertAfter = NodeGetChild(n1, index);
189 Node *insertBefore = NodeGetChild(n1, index+1);
191 insertAfter->next = n2;
192 insertBefore->prev = n2;
193 n2->prev = insertAfter;
194 n2->next = insertBefore;
199 Node *NodeRemove(Node *n1, Node *n2) {
203 Node *prev = n2->prev;
204 Node *next = n2->next;
211 n2->prev = n2->next = n2->parent = NULL;
224 void NodeDraw(Node *n, Node *selected) {
225 static int indent = 0;
226 #define INDENT for (int i = 0; i < indent; i++) printf(" ");
228 vt100DisableNegative();
229 if (n == selected) vt100EnableNegative();
232 case NK_Namespace: { break; }
233 case NK_Struct: { break; }
234 case NK_Func: { printf("fn %s ", n->data); NodeDraw(NodeGetChild(n, 0), selected); printf("\n"); INDENT NodeDraw(NodeGetChild(n, 1), selected); break; }
236 case NK_ExprList: { printf("("); for (int i = 0; i < n->childCount; i++) { if (i != 0) printf(", "); NodeDraw(NodeGetChild(n, i), selected); } printf(")"); break; }
237 case NK_Var: { printf("[%s : ", n->data); NodeDraw(NodeGetChild(n, 0), selected); printf(); break; }
238 case NK_Type: { break; }
239 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; }
240 case NK_If: { printf("if "); NodeDraw(NodeGetChild(n, 0), selected); printf("\n"); INDENT NodeDraw(NodeGetChild(n, 1), selected); break; }
241 case NK_While: { printf("while "); NodeDraw(NodeGetChild(n, 0), selected); printf("\n"); INDENT NodeDraw(NodeGetChild(n, 1), selected); break; }
242 case NK_Num: { printf("%s", n->data); break; }
243 case NK_Str: { printf("'%s'", n->data); break; }
244 case NK_Call: { printf("call %s ", n->data); NodeDraw(NodeGetChild(n, 0), selected); break; }
245 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; }
248 vt100DisableNegative();
254 #define KEY_BACKSPACE1 8
255 #define KEY_BACKSPACE2 127
281 const char *IN_STRINGS[IN_COUNT] = {
309 case ' ': return IN_SPACE;
310 case 'd': return IN_D;
312 case 'h': return IN_H;
313 case 'j': return IN_J;
314 case 'k': return IN_K;
315 case 'l': return IN_L;
317 case 'f': return IN_F;
318 case 'v': return IN_V;
319 case 'i': return IN_I;
320 case 'n': return IN_N;
321 case 's': return IN_S;
322 case 'c': return IN_C;
323 case 'o': return IN_O;
325 case 'q': return IN_Quit;
330 typedef enum InputAction {
352 const char *IA_STRINGS[IA_COUNT] = {
372 void DrawInfo(InputAction actions[NK_COUNT][IN_COUNT], NodeKind nk) {
374 vt100GetScreenSize(&v, &h);
378 vt100CursorPos(line++, h-30);
379 printf("%s:", NK_STRINGS[nk]);
381 for (int i = 0; i < IN_COUNT; i++) {
382 InputAction action = actions[nk][i];
383 if (action != IA_None) {
384 vt100CursorPos(line++, h-30);
385 printf("%s %s", IN_STRINGS[i], IA_STRINGS[action]);
390 Node *GetNode(InputAction actions[NK_COUNT][IN_COUNT]) {
391 Node *result = NEW(Node); result->kind = NK_Body;
401 } mode = Mode_Normal;
407 DrawInfo(actions, n->kind);
409 if (mode == Mode_Editing) {
411 char *s = (char*)n->data;
412 int slen = strlen(s);
414 if (c == KEY_BACKSPACE1 || c == KEY_BACKSPACE2) {
417 else if (c == '\n' || c == '\r') {
420 else if (slen < STR_SIZE) {
424 else if (mode == Mode_Normal) {
430 action = actions[n->kind][in];
432 #define NA(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NodeAppend(PARENT, NAME);
433 #define NS(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NAME->data = NEWARR(char, STR_SIZE); NodeAppend(PARENT, NAME);
436 case IA_StartEditing: { mode = Mode_Editing; break; }
437 case IA_Delete: { n = NodeRemove(n->parent, n); break; }
439 case IA_MoveLeft: { if (n->prev != NULL) n = n->prev; break; }
440 case IA_MoveDown: { if (n->child != NULL) n = n->child; break; }
441 case IA_MoveUp: { if (n->parent != NULL) n = n->parent; break; }
442 case IA_MoveRight: { if (n->next != NULL) n = n->next; break; }
444 case IA_AddFunc: { NS(n1, n, NK_Func) NA(n2, n1, NK_VarList) NA(n3, n1, NK_Body) n = n1; mode = Mode_Editing; break; }
445 case IA_AddVar: { NS(n1, n, NK_Var) n = n1; mode = Mode_Editing; break; }
446 case IA_AddIf: { NA(n1, n, NK_If) NA(n2, n1, NK_ExprList) NA(n3, n1, NK_Body) n = n1; break; }
447 case IA_AddNum: { NS(n1, n, NK_Num) n = n1; mode = Mode_Editing; break; }
448 case IA_AddStr: { NS(n1, n, NK_Str) n = n1; mode = Mode_Editing; break; }
449 case IA_AddCall: { NS(n1, n, NK_Call) NA(n2, n1, NK_ExprList) n = n1; mode = Mode_Editing; break; }
450 case IA_AddOp: { NS(n1, n, NK_Op) n = n1; mode = Mode_Editing; break; }
464 static InputAction actions[NK_COUNT][IN_COUNT];
466 for (int i = 0; i < NK_COUNT; i++) {
467 actions[i][IN_H] = IA_MoveLeft;
468 actions[i][IN_J] = IA_MoveUp;
469 actions[i][IN_K] = IA_MoveDown;
470 actions[i][IN_L] = IA_MoveRight;
473 actions[NK_Func][IN_D] = IA_Delete;
474 actions[NK_Func][IN_SPACE] = IA_StartEditing;
476 actions[NK_VarList][IN_V] = IA_AddVar;
478 actions[NK_ExprList][IN_V] = IA_AddVar;
479 actions[NK_ExprList][IN_I] = IA_AddIf;
480 actions[NK_ExprList][IN_N] = IA_AddNum;
481 actions[NK_ExprList][IN_S] = IA_AddStr;
482 actions[NK_ExprList][IN_C] = IA_AddCall;
483 actions[NK_ExprList][IN_O] = IA_AddOp;
485 actions[NK_Var][IN_D] = IA_Delete;
486 actions[NK_Var][IN_SPACE] = IA_StartEditing;
488 actions[NK_Body][IN_F] = IA_AddFunc;
489 actions[NK_Body][IN_V] = IA_AddVar;
490 actions[NK_Body][IN_I] = IA_AddIf;
491 actions[NK_Body][IN_N] = IA_AddNum;
492 actions[NK_Body][IN_S] = IA_AddStr;
493 actions[NK_Body][IN_C] = IA_AddCall;
494 actions[NK_Body][IN_O] = IA_AddOp;
496 actions[NK_If][IN_D] = IA_Delete;
498 actions[NK_Num][IN_D] = IA_Delete;
499 actions[NK_Num][IN_SPACE] = IA_StartEditing;
501 actions[NK_Str][IN_D] = IA_Delete;
502 actions[NK_Str][IN_SPACE] = IA_StartEditing;
504 actions[NK_Call][IN_D] = IA_Delete;
505 actions[NK_Call][IN_SPACE] = IA_StartEditing;
507 actions[NK_Op][IN_D] = IA_Delete;
508 actions[NK_Op][IN_SPACE] = IA_StartEditing;
509 actions[NK_Op][IN_V] = IA_AddVar;
510 actions[NK_Op][IN_I] = IA_AddIf;
511 actions[NK_Op][IN_N] = IA_AddNum;
512 actions[NK_Op][IN_S] = IA_AddStr;
513 actions[NK_Op][IN_C] = IA_AddCall;
514 actions[NK_Op][IN_O] = IA_AddOp;
517 vt100EnableAlternateBuffer();
520 Node *n = GetNode(actions);
522 vt100DisableAlternateBuffer();
526 vt100GetScreenSize(&v, &h);
527 printf("Screen Size: %d | %d\n", v, h);