mars_base_10 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/mars_base_10/action_bar.rb +1 -1
- data/lib/mars_base_10/comm_central.rb +23 -6
- data/lib/mars_base_10/graph_rover.rb +5 -2
- data/lib/mars_base_10/group_room.rb +128 -0
- data/lib/mars_base_10/pane.rb +15 -4
- data/lib/mars_base_10/ship.rb +38 -0
- data/lib/mars_base_10/subject.rb +4 -0
- data/lib/mars_base_10/version.rb +1 -1
- data/lib/mars_base_10/viewport.rb +18 -9
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ea353d6a59cf0d1ad388a521fa07a121cd94942eb4556c23ee4a11603622141
|
4
|
+
data.tar.gz: 6fd28ad9bd47d54172c4a3c6a0f64e5e4da244af6065ad8514f779cc388dc0c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 248ae50be666debca25a7c253822e941af1c3ba19ac484b6e21423526497c9777419b4b2417756a565bc890afb9dc817d0eb3060eb0b7db34bab0ae5c396ac58
|
7
|
+
data.tar.gz: 20e525d483036e6a815f0e46a3529cdf6d1bee8e4a96bc8c32cc0d27b774331e13d1ae3c76177904da39b845224ed12cfa6b4dc3cb667e943704c75799cb7360
|
@@ -11,7 +11,7 @@ module MarsBase10
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.Default
|
14
|
-
ActionBar.new actions: {'j': 'Move Down', 'k': 'Move Up', 'J': 'Page Down', 'K': 'Page Up', 'q': 'Quit'}
|
14
|
+
ActionBar.new actions: {'j': 'Move Down', 'k': 'Move Up', 'J': 'Page Down', 'K': 'Page Up', 'X': 'Switch App', 'q': 'Quit'}
|
15
15
|
end
|
16
16
|
|
17
17
|
def actions_first_col
|
@@ -2,6 +2,7 @@
|
|
2
2
|
require 'urbit'
|
3
3
|
|
4
4
|
require_relative 'graph_rover'
|
5
|
+
require_relative 'group_room'
|
5
6
|
require_relative 'viewport'
|
6
7
|
|
7
8
|
module MarsBase10
|
@@ -10,22 +11,38 @@ module MarsBase10
|
|
10
11
|
class CommCentral
|
11
12
|
def initialize(config_filename:)
|
12
13
|
@viewport = Viewport.new
|
13
|
-
@
|
14
|
-
|
14
|
+
@ship = Urbit.connect(config_file: config_filename)
|
15
|
+
@ship.login
|
16
|
+
sleep 2 # This is temporary for now, we need a way to know that the subscription callbacks have finished.
|
17
|
+
@controller = GroupRoom.new manager: self, ship_connection: @ship, viewport: @viewport
|
15
18
|
end
|
16
19
|
|
17
20
|
def activate
|
18
|
-
self.
|
21
|
+
self.controller.start
|
22
|
+
end
|
23
|
+
|
24
|
+
def swap_controller
|
25
|
+
self.controller.stop
|
26
|
+
if GroupRoom == self.controller.class
|
27
|
+
@controller = GraphRover.new manager: self, ship_connection: self.ship, viewport: @viewport
|
28
|
+
else
|
29
|
+
@controller = GroupRoom.new manager: self, ship_connection: self.ship, viewport: @viewport
|
30
|
+
end
|
31
|
+
self.controller.start
|
19
32
|
end
|
20
33
|
|
21
34
|
def shutdown
|
22
|
-
self.
|
35
|
+
self.controller.stop
|
23
36
|
end
|
24
37
|
|
25
38
|
private
|
26
39
|
|
27
|
-
def
|
28
|
-
@
|
40
|
+
def controller
|
41
|
+
@controller
|
42
|
+
end
|
43
|
+
|
44
|
+
def ship
|
45
|
+
@ship
|
29
46
|
end
|
30
47
|
end
|
31
48
|
end
|
@@ -6,9 +6,10 @@ require_relative 'subject'
|
|
6
6
|
|
7
7
|
module MarsBase10
|
8
8
|
class GraphRover
|
9
|
-
attr_reader :panes, :ship, :viewport
|
9
|
+
attr_reader :manager, :panes, :ship, :viewport
|
10
10
|
|
11
|
-
def initialize(ship_connection:, viewport:)
|
11
|
+
def initialize(manager:, ship_connection:, viewport:)
|
12
|
+
@manager = manager
|
12
13
|
@ship = Ship.new connection: ship_connection
|
13
14
|
@stack = Stack.new
|
14
15
|
@viewport = viewport
|
@@ -75,6 +76,8 @@ module MarsBase10
|
|
75
76
|
self.viewport.action_bar.remove_action(:p)
|
76
77
|
end
|
77
78
|
end
|
79
|
+
when 'X'
|
80
|
+
self.manager.swap_controller
|
78
81
|
end
|
79
82
|
self.resync if resync_needed
|
80
83
|
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'ship'
|
4
|
+
require_relative 'stack'
|
5
|
+
require_relative 'subject'
|
6
|
+
|
7
|
+
module MarsBase10
|
8
|
+
class GroupRoom
|
9
|
+
attr_reader :manager, :panes, :ship, :viewport
|
10
|
+
|
11
|
+
def initialize(manager:, ship_connection:, viewport:)
|
12
|
+
@manager = manager
|
13
|
+
@ship = Ship.new connection: ship_connection
|
14
|
+
@stack = Stack.new
|
15
|
+
@viewport = viewport
|
16
|
+
@viewport.controller = self
|
17
|
+
|
18
|
+
self.wire_up_panes
|
19
|
+
self.viewport.action_bar = ActionBar.Default.add_action({'i': 'Inspect'})
|
20
|
+
self.viewport.activate pane: @pane_1
|
21
|
+
self.resync
|
22
|
+
end
|
23
|
+
|
24
|
+
def active_node
|
25
|
+
self.ship.fetch_node(resource: self.active_resource, index: self.active_node_index)
|
26
|
+
end
|
27
|
+
|
28
|
+
def active_resource
|
29
|
+
@pane_1.current_subject_index
|
30
|
+
end
|
31
|
+
|
32
|
+
def active_subject(pane:)
|
33
|
+
pane.current_subject_index
|
34
|
+
end
|
35
|
+
|
36
|
+
def load_history
|
37
|
+
return 0 unless @pane_3 == self.viewport.active_pane
|
38
|
+
new_content = self.ship.fetch_older_nodes(resource: self.active_resource, node: self.active_node)
|
39
|
+
@pane_3.subject.prepend_content(ary: new_content)
|
40
|
+
new_content.length
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Called by a pane in this controller for bubbling a key press up
|
45
|
+
#
|
46
|
+
def send(key:)
|
47
|
+
resync_needed = true
|
48
|
+
case key
|
49
|
+
when 'g' # (G)raph View
|
50
|
+
unless @pane_1.active?
|
51
|
+
self.viewport.activate pane: @pane_1
|
52
|
+
end
|
53
|
+
when 'i' # (I)nspect
|
54
|
+
begin
|
55
|
+
self.viewport.activate pane: @pane_3
|
56
|
+
self.viewport.action_bar = ActionBar.Default.add_action({'g': 'Group List'})
|
57
|
+
resync_needed = false
|
58
|
+
end
|
59
|
+
when 'X'
|
60
|
+
self.manager.swap_controller
|
61
|
+
end
|
62
|
+
self.resync if resync_needed
|
63
|
+
end
|
64
|
+
|
65
|
+
def start
|
66
|
+
self.viewport.open
|
67
|
+
end
|
68
|
+
|
69
|
+
def stop
|
70
|
+
self.viewport.close
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def resync
|
76
|
+
self.resync_node_list
|
77
|
+
self.resync_node_view
|
78
|
+
end
|
79
|
+
|
80
|
+
def resync_node_list
|
81
|
+
if @pane_1 == self.viewport.active_pane
|
82
|
+
group_title = self.active_subject(pane: @pane_1)
|
83
|
+
@pane_2.clear
|
84
|
+
@pane_2.subject.title = "#{group_title}"
|
85
|
+
@pane_2.subject.contents = self.ship.fetch_group(group_title: group_title)
|
86
|
+
|
87
|
+
@pane_3.clear
|
88
|
+
@pane_3.subject.title = "Channels of #{self.active_subject(pane: @pane_1)}"
|
89
|
+
@pane_3.subject.contents = self.ship.fetch_group_channels(group_title: self.active_subject(pane: @pane_1))
|
90
|
+
end
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
|
94
|
+
def resync_node_view
|
95
|
+
channel_title = self.active_subject(pane: @pane_3)
|
96
|
+
@pane_4.subject.title = "#{channel_title}"
|
97
|
+
@pane_4.clear
|
98
|
+
@pane_4.subject.contents = self.ship.fetch_channel(group_title: self.active_subject(pane: @pane_1), channel_title: channel_title)
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
|
102
|
+
def wire_up_panes
|
103
|
+
@panes = []
|
104
|
+
|
105
|
+
# Pane #1 is the Group list, It is a fixed height and width in the upper left corner.
|
106
|
+
@pane_1 = @viewport.add_pane height_pct: 0.5, width_pct: 0.5
|
107
|
+
# if @ship.group_names.empty?
|
108
|
+
# @pane_1.view(subject: @ship.graph_names)
|
109
|
+
# else
|
110
|
+
@pane_1.view(subject: @ship.group_names)
|
111
|
+
# end
|
112
|
+
|
113
|
+
# Pane 2 displays the properties of the selected Group. It is variable height in the bottom left corner.
|
114
|
+
@pane_2 = @viewport.add_variable_height_pane at_row: @pane_1.last_row, width_pct: 0.5
|
115
|
+
@pane_2.view(subject: @ship.empty_node)
|
116
|
+
@pane_2.highlight = false
|
117
|
+
|
118
|
+
# The node list is a variable width, fixed height pane in the upper right.
|
119
|
+
@pane_3 = @viewport.add_variable_width_pane at_col: @pane_1.last_col, height_pct: 0.5
|
120
|
+
@pane_3.view(subject: @ship.empty_node_list)
|
121
|
+
|
122
|
+
# The single node viewer is a variable width, variable height pane in the lower right.
|
123
|
+
@pane_4 = @viewport.add_variable_both_pane at_row: @pane_3.last_row, at_col: @pane_1.last_col
|
124
|
+
@pane_4.view(subject: @ship.empty_node)
|
125
|
+
@pane_4.highlight = false
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/mars_base_10/pane.rb
CHANGED
@@ -3,13 +3,14 @@ require 'curses'
|
|
3
3
|
|
4
4
|
module MarsBase10
|
5
5
|
class Pane
|
6
|
-
attr_accessor :draw_row, :draw_col, :index, :latch, :subject
|
6
|
+
attr_accessor :draw_row, :draw_col, :highlight, :index, :latch, :subject
|
7
7
|
attr_reader :height_pct, :left_edge_col, :top_row, :viewport, :width_pct
|
8
8
|
|
9
9
|
def initialize(viewport:, at_row:, at_col:, height_pct: 1, width_pct: 1)
|
10
10
|
@top_row = at_row
|
11
11
|
@left_edge_col = at_col
|
12
12
|
@height_pct = height_pct
|
13
|
+
@highlight = true
|
13
14
|
@index = 1
|
14
15
|
@latch = ''
|
15
16
|
@latch_depth = 0
|
@@ -48,10 +49,10 @@ module MarsBase10
|
|
48
49
|
(first_draw_row..last_draw_row).each do |index|
|
49
50
|
self.draw_line
|
50
51
|
item_index = index + @visible_content_shift
|
51
|
-
self.window.attron(Curses::A_REVERSE) if item_index == self.index
|
52
|
+
self.window.attron(Curses::A_REVERSE) if (item_index == self.index) && self.highlight
|
52
53
|
|
53
54
|
if self.subject.line_length_at(index: item_index) > self.last_col
|
54
|
-
chunks = self.subject.line_at(index: item_index).chars.each_slice(self.last_col).map(&:join)
|
55
|
+
chunks = self.subject.line_at(index: item_index).chars.each_slice(self.last_col - 2).map(&:join)
|
55
56
|
chunks.each do |c|
|
56
57
|
self.window.addstr(c)
|
57
58
|
self.draw_row += 1
|
@@ -63,7 +64,7 @@ module MarsBase10
|
|
63
64
|
self.window.addstr("#{self.subject.line_at(index: item_index)}")
|
64
65
|
end
|
65
66
|
|
66
|
-
self.window.attroff(Curses::A_REVERSE) if item_index == self.index
|
67
|
+
self.window.attroff(Curses::A_REVERSE) if (item_index == self.index) && self.highlight
|
67
68
|
self.window.clrtoeol
|
68
69
|
self.draw_row += 1
|
69
70
|
end
|
@@ -244,6 +245,16 @@ module MarsBase10
|
|
244
245
|
end
|
245
246
|
end
|
246
247
|
|
248
|
+
class VariableHeightPane < Pane
|
249
|
+
def last_col
|
250
|
+
(self.viewport.max_cols * self.width_pct).floor
|
251
|
+
end
|
252
|
+
|
253
|
+
def last_row
|
254
|
+
self.viewport.max_rows - self.top_row
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
247
258
|
class VariableWidthPane < Pane
|
248
259
|
def last_col
|
249
260
|
self.viewport.max_cols - self.left_edge_col
|
data/lib/mars_base_10/ship.rb
CHANGED
@@ -20,6 +20,44 @@ module MarsBase10
|
|
20
20
|
Subject.new title: 'Graphs', contents: @ship.graph_names
|
21
21
|
end
|
22
22
|
|
23
|
+
def group_names
|
24
|
+
Subject.new title: 'Groups', contents: (@ship.groups.map {|g| g.to_list})
|
25
|
+
end
|
26
|
+
|
27
|
+
def fetch_channel(group_title:, channel_title:)
|
28
|
+
if (group = @ship.groups[title: group_title])
|
29
|
+
if (channel = group.graphs.select {|c| channel_title == c.title unless c.nil?}.first)
|
30
|
+
# What we are calling a channel here is really a graph in the urbit-ruby bridge.
|
31
|
+
# This is the equivalent of node.to_pretty_array
|
32
|
+
props = {
|
33
|
+
title: channel.title,
|
34
|
+
description: channel.description,
|
35
|
+
creator: channel.creator,
|
36
|
+
host_ship: channel.host_ship,
|
37
|
+
resource: channel.resource,
|
38
|
+
type: channel.type
|
39
|
+
}
|
40
|
+
return props.each.map {|k, v| "#{k}#{(' ' * [(18 - k.length), 0].max)}#{v}"}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
["Group not found."]
|
44
|
+
end
|
45
|
+
|
46
|
+
def fetch_group(group_title:)
|
47
|
+
if (group = @ship.groups[title: group_title])
|
48
|
+
# This is the equivalent of node.to_pretty_array
|
49
|
+
return group.to_h.each.map {|k, v| "#{k}#{(' ' * [(18 - k.length), 0].max)}#{v}"}
|
50
|
+
end
|
51
|
+
["Group not found."]
|
52
|
+
end
|
53
|
+
|
54
|
+
def fetch_group_channels(group_title:)
|
55
|
+
if (group = @ship.groups[title: group_title])
|
56
|
+
return group.graphs.map {|g| g.nil? ? "Unnamed" : g.title}
|
57
|
+
end
|
58
|
+
["No Channels Available."]
|
59
|
+
end
|
60
|
+
|
23
61
|
def fetch_node(resource:, index:)
|
24
62
|
@ship.graph(resource: resource).node(index: index)
|
25
63
|
end
|
data/lib/mars_base_10/subject.rb
CHANGED
data/lib/mars_base_10/version.rb
CHANGED
@@ -70,15 +70,6 @@ module MarsBase10
|
|
70
70
|
@active_pane = p
|
71
71
|
end
|
72
72
|
|
73
|
-
def add_variable_width_pane(at_row: self.min_row, at_col: self.min_col, height_pct:)
|
74
|
-
p = VariableWidthPane.new viewport: self,
|
75
|
-
at_row: at_row,
|
76
|
-
at_col: at_col,
|
77
|
-
height_pct: height_pct
|
78
|
-
@panes << p
|
79
|
-
p
|
80
|
-
end
|
81
|
-
|
82
73
|
#
|
83
74
|
# Adds a new variable width drawable area (VariableBothPane) to the
|
84
75
|
# right-hand side of the viewport.
|
@@ -95,6 +86,24 @@ module MarsBase10
|
|
95
86
|
p
|
96
87
|
end
|
97
88
|
|
89
|
+
def add_variable_height_pane(at_row:, width_pct:)
|
90
|
+
p = VariableHeightPane.new viewport: self,
|
91
|
+
at_row: at_row,
|
92
|
+
at_col: self.min_col,
|
93
|
+
width_pct: width_pct
|
94
|
+
@panes << p
|
95
|
+
p
|
96
|
+
end
|
97
|
+
|
98
|
+
def add_variable_width_pane(at_row: self.min_row, at_col: self.min_col, height_pct:)
|
99
|
+
p = VariableWidthPane.new viewport: self,
|
100
|
+
at_row: at_row,
|
101
|
+
at_col: at_col,
|
102
|
+
height_pct: height_pct
|
103
|
+
@panes << p
|
104
|
+
p
|
105
|
+
end
|
106
|
+
|
98
107
|
def close
|
99
108
|
Curses.close_screen
|
100
109
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mars_base_10
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daryl Richter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-06-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: curses
|
@@ -152,6 +152,7 @@ files:
|
|
152
152
|
- lib/mars_base_10/cli.rb
|
153
153
|
- lib/mars_base_10/comm_central.rb
|
154
154
|
- lib/mars_base_10/graph_rover.rb
|
155
|
+
- lib/mars_base_10/group_room.rb
|
155
156
|
- lib/mars_base_10/pane.rb
|
156
157
|
- lib/mars_base_10/ship.rb
|
157
158
|
- lib/mars_base_10/stack.rb
|