New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

bun-repl

Package Overview
Dependencies
Maintainers
1
Versions
30
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bun-repl - npm Package Compare versions

Comparing version 2.0.6 to 2.0.7

2

package.json
{
"type": "module",
"name": "bun-repl",
"version": "2.0.6",
"version": "2.0.7",
"description": "Experimental REPL for Bun",

@@ -6,0 +6,0 @@ "main": "src/module/repl.ts",

@@ -13,2 +13,3 @@ import { type JSC } from 'bun-devtools';

const { exit, cwd } = process;
const stdoutWrite = process.stdout.write.bind(process.stdout);

@@ -62,5 +63,11 @@ /**Safely get an object's property. If an error occurs, just treat it as non-existent. */

const ReflectDeleteProperty = Reflect.deleteProperty;
const RegExpTest = Function.prototype.call.bind(RegExp.prototype.test) as Primordial<RegExp, 'test'>;
const RegExpPrototypeSymbolReplace = Function.prototype.call.bind(RegExp.prototype[Symbol.replace]) as Primordial<RegExp, typeof Symbol.replace>;
const FunctionApply = Function.prototype.call.bind(Function.prototype.apply) as Primordial<Function, 'apply'>;
const BufferToString = Function.prototype.call.bind(Reflect.get(Buffer.prototype, 'toString') as Buffer['toString']) as Primordial<Buffer, 'toString'>;
const StringTrim = Function.prototype.call.bind(String.prototype.trim) as Primordial<String, 'trim'>;
const StringPadStart = Function.prototype.call.bind(String.prototype.padStart) as Primordial<String, 'padStart'>;
const StringPadEnd = Function.prototype.call.bind(String.prototype.padEnd) as Primordial<String, 'padEnd'>;
const StringRepeat = Function.prototype.call.bind(String.prototype.repeat) as Primordial<String, 'repeat'>;
const StringMatchAll = Function.prototype.call.bind(String.prototype.matchAll) as Primordial<String, 'matchAll'>;
const StringPrototypeSlice = Function.prototype.call.bind(String.prototype.slice) as Primordial<String, 'slice'>;

@@ -71,2 +78,3 @@ const StringPrototypeSplit = Function.prototype.call.bind(String.prototype.split) as Primordial<String, 'split'>;

const StringPrototypeReplaceAll = Function.prototype.call.bind(String.prototype.replaceAll) as Primordial<String, 'replaceAll'>;
const ArrayPush = Function.prototype.call.bind(Array.prototype.push) as Primordial<Array<any>, 'push'>;
const ArrayPrototypePop = Function.prototype.call.bind(Array.prototype.pop) as Primordial<Array<any>, 'pop'>;

@@ -133,2 +141,13 @@ const ArrayPrototypeJoin = Function.prototype.call.bind(Array.prototype.join) as Primordial<Array<any>, 'join'>;

T extends 'weakref' ? BaseObj : never;
interface Keypress { sequence: string, name: string, ctrl: boolean, meta: boolean, shift: boolean }
enum Modifier {
NONE = 0b000,
CTRL = 0b001,
ALT = 0b010,
SHIFT = 0b100,
CTRL_ALT = CTRL | ALT,
CTRL_SHIFT = CTRL | SHIFT,
ALT_SHIFT = ALT | SHIFT,
CTRL_ALT_SHIFT = CTRL | ALT | SHIFT,
}

@@ -274,3 +293,2 @@ /** Convert a {@link WebSocket.onmessage} `event.data` value to a string. */

const promptReuseBuffer = Buffer.allocUnsafe(0xFFFF);
const stdoutWrite = process.stdout.write.bind(process.stdout);
globalThis.prompt = function prompt(question: string = 'Prompt', defaultValue: unknown = null): string | null {

@@ -524,2 +542,31 @@ stdoutWrite(question + ' ');

// Regex used for ANSI escape code splitting
// Adopted from https://github.com/chalk/ansi-regex/blob/HEAD/index.js
// License: MIT, authors: @sindresorhus, Qix-, arjunmehta and LitoMore
// Matches all ansi escape code sequences in a string
const ansiPattern =
"[\\u001B\\u009B][[\\]()#;?]*" +
"(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*" +
"|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)" +
"|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))";
const ansi = new RegExp(ansiPattern, "g");
/** Remove all VT control characters. Use to estimate displayed string width. */
function stripVTControlCharacters(str: string) {
return RegExpPrototypeSymbolReplace(ansi, str, '' as unknown as (substring: string, ...args: any[]) => string);
}
function rlRefresh(rl: readline.Interface) {
// @ts-expect-error "internal" function
rl._refreshLine(); // eslint-disable-line @typescript-eslint/no-unsafe-call
}
function rlLineInsert(rl: readline.Interface, insert: string, cutoff = 0) {
const { line, cursor } = rl;
const middle = cursor - cutoff;
const lineStart = StringPrototypeSlice(line, 0, middle < 0 ? 0 : middle);
const lineEnd = StringPrototypeSlice(line, cursor);
ReflectSet(rl, 'line', lineStart + insert + lineEnd);
ReflectSet(rl, 'cursor', cursor + insert.length - (middle < 0 ? 0 : cutoff));
rlRefresh(rl);
}
export default {

@@ -609,2 +656,74 @@ async start(singleshotCode?: string, printSingleshot = false) {

//* Only primordials should be used beyond this point!
const multiline = { enabled: false, lines: [] as string[] };
const toggleMultiline = () => {
multiline.enabled = !multiline.enabled;
multiline.lines = [];
if (multiline.enabled) {
rl.setPrompt(`${$.purple}(m)${$.reset} ` + rl.getPrompt());
console.log(
StringPadEnd(
`\r${$.gray}Multi-line mode enabled. End a line with "${$.whiteBright}.${$.gray}" to send.${$.reset}`,
rl.line.length + rl.getPrompt().length
) +
StringRepeat('\n', [...StringMatchAll(rl.line, '\n' as unknown as RegExp)].length)
);
}
else {
rl.setPrompt(process.env.BUN_REPL_PROMPT ?? '> ');
console.log(
StringPadEnd(`\r${$.gray}Multi-line mode disabled.${$.reset}`, rl.line.length + rl.getPrompt().length) +
StringRepeat('\n', [...StringMatchAll(rl.line, '\n' as unknown as RegExp)].length)
);
}
rlRefresh(rl);
};
process.stdin.on('keypress', (char: string, key: Keypress) => {
let modifier: Modifier = Modifier.NONE;
if (key.ctrl) modifier |= Modifier.CTRL;
if (key.meta) modifier |= Modifier.ALT;
if (key.shift) modifier |= Modifier.SHIFT;
if (modifier === Modifier.NONE) {
if (key.name === 'tab') {
// refuse to place the tab in preparation for autocompletion
return rlLineInsert(rl, '', 1);
}
}
else if (modifier === Modifier.SHIFT) switch (key.name) {
case 'tab': {
rlLineInsert(rl, ' ');
} break;
default: return;
}
else if (modifier === Modifier.ALT) switch (key.name) {
case 'n': {
if (!multiline.enabled) rlLineInsert(rl, '\n');
else {
const { line, cursor } = rl;
ReflectSet(rl, 'line', StringPrototypeSlice(line, 0, cursor));
rlRefresh(rl);
rl.write('\n');
ReflectSet(rl, 'line', StringPrototypeSlice(line, cursor));
rlRefresh(rl);
}
} break;
case 'm': {
toggleMultiline();
} break;
default: return;
}
else if (modifier === Modifier.CTRL) switch (key.name) {
default: return;
}
else if (modifier === Modifier.ALT_SHIFT) switch (key.name) {
// TODO: readline.moveCursor is broken ("TypeError: undefined is not a function")
case 'up': {
//readline.moveCursor(process.stdin, 0, -1, () => void 0);
} break;
case 'down': {
//readline.moveCursor(process.stdin, 0, 1, () => void 0);
} break;
default: return;
}
});
rl.on('SIGINT', () => {

@@ -628,7 +747,9 @@ if (rl.line.length === 0) rl.close();

history.lines = newHistory;
});
});
rl.on('line', async line => {
line = StringTrim(line);
if (!line) return rl.prompt();
if (line[0] === '.') {
if (
(line[0] === '.' && multiline.lines.length === 0 && !RegExpTest(/\d/, line[1]))
) {
switch (line) {

@@ -638,6 +759,12 @@ case '.help': {

`Commands & keybinds:\n` +
` .help Show this help message.\n` +
` .info Print extra REPL information.\n` +
` .clear Clear the screen. ${$.gray}(Ctrl+L)${$.reset}\n` +
` .exit Exit the REPL. ${$.gray}(Ctrl+C / Ctrl+D)${$.reset}`
` .help Show this help message.\n` +
` .info Print extra REPL information.\n` +
` .multiline Toggle multi-line mode. ${$.gray}(Alt+M)${$.reset}\n` +
` .clear Clear the screen. ${$.gray}(Ctrl+L)${$.reset}\n` +
` .exit Exit the REPL. ${$.gray}(Ctrl+C / Ctrl+D)${$.reset}\n` +
`\n` +
` Alt+N Insert a raw newline at cursor position, works even in single-line mode.\n` +
` ${$.dim}* In multi-line mode, ${$.noDim+$.gray}Enter${$.reset+$.dim} can only append newline to the end of the input.${$.reset}\n` +
` Alt+M Toggle multi-line mode.\n` +
` Shift+Tab Insert an indent instead of triggering autocompletions (autocomplete not yet implemented).`
);

@@ -653,2 +780,5 @@ } break;

} break;
case '.multiline': {
toggleMultiline();
} break;
case '.clear': {

@@ -668,2 +798,19 @@ console.clear();

} else {
if (multiline.enabled) {
if (line[line.length - 1] === '.') {
ArrayPush(multiline.lines, StringPrototypeSlice(line, 0, -1));
line = ArrayPrototypeJoin(multiline.lines, '\n');
multiline.lines = [];
rl.setPrompt(`${$.purple}(m)${$.reset} ` + (process.env.BUN_REPL_PROMPT ?? '> '));
//rlRefresh(rl);
} else {
ArrayPush(multiline.lines, line);
const promptLineNo = `${$.dim}${multiline.lines.length + 1} | ${$.reset}`;
const stripped = stripVTControlCharacters(promptLineNo);
const padded = StringPadStart(stripped, stripVTControlCharacters(rl.getPrompt()).length);
rl.setPrompt(StringRepeat(' ', padded.length - stripped.length) + promptLineNo);
rlRefresh(rl);
return;
}
}
let code: string = line;

@@ -681,2 +828,3 @@ try {

);
if (IS_DEBUG) console.error(e);
exit(0);

@@ -683,0 +831,0 @@ }

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc