module OrigenTesters # Tester model to generate test program documentation from your pattern sources. # This is intended to be a drop in replacement for existing testers and instead # of generating patterns or test program sheets it will generate a document object # which you can then render out via a template or manually. class Doc include VectorBasedTester autoload :Generator, 'origen_testers/doc/generator' autoload :Model, 'origen_testers/doc/model' attr_accessor :html_mode def generate? html_mode end def initialize(*_args) @pat_extension = 'md' @indent = 0 @snip_counters = [] end # Snip the number of comment lines generated by the contained block # to the number given, this is useful for keeping files sizes down and # is typically used to snip sections like downloading LRE code. def snip(number, _options = {}) @snip_counters.push number + 1 yield @snip_counters.pop end def pc(msg) if @snip_counters.last if @snip_counters.last == 1 @snip_counters[@snip_counters.size - 1] = 0 msg = ' ...snipped' elsif @snip_counters.last == 0 return else @snip_counters[@snip_counters.size - 1] -= 1 end end if html_mode push_comment(msg) else Origen.log.info((' ' * @indent) + msg) end end def c1(msg, options = {}) if generating_program? Origen.interface.doc_comments_capture(msg) else unless @inhibit_comments options = { prefix: true }.merge(options) if @step_comment_on open_text_block if options[:prefix] pc "# #{msg}" else pc "#{msg}" end end end end end def c2(msg, options = {}) unless @inhibit_comments options = { prefix: true }.merge(options) open_text_block if options[:prefix] pc "# #{msg}" else pc "#{msg}" end end end def annotate(msg, _options) unless @inhibit_comments if html_mode pc '' lines = msg.split("\n") leading_spaces = lines.first[/\A */].size lines.each do |line| pc line.gsub(/^.{#{leading_spaces}}/, '') end pc '' end end end def open_text_block if html_mode unless @text_block_open pc '' pc '~~~text' @text_block_open = true end end end def close_text_block if html_mode if @text_block_open pc '~~~' pc '' @text_block_open = false end end end def pattern_name Origen.app.current_job.output_pattern_filename.gsub('.md', '') end def pre_header # pc "---" # pc "layout: bootstrap" # pc "title: #{pattern_name}" # pc "gzip: false" # pc "---" # pc "" # pc "# #{pattern_name}" # pc "" end def pattern_section(msg) unless @inhibit_comments if generating_program? Origen.interface.flow.start_section(name: msg) yield Origen.interface.flow.stop_section else if html_mode counter = next_accordion_counter close_text_block pc '' pc "
" pc "
" pc "" pc "#{msg}" pc '' pc '
' pc "
" pc "
" yield close_text_block pc '
' pc '
' pc '
' else pc '' pc "#{msg}" pc '' @indent += 4 yield @indent -= 4 end end end end def next_accordion_counter @accordion_counter ||= 0 @accordion_counter += 1 end def ss(msg = nil) unless @inhibit_comments @step_comment_on = true if block_given? yield else c2(msg) end @step_comment_on = false end end def self.generate_program_model(files, options = {}) options = { action: :program, return_model: true, skip_diff: true }.merge(options) Origen.app.with_doc_tester do Origen.target.temporary = options[:target] if options[:target] Origen.app.load_target! Origen.interface.reset_globals options[:files] = files Origen.file_handler.preserve_and_clear_state do Origen.app.runner.launch(options) end end model.target = Origen.target.name model end def self.model @model ||= Model.new end def doc? true end def cycle(_options = {}) end # Ignore any tester-specific methods def method_missing(_method, *_args, &_block) if block_given? yield end end end end