salticid 0.9.5 → 0.9.6
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 +7 -0
- data/README.markdown +5 -6
- data/bin/salticid +24 -7
- data/lib/salticid.rb +3 -1
- data/lib/salticid/host.rb +2 -2
- data/lib/salticid/interface.rb +42 -38
- data/lib/salticid/interface/host_view.rb +8 -8
- data/lib/salticid/interface/ncurses.rb +4 -10
- data/lib/salticid/interface/resizable.rb +1 -1
- data/lib/salticid/interface/tab_view.rb +8 -8
- data/lib/salticid/interface/view.rb +4 -4
- data/lib/salticid/version.rb +1 -1
- metadata +15 -28
- data/lib/salticid/interface/conversation_view.rb +0 -150
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 64a66a4ad8d5621362736470e5e59de49304621e
|
|
4
|
+
data.tar.gz: 2d23c1e7bb6805f3930a8b7851c6df1d3249bd78
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 0473e989e79da8851aca8d0c1db2f3a73590811a97d558d56d495bc5437aa412af6d4f4e86bc1121c60d615db4eb815e776543af4e1bebe6e3e14c67756aeeff
|
|
7
|
+
data.tar.gz: 3ab14e47b33c26ba52fcdd4742802e4729c59819dc657b3a985a1e65de4da90a89ec1bb9aca4d547d35dea46c9ac8783a8f2c0b7ee8fde52b76a65832f3c962a
|
data/README.markdown
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
Salticid
|
|
2
2
|
=====
|
|
3
3
|
|
|
4
|
-
<a href="http://www.flickr.com/photos/robertwhyte/8034414631/" title="Salticidae Maratus sp. by Robert Whyte www.arachne.org.au, on Flickr"><img src="http://farm9.staticflickr.com/8034/8034414631_1d7906ac5d_b.jpg" width="850" height="674" alt="Salticidae Maratus sp."></a>
|
|
5
|
-
|
|
6
4
|
Salticidae is the family of jumping spiders: small, nimble, and quite
|
|
7
5
|
intelligent within a limited domain.
|
|
8
6
|
|
|
9
|
-
<img src="http://aphyr.com/media/salticid.png" width="
|
|
7
|
+
<a style="display: inline-block" href="http://www.flickr.com/photos/robertwhyte/8034414631/" title="Salticidae Maratus sp. by Robert Whyte www.arachne.org.au, on Flickr"><img src="http://farm9.staticflickr.com/8034/8034414631_1d7906ac5d_b.jpg" width="302px" height="240px" alt="Salticidae Maratus sp."></a> <img src="http://aphyr.com/media/salticid.png" style="display: inline-block;" width="409px" height="240px" alt="Salticid installing riak" />
|
|
8
|
+
|
|
10
9
|
|
|
11
10
|
Salticid runs commands on other computers via SSH, with just enough
|
|
12
11
|
programmability and structure to run small-scale (~10-20 nodes in parallel)
|
|
@@ -267,7 +266,7 @@ salticid riak.deploy
|
|
|
267
266
|
Salticid parallelizes across hosts. Use the left and right arrow keys, or tab,
|
|
268
267
|
to switch between hosts in the ncurses interface.
|
|
269
268
|
|
|
270
|
-
Typically you'll use salticid with a common set of files over and over again, instead of loading files explicitly with `-l`. You can put any commands to source in `~/.salticidrc
|
|
269
|
+
Typically you'll use salticid with a common set of files over and over again, instead of loading files explicitly with `-l`. You can put any commands to source in `~/.salticidrc` (or .salticidrc in the current working directory); they'll be evaluated on the top-level salticid context:
|
|
271
270
|
|
|
272
271
|
```ruby
|
|
273
272
|
load ENV['HOME'] + '/my-deploy/salticid/*.rb'
|
|
@@ -340,7 +339,7 @@ the full interface:
|
|
|
340
339
|
|
|
341
340
|
```ruby
|
|
342
341
|
task :console do
|
|
343
|
-
|
|
342
|
+
Salticid::Interface.shutdown false
|
|
344
343
|
|
|
345
344
|
if tunnel
|
|
346
345
|
tunnel.open(name, 22) do |port|
|
|
@@ -352,7 +351,7 @@ task :console do
|
|
|
352
351
|
end
|
|
353
352
|
```
|
|
354
353
|
|
|
355
|
-
Now `
|
|
354
|
+
Now `salticid -h my.host.com console` will drop you into an SSH console on that
|
|
356
355
|
node.
|
|
357
356
|
|
|
358
357
|
History
|
data/bin/salticid
CHANGED
|
@@ -5,13 +5,19 @@ require 'trollop'
|
|
|
5
5
|
require "#{File.dirname(__FILE__)}/../lib/salticid"
|
|
6
6
|
require 'salticid/interface'
|
|
7
7
|
|
|
8
|
+
rcfiles = [File.join(ENV["HOME"], '.salticidrc'), ".salticidrc"].select do |f|
|
|
9
|
+
File.exist? f
|
|
10
|
+
end
|
|
11
|
+
# NB: Trollop seems to turn the :multi into a boolean if it's empty (shrug)
|
|
12
|
+
rcfiles = [File.join(ENV["HOME"], '.salticidrc')] if rcfiles.empty?
|
|
13
|
+
|
|
8
14
|
opts = Trollop::options do
|
|
9
|
-
opt :exec,
|
|
10
|
-
opt :group,
|
|
11
|
-
opt :host,
|
|
12
|
-
opt :load,
|
|
13
|
-
opt :role,
|
|
14
|
-
opt :show,
|
|
15
|
+
opt :exec, 'A command line to execute.', :type => :string
|
|
16
|
+
opt :group, 'One or more groups to run task on', :type => :string, :multi => true
|
|
17
|
+
opt :host, 'One or more hosts to run task on', :type => :string, :multi => true
|
|
18
|
+
opt :load, 'Files to load', :default => rcfiles, :multi => true
|
|
19
|
+
opt :role, 'One or more roles. Every host in the role will have the specified task run.', :type => :string, :multi => true
|
|
20
|
+
opt :show, 'Show roles, tasks, hosts, and groups. Try --show salticid or --show <host>', :type => :string
|
|
15
21
|
end
|
|
16
22
|
|
|
17
23
|
task = ARGV.first
|
|
@@ -20,6 +26,10 @@ STDOUT.sync = true
|
|
|
20
26
|
@h = Salticid.new
|
|
21
27
|
|
|
22
28
|
# Load files
|
|
29
|
+
if !opts[:load] || opts[:load].empty?
|
|
30
|
+
Trollop::die 'No salticidrc files found, nothing to do'
|
|
31
|
+
end
|
|
32
|
+
|
|
23
33
|
opts[:load].each do |file|
|
|
24
34
|
@h.load file
|
|
25
35
|
end
|
|
@@ -45,6 +55,12 @@ if opts[:show]
|
|
|
45
55
|
case opts[:show]
|
|
46
56
|
when 'salticid'
|
|
47
57
|
puts @h.to_string
|
|
58
|
+
when 'all-tasks'
|
|
59
|
+
@h.roles.each do |role|
|
|
60
|
+
role.tasks.each do |task|
|
|
61
|
+
puts "#{role}.#{task.name}"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
48
64
|
else
|
|
49
65
|
begin
|
|
50
66
|
o = @h.send(opts[:show].to_sym)
|
|
@@ -95,6 +111,7 @@ begin
|
|
|
95
111
|
# When the interface exits, wait for each thread to complete work.
|
|
96
112
|
threads.each { |t| t.join rescue nil }
|
|
97
113
|
rescue => e
|
|
98
|
-
interface.shutdown
|
|
114
|
+
interface.shutdown false rescue nil
|
|
99
115
|
raise e
|
|
100
116
|
end
|
|
117
|
+
|
data/lib/salticid.rb
CHANGED
|
@@ -2,6 +2,7 @@ require 'rubygems'
|
|
|
2
2
|
require 'net/ssh'
|
|
3
3
|
require 'net/scp'
|
|
4
4
|
require 'net/ssh/gateway'
|
|
5
|
+
require 'thread'
|
|
5
6
|
|
|
6
7
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
7
8
|
|
|
@@ -25,7 +26,7 @@ class Salticid
|
|
|
25
26
|
require 'salticid/gateway'
|
|
26
27
|
require 'salticid/group'
|
|
27
28
|
|
|
28
|
-
attr_accessor :gw, :groups, :hosts, :roles, :tasks
|
|
29
|
+
attr_accessor :gw, :groups, :hosts, :roles, :tasks, :mutex
|
|
29
30
|
|
|
30
31
|
def initialize
|
|
31
32
|
@gw = nil
|
|
@@ -33,6 +34,7 @@ class Salticid
|
|
|
33
34
|
@groups = []
|
|
34
35
|
@roles = []
|
|
35
36
|
@tasks = []
|
|
37
|
+
@mutex = Mutex.new
|
|
36
38
|
end
|
|
37
39
|
|
|
38
40
|
# Define a gateway.
|
data/lib/salticid/host.rb
CHANGED
|
@@ -152,7 +152,7 @@ class Salticid::Host
|
|
|
152
152
|
end
|
|
153
153
|
|
|
154
154
|
# After command, add a semicolon...
|
|
155
|
-
unless command =~ /;\s
|
|
155
|
+
unless command =~ /;\s*\z/
|
|
156
156
|
command += ';'
|
|
157
157
|
end
|
|
158
158
|
|
|
@@ -182,7 +182,7 @@ class Salticid::Host
|
|
|
182
182
|
# Handle STDOUT
|
|
183
183
|
ch.on_data do |c, data|
|
|
184
184
|
# Could this data be the status code?
|
|
185
|
-
if pos = (data =~ /(\d{1,3})\n
|
|
185
|
+
if pos = (data =~ /(\d{1,3})\n\z/)
|
|
186
186
|
# Set status
|
|
187
187
|
status = $1
|
|
188
188
|
|
data/lib/salticid/interface.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
class Salticid
|
|
2
2
|
class Interface
|
|
3
|
-
require '
|
|
3
|
+
require 'curses'
|
|
4
4
|
require 'salticid/interface/ncurses'
|
|
5
5
|
require 'salticid/interface/resizable'
|
|
6
6
|
require 'salticid/interface/view'
|
|
@@ -8,11 +8,11 @@ class Salticid
|
|
|
8
8
|
require 'salticid/interface/host_view'
|
|
9
9
|
|
|
10
10
|
COLORS = {
|
|
11
|
-
:info =>
|
|
12
|
-
:error =>
|
|
13
|
-
:warn =>
|
|
14
|
-
:debug =>
|
|
15
|
-
:finished =>
|
|
11
|
+
:info => Curses::COLOR_WHITE,
|
|
12
|
+
:error => Curses::COLOR_RED,
|
|
13
|
+
:warn => Curses::COLOR_YELLOW,
|
|
14
|
+
:debug => Curses::COLOR_CYAN,
|
|
15
|
+
:finished => Curses::COLOR_GREEN
|
|
16
16
|
}
|
|
17
17
|
COLOR_PAIRS = {}
|
|
18
18
|
|
|
@@ -37,15 +37,17 @@ class Salticid
|
|
|
37
37
|
def initialize(salticid)
|
|
38
38
|
self.class.interfaces << self
|
|
39
39
|
|
|
40
|
+
|
|
40
41
|
# Set up ncurses
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
Curses.init_screen
|
|
43
|
+
Curses.cbreak
|
|
44
|
+
Curses.noecho
|
|
45
|
+
Curses.nonl
|
|
46
|
+
# Gone in Ruby Curses because ???
|
|
47
|
+
# Curses.stdscr.intrflush false
|
|
48
|
+
Curses.stdscr.keypad true
|
|
49
|
+
Curses.start_color
|
|
50
|
+
Curses.use_default_colors
|
|
49
51
|
|
|
50
52
|
@salticid = salticid
|
|
51
53
|
@hosts = []
|
|
@@ -67,7 +69,7 @@ class Salticid
|
|
|
67
69
|
self,
|
|
68
70
|
:host => host,
|
|
69
71
|
:top => 1,
|
|
70
|
-
:height =>
|
|
72
|
+
:height => Curses.lines - 1
|
|
71
73
|
)
|
|
72
74
|
hv.on_state_change do |state|
|
|
73
75
|
@tabs.render
|
|
@@ -76,10 +78,12 @@ class Salticid
|
|
|
76
78
|
tab.show
|
|
77
79
|
end
|
|
78
80
|
|
|
81
|
+
# Set up colors
|
|
79
82
|
def colorize
|
|
80
83
|
COLORS.each_with_index do |c, i|
|
|
81
|
-
|
|
82
|
-
|
|
84
|
+
pair_num = i + 1
|
|
85
|
+
Curses.init_pair pair_num, c.last, -1
|
|
86
|
+
COLOR_PAIRS[c.first] = pair_num
|
|
83
87
|
end
|
|
84
88
|
end
|
|
85
89
|
|
|
@@ -97,16 +101,12 @@ class Salticid
|
|
|
97
101
|
@main.join
|
|
98
102
|
end
|
|
99
103
|
|
|
100
|
-
# List channels and topics
|
|
101
|
-
def list(*channels)
|
|
102
|
-
@connection.list *channels
|
|
103
|
-
end
|
|
104
|
-
|
|
105
104
|
# Mainloop
|
|
106
105
|
def main
|
|
107
106
|
@main = Thread.new do
|
|
108
107
|
Thread.current.priority = -1
|
|
109
|
-
|
|
108
|
+
main_thread = Thread.current
|
|
109
|
+
trap("WINCH") { resize if main_thread.alive? }
|
|
110
110
|
|
|
111
111
|
loop do
|
|
112
112
|
# Get character
|
|
@@ -117,23 +117,27 @@ class Salticid
|
|
|
117
117
|
next
|
|
118
118
|
end
|
|
119
119
|
|
|
120
|
+
File.open("/tmp/curses.log", "a") { |f|
|
|
121
|
+
f.puts char.inspect
|
|
122
|
+
}
|
|
123
|
+
|
|
120
124
|
# Do stuff
|
|
121
125
|
case char
|
|
122
126
|
when 9 # tab
|
|
123
127
|
@tabs.scroll
|
|
124
|
-
when
|
|
128
|
+
when "q" # q
|
|
125
129
|
shutdown
|
|
126
|
-
when
|
|
130
|
+
when Curses::KEY_LEFT
|
|
127
131
|
@tabs.scroll -1
|
|
128
|
-
when
|
|
132
|
+
when Curses::KEY_RIGHT
|
|
129
133
|
@tabs.scroll 1
|
|
130
|
-
when
|
|
134
|
+
when Curses::KEY_PPAGE
|
|
131
135
|
tab.scroll -tab.height / 2
|
|
132
|
-
when
|
|
136
|
+
when Curses::KEY_NPAGE
|
|
133
137
|
tab.scroll tab.height / 2
|
|
134
|
-
when
|
|
138
|
+
when Curses::KEY_UP
|
|
135
139
|
tab.scroll -1
|
|
136
|
-
when
|
|
140
|
+
when Curses::KEY_DOWN
|
|
137
141
|
tab.scroll 1
|
|
138
142
|
end
|
|
139
143
|
end
|
|
@@ -143,10 +147,10 @@ class Salticid
|
|
|
143
147
|
# Resize to fit display
|
|
144
148
|
def resize
|
|
145
149
|
# We need to nuke ncurses to pick up the new dimensions
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
height, width =
|
|
150
|
+
Curses.def_prog_mode
|
|
151
|
+
Curses.close_screen
|
|
152
|
+
Curses.reset_prog_mode
|
|
153
|
+
height, width = Curses.dimensions
|
|
150
154
|
|
|
151
155
|
# Resize tabs
|
|
152
156
|
@tabs.resize(
|
|
@@ -162,10 +166,10 @@ class Salticid
|
|
|
162
166
|
@tabs.shutdown
|
|
163
167
|
|
|
164
168
|
# Shut down ncurses
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
+
Curses.echo
|
|
170
|
+
Curses.nocbreak
|
|
171
|
+
Curses.nl
|
|
172
|
+
Curses.close_screen
|
|
169
173
|
|
|
170
174
|
# Stop interface
|
|
171
175
|
@main.exit rescue nil
|
|
@@ -41,7 +41,7 @@ class Salticid
|
|
|
41
41
|
def render
|
|
42
42
|
return if @hidden
|
|
43
43
|
|
|
44
|
-
@window.
|
|
44
|
+
@window.clear
|
|
45
45
|
|
|
46
46
|
lines_left = @height
|
|
47
47
|
message_i = @scroll_position
|
|
@@ -72,20 +72,20 @@ class Salticid
|
|
|
72
72
|
|
|
73
73
|
if i.zero?
|
|
74
74
|
# Put top line
|
|
75
|
-
@window.
|
|
75
|
+
@window.setpos lines_left, 0
|
|
76
76
|
@window.addstr time + ' '
|
|
77
|
-
@window.attron
|
|
78
|
-
@window.
|
|
77
|
+
@window.attron Curses::A_BOLD
|
|
78
|
+
@window.color_set color if color
|
|
79
79
|
@window.addstr line
|
|
80
80
|
else
|
|
81
81
|
# Put hanging line
|
|
82
|
-
@window.attron
|
|
82
|
+
@window.attron Curses::A_BOLD
|
|
83
83
|
@window.attron color if color
|
|
84
|
-
@window.
|
|
84
|
+
@window.setpos lines_left, offset
|
|
85
85
|
@window.addstr line
|
|
86
86
|
end
|
|
87
|
-
@window.
|
|
88
|
-
@window.attroff
|
|
87
|
+
@window.color_set Interface::COLOR_PAIRS[:info] if color
|
|
88
|
+
@window.attroff Curses::A_BOLD
|
|
89
89
|
|
|
90
90
|
unless @window.cursor[1] == 0
|
|
91
91
|
# Clear rest of line
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
module
|
|
1
|
+
module Curses
|
|
2
2
|
# Returns size of screen [y, x]
|
|
3
3
|
def self.dimensions
|
|
4
|
-
|
|
5
|
-
y = Array.new
|
|
6
|
-
Ncurses.getmaxyx(Ncurses.stdscr, y, x)
|
|
7
|
-
[y.first, x.first]
|
|
4
|
+
[Curses.stdscr.maxy, Curses.stdscr.maxx]
|
|
8
5
|
end
|
|
9
6
|
|
|
10
|
-
class
|
|
7
|
+
class Window
|
|
11
8
|
# Adds a FormattedString
|
|
12
9
|
def add_formatted_string(string)
|
|
13
10
|
string.each do |part|
|
|
@@ -21,10 +18,7 @@ module Ncurses
|
|
|
21
18
|
|
|
22
19
|
# Returns cursor y and x coordinates.
|
|
23
20
|
def cursor
|
|
24
|
-
|
|
25
|
-
x = Array.new
|
|
26
|
-
getyx y, x
|
|
27
|
-
[y.first, x.first]
|
|
21
|
+
[cury, curx]
|
|
28
22
|
end
|
|
29
23
|
end
|
|
30
24
|
end
|
|
@@ -66,21 +66,21 @@ class Salticid
|
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
# Move to start
|
|
69
|
-
@window.
|
|
69
|
+
@window.setpos 0,0
|
|
70
70
|
|
|
71
71
|
@tabs.each_with_index do |tab, i|
|
|
72
72
|
if i > 0
|
|
73
|
-
@window.
|
|
73
|
+
@window.addstr '|'
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
color = Interface::COLOR_PAIRS[tab.state]
|
|
77
|
-
@window.
|
|
78
|
-
@window.attron
|
|
79
|
-
@window.attron
|
|
77
|
+
@window.color_set color if color
|
|
78
|
+
@window.attron Curses::A_BOLD
|
|
79
|
+
@window.attron Curses::A_REVERSE if i == @active
|
|
80
80
|
@window.addstr tab.to_s.slice(0,regions[i]).center(regions[i])
|
|
81
|
-
@window.attroff
|
|
82
|
-
@window.attroff
|
|
83
|
-
@window.
|
|
81
|
+
@window.attroff Curses::A_REVERSE if i == @active
|
|
82
|
+
@window.attroff Curses::A_BOLD
|
|
83
|
+
@window.color_set Interface::COLOR_PAIRS[:info]
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
@window.refresh
|
|
@@ -7,12 +7,12 @@ class Salticid
|
|
|
7
7
|
|
|
8
8
|
def initialize(interface, params = {})
|
|
9
9
|
@interface = interface
|
|
10
|
-
@height = params[:height] ||
|
|
11
|
-
@width = params[:width] ||
|
|
10
|
+
@height = params[:height] || Curses.lines
|
|
11
|
+
@width = params[:width] || Curses.cols
|
|
12
12
|
@top = params[:top] || 0
|
|
13
13
|
@left = params[:left] || 0
|
|
14
14
|
|
|
15
|
-
@window =
|
|
15
|
+
@window = Curses::Window.new @height, @width, @top, @left
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def height=(height)
|
|
@@ -22,7 +22,7 @@ class Salticid
|
|
|
22
22
|
|
|
23
23
|
def hide
|
|
24
24
|
@hidden = true
|
|
25
|
-
@window.
|
|
25
|
+
@window.clear
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def left=(left)
|
data/lib/salticid/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: salticid
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.9.
|
|
5
|
-
prerelease:
|
|
4
|
+
version: 0.9.6
|
|
6
5
|
platform: ruby
|
|
7
6
|
authors:
|
|
8
7
|
- Kyle Kingsbury
|
|
9
8
|
autorequire:
|
|
10
9
|
bindir: bin
|
|
11
10
|
cert_chain: []
|
|
12
|
-
date: 2013-
|
|
11
|
+
date: 2013-12-20 00:00:00.000000000 Z
|
|
13
12
|
dependencies:
|
|
14
13
|
- !ruby/object:Gem::Dependency
|
|
15
14
|
name: trollop
|
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
|
17
|
-
none: false
|
|
18
16
|
requirements:
|
|
19
17
|
- - ~>
|
|
20
18
|
- !ruby/object:Gem::Version
|
|
@@ -22,7 +20,6 @@ dependencies:
|
|
|
22
20
|
type: :runtime
|
|
23
21
|
prerelease: false
|
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
-
none: false
|
|
26
23
|
requirements:
|
|
27
24
|
- - ~>
|
|
28
25
|
- !ruby/object:Gem::Version
|
|
@@ -30,65 +27,57 @@ dependencies:
|
|
|
30
27
|
- !ruby/object:Gem::Dependency
|
|
31
28
|
name: net-scp
|
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
|
33
|
-
none: false
|
|
34
30
|
requirements:
|
|
35
|
-
- -
|
|
31
|
+
- - '>='
|
|
36
32
|
- !ruby/object:Gem::Version
|
|
37
33
|
version: '0'
|
|
38
34
|
type: :runtime
|
|
39
35
|
prerelease: false
|
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
41
|
-
none: false
|
|
42
37
|
requirements:
|
|
43
|
-
- -
|
|
38
|
+
- - '>='
|
|
44
39
|
- !ruby/object:Gem::Version
|
|
45
40
|
version: '0'
|
|
46
41
|
- !ruby/object:Gem::Dependency
|
|
47
42
|
name: net-ssh
|
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
|
49
|
-
none: false
|
|
50
44
|
requirements:
|
|
51
|
-
- -
|
|
45
|
+
- - '>='
|
|
52
46
|
- !ruby/object:Gem::Version
|
|
53
47
|
version: '0'
|
|
54
48
|
type: :runtime
|
|
55
49
|
prerelease: false
|
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
57
|
-
none: false
|
|
58
51
|
requirements:
|
|
59
|
-
- -
|
|
52
|
+
- - '>='
|
|
60
53
|
- !ruby/object:Gem::Version
|
|
61
54
|
version: '0'
|
|
62
55
|
- !ruby/object:Gem::Dependency
|
|
63
56
|
name: net-ssh-gateway
|
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
|
65
|
-
none: false
|
|
66
58
|
requirements:
|
|
67
|
-
- -
|
|
59
|
+
- - '>='
|
|
68
60
|
- !ruby/object:Gem::Version
|
|
69
61
|
version: '0'
|
|
70
62
|
type: :runtime
|
|
71
63
|
prerelease: false
|
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
73
|
-
none: false
|
|
74
65
|
requirements:
|
|
75
|
-
- -
|
|
66
|
+
- - '>='
|
|
76
67
|
- !ruby/object:Gem::Version
|
|
77
68
|
version: '0'
|
|
78
69
|
- !ruby/object:Gem::Dependency
|
|
79
70
|
name: net-ssh-multi
|
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
|
81
|
-
none: false
|
|
82
72
|
requirements:
|
|
83
|
-
- -
|
|
73
|
+
- - '>='
|
|
84
74
|
- !ruby/object:Gem::Version
|
|
85
75
|
version: '0'
|
|
86
76
|
type: :runtime
|
|
87
77
|
prerelease: false
|
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
89
|
-
none: false
|
|
90
79
|
requirements:
|
|
91
|
-
- -
|
|
80
|
+
- - '>='
|
|
92
81
|
- !ruby/object:Gem::Version
|
|
93
82
|
version: '0'
|
|
94
83
|
description:
|
|
@@ -106,7 +95,6 @@ files:
|
|
|
106
95
|
- lib/salticid/host.rb
|
|
107
96
|
- lib/salticid/host/ip.rb
|
|
108
97
|
- lib/salticid/interface.rb
|
|
109
|
-
- lib/salticid/interface/conversation_view.rb
|
|
110
98
|
- lib/salticid/interface/host_view.rb
|
|
111
99
|
- lib/salticid/interface/ncurses.rb
|
|
112
100
|
- lib/salticid/interface/resizable.rb
|
|
@@ -128,26 +116,25 @@ files:
|
|
|
128
116
|
- bin/salticid
|
|
129
117
|
homepage: https://github.com/aphyr/salticid
|
|
130
118
|
licenses: []
|
|
119
|
+
metadata: {}
|
|
131
120
|
post_install_message:
|
|
132
121
|
rdoc_options: []
|
|
133
122
|
require_paths:
|
|
134
123
|
- lib
|
|
135
124
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
136
|
-
none: false
|
|
137
125
|
requirements:
|
|
138
|
-
- -
|
|
126
|
+
- - '>='
|
|
139
127
|
- !ruby/object:Gem::Version
|
|
140
128
|
version: 1.8.7
|
|
141
129
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
|
-
none: false
|
|
143
130
|
requirements:
|
|
144
|
-
- -
|
|
131
|
+
- - '>='
|
|
145
132
|
- !ruby/object:Gem::Version
|
|
146
133
|
version: '0'
|
|
147
134
|
requirements: []
|
|
148
135
|
rubyforge_project:
|
|
149
|
-
rubygems_version: 1.
|
|
136
|
+
rubygems_version: 2.1.11
|
|
150
137
|
signing_key:
|
|
151
|
-
specification_version:
|
|
138
|
+
specification_version: 4
|
|
152
139
|
summary: Run commands over SSH, with Ruby magic.
|
|
153
140
|
test_files: []
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
module IRC
|
|
2
|
-
require ROOT + '/interface'
|
|
3
|
-
require ROOT + '/view'
|
|
4
|
-
class Interface
|
|
5
|
-
class ConversationView < View
|
|
6
|
-
|
|
7
|
-
attr_accessor :messages, :window
|
|
8
|
-
|
|
9
|
-
COLORS = [
|
|
10
|
-
Ncurses::COLOR_WHITE,
|
|
11
|
-
Ncurses::COLOR_RED,
|
|
12
|
-
Ncurses::COLOR_GREEN,
|
|
13
|
-
Ncurses::COLOR_YELLOW,
|
|
14
|
-
Ncurses::COLOR_BLUE,
|
|
15
|
-
Ncurses::COLOR_MAGENTA,
|
|
16
|
-
Ncurses::COLOR_CYAN
|
|
17
|
-
]
|
|
18
|
-
|
|
19
|
-
def initialize(interface, params = {})
|
|
20
|
-
@messages = []
|
|
21
|
-
|
|
22
|
-
@scroll_position = -1
|
|
23
|
-
|
|
24
|
-
super
|
|
25
|
-
|
|
26
|
-
@color_index = 0
|
|
27
|
-
|
|
28
|
-
@color_map = Hash.new do |hash, key|
|
|
29
|
-
if key
|
|
30
|
-
hash[key] = @color_index.modulo Ncurses.COLOR_PAIRS
|
|
31
|
-
@color_index += 1
|
|
32
|
-
else
|
|
33
|
-
nil
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
colorize
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def <<(message)
|
|
41
|
-
# Scroll if at bottom
|
|
42
|
-
@scroll_position += 1 if @scroll_position == @messages.size - 1
|
|
43
|
-
|
|
44
|
-
# Add color
|
|
45
|
-
if message.respond_to? :user
|
|
46
|
-
@color_map[message.user.nick]
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
@messages << message
|
|
50
|
-
render
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
# Set up colors
|
|
54
|
-
def colorize
|
|
55
|
-
COLORS.each_with_index do |color, i|
|
|
56
|
-
Ncurses.init_pair i, color, Ncurses::COLOR_BLACK
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def render
|
|
61
|
-
if @hidden
|
|
62
|
-
return
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
@window.erase
|
|
66
|
-
|
|
67
|
-
lines_left = @height
|
|
68
|
-
message_i = @scroll_position
|
|
69
|
-
while message_i >= 0
|
|
70
|
-
# Message
|
|
71
|
-
message = @messages[message_i]
|
|
72
|
-
message_i -= 1
|
|
73
|
-
|
|
74
|
-
IRC.log "displaying message #{message}"
|
|
75
|
-
|
|
76
|
-
# Time
|
|
77
|
-
time = message.time.strftime "%H:%M:%S"
|
|
78
|
-
|
|
79
|
-
case message
|
|
80
|
-
when PrivMsg
|
|
81
|
-
color = Ncurses.COLOR_PAIR(@color_map[message.user.nick])
|
|
82
|
-
user = message.user.to_s || ''
|
|
83
|
-
text = message.text
|
|
84
|
-
when Event
|
|
85
|
-
user = ''
|
|
86
|
-
text = message.text
|
|
87
|
-
when Command
|
|
88
|
-
user = message.user.to_s || ''
|
|
89
|
-
text = message.text
|
|
90
|
-
else
|
|
91
|
-
user = message.user.to_s || ''
|
|
92
|
-
text = message.command + ' ' + message.params.join(" ")
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
offset = time.length + user.length + 3
|
|
96
|
-
|
|
97
|
-
lines = [text[0, @width - offset]]
|
|
98
|
-
if remaining = text[@width - offset..-1]
|
|
99
|
-
lines += remaining.lines(@width - offset - 1)
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
# Put lines in reverse
|
|
103
|
-
i = lines.size
|
|
104
|
-
while i > 0
|
|
105
|
-
i -= 1
|
|
106
|
-
line = lines[i]
|
|
107
|
-
|
|
108
|
-
lines_left -= 1
|
|
109
|
-
break if lines_left < 0
|
|
110
|
-
|
|
111
|
-
if i.zero?
|
|
112
|
-
# Put top line
|
|
113
|
-
@window.move lines_left, 0
|
|
114
|
-
@window.addstr time + ' '
|
|
115
|
-
@window.attron Ncurses::A_BOLD
|
|
116
|
-
@window.attron color if color
|
|
117
|
-
@window.addstr user
|
|
118
|
-
@window.attroff color if color
|
|
119
|
-
@window.attroff Ncurses::A_BOLD
|
|
120
|
-
@window.addstr ': '
|
|
121
|
-
@window.addstr line
|
|
122
|
-
else
|
|
123
|
-
# Put hanging line
|
|
124
|
-
@window.move lines_left, offset
|
|
125
|
-
@window.addstr line
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
unless @window.cursor[1] == 0
|
|
129
|
-
# Clear rest of line
|
|
130
|
-
@window.clrtoeol
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
@window.refresh
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
# Scrolls the window by delta messages
|
|
138
|
-
def scroll(delta)
|
|
139
|
-
@scroll_position += delta
|
|
140
|
-
if @scroll_position < 0
|
|
141
|
-
@scroll_position = 0
|
|
142
|
-
elsif @scroll_position >= @messages.size
|
|
143
|
-
@scroll_position = @messages.size - 1
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
render
|
|
147
|
-
end
|
|
148
|
-
end
|
|
149
|
-
end
|
|
150
|
-
end
|