1
+ # -------------------------------------------------------------------------------
2
+ # Generic functions for source text, source location computation and formatting
3
+ # functions
4
+
5
+ """
6
+ sourcefile(x)
7
+
8
+ Get the source file object (usually `SourceFile`) for a given syntax object
9
+ `x`. The source file along with a byte range may be used to compute
10
+ `source_line()`, `source_location()`, `filename()`, etc.
11
+ """
12
+ function sourcefile
13
+ end
14
+
15
+ """
16
+ byte_range(x)
17
+
18
+ Return the range of bytes which `x` covers in the source text.
19
+ """
20
+ function byte_range
21
+ end
22
+
23
+ """
24
+ first_byte(x)
25
+
26
+ Return the first byte of `x` in the source text.
27
+ """
28
+ first_byte (x) = first (byte_range (x))
29
+
30
+ """
31
+ first_byte(x)
32
+
33
+ Return the last byte of `x` in the source text.
34
+ """
35
+ last_byte (x) = last (byte_range (x))
36
+
37
+ """
38
+ filename(x)
39
+
40
+ Get file name associated with `source`, or an empty string if one didn't exist.
41
+
42
+ For objects `x` such as syntax trees, defers to `filename(sourcefile(x))` by
43
+ default.
44
+ """
45
+ function filename (x)
46
+ source = sourcefile (x)
47
+ isnothing (source) ? " " : filename (source)
48
+ end
49
+
50
+ """
51
+ source_line(x)
52
+ source_line(source::SourceFile, byte_index::Integer)
53
+
54
+ Get the line number of the first line on which object `x` appears. In the
55
+ second form, get the line number at the given `byte_index` within `source`.
56
+ """
57
+ source_line (x) = source_line (sourcefile (x), first_byte (x))
58
+
59
+ """
60
+ souce_location(x)
61
+ souce_location(source::SourceFile, byte_index::Integer)
62
+
63
+ souce_location(LineNumberNode, x)
64
+ souce_location(LineNumberNode, source, byte_index)
65
+
66
+ Get `(line,column)` of the first byte where object `x` appears in the source.
67
+ The second form allows one to be more precise with the `byte_index`, given the
68
+ source file.
69
+
70
+ Providing `LineNumberNode` as the first agrument will return the line and file
71
+ name in a line number node object.
72
+ """
73
+ source_location (x) = source_location (sourcefile (x), first_byte (x))
74
+
75
+ """
76
+ sourcetext(x)
77
+
78
+ Get the full source text syntax object `x`
79
+ """
80
+ function sourcetext (x)
81
+ view (sourcefile (x), byte_range (x))
82
+ end
83
+
84
+ """
85
+ highlight(io, x; color, note, notecolor,
86
+ context_lines_before, context_lines_inner, context_lines_after)
87
+
88
+ highlight(io::IO, source::SourceFile, range::UnitRange; kws...)
89
+
90
+ Print the lines of source code surrounding `x` which is highlighted with
91
+ background `color` and underlined with markers in the text. A `note` in
92
+ `notecolor` may be provided as annotation. By default, `x` should be an object
93
+ with `sourcefile(x)` and `byte_range(x)` implemented.
94
+
95
+ The context arguments `context_lines_before`, etc, refer to the number of
96
+ lines of code which will be printed as context before and after, with `inner`
97
+ referring to context lines inside a multiline region.
98
+
99
+ The second form shares the keywords of the first but allows an explicit source
100
+ file and byte range to be supplied.
101
+ """
102
+ function highlight (io:: IO , x; kws... )
103
+ highlight (io, sourcefile (x), byte_range (x); kws... )
104
+ end
105
+
106
+
107
+ # -------------------------------------------------------------------------------
1
108
"""
2
109
SourceFile(code [; filename=nothing, first_line=1, first_index=1])
3
110
@@ -53,16 +160,19 @@ function _source_line_index(source::SourceFile, byte_index)
53
160
end
54
161
_source_line (source:: SourceFile , lineidx) = lineidx + source. first_line - 1
55
162
56
- """
57
- Get the line number at the given byte index.
58
- """
59
- source_line (source:: SourceFile , byte_index) =
163
+ function source_location (:: Type{LineNumberNode} , x)
164
+ source_location (LineNumberNode, sourcefile (x), first_byte (x))
165
+ end
166
+
167
+ source_line (source:: SourceFile , byte_index:: Integer ) =
60
168
_source_line (source, _source_line_index (source, byte_index))
61
169
62
- """
63
- Get line number and character within the line at the given byte index.
64
- """
65
- function source_location (source:: SourceFile , byte_index)
170
+ function filename (source:: SourceFile )
171
+ f = source. filename
172
+ ! isnothing (f) ? f : " "
173
+ end
174
+
175
+ function source_location (source:: SourceFile , byte_index:: Integer )
66
176
lineidx = _source_line_index (source, byte_index)
67
177
i = source. line_starts[lineidx]
68
178
column = 1
77
187
Get byte range of the source line at byte_index, buffered by
78
188
`context_lines_before` and `context_lines_after` before and after.
79
189
"""
80
- function source_line_range (source:: SourceFile , byte_index;
190
+ function source_line_range (source:: SourceFile , byte_index:: Integer ;
81
191
context_lines_before= 0 , context_lines_after= 0 )
82
192
lineidx = _source_line_index (source, byte_index)
83
193
fbyte = source. line_starts[max (lineidx- context_lines_before, 1 )]
@@ -86,14 +196,14 @@ function source_line_range(source::SourceFile, byte_index;
86
196
lbyte + source. byte_offset)
87
197
end
88
198
89
- function source_location (:: Type{LineNumberNode} , source:: SourceFile , byte_index)
90
- LineNumberNode ( source_line ( source, byte_index),
91
- isnothing (source . filename ) ? nothing : Symbol (source . filename ))
199
+ function source_location (:: Type{LineNumberNode} , source:: SourceFile , byte_index:: Integer )
200
+ fn = filename ( source)
201
+ LineNumberNode ( source_line (source, byte_index), isempty (fn ) ? nothing : Symbol (fn ))
92
202
end
93
203
94
204
function Base. show (io:: IO , :: MIME"text/plain" , source:: SourceFile )
95
- fn = isnothing (source . filename) ? " " : " $ (source. filename) "
96
- header = " ## SourceFile$fn ##"
205
+ fn = filename (source)
206
+ header = " ## SourceFile$( isempty (fn) ? " " : " " )$ fn ##"
97
207
print (io, header, " \n " )
98
208
heightlim = displaysize (io)[1 ] ÷ 2
99
209
if ! get (io, :limit , false ) || length (source. line_starts) <= heightlim
@@ -193,27 +303,6 @@ function _print_marker_line(io, prefix_str, str, underline, singleline, color,
193
303
end
194
304
end
195
305
196
- function highlight (io:: IO , x; kws... )
197
- highlight (io, sourcefile (x), byte_range (x); kws... )
198
- end
199
-
200
- """
201
- highlight(io::IO, source::SourceFile, range::UnitRange;
202
- color, note, notecolor,
203
- context_lines_before, context_lines_inner, context_lines_after,
204
- highlight(io, x; kws...)
205
-
206
- Print the lines of source code `source` surrounding the given byte `range`
207
- which is highlighted with background `color` and underlined with markers in the
208
- text. A `note` in `notecolor` may be provided as annotation.
209
-
210
- In the second form, `x` is an object with `sourcefile(x)` and `byte_range(x)`
211
- implemented.
212
-
213
- The context arguments `context_lines_before`, etc, refer to the number of
214
- lines of code which will be printed as context before and after, with `inner`
215
- referring to context lines inside a multiline region.
216
- """
217
306
function highlight (io:: IO , source:: SourceFile , range:: UnitRange ;
218
307
color= (120 ,70 ,70 ), context_lines_before= 2 ,
219
308
context_lines_inner= 1 , context_lines_after= 2 ,
0 commit comments