From f41db48681d5fcdde0f6dd9cc0bb36927c853126 Mon Sep 17 00:00:00 2001 From: Philippe PITTOLI Date: Thu, 8 Aug 2019 10:32:09 +0200 Subject: [PATCH] Adding sections. --- debug.cr | 10 +- samples/recipe-example.spec | 17 ++- shard.yml | 2 +- src/spec.cr | 233 +++++++++++++++++++++++++----------- 4 files changed, 184 insertions(+), 78 deletions(-) diff --git a/debug.cr b/debug.cr index 158c0da..adce6a7 100644 --- a/debug.cr +++ b/debug.cr @@ -21,18 +21,22 @@ options["someoptionexample"] = "option" specs = Specs.parse recipe_file_name, options pp! specs + + + + # low level stuff -sectioncontainer = Specs::SectionContainer.new "val" +sectioncontainer = Specs::Section.new "val" begin puts sectioncontainer.as_s - puts "(NOT OK) Specs::SectionContainer should not accept .as_s" + puts "(NOT OK) Specs::Section should not accept .as_s" rescue e puts "(OK) #{e}" end begin pp! sectioncontainer.as_a_or_s - puts "(NOT OK) Specs::SectionContainer should not accept .as_a_or_s" + puts "(NOT OK) Specs::Section should not accept .as_a_or_s" rescue e puts "(OK) #{e}" end diff --git a/samples/recipe-example.spec b/samples/recipe-example.spec index e584812..66b96b3 100644 --- a/samples/recipe-example.spec +++ b/samples/recipe-example.spec @@ -1,12 +1,12 @@ name: hello -version: 2.10 +version: 2.18 versions: 2.10, 2.9, 2.8, 2.7, 2.6 # Lists. sources: - https://ftp.gnu.org/gnu/%{name}/%{name}-%{version}.tar.gz packager: Luka Vandervelden -url: https://www.gnu.org/software/hello/ +url: https://www.gnu.org/software/%{name}%{version}/ flavors: nls, minimal @@ -23,3 +23,16 @@ flavors: nls, minimal cd hello-%{version} make DESTDIR="$PKG" install +%rule .c, .o + simpleass: assignment42 + list: + - blah + +%rule Debian, Ubuntu%{version} + # COMMENT + deps: + - dep for %{name} packager %{packager} + - url %{url} + @free + code flavors %{flavors} + code versions %{versions} diff --git a/shard.yml b/shard.yml index c313cd1..5db07eb 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: spec -version: 0.3.0 +version: 0.4.0 authors: - Philippe Pittoli diff --git a/src/spec.cr b/src/spec.cr index 2520940..527be51 100644 --- a/src/spec.cr +++ b/src/spec.cr @@ -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