daigaku 0.2.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 +5 -5
- data/.travis.yml +7 -4
- data/CODE_OF_CONDUCT.md +77 -0
- data/README.md +11 -11
- data/bin/daigaku +6 -2
- data/daigaku.gemspec +22 -26
- data/lib/daigaku.rb +0 -1
- data/lib/daigaku/chapter.rb +3 -4
- data/lib/daigaku/coloring.rb +22 -27
- data/lib/daigaku/configuration.rb +25 -28
- data/lib/daigaku/congratulator.rb +17 -5
- data/lib/daigaku/course.rb +9 -8
- data/lib/daigaku/exceptions.rb +0 -2
- data/lib/daigaku/generator.rb +13 -15
- data/lib/daigaku/github_client.rb +5 -5
- data/lib/daigaku/loadable.rb +23 -14
- data/lib/daigaku/loading/chapters.rb +0 -2
- data/lib/daigaku/loading/courses.rb +0 -2
- data/lib/daigaku/loading/units.rb +0 -2
- data/lib/daigaku/markdown.rb +1 -0
- data/lib/daigaku/markdown/printer.rb +89 -0
- data/lib/daigaku/markdown/ruby_doc.rb +15 -15
- data/lib/daigaku/solution.rb +23 -15
- data/lib/daigaku/storeable.rb +11 -12
- data/lib/daigaku/task.rb +1 -1
- data/lib/daigaku/terminal.rb +3 -4
- data/lib/daigaku/terminal/cli.rb +8 -8
- data/lib/daigaku/terminal/courses.rb +22 -19
- data/lib/daigaku/terminal/output.rb +46 -53
- data/lib/daigaku/terminal/setup.rb +13 -18
- data/lib/daigaku/terminal/solutions.rb +27 -32
- data/lib/daigaku/terminal/welcome.rb +9 -11
- data/lib/daigaku/test.rb +7 -10
- data/lib/daigaku/test_result.rb +54 -21
- data/lib/daigaku/unit.rb +2 -4
- data/lib/daigaku/version.rb +1 -1
- data/lib/daigaku/views.rb +29 -33
- data/lib/daigaku/views/chapters_menu.rb +16 -20
- data/lib/daigaku/views/courses_menu.rb +12 -15
- data/lib/daigaku/views/main_menu.rb +23 -23
- data/lib/daigaku/views/menu.rb +14 -18
- data/lib/daigaku/views/splash.rb +11 -13
- data/lib/daigaku/views/subscriber.rb +38 -0
- data/lib/daigaku/views/task_view.rb +97 -80
- data/lib/daigaku/views/top_bar.rb +4 -10
- data/lib/daigaku/views/units_menu.rb +16 -21
- data/lib/daigaku/window.rb +12 -70
- data/spec/daigaku/chapter_spec.rb +23 -18
- data/spec/daigaku/coloring_spec.rb +0 -1
- data/spec/daigaku/configuration_spec.rb +54 -50
- data/spec/daigaku/congratulator_spec.rb +11 -8
- data/spec/daigaku/course_spec.rb +75 -52
- data/spec/daigaku/generator_spec.rb +24 -25
- data/spec/daigaku/github_client_spec.rb +17 -18
- data/spec/daigaku/loading/chapters_spec.rb +2 -3
- data/spec/daigaku/loading/courses_spec.rb +2 -3
- data/spec/daigaku/loading/units_spec.rb +4 -5
- data/spec/daigaku/markdown/ruby_doc_spec.rb +12 -6
- data/spec/daigaku/reference_solution_spec.rb +8 -10
- data/spec/daigaku/solution_spec.rb +21 -22
- data/spec/daigaku/storeable_spec.rb +12 -10
- data/spec/daigaku/task_spec.rb +3 -4
- data/spec/daigaku/terminal/cli_spec.rb +29 -21
- data/spec/daigaku/terminal/courses_spec.rb +104 -99
- data/spec/daigaku/terminal/output_spec.rb +44 -39
- data/spec/daigaku/terminal/setup_spec.rb +1 -3
- data/spec/daigaku/terminal/solutions_spec.rb +0 -2
- data/spec/daigaku/terminal/welcome_spec.rb +0 -2
- data/spec/daigaku/terminal_spec.rb +5 -7
- data/spec/daigaku/test_example_spec.rb +16 -14
- data/spec/daigaku/test_result_spec.rb +21 -25
- data/spec/daigaku/test_spec.rb +11 -12
- data/spec/daigaku/unit_spec.rb +24 -27
- data/spec/daigaku/views/chapters_menu_spec.rb +0 -1
- data/spec/daigaku/views/courses_menu_spec.rb +0 -1
- data/spec/daigaku/views/menu_spec.rb +1 -2
- data/spec/daigaku/views/task_view_spec.rb +0 -2
- data/spec/daigaku/views/units_menu_spec.rb +0 -1
- data/spec/daigaku/views_spec.rb +0 -1
- data/spec/daigaku_spec.rb +9 -12
- data/spec/path_helpers_spec.rb +11 -12
- data/spec/resource_helpers_spec.rb +11 -12
- data/spec/spec_helper.rb +3 -4
- data/spec/support/macros/content_helpers.rb +16 -17
- data/spec/support/macros/mock_helpers.rb +6 -6
- data/spec/support/macros/path_helpers.rb +15 -15
- data/spec/support/macros/resource_helpers.rb +34 -35
- metadata +32 -44
@@ -2,9 +2,7 @@ require 'daigaku/views/menu'
|
|
2
2
|
|
3
3
|
module Daigaku
|
4
4
|
module Views
|
5
|
-
|
6
5
|
class CoursesMenu < Menu
|
7
|
-
|
8
6
|
private
|
9
7
|
|
10
8
|
def header_text
|
@@ -14,17 +12,17 @@ module Daigaku
|
|
14
12
|
def interact_with(window)
|
15
13
|
while char = window.getch
|
16
14
|
case char
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
15
|
+
when KEY_UP
|
16
|
+
@position -= 1
|
17
|
+
broadcast(:reset_menu_position)
|
18
|
+
when KEY_DOWN
|
19
|
+
@position += 1
|
20
|
+
broadcast(:reset_menu_position)
|
21
|
+
when 10 # Enter
|
22
|
+
broadcast(:enter, models[@position])
|
23
|
+
return
|
24
|
+
when 27 # ESC
|
25
|
+
exit
|
28
26
|
end
|
29
27
|
|
30
28
|
@position = items.length - 1 if @position < 0
|
@@ -41,12 +39,11 @@ module Daigaku
|
|
41
39
|
non_empty_courses = models.select { |course| !course.chapters.empty? }
|
42
40
|
|
43
41
|
non_empty_courses.map do |course|
|
44
|
-
line =
|
42
|
+
line = course.title
|
45
43
|
self.items_info <<= [(course.author ? "(by #{course.author})" : '')]
|
46
44
|
line
|
47
45
|
end
|
48
46
|
end
|
49
47
|
end
|
50
|
-
|
51
48
|
end
|
52
49
|
end
|
@@ -1,37 +1,37 @@
|
|
1
|
+
require_relative 'subscriber'
|
2
|
+
|
1
3
|
module Daigaku
|
2
4
|
module Views
|
3
|
-
|
5
|
+
# Subscription: `first.subscribe(second)` means
|
6
|
+
# first subscribes second on the first's broadcast.
|
7
|
+
# second has to have method that is broadcasted.
|
4
8
|
class MainMenu
|
5
9
|
include Views
|
6
10
|
|
7
|
-
|
8
|
-
courses_menu = Views::CoursesMenu.new
|
9
|
-
chapters_menu = Views::ChaptersMenu.new
|
10
|
-
units_menu = Views::UnitsMenu.new
|
11
|
-
task_view = Views::TaskView.new
|
11
|
+
attr_reader :courses_menu, :chapters_menu, :units_menu, :task_view
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
def initialize
|
14
|
+
@courses_menu = Views::CoursesMenu.new
|
15
|
+
@chapters_menu = Views::ChaptersMenu.new
|
16
|
+
@units_menu = Views::UnitsMenu.new
|
17
|
+
@task_view = Views::TaskView.new
|
16
18
|
|
17
|
-
|
18
|
-
courses_menu.
|
19
|
-
|
20
|
-
units_menu.subscribe(task_view, on: :enter)
|
19
|
+
subscribe_events
|
20
|
+
courses_menu.enter
|
21
|
+
end
|
21
22
|
|
22
|
-
|
23
|
-
chapters_menu.subscribe(courses_menu, on: :reenter)
|
24
|
-
units_menu.subscribe(chapters_menu, on: :reenter)
|
25
|
-
task_view.subscribe(units_menu, on: :reenter)
|
23
|
+
private
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
def subscribe_events
|
26
|
+
subscriber = Subscriber.new(
|
27
|
+
courses_menu: courses_menu,
|
28
|
+
chapters_menu: chapters_menu,
|
29
|
+
units_menu: units_menu,
|
30
|
+
task_view: task_view
|
31
|
+
)
|
31
32
|
|
32
|
-
|
33
|
+
subscriber.subscribe_events!
|
33
34
|
end
|
34
35
|
end
|
35
|
-
|
36
36
|
end
|
37
37
|
end
|
data/lib/daigaku/views/menu.rb
CHANGED
@@ -2,17 +2,18 @@ require 'wisper'
|
|
2
2
|
|
3
3
|
module Daigaku
|
4
4
|
module Views
|
5
|
-
|
6
5
|
class Menu
|
7
6
|
include Views
|
8
7
|
include Wisper::Publisher
|
9
8
|
|
10
9
|
TOP_BAR_TEXT = [
|
11
|
-
'Use *
|
12
|
-
'Enter menu with *
|
13
|
-
'Go back with *
|
14
|
-
'Exit with *
|
15
|
-
].join(' | ')
|
10
|
+
'Use * 🠕 * and * 🠗 * for menu navigation',
|
11
|
+
'Enter menu with * ⏎ *',
|
12
|
+
'Go back with * ⟵ *',
|
13
|
+
'Exit with *Esc*'
|
14
|
+
].join(' | ').freeze
|
15
|
+
|
16
|
+
attr_writer :items_info
|
16
17
|
|
17
18
|
def initialize
|
18
19
|
@position = 0
|
@@ -46,44 +47,39 @@ module Daigaku
|
|
46
47
|
def draw(window, active_index = 0)
|
47
48
|
window.attrset(A_NORMAL)
|
48
49
|
window.setpos(0, 1)
|
49
|
-
window.print_markdown
|
50
|
+
window.print_markdown(header_text)
|
50
51
|
|
51
52
|
items.each_with_index do |item, index|
|
52
53
|
window.setpos(index + 2, 1)
|
53
54
|
window.print_indicator(models[index])
|
54
55
|
window.attrset(index == active_index ? A_STANDOUT : A_NORMAL)
|
55
|
-
window.write " #{item
|
56
|
+
window.write " #{item} "
|
56
57
|
window.attrset(A_NORMAL)
|
57
|
-
window.write " #{items_info[index].
|
58
|
+
window.write " #{items_info[index] && items_info[index].join(' ')}"
|
58
59
|
end
|
59
60
|
|
60
61
|
window.refresh
|
61
62
|
end
|
62
63
|
|
63
64
|
def interact_with(window)
|
64
|
-
raise
|
65
|
+
raise 'Please implement the method #interact_with!'
|
65
66
|
end
|
66
67
|
|
67
68
|
def models
|
68
|
-
raise
|
69
|
+
raise 'Please implement the method #models!'
|
69
70
|
end
|
70
71
|
|
71
72
|
def items
|
72
|
-
raise
|
73
|
+
raise 'Please implement the method #items!'
|
73
74
|
end
|
74
75
|
|
75
76
|
def header_text
|
76
|
-
raise
|
77
|
+
raise 'Please implement the method #header_text!'
|
77
78
|
end
|
78
79
|
|
79
80
|
def items_info
|
80
81
|
@items_info || []
|
81
82
|
end
|
82
|
-
|
83
|
-
def items_info=(items_info)
|
84
|
-
@items_info = items_info
|
85
|
-
end
|
86
83
|
end
|
87
|
-
|
88
84
|
end
|
89
85
|
end
|
data/lib/daigaku/views/splash.rb
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
module Daigaku
|
2
2
|
module Views
|
3
|
-
|
4
3
|
class Splash
|
5
4
|
include Views
|
6
5
|
|
7
6
|
def initialize
|
8
|
-
title
|
9
|
-
subtitle =
|
10
|
-
|
11
|
-
panel = default_window
|
7
|
+
title = 'DAIGAKU'
|
8
|
+
subtitle = 'Learning the Ruby programming language dead easy.'
|
9
|
+
panel = default_window
|
12
10
|
|
13
11
|
lines.times do |line|
|
14
12
|
panel.setpos(line, 0)
|
@@ -43,15 +41,15 @@ module Daigaku
|
|
43
41
|
|
44
42
|
def ruby_ascii_art
|
45
43
|
[
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
44
|
+
' ___________ ',
|
45
|
+
' /.\\ /.\\ /.\\ ',
|
46
|
+
'/___\\/___\\/___\\',
|
47
|
+
' \\ \\ . / . / ',
|
48
|
+
' \\ \\ ./ ./ ',
|
49
|
+
' \\\\ / / ',
|
50
|
+
' \\./ '
|
53
51
|
]
|
54
52
|
end
|
55
53
|
end
|
56
54
|
end
|
57
|
-
end
|
55
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Daigaku
|
2
|
+
module Views
|
3
|
+
class Subscriber
|
4
|
+
attr_reader :courses_menu, :chapters_menu, :units_menu, :task_view
|
5
|
+
|
6
|
+
def initialize(courses_menu:, chapters_menu:, units_menu:, task_view:)
|
7
|
+
@courses_menu = courses_menu
|
8
|
+
@chapters_menu = chapters_menu
|
9
|
+
@units_menu = units_menu
|
10
|
+
@task_view = task_view
|
11
|
+
end
|
12
|
+
|
13
|
+
def subscribe_events!
|
14
|
+
subscribe_top_down_navigation
|
15
|
+
subscribe_bottom_up_navigation
|
16
|
+
subscribe_menu_position_reset
|
17
|
+
end
|
18
|
+
|
19
|
+
def subscribe_top_down_navigation
|
20
|
+
courses_menu.subscribe(chapters_menu, on: :enter)
|
21
|
+
chapters_menu.subscribe(units_menu, on: :enter)
|
22
|
+
units_menu.subscribe(task_view, on: :enter)
|
23
|
+
end
|
24
|
+
|
25
|
+
def subscribe_bottom_up_navigation
|
26
|
+
chapters_menu.subscribe(courses_menu, on: :reenter)
|
27
|
+
units_menu.subscribe(chapters_menu, on: :reenter)
|
28
|
+
task_view.subscribe(units_menu, on: :reenter)
|
29
|
+
end
|
30
|
+
|
31
|
+
def subscribe_menu_position_reset
|
32
|
+
courses_menu.subscribe(chapters_menu, on: :reset_menu_position)
|
33
|
+
courses_menu.subscribe(units_menu, on: :reset_menu_position)
|
34
|
+
chapters_menu.subscribe(units_menu, on: :reset_menu_position)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,41 +1,41 @@
|
|
1
|
+
require 'wisper'
|
2
|
+
require 'os'
|
3
|
+
|
1
4
|
module Daigaku
|
2
5
|
module Views
|
3
|
-
require 'wisper'
|
4
|
-
require 'os'
|
5
|
-
|
6
6
|
class TaskView
|
7
7
|
include Views
|
8
8
|
include Wisper::Publisher
|
9
9
|
|
10
10
|
TOP_BAR_TEXT = [
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
'Scroll with * 🠕 * and * 🠗 *',
|
12
|
+
'Open solution file with *o*',
|
13
|
+
'Verify solution with *v*',
|
14
|
+
'Clear validation with *c*',
|
15
|
+
'Exit with *Esc*'
|
16
|
+
].join(' | ').freeze
|
17
17
|
|
18
18
|
def initialize
|
19
19
|
@lines = []
|
20
|
-
@top
|
20
|
+
@top = nil
|
21
21
|
end
|
22
22
|
|
23
23
|
def enter(course, chapter, unit)
|
24
|
-
@course
|
24
|
+
@course = course
|
25
25
|
@chapter = chapter
|
26
|
-
@unit
|
26
|
+
@unit = unit
|
27
27
|
|
28
28
|
@test_result_lines = nil
|
29
|
-
@lines
|
30
|
-
@top_bar_height
|
31
|
-
@head_height
|
29
|
+
@lines = @unit.task.markdown.lines
|
30
|
+
@top_bar_height = 4
|
31
|
+
@head_height = 2
|
32
32
|
|
33
33
|
initialize_window(@lines.count + @top_bar_height + @head_height)
|
34
34
|
end
|
35
35
|
|
36
36
|
private
|
37
37
|
|
38
|
-
def
|
38
|
+
def print_head(window)
|
39
39
|
window.setpos(0, 1)
|
40
40
|
window.clear_line
|
41
41
|
|
@@ -55,7 +55,7 @@ module Daigaku
|
|
55
55
|
def draw(window)
|
56
56
|
@top = 0
|
57
57
|
window.attrset(A_NORMAL)
|
58
|
-
|
58
|
+
print_head(window)
|
59
59
|
|
60
60
|
@lines.each_with_index do |line, index|
|
61
61
|
window.setpos(index + 2, 1)
|
@@ -67,24 +67,23 @@ module Daigaku
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def scroll_up(window)
|
70
|
-
|
71
|
-
window.scrl(-1)
|
72
|
-
set_head(window)
|
70
|
+
return unless @top > 0
|
73
71
|
|
74
|
-
|
75
|
-
|
72
|
+
window.scrl(-1)
|
73
|
+
print_head(window)
|
76
74
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
75
|
+
@top -= 1
|
76
|
+
line = @lines[@top]
|
77
|
+
|
78
|
+
return unless line
|
79
|
+
window.setpos(2, 1)
|
80
|
+
print_line(window, line, @top)
|
82
81
|
end
|
83
82
|
|
84
83
|
def scroll_down(window)
|
85
84
|
if @top + Curses.lines <= @lines.count + @top_bar_height + @head_height
|
86
85
|
window.scrl(1)
|
87
|
-
|
86
|
+
print_head(window)
|
88
87
|
|
89
88
|
@top += 1
|
90
89
|
line = @lines[@top + window.maxy - 1]
|
@@ -125,47 +124,47 @@ module Daigaku
|
|
125
124
|
scrollable = true
|
126
125
|
|
127
126
|
case char
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
end
|
148
|
-
end
|
149
|
-
when Curses::KEY_PPAGE
|
150
|
-
0.upto(window.maxy - 2) do |n|
|
151
|
-
scrolled = scroll_up(window)
|
152
|
-
|
153
|
-
unless scrolled
|
154
|
-
scrollable = false if n == 0
|
155
|
-
break
|
156
|
-
end
|
157
|
-
end
|
158
|
-
when Curses::KEY_LEFT, Curses::KEY_CTRL_T
|
159
|
-
while scroll_up(window)
|
127
|
+
when 'v' # verify
|
128
|
+
print_test_results
|
129
|
+
return
|
130
|
+
when 'c' # clear
|
131
|
+
reset_screen
|
132
|
+
return
|
133
|
+
when 'o' # open solution file
|
134
|
+
open_editor(@unit.solution.path)
|
135
|
+
when Curses::KEY_DOWN, Curses::KEY_CTRL_N
|
136
|
+
scrollable = scroll_down(window)
|
137
|
+
when Curses::KEY_UP, Curses::KEY_CTRL_P
|
138
|
+
scrollable = scroll_up(window)
|
139
|
+
when Curses::KEY_NPAGE, '?\s' # white space
|
140
|
+
0.upto(window.maxy - 2) do |n|
|
141
|
+
scrolled = scroll_down(window)
|
142
|
+
|
143
|
+
unless scrolled
|
144
|
+
scrollable = false if n == 0
|
145
|
+
break
|
160
146
|
end
|
161
|
-
|
162
|
-
|
147
|
+
end
|
148
|
+
when Curses::KEY_PPAGE
|
149
|
+
0.upto(window.maxy - 2) do |n|
|
150
|
+
scrolled = scroll_up(window)
|
151
|
+
|
152
|
+
unless scrolled
|
153
|
+
scrollable = false if n == 0
|
154
|
+
break
|
163
155
|
end
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
156
|
+
end
|
157
|
+
when Curses::KEY_LEFT, Curses::KEY_CTRL_T
|
158
|
+
while scroll_up(window)
|
159
|
+
end
|
160
|
+
when Curses::KEY_RIGHT, Curses::KEY_CTRL_B
|
161
|
+
while scroll_down(window)
|
162
|
+
end
|
163
|
+
when Curses::KEY_BACKSPACE
|
164
|
+
broadcast(:reenter, @course, @chapter, @unit)
|
165
|
+
return
|
166
|
+
when 27 # ESC
|
167
|
+
exit
|
169
168
|
end
|
170
169
|
|
171
170
|
Curses.beep unless scrollable
|
@@ -184,16 +183,16 @@ module Daigaku
|
|
184
183
|
end
|
185
184
|
end
|
186
185
|
|
187
|
-
def print_test_results
|
188
|
-
result
|
189
|
-
@test_result_lines = result
|
186
|
+
def print_test_results
|
187
|
+
result = @unit.solution.verify!
|
188
|
+
@test_result_lines = test_result_lines(result)
|
190
189
|
|
191
190
|
if result.passed?
|
192
191
|
code_lines = @unit.reference_solution.code_lines
|
193
192
|
|
194
193
|
unless code_lines.empty?
|
195
194
|
code_lines.map! { |line| " #{line}" }
|
196
|
-
code_lines.unshift('',
|
195
|
+
code_lines.unshift('', 'Reference code:', '')
|
197
196
|
end
|
198
197
|
|
199
198
|
@test_result_lines += code_lines
|
@@ -202,21 +201,40 @@ module Daigaku
|
|
202
201
|
@lines = [''] + @test_result_lines + ['', ''] + @unit.task.markdown.lines
|
203
202
|
@examples = result.examples
|
204
203
|
|
205
|
-
@example_heights = @examples.
|
206
|
-
start = hash.values.reduce(0) { |sum,
|
204
|
+
@example_heights = @examples.each_with_object({}) do |example, hash|
|
205
|
+
start = hash.values.reduce(0) { |sum, results| sum + results.count }
|
207
206
|
range = (start..(start + example.message.split("\n").count) + 2)
|
208
207
|
hash[hash.keys.count] = range
|
209
|
-
hash
|
210
208
|
end
|
211
209
|
|
212
|
-
|
210
|
+
lines_count = @lines.count + @top_bar_height + @head_height
|
211
|
+
height = [lines_count, Curses.lines].max
|
212
|
+
|
213
213
|
initialize_window(height)
|
214
214
|
end
|
215
215
|
|
216
|
-
def
|
216
|
+
def test_result_lines(result)
|
217
|
+
lines = result.summary_lines
|
218
|
+
lines += code_error_lines(@unit.solution.code) unless result.passed?
|
219
|
+
lines
|
220
|
+
end
|
221
|
+
|
222
|
+
def code_error_lines(code)
|
223
|
+
begin
|
224
|
+
eval(code)
|
225
|
+
rescue StandardError, ScriptError => error
|
226
|
+
return error.inspect.gsub(/(\A.*#<|>.*$)/, '').lines.map(&:rstrip)
|
227
|
+
end
|
228
|
+
|
229
|
+
[]
|
230
|
+
end
|
231
|
+
|
232
|
+
def reset_screen
|
217
233
|
@test_result_lines = nil
|
218
|
-
@lines
|
219
|
-
|
234
|
+
@lines = @unit.task.markdown.lines
|
235
|
+
lines_count = @lines.count + @top_bar_height + @head_height
|
236
|
+
height = [lines_count, Curses.lines].max
|
237
|
+
|
220
238
|
initialize_window(height)
|
221
239
|
end
|
222
240
|
|
@@ -228,9 +246,8 @@ module Daigaku
|
|
228
246
|
end
|
229
247
|
|
230
248
|
def example_index(heights, index)
|
231
|
-
heights.values.index { |range| range.include?(index) }
|
249
|
+
heights.values.index { |range| range.include?(index) }.to_i
|
232
250
|
end
|
233
251
|
end
|
234
|
-
|
235
252
|
end
|
236
253
|
end
|