weechat 0.0.1

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,24 @@
1
+ module Weechat
2
+ # Note: As opposed to plain WeeChat, we properly parse arguments
3
+ # given to a command, like a shell would.
4
+ class Modifier < Hook
5
+ attr_reader :modifier
6
+ def initialize(modifier, &callback)
7
+ super
8
+ @modifier = modifier.to_s
9
+ @callback = callback # we do not use the Callback class
10
+ # here because we need the return
11
+ # value of the callback
12
+ @ptr = Weechat.hook_modifier(modifier, "modifier_callback", id.to_s)
13
+ end
14
+
15
+ alias_method :exec, :call
16
+
17
+ class << self
18
+ def call(modifier, data, string)
19
+ Weechat.hook_modifier_exec(modifier.to_s, data.to_s, string.to_s)
20
+ end
21
+ alias_method :exec, :call
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,46 @@
1
+ module Weechat
2
+ class Option < Blankslate
3
+ @options = [] # we can't use a Hash because hashing
4
+ # blankslate... breaks things
5
+
6
+
7
+ def self.options
8
+ @options
9
+ end
10
+
11
+ def initialize(config, option)
12
+ self.__class__.options << [config, option, self]
13
+ @old_obj = config.__get(option)
14
+ @config = config
15
+ @option = option
16
+ @frozen = false
17
+ end
18
+
19
+ def __freeze__
20
+ @frozen = true
21
+ end
22
+
23
+ def method_missing(m, *args, &block)
24
+ if @frozen
25
+ obj = @old_obj
26
+ else
27
+ obj = @config.__get(@option)
28
+ end
29
+ ret = obj.__send__(m, *args, &block)
30
+
31
+ if (@old_obj != obj) && !@frozen
32
+ @config.set!(@option, obj)
33
+ end
34
+
35
+ unless @frozen
36
+ begin
37
+ @old_obj = obj.dup
38
+ rescue TypeError
39
+ @old_obj = obj
40
+ end
41
+ end
42
+
43
+ ret
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,106 @@
1
+ module Weechat
2
+ # == Gettable properties
3
+ #
4
+ # [filename] Filename of the plugin
5
+ # [handle] ?
6
+ # [name] Name of the plugin
7
+ # [description] Description of the plugin
8
+ # [author] Author of the plugin
9
+ # [version] Version of the plugin
10
+ # [license] Licence of the plugin
11
+ # [charset] ?
12
+ # [debug?] ?
13
+ class Plugin
14
+ include Weechat::Pointer
15
+ extend Weechat::Properties
16
+
17
+ @mappings = {
18
+ :licence => :license,
19
+ :debug? => :debug,
20
+ }
21
+
22
+ @transformations = {
23
+ [:debug] => lambda {|v| Weechat.integer_to_bool(v) },
24
+ }
25
+
26
+ init_properties
27
+
28
+ class << self
29
+ def find_by_name(name)
30
+ if name.nil? or name.empty? or name == "core"
31
+ return Plugin.new("")
32
+ end
33
+ plugins.find {|plugin| plugin.name == name}
34
+ end
35
+ alias_method :find, :find_by_name
36
+
37
+ def plugins
38
+ plugins = [Plugin.new("")]
39
+ Weechat::Infolist.parse("plugin").each do |plugin|
40
+ plugins << Plugin.new(plugin[:pointer])
41
+ end
42
+ plugins
43
+ end
44
+ alias_method :all, :plugins
45
+
46
+ # Loads a plugin.
47
+ #
48
+ # @return [void]
49
+ def load(name)
50
+ Weechat.exec("/plugin load #{name}")
51
+ end
52
+
53
+ # Reloads all plugins.
54
+ #
55
+ # Note: This will not reload the ruby plugin.
56
+ #
57
+ # @return [Array<Plugin>] All plugins that have been reloaded.
58
+ def reload_all
59
+ plugins = all.select{|plugin| plugin.name != "ruby"}
60
+ plugins.each {|plugin| plugin.reload}
61
+ end
62
+ end
63
+
64
+ def name
65
+ Weechat.plugin_get_name(@ptr)
66
+ end
67
+
68
+ # Unloads the plugin.
69
+ #
70
+ # @param [Boolean] force If the plugin to be unloaded is "ruby",
71
+ # +force+ has to be true.
72
+ # @return [Boolean] true if we attempted to unload the plugin
73
+ def unload(force = false)
74
+ if name == "ruby" and !force
75
+ Weechat.puts "Won't unload the ruby plugin unless you force it."
76
+ false
77
+ else
78
+ Weechat.exec("/plugin unload #{name}")
79
+ true
80
+ end
81
+ end
82
+
83
+ # Reload the plugin.
84
+ #
85
+ # @param [Boolean] force If the plugin to be reloaded is "ruby", +force+ has to be true.
86
+ # @return [Boolean] true if we attempted to reload the plugin
87
+ def reload(force = false)
88
+ if name == "ruby" and !force
89
+ Weechat.puts "Won't reload the ruby plugin unless you force it."
90
+ else
91
+ Weechat.exec("/plugin reload #{name}")
92
+ end
93
+ end
94
+
95
+ # Returns an array of all scripts loaded by this plugin.
96
+ #
97
+ # @return [Array<Script>]
98
+ def scripts
99
+ scripts = []
100
+ Infolist.parse("#{name}_script").each do |script|
101
+ scripts << Script.new(script[:pointer], self)
102
+ end
103
+ scripts
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,28 @@
1
+ module Weechat
2
+ module Pointer
3
+ attr_reader :ptr
4
+ alias_method :pointer, :ptr
5
+
6
+ def to_s
7
+ @ptr
8
+ end
9
+
10
+ def initialize(ptr)
11
+ @ptr = ptr
12
+ end
13
+
14
+ def ==(other)
15
+ @ptr == other.ptr
16
+ end
17
+ alias_method :eql?, "=="
18
+ alias_method :equal?, "=="
19
+
20
+ def hash
21
+ @ptr.hash
22
+ end
23
+
24
+ def inspect
25
+ sprintf "#<%s:0x%x @ptr=%p>", self.class, object_id << 1, @ptr
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,32 @@
1
+ module Weechat
2
+ class Process < Hook
3
+ # Returns a new instance of Process
4
+ #
5
+ # @param [String] command Command to execute
6
+ # @param [Integer] timeout Timeout after which to terminate the process
7
+ # @param [Boolean] collect If true, buffer output until process ends
8
+
9
+ attr_reader :collect
10
+ def initialize(command, timeout = 0, collect = false, &callback)
11
+ super
12
+ @command = command
13
+ @collect = collect
14
+ @stdout, @stderr = [], []
15
+ @callback = Callback.new(callback)
16
+ @ptr = Weechat.hook_process(command, timeout, "process_callback", id.to_s)
17
+ end
18
+
19
+ def stdout
20
+ @stdout.join("")
21
+ end
22
+
23
+ def stderr
24
+ @stderr.join("")
25
+ end
26
+
27
+ def buffer(stdout, stderr)
28
+ @stdout << stdout
29
+ @stderr << stderr
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,312 @@
1
+ module Weechat
2
+ module Properties
3
+ module ClassMethods
4
+ # Returns all known properties.
5
+ #
6
+ # @return [Array<Symbol>] The properties
7
+ def known_properties
8
+ @known_integer_properties + @known_string_properties
9
+ end
10
+
11
+ def known_integer_properties
12
+ @known_integer_properties
13
+ end
14
+
15
+ def known_string_properties
16
+ @known_string_properties
17
+ end
18
+
19
+ def settable_properties
20
+ @settable_properties
21
+ end
22
+
23
+ def transformations
24
+ @transformations
25
+ end
26
+
27
+ def rtransformations
28
+ @rtransformations
29
+ end
30
+
31
+ def mappings
32
+ @mappings
33
+ end
34
+
35
+ def type
36
+ @type
37
+ end
38
+
39
+ def init_properties
40
+ @known_string_properties ||= [].freeze
41
+ @known_integer_properties ||= [].freeze
42
+ @settable_properties ||= [].freeze
43
+ @transformations ||= {}.freeze
44
+ @rtransformations ||= {}.freeze
45
+ @mappings ||= {}.freeze
46
+
47
+ @type = self.name.downcase.split("::").last
48
+
49
+ # this defines all the getter methods
50
+ known_properties.each do |property|
51
+ define_method(property) { get_property(property) }
52
+ end
53
+
54
+ # this defined all the setter methods
55
+ @settable_properties.each do |property|
56
+ define_method(property + '=') {|v| set_property(property, v, true) }
57
+ end
58
+
59
+ # this adds a few aliases to make interfaces more rubyish
60
+ @mappings.each do |key, value|
61
+ if respond_to?(value)
62
+ # it is a string/integer property
63
+ alias_method key, value
64
+ else
65
+ # it is an infolist property
66
+ define_method(key) do |*args|
67
+ __send__(value, *args)
68
+ end
69
+ end
70
+
71
+ end
72
+
73
+ InstanceMethods.alias_methods(@type)
74
+ include InstanceMethods
75
+ end
76
+
77
+ def apply_transformation(property, value)
78
+ Utilities.apply_transformation(property, value, @transformations)
79
+ end
80
+ end
81
+
82
+ module InstanceMethods
83
+ # Get a property. Transformations, if appropriate, will be applied to the value
84
+ # before returning it. This means that e.g. 0 and 1 might be turned into false and true.
85
+ #
86
+ # @raise [Exception::UnknownProperty]
87
+ # @return [String, Number, Boolean]
88
+ # @see #get_integer_property
89
+ # @see #get_string_property
90
+ # @see #get_infolist_property
91
+ # @see #set_property
92
+ def get_property(property)
93
+ raise Exception::UnknownProperty.new(property) unless valid_property?(property)
94
+ case ret = __get_property(property)
95
+ when true, false, nil
96
+ ret
97
+ else
98
+ Property.new(self, property)
99
+ end
100
+ end
101
+
102
+ # @private
103
+ def __get_property(property)
104
+ property = property.to_s
105
+ if valid_property?(property, :integer)
106
+ v = get_integer_property(property)
107
+ elsif valid_property?(property, :string)
108
+ v = get_string_property(property)
109
+ elsif valid_property?(property, :infolist)
110
+ v = get_infolist_property(property)
111
+ else
112
+ raise Exception::UnknownProperty.new(property)
113
+ end
114
+
115
+ return self.class.apply_transformation(property, v)
116
+ end
117
+
118
+ # Returns an integer property.
119
+ #
120
+ # @raise [Exception::UnknownProperty]
121
+ # @return [Number]
122
+ # @see #get_integer
123
+ # @see #get_property
124
+ # @see #get_string_property
125
+ # @see #get_infolist_property
126
+ def get_integer_property(property)
127
+ property = property.to_s
128
+ raise Exception::UnknownProperty.new(property) unless valid_property?(property, :integer)
129
+ get_integer(property)
130
+ end
131
+
132
+ # Returns an integer property, not doing any checks.
133
+ #
134
+ # @return [Number]
135
+ # @see #get_integer_property
136
+ # @see #get_string
137
+ # @see #get_property
138
+ def get_integer(property)
139
+ Weechat.__send__("#{self.class.type}_get_integer", @ptr, property.to_s).to_i
140
+ end
141
+
142
+ # Returns a string property.
143
+ #
144
+ # @raise [Exception::UnknownProperty]
145
+ # @return [String]
146
+ # @see #get_string
147
+ # @see #get_property
148
+ # @see #get_integer_property
149
+ # @see #set_string_property
150
+ def get_string_property(property)
151
+ property = property.to_s
152
+ raise Exception::UnknownProperty.new(property) unless valid_property?(property, :string)
153
+ get_string(property)
154
+ end
155
+
156
+ # Returns a string property, not doing any checks.
157
+ #
158
+ # @return [String]
159
+ # @see #get_string_property
160
+ # @see #get_property
161
+ # @see #get_integer
162
+ # @see #set_string_property
163
+ def get_string(property)
164
+ Weechat.__send__("#{self.class.type}_get_string", @ptr, property.to_s)
165
+ end
166
+
167
+ # Returns a hash representation of the associated infolist.
168
+ #
169
+ # @return [Hash{Symbol => Object}] All properties in the infolist
170
+ def get_infolist
171
+ Weechat::Infolist.parse(self.class.type, @ptr)
172
+ end
173
+
174
+ # Returns a property obtained by an infolist.
175
+ #
176
+ # @raise [Exception::UnknownProperty]
177
+ # @return [String]
178
+ # @see #get_property
179
+ # @see #get_string_property
180
+ # @see #get_integer_property
181
+ def get_infolist_property(property)
182
+ property = property.to_sym
183
+ values = get_infolist.first
184
+ raise Exception::UnknownProperty.new(property.to_s) unless values[property]
185
+ values[property]
186
+ end
187
+
188
+ # Checks if a property can be set.
189
+ #
190
+ # @return [Boolean]
191
+ # @see #valid_property?
192
+ # @see #set_property
193
+ def settable_property?(property)
194
+ set_method = "#{self.class.type}_set"
195
+ return false unless Weechat.respond_to?(set_method)
196
+
197
+ property = property.to_s
198
+ self.class.settable_properties.include?(property)
199
+ end
200
+
201
+ # Sets a property. Transformations, if appropriate, will be applied to the value
202
+ # before setting it. This means that e.g. true and false will be turned into 1 and 0.
203
+ #
204
+ # @raise [Exception::UnsettableProperty]
205
+ # @return [String, Integer] The value after if has been transformed
206
+ # @see #set_string_property
207
+ # @see #set
208
+ def set_property(property, v, freeze = false)
209
+ property = property.to_s
210
+ raise Exception::UnsettableProperty.new(property) unless settable_property?(property)
211
+ v = Utilities.apply_transformation(property, v, self.class.rtransformations)
212
+
213
+ set(property, v)
214
+ if freeze
215
+ Property.properties.each do |prop|
216
+ if prop[0..1] == [@ptr, property]
217
+ prop[2].__freeze__
218
+ end
219
+ end
220
+ end
221
+ end
222
+
223
+ # Sets a string property, not applying any transformations.
224
+ #
225
+ # @raise [Exception::UnsettableProperty]
226
+ # @return [String] The value
227
+ # @see #set_property
228
+ # @see #set
229
+ def set_string_property(property, v)
230
+ property = property.to_s
231
+ raise Exception::UnsettableProperty.new(property) unless settable_property?(property)
232
+ set(property, v)
233
+ end
234
+
235
+ # Sets a property, not doing any checks or conversions whatsoever.
236
+ #
237
+ # @return [Object] The value
238
+ # @see #set_property
239
+ # @see #set_string_property
240
+ def set(property, value)
241
+ set_method = "#{self.class.type}_set"
242
+ raise CannotSetProperties unless Weechat.respond_to?(set_method)
243
+ Weechat.__send__(set_method, @ptr, property.to_s, value.to_s)
244
+ value
245
+ end
246
+
247
+ # Checks if a property is valid. That is, if get_(integer|string|infolist)_property are
248
+ # able to return a value.
249
+ #
250
+ # @param [#to_s] property The name of the property
251
+ # @param [Symbol] type The type of properties to check for.
252
+ # Can be one of :all, :string, :integer, :localvar or :infolist
253
+ # @return [Boolean]
254
+ # @see #settable_property?
255
+ # @see #get_property
256
+ def valid_property?(property, type = :all)
257
+ property = property.to_s
258
+ case type
259
+ when :all
260
+ valid_property?(property, :string) or
261
+ valid_property?(property, :integer) or
262
+ valid_property?(property, :localvar) or
263
+ valid_property?(property, :infolist)
264
+ when :string
265
+ self.class.known_string_properties.include?(property) or valid_property?(property, :localvar)
266
+ when :integer
267
+ self.class.known_integer_properties.include?(property)
268
+ when :localvar
269
+ property =~ /^localvar_.+$/
270
+ when :infolist
271
+ get_infolist.first[property.to_sym]
272
+ end
273
+ end
274
+
275
+ # method_missing returns buffer local variables.
276
+ #
277
+ # @return [String]
278
+ def method_missing(m, *args)
279
+ if args.empty? && valid_property?(m.to_s)
280
+ get_property(m.to_s)
281
+ else
282
+ super
283
+ end
284
+ end
285
+
286
+ # Returns a Hash representation of the object.
287
+ #
288
+ # @return [Hash{Symbol => Object}]
289
+ def to_h
290
+ h = {}
291
+ self.class.known_properties.each do |property|
292
+ val = __get_property(property)
293
+ h[property.to_sym] = val
294
+ end
295
+
296
+ get_infolist.first.each do |property, value|
297
+ prop = __get_property(property)
298
+ h[property] = prop
299
+ end
300
+
301
+ h
302
+ end
303
+
304
+ def self.alias_methods(type)
305
+ alias_method "#{type}_get_integer", :get_integer
306
+ alias_method "#{type}_get_string", :get_string
307
+ end
308
+ end
309
+
310
+ include ClassMethods
311
+ end
312
+ end