# frozen_string_literal: truerequire_relative'../tilt'require'optparse'moduleTilt::CLIUSAGE=(<<USAGE).freeze
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>
-d, --define-file=<file> Load YAML from <file> and use for variables
--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 -t erb --vars="{:n=>40}"
Answer: 42
$ echo "Answer: <%= 2 + n.to_i %>" | tilt -t erb -Dn=40
Answer: 42
USAGEprivate_constant:USAGE# Backbone of the tilt command line utility. Allows mocking input/output# for simple testing. Returns program exit code.defself.run(argv: ARGV,stdout: $stdout,stdin: $stdin,stderr: $stderr,script_name: File.basename($0))pattern=nillayout=nillocals={}abort=procdo|msg|stderr.putsmsgreturn1endOptionParser.newdo|o|o.program_name=script_name# list all available template engineso.on("-l","--list")dogroups={}Tilt.lazy_map.eachdo|pattern,engines|engines.eachdo|engine,|engine=engine.split('::').last.sub(/Template\z/,'')(groups[engine]||=[])<<patternendendgroups.sort{|(k1,v1),(k2,v2)|k1<=>k2}.eachdo|engine,files|stdout.printf"%-20s %s\n",engine,files.sort.join(', ')endreturn0end# the template type / patterno.on("-t","--type=PATTERN",String)do|val|abort.("unknown template type: #{val}")unlessTilt[val]pattern=valend# pass template output into the specified layout templateo.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}")iflayout.nil?end# define a local variableo.on("-D","--define=PAIR",String)do|pair|key,value=pair.split(/[=:]/,2)locals[key.to_sym]=valueend# define local variables from YAML or JSONo.on("-d","--define-file=FILE",String)do|file|require'yaml'abort.("no such define file: #{file}")unlessFile.exist?filehash=File.open(file,'r:bom|utf-8'){|f|YAML.load(f.read)}abort.("vars must be a Hash, not instance of #{hash.class}")unlesshash.is_a?(Hash)hash.each{|key,value|locals[key.to_sym]=value}end# define local variables using a Ruby hasho.on("--vars=RUBY")do|ruby|hash=eval(ruby)abort.("vars must be a Hash, not instance of #{hash.class}")unlesshash.is_a?(Hash)hash.each{|key,value|locals[key.to_sym]=value}endo.on_tail("-h","--help")dostdout.putsUSAGEreturn0endend.parse!(argv)file=argv.first||'-'pattern=fileifpattern.nil?abort.("template type not given. see: #{script_name} --help")if['-',''].include?(pattern)engine=Tilt[pattern]abort.("template engine not found for: #{pattern}")unlessenginetemplate=engine.new(file){iffile=='-'stdin.readelseFile.read(file)end}output=template.render(self,locals)# process layoutoutput=Tilt.new(layout).render(self,locals){output}iflayoutstdout.write(output)0endend