improve command line display

pull/68/head
Jon Eugster 3 years ago
parent 94b5af1623
commit 60a9c1727b

@ -114,6 +114,11 @@ function Hyp({ hyp: h, mvarId }: HypProps) {
</div> </div>
} }
interface GoalProps2 {
goals: InteractiveGoal[]
filter: GoalFilterState
}
interface GoalProps { interface GoalProps {
goal: InteractiveGoal goal: InteractiveGoal
filter: GoalFilterState filter: GoalFilterState
@ -121,6 +126,11 @@ interface GoalProps {
commandLine: boolean commandLine: boolean
} }
interface ProofDisplayProps {
proof: string
}
/** /**
* Displays the hypotheses, target type and optional case label of a goal according to the * Displays the hypotheses, target type and optional case label of a goal according to the
* provided `filter`. */ * provided `filter`. */
@ -154,10 +164,10 @@ export const Goal = React.memo((props: GoalProps) => {
return <div> return <div>
{/* {goal.userName && <div><strong className="goal-case">case </strong>{goal.userName}</div>} */} {/* {goal.userName && <div><strong className="goal-case">case </strong>{goal.userName}</div>} */}
{filter.reverse && goalLi} {filter.reverse && goalLi}
{ objectHyps.length > 0 && {! commandLine && objectHyps.length > 0 &&
<div className="hyp-group"><div className="hyp-group-title">Objekte:</div> <div className="hyp-group"><div className="hyp-group-title">Objekte:</div>
{objectHyps.map((h, i) => <Hyp hyp={h} mvarId={goal.mvarId} key={i} />)}</div> } {objectHyps.map((h, i) => <Hyp hyp={h} mvarId={goal.mvarId} key={i} />)}</div> }
{ assumptionHyps.length > 0 && {!commandLine && assumptionHyps.length > 0 &&
<div className="hyp-group"><div className="hyp-group-title">Annahmen:</div> <div className="hyp-group"><div className="hyp-group-title">Annahmen:</div>
{assumptionHyps.map((h, i) => <Hyp hyp={h} mvarId={goal.mvarId} key={i} />)}</div> } {assumptionHyps.map((h, i) => <Hyp hyp={h} mvarId={goal.mvarId} key={i} />)}</div> }
{commandLine && commandLineMode && <CommandLine />} {commandLine && commandLineMode && <CommandLine />}
@ -166,6 +176,79 @@ export const Goal = React.memo((props: GoalProps) => {
</div> </div>
}) })
export const MainAssumptions = React.memo((props: GoalProps2) => {
const { goals, filter } = props
const goal = goals[0]
const filteredList = getFilteredHypotheses(goal.hyps, filter);
const hyps = filter.reverse ? filteredList.slice().reverse() : filteredList;
const locs = React.useContext(LocationsContext)
const goalLocs = React.useMemo(() =>
locs && goal.mvarId ?
{ ...locs, subexprTemplate: { mvarId: goal.mvarId, loc: { target: '' }}} :
undefined,
[locs, goal.mvarId])
const goalLi = <div key={'goal'}>
<div className="goal-title">Goal: </div>
<LocationsContext.Provider value={goalLocs}>
<InteractiveCode fmt={goal.type} />
</LocationsContext.Provider>
</div>
const objectHyps = hyps.filter(hyp => !hyp.isAssumption)
const assumptionHyps = hyps.filter(hyp => hyp.isAssumption)
return <div id="main-assumptions">
<div className="goals-section-title">Aktuelles Goal</div>
{filter.reverse && goalLi}
{ objectHyps.length > 0 &&
<div className="hyp-group"><div className="hyp-group-title">Objekte:</div>
{objectHyps.map((h, i) => <Hyp hyp={h} mvarId={goal.mvarId} key={i} />)}</div> }
{ assumptionHyps.length > 0 &&
<div className="hyp-group">
<div className="hyp-group-title">Annahmen:</div>
{assumptionHyps.map((h, i) => <Hyp hyp={h} mvarId={goal.mvarId} key={i} />)}
</div> }
</div>
})
export const OtherGoals = React.memo((props: GoalProps2) => {
const { goals, filter } = props
return <>
{goals && goals.length > 1 &&
<div id="other-goals" className="other-goals">
<div className="goals-section-title">Weitere Goals</div>
{goals.slice(1).map((goal, i) =>
<details key={i}>
<summary>
<InteractiveCode fmt={goal.type} />
</summary>
<Goal commandLine={false} filter={filter} goal={goal} />
</details>)}
</div>}
</>
})
export const ProofDisplay = React.memo((props : ProofDisplayProps) => {
const { proof } = props
const steps = proof.match(/.+/g)
return <>
{ steps &&
<div id="current-proof">
<div className="goals-section-title">Bisheriger Beweis</div>
<div className="proof-display-wrapper">
<div className="proof-display">
{steps.map((s) =>
<div>{s}</div>
)}
</div>
</div>
</div>}
</>
})
interface GoalsProps { interface GoalsProps {
goals: InteractiveGoals goals: InteractiveGoals
filter: GoalFilterState filter: GoalFilterState
@ -176,7 +259,7 @@ export function Goals({ goals, filter }: GoalsProps) {
return <>No goals</> return <>No goals</>
} else { } else {
return <> return <>
{goals.goals.map((g, i) => <Goal commandLine={false} key={i} goal={g} filter={filter} />)} {goals.goals.map((g, i) => <Goal commandLine={false} key={i} goal={g} filter={filter} />)}
</> </>
} }
} }

@ -3,7 +3,7 @@
import * as React from 'react'; import * as React from 'react';
import type { Location, Diagnostic } from 'vscode-languageserver-protocol'; import type { Location, Diagnostic } from 'vscode-languageserver-protocol';
import { goalsToString, Goal, FilteredGoals } from './goals' import { goalsToString, Goal, MainAssumptions, OtherGoals, FilteredGoals, ProofDisplay } from './goals'
import { basename, DocumentPosition, RangeHelpers, useEvent, usePausableState, discardMethodNotFound, import { basename, DocumentPosition, RangeHelpers, useEvent, usePausableState, discardMethodNotFound,
mapRpcError, useAsyncWithTrigger, PausableProps } from '../../../../node_modules/lean4-infoview/src/infoview/util'; mapRpcError, useAsyncWithTrigger, PausableProps } from '../../../../node_modules/lean4-infoview/src/infoview/util';
import { ConfigContext, EditorContext, LspDiagnosticsContext, ProgressContext } from '../../../../node_modules/lean4-infoview/src/infoview/contexts'; import { ConfigContext, EditorContext, LspDiagnosticsContext, ProgressContext } from '../../../../node_modules/lean4-infoview/src/infoview/contexts';
@ -17,6 +17,8 @@ import { RpcContext, useRpcSessionAtPos } from '../../../../node_modules/lean4-i
import { GoalsLocation, Locations, LocationsContext } from '../../../../node_modules/lean4-infoview/src/infoview/goalLocation'; import { GoalsLocation, Locations, LocationsContext } from '../../../../node_modules/lean4-infoview/src/infoview/goalLocation';
import { InteractiveCode } from '../../../../node_modules/lean4-infoview/src/infoview/interactiveCode' import { InteractiveCode } from '../../../../node_modules/lean4-infoview/src/infoview/interactiveCode'
import { CircularProgress } from '@mui/material'; import { CircularProgress } from '@mui/material';
import { InputModeContext, MonacoEditorContext } from '../Level'
type InfoStatus = 'updating' | 'error' | 'ready'; type InfoStatus = 'updating' | 'error' | 'ready';
type InfoKind = 'cursor' | 'pin'; type InfoKind = 'cursor' | 'pin';
@ -84,10 +86,11 @@ interface InfoDisplayContentProps extends PausableProps {
error?: string; error?: string;
userWidgets: UserWidgetInstance[]; userWidgets: UserWidgetInstance[];
triggerUpdate: () => Promise<void>; triggerUpdate: () => Promise<void>;
proof? : string;
} }
const InfoDisplayContent = React.memo((props: InfoDisplayContentProps) => { const InfoDisplayContent = React.memo((props: InfoDisplayContentProps) => {
const {pos, messages, goals, termGoal, error, userWidgets, triggerUpdate, isPaused, setPaused} = props; const {pos, messages, goals, termGoal, error, userWidgets, triggerUpdate, isPaused, setPaused, proof} = props;
const hasWidget = userWidgets.length > 0; const hasWidget = userWidgets.length > 0;
const hasError = !!error; const hasError = !!error;
@ -121,21 +124,26 @@ const InfoDisplayContent = React.memo((props: InfoDisplayContentProps) => {
<a className='link pointer dim' onClick={e => { e.preventDefault(); void triggerUpdate(); }}>{' '}Try again.</a> <a className='link pointer dim' onClick={e => { e.preventDefault(); void triggerUpdate(); }}>{' '}Try again.</a>
</div>} </div>}
<LocationsContext.Provider value={locs}> <LocationsContext.Provider value={locs}>
<div className="goals-section"> <div className="goals-section">
{ goals && ( { goals && goals.goals.length > 0 && <>
goals.goals.length > 0 <MainAssumptions filter={goalFilter} key='mainGoal' goals={goals.goals} />
? <><div className="goals-section-title">Aktuelles Goal</div> <ProofDisplay proof={proof}/>
<Goal commandLine={true} filter={goalFilter} key='mainGoal' goal={goals.goals[0]} showHints={true} /></> <OtherGoals filter={goalFilter} goals={goals.goals} />
: <div className="goals-section-title">No Goals</div> </>}
) } </div>
</div> <div>
{ goals && (goals.goals.length > 0
? <Goal commandLine={true} filter={goalFilter} key='mainGoal' goal={goals.goals[0]} showHints={true} />
: <div className="goals-section-title">No Goals</div>
)}
</div>
</LocationsContext.Provider> </LocationsContext.Provider>
{userWidgets.map(widget => {userWidgets.map(widget =>
<details key={`widget::${widget.id}::${widget.range?.toString()}`} open> <details key={`widget::${widget.id}::${widget.range?.toString()}`} open>
<summary className='mv2 pointer'>{widget.name}</summary> <summary className='mv2 pointer'>{widget.name}</summary>
<PanelWidgetDisplay pos={pos} goals={goals ? goals.goals.map (goal => goal) : []} termGoal={termGoal} <PanelWidgetDisplay pos={pos} goals={goals ? goals.goals.map (goal => goal) : []}
selectedLocations={selectedLocs} widget={widget}/> termGoal={termGoal} selectedLocations={selectedLocs} widget={widget}/>
</details> </details>
)} )}
{nothingToShow && ( {nothingToShow && (
isPaused ? isPaused ?
@ -203,12 +211,14 @@ function InfoDisplay(props0: InfoDisplayProps & InfoPinnable) {
setPaused(isPaused => !isPaused); setPaused(isPaused => !isPaused);
}); });
const editor = React.useContext(MonacoEditorContext)
return ( return (
<RpcContext.Provider value={rpcSess}> <RpcContext.Provider value={rpcSess}>
{/* <details open> */} {/* <details open> */}
{/* <InfoStatusBar {...props} triggerUpdate={triggerDisplayUpdate} isPaused={isPaused} setPaused={setPaused} /> */} {/* <InfoStatusBar {...props} triggerUpdate={triggerDisplayUpdate} isPaused={isPaused} setPaused={setPaused} /> */}
<div> <div>
<InfoDisplayContent {...props} triggerUpdate={triggerDisplayUpdate} isPaused={isPaused} setPaused={setPaused} /> <InfoDisplayContent {...props} proof={editor.getValue()} triggerUpdate={triggerDisplayUpdate} isPaused={isPaused} setPaused={setPaused} />
</div> </div>
{/* </details> */} {/* </details> */}
</RpcContext.Provider> </RpcContext.Provider>

@ -79,3 +79,52 @@
.other-goals .goals-section-title, .other-goals summary, .other-goals summary .font-code { .other-goals .goals-section-title, .other-goals summary, .other-goals summary .font-code {
color: #5191d1; color: #5191d1;
} }
.goals-section {
display: flex;
flex-direction: row;
}
.goals-section div {
flex-grow: 1;
}
#current-proof, #main-assumptions {
margin-right: 0.8em;
}
#current-proof, #other-goals {
margin-left: 0.8em;
}
.proof-display {
max-height: 6em;
overflow-y: auto;
overscroll-behavior-y: contain;
scroll-snap-type: y proximity;
color: #ccc;
}
.proof-display div:nth-last-child(4) {
color: #999;
}
.proof-display div:nth-last-child(3) {
color: #666;
}
.proof-display div:nth-last-child(2) {
color: #333;
}
.proof-display div:nth-last-child(1) {
color: #000;
scroll-snap-align: end;
}
.proof-display-wrapper {
background-color: #f0f0f0;
border-radius: 1em;
padding: 0.6em;
}

Loading…
Cancel
Save