Class: Rundoc::FencedCodeBlock

Inherits:
Object
  • Object
show all
Defined in:
lib/rundoc/fenced_code_block.rb

Overview

A code secttion respesents a block of fenced code

A document can have multiple code sections

Constant Summary collapse

AUTOGEN_WARNING =
"\n<!-- STOP. This document is autogenerated. Do not manually modify. See the top of the doc for more details. -->"
PARTIAL_RESULT =
[]
PARTIAL_ENV =
{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(fence:, lang:, code:, context:) ⇒ FencedCodeBlock

Returns a new instance of FencedCodeBlock.

Parameters:

  • fence (String)

    the fence used to start the code block like ““‘”.

  • lang (String)

    any extra string after the fence like for example a fence of ““‘ruby” the lang would be “ruby”.

  • code (String)

    the code block contents inside the fence.

  • context (Context::Execution)

    The details about where the code block came from.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/rundoc/fenced_code_block.rb', line 27

def initialize(fence:, lang:, code:, context:)
  @fence = fence
  @lang = lang
  @code = code
  @executed = false
  @env = {}
  @stack = []
  @context = context
  @rendered = ""
  self.class.parse_code_commands(@code).each do |code_command|
    @stack.unshift(code_command)
  end

  PARTIAL_RESULT.clear
  PARTIAL_ENV.clear
end

Instance Attribute Details

#codeObject

Returns the value of attribute code.



9
10
11
# File 'lib/rundoc/fenced_code_block.rb', line 9

def code
  @code
end

#fenceObject

Returns the value of attribute fence.



9
10
11
# File 'lib/rundoc/fenced_code_block.rb', line 9

def fence
  @fence
end

#langObject

Returns the value of attribute lang.



9
10
11
# File 'lib/rundoc/fenced_code_block.rb', line 9

def lang
  @lang
end

Class Method Details

.parse_code_commands(code) ⇒ Object



114
115
116
117
118
119
120
121
122
# File 'lib/rundoc/fenced_code_block.rb', line 114

def self.parse_code_commands(code)
  parser = Rundoc::PegParser.new.code_block
  tree = parser.parse(code)
  commands = Rundoc::PegTransformer.new.apply(tree)
  commands = [commands] unless commands.is_a?(Array)
  commands
rescue ::Parslet::ParseFailed => e
  raise "Could not compile code:\n#{code}\nReason: #{e.message}"
end

.partial_result_to_docObject



85
86
87
# File 'lib/rundoc/fenced_code_block.rb', line 85

def self.partial_result_to_doc
  to_doc(result: PARTIAL_RESULT, env: PARTIAL_ENV)
end

.to_doc(result:, env:) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/rundoc/fenced_code_block.rb', line 89

def self.to_doc(result:, env:)
  array = [env[:before]]

  result.flatten!
  result.compact!
  result.map! { |s| s.respond_to?(:rstrip) ? s.rstrip : s }
  result.reject!(&:empty?)
  result.map!(&:to_s)

  if !result.empty?
    array << env[:fence_start]
    array << result
    array << env[:fence_end]
  end
  array << env[:after]

  array.flatten!
  array.compact!
  array.map! { |s| s.respond_to?(:rstrip) ? s.rstrip : s }
  array.reject!(&:empty?)
  array.map!(&:to_s)

  array.join("\n") << "\n"
end

Instance Method Details

#callObject



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/rundoc/fenced_code_block.rb', line 44

def call
  return self if @executed
  @executed = true

  result = []
  env = @env
  env[:commands] = []
  env[:fence_start] = "#{fence}#{lang}"
  env[:fence_end] = "#{fence}#{AUTOGEN_WARNING}"
  env[:before] = []
  env[:after] = []
  env[:context] = @context
  env[:stack] = @stack

  while (code_command = @stack.pop)
    code_output = code_command.call(env) || ""
    code_line = code_command.to_md(env) || ""
    result << code_line if code_command.render_command?
    result << code_output if code_command.render_result?

    PARTIAL_RESULT.replace(result)
    PARTIAL_ENV.replace(env)

    env[:commands] << {
      object: code_command,
      output: code_output,
      command: code_line
    }
  end

  if env[:commands].any? { |c| c[:object].not_hidden? }
    @rendered = self.class.to_doc(result: result, env: env)
  end
  self
end

#executed_commandsObject

Used for tests to inspect the command that was executed



15
16
17
18
19
# File 'lib/rundoc/fenced_code_block.rb', line 15

def executed_commands
  raise "Nothing executed" unless @env[:commands].any?

  @env[:commands].map { |c| c[:object] }
end

#renderObject



80
81
82
83
# File 'lib/rundoc/fenced_code_block.rb', line 80

def render
  call
  @rendered
end