bcat 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'bcat'
3
- s.version = '0.3.0'
4
- s.date = '2010-06-21'
3
+ s.version = '0.4.0'
4
+ s.date = '2010-06-23'
5
5
 
6
6
  s.summary = "browser cat"
7
7
  s.description =
@@ -19,16 +19,21 @@ Gem::Specification.new do |s|
19
19
  README
20
20
  Rakefile
21
21
  bcat.gemspec
22
+ bin/a2h
22
23
  bin/bcat
23
- bin/bcat-encodehtml
24
24
  bin/btee
25
25
  lib/bcat.rb
26
+ lib/bcat/ansi.rb
26
27
  lib/bcat/browser.rb
27
28
  lib/bcat/html.rb
28
29
  lib/bcat/kidgloves.rb
29
30
  lib/bcat/reader.rb
31
+ man/a2h.1.ronn
30
32
  man/bcat.1.ronn
31
33
  man/btee.1.ronn
34
+ test/test_bcat_a2h.rb
35
+ test/test_bcat_ansi.rb
36
+ test/test_bcat_browser.rb
32
37
  test/test_bcat_head_parser.rb
33
38
  ]
34
39
  # = MANIFEST =
data/bin/a2h ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ # Usage: a2h [-] [<file>...]
3
+ # Convert ANSI/VT100 escape sequences to HTML.
4
+ require 'bcat/ansi'
5
+ require 'bcat/reader'
6
+
7
+ $stdin.sync = true
8
+ $stdout.sync = true
9
+
10
+ ARGV.push '-' if ARGV.empty?
11
+
12
+ reader = Bcat::Reader.new(ARGV.to_a)
13
+ filter = Bcat::ANSI.new(reader)
14
+ filter.each { |text| $stdout.write(text) }
data/bin/bcat CHANGED
@@ -1,41 +1,45 @@
1
1
  #!/usr/bin/env ruby
2
- #/ Usage: bcat [-ht] [-m <module>] [-T <title>] [<file>]...
2
+ #/ Usage: bcat [-ht] [-a] [-b <browser>] [-T <title>] [<file>]...
3
3
  #/ btee <options> [<file>]...
4
4
  #/ Pipe to browser utility. Read standard input, possibly one or more <file>s,
5
5
  #/ and write concatenated / formatted output to browser. When invoked as btee,
6
6
  #/ also write all input back to standard output.
7
7
  #/
8
- #/ Input format (auto detected by default):
9
- #/ -h, --html input is already HTML encoded, perhaps a whole document
10
- #/ -t, --text input is unencoded text
8
+ #/ Display options:
9
+ #/ -b, --browser=<browser> open <browser> instead of system default browser
10
+ #/ -T, --title=<text> use <text> as the browser title
11
+ #/ -a, --ansi convert ANSI (color) escape sequences to HTML
11
12
  #/
12
- #/ Tweak output with these options:
13
- #/ -T, --title=<text> use <text> as the page title
14
- #/ -m, --module=<m1>[,<m2>]...
15
- #/ inject formatting module(s)
13
+ #/ Input format (auto detected by default):
14
+ #/ -h, --html input is already HTML encoded, doc or fragment
15
+ #/ -t, --text input is unencoded text
16
16
  #/
17
+ #/ Misc options:
17
18
  #/ -d, --debug enable verbose debug logging on stderr
18
19
  require 'optparse'
19
20
 
20
21
  options = {
21
- :format => nil,
22
- :title => Dir.pwd,
23
- :Host => '127.0.0.1',
24
- :Port => 8091,
25
- :debug => false,
26
- :tee => !!($0 =~ /tee$/)
22
+ :Host => '127.0.0.1',
23
+ :Port => 8091,
24
+ :format => nil,
25
+ :title => Dir.pwd,
26
+ :browser => (ENV['BCAT_BROWSER'].to_s.size > 0 ? ENV['BCAT_BROWSER'] : 'default'),
27
+ :ansi => false,
28
+ :debug => false,
29
+ :tee => !!($0 =~ /tee$/)
27
30
  }
28
31
 
29
32
  (class <<self;self;end).send(:define_method, :notice) { |message|
30
33
  warn "#{File.basename($0)}: #{message}" if options[:debug] }
31
34
 
32
35
  ARGV.options do |argv|
33
- argv.on('-h', '--html') { options[:format] = 'html' }
34
- argv.on('-t', '--text') { options[:format] = 'text' }
35
- argv.on('-a', '--app=v') { |app| ENV['BCAT_APPLICATION'] = app }
36
- argv.on('-T', '--title=v') { |text| options[:title] = text }
37
- argv.on('-d', '--debug') { options[:debug] = true }
38
- argv.on_tail('--help') { exec "grep ^#/ <#{__FILE__} | cut -c4-" }
36
+ argv.on('-h', '--html') { options[:format] = 'html' }
37
+ argv.on('-t', '--text') { options[:format] = 'text' }
38
+ argv.on('-b', '--browser=v') { |app| options[:browser] = app }
39
+ argv.on('-T', '--title=v') { |text| options[:title] = text }
40
+ argv.on('-a', '--ansi') { options[:ansi] = true }
41
+ argv.on('-d', '--debug') { options[:debug] = true }
42
+ argv.on_tail('--help') { exec "grep ^#/ <#{__FILE__} | cut -c4-" }
39
43
  argv.parse!
40
44
  end
41
45
  ARGV.push '-' if ARGV.empty?
@@ -43,9 +47,9 @@ ARGV.push '-' if ARGV.empty?
43
47
  require 'bcat'
44
48
  notice "loaded bcat v#{Bcat::VERSION}"
45
49
 
46
- include Bcat::Browser
47
- notice "env BCAT_APPLICATION=#{ENV['BCAT_APPLICATION'].inspect}"
48
- notice "env BCAT_COMMAND=#{browser_command.inspect}"
50
+ browser = Bcat::Browser.new(options[:browser])
51
+ notice "env BCAT_BROWSER=#{options[:browser].inspect}"
52
+ notice "env BCAT_COMMAND='#{browser.command}'"
49
53
 
50
54
  notice "starting server"
51
55
  pid = nil
@@ -53,13 +57,13 @@ begin
53
57
  bcat = Bcat.new(ARGV, options)
54
58
  bcat.serve! do |sock|
55
59
  url = "http://#{bcat[:Host]}:#{bcat[:Port]}/#{File.basename(Dir.pwd)}"
56
- pid = browser(url)
60
+ pid = browser.open(url)
57
61
  end
58
62
  rescue Interrupt
59
63
  notice "interrupt"
60
64
  end
61
65
 
62
66
  Process.wait(pid) if pid
63
- status = $?
64
- notice "browser exited with #{status}"
67
+ status = $?.exitstatus
68
+ notice "browser [pid: #{pid}] exited with #{status}"
65
69
  exit status
@@ -1,11 +1,12 @@
1
1
  require 'rack'
2
2
  require 'bcat/reader'
3
+ require 'bcat/ansi'
3
4
  require 'bcat/html'
4
5
  require 'bcat/kidgloves'
5
6
  require 'bcat/browser'
6
7
 
7
8
  class Bcat
8
- VERSION = '0.3.0'
9
+ VERSION = '0.4.0'
9
10
  include Rack::Utils
10
11
 
11
12
  attr_reader :format
@@ -18,6 +19,7 @@ class Bcat
18
19
  @filter = @reader
19
20
  @filter = TeeFilter.new(@filter) if @config[:tee]
20
21
  @filter = TextFilter.new(@filter) if @format == 'text'
22
+ @filter = ANSI.new(@filter) if @format == 'text' || @config[:ansi]
21
23
  end
22
24
 
23
25
  def [](key)
@@ -0,0 +1,169 @@
1
+ class Bcat
2
+
3
+ # Converts ANSI color sequences to HTML.
4
+ #
5
+ # The ANSI module is based on code from the following libraries:
6
+ #
7
+ # ansi2html.sh:
8
+ # http://code.google.com/p/wrdese/source/browse/trunk/b/ansi2html.sh?r=5
9
+ #
10
+ # HTML::FromANSI:
11
+ # http://cpansearch.perl.org/src/NUFFIN/HTML-FromANSI-2.03/lib/HTML/FromANSI.pm
12
+ class ANSI
13
+ ESCAPE = "\x1b"
14
+
15
+ # Linux console palette
16
+ STYLES = {
17
+ 'ef0' => 'color:#000',
18
+ 'ef1' => 'color:#A00',
19
+ 'ef2' => 'color:#0A0',
20
+ 'ef3' => 'color:#A50',
21
+ 'ef4' => 'color:#00A',
22
+ 'ef5' => 'color:#A0A',
23
+ 'ef6' => 'color:#0AA',
24
+ 'ef7' => 'color:#AAA',
25
+ 'ef8' => 'color:#555',
26
+ 'ef9' => 'color:#F55',
27
+ 'ef10' => 'color:#5F5',
28
+ 'ef11' => 'color:#FF5',
29
+ 'ef12' => 'color:#55F',
30
+ 'ef13' => 'color:#F5F',
31
+ 'ef14' => 'color:#5FF',
32
+ 'ef15' => 'color:#FFF',
33
+ 'eb0' => 'background-color:#000',
34
+ 'eb1' => 'background-color:#A00',
35
+ 'eb2' => 'background-color:#0A0',
36
+ 'eb3' => 'background-color:#A50',
37
+ 'eb4' => 'background-color:#00A',
38
+ 'eb5' => 'background-color:#A0A',
39
+ 'eb6' => 'background-color:#0AA',
40
+ 'eb7' => 'background-color:#AAA',
41
+ 'eb8' => 'background-color:#555',
42
+ 'eb9' => 'background-color:#F55',
43
+ 'eb10' => 'background-color:#5F5',
44
+ 'eb11' => 'background-color:#FF5',
45
+ 'eb12' => 'background-color:#55F',
46
+ 'eb13' => 'background-color:#F5F',
47
+ 'eb14' => 'background-color:#5FF',
48
+ 'eb15' => 'background-color:#FFF'
49
+ }
50
+
51
+ ##
52
+ # The default xterm 256 colour palette
53
+
54
+ (0..5).each do |red|
55
+ (0..5).each do |green|
56
+ (0..5).each do |blue|
57
+ c = 16 + (red * 36) + (green * 6) + blue
58
+ r = red > 0 ? red * 40 + 55 : 0
59
+ g = green > 0 ? green * 40 + 55 : 0
60
+ b = blue > 0 ? blue * 40 + 55 : 0
61
+ STYLES["ef#{c}"] = "color:#%2.2x%2.2x%2.2x" % [r, g, b]
62
+ STYLES["eb#{c}"] = "background-color:#%2.2x%2.2x%2.2x" % [r, g, b]
63
+ end
64
+ end
65
+ end
66
+
67
+ (0..23).each do |gray|
68
+ c = gray+232
69
+ l = gray*10 + 8
70
+ STYLES["ef#{c}"] = "color:#%2.2x%2.2x%2.2x" % [l, l, l]
71
+ STYLES["eb#{c}"] = "background-color:#%2.2x%2.2x%2.2x" % [l, l, l]
72
+ end
73
+
74
+ def initialize(input)
75
+ @input =
76
+ if input.respond_to?(:to_str)
77
+ [input]
78
+ elsif !input.respond_to?(:each)
79
+ raise ArgumentError, "input must respond to each"
80
+ else
81
+ input
82
+ end
83
+ @stack = []
84
+ end
85
+
86
+ def to_html
87
+ buf = []
88
+ each { |chunk| buf << chunk }
89
+ buf.join
90
+ end
91
+
92
+ def each
93
+ buf = ''
94
+ @input.each do |chunk|
95
+ buf << chunk
96
+ tokenize(buf) do |tok, data|
97
+ case tok
98
+ when :text
99
+ yield data
100
+ when :display
101
+ case code = data
102
+ when 0 ; yield reset_styles if @stack.any?
103
+ when 1 ; yield push_tag("b") # bright
104
+ when 2 ; #dim
105
+ when 3 ; yield push_tag("u")
106
+ when 5 ; yield push_tag("blink")
107
+ when 7 ; #reverse
108
+ when 8 ; yield push_style("display:none")
109
+ when 9 ; yield push_tag("strike")
110
+ when 30..37 ; yield push_style("ef#{code - 30}")
111
+ when 40..47 ; yield push_style("eb#{code - 40}")
112
+ when 90..97 ; yield push_style("ef#{8 + code - 90}")
113
+ when 100..107 ; yield push_style("eb#{8 + code - 100}")
114
+ end
115
+ end
116
+ end
117
+ end
118
+ yield buf if !buf.empty?
119
+ yield reset_styles if @stack.any?
120
+ self
121
+ end
122
+
123
+ def push_tag(tag, style=nil)
124
+ style = STYLES[style] if style && !style.include?(':')
125
+ @stack.push tag
126
+ [ "<#{tag}",
127
+ (" style='#{style}'" if style),
128
+ ">"
129
+ ].join
130
+ end
131
+
132
+ def push_style(style)
133
+ push_tag "span", style
134
+ end
135
+
136
+ def reset_styles
137
+ stack, @stack = @stack, []
138
+ stack.reverse.map { |tag| "</#{tag}>" }.join
139
+ end
140
+
141
+ def tokenize(text)
142
+ tokens = [
143
+ # characters to remove completely
144
+ [/\A\x08+/, lambda { |m| '' }],
145
+
146
+ # ansi escape sequences that mess with the display
147
+ [/\A\x1b\[((?:\d{1,3};?)+)m/, lambda { |m|
148
+ m.chomp(';').split(';').
149
+ each { |code| yield :display, code.to_i };
150
+ '' }],
151
+
152
+ # malformed sequences
153
+ [/\A\x1b\[?[\d;]{0,3}/, lambda { |m| '' }],
154
+
155
+ # real text
156
+ [/\A([^\x1b\x08]+)/m, lambda { |m| yield :text, m; '' }]
157
+ ]
158
+
159
+ while (size = text.size) > 0
160
+ tokens.each do |pattern, sub|
161
+ while text.sub!(pattern) { sub.call($1) }
162
+ end
163
+ end
164
+ break if text.size == size
165
+ end
166
+ end
167
+
168
+ end
169
+ end
@@ -1,24 +1,69 @@
1
1
  class Bcat
2
- module Browser
3
- def browser(url, application=ENV['BCAT_APPLICATION'])
2
+ class Browser
3
+ ENVIRONMENT =
4
+ case `uname`
5
+ when /Darwin/ ; 'Darwin'
6
+ when /Linux/, /BSD/ ; 'X11'
7
+ else 'X11'
8
+ end
9
+
10
+ # browser name -> command mappings
11
+ COMMANDS = {
12
+ 'Darwin' => {
13
+ 'default' => "open",
14
+ 'safari' => "open -a Safari",
15
+ 'firefox' => "open -a Firefox",
16
+ 'chrome' => "open -a Google\\ Chrome",
17
+ 'chromium' => "open -a Chromium",
18
+ 'opera' => "open -a Opera",
19
+ 'curl' => "curl -s"
20
+ },
21
+
22
+ 'X11' => {
23
+ 'default' => "xdg-open",
24
+ 'firefox' => "firefox",
25
+ 'chrome' => "google-chrome",
26
+ 'chromium' => "chromium",
27
+ 'mozilla' => "mozilla",
28
+ 'epiphany' => "epiphany",
29
+ 'curl' => "curl -s"
30
+ }
31
+ }
32
+
33
+ # alternative names for browsers
34
+ ALIASES = {
35
+ 'google-chrome' => 'chrome',
36
+ 'google chrome' => 'chrome',
37
+ 'gnome' => 'epiphany'
38
+ }
39
+
40
+ def initialize(browser, command=ENV['BCAT_COMMAND'])
41
+ @browser = browser
42
+ @command = command
43
+ end
44
+
45
+ def open(url)
4
46
  command = browser_command
5
47
  fork do
6
48
  [$stdin, $stdout].each { |fd| fd.close }
7
- ENV['BCAT_ARGS'] = "-a '#{application}'" if !application.to_s.empty?
8
- ENV['BCAT_URL'] = url
9
- ENV['BCAT_COMMAND'] = command
10
- exec "/bin/sh -c \"#{command.gsub(/"/, '\"')}\""
49
+ exec "#{command} #{shell_quote(url)}"
11
50
  end
12
51
  end
13
52
 
14
- def browser_command
15
- return ENV['BCAT_COMMAND'] if !ENV['BCAT_COMMAND'].to_s.empty?
53
+ def command
54
+ return @command if @command
55
+ browser_command
56
+ end
16
57
 
17
- case `uname`
18
- when /Darwin/ ; 'open $BCAT_ARGS "$BCAT_URL"'
19
- when /Linux/, /BSD/ ; 'xdg-open $BCAT_ARGS "$BCAT_URL"'
20
- else ; 'xdg-open "$BCAT_URL"'
21
- end
58
+ def browser_command(browser=@browser)
59
+ browser ||= 'default'
60
+ browser = browser.downcase
61
+ browser = ALIASES[browser] || browser
62
+ COMMANDS[ENVIRONMENT][browser]
63
+ end
64
+
65
+ def shell_quote(argument)
66
+ arg = argument.to_s.gsub(/([\\'])/) { "\\" + $1 }
22
67
  end
23
68
  end
24
69
  end
@@ -0,0 +1,39 @@
1
+ a2h(1) -- convert ANSI/VT100 escape sequences to HTML
2
+ =====================================================
3
+
4
+ ## SYNOPSIS
5
+
6
+ `a2h` [-] [<file>...]
7
+
8
+ ## DESCRIPTION
9
+
10
+ The `a2h` utility reads from standard input, or one or more <file>s, and
11
+ converts ANSI/VT100 escape sequences to inline HTML.
12
+
13
+ ## ESCAPE SEQUENCES
14
+
15
+ The following escape sequences are supported:
16
+
17
+ * `<ESC>[0m`:
18
+ Resets all attributes / closes all HTML tags.
19
+ * `<ESC>[1m`=`<b>`:
20
+ Bold.
21
+ * `<ESC>[4m`=`<u>`:
22
+ Underscore.
23
+ * `<ESC>[5m`=`<blink>`:
24
+ Blink. Really.
25
+ * `<ESC>[8m`=`<span style='display:none'>`:
26
+ Hidden.
27
+ * `<ESC>[30-37m`=`<span style='color:`<color>`>`:
28
+ Foreground color.
29
+ * `<ESC>[40-47m`=`<span style='background-color:`<color>`>`:
30
+ Background color.
31
+ * `<ESC>[90-97m`=`<span style='color:`<color>`>`:
32
+ Light foreground colors.
33
+ * `<ESC>[100-107m`=`<span style='background-color:`<color>`>`:
34
+ Light background color.
35
+
36
+ ## SEE ALSO
37
+
38
+ [ansi2html.sh](http://code.google.com/p/wrdese/source/browse/trunk/b/ansi2html.sh?r=5),
39
+ [HTML::FromANSI](http://cpansearch.perl.org/src/NUFFIN/HTML-FromANSI-2.03/lib/HTML/FromANSI.pm)
@@ -17,6 +17,25 @@ addition to being piped into the browser.
17
17
 
18
18
  ## OPTIONS
19
19
 
20
+ `bcat` opens a simple, undecorated page with the system default web browser and
21
+ immediately begins streaming input. The following options control the browser
22
+ display:
23
+
24
+ * `-b`, `--browser`=default|firefox|safari|chrome|opera|<other>
25
+ The name of the browser application. Defaults to the value of the
26
+ `BCAT_BROWSER` environment variable, or the system default browser when
27
+ no `BCAT_BROWSER` is defined.
28
+
29
+ * `-T`, `--title`=<text>:
30
+ Use <text> as the page `<title>`. By default, the path to the current working
31
+ directory is used as the title.
32
+
33
+ * `-a`, `--ansi`:
34
+ Turns on VT100/ANSI escape sequence conversion. This causes all input to be
35
+ piped through a2h(1), replacing ANSI escape sequences with HTML for things
36
+ like bold, underline, and colors. On by default when the input is text; use
37
+ the `-a` option to turn it on when the input is HTML.
38
+
20
39
  By default, `bcat` attempts to detect whether input is HTML or plain text using
21
40
  a simple heuristic, but you can force input to be treated as one or the other
22
41
  with these options:
@@ -32,15 +51,7 @@ with these options:
32
51
  document, or it may be an HTML fragment. `bcat` outputs `<html>`, `<head>`,
33
52
  and `<body>` elements even if they are not included in the input.
34
53
 
35
- Customization
36
-
37
- * `-T`, `--title`=<text>:
38
- Use <text> as the page `<title>`. By default, the path to the current working
39
- directory is used as the title.
40
-
41
- * `-a`, `--app`=`Safari`|`Google Chrome`|`Firefox`:
42
- MacOS only. The name of the browser application. This can also be set using
43
- the `BCAT_APPLICATION` environment variable.
54
+ Miscellaneous options:
44
55
 
45
56
  * `-d`, `--debug`:
46
57
  Turn on verbose debug logging to standard error. Include this output when
@@ -48,14 +59,16 @@ Customization
48
59
 
49
60
  ## ENVIRONMENT
50
61
 
51
- * `BCAT_COMMAND`=`open -a $BCAT_APPLICATION $url`:
52
- * `BCAT_COMMAND`=`xdg-open "$url"`:
53
- The command used to launch to the browser application.
62
+ * `BCAT_BROWSER`=default|firefox|safari|chrome|opera|<other>:
63
+ The name of the browser to use by default. `bcat` maps this to an
64
+ actual browser command based on the current platform. The special
65
+ value "default" maps to the system default browser.
54
66
 
55
- * `BCAT_APPLICATION`=[`Safari` | `Google Chrome` | `Firefox`]:
56
- MacOS X only. The name of the browser application . This is given as the
57
- value of the `-a` argument to open(1). When `BCAT_APPLICATION` is undefined,
58
- the system default browser is used.
67
+ * `BCAT_COMMAND`=<command>:
68
+ The entire browser command line (to be executed by `/bin/sh`). This
69
+ overrides the `BCAT_BROWSER` environment variable and makes the `--browser`
70
+ (`-b`) option a no-op. This should only be necessary when running a
71
+ browser unknown to bcat or in order to pass special arguments.
59
72
 
60
73
  ## SEE ALSO
61
74
 
@@ -17,6 +17,25 @@ addition to being piped into the browser.
17
17
 
18
18
  ## OPTIONS
19
19
 
20
+ `bcat` opens a simple, undecorated page with the system default web browser and
21
+ immediately begins streaming input. The following options control the browser
22
+ display:
23
+
24
+ * `-b`, `--browser`=default|firefox|safari|chrome|opera|<other>
25
+ The name of the browser application. Defaults to the value of the
26
+ `BCAT_BROWSER` environment variable, or the system default browser when
27
+ no `BCAT_BROWSER` is defined.
28
+
29
+ * `-T`, `--title`=<text>:
30
+ Use <text> as the page `<title>`. By default, the path to the current working
31
+ directory is used as the title.
32
+
33
+ * `-a`, `--ansi`:
34
+ Turns on VT100/ANSI escape sequence conversion. This causes all input to be
35
+ piped through a2h(1), replacing ANSI escape sequences with HTML for things
36
+ like bold, underline, and colors. On by default when the input is text; use
37
+ the `-a` option to turn it on when the input is HTML.
38
+
20
39
  By default, `bcat` attempts to detect whether input is HTML or plain text using
21
40
  a simple heuristic, but you can force input to be treated as one or the other
22
41
  with these options:
@@ -32,15 +51,7 @@ with these options:
32
51
  document, or it may be an HTML fragment. `bcat` outputs `<html>`, `<head>`,
33
52
  and `<body>` elements even if they are not included in the input.
34
53
 
35
- Customization
36
-
37
- * `-T`, `--title`=<text>:
38
- Use <text> as the page `<title>`. By default, the path to the current working
39
- directory is used as the title.
40
-
41
- * `-a`, `--app`=`Safari`|`Google Chrome`|`Firefox`:
42
- MacOS only. The name of the browser application. This can also be set using
43
- the `BCAT_APPLICATION` environment variable.
54
+ Miscellaneous options:
44
55
 
45
56
  * `-d`, `--debug`:
46
57
  Turn on verbose debug logging to standard error. Include this output when
@@ -48,14 +59,16 @@ Customization
48
59
 
49
60
  ## ENVIRONMENT
50
61
 
51
- * `BCAT_COMMAND`=`open -a $BCAT_APPLICATION $url`:
52
- * `BCAT_COMMAND`=`xdg-open "$url"`:
53
- The command used to launch to the browser application.
62
+ * `BCAT_BROWSER`=default|firefox|safari|chrome|opera|<other>:
63
+ The name of the browser to use by default. `bcat` maps this to an
64
+ actual browser command based on the current platform. The special
65
+ value "default" maps to the system default browser.
54
66
 
55
- * `BCAT_APPLICATION`=[`Safari` | `Google Chrome` | `Firefox`]:
56
- MacOS X only. The name of the browser application . This is given as the
57
- value of the `-a` argument to open(1). When `BCAT_APPLICATION` is undefined,
58
- the system default browser is used.
67
+ * `BCAT_COMMAND`=<command>:
68
+ The entire browser command line (to be executed by `/bin/sh`). This
69
+ overrides the `BCAT_BROWSER` environment variable and makes the `--browser`
70
+ (`-b`) option a no-op. This should only be necessary when running a
71
+ browser unknown to bcat or in order to pass special arguments.
59
72
 
60
73
  ## SEE ALSO
61
74
 
@@ -0,0 +1,19 @@
1
+ require 'contest'
2
+
3
+ ENV['PATH'] = [File.expand_path('../../bin'), ENV['PATH']].join(':')
4
+
5
+ class ANSI2HTMLCommandTest < Test::Unit::TestCase
6
+ test "piping stuff through a2h" do
7
+ IO.popen("a2h", 'w+') do |io|
8
+ io.sync = true
9
+ io.puts "hello there"
10
+ io.flush
11
+ assert_equal "hello there\n", io.read("hello there\n".size)
12
+ io.puts "and \x1b[1mhere's some bold"
13
+ assert_equal "and <b>here's some bold\n", io.read(24)
14
+ io.close_write
15
+ assert_equal "</b>", io.read(4)
16
+ io.close
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,115 @@
1
+ require 'contest'
2
+ require 'bcat/ansi'
3
+
4
+ class ANSITest < Test::Unit::TestCase
5
+ test 'should not modify input string' do
6
+ text = "some text"
7
+ Bcat::ANSI.new(text).to_html
8
+ assert_equal "some text", text
9
+ end
10
+
11
+ test 'passing through text with no escapes' do
12
+ text = "hello\nthis is bcat\n"
13
+ ansi = Bcat::ANSI.new(text)
14
+ assert_equal text, ansi.to_html
15
+ end
16
+
17
+ test "removing backspace characters" do
18
+ text = "like this"
19
+ ansi = Bcat::ANSI.new(text)
20
+ assert_equal "like this", ansi.to_html
21
+ end
22
+
23
+ test "foreground colors" do
24
+ text = "colors: \x1b[30mblack\x1b[37mwhite"
25
+ expect = "colors: " +
26
+ "<span style='color:#000'>black" +
27
+ "<span style='color:#AAA'>white" +
28
+ "</span></span>"
29
+ assert_equal expect, Bcat::ANSI.new(text).to_html
30
+ end
31
+
32
+ test "light foreground colors" do
33
+ text = "colors: \x1b[90mblack\x1b[97mwhite"
34
+ expect = "colors: " +
35
+ "<span style='color:#555'>black" +
36
+ "<span style='color:#FFF'>white" +
37
+ "</span></span>"
38
+ assert_equal expect, Bcat::ANSI.new(text).to_html
39
+ end
40
+
41
+ test "background colors" do
42
+ text = "colors: \x1b[40mblack\x1b[47mwhite"
43
+ expect = "colors: " +
44
+ "<span style='background-color:#000'>black" +
45
+ "<span style='background-color:#AAA'>white" +
46
+ "</span></span>"
47
+ assert_equal expect, Bcat::ANSI.new(text).to_html
48
+ end
49
+
50
+ test "light background colors" do
51
+ text = "colors: \x1b[100mblack\x1b[107mwhite"
52
+ expect = "colors: " +
53
+ "<span style='background-color:#555'>black" +
54
+ "<span style='background-color:#FFF'>white" +
55
+ "</span></span>"
56
+ assert_equal expect, Bcat::ANSI.new(text).to_html
57
+ end
58
+
59
+ test "strikethrough" do
60
+ text = "strike: \x1b[9mthat"
61
+ expect = "strike: <strike>that</strike>"
62
+ assert_equal expect, Bcat::ANSI.new(text).to_html
63
+ end
64
+
65
+ test "blink!" do
66
+ text = "blink: \x1b[5mwhat"
67
+ expect = "blink: <blink>what</blink>"
68
+ assert_equal expect, Bcat::ANSI.new(text).to_html
69
+ end
70
+
71
+ test "underline" do
72
+ text = "underline: \x1b[3mstuff"
73
+ expect = "underline: <u>stuff</u>"
74
+ assert_equal expect, Bcat::ANSI.new(text).to_html
75
+ end
76
+
77
+ test "bold" do
78
+ text = "bold: \x1b[1mstuff"
79
+ expect = "bold: <b>stuff</b>"
80
+ assert_equal expect, Bcat::ANSI.new(text).to_html
81
+ end
82
+
83
+ test "resetting a single sequence" do
84
+ text = "\x1b[1mthis is bold\x1b[0m, but this isn't"
85
+ expect = "<b>this is bold</b>, but this isn't"
86
+ assert_equal expect, Bcat::ANSI.new(text).to_html
87
+ end
88
+
89
+ test "resetting many sequences" do
90
+ text = "normal, \x1b[1mbold, \x1b[3munderline, \x1b[31mred\x1b[0m, normal"
91
+ expect = "normal, <b>bold, <u>underline, " +
92
+ "<span style='color:#A00'>red</span></u></b>, normal"
93
+ assert_equal expect, Bcat::ANSI.new(text).to_html
94
+ end
95
+
96
+ test "multi-attribute sequences" do
97
+ text = "normal, \x1b[1;3;31mbold, underline, and red\x1b[0m, normal"
98
+ expect = "normal, <b><u><span style='color:#A00'>" +
99
+ "bold, underline, and red</span></u></b>, normal"
100
+ assert_equal expect, Bcat::ANSI.new(text).to_html
101
+ end
102
+
103
+ test "multi-attribute sequences with a trailing semi-colon" do
104
+ text = "normal, \x1b[1;3;31;mbold, underline, and red\x1b[0m, normal"
105
+ expect = "normal, <b><u><span style='color:#A00'>" +
106
+ "bold, underline, and red</span></u></b>, normal"
107
+ assert_equal expect, Bcat::ANSI.new(text).to_html
108
+ end
109
+
110
+ test "eating malformed sequences" do
111
+ text = "\x1b[25oops forgot the 'm'"
112
+ expect = "oops forgot the 'm'"
113
+ assert_equal expect, Bcat::ANSI.new(text).to_html
114
+ end
115
+ end
@@ -0,0 +1,5 @@
1
+ require 'contest'
2
+ require 'bcat/browser'
3
+
4
+ class BrowserTest < Test::Unit::TestCase
5
+ end
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bcat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ hash: 15
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 4
9
+ - 0
10
+ version: 0.4.0
5
11
  platform: ruby
6
12
  authors:
7
13
  - Ryan Tomayko
@@ -9,19 +15,23 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2010-06-21 00:00:00 -07:00
18
+ date: 2010-06-23 00:00:00 -07:00
13
19
  default_executable: bcat
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
22
  name: rack
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
20
26
  requirements:
21
27
  - - ">="
22
28
  - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
23
32
  version: "0"
24
- version:
33
+ type: :runtime
34
+ version_requirements: *id001
25
35
  description: Concatenate input from standard input, or one or more files, and write progressive output to a browser.
26
36
  email: rtomayko@gmail.com
27
37
  executables:
@@ -37,16 +47,21 @@ files:
37
47
  - README
38
48
  - Rakefile
39
49
  - bcat.gemspec
50
+ - bin/a2h
40
51
  - bin/bcat
41
- - bin/bcat-encodehtml
42
52
  - bin/btee
43
53
  - lib/bcat.rb
54
+ - lib/bcat/ansi.rb
44
55
  - lib/bcat/browser.rb
45
56
  - lib/bcat/html.rb
46
57
  - lib/bcat/kidgloves.rb
47
58
  - lib/bcat/reader.rb
59
+ - man/a2h.1.ronn
48
60
  - man/bcat.1.ronn
49
61
  - man/btee.1.ronn
62
+ - test/test_bcat_a2h.rb
63
+ - test/test_bcat_ansi.rb
64
+ - test/test_bcat_browser.rb
50
65
  - test/test_bcat_head_parser.rb
51
66
  has_rdoc: true
52
67
  homepage: http://github.com/rtomayko/bcat/
@@ -59,21 +74,27 @@ rdoc_options:
59
74
  require_paths:
60
75
  - lib
61
76
  required_ruby_version: !ruby/object:Gem::Requirement
77
+ none: false
62
78
  requirements:
63
79
  - - ">="
64
80
  - !ruby/object:Gem::Version
81
+ hash: 3
82
+ segments:
83
+ - 0
65
84
  version: "0"
66
- version:
67
85
  required_rubygems_version: !ruby/object:Gem::Requirement
86
+ none: false
68
87
  requirements:
69
88
  - - ">="
70
89
  - !ruby/object:Gem::Version
90
+ hash: 3
91
+ segments:
92
+ - 0
71
93
  version: "0"
72
- version:
73
94
  requirements: []
74
95
 
75
96
  rubyforge_project:
76
- rubygems_version: 1.3.5
97
+ rubygems_version: 1.3.7
77
98
  signing_key:
78
99
  specification_version: 3
79
100
  summary: browser cat
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # Usage: bcat-encodehtml
3
- # Read text from stdin and write HTML encoded result to stdout.
4
-
5
- while char = $stdin.getc
6
- case char
7
- when ?<
8
- $stdout.write('&lt;')
9
- when ?&
10
- $stdout.write('&amp;')
11
- else
12
- $stdout.putc(char)
13
- end
14
- end