diff --git a/pdl-live-react/src/view/masonry/MasonryCombo.tsx b/pdl-live-react/src/view/masonry/MasonryCombo.tsx
index ea6954f77..55570360c 100644
--- a/pdl-live-react/src/view/masonry/MasonryCombo.tsx
+++ b/pdl-live-react/src/view/masonry/MasonryCombo.tsx
@@ -11,7 +11,6 @@ import {
Button,
BackToTop,
Modal,
- type ModalProps,
ModalBody,
ModalFooter,
ModalHeader,
@@ -28,6 +27,7 @@ import MasonryTileWrapper from "./MasonryTileWrapper"
import Toolbar, { type SML } from "./Toolbar"
import computeModel from "./model"
+import ConditionVariable from "./condvar"
import {
hasContextInformation,
hasTimingInformation,
@@ -39,11 +39,7 @@ import RunningIcon from "@patternfly/react-icons/dist/esm/icons/running-icon"
import "./Masonry.css"
-export type Runner = (
- block: NonScalarPdlBlock,
- onExit: () => void,
- modalVariant?: ModalProps["variant"],
-) => void
+export type Runner = (block: NonScalarPdlBlock, onExit: () => void) => void
type Props = {
value: string
@@ -60,9 +56,6 @@ function setSMLUserSetting(sml: SML) {
/** Combines , , ... */
export default function MasonryCombo({ value, setValue }: Props) {
- const [modalVariant, setModalVariant] =
- useState("large")
-
const block = useMemo(() => {
if (value) {
try {
@@ -83,11 +76,17 @@ export default function MasonryCombo({ value, setValue }: Props) {
cmd: string
args?: string[]
onExit?: (exitCode: number) => void
+ cancelCondVar?: ConditionVariable
}>(null)
+ const cancelModal = useCallback(
+ () => modalContent?.cancelCondVar?.signal(),
+ [modalContent?.cancelCondVar],
+ )
const closeModal = useCallback(() => {
+ modalContent?.cancelCondVar?.signal()
setModalContent(null)
setModalIsDone(-1)
- }, [setModalContent, setModalIsDone])
+ }, [modalContent?.cancelCondVar, setModalContent, setModalIsDone])
const onExit = useCallback(
(exitCode: number) => {
setModalIsDone(exitCode)
@@ -97,19 +96,16 @@ export default function MasonryCombo({ value, setValue }: Props) {
},
[setModalIsDone, modalContent],
)
+ useEffect(() => setModalIsDone(-2), [modalContent])
// special form of setModalContent for running a PDL program
const run = useCallback(
- async (runThisBlock, onExit, modalVariant) => {
+ async (runThisBlock, onExit) => {
if (!isNonScalarPdlBlock(block)) {
onExit()
return
}
- if (modalVariant) {
- setModalVariant(modalVariant)
- }
-
const [cmd, input, output] = (await invoke("replay_prep", {
trace: JSON.stringify(runThisBlock),
name:
@@ -132,6 +128,7 @@ export default function MasonryCombo({ value, setValue }: Props) {
...(!data ? [] : ["--data", JSON.stringify(data)]),
input,
],
+ cancelCondVar: new ConditionVariable(),
onExit: async () => {
onExit()
try {
@@ -198,15 +195,11 @@ export default function MasonryCombo({ value, setValue }: Props) {
-
+
@@ -228,10 +222,18 @@ export default function MasonryCombo({ value, setValue }: Props) {
key="Close"
variant={modalIsDone > 0 ? "danger" : "primary"}
onClick={closeModal}
- isDisabled={modalIsDone === -1}
+ isDisabled={modalIsDone < 0}
>
Close
+
>
diff --git a/pdl-live-react/src/view/masonry/MasonryTile.tsx b/pdl-live-react/src/view/masonry/MasonryTile.tsx
index 223b75bc4..2bf949e34 100644
--- a/pdl-live-react/src/view/masonry/MasonryTile.tsx
+++ b/pdl-live-react/src/view/masonry/MasonryTile.tsx
@@ -53,7 +53,7 @@ export default function MasonryTile({
const myRun = useCallback(() => {
if (block && run) {
setIsRunning(true)
- run(block, () => setIsRunning(false), "medium")
+ run(block, () => setIsRunning(false))
}
}, [block, run, setIsRunning])
diff --git a/pdl-live-react/src/view/masonry/condvar.ts b/pdl-live-react/src/view/masonry/condvar.ts
new file mode 100644
index 000000000..61baf0a7d
--- /dev/null
+++ b/pdl-live-react/src/view/masonry/condvar.ts
@@ -0,0 +1,29 @@
+export default class ConditionVariable {
+ private condition: boolean = false
+ private waitingPromises: {
+ resolve: () => void
+ reject: (reason?: unknown) => void
+ }[] = []
+
+ public async wait(): Promise {
+ if (this.condition) {
+ return Promise.resolve()
+ }
+
+ return new Promise((resolve, reject) => {
+ this.waitingPromises.push({ resolve, reject })
+ })
+ }
+
+ public signal(): void {
+ if (this.waitingPromises.length > 0) {
+ const { resolve } = this.waitingPromises.shift()!
+ resolve()
+ this.condition = true
+ }
+ }
+
+ public reset(): void {
+ this.condition = false
+ }
+}
diff --git a/pdl-live-react/src/view/term/RunTerminal.tsx b/pdl-live-react/src/view/term/RunTerminal.tsx
index fcba32da8..f6fb50983 100644
--- a/pdl-live-react/src/view/term/RunTerminal.tsx
+++ b/pdl-live-react/src/view/term/RunTerminal.tsx
@@ -8,16 +8,25 @@ import { ClipboardAddon } from "@xterm/addon-clipboard"
import "./RunTerminal.css"
type Props = {
+ /** The cmd part of `cmd ...args` */
cmd: string
+
+ /** The args part of `cmd ...args */
args?: string[]
+
+ /** A callback provided by caller to be invoked upon pty completion */
onExit?: (exitCode: number) => void
+
+ /** A condition variable used by caller to request pty cancellation */
+ cancel?: import("../masonry/condvar").default
}
-export default function RunTerminal({ cmd, args = [], onExit }: Props) {
+export default function RunTerminal({ cmd, args = [], onExit, cancel }: Props) {
const ref = createRef()
const [term, setTerm] = useState(null)
const [exitCode, setExitCode] = useState(-1)
+ /** Schema adapter from our props.onExit to that of tauri-pty */
const onExit2 = useCallback(
({ exitCode }: { exitCode: number }) => {
setExitCode(exitCode)
@@ -28,7 +37,8 @@ export default function RunTerminal({ cmd, args = [], onExit }: Props) {
[onExit, setExitCode],
)
- useEffect(() => setExitCode(-1), [cmd, args, onExit])
+ /** Re-initialization of exit code if props change */
+ useEffect(() => setExitCode(-1), [cmd, args, onExit, cancel])
// Why a two-stage useEffect? Otherwise: cannot read properties of
// undefined (reading 'dimensions')
@@ -64,6 +74,11 @@ export default function RunTerminal({ cmd, args = [], onExit }: Props) {
rows: term.rows,
})
+ /** Respond to cancellation request by killing the pty */
+ cancel?.wait().then(() => {
+ pty.kill()
+ })
+
pty.onData((data) => term.write(data))
term.onData((data) => pty.write(data))
@@ -78,7 +93,7 @@ export default function RunTerminal({ cmd, args = [], onExit }: Props) {
}
}
}
- }, [term, ref, exitCode, args, cmd, onExit2])
+ }, [term, ref, exitCode, cmd, args, cancel, onExit2])
return (