• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37850

26 Jul 2024 05:48AM UTC coverage: 87.596% (+0.1%) from 87.45%
#37850

push

local

web-flow
Update ModernJuliaWorkflows URL (#55254)

Use our shiny new URL
[modernjuliaworkflows.org](https://modernjuliaworkflows.org/).
[Thanks a
lot](https://github.com/JuliaLang/julia/pull/55036#issuecomment-2211068320)
@ViralBShah!

77671 of 88670 relevant lines covered (87.6%)

16050203.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.22
/stdlib/Markdown/src/render/terminal/render.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
include("formatting.jl")
4

5
cols(io) = displaysize(io)[2]
34✔
6

7
function term(io::IO, content::Vector, cols)
62✔
8
    isempty(content) && return
62✔
9
    for md in content[1:end-1]
61✔
10
        term(io, md, cols)
19✔
11
        print(io, '\n', '\n')
19✔
12
    end
19✔
13
    term(io, content[end], cols)
61✔
14
end
15

16
function term(io::IO, md::MD, columns = cols(io))
26✔
17
    md = insert_hlines(md)
77✔
18
    return term(io, md.content, columns)
43✔
19
end
20

21
function term(io::IO, md::Paragraph, columns)
45✔
22
    lines = wraplines(annotprint(terminline, md.content), columns-2margin)
45✔
23
    for (i, line) in enumerate(lines)
90✔
24
        print(io, ' '^margin, line)
89✔
25
        i < length(lines) && println(io)
89✔
26
    end
89✔
27
end
28

29
function term(io::IO, md::BlockQuote, columns)
1✔
30
    content = annotprint(term, md.content, columns - 10)
1✔
31
    lines = wraplines(rstrip(content), columns - 10)
1✔
32
    for (i, line) in enumerate(lines)
2✔
33
        print(io, ' '^margin, '│', line)
1✔
34
        i < length(lines) && println(io)
1✔
35
    end
1✔
36
end
37

38
function term(io::IO, md::Admonition, columns)
1✔
39
    accent = if md.category == "danger"
1✔
40
        :error
×
41
    elseif md.category in ("warning", "info", "note", "tip")
2✔
42
        Symbol(md.category)
1✔
43
    elseif md.category == "compat"
×
44
        :bright_cyan
×
45
    elseif md.category == "todo"
×
46
        :magenta
×
47
    else
48
        :default
2✔
49
    end
50
    title = if isempty(md.title) md.category else md.title end
2✔
51
    print(io, ' '^margin, styled"{$accent,markdown_admonition:│ $title}",
2✔
52
          '\n', ' '^margin, styled"{$accent,markdown_admonition:│}", '\n')
53
    content = annotprint(term, md.content, columns - 10)
1✔
54
    lines = split(rstrip(content), '\n')
1✔
55
    for (i, line) in enumerate(lines)
2✔
56
        print(io, ' '^margin, styled"{$accent,markdown_admonition:│}", line)
6✔
57
        i < length(lines) && println(io)
3✔
58
    end
3✔
59
end
60

61
function term(io::IO, f::Footnote, columns)
×
62
    print(io, ' '^margin, "│ ")
×
63
    print(io, styled"{markdown_footnote:[^$(f.id)]}")
×
64
    println(io, '\n', ' '^margin, '│')
×
65
    content = annotprint(term, f.text, columns - 10)
×
66
    lines = split(rstrip(content), '\n')
×
67
    for (i, line) in enumerate(lines)
×
68
        print(io, ' '^margin, '│', line)
×
69
        i < length(lines) && println(io)
×
70
    end
×
71
end
72

73
function term(io::IO, md::List, columns)
9✔
74
    for (i, point) in enumerate(md.items)
9✔
75
        bullet = isordered(md) ? "$(i + md.ordered - 1)." : "• "
17✔
76
        print(io, ' '^2margin, styled"{markdown_list:$bullet} ")
17✔
77
        content = annotprint(term, point, columns - 10)
17✔
78
        lines = split(rstrip(content), '\n')
17✔
79
        for (l, line) in enumerate(lines)
34✔
80
            l > 1 && print(io, ' '^(2margin+3))
29✔
81
            print(io, lstrip(line))
29✔
82
            l < length(lines) && println(io)
29✔
83
        end
41✔
84
        i < length(md.items) && print(io, '\n'^(1 + md.loose))
17✔
85
    end
17✔
86
end
87

88
const _header_underlines = collect("≡=–-⋅ ")
89
# TODO settle on another option with unicode e.g. "≡=≃–∼⋅" ?
90

91
function term(io::AnnotIO, md::Header{l}, columns) where l
8✔
92
    face = Symbol("markdown_h$l")
8✔
93
    underline = _header_underlines[l]
8✔
94
    pre = ' '^margin
8✔
95
    local line_width
96
    with_output_annotations(io, :face => face) do io
8✔
97
        headline = annotprint(terminline, md.text)
8✔
98
        lines = wraplines(headline, columns - 4margin)
8✔
99
        for (i, line) in enumerate(lines)
15✔
100
            print(io, pre, line)
7✔
101
            i < length(lines) && println(io)
7✔
102
        end
7✔
103
        line_width = if length(lines) == 1
8✔
104
            min(textwidth(lines[end]), columns)
7✔
105
        elseif length(lines) > 1
1✔
106
            max(textwidth(lines[end]), div(columns, 3)+length(pre))
×
107
        else
108
            0
10✔
109
        end
110
    end
111
    header_width = max(0, line_width)
8✔
112
    if underline != ' ' && header_width > 0
8✔
113
        print(io, '\n', ' '^(margin))
7✔
114
        with_output_annotations(io -> print(io, underline^header_width), io, :face => face)
14✔
115
    end
116
end
117

118
function term(io::IO, md::Code, columns)
5✔
119
    code = if md.language ∈ ("", "julia")
6✔
120
        highlight(md.code)
4✔
121
    elseif md.language == "julia-repl" || Base.startswith(md.language, "jldoctest")
2✔
122
        hl = AnnotatedString(md.code)
1✔
123
        for (; match) in eachmatch(r"(?:^|\n)julia>", hl)
2✔
124
            StyledStrings.face!(match, :markdown_julia_prompt)
14✔
125
            afterprompt = match.offset + ncodeunits(match) + 1
14✔
126
            _, exprend = Meta.parse(md.code, afterprompt, raise = false)
14✔
127
            highlight!(hl[afterprompt:prevind(md.code, exprend)])
14✔
128
            if (nextspace = findnext(' ', md.code, exprend)) |> !isnothing
28✔
129
                nextword = hl[exprend:prevind(hl, nextspace)]
14✔
130
                if nextword == "ERROR:"
14✔
131
                    StyledStrings.face!(nextword, :error)
×
132
                end
133
            end
134
        end
27✔
135
        hl
1✔
136
    elseif md.language == "styled"
×
137
        styled(md.code)
×
138
    else
139
        styled"{markdown_code:$(md.code)}"
6✔
140
    end
141
    lines = split(code, '\n')
5✔
142
    for (i, line) in enumerate(lines)
10✔
143
        print(io, ' '^margin, line)
59✔
144
        i < length(lines) && println(io)
59✔
145
    end
59✔
146
end
147

148
function term(io::IO, tex::LaTeX, columns)
1✔
149
    print(io, ' '^margin, styled"{markdown_latex:$(tex.formula)}")
1✔
150
end
151

152
term(io::IO, br::LineBreak, columns) = nothing # line breaks already printed between subsequent elements
×
153

154
function term(io::IO, br::HorizontalRule, columns)
×
155
    print(io, ' '^margin, styled"{markdown_hrule:$('─'^(columns - 2margin))}")
×
156
end
157

158
function term(io::IO, md::MarkdownElement, columns)
8✔
159
    a = IOContext(AnnotatedIOBuffer(), io)
8✔
160
    term(a, md, columns)
8✔
161
    print(io, read(seekstart(a.io), AnnotatedString))
8✔
162
end
163

164
term(io::IO, x, _) = show(io, MIME"text/plain"(), x)
1✔
165

166
# Inline Content
167

168
terminline(io::IO, content...) = terminline(io, collect(content))
×
169

170
function terminline(io::IO, content::Vector)
83✔
171
    for md in content
83✔
172
        terminline(io, md)
143✔
173
    end
143✔
174
end
175

176
function terminline(io::IO, md::AbstractString)
92✔
177
    print(io, replace(md, r"[\s\t\n]+" => ' '))
93✔
178
end
179

180
function terminline(io::AnnotIO, md::Bold)
2✔
181
    with_output_annotations(io -> terminline(io, md.text), io, :face => :bold)
4✔
182
end
183

184
function terminline(io::AnnotIO, md::Italic)
5✔
185
    with_output_annotations(io -> terminline(io, md.text), io, :face => :italic)
10✔
186
end
187

188
function terminline(io::IO, md::LineBreak)
2✔
189
    println(io)
2✔
190
end
191

192
function terminline(io::IO, md::Image)
1✔
193
    terminline(io, "(Image: $(md.alt))")
1✔
194
end
195

196
function terminline(io::IO, f::Footnote)
×
197
    print(io, styled"{markdown_footnote:[^$(f.id)]}")
×
198
end
199

200
function terminline(io::AnnotIO, md::Link)
13✔
201
    annots = if occursin(r"^(https?|file)://", md.url)
13✔
202
        (:face => :markdown_link, :link => md.url)
1✔
203
    else
204
        (:face => :markdown_link,)
25✔
205
    end
206
    with_output_annotations(io -> terminline(io, md.text), io, annots...)
26✔
207
end
208

209
function terminline(io::IO, code::Code)
27✔
210
    body = if code.language == "styled"
27✔
211
        styled(code.code)
×
212
    else
213
        code.code
54✔
214
    end
215
    print(io, styled"{markdown_inlinecode:$body}")
27✔
216
end
217

218
function terminline(io::IO, tex::LaTeX)
×
219
    print(io, styled"{markdown_latex:$(tex.formula)}")
×
220
end
221

222
function terminline(io::IO, md::MarkdownElement)
×
223
    a = IOContext(AnnotatedIOBuffer(), io)
×
224
    terminline(a, md)
×
225
    print(io, read(seekstart(a.io), AnnotatedString))
×
226
end
227

228
terminline(io::IO, x) = show(io, MIME"text/plain"(), x)
1✔
229

230
# Show in terminal
231
Base.show(io::IO, ::MIME"text/plain", md::MD) = (term(io, md); nothing)
21✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc