diff --git a/src/rename.cr b/src/rename.cr new file mode 100644 index 0000000..445b482 --- /dev/null +++ b/src/rename.cr @@ -0,0 +1,142 @@ +module Rename + alias VHash = Hash(String, String) + + class Variable + property id : String + + def initialize(@id) + end + + def render(hash : VHash) + hash[@id]? || "" + end + end + + class Pattern + @ary = [] of Variable + + def push(var) + @ary.push var + end + + def render(hash : VHash) + @ary.each do |v| + if hash.has_key? v.id + return v.render hash + end + end + "" + end + end + + class Group + @ary = [] of (Pattern | String) + + def push(var) + @ary.push var + end + + def render(hash : VHash) + return "" if @ary.select(&.is_a? Pattern) + .any? &.as(Pattern).render(hash).empty? + @ary.map do |e| + if e.is_a? Pattern + e.render hash + else + e + end + end.join + end + end + + class Rule + ESCAPE = ['/'] + + @ary = [] of (Group | String | Pattern) + + def initialize(str : String) + parse! str + rescue e + raise "Failed to parse rename rule #{str}. Error: #{e}" + end + + private def parse!(str : String) + chars = [] of Char + pattern : Pattern? = nil + group : Group? = nil + + str.each_char_with_index do |char, i| + if ['[', ']', '{', '}', '|'].includes?(char) && !chars.empty? + string = chars.join + if !pattern.nil? + pattern.push Variable.new string + elsif !group.nil? + group.push string + else + @ary.push string + end + chars = [] of Char + end + + case char + when '[' + if !group.nil? || !pattern.nil? + raise "nested groups are not allowed" + end + group = Group.new + when ']' + if group.nil? + raise "unmatched ] at position #{i}" + end + if !pattern.nil? + raise "patterns (`{}`) should be closed before closing the group " \ + "(`[]`)" + end + @ary.push group + group = nil + when '{' + if !pattern.nil? + raise "nested patterns are not allowed" + end + pattern = Pattern.new + when '}' + if pattern.nil? + raise "unmatched } at position #{i}" + end + if !group.nil? + group.push pattern + else + @ary.push pattern + end + pattern = nil + when '|' + else + if ESCAPE.includes? char + raise "the character #{char} at position #{i} is not allowed" + end + chars.push char + end + end + + unless chars.empty? + @ary.push chars.join + end + if !pattern.nil? + raise "unclosed pattern {" + end + if !group.nil? + raise "unclosed group [" + end + end + + def render(hash : VHash) + @ary.map do |e| + if e.is_a? String + e + else + e.render hash + end + end.join.strip + end + end +end