bcat 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/COPYING ADDED
File without changes
@@ -0,0 +1,42 @@
1
+ require 'date'
2
+
3
+ require 'rubygems'
4
+ $spec = eval(File.read('bcat.gemspec'))
5
+
6
+ desc "Build gem package"
7
+ task :package => 'bcat.gemspec' do
8
+ sh "gem build bcat.gemspec"
9
+ end
10
+
11
+ desc 'Build the manual'
12
+ task :man do
13
+ ENV['RONN_MANUAL'] = "Bcat #{source_version}"
14
+ ENV['RONN_ORGANIZATION'] = "Ryan Tomayko"
15
+ sh "ronn -w -r5 man/*.ronn"
16
+ end
17
+
18
+ def source_version
19
+ @source_version ||= `ruby -Ilib -rbcat -e 'puts Bcat::VERSION'`.chomp
20
+ end
21
+
22
+ file 'bcat.gemspec' => FileList['{lib,test,bin}/**','Rakefile'] do |f|
23
+ # read spec file and split out manifest section
24
+ spec = File.read(f.name)
25
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
26
+ # replace version and date
27
+ head.sub!(/\.version = '.*'/, ".version = '#{source_version}'")
28
+ head.sub!(/\.date = '.*'/, ".date = '#{Date.today.to_s}'")
29
+ # determine file list from git ls-files
30
+ files = `git ls-files`.
31
+ split("\n").
32
+ sort.
33
+ reject{ |file| file =~ /^\./ }.
34
+ reject { |file| file =~ /^doc/ }.
35
+ map{ |file| " #{file}" }.
36
+ join("\n")
37
+ # piece file back together and write...
38
+ manifest = " s.files = %w[\n#{files}\n ]\n"
39
+ spec = [head,manifest,tail].join(" # = MANIFEST =\n")
40
+ File.open(f.name, 'w') { |io| io.write(spec) }
41
+ puts "updated #{f.name}"
42
+ end
@@ -0,0 +1,37 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'bcat'
3
+ s.version = '0.0.0'
4
+ s.date = '2010-06-19'
5
+
6
+ s.summary = "browser cat"
7
+ s.description =
8
+ "Concatenate input from standard input, or one or more files, " +
9
+ "and write progressive output to a browser."
10
+
11
+ s.authors = ["Ryan Tomayko"]
12
+ s.email = "rtomayko@gmail.com"
13
+
14
+ # = MANIFEST =
15
+ s.files = %w[
16
+ Rakefile
17
+ bcat.gemspec
18
+ bin/bcat
19
+ lib/bcat.rb
20
+ lib/bcat/kidgloves.rb
21
+ man/bcat.1.ronn
22
+ ]
23
+ # = MANIFEST =
24
+
25
+ s.default_executable = 'bcat'
26
+ s.executables = ['bcat']
27
+
28
+ s.test_files = s.files.select {|path| path =~ /^test\/.*_test.rb/}
29
+ s.add_dependency 'rack'
30
+
31
+ s.extra_rdoc_files = %w[COPYING]
32
+
33
+ s.has_rdoc = true
34
+ s.homepage = "http://github.com/rtomayko/bcat/"
35
+ s.rdoc_options = ["--line-numbers", "--inline-source"]
36
+ s.require_paths = %w[lib]
37
+ end
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+ # Usage: bcat [<file>]...
3
+ # Read standard input, or one or more <file>s, and write to browser.
4
+ require 'bcat'
5
+
6
+ fds =
7
+ ARGV.map do |file|
8
+ if file == '-'
9
+ $stdin
10
+ else
11
+ File.open(file, 'rb')
12
+ end
13
+ end
14
+ fds = [$stdin] if fds.empty?
15
+
16
+ command = ENV['BCAT_COMMAND'] || 'open $BCAT_ARGS "$BCAT_URL"'
17
+
18
+ pid = nil
19
+ begin
20
+ bcat = Bcat.new(fds)
21
+ bcat.serve! do |sock|
22
+ pid =
23
+ fork do
24
+ (fds + [sock, $stdin, $stdout]).uniq.each { |fd| fd.close }
25
+ ENV['BCAT_URL'] = "http://#{bcat[:Host]}:#{bcat[:Port]}/#{File.basename(Dir.pwd)}"
26
+ ENV['BCAT_ARGS'] = "-a '#{ENV['BCAT_APPLICATION']}'" if !ENV['BCAT_APPLICATION'].to_s.empty?
27
+ exec "/bin/sh -c \"#{command}\""
28
+ end
29
+ end
30
+ rescue Interrupt
31
+ end
32
+
33
+ Process.wait(pid) if pid
34
+ exit $?
@@ -0,0 +1,69 @@
1
+ require 'rack'
2
+ require 'bcat/kidgloves'
3
+
4
+ class Bcat
5
+ VERSION = '0.0.0'
6
+ include Rack::Utils
7
+
8
+ def initialize(fds=[$stdin], config={})
9
+ @fds = fds
10
+ @config = {:Host => '127.0.0.1', :Port => 8091}.merge(config)
11
+ end
12
+
13
+ def [](key)
14
+ @config[key]
15
+ end
16
+
17
+ def call(env)
18
+ [200, {"Content-Type" => "text/html;charset=utf-8"}, self]
19
+ end
20
+
21
+ def head
22
+ ["<html>",
23
+ "<head><title>bcat</title></head>",
24
+ "<body><pre>"].join
25
+ end
26
+
27
+ def foot
28
+ "</pre></body></html>"
29
+ end
30
+
31
+ def each
32
+ yield "\n" * 1000
33
+ yield "<!DOCTYPE html>\n"
34
+ yield head
35
+
36
+ begin
37
+ @fds.each do |fd|
38
+ begin
39
+ while buf = fd.readpartial(4096)
40
+ output = escape_html(buf)
41
+ output = output.gsub(/\n/, "<br>")
42
+ yield "<script>document.write('#{output}');</script>"
43
+ end
44
+ rescue EOFError
45
+ ensure
46
+ fd.close rescue nil
47
+ end
48
+ end
49
+ end
50
+
51
+ yield foot
52
+ end
53
+
54
+ def close
55
+ raise Interrupt
56
+ end
57
+
58
+ def to_app
59
+ app = self
60
+ Rack::Builder.new do
61
+ use Rack::Chunked
62
+ run app
63
+ end
64
+ end
65
+
66
+ def serve!(&bk)
67
+ Rack::Handler::KidGloves.run to_app, @config, &bk
68
+ end
69
+ end
@@ -0,0 +1,149 @@
1
+ require 'socket'
2
+ require 'stringio'
3
+
4
+ module Rack
5
+ module Handler
6
+ class KidGloves
7
+ attr_accessor :app
8
+
9
+ StatusMessage = {
10
+ 100 => 'Continue',
11
+ 101 => 'Switching Protocols',
12
+ 200 => 'OK',
13
+ 201 => 'Created',
14
+ 202 => 'Accepted',
15
+ 203 => 'Non-Authoritative Information',
16
+ 204 => 'No Content',
17
+ 205 => 'Reset Content',
18
+ 206 => 'Partial Content',
19
+ 300 => 'Multiple Choices',
20
+ 301 => 'Moved Permanently',
21
+ 302 => 'Found',
22
+ 303 => 'See Other',
23
+ 304 => 'Not Modified',
24
+ 305 => 'Use Proxy',
25
+ 307 => 'Temporary Redirect',
26
+ 400 => 'Bad Request',
27
+ 401 => 'Unauthorized',
28
+ 402 => 'Payment Required',
29
+ 403 => 'Forbidden',
30
+ 404 => 'Not Found',
31
+ 405 => 'Method Not Allowed',
32
+ 406 => 'Not Acceptable',
33
+ 407 => 'Proxy Authentication Required',
34
+ 408 => 'Request Timeout',
35
+ 409 => 'Conflict',
36
+ 410 => 'Gone',
37
+ 411 => 'Length Required',
38
+ 412 => 'Precondition Failed',
39
+ 413 => 'Request Entity Too Large',
40
+ 414 => 'Request-URI Too Large',
41
+ 415 => 'Unsupported Media Type',
42
+ 416 => 'Request Range Not Satisfiable',
43
+ 417 => 'Expectation Failed',
44
+ 500 => 'Internal Server Error',
45
+ 501 => 'Not Implemented',
46
+ 502 => 'Bad Gateway',
47
+ 503 => 'Service Unavailable',
48
+ 504 => 'Gateway Timeout',
49
+ 505 => 'HTTP Version Not Supported'
50
+ }
51
+
52
+ def self.run(app, options={}, &block)
53
+ new(app, options).listen(&block)
54
+ end
55
+
56
+ def initialize(app, options={})
57
+ @app = app
58
+ @host = options[:Host] || '0.0.0.0'
59
+ @port = options[:Port] || 8089
60
+ end
61
+
62
+ def listen
63
+ log "Starting server on #{@host}:#{@port}"
64
+ server = TCPServer.new(@host, @port)
65
+
66
+ yield server if block_given?
67
+
68
+ loop do
69
+ socket = server.accept
70
+ socket.sync = true
71
+ log "#{socket.peeraddr[2]} (#{socket.peeraddr[3]})"
72
+ begin
73
+
74
+ req = {}
75
+
76
+ # parse the request line
77
+ request = socket.gets
78
+ method, path, version = request.split(" ")
79
+ req["REQUEST_METHOD"] = method
80
+ info, query = path.split("?")
81
+ req["PATH_INFO"] = info
82
+ req["QUERY_STRING"] = query
83
+
84
+ # parse the headers
85
+ while (line = socket.gets)
86
+ line.strip!
87
+ break if line.size == 0
88
+ key, val = line.split(": ")
89
+ key = key.upcase.gsub('-', '_')
90
+ key = "HTTP_#{key}" if !%w[CONTENT_TYPE CONTENT_LENGTH].include?(key)
91
+ req[key] = val
92
+ end
93
+
94
+ # parse the body
95
+ body = ''
96
+ if (len = req['CONTENT_LENGTH']) && ["POST", "PUT"].member?(method)
97
+ body = socket.read(len.to_i)
98
+ end
99
+
100
+ # process the request
101
+ process_request(req, body, socket)
102
+
103
+ ensure
104
+ socket.close if not socket.closed?
105
+ end
106
+ end
107
+ end
108
+
109
+ def log(message)
110
+ # $stderr.puts message
111
+ end
112
+
113
+ def status_message(code)
114
+ StatusMessage[code]
115
+ end
116
+
117
+ def process_request(request, input_body, socket)
118
+ env = {}.replace(request)
119
+ env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
120
+ env["QUERY_STRING"] ||= ""
121
+ env["SCRIPT_NAME"] = ""
122
+
123
+ rack_input = StringIO.new(input_body)
124
+ rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
125
+
126
+ env.update({"rack.version" => [1,0],
127
+ "rack.input" => rack_input,
128
+ "rack.errors" => $stderr,
129
+ "rack.multithread" => true,
130
+ "rack.multiprocess" => true,
131
+ "rack.run_once" => false,
132
+
133
+ "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http"
134
+ })
135
+ status, headers, body = app.call(env)
136
+ begin
137
+ socket.write("HTTP/1.1 #{status} #{status_message(status)}\r\n")
138
+ headers.each do |k, vs|
139
+ vs.split("\n").each { |v| socket.write("#{k}: #{v}\r\n")}
140
+ end
141
+ socket.write("\r\n")
142
+ body.each { |s| socket.write(s) }
143
+ ensure
144
+ body.close if body.respond_to? :close
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,27 @@
1
+ bcat(1) -- browser cat
2
+ ======================
3
+
4
+ ## SYNOPSIS
5
+
6
+ `bcat`<br>
7
+ `bcat` <file>... [-]<br>
8
+
9
+ ## DESCRIPTION
10
+
11
+ The `bcat` utility reads from standard input, or one or more <file>s, and writes
12
+ output to a web browser progressively. When <file> is '-'
13
+
14
+ ## ENVIRONMENT
15
+
16
+ * `BCAT_COMMAND`=`open -a $BCAT_APPLICATION $url`:
17
+ * `BCAT_COMMAND`=`xdg-open "$url"`:
18
+ The command used to launch to the browser application.
19
+
20
+ * `BCAT_APPLICATION`=[`Safari | Google Chrome | Firefox`]:
21
+ MacOS X only. The name of the Application . This is given as the value of
22
+ the `-a` argument to open(1). When `BCAT_APPLICATION` is undefined, the
23
+ system default browser is used.
24
+
25
+ ## SEE ALSO
26
+
27
+ cat(1), open(1)
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bcat
3
+ version: !ruby/object:Gem::Version
4
+ hash: 31
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 0
10
+ version: 0.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Ryan Tomayko
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-06-19 00:00:00 -07:00
19
+ default_executable: bcat
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rack
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ description: Concatenate input from standard input, or one or more files, and write progressive output to a browser.
36
+ email: rtomayko@gmail.com
37
+ executables:
38
+ - bcat
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - COPYING
43
+ files:
44
+ - Rakefile
45
+ - bcat.gemspec
46
+ - bin/bcat
47
+ - lib/bcat.rb
48
+ - lib/bcat/kidgloves.rb
49
+ - man/bcat.1.ronn
50
+ - COPYING
51
+ has_rdoc: true
52
+ homepage: http://github.com/rtomayko/bcat/
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --line-numbers
58
+ - --inline-source
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ hash: 3
67
+ segments:
68
+ - 0
69
+ version: "0"
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ requirements: []
80
+
81
+ rubyforge_project:
82
+ rubygems_version: 1.3.7
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: browser cat
86
+ test_files: []
87
+