216 lines
5.6 KiB
Ruby
Executable File
216 lines
5.6 KiB
Ruby
Executable File
#!/usr/bin/env ruby
|
|
require 'coderay'
|
|
|
|
$options, args = ARGV.partition { |arg| arg[/^-[hv]$|--\w+/] }
|
|
subcommand = args.first if /^\w/ === args.first
|
|
subcommand = nil if subcommand && File.exist?(subcommand)
|
|
args.delete subcommand
|
|
|
|
def option? *options
|
|
!($options & options).empty?
|
|
end
|
|
|
|
def tty?
|
|
$stdout.tty? || option?('--tty')
|
|
end
|
|
|
|
def version
|
|
puts <<-USAGE
|
|
CodeRay #{CodeRay::VERSION}
|
|
USAGE
|
|
end
|
|
|
|
def help
|
|
puts <<-HELP
|
|
This is CodeRay #{CodeRay::VERSION}, a syntax highlighting tool for selected languages.
|
|
|
|
usage:
|
|
coderay [-language] [input] [-format] [output]
|
|
|
|
defaults:
|
|
language detect from input file name or shebang; fall back to plain text
|
|
input STDIN
|
|
format detect from output file name or use terminal; fall back to HTML
|
|
output STDOUT
|
|
|
|
common:
|
|
coderay file.rb # highlight file to terminal
|
|
coderay file.rb > file.html # highlight file to HTML page
|
|
coderay file.rb -div > file.html # highlight file to HTML snippet
|
|
|
|
configure output:
|
|
coderay file.py output.json # output tokens as JSON
|
|
coderay file.py -loc # count lines of code in Python file
|
|
|
|
configure input:
|
|
coderay -python file # specify the input language
|
|
coderay -ruby # take input from STDIN
|
|
|
|
more:
|
|
coderay stylesheet [style] # print CSS stylesheet
|
|
HELP
|
|
end
|
|
|
|
def commands
|
|
puts <<-COMMANDS
|
|
general:
|
|
highlight code highlighting (default command, optional)
|
|
stylesheet print the CSS stylesheet with the given name (aliases: style, css)
|
|
|
|
about:
|
|
list [of] list all available plugins (or just the scanners|encoders|styles|filetypes)
|
|
commands print this list
|
|
help show some help
|
|
version print CodeRay version
|
|
COMMANDS
|
|
end
|
|
|
|
def print_list_of plugin_host
|
|
plugins = plugin_host.all_plugins.map do |plugin|
|
|
info = " #{plugin.plugin_id}: #{plugin.title}"
|
|
|
|
aliases = (plugin.aliases - [:default]).map { |key| "-#{key}" }.sort_by { |key| key.size }
|
|
if plugin.respond_to?(:file_extension) || !aliases.empty?
|
|
additional_info = []
|
|
additional_info << aliases.join(', ') unless aliases.empty?
|
|
info << " (#{additional_info.join('; ')})"
|
|
end
|
|
|
|
info << ' <-- default' if plugin.aliases.include? :default
|
|
|
|
info
|
|
end
|
|
puts plugins.sort
|
|
end
|
|
|
|
if option? '-v', '--version'
|
|
version
|
|
end
|
|
|
|
if option? '-h', '--help'
|
|
help
|
|
end
|
|
|
|
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 /^f-f?$/
|
|
input_file, output_format, output_file, = *names
|
|
when /^-ff?$/
|
|
input_lang, input_file, output_file, = *names
|
|
when /^-f-f?$/
|
|
input_lang, input_file, output_format, output_file, = *names
|
|
when /^--?f?$/
|
|
input_lang, output_format, output_file, = *names
|
|
else
|
|
$stdout = $stderr
|
|
help
|
|
puts
|
|
puts "Unknown parameter order: #{args.join ' '}, expected: [-language] [input] [-format] [output]"
|
|
exit 1
|
|
end
|
|
|
|
if input_file
|
|
input_lang ||= CodeRay::FileType.fetch input_file, :text, true
|
|
end
|
|
|
|
if output_file
|
|
output_format ||= CodeRay::FileType[output_file]
|
|
else
|
|
output_format ||= :terminal
|
|
end
|
|
|
|
output_format = :page if output_format.to_s == 'html'
|
|
|
|
if input_file
|
|
input = File.read input_file
|
|
else
|
|
input = $stdin.read
|
|
end
|
|
|
|
begin
|
|
file =
|
|
if output_file
|
|
File.open output_file, 'w'
|
|
else
|
|
$stdout.sync = true
|
|
$stdout
|
|
end
|
|
CodeRay.encode(input, input_lang, output_format, :out => file)
|
|
file.puts
|
|
rescue CodeRay::PluginHost::PluginNotFound => boom
|
|
$stdout = $stderr
|
|
if boom.message[/CodeRay::(\w+)s could not load plugin :?(.*?): /]
|
|
puts "I don't know the #$1 \"#$2\"."
|
|
else
|
|
puts boom.message
|
|
end
|
|
# puts "I don't know this plugin: #{boom.message[/Could not load plugin (.*?): /, 1]}."
|
|
rescue CodeRay::Scanners::Scanner::ScanError # FIXME: rescue Errno::EPIPE
|
|
# this is sometimes raised by pagers; ignore [TODO: wtf?]
|
|
ensure
|
|
file.close if output_file
|
|
end
|
|
end
|
|
when 'li', 'list'
|
|
arg = args.first && args.first.downcase
|
|
if [nil, 's', 'sc', 'scanner', 'scanners'].include? arg
|
|
puts 'input languages (Scanners):'
|
|
print_list_of CodeRay::Scanners
|
|
end
|
|
|
|
if [nil, 'e', 'en', 'enc', 'encoder', 'encoders'].include? arg
|
|
puts 'output formats (Encoders):'
|
|
print_list_of CodeRay::Encoders
|
|
end
|
|
|
|
if [nil, 'st', 'style', 'styles'].include? arg
|
|
puts 'CSS themes for HTML output (Styles):'
|
|
print_list_of CodeRay::Styles
|
|
end
|
|
|
|
if [nil, 'f', 'ft', 'file', 'filetype', 'filetypes'].include? arg
|
|
puts 'recognized file types:'
|
|
|
|
filetypes = Hash.new { |h, k| h[k] = [] }
|
|
CodeRay::FileType::TypeFromExt.inject filetypes do |types, (ext, type)|
|
|
types[type.to_s] << ".#{ext}"
|
|
types
|
|
end
|
|
CodeRay::FileType::TypeFromName.inject filetypes do |types, (name, type)|
|
|
types[type.to_s] << name
|
|
types
|
|
end
|
|
|
|
filetypes.sort.each do |type, exts|
|
|
puts " #{type}: #{exts.sort_by { |ext| ext.size }.join(', ')}"
|
|
end
|
|
end
|
|
when 'stylesheet', 'style', 'css'
|
|
puts CodeRay::Encoders[:html]::CSS.new(args.first || :default).stylesheet
|
|
when 'commands'
|
|
commands
|
|
when 'help'
|
|
help
|
|
else
|
|
$stdout = $stderr
|
|
help
|
|
puts
|
|
if subcommand[/\A\w+\z/]
|
|
puts "Unknown command: #{subcommand}"
|
|
else
|
|
puts "File not found: #{subcommand}"
|
|
end
|
|
exit 1
|
|
end
|