project-wizard: Remove trailing spaces
[anjuta.git] / plugins / language-support-python / python-assist.c
blobcbe399f1f1e3d2d51ed20f152b17570175e51e96
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 DEBUG_PRINT ("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* name = g_match_info_fetch (match_info, 1);
284 gchar* type = g_match_info_fetch (match_info, 3);
285 gchar* location = g_match_info_fetch (match_info, 4);
286 gchar* info = g_match_info_fetch (match_info, 5);
287 tag = anjuta_language_proposal_data_new (name);
289 /* info will be set to "_" if there is no relevant info */
290 tag->info = NULL;
291 if (!g_str_equal(info, "_"))
292 tag->info = g_strdup(info);
295 if (g_str_equal(type, "function") || g_str_equal (type, "builtin"))
297 tag->type = IANJUTA_SYMBOL_TYPE_FUNCTION;
298 tag->is_func = TRUE;
299 /* TODO: not implemented yet */
300 tag->has_para = TRUE;
302 else if (g_str_equal(type, "builder_object"))
304 tag->type = IANJUTA_SYMBOL_TYPE_EXTERNVAR;
305 if (!g_str_equal(location, "_"))
306 tag->info = g_strdup(location);
308 else
309 tag->type = IANJUTA_SYMBOL_TYPE_VARIABLE;
310 g_free (type);
311 g_free (info);
312 g_free (location);
314 if (!g_list_find_custom (suggestions, tag, completion_compare))
316 suggestions = g_list_prepend (suggestions, tag);
318 else
319 anjuta_language_proposal_data_free (tag);
321 g_match_info_free (match_info);
324 g_regex_unref (regex);
325 g_strfreev (completions);
327 g_string_free (assist->priv->rope_cache, TRUE);
328 assist->priv->rope_cache = NULL;
330 assist->priv->completion_cache = g_completion_new (completion_function);
331 g_completion_add_items (assist->priv->completion_cache, suggestions);
332 g_list_free (suggestions);
334 /* Show autocompletion */
335 python_assist_update_autocomplete (assist);
339 static gboolean
340 python_assist_create_word_completion_cache (PythonAssist *assist, IAnjutaIterable* cursor)
342 IAnjutaEditor *editor = IANJUTA_EDITOR (assist->priv->iassist);
343 const gchar *cur_filename;
344 gint offset = ianjuta_iterable_get_position (cursor, NULL);
345 const gchar *project = assist->priv->project_root;
346 gchar *interpreter_path;
347 gchar *ropecommand;
348 GString *builder_file_paths = g_string_new("");
349 GList *project_files_list, *node;
351 gchar *source = ianjuta_editor_get_text_all (editor, NULL);
352 gchar *tmp_file;
354 cur_filename = assist->priv->editor_filename;
355 if (!project)
356 project = g_get_tmp_dir ();
358 /* Create rope command and temporary source file */
359 interpreter_path = g_settings_get_string (assist->priv->settings,
360 PREF_INTERPRETER_PATH);
362 tmp_file = create_tmp_file (source);
363 g_free (source);
365 if (!tmp_file)
366 return FALSE;
368 /* Get a list of all the builder files in the project */
369 IAnjutaProjectManager *manager = anjuta_shell_get_interface (ANJUTA_PLUGIN (assist->priv->plugin)->shell,
370 IAnjutaProjectManager,
371 NULL);
372 project_files_list = ianjuta_project_manager_get_elements (IANJUTA_PROJECT_MANAGER (manager),
373 ANJUTA_PROJECT_SOURCE,
374 NULL);
375 for (node = project_files_list; node != NULL; node = g_list_next (node))
377 gchar *file_path = g_file_get_path (node->data);
378 builder_file_paths = g_string_append (builder_file_paths, FILE_LIST_DELIMITER);
379 builder_file_paths = g_string_append (builder_file_paths, file_path);
380 g_free (file_path);
381 g_object_unref (node->data);
383 g_list_free (project_files_list);
385 ropecommand = g_strdup_printf("%s %s -o autocomplete -p \"%s\" -r \"%s\" -s \"%s\" -f %d -b \"%s\"",
386 interpreter_path, AUTOCOMPLETE_SCRIPT, project,
387 cur_filename, tmp_file, offset, builder_file_paths->str);
388 g_string_free (builder_file_paths, TRUE);
389 g_free (tmp_file);
391 DEBUG_PRINT("%s", ropecommand);
393 /* Exec command and wait for results */
394 assist->priv->launcher = anjuta_launcher_new ();
395 g_signal_connect (assist->priv->launcher, "child-exited",
396 G_CALLBACK(on_autocomplete_finished), assist);
397 anjuta_launcher_execute (assist->priv->launcher, ropecommand,
398 on_autocomplete_output,
399 assist);
400 g_free (ropecommand);
402 assist->priv->cache_position = offset;
404 ianjuta_editor_assist_proposals (IANJUTA_EDITOR_ASSIST (assist->priv->iassist),
405 IANJUTA_PROVIDER (assist), NULL,
406 NULL, FALSE, NULL);
408 return TRUE;
411 static void
412 on_calltip_output (AnjutaLauncher *launcher,
413 AnjutaLauncherOutputType output_type,
414 const gchar *chars,
415 gpointer user_data)
417 PythonAssist* assist = PYTHON_ASSIST (user_data);
418 if (output_type == ANJUTA_LAUNCHER_OUTPUT_STDOUT)
420 if (assist->priv->calltip_cache)
422 g_string_append (assist->priv->calltip_cache, chars);
424 else
426 assist->priv->calltip_cache = g_string_new (chars);
431 static void
432 on_calltip_finished (AnjutaLauncher* launcher,
433 int child_pid, int exit_status,
434 gulong time, gpointer user_data)
436 PythonAssist* assist = PYTHON_ASSIST (user_data);
437 DEBUG_PRINT ("Python-Complete took %lu seconds and returned %d", time, exit_status);
439 g_object_unref (launcher);
440 assist->priv->calltip_launcher = NULL;
442 if (assist->priv->calltip_cache)
444 GString* calltip_text = g_string_new (assist->priv->calltip_cache->str);
445 assist->priv->tips = g_list_prepend (NULL, calltip_text->str);
446 if (g_strncasecmp ("None", assist->priv->tips->data, 4))
448 ianjuta_editor_tip_show (IANJUTA_EDITOR_TIP(assist->priv->itip),
449 assist->priv->tips,
450 assist->priv->calltip_iter,
451 NULL);
453 g_string_free (assist->priv->calltip_cache, TRUE);
454 assist->priv->calltip_cache = NULL;
458 static gint
459 python_assist_get_calltip_context_position (PythonAssist *assist)
461 gchar ch;
462 gint final_offset;
463 IAnjutaEditor *editor = IANJUTA_EDITOR (assist->priv->iassist);
464 IAnjutaIterable *current_iter = ianjuta_editor_get_position (editor, NULL);
466 while (ianjuta_iterable_previous (current_iter, NULL))
468 ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (current_iter), 0, NULL);
469 if (ch == '(')
470 break;
472 final_offset = ianjuta_iterable_get_position (current_iter, NULL);
474 return final_offset-1;
477 static void
478 python_assist_query_calltip (PythonAssist* assist, const gchar *call_context)
480 IAnjutaEditor *editor = IANJUTA_EDITOR (assist->priv->iassist);
482 gint offset = python_assist_get_calltip_context_position (assist);
484 gchar *interpreter_path;
485 const gchar *cur_filename;
486 gchar *source = ianjuta_editor_get_text_all (editor, NULL);
487 const gchar *project = assist->priv->project_root;
488 gchar *tmp_file;
489 gchar *ropecommand;
491 cur_filename = assist->priv->editor_filename;
492 if (!project)
493 project = g_get_tmp_dir ();
495 interpreter_path = g_settings_get_string (assist->priv->settings,
496 PREF_INTERPRETER_PATH);
498 tmp_file = create_tmp_file (source);
499 g_free (source);
501 if (!tmp_file)
502 return;
504 ropecommand = g_strdup_printf("%s %s -o calltip -p \"%s\" -r \"%s\" -s \"%s\" -f %d",
505 interpreter_path, AUTOCOMPLETE_SCRIPT, project,
506 cur_filename, tmp_file, offset);
508 DEBUG_PRINT ("%s", ropecommand);
510 g_free (tmp_file);
512 /* Exec command and wait for results */
513 assist->priv->calltip_launcher = anjuta_launcher_new ();
514 g_signal_connect (assist->priv->calltip_launcher, "child-exited",
515 G_CALLBACK(on_calltip_finished), assist);
516 anjuta_launcher_execute (assist->priv->calltip_launcher, ropecommand,
517 on_calltip_output,
518 assist);
519 g_free (ropecommand);
522 static void
523 python_assist_create_calltip_context (PythonAssist* assist,
524 const gchar* call_context,
525 IAnjutaIterable* position)
527 assist->priv->calltip_context = g_strdup (call_context);
528 assist->priv->calltip_iter = position;
531 static void
532 python_assist_clear_calltip_context (PythonAssist* assist)
534 if (assist->priv->calltip_launcher)
536 g_object_unref (assist->priv->calltip_launcher);
538 assist->priv->calltip_launcher = NULL;
540 g_list_foreach (assist->priv->tips, (GFunc) g_free, NULL);
541 g_list_free (assist->priv->tips);
542 assist->priv->tips = NULL;
544 g_free (assist->priv->calltip_context);
545 assist->priv->calltip_context = NULL;
547 if (assist->priv->calltip_iter)
548 g_object_unref (assist->priv->calltip_iter);
549 assist->priv->calltip_iter = NULL;
552 static gchar*
553 python_assist_get_calltip_context (IAnjutaLanguageProvider *self,
554 IAnjutaIterable *iter,
555 GError** e)
557 PythonAssist* assist = PYTHON_ASSIST (self);
558 gchar* calltip_context;
559 calltip_context = anjuta_language_provider_get_calltip_context (
560 assist->priv->lang_prov, assist->priv->itip, iter,
561 SCOPE_CONTEXT_CHARACTERS);
562 return calltip_context;
565 static void
566 python_assist_update_pre_word (PythonAssist* assist, const gchar* pre_word)
568 g_free (assist->priv->pre_word);
569 if (pre_word == NULL)
570 pre_word = "";
571 assist->priv->pre_word = g_strdup (pre_word);
574 /* returns TRUE if a '.', "'", or '"' preceeds the cursor position */
575 static gint
576 python_assist_completion_trigger_char (IAnjutaEditor* editor,
577 IAnjutaIterable* cursor)
579 IAnjutaIterable* iter = ianjuta_iterable_clone (cursor, NULL);
580 gboolean retval = FALSE;
581 /* Go backward first as we are behind the current character */
582 if (ianjuta_iterable_previous (iter, NULL))
584 gchar c = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter),
585 0, NULL);
586 retval = ((c == '.') || (c == '\'') || (c == '"'));
588 g_object_unref (iter);
589 return retval;
592 static GList*
593 python_assist_get_calltip_cache (IAnjutaLanguageProvider* self,
594 gchar* call_context,
595 GError** e)
597 PythonAssist* assist = PYTHON_ASSIST (self);
598 if (!g_strcmp0 (call_context, assist->priv->calltip_context))
600 DEBUG_PRINT ("Calltip was found in the cache.");
601 return assist->priv->tips;
603 else
605 DEBUG_PRINT ("Calltip is not available in the cache!");
606 return NULL;
610 static void
611 python_assist_new_calltip (IAnjutaLanguageProvider* self,
612 gchar* call_context,
613 IAnjutaIterable* cursor,
614 GError** e)
616 PythonAssist* assist = PYTHON_ASSIST (self);
617 python_assist_clear_calltip_context (assist);
618 python_assist_create_calltip_context (assist, call_context, cursor);
619 python_assist_query_calltip (assist, call_context);
622 static IAnjutaIterable*
623 python_assist_populate_completions (IAnjutaLanguageProvider* self,
624 IAnjutaIterable* cursor,
625 GError** e)
627 PythonAssist* assist = PYTHON_ASSIST (self);
628 IAnjutaIterable* start_iter = NULL;
629 gchar* pre_word;
630 gboolean completion_trigger_char;
632 pre_word = anjuta_language_provider_get_pre_word (
633 assist->priv->lang_prov,
634 IANJUTA_EDITOR (assist->priv->iassist),
635 cursor, &start_iter, WORD_CHARACTER);
637 DEBUG_PRINT ("Preword: %s", pre_word);
639 /* Check if completion was in progress */
640 if (assist->priv->completion_cache)
642 if (pre_word && g_str_has_prefix (pre_word, assist->priv->pre_word))
644 DEBUG_PRINT ("Continue autocomplete for %s", pre_word);
646 /* Great, we just continue the current completion */
647 python_assist_update_pre_word (assist, pre_word);
648 python_assist_update_autocomplete (assist);
649 g_free (pre_word);
650 return start_iter;
653 else
655 DEBUG_PRINT ("Cancelling autocomplete");
656 python_assist_destroy_completion_cache (assist);
659 /* Autocompletion should not be triggered if we haven't started typing a word unless
660 * we just typed . or ' or "
662 completion_trigger_char = python_assist_completion_trigger_char (
663 IANJUTA_EDITOR (assist->priv->iassist),
664 cursor);
665 if (( (pre_word && strlen (pre_word) >= 3) || completion_trigger_char )
666 && python_assist_create_word_completion_cache (assist, cursor))
668 DEBUG_PRINT ("New autocomplete for %s", pre_word);
669 if (!start_iter)
670 start_iter = ianjuta_iterable_clone (cursor, NULL);
671 python_assist_update_pre_word (assist, pre_word ? pre_word : "");
672 g_free (pre_word);
673 return start_iter;
675 g_free (pre_word);
677 return NULL;
680 static void
681 python_assist_install (PythonAssist *assist,
682 IAnjutaEditor *ieditor)
684 g_return_if_fail (assist->priv->iassist == NULL);
686 if (IANJUTA_IS_EDITOR_ASSIST (ieditor))
688 assist->priv->iassist = IANJUTA_EDITOR_ASSIST (ieditor);
689 ianjuta_editor_assist_add (IANJUTA_EDITOR_ASSIST (ieditor), IANJUTA_PROVIDER(assist), NULL);
690 g_signal_connect (ieditor, "cancelled", G_CALLBACK (python_assist_cancelled), assist);
692 else
693 assist->priv->iassist = NULL;
695 if (IANJUTA_IS_EDITOR_TIP (ieditor))
696 assist->priv->itip = IANJUTA_EDITOR_TIP (ieditor);
697 else
698 assist->priv->itip = NULL;
700 if (IANJUTA_IS_FILE (assist->priv->iassist))
702 GFile *file = ianjuta_file_get_file (IANJUTA_FILE (assist->priv->iassist), NULL);
703 if (file != NULL)
705 assist->priv->editor_filename = g_file_get_path (file);
706 g_object_unref (file);
711 static void
712 python_assist_uninstall (PythonAssist *assist)
714 g_return_if_fail (assist->priv->iassist != NULL);
716 if (IANJUTA_EDITOR_ASSIST (assist->priv->iassist))
718 g_signal_handlers_disconnect_by_func (assist->priv->iassist, python_assist_cancelled, assist);
719 ianjuta_editor_assist_remove (assist->priv->iassist, IANJUTA_PROVIDER(assist), NULL);
722 assist->priv->iassist = NULL;
725 static void
726 python_assist_init (PythonAssist *assist)
728 assist->priv = g_new0 (PythonAssistPriv, 1);
731 static void
732 python_assist_finalize (GObject *object)
734 PythonAssist *assist = PYTHON_ASSIST (object);
735 python_assist_uninstall (assist);
736 python_assist_destroy_completion_cache (assist);
737 python_assist_clear_calltip_context (assist);
738 g_free (assist->priv);
739 G_OBJECT_CLASS (python_assist_parent_class)->finalize (object);
742 static void
743 python_assist_class_init (PythonAssistClass *klass)
745 GObjectClass* object_class = G_OBJECT_CLASS (klass);
747 object_class->finalize = python_assist_finalize;
750 PythonAssist *
751 python_assist_new (IAnjutaEditor *ieditor,
752 IAnjutaSymbolManager *isymbol_manager,
753 GSettings* settings,
754 AnjutaPlugin *plugin,
755 const gchar *project_root)
757 PythonAssist *assist = g_object_new (TYPE_PYTHON_ASSIST, NULL);
758 assist->priv->lang_prov = g_object_new (ANJUTA_TYPE_LANGUAGE_PROVIDER, NULL);
759 assist->priv->settings = settings;
760 assist->priv->plugin = plugin;
761 assist->priv->project_root = project_root;
763 /* Install support */
764 python_assist_install (assist, ieditor);
765 anjuta_language_provider_install (assist->priv->lang_prov, ieditor, settings);
766 return assist;
769 static void
770 python_assist_activate (IAnjutaProvider* self,
771 IAnjutaIterable* iter,
772 gpointer data,
773 GError** e)
775 PythonAssist* assist = PYTHON_ASSIST (self);
776 anjuta_language_provider_activate (assist->priv->lang_prov, self, iter,
777 data);
780 static void
781 python_assist_populate (IAnjutaProvider* self,
782 IAnjutaIterable* cursor,
783 GError** e)
785 PythonAssist* assist = PYTHON_ASSIST (self);
786 anjuta_language_provider_populate (assist->priv->lang_prov, self, cursor);
789 static const gchar*
790 python_assist_get_name (IAnjutaProvider* self,
791 GError** e)
793 return _("Python");
796 static IAnjutaIterable*
797 python_assist_get_start_iter (IAnjutaProvider* self,
798 GError** e)
800 PythonAssist* assist = PYTHON_ASSIST (self);
801 return anjuta_language_provider_get_start_iter (assist->priv->lang_prov);
804 static void
805 iprovider_iface_init (IAnjutaProviderIface* iface)
807 iface->activate = python_assist_activate;
808 iface->populate = python_assist_populate;
809 iface->get_name = python_assist_get_name;
810 iface->get_start_iter = python_assist_get_start_iter;
813 static void
814 ilanguage_provider_iface_init (IAnjutaLanguageProviderIface* iface)
816 iface->get_calltip_cache = python_assist_get_calltip_cache;
817 iface->get_calltip_context = python_assist_get_calltip_context;
818 iface->new_calltip = python_assist_new_calltip;
819 iface->populate_completions = python_assist_populate_completions;