ruby-anything 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pry-anything.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Takatoshi Matsumoto
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # RubyAnything
2
+ Provide [anything](http://www.emacswiki.org/Anything) interface for ruby. Adds `_anything_` method to Kernel.
3
+
4
+ ![thumbnail](http://pic.toqoz.net/a74849e3c9c2e55afe925bba2dcc23dfd94184ca.png)
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ group :development do
12
+ gem 'ruby-anything'
13
+ end
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ ```sh
19
+ $ bundle
20
+ ```
21
+
22
+ Or install it yourself as:
23
+
24
+ ```sh
25
+ $ gem install ruby-anything
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ ### Example1
31
+
32
+ Start pry
33
+ ```sh
34
+ $ pry
35
+ [1] pry(main)> require 'ruby-anything'
36
+ => true
37
+ [2] pry(main)> _anything_ Pry.methods
38
+ ```
39
+
40
+ ### Demo
41
+ http://www.youtube.com/watch?v=bCyTMCOBkVw&hd=1
42
+
43
+ ## Contributing
44
+
45
+ 1. Fork it
46
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
47
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
48
+ 4. Push to the branch (`git push origin my-new-feature`)
49
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,151 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module RubyAnything
4
+ # prefix `c_` is curses
5
+ class BaseWindow
6
+ attr_accessor :top
7
+ attr_reader :cursor
8
+
9
+ # Public: Hash has name as key and has array of keycode as value
10
+ KEYS = {
11
+ up: [ Curses::Key::UP, 16 ],
12
+ down: [ Curses::Key::DOWN, 14 ],
13
+ left: [ Curses::Key::LEFT, 2 ],
14
+ right: [ Curses::Key::RIGHT, 6 ],
15
+ enter: [ 10 ],
16
+ interrupt: [ 3, 4 ]
17
+ }
18
+ # Public: initialize BaseWindow
19
+ #
20
+ # parent - The Curses::Window or RubyAnything::Window is parent window for self
21
+ # opt - The Hash is options for drawing self
22
+ # :h height
23
+ # :w width
24
+ # :y y-axis
25
+ # :x x-axis
26
+ def initialize(parent, opt)
27
+ @parent = parent
28
+ @c_window = @parent.subwin(
29
+ opt[:h] || @parent.maxy,
30
+ opt[:w] || @parent.maxx,
31
+ opt[:y] || 0,
32
+ opt[:x] || 0
33
+ )
34
+ @cursor = Cursor.new
35
+ @top = 0
36
+ update
37
+ end
38
+
39
+ def collection; [] end
40
+ def view_collection; collection[@top..@top + maxy - 1] || [] end
41
+
42
+ def update
43
+ in_pos(0, 0) {
44
+ view_collection.each_with_index do |item, index|
45
+ draw_at index
46
+ end
47
+ }
48
+ end
49
+
50
+ def on_input(ch) end
51
+
52
+ def draw_at(y)
53
+ setpos(y, 0)
54
+ clrtoeol
55
+ addstr view_collection[y]
56
+ end
57
+
58
+ def draw_at!(y)
59
+ draw_at y
60
+ refresh
61
+ end
62
+
63
+ def before_left
64
+ @cursor.x > 0
65
+ end
66
+
67
+ def before_right
68
+ @cursor.x < view_collection[@cursor.y].size
69
+ end
70
+
71
+ def before_down
72
+ cursor.y + 1 < view_collection.size
73
+ end
74
+
75
+ def before_up
76
+ cursor.y > 0
77
+ end
78
+
79
+ def down
80
+ unless before_down
81
+ @top += 1 if collection.size > @top + maxy
82
+ update
83
+ else
84
+ change_focus_line { cursor.down }
85
+ refresh
86
+ end
87
+ end
88
+
89
+ def up
90
+ return unless before_up
91
+ change_focus_line { cursor.up }
92
+ refresh
93
+ end
94
+
95
+ def left
96
+ return unless before_left
97
+ cursor.left
98
+ refresh
99
+ end
100
+
101
+ def right
102
+ return unless before_right
103
+ cursor.right
104
+ refresh
105
+ end
106
+
107
+ def change_focus_line
108
+ normalize_line
109
+ yield if block_given?
110
+ enhansive_line
111
+ end
112
+
113
+ def normalize_line
114
+ in_pos(cursor.y, 0) { draw_at(cursor.y) }
115
+ refresh
116
+ end
117
+
118
+ def enhansive_line
119
+ in_color(RubyAnything::ENHANSIVE_COLOR) {
120
+ in_pos(cursor.y, 0) { draw_at(cursor.y) }
121
+ refresh
122
+ }
123
+ end
124
+
125
+ def in_pos(y, x)
126
+ setpos(y, x)
127
+ yield self if block_given?
128
+ setpos(y, x)
129
+ end
130
+
131
+ def in_color(color)
132
+ attron(Curses.color_pair(color))
133
+ yield self if block_given?
134
+ attroff(Curses::A_COLOR)
135
+ end
136
+
137
+ def refresh
138
+ setpos cursor.y, cursor.x
139
+ @c_window.refresh
140
+ end
141
+
142
+ # delegate to instance of Curses::Window
143
+ def method_missing(name, *args)
144
+ if @c_window.respond_to? name.to_s
145
+ @c_window.send name.to_s, *args
146
+ else
147
+ super
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,35 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module RubyAnything
4
+ class Cursor
5
+ attr_accessor :x, :y
6
+
7
+ def initialize(opt = {})
8
+ @x = opt[:x] || 0
9
+ @y = opt[:y] || 0
10
+ @minx = opt[:minx] || 0
11
+ @miny = opt[:miny] || 0
12
+ end
13
+
14
+ def clear
15
+ self.x = 0
16
+ self.y = 0
17
+ end
18
+
19
+ def up
20
+ self.y -= 1 if @miny < y
21
+ end
22
+
23
+ def down
24
+ self.y += 1
25
+ end
26
+
27
+ def left
28
+ self.x -= 1 if @minx < x
29
+ end
30
+
31
+ def right
32
+ self.x += 1
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,12 @@
1
+ module RubyAnything
2
+ module Filterable
3
+ def filter(text)
4
+ patterns = text.split(/\s+/).map do |word|
5
+ /#{word}/i
6
+ end
7
+ select do |e|
8
+ patterns.empty? || patterns.any? { |p| p =~ e }
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Kernel
4
+ def _anything_(ary)
5
+ RubyAnything.execute(ary)
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module RubyAnything
4
+ class Text
5
+ def initialize
6
+ @io = []
7
+ end
8
+
9
+ def to_a
10
+ @io
11
+ end
12
+
13
+ def to_s
14
+ @io.join('')
15
+ end
16
+
17
+ def insert(index, ch)
18
+ @io.insert index, ch
19
+ end
20
+
21
+ def delete(index)
22
+ @io.delete_at index
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,3 @@
1
+ module RubyAnything
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,46 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module RubyAnything
4
+ class ItemsWindow < BaseWindow
5
+ attr_accessor :items
6
+
7
+ def initialize(parent, items = [], opt)
8
+ @items = items
9
+ super parent, opt
10
+ end
11
+
12
+ def filter_text
13
+ @filter_text ||= ""
14
+ end
15
+
16
+ def filter(_filter_text)
17
+ @filter_text = _filter_text
18
+ cursor.clear
19
+ in_pos(0, 0) { update }
20
+ end
21
+
22
+ def update
23
+ items.each_with_index do |item, index|
24
+ setpos index, 0
25
+ clrtoeol
26
+ end
27
+ refresh
28
+
29
+ change_focus_line {
30
+ view_collection.each_with_index do |item, index|
31
+ draw_at index
32
+ end
33
+ }
34
+ end
35
+
36
+ def collection; items.filter(filter_text.to_s) end
37
+ def selected_item; view_collection[cursor.y] end
38
+
39
+ def on_input(ch)
40
+ case ch
41
+ when *KEYS[:up] then up
42
+ when *KEYS[:down] then down
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module RubyAnything
4
+ class PromptWindow < BaseWindow
5
+ def initialize(parent, prompt, opt)
6
+ @prompt = prompt
7
+ super(parent, opt)
8
+ end
9
+ def view_collection; [ @prompt ] end
10
+ def draw_at(*args)
11
+ in_color(PROMPT_COLOR) {
12
+ super(*args)
13
+ }
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,48 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module RubyAnything
4
+ class TextWindow < BaseWindow
5
+ attr_accessor :items_window
6
+
7
+ def initialize(parent, opt = {})
8
+ super(parent, opt)
9
+ end
10
+
11
+ def text
12
+ @text ||= Text.new
13
+ end
14
+
15
+ def update; draw_at! 0 end
16
+ def view_collection; [ text.to_s ] end
17
+
18
+ def on_input(ch)
19
+ # require 'logger'
20
+ # @logger ||= Logger.new('/tmp/ch.txt')
21
+ # @logger.info ch
22
+ case ch
23
+ when *KEYS[:left]
24
+ left
25
+ when *KEYS[:right]
26
+ right
27
+ when Curses::Key::BACKSPACE
28
+ delete
29
+ when String
30
+ insert ch
31
+ end
32
+ end
33
+
34
+ def delete
35
+ cursor.left
36
+ text.delete cursor.x
37
+ @parent.filter text.to_s
38
+ update
39
+ end
40
+
41
+ def insert(ch)
42
+ text.insert cursor.x, ch
43
+ cursor.right
44
+ @parent.filter text.to_s
45
+ update
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,104 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module RubyAnything
4
+ require "ruby-anything/filterable"
5
+ require "ruby-anything/text"
6
+ require "ruby-anything/cursor"
7
+ require 'ruby-anything/base_window'
8
+ require 'ruby-anything/windows/prompt_window'
9
+ require 'ruby-anything/windows/text_window'
10
+ require 'ruby-anything/windows/items_window'
11
+
12
+ ENHANSIVE_COLOR = 1
13
+ PROMPT_COLOR = 2
14
+
15
+ class Windows < BaseWindow
16
+ attr_accessor :items_window, :text_window
17
+
18
+ class << self
19
+ def anything(items)
20
+ windows = new items.extend(Filterable)
21
+ begin
22
+ loop {
23
+ break unless windows.active?
24
+ windows.on_input Curses.getch
25
+ }
26
+ windows.selected_item
27
+ ensure
28
+ windows.close unless Curses.closed?
29
+ end
30
+ end
31
+ end
32
+
33
+ def initialize(items)
34
+ super(screen, h: screen.maxy, w: screen.maxx, y: 0, x: 0)
35
+
36
+ @active = true
37
+ @text_window = TextWindow.new self, opt(:text)
38
+ @items_window = ItemsWindow.new self, items, opt(:items)
39
+ PromptWindow.new self, prompt, opt(:prompt)
40
+
41
+ @screen.setpos @text_window.begy, @text_window.begx
42
+ @screen.refresh
43
+ end
44
+
45
+ def active?; @active end
46
+ def deactivate; @active = false end
47
+ def prompt; '> ' end
48
+
49
+ def opt(window_type)
50
+ case window_type
51
+ when :prompt
52
+ { h: 1, w: prompt.size, y: 0, x: 0}
53
+ when :text
54
+ { h: 1, w: maxx - prompt.size, y: 0, x: 2 }
55
+ when :items
56
+ { h: maxy - 1, w: maxx, y: 1, x: 0 }
57
+ else
58
+ {}
59
+ end
60
+ end
61
+
62
+ def on_input(ch)
63
+ case ch
64
+ when *KEYS[:enter], *KEYS[:interrupt]
65
+ deactivate
66
+ when *KEYS[:up], *KEYS[:down]
67
+ items_window.on_input ch
68
+ else
69
+ text_window.on_input ch
70
+ end
71
+ end
72
+
73
+ def screen
74
+ unless @screen
75
+ configure_curses
76
+ @screen = Curses.stdscr
77
+ end
78
+ @screen
79
+ end
80
+
81
+ def close
82
+ items_window.close
83
+ text_window.close
84
+ @c_window.close
85
+ Curses.close_screen
86
+ end
87
+
88
+ def configure_curses
89
+ Curses.class_eval do
90
+ init_screen
91
+ raw
92
+ noecho
93
+ start_color
94
+ init_pair ENHANSIVE_COLOR, Curses::COLOR_WHITE, Curses::COLOR_MAGENTA
95
+ init_pair PROMPT_COLOR, Curses::COLOR_YELLOW, 0
96
+ stdscr.keypad(true)
97
+ end
98
+ end
99
+
100
+ # delegate to items_window
101
+ def selected_item; items_window.selected_item end
102
+ def filter(*args) items_window.filter(*args) end
103
+ end
104
+ end
@@ -0,0 +1,19 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module RubyAnything
4
+ require "curses"
5
+ require "ruby-anything/version"
6
+ require "ruby-anything/windows"
7
+ require "ruby-anything/kernel_ext"
8
+
9
+ def self.execute(ary)
10
+ unless ary.respond_to? :to_a
11
+ raise ArgumentError, "Invalid argument `#{ary}` for RubyAnything.execute. This argument must be Array"
12
+ end
13
+ unless ary.all? { |e| e.respond_to?(:to_s) }
14
+ raise ArgumentError, "Invalid argument `#{ary}` for RubyAnything.execute. This argument's element must have `to_s` method"
15
+ end
16
+
17
+ Windows.anything ary.map(&:to_s)
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ruby-anything/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "ruby-anything"
8
+ gem.version = RubyAnything::VERSION
9
+ gem.authors = ["Takatoshi Matsumoto"]
10
+ gem.email = ["toqoz403@gmail.com"]
11
+ gem.description = %q{Anything interface for ruby}
12
+ gem.summary = %q{Provide anything interface for ruby. Adds method 'anything' to Kernel.}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_development_dependency "rspec"
21
+ end
@@ -0,0 +1,29 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe RubyAnything::Filterable do
6
+ describe '#filter' do
7
+ [
8
+ [ 'foo', 'hoge', 'foobar' ]
9
+ ].each do |ary|
10
+ context "when self is #{ary}" do
11
+ let(:filtarable) { ary.extend(described_class) }
12
+
13
+ context "when given 'foo'" do
14
+ subject { filtarable.filter 'foo' }
15
+ it { should eq([ 'foo', 'foobar' ]) }
16
+ end
17
+ context "when given 'bar'" do
18
+ subject { filtarable.filter 'bar' }
19
+ it { should eq([ 'foobar' ]) }
20
+ end
21
+
22
+ context "when given 'ho'" do
23
+ subject { filtarable.filter 'ho' }
24
+ it { should eq([ 'hoge' ]) }
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,4 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
4
+ require "ruby-anything"
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-anything
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Takatoshi Matsumoto
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ prerelease: false
16
+ type: :development
17
+ version_requirements: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ name: rspec
24
+ requirement: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: Anything interface for ruby
31
+ email:
32
+ - toqoz403@gmail.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - .gitignore
38
+ - .rspec
39
+ - Gemfile
40
+ - LICENSE.txt
41
+ - README.md
42
+ - Rakefile
43
+ - lib/ruby-anything.rb
44
+ - lib/ruby-anything/base_window.rb
45
+ - lib/ruby-anything/cursor.rb
46
+ - lib/ruby-anything/filterable.rb
47
+ - lib/ruby-anything/kernel_ext.rb
48
+ - lib/ruby-anything/text.rb
49
+ - lib/ruby-anything/version.rb
50
+ - lib/ruby-anything/windows.rb
51
+ - lib/ruby-anything/windows/items_window.rb
52
+ - lib/ruby-anything/windows/prompt_window.rb
53
+ - lib/ruby-anything/windows/text_window.rb
54
+ - ruby-anything.gemspec
55
+ - spec/ruby-anything/filterable_spec.rb
56
+ - spec/spec_helper.rb
57
+ homepage: ''
58
+ licenses: []
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project:
77
+ rubygems_version: 1.8.24
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: Provide anything interface for ruby. Adds method 'anything' to Kernel.
81
+ test_files:
82
+ - spec/ruby-anything/filterable_spec.rb
83
+ - spec/spec_helper.rb
84
+ has_rdoc: