python: Fix crash during auto-indentation
[anjuta.git] / plugins / language-support-python / python-assist.c
blob8379c5e61e0f79ccfa22776e7035dc18e8daf5af
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * python-assist.c
4 * Copyright (C) Ishan Chattopadhyaya 2009 <ichattopadhyaya@gmail.com>
5 *
6 * anjuta is free software.
7 *
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
11 * any later version.
13 * anjuta is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 * See the GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with anjuta. If not, write to:
20 * The Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301, USA.
25 #include <ctype.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <glib/gi18n.h>
29 #include <libanjuta/anjuta-debug.h>
30 #include <libanjuta/anjuta-language-provider.h>
31 #include <libanjuta/anjuta-launcher.h>
32 #include <libanjuta/anjuta-plugin.h>
33 #include <libanjuta/anjuta-utils.h>
34 #include <libanjuta/interfaces/ianjuta-file.h>
35 #include <libanjuta/interfaces/ianjuta-editor.h>
36 #include <libanjuta/interfaces/ianjuta-editor-cell.h>
37 #include <libanjuta/interfaces/ianjuta-editor-tip.h>
38 #include <libanjuta/interfaces/ianjuta-language-provider.h>
39 #include <libanjuta/interfaces/ianjuta-symbol-manager.h>
40 #include <libanjuta/interfaces/ianjuta-symbol.h>
41 #include <libanjuta/interfaces/ianjuta-project-manager.h>
42 #include "python-assist.h"
44 #define PREF_INTERPRETER_PATH "interpreter-path"
45 #define MAX_COMPLETIONS 30
46 #define BRACE_SEARCH_LIMIT 500
47 #define SCOPE_BRACE_JUMP_LIMIT 50
49 #define AUTOCOMPLETE_SCRIPT SCRIPTS_DIR"/anjuta-python-autocomplete.py"
51 #define AUTOCOMPLETE_REGEX_IN_GET_OBJECT "get_object\\s*\\(\\s*['\"]\\w*$"
52 #define FILE_LIST_DELIMITER "|"
53 #define SCOPE_CONTEXT_CHARACTERS ".0"
54 #define WORD_CHARACTER "_0"
56 static void iprovider_iface_init(IAnjutaProviderIface* iface);
57 static void ilanguage_provider_iface_init(IAnjutaLanguageProviderIface* iface);
59 G_DEFINE_TYPE_WITH_CODE (PythonAssist,
60 python_assist,
61 G_TYPE_OBJECT,
62 G_IMPLEMENT_INTERFACE (IANJUTA_TYPE_PROVIDER,
63 iprovider_iface_init)
64 G_IMPLEMENT_INTERFACE (IANJUTA_TYPE_LANGUAGE_PROVIDER,
65 ilanguage_provider_iface_init))
67 struct _PythonAssistPriv {
68 GSettings* settings;
69 IAnjutaEditorAssist* iassist;
70 IAnjutaEditorTip* itip;
71 AnjutaLanguageProvider* lang_prov;
72 AnjutaLauncher* launcher;
73 AnjutaLauncher* calltip_launcher;
74 AnjutaPlugin* plugin;
76 const gchar* project_root;
77 const gchar* editor_filename;
79 /* Autocompletion */
80 GCompletion *completion_cache;
81 gchar *pre_word;
83 gint cache_position;
84 GString* rope_cache;
86 /* Calltips */
87 gchar* calltip_context;
88 IAnjutaIterable* calltip_iter;
89 GList* tips;
90 GString* calltip_cache;
93 static gchar*
94 completion_function (gpointer data)
96 AnjutaLanguageProposalData * tag = ANJUTA_LANGUAGE_PROPOSAL_DATA(data);
97 return tag->name;
100 static gint
101 completion_compare (gconstpointer a, gconstpointer b)
103 AnjutaLanguageProposalData * tag_a = ANJUTA_LANGUAGE_PROPOSAL_DATA(a);
104 AnjutaLanguageProposalData * tag_b = ANJUTA_LANGUAGE_PROPOSAL_DATA(b);
105 gint cmp;
107 cmp = strcmp (tag_a->name, tag_b->name);
108 if (cmp == 0) cmp = tag_a->type - tag_b->type;
110 return cmp;
113 static void
114 python_assist_tag_destroy (AnjutaLanguageProposalData *tag)
116 anjuta_language_proposal_data_free (tag);
119 static void
120 python_assist_cancel_queries (PythonAssist* assist)
122 if (assist->priv->launcher)
124 g_object_unref (assist->priv->launcher);
125 assist->priv->launcher = NULL;
129 static void
130 python_assist_destroy_completion_cache (PythonAssist *assist)
132 python_assist_cancel_queries (assist);
133 if (assist->priv->completion_cache)
135 GList* items = assist->priv->completion_cache->items;
136 if (items)
138 g_list_foreach (items, (GFunc) python_assist_tag_destroy, NULL);
139 g_completion_clear_items (assist->priv->completion_cache);
141 g_completion_free (assist->priv->completion_cache);
142 assist->priv->completion_cache = NULL;
144 if (assist->priv->rope_cache)
146 g_string_free (assist->priv->rope_cache, TRUE);
147 assist->priv->rope_cache = NULL;
151 static void free_proposal (IAnjutaEditorAssistProposal* proposal)
153 g_free (proposal->label);
154 g_free(proposal);
157 static void
158 python_assist_cancelled (IAnjutaEditorAssist* editor,
159 PythonAssist* assist)
161 python_assist_cancel_queries (assist);
164 static void
165 python_assist_update_autocomplete (PythonAssist *assist)
167 GList *node, *suggestions = NULL;
168 GList *completion_list = g_completion_complete (assist->priv->completion_cache, assist->priv->pre_word, NULL);
170 for (node = completion_list; node != NULL; node = g_list_next (node))
172 AnjutaLanguageProposalData *tag = ANJUTA_LANGUAGE_PROPOSAL_DATA(node->data);
173 IAnjutaEditorAssistProposal* proposal = g_new0(IAnjutaEditorAssistProposal, 1);
175 if (tag->is_func)
176 proposal->label = g_strdup_printf ("%s()", tag->name);
177 else
178 proposal->label = g_strdup(tag->name);
180 if (tag->info)
181 proposal->info = g_strdup(tag->info);
182 proposal->data = tag;
183 suggestions = g_list_prepend (suggestions, proposal);
185 suggestions = g_list_reverse (suggestions);
187 ianjuta_editor_assist_proposals (IANJUTA_EDITOR_ASSIST (assist->priv->iassist),
188 IANJUTA_PROVIDER(assist), suggestions,
189 assist->priv->pre_word, TRUE, NULL);
191 g_list_foreach (suggestions, (GFunc) free_proposal, NULL);
192 g_list_free (suggestions);
195 /* Returns NULL if creation fails */
196 static gchar*
197 create_tmp_file (const gchar* source)
199 gchar* tmp_file;
200 gint tmp_fd;
201 GError* err = NULL;
203 tmp_fd = g_file_open_tmp (NULL, &tmp_file, &err);
204 if (tmp_fd >= 0)
206 FILE *rope_file = fdopen (tmp_fd, "w");
207 if (rope_file)
209 fprintf (rope_file, "%s", source);
210 fclose (rope_file);
211 close (tmp_fd);
212 return tmp_file;
216 /* Error */
217 g_warning ("Creating tmp_file failed: %s", err->message);
218 g_error_free (err);
219 return NULL;
222 static void
223 on_autocomplete_output (AnjutaLauncher *launcher,
224 AnjutaLauncherOutputType output_type,
225 const gchar *chars,
226 gpointer user_data)
228 PythonAssist* assist = PYTHON_ASSIST (user_data);
229 if (output_type == ANJUTA_LAUNCHER_OUTPUT_STDOUT)
231 printf ("chars from script: %s", chars);
232 if (assist->priv->rope_cache)
234 g_string_append (assist->priv->rope_cache, chars);
236 else
238 assist->priv->rope_cache = g_string_new (chars);
241 if (output_type == ANJUTA_LAUNCHER_OUTPUT_STDERR)
243 g_warning ("Problem in python script: %s", chars);
247 static void
248 on_autocomplete_finished (AnjutaLauncher* launcher,
249 int child_pid, int exit_status,
250 gulong time, gpointer user_data)
252 PythonAssist* assist = PYTHON_ASSIST (user_data);
253 DEBUG_PRINT ("Python-Complete took %lu seconds and returned %d", time, exit_status);
255 g_object_unref (launcher);
256 assist->priv->launcher = NULL;
258 if (assist->priv->rope_cache)
260 GStrv completions = g_strsplit (assist->priv->rope_cache->str, "\n", -1);
261 GStrv cur_comp;
262 GList* suggestions = NULL;
263 GError *err = NULL;
264 GRegex* regex = g_regex_new ("\\|(.+)\\|(.+)\\|(.+)\\|(.+)\\|(.+)\\|",
265 0, 0, &err);
266 if (err)
268 g_warning ("Error creating regex: %s", err->message);
269 g_error_free (err);
270 return;
273 /* Parse output and create completion list */
274 for (cur_comp = completions; *cur_comp != NULL; cur_comp++)
276 AnjutaLanguageProposalData* tag;
277 GMatchInfo* match_info;
279 g_regex_match (regex, *cur_comp, 0, &match_info);
280 if (g_match_info_matches (match_info) &&
281 g_match_info_get_match_count (match_info) == 6)
283 gchar* type = g_match_info_fetch (match_info, 3);
284 gchar* location = g_match_info_fetch (match_info, 4);
285 gchar* info = g_match_info_fetch (match_info, 5);
286 tag = anjuta_language_proposal_data_new (g_match_info_fetch (match_info, 1));
288 /* info will be set to "_" if there is no relevant info */
289 tag->info = NULL;
290 if (!g_str_equal(info, "_"))
291 tag->info = g_strdup(info);
294 if (g_str_equal(type, "function") || g_str_equal (type, "builtin"))
296 tag->type = IANJUTA_SYMBOL_TYPE_FUNCTION;
297 tag->is_func = TRUE;
298 /* TODO: not implemented yet */
299 tag->has_para = TRUE;
301 else if (g_str_equal(type, "builder_object"))
303 tag->type = IANJUTA_SYMBOL_TYPE_EXTERNVAR;
304 if (!g_str_equal(location, "_"))
305 tag->info = g_strdup(location);
307 else
308 tag->type = IANJUTA_SYMBOL_TYPE_VARIABLE;
309 g_free (type);
310 g_free (info);
311 g_free (location);
313 if (!g_list_find_custom (suggestions, tag, completion_compare))
315 suggestions = g_list_prepend (suggestions, tag);
317 else
318 anjuta_language_proposal_data_free (tag);
320 g_match_info_free (match_info);
323 g_regex_unref (regex);
324 g_strfreev (completions);
325 g_string_free (assist->priv->rope_cache, TRUE);
326 assist->priv->rope_cache = NULL;
328 assist->priv->completion_cache = g_completion_new (completion_function);
329 g_completion_add_items (assist->priv->completion_cache, suggestions);
330 g_list_free (suggestions);
332 /* Show autocompletion */
333 python_assist_update_autocomplete (assist);
337 static gboolean
338 python_assist_create_word_completion_cache (PythonAssist *assist, IAnjutaIterable* cursor)
340 IAnjutaEditor *editor = IANJUTA_EDITOR (assist->priv->iassist);
341 const gchar *cur_filename;
342 gint offset = ianjuta_iterable_get_position (cursor, NULL);
343 const gchar *project = assist->priv->project_root;
344 gchar *interpreter_path;
345 gchar *ropecommand;
346 GString *builder_file_paths = g_string_new("");
347 GList *project_files_list, *node;
349 gchar *source = ianjuta_editor_get_text_all (editor, NULL);
350 gchar *tmp_file;
352 cur_filename = assist->priv->editor_filename;
353 if (!project)
354 project = g_get_tmp_dir ();
356 /* Create rope command and temporary source file */
357 interpreter_path = g_settings_get_string (assist->priv->settings,
358 PREF_INTERPRETER_PATH);
360 tmp_file = create_tmp_file (source);
361 g_free (source);
363 if (!tmp_file)
364 return FALSE;
366 /* Get a list of all the builder files in the project */
367 IAnjutaProjectManager *manager = anjuta_shell_get_interface (ANJUTA_PLUGIN (assist->priv->plugin)->shell,
368 IAnjutaProjectManager,
369 NULL);
370 project_files_list = ianjuta_project_manager_get_elements (IANJUTA_PROJECT_MANAGER (manager),
371 ANJUTA_PROJECT_SOURCE,
372 NULL);
373 for (node = project_files_list; node != NULL; node = g_list_next (node))
375 gchar *file_path = g_file_get_path (node->data);
376 builder_file_paths = g_string_append (builder_file_paths, FILE_LIST_DELIMITER);
377 builder_file_paths = g_string_append (builder_file_paths, file_path);
378 g_free (file_path);
379 g_object_unref (node->data);
381 g_list_free (project_files_list);
383 ropecommand = g_strdup_printf("%s %s -o autocomplete -p \"%s\" -r \"%s\" -s \"%s\" -f %d -b \"%s\"",
384 interpreter_path, AUTOCOMPLETE_SCRIPT, project,
385 cur_filename, tmp_file, offset, builder_file_paths->str);
386 g_string_free (builder_file_paths, TRUE);
387 g_free (tmp_file);
389 DEBUG_PRINT("%s", ropecommand);
391 /* Exec command and wait for results */
392 assist->priv->launcher = anjuta_launcher_new ();
393 g_signal_connect (assist->priv->launcher, "child-exited",
394 G_CALLBACK(on_autocomplete_finished), assist);
395 anjuta_launcher_execute (assist->priv->launcher, ropecommand,
396 on_autocomplete_output,
397 assist);
398 g_free (ropecommand);
400 assist->priv->cache_position = offset;
402 ianjuta_editor_assist_proposals (IANJUTA_EDITOR_ASSIST (assist->priv->iassist),
403 IANJUTA_PROVIDER (assist), NULL,
404 NULL, FALSE, NULL);
406 return TRUE;
409 static void
410 on_calltip_output (AnjutaLauncher *launcher,
411 AnjutaLauncherOutputType output_type,
412 const gchar *chars,
413 gpointer user_data)
415 PythonAssist* assist = PYTHON_ASSIST (user_data);
416 if (output_type == ANJUTA_LAUNCHER_OUTPUT_STDOUT)
418 if (assist->priv->calltip_cache)
420 g_string_append (assist->priv->calltip_cache, chars);
422 else
424 assist->priv->calltip_cache = g_string_new (chars);
429 static void
430 on_calltip_finished (AnjutaLauncher* launcher,
431 int child_pid, int exit_status,
432 gulong time, gpointer user_data)
434 PythonAssist* assist = PYTHON_ASSIST (user_data);
435 DEBUG_PRINT ("Python-Complete took %lu seconds and returned %d", time, exit_status);
437 g_object_unref (launcher);
438 assist->priv->calltip_launcher = NULL;
440 if (assist->priv->calltip_cache)
442 GString* calltip_text = g_string_new (assist->priv->calltip_cache->str);
443 assist->priv->tips = g_list_prepend (NULL, calltip_text->str);
444 if (g_strncasecmp ("None", assist->priv->tips->data, 4))
446 ianjuta_editor_tip_show (IANJUTA_EDITOR_TIP(assist->priv->itip),
447 assist->priv->tips,
448 assist->priv->calltip_iter,
449 NULL);
451 g_string_free (assist->priv->calltip_cache, TRUE);
452 assist->priv->calltip_cache = NULL;
456 static gint
457 python_assist_get_calltip_context_position (PythonAssist *assist)
459 gchar ch;
460 gint final_offset;
461 IAnjutaEditor *editor = IANJUTA_EDITOR (assist->priv->iassist);
462 IAnjutaIterable *current_iter = ianjuta_editor_get_position (editor, NULL);
464 while (ianjuta_iterable_previous (current_iter, NULL))
466 ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (current_iter), 0, NULL);
467 if (ch == '(')
468 break;
470 final_offset = ianjuta_iterable_get_position (current_iter, NULL);
472 return final_offset-1;
475 static void
476 python_assist_query_calltip (PythonAssist* assist, const gchar *call_context)
478 IAnjutaEditor *editor = IANJUTA_EDITOR (assist->priv->iassist);
480 gint offset = python_assist_get_calltip_context_position (assist);
482 gchar *interpreter_path;
483 const gchar *cur_filename;
484 gchar *source = ianjuta_editor_get_text_all (editor, NULL);
485 const gchar *project = assist->priv->project_root;
486 gchar *tmp_file;
487 gchar *ropecommand;
489 cur_filename = assist->priv->editor_filename;
490 if (!project)
491 project = g_get_tmp_dir ();
493 interpreter_path = g_settings_get_string (assist->priv->settings,
494 PREF_INTERPRETER_PATH);
496 tmp_file = create_tmp_file (source);
497 g_free (source);
499 if (!tmp_file)
500 return;
502 ropecommand = g_strdup_printf("%s %s -o calltip -p \"%s\" -r \"%s\" -s \"%s\" -f %d",
503 interpreter_path, AUTOCOMPLETE_SCRIPT, project,
504 cur_filename, tmp_file, offset);
506 DEBUG_PRINT ("%s", ropecommand);
508 g_free (tmp_file);
510 /* Exec command and wait for results */
511 assist->priv->calltip_launcher = anjuta_launcher_new ();
512 g_signal_connect (assist->priv->calltip_launcher, "child-exited",
513 G_CALLBACK(on_calltip_finished), assist);
514 anjuta_launcher_execute (assist->priv->calltip_launcher, ropecommand,
515 on_calltip_output,
516 assist);
517 g_free (ropecommand);
520 static void
521 python_assist_create_calltip_context (PythonAssist* assist,
522 const gchar* call_context,
523 IAnjutaIterable* position)
525 assist->priv->calltip_context = g_strdup (call_context);
526 assist->priv->calltip_iter = position;
529 static void
530 python_assist_clear_calltip_context (PythonAssist* assist)
532 if (assist->priv->calltip_launcher)
534 g_object_unref (assist->priv->calltip_launcher);
536 assist->priv->calltip_launcher = NULL;
538 g_list_foreach (assist->priv->tips, (GFunc) g_free, NULL);
539 g_list_free (assist->priv->tips);
540 assist->priv->tips = NULL;
542 g_free (assist->priv->calltip_context);
543 assist->priv->calltip_context = NULL;
545 if (assist->priv->calltip_iter)
546 g_object_unref (assist->priv->calltip_iter);
547 assist->priv->calltip_iter = NULL;
550 static gchar*
551 python_assist_get_calltip_context (IAnjutaLanguageProvider *self,
552 IAnjutaIterable *iter,
553 GError** e)
555 PythonAssist* assist = PYTHON_ASSIST (self);
556 gchar* calltip_context;
557 calltip_context = anjuta_language_provider_get_calltip_context (
558 assist->priv->lang_prov, assist->priv->itip, iter,
559 SCOPE_CONTEXT_CHARACTERS);
560 return calltip_context;
563 static void
564 python_assist_update_pre_word (PythonAssist* assist, const gchar* pre_word)
566 g_free (assist->priv->pre_word);
567 if (pre_word == NULL)
568 pre_word = "";
569 assist->priv->pre_word = g_strdup (pre_word);
572 /* returns TRUE if a '.', "'", or '"' preceeds the cursor position */
573 static gint
574 python_assist_completion_trigger_char (IAnjutaEditor* editor,
575 IAnjutaIterable* cursor)
577 IAnjutaIterable* iter = ianjuta_iterable_clone (cursor, NULL);
578 gboolean retval = FALSE;
579 /* Go backward first as we are behind the current character */
580 if (ianjuta_iterable_previous (iter, NULL))
582 gchar c = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter),
583 0, NULL);
584 retval = ((c == '.') || (c == '\'') || (c == '"'));
586 g_object_unref (iter);
587 return retval;
590 static GList*
591 python_assist_get_calltip_cache (IAnjutaLanguageProvider* self,
592 gchar* call_context,
593 GError** e)
595 PythonAssist* assist = PYTHON_ASSIST (self);
596 if (!g_strcmp0 (call_context, assist->priv->calltip_context))
598 DEBUG_PRINT ("Calltip was found in the cache.");
599 return assist->priv->tips;
601 else
603 DEBUG_PRINT ("Calltip is not available in the cache!");
604 return NULL;
608 static void
609 python_assist_new_calltip (IAnjutaLanguageProvider* self,
610 gchar* call_context,
611 IAnjutaIterable* cursor,
612 GError** e)
614 PythonAssist* assist = PYTHON_ASSIST (self);
615 python_assist_clear_calltip_context (assist);
616 python_assist_create_calltip_context (assist, call_context, cursor);
617 python_assist_query_calltip (assist, call_context);
620 static IAnjutaIterable*
621 python_assist_populate_completions (IAnjutaLanguageProvider* self,
622 IAnjutaIterable* cursor,
623 GError** e)
625 PythonAssist* assist = PYTHON_ASSIST (self);
626 IAnjutaIterable* start_iter = NULL;
627 gchar* pre_word;
628 gboolean completion_trigger_char;
630 pre_word = anjuta_language_provider_get_pre_word (
631 assist->priv->lang_prov,
632 IANJUTA_EDITOR (assist->priv->iassist),
633 cursor, &start_iter, WORD_CHARACTER);
635 DEBUG_PRINT ("Preword: %s", pre_word);
637 /* Check if completion was in progress */
638 if (assist->priv->completion_cache)
640 if (pre_word && g_str_has_prefix (pre_word, assist->priv->pre_word))
642 DEBUG_PRINT ("Continue autocomplete for %s", pre_word);
644 /* Great, we just continue the current completion */
645 python_assist_update_pre_word (assist, pre_word);
646 python_assist_update_autocomplete (assist);
647 g_free (pre_word);
648 return start_iter;
651 else
653 DEBUG_PRINT ("Cancelling autocomplete");
654 python_assist_destroy_completion_cache (assist);
657 /* Autocompletion should not be triggered if we haven't started typing a word unless
658 * we just typed . or ' or "
660 completion_trigger_char = python_assist_completion_trigger_char (
661 IANJUTA_EDITOR (assist->priv->iassist),
662 cursor);
663 if (( (pre_word && strlen (pre_word) >= 3) || completion_trigger_char )
664 && python_assist_create_word_completion_cache (assist, cursor))
666 DEBUG_PRINT ("New autocomplete for %s", pre_word);
667 if (!start_iter)
668 start_iter = ianjuta_iterable_clone (cursor, NULL);
669 python_assist_update_pre_word (assist, pre_word ? pre_word : "");
670 g_free (pre_word);
671 return start_iter;
673 g_free (pre_word);
675 return NULL;
678 static void
679 python_assist_install (PythonAssist *assist,
680 IAnjutaEditor *ieditor)
682 g_return_if_fail (assist->priv->iassist == NULL);
684 if (IANJUTA_IS_EDITOR_ASSIST (ieditor))
686 assist->priv->iassist = IANJUTA_EDITOR_ASSIST (ieditor);
687 ianjuta_editor_assist_add (IANJUTA_EDITOR_ASSIST (ieditor), IANJUTA_PROVIDER(assist), NULL);
688 g_signal_connect (ieditor, "cancelled", G_CALLBACK (python_assist_cancelled), assist);
690 else
691 assist->priv->iassist = NULL;
693 if (IANJUTA_IS_EDITOR_TIP (ieditor))
694 assist->priv->itip = IANJUTA_EDITOR_TIP (ieditor);
695 else
696 assist->priv->itip = NULL;
698 if (IANJUTA_IS_FILE (assist->priv->iassist))
700 GFile *file = ianjuta_file_get_file (IANJUTA_FILE (assist->priv->iassist), NULL);
701 if (file != NULL)
703 assist->priv->editor_filename = g_file_get_path (file);
704 g_object_unref (file);
709 static void
710 python_assist_uninstall (PythonAssist *assist)
712 g_return_if_fail (assist->priv->iassist != NULL);
714 if (IANJUTA_EDITOR_ASSIST (assist->priv->iassist))
716 g_signal_handlers_disconnect_by_func (assist->priv->iassist, python_assist_cancelled, assist);
717 ianjuta_editor_assist_remove (assist->priv->iassist, IANJUTA_PROVIDER(assist), NULL);
720 assist->priv->iassist = NULL;
723 static void
724 python_assist_init (PythonAssist *assist)
726 assist->priv = g_new0 (PythonAssistPriv, 1);
729 static void
730 python_assist_finalize (GObject *object)
732 PythonAssist *assist = PYTHON_ASSIST (object);
733 python_assist_uninstall (assist);
734 python_assist_destroy_completion_cache (assist);
735 python_assist_clear_calltip_context (assist);
736 g_free (assist->priv);
737 G_OBJECT_CLASS (python_assist_parent_class)->finalize (object);
740 static void
741 python_assist_class_init (PythonAssistClass *klass)
743 GObjectClass* object_class = G_OBJECT_CLASS (klass);
745 object_class->finalize = python_assist_finalize;
748 PythonAssist *
749 python_assist_new (IAnjutaEditor *ieditor,
750 IAnjutaSymbolManager *isymbol_manager,
751 GSettings* settings,
752 AnjutaPlugin *plugin,
753 const gchar *project_root)
755 PythonAssist *assist = g_object_new (TYPE_PYTHON_ASSIST, NULL);
756 assist->priv->lang_prov = g_object_new (ANJUTA_TYPE_LANGUAGE_PROVIDER, NULL);
757 assist->priv->settings = settings;
758 assist->priv->plugin = plugin;
759 assist->priv->project_root = project_root;
761 /* Install support */
762 python_assist_install (assist, ieditor);
763 anjuta_language_provider_install (assist->priv->lang_prov, ieditor, settings);
764 return assist;
767 static void
768 python_assist_activate (IAnjutaProvider* self,
769 IAnjutaIterable* iter,
770 gpointer data,
771 GError** e)
773 PythonAssist* assist = PYTHON_ASSIST (self);
774 anjuta_language_provider_activate (assist->priv->lang_prov, self, iter,
775 data);
778 static void
779 python_assist_populate (IAnjutaProvider* self,
780 IAnjutaIterable* cursor,
781 GError** e)
783 PythonAssist* assist = PYTHON_ASSIST (self);
784 anjuta_language_provider_populate (assist->priv->lang_prov, self, cursor);
787 static const gchar*
788 python_assist_get_name (IAnjutaProvider* self,
789 GError** e)
791 return _("Python");
794 static IAnjutaIterable*
795 python_assist_get_start_iter (IAnjutaProvider* self,
796 GError** e)
798 PythonAssist* assist = PYTHON_ASSIST (self);
799 return anjuta_language_provider_get_start_iter (assist->priv->lang_prov);
802 static void
803 iprovider_iface_init (IAnjutaProviderIface* iface)
805 iface->activate = python_assist_activate;
806 iface->populate = python_assist_populate;
807 iface->get_name = python_assist_get_name;
808 iface->get_start_iter = python_assist_get_start_iter;
811 static void
812 ilanguage_provider_iface_init (IAnjutaLanguageProviderIface* iface)
814 iface->get_calltip_cache = python_assist_get_calltip_cache;
815 iface->get_calltip_context = python_assist_get_calltip_context;
816 iface->new_calltip = python_assist_new_calltip;
817 iface->populate_completions = python_assist_populate_completions;