Skip to content

Commit

Permalink
Add Recent History to SSH Quick Open
Browse files Browse the repository at this point in the history
  • Loading branch information
sedwards2009 committed Jan 3, 2025
1 parent 1c8459c commit 75e91c7
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 11 deletions.
34 changes: 33 additions & 1 deletion extensions/SSHQuickOpen/src/SSHQuickOpenExtension.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,38 @@
/*
* Copyright 2024 Simon Edwards <[email protected]>
* Copyright 2025 Simon Edwards <[email protected]>
*
* This source code is licensed under the MIT license which is detailed in the LICENSE.txt file.
*/
import { ExtensionContext, Logger, SessionConfiguration } from '@extraterm/extraterm-extension-api';
import { createUuid } from "extraterm-uuid";

// Most Recently Used list length.
const MRU_LENGTH = 10;
interface Config {
mru: string[];
}

let log: Logger = null;
let context: ExtensionContext = null;
let config: Config = null;


export function activate(_context: ExtensionContext): any {
context = _context;
log = context.logger;
loadConfig();
context.commands.registerCommand("ssh-quick-open:open", quickOpenCommand);
}

function loadConfig(): void {
config = context.configuration.get();
if (config == null) {
config = {
mru: []
};
}
}

// Note: This is mostly duplicated in SSHSessionEditorExtension.ts.
interface SSHSessionConfiguration extends SessionConfiguration {
host?: string;
Expand All @@ -29,15 +45,31 @@ async function quickOpenCommand(): Promise<void> {
const sshConnectionString = await context.activeTab.showTextInput({
message: "Enter a SSH connection string:",
value: "",
suggestions: config.mru
});
if (sshConnectionString == null) {
return;
}

updateMRU(sshConnectionString);

const sshSessionConfiguration = parseConnectionString(sshConnectionString);
context.commands.executeCommand("extraterm:window.newTerminal", {sessionConfiguration: sshSessionConfiguration});
}

function updateMRU(sshConnectionString: string): void {
const index = config.mru.indexOf(sshConnectionString);
if (index !== -1) {
config.mru.splice(index, 1);
}
config.mru.unshift(sshConnectionString);

if (config.mru.length > MRU_LENGTH) {
config.mru = config.mru.slice(0, MRU_LENGTH);
}
context.configuration.set(config);
}

function parseConnectionString(sshConnectionString: string): SSHSessionConfiguration {
let username: string = null;

Expand Down
1 change: 1 addition & 0 deletions main/src/ThemeTestUtility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ function main(): void {

ComboBox({items: ["One", "Two"]}),
ComboBox({items: ["Disabled One", "Disabled Two"], enabled: false}),
ComboBox({editable: true, items: []}),

Widget({layout:
BoxLayout({
Expand Down
58 changes: 49 additions & 9 deletions main/src/extension/TextInputPopOver.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
/*
* Copyright 2023 Simon Edwards <[email protected]>
* Copyright 2025 Simon Edwards <[email protected]>
*
* This source code is licensed under the MIT license which is detailed in the LICENSE.txt file.
*/
import * as ExtensionApi from "@extraterm/extraterm-extension-api";
import { Logger, log, getLogger } from "extraterm-logging";
import { Logger, getLogger } from "extraterm-logging";
import { doLater } from "extraterm-timeoutqt";
import { Label, LineEdit } from "qt-construct";
import { ComboBox, Label, LineEdit } from "qt-construct";
import { Window } from "../Window.js";
import { UiStyle } from "../ui/UiStyle.js";
import { WindowPopOver } from "../ui/WindowPopOver.js";
import { Direction, Key, QKeyEvent, QLabel, QLineEdit, QPushButton, QRect, TextFormat } from "@nodegui/nodegui";
import { Direction, Key, QComboBox, QKeyEvent, QLabel, QLineEdit, QRect, TextFormat } from "@nodegui/nodegui";
import { BoxLayout, Widget } from "qt-construct";


Expand All @@ -19,11 +19,18 @@ export interface TextInputPopOverOptions extends ExtensionApi.TextInputOptions {
aroundRect?: QRect;
}

enum TextInputPopOverMode {
TEXT,
COMBO_BOX
}

export class TextInputPopOver {
private _log: Logger = null;
#uiStyle: UiStyle = null;
#messageLabel: QLabel = null;
#mode = TextInputPopOverMode.TEXT;
#lineEdit: QLineEdit = null;
#comboBox: QComboBox = null;
#windowPopOver: WindowPopOver = null;
#containingRect: QRect = null;

Expand All @@ -47,6 +54,13 @@ export class TextInputPopOver {
wordWrap: true,
openExternalLinks: true
}),
this.#comboBox = ComboBox({
items: [],
editable: true,
onKeyPress: (nativeEvent) => {
this.#handleKeyPress(new QKeyEvent(nativeEvent));
},
}),
this.#lineEdit = LineEdit({
onKeyPress: (nativeEvent) => {
this.#handleKeyPress(new QKeyEvent(nativeEvent));
Expand All @@ -67,9 +81,13 @@ export class TextInputPopOver {
const key = event.key();
if (key === Key.Key_Enter || key === Key.Key_Return) {
event.accept();
this.#lineEdit.setEventProcessed(true);
this.#sendResult(this.#lineEdit.text());
return;
if (this.#mode === TextInputPopOverMode.COMBO_BOX) {
this.#comboBox.setEventProcessed(true);
this.#sendResult(this.#comboBox.currentText());
} else {
this.#lineEdit.setEventProcessed(true);
this.#sendResult(this.#lineEdit.text());
}
}
}

Expand Down Expand Up @@ -102,7 +120,24 @@ export class TextInputPopOver {
this.#messageLabel.setTextFormat(TextFormat.RichText);
}

this.#lineEdit.setText(options.value ?? "");
this.#mode = (options.suggestions ?? []).length === 0 ? TextInputPopOverMode.TEXT :TextInputPopOverMode.COMBO_BOX;
const isComboBox = this.#mode === TextInputPopOverMode.COMBO_BOX;

if (isComboBox) {
this.#lineEdit.hide();
this.#comboBox.show();

this.#comboBox.clear();
for (const item of options.suggestions) {
this.#comboBox.addItem(undefined, item, undefined);
}
this.#comboBox.setCurrentText(options.value ?? "");

} else {
this.#comboBox.hide();
this.#lineEdit.show();
this.#lineEdit.setText(options.value ?? "");
}

if (options.aroundRect != null) {
const screenGeometry = window.getWidget().windowHandle().screen().geometry();
Expand All @@ -118,7 +153,12 @@ export class TextInputPopOver {
});

this.#windowPopOver.show();
this.#lineEdit.setFocus();

if (isComboBox) {
this.#comboBox.setFocus();
} else {
this.#lineEdit.setFocus();
}

return new Promise<string | undefined>((resolve, reject) => {
this.#resolveFunc = resolve;
Expand Down
2 changes: 1 addition & 1 deletion main/src/ui/styles/DarkTwo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { blue, darken, green, hsl, lighten, lightness, mix, red, rgba, saturate,
import { createIcon } from "../Icons.js";
import { IconPair, UiStyle } from "../UiStyle.js";
import { TitleBarStyle } from "../../config/Config.js";
import { Color } from "packages/extraterm-color-utilities/dist/ColorUtilities.js";
import { Color } from "extraterm-color-utilities";


function toRgba(color: string): number {
Expand Down
1 change: 1 addition & 0 deletions packages/extraterm-extension-api/src/Tab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,5 @@ export interface TextInputOptions {
value: string;
placeholder?: string;
password?: boolean;
suggestions?: string[];
}

0 comments on commit 75e91c7

Please sign in to comment.