@@ -7,6 +7,8 @@ import Lean.Meta.Tactic.TryThis
77import Batteries.Linter.UnreachableTactic
88import Batteries.Control.Nondet.Basic
99import Mathlib.Init
10+ import Mathlib.Lean.Elab.InfoTree
11+ import Mathlib.Tactic.Basic
1012
1113/-!
1214# The `hint` tactic.
@@ -64,28 +66,14 @@ elab (name := registerHintStx)
6466initialize
6567 Batteries.Linter.UnreachableTactic.ignoreTacticKindsRef.modify fun s => s.insert ``registerHintStx
6668
67- /--
68- Extracts the `MessageData` from the first clickable `Try This:` diff widget in the message.
69- Preserves (only) contexts and tags.
70- -/
71- private def getFirstTryThisFromMessage? : MessageData → Option MessageData
72- | .ofWidget w msg => if w.id == ``Meta.Hint.tryThisDiffWidget then msg else none
73- | .nest _ msg
74- | .group msg => getFirstTryThisFromMessage? msg
75- | .compose msg₁ msg₂ => getFirstTryThisFromMessage? msg₁ <|> getFirstTryThisFromMessage? msg₂
76- | .withContext ctx msg => (getFirstTryThisFromMessage? msg).map <| .withContext ctx
77- | .withNamingContext ctx msg => (getFirstTryThisFromMessage? msg).map <| .withNamingContext ctx
78- | .tagged tag msg => (getFirstTryThisFromMessage? msg).map <| .tagged tag
79- | .ofFormatWithInfos _ | .ofGoal _ | .trace .. | .ofLazy .. => none
80-
8169/--
8270Construct a suggestion for a tactic.
8371* Check the passed `MessageLog` for an info message beginning with "Try this: ".
8472* If found, use that as the suggestion.
8573* Otherwise use the provided syntax.
8674* Also, look for remaining goals and pretty print them after the suggestion.
8775 -/
88- def suggestion (tac : TSyntax `tactic) (msgs : MessageLog := {} ) : TacticM Suggestion := do
76+ def suggestion (tac : TSyntax `tactic) (trees : PersistentArray InfoTree ) : TacticM Suggestion := do
8977 -- TODO `addExactSuggestion` has an option to construct `postInfo?`
9078 -- Factor that out so we can use it here instead of copying and pasting?
9179 let goals ← getGoals
@@ -102,27 +90,12 @@ def suggestion (tac : TSyntax `tactic) (msgs : MessageLog := {}) : TacticM Sugge
10290 -/
10391 -- let style? := if goals.isEmpty then some .success else none
10492 let preInfo? := if goals.isEmpty then some "🎉 " else none
105- let msg? : Option MessageData := msgs.toList.firstM (getFirstTryThisFromMessage? ·.data)
106- let suggestion ← match msg ? with
107- | some m => pure <| SuggestionText.string (← m.toString)
108- | none => pure <| SuggestionText.tsyntax tac
93+ let suggestions := collectTryThisSuggestions trees
94+ let suggestion := match suggestions[ 0 ] ? with
95+ | some s => s.suggestion
96+ | none => SuggestionText.tsyntax tac
10997 return { preInfo?, suggestion, postInfo? }
11098
111- /-- Run a tactic, returning any new messages rather than adding them to the message log. -/
112- def withMessageLog (t : TacticM Unit) : TacticM MessageLog := do
113- let initMsgs ← modifyGetThe Core.State fun st => (st.messages, { st with messages := {} })
114- t
115- modifyGetThe Core.State fun st => (st.messages, { st with messages := initMsgs })
116-
117- /--
118- Run a tactic, but revert any changes to info trees.
119- We use this to inhibit the creation of widgets by subsidiary tactics.
120- -/
121- def withoutInfoTrees (t : TacticM Unit) : TacticM Unit := do
122- let trees := (← getInfoState).trees
123- t
124- modifyInfoState fun s => { s with trees }
125-
12699/--
127100Run all tactics registered using `register_hint`.
128101Print a "Try these:" suggestion for each of the successful tactics.
@@ -136,11 +109,11 @@ def hint (stx : Syntax) : TacticM Unit := withMainContext do
136109 let tacs := (← getHints).toArray.qsort (·.1 > ·.1 ) |>.toList.map (·.2 )
137110 let tacs := Nondet.ofList tacs
138111 let results := tacs.filterMapM fun t : TSyntax `tactic => do
139- if let some msgs ← observing? (withMessageLog (withoutInfoTrees ( evalTactic t) )) then
112+ if let some { msgs, trees, .. } ← observing? (withResetServerInfo ( evalTactic t)) then
140113 if msgs.hasErrors then
141114 return none
142115 else
143- return some (← getGoals, ← suggestion t msgs )
116+ return some (← getGoals, ← suggestion t trees )
144117 else
145118 return none
146119 let results ← (results.toMLList.takeUpToFirst fun r => r.1 .1 .isEmpty).asArray
0 commit comments