Zulip Chat Archive
Stream: lean4
Topic: Using `exprDiff` in widgets
Eric Wieser (Jul 16 2024 at 10:49):
I'm trying to print the output of docs#Lean.Widget.exprDiff as a widget, using the <InteractiveCode>
widget, but the diff doesn't seem to be showing up:
import Lean
import ProofWidgets.Data.Html
import ProofWidgets.Component.HtmlDisplay
open Lean Json
open ProofWidgets Jsx
def diff (before after : Name) : MetaM Html := do
let before_t := (← Lean.getConstInfo before).type
let after_t := (← Lean.getConstInfo after).type
let diff ← Lean.Widget.exprDiff before_t after_t
let before_tagged ← Widget.ppExprTagged before_t
let after_tagged ← Widget.ppExprTagged after_t
let before_diff ← Lean.Widget.addDiffTags false diff before_tagged
let after_diff ← Lean.Widget.addDiffTags true diff after_tagged
return <div>
<InteractiveCode fmt={before_diff} /><br />
<InteractiveCode fmt={after_diff} />
</div>
syntax "#diff_types" ident ident : command
elab_rules : command
| `(#diff_types%$tk $a:ident $b:ident) => Elab.Command.liftTermElabM do
let h ← diff a.getId b.getId
Widget.savePanelWidgetInfo (hash ProofWidgets.HtmlDisplayPanel.javascript)
(return json% { html: $(← Server.RpcEncodable.rpcEncode h) }) tk
/-- begin example -/
theorem foo : 1 + 2 = 3 := sorry
theorem bar : 2 + 1 = 3 := sorry
-- doesn't show any diff
#diff_types foo bar
Eric Wieser (Jul 16 2024 at 10:50):
(this doesn't seem to work at all in the web editor due to The requested module 'blob:https://live.lean-lang.org/99574127-ee5e-469d-9348-e622cadff5ad' does not provide an export named 'useRpcSession'
)
Henrik Böving (Jul 16 2024 at 11:19):
@Joachim Breitner is this the fault of our workaround?
Anand Rao Tadipatri (Jul 16 2024 at 11:30):
This widget works on v4.8.0-rc1
, but without the diff highlighting.
Eric Wieser (Jul 16 2024 at 11:35):
Yes, to be clear my issue is that the types appear with no highlighting
Eric Wieser (Jul 16 2024 at 11:49):
It looks to me like Lean.Widget.addDiffTags
is not actually populating the tags?
Henrik Böving (Jul 16 2024 at 11:50):
Ah probably not from our recent workaround then.
Eric Wieser (Jul 16 2024 at 11:50):
open private ExprDiffTag from Lean.Widget.Diff
deriving instance Repr for ExprDiffTag
deriving instance Repr for Widget.DiffTag
deriving instance Repr for Widget.ExprDiff
partial def Lean.Widget.TaggedText.listTags {α} : Widget.TaggedText α → List α
| .text _ => []
| .tag t inner => t :: inner.listTags
| .append ars => (ars.toList.bind Lean.Widget.TaggedText.listTags)
and running Lean.logInfo m!"{repr (before_diff.listTags.map (·.diffStatus?))}"
gives a list of none
s
Patrick Massot (Jul 16 2024 at 12:07):
@Wojciech Nawrocki
Anand Rao Tadipatri (Jul 16 2024 at 12:08):
Here is one way of rendering diffs of expressions that has worked for me in the past:
import Lean
import ProofWidgets.Data.Html
import ProofWidgets.Component.HtmlDisplay
namespace Lean
open Lean ProofWidgets Widget Server Jsx
def Widget.CodeWithInfos.addDiffs (diffs : AssocList SubExpr.Pos DiffTag) (code : CodeWithInfos) : CodeWithInfos :=
code.map fun info ↦
match diffs.find? info.subexprPos with
| some diff => { info with diffStatus? := some diff }
| none => info
def Expr.renderWithDiffs (e : Expr) (diffs : AssocList SubExpr.Pos DiffTag) : MetaM Html := do
let e' := (← Widget.ppExprTagged e).addDiffs diffs
return <InteractiveCode fmt={e'} />
def Name.renderWithDiffs (nm : Name) (diffs : AssocList SubExpr.Pos DiffTag) : MetaM Html := do
let env ← getEnv
let some ci := env.find? nm | failure
ci.type.renderWithDiffs diffs
end Lean
open Lean ProofWidgets
elab stx:"#test_diff_render" thm:ident : command => Elab.Command.liftTermElabM do
let h ← thm.getId.renderWithDiffs (.cons (.root |>.pushBindingBody |>.pushAppArg) .willChange .nil)
Widget.savePanelWidgetInfo (hash ProofWidgets.HtmlDisplayPanel.javascript)
(return json% { html: $(← Server.RpcEncodable.rpcEncode h) }) stx
#test_diff_render Nat.mul_zero
Eric Wieser (Jul 16 2024 at 12:22):
With that example, I have to build the diff myself rather than using Lean.Widget.exprDiff
, right?
Joachim Breitner (Jul 16 2024 at 12:25):
Henrik Böving said:
Joachim Breitner is this the fault of our workaround?
Which work-around again?
𝚠𝚘𝚓𝚌𝚒𝚎𝚌𝚑 𝚗𝚊𝚠𝚛𝚘𝚌𝚔𝚒 (Jul 16 2024 at 12:25):
Eric Wieser said:
(this doesn't seem to work at all in the web editor due to
The requested module 'blob:https://live.lean-lang.org/99574127-ee5e-469d-9348-e622cadff5ad' does not provide an export named 'useRpcSession'
)
Ah, most likely the web editor needs to update its @leanprover/infoview
dependency.
Eric Wieser (Jul 16 2024 at 12:27):
Eric Wieser said:
It looks to me like
Lean.Widget.addDiffTags
is not actually populating the tags?
Looking more closely; the Pos
info in the result of exprDiff
doesn't match with the pos info in ppExprTagged
Eric Wieser (Jul 16 2024 at 12:28):
It works correctly if the theorems being compared start with a pi binder! That is, my original code works with
theorem foo2 {x} : x + 2 = 3 := sorry
theorem bar2 {x} : 2 + x = 3 := sorry
-- works
#diff_types foo2 bar2
Henrik Böving (Jul 16 2024 at 12:29):
Joachim Breitner said:
Henrik Böving said:
Joachim Breitner is this the fault of our workaround?
Which work-around again?
The one where we hide symbols from the LSP, but it's not it.
Eric Wieser (Jul 16 2024 at 23:06):
I think the issue here is that the diff highlighting only works if the Subexpr
being highlighted already has info attached
Eric Wieser (Jul 16 2024 at 23:07):
In my original example, it fails because exprDiff
detects the diff at the nat_lit 1
in @OfNat.ofNat _ _ (nat_lit 1)
, but the tagged format only records a node for the entire @OfNat.ofNat
node
Last updated: May 02 2025 at 03:31 UTC