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:, io: $stdout) ⇒ 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
43
# File 'lib/rundoc/fenced_code_block.rb', line 27

def initialize(fence:, lang:, code:, context:, io: $stdout)
  @io = io
  @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



117
118
119
120
121
122
123
124
125
# File 'lib/rundoc/fenced_code_block.rb', line 117

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



88
89
90
# File 'lib/rundoc/fenced_code_block.rb', line 88

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

.to_doc(result:, env:) ⇒ Object



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

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



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
79
80
81
# File 'lib/rundoc/fenced_code_block.rb', line 45

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 (item = @stack.pop)
    code_command = item.build(io: @io)

    code_output = code_command.call(env) || ""
    code_line = code_command.to_md(env) || ""
    result << code_line if item.render_command?
    result << code_output if item.render_result?

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

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

  if env[:commands].any? { |c| c[:visibility].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[:visibility] }
end

#renderObject



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

def render
  call
  @rendered
end