import Lean set_option doc.verso true /-! This test checks that indentation-specific Verso syntax in docstrings is processed relative to their indentation, rather than an absolute column 0. -/ open Lean Elab Command in def printVersoDocstring (name : Name) : CommandElabM Unit := do match (← findInternalDocString? (← getEnv) name) with | none => IO.println s!"No docstring for {name}" | some (.inl md) => IO.println s!"Markdown:\n{md}" | some (.inr v) => IO.println (repr v.text); IO.println (repr v.subsections) -- Test 1: Indented header on non-first line (e.g. inside where block) def foo := bar where /-- # Header in where block Content here -/ bar := 1 /-- info: #[] #[{ title := #[Lean.Doc.Inline.text "Header in where block"], titleString := "Header in where block", metadata := none, content := #[Lean.Doc.Block.para #[Lean.Doc.Inline.text "Content here", Lean.Doc.Inline.linebreak "\n", Lean.Doc.Inline.text " "]], subParts := #[] }] -/ #guard_msgs in #eval printVersoDocstring ``foo.bar -- Test 2: Multiple headers at indentation level namespace Indented /-- # First header Some text. ## Second header More text. -/ def baz := 1 end Indented /-- info: #[] #[{ title := #[Lean.Doc.Inline.text "First header"], titleString := "First header", metadata := none, content := #[Lean.Doc.Block.para #[Lean.Doc.Inline.text "Some text."]], subParts := #[{ title := #[Lean.Doc.Inline.text "Second header"], titleString := "Second header", metadata := none, content := #[Lean.Doc.Block.para #[Lean.Doc.Inline.text "More text.", Lean.Doc.Inline.linebreak "\n", Lean.Doc.Inline.text " "]], subParts := #[] }] }] -/ #guard_msgs in #eval printVersoDocstring ``Indented.baz -- Test 3: First-line header still works when indented namespace FirstLine /-- # Inline header -/ def qux := 1 /-- # Inline header # Indented -/ def quux := 1 end FirstLine /-- info: #[] #[{ title := #[Lean.Doc.Inline.text "Inline header "], titleString := "Inline header ", metadata := none, content := #[], subParts := #[] }] -/ #guard_msgs in #eval printVersoDocstring ``FirstLine.qux /-- info: #[] #[{ title := #[Lean.Doc.Inline.text "Inline header"], titleString := "Inline header", metadata := none, content := #[], subParts := #[] }, { title := #[Lean.Doc.Inline.text "Indented"], titleString := "Indented", metadata := none, content := #[], subParts := #[] }] -/ #guard_msgs in #eval printVersoDocstring ``FirstLine.quux -- Test 4: Indented code block fences namespace CodeBlock /-- # Code example Some intro text. ``` example code ``` -/ def withCode := 1 end CodeBlock /-- info: #[] #[{ title := #[Lean.Doc.Inline.text "Code example"], titleString := "Code example", metadata := none, content := #[Lean.Doc.Block.para #[Lean.Doc.Inline.text "Some intro text."], Lean.Doc.Block.code "example code\n"], subParts := #[] }] -/ #guard_msgs in #eval printVersoDocstring ``CodeBlock.withCode -- Test 5: Deeply nested indentation (column 8+) namespace Deep namespace Deeper namespace Deepest /-- # Deep header Content at depth. -/ def deep := 1 end Deepest end Deeper end Deep /-- info: #[] #[{ title := #[Lean.Doc.Inline.text "Deep header"], titleString := "Deep header", metadata := none, content := #[Lean.Doc.Block.para #[Lean.Doc.Inline.text "Content at depth.", Lean.Doc.Inline.linebreak "\n", Lean.Doc.Inline.text " "]], subParts := #[] }] -/ #guard_msgs in #eval printVersoDocstring ``Deep.Deeper.Deepest.deep -- Test 6: Non-indented /-- # Top-level header Content. -/ def topLevel := 1 /-- info: #[] #[{ title := #[Lean.Doc.Inline.text "Top-level header"], titleString := "Top-level header", metadata := none, content := #[Lean.Doc.Block.para #[Lean.Doc.Inline.text "Content.", Lean.Doc.Inline.linebreak "\n"]], subParts := #[] }] -/ #guard_msgs in #eval printVersoDocstring ``topLevel -- Test 7: Indented link reference namespace Links /-- # Header with link See [Lean][lean-link] for more. [lean-link]: https://lean-lang.org -/ def withLink := 1 end Links /-- info: #[] #[{ title := #[Lean.Doc.Inline.text "Header with link"], titleString := "Header with link", metadata := none, content := #[Lean.Doc.Block.para #[Lean.Doc.Inline.text "See ", Lean.Doc.Inline.link #[Lean.Doc.Inline.text "Lean"] "https://lean-lang.org", Lean.Doc.Inline.text " for more."], Lean.Doc.Block.concat #[]], subParts := #[] }] -/ #guard_msgs in #eval printVersoDocstring ``Links.withLink -- Test 8: Over-indented # is a syntax error (extra spaces beyond base column) /-- @ +5:4...* error: expected '#' (header) to start at column 2 -/ #guard_msgs (positions := true) in def overIndented := bar where /-- Some text. # Not a header -/ bar := 1