chip 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use ruby-1.9.2
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source :rubygems
2
+
3
+ gem 'nokogiri'
4
+
5
+ group :test do
6
+ gem 'rr'
7
+ gem 'fakeweb'
8
+ gem 'test-unit'
9
+ end
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Narihiro Nakamura
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,84 @@
1
+ # Chip: For easy access to micro Ruby library on a Web page
2
+
3
+ Chip is a micro program manager for Ruby.
4
+
5
+ ## Featrues
6
+
7
+ * Run and install a micro program on some Web page.
8
+ * Chip can extend by Chip.
9
+
10
+ ## Installation
11
+
12
+ Requires ruby and rubygems. Install as a gem:
13
+
14
+ gem install chip
15
+
16
+ ## Usage
17
+
18
+ ### Install
19
+ If you created a awesome monky patch as [this page](https://raw.github.com/gist/1417282):
20
+
21
+ class Fixnum
22
+ def hour; self * 60 * 60; end
23
+ end
24
+
25
+ you can install it:
26
+
27
+ $ chip install https://raw.github.com/gist/1417282
28
+
29
+ And, you can use it as following code:
30
+
31
+ # a.rb
32
+ require "chip"
33
+ require_chip "https://raw.github.com/gist/1417282"
34
+
35
+ puts 1.hour
36
+
37
+ $ ruby a.rb
38
+ 3600
39
+
40
+ #### Dynamic install
41
+
42
+ # a.rb
43
+ require "chip"
44
+ require_chip "https://raw.github.com/gist/1425982"
45
+
46
+ puts 1.minute
47
+
48
+ $ ruby a.rb
49
+ Installing...
50
+ /path/to/.chip.d/https:__raw.github.com_gist_1425982.rb
51
+ ---
52
+ class Fixnum
53
+ def minute; self * 60; end
54
+ end
55
+ ---
56
+ Do you install above a program? [yes/no] > yes
57
+ 60
58
+
59
+ ### Run
60
+
61
+ If a web page has a pre tag that first line is included `chip',
62
+
63
+ #chip
64
+
65
+ eval( %w| put s(" H3429el
66
+ l0 o6 ,_4 C52 h0i 98 62
67
+ 63 0p2455!!2 952 0".gsub
68
+ (/ \\ d/, '') .tr ("
69
+ _",32 .chr ))| *'' )#
70
+
71
+ you can run it by the chip command!!:
72
+
73
+ $ chip run https://github.com/authorNari/chip -f
74
+ Hello, Chip!!
75
+
76
+ ## Extend micro code fetcher by Chip
77
+
78
+ TODO
79
+
80
+ Example fetcher: [Twitter status fetcher](chip/wiki/Twitter-status-fetcher)
81
+
82
+ ## Copyright
83
+
84
+ Copyright (c) 2011 nari. See MIT-LICENSE for further details.
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift(File.expand_path("../lib", File.dirname(__FILE__)))
3
+
4
+ require 'rubygems'
5
+ require 'chip'
6
+
7
+ Chip::CLI.new.run(ARGV.dup)
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "chip/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "chip"
7
+ s.version = Chip::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["nari"]
10
+ s.email = ["authornari@gmail.com"]
11
+ s.homepage = "http://github.com/authorNari/chip"
12
+ s.summary = %q{For easy access to micro Ruby library on a Web page}
13
+ s.description = %q{Chip is a micro program manager for Ruby.}
14
+
15
+ s.rubyforge_project = "chip"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ end
@@ -0,0 +1,39 @@
1
+ module Chip
2
+ class InstallError < StandardError; end
3
+ class FetchError < InstallError; end
4
+
5
+ def self.setup
6
+ config = File.expand_path("~/.chip")
7
+ if not File.exist?(config)
8
+ FileUtils.touch(config)
9
+ File.chmod(0600, config)
10
+ end
11
+ eval(File.read(config))
12
+ end
13
+
14
+ def self.fetcher
15
+ @fetcher ||= CodeFetcher.new
16
+ end
17
+
18
+ def self.escape_to_rbfile(url)
19
+ n = url.gsub("/", "_")
20
+ if not File.extname(n) == ".rb"
21
+ n << ".rb"
22
+ end
23
+ return n
24
+ end
25
+
26
+ def self.chip_filepath(url)
27
+ escape_to_rbfile(url)
28
+ end
29
+ end
30
+
31
+ require 'optparse'
32
+ require "fileutils"
33
+ require_relative "chip/version"
34
+ require_relative "chip/code_fetcher"
35
+ require_relative "chip/command"
36
+ require_relative "chip/cli"
37
+ require_relative "chip/core_ext_kernel"
38
+
39
+ Chip.setup
@@ -0,0 +1,53 @@
1
+ module Chip
2
+ class CLI
3
+ def initialize
4
+ @command = Command.new
5
+
6
+ @opts = OptionParser.new do |o|
7
+ o.on("-h", "--help") do
8
+ @command.send(:help)
9
+ exit 1
10
+ end
11
+
12
+ o.on("-v", "--version") do
13
+ @command.send(:version)
14
+ exit 1
15
+ end
16
+
17
+ o.on("-f", "--force") do
18
+ @command.force = true
19
+ end
20
+ end
21
+ end
22
+ attr_reader :command
23
+
24
+ def run(args)
25
+ args = parse_args!(args)
26
+ method = args.shift || "help"
27
+ @command.send(method, *args)
28
+ rescue ArgumentError
29
+ @command.send(:help)
30
+ rescue InstallError => ex
31
+ puts ex.message
32
+ end
33
+
34
+ private
35
+ def parse_args!(args)
36
+ nonopts = []
37
+
38
+ begin
39
+ @opts.order!(args) do |nonopt|
40
+ nonopts << nonopt
41
+ end
42
+ rescue OptionParser::InvalidOption => e
43
+ nonopts << e.args.first
44
+ retry
45
+ rescue OptionParser::MissingArgument
46
+ @command.send(:help)
47
+ return
48
+ end
49
+
50
+ nonopts + args
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,68 @@
1
+ require "nokogiri"
2
+
3
+ module Chip
4
+ class CodeFetcher
5
+ def initialize
6
+ @fetchers = []
7
+ # text/plain
8
+ @fetchers << [/.*/,
9
+ "text/plain",
10
+ ->(opts){ opts[:response].body }]
11
+ # text/html <pre>#chip\n puts 'hello, world!'</pre>
12
+ @fetchers << [/.*/,
13
+ "text/html",
14
+ ->(opts){
15
+ doc = Nokogiri::HTML::Document.parse(opts[:response].body)
16
+ doc.xpath('//pre').map do |pre|
17
+ t = pre.text
18
+ lines = t.split("\n")
19
+ lines.each do |l|
20
+ if l != nil
21
+ l = l.gsub(" ", "")
22
+ if !l.empty?
23
+ return t if l.include?("#chip")
24
+ break
25
+ end
26
+ end
27
+ end
28
+ end
29
+ return false
30
+ }]
31
+ end
32
+ attr_reader :fetchers
33
+
34
+ def add(url, content_type, &inspector)
35
+ @fetchers.unshift([url, content_type, inspector])
36
+ end
37
+
38
+ def fetch(target_url)
39
+ response = http_get(target_url)
40
+ @fetchers.each do |url, content_type, inspector|
41
+ if target_url.match(url) && response.content_type.match(content_type)
42
+ if res = inspector.call(response: response,
43
+ url: target_url)
44
+ return res
45
+ end
46
+ end
47
+ end
48
+ raise FetchError, "chip don't have a code fetcher for #{target_url}."
49
+ end
50
+
51
+ private
52
+ def http_get(url, limit=10)
53
+ raise FetchError, 'http redirect too deep' if limit == 0
54
+ uri = URI.parse(url)
55
+ http = Net::HTTP.new(uri.host, uri.port)
56
+ http.use_ssl = (uri.scheme == "https")
57
+ res = http.start{|h| h.get(uri.path)}
58
+ case res
59
+ when Net::HTTPSuccess
60
+ return res
61
+ when Net::HTTPRedirection
62
+ return http_get(res['Location'], limit - 1)
63
+ else
64
+ raise FetchError, "#{url} response code is #{res.code}"
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,85 @@
1
+ require "uri"
2
+ require "net/https"
3
+
4
+ module Chip
5
+ class Command
6
+ attr_writer :force
7
+
8
+ def install(url)
9
+ puts "Installing..."
10
+ code = ::Chip.fetcher.fetch(url)
11
+ fn = install_filepath(url)
12
+
13
+ unless @force
14
+ puts "#{fn}"
15
+ puts "---"
16
+ puts code
17
+ puts "---"
18
+ print "Do you install above a program? [yes/no] > "
19
+ end
20
+
21
+ if @force or ask == "yes"
22
+ File.open(fn, "w"){|f| f.write(code) }
23
+ return
24
+ end
25
+ raise InstallError, "#{url} is not installed."
26
+ end
27
+
28
+ def run(url)
29
+ install(url)
30
+ unless @force
31
+ print "Do you run it? [yes/no] > "
32
+ end
33
+ if @force or ask == "yes"
34
+ puts "Running..."
35
+ eval(File.read(install_filepath(url)))
36
+ end
37
+ end
38
+
39
+ def list
40
+ puts Dir.entries(install_dir).select{|f| File.extname(f) == ".rb"}
41
+ end
42
+
43
+ def help
44
+ puts <<-EOF
45
+ chip gem version #{Chip::VERSION}
46
+
47
+ [commands]
48
+ chip help - show this message
49
+
50
+ chip install <URL> - install a micro program on Wep page
51
+ chip run <URL> - run a micro program on Wep page
52
+
53
+ [options]
54
+ -h, --help : show this message
55
+ EOF
56
+ end
57
+
58
+ def version
59
+ puts Chip::VERSION
60
+ end
61
+
62
+ private
63
+ def install_dir(dir=nil)
64
+ dir = File.expand_path("~/.chip.d") if dir.nil?
65
+ if not File.exist?(dir)
66
+ FileUtils.mkdir_p(dir)
67
+ File.chmod(0700, dir)
68
+ end
69
+ return dir
70
+ end
71
+
72
+ def install_filepath(url)
73
+ File.join(install_dir, Chip.escape_to_rbfile(url))
74
+ end
75
+
76
+ def ask
77
+ line = $stdin.gets
78
+ if line
79
+ line.strip
80
+ else
81
+ ""
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,8 @@
1
+ module Kernel
2
+ def require_chip(url)
3
+ c = Chip::Command.new
4
+ fname = c.send(:install_filepath, url)
5
+ c.install(url) if not File.exist?(fname)
6
+ require fname
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ module Chip
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ class Test::Unit::TestCase
2
+ include RR::Adapters::TestUnit
3
+ end
4
+
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ base_dir = File.expand_path(File.dirname(__FILE__))
4
+ top_dir = File.expand_path("..", base_dir)
5
+ $LOAD_PATH.unshift(File.join(top_dir, "lib"))
6
+ $LOAD_PATH.unshift(File.join(top_dir, "test"))
7
+
8
+ require "rubygems"
9
+ require "bundler"
10
+ Bundler.require(:default, :test)
11
+ require "test/unit"
12
+ require_relative "helper"
13
+
14
+ require "chip"
15
+ Dir.glob("./test/test_*.rb") do |file|
16
+ require file
17
+ end
@@ -0,0 +1,18 @@
1
+ class TestCli < Test::Unit::TestCase
2
+ def setup
3
+ @cli = Chip::CLI.new
4
+ @command = @cli.command
5
+ end
6
+
7
+ def test_run
8
+ mock(@command).install("http://test.com/")
9
+
10
+ @cli.run(["install", "http://test.com/"])
11
+ end
12
+
13
+ def test_run_no_args
14
+ mock(@command).help
15
+
16
+ @cli.run([])
17
+ end
18
+ end
@@ -0,0 +1,40 @@
1
+ # -*- coding: utf-8 -*-
2
+ require "fakeweb"
3
+
4
+ class TestCodeFetcher < Test::Unit::TestCase
5
+ def setup
6
+ @fetcher = Chip::CodeFetcher.new
7
+ end
8
+
9
+ def test_fetch_with_plain
10
+ FakeWeb.register_uri(:get, "http://test.com/a.rb",
11
+ body: "puts 'Hi'", content_type: "text/plain")
12
+
13
+ assert_equal "puts 'Hi'", @fetcher.fetch("http://test.com/a.rb")
14
+ end
15
+
16
+ def test_fetch_with_html
17
+ FakeWeb.register_uri(:get, "http://test.com/a.rb",
18
+ body: "<pre>\n\n#chip\nputs 'Hi'</pre>",
19
+ content_type: "text/html")
20
+
21
+ assert_equal "\n\n#chip\nputs 'Hi'", @fetcher.fetch("http://test.com/a.rb")
22
+ end
23
+
24
+ def test_fetch_with_html_have_many_pre
25
+ FakeWeb.register_uri(:get, "http://test.com/a.rb",
26
+ body: "<pre>invalid</pre>" +
27
+ "<pre>\n\n#chip\nputs 'Hi'</pre>",
28
+ content_type: "text/html")
29
+
30
+ assert_equal "\n\n#chip\nputs 'Hi'", @fetcher.fetch("http://test.com/a.rb")
31
+ end
32
+
33
+ def test_add
34
+ assert_equal 2, @fetcher.fetchers.size
35
+ @fetcher.add("test_url", "text/plain"){}
36
+
37
+ assert_equal 3, @fetcher.fetchers.size
38
+ assert_equal "test_url", @fetcher.fetchers.first.first
39
+ end
40
+ end
@@ -0,0 +1,71 @@
1
+ class TestCommand < Test::Unit::TestCase
2
+ TEST_URL = "http://test.com"
3
+ INSTALL_DIR = File.expand_path("~/.chip.d/")
4
+
5
+ def setup
6
+ @command = Chip::Command.new
7
+
8
+ # Capture outputs by stubbing puts
9
+ @stdout_values = []
10
+ stub(@command).puts{|s| @stdout_values << s }
11
+ stub(@command).print{|s| @stdout_values << s }
12
+ end
13
+
14
+ def test_install
15
+ any_instance_of(Chip::CodeFetcher) do |cf|
16
+ mock(cf).fetch(TEST_URL){ "puts 'Hi'"}
17
+ end
18
+ any_instance_of(File) do |f|
19
+ mock(f).write("puts 'Hi'")
20
+ end
21
+ mock(@command).ask{ "yes"}
22
+
23
+ @command.install(TEST_URL)
24
+
25
+ assert_not_empty @stdout_values
26
+ end
27
+
28
+ def test_install_with_force
29
+ any_instance_of(Chip::CodeFetcher) do |cf|
30
+ mock(cf).fetch(TEST_URL){ "puts 'Hi'"}
31
+ end
32
+ any_instance_of(File) do |f|
33
+ mock(f).write("puts 'Hi'")
34
+ end
35
+ dont_allow(@command).ask{ "yes"}
36
+
37
+ @command.force = true
38
+ @command.install(TEST_URL)
39
+
40
+ assert_equal ["Installing..."], @stdout_values
41
+ end
42
+
43
+ def test_run
44
+ mock(@command).install(TEST_URL)
45
+ mock(@command).ask{ "yes"}
46
+ mock(File).read("#{INSTALL_DIR}/http:__test.com.rb"){ "puts 'Hi'"}
47
+
48
+ @command.run(TEST_URL)
49
+
50
+ assert_equal "Hi", @stdout_values.last
51
+ end
52
+
53
+ def test_run_with_force
54
+ mock(@command).install(TEST_URL)
55
+ dont_allow(@command).ask{ "yes"}
56
+ mock(File).read("#{INSTALL_DIR}/http:__test.com.rb"){ "puts 'Hi'"}
57
+
58
+ @command.force = true
59
+ @command.run(TEST_URL)
60
+
61
+ assert_equal ["Running...", "Hi"], @stdout_values
62
+ end
63
+
64
+ def test_list
65
+ mock(Dir).entries(INSTALL_DIR){ [".", "..", "test.rb"] }
66
+
67
+ @command.list
68
+
69
+ assert_equal [["test.rb"]], @stdout_values
70
+ end
71
+ end
File without changes
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chip
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - nari
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-12-06 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: Chip is a micro program manager for Ruby.
15
+ email:
16
+ - authornari@gmail.com
17
+ executables:
18
+ - chip
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - .rvmrc
24
+ - Gemfile
25
+ - MIT-LICENSE
26
+ - README.md
27
+ - Rakefile
28
+ - bin/chip
29
+ - chip.gemspec
30
+ - lib/chip.rb
31
+ - lib/chip/cli.rb
32
+ - lib/chip/code_fetcher.rb
33
+ - lib/chip/command.rb
34
+ - lib/chip/core_ext_kernel.rb
35
+ - lib/chip/version.rb
36
+ - test/helper.rb
37
+ - test/run-test.rb
38
+ - test/test_cli.rb
39
+ - test/test_code_fetcher.rb
40
+ - test/test_command.rb
41
+ - test/test_core_ext_kernel.rb
42
+ homepage: http://github.com/authorNari/chip
43
+ licenses: []
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubyforge_project: chip
62
+ rubygems_version: 1.8.6
63
+ signing_key:
64
+ specification_version: 3
65
+ summary: For easy access to micro Ruby library on a Web page
66
+ test_files: []