@@ -2,6 +2,7 @@ import SubVerso.Examples
22import Lean.Data.NameMap
33import Lean.DocString.Syntax
44import VersoManual
5+ import Verso.Code.HighlightedToTex
56
67open Lean (NameMap MessageSeverity)
78open Lean.Doc.Syntax
@@ -520,26 +521,16 @@ def tpilInline (inline : InlineDescr) : InlineDescr :=
520521 inline.extraCssFiles
521522 }
522523
523- def trimOneLeadingNl : Highlighted → Highlighted
524- | .text s => .text <| if "\n " .isPrefixOf s then s.drop 1 else s
525- | .unparsed s => .unparsed <| if "\n " .isPrefixOf s then s.drop 1 else s
526- | .seq xs =>
527- let i? := xs.findIdx? (!·.isEmpty)
528- match h : i? with
529- | some i =>
530- have : i < xs.size := (Array.findIdx?_eq_some_iff_findIdx_eq.mp h).left
531- xs.extract (i+1 ) |>.foldl (init := trimOneLeadingNl xs[i]) (· ++ ·)
532- | none => .empty
533- | hl@(.point ..) | hl@(.token ..) => hl
534- | .tactics i s e hl => .tactics i s e (trimOneLeadingNl hl)
535- | .span i hl => .span i (trimOneLeadingNl hl)
536-
537524structure ExampleItem where
538525 code : Highlighted
539526 output : Option Highlighted.Message
540527 trailing : String
541528deriving ToJson, FromJson, Repr, Quote
542529
530+ def verbatimBlock (cmd : Highlighted) : TeX :=
531+ let contents := cmd.trimOneTrailingNl.trimOneLeadingNl.toVerbatimTeX
532+ .seq #[.raw s! "\\ begin\{ LeanVerbatim} [vspace=0pt]\n " , contents, .raw "\n\\ end{LeanVerbatim}\n " ]
533+
543534block_extension Block.lean
544535 (allowToggle : Bool)
545536 (pre : Option Highlighted)
@@ -570,7 +561,50 @@ block_extension Block.lean
570561 let v := if let .obj _ := v then v else .obj {}
571562 v.setObjVal! link.link (json%{"context" : $context, "display" : $s}))
572563 pure none
573- toTeX := none
564+ toTeX :=
565+ open Verso.Output.TeX in
566+ open Verso.Doc.TeX in
567+ some <| fun _ _ _ data _ => do
568+ let .arr #[.bool _allowToggle, hlPreJson, hlJson, hlPostJson, goalVisibilityJson, _defs] := data
569+ | logError "Expected five-element JSON for Lean code"
570+ pure .empty
571+ let pre ←
572+ match FromJson.fromJson? (α := Option Highlighted) hlPreJson with
573+ | .error err =>
574+ logError <| "Couldn't deserialize Lean code intro block while rendering HTML: " ++ err
575+ return .empty
576+ | .ok hl => pure hl
577+ let code ←
578+ match FromJson.fromJson? (α := Array ExampleItem) hlJson with
579+ | .error err =>
580+ logError <| "Couldn't deserialize Lean code block while rendering HTML: " ++ err
581+ return .empty
582+ | .ok hl => pure hl
583+ let post ←
584+ match FromJson.fromJson? (α := Option Highlighted) hlPostJson with
585+ | .error err =>
586+ logError <| "Couldn't deserialize Lean code outro block while rendering HTML: " ++ err
587+ return .empty
588+ | .ok hl => pure hl
589+ let visibility ←
590+ match FromJson.fromJson? (α := HighlightHtmlM.VisibleProofStates) goalVisibilityJson with
591+ | .error err =>
592+ logError <| "Couldn't deserialize Lean code outro block while rendering HTML: " ++ err
593+ return .empty
594+ | .ok hl => pure hl
595+ let codeIndent := code.foldl (init := pre.map (·.indentation)) (fun i? y => i?.map (min · y.1 .indentation)) |>.getD 0
596+ let mut codeTeX : TeX := .empty
597+
598+ for ⟨cmd, out?, ws⟩ in code do
599+ let cmd := cmd.deIndent codeIndent
600+ codeTeX := codeTeX ++ verbatimBlock cmd
601+ if let some msg := out? then
602+ codeTeX := codeTeX ++ msg.toTeX
603+ unless ws.isEmpty do
604+ codeTeX := codeTeX ++ (Highlighted.text ws).toTeX
605+
606+ pure codeTeX
607+
574608 extraJsFiles := [{filename := "copybutton.js" , contents := copyButtonJs, sourceMap? := none}]
575609 extraCssFiles := [("copybutton.css" , copyButtonCss), ("examples.css" , examplesCss)]
576610 toHtml :=
@@ -615,7 +649,7 @@ block_extension Block.lean
615649 let inner ←
616650 withDefinitionsAsTargets false <|
617651 withVisibleProofStates visibility <|
618- trimOneLeadingNl p |>.blockHtml "examples" (trim := false ) (g := Verso.Genre.Manual)
652+ p.trimOneLeadingNl |>.blockHtml "examples" (trim := false ) (g := Verso.Genre.Manual)
619653 codeHtml := codeHtml ++ {{ <div class ="hidden" >{{ inner }}</div> }}
620654 codeString := codeString ++ p.toString
621655
@@ -624,7 +658,7 @@ block_extension Block.lean
624658 let moreCode ←
625659 withDefinitionsAsTargets true <|
626660 withVisibleProofStates visibility <|
627- trimOneLeadingNl cmd |>.blockHtml "examples" (trim := false ) (g := Verso.Genre.Manual)
661+ cmd.trimOneLeadingNl |>.blockHtml "examples" (trim := false ) (g := Verso.Genre.Manual)
628662 codeHtml := codeHtml ++ moreCode
629663 codeString := codeString ++ cmd.toString
630664 if let some msg := out? then
@@ -639,7 +673,7 @@ block_extension Block.lean
639673 let inner ←
640674 withDefinitionsAsTargets false <|
641675 withVisibleProofStates visibility <|
642- trimOneLeadingNl p |>.blockHtml "examples" (trim := false ) (g := Verso.Genre.Manual)
676+ p.trimOneLeadingNl |>.blockHtml "examples" (trim := false ) (g := Verso.Genre.Manual)
643677 codeHtml := codeHtml ++ {{ <div class ="hidden" >{{ inner }}</div> }}
644678 codeString := codeString ++ p.toString
645679
@@ -660,7 +694,29 @@ block_extension Block.leanAnchor (code : Highlighted) (completeCode : String)
660694 via withHighlighting, tpilBlock where
661695 data := .arr #[toJson code, toJson completeCode]
662696 traverse _ _ _ := pure none
663- toTeX := none
697+ toTeX :=
698+ open Verso.Output.TeX in
699+ open Verso.Doc.TeX in
700+ some <| fun _ _ _ data _ => do
701+ let .arr #[hlJson, completeCodeJson] := data
702+ | logError "Expected two-element JSON for Lean code"
703+ pure .empty
704+ let code ←
705+ match FromJson.fromJson? (α := Highlighted) hlJson with
706+ | .error err =>
707+ logError <| "Couldn't deserialize Lean code block while rendering TeX: " ++ err
708+ return .empty
709+ | .ok hl => pure hl
710+ let completeCode ←
711+ match FromJson.fromJson? (α := String) completeCodeJson with
712+ | .error err =>
713+ logError <| "Couldn't deserialize Lean code string while rendering TeX: " ++ err
714+ return .empty
715+ | .ok hl => pure hl
716+
717+ let code := code.deIndent code.indentation
718+ pure (verbatimBlock code)
719+
664720 toHtml :=
665721 open Verso.Output.Html in
666722 some <| fun _ _ _ data _ => do
@@ -729,7 +785,18 @@ block_extension Block.goals (goals : Array (Highlighted.Goal Highlighted))
729785 via withHighlighting, tpilBlock where
730786 data := toJson goals
731787 traverse _ _ _ := pure none
732- toTeX := none
788+ toTeX :=
789+ open Verso.Output.TeX in
790+ open Verso.Doc.TeX in
791+ some <| fun _ _ _ data _ => do
792+ let goals ←
793+ match fromJson? (α := Array (Highlighted.Goal Highlighted)) data with
794+ | .ok v => pure v
795+ | .error e =>
796+ logError <| "Failed to deserialize proof state: " ++ e
797+ return .empty
798+ -- TODO: lay these out side-by-side
799+ pure <| .seq (goals.map (·.toTeX))
733800 extraCssFiles := [ ("proof-state.css" , proofStateStyle)]
734801 toHtml :=
735802 open Verso.Output.Html in
@@ -756,7 +823,18 @@ inline_extension Inline.goal (goal : Highlighted.Goal Highlighted)
756823 via withHighlighting, tpilInline where
757824 data := toJson goal
758825 traverse _ _ _ := pure none
759- toTeX := none
826+ toTeX :=
827+ open Verso.Doc.TeX in
828+ open Verso.Output.TeX in
829+ some <| fun _ _ data _ => do
830+ let goal ←
831+ match fromJson? (α := Highlighted.Goal Highlighted) data with
832+ | .ok v => pure v
833+ | .error e =>
834+ logError <| "Failed to deserialize proof goal: " ++ e
835+ return .empty
836+ pure (SubVerso.Highlighting.verbatim (goal.name.getD "<anonymous>" ))
837+
760838 toHtml :=
761839 open Verso.Output.Html in
762840 some <| fun _ _ data _ => do
@@ -810,7 +888,27 @@ kbd > code {
810888inline_extension Inline.kbd (items : Array String) where
811889 data := toJson items
812890 traverse _ _ _ := pure none
813- toTeX := none
891+ toTeX :=
892+ open Verso.Output.TeX in
893+ open Verso.Doc.TeX in
894+ let verb (s : String) : TeX := .seq #[.raw "\\ verb|" , .raw s, raw "|" ] -- Fails if s contains "|"
895+ let verbs (ss : List String) : TeX := List.intersperse (TeX.text " " ) (ss.map verb)
896+ some <| fun _ _ data _ => do
897+ let items ←
898+ match fromJson? (α := Array String) data with
899+ | .ok v => pure v
900+ | .error e =>
901+ logError <| "Failed to deserialize keyboard shortcut: " ++ e
902+ return .empty
903+ if let #[item] := items then
904+ if item.startsWith "\\ " then
905+ pure (verb item)
906+ else
907+ let items : List String := item.toList.map fun c => s! "{ c} "
908+ pure (verbs items)
909+ else
910+ pure (verbs items.toList)
911+
814912 extraCss := [kbdCSS]
815913 toHtml :=
816914 open Verso.Output.Html in
0 commit comments