// }
// return ret
// }
// const goalFilter = {
// reverse: false,
// showType: true,
// showInstance: true,
// showHiddenAssumption: true,
// showLetValue: true
// }
// /** The display of a single entered lean command */
// function Command({ proof, i, deleteProof }: { proof: ProofState, i: number, deleteProof: any }) {
// let {t} = useTranslation()
// // The first step will always have an empty command
// if (!proof?.steps[i]?.command) { return <>> }
// if (isLastStepWithErrors(proof, i)) {
// // If the last step has errors, we display the command in a different style
// // indicating that it will be removed on the next try.
// return
// // //
// // )
// // }, fastIsEqual)
// /** The tabs of goals that lean has after the command of this step has been processed */
// export function GoalsTabs({ goals, last, onClick, onGoalChange=(n)=>{}}: { goals: InteractiveGoalWithHints[], last : boolean, onClick? : any, onGoalChange?: (n?: number) => void }) {
// let { t } = useTranslation()
// const [selectedGoal, setSelectedGoal] = React.useState(0)
// if (goals.length == 0) {
// return <>>
// }
// return
//
// {goals.map((goal, i) => (
// // TODO: Should not use index as key.
//
// }
// // Splitting up Typewriter into two parts is a HACK
// export function TypewriterInterfaceWrapper(props: { world: string, level: number, data: LevelInfo, worldSize: number }) {
// const ec = React.useContext(EditorContext)
// const {gameId} = React.useContext(GameIdContext)
// useClientNotificationEffect(
// 'textDocument/didClose',
// (params: DidCloseTextDocumentParams) => {
// if (ec.events.changedCursorLocation.current &&
// ec.events.changedCursorLocation.current.uri === params.textDocument.uri) {
// ec.events.changedCursorLocation.fire(undefined)
// }
// }, []
// )
// const serverVersion =
// useEventResult(ec.events.serverRestarted, result => new ServerVersion(result.serverInfo?.version ?? ''))
// const serverStoppedResult = useEventResult(ec.events.serverStopped);
// // NB: the cursor may temporarily become `undefined` when a file is closed. In this case
// // it's important not to reconstruct the `WithBlah` wrappers below since they contain state
// // that we want to persist.
// if (!serverVersion) { return <>> }
// if (serverStoppedResult) {
// return
//
{serverStoppedResult.message}
//
{serverStoppedResult.reason}
//
// }
// return
// }
// /** The interface in command line mode */
// export function TypewriterInterface({props}) {
// let { t } = useTranslation()
// const ec = React.useContext(EditorContext)
// const {gameId,worldId, levelId} = React.useContext(GameIdContext)
// const editor = React.useContext(MonacoEditorContext)
// const model = editor.getModel()
// const uri = model.uri.toString()
// const gameInfo = useGetGameInfoQuery({game: gameId})
// let image: string = gameInfo.data?.worlds.nodes[worldId].image
// const [disableInput, setDisableInput] = React.useState(false)
// const [loadingProgress, setLoadingProgress] = React.useState(0)
// const { selectedStep, setSelectedStep, setDeletedChat, showHelp, setShowHelp } = React.useContext(ChatContext)
// const {mobile} = React.useContext(PreferencesContext)
// const { proof, setProof, crashed, setCrashed, interimDiags } = React.useContext(ProofContext)
// const { setTypewriterInput } = React.useContext(PageContext)
// const proofPanelRef = React.useRef(null)
// // const config = useEventResult(ec.events.changedInfoviewConfig) ?? defaultInfoviewConfig;
// // const curUri = useEventResult(ec.events.changedCursorLocation, loc => loc?.uri);
// const rpcSess = useRpcSessionAtPos({uri: uri, line: 0, character: 0})
// /** Delete all proof lines starting from a given line.
// * Note that the first line (i.e. deleting everything) is `1`!
// */
// function deleteProof(line: number) {
// return (ev) => {
// let deletedChat: Array = []
// proof?.steps.slice(line).map((step, i) => {
// let filteredHints = filterHints(step.goals[0]?.hints, proof?.steps[i-1]?.goals[0]?.hints)
// // Only add these hidden hints to the deletion stack which were visible
// deletedChat = [...deletedChat, ...filteredHints.filter(hint => (!hint.hidden || showHelp.has(line + i)))]
// })
// setDeletedChat(deletedChat)
// // delete showHelp for deleted steps
// setShowHelp(new Set(Array.from(showHelp).filter(i => i < line - 1)))
// editor.executeEdits("typewriter", [{
// range: monaco.Selection.fromPositions(
// { lineNumber: line, column: 1 },
// editor.getModel().getFullModelRange().getEndPosition()
// ),
// text: '',
// forceMoveMarkers: false
// }])
// setSelectedStep(null)
// setTypewriterInput(proof?.steps[line].command)
// // Reload proof on deleting
// loadGoals(rpcSess, uri, setProof, setCrashed)
// ev.stopPropagation()
// }
// }
// function toggleSelectStep(line: number) {
// return (ev) => {
// if (mobile) {return}
// if (selectedStep == line) {
// setSelectedStep(null)
// console.debug(`unselected step`)
// } else {
// setSelectedStep(line)
// console.debug(`step ${line} selected`)
// }
// }
// }
// // Scroll to the end of the proof if it is updated.
// React.useEffect(() => {
// if (proof?.steps.length > 1) {
// proofPanelRef.current?.lastElementChild?.scrollIntoView() //scrollTo(0,0)
// } else {
// proofPanelRef.current?.scrollTo(0,0)
// }
// // also reenable the commandline when the proof changes
// // BUG: If selecting 2nd goal on a intermediate proofstep and then delete proof to there,
// // the commandline is not displaying disabled even though it should.
// setDisableInput(false)
// }, [proof])
// // Scroll to element if selection changes
// React.useEffect(() => {
// if (typeof selectedStep !== 'undefined') {
// Array.from(proofPanelRef.current?.getElementsByClassName(`step-${selectedStep}`)).map((elem) => {
// elem.scrollIntoView({ block: "center" })
// })
// }
// }, [selectedStep])
// // TODO: superfluous, can be replaced with `withErr` from above
// let lastStepErrors = proof?.steps.length ? hasInteractiveErrors(getInteractiveDiagsAt(proof, proof?.steps.length)) : false
// useServerNotificationEffect("$/game/loading", (params : any) => {
// if (params.kind == "loadConstants") {
// setLoadingProgress(params.counter/100*50)
// } else if (params.kind == "finalizeExtensions") {
// setLoadingProgress(50 + params.counter/150*50)
// } else {
// console.error(`Unknown loading kind: ${params.kind}`)
// }
// })
// return
//
//
// {/*
// {image &&
//
// }
//
*/}
// {/*
//
//
//
*/}
//
// {/* */}
// {crashed ?
//
{t("Crashed! Go to editor mode and fix your proof! Last server response:")}
: proof?.steps.length ?
// <>
// {proof?.steps.map((step, i) => {
// let filteredHints = filterHints(step.goals[0]?.hints, proof?.steps[i-1]?.goals[0]?.hints)
// // if (i == proof?.steps.length - 1 && hasInteractiveErrors(step.diags)) {
// // // if the last command contains an error, we only display the errors but not the
// // // entered command as it is still present in the command line.
// // // TODO: Should not use index as key.
// // return
// }
// > :
// // note: since we don't know the total number of files,
// // we use a function which strictly monotonely increases towards `100` as `x β β`
// // The base is chosen at random s.t. we get roughly 91% for `x = 100`.
// }
//