~ubuntu-branches/ubuntu/trusty/anjuta/trusty

« back to all changes in this revision

Viewing changes to plugins/language-support-python/python-assist.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2012-08-17 23:48:26 UTC
  • mfrom: (1.1.50)
  • Revision ID: package-import@ubuntu.com-20120817234826-fvk3rfp6nmfaqi9p
Tags: 2:3.5.5-0ubuntu1
* New upstream release.
* debian/control.in:
  - Bump vala dependency to 0.18 series
  - Drop graphviz from build-depends
* debian/watch: Watch for unstable releases

Show diffs side-by-side

added added

removed removed

Lines of Context:
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"
44
43
 
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
55
50
 
56
51
#define AUTOCOMPLETE_REGEX_IN_GET_OBJECT "get_object\\s*\\(\\s*['\"]\\w*$"
57
52
#define FILE_LIST_DELIMITER "|"
58
 
 
59
 
 
60
 
static void python_assist_iface_init(IAnjutaProviderIface* iface);
61
 
 
62
 
//G_DEFINE_TYPE (PythonAssist, python_assist, G_TYPE_OBJECT);
 
53
#define SCOPE_CONTEXT_CHARACTERS ".0"
 
54
#define WORD_CHARACTER "_0"
 
55
 
 
56
static void iprovider_iface_init(IAnjutaProviderIface* iface);
 
57
static void ilanguage_provider_iface_init(IAnjutaLanguageProviderIface* iface);
 
58
 
63
59
G_DEFINE_TYPE_WITH_CODE (PythonAssist,
64
 
                         python_assist,
65
 
                         G_TYPE_OBJECT,
66
 
                         G_IMPLEMENT_INTERFACE (IANJUTA_TYPE_PROVIDER,
67
 
                                                python_assist_iface_init))
68
 
 
69
 
typedef struct
70
 
{
71
 
        gchar *name;
72
 
        gchar *info;
73
 
        gboolean is_func;
74
 
        IAnjutaSymbolType type;
75
 
} PythonAssistTag;
 
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))
76
66
 
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;
90
78
        
91
79
        /* Autocompletion */
92
 
        gchar *search_cache;
 
80
        GCompletion *completion_cache;
93
81
        gchar *pre_word;
94
82
        
95
 
        GCompletion *completion_cache;
96
83
        gint cache_position;
97
84
        GString* rope_cache;
98
 
        IAnjutaIterable* start_iter;
99
85
 
100
86
        /* Calltips */
 
87
        gchar* calltip_context;
 
88
        IAnjutaIterable* calltip_iter;
 
89
        GList* tips;
101
90
        GString* calltip_cache;
102
 
        gchar *calltip_context;
103
 
        gint calltip_context_position;
104
 
        GList *tips;
105
 
        IAnjutaIterable* calltip_iter;
106
91
};
107
92
 
108
93
static gchar*
109
94
completion_function (gpointer data)
110
95
{
111
 
        PythonAssistTag * tag = (PythonAssistTag*) data;
 
96
        AnjutaLanguageProposalData * tag = ANJUTA_LANGUAGE_PROPOSAL_DATA(data);
112
97
        return tag->name;
113
98
}
114
99
 
115
100
static gint 
116
101
completion_compare (gconstpointer a, gconstpointer b)
117
102
{
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);
120
105
        gint cmp;
121
106
        
122
107
        cmp = strcmp (tag_a->name, tag_b->name);
126
111
}
127
112
 
128
113
static void 
129
 
python_assist_tag_destroy (PythonAssistTag *tag)
130
 
{
131
 
        g_free (tag->name);
132
 
        g_free (tag);
133
 
}
134
 
 
135
 
static gboolean 
136
 
is_scope_context_character (gchar ch)
137
 
{
138
 
        if (g_ascii_isspace (ch))
139
 
                return FALSE;
140
 
        if (g_ascii_isalnum (ch))
141
 
                return TRUE;
142
 
        if (ch == '.')
143
 
                return TRUE;
144
 
        
145
 
        return FALSE;
146
 
}
147
 
 
148
 
static gchar* 
149
 
python_assist_get_scope_context (IAnjutaEditor* editor,
150
 
                                 const gchar *scope_operator,
151
 
                                 IAnjutaIterable *iter)
152
 
{
153
 
        IAnjutaIterable* end;
154
 
        gchar ch, *scope_chars = NULL;
155
 
        gboolean out_of_range = FALSE;
156
 
        gboolean scope_chars_found = FALSE;
157
 
        
158
 
        end = ianjuta_iterable_clone (iter, NULL);
159
 
        ianjuta_iterable_next (end, NULL);
160
 
        
161
 
        ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
162
 
        
163
 
        while (ch)
164
 
        {
165
 
                if (is_scope_context_character (ch))
166
 
                {
167
 
                        scope_chars_found = TRUE;
168
 
                }
169
 
                else if (ch == ')')
170
 
                {
171
 
                        if (!anjuta_util_jump_to_matching_brace (iter, ch, SCOPE_BRACE_JUMP_LIMIT))
172
 
                        {
173
 
                                out_of_range = TRUE;
174
 
                                break;
175
 
                        }
176
 
                }
177
 
                else
178
 
                        break;
179
 
                if (!ianjuta_iterable_previous (iter, NULL))
180
 
                {
181
 
                        out_of_range = TRUE;
182
 
                        break;
183
 
                }               
184
 
                ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
185
 
        }
186
 
        if (scope_chars_found)
187
 
        {
188
 
                IAnjutaIterable* begin;
189
 
                begin = ianjuta_iterable_clone (iter, NULL);
190
 
                if (!out_of_range)
191
 
                        ianjuta_iterable_next (begin, NULL);
192
 
                scope_chars = ianjuta_editor_get_text (editor, begin, end, NULL);
193
 
                g_object_unref (begin);
194
 
        }
195
 
        g_object_unref (end);
196
 
        return scope_chars;
197
 
}
198
 
 
199
 
static gboolean
200
 
python_assist_is_word_character (gchar ch)
201
 
{
202
 
        if (g_ascii_isspace (ch))
203
 
                return FALSE;
204
 
        if (g_ascii_isalnum (ch))
205
 
                return TRUE;
206
 
        if (ch == '_')
207
 
                return TRUE;
208
 
        
209
 
        return FALSE;
210
 
}       
211
 
 
212
 
static gchar*
213
 
python_assist_get_pre_word (IAnjutaEditor* editor, IAnjutaIterable *iter, IAnjutaIterable** start_iter)
214
 
{
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;
220
 
        
221
 
        /* Cursor points after the current characters, move back */
222
 
        ianjuta_iterable_previous (begin, NULL);
223
 
        
224
 
        ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (begin), 0, NULL);
225
 
        
226
 
        while (ch && python_assist_is_word_character (ch))
227
 
        {
228
 
                preword_found = TRUE;
229
 
                if (!ianjuta_iterable_previous (begin, NULL))
230
 
                {
231
 
                        out_of_range = TRUE;
232
 
                        break;
233
 
                }
234
 
                ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (begin), 0, NULL);
235
 
        }
236
 
        
237
 
        if (preword_found)
238
 
        {
239
 
                if (!out_of_range)
240
 
                        ianjuta_iterable_next (begin, NULL);
241
 
                preword_chars = ianjuta_editor_get_text (editor, begin, end, NULL);
242
 
                *start_iter = begin;
243
 
        }
244
 
        else
245
 
        {
246
 
                g_object_unref (begin);
247
 
                *start_iter = NULL;
248
 
        }
249
 
        
250
 
        g_object_unref (end);
251
 
        return preword_chars;
 
114
python_assist_tag_destroy (AnjutaLanguageProposalData *tag)
 
115
{
 
116
        anjuta_language_proposal_data_free (tag);
252
117
}
253
118
 
254
119
static void
265
130
python_assist_destroy_completion_cache (PythonAssist *assist)
266
131
{
267
132
        python_assist_cancel_queries (assist);
268
 
        if (assist->priv->search_cache)
269
 
        {
270
 
                g_free (assist->priv->search_cache);
271
 
                assist->priv->search_cache = NULL;
272
 
        }
273
133
        if (assist->priv->completion_cache)
274
134
        {
275
135
                GList* items = assist->priv->completion_cache->items;
309
169
        
310
170
        for (node = completion_list; node != NULL; node = g_list_next (node))
311
171
        {
312
 
                PythonAssistTag *tag = node->data;
 
172
                AnjutaLanguageProposalData *tag = ANJUTA_LANGUAGE_PROPOSAL_DATA(node->data);
313
173
                IAnjutaEditorAssistProposal* proposal = g_new0(IAnjutaEditorAssistProposal, 1);
314
174
 
315
175
                if (tag->is_func)
323
183
                suggestions = g_list_prepend (suggestions, proposal);
324
184
        }
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)))
329
 
        {
330
 
                ianjuta_editor_assist_proposals (assist->priv->iassist, IANJUTA_PROVIDER(assist),
331
 
                                                 suggestions, TRUE, NULL);
332
 
        }
333
 
        else
334
 
                ianjuta_editor_assist_proposals (assist->priv->iassist, IANJUTA_PROVIDER(assist),
335
 
                                                 NULL, TRUE, NULL);             
 
186
        
 
187
        ianjuta_editor_assist_proposals (IANJUTA_EDITOR_ASSIST (assist->priv->iassist),
 
188
                                         IANJUTA_PROVIDER(assist), suggestions,
 
189
                                         assist->priv->pre_word, TRUE, NULL);
 
190
        
336
191
        g_list_foreach (suggestions, (GFunc) free_proposal, NULL);
337
192
        g_list_free (suggestions);
338
193
}
354
209
                        fprintf (rope_file, "%s", source);
355
210
                        fclose (rope_file);
356
211
                        close (tmp_fd);
 
212
                        return tmp_file;
357
213
                }
358
 
                else
359
 
                        goto error;
360
 
                return tmp_file;
361
214
        }
362
215
 
363
 
error:
 
216
        /* Error */
364
217
        g_warning ("Creating tmp_file failed: %s", err->message);
365
218
        g_error_free (err);
366
219
        return NULL;
420
273
                /* Parse output and create completion list */
421
274
                for (cur_comp = completions; *cur_comp != NULL; cur_comp++)
422
275
                {
423
 
                        PythonAssistTag* tag;
 
276
                        AnjutaLanguageProposalData* tag;
424
277
                        GMatchInfo* match_info;
425
278
                        
426
279
                        g_regex_match (regex, *cur_comp, 0, &match_info);
430
283
                                gchar* type = g_match_info_fetch (match_info, 3); 
431
284
                                gchar* location = g_match_info_fetch (match_info, 4); 
432
285
                                gchar* info = g_match_info_fetch (match_info, 5); 
433
 
                                tag = g_new0 (PythonAssistTag, 1);
434
 
                                tag->name = g_match_info_fetch (match_info, 1);
 
286
                                tag = anjuta_language_proposal_data_new (g_match_info_fetch (match_info, 1));
435
287
 
436
288
                                /* info will be set to "_" if there is no relevant info */
437
289
                                tag->info = NULL; 
443
295
                                {
444
296
                                        tag->type = IANJUTA_SYMBOL_TYPE_FUNCTION;
445
297
                                        tag->is_func = TRUE;
 
298
                                        /* TODO: not implemented yet */
 
299
                                        tag->has_para = TRUE;
446
300
                                }
447
301
                                else if (g_str_equal(type, "builder_object"))
448
302
                                {
530
384
        ropecommand = g_strdup_printf("%s %s -o autocomplete -p \"%s\" -r \"%s\" -s \"%s\" -f %d -b \"%s\"", 
531
385
                                      interpreter_path, AUTOCOMPLETE_SCRIPT, project, 
532
386
                                      cur_filename, tmp_file, offset, builder_file_paths->str);
533
 
 
534
387
        g_string_free (builder_file_paths, TRUE);
535
388
        g_free (tmp_file);
536
389
 
546
399
        g_free (ropecommand);
547
400
 
548
401
        assist->priv->cache_position = offset;
549
 
        assist->priv->search_cache = g_strdup (assist->priv->pre_word);
550
 
 
 
402
        
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);
554
406
        
555
407
        return TRUE;
556
408
}
557
409
 
558
 
static void
559
 
python_assist_create_calltip_context (PythonAssist* assist,
560
 
                                      const gchar* call_context,
561
 
                                      gint call_context_position,                                      
562
 
                                      IAnjutaIterable* position)
563
 
{
564
 
        assist->priv->calltip_context = g_strdup (call_context);
565
 
        assist->priv->calltip_context_position = call_context_position;
566
 
        assist->priv->calltip_iter = position;
567
 
}
568
 
 
569
410
static void 
570
411
on_calltip_output (AnjutaLauncher *launcher,
571
412
                   AnjutaLauncherOutputType output_type,
588
429
 
589
430
static void
590
431
on_calltip_finished (AnjutaLauncher* launcher,
591
 
                          int child_pid, int exit_status,
592
 
                          gulong time, gpointer user_data)
 
432
                     int child_pid, int exit_status,
 
433
                     gulong time, gpointer user_data)
593
434
{
594
435
        PythonAssist* assist = PYTHON_ASSIST (user_data);
595
436
        DEBUG_PRINT ("Python-Complete took %lu seconds and returned %d", time, exit_status);
599
440
 
600
441
        if (assist->priv->calltip_cache)
601
442
        {
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, 
605
 
                                         NULL);
606
 
                g_list_free (tips);
 
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))
 
446
                {
 
447
                        ianjuta_editor_tip_show (IANJUTA_EDITOR_TIP(assist->priv->itip),
 
448
                                                     assist->priv->tips,
 
449
                                                     assist->priv->calltip_iter,
 
450
                                                     NULL);
 
451
                }
607
452
                g_string_free (assist->priv->calltip_cache, TRUE);
608
453
                assist->priv->calltip_cache = NULL;
609
454
        }
610
455
}
611
456
 
 
457
static gint
 
458
python_assist_get_calltip_context_position (PythonAssist *assist)
 
459
{
 
460
        gchar ch;
 
461
        gint final_offset;
 
462
        IAnjutaEditor *editor = IANJUTA_EDITOR (assist->priv->iassist);
 
463
        IAnjutaIterable *current_iter = ianjuta_editor_get_position (editor, NULL);
 
464
 
 
465
        while (ianjuta_iterable_previous (current_iter, NULL))
 
466
        {
 
467
                ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (current_iter), 0, NULL);
 
468
                if (ch == '(')
 
469
                    break;
 
470
        }
 
471
        final_offset = ianjuta_iterable_get_position (current_iter, NULL);
 
472
 
 
473
        return final_offset-1;
 
474
}
 
475
 
612
476
static void
613
 
python_assist_query_calltip (PythonAssist *assist, const gchar *call_context)
614
 
{       
 
477
python_assist_query_calltip (PythonAssist* assist, const gchar *call_context)
 
478
{
615
479
        IAnjutaEditor *editor = IANJUTA_EDITOR (assist->priv->iassist);
616
 
        gint offset = assist->priv->calltip_context_position;
 
480
        
 
481
        gint offset = python_assist_get_calltip_context_position (assist);
 
482
        
617
483
        gchar *interpreter_path;
618
484
        const gchar *cur_filename;
619
485
        gchar *source = ianjuta_editor_get_text_all (editor, NULL);
653
519
}
654
520
 
655
521
static void
 
522
python_assist_create_calltip_context (PythonAssist* assist,
 
523
                                      const gchar* call_context,
 
524
                                      IAnjutaIterable* position)
 
525
{
 
526
        assist->priv->calltip_context = g_strdup (call_context);
 
527
        assist->priv->calltip_iter = position;
 
528
}
 
529
 
 
530
static void
656
531
python_assist_clear_calltip_context (PythonAssist* assist)
657
532
{
658
533
        if (assist->priv->calltip_launcher)
661
536
        }       
662
537
        assist->priv->calltip_launcher = NULL;
663
538
        
664
 
        g_free (assist->priv->calltip_context);
665
 
        assist->priv->calltip_context = NULL;
666
 
        
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;
670
 
 
 
542
        
 
543
        g_free (assist->priv->calltip_context);
 
544
        assist->priv->calltip_context = NULL;
 
545
        
671
546
        if (assist->priv->calltip_iter)
672
547
                g_object_unref (assist->priv->calltip_iter);
673
548
        assist->priv->calltip_iter = NULL;
674
549
}
675
550
 
676
 
 
677
551
static gchar*
678
 
python_assist_get_calltip_context (PythonAssist *assist,
679
 
                                     IAnjutaIterable *iter)
680
 
{
681
 
        gchar ch;
682
 
        gchar *context = NULL;  
683
 
        gint original_offset = ianjuta_editor_get_offset (IANJUTA_EDITOR (assist->priv->iassist), NULL);
684
 
        
685
 
        ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
686
 
        if (ch == ')')
687
 
        {
688
 
                if (!anjuta_util_jump_to_matching_brace (iter, ')', -1))
689
 
                        return NULL;
690
 
                if (!ianjuta_iterable_previous (iter, NULL))
691
 
                        return NULL;
692
 
        }
693
 
        if (ch != '(')
694
 
        {
695
 
                if (!anjuta_util_jump_to_matching_brace (iter, ')',
696
 
                                                                                                   BRACE_SEARCH_LIMIT))
697
 
                        return NULL;
698
 
        }
699
 
        
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)))
704
 
                original_offset--;
705
 
 
706
 
        context = python_assist_get_scope_context
707
 
                (IANJUTA_EDITOR (assist->priv->iassist), "(", iter);
708
 
 
709
 
        /* Point iter to the first character of the scope to align calltip correctly */
710
 
        ianjuta_iterable_next (iter, NULL);
711
 
        
712
 
        return context;
713
 
}
714
 
 
715
 
static gint
716
 
python_assist_get_calltip_context_position (PythonAssist *assist,
717
 
                                     IAnjutaIterable *iter)
718
 
{
719
 
        gchar ch;
720
 
        gint final_offset;
721
 
        IAnjutaEditor *editor = IANJUTA_EDITOR (assist->priv->iassist);
722
 
        IAnjutaIterable *current_iter = ianjuta_editor_get_position (editor, NULL);
723
 
        
724
 
        while (ianjuta_iterable_previous (current_iter, NULL))
725
 
        {
726
 
                ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (current_iter), 0, NULL);
727
 
                if (ch == '(')
728
 
                    break;
729
 
        }
730
 
        final_offset = ianjuta_iterable_get_position (current_iter, NULL);
731
 
        
732
 
        return final_offset-1;
733
 
}
734
 
 
735
 
static gboolean
736
 
python_assist_calltip (PythonAssist *assist)
737
 
{
738
 
        IAnjutaEditor *editor;
739
 
        IAnjutaIterable *iter;
740
 
        gchar *call_context;
741
 
        gint call_context_position;
742
 
        
743
 
        editor = IANJUTA_EDITOR (assist->priv->iassist);
744
 
        
745
 
        iter = ianjuta_editor_get_position (editor, NULL);
746
 
        ianjuta_iterable_previous (iter, NULL);
747
 
 
748
 
        call_context = python_assist_get_calltip_context (assist, iter);
749
 
        call_context_position = python_assist_get_calltip_context_position (assist, iter);
750
 
 
751
 
        if (call_context)
752
 
        {
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))
756
 
                {
757
 
                        /* Continue tip */
758
 
                        if (assist->priv->tips)
759
 
                        {
760
 
                                if (!ianjuta_editor_tip_visible (IANJUTA_EDITOR_TIP (editor), NULL))
761
 
                                {
762
 
                                        ianjuta_editor_tip_show (IANJUTA_EDITOR_TIP (editor),
763
 
                                                                 assist->priv->tips,
764
 
                                                                 assist->priv->calltip_iter, NULL);
765
 
                                }
766
 
                        }
767
 
                        g_free (call_context);
768
 
                        return TRUE;
769
 
                }
770
 
                else /* New tip */
771
 
                {
772
 
                        if (ianjuta_editor_tip_visible (IANJUTA_EDITOR_TIP (editor), NULL))
773
 
                                ianjuta_editor_tip_cancel (IANJUTA_EDITOR_TIP (editor), NULL);
774
 
                        
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);
779
 
                        return TRUE;
780
 
                }
781
 
        }
782
 
        else
783
 
        {
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);
787
 
        }
788
 
 
789
 
        g_object_unref (iter);
790
 
        return FALSE;
 
552
python_assist_get_calltip_context (IAnjutaLanguageProvider *self,
 
553
                                   IAnjutaIterable *iter,
 
554
                                   GError** e)
 
555
{
 
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;
791
562
}
792
563
 
793
564
static void
799
570
        assist->priv->pre_word = g_strdup (pre_word);
800
571
}
801
572
 
802
 
static void
803
 
python_assist_none (IAnjutaProvider* self,
804
 
                    PythonAssist* assist)
805
 
{
806
 
        ianjuta_editor_assist_proposals (assist->priv->iassist,
807
 
                                         self,
808
 
                                         NULL, TRUE, NULL);
809
 
}
810
 
 
811
573
/* returns TRUE if a '.', "'", or '"' preceeds the cursor position */
812
574
static gint
813
575
python_assist_completion_trigger_char (IAnjutaEditor* editor,
826
588
        return retval;
827
589
}
828
590
 
 
591
static GList*
 
592
python_assist_get_calltip_cache (IAnjutaLanguageProvider* self,
 
593
                                 gchar* call_context,
 
594
                                 GError** e)
 
595
{
 
596
        PythonAssist* assist = PYTHON_ASSIST (self);
 
597
        if (!g_strcmp0 (call_context, assist->priv->calltip_context))
 
598
        {
 
599
                DEBUG_PRINT ("Calltip was found in the cache.");
 
600
                return assist->priv->tips;
 
601
        }
 
602
        else
 
603
        {
 
604
                DEBUG_PRINT ("Calltip is not available in the cache!");
 
605
                return NULL;
 
606
        }
 
607
}
 
608
 
829
609
static void
830
 
python_assist_populate (IAnjutaProvider* self, IAnjutaIterable* cursor, GError** e)
 
610
python_assist_new_calltip (IAnjutaLanguageProvider* self,
 
611
                           gchar* call_context,
 
612
                           IAnjutaIterable* cursor,
 
613
                           GError** e)
 
614
{
 
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);
 
619
}
 
620
 
 
621
static IAnjutaIterable*
 
622
python_assist_populate_completions (IAnjutaLanguageProvider* self,
 
623
                                    IAnjutaIterable* cursor,
 
624
                                    GError** e)
831
625
{
832
626
        PythonAssist* assist = PYTHON_ASSIST (self);
833
627
        IAnjutaIterable* start_iter = NULL;
834
628
        gchar* pre_word;
835
629
        gboolean completion_trigger_char;
836
 
 
837
 
        /* Check for calltip */
838
 
        if (assist->priv->itip && 
839
 
            g_settings_get_boolean (assist->priv->settings,
840
 
                                    PREF_CALLTIP_ENABLE))
841
 
        {       
842
 
                python_assist_calltip (assist); 
843
 
        }
844
 
        
845
 
        /* Check if we actually want autocompletion at all */
846
 
        if (!g_settings_get_boolean (assist->priv->settings,
847
 
                                     PREF_AUTOCOMPLETE_ENABLE))
848
 
        {
849
 
                python_assist_none (self, assist);
850
 
                return;
851
 
        }
852
 
        
853
 
        /* Check if this is a valid text region for completion */
854
 
        IAnjutaEditorAttribute attrib = ianjuta_editor_cell_get_attribute (IANJUTA_EDITOR_CELL(cursor),
855
 
                                                                           NULL);
856
 
        if (attrib == IANJUTA_EDITOR_COMMENT)
857
 
        {
858
 
                python_assist_none (self, assist);
859
 
                return;
860
 
        }
861
 
 
862
 
        pre_word = python_assist_get_pre_word (IANJUTA_EDITOR (assist->priv->iassist), cursor, &start_iter);
 
630
        
 
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);
863
635
 
864
636
        DEBUG_PRINT ("Preword: %s", pre_word);
865
637
        
869
641
                if (pre_word && g_str_has_prefix (pre_word, assist->priv->pre_word))
870
642
                {
871
643
                        DEBUG_PRINT ("Continue autocomplete for %s", pre_word);
 
644
                        
872
645
                        /* Great, we just continue the current completion */
873
 
                        if (assist->priv->start_iter)
874
 
                                g_object_unref (assist->priv->start_iter);
875
 
                        assist->priv->start_iter = start_iter;
876
 
 
877
646
                        python_assist_update_pre_word (assist, pre_word);
878
647
                        python_assist_update_autocomplete (assist);
879
648
                        g_free (pre_word);
880
 
                        return;
 
649
                        return start_iter;
881
650
                }
882
651
        }
883
652
        else
889
658
        /* Autocompletion should not be triggered if we haven't started typing a word unless
890
659
         * we just typed . or ' or "
891
660
         */
892
 
        completion_trigger_char = python_assist_completion_trigger_char (IANJUTA_EDITOR (assist->priv->iassist),
893
 
                                 cursor);
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),
 
663
                                          cursor);
 
664
        if (( (pre_word && strlen (pre_word) >= 3) || completion_trigger_char )
 
665
                && python_assist_create_word_completion_cache (assist, cursor))
896
666
        {
897
667
                DEBUG_PRINT ("New autocomplete for %s", pre_word);
898
 
                if (assist->priv->start_iter)
899
 
                        g_object_unref (assist->priv->start_iter);
900
 
                if (start_iter)
901
 
                        assist->priv->start_iter = start_iter;
902
 
                else
903
 
                        assist->priv->start_iter = ianjuta_iterable_clone (cursor, NULL);
 
668
                if (!start_iter)
 
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);
906
 
                return;
907
 
        }               
908
 
        /* Nothing to propose */
909
 
        if (assist->priv->start_iter)
910
 
        {
911
 
                g_object_unref (assist->priv->start_iter);
912
 
                assist->priv->start_iter = NULL;
 
672
                return start_iter;
913
673
        }
914
 
        python_assist_none (self, assist);
915
674
        g_free (pre_word);
916
 
917
 
 
918
 
 
919
 
 
920
 
static void 
921
 
python_assist_activate (IAnjutaProvider* self, IAnjutaIterable* iter, gpointer data, GError** e)
922
 
{
923
 
        PythonAssist* assist = PYTHON_ASSIST(self);
924
 
        PythonAssistTag *tag;
925
 
        GString *assistance;
926
 
        IAnjutaEditor *te;
927
 
        gboolean add_space_after_func = FALSE;
928
 
        gboolean add_brace_after_func = FALSE;
929
 
        
930
 
        tag = data;     
931
 
        assistance = g_string_new (tag->name);
932
 
        
933
 
        if (tag->is_func)
934
 
        {
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, " ");
943
 
                
944
 
                if (add_brace_after_func)
945
 
                        g_string_append (assistance, "(");
946
 
        }
947
 
        
948
 
        te = IANJUTA_EDITOR (assist->priv->iassist);
949
 
                
950
 
        ianjuta_document_begin_undo_action (IANJUTA_DOCUMENT (te), NULL);
951
 
        
952
 
        if (ianjuta_iterable_compare(iter, assist->priv->start_iter, NULL) != 0)
953
 
        {
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);
958
 
        }
959
 
        else
960
 
        {
961
 
                ianjuta_editor_insert (te, iter, assistance->str, -1, NULL);
962
 
        }
963
 
        ianjuta_document_end_undo_action (IANJUTA_DOCUMENT (te), NULL);
964
 
        
965
 
        /* Show calltip if we completed function */
966
 
        if (add_brace_after_func)
967
 
                python_assist_calltip (assist);
968
 
        
969
 
        g_string_free (assistance, TRUE);
970
 
}
971
 
 
972
 
static IAnjutaIterable*
973
 
python_assist_get_start_iter (IAnjutaProvider* provider, GError** e)
974
 
975
 
        PythonAssist* assist = PYTHON_ASSIST (provider);
976
 
        return assist->priv->start_iter;
977
 
}
978
 
 
979
 
static const gchar*
980
 
python_assist_get_name (IAnjutaProvider* provider, GError** e)
981
 
{
982
 
        return _("Python");
983
 
}
984
 
 
985
 
static void 
986
 
python_assist_install (PythonAssist *assist, IAnjutaEditor *ieditor)
 
675
        
 
676
        return NULL;
 
677
}
 
678
 
 
679
static void 
 
680
python_assist_install (PythonAssist *assist,
 
681
                       IAnjutaEditor *ieditor)
987
682
{
988
683
        g_return_if_fail (assist->priv->iassist == NULL);
989
684
 
994
689
                g_signal_connect (ieditor, "cancelled", G_CALLBACK (python_assist_cancelled), assist);
995
690
        }
996
691
        else
997
 
        {
998
692
                assist->priv->iassist = NULL;
999
 
        }
1000
693
 
1001
694
        if (IANJUTA_IS_EDITOR_TIP (ieditor))
1002
 
        {
1003
695
                assist->priv->itip = IANJUTA_EDITOR_TIP (ieditor);
1004
 
        }
1005
696
        else
1006
 
        {
1007
697
                assist->priv->itip = NULL;
 
698
                
 
699
        if (IANJUTA_IS_FILE (assist->priv->iassist))
 
700
        {
 
701
                GFile *file = ianjuta_file_get_file (IANJUTA_FILE (assist->priv->iassist), NULL);
 
702
                if (file != NULL)
 
703
                {
 
704
                        assist->priv->editor_filename = g_file_get_path (file);
 
705
                        g_object_unref (file);
 
706
                }
1008
707
        }
1009
708
}
1010
709
 
1015
714
 
1016
715
        if (IANJUTA_EDITOR_ASSIST (assist->priv->iassist))
1017
716
        {
 
717
                g_signal_handlers_disconnect_by_func (assist->priv->iassist, python_assist_cancelled, assist);
1018
718
                ianjuta_editor_assist_remove (assist->priv->iassist, IANJUTA_PROVIDER(assist), NULL);
1019
 
                g_signal_handlers_disconnect_by_func (assist->priv->iassist, python_assist_cancelled, assist);
1020
719
        }
1021
 
 
 
720
        
1022
721
        assist->priv->iassist = NULL;
1023
722
}
1024
723
 
1048
747
}
1049
748
 
1050
749
PythonAssist * 
1051
 
python_assist_new (IAnjutaEditorAssist *iassist,
 
750
python_assist_new (IAnjutaEditor *ieditor,
1052
751
                   IAnjutaSymbolManager *isymbol_manager,
1053
 
                   IAnjutaDocumentManager *idocument_manager,
 
752
                   GSettings* settings,
1054
753
                   AnjutaPlugin *plugin,
1055
 
                   GSettings* settings,
1056
 
                   const gchar *editor_filename,
1057
754
                   const gchar *project_root)
1058
755
{
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));
 
761
                
 
762
        /* Install support */
 
763
        python_assist_install (assist, ieditor);
 
764
        anjuta_language_provider_install (assist->priv->lang_prov, ieditor, settings);
1068
765
        return assist;
1069
766
}
1070
767
 
1071
 
static void python_assist_iface_init(IAnjutaProviderIface* iface)
1072
 
{
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;
 
768
static void
 
769
python_assist_activate (IAnjutaProvider* self,
 
770
                        IAnjutaIterable* iter,
 
771
                        gpointer data,
 
772
                        GError** e)
 
773
{
 
774
        PythonAssist* assist = PYTHON_ASSIST (self);
 
775
        anjuta_language_provider_activate (assist->priv->lang_prov, self, iter,
 
776
                                           data);
 
777
}
 
778
 
 
779
static void
 
780
python_assist_populate (IAnjutaProvider* self,
 
781
                        IAnjutaIterable* cursor,
 
782
                        GError** e)
 
783
{
 
784
        PythonAssist* assist = PYTHON_ASSIST (self);
 
785
        anjuta_language_provider_populate (assist->priv->lang_prov, self, cursor);
 
786
}
 
787
 
 
788
static const gchar*
 
789
python_assist_get_name (IAnjutaProvider* self,
 
790
                        GError** e)
 
791
{
 
792
        return _("Python");
 
793
}
 
794
 
 
795
static IAnjutaIterable*
 
796
python_assist_get_start_iter (IAnjutaProvider* self,
 
797
                              GError** e)
 
798
{
 
799
        PythonAssist* assist = PYTHON_ASSIST (self);
 
800
        return anjuta_language_provider_get_start_iter (assist->priv->lang_prov);
 
801
}
 
802
 
 
803
static void
 
804
iprovider_iface_init (IAnjutaProviderIface* iface)
 
805
{
 
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;
 
810
}
 
811
 
 
812
static void
 
813
ilanguage_provider_iface_init (IAnjutaLanguageProviderIface* iface)
 
814
{
 
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;
1077
819
}