Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions frontend/app/view/term/term-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ export class TermViewModel implements ViewModel {
fontSizeAtom: jotai.Atom<number>;
termThemeNameAtom: jotai.Atom<string>;
termTransparencyAtom: jotai.Atom<number>;
termBPMAtom: jotai.Atom<boolean>;
noPadding: jotai.PrimitiveAtom<boolean>;
endIconButtons: jotai.Atom<IconButtonDecl[]>;
shellProcFullStatus: jotai.PrimitiveAtom<BlockControllerRuntimeStatus>;
shellProcStatus: jotai.Atom<string>;
shellProcStatusUnsubFn: () => void;
termBPMUnsubFn: () => void;
isCmdController: jotai.Atom<boolean>;
isRestarting: jotai.PrimitiveAtom<boolean>;
searchAtoms?: SearchAtoms;
Expand Down Expand Up @@ -204,6 +206,7 @@ export class TermViewModel implements ViewModel {
return true;
});
this.filterOutNowsh = jotai.atom(false);
this.termBPMAtom = getOverrideConfigAtom(blockId, "term:allowbracketedpaste");
this.termThemeNameAtom = useBlockAtom(blockId, "termthemeatom", () => {
return jotai.atom<string>((get) => {
return get(getOverrideConfigAtom(this.blockId, "term:theme")) ?? DefaultTermTheme;
Expand Down Expand Up @@ -313,6 +316,12 @@ export class TermViewModel implements ViewModel {
const fullStatus = get(this.shellProcFullStatus);
return fullStatus?.shellprocstatus ?? "init";
});
this.termBPMUnsubFn = globalStore.sub(this.termBPMAtom, () => {
if (this.termRef.current?.terminal) {
const allowBPM = globalStore.get(this.termBPMAtom) ?? true;
this.termRef.current.terminal.options.ignoreBracketedPasteMode = !allowBPM;
}
});
}

getShellIntegrationIconButton(get: jotai.Getter): IconButtonDecl | null {
Expand Down Expand Up @@ -447,6 +456,9 @@ export class TermViewModel implements ViewModel {
if (this.shellProcStatusUnsubFn) {
this.shellProcStatusUnsubFn();
}
if (this.termBPMUnsubFn) {
this.termBPMUnsubFn();
}
}

giveFocus(): boolean {
Expand Down Expand Up @@ -579,6 +591,7 @@ export class TermViewModel implements ViewModel {
const termThemeKeys = Object.keys(termThemes);
const curThemeName = globalStore.get(getBlockMetaKeyAtom(this.blockId, "term:theme"));
const defaultFontSize = globalStore.get(getSettingsKeyAtom("term:fontsize")) ?? 12;
const defaultAllowBracketedPaste = globalStore.get(getSettingsKeyAtom("term:allowbracketedpaste")) ?? true;
const transparencyMeta = globalStore.get(getBlockMetaKeyAtom(this.blockId, "term:transparency"));
const blockData = globalStore.get(this.blockAtom);
const overrideFontSize = blockData?.meta?.["term:fontsize"];
Expand Down Expand Up @@ -674,6 +687,45 @@ export class TermViewModel implements ViewModel {
label: "Transparency",
submenu: transparencySubMenu,
});
const allowBracketedPaste = blockData?.meta?.["term:allowbracketedpaste"];
fullMenu.push({
label: "Allow Bracketed Paste Mode",
submenu: [
{
label: "Default (" + (defaultAllowBracketedPaste ? "On" : "Off") + ")",
type: "checkbox",
checked: allowBracketedPaste == null,
click: () => {
RpcApi.SetMetaCommand(TabRpcClient, {
oref: WOS.makeORef("block", this.blockId),
meta: { "term:allowbracketedpaste": null },
});
},
},
{
label: "On",
type: "checkbox",
checked: allowBracketedPaste === true,
click: () => {
RpcApi.SetMetaCommand(TabRpcClient, {
oref: WOS.makeORef("block", this.blockId),
meta: { "term:allowbracketedpaste": true },
});
},
},
{
label: "Off",
type: "checkbox",
checked: allowBracketedPaste === false,
click: () => {
RpcApi.SetMetaCommand(TabRpcClient, {
oref: WOS.makeORef("block", this.blockId),
meta: { "term:allowbracketedpaste": false },
});
},
},
],
});
fullMenu.push({ type: "separator" });
fullMenu.push({
label: "Force Restart Controller",
Expand Down
3 changes: 1 addition & 2 deletions frontend/app/view/term/term.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,6 @@ const TerminalView = ({ blockId, model }: ViewComponentProps<TermViewModel>) =>
const fullConfig = globalStore.get(atoms.fullConfigAtom);
const termThemeName = globalStore.get(model.termThemeNameAtom);
const termTransparency = globalStore.get(model.termTransparencyAtom);
const termBPMAtom = getOverrideConfigAtom(blockId, "term:allowbracketedpaste");
const termMacOptionIsMetaAtom = getOverrideConfigAtom(blockId, "term:macoptionismeta");
const [termTheme, _] = computeTheme(fullConfig, termThemeName, termTransparency);
let termScrollback = 2000;
Expand All @@ -261,7 +260,7 @@ const TerminalView = ({ blockId, model }: ViewComponentProps<TermViewModel>) =>
if (termScrollback > 50000) {
termScrollback = 50000;
}
const termAllowBPM = globalStore.get(termBPMAtom) ?? false;
const termAllowBPM = globalStore.get(model.termBPMAtom) ?? true;
const termMacOptionIsMeta = globalStore.get(termMacOptionIsMetaAtom) ?? false;
const wasFocused = model.termRef.current != null && globalStore.get(model.nodeModel.isFocused);
const termWrap = new TermWrap(
Expand Down
1 change: 1 addition & 0 deletions pkg/blockcontroller/shellcontroller.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ func (sc *ShellController) resetTerminalState(logCtx context.Context) {
buf.WriteString("\x1b[?25h") // show cursor
buf.WriteString("\x1b[?1000l") // disable mouse tracking
buf.WriteString("\x1b[?1007l") // disable alternate scroll mode
buf.WriteString("\x1b[?2004l") // disable bracketed paste mode
buf.WriteString(shellutil.FormatOSC(16162, "R")) // OSC 16162 "R" - disable alternate screen mode (only if active), reset "shell integration" status.
buf.WriteString("\r\n\r\n")
err := HandleAppendBlockFile(sc.BlockId, wavebase.BlockFile_Term, buf.Bytes())
Expand Down
Loading