├── .gitignore ├── Gemfile ├── README.md ├── LICENSE ├── vendor └── multipygmentize ├── test ├── multi_albino_test.rb └── albino_test.rb ├── albino.gemspec ├── lib ├── albino │ └── multi.rb └── albino.rb └── Rakefile /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | Gemfile.lock 3 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source :rubygems 2 | gemspec 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **NOTE: This repository is no longer supported or updated by GitHub. If you wish to continue to develop this code yourself, we recommend you fork it.** 2 | 3 | # Albino: a ruby wrapper for pygmentize 4 | 5 | This project is an extraction from GitHub. 6 | 7 | For this and other extractions, see [http://github.com/github]() 8 | 9 | ## Installation 10 | 11 | sudo easy_install pygments 12 | gem install albino 13 | 14 | ## Usage 15 | 16 | ### Simple 17 | 18 | require 'albino' 19 | puts Albino.colorize('puts "Hello World"', :ruby) 20 | 21 | ### Advanced 22 | 23 | require 'albino' 24 | @syntaxer = Albino.new(File.new('albino.rb'), :ruby, :bbcode) 25 | puts @syntaxer.colorize 26 | 27 | ### Multi 28 | 29 | require 'albino/multi' 30 | ruby, python = Albino::Multi.colorize([ [:ruby,'1+2'], [:python,'1-2'] ]) 31 | 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) Chris Wanstrath 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /vendor/multipygmentize: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This script allows you to highlight multiple chunks of code with a single 4 | # invocation. Expected input is on STDIN and takes the form of: 5 | # 6 | # \000\000\000... 7 | # 8 | # where is the shortname of a Pygments lexer and is the source 9 | # code to be highlighted. Each lexer and code pair is separated with a NULL 10 | # byte and pairs of lexer/code are also separated with NULL bytes. 11 | # 12 | # Output is a list of highlighted code blocks separated by NULL bytes in the 13 | # same order in which they were received. 14 | 15 | import sys, os, codecs 16 | 17 | sys.stdin = codecs.getreader('UTF-8')(sys.stdin) 18 | sys.stdout = codecs.getwriter('UTF-8')(sys.stdout) 19 | 20 | vpath = os.path.realpath(__file__).split("/") 21 | vpath.pop() 22 | vpath.pop() 23 | vpath = "/".join(vpath) 24 | 25 | from pygments import highlight 26 | from pygments.lexers import get_lexer_by_name 27 | from pygments.formatters import HtmlFormatter 28 | 29 | parts = sys.stdin.read().split("\000") 30 | newparts = [] 31 | 32 | for i in range(len(parts) / 2): 33 | lang = parts[i * 2] 34 | code = parts[i * 2 + 1] 35 | try: 36 | lexer = get_lexer_by_name(lang) 37 | except: 38 | lexer = get_lexer_by_name('text') 39 | newparts.append([code, lexer]) 40 | 41 | def hl(spec): 42 | code = spec[0] 43 | lexer = spec[1] 44 | try: 45 | return highlight(code, lexer, HtmlFormatter()) 46 | except: 47 | lexer = get_lexer_by_name('text') 48 | return highlight(code, lexer, HtmlFormatter()) 49 | 50 | for spec in newparts: 51 | sys.stdout.write(hl(spec)) 52 | sys.stdout.write("\000") 53 | 54 | -------------------------------------------------------------------------------- /test/multi_albino_test.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require 'rubygems' 4 | require 'albino/multi' 5 | require 'test/unit' 6 | require 'tempfile' 7 | require 'mocha' 8 | 9 | class MultiTest < Test::Unit::TestCase 10 | def setup 11 | @syntaxer = Albino::Multi.new(File.new(__FILE__), :ruby) 12 | end 13 | 14 | def test_defaults_to_text 15 | syntaxer = Albino::Multi.new('abc') 16 | regex = /span/ 17 | assert_no_match regex, syntaxer.colorize 18 | end 19 | 20 | def test_markdown_compatible 21 | code = Albino::Multi.colorize('1+2', :ruby) 22 | assert_no_match %r{\Z}, code 23 | end 24 | 25 | def test_forces_utf8 26 | code = Albino::Multi.colorize('1+2', :ruby) 27 | if code.respond_to?(:encoding) 28 | assert_equal 'UTF-8', code.encoding.to_s 29 | end 30 | end 31 | 32 | def test_accepts_utf8 33 | code = Albino::Multi.colorize('éøü', :html) 34 | assert_includes code, "
éøü\n
" 35 | end 36 | 37 | def test_works_with_strings 38 | syntaxer = Albino::Multi.new("class New\nend", :ruby) 39 | assert_match %r(highlight), code=syntaxer.colorize 40 | assert_match %(New\n), code 41 | end 42 | 43 | def test_works_with_multiple_code_fragments 44 | syntaxer = Albino::Multi.new [ 45 | ['ruby', "class New\nend"], 46 | ['python', "class New:\n pass"]] 47 | codes = syntaxer.colorize 48 | assert_equal 2, codes.size 49 | assert_match %r(highlight), codes[0] 50 | assert_match %r(highlight), codes[1] 51 | assert_match %(New\n), codes[0] 52 | assert_match %(:), codes[1] 53 | end 54 | 55 | def test_works_with_files 56 | contents = "class New\nend" 57 | syntaxer = Albino::Multi.new(contents, :ruby) 58 | file_output = syntaxer.colorize 59 | 60 | Tempfile.open 'albino-test' do |tmp| 61 | tmp << contents 62 | tmp.flush 63 | syntaxer = Albino::Multi.new(File.new(tmp.path), :ruby) 64 | assert_equal file_output, syntaxer.colorize 65 | end 66 | end 67 | 68 | def test_aliases_to_s 69 | syntaxer = Albino::Multi.new(File.new(__FILE__), :ruby) 70 | assert_equal @syntaxer.colorize, syntaxer.to_s 71 | end 72 | 73 | def test_class_method_colorize 74 | assert_equal @syntaxer.colorize, Albino::Multi.colorize(File.new(__FILE__), :ruby) 75 | end 76 | end 77 | 78 | -------------------------------------------------------------------------------- /albino.gemspec: -------------------------------------------------------------------------------- 1 | ## This is the rakegem gemspec template. Make sure you read and understand 2 | ## all of the comments. Some sections require modification, and others can 3 | ## be deleted if you don't need them. Once you understand the contents of 4 | ## this file, feel free to delete any comments that begin with two hash marks. 5 | ## You can find comprehensive Gem::Specification documentation, at 6 | ## http://docs.rubygems.org/read/chapter/20 7 | Gem::Specification.new do |s| 8 | s.specification_version = 2 if s.respond_to? :specification_version= 9 | s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= 10 | s.rubygems_version = '1.3.5' 11 | 12 | ## Leave these as is they will be modified for you by the rake gemspec task. 13 | ## If your rubyforge_project name is different, then edit it and comment out 14 | ## the sub! line in the Rakefile 15 | s.name = 'albino' 16 | s.version = '1.3.3' 17 | s.date = '2011-04-19' 18 | s.rubyforge_project = 'albino' 19 | 20 | ## Make sure your summary is short. The description may be as long 21 | ## as you like. 22 | s.summary = "Ruby wrapper for pygmentize." 23 | s.description = "Ruby wrapper for pygmentize." 24 | 25 | ## List the primary authors. If there are a bunch of authors, it's probably 26 | ## better to set the email to an email list or something. If you don't have 27 | ## a custom homepage, consider using your GitHub URL or the like. 28 | s.authors = ["Chris Wanstrath"] 29 | s.email = 'chris@wanstrath.com' 30 | s.homepage = 'http://github.com/github/albino' 31 | 32 | ## This gets added to the $LOAD_PATH so that 'lib/NAME.rb' can be required as 33 | ## require 'NAME.rb' or'/lib/NAME/file.rb' can be as require 'NAME/file.rb' 34 | s.require_paths = %w[lib] 35 | 36 | s.add_dependency('posix-spawn', '>= 0.3.6') 37 | s.add_development_dependency('mocha') 38 | 39 | ## Leave this section as-is. It will be automatically generated from the 40 | ## contents of your Git repository via the gemspec task. DO NOT REMOVE 41 | ## THE MANIFEST COMMENTS, they are used as delimiters by the task. 42 | # = MANIFEST = 43 | s.files = %w[ 44 | Gemfile 45 | LICENSE 46 | README.md 47 | Rakefile 48 | albino.gemspec 49 | lib/albino.rb 50 | lib/albino/multi.rb 51 | test/albino_test.rb 52 | test/multi_albino_test.rb 53 | vendor/multipygmentize 54 | ] 55 | # = MANIFEST = 56 | 57 | ## Test files will be grabbed from the file list. Make sure the path glob 58 | ## matches what you actually use. 59 | s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ } 60 | end 61 | -------------------------------------------------------------------------------- /test/albino_test.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require 'rubygems' 4 | require 'albino' 5 | require 'test/unit' 6 | require 'tempfile' 7 | require 'mocha' 8 | 9 | class AlbinoTest < Test::Unit::TestCase 10 | def setup 11 | @syntaxer = Albino.new(File.new(__FILE__), :ruby) 12 | end 13 | 14 | def test_defaults_to_text 15 | syntaxer = Albino.new('abc') 16 | regex = /span/ 17 | assert_no_match regex, syntaxer.colorize 18 | end 19 | 20 | def test_accepts_options 21 | assert_match /span/, @syntaxer.colorize 22 | end 23 | 24 | def test_accepts_non_alpha_options 25 | assert_equal '', @syntaxer.colorize(:f => 'html+c#-dump') 26 | end 27 | 28 | def test_markdown_compatible 29 | code = Albino.colorize('1+2', :ruby) 30 | assert_no_match %r{\Z}, code 31 | end 32 | 33 | def test_works_with_strings 34 | syntaxer = Albino.new("class New\nend", :ruby) 35 | assert_match %r(highlight), code=syntaxer.colorize 36 | assert_match %(New\n), code 37 | end 38 | 39 | def test_works_with_utf8_strings 40 | code = Albino.new("# é", :bash).colorize 41 | assert_match %r(highlight), code 42 | assert_match %(# é), code 43 | end 44 | 45 | def test_works_with_files 46 | contents = "class New\nend" 47 | syntaxer = Albino.new(contents, :ruby) 48 | file_output = syntaxer.colorize 49 | 50 | Tempfile.open 'albino-test' do |tmp| 51 | tmp << contents 52 | tmp.flush 53 | syntaxer = Albino.new(File.new(tmp.path), :ruby) 54 | assert_equal file_output, syntaxer.colorize 55 | end 56 | end 57 | 58 | def test_default_encoding 59 | assert_equal Albino.default_encoding, 'utf-8' 60 | end 61 | 62 | def test_change_encoding 63 | before = Albino.default_encoding 64 | 65 | assert_equal Albino.default_encoding, 'utf-8' 66 | Albino.default_encoding = 'ascii' 67 | assert_equal Albino.default_encoding, 'ascii' 68 | ensure 69 | Albino.default_encoding = before 70 | end 71 | 72 | def test_invalid_encoding 73 | before = Albino.default_encoding 74 | Albino.default_encoding = 'binary' 75 | 76 | assert_equal Albino.colorize('class Baño; end', :ruby), '' 77 | ensure 78 | Albino.default_encoding = before 79 | end 80 | 81 | def test_custom_encoding 82 | code = Albino.new('1+2', :ruby, :html, 'ascii').colorize 83 | if code.respond_to?(:encoding) 84 | assert_equal code.encoding.to_s, 'US-ASCII' 85 | end 86 | end 87 | 88 | def test_aliases_to_s 89 | syntaxer = Albino.new(File.new(__FILE__), :ruby) 90 | assert_equal @syntaxer.colorize, syntaxer.to_s 91 | end 92 | 93 | def test_class_method_colorize 94 | assert_equal @syntaxer.colorize, Albino.colorize(File.new(__FILE__), :ruby) 95 | end 96 | 97 | def test_escaped_shell_args 98 | assert_raises Albino::ShellArgumentError do 99 | @syntaxer.convert_options(:l => "'abc;'") 100 | end 101 | end 102 | end 103 | -------------------------------------------------------------------------------- /lib/albino/multi.rb: -------------------------------------------------------------------------------- 1 | require 'albino' 2 | 3 | class Albino 4 | # Wrapper for a custom multipygmentize script. Passes multiple code 5 | # fragments in STDIN to Python. This assumes both Python and pygments are 6 | # installed. 7 | # 8 | # Use like so: 9 | # 10 | # @syntaxer = Albino::Multi.new([ [:ruby, File.open("/some/file.rb")] ]) 11 | # puts @syntaxer.colorize 12 | # 13 | # It takes an Array of two-element arrays [lexer, code]. 14 | # 15 | # You can also use Albino::Multi as a drop-in replacement. It currently has 16 | # a few limitations however: 17 | # 18 | # * Only the HTML output format is supported. 19 | # * UTF-8 encoding is forced. 20 | # 21 | # The default lexer is 'text'. You need to specify a lexer yourself; 22 | # because we are using STDIN there is no auto-detect. 23 | # 24 | # To see all lexers and formatters available, run `pygmentize -L`. 25 | class Multi 26 | include POSIX::Spawn 27 | 28 | class << self 29 | attr_accessor :bin, :timeout_threshold 30 | end 31 | 32 | self.timeout_threshold = 10 33 | self.bin = File.join(File.dirname(__FILE__), *%w(.. .. vendor multipygmentize)) 34 | 35 | # Initializes a new Albino::Multi and runs #colorize. 36 | def self.colorize(*args) 37 | new(*args).colorize 38 | end 39 | 40 | # This method accepts two forms of input: 41 | # 42 | # DEFAULT 43 | # 44 | # target - The Array of two-element [lexer, code] Arrays: 45 | # lexer - The String lexer for the upcoming block of code. 46 | # code - The String block of code to highlight. 47 | # 48 | # LEGACY 49 | # 50 | # target - The String block of code to highlight. 51 | # lexer - The String lexer for the block of code. 52 | # 53 | # Albino#initialize also takes format and encoding which are ignored. 54 | def initialize(target, lexer = :text, *args) 55 | @spec = case target 56 | when Array 57 | @multi = true 58 | target 59 | else 60 | [[lexer, target]] 61 | end 62 | end 63 | 64 | # Colorizes the code blocks. 65 | # 66 | # options - Specify options for the child process: 67 | # timeout - A Fixnum timeout for the child process. 68 | # 69 | # Returns an Array of HTML highlighted code block Strings if an array of 70 | # targets are given to #initialize, or just a single HTML highlighted code 71 | # block String. 72 | def colorize(options = {}) 73 | options[:timeout] ||= self.class.timeout_threshold 74 | options[:input] = @spec.inject([]) do |memo, (lexer, code)| 75 | memo << lexer << SEPARATOR 76 | 77 | if code.respond_to?(:read) 78 | out = code.read 79 | code.close 80 | code = out 81 | end 82 | 83 | memo << code << SEPARATOR 84 | end.join("") 85 | 86 | child = Child.new(self.class.bin, options) 87 | pieces = child.out.split(SEPARATOR).each do |code| 88 | # markdown requires block elements on their own line 89 | code.sub!(%r{\Z}, "\n") 90 | 91 | # albino::multi assumes utf8 encoding 92 | code.force_encoding('UTF-8') if code.respond_to?(:force_encoding) 93 | end 94 | @multi ? pieces : pieces.first 95 | end 96 | 97 | alias_method :to_s, :colorize 98 | 99 | SEPARATOR = "\000".freeze 100 | end 101 | end 102 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'rake' 3 | require 'date' 4 | 5 | ############################################################################# 6 | # 7 | # Helper functions 8 | # 9 | ############################################################################# 10 | 11 | def name 12 | @name ||= Dir['*.gemspec'].first.split('.').first 13 | end 14 | 15 | def version 16 | line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/] 17 | line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1] 18 | end 19 | 20 | def date 21 | Date.today.to_s 22 | end 23 | 24 | def rubyforge_project 25 | name 26 | end 27 | 28 | def gemspec_file 29 | "#{name}.gemspec" 30 | end 31 | 32 | def gem_file 33 | "#{name}-#{version}.gem" 34 | end 35 | 36 | def replace_header(head, header_name) 37 | head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"} 38 | end 39 | 40 | ############################################################################# 41 | # 42 | # Standard tasks 43 | # 44 | ############################################################################# 45 | 46 | task :default => :test 47 | 48 | require 'rake/testtask' 49 | Rake::TestTask.new(:test) do |test| 50 | test.libs << 'lib' << 'test' 51 | test.pattern = 'test/**/*_test.rb' 52 | test.verbose = true 53 | end 54 | 55 | desc "Open an irb session preloaded with this library" 56 | task :console do 57 | sh "irb -rubygems -r ./lib/#{name}.rb" 58 | end 59 | 60 | ############################################################################# 61 | # 62 | # Custom tasks (add your own tasks here) 63 | # 64 | ############################################################################# 65 | 66 | 67 | 68 | ############################################################################# 69 | # 70 | # Packaging tasks 71 | # 72 | ############################################################################# 73 | 74 | task :release => :build do 75 | unless `git branch` =~ /^\* master$/ 76 | puts "You must be on the master branch to release!" 77 | exit! 78 | end 79 | sh "git commit --allow-empty -a -m 'Release #{version}'" 80 | sh "git tag v#{version}" 81 | sh "git push origin master" 82 | sh "git push --tags" 83 | sh "gem push pkg/#{name}-#{version}.gem" 84 | end 85 | 86 | task :build => :gemspec do 87 | sh "mkdir -p pkg" 88 | sh "gem build #{gemspec_file}" 89 | sh "mv #{gem_file} pkg" 90 | end 91 | 92 | task :gemspec => :validate do 93 | # read spec file and split out manifest section 94 | spec = File.read(gemspec_file) 95 | head, manifest, tail = spec.split(" # = MANIFEST =\n") 96 | 97 | # replace name version and date 98 | replace_header(head, :name) 99 | replace_header(head, :version) 100 | replace_header(head, :date) 101 | #comment this out if your rubyforge_project has a different name 102 | replace_header(head, :rubyforge_project) 103 | 104 | # determine file list from git ls-files 105 | files = `git ls-files`. 106 | split("\n"). 107 | sort. 108 | reject { |file| file =~ /^\./ }. 109 | reject { |file| file =~ /^(rdoc|pkg)/ }. 110 | map { |file| " #{file}" }. 111 | join("\n") 112 | 113 | # piece file back together and write 114 | manifest = " s.files = %w[\n#{files}\n ]\n" 115 | spec = [head, manifest, tail].join(" # = MANIFEST =\n") 116 | File.open(gemspec_file, 'w') { |io| io.write(spec) } 117 | puts "Updated #{gemspec_file}" 118 | end 119 | 120 | task :validate do 121 | libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"] 122 | unless libfiles.empty? 123 | puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir." 124 | exit! 125 | end 126 | unless Dir['VERSION*'].empty? 127 | puts "A `VERSION` file at root level violates Gem best practices." 128 | exit! 129 | end 130 | end -------------------------------------------------------------------------------- /lib/albino.rb: -------------------------------------------------------------------------------- 1 | require 'posix-spawn' 2 | 3 | ## 4 | # Wrapper for the Pygments command line tool, pygmentize. 5 | # 6 | # Pygments: http://pygments.org/ 7 | # 8 | # Assumes pygmentize is in the path. If not, set its location 9 | # with Albino.bin = '/path/to/pygmentize' 10 | # 11 | # Use like so: 12 | # 13 | # @syntaxer = Albino.new('puts "Hello World"', :ruby) 14 | # puts @syntaxer.colorize 15 | # 16 | # This'll print out an HTMLized, Ruby-highlighted version 17 | # of '/some/file.rb'. 18 | # 19 | # To use another formatter, pass it as the third argument: 20 | # 21 | # @syntaxer = Albino.new('puts "Hello World"', :ruby, :bbcode) 22 | # puts @syntaxer.colorize 23 | # 24 | # You can also use the #colorize class method: 25 | # 26 | # puts Albino.colorize('puts "Hello World"', :ruby) 27 | # 28 | # To format a file, pass a file stream: 29 | # 30 | # puts Albino.colorize(File.new('/some/file.rb'), :ruby) 31 | # 32 | # Another also: you get a #to_s, for somewhat nicer use in Rails views. 33 | # 34 | # ... helper file ... 35 | # def highlight(text) 36 | # Albino.new(text, :ruby) 37 | # end 38 | # 39 | # ... view file ... 40 | # <%= highlight text %> 41 | # 42 | # The default lexer is 'text'. You need to specify a lexer yourself; 43 | # because we are using STDIN there is no auto-detect. 44 | # 45 | # To see all lexers and formatters available, run `pygmentize -L`. 46 | # 47 | # Chris Wanstrath // chris@ozmm.org 48 | # GitHub // http://github.com 49 | # 50 | class Albino 51 | class ShellArgumentError < ArgumentError; end 52 | include POSIX::Spawn 53 | 54 | VERSION = '1.3.3' 55 | 56 | class << self 57 | attr_accessor :bin, :timeout_threshold 58 | attr_reader :default_encoding 59 | 60 | def default_encoding=(encoding) 61 | # make sure the encoding is valid 62 | Encoding.find(encoding) if defined?(Encoding) 63 | 64 | @default_encoding = encoding 65 | end 66 | end 67 | 68 | self.timeout_threshold = 10 69 | self.default_encoding = 'utf-8' 70 | self.bin = 'pygmentize' 71 | 72 | def self.colorize(*args) 73 | new(*args).colorize 74 | end 75 | 76 | def initialize(target, lexer = :text, format = :html, encoding = self.class.default_encoding) 77 | @target = target 78 | @options = { :l => lexer, :f => format, :O => "encoding=#{encoding}" } 79 | @encoding = encoding 80 | end 81 | 82 | def execute(options = {}) 83 | proc_options = {} 84 | proc_options[:timeout] = options.delete(:timeout) || self.class.timeout_threshold 85 | command = convert_options(options) 86 | command.unshift(bin) 87 | Child.new(*(command + [proc_options.merge(:input => write_target)])) 88 | end 89 | 90 | def colorize(options = {}) 91 | out = execute(options).out 92 | 93 | # markdown requires block elements on their own line 94 | out.sub!(%r{\Z}, "\n") 95 | 96 | # covert output to the encoding we told pygmentize to use 97 | out.force_encoding(@encoding) if out.respond_to?(:force_encoding) 98 | 99 | out 100 | end 101 | alias_method :to_s, :colorize 102 | 103 | def convert_options(options = {}) 104 | @options.merge(options).inject([]) do |memo, (flag, value)| 105 | validate_shell_args(flag.to_s, value.to_s) 106 | memo << "-#{flag}" << value.to_s 107 | end 108 | end 109 | 110 | def write_target 111 | if @target.respond_to?(:read) 112 | out = @target.read 113 | @target.close 114 | out 115 | else 116 | @target.to_s 117 | end 118 | end 119 | 120 | def validate_shell_args(flag, value) 121 | if flag !~ /^[a-z]+$/i 122 | raise ShellArgumentError, "Flag is invalid: #{flag.inspect}" 123 | end 124 | if value !~ /^[a-z0-9\-\_\+\=\#\,\s]+$/i 125 | raise ShellArgumentError, "Flag value is invalid: -#{flag} #{value.inspect}" 126 | end 127 | end 128 | 129 | def bin 130 | self.class.bin 131 | end 132 | end 133 | --------------------------------------------------------------------------------