ruber 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/CHANGES +42 -1
  2. data/lib/ruber/application/application.rb +25 -5
  3. data/lib/ruber/application/plugin.yaml +2 -10
  4. data/lib/ruber/component_manager.rb +2 -2
  5. data/lib/ruber/document_project.rb +5 -3
  6. data/lib/ruber/editor/document.rb +5 -4
  7. data/lib/ruber/editor/ktexteditor_wrapper.rb +1 -1
  8. data/lib/ruber/exception_widgets.rb +1 -1
  9. data/lib/ruber/main_window/main_window.rb +4 -3
  10. data/lib/ruber/main_window/main_window_actions.rb +2 -2
  11. data/lib/ruber/main_window/main_window_internal.rb +1 -1
  12. data/lib/ruber/output_widget.rb +17 -5
  13. data/lib/ruber/project.rb +34 -3
  14. data/lib/ruber/project_dir_scanner.rb +171 -0
  15. data/lib/ruber/settings_container.rb +7 -7
  16. data/lib/ruber/settings_dialog.rb +24 -24
  17. data/lib/ruber/version.rb +1 -1
  18. data/lib/ruber/world/environment.rb +1 -0
  19. data/lib/ruber/world/plugin.yaml +7 -2
  20. data/lib/ruber/{application → world}/project_files_widget.rb +0 -0
  21. data/lib/ruber/{application → world}/ui/project_files_rule_chooser_widget.rb +2 -2
  22. data/lib/ruber/{application → world}/ui/project_files_rule_chooser_widget.ui +0 -0
  23. data/lib/ruber/{application → world}/ui/project_files_widget.rb +2 -2
  24. data/lib/ruber/{application → world}/ui/project_files_widget.ui +0 -0
  25. data/plugins/auto_end/auto_end.rb +21 -18
  26. data/plugins/autosave/autosave.rb +1 -1
  27. data/plugins/find_in_files/find_in_files.rb +1 -1
  28. data/plugins/irb/irb.png +0 -0
  29. data/plugins/irb/irb.rb +142 -0
  30. data/plugins/irb/irb.svg +240 -0
  31. data/plugins/irb/irb_controller.rb +541 -0
  32. data/plugins/irb/irbrc.rb +21 -0
  33. data/plugins/irb/plugin.yaml +19 -0
  34. data/plugins/irb/ui/irb_config_widget.rb +151 -0
  35. data/plugins/irb/ui/irb_config_widget.ui +123 -0
  36. data/plugins/irb/ui/irb_tool_widget.rb +97 -0
  37. data/plugins/irb/ui/irb_tool_widget.ui +86 -0
  38. data/plugins/project_browser/project_browser.rb +1 -1
  39. data/plugins/rspec/plugin.yaml +6 -3
  40. data/plugins/rspec/rspec.rb +172 -473
  41. data/plugins/rspec/tool_widget.rb +462 -0
  42. data/plugins/rspec/ui/rspec_project_widget.rb +58 -38
  43. data/plugins/rspec/ui/rspec_project_widget.ui +68 -64
  44. data/plugins/ruberri/class_formatter.rb +126 -0
  45. data/plugins/ruberri/method_formatter.rb +90 -0
  46. data/plugins/ruberri/plugin.yaml +13 -0
  47. data/plugins/ruberri/ruberri.rb +226 -0
  48. data/plugins/ruberri/search.rb +111 -0
  49. data/plugins/ruberri/ui/tool_widget.rb +73 -0
  50. data/plugins/ruberri/ui/tool_widget.ui +49 -0
  51. data/plugins/ruby_runner/ruby_runner.rb +2 -2
  52. data/plugins/ruby_syntax_checker/plugin.yaml +11 -0
  53. data/plugins/ruby_syntax_checker/ruby_syntax_checker.rb +147 -0
  54. data/plugins/syntax_checker/plugin.yaml +10 -6
  55. data/plugins/syntax_checker/syntax_checker.rb +216 -520
  56. data/plugins/syntax_checker/ui/config_widget.rb +61 -0
  57. data/plugins/syntax_checker/ui/config_widget.ui +44 -0
  58. data/plugins/yaml_syntax_checker/plugin.yaml +11 -0
  59. data/plugins/yaml_syntax_checker/yaml_syntax_checker.rb +62 -0
  60. data/ruber.desktop +0 -0
  61. data/spec/auto_end_spec.rb +224 -186
  62. data/spec/document_project_spec.rb +9 -1
  63. data/spec/document_spec.rb +9 -0
  64. data/spec/environment_spec.rb +12 -0
  65. data/spec/output_widget_spec.rb +69 -2
  66. data/spec/project_dir_scanner_spec.rb +195 -0
  67. data/spec/project_spec.rb +43 -73
  68. data/spec/ruby_syntax_checker_spec.rb +361 -0
  69. data/spec/syntax_checker_spec.rb +1132 -0
  70. data/spec/yaml_syntax_checker_spec.rb +130 -0
  71. metadata +232 -225
  72. data/lib/ruber/application/project_files_list.rb +0 -320
  73. data/spec/project_files_list_spec.rb +0 -411
@@ -1,320 +0,0 @@
1
- =begin
2
- Copyright (C) 2010 by Stefano Crocco
3
- stefano.crocco@alice.it
4
-
5
- This program is free software; you can redistribute it andor 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
17
- Free Software Foundation, Inc.,
18
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
- =end
20
-
21
- require 'thread'
22
- require 'facets/kernel/deep_copy'
23
- require 'find'
24
-
25
- require 'ruber/project'
26
-
27
- module Ruber
28
-
29
- =begin rdoc
30
- Project extension to access the name of the files belonging to the project.
31
-
32
- The file belonging to the projects are determined using the contents of the @general/project_files@
33
- project option. This option is a hash which contains rules (in the form of hashes)
34
- telling which files are part of the project and which aren't.
35
-
36
- Files are kept up to date, both regarding the contents of the filesystem (using a
37
- KDE::DirWatch) and the rules specified in the project.
38
-
39
- To avoid needlessly freezing the application in case projects with a large number of files,
40
- this class only scans the project directory when a list of project files is actually
41
- requested, that is when one of the methods {#each}, {#abs}, {#rel} and {#project_files}
42
- is called. Even in that case, the project directory is only scanned if a file has
43
- been added or removed since the last scan, or if the rules have changed since then.
44
- A scan can be forced by using the {#update} method, but you usually don't need this.
45
-
46
- h3. Rules
47
-
48
- The @general/project_files@ setting is a hash containing the rules to use to decide
49
- whether a given file belongs to the project or not. There are two groups of rules:
50
- inclusive rules and exclusive rules. Inclusive rules specify files which belong
51
- to the project, while exclusive rules specify files which do not belong to the
52
- project. Exclusive rules have precedence on inclusive rules, meaning that if a
53
- file matches both an inclusive and an exclusive rule, it's excluded from the project.
54
-
55
- There are three kinds of rules:
56
-
57
-
58
- Project extension which scans the project directory and finds out which files belong
59
- to the project and which don't (according to rules specified by the user in the
60
- project options), returning an array of the former.
61
-
62
- It also watches the project directory to update the list of project files when a
63
- file in the project directory is added or removed.
64
-
65
- This class provides an {#each} method, which yields all the project files to the
66
- block or, if called without a block, returns an <tt>Enumerable::Enumerator</tt>
67
- which does the same.
68
-
69
- <b>Note:</b> the list of project files is created lazily, only when a method
70
- explicitly needs it and a file or directory (or the rules) have changed since
71
- the last time it was generated. A <tt>KDE::DirWatch</tt> object is used to find
72
- out when a file or directory changes. Also, after a file has changed, the watcher
73
- is stopped until the list is updated again (a single change is enough to rebuild
74
- the whole list, so there's no point in keeping watching).
75
-
76
- The methods which can cause the list to be rebuild are: +each+, +abs+, +rel+ and
77
- <tt>project_files</tt>.
78
-
79
- ===Rules
80
- To decide whether a file belongs to the project or not, ProjectFilesList uses
81
- the general/project_files project option. It is a hash made of three keys, each
82
- specifying a rule telling whether a file is part of the project or not. In application
83
- order, they are
84
- <tt>extensions</tt>::
85
- an array of shell globs. Any file matching one of them (according to <tt>File.fnmatch</tt>)
86
- will be considered a project file, unless another rule says otherwise
87
- <tt>include</tt>::
88
- an array of strings and/or regexps corresponding to files which belong to the
89
- project. Each string entry is the name (relative to the project directory) of
90
- a file which belongs to the project. Each regexp is a pattern which should be
91
- tested against all the names (still relative to the project directory) of the
92
- files in the project directory (and its subdirectories). Each matching file will
93
- be a project file (unless another rule says otherwise).
94
- <tt>exclude</tt>::
95
- as the <tt>include</tt> entry, but the matching files will *not* be project
96
- files. This entry has the precedence with respect to the other two. This means
97
- that if a file is a project file according to one of them but also matches a
98
- rule here, it <i>won't</i> be considered a project file.
99
- =end
100
- class ProjectFilesList < Qt::Object
101
-
102
- include Enumerable
103
-
104
- include Extension
105
-
106
- =begin rdoc
107
- Creates a new ProjectFilesList for the Project _prj_.
108
-
109
- The new object will read the <tt>general/project_files</tt> option from the project
110
- and immediately scan the project directory to find the all the project files.
111
- Besides, it will start monitoring the directory for changes, so as to be
112
- able to update the list of project files when a new file is created or a file
113
- is deleted.
114
- =end
115
- def initialize prj
116
- super
117
- @lock = Mutex.new
118
- @project = prj
119
- @project_files = nil
120
- @watcher = KDE::DirWatch.new self
121
- @watcher.add_dir @project.project_dir, KDE::DirWatch::WatchSubDirs
122
- @up_to_date = false
123
- make_rules
124
- @project_files = []
125
- @watcher.connect(SIGNAL('dirty(QString)')) do
126
- @up_to_date = false
127
- @watcher.stop_scan
128
- end
129
- @project.connect(SIGNAL('option_changed(QString, QString)')) do |g, n|
130
- if g == 'general' and n == 'project_files'
131
- if @project[:general, :project_files] != @rules
132
- @up_to_date = false
133
- make_rules
134
- scan_project
135
- end
136
- end
137
- end
138
- @watcher.start_scan false
139
- end
140
-
141
- =begin rdoc
142
- Returns an array with the name of the files in the project (in arbitrary order).
143
- If _abs_ is *false*, the file names will be relative to the project directory;
144
- if it is *true* they'll be absolute. It is the same as calling <tt>list.abs.to_a</tt>
145
- or <tt>list.rel.to_a</tt>
146
-
147
- <b>Note:</b> if the list isn't up to date, the project will be re-scanned
148
- =end
149
- def project_files abs = true
150
- refresh unless @up_to_date
151
- if abs
152
- dir = @project.project_dir
153
- @project_files.map{|f| File.join dir, f}
154
- else @project_files.deep_copy
155
- end
156
- end
157
-
158
- =begin rdoc
159
- If called with a block, calls the block yielding the names of the files in the
160
- project. If _abs_ is true, absolute file names will be used, otherwise the file
161
- names will be relative to the project directory.
162
-
163
- If called without a block, returns an <tt>Enumerable::Enumerator</tt> which does
164
- the same as above.
165
-
166
- <b>Note:</b> when called with a block and the list isn't up to date,
167
- the project will be re-scanned
168
- =end
169
- def each abs = true
170
- if block_given?
171
- refresh unless @up_to_date
172
- dir = @project.project_dir
173
- @project_files.each do |f|
174
- yield abs ? File.join( dir, f) : f
175
- end
176
- self
177
- else
178
- return self.to_enum(:each, abs)
179
- end
180
- end
181
-
182
- =begin rdoc
183
- Returns an enumerator as that yields the names of the project files relative to
184
- the project directory. It's just a shortcut for <tt>each(false)</tt>.
185
-
186
- <b>Note:</b> if the list isn't up to date, the project will be re-scanned when
187
- any enumerable method returned by the object is called
188
- =end
189
- def rel
190
- self.each false
191
- end
192
- alias_method :relative_paths, :rel
193
-
194
- =begin rdoc
195
- Returns an enumerator as that yields the absolute names of the project files.
196
- It's just a shortcut for <tt>each(true)</tt>.
197
-
198
- <b>Note:</b> if the list isn't up to date, the project will be re-scanned when
199
- any enumerable method returned by the object is called
200
- =end
201
- def abs
202
- self.each true
203
- end
204
- alias_method :absolute_paths, :abs
205
-
206
- =begin rdoc
207
- Updates the list, so that it reflects the current status of the project directory.
208
-
209
- Usually you don't need to call this method, as it's automatically called as needed.
210
- =end
211
- def refresh
212
- scan_project
213
- @up_to_date = true
214
- @watcher.start_scan
215
- end
216
-
217
- =begin rdoc
218
- Tells whether the list is up to date or needs to be rebuilt.
219
-
220
- Usually you don't need this method, as the list is automatically updated when needed.
221
- =end
222
- def up_to_date?
223
- @up_to_date
224
- end
225
-
226
- =begin rdoc
227
- Tells whether the given file belongs to the project or not. If _file_ is a relative
228
- path, it is considered relative to the project directory.
229
-
230
- Returns *true* if _file_ belongs to the project and *false* otherwise. As this method
231
- doesn't access the filesystem, the behaviour in the case _file_ is a directory will
232
- be undefined. If _file_ ends with a slash (which makes it clear it represents a
233
- directory) then *nil* will be returned
234
- <b>Note:</b> this method doesn't use the file list to tell whether the file is in
235
- the project. Rather, it compares the file name with the include and exclude rules
236
- and the extensions.
237
- =end
238
- def file_in_project? file
239
- if file.match %r{^([\w+-.]+)://(.+)}
240
- if $1 != 'file' then return false
241
- else
242
- file = $2
243
- end
244
- end
245
- file = file.sub %r[^#{Regexp.quote(@project.project_directory)}/], ''
246
- return false if file.start_with? '/'
247
- return nil if file.end_with? '/'
248
- # I don't know why I added the following line
249
- # file = File.basename(file)
250
-
251
- return false if @exclude_files.include? file
252
- return true if @include_files.any?{|f| f == file}
253
-
254
- if @exclude_regexp.match(file) then false
255
- elsif @include_regexp.match file then true
256
- elsif @extensions.any?{|e| File.fnmatch?(e, file, File::FNM_DOTMATCH)} then true
257
- else false
258
- end
259
- end
260
-
261
- private
262
-
263
- =begin rdoc
264
- Applies the rules stored in the <tt>general/project_files</tt> project option
265
- to all the files in the project directory and fills the internal cache with the
266
- project files.
267
-
268
- ---
269
- The <tt>@lock</tt> instance variable is used to (hopefully) avoid issues with
270
- two threads calling this method together, since Dir.chdir doesn't nest inside
271
- threads. This created problems with syntax checker, for example.
272
- =end
273
- def scan_project
274
- @lock.synchronize do
275
- Dir.chdir(@project.project_dir) do
276
- res = @include_files.select{|f| File.exist?(f) and File.file?(f)}
277
- # remove the leading ./ from the names of the files
278
- res.map!{|f| f.sub(%r{^./}, '')}
279
- Find.find('.') do |f|
280
- # let's skip the current directory, least it somehow matches one of
281
- # the exclude rules
282
- next if f == '.'
283
- if File.directory?(f)
284
- f = File.join(f, '')
285
- Find.prune if f.match @exclude_regexp
286
- else
287
- # We remove the leading ./
288
- f = f[2..-1]
289
- next if f.match @exclude_regexp or @exclude_files.include?(f)
290
- res << f if @extensions.any?{|ext| File.fnmatch?(ext, f, File::FNM_DOTMATCH)} or
291
- f.match(@include_regexp)
292
- end
293
- end
294
- res.uniq!
295
- @project_files = res
296
- end
297
- end
298
- end
299
-
300
- =begin rdoc
301
- Creates an internal version of the rules from the values in the
302
- <tt>general/project_files</tt> project option
303
- =end
304
- def make_rules
305
- rules = @project[:general, :project_files]
306
- @include_regexp = Regexp.union(*(rules[:include].select{|r| r.is_a?(Regexp)}))
307
- @exclude_regexp = Regexp.union(*(rules[:exclude].select{|r| r.is_a?(Regexp)}))
308
- @exclude_files = rules[:exclude].select{|rule| rule.is_a? String}.map{|f| f.sub(%r{^\./}, '')}
309
- @include_files = rules[:include].select{|rule| rule.is_a? String}.map{|f| f.sub(%r{^\./}, '')}
310
- @include_files-= @exclude_files
311
- @extensions = rules[:extensions]
312
- @rules = YAML.load(YAML.dump rules)
313
- # TODO Uncomment the following line and remove the previous when found out why Marshal
314
- # fails
315
- # @rules = rules.deep_copy
316
- end
317
-
318
- end
319
-
320
- end
@@ -1,411 +0,0 @@
1
- require 'spec/common'
2
-
3
- require 'tempfile'
4
- require 'fileutils'
5
- require 'flexmock'
6
- require 'forwardable'
7
-
8
- require 'ruber/projects/project_files_list'
9
- require 'ruber/project'
10
-
11
-
12
- class SimpleProject < Qt::Object
13
- signals 'option_changed(QString, QString)'
14
- end
15
-
16
- describe 'Ruber::ProjectFilesList' do
17
-
18
- before do
19
- @app = Qt::Object.new
20
- @comp = Qt::Object.new do
21
- class << self
22
- extend Forwardable
23
- def_delegators :@data, :[], :<<
24
- def_delegator :@data, :each, :each_component
25
- end
26
- @data = []
27
- end
28
- @projects = Qt::Object.new
29
- flexmock(Ruber).should_receive(:[]).with(:app).and_return(@app).by_default
30
- flexmock(Ruber).should_receive(:[]).with(:components).and_return(@comp).by_default
31
- flexmock(Ruber).should_receive(:[]).with(:projects).and_return(@projects).by_default
32
- dir = File.dirname __FILE__
33
- @prj = Ruber::Project.new File.join(dir, 'test.ruprj'), 'Test'
34
- @prj.add_option(OS.new({:group => :general, :name => :project_files, :default => {:include => [], :exclude => [], :extensions => []} }))
35
- @l = Ruber::ProjectFilesList.new @prj
36
- @prj.add_extension :file_lister, @l
37
- end
38
-
39
- it 'should be an Enumerable' do
40
- Ruber::ProjectFilesList.ancestors.should include(Enumerable)
41
- end
42
-
43
- it 'should not be up to date when created' do
44
- @l.should_not be_up_to_date
45
- end
46
-
47
- it 'should not attempt to scan the project when created' do
48
- flexmock(Find).should_receive(:find).never
49
- l = Ruber::ProjectFilesList.new @prj
50
- end
51
-
52
- it 'should mark the list as not up to date when the project_files option changes' do
53
- @prj.add_option(OS.new({:group => :general, :name => :xyz, :default => 3}))
54
- @prj[:general, :project_files][:extensions] = ['*.rb']
55
- @l.instance_variable_set :@up_to_date, true
56
- @prj.instance_eval{emit option_changed('general', 'xyz')}
57
- @prj[:general, :project_files] = {:include => [], :exclude => [], :extensions => %w[*.rb *.ui]}
58
- @l.should_not be_up_to_date
59
- end
60
-
61
- describe ', when a file or directory changes' do
62
-
63
- before do
64
- @files = YAML.load('[f1.rb, f1.yaml, README, COPYING, [d2, f21.rb, f22.rb, f21.yaml, f22.yaml, CHANGELOG], [d3, f31.rb, f32.rb]]')
65
- @dir = make_dir_tree @files
66
- @prj = Ruber::Project.new File.join(@dir, 'test.ruprj'), 'Test'
67
- @prj.add_option(OS.new({:group => :general, :name => :project_files, :default => {:include => [], :exclude => [], :extensions => []} }))
68
- @list = Ruber::ProjectFilesList.new @prj
69
- @prj.add_extension :file_lister, @list
70
- end
71
-
72
- it 'should mark itself as not up to date' do
73
- @list.instance_variable_set :@up_to_date, true
74
- w = @list.instance_variable_get :@watcher
75
- dir = @prj.project_directory
76
- w.instance_eval{emit dirty(dir)}
77
- @list.instance_variable_get(:@up_to_date).should be_false
78
- end
79
-
80
- it 'should stop the watcher' do
81
- w = @list.instance_variable_get :@watcher
82
- flexmock(w).should_receive(:stop_scan).once
83
- dir = @prj.project_directory
84
- w.instance_eval{emit dirty(dir)}
85
- end
86
-
87
- end
88
-
89
- describe Ruber::ProjectFilesList, '#refresh' do
90
-
91
- before do
92
- dir = File.dirname __FILE__
93
- @prj = Ruber::Project.new File.join(dir, 'test.ruprj'), 'Test'
94
- @prj.add_option(OS.new({:group => :general, :name => :project_files, :default => {:include => [], :exclude => [], :extensions => []} }))
95
- @list = Ruber::ProjectFilesList.new @prj
96
- @prj.add_extension :file_lister, @list
97
- end
98
-
99
- it 'should call the scan_project method' do
100
- flexmock(@list).should_receive(:scan_project).once
101
- @list.refresh
102
- end
103
-
104
- it 'should set the file list as up to date' do
105
- flexmock(@list).should_receive(:scan_project)
106
- @list.refresh
107
- @list.should be_up_to_date
108
- end
109
-
110
- it 'should restart the watcher' do
111
- flexmock(@list).should_receive(:scan_project)
112
- w = @list.instance_variable_get(:@watcher)
113
- flexmock(w).should_receive(:start_scan).once
114
- @list.refresh
115
- end
116
-
117
- end
118
-
119
- describe 'Ruber::ProjectFilesList#project_files' do
120
-
121
- before do
122
- @files = YAML.load('[f1.rb, f1.yaml, README, COPYING, [d2, f21.rb, f22.rb, f21.yaml, f22.yaml, CHANGELOG], [d3, f31.rb, f32.rb]]')
123
- @dir = make_dir_tree @files
124
- @prj = Ruber::Project.new File.join(@dir, 'test.ruprj'), 'Test'
125
- @prj.add_option(OS.new({:group => :general, :name => :project_files, :default => {:include => [], :exclude => [], :extensions => []} }))
126
- @list = Ruber::ProjectFilesList.new @prj
127
- @prj.add_extension :file_lister, @list
128
- end
129
-
130
- after do
131
- FileUtils.rm_f @dir
132
- end
133
-
134
- it 'updates the cache if it\'s not up to date' do
135
- @list.instance_variable_set :@up_to_date, false
136
- flexmock(@list).should_receive(:refresh).once
137
- @list.project_files
138
- end
139
-
140
- it 'doesn\'t update the cache if it\'s already up to date' do
141
- @list.instance_variable_set :@up_to_date, true
142
- flexmock(@list).should_receive(:refresh).never
143
- @list.project_files
144
- end
145
-
146
- it 'returns an array containing all the files corresponding to include rules of type path unless they also correspond to an exclude rule of type path' do
147
- @prj[:general, :project_files] = {:include => ['README', 'COPYING', 'f1.rb', 'd2/CHANGELOG', 'd2/f21.rb'], :exclude => ['COPYING', 'd2/f21.rb'], :extensions => []}
148
- @list.project_files(false).should =~ %w[README f1.rb d2/CHANGELOG]
149
- end
150
-
151
- it 'doesn\'t include in the returned array files which don\'t exist' do
152
- @prj[:general, :project_files] = {:include => ['README1', 'COPYING', 'f1.rb', 'd2/CHANGELOG', 'd2/f211.rb'], :exclude => ['COPYING'], :extensions => []}
153
- @list.project_files(false).should =~ %w[f1.rb d2/CHANGELOG]
154
- end
155
-
156
- it 'skips include rules of type path corresponding to directories' do
157
- @prj[:general, :project_files] = {:include => ['README', 'COPYING', 'f1.rb', 'd2/CHANGELOG', 'd2/f21.rb', 'd3'], :exclude => ['COPYING', 'd2/f21.rb'], :extensions => []}
158
- @list.project_files(false).should =~ %w[README f1.rb d2/CHANGELOG]
159
- end
160
-
161
- it 'includes all the files in the project directory which correspond to one of the extensions in the returned array, unless they match one of the exclude rule' do
162
- @prj[:general, :project_files] = {:include => [], :exclude => ['COPYING', 'd2/f21.rb'], :extensions => %w[*.rb]}
163
- @list.project_files(false).should =~ %w[f1.rb d2/f22.rb d3/f31.rb d3/f32.rb]
164
- end
165
-
166
- it 'includes all the files in the project directory which match one of the include rules of type regexp and don\'t match any exclude rule' do
167
- @prj[:general, :project_files] = {:include => [%r{d3/.*}, %r{.*\.yaml}], :exclude => [%r{d3/.*2.*}, %r{.*1.*\.rb}], :extensions => []}
168
- @list.project_files(false).should =~ %w[d2/f22.yaml f1.yaml d2/f21.yaml]
169
- end
170
-
171
- it 'doesn\'t include duplicate elements' do
172
- @prj[:general, :project_files] = {:include => [%r{d2/.*}, 'f1.rb'], :exclude => [], :extensions => ['*.rb']}
173
- @list.project_files(false).should =~ %w[f1.rb d2/f21.rb d2/f22.rb d2/f21.yaml d2/f22.yaml d2/CHANGELOG d3/f31.rb d3/f32.rb]
174
- end
175
-
176
- it 'returns a deep copy of the cache object' do
177
- @prj[:general, :project_files] = {:include => [%r{d2/.*}, 'f1.rb'], :exclude => [], :extensions => ['*.rb']}
178
- old_cache = @list.instance_variable_get(:@project_files).deep_copy
179
- res = @list.project_files(false)
180
- res.should == old_cache
181
- res << 'x'
182
- @list.instance_variable_get(:@project_files).should == old_cache
183
- end
184
-
185
- it 'returns full paths if the argument is true' do
186
- @prj[:general, :project_files] = {:include => [%r{d2/.*}, 'f1.rb'], :exclude => [], :extensions => ['*.rb']}
187
- @list.project_files(true).should =~ %w[f1.rb d2/f21.rb d2/f22.rb d2/f21.yaml d2/f22.yaml d2/CHANGELOG d3/f31.rb d3/f32.rb].map{|i| File.join @dir, i}
188
- end
189
-
190
- it 'returns the correct list if a file or directory is added or deleted after the file watcher has been created' do
191
- @prj[:general, :project_files] = {:include => [], :exclude => [], :extensions => ['*.rb']}
192
- # Experiments show that KDE::DirWatch needs an event loop to work. Since we don't have one running, we'll have to make it emit the 'dirty' signal manually
193
- watcher = @list.instance_variable_get(:@watcher)
194
- `touch #@dir/f2.rb`
195
- watcher.instance_eval{emit dirty( @dir)}
196
- `touch #@dir/d2/f23.rb`
197
- watcher.instance_eval{emit dirty( @dir)}
198
- @list.project_files(false).should include('f2.rb')
199
- @list.project_files(false).should include('d2/f23.rb')
200
- FileUtils.mkdir("#@dir/d4")
201
- watcher.instance_eval{emit dirty( @dir)}
202
- `touch #@dir/d4/f41.rb`
203
- watcher.instance_eval{emit dirty( @dir)}
204
- `touch #@dir/d4/f42.rb`
205
- watcher.instance_eval{emit dirty( @dir)}
206
- @list.project_files(false).should include('d4/f41.rb')
207
- @list.project_files(false).should include('d4/f42.rb')
208
- FileUtils.rm_rf "#@dir/d2"
209
- watcher.instance_eval{emit dirty( @dir)}
210
- @list.project_files(false).should_not include("#@dir/d2/f21.rb")
211
- @list.project_files(false).should_not include("#@dir/d2/f22.rb")
212
- FileUtils.rm "#@dir/f1.rb"
213
- watcher.instance_eval{emit dirty( @dir)}
214
- @list.project_files(false).should_not include("f1.rb")
215
- end
216
-
217
- end
218
-
219
- describe 'Ruber::ProjectFilesList#each' do
220
-
221
- before do
222
- @files = YAML.load('[f1.rb, f1.yaml, README, COPYING, [d2, f21.rb, f22.rb, f21.yaml, f22.yaml, CHANGELOG], [d3, f31.rb, f32.rb]]')
223
- @dir = make_dir_tree @files
224
- @prj = Ruber::Project.new File.join(@dir, 'test.ruprj'), 'Test'
225
- @prj.add_option(OS.new({:group => :general, :name => :project_files, :default => {:include => %w[README f1.yaml], :exclude => %w[d2/f22.rb], :extensions => %w[*.rb]} }))
226
- @list = Ruber::ProjectFilesList.new @prj
227
- @prj.add_extension :file_lister, @list
228
- end
229
-
230
- it 'should update the cache if it\'s not up to date and a block is given' do
231
- @list.instance_variable_set :@up_to_date, false
232
- flexmock(@list).should_receive(:refresh).once
233
- @list.each{}
234
- end
235
-
236
- it 'should not update the cache if it\'s already up to date and a block is given' do
237
- @list.instance_variable_set :@up_to_date, true
238
- flexmock(@list).should_receive(:refresh).never
239
- @list.each{}
240
- end
241
-
242
- it 'should call the associated block passing the full file name of each project file if called with a block and the argument is true' do
243
- exp = %w[f1.rb f1.yaml README d2/f21.rb d3/f31.rb d3/f32.rb].map{|f| File.join @dir, f}
244
- m = flexmock do |mk|
245
- exp.each{|f| mk.should_receive(:test).once.with(f)}
246
- end
247
- @list.each(true){|f| m.test f}
248
- end
249
-
250
- it 'should call the associated block passing the file name of each project file relative to the project directory if called with a block and the argument is false' do
251
- exp = %w[f1.rb f1.yaml README d2/f21.rb d3/f31.rb d3/f32.rb]
252
- m = flexmock do |mk|
253
- exp.each{|f| mk.should_receive(:test).once.with(f)}
254
- end
255
- @list.each(false){|f| m.test f}
256
- end
257
-
258
- it 'should return an enumerator which yields the full file name of each project file if called without a block and the argument is true' do
259
- enum = @list.each(true)
260
- enum.should be_a(Enumerable)
261
- exp = %w[f1.rb f1.yaml README d2/f21.rb d3/f31.rb d3/f32.rb].map{|f| File.join @dir, f}
262
- m = flexmock do |mk|
263
- exp.each{|f| mk.should_receive(:test).once.with(f)}
264
- end
265
- enum.each{|f| m.test f}
266
- end
267
-
268
- it 'should return an enumerator which yields the file name of each project file relative to the project directory if called without a block and the argument is false' do
269
- enum = @list.each(false)
270
- enum.should be_a(Enumerable)
271
- exp = %w[f1.rb f1.yaml README d2/f21.rb d3/f31.rb d3/f32.rb]
272
- m = flexmock do |mk|
273
- exp.each{|f| mk.should_receive(:test).once.with(f)}
274
- end
275
- enum.each{|f| m.test f}
276
- end
277
-
278
- it 'should never update the cache if no block is given' do
279
- @list.instance_variable_set :@up_to_date, false
280
- flexmock(@list).should_receive(:refresh).never
281
- @list.each
282
- @list.instance_variable_set :@up_to_date, true
283
- @list.each
284
- end
285
-
286
- end
287
-
288
- describe 'Ruber::ProjectFilesList#rel' do
289
-
290
- before do
291
- @files = YAML.load('[f1.rb, f1.yaml, README, COPYING, [d2, f21.rb, f22.rb, f21.yaml, f22.yaml, CHANGELOG], [d3, f31.rb, f32.rb]]')
292
- @dir = make_dir_tree @files
293
- @prj = Ruber::Project.new File.join(@dir, 'test.ruprj'), 'Test'
294
- @prj.add_option(OS.new({:group => :general, :name => :project_files, :default => {:include => %w[README f1.yaml], :exclude => %w[d2/f22.rb], :extensions => %w[*.rb]} }))
295
- @list = Ruber::ProjectFilesList.new @prj
296
- @prj.add_extension :file_lister, @list
297
- end
298
-
299
- it 'should work as the each method with no block and a false argument' do
300
- enum = @list.rel
301
- enum.should be_a(Enumerable)
302
- exp = %w[f1.rb f1.yaml README d2/f21.rb d3/f31.rb d3/f32.rb]
303
- m = flexmock do |mk|
304
- exp.each{|f| mk.should_receive(:test).once.with(f)}
305
- end
306
- enum.each{|f| m.test f}
307
- end
308
-
309
- end
310
-
311
- describe 'Ruber::ProjectFilesList#abs' do
312
-
313
- before do
314
- @files = YAML.load('[f1.rb, f1.yaml, README, COPYING, [d2, f21.rb, f22.rb, f21.yaml, f22.yaml, CHANGELOG], [d3, f31.rb, f32.rb]]')
315
- @dir = make_dir_tree @files
316
- @prj = Ruber::Project.new File.join(@dir, 'test.ruprj'), 'Test'
317
- @prj.add_option(OS.new({:group => :general, :name => :project_files, :default => {:include => %w[README f1.yaml], :exclude => %w[d2/f22.rb], :extensions => %w[*.rb]} }))
318
- @list = Ruber::ProjectFilesList.new @prj
319
- @prj.add_extension :file_lister, @list
320
- end
321
-
322
- it 'should work as the each method with no block and a true argument' do
323
- enum = @list.abs
324
- enum.should be_a(Enumerable)
325
- exp = %w[f1.rb f1.yaml README d2/f21.rb d3/f31.rb d3/f32.rb].map{|f| File.join @dir, f}
326
- m = flexmock do |mk|
327
- exp.each{|f| mk.should_receive(:test).once.with(f)}
328
- end
329
- enum.each{|f| m.test f}
330
- end
331
-
332
-
333
- end
334
-
335
- describe Ruber::ProjectFilesList do
336
-
337
- describe '#file_in_project?' do
338
-
339
- before do
340
- @dir = File.dirname __FILE__
341
- @prj = Ruber::Project.new File.join(@dir, 'test.ruprj'), 'Test'
342
- @prj.add_option(OS.new({:group => :general, :name => :project_files, :default => {:include => %w[], :exclude => %w[], :extensions => []} }))
343
- @list = Ruber::ProjectFilesList.new @prj
344
- @prj.add_extension :file_lister, @list
345
- end
346
-
347
- it 'returns true if the argument matches one of the exact include rules' do
348
- @prj[:general, :project_files] = {:include => %w[./xyz ./abc ./123], :exclude => [], :extensions => ['*.rb']}
349
- @list.file_in_project?(File.join(@prj.project_dir, 'abc')).should be_true
350
- end
351
-
352
- it 'returns true if the argument matches one of the regexp include rules' do
353
- @prj[:general, :project_files] = {:include => [/a/, /x/], :exclude => [], :extensions => ['*.rb']}
354
- @list.file_in_project?(File.join(@prj.project_dir, 'xyz')).should be_true
355
- end
356
-
357
- it 'returns true if the argument matches one of the include extensions' do
358
- @prj[:general, :project_files] = {:include => [], :exclude => [], :extensions => ['*.rb', '*.yaml']}
359
- @list.file_in_project?(File.join(@prj.project_dir, 'abc.rb')).should be_true
360
- end
361
-
362
- it 'returns false if the file isn\'t in the project directory' do
363
- @prj[:general, :project_files] = {:include => %w[xyz abc 123], :exclude => [], :extensions => ['*.rb']}
364
- @list.file_in_project?('/usr/abc').should be_false
365
- end
366
-
367
- it 'treats the argument as a path relative to the project directory if it isn\'t an absolute path' do
368
- @prj[:general, :project_files] = {:include => %w[xyz abc 123], :exclude => [], :extensions => ['*.rb']}
369
- @list.file_in_project?('abc').should be_true
370
- end
371
-
372
- it 'returns false if the file doesn\'t match any include rule' do
373
- @list.file_in_project?(File.join(@prj.project_dir, 'abc.rb')).should be_false
374
- end
375
-
376
- it 'returns false if the file matches one of the file exclude rules' do
377
- @prj[:general, :project_files] = {:include => %w[xyz abc 123], :exclude => ['abc'], :extensions => ['*.rb']}
378
- @list.file_in_project?(File.join(@prj.project_dir, 'abc')).should be_false
379
- end
380
-
381
- it 'returns false if the file matches one of the exclude regexps' do
382
- @prj[:general, :project_files] = {:include => [/a/], :exclude => [/a/], :extensions => []}
383
- @list.file_in_project?(File.join(@prj.project_dir, 'abc')).should be_false
384
- end
385
-
386
- it 'it considers the whole path of the file, not just the filename' do
387
- @prj[:general, :project_files] = {:include => [%r{a/.*}], :exclude => [%r{b/.*}], :extensions => ['*.rb']}
388
- @list.file_in_project?(File.join(@prj.project_dir, 'a', 'xyz')).should be_true
389
- @list.file_in_project?(File.join(@prj.project_dir, 'b', 'xyz.rb')).should be_false
390
- end
391
-
392
- it 'returns nil if the file name ends with a slash' do
393
- @prj[:general, :project_files] = {:include => [%r{a/.*}], :exclude => [%r{b/.*}], :extensions => ['*.rb']}
394
- @list.file_in_project?('xyz/').should be_nil
395
- end
396
-
397
- it 'returns false if the path represents a remote URL' do
398
- @prj[:general, :project_files] = {:include => [], :exclude => [], :extensions => ['*.rb']}
399
- @list.file_in_project?("http://#{@dir}/abc.xyz.rb").should be_false
400
- end
401
-
402
- it 'works normally if the path represents a local url' do
403
- @prj[:general, :project_files] = {:include => [], :exclude => [], :extensions => ['*.rb']}
404
- @list.file_in_project?("file://#{@dir}/abc.xyz.rb").should be_true
405
- end
406
-
407
- end
408
-
409
- end
410
-
411
- end