@austinthesing/magic-shell 0.2.5 → 0.2.8
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/dist/cli.js +635 -37
- package/dist/index.js +17 -0
- package/dist/tui.js +635 -37
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -20475,6 +20475,523 @@ class EditBufferRenderable extends Renderable {
|
|
|
20475
20475
|
}
|
|
20476
20476
|
}
|
|
20477
20477
|
}
|
|
20478
|
+
var defaultTextareaKeybindings = [
|
|
20479
|
+
{ name: "left", action: "move-left" },
|
|
20480
|
+
{ name: "right", action: "move-right" },
|
|
20481
|
+
{ name: "up", action: "move-up" },
|
|
20482
|
+
{ name: "down", action: "move-down" },
|
|
20483
|
+
{ name: "left", shift: true, action: "select-left" },
|
|
20484
|
+
{ name: "right", shift: true, action: "select-right" },
|
|
20485
|
+
{ name: "up", shift: true, action: "select-up" },
|
|
20486
|
+
{ name: "down", shift: true, action: "select-down" },
|
|
20487
|
+
{ name: "home", action: "buffer-home" },
|
|
20488
|
+
{ name: "end", action: "buffer-end" },
|
|
20489
|
+
{ name: "home", shift: true, action: "select-buffer-home" },
|
|
20490
|
+
{ name: "end", shift: true, action: "select-buffer-end" },
|
|
20491
|
+
{ name: "a", ctrl: true, action: "line-home" },
|
|
20492
|
+
{ name: "e", ctrl: true, action: "line-end" },
|
|
20493
|
+
{ name: "a", ctrl: true, shift: true, action: "select-line-home" },
|
|
20494
|
+
{ name: "e", ctrl: true, shift: true, action: "select-line-end" },
|
|
20495
|
+
{ name: "a", meta: true, action: "visual-line-home" },
|
|
20496
|
+
{ name: "e", meta: true, action: "visual-line-end" },
|
|
20497
|
+
{ name: "a", meta: true, shift: true, action: "select-visual-line-home" },
|
|
20498
|
+
{ name: "e", meta: true, shift: true, action: "select-visual-line-end" },
|
|
20499
|
+
{ name: "f", ctrl: true, action: "move-right" },
|
|
20500
|
+
{ name: "b", ctrl: true, action: "move-left" },
|
|
20501
|
+
{ name: "w", ctrl: true, action: "delete-word-backward" },
|
|
20502
|
+
{ name: "backspace", ctrl: true, action: "delete-word-backward" },
|
|
20503
|
+
{ name: "d", meta: true, action: "delete-word-forward" },
|
|
20504
|
+
{ name: "delete", meta: true, action: "delete-word-forward" },
|
|
20505
|
+
{ name: "delete", ctrl: true, action: "delete-word-forward" },
|
|
20506
|
+
{ name: "d", ctrl: true, shift: true, action: "delete-line" },
|
|
20507
|
+
{ name: "k", ctrl: true, action: "delete-to-line-end" },
|
|
20508
|
+
{ name: "u", ctrl: true, action: "delete-to-line-start" },
|
|
20509
|
+
{ name: "backspace", action: "backspace" },
|
|
20510
|
+
{ name: "backspace", shift: true, action: "backspace" },
|
|
20511
|
+
{ name: "d", ctrl: true, action: "delete" },
|
|
20512
|
+
{ name: "delete", action: "delete" },
|
|
20513
|
+
{ name: "delete", shift: true, action: "delete" },
|
|
20514
|
+
{ name: "return", action: "newline" },
|
|
20515
|
+
{ name: "linefeed", action: "newline" },
|
|
20516
|
+
{ name: "return", meta: true, action: "submit" },
|
|
20517
|
+
{ name: "-", ctrl: true, action: "undo" },
|
|
20518
|
+
{ name: ".", ctrl: true, action: "redo" },
|
|
20519
|
+
{ name: "z", super: true, action: "undo" },
|
|
20520
|
+
{ name: "z", super: true, shift: true, action: "redo" },
|
|
20521
|
+
{ name: "f", meta: true, action: "word-forward" },
|
|
20522
|
+
{ name: "b", meta: true, action: "word-backward" },
|
|
20523
|
+
{ name: "right", meta: true, action: "word-forward" },
|
|
20524
|
+
{ name: "left", meta: true, action: "word-backward" },
|
|
20525
|
+
{ name: "right", ctrl: true, action: "word-forward" },
|
|
20526
|
+
{ name: "left", ctrl: true, action: "word-backward" },
|
|
20527
|
+
{ name: "f", meta: true, shift: true, action: "select-word-forward" },
|
|
20528
|
+
{ name: "b", meta: true, shift: true, action: "select-word-backward" },
|
|
20529
|
+
{ name: "right", meta: true, shift: true, action: "select-word-forward" },
|
|
20530
|
+
{ name: "left", meta: true, shift: true, action: "select-word-backward" },
|
|
20531
|
+
{ name: "backspace", meta: true, action: "delete-word-backward" },
|
|
20532
|
+
{ name: "left", super: true, action: "visual-line-home" },
|
|
20533
|
+
{ name: "right", super: true, action: "visual-line-end" },
|
|
20534
|
+
{ name: "up", super: true, action: "buffer-home" },
|
|
20535
|
+
{ name: "down", super: true, action: "buffer-end" },
|
|
20536
|
+
{ name: "left", super: true, shift: true, action: "select-visual-line-home" },
|
|
20537
|
+
{ name: "right", super: true, shift: true, action: "select-visual-line-end" },
|
|
20538
|
+
{ name: "up", super: true, shift: true, action: "select-buffer-home" },
|
|
20539
|
+
{ name: "down", super: true, shift: true, action: "select-buffer-end" }
|
|
20540
|
+
];
|
|
20541
|
+
|
|
20542
|
+
class TextareaRenderable extends EditBufferRenderable {
|
|
20543
|
+
_placeholder;
|
|
20544
|
+
_unfocusedBackgroundColor;
|
|
20545
|
+
_unfocusedTextColor;
|
|
20546
|
+
_focusedBackgroundColor;
|
|
20547
|
+
_focusedTextColor;
|
|
20548
|
+
_keyBindingsMap;
|
|
20549
|
+
_keyAliasMap;
|
|
20550
|
+
_keyBindings;
|
|
20551
|
+
_actionHandlers;
|
|
20552
|
+
_initialValueSet = false;
|
|
20553
|
+
_submitListener = undefined;
|
|
20554
|
+
static defaults = {
|
|
20555
|
+
backgroundColor: "transparent",
|
|
20556
|
+
textColor: "#FFFFFF",
|
|
20557
|
+
focusedBackgroundColor: "transparent",
|
|
20558
|
+
focusedTextColor: "#FFFFFF",
|
|
20559
|
+
placeholder: null
|
|
20560
|
+
};
|
|
20561
|
+
constructor(ctx, options) {
|
|
20562
|
+
const defaults = TextareaRenderable.defaults;
|
|
20563
|
+
const baseOptions = {
|
|
20564
|
+
...options,
|
|
20565
|
+
backgroundColor: options.backgroundColor || defaults.backgroundColor,
|
|
20566
|
+
textColor: options.textColor || defaults.textColor
|
|
20567
|
+
};
|
|
20568
|
+
super(ctx, baseOptions);
|
|
20569
|
+
this._unfocusedBackgroundColor = parseColor(options.backgroundColor || defaults.backgroundColor);
|
|
20570
|
+
this._unfocusedTextColor = parseColor(options.textColor || defaults.textColor);
|
|
20571
|
+
this._focusedBackgroundColor = parseColor(options.focusedBackgroundColor || options.backgroundColor || defaults.focusedBackgroundColor);
|
|
20572
|
+
this._focusedTextColor = parseColor(options.focusedTextColor || options.textColor || defaults.focusedTextColor);
|
|
20573
|
+
this._placeholder = options.placeholder ?? defaults.placeholder;
|
|
20574
|
+
this._keyAliasMap = mergeKeyAliases(defaultKeyAliases, options.keyAliasMap || {});
|
|
20575
|
+
this._keyBindings = options.keyBindings || [];
|
|
20576
|
+
const mergedBindings = mergeKeyBindings(defaultTextareaKeybindings, this._keyBindings);
|
|
20577
|
+
this._keyBindingsMap = buildKeyBindingsMap(mergedBindings, this._keyAliasMap);
|
|
20578
|
+
this._actionHandlers = this.buildActionHandlers();
|
|
20579
|
+
this._submitListener = options.onSubmit;
|
|
20580
|
+
if (options.initialValue) {
|
|
20581
|
+
this.setText(options.initialValue);
|
|
20582
|
+
this._initialValueSet = true;
|
|
20583
|
+
}
|
|
20584
|
+
this.updateColors();
|
|
20585
|
+
this.applyPlaceholder(this._placeholder);
|
|
20586
|
+
}
|
|
20587
|
+
applyPlaceholder(placeholder) {
|
|
20588
|
+
if (placeholder === null) {
|
|
20589
|
+
this.editorView.setPlaceholderStyledText([]);
|
|
20590
|
+
return;
|
|
20591
|
+
}
|
|
20592
|
+
if (typeof placeholder === "string") {
|
|
20593
|
+
const defaultGray = fg("#666666");
|
|
20594
|
+
const chunks = [defaultGray(placeholder)];
|
|
20595
|
+
this.editorView.setPlaceholderStyledText(chunks);
|
|
20596
|
+
} else {
|
|
20597
|
+
this.editorView.setPlaceholderStyledText(placeholder.chunks);
|
|
20598
|
+
}
|
|
20599
|
+
}
|
|
20600
|
+
buildActionHandlers() {
|
|
20601
|
+
return new Map([
|
|
20602
|
+
["move-left", () => this.moveCursorLeft()],
|
|
20603
|
+
["move-right", () => this.moveCursorRight()],
|
|
20604
|
+
["move-up", () => this.moveCursorUp()],
|
|
20605
|
+
["move-down", () => this.moveCursorDown()],
|
|
20606
|
+
["select-left", () => this.moveCursorLeft({ select: true })],
|
|
20607
|
+
["select-right", () => this.moveCursorRight({ select: true })],
|
|
20608
|
+
["select-up", () => this.moveCursorUp({ select: true })],
|
|
20609
|
+
["select-down", () => this.moveCursorDown({ select: true })],
|
|
20610
|
+
["line-home", () => this.gotoLineHome()],
|
|
20611
|
+
["line-end", () => this.gotoLineEnd()],
|
|
20612
|
+
["select-line-home", () => this.gotoLineHome({ select: true })],
|
|
20613
|
+
["select-line-end", () => this.gotoLineEnd({ select: true })],
|
|
20614
|
+
["visual-line-home", () => this.gotoVisualLineHome()],
|
|
20615
|
+
["visual-line-end", () => this.gotoVisualLineEnd()],
|
|
20616
|
+
["select-visual-line-home", () => this.gotoVisualLineHome({ select: true })],
|
|
20617
|
+
["select-visual-line-end", () => this.gotoVisualLineEnd({ select: true })],
|
|
20618
|
+
["select-buffer-home", () => this.gotoBufferHome({ select: true })],
|
|
20619
|
+
["select-buffer-end", () => this.gotoBufferEnd({ select: true })],
|
|
20620
|
+
["buffer-home", () => this.gotoBufferHome()],
|
|
20621
|
+
["buffer-end", () => this.gotoBufferEnd()],
|
|
20622
|
+
["delete-line", () => this.deleteLine()],
|
|
20623
|
+
["delete-to-line-end", () => this.deleteToLineEnd()],
|
|
20624
|
+
["delete-to-line-start", () => this.deleteToLineStart()],
|
|
20625
|
+
["backspace", () => this.deleteCharBackward()],
|
|
20626
|
+
["delete", () => this.deleteChar()],
|
|
20627
|
+
["newline", () => this.newLine()],
|
|
20628
|
+
["undo", () => this.undo()],
|
|
20629
|
+
["redo", () => this.redo()],
|
|
20630
|
+
["word-forward", () => this.moveWordForward()],
|
|
20631
|
+
["word-backward", () => this.moveWordBackward()],
|
|
20632
|
+
["select-word-forward", () => this.moveWordForward({ select: true })],
|
|
20633
|
+
["select-word-backward", () => this.moveWordBackward({ select: true })],
|
|
20634
|
+
["delete-word-forward", () => this.deleteWordForward()],
|
|
20635
|
+
["delete-word-backward", () => this.deleteWordBackward()],
|
|
20636
|
+
["submit", () => this.submit()]
|
|
20637
|
+
]);
|
|
20638
|
+
}
|
|
20639
|
+
handlePaste(event) {
|
|
20640
|
+
this.insertText(event.text);
|
|
20641
|
+
}
|
|
20642
|
+
handleKeyPress(key) {
|
|
20643
|
+
const bindingKey = getKeyBindingKey({
|
|
20644
|
+
name: key.name,
|
|
20645
|
+
ctrl: key.ctrl,
|
|
20646
|
+
shift: key.shift,
|
|
20647
|
+
meta: key.meta,
|
|
20648
|
+
super: key.super,
|
|
20649
|
+
action: "move-left"
|
|
20650
|
+
});
|
|
20651
|
+
const action = this._keyBindingsMap.get(bindingKey);
|
|
20652
|
+
if (action) {
|
|
20653
|
+
const handler = this._actionHandlers.get(action);
|
|
20654
|
+
if (handler) {
|
|
20655
|
+
return handler();
|
|
20656
|
+
}
|
|
20657
|
+
}
|
|
20658
|
+
if (!key.ctrl && !key.meta && !key.super && !key.hyper) {
|
|
20659
|
+
if (key.name === "space") {
|
|
20660
|
+
this.insertText(" ");
|
|
20661
|
+
return true;
|
|
20662
|
+
}
|
|
20663
|
+
if (key.sequence) {
|
|
20664
|
+
const firstCharCode = key.sequence.charCodeAt(0);
|
|
20665
|
+
if (firstCharCode < 32) {
|
|
20666
|
+
return false;
|
|
20667
|
+
}
|
|
20668
|
+
if (firstCharCode === 127) {
|
|
20669
|
+
return false;
|
|
20670
|
+
}
|
|
20671
|
+
this.insertText(key.sequence);
|
|
20672
|
+
return true;
|
|
20673
|
+
}
|
|
20674
|
+
}
|
|
20675
|
+
return false;
|
|
20676
|
+
}
|
|
20677
|
+
updateColors() {
|
|
20678
|
+
const effectiveBg = this._focused ? this._focusedBackgroundColor : this._unfocusedBackgroundColor;
|
|
20679
|
+
const effectiveFg = this._focused ? this._focusedTextColor : this._unfocusedTextColor;
|
|
20680
|
+
super.backgroundColor = effectiveBg;
|
|
20681
|
+
super.textColor = effectiveFg;
|
|
20682
|
+
}
|
|
20683
|
+
insertChar(char) {
|
|
20684
|
+
if (this.hasSelection()) {
|
|
20685
|
+
this.deleteSelectedText();
|
|
20686
|
+
}
|
|
20687
|
+
this.editBuffer.insertChar(char);
|
|
20688
|
+
this.requestRender();
|
|
20689
|
+
}
|
|
20690
|
+
insertText(text) {
|
|
20691
|
+
if (this.hasSelection()) {
|
|
20692
|
+
this.deleteSelectedText();
|
|
20693
|
+
}
|
|
20694
|
+
this.editBuffer.insertText(text);
|
|
20695
|
+
this.requestRender();
|
|
20696
|
+
}
|
|
20697
|
+
deleteChar() {
|
|
20698
|
+
if (this.hasSelection()) {
|
|
20699
|
+
this.deleteSelectedText();
|
|
20700
|
+
return true;
|
|
20701
|
+
}
|
|
20702
|
+
this._ctx.clearSelection();
|
|
20703
|
+
this.editBuffer.deleteChar();
|
|
20704
|
+
this.requestRender();
|
|
20705
|
+
return true;
|
|
20706
|
+
}
|
|
20707
|
+
deleteCharBackward() {
|
|
20708
|
+
if (this.hasSelection()) {
|
|
20709
|
+
this.deleteSelectedText();
|
|
20710
|
+
return true;
|
|
20711
|
+
}
|
|
20712
|
+
this._ctx.clearSelection();
|
|
20713
|
+
this.editBuffer.deleteCharBackward();
|
|
20714
|
+
this.requestRender();
|
|
20715
|
+
return true;
|
|
20716
|
+
}
|
|
20717
|
+
deleteSelectedText() {
|
|
20718
|
+
this.editorView.deleteSelectedText();
|
|
20719
|
+
this._ctx.clearSelection();
|
|
20720
|
+
this.requestRender();
|
|
20721
|
+
}
|
|
20722
|
+
newLine() {
|
|
20723
|
+
this._ctx.clearSelection();
|
|
20724
|
+
this.editBuffer.newLine();
|
|
20725
|
+
this.requestRender();
|
|
20726
|
+
return true;
|
|
20727
|
+
}
|
|
20728
|
+
deleteLine() {
|
|
20729
|
+
this._ctx.clearSelection();
|
|
20730
|
+
this.editBuffer.deleteLine();
|
|
20731
|
+
this.requestRender();
|
|
20732
|
+
return true;
|
|
20733
|
+
}
|
|
20734
|
+
moveCursorLeft(options) {
|
|
20735
|
+
const select = options?.select ?? false;
|
|
20736
|
+
this.updateSelectionForMovement(select, true);
|
|
20737
|
+
this.editBuffer.moveCursorLeft();
|
|
20738
|
+
this.updateSelectionForMovement(select, false);
|
|
20739
|
+
this.requestRender();
|
|
20740
|
+
return true;
|
|
20741
|
+
}
|
|
20742
|
+
moveCursorRight(options) {
|
|
20743
|
+
const select = options?.select ?? false;
|
|
20744
|
+
this.updateSelectionForMovement(select, true);
|
|
20745
|
+
this.editBuffer.moveCursorRight();
|
|
20746
|
+
this.updateSelectionForMovement(select, false);
|
|
20747
|
+
this.requestRender();
|
|
20748
|
+
return true;
|
|
20749
|
+
}
|
|
20750
|
+
moveCursorUp(options) {
|
|
20751
|
+
const select = options?.select ?? false;
|
|
20752
|
+
this.updateSelectionForMovement(select, true);
|
|
20753
|
+
this.editorView.moveUpVisual();
|
|
20754
|
+
this.updateSelectionForMovement(select, false);
|
|
20755
|
+
this.requestRender();
|
|
20756
|
+
return true;
|
|
20757
|
+
}
|
|
20758
|
+
moveCursorDown(options) {
|
|
20759
|
+
const select = options?.select ?? false;
|
|
20760
|
+
this.updateSelectionForMovement(select, true);
|
|
20761
|
+
this.editorView.moveDownVisual();
|
|
20762
|
+
this.updateSelectionForMovement(select, false);
|
|
20763
|
+
this.requestRender();
|
|
20764
|
+
return true;
|
|
20765
|
+
}
|
|
20766
|
+
gotoLine(line) {
|
|
20767
|
+
this.editBuffer.gotoLine(line);
|
|
20768
|
+
this.requestRender();
|
|
20769
|
+
}
|
|
20770
|
+
gotoLineHome(options) {
|
|
20771
|
+
const select = options?.select ?? false;
|
|
20772
|
+
this.updateSelectionForMovement(select, true);
|
|
20773
|
+
const cursor = this.editorView.getCursor();
|
|
20774
|
+
if (cursor.col === 0 && cursor.row > 0) {
|
|
20775
|
+
this.editBuffer.setCursor(cursor.row - 1, 0);
|
|
20776
|
+
const prevLineEol = this.editBuffer.getEOL();
|
|
20777
|
+
this.editBuffer.setCursor(prevLineEol.row, prevLineEol.col);
|
|
20778
|
+
} else {
|
|
20779
|
+
this.editBuffer.setCursor(cursor.row, 0);
|
|
20780
|
+
}
|
|
20781
|
+
this.updateSelectionForMovement(select, false);
|
|
20782
|
+
this.requestRender();
|
|
20783
|
+
return true;
|
|
20784
|
+
}
|
|
20785
|
+
gotoLineEnd(options) {
|
|
20786
|
+
const select = options?.select ?? false;
|
|
20787
|
+
this.updateSelectionForMovement(select, true);
|
|
20788
|
+
const cursor = this.editorView.getCursor();
|
|
20789
|
+
const eol = this.editBuffer.getEOL();
|
|
20790
|
+
const lineCount = this.editBuffer.getLineCount();
|
|
20791
|
+
if (cursor.col === eol.col && cursor.row < lineCount - 1) {
|
|
20792
|
+
this.editBuffer.setCursor(cursor.row + 1, 0);
|
|
20793
|
+
} else {
|
|
20794
|
+
this.editBuffer.setCursor(eol.row, eol.col);
|
|
20795
|
+
}
|
|
20796
|
+
this.updateSelectionForMovement(select, false);
|
|
20797
|
+
this.requestRender();
|
|
20798
|
+
return true;
|
|
20799
|
+
}
|
|
20800
|
+
gotoVisualLineHome(options) {
|
|
20801
|
+
const select = options?.select ?? false;
|
|
20802
|
+
this.updateSelectionForMovement(select, true);
|
|
20803
|
+
const sol = this.editorView.getVisualSOL();
|
|
20804
|
+
this.editBuffer.setCursor(sol.logicalRow, sol.logicalCol);
|
|
20805
|
+
this.updateSelectionForMovement(select, false);
|
|
20806
|
+
this.requestRender();
|
|
20807
|
+
return true;
|
|
20808
|
+
}
|
|
20809
|
+
gotoVisualLineEnd(options) {
|
|
20810
|
+
const select = options?.select ?? false;
|
|
20811
|
+
this.updateSelectionForMovement(select, true);
|
|
20812
|
+
const eol = this.editorView.getVisualEOL();
|
|
20813
|
+
this.editBuffer.setCursor(eol.logicalRow, eol.logicalCol);
|
|
20814
|
+
this.updateSelectionForMovement(select, false);
|
|
20815
|
+
this.requestRender();
|
|
20816
|
+
return true;
|
|
20817
|
+
}
|
|
20818
|
+
gotoBufferHome(options) {
|
|
20819
|
+
const select = options?.select ?? false;
|
|
20820
|
+
this.updateSelectionForMovement(select, true);
|
|
20821
|
+
this.editBuffer.setCursor(0, 0);
|
|
20822
|
+
this.updateSelectionForMovement(select, false);
|
|
20823
|
+
this.requestRender();
|
|
20824
|
+
return true;
|
|
20825
|
+
}
|
|
20826
|
+
gotoBufferEnd(options) {
|
|
20827
|
+
const select = options?.select ?? false;
|
|
20828
|
+
this.updateSelectionForMovement(select, true);
|
|
20829
|
+
this.editBuffer.gotoLine(999999);
|
|
20830
|
+
this.updateSelectionForMovement(select, false);
|
|
20831
|
+
this.requestRender();
|
|
20832
|
+
return true;
|
|
20833
|
+
}
|
|
20834
|
+
deleteToLineEnd() {
|
|
20835
|
+
const cursor = this.editorView.getCursor();
|
|
20836
|
+
const eol = this.editBuffer.getEOL();
|
|
20837
|
+
if (eol.col > cursor.col) {
|
|
20838
|
+
this.editBuffer.deleteRange(cursor.row, cursor.col, eol.row, eol.col);
|
|
20839
|
+
}
|
|
20840
|
+
this.requestRender();
|
|
20841
|
+
return true;
|
|
20842
|
+
}
|
|
20843
|
+
deleteToLineStart() {
|
|
20844
|
+
const cursor = this.editorView.getCursor();
|
|
20845
|
+
if (cursor.col > 0) {
|
|
20846
|
+
this.editBuffer.deleteRange(cursor.row, 0, cursor.row, cursor.col);
|
|
20847
|
+
}
|
|
20848
|
+
this.requestRender();
|
|
20849
|
+
return true;
|
|
20850
|
+
}
|
|
20851
|
+
undo() {
|
|
20852
|
+
this._ctx.clearSelection();
|
|
20853
|
+
this.editBuffer.undo();
|
|
20854
|
+
this.requestRender();
|
|
20855
|
+
return true;
|
|
20856
|
+
}
|
|
20857
|
+
redo() {
|
|
20858
|
+
this._ctx.clearSelection();
|
|
20859
|
+
this.editBuffer.redo();
|
|
20860
|
+
this.requestRender();
|
|
20861
|
+
return true;
|
|
20862
|
+
}
|
|
20863
|
+
moveWordForward(options) {
|
|
20864
|
+
const select = options?.select ?? false;
|
|
20865
|
+
this.updateSelectionForMovement(select, true);
|
|
20866
|
+
const nextWord = this.editBuffer.getNextWordBoundary();
|
|
20867
|
+
this.editBuffer.setCursorByOffset(nextWord.offset);
|
|
20868
|
+
this.updateSelectionForMovement(select, false);
|
|
20869
|
+
this.requestRender();
|
|
20870
|
+
return true;
|
|
20871
|
+
}
|
|
20872
|
+
moveWordBackward(options) {
|
|
20873
|
+
const select = options?.select ?? false;
|
|
20874
|
+
this.updateSelectionForMovement(select, true);
|
|
20875
|
+
const prevWord = this.editBuffer.getPrevWordBoundary();
|
|
20876
|
+
this.editBuffer.setCursorByOffset(prevWord.offset);
|
|
20877
|
+
this.updateSelectionForMovement(select, false);
|
|
20878
|
+
this.requestRender();
|
|
20879
|
+
return true;
|
|
20880
|
+
}
|
|
20881
|
+
deleteWordForward() {
|
|
20882
|
+
if (this.hasSelection()) {
|
|
20883
|
+
this.deleteSelectedText();
|
|
20884
|
+
return true;
|
|
20885
|
+
}
|
|
20886
|
+
const currentCursor = this.editBuffer.getCursorPosition();
|
|
20887
|
+
const nextWord = this.editBuffer.getNextWordBoundary();
|
|
20888
|
+
if (nextWord.offset > currentCursor.offset) {
|
|
20889
|
+
this.editBuffer.deleteRange(currentCursor.row, currentCursor.col, nextWord.row, nextWord.col);
|
|
20890
|
+
}
|
|
20891
|
+
this._ctx.clearSelection();
|
|
20892
|
+
this.requestRender();
|
|
20893
|
+
return true;
|
|
20894
|
+
}
|
|
20895
|
+
deleteWordBackward() {
|
|
20896
|
+
if (this.hasSelection()) {
|
|
20897
|
+
this.deleteSelectedText();
|
|
20898
|
+
return true;
|
|
20899
|
+
}
|
|
20900
|
+
const currentCursor = this.editBuffer.getCursorPosition();
|
|
20901
|
+
const prevWord = this.editBuffer.getPrevWordBoundary();
|
|
20902
|
+
if (prevWord.offset < currentCursor.offset) {
|
|
20903
|
+
this.editBuffer.deleteRange(prevWord.row, prevWord.col, currentCursor.row, currentCursor.col);
|
|
20904
|
+
}
|
|
20905
|
+
this._ctx.clearSelection();
|
|
20906
|
+
this.requestRender();
|
|
20907
|
+
return true;
|
|
20908
|
+
}
|
|
20909
|
+
focus() {
|
|
20910
|
+
super.focus();
|
|
20911
|
+
this.updateColors();
|
|
20912
|
+
}
|
|
20913
|
+
blur() {
|
|
20914
|
+
super.blur();
|
|
20915
|
+
if (!this.isDestroyed) {
|
|
20916
|
+
this.updateColors();
|
|
20917
|
+
}
|
|
20918
|
+
}
|
|
20919
|
+
get placeholder() {
|
|
20920
|
+
return this._placeholder;
|
|
20921
|
+
}
|
|
20922
|
+
set placeholder(value) {
|
|
20923
|
+
if (this._placeholder !== value) {
|
|
20924
|
+
this._placeholder = value;
|
|
20925
|
+
this.applyPlaceholder(value);
|
|
20926
|
+
this.requestRender();
|
|
20927
|
+
}
|
|
20928
|
+
}
|
|
20929
|
+
get backgroundColor() {
|
|
20930
|
+
return this._unfocusedBackgroundColor;
|
|
20931
|
+
}
|
|
20932
|
+
set backgroundColor(value) {
|
|
20933
|
+
const newColor = parseColor(value ?? TextareaRenderable.defaults.backgroundColor);
|
|
20934
|
+
if (this._unfocusedBackgroundColor !== newColor) {
|
|
20935
|
+
this._unfocusedBackgroundColor = newColor;
|
|
20936
|
+
this.updateColors();
|
|
20937
|
+
}
|
|
20938
|
+
}
|
|
20939
|
+
get textColor() {
|
|
20940
|
+
return this._unfocusedTextColor;
|
|
20941
|
+
}
|
|
20942
|
+
set textColor(value) {
|
|
20943
|
+
const newColor = parseColor(value ?? TextareaRenderable.defaults.textColor);
|
|
20944
|
+
if (this._unfocusedTextColor !== newColor) {
|
|
20945
|
+
this._unfocusedTextColor = newColor;
|
|
20946
|
+
this.updateColors();
|
|
20947
|
+
}
|
|
20948
|
+
}
|
|
20949
|
+
set focusedBackgroundColor(value) {
|
|
20950
|
+
const newColor = parseColor(value ?? TextareaRenderable.defaults.focusedBackgroundColor);
|
|
20951
|
+
if (this._focusedBackgroundColor !== newColor) {
|
|
20952
|
+
this._focusedBackgroundColor = newColor;
|
|
20953
|
+
this.updateColors();
|
|
20954
|
+
}
|
|
20955
|
+
}
|
|
20956
|
+
set focusedTextColor(value) {
|
|
20957
|
+
const newColor = parseColor(value ?? TextareaRenderable.defaults.focusedTextColor);
|
|
20958
|
+
if (this._focusedTextColor !== newColor) {
|
|
20959
|
+
this._focusedTextColor = newColor;
|
|
20960
|
+
this.updateColors();
|
|
20961
|
+
}
|
|
20962
|
+
}
|
|
20963
|
+
set initialValue(value) {
|
|
20964
|
+
if (!this._initialValueSet) {
|
|
20965
|
+
this.setText(value);
|
|
20966
|
+
this._initialValueSet = true;
|
|
20967
|
+
}
|
|
20968
|
+
}
|
|
20969
|
+
submit() {
|
|
20970
|
+
if (this._submitListener) {
|
|
20971
|
+
this._submitListener({});
|
|
20972
|
+
}
|
|
20973
|
+
return true;
|
|
20974
|
+
}
|
|
20975
|
+
set onSubmit(handler) {
|
|
20976
|
+
this._submitListener = handler;
|
|
20977
|
+
}
|
|
20978
|
+
get onSubmit() {
|
|
20979
|
+
return this._submitListener;
|
|
20980
|
+
}
|
|
20981
|
+
set keyBindings(bindings) {
|
|
20982
|
+
this._keyBindings = bindings;
|
|
20983
|
+
const mergedBindings = mergeKeyBindings(defaultTextareaKeybindings, bindings);
|
|
20984
|
+
this._keyBindingsMap = buildKeyBindingsMap(mergedBindings, this._keyAliasMap);
|
|
20985
|
+
}
|
|
20986
|
+
set keyAliasMap(aliases) {
|
|
20987
|
+
this._keyAliasMap = mergeKeyAliases(defaultKeyAliases, aliases);
|
|
20988
|
+
const mergedBindings = mergeKeyBindings(defaultTextareaKeybindings, this._keyBindings);
|
|
20989
|
+
this._keyBindingsMap = buildKeyBindingsMap(mergedBindings, this._keyAliasMap);
|
|
20990
|
+
}
|
|
20991
|
+
get extmarks() {
|
|
20992
|
+
return this.editorView.extmarks;
|
|
20993
|
+
}
|
|
20994
|
+
}
|
|
20478
20995
|
|
|
20479
20996
|
// src/cli.ts
|
|
20480
20997
|
import { spawn } from "child_process";
|
|
@@ -22106,6 +22623,8 @@ var headerText;
|
|
|
22106
22623
|
var statusBarText;
|
|
22107
22624
|
var chatScrollBox;
|
|
22108
22625
|
var inputField;
|
|
22626
|
+
var inputContainer;
|
|
22627
|
+
var inputHintText;
|
|
22109
22628
|
var helpBarText;
|
|
22110
22629
|
var modelSelector = null;
|
|
22111
22630
|
var providerSelector = null;
|
|
@@ -22333,59 +22852,75 @@ function createMainUI() {
|
|
|
22333
22852
|
});
|
|
22334
22853
|
mainContainer.add(chatScrollBox);
|
|
22335
22854
|
addSystemMessage(getWelcomeMessage());
|
|
22336
|
-
|
|
22337
|
-
id: "input-
|
|
22338
|
-
flexDirection: "
|
|
22855
|
+
inputContainer = new BoxRenderable(renderer, {
|
|
22856
|
+
id: "input-container",
|
|
22857
|
+
flexDirection: "column",
|
|
22339
22858
|
width: "100%",
|
|
22340
22859
|
marginTop: 1,
|
|
22341
|
-
|
|
22342
|
-
|
|
22343
|
-
|
|
22344
|
-
|
|
22345
|
-
|
|
22346
|
-
|
|
22347
|
-
|
|
22348
|
-
|
|
22860
|
+
border: true,
|
|
22861
|
+
borderColor: theme.colors.primary,
|
|
22862
|
+
borderStyle: "rounded",
|
|
22863
|
+
paddingLeft: 1,
|
|
22864
|
+
paddingRight: 1,
|
|
22865
|
+
paddingTop: 0,
|
|
22866
|
+
paddingBottom: 0,
|
|
22867
|
+
backgroundColor: theme.colors.backgroundPanel
|
|
22349
22868
|
});
|
|
22350
|
-
|
|
22351
|
-
inputField = new
|
|
22869
|
+
mainContainer.add(inputContainer);
|
|
22870
|
+
inputField = new TextareaRenderable(renderer, {
|
|
22352
22871
|
id: "input-field",
|
|
22353
|
-
|
|
22354
|
-
height:
|
|
22355
|
-
placeholder: "
|
|
22872
|
+
width: "100%",
|
|
22873
|
+
height: 3,
|
|
22874
|
+
placeholder: t`${fg(theme.colors.textMuted)("Describe what you want to do...")}`,
|
|
22356
22875
|
backgroundColor: "transparent",
|
|
22357
|
-
focusedBackgroundColor:
|
|
22876
|
+
focusedBackgroundColor: "transparent",
|
|
22358
22877
|
textColor: theme.colors.text,
|
|
22359
|
-
|
|
22360
|
-
|
|
22361
|
-
|
|
22362
|
-
|
|
22878
|
+
keyBindings: [
|
|
22879
|
+
{ name: "return", action: "submit" },
|
|
22880
|
+
{ name: "linefeed", action: "submit" },
|
|
22881
|
+
{ name: "return", shift: true, action: "newline" },
|
|
22882
|
+
{ name: "linefeed", shift: true, action: "newline" },
|
|
22883
|
+
{ name: "return", meta: true, action: "submit" }
|
|
22884
|
+
],
|
|
22885
|
+
onSubmit: () => {
|
|
22886
|
+
const value = inputField.editBuffer.getText();
|
|
22887
|
+
handleInput(value);
|
|
22363
22888
|
}
|
|
22364
22889
|
});
|
|
22365
|
-
|
|
22890
|
+
inputContainer.add(inputField);
|
|
22891
|
+
inputHintText = new TextRenderable(renderer, {
|
|
22892
|
+
id: "input-hint",
|
|
22893
|
+
content: getInputHintContent()
|
|
22894
|
+
});
|
|
22895
|
+
inputContainer.add(inputHintText);
|
|
22366
22896
|
helpBarText = new TextRenderable(renderer, {
|
|
22367
22897
|
id: "help-bar-text",
|
|
22368
22898
|
content: getHelpBarContent(),
|
|
22369
22899
|
marginTop: 1
|
|
22370
22900
|
});
|
|
22371
22901
|
mainContainer.add(helpBarText);
|
|
22372
|
-
inputField.on(InputRenderableEvents.ENTER, handleInput);
|
|
22373
22902
|
renderer.keyInput.on("keypress", handleKeypress);
|
|
22374
22903
|
inputField.focus();
|
|
22375
22904
|
}
|
|
22376
22905
|
function getStatusBarContent() {
|
|
22377
22906
|
const theme = getTheme();
|
|
22378
22907
|
const providerName = config.provider === "opencode-zen" ? "OpenCode Zen" : "OpenRouter";
|
|
22379
|
-
const safeModeIndicator = dryRunMode ? fg(theme.colors.warning)("[DRY RUN]") :
|
|
22908
|
+
const safeModeIndicator = dryRunMode ? fg(theme.colors.warning)("[DRY RUN]") : "";
|
|
22909
|
+
const safetyLevelColor = config.safetyLevel === "strict" ? theme.colors.warning : config.safetyLevel === "relaxed" ? theme.colors.error : theme.colors.success;
|
|
22910
|
+
const safetyIndicator = fg(safetyLevelColor)(`[${config.safetyLevel}]`);
|
|
22380
22911
|
const repoContextIndicator = config.repoContext ? fg(theme.colors.info)("[Repo]") : "";
|
|
22381
|
-
return t`${fg(theme.colors.textMuted)("Provider:")} ${fg(theme.colors.text)(providerName)} ${fg(theme.colors.textMuted)("Model:")} ${fg(theme.colors.text)(currentModel.name)} ${safeModeIndicator}${repoContextIndicator ? " " : ""}${repoContextIndicator}`;
|
|
22912
|
+
return t`${fg(theme.colors.textMuted)("Provider:")} ${fg(theme.colors.text)(providerName)} ${fg(theme.colors.textMuted)("Model:")} ${fg(theme.colors.text)(currentModel.name)} ${safetyIndicator}${safeModeIndicator ? " " : ""}${safeModeIndicator}${repoContextIndicator ? " " : ""}${repoContextIndicator}`;
|
|
22382
22913
|
}
|
|
22383
22914
|
function getHelpBarContent() {
|
|
22384
22915
|
const theme = getTheme();
|
|
22385
22916
|
if (awaitingConfirmation) {
|
|
22386
22917
|
return t`${fg(theme.colors.warning)(">>> Press Enter to execute command <<<")} ${fg(theme.colors.textMuted)("|")} ${fg(theme.colors.error)("Esc")}${fg(theme.colors.textMuted)(" Cancel")} ${fg(theme.colors.primary)("e")}${fg(theme.colors.textMuted)(" Edit")} ${fg(theme.colors.primary)("c")}${fg(theme.colors.textMuted)(" Copy")}`;
|
|
22387
22918
|
}
|
|
22388
|
-
return t`${fg(theme.colors.
|
|
22919
|
+
return t`${fg(theme.colors.primary)("Ctrl+X P")}${fg(theme.colors.textMuted)(" Commands")} ${fg(theme.colors.primary)("Ctrl+Y")}${fg(theme.colors.textMuted)(" Safety")} ${fg(theme.colors.primary)("Ctrl+Z")}${fg(theme.colors.textMuted)(" Exit")}`;
|
|
22920
|
+
}
|
|
22921
|
+
function getInputHintContent() {
|
|
22922
|
+
const theme = getTheme();
|
|
22923
|
+
return t`${fg(theme.colors.textMuted)("Enter")}${fg(theme.colors.border)(" send")} ${fg(theme.colors.textMuted)("Shift+Enter")}${fg(theme.colors.border)(" newline")} ${fg(theme.colors.textMuted)("!")}${fg(theme.colors.border)(" shell")}`;
|
|
22389
22924
|
}
|
|
22390
22925
|
function getWelcomeMessage() {
|
|
22391
22926
|
const providerName = config.provider === "opencode-zen" ? "OpenCode Zen" : "OpenRouter";
|
|
@@ -22647,17 +23182,23 @@ function refreshThemeColors() {
|
|
|
22647
23182
|
};
|
|
22648
23183
|
}
|
|
22649
23184
|
if (inputField) {
|
|
22650
|
-
inputField.focusedBackgroundColor =
|
|
23185
|
+
inputField.focusedBackgroundColor = "transparent";
|
|
22651
23186
|
inputField.textColor = theme.colors.text;
|
|
22652
|
-
inputField.
|
|
22653
|
-
|
|
23187
|
+
inputField.placeholder = t`${fg(theme.colors.textMuted)("Describe what you want to do...")}`;
|
|
23188
|
+
}
|
|
23189
|
+
if (inputContainer) {
|
|
23190
|
+
inputContainer.borderColor = theme.colors.primary;
|
|
23191
|
+
inputContainer.backgroundColor = theme.colors.backgroundPanel;
|
|
23192
|
+
}
|
|
23193
|
+
if (inputHintText) {
|
|
23194
|
+
inputHintText.content = getInputHintContent();
|
|
22654
23195
|
}
|
|
22655
23196
|
}
|
|
22656
23197
|
async function handleInput(value) {
|
|
22657
23198
|
const input = value.trim();
|
|
22658
23199
|
if (!input)
|
|
22659
23200
|
return;
|
|
22660
|
-
inputField.
|
|
23201
|
+
inputField.setText("");
|
|
22661
23202
|
if (input.startsWith("!")) {
|
|
22662
23203
|
await handleSpecialCommand(input);
|
|
22663
23204
|
return;
|
|
@@ -22850,16 +23391,22 @@ function clearChat() {
|
|
|
22850
23391
|
addSystemMessage(getWelcomeMessage());
|
|
22851
23392
|
}
|
|
22852
23393
|
function showHelp() {
|
|
22853
|
-
const helpText = `
|
|
23394
|
+
const helpText = `Direct Shortcuts:
|
|
23395
|
+
Ctrl+Y Cycle safety level (strict/moderate/relaxed)
|
|
23396
|
+
Ctrl+Z Exit magic-shell
|
|
23397
|
+
Ctrl+C Cancel / Close popup
|
|
23398
|
+
|
|
23399
|
+
Chord Shortcuts (Ctrl+X then...):
|
|
22854
23400
|
P Command palette M Change model
|
|
22855
23401
|
S Switch provider D Toggle dry-run
|
|
22856
23402
|
T Change theme R Toggle repo context
|
|
22857
23403
|
H Show history L Clear chat
|
|
22858
23404
|
C Show config ? This help
|
|
22859
|
-
Q Exit
|
|
22860
23405
|
|
|
22861
|
-
|
|
22862
|
-
|
|
23406
|
+
Safety Levels:
|
|
23407
|
+
- strict: Confirm ALL potentially dangerous commands
|
|
23408
|
+
- moderate: Confirm high/critical severity commands (default)
|
|
23409
|
+
- relaxed: Only confirm critical commands
|
|
22863
23410
|
|
|
22864
23411
|
Tips:
|
|
22865
23412
|
- Type naturally: "list all files" -> ls -la
|
|
@@ -23148,6 +23695,26 @@ function getCommandPaletteOptions() {
|
|
|
23148
23695
|
addSystemMessage(`Dry-run mode: ${dryRunMode ? "ON" : "OFF"}`);
|
|
23149
23696
|
}
|
|
23150
23697
|
},
|
|
23698
|
+
{
|
|
23699
|
+
name: "Cycle Safety Level",
|
|
23700
|
+
description: `Current: ${config.safetyLevel}`,
|
|
23701
|
+
key: "y",
|
|
23702
|
+
chord: "y",
|
|
23703
|
+
action: () => {
|
|
23704
|
+
const levels = ["moderate", "strict", "relaxed"];
|
|
23705
|
+
const currentIndex = levels.indexOf(config.safetyLevel);
|
|
23706
|
+
const nextIndex = (currentIndex + 1) % levels.length;
|
|
23707
|
+
config.safetyLevel = levels[nextIndex];
|
|
23708
|
+
saveConfig(config);
|
|
23709
|
+
statusBarText.content = getStatusBarContent();
|
|
23710
|
+
const descriptions = {
|
|
23711
|
+
strict: "confirms ALL potentially dangerous commands",
|
|
23712
|
+
moderate: "confirms high/critical severity commands",
|
|
23713
|
+
relaxed: "only confirms critical commands"
|
|
23714
|
+
};
|
|
23715
|
+
addSystemMessage(`Safety level: ${config.safetyLevel} (${descriptions[config.safetyLevel]})`);
|
|
23716
|
+
}
|
|
23717
|
+
},
|
|
23151
23718
|
{
|
|
23152
23719
|
name: "Toggle Project Context",
|
|
23153
23720
|
description: config.repoContext ? "Currently ON (sends script names to AI)" : "Currently OFF",
|
|
@@ -23270,6 +23837,25 @@ function closeCommandPalette() {
|
|
|
23270
23837
|
}
|
|
23271
23838
|
function handleKeypress(key) {
|
|
23272
23839
|
const commands = getCommandPaletteOptions();
|
|
23840
|
+
if (key.ctrl && key.name === "y") {
|
|
23841
|
+
const levels = ["moderate", "strict", "relaxed"];
|
|
23842
|
+
const currentIndex = levels.indexOf(config.safetyLevel);
|
|
23843
|
+
const nextIndex = (currentIndex + 1) % levels.length;
|
|
23844
|
+
config.safetyLevel = levels[nextIndex];
|
|
23845
|
+
saveConfig(config);
|
|
23846
|
+
statusBarText.content = getStatusBarContent();
|
|
23847
|
+
const descriptions = {
|
|
23848
|
+
strict: "confirms ALL potentially dangerous commands",
|
|
23849
|
+
moderate: "confirms high/critical severity commands",
|
|
23850
|
+
relaxed: "only confirms critical commands"
|
|
23851
|
+
};
|
|
23852
|
+
addSystemMessage(`Safety level: ${config.safetyLevel} (${descriptions[config.safetyLevel]})`);
|
|
23853
|
+
return;
|
|
23854
|
+
}
|
|
23855
|
+
if (key.ctrl && key.name === "z") {
|
|
23856
|
+
renderer.destroy();
|
|
23857
|
+
process.exit(0);
|
|
23858
|
+
}
|
|
23273
23859
|
if (key.ctrl && key.name === "x") {
|
|
23274
23860
|
chordMode = "ctrl-x";
|
|
23275
23861
|
return;
|
|
@@ -23308,12 +23894,24 @@ function handleKeypress(key) {
|
|
|
23308
23894
|
inputField.focus();
|
|
23309
23895
|
return;
|
|
23310
23896
|
}
|
|
23897
|
+
if (themeSelector) {
|
|
23898
|
+
renderer.root.remove("theme-selector-container");
|
|
23899
|
+
themeSelector = null;
|
|
23900
|
+
inputField.focus();
|
|
23901
|
+
return;
|
|
23902
|
+
}
|
|
23903
|
+
if (awaitingConfirmation && pendingMessageId) {
|
|
23904
|
+
clearCommandState();
|
|
23905
|
+
addSystemMessage("Command cancelled.");
|
|
23906
|
+
inputField.focus();
|
|
23907
|
+
return;
|
|
23908
|
+
}
|
|
23311
23909
|
if (providerSelector) {
|
|
23312
23910
|
renderer.destroy();
|
|
23313
23911
|
process.exit(0);
|
|
23314
23912
|
}
|
|
23315
|
-
|
|
23316
|
-
|
|
23913
|
+
addSystemMessage("Press Ctrl+Z to exit.");
|
|
23914
|
+
return;
|
|
23317
23915
|
}
|
|
23318
23916
|
if (key.name === "escape") {
|
|
23319
23917
|
chordMode = "none";
|
|
@@ -23345,7 +23943,7 @@ function handleKeypress(key) {
|
|
|
23345
23943
|
if (key.name === "e" && awaitingConfirmation && pendingMessageId) {
|
|
23346
23944
|
const msg = chatMessages.find((m) => m.id === pendingMessageId);
|
|
23347
23945
|
if (msg && msg.command) {
|
|
23348
|
-
inputField.
|
|
23946
|
+
inputField.setText(msg.command);
|
|
23349
23947
|
clearCommandState();
|
|
23350
23948
|
inputField.focus();
|
|
23351
23949
|
}
|