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.

enhance cprintf formatting with <br=val/>

+96 -37
+84 -33
src/cli/cprintf.c
··· 12 12 * <gray/grey> <bright_red> <bright_green> ... etc 13 13 * <bg_red> <bg_green> ... <bg_#RGB> <bg_#RRGGBB> 14 14 * <bold> <dim> <ul> (underline) 15 + * <bold_red> <dim_cyan> etc - combine styles with underscores 15 16 * <#RRGGBB> or <#RGB> for arbitrary 24-bit foreground colors 16 17 * <pad=N> ... </pad> - right-pad contents to N visible columns 18 + * <br/> - emit a newline, <br=N/> - emit N newlines 17 19 * <rpad=N> ... </rpad> - left-pad (right-align) contents to N visible columns 18 - * <let name=style1+style2+...> - define a named style variable 20 + * <space=N/> - emit N spaces 21 + * <gap=N/> - emit N spaces (alias for space) 22 + * <let name=style1+style2+...> or <let name=style1, name2=style2...> - define a named style variable 19 23 * <$name> to apply a previously defined style variable 20 24 * </tagname> or </> to reset (pops one level) 21 25 * <reset/> to reset all styles (clears entire stack) 22 26 * << and >> to emit literal < and > 27 + * %% to emit a literal % 23 28 * 24 29 */ 25 30 ··· 56 61 OP_RPAD_BEGIN, 57 62 OP_PAD_END, 58 63 OP_EMIT_SPACES, 64 + OP_EMIT_NEWLINES, 59 65 OP_HALT, 60 66 OP_MAX 61 67 } opcode_t; ··· 325 331 return emitted; 326 332 } 327 333 328 - static int compile_let(var_table_t *vars, const char *tag, int len) { 329 - const char *eq = memchr(tag + 4, '=', len - 4); 330 - if (!eq) return 0; 334 + static int compile_let(var_table_t *vars, const char *body, int len) { 335 + if (len > 0 && body[len - 1] == '/') len--; 336 + 337 + const char *p = body; 338 + const char *end = body + len; 339 + 340 + while (p < end) { 341 + while (p < end && (*p == ' ' || *p == ',')) p++; 342 + if (p >= end) break; 331 343 332 - int nlen = (int)(eq - (tag + 4)); 333 - int vlen = (int)((tag + len) - (eq + 1)); 334 - if (nlen <= 0 || nlen >= MAX_VAR_NAME || vlen <= 0 || vlen >= MAX_VAR_VALUE) return 0; 335 - if (vars->count >= MAX_VARS) return 0; 344 + const char *eq = memchr(p, '=', end - p); 345 + if (!eq) return 0; 346 + 347 + int nlen = (int)(eq - p); 348 + 349 + const char *vstart = eq + 1; 350 + const char *vend = vstart; 351 + while (vend < end && *vend != ',') vend++; 352 + 353 + int vlen = (int)(vend - vstart); 354 + if (nlen <= 0 || nlen >= MAX_VAR_NAME || vlen <= 0 || vlen >= MAX_VAR_VALUE) return 0; 355 + if (vars->count >= MAX_VARS) return 0; 356 + 357 + cprintf_var_t *v = &vars->vars[vars->count++]; 358 + memcpy(v->name, p, nlen); 359 + v->name[nlen] = '\0'; v->nlen = nlen; 360 + 361 + memcpy(v->value, vstart, vlen); 362 + v->value[vlen] = '\0'; v->vlen = vlen; 363 + p = vend; 364 + } 336 365 337 - cprintf_var_t *v = &vars->vars[vars->count++]; 338 - memcpy(v->name, tag + 4, nlen); 339 - v->name[nlen] = '\0'; v->nlen = nlen; 340 - 341 - memcpy(v->value, eq + 1, vlen); 342 - v->value[vlen] = '\0'; v->vlen = vlen; 343 366 return 1; 344 367 } 345 368 ··· 363 386 return 1; 364 387 } 365 388 366 - if (tag_prefix(tag, len, "let ")) return compile_let(vars, tag, len); 389 + if (tag_prefix(tag, len, "let ")) return compile_let(vars, tag + 4, len - 4); 367 390 if (tag[0] == '$' && len > 1) return compile_var_ref(p, vars, tag, len); 368 391 369 392 if (tag_prefix(tag, len, "pad=")) { emit_op(p, OP_PAD_BEGIN, (uint32_t)atoi(tag + 4)); return 1; } ··· 373 396 emit_op(p, OP_EMIT_SPACES, (uint32_t)atoi(tag + 6)); 374 397 return 1; 375 398 } 399 + 400 + if (tag_prefix(tag, len, "gap=") && tag[len-1] == '/') { 401 + emit_op(p, OP_EMIT_SPACES, (uint32_t)atoi(tag + 4)); 402 + return 1; 403 + } 376 404 377 405 if (tag_eq(tag, len, "reset/")) { 378 406 emit_op(p, OP_STYLE_RESET_ALL, 0); 379 407 return 1; 380 408 } 409 + 410 + if (tag_eq(tag, len, "br/")) { 411 + emit_op(p, OP_EMIT_NEWLINES, 1); 412 + return 1; 413 + } 414 + 415 + if (tag_prefix(tag, len, "br=") && tag[len-1] == '/') { 416 + emit_op(p, OP_EMIT_NEWLINES, (uint32_t)atoi(tag + 3)); 417 + return 1; 418 + } 381 419 382 420 emit_op(p, OP_STYLE_PUSH, 0); 383 421 ··· 568 606 569 607 const instruction_t *ip = prog->code; 570 608 static const void *dispatch[OP_MAX] = { 571 - [OP_NOP] = &&op_nop, 572 - [OP_EMIT_LIT] = &&op_emit_lit, 573 - [OP_EMIT_FMT] = &&op_emit_fmt, 574 - [OP_SET_FG] = &&op_set_fg, 575 - [OP_SET_BG] = &&op_set_bg, 576 - [OP_SET_FG_RGB] = &&op_set_fg_rgb, 577 - [OP_SET_BG_RGB] = &&op_set_bg_rgb, 578 - [OP_SET_BOLD] = &&op_set_bold, 579 - [OP_SET_DIM] = &&op_set_dim, 580 - [OP_SET_UL] = &&op_set_ul, 581 - [OP_STYLE_PUSH] = &&op_style_push, 582 - [OP_STYLE_FLUSH] = &&op_style_flush, 609 + [OP_NOP] = &&op_nop, 610 + [OP_EMIT_LIT] = &&op_emit_lit, 611 + [OP_EMIT_FMT] = &&op_emit_fmt, 612 + [OP_SET_FG] = &&op_set_fg, 613 + [OP_SET_BG] = &&op_set_bg, 614 + [OP_SET_FG_RGB] = &&op_set_fg_rgb, 615 + [OP_SET_BG_RGB] = &&op_set_bg_rgb, 616 + [OP_SET_BOLD] = &&op_set_bold, 617 + [OP_SET_DIM] = &&op_set_dim, 618 + [OP_SET_UL] = &&op_set_ul, 619 + [OP_STYLE_PUSH] = &&op_style_push, 620 + [OP_STYLE_FLUSH] = &&op_style_flush, 583 621 [OP_STYLE_RESET] = &&op_style_reset, 584 622 [OP_STYLE_RESET_ALL] = &&op_style_reset_all, 585 623 [OP_PAD_BEGIN] = &&op_pad_begin, 586 - [OP_RPAD_BEGIN] = &&op_rpad_begin, 587 - [OP_PAD_END] = &&op_pad_end, 588 - [OP_EMIT_SPACES] = &&op_emit_spaces, 589 - [OP_HALT] = &&op_halt, 624 + [OP_RPAD_BEGIN] = &&op_rpad_begin, 625 + [OP_PAD_END] = &&op_pad_end, 626 + [OP_EMIT_SPACES] = &&op_emit_spaces, 627 + [OP_EMIT_NEWLINES] = &&op_emit_newlines, 628 + [OP_HALT] = &&op_halt, 590 629 }; 591 630 592 631 #define DISPATCH() goto *dispatch[ip->op] ··· 722 761 pos += n; 723 762 NEXT(); 724 763 } 764 + 765 + op_emit_newlines: { 766 + size_t n = (size_t)ip->operand; 767 + ENSURE(n); 768 + memset(out + pos, '\n', n); 769 + pos += n; 770 + NEXT(); 771 + } 725 772 726 773 op_style_reset: { 727 774 if (regs.style_depth > 0) { ··· 841 888 [OP_RPAD_BEGIN] = "RPAD_BEGIN", 842 889 [OP_PAD_END] = "PAD_END", 843 890 [OP_EMIT_SPACES] = "EMIT_SPACES", 891 + [OP_EMIT_NEWLINES] = "EMIT_NEWLINES", 844 892 [OP_HALT] = "HALT", 845 893 }; 846 894 ··· 940 988 case OP_EMIT_SPACES: 941 989 fprintf(out, "%u", ins->operand); 942 990 break; 991 + 992 + case OP_EMIT_NEWLINES: 993 + fprintf(out, "%u", ins->operand); 994 + break; 943 995 944 996 case OP_NOP: 945 997 case OP_STYLE_PUSH: ··· 947 999 case OP_STYLE_RESET: 948 1000 case OP_STYLE_RESET_ALL: 949 1001 case OP_PAD_END: 950 - case OP_HALT: 951 - break; 1002 + case OP_HALT: break; 952 1003 953 1004 default: 954 1005 if (compact) {
+12 -4
src/main.c
··· 302 302 int nerrors = arg_parse(argc, argv, argtable); 303 303 304 304 if (help->count > 0) { 305 - cprintf("<bold_red>Ant</> is a tiny JavaScript runtime and package manager (%s)\n\n", ANT_VERSION); 306 - cprintf("<bold>Usage: ant <yellow>[module.js]</yellow> <cyan>[...flags]</><reset/>\n"); 307 - cprintf("<bold><space=7/>ant <<command>><space=3/><cyan>[...args]</><reset/>\n\n"); 308 - printf("If no module file is specified, Ant starts in REPL mode.\n\n"); 305 + cprintf( 306 + "<let h=bold, arg=cyan/>" 307 + "<bold_red>Ant</> is a tiny JavaScript runtime and package manager (%s)<br=2/>" 308 + "<$h>Usage: ant <yellow>[module.js]</yellow> <$arg>[...flags]</><reset/><br/>" 309 + "<$h><gap=7/>ant <<command>><gap=3/><$arg>[...args]</><reset/><br=2/>" 310 + "If no module file is specified, Ant starts in REPL mode.<br=2/>", 311 + ANT_VERSION 312 + ); 313 + 309 314 print_subcommands(); 310 315 cprintf("<bold>Flags:</>\n"); 316 + 311 317 print_flags_help(stdout, argtable); 312 318 print_flag(stdout, (flag_help_t){ .l = "verbose", .g = "enable verbose output" }); 313 319 print_flag(stdout, (flag_help_t){ .l = "no-color", .g = "disable colored output" }); 320 + 314 321 arg_freetable(argtable, ARGTABLE_COUNT); 315 322 free(filtered_argv); 323 + 316 324 return EXIT_SUCCESS; 317 325 } 318 326