dev-ui 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: '0088aa409f65b6130d130f404bb71662a06a6f3d'
4
- data.tar.gz: a1a7e7da5c2b8534882f67b22953d4fe886f4d4b
3
+ metadata.gz: cb7feeed4cd2083e294dd368521e85d4240cb954
4
+ data.tar.gz: d87bb0bab774010578bfaed70966e87e8a0222b6
5
5
  SHA512:
6
- metadata.gz: d8dc9c83e8145df6ba606ad805b9c2fd1444c372ad00cbd34e534878ba1a3f0180d00488371cac76706f22bd4d8335e1dc51a3b144fc00e08496ecd07eac471e
7
- data.tar.gz: b89f0a81a0840ed0ffde9b9f118ae4d9552b0ac4fde6505158a63ecd2bddcb4fdc8a1a74db78ffd9a7a0a27acc970cc68321905a1cfa89135299d1ad2883e2f0
6
+ metadata.gz: b371ef8177c5d3626d75c940d56b3afa40924a70fbdc0bb941b3f33c1e5253eb41118a023c6c3a72e92bd15df2bacc65dc361874cc9f4dd08162d402c9215100
7
+ data.tar.gz: 0dfc477dd137c74de7a99336478c7c120c3cd394c5e259e2b758a6777a7d1fe1eae0ab859c0728c9a224d80bd0f28601e5c2088488bf4ba4025c32dc0b42005f
data/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
1
  # NOTE: These are development-only dependencies
2
2
  source "https://rubygems.org"
3
3
 
4
+ gemspec
5
+
4
6
  group :development, :test do
5
7
  gem 'rubocop'
6
8
  gem 'byebug'
data/Gemfile.lock CHANGED
@@ -1,3 +1,8 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ dev-ui (0.1.0)
5
+
1
6
  GEM
2
7
  remote: https://rubygems.org/
3
8
  specs:
@@ -21,7 +26,7 @@ GEM
21
26
  powerpack (0.1.1)
22
27
  rainbow (2.2.2)
23
28
  rake
24
- rake (12.0.0)
29
+ rake (10.5.0)
25
30
  rubocop (0.49.1)
26
31
  parallel (~> 1.10)
27
32
  parser (>= 2.3.3.1, < 3.0)
@@ -36,12 +41,15 @@ PLATFORMS
36
41
  ruby
37
42
 
38
43
  DEPENDENCIES
44
+ bundler (~> 1.15)
39
45
  byebug
46
+ dev-ui!
40
47
  method_source
41
48
  minitest (>= 5.0.0)
42
49
  minitest-reporters
43
50
  mocha
51
+ rake (~> 10.0)
44
52
  rubocop
45
53
 
46
54
  BUNDLED WITH
47
- 1.15.0
55
+ 1.16.0
data/README.md CHANGED
@@ -1,3 +1,125 @@
1
+ Dev UI
2
+ ---
3
+
4
+ Dev UI is a small framework who's only responsibility is to print pretty to the terminal
5
+
6
+ - [Master Documentation](http://www.rubydoc.info/github/Shopify/dev-ui/master/Dev/UI)
7
+ - [Documentation of the Rubygems version](http://www.rubydoc.info/gems/dev-ui/)
8
+ - [Rubygems](https://rubygems.org/gems/dev-ui)
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ gem install dev-ui
14
+ ```
15
+
16
+ or add the following to your Gemfile:
17
+
18
+ ```ruby
19
+ gem 'dev-ui'
20
+ ```
21
+
22
+ In your code, simply add a `require 'dev/ui'`. Most options assume `Dev::UI::StdoutRouter.enable` has been called.
23
+
24
+ ## Features
25
+
26
+ This may not be an exhaustive list. Please check our [documentation](http://www.rubydoc.info/github/Shopify/dev-ui/master/Dev/UI) for more information.
27
+
28
+ ---
29
+
30
+ ### Nested framing
31
+ To handle content flow (see example below)
32
+
33
+ ```ruby
34
+ Dev::UI::StdoutRouter.enable
35
+ Dev::UI::Frame.open('Frame 1') do
36
+ Dev::UI::Frame.open('Frame 2') { puts "inside frame 2" }
37
+ puts "inside frame 1"
38
+ end
39
+ ```
40
+
41
+ ![Nested Framing](https://user-images.githubusercontent.com/3074765/33799861-cb5dcb5c-dd01-11e7-977e-6fad38cee08c.png)
42
+
43
+ ---
44
+
45
+ ### Interactive Prompts
46
+ Prompt user with options and ask them to choose. Can answer using arrow keys, numbers, or vim bindings (or y/n for yes/no questions)
47
+
48
+ ```ruby
49
+ Dev::UI.ask('What language/framework do you use?', options: %w(rails go ruby python))
50
+ Dev::UI::InteractivePrompt.call(%w(rails go ruby python))
51
+ ```
52
+
53
+ ![Interactive Prompt](https://user-images.githubusercontent.com/3074765/33797984-0ebb5e64-dcdf-11e7-9e7e-7204f279cece.gif)
54
+
55
+ ---
56
+
57
+ ### Free form text prompts
58
+
59
+ ```ruby
60
+ Dev::UI.ask('Is Dev UI Awesome?', default: 'It is great!')
61
+ ```
62
+
63
+ ![Free form text prompt](https://user-images.githubusercontent.com/3074765/33799822-47f23302-dd01-11e7-82f3-9072a5a5f611.png)
64
+
65
+ ---
66
+
67
+ ### Spinner groups
68
+ Handle many multi-threaded processes while suppressing output unless there is an issue. Can update title to show state.
69
+
70
+ ```ruby
71
+ spin_group = Dev::UI::SpinGroup.new
72
+ spin_group.add('Title') { |spinner| sleep 3.0 }
73
+ spin_group.add('Title 2') { |spinner| sleep 3.0; spinner.update_title('New Title'); sleep 3.0 }
74
+ spin_group.wait
75
+ ```
76
+
77
+ ![Spinner Group](https://user-images.githubusercontent.com/3074765/33798295-d94fd822-dce3-11e7-819b-43e5502d490e.gif)
78
+
79
+ ---
80
+
81
+ ### Text Color formatting
82
+ e.g. `{{red:Red}} {{green:Green}}`
83
+
84
+ ```ruby
85
+ puts Dev::UI.fmt "{{red:Red}} {{green:Green}}"
86
+ ```
87
+
88
+ ![Text Format](https://user-images.githubusercontent.com/3074765/33799827-6d0721a2-dd01-11e7-9ab5-c3d455264afe.png)
89
+
90
+ ---
91
+
92
+ ### Symbol/Glyph Formatting
93
+ e.g. `{{*}}` => a yellow ⭑
94
+
95
+ ```ruby
96
+ puts Dev::UI.fmt "{{*}} {{x}} {{?}} {{v}}"
97
+ ```
98
+
99
+ ![Symbol Formatting](https://user-images.githubusercontent.com/3074765/33799847-9ec03fd0-dd01-11e7-93f7-5f5cc540e61e.png)
100
+
101
+ ---
102
+
103
+ ### Progress Bar
104
+
105
+ Show progress of a process or operation.
106
+
107
+ ```ruby
108
+ Dev::UI::Progress.progress do |bar|
109
+ 100.times do
110
+ bar.tick
111
+ end
112
+ end
113
+ ```
114
+
115
+ ![Progress Bar](https://user-images.githubusercontent.com/3074765/33799794-cc4c940e-dd00-11e7-9bdc-90f77ec9167c.gif)
116
+
117
+ ---
118
+
119
+ ## Example Usage
120
+
121
+ The following code makes use of nested-framing, multi-threaded spinners, formatted text, and more.
122
+
1
123
  ```ruby
2
124
  require 'dev/ui'
3
125
 
@@ -7,16 +129,24 @@ Dev::UI::Frame.open('{{*}} {{bold:a}}', color: :green) do
7
129
  Dev::UI::Frame.open('{{i}} b', color: :magenta) do
8
130
  Dev::UI::Frame.open('{{?}} c', color: :cyan) do
9
131
  sg = Dev::UI::SpinGroup.new
10
- sg.add('wow') { sleep(2.5) }
132
+ sg.add('wow') do |spinner|
133
+ sleep(2.5)
134
+ spinner.update_title('second round!')
135
+ sleep (1.0)
136
+ end
11
137
  sg.add('such spin') { sleep(1.6) }
12
138
  sg.add('many glyph') { sleep(2.0) }
13
139
  sg.wait
14
140
  end
15
141
  end
16
142
  Dev::UI::Frame.divider('{{v}} lol')
17
- puts 'words'
143
+ puts Dev::UI.fmt '{{info:words}} {{red:oh no!}} {{green:success!}}'
18
144
  sg = Dev::UI::SpinGroup.new
19
145
  sg.add('more spins') { sleep(0.5) ; raise 'oh no' }
20
146
  sg.wait
21
147
  end
22
148
  ```
149
+
150
+ Output:
151
+
152
+ ![Example Output](https://user-images.githubusercontent.com/3074765/33797758-7a54c7cc-dcdb-11e7-918e-a47c9689f068.gif)
data/dev.yml CHANGED
@@ -1,5 +1,4 @@
1
1
  up:
2
- - homebrew:
3
2
  - ruby: 2.3.3
4
3
  - bundler
5
4
 
data/lib/dev/ui.rb CHANGED
@@ -12,16 +12,27 @@ module Dev
12
12
  autoload :Formatter, 'dev/ui/formatter'
13
13
  autoload :Spinner, 'dev/ui/spinner'
14
14
 
15
-
16
- # TODO: this, better
15
+ # Convenience accessor to +Dev::UI::Spinner::SpinGroup+
17
16
  SpinGroup = Spinner::SpinGroup
18
17
 
19
- # TODO: test
18
+ # Glyph resolution using +Dev::UI::Glyph.lookup+
19
+ # Look at the method signature for +Glyph.lookup+ for more details
20
+ #
21
+ # ==== Attributes
22
+ #
23
+ # * +handle+ - handle of the glyph to resolve
24
+ #
20
25
  def self.glyph(handle)
21
26
  Dev::UI::Glyph.lookup(handle)
22
27
  end
23
28
 
24
- # TODO: test
29
+ # Color resolution using +Dev::UI::Color.lookup+
30
+ # Will lookup using +Color.lookup+ if a symbol, otherwise we assume it is a valid color and return it
31
+ #
32
+ # ==== Attributes
33
+ #
34
+ # * +input+ - color to resolve
35
+ #
25
36
  def self.resolve_color(input)
26
37
  case input
27
38
  when Symbol
@@ -31,35 +42,96 @@ module Dev
31
42
  end
32
43
  end
33
44
 
45
+ # Conviencence Method for +Dev::UI::Prompt.confirm+
46
+ #
47
+ # ==== Attributes
48
+ #
49
+ # * +question+ - question to confirm
50
+ #
34
51
  def self.confirm(question)
35
52
  Dev::UI::Prompt.confirm(question)
36
53
  end
37
54
 
55
+ # Conviencence Method for +Dev::UI::Prompt.ask+
56
+ #
57
+ # ==== Attributes
58
+ #
59
+ # * +question+ - question to ask
60
+ # * +kwargs+ - arugments for +Prompt.ask+
61
+ #
38
62
  def self.ask(question, **kwargs)
39
63
  Dev::UI::Prompt.ask(question, **kwargs)
40
64
  end
41
65
 
66
+ # Conviencence Method to resolve text using +Dev::UI::Formatter.format+
67
+ # Check +Dev::UI::Formatter::SGR_MAP+ for available formatting options
68
+ #
69
+ # ==== Attributes
70
+ #
71
+ # * +input+ - input to format
72
+ #
42
73
  def self.resolve_text(input)
43
74
  return input if input.nil?
44
75
  Dev::UI::Formatter.new(input).format
45
76
  end
46
77
 
78
+ # Conviencence Method to format text using +Dev::UI::Formatter.format+
79
+ # Check +Dev::UI::Formatter::SGR_MAP+ for available formatting options
80
+ #
81
+ # https://user-images.githubusercontent.com/3074765/33799827-6d0721a2-dd01-11e7-9ab5-c3d455264afe.png
82
+ # https://user-images.githubusercontent.com/3074765/33799847-9ec03fd0-dd01-11e7-93f7-5f5cc540e61e.png
83
+ #
84
+ # ==== Attributes
85
+ #
86
+ # * +input+ - input to format
87
+ #
88
+ # ==== Options
89
+ #
90
+ # * +enable_color+ - should color be used? default to true
91
+ #
47
92
  def self.fmt(input, enable_color: true)
48
93
  Dev::UI::Formatter.new(input).format(enable_color: enable_color)
49
94
  end
50
95
 
96
+ # Conviencence Method for +Dev::UI::Frame.open+
97
+ #
98
+ # ==== Attributes
99
+ #
100
+ # * +args+ - arguments for +Frame.open+
101
+ # * +block+ - block for +Frame.open+
102
+ #
51
103
  def self.frame(*args, &block)
52
104
  Dev::UI::Frame.open(*args, &block)
53
105
  end
54
106
 
107
+ # Conviencence Method for +Dev::UI::Spinner.spin+
108
+ #
109
+ # ==== Attributes
110
+ #
111
+ # * +args+ - arguments for +Spinner.open+
112
+ # * +block+ - block for +Spinner.open+
113
+ #
55
114
  def self.spinner(*args, &block)
56
115
  Dev::UI::Spinner.spin(*args, &block)
57
116
  end
58
117
 
118
+ # Conviencence Method to override frame color using +Dev::UI::Frame.with_frame_color+
119
+ #
120
+ # ==== Attributes
121
+ #
122
+ # * +color+ - color to override to
123
+ # * +block+ - block for +Frame.with_frame_color_override+
124
+ #
59
125
  def self.with_frame_color(color, &block)
60
126
  Dev::UI::Frame.with_frame_color_override(color, &block)
61
127
  end
62
128
 
129
+ # Duplicate output to a file path
130
+ #
131
+ # ==== Attributes
132
+ #
133
+ # * +path+ - path to duplicate output to
134
+ #
63
135
  def self.log_output_to(path)
64
136
  if Dev::UI::StdoutRouter.duplicate_output_to
65
137
  raise "multiple logs not allowed"
@@ -73,6 +145,12 @@ module Dev
73
145
  end
74
146
  end
75
147
 
148
+ # Disable all framing within a block
149
+ #
150
+ # ==== Attributes
151
+ #
152
+ # * +block+ - block in which to disable frames
153
+ #
76
154
  def self.raw
77
155
  prev = Thread.current[:no_devui_frame_inset]
78
156
  Thread.current[:no_devui_frame_inset] = true
data/lib/dev/ui/ansi.rb CHANGED
@@ -7,9 +7,9 @@ module Dev
7
7
 
8
8
  # ANSI escape sequences (like \x1b[31m) have zero width.
9
9
  # when calculating the padding width, we must exclude them.
10
- # This also implements a *reaaaallly* shitty version of utf8 character
11
- # width calculation like we could get for real from something like
12
- # utf8proc.
10
+ # This also implements a basic version of utf8 character width calculation like
11
+ # we could get for real from something like utf8proc.
12
+ #
13
13
  def self.printing_width(str)
14
14
  zwj = false
15
15
  strip_codes(str).codepoints.reduce(0) do |acc, cp|
@@ -27,10 +27,23 @@ module Dev
27
27
  end
28
28
  end
29
29
 
30
+ # Strips ANSI codes from a str
31
+ #
32
+ # ==== Attributes
33
+ #
34
+ # - +str+ - The string from which to strip codes
35
+ #
30
36
  def self.strip_codes(str)
31
37
  str.gsub(/\x1b\[[\d;]+[A-z]|\r/, '')
32
38
  end
33
39
 
40
+ # Returns an ANSI control sequence
41
+ #
42
+ # ==== Attributes
43
+ #
44
+ # - +args+ - Argument to pass to the ANSI control sequence
45
+ # - +cmd+ - ANSI control sequence Command
46
+ #
34
47
  def self.control(args, cmd)
35
48
  ESC + "[" + args + cmd
36
49
  end
@@ -42,50 +55,98 @@ module Dev
42
55
 
43
56
  # Cursor Movement
44
57
 
58
+ # Move the cursor up n lines
59
+ #
60
+ # ==== Attributes
61
+ #
62
+ # * +n+ - number of lines by which to move the cursor up
63
+ #
45
64
  def self.cursor_up(n = 1)
46
65
  return '' if n.zero?
47
66
  control(n.to_s, 'A')
48
67
  end
49
68
 
69
+ # Move the cursor down n lines
70
+ #
71
+ # ==== Attributes
72
+ #
73
+ # * +n+ - number of lines by which to move the cursor down
74
+ #
50
75
  def self.cursor_down(n = 1)
51
76
  return '' if n.zero?
52
77
  control(n.to_s, 'B')
53
78
  end
54
79
 
80
+ # Move the cursor forward n columns
81
+ #
82
+ # ==== Attributes
83
+ #
84
+ # * +n+ - number of columns by which to move the cursor forward
85
+ #
55
86
  def self.cursor_forward(n = 1)
56
87
  return '' if n.zero?
57
88
  control(n.to_s, 'C')
58
89
  end
59
90
 
91
+ # Move the cursor back n columns
92
+ #
93
+ # ==== Attributes
94
+ #
95
+ # * +n+ - number of columns by which to move the cursor back
96
+ #
60
97
  def self.cursor_back(n = 1)
61
98
  return '' if n.zero?
62
99
  control(n.to_s, 'D')
63
100
  end
64
101
 
102
+ # Move the cursor to a specific column
103
+ #
104
+ # ==== Attributes
105
+ #
106
+ # * +n+ - The column to move to
107
+ #
65
108
  def self.cursor_horizontal_absolute(n = 1)
66
109
  control(n.to_s, 'G')
67
110
  end
68
111
 
69
- # Cursor Visibility
70
-
112
+ # Show the cursor
113
+ #
71
114
  def self.show_cursor
72
115
  control('', "?25h")
73
116
  end
74
117
 
118
+ # Hide the cursor
119
+ #
75
120
  def self.hide_cursor
76
121
  control('', "?25l")
77
122
  end
78
123
 
79
- # Line Handling
124
+ # Save the cursor position
125
+ #
126
+ def self.cursor_save
127
+ control('', 's')
128
+ end
129
+
130
+ # Restore the saved cursor position
131
+ #
132
+ def self.cursor_restore
133
+ control('', 'u')
134
+ end
80
135
 
136
+ # Move to the next line
137
+ #
81
138
  def self.next_line
82
139
  cursor_down + control('1', 'G')
83
140
  end
84
141
 
142
+ # Move to the previous line
143
+ #
85
144
  def self.previous_line
86
145
  cursor_up + control('1', 'G')
87
146
  end
88
147
 
148
+ # Move to the end of the line
149
+ #
89
150
  def self.end_of_line
90
151
  control("\033[", 'C')
91
152
  end