MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

allow multi-line repl history

+57 -7
+50 -6
src/readline.c
··· 1 1 #include <ctype.h> 2 + #include <stdint.h> 2 3 #include <signal.h> 3 4 #include <stdio.h> 4 5 #include <stdlib.h> ··· 26 27 27 28 #define MAX_LINE_LENGTH 4096 28 29 30 + static const unsigned char HISTORY_FILE_MAGIC[] = { 31 + 0x61, 0x6E, 0x74, 0x72, 0x65, 0x70, 0x6C, 0x73, 32 + 0x63, 0x68, 0x65, 0x6D, 0x61, 0x32, 0x0A, 0x00 33 + }; 34 + 29 35 static volatile sig_atomic_t ctrl_c_pressed = 0; 30 36 static crprintf_compiled *hl_prog = NULL; 37 + 31 38 static highlight_state hl_line_state = HL_STATE_INIT; 32 39 static int repl_last_cursor_row = 0; 33 40 34 41 static void sigint_handler(int sig) { 35 - (void)sig; 36 42 ctrl_c_pressed++; 37 43 } 38 44 ··· 118 124 119 125 void ant_history_load(ant_history_t *hist) { 120 126 if (!hist || !hist->lines || hist->capacity <= 0) return; 127 + 121 128 char *path = get_history_path(); 122 129 if (!path) return; 123 130 124 131 FILE *fp = fopen(path, "r"); 125 132 free(path); 133 + 126 134 if (!fp) return; 135 + char header[sizeof(HISTORY_FILE_MAGIC)]; 136 + 137 + if ( 138 + !fgets(header, sizeof(header), fp) || 139 + strcmp(header, (const char *)HISTORY_FILE_MAGIC) != 0 140 + ) { 141 + fclose(fp); 142 + return; 143 + } 127 144 128 - char line[MAX_LINE_LENGTH]; 129 - while (fgets(line, sizeof(line), fp)) { 130 - size_t len = strlen(line); 131 - if (len > 0 && line[len - 1] == '\n') line[len - 1] = '\0'; 145 + char lenbuf[32]; 146 + while (fgets(lenbuf, sizeof(lenbuf), fp)) { 147 + char *end = NULL; 148 + unsigned long long record_len = strtoull(lenbuf, &end, 10); 149 + 150 + if (end == lenbuf || (*end != '\n' && *end != '\0')) break; 151 + if (record_len > (unsigned long long)SIZE_MAX - 1) break; 152 + 153 + size_t line_len = (size_t)record_len; 154 + char *line = malloc(line_len + 1); 155 + 156 + if (!line) break; 157 + 158 + if (fread(line, 1, line_len, fp) != line_len) { 159 + free(line); 160 + break; 161 + } 162 + 163 + line[line_len] = '\0'; 132 164 if (line[0]) ant_history_add(hist, line); 165 + free(line); 166 + 167 + int sep = fgetc(fp); 168 + if (sep != '\n' && sep != EOF) break; 133 169 } 170 + 134 171 fclose(fp); 135 172 } 136 173 137 174 void ant_history_save(const ant_history_t *hist) { 138 175 if (!hist || !hist->lines) return; 176 + 139 177 char *path = get_history_path(); 140 178 if (!path) return; 141 179 142 180 FILE *fp = fopen(path, "w"); 143 181 free(path); 182 + 144 183 if (!fp) return; 184 + fputs((const char *)HISTORY_FILE_MAGIC, fp); 145 185 146 186 for (int i = 0; i < hist->count; i++) { 147 - fprintf(fp, "%s\n", hist->lines[i]); 187 + size_t len = strlen(hist->lines[i]); 188 + fprintf(fp, "%zu\n", len); 189 + fwrite(hist->lines[i], 1, len, fp); 190 + fputc('\n', fp); 148 191 } 192 + 149 193 fclose(fp); 150 194 } 151 195
+7 -1
src/repl.c
··· 532 532 int template_count, template_cap; 533 533 char string_char; 534 534 bool in_string, escaped; 535 + char last_code_char; 535 536 } parse_state_t; 536 537 537 538 static void push_template(parse_state_t *s) { ··· 585 586 case '[': s.bracket++; break; case ']': s.bracket--; break; 586 587 case '{': s.brace++; break; case '}': s.brace--; break; 587 588 } 589 + if (!isspace((unsigned char)c)) s.last_code_char = c; 588 590 } 589 591 590 - bool incomplete = s.in_string || s.template_count > 0 || s.paren > 0 || s.bracket > 0 || s.brace > 0; 592 + bool incomplete = 593 + s.in_string || s.template_count > 0 || 594 + s.paren > 0 || s.bracket > 0 || s.brace > 0 || 595 + s.last_code_char == ','; 596 + 591 597 free(s.templates); 592 598 return incomplete; 593 599 }