Pickaxe 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +9 -0
- data/bin/drill +4 -0
- data/bin/pickaxe +1 -61
- data/lib/pickaxe.rb +1 -1
- data/lib/pickaxe/cli.rb +53 -0
- data/lib/pickaxe/main.rb +12 -3
- data/lib/pickaxe/test.rb +26 -9
- metadata +8 -5
data/README.markdown
CHANGED
@@ -4,3 +4,12 @@ Pickaxe provides a simple way to load, solve and rate tests
|
|
4
4
|
(bundle of questions) written in simple text format.
|
5
5
|
|
6
6
|
Documentation can be read [here](http://dejw.github.com/pickaxe/).
|
7
|
+
|
8
|
+
**Note:** pickaxe was not tested on Windows yet (and it will not work there
|
9
|
+
since `Pickaxe::Shell` executes some terminal related code).
|
10
|
+
|
11
|
+
## instalation
|
12
|
+
|
13
|
+
sudo gem install Pickaxe
|
14
|
+
|
15
|
+
|
data/bin/drill
ADDED
data/bin/pickaxe
CHANGED
@@ -1,64 +1,4 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'optparse'
|
4
|
-
|
5
2
|
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
|
6
|
-
|
7
3
|
require 'pickaxe'
|
8
|
-
|
9
|
-
# TODO:
|
10
|
-
# time limit
|
11
|
-
# syntax check only
|
12
|
-
# default -> warns + ignore, options for exception on syntax error ;-)
|
13
|
-
|
14
|
-
options = {}
|
15
|
-
OptionParser.new do |opts|
|
16
|
-
opts.banner = <<END_OF_BANNER
|
17
|
-
Usage:
|
18
|
-
pickaxe path [, path ...]
|
19
|
-
|
20
|
-
Uses given paths (files or directories) to generate a test from *.txt files.
|
21
|
-
END_OF_BANNER
|
22
|
-
|
23
|
-
opts.separator ""
|
24
|
-
opts.on("-e", "--ext [EXTENSION]", "Use files with given EXTENSION (default 'txt')") do |extension|
|
25
|
-
options[:extension] = extension
|
26
|
-
end
|
27
|
-
|
28
|
-
opts.on("-s", "--sorted", "Do not shuffle questions") do |v|
|
29
|
-
options[:sorted] = true
|
30
|
-
end
|
31
|
-
|
32
|
-
opts.on("--select [NUMBER]", "Select certain number of questions") do |v|
|
33
|
-
options[:select] = Integer(v)
|
34
|
-
end
|
35
|
-
|
36
|
-
opts.on("--full-test", "Checks test after all questions are answered") do |v|
|
37
|
-
options[:full_test] = true
|
38
|
-
end
|
39
|
-
|
40
|
-
opts.on("--strict", "Quit on syntax error in test file") do |v|
|
41
|
-
options[:strict] = true
|
42
|
-
end
|
43
|
-
|
44
|
-
opts.on_tail("--syntax-check", "Check syntax only - do not run test") do
|
45
|
-
options[:syntax_check] = true
|
46
|
-
end
|
47
|
-
|
48
|
-
opts.on_tail("--version", "Show version") do
|
49
|
-
puts "pickaxe version #{Pickaxe::VERSION}"
|
50
|
-
exit
|
51
|
-
end
|
52
|
-
|
53
|
-
opts.on_tail("-h", "--help", "Show this message") do
|
54
|
-
puts opts
|
55
|
-
exit
|
56
|
-
end
|
57
|
-
end.parse!
|
58
|
-
|
59
|
-
begin
|
60
|
-
Pickaxe::Main.new(ARGV, options)
|
61
|
-
rescue Pickaxe::PickaxeError => e
|
62
|
-
$stderr.puts(("! " + e.message).color(:red))
|
63
|
-
exit(e.status_code)
|
64
|
-
end
|
4
|
+
require "pickaxe/cli"
|
data/lib/pickaxe.rb
CHANGED
data/lib/pickaxe/cli.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
options = {}
|
4
|
+
OptionParser.new do |opts|
|
5
|
+
opts.banner = <<END_OF_BANNER
|
6
|
+
Usage:
|
7
|
+
#{$0.split("/").last} path [, path ...]
|
8
|
+
|
9
|
+
Uses given paths (files or directories) to generate a test from *.txt files.
|
10
|
+
END_OF_BANNER
|
11
|
+
|
12
|
+
opts.separator ""
|
13
|
+
opts.on("-e", "--ext [EXTENSION]", "Use files with given EXTENSION (default 'txt')") do |extension|
|
14
|
+
options[:extension] = extension
|
15
|
+
end
|
16
|
+
|
17
|
+
opts.on("-s", "--sorted", "Do not shuffle questions") do |v|
|
18
|
+
options[:sorted] = true
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on("--select [NUMBER]", "Select certain number of questions") do |v|
|
22
|
+
options[:select] = Integer(v)
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on("--full-test", "Checks test after all questions are answered") do |v|
|
26
|
+
options[:full_test] = true
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on("--strict", "Quit on syntax error in test file") do |v|
|
30
|
+
options[:strict] = true
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on_tail("--syntax-check", "Check syntax only - do not run test") do
|
34
|
+
options[:syntax_check] = true
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on_tail("--version", "Show version") do
|
38
|
+
puts "pickaxe version #{Pickaxe::VERSION}"
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
|
42
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
43
|
+
puts opts
|
44
|
+
exit
|
45
|
+
end
|
46
|
+
end.parse!
|
47
|
+
|
48
|
+
begin
|
49
|
+
Pickaxe::Main.new(ARGV, options)
|
50
|
+
rescue Pickaxe::PickaxeError => e
|
51
|
+
$stderr.puts(("! " + e.message).color(:red))
|
52
|
+
exit(e.status_code)
|
53
|
+
end
|
data/lib/pickaxe/main.rb
CHANGED
@@ -18,6 +18,11 @@ END_OF_TEST
|
|
18
18
|
@test = Test.new(*paths)
|
19
19
|
return if options[:syntax_check]
|
20
20
|
|
21
|
+
puts "! Hit Control-D to end test.\n\n"
|
22
|
+
|
23
|
+
@logger = Logger.new(File.open('answers.log', File::WRONLY|File::TRUNC|File::CREAT))
|
24
|
+
@logger.formatter = lambda { |severity, time, progname, msg| msg.to_s + "\n" }
|
25
|
+
|
21
26
|
@questions = @test.shuffled_questions
|
22
27
|
@answers = Hash.new([])
|
23
28
|
@started_at = Time.now
|
@@ -74,7 +79,7 @@ END_OF_TEST
|
|
74
79
|
if Main.options[:full_test] and @question.nil?
|
75
80
|
Main.options[:full_test] = false
|
76
81
|
Main.options[:force_show_answers] = true
|
77
|
-
|
82
|
+
|
78
83
|
@current_index = 0
|
79
84
|
else
|
80
85
|
@current_index += 1
|
@@ -93,7 +98,7 @@ Available commands (whitespace does not matter):
|
|
93
98
|
END_OF_HELP
|
94
99
|
false
|
95
100
|
else
|
96
|
-
@answers[@question] = line.split(/\s+/).collect(&:strip)
|
101
|
+
@answers[@question] = line.strip.split(/\s+/).collect(&:strip)
|
97
102
|
puts @question.check?(@answers[@question]) unless Main.options[:full_test]
|
98
103
|
@current_index += 1
|
99
104
|
true
|
@@ -102,7 +107,11 @@ END_OF_HELP
|
|
102
107
|
|
103
108
|
def statistics!
|
104
109
|
@stats = @test.statistics!(@answers)
|
105
|
-
|
110
|
+
|
111
|
+
@answers.each do |question, answers|
|
112
|
+
@logger << ("#{question.index}: #{answers.join(" ")}\n")
|
113
|
+
end
|
114
|
+
|
106
115
|
puts
|
107
116
|
puts "Time: #{spent?}"
|
108
117
|
puts "All: #{@questions.length}"
|
data/lib/pickaxe/test.rb
CHANGED
@@ -5,6 +5,7 @@ module Pickaxe
|
|
5
5
|
class TestSyntaxError < PickaxeError; status_code(2) ; end
|
6
6
|
class MissingAnswers < TestSyntaxError; status_code(2) ; end
|
7
7
|
class BadAnswer < TestSyntaxError; status_code(3) ; end
|
8
|
+
class BadQuestion < TestSyntaxError; status_code(4) ; end
|
8
9
|
class NoCorrectAnswer < TestSyntaxError; status_code(3) ; end
|
9
10
|
|
10
11
|
class TestLine < String
|
@@ -34,7 +35,7 @@ module Pickaxe
|
|
34
35
|
include Enumerable
|
35
36
|
|
36
37
|
# Ruby-comments and C-comments
|
37
|
-
COMMENTS_RE =
|
38
|
+
COMMENTS_RE = /^\s*#.*|^\/\/.*/
|
38
39
|
|
39
40
|
def initialize(*files)
|
40
41
|
@files = files.collect do |file_or_directory|
|
@@ -44,7 +45,7 @@ module Pickaxe
|
|
44
45
|
else
|
45
46
|
Dir.glob("#{file_or_directory}/*.#{Main.options[:extension] || "txt"}")
|
46
47
|
end
|
47
|
-
end.flatten.collect(
|
48
|
+
end.flatten.collect { |f| f.squeeze('/') }
|
48
49
|
|
49
50
|
@questions = []
|
50
51
|
@files.each do |file|
|
@@ -108,7 +109,9 @@ module Pickaxe
|
|
108
109
|
end
|
109
110
|
end
|
110
111
|
|
111
|
-
class Question < Struct.new(:file, :content, :answers)
|
112
|
+
class Question < Struct.new(:file, :index, :content, :answers)
|
113
|
+
RE = /^\s*(\d+)\.?\s*(.+)$/
|
114
|
+
|
112
115
|
def self.parse(file, answers)
|
113
116
|
content = []
|
114
117
|
until answers.first.nil? or Answer::RE.match(answers.first)
|
@@ -116,10 +119,22 @@ module Pickaxe
|
|
116
119
|
end
|
117
120
|
|
118
121
|
raise MissingAnswers, "#{file}: line #{answers.first.index}: no content (check blank lines nearby)" if content.blank?
|
119
|
-
|
122
|
+
raise BadQuestion, "#{file}: line #{content.first.index}: '#{content.first.truncate(20)}' does not look like question" unless m = RE.match(content.first)
|
123
|
+
|
120
124
|
error_template = "#{file}: line #{content.first.index}: question '#{content.first.truncate(20)}' %s"
|
121
125
|
raise MissingAnswers, (error_template % "has no answers") if answers.blank?
|
122
|
-
|
126
|
+
|
127
|
+
answers = answers.inject([]) do |joined, line|
|
128
|
+
if Answer::RE.match(line)
|
129
|
+
joined << [line]
|
130
|
+
else
|
131
|
+
raise BadAnswer, "#{file}: line #{line.index}: '#{line.truncate(20)}' starts with weird characters" unless Answer::LINE_RE.match(line)
|
132
|
+
joined.last << line
|
133
|
+
end
|
134
|
+
joined
|
135
|
+
end
|
136
|
+
|
137
|
+
Question.new(file, m[1], content, answers.collect {|answer| Answer.parse(file, answer) }).tap do |q|
|
123
138
|
raise NoCorrectAnswer, (error_template % "has no correct answer") if q.correct_answers.blank?
|
124
139
|
end
|
125
140
|
end
|
@@ -160,10 +175,12 @@ module Pickaxe
|
|
160
175
|
end
|
161
176
|
|
162
177
|
class Answer < Struct.new(:content, :index, :correctness)
|
163
|
-
RE = /^\s*(>>)
|
164
|
-
|
165
|
-
|
166
|
-
|
178
|
+
RE = /^\s*(>>)?\s*(\?\?)?\s*\((\w+)\)\s*(.+)$/
|
179
|
+
LINE_RE = /^\s*(\w+)/
|
180
|
+
|
181
|
+
def self.parse(file, lines)
|
182
|
+
m = RE.match(lines.shift)
|
183
|
+
Answer.new(m[m.size-1].strip + " " + lines.collect(&:strip).join(" "), m[m.size-2].strip, m[1] == ">>")
|
167
184
|
end
|
168
185
|
|
169
186
|
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: 11
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 4
|
9
|
-
-
|
10
|
-
version: 0.4.
|
9
|
+
- 2
|
10
|
+
version: 0.4.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Dawid Fatyga
|
@@ -15,8 +15,8 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
19
|
-
default_executable:
|
18
|
+
date: 2010-12-01 00:00:00 +01:00
|
19
|
+
default_executable: bin/pickaxe
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
@@ -73,6 +73,7 @@ description: |
|
|
73
73
|
email: dawid.fatyga@gmail.com
|
74
74
|
executables:
|
75
75
|
- pickaxe
|
76
|
+
- drill
|
76
77
|
extensions: []
|
77
78
|
|
78
79
|
extra_rdoc_files:
|
@@ -82,10 +83,12 @@ extra_rdoc_files:
|
|
82
83
|
files:
|
83
84
|
- lib/pickaxe.rb
|
84
85
|
- lib/pickaxe/test.rb
|
86
|
+
- lib/pickaxe/cli.rb
|
85
87
|
- lib/pickaxe/color.rb
|
86
88
|
- lib/pickaxe/extensions.rb
|
87
89
|
- lib/pickaxe/shell.rb
|
88
90
|
- lib/pickaxe/main.rb
|
91
|
+
- bin/drill
|
89
92
|
- bin/pickaxe
|
90
93
|
- README.markdown
|
91
94
|
- Gemfile
|