tilt 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #!/usr/bin/env ruby
  2. require 'ostruct'
  3. require 'optparse'
  4. require 'tilt'
  5. usage = <<USAGE
  6. Usage: tilt <options> <file>
  7. Process template <file> and write output to stdout. With no <file> or
  8. when <file> is '-', read template from stdin and use the --type option
  9. to determine the template's type.
  10. Options
  11. -l, --list List template engines + file patterns and exit
  12. -t, --type=<pattern> Use this template engine; required if no <file>
  13. -y, --layout=<file> Use <file> as a layout template
  14. -D<name>=<value> Define variable <name> as <value>
  15. -o, --vars=<ruby> Evaluate <ruby> to Hash and use for variables
  16. -h, --help Show this help message
  17. Convert markdown to HTML:
  18. $ tilt foo.markdown > foo.html
  19. Process ERB template:
  20. $ echo "Answer: <%= 2 + 2 %>" | tilt -t erb
  21. Answer: 4
  22. Define variables:
  23. $ echo "Answer: <%= 2 + n %>" | tilt --locals="{:n=>40, :x=>0}"
  24. Answer: 42
  25. $ echo "Answer: <%= 2 + n %>" | tilt -Dn=40 -Dx=0
  26. Answer: 42
  27. USAGE
  28. script_name = File.basename($0)
  29. pattern = nil
  30. layout = nil
  31. locals = {}
  32. ARGV.options do |o|
  33. o.program_name = script_name
  34. # list all available template engines
  35. o.on("-l", "--list") do
  36. groups = {}
  37. Tilt.mappings.each do |pattern,engine|
  38. key = engine.name.split('::').last.sub(/Template$/, '')
  39. (groups[key] ||= []) << pattern
  40. end
  41. groups.sort { |(k1,v1),(k2,v2)| k1 <=> k2 }.each do |engine,files|
  42. printf "%-15s %s\n", engine, files.sort.join(', ')
  43. end
  44. exit
  45. end
  46. # the template type / pattern
  47. o.on("-t", "--type=PATTERN", String) do |val|
  48. abort "unknown template type: #{val}" if Tilt[val].nil?
  49. pattern = val
  50. end
  51. # pass template output into the specified layout template
  52. o.on("-y", "--layout=FILE", String) do |file|
  53. paths = [file, "~/.tilt/#{file}", "/etc/tilt/#{file}"]
  54. layout = paths.
  55. map { |p| File.expand_path(p) }.
  56. find { |p| File.exist?(p) }
  57. abort "no such layout: #{file}" if layout.nil?
  58. end
  59. # define a local variable
  60. o.on("-D", "--define=PAIR", String) do |pair|
  61. key, value = pair.split(/[=:]/, 2)
  62. locals[key.to_sym] = value
  63. end
  64. # define local variables using a Ruby hash
  65. o.on("--vars=RUBY") do |ruby|
  66. hash = eval(ruby)
  67. abort "vars must be a Hash, not #{hash.inspect}" if !hash.is_a?(Hash)
  68. hash.each { |key, value| locals[key.to_sym] = value }
  69. end
  70. o.on_tail("-h", "--help") { puts usage; exit }
  71. o.parse!
  72. end
  73. file = ARGV.first || '-'
  74. pattern = file if pattern.nil?
  75. abort "template type not given. see: #{$0} --help" if ['-', ''].include?(pattern)
  76. engine = Tilt[pattern]
  77. abort "template engine not found for: #{pattern}" if engine.nil?
  78. template =
  79. engine.new(file) {
  80. if file == '-'
  81. $stdin.read
  82. else
  83. File.read(file)
  84. end
  85. }
  86. output = template.render(self, locals)
  87. # process layout
  88. output = Tilt.new(layout).render(self, locals) { output } if layout
  89. $stdout.write(output)