@@ -125,6 +125,7 @@ struct TestCase <: AbstractTestCase
125
125
code:: TextBlock
126
126
pre:: Union{TextBlock,Nothing}
127
127
expect:: Union{TextBlock,Nothing}
128
+ repl:: Bool
128
129
end
129
130
130
131
location (test:: TestCase ) = test. loc
@@ -537,29 +538,36 @@ function parsemd!(stack::Vector{TextBlock})
537
538
line = pop! (stack)
538
539
if isfence (line)
539
540
# Extract a fenced block.
541
+ isrepl = false
540
542
fenceloc = line. loc
541
543
lang = strip (line. val[4 : end ])
542
544
jlstack = TextBlock[]
543
545
while ! isempty (stack) && ! isfence (stack[end ])
544
- push! (jlstack, pop! (stack))
546
+ block = pop! (stack)
547
+ isrepl = isrepl || startswith (block. val, " julia>" )
548
+ push! (jlstack, block)
545
549
end
546
550
if isempty (stack)
547
551
push! (suite, BrokenTestCase (fenceloc, " incomplete fenced code block" ))
548
552
else
549
553
pop! (stack)
550
554
if isempty (lang)
551
555
reverse! (jlstack)
552
- append! (suite, parsejl! (jlstack))
556
+ append! (suite, isrepl ? parsejlrepl! (jlstack) : parsejl! (jlstack))
553
557
end
554
558
end
555
559
elseif isindent (line) && ! isblank (line)
556
560
# Extract an indented block.
557
- jlstack = TextBlock[unindent (line)]
561
+ block = unindent (line)
562
+ isrepl = startswith (block. val, " julia>" )
563
+ jlstack = TextBlock[block]
558
564
while ! isempty (stack) && (isindent (stack[end ]) || isblank (stack[end ]))
559
- push! (jlstack, unindent (pop! (stack)))
565
+ block = unindent (pop! (stack))
566
+ isrepl = isrepl || startswith (block. val, " julia> " )
567
+ push! (jlstack, block)
560
568
end
561
569
reverse! (jlstack)
562
- append! (suite, parsejl! (jlstack))
570
+ append! (suite, isrepl ? parsejlrepl! (jlstack) : parsejl! (jlstack))
563
571
elseif isadmonition (line)
564
572
# Skip an indented admonition block.
565
573
while ! isempty (stack) && (isindent (stack[end ]) || isblank (stack[end ]))
@@ -588,6 +596,78 @@ function parsejl!(stack::Vector{TextBlock})
588
596
return suite
589
597
end
590
598
599
+ const PROMPT_REGEX = r" ^julia>(?: (.*))?$"
600
+ const SOURCE_REGEX = r" ^ (.*)$"
601
+
602
+ function parsejlrepl! (stack:: Vector{TextBlock} )
603
+ reverse! (stack)
604
+ code = TextBlock[]
605
+ expect = TextBlock[]
606
+ buf = IOBuffer ()
607
+ processing_prompt = false
608
+ function savecode! (loc)
609
+ data = consumebuf! (buf)
610
+ if data != = nothing
611
+ push! (code, TextBlock (loc, strip (data)))
612
+ else
613
+ push! (code, TextBlock (loc, " " ))
614
+ end
615
+ end
616
+ function saveexpect! (loc)
617
+ data = consumebuf! (buf)
618
+ if data != = nothing
619
+ push! (expect, TextBlock (loc, rstrip (data)))
620
+ end
621
+ end
622
+ while true
623
+ line = popfirst! (stack)
624
+ prompt = match (PROMPT_REGEX, line. val)
625
+ if prompt === nothing
626
+ source = match (SOURCE_REGEX, line. val)
627
+ if source === nothing
628
+ processing_prompt = false
629
+ savecode! (line. loc)
630
+ println (buf, rstrip (line. val))
631
+ takeuntil! (PROMPT_REGEX, buf, stack)
632
+ else
633
+ processing_prompt = true
634
+ println (buf, source[1 ])
635
+ end
636
+ else
637
+ processing_prompt = true
638
+ saveexpect! (line. loc)
639
+ if prompt[1 ] != = nothing
640
+ println (buf, prompt[1 ])
641
+ end
642
+ end
643
+ if isempty (stack)
644
+ processing_prompt ? savecode! (line. loc) : saveexpect! (line. loc)
645
+ for _ in length (code): length (expect) + 1
646
+ push! (expect, TextBlock (line. loc, " " ))
647
+ end
648
+ break
649
+ end
650
+ end
651
+ [isempty (c. val) ?
652
+ BrokenTestCase (c. loc, " empty test case" ) :
653
+ TestCase (c. loc, c, nothing , e, true ) for (c, e) in zip (code, expect)]
654
+ end
655
+
656
+ function consumebuf! (buf)
657
+ n = bytesavailable (seekstart (buf))
658
+ n > 0 ? String (take! (buf)) : nothing
659
+ end
660
+
661
+ function takeuntil! (r, buf, lines:: Vector{TextBlock} )
662
+ while ! isempty (lines)
663
+ if ! occursin (r, lines[1 ]. val)
664
+ println (buf, rstrip (popfirst! (lines). val))
665
+ else
666
+ break
667
+ end
668
+ end
669
+ end
670
+
591
671
# Extract a test case from Julia source.
592
672
593
673
function parsecase! (stack:: Vector{TextBlock} )
@@ -638,7 +718,7 @@ function parsecase!(stack::Vector{TextBlock})
638
718
end
639
719
end
640
720
! isempty (code) || return BrokenTestCase (loc, " missing test code" )
641
- return TestCase (loc, collapse (code), collapse (pre), collapse (expect))
721
+ return TestCase (loc, collapse (code), collapse (pre), collapse (expect), false )
642
722
end
643
723
644
724
# Run a single test case.
@@ -703,7 +783,11 @@ function runtest(test::TestCase; subs=common_subs(), mod=nothing)
703
783
body = asexpr (test. code)
704
784
ans = Core. eval (mod, body)
705
785
if ans != = nothing && ! no_output
706
- Base. invokelatest (show, io, ans)
786
+ if test. repl
787
+ Base. invokelatest (show, io, " text/plain" , ans)
788
+ else
789
+ Base. invokelatest (show, io, ans)
790
+ end
707
791
end
708
792
end
709
793
catch exc
@@ -746,10 +830,11 @@ end
746
830
runtest (test:: BrokenTestCase ; subs= common_subs (), mod= nothing ) =
747
831
Error (test)
748
832
749
- runtest (loc, code; pre= nothing , expect= nothing , subs= common_subs (), mod= nothing ) =
833
+ runtest (loc, code; pre= nothing , expect= nothing , subs= common_subs (), mod= nothing , repl = false ) =
750
834
runtest (TestCase (loc, TextBlock (loc, code),
751
835
pre != = nothing ? TextBlock (loc, pre) : nothing ,
752
- expect != = nothing ? TextBlock (loc, expect) : nothing ),
836
+ expect != = nothing ? TextBlock (loc, expect) : nothing ,
837
+ repl),
753
838
subs= subs, mod= mod)
754
839
755
840
# Convert expected output block to a regex.
0 commit comments