|
|
|
@ -51,14 +51,6 @@ class Specs |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
class SectionContainer |
|
|
|
|
Specs.incompatible_methods as_s, as_a_or_s, as_s_or_ls |
|
|
|
|
property value : String |
|
|
|
|
|
|
|
|
|
def initialize(@value) |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
class ArrayContainer |
|
|
|
|
Specs.incompatible_methods as_s, as_s_or_ls |
|
|
|
|
property value : Array(String) |
|
|
|
@ -71,15 +63,25 @@ class Specs |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
class Section |
|
|
|
|
Specs.incompatible_methods as_s, as_a_or_s, as_s_or_ls |
|
|
|
|
property name : String |
|
|
|
|
property options : Array(String) |
|
|
|
|
property content : Hash(String, StringContainer | ArrayContainer | LongStringContainer) |
|
|
|
|
|
|
|
|
|
property assignments : Hash(String, StringContainer | LongStringContainer | SectionContainer | ArrayContainer) |
|
|
|
|
|
|
|
|
|
def initialize |
|
|
|
|
@assignments = Hash(String, StringContainer | LongStringContainer | SectionContainer | ArrayContainer).new |
|
|
|
|
def initialize(@name) |
|
|
|
|
@options = Array(String).new |
|
|
|
|
@content = Hash(String, StringContainer | ArrayContainer | LongStringContainer).new |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
# current_line = current_line.lstrip(" ").rstrip(" ") |
|
|
|
|
|
|
|
|
|
property assignments : Hash(String, StringContainer | LongStringContainer | Array(Section) | ArrayContainer) |
|
|
|
|
|
|
|
|
|
def initialize |
|
|
|
|
@assignments = Hash(String, StringContainer | LongStringContainer | Array(Section) | ArrayContainer).new |
|
|
|
|
@assignments["sections"] = Array(Section).new |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
def parse_assignment (line : String) |
|
|
|
|
# puts "simple assignment: #{line}" |
|
|
|
@ -155,6 +157,91 @@ class Specs |
|
|
|
|
@assignments[name] = LongStringContainer.new value |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
def parse_section(header : String, content : Array(String)) |
|
|
|
|
results = /^[%]([a-zA-Z][a-zA-Z0-9]*)[ \t]*([^#]*)/.match(header) |
|
|
|
|
name = results[1]? if results |
|
|
|
|
options = results[2]? if results |
|
|
|
|
|
|
|
|
|
if name.nil? |
|
|
|
|
return |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
section = Section.new name |
|
|
|
|
unless options.nil? |
|
|
|
|
section.options = options.split(",").map &.lstrip(" ").rstrip(" ") |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
while line = content.shift? |
|
|
|
|
case line |
|
|
|
|
when /^[ \t]*#.*$/ |
|
|
|
|
# puts "blank line or comment, still in a section" |
|
|
|
|
when /^([ \t]+)([^:]+):[ \t]+(.+)/ |
|
|
|
|
aname = $~[2].lstrip(" ").rstrip(" ") |
|
|
|
|
avalue = $~[3].lstrip(" ").rstrip(" ") |
|
|
|
|
# puts "simple assignation: #{aname} => #{avalue}" |
|
|
|
|
section.content[aname] = StringContainer.new avalue |
|
|
|
|
|
|
|
|
|
when /^([ \t]+)[@]([^ \t#]+)/ # free text |
|
|
|
|
indent = $~[1] |
|
|
|
|
codeblockname = $~[2].lstrip(" ").rstrip(" ") |
|
|
|
|
# puts "code block name: #{codeblockname}" |
|
|
|
|
|
|
|
|
|
codeblockvalue = String.build do |str| |
|
|
|
|
while line = content.shift? |
|
|
|
|
case line |
|
|
|
|
when /^[ \t]*#.*?$/ |
|
|
|
|
# puts "blank line or comment, still in a free text in a section" |
|
|
|
|
when /#{indent}[ \t]+(.*)/ |
|
|
|
|
v = $~[1].lstrip(" ").rstrip(" ") |
|
|
|
|
# puts "freetext content in section: #{v}" |
|
|
|
|
# puts "code content: #{$~[1]}" |
|
|
|
|
str << "#{v};" |
|
|
|
|
else |
|
|
|
|
content.unshift line |
|
|
|
|
break |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
section.content[codeblockname] = LongStringContainer.new codeblockvalue |
|
|
|
|
|
|
|
|
|
when /^([ \t]+)([^:]+):/ |
|
|
|
|
indent = $~[1] |
|
|
|
|
lname = $~[2].lstrip(" ").rstrip(" ") |
|
|
|
|
# puts "list: #{lname}" |
|
|
|
|
|
|
|
|
|
list = Array(String).new |
|
|
|
|
while line = content.shift? |
|
|
|
|
case line |
|
|
|
|
when /^[ \t]*#.*?$/ |
|
|
|
|
# puts "blank line or comment, still in a list in a section" |
|
|
|
|
when /^#{indent}[ \t]+-([^#]*)/ |
|
|
|
|
lcontent = $~[1].lstrip(" ").rstrip(" ") |
|
|
|
|
# puts "list item in section: #{lcontent}" |
|
|
|
|
list.push lcontent |
|
|
|
|
else |
|
|
|
|
content.unshift line |
|
|
|
|
break |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
if list.empty? |
|
|
|
|
next |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
section.content[lname] = ArrayContainer.new list |
|
|
|
|
else |
|
|
|
|
content.unshift line |
|
|
|
|
break |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
sections = @assignments["sections"] |
|
|
|
|
if sections.is_a?(Array(Section)) |
|
|
|
|
sections.push section |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
def parse_lines(content : Array(String)) |
|
|
|
|
count = 0 |
|
|
|
|
|
|
|
|
@ -166,16 +253,18 @@ class Specs |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
case line |
|
|
|
|
when /^[a-zA-Z][a-zA-Z]*:[ \t]+[a-zA-Z0-9-;|'"]+/ |
|
|
|
|
parse_assignment line |
|
|
|
|
when /^[a-zA-Z][a-zA-Z]*:[ \t]*([#].*)?/ |
|
|
|
|
when /^[a-zA-Z][a-zA-Z0-9]*:[ \t]*([#].*)?$/ |
|
|
|
|
parse_list line, content |
|
|
|
|
when /^[a-zA-Z][a-zA-Z]*:[ \t]+[^#]+/ |
|
|
|
|
parse_assignment line |
|
|
|
|
when /^[@][a-zA-Z][a-zA-Z]*[ \t]*([#].*)?/ |
|
|
|
|
parse_code_block line, content |
|
|
|
|
when /^[%][a-zA-Z][a-zA-Z]*[ \t]*([#].*)?/ |
|
|
|
|
parse_section line, content |
|
|
|
|
when /^[ \t]*#/ |
|
|
|
|
# puts "comment" |
|
|
|
|
when /^[ \t]+/ |
|
|
|
|
# puts "tab!!" |
|
|
|
|
puts "tab!! should not happen" |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
count += 1 |
|
|
|
@ -184,39 +273,40 @@ class Specs |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def replace_string_obj (v : StringContainer | SectionContainer | LongStringContainer) |
|
|
|
|
def replace_string (str : String) |
|
|
|
|
reg = /%\{([^}]*)\}/ |
|
|
|
|
|
|
|
|
|
while str =~ reg |
|
|
|
|
x = reg.match(str) |
|
|
|
|
unless x.nil? |
|
|
|
|
var = x.captures() |
|
|
|
|
|
|
|
|
|
if var[0]? && @assignments[var[0]]? |
|
|
|
|
replacement_object = @assignments[var[0]] |
|
|
|
|
case replacement_object |
|
|
|
|
when StringContainer |
|
|
|
|
replacement_value = replacement_object.value |
|
|
|
|
str = str.gsub "%{#{var[0]}}", "#{replacement_value}" |
|
|
|
|
end |
|
|
|
|
else |
|
|
|
|
# TODO: search in sections for assignments? |
|
|
|
|
raise "cannot find variable \033[31m#{var[0]}\033[00m" |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
str |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
def replace_string_obj (v : StringContainer | LongStringContainer) |
|
|
|
|
is_missing_references = false |
|
|
|
|
value = v.value |
|
|
|
|
|
|
|
|
|
begin |
|
|
|
|
while value =~ reg |
|
|
|
|
|
|
|
|
|
x = reg.match(value) |
|
|
|
|
unless x.nil? |
|
|
|
|
var = x.captures() |
|
|
|
|
|
|
|
|
|
if var[0]? && @assignments[var[0]]? |
|
|
|
|
replacement_object = @assignments[var[0]] |
|
|
|
|
case replacement_object |
|
|
|
|
when StringContainer |
|
|
|
|
replacement_value = replacement_object.value |
|
|
|
|
value = value.gsub "%{#{var[0]}}", "#{replacement_value}" |
|
|
|
|
end |
|
|
|
|
else |
|
|
|
|
is_missing_references = true |
|
|
|
|
raise "cannot find variable \033[31m#{var[0]}\033[00m" |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
v.value = value |
|
|
|
|
|
|
|
|
|
value = v.value |
|
|
|
|
end |
|
|
|
|
v.value = replace_string value |
|
|
|
|
rescue e |
|
|
|
|
puts "#{e}" |
|
|
|
|
is_missing_references = true |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
if is_missing_references |
|
|
|
@ -224,63 +314,62 @@ class Specs |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
def replace_array_obj (v : ArrayContainer) |
|
|
|
|
reg = /%\{([^}]*)\}/ |
|
|
|
|
|
|
|
|
|
str_array = v.value |
|
|
|
|
|
|
|
|
|
def replace_array (a : Array(String)) |
|
|
|
|
newarray = Array(String).new |
|
|
|
|
|
|
|
|
|
is_missing_references = false |
|
|
|
|
|
|
|
|
|
str_array.each do |value| |
|
|
|
|
tmp = value |
|
|
|
|
a.each do |value| |
|
|
|
|
begin |
|
|
|
|
|
|
|
|
|
while tmp =~ reg |
|
|
|
|
|
|
|
|
|
x = reg.match(tmp) |
|
|
|
|
unless x.nil? |
|
|
|
|
var = x.captures() |
|
|
|
|
|
|
|
|
|
if var[0]? && @assignments[var[0]]? |
|
|
|
|
replacement_object = @assignments[var[0]] |
|
|
|
|
case replacement_object |
|
|
|
|
when StringContainer |
|
|
|
|
replacement_value = replacement_object.value |
|
|
|
|
tmp = tmp.gsub "%{#{var[0]}}", "#{replacement_value}" |
|
|
|
|
end |
|
|
|
|
else |
|
|
|
|
is_missing_references = true |
|
|
|
|
raise "cannot find variable \033[31m#{var[0]}\033[00m" |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
newarray.push replace_string(value) |
|
|
|
|
rescue e |
|
|
|
|
puts "#{e}" |
|
|
|
|
is_missing_references = true |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
newarray.push tmp |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
if is_missing_references |
|
|
|
|
raise "there are missing references in the document: fix it" |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
newarray |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
def replace_array_obj (v : ArrayContainer) |
|
|
|
|
str_array = v.value |
|
|
|
|
newarray = replace_array str_array |
|
|
|
|
v.value = newarray |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
def replace_section_obj (v : Section) |
|
|
|
|
is_missing_references = false |
|
|
|
|
v.options = replace_array v.options |
|
|
|
|
v.content.map do |k, v| |
|
|
|
|
case v |
|
|
|
|
when StringContainer |
|
|
|
|
replace_string_obj v |
|
|
|
|
when LongStringContainer |
|
|
|
|
replace_string_obj v |
|
|
|
|
when ArrayContainer |
|
|
|
|
replace_array_obj v |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
def rewrite |
|
|
|
|
# replaces all occurrences of %{variable} by the content of @assignments[variable] |
|
|
|
|
@assignments.map do |k, v| |
|
|
|
|
case v |
|
|
|
|
when StringContainer |
|
|
|
|
replace_string_obj v |
|
|
|
|
when SectionContainer |
|
|
|
|
replace_string_obj v |
|
|
|
|
when LongStringContainer |
|
|
|
|
replace_string_obj v |
|
|
|
|
when ArrayContainer |
|
|
|
|
replace_array_obj v |
|
|
|
|
when Array(Section) |
|
|
|
|
v.each do |section| |
|
|
|
|
replace_section_obj section |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|