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.
@@ -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
@@ -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="100%" alt="Salticid installing riak" />
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`; they'll be evaluated on the top-level salticid context:
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
- Hydra::Interface.shutdown false
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 `hydra -h my.host.com console` will drop you into an SSH console on that
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
@@ -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, 'A command line to execute.', :type => :string
10
- opt :group, 'One or more groups to run task on', :type => :string, :multi => true
11
- opt :host, 'One or more hosts to run task on', :type => :string, :multi => true
12
- opt :load, 'Files to load', :default => [File.join(ENV["HOME"], '.salticidrc')], :multi => true
13
- opt :role, 'One or more roles. Every host in the role will have the specified task run.', :type => :string, :multi => true
14
- opt :show, 'Show roles, tasks, hosts, and groups. Try --show salticid or --show <host>', :type => :string
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
+
@@ -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.
@@ -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
 
@@ -1,6 +1,6 @@
1
1
  class Salticid
2
2
  class Interface
3
- require 'ncurses'
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 => Ncurses::COLOR_WHITE,
12
- :error => Ncurses::COLOR_RED,
13
- :warn => Ncurses::COLOR_YELLOW,
14
- :debug => Ncurses::COLOR_CYAN,
15
- :finished => Ncurses::COLOR_GREEN
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
- Ncurses.initscr
42
- Ncurses.cbreak
43
- Ncurses.noecho
44
- Ncurses.nonl
45
- Ncurses.stdscr.intrflush false
46
- Ncurses.stdscr.keypad true
47
- Ncurses.start_color
48
- Ncurses.use_default_colors
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 => Ncurses.LINES - 1
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
- Ncurses.init_pair i + 1, c.last, -1
82
- COLOR_PAIRS[c.first] = Ncurses.COLOR_PAIR(i + 1)
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
- trap("WINCH") { resize if Thread.current.alive? }
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 113 # q
128
+ when "q" # q
125
129
  shutdown
126
- when Ncurses::KEY_LEFT
130
+ when Curses::KEY_LEFT
127
131
  @tabs.scroll -1
128
- when Ncurses::KEY_RIGHT
132
+ when Curses::KEY_RIGHT
129
133
  @tabs.scroll 1
130
- when Ncurses::KEY_PPAGE
134
+ when Curses::KEY_PPAGE
131
135
  tab.scroll -tab.height / 2
132
- when Ncurses::KEY_NPAGE
136
+ when Curses::KEY_NPAGE
133
137
  tab.scroll tab.height / 2
134
- when Ncurses::KEY_UP
138
+ when Curses::KEY_UP
135
139
  tab.scroll -1
136
- when Ncurses::KEY_DOWN
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
- Ncurses.def_prog_mode
147
- Ncurses.endwin
148
- Ncurses.reset_prog_mode
149
- height, width = Ncurses.dimensions
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
- Ncurses.echo
166
- Ncurses.nocbreak
167
- Ncurses.nl
168
- Ncurses.endwin
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.erase
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.move lines_left, 0
75
+ @window.setpos lines_left, 0
76
76
  @window.addstr time + ' '
77
- @window.attron Ncurses::A_BOLD
78
- @window.attron color if color
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 Ncurses::A_BOLD
82
+ @window.attron Curses::A_BOLD
83
83
  @window.attron color if color
84
- @window.move lines_left, offset
84
+ @window.setpos lines_left, offset
85
85
  @window.addstr line
86
86
  end
87
- @window.attroff color if color
88
- @window.attroff Ncurses::A_BOLD
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 Ncurses
1
+ module Curses
2
2
  # Returns size of screen [y, x]
3
3
  def self.dimensions
4
- x = Array.new
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 WINDOW
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
- y = Array.new
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
@@ -12,7 +12,7 @@ class Salticid
12
12
 
13
13
  if @window
14
14
  # Resize window
15
- @window.mvwin @top, @left
15
+ @window.move @top, @left
16
16
  @window.resize @height, @width
17
17
  end
18
18
 
@@ -66,21 +66,21 @@ class Salticid
66
66
  end
67
67
 
68
68
  # Move to start
69
- @window.move 0,0
69
+ @window.setpos 0,0
70
70
 
71
71
  @tabs.each_with_index do |tab, i|
72
72
  if i > 0
73
- @window.addch Ncurses::ACS_VLINE
73
+ @window.addstr '|'
74
74
  end
75
75
 
76
76
  color = Interface::COLOR_PAIRS[tab.state]
77
- @window.attron color if color
78
- @window.attron Ncurses::A_BOLD
79
- @window.attron Ncurses::A_REVERSE if i == @active
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 Ncurses::A_REVERSE if i == @active
82
- @window.attroff Ncurses::A_BOLD
83
- @window.attroff color if color
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] || Ncurses.LINES
11
- @width = params[:width] || Ncurses.COLS
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 = Ncurses::WINDOW.new @height, @width, @top, @left
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.erase
25
+ @window.clear
26
26
  end
27
27
 
28
28
  def left=(left)
@@ -1,3 +1,3 @@
1
1
  class Salticid
2
- VERSION = "0.9.5"
2
+ VERSION = "0.9.6"
3
3
  end
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
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-04-22 00:00:00.000000000 Z
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.8.25
136
+ rubygems_version: 2.1.11
150
137
  signing_key:
151
- specification_version: 3
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