ruber 0.0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +339 -0
- data/INSTALL +137 -0
- data/LICENSE +8 -0
- data/bin/ruber +65 -0
- data/data/share/apps/ruber/core_components.yaml +31 -0
- data/data/share/apps/ruber/ruberui.rc +109 -0
- data/data/share/icons/ruber.png +0 -0
- data/data/share/pixmaps/ruby.png +0 -0
- data/icons/ruber-16.png +0 -0
- data/icons/ruber-32.png +0 -0
- data/icons/ruber-48.png +0 -0
- data/icons/ruber-8.png +0 -0
- data/lib/ruber/application/application.rb +288 -0
- data/lib/ruber/application/plugin.yaml +11 -0
- data/lib/ruber/component_manager.rb +899 -0
- data/lib/ruber/config/config.rb +82 -0
- data/lib/ruber/config/plugin.yaml +3 -0
- data/lib/ruber/document_project.rb +209 -0
- data/lib/ruber/documents/document_list.rb +416 -0
- data/lib/ruber/documents/plugin.yaml +4 -0
- data/lib/ruber/editor/document.rb +506 -0
- data/lib/ruber/editor/editor_view.rb +167 -0
- data/lib/ruber/editor/ktexteditor_wrapper.rb +202 -0
- data/lib/ruber/exception_widgets.rb +245 -0
- data/lib/ruber/external_program_plugin.rb +397 -0
- data/lib/ruber/filtered_output_widget.rb +342 -0
- data/lib/ruber/gui_states_handler.rb +231 -0
- data/lib/ruber/kde_config_option_backend.rb +167 -0
- data/lib/ruber/kde_sugar.rb +249 -0
- data/lib/ruber/main_window/choose_plugins_dlg.rb +353 -0
- data/lib/ruber/main_window/main_window.rb +524 -0
- data/lib/ruber/main_window/main_window_actions.rb +537 -0
- data/lib/ruber/main_window/main_window_internal.rb +239 -0
- data/lib/ruber/main_window/open_file_in_project_dlg.rb +212 -0
- data/lib/ruber/main_window/output_color_widget.rb +35 -0
- data/lib/ruber/main_window/plugin.yaml +58 -0
- data/lib/ruber/main_window/save_modified_files_dlg.rb +89 -0
- data/lib/ruber/main_window/status_bar.rb +156 -0
- data/lib/ruber/main_window/ui/choose_plugins_widget.rb +90 -0
- data/lib/ruber/main_window/ui/choose_plugins_widget.ui +77 -0
- data/lib/ruber/main_window/ui/main_window_settings_widget.rb +108 -0
- data/lib/ruber/main_window/ui/main_window_settings_widget.ui +89 -0
- data/lib/ruber/main_window/ui/new_project_widget.rb +119 -0
- data/lib/ruber/main_window/ui/new_project_widget.ui +178 -0
- data/lib/ruber/main_window/ui/open_file_in_project_dlg.rb +109 -0
- data/lib/ruber/main_window/ui/open_file_in_project_dlg.ui +168 -0
- data/lib/ruber/main_window/ui/output_color_widget.rb +241 -0
- data/lib/ruber/main_window/ui/output_color_widget.ui +204 -0
- data/lib/ruber/main_window/workspace.rb +442 -0
- data/lib/ruber/output_widget.rb +1093 -0
- data/lib/ruber/plugin.rb +264 -0
- data/lib/ruber/plugin_like.rb +589 -0
- data/lib/ruber/plugin_specification.rb +106 -0
- data/lib/ruber/plugin_specification_reader.rb +451 -0
- data/lib/ruber/project.rb +493 -0
- data/lib/ruber/project_backend.rb +105 -0
- data/lib/ruber/projects/plugin.yaml +11 -0
- data/lib/ruber/projects/project_files_list.rb +314 -0
- data/lib/ruber/projects/project_files_widget.rb +301 -0
- data/lib/ruber/projects/project_list.rb +314 -0
- data/lib/ruber/projects/ui/project_files_rule_chooser_widget.rb +74 -0
- data/lib/ruber/projects/ui/project_files_rule_chooser_widget.ui +61 -0
- data/lib/ruber/projects/ui/project_files_widget.rb +117 -0
- data/lib/ruber/projects/ui/project_files_widget.ui +123 -0
- data/lib/ruber/qt_sugar.rb +673 -0
- data/lib/ruber/settings_container.rb +515 -0
- data/lib/ruber/settings_dialog.rb +244 -0
- data/lib/ruber/settings_dialog_manager.rb +503 -0
- data/lib/ruber/utils.rb +414 -0
- data/lib/ruber/yaml_option_backend.rb +159 -0
- data/outsider_files +15 -0
- data/plugins/autosave/autosave.rb +404 -0
- data/plugins/autosave/plugin.yaml +16 -0
- data/plugins/autosave/ui/autosave_config_widget.rb +83 -0
- data/plugins/autosave/ui/autosave_config_widget.ui +68 -0
- data/plugins/command/command.png +0 -0
- data/plugins/command/command.rb +74 -0
- data/plugins/command/plugin.yaml +11 -0
- data/plugins/find_in_files/find_in_files.rb +337 -0
- data/plugins/find_in_files/find_in_files_dlg.rb +411 -0
- data/plugins/find_in_files/find_in_files_ui.rc +11 -0
- data/plugins/find_in_files/find_in_files_widgets.rb +485 -0
- data/plugins/find_in_files/plugin.yaml +23 -0
- data/plugins/find_in_files/ui/config_widget.rb +58 -0
- data/plugins/find_in_files/ui/config_widget.ui +41 -0
- data/plugins/find_in_files/ui/find_in_files_widget.rb +260 -0
- data/plugins/find_in_files/ui/find_in_files_widget.ui +324 -0
- data/plugins/project_browser/plugin.yaml +10 -0
- data/plugins/project_browser/project_browser.rb +245 -0
- data/plugins/rake/plugin.yaml +39 -0
- data/plugins/rake/rake.png +0 -0
- data/plugins/rake/rake.rb +567 -0
- data/plugins/rake/rake_extension.rb +153 -0
- data/plugins/rake/rake_widgets.rb +615 -0
- data/plugins/rake/rakeui.rc +27 -0
- data/plugins/rake/ui/add_quick_task_widget.rb +71 -0
- data/plugins/rake/ui/add_quick_task_widget.ui +59 -0
- data/plugins/rake/ui/choose_task_widget.rb +77 -0
- data/plugins/rake/ui/choose_task_widget.ui +72 -0
- data/plugins/rake/ui/config_widget.rb +127 -0
- data/plugins/rake/ui/config_widget.ui +123 -0
- data/plugins/rake/ui/project_widget.rb +217 -0
- data/plugins/rake/ui/project_widget.ui +246 -0
- data/plugins/rspec/plugin.yaml +30 -0
- data/plugins/rspec/rspec.png +0 -0
- data/plugins/rspec/rspec.rb +945 -0
- data/plugins/rspec/rspec.svg +90 -0
- data/plugins/rspec/rspecui.rc +20 -0
- data/plugins/rspec/ruber_rspec_formatter.rb +312 -0
- data/plugins/rspec/ui/rspec_project_widget.rb +170 -0
- data/plugins/rspec/ui/rspec_project_widget.ui +193 -0
- data/plugins/ruby_development/plugin.yaml +27 -0
- data/plugins/ruby_development/ruby_development.png +0 -0
- data/plugins/ruby_development/ruby_development.rb +453 -0
- data/plugins/ruby_development/ruby_developmentui.rc +19 -0
- data/plugins/ruby_development/ui/project_widget.rb +112 -0
- data/plugins/ruby_development/ui/project_widget.ui +108 -0
- data/plugins/ruby_runner/config_widget.rb +116 -0
- data/plugins/ruby_runner/plugin.yaml +26 -0
- data/plugins/ruby_runner/project_widget.rb +62 -0
- data/plugins/ruby_runner/ruby.png +0 -0
- data/plugins/ruby_runner/ruby_interpretersui.rc +26 -0
- data/plugins/ruby_runner/ruby_runner.rb +411 -0
- data/plugins/ruby_runner/ui/config_widget.rb +92 -0
- data/plugins/ruby_runner/ui/config_widget.ui +91 -0
- data/plugins/ruby_runner/ui/project_widget.rb +60 -0
- data/plugins/ruby_runner/ui/project_widget.ui +48 -0
- data/plugins/ruby_runner/ui/ruby_runnner_plugin_option_widget.rb +59 -0
- data/plugins/ruby_runner/ui/ruby_runnner_plugin_option_widget.ui +44 -0
- data/plugins/state/plugin.yaml +28 -0
- data/plugins/state/state.rb +520 -0
- data/plugins/state/ui/config_widget.rb +92 -0
- data/plugins/state/ui/config_widget.ui +89 -0
- data/plugins/syntax_checker/plugin.yaml +18 -0
- data/plugins/syntax_checker/syntax_checker.rb +662 -0
- data/ruber.desktop +10 -0
- data/spec/annotation_model_spec.rb +174 -0
- data/spec/common.rb +119 -0
- data/spec/component_manager_spec.rb +1259 -0
- data/spec/document_list_spec.rb +626 -0
- data/spec/document_project_spec.rb +373 -0
- data/spec/document_spec.rb +779 -0
- data/spec/editor_view_spec.rb +167 -0
- data/spec/external_program_plugin_spec.rb +676 -0
- data/spec/filtered_output_widget_spec.rb +642 -0
- data/spec/gui_states_handler_spec.rb +304 -0
- data/spec/kde_config_option_backend_spec.rb +214 -0
- data/spec/kde_sugar_spec.rb +101 -0
- data/spec/ktexteditor_wrapper_spec.rb +305 -0
- data/spec/output_widget_spec.rb +1703 -0
- data/spec/plugin_spec.rb +1393 -0
- data/spec/plugin_specification_reader_spec.rb +1765 -0
- data/spec/plugin_specification_spec.rb +401 -0
- data/spec/project_backend_spec.rb +172 -0
- data/spec/project_files_list_spec.rb +401 -0
- data/spec/project_list_spec.rb +511 -0
- data/spec/project_spec.rb +990 -0
- data/spec/qt_sugar_spec.rb +328 -0
- data/spec/settings_container_spec.rb +617 -0
- data/spec/settings_dialog_manager_spec.rb +773 -0
- data/spec/settings_dialog_spec.rb +419 -0
- data/spec/state_spec.rb +991 -0
- data/spec/utils_spec.rb +406 -0
- data/spec/workspace_spec.rb +869 -0
- data/spec/yaml_option_backend_spec.rb +246 -0
- metadata +284 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
=begin
|
2
|
+
** Form generated from reading ui file 'config_widget.ui'
|
3
|
+
**
|
4
|
+
** Created: ven ott 29 17:39:04 2010
|
5
|
+
** by: Qt User Interface Compiler version 4.7.0
|
6
|
+
**
|
7
|
+
** WARNING! All changes made in this file will be lost when recompiling ui file!
|
8
|
+
=end
|
9
|
+
|
10
|
+
class Ui_StateConfigWidget
|
11
|
+
attr_reader :verticalLayout
|
12
|
+
attr_reader :groupBox
|
13
|
+
attr_reader :gridLayout
|
14
|
+
attr_reader :_state__restore_cursor_position
|
15
|
+
attr_reader :_state__restore_project_files
|
16
|
+
attr_reader :horizontalLayout_2
|
17
|
+
attr_reader :label_2
|
18
|
+
attr_reader :_state__startup_behaviour
|
19
|
+
|
20
|
+
def setupUi(stateConfigWidget)
|
21
|
+
if stateConfigWidget.objectName.nil?
|
22
|
+
stateConfigWidget.objectName = "stateConfigWidget"
|
23
|
+
end
|
24
|
+
stateConfigWidget.resize(400, 128)
|
25
|
+
@verticalLayout = Qt::VBoxLayout.new(stateConfigWidget)
|
26
|
+
@verticalLayout.objectName = "verticalLayout"
|
27
|
+
@groupBox = Qt::GroupBox.new(stateConfigWidget)
|
28
|
+
@groupBox.objectName = "groupBox"
|
29
|
+
@gridLayout = Qt::GridLayout.new(@groupBox)
|
30
|
+
@gridLayout.objectName = "gridLayout"
|
31
|
+
@_state__restore_cursor_position = Qt::CheckBox.new(@groupBox)
|
32
|
+
@_state__restore_cursor_position.objectName = "_state__restore_cursor_position"
|
33
|
+
|
34
|
+
@gridLayout.addWidget(@_state__restore_cursor_position, 0, 0, 1, 1)
|
35
|
+
|
36
|
+
@_state__restore_project_files = Qt::CheckBox.new(@groupBox)
|
37
|
+
@_state__restore_project_files.objectName = "_state__restore_project_files"
|
38
|
+
|
39
|
+
@gridLayout.addWidget(@_state__restore_project_files, 1, 0, 1, 1)
|
40
|
+
|
41
|
+
@horizontalLayout_2 = Qt::HBoxLayout.new()
|
42
|
+
@horizontalLayout_2.objectName = "horizontalLayout_2"
|
43
|
+
@label_2 = Qt::Label.new(@groupBox)
|
44
|
+
@label_2.objectName = "label_2"
|
45
|
+
|
46
|
+
@horizontalLayout_2.addWidget(@label_2)
|
47
|
+
|
48
|
+
@_state__startup_behaviour = KDE::ComboBox.new(@groupBox)
|
49
|
+
@_state__startup_behaviour.objectName = "_state__startup_behaviour"
|
50
|
+
|
51
|
+
@horizontalLayout_2.addWidget(@_state__startup_behaviour)
|
52
|
+
|
53
|
+
|
54
|
+
@gridLayout.addLayout(@horizontalLayout_2, 2, 0, 1, 1)
|
55
|
+
|
56
|
+
|
57
|
+
@verticalLayout.addWidget(@groupBox)
|
58
|
+
|
59
|
+
|
60
|
+
retranslateUi(stateConfigWidget)
|
61
|
+
|
62
|
+
Qt::MetaObject.connectSlotsByName(stateConfigWidget)
|
63
|
+
end # setupUi
|
64
|
+
|
65
|
+
def setup_ui(stateConfigWidget)
|
66
|
+
setupUi(stateConfigWidget)
|
67
|
+
end
|
68
|
+
|
69
|
+
def retranslateUi(stateConfigWidget)
|
70
|
+
stateConfigWidget.windowTitle = Qt::Application.translate("StateConfigWidget", "Form", nil, Qt::Application::UnicodeUTF8)
|
71
|
+
@groupBox.title = Qt::Application.translate("StateConfigWidget", "State", nil, Qt::Application::UnicodeUTF8)
|
72
|
+
@_state__restore_cursor_position.text = Qt::Application.translate("StateConfigWidget", "Restore cursor position when opening documents", nil, Qt::Application::UnicodeUTF8)
|
73
|
+
@_state__restore_project_files.text = Qt::Application.translate("StateConfigWidget", "Restore open files when opening a project", nil, Qt::Application::UnicodeUTF8)
|
74
|
+
@label_2.text = Qt::Application.translate("StateConfigWidget", "On startup", nil, Qt::Application::UnicodeUTF8)
|
75
|
+
@_state__startup_behaviour.insertItems(0, [Qt::Application.translate("StateConfigWidget", "Restore open project and files", nil, Qt::Application::UnicodeUTF8),
|
76
|
+
Qt::Application.translate("StateConfigWidget", "Restore open files only", nil, Qt::Application::UnicodeUTF8),
|
77
|
+
Qt::Application.translate("StateConfigWidget", "Restore open project only", nil, Qt::Application::UnicodeUTF8),
|
78
|
+
Qt::Application.translate("StateConfigWidget", "Keep empty workspace", nil, Qt::Application::UnicodeUTF8)])
|
79
|
+
@_state__startup_behaviour.setProperty("access", Qt::Variant.new(Qt::Application.translate("StateConfigWidget", "$startup_behaviour", nil, Qt::Application::UnicodeUTF8)))
|
80
|
+
end # retranslateUi
|
81
|
+
|
82
|
+
def retranslate_ui(stateConfigWidget)
|
83
|
+
retranslateUi(stateConfigWidget)
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
module Ui
|
89
|
+
class StateConfigWidget < Ui_StateConfigWidget
|
90
|
+
end
|
91
|
+
end # module Ui
|
92
|
+
|
@@ -0,0 +1,89 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<ui version="4.0">
|
3
|
+
<class>StateConfigWidget</class>
|
4
|
+
<widget class="QWidget" name="StateConfigWidget">
|
5
|
+
<property name="geometry">
|
6
|
+
<rect>
|
7
|
+
<x>0</x>
|
8
|
+
<y>0</y>
|
9
|
+
<width>400</width>
|
10
|
+
<height>128</height>
|
11
|
+
</rect>
|
12
|
+
</property>
|
13
|
+
<property name="windowTitle">
|
14
|
+
<string>Form</string>
|
15
|
+
</property>
|
16
|
+
<layout class="QVBoxLayout" name="verticalLayout">
|
17
|
+
<item>
|
18
|
+
<widget class="QGroupBox" name="groupBox">
|
19
|
+
<property name="title">
|
20
|
+
<string>State</string>
|
21
|
+
</property>
|
22
|
+
<layout class="QGridLayout" name="gridLayout">
|
23
|
+
<item row="0" column="0">
|
24
|
+
<widget class="QCheckBox" name="_state__restore_cursor_position">
|
25
|
+
<property name="text">
|
26
|
+
<string>Restore cursor position when opening documents</string>
|
27
|
+
</property>
|
28
|
+
</widget>
|
29
|
+
</item>
|
30
|
+
<item row="1" column="0">
|
31
|
+
<widget class="QCheckBox" name="_state__restore_project_files">
|
32
|
+
<property name="text">
|
33
|
+
<string>Restore open files when opening a project</string>
|
34
|
+
</property>
|
35
|
+
</widget>
|
36
|
+
</item>
|
37
|
+
<item row="2" column="0">
|
38
|
+
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
39
|
+
<item>
|
40
|
+
<widget class="QLabel" name="label_2">
|
41
|
+
<property name="text">
|
42
|
+
<string>On startup</string>
|
43
|
+
</property>
|
44
|
+
</widget>
|
45
|
+
</item>
|
46
|
+
<item>
|
47
|
+
<widget class="KComboBox" name="_state__startup_behaviour">
|
48
|
+
<property name="access" stdset="0">
|
49
|
+
<string>$startup_behaviour</string>
|
50
|
+
</property>
|
51
|
+
<item>
|
52
|
+
<property name="text">
|
53
|
+
<string>Restore open project and files</string>
|
54
|
+
</property>
|
55
|
+
</item>
|
56
|
+
<item>
|
57
|
+
<property name="text">
|
58
|
+
<string>Restore open files only</string>
|
59
|
+
</property>
|
60
|
+
</item>
|
61
|
+
<item>
|
62
|
+
<property name="text">
|
63
|
+
<string>Restore open project only</string>
|
64
|
+
</property>
|
65
|
+
</item>
|
66
|
+
<item>
|
67
|
+
<property name="text">
|
68
|
+
<string>Keep empty workspace</string>
|
69
|
+
</property>
|
70
|
+
</item>
|
71
|
+
</widget>
|
72
|
+
</item>
|
73
|
+
</layout>
|
74
|
+
</item>
|
75
|
+
</layout>
|
76
|
+
</widget>
|
77
|
+
</item>
|
78
|
+
</layout>
|
79
|
+
</widget>
|
80
|
+
<customwidgets>
|
81
|
+
<customwidget>
|
82
|
+
<class>KComboBox</class>
|
83
|
+
<extends>QComboBox</extends>
|
84
|
+
<header>kcombobox.h</header>
|
85
|
+
</customwidget>
|
86
|
+
</customwidgets>
|
87
|
+
<resources/>
|
88
|
+
<connections/>
|
89
|
+
</ui>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
name: syntax_checker
|
2
|
+
version: 0.0.1
|
3
|
+
about:
|
4
|
+
authors: [Stefano Crocco, stefano.crocco@alice.it]
|
5
|
+
license: :gpl
|
6
|
+
description: Checks the syntax of the current document
|
7
|
+
icon: tools-check-spelling
|
8
|
+
bug_address: http://github.com/stcrocco/ruber/issues
|
9
|
+
class: Ruber::SyntaxChecker::SyntaxCheckerPlugin
|
10
|
+
require: syntax_checker
|
11
|
+
deps: ruby_development
|
12
|
+
config_options:
|
13
|
+
syntax_checker:
|
14
|
+
automatic_check: {default: true}
|
15
|
+
config_widgets:
|
16
|
+
{caption: Syntax, code: 'Qt::CheckBox.new("&Automatically check syntax"){self.object_name = "_syntax_checker__automatic_check"}', pixmap: tools-check-spelling.png}
|
17
|
+
extensions:
|
18
|
+
syntax_checker: {class: Ruber::SyntaxChecker::SyntaxCheckerExtension, scope: document}
|
@@ -0,0 +1,662 @@
|
|
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 'tempfile'
|
22
|
+
require 'open3'
|
23
|
+
|
24
|
+
require 'facets/boolean'
|
25
|
+
|
26
|
+
module Ruber
|
27
|
+
|
28
|
+
=begin rdoc
|
29
|
+
Module for the *Syntax checker* plugin.
|
30
|
+
|
31
|
+
This plugin provides a framework to let the user know whether the file in the
|
32
|
+
current editor view is syntactically correct or not (according to the most appropriate
|
33
|
+
sytnax for that kind of file). The result of the syntax check is displayed in a
|
34
|
+
widget at the right end of the status bar (this will be referred to as the *syntax
|
35
|
+
result widget). This implementation of the @syntax_checker@ feature uses a @KDE::Led@
|
36
|
+
whose colour changes according to the result of the syntax check, but other plugins
|
37
|
+
may use other widgets. If the user right clikcs on the widget, a menu showing a
|
38
|
+
list of syntax errors is displayed. Clicking on it will jump to the corresponding
|
39
|
+
like, while clicking on the widget itself jumps to the line corresponding to the
|
40
|
+
first error.
|
41
|
+
|
42
|
+
The syntax check is run every time the file is activated or saved and the user can choose to
|
43
|
+
have it run automatically when one second has passed since he last edited the
|
44
|
+
file. The reasoning is that it makes little sense to check the syntax while the
|
45
|
+
user is writing text: it will most likely be wrong (because the user hasn't finished
|
46
|
+
writing what he wants), may quickly change from valid to invalid depending on the
|
47
|
+
point the user has reached in writing, and the user won't look at it because he's
|
48
|
+
busy writing.
|
49
|
+
|
50
|
+
The kind of syntax check to perform on a document is decided according to the mimetype
|
51
|
+
of the document (this means that only documents associated with a file can be
|
52
|
+
syntax-checked). Currently, this plugin contains syntax checkers for ruby files
|
53
|
+
and YAML files, but syntax checkers for other kind of files can be added by other
|
54
|
+
plugins (see the documentation for {SyntaxCheckerPlugin#register_syntax_checker register_syntax_checker}
|
55
|
+
for details)
|
56
|
+
|
57
|
+
@api feature syntax_checker
|
58
|
+
@plugin
|
59
|
+
@config_option syntax_checker automatic_check [Boolean] Whether to perform automatic
|
60
|
+
syntax checks after one second of inactivity
|
61
|
+
=end
|
62
|
+
module SyntaxChecker
|
63
|
+
|
64
|
+
=begin rdoc
|
65
|
+
Plugin object for the @sytax_checker@ feature
|
66
|
+
|
67
|
+
@api class SyntaxChecker::SyntaxCheckerPlugin
|
68
|
+
@api_method #register_syntax_checker
|
69
|
+
@api_method #remove_syntax_checker
|
70
|
+
=end
|
71
|
+
class SyntaxCheckerPlugin < Plugin
|
72
|
+
|
73
|
+
=begin rdoc
|
74
|
+
Class containing the information about a syntax error. It has four attributes:
|
75
|
+
line:= the line at which the syntax error occurred (note that this starts from
|
76
|
+
1, while Document and EditorView count lines from 0)
|
77
|
+
message:= a string describing the syntax error
|
78
|
+
code:= a string with the code around the point where the syntax error occurred
|
79
|
+
column:= the column at which the syntax error occurred
|
80
|
+
|
81
|
+
This class'constructor can take up to four parameters, corresponding (in
|
82
|
+
the same order) to the four attributes described above.
|
83
|
+
=end
|
84
|
+
ErrorDescription = Struct.new(:line, :message, :code, :column)
|
85
|
+
|
86
|
+
=begin rdoc
|
87
|
+
Colors used to display the different states of the document
|
88
|
+
=end
|
89
|
+
COLORS = {
|
90
|
+
:correct => Qt::Color.new(Qt.green),
|
91
|
+
:error => Qt::Color.new(Qt.red),
|
92
|
+
:unknown => Qt::Color.new(Qt.gray)
|
93
|
+
}
|
94
|
+
|
95
|
+
=begin rdoc
|
96
|
+
Signal emitted when it's time to perform an automatic syntax check
|
97
|
+
=end
|
98
|
+
signals :timeout
|
99
|
+
|
100
|
+
=begin rdoc
|
101
|
+
Creates an instance of the plugin
|
102
|
+
|
103
|
+
It also registers the two built-in syntax checkers
|
104
|
+
|
105
|
+
@param [Ruber::PluginSpecification] the specification associated to the
|
106
|
+
plugin
|
107
|
+
=end
|
108
|
+
def initialize psf
|
109
|
+
super
|
110
|
+
@availlable_syntax_checkers = {}
|
111
|
+
register_syntax_checker RubySyntaxChecker, 'application/x-ruby',
|
112
|
+
%w[*.rb rakefile Rakefile]
|
113
|
+
register_syntax_checker YamlSyntaxChecker, [], %w[*.yml *.yaml]
|
114
|
+
@led = SyntaxResultWidget.new
|
115
|
+
Ruber[:main_window].status_bar.add_permanent_widget @led
|
116
|
+
mark_document_as :unknown
|
117
|
+
end
|
118
|
+
|
119
|
+
=begin rdoc
|
120
|
+
Instantiates an appropriate syntax checker for a document
|
121
|
+
|
122
|
+
@param [Document] doc the document to create the syntax checker for
|
123
|
+
@return [Object,nil] a syntax checker suitable for _doc_ or *nil* if _doc_ is not
|
124
|
+
associated with a file or no syntax checker has been registered for <i>doc</i>'s extension
|
125
|
+
or mimetype
|
126
|
+
=end
|
127
|
+
def syntax_checker_for doc
|
128
|
+
checker_cls = @availlable_syntax_checkers.find! do |cls, data|
|
129
|
+
doc.file_type_match?(*data) ? cls : nil
|
130
|
+
end
|
131
|
+
checker_cls ? checker_cls.new(doc) : nil
|
132
|
+
end
|
133
|
+
|
134
|
+
=begin rdoc
|
135
|
+
Tells the plugin to display the result of the syntax check for the current document
|
136
|
+
|
137
|
+
@param [Symbol] status the result of the syntax check. It can be one of @:correct@,
|
138
|
+
@:error@ or @:unknown@ (if no syntax checker was availlable for the document)
|
139
|
+
@param [Array<SyntaxCheckerPlugin::ErrorDescription>] errors an array containing
|
140
|
+
instances of class {SyntaxCheckerPlugin::ErrorDescription} describing each of the
|
141
|
+
syntax error which where found in the document. This argument is only used if
|
142
|
+
_status_ is @:error@
|
143
|
+
@return [SyntaxCheckerPlugin] *self*
|
144
|
+
=end
|
145
|
+
def mark_document_as status, errors = []
|
146
|
+
msg = case status
|
147
|
+
when :correct then 'Syntax OK'
|
148
|
+
when :unknown then 'Document type unknown'
|
149
|
+
when :error then errors.map{|e| format_error_message e}.join "\n"
|
150
|
+
end
|
151
|
+
@led.tool_tip = msg
|
152
|
+
@led.color = COLORS[status]
|
153
|
+
self
|
154
|
+
end
|
155
|
+
|
156
|
+
=begin rdoc
|
157
|
+
Registers a new syntax checker.
|
158
|
+
|
159
|
+
A syntax checker is an object which analyzes the contents of a document and tells
|
160
|
+
whether its syntax is correct or not. To register it with the plugin, you need
|
161
|
+
to pass the object's class, toghether with the mimetypes and file patterns it
|
162
|
+
should be used to check syntax for, to this method. When a new document with the
|
163
|
+
appropriate mimetype or file name is created, a new instances of the syntax checker
|
164
|
+
class will be created.
|
165
|
+
|
166
|
+
The syntax checker class must have the following characteristics:
|
167
|
+
* its constructor should take the document as only parameter
|
168
|
+
* it should have a @check@ method which takes a string (corresponding to the text
|
169
|
+
of the document) and performs the syntax check on it. It must return a string
|
170
|
+
with all the information needed to retrieve the information about the single
|
171
|
+
errors.
|
172
|
+
* it should have a @convert_check_result@ method, which takes the string
|
173
|
+
returned by the @check@ method and converts it to an array of {ErrorDescription}
|
174
|
+
objects, with each object containing the information about a single error. If
|
175
|
+
the document doesn't contain any syntax error, this method should return an
|
176
|
+
empty array.
|
177
|
+
|
178
|
+
|
179
|
+
@param [Class] cls the class to instantiate to create the syntax checker
|
180
|
+
@param [String, <String>] mimetypes the mimetypes to use the new syntax checker
|
181
|
+
for. It has the format described in {Document#file_type_match?}
|
182
|
+
@param [String, <String>] patterns the file patterns to use the new syntax checker
|
183
|
+
for. It has the format described in {Document#file_type_match?}
|
184
|
+
@return [SyntaxCheckerPlugin] *self*
|
185
|
+
@raise ArgumentError if _cls_ had already been registered as a syntax checker.
|
186
|
+
=end
|
187
|
+
def register_syntax_checker cls, mimetypes, patterns = []
|
188
|
+
if @availlable_syntax_checkers.include? cls
|
189
|
+
raise ArgumentError, "class #{cls} has already been registered as syntax checker"
|
190
|
+
else
|
191
|
+
@availlable_syntax_checkers[cls] = [mimetypes, patterns] end
|
192
|
+
end
|
193
|
+
|
194
|
+
=begin rdoc
|
195
|
+
Removes a registered syntax checker.
|
196
|
+
|
197
|
+
Nothing is done if the syntax checker hadn't been registered.
|
198
|
+
|
199
|
+
@param [Class] cls the class of the syntax checker to remove
|
200
|
+
@return [Boolean] *true* if the syntax checker was removed and *false* if it wasn't
|
201
|
+
registered
|
202
|
+
=end
|
203
|
+
def remove_syntax_checker cls
|
204
|
+
res = @availlable_syntax_checkers.delete cls
|
205
|
+
res.to_bool
|
206
|
+
end
|
207
|
+
|
208
|
+
=begin rdoc
|
209
|
+
Prepares the plugin for application shutdown
|
210
|
+
@return [SyntaxCheckerPlugin] *self*
|
211
|
+
=end
|
212
|
+
def shutdown
|
213
|
+
@timer.stop
|
214
|
+
self
|
215
|
+
end
|
216
|
+
|
217
|
+
=begin rdoc
|
218
|
+
Prepares the plugin to be unloaded
|
219
|
+
|
220
|
+
@return [SyntaxCheckerPlugin] *self*
|
221
|
+
=end
|
222
|
+
def unload
|
223
|
+
Ruber[:main_window].status_bar.remove_widget @led
|
224
|
+
super
|
225
|
+
self
|
226
|
+
end
|
227
|
+
|
228
|
+
=begin rdoc
|
229
|
+
Generates an error message from an error object
|
230
|
+
|
231
|
+
The returned string contains the error message together with information about
|
232
|
+
the line and the column (if known) where the error happened
|
233
|
+
|
234
|
+
@param [ErrorDescription] error the object containing the error message
|
235
|
+
@return [String] a string containing the error message, including line and row
|
236
|
+
where the error happened, formatted in a standard way
|
237
|
+
=end
|
238
|
+
def format_error_message error
|
239
|
+
res = "Line #{error.line}"
|
240
|
+
res += " Col #{error.column}" if error.column
|
241
|
+
res += ": #{error.message}"
|
242
|
+
res
|
243
|
+
end
|
244
|
+
|
245
|
+
=begin
|
246
|
+
Starts the timer for the automatic check
|
247
|
+
|
248
|
+
@return [SyntaxCheckerPlugin] *self*
|
249
|
+
=end
|
250
|
+
def start_timer
|
251
|
+
if @timer
|
252
|
+
@timer.stop
|
253
|
+
@timer.start
|
254
|
+
end
|
255
|
+
self
|
256
|
+
end
|
257
|
+
|
258
|
+
=begin
|
259
|
+
Stops the timer for the automatic check
|
260
|
+
|
261
|
+
@return [SyntaxCheckerPlugin] *self*
|
262
|
+
=end
|
263
|
+
def stop_timer
|
264
|
+
@timer.stop if @timer
|
265
|
+
self
|
266
|
+
end
|
267
|
+
|
268
|
+
=begin rdoc
|
269
|
+
Loads the settings
|
270
|
+
|
271
|
+
If automatic checking has been enabled, a timer is created; if it has been disabled,
|
272
|
+
the timer is destroyed
|
273
|
+
|
274
|
+
@return [nil]
|
275
|
+
=end
|
276
|
+
def load_settings
|
277
|
+
auto_check = Ruber[:config][:syntax_checker, :automatic_check]
|
278
|
+
if auto_check and !@timer
|
279
|
+
@timer = Qt::Timer.new self
|
280
|
+
@timer.interval = 1000
|
281
|
+
connect @timer, SIGNAL(:timeout), self, SIGNAL(:timeout)
|
282
|
+
@timer.start if Ruber[:main_window].current_document
|
283
|
+
elsif !auto_check
|
284
|
+
@timer.disconnect self
|
285
|
+
@timer.dispose
|
286
|
+
@timer = nil
|
287
|
+
end
|
288
|
+
nil
|
289
|
+
end
|
290
|
+
|
291
|
+
end
|
292
|
+
|
293
|
+
=begin rdoc
|
294
|
+
Document extension which checks the syntax for a document. The syntax check happens:
|
295
|
+
* when the document becomes active
|
296
|
+
* when the document is saved
|
297
|
+
* one second after the last modification (if the user has enabled automatic checks)
|
298
|
+
|
299
|
+
The check can only be done if a syntax checker for the document's mimetype
|
300
|
+
or file extension exists. New syntax checkers must be added to the syntax checker
|
301
|
+
plugin using the {SyntaxCheckerPlugin#register_syntax_checker} method,
|
302
|
+
and can be removed using {SyntaxCheckerPlugin#remove_syntax_checker}.
|
303
|
+
|
304
|
+
The appropriate syntax checker for the document is chosen when the extension is
|
305
|
+
added to the document, and is changed (if needed) whenever the @document_name@
|
306
|
+
of the document changes.
|
307
|
+
|
308
|
+
*Note:* in the documentation of this class, the term _document_ will refer
|
309
|
+
to the Document passed as argument to the constructor.
|
310
|
+
=end
|
311
|
+
class SyntaxCheckerExtension < Qt::Object
|
312
|
+
|
313
|
+
include Extension
|
314
|
+
|
315
|
+
=begin rdoc
|
316
|
+
Signal emitted after a syntax check has been completed
|
317
|
+
|
318
|
+
@param [String] result a string containing the results of the syntax check
|
319
|
+
=end
|
320
|
+
signals 'check_done(QString)'
|
321
|
+
|
322
|
+
slots 'update_ui(QString)', :check, :document_activated,
|
323
|
+
:document_deactivated, :document_name_changed, :create_syntax_checker
|
324
|
+
|
325
|
+
=begin rdoc
|
326
|
+
A list of the syntax errors found in the document
|
327
|
+
|
328
|
+
The list is empty if the document doesn't contain syntax errors or if it hasn't
|
329
|
+
been checked yet
|
330
|
+
|
331
|
+
@return [<SyntaxCheckerPlugin::ErrorDescription>] the syntax errors found in the
|
332
|
+
document
|
333
|
+
=end
|
334
|
+
attr_reader :errors
|
335
|
+
|
336
|
+
=begin rdoc
|
337
|
+
Creates a new instance
|
338
|
+
|
339
|
+
@param [DocumentProject] prj the project associated with the document
|
340
|
+
=end
|
341
|
+
def initialize prj
|
342
|
+
super
|
343
|
+
@plugin = Ruber[:syntax_checker]
|
344
|
+
@doc = prj.document
|
345
|
+
@errors = []
|
346
|
+
@checker = nil
|
347
|
+
connect @doc, SIGNAL(:activated), self, SLOT(:document_activated)
|
348
|
+
connect @doc, SIGNAL(:deactivated), self, SLOT(:document_deactivated)
|
349
|
+
@doc.connect(SIGNAL('modified_changed(bool, QObject*)')) do |mod, _|
|
350
|
+
check if !mod
|
351
|
+
end
|
352
|
+
connect @doc, SIGNAL('document_name_changed(QString, QObject*)'), self, SLOT(:create_syntax_checker)
|
353
|
+
@doc.connect SIGNAL('text_changed(QObject*)') do
|
354
|
+
if @doc.active?
|
355
|
+
@plugin.stop_timer
|
356
|
+
@plugin.start_timer
|
357
|
+
end
|
358
|
+
end
|
359
|
+
@thread = nil
|
360
|
+
create_syntax_checker
|
361
|
+
end
|
362
|
+
|
363
|
+
=begin rdoc
|
364
|
+
Sets the syntax status according to the results of the last syntax check
|
365
|
+
|
366
|
+
It marks the current document as having correct or incorrect syntax depending on
|
367
|
+
the contents of _str_.
|
368
|
+
|
369
|
+
@param [String] str the string containing the results of the syntax check (such as
|
370
|
+
the one that a syntax checker's @check@ method). It is passed to the syntax checker's
|
371
|
+
@convert_check_result@ method
|
372
|
+
@return [nil]
|
373
|
+
=end
|
374
|
+
def update_ui str
|
375
|
+
@errors = @checker.convert_check_result str
|
376
|
+
if @errors.empty? then @plugin.mark_document_as :correct
|
377
|
+
else @plugin.mark_document_as :error, @errors
|
378
|
+
end
|
379
|
+
nil
|
380
|
+
end
|
381
|
+
|
382
|
+
=begin rdoc
|
383
|
+
Starts a syntax check for the document
|
384
|
+
|
385
|
+
The syntax check can be synchronous or asynchronous, according to the value of
|
386
|
+
the argument. In the first case, this method won't return until the syntax check
|
387
|
+
has finished and the UI has been updated. In the second case, the method will
|
388
|
+
start the syntax check in a new thread and return immediately. The {#check_done}
|
389
|
+
signal will be emitted when the syntax check has been finished.
|
390
|
+
|
391
|
+
Nothing will be done if no checker exists for the document.
|
392
|
+
|
393
|
+
*Note:* while an asynchronous syntax check avoids freezing the UI if it takes
|
394
|
+
a long time, it seems that it takes much longer than a synchronous check.
|
395
|
+
|
396
|
+
@param [Boolean] async whether the syntax check should or not be asynchronous
|
397
|
+
@todo the decision on whether the check should be synchronous or asynchronous
|
398
|
+
should be delegated to the checker
|
399
|
+
@return [nil]
|
400
|
+
=end
|
401
|
+
def check async = false
|
402
|
+
return unless @checker
|
403
|
+
@plugin.stop_timer
|
404
|
+
if async
|
405
|
+
@threak.kill if @thread
|
406
|
+
@thread = Thread.new(@doc.text) do |str|
|
407
|
+
res = @checker.check @doc.text
|
408
|
+
emit check_done res
|
409
|
+
end
|
410
|
+
else
|
411
|
+
res = @checker.check @doc.text
|
412
|
+
update_ui res
|
413
|
+
end
|
414
|
+
nil
|
415
|
+
end
|
416
|
+
|
417
|
+
private
|
418
|
+
|
419
|
+
=begin rdoc
|
420
|
+
Creates a syntax checker for the document
|
421
|
+
|
422
|
+
If needed, it also removes the old one and immediately performs a syntax check
|
423
|
+
|
424
|
+
@return [nil]
|
425
|
+
=end
|
426
|
+
def create_syntax_checker
|
427
|
+
new_checker = Ruber[:syntax_checker].syntax_checker_for @doc
|
428
|
+
if @checker.class != new_checker.class
|
429
|
+
@checker.disconnect if @checker
|
430
|
+
@checker = nil
|
431
|
+
if new_checker
|
432
|
+
@checker = new_checker
|
433
|
+
connect self, SIGNAL('check_done(QString)'), self, SLOT('update_ui(QString)')
|
434
|
+
end
|
435
|
+
check if @doc.active?
|
436
|
+
end
|
437
|
+
nil
|
438
|
+
end
|
439
|
+
|
440
|
+
=begin rdoc
|
441
|
+
Informs the extension that the document is not active anymore
|
442
|
+
|
443
|
+
@return [nil]
|
444
|
+
=end
|
445
|
+
def document_deactivated
|
446
|
+
@thread.kill if @thread
|
447
|
+
@plugin.stop_timer
|
448
|
+
@plugin.disconnect SIGNAL(:timeout), self, SLOT(:check)
|
449
|
+
Ruber[:syntax_checker].mark_document_as :unknown
|
450
|
+
nil
|
451
|
+
end
|
452
|
+
|
453
|
+
=begin rdoc
|
454
|
+
Informs the extension that the document became active
|
455
|
+
|
456
|
+
@return [nil]
|
457
|
+
=end
|
458
|
+
def document_activated
|
459
|
+
connect @plugin, SIGNAL(:timeout), self, SLOT(:check)
|
460
|
+
check
|
461
|
+
nil
|
462
|
+
end
|
463
|
+
|
464
|
+
end
|
465
|
+
|
466
|
+
=begin rdoc
|
467
|
+
Class which checks the syntax of a ruby file.
|
468
|
+
|
469
|
+
To do so, it runs a separate ruby process (using the ruby interpreter set by the
|
470
|
+
Ruby Runner plugin) passing it the @-c@ and the @-e@ options with the document's
|
471
|
+
content as argument.
|
472
|
+
|
473
|
+
The process is executed using @Open3.popen3@
|
474
|
+
=end
|
475
|
+
class RubySyntaxChecker
|
476
|
+
|
477
|
+
=begin rdoc
|
478
|
+
Creates a new instance.
|
479
|
+
|
480
|
+
@param [Document] doc the document to check
|
481
|
+
=end
|
482
|
+
def initialize doc
|
483
|
+
@doc = doc
|
484
|
+
end
|
485
|
+
|
486
|
+
=begin rdoc
|
487
|
+
Checks the syntax of the given string.
|
488
|
+
|
489
|
+
@param [String] str the string to check (usually, it'll be the document's text)
|
490
|
+
@return [String] a string containing the lines of output produced by ruby concerning
|
491
|
+
syntax errors or an empty string if there were no syntax error
|
492
|
+
=end
|
493
|
+
def check str
|
494
|
+
ruby = Ruber[:ruby_development].interpreter_for @doc
|
495
|
+
Open3.popen3(ruby, '-c', '-e', str) do |in_s, out_s, err_s|
|
496
|
+
error = err_s.read
|
497
|
+
error.gsub! %r{^-e(?=:\d+:\s+syntax error,)}, @doc.path
|
498
|
+
out_s.read.strip != 'Syntax OK' ? error : ''
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
=begin rdoc
|
503
|
+
Parses the output of {#check}
|
504
|
+
|
505
|
+
@param [String] str the string to parse.
|
506
|
+
@return [<SyntaxCheckerPlugin::ErrorDescription>] a list of {SyntaxCheckerPlugin::ErrorDescription ErrorDescription}s
|
507
|
+
corresponding to the syntax errors mentioned in _str_
|
508
|
+
=end
|
509
|
+
def convert_check_result str
|
510
|
+
groups = [[]]
|
511
|
+
lines = str.split "\n"
|
512
|
+
lines.each do |l|
|
513
|
+
if l.match(/^#{Regexp.quote(@doc.path||'')}:\d+:\s+syntax error,\s+/) then groups << [l]
|
514
|
+
else groups[-1] << l
|
515
|
+
end
|
516
|
+
end
|
517
|
+
groups.delete_if{|g| g.empty?}
|
518
|
+
groups.map do |a|
|
519
|
+
a.shift.match(/^#{Regexp.quote(@doc.path||'')}:(\d+):\s+syntax error,\s+(.*)/)
|
520
|
+
msgs = [$2]
|
521
|
+
error = SyntaxCheckerPlugin::ErrorDescription.new $1.to_i
|
522
|
+
if a[-1] and a[-1].match(/^\s*\^\s*$/)
|
523
|
+
error.code = a[-2]
|
524
|
+
# Sometimes, ruby doesn't report the whole line where the error occurs, but only
|
525
|
+
# the part nearest it. In this case, the beginning of the line is replaced with ... .
|
526
|
+
# In this case, to obtain the correct column number, we try a regexp match
|
527
|
+
# between the part of code reported by ruby and the whole line. If it works, we
|
528
|
+
# add that position to the one returned by ruby. If it doesn't (for example because
|
529
|
+
# the user changed the document in the meantime), we'll just report what ruby reports
|
530
|
+
col = a[-1].index('^')
|
531
|
+
if a[-2].match(/^\.\.\./)
|
532
|
+
lines = @doc.text.split("\n")
|
533
|
+
# error.line is 1-based
|
534
|
+
l = lines[error.line-1] || ''
|
535
|
+
pos = (l =~ /#{Regexp.quote(a[-2][3..-1])}/)
|
536
|
+
error.column = pos ? col + pos - 1 : col
|
537
|
+
else error.column = col
|
538
|
+
end
|
539
|
+
a.pop 2
|
540
|
+
end
|
541
|
+
a.each{|l| msgs << l}
|
542
|
+
error.message = msgs.join ' '
|
543
|
+
error
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
end
|
548
|
+
|
549
|
+
=begin rdoc
|
550
|
+
Class which checks the syntax of a ruby file.
|
551
|
+
|
552
|
+
It calls the @YAML.load@ method on the document's content within a begin/rescue
|
553
|
+
block, rescuing any ArgumentError exception. The message of the exception is used
|
554
|
+
to find information about the error
|
555
|
+
=end
|
556
|
+
class YamlSyntaxChecker
|
557
|
+
|
558
|
+
=begin rdoc
|
559
|
+
Creates a new instance
|
560
|
+
|
561
|
+
@param [Document] doc the document to check
|
562
|
+
=end
|
563
|
+
def initialize doc
|
564
|
+
end
|
565
|
+
|
566
|
+
=begin rdoc
|
567
|
+
Checks the syntax of the given string.
|
568
|
+
|
569
|
+
@param [String] str the string to check (usually, it'll be the document's text)
|
570
|
+
@return [String] a string containing the lines of output produced by @YAML.load@
|
571
|
+
concerning syntax errors or an empty string if there were no syntax error
|
572
|
+
=end
|
573
|
+
def check str
|
574
|
+
begin
|
575
|
+
YAML.load str
|
576
|
+
''
|
577
|
+
rescue ArgumentError => e
|
578
|
+
e.message
|
579
|
+
end
|
580
|
+
end
|
581
|
+
|
582
|
+
=begin rdoc
|
583
|
+
Parses the output of {#check}
|
584
|
+
|
585
|
+
@param [String] str the string to parse.
|
586
|
+
@return [<SyntaxCheckerPlugin::ErrorDescription>] a list of {SyntaxCheckerPlugin::ErrorDescription ErrorDescription}s
|
587
|
+
corresponding to the syntax errors mentioned in _str_
|
588
|
+
=end
|
589
|
+
def convert_check_result str
|
590
|
+
return [] if str.empty?
|
591
|
+
str.match(/^syntax error on line (\d+), col (\d+): `(.*)'$/)
|
592
|
+
error = SyntaxCheckerPlugin::ErrorDescription.new $1.to_i, 'Syntax error', $3.to_s, $2.to_i
|
593
|
+
[error]
|
594
|
+
end
|
595
|
+
|
596
|
+
end
|
597
|
+
|
598
|
+
=begin rdoc
|
599
|
+
@KDE::Led@ with the ability to jump to the first syntax error on left or middle mouse
|
600
|
+
click and to popup a menu with a list of all syntax errors in the current document
|
601
|
+
on right click
|
602
|
+
=end
|
603
|
+
class SyntaxResultWidget < KDE::Led
|
604
|
+
|
605
|
+
=begin rdoc
|
606
|
+
Override of @Qt::Widget#mouseReleaseEvent@
|
607
|
+
|
608
|
+
If the event refers to the left button and the current document contains syntax
|
609
|
+
errors, it moves the cursor in the editor view to the position of the first error
|
610
|
+
|
611
|
+
@return [nil]
|
612
|
+
=end
|
613
|
+
def mouseReleaseEvent e
|
614
|
+
return unless e.button == Qt::LeftButton or e.button == Qt::MidButton
|
615
|
+
doc = Ruber[:main_window].current_document
|
616
|
+
view = Ruber[:main_window].active_editor
|
617
|
+
return unless view and doc and doc.extension(:syntax_checker)
|
618
|
+
checker = doc.extension(:syntax_checker)
|
619
|
+
err = checker.errors.first
|
620
|
+
if err
|
621
|
+
view.go_to err.line - 1, (err.column || 0)
|
622
|
+
Ruber[:main_window].status_bar.show_message Ruber[:syntax_checker].format_error_message(err), 4000
|
623
|
+
end
|
624
|
+
nil
|
625
|
+
end
|
626
|
+
|
627
|
+
=begin rdoc
|
628
|
+
Override of @Qt::Widget#contextMenuEvent@
|
629
|
+
|
630
|
+
If the current document contains syntax errors, it displays a menu listing them.
|
631
|
+
Each action in the menu moves the cursor in the editor view to display to the line
|
632
|
+
and column of the corresponding error.
|
633
|
+
|
634
|
+
If the current document doesn't contain syntax errors, the menu will only contain
|
635
|
+
an entry with text @Syntax OK@ which does nothing when activated.
|
636
|
+
|
637
|
+
@return [nil]
|
638
|
+
=end
|
639
|
+
def contextMenuEvent event
|
640
|
+
doc = Ruber[:main_window].current_document
|
641
|
+
view = Ruber[:main_window].active_editor
|
642
|
+
return unless doc and view and (checker = doc.extension :syntax_checker)
|
643
|
+
errors = checker.errors
|
644
|
+
actions = errors.map do |e|
|
645
|
+
a = KDE::Action.new Ruber[:syntax_checker].format_error_message(e), self
|
646
|
+
end
|
647
|
+
actions << KDE::Action.new('Syntax OK', self) if actions.empty?
|
648
|
+
res = Qt::Menu.exec(actions, event.global_pos)
|
649
|
+
return if !res or errors.empty?
|
650
|
+
idx = actions.index res
|
651
|
+
return unless idx
|
652
|
+
error = errors[idx]
|
653
|
+
view.go_to error.line - 1, (error.column || 0)
|
654
|
+
Ruber[:main_window].status_bar.show_message res.text, 4000
|
655
|
+
nil
|
656
|
+
end
|
657
|
+
|
658
|
+
end
|
659
|
+
|
660
|
+
end
|
661
|
+
|
662
|
+
end
|