tty-prompt 0.18.0 → 0.22.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +92 -0
- data/README.md +549 -248
- data/lib/tty-prompt.rb +1 -2
- data/lib/tty/prompt.rb +187 -143
- data/lib/tty/prompt/answers_collector.rb +5 -5
- data/lib/tty/prompt/{enum_paginator.rb → block_paginator.rb} +20 -19
- data/lib/tty/prompt/choice.rb +5 -7
- data/lib/tty/prompt/choices.rb +29 -11
- data/lib/tty/prompt/confirm_question.rb +38 -16
- data/lib/tty/prompt/const.rb +17 -0
- data/lib/tty/prompt/converter_dsl.rb +6 -7
- data/lib/tty/prompt/converter_registry.rb +31 -26
- data/lib/tty/prompt/converters.rb +139 -32
- data/lib/tty/prompt/enum_list.rb +57 -27
- data/lib/tty/prompt/errors.rb +31 -0
- data/lib/tty/prompt/evaluator.rb +1 -1
- data/lib/tty/prompt/expander.rb +39 -13
- data/lib/tty/prompt/keypress.rb +31 -36
- data/lib/tty/prompt/list.rb +175 -65
- data/lib/tty/prompt/mask_question.rb +4 -5
- data/lib/tty/prompt/multi_list.rb +124 -33
- data/lib/tty/prompt/multiline.rb +7 -6
- data/lib/tty/prompt/paginator.rb +38 -26
- data/lib/tty/prompt/question.rb +83 -34
- data/lib/tty/prompt/question/checks.rb +18 -0
- data/lib/tty/prompt/question/validation.rb +3 -3
- data/lib/tty/prompt/selected_choices.rb +76 -0
- data/lib/tty/prompt/slider.rb +83 -16
- data/lib/tty/prompt/statement.rb +3 -3
- data/lib/tty/prompt/suggestion.rb +6 -6
- data/lib/tty/prompt/symbols.rb +58 -34
- data/lib/tty/prompt/test.rb +36 -0
- data/lib/tty/prompt/timer.rb +75 -0
- data/lib/tty/prompt/utils.rb +1 -3
- data/lib/tty/prompt/version.rb +1 -1
- metadata +29 -227
- data/Rakefile +0 -8
- data/examples/ask.rb +0 -7
- data/examples/ask_valid.rb +0 -12
- data/examples/collect.rb +0 -21
- data/examples/echo.rb +0 -11
- data/examples/enum_select.rb +0 -7
- data/examples/enum_select_disabled.rb +0 -16
- data/examples/enum_select_paged.rb +0 -9
- data/examples/enum_select_wrapped.rb +0 -15
- data/examples/expand.rb +0 -29
- data/examples/in.rb +0 -9
- data/examples/inputs.rb +0 -10
- data/examples/key_events.rb +0 -15
- data/examples/keypress.rb +0 -9
- data/examples/mask.rb +0 -13
- data/examples/multi_select.rb +0 -8
- data/examples/multi_select_disabled.rb +0 -17
- data/examples/multi_select_paged.rb +0 -9
- data/examples/multi_select_wrapped.rb +0 -15
- data/examples/multiline.rb +0 -9
- data/examples/pause.rb +0 -9
- data/examples/select.rb +0 -20
- data/examples/select_disabled.rb +0 -18
- data/examples/select_enum.rb +0 -8
- data/examples/select_filtered.rb +0 -11
- data/examples/select_paginated.rb +0 -11
- data/examples/select_wrapped.rb +0 -15
- data/examples/slider.rb +0 -6
- data/examples/validation.rb +0 -9
- data/examples/yes_no.rb +0 -7
- data/lib/tty/prompt/messages.rb +0 -49
- data/lib/tty/prompt/timeout.rb +0 -78
- data/lib/tty/test_prompt.rb +0 -20
- data/spec/spec_helper.rb +0 -45
- data/spec/unit/ask_spec.rb +0 -132
- data/spec/unit/choice/eql_spec.rb +0 -22
- data/spec/unit/choice/from_spec.rb +0 -96
- data/spec/unit/choices/add_spec.rb +0 -12
- data/spec/unit/choices/each_spec.rb +0 -13
- data/spec/unit/choices/find_by_spec.rb +0 -10
- data/spec/unit/choices/new_spec.rb +0 -10
- data/spec/unit/choices/pluck_spec.rb +0 -9
- data/spec/unit/collect_spec.rb +0 -96
- data/spec/unit/converters/convert_bool_spec.rb +0 -58
- data/spec/unit/converters/convert_char_spec.rb +0 -11
- data/spec/unit/converters/convert_custom_spec.rb +0 -14
- data/spec/unit/converters/convert_date_spec.rb +0 -34
- data/spec/unit/converters/convert_file_spec.rb +0 -18
- data/spec/unit/converters/convert_number_spec.rb +0 -39
- data/spec/unit/converters/convert_path_spec.rb +0 -15
- data/spec/unit/converters/convert_range_spec.rb +0 -22
- data/spec/unit/converters/convert_regex_spec.rb +0 -12
- data/spec/unit/converters/convert_string_spec.rb +0 -21
- data/spec/unit/converters/on_error_spec.rb +0 -9
- data/spec/unit/distance/distance_spec.rb +0 -73
- data/spec/unit/enum_paginator_spec.rb +0 -75
- data/spec/unit/enum_select_spec.rb +0 -446
- data/spec/unit/error_spec.rb +0 -20
- data/spec/unit/evaluator_spec.rb +0 -67
- data/spec/unit/expand_spec.rb +0 -198
- data/spec/unit/keypress_spec.rb +0 -72
- data/spec/unit/mask_spec.rb +0 -132
- data/spec/unit/multi_select_spec.rb +0 -495
- data/spec/unit/multiline_spec.rb +0 -77
- data/spec/unit/new_spec.rb +0 -20
- data/spec/unit/ok_spec.rb +0 -10
- data/spec/unit/paginator_spec.rb +0 -73
- data/spec/unit/question/checks_spec.rb +0 -97
- data/spec/unit/question/default_spec.rb +0 -31
- data/spec/unit/question/echo_spec.rb +0 -38
- data/spec/unit/question/in_spec.rb +0 -115
- data/spec/unit/question/initialize_spec.rb +0 -12
- data/spec/unit/question/modifier/apply_to_spec.rb +0 -24
- data/spec/unit/question/modifier/letter_case_spec.rb +0 -41
- data/spec/unit/question/modifier/whitespace_spec.rb +0 -51
- data/spec/unit/question/modify_spec.rb +0 -41
- data/spec/unit/question/required_spec.rb +0 -92
- data/spec/unit/question/validate_spec.rb +0 -115
- data/spec/unit/question/validation/call_spec.rb +0 -31
- data/spec/unit/question/validation/coerce_spec.rb +0 -30
- data/spec/unit/result_spec.rb +0 -40
- data/spec/unit/say_spec.rb +0 -67
- data/spec/unit/select_spec.rb +0 -643
- data/spec/unit/slider_spec.rb +0 -100
- data/spec/unit/statement/initialize_spec.rb +0 -15
- data/spec/unit/subscribe_spec.rb +0 -22
- data/spec/unit/suggest_spec.rb +0 -28
- data/spec/unit/warn_spec.rb +0 -21
- data/spec/unit/yes_no_spec.rb +0 -251
- data/tasks/console.rake +0 -11
- data/tasks/coverage.rake +0 -11
- data/tasks/spec.rake +0 -29
- data/tty-prompt.gemspec +0 -33
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../const"
|
4
|
+
|
3
5
|
module TTY
|
4
6
|
class Prompt
|
5
7
|
class Question
|
@@ -81,6 +83,22 @@ module TTY
|
|
81
83
|
end
|
82
84
|
end
|
83
85
|
end
|
86
|
+
|
87
|
+
class CheckConversion
|
88
|
+
def self.call(question, value)
|
89
|
+
if question.convert? && !Utils.blank?(value)
|
90
|
+
result = question.convert_result(value)
|
91
|
+
if result == Const::Undefined
|
92
|
+
tokens = {value: value, type: question.convert}
|
93
|
+
[value, question.message_for(:convert?, tokens)]
|
94
|
+
else
|
95
|
+
[result]
|
96
|
+
end
|
97
|
+
else
|
98
|
+
[value]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
84
102
|
end # Checks
|
85
103
|
end # Question
|
86
104
|
end # Prompt
|
@@ -57,11 +57,11 @@ module TTY
|
|
57
57
|
def call(input)
|
58
58
|
if pattern.is_a?(String) || pattern.is_a?(Symbol)
|
59
59
|
VALIDATORS.key?(pattern.to_sym)
|
60
|
-
!VALIDATORS[pattern.to_sym].match(input).nil?
|
60
|
+
!VALIDATORS[pattern.to_sym].match(input.to_s).nil?
|
61
61
|
elsif pattern.is_a?(Regexp)
|
62
|
-
!pattern.match(input).nil?
|
62
|
+
!pattern.match(input.to_s).nil?
|
63
63
|
elsif pattern.is_a?(Proc)
|
64
|
-
result = pattern.call(input)
|
64
|
+
result = pattern.call(input.to_s)
|
65
65
|
result.nil? ? false : result
|
66
66
|
else false
|
67
67
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TTY
|
4
|
+
class Prompt
|
5
|
+
# @api private
|
6
|
+
class SelectedChoices
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
attr_reader :size
|
10
|
+
|
11
|
+
# Create selected choices
|
12
|
+
#
|
13
|
+
# @param [Array<Choice>] selected
|
14
|
+
# @param [Array<Integer>] indexes
|
15
|
+
#
|
16
|
+
# @api public
|
17
|
+
def initialize(selected = [], indexes = [])
|
18
|
+
@selected = selected
|
19
|
+
@indexes = indexes
|
20
|
+
@size = @selected.size
|
21
|
+
end
|
22
|
+
|
23
|
+
# Clear selected choices
|
24
|
+
#
|
25
|
+
# @api public
|
26
|
+
def clear
|
27
|
+
@indexes.clear
|
28
|
+
@selected.clear
|
29
|
+
@size = 0
|
30
|
+
end
|
31
|
+
|
32
|
+
# Iterate over selected choices
|
33
|
+
#
|
34
|
+
# @api public
|
35
|
+
def each(&block)
|
36
|
+
return to_enum unless block_given?
|
37
|
+
@selected.each(&block)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Insert choice at index
|
41
|
+
#
|
42
|
+
# @param [Integer] index
|
43
|
+
# @param [Choice] choice
|
44
|
+
#
|
45
|
+
# @api public
|
46
|
+
def insert(index, choice)
|
47
|
+
insert_idx = find_index_by { |i| index < @indexes[i] }
|
48
|
+
insert_idx ||= -1
|
49
|
+
@indexes.insert(insert_idx, index)
|
50
|
+
@selected.insert(insert_idx, choice)
|
51
|
+
@size += 1
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
# Delete choice at index
|
56
|
+
#
|
57
|
+
# @return [Choice]
|
58
|
+
# the deleted choice
|
59
|
+
#
|
60
|
+
# @api public
|
61
|
+
def delete_at(index)
|
62
|
+
delete_idx = @indexes.each_index.find { |i| index == @indexes[i] }
|
63
|
+
return nil unless delete_idx
|
64
|
+
|
65
|
+
@indexes.delete_at(delete_idx)
|
66
|
+
choice = @selected.delete_at(delete_idx)
|
67
|
+
@size -= 1
|
68
|
+
choice
|
69
|
+
end
|
70
|
+
|
71
|
+
def find_index_by(&search)
|
72
|
+
(0...@size).bsearch(&search)
|
73
|
+
end
|
74
|
+
end # SelectedChoices
|
75
|
+
end # Prompt
|
76
|
+
end # TTY
|
data/lib/tty/prompt/slider.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'symbols'
|
4
|
-
|
5
3
|
module TTY
|
6
4
|
# A class responsible for shell prompt interactions.
|
7
5
|
class Prompt
|
@@ -9,11 +7,9 @@ module TTY
|
|
9
7
|
#
|
10
8
|
# @api public
|
11
9
|
class Slider
|
12
|
-
|
13
|
-
|
14
|
-
HELP = '(Use arrow keys, press Enter to select)'.freeze
|
10
|
+
HELP = "(Use %s arrow keys, press Enter to select)"
|
15
11
|
|
16
|
-
FORMAT =
|
12
|
+
FORMAT = ":slider %d"
|
17
13
|
|
18
14
|
# Initailize a Slider
|
19
15
|
#
|
@@ -27,7 +23,7 @@ module TTY
|
|
27
23
|
# @option options [String] :format The display format
|
28
24
|
#
|
29
25
|
# @api public
|
30
|
-
def initialize(prompt, options
|
26
|
+
def initialize(prompt, **options)
|
31
27
|
@prompt = prompt
|
32
28
|
@prefix = options.fetch(:prefix) { @prompt.prefix }
|
33
29
|
@min = options.fetch(:min) { 0 }
|
@@ -37,10 +33,26 @@ module TTY
|
|
37
33
|
@active_color = options.fetch(:active_color) { @prompt.active_color }
|
38
34
|
@help_color = options.fetch(:help_color) { @prompt.help_color }
|
39
35
|
@format = options.fetch(:format) { FORMAT }
|
36
|
+
@quiet = options.fetch(:quiet) { @prompt.quiet }
|
37
|
+
@help = options[:help]
|
38
|
+
@show_help = options.fetch(:show_help) { :start }
|
39
|
+
@symbols = @prompt.symbols.merge(options.fetch(:symbols, {}))
|
40
40
|
@first_render = true
|
41
41
|
@done = false
|
42
42
|
end
|
43
43
|
|
44
|
+
# Change symbols used by this prompt
|
45
|
+
#
|
46
|
+
# @param [Hash] new_symbols
|
47
|
+
# the new symbols to use
|
48
|
+
#
|
49
|
+
# @api public
|
50
|
+
def symbols(new_symbols = (not_set = true))
|
51
|
+
return @symbols if not_set
|
52
|
+
|
53
|
+
@symbols.merge!(new_symbols)
|
54
|
+
end
|
55
|
+
|
44
56
|
# Setup initial active position
|
45
57
|
#
|
46
58
|
# @return [Integer]
|
@@ -54,11 +66,39 @@ module TTY
|
|
54
66
|
end
|
55
67
|
end
|
56
68
|
|
69
|
+
# Default help text
|
70
|
+
#
|
71
|
+
# @api public
|
72
|
+
def default_help
|
73
|
+
arrows = @symbols[:arrow_left] + "/" + @symbols[:arrow_right]
|
74
|
+
sprintf(HELP, arrows)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Set help text
|
78
|
+
#
|
79
|
+
# @param [String] text
|
80
|
+
#
|
81
|
+
# @api private
|
82
|
+
def help(text = (not_set = true))
|
83
|
+
return @help if !@help.nil? && not_set
|
84
|
+
|
85
|
+
@help = (@help.nil? && not_set) ? default_help : text
|
86
|
+
end
|
87
|
+
|
88
|
+
# Change when help is displayed
|
89
|
+
#
|
90
|
+
# @api public
|
91
|
+
def show_help(value = (not_set = true))
|
92
|
+
return @show_ehlp if not_set
|
93
|
+
|
94
|
+
@show_help = value
|
95
|
+
end
|
96
|
+
|
57
97
|
# Range of numbers to render
|
58
98
|
#
|
59
99
|
# @return [Array[Integer]]
|
60
100
|
#
|
61
|
-
# @
|
101
|
+
# @api private
|
62
102
|
def range
|
63
103
|
(@min..@max).step(@step).to_a
|
64
104
|
end
|
@@ -87,6 +127,13 @@ module TTY
|
|
87
127
|
@format = value
|
88
128
|
end
|
89
129
|
|
130
|
+
# Set quiet mode.
|
131
|
+
#
|
132
|
+
# @api public
|
133
|
+
def quiet(value)
|
134
|
+
@quiet = value
|
135
|
+
end
|
136
|
+
|
90
137
|
# Call the slider by passing question
|
91
138
|
#
|
92
139
|
# @param [String] question
|
@@ -120,6 +167,20 @@ module TTY
|
|
120
167
|
|
121
168
|
private
|
122
169
|
|
170
|
+
# Check if help is shown only on start
|
171
|
+
#
|
172
|
+
# @api private
|
173
|
+
def help_start?
|
174
|
+
@show_help =~ /start/i
|
175
|
+
end
|
176
|
+
|
177
|
+
# Check if help is always displayed
|
178
|
+
#
|
179
|
+
# @api private
|
180
|
+
def help_always?
|
181
|
+
@show_help =~ /always/i
|
182
|
+
end
|
183
|
+
|
123
184
|
# Render an interactive range slider.
|
124
185
|
#
|
125
186
|
# @api private
|
@@ -131,7 +192,7 @@ module TTY
|
|
131
192
|
@prompt.read_keypress
|
132
193
|
refresh(question.lines.count)
|
133
194
|
end
|
134
|
-
@prompt.print(render_question)
|
195
|
+
@prompt.print(render_question) unless @quiet
|
135
196
|
answer
|
136
197
|
ensure
|
137
198
|
@prompt.print(@prompt.show)
|
@@ -167,8 +228,9 @@ module TTY
|
|
167
228
|
else
|
168
229
|
header << render_slider
|
169
230
|
end
|
170
|
-
if @first_render
|
171
|
-
|
231
|
+
if @first_render && (help_start? || help_always?) ||
|
232
|
+
(help_always? && !@done)
|
233
|
+
header << "\n" + @prompt.decorate(help, @help_color)
|
172
234
|
@first_render = false
|
173
235
|
end
|
174
236
|
header.join
|
@@ -180,11 +242,16 @@ module TTY
|
|
180
242
|
#
|
181
243
|
# @api private
|
182
244
|
def render_slider
|
183
|
-
slider = (symbols[:line] * @active) +
|
184
|
-
@prompt.decorate(symbols[:
|
185
|
-
(symbols[:line] * (range.size - @active - 1))
|
186
|
-
value =
|
187
|
-
@format
|
245
|
+
slider = (@symbols[:line] * @active) +
|
246
|
+
@prompt.decorate(@symbols[:bullet], @active_color) +
|
247
|
+
(@symbols[:line] * (range.size - @active - 1))
|
248
|
+
value = range[@active]
|
249
|
+
case @format
|
250
|
+
when Proc
|
251
|
+
@format.call(slider, value)
|
252
|
+
else
|
253
|
+
@format.gsub(":slider", slider) % [value]
|
254
|
+
end
|
188
255
|
end
|
189
256
|
end # Slider
|
190
257
|
end # Prompt
|
data/lib/tty/prompt/statement.rb
CHANGED
@@ -28,10 +28,10 @@ module TTY
|
|
28
28
|
# change the message display to color
|
29
29
|
#
|
30
30
|
# @api public
|
31
|
-
def initialize(prompt,
|
31
|
+
def initialize(prompt, newline: true, color: false)
|
32
32
|
@prompt = prompt
|
33
|
-
@newline =
|
34
|
-
@color =
|
33
|
+
@newline = newline
|
34
|
+
@color = color
|
35
35
|
end
|
36
36
|
|
37
37
|
# Output the message to the prompt
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative "distance"
|
4
4
|
|
5
5
|
module TTY
|
6
6
|
# A class responsible for terminal prompt interactions.
|
@@ -11,9 +11,9 @@ module TTY
|
|
11
11
|
class Suggestion
|
12
12
|
DEFAULT_INDENT = 8
|
13
13
|
|
14
|
-
SINGLE_TEXT =
|
14
|
+
SINGLE_TEXT = "Did you mean this?"
|
15
15
|
|
16
|
-
PLURAL_TEXT =
|
16
|
+
PLURAL_TEXT = "Did you mean one of these?"
|
17
17
|
|
18
18
|
# Number of spaces
|
19
19
|
#
|
@@ -33,7 +33,7 @@ module TTY
|
|
33
33
|
# Initialize a Suggestion
|
34
34
|
#
|
35
35
|
# @api public
|
36
|
-
def initialize(options
|
36
|
+
def initialize(**options)
|
37
37
|
@indent = options.fetch(:indent) { DEFAULT_INDENT }
|
38
38
|
@single_text = options.fetch(:single_text) { SINGLE_TEXT }
|
39
39
|
@plural_text = options.fetch(:plural_text) { PLURAL_TEXT }
|
@@ -97,14 +97,14 @@ module TTY
|
|
97
97
|
|
98
98
|
# @api private
|
99
99
|
def build_single_suggestion
|
100
|
-
single_text + "\n" + (
|
100
|
+
single_text + "\n" + (" " * indent) + @suggestions.first
|
101
101
|
end
|
102
102
|
|
103
103
|
# @api private
|
104
104
|
def build_multiple_suggestions
|
105
105
|
plural_text + "\n" +
|
106
106
|
@suggestions.map do |sugest|
|
107
|
-
|
107
|
+
" " * indent + sugest
|
108
108
|
end.join("\n")
|
109
109
|
end
|
110
110
|
end # Suggestion
|
data/lib/tty/prompt/symbols.rb
CHANGED
@@ -7,43 +7,67 @@ module TTY
|
|
7
7
|
# @api public
|
8
8
|
module Symbols
|
9
9
|
KEYS = {
|
10
|
-
tick:
|
11
|
-
cross:
|
12
|
-
star:
|
13
|
-
square:
|
14
|
-
square_empty:
|
15
|
-
dot:
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
10
|
+
tick: "✓",
|
11
|
+
cross: "✘",
|
12
|
+
star: "★",
|
13
|
+
square: "◼",
|
14
|
+
square_empty: "◻",
|
15
|
+
dot: "•",
|
16
|
+
bullet: "●",
|
17
|
+
bullet_empty: "○",
|
18
|
+
marker: "‣",
|
19
|
+
line: "─",
|
20
|
+
pipe: "|",
|
21
|
+
ellipsis: "…",
|
22
|
+
radio_on: "⬢",
|
23
|
+
radio_off: "⬡",
|
24
|
+
checkbox_on: "☒",
|
25
|
+
checkbox_off: "☐",
|
26
|
+
circle: "◯",
|
27
|
+
circle_on: "ⓧ",
|
28
|
+
circle_off: "Ⓘ",
|
29
|
+
arrow_up: "↑",
|
30
|
+
arrow_down: "↓",
|
31
|
+
arrow_up_down: "↕",
|
32
|
+
arrow_left: "←",
|
33
|
+
arrow_right: "→",
|
34
|
+
arrow_left_right: "↔",
|
35
|
+
heart: "♥",
|
36
|
+
diamond: "♦",
|
37
|
+
club: "♣",
|
38
|
+
spade: "♠"
|
27
39
|
}.freeze
|
28
40
|
|
29
41
|
WIN_KEYS = {
|
30
|
-
tick:
|
31
|
-
cross:
|
32
|
-
star:
|
33
|
-
square:
|
34
|
-
square_empty:
|
35
|
-
dot:
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
42
|
+
tick: "√",
|
43
|
+
cross: "x",
|
44
|
+
star: "*",
|
45
|
+
square: "[█]",
|
46
|
+
square_empty: "[ ]",
|
47
|
+
dot: ".",
|
48
|
+
bullet: "O",
|
49
|
+
bullet_empty: "○",
|
50
|
+
marker: ">",
|
51
|
+
line: "-",
|
52
|
+
pipe: "|",
|
53
|
+
ellipsis: "...",
|
54
|
+
radio_on: "(*)",
|
55
|
+
radio_off: "( )",
|
56
|
+
checkbox_on: "[×]",
|
57
|
+
checkbox_off: "[ ]",
|
58
|
+
circle: "( )",
|
59
|
+
circle_on: "(x)",
|
60
|
+
circle_off: "( )",
|
61
|
+
arrow_up: "↑",
|
62
|
+
arrow_down: "↓",
|
63
|
+
arrow_up_down: "↕",
|
64
|
+
arrow_left: "←",
|
65
|
+
arrow_right: "→",
|
66
|
+
arrow_left_right: "↔",
|
67
|
+
heart: "♥",
|
68
|
+
diamond: "♦",
|
69
|
+
club: "♣",
|
70
|
+
spade: "♠"
|
47
71
|
}.freeze
|
48
72
|
|
49
73
|
def symbols
|