non-haml 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,14 @@
1
+ module Color
2
+ COLORS = {clear: 0, red: 31, green: 32, yellow: 33, blue: 34, gray: 30, grey: 30}
3
+ def self.method_missing(color_name, *args)
4
+ if args.first.is_a? String
5
+ color(color_name) + args.first + color(:clear)
6
+ else
7
+ color(color_name) + args.first.inspect + color(:clear)
8
+ end
9
+ end
10
+
11
+ def self.color(color)
12
+ "\e[#{COLORS[color.to_sym]}m"
13
+ end
14
+ end
@@ -0,0 +1,204 @@
1
+ # Simple line-wise parser for converting special files into slightly-enhanced
2
+ # files. No need for anything too complicated like a full-on grammar.
3
+ # Similar syntax to haml.
4
+
5
+ # Example usage:
6
+ # require 'non-haml'
7
+ # NonHaml.generate 'output/source.c', 'source.c', binding
8
+
9
+ module NonHaml
10
+ class << self
11
+ attr_accessor :last_ok_line, :out, :base_dir
12
+
13
+ def concat spaces=nil, text=nil
14
+ if spaces.nil? and text.nil?
15
+ self.out << "\n"
16
+ else
17
+ text.to_s.lines do |l|
18
+ self.out << "#{' '*spaces}#{l.rstrip}\n"
19
+ end
20
+ end
21
+ end
22
+
23
+ def generate out_name, in_name, context, base_dir='./', verbose=false
24
+ NonHamlParser.new.generate out_name, in_name, context, base_dir, verbose
25
+ end
26
+
27
+ def filename
28
+ # Retrieves the current filename.
29
+ @filenames.last
30
+ end
31
+
32
+ def push_filename new_name
33
+ @filenames ||= []
34
+ @filenames << new_name
35
+ end
36
+
37
+ def pop_filename
38
+ @filenames.pop
39
+ end
40
+
41
+ def current_filename
42
+ "#{base_dir}#{NonHaml.filename}"
43
+ end
44
+ end
45
+
46
+ class IndentError < StandardError
47
+ end
48
+
49
+ class ParseError < StandardError
50
+ end
51
+
52
+ class NonHamlParser
53
+ def parse text, base_control_indent=0, base_indent=0
54
+ @s = ""
55
+ def store text
56
+ @s << "#{text}\n"
57
+ end
58
+
59
+ # Number of indents at the start of blocks.
60
+ @block_starts = []
61
+ @statements = []
62
+ @base_control_indent = base_control_indent
63
+ def control_indent
64
+ ' ' * (@block_starts.length + @base_control_indent)
65
+ end
66
+
67
+ def dedent indent, suppress_end=false
68
+ dedented = false
69
+ @block_starts.reverse.take_while{|x| x >= indent}.each do |x|
70
+ # Close some blocks to get back to the right indentation level.
71
+ @block_starts.pop
72
+ unless suppress_end and %w{if elsif else}.include?(@statements.pop) and x == indent
73
+ store control_indent + 'end'
74
+ end
75
+ dedented = true # return status so we know whether to skip a blank line.
76
+ end
77
+ dedented
78
+ end
79
+
80
+ text.lines.with_index do |line,i|
81
+ line.rstrip!
82
+
83
+ line =~ /^( *)(.*)$/
84
+ indent, line = $1.length, $2
85
+ indent += base_indent
86
+
87
+ if (line =~ /^- *((if|unless|for|elsif|else)\b.*)$/) or (line =~ /^- *(.*\bdo\b *(|.*|)?)$/)
88
+ # Entering a block.
89
+
90
+ if %w{elsif else}.include? $2
91
+ store control_indent + "NonHaml.last_ok_line = #{i}"
92
+ dedent indent, %w{elsif else}.include?($2)
93
+ else
94
+ dedent indent, %w{elsif else}.include?($2)
95
+ store control_indent + "NonHaml.last_ok_line = #{i}"
96
+ end
97
+
98
+ store control_indent + $1
99
+ @block_starts << indent
100
+ @statements << $2
101
+ # Output should have same indent as block.
102
+ concat_indent = indent
103
+ elsif line =~ /= ?non_haml ['"](.*)['"]/
104
+ store control_indent + "NonHaml.last_ok_line = #{i}"
105
+ file = NonHaml.base_dir + $1
106
+ if File.readable? file
107
+ store control_indent + "NonHaml.push_filename '#{$1}'"
108
+ @s += parse open(file).read, control_indent.length, indent
109
+ else
110
+ store control_indent + "raise Errno::ENOENT, '\"#{$1}\"'"
111
+ end
112
+ store control_indent + "NonHaml.pop_filename"
113
+ elsif line.strip.length.zero?
114
+ # Blank line. Output and move on. Don't change indent. Only do this
115
+ # for if blocks though, so 'if false' doesn't generate optional blank
116
+ # line and 'if true' does.
117
+ #if @statements.last == 'if' or @statements.empty?
118
+ # XXX disabled temporarily because it sucked.
119
+ store control_indent + "NonHaml.last_ok_line = #{i}"
120
+ #if @statements.empty?
121
+ store "#{control_indent}NonHaml.concat"
122
+ #end
123
+ else
124
+ dedented = dedent indent
125
+ store control_indent + "NonHaml.last_ok_line = #{i}"
126
+
127
+ # Now deal with whatever we have left.
128
+ if line =~ /^- *(.*)$/
129
+ # Generic Ruby statement that isn't entering/leaving a block.
130
+ store control_indent + $1
131
+ elsif line =~ /^= *(.*)$/
132
+ # Concatenate this for evaluation.
133
+ target_indent = indent - control_indent.length
134
+ # Deal with blank lines.
135
+ content = $1
136
+ content = '""' if content.empty?
137
+ store "#{control_indent}NonHaml.concat(#{target_indent}, (#{content}))"
138
+ elsif dedented and line.strip.empty?
139
+ puts 'skipping'
140
+ # Skip up to one blank line after dedenting.
141
+ next
142
+ else
143
+ # Concatenate this for output.
144
+ target_indent = indent - control_indent.length
145
+ # Replace #{} blocks, but completely quote the rest.
146
+ # TODO clean up more nicely if we fail here!!!
147
+ to_sub = []
148
+ line.gsub!('%', '%%')
149
+ line.gsub!(/#\{(.*?)\}/){to_sub << $1; '%s'}
150
+ if to_sub.empty?
151
+ # Must do pretend substitutions to get around %% characters.
152
+ subst = " % []"
153
+ else
154
+ # Include brackets around all quantities, so bracket-free
155
+ # functions get the right arguments.
156
+ subst = " % [#{to_sub.map{|x| "(#{x})"}.join ', '}]"
157
+ end
158
+ store "#{control_indent}NonHaml.concat #{target_indent}, (%q##{line.gsub('#', '\\#')}##{subst})"
159
+ end
160
+ end
161
+ end
162
+ dedent 0
163
+ @s
164
+ end
165
+
166
+ def generate out_name, in_name, context, base_dir, verbose
167
+ NonHaml.base_dir = base_dir
168
+ NonHaml.out = ""
169
+
170
+ NonHaml.push_filename in_name
171
+
172
+ src = parse open(NonHaml.current_filename).read
173
+ if verbose
174
+ src.lines.each_with_index do |l,i|
175
+ print Color.blue '%3d ' % (i + 1)
176
+ puts l
177
+ end
178
+ end
179
+
180
+ begin
181
+ eval src, context
182
+ rescue Exception => e
183
+ # Interrupt everything, give more info, then dump out the old exception.
184
+ $stderr.puts
185
+ $stderr.puts "in #{NonHaml.current_filename}:"
186
+ $stderr.puts Color.red " #{e.class.name}: #{Color.blue e.to_s}"
187
+ open(NonHaml.current_filename).lines.each_with_index.drop([NonHaml.last_ok_line - 2, 0].max).first(5).each do |line,i|
188
+ if i == NonHaml.last_ok_line
189
+ $stderr.print Color.red ' %3d ' % (i + 1)
190
+ $stderr.print Color.red line
191
+ else
192
+ $stderr.print ' %3d ' % (i + 1)
193
+ $stderr.print line
194
+ end
195
+ end
196
+ raise e
197
+ else
198
+ open(out_name, 'w') do |f|
199
+ f.puts NonHaml.out
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,9 @@
1
+ module NonHaml
2
+ unless const_defined?('VERSION')
3
+ VERSION = "1.0"
4
+ end
5
+
6
+ def self.version
7
+ VERSION
8
+ end
9
+ end
data/lib/non-haml.rb ADDED
@@ -0,0 +1,3 @@
1
+ require "non-haml/version"
2
+ require "non-haml/colorizer"
3
+ require "non-haml/parser"
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: non-haml
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jacob Mattingley
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-16 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: HAML-like syntax for non-HTML
15
+ email: jem@ieee.org
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/non-haml/colorizer.rb
21
+ - lib/non-haml/parser.rb
22
+ - lib/non-haml/version.rb
23
+ - lib/non-haml.rb
24
+ homepage: http://stanford.edu/~jacobm
25
+ licenses: []
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - lib
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ version: 1.9.2
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubyforge_project:
44
+ rubygems_version: 1.8.11
45
+ signing_key:
46
+ specification_version: 3
47
+ summary: HAML-like syntax for non-HTML
48
+ test_files: []
49
+ has_rdoc: