Fix a Gtk warning when checking path input in the log viewer.
[anjuta-git-plugin.git] / plugins / language-support-cpp-java / cpp-java-assist.c
blobd70d9a16fe6ef240e8d35710f9c98f7951f44f34
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * cpp-java-assist.c
4 * Copyright (C) 2007 Naba Kumar <naba@gnome.org>
5 * Johannes Schmid <jhs@gnome.org>
6 *
7 * anjuta is free software.
8 *
9 * You may redistribute it and/or modify it under the terms of the
10 * GNU General Public License, as published by the Free Software
11 * Foundation; either version 2 of the License, or (at your option)
12 * any later version.
14 * anjuta is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 * See the GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with anjuta. If not, write to:
21 * The Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor
23 * Boston, MA 02110-1301, USA.
26 #include <ctype.h>
27 #include <string.h>
28 #include <libanjuta/anjuta-debug.h>
29 #include <libanjuta/interfaces/ianjuta-editor-cell.h>
30 #include <libanjuta/interfaces/ianjuta-editor-selection.h>
31 #include <libanjuta/interfaces/ianjuta-document.h>
32 #include <libanjuta/interfaces/ianjuta-symbol-manager.h>
33 #include "cpp-java-assist.h"
34 #include "cpp-java-utils.h"
36 #define PREF_AUTOCOMPLETE_ENABLE "language.cpp.code.completion.enable"
37 #define PREF_AUTOCOMPLETE_CHOICES "language.cpp.code.completion.choices"
38 #define PREF_AUTOCOMPLETE_SPACE_AFTER_FUNC "language.cpp.code.completion.space.after.func"
39 #define PREF_AUTOCOMPLETE_BRACE_AFTER_FUNC "language.cpp.code.completion.brace.after.func"
40 #define PREF_CALLTIP_ENABLE "language.cpp.code.calltip.enable"
41 #define MAX_COMPLETIONS 10
42 #define BRACE_SEARCH_LIMIT 500
44 G_DEFINE_TYPE (CppJavaAssist, cpp_java_assist, G_TYPE_OBJECT);
46 typedef struct
48 gchar *name;
49 gboolean is_func;
50 IAnjutaSymbolType type;
51 } CppJavaAssistTag;
53 struct _CppJavaAssistPriv {
54 AnjutaPreferences *preferences;
55 IAnjutaSymbolManager* isymbol_manager;
56 IAnjutaEditorAssist* iassist;
58 /* Last used cache */
59 gchar *search_cache;
60 gchar *scope_context_cache;
61 GCompletion *completion_cache;
62 gboolean editor_only;
65 static gchar*
66 completion_function (gpointer data)
68 CppJavaAssistTag * tag = (CppJavaAssistTag*) data;
69 return tag->name;
72 static gint
73 completion_compare (gconstpointer a, gconstpointer b)
75 CppJavaAssistTag * tag_a = (CppJavaAssistTag*) a;
76 CppJavaAssistTag * tag_b = (CppJavaAssistTag*) b;
77 return (strcmp (tag_a->name, tag_b->name) &&
78 tag_a->type == tag_b->type);
81 static void
82 cpp_java_assist_tag_destroy (CppJavaAssistTag *tag)
84 g_free (tag->name);
85 g_free (tag);
88 static gint
89 get_iter_column (CppJavaAssist *assist, IAnjutaIterable *iter)
91 gchar ch;
92 gint offset = 0;
93 gint tabsize =
94 ianjuta_editor_get_tabsize (IANJUTA_EDITOR (assist->priv->iassist),
95 NULL);
96 ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter),
97 0, NULL);
99 while (ch != '\n')
101 if (!ianjuta_iterable_previous (iter, NULL))
102 break;
103 if (ch == '\t')
104 offset += tabsize - 1;
105 offset++;
106 ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter),
107 0, NULL);
109 //DEBUG_PRINT ("Iter column: %d", offset);
110 return offset;
113 static gboolean
114 is_scope_context_character (gchar ch)
116 if (g_ascii_isspace (ch))
117 return FALSE;
118 if (g_ascii_isalnum (ch))
119 return TRUE;
120 if (ch == '_' || ch == '.' || ch == ':' || ch == '>' || ch == '-')
121 return TRUE;
123 return FALSE;
126 static gboolean
127 is_word_character (gchar ch)
129 if (g_ascii_isspace (ch))
130 return FALSE;
131 if (g_ascii_isalnum (ch))
132 return TRUE;
133 if (ch == '_')
134 return TRUE;
136 return FALSE;
140 * If mergeable is NULL than no merge will be made with iter elements, elsewhere
141 * mergeable will be returned with iter elements.
143 static GCompletion*
144 create_completion (IAnjutaEditorAssist* iassist, IAnjutaIterable* iter,
145 GCompletion* mergeable)
147 GCompletion *completion;
149 if (mergeable == NULL)
150 completion = g_completion_new (completion_function);
151 else
152 completion = mergeable;
154 GList* suggestions = NULL;
157 const gchar* name = ianjuta_symbol_get_name (IANJUTA_SYMBOL(iter), NULL);
158 if (name != NULL)
160 CppJavaAssistTag *tag = g_new0 (CppJavaAssistTag, 1);
161 tag->name = g_strdup (name);
162 tag->type = ianjuta_symbol_get_sym_type (IANJUTA_SYMBOL (iter),
163 NULL);
164 tag->is_func = (tag->type == IANJUTA_SYMBOL_TYPE_FUNCTION ||
165 tag->type == IANJUTA_SYMBOL_TYPE_METHOD ||
166 tag->type == IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG);
167 if (!g_list_find_custom (suggestions, tag, completion_compare))
168 suggestions = g_list_prepend (suggestions, tag);
169 else
170 g_free (tag);
172 else
173 break;
175 while (ianjuta_iterable_next (iter, NULL));
179 suggestions = g_list_sort (suggestions, completion_compare);
180 g_completion_add_items (completion, suggestions);
181 return completion;
184 static gchar*
185 cpp_java_assist_get_scope_context (IAnjutaEditor* editor,
186 const gchar *scope_operator,
187 IAnjutaIterable *iter)
189 IAnjutaIterable* end;
190 gchar ch, *scope_chars = NULL;
191 gboolean out_of_range = FALSE;
192 gboolean scope_chars_found = FALSE;
194 end = ianjuta_iterable_clone (iter, NULL);
195 ianjuta_iterable_next (end, NULL);
197 ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
199 while (ch && is_scope_context_character (ch))
201 scope_chars_found = TRUE;
202 if (!ianjuta_iterable_previous (iter, NULL))
204 out_of_range = TRUE;
205 break;
207 ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
209 if (scope_chars_found)
211 IAnjutaIterable* begin;
212 begin = ianjuta_iterable_clone (iter, NULL);
213 if (!out_of_range)
214 ianjuta_iterable_next (begin, NULL);
215 scope_chars = ianjuta_editor_get_text (editor, begin, end, NULL);
216 g_object_unref (begin);
218 g_object_unref (end);
219 return scope_chars;
222 static gchar*
223 cpp_java_assist_get_pre_word (IAnjutaEditor* editor, IAnjutaIterable *iter)
225 IAnjutaIterable *end;
226 gchar ch, *preword_chars = NULL;
227 gboolean out_of_range = FALSE;
228 gboolean preword_found = TRUE;
230 end = ianjuta_iterable_clone (iter, NULL);
231 ianjuta_iterable_next (end, NULL);
233 ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
235 while (ch && is_word_character (ch))
237 preword_found = TRUE;
238 if (!ianjuta_iterable_previous (iter, NULL))
240 out_of_range = TRUE;
241 break;
243 ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
246 if (preword_found)
248 IAnjutaIterable *begin = ianjuta_iterable_clone (iter, NULL);
249 if (!out_of_range)
250 ianjuta_iterable_next (begin, NULL);
251 preword_chars = ianjuta_editor_get_text (editor, begin, end, NULL);
252 g_object_unref (begin);
254 g_object_unref (end);
255 return preword_chars;
258 static gchar*
259 cpp_java_assist_get_scope_operator (IAnjutaEditor* editor,
260 IAnjutaIterable *iter)
262 gchar op[3] = {'\0', '\0', '\0'};
264 op[1] = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
265 if (op[1] == ':' || op[1] == '>' || op[1] == '.')
267 if (ianjuta_iterable_previous (iter, NULL))
269 op[0] = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter),
270 0, NULL);
271 if ((op[0] == ':' && op[1] == ':') ||
272 (op[0] == '-' && op[1] == '>'))
274 ianjuta_iterable_previous (iter, NULL);
275 return g_strdup (op);
277 else
279 if (op[1] == '.')
280 return g_strdup (&op[1]);
283 else
285 if (op[1] == '.')
286 return g_strdup (&op[1]);
289 return NULL;
292 static void
293 cpp_java_assist_destroy_completion_cache (CppJavaAssist *assist)
295 if (assist->priv->search_cache)
297 g_free (assist->priv->search_cache);
298 assist->priv->search_cache = NULL;
300 if (assist->priv->scope_context_cache)
302 g_free (assist->priv->scope_context_cache);
303 assist->priv->scope_context_cache = NULL;
305 if (assist->priv->completion_cache)
307 GList* items = assist->priv->completion_cache->items;
308 if (items)
310 g_list_foreach (items, (GFunc) cpp_java_assist_tag_destroy, NULL);
311 g_completion_clear_items (assist->priv->completion_cache);
313 g_completion_free (assist->priv->completion_cache);
314 assist->priv->completion_cache = NULL;
318 static void
319 cpp_java_assist_create_scope_completion_cache (CppJavaAssist *assist,
320 const gchar *scope_operator,
321 const gchar *scope_context)
323 DEBUG_PRINT ("TODO: cpp_java_assist_create_scope_completion_cache ()");
324 #if 0
325 cpp_java_assist_destroy_completion_cache (assist);
326 if (g_str_equal (scope_operator, "::"))
328 IAnjutaIterable* iter =
329 ianjuta_symbol_manager_get_members (assist->priv->isymbol_manager,
330 scope_context, TRUE, NULL);
331 if (iter)
333 assist->priv->completion_cache =
334 create_completion (assist->priv->iassist, iter);
335 assist->priv->scope_context_cache = g_strdup (scope_context);
336 g_object_unref (iter);
339 else if (g_str_equal (scope_operator, ".") ||
340 g_str_equal (scope_operator, "->"))
342 /* TODO: Find the type of context by parsing the file somehow and
343 search for the member as it is done with the :: context */
345 #endif
348 static void
349 cpp_java_assist_create_word_completion_cache (CppJavaAssist *assist,
350 const gchar *pre_word)
352 gint max_completions;
353 GCompletion *completion = NULL;
354 GList* editor_completions = NULL;
355 assist->priv->editor_only = FALSE;
356 max_completions =
357 anjuta_preferences_get_int_with_default (assist->priv->preferences,
358 PREF_AUTOCOMPLETE_CHOICES,
359 MAX_COMPLETIONS);
361 cpp_java_assist_destroy_completion_cache (assist);
362 IAnjutaIterable* iter_project =
363 ianjuta_symbol_manager_search (assist->priv->isymbol_manager,
364 IANJUTA_SYMBOL_TYPE_MAX,
365 TRUE,
366 IANJUTA_SYMBOL_FIELD_SIMPLE|IANJUTA_SYMBOL_FIELD_TYPE,
367 pre_word, TRUE, FALSE, FALSE, max_completions, -1, NULL);
369 IAnjutaIterable* iter_globals =
370 ianjuta_symbol_manager_search (assist->priv->isymbol_manager,
371 IANJUTA_SYMBOL_TYPE_MAX,
372 TRUE,
373 IANJUTA_SYMBOL_FIELD_SIMPLE|IANJUTA_SYMBOL_FIELD_TYPE,
374 pre_word, TRUE, TRUE, TRUE, max_completions, -1, NULL);
376 if (iter_project)
378 DEBUG_PRINT ("length iter_project %d", ianjuta_iterable_get_length (iter_project, NULL));
379 completion = create_completion (assist->priv->iassist, iter_project, NULL);
380 g_object_unref (iter_project);
383 if (iter_globals)
385 DEBUG_PRINT ("length iter_globals %d", ianjuta_iterable_get_length (iter_globals, NULL));
386 completion = create_completion (assist->priv->iassist, iter_globals, completion);
387 g_object_unref (iter_globals);
390 editor_completions = ianjuta_editor_assist_get_suggestions (assist->priv->iassist,
391 pre_word,
392 NULL);
393 if (editor_completions)
395 GList* tag_list = NULL;
396 GList* node;
397 for (node = editor_completions; node != NULL; node = g_list_next (node))
399 CppJavaAssistTag *tag = g_new0 (CppJavaAssistTag, 1);
400 tag->name = node->data;
401 tag->type = 0;
402 tag->is_func = FALSE;
403 if (completion && !g_list_find_custom (completion->items, tag,
404 completion_compare))
405 tag_list = g_list_append (tag_list, tag);
406 else
407 cpp_java_assist_tag_destroy (tag);
409 if (!completion)
411 completion = g_completion_new(completion_function);
412 assist->priv->editor_only = TRUE;
414 tag_list = g_list_sort (tag_list, completion_compare);
415 g_completion_add_items (completion, tag_list);
416 g_list_free (editor_completions);
419 assist->priv->completion_cache = completion;
420 assist->priv->search_cache = g_strdup (pre_word);
423 static gboolean
424 cpp_java_assist_show_autocomplete (CppJavaAssist *assist,
425 const gchar *pre_word)
427 IAnjutaIterable *position;
428 gint max_completions, length;
429 GList *completion_list;
431 if (assist->priv->completion_cache == NULL) return FALSE;
433 if (pre_word)
434 g_completion_complete (assist->priv->completion_cache, pre_word, NULL);
435 else
436 g_completion_complete (assist->priv->completion_cache, "", NULL);
438 position =
439 ianjuta_editor_get_position (IANJUTA_EDITOR (assist->priv->iassist),
440 NULL);
441 max_completions =
442 anjuta_preferences_get_int_with_default (assist->priv->preferences,
443 PREF_AUTOCOMPLETE_CHOICES,
444 MAX_COMPLETIONS);
445 /* If there is cache use that */
446 if (assist->priv->completion_cache->cache)
447 completion_list = assist->priv->completion_cache->cache;
449 /* If there is no cache, it means that no string completion happened
450 * because the list is being shown for member completion just after
451 * scope operator where there is no preword yet entered. So use the
452 * full list because that's the full list of members of that scope.
454 else if (!pre_word)
455 completion_list = assist->priv->completion_cache->items;
457 else
458 return FALSE;
460 length = g_list_length (completion_list);
461 if (length <= max_completions)
463 if (length > 1 || !pre_word ||
464 !g_str_equal (pre_word,
465 ((CppJavaAssistTag*)completion_list->data)->name))
467 GList *node, *suggestions = NULL;
468 gint alignment;
470 node = completion_list;
471 while (node)
473 CppJavaAssistTag *tag = node->data;
475 gchar *entry;
477 if (tag->is_func)
478 entry = g_strdup_printf ("%s()", tag->name);
479 else
480 entry = g_strdup_printf ("%s", tag->name);
481 suggestions = g_list_prepend (suggestions, entry);
482 node = g_list_next (node);
484 suggestions = g_list_reverse (suggestions);
485 alignment = pre_word? strlen (pre_word) : 0;
487 ianjuta_editor_assist_suggest (assist->priv->iassist,
488 suggestions,
489 position,
490 alignment,
491 NULL);
492 g_list_foreach (suggestions, (GFunc) g_free, NULL);
493 g_list_free (suggestions);
494 g_object_unref (position);
495 return TRUE;
498 g_object_unref (position);
499 return FALSE;
502 static gchar*
503 cpp_java_assist_get_calltip_context (CppJavaAssist *assist,
504 IAnjutaIterable *iter,
505 gint *context_offset)
507 gchar ch;
508 gchar *context = NULL;
510 ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
511 if (ch == ')')
513 if (!cpp_java_util_jump_to_matching_brace (iter, ')', -1))
514 return NULL;
515 if (!ianjuta_iterable_previous (iter, NULL))
516 return NULL;
518 if (ch != '(')
520 if (!cpp_java_util_jump_to_matching_brace (iter, ')',
521 BRACE_SEARCH_LIMIT))
522 return NULL;
525 /* Skip white spaces */
526 while (ianjuta_iterable_previous (iter, NULL)
527 && g_ascii_isspace (ianjuta_editor_cell_get_char
528 (IANJUTA_EDITOR_CELL (iter), 0, NULL)));
531 context = cpp_java_assist_get_scope_context
532 (IANJUTA_EDITOR (assist->priv->iassist), "(", iter);
534 if (context_offset)
536 *context_offset = get_iter_column (assist, iter);
539 return context;
542 static gboolean
543 cpp_java_assist_show_calltip (CppJavaAssist *assist, gchar *call_context,
544 gint context_offset,
545 IAnjutaIterable *position_iter)
547 GList *tips = NULL;
548 gint max_completions;
550 max_completions =
551 anjuta_preferences_get_int_with_default (assist->priv->preferences,
552 PREF_AUTOCOMPLETE_CHOICES,
553 MAX_COMPLETIONS);
555 IAnjutaIterable* iter =
556 ianjuta_symbol_manager_search (assist->priv->isymbol_manager,
557 IANJUTA_SYMBOL_TYPE_PROTOTYPE|
558 IANJUTA_SYMBOL_TYPE_FUNCTION|
559 IANJUTA_SYMBOL_TYPE_METHOD|
560 IANJUTA_SYMBOL_TYPE_MACRO_WITH_ARG,
561 TRUE, IANJUTA_SYMBOL_FIELD_SIMPLE,
562 call_context, FALSE, TRUE, TRUE,
563 max_completions, -1, NULL);
564 if (iter)
568 IAnjutaSymbol* symbol = IANJUTA_SYMBOL(iter);
569 const gchar* name = ianjuta_symbol_get_name(symbol, NULL);
570 if (name != NULL)
572 const gchar* args = ianjuta_symbol_get_args(symbol, NULL);
573 gchar* print_args;
574 gchar* separator;
575 gchar* white_name = g_strnfill (strlen(name) + 1, ' ');
577 separator = g_strjoin (NULL, ", \n", white_name, NULL);
578 //DEBUG_PRINT ("Separator: \n%s", separator);
580 gchar** argv;
581 if (!args)
582 args = "()";
584 argv = g_strsplit (args, ",", -1);
585 print_args = g_strjoinv (separator, argv);
587 gchar* tip = g_strdup_printf ("%s %s", name, print_args);
589 if (!g_list_find_custom (tips, tip, (GCompareFunc) strcmp))
590 tips = g_list_append (tips, tip);
592 g_strfreev (argv);
593 g_free (print_args);
594 g_free (separator);
595 g_free (white_name);
597 else
598 break;
600 while (ianjuta_iterable_next (iter, NULL));
602 if (tips)
604 /* Calculate calltip offset from context offset */
605 gint char_alignment =
606 get_iter_column (assist, position_iter)- context_offset;
608 if (char_alignment < 0)
609 char_alignment = context_offset;
611 ianjuta_editor_assist_show_tips (assist->priv->iassist, tips,
612 position_iter, char_alignment,
613 NULL);
614 g_list_foreach (tips, (GFunc) g_free, NULL);
615 g_list_free (tips);
616 return TRUE;
619 return FALSE;
622 gboolean
623 cpp_java_assist_check (CppJavaAssist *assist, gboolean autocomplete,
624 gboolean calltips)
626 gboolean shown = FALSE;
627 IAnjutaEditor *editor;
628 IAnjutaIterable *iter, *iter_save;
629 IAnjutaEditorAttribute attribute;
630 gchar *pre_word = NULL, *scope_operator = NULL;
632 //DEBUG_PRINT ("Autocomplete enable is: %d", autocomplete);
633 //DEBUG_PRINT ("Calltips enable is: %d", calltips);
635 if (!autocomplete && !calltips)
636 return FALSE; /* Nothing to do */
638 editor = IANJUTA_EDITOR (assist->priv->iassist);
640 iter = ianjuta_editor_get_position (editor, NULL);
641 ianjuta_iterable_previous (iter, NULL);
642 iter_save = ianjuta_iterable_clone (iter, NULL);
644 attribute = ianjuta_editor_cell_get_attribute (IANJUTA_EDITOR_CELL (iter),
645 NULL);
647 if (attribute == IANJUTA_EDITOR_COMMENT ||
648 attribute == IANJUTA_EDITOR_STRING);
650 g_object_unref (iter);
651 g_object_unref (iter_save);
652 return FALSE;
656 //DEBUG_PRINT ("assist init: %f", g_timer_elapsed (timer, NULL));
658 if (autocomplete)
660 pre_word = cpp_java_assist_get_pre_word (editor, iter);
661 //DEBUG_PRINT ("assist pre word: %f", g_timer_elapsed (timer, NULL));
663 scope_operator = cpp_java_assist_get_scope_operator (editor, iter);
664 //DEBUG_PRINT ("assist scope operator: %f", g_timer_elapsed (timer, NULL));
666 //DEBUG_PRINT ("Pre word: %s", pre_word);
667 //DEBUG_PRINT ("Scope op: %s", scope_operator);
669 if (scope_operator)
671 gchar *scope_context = NULL;
672 scope_context = cpp_java_assist_get_scope_context (editor,
673 scope_operator,
674 iter);
676 DEBUG_PRINT ("Scope context: %s", scope_context);
678 if (scope_context)
680 if (!assist->priv->scope_context_cache ||
681 strcmp (scope_context,
682 assist->priv->scope_context_cache) != 0)
684 cpp_java_assist_create_scope_completion_cache (assist,
685 scope_operator,
686 scope_context);
688 shown = cpp_java_assist_show_autocomplete (assist, pre_word);
690 g_free (scope_context);
692 else if (pre_word && strlen (pre_word) > 3)
694 if (!assist->priv->search_cache ||
695 strncmp (assist->priv->search_cache,
696 pre_word, strlen (assist->priv->search_cache)) != 0 ||
697 assist->priv->editor_only)
699 cpp_java_assist_create_word_completion_cache (assist, pre_word);
701 shown = cpp_java_assist_show_autocomplete (assist, pre_word);
703 if (!shown)
705 ianjuta_editor_assist_hide_suggestions (assist->priv->iassist,
706 NULL);
708 //DEBUG_PRINT ("assist autocomplete: %f", g_timer_elapsed (timer, NULL));
710 if (calltips)
712 if (!shown)
714 gint offset;
715 gchar *call_context =
716 cpp_java_assist_get_calltip_context (assist, iter, &offset);
717 //DEBUG_PRINT ("get calltip context: %f", g_timer_elapsed (timer, NULL));
718 if (call_context)
720 shown = cpp_java_assist_show_calltip (assist, call_context,
721 offset, iter_save);
723 else
725 ianjuta_editor_assist_cancel_tips (assist->priv->iassist, NULL);
727 g_free (call_context);
729 //DEBUG_PRINT ("assist calltip: %f", g_timer_elapsed (timer, NULL));
731 g_object_unref (iter);
732 g_object_unref (iter_save);
733 g_free (pre_word);
734 g_free (scope_operator);
736 return shown;
739 static void
740 on_editor_char_added (IAnjutaEditor *editor, IAnjutaIterable *insert_pos,
741 gchar ch, CppJavaAssist *assist)
743 gboolean enable_complete =
744 anjuta_preferences_get_int_with_default (assist->priv->preferences,
745 PREF_AUTOCOMPLETE_ENABLE,
746 TRUE);
748 gboolean enable_calltips =
749 anjuta_preferences_get_int_with_default (assist->priv->preferences,
750 PREF_CALLTIP_ENABLE,
751 TRUE);
752 cpp_java_assist_check (assist, enable_complete, enable_calltips);
755 static void
756 on_assist_chosen (IAnjutaEditorAssist* iassist, gint selection,
757 CppJavaAssist* assist)
759 CppJavaAssistTag *tag;
760 IAnjutaIterable *cur_pos;
761 GString *assistance;
762 IAnjutaEditor *te;
763 IAnjutaIterable *iter;
764 gchar *pre_word = NULL;
765 gboolean add_space_after_func = FALSE;
766 gboolean add_brace_after_func = FALSE;
768 //DEBUG_PRINT ("assist-chosen: %d", selection);
770 if (assist->priv->completion_cache->cache)
771 tag = g_list_nth_data (assist->priv->completion_cache->cache,
772 selection);
773 else
774 tag = g_list_nth_data (assist->priv->completion_cache->items,
775 selection);
777 assistance = g_string_new (tag->name);
779 if (tag->is_func)
781 add_space_after_func =
782 anjuta_preferences_get_int_with_default (assist->priv->preferences,
783 PREF_AUTOCOMPLETE_SPACE_AFTER_FUNC,
784 TRUE);
785 add_brace_after_func =
786 anjuta_preferences_get_int_with_default (assist->priv->preferences,
787 PREF_AUTOCOMPLETE_BRACE_AFTER_FUNC,
788 TRUE);
789 if (add_space_after_func)
790 g_string_append (assistance, " ");
792 if (add_brace_after_func)
793 g_string_append (assistance, "(");
796 te = IANJUTA_EDITOR (assist->priv->iassist);
797 cur_pos = ianjuta_editor_get_position (te, NULL);
798 iter = ianjuta_iterable_clone (cur_pos, NULL);
800 if (ianjuta_iterable_previous (iter, NULL))
802 pre_word = cpp_java_assist_get_pre_word (te, iter);
805 ianjuta_document_begin_undo_action (IANJUTA_DOCUMENT (te), NULL);
806 if (pre_word)
808 ianjuta_iterable_next (iter, NULL);
809 ianjuta_editor_selection_set (IANJUTA_EDITOR_SELECTION (te),
810 iter, cur_pos, NULL);
811 ianjuta_editor_selection_replace (IANJUTA_EDITOR_SELECTION (te),
812 assistance->str, -1, NULL);
813 g_free (pre_word);
815 else
817 ianjuta_editor_insert (te, cur_pos, assistance->str, -1, NULL);
819 g_object_unref (iter);
820 g_object_unref (cur_pos);
822 ianjuta_document_end_undo_action (IANJUTA_DOCUMENT (te), NULL);
824 ianjuta_editor_assist_hide_suggestions (assist->priv->iassist, NULL);
826 /* Show calltip if we completed function */
827 if (add_brace_after_func)
828 cpp_java_assist_check (assist, FALSE, TRUE);
830 g_string_free (assistance, TRUE);
833 static void
834 cpp_java_assist_install (CppJavaAssist *assist, IAnjutaEditorAssist *iassist)
836 g_return_if_fail (assist->priv->iassist == NULL);
838 assist->priv->iassist = iassist;
839 g_signal_connect (iassist, "char-added",
840 G_CALLBACK (on_editor_char_added), assist);
841 g_signal_connect (iassist, "assist-chosen",
842 G_CALLBACK(on_assist_chosen), assist);
845 static void
846 cpp_java_assist_uninstall (CppJavaAssist *assist)
848 g_return_if_fail (assist->priv->iassist != NULL);
849 g_signal_handlers_disconnect_by_func (assist->priv->iassist,
850 G_CALLBACK(on_assist_chosen), assist);
851 g_signal_handlers_disconnect_by_func (assist->priv->iassist,
852 G_CALLBACK (on_editor_char_added),
853 assist);
854 assist->priv->iassist = NULL;
857 static void
858 cpp_java_assist_init (CppJavaAssist *assist)
860 assist->priv = g_new0 (CppJavaAssistPriv, 1);
863 static void
864 cpp_java_assist_finalize (GObject *object)
866 CppJavaAssist *assist = CPP_JAVA_ASSIST (object);
867 cpp_java_assist_uninstall (assist);
868 cpp_java_assist_destroy_completion_cache (assist);
869 g_free (assist->priv);
870 G_OBJECT_CLASS (cpp_java_assist_parent_class)->finalize (object);
873 static void
874 cpp_java_assist_class_init (CppJavaAssistClass *klass)
876 GObjectClass* object_class = G_OBJECT_CLASS (klass);
878 object_class->finalize = cpp_java_assist_finalize;
881 CppJavaAssist *
882 cpp_java_assist_new (IAnjutaEditorAssist *iassist,
883 IAnjutaSymbolManager *isymbol_manager,
884 AnjutaPreferences *prefs)
886 CppJavaAssist *assist = g_object_new (TYPE_CPP_JAVA_ASSIST, NULL);
887 assist->priv->isymbol_manager = isymbol_manager;
888 assist->priv->preferences = prefs;
889 cpp_java_assist_install (assist, iassist);
890 return assist;