|
|
@@ -1,4 +1,104 @@
|
|
|
-const term = new Terminal();
|
|
|
+const MINIMUM_COLS = 2
|
|
|
+const MINIMUM_ROWS = 1
|
|
|
+
|
|
|
+class FitAddon {
|
|
|
+ constructor() {}
|
|
|
+
|
|
|
+ activate(terminal) {
|
|
|
+ this._terminal = terminal
|
|
|
+ }
|
|
|
+
|
|
|
+ dispose() {}
|
|
|
+
|
|
|
+ fit() {
|
|
|
+ const dims = this.proposeDimensions()
|
|
|
+ if (!dims || !this._terminal || isNaN(dims.cols) || isNaN(dims.rows)) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // TODO: Remove reliance on private API
|
|
|
+ const core = this._terminal._core
|
|
|
+
|
|
|
+ // Force a full render
|
|
|
+ if (
|
|
|
+ this._terminal.rows !== dims.rows ||
|
|
|
+ this._terminal.cols !== dims.cols
|
|
|
+ ) {
|
|
|
+ core._renderService.clear()
|
|
|
+ this._terminal.resize(dims.cols, dims.rows)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ proposeDimensions() {
|
|
|
+ if (!this._terminal) {
|
|
|
+ return undefined
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this._terminal.element || !this._terminal.element.parentElement) {
|
|
|
+ return undefined
|
|
|
+ }
|
|
|
+
|
|
|
+ // TODO: Remove reliance on private API
|
|
|
+ const core = this._terminal._core
|
|
|
+ const dims = core._renderService.dimensions
|
|
|
+
|
|
|
+ if (dims.actualCellWidth === 0 || dims.actualCellHeight === 0) {
|
|
|
+ return undefined
|
|
|
+ }
|
|
|
+
|
|
|
+ const scrollbarWidth =
|
|
|
+ this._terminal.options.scrollback === 0 ? 0 : core.viewport.scrollBarWidth
|
|
|
+
|
|
|
+ const parentElementStyle = window.getComputedStyle(
|
|
|
+ this._terminal.element.parentElement
|
|
|
+ )
|
|
|
+ const parentElementHeight = parseInt(
|
|
|
+ parentElementStyle.getPropertyValue("height")
|
|
|
+ )
|
|
|
+ const parentElementWidth = Math.max(
|
|
|
+ 0,
|
|
|
+ parseInt(parentElementStyle.getPropertyValue("width"))
|
|
|
+ )
|
|
|
+ const elementStyle = window.getComputedStyle(this._terminal.element)
|
|
|
+ const elementPadding = {
|
|
|
+ top: parseInt(elementStyle.getPropertyValue("padding-top")),
|
|
|
+ bottom: parseInt(elementStyle.getPropertyValue("padding-bottom")),
|
|
|
+ right: parseInt(elementStyle.getPropertyValue("padding-right")),
|
|
|
+ left: parseInt(elementStyle.getPropertyValue("padding-left"))
|
|
|
+ }
|
|
|
+ const elementPaddingVer = elementPadding.top + elementPadding.bottom
|
|
|
+ const elementPaddingHor = elementPadding.right + elementPadding.left
|
|
|
+ const availableHeight = parentElementHeight - elementPaddingVer
|
|
|
+ const availableWidth =
|
|
|
+ parentElementWidth - elementPaddingHor - scrollbarWidth
|
|
|
+ const geometry = {
|
|
|
+ cols: Math.max(
|
|
|
+ MINIMUM_COLS,
|
|
|
+ Math.floor(availableWidth / dims.actualCellWidth)
|
|
|
+ ),
|
|
|
+ rows: Math.max(
|
|
|
+ MINIMUM_ROWS,
|
|
|
+ Math.floor(availableHeight / dims.actualCellHeight)
|
|
|
+ )
|
|
|
+ }
|
|
|
+ return geometry
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+const term = new Terminal(
|
|
|
+ {
|
|
|
+ cursorBlink: true,
|
|
|
+ fontSize: 16,
|
|
|
+ theme: {
|
|
|
+ background: '#282C34',
|
|
|
+ foreground: '#ffffff',
|
|
|
+ cursor: '#ffffff',
|
|
|
+ cursorAccent: '#282C34',
|
|
|
+ selection: '#41454E',
|
|
|
+ },
|
|
|
+ }
|
|
|
+);
|
|
|
|
|
|
var command = "";
|
|
|
var need_more_lines = false;
|
|
|
@@ -12,7 +112,7 @@ var Module = {
|
|
|
'printErr': function(text) {
|
|
|
term.write(text + "\r\n");
|
|
|
},
|
|
|
- 'onRuntimeInitialized': function(text) {
|
|
|
+ 'onRuntimeInitialized': function(text) {
|
|
|
var vm = Module.ccall('pkpy_new_vm', 'number', ['boolean'], [true]);
|
|
|
repl = Module.ccall('pkpy_new_repl', 'number', ['number'], [vm]);
|
|
|
term.write(need_more_lines ? "... " : ">>> ");
|
|
|
@@ -24,6 +124,15 @@ var Module = {
|
|
|
|
|
|
function term_init() {
|
|
|
term.open(document.getElementById('terminal'));
|
|
|
+ const addon = new FitAddon();
|
|
|
+ term.loadAddon(addon);
|
|
|
+ addon.fit();
|
|
|
+
|
|
|
+ // refit when window is resized
|
|
|
+ window.addEventListener('resize', () => {
|
|
|
+ addon.fit();
|
|
|
+ });
|
|
|
+
|
|
|
term.onData(e => {
|
|
|
if (stopped) return;
|
|
|
switch (e) {
|