belajar 0.1.1

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.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +4 -0
  5. data/Guardfile +5 -0
  6. data/README.md +5 -0
  7. data/Rakefile +5 -0
  8. data/belajar.gemspec +38 -0
  9. data/bin/belajar +12 -0
  10. data/lib/belajar.rb +24 -0
  11. data/lib/belajar/chapter.rb +23 -0
  12. data/lib/belajar/configuration.rb +89 -0
  13. data/lib/belajar/congratulator.rb +13 -0
  14. data/lib/belajar/course.rb +80 -0
  15. data/lib/belajar/exceptions.rb +19 -0
  16. data/lib/belajar/generator.rb +60 -0
  17. data/lib/belajar/github_client.rb +30 -0
  18. data/lib/belajar/loadable.rb +23 -0
  19. data/lib/belajar/loading/chapters.rb +9 -0
  20. data/lib/belajar/loading/courses.rb +9 -0
  21. data/lib/belajar/loading/units.rb +9 -0
  22. data/lib/belajar/reference_solution.rb +18 -0
  23. data/lib/belajar/solution.rb +53 -0
  24. data/lib/belajar/storeable.rb +32 -0
  25. data/lib/belajar/task.rb +10 -0
  26. data/lib/belajar/terminal.rb +12 -0
  27. data/lib/belajar/terminal/cli.rb +59 -0
  28. data/lib/belajar/terminal/courses.rb +179 -0
  29. data/lib/belajar/terminal/output.rb +78 -0
  30. data/lib/belajar/terminal/setup.rb +115 -0
  31. data/lib/belajar/terminal/solutions.rb +46 -0
  32. data/lib/belajar/terminal/texts/about.txt +19 -0
  33. data/lib/belajar/terminal/texts/congratulations.txt +12 -0
  34. data/lib/belajar/terminal/texts/courses_empty.txt +3 -0
  35. data/lib/belajar/terminal/texts/hint_course_download.txt +13 -0
  36. data/lib/belajar/terminal/texts/welcome.txt +12 -0
  37. data/lib/belajar/terminal/welcome.rb +98 -0
  38. data/lib/belajar/test.rb +46 -0
  39. data/lib/belajar/test_result.rb +86 -0
  40. data/lib/belajar/unit.rb +28 -0
  41. data/lib/belajar/version.rb +3 -0
  42. data/lib/belajar/views.rb +51 -0
  43. data/lib/belajar/views/chapters_menu.rb +60 -0
  44. data/lib/belajar/views/courses_menu.rb +52 -0
  45. data/lib/belajar/views/main_menu.rb +37 -0
  46. data/lib/belajar/views/menu.rb +89 -0
  47. data/lib/belajar/views/splash.rb +57 -0
  48. data/lib/belajar/views/task_view.rb +236 -0
  49. data/lib/belajar/views/top_bar.rb +40 -0
  50. data/lib/belajar/views/units_menu.rb +61 -0
  51. data/lib/belajar/window.rb +215 -0
  52. data/spec/belajar/chapter_spec.rb +76 -0
  53. data/spec/belajar/configuration_spec.rb +161 -0
  54. data/spec/belajar/congratulator_spec.rb +24 -0
  55. data/spec/belajar/course_spec.rb +201 -0
  56. data/spec/belajar/generator_spec.rb +82 -0
  57. data/spec/belajar/github_client_spec.rb +53 -0
  58. data/spec/belajar/loading/chapters_spec.rb +16 -0
  59. data/spec/belajar/loading/courses_spec.rb +16 -0
  60. data/spec/belajar/loading/units_spec.rb +21 -0
  61. data/spec/belajar/reference_solution_spec.rb +41 -0
  62. data/spec/belajar/solution_spec.rb +86 -0
  63. data/spec/belajar/storeable_spec.rb +35 -0
  64. data/spec/belajar/task_spec.rb +23 -0
  65. data/spec/belajar/terminal/cli_spec.rb +51 -0
  66. data/spec/belajar/terminal/courses_spec.rb +293 -0
  67. data/spec/belajar/terminal/output_spec.rb +151 -0
  68. data/spec/belajar/terminal/setup_spec.rb +10 -0
  69. data/spec/belajar/terminal/solutions_spec.rb +8 -0
  70. data/spec/belajar/terminal/welcome_spec.rb +12 -0
  71. data/spec/belajar/terminal_spec.rb +24 -0
  72. data/spec/belajar/test_example_spec.rb +54 -0
  73. data/spec/belajar/test_result_spec.rb +91 -0
  74. data/spec/belajar/test_spec.rb +48 -0
  75. data/spec/belajar/unit_spec.rb +85 -0
  76. data/spec/belajar/views/chapters_menu_spec.rb +6 -0
  77. data/spec/belajar/views/courses_menu_spec.rb +6 -0
  78. data/spec/belajar/views/menu_spec.rb +19 -0
  79. data/spec/belajar/views/task_view_spec.rb +7 -0
  80. data/spec/belajar/views/units_menu_spec.rb +6 -0
  81. data/spec/belajar/views_spec.rb +21 -0
  82. data/spec/belajar_spec.rb +51 -0
  83. data/spec/path_helpers_spec.rb +60 -0
  84. data/spec/resource_helpers_spec.rb +33 -0
  85. data/spec/spec_helper.rb +28 -0
  86. data/spec/support/macros/content_helpers.rb +129 -0
  87. data/spec/support/macros/mock_helpers.rb +25 -0
  88. data/spec/support/macros/path_helpers.rb +139 -0
  89. data/spec/support/macros/resource_helpers.rb +157 -0
  90. data/spec/support/macros/test_helpers.rb +6 -0
  91. metadata +385 -0
@@ -0,0 +1,115 @@
1
+ require 'thor'
2
+
3
+ module Belajar
4
+ module Terminal
5
+
6
+ require_relative 'output'
7
+
8
+ class Setup < Thor
9
+ include Terminal::Output
10
+
11
+ desc 'init', 'Initially setup belajar paths'
12
+ def init
13
+ empty_line
14
+ say 'Please type the base path in which you want to save your belajar'
15
+ say 'files. The "courses" folder and "solutions" folder will be created'
16
+ say 'automatically.'
17
+
18
+ loop do
19
+ path = get 'path:'
20
+
21
+ begin
22
+ @belajar_path = File.expand_path("#{path}", Dir.pwd)
23
+ rescue
24
+ say_warning "#{path} is no valid path name. Try another!"
25
+ next
26
+ end
27
+
28
+ say_warning 'Do you want to use the following path as your belajar base path?'
29
+ say "\"#{@belajar_path}\""
30
+
31
+ confirmation = get '(yes|no)'
32
+ break if confirmation.downcase == 'yes'
33
+
34
+ empty_line
35
+ say 'No Problem. Just type another one!'
36
+ end
37
+
38
+ prepare_directories(@belajar_path)
39
+ end
40
+
41
+ desc 'list', 'List the current belajar setup'
42
+ def list
43
+ say_info "Your current belajar setup is:\n\n#{Belajar.config.summary}"
44
+ end
45
+
46
+ desc 'set [OPTIONS]', 'Update the settings of your belajar environment'
47
+ method_option :courses_path,
48
+ type: :string,
49
+ aliases: '-c',
50
+ desc: 'Set courses_path directory'
51
+ method_option :solutions_path,
52
+ type: :string,
53
+ aliases: '-s',
54
+ desc: 'Set solutions_path directory'
55
+ method_option :paths,
56
+ type: :string,
57
+ aliases: '-p',
58
+ desc: 'Set all belajar paths to a certain path'
59
+ def set
60
+ courses_path = options[:paths] || options[:courses_path]
61
+ solutions_path = options[:paths] || options[:solutions_path]
62
+
63
+ if courses_path.nil? && solutions_path.nil?
64
+ say_warning "Please specify options when using this command!"
65
+ say %x{ belajar setup help set }
66
+ return
67
+ end
68
+
69
+ update_config(:courses_path, courses_path) if courses_path
70
+ update_config(:solutions_path, solutions_path) if solutions_path
71
+
72
+ Belajar.config.save
73
+ list
74
+ end
75
+
76
+ private
77
+
78
+ def prepare_directories(path)
79
+ courses_dir = Belajar::Configuration::COURSES_DIR
80
+ courses_path = File.join(path, courses_dir)
81
+ Belajar.config.courses_path = courses_path
82
+
83
+ solutions_dir = Belajar::Configuration::SOLUTIONS_DIR
84
+ solutions_path = File.join(path, solutions_dir)
85
+
86
+ if Dir.exist? solutions_path
87
+ Belajar.config.solutions_path = solutions_path
88
+ end
89
+
90
+ generator = Belajar::Generator.new
91
+ generator.prepare
92
+
93
+ text = [
94
+ "Your Belajar directory is now set up.\n",
95
+ "Belajar created/updated following two paths for you:",
96
+ courses_path,
97
+ solutions_path
98
+ ]
99
+
100
+ say_info text.join("\n")
101
+ end
102
+
103
+ def update_config(attribute, value)
104
+ begin
105
+ path = File.expand_path(value, Dir.pwd)
106
+ Belajar.config.send("#{attribute}=", path)
107
+ rescue Exception => e
108
+ say_warning e.message
109
+ end
110
+ end
111
+
112
+ end
113
+
114
+ end
115
+ end
@@ -0,0 +1,46 @@
1
+ module Belajar
2
+ module Terminal
3
+
4
+ require 'os'
5
+ require_relative 'output'
6
+
7
+ class Solutions < Thor
8
+ include Terminal::Output
9
+
10
+ desc 'solutions open [COURSE NAME]', 'Open the solutions folder of a course in a GUI window'
11
+ def open(course_name = '')
12
+ begin
13
+ path = File.join(Belajar.config.solutions_path, course_name)
14
+
15
+ unless Dir.exist?(path)
16
+ text = [
17
+ "The course directory \"#{File.basename(path)}\" is not available in",
18
+ "\"#{File.dirname(path)}\".\n",
19
+ 'Hint:',
20
+ 'Run "belajar scaffold" to create empty solution files for all courses.'
21
+ ]
22
+ say_warning text.join("\n")
23
+
24
+ unless Loading::Courses.load(Belajar.config.courses_path).empty?
25
+ Terminal::Courses.new.list
26
+ end
27
+
28
+ return
29
+ end
30
+
31
+ if OS.windows?
32
+ system "explorer '#{path}'"
33
+ elsif OS.mac?
34
+ system "open '#{path}'"
35
+ elsif OS.linux?
36
+ system "xdg-open '#{path}'"
37
+ end
38
+ rescue ConfigurationError => e
39
+ say_warning e.message
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,19 @@
1
+ **********************************************************************
2
+ ◇ ABOUT BELAJAR! ◇
3
+ **********************************************************************
4
+
5
+ Belajar is the Japanese word for "university".
6
+ With Belajar you can master your way of learning the Ruby programming
7
+ language with courses that are created by the community.
8
+
9
+ Belajar is a command line tool and a text based interface and provides
10
+ you with a number of learning tasks and explanations about the Ruby
11
+ programming language. You will learn Ruby step by step by solving small
12
+ language-explaining programming tasks.
13
+
14
+ Belajar's command line interface provides several commands which you
15
+ can use in your terminal to setup the system, download new courses,
16
+ and navigate through your solutions.
17
+
18
+ By typing "belajar help" in you terminal you are provided with an
19
+ overview of all available commands.
@@ -0,0 +1,12 @@
1
+ Well done!
2
+ Three cheers!
3
+ You did it!
4
+ Congrats!
5
+ Bravo!
6
+ Hip, hip, hurrah!
7
+ Congratulations!
8
+ Kudos!
9
+ Props!
10
+ Hats off!
11
+ Yay!
12
+ Well done! Ready for the next task?
@@ -0,0 +1,3 @@
1
+ There are no courses available in your current courses path.
2
+
3
+ Go and insert some to your courses path!
@@ -0,0 +1,13 @@
1
+ You can download a new belajar course by using the
2
+ "belajar courses download [URL] [OPTIONS]" command, e.g.:
3
+
4
+ $ belajar courses download https://github.com/wong-bejo/Get_started_with_Ruby/archive/master.zip
5
+
6
+ For Github resources you can also use the `--github` (short `-g`) option:
7
+
8
+ $ belajar courses download -g wong-bejo/Get_started_with_Ruby
9
+
10
+ If you want to quick start with Daiaku's "Get started with Ruby"
11
+ course just run:
12
+
13
+ $ belajar courses download
@@ -0,0 +1,12 @@
1
+ **********************************************************************
2
+ ◇ WELCOME TO BELAJAR! ◇
3
+ **********************************************************************
4
+
5
+ To get started, you need a folder where you can save your courses and
6
+ solutions. By default, belajar uses the same base path for both.
7
+ Your courses will be saved to a "courses" folder and your solutions
8
+ can be found in a "solutions" folder.
9
+
10
+ The "solutions" path and "courses" path can be changed later on.
11
+ See which command you can use to update your setup by simply typing
12
+ "belajar setup help set" in your command line.
@@ -0,0 +1,98 @@
1
+ module Belajar
2
+ module Terminal
3
+
4
+ class Welcome
5
+ include Terminal::Output
6
+
7
+ def self.run
8
+ self.new.run
9
+ end
10
+
11
+ def self.about
12
+ self.new.about
13
+ end
14
+
15
+ def run
16
+ empty_line
17
+ say Terminal.text :welcome
18
+ empty_line
19
+ say "For now, let's setup the belajar paths."
20
+ Belajar::Terminal::Setup.new.init
21
+
22
+ show_setup_list_announcement
23
+ show_courses_list_announcement
24
+
25
+ courses = Loading::Courses.load(Belajar.config.courses_path)
26
+
27
+ if courses.empty?
28
+ show_courses_download_announcement
29
+ show_solutions_open_announcement
30
+ end
31
+
32
+ empty_line
33
+ show_learn_announcement
34
+ end
35
+
36
+ def about
37
+ empty_line
38
+ say Terminal.text :about
39
+ empty_line
40
+ say %x{belajar help}
41
+ end
42
+
43
+ private
44
+
45
+ def show_setup_list_announcement
46
+ command = 'belajar setup list'
47
+ text = [
48
+ "The courses path and solutions path have been added to your settings.",
49
+ "Just list your current settings with the \"#{command}\" command:"
50
+ ].join("\n")
51
+
52
+ get_command(command, text)
53
+ end
54
+
55
+ def show_courses_list_announcement
56
+ command = 'belajar courses list'
57
+ text = [
58
+ "Well done. Now, type \"#{command}\" to see what courses are",
59
+ "available in your belajar folder:"
60
+ ].join("\n")
61
+
62
+ get_command(command, text)
63
+ end
64
+
65
+ def show_courses_download_announcement
66
+ command = 'belajar courses download'
67
+ text = [
68
+ "Oh! You don't have any courses, yet?",
69
+ "Just enter \"#{command}\" to download the basic Belajar course:"
70
+ ].join("\n")
71
+
72
+ get_command(command, text)
73
+ end
74
+
75
+ def show_solutions_open_announcement
76
+ command = 'belajar solutions open'
77
+ text = [
78
+ "When downloading a course, Belajar scaffolds empty solution files",
79
+ "for your code on the fly.\n",
80
+ "Type \"#{command}\" to open your solutions folder:"
81
+ ].join("\n")
82
+
83
+ get_command(command, text)
84
+ end
85
+
86
+ def show_learn_announcement
87
+ command = 'belajar learn'
88
+ text = [
89
+ "Congratulations! You learned the first steps of using belajar.",
90
+ "To continue and start learning Ruby type \"#{command}\":"
91
+ ].join("\n")
92
+
93
+ get_command(command, text)
94
+ end
95
+ end
96
+
97
+ end
98
+ end
@@ -0,0 +1,46 @@
1
+ module Belajar
2
+ require 'fileutils'
3
+
4
+ class Test
5
+
6
+ attr_reader :path
7
+
8
+ CODE_REGEX = /\[\['solution::code'\]\]/
9
+
10
+ def initialize(path)
11
+ @unit_path = path
12
+ @path = Dir[File.join(path, '*spec.rb')].first
13
+ end
14
+
15
+ def run(solution_code)
16
+ spec_code = File.read(@path)
17
+ patched_spec_code = insert_code(spec_code, solution_code.to_s)
18
+
19
+ temp_spec = File.join(File.dirname(@path), "temp_#{File.basename(@path)}")
20
+ create_temp_spec(temp_spec, patched_spec_code)
21
+
22
+ result = %x{ rspec --color --format j #{temp_spec} }
23
+ remove_file(temp_spec)
24
+
25
+ TestResult.new(result)
26
+ end
27
+
28
+ private
29
+
30
+ def insert_code(spec, code)
31
+ spec.gsub(CODE_REGEX, code)
32
+ end
33
+
34
+ def create_temp_spec(path, content)
35
+ base_path = File.dirname(path)
36
+ FileUtils.mkdir_p(base_path) unless Dir.exist?(base_path)
37
+ File.open(path, 'w') { |f| f.puts content }
38
+ end
39
+
40
+ def remove_file(path)
41
+ FileUtils.rm(path) if File.exist?(path)
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,86 @@
1
+ module Belajar
2
+
3
+ class TestResult
4
+ require 'json'
5
+
6
+ attr_reader :examples, :example_count, :failure_count
7
+
8
+ def initialize(result_json)
9
+ @result = begin
10
+ JSON.parse(result_json, symbolize_names: true)
11
+ rescue
12
+ syntax_error_json
13
+ end
14
+
15
+ @example_count = @result[:summary][:example_count]
16
+ @failure_count = @result[:summary][:failure_count]
17
+
18
+ @examples = @result[:examples].map do |example|
19
+ description = example[:full_description]
20
+ status = example[:status]
21
+ exception = example[:exception]
22
+ message = exception ? exception[:message] : nil
23
+
24
+ TestExample.new(description: description, status: status, message: message)
25
+ end
26
+ end
27
+
28
+ def passed?
29
+ @examples.reduce(true) do |passed, example|
30
+ passed && example.passed?
31
+ end
32
+ end
33
+
34
+ def summary
35
+ if passed?
36
+ "Your code passed all tests. #{Belajar::Congratulator.message}"
37
+ else
38
+ build_failed_summary
39
+ end
40
+ end
41
+
42
+ def summary_lines
43
+ summary.lines.map(&:strip)
44
+ end
45
+
46
+ private
47
+
48
+ def build_failed_summary
49
+ message = examples.map do |example|
50
+ "#{example.description}\n#{example.status}: #{example.message}"
51
+ end
52
+
53
+ summary = message.map(&:strip).join("\n" * 3)
54
+ end
55
+
56
+ def syntax_error_json
57
+ {
58
+ summary: {},
59
+ examples: [
60
+ {
61
+ status: 'failed',
62
+ exception: { message: ":( You got a syntax error in your code!" }
63
+ }
64
+ ]
65
+ }
66
+ end
67
+ end
68
+
69
+ class TestExample
70
+
71
+ attr_reader :description, :status, :message
72
+
73
+ EXAMPLE_PASSED_MESSAGE = "Your code passed this requirement."
74
+
75
+ def initialize(args = {})
76
+ @description = args[:description]
77
+ @status = args[:status]
78
+ @message = args[:message] || EXAMPLE_PASSED_MESSAGE
79
+ end
80
+
81
+ def passed?
82
+ @status == 'passed'
83
+ end
84
+ end
85
+
86
+ end