-
Notifications
You must be signed in to change notification settings - Fork 103
/
code-snippet-fetcher.rb
58 lines (54 loc) · 1.49 KB
/
code-snippet-fetcher.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
module Test
module Unit
class CodeSnippetFetcher
def initialize
@sources = {}
end
def fetch(path, line, options={})
n_context_line = options[:n_context_line] || 3
lines = source(path)
return [] if lines.nil?
min_line = [line - n_context_line, 1].max
max_line = [line + n_context_line, lines.length].min
window = min_line..max_line
window.collect do |n|
attributes = {:target_line? => (n == line)}
[n, lines[n - 1].chomp, attributes]
end
end
def source(path)
@sources[path] ||= read_source(path)
end
private
def read_source(path)
return nil unless File.exist?(path)
lines = []
File.open(path) do |file|
first_line = file.gets
break if first_line.nil?
encoding = detect_encoding(first_line)
if encoding
first_line.force_encoding(encoding)
file.set_encoding(encoding, encoding)
end
lines << first_line
lines.concat(file.readlines)
end
lines
end
def detect_encoding(first_line)
return nil unless first_line.respond_to?(:ascii_only?)
return nil unless first_line.ascii_only?
if /\b(?:en)?coding[:=]\s*([a-z\d_-]+)/i =~ first_line
begin
Encoding.find($1)
rescue ArgumentError
nil
end
else
nil
end
end
end
end
end