raindown 0.5.1 → 0.6.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/cli.rb +2 -2
- data/lib/raindown/document.rb +15 -4
- data/lib/raindown/endpoint/curl.rb +15 -0
- data/lib/raindown/projects.rb +8 -4
- data/lib/raindown/tui/card.rb +56 -0
- data/lib/raindown/tui/endpoint.rb +16 -0
- data/lib/raindown/tui/endpoints.rb +40 -0
- data/lib/raindown/tui/events.rb +35 -0
- data/lib/raindown/tui/file_tree.rb +53 -11
- data/lib/raindown/tui/layout.rb +60 -78
- data/lib/raindown/tui/menu_overlay.rb +59 -0
- data/lib/raindown/tui/navigator/commands.rb +84 -0
- data/lib/raindown/tui/navigator/focus.rb +25 -0
- data/lib/raindown/tui/navigator/navigator.rb +127 -0
- data/lib/raindown/tui/navigator/project_menu.rb +61 -0
- data/lib/raindown/tui/navigator/views.rb +49 -0
- data/lib/raindown/tui/renderers/dashboard_renderer.rb +102 -0
- data/lib/raindown/tui/renderers/endpoint_renderer.rb +77 -0
- data/lib/raindown/tui/renderers/list_renderer.rb +15 -0
- data/lib/raindown/tui/renderers/outline_renderer.rb +21 -0
- data/lib/raindown/tui/renderers/renderer.rb +15 -0
- data/lib/raindown/tui/row.rb +10 -3
- data/lib/raindown/tui/rows.rb +57 -0
- data/lib/raindown/tui/{input.rb → terminal/input.rb} +10 -11
- data/lib/raindown/tui/terminal/ncurses_shim.rb +46 -0
- data/lib/raindown/tui/terminal/quiet.rb +32 -0
- data/lib/raindown/tui/{screen.rb → terminal/screen.rb} +32 -17
- data/lib/raindown/tui/terminal/styles.rb +96 -0
- data/lib/raindown/tui/text.rb +83 -0
- data/lib/raindown/tui/title.rb +29 -0
- data/lib/raindown/tui/views/dashboard_view.rb +145 -0
- data/lib/raindown/tui/views/endpoint_view.rb +75 -0
- data/lib/raindown/tui/{pane.rb → views/list_view.rb} +9 -8
- data/lib/raindown/tui/{outline.rb → views/outline_view.rb} +39 -20
- data/lib/raindown/tui/workers/project.rb +122 -0
- data/lib/raindown/tui/workers/worker.rb +124 -0
- data/lib/raindown/tui/workers/workers.rb +53 -0
- data/lib/raindown/tui.rb +8 -5
- data/lib/version.rb +1 -1
- metadata +32 -9
- data/lib/raindown/tui/commands.rb +0 -70
- data/lib/raindown/tui/navigator.rb +0 -123
- data/lib/raindown/tui/styles.rb +0 -36
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative 'file_tree'
|
|
4
|
-
require_relative 'commands'
|
|
5
|
-
require_relative 'outline'
|
|
6
|
-
require_relative 'pane'
|
|
7
|
-
|
|
8
|
-
module Raindown
|
|
9
|
-
module TUI
|
|
10
|
-
# What the terminal UI shows and does, in plain Ruby, with no terminal: a FileTree of the project's Markdown files,
|
|
11
|
-
# beside the open file's Outline. The Screen draws it and sends it events, like :down or
|
|
12
|
-
# [:press, :outline, 3, :execute], and handle returns what the Screen should do next:
|
|
13
|
-
# nil draw again
|
|
14
|
-
# :quit stop
|
|
15
|
-
# [:run, command] leave the screen to run a command, like the editor, then call ran
|
|
16
|
-
# [:wait, message, task] show the message while the task runs, like an endpoint's request
|
|
17
|
-
class Navigator
|
|
18
|
-
include Commands
|
|
19
|
-
|
|
20
|
-
# Keys of the events that move the cursor or the focus, and those that act on what's selected.
|
|
21
|
-
MOVES = { up: -1, down: 1 }.freeze
|
|
22
|
-
PANES = { tab: nil, left: :files, right: :outline }.freeze
|
|
23
|
-
ACTIONS = { execute: :execute, edit: :edit, write_back: :write_back, reload: :reload, tick: :refresh }.freeze
|
|
24
|
-
|
|
25
|
-
attr_reader :focus, :status
|
|
26
|
-
|
|
27
|
-
def initialize(root:, path: nil)
|
|
28
|
-
@files = FileTree.new(root:)
|
|
29
|
-
@focus = :files
|
|
30
|
-
@panes = { files: Pane.new { @files.rows }, outline: Pane.new { @outline ? @outline.rows : [] } }
|
|
31
|
-
@status = [:info, 'Tab switches panes, Enter opens and folds, q quits']
|
|
32
|
-
first = @files.rows.find { it.kind == :file }&.target
|
|
33
|
-
show(path || first) if path || first
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def handle(event)
|
|
37
|
-
name, *args = event
|
|
38
|
-
return :quit if name == :quit
|
|
39
|
-
return move(MOVES[name]) if MOVES.key?(name)
|
|
40
|
-
return switch(PANES[name] || other_pane) if PANES.key?(name)
|
|
41
|
-
return select(*args) if name == :select
|
|
42
|
-
return press(*args) if name == :press
|
|
43
|
-
return activate(name) if %i[enter toggle].include?(name)
|
|
44
|
-
|
|
45
|
-
send(ACTIONS[name]) if ACTIONS.key?(name)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# After the editor closes, the file is written back, like a save while it's watched, and read again.
|
|
49
|
-
def ran
|
|
50
|
-
write_back
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def root = @files.root
|
|
54
|
-
def path = @outline&.path
|
|
55
|
-
def relative(path) = @files.relative(path)
|
|
56
|
-
|
|
57
|
-
def rows(pane) = @panes[pane].rows
|
|
58
|
-
def cursor(pane) = @panes[pane].cursor
|
|
59
|
-
def visible(pane, height) = @panes[pane].visible(height)
|
|
60
|
-
|
|
61
|
-
private
|
|
62
|
-
|
|
63
|
-
def show(path)
|
|
64
|
-
@outline = Outline.new(File.expand_path(path))
|
|
65
|
-
@panes[:outline].reset
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def other_pane
|
|
69
|
-
@focus == :files ? :outline : :files
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def move(by)
|
|
73
|
-
@panes[@focus].move(by)
|
|
74
|
-
nil
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def switch(pane)
|
|
78
|
-
@focus = pane
|
|
79
|
-
nil
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def select(pane, index)
|
|
83
|
-
@focus = pane
|
|
84
|
-
@panes[pane].cursor = index
|
|
85
|
-
nil
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def press(pane, index, event)
|
|
89
|
-
select(pane, index)
|
|
90
|
-
handle(event)
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def selected(pane = @focus)
|
|
94
|
-
@panes[pane].selected
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
# Enter opens what's selected, or folds it, and Space only folds.
|
|
98
|
-
# A line of output, or a directive without any, opens in the editor.
|
|
99
|
-
def activate(name)
|
|
100
|
-
row = selected
|
|
101
|
-
return edit if name == :enter && editable?(row)
|
|
102
|
-
|
|
103
|
-
case row&.kind
|
|
104
|
-
when :folder then @files.toggle(row.target)
|
|
105
|
-
when :file then open_file(row.target) if name == :enter
|
|
106
|
-
when :heading then @outline.fold(row.target)
|
|
107
|
-
when :directive then @outline.expand(row.target) if row.target.output
|
|
108
|
-
end
|
|
109
|
-
nil
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def editable?(row)
|
|
113
|
-
row&.kind == :output || (row&.kind == :directive && !row.target.output)
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def open_file(path)
|
|
117
|
-
show(path)
|
|
118
|
-
@focus = :outline
|
|
119
|
-
info("Opened #{relative(path)}")
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
end
|
data/lib/raindown/tui/styles.rb
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
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
|