ruby-anything 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: