rip-lang 2.9.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/repl.js CHANGED
@@ -30,7 +30,6 @@ const colors = {
30
30
  red: '\x1b[31m',
31
31
  green: '\x1b[32m',
32
32
  yellow: '\x1b[33m',
33
- blue: '\x1b[34m',
34
33
  magenta: '\x1b[35m',
35
34
  cyan: '\x1b[36m',
36
35
  gray: '\x1b[90m'
@@ -152,7 +151,7 @@ export class RipREPL {
152
151
  const c = {
153
152
  dependencies: new Set(),
154
153
  markDirty() {
155
- if (dead || locked || !dirty) { if (!dead && !locked && !dirty) { dirty = true; for (const s of subs) if (s.markDirty) s.markDirty(); for (const s of subs) if (!s.markDirty) ctx.__pendingEffects.add(s); } }
154
+ if (!dead && !locked && !dirty) { dirty = true; for (const s of subs) if (s.markDirty) s.markDirty(); for (const s of subs) if (!s.markDirty) ctx.__pendingEffects.add(s); }
156
155
  },
157
156
  get value() {
158
157
  if (dead) return v;
@@ -268,7 +267,6 @@ export class RipREPL {
268
267
 
269
268
  if (trimmed.endsWith('+') || trimmed.endsWith('-')) return false;
270
269
  if (trimmed.endsWith('*') && !trimmed.endsWith('**')) return false;
271
- if (trimmed.endsWith('/') && !trimmed.endsWith('//') && !/\/[gimsuvy]*$/.test(trimmed)) return false;
272
270
 
273
271
  return true;
274
272
  }
@@ -369,8 +367,8 @@ export class RipREPL {
369
367
  async moduleEval(js) {
370
368
  // Extract declared variables (both let and const)
371
369
  const declaredVars = new Set();
372
- for (const match of js.matchAll(/^let\s+(\w+)/gm)) {
373
- declaredVars.add(match[1]);
370
+ for (const match of js.matchAll(/^let\s+([^=]+);$/gm)) {
371
+ for (const name of match[1].split(/\s*,\s*/)) declaredVars.add(name.trim());
374
372
  }
375
373
  for (const match of js.matchAll(/^const\s+(\w+)\s*=/gm)) {
376
374
  declaredVars.add(match[1]);
@@ -405,8 +403,16 @@ export class RipREPL {
405
403
  const existingVars = Object.keys(this.vars);
406
404
  const existingNonReactive = existingVars.filter(v => !this.reactiveVars.has(v));
407
405
 
406
+ // Remove existing vars from hoisted let declarations (handles comma-separated)
407
+ const existingSet = new Set(existingNonReactive);
408
+ js = js.replace(/^let\s+([^=]+);$/gm, (match, varList) => {
409
+ const vars = varList.split(/\s*,\s*/);
410
+ const newVars = vars.filter(v => !existingSet.has(v));
411
+ if (newVars.length === 0) return '';
412
+ return `let ${newVars.join(', ')};`;
413
+ });
414
+ // Remove let from initialized existing vars: let x = → x =
408
415
  for (const v of existingNonReactive) {
409
- js = js.replace(new RegExp(`^let ${v};\\n?`, 'm'), '');
410
416
  js = js.replace(new RegExp(`^let ${v}(\\s*=)`, 'm'), `${v}$1`);
411
417
  }
412
418
 
@@ -609,9 +615,10 @@ ${colors.cyan}Tips:${colors.reset}
609
615
  }
610
616
 
611
617
  console.log(`${colors.bright}Command history:${colors.reset}`);
612
- this.history.slice(-20).forEach((cmd, i) => {
613
- const num = this.history.length - 20 + i + 1;
614
- console.log(` ${colors.gray}${num}:${colors.reset} ${cmd.replace(/\n/g, '⏎ ')}`);
618
+ const recent = this.history.slice(-20);
619
+ const startIdx = this.history.length - recent.length;
620
+ recent.forEach((cmd, i) => {
621
+ console.log(` ${colors.gray}${startIdx + i + 1}:${colors.reset} ${cmd.replace(/\n/g, '⏎ ')}`);
615
622
  });
616
623
  }
617
624