daigaku 0.0.2 → 0.1.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 +4 -4
- data/.travis.yml +6 -0
- data/README.md +25 -3
- data/Rakefile +3 -0
- data/daigaku.gemspec +3 -2
- data/lib/daigaku/configuration.rb +7 -4
- data/lib/daigaku/congratulator.rb +13 -0
- data/lib/daigaku/course.rb +5 -0
- data/lib/daigaku/generator.rb +13 -6
- data/lib/daigaku/github_client.rb +30 -0
- data/lib/daigaku/reference_solution.rb +10 -2
- data/lib/daigaku/solution.rb +19 -8
- data/lib/daigaku/storeable.rb +32 -0
- data/lib/daigaku/terminal/courses.rb +103 -11
- data/lib/daigaku/terminal/output.rb +6 -0
- data/lib/daigaku/terminal/texts/congratulations.txt +12 -0
- data/lib/daigaku/terminal.rb +2 -1
- data/lib/daigaku/test_result.rb +5 -3
- data/lib/daigaku/version.rb +1 -1
- data/lib/daigaku/views/chapters_menu.rb +19 -50
- data/lib/daigaku/views/courses_menu.rb +14 -49
- data/lib/daigaku/views/main_menu.rb +6 -6
- data/lib/daigaku/views/menu.rb +89 -0
- data/lib/daigaku/views/task_view.rb +29 -11
- data/lib/daigaku/views/top_bar.rb +9 -17
- data/lib/daigaku/views/units_menu.rb +21 -52
- data/lib/daigaku/views.rb +4 -12
- data/lib/daigaku/window.rb +46 -3
- data/lib/daigaku.rb +1 -4
- data/spec/daigaku/configuration_spec.rb +11 -11
- data/spec/daigaku/congratulator_spec.rb +24 -0
- data/spec/daigaku/course_spec.rb +18 -0
- data/spec/daigaku/generator_spec.rb +4 -4
- data/spec/daigaku/github_client_spec.rb +53 -0
- data/spec/daigaku/reference_solution_spec.rb +20 -2
- data/spec/daigaku/solution_spec.rb +13 -6
- data/spec/daigaku/storeable_spec.rb +35 -0
- data/spec/daigaku/terminal/courses_spec.rb +215 -5
- data/spec/daigaku/terminal/output_spec.rb +31 -3
- data/spec/daigaku/terminal_spec.rb +12 -2
- data/spec/daigaku/test_result_spec.rb +12 -2
- data/spec/daigaku/views/chapters_menu_spec.rb +1 -3
- data/spec/daigaku/views/courses_menu_spec.rb +1 -3
- data/spec/daigaku/views/menu_spec.rb +19 -0
- data/spec/daigaku/views/task_view_spec.rb +1 -1
- data/spec/daigaku/views/units_menu_spec.rb +1 -3
- data/spec/daigaku/views_spec.rb +0 -2
- data/spec/daigaku_spec.rb +0 -6
- data/spec/support/macros/content_helpers.rb +1 -1
- data/spec/support/macros/mock_helpers.rb +6 -1
- data/spec/support/macros/path_helpers.rb +12 -6
- data/spec/support/macros/resource_helpers.rb +3 -1
- metadata +33 -8
- data/lib/daigaku/database.rb +0 -64
- data/spec/daigaku/database_spec.rb +0 -79
@@ -1,53 +1,24 @@
|
|
1
|
+
require 'daigaku/views/menu'
|
2
|
+
|
1
3
|
module Daigaku
|
2
4
|
module Views
|
3
|
-
require 'wisper'
|
4
|
-
|
5
|
-
class ChaptersMenu
|
6
|
-
include Views
|
7
|
-
include Wisper::Publisher
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
@position = 0
|
11
|
-
end
|
12
|
-
|
13
|
-
def enter_chapters_menu(course)
|
14
|
-
@window = default_window
|
15
|
-
@course = course
|
16
|
-
|
17
|
-
main_panel(@window) do |window|
|
18
|
-
show sub_window_below_top_bar(window)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def reenter_chapters_menu(course, chapter)
|
23
|
-
@course = course
|
24
|
-
@chapter = chapter
|
25
5
|
|
26
|
-
|
27
|
-
enter_chapters_menu(@course)
|
28
|
-
end
|
6
|
+
class ChaptersMenu < Menu
|
29
7
|
|
30
8
|
private
|
31
9
|
|
32
|
-
def
|
33
|
-
|
34
|
-
interact_with(window)
|
10
|
+
def before_enter(*args)
|
11
|
+
@course = args[0]
|
35
12
|
end
|
36
13
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
menu_items.each_with_index do |item, index|
|
44
|
-
window.setpos(index + 2, 1)
|
45
|
-
window.print_indicator(chapters[index])
|
46
|
-
window.attrset(index == active_index ? A_STANDOUT : A_NORMAL)
|
47
|
-
window.write " #{item.to_s} "
|
48
|
-
end
|
14
|
+
def before_reenter(*args)
|
15
|
+
@course = args[0]
|
16
|
+
@chapter = args[1]
|
17
|
+
@position = @course.chapters.find_index(@chapter)
|
18
|
+
end
|
49
19
|
|
50
|
-
|
20
|
+
def header_text
|
21
|
+
"*#{@course.title}* - available chapters:"
|
51
22
|
end
|
52
23
|
|
53
24
|
def interact_with(window)
|
@@ -60,29 +31,27 @@ module Daigaku
|
|
60
31
|
@position += 1
|
61
32
|
broadcast(:reset_menu_position)
|
62
33
|
when 10 # Enter
|
63
|
-
broadcast(:
|
34
|
+
broadcast(:enter, @course, models[@position])
|
64
35
|
return
|
65
36
|
when 263 # Backspace
|
66
|
-
broadcast(:
|
37
|
+
broadcast(:reenter, @course)
|
67
38
|
return
|
68
39
|
when 27 # ESC
|
69
40
|
exit
|
70
41
|
end
|
71
42
|
|
72
|
-
@position =
|
73
|
-
@position = 0 if @position >=
|
43
|
+
@position = items.length - 1 if @position < 0
|
44
|
+
@position = 0 if @position >= items.length
|
74
45
|
draw(window, @position)
|
75
46
|
end
|
76
47
|
end
|
77
48
|
|
78
|
-
def
|
49
|
+
def models
|
79
50
|
@course.chapters
|
80
51
|
end
|
81
52
|
|
82
|
-
def
|
83
|
-
|
84
|
-
chapter.title
|
85
|
-
end
|
53
|
+
def items
|
54
|
+
models.map(&:title)
|
86
55
|
end
|
87
56
|
|
88
57
|
end
|
@@ -1,48 +1,14 @@
|
|
1
|
+
require 'daigaku/views/menu'
|
2
|
+
|
1
3
|
module Daigaku
|
2
4
|
module Views
|
3
|
-
require 'wisper'
|
4
|
-
|
5
|
-
class CoursesMenu
|
6
|
-
include Views
|
7
|
-
include Wisper::Publisher
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
@position = 0
|
11
|
-
end
|
12
|
-
|
13
|
-
def enter
|
14
|
-
@window = default_window
|
15
|
-
|
16
|
-
main_panel(@window) do |window|
|
17
|
-
show sub_window_below_top_bar(window)
|
18
|
-
end
|
19
|
-
end
|
20
5
|
|
21
|
-
|
22
|
-
@current_course = course
|
23
|
-
enter
|
24
|
-
end
|
6
|
+
class CoursesMenu < Menu
|
25
7
|
|
26
8
|
private
|
27
9
|
|
28
|
-
def
|
29
|
-
|
30
|
-
interact_with(window)
|
31
|
-
end
|
32
|
-
|
33
|
-
def draw(window, active_index = 0)
|
34
|
-
window.attrset(A_NORMAL)
|
35
|
-
window.setpos(0, 1)
|
36
|
-
window.write 'Available daigaku courses:'
|
37
|
-
|
38
|
-
course_entries.each_with_index do |item, index|
|
39
|
-
window.setpos(index + 2, 1)
|
40
|
-
window.print_indicator(courses[index])
|
41
|
-
window.attrset(index == active_index ? A_STANDOUT : A_NORMAL)
|
42
|
-
window.write " #{item.to_s} "
|
43
|
-
end
|
44
|
-
|
45
|
-
window.refresh
|
10
|
+
def header_text
|
11
|
+
'Available daigaku courses:'
|
46
12
|
end
|
47
13
|
|
48
14
|
def interact_with(window)
|
@@ -55,29 +21,28 @@ module Daigaku
|
|
55
21
|
@position += 1
|
56
22
|
broadcast(:reset_menu_position)
|
57
23
|
when 10 # Enter
|
58
|
-
broadcast(:
|
24
|
+
broadcast(:enter, models[@position])
|
59
25
|
return
|
60
26
|
when 27 # ESC
|
61
27
|
exit
|
62
28
|
end
|
63
29
|
|
64
|
-
|
65
|
-
@position =
|
66
|
-
@position = 0 if @position >= entries.length
|
30
|
+
@position = items.length - 1 if @position < 0
|
31
|
+
@position = 0 if @position >= items.length
|
67
32
|
draw(window, @position)
|
68
33
|
end
|
69
34
|
end
|
70
35
|
|
71
|
-
def
|
72
|
-
|
36
|
+
def models
|
37
|
+
Loading::Courses.load(Daigaku.config.courses_path)
|
73
38
|
end
|
74
39
|
|
75
|
-
def
|
76
|
-
non_empty_courses =
|
40
|
+
def items
|
41
|
+
non_empty_courses = models.select { |course| !course.chapters.empty? }
|
77
42
|
|
78
|
-
|
43
|
+
non_empty_courses.map do |course|
|
79
44
|
line = "#{course.title}"
|
80
|
-
|
45
|
+
self.items_info <<= [(course.author ? "(by #{course.author})" : '')]
|
81
46
|
line
|
82
47
|
end
|
83
48
|
end
|
@@ -15,14 +15,14 @@ module Daigaku
|
|
15
15
|
# second has to have method that is broadcasted.
|
16
16
|
|
17
17
|
# top down navigation
|
18
|
-
courses_menu.subscribe(chapters_menu, on: :
|
19
|
-
chapters_menu.subscribe(units_menu, on: :
|
20
|
-
units_menu.subscribe(task_view, on: :
|
18
|
+
courses_menu.subscribe(chapters_menu, on: :enter)
|
19
|
+
chapters_menu.subscribe(units_menu, on: :enter)
|
20
|
+
units_menu.subscribe(task_view, on: :enter)
|
21
21
|
|
22
22
|
# bottom up navigation
|
23
|
-
chapters_menu.subscribe(courses_menu, on: :
|
24
|
-
units_menu.subscribe(chapters_menu, on: :
|
25
|
-
task_view.subscribe(units_menu, on: :
|
23
|
+
chapters_menu.subscribe(courses_menu, on: :reenter)
|
24
|
+
units_menu.subscribe(chapters_menu, on: :reenter)
|
25
|
+
task_view.subscribe(units_menu, on: :reenter)
|
26
26
|
|
27
27
|
# position reset
|
28
28
|
courses_menu.subscribe(chapters_menu, on: :reset_menu_position)
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'wisper'
|
2
|
+
|
3
|
+
module Daigaku
|
4
|
+
module Views
|
5
|
+
|
6
|
+
class Menu
|
7
|
+
include Views
|
8
|
+
include Wisper::Publisher
|
9
|
+
|
10
|
+
TOP_BAR_TEXT = [
|
11
|
+
'Use *UP KEY* and *DOWN KEY* for menu navigation',
|
12
|
+
'Enter menu with *RETURN*',
|
13
|
+
'Go back with *BACKSPACE*',
|
14
|
+
'Exit with *ESC*'
|
15
|
+
].join(' | ')
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@position = 0
|
19
|
+
end
|
20
|
+
|
21
|
+
def enter(*args)
|
22
|
+
if self.class.private_method_defined?(:before_enter)
|
23
|
+
before_enter(*args)
|
24
|
+
end
|
25
|
+
|
26
|
+
@window = default_window
|
27
|
+
top_bar = TopBar.new(@window, TOP_BAR_TEXT)
|
28
|
+
show sub_window_below_top_bar(@window, top_bar)
|
29
|
+
end
|
30
|
+
|
31
|
+
def reenter(*args)
|
32
|
+
if self.class.private_method_defined?(:before_reenter)
|
33
|
+
before_reenter(*args)
|
34
|
+
end
|
35
|
+
|
36
|
+
enter(*args)
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def show(window)
|
42
|
+
draw(window, @position)
|
43
|
+
interact_with(window)
|
44
|
+
end
|
45
|
+
|
46
|
+
def draw(window, active_index = 0)
|
47
|
+
window.attrset(A_NORMAL)
|
48
|
+
window.setpos(0, 1)
|
49
|
+
window.print_markdown header_text
|
50
|
+
|
51
|
+
items.each_with_index do |item, index|
|
52
|
+
window.setpos(index + 2, 1)
|
53
|
+
window.print_indicator(models[index])
|
54
|
+
window.attrset(index == active_index ? A_STANDOUT : A_NORMAL)
|
55
|
+
window.write " #{item.to_s} "
|
56
|
+
window.attrset(A_NORMAL)
|
57
|
+
window.write " #{items_info[index].try(:join, ' ')}"
|
58
|
+
end
|
59
|
+
|
60
|
+
window.refresh
|
61
|
+
end
|
62
|
+
|
63
|
+
def interact_with(window)
|
64
|
+
raise "Please implement the method #interact_with!"
|
65
|
+
end
|
66
|
+
|
67
|
+
def models
|
68
|
+
raise "Please implement the method #models!"
|
69
|
+
end
|
70
|
+
|
71
|
+
def items
|
72
|
+
raise "Please implement the method #items!"
|
73
|
+
end
|
74
|
+
|
75
|
+
def header_text
|
76
|
+
raise "Please implement the method #header_text!"
|
77
|
+
end
|
78
|
+
|
79
|
+
def items_info
|
80
|
+
@items_info || []
|
81
|
+
end
|
82
|
+
|
83
|
+
def items_info=(items_info)
|
84
|
+
@items_info = items_info
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
@@ -7,12 +7,20 @@ module Daigaku
|
|
7
7
|
include Views
|
8
8
|
include Wisper::Publisher
|
9
9
|
|
10
|
+
TOP_BAR_TEXT = [
|
11
|
+
'Scroll with *UP KEY* and *DOWN KEY*',
|
12
|
+
'Verify solution with *v*',
|
13
|
+
'Open solution file with *o*',
|
14
|
+
'Clear validation with *c*',
|
15
|
+
'Exit with *ESC*'
|
16
|
+
].join(' | ')
|
17
|
+
|
10
18
|
def initialize
|
11
19
|
@lines = []
|
12
20
|
@top = nil
|
13
21
|
end
|
14
22
|
|
15
|
-
def
|
23
|
+
def enter(course, chapter, unit)
|
16
24
|
@course = course
|
17
25
|
@chapter = chapter
|
18
26
|
@unit = unit
|
@@ -30,12 +38,9 @@ module Daigaku
|
|
30
38
|
def set_head(window)
|
31
39
|
window.setpos(0, 1)
|
32
40
|
window.clear_line
|
33
|
-
|
34
|
-
|
35
|
-
window.
|
36
|
-
window.write ' > '
|
37
|
-
window.emphasize @unit.title
|
38
|
-
window.write ':'
|
41
|
+
|
42
|
+
text = "*#{@course.title}* > *#{@chapter.title}* > *#{@unit.title}*:"
|
43
|
+
window.print_markdown(text)
|
39
44
|
|
40
45
|
window.setpos(1, 1)
|
41
46
|
window.clear_line
|
@@ -120,7 +125,7 @@ module Daigaku
|
|
120
125
|
scrollable = true
|
121
126
|
|
122
127
|
case char
|
123
|
-
when 'v' #
|
128
|
+
when 'v' # verify
|
124
129
|
print_test_results(window)
|
125
130
|
return
|
126
131
|
when 'c' # clear
|
@@ -157,7 +162,7 @@ module Daigaku
|
|
157
162
|
while scroll_down(window)
|
158
163
|
end
|
159
164
|
when Curses::KEY_BACKSPACE
|
160
|
-
broadcast(:
|
165
|
+
broadcast(:reenter, @course, @chapter, @unit)
|
161
166
|
return
|
162
167
|
when 27 # ESC
|
163
168
|
exit
|
@@ -181,8 +186,19 @@ module Daigaku
|
|
181
186
|
|
182
187
|
def print_test_results(window)
|
183
188
|
result = @unit.solution.verify!
|
189
|
+
@test_result_lines = result.summary_lines
|
190
|
+
|
191
|
+
if result.passed?
|
192
|
+
code_lines = @unit.reference_solution.code_lines
|
193
|
+
|
194
|
+
unless code_lines.empty?
|
195
|
+
code_lines.map! { |line| " #{line}" }
|
196
|
+
code_lines.unshift('', "Reference code:", '')
|
197
|
+
end
|
198
|
+
|
199
|
+
@test_result_lines += code_lines
|
200
|
+
end
|
184
201
|
|
185
|
-
@test_result_lines = result.summary.strip.split("\n")
|
186
202
|
@lines = [''] + @test_result_lines + ['', ''] + @unit.task.markdown.lines
|
187
203
|
@examples = result.examples
|
188
204
|
|
@@ -206,7 +222,9 @@ module Daigaku
|
|
206
222
|
|
207
223
|
def initialize_window(height)
|
208
224
|
@window = default_window(height)
|
209
|
-
|
225
|
+
|
226
|
+
top_bar = TopBar.new(@window, TOP_BAR_TEXT)
|
227
|
+
show sub_window_below_top_bar(@window, top_bar)
|
210
228
|
end
|
211
229
|
|
212
230
|
def example_index(heights, index)
|
@@ -4,12 +4,14 @@ module Daigaku
|
|
4
4
|
class TopBar
|
5
5
|
include Curses
|
6
6
|
|
7
|
+
HEIGHT = 4
|
8
|
+
|
7
9
|
attr_reader :height, :width, :panel
|
8
10
|
|
9
|
-
def initialize(window)
|
10
|
-
@height =
|
11
|
+
def initialize(window, text = '')
|
12
|
+
@height = HEIGHT
|
11
13
|
@width = window.maxx
|
12
|
-
@panel = create_panel(window, @width, @height)
|
14
|
+
@panel = create_panel(window, @width, @height, text)
|
13
15
|
end
|
14
16
|
|
15
17
|
def show
|
@@ -18,23 +20,13 @@ module Daigaku
|
|
18
20
|
|
19
21
|
private
|
20
22
|
|
21
|
-
def create_panel(window, width,
|
22
|
-
panel = window.subwin(
|
23
|
+
def create_panel(window, width, height, text)
|
24
|
+
panel = window.subwin(height, window.maxx, 0, 0)
|
23
25
|
|
24
26
|
panel.setpos(1, 1)
|
25
|
-
panel.
|
26
|
-
panel.emphasize 'UP KEY'
|
27
|
-
panel.write ' and '
|
28
|
-
panel.emphasize 'DOWN KEY'
|
29
|
-
panel.write ' for menu navigation'
|
30
|
-
panel.write ' | Enter menu with '
|
31
|
-
panel.emphasize 'RETURN'
|
32
|
-
panel.write ' | Go back with '
|
33
|
-
panel.emphasize 'BACKSPACE'
|
34
|
-
panel.write ' | Exit with '
|
35
|
-
panel.emphasize 'ESC'
|
27
|
+
panel.print_markdown(text)
|
36
28
|
panel.setpos(2, 1)
|
37
|
-
panel.
|
29
|
+
panel.clear_line(text: '_')
|
38
30
|
|
39
31
|
panel
|
40
32
|
end
|
@@ -1,56 +1,27 @@
|
|
1
|
+
require 'daigaku/views/menu'
|
2
|
+
|
1
3
|
module Daigaku
|
2
4
|
module Views
|
3
|
-
require 'wisper'
|
4
|
-
|
5
|
-
class UnitsMenu
|
6
|
-
include Views
|
7
|
-
include Wisper::Publisher
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
@position = 0
|
11
|
-
end
|
12
5
|
|
13
|
-
|
14
|
-
@window = default_window
|
15
|
-
@course = course
|
16
|
-
@chapter = chapter
|
17
|
-
|
18
|
-
main_panel(@window) do |window|
|
19
|
-
show sub_window_below_top_bar(window)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def reenter_units_menu(course, chapter, unit)
|
24
|
-
@course = course
|
25
|
-
@chapter = chapter
|
26
|
-
|
27
|
-
@position = chapter.units.find_index(unit)
|
28
|
-
enter_units_menu(@course, @chapter)
|
29
|
-
end
|
6
|
+
class UnitsMenu < Menu
|
30
7
|
|
31
8
|
private
|
32
9
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
10
|
+
def before_enter(*args)
|
11
|
+
@course = args[0]
|
12
|
+
@chapter = args[1]
|
36
13
|
end
|
37
14
|
|
38
|
-
def
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
window.write ' > '
|
43
|
-
window.emphasize @chapter.title
|
44
|
-
window.write ' > - available units:'
|
15
|
+
def before_reenter(*args)
|
16
|
+
@course = args[0]
|
17
|
+
@chapter = args[1]
|
18
|
+
@unit = args[2]
|
45
19
|
|
46
|
-
|
47
|
-
|
48
|
-
window.print_indicator(units[index])
|
49
|
-
window.attrset(index == active_index ? A_STANDOUT : A_NORMAL)
|
50
|
-
window.write " #{item.to_s} "
|
51
|
-
end
|
20
|
+
@position = @chapter.units.find_index(@unit)
|
21
|
+
end
|
52
22
|
|
53
|
-
|
23
|
+
def header_text
|
24
|
+
"*#{@course.title}* > *#{@chapter.title}* - available units:"
|
54
25
|
end
|
55
26
|
|
56
27
|
def interact_with(window)
|
@@ -61,29 +32,27 @@ module Daigaku
|
|
61
32
|
when KEY_DOWN
|
62
33
|
@position += 1
|
63
34
|
when 10 # Enter
|
64
|
-
broadcast(:
|
35
|
+
broadcast(:enter, @course, @chapter, models[@position])
|
65
36
|
return
|
66
37
|
when 263 # Backspace
|
67
|
-
broadcast(:
|
38
|
+
broadcast(:reenter, @course, @chapter)
|
68
39
|
return
|
69
40
|
when 27 # ESC
|
70
41
|
exit
|
71
42
|
end
|
72
43
|
|
73
|
-
@position =
|
74
|
-
@position = 0 if @position >=
|
44
|
+
@position = items.length - 1 if @position < 0
|
45
|
+
@position = 0 if @position >= items.length
|
75
46
|
draw(window, @position)
|
76
47
|
end
|
77
48
|
end
|
78
49
|
|
79
|
-
def
|
50
|
+
def models
|
80
51
|
@chapter.units
|
81
52
|
end
|
82
53
|
|
83
|
-
def
|
84
|
-
|
85
|
-
unit.title
|
86
|
-
end
|
54
|
+
def items
|
55
|
+
models.map(&:title)
|
87
56
|
end
|
88
57
|
|
89
58
|
end
|
data/lib/daigaku/views.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'curses'
|
2
2
|
require 'active_support/concern'
|
3
|
-
|
3
|
+
require 'daigaku/views/top_bar'
|
4
4
|
|
5
5
|
module Daigaku
|
6
6
|
module Views
|
@@ -38,17 +38,9 @@ module Daigaku
|
|
38
38
|
window
|
39
39
|
end
|
40
40
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
def main_panel(window)
|
46
|
-
top_bar(window).show
|
47
|
-
yield(window) if block_given?
|
48
|
-
end
|
49
|
-
|
50
|
-
def sub_window_below_top_bar(window)
|
51
|
-
top = top_bar(window).height
|
41
|
+
def sub_window_below_top_bar(window, top_bar)
|
42
|
+
top_bar.show
|
43
|
+
top = top_bar.height
|
52
44
|
sub_window = window.subwin(window.maxy - top, window.maxx, top, 0)
|
53
45
|
sub_window.keypad(true)
|
54
46
|
sub_window
|
data/lib/daigaku/window.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'curses'
|
2
|
+
require 'cgi'
|
2
3
|
|
3
4
|
module Daigaku
|
4
5
|
class Window < Curses::Window
|
@@ -72,7 +73,7 @@ module Daigaku
|
|
72
73
|
|
73
74
|
x = curx
|
74
75
|
setpos(cury, start)
|
75
|
-
write(' ' * (stop - 1), color, text_decoration)
|
76
|
+
write((options[:text] || ' ') * (stop - 1), color, text_decoration)
|
76
77
|
setpos(cury, x)
|
77
78
|
refresh
|
78
79
|
end
|
@@ -106,8 +107,10 @@ module Daigaku
|
|
106
107
|
h1 = /^\#{1}[^#]+/ # '# heading'
|
107
108
|
h2 = /^\#{2}[^#]+/ # '## sub heading'
|
108
109
|
bold = /(\*[^*]*\*)/ # '*text*'
|
109
|
-
line = /^-{3,}/
|
110
|
-
code = /(\`*\`)/
|
110
|
+
line = /^-{3,}/ # '---' vertical line
|
111
|
+
code = /(\`*\`)/ # '`code line`'
|
112
|
+
ruby_doc_core = /(\(ruby-doc core:.*\))/ # '(ruby-doc core: Kernel#print)'
|
113
|
+
ruby_doc_stdlib = /(\(ruby-doc stdlib:.*\))/ # '(ruby-doc stdlib: CSV#Row::<<)'
|
111
114
|
|
112
115
|
case text
|
113
116
|
when h1
|
@@ -149,6 +152,12 @@ module Daigaku
|
|
149
152
|
end
|
150
153
|
when line
|
151
154
|
write('-' * (Curses.cols - 2))
|
155
|
+
when ruby_doc_core
|
156
|
+
capture = text.match(/\(ruby-doc core:\s?(.*)\)/).captures.first
|
157
|
+
write text.gsub(ruby_doc_core, ruby_doc_core_link(capture))
|
158
|
+
when ruby_doc_stdlib
|
159
|
+
capture = text.match(/\(ruby-doc stdlib:\s?(.*)\)/).captures.first
|
160
|
+
write text.gsub(ruby_doc_stdlib, ruby_doc_stdlib_link(capture))
|
152
161
|
else
|
153
162
|
write(text)
|
154
163
|
end
|
@@ -165,5 +174,39 @@ module Daigaku
|
|
165
174
|
Curses.init_pair(COLOR_GREEN, GREEN, BACKGROUND)
|
166
175
|
Curses.init_pair(COLOR_YELLOW, YELLOW, BACKGROUND)
|
167
176
|
end
|
177
|
+
|
178
|
+
private
|
179
|
+
|
180
|
+
def ruby_doc_core_link(text)
|
181
|
+
base_url = "http://ruby-doc.org/core-#{RUBY_VERSION}"
|
182
|
+
class_part = ruby_doc_class_parts(text).join('/')
|
183
|
+
method = ruby_doc_method(text)
|
184
|
+
|
185
|
+
"#{base_url}/#{class_part}.html#{method}"
|
186
|
+
end
|
187
|
+
|
188
|
+
def ruby_doc_stdlib_link(text)
|
189
|
+
base_url = "http://ruby-doc.org/stdlib-#{RUBY_VERSION}"
|
190
|
+
class_parts = ruby_doc_class_parts(text)
|
191
|
+
libdoc_part = "libdoc/#{class_parts.first.downcase}/rdoc"
|
192
|
+
method = ruby_doc_method(text)
|
193
|
+
|
194
|
+
"#{base_url}/#{libdoc_part}/#{class_parts.join('/')}.html#{method}"
|
195
|
+
end
|
196
|
+
|
197
|
+
def ruby_doc_class_parts(text)
|
198
|
+
parts = text.split(/::|#/)
|
199
|
+
parts[0..(parts.count > 1 ? -2 : -1)]
|
200
|
+
end
|
201
|
+
|
202
|
+
def ruby_doc_method(text)
|
203
|
+
parts = text.split(/::|#/)
|
204
|
+
|
205
|
+
if parts.count > 1
|
206
|
+
method_type = text.match(/#/) ? 'i' : 'c'
|
207
|
+
method_name = CGI.escape(parts.last.strip).gsub('%', '-').gsub(/\A-/, '')
|
208
|
+
"#method-#{method_type}-#{method_name}"
|
209
|
+
end
|
210
|
+
end
|
168
211
|
end
|
169
212
|
end
|
data/lib/daigaku.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'quick_store'
|
1
2
|
require 'daigaku/window'
|
2
3
|
|
3
4
|
Dir[File.join("#{File.dirname(__FILE__)}/**/*.rb")].sort.each do |file|
|
@@ -19,9 +20,5 @@ module Daigaku
|
|
19
20
|
Views::Splash.new
|
20
21
|
Views::MainMenu.new
|
21
22
|
end
|
22
|
-
|
23
|
-
def database
|
24
|
-
Database.instance
|
25
|
-
end
|
26
23
|
end
|
27
24
|
end
|