pecorb 1.1.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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