tty-prompt 0.10.1 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -1
  3. data/CHANGELOG.md +30 -0
  4. data/README.md +39 -9
  5. data/examples/echo.rb +5 -1
  6. data/examples/inputs.rb +10 -0
  7. data/examples/mask.rb +6 -2
  8. data/examples/multi_select.rb +1 -1
  9. data/examples/multi_select_paged.rb +9 -0
  10. data/examples/select.rb +5 -5
  11. data/examples/slider.rb +1 -1
  12. data/lib/tty-prompt.rb +2 -36
  13. data/lib/tty/prompt.rb +49 -8
  14. data/lib/tty/prompt/choices.rb +2 -0
  15. data/lib/tty/prompt/confirm_question.rb +6 -1
  16. data/lib/tty/prompt/converter_dsl.rb +9 -6
  17. data/lib/tty/prompt/converter_registry.rb +27 -19
  18. data/lib/tty/prompt/converters.rb +16 -22
  19. data/lib/tty/prompt/enum_list.rb +8 -4
  20. data/lib/tty/prompt/enum_paginator.rb +2 -0
  21. data/lib/tty/prompt/evaluator.rb +1 -1
  22. data/lib/tty/prompt/expander.rb +1 -1
  23. data/lib/tty/prompt/list.rb +21 -11
  24. data/lib/tty/prompt/mask_question.rb +15 -6
  25. data/lib/tty/prompt/multi_list.rb +12 -10
  26. data/lib/tty/prompt/question.rb +38 -36
  27. data/lib/tty/prompt/question/modifier.rb +2 -0
  28. data/lib/tty/prompt/question/validation.rb +5 -4
  29. data/lib/tty/prompt/reader.rb +104 -58
  30. data/lib/tty/prompt/reader/codes.rb +103 -63
  31. data/lib/tty/prompt/reader/console.rb +57 -0
  32. data/lib/tty/prompt/reader/key_event.rb +51 -88
  33. data/lib/tty/prompt/reader/mode.rb +5 -5
  34. data/lib/tty/prompt/reader/win_api.rb +29 -0
  35. data/lib/tty/prompt/reader/win_console.rb +49 -0
  36. data/lib/tty/prompt/slider.rb +10 -6
  37. data/lib/tty/prompt/suggestion.rb +1 -1
  38. data/lib/tty/prompt/symbols.rb +52 -10
  39. data/lib/tty/prompt/version.rb +1 -1
  40. data/lib/tty/{prompt/test.rb → test_prompt.rb} +2 -1
  41. data/spec/unit/ask_spec.rb +8 -16
  42. data/spec/unit/converters/convert_bool_spec.rb +1 -2
  43. data/spec/unit/converters/on_error_spec.rb +9 -0
  44. data/spec/unit/enum_paginator_spec.rb +16 -0
  45. data/spec/unit/enum_select_spec.rb +69 -25
  46. data/spec/unit/expand_spec.rb +14 -14
  47. data/spec/unit/mask_spec.rb +66 -29
  48. data/spec/unit/multi_select_spec.rb +120 -74
  49. data/spec/unit/new_spec.rb +5 -3
  50. data/spec/unit/paginator_spec.rb +16 -0
  51. data/spec/unit/question/default_spec.rb +2 -4
  52. data/spec/unit/question/echo_spec.rb +2 -3
  53. data/spec/unit/question/in_spec.rb +9 -14
  54. data/spec/unit/question/modifier/letter_case_spec.rb +32 -11
  55. data/spec/unit/question/modifier/whitespace_spec.rb +41 -15
  56. data/spec/unit/question/required_spec.rb +9 -13
  57. data/spec/unit/question/validate_spec.rb +7 -10
  58. data/spec/unit/reader/key_event_spec.rb +36 -50
  59. data/spec/unit/reader/publish_keypress_event_spec.rb +5 -3
  60. data/spec/unit/reader/read_keypress_spec.rb +8 -7
  61. data/spec/unit/reader/read_line_spec.rb +9 -9
  62. data/spec/unit/reader/read_multiline_spec.rb +8 -7
  63. data/spec/unit/select_spec.rb +85 -25
  64. data/spec/unit/slider_spec.rb +43 -16
  65. data/spec/unit/yes_no_spec.rb +14 -28
  66. data/tasks/console.rake +1 -0
  67. data/tty-prompt.gemspec +2 -2
  68. metadata +14 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e0dae59e66025830ef0a5c219e863d20a3fb9819
4
- data.tar.gz: 4577e97283604bc010de09be994612d123a0581a
3
+ metadata.gz: 4ff94c2773632a84c5e652c8c725cdc576718ae6
4
+ data.tar.gz: 382b630ad1f975325744210cb7a308bfc09175e2
5
5
  SHA512:
6
- metadata.gz: 679adea2e8b4fbd15f7612081fd5f6a2d0253f92aefb162b9d69b7d9be626cfadd67855363b54db68dde55a2cbecbb481e7e5bf30acb7cf1d78d3a7e8ca99af8
7
- data.tar.gz: 5bec8d5cae28cb7099f21d0a979bdf441a7440f52b5f0eea9b6430610d902bb7aa5b380fb994119c45cdf3492c1e0bad24c3d557d2a210029845b585d2213760
6
+ metadata.gz: ed722a06def652f9cb1e02fa627fe28ebfdfa0a8bdfa7a36e426b8976d4c0eab287f1e50f2800f2b7c87a185d1b4325d7628409991f6ba9061029976909c2805
7
+ data.tar.gz: 5bad4344ba8e132eaf35409329ab8583aa52f2a94a296b5b23eb13cb11c3436e71601c7bd9351ecf17d70b1851d910b2600e4ea8cfea81e08d3de507edbfa43f
@@ -17,7 +17,6 @@ rvm:
17
17
  - rbx-3
18
18
  matrix:
19
19
  allow_failures:
20
- - rvm: 2.4.0
21
20
  - rvm: ruby-head
22
21
  - rvm: jruby-head
23
22
  - rvm: rbx-3
@@ -1,5 +1,34 @@
1
1
  # Change log
2
2
 
3
+ ## [v0.11.0] - 2017-02-26
4
+
5
+ ### Added
6
+ * Add Console for reading input characters on Unix systems
7
+ * Add WinConsole for reading input characters on Windows systems
8
+ * Add WindowsApi to allow for calls to external Windows api
9
+ * Add echo support to multilist by Keith Keith T. Garner(@ktgeek)
10
+
11
+ ### Changed
12
+ * Change Reader to use Console for input reading
13
+ * Change Codes to use codepoints instead of strings
14
+ * Change Reader#read_line to match #gets behaviour
15
+ * Change Symbols to provide Unicode support on windows
16
+ * Change Slider to display Unicode when possible
17
+ * Change ConverterRegistry to be immutable
18
+ * Change Reader to expose #trigger in place of #publish for events firing
19
+
20
+ ### Fixed
21
+ * Fix `modify` throwing exception, when user enters empty input by Igor Rzegocki(@ajgon)
22
+ * Fix #clear_line behaviour by using tty-cursor 0.4.0 to work in all terminals
23
+ * Fix paging issue for lists shorter than :per_page value repeating title
24
+ * Fix #mask prompt to correctly match input on Windows
25
+ * Fix @mask to use default error messages
26
+ * Fix #select & #multi_select prompts to allow changing options with arrow keys on Windows
27
+ * Fix #echo to work correctly in zsh shell by štef(@d4be4st)
28
+ * Fix Slider#keyright event accepting max value outside of range
29
+ * Fix 2.4.0 conversion errors by using necromancer 0.4.0
30
+ * Fix #enum_select preventing selection of first item
31
+
3
32
  ## [v0.10.1] - 2017-02-06
4
33
 
5
34
  ### Fixed
@@ -137,6 +166,7 @@
137
166
 
138
167
  * Initial implementation and release
139
168
 
169
+ [v0.11.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.10.1...v0.11.0
140
170
  [v0.10.1]: https://github.com/piotrmurach/tty-prompt/compare/v0.10.0...v0.10.1
141
171
  [v0.10.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.9.0...v0.10.0
142
172
  [v0.9.0]: https://github.com/piotrmurach/tty-prompt/compare/v0.8.0...v0.9.0
data/README.md CHANGED
@@ -62,6 +62,7 @@ Or install it yourself as:
62
62
  * [2.6 menu](#26-menu)
63
63
  * [2.6.1 select](#261-select)
64
64
  * [2.6.2 multi_select](#262-multi_select)
65
+ * [2.6.2.1 echo](#2621-echo)
65
66
  * [2.6.3 enum_select](#263-enum_select)
66
67
  * [2.7 expand](#27-expand)
67
68
  * [2.8 collect](#28-collect)
@@ -142,10 +143,10 @@ prompt.enum_select("Select an editor?", choices)
142
143
  # =>
143
144
  #
144
145
  # Select an editor?
145
- # 1) /bin/nano
146
- # 2) /usr/bin/vim.basic
147
- # 3) /usr/bin/vim.tiny
148
- # Choose 1-3 [2]:
146
+ # 1) emacs
147
+ # 2) nano
148
+ # 3) vim
149
+ # Choose 1-3 [1]:
149
150
  ```
150
151
 
151
152
  However, if you have a lot of options to choose from you may want to use `expand`:
@@ -561,7 +562,7 @@ letters = ('A'..'Z').to_a
561
562
  prompt.select("Choose your letter?") do |menu|
562
563
  menu.per_page 4
563
564
  menu.page_help '(Wiggle thy finger up or down to see more)'
564
- menu.choices letters, per_page: 4)
565
+ menu.choices letters
565
566
  end
566
567
  ```
567
568
 
@@ -680,6 +681,23 @@ prompt.multi_select("Choose your letter?", letters, per_page: 4)
680
681
  # (Move up or down to reveal more choices)
681
682
  ```
682
683
 
684
+ ### 2.6.2.1 echo
685
+
686
+ To control whether the selected items are shown on the question
687
+ header use the :echo option:
688
+
689
+ ```ruby
690
+ choices = %w(vodka beer wine whisky bourbon)
691
+ prompt.multi_select("Select drinks?", choices, echo: false)
692
+ # =>
693
+ # Select drinks?
694
+ # ⬡ vodka
695
+ # ⬢ 2) beer
696
+ # ⬡ 3) wine
697
+ # ⬡ 4) whisky
698
+ # ‣ ⬢ 5) bourbon
699
+ ```
700
+
683
701
  ### 2.6.3 enum_select
684
702
 
685
703
  In order to ask for standard selection from indexed list you can use `enum_select` and pass question together with possible choices:
@@ -944,12 +962,12 @@ For example, to add vim like key navigation to `select` prompt one would do the
944
962
 
945
963
  ```ruby
946
964
  prompt.on(:keypress) do |event|
947
- if event.key.name == 'j'
948
- prompt.publish(:keydown)
965
+ if event.value == 'j'
966
+ prompt.trigger(:keydown)
949
967
  end
950
968
 
951
- if event.key.name == 'k'
952
- prompt.publish(:keyup)
969
+ if event.value == 'k'
970
+ prompt.trigger(:keyup)
953
971
  end
954
972
  end
955
973
  ```
@@ -983,6 +1001,12 @@ The available events are:
983
1001
 
984
1002
  All prompt types support `:active_color` option. In case of `select`, `multi_select`, `enum_select` or `expand` this color is used to highlight the currently selected choice. All the resulted inputs provided by user that are read in by the prompt as answer are highlighted with this color. This option can be applied either globablly for all prompts or individually.
985
1003
 
1004
+ ```ruby
1005
+ prompt = TTY::Prompt.new(active_color: :cyan)
1006
+ ```
1007
+
1008
+ or per individual input do:
1009
+
986
1010
  ```ruby
987
1011
  prompt.select('What size?', %w(Large Medium Small), active_color: :cyan)
988
1012
  ```
@@ -1001,6 +1025,12 @@ prompt = TTY::Prompt.new(enable_color: true)
1001
1025
 
1002
1026
  Prompts such as `select`, `multi_select`, `expand` support `:help_color` which is used to customize the help text. This option can be applied either globablly for all prompts or individually.
1003
1027
 
1028
+ ```ruby
1029
+ prompt = TTY::Prompt.new(help_color: :cyan)
1030
+ ```
1031
+
1032
+ or per individual input do:
1033
+
1004
1034
  ```ruby
1005
1035
  prompt.select('What size?', %w(Large Medium Small), help_color: :cyan)
1006
1036
  ```
@@ -4,4 +4,8 @@ require 'tty-prompt'
4
4
 
5
5
  prompt = TTY::Prompt.new
6
6
 
7
- puts prompt.ask('Password?', echo: false)
7
+ answer = prompt.ask('Password?', echo: false) do |q|
8
+ q.validate(/^[^\.]+\.[^\.]+/)
9
+ end
10
+
11
+ #puts answer
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ require 'tty-prompt'
4
+
5
+ prompt = TTY::Prompt.new
6
+
7
+ prompt.ask('What is your name?', default: ENV['USER'])
8
+ prompt.yes?('Do you like Ruby?')
9
+ prompt.mask("What is your secret?")
10
+ prompt.select("Choose your destiny?", %w(Scorpion Kano Jax))
@@ -1,9 +1,13 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'tty-prompt'
4
+ require 'pastel'
4
5
 
5
6
  prompt = TTY::Prompt.new
7
+ heart = prompt.decorate('❤ ', :magenta)
6
8
 
7
- prompt.mask('What is your secret?') do |q|
8
- q.validate /[a-z]{5,8}/
9
+ res = prompt.mask('What is your secret?', mask: heart) do |q|
10
+ q.validate(/[a-z\ ]{5,15}/)
9
11
  end
12
+
13
+ puts "Secret: \"#{res}\""
@@ -5,4 +5,4 @@ require 'tty-prompt'
5
5
  prompt = TTY::Prompt.new
6
6
 
7
7
  drinks = %w(vodka beer wine whisky bourbon)
8
- prompt.multi_select('Choose your favourite drink?', drinks)
8
+ prompt.multi_select('Choose your favourite drink?', drinks, help: '(Use arrow keys and Enter to finish)')
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ require 'tty-prompt'
4
+
5
+ prompt = TTY::Prompt.new
6
+
7
+ alfabet = ('A'..'Z').to_a
8
+
9
+ prompt.multi_select('Which letter?', alfabet, per_page: 5)
@@ -4,14 +4,14 @@ require 'tty-prompt'
4
4
 
5
5
  prompt = TTY::Prompt.new
6
6
 
7
- warriors = %w(Scorpion Kano Jax)
7
+ warriors = %w(Scorpion Kano Jax Kitana Raiden)
8
8
 
9
9
  prompt.on(:keypress) do |event|
10
- if event.key.name == 'j'
11
- prompt.publish(:keydown)
10
+ if event.value == 'j'
11
+ prompt.trigger(:keydown)
12
12
  end
13
- if event.key.name == 'k'
14
- prompt.publish(:keyup)
13
+ if event.value == 'k'
14
+ prompt.trigger(:keyup)
15
15
  end
16
16
  end
17
17
 
@@ -3,4 +3,4 @@
3
3
  require 'tty-prompt'
4
4
 
5
5
  prompt = TTY::Prompt.new
6
- prompt.slider("What size?", min: 32, max: 54, step: 2)
6
+ prompt.slider("What size?", min: 0, max: 40, step: 1)
@@ -1,38 +1,4 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'necromancer'
4
- require 'pastel'
5
- require 'tty-cursor'
6
-
7
- require 'tty/prompt'
8
- require 'tty/prompt/choice'
9
- require 'tty/prompt/choices'
10
- require 'tty/prompt/enum_list'
11
- require 'tty/prompt/expander'
12
- require 'tty/prompt/evaluator'
13
- require 'tty/prompt/list'
14
- require 'tty/prompt/multi_list'
15
- require 'tty/prompt/question'
16
- require 'tty/prompt/mask_question'
17
- require 'tty/prompt/confirm_question'
18
- require 'tty/prompt/reader'
19
- require 'tty/prompt/slider'
20
- require 'tty/prompt/statement'
21
- require 'tty/prompt/suggestion'
22
- require 'tty/prompt/answers_collector'
23
- require 'tty/prompt/paginator'
24
- require 'tty/prompt/enum_paginator'
25
- require 'tty/prompt/symbols'
26
- require 'tty/prompt/test'
27
- require 'tty/prompt/utils'
28
- require 'tty/prompt/version'
29
-
30
- # A collection of small libraries for building CLI apps,
31
- # each following unix philosophy of focused task
32
- module TTY
33
- class Prompt
34
- ConfigurationError = Class.new(StandardError)
35
-
36
- ConversionError = Class.new(StandardError)
37
- end
38
- end # TTY
3
+ require_relative 'tty/prompt'
4
+ require_relative 'tty/test_prompt'
@@ -1,23 +1,46 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'forwardable'
4
+ require 'pastel'
5
+ require 'tty-cursor'
6
+
7
+ require_relative 'prompt/answers_collector'
8
+ require_relative 'prompt/confirm_question'
9
+ require_relative 'prompt/expander'
10
+ require_relative 'prompt/enum_list'
11
+ require_relative 'prompt/list'
12
+ require_relative 'prompt/multi_list'
13
+ require_relative 'prompt/mask_question'
14
+ require_relative 'prompt/question'
15
+ require_relative 'prompt/reader'
16
+ require_relative 'prompt/slider'
17
+ require_relative 'prompt/statement'
18
+ require_relative 'prompt/suggestion'
19
+ require_relative 'prompt/utils'
20
+ require_relative 'prompt/version'
4
21
 
5
22
  module TTY
6
23
  # A main entry for asking prompt questions.
7
24
  class Prompt
8
25
  extend Forwardable
9
26
 
27
+ # Raised when wrong parameter is used to configure prompt
28
+ ConfigurationError = Class.new(StandardError)
29
+
30
+ # Raised when type conversion cannot be performed
31
+ ConversionError = Class.new(StandardError)
32
+
10
33
  # Raised when the passed in validation argument is of wrong type
11
- class ValidationCoercion < TypeError; end
34
+ ValidationCoercion = Class.new(TypeError)
12
35
 
13
36
  # Raised when the required argument is not supplied
14
- class ArgumentRequired < ArgumentError; end
37
+ ArgumentRequired = Class.new(ArgumentError)
15
38
 
16
39
  # Raised when the argument validation fails
17
- class ArgumentValidation < ArgumentError; end
40
+ ArgumentValidation = Class.new(ArgumentError)
18
41
 
19
42
  # Raised when the argument is not expected
20
- class InvalidArgument < ArgumentError; end
43
+ InvalidArgument = Class.new(ArgumentError)
21
44
 
22
45
  # @api private
23
46
  attr_reader :input
@@ -42,7 +65,7 @@ module TTY
42
65
  # Theme colors
43
66
  #
44
67
  # @api private
45
- attr_reader :active_color, :help_color, :error_color
68
+ attr_reader :active_color, :help_color, :error_color, :enabled_color
46
69
 
47
70
  def_delegators :@pastel, :decorate, :strip
48
71
 
@@ -50,7 +73,7 @@ module TTY
50
73
  :show, :hide
51
74
 
52
75
  def_delegators :@reader, :read_char, :read_line, :read_keypress,
53
- :read_multiline, :on, :subscribe, :publish
76
+ :read_multiline, :on, :subscribe, :trigger
54
77
 
55
78
  def_delegators :@output, :print, :puts, :flush
56
79
 
@@ -69,6 +92,7 @@ module TTY
69
92
  options = Utils.extract_options!(args)
70
93
  @input = options.fetch(:input) { $stdin }
71
94
  @output = options.fetch(:output) { $stdout }
95
+ @env = options.fetch(:env) { ENV }
72
96
  @prefix = options.fetch(:prefix) { '' }
73
97
  @enabled_color = options[:enable_color]
74
98
  @active_color = options.fetch(:active_color) { :green }
@@ -77,7 +101,7 @@ module TTY
77
101
 
78
102
  @cursor = TTY::Cursor
79
103
  @pastel = Pastel.new(@enabled_color.nil? ? {} : { enabled: @enabled_color })
80
- @reader = Reader.new(@input, @output, interrupt: options[:interrupt])
104
+ @reader = Reader.new(@input, @output, interrupt: options[:interrupt], env: @env)
81
105
  end
82
106
 
83
107
  # Ask a question.
@@ -139,7 +163,7 @@ module TTY
139
163
  # @api public
140
164
  def mask(message, *args, &block)
141
165
  options = Utils.extract_options!(args)
142
-
166
+ options.merge!({messages: self.class.messages})
143
167
  question = MaskQuestion.new(self, options)
144
168
  question.call(message, &block)
145
169
  end
@@ -452,5 +476,22 @@ module TTY
452
476
  def stderr
453
477
  $stderr
454
478
  end
479
+
480
+ # Inspect class name and public attributes
481
+ # @return [String]
482
+ #
483
+ # @api public
484
+ def inspect
485
+ attributes = {
486
+ input: input,
487
+ output: output,
488
+ prefix: prefix,
489
+ active_color: active_color,
490
+ error_color: error_color,
491
+ enabled_color: enabled_color,
492
+ help_color: help_color
493
+ }
494
+ "#<#{self.class}: #{attributes.each { |name, val| "@#{name}=#{val}" } }"
495
+ end
455
496
  end # Prompt
456
497
  end # TTY
@@ -2,6 +2,8 @@
2
2
 
3
3
  require 'forwardable'
4
4
 
5
+ require_relative 'choice'
6
+
5
7
  module TTY
6
8
  class Prompt
7
9
  # A class responsible for storing a collection of choices
@@ -1,5 +1,8 @@
1
1
  # encoding: utf-8
2
2
 
3
+ require_relative 'question'
4
+ require_relative 'utils'
5
+
3
6
  module TTY
4
7
  class Prompt
5
8
  class ConfirmQuestion < Question
@@ -75,7 +78,9 @@ module TTY
75
78
  header += @prompt.decorate(label, @active_color)
76
79
  end
77
80
  @prompt.print(header)
78
- @prompt.print("\n") if @done
81
+ @prompt.puts if @done
82
+
83
+ header.lines.count + (@done ? 1 : 0)
79
84
  end
80
85
 
81
86
  protected
@@ -1,18 +1,21 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty/prompt/converter_registry'
3
+ require_relative 'converter_registry'
4
4
 
5
5
  module TTY
6
6
  class Prompt
7
7
  module ConverterDSL
8
- def self.extended(base)
9
- attr_reader :converter_registry
10
-
11
- base.instance_variable_set(:@converter_registry, ConverterRegistry.new)
8
+ def converter_registry
9
+ @converter_registry ||= ConverterRegistry.new
12
10
  end
13
11
 
14
12
  def converter(name, &block)
15
- converter_registry.register(name, &block)
13
+ @converter_registry = converter_registry.register(name, &block)
14
+ self
15
+ end
16
+
17
+ def convert(name, data)
18
+ @converter_registry[name, data]
16
19
  end
17
20
  end # ConverterDSL
18
21
  end # Prompt