Add code formatting button, Python/Haskell support
This commit is contained in:
parent
3fd5bd32d8
commit
68bb853fa0
|
@ -35,6 +35,12 @@ export class Session {
|
|||
writer: rpc.StreamMessageWriter;
|
||||
} | null = null;
|
||||
daemon: { proc: ChildProcess } | null = null;
|
||||
formatter: {
|
||||
proc: ChildProcess;
|
||||
live: boolean;
|
||||
input: string;
|
||||
output: string;
|
||||
} | null = null;
|
||||
|
||||
get homedir() {
|
||||
return `/tmp/riju/${this.uuid}`;
|
||||
|
@ -224,6 +230,13 @@ export class Session {
|
|||
}
|
||||
await this.runCode(msg.code);
|
||||
break;
|
||||
case "formatCode":
|
||||
if (typeof msg.code !== "string") {
|
||||
this.logBadMessage(msg);
|
||||
break;
|
||||
}
|
||||
await this.formatCode(msg.code);
|
||||
break;
|
||||
case "lspInput":
|
||||
if (typeof msg.input !== "object" || !msg) {
|
||||
this.logBadMessage(msg);
|
||||
|
@ -257,12 +270,11 @@ export class Session {
|
|||
compile,
|
||||
run,
|
||||
template,
|
||||
hacks,
|
||||
} = this.config;
|
||||
if (this.term) {
|
||||
const pid = this.term.pty.pid;
|
||||
const args = this.privilegedSpawn(
|
||||
bash(`kill -SIGTERM ${pid}; sleep 3; kill -SIGKILL ${pid}`)
|
||||
bash(`kill -SIGTERM ${pid}; sleep 1; kill -SIGKILL ${pid}`)
|
||||
);
|
||||
spawn(args[0], args.slice(1));
|
||||
// Signal to terminalOutput message generator using closure.
|
||||
|
@ -304,18 +316,6 @@ export class Session {
|
|||
]),
|
||||
{ input: code }
|
||||
);
|
||||
if (hacks && hacks.includes("ghci-config") && run) {
|
||||
if (code) {
|
||||
await this.run(
|
||||
this.privilegedSpawn(["sh", "-c", `cat > ${this.homedir}/.ghci`]),
|
||||
{ input: ":load Main\nmain\n" }
|
||||
);
|
||||
} else {
|
||||
await this.run(
|
||||
this.privilegedSpawn(["rm", "-f", `${this.homedir}/.ghci`])
|
||||
);
|
||||
}
|
||||
}
|
||||
const termArgs = this.privilegedSpawn(bash(cmdline));
|
||||
const term = {
|
||||
pty: pty.spawn(termArgs[0], termArgs.slice(1), {
|
||||
|
@ -338,6 +338,66 @@ export class Session {
|
|||
}
|
||||
};
|
||||
|
||||
formatCode = async (code: string) => {
|
||||
if (!this.config.format) {
|
||||
this.log("formatCode ignored because format is null");
|
||||
return;
|
||||
}
|
||||
if (this.formatter) {
|
||||
const pid = this.formatter.proc.pid;
|
||||
const args = this.privilegedSpawn(
|
||||
bash(`kill -SIGTERM ${pid}; sleep 1; kill -SIGKILL ${pid}`)
|
||||
);
|
||||
spawn(args[0], args.slice(1));
|
||||
this.formatter.live = false;
|
||||
this.formatter = null;
|
||||
}
|
||||
const args = this.privilegedSpawn(bash(this.config.format));
|
||||
const formatter = {
|
||||
proc: spawn(args[0], args.slice(1)),
|
||||
live: true,
|
||||
input: code,
|
||||
output: "",
|
||||
};
|
||||
formatter.proc.stdout!.on("data", (data) => {
|
||||
if (formatter.live) {
|
||||
formatter.output += data.toString("utf8");
|
||||
}
|
||||
});
|
||||
formatter.proc.stderr!.on("data", (data) => {
|
||||
if (formatter.live) {
|
||||
this.send({
|
||||
event: "serviceLog",
|
||||
service: "formatter",
|
||||
output: data.toString("utf8"),
|
||||
});
|
||||
}
|
||||
});
|
||||
formatter.proc.on("exit", (code, signal) => {
|
||||
if (code === 0) {
|
||||
this.send({
|
||||
event: "formattedCode",
|
||||
code: formatter.output,
|
||||
originalCode: formatter.input,
|
||||
});
|
||||
} else {
|
||||
this.send({
|
||||
event: "serviceFailed",
|
||||
service: "formatter",
|
||||
error: `Exited with status ${signal || code}`,
|
||||
});
|
||||
}
|
||||
});
|
||||
formatter.proc.on("error", (err) =>
|
||||
this.send({
|
||||
event: "serviceFailed",
|
||||
service: "formatter",
|
||||
error: `${err}`,
|
||||
})
|
||||
);
|
||||
this.formatter = formatter;
|
||||
};
|
||||
|
||||
teardown = async () => {
|
||||
try {
|
||||
if (this.tearingDown) {
|
||||
|
|
|
@ -11,6 +11,7 @@ export interface LangConfig {
|
|||
createEmpty?: string;
|
||||
compile?: string;
|
||||
run: string;
|
||||
format?: string;
|
||||
pkg?: {
|
||||
install: string;
|
||||
uninstall?: string;
|
||||
|
@ -24,7 +25,6 @@ export interface LangConfig {
|
|||
lspConfig?: any;
|
||||
lspLang?: string;
|
||||
template: string;
|
||||
hacks?: "ghci-config"[];
|
||||
test?: {
|
||||
ensure?: string;
|
||||
};
|
||||
|
@ -764,9 +764,10 @@ function main(): void {
|
|||
haskell: {
|
||||
aliases: ["ghc", "ghci", "hs"],
|
||||
name: "Haskell",
|
||||
repl: "ghci",
|
||||
repl: "rm -f .ghci && ghci",
|
||||
main: "Main.hs",
|
||||
run: "ghci",
|
||||
run: "(echo ':load Main' && echo 'main') > .ghci && ghci",
|
||||
format: "brittany Main.hs",
|
||||
lspSetup: "cp /opt/haskell/hie.yaml hie.yaml",
|
||||
lsp: "HIE_HOOGLE_DATABASE=/opt/haskell/hoogle.hoo hie --lsp",
|
||||
lspInit: {
|
||||
|
@ -1337,6 +1338,7 @@ main = do
|
|||
repl: "python3 -u",
|
||||
main: "main.py",
|
||||
run: "python3 -u -i main.py",
|
||||
format: "cat main.py | black -",
|
||||
pkg: {
|
||||
install: "pip3 install --user NAME",
|
||||
uninstall: "pip3 uninstall NAME",
|
||||
|
@ -1350,7 +1352,7 @@ main = do
|
|||
},
|
||||
},
|
||||
},
|
||||
template: `print("Hello, world!")
|
||||
template: `print('Hello, world!')
|
||||
`,
|
||||
},
|
||||
قلب: {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<div id="editor" class="column"></div>
|
||||
<div id="terminal" class="column"></div>
|
||||
<button type="button" class="btn btn-success" id="runButton">Run</button>
|
||||
<button type="button" class="btn btn-info" id="formatButton">Prettify</button>
|
||||
<a href="/" class="btn btn-secondary" id="backButton">Switch to a different language</a>
|
||||
</div>
|
||||
<script>
|
||||
|
|
|
@ -25,6 +25,7 @@ interface RijuConfig {
|
|||
id: string;
|
||||
monacoLang?: string;
|
||||
main: string;
|
||||
format?: string;
|
||||
lspDisableDynamicRegistration?: boolean;
|
||||
lspInit?: any;
|
||||
lspConfig?: any;
|
||||
|
@ -133,7 +134,7 @@ async function main() {
|
|||
|
||||
function sendMessage(message: any) {
|
||||
if (DEBUG) {
|
||||
console.log("SEND", message);
|
||||
console.log("SEND:", message);
|
||||
}
|
||||
if (socket) {
|
||||
socket.send(JSON.stringify(message));
|
||||
|
@ -165,8 +166,7 @@ async function main() {
|
|||
DEBUG &&
|
||||
message &&
|
||||
message.event !== "lspOutput" &&
|
||||
message.event !== "lspLog" &&
|
||||
message.event !== "daemonLog"
|
||||
message.event !== "serviceLog"
|
||||
) {
|
||||
console.log("RECEIVE:", message);
|
||||
}
|
||||
|
@ -184,6 +184,18 @@ async function main() {
|
|||
}
|
||||
term.write(message.output);
|
||||
return;
|
||||
case "formattedCode":
|
||||
if (
|
||||
typeof message.code !== "string" ||
|
||||
typeof message.originalCode !== "string"
|
||||
) {
|
||||
console.error("Unexpected message from server:", message);
|
||||
return;
|
||||
}
|
||||
if (editor.getValue() === message.originalCode) {
|
||||
editor.setValue(message.code);
|
||||
}
|
||||
return;
|
||||
case "lspStarted":
|
||||
if (typeof message.root !== "string") {
|
||||
console.error("Unexpected message from server:", message);
|
||||
|
@ -308,6 +320,12 @@ async function main() {
|
|||
document.getElementById("runButton")!.addEventListener("click", () => {
|
||||
sendMessage({ event: "runCode", code: editor.getValue() });
|
||||
});
|
||||
if (config.format) {
|
||||
document.getElementById("formatButton")!.classList.add("visible");
|
||||
document.getElementById("formatButton")!.addEventListener("click", () => {
|
||||
sendMessage({ event: "formatCode", code: editor.getValue() });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
|
|
|
@ -27,6 +27,17 @@ body {
|
|||
right: calc(50% + 25px);
|
||||
}
|
||||
|
||||
#formatButton {
|
||||
position: absolute;
|
||||
bottom: 25px;
|
||||
right: calc(50% + 25px);
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#formatButton.visible {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#backButton {
|
||||
position: absolute;
|
||||
left: 25px;
|
||||
|
|
|
@ -82,6 +82,9 @@ npm install -g pug-cli
|
|||
# PureScript
|
||||
npm install -g purescript spago
|
||||
|
||||
# Python
|
||||
pip3 install black
|
||||
|
||||
# ReasonML
|
||||
npm install -g bs-platform
|
||||
|
||||
|
|
|
@ -121,6 +121,9 @@ tar -xf linux-x86_64-static.tar.gz
|
|||
mv stack-*-linux-x86_64-static/stack /usr/bin/stack
|
||||
rm -rf stack-*-linux-x86_64-static linux-x86_64-static.tar.gz
|
||||
|
||||
wget "https://drive.google.com/uc?export=download&id=1MpozlNLmWeUaQuT-5t6gyE3Yv56gUbea" -O /usr/local/bin/brittany
|
||||
chmod +x /usr/local/bin/brittany
|
||||
|
||||
mkdir -p /opt/haskell
|
||||
gdown "https://drive.google.com/uc?export=download&id=1GPoR_ja4ns16KCamRgwB-JVag4HK0igz" /usr/bin/hie
|
||||
gdown "https://drive.google.com/uc?export=download&id=1qSxj8JjAeetAmNjUGayX0RBARgr5R4Ij" /opt/haskell/hoogle.hoo
|
||||
|
|
Loading…
Reference in New Issue