raindown 0.7.0 → 0.8.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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nodes/endpoint_node.rb +3 -2
  3. data/lib/raindown/actions.rb +5 -3
  4. data/lib/raindown/bare_directives.rb +14 -27
  5. data/lib/raindown/blueprints.rb +255 -0
  6. data/lib/raindown/cli.rb +39 -54
  7. data/lib/raindown/config.rb +2 -3
  8. data/lib/raindown/directives.rb +30 -13
  9. data/lib/raindown/document.rb +21 -15
  10. data/lib/raindown/endpoint/endpoint_runner.rb +13 -5
  11. data/lib/raindown/node_blocks.rb +22 -16
  12. data/lib/raindown/node_injector.rb +7 -10
  13. data/lib/raindown/pages.rb +1 -1
  14. data/lib/raindown/pre_renderer.rb +18 -0
  15. data/lib/raindown/tui/blueprints/blueprints_renderer.rb +93 -0
  16. data/lib/raindown/tui/blueprints/blueprints_view.rb +146 -0
  17. data/lib/raindown/tui/blueprints/canvas.rb +58 -0
  18. data/lib/raindown/tui/blueprints/code_comments.rb +71 -0
  19. data/lib/raindown/tui/blueprints/filter.rb +77 -0
  20. data/lib/raindown/tui/blueprints/traced_code.rb +56 -0
  21. data/lib/raindown/tui/blueprints/tracing.rb +129 -0
  22. data/lib/raindown/tui/{feelings/code_box.rb → code_box.rb} +44 -30
  23. data/lib/raindown/tui/endpoints.rb +2 -2
  24. data/lib/raindown/tui/events.rb +3 -1
  25. data/lib/raindown/tui/feelings/bins.rb +5 -5
  26. data/lib/raindown/tui/feelings/{celebration.rb → celebration/celebration.rb} +5 -2
  27. data/lib/raindown/tui/feelings/{scene.rb → celebration/scene.rb} +4 -1
  28. data/lib/raindown/tui/feelings/cell_moves.rb +34 -0
  29. data/lib/raindown/tui/feelings/feelings_code_box.rb +40 -0
  30. data/lib/raindown/tui/feelings/feelings_log.rb +22 -19
  31. data/lib/raindown/tui/feelings/feelings_renderer.rb +94 -95
  32. data/lib/raindown/tui/feelings/feelings_view.rb +28 -32
  33. data/lib/raindown/tui/feelings/magnifier.rb +68 -0
  34. data/lib/raindown/tui/feelings/motion.rb +93 -0
  35. data/lib/raindown/tui/feelings/waffle/baked_waffle.rb +88 -0
  36. data/lib/raindown/tui/feelings/waffle/balloons.rb +81 -0
  37. data/lib/raindown/tui/feelings/waffle/confetti.rb +55 -0
  38. data/lib/raindown/tui/feelings/waffle/sparkles.rb +61 -0
  39. data/lib/raindown/tui/feelings/waffle/waffle.rb +62 -0
  40. data/lib/raindown/tui/feelings/weekly_batch.rb +24 -5
  41. data/lib/raindown/tui/layout.rb +25 -18
  42. data/lib/raindown/tui/navigator/commands.rb +32 -1
  43. data/lib/raindown/tui/navigator/mouse.rb +43 -0
  44. data/lib/raindown/tui/navigator/navigator.rb +40 -44
  45. data/lib/raindown/tui/navigator/{search.rb → teleport.rb} +14 -12
  46. data/lib/raindown/tui/navigator/views.rb +2 -3
  47. data/lib/raindown/tui/{workers/project.rb → project.rb} +33 -22
  48. data/lib/raindown/tui/{menu_overlay.rb → project_box.rb} +1 -1
  49. data/lib/raindown/tui/renderers/renderer.rb +1 -0
  50. data/lib/raindown/tui/saves.rb +22 -0
  51. data/lib/raindown/tui/{search_overlay.rb → search_box.rb} +27 -14
  52. data/lib/raindown/tui/terminal/input.rb +58 -7
  53. data/lib/raindown/tui/terminal/screen.rb +31 -26
  54. data/lib/raindown/tui/terminal/styles.rb +55 -28
  55. data/lib/raindown/tui/terminal/terminal_title.rb +31 -0
  56. data/lib/raindown/tui/text.rb +35 -12
  57. data/lib/raindown/tui/views/dashboard_view.rb +2 -2
  58. data/lib/raindown/tui/views/endpoint_view.rb +3 -3
  59. data/lib/raindown/tui/views/list_view.rb +1 -1
  60. data/lib/raindown/tui/views/outline_view.rb +5 -4
  61. data/lib/raindown/tui.rb +17 -7
  62. data/lib/raindown/watcher/changes.rb +33 -0
  63. data/lib/raindown/watcher/file_watcher.rb +58 -0
  64. data/lib/raindown/watcher/project.rb +47 -0
  65. data/lib/raindown/watcher/supervisor.rb +111 -0
  66. data/lib/raindown/{tui/workers → workers}/worker.rb +37 -29
  67. data/lib/raindown/workers/workers.rb +63 -0
  68. data/lib/raindown.rb +4 -4
  69. data/lib/version.rb +1 -1
  70. metadata +37 -17
  71. data/lib/raindown/project_worker.rb +0 -48
  72. data/lib/raindown/supervisor.rb +0 -160
  73. data/lib/raindown/tui/feelings/waffle.rb +0 -43
  74. data/lib/raindown/tui/workers/workers.rb +0 -53
  75. data/lib/raindown/watcher.rb +0 -57
  76. /data/lib/raindown/tui/feelings/{fireworks.rb → celebration/fireworks.rb} +0 -0
  77. /data/lib/raindown/tui/feelings/{rain.rb → celebration/rain.rb} +0 -0
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../raindown'
4
+ require_relative '../rewriter'
5
+
6
+ module Raindown
7
+ module Watcher
8
+ # Writes back to one project's Markdown files as they're saved, like its TOCs, tables and endpoint responses,
9
+ # with the project's own nodes, in its Workers::Worker. Each line it shows starts with the project's name.
10
+ class Project
11
+ attr_reader :root, :name
12
+
13
+ def initialize(root:, name: File.basename(root), bare: false, execute: false)
14
+ @root = root
15
+ @name = name
16
+ @bare = bare
17
+ @execute = execute
18
+ end
19
+
20
+ # Loads the project's nodes from its .raindown folder.
21
+ def start
22
+ Nodes.load(File.join(root, Nodes::FOLDER))
23
+ rescue StandardError, ScriptError => e
24
+ raise if ENV['RAINDOWN_DEBUG']
25
+
26
+ warn "[#{name}] raindown: #{Nodes::FOLDER}: #{e.message}"
27
+ end
28
+
29
+ # Writing back saves the file again, and that save changes nothing, so it ends there.
30
+ def update(path)
31
+ changed = Rewriter.update(path:, bare: @bare, execute: @execute, metadata: Pages.for(path))
32
+ puts "[#{name}] Updated #{relative(path)}" if changed
33
+ rescue StandardError => e
34
+ raise if ENV['RAINDOWN_DEBUG']
35
+
36
+ # An error in the file is shown rather than stopping the watcher, so it can be fixed and saved again.
37
+ warn "[#{name}] raindown: #{relative(path)}: #{e.message}"
38
+ end
39
+
40
+ private
41
+
42
+ def relative(path)
43
+ File.expand_path(path).delete_prefix(File.join(root, ''))
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../projects'
4
+ require_relative '../workers/workers'
5
+ require_relative 'changes'
6
+ require_relative 'project'
7
+
8
+ module Raindown
9
+ module Watcher
10
+ # Watches every Raindown project in a directory, like ~/dev, and writes back to each Markdown file as it's saved.
11
+ #
12
+ # Each project's nodes load in a process of its own, forked once the shared code has loaded, so starting a project
13
+ # costs almost nothing and two projects can have nodes of the same name. One listener watches the directory and
14
+ # sends each changed file to its project's process. Without fork, as on Windows, the projects share this process.
15
+ class Supervisor
16
+ attr_reader :directory, :workers
17
+
18
+ def initialize(directory:, bare: false, execute: false)
19
+ @directory = File.expand_path(directory)
20
+ @workers = Workers.new(root: @directory, fork: fork?, quiet: false) do |root|
21
+ Project.new(root:, name: name(root), bare:, execute:).tap(&:start)
22
+ end
23
+ @queues = {}
24
+ end
25
+
26
+ def start
27
+ $stdout.sync = true
28
+ preload
29
+
30
+ projects = Projects.roots(directory).each { workers[it].start }
31
+ puts "Watching #{projects.size} #{projects.size == 1 ? 'project' : 'projects'} in #{directory} for changes..."
32
+
33
+ trap_interrupt
34
+ Watcher.listen(directory) { handle(it) }.start
35
+ sleep
36
+ ensure
37
+ stop
38
+ end
39
+
40
+ # Sends each saved file to its project, starting a worker for a new project, or restarting one when its nodes
41
+ # change. With fork, each project takes its changes in order in a thread of its own, so a slow write-back, like an
42
+ # endpoint's request with -x, only holds up its own project. Without fork, the projects share this process, so
43
+ # they're taken in turn.
44
+ def handle(paths)
45
+ Watcher.changes(paths).each do |change|
46
+ next unless change.nodes? || change.saved?
47
+ next take(change) unless fork?
48
+
49
+ queue(change.root) << change
50
+ end
51
+ end
52
+
53
+ def stop
54
+ @queues.each_value(&:close)
55
+ workers.stop
56
+ end
57
+
58
+ private
59
+
60
+ # The project's changes still to take, by the thread that takes them, until the queue's closed.
61
+ def queue(root)
62
+ @queues[root] ||= Thread::Queue.new.tap do |queue|
63
+ Thread.new { while (change = queue.pop) do take(change) end }
64
+ end
65
+ end
66
+
67
+ # An error, like a worker stopping partway from a crash, is shown, and the project takes its next change, its
68
+ # worker starting again.
69
+ def take(change)
70
+ return restart(change.root) if change.nodes?
71
+
72
+ workers[change.root].call(:update, change.path)
73
+ rescue StandardError => e
74
+ warn "[#{name(change.root)}] raindown: #{e.message}"
75
+ end
76
+
77
+ # Without fork the projects share this process, where nodes can't be unloaded.
78
+ def restart(root)
79
+ return warn("[#{name(root)}] Restart raindown to load the node changes") unless fork?
80
+ return unless workers.restart(root)
81
+
82
+ puts "[#{name(root)}] Reloading nodes"
83
+ workers[root].start
84
+ end
85
+
86
+ # A project in the directory is named by its path from there, and the project the directory is in by its folder.
87
+ def name(root)
88
+ return File.basename(root) unless root.start_with?(File.join(directory, ''))
89
+
90
+ root.delete_prefix(File.join(directory, ''))
91
+ end
92
+
93
+ # Loaded before forking, so every project's process shares them instead of loading its own.
94
+ def preload
95
+ return unless fork?
96
+
97
+ require 'lownode'
98
+ require 'dirload'
99
+ end
100
+
101
+ def fork?
102
+ Process.respond_to?(:fork)
103
+ end
104
+
105
+ # Ctrl+C reaches every process in the terminal, so the workers stop with the watcher.
106
+ def trap_interrupt
107
+ trap('INT') { exit }
108
+ end
109
+ end
110
+ end
111
+ end
@@ -1,13 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'project'
4
-
5
3
  module Raindown
6
- module TUI
7
- # A Project in a process of its own, forked so it loads the project's nodes apart from other projects', like watching.
4
+ class Workers
5
+ # What answers a project's requests, made by the block, like the terminal UI's Project, or a Watcher::Project when
6
+ # watching, in a process of its own, forked so it loads the project's nodes apart from other projects'.
8
7
  # Requests and answers go through two pipes, as Marshal data, one at a time. Without fork, like on Windows,
9
- # or with fork off, like in specs, the Project answers in this process instead.
10
- # The process ends with exit!, since it's forked mid-call, so the terminal UI's ensure doesn't run in it.
8
+ # or with fork off, like in specs, it answers in this process instead. A quiet worker writes nothing, as the terminal
9
+ # UI's screen is its own. The process ends with exit!, since it's forked mid-call, so the parent's ensure doesn't run.
11
10
  class Worker
12
11
  class Error < StandardError; end
13
12
 
@@ -27,12 +26,14 @@ module Raindown
27
26
 
28
27
  attr_reader :root
29
28
 
30
- def initialize(root:, fork: self.class.fork?)
29
+ def initialize(root:, fork: self.class.fork?, quiet: true, &answering)
31
30
  @root = root
32
31
  @fork = fork
32
+ @quiet = quiet
33
+ @answering = answering
33
34
  end
34
35
 
35
- # The Project's answer, or a Worker::Error with its error's message. A worker that stopped starts again.
36
+ # The answer, or a Worker::Error with its error's message. A worker that stopped starts again.
36
37
  def call(name, *args, **options)
37
38
  return local(name, args, options) unless @fork
38
39
 
@@ -54,21 +55,12 @@ module Raindown
54
55
  @pid = nil
55
56
  end
56
57
 
57
- private
58
-
59
- def local(name, args, options)
60
- @project ||= Project.new(root:)
61
- @project.public_send(name, *args, **options)
62
- rescue StandardError => e
63
- raise Error, e.message
64
- end
65
-
58
+ # Starts the worker's process, or makes what answers in this one, so it's ready before the first request.
66
59
  def start
60
+ return @answerer ||= @answering.call unless @fork
61
+
67
62
  stop
68
- requests, @requests = IO.pipe
69
- @answers, answers = IO.pipe
70
- self.class.pipes.reject!(&:closed?)
71
- self.class.pipes.push(@requests, @answers)
63
+ requests, answers = open_pipes
72
64
  @pid = fork do
73
65
  self.class.pipes.each { it.close unless it.closed? }
74
66
  serve(requests, answers)
@@ -77,23 +69,39 @@ module Raindown
77
69
  answers.close
78
70
  end
79
71
 
80
- # Answers until the terminal UI closes its end. The screen is the terminal UI's, so nothing is written to it,
81
- # and Ctrl+C, which reaches every process in the terminal, is the terminal UI's to handle.
72
+ private
73
+
74
+ # The worker's ends of the pipes, while this process keeps the others.
75
+ def open_pipes
76
+ requests, @requests = IO.pipe
77
+ @answers, answers = IO.pipe
78
+ self.class.pipes.reject!(&:closed?)
79
+ self.class.pipes.push(@requests, @answers)
80
+ [requests, answers]
81
+ end
82
+
83
+ def local(name, args, options)
84
+ start.public_send(name, *args, **options)
85
+ rescue StandardError => e
86
+ raise Error, e.message
87
+ end
88
+
89
+ # Answers until the parent closes its end. Ctrl+C, which reaches every process in the terminal, is the parent's to
90
+ # handle, stopping its workers.
82
91
  def serve(requests, answers)
83
92
  trap('INT', 'IGNORE')
84
- $stdout.reopen(File::NULL)
85
- $stderr.reopen(File::NULL)
86
- project = Project.new(root:)
93
+ [$stdout, $stderr].each { it.reopen(File::NULL) } if @quiet
94
+ answerer = @answering.call
87
95
 
88
96
  while (request = read(requests))
89
- write(answers, answer(project, *request))
97
+ write(answers, answer(answerer, *request))
90
98
  end
91
99
  ensure
92
100
  exit!(0)
93
101
  end
94
102
 
95
- def answer(project, name, args, options)
96
- [:ok, project.public_send(name, *args, **options)]
103
+ def answer(answerer, name, args, options)
104
+ [:ok, answerer.public_send(name, *args, **options)]
97
105
  rescue StandardError, ScriptError => e
98
106
  [:error, e.message]
99
107
  end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../projects'
4
+ require_relative 'worker'
5
+
6
+ module Raindown
7
+ # A Worker for each project in a folder: the folder's own, and every project inside it, each answering with what the
8
+ # block makes from its root, like the terminal UI's Project. A file's requests go to the worker of the project it's in,
9
+ # the nearest one above it, even when it's new, or else the folder's. Workers start when they're first asked something.
10
+ class Workers
11
+ attr_reader :root
12
+
13
+ def initialize(root:, fork: Worker.fork?, quiet: true, &answering)
14
+ @root = root
15
+ @fork = fork
16
+ @quiet = quiet
17
+ @answering = answering
18
+ @workers = {}
19
+ end
20
+
21
+ def for(path) = self[Projects.root(path) || root]
22
+
23
+ def [](project)
24
+ @workers[project] ||= Worker.new(root: project, fork: @fork, quiet: @quiet) { @answering.call(project) }
25
+ end
26
+
27
+ # The folder's project and those inside it, found when they're first asked for, and again after a restart.
28
+ def roots = @roots ||= [root, *Projects.roots(root)].uniq.sort
29
+
30
+ # A worker for each project, as they were found when the workers last started.
31
+ def each(&)
32
+ roots.map { self[it] }.each(&)
33
+ end
34
+
35
+ # The workers asked something, by their project's root.
36
+ def started = @workers.dup
37
+
38
+ # Stops the project's worker, so its next request starts it again, loading its nodes again, and returns whether it
39
+ # had started. Without a project, they all stop, and the projects are found again, like ones added since.
40
+ def restart(project = nil)
41
+ return restart_project(project) if project
42
+
43
+ stop
44
+ @roots = nil
45
+ end
46
+
47
+ # Stops the workers, so the next requests start them again.
48
+ def stop
49
+ @workers.each_value(&:stop)
50
+ @workers.clear
51
+ end
52
+
53
+ private
54
+
55
+ def restart_project(project)
56
+ worker = @workers.delete(project)
57
+ return false unless worker
58
+
59
+ worker.stop
60
+ true
61
+ end
62
+ end
63
+ end
data/lib/raindown.rb CHANGED
@@ -37,16 +37,16 @@ module Raindown
37
37
 
38
38
  module_function
39
39
 
40
- # Directives show in bold and code is highlighted, unless the file's project changes them in .raindown/config.yml.
40
+ # Code is highlighted, unless the file's project changes it in .raindown/config.yml.
41
41
  def render_file(path:, metadata: NoMetadata, bare: false, **options)
42
42
  options = Config.render_options(path).merge(options)
43
43
  render(markdown: File.read(path, encoding: Encoding::UTF_8), metadata:, bare: bare || BareDirectives.file?(path), **options)
44
44
  end
45
45
 
46
46
  # Front matter keys are variables, like {title} or <{ title }>.
47
- # Directives like "toc:" export to HTML as bold or comments depending on hide_directives config.
47
+ # Bare directives like "toc:" show in bold in the HTML, and the rest stay hidden, as comments.
48
48
  # Code blocks are highlighted, unless highlight_code is false for a site that highlights code in the browser.
49
- def render(markdown:, metadata: NoMetadata, bare: false, hide_directives: false, highlight_code: true)
49
+ def render(markdown:, metadata: NoMetadata, bare: false, highlight_code: true)
50
50
  bare ||= BareDirectives.front_matter?(markdown)
51
51
 
52
52
  highlighting(highlight_code) do
@@ -55,7 +55,7 @@ module Raindown
55
55
  html = assembled(markdown:, metadata:, bare:)
56
56
  html = Nodes.render_placeholders(html, document: markdown, metadata:, bare:, html:)
57
57
 
58
- Directives.render("#{html.chomp}\n", hide: hide_directives)
58
+ Directives.render("#{html.chomp}\n")
59
59
  end
60
60
  end
61
61
  end
data/lib/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Raindown
4
- VERSION = '0.7.0'
4
+ VERSION = '0.8.0'
5
5
  end
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.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - maedi
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-10-28 00:00:00.000000000 Z
10
+ date: 2026-11-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: antlers
@@ -197,6 +197,7 @@ files:
197
197
  - lib/raindown.rb
198
198
  - lib/raindown/actions.rb
199
199
  - lib/raindown/bare_directives.rb
200
+ - lib/raindown/blueprints.rb
200
201
  - lib/raindown/chart/bars.rb
201
202
  - lib/raindown/chart/chart.rb
202
203
  - lib/raindown/chart/columns.rb
@@ -223,41 +224,56 @@ files:
223
224
  - lib/raindown/page.rb
224
225
  - lib/raindown/pages.rb
225
226
  - lib/raindown/pre_renderer.rb
226
- - lib/raindown/project_worker.rb
227
227
  - lib/raindown/projects.rb
228
228
  - lib/raindown/rewriter.rb
229
229
  - lib/raindown/stat.rb
230
- - lib/raindown/supervisor.rb
231
230
  - lib/raindown/table_formatter.rb
232
231
  - lib/raindown/toc.rb
233
232
  - lib/raindown/tui.rb
233
+ - lib/raindown/tui/blueprints/blueprints_renderer.rb
234
+ - lib/raindown/tui/blueprints/blueprints_view.rb
235
+ - lib/raindown/tui/blueprints/canvas.rb
236
+ - lib/raindown/tui/blueprints/code_comments.rb
237
+ - lib/raindown/tui/blueprints/filter.rb
238
+ - lib/raindown/tui/blueprints/traced_code.rb
239
+ - lib/raindown/tui/blueprints/tracing.rb
234
240
  - lib/raindown/tui/card.rb
241
+ - lib/raindown/tui/code_box.rb
235
242
  - lib/raindown/tui/endpoint.rb
236
243
  - lib/raindown/tui/endpoints.rb
237
244
  - lib/raindown/tui/events.rb
238
245
  - lib/raindown/tui/feelings/batch.rb
239
246
  - lib/raindown/tui/feelings/bins.rb
240
- - lib/raindown/tui/feelings/celebration.rb
241
- - lib/raindown/tui/feelings/code_box.rb
247
+ - lib/raindown/tui/feelings/celebration/celebration.rb
248
+ - lib/raindown/tui/feelings/celebration/fireworks.rb
249
+ - lib/raindown/tui/feelings/celebration/rain.rb
250
+ - lib/raindown/tui/feelings/celebration/scene.rb
251
+ - lib/raindown/tui/feelings/cell_moves.rb
242
252
  - lib/raindown/tui/feelings/code_methods.rb
253
+ - lib/raindown/tui/feelings/feelings_code_box.rb
243
254
  - lib/raindown/tui/feelings/feelings_log.rb
244
255
  - lib/raindown/tui/feelings/feelings_renderer.rb
245
256
  - lib/raindown/tui/feelings/feelings_view.rb
246
- - lib/raindown/tui/feelings/fireworks.rb
247
- - lib/raindown/tui/feelings/rain.rb
248
- - lib/raindown/tui/feelings/scene.rb
249
- - lib/raindown/tui/feelings/waffle.rb
257
+ - lib/raindown/tui/feelings/magnifier.rb
258
+ - lib/raindown/tui/feelings/motion.rb
259
+ - lib/raindown/tui/feelings/waffle/baked_waffle.rb
260
+ - lib/raindown/tui/feelings/waffle/balloons.rb
261
+ - lib/raindown/tui/feelings/waffle/confetti.rb
262
+ - lib/raindown/tui/feelings/waffle/sparkles.rb
263
+ - lib/raindown/tui/feelings/waffle/waffle.rb
250
264
  - lib/raindown/tui/feelings/weekly_batch.rb
251
265
  - lib/raindown/tui/file_tree.rb
252
266
  - lib/raindown/tui/highlighter.rb
253
267
  - lib/raindown/tui/layout.rb
254
- - lib/raindown/tui/menu_overlay.rb
255
268
  - lib/raindown/tui/navigator/commands.rb
256
269
  - lib/raindown/tui/navigator/focus.rb
270
+ - lib/raindown/tui/navigator/mouse.rb
257
271
  - lib/raindown/tui/navigator/navigator.rb
258
272
  - lib/raindown/tui/navigator/project_menu.rb
259
- - lib/raindown/tui/navigator/search.rb
273
+ - lib/raindown/tui/navigator/teleport.rb
260
274
  - lib/raindown/tui/navigator/views.rb
275
+ - lib/raindown/tui/project.rb
276
+ - lib/raindown/tui/project_box.rb
261
277
  - lib/raindown/tui/renderers/dashboard_renderer.rb
262
278
  - lib/raindown/tui/renderers/endpoint_renderer.rb
263
279
  - lib/raindown/tui/renderers/list_renderer.rb
@@ -265,23 +281,27 @@ files:
265
281
  - lib/raindown/tui/renderers/renderer.rb
266
282
  - lib/raindown/tui/row.rb
267
283
  - lib/raindown/tui/rows.rb
268
- - lib/raindown/tui/search_overlay.rb
284
+ - lib/raindown/tui/saves.rb
285
+ - lib/raindown/tui/search_box.rb
269
286
  - lib/raindown/tui/terminal/input.rb
270
287
  - lib/raindown/tui/terminal/ncurses_shim.rb
271
288
  - lib/raindown/tui/terminal/quiet.rb
272
289
  - lib/raindown/tui/terminal/screen.rb
273
290
  - lib/raindown/tui/terminal/styles.rb
291
+ - lib/raindown/tui/terminal/terminal_title.rb
274
292
  - lib/raindown/tui/text.rb
275
293
  - lib/raindown/tui/title.rb
276
294
  - lib/raindown/tui/views/dashboard_view.rb
277
295
  - lib/raindown/tui/views/endpoint_view.rb
278
296
  - lib/raindown/tui/views/list_view.rb
279
297
  - lib/raindown/tui/views/outline_view.rb
280
- - lib/raindown/tui/workers/project.rb
281
- - lib/raindown/tui/workers/worker.rb
282
- - lib/raindown/tui/workers/workers.rb
283
298
  - lib/raindown/variables.rb
284
- - lib/raindown/watcher.rb
299
+ - lib/raindown/watcher/changes.rb
300
+ - lib/raindown/watcher/file_watcher.rb
301
+ - lib/raindown/watcher/project.rb
302
+ - lib/raindown/watcher/supervisor.rb
303
+ - lib/raindown/workers/worker.rb
304
+ - lib/raindown/workers/workers.rb
285
305
  - lib/version.rb
286
306
  homepage: https://github.com/raindeer-rb/raindown
287
307
  licenses: []
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../raindown'
4
- require_relative 'rewriter'
5
-
6
- module Raindown
7
- # Writes back to one project's Markdown files as they're saved, like its TOCs, tables and endpoint responses,
8
- # with the project's own nodes. Each line it shows starts with the project's name.
9
- class ProjectWorker
10
- attr_reader :root, :name
11
-
12
- def initialize(root:, name: File.basename(root), bare: false, execute: false)
13
- @root = root
14
- @name = name
15
- @bare = bare
16
- @execute = execute
17
- end
18
-
19
- # Loads the project's nodes from its .raindown folder.
20
- def start
21
- Nodes.load(File.join(root, Nodes::FOLDER))
22
- rescue StandardError, ScriptError => e
23
- raise if ENV['RAINDOWN_DEBUG']
24
-
25
- warn "[#{name}] raindown: #{Nodes::FOLDER}: #{e.message}"
26
- end
27
-
28
- # Writing back saves the file again, and that save changes nothing, so it ends there.
29
- def update(path)
30
- changed = Rewriter.update(path:, bare: @bare, execute: @execute, metadata: Pages.for(path))
31
- puts "[#{name}] Updated #{relative(path)}" if changed
32
- rescue StandardError => e
33
- raise if ENV['RAINDOWN_DEBUG']
34
-
35
- # An error in the file is shown rather than stopping the watcher, so it can be fixed and saved again.
36
- warn "[#{name}] raindown: #{relative(path)}: #{e.message}"
37
- end
38
-
39
- # Workers in this process have nothing to stop, unlike a ForkedWorker's process.
40
- def stop; end
41
-
42
- private
43
-
44
- def relative(path)
45
- File.expand_path(path).delete_prefix(File.join(root, ''))
46
- end
47
- end
48
- end