Pickaxe 0.4.4 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/pickaxe.rb +1 -1
- data/lib/pickaxe/cli.rb +3 -2
- data/lib/pickaxe/color.rb +2 -1
- data/lib/pickaxe/extensions.rb +5 -1
- data/lib/pickaxe/main.rb +14 -7
- data/lib/pickaxe/shell.rb +2 -1
- data/lib/pickaxe/test.rb +71 -23
- metadata +4 -4
data/lib/pickaxe.rb
CHANGED
data/lib/pickaxe/cli.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'optparse'
|
2
2
|
|
3
|
-
options = {}
|
3
|
+
options = { :extension => "txt" }
|
4
4
|
OptionParser.new do |opts|
|
5
5
|
opts.banner = <<END_OF_BANNER
|
6
6
|
Usage:
|
@@ -10,7 +10,8 @@ Uses given paths (files or directories) to generate a test from *.txt files.
|
|
10
10
|
END_OF_BANNER
|
11
11
|
|
12
12
|
opts.separator ""
|
13
|
-
opts.on("-e", "--ext [EXTENSION]", "Use files with given EXTENSION
|
13
|
+
opts.on("-e", "--ext [EXTENSION]", "Use files with given EXTENSION " +
|
14
|
+
"(default 'txt')") do |extension|
|
14
15
|
options[:extension] = extension
|
15
16
|
end
|
16
17
|
|
data/lib/pickaxe/color.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Pickaxe
|
2
|
-
# Extracted from
|
2
|
+
# Extracted from
|
3
|
+
# https://github.com/wycats/thor/blob/master/lib/thor/shell/color.rb
|
3
4
|
module Color
|
4
5
|
# Embed in a String to clear all previous ANSI sequences.
|
5
6
|
CLEAR = "\e[0m"
|
data/lib/pickaxe/extensions.rb
CHANGED
@@ -7,7 +7,11 @@ class String
|
|
7
7
|
options.reverse_merge!(:line_width => Pickaxe::Shell.dynamic_width || 80)
|
8
8
|
|
9
9
|
self.split("\n").collect do |line|
|
10
|
-
line.length > options[:line_width]
|
10
|
+
if line.length > options[:line_width]
|
11
|
+
line.gsub(/(.{1,#{options[:line_width]}})(\s+|$)/, "\\1\n").strip
|
12
|
+
else
|
13
|
+
line
|
14
|
+
end
|
11
15
|
end * "\n"
|
12
16
|
end
|
13
17
|
|
data/lib/pickaxe/main.rb
CHANGED
@@ -22,8 +22,9 @@ END_OF_TEST
|
|
22
22
|
|
23
23
|
puts "! Hit Control-D to end test.\n\n"
|
24
24
|
|
25
|
-
@logger = Logger.new(File.open('answers.log',
|
26
|
-
|
25
|
+
@logger = Logger.new(File.open('answers.log',
|
26
|
+
File::WRONLY|File::TRUNC|File::CREAT))
|
27
|
+
@logger.formatter = lambda { |s, t, p, msg| msg.to_s + "\n" }
|
27
28
|
|
28
29
|
@questions = @test.shuffled_questions
|
29
30
|
@questions_length = @questions.length.to_f
|
@@ -31,11 +32,14 @@ END_OF_TEST
|
|
31
32
|
@started_at = Time.now
|
32
33
|
@current_index = 0
|
33
34
|
|
34
|
-
|
35
|
+
info = Main.options[:full_test] ? 1 : 0
|
36
|
+
while @current_index < @questions.length + info do
|
35
37
|
@question = @questions[@current_index]
|
36
38
|
|
37
39
|
unless @question.nil?
|
38
|
-
|
40
|
+
print "#{@current_index+1} / #{@questions.length}\t\t"
|
41
|
+
puts "From: #{@question.file}\t\tTime spent: #{spent?}"
|
42
|
+
|
39
43
|
puts @question.answered(@answers[@question])
|
40
44
|
else
|
41
45
|
puts END_OF_TEST_MESSAGE
|
@@ -102,8 +106,10 @@ Available commands (whitespace does not matter):
|
|
102
106
|
END_OF_HELP
|
103
107
|
false
|
104
108
|
else
|
105
|
-
@answers[@question] = line.
|
106
|
-
|
109
|
+
@answers[@question] = line.gsub(/\s+/, "").each_char.collect.to_a.uniq
|
110
|
+
unless Main.options[:full_test]
|
111
|
+
puts @question.check?(@answers[@question])
|
112
|
+
end
|
107
113
|
@current_index += 1
|
108
114
|
true
|
109
115
|
end
|
@@ -140,7 +146,8 @@ END_OF_HELP
|
|
140
146
|
protected
|
141
147
|
def stat(name, color)
|
142
148
|
value = @stats[name.to_s.downcase.to_sym]
|
143
|
-
puts format("#{name.to_s.capitalize}: #{value} (%g%%)",
|
149
|
+
puts format("#{name.to_s.capitalize}: #{value} (%g%%)",
|
150
|
+
value/@questions_length * 100).color(color)
|
144
151
|
end
|
145
152
|
end
|
146
153
|
end
|
data/lib/pickaxe/shell.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Pickaxe
|
2
2
|
module Shell
|
3
|
-
# Extracted from
|
3
|
+
# Extracted from
|
4
|
+
# https://github.com/wycats/thor/blob/master/lib/thor/shell/basic.rb
|
4
5
|
def self.dynamic_width
|
5
6
|
(dynamic_width_stty.nonzero? || dynamic_width_tput)
|
6
7
|
end
|
data/lib/pickaxe/test.rb
CHANGED
@@ -1,12 +1,54 @@
|
|
1
1
|
module Pickaxe
|
2
2
|
|
3
|
-
class PathError < PickaxeError
|
3
|
+
class PathError < PickaxeError
|
4
|
+
def initialize(file_or_directory)
|
5
|
+
super("file or directory '#{file_or_directory}' does not exist")
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class TestSyntaxError < PickaxeError
|
10
|
+
def initialize(file, line, message)
|
11
|
+
super("#{file}: line #{line}: #{message}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class MissingContent < TestSyntaxError
|
16
|
+
def initialize(file, line)
|
17
|
+
super(file, line, "no content (check blank lines nearby)")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class MissingAnswers < TestSyntaxError
|
22
|
+
def initialize(file, question)
|
23
|
+
super(file, question.index,
|
24
|
+
BadQuestion.message(question, "has no answers"))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class BadAnswer < TestSyntaxError
|
29
|
+
def initialize(file, line)
|
30
|
+
super(file, line.index,
|
31
|
+
"'#{line.truncate(20)}' starts with weird characters")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class BadQuestion < TestSyntaxError
|
36
|
+
def self.message(question, m)
|
37
|
+
"question '#{question.truncate(20)}' #{m}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(file, question)
|
41
|
+
super(file, question.index,
|
42
|
+
"'#{question.truncate(20)}' does not look like question")
|
43
|
+
end
|
44
|
+
end
|
4
45
|
|
5
|
-
class
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
46
|
+
class NoCorrectAnswer < TestSyntaxError
|
47
|
+
def initialize(file, question)
|
48
|
+
super(file, question.content.first.index,
|
49
|
+
BadQuestion.message(question.content.first, "has no correct answers"))
|
50
|
+
end
|
51
|
+
end
|
10
52
|
|
11
53
|
class TestLine < String
|
12
54
|
attr_accessor :index
|
@@ -39,19 +81,22 @@ module Pickaxe
|
|
39
81
|
|
40
82
|
def initialize(*files)
|
41
83
|
@files = files.collect do |file_or_directory|
|
42
|
-
|
84
|
+
unless File.exist?(file_or_directory)
|
85
|
+
raise PathError.new(file_or_directory)
|
86
|
+
end
|
87
|
+
|
43
88
|
if File.file?(file_or_directory)
|
44
89
|
file_or_directory
|
45
90
|
else
|
46
|
-
Dir.glob("#{file_or_directory}/*.#{Main.options[:extension]
|
91
|
+
Dir.glob("#{file_or_directory}/*.#{Main.options[:extension]}")
|
47
92
|
end
|
48
93
|
end.flatten.collect { |f| f.squeeze('/') }
|
49
94
|
|
50
95
|
@questions = []
|
51
96
|
@files.each do |file|
|
52
97
|
File.open(file) do |f|
|
53
|
-
lines = f.readlines.collect(&:strip).
|
54
|
-
TestLine.new(
|
98
|
+
lines = f.readlines.collect(&:strip).each_with_index.collect do |l, i|
|
99
|
+
TestLine.new(l, i)
|
55
100
|
end
|
56
101
|
|
57
102
|
lines = lines.reject {|line| line =~ COMMENTS_RE }
|
@@ -117,25 +162,26 @@ module Pickaxe
|
|
117
162
|
until answers.first.nil? or Answer::RE.match(answers.first)
|
118
163
|
content << answers.shift
|
119
164
|
end
|
120
|
-
|
121
|
-
raise MissingAnswers,
|
122
|
-
|
165
|
+
|
166
|
+
raise MissingAnswers.new(file, answers.first.index) if content.blank?
|
167
|
+
unless m = RE.match(content.first)
|
168
|
+
raise BadQuestion.new(file, content.first)
|
169
|
+
end
|
170
|
+
raise MissingAnswers.new(file, content.first) if answers.blank?
|
123
171
|
|
124
|
-
error_template = "#{file}: line #{content.first.index}: question '#{content.first.truncate(20)}' %s"
|
125
|
-
raise MissingAnswers, (error_template % "has no answers") if answers.blank?
|
126
|
-
|
127
172
|
answers = answers.inject([]) do |joined, line|
|
128
173
|
if Answer::RE.match(line)
|
129
174
|
joined << [line]
|
130
175
|
else
|
131
|
-
raise BadAnswer,
|
176
|
+
raise BadAnswer.new(file, line)unless Answer::LINE_RE.match(line)
|
132
177
|
joined.last << line
|
133
178
|
end
|
134
179
|
joined
|
135
180
|
end
|
136
181
|
|
137
|
-
|
138
|
-
|
182
|
+
answers = answers.collect {|answer| Answer.parse(file, answer) }
|
183
|
+
Question.new(file, m[1], content, answers).tap do |q|
|
184
|
+
raise NoCorrectAnswer.new(file, q) if q.correct_answers.blank?
|
139
185
|
end
|
140
186
|
end
|
141
187
|
|
@@ -145,7 +191,8 @@ module Pickaxe
|
|
145
191
|
selected = indices.include?(answer.index)
|
146
192
|
line = (selected ? ">> " : " ") + answer.to_s
|
147
193
|
|
148
|
-
if
|
194
|
+
if(Main.options[:force_show_answers] or
|
195
|
+
(not indices.blank? and not Main.options[:full_test])) then
|
149
196
|
if selected and answer.correctness
|
150
197
|
line.color(:green)
|
151
198
|
elsif not selected and answer.correctness
|
@@ -175,12 +222,13 @@ module Pickaxe
|
|
175
222
|
end
|
176
223
|
|
177
224
|
class Answer < Struct.new(:content, :index, :correctness)
|
178
|
-
RE = /^\s*(>+)?\s*(
|
179
|
-
LINE_RE = /^\s*(
|
225
|
+
RE = /^\s*(>+)?\s*(\?+)?\s*\(?(\w)\)\s*(.+)$/u
|
226
|
+
LINE_RE = /^\s*([[:alpha:]]|\w+)/u
|
180
227
|
|
181
228
|
def self.parse(file, lines)
|
182
229
|
m = RE.match(lines.shift)
|
183
|
-
Answer.new(m[4].strip + " " + lines.collect(&:strip).join(" "),
|
230
|
+
Answer.new(m[4].strip + " " + lines.collect(&:strip).join(" "),
|
231
|
+
m[3].strip, !m[1].nil?)
|
184
232
|
end
|
185
233
|
|
186
234
|
def to_s
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: Pickaxe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 9
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 5
|
9
|
+
- 1
|
10
|
+
version: 0.5.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Dawid Fatyga
|