ruber 0.0.8 → 0.0.9

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.
Files changed (81) hide show
  1. data/CHANGES +21 -0
  2. data/data/share/apps/ruber/ruberui.rc +3 -1
  3. data/lib/ruber/application/application.rb +22 -23
  4. data/lib/ruber/application/plugin.yaml +7 -2
  5. data/lib/ruber/{projects → application}/project_files_list.rb +0 -0
  6. data/lib/ruber/{projects → application}/project_files_widget.rb +0 -0
  7. data/lib/ruber/application/ui/project_files_rule_chooser_widget.rb +74 -0
  8. data/lib/ruber/{projects → application}/ui/project_files_rule_chooser_widget.ui +0 -0
  9. data/lib/ruber/application/ui/project_files_widget.rb +117 -0
  10. data/lib/ruber/{projects → application}/ui/project_files_widget.ui +0 -0
  11. data/lib/ruber/component_manager.rb +14 -9
  12. data/lib/ruber/editor/document.rb +35 -5
  13. data/lib/ruber/kde_sugar.rb +16 -0
  14. data/lib/ruber/main_window/choose_plugins_dlg.rb +7 -4
  15. data/lib/ruber/main_window/main_window.rb +131 -193
  16. data/lib/ruber/main_window/main_window_actions.rb +157 -58
  17. data/lib/ruber/main_window/main_window_internal.rb +145 -54
  18. data/lib/ruber/main_window/open_file_in_project_dlg.rb +4 -4
  19. data/lib/ruber/main_window/plugin.yaml +3 -6
  20. data/lib/ruber/main_window/ui/workspace_settings_widget.rb +2 -2
  21. data/lib/ruber/main_window/workspace.rb +62 -32
  22. data/lib/ruber/output_widget.rb +20 -16
  23. data/lib/ruber/pane.rb +11 -5
  24. data/lib/ruber/project.rb +27 -12
  25. data/lib/ruber/projects/ui/project_files_rule_chooser_widget.rb +2 -2
  26. data/lib/ruber/projects/ui/project_files_widget.rb +2 -2
  27. data/lib/ruber/utils.rb +37 -4
  28. data/lib/ruber/version.rb +1 -1
  29. data/lib/ruber/world/document_factory.rb +121 -0
  30. data/lib/ruber/world/document_list.rb +396 -0
  31. data/lib/ruber/world/environment.rb +470 -0
  32. data/lib/ruber/{main_window → world}/hint_solver.rb +1 -1
  33. data/lib/ruber/world/plugin.yaml +11 -0
  34. data/lib/ruber/world/project_factory.rb +131 -0
  35. data/lib/ruber/world/project_list.rb +265 -0
  36. data/lib/ruber/world/ui/workspace_settings_widget.rb +51 -0
  37. data/lib/ruber/{main_window → world}/ui/workspace_settings_widget.ui +0 -0
  38. data/lib/ruber/world/world.rb +307 -0
  39. data/plugins/auto_end/auto_end.rb +135 -9
  40. data/plugins/autosave/autosave.rb +4 -4
  41. data/plugins/find_in_files/find_in_files.rb +5 -5
  42. data/plugins/find_in_files/find_in_files_widgets.rb +1 -1
  43. data/plugins/project_browser/project_browser.rb +4 -4
  44. data/plugins/rake/rake.rb +4 -4
  45. data/plugins/rake/rake_extension.rb +1 -1
  46. data/plugins/rspec/rspec.rb +4 -4
  47. data/plugins/rspec/ruber_rspec_formatter.rb +2 -2
  48. data/plugins/ruby_development/ruby_development.rb +3 -3
  49. data/plugins/ruby_runner/ruby_runner.rb +2 -2
  50. data/plugins/state/plugin.yaml +6 -8
  51. data/plugins/state/state.rb +201 -391
  52. data/plugins/state/ui/config_widget.rb +5 -5
  53. data/plugins/state/ui/config_widget.ui +3 -3
  54. data/plugins/syntax_checker/syntax_checker.rb +4 -0
  55. data/spec/annotation_model_spec.rb +1 -1
  56. data/spec/auto_end_spec.rb +98 -47
  57. data/spec/component_manager_spec.rb +80 -21
  58. data/spec/document_factory_spec.rb +115 -0
  59. data/spec/document_list_spec.rb +560 -450
  60. data/spec/document_spec.rb +143 -55
  61. data/spec/editor_view_spec.rb +2 -2
  62. data/spec/environment_spec.rb +1900 -0
  63. data/spec/hint_solver_spec.rb +5 -5
  64. data/spec/kde_sugar_spec.rb +16 -0
  65. data/spec/output_widget_spec.rb +177 -51
  66. data/spec/pane_spec.rb +29 -5
  67. data/spec/plugin_spec.rb +1 -1
  68. data/spec/project_factory_spec.rb +104 -0
  69. data/spec/project_list_spec.rb +352 -447
  70. data/spec/project_spec.rb +34 -33
  71. data/spec/qt_sugar_spec.rb +2 -2
  72. data/spec/state_spec.rb +508 -811
  73. data/spec/utils_spec.rb +149 -98
  74. data/spec/workspace_spec.rb +120 -9
  75. data/spec/world_spec.rb +1219 -0
  76. metadata +23 -14
  77. data/lib/ruber/documents/document_list.rb +0 -412
  78. data/lib/ruber/documents/plugin.yaml +0 -4
  79. data/lib/ruber/main_window/view_manager.rb +0 -431
  80. data/lib/ruber/projects/plugin.yaml +0 -11
  81. data/lib/ruber/projects/project_list.rb +0 -314
@@ -1,511 +1,416 @@
1
- require 'spec/common'
1
+ require './spec/framework'
2
+ require './spec/common'
3
+ require 'ruber/world/project_list'
4
+ require 'ruber/project'
2
5
 
3
- require 'flexmock'
6
+ require 'tmpdir'
4
7
 
5
- require 'ruber/projects/project_list'
6
- require 'ruber/plugin_specification'
7
-
8
- class Ruber::ProjectList::FakeProject < Qt::Object
9
-
10
- signals 'closing(QObject*)'
11
- attr_reader :project_name, :project_file
12
- def initialize name = 'test', file = nil
13
- super()
14
- @project_file = file || Array.new(6){97 + rand(26)}.join
15
- @project_name = name
16
- end
17
-
18
- def deactivate;end
19
-
20
- def activate;end
21
-
22
- def close
23
- emit closing(self)
24
- end
25
- end
26
-
27
- describe Ruber::ProjectList do
8
+ describe Ruber::World::ProjectList do
28
9
 
29
- it 'should mix-in Enumerable' do
30
- Ruber::ProjectList.ancestors.include?(Enumerable).should be_true
10
+ def create_project file, name = nil
11
+ name ||= file.sub(/[_-]/, ' ').sub('.ruprj','').capitalize
12
+ file = File.join Dir.tmpdir, file unless file.start_with? '/'
13
+ file += '.ruprj' unless file.end_with?('ruprj')
14
+ Ruber::Project.new file, name
31
15
  end
32
-
33
- end
34
-
35
- describe 'Ruber::ProjectList#project_for_file' do
36
16
 
37
17
  before do
38
- manager = flexmock('components'){|m| m.should_ignore_missing}
39
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(KDE::Application.instance).by_default
40
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil).by_default
41
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager).by_default
42
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
43
- @projects = Ruber::ProjectList.new manager, pdf
44
- end
45
-
46
- it 'returns nil if there\'s no current project' do
47
- flexmock(@projects).should_receive(:current).twice.and_return nil
48
- @projects.project_for_file(__FILE__, :active).should be_nil
49
- @projects.project_for_file(__FILE__, :all).should be_nil
18
+ @projects = 3.times.map{|i| create_project "project-#{i}"}
19
+ @list = Ruber::World::ProjectList.new @projects
50
20
  end
51
21
 
52
- it 'returns the current project if there\'s one and the file belongs to it' do
53
- prj = flexmock{|m| m.should_receive('project_files.file_in_project?').twice.with(__FILE__).and_return true}
54
- flexmock(@projects).should_receive(:current).twice.and_return prj
55
- @projects.project_for_file(__FILE__, :active).should == prj
56
- @projects.project_for_file(__FILE__, :all).should == prj
22
+ it 'includes the Enumerable module' do
23
+ Ruber::World::ProjectList.ancestors.should include(Enumerable)
57
24
  end
58
25
 
59
- it 'returns nil if the file doesn\'t belong to the current project and the second argument is :active, even if the file belongs to another project' do
60
- active_prj = flexmock{|m| m.should_receive('project_files.file_in_project?').once.with(__FILE__).and_return false}
61
- prj = flexmock{|m| m.should_receive('project_files.file_in_project?').with(__FILE__).and_return true}
62
- flexmock(@projects).should_receive(:current).once.and_return(active_prj)
63
- flexmock(@projects).should_receive(:each).and_yield(active_prj, prj)
64
- @projects.project_for_file(__FILE__, :active).should be_nil
65
- end
66
-
67
- it 'returns the first project to which the file belongs, if it doesn\'t belong to the current one and the second argument is :all' do
68
- active_prj = flexmock{|m| m.should_receive('project_files.file_in_project?').twice.with(__FILE__).and_return false}
69
- prjs = [
70
- flexmock{|m| m.should_receive('project_files.file_in_project?').with(__FILE__).once.and_return false},
71
- active_prj,
72
- flexmock{|m| m.should_receive('project_files.file_in_project?').with(__FILE__).once.and_return true},
73
- flexmock{|m| m.should_receive('project_files.file_in_project?').with(__FILE__).never}
74
- ]
75
- flexmock(@projects).should_receive(:current).once.and_return(active_prj)
76
- projects = {
77
- '0' => prjs[0],
78
- '1' => prjs[1],
79
- '2' => prjs[2],
80
- '3' => prjs[3]
81
- }
82
- @projects.instance_variable_set(:@projects, projects)
83
- @projects.project_for_file(__FILE__, :all).should equal(prjs[2])
84
- end
26
+ describe '.new' do
85
27
 
86
- it 'returns nil if the second argument is :all and the file doesn\'t belong to any project' do
87
- active_prj = flexmock{|m| m.should_receive('project_files.file_in_project?').twice.with(__FILE__).and_return false}
88
- prjs = [
89
- flexmock{|m| m.should_receive('project_files.file_in_project?').with(__FILE__).once.and_return false},
90
- active_prj,
91
- flexmock{|m| m.should_receive('project_files.file_in_project?').with(__FILE__).once.and_return false},
92
- flexmock{|m| m.should_receive('project_files.file_in_project?').with(__FILE__).once.and_return false}
93
- ]
94
- flexmock(@projects).should_receive(:current).once.and_return(active_prj)
95
- projects = {
96
- '0' => prjs[0],
97
- '1' => prjs[1],
98
- '2' => prjs[2],
99
- '3' => prjs[3]
100
- }
101
- @projects.instance_variable_set(:@projects, projects)
102
- @projects.project_for_file(__FILE__, :all).should be_nil
103
- end
104
-
105
- end
106
-
107
- describe 'Ruber::ProjectList#each_project' do
108
-
109
- before do
110
- app = Qt::Object.new
111
- manager = flexmock('components'){|m| m.should_ignore_missing}
112
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
113
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
114
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
115
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
116
- @keeper = Ruber::ProjectList.new manager, pdf
117
- end
118
-
119
-
120
- it 'should yield all the projects in the list if called with a block' do
121
- prjs = Array.new(3){|i| Ruber::ProjectList::FakeProject.new("test#{i}")}
122
- prjs.each{|pr| @keeper.add_project pr}
123
- res = []
124
- @keeper.each_project{|pr| res << pr}
125
- res.sort_by{|pr| pr.project_file}.should == prjs.sort_by{|pr| pr.project_file}
126
- end
127
-
128
- it 'should return an enumerable which yields all the projects in the list if called without a block' do
129
- prjs = Array.new(3){|i| Ruber::ProjectList::FakeProject.new("test#{i}")}
130
- prjs.each{|pr| @keeper.add_project pr}
131
- m = flexmock do |mk|
132
- prjs.each{|prj| mk.should_receive(:test).once.with prj}
28
+ it 'takes a hash or a DocumentList as argument' do
29
+ list = Ruber::World::ProjectList.new @projects
30
+ list.to_a.map(&:project_file).sort == @projects.map(&:project_file).sort
31
+ other_list = Ruber::World::ProjectList.new @projects
32
+ list = Ruber::World::ProjectList.new other_list
33
+ list.to_a.map(&:project_file).sort == @projects.map(&:project_file).sort
133
34
  end
134
- en = @keeper.each_project
135
- if RUBY_VERSION.match(/8/) then en.should be_an(Enumerable::Enumerator)
136
- else en.should be_an(Enumerator)
35
+
36
+ it 'creates a duplicate of the argument if it is a hash' do
37
+ list = Ruber::World::ProjectList.new @projects
38
+ new_project = create_project 'project-3'
39
+ @projects << new_project
40
+ list.count.should == 3
137
41
  end
138
- en.each{|prj| m.test prj}
139
- end
140
-
141
- end
142
-
143
- describe 'Ruber::ProjectList, when created' do
144
-
145
- before do
146
- app = Qt::Object.new
147
- manager = flexmock('components'){|m| m.should_ignore_missing}
148
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
149
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
150
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
151
- @pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
152
- @keeper = Ruber::ProjectList.new manager, @pdf
153
- end
154
-
155
- it 'should call its initialize_plugin method' do
156
- @keeper.plugin_description.should == @pdf
157
- end
158
-
159
- it 'should have no project' do
160
- @keeper.projects.should be_empty
161
- end
162
-
163
- it 'should have no current project' do
164
- @keeper.current_project.should be_nil
165
- end
166
-
167
- end
168
-
169
- describe 'Ruber::Project#current_project=, when called with a non-nil argument' do
170
-
171
- before do
172
- app = Qt::Object.new
173
- manager = flexmock('components'){|m| m.should_ignore_missing}
174
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
175
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
176
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
177
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
178
- @keeper = Ruber::ProjectList.new manager, pdf
179
- @prj = Ruber::ProjectList::FakeProject.new
180
- @keeper.instance_variable_get(:@projects)[@prj.project_file] = @prj
181
- @keeper.instance_variable_get(:@projects)['test'] = @prj
182
- end
183
-
184
- it 'should set the current project to its argument' do
185
- @keeper.current_project = @prj
186
- @keeper.current_project.should equal( @prj )
187
- end
188
-
189
- it 'should call the "deactivate" method of the old current project, if it\'s not nil' do
190
- @keeper.instance_variable_set(:@current_project, @prj)
191
- new_prj = Ruber::ProjectList::FakeProject.new 'Test1'
192
- @keeper.add_project new_prj
193
- flexmock(@prj).should_receive( :deactivate).once
194
- @keeper.current_project = new_prj
195
- @keeper.instance_variable_set :@current_project, nil
196
- lambda{@keeper.current_project = @prj}.should_not raise_error
197
- end
198
-
199
- it 'should emit the "current_project_changed(QObject*)" signal with the project as argument' do
200
- test = flexmock('test'){|m| m.should_receive(:current_project_changed).once.with(@prj)}
201
- @keeper.connect(SIGNAL('current_project_changed(QObject*)')){|o| test.current_project_changed(o)}
202
- @keeper.current_project = @prj
203
- end
204
-
205
- it 'should call the "activate" method of the new current project' do
206
- @keeper.instance_variable_set(:@current_project, @prj)
207
- new_prj = Ruber::ProjectList::FakeProject.new 'Test1'
208
- @keeper.add_project new_prj
209
- flexmock(new_prj).should_receive( :activate).once
210
- @keeper.current_project = new_prj
211
- end
212
-
213
- it 'should raise ArgumentError if the project is not in the project list' do
214
- @keeper.instance_variable_get(:@projects).clear
215
- lambda{@keeper.current_project = @prj}.should raise_error(ArgumentError, "Tried to set an unknown as current project")
216
- end
217
-
218
- end
219
-
220
- describe 'Ruber::Project#current_project=, when called with nil' do
221
-
222
- before do
223
- app = Qt::Object.new
224
- manager = flexmock('components'){|m| m.should_ignore_missing}
225
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
226
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
227
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
228
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
229
- @keeper = Ruber::ProjectList.new manager, pdf
230
- end
231
-
232
- it 'should set the current project to nil' do
233
- @keeper.current_project = nil
234
- @keeper.current_project.should be_nil
235
- end
236
-
237
- it 'should emit the "current_project_changed(QObject*)" signal with Qt::NilObject as argument' do
238
- test = flexmock('test'){|m| m.should_receive(:current_project_changed).once.with(nil)}
239
- @keeper.connect(SIGNAL('current_project_changed(QObject*)')){|o| test.current_project_changed(o)}
240
- @keeper.current_project = nil
241
- end
242
-
243
- end
244
-
245
- describe 'Ruber::ProjectList#add_project' do
246
-
247
- before do
248
- app = Qt::Object.new
249
- manager = flexmock('components'){|m| m.should_ignore_missing}
250
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
251
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
252
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
253
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
254
- @keeper = Ruber::ProjectList.new manager, pdf
255
- end
256
-
257
- it 'should add the project passed as argument to the list of projects' do
258
- prj = Ruber::ProjectList::FakeProject.new 'Test'
259
- @keeper.add_project prj
260
- @keeper.instance_variable_get(:@projects)[prj.project_file].should equal(prj)
42
+
43
+ it 'doesn\'t create a duplicate of the argument if it is a ProjectList' do
44
+ other_list = Ruber::World::ProjectList.new @projects
45
+ list = Ruber::World::ProjectList.new other_list
46
+ list.send(:project_hash).should equal(other_list.send(:project_hash))
47
+ end
48
+
49
+ it 'keeps a single copy of projects with the same project file' do
50
+ @projects << create_project('project-1')
51
+ @list = Ruber::World::ProjectList.new @projects
52
+ @list.to_a.select{|prj| prj.project_name == "Project 1"}.count.should == 1
53
+ end
54
+
261
55
  end
262
56
 
263
- it 'should return the project' do
264
- prj = Ruber::ProjectList::FakeProject.new 'Test'
265
- @keeper.add_project( prj).should equal(prj)
57
+ describe '#each' do
58
+
59
+ context 'when called with a block' do
60
+
61
+ it 'calls the block once for each project' do
62
+ res = []
63
+ @list.each{|prj| res << prj}
64
+ res.should == @projects
65
+ end
66
+
67
+ it 'returns self' do
68
+ @list.each{}.should equal(@list)
69
+ end
70
+
71
+ end
72
+
73
+ context 'when called without a block' do
74
+
75
+ it 'returns an Enumerator which iterates on the projects' do
76
+ res = []
77
+ enum = @list.each
78
+ enum.should be_an(Enumerator)
79
+ enum.each{|prj| res << prj}
80
+ res.should == @projects
81
+
82
+ end
83
+
84
+ end
85
+
266
86
  end
267
87
 
268
- it 'should emit the "project_added(QObject*)" signal passing the added project' do
269
- prj = Ruber::ProjectList::FakeProject.new 'Test'
270
- m = flexmock('test'){|mk| mk.should_receive(:project_added).once.with(prj)}
271
- @keeper.connect(SIGNAL('project_added(QObject*)')){|o| m.project_added(o)}
272
- @keeper.add_project prj
88
+ describe '#empty?' do
89
+
90
+ it 'returns true if the list doesn\'t contain any element' do
91
+ list = Ruber::World::ProjectList.new({})
92
+ list.should be_empty
93
+ end
94
+
95
+ it 'returns false if the list contains at least one element' do
96
+ @list.should_not be_empty
97
+ end
98
+
273
99
  end
274
100
 
275
- it 'should raise RuntimeError if the project is already in the list' do
276
- prj_file = File.expand_path('test.ruprj')
277
- prj1 = Ruber::ProjectList::FakeProject.new 'test1', prj_file
278
- prj2 = Ruber::ProjectList::FakeProject.new 'test2', prj_file
279
- @keeper.add_project prj1
280
- lambda{@keeper.add_project prj2}.should raise_error(RuntimeError, "A project with project file #{prj_file} is already open")
101
+ describe '#size' do
102
+
103
+ it 'returns the number of elements in the list' do
104
+ list = Ruber::World::ProjectList.new({})
105
+ list.size.should == 0
106
+ list = Ruber::World::ProjectList.new @projects
107
+ list.size.should == 3
108
+ end
109
+
281
110
  end
282
111
 
283
- end
284
-
285
- describe 'Ruber::ProjectList, when a project in the list is closed' do
286
-
287
- before do
288
- app = Qt::Object.new
289
- manager = flexmock('components'){|m| m.should_ignore_missing}
290
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
291
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
292
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
293
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
294
- @keeper = Ruber::ProjectList.new manager, pdf
112
+ describe '#==' do
113
+
114
+ context 'when the argument is a ProjectList' do
115
+
116
+ it 'returns true if the argument contains the same projects' do
117
+ other = Ruber::World::ProjectList.new @projects
118
+ @list.should == other
119
+ end
120
+
121
+ it 'returns false if the argument contains different projects' do
122
+ new_prj = create_project 'project-3'
123
+ @projects << new_prj
124
+ other = Ruber::World::ProjectList.new @projects
125
+ @list.should_not == other
126
+ end
127
+
128
+ end
129
+
130
+ context 'when the argument is an Array' do
131
+
132
+ it 'returns true if the argument contains the same projects' do
133
+ @list.should == @projects.reverse
134
+ end
135
+
136
+ it 'returns false if the argument contains different projects' do
137
+ @list.should_not == [@projects[0], 'x']
138
+ end
139
+
140
+ end
141
+
142
+ context 'when the argument is neither a ProjectList nor an array' do
143
+
144
+ it 'returns false' do
145
+ @list.should_not == {}
146
+ @list.should_not == 'x'
147
+ end
148
+
149
+ end
150
+
295
151
  end
296
152
 
297
- it 'should emit the "project_closing" signal, passing the project as argument' do
298
- prj = Ruber::ProjectList::FakeProject.new
299
- @keeper.add_project prj
300
- m = flexmock{|mk| mk.should_receive(:project_closing).once}
301
- @keeper.connect(SIGNAL('closing_project(QObject*)')){|o| m.project_closing(o)}
302
- prj.close
153
+ describe '#eql?' do
154
+
155
+ context 'when the argument is a ProjectList' do
156
+
157
+ it 'returns true if the argument contains the same projects' do
158
+ other = Ruber::World::ProjectList.new @projects
159
+ @list.should eql(other)
160
+ end
161
+
162
+ it 'returns false if the argument contains different projects' do
163
+ new_prj = create_project 'project-3'
164
+ @projects << new_prj
165
+ other = Ruber::World::ProjectList.new @projects
166
+ @list.should_not eql(other)
167
+ end
168
+
169
+ end
170
+
171
+ context 'when the argument is not a ProjectList' do
172
+
173
+ it 'returns false' do
174
+ @list.should_not eql({})
175
+ @list.should_not eql('x')
176
+ @list.should_not eql(@projects)
177
+ end
178
+
179
+ end
180
+
303
181
  end
304
182
 
305
- it 'should set the current project to nil if the closed project was the current one' do
306
- prj = Ruber::ProjectList::FakeProject.new
307
- @keeper.add_project prj
308
- @keeper.current_project = prj
309
- prj.close
310
- @keeper.current_project.should be_nil
183
+ describe '#hash' do
184
+
185
+ it 'returns the same value as an hash contining the same arguments' do
186
+ @list.hash.should == Hash[@projects.map{|prj| [prj.project_file, prj]}].hash
187
+ end
188
+
311
189
  end
312
-
313
- end
314
190
 
315
- describe 'Ruber::ProjectList#close_current_project' do
316
-
317
- include FlexMock::ArgumentTypes
318
-
319
- before do
320
- app = Qt::Object.new
321
- manager = flexmock('components'){|m| m.should_ignore_missing}
322
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
323
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
324
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
325
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
326
- @keeper = Ruber::ProjectList.new manager, pdf
327
- @prj = Ruber::ProjectList::FakeProject.new{self.object_name = 'project'}
328
- @keeper.add_project = @prj
329
- @keeper.current_project= @prj
330
- end
331
-
332
- it 'should set the current project to nil' do
333
- flexmock(@keeper).should_receive(:current_project=).with(nil).once
334
- @keeper.close_current_project
335
- end
336
-
337
- it 'should emit the "closing_project(QObject*)" signal after setting the current_project to nil, passing the project as argument' do
338
- test = flexmock("test"){|m| m.should_receive(:project_closed).once.with(on{|a| a == @prj and !a.disposed?})}
339
- flexmock(Ruber).should_receive(:[]).and_return(flexmock{|m| m.should_ignore_missing})
340
- @keeper.connect(SIGNAL('closing_project(QObject*)')){|o| test.project_closed(o)}
341
- @keeper.close_current_project
342
- end
343
-
344
- it 'should do nothing if the current project is nil' do
345
- @keeper.instance_variable_set(:@current_project, nil)
346
- lambda{@keeper.close_current_project}.should_not raise_error
191
+ describe "#[]" do
192
+
193
+ context 'if the argument starts with a slash' do
194
+
195
+ it 'retuns the project associated witt the given file' do
196
+ @list[@projects[0].project_file].should == @projects[0]
197
+ end
198
+
199
+ it 'returns nil if there\'s no project in the list associated with the given file' do
200
+ @list['/xyz.ruprj'].should be_nil
201
+ end
202
+
203
+ end
204
+
205
+ context 'if the argument doesn\'t start with a slash' do
206
+
207
+ it 'returns the project having the argument as project name' do
208
+ name = 'Project 1'
209
+ @list[name].project_name.should == 'Project 1'
210
+ end
211
+
212
+ it 'returns nil if there\'s no project with the given name in the list' do
213
+ @list['xyz'].should be_nil
214
+ end
215
+
216
+ end
217
+
347
218
  end
348
219
 
349
220
  end
350
221
 
351
- describe 'Ruber::ProjectList#new_project' do
352
-
353
- before do
354
- app = Qt::Object.new
355
- manager = flexmock('components'){|m| m.should_ignore_missing}
356
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
357
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
358
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
359
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
360
- @keeper = Ruber::ProjectList.new manager, pdf
361
- end
362
-
363
- it 'should create a new empty project and return it' do
364
- prj = Ruber::ProjectList::FakeProject.new 'test.ruprj', 'Test'
365
- flexmock(Ruber::Project).should_receive(:new).once.with('test.ruprj', 'Test').and_return prj
366
- res = @keeper.new_project 'test.ruprj', 'Test'
367
- res.should equal(prj)
368
- end
369
-
370
- it 'should add the new project to the project list' do
371
- prj = Ruber::ProjectList::FakeProject.new 'Test', 'test.ruprj'
372
- flexmock(Ruber::Project).should_receive(:new).once.with('test.ruprj', 'Test').and_return prj
373
- @keeper.new_project 'test.ruprj', 'Test'
374
- @keeper.instance_variable_get(:@projects)['test.ruprj'].should equal(prj)
375
- end
222
+ describe Ruber::World::MutableProjectList do
376
223
 
377
- it 'should emit the "project_added(QObject*)" signal with the new project as argument' do
378
- prj = Ruber::ProjectList::FakeProject.new 'Test', 'test.ruprj'
379
- flexmock(Ruber::Project).should_receive(:new).once.with('test.ruprj', 'Test').and_return prj
380
- m = flexmock('test'){|mk| mk.should_receive(:project_added).once.with(prj)}
381
- @keeper.connect(SIGNAL('project_added(QObject*)')){|o| m.project_added(o)}
382
- @keeper.new_project 'test.ruprj', 'Test'
224
+ def create_project file, name = nil
225
+ name ||= file.sub(/[_-]/, ' ').sub('.ruprj','').capitalize
226
+ file = File.join Dir.tmpdir, file unless file.start_with? '/'
227
+ file += '.ruprj' unless file.end_with?('ruprj')
228
+ Ruber::Project.new file, name
383
229
  end
384
230
 
385
- end
386
-
387
- describe 'Ruber::Project#project' do
388
-
389
231
  before do
390
- app = Qt::Object.new
391
- manager = flexmock('components'){|m| m.should_ignore_missing}
392
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
393
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
394
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
395
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
396
- @keeper = Ruber::ProjectList.new manager, pdf
232
+ @projects = 3.times.map{|i| create_project "project-#{i}"}
233
+ @list = Ruber::World::MutableProjectList.new
397
234
  end
398
235
 
399
- it 'should return the project corresponding to the file passed as argument, if it is in the list' do
400
- prj = Ruber::ProjectList::FakeProject.new 'Test', 'test.ruprj'
401
- @keeper.instance_variable_get(:@projects)[prj.project_file] = prj
402
- @keeper.project('test.ruprj').should equal(prj)
236
+ it 'inherits from Ruber::World::ProjectList' do
237
+ Ruber::World::MutableProjectList.ancestors.should include(Ruber::World::ProjectList)
403
238
  end
404
239
 
405
- it 'should load the project from the file passed as argument if it isn\'t in the list' do
406
- prj = Ruber::ProjectList::FakeProject.new 'Test', 'test.ruprj'
407
- flexmock(Ruber::Project).should_receive(:new).once.with('test.ruprj').and_return prj
408
- @keeper.project('test.ruprj').should equal(prj)
409
- end
410
-
411
- it 'should emit the "project_added(QObject*)" signal, passing the project as argument, if the project isn\'t in the list' do
412
- prj = Ruber::ProjectList::FakeProject.new 'Test', 'test.ruprj'
413
- flexmock(Ruber::Project).should_receive(:new).once.with('test.ruprj').and_return prj
414
- m = flexmock{|mk| mk.should_receive(:project_added).once.with(prj)}
415
- @keeper.connect(SIGNAL('project_added(QObject*)')){|o| m.project_added(o)}
416
- @keeper.project 'test.ruprj'
240
+ describe '#initialize' do
241
+
242
+ context 'when called with no arguments' do
243
+
244
+ it 'creates an empty list' do
245
+ @list.should be_empty
246
+ end
247
+
248
+ end
249
+
250
+ context 'when called with an array as argument' do
251
+
252
+ it 'creates a list containing the same projects as the argument' do
253
+ @list = Ruber::World::MutableProjectList.new @projects
254
+ @list.to_a.sort_by{|prj| prj.object_id}.should == @projects.sort_by{|prj| prj.object_id}
255
+ end
256
+
257
+ it 'creates a duplicate of the argument' do
258
+ @list = Ruber::World::MutableProjectList.new @projects
259
+ new_prj = create_project 'project-4'
260
+ @projects << new_prj
261
+ @list.size.should == 3
262
+ end
263
+
264
+ end
265
+
266
+ context 'when called with a ProjectList as argument' do
267
+
268
+ it 'creates a list containing the same documents as the argument' do
269
+ orig = Ruber::World::ProjectList.new @projects
270
+ @list = Ruber::World::MutableProjectList.new orig
271
+ @list.to_a.should == @projects
272
+ end
273
+
274
+ it 'creates a duplicate of the argument' do
275
+ orig = Ruber::World::ProjectList.new @projects
276
+ @list = Ruber::World::MutableProjectList.new orig
277
+ new_prj = create_project 'project-4'
278
+ orig.send(:project_hash)[new_prj.project_file] = new_prj
279
+ @list.size.should == 3
280
+ end
281
+
282
+ end
283
+
417
284
  end
418
285
 
419
- end
420
-
421
- describe 'Ruber::Project#[]' do
422
-
423
- before do
424
- app = Qt::Object.new
425
- manager = flexmock('components'){|m| m.should_ignore_missing}
426
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
427
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
428
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
429
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
430
- @keeper = Ruber::ProjectList.new manager, pdf
286
+ describe '#dup' do
287
+
288
+ it 'duplicates the document list' do
289
+ @list.add @projects
290
+ new_list = @list.dup
291
+ new_list.remove @projects[1]
292
+ @list.should == @projects
293
+ end
294
+
431
295
  end
432
296
 
433
- it 'should return the project corresponding to the given file, if the argument is a string starting with /, if such a project exists' do
434
- prj = Ruber::ProjectList::FakeProject.new 'Test', '/test.ruprj'
435
- @keeper.add_project prj
436
- @keeper['/test.ruprj'].should equal(prj)
297
+ describe '#clone' do
298
+
299
+ it 'duplicates the document list' do
300
+ @list.add @projects
301
+ new_list = @list.clone
302
+ new_list.remove @projects[1]
303
+ @list.should == @projects
304
+ end
305
+
306
+ it 'copies the frozen status of the project list' do
307
+ @list.freeze
308
+ new_list = @list.clone
309
+ new_list.should be_frozen
310
+ lambda{new_list.add create_project('project-4')}.should raise_error(RuntimeError)
311
+ end
312
+
437
313
  end
438
314
 
439
- it 'should return the project with the given name if the argument is a string not starting with /, if such a project exists' do
440
- prj = Ruber::ProjectList::FakeProject.new 'xyz', '/test.ruprj'
441
- @keeper.add_project prj
442
- @keeper['xyz'].should equal(prj)
315
+ describe '#add' do
316
+
317
+ it 'appends the given projects to the list' do
318
+ @list.add @projects[0]
319
+ @list.to_a.should == [@projects[0]]
320
+ @list.add *@projects[1..-1]
321
+ @list.to_a.should == @projects
322
+ end
323
+
324
+ it 'treats arrays of projects as if each project was an argument by itself' do
325
+ @list.add @projects
326
+ @list.to_a.should == @projects
327
+ end
328
+
329
+ it 'returns self' do
330
+ @list.add(@projects).should equal(@list)
331
+ end
332
+
443
333
  end
444
334
 
445
- it 'should return nil if the requested project doesn\'t exist' do
446
- prj = Ruber::ProjectList::FakeProject.new 'xyz', '/test.ruprj'
447
- @keeper.add_project prj
448
- @keeper['abc'].should be_nil
449
- @keeper['/xyz.ruprj'].should be_nil
335
+ describe '#merge!' do
336
+
337
+ before do
338
+ @projects = 5.times.map{|i| create_project "project-#{i}"}
339
+ @list.add @projects[3..4]
340
+ end
341
+
342
+ it 'adds the contents of the argument to self' do
343
+ other = Ruber::World::MutableProjectList.new @projects[0..2]
344
+ @list.merge!(other)
345
+ @list.should == @projects[3..4]+@projects[0..2]
346
+ end
347
+
348
+ it 'also works with an array argument' do
349
+ @list.merge!(@projects[0..2])
350
+ @list.should == @projects[3..4]+@projects[0..2]
351
+ end
352
+
353
+ it 'returns self' do
354
+ @list.merge!(@projects[0..2]).should equal(@list)
355
+ end
356
+
450
357
  end
451
358
 
452
- end
453
-
454
- describe 'Ruber::ProjectList#save_settings' do
455
-
456
- before do
457
- app = Qt::Object.new
458
- manager = flexmock('components'){|m| m.should_ignore_missing}
459
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
460
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
461
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
462
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
463
- @keeper = Ruber::ProjectList.new manager, pdf
359
+ describe '#remove' do
360
+
361
+ before do
362
+ @list.add @projects
363
+ end
364
+
365
+ it 'removes the project from the list' do
366
+ @list.remove @projects[1]
367
+ @list.to_a.should == [@projects[0], @projects[2]]
368
+ end
369
+
370
+ it 'does nothing if the project is not in the list' do
371
+ @list.remove create_project('project-4')
372
+ @list.to_a.should == @projects
373
+ end
374
+
375
+ it 'returns the removed document, if any' do
376
+ @list.remove(@projects[1]).should == @projects[1]
377
+ end
378
+
379
+ it 'returns nil if no document was removed' do
380
+ @list.remove(create_project('project-4')).should be_nil
381
+ end
382
+
464
383
  end
465
384
 
466
- it 'should call the save method of each open project' do
467
- projects = @keeper.instance_variable_get(:@projects)
468
- 5.times do |i|
469
- projects[i] = flexmock(i.to_s){|m| m.should_receive(:save).once}
385
+ describe '#clear' do
386
+
387
+ it 'removes all elements from the list' do
388
+ @list.add @projects
389
+ @list.clear
390
+ @list.should be_empty
391
+ end
392
+
393
+ it 'returns self' do
394
+ @list.clear.should equal(@list)
470
395
  end
471
- @keeper.save_settings
396
+
472
397
  end
473
398
 
474
- end
475
-
476
- describe Ruber::ProjectList do
477
-
478
- describe '#query_close' do
399
+ describe '#delete_if' do
479
400
 
480
401
  before do
481
- app = Qt::Object.new
482
- manager = flexmock('components'){|m| m.should_ignore_missing}
483
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(app)
484
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(manager)
485
- flexmock(Ruber).should_receive(:[]).with(:config).and_return(nil)
486
- pdf = Ruber::PluginSpecification.full({:name => :projects, :class => Ruber::ProjectList})
487
- @keeper = Ruber::ProjectList.new manager, pdf
488
- @values = 5.times.map{|i| flexmock(:project_name => i.to_s)}
489
- prjs = @keeper.instance_variable_get(:@projects)
490
- @values.each{|v| prjs[v.project_name] = v}
491
- def prjs.values
492
- super.sort_by{|p| p.project_name}
493
- end
402
+ @list.add @projects
494
403
  end
495
404
 
496
- it 'calls the query_close method of all the projects and returns true if they all return true' do
497
- @values.each{|pr| pr.should_receive(:query_close).once.and_return true}
498
- @keeper.query_close.should be_true
405
+ it 'removes all the elements for which the block returns true' do
406
+ @list.delete_if{|prj| prj.project_name == 'Project 1'}
407
+ @list.should == [@projects[0], @projects[2]]
499
408
  end
500
409
 
501
- it 'stops iterating through the projects and returns false if one of the project\'s query_close method returns false' do
502
- @values[0].should_receive(:query_close).once.and_return true
503
- @values[1].should_receive(:query_close).once.and_return true
504
- @values[2].should_receive(:query_close).once.and_return false
505
- @values[3].should_receive(:query_close).never
506
- @values[4].should_receive(:query_close).never
507
- @keeper.query_close.should be_false
410
+ it 'returns self' do
411
+ @list.delete_if{|prj| prj.project_name == 'Project 1'}.should equal(@list)
508
412
  end
509
413
 
510
414
  end
415
+
511
416
  end