-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathentry.rb
executable file
·137 lines (106 loc) · 3.04 KB
/
entry.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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/usr/bin/env ruby
Warning[:deprecated] = false
require 'open3'
require 'shellwords'
require 'strscan'
files = ARGV[0].shellsplit.flat_map { |path| Dir.glob(path) }
args = ARGV[1].shellsplit
raise "No files files specified." if files.empty?
def escape(s)
s.gsub(/\r/, '%0D')
.gsub(/\n/, '%0A')
.gsub(/]/, '%5D')
.gsub(/;/, '%3B');
end
def assert_rest(rest)
raise "Failed to parse rest of output: #{rest}" unless rest.empty?
end
def check_file(file, args)
Open3.popen3('aspell', 'pipe', *args) do |stdin, stdout, stderr, wait_thread|
errors = []
begin
extension = File.extname(file)
code_block = false
File.open(file, 'r').each_line.with_index do |line, i|
if extension == '.tex'
if line.match?(/^\s*\\begin{\s*lstlisting\s*}/)
code_block = true
next
elsif line.match?(/^\s*\\end{\s*lstlisting\s*}/)
code_block = false
next
elsif code_block
next
end
end
stdin.print '^'
stdin.puts line.chomp
loop do
output = stdout.readline
next if output.start_with?('@(#)')
break if output == "\n"
output = StringScanner.new(output)
if type = output.scan(/(&|#|\*)/)
if type == '*'
output.skip(/\n/)
next
end
output.skip(/\ /)
word = output.scan(/[^\ \n]+/)
output.skip(/\ /)
if type == '&'
suggestion_count = Integer(output.scan(/\d+/))
output.skip(/\ /)
else
suggestion_count = 0
end
column = Integer(output.scan(/\d+/))
suggestions = (0...suggestion_count).map { |i|
output.skip(i.zero? ? /:/ : /,/)
output.skip(/ /)
output.scan(/[^,\n]+/)
}
output.skip(/\n/)
errors << {
word: word,
line: i + 1,
column: column - 1, # https://github.com/GNUAspell/aspell/issues/277
suggestions: suggestions,
}
end
assert_rest(output.rest)
end
end
ensure
stdin.close
end
assert_rest(stdout.read)
status = wait_thread.value
return errors if status.success?
raise stderr.read
rescue EOFError
wait_thread.value
raise stderr.read
end
end
exit_status = 0
files.each do |file|
puts "Checking spelling in file '#{file}':"
errors = check_file(file, args)
if errors.empty?
puts "No errors found."
else
errors.each do |word:, line:, column:, suggestions:|
message = <<~EOF
Wrong spelling of “#{word}” found (line #{line}, column #{column}). Maybe you meant one of the following?
#{suggestions.join(', ')}
EOF
puts "::error file=#{escape(file)},line=#{line},col=#{column}::#{escape(message)}"
end
exit_status = 1
end
rescue => e
puts "::error file=#{escape(file)}::#{e}"
exit_status = 1
end
exit exit_status