37
loading...
This website collects cookies to deliver better user experience
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="./terminal.css" />
</head>
<body>
<h1>Very amazing terminal app</h1>
<div id="terminal">
<div id="history">
</div>
<div class="input-line">
<span class="prompt">$</span>
<form>
<input type="text" autofocus />
</form>
</div>
</div>
<script src="./terminal.js"></script>
</body>
</html>
body {
background-color: #444;
color: #fff;
}
h1 {
font-family: monospace;
}
#terminal {
font-family: monospace;
}
.input-line {
display: flex;
}
.input-line > * {
flex: 1;
}
.input-line > .prompt {
flex: 0;
padding-right: 0.5rem;
}
.output {
padding-bottom: 0.5rem;
}
.input {
color: #ffa;
}
.output {
color: #afa;
white-space: pre;
}
form {
display: flex;
}
input {
flex: 1;
font-family: monospace;
background-color: #444;
color: #fff;
border: none;
}
let form = document.querySelector("form")
let input = document.querySelector("input")
let terminalHistory = document.querySelector("#history")
function createInputLine(command) {
let inputLine = document.createElement("div")
inputLine.className = "input-line"
let promptSpan = document.createElement("span")
promptSpan.className = "prompt"
promptSpan.append("$")
let inputSpan = document.createElement("span")
inputSpan.className = "input"
inputSpan.append(command)
inputLine.append(promptSpan)
inputLine.append(inputSpan)
return inputLine
}
function createTerminalHistoryEntry(command, commandOutput) {
let inputLine = createInputLine(command)
let output = document.createElement("div")
output.className = "output"
output.append(commandOutput)
terminalHistory.append(inputLine)
terminalHistory.append(output)
}
form.addEventListener("submit", async (e) => {
e.preventDefault()
let command = input.value
let output = await window.pywebview.api.execute(command)
createTerminalHistoryEntry(command, output)
input.value = ""
input.scrollIntoView()
})
let output = await window.pywebview.api.execute(command)
. The execute(command)
function needs to be exposed by the Python backend.#!/usr/bin/env python3
import webview
import subprocess
class App:
def execute(self, command):
result = subprocess.run(command, capture_output=True, shell=True, encoding="utf-8")
return result.stdout + result.stderr
app = App()
window = webview.create_window(
"Terminal App",
"terminal.html",
js_api=App()
)
webview.start()
string
(with encoding="utf-8"
), as pywebview can't send bytes
over, even though technically that's a valid JavaScript types these days (Uint8Array
).