redcar 0.3.9.0dev → 0.3.9

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -3,9 +3,9 @@ Version 0.3.9 (TBA)
3
3
  ===================
4
4
 
5
5
  * Clojure REPL (David Byrne)
6
- * Remote edit files (Felipe Coury)
7
- * Remote directory view (Felipe Coury)
8
- * Connection manager (Felipe Coury)
6
+ * Remote edit files (Felipe Coury & Dan Lucraft)
7
+ * Remote directory view (Felipe Coury & Dan Lucraft)
8
+ * Connection manager (Felipe Coury & Dan Lucraft)
9
9
  * Added a truckload more Textmate themes (Dan Lucraft - thanks github.com/filmgirl !)
10
10
  * Fix crashing bug when exceptions have no message (Kieran Pilkington)
11
11
  * Runnables tab shows name of process (Delisa Mason)
@@ -23,7 +23,7 @@ Version 0.3.9 (TBA)
23
23
  * View keyboard shortcuts help command (Delisa Mason)
24
24
  * Clear REPL history command (David Byrne)
25
25
  * Change case commands (to uppercase, to lowercase, to titlecase, to opposite case, toggle snake_case/CamelCase/pascalCase) (Mat Schaffer)
26
- * Took 6.5 seconds off startup time (on my machine) (Dan Lucraft)
26
+ * Smarter word matching for Ruby (and internal changes to support differing definitions of "words" across languages.) (Johannes Wollert)
27
27
 
28
28
  Version 0.3.8.4 (24 July 2010)
29
29
  ==============================
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
- REDCAR_VERSION = "0.3.9.0dev"
1
+ REDCAR_VERSION = "0.3.9"
2
2
  require 'rubygems'
3
3
  require 'fileutils'
4
4
  require 'spec/rake/spectask'
@@ -173,6 +173,7 @@ module Redcar
173
173
 
174
174
  if File.open(path).read(200) =~ /Access Denied/
175
175
  puts "\n\n*** Error downloading #{uri}, got Access Denied from S3."
176
+ FileUtils.rm_rf(path)
176
177
  exit
177
178
  end
178
179
 
data/lib/redcar.rb CHANGED
@@ -41,7 +41,7 @@ require 'uri'
41
41
  #
42
42
  # and so on.
43
43
  module Redcar
44
- VERSION = '0.3.9.0dev'
44
+ VERSION = '0.3.9'
45
45
  VERSION_MAJOR = 0
46
46
  VERSION_MINOR = 3
47
47
  VERSION_RELEASE = 9
@@ -1,5 +1,6 @@
1
1
 
2
2
  Given /^I will choose "([^\"]*)" from the "([^\"]*)" dialog$/ do |path, type|
3
+ Redcar.gui.dialog_adapter.should_get_message(:any)
3
4
  Redcar.gui.dialog_adapter.set(type.to_sym, path)
4
5
  end
5
6
 
@@ -74,7 +74,8 @@ class FakeDialogAdapter
74
74
  end
75
75
 
76
76
  def message_box(*args)
77
- if @message
77
+ if @message == :any
78
+ elsif @message
78
79
  unless @message == args.first
79
80
  raise TestingError.new("expected the message #{@message.inspect} got #{args.first.inspect}")
80
81
  end
@@ -82,6 +83,7 @@ class FakeDialogAdapter
82
83
  else
83
84
  raise TestingError.new("got a message box showing #{args.first.inspect} when I didn't expect one")
84
85
  end
86
+ @responses[:message_box].to_sym if @responses[:message_box]
85
87
  end
86
88
 
87
89
  def check_for_raise(result)
@@ -46,6 +46,7 @@ module Redcar
46
46
  end
47
47
 
48
48
  def execute
49
+ return if @project.remote?
49
50
  file = Declarations::File.new(Declarations.file_path(@project))
50
51
  file.update_files(@file_list)
51
52
  file.dump
@@ -89,6 +90,11 @@ module Redcar
89
90
  class GoToTagCommand < EditTabCommand
90
91
 
91
92
  def execute
93
+ if Project::Manager.focussed_project.remote?
94
+ Application::Dialog.message_box("Go to declaration doesn't work in remote projects yet :(")
95
+ return
96
+ end
97
+
92
98
  if doc.selection?
93
99
  handle_tag(doc.selected_text)
94
100
  else
@@ -32,12 +32,6 @@ module Redcar
32
32
  end
33
33
  end
34
34
 
35
- class OppositeCaseTextCommand < TextConversionCommand
36
- def convert(text)
37
- text.tr('a-zA-Z', 'A-Za-z')
38
- end
39
- end
40
-
41
35
  class OppositeCaseTextCommand < TextConversionCommand
42
36
  def convert(text)
43
37
  text.tr('a-zA-Z', 'A-Za-z')
@@ -13,12 +13,16 @@ module Redcar
13
13
  end
14
14
 
15
15
  def connection
16
- @connection ||= Net::SSH.start(host, user, :password => password, :keys => private_key_files)
16
+ Redcar.timeout(10) do
17
+ @connection ||= Net::SSH.start(host, user, :password => password, :keys => private_key_files)
18
+ end
17
19
  rescue OpenSSL::PKey::DSAError => error
18
20
  puts "*** Warning, DSA keys not supported."
19
21
  # Error with DSA key. Throw us back to a password input. Think this is because jopenssl bugs
20
22
  # out on valid dsa keys.
21
23
  raise Net::SSH::AuthenticationFailed, "DSA key-based authentication failed."
24
+ rescue Redcar::TimeoutError
25
+ raise "connection to #{host} timed out"
22
26
  end
23
27
 
24
28
  def touch(file)
@@ -92,6 +96,10 @@ module Redcar
92
96
  contents
93
97
  end
94
98
 
99
+ def exists?(path)
100
+ is_file(path) or is_folder(path)
101
+ end
102
+
95
103
  def is_folder(path)
96
104
  result = exec(%Q(
97
105
  test -d "#{path}" && echo y
@@ -100,6 +108,14 @@ module Redcar
100
108
  result =~ /^y/ ? true : false
101
109
  end
102
110
 
111
+ def is_file(path)
112
+ result = exec(%Q(
113
+ test -f "#{path}" && echo y
114
+ ))
115
+
116
+ result =~ /^y/ ? true : false
117
+ end
118
+
103
119
  def with_cached_directories(dirs)
104
120
  @cached_dirs = list_dirs(dirs)
105
121
  @use_cache = true
@@ -141,8 +157,7 @@ module Redcar
141
157
  connection.exec!(what)
142
158
  end
143
159
  rescue Redcar::TimeoutError => e
144
- puts "#{host} connection timed out"
145
- puts caller
160
+ connection.shutdown!
146
161
  raise "#{host} connection timed out"
147
162
  end
148
163
  end
@@ -154,6 +169,7 @@ module Redcar
154
169
  connection.sftp.send(method, *args)
155
170
  end
156
171
  rescue Redcar::TimeoutError
172
+ connection.shutdown!
157
173
  raise "#{host} connection timed out"
158
174
  end
159
175
  end
@@ -133,18 +133,18 @@ module Redcar
133
133
  end
134
134
  end
135
135
 
136
- class OpenRemoteCommand < Command
137
- def initialize(url=nil)
138
- @url = url
139
- end
140
-
141
- def execute
142
- unless @url
143
- @speedbar = OpenRemoteSpeedbar.new
144
- win.open_speedbar(@speedbar)
145
- end
146
- end
147
- end
136
+ #class OpenRemoteCommand < Command
137
+ # def initialize(url=nil)
138
+ # @url = url
139
+ # end
140
+ #
141
+ # def execute
142
+ # unless @url
143
+ # @speedbar = OpenRemoteSpeedbar.new
144
+ # win.open_speedbar(@speedbar)
145
+ # end
146
+ # end
147
+ #end
148
148
 
149
149
  class FileSaveCommand < EditTabCommand
150
150
  def initialize(tab=nil)
@@ -233,6 +233,10 @@ module Redcar
233
233
  class FindFileCommand < ProjectCommand
234
234
 
235
235
  def execute
236
+ if Manager.focussed_project.remote?
237
+ Application::Dialog.message_box("Find file doesn't work in remote projects yet :(")
238
+ return
239
+ end
236
240
  dialog = FindFileDialog.new(Manager.focussed_project)
237
241
  dialog.open
238
242
  end
@@ -14,6 +14,11 @@ module Redcar
14
14
  end
15
15
  end
16
16
 
17
+ def handle_error(tree, error)
18
+ tree.close
19
+ Application::Dialog.message_box(error.message, :type => :error)
20
+ end
21
+
17
22
  class DragController
18
23
  include Redcar::Tree::Controller::DragController
19
24
 
@@ -160,6 +165,7 @@ module Redcar
160
165
  @pairs = nodes.map {|node| [node, File.basename(node.path)] }
161
166
  @match_pattern = ""
162
167
  @replace_pattern = ""
168
+ @adapter = DirController.adapter(nodes.first, tree)
163
169
  end
164
170
 
165
171
  def title
@@ -182,11 +188,15 @@ module Redcar
182
188
  old_name = File.basename(node.path)
183
189
  new_name = transform_name(old_name)
184
190
  new_path = File.join(File.dirname(node.path), new_name)
185
- conflicts = (File.exist?(new_path) and new_name != old_name)
191
+ conflicts = (@adapter.exists?(new_path) and new_name != old_name)
186
192
  legal = (new_name != "" and legal_path?(new_path))
187
193
  [new_name, conflicts, legal]
188
194
  end
189
195
  result
196
+ rescue => e
197
+ puts e.class
198
+ puts e.message
199
+ puts e.backtrace
190
200
  end
191
201
 
192
202
  def submit(params)
@@ -195,7 +205,8 @@ module Redcar
195
205
  new_name = transform_name(old_name)
196
206
  next if old_name == new_name
197
207
  new_path = File.join(File.dirname(node.path), new_name)
198
- FileUtils.mv(node.path, new_path)
208
+
209
+ @adapter.mv(node.path, new_path)
199
210
  end
200
211
  @tab.close
201
212
  @tree.refresh
@@ -240,7 +251,7 @@ module Redcar
240
251
  adapter = DirController.adapter(node, tree)
241
252
  adapter.mv(node.path, new_path)
242
253
  tree.refresh
243
- new_node = DirMirror::Node.create_from_path(adapter, new_path)
254
+ new_node = DirMirror::Node.create_from_path(adapter, {:fullname => new_path})
244
255
  tree.select(new_node)
245
256
  end
246
257
 
@@ -56,7 +56,7 @@ module Redcar
56
56
  #
57
57
  # @return [Node]
58
58
  def from_data(path)
59
- Node.create_from_path(@adapter, path)
59
+ Node.create_from_path(@adapter, {:fullname => path})
60
60
  end
61
61
 
62
62
  # Turn the nodes into data.
@@ -287,7 +287,7 @@ module Redcar
287
287
  item "Open", Project::FileOpenCommand
288
288
  item "Reload File", Project::FileReloadCommand
289
289
  item "Open Directory", Project::DirectoryOpenCommand
290
- item "Open Remote...", Project::OpenRemoteCommand
290
+ #item "Open Remote...", Project::OpenRemoteCommand
291
291
  lazy_sub_menu "Open Recent" do
292
292
  Project::RecentDirectories.generate_menu(self)
293
293
  end
@@ -324,7 +324,7 @@ module Redcar
324
324
  separator
325
325
  if tree.selection.length > 1
326
326
  dirs = tree.selection.map {|node| node.parent_dir }
327
- if dirs.uniq.length == 1
327
+ if dirs.uniq.length == 1 and node.adapter.is_a?(Adapters::Local)
328
328
  item("Bulk Rename") { controller.rename(tree, node) }
329
329
  end
330
330
  else
@@ -42,12 +42,16 @@ module Redcar
42
42
  if dir_mirror.exists?
43
43
  @tree = Tree.new(dir_mirror, Project::DirController.new)
44
44
  @window = nil
45
- file_list_resource.compute
45
+ file_list_resource.compute unless remote?
46
46
  else
47
47
  raise "#{path} doesn't seem to exist"
48
48
  end
49
49
  end
50
50
 
51
+ def remote?
52
+ adapter.is_a?(Adapters::Remote)
53
+ end
54
+
51
55
  def ready?
52
56
  @tree && @path
53
57
  end
@@ -80,7 +84,7 @@ module Redcar
80
84
  # there is one.
81
85
  def refresh
82
86
  @tree.refresh
83
- file_list_resource.compute
87
+ file_list_resource.compute unless remote?
84
88
  end
85
89
 
86
90
  def contains_path?(path)
@@ -106,6 +110,7 @@ module Redcar
106
110
  end
107
111
 
108
112
  def file_list
113
+ raise "can't access a file list for a remote project" if remote?
109
114
  @file_list ||= FileList.new(path)
110
115
  end
111
116
 
@@ -4,7 +4,7 @@ class Redcar::Project
4
4
  describe Adapters::RemoteProtocols::FTP do
5
5
  let(:conn) { double('connection') }
6
6
  subject do
7
- Adapters::RemoteProtocols::FTP.new('server', 'user', 'secret', nil, '/creation')
7
+ Adapters::RemoteProtocols::FTP.new('server', 'user', 'secret', [])
8
8
  end
9
9
 
10
10
  before(:each) do
@@ -20,7 +20,7 @@ class Redcar::Project
20
20
 
21
21
  describe 'methods' do
22
22
  subject do
23
- Adapters::RemoteProtocols::FTP.new('server', 'user', 'secret', nil, '/creation').tap do |ftp|
23
+ Adapters::RemoteProtocols::FTP.new('server', 'user', 'secret', []).tap do |ftp|
24
24
  ftp.stub!(:connection).and_return(conn)
25
25
  end
26
26
  end
@@ -30,8 +30,8 @@ class Redcar::Project
30
30
  mtime1 = stub('mtime1')
31
31
  mtime2 = stub('mtime2')
32
32
  subject.stub!(:fetch).with("/creation").and_return([
33
- { :fullname => '/creation/first_file.txt', :name => 'first_file.txt', :type => 'file', :mtime => mtime1 },
34
- { :fullname => '/creation/scripts', :name => 'scripts', :type => 'dir' , :mtime => mtime2 }
33
+ { :fullname => '/creation/first_file.txt', :name => 'first_file.txt', :type => :file, :mtime => mtime1 },
34
+ { :fullname => '/creation/scripts', :name => 'scripts', :type => :dir , :mtime => mtime2 }
35
35
  ])
36
36
  subject.mtime("/creation/first_file.txt").should == mtime1
37
37
  subject.mtime("/creation/scripts").should == mtime2
@@ -4,7 +4,7 @@ class Redcar::Project
4
4
  describe Adapters::RemoteProtocols::SFTP do
5
5
  let(:conn) { double('connection').as_null_object }
6
6
  subject do
7
- Adapters::RemoteProtocols::SFTP.new('server', 'user', 'secret', nil, '/home/fcoury')
7
+ Adapters::RemoteProtocols::SFTP.new('server', 'user', 'secret', [])
8
8
  end
9
9
 
10
10
  before(:each) do
@@ -12,64 +12,35 @@ class Redcar::Project
12
12
  end
13
13
 
14
14
  context "Public methods" do
15
- describe '#exist?' do
16
- it "returns true if fetch throws exception (path does not exist)" do
17
- subject.path = '/home/fcoury'
18
- subject.should_receive(:exec).with(/test -d "\/home\/fcoury"/).and_return("n\n")
19
- subject.exist?.should be_false
20
- end
21
-
22
- it "returns true if fetch runs" do
23
- subject.path = '/home/fcoury'
24
- subject.should_receive(:exec).with(/test -d "\/home\/fcoury"/).and_return("y\n")
25
- subject.exist?.should be_true
26
- end
27
- end
28
-
29
15
  describe '#directory?' do
30
16
  it "fetches the folder if it's not the base folder" do
31
17
  subject.stub!(:fetch).with("/home/fcoury").and_return([
32
- { :fullname => '/home/fcoury/hello_world.rb', :name => 'hello_world.rb', :type => 'file' },
33
- { :fullname => '/home/fcoury/snippets', :name => 'snippets', :type => 'dir' }
18
+ { :fullname => '/home/fcoury/hello_world.rb', :name => 'hello_world.rb', :type => :file },
19
+ { :fullname => '/home/fcoury/snippets', :name => 'snippets', :type => :dir }
34
20
  ])
35
21
  subject.directory?("/home/fcoury/hello_world.rb").should be_false
36
22
  subject.directory?("/home/fcoury/snippets").should be_true
37
23
  end
38
-
39
- it "checks for directory flag on the file if it's the base folder" do
40
- subject.path = '/home/fcoury'
41
- subject.stub!(:check_folder).with('/home/fcoury').and_return(true)
42
- subject.directory?("/home/fcoury").should be_true
43
- end
44
24
  end
45
25
 
46
26
  describe '#file?' do
47
27
  it "fetches the folder for the file" do
48
28
  subject.stub!(:fetch).with("/home/fcoury").and_return([
49
- { :fullname => '/home/fcoury/hello_world.rb', :name => 'hello_world.rb', :type => 'file' },
50
- { :fullname => '/home/fcoury/snippets', :name => 'snippets', :type => 'dir' }
29
+ { :fullname => '/home/fcoury/hello_world.rb', :name => 'hello_world.rb', :type => :file },
30
+ { :fullname => '/home/fcoury/snippets', :name => 'snippets', :type => :dir }
51
31
  ])
52
32
  subject.file?("/home/fcoury/hello_world.rb").should be_true
53
33
  subject.file?("/home/fcoury/snippets").should be_false
54
34
  end
55
35
  end
56
36
 
57
- describe '#fetch_contents' do
58
- it "return the name for all files retrieved" do
59
- subject.stub!(:fetch).with("/home/fcoury").and_return([
60
- { :fullname => '/home/fcoury/hello_world.rb', :name => 'hello_world.rb', :type => 'file' },
61
- { :fullname => '/home/fcoury/snippets', :name => 'snippets', :type => 'dir' }
62
- ])
63
- subject.fetch_contents("/home/fcoury").should == ['/home/fcoury/hello_world.rb', '/home/fcoury/snippets']
64
- end
65
- end
66
37
 
67
38
  describe '#load' do
68
39
  let(:conn) { double('connection').as_null_object }
69
40
  let(:sftp) { double('sftp connection').as_null_object }
70
41
 
71
42
  subject do
72
- Adapters::RemoteProtocols::SFTP.new('server', 'user', 'secret', nil, '/home/fcoury').tap do |protocol|
43
+ Adapters::RemoteProtocols::SFTP.new('server', 'user', 'secret', []).tap do |protocol|
73
44
  conn.stub!(:sftp).and_return(sftp)
74
45
  protocol.stub!(:connection).and_return(conn)
75
46
  end
@@ -103,7 +74,7 @@ class Redcar::Project
103
74
  let(:sftp) { double('sftp connection').as_null_object }
104
75
 
105
76
  subject do
106
- Adapters::RemoteProtocols::SFTP.new('server', 'user', 'secret', nil, '/home/fcoury').tap do |protocol|
77
+ Adapters::RemoteProtocols::SFTP.new('server', 'user', 'secret', []).tap do |protocol|
107
78
  conn.stub!(:sftp).and_return(sftp)
108
79
  protocol.stub!(:connection).and_return(conn)
109
80
  end
@@ -715,7 +715,7 @@ module Redcar
715
715
  link "Cmd+O", Project::FileOpenCommand
716
716
  link "Cmd+U", Project::FileReloadCommand
717
717
  link "Cmd+Shift+O", Project::DirectoryOpenCommand
718
- link "Cmd+Ctrl+O", Project::OpenRemoteCommand
718
+ #link "Cmd+Ctrl+O", Project::OpenRemoteCommand
719
719
  link "Cmd+S", Project::FileSaveCommand
720
720
  link "Cmd+Shift+S", Project::FileSaveAsCommand
721
721
  link "Cmd+Ctrl+R", Project::RevealInProjectCommand
@@ -784,7 +784,7 @@ module Redcar
784
784
  link "Ctrl+Alt+N", NewWindowCommand
785
785
  link "Ctrl+O", Project::FileOpenCommand
786
786
  link "Ctrl+Shift+O", Project::DirectoryOpenCommand
787
- link "Alt+Shift+O", Project::OpenRemoteCommand
787
+ #link "Alt+Shift+O", Project::OpenRemoteCommand
788
788
  link "Ctrl+S", Project::FileSaveCommand
789
789
  link "Ctrl+Shift+S", Project::FileSaveAsCommand
790
790
  link "Ctrl+Shift+R", Project::RevealInProjectCommand
@@ -83,6 +83,11 @@ module Redcar
83
83
  def visible_nodes
84
84
  controller.visible_nodes
85
85
  end
86
+
87
+ # Close the tree (removes it from the Window's Treebook)
88
+ def close
89
+ Redcar.app.windows.detect {|win| win.treebook.trees.include?(self) }.treebook.remove_tree(self)
90
+ end
86
91
  end
87
92
  end
88
93
 
@@ -23,10 +23,10 @@ module Redcar
23
23
  @viewer.get_tree.set_layout_data(grid_data)
24
24
  @composite.layout
25
25
  JFace::Viewers::ColumnViewerToolTipSupport.enableFor(@viewer)
26
- @viewer.set_content_provider(TreeMirrorContentProvider.new)
26
+ @viewer.set_content_provider(TreeMirrorContentProvider.new(self))
27
27
  #@viewer.getTree.setLinesVisible(true)
28
28
  #@viewer.getTree.setHeaderVisible(true)
29
- @viewer.set_label_provider(TreeMirrorLabelProvider.new)
29
+ @viewer.set_label_provider(TreeMirrorLabelProvider.new(self))
30
30
  @viewer.set_input(@model.tree_mirror)
31
31
 
32
32
  if @model.tree_controller
@@ -40,8 +40,12 @@ module Redcar
40
40
  register_dnd if @model.tree_mirror.drag_and_drop?
41
41
 
42
42
  @model.add_listener(:refresh) do
43
- @model.tree_mirror.refresh_operation(@model) do
44
- @viewer.refresh
43
+ begin
44
+ @model.tree_mirror.refresh_operation(@model) do
45
+ @viewer.refresh
46
+ end
47
+ rescue => e
48
+ handle_mirror_error(e)
45
49
  end
46
50
  end
47
51
 
@@ -276,6 +280,22 @@ module Redcar
276
280
  end
277
281
  end
278
282
 
283
+ def handle_mirror_error(e)
284
+ if @model.tree_controller.respond_to?(:handle_error)
285
+ begin
286
+ @model.tree_controller.handle_error(@model, e)
287
+ rescue => e
288
+ puts "error in error hander: #{e.class} #{e.message}"
289
+ puts e.backtrace
290
+ end
291
+ else
292
+ puts e.class
293
+ puts e.message
294
+ puts e.backtrace
295
+ Application::Dialog.message_box(e.message, :type => :error)
296
+ end
297
+ end
298
+
279
299
  class TreeListener
280
300
  def tree_collapsed(e)
281
301
  end
@@ -340,6 +360,7 @@ module Redcar
340
360
  else
341
361
  viewer.expandToLevel(double_clicked_element, 1)
342
362
  end
363
+ rescue
343
364
  end
344
365
  end
345
366
 
@@ -357,6 +378,10 @@ module Redcar
357
378
 
358
379
  class TreeMirrorContentProvider
359
380
  include JFace::Viewers::ITreeContentProvider
381
+
382
+ def initialize(tree_view_swt)
383
+ @tree_view_swt = tree_view_swt
384
+ end
360
385
 
361
386
  def input_changed(viewer, _, tree_mirror)
362
387
  @viewer, @tree_mirror = viewer, tree_mirror
@@ -364,6 +389,8 @@ module Redcar
364
389
 
365
390
  def get_elements(tree_mirror)
366
391
  tree_mirror.top.to_java
392
+ rescue => e
393
+ @tree_view_swt.handle_mirror_error(e)
367
394
  end
368
395
 
369
396
  def has_children(tree_node)
@@ -373,10 +400,14 @@ module Redcar
373
400
  children = tree_node.children
374
401
  children.any? if children
375
402
  end
403
+ rescue => e
404
+ @tree_view_swt.handle_mirror_error(e)
376
405
  end
377
406
 
378
407
  def get_children(tree_node)
379
408
  tree_node.children.to_java
409
+ rescue => e
410
+ @tree_view_swt.handle_mirror_error(e)
380
411
  end
381
412
 
382
413
  def get_parent(tree_node)
@@ -389,6 +420,10 @@ module Redcar
389
420
 
390
421
  class TreeMirrorLabelProvider
391
422
  include JFace::Viewers::ILabelProvider
423
+
424
+ def initialize(tree_view_swt)
425
+ @tree_view_swt = tree_view_swt
426
+ end
392
427
 
393
428
  def add_listener(*_)
394
429
  end