raindown 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/raindown/actions.rb +54 -0
- data/lib/raindown/cli.rb +59 -17
- data/lib/raindown/document.rb +148 -0
- data/lib/raindown/endpoint/endpoint_runner.rb +15 -5
- data/lib/raindown/node_blocks.rb +22 -12
- data/lib/raindown/project_worker.rb +48 -0
- data/lib/raindown/projects.rb +71 -0
- data/lib/raindown/supervisor.rb +160 -0
- data/lib/raindown/tui/commands.rb +70 -0
- data/lib/raindown/tui/file_tree.rb +55 -0
- data/lib/raindown/tui/input.rb +55 -0
- data/lib/raindown/tui/layout.rb +142 -0
- data/lib/raindown/tui/navigator.rb +123 -0
- data/lib/raindown/tui/outline.rb +114 -0
- data/lib/raindown/tui/pane.rb +41 -0
- data/lib/raindown/tui/row.rb +16 -0
- data/lib/raindown/tui/screen.rb +131 -0
- data/lib/raindown/tui/styles.rb +36 -0
- data/lib/raindown/tui.rb +27 -0
- data/lib/raindown/watcher.rb +7 -23
- data/lib/version.rb +1 -1
- metadata +32 -2
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../document'
|
|
4
|
+
require_relative 'row'
|
|
5
|
+
|
|
6
|
+
module Raindown
|
|
7
|
+
module TUI
|
|
8
|
+
# The outline pane: a file's headings and directives, read from its Document. Headings fold the section below them,
|
|
9
|
+
# and a directive's output, the lines Raindown wrote back, expands below it. Both start folded away.
|
|
10
|
+
class Outline
|
|
11
|
+
attr_reader :path, :error
|
|
12
|
+
|
|
13
|
+
def initialize(path)
|
|
14
|
+
@path = path
|
|
15
|
+
@folded = Set.new
|
|
16
|
+
@expanded = Set.new
|
|
17
|
+
read
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Reads the file again, keeping what's folded.
|
|
21
|
+
def read
|
|
22
|
+
@mtime = File.mtime(path)
|
|
23
|
+
@document = Document.read(path)
|
|
24
|
+
@lines = File.readlines(path, chomp: true)
|
|
25
|
+
@document.directives # Finds an error in the file, like a missing end tag, now rather than while drawing.
|
|
26
|
+
@error = nil
|
|
27
|
+
rescue StandardError => e
|
|
28
|
+
@error = e.message
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def changed?
|
|
32
|
+
File.exist?(path) && File.mtime(path) != @mtime
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def fold(heading)
|
|
36
|
+
@folded.delete?(heading.line) || @folded.add(heading.line)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def expand(directive)
|
|
40
|
+
@expanded.delete?(directive.line) || @expanded.add(directive.line)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def rows
|
|
44
|
+
return [Row.new(text: error, depth: 0, kind: :error, target: 1)] if error
|
|
45
|
+
|
|
46
|
+
sections.flat_map do |heading, items|
|
|
47
|
+
next items.flat_map { directive_rows(it, depth: 0) } unless heading
|
|
48
|
+
|
|
49
|
+
depth = heading.level - min_level + 1
|
|
50
|
+
[heading_row(heading), *(items.flat_map { directive_rows(it, depth:) } unless @folded.include?(heading.line))]
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
# Each heading with the directives below it, leaving out the headings in a folded heading's section.
|
|
57
|
+
# Directives before the first heading come first, with no heading.
|
|
58
|
+
def sections
|
|
59
|
+
sections = [[nil, []]]
|
|
60
|
+
hidden = nil
|
|
61
|
+
|
|
62
|
+
items.each do |item|
|
|
63
|
+
heading = item.is_a?(Document::Heading)
|
|
64
|
+
next if hidden && !(heading && item.level <= hidden)
|
|
65
|
+
|
|
66
|
+
hidden = (item.level if @folded.include?(item.line)) if heading
|
|
67
|
+
heading ? sections << [item, []] : sections.last.last << item
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
sections
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Headings a directive wrote are part of its output, so they show when it's expanded rather than on their own.
|
|
74
|
+
def items
|
|
75
|
+
outputs = @document.directives.filter_map(&:output)
|
|
76
|
+
@document.outline.reject { |item| item.is_a?(Document::Heading) && outputs.any? { it.cover?(item.line) } }
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def min_level
|
|
80
|
+
@document.headings.map(&:level).min || 1
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def heading_row(heading)
|
|
84
|
+
folded = @folded.include?(heading.line) ? ' …' : ''
|
|
85
|
+
Row.new(text: "#{'#' * heading.level} #{heading.text}#{folded}", depth: heading.level - min_level, kind: :heading,
|
|
86
|
+
target: heading)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def directive_rows(directive, depth:)
|
|
90
|
+
expanded = @expanded.include?(directive.line)
|
|
91
|
+
row = Row.new(text: directive_text(directive), depth:, kind: :directive, target: directive,
|
|
92
|
+
buttons: buttons(directive, expanded:))
|
|
93
|
+
return [row] unless expanded
|
|
94
|
+
|
|
95
|
+
[row, *directive.output.map do |number|
|
|
96
|
+
Row.new(text: @lines[number - 1].to_s, depth: depth + 1, kind: :output, target: number)
|
|
97
|
+
end]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def buttons(directive, expanded:)
|
|
101
|
+
buttons = []
|
|
102
|
+
buttons << [expanded ? '[-]' : "[+#{directive.output.size}]", :toggle] if directive.output
|
|
103
|
+
buttons << ['[Run]', :execute] if directive.endpoint?
|
|
104
|
+
buttons
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def directive_text(directive)
|
|
108
|
+
return ":#{directive.name}" unless directive.writes
|
|
109
|
+
|
|
110
|
+
[directive.name, ':', (" #{directive.args}" unless directive.args.empty?)].join
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Raindown
|
|
4
|
+
module TUI
|
|
5
|
+
# A pane's cursor and how far it's scrolled, over rows that can change between draws, like when a folder folds.
|
|
6
|
+
class Pane
|
|
7
|
+
attr_writer :cursor
|
|
8
|
+
|
|
9
|
+
def initialize(&rows)
|
|
10
|
+
@rows = rows
|
|
11
|
+
@cursor = 0
|
|
12
|
+
@offset = 0
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def rows = @rows.call
|
|
16
|
+
def selected = rows[cursor]
|
|
17
|
+
|
|
18
|
+
# The cursor stays on a row when there are fewer rows than before.
|
|
19
|
+
def cursor
|
|
20
|
+
@cursor.clamp(0, [rows.length - 1, 0].max)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def move(by)
|
|
24
|
+
@cursor = (cursor + by).clamp(0, [rows.length - 1, 0].max)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def reset
|
|
28
|
+
@cursor = 0
|
|
29
|
+
@offset = 0
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# The rows that fit in the height, scrolled so the cursor's row is one of them, and the first one's index.
|
|
33
|
+
def visible(height)
|
|
34
|
+
cursor = self.cursor
|
|
35
|
+
@offset = @offset.clamp([cursor - height + 1, 0].max, cursor)
|
|
36
|
+
|
|
37
|
+
[rows[@offset, height] || [], @offset]
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Raindown
|
|
4
|
+
module TUI
|
|
5
|
+
# A line of a pane. Target is what it's about: a folder or file path, a Heading or Directive, or a line number.
|
|
6
|
+
# Buttons are [label, event] pairs, like ['[Run]', :execute].
|
|
7
|
+
Row = Data.define(:text, :depth, :kind, :target, :buttons) do
|
|
8
|
+
def initialize(buttons: [], **) = super
|
|
9
|
+
|
|
10
|
+
# The line the editor opens at for the row.
|
|
11
|
+
def line
|
|
12
|
+
target.is_a?(Integer) ? target : target.line
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'curses'
|
|
4
|
+
|
|
5
|
+
require_relative 'input'
|
|
6
|
+
require_relative 'layout'
|
|
7
|
+
require_relative 'styles'
|
|
8
|
+
|
|
9
|
+
module Raindown
|
|
10
|
+
module TUI
|
|
11
|
+
# Paints a Navigator's Layout with curses, and sends the Navigator the events of keys and clicks, read with Input.
|
|
12
|
+
# Only this class draws on the terminal, so another library could draw the same Layout.
|
|
13
|
+
class Screen
|
|
14
|
+
# How often, in milliseconds, the open file is checked for changes while no key is pressed.
|
|
15
|
+
TICK = 500
|
|
16
|
+
|
|
17
|
+
def initialize(navigator)
|
|
18
|
+
@navigator = navigator
|
|
19
|
+
@zones = []
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def run
|
|
23
|
+
start
|
|
24
|
+
|
|
25
|
+
loop do
|
|
26
|
+
draw
|
|
27
|
+
effect = @navigator.handle(read)
|
|
28
|
+
break if effect == :quit
|
|
29
|
+
|
|
30
|
+
perform(*effect) if effect.is_a?(Array)
|
|
31
|
+
end
|
|
32
|
+
rescue Interrupt
|
|
33
|
+
nil
|
|
34
|
+
ensure
|
|
35
|
+
stop
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def perform(name, *args)
|
|
41
|
+
case name
|
|
42
|
+
when :run
|
|
43
|
+
suspend { system(*args.first) }
|
|
44
|
+
@navigator.ran
|
|
45
|
+
when :wait
|
|
46
|
+
message, task = args
|
|
47
|
+
show(message)
|
|
48
|
+
task.call
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def start
|
|
53
|
+
ENV['ESCDELAY'] ||= '25'
|
|
54
|
+
Curses.init_screen
|
|
55
|
+
@styles = Styles.start
|
|
56
|
+
Curses.noecho
|
|
57
|
+
Curses.cbreak
|
|
58
|
+
Curses.nonl
|
|
59
|
+
Curses.curs_set(0)
|
|
60
|
+
Curses.stdscr.keypad(true)
|
|
61
|
+
Curses.stdscr.timeout = TICK
|
|
62
|
+
Curses.mousemask(Curses::BUTTON1_PRESSED | Curses::BUTTON1_CLICKED | Input.wheel.keys.sum)
|
|
63
|
+
Curses.mouseinterval(0)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def stop
|
|
67
|
+
Curses.close_screen
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def draw
|
|
71
|
+
lines = Layout.new(@navigator, width: Curses.cols, height: Curses.lines).lines
|
|
72
|
+
@zones = Input.zones(lines)
|
|
73
|
+
window = Curses.stdscr
|
|
74
|
+
window.erase
|
|
75
|
+
|
|
76
|
+
lines.each_with_index do |segments, row|
|
|
77
|
+
window.setpos(row, 0)
|
|
78
|
+
# Writing the bottom-right corner would scroll the screen, so the last line stops a column short.
|
|
79
|
+
segments = last_line(segments) if row == Curses.lines - 1
|
|
80
|
+
segments.each { |segment| paint(window, segment) }
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
window.refresh
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def paint(window, segment)
|
|
87
|
+
window.attron(@styles.fetch(segment.style, Curses::A_NORMAL)) { window.addstr(segment.text) }
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def last_line(segments)
|
|
91
|
+
*rest, last = segments
|
|
92
|
+
[*rest, last.with(text: last.text[0...-1])]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# The next event, or :tick when no key is pressed in time, or nil for keys without one, like a resize.
|
|
96
|
+
def read
|
|
97
|
+
key = Curses.stdscr.getch
|
|
98
|
+
return :tick if key.nil?
|
|
99
|
+
return mouse if key == Curses::KEY_MOUSE
|
|
100
|
+
|
|
101
|
+
Curses.stdscr.clear if key == Curses::KEY_RESIZE
|
|
102
|
+
Input.key_event(key)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def mouse
|
|
106
|
+
event = Curses.getmouse
|
|
107
|
+
Input.mouse_event(event, @zones) if event
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Shows a message in the status line while something slow runs, like an endpoint's request.
|
|
111
|
+
def show(message)
|
|
112
|
+
window = Curses.stdscr
|
|
113
|
+
window.setpos(Curses.lines - 2, 0)
|
|
114
|
+
window.clrtoeol
|
|
115
|
+
window.addstr(" #{message}"[0, Curses.cols])
|
|
116
|
+
window.refresh
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Leaves the screen to the command, like the editor, and comes back to it after.
|
|
120
|
+
def suspend
|
|
121
|
+
Curses.def_prog_mode
|
|
122
|
+
Curses.close_screen
|
|
123
|
+
yield
|
|
124
|
+
ensure
|
|
125
|
+
Curses.reset_prog_mode
|
|
126
|
+
Curses.stdscr.clear
|
|
127
|
+
Curses.refresh
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'curses'
|
|
4
|
+
|
|
5
|
+
module Raindown
|
|
6
|
+
module TUI
|
|
7
|
+
# The curses attributes of a Layout's styles, in colour on the terminal's own background when it has colours.
|
|
8
|
+
module Styles
|
|
9
|
+
COLORS = { directive: Curses::COLOR_CYAN, button: Curses::COLOR_YELLOW, error: Curses::COLOR_RED,
|
|
10
|
+
folder: Curses::COLOR_BLUE }.freeze
|
|
11
|
+
|
|
12
|
+
module_function
|
|
13
|
+
|
|
14
|
+
# Sets up the colours, once the screen has started, and returns the attribute of each style.
|
|
15
|
+
def start
|
|
16
|
+
colors = Curses.has_colors?
|
|
17
|
+
start_colors if colors
|
|
18
|
+
color = ->(name) { colors ? Curses.color_pair(COLORS.keys.index(name) + 1) : Curses::A_NORMAL }
|
|
19
|
+
|
|
20
|
+
{
|
|
21
|
+
title: Curses::A_REVERSE | Curses::A_BOLD, selected: Curses::A_REVERSE, cursor: Curses::A_UNDERLINE,
|
|
22
|
+
heading: Curses::A_BOLD, directive: color[:directive], output: Curses::A_DIM,
|
|
23
|
+
error: color[:error] | Curses::A_BOLD, button: color[:button] | Curses::A_BOLD,
|
|
24
|
+
selected_button: color[:button] | Curses::A_REVERSE, folder: color[:folder] | Curses::A_BOLD,
|
|
25
|
+
key: Curses::A_REVERSE, border: Curses::A_DIM
|
|
26
|
+
}
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def start_colors
|
|
30
|
+
Curses.start_color
|
|
31
|
+
Curses.use_default_colors
|
|
32
|
+
COLORS.each_value.with_index(1) { |color, pair| Curses.init_pair(pair, color, -1) }
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
data/lib/raindown/tui.rb
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'nodes'
|
|
4
|
+
require_relative 'projects'
|
|
5
|
+
require_relative 'tui/navigator'
|
|
6
|
+
|
|
7
|
+
module Raindown
|
|
8
|
+
# The terminal UI, started with "raindown tui": a project's Markdown files beside the open file's outline,
|
|
9
|
+
# where directives fold, endpoints run and the editor opens at a line. Curses only loads here,
|
|
10
|
+
# so watching and rendering start without it.
|
|
11
|
+
module TUI
|
|
12
|
+
module_function
|
|
13
|
+
|
|
14
|
+
# PATH is a file to open, or a directory. Its project is the one it's in, or else the directory itself.
|
|
15
|
+
def start(path)
|
|
16
|
+
require_relative 'tui/screen'
|
|
17
|
+
# Without a terminal, curses' own error is "Error opening terminal: unknown".
|
|
18
|
+
abort('raindown tui needs a terminal') unless $stdin.tty? && $stdout.tty?
|
|
19
|
+
|
|
20
|
+
path = File.expand_path(path)
|
|
21
|
+
root = Projects.root(path) || (File.directory?(path) ? path : File.dirname(path))
|
|
22
|
+
Nodes.load(File.join(root, Nodes::FOLDER))
|
|
23
|
+
|
|
24
|
+
Screen.new(Navigator.new(root:, path: (path unless File.directory?(path)))).run
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
data/lib/raindown/watcher.rb
CHANGED
|
@@ -4,12 +4,12 @@ require_relative '../raindown'
|
|
|
4
4
|
require_relative 'rewriter'
|
|
5
5
|
|
|
6
6
|
module Raindown
|
|
7
|
+
# Watches one file and writes back to it as it's saved, like its TOC, tables and endpoint responses.
|
|
7
8
|
class Watcher
|
|
8
|
-
attr_reader :path, :
|
|
9
|
+
attr_reader :path, :bare, :execute
|
|
9
10
|
|
|
10
|
-
def initialize(path:,
|
|
11
|
+
def initialize(path:, bare: false, execute: false)
|
|
11
12
|
@path = path
|
|
12
|
-
@output = output || default_output
|
|
13
13
|
@bare = bare
|
|
14
14
|
@execute = execute
|
|
15
15
|
end
|
|
@@ -19,11 +19,8 @@ module Raindown
|
|
|
19
19
|
|
|
20
20
|
$stdout.sync = true
|
|
21
21
|
|
|
22
|
-
safely
|
|
23
|
-
|
|
24
|
-
render
|
|
25
|
-
end
|
|
26
|
-
puts "Watching #{path} for changes (writing to #{output})..."
|
|
22
|
+
safely { rewrite }
|
|
23
|
+
puts "Watching #{path} for changes..."
|
|
27
24
|
|
|
28
25
|
listener.start
|
|
29
26
|
sleep
|
|
@@ -38,13 +35,8 @@ module Raindown
|
|
|
38
35
|
Listen.to(directory) do |modified, added, _removed|
|
|
39
36
|
next unless (modified + added).any? { |f| File.basename(f) == filename }
|
|
40
37
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
next if rewrite
|
|
44
|
-
|
|
45
|
-
render
|
|
46
|
-
puts "Re-rendered #{path} -> #{output}"
|
|
47
|
-
end
|
|
38
|
+
# Writing back saves the file again, and that save changes nothing, so it ends there.
|
|
39
|
+
safely { puts "Updated #{path}" if rewrite }
|
|
48
40
|
end
|
|
49
41
|
end
|
|
50
42
|
|
|
@@ -61,13 +53,5 @@ module Raindown
|
|
|
61
53
|
def rewrite
|
|
62
54
|
Rewriter.update(path:, bare:, execute:, metadata: Pages.for(path))
|
|
63
55
|
end
|
|
64
|
-
|
|
65
|
-
def render
|
|
66
|
-
File.write(output, Raindown.render_file(path:, bare:, metadata: Pages.for(path)))
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def default_output
|
|
70
|
-
"#{File.dirname(path)}/#{File.basename(path, '.*')}.html"
|
|
71
|
-
end
|
|
72
56
|
end
|
|
73
57
|
end
|
data/lib/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: raindown
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- maedi
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-10-
|
|
10
|
+
date: 2026-10-26 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: antlers
|
|
@@ -51,6 +51,20 @@ dependencies:
|
|
|
51
51
|
- - ">="
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
53
|
version: '0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: curses
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '1.7'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '1.7'
|
|
54
68
|
- !ruby/object:Gem::Dependency
|
|
55
69
|
name: dirload
|
|
56
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -167,6 +181,7 @@ files:
|
|
|
167
181
|
- lib/nodes/endpoint_node.rb
|
|
168
182
|
- lib/nodes/list_node.rb
|
|
169
183
|
- lib/raindown.rb
|
|
184
|
+
- lib/raindown/actions.rb
|
|
170
185
|
- lib/raindown/bare_directives.rb
|
|
171
186
|
- lib/raindown/chart/bars.rb
|
|
172
187
|
- lib/raindown/chart/chart.rb
|
|
@@ -180,6 +195,7 @@ files:
|
|
|
180
195
|
- lib/raindown/code_blocks.rb
|
|
181
196
|
- lib/raindown/config.rb
|
|
182
197
|
- lib/raindown/directives.rb
|
|
198
|
+
- lib/raindown/document.rb
|
|
183
199
|
- lib/raindown/endpoint/curl.rb
|
|
184
200
|
- lib/raindown/endpoint/endpoint_runner.rb
|
|
185
201
|
- lib/raindown/files.rb
|
|
@@ -193,9 +209,23 @@ files:
|
|
|
193
209
|
- lib/raindown/page.rb
|
|
194
210
|
- lib/raindown/pages.rb
|
|
195
211
|
- lib/raindown/pre_renderer.rb
|
|
212
|
+
- lib/raindown/project_worker.rb
|
|
213
|
+
- lib/raindown/projects.rb
|
|
196
214
|
- lib/raindown/rewriter.rb
|
|
215
|
+
- lib/raindown/supervisor.rb
|
|
197
216
|
- lib/raindown/table_formatter.rb
|
|
198
217
|
- lib/raindown/toc.rb
|
|
218
|
+
- lib/raindown/tui.rb
|
|
219
|
+
- lib/raindown/tui/commands.rb
|
|
220
|
+
- lib/raindown/tui/file_tree.rb
|
|
221
|
+
- lib/raindown/tui/input.rb
|
|
222
|
+
- lib/raindown/tui/layout.rb
|
|
223
|
+
- lib/raindown/tui/navigator.rb
|
|
224
|
+
- lib/raindown/tui/outline.rb
|
|
225
|
+
- lib/raindown/tui/pane.rb
|
|
226
|
+
- lib/raindown/tui/row.rb
|
|
227
|
+
- lib/raindown/tui/screen.rb
|
|
228
|
+
- lib/raindown/tui/styles.rb
|
|
199
229
|
- lib/raindown/variables.rb
|
|
200
230
|
- lib/raindown/watcher.rb
|
|
201
231
|
- lib/version.rb
|