salticid 0.9.5 → 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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