12 #define MEMORY_SIZE 1024*1024
13 #define EDIT_QUEUE_SIZE 10
17 static char g_memory[1024*1024];
18 static int g_memory_index = 0;
20 void * alloc(int num, int size) {
21 assert(g_memory_index + num*size < MEMORY_SIZE);
23 void * result = g_memory + g_memory_index;
24 for (int i = 0; i < num*size; i++)
25 g_memory[g_memory_index+i] = 0;
26 g_memory_index += num*size;
30 #define NEW(TYPE) ((TYPE *)alloc(1, sizeof(TYPE)))
31 #define NEWARR(TYPE, NUM) ((TYPE *)alloc(NUM, sizeof(TYPE)))
32 #define NEWSTR NEWARR(char, STR_SIZE)
40 #include <sys/ioctl.h>
45 /* reads from keypress, doesn't echo */
48 struct termios oldattr, newattr;
50 tcgetattr( STDIN_FILENO, &oldattr );
52 newattr.c_lflag &= ~( ICANON | ECHO ); // no ECHO for echo(?)
53 tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
55 tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
62 struct termios oldattr, newattr;
63 tcgetattr( STDIN_FILENO, &oldattr );
65 newattr.c_lflag &= ~( ICANON | ECHO );
66 tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
68 tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
83 void vt100Escape(const char * str, ...) {
87 printf("%c", ASCII_ESC);
91 void vt100ClearScreen() { vt100Escape("[2J"); }
92 void vt100CursorHome() { vt100Escape("[H"); }
93 void vt100CursorPos(int v, int h) { vt100Escape("[%d;%df", v, h); }
94 void vt100SaveCursor() { vt100Escape("7"); }
95 void vt100RestoreCursor() { vt100Escape("8"); }
96 void vt100EnableAlternateBuffer() { vt100Escape("[?1049h"); }
97 void vt100DisableAlternateBuffer() { vt100Escape("[?1049l"); }
98 void vt100EnableNegative() { vt100Escape("[7m"); }
99 void vt100DisableNegative() { vt100Escape("[27m"); }
100 void vt100ShowCursor() { vt100Escape("[?25h"); }
101 void vt100HideCursor() { vt100Escape("[?25l"); }
102 void vt100GetScreenSize(int * v, int * h) {
104 CONSOLE_SCREEN_BUFFER_INFO csbi;
105 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
106 *h = csbi.srWindow.Right - csbi.srWindow.Left + 1;
107 *v = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
110 ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
118 typedef enum NodeKind {
139 const char *NK_STRINGS[NK_COUNT] = {
158 typedef struct Node Node;
164 Node *next, *prev, *prnt, *chld;
167 Node *NodeGetChild(Node *n, unsigned int index) {
168 if (index >= n->childCount)
171 Node *result = n->chld;
172 for (int i = 0; i < index; i++)
173 result = result->next;
177 void NodeAppend(Node *n1, Node *n2) {
178 if (n1->childCount == 0) {
182 Node *lastChild = NodeGetChild(n1, n1->childCount-1);
184 lastChild->next = n2;
185 n2->prev = lastChild;
192 void NodeInsert(Node *n1, Node *n2, unsigned int index) {
193 if (index >= n1->childCount-1) {
198 Node *insertAfter = NodeGetChild(n1, index);
199 Node *insertBefore = NodeGetChild(n1, index+1);
201 insertAfter->next = n2;
202 insertBefore->prev = n2;
203 n2->prev = insertAfter;
204 n2->next = insertBefore;
209 Node *NodeRemove(Node *n1, Node *n2) {
213 Node *prev = n2->prev;
214 Node *next = n2->next;
221 n2->prev = n2->next = n2->prnt = NULL;
234 void NodeDraw(Node *n);
235 Node *g_NodeDrawSelected;
237 void Printf(Node *n, char* format, ...)
240 va_start(argp, format);
241 while (*format != '\0') {
242 if (*format == '%') {
244 if (*format == '%') {
246 } else if (*format == 'n') {
247 Node *n = va_arg(argp, Node*);
249 } else if (*format == 's') {
250 char *s = va_arg(argp, char*);
252 if (g_NodeDrawSelected == n && s == n->data)
254 } else if (*format == ',' && format[1] == 'n') {
255 Node *n = va_arg(argp, Node*);
256 for (int i = 0; i < n->childCount; i++) {
257 if (i > 0) printf(", ");
258 NodeDraw(NodeGetChild(n, i));
261 } else if (*format == ';' && format[1] == 'n') {
262 Node *n = va_arg(argp, Node*);
263 for (int i = 0; i < n->childCount; i++) {
264 if (i == 0) printf("\n");
265 NodeDraw(NodeGetChild(n, i));
270 fputs("Not implemented", stderr);
272 } else if (*format == '_') {
273 static bool highlighted = false;
274 // Node *n = va_arg(argp, Node*);
276 vt100DisableNegative();
279 else if (g_NodeDrawSelected == n) {
280 vt100EnableNegative();
291 void NodeDraw(Node *n) {
292 static int indent = 0;
293 #define INDENT printf("\n"); for (int i = 0; i < indent; i++) printf(" ");
295 #define PRINTF(...) do { if (n == g_NodeDrawSelected) vt100EnableNegative(); printf(__VA_ARGS__); vt100DisableNegative(); } while(0);
298 case NK_Namespace: { Printf(n, "_namespace %s {_%;n_}_\n", n->data, n); break; }
299 case NK_Struct: { Printf(n, "_struct %s {_%;n_}_\n", n->data, n); break; }
300 case NK_Func: { Printf(n, "_fn %s_ %n %n", n->data, NodeGetChild(n, 0), NodeGetChild(n, 1)); break; }
302 case NK_ExprList: { Printf(n, "_(_%,n_)_", n); break; }
303 case NK_Var: { Printf(n, "_%s_", n->data); break; }
304 case NK_VarDecl: { Printf(n, "_%s:_ %n", n->data, NodeGetChild(n, 0)); break; }
306 case NK_Type: { Printf(n, "_%s%s%,n%s_", n->data, (n->childCount > 0 ? "<" : ""), n, (n->childCount > 0 ? ">" : "")); break; }
307 case NK_Body: { Printf(n, "_{_%;n_}_", n); break; }
308 case NK_If: { Printf(n, "_if_ %n %n", NodeGetChild(n, 0), NodeGetChild(n, 1)); break; }
309 case NK_While: { Printf(n, "_while_ %n %n", NodeGetChild(n, 0), NodeGetChild(n, 1)); break; }
310 case NK_Num: { Printf(n, "_%s_", n->data); break; }
311 case NK_Str: { Printf(n, "_'%s'_", n->data); break; }
312 case NK_Call: { Printf(n, "_%s_(%n)", n->data, NodeGetChild(n, 0)); break; }
313 case NK_Op: { for (int i = 0; i < n->childCount; i++) { if (n->childCount == 0 || i != 0) { Printf(n, " _%s_ ", n->data); } NodeDraw(NodeGetChild(n, i)); } break; }
320 #define KEY_BACKSPACE1 8
321 #define KEY_BACKSPACE2 127
350 const char *IN_STRINGS[IN_COUNT] = {
381 case 'h': return IN_H;
382 case 'j': return IN_J;
383 case 'k': return IN_K;
384 case 'l': return IN_L;
386 case ' ': return IN_SPACE;
387 case 'd': return IN_D;
389 case 'f': return IN_F;
390 case 'v': return IN_V;
391 case 't': return IN_T;
392 case 'i': return IN_I;
393 case 'w': return IN_W;
394 case 'n': return IN_N;
395 case 's': return IN_S;
396 case 'c': return IN_C;
397 case 'o': return IN_O;
399 case 'q': return IN_Quit;
404 typedef enum InputAction {
431 const char *IA_STRINGS[IA_COUNT] = {
456 typedef enum InputMode {
461 void DrawInfo(InputAction actions[NK_COUNT][IN_COUNT], NodeKind nk, InputMode mode) {
463 vt100GetScreenSize(&v, &h);
467 vt100CursorPos(line++, h-30);
468 printf("%d:%d", v, h);
469 vt100CursorPos(line++, h-30);
471 printf("%s:%s", NK_STRINGS[nk], (mode == IM_Normal ? "" : " (editing)"));
473 for (int i = IN_L+1; i < IN_COUNT; i++) {
474 InputAction action = actions[nk][i];
475 if (action != IA_None) {
476 vt100CursorPos(line++, h-30);
477 printf("%s %s", IN_STRINGS[i], IA_STRINGS[action]);
482 bool ValidChar(NodeKind nk, int c) {
483 const char *allow = NULL;
484 const char *block = NULL;
501 allow = "+-.0123456789";
515 for (int i = 0; (a = allow[i]) != '\0'; i++) {
516 if (a == c) return true;
520 else if (block != NULL) {
522 for (int i = 0; (b = block[i]) != '\0'; i++) {
523 if (b == c) return false;
532 Node *PopEditQueue(Node ** q) {
534 for (int i = 0; i < EDIT_QUEUE_SIZE-1 && q[i] != NULL; i++) {
540 Node *GetNode(InputAction actions[NK_COUNT][IN_COUNT]) {
541 Node *result = NEW(Node); result->data = NEWSTR; result->kind = NK_Namespace;
544 Node * q[EDIT_QUEUE_SIZE] = {0};
549 InputMode mode = IM_Normal;
554 g_NodeDrawSelected = n;
556 g_NodeDrawSelected = NULL;
557 DrawInfo(actions, n->kind, mode);
559 if (mode == IM_Editing) {
561 char *s = (char*)n->data;
562 int slen = strlen(s);
564 if (c == KEY_BACKSPACE1 || c == KEY_BACKSPACE2) {
567 else if (c == '\n' || c == '\r') {
573 else if (slen < STR_SIZE && ValidChar(n->kind, c)) {
577 else if (mode == IM_Normal) {
583 action = actions[n->kind][in];
585 #define N(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NodeAppend(PARENT, NAME);
586 #define S(NAME, PARENT, KIND) Node *NAME = NEW(Node); NAME->kind = KIND; NAME->data = NEWSTR; NodeAppend(PARENT, NAME);
589 case IA_MoveLeft: { if (n->prev != NULL) n = n->prev; break; }
590 case IA_MoveDown: { if (n->chld != NULL) n = n->chld; break; }
591 case IA_MoveUp: { if (n->prnt != NULL) n = n->prnt; break; }
592 case IA_MoveRight: { if (n->next != NULL) n = n->next; break; }
594 case IA_StartEditing: { mode = IM_Editing; break; }
595 case IA_Delete: { n = NodeRemove(n->prnt, n); break; }
597 case IA_AddNamespace: { S(n1, n, NK_Namespace) n=n1; mode=IM_Editing; break; }
598 case IA_AddStruct: { S(n1, n, NK_Struct) n=n1; mode=IM_Editing; break; }
599 case IA_AddFunc: { S(n1, n, NK_Func)
600 N(n2, n1, NK_VarList)
601 N(n3, n1, NK_Body) n=n1; mode=IM_Editing; break; }
602 case IA_AddVar: { S(n1, n, NK_Var) n=n1; mode=IM_Editing; break; }
603 case IA_AddVarDecl: { S(n1, n, NK_VarDecl) n=n1;
604 S(n2, n1, NK_VarType) q[0]=n2; mode=IM_Editing; break; }
605 case IA_AddType: { S(n1, n, NK_Type) n=n1; mode=IM_Editing; break; }
606 case IA_AddIf: { N(n1, n, NK_If)
607 N(n2, n1, NK_ExprList)
608 N(n3, n1, NK_Body) n=n2; break; }
609 case IA_AddWhile: { N(n1, n, NK_While)
610 N(n2, n1, NK_ExprList)
611 N(n3, n1, NK_Body) n=n2; break; }
612 case IA_AddNum: { S(n1, n, NK_Num) n=n1; mode=IM_Editing; break; }
613 case IA_AddStr: { S(n1, n, NK_Str) n=n1; mode=IM_Editing; break; }
614 case IA_AddCall: { S(n1, n, NK_Call)
615 N(n2, n1, NK_ExprList) n=n1; mode=IM_Editing; break; }
616 case IA_AddOp: { S(n1, n, NK_Op) n=n1; mode=IM_Editing; break; }
628 void SetupInputActions(InputAction actions[NK_COUNT][IN_COUNT]) {
629 for (int i = 0; i < NK_COUNT; i++) {
630 actions[i][IN_H] = IA_MoveLeft;
631 actions[i][IN_J] = IA_MoveDown;
632 actions[i][IN_K] = IA_MoveUp;
633 actions[i][IN_L] = IA_MoveRight;
636 actions[NK_Namespace][IN_D] = IA_Delete;
637 actions[NK_Namespace][IN_SPACE] = IA_StartEditing;
638 actions[NK_Namespace][IN_N] = IA_AddNamespace;
639 actions[NK_Namespace][IN_S] = IA_AddStruct;
640 actions[NK_Namespace][IN_F] = IA_AddFunc;
642 actions[NK_Struct][IN_D] = IA_Delete;
643 actions[NK_Struct][IN_SPACE] = IA_StartEditing;
644 actions[NK_Struct][IN_V] = IA_AddVarDecl;
645 actions[NK_Struct][IN_F] = IA_AddFunc;
647 actions[NK_Func][IN_D] = IA_Delete;
648 actions[NK_Func][IN_SPACE] = IA_StartEditing;
650 actions[NK_VarList][IN_V] = IA_AddVarDecl;
652 actions[NK_ExprList][IN_V] = IA_AddVar;
653 actions[NK_ExprList][IN_I] = IA_AddIf;
654 actions[NK_ExprList][IN_W] = IA_AddWhile;
655 actions[NK_ExprList][IN_N] = IA_AddNum;
656 actions[NK_ExprList][IN_S] = IA_AddStr;
657 actions[NK_ExprList][IN_C] = IA_AddCall;
658 actions[NK_ExprList][IN_O] = IA_AddOp;
660 actions[NK_Var][IN_D] = IA_Delete;
661 actions[NK_Var][IN_SPACE] = IA_StartEditing;
663 actions[NK_VarDecl][IN_D] = IA_Delete;
664 actions[NK_VarDecl][IN_SPACE] = IA_StartEditing;
666 actions[NK_VarType][IN_SPACE] = IA_StartEditing;
667 actions[NK_VarType][IN_T] = IA_AddType;
669 actions[NK_Type][IN_D] = IA_Delete;
670 actions[NK_Type][IN_SPACE] = IA_StartEditing;
671 actions[NK_Type][IN_T] = IA_AddType;
673 actions[NK_Body][IN_F] = IA_AddFunc;
674 actions[NK_Body][IN_V] = IA_AddVarDecl;
675 actions[NK_Body][IN_I] = IA_AddIf;
676 actions[NK_Body][IN_W] = IA_AddWhile;
677 actions[NK_Body][IN_N] = IA_AddNum;
678 actions[NK_Body][IN_S] = IA_AddStr;
679 actions[NK_Body][IN_C] = IA_AddCall;
680 actions[NK_Body][IN_O] = IA_AddOp;
682 actions[NK_If][IN_D] = IA_Delete;
684 actions[NK_While][IN_D] = IA_Delete;
686 actions[NK_Num][IN_D] = IA_Delete;
687 actions[NK_Num][IN_SPACE] = IA_StartEditing;
689 actions[NK_Str][IN_D] = IA_Delete;
690 actions[NK_Str][IN_SPACE] = IA_StartEditing;
692 actions[NK_Call][IN_D] = IA_Delete;
693 actions[NK_Call][IN_SPACE] = IA_StartEditing;
695 actions[NK_Op][IN_D] = IA_Delete;
696 actions[NK_Op][IN_SPACE] = IA_StartEditing;
697 actions[NK_Op][IN_V] = IA_AddVar;
698 actions[NK_Op][IN_I] = IA_AddIf;
699 actions[NK_Op][IN_W] = IA_AddWhile;
700 actions[NK_Op][IN_N] = IA_AddNum;
701 actions[NK_Op][IN_S] = IA_AddStr;
702 actions[NK_Op][IN_C] = IA_AddCall;
703 actions[NK_Op][IN_O] = IA_AddOp;
708 static InputAction actions[NK_COUNT][IN_COUNT];
709 SetupInputActions(actions);
712 vt100EnableAlternateBuffer();
715 Node *n = GetNode(actions);
717 vt100DisableAlternateBuffer();