1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
3 Copyright (C) 2009 Maxim Ermilov <zaspire@rambler.ru>
5 This program is free software; you can redistribute it and/or 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.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <libanjuta/anjuta-shell.h>
22 #include <libanjuta/anjuta-session.h>
23 #include <libanjuta/anjuta-debug.h>
24 #include <libanjuta/anjuta-language-provider.h>
25 #include <libanjuta/interfaces/ianjuta-document-manager.h>
26 #include <libanjuta/interfaces/ianjuta-project-manager.h>
27 #include <libanjuta/interfaces/ianjuta-editor-assist.h>
28 #include <libanjuta/interfaces/ianjuta-editor-tip.h>
29 #include <libanjuta/interfaces/ianjuta-language.h>
30 #include <libanjuta/interfaces/ianjuta-language-provider.h>
31 #include <libanjuta/interfaces/ianjuta-preferences.h>
38 #include "code-completion.h"
40 #include "gi-symbol.h"
42 #define PREFS_BUILDER ANJUTA_GLADE_DIR"/anjuta-language-javascript.ui"
43 #define ICON_FILE "anjuta-language-cpp-java-plugin.png"
44 #define UI_FILE ANJUTA_UI_DIR"/anjuta-language-javascript.xml"
46 #define JSDIRS_LISTSTORE "jsdirs_liststore"
47 #define JSDIRS_TREEVIEW "jsdirs_treeview"
49 static gpointer parent_class
;
52 on_value_added_current_editor (AnjutaPlugin
*plugin
, const gchar
*name
,
53 const GValue
*value
, gpointer data
);
55 on_value_removed_current_editor (AnjutaPlugin
*plugin
, const gchar
*name
,
58 /*Export for GtkBuilder*/
60 on_jsdirs_rm_button_clicked (GtkButton
*button
, gpointer user_data
);
62 on_jsdirs_add_button_clicked (GtkButton
*button
, gpointer user_data
);
65 js_support_plugin_activate (AnjutaPlugin
*plugin
)
67 JSLang
*js_support_plugin
;
69 DEBUG_PRINT ("%s", "JSLang: Activating JSLang plugin ...");
70 js_support_plugin
= (JSLang
*) plugin
;
71 js_support_plugin
->prefs
= g_settings_new (JS_SUPPORT_SCHEMA
);
72 js_support_plugin
->editor_watch_id
=
73 anjuta_plugin_add_watch (plugin
, IANJUTA_DOCUMENT_MANAGER_CURRENT_DOCUMENT
,
74 on_value_added_current_editor
,
75 on_value_removed_current_editor
,
81 js_support_plugin_deactivate (AnjutaPlugin
*plugin
)
83 JSLang
*js_support_plugin
;
85 DEBUG_PRINT ("%s", "JSLang: Dectivating JSLang plugin ...");
86 js_support_plugin
= (JSLang
*) plugin
;
87 anjuta_plugin_remove_watch (plugin
, js_support_plugin
->editor_watch_id
, TRUE
);
92 js_support_plugin_finalize (GObject
*obj
)
94 JSLang
*self
= (JSLang
*)obj
;
96 g_object_unref (self
->symbol
);
99 G_OBJECT_CLASS (parent_class
)->finalize (obj
);
103 js_support_plugin_dispose (GObject
*obj
)
105 JSLang
*self
= (JSLang
*)obj
;
107 g_assert (self
!= NULL
);
109 g_object_unref (self
->symbol
);
112 G_OBJECT_CLASS (parent_class
)->dispose (obj
);
116 js_support_plugin_instance_init (GObject
*obj
)
118 JSLang
*plugin
= (JSLang
*)obj
;
119 plugin
->prefs
= NULL
;
120 plugin
->symbol
= NULL
;
124 js_support_plugin_class_init (GObjectClass
*klass
)
126 AnjutaPluginClass
*plugin_class
= ANJUTA_PLUGIN_CLASS (klass
);
128 parent_class
= g_type_class_peek_parent (klass
);
130 plugin_class
->activate
= js_support_plugin_activate
;
131 plugin_class
->deactivate
= js_support_plugin_deactivate
;
132 klass
->finalize
= js_support_plugin_finalize
;
133 klass
->dispose
= js_support_plugin_dispose
;
137 install_support (JSLang
*plugin
)
140 IAnjutaLanguage
* lang_manager
;
144 if (!IANJUTA_IS_EDITOR (plugin
->current_editor
))
146 lang_manager
= anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin
)->shell
,
147 IAnjutaLanguage
, NULL
);
150 lang
= ianjuta_language_get_name_from_editor (lang_manager
,
151 IANJUTA_EDITOR_LANGUAGE (plugin
->current_editor
), NULL
);
152 if (!lang
|| !g_str_equal (lang
, "JavaScript"))
155 plugin
->lang_prov
= g_object_new (ANJUTA_TYPE_LANGUAGE_PROVIDER
, NULL
);
156 anjuta_language_provider_install (plugin
->lang_prov
,
157 IANJUTA_EDITOR (plugin
->current_editor
),
160 DEBUG_PRINT ("%s", "JSLang: Install support");
162 ianjuta_editor_assist_add (IANJUTA_EDITOR_ASSIST(plugin
->current_editor
),
163 IANJUTA_PROVIDER(plugin
), NULL
);
167 uninstall_support (JSLang
*plugin
)
169 if (plugin
->lang_prov
)
171 g_object_unref (plugin
->lang_prov
);
172 plugin
->lang_prov
= NULL
;
175 DEBUG_PRINT ("%s", "JSLang: Uninstall support");
177 ianjuta_editor_assist_remove (IANJUTA_EDITOR_ASSIST(plugin
->current_editor
),
178 IANJUTA_PROVIDER(plugin
), NULL
);
183 on_value_added_current_editor (AnjutaPlugin
*plugin
, const gchar
*name
,
184 const GValue
*value
, gpointer data
)
186 JSLang
*js_support_plugin
;
187 IAnjutaDocument
* doc
= IANJUTA_DOCUMENT(g_value_get_object (value
));
189 DEBUG_PRINT ("%s", "JSLang: Add editor");
191 js_support_plugin
= (JSLang
*) plugin
;
192 if (IANJUTA_IS_EDITOR(doc
))
193 js_support_plugin
->current_editor
= G_OBJECT(doc
);
196 js_support_plugin
->current_editor
= NULL
;
199 install_support (js_support_plugin
);
203 on_value_removed_current_editor (AnjutaPlugin
*plugin
, const gchar
*name
,
206 JSLang
*js_support_plugin
;
208 DEBUG_PRINT ("%s", "JSLang: Remove editor");
210 js_support_plugin
= (JSLang
*) plugin
;
211 if (IANJUTA_IS_EDITOR(js_support_plugin
->current_editor
))
212 uninstall_support (js_support_plugin
);
213 js_support_plugin
->current_editor
= NULL
;
217 jsdirs_save (GtkTreeModel
*list_store
)
220 const gchar
*project_root
= NULL
;
221 anjuta_shell_get (ANJUTA_PLUGIN (getPlugin ())->shell
,
222 IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI
,
223 G_TYPE_STRING
, &project_root
, NULL
);
225 GFile
*tmp
= g_file_new_for_uri (project_root
);
226 AnjutaSession
*session
= anjuta_session_new (g_file_get_path (tmp
));
227 g_object_unref (tmp
);
230 if (!gtk_tree_model_iter_children (list_store
, &iter
, NULL
))
235 gtk_tree_model_get (list_store
, &iter
, 0, &dir
, -1);
237 g_assert (dir
!= NULL
);
239 dirs
= g_list_append (dirs
, dir
);
240 } while (gtk_tree_model_iter_next (list_store
, &iter
));
241 anjuta_session_set_string_list (session
, "options", "js_dirs", dirs
);
242 anjuta_session_sync (session
);
246 on_jsdirs_rm_button_clicked (GtkButton
*button
, gpointer user_data
)
249 GtkTreeView
*tree
= GTK_TREE_VIEW (user_data
);
250 GtkTreeModel
*list_store
= gtk_tree_view_get_model (tree
);
251 GtkTreeSelection
*selection
= gtk_tree_view_get_selection (tree
);
253 if (!gtk_tree_selection_get_selected (selection
, &list_store
, &iter
))
255 gtk_list_store_remove (GTK_LIST_STORE (list_store
), &iter
);
256 jsdirs_save (list_store
);
260 on_jsdirs_add_button_clicked (GtkButton
*button
, gpointer user_data
)
264 g_assert (user_data
!= NULL
);
266 GtkTreeView
*tree
= GTK_TREE_VIEW (user_data
);
267 GtkListStore
*list_store
= GTK_LIST_STORE (gtk_tree_view_get_model (tree
));
269 g_assert (list_store
!= NULL
);
271 dialog
= gtk_file_chooser_dialog_new ("Choose directory",
273 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
,
274 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
275 GTK_STOCK_OPEN
, GTK_RESPONSE_ACCEPT
,
277 if (gtk_dialog_run (GTK_DIALOG (dialog
)) == GTK_RESPONSE_ACCEPT
)
280 filename
= gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog
));
284 gtk_list_store_append (list_store
, &iter
);
285 gtk_list_store_set (list_store
, &iter
, 0, filename
, -1);
288 jsdirs_save (GTK_TREE_MODEL (list_store
));
290 gtk_widget_destroy (dialog
);
294 jsdirs_init_treeview (JSLang
* plugin
)
296 const gchar
*project_root
= NULL
;
298 GtkListStore
*list_store
= GTK_LIST_STORE (gtk_builder_get_object (
299 plugin
->bxml
, JSDIRS_LISTSTORE
));
303 anjuta_shell_get (ANJUTA_PLUGIN (plugin
)->shell
,
304 IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI
,
305 G_TYPE_STRING
, &project_root
, NULL
);
307 GFile
*tmp
= g_file_new_for_uri (project_root
);
308 AnjutaSession
*session
= anjuta_session_new (g_file_get_path (tmp
));
309 g_object_unref (tmp
);
310 GList
* dir_list
= anjuta_session_get_string_list (session
, "options", "js_dirs");
312 gtk_list_store_clear (list_store
);
314 for (i
= dir_list
; i
; i
= g_list_next (i
))
316 gtk_list_store_append (list_store
, &iter
);
317 gtk_list_store_set (list_store
, &iter
, 0, i
->data
, -1);
321 gtk_list_store_append (list_store
, &iter
);
322 gtk_list_store_set (list_store
, &iter
, 0, ".", -1);
326 #define PREF_WIDGET_SPACE "preferences:completion-space-after-func"
327 #define PREF_WIDGET_BRACE "preferences:completion-brace-after-func"
328 #define PREF_WIDGET_CLOSEBRACE "preferences:completion-closebrace-after-func"
329 #define PREF_WIDGET_AUTO "preferences:completion-enable"
332 on_autocompletion_toggled (GtkToggleButton
* button
,
336 gboolean sensitive
= gtk_toggle_button_get_active (button
);
338 widget
= GTK_WIDGET (gtk_builder_get_object (plugin
->bxml
, PREF_WIDGET_SPACE
));
339 gtk_widget_set_sensitive (widget
, sensitive
);
340 widget
= GTK_WIDGET (gtk_builder_get_object (plugin
->bxml
, PREF_WIDGET_BRACE
));
341 gtk_widget_set_sensitive (widget
, sensitive
);
342 widget
= GTK_WIDGET (gtk_builder_get_object (plugin
->bxml
, PREF_WIDGET_CLOSEBRACE
));
343 gtk_widget_set_sensitive (widget
, sensitive
);
347 ipreferences_merge (IAnjutaPreferences
* ipref
, AnjutaPreferences
* prefs
,
350 /* Add preferences */
351 GError
* error
= NULL
;
352 JSLang
* plugin
= (JSLang
*) ipref
;
353 plugin
->bxml
= gtk_builder_new ();
356 if (!gtk_builder_add_from_file (plugin
->bxml
, PREFS_BUILDER
, &error
))
358 g_warning ("Couldn't load builder file: %s", error
->message
);
359 g_error_free (error
);
362 GtkTreeView
*tree
= GTK_TREE_VIEW (gtk_builder_get_object (plugin
->bxml
, JSDIRS_TREEVIEW
));
364 gtk_builder_connect_signals (plugin
->bxml
, tree
);
365 jsdirs_init_treeview (plugin
);
367 anjuta_preferences_add_from_builder (prefs
,
370 "preferences", _("JavaScript"),
372 toggle
= GTK_WIDGET (gtk_builder_get_object (plugin
->bxml
, PREF_WIDGET_AUTO
));
373 g_signal_connect (toggle
, "toggled", G_CALLBACK (on_autocompletion_toggled
),
375 on_autocompletion_toggled (GTK_TOGGLE_BUTTON (toggle
), plugin
);
379 ipreferences_unmerge (IAnjutaPreferences
* ipref
, AnjutaPreferences
* prefs
,
382 JSLang
* plugin
= (JSLang
*) ipref
;
383 anjuta_preferences_remove_page(prefs
, _("JavaScript"));
384 g_object_unref (plugin
->bxml
);
388 ipreferences_iface_init (IAnjutaPreferencesIface
* iface
)
390 iface
->merge
= ipreferences_merge
;
391 iface
->unmerge
= ipreferences_unmerge
;
395 iprovider_activate (IAnjutaProvider
* self
,
396 IAnjutaIterable
* iter
,
400 JSLang
*plugin
= (JSLang
*) self
;
401 anjuta_language_provider_activate (plugin
->lang_prov
, self
, iter
, data
);
405 iprovider_populate (IAnjutaProvider
* self
,
406 IAnjutaIterable
* cursor
,
409 JSLang
*plugin
= (JSLang
*) self
;
410 anjuta_language_provider_populate (plugin
->lang_prov
, self
, cursor
);
414 iprovider_get_name (IAnjutaProvider
* self
,
417 return _("JavaScript");
420 static IAnjutaIterable
*
421 iprovider_get_start_iter (IAnjutaProvider
* self
,
424 JSLang
*plugin
= (JSLang
*) self
;
425 return anjuta_language_provider_get_start_iter (plugin
->lang_prov
);
429 iprovider_iface_init (IAnjutaProviderIface
* iface
)
431 iface
->activate
= iprovider_activate
;
432 iface
->populate
= iprovider_populate
;
433 iface
->get_name
= iprovider_get_name
;
434 iface
->get_start_iter
= iprovider_get_start_iter
;
438 ilanguage_provider_get_calltip_cache (IAnjutaLanguageProvider
*obj
,
442 /* TODO: Not implemented yet */
447 ilanguage_provider_get_calltip_context (IAnjutaLanguageProvider
*obj
,
448 IAnjutaIterable
*iter
,
451 /* TODO: Not implemented yet
453 gchar *args = code_completion_get_func_tooltip (plugin, sym);
454 t = g_list_append (t, args);
457 ianjuta_editor_tip_show (IANJUTA_EDITOR_TIP(plugin->current_editor), t,
466 ilanguage_provider_new_calltip (IAnjutaLanguageProvider
* obj
,
468 IAnjutaIterable
* cursor
,
471 /* TODO: Not implemented yet */
475 static IAnjutaIterable
*
476 ilanguage_provider_populate (IAnjutaLanguageProvider
* obj
,
477 IAnjutaIterable
* iter
,
480 JSLang
*plugin
= (JSLang
*)obj
;
481 IAnjutaIterable
* start_iter
;
484 start_iter
= ianjuta_iterable_clone (iter
, NULL
);
486 if (!plugin
->current_editor
)
489 gchar
*str
= code_completion_get_str (IANJUTA_EDITOR (plugin
->current_editor
), FALSE
);
494 g_assert (plugin
->prefs
);
495 gchar
*file
= file_completion (IANJUTA_EDITOR (plugin
->current_editor
), &depth
);
497 if (strlen (str
) < g_settings_get_int (plugin
->prefs
, MIN_CODECOMPLETE
))
499 ianjuta_editor_assist_proposals (IANJUTA_EDITOR_ASSIST (plugin
->current_editor
),
500 IANJUTA_PROVIDER(obj
), NULL
, NULL
, TRUE
, NULL
);
501 /* Highlight missed semicolon */
502 code_completion_get_list (plugin
, file
, NULL
, depth
);
507 DEBUG_PRINT ("JSLang: Auto complete for %s (TMFILE=%s)", str
, file
);
508 for (i
= strlen (str
) - 1; i
; i
--)
513 /* TODO: Use anjuta_language_provider_get_pre_word in the future */
515 suggestions
= code_completion_get_list (plugin
, file
, g_strndup (str
, i
), depth
);
517 suggestions
= code_completion_get_list (plugin
, file
, NULL
, depth
);
520 GList
*nsuggest
= NULL
;
524 suggestions
= filter_list (suggestions
, str
+ i
+ 1);
525 k
= strlen (str
+ i
+ 1);
528 suggestions
= filter_list (suggestions
, str
);
533 ianjuta_iterable_previous (start_iter
, NULL
);
535 for (i
= suggestions
; i
; i
= g_list_next(i
)) {
536 IAnjutaEditorAssistProposal
* proposal
;
537 AnjutaLanguageProposalData
* prop_data
;
539 proposal
= g_new0(IAnjutaEditorAssistProposal
, 1);
544 proposal
->label
= i
->data
;
545 prop_data
= anjuta_language_proposal_data_new (i
->data
);
546 prop_data
->is_func
= code_completion_is_symbol_func (plugin
, str
);
547 /* TODO: Not implemented yet */
548 prop_data
->has_para
= TRUE
;
549 prop_data
->info
= i
->data
;
550 proposal
->data
= prop_data
;
551 nsuggest
= g_list_prepend (nsuggest
, proposal
);
553 ianjuta_editor_assist_proposals (IANJUTA_EDITOR_ASSIST (plugin
->current_editor
),
554 IANJUTA_PROVIDER(obj
), nsuggest
, NULL
, TRUE
, NULL
);
555 g_list_free (nsuggest
);
558 ianjuta_editor_assist_proposals (IANJUTA_EDITOR_ASSIST (plugin
->current_editor
),
559 IANJUTA_PROVIDER(obj
), NULL
, NULL
, TRUE
, NULL
);
565 ilanguage_provider_iface_init (IAnjutaLanguageProviderIface
* iface
)
567 iface
->get_calltip_cache
= ilanguage_provider_get_calltip_cache
;
568 iface
->get_calltip_context
= ilanguage_provider_get_calltip_context
;
569 iface
->new_calltip
= ilanguage_provider_new_calltip
;
570 iface
->populate_completions
= ilanguage_provider_populate
;
573 ANJUTA_PLUGIN_BEGIN (JSLang
, js_support_plugin
);
574 ANJUTA_PLUGIN_ADD_INTERFACE(ipreferences
, IANJUTA_TYPE_PREFERENCES
);
575 ANJUTA_PLUGIN_ADD_INTERFACE(iprovider
, IANJUTA_TYPE_PROVIDER
);
576 ANJUTA_PLUGIN_ADD_INTERFACE(ilanguage_provider
, IANJUTA_TYPE_LANGUAGE_PROVIDER
)
579 ANJUTA_SIMPLE_PLUGIN (JSLang
, js_support_plugin
);