#!/usr/bin/env ruby require 'coderay' $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 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) stylesheet print the CSS stylesheet with the given name about: list [of] list all available plugins (or just the scanners|encoders) commands print this list help show some help version print CodeRay version COMMANDS 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_filetype, 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 raise signature end if input_file input_filetype ||= CodeRay::FileType.fetch input_file, :text, true end if output_file output_filetype ||= CodeRay::FileType[output_file] else output_filetype ||= :term end output_filetype = :page if output_filetype.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_filetype, output_filetype, :out => file) file.puts rescue CodeRay::PluginHost::PluginNotFound => boom 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 # ignore ensure file.close end end when 'list' arg = args.first && args.first.downcase if [nil, 's', 'sc', 'scanner', 'scanners'].include? arg puts 'input languages (Scanners):' scanners = CodeRay::Scanners.all_plugins.map do |plugin| aliases = (plugin.aliases - [nil]).map { |key| "-#{key}" }.sort_by { |key| key.size } " #{plugin.lang}: #{plugin.title}#{" (.#{plugin.file_extension}; #{aliases.join(', ')})" unless aliases.empty?}" end puts scanners.sort puts end if [nil, 'e', 'en', 'enc', 'encoder', 'encoders'].include? arg puts 'output formats (Encoders):' encoders = CodeRay::Encoders.all_plugins.map do |plugin| aliases = (plugin.aliases - [nil]).map { |key| "-#{key}" }.sort_by { |key| key.size } " #{plugin.plugin_id}: #{plugin.title}#{" (.#{plugin.file_extension}; #{aliases.join(', ')})" unless aliases.empty?}" end puts encoders.sort end when 'stylesheet' puts CodeRay::Encoders[:html]::CSS.new(args.first).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