1#!/usr/bin/env ruby
2# Tiny eRuby --- ERB2
3# Copyright (c) 1999-2000,2002 Masatoshi SEKI
4# You can redistribute it and/or modify it under the same terms as Ruby.
5
6require 'erb'
7
8class ERB
9  module Main
10    def ARGV.switch
11      return nil if self.empty?
12      arg = self.shift
13      return nil if arg == '--'
14      if arg =~ /^-(.)(.*)/
15        if $1 == '-'
16          arg, @maybe_arg = arg.split(/=/, 2)
17          return arg
18        end
19        raise 'unknown switch "-"' if $2[0] == ?- and $1 != 'T'
20        if $2.size > 0
21          self.unshift "-#{$2}"
22          @maybe_arg = $2
23        else
24          @maybe_arg = nil
25        end
26        "-#{$1}"
27      else
28        self.unshift arg
29        nil
30      end
31    end
32
33    def ARGV.req_arg
34      (@maybe_arg || self.shift || raise('missing argument')).tap {
35        @maybe_arg = nil
36      }
37    end
38
39    def trim_mode_opt(trim_mode, disable_percent)
40      return trim_mode if disable_percent
41      case trim_mode
42      when 0
43        return '%'
44      when 1
45        return '%>'
46      when 2
47        return '%<>'
48      when '-'
49        return '%-'
50      end
51    end
52    module_function :trim_mode_opt
53
54    def run(factory=ERB)
55      trim_mode = 0
56      disable_percent = false
57      begin
58        while switch = ARGV.switch
59          case switch
60          when '-x'                        # ruby source
61            output = true
62          when '-n'                        # line number
63            number = true
64          when '-v'                        # verbose
65            $VERBOSE = true
66          when '--version'                 # version
67            STDERR.puts factory.version
68            exit
69          when '-d', '--debug'             # debug
70            $DEBUG = true
71          when '-r'                        # require
72            require ARGV.req_arg
73          when '-S'                        # security level
74            arg = ARGV.req_arg
75            raise "invalid safe_level #{arg.dump}" unless arg =~ /^[0-4]$/
76            safe_level = arg.to_i
77          when '-T'                        # trim mode
78            arg = ARGV.req_arg
79            if arg == '-'
80              trim_mode = arg
81              next
82            end
83            raise "invalid trim mode #{arg.dump}" unless arg =~ /^[0-2]$/
84            trim_mode = arg.to_i
85          when '-E', '--encoding'
86            arg = ARGV.req_arg
87            set_encoding(*arg.split(/:/, 2))
88          when '-U'
89            set_encoding(Encoding::UTF_8, Encoding::UTF_8)
90          when '-P'
91            disable_percent = true
92          when '--help'
93            raise "print this help"
94          else
95            raise "unknown switch #{switch.dump}"
96          end
97        end
98      rescue                               # usage
99        STDERR.puts $!.to_s
100        STDERR.puts File.basename($0) +
101          " [switches] [inputfile]"
102        STDERR.puts <<EOU
103  -x               print ruby script
104  -n               print ruby script with line number
105  -v               enable verbose mode
106  -d               set $DEBUG to true
107  -r library       load a library
108  -S safe_level    set $SAFE (0..4)
109  -E ex[:in]       set default external/internal encodings
110  -U               set default encoding to UTF-8.
111  -T trim_mode     specify trim_mode (0..2, -)
112  -P               ignore lines which start with "%"
113EOU
114        exit 1
115      end
116
117      $<.set_encoding(Encoding::ASCII_8BIT, nil)
118      src = $<.read
119      filename = $FILENAME
120      exit 2 unless src
121      trim = trim_mode_opt(trim_mode, disable_percent)
122      erb = factory.new(src.untaint, safe_level, trim)
123      erb.filename = filename
124      if output
125        if number
126          erb.src.each_line.with_index do |line, l|
127            puts "%3d %s"%[l+1, line]
128          end
129        else
130          puts erb.src
131        end
132      else
133        erb.run(TOPLEVEL_BINDING.taint)
134      end
135    end
136    module_function :run
137
138    def set_encoding(extern, intern = nil)
139      verbose, $VERBOSE = $VERBOSE, nil
140      Encoding.default_external = extern unless extern.nil? || extern.empty?
141      Encoding.default_internal = intern unless intern.nil? || intern.empty?
142      [$stdin, $stdout, $stderr].each do |io|
143        io.set_encoding(extern, intern)
144      end
145    ensure
146      $VERBOSE = verbose
147    end
148    module_function :set_encoding
149    class << self; private :set_encoding; end
150  end
151end
152
153if __FILE__ == $0
154  ERB::Main.run
155end
156