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.

introduce named style variables for cprintf

+155 -27
+154 -26
src/cli/cprintf.c
··· 15 15 * <#RRGGBB> or <#RGB> for arbitrary 24-bit foreground colors 16 16 * <pad=N> ... </pad> - right-pad contents to N visible columns 17 17 * <rpad=N> ... </rpad> - left-pad (right-align) contents to N visible columns 18 + * <let name=style1+style2+...> - define a named style variable 19 + * <$name> to apply a previously defined style variable 18 20 * </tagname> or </> to reset 19 21 * 20 22 */ ··· 40 42 OP_SET_BOLD, 41 43 OP_SET_DIM, 42 44 OP_SET_UL, 45 + OP_STYLE_PUSH, 43 46 OP_STYLE_FLUSH, 44 47 OP_STYLE_RESET, 45 48 OP_PAD_BEGIN, ··· 75 78 int width; 76 79 int right_align; 77 80 } pad_entry_t; 81 + 82 + typedef struct { 83 + uint32_t fg; 84 + uint32_t bg; 85 + uint32_t fg_rgb; 86 + uint32_t bg_rgb; 87 + int bold; 88 + int dim; 89 + int ul; 90 + } style_entry_t; 78 91 79 92 typedef struct { 80 93 uint32_t fg; ··· 85 98 int bold; 86 99 int dim; 87 100 int ul; 101 + 102 + style_entry_t style_stack[8]; 103 + int style_depth; 88 104 89 105 pad_entry_t pad_stack[8]; 90 106 int pad_depth; 91 107 } vm_regs_t; 108 + 109 + #define MAX_VARS 16 110 + #define MAX_VAR_NAME 32 111 + #define MAX_VAR_VALUE 128 112 + 113 + typedef struct { 114 + char name[MAX_VAR_NAME]; 115 + char value[MAX_VAR_VALUE]; 116 + int nlen; int vlen; 117 + } cprintf_var_t; 118 + 119 + typedef struct { 120 + cprintf_var_t vars[MAX_VARS]; 121 + int count; 122 + } var_table_t; 92 123 93 124 struct program_t { 94 125 instruction_t *code; ··· 260 291 return sep; 261 292 } 262 293 263 - static int compile_tag(program_t *p, const char *tag, int len, int closing) { 294 + static int match_plus_seg(program_t *p, const char *seg, int slen) { 295 + if (match_attr(p, seg, slen)) return 1; 296 + if (match_fg(p, seg, slen)) return 1; 297 + if (match_bg(p, seg, slen)) return 1; 298 + if (slen > 0 && seg[0] == '#') return compile_hex_fg(p, seg, slen); 299 + if (tag_prefix(seg, slen, "bg_#")) return compile_hex_bg(p, seg + 3, slen - 3); 300 + if (tag_prefix(seg, slen, "bg_")) return match_seg_bg(p, seg + 3, slen - 3); 301 + return 0; 302 + } 303 + 304 + static int compile_plus_segs(program_t *p, const char *s, int len) { 305 + const char *seg = s; 306 + const char *end = s + len; 307 + int emitted = 0; 308 + 309 + while (seg < end) { 310 + const char *next = seg; 311 + while (next < end && *next != '+') next++; 312 + int slen = (int)(next - seg); 313 + if (!match_plus_seg(p, seg, slen)) return 0; 314 + emitted++; seg = (next < end) ? next + 1 : end; 315 + } 316 + 317 + return emitted; 318 + } 319 + 320 + static int compile_let(var_table_t *vars, const char *tag, int len) { 321 + const char *eq = memchr(tag + 4, '=', len - 4); 322 + if (!eq) return 0; 323 + 324 + int nlen = (int)(eq - (tag + 4)); 325 + int vlen = (int)((tag + len) - (eq + 1)); 326 + if (nlen <= 0 || nlen >= MAX_VAR_NAME || vlen <= 0 || vlen >= MAX_VAR_VALUE) return 0; 327 + if (vars->count >= MAX_VARS) return 0; 328 + 329 + cprintf_var_t *v = &vars->vars[vars->count++]; 330 + memcpy(v->name, tag + 4, nlen); 331 + v->name[nlen] = '\0'; v->nlen = nlen; 332 + 333 + memcpy(v->value, eq + 1, vlen); 334 + v->value[vlen] = '\0'; v->vlen = vlen; 335 + return 1; 336 + } 337 + 338 + static int compile_var_ref(program_t *p, var_table_t *vars, const char *tag, int len) { 339 + int nlen = len - 1; 340 + for (int i = 0; i < vars->count; i++) { 341 + if (nlen == vars->vars[i].nlen && memcmp(tag + 1, vars->vars[i].name, nlen) == 0) { 342 + emit_op(p, OP_STYLE_PUSH, 0); 343 + if (!compile_plus_segs(p, vars->vars[i].value, vars->vars[i].vlen)) return 0; 344 + emit_op(p, OP_STYLE_FLUSH, 0); 345 + return 1; 346 + } 347 + } 348 + return 0; 349 + } 350 + 351 + static int compile_tag(program_t *p, const char *tag, int len, int closing, var_table_t *vars) { 264 352 if (closing) { 265 353 if (tag_eq(tag, len, "pad") || tag_eq(tag, len, "rpad")) emit_op(p, OP_PAD_END, 0); 266 354 else emit_op(p, OP_STYLE_RESET, 0); 267 355 return 1; 268 356 } 269 357 358 + if (tag_prefix(tag, len, "let ")) return compile_let(vars, tag, len); 359 + if (tag[0] == '$' && len > 1) return compile_var_ref(p, vars, tag, len); 360 + 270 361 if (tag_prefix(tag, len, "pad=")) { emit_op(p, OP_PAD_BEGIN, (uint32_t)atoi(tag + 4)); return 1; } 271 362 if (tag_prefix(tag, len, "rpad=")) { emit_op(p, OP_RPAD_BEGIN, (uint32_t)atoi(tag + 5)); return 1; } 363 + 364 + emit_op(p, OP_STYLE_PUSH, 0); 272 365 273 366 if (match_attr(p, tag, len)) { emit_op(p, OP_STYLE_FLUSH, 0); return 1; } 274 367 if (match_fg(p, tag, len)) { emit_op(p, OP_STYLE_FLUSH, 0); return 1; } ··· 313 406 emit_op(p, OP_EMIT_LIT, off); 314 407 } 315 408 316 - static const char *scan_tag(program_t *p, const char *ptr, const char **lit) { 409 + static const char *scan_tag(program_t *p, const char *ptr, const char **lit, var_table_t *vars) { 317 410 flush_lit(p, *lit, ptr); 318 411 319 412 const char *start = ptr + 1; ··· 329 422 const char *end = start; 330 423 while (*end && *end != '>') end++; 331 424 332 - if (*end == '>' && compile_tag(p, start, (int)(end - start), closing)) { 425 + if (*end == '>' && compile_tag(p, start, (int)(end - start), closing, vars)) { 333 426 *lit = end + 1; 334 427 return *lit; 335 428 } ··· 404 497 405 498 program_t *cprintf_compile(const char *fmt) { 406 499 program_t *p = program_new(); 500 + var_table_t vars = {0}; 407 501 const char *ptr = fmt; 408 502 const char *lit = ptr; 409 503 410 504 while (*ptr) { 411 505 if (*ptr == '<') 412 - ptr = scan_tag(p, ptr, &lit); 506 + ptr = scan_tag(p, ptr, &lit, &vars); 413 507 else if (*ptr == '%' && ptr[1] && ptr[1] != '%') 414 508 ptr = scan_fmt(p, ptr, &lit); 415 509 else if (*ptr == '%' && ptr[1] == '%') ··· 459 553 [OP_SET_BOLD] = &&op_set_bold, 460 554 [OP_SET_DIM] = &&op_set_dim, 461 555 [OP_SET_UL] = &&op_set_ul, 556 + [OP_STYLE_PUSH] = &&op_style_push, 462 557 [OP_STYLE_FLUSH] = &&op_style_flush, 463 558 [OP_STYLE_RESET] = &&op_style_reset, 464 559 [OP_PAD_BEGIN] = &&op_pad_begin, ··· 556 651 NEXT(); 557 652 } 558 653 559 - op_style_reset: { 560 - regs.fg = COL_NONE; regs.bg = COL_NONE; 561 - regs.fg_rgb = 0; regs.bg_rgb = 0; 562 - regs.bold = 0; regs.dim = 0; regs.ul = 0; 563 - if (!io_no_color) { OUT_CSTR("\x1b[0m"); } 654 + op_style_push: { 655 + if (regs.style_depth < 8) regs.style_stack[regs.style_depth++] = (style_entry_t){ 656 + regs.fg, regs.bg, regs.fg_rgb, regs.bg_rgb, regs.bold, regs.dim, regs.ul, 657 + }; 564 658 NEXT(); 565 659 } 566 660 ··· 569 663 = (pad_entry_t){ pos, (int)ip->operand, 0 }; 570 664 NEXT(); 571 665 } 572 - 666 + 573 667 op_rpad_begin: { 574 668 if (regs.pad_depth < 8) regs.pad_stack[regs.pad_depth++] 575 669 = (pad_entry_t){ pos, (int)ip->operand, 1 }; 576 670 NEXT(); 577 671 } 672 + 673 + op_pad_end: { 674 + if (regs.pad_depth <= 0) NEXT(); 675 + regs.pad_depth--; 676 + pad_entry_t pe = regs.pad_stack[regs.pad_depth]; 677 + size_t vis = visible_len(out + pe.mark, pos - pe.mark); 678 + if ((size_t)pe.width <= vis) NEXT(); 679 + 680 + size_t pad_n = pe.width - vis; 681 + ENSURE(pad_n); 682 + if (pe.right_align) { 683 + memmove(out + pe.mark + pad_n, out + pe.mark, pos - pe.mark); 684 + memset(out + pe.mark, ' ', pad_n); 685 + } else memset(out + pos, ' ', pad_n); 686 + 687 + pos += pad_n; 688 + NEXT(); 689 + } 578 690 579 - op_style_flush: { 691 + op_style_reset: { 692 + if (regs.style_depth > 0) { 693 + style_entry_t se = regs.style_stack[--regs.style_depth]; 694 + regs.fg = se.fg; regs.bg = se.bg; 695 + regs.fg_rgb = se.fg_rgb; regs.bg_rgb = se.bg_rgb; 696 + regs.bold = se.bold; regs.dim = se.dim; regs.ul = se.ul; 697 + } else { 698 + regs.fg = COL_NONE; regs.bg = COL_NONE; 699 + regs.fg_rgb = 0; regs.bg_rgb = 0; 700 + regs.bold = 0; regs.dim = 0; regs.ul = 0; 701 + } 702 + 580 703 if (!io_no_color) { 581 704 char esc[128]; 582 705 int n = snprintf(esc, sizeof(esc), "\x1b[0m"); ··· 595 718 n += snprintf(esc+n, sizeof(esc)-n, "\x1b[%dm", regs.bg + 10); 596 719 OUT_STR(esc, (size_t)n); 597 720 } 721 + 598 722 NEXT(); 599 723 } 600 - 601 - op_pad_end: { 602 - if (regs.pad_depth <= 0) NEXT(); 603 - regs.pad_depth--; 604 - pad_entry_t pe = regs.pad_stack[regs.pad_depth]; 605 - size_t vis = visible_len(out + pe.mark, pos - pe.mark); 606 - if ((size_t)pe.width <= vis) NEXT(); 607 724 608 - size_t pad_n = pe.width - vis; 609 - ENSURE(pad_n); 610 - if (pe.right_align) { 611 - memmove(out + pe.mark + pad_n, out + pe.mark, pos - pe.mark); 612 - memset(out + pe.mark, ' ', pad_n); 613 - } else memset(out + pos, ' ', pad_n); 614 - 615 - pos += pad_n; 725 + op_style_flush: { 726 + if (!io_no_color) { 727 + char esc[128]; 728 + int n = snprintf(esc, sizeof(esc), "\x1b[0m"); 729 + if (regs.bold) n += snprintf(esc+n, sizeof(esc)-n, "\x1b[1m"); 730 + if (regs.dim) n += snprintf(esc+n, sizeof(esc)-n, "\x1b[2m"); 731 + if (regs.ul) n += snprintf(esc+n, sizeof(esc)-n, "\x1b[4m"); 732 + if (regs.fg == COL_RGB) 733 + n += snprintf(esc+n, sizeof(esc)-n, "\x1b[38;2;%d;%d;%dm", 734 + UNPACK_R(regs.fg_rgb), UNPACK_G(regs.fg_rgb), UNPACK_B(regs.fg_rgb)); 735 + else if (regs.fg) 736 + n += snprintf(esc+n, sizeof(esc)-n, "\x1b[%dm", regs.fg); 737 + if (regs.bg == COL_RGB) 738 + n += snprintf(esc+n, sizeof(esc)-n, "\x1b[48;2;%d;%d;%dm", 739 + UNPACK_R(regs.bg_rgb), UNPACK_G(regs.bg_rgb), UNPACK_B(regs.bg_rgb)); 740 + else if (regs.bg) 741 + n += snprintf(esc+n, sizeof(esc)-n, "\x1b[%dm", regs.bg + 10); 742 + OUT_STR(esc, (size_t)n); 743 + } 616 744 NEXT(); 617 745 } 618 746
+1 -1
src/main.c
··· 288 288 289 289 if (help->count > 0) { 290 290 cprintf("<bold_red>Ant</> is a tiny JavaScript runtime and package manager (%s)\n\n", ANT_VERSION); 291 - printf("%sUsage: ant %s[...options] %s[module.js]\n%s", C_BOLD, C_CYAN, C_YELLOW, C_RESET); 291 + cprintf("<bold>Usage: ant <cyan>[...options]</cyan> <yellow>[module.js]\n</>"); 292 292 printf("%s ant <command> %s[...args]%s\n\n", C_BOLD, C_CYAN, C_RESET); 293 293 print_subcommands(); 294 294 printf("If no module file is specified, ant starts in REPL mode.\n\n");