daigaku 0.6.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0e51c3ee2e1a66caaa9175593f91548ad87775c715be4f73fbe431dac530cd17
4
- data.tar.gz: 45e3fd1854e26d55c201aaf9922ed13255dd543b2b08d003836159df72df8880
3
+ metadata.gz: 3d2569151b28f6803d8c351ad6c131e13d741c7515a08e3d6e5ff2db007d085b
4
+ data.tar.gz: d53b84a072e46320f7e4555c00ba3955e9de81a0729037257c4c41e217e72c67
5
5
  SHA512:
6
- metadata.gz: 64b9d02de58bf07df8d6c529c075f2799f6e6af436da46dc012b4c7555d7a991ac8ce71a82443f3a27f66c82cd08aabec8a6206e8133dfe85510c5756f25f657
7
- data.tar.gz: 6fb51479ce5fa62bde15305f817c3e9979da389797dd678afe496e054e134f8b24f9c69bd44173448f8ece9290a032dae2d166192d13aabc24635c633b1d3984
6
+ metadata.gz: c3d43f800a282522f4cae4550e56785e92b1feee01f179306e5022e81223716437fd2b3b813adb37328d9d6b835cfafacd6842de8d7db5c8cbe05c4703deb4ad
7
+ data.tar.gz: 6373c4ae4ba47cb9ae150d5048b16898b98cf4e768d8f70b9f46d406e2b6951e0e4d260b141fe85e5602007be44dc92f55b25a3763000e81b366d55534e786c0
@@ -4,10 +4,6 @@ before_install:
4
4
  - gem install bundler
5
5
 
6
6
  rvm:
7
- - 2.4.5
8
- - 2.4.9
9
7
  - 2.5.0
10
- - 2.5.7
11
8
  - 2.6.0
12
- - 2.6.5
13
- - ruby-head
9
+ - 2.7.0
data/README.md CHANGED
@@ -16,7 +16,7 @@ language-explaining programming tasks.
16
16
  ## Installation
17
17
 
18
18
  First of all make sure Ruby is installed on your computer.
19
- Daigaku works with [MRI Ruby](https://www.ruby-lang.org/en/documentation/installation/) v2.4.5 or higher.
19
+ Daigaku works with [MRI Ruby](https://www.ruby-lang.org/en/documentation/installation/) v2.5 or higher.
20
20
 
21
21
  Then open a terminal and install Daigaku by running:
22
22
 
@@ -6,7 +6,11 @@ begin
6
6
  require 'daigaku'
7
7
  rescue LoadError => e
8
8
  warn "could not load \"daigaku\"\n#{e}"
9
- exit -1
9
+ exit(-1)
10
10
  end
11
11
 
12
- Daigaku::Terminal::CLI.start
12
+ begin
13
+ Daigaku::Terminal::CLI.start
14
+ rescue Interrupt
15
+ puts "\n\n\t👋 See you soon!"
16
+ end
@@ -16,17 +16,17 @@ Gem::Specification.new do |spec|
16
16
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
17
  spec.require_paths = ['lib']
18
18
 
19
- spec.required_ruby_version = '>= 2.4.5'
19
+ spec.required_ruby_version = '>= 2.5'
20
20
 
21
21
  spec.add_runtime_dependency 'curses', '~> 1.3'
22
22
  spec.add_runtime_dependency 'rspec', '~> 3.0'
23
- spec.add_runtime_dependency 'thor', '~> 0.20'
23
+ spec.add_runtime_dependency 'thor', '~> 1.0'
24
24
  spec.add_runtime_dependency 'os', '~> 1.0'
25
25
  spec.add_runtime_dependency 'colorize', '~> 0.8'
26
26
  spec.add_runtime_dependency 'rubyzip', '~> 2.0'
27
27
  spec.add_runtime_dependency 'wisper', '~> 2.0'
28
- spec.add_runtime_dependency 'quick_store', '~> 0.2'
29
- spec.add_runtime_dependency 'code_breaker', '~> 0.3'
28
+ spec.add_runtime_dependency 'quick_store', '~> 1.0'
29
+ spec.add_runtime_dependency 'code_breaker', '~> 1.0'
30
30
 
31
31
  spec.add_development_dependency 'bundler', '~> 2.0'
32
32
  spec.add_development_dependency 'rake', '~> 13.0'
@@ -12,7 +12,7 @@ module Daigaku
12
12
  # Returns the timestamp of updated_at for the repo from the Github API.
13
13
  def self.updated_at(user_and_repo)
14
14
  url = "https://api.github.com/repos/#{user_and_repo}"
15
- JSON.parse(open(url).read)['updated_at']
15
+ JSON.parse(URI.open(url).read)['updated_at']
16
16
  end
17
17
 
18
18
  # Returns whether the pushed_at time from Github API is newer than the
@@ -7,12 +7,13 @@ module Daigaku
7
7
  def initialize(unit_path)
8
8
  @unit_path = unit_path
9
9
  @path = solution_path(unit_path)
10
- @code = File.read(@path).strip if File.file?(@path)
10
+ @code = load_code(@path)
11
11
  @verified = store_state
12
12
  end
13
13
 
14
14
  def verify!
15
- result = Daigaku::Test.new(@unit_path).run(code)
15
+ @code = load_code(@path)
16
+ result = Daigaku::Test.new(@unit_path).run(@code)
16
17
  self.store_state = result.passed?
17
18
  result
18
19
  end
@@ -32,6 +33,10 @@ module Daigaku
32
33
 
33
34
  private
34
35
 
36
+ def load_code(path)
37
+ File.read(path).strip if File.file?(path)
38
+ end
39
+
35
40
  def solution_path(path)
36
41
  local_path = Daigaku.config.solutions_path
37
42
  sub_directory = Storeable.key(directory_from(path))
@@ -9,6 +9,8 @@ module Daigaku
9
9
  class CLI < Thor
10
10
  include Terminal::Output
11
11
 
12
+ package_name 'Daigaku'
13
+
12
14
  desc 'courses [COMMAND]', 'Handle daigaku courses'
13
15
  subcommand 'courses', Terminal::Courses
14
16
 
@@ -37,7 +37,7 @@ module Daigaku
37
37
 
38
38
  file_name = File.join(courses_path, url.split('/').last)
39
39
 
40
- File.open(file_name, 'w') { |file| file << open(url).read }
40
+ File.open(file_name, 'w') { |file| file << URI.open(url).read }
41
41
  course = Course.unzip(file_name, github_repo: github)
42
42
 
43
43
  if github
@@ -18,7 +18,7 @@ module Daigaku
18
18
  temp_spec = File.join(File.dirname(@path), "temp_#{File.basename(@path)}")
19
19
  create_temp_spec(temp_spec, patched_spec_code)
20
20
 
21
- result = `rspec --color --format j #{temp_spec}`
21
+ result = `rspec --no-color --order defined --format j #{temp_spec}`
22
22
  remove_file(temp_spec)
23
23
 
24
24
  TestResult.new(result)
@@ -2,17 +2,26 @@ require 'json'
2
2
 
3
3
  module Daigaku
4
4
  class TestResult
5
+ CODE_ERROR_MESSAGE = ':( You got an error in your code!'.freeze
6
+
5
7
  attr_reader :examples, :example_count, :failure_count
6
8
 
7
9
  def initialize(result_json)
8
10
  @result = begin
9
11
  JSON.parse(result_json, symbolize_names: true)
10
- rescue
11
- syntax_error_json
12
+ rescue => error
13
+ syntax_error_json(error)
12
14
  end
13
15
 
14
- @example_count = @result[:summary][:example_count]
15
- @failure_count = @result[:summary][:failure_count]
16
+ @example_count = @result.dig(:summary, :example_count)
17
+ @failure_count = @result.dig(:summary, :failure_count)
18
+ error_count = @result.dig(:summary, :errors_outside_of_examples_count) || 0
19
+
20
+ if error_count > 0
21
+ @failure_count = error_count
22
+ details = error_details(@result)
23
+ @result = error_json(details)
24
+ end
16
25
 
17
26
  @examples = @result[:examples].map do |example|
18
27
  description = example[:full_description]
@@ -52,32 +61,59 @@ module Daigaku
52
61
  message.join("\n" * 3)
53
62
  end
54
63
 
55
- def syntax_error_json
64
+ def syntax_error_json(error)
65
+ details = failure_details(error)
66
+ error_json(details)
67
+ end
68
+
69
+ def error_details(result)
70
+ result[:messages]
71
+ .first
72
+ .split('\n')
73
+ .each_with_index
74
+ .select { |line, index| index > 0 && line.matches?(/temp_.+\.rb/) }
75
+ .first.to_s
76
+ end
77
+
78
+ def error_json(details)
56
79
  {
57
80
  summary: {},
58
81
  examples: [
59
82
  {
60
- status: 'failed',
61
- exception: { message: ':( You got an error in your code!' }
83
+ status: TestExample::FAILED,
84
+ exception: { message: "#{CODE_ERROR_MESSAGE}\n\n#{details}" }
62
85
  }
63
86
  ]
64
87
  }
65
88
  end
89
+
90
+ def failure_details(error)
91
+ line = error.backtrace.first
92
+ error_message = remove_colorization(error.message)
93
+ "#{error.class} in #{line}:\n#{error_message}"
94
+ end
95
+
96
+ def remove_colorization(text)
97
+ text.gsub(/\x1b\[[0-9]*m/i, '')
98
+ end
66
99
  end
67
100
 
68
101
  class TestExample
102
+ PASSED = 'passed'.freeze
103
+ FAILED = 'failed'.freeze
104
+
69
105
  attr_reader :description, :status, :message
70
106
 
71
107
  EXAMPLE_PASSED_MESSAGE = 'Your code passed this requirement.'.freeze
72
108
 
73
- def initialize(description:, status:, message: nil)
109
+ def initialize(status:, description: nil, message: nil)
74
110
  @description = description
75
111
  @status = status
76
112
  @message = message || EXAMPLE_PASSED_MESSAGE
77
113
  end
78
114
 
79
115
  def passed?
80
- @status == 'passed'
116
+ @status == PASSED
81
117
  end
82
118
  end
83
119
  end
@@ -16,7 +16,7 @@ module Daigaku
16
16
  end
17
17
 
18
18
  def solution
19
- @solution = Solution.new(@path)
19
+ @solution ||= Solution.new(@path)
20
20
  end
21
21
 
22
22
  def mastered?
@@ -1,3 +1,3 @@
1
1
  module Daigaku
2
- VERSION = '0.6.0'.freeze
2
+ VERSION = '1.0.0'.freeze
3
3
  end
@@ -7,10 +7,10 @@ module Daigaku
7
7
  include Wisper::Publisher
8
8
 
9
9
  TOP_BAR_TEXT = [
10
- 'Use *UP KEY* and *DOWN KEY* for menu navigation',
11
- 'Enter menu with *RETURN*',
12
- 'Go back with *BACKSPACE*',
13
- 'Exit with *ESC*'
10
+ 'Use * 🠕 * and * 🠗 * for menu navigation',
11
+ 'Enter menu with **',
12
+ 'Go back with **',
13
+ 'Exit with *Esc*'
14
14
  ].join(' | ').freeze
15
15
 
16
16
  attr_writer :items_info
@@ -8,11 +8,11 @@ module Daigaku
8
8
  include Wisper::Publisher
9
9
 
10
10
  TOP_BAR_TEXT = [
11
- 'Scroll with *UP KEY* and *DOWN KEY*',
11
+ 'Scroll with * 🠕 * and * 🠗 *',
12
12
  'Open solution file with *o*',
13
13
  'Verify solution with *v*',
14
14
  'Clear validation with *c*',
15
- 'Exit with *ESC*'
15
+ 'Exit with *Esc*'
16
16
  ].join(' | ').freeze
17
17
 
18
18
  def initialize
@@ -201,11 +201,10 @@ module Daigaku
201
201
  @lines = [''] + @test_result_lines + ['', ''] + @unit.task.markdown.lines
202
202
  @examples = result.examples
203
203
 
204
- @example_heights = @examples.reduce({}) do |hash, example|
204
+ @example_heights = @examples.each_with_object({}) do |example, hash|
205
205
  start = hash.values.reduce(0) { |sum, results| sum + results.count }
206
206
  range = (start..(start + example.message.split("\n").count) + 2)
207
207
  hash[hash.keys.count] = range
208
- hash
209
208
  end
210
209
 
211
210
  lines_count = @lines.count + @top_bar_height + @head_height
@@ -223,8 +222,8 @@ module Daigaku
223
222
  def code_error_lines(code)
224
223
  begin
225
224
  eval(code)
226
- rescue StandardError => e
227
- return e.inspect.gsub(/(\A.*#<|>.*$)/, '').lines.map(&:rstrip)
225
+ rescue StandardError, ScriptError => error
226
+ return error.inspect.gsub(/(\A.*#<|>.*$)/, '').lines.map(&:rstrip)
228
227
  end
229
228
 
230
229
  []
@@ -62,10 +62,11 @@ describe Daigaku::Solution do
62
62
  end
63
63
 
64
64
  it 'sets the solution’s state in the store to unverified unless passed' do
65
- subject.instance_variable_set(:@code, 'puts "I ❤ Daigaku!"')
65
+ allow(File).to receive(:read).and_return('puts "I ❤ Daigaku!"')
66
+ QuickStore.store.set(subject.store_key, true)
67
+
66
68
  subject.verify!
67
69
  mastered = QuickStore.store.get(subject.store_key)
68
-
69
70
  expect(mastered).to be_falsey
70
71
  end
71
72
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: daigaku
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Götze
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-27 00:00:00.000000000 Z
11
+ date: 2020-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: curses
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0.20'
47
+ version: '1.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0.20'
54
+ version: '1.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: os
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -114,28 +114,28 @@ dependencies:
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0.2'
117
+ version: '1.0'
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '0.2'
124
+ version: '1.0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: code_breaker
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '0.3'
131
+ version: '1.0'
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '0.3'
138
+ version: '1.0'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: bundler
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -310,14 +310,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
310
310
  requirements:
311
311
  - - ">="
312
312
  - !ruby/object:Gem::Version
313
- version: 2.4.5
313
+ version: '2.5'
314
314
  required_rubygems_version: !ruby/object:Gem::Requirement
315
315
  requirements:
316
316
  - - ">="
317
317
  - !ruby/object:Gem::Version
318
318
  version: '0'
319
319
  requirements: []
320
- rubygems_version: 3.0.3
320
+ rubygems_version: 3.1.3
321
321
  signing_key:
322
322
  specification_version: 4
323
323
  summary: Learning Ruby on the command line.