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

JuliaLang / julia / #37846

22 Jul 2024 01:06AM UTC coverage: 86.908% (+0.8%) from 86.098%
#37846

push

local

web-flow
Preserve Git objects from being garbage collected (#55142)

This issue has been discussed
[here](https://discourse.julialang.org/t/preserve-against-garbage-collection-in-libgit2/117095).

In most cases, thanks to the specialization of `Base.unsafe_convert`, it
is sufficient to replace `obj.ptr` by `obj` in `ccalls` to fix the
issue.

In other cases, for example when a pointer to an internal string is
returned, the code has to be wrapped in `GC.https://github.com/preserve
obj begin ... end` block.

All `LibGit2` tests run successfully. I have left a few `FIXME` comments
where I have doubts about the code, notably with `Ptr{Ptr{Cvoid}}`
arguments.

71 of 73 new or added lines in 15 files covered. (97.26%)

560 existing lines in 28 files now uncovered.

76034 of 87488 relevant lines covered (86.91%)

15443040.18 hits per line

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

47.71
/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]
3✔
6

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

16
term(io::IO, md::MD, columns = cols(io)) = term(io, md.content, columns)
11✔
17

18
function term(io::IO, md::Paragraph, columns)
13✔
19
    lines = wraplines(annotprint(terminline, md.content), columns-2margin)
13✔
20
    for (i, line) in enumerate(lines)
13✔
21
        print(io, ' '^margin, line)
30✔
22
        i < length(lines) && println(io)
30✔
23
    end
30✔
24
end
25

UNCOV
26
function term(io::IO, md::BlockQuote, columns)
×
UNCOV
27
    content = annotprint(term, md.content, columns - 10)
×
UNCOV
28
    lines = wraplines(rstrip(content), columns - 10)
×
UNCOV
29
    for (i, line) in enumerate(lines)
×
UNCOV
30
        print(io, ' '^margin, '│', line)
×
UNCOV
31
        i < length(lines) && println(io)
×
UNCOV
32
    end
×
33
end
34

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

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

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

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

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

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

UNCOV
145
function term(io::IO, tex::LaTeX, columns)
×
UNCOV
146
    print(io, ' '^margin, styled"{markdown_latex:$(tex.formula)}")
×
147
end
148

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

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

155
function term(io::IO, md::MarkdownElement, columns)
1✔
156
    a = IOContext(AnnotatedIOBuffer(), io)
1✔
157
    term(a, md, columns)
1✔
158
    print(io, read(seekstart(a.io), AnnotatedString))
1✔
159
end
160

UNCOV
161
term(io::IO, x, _) = show(io, MIME"text/plain"(), x)
×
162

163
# Inline Content
164

165
terminline(io::IO, content...) = terminline(io, collect(content))
×
166

167
function terminline(io::IO, content::Vector)
23✔
168
    for md in content
23✔
169
        terminline(io, md)
75✔
170
    end
75✔
171
end
172

173
function terminline(io::IO, md::AbstractString)
39✔
174
    print(io, replace(md, r"[\s\t\n]+" => ' '))
39✔
175
end
176

UNCOV
177
function terminline(io::AnnotIO, md::Bold)
×
UNCOV
178
    with_output_annotations(io -> terminline(io, md.text), io, :face => :bold)
×
179
end
180

UNCOV
181
function terminline(io::AnnotIO, md::Italic)
×
UNCOV
182
    with_output_annotations(io -> terminline(io, md.text), io, :face => :italic)
×
183
end
184

UNCOV
185
function terminline(io::IO, md::LineBreak)
×
UNCOV
186
    println(io)
×
187
end
188

UNCOV
189
function terminline(io::IO, md::Image)
×
UNCOV
190
    terminline(io, "(Image: $(md.alt))")
×
191
end
192

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

197
function terminline(io::AnnotIO, md::Link)
9✔
198
    annots = if occursin(r"^(https?|file)://", md.url)
9✔
UNCOV
199
        (:face => :markdown_link, :link => md.url)
×
200
    else
201
        (:face => :markdown_link,)
9✔
202
    end
203
    with_output_annotations(io -> terminline(io, md.text), io, annots...)
18✔
204
end
205

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

215
function terminline(io::IO, tex::LaTeX)
×
216
    print(io, styled"{markdown_latex:$(tex.formula)}")
×
217
end
218

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

UNCOV
225
terminline(io::IO, x) = show(io, MIME"text/plain"(), x)
×
226

227
# Show in terminal
228
Base.show(io::IO, ::MIME"text/plain", md::MD) = (term(io, md); nothing)
3✔
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