pecorb 1.1.0 → 2.0.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: dc95ef88893133f15ebad8a99f97f2c1dc2ad1c1
4
- data.tar.gz: 51edf909a9588acaae62f4d7caffef90749b507d
3
+ metadata.gz: ac862459ac7398a7e517d4d1b169e1b76c78c676
4
+ data.tar.gz: c234e84d93a3089facd5d786cc5d25f10b93fe70
5
5
  SHA512:
6
- metadata.gz: 46f6e081725eff2335c66f39419aed3633fb3129ae1621bba1ac1c6091e1429cbab228ab93fb173659cfa384b0ff254a24dccc3f26be5312d8cfa0920f7eb1b0
7
- data.tar.gz: e61814a55c82e153708fd76ffb43605874f05201da8cd46ff64303dab70f84dada79f9fcd88d10742c085a8d9e578aed47b974042695794c8b3a7f412a95ca13
6
+ metadata.gz: ab9498a864ed1a74adeddb706a08b069ab11438015213fb19e8788462ea8ed4e029bf5611c6a1ac2e9d6e17fca9742cfd52664c9da41a6f780e34dc59c7d5697
7
+ data.tar.gz: 723c86474c4a89ec9d1bc1efcc4f02e84539c0fa2a2825eac0a1b7e706ab28d6fe4b09742f8f1c20a48035e74e229a0fc3a818771a4fff51bf1423517b30e768
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile.lock CHANGED
@@ -1,22 +1,74 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pecorb (1.1.0)
4
+ pecorb (2.0.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- minitest (5.9.1)
9
+ byebug (9.0.6)
10
+ coderay (1.1.1)
11
+ diff-lcs (1.2.5)
12
+ ffi (1.9.14)
13
+ formatador (0.2.5)
14
+ guard (2.14.0)
15
+ formatador (>= 0.2.4)
16
+ listen (>= 2.7, < 4.0)
17
+ lumberjack (~> 1.0)
18
+ nenv (~> 0.1)
19
+ notiffany (~> 0.0)
20
+ pry (>= 0.9.12)
21
+ shellany (~> 0.0)
22
+ thor (>= 0.18.1)
23
+ listen (3.1.5)
24
+ rb-fsevent (~> 0.9, >= 0.9.4)
25
+ rb-inotify (~> 0.9, >= 0.9.7)
26
+ ruby_dep (~> 1.2)
27
+ lumberjack (1.0.10)
28
+ method_source (0.8.2)
29
+ nenv (0.3.0)
30
+ notiffany (0.1.1)
31
+ nenv (~> 0.1)
32
+ shellany (~> 0.0)
33
+ pry (0.10.4)
34
+ coderay (~> 1.1.0)
35
+ method_source (~> 0.8.1)
36
+ slop (~> 3.4)
37
+ pry-byebug (3.4.0)
38
+ byebug (~> 9.0)
39
+ pry (~> 0.10)
10
40
  rake (10.4.2)
41
+ rb-fsevent (0.9.8)
42
+ rb-inotify (0.9.7)
43
+ ffi (>= 0.5.0)
44
+ rspec (3.5.0)
45
+ rspec-core (~> 3.5.0)
46
+ rspec-expectations (~> 3.5.0)
47
+ rspec-mocks (~> 3.5.0)
48
+ rspec-core (3.5.4)
49
+ rspec-support (~> 3.5.0)
50
+ rspec-expectations (3.5.0)
51
+ diff-lcs (>= 1.2.0, < 2.0)
52
+ rspec-support (~> 3.5.0)
53
+ rspec-mocks (3.5.0)
54
+ diff-lcs (>= 1.2.0, < 2.0)
55
+ rspec-support (~> 3.5.0)
56
+ rspec-support (3.5.0)
57
+ ruby_dep (1.5.0)
58
+ shellany (0.0.1)
59
+ slop (3.6.0)
60
+ thor (0.19.4)
11
61
 
12
62
  PLATFORMS
13
63
  ruby
14
64
 
15
65
  DEPENDENCIES
16
- bundler (~> 1.13)
17
- minitest (~> 5.0)
66
+ bundler
67
+ guard
18
68
  pecorb!
19
- rake (~> 10.0)
69
+ pry-byebug
70
+ rake
71
+ rspec
20
72
 
21
73
  BUNDLED WITH
22
74
  1.13.3
data/Guardfile ADDED
@@ -0,0 +1,70 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec features) \
6
+ # .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
7
+
8
+ ## Note: if you are using the `directories` clause above and you are not
9
+ ## watching the project directory ('.'), then you will want to move
10
+ ## the Guardfile to a watched dir and symlink it back, e.g.
11
+ #
12
+ # $ mkdir config
13
+ # $ mv Guardfile config/
14
+ # $ ln -s config/Guardfile .
15
+ #
16
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
17
+
18
+ # Note: The cmd option is now required due to the increasing number of ways
19
+ # rspec may be run, below are examples of the most common uses.
20
+ # * bundler: 'bundle exec rspec'
21
+ # * bundler binstubs: 'bin/rspec'
22
+ # * spring: 'bin/rspec' (This will use spring if running and you have
23
+ # installed the spring binstubs per the docs)
24
+ # * zeus: 'zeus rspec' (requires the server to be started separately)
25
+ # * 'just' rspec: 'rspec'
26
+
27
+ guard :rspec, cmd: "bundle exec rspec" do
28
+ require "guard/rspec/dsl"
29
+ dsl = Guard::RSpec::Dsl.new(self)
30
+
31
+ # Feel free to open issues for suggestions and improvements
32
+
33
+ # RSpec files
34
+ rspec = dsl.rspec
35
+ watch(rspec.spec_helper) { rspec.spec_dir }
36
+ watch(rspec.spec_support) { rspec.spec_dir }
37
+ watch(rspec.spec_files)
38
+
39
+ # Ruby files
40
+ ruby = dsl.ruby
41
+ dsl.watch_spec_files_for(ruby.lib_files)
42
+
43
+ # Rails files
44
+ rails = dsl.rails(view_extensions: %w(erb haml slim))
45
+ dsl.watch_spec_files_for(rails.app_files)
46
+ dsl.watch_spec_files_for(rails.views)
47
+
48
+ watch(rails.controllers) do |m|
49
+ [
50
+ rspec.spec.call("routing/#{m[1]}_routing"),
51
+ rspec.spec.call("controllers/#{m[1]}_controller"),
52
+ rspec.spec.call("acceptance/#{m[1]}")
53
+ ]
54
+ end
55
+
56
+ # Rails config changes
57
+ watch(rails.spec_helper) { rspec.spec_dir }
58
+ watch(rails.routes) { "#{rspec.spec_dir}/routing" }
59
+ watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
60
+
61
+ # Capybara features specs
62
+ watch(rails.view_dirs) { |m| rspec.spec.call("features/#{m[1]}") }
63
+ watch(rails.layouts) { |m| rspec.spec.call("features/#{m[1]}") }
64
+
65
+ # Turnip features and steps
66
+ watch(%r{^spec/acceptance/(.+)\.feature$})
67
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
68
+ Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance"
69
+ end
70
+ end
data/README.md CHANGED
@@ -6,17 +6,11 @@ It is based on `inquirer.js` and `peco` (which itself is based on `percol`).
6
6
  The above mentioned tools are all more feature rich than this one (and I'm sure
7
7
  the code is better too), but I wanted a few different features:
8
8
 
9
- - A list that can be navigated using the arrow keys (like `enquirer`)
9
+ - A list that can be navigated using the keyboard (like `enquirer`)
10
10
  - Fuzzy filterable (like `ctrl-p` in vim, etc.)
11
11
  - Not take over the entire screen (like curses interfaces normally do)
12
- - (Ideally) dependency free
12
+ - Dependency free (except for development dependencies)
13
13
 
14
- ## Status
15
-
16
- Currently this works well on the command line but may still have some bugs.
17
- Using it as part of a ruby program still needs to be tested.
18
-
19
- This was written during a hackathon and has no tests :'(
20
14
 
21
15
  ## Installation
22
16
 
@@ -27,12 +21,15 @@ gem 'pecorb'
27
21
  ```
28
22
 
29
23
  And then execute:
24
+ ```
25
+ $ bundle
26
+ ```
30
27
 
31
- $ bundle
32
-
33
- Or install it yourself as:
28
+ Or install it system wide for use on the command line:
29
+ ```
30
+ $ gem install pecorb
31
+ ```
34
32
 
35
- $ gem install pecorb
36
33
 
37
34
  ## Usage
38
35
 
@@ -46,10 +43,30 @@ pecorb myFile.txt
46
43
  For use in a ruby program:
47
44
 
48
45
  ```ruby
49
- Pecorb.prompt %w[Apples Bananas Cake Donuts]
50
- Pecorb.prompt %w[Apples Bananas Cake Donuts], "Favourite food: "
46
+ result = Pecorb.list %w[Apples Bananas Cake Donuts]
47
+ result = Pecorb.list %w[Apples Bananas Cake Donuts], prompt: "Favourite food: "
51
48
  ```
52
49
 
50
+
51
+ ## Key Bindings
52
+
53
+ - `up` and `ctrl-k` will move up through the list
54
+ - `down` and `ctrl-j` will move down through the list
55
+ - `ctrl-l` will clear the screen and re-print the menu
56
+ - `crtl-c` and `escape` will exit (with exit code `0`)
57
+ - `ctrl-d` (`eof`) and `enter` (`\r`) will select the item
58
+ - `baskspace`, `left` and `right` do what you would expect
59
+
60
+
61
+ ## Status
62
+
63
+ Currently this seems to work well on the command line and as a ruby library.
64
+
65
+ There are some tests but not great coverage. The complex parts are mainly the
66
+ paging logic (which does have tests) and the random access terminal printing
67
+ that makes up the user interface (which doesn't have tests).
68
+
69
+
53
70
  ## Development
54
71
 
55
72
  After checking out the repo, run `bundle install` to install dependencies.
@@ -60,16 +77,19 @@ run `bundle install` and `bundle exec rake release`, which will create a git
60
77
  tag for the version, push git commits and tags, and push the `.gem` file to
61
78
  [rubygems.org](https://rubygems.org).
62
79
 
80
+
63
81
  ## Contributing
64
82
 
65
83
  Bug reports and pull requests are welcome on GitHub at
66
84
  https://github.com/stevenocchipinti/pecorb.
67
85
 
86
+
68
87
  ## License
69
88
 
70
89
  The gem is available as open source under the terms of the
71
90
  [MIT License](http://opensource.org/licenses/MIT).
72
91
 
92
+
73
93
  ## Kudos
74
94
 
75
95
  Inspiration and education came from these resources:
data/bin/pecorb CHANGED
@@ -1,10 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
  require_relative "../lib/pecorb"
3
3
 
4
+ Pecorb.configure do |config|
5
+ config.output_stream = $stdout.isatty ? $stdout : $stderr
6
+ end
7
+
4
8
  input = ARGF.readlines.map(&:strip).reject(&:empty?)
5
9
 
6
10
  # After reading from $stdin (file, pipe, etc.), switch $stdin to be the users
7
- # terminal to present the prompt
11
+ # terminal so they can interact with the prompt
8
12
  $stdin.reopen(File.open("/dev/tty", "r"))
9
13
 
10
- Pecorb.prompt input unless input.empty?
14
+ $stdout.puts Pecorb.list input unless input.empty?
@@ -0,0 +1,10 @@
1
+ # This method was introduced in ruby 2.4, however this patch will allow this
2
+ # feature to be available in older versions fo ruby
3
+
4
+ module Comparable
5
+ def clamp(min, max)
6
+ return min if self < min
7
+ return max if self > max
8
+ self
9
+ end
10
+ end
@@ -1,56 +1,71 @@
1
1
  require "io/console"
2
+ require_relative "../pecorb"
2
3
 
3
- module Console
4
- CSI = "\e["
5
- UP = "#{CSI}A"
6
- DOWN = "#{CSI}B"
7
- RIGHT = "#{CSI}C"
8
- LEFT = "#{CSI}D"
9
-
10
- def read_char
11
- $stdin.echo = false
12
- $stdin.raw!
13
- input = $stdin.getc.chr
14
- if input == "\e" then
15
- input << $stdin.read_nonblock(3) rescue nil
16
- input << $stdin.read_nonblock(2) rescue nil
4
+ module Pecorb
5
+ module Console
6
+ CSI = "\e["
7
+ UP = "#{CSI}A"
8
+ DOWN = "#{CSI}B"
9
+ RIGHT = "#{CSI}C"
10
+ LEFT = "#{CSI}D"
11
+
12
+ def read_char
13
+ input_stream.echo = false
14
+ input_stream.raw!
15
+ input = input_stream.getc.chr
16
+ if input == "\e" then
17
+ input << input_stream.read_nonblock(3) rescue nil
18
+ input << input_stream.read_nonblock(2) rescue nil
19
+ end
20
+ ensure
21
+ input_stream.echo = true
22
+ input_stream.cooked!
23
+ return input
24
+ end
25
+
26
+ def puts(val="") output_stream.puts val end
27
+ def print(val="") output_stream.print val end
28
+
29
+ def up(n=1) output_stream.print "#{CSI}#{n}A" end
30
+ def down(n=1) output_stream.print "#{CSI}#{n}B" end
31
+ def right(n=1) output_stream.print "#{CSI}#{n}C" end
32
+ def left(n=1) output_stream.print "#{CSI}#{n}D" end
33
+
34
+ def backspace(n=1) output_stream.print "\b"*n end
35
+ def carriage_return() output_stream.print "\r" end
36
+ def clear_to_eol() output_stream.print "#{CSI}K" end
37
+ def clear_to_eos() output_stream.print "#{CSI}J" end
38
+ def clear_screen() output_stream.print "#{CSI}H#{CSI}J" end
39
+
40
+ def black() output_stream.print "#{CSI}#{CSI}30m" end
41
+ def red() output_stream.print "#{CSI}#{CSI}31m" end
42
+ def green() output_stream.print "#{CSI}#{CSI}32m" end
43
+ def yellow() output_stream.print "#{CSI}#{CSI}33m" end
44
+ def blue() output_stream.print "#{CSI}#{CSI}34m" end
45
+ def magenta() output_stream.print "#{CSI}#{CSI}35m" end
46
+ def cyan() output_stream.print "#{CSI}#{CSI}36m" end
47
+ def white() output_stream.print "#{CSI}#{CSI}37m" end
48
+ def reset_color() output_stream.print "#{CSI}#{CSI}0m" end
49
+
50
+ # WARNING: Only use this for updates, when we can be sure no new lines will
51
+ # be added as this causes lines to be overwritten, see issue #1
52
+ def save_pos
53
+ output_stream.print "#{CSI}s"
54
+ if block_given?
55
+ yield
56
+ load_pos
57
+ end
58
+ end
59
+ def load_pos() output_stream.print "#{CSI}u" end
60
+
61
+ private
62
+
63
+ def input_stream
64
+ Pecorb.config.input_stream
17
65
  end
18
- ensure
19
- $stdin.echo = true
20
- $stdin.cooked!
21
- return input
22
- end
23
66
 
24
- def print(val) $stderr.print val end
25
- def puts(val) $stderr.puts val end
26
- def output(val) $stdout.puts val end
27
-
28
- def up(n=1) $stderr.print "#{CSI}#{n}A" end
29
- def down(n=1) $stderr.print "#{CSI}#{n}B" end
30
- def right(n=1) $stderr.print "#{CSI}#{n}C" end
31
- def left(n=1) $stderr.print "#{CSI}#{n}D" end
32
-
33
- def backspace(n=1) $stderr.print "\b"*n end
34
- def carriage_return() $stderr.print "\r" end
35
- def clear_to_eol() $stderr.print "#{CSI}K" end
36
- def clear_screen() $stderr.print "#{CSI}H#{CSI}J" end
37
-
38
- def black() $stderr.print "#{CSI}#{CSI}30m" end
39
- def red() $stderr.print "#{CSI}#{CSI}31m" end
40
- def green() $stderr.print "#{CSI}#{CSI}32m" end
41
- def yellow() $stderr.print "#{CSI}#{CSI}33m" end
42
- def blue() $stderr.print "#{CSI}#{CSI}34m" end
43
- def magenta() $stderr.print "#{CSI}#{CSI}35m" end
44
- def cyan() $stderr.print "#{CSI}#{CSI}36m" end
45
- def white() $stderr.print "#{CSI}#{CSI}37m" end
46
- def reset_color() $stderr.print "#{CSI}#{CSI}0m" end
47
-
48
- def save_pos
49
- $stderr.print "#{CSI}s"
50
- if block_given?
51
- yield
52
- load_pos
67
+ def output_stream
68
+ Pecorb.config.output_stream
53
69
  end
54
70
  end
55
- def load_pos() $stderr.print "#{CSI}u" end
56
71
  end
@@ -0,0 +1,113 @@
1
+ require_relative "console"
2
+ require_relative "../core_extensions/comparable"
3
+ require_relative "pager"
4
+
5
+ module Pecorb
6
+ class List
7
+ include Console
8
+
9
+ def initialize(items, opts={})
10
+ raise "Items must be enumerable!" unless items.is_a? Enumerable
11
+ @prompt = opts.fetch(:prompt, "Select an item: ")
12
+ @pager = Pager.new items, IO.console.winsize.first - 2
13
+ @cursor = 0
14
+ @filter_text = ""
15
+ end
16
+
17
+ def prompt
18
+ init_ui
19
+ while c = read_char
20
+ case c
21
+ when "", "\r"
22
+ break
23
+ when "", ""
24
+ carriage_return
25
+ clear_to_eos
26
+ exit 0
27
+ when " "
28
+ clear_screen
29
+ print @prompt
30
+ @cursor.times { right }
31
+ update_ui
32
+ when "" # Backspace key
33
+ next if @filter_text.empty? || @cursor <= 0
34
+ @filter_text.slice!(@cursor - 1)
35
+ update_ui
36
+ backspace
37
+ @cursor -= 1
38
+ when Console::LEFT
39
+ next unless @cursor > 0
40
+ print c
41
+ @cursor -= 1
42
+ when Console::RIGHT
43
+ next unless @cursor < @filter_text.length
44
+ print c
45
+ @cursor += 1
46
+ when Console::UP, " "
47
+ @pager.up
48
+ update_ui
49
+ when Console::DOWN, "\n" # CTRL-J enters a linefeed char in bash
50
+ @pager.down
51
+ update_ui
52
+ else
53
+ @filter_text.insert(@cursor, c)
54
+ update_ui
55
+ print c
56
+ @cursor += 1
57
+ end
58
+ end
59
+
60
+ backspace(@cursor)
61
+ clear_to_eos
62
+ cyan
63
+ puts @pager.selected_item
64
+ reset_color
65
+ @pager.selected_item
66
+ end
67
+
68
+ private
69
+
70
+ def init_ui
71
+ # WARNING: Can't use save_pos here because it causes problems when
72
+ # introducing newlines, see issue #1
73
+ puts
74
+ print_items
75
+ carriage_return; (@pager.items_in_viewport.size + 1).times { up }
76
+ print @prompt
77
+ end
78
+
79
+ def update_ui
80
+ save_pos do
81
+ update_filter_text
82
+ clear_items
83
+ @pager.filter! @filter_text
84
+ print_items
85
+ end
86
+ end
87
+
88
+ def update_filter_text
89
+ backspace(@cursor)
90
+ print @filter_text
91
+ clear_to_eol
92
+ end
93
+
94
+ def clear_items
95
+ carriage_return; down; clear_to_eol
96
+ @pager.items_in_viewport.size.times { down; clear_to_eol }
97
+ @pager.items_in_viewport.size.times { up }
98
+ end
99
+
100
+ def print_items
101
+ @pager.items_in_viewport.each_with_index do |item, i|
102
+ if item == @pager.selected_item
103
+ cyan
104
+ print "‣ "
105
+ else
106
+ print " "
107
+ end
108
+ puts item
109
+ reset_color
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,81 @@
1
+ require_relative "../core_extensions/comparable"
2
+
3
+ module Pecorb
4
+ class Pager
5
+ def initialize(items, viewport_size)
6
+ @configured_items = @items = items
7
+ @viewport_size = viewport_size
8
+ @cursor = 0
9
+ set_viewport_to_top
10
+ end
11
+
12
+ def selected_item
13
+ @items.fetch(@cursor)
14
+ end
15
+
16
+ def items_in_viewport
17
+ @items.slice(@viewport.min, @viewport_size)
18
+ end
19
+
20
+ def filter!(filter_text)
21
+ self.items = fuzzy_filter(filter_text)
22
+ end
23
+
24
+ def items=(new_items)
25
+ @items = new_items
26
+ @cursor = @cursor.clamp(0, @items.size-1)
27
+ reset_viewport_to_cover_cursor
28
+ end
29
+
30
+ def down
31
+ move_cursor_by(1)
32
+ end
33
+
34
+ def up
35
+ move_cursor_by(-1)
36
+ end
37
+
38
+
39
+ private
40
+
41
+ def move_cursor_by(number)
42
+ new_cursor = @cursor + number
43
+ if new_cursor >= @items.size
44
+ @cursor = 0
45
+ reset_viewport_to_cover_cursor
46
+ elsif new_cursor > @viewport.max
47
+ shift_viewport_by(1)
48
+ end
49
+ if new_cursor < 0
50
+ @cursor = @items.size - 1
51
+ reset_viewport_to_cover_cursor
52
+ elsif new_cursor < @viewport.min
53
+ shift_viewport_by(-1)
54
+ end
55
+ @cursor = new_cursor % @items.size
56
+ end
57
+
58
+ def shift_viewport_by(number)
59
+ @viewport = (@viewport.min + number)..(@viewport.max + number)
60
+ end
61
+
62
+ def reset_viewport_to_cover_cursor
63
+ set_viewport_to_top unless @viewport.all? {|i| @items[i]}
64
+ if @cursor < @viewport.min
65
+ @viewport = @cursor..(@cursor + @viewport_size - 1)
66
+ elsif @cursor > @viewport.max
67
+ @viewport = (@cursor - @viewport_size + 1)..@cursor
68
+ end
69
+ end
70
+
71
+ def set_viewport_to_top
72
+ @viewport = 0..(@viewport_size - 1)
73
+ end
74
+
75
+ def fuzzy_filter(filter_text)
76
+ return @configured_items unless filter_text
77
+ regex = Regexp.new(filter_text.chars.join(".*"), "i")
78
+ @configured_items.select {|i| regex.match i }
79
+ end
80
+ end
81
+ end
@@ -1,3 +1,3 @@
1
1
  module Pecorb
2
- VERSION = "1.1.0"
2
+ VERSION = "2.0.0"
3
3
  end
data/lib/pecorb.rb CHANGED
@@ -1,131 +1,27 @@
1
+ require_relative "pecorb/list"
1
2
  require_relative "pecorb/version"
2
- require_relative "pecorb/console"
3
3
 
4
4
  module Pecorb
5
5
  extend self
6
- extend Console
7
6
 
8
- @input = ""
9
- @cursor = 0
10
- @selected = 0
11
- @items = []
12
- @displayed_items = []
13
-
14
-
15
- def prompt(items, prompt="Select an item: ")
16
- @displayed_items = @items = items
17
- @prompt = prompt
18
-
19
- print_menu
20
-
21
- while c = read_char
22
- case c
23
- when /[\r]/
24
- break
25
- when /[]/
26
- @input = ""
27
- break
28
- when /[ ]/
29
- clear_screen
30
- print_menu
31
- when "" # Backspace key
32
- next if @input.empty? || @cursor <= 0
33
- @input.slice!(@cursor-1)
34
- replace_input(@input)
35
- replace_items { filter_items(@items, @input) }
36
- backspace
37
- @cursor -= 1
38
- when Console::LEFT
39
- next unless @cursor > 0
40
- print c
41
- @cursor -= 1
42
- when Console::RIGHT
43
- next unless @cursor < @input.length
44
- print c
45
- @cursor += 1
46
- when Console::UP
47
- @selected = (@selected - 1) % @displayed_items.size
48
- replace_items { filter_items(@items, @input) }
49
- when Console::DOWN
50
- @selected = (@selected + 1) % @displayed_items.size
51
- replace_items { filter_items(@items, @input) }
52
- else
53
- @input.insert(@cursor, c)
54
- replace_input(@input)
55
- replace_items { filter_items(@items, @input) }
56
- print c
57
- @cursor += 1
58
- end
59
- end
60
-
61
- move_cursor_from_start_to_end
62
- output @displayed_items[@selected]
63
- @displayed_items[@selected]
7
+ def list(*args)
8
+ List.new(*args).prompt
64
9
  end
65
10
 
66
- private
67
-
68
- def print_menu
69
- puts @prompt
70
- print_items(@displayed_items)
71
- move_cursor_from_end_to_start
72
- print @input
73
- end
74
-
75
- def move_cursor_from_end_to_start
76
- up(@displayed_items.size + 1)
77
- right(@prompt.size)
78
- end
79
-
80
- def move_cursor_from_start_to_end
81
- down(@displayed_items.size + 1)
82
- carriage_return
83
- end
84
-
85
- def replace_input(str)
86
- save_pos do
87
- backspace(@cursor)
88
- print @input
89
- clear_to_eol
11
+ DefaultConfig = Struct.new(:input_stream, :output_stream) do
12
+ def initialize
13
+ self.input_stream = $stdin
14
+ self.output_stream = $stdout
90
15
  end
91
16
  end
92
17
 
93
- def replace_items
94
- return unless block_given?
95
- list_size = @displayed_items.size
96
- save_pos do
97
- down
98
- carriage_return
99
- clear_to_eol
100
- if list_size > 0
101
- (list_size - 1).times { down; clear_to_eol}
102
- (list_size - 1).times { up }
103
- end
104
- @displayed_items = yield
105
- @selected = limit_max @selected, list_size - 1
106
- print_items @displayed_items
107
- end
108
- end
109
-
110
- def limit_max(n, max)
111
- [[max, n].min, 0].max
112
- end
113
-
114
- def print_items(items)
115
- items.each_with_index do |item, i|
116
- if @selected == i
117
- cyan
118
- print "‣ "
119
- else
120
- print " "
121
- end
122
- puts item
123
- reset_color
124
- end
18
+ def self.configure
19
+ @config = DefaultConfig.new
20
+ yield(@config) if block_given?
21
+ @config
125
22
  end
126
23
 
127
- def filter_items(items, filter)
128
- regex = Regexp.new(filter.chars.join(".*"), "i")
129
- items.select {|i| regex.match i }
24
+ def self.config
25
+ @config || configure
130
26
  end
131
27
  end
data/pecorb.gemspec CHANGED
@@ -21,7 +21,9 @@ Gem::Specification.new do |spec|
21
21
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
22
  spec.require_paths = ["lib"]
23
23
 
24
- spec.add_development_dependency "bundler", "~> 1.13"
25
- spec.add_development_dependency "rake", "~> 10.0"
26
- spec.add_development_dependency "minitest", "~> 5.0"
24
+ spec.add_development_dependency "bundler"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rspec"
27
+ spec.add_development_dependency "guard"
28
+ spec.add_development_dependency "pry-byebug"
27
29
  end
metadata CHANGED
@@ -1,57 +1,85 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pecorb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Occhipinti
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-09 00:00:00.000000000 Z
11
+ date: 2016-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.13'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.13'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: minitest
42
+ name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '5.0'
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '5.0'
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  description: A lightweight, ruby version of peco with filtering
56
84
  email:
57
85
  - dev@stevenocchipinti.com
@@ -61,14 +89,19 @@ extensions: []
61
89
  extra_rdoc_files: []
62
90
  files:
63
91
  - ".gitignore"
92
+ - ".rspec"
64
93
  - Gemfile
65
94
  - Gemfile.lock
95
+ - Guardfile
66
96
  - LICENSE.txt
67
97
  - README.md
68
98
  - Rakefile
69
99
  - bin/pecorb
100
+ - lib/core_extensions/comparable.rb
70
101
  - lib/pecorb.rb
71
102
  - lib/pecorb/console.rb
103
+ - lib/pecorb/list.rb
104
+ - lib/pecorb/pager.rb
72
105
  - lib/pecorb/version.rb
73
106
  - pecorb.gemspec
74
107
  - pecorb/.gitignore