ruber 0.0.9 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +42 -1
- data/lib/ruber/application/application.rb +25 -5
- data/lib/ruber/application/plugin.yaml +2 -10
- data/lib/ruber/component_manager.rb +2 -2
- data/lib/ruber/document_project.rb +5 -3
- data/lib/ruber/editor/document.rb +5 -4
- data/lib/ruber/editor/ktexteditor_wrapper.rb +1 -1
- data/lib/ruber/exception_widgets.rb +1 -1
- data/lib/ruber/main_window/main_window.rb +4 -3
- data/lib/ruber/main_window/main_window_actions.rb +2 -2
- data/lib/ruber/main_window/main_window_internal.rb +1 -1
- data/lib/ruber/output_widget.rb +17 -5
- data/lib/ruber/project.rb +34 -3
- data/lib/ruber/project_dir_scanner.rb +171 -0
- data/lib/ruber/settings_container.rb +7 -7
- data/lib/ruber/settings_dialog.rb +24 -24
- data/lib/ruber/version.rb +1 -1
- data/lib/ruber/world/environment.rb +1 -0
- data/lib/ruber/world/plugin.yaml +7 -2
- data/lib/ruber/{application → world}/project_files_widget.rb +0 -0
- data/lib/ruber/{application → world}/ui/project_files_rule_chooser_widget.rb +2 -2
- data/lib/ruber/{application → world}/ui/project_files_rule_chooser_widget.ui +0 -0
- data/lib/ruber/{application → world}/ui/project_files_widget.rb +2 -2
- data/lib/ruber/{application → world}/ui/project_files_widget.ui +0 -0
- data/plugins/auto_end/auto_end.rb +21 -18
- data/plugins/autosave/autosave.rb +1 -1
- data/plugins/find_in_files/find_in_files.rb +1 -1
- data/plugins/irb/irb.png +0 -0
- data/plugins/irb/irb.rb +142 -0
- data/plugins/irb/irb.svg +240 -0
- data/plugins/irb/irb_controller.rb +541 -0
- data/plugins/irb/irbrc.rb +21 -0
- data/plugins/irb/plugin.yaml +19 -0
- data/plugins/irb/ui/irb_config_widget.rb +151 -0
- data/plugins/irb/ui/irb_config_widget.ui +123 -0
- data/plugins/irb/ui/irb_tool_widget.rb +97 -0
- data/plugins/irb/ui/irb_tool_widget.ui +86 -0
- data/plugins/project_browser/project_browser.rb +1 -1
- data/plugins/rspec/plugin.yaml +6 -3
- data/plugins/rspec/rspec.rb +172 -473
- data/plugins/rspec/tool_widget.rb +462 -0
- data/plugins/rspec/ui/rspec_project_widget.rb +58 -38
- data/plugins/rspec/ui/rspec_project_widget.ui +68 -64
- data/plugins/ruberri/class_formatter.rb +126 -0
- data/plugins/ruberri/method_formatter.rb +90 -0
- data/plugins/ruberri/plugin.yaml +13 -0
- data/plugins/ruberri/ruberri.rb +226 -0
- data/plugins/ruberri/search.rb +111 -0
- data/plugins/ruberri/ui/tool_widget.rb +73 -0
- data/plugins/ruberri/ui/tool_widget.ui +49 -0
- data/plugins/ruby_runner/ruby_runner.rb +2 -2
- data/plugins/ruby_syntax_checker/plugin.yaml +11 -0
- data/plugins/ruby_syntax_checker/ruby_syntax_checker.rb +147 -0
- data/plugins/syntax_checker/plugin.yaml +10 -6
- data/plugins/syntax_checker/syntax_checker.rb +216 -520
- data/plugins/syntax_checker/ui/config_widget.rb +61 -0
- data/plugins/syntax_checker/ui/config_widget.ui +44 -0
- data/plugins/yaml_syntax_checker/plugin.yaml +11 -0
- data/plugins/yaml_syntax_checker/yaml_syntax_checker.rb +62 -0
- data/ruber.desktop +0 -0
- data/spec/auto_end_spec.rb +224 -186
- data/spec/document_project_spec.rb +9 -1
- data/spec/document_spec.rb +9 -0
- data/spec/environment_spec.rb +12 -0
- data/spec/output_widget_spec.rb +69 -2
- data/spec/project_dir_scanner_spec.rb +195 -0
- data/spec/project_spec.rb +43 -73
- data/spec/ruby_syntax_checker_spec.rb +361 -0
- data/spec/syntax_checker_spec.rb +1132 -0
- data/spec/yaml_syntax_checker_spec.rb +130 -0
- metadata +232 -225
- data/lib/ruber/application/project_files_list.rb +0 -320
- data/spec/project_files_list_spec.rb +0 -411
data/CHANGES
CHANGED
@@ -1,9 +1,48 @@
|
|
1
1
|
h1. Changes
|
2
2
|
|
3
|
-
h2. Ruber 0.0.
|
3
|
+
h2. Ruber 0.0.10
|
4
4
|
|
5
5
|
h3. Features
|
6
6
|
|
7
|
+
* Added a RI plugin. You can now insert the class or method name in the RI tool widget
|
8
|
+
and see the documentation in a nice HTML format inside the tool widget itself.
|
9
|
+
This plugin requires RDoc version 3.x (it isn't tested with version 2.x).
|
10
|
+
* Added an IRB plugin
|
11
|
+
* The syntax checker plugin has been rewritten. Now other plugins can check the
|
12
|
+
syntax of a document
|
13
|
+
* Ruby and YAML syntax checker now are in their own plugin, rather than being part
|
14
|
+
of the syntax checker plugin
|
15
|
+
* The auto end plugin doesn't use indentation anymore to decide whether the end keyword
|
16
|
+
should be inserted or not. Instead, it performs a syntax check and only inserts
|
17
|
+
end if ruby reports a missing end keyword. This should improve the accuracy of
|
18
|
+
the plugin
|
19
|
+
* The Auto End plugin now inserts the @end@ keyword after a @case@ expression
|
20
|
+
* Clicking on a file name in an output widget with the middle mouse button now
|
21
|
+
prevents the tool widget from being hidden, as if the pin button were clicked
|
22
|
+
* Changed the interface to specify patterns in the RSpec plugin
|
23
|
+
* The RSpec plugin now supports specs inside subdirectories. You can also specify
|
24
|
+
subdirectories inside the pattern to match code file and the respective spec
|
25
|
+
file
|
26
|
+
* When choosing the Run Specs for Current File action in the RSpec plugin, if the current
|
27
|
+
document is associated with a code file, all the specs associated with it are
|
28
|
+
run (previously, only one of them was run)
|
29
|
+
* When choosing the Run Current Spec action in the RSpec plugin, if the current
|
30
|
+
document is a code file, the plugin will look at the most recently activated
|
31
|
+
editor containing a spec file for the current file to determine which is the
|
32
|
+
current spec.
|
33
|
+
* The behaviour of output widgets when clicking on a file name which requires
|
34
|
+
opening a new editor has changed. The choice made by the user to open the editor
|
35
|
+
in the current tab by splitting the current editor is ignored if the current
|
36
|
+
tab already contains more than one editor. The reason is that usually there
|
37
|
+
won't be enough space on the sceen to comfortably accomodate more than two
|
38
|
+
editors.
|
39
|
+
|
40
|
+
h3. Bug fixes
|
41
|
+
|
42
|
+
* Do not crash when closing with unsaved files
|
43
|
+
* Horizontal scrollbar in the RSpec tool widget will be displayed when the spec
|
44
|
+
description is larger than the widget but the rest of the text isn't
|
45
|
+
|
7
46
|
h2. Ruber 0.0.9
|
8
47
|
|
9
48
|
h3. Features
|
@@ -20,6 +59,8 @@ h3. Bug fixes
|
|
20
59
|
* The RSpec plugin now correctly displays pending examples
|
21
60
|
* Fixed a crash when creating a new document and saving it as a ruby file while
|
22
61
|
using the Syntax Checker plugin
|
62
|
+
* When clicking on a file name in an output widget, give focus to the editor instead
|
63
|
+
of keeping it in the tool widget
|
23
64
|
|
24
65
|
h2. Ruber 0.0.8
|
25
66
|
|
@@ -62,7 +62,8 @@ The default plugins to load
|
|
62
62
|
|
63
63
|
Currently, they are: ruby_development, find_in_files, syntax_checker, command and state
|
64
64
|
=end
|
65
|
-
DEFAULT_PLUGINS = %w[ruby_development find_in_files rake command syntax_checker
|
65
|
+
DEFAULT_PLUGINS = %w[ruby_development find_in_files rake command syntax_checker
|
66
|
+
state auto_end project_browser ruby_syntax_checker yaml_syntax_checker]
|
66
67
|
|
67
68
|
include PluginLike
|
68
69
|
|
@@ -74,7 +75,6 @@ Currently, they are: ruby_development, find_in_files, syntax_checker, command an
|
|
74
75
|
attr_reader :cmd_line_options
|
75
76
|
|
76
77
|
=begin rdoc
|
77
|
-
<<<<<<< HEAD
|
78
78
|
=======
|
79
79
|
The state Ruber is in
|
80
80
|
|
@@ -87,7 +87,6 @@ Ruber can be in three states:
|
|
87
87
|
- *quitting*:= from when the user chooses to quit Ruber onwards
|
88
88
|
- *asking_to_quit*:= while asking the user to confirm quitting Ruber
|
89
89
|
|
90
|
-
>>>>>>> master
|
91
90
|
@return [Symbol] the status of the application. It can be: @:starting@, @:running@
|
92
91
|
or @:quitting@
|
93
92
|
=end
|
@@ -117,6 +116,7 @@ and is fired as soon as the event loop starts.
|
|
117
116
|
@plugin_dirs = []
|
118
117
|
load_core_components
|
119
118
|
@status = :starting
|
119
|
+
@chdir_lock = Mutex.new
|
120
120
|
Qt::Timer.single_shot(0, self, SLOT(:setup))
|
121
121
|
end
|
122
122
|
|
@@ -251,6 +251,25 @@ or sorting dependencies.
|
|
251
251
|
@components.load_plugins plugins, dirs || @plugin_dirs, &blk
|
252
252
|
|
253
253
|
end
|
254
|
+
|
255
|
+
=begin rdoc
|
256
|
+
Thread-safe Dir.chdir
|
257
|
+
|
258
|
+
@Dir.chdir@ is not thread-safe, meaning that a Dir.chdir done in a thread will
|
259
|
+
change the directory in all other threads. To avoid this unpleasant behaviour,
|
260
|
+
don't use Dir.chdir. Instead, use this method, which uses a mutex to control calls
|
261
|
+
to Dir.chdir.
|
262
|
+
@param [String] dir the directory to change to
|
263
|
+
@yield the block to execute from within _dir_. The current directory will
|
264
|
+
be changed back after executing the block.
|
265
|
+
@raise [LocalJumpError] if no block is given
|
266
|
+
@return [Object] the value returned by the block otherwise
|
267
|
+
=end
|
268
|
+
def chdir dir
|
269
|
+
@chdir_lock.synchronize do
|
270
|
+
Dir.chdir(dir){yield}
|
271
|
+
end
|
272
|
+
end
|
254
273
|
|
255
274
|
private
|
256
275
|
|
@@ -304,7 +323,7 @@ At the end, the main window is shown
|
|
304
323
|
#{e.message}
|
305
324
|
|
306
325
|
Ruber will start with no plugin loaded. Please, use the Choose Plugins menu entry in the Settings menu to solve the issue.
|
307
|
-
|
326
|
+
EOS
|
308
327
|
end
|
309
328
|
begin
|
310
329
|
availlable_plugins = ComponentManager.find_plugins @plugin_dirs, true
|
@@ -316,7 +335,7 @@ At the end, the main window is shown
|
|
316
335
|
Ruber couldn't find some plugins it has been configured to automatically load at startup. They are:
|
317
336
|
#{missing.join("\n")}
|
318
337
|
Do you want to start the application without them or to quit Ruber?
|
319
|
-
|
338
|
+
EOS
|
320
339
|
ans = KDE::MessageBox.question_yes_no nil, question, 'Missing plugins',
|
321
340
|
KDE::GuiItem.new('Start Ruber'), KDE::GuiItem.new('Quit')
|
322
341
|
exit if ans == KDE::MessageBox::No
|
@@ -397,6 +416,7 @@ necessary to to them later
|
|
397
416
|
def register_with_config
|
398
417
|
config = Ruber[:config]
|
399
418
|
@plugin_description.config_options.each_value{|o| config.add_option o}
|
419
|
+
@plugin_description.config_widgets.each{|w| config.add_widget w}
|
400
420
|
load_settings
|
401
421
|
connect config, SIGNAL(:settings_changed), self, SLOT(:load_settings)
|
402
422
|
nil
|
@@ -1,16 +1,8 @@
|
|
1
1
|
name: app
|
2
2
|
description: The application itself
|
3
|
-
require: [application
|
3
|
+
require: [application]
|
4
4
|
class: 'Ruber::Application'
|
5
5
|
config_options:
|
6
6
|
:general:
|
7
7
|
:plugin_dirs: {:default: Ruber::Application::DEFAULT_PLUGIN_PATHS}
|
8
|
-
:plugins: {:default: Ruber::Application::DEFAULT_PLUGINS}
|
9
|
-
:auto_load_project: {:default: false }
|
10
|
-
config_widgets:
|
11
|
-
- {:caption: General, :pixmap: configure, :code: "w=Qt::CheckBox.new('&Open last project at startup');w.object_name='kcfg_general_auto_load_project';w"}
|
12
|
-
project_options:
|
13
|
-
general:
|
14
|
-
project_files: {default: {:include: [], :exclude: [], :extensions: ["*.rb"]}}
|
15
|
-
extensions:
|
16
|
-
project_files: {class: ProjectFilesList}
|
8
|
+
:plugins: {:default: Ruber::Application::DEFAULT_PLUGINS}
|
@@ -429,7 +429,7 @@ possible kinds of dependency errors.
|
|
429
429
|
def self.find_plugins dirs, info = false
|
430
430
|
res = {}
|
431
431
|
dirs.each do |dir|
|
432
|
-
Dir.entries(dir)[2..-1].each do |name|
|
432
|
+
Dir.entries(dir).sort[2..-1].each do |name|
|
433
433
|
next if res[name.to_sym]
|
434
434
|
d = File.join dir, name
|
435
435
|
if File.directory?(d) and File.exist?(File.join d, 'plugin.yaml')
|
@@ -861,7 +861,7 @@ Method required for the Plugin interface. Does nothing
|
|
861
861
|
def locate_plugins dirs
|
862
862
|
plugin_files = {}
|
863
863
|
dirs.reverse.each do |d|
|
864
|
-
Dir.entries(d)[2..-1].each do |f|
|
864
|
+
Dir.entries(d).sort[2..-1].each do |f|
|
865
865
|
full_dir = File.join d, f
|
866
866
|
if File.directory?(full_dir) and File.exist?(File.join(full_dir, 'plugin.yaml'))
|
867
867
|
plugin_files[f] = File.join full_dir, 'plugin.yaml'
|
@@ -54,7 +54,6 @@ didn't exist. This means that it will be overwritten when the project is saved.
|
|
54
54
|
The reason for this behaviour is that there should be no user file in the directory
|
55
55
|
where document projects are saved.
|
56
56
|
=end
|
57
|
-
# $CALLED = 0
|
58
57
|
def initialize file
|
59
58
|
@old_files = []
|
60
59
|
begin super file_for(file)
|
@@ -157,9 +156,12 @@ The comparison is made using <tt>Document#file_type_match?</tt>. This method ret
|
|
157
156
|
rule's scope includes +:document+
|
158
157
|
=end
|
159
158
|
def match_rule? obj
|
159
|
+
doc_place = if !@document.path.empty?
|
160
|
+
@document.url.local_file? ? :local : :remote
|
161
|
+
else :local
|
162
|
+
end
|
160
163
|
if !super then false
|
161
|
-
elsif !obj.place.include?
|
162
|
-
false
|
164
|
+
elsif !obj.place.include? doc_place then false
|
163
165
|
elsif !@document.file_type_match? obj.mimetype, obj.file_extension then false
|
164
166
|
else true
|
165
167
|
end
|
@@ -92,7 +92,8 @@ module Ruber
|
|
92
92
|
'view_created(QObject*, QObject*)', 'closing(QObject*)', :activated, :deactivated,
|
93
93
|
'modified_on_disk(QObject*, bool, KTextEditor::ModificationInterface::ModifiedOnDiskReason)',
|
94
94
|
'sig_query_close(bool*, bool*)', 'canceled(QString)', 'completed()', 'completed1(bool)',
|
95
|
-
'started(KIO::Job*)', 'set_status_bar_text(QString)', 'setWindowCaption(QString)'
|
95
|
+
'started(KIO::Job*)', 'set_status_bar_text(QString)', 'setWindowCaption(QString)',
|
96
|
+
'document_saved_or_uploaded(QObject*, bool)'
|
96
97
|
|
97
98
|
=begin rdoc
|
98
99
|
Signal emitted before a view associated with the document is closed
|
@@ -127,7 +128,7 @@ Creates a new Ruber::Document.
|
|
127
128
|
interface('modification_interface').modified_on_disk_warning = true
|
128
129
|
@modified_on_disk = false
|
129
130
|
@project = DocumentProject.new self
|
130
|
-
|
131
|
+
@project.finalize
|
131
132
|
@doc.connect(SIGNAL('modifiedChanged(KTextEditor::Document*)')) do |doc|
|
132
133
|
emit modified_changed(@doc.modified?, self)
|
133
134
|
end
|
@@ -155,7 +156,7 @@ Creates a new Ruber::Document.
|
|
155
156
|
begin
|
156
157
|
emit text_inserted(r, self)
|
157
158
|
rescue ArgumentError => e
|
158
|
-
ExceptionDialog.new e, nil, true, "An exception was raised
|
159
|
+
ExceptionDialog.new e, nil, true, "An exception was raised from emit text_inserted. See issue number 6 at http://github.com/stcrocco/ruber/issues"
|
159
160
|
end
|
160
161
|
end
|
161
162
|
|
@@ -357,7 +358,7 @@ Return the project with wider scope the document belongs to. This is:
|
|
357
358
|
def project
|
358
359
|
prj = Ruber[:world].active_project
|
359
360
|
return @project if path.empty? or !prj
|
360
|
-
prj.
|
361
|
+
prj.file_in_project?(url.to_encoded.to_s) ? prj : @project
|
361
362
|
end
|
362
363
|
|
363
364
|
=begin rdoc
|
@@ -133,7 +133,7 @@ containing the information for the signal and slot to create.
|
|
133
133
|
def __emit_#{name}_signal(#{old_args.size.times.map{|i| "a#{i}"}.join ', '})
|
134
134
|
emit #{name}(#{d[1].map{|i| i ? "a#{i}" : 'self'}.join ', '})
|
135
135
|
end
|
136
|
-
|
136
|
+
EOS
|
137
137
|
cls.class_eval method_def
|
138
138
|
end
|
139
139
|
res
|
@@ -233,7 +233,7 @@ are suitable for use by a block passed to {ComponentManager#load_plugins}.
|
|
233
233
|
def exec
|
234
234
|
res = super
|
235
235
|
case res
|
236
|
-
when KDE::Dialog::Yes then
|
236
|
+
when KDE::Dialog::Yes then silently? ? :silent : true
|
237
237
|
when KDE::Dialog::No then false
|
238
238
|
when KDE::Dialog::Cancel then :skip
|
239
239
|
else res
|
@@ -1,5 +1,5 @@
|
|
1
1
|
=begin
|
2
|
-
Copyright (C) 2010 by Stefano Crocco
|
2
|
+
Copyright (C) 2010, 2011 by Stefano Crocco
|
3
3
|
stefano.crocco@alice.it
|
4
4
|
|
5
5
|
This program is free software; you can redistribute it andor modify
|
@@ -538,13 +538,14 @@ In the second and third cases, the method simply returns respectively *true* or
|
|
538
538
|
can be carried on and *false* if the user chose to abort it
|
539
539
|
=end
|
540
540
|
def save_documents docs = nil
|
541
|
-
docs ||= Ruber[:
|
541
|
+
docs ||= Ruber[:world].documents
|
542
542
|
to_save = docs.select{|d| d.modified?}
|
543
543
|
until to_save.empty?
|
544
544
|
dlg = SaveModifiedFilesDlg.new to_save, self
|
545
|
+
to_save = dlg.to_save
|
545
546
|
case dlg.exec
|
546
547
|
when KDE::Dialog::Yes
|
547
|
-
to_save
|
548
|
+
to_save.delete_if{|doc| doc.save}
|
548
549
|
unless to_save.empty?
|
549
550
|
msg = "The following documents couldn't be saved: #{to_save.join "\n"}\nPlease, choose how to proceed"
|
550
551
|
KDE::MessageBox.sorry nil, KDE.i18n(msg)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
=begin
|
2
|
-
Copyright (C) 2010 by Stefano Crocco
|
2
|
+
Copyright (C) 2010, 2011 by Stefano Crocco
|
3
3
|
stefano.crocco@alice.it
|
4
4
|
|
5
5
|
This program is free software; you can redistribute it andor modify
|
@@ -280,7 +280,7 @@ informing the user
|
|
280
280
|
pl.save_settings
|
281
281
|
loaded << pl.plugin_name
|
282
282
|
end
|
283
|
-
loaded.
|
283
|
+
loaded.reverse_each{|pl| Ruber[:components].unload_plugin pl}
|
284
284
|
res = Ruber[:app].safe_load_plugins dlg.plugins.keys.map(&:to_s)
|
285
285
|
close unless res
|
286
286
|
nil
|
data/lib/ruber/output_widget.rb
CHANGED
@@ -757,7 +757,9 @@ option is used.
|
|
757
757
|
existing = (Qt::MetaModifier & modifiers) == 0 ? :always : :never
|
758
758
|
display_hints = hints.merge(:line => line, :existing => existing)
|
759
759
|
ed = Ruber[:main_window].display_document file, display_hints
|
760
|
-
|
760
|
+
hide_tool = pinned_down? and Qt::Application.mouse_buttons != Qt::MidButton
|
761
|
+
Ruber[:main_window].hide_tool self if hide_tool
|
762
|
+
ed.set_focus if ed
|
761
763
|
ed
|
762
764
|
end
|
763
765
|
|
@@ -771,11 +773,21 @@ however, that the @:existing@ entry won't be used.
|
|
771
773
|
@return [Hash] see the description for the _hints_ argument of {MainWindow#editor_for!}
|
772
774
|
=end
|
773
775
|
def hints
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
776
|
+
hints = {:new => :new_tab}
|
777
|
+
choice = Ruber[:config][:general, :tool_open_files]
|
778
|
+
case choice
|
779
|
+
when :split_horizontally then hints[:split] = :horizontal
|
780
|
+
when :split_vertically then hints[:split] = :vertical
|
778
781
|
end
|
782
|
+
if hints[:split]
|
783
|
+
env = Ruber[:world].active_environment
|
784
|
+
view = env.active_editor
|
785
|
+
n_views = view ? env.tab(view).views.count : 0
|
786
|
+
if n_views == 1 then hints[:new] = :current_tab
|
787
|
+
else hints.delete :split
|
788
|
+
end
|
789
|
+
end
|
790
|
+
hints
|
779
791
|
end
|
780
792
|
|
781
793
|
=begin rdoc
|
data/lib/ruber/project.rb
CHANGED
@@ -24,6 +24,7 @@ require 'yaml'
|
|
24
24
|
require 'ruber/plugin'
|
25
25
|
require 'ruber/settings_container'
|
26
26
|
require 'ruber/project_backend'
|
27
|
+
require 'ruber/project_dir_scanner'
|
27
28
|
|
28
29
|
module Ruber
|
29
30
|
|
@@ -130,7 +131,6 @@ When the project is created, it's not active.
|
|
130
131
|
@project_extensions = {}
|
131
132
|
Ruber[:components].named_connect(SIGNAL('component_loaded(QObject*)'), "register_component_with_project #{object_id}"){|c| c.register_with_project self}
|
132
133
|
Ruber[:components].named_connect(SIGNAL('unloading_component(QObject*)'), "remove_component_from_project #{object_id}"){|c| c.remove_from_project self}
|
133
|
-
Ruber[:components].each_component{|c| c.register_with_project self}
|
134
134
|
end
|
135
135
|
|
136
136
|
=begin rdoc
|
@@ -324,6 +324,22 @@ will be removed (calling their @remove_from_project@ method if they have one).
|
|
324
324
|
true
|
325
325
|
end
|
326
326
|
|
327
|
+
=begin rdoc
|
328
|
+
Registers each component with the project
|
329
|
+
|
330
|
+
This is done in {#initialize} because, at least for {DocumentProject}, the extensions
|
331
|
+
may try to access the project (directly or not) before it has fully been created.
|
332
|
+
|
333
|
+
This method should only be called from the object calling {.new}
|
334
|
+
|
335
|
+
@note This method has nothing to do with finalizers
|
336
|
+
@return [nil]
|
337
|
+
=end
|
338
|
+
def finalize
|
339
|
+
Ruber[:components].each_component{|c| c.register_with_project self}
|
340
|
+
nil
|
341
|
+
end
|
342
|
+
|
327
343
|
end
|
328
344
|
|
329
345
|
=begin rdoc
|
@@ -378,6 +394,16 @@ AbstractProject::InvalidProjectFile will be raised.
|
|
378
394
|
raise Ruber::AbstractProject::InvalidProjectFile, e.message
|
379
395
|
end
|
380
396
|
super Ruber[:world], back, name
|
397
|
+
finalize
|
398
|
+
@dir_scanner = ProjectDirScanner.new self
|
399
|
+
@dir_scanner.connect(SIGNAL('file_added(QString)')) do |f|
|
400
|
+
@files << f if @files
|
401
|
+
end
|
402
|
+
@dir_scanner.connect(SIGNAL('file_removed(QString)')) do |f|
|
403
|
+
@files.delete f if @files
|
404
|
+
end
|
405
|
+
@dir_scanner.connect(SIGNAL(:rules_changed)){@files = nil}
|
406
|
+
@files = nil
|
381
407
|
end
|
382
408
|
|
383
409
|
=begin rdoc
|
@@ -417,9 +443,14 @@ to the project.
|
|
417
443
|
<b>Note:</b> this method uses the <tt>project_files</tt> extension
|
418
444
|
=end
|
419
445
|
def files
|
420
|
-
@
|
446
|
+
@files ||= @dir_scanner.project_files
|
447
|
+
ProjectFiles.new project_directory, @files
|
448
|
+
end
|
449
|
+
alias_method :project_files, :files
|
450
|
+
|
451
|
+
def file_in_project? file
|
452
|
+
@dir_scanner.file_in_project? file
|
421
453
|
end
|
422
|
-
|
423
454
|
end
|
424
455
|
|
425
456
|
=begin rdoc
|
@@ -0,0 +1,171 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright (C) 2011 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 'set'
|
22
|
+
require 'find'
|
23
|
+
require 'delegate'
|
24
|
+
|
25
|
+
require 'kio'
|
26
|
+
|
27
|
+
module Ruber
|
28
|
+
|
29
|
+
class ProjectDirScanner < Qt::Object
|
30
|
+
|
31
|
+
signals :rules_changed
|
32
|
+
|
33
|
+
signals 'file_added(QString)'
|
34
|
+
|
35
|
+
signals 'file_removed(QString)'
|
36
|
+
|
37
|
+
def initialize prj
|
38
|
+
super
|
39
|
+
@project = prj
|
40
|
+
#The /? at the end is there to avoid depending on whether Project#project_directory
|
41
|
+
#returns a string ending with / or not
|
42
|
+
@regexp = %r[^#{Regexp.quote @project.project_directory}/?]
|
43
|
+
make_rules
|
44
|
+
@watcher = KDE::DirWatch.new self do
|
45
|
+
add_dir prj.project_directory,
|
46
|
+
KDE::DirWatch::WatchFiles | KDE::DirWatch::WatchSubDirs
|
47
|
+
end
|
48
|
+
@watcher.connect(SIGNAL('created(QString)')) do |f|
|
49
|
+
emit file_added(f) if file_in_project? f
|
50
|
+
end
|
51
|
+
@watcher.connect(SIGNAL('deleted(QString)')) do |f|
|
52
|
+
emit file_removed(f) if file_in_project? f
|
53
|
+
end
|
54
|
+
@project.connect(SIGNAL('option_changed(QString, QString)')) do |g, n|
|
55
|
+
if g == 'general' and n == 'project_files'
|
56
|
+
if @project[:general, :project_files] != @rules
|
57
|
+
make_rules
|
58
|
+
emit rules_changed
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
@watcher.start_scan false
|
63
|
+
end
|
64
|
+
|
65
|
+
def file_in_project? file
|
66
|
+
if file.start_with? '/'
|
67
|
+
file = file.dup
|
68
|
+
return false unless file.sub! @regexp, ''
|
69
|
+
end
|
70
|
+
return nil if file.end_with? '/'
|
71
|
+
if file =~ %r{^([\w+-.]+)://(.+)}
|
72
|
+
if $1 == 'file' then file = $2
|
73
|
+
else return false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
return false if @exclude_regexp =~ file
|
77
|
+
return false if @exclude_files.include? file
|
78
|
+
return true if @extensions.any?{|e| File.fnmatch?(e, file, File::FNM_DOTMATCH)}
|
79
|
+
return true if @include_regexp =~ file or @include_files.include? file
|
80
|
+
false
|
81
|
+
end
|
82
|
+
|
83
|
+
def project_files
|
84
|
+
res = Set.new
|
85
|
+
dir = @project.project_directory
|
86
|
+
Ruber[:app].chdir dir do
|
87
|
+
Find.find '.' do |f|
|
88
|
+
next if File.directory? f
|
89
|
+
#remove the leading './'
|
90
|
+
f = f[2..-1]
|
91
|
+
res << File.join(dir, f) if file_in_project? f
|
92
|
+
end
|
93
|
+
end
|
94
|
+
res
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def make_rules
|
100
|
+
rules = @project[:general, :project_files]
|
101
|
+
@include_regexp = Regexp.union(*(rules[:include].select{|r| r.is_a?(Regexp)}))
|
102
|
+
@exclude_regexp = Regexp.union(*(rules[:exclude].select{|r| r.is_a?(Regexp)}))
|
103
|
+
@exclude_files = rules[:exclude].select{|rule| rule.is_a? String}.map{|f| f.sub(%r{^\./}, '')}
|
104
|
+
@include_files = rules[:include].select{|rule| rule.is_a? String}.map{|f| f.sub(%r{^\./}, '')}
|
105
|
+
@include_files-= @exclude_files
|
106
|
+
@extensions = rules[:extensions]
|
107
|
+
@rules = YAML.load(YAML.dump rules)
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
class ProjectFiles < Delegator
|
113
|
+
|
114
|
+
include Enumerable
|
115
|
+
|
116
|
+
def initialize project_dir, set
|
117
|
+
super set
|
118
|
+
@set = set
|
119
|
+
@project_dir = project_dir.dup
|
120
|
+
@project_dir << '/' unless @project_dir.end_with? '/'
|
121
|
+
end
|
122
|
+
|
123
|
+
def __getobj__
|
124
|
+
@set
|
125
|
+
end
|
126
|
+
|
127
|
+
def __setobj__ obj
|
128
|
+
@set = obj
|
129
|
+
end
|
130
|
+
|
131
|
+
def dup
|
132
|
+
self.class.new @project_dir, @set
|
133
|
+
end
|
134
|
+
|
135
|
+
def clone
|
136
|
+
res = dup
|
137
|
+
dup.freeze if frozen?
|
138
|
+
res
|
139
|
+
end
|
140
|
+
|
141
|
+
def to_set
|
142
|
+
Set.new self
|
143
|
+
end
|
144
|
+
|
145
|
+
def each_relative
|
146
|
+
if block_given?
|
147
|
+
l = @project_dir.size
|
148
|
+
@set.each{|f| yield f[l, f.size-l]}
|
149
|
+
else self.to_enum :each_relative
|
150
|
+
end
|
151
|
+
end
|
152
|
+
alias_method :rel, :each_relative
|
153
|
+
|
154
|
+
def each
|
155
|
+
if block_given?
|
156
|
+
@set.each{|f| yield f}
|
157
|
+
else self.to_enum
|
158
|
+
end
|
159
|
+
end
|
160
|
+
alias_method :abs, :each
|
161
|
+
|
162
|
+
[:<<, :add, :clear, :collect!, :delete, :delete_if, :flatten!, :keep_if,
|
163
|
+
:map!, :merge, :reject!, :replace, :subtract].each do |m|
|
164
|
+
define_method m do |*args|
|
165
|
+
raise NoMethodError
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|