cork 0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f69595883925c08a5f98b7efc4a3ad1cf121ed6e
4
+ data.tar.gz: 210dc43c15f92df038158ee8b1c2eb68f1b14274
5
+ SHA512:
6
+ metadata.gz: 13fb39df2ac37a8029147de9e138a40a68581d0e192f29525d967c2e5716b6494ed98a950138aa19b6221a277724d07d7ceea469b620cdc77064b02d70e777dc
7
+ data.tar.gz: 8357f4c295ea96d1137a187536b85cd55fd5e0a7cbb0f8e04b9e45fd32baad4711a5523031ca16efe415fa8dd82d6df25db354ee5bfd1474f3e95c0357db8950
@@ -0,0 +1,3 @@
1
+ ## Master
2
+
3
+ This version is extracted from CocoaPods.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,55 @@
1
+ # Cork
2
+
3
+ A delightful CLI UI module.
4
+
5
+ ## Usage
6
+
7
+ ```ruby
8
+ board = Cork::Board.new()
9
+ ```
10
+
11
+ You can use Cork to print simple messages.
12
+
13
+ ```ruby
14
+ board.puts('Hello World')
15
+ ```
16
+
17
+ You can use notice to print notices to the user colored in green.
18
+
19
+ ```ruby
20
+ board.notice("We're out of 🍷.")
21
+ ```
22
+
23
+ This is an example of Cork used to build a simple list.
24
+
25
+ ```ruby
26
+ board.section('Types of Wine') do
27
+ board.labeled('Red', ['Shiraz', 'Merlot'])
28
+ board.labeled('White', ['Gewürztraminer', 'Riesling'])
29
+ end
30
+ ```
31
+
32
+ ```
33
+ Types of Wine
34
+ - Red:
35
+ - Shiraz
36
+ - Merlot
37
+ - White:
38
+ - Gewürztraminer
39
+ - Riesling
40
+ ```
41
+
42
+ This is an example of Cork used to print a warning with actions the user can take.
43
+
44
+ ```ruby
45
+ board.warn('Merlot is down to 1 oz', [
46
+ 'Purchase some more.'
47
+ ])
48
+
49
+ board.print_warnings
50
+ ```
51
+
52
+ ```
53
+ [!] Merlot is down to 1 oz
54
+ - Purchase some more.
55
+ ```
@@ -0,0 +1,5 @@
1
+ module Cork
2
+ require 'cork/board'
3
+ require 'cork/gem_version'
4
+ require 'cork/text_wrapper'
5
+ end
@@ -0,0 +1,348 @@
1
+ require 'colored'
2
+
3
+ module Cork
4
+ # provides support for UI output. Cork provides support for nested
5
+ # sections of information and for a verbose mode.
6
+ #
7
+
8
+ class Board
9
+ # @return [input] The input specification that contains the user input
10
+ # for the UI.
11
+ #
12
+ attr_reader :input
13
+ # @return [output] The output specification containing the UI output.
14
+ attr_reader :out
15
+ # @return [error] The error specification containing the UI error.
16
+ attr_reader :err
17
+ # @return [warnings] The warnings specification containing the UI warnings.
18
+ attr_reader :warnings
19
+ # @return [Bool] Whether the wrapping of the strings to the width of the
20
+ # terminal should be disabled.
21
+ #
22
+ attr_accessor :disable_wrap
23
+ alias_method :disable_wrap?, :disable_wrap
24
+
25
+ attr_reader :verbose
26
+ alias_method :verbose?, :verbose
27
+
28
+ attr_reader :silent
29
+ alias_method :silent?, :silent
30
+
31
+ attr_reader :ansi
32
+ alias_method :ansi?, :ansi
33
+
34
+ attr_accessor :indentation_level
35
+ attr_accessor :title_level
36
+
37
+ # Initialize a new instance.
38
+ #
39
+ # @param [Boolean] verbose When verbose is true verbose output is printed.
40
+ # this defaults to true
41
+ # @param [Boolean] silent When silent is true all output is supressed.
42
+ # This defaults to false.
43
+ # @param [Boolean] ansi When ansi is true output may contain ansi
44
+ # color codes. This is true by default.
45
+ # @param [IO] input The file descriptor to read the user input.
46
+ # @param [IO] out The file descriptor to print all output to.
47
+ # @param [IO] err The file descriptor to print all errors to.
48
+ #
49
+ def initialize(verbose: false, silent: false, ansi: true,
50
+ input: $stdin, out: $stdout, err: $stderr)
51
+
52
+ @input = input
53
+ @out = out
54
+ @err = err
55
+ @verbose = verbose
56
+ @silent = silent
57
+ @ansi = ansi
58
+ @warnings = []
59
+ @title_colors = %w( yellow green )
60
+ @title_level = 0
61
+ @indentation_level = 2
62
+ end
63
+
64
+ # Prints a message followed by a new line unless silent.
65
+ #
66
+ def puts(message = '')
67
+ out.puts(message) unless silent?
68
+ end
69
+
70
+ # Prints a message without a new line unless silent.
71
+ #
72
+ def print(message)
73
+ out.print(message) unless silent?
74
+ end
75
+
76
+ # Prints a message respecting the current indentation level and
77
+ # wrapping it to the terminal width if necessary.
78
+ #
79
+ def puts_indented(message = '')
80
+ indented = wrap_string(message, @indentation_level)
81
+ puts(indented)
82
+ end
83
+
84
+ # Gets input from the configured input.
85
+ #
86
+ def gets
87
+ input.gets
88
+ end
89
+
90
+ # Stores important warning to the user optionally followed by actions that
91
+ # the user should take. To print them use {#print_warnings}.
92
+ #
93
+ # @param [String] message The message to print.
94
+ # @param [Array] actions The actions that the user should take.
95
+ # @param [Boolean] verbose_only When verbose_only is configured to
96
+ # true, the warning will only be printed when
97
+ # Board is configured to print verbose messages.
98
+ # This is false by default.
99
+ #
100
+ # @return [void]
101
+ #
102
+ def warn(message, actions = [], verbose_only = false)
103
+ warnings << {
104
+ :message => message,
105
+ :actions => actions,
106
+ :verbose_only => verbose_only,
107
+ }
108
+ end
109
+
110
+ # The returned path is quoted. If the argument is nil it returns an empty
111
+ # string.
112
+ #
113
+ # @param [#to_str,Nil] pathname
114
+ # The path to return.
115
+ # @param [Pathname] relative_to
116
+ #
117
+ def path(pathname, relative_to = Pathname.pwd)
118
+ if pathname
119
+ path = Pathname(pathname).relative_path_from(relative_to)
120
+ "`#{path}`"
121
+ else
122
+ ''
123
+ end
124
+ end
125
+
126
+ # Prints a message with a label.
127
+ #
128
+ # @param [String] label
129
+ # The label to print.
130
+ #
131
+ # @param [#to_s] value
132
+ # The value to print.
133
+ #
134
+ # @param [FixNum] justification
135
+ # The justification of the label.
136
+ #
137
+ def labeled(label, value, justification = 12)
138
+ if value
139
+ title = "- #{label}:"
140
+ if value.is_a?(Enumerable)
141
+ lines = [wrap_string(title, indentation_level)]
142
+ lines += value.map do |v|
143
+ wrap_string("- #{v}", indentation_level + 2)
144
+ end
145
+ puts lines.join("\n")
146
+ else
147
+ string = title.ljust(justification) + "#{value}"
148
+ puts wrap_string(string, indentation_level)
149
+ end
150
+ end
151
+ end
152
+
153
+ # Prints a title taking an optional verbose prefix and
154
+ # a relative indentation valid for the UI action in the passed
155
+ # block.
156
+ #
157
+ # In verbose mode titles are printed with a color according
158
+ # to their level. In normal mode titles are printed only if
159
+ # they have nesting level smaller than 2.
160
+ #
161
+ # @todo Refactor to title (for always visible titles like search)
162
+ # and sections (titles that represent collapsible sections).
163
+ #
164
+ # @param [String] title
165
+ # The title to print
166
+ #
167
+ # @param [String] verbose_prefix
168
+ # See #message
169
+ #
170
+ # @param [FixNum] relative_indentation
171
+ # The indentation level relative to the current,
172
+ # when the message is printed.
173
+ #
174
+ def section(title, verbose_prefix = '', relative_indentation = 0,
175
+ titled = false)
176
+ if verbose?
177
+ title(title, verbose_prefix, relative_indentation)
178
+ elsif title_level < 1 || titled
179
+ puts title
180
+ end
181
+
182
+ @indentation_level += relative_indentation
183
+ @title_level += 1
184
+ yield if block_given?
185
+ @indentation_level -= relative_indentation
186
+ @title_level -= 1
187
+ end
188
+
189
+ # Prints an info to the user. The info is always displayed.
190
+ # It respects the current indentation level only in verbose
191
+ # mode.
192
+ #
193
+ # Any title printed in the optional block is treated as a message.
194
+ #
195
+ # @param [String] message
196
+ # The message to print.
197
+ #
198
+ def info(message)
199
+ indentation = verbose? ? @indentation_level : 0
200
+ indented = wrap_string(message, indentation)
201
+ puts(indented)
202
+
203
+ if block_given?
204
+ @indentation_level += 2
205
+ @treat_titles_as_messages = true
206
+ yield
207
+ @treat_titles_as_messages = false
208
+ @indentation_level -= 2
209
+ end
210
+ end
211
+
212
+ # A title opposed to a section is always visible
213
+ #
214
+ # @param [String] title
215
+ # The title to print
216
+ #
217
+ # @param [String] verbose_prefix
218
+ # See #message
219
+ #
220
+ # @param [FixNum] relative_indentation
221
+ # The indentation level relative to the current,
222
+ # when the message is printed.
223
+ #
224
+ def title(title, verbose_prefix = '', relative_indentation = 2)
225
+ if @treat_titles_as_messages
226
+ message(title, verbose_prefix)
227
+ else
228
+ puts_title(title, verbose_prefix)
229
+ end
230
+
231
+ if block_given?
232
+ @indentation_level += relative_indentation
233
+ @title_level += 1
234
+ yield
235
+ @indentation_level -= relative_indentation
236
+ @title_level -= 1
237
+ end
238
+ end
239
+
240
+ # Prints a verbose message taking an optional verbose prefix and
241
+ # a relatvie indentation valid for the UI action in the passed block.
242
+ #
243
+ def notice(message)
244
+ line = "\n[!] #{message}"
245
+ line = line.green if ansi?
246
+ puts(line)
247
+ end
248
+
249
+ # @todo Clean interface.
250
+ #
251
+ # @param [String] message
252
+ # The message to print.
253
+ #
254
+ # @param [String] verbose_prefix
255
+ # See #message
256
+ #
257
+ # @param [FixNum] relative_indentation
258
+ # The indentation level relative to the current,
259
+ # when the message is printed.
260
+ #
261
+
262
+ # Prints the stored warnings. This method is intended to be called at the
263
+ # end of the execution of the binary.
264
+ #
265
+ # @return [void]
266
+ #
267
+ def print_warnings
268
+ out.flush
269
+ warnings.each do |warning|
270
+ next if warning[:verbose_only] && !verbose?
271
+
272
+ message = "\n[!] #{warning[:message]}"
273
+ message = message.yellow if ansi?
274
+ err.puts(message)
275
+
276
+ warning[:actions].each do |action|
277
+ string = "- #{action}"
278
+ string = wrap_string(string, 4)
279
+ err.puts(string)
280
+ end
281
+ end
282
+ end
283
+
284
+ # Prints a verbose message taking an optional verbose prefix and
285
+ # a relative indentation valid for the UI action in the passed
286
+ # block.
287
+ #
288
+ # @todo Clean interface.
289
+ #
290
+ def message(message, verbose_prefix = '', relative_indentation = 2)
291
+ message = verbose_prefix + message if verbose?
292
+ puts_indented message if verbose?
293
+
294
+ @indentation_level += relative_indentation
295
+ yield if block_given?
296
+ @indentation_level -= relative_indentation
297
+ end
298
+
299
+ private
300
+
301
+ # @!group Helpers
302
+
303
+ attr_writer :indentation_level
304
+ attr_accessor :title_level
305
+
306
+ # Prints a title taking an optional verbose prefix and
307
+ # a relative indentation valid for the UI action in the passed
308
+ # block.
309
+ #
310
+ # In verbose mode titles are printed with a color according
311
+ # to their level. In normal mode titles are printed only if
312
+ # they have nesting level smaller than 2.
313
+ #
314
+ # @todo Refactor to title (for always visible titles like search)
315
+ # and sections (titles that represent collapsible sections).
316
+ #
317
+ # @param [String] title
318
+ # The title to print
319
+ #
320
+ # @param [String] verbose_prefix
321
+ # See #message
322
+ #
323
+ # @param [FixNum] relative_indentation
324
+ # The indentation level relative to the current,
325
+ # when the message is printed.
326
+ #
327
+
328
+ def wrap_string(string, indent = 0)
329
+ first_space = ' ' * indent
330
+ if disable_wrap
331
+ first_space << string
332
+ else
333
+ columns = out.winsize[1]
334
+ indented = TextWrapper.wrap_with_indent(string, indent, columns)
335
+ first_space << indented
336
+ end
337
+ end
338
+
339
+ def puts_title(title, verbose_prefix)
340
+ title = verbose_prefix + title if verbose?
341
+ title = "\n#{title}" if @title_level < 2
342
+ if ansi? && (color = @title_colors[title_level])
343
+ title = title.send(color)
344
+ end
345
+ puts "#{title}"
346
+ end
347
+ end
348
+ end
@@ -0,0 +1,3 @@
1
+ module Cork
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,76 @@
1
+ # encoding: utf-8
2
+
3
+ module Cork
4
+ module TextWrapper
5
+ # @return [String] Wraps a formatted string (e.g. markdown) by stripping
6
+ # heredoc indentation and wrapping by word to the terminal width
7
+ # taking into account a maximum one, and indenting the string.
8
+ # Code lines (i.e. indented by four spaces) are not wrapped.
9
+ #
10
+ # @param [String] string
11
+ # The string to format.
12
+ #
13
+ # @param [Fixnum] indent
14
+ # The number of spaces to insert before the string.
15
+ #
16
+ # @param [Fixnum] width
17
+ # The width to use to format the string if the terminal
18
+ # is too wide.
19
+ #
20
+ def wrap_formatted_text(string, indent = 0, width = 80)
21
+ paragraphs = strip_heredoc(string).split("\n\n")
22
+ paragraphs = paragraphs.map do |paragraph|
23
+ if paragraph.start_with?(' ' * 4)
24
+ paragraphs.gsub!(/\n/, "\n#{' ' * indent}")
25
+ else
26
+ paragraph = wrap_with_indent(paragraph, indent, width)
27
+ end
28
+ paragraph.insert(0, ' ' * indent).rstrip
29
+ end
30
+ paragraphs.join("\n\n")
31
+ end
32
+
33
+ module_function :wrap_formatted_text
34
+
35
+ # @return [String] Wraps a string to the terminal width taking into
36
+ # account the given indentation.
37
+ #
38
+ # @param [String] string
39
+ # The string to indent.
40
+ #
41
+ # @param [Fixnum] indent
42
+ # The number of spaces to insert before the string.
43
+ #
44
+ # @param [Fixnum] width
45
+ # The width to use when formatting the string in the terminal
46
+ #
47
+ def wrap_with_indent(string, indent = 0, width = 80)
48
+ full_line = string.gsub("\n", ' ')
49
+ available_width = width - indent
50
+ space = ' ' * indent
51
+ word_wrap(full_line, available_width).split("\n").join("\n#{space}")
52
+ end
53
+
54
+ module_function :wrap_with_indent
55
+
56
+ # @return [String] Lifted straigth from Actionview. Thanks Guys!
57
+ #
58
+ def word_wrap(line, line_width)
59
+ line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip
60
+ end
61
+
62
+ module_function :word_wrap
63
+
64
+ # @return [String] Lifted straigth from Actionview. Thanks Guys!
65
+ #
66
+ def strip_heredoc(string)
67
+ if min = string.scan(/^[ \t]*(?=\S)/).min
68
+ string.gsub(/^[ \t]{#{min.size}}/, '')
69
+ else
70
+ string
71
+ end
72
+ end
73
+
74
+ module_function :strip_heredoc
75
+ end
76
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cork
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Karla Sandoval
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-03-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: colored
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bacon
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.1'
69
+ description:
70
+ email:
71
+ - k.isabel.sandoval@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - CHANGELOG.md
77
+ - LICENSE
78
+ - README.md
79
+ - lib/cork.rb
80
+ - lib/cork/board.rb
81
+ - lib/cork/gem_version.rb
82
+ - lib/cork/text_wrapper.rb
83
+ homepage: https://github.com/CocoaPods/Cork
84
+ licenses:
85
+ - MIT
86
+ metadata: {}
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: 2.0.0
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubyforge_project:
103
+ rubygems_version: 2.4.8
104
+ signing_key:
105
+ specification_version: 3
106
+ summary: A delightful CLI UI module.
107
+ test_files: []