hints and diags in editor

v4.6.0-bump
Jon Eugster 2 years ago
parent 976d1c6901
commit c0acde14e2

@ -68,12 +68,12 @@ function hasHiddenHints(step: InteractiveGoalsWithHints): boolean {
} }
export function MoreHelpButton() { export function MoreHelpButton({selected=null} : {selected?: number}) {
const {proof, setProof} = React.useContext(ProofContext) const {proof, setProof} = React.useContext(ProofContext)
const {deletedChat, setDeletedChat, showHelp, setShowHelp} = React.useContext(DeletedChatContext) const {deletedChat, setDeletedChat, showHelp, setShowHelp} = React.useContext(DeletedChatContext)
let k = proof.steps.length - (lastStepHasErrors(proof) ? 2 : 1) let k = (selected === null) ? (proof.steps.length - (lastStepHasErrors(proof) ? 2 : 1)) : selected
const activateHiddenHints = (ev) => { const activateHiddenHints = (ev) => {
// If the last step (`k`) has errors, we want the hidden hints from the // If the last step (`k`) has errors, we want the hidden hints from the

@ -155,7 +155,20 @@ export function Main(props: { world: string, level: number, data: LevelInfo}) {
const {worldId, levelId} = React.useContext(WorldLevelIdContext) const {worldId, levelId} = React.useContext(WorldLevelIdContext)
const { proof, setProof } = React.useContext(ProofContext) const { proof, setProof } = React.useContext(ProofContext)
const {selectedStep, setSelectedStep} = React.useContext(SelectionContext)
const { setDeletedChat, showHelp, setShowHelp } = React.useContext(DeletedChatContext)
function toggleSelection(line: number) {
return (ev) => {
console.debug('toggled selection')
if (selectedStep == line) {
setSelectedStep(undefined)
} else {
setSelectedStep(line)
}
}
}
console.debug(`template: ${props.data?.template}`) console.debug(`template: ${props.data?.template}`)
// React.useEffect (() => { // React.useEffect (() => {
@ -182,6 +195,19 @@ export function Main(props: { world: string, level: number, data: LevelInfo}) {
const curUri = useEventResult(ec.events.changedCursorLocation, loc => loc?.uri); const curUri = useEventResult(ec.events.changedCursorLocation, loc => loc?.uri);
const curPos: DocumentPosition | undefined =
useEventResult(ec.events.changedCursorLocation, loc => loc ? { uri: loc.uri, ...loc.range.start } : undefined)
// Effect when the cursor changes in the editor
React.useEffect(() => {
// TODO: this is a bit of a hack and will yield unexpected behaviour if lines
// are indented.
let newPos = curPos?.line + (curPos?.character == 0 ? 0 : 1)
// scroll the chat along
setSelectedStep(newPos)
}, [curPos])
useClientNotificationEffect( useClientNotificationEffect(
'textDocument/didClose', 'textDocument/didClose',
(params: DidCloseTextDocumentParams) => { (params: DidCloseTextDocumentParams) => {
@ -208,6 +234,11 @@ export function Main(props: { world: string, level: number, data: LevelInfo}) {
ret = <div className="infoview vscode-light"> ret = <div className="infoview vscode-light">
{proof.completed && <div className="level-completed">Level completed! 🎉</div>} {proof.completed && <div className="level-completed">Level completed! 🎉</div>}
<Infos /> <Infos />
<Hints hints={proof.steps[curPos?.line]?.goals[0]?.hints}
showHidden={showHelp.has(curPos?.line)} step={curPos?.line}
selected={selectedStep} toggleSelection={toggleSelection(curPos?.line)}
lastLevel={curPos?.line == proof.steps.length - 1}/>
<MoreHelpButton selected={curPos?.line}/>
</div> </div>
} }

@ -194,16 +194,24 @@ export function AllMessages() {
</a> </a>
</span> </span>
</summary> */} </summary> */}
<AllMessagesBody uri={curPos.uri} key={curPos.uri} messages={iDiags0} /> <AllMessagesBody uri={curPos.uri} key={curPos.uri} messages={iDiags0} curPos={curPos} />
{/* </Details> */} {/* </Details> */}
</RpcContext.Provider> </RpcContext.Provider>
) )
} }
/** We factor out the body of {@link AllMessages} which lazily fetches its contents only when expanded. */ /** We factor out the body of {@link AllMessages} which lazily fetches its contents only when expanded. */
function AllMessagesBody({uri, messages}: {uri: DocumentUri, messages: () => Promise<InteractiveDiagnostic[]>}) { function AllMessagesBody({uri, curPos, messages}: {uri: DocumentUri, curPos: DocumentPosition | undefined , messages: () => Promise<InteractiveDiagnostic[]>}) {
const [msgs, setMsgs] = React.useState<InteractiveDiagnostic[] | undefined>(undefined) const [msgs, setMsgs] = React.useState<InteractiveDiagnostic[] | undefined>(undefined)
React.useEffect(() => { void messages().then(setMsgs) }, [messages]) React.useEffect(() => { void messages().then(
msgs => setMsgs(msgs.filter(
(d)=>{
//console.log(`message start: ${d.range.start.line}. CurPos: ${curPos.line}`)
// Only show the messages from the line where the cursor is.
return d.range.start.line == curPos.line
}))
) }, [messages, curPos])
if (msgs === undefined) return <div>Loading messages...</div> if (msgs === undefined) return <div>Loading messages...</div>
else return <MessagesList uri={uri} messages={msgs}/> else return <MessagesList uri={uri} messages={msgs}/>
} }

@ -73,7 +73,7 @@ function Level() {
</WorldLevelIdContext.Provider> </WorldLevelIdContext.Provider>
} }
function ChatPanel({lastLevel}) { function ChatPanel({lastLevel, visible = true}) {
const chatRef = useRef<HTMLDivElement>(null) const chatRef = useRef<HTMLDivElement>(null)
const {mobile} = useContext(PreferencesContext) const {mobile} = useContext(PreferencesContext)
const gameId = useContext(GameIdContext) const gameId = useContext(GameIdContext)
@ -122,7 +122,7 @@ function ChatPanel({lastLevel}) {
let introText: Array<string> = level?.data?.introduction.split(/\n(\s*\n)+/) let introText: Array<string> = level?.data?.introduction.split(/\n(\s*\n)+/)
return <div className="chat-panel"> return <div className={`chat-panel ${visible ? '' : 'hidden'}`}>
<div ref={chatRef} className="chat"> <div ref={chatRef} className="chat">
{introText?.filter(t => t.trim()).map(((t, i) => {introText?.filter(t => t.trim()).map(((t, i) =>
// Show the level's intro text as hints, too // Show the level's intro text as hints, too
@ -177,7 +177,7 @@ function ChatPanel({lastLevel}) {
} }
function ExercisePanel({codeviewRef, visible=true}) { function ExercisePanel({codeviewRef, visible=true}: {codeviewRef: React.MutableRefObject<HTMLDivElement>, visible?: boolean}) {
const gameId = React.useContext(GameIdContext) const gameId = React.useContext(GameIdContext)
const {worldId, levelId} = useContext(WorldLevelIdContext) const {worldId, levelId} = useContext(WorldLevelIdContext)
const level = useLoadLevelQuery({game: gameId, world: worldId, level: levelId}) const level = useLoadLevelQuery({game: gameId, world: worldId, level: levelId})
@ -602,7 +602,7 @@ function useLevelEditor(codeviewRef, initialCode, initialSelections, onDidChange
setInfoProvider(infoProvider) setInfoProvider(infoProvider)
// TODO: it looks like we get errors "File Changed" here. // TODO: it looks like we get errors "File Changed" here.
client.restart() client.restart("Lean4Game")
const editorApi = infoProvider.getApi() const editorApi = infoProvider.getApi()

Loading…
Cancel
Save