Created
July 29, 2014 11:37
-
-
Save tobalsan/451f380a0489220a523f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'posix-spawn' | |
require 'rbconfig' | |
## | |
# Wrapper for the Pygments command line tool, pygmentize. | |
# | |
# Pygments: http://pygments.org/ | |
# | |
# Assumes pygmentize is in the path. If not, set its location | |
# with Albino.bin = '/path/to/pygmentize' | |
# | |
# Use like so: | |
# | |
# @syntaxer = Albino.new('puts "Hello World"', :ruby) | |
# puts @syntaxer.colorize | |
# | |
# This'll print out an HTMLized, Ruby-highlighted version | |
# of '/some/file.rb'. | |
# | |
# To use another formatter, pass it as the third argument: | |
# | |
# @syntaxer = Albino.new('puts "Hello World"', :ruby, :bbcode) | |
# puts @syntaxer.colorize | |
# | |
# You can also use the #colorize class method: | |
# | |
# puts Albino.colorize('puts "Hello World"', :ruby) | |
# | |
# To format a file, pass a file stream: | |
# | |
# puts Albino.colorize(File.new('/some/file.rb'), :ruby) | |
# | |
# Another also: you get a #to_s, for somewhat nicer use in Rails views. | |
# | |
# ... helper file ... | |
# def highlight(text) | |
# Albino.new(text, :ruby) | |
# end | |
# | |
# ... view file ... | |
# <%= highlight text %> | |
# | |
# The default lexer is 'text'. You need to specify a lexer yourself; | |
# because we are using STDIN there is no auto-detect. | |
# | |
# To see all lexers and formatters available, run `pygmentize -L`. | |
# | |
# Chris Wanstrath // chris@ozmm.org | |
# GitHub // http://github.com | |
# | |
class Albino | |
class ShellArgumentError < ArgumentError; end | |
include POSIX::Spawn | |
VERSION = '1.3.3' | |
class << self | |
attr_accessor :bin, :timeout_threshold | |
attr_reader :default_encoding | |
def default_encoding=(encoding) | |
# make sure the encoding is valid | |
Encoding.find(encoding) if defined?(Encoding) | |
@default_encoding = encoding | |
end | |
end | |
self.timeout_threshold = 10 | |
self.default_encoding = 'utf-8' | |
self.bin = 'pygmentize' | |
def self.colorize(*args) | |
new(*args).colorize | |
end | |
def initialize(target, lexer = :text, format = :html, encoding = self.class.default_encoding) | |
@target = target | |
@options = { :l => lexer, :f => format, :O => "encoding=#{encoding}" } | |
@encoding = encoding | |
end | |
def execute(options = {}) | |
proc_options = {} | |
proc_options[:timeout] = options.delete(:timeout) || self.class.timeout_threshold | |
command = convert_options(options) | |
command.unshift(bin) | |
if RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/ | |
output = '' | |
IO.popen(command, mode='r+') do |p| | |
p.write @target | |
p.close_write | |
output = p.read.strip | |
end | |
output | |
else | |
Child.new(*(command + [proc_options.merge(:input => write_target)])) | |
end | |
end | |
def colorize(options = {}) | |
out = RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/ ? execute(options) : execute(options).out | |
# markdown requires block elements on their own line | |
out.sub!(%r{</pre></div>\Z}, "</pre>\n</div>") | |
# covert output to the encoding we told pygmentize to use | |
out.force_encoding(@encoding) if out.respond_to?(:force_encoding) | |
out | |
end | |
alias_method :to_s, :colorize | |
def convert_options(options = {}) | |
@options.merge(options).inject([]) do |memo, (flag, value)| | |
validate_shell_args(flag.to_s, value.to_s) | |
memo << "-#{flag}" << value.to_s | |
end | |
end | |
def write_target | |
if @target.respond_to?(:read) | |
out = @target.read | |
@target.close | |
out | |
else | |
@target.to_s | |
end | |
end | |
def validate_shell_args(flag, value) | |
if flag !~ /^[a-z]+$/i | |
raise ShellArgumentError, "Flag is invalid: #{flag.inspect}" | |
end | |
if value !~ /^[a-z0-9\-\_\+\=\#\,\s]+$/i | |
raise ShellArgumentError, "Flag value is invalid: -#{flag} #{value.inspect}" | |
end | |
end | |
def bin | |
self.class.bin | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment