Chris@909
|
1 #!/usr/bin/env ruby
|
Chris@909
|
2 require 'coderay'
|
Chris@909
|
3
|
Chris@909
|
4 $options, args = ARGV.partition { |arg| arg[/^-[hv]$|--\w+/] }
|
Chris@909
|
5 subcommand = args.first if /^\w/ === args.first
|
Chris@909
|
6 subcommand = nil if subcommand && File.exist?(subcommand)
|
Chris@909
|
7 args.delete subcommand
|
Chris@909
|
8
|
Chris@909
|
9 def option? *options
|
Chris@909
|
10 !($options & options).empty?
|
Chris@909
|
11 end
|
Chris@909
|
12
|
Chris@909
|
13 def tty?
|
Chris@909
|
14 $stdout.tty? || option?('--tty')
|
Chris@909
|
15 end
|
Chris@909
|
16
|
Chris@909
|
17 def version
|
Chris@909
|
18 puts <<-USAGE
|
Chris@909
|
19 CodeRay #{CodeRay::VERSION}
|
Chris@909
|
20 USAGE
|
Chris@909
|
21 end
|
Chris@909
|
22
|
Chris@909
|
23 def help
|
Chris@909
|
24 puts <<-HELP
|
Chris@909
|
25 This is CodeRay #{CodeRay::VERSION}, a syntax highlighting tool for selected languages.
|
Chris@909
|
26
|
Chris@909
|
27 usage:
|
Chris@909
|
28 coderay [-language] [input] [-format] [output]
|
Chris@909
|
29
|
Chris@909
|
30 defaults:
|
Chris@909
|
31 language detect from input file name or shebang; fall back to plain text
|
Chris@909
|
32 input STDIN
|
Chris@909
|
33 format detect from output file name or use terminal; fall back to HTML
|
Chris@909
|
34 output STDOUT
|
Chris@909
|
35
|
Chris@909
|
36 common:
|
Chris@909
|
37 coderay file.rb # highlight file to terminal
|
Chris@909
|
38 coderay file.rb > file.html # highlight file to HTML page
|
Chris@909
|
39 coderay file.rb -div > file.html # highlight file to HTML snippet
|
Chris@909
|
40
|
Chris@909
|
41 configure output:
|
Chris@909
|
42 coderay file.py output.json # output tokens as JSON
|
Chris@909
|
43 coderay file.py -loc # count lines of code in Python file
|
Chris@909
|
44
|
Chris@909
|
45 configure input:
|
Chris@909
|
46 coderay -python file # specify the input language
|
Chris@909
|
47 coderay -ruby # take input from STDIN
|
Chris@909
|
48
|
Chris@909
|
49 more:
|
Chris@909
|
50 coderay stylesheet [style] # print CSS stylesheet
|
Chris@909
|
51 HELP
|
Chris@909
|
52 end
|
Chris@909
|
53
|
Chris@909
|
54 def commands
|
Chris@909
|
55 puts <<-COMMANDS
|
Chris@909
|
56 general:
|
Chris@909
|
57 highlight code highlighting (default command, optional)
|
Chris@909
|
58 stylesheet print the CSS stylesheet with the given name (aliases: style, css)
|
Chris@909
|
59
|
Chris@909
|
60 about:
|
Chris@909
|
61 list [of] list all available plugins (or just the scanners|encoders|styles|filetypes)
|
Chris@909
|
62 commands print this list
|
Chris@909
|
63 help show some help
|
Chris@909
|
64 version print CodeRay version
|
Chris@909
|
65 COMMANDS
|
Chris@909
|
66 end
|
Chris@909
|
67
|
Chris@909
|
68 def print_list_of plugin_host
|
Chris@909
|
69 plugins = plugin_host.all_plugins.map do |plugin|
|
Chris@909
|
70 info = " #{plugin.plugin_id}: #{plugin.title}"
|
Chris@909
|
71
|
Chris@909
|
72 aliases = (plugin.aliases - [:default]).map { |key| "-#{key}" }.sort_by { |key| key.size }
|
Chris@909
|
73 if plugin.respond_to?(:file_extension) || !aliases.empty?
|
Chris@909
|
74 additional_info = []
|
Chris@909
|
75 additional_info << aliases.join(', ') unless aliases.empty?
|
Chris@909
|
76 info << " (#{additional_info.join('; ')})"
|
Chris@909
|
77 end
|
Chris@909
|
78
|
Chris@909
|
79 info << ' <-- default' if plugin.aliases.include? :default
|
Chris@909
|
80
|
Chris@909
|
81 info
|
Chris@909
|
82 end
|
Chris@909
|
83 puts plugins.sort
|
Chris@909
|
84 end
|
Chris@909
|
85
|
Chris@909
|
86 if option? '-v', '--version'
|
Chris@909
|
87 version
|
Chris@909
|
88 end
|
Chris@909
|
89
|
Chris@909
|
90 if option? '-h', '--help'
|
Chris@909
|
91 help
|
Chris@909
|
92 end
|
Chris@909
|
93
|
Chris@909
|
94 case subcommand
|
Chris@909
|
95 when 'highlight', nil
|
Chris@909
|
96 if ARGV.empty?
|
Chris@909
|
97 version
|
Chris@909
|
98 help
|
Chris@909
|
99 else
|
Chris@909
|
100 signature = args.map { |arg| arg[/^-/] ? '-' : 'f' }.join
|
Chris@909
|
101 names = args.map { |arg| arg.sub(/^-/, '') }
|
Chris@909
|
102 case signature
|
Chris@909
|
103 when /^$/
|
Chris@909
|
104 exit
|
Chris@909
|
105 when /^ff?$/
|
Chris@909
|
106 input_file, output_file, = *names
|
Chris@909
|
107 when /^f-f?$/
|
Chris@909
|
108 input_file, output_format, output_file, = *names
|
Chris@909
|
109 when /^-ff?$/
|
Chris@909
|
110 input_lang, input_file, output_file, = *names
|
Chris@909
|
111 when /^-f-f?$/
|
Chris@909
|
112 input_lang, input_file, output_format, output_file, = *names
|
Chris@909
|
113 when /^--?f?$/
|
Chris@909
|
114 input_lang, output_format, output_file, = *names
|
Chris@909
|
115 else
|
Chris@909
|
116 $stdout = $stderr
|
Chris@909
|
117 help
|
Chris@909
|
118 puts
|
Chris@909
|
119 puts "Unknown parameter order: #{args.join ' '}, expected: [-language] [input] [-format] [output]"
|
Chris@909
|
120 exit 1
|
Chris@909
|
121 end
|
Chris@909
|
122
|
Chris@909
|
123 if input_file
|
Chris@909
|
124 input_lang ||= CodeRay::FileType.fetch input_file, :text, true
|
Chris@909
|
125 end
|
Chris@909
|
126
|
Chris@909
|
127 if output_file
|
Chris@909
|
128 output_format ||= CodeRay::FileType[output_file]
|
Chris@909
|
129 else
|
Chris@909
|
130 output_format ||= :terminal
|
Chris@909
|
131 end
|
Chris@909
|
132
|
Chris@909
|
133 output_format = :page if output_format.to_s == 'html'
|
Chris@909
|
134
|
Chris@909
|
135 if input_file
|
Chris@909
|
136 input = File.read input_file
|
Chris@909
|
137 else
|
Chris@909
|
138 input = $stdin.read
|
Chris@909
|
139 end
|
Chris@909
|
140
|
Chris@909
|
141 begin
|
Chris@909
|
142 file =
|
Chris@909
|
143 if output_file
|
Chris@909
|
144 File.open output_file, 'w'
|
Chris@909
|
145 else
|
Chris@909
|
146 $stdout.sync = true
|
Chris@909
|
147 $stdout
|
Chris@909
|
148 end
|
Chris@909
|
149 CodeRay.encode(input, input_lang, output_format, :out => file)
|
Chris@909
|
150 file.puts
|
Chris@909
|
151 rescue CodeRay::PluginHost::PluginNotFound => boom
|
Chris@909
|
152 $stdout = $stderr
|
Chris@909
|
153 if boom.message[/CodeRay::(\w+)s could not load plugin :?(.*?): /]
|
Chris@909
|
154 puts "I don't know the #$1 \"#$2\"."
|
Chris@909
|
155 else
|
Chris@909
|
156 puts boom.message
|
Chris@909
|
157 end
|
Chris@909
|
158 # puts "I don't know this plugin: #{boom.message[/Could not load plugin (.*?): /, 1]}."
|
Chris@909
|
159 rescue CodeRay::Scanners::Scanner::ScanError # FIXME: rescue Errno::EPIPE
|
Chris@909
|
160 # this is sometimes raised by pagers; ignore [TODO: wtf?]
|
Chris@909
|
161 ensure
|
Chris@909
|
162 file.close if output_file
|
Chris@909
|
163 end
|
Chris@909
|
164 end
|
Chris@909
|
165 when 'li', 'list'
|
Chris@909
|
166 arg = args.first && args.first.downcase
|
Chris@909
|
167 if [nil, 's', 'sc', 'scanner', 'scanners'].include? arg
|
Chris@909
|
168 puts 'input languages (Scanners):'
|
Chris@909
|
169 print_list_of CodeRay::Scanners
|
Chris@909
|
170 end
|
Chris@909
|
171
|
Chris@909
|
172 if [nil, 'e', 'en', 'enc', 'encoder', 'encoders'].include? arg
|
Chris@909
|
173 puts 'output formats (Encoders):'
|
Chris@909
|
174 print_list_of CodeRay::Encoders
|
Chris@909
|
175 end
|
Chris@909
|
176
|
Chris@909
|
177 if [nil, 'st', 'style', 'styles'].include? arg
|
Chris@909
|
178 puts 'CSS themes for HTML output (Styles):'
|
Chris@909
|
179 print_list_of CodeRay::Styles
|
Chris@909
|
180 end
|
Chris@909
|
181
|
Chris@909
|
182 if [nil, 'f', 'ft', 'file', 'filetype', 'filetypes'].include? arg
|
Chris@909
|
183 puts 'recognized file types:'
|
Chris@909
|
184
|
Chris@909
|
185 filetypes = Hash.new { |h, k| h[k] = [] }
|
Chris@909
|
186 CodeRay::FileType::TypeFromExt.inject filetypes do |types, (ext, type)|
|
Chris@909
|
187 types[type.to_s] << ".#{ext}"
|
Chris@909
|
188 types
|
Chris@909
|
189 end
|
Chris@909
|
190 CodeRay::FileType::TypeFromName.inject filetypes do |types, (name, type)|
|
Chris@909
|
191 types[type.to_s] << name
|
Chris@909
|
192 types
|
Chris@909
|
193 end
|
Chris@909
|
194
|
Chris@909
|
195 filetypes.sort.each do |type, exts|
|
Chris@909
|
196 puts " #{type}: #{exts.sort_by { |ext| ext.size }.join(', ')}"
|
Chris@909
|
197 end
|
Chris@909
|
198 end
|
Chris@909
|
199 when 'stylesheet', 'style', 'css'
|
Chris@909
|
200 puts CodeRay::Encoders[:html]::CSS.new(args.first).stylesheet
|
Chris@909
|
201 when 'commands'
|
Chris@909
|
202 commands
|
Chris@909
|
203 when 'help'
|
Chris@909
|
204 help
|
Chris@909
|
205 else
|
Chris@909
|
206 $stdout = $stderr
|
Chris@909
|
207 help
|
Chris@909
|
208 puts
|
Chris@909
|
209 if subcommand[/\A\w+\z/]
|
Chris@909
|
210 puts "Unknown command: #{subcommand}"
|
Chris@909
|
211 else
|
Chris@909
|
212 puts "File not found: #{subcommand}"
|
Chris@909
|
213 end
|
Chris@909
|
214 exit 1
|
Chris@909
|
215 end
|