mars_base_10 0.4.0 → 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/bin/mb10 +2 -2
- data/lib/.DS_Store +0 -0
- data/lib/mars_base_10/action_bar.rb +3 -3
- data/lib/mars_base_10/cli.rb +2 -2
- data/lib/mars_base_10/{graph_rover.rb → controller/graph_rover.rb} +16 -37
- data/lib/mars_base_10/controller/group_room.rb +108 -0
- data/lib/mars_base_10/controller/social_lounge.rb +114 -0
- data/lib/mars_base_10/controller.rb +54 -0
- data/lib/mars_base_10/mission_control.rb +48 -0
- data/lib/mars_base_10/pane.rb +95 -45
- data/lib/mars_base_10/ship.rb +49 -4
- 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 +23 -9
- metadata +7 -4
- data/lib/mars_base_10/comm_central.rb +0 -31
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b0d8748c4298354146d42d5f36cbba46c4957d2e4604b58465b365c980041089
|
|
4
|
+
data.tar.gz: b881836e892d29f0e195422690ecdb4913daf0f58daeed3170bb9b8d4eeb83c0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0c14c3247c13710a5a053da98bc140e14bbf501d1f4f5888aba12ca8fd54c3807352da004b82e891beaff9b0b6da286f8151e105989b0d3dad3f5705d331045d
|
|
7
|
+
data.tar.gz: 3323624dc9690b1eb539ada863729cc615c63743679a824dc21ab07e82fee61b875025c64f329df6802527884379f133a9e622a2159f11b1c406a9be245458ae
|
data/bin/mb10
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
# require "bundler/setup"
|
|
5
|
-
# require "mars_base_10/
|
|
5
|
+
# require "mars_base_10/mission_control"
|
|
6
6
|
|
|
7
7
|
# begin
|
|
8
|
-
# cc = MarsBase10::
|
|
8
|
+
# cc = MarsBase10::MissionControl.new
|
|
9
9
|
# cc.activate
|
|
10
10
|
# ensure
|
|
11
11
|
# cc.shutdown
|
data/lib/.DS_Store
CHANGED
|
Binary file
|
|
@@ -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
|
|
@@ -60,8 +60,8 @@ module MarsBase10
|
|
|
60
60
|
1
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
def
|
|
64
|
-
self.actions.delete_if {|k, v| k
|
|
63
|
+
def remove_actions(keys)
|
|
64
|
+
self.actions.delete_if {|k, v| keys.include? k}
|
|
65
65
|
self
|
|
66
66
|
end
|
|
67
67
|
|
data/lib/mars_base_10/cli.rb
CHANGED
|
@@ -39,9 +39,9 @@ module MarsBase10
|
|
|
39
39
|
invoke :help, ["launch"]
|
|
40
40
|
else
|
|
41
41
|
if (config)
|
|
42
|
-
require_relative "
|
|
42
|
+
require_relative "mission_control"
|
|
43
43
|
begin
|
|
44
|
-
cc = MarsBase10::
|
|
44
|
+
cc = MarsBase10::MissionControl.new config_filename: config
|
|
45
45
|
cc.activate
|
|
46
46
|
ensure
|
|
47
47
|
cc.shutdown
|
|
@@ -1,37 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative '
|
|
4
|
-
require_relative 'stack'
|
|
5
|
-
require_relative 'subject'
|
|
3
|
+
require_relative '../controller'
|
|
6
4
|
|
|
7
5
|
module MarsBase10
|
|
8
|
-
class GraphRover
|
|
9
|
-
attr_reader :panes, :ship, :viewport
|
|
10
|
-
|
|
11
|
-
def initialize(ship_connection:, viewport:)
|
|
12
|
-
@ship = Ship.new connection: ship_connection
|
|
13
|
-
@stack = Stack.new
|
|
14
|
-
@viewport = viewport
|
|
15
|
-
@viewport.controller = self
|
|
16
|
-
|
|
17
|
-
self.wire_up_panes
|
|
18
|
-
self.viewport.action_bar = ActionBar.Default.add_action({'i': 'Inspect'})
|
|
19
|
-
self.viewport.activate pane: @graph_list_pane
|
|
20
|
-
self.resync
|
|
21
|
-
end
|
|
22
|
-
|
|
6
|
+
class GraphRover < Controller
|
|
23
7
|
def active_node_index
|
|
24
8
|
@node_list_pane.current_subject_index
|
|
25
9
|
end
|
|
26
10
|
|
|
27
|
-
def active_node
|
|
28
|
-
self.ship.fetch_node(resource: self.active_resource, index: self.active_node_index)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def active_resource
|
|
32
|
-
@graph_list_pane.current_subject_index
|
|
33
|
-
end
|
|
34
|
-
|
|
35
11
|
def load_history
|
|
36
12
|
return 0 unless @node_list_pane == self.viewport.active_pane
|
|
37
13
|
new_content = self.ship.fetch_older_nodes(resource: self.active_resource, node: self.active_node)
|
|
@@ -48,7 +24,8 @@ module MarsBase10
|
|
|
48
24
|
when 'd' # (D)ive
|
|
49
25
|
begin
|
|
50
26
|
if @node_view_pane.subject.contents[4].include?('true')
|
|
51
|
-
self.
|
|
27
|
+
self.action_bar.add_action({'p': 'Pop Out'})
|
|
28
|
+
self.action_bar.remove_actions([:d, :g])
|
|
52
29
|
@stack.push(self.active_resource)
|
|
53
30
|
@node_list_pane.clear
|
|
54
31
|
@node_list_pane.subject.contents = self.ship.fetch_node_children(resource: self.active_resource, index: self.active_node_index)
|
|
@@ -57,12 +34,12 @@ module MarsBase10
|
|
|
57
34
|
when 'i' # (I)nspect
|
|
58
35
|
begin
|
|
59
36
|
self.viewport.activate pane: @node_list_pane
|
|
60
|
-
self.
|
|
37
|
+
self.action_bar.add_action({'d': 'Dive In', 'g': 'Graph List'})
|
|
61
38
|
resync_needed = false
|
|
62
39
|
end
|
|
63
40
|
when 'g' # (G)raph View
|
|
64
|
-
unless @
|
|
65
|
-
self.viewport.activate pane: @
|
|
41
|
+
unless @pane_1.active?
|
|
42
|
+
self.viewport.activate pane: @pane_1
|
|
66
43
|
# resync_needed = false
|
|
67
44
|
end
|
|
68
45
|
when 'p' # (P)op
|
|
@@ -72,9 +49,11 @@ module MarsBase10
|
|
|
72
49
|
@node_list_pane.subject.contents = self.ship.fetch_node_list(resource: resource)
|
|
73
50
|
end
|
|
74
51
|
if (@stack.length == 0)
|
|
75
|
-
self.
|
|
52
|
+
self.action_bar.remove_actions([:p])
|
|
76
53
|
end
|
|
77
54
|
end
|
|
55
|
+
when 'X'
|
|
56
|
+
self.manager.swap_controller
|
|
78
57
|
end
|
|
79
58
|
self.resync if resync_needed
|
|
80
59
|
end
|
|
@@ -95,7 +74,7 @@ module MarsBase10
|
|
|
95
74
|
end
|
|
96
75
|
|
|
97
76
|
def resync_node_list
|
|
98
|
-
if @
|
|
77
|
+
if @pane_1 == self.viewport.active_pane
|
|
99
78
|
@node_list_pane.clear
|
|
100
79
|
@node_list_pane.subject.title = "Nodes of #{self.active_resource}"
|
|
101
80
|
@node_list_pane.subject.contents = self.ship.fetch_node_list(resource: self.active_resource)
|
|
@@ -120,16 +99,16 @@ module MarsBase10
|
|
|
120
99
|
@panes = []
|
|
121
100
|
|
|
122
101
|
# The graph list is a fixed width, variable height (full screen) pane on the left.
|
|
123
|
-
@
|
|
124
|
-
@
|
|
102
|
+
@pane_1 = @viewport.add_pane width_pct: 0.3
|
|
103
|
+
@pane_1.view(subject: @ship.graph_names)
|
|
125
104
|
|
|
126
105
|
# The node list is a variable width, fixed height pane in the upper right.
|
|
127
|
-
@node_list_pane = @viewport.add_variable_width_pane at_col: @
|
|
106
|
+
@node_list_pane = @viewport.add_variable_width_pane at_col: @pane_1.last_col, height_pct: 0.5
|
|
128
107
|
@node_list_pane.view(subject: @ship.empty_node_list)
|
|
129
108
|
|
|
130
109
|
# The single node viewer is a variable width, variable height pane in the lower right.
|
|
131
|
-
@node_view_pane = @viewport.add_variable_both_pane at_row: @node_list_pane.last_row, at_col: @
|
|
110
|
+
@node_view_pane = @viewport.add_variable_both_pane at_row: @node_list_pane.last_row, at_col: @pane_1.last_col
|
|
132
111
|
@node_view_pane.view(subject: @ship.empty_node)
|
|
133
112
|
end
|
|
134
113
|
end
|
|
135
|
-
end
|
|
114
|
+
end # Module Mars::Base::10
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../controller'
|
|
4
|
+
|
|
5
|
+
module MarsBase10
|
|
6
|
+
class GroupRoom < Controller
|
|
7
|
+
def active_subject(pane:)
|
|
8
|
+
pane.current_subject_index
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def load_history
|
|
12
|
+
return 0 unless @pane_3 == self.viewport.active_pane
|
|
13
|
+
new_content = self.ship.fetch_older_nodes(resource: self.active_resource, node: self.active_node)
|
|
14
|
+
@pane_3.subject.prepend_content(ary: new_content)
|
|
15
|
+
new_content.length
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
#
|
|
19
|
+
# Called by a pane in this controller for bubbling a key press up
|
|
20
|
+
#
|
|
21
|
+
def send(key:)
|
|
22
|
+
resync_needed = true
|
|
23
|
+
case key
|
|
24
|
+
when 'g' # (G)raph View
|
|
25
|
+
unless @pane_1.active?
|
|
26
|
+
self.action_bar.remove_actions([:r])
|
|
27
|
+
self.viewport.activate pane: @pane_1
|
|
28
|
+
end
|
|
29
|
+
when 'i' # (I)nspect
|
|
30
|
+
begin
|
|
31
|
+
resync_needed = false
|
|
32
|
+
self.action_bar.add_action({'g': 'Group List'})
|
|
33
|
+
self.action_bar.add_action({'r': 'Read Channel'})
|
|
34
|
+
self.viewport.activate pane: @pane_3
|
|
35
|
+
end
|
|
36
|
+
when 'r' # (r)ead -> go to the Social Lounge
|
|
37
|
+
if @pane_3.active?
|
|
38
|
+
resync_needed = false
|
|
39
|
+
self.action_bar.remove_actions([:g, :r])
|
|
40
|
+
opts = {
|
|
41
|
+
group_title: self.active_subject(pane: @pane_1),
|
|
42
|
+
channel_title: self.active_subject(pane: @pane_3)
|
|
43
|
+
}
|
|
44
|
+
self.manager.assign(controller_class: SocialLounge, options: opts)
|
|
45
|
+
end
|
|
46
|
+
when 'X'
|
|
47
|
+
resync_needed = false
|
|
48
|
+
self.manager.swap_controller
|
|
49
|
+
end
|
|
50
|
+
self.resync if resync_needed
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def resync
|
|
56
|
+
self.resync_node_list
|
|
57
|
+
self.resync_node_view
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def resync_node_list
|
|
61
|
+
if @pane_1 == self.viewport.active_pane
|
|
62
|
+
group_title = self.active_subject(pane: @pane_1)
|
|
63
|
+
@pane_2.clear
|
|
64
|
+
@pane_2.subject.title = "#{group_title}"
|
|
65
|
+
@pane_2.subject.contents = self.ship.fetch_group(group_title: group_title)
|
|
66
|
+
|
|
67
|
+
@pane_3.clear
|
|
68
|
+
@pane_3.subject.title = "Channels of #{self.active_subject(pane: @pane_1)}"
|
|
69
|
+
@pane_3.subject.contents = self.ship.fetch_group_channels(group_title: self.active_subject(pane: @pane_1))
|
|
70
|
+
end
|
|
71
|
+
nil
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def resync_node_view
|
|
75
|
+
channel_title = self.active_subject(pane: @pane_3)
|
|
76
|
+
@pane_4.subject.title = "#{channel_title}"
|
|
77
|
+
@pane_4.clear
|
|
78
|
+
@pane_4.subject.contents = self.ship.fetch_channel_props(group_title: self.active_subject(pane: @pane_1), channel_title: channel_title)
|
|
79
|
+
nil
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def wire_up_panes
|
|
83
|
+
@panes = []
|
|
84
|
+
|
|
85
|
+
# Pane #1 is the Group list, It is a fixed height and width in the upper left corner.
|
|
86
|
+
@pane_1 = @viewport.add_pane height_pct: 0.5, width_pct: 0.5
|
|
87
|
+
# if @ship.group_names.empty?
|
|
88
|
+
# @pane_1.view(subject: @ship.graph_names)
|
|
89
|
+
# else
|
|
90
|
+
@pane_1.view(subject: @ship.group_names)
|
|
91
|
+
# end
|
|
92
|
+
|
|
93
|
+
# Pane 2 displays the properties of the selected Group. It is variable height in the bottom left corner.
|
|
94
|
+
@pane_2 = @viewport.add_variable_height_pane at_row: @pane_1.last_row, width_pct: 0.5
|
|
95
|
+
@pane_2.view(subject: @ship.empty_node)
|
|
96
|
+
@pane_2.highlight = false
|
|
97
|
+
|
|
98
|
+
# Pane 3 is the Channel list. It is a variable width, fixed height pane in the upper right.
|
|
99
|
+
@pane_3 = @viewport.add_variable_width_pane at_col: @pane_1.last_col, height_pct: 0.5
|
|
100
|
+
@pane_3.view(subject: @ship.empty_node_list)
|
|
101
|
+
|
|
102
|
+
# The single node viewer is a variable width, variable height pane in the lower right.
|
|
103
|
+
@pane_4 = @viewport.add_variable_both_pane at_row: @pane_3.last_row, at_col: @pane_1.last_col
|
|
104
|
+
@pane_4.view(subject: @ship.empty_node)
|
|
105
|
+
@pane_4.highlight = false
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end # Module Mars::Base::10
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../controller'
|
|
4
|
+
|
|
5
|
+
module MarsBase10
|
|
6
|
+
class SocialLounge < Controller
|
|
7
|
+
attr_accessor :channel
|
|
8
|
+
|
|
9
|
+
def initialize(manager:, ship_connection:, viewport:, options: {})
|
|
10
|
+
@index_ary = []
|
|
11
|
+
@group_title = options[:group_title]
|
|
12
|
+
@channel_title = options[:channel_title]
|
|
13
|
+
super(manager: manager, ship_connection: ship_connection, viewport: viewport)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def active_channel
|
|
17
|
+
if self.channel.nil?
|
|
18
|
+
self.channel = self.ship.fetch_channel(group_title: @group_title, channel_title: @channel_title)
|
|
19
|
+
end
|
|
20
|
+
self.channel
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def active_node_index
|
|
24
|
+
@index_ary[@pane_1.index]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def active_resource
|
|
28
|
+
self.active_channel.resource # '~winter-paches/top-shelf-6391'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def active_subject(pane:)
|
|
32
|
+
pane.current_subject_index
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def fetch_channel_messages
|
|
36
|
+
if @pane_1 == self.viewport.active_pane
|
|
37
|
+
@pane_1.clear
|
|
38
|
+
@pane_1.subject.title = "Messages in #{self.active_channel.title}"
|
|
39
|
+
@pane_1.subject.contents = self.load_messages(count: @pane_1.last_visible_row)
|
|
40
|
+
end
|
|
41
|
+
nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def load_history
|
|
45
|
+
return 0 unless @pane_1 == self.viewport.active_pane
|
|
46
|
+
messages = self.node_indexes_to_messages(node_indexes: self.ship.fetch_older_nodes(resource: self.active_resource, node: self.active_node, count: @pane_1.last_visible_row))
|
|
47
|
+
@pane_1.subject.prepend_content(ary: messages)
|
|
48
|
+
messages.length
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def load_messages(count:)
|
|
52
|
+
self.node_indexes_to_messages(node_indexes: self.ship.fetch_node_list(resource: self.active_resource, count: count))
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# This will eventually be a native part of the Airlock API
|
|
56
|
+
def message(node:)
|
|
57
|
+
"~#{node.to_h[:author]} #{self.message_content(node_content: node.to_h[:contents])}"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def message_content(node_content:)
|
|
61
|
+
n0 = node_content[0]
|
|
62
|
+
if n0["reference"]
|
|
63
|
+
# http://localhost:8080/apps/landscape/perma/group/~winter-paches/the-great-north/graph/~winter-paches/top-shelf-6391/170141184505732100235824355185168220160
|
|
64
|
+
ref = n0["reference"]["graph"]
|
|
65
|
+
# grup = ref["group"].split('/').last
|
|
66
|
+
# graf = ref["graph"].split('/').last
|
|
67
|
+
return "=> #{node_content[2]["mention"]} -> #{node_content[3]["text"]} (#{ref["index"]})"
|
|
68
|
+
end
|
|
69
|
+
n0["text"] || n0["url"]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def node_indexes_to_messages(node_indexes:)
|
|
73
|
+
@index_ary = node_indexes + @index_ary
|
|
74
|
+
messages = node_indexes.map do |i|
|
|
75
|
+
# Can't use fetch_node_contents because we're formatting differently now.
|
|
76
|
+
# This will eventually be a native part of the Airlock API
|
|
77
|
+
self.message(node: self.ship.fetch_node(resource: self.active_resource, index: i))
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
#
|
|
82
|
+
# Called by a pane in this controller for bubbling a key press up
|
|
83
|
+
#
|
|
84
|
+
def send(key:)
|
|
85
|
+
case key
|
|
86
|
+
when 'g' # (G)raph View
|
|
87
|
+
unless @pane_1.active?
|
|
88
|
+
self.viewport.activate pane: @pane_1
|
|
89
|
+
self.action_bar.remove_actions([:g])
|
|
90
|
+
end
|
|
91
|
+
when 'i' # (I)nspect
|
|
92
|
+
begin
|
|
93
|
+
self.viewport.activate pane: @pane_3
|
|
94
|
+
self.action_bar.add_action({'g': 'Group List'})
|
|
95
|
+
end
|
|
96
|
+
when 'X'
|
|
97
|
+
self.manager.swap_controller
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def show
|
|
102
|
+
self.fetch_channel_messages
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
private
|
|
106
|
+
|
|
107
|
+
def wire_up_panes
|
|
108
|
+
@panes = []
|
|
109
|
+
# Pane #1 is the Chat Channel Reader. It takes up the entire Viewport. (For now?)
|
|
110
|
+
@pane_1 = self.viewport.add_pane height_pct: 1.0, width_pct: 1.0
|
|
111
|
+
@pane_1.view(subject: self.ship.empty_node_list)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end # Module Mars::Base::10
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'ship'
|
|
4
|
+
require_relative 'stack'
|
|
5
|
+
require_relative 'subject'
|
|
6
|
+
|
|
7
|
+
module MarsBase10
|
|
8
|
+
class Controller
|
|
9
|
+
attr_reader :manager, :panes, :ship, :viewport
|
|
10
|
+
|
|
11
|
+
def initialize(manager:, ship_connection:, viewport:, options: {})
|
|
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.action_bar = ActionBar.Default.add_action({'i': 'Inspect'})
|
|
20
|
+
self.viewport.activate pane: @pane_1
|
|
21
|
+
self.show
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def action_bar
|
|
25
|
+
self.viewport.action_bar
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def active_node
|
|
29
|
+
self.ship.fetch_node(resource: self.active_resource, index: self.active_node_index)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def active_resource
|
|
33
|
+
@pane_1.current_subject_index
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def show
|
|
37
|
+
self.resync
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def start
|
|
41
|
+
self.viewport.open
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def stop
|
|
45
|
+
self.viewport.close
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def action_bar=(an_action_bar)
|
|
51
|
+
self.viewport.action_bar = an_action_bar
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'urbit'
|
|
3
|
+
|
|
4
|
+
require_relative 'controller/group_room'
|
|
5
|
+
require_relative 'controller/graph_rover'
|
|
6
|
+
require_relative 'controller/social_lounge'
|
|
7
|
+
require_relative 'viewport'
|
|
8
|
+
|
|
9
|
+
module MarsBase10
|
|
10
|
+
class Error < StandardError; end
|
|
11
|
+
|
|
12
|
+
class MissionControl
|
|
13
|
+
attr_accessor :controller
|
|
14
|
+
attr_reader :ship
|
|
15
|
+
|
|
16
|
+
def initialize(config_filename:)
|
|
17
|
+
@ship = Urbit.connect(config_file: config_filename)
|
|
18
|
+
@ship.login
|
|
19
|
+
sleep 2 # This is temporary for now, we need a way to know that the subscription callbacks have finished.
|
|
20
|
+
@viewport = Viewport.new
|
|
21
|
+
@controller = GroupRoom.new manager: self, ship_connection: @ship, viewport: @viewport
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def activate
|
|
25
|
+
self.controller.start
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def assign(controller_class:, options: {})
|
|
29
|
+
@viewport.dispose_panes
|
|
30
|
+
self.controller = controller_class.send(:new, {manager: self, ship_connection: self.ship, viewport: @viewport, options: options})
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def shutdown
|
|
34
|
+
self.controller.stop
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def swap_controller
|
|
38
|
+
if GroupRoom == self.controller.class
|
|
39
|
+
cls = GraphRover
|
|
40
|
+
elsif GraphRover == self.controller.class
|
|
41
|
+
cls = SocialLounge
|
|
42
|
+
else
|
|
43
|
+
cls = GroupRoom
|
|
44
|
+
end
|
|
45
|
+
self.assign(controller_class: cls)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
data/lib/mars_base_10/pane.rb
CHANGED
|
@@ -3,21 +3,24 @@ require 'curses'
|
|
|
3
3
|
|
|
4
4
|
module MarsBase10
|
|
5
5
|
class Pane
|
|
6
|
-
attr_accessor :
|
|
6
|
+
attr_accessor :cur_draw_row, :cur_draw_col, :extended_lines, :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
|
-
@
|
|
11
|
-
@
|
|
12
|
-
@
|
|
13
|
-
@index
|
|
14
|
-
@
|
|
15
|
-
@
|
|
16
|
-
@
|
|
17
|
-
@
|
|
18
|
-
@
|
|
19
|
-
@
|
|
20
|
-
@
|
|
10
|
+
@first_visible_index = 1
|
|
11
|
+
@height_pct = height_pct
|
|
12
|
+
@highlight = false
|
|
13
|
+
@index = 1
|
|
14
|
+
@last_visible_index = 0
|
|
15
|
+
@latch = ''
|
|
16
|
+
@latch_depth = 0
|
|
17
|
+
@left_edge_col = at_col
|
|
18
|
+
@subject = nil
|
|
19
|
+
@top_row = at_row
|
|
20
|
+
@win = nil
|
|
21
|
+
@viewport = viewport
|
|
22
|
+
# @visible_content_shift = 0
|
|
23
|
+
@width_pct = width_pct
|
|
21
24
|
end
|
|
22
25
|
|
|
23
26
|
def active?
|
|
@@ -28,13 +31,17 @@ module MarsBase10
|
|
|
28
31
|
self.reset
|
|
29
32
|
self.prepare_for_writing_contents
|
|
30
33
|
(0..(self.last_row - 1)).each do |item|
|
|
31
|
-
self.window.setpos(self.
|
|
34
|
+
self.window.setpos(self.cur_draw_row, self.cur_draw_col)
|
|
32
35
|
self.window.addstr("")
|
|
33
36
|
self.window.clrtoeol
|
|
34
|
-
self.
|
|
37
|
+
self.cur_draw_row += 1
|
|
35
38
|
end
|
|
36
39
|
end
|
|
37
40
|
|
|
41
|
+
def current_item_index
|
|
42
|
+
(self.cur_draw_row - self.extended_lines) + self.visible_content_shift
|
|
43
|
+
end
|
|
44
|
+
|
|
38
45
|
def current_subject_index
|
|
39
46
|
self.subject.at(index: self.index)
|
|
40
47
|
end
|
|
@@ -42,33 +49,42 @@ module MarsBase10
|
|
|
42
49
|
def draw
|
|
43
50
|
self.prepare_for_writing_contents
|
|
44
51
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
self.window.attron(Curses::A_REVERSE) if item_index == self.index
|
|
52
|
+
while self.cur_draw_row <= self.last_drawable_row
|
|
53
|
+
if self.current_item_index <= self.subject.item_index_range.last
|
|
54
|
+
if (self.current_item_index == self.index) && !self.highlight
|
|
55
|
+
self.window.attron(Curses::A_REVERSE)
|
|
56
|
+
self.highlight = true
|
|
57
|
+
end
|
|
52
58
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
if self.subject.line_length_at(index: self.current_item_index) > self.last_col
|
|
60
|
+
chunks = self.subject.line_at(index: self.current_item_index).chars.each_slice(self.last_col - 2).map(&:join)
|
|
61
|
+
chunks.each do |c|
|
|
62
|
+
self.draw_line
|
|
63
|
+
self.window.addstr("#{c}")
|
|
64
|
+
self.cur_draw_row += 1
|
|
65
|
+
self.extended_lines += 1
|
|
66
|
+
end
|
|
67
|
+
self.extended_lines -= 1
|
|
68
|
+
else
|
|
58
69
|
self.draw_line
|
|
59
|
-
|
|
70
|
+
self.window.addstr("#{self.subject.line_at(index: self.current_item_index)}")
|
|
71
|
+
self.cur_draw_row += 1
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
if self.highlight
|
|
75
|
+
self.window.attroff(Curses::A_REVERSE)
|
|
76
|
+
self.highlight = false
|
|
60
77
|
end
|
|
61
|
-
self.draw_row -= 1
|
|
62
78
|
else
|
|
63
|
-
self.
|
|
79
|
+
self.draw_line
|
|
80
|
+
self.window.addstr(" ")
|
|
81
|
+
self.cur_draw_row += 1
|
|
64
82
|
end
|
|
65
|
-
|
|
66
|
-
self.window.attroff(Curses::A_REVERSE) if item_index == self.index
|
|
67
83
|
self.window.clrtoeol
|
|
68
|
-
self.draw_row += 1
|
|
69
84
|
end
|
|
70
|
-
|
|
71
85
|
self.draw_border
|
|
86
|
+
|
|
87
|
+
@last_visible_index = self.current_item_index - 1 # Subtract one b/c we have already incremented before loop
|
|
72
88
|
end
|
|
73
89
|
|
|
74
90
|
def draw_border
|
|
@@ -79,7 +95,7 @@ module MarsBase10
|
|
|
79
95
|
end
|
|
80
96
|
|
|
81
97
|
def draw_line
|
|
82
|
-
self.window.setpos(self.
|
|
98
|
+
self.window.setpos(self.cur_draw_row, self.cur_draw_col)
|
|
83
99
|
end
|
|
84
100
|
|
|
85
101
|
def draw_title
|
|
@@ -87,11 +103,11 @@ module MarsBase10
|
|
|
87
103
|
self.window.addstr(" #{self.subject.title} (#{self.max_contents_rows} total) ")
|
|
88
104
|
end
|
|
89
105
|
|
|
90
|
-
def
|
|
106
|
+
def first_drawable_col
|
|
91
107
|
1
|
|
92
108
|
end
|
|
93
109
|
|
|
94
|
-
def
|
|
110
|
+
def first_drawable_row
|
|
95
111
|
1
|
|
96
112
|
end
|
|
97
113
|
|
|
@@ -103,7 +119,8 @@ module MarsBase10
|
|
|
103
119
|
# This is the _relative_ last column, e.g. the width of the pane in columns.
|
|
104
120
|
#
|
|
105
121
|
def last_col
|
|
106
|
-
[(self.viewport.max_cols * self.width_pct).floor, self.min_column_width].max
|
|
122
|
+
# [(self.viewport.max_cols * self.width_pct).floor, self.min_column_width].max
|
|
123
|
+
(self.viewport.max_cols * self.width_pct).floor
|
|
107
124
|
end
|
|
108
125
|
|
|
109
126
|
def last_drawable_row
|
|
@@ -111,12 +128,15 @@ module MarsBase10
|
|
|
111
128
|
end
|
|
112
129
|
|
|
113
130
|
#
|
|
114
|
-
# This is the _relative_ last row, e.g. the height of the pane in
|
|
131
|
+
# This is the _relative_ last row, e.g. the height of the pane in rows
|
|
115
132
|
#
|
|
116
133
|
def last_row
|
|
117
134
|
(self.viewport.max_rows * self.height_pct).floor
|
|
118
135
|
end
|
|
119
136
|
|
|
137
|
+
#
|
|
138
|
+
# This is the height of the pane minus the border
|
|
139
|
+
#
|
|
120
140
|
def last_visible_row
|
|
121
141
|
self.last_row - 2
|
|
122
142
|
end
|
|
@@ -137,8 +157,11 @@ module MarsBase10
|
|
|
137
157
|
end
|
|
138
158
|
|
|
139
159
|
def prepare_for_writing_contents
|
|
140
|
-
self.
|
|
141
|
-
self.
|
|
160
|
+
self.cur_draw_row = self.first_drawable_row
|
|
161
|
+
self.cur_draw_col = self.first_drawable_col
|
|
162
|
+
self.extended_lines = 0
|
|
163
|
+
@first_visible_index = self.cur_draw_row + self.visible_content_shift
|
|
164
|
+
@last_visible_index = self.subject.item_count if @last_visible_index < @first_visible_index
|
|
142
165
|
end
|
|
143
166
|
|
|
144
167
|
#
|
|
@@ -158,7 +181,7 @@ module MarsBase10
|
|
|
158
181
|
when 'J'
|
|
159
182
|
self.index = self.set_row([self.index + (self.last_visible_row), self.max_contents_rows].min)
|
|
160
183
|
when 'K'
|
|
161
|
-
self.index = self.set_row(self.index -
|
|
184
|
+
self.index = self.set_row(self.index - self.visible_content_range.count)
|
|
162
185
|
when 'q'
|
|
163
186
|
exit 0
|
|
164
187
|
when ('0'..'9')
|
|
@@ -184,7 +207,7 @@ module MarsBase10
|
|
|
184
207
|
@index = 1
|
|
185
208
|
@latch = ''
|
|
186
209
|
@latch_depth = 0
|
|
187
|
-
@visible_content_shift = 0
|
|
210
|
+
# @visible_content_shift = 0
|
|
188
211
|
end
|
|
189
212
|
|
|
190
213
|
def right_pad
|
|
@@ -192,12 +215,19 @@ module MarsBase10
|
|
|
192
215
|
end
|
|
193
216
|
|
|
194
217
|
def scroll_to_row(index)
|
|
218
|
+
jump = [(index - self.index), (self.max_contents_rows - self.visible_content_range.last)].min
|
|
195
219
|
if index > self.index
|
|
196
220
|
# Scrolling down
|
|
197
|
-
|
|
221
|
+
if index > self.visible_content_range.last
|
|
222
|
+
@first_visible_index = @first_visible_index + jump
|
|
223
|
+
@last_visible_index = @last_visible_index + jump
|
|
224
|
+
end
|
|
198
225
|
else
|
|
199
226
|
# Scrolling up
|
|
200
|
-
|
|
227
|
+
if index < self.visible_content_range.first
|
|
228
|
+
@first_visible_index = [(@first_visible_index + jump), 1].max
|
|
229
|
+
@last_visible_index = @last_visible_index + jump
|
|
230
|
+
end
|
|
201
231
|
end
|
|
202
232
|
[index, 1].max
|
|
203
233
|
end
|
|
@@ -214,7 +244,12 @@ module MarsBase10
|
|
|
214
244
|
|
|
215
245
|
# Check if we have tried to move "above" the visible screen limit (i = 1) and retrieve more items, if possible.
|
|
216
246
|
if (i < 1)
|
|
247
|
+
if i < 0
|
|
248
|
+
target_index = self.index
|
|
249
|
+
self.index = 1
|
|
250
|
+
end
|
|
217
251
|
i = [self.viewport.controller.load_history, 1].max
|
|
252
|
+
i = target_index if target_index
|
|
218
253
|
end
|
|
219
254
|
|
|
220
255
|
return self.scroll_to_row(i)
|
|
@@ -225,7 +260,12 @@ module MarsBase10
|
|
|
225
260
|
end
|
|
226
261
|
|
|
227
262
|
def visible_content_range
|
|
228
|
-
((self.
|
|
263
|
+
# ((self.first_drawable_row + @visible_content_shift)..(self.last_drawable_row + @visible_content_shift))
|
|
264
|
+
(@first_visible_index..@last_visible_index)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def visible_content_shift
|
|
268
|
+
self.visible_content_range.first - self.first_drawable_row
|
|
229
269
|
end
|
|
230
270
|
|
|
231
271
|
def window
|
|
@@ -244,6 +284,16 @@ module MarsBase10
|
|
|
244
284
|
end
|
|
245
285
|
end
|
|
246
286
|
|
|
287
|
+
class VariableHeightPane < Pane
|
|
288
|
+
def last_col
|
|
289
|
+
(self.viewport.max_cols * self.width_pct).floor
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def last_row
|
|
293
|
+
self.viewport.max_rows - self.top_row
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
247
297
|
class VariableWidthPane < Pane
|
|
248
298
|
def last_col
|
|
249
299
|
self.viewport.max_cols - self.left_edge_col
|
data/lib/mars_base_10/ship.rb
CHANGED
|
@@ -20,6 +20,51 @@ 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
|
+
return channel
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
nil
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def fetch_channel_props(group_title:, channel_title:)
|
|
37
|
+
if (channel = self.fetch_channel(group_title: group_title, channel_title: channel_title))
|
|
38
|
+
# What we are calling a channel here is really a graph in the urbit-ruby bridge.
|
|
39
|
+
# This is the equivalent of node.to_pretty_array
|
|
40
|
+
props = {
|
|
41
|
+
title: channel.title,
|
|
42
|
+
description: channel.description,
|
|
43
|
+
creator: channel.creator,
|
|
44
|
+
host_ship: channel.host_ship,
|
|
45
|
+
resource: channel.resource,
|
|
46
|
+
type: channel.type
|
|
47
|
+
}
|
|
48
|
+
return props.each.map {|k, v| "#{k}#{(' ' * [(18 - k.length), 0].max)}#{v}"}
|
|
49
|
+
end
|
|
50
|
+
["Channel not found."]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def fetch_group(group_title:)
|
|
54
|
+
if (group = @ship.groups[title: group_title])
|
|
55
|
+
# This is the equivalent of node.to_pretty_array
|
|
56
|
+
return group.to_h.each.map {|k, v| "#{k}#{(' ' * [(18 - k.length), 0].max)}#{v}"}
|
|
57
|
+
end
|
|
58
|
+
["Group not found."]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def fetch_group_channels(group_title:)
|
|
62
|
+
if (group = @ship.groups[title: group_title])
|
|
63
|
+
return group.graphs.map {|g| g.nil? ? "Unnamed" : g.title}
|
|
64
|
+
end
|
|
65
|
+
["No Channels Available."]
|
|
66
|
+
end
|
|
67
|
+
|
|
23
68
|
def fetch_node(resource:, index:)
|
|
24
69
|
@ship.graph(resource: resource).node(index: index)
|
|
25
70
|
end
|
|
@@ -33,12 +78,12 @@ module MarsBase10
|
|
|
33
78
|
n.to_pretty_array
|
|
34
79
|
end
|
|
35
80
|
|
|
36
|
-
def fetch_node_list(resource:)
|
|
37
|
-
@ship.graph(resource: resource).newest_nodes(count:
|
|
81
|
+
def fetch_node_list(resource:, count: 60)
|
|
82
|
+
@ship.graph(resource: resource).newest_nodes(count: count).map {|node| node.index}.sort
|
|
38
83
|
end
|
|
39
84
|
|
|
40
|
-
def fetch_older_nodes(resource:, node:)
|
|
41
|
-
@ship.graph(resource: resource).older_sibling_nodes(node: node, count:
|
|
85
|
+
def fetch_older_nodes(resource:, node:, count: 60)
|
|
86
|
+
@ship.graph(resource: resource).older_sibling_nodes(node: node, count: count).map {|node| node.index}.sort
|
|
42
87
|
end
|
|
43
88
|
end
|
|
44
89
|
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,10 +86,33 @@ 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
|
|
101
110
|
|
|
111
|
+
def dispose_panes
|
|
112
|
+
@active_pane = nil
|
|
113
|
+
@panes = []
|
|
114
|
+
end
|
|
115
|
+
|
|
102
116
|
def max_cols
|
|
103
117
|
self.win.maxx
|
|
104
118
|
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.6.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-09-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: curses
|
|
@@ -150,8 +150,11 @@ files:
|
|
|
150
150
|
- lib/mars_base_10.rb
|
|
151
151
|
- lib/mars_base_10/action_bar.rb
|
|
152
152
|
- lib/mars_base_10/cli.rb
|
|
153
|
-
- lib/mars_base_10/
|
|
154
|
-
- lib/mars_base_10/graph_rover.rb
|
|
153
|
+
- lib/mars_base_10/controller.rb
|
|
154
|
+
- lib/mars_base_10/controller/graph_rover.rb
|
|
155
|
+
- lib/mars_base_10/controller/group_room.rb
|
|
156
|
+
- lib/mars_base_10/controller/social_lounge.rb
|
|
157
|
+
- lib/mars_base_10/mission_control.rb
|
|
155
158
|
- lib/mars_base_10/pane.rb
|
|
156
159
|
- lib/mars_base_10/ship.rb
|
|
157
160
|
- lib/mars_base_10/stack.rb
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
require 'urbit'
|
|
3
|
-
|
|
4
|
-
require_relative 'graph_rover'
|
|
5
|
-
require_relative 'viewport'
|
|
6
|
-
|
|
7
|
-
module MarsBase10
|
|
8
|
-
class Error < StandardError; end
|
|
9
|
-
|
|
10
|
-
class CommCentral
|
|
11
|
-
def initialize(config_filename:)
|
|
12
|
-
@viewport = Viewport.new
|
|
13
|
-
@rover = GraphRover.new ship_connection: Urbit.connect(config_file: config_filename),
|
|
14
|
-
viewport: @viewport
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def activate
|
|
18
|
-
self.rover.start
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def shutdown
|
|
22
|
-
self.rover.stop
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
private
|
|
26
|
-
|
|
27
|
-
def rover
|
|
28
|
-
@rover
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|