File: cli.rb

package info (click to toggle)
ruby-hamlit 2.15.1-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 1,996 kB
  • sloc: ruby: 10,548; ansic: 536; sh: 23; makefile: 8
file content (154 lines) | stat: -rw-r--r-- 4,117 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# frozen_string_literal: true
require 'hamlit'
require 'thor'

module Hamlit
  class CLI < Thor
    class_option :escape_html, type: :boolean, default: true
    class_option :escape_attrs, type: :boolean, default: true

    desc 'render HAML', 'Render haml template'
    option :load_path, type: :string, aliases: %w[-I]
    option :require, type: :string, aliases: %w[-r]
    def render(file)
      process_load_options
      code = generate_code(file)
      puts eval(code, binding, file)
    end

    desc 'compile HAML', 'Show compile result'
    option :actionview, type: :boolean, default: false, aliases: %w[-a]
    option :color, type: :boolean, default: true
    option :check, type: :boolean, default: false, aliases: %w[-c]
    def compile(file)
      code = generate_code(file)
      if options[:check]
        if error = validate_ruby(code, file)
          abort error.message.split("\n").first
        end
        puts "Syntax OK"
        return
      end
      puts_code(code, color: options[:color])
    end

    desc 'temple HAML', 'Show temple intermediate expression'
    option :color, type: :boolean, default: true
    def temple(file)
      pp_object(generate_temple(file), color: options[:color])
    end

    desc 'parse HAML', 'Show parse result'
    option :color, type: :boolean, default: true
    def parse(file)
      pp_object(generate_ast(file), color: options[:color])
    end

    desc 'version', 'Show the used hamlit version'
    def version
      puts Hamlit::VERSION
    end

    private

    def process_load_options
      if options[:load_path]
        options[:load_path].split(':').each do |dir|
          $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir)
        end
      end

      if options[:require]
        require options[:require]
      end
    end

    def read_file(file)
      if file == '-'
        STDIN.read
      else
        File.read(file)
      end
    end

    def generate_code(file)
      template = read_file(file)
      if options[:actionview]
        require 'action_view'
        require 'action_view/base'
        require 'hamlit/rails_template'
        handler = Hamlit::RailsTemplate.new
        template = ActionView::Template.new(template, 'inline template', handler, { locals: [] })
        code = handler.call(template)
        <<-end_src
          def _inline_template___2144273726781623612_70327218547300(local_assigns, output_buffer)
            _old_virtual_path, @virtual_path = @virtual_path, nil;_old_output_buffer = @output_buffer;;#{code}
          ensure
            @virtual_path, @output_buffer = _old_virtual_path, _old_output_buffer
          end
        end_src
      else
        Hamlit::Engine.new(engine_options).call(template)
      end
    end

    def generate_ast(file)
      template = read_file(file)
      Hamlit::Parser.new(engine_options).call(template)
    end

    def generate_temple(file)
      ast = generate_ast(file)
      Hamlit::Compiler.new(engine_options).call(ast)
    end

    def engine_options
      Hamlit::Engine.options.to_h.merge(
        escape_attrs: options[:escape_attrs],
        escape_html:  options[:escape_html],
      )
    end

    # Flexible default_task, compatible with haml's CLI
    def method_missing(*args)
      return super(*args) if args.length > 1
      render(args.first.to_s)
    end

    def puts_code(code, color: true)
      begin
        require 'irb/color'
      rescue LoadError
        color = false
      end
      if color
        puts IRB::Color.colorize_code(code)
      else
        puts code
      end
    end

    # Enable colored pretty printing only for development environment.
    def pp_object(arg, color: true)
      begin
        require 'irb/color_printer'
      rescue LoadError
        color = false
      end
      if color
        IRB::ColorPrinter.pp(arg)
      else
        require 'pp'
        pp(arg)
      end
    end

    def validate_ruby(code, file)
      begin
        eval("BEGIN {return nil}; #{code}", binding, file)
      rescue ::SyntaxError # Not to be confused with Hamlit::SyntaxError
        $!
      end
    end
  end
end