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