module Tilt::CLI

Constants

USAGE

Public Class Methods

run(argv: ARGV, stdout: $stdout, stdin: $stdin, stderr: $stderr, script_name: File.basename($0)) click to toggle source

Backbone of the tilt command line utility. Allows mocking input/output for simple testing. Returns program exit code.

    # File lib/tilt/cli.rb
 40 def self.run(argv: ARGV, stdout: $stdout, stdin: $stdin, stderr: $stderr, script_name: File.basename($0))
 41   pattern = nil
 42   layout = nil
 43   locals = {}
 44   abort = proc do |msg|
 45     stderr.puts msg
 46     return 1
 47   end
 48 
 49   OptionParser.new do |o|
 50     o.program_name = script_name
 51 
 52     # list all available template engines
 53     o.on("-l", "--list") do
 54       groups = {}
 55       Tilt.lazy_map.each do |pattern,engines|
 56         engines.each do |engine,|
 57           engine = engine.split('::').last.sub(/Template\z/, '')
 58           (groups[engine] ||= []) << pattern
 59         end
 60       end
 61       groups.sort { |(k1,v1),(k2,v2)| k1 <=> k2 }.each do |engine,files|
 62         stdout.printf "%-20s %s\n", engine, files.sort.join(', ')
 63       end
 64       return 0
 65     end
 66 
 67     # the template type / pattern
 68     o.on("-t", "--type=PATTERN", String) do |val|
 69       abort.("unknown template type: #{val}") unless Tilt[val]
 70       pattern = val
 71     end
 72 
 73     # pass template output into the specified layout template
 74     o.on("-y", "--layout=FILE", String)  do |file|
 75       paths = [file, "~/.tilt/#{file}", "/etc/tilt/#{file}"]
 76       layout = paths.
 77         map  { |p| File.expand_path(p) }.
 78         find { |p| File.exist?(p) }
 79       abort.("no such layout: #{file}") if layout.nil?
 80     end
 81 
 82     # define a local variable
 83     o.on("-D", "--define=PAIR", String) do |pair|
 84       key, value = pair.split(/[=:]/, 2)
 85       locals[key.to_sym] = value
 86     end
 87 
 88     # define local variables from YAML or JSON
 89     o.on("-d", "--define-file=FILE", String) do |file|
 90       require 'yaml'
 91       abort.("no such define file: #{file}") unless File.exist? file
 92       hash = File.open(file, 'r:bom|utf-8') { |f| YAML.load(f.read) }
 93       abort.("vars must be a Hash, not instance of #{hash.class}") unless hash.is_a?(Hash)
 94       hash.each { |key, value| locals[key.to_sym] = value }
 95     end
 96 
 97     # define local variables using a Ruby hash
 98     o.on("--vars=RUBY") do |ruby|
 99       hash = eval(ruby)
100       abort.("vars must be a Hash, not instance of #{hash.class}") unless hash.is_a?(Hash)
101       hash.each { |key, value| locals[key.to_sym] = value }
102     end
103 
104     o.on_tail("-h", "--help") do
105       stdout.puts USAGE
106       return 0
107     end
108   end.parse!(argv)
109 
110   file = argv.first || '-'
111   pattern = file if pattern.nil?
112   abort.("template type not given. see: #{script_name} --help") if ['-', ''].include?(pattern)
113 
114   engine = Tilt[pattern]
115   abort.("template engine not found for: #{pattern}") unless engine
116 
117   template =
118     engine.new(file) {
119       if file == '-'
120         stdin.read
121       else
122         File.read(file)
123       end
124     }
125   output = template.render(self, locals)
126 
127   # process layout
128   output = Tilt.new(layout).render(self, locals) { output } if layout
129 
130   stdout.write(output)
131 
132   0
133 end