chip 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.
@@ -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: []