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.
- data/lib/non-haml/colorizer.rb +14 -0
- data/lib/non-haml/parser.rb +204 -0
- data/lib/non-haml/version.rb +9 -0
- data/lib/non-haml.rb +3 -0
- metadata +49 -0
@@ -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
|
data/lib/non-haml.rb
ADDED
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:
|