tty-prompt 0.13.2 → 0.14.0

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: 774726386ea09cc8c3fc2abd877e377eb3db3c3d
4
- data.tar.gz: 43ac05278ae482148a133e7b4ca1ad304e304189
3
+ metadata.gz: 914b91c8d5090e18ffa6da38c4e4ba7f26a7f50a
4
+ data.tar.gz: 0dea47a0af899dc93a532fc4371710807e8ef472
5
5
  SHA512:
6
- metadata.gz: d78bc4524d6e8183692e636d783d4c40c4666af82364084e67d3dae701dd9a2bd0695eeb4eac9925616bd054cf1edcca701307f016c3f9ea7a0756c6a0eedeac
7
- data.tar.gz: 6965d2d8df2dcffdfe33539d71da7426a185fca2a1649d665417cca03d4961edb20c45e2cd65c2f74784201b86ec3a4e7135b21de547f73db1e7da410b459f2f
6
+ metadata.gz: 9476326073c28e1c92c8b1a48fe66ce4769589ad44a15758ac376512a20f77065a5f78dc51a4b2c897f7825cf9d325d0c285700961c4a7f942c7a2bd8351bde8
7
+ data.tar.gz: 7206776eb52eb9451641be93db1de554bbbf94cdab014d8f5f21a4f46aa52acbd4cb50745806b6eb078f88eb863b97645483833d2df441cbb995245a64901912
data/.travis.yml CHANGED
@@ -2,17 +2,18 @@
2
2
  language: ruby
3
3
  sudo: false
4
4
  cache: bundler
5
+ before_install: "gem update bundler"
5
6
  bundler_args: --without tools
6
7
  script: "bundle exec rake ci"
7
8
  rvm:
8
- - 1.9.3
9
9
  - 2.0.0
10
10
  - 2.1.10
11
- - 2.2.6
12
- - 2.3.3
13
- - 2.4.1
11
+ - 2.2.8
12
+ - 2.3.6
13
+ - 2.4.3
14
14
  - ruby-head
15
15
  - jruby-9000
16
+ - jruby-9.1.1.0
16
17
  - jruby-head
17
18
  matrix:
18
19
  allow_failures:
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Change log
2
2
 
3
+ ## [v0.14.0] - 2018-01-01
4
+
5
+ ### Added
6
+ * Add :cycle option to #select, #multi_select & #enum_select prompts to allow toggling between infinite and bounded list by Jonas Müller(@muellerj)
7
+
8
+ ### Changed
9
+ * Change #multi_selct, #select & #enum_select to stop cycling options by default by Jona Müller(@muellerj)
10
+ * Change gemspec to require ruby >= 2.0.0
11
+ * Change #slider prompt to display slider next to query and help underneath
12
+ * Change to use tty-reader v0.2.0 with new line editing features for processing long inputs
13
+
14
+ ### Fixed
15
+ * Fix Paginator & EnumPaginator to allow only positive integer values by Andy Brody(@ab)
16
+ * Fix EnumSelect to report on default option out of range and raise correctly
17
+ * Fix #ask :file & :path converters to correctly locate the files
18
+ * Fix #ask, #multiline to correctly handle long strings that wrap around screen
19
+ * Fix #slider prompt to correctly scale sliding
20
+
3
21
  ## [v0.13.2] - 2017-08-30
4
22
 
5
23
  ### Changed
data/Gemfile CHANGED
@@ -6,7 +6,7 @@ gemspec
6
6
  # gem 'tty-reader', git: 'https://github.com/piotrmurach/tty-reader'
7
7
 
8
8
  group :test do
9
- gem 'benchmark-ips', '~> 2.0.0'
9
+ gem 'benchmark-ips', '~> 2.7.2'
10
10
  gem 'simplecov', '~> 0.10.0'
11
11
  gem 'coveralls', '~> 0.8.2'
12
12
  gem 'term-ansicolor', '=1.3.2'
@@ -17,6 +17,6 @@ group :tools do
17
17
  end
18
18
 
19
19
  group :metrics do
20
- gem 'yard', '~> 0.8.7'
20
+ gem 'yard', '~> 0.9.12'
21
21
  gem 'yardstick', '~> 0.9.9'
22
22
  end
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # TTY::Prompt [![Gitter](https://badges.gitter.im/Join%20Chat.svg)][gitter]
2
+
2
3
  [![Gem Version](https://badge.fury.io/rb/tty-prompt.svg)][gem]
3
4
  [![Build Status](https://secure.travis-ci.org/piotrmurach/tty-prompt.svg?branch=master)][travis]
4
5
  [![Build status](https://ci.appveyor.com/api/projects/status/4cguoiah5dprbq7n?svg=true)][appveyor]
@@ -25,6 +26,17 @@
25
26
  * User friendly error feedback
26
27
  * Intuitive DSL for creating complex menus
27
28
  * Ability to page long menus
29
+ * Support for Linux, OS X, FreeBSD and Windows systems
30
+
31
+ ## Windows support
32
+
33
+ `tty-prompt` works across all Unix and Windows systems in the "best possible" way. On Windows, it uses Win32 API in place of terminal device to provide matching functionality.
34
+
35
+ Since Unix terminals provide richer set of features than Windows PowerShell consoles, expect to have a better experience on Unix-like platform.
36
+
37
+ Some features like `select` or `multi_select` menus may not work on Windows when run from Git Bash. See GitHub suggested [fixes](https://github.com/git-for-windows/git/wiki/FAQ#some-native-console-programs-dont-work-when-run-from-git-bash-how-to-fix-it).
38
+
39
+ For Windows, consider installing [ConEmu](https://conemu.github.io/), [cmder](http://cmder.net/) or [PowerCmd](http://www.powercmd.com/).
28
40
 
29
41
  ## Installation
30
42
 
@@ -362,7 +374,7 @@ prompt.keypress("Press key ?")
362
374
  By default any key is accepted but you can limit keys by using `:keys` option. Any key event names such as `:space` or `:ctrl_k` are valid:
363
375
 
364
376
  ```ruby
365
- prompt.keypress("Press space or enter to continue, keys: [:space, :return])
377
+ prompt.keypress("Press space or enter to continue", keys: [:space, :return])
366
378
  ```
367
379
 
368
380
  #### 2.2.1 timeout
@@ -564,6 +576,17 @@ end
564
576
  # ‣ Jax
565
577
  ```
566
578
 
579
+ You can navigate the choices using the arrow keys or define your own keymappings (see [keyboard events](#212-keyboard-events). When reaching the top/bottom of the list, the selection does not cycle around by default. If you wish to enable cycling, you can pass `cycle: true` to `select` and `mutli_select`:
580
+
581
+ ```ruby
582
+ prompt.select("Choose your destiny?", %w(Scorpion Kano Jax), cycle: true)
583
+ # =>
584
+ # Choose your destiny? (Use arrow keys, press Enter to select)
585
+ # ‣ Scorpion
586
+ # Kano
587
+ # Jax
588
+ ```
589
+
567
590
  For ordered choices set `enum` to any delimiter String. In that way, you can use arrows keys and numbers (0-9) to select the item.
568
591
 
569
592
  ```ruby
@@ -704,6 +727,12 @@ And when you press enter you will see the following selected:
704
727
  # => [{score: 20}, {score: 50}]
705
728
  ```
706
729
 
730
+ Also like, `select`, the method takes an option `cycle` (which defaults to `false`), which lets you configure whether the selection should cycle around when reaching the top/bottom of the list when navigating:
731
+
732
+ ```ruby
733
+ prompt.multi_select("Select drinks?", %w(vodka beer wine), cycle: true)
734
+ ```
735
+
707
736
  You can configure help message and/or marker like so
708
737
 
709
738
  ```ruby
@@ -933,29 +962,47 @@ prompt.suggest('b', possible, indent: 4, single_text: 'Perhaps you meant?')
933
962
 
934
963
  ### 2.10 slider
935
964
 
936
- If you have constrained range of numbers for user to choose from you may consider using `slider`. The slider provides easy visual way of picking a value marked by `O` marker.
965
+ If you have constrained range of numbers for user to choose from you may consider using `slider`.
966
+
967
+ The slider provides easy visual way of picking a value marked by `O` marker. You can set `:min`(defaults to 0), `:max` and `:step`(defaults to 1) options to configure slider range:
937
968
 
938
969
  ```ruby
939
- prompt.slider('What size?', min: 32, max: 54, step: 2)
970
+ prompt.slider('Volume', max: 100, step: 5)
940
971
  # =>
941
- #
942
- # What size? (User arrow keys, press Enter to select)
943
- # |------O-----| 44
972
+ # Volume ──────────O────────── 50
973
+ # (User arrow keys, press Enter to select)
974
+ ```
975
+
976
+ By default the slider is configured to pick middle of the range as a start value, you can change this by using the `:default` option:
977
+
978
+ ```ruby
979
+ prompt.slider('Volume', max: 100, step: 5, default: 75)
980
+ # =>
981
+ # Volume ───────────────O───── 75
982
+ # (Use arrow keys, press Enter to select)
983
+ ```
984
+
985
+ You can also change the default slider formatting using the `:format`. The value must contain the `:slider` token for placing the actual animation and any `sprintf` compatible flag for number display, in our case `%d`:
986
+
987
+ ```ruby
988
+ prompt.slider('Volume', max: 100, step: 5, default: 75, format: "|:slider| %d%")
989
+ # =>
990
+ # Volume |───────────────O─────| 75%
991
+ # (Use arrow keys, press Enter to select)
944
992
  ```
945
993
 
946
994
  Slider can be configured through DSL as well:
947
995
 
948
996
  ```ruby
949
997
  prompt.slider('What size?') do |range|
950
- range.default 4
951
- range.min 0
952
- range.max 20
953
- range.step 2
998
+ range.max 100
999
+ range.step 5
1000
+ range.default 75
1001
+ range.format "|:slider| %d%"
954
1002
  end
955
1003
  # =>
956
- #
957
- # What size? (User arrow keys, press Enter to select)
958
- # |--O-------| 4
1004
+ # Volume |───────────────O─────| 75%
1005
+ # (Use arrow keys, press Enter to select)
959
1006
  ```
960
1007
 
961
1008
  ### 2.11 say
@@ -1129,4 +1176,4 @@ This project is intended to be a safe, welcoming space for collaboration, and co
1129
1176
 
1130
1177
  ## Copyright
1131
1178
 
1132
- Copyright (c) 2015-2017 Piotr Murach. See LICENSE for further details.
1179
+ Copyright (c) 2015-2018 Piotr Murach. See LICENSE for further details.
data/appveyor.yml CHANGED
@@ -9,7 +9,6 @@ test_script:
9
9
  - bundle exec rake ci
10
10
  environment:
11
11
  matrix:
12
- - ruby_version: "193"
13
12
  - ruby_version: "200"
14
13
  - ruby_version: "200-x64"
15
14
  - ruby_version: "21"
@@ -20,6 +19,3 @@ environment:
20
19
  - ruby_version: "23-x64"
21
20
  - ruby_version: "24"
22
21
  - ruby_version: "24-x64"
23
- matrix:
24
- allow_failures:
25
- - ruby_version: "193"
data/benchmarks/speed.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  # coding: utf-8
2
2
 
3
- require 'tty-prompt'
4
3
  require 'benchmark/ips'
5
4
  require 'stringio'
5
+ require_relative '../lib/tty-prompt'
6
6
 
7
7
  input = ::StringIO.new
8
8
  output = ::StringIO.new
data/examples/ask.rb CHANGED
@@ -1,15 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt.new
6
6
 
7
7
  prompt.ask('What is your name?', default: ENV['USER'])
8
-
9
- prompt.ask('Folder name?') do |q|
10
- q.required(true)
11
- q.validate ->(v) { return !Dir.exist?(v) }
12
- q.messages[:valid?] = 'Folder already exists?'
13
- q.messages[:required?] = 'Folder name must not be empty'
14
- end
15
-
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+
3
+ require_relative "../lib/tty-prompt"
4
+
5
+ prompt = TTY::Prompt.new
6
+
7
+ prompt.ask('Folder name?') do |q|
8
+ q.required(true)
9
+ q.validate ->(v) { return !Dir.exist?(v) }
10
+ q.messages[:valid?] = 'Folder already exists?'
11
+ q.messages[:required?] = 'Folder name must not be empty'
12
+ end
data/examples/collect.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require 'json'
4
+
5
+ require_relative "../lib/tty-prompt"
4
6
 
5
7
  prompt = TTY::Prompt.new(prefix: '[?] ')
6
8
 
@@ -16,4 +18,4 @@ result = prompt.collect do
16
18
  end
17
19
  end
18
20
 
19
- puts result
21
+ puts JSON.pretty_generate(result)
data/examples/echo.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt.new
6
6
 
@@ -8,4 +8,4 @@ answer = prompt.ask('Password?', echo: false) do |q|
8
8
  q.validate(/^[^\.]+\.[^\.]+/)
9
9
  end
10
10
 
11
- #puts answer
11
+ puts "Password: #{answer}"
data/examples/enum.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt.new
6
6
 
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt.new
6
6
 
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt.new
6
6
  choices = %w(/bin/nano /usr/bin/vim.basic /usr/bin/vim.tiny)
data/examples/expand.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  choices = [{
6
6
  key: 'y',
data/examples/in.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt.new
6
6
 
data/examples/inputs.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt.new
6
6
 
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt::new(interrupt: :exit)
6
6
 
data/examples/keypress.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt::new
6
6
 
data/examples/mask.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
  require 'pastel'
5
5
 
6
6
  prompt = TTY::Prompt.new
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt.new
6
6
 
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt.new
6
6
 
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt::new
6
6
 
data/examples/pause.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt::new
6
6
 
data/examples/select.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt.new
6
6
 
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt.new
6
6
 
data/examples/slider.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt.new
6
- prompt.slider("What size?", min: 0, max: 40, step: 1)
6
+ prompt.slider("Volume", max: 100, step: 5, default: 75, format: "|:slider| %d%")
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt.new
6
6
 
data/examples/yes_no.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'tty-prompt'
3
+ require_relative "../lib/tty-prompt"
4
4
 
5
5
  prompt = TTY::Prompt.new
6
6
 
data/lib/tty/prompt.rb CHANGED
@@ -75,7 +75,8 @@ module TTY
75
75
  :show, :hide
76
76
 
77
77
  def_delegators :@reader, :read_char, :read_line, :read_keypress,
78
- :read_multiline, :on, :subscribe, :trigger
78
+ :read_multiline, :on, :subscribe, :trigger,
79
+ :count_screen_lines
79
80
 
80
81
  def_delegators :@output, :print, :puts, :flush
81
82
 
@@ -127,8 +128,13 @@ module TTY
127
128
 
128
129
  @cursor = TTY::Cursor
129
130
  @pastel = Pastel.new(@enabled_color.nil? ? {} : { enabled: @enabled_color })
130
- @reader = TTY::Reader.new(@input, @output, interrupt: @interrupt,
131
- track_history: @track_history, env: @env)
131
+ @reader = TTY::Reader.new(
132
+ input: @input,
133
+ output: @output,
134
+ interrupt: @interrupt,
135
+ track_history: @track_history,
136
+ env: @env
137
+ )
132
138
  end
133
139
 
134
140
  # Invoke a question type of prompt
@@ -60,13 +60,11 @@ module TTY
60
60
  end
61
61
 
62
62
  converter(:file) do |input|
63
- directory = ::File.expand_path(::File.dirname($0))
64
- ::File.open(::File.join(directory, input))
63
+ ::File.open(::File.join(Dir.pwd, input))
65
64
  end
66
65
 
67
66
  converter(:path) do |input|
68
- directory = ::File.expand_path(::File.dirname($0))
69
- Pathname.new(::File.join(directory, input))
67
+ Pathname.new(::File.join(Dir.pwd, input))
70
68
  end
71
69
 
72
70
  converter(:char) do |input|
@@ -24,6 +24,7 @@ module TTY
24
24
  @active_color = options.fetch(:active_color) { @prompt.active_color }
25
25
  @help_color = options.fetch(:help_color) { @prompt.help_color }
26
26
  @error_color = options.fetch(:error_color) { @prompt.error_color }
27
+ @cycle = options.fetch(:cycle) { false }
27
28
  @input = nil
28
29
  @done = false
29
30
  @first_render = true
@@ -139,7 +140,7 @@ module TTY
139
140
  def keyright(*)
140
141
  if (@page_active + page_size) <= @choices.size
141
142
  @page_active += page_size
142
- else
143
+ elsif @cycle
143
144
  @page_active = 1
144
145
  end
145
146
  end
@@ -148,7 +149,7 @@ module TTY
148
149
  def keyleft(*)
149
150
  if (@page_active - page_size) >= 0
150
151
  @page_active -= page_size
151
- else
152
+ elsif @cycle
152
153
  @page_active = @choices.size - 1
153
154
  end
154
155
  end
@@ -174,8 +175,8 @@ module TTY
174
175
  # @api private
175
176
  def validate_defaults
176
177
  return if @default >= 1 && @default <= @choices.size
177
- raise PromptConfigurationError,
178
- "default index `#{d}` out of range (1 - #{@choices.size})"
178
+ raise ConfigurationError,
179
+ "default index `#{@default}` out of range (1 - #{@choices.size})"
179
180
  end
180
181
 
181
182
  # Setup default option and active selection
@@ -13,6 +13,8 @@ module TTY
13
13
  default_size = (list.size <= DEFAULT_PAGE_SIZE ? list.size : DEFAULT_PAGE_SIZE)
14
14
  @per_page = @per_page || per_page || default_size
15
15
 
16
+ check_page_size!
17
+
16
18
  # Don't paginate short lists
17
19
  if list.size <= @per_page
18
20
  @lower_index = 0
@@ -25,7 +25,9 @@ module TTY
25
25
  @interval_handler = proc { |time|
26
26
  unless @done
27
27
  question = render_question
28
- @prompt.print(refresh(question.lines.count))
28
+ line_size = question.size
29
+ total_lines = @prompt.count_screen_lines(line_size)
30
+ @prompt.print(refresh(question.lines.count, total_lines))
29
31
  countdown(time)
30
32
  @prompt.print(render_question)
31
33
  end
@@ -70,6 +72,7 @@ module TTY
70
72
 
71
73
  def process_input(question)
72
74
  time do
75
+ @prompt.print(render_question)
73
76
  until @done
74
77
  @input = @prompt.read_keypress(nonblock: true)
75
78
  end
@@ -77,7 +80,7 @@ module TTY
77
80
  @evaluator.(@input)
78
81
  end
79
82
 
80
- def refresh(lines)
83
+ def refresh(lines, lines_to_clear)
81
84
  @prompt.clear_lines(lines)
82
85
  end
83
86
 
@@ -41,6 +41,7 @@ module TTY
41
41
  @active_color = options.fetch(:active_color) { @prompt.active_color }
42
42
  @help_color = options.fetch(:help_color) { @prompt.help_color }
43
43
  @marker = options.fetch(:marker) { symbols[:pointer] }
44
+ @cycle = options.fetch(:cycle) { false }
44
45
  @help = options[:help]
45
46
  @first_render = true
46
47
  @done = false
@@ -169,20 +170,26 @@ module TTY
169
170
  @active = value
170
171
  end
171
172
 
172
- def keyspace(*)
173
- @done = true
174
- end
175
-
176
- def keyreturn(*)
173
+ def keyenter(*)
177
174
  @done = true
178
175
  end
176
+ alias keyreturn keyenter
177
+ alias keyspace keyenter
179
178
 
180
179
  def keyup(*)
181
- @active = (@active == 1) ? @choices.length : @active - 1
180
+ if @active == 1
181
+ @active = @choices.length if @cycle
182
+ else
183
+ @active -= 1
184
+ end
182
185
  end
183
186
 
184
187
  def keydown(*)
185
- @active = (@active == @choices.length) ? 1 : @active + 1
188
+ if @active == @choices.length
189
+ @active = 1 if @cycle
190
+ else
191
+ @active += 1
192
+ end
186
193
  end
187
194
  alias keytab keydown
188
195
 
@@ -78,9 +78,12 @@ module TTY
78
78
  @done_masked = false
79
79
  @failure = false
80
80
  @input = ''
81
+ @prompt.print(question)
81
82
  until @done_masked
82
83
  @prompt.read_keypress
83
- @prompt.print(@prompt.clear_line)
84
+ question = render_question
85
+ total_lines = @prompt.count_screen_lines(question)
86
+ @prompt.print(@prompt.clear_lines(total_lines))
84
87
  @prompt.print(render_question)
85
88
  end
86
89
  @prompt.puts
@@ -54,6 +54,7 @@ module TTY
54
54
  end
55
55
 
56
56
  def process_input(question)
57
+ @prompt.print(question)
57
58
  @lines = read_input
58
59
  @input = "#{@lines.first.strip} ..." unless @lines.first.to_s.empty?
59
60
  if Utils.blank?(@input)
@@ -62,8 +63,8 @@ module TTY
62
63
  @evaluator.(@lines)
63
64
  end
64
65
 
65
- def refresh(lines)
66
- size = @lines_count + lines + 1
66
+ def refresh(lines, lines_to_clear)
67
+ size = @lines_count + lines_to_clear + 1
67
68
  @prompt.clear_lines(size)
68
69
  end
69
70
  end # Multiline
@@ -24,6 +24,15 @@ module TTY
24
24
  @lower_index + @per_page - 1
25
25
  end
26
26
 
27
+ # Check if page size is valid
28
+ #
29
+ # @raise [InvalidArgument]
30
+ #
31
+ # @api private
32
+ def check_page_size!
33
+ raise InvalidArgument, 'per_page must be > 0' if @per_page < 1
34
+ end
35
+
27
36
  # Paginate collection given an active index
28
37
  #
29
38
  # @param [Array[Choice]] list
@@ -43,6 +52,8 @@ module TTY
43
52
  @lower_index ||= current_index
44
53
  @upper_index ||= max_index
45
54
 
55
+ check_page_size!
56
+
46
57
  # Don't paginate short lists
47
58
  if list.size <= @per_page
48
59
  @lower_index = 0
@@ -107,16 +107,17 @@ module TTY
107
107
  def render
108
108
  @errors = []
109
109
  until @done
110
- question = render_question
111
- @prompt.print(question)
112
- result = process_input(question)
110
+ result = process_input(render_question)
113
111
  if result.failure?
114
112
  @errors = result.errors
115
113
  @prompt.print(render_error(result.errors))
116
114
  else
117
115
  @done = true
118
116
  end
119
- @prompt.print(refresh(question.lines.count))
117
+ question = render_question
118
+ input_line = question + result.value.to_s
119
+ total_lines = @prompt.count_screen_lines(input_line)
120
+ @prompt.print(refresh(question.lines.count, total_lines))
120
121
  end
121
122
  @prompt.print(render_question)
122
123
  convert_result(result.value)
@@ -164,11 +165,10 @@ module TTY
164
165
  #
165
166
  # @api private
166
167
  def render_error(errors)
167
- errors.reduce('') do |acc, err|
168
- newline = (@echo ? '' : "\n")
169
- acc << newline + @prompt.decorate('>>', :red) + ' ' + err
168
+ errors.reduce([]) do |acc, err|
169
+ acc << @prompt.decorate('>>', :red) + ' ' + err
170
170
  acc
171
- end
171
+ end.join("\n")
172
172
  end
173
173
 
174
174
  # Determine area of the screen to clear
@@ -179,18 +179,19 @@ module TTY
179
179
  # @return [String]
180
180
  #
181
181
  # @api private
182
- def refresh(lines)
182
+ def refresh(lines, lines_to_clear)
183
183
  output = ''
184
184
  if @done
185
- if @errors.count.zero? && @echo
185
+ if @errors.count.zero?
186
186
  output << @prompt.cursor.up(lines)
187
187
  else
188
188
  lines += @errors.count
189
+ lines_to_clear += @errors.count
189
190
  end
190
191
  else
191
192
  output << @prompt.cursor.up(lines)
192
193
  end
193
- output + @prompt.clear_lines(lines)
194
+ output + @prompt.clear_lines(lines_to_clear)
194
195
  end
195
196
 
196
197
  # Convert value to expected type
@@ -13,8 +13,19 @@ module TTY
13
13
 
14
14
  HELP = '(Use arrow keys, press Enter to select)'.freeze
15
15
 
16
+ FORMAT = ':slider %d'.freeze
17
+
16
18
  # Initailize a Slider
17
19
  #
20
+ # @param [Prompt] prompt
21
+ # the prompt
22
+ # @param [Hash] options
23
+ # the options to configure this slider
24
+ # @option options [Integer] :min The minimum value
25
+ # @option options [Integer] :max The maximum value
26
+ # @option options [Integer] :step The step value
27
+ # @option options [String] :format The display format
28
+ #
18
29
  # @api public
19
30
  def initialize(prompt, options = {})
20
31
  @prompt = prompt
@@ -25,6 +36,7 @@ module TTY
25
36
  @default = options[:default]
26
37
  @active_color = options.fetch(:active_color) { @prompt.active_color }
27
38
  @help_color = options.fetch(:help_color) { @prompt.help_color }
39
+ @format = options.fetch(:format) { FORMAT }
28
40
  @first_render = true
29
41
  @done = false
30
42
 
@@ -73,6 +85,10 @@ module TTY
73
85
  @step = value
74
86
  end
75
87
 
88
+ def format(value)
89
+ @format = value
90
+ end
91
+
76
92
  # Call the slider by passing question
77
93
  #
78
94
  # @param [String] question
@@ -89,17 +105,18 @@ module TTY
89
105
  def keyleft(*)
90
106
  @active -= 1 if @active > 0
91
107
  end
92
- alias_method :keydown, :keyleft
108
+ alias keydown keyleft
93
109
 
94
110
  def keyright(*)
95
- @active += 1 if (@active + @step) < range.size
111
+ @active += 1 if (@active + 1) < range.size
96
112
  end
97
- alias_method :keyup, :keyright
113
+ alias keyup keyright
98
114
 
99
115
  def keyreturn(*)
100
116
  @done = true
101
117
  end
102
- alias_method :keyspace, :keyreturn
118
+ alias keyspace keyreturn
119
+ alias keyenter keyreturn
103
120
 
104
121
  private
105
122
 
@@ -143,23 +160,18 @@ module TTY
143
160
  #
144
161
  # @api private
145
162
  def render_question
146
- header = "#{@prefix}#{@question} #{render_header}\n"
147
- @first_render = false
148
- header << render_slider unless @done
149
- header
150
- end
151
-
152
- # Render actual answer or help
153
- #
154
- # @return [String]
155
- #
156
- # @api private
157
- def render_header
163
+ header = "#{@prefix}#{@question} "
158
164
  if @done
159
- @prompt.decorate(answer.to_s, @active_color)
160
- elsif @first_render
161
- @prompt.decorate(HELP, @help_color)
165
+ header << @prompt.decorate(answer.to_s, @active_color)
166
+ header << "\n"
167
+ else
168
+ header << render_slider
169
+ end
170
+ if @first_render
171
+ header << "\n" + @prompt.decorate(HELP, @help_color)
172
+ @first_render = false
162
173
  end
174
+ header
163
175
  end
164
176
 
165
177
  # Render slider representation
@@ -168,14 +180,11 @@ module TTY
168
180
  #
169
181
  # @api private
170
182
  def render_slider
171
- output = ''
172
- output << symbols[:pipe]
173
- output << symbols[:line] * @active
174
- output << @prompt.decorate(symbols[:handle], @active_color)
175
- output << symbols[:line] * (range.size - @active - 1)
176
- output << symbols[:pipe]
177
- output << " #{range[@active]}"
178
- output
183
+ slider = (symbols[:line] * @active) +
184
+ @prompt.decorate(symbols[:handle], @active_color) +
185
+ (symbols[:line] * (range.size - @active - 1))
186
+ value = " #{range[@active]}"
187
+ @format.gsub(':slider', slider) % [value]
179
188
  end
180
189
  end # Slider
181
190
  end # Prompt
@@ -10,6 +10,8 @@ module TTY
10
10
  tick: '✓',
11
11
  cross: '✘',
12
12
  star: '★',
13
+ square: '◼',
14
+ square_empty: '◻',
13
15
  dot: '•',
14
16
  pointer: '‣',
15
17
  line: '─',
@@ -28,6 +30,8 @@ module TTY
28
30
  tick: '√',
29
31
  cross: '×',
30
32
  star: '*',
33
+ square: '[█]',
34
+ square_empty: '[ ]',
31
35
  dot: '.',
32
36
  pointer: '>',
33
37
  line: '-',
@@ -2,6 +2,6 @@
2
2
 
3
3
  module TTY
4
4
  class Prompt
5
- VERSION = "0.13.2"
5
+ VERSION = '0.14.0'.freeze
6
6
  end # Prompt
7
7
  end # TTY
data/tty-prompt.gemspec CHANGED
@@ -20,13 +20,15 @@ Gem::Specification.new do |spec|
20
20
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
21
  spec.require_paths = ["lib"]
22
22
 
23
+ spec.required_ruby_version = '>= 2.0.0'
24
+
23
25
  spec.add_dependency 'necromancer', '~> 0.4.0'
24
26
  spec.add_dependency 'pastel', '~> 0.7.0'
25
27
  spec.add_dependency 'timers', '~> 4.1.2'
26
28
  spec.add_dependency 'tty-cursor', '~> 0.5.0'
27
- spec.add_dependency 'tty-reader', '~> 0.1.0'
29
+ spec.add_dependency 'tty-reader', '~> 0.2.0'
28
30
 
29
31
  spec.add_development_dependency 'bundler', '>= 1.5.0', '< 2.0'
30
32
  spec.add_development_dependency 'rake'
31
- spec.add_development_dependency 'rspec', '~> 3.5.0'
33
+ spec.add_development_dependency 'rspec', '~> 3.0'
32
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tty-prompt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.2
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Murach
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-30 00:00:00.000000000 Z
11
+ date: 2018-01-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: necromancer
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 0.1.0
75
+ version: 0.2.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 0.1.0
82
+ version: 0.2.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: bundler
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -120,14 +120,14 @@ dependencies:
120
120
  requirements:
121
121
  - - "~>"
122
122
  - !ruby/object:Gem::Version
123
- version: 3.5.0
123
+ version: '3.0'
124
124
  type: :development
125
125
  prerelease: false
126
126
  version_requirements: !ruby/object:Gem::Requirement
127
127
  requirements:
128
128
  - - "~>"
129
129
  - !ruby/object:Gem::Version
130
- version: 3.5.0
130
+ version: '3.0'
131
131
  description: A beautiful and powerful interactive command line prompt with a robust
132
132
  API for getting and validating complex inputs.
133
133
  email:
@@ -148,6 +148,7 @@ files:
148
148
  - appveyor.yml
149
149
  - benchmarks/speed.rb
150
150
  - examples/ask.rb
151
+ - examples/ask_valid.rb
151
152
  - examples/collect.rb
152
153
  - examples/echo.rb
153
154
  - examples/enum.rb
@@ -217,7 +218,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
217
218
  requirements:
218
219
  - - ">="
219
220
  - !ruby/object:Gem::Version
220
- version: '0'
221
+ version: 2.0.0
221
222
  required_rubygems_version: !ruby/object:Gem::Requirement
222
223
  requirements:
223
224
  - - ">="
@@ -230,4 +231,3 @@ signing_key:
230
231
  specification_version: 4
231
232
  summary: A beautiful and powerful interactive command line prompt.
232
233
  test_files: []
233
- has_rdoc: