rpw 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -1
- data/HISTORY.md +4 -0
- data/lib/rpw/README.md +2 -2
- data/lib/rpw/cli.rb +21 -18
- data/lib/rpw/cli/lesson.rb +43 -15
- data/lib/rpw/cli/progress.rb +13 -9
- data/lib/rpw/cli/quiz.rb +2 -2
- data/lib/rpw/client.rb +1 -2
- data/lib/rpw/client_data.rb +2 -2
- data/lib/rpw/gateway.rb +14 -24
- data/lib/rpw/version.rb +1 -1
- data/rpw.gemspec +1 -0
- metadata +15 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 317f37137765f78e5a587b36e3ecb4898d18e4b011cc3ef67f60d5d0e710c6d8
|
4
|
+
data.tar.gz: 4c9f5e3edf56c6dad2d887e4653d358850255dbf9682e0a6fcc8261e0e3a543f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7526987cc970e87b387154632256c89190b8cb7ec9fb9cfe9f1fe2364e73a46cabe81ecbe6a6707e8d5c7ca2c3a5f1591f2bf27d8b63a4e801ff69fcfefa1f11
|
7
|
+
data.tar.gz: eeb1628660e72e1d655e428c0640b6255ba43794db4704b42293eee6975a7f1a157c345ba6f2e87e8952af4198750d7aa271f7c925c4977d8f50e0f3e8fdb837
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rpw (1.0
|
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
data/lib/rpw/README.md
CHANGED
@@ -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
|
38
|
-
$ rpw lesson show | Show any particular workshop lesson.
|
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
|
|
data/lib/rpw/cli.rb
CHANGED
@@ -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
|
-
|
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
|
77
|
-
"this command will wipe all of your current progress. Continue?
|
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
|
data/lib/rpw/cli/lesson.rb
CHANGED
@@ -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
|
-
|
32
|
-
|
33
|
-
|
30
|
+
::CLI::UI::Frame.open("{{*}} {{bold:All Lessons}}", color: :green)
|
31
|
+
|
32
|
+
frame_open = false
|
34
33
|
client.list.each do |lesson|
|
35
|
-
|
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
|
40
|
-
def download
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
70
|
+
desc "show", "Show any individal workshop lesson"
|
50
71
|
option :"no-open"
|
51
|
-
def show
|
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"])
|
data/lib/rpw/cli/progress.rb
CHANGED
@@ -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
|
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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
|
data/lib/rpw/cli/quiz.rb
CHANGED
@@ -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
|
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
|
data/lib/rpw/client.rb
CHANGED
data/lib/rpw/client_data.rb
CHANGED
@@ -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
|
-
|
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
|
|
data/lib/rpw/gateway.rb
CHANGED
@@ -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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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?
|
data/lib/rpw/version.rb
CHANGED
data/rpw.gemspec
CHANGED
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
|
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
|