123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- #!/usr/bin/env ruby
- require 'ostruct'
- require 'optparse'
- require 'tilt'
- usage = <<USAGE
- Usage: tilt <options> <file>
- Process template <file> and write output to stdout. With no <file> or
- when <file> is '-', read template from stdin and use the --type option
- to determine the template's type.
- Options
- -l, --list List template engines + file patterns and exit
- -t, --type=<pattern> Use this template engine; required if no <file>
- -y, --layout=<file> Use <file> as a layout template
- -D<name>=<value> Define variable <name> as <value>
- -o, --vars=<ruby> Evaluate <ruby> to Hash and use for variables
- -h, --help Show this help message
- Convert markdown to HTML:
- $ tilt foo.markdown > foo.html
- Process ERB template:
- $ echo "Answer: <%= 2 + 2 %>" | tilt -t erb
- Answer: 4
- Define variables:
- $ echo "Answer: <%= 2 + n %>" | tilt --locals="{:n=>40, :x=>0}"
- Answer: 42
- $ echo "Answer: <%= 2 + n %>" | tilt -Dn=40 -Dx=0
- Answer: 42
- USAGE
- script_name = File.basename($0)
- pattern = nil
- layout = nil
- locals = {}
- ARGV.options do |o|
- o.program_name = script_name
- # list all available template engines
- o.on("-l", "--list") do
- groups = {}
- Tilt.mappings.each do |pattern,engine|
- key = engine.name.split('::').last.sub(/Template$/, '')
- (groups[key] ||= []) << pattern
- end
- groups.sort { |(k1,v1),(k2,v2)| k1 <=> k2 }.each do |engine,files|
- printf "%-15s %s\n", engine, files.sort.join(', ')
- end
- exit
- end
- # the template type / pattern
- o.on("-t", "--type=PATTERN", String) do |val|
- abort "unknown template type: #{val}" if Tilt[val].nil?
- pattern = val
- end
- # pass template output into the specified layout template
- o.on("-y", "--layout=FILE", String) do |file|
- paths = [file, "~/.tilt/#{file}", "/etc/tilt/#{file}"]
- layout = paths.
- map { |p| File.expand_path(p) }.
- find { |p| File.exist?(p) }
- abort "no such layout: #{file}" if layout.nil?
- end
- # define a local variable
- o.on("-D", "--define=PAIR", String) do |pair|
- key, value = pair.split(/[=:]/, 2)
- locals[key.to_sym] = value
- end
- # define local variables using a Ruby hash
- o.on("--vars=RUBY") do |ruby|
- hash = eval(ruby)
- abort "vars must be a Hash, not #{hash.inspect}" if !hash.is_a?(Hash)
- hash.each { |key, value| locals[key.to_sym] = value }
- end
- o.on_tail("-h", "--help") { puts usage; exit }
- o.parse!
- end
- file = ARGV.first || '-'
- pattern = file if pattern.nil?
- abort "template type not given. see: #{$0} --help" if ['-', ''].include?(pattern)
- engine = Tilt[pattern]
- abort "template engine not found for: #{pattern}" if engine.nil?
- template =
- engine.new(file) {
- if file == '-'
- $stdin.read
- else
- File.read(file)
- end
- }
- output = template.render(self, locals)
- # process layout
- output = Tilt.new(layout).render(self, locals) { output } if layout
- $stdout.write(output)
|