highline 2.0.0.pre.develop.2 → 2.0.0.pre.develop.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,11 +1,16 @@
1
1
  #coding: utf-8
2
2
 
3
3
  class HighLine
4
+ # Builtin Styles that are included at HighLine initialization.
5
+ # It has the basic styles like :bold and :underline.
4
6
  module BuiltinStyles
7
+ # Included callback
8
+ # @param base [Class, Module] base class
5
9
  def self.included(base)
6
10
  base.extend ClassMethods
7
11
  end
8
12
 
13
+ # Basic styles' ANSI escape codes like :bold => "\e[1m"
9
14
  STYLE_LIST = {
10
15
  erase_line: "\e[K",
11
16
  erase_char: "\e[P",
@@ -27,8 +32,10 @@ class HighLine
27
32
  const_set style + "_STYLE", Style.new(name: style_name, code: code, builtin: true)
28
33
  end
29
34
 
35
+ # Basic Style names like CLEAR, BOLD, UNDERLINE
30
36
  STYLES = %w{CLEAR RESET BOLD DARK UNDERLINE UNDERSCORE BLINK REVERSE CONCEALED}
31
37
 
38
+ # A Hash with the basic colors an their ANSI escape codes.
32
39
  COLOR_LIST = {
33
40
  black: { code: "\e[30m", rgb: [0, 0, 0] },
34
41
  red: { code: "\e[31m", rgb: [128, 0, 0] },
@@ -56,6 +63,7 @@ class HighLine
56
63
  const_set color + "_STYLE", style
57
64
  end
58
65
 
66
+ # The builtin styles basic colors like black, red, green.
59
67
  BASIC_COLORS = %w{BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE GRAY GREY NONE}
60
68
 
61
69
  colors = BASIC_COLORS.dup
@@ -68,6 +76,8 @@ class HighLine
68
76
  colors << light_color
69
77
  const_set light_color + '_STYLE', const_get(color + '_STYLE').light
70
78
  end
79
+
80
+ # The builtin styles' colors like LIGHT_RED and BRIGHT_BLUE.
71
81
  COLORS = colors
72
82
 
73
83
  colors.each do |color|
@@ -78,11 +88,17 @@ class HighLine
78
88
 
79
89
  ON_NONE_STYLE.rgb = [255,255,255] # Override; white background
80
90
 
91
+ # BuiltinStyles class methods to be extended.
81
92
  module ClassMethods
82
- RGB_COLOR = /^(ON_)?(RGB_)([A-F0-9]{6})(_STYLE)?$/
83
93
 
94
+ # Regexp to match against RGB style constant names.
95
+ RGB_COLOR_PATTERN = /^(ON_)?(RGB_)([A-F0-9]{6})(_STYLE)?$/
96
+
97
+ # const_missing callback for automatically respond to
98
+ # builtin constants (without explicitly defining them)
99
+ # @param name [Symbol] missing constant name
84
100
  def const_missing(name)
85
- if name.to_s =~ RGB_COLOR
101
+ if name.to_s =~ RGB_COLOR_PATTERN
86
102
  on = $1
87
103
  suffix = $4
88
104
 
@@ -8,19 +8,18 @@
8
8
  #
9
9
  # This is Free Software. See LICENSE and COPYING for details
10
10
 
11
+
11
12
  class HighLine
12
13
  #
13
14
  # ColorScheme objects encapsulate a named set of colors to be used in the
14
- # HighLine.colors() method call. For example, by applying a ColorScheme that
15
+ # {HighLine.color} method call. For example, by applying a ColorScheme that
15
16
  # has a <tt>:warning</tt> color then the following could be used:
16
17
  #
17
- # colors("This is a warning", :warning)
18
+ # color("This is a warning", :warning)
18
19
  #
19
20
  # A ColorScheme contains named sets of HighLine color constants.
20
21
  #
21
- # Example: Instantiating a color scheme, applying it to HighLine,
22
- # and using it:
23
- #
22
+ # @example Instantiating a color scheme, applying it to HighLine, and using it:
24
23
  # ft = HighLine::ColorScheme.new do |cs|
25
24
  # cs[:headline] = [ :bold, :yellow, :on_black ]
26
25
  # cs[:horizontal_line] = [ :bold, :white ]
@@ -49,6 +48,7 @@ class HighLine
49
48
  # converted to <tt>:symbols</tt> and values are converted to HighLine
50
49
  # constants.
51
50
  #
51
+ # @param h [Hash]
52
52
  def initialize( h = nil )
53
53
  @scheme = Hash.new
54
54
  load_from_hash(h) if h
@@ -56,6 +56,7 @@ class HighLine
56
56
  end
57
57
 
58
58
  # Load multiple colors from key/value pairs.
59
+ # @param h [Hash]
59
60
  def load_from_hash( h )
60
61
  h.each_pair do |color_tag, constants|
61
62
  self[color_tag] = constants
@@ -63,33 +64,42 @@ class HighLine
63
64
  end
64
65
 
65
66
  # Does this color scheme include the given tag name?
67
+ # @param color_tag [#to_sym]
68
+ # @return [Boolean]
66
69
  def include?( color_tag )
67
70
  @scheme.keys.include?(to_symbol(color_tag))
68
71
  end
69
72
 
70
73
  # Allow the scheme to be accessed like a Hash.
74
+ # @param color_tag [#to_sym]
75
+ # @return [Style]
71
76
  def []( color_tag )
72
77
  @scheme[to_symbol(color_tag)]
73
78
  end
74
79
 
75
80
  # Retrieve the original form of the scheme
81
+ # @param color_tag [#to_sym]
76
82
  def definition( color_tag )
77
83
  style = @scheme[to_symbol(color_tag)]
78
84
  style && style.list
79
85
  end
80
86
 
81
87
  # Retrieve the keys in the scheme
88
+ # @return [Array] of keys
82
89
  def keys
83
90
  @scheme.keys
84
91
  end
85
92
 
86
93
  # Allow the scheme to be set like a Hash.
94
+ # @param color_tag [#to_sym]
95
+ # @param constants [Array<Symbol>] Array of Style symbols
87
96
  def []=( color_tag, constants )
88
97
  @scheme[to_symbol(color_tag)] = HighLine::Style.new(:name=>color_tag.to_s.downcase.to_sym,
89
98
  :list=>constants, :no_index=>true)
90
99
  end
91
100
 
92
101
  # Retrieve the color scheme hash (in original definition format)
102
+ # @return [Hash] scheme as Hash. It may be reused in a new ColorScheme.
93
103
  def to_hash
94
104
  @scheme.inject({}) { |hsh, pair| key, value = pair; hsh[key] = value.list; hsh }
95
105
  end
@@ -1,18 +1,23 @@
1
1
  # coding: utf-8
2
2
 
3
3
  unless STDIN.respond_to? :getbyte
4
+ # HighLine adds #getbyte alias to #getc when #getbyte is not available.
4
5
  class IO
6
+ # alias to #getc when #getbyte is not available
5
7
  alias_method :getbyte, :getc
6
8
  end
7
9
 
10
+ # HighLine adds #getbyte alias to #getc when #getbyte is not available.
8
11
  class StringIO
12
+ # alias to #getc when #getbyte is not available
9
13
  alias_method :getbyte, :getc
10
14
  end
11
15
  end
12
16
 
13
17
  unless "".respond_to? :each_line
14
- # Not a perfect translation, but sufficient for our needs.
18
+ # HighLine adds #each_line alias to #each when each_line is not available.
15
19
  class String
20
+ # alias to #each when each_line is not available.
16
21
  alias_method :each_line, :each
17
22
  end
18
23
  end
@@ -1,19 +1,56 @@
1
1
  class HighLine
2
+
3
+ # Internal HighLine errors.
2
4
  module CustomErrors
3
- # Internal HighLine errors.
4
- class QuestionError < StandardError
5
+ # An error that responds to :explanation_key
6
+ class ExplainableError < StandardError
7
+ # Explanation key as Symbol or nil. Used to
8
+ # select the proper error message to be displayed.
9
+ # @return [nil, Symbol] explanation key to get the
10
+ # proper error message.
11
+ def explanation_key
12
+ nil
13
+ end
14
+ end
15
+
16
+ # Bare Question error
17
+ class QuestionError < ExplainableError
18
+ # (see ExplainableError#explanation_key)
19
+ def explanation_key
20
+ nil
21
+ end
5
22
  end
6
23
 
7
- class NotValidQuestionError < QuestionError
24
+ # Invalid Question error
25
+ class NotValidQuestionError < ExplainableError
26
+ # (see ExplainableError#explanation_key)
27
+ def explanation_key
28
+ :not_valid
29
+ end
8
30
  end
9
31
 
10
- class NotInRangeQuestionError < QuestionError
32
+ # Out of Range Question error
33
+ class NotInRangeQuestionError < ExplainableError
34
+ # (see ExplainableError#explanation_key)
35
+ def explanation_key
36
+ :not_in_range
37
+ end
11
38
  end
12
39
 
13
- class NoConfirmationQuestionError < QuestionError
40
+ # Unconfirmed Question error
41
+ class NoConfirmationQuestionError < ExplainableError
42
+ # (see ExplainableError#explanation_key)
43
+ def explanation_key
44
+ nil
45
+ end
14
46
  end
15
47
 
16
- class NoAutoCompleteMatch < StandardError
48
+ # Unavailable auto complete error
49
+ class NoAutoCompleteMatch < ExplainableError
50
+ # (see ExplainableError#explanation_key)
51
+ def explanation_key
52
+ :no_completion
53
+ end
17
54
  end
18
55
  end
19
56
  end
@@ -14,11 +14,12 @@ $terminal = HighLine.new
14
14
 
15
15
  #
16
16
  # <tt>require "highline/import"</tt> adds shortcut methods to Kernel, making
17
- # agree(), ask(), choose() and say() globally available. This is handy for
17
+ # {HighLine#agree}, {HighLine#ask}, {HighLine#choose} and {HighLine#say}
18
+ # globally available. This is handy for
18
19
  # quick and dirty input and output. These methods use the HighLine object in
19
- # the global variable <tt>$terminal</tt>, which is initialized to used
20
+ # the global variable <tt>$terminal</tt>, which is initialized to use
20
21
  # <tt>$stdin</tt> and <tt>$stdout</tt> (you are free to change this).
21
- # Otherwise, these methods are identical to their HighLine counterparts, see that
22
+ # Otherwise, these methods are identical to their {HighLine} counterparts, see that
22
23
  # class for detailed explanations.
23
24
  #
24
25
  module Kernel
@@ -26,6 +27,8 @@ module Kernel
26
27
  def_delegators :$terminal, :agree, :ask, :choose, :say
27
28
  end
28
29
 
30
+ # When requiring 'highline/import' HighLine adds {#or_ask} to Object so
31
+ # it is globally available.
29
32
  class Object
30
33
  #
31
34
  # Tries this object as a _first_answer_ for a HighLine::Question. See that
@@ -33,6 +36,10 @@ class Object
33
36
  #
34
37
  # *Warning*: This Object will be passed to String() before set.
35
38
  #
39
+ # @param args [Array<#to_s>]
40
+ # @param details [lambda] block to be called with the question
41
+ # instance as argument.
42
+ # @return [String] answer
36
43
  def or_ask( *args, &details )
37
44
  ask(*args) do |question|
38
45
  question.first_answer = String(self)
@@ -1,18 +1,76 @@
1
1
  # coding: utf-8
2
2
 
3
3
  class HighLine
4
+
5
+ # List class with some convenience methods like {#col_down}.
4
6
  class List
5
- attr_reader :items, :cols
6
- attr_reader :transpose_mode, :col_down_mode
7
+
8
+ # Original given *items* argument.
9
+ # It's frozen at initialization time and
10
+ # all later transformations will happen on {#list}.
11
+ # @return [Array]
12
+ attr_reader :items
13
+
14
+ # Number of columns for each list row.
15
+ # @return [Integer]
16
+ attr_reader :cols
17
+
18
+ # Columns turn into rows in transpose mode.
19
+ # @return [Boolean]
20
+ #
21
+ # @example A two columns array like this:
22
+ # [ [ "a", "b" ],
23
+ # [ "c", "d" ],
24
+ # [ "e", "f" ],
25
+ # [ "g", "h" ],
26
+ # [ "i", "j" ] ]
27
+ #
28
+ # @example When in transpose mode will be like this:
29
+ # [ [ "a", "c", "e", "g", "i" ],
30
+ # [ "b", "d", "f", "h", "j" ] ]
31
+ #
32
+ # @see #col_down_mode
33
+
34
+ attr_reader :transpose_mode
35
+
36
+
37
+ # Content are distributed first by column in col down mode.
38
+ # @return [Boolean]
39
+ #
40
+ # @example A two columns array like this:
41
+ # [ [ "a", "b" ],
42
+ # [ "c", "d" ],
43
+ # [ "e", "f" ],
44
+ # [ "g", "h" ],
45
+ # [ "i", "j" ] ]
46
+ #
47
+ # @example In col down mode will be like this:
48
+ # [ [ "a", "f"],
49
+ # [ "b", "g"],
50
+ # [ "c", "h"],
51
+ # [ "d", "i"],
52
+ # [ "e", "j"] ]
53
+ #
54
+ # @see #transpose_mode
55
+
56
+ attr_reader :col_down_mode
57
+
58
+ # @param items [#to_a] an array of items to compose the list.
59
+ # @param options [Hash] a hash of options to tailor the list.
60
+ # @option options [Boolean] :transpose (false) set {#transpose_mode}.
61
+ # @option options [Boolean] :col_down (false) set {#col_down_mode}.
62
+ # @option options [Integer] :cols (1) set {#cols}.
7
63
 
8
64
  def initialize(items, options = {})
9
- @items = items
65
+ @items = items.to_a.dup.freeze
10
66
  @transpose_mode = options.fetch(:transpose) { false }
11
67
  @col_down_mode = options.fetch(:col_down) { false }
12
68
  @cols = options.fetch(:cols) { 1 }
13
69
  build
14
70
  end
15
71
 
72
+ # Transpose the (already sliced by rows) list, turning its rows into columns.
73
+ # @return [self]
16
74
  def transpose
17
75
  first_row = @list[0]
18
76
  other_rows = @list[1..-1]
@@ -20,47 +78,77 @@ class HighLine
20
78
  self
21
79
  end
22
80
 
81
+ # Slice the list by rows and transpose it.
82
+ # @return [self]
23
83
  def col_down
24
84
  slice_by_rows
25
85
  transpose
26
86
  self
27
87
  end
28
88
 
89
+ # Slice the list by rows. The row count is calculated
90
+ # indirectly based on the {#cols} param and the items count.
91
+ # @return [self]
29
92
  def slice_by_rows
30
93
  @list = items_sliced_by_rows
31
94
  self
32
95
  end
33
96
 
97
+ # Slice the list by cols based on the {#cols} param.
98
+ # @return [self]
34
99
  def slice_by_cols
35
100
  @list = items_sliced_by_cols
36
101
  self
37
102
  end
38
103
 
104
+ # Set the cols number.
105
+ # @return [self]
39
106
  def cols=(cols)
40
107
  @cols = cols
41
108
  build
42
109
  end
43
110
 
44
- def to_a
45
- list
46
- end
47
-
111
+ # Returns an Array representation of the list
112
+ # in its current state.
113
+ # @return [Array] @list.dup
48
114
  def list
49
115
  @list.dup
50
116
  end
51
117
 
118
+ # (see #list)
119
+ def to_a
120
+ list
121
+ end
122
+
123
+ # Stringfies the list in its current state.
124
+ # It joins each individual _cell_ with the current
125
+ # {#row_join_string} between them.
126
+ # It joins each individual row with a
127
+ # newline character. So the returned String is
128
+ # suitable to be directly outputed
129
+ # to the screen, preserving row/columns divisions.
130
+ # @return [String]
52
131
  def to_s
53
132
  list.map { |row| stringfy(row) }.join
54
133
  end
55
134
 
135
+ # The String that will be used to join each
136
+ # cell of the list and stringfying it.
137
+ # @return [String] defaults to " " (space)
56
138
  def row_join_string
57
139
  @row_join_string ||= " "
58
140
  end
59
141
 
142
+ # Set the {#row_join_string}.
143
+ # @see #row_join_string
60
144
  def row_join_string=(string)
61
145
  @row_join_string = string
62
146
  end
63
147
 
148
+ # Returns the row join string size.
149
+ # Useful for calculating the actual size of
150
+ # rendered list.
151
+ # @return [Integer]
64
152
  def row_join_str_size
65
153
  row_join_string.size
66
154
  end
@@ -4,24 +4,34 @@ require 'highline/template_renderer'
4
4
  require 'highline/wrapper'
5
5
  require 'highline/list'
6
6
 
7
+ #
8
+ # This class is a utility for quickly and easily laying out lists
9
+ # to be used by HighLine.
10
+ #
7
11
  class HighLine::ListRenderer
8
- attr_reader :items, :mode, :option, :highline
9
-
10
- def initialize(items, mode = :rows, option = nil, highline)
11
- @highline = highline
12
- @mode = mode
13
- @option = option
14
- @items = render_list_items(items)
15
- end
16
-
17
- #
18
- # This method is a utility for quickly and easily laying out lists. It can
19
- # be accessed within ERb replacements of any text that will be sent to the
20
- # user.
12
+ # Items list
13
+ # @return [Array]
14
+ attr_reader :items
15
+
16
+ # @return [Symbol] the current mode the List is being rendered
17
+ # @see #initialize for more details see mode parameter of #initialize
18
+ attr_reader :mode
19
+
20
+ # Changes the behaviour of some modes. Example, in :inline mode
21
+ # the option is treated as the 'end separator' (defaults to " or ")
22
+ # @return option parameter that changes the behaviour of some modes.
23
+ attr_reader :option
24
+
25
+ # @return [HighLine] context
26
+ attr_reader :highline
27
+
28
+ # The only required parameters are _items_ and _highline_.
29
+ # @param items [Array] the Array of items to list
30
+ # @param mode [Symbol] controls how that list is formed
31
+ # @param option has different effects, depending on the _mode_.
32
+ # @param highline [HighLine] a HighLine instance to direct the output to.
21
33
  #
22
- # The only required parameter is _items_, which should be the Array of items
23
- # to list. A specified _mode_ controls how that list is formed and _option_
24
- # has different effects, depending on the _mode_. Recognized modes are:
34
+ # Recognized modes are:
25
35
  #
26
36
  # <tt>:columns_across</tt>:: _items_ will be placed in columns,
27
37
  # flowing from left to right. If given,
@@ -46,7 +56,16 @@ class HighLine::ListRenderer
46
56
  # Each member of the _items_ Array is passed through ERb and thus can contain
47
57
  # their own expansions. Color escape expansions do not contribute to the
48
58
  # final field width.
49
- #
59
+
60
+ def initialize(items, mode = :rows, option = nil, highline)
61
+ @highline = highline
62
+ @mode = mode
63
+ @option = option
64
+ @items = render_list_items(items)
65
+ end
66
+
67
+ # Render the list using the appropriate mode and options.
68
+ # @return [String] rendered list as String
50
69
  def render
51
70
  return "" if items.empty?
52
71