ratchet 0.3.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.
- data/gem_bin/ratchet +23 -0
- data/lib/ratchet.rb +613 -0
- data/lib/ratchet/aliases.rb +106 -0
- data/lib/ratchet/bufferparser.rb +409 -0
- data/lib/ratchet/commandbuffer.rb +66 -0
- data/lib/ratchet/commandparser.rb +668 -0
- data/lib/ratchet/configuration.rb +278 -0
- data/lib/ratchet/connections.rb +403 -0
- data/lib/ratchet/constants.rb +111 -0
- data/lib/ratchet/contrib/instance_exec.rb +21 -0
- data/lib/ratchet/eventparser.rb +486 -0
- data/lib/ratchet/gtk/bufferlistview.rb +514 -0
- data/lib/ratchet/gtk/bufferview.rb +167 -0
- data/lib/ratchet/gtk/configwindow.rb +229 -0
- data/lib/ratchet/gtk/connectionwindow.rb +218 -0
- data/lib/ratchet/gtk/keybinding.rb +356 -0
- data/lib/ratchet/gtk/linkwindow.rb +137 -0
- data/lib/ratchet/gtk/mainwindow.rb +504 -0
- data/lib/ratchet/gtk/networkpresenceconf.rb +567 -0
- data/lib/ratchet/gtk/pluginconfig.rb +94 -0
- data/lib/ratchet/gtk/pluginwindow.rb +146 -0
- data/lib/ratchet/gtk/userlistview.rb +161 -0
- data/lib/ratchet/help.rb +64 -0
- data/lib/ratchet/items.rb +271 -0
- data/lib/ratchet/lines.rb +63 -0
- data/lib/ratchet/networks.rb +652 -0
- data/lib/ratchet/plugins.rb +616 -0
- data/lib/ratchet/queue.rb +47 -0
- data/lib/ratchet/ratchet-version.rb +21 -0
- data/lib/ratchet/replies.rb +134 -0
- data/lib/ratchet/replyparser.rb +441 -0
- data/lib/ratchet/tabcomplete.rb +98 -0
- data/lib/ratchet/users.rb +237 -0
- data/lib/ratchet/utils.rb +178 -0
- data/share/defaults.yaml +169 -0
- data/share/glade/config.glade +2634 -0
- data/share/glade/connect.glade +950 -0
- data/share/glade/keybindings.glade +109 -0
- data/share/glade/linkwindow.glade +188 -0
- data/share/glade/mainwindow.glade +335 -0
- data/share/glade/network-presences.glade +1373 -0
- data/share/glade/pluginconf.glade +97 -0
- data/share/glade/plugins.glade +360 -0
- data/share/plugins/colorewrite.rb +193 -0
- data/share/plugins/highlighter.rb +115 -0
- data/share/plugins/mpdplay.rb +123 -0
- data/share/plugins/numberswitcher.rb +30 -0
- data/share/plugins/sysinfo.rb +82 -0
- metadata +96 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
This file is part of the Ratchet project, a client for Icecap.
|
|
3
|
+
Copyright (C) 2005-6 Andrew Thompson
|
|
4
|
+
|
|
5
|
+
This program is free software; you can redistribute it and/or modify
|
|
6
|
+
it under the terms of the GNU General Public License as published by
|
|
7
|
+
the Free Software Foundation; either version 2 of the License, or
|
|
8
|
+
(at your option) any later version.
|
|
9
|
+
|
|
10
|
+
This program is distributed in the hope that it will be useful,
|
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
You should have received a copy of the GNU General Public License
|
|
16
|
+
along with this program; if not, write to the Free Software
|
|
17
|
+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
18
|
+
=end
|
|
19
|
+
|
|
20
|
+
#### items.rb ####
|
|
21
|
+
# Ugh, this file still exists. Its function is to store the network-gateway-presence relations
|
|
22
|
+
# I really would like to unify this with the actual buffers, but its tricker than I'd hoped
|
|
23
|
+
####
|
|
24
|
+
|
|
25
|
+
#TODO: get rid this damndable thing, or at least make it a bit nicer, but its not massively important
|
|
26
|
+
|
|
27
|
+
module Ratchet
|
|
28
|
+
class Item
|
|
29
|
+
def <=>(object)
|
|
30
|
+
return 0 unless @name
|
|
31
|
+
return 1 unless object
|
|
32
|
+
return @name<=>object.name
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
#~ def ==(object)
|
|
36
|
+
#~ return nil unless object
|
|
37
|
+
#~ return @name == object.name
|
|
38
|
+
#~ end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class Network < Item
|
|
42
|
+
attr_reader :name, :protocol
|
|
43
|
+
attr_accessor :charset
|
|
44
|
+
def initialize(name, protocol)
|
|
45
|
+
@name = name
|
|
46
|
+
@protocol = protocol
|
|
47
|
+
@gateways = ItemList.new(Gateway)
|
|
48
|
+
@presences = ItemList.new(Presence)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def add_gateway(host, port=nil)
|
|
52
|
+
return @gateways.add(host, port)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def gateways
|
|
56
|
+
return @gateways
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def add_presence(name)
|
|
60
|
+
return @presences.add(name)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def presences
|
|
64
|
+
return @presences
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def presences=(list)
|
|
68
|
+
@presences = list
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def gateways=(list)
|
|
72
|
+
@gateways = list
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def diff(object)
|
|
76
|
+
settings = []
|
|
77
|
+
if object.charset != @charset
|
|
78
|
+
settings.push('charset='+@charset.to_s)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
if settings.empty?
|
|
82
|
+
return nil
|
|
83
|
+
else
|
|
84
|
+
return settings.join(';')
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def update(object)
|
|
89
|
+
@charset = object.charset
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def create
|
|
93
|
+
string = 'network add;network='+@name+';protocol='+@protocol
|
|
94
|
+
if @charset
|
|
95
|
+
string += ';charset='+@charset
|
|
96
|
+
end
|
|
97
|
+
return string
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
class Protocol < Item
|
|
103
|
+
attr_reader :name, :charsets_in, :charset_out
|
|
104
|
+
def initialize(name, charset_in, charset_out)
|
|
105
|
+
@name = name
|
|
106
|
+
@charsets_in = charset_in.split(' ')
|
|
107
|
+
@charset_out = charset_out
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
class Gateway < Item
|
|
112
|
+
attr_reader :network
|
|
113
|
+
attr_accessor :host, :port, :password, :priority
|
|
114
|
+
def initialize(host, port=nil)
|
|
115
|
+
@host = host
|
|
116
|
+
@port = port
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def name
|
|
120
|
+
return @host
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def diff(object)
|
|
124
|
+
settings = []
|
|
125
|
+
settings.push('port='+@port.to_s) if object.port != @port
|
|
126
|
+
settings.push('password='+@password.to_s) if object.password != @password
|
|
127
|
+
#settings.push('port='+port) if object.port != @port
|
|
128
|
+
|
|
129
|
+
if settings.empty?
|
|
130
|
+
return nil
|
|
131
|
+
else
|
|
132
|
+
return settings.join(';')
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def update(object)
|
|
137
|
+
@port = object.port
|
|
138
|
+
@password = object.password
|
|
139
|
+
@priority = object.priority
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def create(network)
|
|
143
|
+
string = 'gateway add;host='+@host+';network='+network
|
|
144
|
+
if @port
|
|
145
|
+
string += ';port='+@port
|
|
146
|
+
end
|
|
147
|
+
if @password
|
|
148
|
+
string += ';password='+@password
|
|
149
|
+
end
|
|
150
|
+
return string
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
#~ def ==(object)
|
|
154
|
+
#~ return false unless object
|
|
155
|
+
#~ x = (@host == object.host and @port == object.port)
|
|
156
|
+
#~ return x
|
|
157
|
+
#~ end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
class Presence < Item
|
|
161
|
+
attr_reader :name
|
|
162
|
+
attr_accessor :autoconnect
|
|
163
|
+
def initialize(name)
|
|
164
|
+
@name = name
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def diff(object)
|
|
168
|
+
settings = []
|
|
169
|
+
if object.autoconnect != @autoconnect
|
|
170
|
+
if @autoconnect
|
|
171
|
+
settings.push('autoconnect')
|
|
172
|
+
else
|
|
173
|
+
settings.push('autoconnect=')
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
if settings.empty?
|
|
178
|
+
return nil
|
|
179
|
+
else
|
|
180
|
+
return settings.join(';')
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def update(object)
|
|
185
|
+
@autoconnect = object.autoconnect
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def create(network)
|
|
189
|
+
string = 'presence add;mypresence='+@name+';network='+network
|
|
190
|
+
return string
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
class ItemList
|
|
195
|
+
attr_reader :list
|
|
196
|
+
def initialize(classtype)
|
|
197
|
+
@classtype = classtype
|
|
198
|
+
@list = []
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def [](key)
|
|
202
|
+
results = []
|
|
203
|
+
@list.each do |item|
|
|
204
|
+
if item.name == key
|
|
205
|
+
return item
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
return nil
|
|
210
|
+
|
|
211
|
+
#~ if results.length == 1
|
|
212
|
+
#~ return results[0]
|
|
213
|
+
#~ elsif results.length > 1
|
|
214
|
+
#~ return results
|
|
215
|
+
#~ else
|
|
216
|
+
#~ return nil
|
|
217
|
+
#~ end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def []=(key, replacement)
|
|
221
|
+
results = []
|
|
222
|
+
@list.each do |item|
|
|
223
|
+
if item.name == key
|
|
224
|
+
return item.update(replacement)
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
return nil
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
#~ def exists?(*args)
|
|
232
|
+
#~ item = @classtype.new(*args)
|
|
233
|
+
#~ return includes?(item)
|
|
234
|
+
#~ end
|
|
235
|
+
|
|
236
|
+
def add(*args)
|
|
237
|
+
item = @classtype.new(*args)
|
|
238
|
+
return nil if self.include?(item)
|
|
239
|
+
@list.push(item)
|
|
240
|
+
return item
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def insert(item)
|
|
244
|
+
return nil if self.include?(item)
|
|
245
|
+
@list.push(item)
|
|
246
|
+
return item
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def remove(item)
|
|
250
|
+
@list.delete(item)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def include?(item)
|
|
254
|
+
@list.each do |i|
|
|
255
|
+
if i.name == item.name
|
|
256
|
+
return true
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
return false
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def sort!
|
|
263
|
+
@list.sort!
|
|
264
|
+
return @list
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def sort
|
|
268
|
+
return @list.sort
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
This file is part of the Ratchet project, a client for Icecap.
|
|
3
|
+
Copyright (C) 2005-6 Andrew Thompson
|
|
4
|
+
|
|
5
|
+
This program is free software; you can redistribute it and/or modify
|
|
6
|
+
it under the terms of the GNU General Public License as published by
|
|
7
|
+
the Free Software Foundation; either version 2 of the License, or
|
|
8
|
+
(at your option) any later version.
|
|
9
|
+
|
|
10
|
+
This program is distributed in the hope that it will be useful,
|
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
You should have received a copy of the GNU General Public License
|
|
16
|
+
along with this program; if not, write to the Free Software
|
|
17
|
+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
18
|
+
=end
|
|
19
|
+
|
|
20
|
+
#### lines.rb ####
|
|
21
|
+
# A simple hash derivative that internally converts to symbols
|
|
22
|
+
####
|
|
23
|
+
|
|
24
|
+
#TODO: is this *really* needed? Seems like I was just anxious to try some subclassing
|
|
25
|
+
|
|
26
|
+
module Ratchet
|
|
27
|
+
#derive from Hash and simply convert all keys to symbols for internal storage
|
|
28
|
+
#also convert all lookup keys to symbols
|
|
29
|
+
class Line < Hash
|
|
30
|
+
#convert keys to symbols
|
|
31
|
+
def self.[](*args)
|
|
32
|
+
|
|
33
|
+
if args[0].class == Hash
|
|
34
|
+
new = {}
|
|
35
|
+
args[0].each do |k,v|
|
|
36
|
+
new[k.to_sym] = v
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
args[0] = new
|
|
40
|
+
else
|
|
41
|
+
x = true
|
|
42
|
+
args.each_with_index do |k, i|
|
|
43
|
+
if x
|
|
44
|
+
args[i] = k.to_sym
|
|
45
|
+
end
|
|
46
|
+
x = !x
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
super(*args)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def[]=(key, value)
|
|
54
|
+
key = key.to_sym
|
|
55
|
+
super(key, value)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def [](key)
|
|
59
|
+
key = key.to_sym
|
|
60
|
+
super(key)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,652 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
This file is part of the Ratchet project, a client for Icecap.
|
|
3
|
+
Copyright (C) 2005-6 Andrew Thompson
|
|
4
|
+
|
|
5
|
+
This program is free software; you can redistribute it and/or modify
|
|
6
|
+
it under the terms of the GNU General Public License as published by
|
|
7
|
+
the Free Software Foundation; either version 2 of the License, or
|
|
8
|
+
(at your option) any later version.
|
|
9
|
+
|
|
10
|
+
This program is distributed in the hope that it will be useful,
|
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
You should have received a copy of the GNU General Public License
|
|
16
|
+
along with this program; if not, write to the Free Software
|
|
17
|
+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
18
|
+
=end
|
|
19
|
+
|
|
20
|
+
#### networks.rb ####
|
|
21
|
+
# Provides the M and C of the buffers' MVC
|
|
22
|
+
# also contains the channel, network, chat and console objects
|
|
23
|
+
####
|
|
24
|
+
|
|
25
|
+
module Ratchet
|
|
26
|
+
#hopefully, the program will only need access to the controller, so wrap all the useful stuff here?
|
|
27
|
+
class BufferListController
|
|
28
|
+
#include PluginAPI
|
|
29
|
+
#include BufferParser
|
|
30
|
+
attr_reader :view, :config, :window, :model
|
|
31
|
+
def initialize(window, console=false)
|
|
32
|
+
@window = window
|
|
33
|
+
@config = window.config
|
|
34
|
+
@model = BufferListModel.new(self, console)
|
|
35
|
+
set_sort(BufferListModel::HIERARCHICAL)
|
|
36
|
+
set_comparator(BufferListModel::INSENSITIVE)
|
|
37
|
+
#initialize the view with the references it needs
|
|
38
|
+
# @view = TreeBufferListView.new(self, @model)
|
|
39
|
+
# @model.view = view #give the model a reference to the view
|
|
40
|
+
recreate
|
|
41
|
+
@window.switch_buffer(@model.console) if @model.console
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def console
|
|
45
|
+
@model.console
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def recreate
|
|
49
|
+
if @config['tablisttype'] == 'button' and @view.class.superclass != BoxBufferListView
|
|
50
|
+
puts 'new buttonbox'
|
|
51
|
+
@view = HBoxBufferListView.new(self, @model)
|
|
52
|
+
elsif @config['tablisttype'] == 'treeview' and @view.class != TreeBufferListView
|
|
53
|
+
puts 'new treeview'
|
|
54
|
+
@view = TreeBufferListView.new(self, @model)
|
|
55
|
+
end
|
|
56
|
+
@model.view = @view
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
#most of these wrap model functions...
|
|
60
|
+
#~ def add_network(name, presence)
|
|
61
|
+
#~ @model.add_network(name, presence)
|
|
62
|
+
#~ end
|
|
63
|
+
|
|
64
|
+
def next_buffer
|
|
65
|
+
index = @model.structure.index(active)+1
|
|
66
|
+
index %= @model.structure.length
|
|
67
|
+
set_active(@model.structure[index])
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def prev_buffer
|
|
71
|
+
index = @model.structure.index(active)-1
|
|
72
|
+
set_active(@model.structure[index])
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def connect(buffer)
|
|
76
|
+
if buffer.respond_to? 'connect'
|
|
77
|
+
#buffer.connect
|
|
78
|
+
@model.sort
|
|
79
|
+
set_active(buffer) if buffer.connected?
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def join(buffer)
|
|
84
|
+
if buffer.respond_to? 'join'
|
|
85
|
+
#buffer.connect
|
|
86
|
+
@model.sort
|
|
87
|
+
set_active(buffer) if buffer.joined?
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def add_buffer(buffer)
|
|
92
|
+
return unless buffer
|
|
93
|
+
# puts 'adding to window'
|
|
94
|
+
buffer.controller = self
|
|
95
|
+
case buffer
|
|
96
|
+
when NetworkBuffer
|
|
97
|
+
# puts 'network'
|
|
98
|
+
@model.add_network(buffer)
|
|
99
|
+
when ChannelBuffer
|
|
100
|
+
@model.add_channel(buffer)
|
|
101
|
+
when ChatBuffer
|
|
102
|
+
@model.add_chat(buffer)
|
|
103
|
+
set_active(buffer)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
#~ def add_chat(name, network)
|
|
108
|
+
#~ @model.add_chat(name, network)
|
|
109
|
+
#~ end
|
|
110
|
+
|
|
111
|
+
#~ def add_channel(name, network)
|
|
112
|
+
#~ @model.add_channel(name, network)
|
|
113
|
+
#~ end
|
|
114
|
+
|
|
115
|
+
def find_network(name, presence)
|
|
116
|
+
@model.find_network(name, presence)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
#here we provide a unified function for looking up channels/chats
|
|
120
|
+
def find_chat(*args)
|
|
121
|
+
if args.length == 2
|
|
122
|
+
@model.find_chat_in_network(*args)
|
|
123
|
+
elsif args.length == 3
|
|
124
|
+
@model.find_chat(*args)
|
|
125
|
+
else
|
|
126
|
+
raise ArgumentError, 'function takes 2 or 3 arguments'
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def find_channel(*args)
|
|
131
|
+
if args.length == 2
|
|
132
|
+
@model.find_channel_in_network(*args)
|
|
133
|
+
elsif args.length == 3
|
|
134
|
+
@model.find_channel(*args)
|
|
135
|
+
else
|
|
136
|
+
raise ArgumentError, 'function takes 2 or 3 arguments'
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def close_buffer(buffer)
|
|
141
|
+
return unless buffer
|
|
142
|
+
case buffer
|
|
143
|
+
when NetworkBuffer
|
|
144
|
+
#puts 'network'
|
|
145
|
+
#@model.add_network(buffer)
|
|
146
|
+
when ChannelBuffer
|
|
147
|
+
#@model.add_channel(buffer)
|
|
148
|
+
when ChatBuffer
|
|
149
|
+
@model.remove_chat(buffer)
|
|
150
|
+
@window.main.remove_buffer(buffer)
|
|
151
|
+
end
|
|
152
|
+
@model.sort
|
|
153
|
+
@window.switch_buffer(@model.active)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def include?(object)
|
|
157
|
+
# puts networks.include?(object)
|
|
158
|
+
# puts channels.include?(object)
|
|
159
|
+
# puts chats.include?(object)
|
|
160
|
+
# puts console == object
|
|
161
|
+
networks.include?(object) || channels.include?(object) || chats.include?(object) || console == object
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def active
|
|
165
|
+
@model.active
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def channels
|
|
169
|
+
@model.channels
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def networks
|
|
173
|
+
@model.networks
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def chats
|
|
177
|
+
@model.chats
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def remove_network(obj)
|
|
181
|
+
@model.remove_network(obj)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def remove_channel(obj)
|
|
185
|
+
@model.remove_channel(obj)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def remove_chat(obj)
|
|
189
|
+
@model.remove_chat(obj)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
#do some prefunctory checking here...
|
|
193
|
+
def set_sort(block)
|
|
194
|
+
return if @model.sort and @model.sort == block
|
|
195
|
+
@model.set_sort(block)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def set_comparator(block)
|
|
199
|
+
return if @model.comp and @model.comp == block
|
|
200
|
+
@model.set_comparator(block)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def set_status(object, status)
|
|
205
|
+
@model.set_status(object, status) if @model
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def set_active(object)
|
|
209
|
+
#if the model includes the object and the model isn't already set this as active
|
|
210
|
+
if @model.structure.include? object and @model.active != object
|
|
211
|
+
@model.set_active(object)
|
|
212
|
+
end
|
|
213
|
+
#switch the window to display this tab
|
|
214
|
+
@window.switch_buffer(object) unless @window.currentbuffer == object
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
#model, so all the data munging here, the controller should protect us from too much invalid nonsense
|
|
219
|
+
class BufferListModel
|
|
220
|
+
attr_reader :structure, :view, :sort, :comp, :active, :console, :networks, :channels, :chats
|
|
221
|
+
|
|
222
|
+
#ooh look, the layout/sort algorithms are pluggable. me++
|
|
223
|
+
HIERARCHICAL = Proc.new do |console, networks, channels, chats, comp|
|
|
224
|
+
res= []
|
|
225
|
+
res << console if console
|
|
226
|
+
networks.sort(&comp).each do |n|
|
|
227
|
+
res << n
|
|
228
|
+
channels.select{|c| c.network == n}.sort(&comp).each{|c| res << c}
|
|
229
|
+
chats.select{|c| c.network == n}.sort(&comp).each{|c| res << c}
|
|
230
|
+
end
|
|
231
|
+
res
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
FLAT = Proc.new do |console, networks, channels, chats, comp|
|
|
235
|
+
res= []
|
|
236
|
+
res << console if console
|
|
237
|
+
channels.sort(&comp).each{|x| res << x}
|
|
238
|
+
chats.sort(&comp).each{|x| res << x}
|
|
239
|
+
res
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
SENSITIVE = Proc.new{|x, y| x.name<=>y.name}
|
|
243
|
+
INSENSITIVE = Proc.new{|x, y| x.name.downcase<=>y.name.downcase}
|
|
244
|
+
|
|
245
|
+
def initialize(controller, console=false)
|
|
246
|
+
@controller = controller
|
|
247
|
+
@networks = []
|
|
248
|
+
@channels = []
|
|
249
|
+
@chats = []
|
|
250
|
+
@structure = []
|
|
251
|
+
if console
|
|
252
|
+
@console = console#ConsoleBuffer.new(@controller)
|
|
253
|
+
console.add_controller(@controller)
|
|
254
|
+
set_active(@console)
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def view=(view)
|
|
259
|
+
@view = view
|
|
260
|
+
sort
|
|
261
|
+
view.fill unless view.filled?
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def set_status(object, status)
|
|
265
|
+
# puts object, status, object.status
|
|
266
|
+
object.status = status if status > object.status or status == 0
|
|
267
|
+
@view.update_status(object)
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
#set the block to use to sort the networks/channels/chats
|
|
271
|
+
def set_sort(block)
|
|
272
|
+
@sort = block
|
|
273
|
+
sort
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
#set the block used to compare networks/channels/chats
|
|
277
|
+
def set_comparator(block)
|
|
278
|
+
@comp = block
|
|
279
|
+
sort
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
#updates the view, then stores the new active
|
|
283
|
+
def set_active(obj)
|
|
284
|
+
@active.set_status(0) if @active
|
|
285
|
+
# obj.set_status(0)
|
|
286
|
+
# @view.update_status(obj) if @view
|
|
287
|
+
@view.set_active(obj) if @view
|
|
288
|
+
@active = obj
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def add_network(network)
|
|
292
|
+
@networks << network
|
|
293
|
+
sort
|
|
294
|
+
#set_active(network)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def add_channel(channel)
|
|
298
|
+
@channels << channel
|
|
299
|
+
sort
|
|
300
|
+
#set_active(channel)
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def add_chat(chat)
|
|
304
|
+
@chats << chat
|
|
305
|
+
sort
|
|
306
|
+
#set_active(chat)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
#~ #takes a name string
|
|
310
|
+
#~ def add_network(name, presence)
|
|
311
|
+
#~ unless network = @networks.detect{|n| n.name == name and n.presence == presence}
|
|
312
|
+
#~ network = NetworkBuffer.new(@controller, name, presence)
|
|
313
|
+
#~ @networks << network
|
|
314
|
+
#~ end
|
|
315
|
+
#~ sort
|
|
316
|
+
#~ network
|
|
317
|
+
#~ end
|
|
318
|
+
|
|
319
|
+
#~ def add_channel(name, network)
|
|
320
|
+
#~ unless channel = @channels.detect{|c| c.name == name and c.network = network}
|
|
321
|
+
#~ channel = ChannelBuffer.new(@controller, name, network)
|
|
322
|
+
#~ @channels << channel
|
|
323
|
+
#~ end
|
|
324
|
+
#~ sort
|
|
325
|
+
#~ channel
|
|
326
|
+
#~ end
|
|
327
|
+
|
|
328
|
+
#~ def add_chat(name, network)
|
|
329
|
+
#~ unless chat = @chats.detect{|c| c.name == name and c.network = network}
|
|
330
|
+
#~ chat = ChatBuffer.new(@controller, name, network)
|
|
331
|
+
#~ @chats << chat
|
|
332
|
+
#~ end
|
|
333
|
+
#~ sort
|
|
334
|
+
#~ set_active(chat)
|
|
335
|
+
#~ chat
|
|
336
|
+
#~ end
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
#takes a Network object
|
|
341
|
+
def remove_network(network)
|
|
342
|
+
# puts network.class
|
|
343
|
+
@networks.delete(network)
|
|
344
|
+
@channels.delete_if{|x| x.network == network}
|
|
345
|
+
@chats.delete_if{|x| x.network == network}
|
|
346
|
+
sort
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
#takes a Channel object
|
|
350
|
+
def remove_channel(channel)
|
|
351
|
+
@channels.delete(channel)
|
|
352
|
+
sort
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
#takes a Chat object
|
|
356
|
+
def remove_chat(chat)
|
|
357
|
+
@chats.delete(chat)
|
|
358
|
+
sort
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
def find_network(name, presence)
|
|
362
|
+
@networks.detect{|n| n.name == name and n.presence == presence}
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
def find_channel(networkname, presence, channelname)
|
|
366
|
+
res = nil
|
|
367
|
+
if network = find_network(networkname, presence)
|
|
368
|
+
res = find_channel_in_network(network, channelname)
|
|
369
|
+
end
|
|
370
|
+
return res
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def find_chat(networkname, presence, chatname)
|
|
374
|
+
res = nil
|
|
375
|
+
if network = find_network(networkname, presence)
|
|
376
|
+
res = find_chat_in_network(network, chatname)
|
|
377
|
+
end
|
|
378
|
+
return res
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
#needs a network object
|
|
382
|
+
def find_channel_in_network(network, name)
|
|
383
|
+
@channels.detect{|x| x.network == network and x.name == name}
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
def find_chat_in_network(network, name)
|
|
387
|
+
@chats.detect{|x| x.network == network and x.name == name}
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
def sort
|
|
391
|
+
return unless @sort and @comp
|
|
392
|
+
oldstructure = @structure
|
|
393
|
+
@structure = @sort.call(@console, @networks.select{|x| x.buffer}, @channels.select{|x| x.buffer}, @chats.select{|x| x.buffer}, @comp)
|
|
394
|
+
return @structure unless @view
|
|
395
|
+
|
|
396
|
+
#check if its an add or a delete
|
|
397
|
+
#TODO - renames, mainly for chats
|
|
398
|
+
if oldstructure.length < @structure.length
|
|
399
|
+
(@structure - oldstructure).each do |x|
|
|
400
|
+
index = @structure.index(x)
|
|
401
|
+
if index == 0
|
|
402
|
+
obj = nil
|
|
403
|
+
else
|
|
404
|
+
obj = @structure[index-1]
|
|
405
|
+
end
|
|
406
|
+
#insert passes the object to be inserted and the object that comes before it
|
|
407
|
+
#this makes it easier to determine where to insert (I think)
|
|
408
|
+
@view.insert(x, obj)
|
|
409
|
+
end
|
|
410
|
+
elsif oldstructure.length > @structure.length
|
|
411
|
+
(oldstructure - @structure).each do |x|
|
|
412
|
+
@view.remove(x)
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
#switch the active tab if the active one got removed
|
|
417
|
+
unless @structure.include? @active
|
|
418
|
+
if oldstructure.index(@active) == 0
|
|
419
|
+
set_active(@structure[0])
|
|
420
|
+
elsif oldstructure.include? @active
|
|
421
|
+
#try to go to the next channel, but don't try too hard
|
|
422
|
+
if oldstructure[oldstructure.index(@active)+1].kind_of? ChannelBuffer
|
|
423
|
+
set_active(oldstructure[oldstructure.index(@active)+1])
|
|
424
|
+
else
|
|
425
|
+
set_active(oldstructure[oldstructure.index(@active)-1])
|
|
426
|
+
end
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
@structure.uniq
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
class Buffer
|
|
434
|
+
include PluginAPI
|
|
435
|
+
include BufferParser
|
|
436
|
+
include TabCompleteModule
|
|
437
|
+
attr_reader :buffer, :name, :commandbuffer, :controller, :main
|
|
438
|
+
attr_accessor :status
|
|
439
|
+
def initialize(*args)
|
|
440
|
+
@controller = nil
|
|
441
|
+
@main = args[-1]
|
|
442
|
+
@config = @main.config
|
|
443
|
+
@status = 0
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
def controller=(controller)
|
|
447
|
+
@controller = controller
|
|
448
|
+
@config = controller.config
|
|
449
|
+
@main = @controller.window.main
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
def set_status(status)
|
|
453
|
+
@controller.set_status(self, status)
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
def close
|
|
457
|
+
@buffer = nil
|
|
458
|
+
@controller.close_buffer(self)
|
|
459
|
+
end
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
class ConsoleBuffer < Buffer
|
|
463
|
+
def initialize(main)
|
|
464
|
+
@main = main
|
|
465
|
+
@config = @main.config
|
|
466
|
+
@controllers = []
|
|
467
|
+
@buffer = BufferView.new(@config)
|
|
468
|
+
@name = 'Console'
|
|
469
|
+
@commandbuffer = CommandBuffer.new(@config)
|
|
470
|
+
@status = 0
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
def add_controller(controller)
|
|
474
|
+
@controllers.push(controller)
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
def set_status(status)
|
|
478
|
+
@controllers.each{|x| x.set_status(self, status)}
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
class NetworkBuffer < Buffer
|
|
483
|
+
attr_reader :presence, :users
|
|
484
|
+
#attr_writer :username
|
|
485
|
+
def initialize(name, presence, main)
|
|
486
|
+
super
|
|
487
|
+
@name = name
|
|
488
|
+
@presence = presence
|
|
489
|
+
@username = presence
|
|
490
|
+
@users = UserList.new
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
def username
|
|
494
|
+
@username
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
def username=(username)
|
|
498
|
+
@username = username
|
|
499
|
+
@controller.window.get_username if @controller.active.respond_to? :network and @controller.active.network == self
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
def network
|
|
503
|
+
self
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
def connect
|
|
507
|
+
@connected = true
|
|
508
|
+
@buffer ||= BufferView.new(@config)
|
|
509
|
+
@commandbuffer ||= CommandBuffer.new(@config)
|
|
510
|
+
@controller.connect(self)
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
def connected?
|
|
514
|
+
@connected
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
def disconnect
|
|
518
|
+
@connected = nil
|
|
519
|
+
# @commandbuffer = nil
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
def close
|
|
523
|
+
disconnect
|
|
524
|
+
@commandbuffer = nil
|
|
525
|
+
super
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
def reconnect
|
|
529
|
+
#TODO
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
def identifier_string
|
|
533
|
+
"network=#{@name};mypresence=#{@presence}"
|
|
534
|
+
end
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
class ChatBuffer < Buffer
|
|
538
|
+
attr_reader :network, :name, :presence, :users
|
|
539
|
+
def initialize(name, network, main)
|
|
540
|
+
super
|
|
541
|
+
@name = name
|
|
542
|
+
@network = network
|
|
543
|
+
@presence = network.presence
|
|
544
|
+
@buffer = BufferView.new(@config)
|
|
545
|
+
@users = UserList.new
|
|
546
|
+
@commandbuffer = CommandBuffer.new(@config)
|
|
547
|
+
|
|
548
|
+
#fill the userlist... there's only 2 people in a chat
|
|
549
|
+
@users.add(network.users[username])
|
|
550
|
+
@users.add(network.users[name])
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
def username
|
|
554
|
+
@network.username
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
def identifier_string
|
|
558
|
+
"network=#{@network.name};mypresence=#{@presence};presence=#{@name}"
|
|
559
|
+
end
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
class ChannelBuffer < Buffer
|
|
563
|
+
attr_reader :network, :name, :presence, :users, :topic, :userlistview
|
|
564
|
+
attr_accessor :eventsync, :usersync
|
|
565
|
+
def initialize(name, network, main)
|
|
566
|
+
super
|
|
567
|
+
@topic = ''
|
|
568
|
+
@name = name
|
|
569
|
+
@network = network
|
|
570
|
+
@presence = network.presence
|
|
571
|
+
@eventsync = @usersync = false
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
def topic=(topic)
|
|
575
|
+
@topic = topic
|
|
576
|
+
@controller.window.update_topic if @controller.active == self
|
|
577
|
+
end
|
|
578
|
+
|
|
579
|
+
def username
|
|
580
|
+
@network.username
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
def join
|
|
584
|
+
@joined = true
|
|
585
|
+
@buffer ||= BufferView.new(@config)
|
|
586
|
+
@users ||= ChannelUserList.new
|
|
587
|
+
@userlistview ||= UserListView.new(self)
|
|
588
|
+
@users.view ||= @userlistview
|
|
589
|
+
@commandbuffer ||= CommandBuffer.new(@config)
|
|
590
|
+
@controller.join(self)
|
|
591
|
+
#@userlist = SomeUnwrittenClass.new
|
|
592
|
+
end
|
|
593
|
+
|
|
594
|
+
def joined?
|
|
595
|
+
@joined
|
|
596
|
+
end
|
|
597
|
+
|
|
598
|
+
def close
|
|
599
|
+
@commandbuffer = nil
|
|
600
|
+
@userlistview = nil
|
|
601
|
+
part
|
|
602
|
+
super
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
def part
|
|
606
|
+
@joined = false
|
|
607
|
+
@users = nil
|
|
608
|
+
@userlistview.clear if @userlistview
|
|
609
|
+
#@users.clear
|
|
610
|
+
end
|
|
611
|
+
def identifier_string
|
|
612
|
+
"network=#{@network.name};mypresence=#{@presence};channel=#{@name}"
|
|
613
|
+
end
|
|
614
|
+
end
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
#******some testing******
|
|
618
|
+
|
|
619
|
+
#~ f = NetworkController.new(nil, true)
|
|
620
|
+
#~ f.set_sort(NetworkModel::HIERARCHICAL)
|
|
621
|
+
#~ f.set_comparator(NetworkModel::INSENSITIVE)
|
|
622
|
+
#~ n = f.add_network('Freenode', 'Vagabond')
|
|
623
|
+
#~ f.add_channel('#icecap', n)
|
|
624
|
+
#~ f.add_channel('#aardvark', n)
|
|
625
|
+
#~ f.add_chat('foo', n)
|
|
626
|
+
#~ f.add_channel('#zztop', n)
|
|
627
|
+
#~ n = f.add_network('EFNet', 'Vagabond')
|
|
628
|
+
#~ f.add_channel('#dragonflybsd', n)
|
|
629
|
+
#~ f.add_channel('#Foo', n)
|
|
630
|
+
#~ n = f.add_network('arpanet', 'Vagabond')
|
|
631
|
+
|
|
632
|
+
#~ puts f.find_network('EFNet', 'Vagabond')
|
|
633
|
+
#~ puts f.find_channel('Freenode', 'Vagabond', '#icecap')
|
|
634
|
+
#~ puts f.find_chat('Freenode', 'Vagabond', 'foo')
|
|
635
|
+
|
|
636
|
+
#~ #f.structure.each{|x| puts x.name}
|
|
637
|
+
#~ Gtk::Window.new.add(f.view.widget).show_all
|
|
638
|
+
|
|
639
|
+
#~ Thread.new do
|
|
640
|
+
#~ sleep 4
|
|
641
|
+
#~ f.remove_network(f.find_network('arpanet', 'Vagabond'))
|
|
642
|
+
#~ f.remove_channel(f.find_channel('Freenode', 'Vagabond', '#icecap'))
|
|
643
|
+
#~ end
|
|
644
|
+
|
|
645
|
+
#~ Gtk::main
|
|
646
|
+
|
|
647
|
+
#~ f.sort.each{|x| puts x.name}
|
|
648
|
+
|
|
649
|
+
#~ f.remove_channel(f.find_channel('Freenode', 'Vagabond', '#icecap'))
|
|
650
|
+
#~ puts
|
|
651
|
+
|
|
652
|
+
#~ f.sort.each{|x| puts x.name}
|