diff --git a/client/src/components/Level.tsx b/client/src/components/Level.tsx
index 3cb8b54..42c1b38 100644
--- a/client/src/components/Level.tsx
+++ b/client/src/components/Level.tsx
@@ -13,6 +13,8 @@ import Grid from '@mui/material/Unstable_Grid2';
import LeftPanel from './LeftPanel';
import { LeanTaskGutter } from 'lean4web/client/src/editor/taskgutter';
import { AbbreviationProvider } from 'lean4web/client/src/editor/abbreviation/AbbreviationProvider';
+import 'lean4web/client/src/editor/vscode.css';
+import 'lean4web/client/src/editor/infoview.css';
import { AbbreviationRewriter } from 'lean4web/client/src/editor/abbreviation/rewriter/AbbreviationRewriter';
import { InfoProvider } from 'lean4web/client/src/editor/infoview';
import 'lean4web/client/src/editor/infoview.css'
diff --git a/client/src/components/infoview/goals.tsx b/client/src/components/infoview/goals.tsx
new file mode 100644
index 0000000..d40fbb1
--- /dev/null
+++ b/client/src/components/infoview/goals.tsx
@@ -0,0 +1,241 @@
+/* Mostly copied from https://github.com/leanprover/vscode-lean4/blob/master/lean4-infoview/src/infoview/goals.tsx */
+
+import * as React from 'react'
+import { InteractiveCode } from '../../../../node_modules/lean4-infoview/src/infoview/interactiveCode'
+import { InteractiveGoal, InteractiveGoals, InteractiveHypothesisBundle, InteractiveHypothesisBundle_nonAnonymousNames, MVarId, TaggedText_stripTags } from '@leanprover/infoview-api'
+import { WithTooltipOnHover } from '../../../../node_modules/lean4-infoview/src/infoview/tooltips';
+import { EditorContext } from '../../../../node_modules/lean4-infoview/src/infoview/contexts';
+import { Locations, LocationsContext, SelectableLocation } from '../../../../node_modules/lean4-infoview/src/infoview/goalLocation';
+
+/** Returns true if `h` is inaccessible according to Lean's default name rendering. */
+function isInaccessibleName(h: string): boolean {
+ return h.indexOf('✝') >= 0;
+}
+
+function goalToString(g: InteractiveGoal): string {
+ let ret = ''
+
+ if (g.userName) {
+ ret += `case ${g.userName}\n`
+ }
+
+ for (const h of g.hyps) {
+ const names = InteractiveHypothesisBundle_nonAnonymousNames(h).join(' ')
+ ret += `${names} : ${TaggedText_stripTags(h.type)}`
+ if (h.val) {
+ ret += ` := ${TaggedText_stripTags(h.val)}`
+ }
+ ret += '\n'
+ }
+
+ ret += `⊢ ${TaggedText_stripTags(g.type)}`
+
+ return ret
+}
+
+export function goalsToString(goals: InteractiveGoals): string {
+ return goals.goals.map(goalToString).join('\n\n')
+}
+
+interface GoalFilterState {
+ /** If true reverse the list of hypotheses, if false present the order received from LSP. */
+ reverse: boolean,
+ /** If true show hypotheses that have isType=True, otherwise hide them. */
+ showType: boolean,
+ /** If true show hypotheses that have isInstance=True, otherwise hide them. */
+ showInstance: boolean,
+ /** If true show hypotheses that contain a dagger in the name, otherwise hide them. */
+ showHiddenAssumption: boolean
+ /** If true show the bodies of let-values, otherwise hide them. */
+ showLetValue: boolean;
+}
+
+function getFilteredHypotheses(hyps: InteractiveHypothesisBundle[], filter: GoalFilterState): InteractiveHypothesisBundle[] {
+ return hyps.reduce((acc: InteractiveHypothesisBundle[], h) => {
+ if (h.isInstance && !filter.showInstance) return acc
+ if (h.isType && !filter.showType) return acc
+ const names = filter.showHiddenAssumption ? h.names : h.names.filter(n => !isInaccessibleName(n))
+ const hNew: InteractiveHypothesisBundle = filter.showLetValue ? { ...h, names } : { ...h, names, val: undefined }
+ if (names.length !== 0) acc.push(hNew)
+ return acc
+ }, [])
+}
+
+interface HypProps {
+ hyp: InteractiveHypothesisBundle
+ mvarId?: MVarId
+}
+
+function Hyp({ hyp: h, mvarId }: HypProps) {
+ const locs = React.useContext(LocationsContext)
+
+ const namecls: string = 'mr1 ' +
+ (h.isInserted ? 'inserted-text ' : '') +
+ (h.isRemoved ? 'removed-text ' : '')
+
+ const names = InteractiveHypothesisBundle_nonAnonymousNames(h).map((n, i) =>
+
+
Click somewhere in the Lean file to enable the infoview.
} +{title}
++++