learn-open 1.2.20 → 1.2.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +4 -0
  3. data/Guardfile +70 -0
  4. data/learn-open.gemspec +7 -1
  5. data/lib/learn_open.rb +66 -0
  6. data/lib/learn_open/adapters/io_adapter.rb +24 -0
  7. data/lib/learn_open/adapters/learn_web_adapter.rb +103 -0
  8. data/lib/learn_open/adapters/system_adapter.rb +30 -0
  9. data/lib/learn_open/environments.rb +35 -0
  10. data/lib/learn_open/environments/base_environment.rb +70 -0
  11. data/lib/learn_open/environments/generic_environment.rb +9 -0
  12. data/lib/learn_open/environments/ide_environment.rb +63 -0
  13. data/lib/learn_open/environments/jupyter_container_environment.rb +28 -0
  14. data/lib/learn_open/environments/linux_environment.rb +17 -0
  15. data/lib/learn_open/environments/mac_environment.rb +75 -0
  16. data/lib/learn_open/lessons.rb +24 -0
  17. data/lib/learn_open/lessons/base_lesson.rb +57 -0
  18. data/lib/learn_open/lessons/ios_lesson.rb +14 -0
  19. data/lib/learn_open/lessons/jupyter_lesson.rb +14 -0
  20. data/lib/learn_open/lessons/lab_lesson.rb +9 -0
  21. data/lib/learn_open/lessons/readme_lesson.rb +13 -0
  22. data/lib/learn_open/opener.rb +26 -469
  23. data/lib/learn_open/services/dependency_installers.rb +19 -0
  24. data/lib/learn_open/services/dependency_installers/base_installer.rb +21 -0
  25. data/lib/learn_open/services/dependency_installers/gem_installer.rb +14 -0
  26. data/lib/learn_open/services/dependency_installers/jupyter_pip_installer.rb +14 -0
  27. data/lib/learn_open/services/dependency_installers/node_package_installer.rb +20 -0
  28. data/lib/learn_open/services/dependency_installers/pip_installer.rb +14 -0
  29. data/lib/learn_open/services/file_backup_starter.rb +20 -0
  30. data/lib/learn_open/services/lesson_downloader.rb +82 -0
  31. data/lib/learn_open/services/logger.rb +23 -0
  32. data/lib/learn_open/version.rb +1 -1
  33. data/spec/fakes/fake_git.rb +20 -0
  34. data/spec/fakes/fake_learn_client.rb +214 -0
  35. data/spec/fixtures/learn-config +3 -0
  36. data/spec/learn_open/environments/ide_environment_spec.rb +62 -0
  37. data/spec/learn_open/opener_spec.rb +789 -14
  38. data/spec/spec_helper.rb +41 -0
  39. metadata +121 -5
  40. data/spec/home_dir/.learn-config +0 -3
@@ -0,0 +1,9 @@
1
+ module LearnOpen
2
+ module Environments
3
+ class GenericEnvironment < BaseEnvironment
4
+ def open_readme(_lesson)
5
+ io.puts "It looks like this lesson is a Readme. Please open it in your browser."
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,63 @@
1
+ module LearnOpen
2
+ module Environments
3
+ class IDEEnvironment < BaseEnvironment
4
+ def open_readme(lesson)
5
+ when_valid(lesson) do
6
+ warn_if_necessary(lesson)
7
+ io.puts "Opening readme..."
8
+ run_custom_command(:browser_open, {url: lesson.to_url})
9
+ end
10
+ end
11
+
12
+ def open_jupyter_lab(lesson, location, editor)
13
+ when_valid(lesson) do
14
+ warn_if_necessary(lesson)
15
+ io.puts "Opening Jupyter Lesson..."
16
+ run_custom_command(:browser_open, {url: lesson.to_url})
17
+ end
18
+ end
19
+
20
+ def open_lab(lesson, location, editor)
21
+ when_valid(lesson) do
22
+ warn_if_necessary(lesson)
23
+ case lesson
24
+ when LearnOpen::Lessons::IosLesson
25
+ super
26
+ when -> (l) { valid?(l) }
27
+ download_lesson(lesson, location)
28
+ open_editor(lesson, location, editor)
29
+ start_file_backup(lesson, location)
30
+ install_dependencies(lesson, location)
31
+ notify_of_completion
32
+ open_shell
33
+ end
34
+ end
35
+ end
36
+
37
+ def when_valid(lesson, &block)
38
+ if valid?(lesson)
39
+ block.call
40
+ else
41
+ on_invalid(lesson)
42
+ end
43
+ end
44
+
45
+ def valid?(lesson)
46
+ lesson.name == environment_vars['LAB_NAME']
47
+ end
48
+
49
+ def on_invalid(lesson)
50
+ io.puts "Opening new window"
51
+ run_custom_command(:open_lab, {lab_name: lesson.name})
52
+ end
53
+
54
+ def run_custom_command(command, message)
55
+ home_dir = "/home/#{environment_vars['CREATED_USER']}"
56
+ custom_commands_log = "#{home_dir}/.custom_commands.log"
57
+ File.open(custom_commands_log, "a") do |f|
58
+ f.puts({:command => command}.merge(message).to_json)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,28 @@
1
+ module LearnOpen
2
+ module Environments
3
+ class JupyterContainerEnvironment < BaseEnvironment
4
+ def open_jupyter_lab(lesson, location, editor)
5
+ download_lesson(lesson, location)
6
+ open_editor(lesson, location, editor)
7
+ start_file_backup(lesson, location)
8
+ install_jupyter_dependencies(lesson, location)
9
+ notify_of_completion
10
+ open_shell
11
+ end
12
+
13
+ def open_editor(lesson, location, editor)
14
+ io.puts "Opening lesson..."
15
+ system_adapter.change_context_directory(lesson.to_path)
16
+ system_adapter.open_editor(editor, path: ".")
17
+ end
18
+
19
+ def install_jupyter_dependencies(lesson, location)
20
+ LearnOpen::DependencyInstallers::JupyterPipInstall.call(lesson, location, self, options)
21
+ end
22
+
23
+ def open_shell
24
+ system_adapter.open_login_shell(environment_vars['SHELL'])
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ module LearnOpen
2
+ module Environments
3
+ class LinuxEnvironment < BaseEnvironment
4
+ def open_readme(lesson)
5
+ warn_if_necessary(lesson)
6
+ io.puts "Opening readme..."
7
+ system_adapter.run_command("xdg-open #{lesson.to_url}")
8
+ end
9
+
10
+ def open_jupyter_lab(lesson, location, editor)
11
+ warn_if_necessary(lesson)
12
+ io.puts "Opening Jupyter Lesson..."
13
+ system_adapter.run_command("xdg-open #{lesson.to_url}")
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,75 @@
1
+ module LearnOpen
2
+ module Environments
3
+ class MacEnvironment < BaseEnvironment
4
+ def self.classify(options)
5
+ if chrome_installed?
6
+ MacWithChromeEnvironment.new(options)
7
+ else
8
+ self.new(options)
9
+ end
10
+ end
11
+
12
+ def self.chrome_installed?
13
+ File.exists?('/Applications/Google Chrome.app')
14
+ end
15
+
16
+ def open_readme(lesson)
17
+ warn_if_necessary(lesson)
18
+ io.puts "Opening readme..."
19
+ system_adapter.run_command("open -a Safari #{lesson.to_url}")
20
+ end
21
+
22
+ def open_lab(lesson, location, editor)
23
+ warn_if_necessary(lesson)
24
+ case lesson
25
+ when LearnOpen::Lessons::IosLesson
26
+ download_lesson(lesson, location)
27
+ open_xcode(lesson)
28
+ notify_of_completion
29
+ open_shell
30
+ else
31
+ super
32
+ end
33
+ end
34
+
35
+ def open_jupyter_lab(lesson, location, editor)
36
+ warn_if_necessary(lesson)
37
+ io.puts "Opening Jupyter Lesson..."
38
+ system_adapter.run_command("open -a Safari #{lesson.to_url}")
39
+ end
40
+
41
+ def xcodeproj_file?(lesson)
42
+ Dir.glob("#{lesson.to_path}/*.xcodeproj").any?
43
+ end
44
+
45
+ def xcworkspace_file?(lesson)
46
+ Dir.glob("#{lesson.to_path}/*.xcworkspace").any?
47
+ end
48
+
49
+ def open_xcode(lesson)
50
+ io.puts "Opening lesson..."
51
+ system_adapter.change_context_directory("#{lesson.to_path}")
52
+ if xcworkspace_file?(lesson)
53
+ system_adapter.run_command("cd #{lesson.to_path} && open *.xcworkspace")
54
+ elsif xcodeproj_file?(lesson)
55
+ system_adapter.run_command("cd #{lesson.to_path} && open *.xcodeproj")
56
+ end
57
+ end
58
+ end
59
+
60
+ class MacWithChromeEnvironment < MacEnvironment
61
+ def open_readme(lesson)
62
+ warn_if_necessary(lesson)
63
+ io.puts "Opening readme..."
64
+ system_adapter.run_command("open -a 'Google Chrome' #{lesson.to_url}")
65
+ end
66
+
67
+ def open_jupyter_lab(lesson, location, editor)
68
+ warn_if_necessary(lesson)
69
+ io.puts "Opening Jupyter Lesson..."
70
+ system_adapter.run_command("open -a 'Google Chrome' #{lesson.to_url}")
71
+ end
72
+
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,24 @@
1
+ module LearnOpen
2
+ module Lessons
3
+
4
+ def self.default
5
+ LabLesson
6
+ end
7
+
8
+ def self.lesson_types
9
+ [
10
+ JupyterLesson,
11
+ ReadmeLesson,
12
+ IosLesson,
13
+ ]
14
+ end
15
+
16
+ def self.classify(lesson_data, options = {})
17
+ lesson = lesson_data[:lesson]
18
+ default = method(:default)
19
+ lesson_types.find(default) do |type|
20
+ type.detect(lesson)
21
+ end.new(lesson_data, options)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,57 @@
1
+ module LearnOpen
2
+ module Lessons
3
+ class BaseLesson
4
+ attr_reader :repo_path,
5
+ :organization,
6
+ :name,
7
+ :id,
8
+ :dot_learn,
9
+ :git_server,
10
+ :later_lesson,
11
+ :options,
12
+ :io,
13
+ :system_adapter,
14
+ :platform,
15
+ :environment_vars,
16
+ :logger,
17
+ :location
18
+
19
+ def initialize(lesson_data, options = {})
20
+ lesson = lesson_data[:lesson]
21
+
22
+ @repo_path = lesson.clone_repo
23
+ @organization, @name = repo_path.split('/')
24
+
25
+ @git_server = lesson.git_server
26
+ @dot_learn = lesson.dot_learn
27
+ @is_lab = lesson.lab
28
+ @later_lesson = lesson_data[:later_lesson]
29
+ @id = lesson_data[:id]
30
+
31
+ @logger = options.fetch(:logger, LearnOpen.logger)
32
+ @io = options.fetch(:io, LearnOpen.default_io)
33
+ @system_adapter = options.fetch(:system_adapter, LearnOpen.system_adapter)
34
+ @platform = options.fetch(:platform, LearnOpen.platform)
35
+ @environment_vars = options.fetch(:environment_vars, LearnOpen.environment_vars)
36
+ @location = options.fetch(:lessons_directory) {LearnOpen.lessons_directory}
37
+ @options = options
38
+ end
39
+
40
+ def lab?
41
+ @is_lab
42
+ end
43
+
44
+ def readme?
45
+ !lab?
46
+ end
47
+
48
+ def to_path
49
+ "#{location}/#{name}"
50
+ end
51
+
52
+ def to_url
53
+ "https://learn.co/lessons/#{id}"
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,14 @@
1
+ module LearnOpen
2
+ module Lessons
3
+ class IosLesson < BaseLesson
4
+ def self.detect(lesson)
5
+ languages = Hash(lesson.dot_learn)[:languages]
6
+ (languages & ["swift", "objc"]).any?
7
+ end
8
+
9
+ def open(environment, editor)
10
+ environment.open_lab(self, location, editor)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module LearnOpen
2
+ module Lessons
3
+ class JupyterLesson < BaseLesson
4
+ def self.detect(lesson)
5
+ dot_learn = Hash(lesson.dot_learn)
6
+ !!dot_learn[:jupyter_notebook]
7
+ end
8
+
9
+ def open(environment, editor)
10
+ environment.open_jupyter_lab(self, location, editor)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ module LearnOpen
2
+ module Lessons
3
+ class LabLesson < BaseLesson
4
+ def open(environment, editor)
5
+ environment.open_lab(self, location, editor)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ module LearnOpen
2
+ module Lessons
3
+ class ReadmeLesson < BaseLesson
4
+ def self.detect(lesson)
5
+ !lesson.lab
6
+ end
7
+
8
+ def open(environment, _editor)
9
+ environment.open_readme(self)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,484 +1,41 @@
1
1
  module LearnOpen
2
2
  class Opener
3
- HOME_DIR = File.expand_path("~")
4
- attr_reader :editor, :client, :lessons_dir, :file_path, :get_next_lesson, :token
5
- attr_accessor :lesson, :repo_dir, :lesson_is_lab, :lesson_id, :later_lesson, :dot_learn
3
+ attr_reader :editor,
4
+ :target_lesson,
5
+ :get_next_lesson,
6
+ :io,
7
+ :logger,
8
+ :options
6
9
 
7
10
  def self.run(lesson:, editor_specified:, get_next_lesson:)
8
11
  new(lesson, editor_specified, get_next_lesson).run
9
12
  end
10
13
 
11
- def initialize(lesson, editor, get_next_lesson)
12
- _login, @token = Netrc.read['learn-config']
13
- @client = LearnWeb::Client.new(token: @token)
14
-
15
- @lesson = lesson
16
- @editor = editor
14
+ def initialize(target_lesson, editor, get_next_lesson, options = {})
15
+ @target_lesson = target_lesson
16
+ @editor = editor
17
17
  @get_next_lesson = get_next_lesson
18
- @lessons_dir = YAML.load(File.read("#{HOME_DIR}/.learn-config"))[:learn_directory]
19
- @file_path = "#{HOME_DIR}/.learn-open-tmp"
20
- end
21
-
22
- def run
23
- setup_tmp_file
24
-
25
- set_lesson
26
-
27
- if ide_version_3?
28
- if self.repo_dir != ENV['LAB_NAME']
29
- home_dir = "/home/#{ENV['CREATED_USER']}"
30
- File.open("#{home_dir}/.custom_commands.log", "a") do |f|
31
- f.puts %Q{{"command": "open_lab", "lab_name": "#{self.repo_dir}"}}
32
- end
33
- exit
34
- end
35
- end
36
-
37
- puts "Looking for lesson..."
38
-
39
- if jupyter_notebook_environment?
40
- git_tasks
41
- file_tasks
42
- restore_files
43
- watch_for_changes
44
- jupyter_pip_install
45
- completion_tasks
46
- else
47
- warn_if_necessary
48
- if lesson_is_readme?
49
- open_readme
50
- else
51
- git_tasks
52
- file_tasks
53
- setup_backup_if_needed
54
- dependency_tasks
55
- completion_tasks
56
- end
57
- end
58
-
59
- end
60
-
61
- def repo_exists?
62
- File.exists?("#{lessons_dir}/#{repo_dir}/.git")
63
- end
64
-
65
- private
66
-
67
- def setup_backup_if_needed
68
- if ide_environment? && ide_git_wip_enabled?
69
- restore_files
70
- watch_for_changes
71
- end
72
- end
73
-
74
- def ping_fork_completion(retries=3)
75
- begin
76
- Timeout::timeout(15) do
77
- client.submit_event(
78
- event: 'fork',
79
- learn_oauth_token: token,
80
- repo_name: repo_dir,
81
- base_org_name: lesson.split('/')[0],
82
- forkee: { full_name: nil }
83
- )
84
- end
85
- rescue Timeout::Error
86
- if retries > 0
87
- puts "There was a problem forking and cloning this lesson. Retrying..."
88
- ping_fork_completion(retries-1)
89
- else
90
- puts "There is an issue connecting to Learn. Please try again."
91
- File.write(file_path, 'ERROR: Error connecting to Learn')
92
- exit
93
- end
94
- end
95
- end
96
-
97
- def warn_if_necessary
98
- temp_args = nil
99
-
100
- if self.later_lesson
101
- puts 'WARNING: You are attempting to open a lesson that is beyond your current lesson.'
102
- print 'Are you sure you want to continue? [Yn]: '
103
-
104
- if ARGV.any?
105
- temp_args = ARGV
106
- ARGV.clear
107
- end
108
-
109
- warn_response = gets.chomp.downcase
110
-
111
- if !warn_response.empty? && !['yes', 'y'].include?(warn_response)
112
- exit
113
- end
114
- end
115
-
116
- if temp_args
117
- temp_args.each do |arg|
118
- ARGV << arg
119
- end
120
- end
121
- end
122
-
123
- def setup_tmp_file
124
- FileUtils.touch(file_path)
125
- File.write(file_path, '')
126
- end
127
-
128
- def cleanup_tmp_file
129
- File.write(file_path, 'Done.')
130
- end
131
18
 
132
- def set_lesson
133
- File.write(file_path, 'Getting lesson...')
134
-
135
- if !lesson && !get_next_lesson
136
- self.lesson = get_current_lesson_forked_repo
137
- self.lesson_is_lab = current_lesson.lab
138
- self.lesson_id = current_lesson.id
139
- self.later_lesson = false
140
- self.dot_learn = current_lesson.dot_learn
141
- elsif !lesson && get_next_lesson
142
- self.lesson = get_next_lesson_forked_repo
143
- self.lesson_is_lab = next_lesson.lab
144
- self.lesson_id = next_lesson.id
145
- self.later_lesson = false
146
- self.dot_learn = next_lesson.dot_learn
147
- else
148
- self.lesson = ensure_correct_lesson.clone_repo
149
- self.lesson_is_lab = correct_lesson.lab
150
- self.lesson_id = correct_lesson.lesson_id
151
- self.later_lesson = correct_lesson.later_lesson
152
- self.dot_learn = correct_lesson.dot_learn
153
- end
154
-
155
- self.repo_dir = lesson.split('/').last
156
- end
157
-
158
- def current_lesson
159
- @current_lesson ||= client.current_lesson
160
- end
161
-
162
- def next_lesson
163
- @next_lesson ||= client.next_lesson
164
- end
165
-
166
- def get_current_lesson_forked_repo(retries=3)
167
- begin
168
- Timeout::timeout(15) do
169
- current_lesson.clone_repo
170
- end
171
- rescue Timeout::Error
172
- if retries > 0
173
- puts "There was a problem getting your lesson from Learn. Retrying..."
174
- get_current_lesson_forked_repo(retries-1)
175
- else
176
- puts "There seems to be a problem connecting to Learn. Please try again."
177
- File.write(file_path, 'ERROR: Error connecting to Learn')
178
- exit
179
- end
180
- end
181
- end
182
-
183
- def get_next_lesson_forked_repo(retries=3)
184
- begin
185
- Timeout::timeout(15) do
186
- next_lesson.clone_repo
187
- end
188
- rescue Timeout::Error
189
- if retries > 0
190
- puts "There was a problem getting your next lesson from Learn. Retrying..."
191
- get_next_lesson_forked_repo(retries-1)
192
- else
193
- puts "There seems to be a problem connecting to Learn. Please try again."
194
- File.write(file_path, 'ERROR: Error connecting to Learn')
195
- exit
196
- end
197
- end
198
- end
199
-
200
- def ensure_correct_lesson
201
- correct_lesson
202
- end
203
-
204
- def correct_lesson(retries=3)
205
- @correct_lesson ||= begin
206
- Timeout::timeout(15) do
207
- client.validate_repo_slug(repo_slug: lesson)
208
- end
209
- rescue Timeout::Error
210
- if retries > 0
211
- puts "There was a problem connecting to Learn. Retrying..."
212
- correct_lesson(retries-1)
213
- else
214
- puts "Cannot connect to Learn right now. Please try again."
215
- File.write(file_path, 'ERROR: Error connecting to Learn')
216
- exit
217
- end
218
- end
219
- end
220
-
221
- def fork_repo(retries=3)
222
- if !repo_exists?
223
- File.write(file_path, 'Forking repository...')
224
- puts "Forking lesson..."
225
-
226
- if !github_disabled?
227
- begin
228
- Timeout::timeout(15) do
229
- client.fork_repo(repo_name: repo_dir)
230
- end
231
- rescue Timeout::Error
232
- if retries > 0
233
- puts "There was a problem forking this lesson. Retrying..."
234
- fork_repo(retries-1)
235
- else
236
- puts "There is an issue connecting to Learn. Please try again."
237
- File.write(file_path, 'ERROR: Error connecting to Learn')
238
- exit
239
- end
240
- end
241
- end
242
- end
243
- end
244
-
245
- def clone_repo(retries=3)
246
- if !repo_exists?
247
- File.write(file_path, 'Cloning to your machine...')
248
- puts "Cloning lesson..."
249
- begin
250
- Timeout::timeout(15) do
251
- Git.clone("git@github.com:#{lesson}.git", repo_dir, path: lessons_dir)
252
- end
253
- rescue Git::GitExecuteError
254
- if retries > 0
255
- puts "There was a problem cloning this lesson. Retrying..." if retries > 1
256
- sleep(1)
257
- clone_repo(retries-1)
258
- else
259
- puts "Cannot clone this lesson right now. Please try again."
260
- File.write(file_path, 'ERROR: Error cloning. Try again.')
261
- exit
262
- end
263
- rescue Timeout::Error
264
- if retries > 0
265
- puts "There was a problem cloning this lesson. Retrying..."
266
- clone_repo(retries-1)
267
- else
268
- puts "Cannot clone this lesson right now. Please try again."
269
- File.write(file_path, 'ERROR: Error cloning. Try again.')
270
- exit
271
- end
272
- end
273
- end
274
-
275
- if github_disabled?
276
- ping_fork_completion
277
- end
278
- end
279
-
280
- def open_with_editor
281
- if ios_lesson?
282
- open_ios_lesson
283
- elsif editor
284
- system("#{editor} .")
285
- end
286
- end
287
-
288
- def ios_lesson?
289
- begin
290
- languages = YAML.load(File.read("#{lessons_dir}/#{repo_dir}/.learn"))['languages']
291
- ios_lang = languages.any? {|l| ['objc', 'swift'].include?(l)}
292
-
293
- ios_lang || xcodeproj_file? || xcworkspace_file?
294
- rescue Psych::SyntaxError
295
- if xcodeproj_file? || xcworkspace_file?
296
- true
297
- else
298
- puts "Sorry, there seems to be a problem with this lesson. Please submit a bug report to bugs@learn.co and try again later."
299
- puts "If you'd like to work on your next lesson now, type: learn next"
300
- File.write(file_path, 'ERROR: Problem parsing lesson data. Try again.')
301
- exit
302
- end
303
- rescue NoMethodError, Errno::ENOENT => e
304
- if xcodeproj_file? || xcworkspace_file?
305
- true
306
- elsif e.message.match(/for false:FalseClass/) || e.message.match(/No such file or directory/)
307
- false
308
- else
309
- puts "Sorry, there seems to be a problem with this lesson. Please submit a bug report to bugs@learn.co and try again later."
310
- puts "If you'd like to work on your next lesson now, type: learn next"
311
- File.write(file_path, 'ERROR: Problem parsing lesson data. Try again.')
312
- exit
313
- end
314
- end
315
- end
316
-
317
- def open_ios_lesson
318
- if can_open_ios_lesson?
319
- open_xcode
320
- else
321
- puts "You need to be on a Mac to work on iOS lessons."
322
- exit
323
- end
324
- end
19
+ @io = options.fetch(:io, LearnOpen.default_io)
20
+ @logger = options.fetch(:logger, LearnOpen.logger)
325
21
 
326
- def can_open_ios_lesson?
327
- on_mac?
22
+ @options = options
328
23
  end
329
24
 
330
- def open_xcode
331
- if xcworkspace_file?
332
- system("cd #{lessons_dir}/#{repo_dir} && open *.xcworkspace")
333
- elsif xcodeproj_file?
334
- system("cd #{lessons_dir}/#{repo_dir} && open *.xcodeproj")
335
- end
336
- end
337
-
338
- def xcodeproj_file?
339
- Dir.glob("#{lessons_dir}/#{repo_dir}/*.xcodeproj").any?
340
- end
341
-
342
- def xcworkspace_file?
343
- Dir.glob("#{lessons_dir}/#{repo_dir}/*.xcworkspace").any?
344
- end
345
-
346
- def cd_to_lesson
347
- puts "Opening lesson..."
348
- Dir.chdir("#{lessons_dir}/#{repo_dir}")
349
- end
350
-
351
- def pip_install
352
- if !ios_lesson? && File.exists?("#{lessons_dir}/#{repo_dir}/requirements.txt")
353
- puts "Installing pip dependencies..."
354
- system("python -m pip install -r requirements.txt")
355
- end
356
- end
357
-
358
- def jupyter_pip_install
359
- if !ios_lesson? && File.exists?("#{lessons_dir}/#{repo_dir}/requirements.txt")
360
- puts "Installing pip dependencies..."
361
- system("/opt/conda/bin/python -m pip install -r requirements.txt")
362
- end
363
- end
364
-
365
- def bundle_install
366
- if !ios_lesson? && File.exists?("#{lessons_dir}/#{repo_dir}/Gemfile")
367
- puts "Bundling..."
368
- system("bundle install")
369
- end
370
- end
371
-
372
- def npm_install
373
- if !ios_lesson? && File.exists?("#{lessons_dir}/#{repo_dir}/package.json")
374
- puts 'Installing npm dependencies...'
375
-
376
- if ide_environment?
377
- system("yarn install --no-lockfile")
378
- else
379
- system("npm install")
380
- end
381
- end
382
- end
383
-
384
- def lesson_is_readme?
385
- !lesson_is_lab
386
- end
387
-
388
- def open_readme
389
- if ide_environment?
390
- puts "Opening readme..."
391
- File.open(".custom_commands.log", "a") do |f|
392
- f.puts %Q{{"command": "browser_open", "url": "https://learn.co/lessons/#{lesson_id}"}}
393
- end
394
- elsif can_open_readme?
395
- puts "Opening readme..."
396
- launch_browser
397
- else
398
- puts "It looks like this lesson is a Readme. Please open it in your browser."
399
- exit
400
- end
401
- end
402
-
403
- def launch_browser
404
- if chrome_installed?
405
- open_chrome
406
- else
407
- open_safari
408
- end
409
- end
410
-
411
- def chrome_installed?
412
- File.exists?('/Applications/Google Chrome.app')
413
- end
414
-
415
- def open_chrome
416
- system("open -a 'Google Chrome' https://learn.co/lessons/#{lesson_id}")
417
- end
418
-
419
- def open_safari
420
- system("open -a Safari https://learn.co/lessons/#{lesson_id}")
421
- end
422
-
423
- def can_open_readme?
424
- on_mac?
425
- end
426
-
427
- def on_mac?
428
- !!RUBY_PLATFORM.match(/darwin/)
429
- end
430
-
431
- def github_disabled?
432
- !dot_learn.nil? && dot_learn[:github] == false
433
- end
434
-
435
- def ide_environment?
436
- ENV['IDE_CONTAINER'] == "true"
437
- end
438
-
439
- def ide_git_wip_enabled?
440
- return false if github_disabled?
441
-
442
- ENV['IDE_GIT_WIP'] == "true"
443
- end
444
-
445
- def ide_version_3?
446
- ENV['IDE_VERSION'] == "3"
447
- end
448
-
449
- def jupyter_notebook_environment?
450
- ENV['JUPYTER_CONTAINER'] == "true"
451
- end
452
-
453
- def git_tasks
454
- fork_repo
455
- clone_repo
456
- end
457
-
458
- def file_tasks
459
- cd_to_lesson
460
- open_with_editor
461
- end
462
-
463
- def dependency_tasks
464
- bundle_install
465
- npm_install
466
- pip_install
467
- end
468
-
469
- def restore_files
470
- pid = Process.spawn("restore-lab", [:out, :err] => File::NULL)
471
- Process.waitpid(pid)
472
- end
473
-
474
- def watch_for_changes
475
- Process.spawn("while inotifywait -e close_write,create,moved_to -r #{lessons_dir}/#{repo_dir}; do backup-lab; done", [:out, :err] => File::NULL)
476
- end
477
-
478
- def completion_tasks
479
- cleanup_tmp_file
480
- puts "Done."
481
- exec("#{ENV['SHELL']} -l")
25
+ def run
26
+ logger.log('Getting lesson...')
27
+ io.puts "Looking for lesson..."
28
+
29
+ lesson_data = LearnOpen::Adapters::LearnWebAdapter
30
+ .new(options)
31
+ .fetch_lesson_data(
32
+ target_lesson: target_lesson,
33
+ fetch_next_lesson: get_next_lesson
34
+ )
35
+
36
+ lesson = Lessons.classify(lesson_data, options)
37
+ environment = LearnOpen::Environments.classify(options)
38
+ lesson.open(environment, editor)
482
39
  end
483
40
  end
484
41
  end