Skip to content

Commit da0b444

Browse files
authored
add loop_delay documenter option, expose idle_time_limit, and fix parsing of delay in @cast blocks to not truncate (#39)
* add loop_delay documenter option * comment * add tests * add debug logs
1 parent 1c443a3 commit da0b444

File tree

4 files changed

+81
-18
lines changed

4 files changed

+81
-18
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "Asciicast"
22
uuid = "2600d445-abca-43b9-92aa-ce144ac0b05b"
33
authors = ["Eric Hanson <[email protected]> and contributors"]
4-
version = "0.1.2"
4+
version = "0.1.3"
55

66
[deps]
77
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

docs/src/documenter_usage.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,49 @@ println("="^80)
196196
println("="^80)
197197
```
198198

199+
### Loops
200+
We can use `loop=true` to infinitely loop the cast:
201+
202+
````markdown
203+
```@cast; delay=0.5, loop=true, hide_inputs=true
204+
1
205+
2
206+
3
207+
```
208+
````
209+
210+
```@cast; delay=0.5, loop=true, hide_inputs=true
211+
1
212+
2
213+
3
214+
```
215+
216+
We can also specify a delay to write at the end of each loop:
217+
218+
````markdown
219+
```@cast; delay=0.5, loop=true, loop_delay=4.5, hide_inputs=true
220+
1
221+
2
222+
3
223+
```
224+
````
225+
226+
```@cast; delay=0.5, loop=true, loop_delay=4.5, hide_inputs=true
227+
1
228+
2
229+
3
230+
```
231+
232+
Note that currently setting `loop_delay` increases `idle_time_limit` as an implementation detail, meaning that delays of up to `loop_delay` during code execution will be shown.
233+
199234
### All supported options in `@cast` Documenter blocks
200235

201236
* `hide_inputs::Bool=false`. Whether or not to hide the `@repl`-style inputs before the animated gif.
202237
* `allow_errors::Bool=false`. Whether or not the Documenter build should fail if exceptions are encountered during execution of the `@cast` block.
203238
* `delay::Float64=0.25`. The amount of delay between line executions (to emulate typing time).
204239
* `loop::Union{Int,Bool}=false`. Set to `true` for infinite looping, or an integer to loop a fixed number of times.
240+
* `loop_delay::Union{Int,Float64}=0`. An amount of time to wait at the end of the cast, usually useful to pause before looping.
241+
* `idle_time_limit::Union{Int,Float64}=1`. Sets the maximum amount of time to wait between printing.
205242
* `height::Int`. Heuristically determined by default. Set to an integer to specify the number of lines.
206243
* `width::Int`. Set to `80` by default. Set to an integer to specify the number of columns.
207244

src/runner.jl

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,20 @@ abstract type CastBlocks <: ExpanderPipeline end
33
Selectors.order(::Type{CastBlocks}) = 9.1 # just after REPL blocks
44
Selectors.matcher(::Type{CastBlocks}, node, page, doc) = iscode(node, r"^@cast")
55

6+
function parse_float_int(name, kwargs)
7+
matched = match(Regex("\\b$(name)\\s*=\\s*((?:[0-9]*[.])?[0-9]+)"), kwargs)
8+
if matched !== nothing
9+
return parse(Float64, matched[1])
10+
else
11+
# match integer delay
12+
matched = match(Regex("\\b$(name)\\s*=\\s*([0-9]+)"), kwargs)
13+
if matched !== nothing
14+
return convert(Float64, parse(Int, matched[1]))
15+
end
16+
end
17+
return nothing
18+
end
19+
620
# We can't just run the actual REPLBlocks, because then we have no timing information.
721
# Thus, we need to basically reproduce their implementation, while saving timing info.
822

@@ -34,6 +48,8 @@ function Selectors.runner(::Type{CastBlocks}, node, page, doc)
3448
height = nothing
3549
width = nothing
3650
loop = false
51+
loop_delay = 0
52+
idle_time_limit = 1
3753
if kwargs !== nothing
3854
# ansicolor
3955
matched = match(r"\bansicolor\s*=\s*(true|false)\b", kwargs)
@@ -80,30 +96,23 @@ function Selectors.runner(::Type{CastBlocks}, node, page, doc)
8096
end
8197
end
8298

83-
# delay
84-
# match integer delay
85-
matched = match(r"\bdelay\s*=\s*([0-9]+)", kwargs)
86-
if matched !== nothing
87-
delay = convert(Float64, parse(Int, matched[1]))
88-
else
89-
# match float delay
90-
matched = match(r"\bdelay\s*=\s*((?:[0-9]*[.])?[0-9]+)", kwargs)
91-
if matched !== nothing
92-
delay = parse(Float64, matched[1])
93-
end
94-
end
95-
end
99+
delay = something(parse_float_int("delay", kwargs), delay)
96100

97-
multicodeblock = MarkdownAST.CodeBlock[]
101+
idle_time_limit = something(parse_float_int("idle_time_limit", kwargs), idle_time_limit)
98102

103+
loop_delay = something(parse_float_int("loop_delay", kwargs), loop_delay)
104+
end
105+
idle_time_limit = max(idle_time_limit, loop_delay)
106+
@debug "`@cast` block delays" delay loop_delay idle_time_limit
107+
multicodeblock = MarkdownAST.CodeBlock[]
99108
n_lines = length(split(x.code))
100109

101110
# If `height` isn't provided, we guess the number of lines:
102111
height = something(height, min(n_lines * 2, 24))
103112
width = something(width, 80)
104-
cast = Cast(IOBuffer(), Header(; height, width, idle_time_limit=1); delay, loop)
113+
cast = Cast(IOBuffer(), Header(; height, width, idle_time_limit); delay, loop)
105114

106-
cast_from_string!(x.code, cast; doc, page, ansicolor, mod, multicodeblock, allow_errors, x)
115+
cast_from_string!(x.code, cast; doc, page, ansicolor, mod, multicodeblock, allow_errors, x, loop_delay)
107116

108117
raw_html = sprint(show, MIME"text/html"(), cast)
109118

@@ -149,7 +158,7 @@ function Base.showerror(io::IO, c::CastExecutionException)
149158
""")
150159
end
151160

152-
function cast_from_string!(code_string::AbstractString, cast::Cast; doc=FakeDoc(), page=FakePage(), ansicolor=true, mod=get_module(), multicodeblock=MarkdownAST.CodeBlock[], allow_errors=false, x=nothing, remove_prompt=false)
161+
function cast_from_string!(code_string::AbstractString, cast::Cast; doc=FakeDoc(), page=FakePage(), ansicolor=true, mod=get_module(), multicodeblock=MarkdownAST.CodeBlock[], allow_errors=false, x=nothing, remove_prompt=false, loop_delay=0.0)
153162
linenumbernode = LineNumberNode(0, "REPL") # line unused, set to 0
154163
@debug "Evaluating @cast:\n$(x.code)"
155164

@@ -235,6 +244,12 @@ function cast_from_string!(code_string::AbstractString, cast::Cast; doc=FakeDoc(
235244
end
236245
push!(multicodeblock, MarkdownAST.CodeBlock("documenter-ansi", rstrip(outstr)))
237246
end
247+
if loop_delay > 0 # if there's delay, write an empty output
248+
# note: for some reason, it doesn't seem to matter if we write an empty string or actual output here- for me
249+
# it doesn't display either way
250+
event = Event(time() + loop_delay - cast.start_time, OutputEvent, "")
251+
write_event!(cast, event)
252+
end
238253
end
239254

240255

test/runtests.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,17 @@ end
150150
c = cast"""include("test_file.jl")"""
151151
@test c isa Cast
152152
end
153+
154+
@testset "Float-int parsing" begin
155+
@test Asciicast.parse_float_int("delay", "delay=0.5, loop=true, loop_delay=4.5, hide_inputs=true") == 0.5
156+
@test Asciicast.parse_float_int("delay", "delay=1, loop=true, loop_delay=4.5, hide_inputs=true") == 1.0
157+
@test Asciicast.parse_float_int("delay", "delay=1.0, loop=true, loop_delay=4.5, hide_inputs=true") == 1.0
158+
@test Asciicast.parse_float_int("delay", "delay=1.5, loop=true, loop_delay=4.5, hide_inputs=true") == 1.5
159+
@test Asciicast.parse_float_int("delay",
160+
"width=100, height=50, delay=0.1, loop=true, loop_delay=5") == 0.1
161+
@test Asciicast.parse_float_int("loop_delay",
162+
"width=100, height=50, delay=0.1, loop=true, loop_delay=5") == 5
163+
end
153164
end
154165

155166

0 commit comments

Comments
 (0)