ruber 0.0.9 → 0.0.10

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 (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