Terminal text cols adjusts to terminal container. (#285)

Co-authored-by: Louis Lam <louislam@users.noreply.github.com>
This commit is contained in:
Zack Hankin 2023-12-16 20:57:21 +11:00 committed by GitHub
parent 94ca8a152a
commit e2819afce1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 98 additions and 19 deletions

View file

@ -162,9 +162,44 @@ export class TerminalSocketHandler extends SocketHandler {
} }
}); });
// TODO: Resize Terminal // Resize Terminal
socket.on("terminalResize", async (rows : unknown) => { socket.on(
"terminalResize",
async (terminalName: unknown, rows: unknown, cols: unknown) => {
log.info("terminalResize", `Terminal: ${terminalName}`);
try {
checkLogin(socket);
if (typeof terminalName !== "string") {
throw new Error("Terminal name must be a string.");
}
}); if (typeof rows !== "number") {
throw new Error("Command must be a number.");
}
if (typeof cols !== "number") {
throw new Error("Command must be a number.");
}
let terminal = Terminal.getTerminal(terminalName);
// log.info("terminal", terminal);
if (terminal instanceof Terminal) {
//log.debug("terminalInput", "Terminal found, writing to terminal.");
terminal.rows = rows;
terminal.cols = cols;
} else {
throw new Error(`${terminalName} Terminal not found.`);
}
} catch (e) {
log.debug(
"terminalResize",
// Added to prevent the lint error when adding the type
// and ts type checker saying type is unknown.
// @ts-ignore
`Error on ${terminalName}: ${e.message}`
);
}
}
);
} }
} }

View file

@ -67,6 +67,7 @@ export class Terminal {
set cols(cols : number) { set cols(cols : number) {
this._cols = cols; this._cols = cols;
log.debug("Terminal", `Terminal cols: ${this._cols}`); // Added to check if cols is being set when changing terminal size.
try { try {
this.ptyProcess?.resize(this.cols, this.rows); this.ptyProcess?.resize(this.cols, this.rows);
} catch (e) { } catch (e) {

View file

@ -5,7 +5,8 @@
</template> </template>
<script> <script>
import { Terminal } from "xterm"; import { Terminal } from "@xterm/xterm";
import { FitAddon } from "@xterm/addon-fit";
import { WebLinksAddon } from "xterm-addon-web-links"; import { WebLinksAddon } from "xterm-addon-web-links";
import { TERMINAL_COLS, TERMINAL_ROWS } from "../../../backend/util-common"; import { TERMINAL_COLS, TERMINAL_ROWS } from "../../../backend/util-common";
@ -122,10 +123,12 @@ export default {
} }
}); });
} }
// Fit the terminal width to the div container size after terminal is created.
this.updateTerminalSize();
}, },
unmounted() { unmounted() {
window.removeEventListener("resize", this.onResizeEvent); // Remove the resize event listener from the window object.
this.$root.unbindTerminal(this.name); this.$root.unbindTerminal(this.name);
this.terminal.dispose(); this.terminal.dispose();
}, },
@ -208,6 +211,30 @@ export default {
} }
}); });
}); });
},
/**
* Update the terminal size to fit the container size.
*
* If the terminalFitAddOn is not created, creates it, loads it and then fits the terminal to the appropriate size.
* It then addes an event listener to the window object to listen for resize events and calls the fit method of the terminalFitAddOn.
*/
updateTerminalSize() {
if (!Object.hasOwn(this, "terminalFitAddOn")) {
this.terminalFitAddOn = new FitAddon();
this.terminal.loadAddon(this.terminalFitAddOn);
window.addEventListener("resize", this.onResizeEvent);
}
this.terminalFitAddOn.fit();
},
/**
* Handles the resize event of the terminal component.
*/
onResizeEvent() {
this.terminalFitAddOn.fit();
let rows = this.terminal.rows;
let cols = this.terminal.cols;
this.$root.getSocket().emit("terminalResize", this.name, rows, cols);
} }
} }
}; };

View file

@ -10,12 +10,12 @@ import { i18n } from "./i18n";
// Dependencies // Dependencies
import "bootstrap"; import "bootstrap";
import Toast, { POSITION, useToast } from "vue-toastification"; import Toast, { POSITION, useToast } from "vue-toastification";
import "xterm/lib/xterm.js"; import "@xterm/xterm/lib/xterm.js";
// CSS // CSS
import "@fontsource/jetbrains-mono"; import "@fontsource/jetbrains-mono";
import "vue-toastification/dist/index.css"; import "vue-toastification/dist/index.css";
import "xterm/css/xterm.css"; import "@xterm/xterm/css/xterm.css";
import "./styles/main.scss"; import "./styles/main.scss";
// Minxins // Minxins

View file

@ -2,7 +2,7 @@ import { io } from "socket.io-client";
import { Socket } from "socket.io-client"; import { Socket } from "socket.io-client";
import { defineComponent } from "vue"; import { defineComponent } from "vue";
import jwtDecode from "jwt-decode"; import jwtDecode from "jwt-decode";
import { Terminal } from "xterm"; import { Terminal } from "@xterm/xterm";
let socket : Socket; let socket : Socket;

View file

@ -55,8 +55,6 @@
"yaml": "~2.3.4" "yaml": "~2.3.4"
}, },
"devDependencies": { "devDependencies": {
"concurrently": "^8.2.2",
"wait-on": "^7.2.0",
"@actions/github": "^6.0.0", "@actions/github": "^6.0.0",
"@fontsource/jetbrains-mono": "^5.0.18", "@fontsource/jetbrains-mono": "^5.0.18",
"@fortawesome/fontawesome-svg-core": "6.4.2", "@fortawesome/fontawesome-svg-core": "6.4.2",
@ -71,8 +69,11 @@
"@typescript-eslint/eslint-plugin": "~6.8.0", "@typescript-eslint/eslint-plugin": "~6.8.0",
"@typescript-eslint/parser": "~6.8.0", "@typescript-eslint/parser": "~6.8.0",
"@vitejs/plugin-vue": "~4.5.2", "@vitejs/plugin-vue": "~4.5.2",
"@xterm/addon-fit": "beta",
"@xterm/xterm": "beta",
"bootstrap": "5.3.2", "bootstrap": "5.3.2",
"bootstrap-vue-next": "~0.14.10", "bootstrap-vue-next": "~0.14.10",
"concurrently": "^8.2.2",
"cross-env": "~7.0.3", "cross-env": "~7.0.3",
"eslint": "~8.50.0", "eslint": "~8.50.0",
"eslint-plugin-jsdoc": "~46.8.2", "eslint-plugin-jsdoc": "~46.8.2",
@ -90,7 +91,7 @@
"vue-qrcode": "~2.2.0", "vue-qrcode": "~2.2.0",
"vue-router": "~4.2.5", "vue-router": "~4.2.5",
"vue-toastification": "2.0.0-rc.5", "vue-toastification": "2.0.0-rc.5",
"xterm": "5.4.0-beta.37", "wait-on": "^7.2.0",
"xterm-addon-web-links": "~0.9.0" "xterm-addon-web-links": "~0.9.0"
} }
} }

View file

@ -133,6 +133,12 @@ devDependencies:
'@vitejs/plugin-vue': '@vitejs/plugin-vue':
specifier: ~4.5.2 specifier: ~4.5.2
version: 4.5.2(vite@5.0.7)(vue@3.3.11) version: 4.5.2(vite@5.0.7)(vue@3.3.11)
'@xterm/addon-fit':
specifier: beta
version: 0.9.0-beta.17(@xterm/xterm@5.4.0-beta.17)
'@xterm/xterm':
specifier: beta
version: 5.4.0-beta.17
bootstrap: bootstrap:
specifier: 5.3.2 specifier: 5.3.2
version: 5.3.2(@popperjs/core@2.11.8) version: 5.3.2(@popperjs/core@2.11.8)
@ -196,12 +202,9 @@ devDependencies:
wait-on: wait-on:
specifier: ^7.2.0 specifier: ^7.2.0
version: 7.2.0 version: 7.2.0
xterm:
specifier: 5.4.0-beta.37
version: 5.4.0-beta.37
xterm-addon-web-links: xterm-addon-web-links:
specifier: ~0.9.0 specifier: ~0.9.0
version: 0.9.0(xterm@5.4.0-beta.37) version: 0.9.0(xterm@5.3.0)
packages: packages:
@ -1569,6 +1572,18 @@ packages:
- vue - vue
dev: true dev: true
/@xterm/addon-fit@0.9.0-beta.17(@xterm/xterm@5.4.0-beta.17):
resolution: {integrity: sha512-4jYMsbyferF29hF0vCaQj6CQlT2A6ML6DhLZdi6cCZI5qn60mGUXZfDeO/Qoq2nmyK/PBrPyFYSOzWapSy45Zg==}
peerDependencies:
'@xterm/xterm': ^5.0.0
dependencies:
'@xterm/xterm': 5.4.0-beta.17
dev: true
/@xterm/xterm@5.4.0-beta.17:
resolution: {integrity: sha512-EhQsTHeO7VhCOnYLdrowWAqEbmZKf6k6Z/Rd3GriikB394jivux6OBcJbt7QdewIOAKqFah53d4rNXfz3/6mwQ==}
dev: true
/abbrev@1.1.1: /abbrev@1.1.1:
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
requiresBuild: true requiresBuild: true
@ -5524,16 +5539,16 @@ packages:
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
dev: false dev: false
/xterm-addon-web-links@0.9.0(xterm@5.4.0-beta.37): /xterm-addon-web-links@0.9.0(xterm@5.3.0):
resolution: {integrity: sha512-LIzi4jBbPlrKMZF3ihoyqayWyTXAwGfu4yprz1aK2p71e9UKXN6RRzVONR0L+Zd+Ik5tPVI9bwp9e8fDTQh49Q==} resolution: {integrity: sha512-LIzi4jBbPlrKMZF3ihoyqayWyTXAwGfu4yprz1aK2p71e9UKXN6RRzVONR0L+Zd+Ik5tPVI9bwp9e8fDTQh49Q==}
peerDependencies: peerDependencies:
xterm: ^5.0.0 xterm: ^5.0.0
dependencies: dependencies:
xterm: 5.4.0-beta.37 xterm: 5.3.0
dev: true dev: true
/xterm@5.4.0-beta.37: /xterm@5.3.0:
resolution: {integrity: sha512-ys+mXqLFrJc7khmYN/MgBnfLv38NgXfkwkEXsCZKHGqn3h2xUBvTvsrSEWO3NQeDPLj4zMr1RwqTblMK9St3BA==} resolution: {integrity: sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==}
dev: true dev: true
/y18n@4.0.3: /y18n@4.0.3: