/
readme.kt
191 lines (162 loc) · 7.11 KB
/
readme.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
package com.jillesvangurp.kotlin4example.docs
import com.jillesvangurp.kotlin4example.DocGenTest
import com.jillesvangurp.kotlin4example.SourceRepository
val k4ERepo = SourceRepository("https://github.com/jillesvangurp/kotlin4example", branch = "master")
val readmeMarkdown by k4ERepo.md {
// for larger bits of text, it's nice to load them from a markdown file
includeMdFile("intro.md")
section("Usage") {
subSection("Example blocks") {
+"""
With Kotlin4Example you can mix examples and markdown easily.
An example is a code block
and it is executed by default. Because it is a code block,
you are forced to ensure
it is syntactically correct and compiles.
By executing it, you can further guarantee it does what it
is supposed to and you can
intercept output and integrate that into your documentation.
For example:
""".trimIndent()
// a bit of kotlin4example inception here, but it works
example {
// out is an ExampleOutput instance
// with both stdout and the return
// value as a Result<T>. Any exceptions
// are captured as well.
val out = example {
print("Hello World")
}
// this is how you can append arbitrary markdown
+"""
This example prints **${out.stdOut}** when it executes.
""".trimIndent()
}
+"""
The block you pass to example can be a suspending block. It uses `runBlocking` to run it. Earlier
versions of this library had a separate function for this; this is no longer needed.
""".trimIndent()
}
subSection("Configuring examples") {
+"""
Sometimes you just want to show but not run the code. You can control this with the
`runExample` parameter.
""".trimIndent()
example(runExample = false) {
//
example(
runExample = false,
) {
// your code goes here
}
}
+"""
The library imposes a line length of 80 characters on your examples. The
reason is that code blocks with horizontal scroll bars look ugly.
You can of course turn this off or turn on the built in wrapping (wraps at the 80th character)
""".trimIndent()
example(runExample = false) {
// making sure the example fits in a web page
// long lines tend to look ugly in documentation
example(
// default is 80
lineLength = 120,
// default is false
wrap = true,
// default is false
allowLongLines = true,
) {
// your code goes here
}
}
}
subSection("Code snippets") {
+"""
While it is nice to have executable blocks,
sometimes you just want to grab
code directly from a file. You can do that with snippets.
""".trimIndent()
example {
// the BEGIN_ and END_ are optional but I find it
// helps for readability.
// BEGIN_MY_CODE_SNIPPET
println("Example code that shows in a snippet")
// END_MY_CODE_SNIPPET
exampleFromSnippet("readme.kt", "MY_CODE_SNIPPET")
}
}
subSection("Markdown") {
// you can use our Kotlin DSL to structure your documentation.
example(runExample = false) {
section("Section") {
+"""
You can use string literals, templates ${1 + 1},
and [links](https://github.com/jillesvangurp/kotlin4example)
or other markdown formatting.
""".trimIndent()
}
// you can also just include markdown files
// useful if you have a lot of markdown
// content without code examples
includeMdFile("intro.md")
// link to things in your git repository
mdLink(DocGenTest::class)
mdLinkToRepoResource("build file", "build.gradle.kts")
mdLinkToSelf("This class")
}
}
subSection("Source code blocks") {
+"""
You can add your own source code blocks as well.
""".trimIndent()
example(runExample = false) {
mdCodeBlock(
code = """
Useful if you have some non kotlin code that you want to show
""".trimIndent(),
type = "text"
)
}
}
subSection("This README is generated") {
+"""
This README.md is of course created from kotlin code that
runs as part of the test suite. You can look at the kotlin
source code that generates this markdown ${mdLinkToSelf("here")}.
The code that writes the `README.md file` is as follows:
""".trimIndent()
exampleFromSnippet(DocGenTest::class, "READMEWRITE")
}
subSection("Context receivers") {
+"""
A new feature in Kotlin that you currently have to opt into is context receivers.
Context receivers are useful for processing the output of your examples since you typically
need Kotlin4Example when you use the ExampleOutput.
I don't want
to force people to opt into context receivers yet but it's easy to add this yourself.
Simply add a simple extension function like this:.
""".trimIndent()
mdCodeBlock("""
context(Kotlin4Example)!
fun ExampleOutput<*>.printStdOut() {
+""${'"'}
This prints:
""${'"'}.trimIndent()
mdCodeBlock(stdOut, type = "text", wrap = true)
}
""".trimIndent(), "kotlin")
+"""
And then you can use it `example { 1+1}.printStdOut()`.
To opt into context receivers, add this to your build file
""".trimIndent()
mdCodeBlock("""
kotlin {
compilerOptions {
freeCompilerArgs= listOf("-Xcontext-receivers")
}
}
""".trimIndent(), "kotlin")
}
}
includeMdFile("outro.md")
}