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.

copy command

+119 -3
+119 -3
src/repl.c
··· 25 25 #include "reactor.h" 26 26 #include "runtime.h" 27 27 #include "internal.h" 28 + #include "base64.h" 29 + 28 30 #include "silver/ast.h" 29 31 #include "silver/engine.h" 30 - #include "modules/io.h" 31 32 32 33 #include <crprintf.h> 34 + #include "modules/io.h" 33 35 #include "highlight.h" 34 36 #include "highlight/regex.h" 35 37 ··· 340 342 static cmd_result_t cmd_load(ant_t *js, history_t *history, const char *arg); 341 343 static cmd_result_t cmd_save(ant_t *js, history_t *history, const char *arg); 342 344 static cmd_result_t cmd_stats(ant_t *js, history_t *history, const char *arg); 345 + static cmd_result_t cmd_copy(ant_t *js, history_t *history, const char *arg); 343 346 344 347 static const repl_command_t commands[] = { 345 348 { "help", "Show this help message", false, cmd_help }, ··· 347 350 { "load", "Load JS from a file into the REPL session", true, cmd_load }, 348 351 { "save", "Save all evaluated commands in this REPL session to a file", true, cmd_save }, 349 352 { "stats", "Show memory statistics", false, cmd_stats }, 353 + { "copy", "Evaluate expression and copy its value", true, cmd_copy }, 350 354 { NULL, NULL, false, NULL } 351 355 }; 352 356 ··· 421 425 return CMD_OK; 422 426 } 423 427 428 + #ifdef _WIN32 429 + static bool repl_stdout_is_tty(void) { 430 + return _isatty(_fileno(stdout)) != 0; 431 + } 432 + 433 + static bool repl_copy_with_osc52(const char *data, size_t len) { 434 + const char *term = getenv("TERM"); 435 + if (!repl_stdout_is_tty()) return false; 436 + if (term && strcmp(term, "dumb") == 0) return false; 437 + 438 + size_t b64_len = 0; 439 + char *b64 = ant_base64_encode((const uint8_t *)data, len, &b64_len); 440 + (void)b64_len; 441 + if (!b64) return false; 442 + 443 + int rc = fprintf(stdout, "\033]52;c;%s\a", b64); 444 + fflush(stdout); 445 + free(b64); 446 + return rc > 0; 447 + } 448 + 449 + static bool repl_copy_with_command(const char *data, size_t len) { 450 + FILE *pipe = _popen("clip", "wb"); 451 + if (!pipe) return false; 452 + 453 + size_t written = fwrite(data, 1, len, pipe); 454 + int close_rc = _pclose(pipe); 455 + return written == len && close_rc == 0; 456 + } 457 + #else 458 + static bool repl_stdout_is_tty(void) { 459 + return isatty(STDOUT_FILENO) == 1; 460 + } 461 + 462 + static bool repl_copy_with_osc52(const char *data, size_t len) { 463 + const char *term = getenv("TERM"); 464 + if (!repl_stdout_is_tty()) return false; 465 + if (term && strcmp(term, "dumb") == 0) return false; 466 + 467 + size_t b64_len = 0; 468 + char *b64 = ant_base64_encode((const uint8_t *)data, len, &b64_len); 469 + (void)b64_len; 470 + if (!b64) return false; 471 + 472 + int rc = 0; 473 + const char *tmux = getenv("TMUX"); 474 + if (tmux && *tmux) { 475 + rc = fprintf(stdout, "\033Ptmux;\033\033]52;c;%s\a\033\\", b64); 476 + } else { 477 + rc = fprintf(stdout, "\033]52;c;%s\a", b64); 478 + } 479 + 480 + fflush(stdout); 481 + free(b64); 482 + return rc > 0; 483 + } 484 + 485 + static bool repl_copy_with_single_command(const char *cmd, const char *data, size_t len) { 486 + FILE *pipe = popen(cmd, "w"); 487 + if (!pipe) return false; 488 + 489 + size_t written = fwrite(data, 1, len, pipe); 490 + int close_rc = pclose(pipe); 491 + return written == len && close_rc == 0; 492 + } 493 + 494 + static bool repl_copy_with_command(const char *data, size_t len) { 495 + static const char *cmds[] = { 496 + "pbcopy", 497 + "wl-copy", 498 + "xclip -selection clipboard", 499 + "xsel --clipboard --input", 500 + }; 501 + for (size_t i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) { 502 + if (repl_copy_with_single_command(cmds[i], data, len)) return true; 503 + } 504 + return false; 505 + } 506 + #endif 507 + 508 + static cmd_result_t cmd_copy(ant_t *js, history_t *history, const char *arg) { 509 + (void)history; 510 + if (!arg || *arg == '\0') { 511 + fprintf(stderr, "Usage: .copy <expression>\n"); 512 + return CMD_OK; 513 + } 514 + 515 + repl_clear_exception_state(js); 516 + jsval_t result = js_eval_bytecode_repl(js, arg, strlen(arg)); 517 + js_run_event_loop(js); 518 + 519 + if (print_uncaught_throw(js)) return CMD_OK; 520 + 521 + char cbuf[512]; 522 + js_cstr_t cstr = js_to_cstr(js, result, cbuf, sizeof(cbuf)); 523 + bool copied_osc52 = repl_copy_with_osc52(cstr.ptr, cstr.len); 524 + bool copied = copied_osc52 || repl_copy_with_command(cstr.ptr, cstr.len); 525 + 526 + if (cstr.needs_free) free((void *)cstr.ptr); 527 + 528 + if (!copied) { 529 + fprintf(stderr, "Failed to copy to clipboard (no clipboard command available).\n"); 530 + return CMD_OK; 531 + } 532 + 533 + if (copied_osc52) printf("Copied to clipboard (OSC 52).\n"); 534 + else printf("Copied to clipboard.\n"); 535 + return CMD_OK; 536 + } 537 + 424 538 static cmd_result_t execute_command(ant_t *js, history_t *history, const char *line) { 425 539 const char *cmd_start = line + 1; 426 540 ··· 602 716 } else if (len > 0) fwrite(line, 1, (size_t)len, stdout); 603 717 604 718 int end_cols = prompt_len + len; 605 - int end_row = end_cols > 0 ? end_cols / cols : 0; 719 + int end_rows = end_cols > 0 ? (end_cols - 1) / cols + 1 : 1; 720 + int end_row = end_rows - 1; 721 + 606 722 int cursor_cols = prompt_len + pos; 607 723 int cursor_row = cursor_cols > 0 ? cursor_cols / cols : 0; 608 724 int cursor_col = cursor_cols > 0 ? cursor_cols % cols : 0; ··· 621 737 fputs(move_buf, stdout); 622 738 } 623 739 624 - repl_last_render_rows = end_cols > 0 ? end_cols / cols + 1 : 1; 740 + repl_last_render_rows = end_rows; 625 741 626 742 fflush(stdout); 627 743 }