Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@
"typescript": "~5.6.2",
"vite": "^6.0.3"
}
}
}
59 changes: 53 additions & 6 deletions src/lib/panel/Sequent.svelte
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
<script lang="ts">
import TermTree from "$lib/components/TermTree.svelte";
import type {
Client,
NodeId,
NodeTextDesc,
ProofId,
} from "../../routes/api";

let { appState } = $props();

let sequent = $state(null);
let sequent = $state<NodeTextDesc | null>(null);
let width = $state(120);
let contentEl: HTMLDivElement | null = $state(null);
let charWidthEstimatorEl: HTMLSpanElement | null = $state(null);

async function fetchSequent(client, proof, node) {
async function fetchSequent(
client: Client,
proof: ProofId,
node: NodeId,
width: number,
) {
const options = {
unicode: false,
width: 120,
width,
indentation: 0,
pure: false,
termLabels: true,
Expand All @@ -18,15 +32,34 @@
return seq;
}

$effect(() => {
if (!contentEl || !charWidthEstimatorEl) return;

const ro = new ResizeObserver((entries) => {
const px = entries[0].contentRect.width;
const charWidth = charWidthEstimatorEl?.offsetWidth!;
const newWidth = Math.floor(px / charWidth);

console.debug("resize to new width: " + newWidth);
width = newWidth;
});

ro.observe(contentEl);
return () => ro.disconnect();
});

$effect(() => {
if (appState.proof == null || appState.active_node == null) {
return;
}

const w = width;

fetchSequent(
appState.client,
appState.proof,
appState.active_node,
w,
).then((seq) => {
sequent = seq;
});
Expand All @@ -35,7 +68,15 @@

<div class="sequent-container">
<h3>Sequent</h3>
<div class="sequent-content">
<div class="sequent-content" bind:this={contentEl}>
<!-- This element is invisible and only exists so that we can extract
the character width, regardless of font size.
The character that we use for estimation does not matter; we use a monospace font.
-->
<code class="character-width-estimator" bind:this={charWidthEstimatorEl}
>x</code
>

<!-- NOTE: That all of this is on a single line is deliberate: the pre element is whitespace/tab sensitive. -->
<pre><code
>{#if sequent}{#key sequent}<TermTree {appState} {sequent} />
Expand Down Expand Up @@ -65,11 +106,17 @@

pre {
margin: 0;
white-space: pre-wrap;
word-wrap: break-word;
white-space: pre;
}

code {
display: block;
}

.character-width-estimator {
top: 0;
left: 0;
position: absolute;
visibility: hidden;
}
</style>
24 changes: 23 additions & 1 deletion src/routes/Header.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import ThemeToggle from "$lib/components/ThemeToggle.svelte";
import Menu from "./Menu.svelte";
import FilePicker from "./FilePicker.svelte";
import { open } from "@tauri-apps/plugin-fs";
import { save } from "@tauri-apps/plugin-dialog";

let { appState, onError } = $props();

Expand All @@ -23,6 +23,25 @@
function tryOpenKeyFile(path: string) {
openKeyFile(path).catch((err) => onError(err.toString()));
}
async function saveProofTo(path: string) {
await appState.client.saveProof(appState.proof, path);
}

async function onSaveProof() {
if (!appState.proof) {
onError("No proof loaded");
return;
}

const path = await save({
title: "Save proof",
defaultPath: "proof.proof",
});

if (!path) return; // user cancelled

saveProofTo(path).catch((err) => onError(err.toString()));
}
</script>

<div class="header">
Expand All @@ -36,6 +55,9 @@
<FilePicker action={tryOpenKeyFile}>Open</FilePicker
>
</li>
<li>
<button onclick={onSaveProof}>Save</button>
</li>
</ul>
</Menu>
{/if}
Expand Down