Compare commits

..

5 Commits

23 changed files with 184 additions and 2487 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
if: matrix.platform == 'linux'
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends -y libarchive-tools libopenjp2-tools rpm snapcraft snapd
sudo apt-get install --no-install-recommends -y libarchive-tools libopenjp2-tools rpm
- uses: actions/setup-go@v5
with:
go-version: ${{env.GO_VERSION}}
+6
View File
@@ -53,6 +53,12 @@ Install modules (we use yarn):
yarn
```
Electron also requires specific builds of node_modules to work (because Electron embeds a specific node.js version that might not match your development node.js version). We use a special electron command to cross-compile those modules:
```
scripthaus run electron-rebuild
```
## Running WebPack
We use webpack to build both the React and Electron App Wrapper code. They are both run together using:
+1 -1
View File
@@ -20,7 +20,7 @@ Wave isn't just another terminal emulator; it's a rethink on how terminals are b
- CodeEdit, to edit local and remote files with a VSCode-like inline editor
- AI Integration with ChatGPT (or ChatGPT compatible APIs) to help write commands and get answers inline
![WaveTerm Screenshot](./assets/wave-screenshot.png)
![WaveTerm Screenshot](./assets/wave-screenshot.jpeg)
## Installation
+2 -2
View File
@@ -11,9 +11,9 @@ The license disclaimers for the backend are generated using the [go-licenses](ht
The license disclaimers for the frontend are generated using the [`yarn licenses` tool](https://classic.yarnpkg.com/lang/en/docs/cli/licenses/). This outputs to the file [`frontend.md`](./disclaimers/frontend.md).
These disclaimer files linked above will be periodically regenerated to reflect new dependencies.
These three disclaimer files linked above will be periodically regenerated to reflect new dependencies.
The [`scripthaus.md` file](../scripthaus.md) contains scripts to generate the disclaimers and package them. To manually generate the disclaimers, run the following from the repository root directory:
The [`scripthaus.md` file](../scripthaus.md) contains scripts to genrate the disclaimers and package them. To manually generate the disclaimers, run the following from the repository root directory:
```bash
scripthaus run generate-license-disclaimers
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -39,14 +39,6 @@
"command": "app:openTabSearchModal",
"keys": ["Cmd:p"]
},
{
"command": "app:openConnectionsView",
"keys": []
},
{
"command": "app:openSettingsView",
"keys": []
},
{
"command": "app:newTab",
"keys": ["Cmd:t"]
Binary file not shown.

After

Width:  |  Height:  |  Size: 306 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 KiB

+1 -20
View File
@@ -56,7 +56,6 @@ const config = {
arch: "universal",
},
],
appId: "dev.commandline.waveterm",
icon: "public/waveterm.icns",
category: "public.app-category.developer-tools",
minimumSystemVersion: "10.15.0",
@@ -71,11 +70,10 @@ const config = {
.map((f) => path.resolve(f.path, f.name)),
},
linux: {
appId: "dev.commandline.waveterm",
executableName: pkg.productName,
category: "TerminalEmulator",
icon: "public/waveterm.icns",
target: ["zip", "deb", "rpm", "AppImage", "pacman", "snap"],
target: ["zip", "deb", "rpm", "AppImage", "pacman"],
synopsis: pkg.description,
description: null,
desktop: {
@@ -88,23 +86,6 @@ const config = {
appImage: {
license: "LICENSE",
},
snap: {
base: "core20",
grade: "stable",
confinement: "classic",
summary: pkg.productName,
title: pkg.productName,
description: null,
synopsis: pkg.description,
allowNativeWayland: true,
desktop: {
Name: pkg.productName,
Comment: pkg.description,
Keywords: "developer;terminal;emulator;",
category: "Development;Utility;",
exec: pkg.productName,
},
},
publish: {
provider: "generic",
url: "https://dl.waveterm.dev/releases",
+2
View File
@@ -220,4 +220,6 @@
--modal-header-bottom-border-color: rgba(241, 246, 243, 0.15);
--logo-button-hover-bg-color: #1e1e1e;
--xterm-viewport-border-color: rgba(241, 246, 243, 0.15);
}
+2
View File
@@ -74,4 +74,6 @@
--toggle-thumb-color: var(--app-bg-color);
--logo-button-hover-bg-color: #f0f0f0;
--xterm-viewport-border-color: rgba(0, 0, 0, 0.3);
}
+1 -2
View File
@@ -3,7 +3,7 @@
:root {
/*
* term colors (16 + 5) form the base terminal theme
* term colors (16 + 2) form the base terminal theme
* for consistency these colors should be used by plugins/applications
*/
--term-black: #000000;
@@ -27,5 +27,4 @@
--term-cmdtext: #ffffff;
--term-foreground: #d3d7cf;
--term-background: #000000;
--term-selection-background: #ffffff40;
}
-1
View File
@@ -6,5 +6,4 @@
--term-foreground: #000000;
--term-background: #fefefe;
--term-cmdtext: #000000;
--term-selection-background: #00000018;
}
@@ -90,12 +90,25 @@
margin-top: 5px;
overflow-x: auto;
overflow-y: hidden;
border: 1px solid var(--app-border-color);
border-radius: 6px;
padding: 6px 10px;
.terminal-connectelem {
height: 163px !important; // Needed to override plugin height
.xterm-viewport {
display: flex;
padding: 6px 10px;
gap: 8px;
align-items: flex-start;
align-self: stretch;
border-radius: 6px;
border: 1px solid var(--xterm-viewport-border-color);
background: #080a08;
height: 163px !important; // Needed to override plugin height
}
.xterm-screen {
padding: 10px;
}
}
}
}
+18 -1
View File
@@ -355,6 +355,13 @@ function createMainWindow(clientData: ClientDataType | null): Electron.BrowserWi
e.preventDefault();
return;
}
if (checkKeyPressed(waveEvent, "Cmd:i")) {
e.preventDefault();
if (!input.alt) {
win.webContents.send("i-cmd", mods);
}
return;
}
if (checkKeyPressed(waveEvent, "Cmd:r")) {
e.preventDefault();
win.webContents.send("r-cmd", mods);
@@ -370,6 +377,16 @@ function createMainWindow(clientData: ClientDataType | null): Electron.BrowserWi
win.webContents.send("w-cmd", mods);
return;
}
if (checkKeyPressed(waveEvent, "Cmd:h")) {
win.webContents.send("h-cmd", mods);
e.preventDefault();
return;
}
if (checkKeyPressed(waveEvent, "Cmd:p")) {
win.webContents.send("p-cmd", mods);
e.preventDefault();
return;
}
if (checkKeyPressed(waveEvent, "Cmd:ArrowUp") || checkKeyPressed(waveEvent, "Cmd:ArrowDown")) {
if (checkKeyPressed(waveEvent, "Cmd:ArrowUp")) {
win.webContents.send("meta-arrowup");
@@ -388,7 +405,7 @@ function createMainWindow(clientData: ClientDataType | null): Electron.BrowserWi
e.preventDefault();
return;
}
if (input.code.startsWith("Digit") && input.meta && !input.control) {
if (input.code.startsWith("Digit") && input.meta) {
const digitNum = parseInt(input.code.substring(5));
if (isNaN(digitNum) || digitNum < 1 || digitNum > 9) {
return;
+3
View File
@@ -21,8 +21,11 @@ contextBridge.exposeInMainWorld("api", {
getAppUpdateStatus: () => ipcRenderer.sendSync("get-app-update-status"),
onAppUpdateStatus: (callback) => ipcRenderer.on("app-update-status", (_, val) => callback(val)),
onTCmd: (callback) => ipcRenderer.on("t-cmd", callback),
onICmd: (callback) => ipcRenderer.on("i-cmd", callback),
onLCmd: (callback) => ipcRenderer.on("l-cmd", callback),
onHCmd: (callback) => ipcRenderer.on("h-cmd", callback),
onWCmd: (callback) => ipcRenderer.on("w-cmd", callback),
onPCmd: (callback) => ipcRenderer.on("p-cmd", callback),
onRCmd: (callback) => ipcRenderer.on("r-cmd", callback),
onZoomChanged: (callback) => ipcRenderer.on("zoom-changed", callback),
onMetaArrowUp: (callback) => ipcRenderer.on("meta-arrowup", callback),
+57 -129
View File
@@ -36,7 +36,6 @@ import { Cmd } from "./cmd";
import { GlobalCommandRunner } from "./global";
import { clearMonoFontCache, getMonoFontSize } from "@/util/textmeasure";
import type { TermWrap } from "@/plugins/terminal/term";
import * as util from "@/util/util";
type SWLinePtr = {
line: LineType;
@@ -144,9 +143,6 @@ class Model {
});
this.ws.reconnect();
this.keybindManager = new KeybindManager();
this.readConfigKeybindings();
this.initSystemKeybindings();
this.initAppKeybindings();
this.inputModel = new InputModel(this);
this.pluginsModel = new PluginsModel(this);
this.bookmarksModel = new BookmarksModel(this);
@@ -175,8 +171,18 @@ class Model {
}
return fontSize;
});
this.keybindManager.registerKeybinding("system", "electron", "any", (waveEvent) => {
if (this.keybindManager.checkKeyPressed(waveEvent, "system:toggleDeveloperTools")) {
getApi().toggleDeveloperTools();
return true;
}
return false;
});
getApi().onTCmd(this.onTCmd.bind(this));
getApi().onICmd(this.onICmd.bind(this));
getApi().onLCmd(this.onLCmd.bind(this));
getApi().onHCmd(this.onHCmd.bind(this));
getApi().onPCmd(this.onPCmd.bind(this));
getApi().onWCmd(this.onWCmd.bind(this));
getApi().onRCmd(this.onRCmd.bind(this));
getApi().onZoomChanged(this.onZoomChanged.bind(this));
@@ -202,68 +208,6 @@ class Model {
};
}
readConfigKeybindings() {
const url = new URL(this.getBaseHostPort() + "/config/keybindings.json");
let prtn = fetch(url, { method: "get", body: null, headers: this.getFetchHeaders() });
prtn.then((resp) => {
if (resp.status == 404) {
return [];
} else if (!resp.ok) {
util.handleNotOkResp(resp, url);
}
return resp.json();
}).then((userKeybindings) => {
this.keybindManager.setUserKeybindings(userKeybindings);
});
}
initSystemKeybindings() {
this.keybindManager.registerKeybinding("system", "electron", "system:toggleDeveloperTools", (waveEvent) => {
getApi().toggleDeveloperTools();
return true;
});
}
initAppKeybindings() {
for (let index = 1; index <= 9; index++) {
this.keybindManager.registerKeybinding("app", "model", "app:selectWorkspace-" + index, (waveEvent) => {
this.onSwitchSessionCmd(index);
return true;
});
}
this.keybindManager.registerKeybinding("app", "model", "app:focusCmdInput", (waveEvent) => {
console.log("focus cmd input callback");
this.onFocusCmdInputPressed();
return true;
});
this.keybindManager.registerKeybinding("app", "model", "app:bookmarkActiveLine", (waveEvent) => {
this.onBookmarkViewPressed();
return true;
});
this.keybindManager.registerKeybinding("app", "model", "app:openHistory", (waveEvent) => {
this.onOpenHistoryPressed();
return true;
});
this.keybindManager.registerKeybinding("app", "model", "app:openTabSearchModal", (waveEvent) => {
this.onOpenTabSearchModalPressed();
return true;
});
this.keybindManager.registerKeybinding("app", "model", "app:openConnectionsView", (waveEvent) => {
this.onOpenConnectionsViewPressed();
return true;
});
this.keybindManager.registerKeybinding("app", "model", "app:openSettingsView", (waveEvent) => {
this.onOpenSettingsViewPressed();
return true;
});
}
static getInstance(): Model {
if (!(window as any).GlobalModel) {
(window as any).GlobalModel = new Model();
@@ -505,49 +449,56 @@ class Model {
}
if (this.activeMainView.get() == "bookmarks") {
this.bookmarksModel.handleDocKeyDown(e);
return;
}
if (this.activeMainView.get() == "history") {
this.historyViewModel.handleDocKeyDown(e);
return;
}
if (this.activeMainView.get() == "connections") {
this.historyViewModel.handleDocKeyDown(e);
return;
}
if (this.activeMainView.get() == "clientsettings") {
this.historyViewModel.handleDocKeyDown(e);
} else {
if (checkKeyPressed(waveEvent, "Escape")) {
e.preventDefault();
if (this.activeMainView.get() == "webshare") {
this.showSessionView();
return;
}
if (this.clearModals()) {
return;
}
const inputModel = this.inputModel;
inputModel.toggleInfoMsg();
if (inputModel.inputMode.get() != null) {
inputModel.resetInputMode();
}
return;
}
if (checkKeyPressed(waveEvent, "Escape")) {
e.preventDefault();
if (this.activeMainView.get() == "webshare") {
this.showSessionView();
return;
}
if (this.activeMainView.get() == "session" && checkKeyPressed(waveEvent, "Cmd:Ctrl:s")) {
e.preventDefault();
const activeScreen = this.getActiveScreen();
if (activeScreen != null) {
const isSidebarOpen = activeScreen.isSidebarOpen();
if (isSidebarOpen) {
GlobalCommandRunner.screenSidebarClose();
} else {
GlobalCommandRunner.screenSidebarOpen();
}
if (this.clearModals()) {
return;
}
const inputModel = this.inputModel;
inputModel.toggleInfoMsg();
if (inputModel.inputMode.get() != null) {
inputModel.resetInputMode();
}
return;
}
if (checkKeyPressed(waveEvent, "Cmd:b")) {
e.preventDefault();
GlobalCommandRunner.bookmarksView();
}
if (this.activeMainView.get() == "session" && checkKeyPressed(waveEvent, "Cmd:Ctrl:s")) {
e.preventDefault();
const activeScreen = this.getActiveScreen();
if (activeScreen != null) {
const isSidebarOpen = activeScreen.isSidebarOpen();
if (isSidebarOpen) {
GlobalCommandRunner.screenSidebarClose();
} else {
GlobalCommandRunner.screenSidebarOpen();
}
}
if (checkKeyPressed(waveEvent, "Cmd:d")) {
const ranDelete = this.deleteActiveLine();
if (ranDelete) {
e.preventDefault();
}
}
if (checkKeyPressed(waveEvent, "Cmd:d")) {
const ranDelete = this.deleteActiveLine();
if (ranDelete) {
e.preventDefault();
}
}
this.keybindManager.processKeyEvent(e, waveEvent);
@@ -747,22 +698,8 @@ class Model {
GlobalCommandRunner.createNewScreen();
}
onBookmarkViewPressed() {
GlobalCommandRunner.bookmarksView();
}
onFocusCmdInputPressed() {
if (this.activeMainView.get() != "session") {
mobx.action(() => {
this.activeMainView.set("session");
setTimeout(() => {
// allows for the session view to load
this.inputModel.giveFocus();
}, 100);
})();
} else {
this.inputModel.giveFocus();
}
onICmd(e: any, mods: KeyModsType) {
this.inputModel.giveFocus();
}
onLCmd(e: any, mods: KeyModsType) {
@@ -772,22 +709,14 @@ class Model {
}
}
onOpenHistoryPressed() {
onHCmd(e: any, mods: KeyModsType) {
this.historyViewModel.reSearch();
}
onOpenTabSearchModalPressed() {
onPCmd(e: any, mods: KeyModsType) {
this.modalsModel.pushModal(appconst.TAB_SWITCHER);
}
onOpenConnectionsViewPressed() {
this.activeMainView.set("connections");
}
onOpenSettingsViewPressed() {
this.activeMainView.set("clientsettings");
}
getFocusedLine(): LineFocusType {
if (this.inputModel.hasFocus()) {
return { cmdInputFocus: true };
@@ -854,12 +783,11 @@ class Model {
}
}
onSwitchSessionCmd(digit: number) {
console.log("switching to ", digit);
GlobalCommandRunner.switchSession(String(digit));
}
onDigitCmd(e: any, arg: { digit: number }, mods: KeyModsType) {
if (mods.meta && mods.ctrl) {
GlobalCommandRunner.switchSession(String(arg.digit));
return;
}
GlobalCommandRunner.switchScreen(String(arg.digit));
}
@@ -1370,7 +1298,7 @@ class Model {
};
/**
console.log(
"CMD"
"CMD",
pk.metacmd + (pk.metasubcmd != null ? ":" + pk.metasubcmd : ""),
pk.args,
pk.kwargs,
@@ -1598,7 +1526,7 @@ class Model {
.then((resp) => {
if (!resp.ok) {
badResponseStr = sprintf(
"Bad fetch response for /apiread-file: %d %s",
"Bad fetch response for /api/read-file: %d %s",
resp.status,
resp.statusText
);
-1
View File
@@ -57,7 +57,6 @@ function getThemeFromCSSVars(): ITheme {
theme.brightMagenta = rootStyle.getPropertyValue("--term-bright-magenta");
theme.brightCyan = rootStyle.getPropertyValue("--term-bright-cyan");
theme.brightWhite = rootStyle.getPropertyValue("--term-bright-white");
theme.selectionBackground = rootStyle.getPropertyValue("--term-selection-background");
return theme;
}
+3
View File
@@ -896,7 +896,10 @@ declare global {
getAppUpdateStatus: () => AppUpdateStatusType;
onAppUpdateStatus: (callback: (status: AppUpdateStatusType) => void) => void;
onTCmd: (callback: (mods: KeyModsType) => void) => void;
onICmd: (callback: (mods: KeyModsType) => void) => void;
onLCmd: (callback: (mods: KeyModsType) => void) => void;
onHCmd: (callback: (mods: KeyModsType) => void) => void;
onPCmd: (callback: (mods: KeyModsType) => void) => void;
onRCmd: (callback: (mods: KeyModsType) => void) => void;
onWCmd: (callback: (mods: KeyModsType) => void) => void;
onZoomChanged: (callback: () => void) => void;

Some files were not shown because too many files have changed in this diff Show More