# frozen-string-literal: true # Copyright (C) 2020 Thomas Baron # # This file is part of term_utils. # # term_utils is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, version 3 of the License. # # term_utils is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with term_utils. If not, see . module TermUtils module AP # Represents an argument parsing Result. class Result # @return [Syntax] attr_reader :parameter # @return [Array] attr_reader :results # @return [Array] attr_accessor :remaining_arguments # Constructs a new Result. # @param syntax [Syntax] def initialize(syntax) @syntax = syntax @results = [] @remaining_arguments = nil end # Adds a ParameterResult. # @param result [ParameterResult] def add_result(result) @results << result end # Returns the first ParameterResult for a given parameter id. # @param id [Symbol] # @return [ParameterResult] def find_parameter(id) @results.find { |r| r.param_id == id } end # Returns all ParameterResult(s) for a given parameter id. # @param id [Symbol] # @return [Array] def find_parameters(id) @results.find_all { |r| r.param_id == id } end # Walks through this one. def walk(&block) walker = TermUtils::AP::Walker.new block.call(walker) @results.each do |p| p.results.each do |a| walker.notify_article(a) end walker.notify_parameter(p) end walker.notify_finished(@remaining_arguments) end end # Represents a result for a parameter. class ParameterResult # @return [Parameter] attr_accessor :parameter # @return [Array] attr_accessor :results # Constructs a new ParameterResult. # @param parent [Result] # @param parameter [Parameter] def initialize(parent, parameter) @parent = parent @parent.add_result(self) @parameter = parameter @results = [] end # Adds an ArticleResult. # @param result [ArticleResult] def add_result(result) @results << result end # @return [Symbol] def param_id @parameter.id end # Returns the first ArticleResult for a given article id. # @param id [Symbol] # @return [ArticleResult] def find_article(id) @results.find { |r| r.art_id == id } end # Returns all ArticleResult(s) for a given article id. # @param id [Symbol] # @return [Array] def find_articles(id) @results.find_all { |r| r.art_id == id } end # Returns the value of the first ArticleResult. # @param id [Symbol] Filter of article id. # @return [Object] def value(id = nil) return @results.first.value unless id find_article(id).value end # Returns the value of all ArticleResult(s). # @param id [Symbol] Filter of article id. # @return [Array] def values(id = nil) return @results.map(&:value) unless id vals = [] @results.each do |r| next if r.art_id != id vals << r.values end vals end end # Represents a result for an article. class ArticleResult # @return [ParameterResult] attr_accessor :parent # @return [Article] attr_accessor :article # @return [Object] attr_accessor :value # Constructs a new ArticleResult. # @param parent [ParameterResult] # @param article [Article] # @param value [Object] def initialize(parent, article, value) @parent = parent @parent.add_result(self) @article = article @value = value end # @return [Symbol] def art_id @article.id end end # Represents a Result Walker. class Walker # Constructs a new Walker. def initialize @anonymous_parameter_hook = nil @anonymous_article_hook = nil @parameter_hooks = {} @finished_hook = nil end # Registers a parameter hook. def parameter(param_id = nil, &block) unless param_id # Anonymous parameter hook @anonymous_parameter_hook = block return end @parameter_hooks[param_id] = TermUtils::AP::ParameterWalkerHooks.new unless @parameter_hooks.key?(param_id) @parameter_hooks[param_id].hook = block end # Registers an article hook. def article(param_id = nil, art_id = nil, &block) unless param_id # Anonymous article hook @anonymous_article_hook = block return end unless art_id # Anonymous article hook @parameter_hooks[param_id] = TermUtils::AP::ParameterWalkerHooks.new unless @parameter_hooks.key?(param_id) @parameter_hooks[param_id].anonymous_article_hook = block return end @parameter_hooks[param_id] = TermUtils::AP::ParameterWalkerHooks.new unless @parameter_hooks.key?(param_id) @parameter_hooks[param_id].article_hooks ||= {} @parameter_hooks[param_id].article_hooks[art_id] = block end # Registers a walk finished hook. def finished(&block) @finished_hook = block end # Calls parameter hooks. def notify_parameter(parameter) # (1of2) ID parameter hook param_hooks = @parameter_hooks[parameter.param_id] param_hooks.hook.call(parameter) if param_hooks && param_hooks.hook # (2of2) Anonymous parameter hook @anonymous_parameter_hook.call(parameter) if @anonymous_parameter_hook end # Calls article hooks. def notify_article(article) # (1of2) ID article hook param_hooks = @parameter_hooks[article.parent.param_id] if param_hooks # ID article hook param_hooks.article_hooks[article.art_id].call(article) if param_hooks.article_hooks && param_hooks.article_hooks.key?(article.art_id) # Anonymous article hook param_hooks.anonymous_article_hook.call(article) if param_hooks.anonymous_article_hook end # (2of2) Anonymous article hook @anonymous_article_hook.call(article) if @anonymous_article_hook end # Calls finished hook. def notify_finished(remaining_arguments) @finished_hook.call(remaining_arguments) if @finished_hook end end # Parameter hooks for Walker. ParameterWalkerHooks = Struct.new('ParameterWalkerHooks', :hook, :anonymous_article_hook, :article_hooks) end end