I noticed that a change to `Lean.PrettyPrinter.Delaborator.Builtins` rebuilt more modules than I expected, so I moved a definition and reduced some dependcies. More reduction would be possible to move const-delaboration out of the big `Lean.PrettyPrinter`, and import from `Lean.PrettyPrinter` selectively.
106 lines
3.7 KiB
Text
106 lines
3.7 KiB
Text
/-
|
||
Copyright (c) 2021 Microsoft Corporation. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
|
||
Authors: Wojciech Nawrocki
|
||
-/
|
||
prelude
|
||
import Lean.Server.Rpc.Basic
|
||
import Lean.Server.InfoUtils
|
||
import Lean.Widget.TaggedText
|
||
import Lean.Widget.Basic
|
||
|
||
/-! RPC infrastructure for storing and formatting code fragments, in particular `Expr`s,
|
||
with environment and subexpression information. -/
|
||
|
||
namespace Lean.Widget
|
||
open Server
|
||
|
||
/-- A tag indicating the diff status of the expression. Used when showing tactic diffs. -/
|
||
inductive DiffTag where
|
||
| wasChanged
|
||
| willChange
|
||
| wasDeleted
|
||
| willDelete
|
||
| wasInserted
|
||
| willInsert
|
||
deriving ToJson, FromJson
|
||
|
||
/-- Information about a subexpression within delaborated code. -/
|
||
structure SubexprInfo where
|
||
/-- The `Elab.Info` node with the semantics of this part of the output. -/
|
||
info : WithRpcRef Lean.Elab.InfoWithCtx
|
||
/-- The position of this subexpression within the top-level expression. See `Lean.SubExpr`. -/
|
||
subexprPos : Lean.SubExpr.Pos
|
||
-- TODO(WN): add fields for semantic highlighting
|
||
-- kind : Lsp.SymbolKind
|
||
/-- In certain situations such as when goal states change between positions in a tactic-mode proof,
|
||
we can show subexpression-level diffs between two expressions. This field asks the renderer to
|
||
display the subexpression as in a diff view (e.g. red/green like `git diff`). -/
|
||
diffStatus? : Option DiffTag := none
|
||
deriving RpcEncodable
|
||
|
||
/-- Pretty-printed syntax (usually but not necessarily an `Expr`) with embedded `Info`s. -/
|
||
abbrev CodeWithInfos := TaggedText SubexprInfo
|
||
|
||
def CodeWithInfos.mergePosMap [Monad m] (merger : SubexprInfo → α → m SubexprInfo) (pm : Lean.SubExpr.PosMap α) (tt : CodeWithInfos) : m CodeWithInfos :=
|
||
if pm.isEmpty then return tt else
|
||
tt.mapM (fun (info : SubexprInfo) =>
|
||
match pm.find? info.subexprPos with
|
||
| some a => merger info a
|
||
| none => pure info
|
||
)
|
||
|
||
def CodeWithInfos.pretty (tt : CodeWithInfos) :=
|
||
tt.stripTags
|
||
|
||
def SubexprInfo.withDiffTag (tag : DiffTag) (c : SubexprInfo) : SubexprInfo :=
|
||
{ c with diffStatus? := some tag }
|
||
|
||
/-- Tags pretty-printed code with infos from the delaborator. -/
|
||
partial def tagCodeInfos (ctx : Elab.ContextInfo) (infos : SubExpr.PosMap Elab.Info) (tt : TaggedText (Nat × Nat))
|
||
: CodeWithInfos :=
|
||
go tt
|
||
where
|
||
go (tt : TaggedText (Nat × Nat)) :=
|
||
tt.rewrite fun (n, _) subTt =>
|
||
match infos.find? n with
|
||
| none => go subTt
|
||
| some i =>
|
||
let t : SubexprInfo := {
|
||
info := WithRpcRef.mk { ctx, info := i, children := .empty }
|
||
subexprPos := n
|
||
}
|
||
TaggedText.tag t (go subTt)
|
||
|
||
def ppExprTagged (e : Expr) (explicit : Bool := false) : MetaM CodeWithInfos := do
|
||
if pp.raw.get (← getOptions) then
|
||
return .text (toString (← instantiateMVars e))
|
||
let delab := open PrettyPrinter.Delaborator in
|
||
if explicit then
|
||
withOptionAtCurrPos pp.tagAppFns.name true do
|
||
withOptionAtCurrPos pp.explicit.name true do
|
||
withOptionAtCurrPos pp.mvars.name true do
|
||
delabApp
|
||
else
|
||
withOptionAtCurrPos pp.proofs.name true do
|
||
delab
|
||
let mut e := e
|
||
-- When hovering over a metavariable, we want to see its value, even if `pp.instantiateMVars` is false.
|
||
if explicit && e.isMVar then
|
||
if let some e' ← getExprMVarAssignment? e.mvarId! then
|
||
e := e'
|
||
let ⟨fmt, infos⟩ ← PrettyPrinter.ppExprWithInfos e (delab := delab)
|
||
let tt := TaggedText.prettyTagged fmt
|
||
let ctx := {
|
||
env := (← getEnv)
|
||
mctx := (← getMCtx)
|
||
options := (← getOptions)
|
||
currNamespace := (← getCurrNamespace)
|
||
openDecls := (← getOpenDecls)
|
||
fileMap := default
|
||
ngen := (← getNGen)
|
||
}
|
||
return tagCodeInfos ctx infos tt
|
||
|
||
end Lean.Widget
|