├── test_files ├── hello.sql ├── node_modules │ └── node-fetch │ │ ├── src │ │ └── index.js │ │ └── package.json ├── hello.lua ├── hello.js ├── hello.clj ├── hello_tcl.tcl ├── hi_julia.jl ├── require_node_fetch.js ├── global_bug_submodule.js ├── main_module_scoped_to_global_submodule.js ├── sumofsquares.scala ├── main_module_scoped_to_global.js ├── package.json ├── module_patching.js ├── global_bug.js └── package-lock.json ├── languages ├── lua │ ├── testdata │ │ └── test.lua │ ├── lua_test.go │ ├── pry.h │ ├── pry.c │ ├── main.go │ └── lua.c ├── ruby │ ├── pry_ruby.h │ ├── main.go │ └── pry_ruby.c ├── julia │ ├── julia.pc │ ├── julia.nix │ ├── main.go │ └── pry.h ├── sqlite │ ├── compile │ ├── patch │ │ └── patch.c │ └── main.go ├── python3 │ ├── pry_python3.h │ ├── pry_python3.c │ └── main.go ├── python311 │ ├── pry_python311.h │ ├── pry_python311.c │ └── main.go ├── clojure │ ├── prybar_repl.clj │ ├── wrappedClojure.nix │ ├── deps.nix │ └── main.go ├── tcl │ ├── tcl.pc │ └── main.go ├── ocaml │ ├── README.md │ ├── main.go │ └── repl.ml ├── scala │ └── main.go ├── R │ └── main.go ├── nodejs │ ├── main.go │ └── repl.js └── elisp │ └── main.go ├── osx-env.sh ├── .prettierrc ├── .dockerignore ├── tests ├── sqlite │ ├── exec.exp │ ├── eval.exp │ ├── quiet.exp │ ├── read_file.exp │ ├── 1_plus_1.exp │ └── header.exp ├── clojure │ ├── run_script.exp │ ├── run_code.exp │ ├── quiet_repl.exp │ ├── evaluate_expression.exp │ ├── initialize_expression_with_script.exp │ ├── initialize_code_with_script.exp │ ├── plus_1_1.exp │ ├── initialize_repl_with_script.exp │ ├── print.exp │ └── all.exp ├── nodejs │ ├── run_code.exp │ ├── eval_code.exp │ ├── header.exp │ ├── err.exp │ ├── 1_plus_1.exp │ ├── set_ps1.exp │ ├── printing.exp │ ├── global_bug.exp │ ├── prompt_no_tty.exp │ ├── module_patching.exp │ ├── run_file.exp │ ├── main_module_scoped_to_global.exp │ ├── prompt_escape.exp │ ├── confirm.exp │ ├── node_fetch.exp │ ├── prompt_tty.exp │ ├── prompt_tty_bounds.exp │ └── prompt_tty_escapes.exp ├── python3 │ ├── eval_code.exp │ ├── run_code.exp │ ├── 1_plus_1.exp │ ├── set_ps1.exp │ ├── show_header.exp │ ├── printing.exp │ ├── set_ps2.exp │ └── stderr_red.exp ├── ocaml │ ├── expr.exp │ ├── code_print.exp │ ├── ps1.exp │ ├── not_quiet.exp │ ├── quiet.exp │ ├── exception.exp │ └── ps2.exp ├── tcl │ ├── invalid_command.exp │ ├── unknown_command.exp │ ├── 1_plus_1.exp_skip │ ├── from_file.exp │ ├── input_output.exp │ └── a_few_outputs.exp └── julia │ ├── 1_plus_1.exp │ ├── start_with_file.exp │ ├── print_a_line.exp │ ├── input.exp │ └── header.exp ├── .gitignore ├── prybar_assets ├── nodejs │ ├── node_modules │ │ ├── fetch-blob │ │ │ ├── file.d.ts │ │ │ ├── index.d.ts │ │ │ ├── from.d.ts │ │ │ ├── LICENSE │ │ │ ├── file.js │ │ │ ├── streams.cjs │ │ │ ├── package.json │ │ │ ├── from.js │ │ │ ├── README.md │ │ │ └── index.js │ │ ├── @replit │ │ │ └── node-fetch │ │ │ │ ├── index.js.map │ │ │ │ ├── index.js │ │ │ │ ├── package.json │ │ │ │ ├── README.md │ │ │ │ ├── LICENSE.md │ │ │ │ └── index.d.ts │ │ ├── formdata-polyfill │ │ │ ├── esm.min.d.ts │ │ │ ├── LICENSE │ │ │ ├── formdata-to-blob.js │ │ │ ├── package.json │ │ │ ├── esm.min.js │ │ │ └── README.md │ │ ├── web-streams-polyfill │ │ │ ├── ponyfill │ │ │ │ ├── package.json │ │ │ │ ├── es6 │ │ │ │ │ └── package.json │ │ │ │ └── es2018 │ │ │ │ │ └── package.json │ │ │ ├── es6 │ │ │ │ └── package.json │ │ │ ├── es2018 │ │ │ │ └── package.json │ │ │ ├── dist │ │ │ │ └── types │ │ │ │ │ └── tsdoc-metadata.json │ │ │ ├── LICENSE │ │ │ ├── package.json │ │ │ └── README.md │ │ └── node-domexception │ │ │ ├── index.js │ │ │ ├── package.json │ │ │ ├── LICENSE │ │ │ └── README.md │ ├── package.json │ ├── runCode.js │ └── input-sync.js └── elisp │ └── repl.el ├── inject_claunch.go ├── inject_elaunch.go ├── scripts ├── inject.sh ├── gofiles.sh └── docker-install.sh ├── run_no_pty ├── go.mod ├── Dockerfile.dev ├── Dockerfile ├── default.nix ├── run_tests ├── run_tests_language ├── .circleci └── config.yml ├── go.sum ├── flake.lock ├── utils ├── utils.go └── language.go ├── Makefile ├── flake.nix └── README.md /test_files/hello.sql: -------------------------------------------------------------------------------- 1 | select 'hey there'; 2 | -------------------------------------------------------------------------------- /test_files/node_modules/node-fetch/src/index.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /languages/lua/testdata/test.lua: -------------------------------------------------------------------------------- 1 | print("Hello, World!") -------------------------------------------------------------------------------- /test_files/hello.lua: -------------------------------------------------------------------------------- 1 | a = "hello" 2 | print("hi!") 3 | -------------------------------------------------------------------------------- /test_files/hello.js: -------------------------------------------------------------------------------- 1 | let a = "hello"; 2 | console.log(a); 3 | a; -------------------------------------------------------------------------------- /test_files/hello.clj: -------------------------------------------------------------------------------- 1 | (def a "hello") 2 | (def b 42) 3 | (println a) 4 | -------------------------------------------------------------------------------- /test_files/hello_tcl.tcl: -------------------------------------------------------------------------------- 1 | puts "Hello, Tcl!" 2 | 3 | set my_num 1000 4 | -------------------------------------------------------------------------------- /osx-env.sh: -------------------------------------------------------------------------------- 1 | export PKG_CONFIG_PATH="/usr/local/opt/tcl-tk/lib/pkgconfig/" 2 | -------------------------------------------------------------------------------- /test_files/hi_julia.jl: -------------------------------------------------------------------------------- 1 | my_number = 500 2 | 3 | println("hey from julia") 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "all", 3 | "singleQuote": true 4 | } 5 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | prybar-* 2 | plugins 3 | Dockerfile 4 | extract.sh 5 | deps.lst 6 | prybar.tar.gz 7 | -------------------------------------------------------------------------------- /test_files/require_node_fetch.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | 3 | console.log('ok'); 4 | -------------------------------------------------------------------------------- /test_files/global_bug_submodule.js: -------------------------------------------------------------------------------- 1 | // see global_bug.js 2 | module.exports = { 3 | global, 4 | Object, 5 | } -------------------------------------------------------------------------------- /tests/sqlite/exec.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | spawn ./prybar-sqlite -c "select 1+1;" 4 | expect ^eof 5 | -------------------------------------------------------------------------------- /tests/sqlite/eval.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | spawn ./prybar-sqlite -e "select 1+1;" 4 | expect ^2 5 | expect eof 6 | -------------------------------------------------------------------------------- /test_files/main_module_scoped_to_global_submodule.js: -------------------------------------------------------------------------------- 1 | console.assert(typeof shouldNotBeAvailableInOtherModules === 'undefined') -------------------------------------------------------------------------------- /tests/clojure/run_script.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | spawn ./prybar-clojure ./test_files/hello.clj 4 | expect eof 5 | 6 | -------------------------------------------------------------------------------- /test_files/sumofsquares.scala: -------------------------------------------------------------------------------- 1 | def sumOfSquares(x: Int, y: Int): Int = { 2 | val x2 = x * x 3 | val y2 = y * y 4 | x2 + y2 5 | } -------------------------------------------------------------------------------- /tests/sqlite/quiet.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | spawn ./prybar-sqlite -q -i 4 | expect "^--> " 5 | send ".quit \r" 6 | expect eof 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | plugins/ 2 | prybar-* 3 | prybar_assets/sqlite/patch.so 4 | deps.lst 5 | prybar.tar.gz 6 | generated_*.go 7 | result* 8 | __pycache__ 9 | -------------------------------------------------------------------------------- /tests/nodejs/run_code.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-nodejs -q -c 1+1 5 | match_max 100000 6 | expect eof 7 | -------------------------------------------------------------------------------- /tests/python3/eval_code.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-python3 -e 1+1 5 | match_max 100000 6 | expect eof 7 | -------------------------------------------------------------------------------- /tests/ocaml/expr.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | spawn ./prybar-ocaml -q -e 1+1 4 | match_max 100000 5 | expect -exact "- : int = 2" 6 | expect eof 7 | -------------------------------------------------------------------------------- /tests/sqlite/read_file.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | spawn ./prybar-sqlite -q -i ./test_files/hello.sql 4 | expect -- "^hey there\r 5 | --> " 6 | -------------------------------------------------------------------------------- /tests/python3/run_code.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-python3 -c print('hello') 5 | match_max 100000 6 | expect eof 7 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/fetch-blob/file.d.ts: -------------------------------------------------------------------------------- 1 | /** @type {typeof globalThis.File} */ export const File: typeof globalThis.File; 2 | export default File; 3 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@replit/prybar-assets", 3 | "dependencies": { 4 | "@replit/node-fetch": "^3.1.0" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/fetch-blob/index.d.ts: -------------------------------------------------------------------------------- 1 | /** @type {typeof globalThis.Blob} */ 2 | export const Blob: typeof globalThis.Blob; 3 | export default Blob; 4 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/@replit/node-fetch/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;"} -------------------------------------------------------------------------------- /tests/sqlite/1_plus_1.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | spawn ./prybar-sqlite -q -i 4 | expect -- "^--> " 5 | send "select 1+1;\r" 6 | expect -exact "2" 7 | expect -exact "--> " 8 | -------------------------------------------------------------------------------- /tests/ocaml/code_print.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | spawn ./prybar-ocaml -q -c "print_endline(\"hello world\")" 4 | match_max 100000 5 | expect -exact "hello world" 6 | expect eof 7 | -------------------------------------------------------------------------------- /tests/nodejs/eval_code.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-nodejs -q -e 1+1 5 | match_max 100000 6 | expect -exact "\u001b\[33m2\u001b\[39m\r 7 | " 8 | expect eof 9 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/runCode.js: -------------------------------------------------------------------------------- 1 | require = require("module").createRequire( 2 | global[Symbol.for("replit.prybar.eval.file")] 3 | ); 4 | module.exports = eval(global[Symbol.for("replit.prybar.eval.code")]); 5 | -------------------------------------------------------------------------------- /tests/clojure/run_code.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-clojure -q -c {(do (println "foo") "bar")} 5 | match_max 100000 6 | expect -re "^\r\r\u001b\\\[K\rfoo\r\r\n$" 7 | 8 | -------------------------------------------------------------------------------- /inject_claunch.go: -------------------------------------------------------------------------------- 1 | // this file will be injected into a language's main package at build. 2 | package main 3 | 4 | import "github.com/replit/prybar/utils" 5 | 6 | func main() { 7 | utils.DoCli(Instance) 8 | } 9 | -------------------------------------------------------------------------------- /tests/sqlite/header.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | spawn ./prybar-sqlite -i 4 | expect -gl "-- Loading resources from /tmp/sqlite-config*\r\nSQLite version 3.27.2*\r\nEnter \".help\" for usage hints.\r\n--> " 5 | -------------------------------------------------------------------------------- /inject_elaunch.go: -------------------------------------------------------------------------------- 1 | // this file will be injected into a language's main package at build. 2 | package main 3 | 4 | import "github.com/replit/prybar/utils" 5 | 6 | func main() { 7 | Execute(utils.ParseFlags()) 8 | } 9 | -------------------------------------------------------------------------------- /languages/ruby/pry_ruby.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void pry_open(); 5 | const char *pry_ruby_version(); 6 | char *pry_eval(const char *code); 7 | int pry_eval_file(const char *file); 8 | 9 | -------------------------------------------------------------------------------- /tests/tcl/invalid_command.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-tcl -q -i ./test-files/hi_julia.jl 5 | match_max 100000 6 | 7 | expect -exact "error: invalid command name \"my_number\"\r" 8 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/formdata-polyfill/esm.min.d.ts: -------------------------------------------------------------------------------- 1 | export declare const FormData: { 2 | new (): FormData; 3 | prototype: FormData; 4 | }; 5 | export declare function formDataToBlob(formData: FormData): Blob; 6 | -------------------------------------------------------------------------------- /tests/clojure/quiet_repl.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | # ignore ANSI escape sequences 4 | set _ "(?:.*?)" 5 | 6 | spawn ./prybar-clojure -i -q 7 | expect -re "^${_}--> $" 8 | 9 | send -- "" 10 | expect eof 11 | 12 | -------------------------------------------------------------------------------- /tests/ocaml/ps1.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | spawn ./prybar-ocaml -q -i -ps1 ">>" 4 | match_max 100000 5 | expect -exact ">>" 6 | send -- "1+1;;\r" 7 | expect -exact "- : int = 2" 8 | send -- "" 9 | expect eof 10 | -------------------------------------------------------------------------------- /tests/ocaml/not_quiet.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | spawn ./prybar-ocaml -e 1+1 4 | match_max 100000 5 | 6 | # OCaml 4.06.0 on Unix 7 | expect -re "^OCaml (.*) on Unix" 8 | expect -exact "- : int = 2" 9 | expect eof 10 | -------------------------------------------------------------------------------- /tests/ocaml/quiet.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | spawn ./prybar-ocaml -q -i 4 | match_max 100000 5 | expect -exact "--> " 6 | send -- "1+1;;\r" 7 | expect -exact "- : int = 2\r 8 | --> " 9 | send -- "" 10 | expect eof 11 | -------------------------------------------------------------------------------- /languages/julia/julia.pc: -------------------------------------------------------------------------------- 1 | prefix=/usr 2 | libdir=${prefix}/lib 3 | includedir=${prefix}/include/julia 4 | 5 | Name: julia 6 | Cflags: -I${includedir} 7 | Version: 1.1.0 8 | Description: it's julia 9 | Libs: -L${libdir} -ljulia 10 | -------------------------------------------------------------------------------- /scripts/inject.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if grep -q "USING_CGO" ./languages/$1/main.go; then 4 | cp inject_claunch.go ./languages/$1/generated_launch.go 5 | else 6 | cp inject_elaunch.go ./languages/$1/generated_launch.go 7 | fi 8 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/web-streams-polyfill/ponyfill/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web-streams-ponyfill", 3 | "main": "../dist/ponyfill", 4 | "module": "../dist/ponyfill.mjs", 5 | "types": "../dist/types/polyfill.d.ts" 6 | } 7 | -------------------------------------------------------------------------------- /test_files/main_module_scoped_to_global.js: -------------------------------------------------------------------------------- 1 | // In this bug the main module was adding module scope variables 2 | // to the global scope! 3 | const shouldNotBeAvailableInOtherModules = 'a'; 4 | 5 | require('./main_module_scoped_to_global_submodule'); -------------------------------------------------------------------------------- /tests/nodejs/header.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-nodejs -i 5 | match_max 100000 6 | expect -re {Node v\d+\.\d+.\d+ on (linux|darwin)} 7 | expect -exact "\[1G\[0J--> \[5G" 8 | send -- "" 9 | expect eof 10 | -------------------------------------------------------------------------------- /tests/python3/1_plus_1.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-python3 -i -q 5 | match_max 100000 6 | expect -exact "--> " 7 | send -- "1+1\r" 8 | expect -exact "1+1\r 9 | 2\r 10 | --> " 11 | send -- "" 12 | expect eof 13 | -------------------------------------------------------------------------------- /tests/tcl/unknown_command.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-tcl -q -i 5 | match_max 100000 6 | send "hmm\r" 7 | expect -exact "hmm\r" 8 | expect -exact "error: invalid command name \"hmm\"\r" 9 | expect -exact "--> " 10 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/web-streams-polyfill/ponyfill/es6/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web-streams-ponyfill-es6", 3 | "main": "../../dist/ponyfill.es6", 4 | "module": "../../dist/ponyfill.es6.mjs", 5 | "types": "../../dist/types/polyfill.d.ts" 6 | } 7 | -------------------------------------------------------------------------------- /tests/nodejs/err.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-nodejs -i -q 5 | match_max 100000 6 | expect -exact "\[1G\[0J--> \[5G" 7 | send -- "x\r" 8 | expect -e "ReferenceError: x is not defined" 9 | send -- "" 10 | expect eof 11 | -------------------------------------------------------------------------------- /tests/clojure/evaluate_expression.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | # ignore ANSI escape sequences 4 | set _ "(?:.*?)" 5 | 6 | set timeout -1 7 | spawn ./prybar-clojure -e {(str (+ 1 1))} 8 | match_max 100000 9 | expect -re "^${_}\"2\"${_}$" 10 | expect eof 11 | 12 | -------------------------------------------------------------------------------- /tests/tcl/1_plus_1.exp_skip: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-tcl -q -i 5 | match_max 100000 6 | expect -exact "\[J\[2K\r--> " 7 | send -- "expr 1+1\r" 8 | expect -exact "2\r 9 | \[J\[2K\r--> " 10 | send -- "" 11 | expect eof 12 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/web-streams-polyfill/ponyfill/es2018/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web-streams-ponyfill-es2018", 3 | "main": "../../dist/ponyfill.es2018", 4 | "module": "../../dist/ponyfill.es2018.mjs", 5 | "types": "../../dist/types/polyfill.d.ts" 6 | } 7 | -------------------------------------------------------------------------------- /tests/ocaml/exception.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | spawn ./prybar-ocaml -q -i 4 | match_max 100000 5 | expect -exact "--> " 6 | send -- "raise (Invalid_argument \"doh\");;\r" 7 | expect -exact "Exception: Invalid_argument \"doh\".\r 8 | --> " 9 | send -- "" 10 | expect eof 11 | -------------------------------------------------------------------------------- /tests/python3/set_ps1.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-python3 -i -q -ps1 custom 5 | match_max 100000 6 | expect -exact "custom" 7 | send -- "print('hit')\r" 8 | expect -exact "print('hit')\r 9 | hit\r 10 | custom" 11 | send -- "" 12 | expect eof 13 | -------------------------------------------------------------------------------- /languages/sqlite/compile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | COMPILE_DIR="$(dirname "$0")" 7 | DEST_DIR="$COMPILE_DIR/../../prybar_assets/sqlite" 8 | mkdir -p "$DEST_DIR" 9 | gcc -Wall -shared -fPIC -ldl -o "$DEST_DIR/patch.so" "$COMPILE_DIR/patch/patch.c" 10 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/web-streams-polyfill/es6/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web-streams-polyfill-es6", 3 | "main": "../dist/polyfill.es6", 4 | "browser": "../dist/polyfill.es6.min.js", 5 | "module": "../dist/polyfill.es6.mjs", 6 | "types": "../dist/types/polyfill.d.ts" 7 | } 8 | -------------------------------------------------------------------------------- /tests/clojure/initialize_expression_with_script.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | # ignore ANSI escape sequences 4 | set _ "(?:.*?)" 5 | 6 | set timeout -1 7 | spawn ./prybar-clojure -e "(str (inc b))" ./test_files/hello.clj 8 | match_max 100000 9 | expect -re "^${_}\"43\"${_}\r$" 10 | 11 | -------------------------------------------------------------------------------- /tests/nodejs/1_plus_1.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-nodejs -i -q 5 | match_max 100000 6 | expect -exact "\[1G\[0J--> \[5G" 7 | send -- "1+1\r" 8 | expect -exact "1+1\r\r 9 | \[33m2\[39m\r 10 | \[1G\[0J--> \[5G" 11 | send -- "" 12 | expect eof 13 | -------------------------------------------------------------------------------- /tests/tcl/from_file.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-tcl -q -i ./test_files/hello_tcl.tcl 5 | match_max 100000 6 | 7 | expect -exact "Hello, Tcl!\r" 8 | 9 | send "puts \$my_num\r" 10 | expect -exact "--> puts \$my_num\r" 11 | expect -exact "1000\r" 12 | -------------------------------------------------------------------------------- /tests/nodejs/set_ps1.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-nodejs -i -q -ps1 custom 5 | match_max 100000 6 | expect -exact "\[1G\[0Jcustom\[7G" 7 | send -- "console.log('hit')" 8 | expect -exact "console.log('hit')" 9 | send -- "\r" 10 | send -- "" 11 | expect eof 12 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/web-streams-polyfill/es2018/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web-streams-polyfill-es2018", 3 | "main": "../dist/polyfill.es2018", 4 | "browser": "../dist/polyfill.es2018.min.js", 5 | "module": "../dist/polyfill.es2018.mjs", 6 | "types": "../dist/types/polyfill.d.ts" 7 | } 8 | -------------------------------------------------------------------------------- /tests/clojure/initialize_code_with_script.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | # ignore ANSI escape sequences 4 | set _ "(?:.*?)" 5 | 6 | set timeout -1 7 | spawn ./prybar-clojure -c {(do (print (str a " " b)) "return-value")} ./test_files/hello.clj 8 | match_max 100000 9 | expect -re "^${_}hello 42${_}$" 10 | expect eof 11 | 12 | -------------------------------------------------------------------------------- /tests/nodejs/printing.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-nodejs -i -q 5 | match_max 100000 6 | expect -exact "\[1G\[0J--> \[5G" 7 | send -- "console.log('x')\r" 8 | expect -exact "console.log('x')\r\r 9 | x\r 10 | \[90mundefined\[39m\r 11 | \[1G\[0J--> " 12 | send -- "" 13 | expect eof 14 | -------------------------------------------------------------------------------- /tests/python3/show_header.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-python3 -i 5 | match_max 100000 6 | expect -re {Python 3\.\d+\.\d+ ([^)]+)} 7 | expect -re {\[.+\] on [a-z0-9]+\r\n} 8 | expect -exact "--> " 9 | send -- "1+1\r" 10 | expect -exact "1+1\r 11 | 2\r 12 | --> " 13 | send -- "" 14 | expect eof 15 | -------------------------------------------------------------------------------- /test_files/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test_files", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "global_bug.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "dependencies": { 12 | "node-fetch": "^3.2.10" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/nodejs/global_bug.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-nodejs -i ./test_files/global_bug.js 5 | match_max 100000 6 | expect -re {Node v\d+\.\d+.\d+ on (linux|darwin)} 7 | expect -exact "\[0m\[90mHint: hit control+c anytime to enter REPL.\[0m\r 8 | \[1G\[0J--> \[5G" 9 | send -- "" 10 | expect eof 11 | -------------------------------------------------------------------------------- /tests/nodejs/prompt_no_tty.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | set timeout -1 3 | set stty_init raw 4 | spawn bash ./run_no_pty ./prybar-nodejs -q -i 5 | match_max 100000 6 | expect -exact "--> " 7 | 8 | send -- "prompt('abc')\n" 9 | expect -exact "abc> " 10 | send -- "hello\n" 11 | expect -exact "'hello'\n" 12 | send -- ".exit\n" 13 | expect eof 14 | -------------------------------------------------------------------------------- /test_files/node_modules/node-fetch/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Fake node-fetch module for testing", 3 | "engines": { 4 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 5 | }, 6 | "files": [ 7 | "src" 8 | ], 9 | "main": "./src/index.js", 10 | "name": "node-fetch", 11 | "type": "module", 12 | "version": "3.2.10" 13 | } 14 | -------------------------------------------------------------------------------- /tests/nodejs/module_patching.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-nodejs -i ./test_files/global_bug.js 5 | match_max 100000 6 | expect -re {Node v\d+\.\d+.\d+ on (linux|darwin)} 7 | expect -exact "\[0m\[90mHint: hit control+c anytime to enter REPL.\[0m\r 8 | \[1G\[0J--> \[5G" 9 | send -- "" 10 | expect eof 11 | -------------------------------------------------------------------------------- /tests/nodejs/run_file.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-nodejs -i ./test_files/hello.js 5 | match_max 100000 6 | expect -re {Node v\d+\.\d+.\d+ on (linux|darwin)} 7 | expect -exact "hello\r 8 | \[0m\[90mHint: hit control+c anytime to enter REPL.\[0m\r 9 | \[1G\[0J--> \[5G" 10 | send -- "" 11 | expect eof 12 | -------------------------------------------------------------------------------- /tests/python3/printing.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-python3 -i -q 5 | match_max 100000 6 | expect -exact "--> " 7 | send -- "print('hello!')\r" 8 | expect -exact "'hello!')\r 9 | hello!\r 10 | --> " 11 | send -- "print(1+1)\r" 12 | expect -exact "print(1+1)\r 13 | 2\r 14 | --> " 15 | send -- "" 16 | expect eof 17 | -------------------------------------------------------------------------------- /run_no_pty: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | stdin="/tmp/prybar_stdin" 3 | stdout="/tmp/prybar_stdout" 4 | stderr="/tmp/prybar_stderr" 5 | stdio=( $stdin $stdout $stderr ) 6 | 7 | rm ${stdio[*]} 2>/dev/null 8 | mkfifo ${stdio[*]} 9 | 10 | cat <&0 >$stdin & 11 | cat $stdout >&1 & 12 | cat $stderr >&2 & 13 | sh -c "${*}" <$stdin 1>$stdout 2>$stderr 14 | 15 | rm ${stdio[*]} 16 | -------------------------------------------------------------------------------- /tests/ocaml/ps2.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | spawn ./prybar-ocaml -q -i -ps2 continuation 4 | match_max 100000 5 | expect -exact "--> " 6 | send -- "let a =\r" 7 | expect -exact "let a =\r 8 | continuation" 9 | send -- "print_endline(\"continued!\");;\r" 10 | expect -exact "continued!\r 11 | val a : unit = ()\r 12 | -->" 13 | send -- "" 14 | expect eof 15 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/replit/prybar 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/chzyer/logex v1.1.10 // indirect 7 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e 8 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect 9 | github.com/creack/pty v1.1.17 10 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 11 | ) 12 | -------------------------------------------------------------------------------- /languages/lua/lua_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | // Mostly a debugging aid, not sure if it'll actually fail if something goes wrong 8 | func TestLuaStuff(t *testing.T) { 9 | var lua Lua 10 | lua.Open() 11 | lua.Version() 12 | for i := 0; i < 100; i++ { 13 | lua.EvalFile("testdata/test.lua", make([]string, 0)) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/nodejs/main_module_scoped_to_global.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-nodejs -i ./test_files/main_module_scoped_to_global.js 5 | match_max 100000 6 | expect -re {Node v\d+\.\d+.\d+ on (linux|darwin)} 7 | expect -exact "\[0m\[90mHint: hit control+c anytime to enter REPL.\[0m\r 8 | \[1G\[0J--> \[5G" 9 | send -- "" 10 | expect eof -------------------------------------------------------------------------------- /tests/nodejs/prompt_escape.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-nodejs -i -q 5 | match_max 100000 6 | expect -exact "\[1G\[0J--> \[5G" 7 | 8 | send -- "prompt('abc')\r" 9 | expect -exact "prompt('abc')" 10 | expect -exact "abc> " 11 | # End of text. This is what Ctrl+C translates to 12 | # in raw mode. 13 | send -- "\x03" 14 | 15 | expect eof 16 | -------------------------------------------------------------------------------- /tests/python3/set_ps2.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-python3 -i -q -ps2 custom 5 | match_max 100000 6 | expect -exact "--> " 7 | send -- "while False:\r" 8 | expect -exact "while False:\r 9 | custom" 10 | send -- " pass\r" 11 | expect -exact " pass\r 12 | custom" 13 | send -- "\r" 14 | expect -exact "\r 15 | --> " 16 | send -- "" 17 | expect eof 18 | -------------------------------------------------------------------------------- /languages/python3/pry_python3.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int pry_eval_file(FILE *f, const char *file, int argn, const char *argv); 4 | const char *pry_eval(const char *code, int start); 5 | void pry_set_prompts(const char *ps1, const char *ps2); 6 | int pymain_run_interactive_hook(int *exitcode); 7 | int pymain_err_print(int *exitcode_p); 8 | PyAPI_FUNC(int) _Py_HandleSystemExit(int *exitcode_p); 9 | -------------------------------------------------------------------------------- /Dockerfile.dev: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | 3 | COPY scripts/docker-install.sh /tmp/docker-install.sh 4 | RUN /tmp/docker-install.sh 5 | 6 | RUN mkdir -p /gocode/src/github.com/replit/prybar 7 | WORKDIR /gocode/src/github.com/replit/prybar 8 | 9 | ENV GOPATH=/gocode LC_ALL=C.UTF-8 PATH="/gocode/src/github.com/replit/prybar:$PATH" 10 | 11 | RUN ln -s "$PWD/languages/tcl/tcl.pc" /usr/lib/pkgconfig/ 12 | -------------------------------------------------------------------------------- /languages/python311/pry_python311.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int pry_eval_file(FILE *f, const char *file, int argn, const char *argv); 4 | const char *pry_eval(const char *code, int start); 5 | void pry_set_prompts(const char *ps1, const char *ps2); 6 | int pymain_run_interactive_hook(int *exitcode); 7 | int pymain_err_print(int *exitcode_p); 8 | PyAPI_FUNC(int) _Py_HandleSystemExit(int *exitcode_p); 9 | -------------------------------------------------------------------------------- /tests/clojure/plus_1_1.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | # ignore ANSI escape sequences 4 | set _ "(?:.*?)" 5 | 6 | set timeout -1 7 | spawn ./prybar-clojure -i 8 | match_max 100000 9 | expect -re "^${_}Clojure${_}\r 10 | ${_}--> $" 11 | 12 | send -- "(str (+ 1 1))\r" 13 | expect -re "${_}\\(str \\(\\+ 1 1\\)\\)${_}\r 14 | ${_}2${_}\r 15 | ${_}--> $" 16 | 17 | send -- "" 18 | expect eof 19 | 20 | -------------------------------------------------------------------------------- /languages/lua/pry.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern lua_State *pry_L; 4 | 5 | const char *pry_get_version(void); 6 | void pry_eval(const char *code); 7 | int pry_eval_file(char *file); 8 | void pry_do_repl(void); 9 | 10 | // from the lua repl lib (lua.c) 11 | void dotty(lua_State *L); 12 | int handle_script(lua_State *L, char **argv, int n); 13 | int dostring(lua_State *L, const char *s, const char *name); 14 | -------------------------------------------------------------------------------- /tests/tcl/input_output.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-tcl -q -i 5 | match_max 100000 6 | expect -exact "--> " 7 | send "set inp \[gets stdin\]\r" 8 | expect -exact "--> set inp \[gets stdin\]\r" 9 | send "hey\r" 10 | expect -exact "hey\r" 11 | expect -exact "--> " 12 | send "puts \$inp\r" 13 | expect -exact "--> puts \$inp\r" 14 | expect -exact "hey\r" 15 | expect -exact "--> " 16 | -------------------------------------------------------------------------------- /languages/clojure/prybar_repl.clj: -------------------------------------------------------------------------------- 1 | (def prybar-ps1 (System/getProperty "PRYBAR_PS1" "--> ")) 2 | (def prybar-quiet? (System/getProperty "PRYBAR_QUIET" "false")) 3 | 4 | (when-not (Boolean/valueOf prybar-quiet?) 5 | (println "Clojure" (clojure-version))) 6 | 7 | (clojure.main/repl :init #(apply require clojure.main/repl-requires) 8 | :prompt #(print prybar-ps1)) 9 | (prn) 10 | (System/exit 0) 11 | 12 | -------------------------------------------------------------------------------- /tests/nodejs/confirm.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-nodejs -i -q 5 | match_max 100000 6 | expect -exact "\[1G\[0J--> \[5G" 7 | 8 | send -- "confirm('abc')\r" 9 | expect -exact "confirm('abc')" 10 | expect -exact "abc \[y/n\]: " 11 | send -- "helo" 12 | send -- "y" 13 | expect -exact "y" 14 | expect -exact "true" 15 | 16 | # end of transmission 17 | send -- "\x04" 18 | expect eof 19 | -------------------------------------------------------------------------------- /test_files/module_patching.js: -------------------------------------------------------------------------------- 1 | // Make sure that the module has the right values 2 | console.assert(module.id === '.') 3 | console.assert(Object.keys(module.exports).length === 0) 4 | console.assert(module.parent === null) 5 | console.assert(module.loaded === false) 6 | console.assert(module.children.length === 0) 7 | console.assert(module.filename === __filename) 8 | console.assert(module.filename.endsWith('/test_files/module_patching.js')); -------------------------------------------------------------------------------- /languages/lua/pry.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "pry.h" 7 | 8 | lua_State *pry_L; 9 | 10 | const char *pry_get_version(void) { return LUA_RELEASE " " LUA_COPYRIGHT; } 11 | 12 | void pry_eval(const char *code) { dostring(pry_L, code, ""); } 13 | 14 | void pry_do_repl(void) { dotty(pry_L); } 15 | 16 | int pry_eval_file(char *file) { return handle_script(pry_L, &file, 0); } 17 | -------------------------------------------------------------------------------- /tests/julia/1_plus_1.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-julia -q -i 5 | match_max 100000 6 | expect -exact "\[?2004h\r\[0K\[1m--> \[0m\[0m\r\[4C\r\[4C" 7 | send -- "1+1\r" 8 | expect -exact "1+1\r\[0K\[1m--> \[0m\[0m\r\[4C1+1\r\[7C\r 9 | \[?2004l\[0m\[0m2\r 10 | \r 11 | \r\[0K\r\[0K\[1m--> \[0m\[0m\r\[4C\r\[4C\[?2004h\r\[0K\[1m--> \[0m\[0m\r\[4C\r\[4C" 12 | send -- "" 13 | expect eof 14 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/web-streams-polyfill/dist/types/tsdoc-metadata.json: -------------------------------------------------------------------------------- 1 | // This file is read by tools that parse documentation comments conforming to the TSDoc standard. 2 | // It should be published with your NPM package. It should not be tracked by Git. 3 | { 4 | "tsdocVersion": "0.12", 5 | "toolPackages": [ 6 | { 7 | "packageName": "@microsoft/api-extractor", 8 | "packageVersion": "7.13.4" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /tests/nodejs/node_fetch.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | 5 | spawn sh 6 | send "export PRYBAR_ASSETS_DIR=\$PWD/prybar_assets\r" 7 | send "cd test_files\r" 8 | send "../prybar-nodejs -i require_node_fetch.js\r" 9 | match_max 100000 10 | expect -re {Node v\d+\.\d+.\d+ on (linux|darwin)} 11 | expect -re {Auto\-switching} 12 | expect -re {ok} 13 | expect -exact "\[0m\[90mHint: hit control+c anytime to enter REPL.\[0m\r 14 | \[1G\[0J--> \[5G" 15 | -------------------------------------------------------------------------------- /tests/clojure/initialize_repl_with_script.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | # ignore ANSI escape sequences 4 | set _ "(?:.*?)" 5 | 6 | set timeout -1 7 | spawn ./prybar-clojure -i ./test_files/hello.clj 8 | match_max 100000 9 | expect -re "^${_}hello${_}\r 10 | ${_}Clojure${_}\r 11 | ${_}--> $" 12 | 13 | # b is defined in ./test_files/hello.clj 14 | send -- "b\r" 15 | expect -re "^${_}b${_}\r 16 | ${_}42${_}\r 17 | ${_}--> $" 18 | 19 | send -- "" 20 | expect eof 21 | 22 | -------------------------------------------------------------------------------- /tests/tcl/a_few_outputs.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-tcl -q -i 5 | match_max 100000 6 | 7 | send "puts \"hey\"\r" 8 | expect -exact "puts \"hey\"\r" 9 | expect -exact "hey\r" 10 | expect -exact "--> " 11 | 12 | send "puts \"hey\"\r" 13 | expect -exact "puts \"hey\"\r" 14 | expect -exact "hey\r" 15 | expect -exact "--> " 16 | 17 | send "puts \"hello\"\r" 18 | expect -exact "puts \"hello\"\r" 19 | expect -exact "hello\r" 20 | expect -exact "--> " 21 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | 3 | COPY scripts/docker-install.sh /tmp/docker-install.sh 4 | RUN /tmp/docker-install.sh 5 | 6 | RUN mkdir -p /gocode/src/github.com/replit/prybar 7 | COPY . /gocode/src/github.com/replit/prybar 8 | WORKDIR /gocode/src/github.com/replit/prybar 9 | 10 | ENV GOPATH=/gocode LC_ALL=C.UTF-8 PATH="/gocode/src/github.com/replit/prybar:$PATH" 11 | ENV GOROOT=/usr/local/go 12 | ENV PATH=$PATH:$GOROOT/bin 13 | 14 | RUN cp languages/tcl/tcl.pc /usr/lib/pkgconfig/ 15 | RUN make 16 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | { system ? builtins.currentSystem }: 2 | 3 | let 4 | 5 | # flake-compat makes Nix flakes compatible with the old Nix cli commands, like nix-build and nix-shell. 6 | default = (import (fetchTarball { 7 | url = 8 | "https://github.com/edolstra/flake-compat/archive/99f1c2157fba4bfe6211a321fd0ee43199025dbf.tar.gz"; 9 | sha256 = "0x2jn3vrawwv9xp15674wjz9pixwjyj3j771izayl962zziivbx2"; 10 | }) { src = ./.; }).defaultNix; 11 | 12 | in 13 | 14 | builtins.getAttr system default.packages 15 | -------------------------------------------------------------------------------- /languages/tcl/tcl.pc: -------------------------------------------------------------------------------- 1 | # tcl pkg-config source file 2 | 3 | prefix=/usr 4 | exec_prefix=/usr 5 | libdir=/usr/lib 6 | includedir=${prefix}/include 7 | 8 | Name: Tool Command Language 9 | Description: Tcl is a powerful, easy-to-learn dynamic programming language, suitable for a wide range of uses. 10 | URL: http://www.tcl.tk/ 11 | Version: 8.6.9 12 | Requires.private: zlib >= 1.2.3 13 | Libs: -L${libdir} -ltcl8.6 -ltclstub8.6 14 | Libs.private: -ldl -lz -lpthread -lm 15 | Cflags: -I${includedir} -I${includedir}/tcl 16 | -------------------------------------------------------------------------------- /tests/julia/start_with_file.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-julia -q -i ./test_files/hi_julia.jl 5 | match_max 100000 6 | expect -exact "hey from julia\r 7 | \[?2004h\r\[0K\[1m--> \[0m\[0m\r\[4C\r\[4C" 8 | send -- "my_number\r" 9 | expect -exact "my_number\r\[0K\[1m--> \[0m\[0m\r\[4Cmy_number\r\[13C\r 10 | \[?2004l\[0m\[0m500\r 11 | \r 12 | \r\[0K\r\[0K\[1m--> \[0m\[0m\r\[4C\r\[4C\[?2004h\r\[0K\[1m--> \[0m\[0m\r\[4C\r\[4C" 13 | send -- "" 14 | expect eof 15 | -------------------------------------------------------------------------------- /tests/clojure/print.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | # ignore ANSI escape sequences 4 | set _ "(?:.*?)" 5 | 6 | set timeout -1 7 | spawn ./prybar-clojure -i 8 | match_max 100000 9 | expect -re "^${_}Clojure${_}\r 10 | ${_}--> $" 11 | 12 | send -- "(print \"hello!\")\r" 13 | expect -re "^${_}\\(print \"hello!\"\\)${_}\r 14 | ${_}hello!nil${_}\r 15 | ${_}--> $" 16 | 17 | send -- "(print (+ 1 1))\r" 18 | expect -re "^${_}\\(print \\(\\+ 1 1\\)\\)${_}\r 19 | ${_}2nil${_}\r 20 | ${_}--> $" 21 | 22 | send -- "" 23 | expect eof 24 | 25 | -------------------------------------------------------------------------------- /languages/clojure/wrappedClojure.nix: -------------------------------------------------------------------------------- 1 | { pkgs }: 2 | 3 | let 4 | cljdeps = import ./deps.nix { inherit pkgs; }; 5 | classp = cljdeps.makeClasspaths {}; 6 | in pkgs.stdenv.mkDerivation { 7 | name = "wrapped-clojure-with-deps"; 8 | 9 | src = ./.; 10 | nativeBuildInputs = [ pkgs.makeWrapper ]; 11 | buildInputs = [ pkgs.clojure ]; 12 | 13 | installPhase = '' 14 | mkdir -p $out/bin 15 | 16 | makeWrapper ${pkgs.clojure}/bin/clojure $out/bin/clojure --add-flags "-Scp ${builtins.toString classp}" 17 | ''; 18 | } 19 | -------------------------------------------------------------------------------- /scripts/gofiles.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cat << EOF > $1 4 | // generated by $0 $*; DO NOT EDIT 5 | 6 | package main 7 | 8 | import "encoding/base64" 9 | 10 | func File(name string) ([]byte, error) { 11 | 12 | switch name { 13 | 14 | EOF 15 | 16 | for fn in $(ls | egrep -i '.*\.(clj|js|ml)'); do 17 | 18 | echo " case \"$fn\":" >> $1 19 | echo " return base64.StdEncoding.DecodeString(\"$(base64 -i $fn | tr -d \\n)\")" >> $1 20 | 21 | done 22 | 23 | cat << EOF >> $1 24 | 25 | } 26 | return nil, nil 27 | } 28 | EOF 29 | 30 | echo "Generated $(realpath $1)" 31 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/node-domexception/index.js: -------------------------------------------------------------------------------- 1 | /*! node-domexception. MIT License. Jimmy Wärting */ 2 | 3 | if (!globalThis.DOMException) { 4 | try { 5 | const { MessageChannel } = require('worker_threads'), 6 | port = new MessageChannel().port1, 7 | ab = new ArrayBuffer() 8 | port.postMessage(ab, [ab, ab]) 9 | } catch (err) { 10 | err.constructor.name === 'DOMException' && ( 11 | globalThis.DOMException = err.constructor 12 | ) 13 | } 14 | } 15 | 16 | module.exports = globalThis.DOMException 17 | -------------------------------------------------------------------------------- /tests/julia/print_a_line.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-julia -q -i 5 | match_max 100000 6 | expect -exact "\[?2004h\r\[0K\[1m--> \[0m\[0m\r\[4C\r\[4C" 7 | send -- "println()" 8 | expect -exact "\r\[0K\[1m--> \[0m\[0m\r\[4Cprintln(\r\[12C" 9 | send -- "\"hellooooooo\")\r" 10 | expect -exact "\"hellooooooo\")\r\[0K\[1m--> \[0m\[0m\r\[4Cprintln(\"hellooooooo\")\r\[26C\r 11 | \[?2004l\[0mhellooooooo\r 12 | \r 13 | \r\[0K\r\[0K\[1m--> \[0m\[0m\r\[4C\r\[4C\[?2004h\r\[0K\[1m--> \[0m\[0m\r\[4C\r\[4C" 14 | send -- "" 15 | expect eof 16 | -------------------------------------------------------------------------------- /languages/ocaml/README.md: -------------------------------------------------------------------------------- 1 | # OCaml / Reason interpreter 2 | 3 | ** Usage: ** 4 | ``` 5 | ocaml repl.ml --help 6 | OCaml / Reason repl script for prybar. Options available: 7 | -q Don't print OCaml version on startup 8 | -e Eval and output results of interpreted code 9 | -c Run code without printing the output 10 | -i Run as interactive repl 11 | -s {ml|re} Sets the syntax for the repl (default: ml) 12 | -help Display this list of options 13 | --help Display this list of options 14 | ``` 15 | 16 | ** Usage examples: ** 17 | 18 | ``` 19 | # Run some ocaml code 20 | ocaml repl.ml -e "let foo = 1;;" 21 | 22 | # Run some reason code 23 | ocaml repl.ml -s re -e "let foo = 1;" 24 | ``` 25 | -------------------------------------------------------------------------------- /tests/nodejs/prompt_tty.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-nodejs -i -q 5 | match_max 100000 6 | expect -exact "\[1G\[0J--> \[5G" 7 | 8 | send -- "prompt('abc')\r" 9 | expect -exact "prompt('abc')" 10 | expect -exact "abc> " 11 | send -- "makr" 12 | expect -exact "makr" 13 | 14 | # left arrow key 15 | send -- "\x1b\[D" 16 | expect -exact "makr" 17 | 18 | # delete 19 | send -- "\x7f" 20 | expect -exact "mar" 21 | 22 | # right arrow key 23 | send -- "\x1b\[C" 24 | expect -exact "mar" 25 | 26 | send -- "k" 27 | expect -exact "mark" 28 | 29 | send -- "\r" 30 | expect -exact "\r\n" 31 | 32 | expect -exact "'mark'" 33 | # end of transmission 34 | send -- "\x04" 35 | expect eof 36 | -------------------------------------------------------------------------------- /run_tests: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | stty cols 80 4 | stty rows 20 5 | 6 | tests=$(find ./tests ! -name '*.go' -printf '%P\n') 7 | 8 | for t in ${tests}; do 9 | if [[ $t != *.exp ]]; then 10 | echo "$t:" 11 | 12 | if [[ $t == 'nodejs' && $DISABLE_GO_TESTS != 1 ]]; then 13 | 14 | go test ./tests/nodejs 15 | fi 16 | 17 | continue 18 | fi 19 | 20 | name=$(echo -n $t | sed -s 's/.*\/\(.*\).exp/\1/' | sed -s 's/_/ /g') 21 | 22 | echo -n "... $name" 23 | 24 | test_out=$(timeout 15 expect "./tests/$t" 2>&1) 25 | if [[ $? != 0 ]]; then 26 | echo -e "\n========== \"$t\" failed ==========" 27 | echo $test_out 28 | exit 1; 29 | fi 30 | 31 | echo -ne '\r' 32 | echo -e " \e[32m✓\e[0m $name" 33 | done 34 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/@replit/node-fetch/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 'use strict'; 3 | 4 | 5 | 6 | require('http'); 7 | require('https'); 8 | require('zlib'); 9 | require('stream'); 10 | var index = require('./index-3a548b1a.js'); 11 | module.exports = exports = index.fetch; 12 | Object.defineProperty(exports, '__esModule', { value: true }); 13 | require('util'); 14 | require('url'); 15 | require('net'); 16 | 17 | 18 | 19 | exports.AbortError = index.AbortError; 20 | exports.FetchError = index.FetchError; 21 | exports.Headers = index.Headers; 22 | exports.Request = index.Request; 23 | exports.Response = index.Response; 24 | exports["default"] = index.fetch; 25 | exports.isRedirect = index.isRedirect; 26 | /* eslint-enable */ 27 | //# sourceMappingURL=index.js.map 28 | -------------------------------------------------------------------------------- /run_tests_language: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | stty cols 80 4 | stty rows 20 5 | 6 | language=$1 7 | tests=$(find "./tests/${language}" ! -name '*.go' -printf '%P\n') 8 | 9 | for t in ${tests}; do 10 | if [[ $t != *.exp ]]; then 11 | echo "$t:" 12 | continue 13 | fi 14 | 15 | name=$(echo -n $t | sed -s 's/.*\/\(.*\).exp/\1/' | sed -s 's/_/ /g') 16 | 17 | echo -n "... ${language} $name" 18 | 19 | 20 | test_out=$(timeout 15 expect -f "./tests/${language}/$t" 2>&1) 21 | if [[ $? != 0 ]]; then 22 | echo -e "\n========== \"$t\" failed ==========" 23 | echo "$test_out" 24 | exit 1 25 | fi 26 | 27 | echo -ne '\r' 28 | echo -e " \e[32m✓\e[0m $name" 29 | done 30 | 31 | if [[ $language == 'nodejs' && $DISABLE_GO_TESTS != 1 ]]; then 32 | echo running go tests 33 | go test ./tests/nodejs 34 | fi 35 | -------------------------------------------------------------------------------- /tests/nodejs/prompt_tty_bounds.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-nodejs -i -q 5 | match_max 100000 6 | expect -exact "\[1G\[0J--> \[5G" 7 | 8 | send -- "prompt('abc')\r" 9 | expect -exact "prompt('abc')" 10 | expect -exact "abc> " 11 | 12 | send -- "d" 13 | expect -exact "abc> d" 14 | 15 | # right arrow key (index 1/1) 16 | send -- "\x1b\[C" 17 | 18 | send -- "e" 19 | expect -exact "abc> de" 20 | 21 | # left arrow key (index 2/3) 22 | send -- "\x1b\[D" 23 | 24 | # delete / backspace (index 1/2) 25 | send -- "\x7f" 26 | expect -exact "abc> e" 27 | 28 | # delete / backspace (index: 0/1) 29 | send -- "\x7f" 30 | expect -exact "abc> e" 31 | 32 | # left arrow key (index 0/1) 33 | send -- "\x1b\[D" 34 | send -- "d" 35 | expect -exact "abc> de" 36 | 37 | # end of transmission 38 | send -- "\x04" 39 | expect eof 40 | -------------------------------------------------------------------------------- /tests/clojure/all.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | # ignore ANSI escape sequences 4 | set _ "(?:.*?)" 5 | 6 | set timeout -1 7 | spawn ./prybar-clojure -c {(defn f [x] (inc x))} -e {(def s "bar")} -I -i -q ./test_files/hello.clj 8 | match_max 100000 9 | expect -re "^${_}hello${_}\r 10 | ${_}#'user/s${_}\r 11 | ${_}--> $" 12 | 13 | # a is defined in ./test_files/hello.clj 14 | send -- "a\r" 15 | expect -re "^${_}a${_}\r 16 | ${_}\"hello\"${_}\r 17 | ${_}--> $" 18 | 19 | # b is defined in ./test_files/hello.clj 20 | send -- "b\r" 21 | expect -re "^${_}b${_}\r 22 | ${_}42${_}\r 23 | ${_}--> $" 24 | 25 | # defined with "-c" 26 | send -- "(f b)\r" 27 | expect -re "^${_}(f b)${_}\r 28 | ${_}43${_}\r 29 | ${_}--> $" 30 | 31 | # defined with "-e" 32 | send -- "s\r" 33 | expect -re "^${_}s${_}\r 34 | ${_}\"bar\"${_}\r 35 | ${_}--> $" 36 | 37 | send -- "" 38 | expect eof 39 | 40 | -------------------------------------------------------------------------------- /tests/nodejs/prompt_tty_escapes.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-nodejs -i -q 5 | match_max 100000 6 | expect -exact "\[1G\[0J--> \[5G" 7 | 8 | send -- "prompt('abc')\r" 9 | expect -exact "prompt('abc')" 10 | expect -exact "abc> " 11 | send -- "ab" 12 | 13 | # left arrow key (index 2/2) 14 | send -- "\x1b\[D" 15 | expect -exact "abc> ab" 16 | 17 | # up arrow key (should be escaped) (index 1/2) 18 | send -- "\x1b\[A" 19 | expect -exact "abc> a^\[Ab" 20 | 21 | # right arrow key + a few deletes to clear the prompt (index 6/6) 22 | send -- "\x1b\[C\x7f\x7f\x7f\x7f\x7f\x7f" 23 | 24 | # random escape that doesn't exist (should be escaped) 25 | send -- "\x1bfake escape" 26 | expect -exact "abc> ^fake escape" 27 | 28 | send -- "\r" 29 | expect -exact "\r\n" 30 | expect -exact "'^fake escape'" 31 | 32 | # end of transmission 33 | send -- "\x04" 34 | expect eof 35 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/node-domexception/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-domexception", 3 | "version": "1.0.0", 4 | "description": "An implementation of the DOMException class from NodeJS", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/jimmywarting/node-domexception.git" 9 | }, 10 | "engines": { 11 | "node": ">=10.5.0" 12 | }, 13 | "author": "Jimmy Wärting", 14 | "license": "MIT", 15 | "bugs": { 16 | "url": "https://github.com/jimmywarting/node-domexception/issues" 17 | }, 18 | "homepage": "https://github.com/jimmywarting/node-domexception#readme", 19 | "funding": [ 20 | { 21 | "type": "github", 22 | "url": "https://github.com/sponsors/jimmywarting" 23 | }, 24 | { 25 | "type": "github", 26 | "url": "https://paypal.me/jimmywarting" 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /test_files/global_bug.js: -------------------------------------------------------------------------------- 1 | // In this bug, the main module's globals were not the same 2 | // as the global in other modules. Also some things were 3 | // missing from the global like timing functions 4 | console.assert([] instanceof global.Array); 5 | console.assert([] instanceof Array); 6 | console.assert(process); 7 | console.assert(URL); 8 | console.assert(URLSearchParams); 9 | console.assert(clearImmediate); 10 | console.assert(clearInterval); 11 | console.assert(clearTimeout); 12 | console.assert(setImmediate); 13 | console.assert(setInterval); 14 | console.assert(setTimeout); 15 | console.assert(Buffer); 16 | console.assert(globalThis === global); 17 | 18 | // Current implementation has this bug 19 | // const { Object: importedObject, global: importedGlobal} = require('./global_bug_submodule') 20 | // console.assert(importedObject === Object); 21 | // console.assert(global === importedGlobal) 22 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | jobs: 3 | build_and_test: 4 | docker: 5 | - image: docker:18.09 6 | steps: 7 | - run: echo skip 8 | nix_build: 9 | docker: 10 | - image: nixos/nix:2.3.16 11 | steps: 12 | - checkout 13 | - run: git checkout . # circle CI checkout deleted the vendored node_modules 14 | # folders, this adds them back 15 | - restore_cache: 16 | key: nix-store 17 | - run: apk add coreutils git 18 | - run: nix-build 19 | - save_cache: 20 | key: nix-store 21 | when: always 22 | paths: 23 | - /nix 24 | workflows: 25 | ci: 26 | jobs: 27 | - build_and_test: 28 | filters: 29 | branches: 30 | ignore: master 31 | - nix_build: 32 | filters: 33 | branches: 34 | ignore: master 35 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/@replit/node-fetch/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@replit/node-fetch", 3 | "version": "3.1.0", 4 | "description": "A light-weight module that brings Fetch API to node.js", 5 | "main": "index.js", 6 | "sideEffects": false, 7 | "engines": { 8 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git@github.com:replit/node-fetch.git" 13 | }, 14 | "keywords": [ 15 | "fetch", 16 | "http", 17 | "promise", 18 | "request", 19 | "curl", 20 | "wget", 21 | "xhr", 22 | "whatwg" 23 | ], 24 | "author": "David Frank", 25 | "license": "MIT", 26 | "funding": { 27 | "type": "opencollective", 28 | "url": "https://opencollective.com/node-fetch" 29 | }, 30 | "dependencies": { 31 | "formdata-polyfill": "^4.0.10", 32 | "web-streams-polyfill": "^3.1.1" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /languages/julia/julia.nix: -------------------------------------------------------------------------------- 1 | { pkgs }: 2 | 3 | pkgs.stdenv.mkDerivation rec { 4 | pname = "julia-sources"; 5 | version = "1.5.4"; 6 | 7 | src = { 8 | x86_64-linux = pkgs.fetchurl { 9 | url = "https://julialang-s3.julialang.org/bin/linux/x64/${pkgs.lib.versions.majorMinor version}/julia-${version}-linux-x86_64.tar.gz"; 10 | sha256 = "1icb3rpn2qs6c3rqfb5rzby1pj6h90d9fdi62nnyi4x5s58w7pl0"; 11 | }; 12 | }.${pkgs.stdenv.hostPlatform.system} or (throw "Unsupported system: ${pkgs.stdenv.hostPlatform.system}"); 13 | 14 | installPhase = '' 15 | cp -r . $out 16 | 17 | mkdir $out/lib/pkgconfig 18 | cat > $out/lib/pkgconfig/julia.pc <<- EOM 19 | Name: julia 20 | Cflags: -I$out/include/julia 21 | Version: 1.5.4 22 | Description: it's julia 23 | Libs: -L$out\/lib -ljulia 24 | EOM 25 | ''; 26 | } -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/@replit/node-fetch/README.md: -------------------------------------------------------------------------------- 1 | # @replit/node-fetch 2 | 3 | [node-fetch](https://github.com/node-fetch/node-fetch) but in CommonJS format. This module is built from `node-fetch` directly. 4 | 5 | ## Version check 6 | 7 | ![Latest upstream version](https://img.shields.io/npm/v/node-fetch?label=latest%20upstream) 8 | ![Current upstream version](https://img.shields.io/badge/current%20upstream-v3.1.0-brightgreen) 9 | 10 | ## Differences 11 | 12 | 1. You can `require("@replit/node-fetch")` directly. 13 | 2. You will not see the `ExperimentalWarning: stream/web is an experimental feature` warning. 14 | 3. It works on older Node.js versions that don’t support [requiring built-in modules with a `node:` prefix](https://github.com/node-fetch/node-fetch/issues/1367). 15 | 16 | ## Build 17 | 18 | ```bash 19 | yarn 20 | ./build.js # Output to `lib` folder 21 | ``` 22 | 23 | ## Install 24 | 25 | ```bash 26 | yarn add @replit/node-fetch 27 | ``` 28 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/fetch-blob/from.d.ts: -------------------------------------------------------------------------------- 1 | export default blobFromSync; 2 | /** 3 | * @param {string} path filepath on the disk 4 | * @param {string} [type] mimetype to use 5 | */ 6 | export function blobFromSync(path: string, type?: string): Blob; 7 | import File from "./file.js"; 8 | import Blob from "./index.js"; 9 | /** 10 | * @param {string} path filepath on the disk 11 | * @param {string} [type] mimetype to use 12 | * @returns {Promise} 13 | */ 14 | export function blobFrom(path: string, type?: string): Promise; 15 | /** 16 | * @param {string} path filepath on the disk 17 | * @param {string} [type] mimetype to use 18 | * @returns {Promise} 19 | */ 20 | export function fileFrom(path: string, type?: string): Promise; 21 | /** 22 | * @param {string} path filepath on the disk 23 | * @param {string} [type] mimetype to use 24 | */ 25 | export function fileFromSync(path: string, type?: string): File; 26 | export { File, Blob }; 27 | -------------------------------------------------------------------------------- /languages/scala/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/exec" 7 | "syscall" 8 | "github.com/replit/prybar/utils" 9 | ) 10 | 11 | 12 | func Execute(config *utils.Config) { 13 | path, err := exec.LookPath("scala") 14 | 15 | if err != nil { 16 | panic(err) 17 | } 18 | 19 | env := os.Environ() 20 | args := []string{"scala"} 21 | 22 | if config.Quiet { 23 | args = append(args, "-Dscala.shell.welcome=") 24 | } 25 | 26 | if config.Code != "" { 27 | args = append(args, "-e", config.Code) 28 | } 29 | 30 | if config.Exp != "" { 31 | printStatement := fmt.Sprintf("print(%s)", config.Exp) 32 | args = append(args, "-e", printStatement) 33 | } 34 | 35 | if config.Ps1 != "" { 36 | args = append(args, "-Dscala.shell.prompt=%n" + config.Ps1) 37 | } 38 | 39 | if config.Args != nil && len(config.Args) > 0 { 40 | args = append(args, "-i") 41 | args = append(args, config.Args...) 42 | } 43 | 44 | syscall.Exec(path, args, env) 45 | } 46 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= 2 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 3 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= 4 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 5 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= 6 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 7 | github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= 8 | github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= 9 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= 10 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 11 | -------------------------------------------------------------------------------- /languages/ruby/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // USING_CGO 4 | 5 | /* 6 | #cgo pkg-config: ruby-2.7 7 | #include "pry_ruby.h" 8 | */ 9 | import "C" 10 | 11 | import ( 12 | "unsafe" 13 | ) 14 | 15 | type Ruby struct { 16 | } 17 | 18 | func (p Ruby) Open() { 19 | C.pry_open() 20 | } 21 | 22 | func (p Ruby) Version() string { 23 | return C.GoString(C.pry_ruby_version()) 24 | } 25 | 26 | func (p Ruby) Eval(code string) { 27 | p.EvalExpression(code) 28 | } 29 | 30 | func (p Ruby) EvalExpression(code string) string { 31 | ccode := C.CString(code) 32 | defer C.free(unsafe.Pointer(ccode)) 33 | res := C.pry_eval(ccode) 34 | return C.GoString(res) 35 | } 36 | 37 | func (p Ruby) EvalFile(file string, args []string) int { 38 | cfile := C.CString(file) 39 | defer C.free(unsafe.Pointer(cfile)) 40 | return int(C.pry_eval_file(cfile)) 41 | } 42 | 43 | func (p Ruby) REPL() { 44 | p.Eval("require 'irb'\nbinding.irb") 45 | } 46 | func (p Ruby) Close() { 47 | C.ruby_cleanup(0) 48 | } 49 | 50 | var Instance = Ruby{} 51 | -------------------------------------------------------------------------------- /languages/julia/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // USING_CGO 4 | 5 | /* 6 | #cgo pkg-config: julia 7 | #cgo LDFLAGS: -ljulia 8 | #include "pry.h" 9 | */ 10 | import "C" 11 | 12 | import ( 13 | "unsafe" 14 | ) 15 | 16 | type Julia struct{} 17 | 18 | func (p Julia) Open() { 19 | C.setup() 20 | } 21 | 22 | func (p Julia) SetPrompts(ps1, ps2 string) { 23 | cps1 := C.CString(ps1) 24 | defer C.free(unsafe.Pointer(cps1)) 25 | 26 | C.set_prompt(cps1) 27 | } 28 | 29 | func (p Julia) Version() string { 30 | return C.GoString(C.get_banner()) 31 | } 32 | 33 | func (p Julia) Eval(code string) { 34 | cstr := C.CString(code) 35 | defer C.free(unsafe.Pointer(cstr)) 36 | 37 | C.eval(cstr) 38 | } 39 | 40 | func (p Julia) EvalFile(file string, args []string) int { 41 | cstr := C.CString(file) 42 | defer C.free(unsafe.Pointer(cstr)) 43 | 44 | return int(C.eval_file(cstr)) 45 | } 46 | 47 | func (p Julia) REPL() { 48 | C.run_repl() 49 | } 50 | 51 | func (p Julia) Close() { 52 | C.cleanup() 53 | } 54 | 55 | var Instance = Julia{} 56 | -------------------------------------------------------------------------------- /tests/python3/stderr_red.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | # red is currently nondeterministic 4 | exit 0 5 | 6 | spawn ./prybar-python3 -i -q -R 7 | match_max 100000 8 | expect -exact "--> " 9 | send -- "import sys\r" 10 | expect -exact "import sys\r 11 | --> " 12 | send -- "sys.stderr.write()\[D" 13 | expect -exact "" 14 | send -- "'" 15 | expect -exact "')" 16 | send -- "'" 17 | expect -exact "')" 18 | send -- "\[D" 19 | expect -exact "" 20 | send -- "w" 21 | expect -exact "w')" 22 | send -- "e" 23 | expect -exact "e')" 24 | send -- "e" 25 | expect -exact "e')" 26 | send -- "e" 27 | expect -exact "e')" 28 | send -- "e" 29 | expect -exact "e')" 30 | send -- "e" 31 | expect -exact "e')" 32 | send -- "e" 33 | expect -exact "e')" 34 | send -- "e" 35 | expect -exact "e')" 36 | send -- "e" 37 | expect -exact "e')" 38 | send -- "e" 39 | expect -exact "e')" 40 | send -- "e" 41 | expect -exact "e')" 42 | send -- "e" 43 | expect -exact "e')" 44 | send -- "e" 45 | expect -exact "e')" 46 | send -- "\\" 47 | expect -exact "\\')" 48 | send -- "n" 49 | expect -exact "n')" 50 | send -- "\r" 51 | expect eof 52 | -------------------------------------------------------------------------------- /languages/ruby/pry_ruby.c: -------------------------------------------------------------------------------- 1 | #include "pry_ruby.h" 2 | 3 | VALUE binding; 4 | 5 | void pry_open() 6 | { 7 | ruby_init(); 8 | ruby_init_loadpath(); 9 | binding = rb_binding_new(); 10 | } 11 | 12 | const char *pry_ruby_version() 13 | { 14 | return ruby_description; 15 | } 16 | 17 | char *pry_eval(const char *code) 18 | { 19 | 20 | int state; 21 | VALUE result; 22 | result = rb_eval_string_wrap(code, &state); 23 | 24 | if (state) 25 | { 26 | VALUE exception = rb_errinfo(); 27 | rb_set_errinfo(Qnil); 28 | if (RTEST(exception)) 29 | rb_warn("%" PRIsVALUE "", rb_funcall(exception, rb_intern("full_message"), 0)); 30 | return NULL; 31 | } 32 | else 33 | { 34 | VALUE str = rb_sprintf("%" PRIsVALUE "", result); 35 | return StringValueCStr(str); 36 | } 37 | } 38 | 39 | int pry_eval_file(const char *file) 40 | { 41 | char *options[] = {"ruby", file}; 42 | void *node = ruby_options(2, options); 43 | 44 | int state = 0; 45 | if (ruby_executable_node(node, &state)) 46 | { 47 | state = ruby_exec_node(node); 48 | } 49 | 50 | return state; 51 | } 52 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/fetch-blob/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 David Frank 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/node-domexception/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Jimmy Wärting 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/formdata-polyfill/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Jimmy Karl Roland Wärting 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "locked": { 5 | "lastModified": 1667395993, 6 | "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", 7 | "owner": "numtide", 8 | "repo": "flake-utils", 9 | "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "numtide", 14 | "repo": "flake-utils", 15 | "type": "github" 16 | } 17 | }, 18 | "nixpkgs": { 19 | "locked": { 20 | "lastModified": 1724300212, 21 | "narHash": "sha256-x3jl6OWTs+L9C7EtscuWZmGZWI0iSBDafvg3X7JMa1A=", 22 | "owner": "nixos", 23 | "repo": "nixpkgs", 24 | "rev": "4de4818c1ffa76d57787af936e8a23648bda6be4", 25 | "type": "github" 26 | }, 27 | "original": { 28 | "owner": "nixos", 29 | "ref": "nixpkgs-unstable", 30 | "repo": "nixpkgs", 31 | "type": "github" 32 | } 33 | }, 34 | "root": { 35 | "inputs": { 36 | "flake-utils": "flake-utils", 37 | "nixpkgs": "nixpkgs" 38 | } 39 | } 40 | }, 41 | "root": "root", 42 | "version": 7 43 | } 44 | -------------------------------------------------------------------------------- /tests/julia/input.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set timeout -1 4 | spawn ./prybar-julia -q -i 5 | match_max 100000 6 | expect -exact "\[?2004h\r\[0K\[1m--> \[0m\[0m\r\[4C\r\[4C" 7 | send -- "n = readline()\r" 8 | expect -exact "n = readline()\r\[0K\[1m--> \[0m\[0m\r\[4Cn = readline()\r\[18C\r 9 | \[?2004l\[0m" 10 | send -- "hello\r" 11 | expect -exact "hello\r 12 | \[0m\"hello\"\r 13 | \r 14 | \r\[0K\r\[0K\[1m--> \[0m\[0m\r\[4C\r\[4C\[?2004h\r\[0K\[1m--> \[0m\[0m\r\[4C\r\[4C" 15 | send -- "println(hello" 16 | expect -exact "\r\[0K\[1m--> \[0m\[0m\r\[4Cprintln(hell\r\[16C" 17 | send -- "" 18 | expect -exact "\r\[0K\[1m--> \[0m\[0m\r\[4Cprintln(hel\r\[15C" 19 | send -- "" 20 | expect -exact "\r\[0K\[1m--> \[0m\[0m\r\[4Cprintln(he\r\[14C" 21 | send -- "" 22 | expect -exact "\r\[0K\[1m--> \[0m\[0m\r\[4Cprintln(h\r\[13C" 23 | send -- "" 24 | expect -exact "\r\[0K\[1m--> \[0m\[0m\r\[4Cprintln(\r\[12C" 25 | send -- "n)\r" 26 | expect -exact "n)\r\[0K\[1m--> \[0m\[0m\r\[4Cprintln(n)\r\[14C\r 27 | \[?2004l\[0mhello\r 28 | \r 29 | \r\[0K\r\[0K\[1m--> \[0m\[0m\r\[4C\r\[4C\[?2004h\r\[0K\[1m--> \[0m\[0m\r\[4C\r\[4C" 30 | send -- "" 31 | expect eof 32 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/@replit/node-fetch/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 - 2020 Node Fetch Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/web-streams-polyfill/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Mattias Buelens 4 | Copyright (c) 2016 Diwank Singh Tomer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /languages/R/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // USING_CGO 4 | 5 | /* 6 | #cgo pkg-config: libR 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | void pry_open() { 15 | const char *args[] = {"/usr/local/bin/R", "--silent", NULL}; 16 | Rf_initEmbeddedR(2, args); 17 | } 18 | 19 | const char* pry_version() { 20 | return "R version " R_MAJOR "." R_MINOR " (" R_YEAR "-" R_MONTH "-" R_DAY ") -- \"" R_NICK "\""; 21 | } 22 | 23 | pry_eval(const char* code) { 24 | ParseStatus status; 25 | SEXP x = R_ParseVector(mkString(code), 1, &status, R_NilValue); 26 | SEXP result = eval(VECTOR_ELT(x, 0), R_GlobalEnv); 27 | PrintValue(result); 28 | } 29 | 30 | void pry_repl() { 31 | R_ReplDLLinit(); 32 | while (R_ReplDLLdo1() > 0) { 33 | 34 | } 35 | } 36 | 37 | */ 38 | import "C" 39 | 40 | import ( 41 | "unsafe" 42 | ) 43 | 44 | type R struct { 45 | } 46 | 47 | func (p R) Open() { 48 | C.pry_open() 49 | } 50 | 51 | func (p R) Version() string { 52 | return C.GoString(C.pry_version()) 53 | } 54 | 55 | func (p R) Eval(code string) { 56 | ccode := C.CString(code) 57 | defer C.free(unsafe.Pointer(ccode)) 58 | C.pry_eval(ccode) 59 | } 60 | 61 | func (p R) REPL() { 62 | C.pry_repl() 63 | } 64 | 65 | func (p R) Close() { 66 | C.Rf_endEmbeddedR(0) 67 | } 68 | 69 | var Instance = R{} 70 | -------------------------------------------------------------------------------- /languages/lua/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // USING_CGO 4 | 5 | /* 6 | #cgo pkg-config: lua-5.1 7 | #cgo LDFLAGS: -lreadline 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "pry.h" 13 | 14 | */ 15 | import "C" 16 | 17 | import ( 18 | "unsafe" 19 | ) 20 | 21 | type Lua struct{} 22 | 23 | func (p Lua) Open() { 24 | C.pry_L = C.luaL_newstate() 25 | C.luaL_openlibs(C.pry_L) 26 | } 27 | 28 | func (p Lua) Version() string { 29 | return C.GoString(C.pry_get_version()) 30 | } 31 | 32 | func (p Lua) SetPrompts(ps1, ps2 string) { 33 | c1 := C.CString(ps1) 34 | C.lua_pushstring(C.pry_L, c1) 35 | C.free(unsafe.Pointer(c1)) 36 | 37 | C.lua_setfield(C.pry_L, C.LUA_GLOBALSINDEX, C.CString("_PROMPT")) 38 | 39 | c2 := C.CString(ps2) 40 | C.lua_pushstring(C.pry_L, c2) 41 | C.free(unsafe.Pointer(c2)) 42 | 43 | C.lua_setfield(C.pry_L, C.LUA_GLOBALSINDEX, C.CString("_PROMPT2")) 44 | } 45 | 46 | func (p Lua) Eval(code string) { 47 | ccode := C.CString(code) 48 | defer C.free(unsafe.Pointer(ccode)) 49 | C.pry_eval(ccode) 50 | } 51 | 52 | func (p Lua) EvalFile(file string, args []string) int { 53 | cfile := C.CString(file) 54 | defer C.free(unsafe.Pointer(cfile)) 55 | 56 | return int(C.pry_eval_file(cfile)) 57 | } 58 | 59 | func (p Lua) REPL() { 60 | C.pry_do_repl() 61 | } 62 | 63 | func (p Lua) Close() { 64 | C.lua_close(C.pry_L) 65 | } 66 | 67 | var Instance = Lua{} 68 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/fetch-blob/file.js: -------------------------------------------------------------------------------- 1 | import Blob from './index.js' 2 | 3 | const _File = class File extends Blob { 4 | #lastModified = 0 5 | #name = '' 6 | 7 | /** 8 | * @param {*[]} fileBits 9 | * @param {string} fileName 10 | * @param {{lastModified?: number, type?: string}} options 11 | */// @ts-ignore 12 | constructor (fileBits, fileName, options = {}) { 13 | if (arguments.length < 2) { 14 | throw new TypeError(`Failed to construct 'File': 2 arguments required, but only ${arguments.length} present.`) 15 | } 16 | super(fileBits, options) 17 | 18 | if (options === null) options = {} 19 | 20 | // Simulate WebIDL type casting for NaN value in lastModified option. 21 | const lastModified = options.lastModified === undefined ? Date.now() : Number(options.lastModified) 22 | if (!Number.isNaN(lastModified)) { 23 | this.#lastModified = lastModified 24 | } 25 | 26 | this.#name = String(fileName) 27 | } 28 | 29 | get name () { 30 | return this.#name 31 | } 32 | 33 | get lastModified () { 34 | return this.#lastModified 35 | } 36 | 37 | get [Symbol.toStringTag] () { 38 | return 'File' 39 | } 40 | 41 | static [Symbol.hasInstance] (object) { 42 | return !!object && object instanceof Blob && 43 | /^(File)$/.test(object[Symbol.toStringTag]) 44 | } 45 | } 46 | 47 | /** @type {typeof globalThis.File} */// @ts-ignore 48 | export const File = _File 49 | export default File 50 | -------------------------------------------------------------------------------- /languages/nodejs/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | //go:generate bash ../../scripts/gofiles.sh generated_files.go 4 | 5 | import ( 6 | "io/ioutil" 7 | "os" 8 | "os/exec" 9 | "syscall" 10 | 11 | "github.com/replit/prybar/utils" 12 | ) 13 | 14 | func findHelper(path string) string { 15 | bytes, err := File(path + ".js") 16 | if bytes != nil { 17 | f, err := ioutil.TempFile("", "prybar-nodejs-*.js") 18 | if err != nil { 19 | panic(err) 20 | } 21 | 22 | if _, err = f.Write(bytes); err != nil { 23 | panic(err) 24 | } 25 | if err = f.Close(); err != nil { 26 | panic(err) 27 | } 28 | return f.Name() 29 | } 30 | if err != nil { 31 | panic(err) 32 | } 33 | panic("File not found") 34 | } 35 | 36 | func Execute(config *utils.Config) { 37 | path, err := exec.LookPath("node") 38 | 39 | if err != nil { 40 | panic(err) 41 | } 42 | 43 | args := []string{"node", findHelper("repl")} 44 | 45 | if config.Quiet { 46 | os.Setenv("PRYBAR_QUIET", "1") 47 | } 48 | 49 | os.Setenv("PRYBAR_CODE", config.Code) 50 | os.Setenv("PRYBAR_EXP", config.Exp) 51 | os.Setenv("PRYBAR_PS1", config.Ps1) 52 | 53 | if config.Interactive { 54 | os.Setenv("PRYBAR_INTERACTIVE", "1") 55 | } 56 | 57 | // We only support one file, despite the fact that this 58 | // variable is a list. 59 | if len(config.Args) >= 1 { 60 | os.Setenv("PRYBAR_FILE", config.Args[0]) 61 | } else { 62 | os.Setenv("PRYBAR_FILE", "") 63 | } 64 | 65 | syscall.Exec(path, args, os.Environ()) 66 | } 67 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/formdata-polyfill/formdata-to-blob.js: -------------------------------------------------------------------------------- 1 | /*! formdata-polyfill. MIT License. Jimmy Wärting */ 2 | 3 | const escape = (str, filename) => 4 | (filename ? str : str.replace(/\r?\n|\r/g, '\r\n')) 5 | .replace(/\n/g, '%0A') 6 | .replace(/\r/g, '%0D') 7 | .replace(/"/g, '%22') 8 | 9 | /** 10 | * pure function to convert any formData instance to a Blob 11 | * instances synchronous without reading all of the files 12 | * 13 | * @param {FormData|*} formData an instance of a formData Class 14 | * @param {Blob|*} [BlobClass=Blob] the Blob class to use when constructing it 15 | */ 16 | export function formDataToBlob (formData, BlobClass = Blob) { 17 | const boundary = ('----formdata-polyfill-' + Math.random()) 18 | const chunks = [] 19 | const prefix = `--${boundary}\r\nContent-Disposition: form-data; name="` 20 | 21 | for (let [name, value] of formData) { 22 | if (typeof value === 'string') { 23 | chunks.push(prefix + escape(name) + `"\r\n\r\n${value.replace(/\r(?!\n)|(?=12.20.0" 27 | }, 28 | "keywords": [ 29 | "formdata", 30 | "fetch", 31 | "node-fetch", 32 | "html5", 33 | "browser", 34 | "polyfill" 35 | ], 36 | "author": "Jimmy Wärting", 37 | "license": "MIT", 38 | "bugs": { 39 | "url": "https://github.com/jimmywarting/FormData/issues" 40 | }, 41 | "homepage": "https://github.com/jimmywarting/FormData#readme", 42 | "dependencies": { 43 | "fetch-blob": "^3.1.2" 44 | }, 45 | "devDependencies": { 46 | "@types/google-closure-compiler": "^0.0.19", 47 | "@types/node": "^16.7.10", 48 | "google-closure-compiler": "^20210808.0.0" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/fetch-blob/streams.cjs: -------------------------------------------------------------------------------- 1 | /* c8 ignore start */ 2 | // 64 KiB (same size chrome slice theirs blob into Uint8array's) 3 | const POOL_SIZE = 65536 4 | 5 | if (!globalThis.ReadableStream) { 6 | // `node:stream/web` got introduced in v16.5.0 as experimental 7 | // and it's preferred over the polyfilled version. So we also 8 | // suppress the warning that gets emitted by NodeJS for using it. 9 | try { 10 | const process = require('node:process') 11 | const { emitWarning } = process 12 | try { 13 | process.emitWarning = () => {} 14 | Object.assign(globalThis, require('node:stream/web')) 15 | process.emitWarning = emitWarning 16 | } catch (error) { 17 | process.emitWarning = emitWarning 18 | throw error 19 | } 20 | } catch (error) { 21 | // fallback to polyfill implementation 22 | Object.assign(globalThis, require('web-streams-polyfill/dist/ponyfill.es2018.js')) 23 | } 24 | } 25 | 26 | try { 27 | // Don't use node: prefix for this, require+node: is not supported until node v14.14 28 | // Only `import()` can use prefix in 12.20 and later 29 | const { Blob } = require('buffer') 30 | if (Blob && !Blob.prototype.stream) { 31 | Blob.prototype.stream = function name (params) { 32 | let position = 0 33 | const blob = this 34 | 35 | return new ReadableStream({ 36 | type: 'bytes', 37 | async pull (ctrl) { 38 | const chunk = blob.slice(position, Math.min(blob.size, position + POOL_SIZE)) 39 | const buffer = await chunk.arrayBuffer() 40 | position += buffer.byteLength 41 | ctrl.enqueue(new Uint8Array(buffer)) 42 | 43 | if (position === blob.size) { 44 | ctrl.close() 45 | } 46 | } 47 | }) 48 | } 49 | } 50 | } catch (error) {} 51 | /* c8 ignore end */ 52 | -------------------------------------------------------------------------------- /languages/tcl/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // USING_CGO 4 | 5 | /* 6 | #cgo pkg-config: tcl 7 | #include 8 | #include 9 | 10 | */ 11 | import "C" 12 | 13 | import ( 14 | "fmt" 15 | "os" 16 | "strconv" 17 | "unsafe" 18 | ) 19 | 20 | type Tcl struct { 21 | interp *C.Tcl_Interp 22 | } 23 | 24 | func (p *Tcl) Open() { 25 | p.interp = C.Tcl_CreateInterp() 26 | 27 | if C.Tcl_Init(p.interp) != C.TCL_OK { 28 | panic("tcl interp did not init") 29 | } 30 | } 31 | 32 | func (p *Tcl) Version() string { 33 | major := C.int(0) 34 | minor := C.int(0) 35 | patch := C.int(0) 36 | 37 | C.Tcl_GetVersion( 38 | &major, 39 | &minor, 40 | &patch, 41 | nil, 42 | ) 43 | 44 | return "TCL " + 45 | strconv.Itoa(int(major)) + "." + 46 | strconv.Itoa(int(minor)) + "." + 47 | strconv.Itoa(int(patch)) 48 | } 49 | 50 | func (p *Tcl) eval(code string) string { 51 | ccode := C.CString(code) 52 | 53 | status := C.Tcl_Eval(p.interp, ccode) 54 | 55 | result := C.GoString(C.Tcl_GetStringResult(p.interp)) 56 | 57 | if status == C.TCL_OK { 58 | return result 59 | } 60 | 61 | errstr := C.GoString(C.Tcl_GetStringResult(p.interp)) 62 | fmt.Fprintf(os.Stderr, "error: %s\n", errstr) 63 | return "" 64 | } 65 | 66 | func (p *Tcl) EvalFile(file string, args []string) int { 67 | cfile := C.CString(file) 68 | defer C.free(unsafe.Pointer(cfile)) 69 | 70 | status := C.Tcl_EvalFile(p.interp, cfile) 71 | 72 | if status != C.TCL_OK { 73 | errstr := C.GoString(C.Tcl_GetStringResult(p.interp)) 74 | fmt.Fprintf(os.Stderr, "error: %s\n", errstr) 75 | return int(status) 76 | } 77 | 78 | return 0 79 | } 80 | 81 | func (p *Tcl) Eval(code string) { 82 | p.eval(code) 83 | } 84 | 85 | func (p *Tcl) EvalExpression(code string) string { 86 | return p.eval(code) 87 | } 88 | 89 | func (p *Tcl) Close() { 90 | C.Tcl_Finalize() 91 | } 92 | 93 | var Instance = &Tcl{} 94 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/fetch-blob/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fetch-blob", 3 | "version": "3.2.0", 4 | "description": "Blob & File implementation in Node.js, originally from node-fetch.", 5 | "main": "index.js", 6 | "type": "module", 7 | "files": [ 8 | "from.js", 9 | "file.js", 10 | "file.d.ts", 11 | "index.js", 12 | "index.d.ts", 13 | "from.d.ts", 14 | "streams.cjs" 15 | ], 16 | "scripts": { 17 | "test": "node --experimental-loader ./test/http-loader.js ./test/test-wpt-in-node.js", 18 | "report": "c8 --reporter json --reporter text npm run test", 19 | "coverage": "npm run report && codecov -f coverage/coverage-final.json", 20 | "prepublishOnly": "tsc --declaration --emitDeclarationOnly --allowJs index.js from.js" 21 | }, 22 | "repository": "https://github.com/node-fetch/fetch-blob.git", 23 | "keywords": [ 24 | "blob", 25 | "file", 26 | "node-fetch" 27 | ], 28 | "engines": { 29 | "node": "^12.20 || >= 14.13" 30 | }, 31 | "author": "Jimmy Wärting (https://jimmy.warting.se)", 32 | "license": "MIT", 33 | "bugs": { 34 | "url": "https://github.com/node-fetch/fetch-blob/issues" 35 | }, 36 | "homepage": "https://github.com/node-fetch/fetch-blob#readme", 37 | "devDependencies": { 38 | "@types/node": "^17.0.9", 39 | "c8": "^7.11.0", 40 | "typescript": "^4.5.4" 41 | }, 42 | "funding": [ 43 | { 44 | "type": "github", 45 | "url": "https://github.com/sponsors/jimmywarting" 46 | }, 47 | { 48 | "type": "paypal", 49 | "url": "https://paypal.me/jimmywarting" 50 | } 51 | ], 52 | "dependencies": { 53 | "node-domexception": "^1.0.0", 54 | "web-streams-polyfill": "^3.0.3" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /languages/ocaml/main.go: -------------------------------------------------------------------------------- 1 | // OCaml main 2 | package main 3 | 4 | //go:generate bash ../../scripts/gofiles.sh generated_files.go 5 | 6 | import ( 7 | "github.com/replit/prybar/utils" 8 | "io/ioutil" 9 | "os" 10 | "os/exec" 11 | "strings" 12 | "syscall" 13 | ) 14 | 15 | func findHelper(path string) string { 16 | bytes, err := File(path + ".ml") 17 | if bytes != nil { 18 | f, err := ioutil.TempFile("", "prybar-ocaml-*.ml") 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | if _, err = f.Write(bytes); err != nil { 24 | panic(err) 25 | } 26 | if err = f.Close(); err != nil { 27 | panic(err) 28 | } 29 | return f.Name() 30 | } 31 | if err != nil { 32 | panic(err) 33 | } 34 | panic("File not found: " + path + ".ml") 35 | } 36 | 37 | func Execute(config *utils.Config) { 38 | path, err := exec.LookPath("ocaml") 39 | 40 | if err != nil { 41 | panic(err) 42 | } 43 | 44 | args := []string{"ocaml"} 45 | // Fix for getting the various libs added to prybar when running through nix 46 | if value, ok := os.LookupEnv("OCAMLPATH"); ok { 47 | for _, val := range strings.Split(value, ":") { 48 | args = append(args, "-I", val) 49 | } 50 | } 51 | 52 | env := os.Environ() 53 | args = append(args, findHelper("repl"), "-s", "ml") 54 | 55 | if config.Quiet { 56 | args = append(args, "-q") 57 | } 58 | 59 | if config.Code != "" { 60 | args = append(args, "-c", config.Code) 61 | } else if config.Exp != "" { 62 | args = append(args, "-e", config.Exp) 63 | } else if (config.Interactive || config.OurInteractive) { 64 | args = append(args, "-i") 65 | } 66 | 67 | if config.Ps1 != "" { 68 | env = append(env, "PRYBAR_PS1="+config.Ps1) 69 | } 70 | 71 | if config.Ps2 != "" { 72 | env = append(env, "PRYBAR_PS2="+config.Ps2) 73 | } 74 | 75 | if config.Args != nil && len(config.Args) > 0 { 76 | args = append(args, config.Args...) 77 | } 78 | 79 | syscall.Exec(path, args, env) 80 | } 81 | -------------------------------------------------------------------------------- /languages/elisp/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/exec" 7 | "path/filepath" 8 | "syscall" 9 | 10 | "github.com/replit/prybar/utils" 11 | ) 12 | 13 | func Execute(config *utils.Config) { 14 | args := []string{} 15 | 16 | if _, err := os.Stat("Cask"); err == nil { 17 | if _, err := exec.LookPath("cask"); err == nil { 18 | args = append(args, "cask", "exec") 19 | } 20 | } 21 | 22 | execPath, err := os.Executable() 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | runDir := filepath.Dir(execPath) 28 | 29 | prybarAssetDir := os.Getenv("PRYBAR_ASSETS_DIR") 30 | if prybarAssetDir == "" { 31 | prybarAssetDir = filepath.Join(runDir, "prybar_assets") 32 | } 33 | replPath := filepath.Join(prybarAssetDir, "elisp", "repl.el") 34 | 35 | args = append( 36 | args, "emacs", "-nw", "-Q", "--load", replPath, 37 | "--eval", "(prybar-repl)", 38 | ) 39 | 40 | os.Setenv("PRYBAR_EVAL", config.Exp) 41 | os.Setenv("PRYBAR_EXEC", config.Code) 42 | os.Setenv("PRYBAR_PS1", config.Ps1) 43 | 44 | if config.Quiet { 45 | os.Setenv("PRYBAR_QUIET", "1") 46 | } else { 47 | os.Setenv("PRYBAR_QUIET", "") 48 | } 49 | 50 | // We only support one file, despite the fact that this 51 | // variable is a list. 52 | if len(config.Args) >= 1 { 53 | os.Setenv("PRYBAR_FILE", config.Args[0]) 54 | } else { 55 | os.Setenv("PRYBAR_FILE", "") 56 | } 57 | 58 | if !(config.Interactive || config.OurInteractive) { 59 | fmt.Fprintln(os.Stderr, "prybar-elisp: warn: non-interactive mode not implemented") 60 | } 61 | 62 | if config.Ps2 != "... " { 63 | fmt.Fprintln(os.Stderr, "prybar-elisp: warn: ps2 not implemented") 64 | } 65 | 66 | path, err := exec.LookPath(args[0]) 67 | if err != nil { 68 | fmt.Fprintf(os.Stderr, "%s: command not found\n", args[0]) 69 | } 70 | 71 | err = syscall.Exec(path, args, os.Environ()) 72 | if err != nil { 73 | fmt.Fprintf(os.Stderr, "failed to exec %s: %s\n", path, err) 74 | os.Exit(1) 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/node-domexception/README.md: -------------------------------------------------------------------------------- 1 | # DOMException 2 | An implementation of the DOMException class from NodeJS 3 | 4 | NodeJS has DOMException built in, but it's not globally available, and you can't require/import it from somewhere. 5 | 6 | This package exposes the [`DOMException`](https://developer.mozilla.org/en-US/docs/Web/API/DOMException) class that comes from NodeJS itself. (including all of the legacy codes) 7 | 8 | (plz don't depend on this package in any other environment other than node >=10.5) 9 | 10 | ```js 11 | import DOMException from 'node-domexception' 12 | import { MessageChannel } from 'worker_threads' 13 | 14 | async function hello() { 15 | const port = new MessageChannel().port1 16 | const ab = new ArrayBuffer() 17 | port.postMessage(ab, [ab, ab]) 18 | } 19 | 20 | hello().catch(err => { 21 | console.assert(err.name === 'DataCloneError') 22 | console.assert(err.code === 25) 23 | console.assert(err instanceof DOMException) 24 | }) 25 | 26 | const e1 = new DOMException('Something went wrong', 'BadThingsError') 27 | console.assert(e1.name === 'BadThingsError') 28 | console.assert(e1.code === 0) 29 | 30 | const e2 = new DOMException('Another exciting error message', 'NoModificationAllowedError') 31 | console.assert(e2.name === 'NoModificationAllowedError') 32 | console.assert(e2.code === 7) 33 | 34 | console.assert(DOMException.INUSE_ATTRIBUTE_ERR === 10) 35 | ``` 36 | 37 | # Background 38 | 39 | The only possible way is to use some web-ish tools that have been introduced into NodeJS that throws a DOMException and catch the constructor. This is exactly what this package dose for you and exposes it.
40 | This way you will have the same class that NodeJS has and you can check if the error is a instance of DOMException.
41 | The instanceof check would not have worked with a custom class such as the DOMException provided by domenic which also is much larger in size since it has to re-construct the hole class from the ground up. 42 | 43 | The DOMException is used in many places such as the Fetch API, File & Blobs, PostMessaging and more.
44 | Why they decided to call it **DOM**, I don't know 45 | 46 | Please consider sponsoring if you find this helpful 47 | -------------------------------------------------------------------------------- /utils/utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | "runtime" 8 | ) 9 | 10 | type Config struct { 11 | Code string 12 | Quiet bool 13 | Exp string 14 | Ps1, Ps2 string 15 | Args []string 16 | Interactive, OurInteractive bool 17 | } 18 | 19 | func ParseFlags() *Config { 20 | config := &Config{} 21 | 22 | flag.StringVar(&config.Code, "c", "", "execute without printing result") 23 | flag.StringVar(&config.Exp, "e", "", "evaluate and print result") 24 | 25 | flag.StringVar(&config.Ps1, "ps1", "--> ", "repl prompt") 26 | flag.StringVar(&config.Ps2, "ps2", "... ", "repl continuation prompt") 27 | 28 | flag.BoolVar(&config.Interactive, "i", false, "interactive (use language repl)") 29 | flag.BoolVar(&config.OurInteractive, "I", false, "interactive (use readline repl)") 30 | flag.BoolVar(&config.Quiet, "q", false, "don't print language version") 31 | 32 | flag.Usage = func() { 33 | fmt.Fprintf(os.Stderr, "Usage: %s [FLAGS] [FILENAME]...\n", os.Args[0]) 34 | flag.PrintDefaults() 35 | } 36 | 37 | flag.Parse() 38 | 39 | config.Args = flag.Args() 40 | return config 41 | } 42 | 43 | func DoCli(p PluginBase) { 44 | 45 | config := ParseFlags() 46 | 47 | runtime.LockOSThread() 48 | p.Open() 49 | lang := &Language{ptr: p, ps1: config.Ps1} 50 | 51 | if !config.Quiet { 52 | fmt.Println(lang.Version()) 53 | } 54 | 55 | if config.Code != "" { 56 | lang.Eval(config.Code) 57 | } 58 | if config.Exp != "" { 59 | lang.EvalAndTryToPrint(config.Exp) 60 | } 61 | 62 | if len(config.Args) > 0 { 63 | if _, err := os.Stat(config.Args[0]); os.IsNotExist(err) { 64 | fmt.Println("No such file:", config.Args[0]) 65 | os.Exit(2) 66 | } else { 67 | exitCode := lang.EvalFile(config.Args[0], config.Args[1:]) 68 | // TODO: Maybe log if exitCode is non-zero and interractive is true? 69 | if exitCode != 0 && !config.Interactive && !config.OurInteractive { 70 | os.Exit(exitCode) 71 | } 72 | } 73 | } 74 | 75 | if config.Interactive { 76 | lang.SetPrompts(config.Ps1, config.Ps2) 77 | lang.REPL() 78 | } else if config.OurInteractive { 79 | lang.InternalREPL() 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /test_files/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test_files", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "data-uri-to-buffer": { 8 | "version": "4.0.0", 9 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", 10 | "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==" 11 | }, 12 | "fetch-blob": { 13 | "version": "3.2.0", 14 | "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", 15 | "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", 16 | "requires": { 17 | "node-domexception": "^1.0.0", 18 | "web-streams-polyfill": "^3.0.3" 19 | } 20 | }, 21 | "formdata-polyfill": { 22 | "version": "4.0.10", 23 | "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", 24 | "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", 25 | "requires": { 26 | "fetch-blob": "^3.1.2" 27 | } 28 | }, 29 | "node-domexception": { 30 | "version": "1.0.0", 31 | "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", 32 | "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" 33 | }, 34 | "node-fetch": { 35 | "version": "3.2.10", 36 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.10.tgz", 37 | "integrity": "sha512-MhuzNwdURnZ1Cp4XTazr69K0BTizsBroX7Zx3UgDSVcZYKF/6p0CBe4EUb/hLqmzVhl0UpYfgRljQ4yxE+iCxA==", 38 | "requires": { 39 | "data-uri-to-buffer": "^4.0.0", 40 | "fetch-blob": "^3.1.4", 41 | "formdata-polyfill": "^4.0.10" 42 | } 43 | }, 44 | "web-streams-polyfill": { 45 | "version": "3.2.1", 46 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", 47 | "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /languages/clojure/deps.nix: -------------------------------------------------------------------------------- 1 | # generated by clj2nix-1.0.6 2 | { pkgs ? import {} }: 3 | 4 | let repos = [ 5 | "http://jcenter.bintray.com" 6 | "https://repo1.maven.org/maven2/" 7 | "https://repo.clojars.org/" ]; 8 | 9 | in rec { 10 | makePaths = {extraClasspaths ? null}: 11 | (pkgs.lib.concatMap 12 | (dep: 13 | builtins.map 14 | (path: 15 | if builtins.isString path then 16 | path 17 | else if builtins.hasAttr "jar" path then 18 | path.jar 19 | else if builtins.hasAttr "outPath" path then 20 | path.outPath 21 | else 22 | path 23 | ) 24 | dep.paths) 25 | packages) 26 | ++ (if extraClasspaths != null then [ extraClasspaths ] else []); 27 | makeClasspaths = {extraClasspaths ? null}: builtins.concatStringsSep ":" (makePaths {inherit extraClasspaths;}); 28 | packageSources = builtins.map (dep: dep.src) packages; 29 | 30 | packages = [ 31 | rec { 32 | name = "clojure/org.clojure"; 33 | src = pkgs.fetchMavenArtifact { 34 | inherit repos; 35 | artifactId = "clojure"; 36 | groupId = "org.clojure"; 37 | sha512 = "4bb567b9262d998f554f44e677a8628b96e919bc8bcfb28ab2e80d9810f8adf8f13a8898142425d92f3515e58c57b16782cff12ba1b5ffb38b7d0ccd13d99bbc"; 38 | version = "1.10.3"; 39 | }; 40 | paths = [ src ]; 41 | } 42 | rec { 43 | name = "spec.alpha/org.clojure"; 44 | src = pkgs.fetchMavenArtifact { 45 | inherit repos; 46 | artifactId = "spec.alpha"; 47 | groupId = "org.clojure"; 48 | sha512 = "0740dc3a755530f52e32d27139a9ebfd7cbdb8d4351c820de8d510fe2d52a98acd6e4dfc004566ede3d426e52ec98accdca1156965218f269e60dd1cd4242a73"; 49 | version = "0.2.194"; 50 | }; 51 | paths = [ src ]; 52 | } 53 | rec { 54 | name = "core.specs.alpha/org.clojure"; 55 | src = pkgs.fetchMavenArtifact { 56 | inherit repos; 57 | artifactId = "core.specs.alpha"; 58 | groupId = "org.clojure"; 59 | sha512 = "c1d2a740963896d97cd6b9a8c3dcdcc84459ea66b44170c05b8923e5fbb731b4b292b217ed3447bbc9e744c9a496552f77a6c38aea232e5e69f8faa627dea4b5"; 60 | version = "0.2.56"; 61 | }; 62 | paths = [ src ]; 63 | } 64 | ]; 65 | } -------------------------------------------------------------------------------- /languages/clojure/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | //go:generate bash ../../scripts/gofiles.sh generated_files.go 4 | 5 | import ( 6 | "fmt" 7 | "io/ioutil" 8 | "os" 9 | "os/exec" 10 | "syscall" 11 | "github.com/replit/prybar/utils" 12 | ) 13 | 14 | func findHelper(path string) string { 15 | fileName := path + ".clj" 16 | bytes, err := File(fileName) 17 | if bytes != nil { 18 | f, err := ioutil.TempFile("", fileName) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | if _, err = f.Write(bytes); err != nil { 24 | panic(err) 25 | } 26 | if err = f.Close(); err != nil { 27 | panic(err) 28 | } 29 | return f.Name() 30 | } 31 | if err != nil { 32 | panic(err) 33 | } 34 | panic("File not found: " + fileName) 35 | } 36 | 37 | func Execute(config *utils.Config) { 38 | path, err := exec.LookPath("clojure") 39 | 40 | if err != nil { 41 | panic(err) 42 | } 43 | 44 | env := os.Environ() 45 | args := []string{"clojure"} 46 | 47 | hasOption := config.Code != "" || config.Exp != "" || 48 | config.Interactive || config.OurInteractive 49 | hasFile := false 50 | 51 | if config.Ps1 != "" { 52 | args = append(args, "-J-DPRYBAR_PS1=" + config.Ps1) 53 | } 54 | 55 | if config.Ps2 != "" { 56 | args = append(args, "-J-DPRYBAR_PS2=" + config.Ps2) 57 | } 58 | 59 | if config.Quiet { 60 | args = append(args, "-J-DPRYBAR_QUIET=true") 61 | } 62 | 63 | if hasOption { 64 | if config.Args != nil && len(config.Args) > 0 { 65 | if _, err := os.Stat(config.Args[0]); os.IsNotExist(err) { 66 | fmt.Println("No such file:", config.Args[0]) 67 | os.Exit(2) 68 | } 69 | 70 | hasFile = true 71 | } 72 | 73 | if hasFile { 74 | args = append(args, "--init", config.Args[0]) 75 | } 76 | 77 | if config.Code != "" { 78 | // "--eval" prints non-nil results only. 79 | effect := fmt.Sprintf("(do %s nil)", config.Code) 80 | args = append(args, "--eval", effect) 81 | } 82 | 83 | if config.Exp != "" { 84 | args = append(args, "--eval", config.Exp) 85 | } 86 | 87 | if config.Interactive || config.OurInteractive { 88 | args = append(args, findHelper("prybar_repl")) 89 | } 90 | 91 | if hasFile { 92 | args = append(args, config.Args[1:]...) 93 | } else { 94 | args = append(args, config.Args...) 95 | } 96 | } else { 97 | args = append(args, "--eval", "") 98 | args = append(args, config.Args...) 99 | } 100 | 101 | syscall.Exec(path, args, env) 102 | } 103 | 104 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/formdata-polyfill/esm.min.js: -------------------------------------------------------------------------------- 1 | /*! formdata-polyfill. MIT License. Jimmy Wärting */ 2 | 3 | import C from 'fetch-blob' 4 | import F from 'fetch-blob/file.js' 5 | 6 | var {toStringTag:t,iterator:i,hasInstance:h}=Symbol, 7 | r=Math.random, 8 | m='append,set,get,getAll,delete,keys,values,entries,forEach,constructor'.split(','), 9 | f=(a,b,c)=>(a+='',/^(Blob|File)$/.test(b && b[t])?[(c=c!==void 0?c+'':b[t]=='File'?b.name:'blob',a),b.name!==c||b[t]=='blob'?new F([b],c,b):b]:[a,b+'']), 10 | e=(c,f)=>(f?c:c.replace(/\r?\n|\r/g,'\r\n')).replace(/\n/g,'%0A').replace(/\r/g,'%0D').replace(/"/g,'%22'), 11 | x=(n, a, e)=>{if(a.lengthtypeof o[m]!='function')} 22 | append(...a){x('append',arguments,2);this.#d.push(f(...a))} 23 | delete(a){x('delete',arguments,1);a+='';this.#d=this.#d.filter(([b])=>b!==a)} 24 | get(a){x('get',arguments,1);a+='';for(var b=this.#d,l=b.length,c=0;cc[0]===a&&b.push(c[1]));return b} 26 | has(a){x('has',arguments,1);a+='';return this.#d.some(b=>b[0]===a)} 27 | forEach(a,b){x('forEach',arguments,1);for(var [c,d]of this)a.call(b,d,c,this)} 28 | set(...a){x('set',arguments,2);var b=[],c=!0;a=f(...a);this.#d.forEach(d=>{d[0]===a[0]?c&&(c=!b.push(a)):b.push(d)});c&&b.push(a);this.#d=b} 29 | *entries(){yield*this.#d} 30 | *keys(){for(var[a]of this)yield a} 31 | *values(){for(var[,a]of this)yield a}} 32 | 33 | /** @param {FormData} F */ 34 | export function formDataToBlob (F,B=C){ 35 | var b=`${r()}${r()}`.replace(/\./g, '').slice(-28).padStart(32, '-'),c=[],p=`--${b}\r\nContent-Disposition: form-data; name="` 36 | F.forEach((v,n)=>typeof v=='string' 37 | ?c.push(p+e(n)+`"\r\n\r\n${v.replace(/\r(?!\n)|(?&2 62 | @grep -h "[#]# " $(MAKEFILE_LIST) | \ 63 | sed 's/^/ make /' | \ 64 | sed 's/:[^#]*[#]# /|/' | \ 65 | sed 's/%/LANG/' | \ 66 | column -t -s'|' >&2 67 | -------------------------------------------------------------------------------- /utils/language.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | 7 | "github.com/chzyer/readline" 8 | ) 9 | 10 | type PluginBase interface { 11 | Open() 12 | Close() 13 | Version() string 14 | } 15 | 16 | type PluginEval interface { 17 | PluginBase 18 | Eval(code string) 19 | } 20 | 21 | type PluginEvalExpression interface { 22 | PluginBase 23 | EvalExpression(code string) string 24 | } 25 | 26 | type PluginEvalFile interface { 27 | PluginBase 28 | EvalFile(file string, args []string) int 29 | } 30 | 31 | type PluginREPL interface { 32 | PluginBase 33 | REPL() 34 | } 35 | 36 | type PluginREPLLikeEval interface { 37 | PluginBase 38 | REPLLikeEval(code string) 39 | } 40 | 41 | type PluginSetPrompts interface { 42 | PluginBase 43 | SetPrompts(ps1, ps2 string) 44 | } 45 | 46 | type Language struct { 47 | ptr PluginBase 48 | ps1 string 49 | } 50 | 51 | func (lang Language) Version() string { 52 | return lang.ptr.Version() 53 | } 54 | 55 | func (lang Language) Eval(code string) { 56 | lang.ptr.(PluginEval).Eval(code) 57 | } 58 | 59 | func (lang Language) EvalAndTryToPrint(code string) { 60 | ee, ok := lang.ptr.(PluginEvalExpression) 61 | if ok { 62 | fmt.Println(ee.EvalExpression(code)) 63 | } else { 64 | lang.ptr.(PluginEval).Eval(code) 65 | } 66 | } 67 | 68 | func (lang Language) REPLLikeEval(code string) { 69 | rle, ok := lang.ptr.(PluginREPLLikeEval) 70 | if ok { 71 | rle.REPLLikeEval(code) 72 | return 73 | } 74 | 75 | ee, ok := lang.ptr.(PluginEvalExpression) 76 | if ok { 77 | fmt.Println(ee.EvalExpression(code)) 78 | } else { 79 | lang.ptr.(PluginEval).Eval(code) 80 | } 81 | } 82 | 83 | func (lang Language) EvalFile(file string, args []string) int { 84 | pef, ok := lang.ptr.(PluginEvalFile) 85 | if ok { 86 | return pef.EvalFile(file, args) 87 | } else { 88 | dat, err := ioutil.ReadFile(file) 89 | if err != nil { 90 | panic(err) 91 | } 92 | lang.Eval(string(dat)) 93 | return 0 94 | } 95 | } 96 | 97 | func (lang Language) REPL() { 98 | repl, ok := lang.ptr.(PluginREPL) 99 | if ok { 100 | repl.REPL() 101 | } else { 102 | lang.InternalREPL() 103 | } 104 | } 105 | 106 | func (lang Language) InternalREPL() { 107 | for { 108 | line, err := readline.Line(lang.ps1) 109 | if err != nil { 110 | break 111 | } 112 | lang.REPLLikeEval(line) 113 | readline.AddHistory(line) 114 | } 115 | } 116 | 117 | func (lang Language) SetPrompts(ps1, ps2 string) { 118 | ee, ok := lang.ptr.(PluginSetPrompts) 119 | if ok { 120 | ee.SetPrompts(ps1, ps2) 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /tests/julia/header.exp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | # 3 | # This Expect script was generated by autoexpect on Fri Jun 12 21:00:42 2020 4 | # Expect and autoexpect were both written by Don Libes, NIST. 5 | # 6 | # Note that autoexpect does not guarantee a working script. It 7 | # necessarily has to guess about certain things. Two reasons a script 8 | # might fail are: 9 | # 10 | # 1) timing - A surprising number of programs (rn, ksh, zsh, telnet, 11 | # etc.) and devices discard or ignore keystrokes that arrive "too 12 | # quickly" after prompts. If you find your new script hanging up at 13 | # one spot, try adding a short sleep just before the previous send. 14 | # Setting "force_conservative" to 1 (see below) makes Expect do this 15 | # automatically - pausing briefly before sending each character. This 16 | # pacifies every program I know of. The -c flag makes the script do 17 | # this in the first place. The -C flag allows you to define a 18 | # character to toggle this mode off and on. 19 | 20 | set force_conservative 0 ;# set to 1 to force conservative mode even if 21 | ;# script wasn't run conservatively originally 22 | if {$force_conservative} { 23 | set send_slow {1 .1} 24 | proc send {ignore arg} { 25 | sleep .1 26 | exp_send -s -- $arg 27 | } 28 | } 29 | 30 | # 31 | # 2) differing output - Some programs produce different output each time 32 | # they run. The "date" command is an obvious example. Another is 33 | # ftp, if it produces throughput statistics at the end of a file 34 | # transfer. If this causes a problem, delete these patterns or replace 35 | # them with wildcards. An alternative is to use the -p flag (for 36 | # "prompt") which makes Expect only look for the last line of output 37 | # (i.e., the prompt). The -P flag allows you to define a character to 38 | # toggle this mode off and on. 39 | # 40 | # Read the man page for more info. 41 | # 42 | # -Don 43 | 44 | 45 | set timeout -1 46 | spawn ./prybar-julia -i 47 | match_max 100000 48 | expect -exact " \[1m\[32m_\[0m\r 49 | \[1m\[34m_\[0m \[0m_\[0m \[1m\[31m_\[1m\[32m(_)\[1m\[35m_\[0m | Documentation: https://docs.julialang.org\r 50 | \[1m\[34m(_)\[0m | \[1m\[31m(_)\[0m \[1m\[35m(_)\[0m |\r 51 | \[0m_ _ _| |_ __ _\[0m | Type \"?\" for help, \"\]?\" for Pkg help.\r 52 | \[0m| | | | | | |/ _` |\[0m |\r 53 | \[0m| | |_| | | | (_| |\[0m | Version 1.5.4 (2021-03-11)\r 54 | \[0m_/ |\\__'_|_|_|\\__'_|\[0m | Official https://julialang.org/ release\r 55 | \[0m|__/\[0m |\r 56 | \r 57 | \r 58 | \[?2004h\r\[0K\[1m--> \[0m\[0m\r\[4C\r\[4C" 59 | send -- "" 60 | expect eof 61 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/web-streams-polyfill/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web-streams-polyfill", 3 | "version": "3.2.1", 4 | "description": "Web Streams, based on the WHATWG spec reference implementation", 5 | "main": "dist/polyfill", 6 | "browser": "dist/polyfill.min.js", 7 | "module": "dist/polyfill.mjs", 8 | "types": "dist/types/polyfill.d.ts", 9 | "typesVersions": { 10 | ">=3.6": { 11 | "dist/types/*": [ 12 | "dist/types/ts3.6/*" 13 | ] 14 | } 15 | }, 16 | "scripts": { 17 | "test": "npm run test:types && npm run test:unit && npm run test:wpt", 18 | "test:wpt": "node --expose_gc ./test/run-web-platform-tests.js", 19 | "pretest:wpt": "git submodule update --init --recursive", 20 | "test:types": "tsc -p ./test/types/tsconfig.json", 21 | "test:unit": "jasmine --config=test/unit/jasmine.json", 22 | "lint": "eslint \"src/**/*.ts\"", 23 | "build": "npm run build:bundle && npm run build:types", 24 | "build:bundle": "rollup -c", 25 | "build:types": "tsc --project . --emitDeclarationOnly --declarationDir ./lib && api-extractor run && node ./build/downlevel-dts.js", 26 | "accept:types": "tsc --project . --emitDeclarationOnly --declarationDir ./lib && api-extractor run --local && node ./build/downlevel-dts.js", 27 | "prepare": "npm run build" 28 | }, 29 | "files": [ 30 | "dist", 31 | "es6", 32 | "es2018", 33 | "ponyfill" 34 | ], 35 | "engines": { 36 | "node": ">= 8" 37 | }, 38 | "repository": { 39 | "type": "git", 40 | "url": "git+https://github.com/MattiasBuelens/web-streams-polyfill.git" 41 | }, 42 | "keywords": [ 43 | "streams", 44 | "whatwg", 45 | "polyfill" 46 | ], 47 | "author": "Mattias Buelens ", 48 | "contributors": [ 49 | "Diwank Singh " 50 | ], 51 | "license": "MIT", 52 | "bugs": { 53 | "url": "https://github.com/MattiasBuelens/web-streams-polyfill/issues" 54 | }, 55 | "homepage": "https://github.com/MattiasBuelens/web-streams-polyfill#readme", 56 | "devDependencies": { 57 | "@microsoft/api-extractor": "^7.13.4", 58 | "@rollup/plugin-inject": "^4.0.2", 59 | "@rollup/plugin-replace": "^2.4.2", 60 | "@rollup/plugin-strip": "^2.0.0", 61 | "@rollup/plugin-typescript": "^8.2.1", 62 | "@types/node": "^14.14.37", 63 | "@typescript-eslint/eslint-plugin": "^4.21.0", 64 | "@typescript-eslint/parser": "^4.21.0", 65 | "@ungap/promise-all-settled": "^1.1.2", 66 | "eslint": "^7.23.0", 67 | "jasmine": "^3.7.0", 68 | "micromatch": "^4.0.2", 69 | "rollup": "^2.44.0", 70 | "rollup-plugin-terser": "^7.0.2", 71 | "ts-morph": "^10.0.2", 72 | "tslib": "^2.2.0", 73 | "typescript": "^4.2.4", 74 | "wpt-runner": "^3.2.1" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /scripts/docker-install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | cd /tmp 7 | 8 | packages=" 9 | 10 | # languages 11 | default-jre-headless 12 | emacs-nox 13 | liblua5.1-dev 14 | nodejs 15 | ocaml 16 | ocaml-findlib 17 | opam 18 | python-dev 19 | ruby2.7-dev 20 | sqlite3 21 | tcl-dev 22 | 23 | # install the same version of Python in this image that we intend to use with 24 | # Python in prod, since Prybar is dynamically linked. 25 | python3.8-dev 26 | 27 | # build and test 28 | bsdmainutils 29 | build-essential 30 | expect 31 | 32 | # things we link against 33 | libreadline-dev 34 | 35 | # used during installation 36 | git 37 | wget 38 | 39 | # used during runtime 40 | rlwrap 41 | 42 | " 43 | 44 | 45 | export DEBIAN_FRONTEND=noninteractive 46 | apt-get update 47 | apt install software-properties-common -y 48 | apt-get install -y curl 49 | curl -sL https://deb.nodesource.com/setup_14.x | bash - 50 | apt-get install -y $(grep -v "^#" <<< "$packages") 51 | rm -rf /var/lib/apt/lists/* 52 | 53 | printf "\n" | add-apt-repository ppa:deadsnakes/ppa 54 | apt install python3.10 -y 55 | apt install python3.10-dev -y 56 | 57 | go_version=1.16.5 58 | wget "https://dl.google.com/go/go${go_version}.linux-amd64.tar.gz" 59 | tar -xvf "go${go_version}.linux-amd64.tar.gz" 60 | mv go /usr/local 61 | rm -f "go${go_version}.linux-amd64.tar.gz" 62 | rm -rf go 63 | 64 | clojure_version=1.10.1.478 65 | wget "https://download.clojure.org/install/linux-install-${clojure_version}.sh" 66 | chmod +x "linux-install-${clojure_version}.sh" 67 | "./linux-install-${clojure_version}.sh" 68 | 69 | # The version in the Disco repos is out of date (1.0 series) and does 70 | # not expose the API we need. 71 | wget -nv https://julialang-s3.julialang.org/bin/linux/x64/1.5/julia-1.5.4-linux-x86_64.tar.gz 72 | tar -xf *.tar.gz 73 | cp -R julia-*/bin/* /usr/bin/ 74 | cp -R julia-*/include/* /usr/include/ 75 | cp -R julia-*/lib/* /usr/lib/ 76 | cp -R julia-*/share/* /usr/share/ 77 | rm -rf julia-* 78 | 79 | cat > /usr/lib/x86_64-linux-gnu/pkgconfig/julia.pc <<- EOM 80 | Name: julia 81 | Cflags: -I/usr/include/julia 82 | Version: 1.5.4 83 | Description: it's julia 84 | Libs: -L/usr/lib -ljulia 85 | EOM 86 | 87 | wget -nv https://downloads.lightbend.com/scala/2.13.1/scala-2.13.1.tgz 88 | tar -xf *.tgz 89 | cp -R scala-*/bin/* /usr/local/bin/ 90 | cp -R scala-*/lib/* /usr/local/lib/ 91 | rm -rf scala-* 92 | 93 | # prybar-elisp has support for automatically running inside a Cask 94 | # environment if there is a Cask file in the working directory. Might 95 | # as well install Cask so it's easy to test. 96 | git clone https://github.com/cask/cask.git /usr/local/cask 97 | ln -s /usr/local/cask/bin/cask /usr/local/bin/cask 98 | cask upgrade-cask 99 | 100 | rm /tmp/docker-install.sh 101 | -------------------------------------------------------------------------------- /languages/python311/pry_python311.c: -------------------------------------------------------------------------------- 1 | #include "pry_python311.h" 2 | 3 | int pry_eval_file(FILE *f, const char *file, int argn, const char *argv) 4 | { 5 | wchar_t *xargv[argn + 1]; 6 | const char *ptr = argv; 7 | for (int i = 0; i < argn; ++i) 8 | { 9 | xargv[i] = Py_DecodeLocale(ptr, NULL); 10 | ptr += strlen(ptr) + 1; 11 | } 12 | xargv[argn] = NULL; 13 | PySys_SetArgvEx(argn, xargv, 1); 14 | 15 | return PyRun_AnyFile(f, file); 16 | } 17 | 18 | const char *pry_eval(const char *code, int start) 19 | { 20 | 21 | PyObject *m, *d, *s, *t, *v; 22 | PyObject *c; 23 | m = PyImport_AddModule("__main__"); 24 | 25 | if (m == NULL) 26 | return NULL; 27 | 28 | d = PyModule_GetDict(m); 29 | c = Py_CompileString(code, "(eval)", start); 30 | if (c == NULL) 31 | { 32 | PyErr_Print(); 33 | return NULL; 34 | } 35 | v = PyEval_EvalCode(c, d, d); 36 | if (v == NULL) 37 | { 38 | PyErr_Print(); 39 | return NULL; 40 | } 41 | s = PyObject_Str(v); 42 | if (s == NULL) 43 | { 44 | PyErr_Print(); 45 | return NULL; 46 | } 47 | 48 | t = PyUnicode_AsUTF8String(s); 49 | if (t == NULL) 50 | { 51 | PyErr_Print(); 52 | return NULL; 53 | } 54 | 55 | 56 | char *str = PyBytes_AsString(t); 57 | Py_DECREF(v); 58 | Py_DECREF(s); 59 | Py_DECREF(t); 60 | return str; 61 | } 62 | 63 | void pry_set_prompts(const char *ps1, const char *ps2) 64 | { 65 | PyObject *po1 = PyUnicode_FromString(ps1); 66 | PyObject *po2 = PyUnicode_FromString(ps2); 67 | PySys_SetObject("ps1", po1); 68 | PySys_SetObject("ps2", po2); 69 | Py_DECREF(po1); 70 | Py_DECREF(po2); 71 | } 72 | 73 | //From python3 sourcecode 74 | int 75 | pymain_run_interactive_hook(int *exitcode) 76 | { 77 | PyObject *sys, *hook, *result; 78 | sys = PyImport_ImportModule("sys"); 79 | if (sys == NULL) { 80 | goto error; 81 | } 82 | 83 | hook = PyObject_GetAttrString(sys, "__interactivehook__"); 84 | Py_DECREF(sys); 85 | if (hook == NULL) { 86 | PyErr_Clear(); 87 | return 0; 88 | } 89 | 90 | if (PySys_Audit("cpython.run_interactivehook", "O", hook) < 0) { 91 | goto error; 92 | } 93 | 94 | result = PyObject_CallNoArgs(hook); 95 | Py_DECREF(hook); 96 | if (result == NULL) { 97 | goto error; 98 | } 99 | Py_DECREF(result); 100 | 101 | return 0; 102 | 103 | error: 104 | PySys_WriteStderr("Failed calling sys.__interactivehook__\n"); 105 | return pymain_err_print(exitcode); 106 | } 107 | 108 | int 109 | pymain_err_print(int *exitcode_p) 110 | { 111 | int exitcode; 112 | if (_Py_HandleSystemExit(&exitcode)) { 113 | *exitcode_p = exitcode; 114 | return 1; 115 | } 116 | 117 | PyErr_Print(); 118 | return 0; 119 | } 120 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/fetch-blob/from.js: -------------------------------------------------------------------------------- 1 | import { statSync, createReadStream, promises as fs } from 'node:fs' 2 | import { basename } from 'node:path' 3 | import DOMException from 'node-domexception' 4 | 5 | import File from './file.js' 6 | import Blob from './index.js' 7 | 8 | const { stat } = fs 9 | 10 | /** 11 | * @param {string} path filepath on the disk 12 | * @param {string} [type] mimetype to use 13 | */ 14 | const blobFromSync = (path, type) => fromBlob(statSync(path), path, type) 15 | 16 | /** 17 | * @param {string} path filepath on the disk 18 | * @param {string} [type] mimetype to use 19 | * @returns {Promise} 20 | */ 21 | const blobFrom = (path, type) => stat(path).then(stat => fromBlob(stat, path, type)) 22 | 23 | /** 24 | * @param {string} path filepath on the disk 25 | * @param {string} [type] mimetype to use 26 | * @returns {Promise} 27 | */ 28 | const fileFrom = (path, type) => stat(path).then(stat => fromFile(stat, path, type)) 29 | 30 | /** 31 | * @param {string} path filepath on the disk 32 | * @param {string} [type] mimetype to use 33 | */ 34 | const fileFromSync = (path, type) => fromFile(statSync(path), path, type) 35 | 36 | // @ts-ignore 37 | const fromBlob = (stat, path, type = '') => new Blob([new BlobDataItem({ 38 | path, 39 | size: stat.size, 40 | lastModified: stat.mtimeMs, 41 | start: 0 42 | })], { type }) 43 | 44 | // @ts-ignore 45 | const fromFile = (stat, path, type = '') => new File([new BlobDataItem({ 46 | path, 47 | size: stat.size, 48 | lastModified: stat.mtimeMs, 49 | start: 0 50 | })], basename(path), { type, lastModified: stat.mtimeMs }) 51 | 52 | /** 53 | * This is a blob backed up by a file on the disk 54 | * with minium requirement. Its wrapped around a Blob as a blobPart 55 | * so you have no direct access to this. 56 | * 57 | * @private 58 | */ 59 | class BlobDataItem { 60 | #path 61 | #start 62 | 63 | constructor (options) { 64 | this.#path = options.path 65 | this.#start = options.start 66 | this.size = options.size 67 | this.lastModified = options.lastModified 68 | } 69 | 70 | /** 71 | * Slicing arguments is first validated and formatted 72 | * to not be out of range by Blob.prototype.slice 73 | */ 74 | slice (start, end) { 75 | return new BlobDataItem({ 76 | path: this.#path, 77 | lastModified: this.lastModified, 78 | size: end - start, 79 | start: this.#start + start 80 | }) 81 | } 82 | 83 | async * stream () { 84 | const { mtimeMs } = await stat(this.#path) 85 | if (mtimeMs > this.lastModified) { 86 | throw new DOMException('The requested file could not be read, typically due to permission problems that have occurred after a reference to a file was acquired.', 'NotReadableError') 87 | } 88 | yield * createReadStream(this.#path, { 89 | start: this.#start, 90 | end: this.#start + this.size - 1 91 | }) 92 | } 93 | 94 | get [Symbol.toStringTag] () { 95 | return 'Blob' 96 | } 97 | } 98 | 99 | export default blobFromSync 100 | export { File, Blob, blobFrom, blobFromSync, fileFrom, fileFromSync } 101 | -------------------------------------------------------------------------------- /languages/python3/pry_python3.c: -------------------------------------------------------------------------------- 1 | #include "pry_python3.h" 2 | 3 | int pry_eval_file(FILE *f, const char *file, int argn, const char *argv) 4 | { 5 | wchar_t *xargv[argn + 1]; 6 | const char *ptr = argv; 7 | for (int i = 0; i < argn; ++i) 8 | { 9 | xargv[i] = Py_DecodeLocale(ptr, NULL); 10 | ptr += strlen(ptr) + 1; 11 | } 12 | xargv[argn] = NULL; 13 | PySys_SetArgvEx(argn, xargv, 1); 14 | 15 | #if defined(PYTHON_3_10) || defined(PYTHON_3_11) 16 | char absolutePathBuffer [PATH_MAX+1]; 17 | file = realpath(file, absolutePathBuffer); 18 | #endif 19 | 20 | return PyRun_AnyFile(f, file); 21 | } 22 | 23 | const char *pry_eval(const char *code, int start) 24 | { 25 | 26 | PyObject *m, *d, *s, *t, *v; 27 | PyObject *c; 28 | m = PyImport_AddModule("__main__"); 29 | 30 | if (m == NULL) 31 | return NULL; 32 | 33 | d = PyModule_GetDict(m); 34 | c = Py_CompileString(code, "(eval)", start); 35 | if (c == NULL) 36 | { 37 | PyErr_Print(); 38 | return NULL; 39 | } 40 | v = PyEval_EvalCode(c, d, d); 41 | if (v == NULL) 42 | { 43 | PyErr_Print(); 44 | return NULL; 45 | } 46 | s = PyObject_Str(v); 47 | if (s == NULL) 48 | { 49 | PyErr_Print(); 50 | return NULL; 51 | } 52 | 53 | t = PyUnicode_AsUTF8String(s); 54 | if (t == NULL) 55 | { 56 | PyErr_Print(); 57 | return NULL; 58 | } 59 | 60 | 61 | char *str = PyBytes_AsString(t); 62 | Py_DECREF(v); 63 | Py_DECREF(s); 64 | Py_DECREF(t); 65 | return str; 66 | } 67 | 68 | void pry_set_prompts(const char *ps1, const char *ps2) 69 | { 70 | PyObject *po1 = PyUnicode_FromString(ps1); 71 | PyObject *po2 = PyUnicode_FromString(ps2); 72 | PySys_SetObject("ps1", po1); 73 | PySys_SetObject("ps2", po2); 74 | Py_DECREF(po1); 75 | Py_DECREF(po2); 76 | } 77 | 78 | //From python3 sourcecode 79 | int 80 | pymain_run_interactive_hook(int *exitcode) 81 | { 82 | PyObject *sys, *hook, *result; 83 | sys = PyImport_ImportModule("sys"); 84 | if (sys == NULL) { 85 | goto error; 86 | } 87 | 88 | hook = PyObject_GetAttrString(sys, "__interactivehook__"); 89 | Py_DECREF(sys); 90 | if (hook == NULL) { 91 | PyErr_Clear(); 92 | return 0; 93 | } 94 | 95 | if (PySys_Audit("cpython.run_interactivehook", "O", hook) < 0) { 96 | goto error; 97 | } 98 | 99 | #ifdef PYTHON_3_11 100 | result = PyObject_CallNoArgs(hook); 101 | #else 102 | result = _PyObject_CallNoArg(hook); 103 | #endif 104 | 105 | 106 | Py_DECREF(hook); 107 | if (result == NULL) { 108 | goto error; 109 | } 110 | Py_DECREF(result); 111 | 112 | return 0; 113 | 114 | error: 115 | PySys_WriteStderr("Failed calling sys.__interactivehook__\n"); 116 | return pymain_err_print(exitcode); 117 | } 118 | 119 | int 120 | pymain_err_print(int *exitcode_p) 121 | { 122 | int exitcode; 123 | if (_Py_HandleSystemExit(&exitcode)) { 124 | *exitcode_p = exitcode; 125 | return 1; 126 | } 127 | 128 | PyErr_Print(); 129 | return 0; 130 | } 131 | -------------------------------------------------------------------------------- /prybar_assets/elisp/repl.el: -------------------------------------------------------------------------------- 1 | (require 'ielm) 2 | 3 | (defun prybar-config (key) 4 | "Read a Prybar configuration variable from the environment. 5 | KEY is a symbol, like `quiet'. Return the value of the 6 | environment variable \"PRYBAR_QUIET\" (or analogously for other 7 | KEYs). If the environment variable is unset, or its value is the 8 | empty string, then return nil instead." 9 | (let* ((name (format "PRYBAR_%s" (upcase (symbol-name key)))) 10 | (val (getenv name))) 11 | (and val (/= (length val) 0) val))) 12 | 13 | (defmacro with-prybar-config (vars &rest body) 14 | "Read Prybar configuration VARS and bind lexically while running BODY. 15 | VARS is a list of symbols as could be passed to `prybar-config'. 16 | Each symbol is prepended with `prybar-' and bound lexically to 17 | the return value of `prybar-config'. 18 | 19 | VARS may also contain lists of the form (SYMBOL DEFAULT), not 20 | just symbols. In this case, the behavior is the same except that 21 | DEFAULT is used as the binding for the symbol if `prybar-config' 22 | returns nil. 23 | 24 | For example, the following usage: 25 | 26 | (with-prybar-config (eval (ps1 \"-->\")) 27 | ...) 28 | 29 | expands to: 30 | 31 | (let ((prybar-eval (prybar-config 'eval)) 32 | (prybar-ps1 (or (prybar-config 'ps1) \"-->\"))) 33 | ...)" 34 | (declare (indent 1)) 35 | `(let (,@(mapcar 36 | (lambda (var) 37 | (if (listp var) 38 | `(,(intern (format "prybar-%S" (nth 0 var))) 39 | (or (prybar-config ',(nth 0 var)) 40 | ,(nth 1 var))) 41 | `(,(intern (format "prybar-%S" var)) 42 | (prybar-config ',var)))) 43 | vars)) 44 | ,@body)) 45 | 46 | (defun prybar-repl () 47 | "Start a Prybar REPL at the top level. This mutates global state. 48 | The REPL uses `ielm', which see. After version information is 49 | printed and forms for immediate evaluation or execution are 50 | handled, display the IELM buffer and return." 51 | ;; For some reason in the repl.it environment the text all gets 52 | ;; underlined sometimes. Redisplaying fixes this. 53 | (redisplay) 54 | (menu-bar-mode -1) 55 | ;; Make it so you can `load' or `require' files from the project 56 | ;; directory, and any lisp/ subdirectory (often seen in larger 57 | ;; projects). 58 | (add-to-list 'load-path default-directory) 59 | (add-to-list 'load-path (expand-file-name "lisp" default-directory)) 60 | ;; IELM only supports PS1, not PS2. 61 | (with-prybar-config 62 | (eval exec (ps1 "--> ") quiet file) 63 | (setq ielm-prompt prybar-ps1) 64 | (with-current-buffer (get-buffer-create "*ielm*") 65 | (if prybar-quiet 66 | (setq ielm-header "") 67 | (insert (format "GNU Emacs %s\n" emacs-version))) 68 | (when prybar-file 69 | (condition-case e 70 | (load (expand-file-name prybar-file) nil 'nomessage) 71 | (error 72 | (insert (format "%s\n" (error-message-string e)))))) 73 | (inferior-emacs-lisp-mode) 74 | (when prybar-exec 75 | (insert prybar-exec) 76 | (ielm-send-input 'for-effect)) 77 | (when prybar-eval 78 | (insert prybar-eval) 79 | (ielm-send-input))) 80 | (pop-to-buffer-same-window "*ielm*"))) 81 | -------------------------------------------------------------------------------- /languages/sqlite/patch/patch.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* a shared library designed to be LD_PRELOADed into SQLite CLI 7 | 8 | If PRYBAR_QUIET is set in the environment, then this suppresses the "Loading 9 | resources" message due to the CLI's `-init` flag, and also hides the version 10 | header and help message. 11 | 12 | What happens in SQLite CLI: 13 | 14 | 1. fprintf to stderr containing the "Loading resources..." message 15 | 2. printf containing version and help string 16 | 17 | We need to suppress the output if the PRYBAR_QUIET env var is set. So, we wait 18 | for the CLI to make calls to libc print functions and intercept them. If they're 19 | what we expect, then we don't print anything and then advance the state as 20 | necessary. 21 | 22 | Check out the SQLite CLI code to see what it does: 23 | https://www.sqlite.org/src/artifact/4e1bcf8c70b8fb97 24 | 25 | */ 26 | 27 | // this macro lets us roll up the varargs once instead of in four separate 28 | // places below. 29 | #define VAR_PRINT(out, format) \ 30 | { \ 31 | va_list arg; \ 32 | va_start(arg, format); \ 33 | int rc = vfprintf(out, format, arg); \ 34 | va_end(arg); \ 35 | return rc; \ 36 | } 37 | 38 | /* three states: 39 | - no output suppressed 40 | - suppressed "Loading resources..." message on stderr 41 | - suppressed version and help string on stdout 42 | */ 43 | static enum { 44 | INITIAL, 45 | LOADING_SUPPRESSED, 46 | VERSION_SUPPRESSED 47 | } current_state = INITIAL; 48 | 49 | int __fprintf_chk(FILE *out, int flag, const char *format, ...) { 50 | // don't do anything; pass through print 51 | if (current_state != INITIAL) { 52 | VAR_PRINT(out, format); 53 | } 54 | 55 | // check if this is the first time we're seeing the output that we're aiming 56 | // to suppress 57 | const char *expected = "-- Loading resources from %s\n"; 58 | if (getenv("PRYBAR_QUIET") && out == stderr && 59 | strcmp(format, expected) == 0) { 60 | // advance to next state and suppress output 61 | current_state = LOADING_SUPPRESSED; 62 | return 0; 63 | } 64 | 65 | // this isn't the output we were looking for... 66 | VAR_PRINT(out, format); 67 | } 68 | 69 | int __printf_chk(int flag, const char *format, ...) { 70 | // don't do anything; pass through print 71 | if (current_state != LOADING_SUPPRESSED) { 72 | VAR_PRINT(stdout, format); 73 | } 74 | 75 | // check if this is the first time we're seeing the output that we're aiming 76 | // to suppress 77 | const char *expected = "SQLite version %s %.19s\nEnter \".help\" for usage " 78 | "hints.\n"; 79 | if (getenv("PRYBAR_QUIET") && strcmp(format, expected) == 0) { 80 | // advance to next state and suppress output 81 | current_state = VERSION_SUPPRESSED; 82 | return 0; 83 | } 84 | 85 | // this isn't the output we were looking for... 86 | VAR_PRINT(stdout, format); 87 | } 88 | -------------------------------------------------------------------------------- /languages/python3/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // USING_CGO 4 | 5 | /* 6 | #include "pry_python3.h" 7 | */ 8 | import "C" 9 | 10 | import ( 11 | "fmt" 12 | "os" 13 | "path" 14 | "strings" 15 | "unsafe" 16 | ) 17 | 18 | var programName *C.wchar_t 19 | 20 | func Py_SetProgramName(name string) error { 21 | cname := C.CString(name) 22 | defer C.free(unsafe.Pointer(cname)) 23 | 24 | newProgramName := C.Py_DecodeLocale(cname, nil) 25 | if newProgramName == nil { 26 | return fmt.Errorf("fail to call Py_DecodeLocale on '%s'", name) 27 | } 28 | C.Py_SetProgramName(newProgramName) 29 | 30 | //no operation is performed if nil 31 | C.PyMem_RawFree(unsafe.Pointer(programName)) 32 | programName = newProgramName 33 | 34 | return nil 35 | } 36 | 37 | func init() { 38 | name := "python" 39 | virtualEnv, virtualEnvSet := os.LookupEnv("VIRTUAL_ENV") 40 | if virtualEnvSet { 41 | name = path.Join(virtualEnv, "bin", "python") 42 | } 43 | err := Py_SetProgramName(name) 44 | if err != nil { 45 | panic(fmt.Sprintf("cannot set prybar-python3 program name to '%s': %s", name, err)) 46 | } 47 | } 48 | 49 | type Python struct{} 50 | 51 | func (p Python) Open() { 52 | C.Py_Initialize() 53 | p.loadModule("readline") 54 | p.Eval("import signal") 55 | p.Eval("signal.signal(signal.SIGINT, signal.default_int_handler)") 56 | p.Eval("del signal") 57 | } 58 | 59 | func (p Python) Version() string { 60 | return "Python " + C.GoString(C.Py_GetVersion()) + " on " + C.GoString(C.Py_GetPlatform()) 61 | } 62 | 63 | func (p Python) Eval(code string) { 64 | ccode := C.CString(code) 65 | defer C.free(unsafe.Pointer(ccode)) 66 | C.GoString(C.pry_eval(ccode, C.Py_file_input)) 67 | } 68 | 69 | func (p Python) EvalExpression(code string) string { 70 | ccode := C.CString(code) 71 | defer C.free(unsafe.Pointer(ccode)) 72 | return C.GoString(C.pry_eval(ccode, C.Py_eval_input)) 73 | } 74 | 75 | func (p Python) EvalFile(file string, args []string) int { 76 | handle := C.stdin 77 | cfile := C.CString(file) 78 | defer C.free(unsafe.Pointer(cfile)) 79 | 80 | if file != "-" { 81 | cmode := C.CString("r") 82 | 83 | defer C.free(unsafe.Pointer(cmode)) 84 | handle = C.fopen(cfile, cmode) 85 | defer C.fclose(handle) 86 | } 87 | 88 | argv := C.CString(file + "\x00" + strings.Join(args, "\x00")) 89 | defer C.free(unsafe.Pointer(argv)) 90 | 91 | status := (C.pry_eval_file(handle, cfile, C.int(len(args)+1), argv)) 92 | 93 | // if status is non-zero an error occured. 94 | if status != 0 { 95 | return 1 96 | } 97 | 98 | return 0 99 | } 100 | 101 | func (p Python) REPLLikeEval(code string) { 102 | ccode := C.CString(code) 103 | defer C.free(unsafe.Pointer(ccode)) 104 | C.pry_eval(ccode, C.Py_single_input) 105 | } 106 | 107 | func (p Python) loadModule(mod string) { 108 | cmode := C.CString(mod) 109 | defer C.free(unsafe.Pointer(cmode)) 110 | C.PyImport_ImportModule(cmode) 111 | } 112 | 113 | func (p Python) REPL() { 114 | var exitCode C.int 115 | if C.pymain_run_interactive_hook(&exitCode) != 0 { 116 | os.Exit(int(exitCode)) 117 | } 118 | 119 | fn := C.CString("") 120 | defer C.free(unsafe.Pointer(fn)) 121 | C.PyRun_InteractiveLoopFlags(C.stdin, fn, nil) 122 | } 123 | 124 | func (p Python) SetPrompts(ps1, ps2 string) { 125 | cps1 := C.CString(ps1) 126 | defer C.free(unsafe.Pointer(cps1)) 127 | cps2 := C.CString(ps2) 128 | defer C.free(unsafe.Pointer(cps2)) 129 | 130 | C.pry_set_prompts(cps1, cps2) 131 | } 132 | 133 | func (p Python) Close() { 134 | C.Py_Finalize() 135 | } 136 | 137 | var Instance = Python{} 138 | -------------------------------------------------------------------------------- /languages/python311/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // USING_CGO 4 | 5 | /* 6 | #cgo pkg-config: python-3.11-embed 7 | #include "pry_python311.h" 8 | */ 9 | import "C" 10 | 11 | import ( 12 | "fmt" 13 | "os" 14 | "path" 15 | "strings" 16 | "unsafe" 17 | ) 18 | 19 | var programName *C.wchar_t 20 | 21 | func Py_SetProgramName(name string) error { 22 | cname := C.CString(name) 23 | defer C.free(unsafe.Pointer(cname)) 24 | 25 | newProgramName := C.Py_DecodeLocale(cname, nil) 26 | if newProgramName == nil { 27 | return fmt.Errorf("fail to call Py_DecodeLocale on '%s'", name) 28 | } 29 | C.Py_SetProgramName(newProgramName) 30 | 31 | //no operation is performed if nil 32 | C.PyMem_RawFree(unsafe.Pointer(programName)) 33 | programName = newProgramName 34 | 35 | return nil 36 | } 37 | 38 | func init() { 39 | name := "python" 40 | virtualEnv, virtualEnvSet := os.LookupEnv("VIRTUAL_ENV") 41 | if virtualEnvSet { 42 | name = path.Join(virtualEnv, "bin", "python") 43 | } 44 | err := Py_SetProgramName(name) 45 | if err != nil { 46 | panic(fmt.Sprintf("cannot set prybar-python3 program name to '%s': %s", name, err)) 47 | } 48 | } 49 | 50 | type Python struct{} 51 | 52 | func (p Python) Open() { 53 | C.Py_Initialize() 54 | p.loadModule("readline") 55 | p.Eval("import signal") 56 | p.Eval("signal.signal(signal.SIGINT, signal.default_int_handler)") 57 | p.Eval("del signal") 58 | } 59 | 60 | func (p Python) Version() string { 61 | return "Python " + C.GoString(C.Py_GetVersion()) + " on " + C.GoString(C.Py_GetPlatform()) 62 | } 63 | 64 | func (p Python) Eval(code string) { 65 | ccode := C.CString(code) 66 | defer C.free(unsafe.Pointer(ccode)) 67 | C.GoString(C.pry_eval(ccode, C.Py_file_input)) 68 | } 69 | 70 | func (p Python) EvalExpression(code string) string { 71 | ccode := C.CString(code) 72 | defer C.free(unsafe.Pointer(ccode)) 73 | return C.GoString(C.pry_eval(ccode, C.Py_eval_input)) 74 | } 75 | 76 | func (p Python) EvalFile(file string, args []string) int { 77 | handle := C.stdin 78 | cfile := C.CString(file) 79 | defer C.free(unsafe.Pointer(cfile)) 80 | 81 | if file != "-" { 82 | cmode := C.CString("r") 83 | 84 | defer C.free(unsafe.Pointer(cmode)) 85 | handle = C.fopen(cfile, cmode) 86 | defer C.fclose(handle) 87 | } 88 | 89 | argv := C.CString(file + "\x00" + strings.Join(args, "\x00")) 90 | defer C.free(unsafe.Pointer(argv)) 91 | 92 | status := (C.pry_eval_file(handle, cfile, C.int(len(args)+1), argv)) 93 | 94 | // if status is non-zero an error occured. 95 | if status != 0 { 96 | return 1 97 | } 98 | 99 | return 0 100 | } 101 | 102 | func (p Python) REPLLikeEval(code string) { 103 | ccode := C.CString(code) 104 | defer C.free(unsafe.Pointer(ccode)) 105 | C.pry_eval(ccode, C.Py_single_input) 106 | } 107 | 108 | func (p Python) loadModule(mod string) { 109 | cmode := C.CString(mod) 110 | defer C.free(unsafe.Pointer(cmode)) 111 | C.PyImport_ImportModule(cmode) 112 | } 113 | 114 | func (p Python) REPL() { 115 | var exitCode C.int 116 | if C.pymain_run_interactive_hook(&exitCode) != 0 { 117 | os.Exit(int(exitCode)) 118 | } 119 | 120 | fn := C.CString("") 121 | defer C.free(unsafe.Pointer(fn)) 122 | C.PyRun_InteractiveLoopFlags(C.stdin, fn, nil) 123 | } 124 | 125 | func (p Python) SetPrompts(ps1, ps2 string) { 126 | cps1 := C.CString(ps1) 127 | defer C.free(unsafe.Pointer(cps1)) 128 | cps2 := C.CString(ps2) 129 | defer C.free(unsafe.Pointer(cps2)) 130 | 131 | C.pry_set_prompts(cps1, cps2) 132 | } 133 | 134 | func (p Python) Close() { 135 | C.Py_Finalize() 136 | } 137 | 138 | var Instance = Python{} 139 | -------------------------------------------------------------------------------- /languages/julia/pry.h: -------------------------------------------------------------------------------- 1 | // This file is a part of Julia. License is MIT: https://julialang.org/license 2 | 3 | /* 4 | repl.c 5 | system startup, main(), and console interaction 6 | */ 7 | 8 | #define JULIA_ENABLE_THREADING 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | JULIA_DEFINE_FAST_TLS() 29 | 30 | void fancy_repl(void) { 31 | assert(jl_base_module && "oh no, we have no repl?"); 32 | 33 | jl_function_t *start_client = 34 | (jl_function_t *)jl_get_global(jl_base_module, jl_symbol("_start")); 35 | 36 | JL_TRY { 37 | size_t last_age = jl_get_ptls_states()->world_age; 38 | jl_get_ptls_states()->world_age = jl_get_world_counter(); 39 | 40 | jl_apply(&start_client, 1); 41 | 42 | jl_get_ptls_states()->world_age = last_age; 43 | } 44 | JL_CATCH { jl_no_exc_handler(jl_current_exception()); } 45 | } 46 | 47 | static int exec_program(const char *program) { 48 | JL_TRY { jl_load(jl_main_module, program); } 49 | JL_CATCH { 50 | jl_value_t *errs = jl_stderr_obj(); 51 | volatile int shown_err = 0; 52 | jl_printf(JL_STDERR, "error during bootstrap:\n"); 53 | JL_TRY { 54 | if (errs) { 55 | jl_value_t *showf = jl_get_function(jl_base_module, "show"); 56 | if (showf != NULL) { 57 | jl_call2(showf, errs, jl_current_exception()); 58 | jl_printf(JL_STDERR, "\n"); 59 | shown_err = 1; 60 | } 61 | } 62 | } 63 | JL_CATCH {} 64 | if (!shown_err) { 65 | jl_static_show(JL_STDERR, jl_current_exception()); 66 | jl_printf(JL_STDERR, "\n"); 67 | } 68 | jlbacktrace(); 69 | jl_printf(JL_STDERR, "\n"); 70 | return 1; 71 | } 72 | return 0; 73 | } 74 | 75 | const char *get_banner(void) { 76 | jl_value_t *ret = jl_eval_string("io = IOBuffer(); Base.banner(IOContext(io, " 77 | ":color => true)); String(take!(io))"); 78 | 79 | assert(jl_typeis(ret, jl_string_type) && "banner should be a string"); 80 | 81 | return jl_string_ptr(ret); 82 | } 83 | 84 | void setup() { 85 | jl_init(); 86 | libsupport_init(); 87 | 88 | jl_options.banner = 0; 89 | jl_options.color = 1; 90 | 91 | jl_eval_string("import REPL"); 92 | jl_set_global(jl_base_module, jl_symbol("replit_prompt"), 93 | jl_cstr_to_string("julia> ")); 94 | jl_eval_string( 95 | "atreplinit(function (r)" 96 | "pparts = match(r\"(\\e\\[.+m)?(.*)\", Base.replit_prompt);" 97 | "r.prompt_color = pparts[1] == nothing ? \"\" : String(pparts[1]);" 98 | "r.interface = REPL.setup_interface(r, true, r.options.extra_keymap); " 99 | "r.interface.modes[1].prompt =" 100 | " pparts[2] == nothing ? \"\" : String(pparts[2]);" 101 | "r.interface.modes[2].prompt = \"shell> \";" 102 | "r.interface.modes[3].prompt = \"help?> \";" 103 | "end)"); 104 | } 105 | 106 | void cleanup() { jl_atexit_hook(0); } 107 | 108 | void eval(const char *str) { jl_eval_string(str); } 109 | 110 | int eval_file(const char *path) { return exec_program(path); } 111 | 112 | void run_repl() { fancy_repl(); } 113 | 114 | void set_prompt(const char *prompt) { 115 | jl_set_global(jl_base_module, jl_symbol("replit_prompt"), 116 | jl_cstr_to_string(prompt)); 117 | } 118 | -------------------------------------------------------------------------------- /languages/sqlite/main.go: -------------------------------------------------------------------------------- 1 | // Take a Prybar config and exec the SQLite CLI with it. 2 | // 3 | // Note: the prompt config (ps1 and ps2) must be SQL strings, i.e. single quotation 4 | // marks must be properly escaped. 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | "io/ioutil" 10 | "os" 11 | "os/exec" 12 | "path/filepath" 13 | "syscall" 14 | 15 | "github.com/replit/prybar/utils" 16 | ) 17 | 18 | var Instance = &SQLite{} 19 | 20 | type SQLite struct{} 21 | 22 | // writeConfig writes the provided slice of strings out to temporary file and 23 | // returns its pathname. 24 | func writeConfig(lines []string) string { 25 | f, err := ioutil.TempFile("", "sqlite-config") 26 | if err != nil { 27 | panic(err) 28 | } 29 | defer f.Close() 30 | 31 | for _, line := range lines { 32 | f.WriteString(line) 33 | } 34 | 35 | return f.Name() 36 | } 37 | 38 | // preloadQuietLib adds our LD_PRELOAD lib to environment and enables it 39 | func preloadQuietLib(env []string) []string { 40 | execPath, err := os.Executable() 41 | if err != nil { 42 | panic(err) 43 | } 44 | runDir := filepath.Dir(execPath) 45 | 46 | prybarAssetDir := os.Getenv("PRYBAR_ASSETS_DIR") 47 | if prybarAssetDir == "" { 48 | prybarAssetDir = filepath.Join(runDir, "prybar_assets") 49 | } 50 | libPath := filepath.Join(prybarAssetDir, "sqlite", "patch.so") 51 | return append(env, []string{"LD_PRELOAD=" + libPath, "PRYBAR_QUIET=1"}...) 52 | } 53 | 54 | func eval(sqlite string, config *utils.Config) { 55 | args := []string{"sqlite3"} 56 | env := os.Environ() 57 | 58 | if len(config.Code) > 0 { 59 | // We have to execute provided code without showing output. 60 | // So, let's have sqlite run a command that will output to /dev/null. 61 | confLines := []string{".output /dev/null\n"} 62 | args = append(args, []string{"-init", writeConfig(confLines), ":memory:", config.Code}...) 63 | 64 | // add LD_PRELOAD lib to environment to suppress initialization output 65 | env = preloadQuietLib(env) 66 | } else { 67 | // we can just run the code without a config file since we want its output 68 | args = append(args, []string{":memory:", config.Exp}...) 69 | } 70 | 71 | err := syscall.Exec(sqlite, args, env) 72 | if err != nil { 73 | panic(err) 74 | } 75 | } 76 | 77 | func interactive(sqlite string, config *utils.Config) { 78 | // main and continuation prompts 79 | confLines := []string{ 80 | fmt.Sprintf(".prompt '%s' '%s'\n", config.Ps1, config.Ps2), 81 | } 82 | 83 | // execute file, if specified 84 | if len(config.Args) == 1 { 85 | fileToRun := config.Args[0] 86 | confLines = append(confLines, fmt.Sprintf(".read %s\n", fileToRun)) 87 | } 88 | 89 | args := []string{"sqlite3", "-init", writeConfig(confLines)} 90 | 91 | env := os.Environ() 92 | if config.Quiet { 93 | env = preloadQuietLib(env) 94 | } 95 | 96 | err := syscall.Exec(sqlite, args, env) 97 | if err != nil { 98 | panic(err) 99 | } 100 | } 101 | 102 | func Execute(config *utils.Config) { 103 | // sanity check 104 | if len(config.Args) > 1 { 105 | fmt.Fprint(os.Stderr, "too many arguments\n") 106 | os.Exit(1) 107 | } 108 | 109 | if config.OurInteractive { 110 | fmt.Fprint(os.Stderr, "not supported\n") 111 | os.Exit(1) 112 | } 113 | 114 | // make sure we have the sqlite CLI 115 | sqlite, err := exec.LookPath("sqlite3") 116 | if err != nil { 117 | panic(err) 118 | } 119 | 120 | if len(config.Code) > 0 || len(config.Exp) > 0 { 121 | // we're executing provided code 122 | eval(sqlite, config) 123 | } else { 124 | // running sqlite CLI interactively 125 | interactive(sqlite, config) 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "A universal interpreter front-end"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; 6 | flake-utils.url = "github:numtide/flake-utils"; 7 | }; 8 | 9 | outputs = { self, nixpkgs, flake-utils }: 10 | { 11 | overlays.default = final: prev: { 12 | prybar = prev.lib.recurseIntoAttrs { 13 | inherit (self.packages.${prev.system}) 14 | prybar-elisp prybar-julia prybar-lua prybar-nodejs 15 | prybar-python2 prybar-python3 prybar-python38 prybar-python310 prybar-python311 16 | prybar-scala prybar-sqlite prybar-tcl; 17 | }; 18 | }; 19 | } // 20 | flake-utils.lib.eachDefaultSystem (system: 21 | let 22 | pkgs = nixpkgs.legacyPackages.${system}; 23 | 24 | rev = if self ? rev then 25 | "0.0.0-${builtins.substring 0 7 self.rev}" 26 | else 27 | "0.0.0-dirty"; 28 | 29 | buildPrybar = attrs: 30 | pkgs.callPackage (import ./build-prybar.nix attrs) { inherit rev; }; 31 | 32 | julia = import ./languages/julia/julia.nix { inherit pkgs; }; 33 | 34 | python38Full = pkgs.python3.override { 35 | self = python38Full; 36 | sourceVersion = { 37 | major = "3"; 38 | minor = "8"; 39 | patch = "18"; 40 | suffix = ""; 41 | }; 42 | hash = "sha256-P/txzTSaMmunsvrcfn34a6V33ZxJF+UqhAGtvadAXj8="; 43 | pythonAttr = "python38Full"; 44 | bluezSupport = true; 45 | x11Support = true; 46 | }; 47 | 48 | python310Full = pkgs.python310.override { 49 | self = python310Full; 50 | pythonAttr = "python310Full"; 51 | bluezSupport = true; 52 | x11Support = true; 53 | }; 54 | 55 | python311Full = pkgs.python311.override { 56 | self = python311Full; 57 | pythonAttr = "python311Full"; 58 | bluezSupport = true; 59 | x11Support = true; 60 | }; 61 | 62 | in { 63 | packages = rec { 64 | 65 | prybar-nodejs = buildPrybar { 66 | language = "nodejs"; 67 | binaries = [ pkgs.nodejs ]; 68 | }; 69 | 70 | prybar-python38 = buildPrybar { 71 | language = "python3"; 72 | target = "python3"; 73 | cgoPkgs = "python-3.8-embed"; 74 | cgoExtraCflags = "-DPYTHON_3_8"; 75 | buildInputs = [ pkgs.libxcrypt python38Full ]; 76 | }; 77 | 78 | prybar-python3 = prybar-python38; 79 | 80 | prybar-python310 = buildPrybar { 81 | language = "python3"; 82 | target = "python310"; 83 | cgoPkgs = "python-3.10-embed"; 84 | cgoExtraCflags = "-DPYTHON_3_10"; 85 | buildInputs = [ pkgs.libxcrypt python310Full ]; 86 | }; 87 | 88 | prybar-python311 = buildPrybar { 89 | language = "python3"; 90 | target = "python311"; 91 | cgoPkgs = "python-3.11-embed"; 92 | cgoExtraCflags = "-DPYTHON_3_11"; 93 | buildInputs = [ pkgs.libxcrypt python311Full ]; 94 | }; 95 | 96 | prybar-lua = buildPrybar { 97 | language = "lua"; 98 | buildInputs = [ pkgs.lua5_1 pkgs.readline ]; 99 | }; 100 | 101 | prybar-elisp = buildPrybar { language = "elisp"; }; 102 | 103 | prybar-scala = buildPrybar { language = "scala"; }; 104 | 105 | prybar-sqlite = buildPrybar { 106 | language = "sqlite"; 107 | binaries = [ pkgs.sqlite ]; 108 | }; 109 | 110 | prybar-tcl = buildPrybar { 111 | language = "tcl"; 112 | buildInputs = [ pkgs.tcl ]; 113 | }; 114 | } 115 | # These packages have issues on macOS 116 | // nixpkgs.lib.optionalAttrs (!pkgs.stdenv.isDarwin) { 117 | prybar-julia = buildPrybar { 118 | language = "julia"; 119 | buildInputs = [ julia ]; 120 | setFlags = true; 121 | binaries = [ pkgs.zlib ]; 122 | }; 123 | 124 | }; 125 | 126 | 127 | devShells.default = pkgs.mkShell { 128 | nativeBuildInputs = [ 129 | pkgs.pkg-config 130 | ]; 131 | buildInputs = [ 132 | pkgs.libxcrypt 133 | pkgs.nodejs 134 | python38Full 135 | python310Full 136 | python311Full 137 | pkgs.readline 138 | pkgs.zlib 139 | pkgs.sqlite 140 | pkgs.tcl 141 | pkgs.expect 142 | ]; 143 | shellHook = '' 144 | export CGO_LDFLAGS_ALLOW="-Wl,--compress-debug-sections=zlib" 145 | export DISABLE_GO_TESTS=1 146 | ''; 147 | }; 148 | }); 149 | } 150 | 151 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ![Prybar](logo.svg) 2 | 3 | Prybar is a universal interpreter front-end. Same interface, same 4 | REPL, different languages. 5 | 6 | ## Why 7 | 8 | At [Repl.it](https://repl.it), we're in the business of running REPLs. 9 | As it happens to be, every language implements them differently. We 10 | wanted them to all behave the same: run code and drop into a REPL! 11 | 12 | ## How it works 13 | 14 | Prybar, written in [Go](https://golang.org/), maintains a common 15 | command-line interface that calls into a select language backend. When 16 | possible, the language backends are implemented using cgo and the 17 | language's C-bindings. Otherwise, they make use of a small script 18 | written in the host language which starts a Prybar-compatible REPL. 19 | 20 | ## Usage 21 | 22 | Usage: ./prybar-LANG [FLAGS] [FILENAME]... 23 | -I interactive (use readline repl) 24 | -c string 25 | execute without printing result 26 | -e string 27 | evaluate and print result 28 | -i interactive (use language repl) 29 | -ps1 string 30 | repl prompt (default "--> ") 31 | -ps2 string 32 | repl continuation prompt (default "... ") 33 | -q don't print language version 34 | 35 | ## Language Support 36 | 37 | | language | eval | eval expression | eval file | repl | repl like eval | set prompt | 38 | | ------------------------- | ---- | --------------- | --------- | ---- | -------------- | ---------- | 39 | | Clojure | ✔ | ✔ | ✔ | ✔ | ✔ | - | 40 | | Emacs Lisp | ✔ | ✔ | ✔ | ✔ | ✗ | ✔ | 41 | | Javascript (nodejs) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | 42 | | Javascript (spidermonkey) | ✔ | ✗ | ✗ | ✗ | ✗ | - | 43 | | Julia | ✔ | ✗ | ✔ | ✔ | ✗ | ✔ | 44 | | Lua 5.1 | ✔ | ✗ | ✔ | ✔ | ✗ | ✔ | 45 | | OCaml | ✔ | ✔ | ✔ | ✔ | ✗ | ✔ | 46 | | Python 2.7 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | 47 | | Python 3.x | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | 48 | | R | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | 49 | | Ruby 2.5 | ✔ | ✔ | ✔ | ✔ | ✗ | ✗ | 50 | | SQLite | ✔ | ✔ | ✔ | ✔ | ✗ | ✔ | 51 | | Tcl | ✔ | ✔ | ✔ | ✗ | ✗ | - | 52 | 53 | ## Start to Develop with Nix 54 | 55 | Look in `packages` in `flake.nix`. For each package present, you can do 56 | 57 | ``` 58 | nix build .# 59 | ``` 60 | 61 | to build it. The result will be a directory named `result`. 62 | 63 | Example: 64 | 65 | ``` 66 | $ nix build .#prybar-python311 67 | $ ls result/bin 68 | prybar-python311 69 | ``` 70 | 71 | Alternately, you can use the nix shell. Enter 72 | 73 | ``` 74 | nix develop 75 | ``` 76 | 77 | to drop into a shell that has all dependencies installed an ready to go. 78 | 79 | If you don't have nix yet, install that: https://nixos.org/ 80 | 81 | ## Build and run 82 | 83 | % make help 84 | usage: 85 | make all Build all Prybar binaries 86 | make prybar-LANG Build the Prybar binary for LANG 87 | make docker Run a shell with Prybar inside Docker 88 | (don't do this in the nix shell, although this is 89 | not needed if you use nix) 90 | make image Build a Docker image with Prybar for distribution 91 | make test Run integration tests 92 | make test-image Test Docker image for distribution 93 | make clean Remove build artifacts 94 | make help Show this message 95 | 96 | ### Distribution 97 | 98 | Run `make image` to create a Docker image containing not only Prybar's 99 | dependencies and source code but also its compiled binaries, which can 100 | be embedded inside other Docker images by means of `COPY 101 | --from=basicer/prybar`. 102 | 103 | This image is automatically built and deployed to [Docker 104 | Hub](https://hub.docker.com/) every time a commit is merged to 105 | `master`. 106 | 107 | ## License 108 | 109 | Copyright (C) 2004-2018 Neoreason, Inc. et al. 110 | 111 | This program is free software; you can redistribute it and/or 112 | modify it under the terms of the GNU General Public License 113 | as published by the Free Software Foundation; either version 2 114 | of the License, or (at your option) any later version. 115 | 116 | This program is distributed in the hope that it will be useful, 117 | but WITHOUT ANY WARRANTY; without even the implied warranty of 118 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 119 | GNU General Public License for more details. 120 | 121 | You should have received a copy of the GNU General Public License 122 | along with this program; if not, write to the Free Software 123 | Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 124 | 02110-1335, USA. 125 | 126 | See the COPYING file for more information regarding the GNU General 127 | Public License. 128 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/fetch-blob/README.md: -------------------------------------------------------------------------------- 1 | # fetch-blob 2 | 3 | [![npm version][npm-image]][npm-url] 4 | [![build status][ci-image]][ci-url] 5 | [![coverage status][codecov-image]][codecov-url] 6 | [![install size][install-size-image]][install-size-url] 7 | 8 | A Blob implementation in Node.js, originally from [node-fetch](https://github.com/node-fetch/node-fetch). 9 | 10 | ## Installation 11 | 12 | ```sh 13 | npm install fetch-blob 14 | ``` 15 | 16 |
17 | Upgrading from 2x to 3x 18 | 19 | Updating from 2 to 3 should be a breeze since there is not many changes to the blob specification. 20 | The major cause of a major release is coding standards. 21 | - internal WeakMaps was replaced with private fields 22 | - internal Buffer.from was replaced with TextEncoder/Decoder 23 | - internal buffers was replaced with Uint8Arrays 24 | - CommonJS was replaced with ESM 25 | - The node stream returned by calling `blob.stream()` was replaced with whatwg streams 26 | - (Read "Differences from other blobs" for more info.) 27 | 28 |
29 | 30 |
31 | Differences from other Blobs 32 | 33 | - Unlike NodeJS `buffer.Blob` (Added in: v15.7.0) and browser native Blob this polyfilled version can't be sent via PostMessage 34 | - This blob version is more arbitrary, it can be constructed with blob parts that isn't a instance of itself 35 | it has to look and behave as a blob to be accepted as a blob part. 36 | - The benefit of this is that you can create other types of blobs that don't contain any internal data that has to be read in other ways, such as the `BlobDataItem` created in `from.js` that wraps a file path into a blob-like item and read lazily (nodejs plans to [implement this][fs-blobs] as well) 37 | - The `blob.stream()` is the most noticeable differences. It returns a WHATWG stream now. to keep it as a node stream you would have to do: 38 | 39 | ```js 40 | import {Readable} from 'stream' 41 | const stream = Readable.from(blob.stream()) 42 | ``` 43 |
44 | 45 | ## Usage 46 | 47 | ```js 48 | // Ways to import 49 | // (PS it's dependency free ESM package so regular http-import from CDN works too) 50 | import Blob from 'fetch-blob' 51 | import File from 'fetch-blob/file.js' 52 | 53 | import {Blob} from 'fetch-blob' 54 | import {File} from 'fetch-blob/file.js' 55 | 56 | const {Blob} = await import('fetch-blob') 57 | 58 | 59 | // Ways to read the blob: 60 | const blob = new Blob(['hello, world']) 61 | 62 | await blob.text() 63 | await blob.arrayBuffer() 64 | for await (let chunk of blob.stream()) { ... } 65 | blob.stream().getReader().read() 66 | blob.stream().getReader({mode: 'byob'}).read(view) 67 | ``` 68 | 69 | ### Blob part backed up by filesystem 70 | 71 | `fetch-blob/from.js` comes packed with tools to convert any filepath into either a Blob or a File 72 | It will not read the content into memory. It will only stat the file for last modified date and file size. 73 | 74 | ```js 75 | // The default export is sync and use fs.stat to retrieve size & last modified as a blob 76 | import blobFromSync from 'fetch-blob/from.js' 77 | import {File, Blob, blobFrom, blobFromSync, fileFrom, fileFromSync} from 'fetch-blob/from.js' 78 | 79 | const fsFile = fileFromSync('./2-GiB-file.bin', 'application/octet-stream') 80 | const fsBlob = await blobFrom('./2-GiB-file.mp4') 81 | 82 | // Not a 4 GiB memory snapshot, just holds references 83 | // points to where data is located on the disk 84 | const blob = new Blob([fsFile, fsBlob, 'memory', new Uint8Array(10)]) 85 | console.log(blob.size) // ~4 GiB 86 | ``` 87 | 88 | `blobFrom|blobFromSync|fileFrom|fileFromSync(path, [mimetype])` 89 | 90 | ### Creating Blobs backed up by other async sources 91 | Our Blob & File class are more generic then any other polyfills in the way that it can accept any blob look-a-like item 92 | An example of this is that our blob implementation can be constructed with parts coming from [BlobDataItem](https://github.com/node-fetch/fetch-blob/blob/8ef89adad40d255a3bbd55cf38b88597c1cd5480/from.js#L32) (aka a filepath) or from [buffer.Blob](https://nodejs.org/api/buffer.html#buffer_new_buffer_blob_sources_options), It dose not have to implement all the methods - just enough that it can be read/understood by our Blob implementation. The minium requirements is that it has `Symbol.toStringTag`, `size`, `slice()` and either a `stream()` or a `arrayBuffer()` method. If you then wrap it in our Blob or File `new Blob([blobDataItem])` then you get all of the other methods that should be implemented in a blob or file 93 | 94 | An example of this could be to create a file or blob like item coming from a remote HTTP request. Or from a DataBase 95 | 96 | See the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/Blob) and [tests](https://github.com/node-fetch/fetch-blob/blob/master/test.js) for more details of how to use the Blob. 97 | 98 | [npm-image]: https://flat.badgen.net/npm/v/fetch-blob 99 | [npm-url]: https://www.npmjs.com/package/fetch-blob 100 | [ci-image]: https://github.com/node-fetch/fetch-blob/workflows/CI/badge.svg 101 | [ci-url]: https://github.com/node-fetch/fetch-blob/actions 102 | [codecov-image]: https://flat.badgen.net/codecov/c/github/node-fetch/fetch-blob/master 103 | [codecov-url]: https://codecov.io/gh/node-fetch/fetch-blob 104 | [install-size-image]: https://flat.badgen.net/packagephobia/install/fetch-blob 105 | [install-size-url]: https://packagephobia.now.sh/result?p=fetch-blob 106 | [fs-blobs]: https://github.com/nodejs/node/issues/37340 107 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/formdata-polyfill/README.md: -------------------------------------------------------------------------------- 1 | ### A `FormData` polyfill for the browser ...and a module for NodeJS (`New!`) 2 | 3 | ```bash 4 | npm install formdata-polyfill 5 | ``` 6 | 7 | The browser polyfill will likely have done its part already, and i hope you stop supporting old browsers c",)
8 | But NodeJS still laks a proper FormData
The good old form-data package is a very old and isn't spec compatible and dose some abnormal stuff to construct and read FormData instances that other http libraries are not happy about when it comes to follow the spec. 9 | 10 | ### The NodeJS / ESM version 11 | - The modular (~2.3 KiB minified uncompressed) version of this package is independent of any browser stuff and don't patch anything 12 | - It's as pure/spec compatible as it possible gets the test are run by WPT. 13 | - It's compatible with [node-fetch](https://github.com/node-fetch/node-fetch). 14 | - It have higher platform dependencies as it uses classes, symbols, ESM & private fields 15 | - Only dependency it has is [fetch-blob](https://github.com/node-fetch/fetch-blob) 16 | 17 | ```js 18 | // Node example 19 | import fetch from 'node-fetch' 20 | import File from 'fetch-blob/file.js' 21 | import { fileFromSync } from 'fetch-blob/from.js' 22 | import { FormData } from 'formdata-polyfill/esm.min.js' 23 | 24 | const file = fileFromSync('./README.md') 25 | const fd = new FormData() 26 | 27 | fd.append('file-upload', new File(['abc'], 'hello-world.txt')) 28 | fd.append('file-upload', file) 29 | 30 | // it's also possible to append file/blob look-a-like items 31 | // if you have streams coming from other destinations 32 | fd.append('file-upload', { 33 | size: 123, 34 | type: '', 35 | name: 'cat-video.mp4', 36 | stream() { return stream }, 37 | [Symbol.toStringTag]: 'File' 38 | }) 39 | 40 | fetch('https://httpbin.org/post', { method: 'POST', body: fd }) 41 | ``` 42 | 43 | ---- 44 | 45 | It also comes with way to convert FormData into Blobs - it's not something that every developer should have to deal with. 46 | It's mainly for [node-fetch](https://github.com/node-fetch/node-fetch) and other http library to ease the process of serializing a FormData into a blob and just wish to deal with Blobs instead (Both Deno and Undici adapted a version of this [formDataToBlob](https://github.com/jimmywarting/FormData/blob/5ddea9e0de2fc5e246ab1b2f9d404dee0c319c02/formdata-to-blob.js) to the core and passes all WPT tests run by the browser itself) 47 | ```js 48 | import { Readable } from 'node:stream' 49 | import { FormData, formDataToBlob } from 'formdata-polyfill/esm.min.js' 50 | 51 | const blob = formDataToBlob(new FormData()) 52 | fetch('https://httpbin.org/post', { method: 'POST', body: blob }) 53 | 54 | // node built in http and other similar http library have to do: 55 | const stream = Readable.from(blob.stream()) 56 | const req = http.request('http://httpbin.org/post', { 57 | method: 'post', 58 | headers: { 59 | 'Content-Length': blob.size, 60 | 'Content-Type': blob.type 61 | } 62 | }) 63 | stream.pipe(req) 64 | ``` 65 | 66 | PS: blob & file that are appended to the FormData will not be read until any of the serialized blob read-methods gets called 67 | ...so uploading very large files is no biggie 68 | 69 | ### Browser polyfill 70 | 71 | usage: 72 | 73 | ```js 74 | import 'formdata-polyfill' // that's it 75 | ``` 76 | 77 | The browser polyfill conditionally replaces the native implementation rather than fixing the missing functions, 78 | since otherwise there is no way to get or delete existing values in the FormData object. 79 | Therefore this also patches `XMLHttpRequest.prototype.send` and `fetch` to send the `FormData` as a blob, 80 | and `navigator.sendBeacon` to send native `FormData`. 81 | 82 | I was unable to patch the Response/Request constructor 83 | so if you are constructing them with FormData then you need to call `fd._blob()` manually. 84 | 85 | ```js 86 | new Request(url, { 87 | method: 'post', 88 | body: fd._blob ? fd._blob() : fd 89 | }) 90 | ``` 91 | 92 | Dependencies 93 | --- 94 | 95 | If you need to support IE <= 9 then I recommend you to include eligrey's [blob.js] 96 | (which i hope you don't - since IE is now dead) 97 | 98 |
99 | Updating from 2.x to 3.x 100 | 101 | Previously you had to import the polyfill and use that, 102 | since it didn't replace the global (existing) FormData implementation. 103 | But now it transparently calls `_blob()` for you when you are sending something with fetch or XHR, 104 | by way of monkey-patching the `XMLHttpRequest.prototype.send` and `fetch` functions. 105 | 106 | So you maybe had something like this: 107 | 108 | ```javascript 109 | var FormData = require('formdata-polyfill') 110 | var fd = new FormData(form) 111 | xhr.send(fd._blob()) 112 | ``` 113 | 114 | There is no longer anything exported from the module 115 | (though you of course still need to import it to install the polyfill), 116 | so you can now use the FormData object as normal: 117 | 118 | ```javascript 119 | require('formdata-polyfill') 120 | var fd = new FormData(form) 121 | xhr.send(fd) 122 | ``` 123 | 124 |
125 | 126 | 127 | 128 | Native Browser compatibility (as of 2021-05-08) 129 | --- 130 | Based on this you can decide for yourself if you need this polyfill. 131 | 132 | [![screenshot](https://user-images.githubusercontent.com/1148376/117550329-0993aa80-b040-11eb-976c-14e31f1a3ba4.png)](https://developer.mozilla.org/en-US/docs/Web/API/FormData#Browser_compatibility) 133 | 134 | 135 | 136 | This normalizes support for the FormData API: 137 | 138 | - `append` with filename 139 | - `delete()`, `get()`, `getAll()`, `has()`, `set()` 140 | - `entries()`, `keys()`, `values()`, and support for `for...of` 141 | - Available in web workers (just include the polyfill) 142 | 143 | [npm-image]: https://img.shields.io/npm/v/formdata-polyfill.svg 144 | [npm-url]: https://www.npmjs.com/package/formdata-polyfill 145 | [blob.js]: https://github.com/eligrey/Blob.js 146 | -------------------------------------------------------------------------------- /languages/nodejs/repl.js: -------------------------------------------------------------------------------- 1 | const repl = require('repl'); 2 | const path = require('path'); 3 | const assets_dir = 4 | process.env.PRYBAR_ASSETS_DIR || path.join(process.cwd(), 'prybar_assets'); 5 | /** 6 | * @type {import("../../prybar_assets/nodejs/input-sync")} 7 | */ 8 | const rl = require(path.join(assets_dir, 'nodejs', 'input-sync.js')); 9 | /** 10 | * @type {import("../../prybar_assets/nodejs/module-context-hook")} 11 | */ 12 | const { runCode, runModule, getRepl } = require(path.join( 13 | assets_dir, 14 | 'nodejs', 15 | 'module-context-hook.js' 16 | )); 17 | 18 | // imports to builtin modules don't get added to require.cache. 19 | const prybarFilenames = Object.keys(require.cache); 20 | 21 | for (const filename of prybarFilenames) { 22 | delete require.cache[filename]; 23 | } 24 | 25 | Error.prepareStackTrace = function prepareStackTrace(error, callSites) { 26 | // this logic is sourced from the internal repl error handler 27 | 28 | // Search from the bottom of the call stack to 29 | // find the first frame with a null function name 30 | callSites.reverse(); 31 | 32 | const idx = callSites.findIndex((frame) => frame.getFunctionName() === null); 33 | const domainIndex = callSites.findIndex( 34 | (site) => site.getFileName() === 'domain.js' 35 | ); 36 | 37 | if (domainIndex !== -1 && domainIndex < idx) { 38 | // If found, get rid of it and everything below it 39 | callSites = callSites.slice(idx); 40 | } 41 | 42 | callSites.reverse(); 43 | 44 | const lowestPrybarFileIndex = callSites.findIndex((site) => 45 | prybarFilenames.includes(site.getFileName()) 46 | ); 47 | 48 | callSites = callSites.slice(0, lowestPrybarFileIndex); 49 | 50 | if (!(error instanceof Error)) { 51 | const tmp = new Error(); 52 | 53 | tmp.message = error.message; 54 | tmp.name = error.name; 55 | error = tmp; 56 | } 57 | 58 | return callSites.length > 0 59 | ? `${error.toString()}\n at ${callSites.join('\n at ')}` 60 | : error.toString(); 61 | }; 62 | 63 | const isInterractive = Boolean(process.env.PRYBAR_INTERACTIVE); 64 | 65 | let r; 66 | if (!process.env.PRYBAR_QUIET) { 67 | console.log('Node ' + process.version + ' on ' + process.platform); 68 | } 69 | 70 | // Red errors (if stderr is a TTY) 71 | function logError(msg) { 72 | if (process.stderr.isTTY) { 73 | process.stderr.write(`\u001b[0m\u001b[31m${msg}\u001b[0m`); 74 | } else { 75 | process.stderr.write(msg); 76 | } 77 | 78 | if (!msg.endsWith('\n')) { 79 | process.stderr.write('\n'); 80 | } 81 | } 82 | 83 | // The nodejs repl operates in raw mode and does some funky stuff to 84 | // the terminal. This ns the repl and forces non-raw mode. 85 | function pauseRepl() { 86 | if (!r) return; 87 | 88 | r.pause(); 89 | } 90 | 91 | // Forces raw mode and resumes the repl. 92 | function resumeRepl() { 93 | if (!r) return; 94 | r.resume(); 95 | } 96 | 97 | // Clear the line if it has anything on it. 98 | function clearLine() { 99 | if (process.stdout.isTTY && r && r.line) r.clearLine(); 100 | } 101 | 102 | // Adapted from the internal node repl code just a lot simpler and adds 103 | // red errors (see https://bit.ly/2FRM86S) 104 | function handleError(e) { 105 | if (r) { 106 | r.lastError = e; 107 | } 108 | 109 | if (e && typeof e === 'object' && e.stack && e.name) { 110 | if (e.name === 'SyntaxError') { 111 | e.stack = e.stack 112 | .replace(/^repl:\d+\r?\n/, '') 113 | .replace(/^\s+at\s.*\n?/gm, ''); 114 | } 115 | 116 | logError(e.stack); 117 | } else { 118 | // For some reason needs a newline to flush. 119 | logError('Thrown: ' + r.writer(e)); 120 | } 121 | 122 | if (r) { 123 | r.clearBufferedCommand(); 124 | r.lines.level = []; 125 | r.displayPrompt(); 126 | } 127 | } 128 | 129 | function start() { 130 | /** @type { repl.REPLServer} */ 131 | r = 132 | getRepl() || 133 | repl.start({ 134 | useGlobal: true, 135 | prompt: process.env.PRYBAR_PS1, 136 | }); 137 | 138 | // remove the internal error and ours for red etc. 139 | r._domain.removeListener('error', r._domain.listeners('error')[0]); 140 | 141 | r._domain.on('error', handleError); 142 | process.on('uncaughtException', handleError); 143 | return false; 144 | } 145 | 146 | global.alert = console.log; 147 | global.prompt = (p) => { 148 | pauseRepl(); 149 | clearLine(); 150 | 151 | let ret = rl.question(`${p}> `); 152 | 153 | resumeRepl(); 154 | 155 | // Display prompt on the next turn. 156 | if (r) setImmediate(() => r.displayPrompt()); 157 | 158 | return ret; 159 | }; 160 | 161 | global.confirm = (q) => { 162 | pauseRepl(); 163 | clearLine(); 164 | 165 | const ret = rl.keyInYNStrict(q); 166 | 167 | resumeRepl(); 168 | 169 | // Display prompt on the next turn. 170 | if (r) setImmediate(() => r.displayPrompt()); 171 | return ret; 172 | }; 173 | 174 | if (process.env.PRYBAR_CODE) { 175 | try { 176 | runCode(process.env.PRYBAR_CODE, isInterractive); 177 | } catch (err) { 178 | handleError(err); 179 | 180 | if (!isInterractive) { 181 | process.exit(1); 182 | } 183 | } 184 | 185 | if (isInterractive) { 186 | process.once('beforeExit', start); 187 | } 188 | } else if (process.env.PRYBAR_EXP) { 189 | try { 190 | console.log(runCode(process.env.PRYBAR_EXP, false)); 191 | } catch (err) { 192 | handleError(err); 193 | 194 | if (!isInterractive) { 195 | process.exit(1); 196 | } 197 | } 198 | } else if (process.env.PRYBAR_FILE) { 199 | try { 200 | runModule(process.env.PRYBAR_FILE, isInterractive); 201 | } catch (err) { 202 | handleError(err); 203 | 204 | if (!isInterractive) { 205 | process.exit(1); 206 | } 207 | } 208 | 209 | if (isInterractive) { 210 | if (process.stdout.isTTY && process.stdin.isTTY) { 211 | console.log( 212 | '\u001b[0m\u001b[90mHint: hit control+c anytime to enter REPL.\u001b[0m' 213 | ); 214 | } 215 | 216 | process.once('beforeExit', start); 217 | process.once('SIGINT', start); 218 | } 219 | } else if (isInterractive) { 220 | start(); 221 | } 222 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/@replit/node-fetch/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | import {Agent} from 'http'; 5 | 6 | type AbortSignal = { 7 | readonly aborted: boolean; 8 | 9 | addEventListener: (type: 'abort', listener: (this: AbortSignal) => void) => void; 10 | removeEventListener: (type: 'abort', listener: (this: AbortSignal) => void) => void; 11 | }; 12 | 13 | export type HeadersInit = Headers | Record | Iterable | Iterable>; 14 | 15 | /** 16 | * This Fetch API interface allows you to perform various actions on HTTP request and response headers. 17 | * These actions include retrieving, setting, adding to, and removing. 18 | * A Headers object has an associated header list, which is initially empty and consists of zero or more name and value pairs. 19 | * You can add to this using methods like append() (see Examples.) 20 | * In all methods of this interface, header names are matched by case-insensitive byte sequence. 21 | * */ 22 | export class Headers { 23 | constructor(init?: HeadersInit); 24 | 25 | append(name: string, value: string): void; 26 | delete(name: string): void; 27 | get(name: string): string | null; 28 | has(name: string): boolean; 29 | set(name: string, value: string): void; 30 | forEach( 31 | callbackfn: (value: string, key: string, parent: Headers) => void, 32 | thisArg?: any 33 | ): void; 34 | 35 | [Symbol.iterator](): IterableIterator<[string, string]>; 36 | /** 37 | * Returns an iterator allowing to go through all key/value pairs contained in this object. 38 | */ 39 | entries(): IterableIterator<[string, string]>; 40 | /** 41 | * Returns an iterator allowing to go through all keys of the key/value pairs contained in this object. 42 | */ 43 | keys(): IterableIterator; 44 | /** 45 | * Returns an iterator allowing to go through all values of the key/value pairs contained in this object. 46 | */ 47 | values(): IterableIterator; 48 | 49 | /** Node-fetch extension */ 50 | raw(): Record; 51 | } 52 | 53 | export interface RequestInit { 54 | /** 55 | * A BodyInit object or null to set request's body. 56 | */ 57 | body?: BodyInit | null; 58 | /** 59 | * A Headers object, an object literal, or an array of two-item arrays to set request's headers. 60 | */ 61 | headers?: HeadersInit; 62 | /** 63 | * A string to set request's method. 64 | */ 65 | method?: string; 66 | /** 67 | * A string indicating whether request follows redirects, results in an error upon encountering a redirect, or returns the redirect (in an opaque fashion). Sets request's redirect. 68 | */ 69 | redirect?: RequestRedirect; 70 | /** 71 | * An AbortSignal to set request's signal. 72 | */ 73 | signal?: AbortSignal | null; 74 | /** 75 | * A string whose value is a same-origin URL, "about:client", or the empty string, to set request’s referrer. 76 | */ 77 | referrer?: string; 78 | /** 79 | * A referrer policy to set request’s referrerPolicy. 80 | */ 81 | referrerPolicy?: ReferrerPolicy; 82 | 83 | // Node-fetch extensions to the whatwg/fetch spec 84 | agent?: Agent | ((parsedUrl: URL) => Agent); 85 | compress?: boolean; 86 | counter?: number; 87 | follow?: number; 88 | hostname?: string; 89 | port?: number; 90 | protocol?: string; 91 | size?: number; 92 | highWaterMark?: number; 93 | insecureHTTPParser?: boolean; 94 | } 95 | 96 | export interface ResponseInit { 97 | headers?: HeadersInit; 98 | status?: number; 99 | statusText?: string; 100 | } 101 | 102 | export type BodyInit = 103 | | Blob 104 | | Buffer 105 | | URLSearchParams 106 | | FormData 107 | | NodeJS.ReadableStream 108 | | string; 109 | declare class BodyMixin { 110 | constructor(body?: BodyInit, options?: {size?: number}); 111 | 112 | readonly body: NodeJS.ReadableStream | null; 113 | readonly bodyUsed: boolean; 114 | readonly size: number; 115 | 116 | /** 117 | * @deprecated Please use 'response.arrayBuffer()' instead of 'response.buffer() 118 | */ 119 | buffer(): Promise; 120 | arrayBuffer(): Promise; 121 | formData(): Promise; 122 | blob(): Promise; 123 | json(): Promise; 124 | text(): Promise; 125 | } 126 | 127 | // `Body` must not be exported as a class since it's not exported from the JavaScript code. 128 | export interface Body extends Pick {} 129 | 130 | export type RequestRedirect = 'error' | 'follow' | 'manual'; 131 | export type ReferrerPolicy = '' | 'no-referrer' | 'no-referrer-when-downgrade' | 'same-origin' | 'origin' | 'strict-origin' | 'origin-when-cross-origin' | 'strict-origin-when-cross-origin' | 'unsafe-url'; 132 | export type RequestInfo = string | Request; 133 | export class Request extends BodyMixin { 134 | constructor(input: RequestInfo, init?: RequestInit); 135 | 136 | /** 137 | * Returns a Headers object consisting of the headers associated with request. Note that headers added in the network layer by the user agent will not be accounted for in this object, e.g., the "Host" header. 138 | */ 139 | readonly headers: Headers; 140 | /** 141 | * Returns request's HTTP method, which is "GET" by default. 142 | */ 143 | readonly method: string; 144 | /** 145 | * Returns the redirect mode associated with request, which is a string indicating how redirects for the request will be handled during fetching. A request will follow redirects by default. 146 | */ 147 | readonly redirect: RequestRedirect; 148 | /** 149 | * Returns the signal associated with request, which is an AbortSignal object indicating whether or not request has been aborted, and its abort event handler. 150 | */ 151 | readonly signal: AbortSignal; 152 | /** 153 | * Returns the URL of request as a string. 154 | */ 155 | readonly url: string; 156 | /** 157 | * A string whose value is a same-origin URL, "about:client", or the empty string, to set request’s referrer. 158 | */ 159 | readonly referrer: string; 160 | /** 161 | * A referrer policy to set request’s referrerPolicy. 162 | */ 163 | readonly referrerPolicy: ReferrerPolicy; 164 | clone(): Request; 165 | } 166 | 167 | type ResponseType = 'basic' | 'cors' | 'default' | 'error' | 'opaque' | 'opaqueredirect'; 168 | 169 | export class Response extends BodyMixin { 170 | constructor(body?: BodyInit | null, init?: ResponseInit); 171 | 172 | readonly headers: Headers; 173 | readonly ok: boolean; 174 | readonly redirected: boolean; 175 | readonly status: number; 176 | readonly statusText: string; 177 | readonly type: ResponseType; 178 | readonly url: string; 179 | clone(): Response; 180 | 181 | static error(): Response; 182 | static redirect(url: string, status?: number): Response; 183 | } 184 | 185 | export class FetchError extends Error { 186 | constructor(message: string, type: string, systemError?: Record); 187 | 188 | name: 'FetchError'; 189 | [Symbol.toStringTag]: 'FetchError'; 190 | type: string; 191 | code?: string; 192 | errno?: string; 193 | } 194 | 195 | export class AbortError extends Error { 196 | type: string; 197 | name: 'AbortError'; 198 | [Symbol.toStringTag]: 'AbortError'; 199 | } 200 | 201 | export function isRedirect(code: number): boolean; 202 | export default function fetch(url: RequestInfo, init?: RequestInit): Promise; 203 | -------------------------------------------------------------------------------- /languages/lua/lua.c: -------------------------------------------------------------------------------- 1 | // Copied straight from https://www.lua.org/source/5.1/lua.c.html 2 | // with some of the cli stuff stripped out. 3 | 4 | /* 5 | ** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp $ 6 | ** Lua stand-alone interpreter 7 | ** See Copyright Notice in lua.h 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define lua_c 16 | #define LUA_USE_LINUX 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | extern lua_State *pry_L; 25 | 26 | static const char *progname = LUA_PROGNAME; 27 | 28 | static void lstop(lua_State *L, lua_Debug *ar) { 29 | (void)ar; /* unused arg. */ 30 | lua_sethook(L, NULL, 0, 0); 31 | luaL_error(L, "interrupted!"); 32 | } 33 | 34 | static void laction(int i) { 35 | signal(i, SIG_DFL); /* if another SIGINT happens before lstop, 36 | terminate process (default action) */ 37 | lua_sethook(pry_L, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); 38 | } 39 | 40 | static void l_message(const char *pname, const char *msg) { 41 | if (pname) 42 | fprintf(stderr, "%s: ", pname); 43 | fprintf(stderr, "%s\n", msg); 44 | fflush(stderr); 45 | } 46 | 47 | static int report(lua_State *L, int status) { 48 | if (status && !lua_isnil(L, -1)) { 49 | const char *msg = lua_tostring(L, -1); 50 | if (msg == NULL) 51 | msg = "(error object is not a string)"; 52 | l_message(progname, msg); 53 | lua_pop(L, 1); 54 | } 55 | return status; 56 | } 57 | 58 | static int traceback(lua_State *L) { 59 | if (!lua_isstring(L, 1)) /* 'message' not a string? */ 60 | return 1; /* keep it intact */ 61 | lua_getfield(L, LUA_GLOBALSINDEX, "debug"); 62 | if (!lua_istable(L, -1)) { 63 | lua_pop(L, 1); 64 | return 1; 65 | } 66 | lua_getfield(L, -1, "traceback"); 67 | if (!lua_isfunction(L, -1)) { 68 | lua_pop(L, 2); 69 | return 1; 70 | } 71 | lua_pushvalue(L, 1); /* pass error message */ 72 | lua_pushinteger(L, 2); /* skip this function and traceback */ 73 | lua_call(L, 2, 1); /* call debug.traceback */ 74 | return 1; 75 | } 76 | 77 | static int docall(lua_State *L, int narg, int clear) { 78 | int status; 79 | int base = lua_gettop(L) - narg; /* function index */ 80 | lua_pushcfunction(L, traceback); /* push traceback function */ 81 | lua_insert(L, base); /* put it under chunk and args */ 82 | signal(SIGINT, laction); 83 | status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); 84 | signal(SIGINT, SIG_DFL); 85 | lua_remove(L, base); /* remove traceback function */ 86 | /* force a complete garbage collection in case of errors */ 87 | if (status != 0) 88 | lua_gc(L, LUA_GCCOLLECT, 0); 89 | return status; 90 | } 91 | 92 | static void print_version(void) { 93 | l_message(NULL, LUA_RELEASE " " LUA_COPYRIGHT); 94 | } 95 | 96 | static int getargs(lua_State *L, char **argv, int n, int argc) { 97 | int narg; 98 | int i; 99 | narg = argc - (n + 1); /* number of arguments to the script */ 100 | luaL_checkstack(L, narg + 3, "too many arguments to script"); 101 | for (i = n + 1; i < argc; i++) 102 | lua_pushstring(L, argv[i]); 103 | lua_createtable(L, narg, n + 1); 104 | for (i = 0; i < argc; i++) { 105 | lua_pushstring(L, argv[i]); 106 | lua_rawseti(L, -2, i - n); 107 | } 108 | return narg; 109 | } 110 | 111 | int dostring(lua_State *L, const char *s, const char *name) { 112 | int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1); 113 | return report(L, status); 114 | } 115 | 116 | static const char *get_prompt(lua_State *L, int firstline) { 117 | const char *p; 118 | lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2"); 119 | p = lua_tostring(L, -1); 120 | if (p == NULL) 121 | p = (firstline ? LUA_PROMPT : LUA_PROMPT2); 122 | lua_pop(L, 1); /* remove global */ 123 | return p; 124 | } 125 | 126 | static int incomplete(lua_State *L, int status) { 127 | if (status == LUA_ERRSYNTAX) { 128 | size_t lmsg; 129 | const char *msg = lua_tolstring(L, -1, &lmsg); 130 | const char *tp = msg + lmsg - (sizeof(LUA_QL("")) - 1); 131 | if (strstr(msg, LUA_QL("")) == tp) { 132 | lua_pop(L, 1); 133 | return 1; 134 | } 135 | } 136 | 137 | return 0; /* else... */ 138 | } 139 | 140 | static int pushline(lua_State *L, int firstline) { 141 | char buffer[LUA_MAXINPUT]; 142 | char *b = buffer; 143 | size_t l; 144 | const char *prmt = get_prompt(L, firstline); 145 | if (lua_readline(L, b, prmt) == 0) 146 | return 0; /* no input */ 147 | l = strlen(b); 148 | if (l > 0 && b[l - 1] == '\n') /* line ends with newline? */ 149 | b[l - 1] = '\0'; /* remove it */ 150 | if (firstline && b[0] == '=') /* first line starts with `=' ? */ 151 | lua_pushfstring(L, "return %s", b + 1); /* change it to `return' */ 152 | else 153 | lua_pushstring(L, b); 154 | lua_freeline(L, b); 155 | return 1; 156 | } 157 | 158 | static int try_expression(lua_State *L) { 159 | lua_pushliteral(L, "return "); 160 | lua_pushvalue(L, 1); 161 | lua_concat(L, 2); 162 | 163 | int rstatus = 164 | luaL_loadbuffer(L, lua_tostring(L, -1), lua_strlen(L, -1), "=stdin"); 165 | 166 | if (rstatus) { 167 | lua_pop(L, 2); 168 | return 1; 169 | } 170 | 171 | lua_remove(L, 2); 172 | 173 | return 0; 174 | } 175 | 176 | static int loadline(lua_State *L) { 177 | int status = 0; 178 | lua_settop(L, 0); 179 | if (!pushline(L, 1)) 180 | return -1; /* no input */ 181 | 182 | for (;;) { /* repeat until gets a complete line */ 183 | status = try_expression(L); 184 | if (!status) 185 | break; 186 | 187 | status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin"); 188 | 189 | if (!incomplete(L, status)) 190 | break; /* cannot try to add lines? */ 191 | 192 | if (!pushline(L, 0)) /* no more input? */ 193 | return -1; 194 | lua_pushliteral(L, "\n"); /* add a new line... */ 195 | lua_insert(L, -2); /* ...between the two lines */ 196 | lua_concat(L, 3); /* join them */ 197 | } 198 | 199 | lua_saveline(L, 1); 200 | lua_remove(L, 1); /* remove line */ 201 | return status; 202 | } 203 | 204 | void dotty(lua_State *L) { 205 | int status; 206 | const char *oldprogname = progname; 207 | progname = NULL; 208 | while ((status = loadline(L)) != -1) { 209 | if (status == 0) 210 | status = docall(L, 0, 0); 211 | report(L, status); 212 | if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */ 213 | lua_getglobal(L, "print"); 214 | lua_insert(L, 1); 215 | if (lua_pcall(L, lua_gettop(L) - 1, 0, 0) != 0) 216 | l_message(progname, 217 | lua_pushfstring(L, "error calling " LUA_QL("print") " (%s)", 218 | lua_tostring(L, -1))); 219 | } 220 | } 221 | lua_settop(L, 0); /* clear stack */ 222 | fputs("\n", stdout); 223 | fflush(stdout); 224 | progname = oldprogname; 225 | } 226 | 227 | int handle_script(lua_State *L, char **argv, int n) { 228 | int status; 229 | const char *fname; 230 | int narg = getargs(L, argv, n, 1); /* collect arguments */ 231 | lua_setglobal(L, "arg"); 232 | fname = argv[n]; 233 | if (strcmp(fname, "-") == 0 && strcmp(argv[n - 1], "--") != 0) 234 | fname = NULL; /* stdin */ 235 | status = luaL_loadfile(L, fname); 236 | lua_insert(L, -(narg + 1)); 237 | if (status == 0) 238 | status = docall(L, narg, 0); 239 | else 240 | lua_pop(L, narg); 241 | return report(L, status); 242 | } 243 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/web-streams-polyfill/README.md: -------------------------------------------------------------------------------- 1 | # web-streams-polyfill 2 | 3 | Web Streams, based on the WHATWG spec reference implementation. 4 | 5 | [![build status](https://api.travis-ci.com/MattiasBuelens/web-streams-polyfill.svg?branch=master)](https://travis-ci.com/MattiasBuelens/web-streams-polyfill) 6 | [![npm version](https://img.shields.io/npm/v/web-streams-polyfill.svg)](https://www.npmjs.com/package/web-streams-polyfill) 7 | [![license](https://img.shields.io/npm/l/web-streams-polyfill.svg)](https://github.com/MattiasBuelens/web-streams-polyfill/blob/master/LICENSE) 8 | [![Join the chat at https://gitter.im/web-streams-polyfill/Lobby](https://badges.gitter.im/web-streams-polyfill/Lobby.svg)](https://gitter.im/web-streams-polyfill/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 9 | 10 | ## Links 11 | 12 | - [Official spec][spec] 13 | - [Reference implementation][ref-impl] 14 | 15 | ## Usage 16 | 17 | This library comes in multiple variants: 18 | * `web-streams-polyfill`: a polyfill that replaces the native stream implementations. 19 | Recommended for use in web apps supporting older browsers through a ` 37 | 38 | 39 | 42 | ``` 43 | Usage as a Node module: 44 | ```js 45 | var streams = require("web-streams-polyfill/ponyfill"); 46 | var readable = new streams.ReadableStream(); 47 | ``` 48 | Usage as a ES2015 module: 49 | ```js 50 | import { ReadableStream } from "web-streams-polyfill/ponyfill"; 51 | const readable = new ReadableStream(); 52 | ``` 53 | 54 | ### Compatibility 55 | 56 | The `polyfill` and `ponyfill` variants work in any ES5-compatible environment that has a global `Promise`. 57 | If you need to support older browsers or Node versions that do not have a native `Promise` implementation 58 | (check the [support table][promise-support]), you must first include a `Promise` polyfill 59 | (e.g. [promise-polyfill][promise-polyfill]). 60 | 61 | The `polyfill/es6` and `ponyfill/es6` variants work in any ES2015-compatible environment. 62 | 63 | The `polyfill/es2018` and `ponyfill/es2018` variants work in any ES2018-compatible environment. 64 | 65 | [Async iterable support for `ReadableStream`][rs-asynciterator] is available in all variants, but requires an ES2018-compatible environment or a polyfill for `Symbol.asyncIterator`. 66 | 67 | [`WritableStreamDefaultController.signal`][ws-controller-signal] is available in all variants, but requires a global `AbortController` constructor. If necessary, consider using a polyfill such as [abortcontroller-polyfill]. 68 | 69 | ### Compliance 70 | 71 | The polyfill implements [version `4b6b93c` (25 Oct 2021)][spec-snapshot] of the streams specification. 72 | 73 | The polyfill is tested against the same [web platform tests][wpt] that are used by browsers to test their native implementations. 74 | The polyfill aims to pass all tests, although it allows some exceptions for practical reasons: 75 | * The `es2018` variant passes all of the tests, except for the ["bad buffers and views" tests for readable byte streams][wpt-bad-buffers]. 76 | These tests require the implementation to synchronously transfer the contents of an `ArrayBuffer`, which is not yet possible from JavaScript (although there is a [proposal][proposal-arraybuffer-transfer] to make it possible). 77 | The reference implementation "cheats" on these tests [by making a copy instead][ref-impl-transferarraybuffer], but that is unacceptable for the polyfill's performance ([#3][issue-3]). 78 | * The `es6` variant passes the same tests as the `es2018` variant, except for the [test for the prototype of `ReadableStream`'s async iterator][wpt-async-iterator-prototype]. 79 | Retrieving the correct `%AsyncIteratorPrototype%` requires using an async generator (`async function* () {}`), which is invalid syntax before ES2018. 80 | Instead, the polyfill [creates its own version][stub-async-iterator-prototype] which is functionally equivalent to the real prototype. 81 | * The `es5` variant passes the same tests as the `es6` variant, except for various tests about specific characteristics of the constructors, properties and methods. 82 | These test failures do not affect the run-time behavior of the polyfill. 83 | For example: 84 | * The `name` property of down-leveled constructors is incorrect. 85 | * The `length` property of down-leveled constructors and methods with optional arguments is incorrect. 86 | * Not all properties and methods are correctly marked as non-enumerable. 87 | * Down-leveled class methods are not correctly marked as non-constructable. 88 | 89 | The type definitions are compatible with the built-in stream types of TypeScript 3.3. 90 | 91 | ### Contributors 92 | 93 | Thanks to these people for their work on [the original polyfill][creatorrr-polyfill]: 94 | 95 | - Diwank Singh Tomer ([creatorrr](https://github.com/creatorrr)) 96 | - Anders Riutta ([ariutta](https://github.com/ariutta)) 97 | 98 | [spec]: https://streams.spec.whatwg.org 99 | [ref-impl]: https://github.com/whatwg/streams 100 | [ponyfill]: https://github.com/sindresorhus/ponyfill 101 | [promise-support]: https://kangax.github.io/compat-table/es6/#test-Promise 102 | [promise-polyfill]: https://www.npmjs.com/package/promise-polyfill 103 | [rs-asynciterator]: https://streams.spec.whatwg.org/#rs-asynciterator 104 | [ws-controller-signal]: https://streams.spec.whatwg.org/#ws-default-controller-signal 105 | [abortcontroller-polyfill]: https://www.npmjs.com/package/abortcontroller-polyfill 106 | [spec-snapshot]: https://streams.spec.whatwg.org/commit-snapshots/4b6b93c69e531e2fe45a6ed4cb1484a7ba4eb8bb/ 107 | [wpt]: https://github.com/web-platform-tests/wpt/tree/96ca25f0f7526282c0d47e6bf6a7edd439da1968/streams 108 | [wpt-bad-buffers]: https://github.com/web-platform-tests/wpt/blob/96ca25f0f7526282c0d47e6bf6a7edd439da1968/streams/readable-byte-streams/bad-buffers-and-views.any.js 109 | [proposal-arraybuffer-transfer]: https://github.com/domenic/proposal-arraybuffer-transfer 110 | [ref-impl-transferarraybuffer]: https://github.com/whatwg/streams/blob/4b6b93c69e531e2fe45a6ed4cb1484a7ba4eb8bb/reference-implementation/lib/abstract-ops/ecmascript.js#L16 111 | [issue-3]: https://github.com/MattiasBuelens/web-streams-polyfill/issues/3 112 | [wpt-async-iterator-prototype]: https://github.com/web-platform-tests/wpt/blob/96ca25f0f7526282c0d47e6bf6a7edd439da1968/streams/readable-streams/async-iterator.any.js#L24 113 | [stub-async-iterator-prototype]: https://github.com/MattiasBuelens/web-streams-polyfill/blob/v2.0.0/src/target/es5/stub/async-iterator-prototype.ts 114 | [creatorrr-polyfill]: https://github.com/creatorrr/web-streams-polyfill 115 | -------------------------------------------------------------------------------- /languages/ocaml/repl.ml: -------------------------------------------------------------------------------- 1 | #use "topfind";; 2 | #require "compiler-libs";; 3 | #require "unix";; 4 | (*#require "reason";;*) 5 | #load "ocamlcommon.cma";; 6 | #load "unix.cma";; 7 | (*#load "reason.cma";;*) 8 | 9 | type syntax = Reason | OCaml 10 | 11 | type eval_result = Success | Error of string 12 | 13 | type mode = 14 | | RunCode of string * syntax 15 | | StartRepl of syntax 16 | | PrintExpression of string * syntax 17 | | Stdin of syntax 18 | | Invalid of string 19 | 20 | type args = {mode: mode} 21 | 22 | exception LangException of string 23 | 24 | let _ = 25 | let interactive_mode = ref false in 26 | let eval_filepath = ref None in 27 | let quiet = ref false in 28 | let syntax = ref OCaml in 29 | let print_mode = ref false in 30 | let run_mode = ref false in 31 | let ps1 = Sys.getenv_opt "PRYBAR_PS1" |> function | Some str -> str | None -> "#" in 32 | let ps2 = Sys.getenv_opt "PRYBAR_PS2" |> function | Some str -> str | None -> " " in 33 | (* If there is code provided to interpret *) 34 | let code = ref "" in 35 | let parse_syntax = function 36 | | "re" -> syntax := Reason 37 | | "ml" -> syntax := OCaml 38 | | arg -> raise (Arg.Bad ("Unknown syntax: " ^ arg)) 39 | in 40 | let print_mode_arg str = 41 | print_mode := true ; 42 | code := str 43 | in 44 | let run_mode_arg str = 45 | run_mode := true ; 46 | code := str 47 | in 48 | let speclist = 49 | [ ("-q", Arg.Set quiet, "Don't print OCaml version on startup") 50 | ; ( "-e" , Arg.String print_mode_arg , "Eval and output results of interpreted code" ) 51 | ; ("-c", Arg.String run_mode_arg, "Run code without printing the output") 52 | ; ("-i", Arg.Set interactive_mode, "Run as interactive repl") 53 | ; ( "-s" , Arg.Symbol (["ml"; "re"], parse_syntax), " Sets the syntax for the repl (default: ml)" ) ] 54 | in 55 | let usage_msg = 56 | "OCaml / Reason repl script for prybar. Options available:" 57 | in 58 | Arg.parse speclist 59 | (fun str -> 60 | match (str, !interactive_mode) with 61 | | (path, true) -> eval_filepath := Some(path) 62 | | _ -> print_endline ("Anonymous arg: " ^ str) 63 | ) 64 | usage_msg ; 65 | let mode = 66 | match (!print_mode, !run_mode, !interactive_mode) with 67 | | true, false, false -> PrintExpression (!code, !syntax) 68 | | false, true, false -> RunCode (!code, !syntax) 69 | | false, false, true -> StartRepl !syntax 70 | | _ -> Invalid "You can only use one mode: -e | -i | -c" 71 | in 72 | let module Custom_Toploop = struct 73 | include Toploop 74 | open Format 75 | 76 | (* Most stuff is straightly copied and modified 77 | * from github.com/ocaml/ocaml/blob/trunk/toplevel/toploop.ml *) 78 | exception PPerror 79 | 80 | let first_line = ref true 81 | 82 | let got_eof = ref false 83 | 84 | let refill_lexbuf buffer len = 85 | if !got_eof then ( 86 | got_eof := false ; 87 | 0 ) 88 | else 89 | let prompt = 90 | if !first_line then ps1 ^ " " 91 | else if Lexer.in_comment () then "* " 92 | else ps2 (* continuation prompt *) 93 | in 94 | first_line := false ; 95 | let len, eof = !read_interactive_input prompt buffer len in 96 | if eof then ( 97 | Location.echo_eof () ; 98 | if len > 0 then got_eof := true ; 99 | len ) 100 | else len 101 | 102 | (* Minimal version of just running any input file, we stripped a lot of original logic 103 | * because we don't want to do any side effects on the compiler environment *) 104 | let run_script ppf name = 105 | let explicit_name = 106 | (* Prevent use_silently from searching in the path. *) 107 | if name <> "" && Filename.is_implicit name 108 | then Filename.concat Filename.current_dir_name name 109 | else name 110 | in 111 | use_silently ppf explicit_name 112 | 113 | let loop ppf = 114 | Clflags.debug := true ; 115 | Location.formatter_for_warnings := ppf ; 116 | ( try initialize_toplevel_env () with 117 | | (Env.Error _ | Typetexp.Error _) as exn -> 118 | Location.report_exception ppf exn ; 119 | exit 2 ) ; 120 | let lb = Lexing.from_function refill_lexbuf in 121 | Location.init lb "//toplevel//" ; 122 | Location.input_name := "//toplevel//" ; 123 | Location.input_lexbuf := Some lb ; 124 | Sys.catch_break true ; 125 | (*load_ocamlinit ppf;*) 126 | 127 | (* If there's an entry file provided, run it before dropping into interactive mode *) 128 | (match !eval_filepath with 129 | | Some name -> run_script ppf name 130 | | _ -> false) |> ignore ; 131 | 132 | while true do 133 | let snap = Btype.snapshot () in 134 | try 135 | Lexing.flush_input lb ; 136 | Location.reset () ; 137 | Warnings.reset_fatal () ; 138 | first_line := true ; 139 | let phr = 140 | try !parse_toplevel_phrase lb with Exit -> raise PPerror 141 | in 142 | let phr = preprocess_phrase ppf phr in 143 | Env.reset_cache_toplevel () ; 144 | ignore (execute_phrase true ppf phr) 145 | with 146 | | End_of_file -> exit 0 147 | | Sys.Break -> 148 | fprintf ppf "Interrupted.@." ; 149 | Btype.backtrack snap 150 | | PPerror -> () 151 | | x -> 152 | Location.report_exception ppf x ; 153 | Btype.backtrack snap 154 | done 155 | end in 156 | let module Repl = struct 157 | let std_fmt = Format.std_formatter 158 | 159 | let noop_fmt = Format.make_formatter (fun _ _ _ -> ()) ignore 160 | 161 | let init_toploop () = 162 | Topfind.add_predicates ["byte"; "toploop"] ; 163 | (* Add findlib path so Topfind is available and it won't be 164 | initialized twice if the user does [#use "topfind"]. *) 165 | Topdirs.dir_directory (Findlib.package_directory "findlib") ; 166 | Toploop.initialize_toplevel_env () 167 | 168 | let start_loop ?(fmt = std_fmt) () = Custom_Toploop.loop fmt 169 | 170 | let eval ?(fmt = std_fmt) ~syntax str = 171 | try 172 | let lex = Lexing.from_string str in 173 | let tpl_phrases = 174 | match syntax with 175 | | OCaml | Reason -> Parse.use_file lex 176 | (*| Reason ->*) 177 | (*List.map Reason_toolchain.To_current.copy_toplevel_phrase*) 178 | (*(Reason_toolchain.RE.use_file lex)*) 179 | in 180 | let exec phr = 181 | if Toploop.execute_phrase true fmt phr then Success 182 | else Error "No result" 183 | in 184 | let rec execAll phrases = 185 | match phrases with 186 | | [] -> Error "No result" 187 | | [phr] -> exec phr 188 | | phr :: next -> ( 189 | let ret = exec phr in 190 | match ret with Error _ -> ret | _ -> execAll next ) 191 | in 192 | execAll tpl_phrases 193 | with 194 | | Syntaxerr.Error _ -> Error "Syntax Error occurred" 195 | (*| Reason_syntax_util.Error _ -> Error "Reason Parsing Error"*) 196 | | _ -> Error ("Error while exec: " ^ str) 197 | end in 198 | if not !quiet then print_endline ("OCaml " ^ Sys.ocaml_version ^ " on " ^ Sys.os_type); 199 | match mode with 200 | | PrintExpression (code, syntax) -> 201 | Repl.init_toploop () ; 202 | Repl.eval ~syntax code |> ignore 203 | | RunCode (code, syntax) -> 204 | Repl.init_toploop () ; 205 | Repl.eval ~syntax ~fmt:Repl.noop_fmt code |> ignore 206 | | StartRepl syntax -> 207 | Repl.init_toploop () ; 208 | Repl.start_loop () 209 | | Stdin syntax -> print_endline "Reading from stdin" 210 | | Invalid str -> print_endline str 211 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/node_modules/fetch-blob/index.js: -------------------------------------------------------------------------------- 1 | /*! fetch-blob. MIT License. Jimmy Wärting */ 2 | 3 | // TODO (jimmywarting): in the feature use conditional loading with top level await (requires 14.x) 4 | // Node has recently added whatwg stream into core 5 | 6 | import './streams.cjs' 7 | 8 | // 64 KiB (same size chrome slice theirs blob into Uint8array's) 9 | const POOL_SIZE = 65536 10 | 11 | /** @param {(Blob | Uint8Array)[]} parts */ 12 | async function * toIterator (parts, clone = true) { 13 | for (const part of parts) { 14 | if ('stream' in part) { 15 | yield * (/** @type {AsyncIterableIterator} */ (part.stream())) 16 | } else if (ArrayBuffer.isView(part)) { 17 | if (clone) { 18 | let position = part.byteOffset 19 | const end = part.byteOffset + part.byteLength 20 | while (position !== end) { 21 | const size = Math.min(end - position, POOL_SIZE) 22 | const chunk = part.buffer.slice(position, position + size) 23 | position += chunk.byteLength 24 | yield new Uint8Array(chunk) 25 | } 26 | } else { 27 | yield part 28 | } 29 | /* c8 ignore next 10 */ 30 | } else { 31 | // For blobs that have arrayBuffer but no stream method (nodes buffer.Blob) 32 | let position = 0, b = (/** @type {Blob} */ (part)) 33 | while (position !== b.size) { 34 | const chunk = b.slice(position, Math.min(b.size, position + POOL_SIZE)) 35 | const buffer = await chunk.arrayBuffer() 36 | position += buffer.byteLength 37 | yield new Uint8Array(buffer) 38 | } 39 | } 40 | } 41 | } 42 | 43 | const _Blob = class Blob { 44 | /** @type {Array.<(Blob|Uint8Array)>} */ 45 | #parts = [] 46 | #type = '' 47 | #size = 0 48 | #endings = 'transparent' 49 | 50 | /** 51 | * The Blob() constructor returns a new Blob object. The content 52 | * of the blob consists of the concatenation of the values given 53 | * in the parameter array. 54 | * 55 | * @param {*} blobParts 56 | * @param {{ type?: string, endings?: string }} [options] 57 | */ 58 | constructor (blobParts = [], options = {}) { 59 | if (typeof blobParts !== 'object' || blobParts === null) { 60 | throw new TypeError('Failed to construct \'Blob\': The provided value cannot be converted to a sequence.') 61 | } 62 | 63 | if (typeof blobParts[Symbol.iterator] !== 'function') { 64 | throw new TypeError('Failed to construct \'Blob\': The object must have a callable @@iterator property.') 65 | } 66 | 67 | if (typeof options !== 'object' && typeof options !== 'function') { 68 | throw new TypeError('Failed to construct \'Blob\': parameter 2 cannot convert to dictionary.') 69 | } 70 | 71 | if (options === null) options = {} 72 | 73 | const encoder = new TextEncoder() 74 | for (const element of blobParts) { 75 | let part 76 | if (ArrayBuffer.isView(element)) { 77 | part = new Uint8Array(element.buffer.slice(element.byteOffset, element.byteOffset + element.byteLength)) 78 | } else if (element instanceof ArrayBuffer) { 79 | part = new Uint8Array(element.slice(0)) 80 | } else if (element instanceof Blob) { 81 | part = element 82 | } else { 83 | part = encoder.encode(`${element}`) 84 | } 85 | 86 | this.#size += ArrayBuffer.isView(part) ? part.byteLength : part.size 87 | this.#parts.push(part) 88 | } 89 | 90 | this.#endings = `${options.endings === undefined ? 'transparent' : options.endings}` 91 | const type = options.type === undefined ? '' : String(options.type) 92 | this.#type = /^[\x20-\x7E]*$/.test(type) ? type : '' 93 | } 94 | 95 | /** 96 | * The Blob interface's size property returns the 97 | * size of the Blob in bytes. 98 | */ 99 | get size () { 100 | return this.#size 101 | } 102 | 103 | /** 104 | * The type property of a Blob object returns the MIME type of the file. 105 | */ 106 | get type () { 107 | return this.#type 108 | } 109 | 110 | /** 111 | * The text() method in the Blob interface returns a Promise 112 | * that resolves with a string containing the contents of 113 | * the blob, interpreted as UTF-8. 114 | * 115 | * @return {Promise} 116 | */ 117 | async text () { 118 | // More optimized than using this.arrayBuffer() 119 | // that requires twice as much ram 120 | const decoder = new TextDecoder() 121 | let str = '' 122 | for await (const part of toIterator(this.#parts, false)) { 123 | str += decoder.decode(part, { stream: true }) 124 | } 125 | // Remaining 126 | str += decoder.decode() 127 | return str 128 | } 129 | 130 | /** 131 | * The arrayBuffer() method in the Blob interface returns a 132 | * Promise that resolves with the contents of the blob as 133 | * binary data contained in an ArrayBuffer. 134 | * 135 | * @return {Promise} 136 | */ 137 | async arrayBuffer () { 138 | // Easier way... Just a unnecessary overhead 139 | // const view = new Uint8Array(this.size); 140 | // await this.stream().getReader({mode: 'byob'}).read(view); 141 | // return view.buffer; 142 | 143 | const data = new Uint8Array(this.size) 144 | let offset = 0 145 | for await (const chunk of toIterator(this.#parts, false)) { 146 | data.set(chunk, offset) 147 | offset += chunk.length 148 | } 149 | 150 | return data.buffer 151 | } 152 | 153 | stream () { 154 | const it = toIterator(this.#parts, true) 155 | 156 | return new globalThis.ReadableStream({ 157 | // @ts-ignore 158 | type: 'bytes', 159 | async pull (ctrl) { 160 | const chunk = await it.next() 161 | chunk.done ? ctrl.close() : ctrl.enqueue(chunk.value) 162 | }, 163 | 164 | async cancel () { 165 | await it.return() 166 | } 167 | }) 168 | } 169 | 170 | /** 171 | * The Blob interface's slice() method creates and returns a 172 | * new Blob object which contains data from a subset of the 173 | * blob on which it's called. 174 | * 175 | * @param {number} [start] 176 | * @param {number} [end] 177 | * @param {string} [type] 178 | */ 179 | slice (start = 0, end = this.size, type = '') { 180 | const { size } = this 181 | 182 | let relativeStart = start < 0 ? Math.max(size + start, 0) : Math.min(start, size) 183 | let relativeEnd = end < 0 ? Math.max(size + end, 0) : Math.min(end, size) 184 | 185 | const span = Math.max(relativeEnd - relativeStart, 0) 186 | const parts = this.#parts 187 | const blobParts = [] 188 | let added = 0 189 | 190 | for (const part of parts) { 191 | // don't add the overflow to new blobParts 192 | if (added >= span) { 193 | break 194 | } 195 | 196 | const size = ArrayBuffer.isView(part) ? part.byteLength : part.size 197 | if (relativeStart && size <= relativeStart) { 198 | // Skip the beginning and change the relative 199 | // start & end position as we skip the unwanted parts 200 | relativeStart -= size 201 | relativeEnd -= size 202 | } else { 203 | let chunk 204 | if (ArrayBuffer.isView(part)) { 205 | chunk = part.subarray(relativeStart, Math.min(size, relativeEnd)) 206 | added += chunk.byteLength 207 | } else { 208 | chunk = part.slice(relativeStart, Math.min(size, relativeEnd)) 209 | added += chunk.size 210 | } 211 | relativeEnd -= size 212 | blobParts.push(chunk) 213 | relativeStart = 0 // All next sequential parts should start at 0 214 | } 215 | } 216 | 217 | const blob = new Blob([], { type: String(type).toLowerCase() }) 218 | blob.#size = span 219 | blob.#parts = blobParts 220 | 221 | return blob 222 | } 223 | 224 | get [Symbol.toStringTag] () { 225 | return 'Blob' 226 | } 227 | 228 | static [Symbol.hasInstance] (object) { 229 | return ( 230 | object && 231 | typeof object === 'object' && 232 | typeof object.constructor === 'function' && 233 | ( 234 | typeof object.stream === 'function' || 235 | typeof object.arrayBuffer === 'function' 236 | ) && 237 | /^(Blob|File)$/.test(object[Symbol.toStringTag]) 238 | ) 239 | } 240 | } 241 | 242 | Object.defineProperties(_Blob.prototype, { 243 | size: { enumerable: true }, 244 | type: { enumerable: true }, 245 | slice: { enumerable: true } 246 | }) 247 | 248 | /** @type {typeof globalThis.Blob} */ 249 | export const Blob = _Blob 250 | export default Blob 251 | -------------------------------------------------------------------------------- /prybar_assets/nodejs/input-sync.js: -------------------------------------------------------------------------------- 1 | const { readSync, writeSync, openSync } = require("fs"); 2 | const { isatty } = require("tty"); 3 | const buf = Buffer.alloc(1); 4 | const isTTY = isatty(process.stdin.fd); 5 | 6 | /** 7 | * The escape (excluding \x1b) to move the cursur right one. 8 | * 9 | * This is what the right arrow key translates to in raw mode. 10 | */ 11 | const cursorRight = "[C"; 12 | /** 13 | * The escape (excluding \x1b) to move the cursur left one. 14 | * 15 | * This is what the left arrow key translates to in raw mode. 16 | */ 17 | const cursorLeft = "[D"; 18 | 19 | /** 20 | * The ASCII character sent when the tty is in raw mode and backspace is pressed. 21 | */ 22 | const del = "\x7f"; 23 | 24 | /** 25 | * The ASCII characcter sent when the tty is in raw mode and Ctrl+C is pressed. 26 | */ 27 | const endOfText = "\x03"; 28 | /** 29 | * The ASCII character sent when the tty is in raw mode and Ctrl+D is pressed. 30 | */ 31 | const endOfTransmission = "\x04"; 32 | 33 | /** 34 | * Reads a single byte from stdin to buf. 35 | * @return {boolean} Whether a byte was read or not (false on EOF) 36 | */ 37 | function readByteSync() { 38 | const read = readSync(stdinFd, buf); 39 | 40 | return read > 0; 41 | } 42 | 43 | /** 44 | * The file descriptor of our stdin stream. 45 | * @type {number} 46 | */ 47 | const stdinFd = isTTY 48 | ? // We can't just use process.stdin.fd here since node has some getter shenanigans 49 | // which cause sync reads to throw 50 | openSync("/dev/tty", "r") 51 | : openSync("/dev/stdin", "r"); 52 | 53 | /** 54 | * Writes output to stdout. 55 | * 56 | * @param {NodeJS.ArrayBufferView} b The outpus which should be written to stdout. 57 | */ 58 | function writeOutput(b) { 59 | writeSync(process.stdout.fd, b); 60 | } 61 | 62 | /** 63 | * Writes a buffer or string to stdout, only if stdin is a tty. 64 | * @param {NodeJS.ArrayBufferView} b The outpus which should be written to stdout (if stdin is a tty). 65 | */ 66 | function writeTTYOutput(b) { 67 | if (isTTY) { 68 | writeOutput(b); 69 | } 70 | } 71 | 72 | /** 73 | * If stdin is a tty, ensure raw mode is on prior to executing cb, 74 | * then reset it to its previous state afterwards. If stdin isn't a tty, 75 | * cb will just be executed normally. 76 | * 77 | * @template T 78 | * @param {() => T} cb The function which is being executed. 79 | * @return {T} The return value of cb 80 | */ 81 | function ensureRawMode(cb) { 82 | if (!isTTY) { 83 | return cb(); 84 | } 85 | 86 | const previousRawMode = process.stdin.isRaw; 87 | 88 | let ret; 89 | 90 | try { 91 | process.stdin.setRawMode(true); 92 | ret = cb(); 93 | } finally { 94 | process.stdin.setRawMode(previousRawMode); 95 | } 96 | 97 | return ret; 98 | } 99 | 100 | /** 101 | * Handles ANSI escapes from stdin. 102 | * 103 | * @return {string | -1 | 1} String if the escape isn't a left or right arrow . 104 | * Otherwise, -1 on left arrow and 1 on right arrow 105 | */ 106 | function handleArrowKey() { 107 | if (!readByteSync()) { 108 | return "^"; 109 | } 110 | 111 | let str = buf.toString("binary"); 112 | 113 | if (str !== "[") { 114 | return `^${str}`; 115 | } 116 | 117 | if (!readByteSync()) { 118 | return `^${str}`; 119 | } 120 | 121 | str += buf.toString("binary"); 122 | 123 | switch (str) { 124 | case cursorRight: 125 | return 1; 126 | case cursorLeft: 127 | return -1; 128 | default: 129 | return `^${str}`; 130 | } 131 | } 132 | 133 | /** 134 | * Checks to see if the input character is what we get in raw mode for 135 | * Ctrl+C or Ctrl+D, and if so sends the proc SIGINT> 136 | * 137 | * @param {string} char The character read. 138 | */ 139 | function checkForSigs(char) { 140 | if (isTTY && (char === endOfText || char === endOfTransmission)) { 141 | process.exit(); 142 | } 143 | } 144 | 145 | /** 146 | * Writes a string at an index of another string, appending as needed. 147 | * 148 | * @param {string} str The base string 149 | * @param {string} other The new string which is being written 150 | * @param {number} index The index at which the new string should start at. 151 | * @return {string} str with other written at index. 152 | */ 153 | function insertAt(str, other, index) { 154 | return [str.slice(0, index) + other + str.slice(index), index + other.length]; 155 | } 156 | 157 | /** 158 | * The ANSI escape code used to clear the contents of the current line to the right 159 | * of the cursor. 160 | */ 161 | const escapeClearLineRight = "\x1b[K"; 162 | 163 | /** 164 | * The escape used to move the cursor to a specific position in-line. 165 | * 166 | * @param {number} columnNum The position (starting at 1) in the current line which the cursor should be moved to. 167 | * 168 | */ 169 | function escapeMoveCursorToColumn(columnNum) { 170 | return `\x1b[${columnNum}G`; 171 | } 172 | 173 | /** 174 | * Sets the current line to our promt + string w/ the cursor at the right index. 175 | * 176 | * @param {string} prompt The question's prompt 177 | * @param {string} current The current string (what the user has input so far) 178 | * @param {number} index The index that 179 | */ 180 | function displayPromptAndStr(prompt, current, index) { 181 | writeTTYOutput( 182 | // reset cursor position 183 | "\r" + 184 | // clear the rest of the line 185 | // EL (Erase in Line ): in this case, as no number is speciifed, 186 | // erases everything to the right of the cursor. 187 | escapeClearLineRight + 188 | // write the prompt 189 | prompt + 190 | // write the string 191 | current + 192 | escapeMoveCursorToColumn(prompt.length + index + 1) 193 | ); 194 | } 195 | 196 | /** 197 | * Synchronously reads from stdin until `\n` or `\r` 198 | * 199 | * @param {string} prompt The prompt to be displayed 200 | * @return {string} The input read (excluding newlines) 201 | */ 202 | function question(prompt) { 203 | return ensureRawMode(() => { 204 | let str = ""; 205 | let index = 0; 206 | 207 | if (!isTTY) { 208 | writeOutput(prompt); 209 | } 210 | 211 | for (;;) { 212 | displayPromptAndStr(prompt, str, index); 213 | const didRead = readByteSync(); 214 | 215 | if (!didRead) { 216 | return str; 217 | } 218 | 219 | const char = buf.toString("binary"); 220 | checkForSigs(char); 221 | 222 | if (char === "\n" || char === "\r") { 223 | writeTTYOutput("\r\n"); 224 | 225 | return str; 226 | } else if (isTTY && char === "\x1b") { 227 | const ret = handleArrowKey(); 228 | 229 | // if ret is a number, its the difference for the index 230 | if (typeof ret === "number") { 231 | // Only move the cursor if it will be in a valid position. 232 | const newIndex = index + ret; 233 | // the index can be equal to the strs length, if that's the case we're appending to the string. 234 | if (newIndex >= 0 && newIndex <= str.length) { 235 | index = newIndex; 236 | } 237 | 238 | // otherwise, the escape wasn't a left or right arrow key, 239 | // meaning we got an escaped version of the code. 240 | } else { 241 | [str, index] = insertAt(str, ret, index); 242 | } 243 | } else if (isTTY && char === del) { 244 | if (index > 0) { 245 | index--; 246 | // remove the character at the old index 247 | str = str.slice(0, index) + str.slice(index + 1); 248 | } 249 | } else { 250 | [str, index] = insertAt(str, char, index); 251 | } 252 | } 253 | }); 254 | } 255 | 256 | /** 257 | * Synchronously waits for 'y' or 'n' (case insensitive) and returns a boolean 258 | * where 'y' is true and 'n' is false. 259 | * 260 | * @param {string | undefined | null} prompt The prompt. 261 | * @returns {boolean} True if the input was y; false otherwise. 262 | * @throws {Error} If EOF is received before y/n 263 | */ 264 | function keyInYNStrict(prompt) { 265 | return ensureRawMode(() => { 266 | writeOutput(`${prompt == null ? "Are you sure?" : prompt} [y/n]: `); 267 | 268 | for (;;) { 269 | const didRead = readByteSync(); 270 | 271 | if (!didRead) { 272 | throw new Error("Unexpected EOF / end of input. Expected y/n."); 273 | } 274 | 275 | const char = buf.toString("binary"); 276 | checkForSigs(char); 277 | 278 | if (char.match(/[yn]/i)) { 279 | writeTTYOutput(`${char}\r\n`); 280 | 281 | return char === "y" || char === "Y"; 282 | } 283 | } 284 | }); 285 | } 286 | 287 | module.exports = { 288 | question, 289 | keyInYNStrict, 290 | }; 291 | --------------------------------------------------------------------------------