27
27
#include <unistd.h>
28
28
#include <glib/gi18n.h>
29
29
#include <libanjuta/anjuta-debug.h>
30
#include <libanjuta/anjuta-language-provider.h>
30
31
#include <libanjuta/anjuta-launcher.h>
32
#include <libanjuta/anjuta-plugin.h>
31
33
#include <libanjuta/anjuta-utils.h>
32
34
#include <libanjuta/interfaces/ianjuta-file.h>
33
35
#include <libanjuta/interfaces/ianjuta-editor.h>
34
36
#include <libanjuta/interfaces/ianjuta-editor-cell.h>
35
#include <libanjuta/interfaces/ianjuta-editor-selection.h>
36
37
#include <libanjuta/interfaces/ianjuta-editor-tip.h>
37
#include <libanjuta/interfaces/ianjuta-document.h>
38
#include <libanjuta/interfaces/ianjuta-language-provider.h>
38
39
#include <libanjuta/interfaces/ianjuta-symbol-manager.h>
39
40
#include <libanjuta/interfaces/ianjuta-symbol.h>
40
#include <libanjuta/interfaces/ianjuta-document-manager.h>
41
#include <libanjuta/interfaces/ianjuta-project-manager.h>
42
#include <libanjuta/anjuta-plugin.h>
41
#include <libanjuta/interfaces/ianjuta-project-manager.h>
43
42
#include "python-assist.h"
45
#define PREF_AUTOCOMPLETE_ENABLE "completion-enable"
46
#define PREF_AUTOCOMPLETE_SPACE_AFTER_FUNC "completion-func-space"
47
#define PREF_AUTOCOMPLETE_BRACE_AFTER_FUNC "completion-func-brace"
48
#define PREF_CALLTIP_ENABLE "calltip-enable"
49
44
#define PREF_INTERPRETER_PATH "interpreter-path"
50
45
#define MAX_COMPLETIONS 30
51
46
#define BRACE_SEARCH_LIMIT 500
56
51
#define AUTOCOMPLETE_REGEX_IN_GET_OBJECT "get_object\\s*\\(\\s*['\"]\\w*$"
57
52
#define FILE_LIST_DELIMITER "|"
60
static void python_assist_iface_init(IAnjutaProviderIface* iface);
62
//G_DEFINE_TYPE (PythonAssist, python_assist, G_TYPE_OBJECT);
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);
63
59
G_DEFINE_TYPE_WITH_CODE (PythonAssist,
66
G_IMPLEMENT_INTERFACE (IANJUTA_TYPE_PROVIDER,
67
python_assist_iface_init))
74
IAnjutaSymbolType type;
62
G_IMPLEMENT_INTERFACE (IANJUTA_TYPE_PROVIDER,
64
G_IMPLEMENT_INTERFACE (IANJUTA_TYPE_LANGUAGE_PROVIDER,
65
ilanguage_provider_iface_init))
77
67
struct _PythonAssistPriv {
78
68
GSettings* settings;
79
IAnjutaSymbolManager* isymbol_manager;
80
IAnjutaDocumentManager* idocument_manager;
81
69
IAnjutaEditorAssist* iassist;
82
70
IAnjutaEditorTip* itip;
83
IAnjutaEditor* editor;
71
AnjutaLanguageProvider* lang_prov;
84
72
AnjutaLauncher* launcher;
85
73
AnjutaLauncher* calltip_launcher;
86
74
AnjutaPlugin* plugin;
89
77
const gchar* editor_filename;
91
79
/* Autocompletion */
80
GCompletion *completion_cache;
95
GCompletion *completion_cache;
96
83
gint cache_position;
97
84
GString* rope_cache;
98
IAnjutaIterable* start_iter;
87
gchar* calltip_context;
88
IAnjutaIterable* calltip_iter;
101
90
GString* calltip_cache;
102
gchar *calltip_context;
103
gint calltip_context_position;
105
IAnjutaIterable* calltip_iter;
109
94
completion_function (gpointer data)
111
PythonAssistTag * tag = (PythonAssistTag*) data;
96
AnjutaLanguageProposalData * tag = ANJUTA_LANGUAGE_PROPOSAL_DATA(data);
116
101
completion_compare (gconstpointer a, gconstpointer b)
118
PythonAssistTag * tag_a = (PythonAssistTag*) a;
119
PythonAssistTag * tag_b = (PythonAssistTag*) b;
103
AnjutaLanguageProposalData * tag_a = ANJUTA_LANGUAGE_PROPOSAL_DATA(a);
104
AnjutaLanguageProposalData * tag_b = ANJUTA_LANGUAGE_PROPOSAL_DATA(b);
122
107
cmp = strcmp (tag_a->name, tag_b->name);
129
python_assist_tag_destroy (PythonAssistTag *tag)
136
is_scope_context_character (gchar ch)
138
if (g_ascii_isspace (ch))
140
if (g_ascii_isalnum (ch))
149
python_assist_get_scope_context (IAnjutaEditor* editor,
150
const gchar *scope_operator,
151
IAnjutaIterable *iter)
153
IAnjutaIterable* end;
154
gchar ch, *scope_chars = NULL;
155
gboolean out_of_range = FALSE;
156
gboolean scope_chars_found = FALSE;
158
end = ianjuta_iterable_clone (iter, NULL);
159
ianjuta_iterable_next (end, NULL);
161
ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
165
if (is_scope_context_character (ch))
167
scope_chars_found = TRUE;
171
if (!anjuta_util_jump_to_matching_brace (iter, ch, SCOPE_BRACE_JUMP_LIMIT))
179
if (!ianjuta_iterable_previous (iter, NULL))
184
ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
186
if (scope_chars_found)
188
IAnjutaIterable* begin;
189
begin = ianjuta_iterable_clone (iter, NULL);
191
ianjuta_iterable_next (begin, NULL);
192
scope_chars = ianjuta_editor_get_text (editor, begin, end, NULL);
193
g_object_unref (begin);
195
g_object_unref (end);
200
python_assist_is_word_character (gchar ch)
202
if (g_ascii_isspace (ch))
204
if (g_ascii_isalnum (ch))
213
python_assist_get_pre_word (IAnjutaEditor* editor, IAnjutaIterable *iter, IAnjutaIterable** start_iter)
215
IAnjutaIterable *end = ianjuta_iterable_clone (iter, NULL);
216
IAnjutaIterable *begin = ianjuta_iterable_clone (iter, NULL);
217
gchar ch, *preword_chars = NULL;
218
gboolean out_of_range = FALSE;
219
gboolean preword_found = FALSE;
221
/* Cursor points after the current characters, move back */
222
ianjuta_iterable_previous (begin, NULL);
224
ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (begin), 0, NULL);
226
while (ch && python_assist_is_word_character (ch))
228
preword_found = TRUE;
229
if (!ianjuta_iterable_previous (begin, NULL))
234
ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (begin), 0, NULL);
240
ianjuta_iterable_next (begin, NULL);
241
preword_chars = ianjuta_editor_get_text (editor, begin, end, NULL);
246
g_object_unref (begin);
250
g_object_unref (end);
251
return preword_chars;
114
python_assist_tag_destroy (AnjutaLanguageProposalData *tag)
116
anjuta_language_proposal_data_free (tag);
323
183
suggestions = g_list_prepend (suggestions, proposal);
325
185
suggestions = g_list_reverse (suggestions);
326
/* Hide if the only suggetions is exactly the typed word */
327
if (!(g_list_length (suggestions) == 1 &&
328
g_str_equal (((PythonAssistTag*)(suggestions->data))->name, assist->priv->pre_word)))
330
ianjuta_editor_assist_proposals (assist->priv->iassist, IANJUTA_PROVIDER(assist),
331
suggestions, TRUE, NULL);
334
ianjuta_editor_assist_proposals (assist->priv->iassist, IANJUTA_PROVIDER(assist),
187
ianjuta_editor_assist_proposals (IANJUTA_EDITOR_ASSIST (assist->priv->iassist),
188
IANJUTA_PROVIDER(assist), suggestions,
189
assist->priv->pre_word, TRUE, NULL);
336
191
g_list_foreach (suggestions, (GFunc) free_proposal, NULL);
337
192
g_list_free (suggestions);
546
399
g_free (ropecommand);
548
401
assist->priv->cache_position = offset;
549
assist->priv->search_cache = g_strdup (assist->priv->pre_word);
551
403
ianjuta_editor_assist_proposals (IANJUTA_EDITOR_ASSIST (assist->priv->iassist),
552
IANJUTA_PROVIDER (assist),
404
IANJUTA_PROVIDER (assist), NULL,
553
405
NULL, FALSE, NULL);
559
python_assist_create_calltip_context (PythonAssist* assist,
560
const gchar* call_context,
561
gint call_context_position,
562
IAnjutaIterable* position)
564
assist->priv->calltip_context = g_strdup (call_context);
565
assist->priv->calltip_context_position = call_context_position;
566
assist->priv->calltip_iter = position;
570
411
on_calltip_output (AnjutaLauncher *launcher,
571
412
AnjutaLauncherOutputType output_type,
600
441
if (assist->priv->calltip_cache)
602
GList* tips = g_list_prepend (NULL, assist->priv->calltip_cache->str);
603
ianjuta_editor_tip_show (IANJUTA_EDITOR_TIP(assist->priv->itip), tips,
604
assist->priv->calltip_iter,
443
GString* calltip_text = g_string_new (assist->priv->calltip_cache->str);
444
assist->priv->tips = g_list_prepend (NULL, calltip_text->str);
445
if (g_strncasecmp ("None", assist->priv->tips->data, 4))
447
ianjuta_editor_tip_show (IANJUTA_EDITOR_TIP(assist->priv->itip),
449
assist->priv->calltip_iter,
607
452
g_string_free (assist->priv->calltip_cache, TRUE);
608
453
assist->priv->calltip_cache = NULL;
458
python_assist_get_calltip_context_position (PythonAssist *assist)
462
IAnjutaEditor *editor = IANJUTA_EDITOR (assist->priv->iassist);
463
IAnjutaIterable *current_iter = ianjuta_editor_get_position (editor, NULL);
465
while (ianjuta_iterable_previous (current_iter, NULL))
467
ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (current_iter), 0, NULL);
471
final_offset = ianjuta_iterable_get_position (current_iter, NULL);
473
return final_offset-1;
613
python_assist_query_calltip (PythonAssist *assist, const gchar *call_context)
477
python_assist_query_calltip (PythonAssist* assist, const gchar *call_context)
615
479
IAnjutaEditor *editor = IANJUTA_EDITOR (assist->priv->iassist);
616
gint offset = assist->priv->calltip_context_position;
481
gint offset = python_assist_get_calltip_context_position (assist);
617
483
gchar *interpreter_path;
618
484
const gchar *cur_filename;
619
485
gchar *source = ianjuta_editor_get_text_all (editor, NULL);
662
537
assist->priv->calltip_launcher = NULL;
664
g_free (assist->priv->calltip_context);
665
assist->priv->calltip_context = NULL;
667
539
g_list_foreach (assist->priv->tips, (GFunc) g_free, NULL);
668
540
g_list_free (assist->priv->tips);
669
541
assist->priv->tips = NULL;
543
g_free (assist->priv->calltip_context);
544
assist->priv->calltip_context = NULL;
671
546
if (assist->priv->calltip_iter)
672
547
g_object_unref (assist->priv->calltip_iter);
673
548
assist->priv->calltip_iter = NULL;
678
python_assist_get_calltip_context (PythonAssist *assist,
679
IAnjutaIterable *iter)
682
gchar *context = NULL;
683
gint original_offset = ianjuta_editor_get_offset (IANJUTA_EDITOR (assist->priv->iassist), NULL);
685
ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
688
if (!anjuta_util_jump_to_matching_brace (iter, ')', -1))
690
if (!ianjuta_iterable_previous (iter, NULL))
695
if (!anjuta_util_jump_to_matching_brace (iter, ')',
700
/* Skip white spaces */
701
while (ianjuta_iterable_previous (iter, NULL)
702
&& g_ascii_isspace (ianjuta_editor_cell_get_char
703
(IANJUTA_EDITOR_CELL (iter), 0, NULL)))
706
context = python_assist_get_scope_context
707
(IANJUTA_EDITOR (assist->priv->iassist), "(", iter);
709
/* Point iter to the first character of the scope to align calltip correctly */
710
ianjuta_iterable_next (iter, NULL);
716
python_assist_get_calltip_context_position (PythonAssist *assist,
717
IAnjutaIterable *iter)
721
IAnjutaEditor *editor = IANJUTA_EDITOR (assist->priv->iassist);
722
IAnjutaIterable *current_iter = ianjuta_editor_get_position (editor, NULL);
724
while (ianjuta_iterable_previous (current_iter, NULL))
726
ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (current_iter), 0, NULL);
730
final_offset = ianjuta_iterable_get_position (current_iter, NULL);
732
return final_offset-1;
736
python_assist_calltip (PythonAssist *assist)
738
IAnjutaEditor *editor;
739
IAnjutaIterable *iter;
741
gint call_context_position;
743
editor = IANJUTA_EDITOR (assist->priv->iassist);
745
iter = ianjuta_editor_get_position (editor, NULL);
746
ianjuta_iterable_previous (iter, NULL);
748
call_context = python_assist_get_calltip_context (assist, iter);
749
call_context_position = python_assist_get_calltip_context_position (assist, iter);
753
DEBUG_PRINT ("Searching calltip for: %s", call_context);
754
if (assist->priv->calltip_context &&
755
g_str_equal (call_context, assist->priv->calltip_context))
758
if (assist->priv->tips)
760
if (!ianjuta_editor_tip_visible (IANJUTA_EDITOR_TIP (editor), NULL))
762
ianjuta_editor_tip_show (IANJUTA_EDITOR_TIP (editor),
764
assist->priv->calltip_iter, NULL);
767
g_free (call_context);
772
if (ianjuta_editor_tip_visible (IANJUTA_EDITOR_TIP (editor), NULL))
773
ianjuta_editor_tip_cancel (IANJUTA_EDITOR_TIP (editor), NULL);
775
python_assist_clear_calltip_context (assist);
776
python_assist_create_calltip_context (assist, call_context, call_context_position, iter);
777
python_assist_query_calltip (assist, call_context);
778
g_free (call_context);
784
if (ianjuta_editor_tip_visible (IANJUTA_EDITOR_TIP (editor), NULL))
785
ianjuta_editor_tip_cancel (IANJUTA_EDITOR_TIP (editor), NULL);
786
python_assist_clear_calltip_context (assist);
789
g_object_unref (iter);
552
python_assist_get_calltip_context (IAnjutaLanguageProvider *self,
553
IAnjutaIterable *iter,
556
PythonAssist* assist = PYTHON_ASSIST (self);
557
gchar* calltip_context;
558
calltip_context = anjuta_language_provider_get_calltip_context (
559
assist->priv->lang_prov, assist->priv->itip, iter,
560
SCOPE_CONTEXT_CHARACTERS);
561
return calltip_context;
592
python_assist_get_calltip_cache (IAnjutaLanguageProvider* self,
596
PythonAssist* assist = PYTHON_ASSIST (self);
597
if (!g_strcmp0 (call_context, assist->priv->calltip_context))
599
DEBUG_PRINT ("Calltip was found in the cache.");
600
return assist->priv->tips;
604
DEBUG_PRINT ("Calltip is not available in the cache!");
830
python_assist_populate (IAnjutaProvider* self, IAnjutaIterable* cursor, GError** e)
610
python_assist_new_calltip (IAnjutaLanguageProvider* self,
612
IAnjutaIterable* cursor,
615
PythonAssist* assist = PYTHON_ASSIST (self);
616
python_assist_clear_calltip_context (assist);
617
python_assist_create_calltip_context (assist, call_context, cursor);
618
python_assist_query_calltip (assist, call_context);
621
static IAnjutaIterable*
622
python_assist_populate_completions (IAnjutaLanguageProvider* self,
623
IAnjutaIterable* cursor,
832
626
PythonAssist* assist = PYTHON_ASSIST (self);
833
627
IAnjutaIterable* start_iter = NULL;
835
629
gboolean completion_trigger_char;
837
/* Check for calltip */
838
if (assist->priv->itip &&
839
g_settings_get_boolean (assist->priv->settings,
840
PREF_CALLTIP_ENABLE))
842
python_assist_calltip (assist);
845
/* Check if we actually want autocompletion at all */
846
if (!g_settings_get_boolean (assist->priv->settings,
847
PREF_AUTOCOMPLETE_ENABLE))
849
python_assist_none (self, assist);
853
/* Check if this is a valid text region for completion */
854
IAnjutaEditorAttribute attrib = ianjuta_editor_cell_get_attribute (IANJUTA_EDITOR_CELL(cursor),
856
if (attrib == IANJUTA_EDITOR_COMMENT)
858
python_assist_none (self, assist);
862
pre_word = python_assist_get_pre_word (IANJUTA_EDITOR (assist->priv->iassist), cursor, &start_iter);
631
pre_word = anjuta_language_provider_get_pre_word (
632
assist->priv->lang_prov,
633
IANJUTA_EDITOR (assist->priv->iassist),
634
cursor, &start_iter, WORD_CHARACTER);
864
636
DEBUG_PRINT ("Preword: %s", pre_word);
889
658
/* Autocompletion should not be triggered if we haven't started typing a word unless
890
659
* we just typed . or ' or "
892
completion_trigger_char = python_assist_completion_trigger_char (IANJUTA_EDITOR (assist->priv->iassist),
894
if ( (( (pre_word && strlen (pre_word) >= 3) || completion_trigger_char ) &&
895
python_assist_create_word_completion_cache (assist, cursor)) )
661
completion_trigger_char = python_assist_completion_trigger_char (
662
IANJUTA_EDITOR (assist->priv->iassist),
664
if (( (pre_word && strlen (pre_word) >= 3) || completion_trigger_char )
665
&& python_assist_create_word_completion_cache (assist, cursor))
897
667
DEBUG_PRINT ("New autocomplete for %s", pre_word);
898
if (assist->priv->start_iter)
899
g_object_unref (assist->priv->start_iter);
901
assist->priv->start_iter = start_iter;
903
assist->priv->start_iter = ianjuta_iterable_clone (cursor, NULL);
669
start_iter = ianjuta_iterable_clone (cursor, NULL);
904
670
python_assist_update_pre_word (assist, pre_word ? pre_word : "");
905
671
g_free (pre_word);
908
/* Nothing to propose */
909
if (assist->priv->start_iter)
911
g_object_unref (assist->priv->start_iter);
912
assist->priv->start_iter = NULL;
914
python_assist_none (self, assist);
915
674
g_free (pre_word);
921
python_assist_activate (IAnjutaProvider* self, IAnjutaIterable* iter, gpointer data, GError** e)
923
PythonAssist* assist = PYTHON_ASSIST(self);
924
PythonAssistTag *tag;
927
gboolean add_space_after_func = FALSE;
928
gboolean add_brace_after_func = FALSE;
931
assistance = g_string_new (tag->name);
935
add_space_after_func =
936
g_settings_get_boolean (assist->priv->settings,
937
PREF_AUTOCOMPLETE_SPACE_AFTER_FUNC);
938
add_brace_after_func =
939
g_settings_get_boolean (assist->priv->settings,
940
PREF_AUTOCOMPLETE_BRACE_AFTER_FUNC);
941
if (add_space_after_func)
942
g_string_append (assistance, " ");
944
if (add_brace_after_func)
945
g_string_append (assistance, "(");
948
te = IANJUTA_EDITOR (assist->priv->iassist);
950
ianjuta_document_begin_undo_action (IANJUTA_DOCUMENT (te), NULL);
952
if (ianjuta_iterable_compare(iter, assist->priv->start_iter, NULL) != 0)
954
ianjuta_editor_selection_set (IANJUTA_EDITOR_SELECTION (te),
955
assist->priv->start_iter, iter, FALSE, NULL);
956
ianjuta_editor_selection_replace (IANJUTA_EDITOR_SELECTION (te),
957
assistance->str, -1, NULL);
961
ianjuta_editor_insert (te, iter, assistance->str, -1, NULL);
963
ianjuta_document_end_undo_action (IANJUTA_DOCUMENT (te), NULL);
965
/* Show calltip if we completed function */
966
if (add_brace_after_func)
967
python_assist_calltip (assist);
969
g_string_free (assistance, TRUE);
972
static IAnjutaIterable*
973
python_assist_get_start_iter (IAnjutaProvider* provider, GError** e)
975
PythonAssist* assist = PYTHON_ASSIST (provider);
976
return assist->priv->start_iter;
980
python_assist_get_name (IAnjutaProvider* provider, GError** e)
986
python_assist_install (PythonAssist *assist, IAnjutaEditor *ieditor)
680
python_assist_install (PythonAssist *assist,
681
IAnjutaEditor *ieditor)
988
683
g_return_if_fail (assist->priv->iassist == NULL);
1051
python_assist_new (IAnjutaEditorAssist *iassist,
750
python_assist_new (IAnjutaEditor *ieditor,
1052
751
IAnjutaSymbolManager *isymbol_manager,
1053
IAnjutaDocumentManager *idocument_manager,
1054
753
AnjutaPlugin *plugin,
1055
GSettings* settings,
1056
const gchar *editor_filename,
1057
754
const gchar *project_root)
1059
756
PythonAssist *assist = g_object_new (TYPE_PYTHON_ASSIST, NULL);
1060
assist->priv->isymbol_manager = isymbol_manager;
1061
assist->priv->idocument_manager = idocument_manager;
1062
assist->priv->editor_filename = editor_filename;
757
assist->priv->lang_prov = g_object_new (ANJUTA_TYPE_LANGUAGE_PROVIDER, NULL);
1063
758
assist->priv->settings = settings;
759
assist->priv->plugin = plugin;
1064
760
assist->priv->project_root = project_root;
1065
assist->priv->editor = (IAnjutaEditor*)iassist;
1066
assist->priv->plugin = plugin;
1067
python_assist_install (assist, IANJUTA_EDITOR (iassist));
762
/* Install support */
763
python_assist_install (assist, ieditor);
764
anjuta_language_provider_install (assist->priv->lang_prov, ieditor, settings);
1071
static void python_assist_iface_init(IAnjutaProviderIface* iface)
1073
iface->populate = python_assist_populate;
1074
iface->get_start_iter = python_assist_get_start_iter;
1075
iface->activate = python_assist_activate;
1076
iface->get_name = python_assist_get_name;
769
python_assist_activate (IAnjutaProvider* self,
770
IAnjutaIterable* iter,
774
PythonAssist* assist = PYTHON_ASSIST (self);
775
anjuta_language_provider_activate (assist->priv->lang_prov, self, iter,
780
python_assist_populate (IAnjutaProvider* self,
781
IAnjutaIterable* cursor,
784
PythonAssist* assist = PYTHON_ASSIST (self);
785
anjuta_language_provider_populate (assist->priv->lang_prov, self, cursor);
789
python_assist_get_name (IAnjutaProvider* self,
795
static IAnjutaIterable*
796
python_assist_get_start_iter (IAnjutaProvider* self,
799
PythonAssist* assist = PYTHON_ASSIST (self);
800
return anjuta_language_provider_get_start_iter (assist->priv->lang_prov);
804
iprovider_iface_init (IAnjutaProviderIface* iface)
806
iface->activate = python_assist_activate;
807
iface->populate = python_assist_populate;
808
iface->get_name = python_assist_get_name;
809
iface->get_start_iter = python_assist_get_start_iter;
813
ilanguage_provider_iface_init (IAnjutaLanguageProviderIface* iface)
815
iface->get_calltip_cache = python_assist_get_calltip_cache;
816
iface->get_calltip_context = python_assist_get_calltip_context;
817
iface->new_calltip = python_assist_new_calltip;
818
iface->populate_completions = python_assist_populate_completions;