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+ # -------------------------------------------------------------------------------
1108"""
2109 SourceFile(code [; filename=nothing, first_line=1, first_index=1])
3110
@@ -53,16 +160,19 @@ function _source_line_index(source::SourceFile, byte_index)
53160end
54161_source_line (source:: SourceFile , lineidx) = lineidx + source. first_line - 1
55162
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 ) =
60168 _source_line (source, _source_line_index (source, byte_index))
61169
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 )
66176 lineidx = _source_line_index (source, byte_index)
67177 i = source. line_starts[lineidx]
68178 column = 1
77187Get byte range of the source line at byte_index, buffered by
78188`context_lines_before` and `context_lines_after` before and after.
79189"""
80- function source_line_range (source:: SourceFile , byte_index;
190+ function source_line_range (source:: SourceFile , byte_index:: Integer ;
81191 context_lines_before= 0 , context_lines_after= 0 )
82192 lineidx = _source_line_index (source, byte_index)
83193 fbyte = source. line_starts[max (lineidx- context_lines_before, 1 )]
@@ -86,14 +196,14 @@ function source_line_range(source::SourceFile, byte_index;
86196 lbyte + source. byte_offset)
87197end
88198
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 ))
92202end
93203
94204function 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 ##"
97207 print (io, header, " \n " )
98208 heightlim = displaysize (io)[1 ] ÷ 2
99209 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,
193303 end
194304end
195305
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- """
217306function highlight (io:: IO , source:: SourceFile , range:: UnitRange ;
218307 color= (120 ,70 ,70 ), context_lines_before= 2 ,
219308 context_lines_inner= 1 , context_lines_after= 2 ,
0 commit comments