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 syntax and case transformations

+107 -11
+102 -6
src/cli/cprintf.c
··· 21 21 * <space=N/> - emit N spaces 22 22 * <gap=N/> - emit N spaces (alias for space) 23 23 * <let name=style1+style2+...> or <let name=style1, name2=style2...> - define a named style variable 24 - * <$name> to apply a previously defined style variable 24 + * {let name=style1+style2+...} or {let name=style1, name2=style2...} - alternative syntax 25 + * quoted values: {let label='hello'} or <let label="world"/> - quotes are stripped from value 26 + * <$name> to apply a variable as a style, {name} to emit its value as literal text 27 + * {~name} for lowercase, {^name} for uppercase 25 28 * </tagname> or </> to reset (pops one level) 26 29 * <reset/> to reset all styles (clears entire stack) 27 30 * << and >> to emit literal < and > ··· 349 352 350 353 const char *vstart = eq + 1; 351 354 const char *vend = vstart; 355 + 356 + if (vstart < end && (*vstart == '\'' || *vstart == '"')) { 357 + char quote = *vstart; 358 + vstart++; 359 + vend = vstart; 360 + 361 + while (vend < end && *vend != quote) vend++; 362 + if (vend >= end) return 0; 363 + const char *after = vend + 1; 364 + 365 + while (after < end && (*after == ' ' || *after == ',')) after++; 366 + int vlen = (int)(vend - vstart); 367 + 368 + if (nlen <= 0 || nlen >= MAX_VAR_NAME || vlen < 0 || vlen >= MAX_VAR_VALUE) return 0; 369 + if (vars->count >= MAX_VARS) return 0; 370 + 371 + cprintf_var_t *v = &vars->vars[vars->count++]; 372 + memcpy(v->name, p, nlen); 373 + 374 + v->name[nlen] = '\0'; v->nlen = nlen; 375 + memcpy(v->value, vstart, vlen); 376 + 377 + v->value[vlen] = '\0'; v->vlen = vlen; 378 + p = after; 379 + 380 + continue; 381 + } 382 + 352 383 while (vend < end && *vend != ',') vend++; 353 384 354 385 int vlen = (int)(vend - vstart); ··· 573 604 return *lit; 574 605 } 575 606 607 + static void transform_case(char *dst, const char *src, int len, int lower) { 608 + for (int i = 0; i < len; i++) dst[i] = (char)(lower 609 + ? tolower((unsigned char)src[i]) 610 + : toupper((unsigned char)src[i]) 611 + ); 612 + } 613 + 614 + static const char *scan_var_brace(program_t *p, const char *ptr, const char **lit, var_table_t *vars) { 615 + flush_lit(p, *lit, ptr); 616 + 617 + const char *name = ptr + 1; 618 + const char *end = name; 619 + while (*end && *end != '}') end++; 620 + 621 + if (*end != '}') goto emit_brace; 622 + 623 + int lower = 0, upper = 0; 624 + if (*name == '~') { lower = 1; name++; } 625 + else if (*name == '^') { upper = 1; name++; } 626 + int nlen = (int)(end - name); 627 + 628 + for (int i = 0; i < vars->count; i++) { 629 + cprintf_var_t *v = &vars->vars[i]; 630 + if (nlen != v->nlen || memcmp(name, v->name, nlen) != 0) continue; 631 + 632 + const char *val = v->value; 633 + int vlen = v->vlen; 634 + char buf[MAX_VAR_VALUE]; 635 + if (lower || upper) { 636 + transform_case(buf, val, vlen, lower); 637 + val = buf; 638 + } 639 + uint32_t off = add_literal(p, val, vlen); 640 + emit_op(p, OP_EMIT_LIT, off); 641 + *lit = end + 1; 642 + return *lit; 643 + } 644 + 645 + emit_brace:; 646 + uint32_t off = add_literal(p, "{", 1); 647 + emit_op(p, OP_EMIT_LIT, off); 648 + *lit = ptr + 1; 649 + return *lit; 650 + } 651 + 652 + static const char *scan_let_brace(program_t *p, const char *ptr, const char **lit, var_table_t *vars) { 653 + flush_lit(p, *lit, ptr); 654 + 655 + const char *body = ptr + 5; 656 + const char *end = body; 657 + while (*end && *end != '}') end++; 658 + 659 + if (*end == '}' && compile_let(vars, body, (int)(end - body))) { 660 + *lit = end + 1; 661 + return *lit; 662 + } 663 + 664 + uint32_t off = add_literal(p, "{", 1); 665 + emit_op(p, OP_EMIT_LIT, off); 666 + *lit = ptr + 1; 667 + return *lit; 668 + } 669 + 576 670 program_t *cprintf_compile(const char *fmt) { 577 671 program_t *p = program_new(); 578 672 var_table_t vars = {0}; ··· 580 674 const char *lit = ptr; 581 675 582 676 while (*ptr) { 583 - if (*ptr == '<' && ptr[1] == '<') ptr = scan_escape(p, ptr, &lit, "<", 1); 584 - else if (*ptr == '>' && ptr[1] == '>') ptr = scan_escape(p, ptr, &lit, ">", 1); 585 - else if (*ptr == '%' && ptr[1] == '%') ptr = scan_escape(p, ptr, &lit, "%%", 2); 586 - else if (*ptr == '<') ptr = scan_tag(p, ptr, &lit, &vars); 587 - else if (*ptr == '%' && ptr[1] && ptr[1] != '%') ptr = scan_fmt(p, ptr, &lit); 677 + if (*ptr == '<' && ptr[1] == '<') ptr = scan_escape(p, ptr, &lit, "<", 1); 678 + else if (*ptr == '>' && ptr[1] == '>') ptr = scan_escape(p, ptr, &lit, ">", 1); 679 + else if (*ptr == '%' && ptr[1] == '%') ptr = scan_escape(p, ptr, &lit, "%%", 2); 680 + else if (*ptr == '{' && memcmp(ptr, "{let ", 5) == 0) ptr = scan_let_brace(p, ptr, &lit, &vars); 681 + else if (*ptr == '{') ptr = scan_var_brace(p, ptr, &lit, &vars); 682 + else if (*ptr == '<') ptr = scan_tag(p, ptr, &lit, &vars); 683 + else if (*ptr == '%' && ptr[1] && ptr[1] != '%') ptr = scan_fmt(p, ptr, &lit); 588 684 else ptr++; 589 685 } 590 686
+5 -5
src/main.c
··· 303 303 304 304 if (help->count > 0) { 305 305 cprintf( 306 - "<let h=bold, arg=cyan/>" 307 - "<$h+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/>", 306 + "{let h=bold, arg=cyan, name='Ant'}" 307 + "<$h+red>{name}</> is a tiny JavaScript runtime and package manager (%s)<br=2/>" 308 + "<$h>Usage: {~name} <yellow>[module.js]</yellow> <$arg>[...flags]</><reset/><br/>" 309 + "<$h><gap=7/>{~name} <<command>><gap=3/><$arg>[...args]</><reset/><br=2/>" 310 + "If no module file is specified, {name} starts in REPL mode.<br=2/>", 311 311 ANT_VERSION 312 312 ); 313 313