This PR adds support for blockquotes to Verso docstrings, which had been missing before. It also substantially improves the robustness of Verso->Markdown rendering of docstrings, especially the handling of blockquote line prefixes.
362 lines
7.1 KiB
Text
362 lines
7.1 KiB
Text
import Lean.Elab.Command
|
||
|
||
set_option doc.verso true
|
||
|
||
/-!
|
||
# Verso Docstring Markdown Tests
|
||
|
||
This module tests the Markdown rendering of all the builtin Verso docstring operators.
|
||
|
||
Each section begins with a command that will fail when a new, untested operator is added.
|
||
|
||
## Helpers
|
||
|
||
-/
|
||
|
||
section
|
||
open Lean Elab Command Term
|
||
|
||
private def toMarkdown : VersoDocString → String
|
||
| .mk bs ps => Doc.MarkdownM.run' do
|
||
let blockLines ← bs.mapM Doc.ToMarkdown.toMarkdown
|
||
let partLines ← ps.mapM Doc.ToMarkdown.toMarkdown
|
||
return Doc.joinBlocks (blockLines ++ partLines)
|
||
|
||
private def manualRw (md : String) : String := md.replace manualRoot "$MANUAL_ROOT/"
|
||
|
||
elab "#verso_to_markdown " name:ident : command => do
|
||
let env ← getEnv
|
||
runTermElabM fun _ => do
|
||
let declName ← realizeGlobalConstNoOverloadWithInfo name
|
||
match (← findInternalDocString? env declName (includeBuiltin := true)) with
|
||
| some (.inl ..) => throwError m!"`{.ofConstName declName}` has a Markdown docstring"
|
||
| some (.inr verso) => logInfo (manualRw (toMarkdown verso))
|
||
| none => throwError m!"`{.ofConstName declName}` has no docstring"
|
||
|
||
/-!
|
||
## Code Blocks
|
||
-/
|
||
|
||
/-- info: #[Lean.Doc.lean, Lean.Doc.leanTerm, Lean.Doc.output] -/
|
||
#guard_msgs in
|
||
#eval show CommandElabM Unit from do
|
||
let builtinBlocks ← Doc.builtinDocCodeBlocks.get
|
||
let blockNames := builtinBlocks.keysArray |>.qsort (fun x y => x.toString < y.toString)
|
||
IO.println blockNames
|
||
|
||
/--
|
||
```lean
|
||
example : codeblockTest 4 5 = 9 := by rfl
|
||
```
|
||
```leanTerm
|
||
codeblockTest 4 5
|
||
```
|
||
```lean (name := x)
|
||
#eval codeblockTest 4 5
|
||
```
|
||
```output x
|
||
9
|
||
```
|
||
-/
|
||
def codeblockTest (x y : Nat) := x + y
|
||
|
||
/--
|
||
info: ```
|
||
example : codeblockTest 4 5 = 9 := by rfl
|
||
```
|
||
|
||
```
|
||
codeblockTest 4 5
|
||
```
|
||
|
||
```
|
||
#eval codeblockTest 4 5
|
||
```
|
||
|
||
```
|
||
9
|
||
```
|
||
-/
|
||
#guard_msgs in
|
||
#verso_to_markdown codeblockTest
|
||
|
||
/-!
|
||
## Directives
|
||
|
||
There are no builtin directives, but should any be added, they must be tested.
|
||
-/
|
||
|
||
/-- info: #[] -/
|
||
#guard_msgs in
|
||
#eval show CommandElabM Unit from do
|
||
let builtinBlocks ← Doc.builtinDocDirectives.get
|
||
let blockNames := builtinBlocks.keysArray |>.qsort (fun x y => x.toString < y.toString)
|
||
IO.println blockNames
|
||
|
||
/-!
|
||
## Commands
|
||
-/
|
||
|
||
/-- info: #[Lean.Doc.open, Lean.Doc.set_option] -/
|
||
#guard_msgs in
|
||
#eval show CommandElabM Unit from do
|
||
let builtinBlocks ← Doc.builtinDocCommands.get
|
||
let blockNames := builtinBlocks.keysArray |>.qsort (fun x y => x.toString < y.toString)
|
||
IO.println blockNames
|
||
|
||
namespace X
|
||
def z := 5
|
||
end X
|
||
|
||
/--
|
||
None of these commands should appear in the output:
|
||
|
||
{open X}
|
||
|
||
{set_option pp.all true}
|
||
|
||
-/
|
||
def commandTests (x y : Nat) : Nat := x + y
|
||
|
||
/-- info: None of these commands should appear in the output: -/
|
||
#guard_msgs in
|
||
#verso_to_markdown commandTests
|
||
|
||
/-!
|
||
## Roles
|
||
-/
|
||
|
||
/--
|
||
info: Lean.Doc.assert
|
||
Lean.Doc.assert'
|
||
Lean.Doc.attr
|
||
Lean.Doc.conv
|
||
Lean.Doc.given
|
||
Lean.Doc.givenInstance
|
||
Lean.Doc.kw
|
||
Lean.Doc.kw!
|
||
Lean.Doc.kw?
|
||
Lean.Doc.lean
|
||
Lean.Doc.lit
|
||
Lean.Doc.manual
|
||
Lean.Doc.module
|
||
Lean.Doc.name
|
||
Lean.Doc.option
|
||
Lean.Doc.syntax
|
||
Lean.Doc.syntaxCat
|
||
Lean.Doc.tactic
|
||
-/
|
||
#guard_msgs in
|
||
#eval show CommandElabM Unit from do
|
||
let builtinRoles ← Doc.builtinDocRoles.get
|
||
let blockNames := builtinRoles.keysArray |>.qsort (fun x y => x.toString < y.toString)
|
||
blockNames.forM (IO.println ·)
|
||
|
||
/--
|
||
Because {assert}`assertTests 2 4 = 6`, it must certainly be addition.
|
||
-/
|
||
def assertTests (x y : Nat) := x + y
|
||
|
||
/-- info: Because `assertTests 2 4 = 6`, it must certainly be addition. -/
|
||
#guard_msgs in
|
||
#verso_to_markdown assertTests
|
||
|
||
-- assert' not tested here because it's for bootstrapping and doesn't work outside early Prelude
|
||
|
||
/--
|
||
The attribute {attr}`simp` registers a simp lemma. Use {attr}`@[simp]`.
|
||
-/
|
||
def attrTests (x y : Nat) := x + y
|
||
|
||
/-- info: The attribute `simp` registers a simp lemma. Use `@[simp]`. -/
|
||
#guard_msgs in
|
||
#verso_to_markdown attrTests
|
||
|
||
/-- The {conv}`fun` tactic -/
|
||
def convTests (x y : Nat) := x + y
|
||
|
||
/-- info: The `fun` tactic -/
|
||
#guard_msgs in
|
||
#verso_to_markdown convTests
|
||
|
||
/--
|
||
Invisible: {given -show}`m : Nat`
|
||
|
||
Visible:
|
||
* For {given}`n`, {assert}`givenTests n n = n - n`.
|
||
* For {given}`n, k : Nat`, {assert}`givenTests n k = n - k`.
|
||
* For {given}`n, k`, {assert}`givenTests n k = n - k`.
|
||
* For {given (type:="Nat")}`k`, {assert}`givenTests m k = m - k`.
|
||
-/
|
||
def givenTests (x y : Nat) : Nat := x - y
|
||
|
||
/--
|
||
{given -show}`α : Type, β : Type, γ : Type` {given -show}`x : α, y : α, z : α`
|
||
Invisible: {givenInstance -show}`Add α` {givenInstance -show}`addInst : Add β`
|
||
|
||
There is an {lean}`addInst : Add β` and an {lean}`inferInstance : Add α`, and {lean}`x + y + z`.
|
||
|
||
Visible: {givenInstance}`Add γ`&{givenInstance}`addInst : OfNat γ 5`
|
||
|
||
Check: {lean}`(5 : γ) + 5`
|
||
|
||
-/
|
||
def givenInstanceTests (x y : Nat) : Nat := x - y
|
||
|
||
/--
|
||
info: ⏎
|
||
Invisible: ⏎
|
||
|
||
There is an `addInst : Add β` and an `inferInstance : Add α`, and `x + y + z`.
|
||
|
||
Visible: `Add γ`&`addInst : OfNat γ 5`
|
||
|
||
Check: `(5 : γ) + 5`
|
||
-/
|
||
#guard_msgs in
|
||
#verso_to_markdown givenInstanceTests
|
||
|
||
/--
|
||
info: Invisible: ⏎
|
||
|
||
Visible:
|
||
|
||
* For `n`, `givenTests n n = n - n`.
|
||
|
||
* For `n`, `k : Nat`, `givenTests n k = n - k`.
|
||
|
||
* For `n`, `k`, `givenTests n k = n - k`.
|
||
|
||
* For `k`, `givenTests m k = m - k`.
|
||
-/
|
||
#guard_msgs in
|
||
#verso_to_markdown givenTests
|
||
|
||
|
||
/--
|
||
info:
|
||
|
||
Hint: Specify the syntax kind:
|
||
kw?̵ ̲(̲o̲f̲ ̲:̲=̲ ̲P̲a̲r̲s̲e̲r̲.̲T̲a̲c̲t̲i̲c̲.̲C̲o̲n̲v̲.̲f̲u̲n̲)̲
|
||
-/
|
||
#guard_msgs in
|
||
/--
|
||
* {kw (of := termIfThenElse)}`if`
|
||
* {kw! (of := Lean.Parser.Term.fun)}`fun`
|
||
* {kw?}`fun`
|
||
-/
|
||
def kwTests := ()
|
||
|
||
/--
|
||
info: * `if`
|
||
|
||
* `fun`
|
||
|
||
* `fun`
|
||
-/
|
||
#guard_msgs in
|
||
#verso_to_markdown kwTests
|
||
|
||
/-- {lit}`$ ls -l`-/
|
||
def litTests := ()
|
||
|
||
/-- info: `$ ls -l` -/
|
||
#guard_msgs in
|
||
#verso_to_markdown litTests
|
||
|
||
/--
|
||
1. {lean}`2 + 2`
|
||
2. {lean (type :="Int")}`2 + 2`
|
||
-/
|
||
def leanRoleTests := ()
|
||
|
||
/--
|
||
info: 1. `2 + 2`
|
||
|
||
2. `2 + 2`
|
||
-/
|
||
#guard_msgs in
|
||
#verso_to_markdown leanRoleTests
|
||
|
||
/--
|
||
Link: {manual section "bar"}[link text] and done and {manual errorExplanation "errorId"}[other link]
|
||
-/
|
||
def manualLinkTests := ()
|
||
|
||
/--
|
||
info: Link: [link text]($MANUAL_ROOT/find/?domain=Verso.Genre.Manual.section&name=bar) and done and [other link]($MANUAL_ROOT/find/?domain=Manual.errorExplanation&name=errorId)
|
||
-/
|
||
#guard_msgs in
|
||
#verso_to_markdown manualLinkTests
|
||
|
||
/--
|
||
{module -checked}`NoModule` and {module}`Init`
|
||
-/
|
||
def moduleTests := ()
|
||
|
||
/-- info: `NoModule` and `Init` -/
|
||
#guard_msgs in
|
||
#verso_to_markdown moduleTests
|
||
|
||
/--
|
||
Argument names:
|
||
|
||
{name}`x`{name}`z`{name (full := X.z)}`z`
|
||
-/
|
||
def nameTests (x y z : Nat) := x - y + z
|
||
|
||
-- IMPORTANT: This has zero-width spaces between the code inlines. When updating the file, make sure
|
||
-- they're present.
|
||
/--
|
||
info: Argument names:
|
||
|
||
`x``z``z`
|
||
-/
|
||
#guard_msgs in
|
||
#verso_to_markdown nameTests
|
||
|
||
/--
|
||
* {option}`pp.all`
|
||
* {option}`set_option pp.all true`
|
||
-/
|
||
def optionTests := ()
|
||
|
||
/--
|
||
info: * `pp.all`
|
||
|
||
* `set_option pp.all true`
|
||
-/
|
||
#guard_msgs in
|
||
#verso_to_markdown optionTests
|
||
|
||
set_option linter.unusedVariables false in
|
||
/--
|
||
|
||
Tests:
|
||
1. {syntaxCat}`term`
|
||
2. {syntax level}`$x + $y`
|
||
|
||
A level: {name}`x`
|
||
-/
|
||
def syntaxTests := ()
|
||
|
||
/--
|
||
info: Tests:
|
||
|
||
1. `term`
|
||
|
||
2. `$x + $y`
|
||
|
||
A level: `x`
|
||
-/
|
||
#guard_msgs in
|
||
#verso_to_markdown syntaxTests
|
||
|
||
/--
|
||
{tactic}`intros`
|
||
-/
|
||
def tacticTests := ()
|
||
|
||
/-- info: `intros` -/
|
||
#guard_msgs in
|
||
#verso_to_markdown tacticTests
|