summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormurphy <murphy@rubychan.de>2011-06-17 23:13:24 +0000
committermurphy <murphy@rubychan.de>2011-06-17 23:13:24 +0000
commit90f70ee61e87e137aa192c5db97c382e1ec7d24b (patch)
treea9d5e9c7e0664faaada8d99741679d0bb8f6403c
parent4c8b5dac9d881b916a49e20401659bf107168e0b (diff)
downloadcoderay-90f70ee61e87e137aa192c5db97c382e1ec7d24b.tar.gz
issue #45: new command line interface!
-rwxr-xr-xbin/coderay167
-rwxr-xr-xbin/coderay_stylesheet4
-rw-r--r--etc/CodeRay.tmproj50
-rw-r--r--lib/coderay.rb4
-rw-r--r--rake_tasks/gem.rake2
-rw-r--r--test/executable/source.py1
-rw-r--r--test/executable/source.rb1
-rw-r--r--test/executable/suite.rb191
8 files changed, 317 insertions, 103 deletions
diff --git a/bin/coderay b/bin/coderay
index 690d8fc..70baa99 100755
--- a/bin/coderay
+++ b/bin/coderay
@@ -1,99 +1,112 @@
#!/usr/bin/env ruby
-# CodeRay Executable
-#
-# Version: 0.2
-# Author: murphy
+require 'coderay'
-def err msg
- $stderr.puts msg
-end
+$options, $args = ARGV.partition { |arg| arg[/^-[hv]$|--\w+/] }
+subcommand = $args.detect { |arg| arg[/^\w/] }
+subcommand = nil if subcommand && File.exist?(subcommand)
+$args.delete subcommand
-def read
- if file = ARGV[2]
- File.read file
- else
- $stdin.read
- end
+def option? *options
+ !($options & options).empty?
end
-begin
- require 'coderay'
+def tty?
+ $stdout.tty? || option?('--tty')
+end
- if ARGV.empty?
- puts <<-USAGE
-CodeRay #{CodeRay::VERSION} (http://coderay.rubychan.de)
+def version
+ puts <<-USAGE
+CodeRay #{CodeRay::VERSION}
+ USAGE
+end
+def help
+ puts <<-HELP
Usage:
- coderay -<lang> [-<format>] < file > output
- coderay file [-<format>]
+ coderay [-<language>] [input] [-<format>] [output]
Examples:
- coderay -ruby -statistic < foo.rb
- coderay -ruby < foo.rb # colorized output to terminal
- coderay -ruby -page foo.rb # HTML page output to terminal
- coderay -ruby -page foo.rb > foo.html # HTML page output to file
- coderay codegen.c # generates codegen.c.html
- USAGE
- end
+ coderay -ruby file -loc # count lines of code in Ruby file
+ coderay -ruby < foo.rb # colorized output to terminal
+ coderay -ruby foo.rb -page foo.html # HTML page output to file
+ coderay stylesheet # CSS stylesheet
+ HELP
+end
+
+def commands
+ puts <<-COMMANDS
+ General:
+ help print some help
+ version print CodeRay version
+ commands print this list
+ stylesheet print the CSS stylesheet with the given name
+ COMMANDS
+end
- first, second = ARGV
+if option? '-v', '--version'
+ version
+end
+
+if option? '-h', '--help'
+ help
+end
- if first
- if first[/-(\w+)/] == first
- lang = $1
- input = read
- tokens = :scan
- elsif first == '-'
- lang = $1
- input = read
- tokens = :scan
+case subcommand
+when 'highlight', nil
+ if ARGV.empty?
+ version
+ help
+ else
+ signature = $args.map { |arg| arg[/^-/] ? '-' : 'f' }.join
+ names = $args.map { |arg| arg.sub(/^-/, '') }
+ case signature
+ when /^$/
+ exit
+ when /^ff?$/
+ input_file, output_file, = *names
+ when /^-ff?$/
+ input_filetype, input_file, output_file, = *names
+ when /^-f-f?$/
+ input_filetype, input_file, output_filetype, output_file, = *names
+ when /^--?f?$/
+ input_filetype, output_filetype, output_file, = *names
else
- file = first
- tokens = CodeRay.scan_file file
- output_filename, output_ext = file, /#{Regexp.escape(File.extname(file))}$/
+ raise signature
end
- else
- puts 'No lang/file given.'
- exit 1
- end
-
- if second
- if second[/-(\w+)/] == second
- format = $1
+
+ if input_file
+ input_filetype ||= CodeRay::FileType.fetch input_file, :text, true
+ end
+
+ if output_file
+ output_filetype ||= CodeRay::FileType[output_file]
else
- raise 'invalid format (must be -xxx)'
+ output_filetype ||= tty? ? :term : :page
end
- else
- if $stdout.tty?
- format = :term
+
+ if input_file
+ input = File.read input_file
else
- $stderr.puts 'No format given; setting to default (HTML Page).'
- format = :page
+ input = $stdin.read
end
- end
-
- if tokens == :scan
- output = CodeRay.encoder(format).encode(input, lang)
- else
- output = tokens.encode format
- end
- out = $stdout
- if output_filename
- output_filename += '.' + CodeRay::Encoders[format]::FILE_EXTENSION.to_s
- if File.exist? output_filename
- err 'File %s already exists.' % output_filename
- exit
+
+ output = CodeRay.scan(input, input_filetype).encode(output_filetype)
+
+ if output_file
+ File.open output_file, 'w' do |file|
+ file.puts output
+ end
else
- out = File.open output_filename, 'w'
- puts "Writing to #{output_filename}..."
+ puts output
end
end
- out.puts output
-
-rescue => boom
- err "Error: #{boom.message}\n"
- err boom.backtrace
- err '-' * 50
- err ARGV
- exit 1
+when 'stylesheet'
+ puts CodeRay::Encoders[:html]::CSS.new($args.first).stylesheet
+when 'commands'
+ commands
+when 'help'
+ help
+else
+ puts "Unknown command: #{subcommand}"
+ help
end
diff --git a/bin/coderay_stylesheet b/bin/coderay_stylesheet
deleted file mode 100755
index 0e19395..0000000
--- a/bin/coderay_stylesheet
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/usr/bin/env ruby
-require 'coderay'
-
-puts CodeRay::Encoders[:html]::CSS.new.stylesheet
diff --git a/etc/CodeRay.tmproj b/etc/CodeRay.tmproj
index af6886f..1bbbc22 100644
--- a/etc/CodeRay.tmproj
+++ b/etc/CodeRay.tmproj
@@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
+ <key>currentDocument</key>
+ <string>../lib/coderay/scanners/ruby.rb</string>
<key>documents</key>
<array>
<dict>
@@ -174,7 +176,55 @@
<key>firstVisibleLine</key>
<integer>3</integer>
</dict>
+ <key>../lib/coderay/scanners/ruby.rb</key>
+ <dict>
+ <key>caret</key>
+ <dict>
+ <key>column</key>
+ <integer>39</integer>
+ <key>line</key>
+ <integer>83</integer>
+ </dict>
+ <key>firstVisibleColumn</key>
+ <integer>0</integer>
+ <key>firstVisibleLine</key>
+ <integer>71</integer>
+ </dict>
+ <key>../lib/coderay/scanners/ruby/patterns.rb</key>
+ <dict>
+ <key>caret</key>
+ <dict>
+ <key>column</key>
+ <integer>28</integer>
+ <key>line</key>
+ <integer>28</integer>
+ </dict>
+ <key>firstVisibleColumn</key>
+ <integer>0</integer>
+ <key>firstVisibleLine</key>
+ <integer>0</integer>
+ </dict>
+ <key>../lib/coderay/scanners/scheme.rb</key>
+ <dict>
+ <key>caret</key>
+ <dict>
+ <key>column</key>
+ <integer>32</integer>
+ <key>line</key>
+ <integer>21</integer>
+ </dict>
+ <key>firstVisibleColumn</key>
+ <integer>0</integer>
+ <key>firstVisibleLine</key>
+ <integer>0</integer>
+ </dict>
</dict>
+ <key>openDocuments</key>
+ <array>
+ <string>../lib/coderay/scanners/scheme.rb</string>
+ <string>../lib/coderay/scanners/ruby/patterns.rb</string>
+ <string>../lib/coderay/scanners/ruby.rb</string>
+ </array>
<key>showFileHierarchyDrawer</key>
<true/>
<key>windowFrame</key>
diff --git a/lib/coderay.rb b/lib/coderay.rb
index 60dcfd0..9b81772 100644
--- a/lib/coderay.rb
+++ b/lib/coderay.rb
@@ -134,6 +134,9 @@ module CodeRay
# Revision: Subversion Revision number (generated on rake gem:make)
VERSION = '1.0.0'
+ # helpers
+ autoload :FileType, 'coderay/helpers/file_type'
+
# Tokens
autoload :Tokens, 'coderay/tokens'
autoload :TokenKinds, 'coderay/token_kinds'
@@ -178,7 +181,6 @@ module CodeRay
def scan_file filename, lang = :auto, options = {}, &block
file = IO.read filename
if lang == :auto
- require 'coderay/helpers/file_type'
lang = FileType.fetch filename, :text, true
end
scan file, lang, options = {}, &block
diff --git a/rake_tasks/gem.rake b/rake_tasks/gem.rake
index bef2ac9..71b55a1 100644
--- a/rake_tasks/gem.rake
+++ b/rake_tasks/gem.rake
@@ -31,7 +31,7 @@ def gemspec
s.files = Dir['lib/**/*.rb'] + %w(Rakefile README.rdoc LICENSE) + Dir['test/functional/*.rb']
s.test_files = Dir['test/functional/*.rb']
- s.executables = [ 'coderay', 'coderay_stylesheet' ]
+ s.executables = ['coderay']
s.require_paths = ['lib']
s.rubyforge_project = s.name
diff --git a/test/executable/source.py b/test/executable/source.py
new file mode 100644
index 0000000..1bb2c00
--- /dev/null
+++ b/test/executable/source.py
@@ -0,0 +1 @@
+class ClassName(): pass \ No newline at end of file
diff --git a/test/executable/source.rb b/test/executable/source.rb
new file mode 100644
index 0000000..226f15f
--- /dev/null
+++ b/test/executable/source.rb
@@ -0,0 +1 @@
+class ClassName; end \ No newline at end of file
diff --git a/test/executable/suite.rb b/test/executable/suite.rb
index ddb0527..fd40909 100644
--- a/test/executable/suite.rb
+++ b/test/executable/suite.rb
@@ -1,4 +1,6 @@
require 'test/unit'
+require 'shoulda-context'
+
require 'pathname'
$:.unshift 'lib'
require 'coderay'
@@ -8,38 +10,187 @@ puts "Running CodeRay #{CodeRay::VERSION} executable tests..."
class TestCodeRayExecutable < Test::Unit::TestCase
ruby = `ps -c #$$`[/\w+\Z/]
- ruby = 'jruby' if ruby == 'java'
ROOT_DIR = Pathname.new(File.dirname(__FILE__)) + '..' + '..'
EXECUTABLE = ROOT_DIR + 'bin' + 'coderay'
EXE_COMMAND = '%s -wI%s %s'% [
- ruby, # calling Ruby process command
+ ruby, # calling Ruby process command
ROOT_DIR + 'lib', # library dir
- EXECUTABLE
+ EXECUTABLE # coderay
]
- def coderay args
- command = "#{EXE_COMMAND} #{args}"
- # puts command
- `#{command}`
+ def coderay args, fake_tty = false
+ if fake_tty
+ command = "#{EXE_COMMAND} #{args} --tty"
+ else
+ command = "#{EXE_COMMAND} #{args}"
+ end
+ puts command if $DEBUG
+ output = `#{command} 2>&1`
+ if output[EXECUTABLE.to_s]
+ raise output
+ else
+ output
+ end
+ end
+
+ context 'a simple call with no arguments' do
+ should 'work' do
+ assert_nothing_raised { coderay('') }
+ end
+ should 'print version and help' do
+ assert_match(/CodeRay #{CodeRay::VERSION}/, coderay(''))
+ assert_match(/Usage:/, coderay(''))
+ end
+ end
+
+ context 'version' do
+ should 'be printed with -v' do
+ assert_match(/\ACodeRay #{CodeRay::VERSION}\Z/, coderay('-v'))
+ end
+ should 'be printed with --version' do
+ assert_match(/\ACodeRay #{CodeRay::VERSION}\Z/, coderay('--version'))
+ end
+ end
+
+ context 'help' do
+ should 'be printed with -h' do
+ assert_match(/^Usage:/, coderay('-h'))
+ end
+ should 'be printed with --help' do
+ assert_match(/^Usage:/, coderay('--help'))
+ end
+ should 'be printed with subcommand help' do
+ assert_match(/^Usage:/, coderay('help'))
+ end
+ end
+
+ context 'commands' do
+ should 'be printed with subcommand commands' do
+ assert_match(/^ +help/, coderay('commands'))
+ assert_match(/^ +version/, coderay('commands'))
+ end
+ end
+
+ context 'highlighting a file to the terminal' do
+ source_file = 'test/executable/source.py'
+
+ source = File.read source_file
+
+ ansi_seq = /\e\[[0-9;]+m/
+
+ should 'not throw an error' do
+ assert_nothing_raised { coderay(source_file, :tty) }
+ end
+ should 'output its contents to stdout' do
+ target = coderay(source_file, :tty)
+ assert_equal source, target.chomp.gsub(ansi_seq, '')
+ end
+ should 'output ANSI-colored text' do
+ target = coderay(source_file, :tty)
+ assert_not_equal source, target.chomp
+ assert_equal 6, target.scan(ansi_seq).size
+ end
+ end
+
+ context 'highlighting a file into a pipe (source.rb > source.rb.html)' do
+ source_file = 'test/executable/source.rb'
+ target_file = "#{source_file}.html"
+ command = "#{source_file} > #{target_file}"
+
+ source = File.read source_file
+
+ pre = %r{<pre [^>]*>(.*?)</pre>}m
+ tag = /<[^>]*>/
+
+ should 'not throw an error' do
+ assert_nothing_raised { coderay(command) }
+ end
+ should 'output its contents to the pipe' do
+ coderay(command)
+ target = File.read(target_file)
+ if target = target[pre, 1]
+ assert_equal source, target.gsub(tag, '').strip
+ else
+ flunk "target code has no <pre> tag: #{target}"
+ end
+ end
+ should 'output valid HTML' do
+ coderay(command)
+ target = File.read(target_file)
+ assert_not_equal source, target[pre, 1]
+ assert_equal 6, target[pre, 1].scan(tag).size
+ assert_match %r{\A<!DOCTYPE html>\n<html>\n<head>}, target
+ end
+ end
+
+ context 'highlighting a file into another file (source.rb source.rb.json)' do
+ source_file = 'test/executable/source.rb'
+ target_file = "#{source_file}.json"
+ command = "#{source_file} #{target_file}"
+
+ source = File.read source_file
+
+ text = /"text":"([^"]*)"/
+
+ should 'not throw an error' do
+ assert_nothing_raised { coderay(command) }
+ end
+ should 'output its contents to the file' do
+ coderay(command)
+ target = File.read(target_file)
+ assert_equal source, target.scan(text).join
+ end
+ should 'output JSON' do
+ coderay(command)
+ target = File.read(target_file)
+ assert_not_equal source, target
+ assert_equal 6, target.scan(text).size
+ end
end
- def test_simple
- assert_nothing_raised { coderay('') }
+ context 'highlighting a file without explicit input type (source.py)' do
+ source_file = 'test/executable/source.py'
+ command = source_file
+
+ source = File.read source_file
+
+ pre = %r{<pre [^>]*>(.*?)</pre>}m
+ tag_class = /<span class="([^>"]*)"?[^>]*>/
+
+ should 'respect the file extension and highlight the input as Python' do
+ target = coderay(command)
+ assert_equal %w(kw cl kw), target[pre, 1].scan(tag_class).flatten
+ end
end
- VERSION_PATTERN = /CodeRay \d\.\d\.\d/
- def test_version
- assert_match(VERSION_PATTERN, coderay(''))
- # assert_match(VERSION_PATTERN, coderay('--version'))
- # assert_match(VERSION_PATTERN, coderay('-v'))
+ context 'highlighting a file with explicit input type (-ruby source.py)' do
+ source_file = 'test/executable/source.py'
+ command = "-ruby #{source_file}"
+
+ source = File.read source_file
+
+ pre = %r{<pre [^>]*>(.*?)</pre>}m
+ tag_class = /<span class="([^>"]*)"?[^>]*>/
+
+ should 'ignore the file extension and highlight the input as Ruby' do
+ target = coderay(command)
+ assert_equal %w(kw cl), target[pre, 1].scan(tag_class).flatten
+ end
end
- HELP_PATTERN = /Usage:/
- def test_help
- assert_match(HELP_PATTERN, coderay(''))
- # assert_match(HELP_PATTERN, coderay('--help'))
- # assert_match(HELP_PATTERN, coderay('-h'))
+ context 'highlighting a file with explicit input and output type (-ruby source.py -span)' do
+ source_file = 'test/executable/source.py'
+ command = "-ruby #{source_file} -span"
+
+ source = File.read source_file
+
+ span_tags = /<\/?span[^>]*>/
+
+ should 'just respect the output type and include span tags' do
+ target = coderay(command)
+ assert_equal source, target.chomp.gsub(span_tags, '')
+ end
end
-end \ No newline at end of file
+end