rpw 1.0.1 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aee4cd056139ea78d75fc48a6c0337c32c7e9ca958ac0c24716ec7a27abc5617
4
- data.tar.gz: 6688f3f8b1edef9c6004af6146d10e4d6b190d103f95ee233902523f73760043
3
+ metadata.gz: 317f37137765f78e5a587b36e3ecb4898d18e4b011cc3ef67f60d5d0e710c6d8
4
+ data.tar.gz: 4c9f5e3edf56c6dad2d887e4653d358850255dbf9682e0a6fcc8261e0e3a543f
5
5
  SHA512:
6
- metadata.gz: 5682fb0676abd4d9a69ecee1193a332ed7d580ea5d8f37919d2925da01d64a4f911cb042ec0ec8e72e39479f75f3cb3fdfac3d640a178dd3d70f3b7c41bdf396
7
- data.tar.gz: edc9f5b0994db202b3b9b94838efeec9ecc26f7d52e05e8fc73c35a6c22e10ff969e9065cb66a51c2151c31c93fea9e07f6a6277c420fbd6832ba58fe510f69d
6
+ metadata.gz: 7526987cc970e87b387154632256c89190b8cb7ec9fb9cfe9f1fe2364e73a46cabe81ecbe6a6707e8d5c7ca2c3a5f1591f2bf27d8b63a4e801ff69fcfefa1f11
7
+ data.tar.gz: eeb1628660e72e1d655e428c0640b6255ba43794db4704b42293eee6975a7f1a157c345ba6f2e87e8952af4198750d7aa271f7c925c4977d8f50e0f3e8fdb837
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rpw (1.0.1)
4
+ rpw (1.1.0)
5
+ cli-ui
5
6
  excon
6
7
  thor
7
8
  thor-hollaback
@@ -10,6 +11,7 @@ GEM
10
11
  remote: https://rubygems.org/
11
12
  specs:
12
13
  ast (2.4.1)
14
+ cli-ui (1.4.0)
13
15
  excon (0.78.0)
14
16
  hollaback (0.1.0)
15
17
  minitest (5.14.2)
data/HISTORY.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 1.1.0
2
+
3
+ * sick colors
4
+
1
5
  ## 1.0.1
2
6
 
3
7
  * Pre-launch bugfix
@@ -34,8 +34,8 @@ Here are some important commands for you to know:
34
34
  $ rpw lesson next | Proceed to the next part of the workshop.
35
35
  $ rpw lesson complete | Mark current lesson as complete.
36
36
  $ rpw lesson list | List all workshop lessons. Note each lesson is preceded with an ID.
37
- $ rpw lesson download | Download any or all lessons. Use the IDs from "list".
38
- $ rpw lesson show | Show any particular workshop lesson. Use the IDs from "list".
37
+ $ rpw lesson download | Download all lessons. Useful for offline access.
38
+ $ rpw lesson show | Show any particular workshop lesson.
39
39
  $ rpw progress | Show where you're currently at in the workshop.
40
40
  ```
41
41
 
@@ -6,11 +6,13 @@ require "rpw/cli/sub_command_base"
6
6
  require "rpw/cli/key"
7
7
  require "rpw/cli/lesson"
8
8
  require "rpw/cli/progress"
9
+ require "cli/ui"
10
+
11
+ CLI::UI::StdoutRouter.enable
9
12
 
10
13
  module RPW
11
14
  class CLI < Thor
12
15
  class_before :check_version
13
- class_before :check_setup
14
16
 
15
17
  desc "key register [EMAIL_ADDRESS]", "Change email registered w/Speedshop"
16
18
  subcommand "key", Key
@@ -28,7 +30,7 @@ module RPW
28
30
  warn_if_already_started
29
31
 
30
32
  print_banner
31
- say "Welcome to the Rails Performance Workshop."
33
+ say "\u{1F48E} Welcome to the Rails Performance Workshop. \u{1F48E}"
32
34
  say ""
33
35
  say "This is rpw, the command line client for this workshop."
34
36
  say ""
@@ -36,14 +38,22 @@ module RPW
36
38
  say "working directory, so it's best to run this client from a new directory"
37
39
  say "that you'll use as your 'scratch space' for working on the Workshop."
38
40
  say ""
39
- say "We will create a handful of new files and folders in the current directory."
40
- return unless yes? "Is this OK? (y/N) (N will quit)"
41
- puts ""
42
- say "We'll also create a .rpw_info file at #{File.expand_path("~/.rpw")} to save your purchase key."
43
- home_dir_ok = yes?("Is this OK? (y/N) (N will create it in the current directory)")
44
- client.directory_setup(home_dir_ok)
45
41
 
46
- key = ask("Your Purchase Key: ")
42
+ ans = ::CLI::UI.confirm "Create files and folders in this directory? (no will quit)"
43
+
44
+ exit(1) unless ans
45
+
46
+ say ""
47
+
48
+ ans = ::CLI::UI::Prompt.ask("Where should we save your course progress?",
49
+ options: [
50
+ "here",
51
+ "my home directory (~/.rpw)"
52
+ ])
53
+
54
+ client.directory_setup((ans == "my home directory (~/.rpw)"))
55
+
56
+ key = ::CLI::UI::Prompt.ask("Your Purchase Key: ")
47
57
 
48
58
  unless client.setup(key)
49
59
  say "That is not a valid key. Please try again."
@@ -73,8 +83,8 @@ module RPW
73
83
 
74
84
  def warn_if_already_started
75
85
  return unless client.setup?
76
- exit(0) unless yes? "You have already started the workshop. Continuing "\
77
- "this command will wipe all of your current progress. Continue? (y/N)"
86
+ exit(0) unless ::CLI::UI.confirm "You have already started the workshop. Continuing "\
87
+ "this command will wipe all of your current progress. Continue?", default: false
78
88
  end
79
89
 
80
90
  def check_version
@@ -83,12 +93,5 @@ module RPW
83
93
  say "WARNING: Please run `$ gem install rpw`"
84
94
  end
85
95
  end
86
-
87
- def check_setup
88
- unless client.setup? || current_command_chain == [:start]
89
- say "WARNING: You do not have a purchase key set. Run `$ rpw start`"
90
- exit(0)
91
- end
92
- end
93
96
  end
94
97
  end
@@ -1,10 +1,9 @@
1
1
  module RPW
2
2
  class Lesson < SubCommandBase
3
- class_before :exit_with_no_key
4
-
5
3
  desc "next", "Proceed to the next lesson of the workshop"
6
4
  option :"no-open"
7
5
  def next
6
+ exit_with_no_key
8
7
  say "Proceeding to next lesson..."
9
8
  content = client.next
10
9
 
@@ -28,27 +27,56 @@ module RPW
28
27
 
29
28
  desc "list", "Show all available workshop lessons"
30
29
  def list
31
- say "All available workshop lessons:"
32
- say "Use [ID] for the show/download command"
33
- say "[ID]: Lesson Name"
30
+ ::CLI::UI::Frame.open("{{*}} {{bold:All Lessons}}", color: :green)
31
+
32
+ frame_open = false
34
33
  client.list.each do |lesson|
35
- puts "[#{lesson["position"]}]:#{" " * lesson["indent"]} #{lesson["title"]}"
34
+ if lesson["title"].start_with?("Section")
35
+ ::CLI::UI::Frame.close(nil) if frame_open
36
+ ::CLI::UI::Frame.open(lesson["title"])
37
+ frame_open = true
38
+ next
39
+ end
40
+
41
+ case lesson["style"]
42
+ when "video"
43
+ puts ::CLI::UI.fmt "{{red:#{lesson["title"]}}}"
44
+ when "quiz"
45
+ # puts ::CLI::UI.fmt "{{green:#{" " + lesson["title"]}}}"
46
+ when "lab"
47
+ puts ::CLI::UI.fmt "{{yellow:#{" " + lesson["title"]}}}"
48
+ when "text"
49
+ puts ::CLI::UI.fmt "{{magenta:#{" " + lesson["title"]}}}"
50
+ else
51
+ puts ::CLI::UI.fmt "{{magenta:#{" " + lesson["title"]}}}"
52
+ end
36
53
  end
54
+
55
+ ::CLI::UI::Frame.close(nil)
56
+ ::CLI::UI::Frame.close(nil, color: :green)
37
57
  end
38
58
 
39
- desc "download [CONTENT | all]", "Download one or all workshop contents"
40
- def download(content_pos)
41
- to_download = if content_pos.downcase == "all"
42
- client.list
43
- else
44
- [client.show(content_pos)]
59
+ desc "download", "Download all workshop contents"
60
+ def download
61
+ exit_with_no_key
62
+ total = client.list.size
63
+ client.list.each do |content|
64
+ current = client.list.index(content)
65
+ puts "Downloading #{content["title"]} (#{current}/#{total})"
66
+ client.download_and_extract(content)
45
67
  end
46
- to_download.each { |content| client.download_and_extract(content) }
47
68
  end
48
69
 
49
- desc "show [CONTENT]", "Show any workshop lesson, shows current lesson w/no arguments"
70
+ desc "show", "Show any individal workshop lesson"
50
71
  option :"no-open"
51
- def show(content_order = :current)
72
+ def show
73
+ exit_with_no_key
74
+ title = ::CLI::UI::Prompt.ask(
75
+ "Which lesson would you like to view?",
76
+ options: client.list.reject { |l| l["title"] == "Quiz" }.map { |l| " " * l["indent"] + l["title"] }
77
+ )
78
+ title.strip!
79
+ content_order = client.list.find { |l| l["title"] == title }["position"]
52
80
  content = client.show(content_order)
53
81
  client.download_and_extract(content)
54
82
  display_content(content, !options[:"no-open"])
@@ -1,7 +1,5 @@
1
1
  module RPW
2
2
  class Progress < SubCommandBase
3
- class_before :exit_with_no_key
4
-
5
3
  desc "set [LESSON]", "Set current lesson to a particular lesson"
6
4
  def set(pos)
7
5
  lesson = client.set_progress(pos.to_i)
@@ -10,7 +8,7 @@ module RPW
10
8
 
11
9
  desc "reset", "Erase all progress and start over"
12
10
  def reset
13
- return unless yes? "Are you sure you want to reset your progress? (Y/N)"
11
+ return unless ::CLI::UI.confirm("Are you sure you want to erase all of your progress?", default: false)
14
12
  say "Resetting progress."
15
13
  client.set_progress(nil)
16
14
  end
@@ -18,12 +16,18 @@ module RPW
18
16
  desc "show", "Show current workshop progress"
19
17
  def show
20
18
  data = client.progress
21
- say "The Rails Performance Workshop"
22
- say "You have completed #{data[:completed]} out of #{data[:total]} total sections."
23
- say "Current lesson: #{data[:current_lesson]["title"]}" if data[:current_lesson]
24
- say "Progress by Section (X == completed, O == current):"
25
- data[:sections].each do |section|
26
- say "#{section[:title]}: #{section[:progress]}"
19
+ ::CLI::UI::Frame.open("The Rails Performance Workshop", timing: false, color: :red) do
20
+ say "You have completed #{data[:completed]} out of #{data[:total]} total sections."
21
+ say ""
22
+ say "Current lesson: #{data[:current_lesson]["title"]}" if data[:current_lesson]
23
+ say ""
24
+ ::CLI::UI::Frame.open("Progress", timing: false, color: :red) do
25
+ puts ::CLI::UI.fmt "{{i}} (X == completed, O == current)"
26
+ say ""
27
+ data[:sections].each do |section|
28
+ say "#{section[:title]}: #{section[:progress]}"
29
+ end
30
+ end
27
31
  end
28
32
  end
29
33
 
@@ -14,8 +14,8 @@ module RPW
14
14
  def question(data)
15
15
  puts data["prompt"]
16
16
  data["answer_choices"].each { |ac| puts ac }
17
- provided_answer = ask("Your answer?")
18
- answer_digest = Digest::MD5.hexdigest(data["prompt"] + provided_answer.upcase)
17
+ provided_answer = ::CLI::UI::Prompt.ask("Your answer?", options: %w[A B C D])
18
+ answer_digest = Digest::MD5.hexdigest(data["prompt"] + provided_answer)
19
19
  if answer_digest == data["answer_digest"]
20
20
  say "Correct!"
21
21
  else
@@ -44,8 +44,7 @@ module RPW
44
44
  end
45
45
 
46
46
  def show(content_pos)
47
- content_pos = current_position if content_pos == :current
48
- gateway.get_content_by_position(content_pos)
47
+ list.find { |l| l["position"] == content_pos }
49
48
  end
50
49
 
51
50
  def directory_setup(home_dir_ok = true)
@@ -20,8 +20,8 @@ module RPW
20
20
  begin
21
21
  File.open(filestore_location, "w") { |f| f.write(YAML.dump(data)) }
22
22
  rescue
23
- raise Error, "The RPW data at #{filestore_location} is not writable. \
24
- Check your file permissions."
23
+ # raise Error, "The RPW data at #{filestore_location} is not writable. \
24
+ # Check your file permissions."
25
25
  end
26
26
  end
27
27
 
@@ -16,16 +16,6 @@ module RPW
16
16
  Excon.get(domain + "/license", user: key).status == 200
17
17
  end
18
18
 
19
- def get_content_by_position(position)
20
- response = Excon.get(domain + "/contents/positional?position=#{position}", user: @key)
21
- if response.status == 200
22
- JSON.parse(response.body)
23
- else
24
- puts response.inspect
25
- raise Error, "There was a problem fetching this content."
26
- end
27
- end
28
-
29
19
  def list_content
30
20
  response = Excon.get(domain + "/contents", user: @key)
31
21
  if response.status == 200
@@ -37,21 +27,21 @@ module RPW
37
27
  end
38
28
 
39
29
  def download_content(content, folder:)
40
- puts "Downloading #{content["title"]}..."
41
- downloaded_file = File.open("#{folder}/#{content["s3_key"]}.partial", "w")
42
- streamer = lambda do |chunk, remaining_bytes, total_bytes|
43
- downloaded_file.write(chunk)
44
- print 13.chr
45
- print "Remaining: #{(remaining_bytes.to_f / total_bytes * 100).round(2).to_s.rjust(8)}%" if remaining_bytes
46
- end
47
- response = Excon.get(content["url"], response_block: streamer)
48
- unless response.status == 200
49
- puts response.inspect
50
- raise Error.new("Server problem: #{response.status}")
30
+ ::CLI::UI::Progress.progress do |bar|
31
+ downloaded_file = File.open("#{folder}/#{content["s3_key"]}.partial", "w")
32
+ streamer = lambda do |chunk, remaining_bytes, total_bytes|
33
+ downloaded_file.write(chunk)
34
+ bar.tick(set_percent: 1 - (remaining_bytes.to_f / total_bytes).round(2))
35
+ end
36
+ response = Excon.get(content["url"], response_block: streamer)
37
+ unless response.status == 200
38
+ puts response.inspect
39
+ raise Error.new("Server problem: #{response.status}")
40
+ end
41
+ downloaded_file.close
42
+ File.rename(downloaded_file, "#{folder}/#{content["s3_key"]}")
43
+ bar.tick(set_percent: 1)
51
44
  end
52
- downloaded_file.close
53
- print "\n"
54
- File.rename(downloaded_file, "#{folder}/#{content["s3_key"]}")
55
45
  end
56
46
 
57
47
  def latest_version?
@@ -1,3 +1,3 @@
1
1
  module RPW
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -27,4 +27,5 @@ Gem::Specification.new do |spec|
27
27
  spec.add_dependency "thor"
28
28
  spec.add_dependency "thor-hollaback"
29
29
  spec.add_dependency "excon"
30
+ spec.add_dependency "cli-ui"
30
31
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rpw
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nate Berkopec
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: cli-ui
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  description:
56
70
  email:
57
71
  - nate@speedshop.co