dsh-neotui 0.1.9 → 0.1.10

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/widgets.js +21 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-neotui",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Neo-TUI: mouse-driven terminal UI client for DeepSeek Harness (B-tier per dsh-tui-design.md)",
5
5
  "type": "module",
6
6
  "bin": {
package/src/widgets.js CHANGED
@@ -433,6 +433,7 @@ export class Input extends Widget {
433
433
  const row = start + Math.max(0, Math.min(h - 1, ev.y - this.y));
434
434
  const rx = ev.x - this.x - (row === 0 ? strWidth(this.prompt) : 1);
435
435
  this.cursor = this.#indexAtVisual(row, Math.max(0, rx));
436
+ this.#snapCursor();
436
437
  } else {
437
438
  const rx = ev.x - this.x - strWidth(this.prompt);
438
439
  let w = 0, idx = 0;
@@ -443,11 +444,25 @@ export class Input extends Widget {
443
444
  idx++;
444
445
  }
445
446
  this.cursor = idx;
447
+ this.#snapCursor();
446
448
  }
447
449
  return true;
448
450
  }
449
451
  return false;
450
452
  }
453
+ /** The paste token is a single cursor unit: the caret never rests inside
454
+ * its span — LEFT from the end hops to its start, RIGHT from the start
455
+ * hops to its end, and clicks/moves snap to the nearest boundary.
456
+ * dir: -1 = leftward movement → start, +1 = rightward → end, 0 = nearest. */
457
+ #snapCursor(dir = 0) {
458
+ const m = this.pasteMark;
459
+ if (!m) return;
460
+ if (this.cursor > m.start && this.cursor < m.end) {
461
+ if (dir < 0) this.cursor = m.start;
462
+ else if (dir > 0) this.cursor = m.end;
463
+ else this.cursor = this.cursor - m.start < m.end - this.cursor ? m.start : m.end;
464
+ }
465
+ }
451
466
  /** Cancel the held-back paste AND its token. */
452
467
  #touch() { this.pendingPaste = null; this.pasteMark = null; }
453
468
  /** Claude-Code-style two-stage paste: the first Ctrl+Shift+V of a large
@@ -490,23 +505,25 @@ export class Input extends Widget {
490
505
  case "delete":
491
506
  if (this.cursor < this.#cps().length) { this.#edit(this.cursor, this.cursor + 1); this.onChange?.(); }
492
507
  return true;
493
- case "left": this.selectAll = false; this.cursor = Math.max(0, this.cursor - 1); return true;
494
- case "right": this.selectAll = false; this.cursor = Math.min(this.#cps().length, this.cursor + 1); return true;
508
+ case "left": this.selectAll = false; this.cursor = Math.max(0, this.cursor - 1); this.#snapCursor(-1); return true;
509
+ case "right": this.selectAll = false; this.cursor = Math.min(this.#cps().length, this.cursor + 1); this.#snapCursor(1); return true;
495
510
  case "home": {
496
511
  if (this.multi) { const rows = this.#visualRows(); const { row } = this.#cursorVisual(); this.cursor = rows[row].start; }
497
512
  else this.cursor = 0;
513
+ this.#snapCursor();
498
514
  return true;
499
515
  }
500
516
  case "end": {
501
517
  if (this.multi) { const rows = this.#visualRows(); const { row } = this.#cursorVisual(); this.cursor = rows[row].end; }
502
518
  else this.cursor = this.#cps().length;
519
+ this.#snapCursor();
503
520
  return true;
504
521
  }
505
522
  case "up":
506
523
  if (this.multi) {
507
524
  const rows = this.#visualRows();
508
525
  const { row, col } = this.#cursorVisual();
509
- if (row > 0) this.cursor = this.#indexAtVisual(row - 1, col);
526
+ if (row > 0) { this.cursor = this.#indexAtVisual(row - 1, col); this.#snapCursor(); }
510
527
  } else if (this.history.length) {
511
528
  this.histIdx = this.histIdx < 0 ? this.history.length - 1 : Math.max(0, this.histIdx - 1);
512
529
  this.setValue(this.history[this.histIdx] ?? "");
@@ -516,7 +533,7 @@ export class Input extends Widget {
516
533
  if (this.multi) {
517
534
  const rows = this.#visualRows();
518
535
  const { row, col } = this.#cursorVisual();
519
- if (row < rows.length - 1) this.cursor = this.#indexAtVisual(row + 1, col);
536
+ if (row < rows.length - 1) { this.cursor = this.#indexAtVisual(row + 1, col); this.#snapCursor(); }
520
537
  } else if (this.histIdx >= 0) {
521
538
  this.histIdx++;
522
539
  if (this.histIdx >= this.history.length) { this.histIdx = -1; this.setValue(""); }