daigaku 0.6.0 → 1.0.0

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.
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.