1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) Ishan Chattopadhyaya 2009 <ichattopadhyaya@gmail.com>
6 * plugin.c is free software.
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)
13 * plugin.c 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 plugin.c. If not, write to:
20 * The Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301, USA.
29 #include <libanjuta/anjuta-shell.h>
30 #include <libanjuta/anjuta-debug.h>
31 #include <libanjuta/anjuta-launcher.h>
32 #include <libanjuta/anjuta-preferences.h>
33 #include <libanjuta/interfaces/ianjuta-iterable.h>
34 #include <libanjuta/interfaces/ianjuta-document.h>
35 #include <libanjuta/interfaces/ianjuta-document-manager.h>
36 #include <libanjuta/interfaces/ianjuta-editor.h>
37 #include <libanjuta/interfaces/ianjuta-file.h>
38 #include <libanjuta/interfaces/ianjuta-editor-cell.h>
39 #include <libanjuta/interfaces/ianjuta-editor-language.h>
40 #include <libanjuta/interfaces/ianjuta-editor-selection.h>
41 #include <libanjuta/interfaces/ianjuta-editor-assist.h>
42 #include <libanjuta/interfaces/ianjuta-preferences.h>
43 #include <libanjuta/interfaces/ianjuta-symbol.h>
44 #include <libanjuta/interfaces/ianjuta-language.h>
46 //REMOVE GLADE #include <glade/glade.h>
49 #include "python-utils.h"
50 #include "python-assist.h"
53 #define ANJUTA_PIXMAP_COMPLETE "anjuta-complete"
54 #define ANJUTA_PIXMAP_AUTOCOMPLETE "anjuta-complete-auto"
55 #define ANJUTA_PIXMAP_AUTOINDENT "anjuta-indent-auto"
56 #define ANJUTA_STOCK_SWAP "anjuta-swap"
57 #define ANJUTA_STOCK_COMPLETE "anjuta-complete"
58 #define ANJUTA_STOCK_AUTOCOMPLETE "anjuta-autocomplete"
59 #define ANJUTA_STOCK_AUTOINDENT "anjuta-indent"
61 #define UI_FILE PACKAGE_DATA_DIR"/ui/python-plugin.xml"
62 #define PROPERTIES_FILE_UI PACKAGE_DATA_DIR"/glade/python-plugin-properties.ui"
63 #define ICON_FILE "python_plugin.png"
65 /* Preferences keys */
67 #define PREF_SCHEMA "org.gnome.anjuta.python"
68 #define PREF_INDENT_AUTOMATIC "python-indent-automatic"
69 #define PREF_INDENT_ADAPTIVE "python-indent-adaptive"
70 #define PREF_INDENT_TAB_INDENTS "python-indent-tab-indents"
71 #define PREF_INDENT_STATEMENT_SIZE "python-indent-statement-size"
72 #define PREF_INDENT_BRACE_SIZE "python-indent-brace-size"
74 #define PREF_NO_ROPE_WARNING "python-no-rope-warning"
75 #define PREF_INTERPRETER_PATH "python-interpreter-path"
77 #define TAB_SIZE (ianjuta_editor_get_tabsize (editor, NULL))
79 #define USE_SPACES_FOR_INDENTATION (ianjuta_editor_get_use_spaces (editor, NULL))
82 (plugin->param_statement_indentation >= 0? \
83 plugin->param_statement_indentation : \
84 g_settings_get_int (plugin->settings, PREF_INDENT_STATEMENT_SIZE))
86 #define BRACE_INDENT \
87 (plugin->param_brace_indentation >= 0? \
88 plugin->param_brace_indentation : \
89 g_settings_get_int (plugin->settings, PREF_INDENT_BRACE_SIZE))
91 #define CASE_INDENT (INDENT_SIZE)
92 #define LABEL_INDENT (INDENT_SIZE)
94 static gpointer parent_class
;
97 iter_is_newline (IAnjutaIterable
*iter
, gchar ch
)
99 if (ch
== '\n' || ch
== '\r')
104 /* Returns TRUE if iter was moved */
106 skip_iter_to_newline_head (IAnjutaIterable
*iter
, gchar ch
)
108 gboolean ret_val
= FALSE
;
112 /* Possibly at tail */
113 if (ianjuta_iterable_previous (iter
, NULL
))
115 ch
= ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter
),
118 /* Already at head, undo iter */
119 ianjuta_iterable_next (iter
, NULL
);
121 /* Correctly at head */
128 /* Returns TRUE if iter was moved */
130 skip_iter_to_newline_tail (IAnjutaIterable
*iter
, gchar ch
)
132 gboolean ret_val
= FALSE
;
136 /* Possibly at head */
137 if (ianjuta_iterable_previous (iter
, NULL
))
139 ch
= ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter
),
142 /* Already at tail, undo iter */
143 ianjuta_iterable_next (iter
, NULL
);
145 /* Correctly at tail */
152 /* Jumps to the reverse matching brace of the given brace character */
155 get_line_indentation (IAnjutaEditor
*editor
, gint line_num
)
157 IAnjutaIterable
*line_begin
, *line_end
;
158 gchar
*line_string
, *idx
;
159 gint line_indent
= 0;
161 line_begin
= ianjuta_editor_get_line_begin_position (editor
, line_num
, NULL
);
162 line_end
= ianjuta_editor_get_line_end_position (editor
, line_num
, NULL
);
164 DEBUG_PRINT ("%s: line begin = %d, line end = %d", __FUNCTION__,
165 line_begin, line_end);
167 if (ianjuta_iterable_compare (line_begin
, line_end
, NULL
) == 0)
169 g_object_unref (line_begin
);
170 g_object_unref (line_end
);
174 line_string
= ianjuta_editor_get_text (editor
, line_begin
, line_end
,
176 g_object_unref (line_begin
);
177 g_object_unref (line_end
);
179 /* DEBUG_PRINT ("line_string = '%s'", line_string); */
186 /* Find first non-white space */
187 while (*idx
!= '\0' && isspace (*idx
))
190 line_indent
+= TAB_SIZE
;
193 idx
++; /* Since we are looking for first non-space char, simple
194 * increment of the utf8 chars would do */
196 g_free (line_string
);
201 get_line_indentation_string (IAnjutaEditor
*editor
, gint spaces
, gint line_indent_spaces
)
204 gchar
*indent_string
;
206 if ((spaces
+ line_indent_spaces
) <= 0)
209 if (USE_SPACES_FOR_INDENTATION
)
211 indent_string
= g_new0 (gchar
, spaces
+ line_indent_spaces
+ 1);
212 for (i
= 0; i
< (spaces
+ line_indent_spaces
); i
++)
213 indent_string
[i
] = ' ';
217 gint num_tabs
= spaces
/ TAB_SIZE
;
218 gint num_spaces
= spaces
% TAB_SIZE
;
219 indent_string
= g_new0 (gchar
, num_tabs
+ num_spaces
+ line_indent_spaces
+ 1);
221 for (i
= 0; i
< num_tabs
; i
++)
222 indent_string
[i
] = '\t';
223 for (; i
< num_tabs
+ (num_spaces
+ line_indent_spaces
); i
++)
224 indent_string
[i
] = ' ';
226 return indent_string
;
230 set_indentation_param_emacs (PythonPlugin
* plugin
, const gchar
*param
,
233 //DEBUG_PRINT ("Setting indent param: %s = %s", param, value);
234 if (strcasecmp (param
, "indent-tabs-mode") == 0)
236 if (strcasecmp (value
, "t") == 0)
238 plugin
->param_use_spaces
= 0;
239 ianjuta_editor_set_use_spaces (IANJUTA_EDITOR (plugin
->current_editor
),
242 else if (strcasecmp (value
, "nil") == 0)
244 plugin
->param_use_spaces
= 1;
245 ianjuta_editor_set_use_spaces (IANJUTA_EDITOR (plugin
->current_editor
),
249 else if (strcasecmp (param
, "c-basic-offset") == 0)
251 plugin
->param_statement_indentation
= atoi (value
);
253 else if (strcasecmp (param
, "tab-width") == 0)
255 plugin
->param_tab_size
= atoi (value
);
256 ianjuta_editor_set_tabsize (IANJUTA_EDITOR (plugin
->current_editor
),
257 plugin
->param_tab_size
, NULL
);
262 set_indentation_param_vim (PythonPlugin
* plugin
, const gchar
*param
,
265 //DEBUG_PRINT ("Setting indent param: %s = %s", param, value);
266 if (g_str_equal (param
, "expandtab") ||
267 g_str_equal (param
, "et"))
269 plugin
->param_use_spaces
= 1;
270 ianjuta_editor_set_use_spaces (IANJUTA_EDITOR (plugin
->current_editor
),
273 else if (g_str_equal (param
, "noexpandtabs") ||
274 g_str_equal (param
, "noet"))
276 plugin
->param_use_spaces
= 0;
277 ianjuta_editor_set_use_spaces (IANJUTA_EDITOR (plugin
->current_editor
),
282 else if (g_str_equal (param
, "shiftwidth") ||
283 g_str_equal (param
, "sw"))
285 plugin
->param_statement_indentation
= atoi (value
);
287 else if (g_str_equal (param
, "softtabstop") ||
288 g_str_equal (param
, "sts") ||
289 g_str_equal (param
, "tabstop") ||
290 g_str_equal (param
, "ts"))
292 plugin
->param_tab_size
= atoi (value
);
293 ianjuta_editor_set_tabsize (IANJUTA_EDITOR (plugin
->current_editor
),
294 plugin
->param_tab_size
, NULL
);
299 parse_mode_line_emacs (PythonPlugin
*plugin
, const gchar
*modeline
)
303 strv
= g_strsplit (modeline
, ";", -1);
308 keyval
= g_strsplit (*ptr
, ":", 2);
309 if (keyval
[0] && keyval
[1])
311 g_strstrip (keyval
[0]);
312 g_strstrip (keyval
[1]);
313 set_indentation_param_emacs (plugin
, g_strchug (keyval
[0]),
314 g_strchug (keyval
[1]));
323 parse_mode_line_vim (PythonPlugin
*plugin
, const gchar
*modeline
)
327 strv
= g_strsplit (modeline
, " ", -1);
332 keyval
= g_strsplit (*ptr
, "=", 2);
335 g_strstrip (keyval
[0]);
338 g_strstrip (keyval
[1]);
339 set_indentation_param_vim (plugin
, g_strchug (keyval
[0]),
340 g_strchug (keyval
[1]));
343 set_indentation_param_vim (plugin
, g_strchug (keyval
[0]),
353 extract_mode_line (const gchar
*comment_text
, gboolean
* vim
)
355 /* Search for emacs-like modelines */
356 gchar
*begin_modeline
, *end_modeline
;
357 begin_modeline
= strstr (comment_text
, "-*-");
361 end_modeline
= strstr (begin_modeline
, "-*-");
365 return g_strndup (begin_modeline
, end_modeline
- begin_modeline
);
368 /* Search for vim-like modelines */
369 begin_modeline
= strstr (comment_text
, "vim:set");
373 end_modeline
= strstr (begin_modeline
, ":");
374 /* Check for escape characters */
377 if (!g_str_equal ((end_modeline
- 1), "\\"))
380 end_modeline
= strstr (end_modeline
, ":");
384 gchar
* vim_modeline
= g_strndup (begin_modeline
, end_modeline
- begin_modeline
);
392 #define MINI_BUFFER_SIZE 3
395 initialize_indentation_params (PythonPlugin
*plugin
)
397 IAnjutaIterable
*iter
;
398 GString
*comment_text
;
399 gboolean comment_begun
= FALSE
;
400 gboolean line_comment
= FALSE
;
401 gchar mini_buffer
[MINI_BUFFER_SIZE
] = {0};
403 /* Initialize indentation parameters */
404 plugin
->param_tab_size
= -1;
405 plugin
->param_statement_indentation
= -1;
406 plugin
->param_brace_indentation
= -1;
407 plugin
->param_case_indentation
= -1;
408 plugin
->param_label_indentation
= -1;
409 plugin
->param_use_spaces
= -1;
411 /* Find the first comment text in the buffer */
412 comment_text
= g_string_new (NULL
);
413 iter
= ianjuta_editor_get_start_position (IANJUTA_EDITOR (plugin
->current_editor
),
417 gboolean shift_buffer
= TRUE
;
419 gchar ch
= ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter
),
422 for (i
= 0; i
< MINI_BUFFER_SIZE
- 1; i
++)
424 if (mini_buffer
[i
] == '\0')
427 shift_buffer
= FALSE
;
431 if (shift_buffer
== TRUE
)
433 /* Shift buffer and add */
434 for (i
= 0; i
< MINI_BUFFER_SIZE
- 1; i
++)
435 mini_buffer
[i
] = mini_buffer
[i
+1];
439 if (!comment_begun
&& strncmp (mini_buffer
, "/*", 2) == 0)
441 comment_begun
= TRUE
;
443 mini_buffer
[0] = mini_buffer
[1] = '\0';
445 else if (!comment_begun
&& strncmp (mini_buffer
, "//", 2) == 0)
447 comment_begun
= TRUE
;
450 else if (!comment_begun
&& mini_buffer
[1] != '\0')
452 /* The buffer doesn't begin with a comment */
455 else if (comment_begun
)
457 if ((line_comment
&& ch
== '\n') ||
458 (!line_comment
&& strncmp (mini_buffer
, "*/", 2) == 0))
465 g_string_append_c (comment_text
, ch
);
468 while (ianjuta_iterable_next (iter
, NULL
));
470 /* DEBUG_PRINT ("Comment text: %s", comment_text->str);*/
471 if (comment_text
->len
> 0)
474 /* First comment found */
476 gchar
*modeline
= extract_mode_line (comment_text
->str
, &vim
);
480 parse_mode_line_emacs (plugin
, modeline
);
482 parse_mode_line_vim (plugin
, modeline
);
486 g_string_free (comment_text
, TRUE
);
487 g_object_unref (iter
);
491 set_line_indentation (IAnjutaEditor
*editor
, gint line_num
, gint indentation
, gint line_indent_spaces
)
493 IAnjutaIterable
*line_begin
, *line_end
, *indent_position
;
494 IAnjutaIterable
*current_pos
;
495 gint carat_offset
, nchars
= 0, nchars_removed
= 0;
496 gchar
*old_indent_string
= NULL
, *indent_string
= NULL
;
498 /* DEBUG_PRINT ("In %s()", __FUNCTION__); */
499 line_begin
= ianjuta_editor_get_line_begin_position (editor
, line_num
, NULL
);
500 line_end
= ianjuta_editor_get_line_end_position (editor
, line_num
, NULL
);
503 DEBUG_PRINT ("line begin = %d, line end = %d, current_pos = %d",
504 line_begin, line_end, current_pos);
506 indent_position
= ianjuta_iterable_clone (line_begin
, NULL
);
508 if (ianjuta_iterable_compare (line_end
, line_begin
, NULL
) > 0)
511 gchar
*line_string
= ianjuta_editor_get_text (editor
, line_begin
,
514 //DEBUG_PRINT ("line_string = '%s'", line_string);
519 /* Find first non-white space */
520 while (*idx
!= '\0' && isspace (*idx
))
522 idx
= g_utf8_find_next_char (idx
, NULL
);
523 ianjuta_iterable_next (indent_position
, NULL
);
525 g_free (line_string
);
528 /* Indent iter defined at this point, Identify how much is current
529 * position is beyound this point. We need to restore it later after
532 current_pos
= ianjuta_editor_get_position (editor
, NULL
);
533 carat_offset
= ianjuta_iterable_diff (indent_position
, current_pos
, NULL
);
534 //DEBUG_PRINT ("carat offset is = %d", carat_offset);
536 /* Set new indentation */
537 if ((indentation
+ line_indent_spaces
) > 0)
539 indent_string
= get_line_indentation_string (editor
, indentation
, line_indent_spaces
);
540 nchars
= indent_string
? g_utf8_strlen (indent_string
, -1) : 0;
542 /* Only indent if there is something to indent with */
545 /* Get existing indentation */
546 if (ianjuta_iterable_compare (indent_position
, line_begin
, NULL
) > 0)
549 ianjuta_editor_get_text (editor
, line_begin
,
550 indent_position
, NULL
);
552 //DEBUG_PRINT ("old_indent_string = '%s'", old_indent_string);
553 nchars_removed
= g_utf8_strlen (old_indent_string
, -1);
556 /* Only indent if there was no indentation before or old
557 * indentation string was different from the new indent string
559 if (old_indent_string
== NULL
||
560 strcmp (old_indent_string
, indent_string
) != 0)
562 /* Remove the old indentation string, if there is any */
563 if (old_indent_string
)
564 ianjuta_editor_erase (editor
, line_begin
,
565 indent_position
, NULL
);
567 /* Insert the new indentation string */
568 ianjuta_editor_insert (editor
, line_begin
,
569 indent_string
, -1, NULL
);
574 /* If indentation == 0, we really didn't enter the previous code block,
575 * but we may need to clear existing indentation.
577 if ((indentation
+ line_indent_spaces
) == 0)
579 /* Get existing indentation */
580 if (ianjuta_iterable_compare (indent_position
, line_begin
, NULL
) > 0)
583 ianjuta_editor_get_text (editor
, line_begin
,
584 indent_position
, NULL
);
585 nchars_removed
= g_utf8_strlen (old_indent_string
, -1);
587 if (old_indent_string
)
588 ianjuta_editor_erase (editor
, line_begin
, indent_position
, NULL
);
591 /* Restore current position */
592 if (carat_offset
>= 0)
594 /* If the cursor was not before the first non-space character in
595 * the line, restore it's position after indentation.
598 IAnjutaIterable
*pos
= ianjuta_editor_get_line_begin_position (editor
, line_num
, NULL
);
599 for (i
= 0; i
< nchars
+ carat_offset
; i
++)
600 ianjuta_iterable_next (pos
, NULL
);
601 ianjuta_editor_goto_position (editor
, pos
, NULL
);
602 g_object_unref (pos
);
604 else /* cursor_offset < 0 */
606 /* If the cursor was somewhere in the old indentation spaces,
607 * home the cursor to first non-space character in the line (or
608 * end of line if there is no non-space characters in the line.
611 IAnjutaIterable
*pos
= ianjuta_editor_get_line_begin_position (editor
, line_num
, NULL
);
612 for (i
= 0; i
< nchars
; i
++)
613 ianjuta_iterable_next (pos
, NULL
);
614 ianjuta_editor_goto_position (editor
, pos
, NULL
);
615 g_object_unref (pos
);
618 g_object_unref (current_pos
);
619 g_object_unref (indent_position
);
620 g_object_unref (line_begin
);
621 g_object_unref (line_end
);
623 g_free (old_indent_string
);
624 g_free (indent_string
);
628 /* incomplete_statement:
629 * 1 == COMPLETE STATEMENT
630 * 0 == INCOMPLETE STATEMENT
635 get_current_statement (IAnjutaEditor
*editor
, gint line_num
, gint
*found_line_num
)
638 IAnjutaIterable
*iter
= ianjuta_editor_get_line_begin_position (editor
, line_num
, NULL
);
639 gchar statement
[1024];
644 point_ch
= ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter
), 0, NULL
);
646 if (!ianjuta_iterable_next (iter
, NULL
) )
648 } while (point_ch
== ' ' || point_ch
== '\t'); // Whitespace
650 if (!ianjuta_iterable_previous (iter
, NULL
))
655 point_ch
= ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter
), 0, NULL
);
656 statement
[counter
++] = point_ch
;
658 if (!ianjuta_iterable_next (iter
, NULL
) )
660 } while (isalpha(point_ch
) || isdigit(point_ch
)); // FIXME: Is this UTF-8 compatible?
661 statement
[counter
-1] = '\0';
663 g_object_unref (iter
);
664 return g_strdup_printf("%s", statement
);
668 get_last_char (IAnjutaEditor
*editor
, gint line_num
, gint
*found_line_num
)
671 IAnjutaIterable
*iter
= ianjuta_editor_get_line_end_position (editor
, line_num
, NULL
);
675 if (ianjuta_iterable_previous (iter
, NULL
) )
677 point_ch
= ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter
), 0,
683 while (point_ch
== ' ' || point_ch
== '\n' || point_ch
== '\r' || point_ch
== '\t'); // Whitespace
685 *found_line_num
= ianjuta_editor_get_line_from_position (editor
, iter
, NULL
);
690 spaces_only (IAnjutaEditor
* editor
, IAnjutaIterable
* begin
, IAnjutaIterable
* end
);
693 is_spaces_only (IAnjutaEditor
*editor
, gint line_num
)
695 IAnjutaIterable
* begin
= ianjuta_editor_get_line_begin_position (editor
, line_num
, NULL
);
696 IAnjutaIterable
* end
= ianjuta_editor_get_line_end_position (editor
, line_num
, NULL
);
698 if (spaces_only (editor
, begin
, end
))
707 get_line_indentation_base (PythonPlugin
*plugin
,
708 IAnjutaEditor
*editor
,
710 gint
*incomplete_statement
,
711 gint
*line_indent_spaces
,
712 gboolean
*colon_indent
)
714 IAnjutaIterable
*iter
;
716 gint line_indent
= 0;
717 gint currentline
= line_num
- 1;
718 gchar
*last_line_statement
;
720 *incomplete_statement
= 0;
721 *line_indent_spaces
= 0;
723 if (currentline
<= 1)
726 iter
= ianjuta_editor_get_line_end_position (editor
, line_num
, NULL
);
728 point_ch
= get_last_char (editor
, currentline
, ¤tline
);
729 last_line_statement
= get_current_statement (editor
, currentline
, ¤tline
);
731 if (!g_strcmp0(last_line_statement
, "return") ||
732 !g_strcmp0(last_line_statement
, "break") ||
733 !g_strcmp0(last_line_statement
, "pass") ||
734 !g_strcmp0(last_line_statement
, "raise") ||
735 !g_strcmp0(last_line_statement
, "continue") )
737 if (get_line_indentation (editor
, currentline
)>= INDENT_SIZE
)
738 line_indent
= get_line_indentation (editor
, currentline
) - INDENT_SIZE
;
740 else if (point_ch
== ':')
742 line_indent
= get_line_indentation (editor
, currentline
) + INDENT_SIZE
;
746 gint line
= currentline
;
747 while (is_spaces_only(editor
, line
) && line
>= 0)
749 line_indent
= get_line_indentation (editor
, line
);
756 spaces_only (IAnjutaEditor
* editor
, IAnjutaIterable
* begin
, IAnjutaIterable
* end
)
758 gboolean empty
= TRUE
;
760 gchar
* text
= ianjuta_editor_get_text (editor
, begin
, end
, NULL
);
766 for (idx
= text
; *idx
!= '\0'; idx
++)
779 get_line_auto_indentation (PythonPlugin
*plugin
, IAnjutaEditor
*editor
,
780 gint line
, gint
*line_indent_spaces
)
782 IAnjutaIterable
*iter
;
783 gint line_indent
= 0;
784 gint incomplete_statement
= -1;
785 gboolean colon_indent
= FALSE
;
787 g_return_val_if_fail (line
> 0, 0);
789 if (line
== 1) /* First line */
795 IAnjutaIterable
* begin
= ianjuta_editor_get_line_begin_position (editor
, line
-1 , NULL
);
796 IAnjutaIterable
* end
= ianjuta_editor_get_line_end_position (editor
, line
-1 , NULL
);
798 if (spaces_only (editor
, begin
, end
))
800 set_line_indentation (editor
, line
-1, 0, 0);
802 g_object_unref (begin
);
803 g_object_unref (end
);
806 iter
= ianjuta_editor_get_line_begin_position (editor
, line
, NULL
);
808 /* if (is_iter_inside_string (iter))
810 line_indent = get_line_indentation (editor, line - 1);
814 line_indent
= get_line_indentation_base (plugin
, editor
, line
,
815 &incomplete_statement
,
820 /* Determine what the first non-white char in the line is */
824 /* Check if we are *inside* comment or string. Begining of comment
825 * or string does not count as inside. If inside, just align with
826 * previous indentation.
828 /*if (is_iter_inside_string (iter))
830 line_indent = get_line_indentation (editor, line - 1);
833 ch
= ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter
),
835 if (iter_is_newline (iter
, ch
))
837 skip_iter_to_newline_tail (iter
, ch
);
839 /* First levels are excused from incomplete statement indent */
840 if (incomplete_statement
== 1 && line_indent
> 0)
841 line_indent
+= INDENT_SIZE
;
845 else if (!isspace (ch
))
847 /* First levels are excused from incomplete statement indent */
848 if (incomplete_statement
== 1 && line_indent
> 0)
849 line_indent
+= INDENT_SIZE
;
854 while (ianjuta_iterable_next (iter
, NULL
));
855 g_object_unref (iter
);
861 on_editor_char_inserted_cpp (IAnjutaEditor
*editor
,
862 IAnjutaIterable
*insert_pos
,
864 PythonPlugin
*plugin
)
866 IAnjutaIterable
*iter
;
867 gboolean should_auto_indent
= FALSE
;
869 iter
= ianjuta_iterable_clone (insert_pos
, NULL
);
871 /* If autoindent is enabled*/
872 if (g_settings_get_boolean (plugin
->settings
, PREF_INDENT_AUTOMATIC
))
874 if (iter_is_newline (iter
, ch
))
876 skip_iter_to_newline_head (iter
, ch
);
877 /* All newline entries means enable indenting */
878 should_auto_indent
= TRUE
;
881 if (should_auto_indent
)
885 gint line_indent_spaces
;
887 ianjuta_document_begin_undo_action (IANJUTA_DOCUMENT(editor
), NULL
);
888 initialize_indentation_params (plugin
);
890 insert_line
= ianjuta_editor_get_lineno (editor
, NULL
);
891 line_indent
= get_line_auto_indentation (plugin
, editor
, insert_line
, &line_indent_spaces
);
892 set_line_indentation (editor
, insert_line
, line_indent
, line_indent_spaces
);
893 ianjuta_document_end_undo_action (IANJUTA_DOCUMENT(editor
), NULL
);
898 g_object_unref (iter
);
902 on_check_finished (AnjutaLauncher
* launcher
,
903 int child_pid
, int exit_status
,
904 gulong time
, gpointer user_data
)
906 PythonPlugin
* plugin
= ANJUTA_PLUGIN_PYTHON (user_data
);
907 if (exit_status
!= 0)
909 GtkWidget
* dialog
= gtk_dialog_new_with_buttons (_("Python support warning"),
915 GtkWidget
* area
= gtk_dialog_get_content_area (GTK_DIALOG (dialog
));
917 GtkWidget
* label
= gtk_label_new (_("Either python path is wrong or python-rope (http://rope.sf.net) libraries\n"
918 "aren't installed. Both are required for autocompletion in python files.\n"
919 "Please install them and check the python path in the preferences."));
920 GtkWidget
* check_button
= gtk_check_button_new_with_label (_("Do not show that warning again"));
922 gtk_box_pack_start (GTK_BOX (area
), label
,
924 gtk_box_pack_start (GTK_BOX (area
), check_button
,
926 gtk_widget_show_all (dialog
);
928 gtk_dialog_run (GTK_DIALOG(dialog
));
930 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check_button
)))
932 g_settings_get_boolean (plugin
->settings
,
933 PREF_NO_ROPE_WARNING
);
935 gtk_widget_destroy (dialog
);
937 g_object_unref (launcher
);
941 check_support (PythonPlugin
*python_plugin
)
943 if (!g_settings_get_boolean (python_plugin
->settings
,
944 PREF_NO_ROPE_WARNING
))
946 AnjutaLauncher
* launcher
= anjuta_launcher_new ();
947 gchar
* python_path
= g_settings_get_string (python_plugin
->settings
,
948 PREF_INTERPRETER_PATH
);
949 gchar
* command
= g_strdup_printf ("%s -c \"import rope\"", python_path
);
951 g_signal_connect (launcher
, "child-exited",
952 G_CALLBACK(on_check_finished
), python_plugin
);
953 anjuta_launcher_execute (launcher
, command
, NULL
, NULL
);
955 g_free (python_path
);
962 install_support (PythonPlugin
*lang_plugin
)
964 IAnjutaLanguage
* lang_manager
=
965 anjuta_shell_get_interface (ANJUTA_PLUGIN (lang_plugin
)->shell
,
966 IAnjutaLanguage
, NULL
);
967 IAnjutaSymbolManager
* sym_manager
=
968 anjuta_shell_get_interface (ANJUTA_PLUGIN (lang_plugin
)->shell
,
969 IAnjutaSymbolManager
,
971 IAnjutaDocumentManager
* docman
=
972 anjuta_shell_get_interface (ANJUTA_PLUGIN (lang_plugin
)->shell
,
973 IAnjutaDocumentManager
,
976 if (!lang_manager
|| !sym_manager
|| !docman
)
979 if (lang_plugin
->support_installed
)
982 lang_plugin
->current_language
=
983 ianjuta_language_get_name_from_editor (lang_manager
,
984 IANJUTA_EDITOR_LANGUAGE (lang_plugin
->current_editor
), NULL
);
986 DEBUG_PRINT("Language support installed for: %s",
987 lang_plugin
->current_language
);
989 if (lang_plugin
->current_language
&&
990 (g_str_equal (lang_plugin
->current_language
, "Python")))
992 g_signal_connect (lang_plugin
->current_editor
,
994 G_CALLBACK (on_editor_char_inserted_cpp
),
1002 initialize_indentation_params (lang_plugin
);
1003 /* Disable editor intern auto-indent */
1004 ianjuta_editor_set_auto_indent (IANJUTA_EDITOR(lang_plugin
->current_editor
),
1007 if (IANJUTA_IS_EDITOR_ASSIST (lang_plugin
->current_editor
) )
1009 AnjutaPlugin
*plugin
;
1011 IAnjutaEditorAssist
* iassist
;
1013 const gchar
*project_root
;
1014 gchar
*editor_filename
;
1015 GValue value
= {0,};
1017 check_support (lang_plugin
);
1019 plugin
= ANJUTA_PLUGIN (lang_plugin
);
1020 ui
= anjuta_shell_get_ui (plugin
->shell
, NULL
);
1021 iassist
= IANJUTA_EDITOR_ASSIST (lang_plugin
->current_editor
);
1023 g_assert (lang_plugin
->assist
== NULL
);
1025 anjuta_shell_get_value (ANJUTA_PLUGIN (lang_plugin
)->shell
,
1026 IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI
, &value
, NULL
);
1027 project_root
= ANJUTA_PLUGIN_PYTHON(plugin
)->project_root_directory
; //g_value_get_string (&value);
1028 editor_filename
= ANJUTA_PLUGIN_PYTHON(plugin
)->current_editor_filename
;
1030 lang_plugin
->assist
= python_assist_new (iassist
,
1033 lang_plugin
->settings
,
1038 lang_plugin
->support_installed
= TRUE
;
1042 uninstall_support (PythonPlugin
*lang_plugin
)
1044 if (!lang_plugin
->support_installed
)
1047 if (lang_plugin
->current_language
&&
1048 (g_str_equal (lang_plugin
->current_language
, "Python")))
1050 g_signal_handlers_disconnect_by_func (lang_plugin
->current_editor
,
1051 G_CALLBACK (on_editor_char_inserted_cpp
),
1055 if (lang_plugin
->assist
)
1057 g_object_unref (lang_plugin
->assist
);
1058 lang_plugin
->assist
= NULL
;
1061 lang_plugin
->support_installed
= FALSE
;
1065 on_editor_language_changed (IAnjutaEditor
*editor
,
1066 const gchar
*new_language
,
1067 PythonPlugin
*plugin
)
1069 uninstall_support (plugin
);
1070 install_support (plugin
);
1074 on_value_added_current_editor (AnjutaPlugin
*plugin
, const gchar
*name
,
1075 const GValue
*value
, gpointer data
)
1077 PythonPlugin
*lang_plugin
;
1078 IAnjutaDocument
* doc
= IANJUTA_DOCUMENT(g_value_get_object (value
));
1079 lang_plugin
= (PythonPlugin
*) (plugin
);
1082 if (IANJUTA_IS_EDITOR(doc
))
1084 lang_plugin
->current_editor
= G_OBJECT(doc
);
1088 lang_plugin
->current_editor
= NULL
;
1091 if (lang_plugin
->current_editor
)
1093 IAnjutaEditor
* editor
= IANJUTA_EDITOR (lang_plugin
->current_editor
);
1094 GFile
* current_editor_file
= ianjuta_file_get_file (IANJUTA_FILE (editor
),
1097 if (current_editor_file
)
1099 lang_plugin
->current_editor_filename
= g_file_get_path (current_editor_file
);
1100 g_object_unref (current_editor_file
);
1103 install_support (lang_plugin
);
1106 g_signal_connect (lang_plugin
->current_editor
, "language-changed",
1107 G_CALLBACK (on_editor_language_changed
),
1112 on_value_removed_current_editor (AnjutaPlugin
*plugin
, const gchar
*name
,
1115 PythonPlugin
*lang_plugin
;
1116 lang_plugin
= (PythonPlugin
*) (plugin
);
1117 if (lang_plugin
->current_editor
)
1118 g_signal_handlers_disconnect_by_func (lang_plugin
->current_editor
,
1119 G_CALLBACK (on_editor_language_changed
),
1122 uninstall_support (lang_plugin
);
1124 g_free (lang_plugin
->current_editor_filename
);
1125 lang_plugin
->current_editor_filename
= NULL
;
1126 lang_plugin
->current_editor
= NULL
;
1130 on_auto_indent (GtkAction
*action
, gpointer data
)
1132 gint line_start
, line_end
;
1135 gboolean has_selection
;
1137 PythonPlugin
*lang_plugin
;
1138 IAnjutaEditor
*editor
;
1139 lang_plugin
= (PythonPlugin
*) (data
);
1140 editor
= IANJUTA_EDITOR (lang_plugin
->current_editor
);
1142 has_selection
= ianjuta_editor_selection_has_selection
1143 (IANJUTA_EDITOR_SELECTION (editor
), NULL
);
1146 IAnjutaIterable
*sel_start
, *sel_end
;
1147 sel_start
= ianjuta_editor_selection_get_start (IANJUTA_EDITOR_SELECTION (editor
),
1149 sel_end
= ianjuta_editor_selection_get_end (IANJUTA_EDITOR_SELECTION (editor
),
1151 line_start
= ianjuta_editor_get_line_from_position (editor
, sel_start
, NULL
);
1152 line_end
= ianjuta_editor_get_line_from_position (editor
, sel_end
, NULL
);
1153 g_object_unref (sel_start
);
1154 g_object_unref (sel_end
);
1158 line_start
= ianjuta_editor_get_lineno (IANJUTA_EDITOR(editor
), NULL
);
1159 line_end
= line_start
;
1161 ianjuta_document_begin_undo_action (IANJUTA_DOCUMENT(editor
), NULL
);
1162 initialize_indentation_params (lang_plugin
);
1164 for (insert_line
= line_start
; insert_line
<= line_end
; insert_line
++)
1166 gint line_indent_spaces
= 0;
1167 line_indent
= get_line_auto_indentation (lang_plugin
, editor
,
1169 &line_indent_spaces
);
1170 /* DEBUG_PRINT ("Line indent for line %d = %d", insert_line, line_indent); */
1171 set_line_indentation (editor
, insert_line
, line_indent
, line_indent_spaces
);
1173 ianjuta_document_end_undo_action (IANJUTA_DOCUMENT(editor
), NULL
);
1176 static GtkActionEntry actions
[] = {
1183 "ActionEditAutoindent",
1184 GTK_STOCK_NEW
, //ANJUTA_STOCK_AUTOINDENT,
1185 N_("Auto-Indent"), "<control>i",
1186 N_("Auto-indent current line or selection based on indentation settings"),
1187 G_CALLBACK (on_auto_indent
)
1192 register_stock_icons (AnjutaPlugin
*plugin
)
1194 static gboolean registered
= FALSE
;
1200 /* Register stock icons */
1201 BEGIN_REGISTER_ICON (plugin
);
1202 // REGISTER_ICON_FULL (ANJUTA_PIXMAP_SWAP, ANJUTA_STOCK_SWAP);
1203 // REGISTER_ICON_FULL (ANJUTA_PIXMAP_COMPLETE, ANJUTA_STOCK_COMPLETE);
1204 // REGISTER_ICON_FULL (ANJUTA_PIXMAP_AUTOCOMPLETE, ANJUTA_STOCK_AUTOCOMPLETE);
1205 // REGISTER_ICON_FULL (ANJUTA_PIXMAP_AUTOINDENT, ANJUTA_STOCK_AUTOINDENT);
1209 // CODE from git PLUGIN
1211 on_project_root_added (AnjutaPlugin
*plugin
, const gchar
*name
,
1212 const GValue
*value
, gpointer user_data
)
1214 PythonPlugin
*python_plugin
;
1215 gchar
*project_root_uri
;
1218 python_plugin
= ANJUTA_PLUGIN_PYTHON (plugin
);
1220 g_free (python_plugin
->project_root_directory
);
1221 project_root_uri
= g_value_dup_string (value
);
1222 file
= g_file_new_for_uri (project_root_uri
);
1223 python_plugin
->project_root_directory
= g_file_get_path (file
);
1224 g_object_unref (file
);
1225 g_free (project_root_uri
);
1229 on_project_root_removed (AnjutaPlugin
*plugin
, const gchar
*name
,
1233 PythonPlugin
*python_plugin
;
1235 python_plugin
= ANJUTA_PLUGIN_PYTHON (plugin
);
1237 g_free (python_plugin
->project_root_directory
);
1238 python_plugin
->project_root_directory
= NULL
;
1240 ui
= anjuta_shell_get_ui (plugin
->shell
, NULL
);
1244 python_plugin_activate (AnjutaPlugin
*plugin
)
1248 PythonPlugin
*python_plugin
;
1249 static gboolean initialized
= FALSE
;
1251 python_plugin
= (PythonPlugin
*) plugin
;
1255 register_stock_icons (plugin
);
1259 python_plugin
->prefs
= anjuta_shell_get_preferences (plugin
->shell
, NULL
);
1261 /* Add all UI actions and merge UI */
1262 ui
= anjuta_shell_get_ui (plugin
->shell
, NULL
);
1264 python_plugin
->action_group
=
1266 anjuta_ui_add_action_group_entries (ui
, "ActionGroupPythonAssist",
1267 _("Python Assistance"),
1269 G_N_ELEMENTS (actions
),
1270 GETTEXT_PACKAGE
, TRUE
,
1272 python_plugin
->uiid
= anjuta_ui_merge (ui
, UI_FILE
);
1274 initialized
= FALSE
;
1277 python_plugin
->project_root_watch_id
= anjuta_plugin_add_watch (plugin
,
1278 IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI
,
1279 on_project_root_added
,
1280 on_project_root_removed
,
1283 python_plugin
->editor_watch_id
= anjuta_plugin_add_watch (plugin
,
1284 IANJUTA_DOCUMENT_MANAGER_CURRENT_DOCUMENT
,
1285 on_value_added_current_editor
,
1286 on_value_removed_current_editor
,
1292 python_plugin_deactivate (AnjutaPlugin
*plugin
)
1296 PythonPlugin
*lang_plugin
;
1297 lang_plugin
= (PythonPlugin
*) (plugin
);
1298 DEBUG_PRINT ("%s", "PythonPlugin: Dectivating PythonPlugin plugin ...");
1300 anjuta_plugin_remove_watch (plugin
,
1301 lang_plugin
->editor_watch_id
,
1303 anjuta_plugin_remove_watch (plugin
,
1304 lang_plugin
->project_root_watch_id
,
1308 ui
= anjuta_shell_get_ui (plugin
->shell
, NULL
);
1309 anjuta_ui_remove_action_group (ui
, ANJUTA_PLUGIN_PYTHON(plugin
)->action_group
);
1310 anjuta_ui_unmerge (ui
, ANJUTA_PLUGIN_PYTHON(plugin
)->uiid
);
1312 DEBUG_PRINT ("%s", "PythonPlugin: Deactivated plugin.");
1318 python_plugin_finalize (GObject
*obj
)
1320 /* Finalization codes here */
1321 G_OBJECT_CLASS (parent_class
)->finalize (obj
);
1325 python_plugin_dispose (GObject
*obj
)
1327 /* Disposition codes */
1328 PythonPlugin
*plugin
= (PythonPlugin
*)obj
;
1330 if (plugin
->settings
)
1331 g_object_unref (plugin
->settings
);
1332 plugin
->settings
= NULL
;
1334 G_OBJECT_CLASS (parent_class
)->dispose (obj
);
1338 python_plugin_instance_init (GObject
*obj
)
1340 PythonPlugin
*plugin
= (PythonPlugin
*)obj
;
1341 plugin
->action_group
= NULL
;
1342 plugin
->current_editor
= NULL
;
1343 plugin
->current_language
= NULL
;
1344 plugin
->editor_watch_id
= 0;
1346 plugin
->assist
= NULL
;
1347 plugin
->settings
= g_settings_new (PREF_SCHEMA
);
1351 python_plugin_class_init (GObjectClass
*klass
)
1353 AnjutaPluginClass
*plugin_class
= ANJUTA_PLUGIN_CLASS (klass
);
1355 parent_class
= g_type_class_peek_parent (klass
);
1357 plugin_class
->activate
= python_plugin_activate
;
1358 plugin_class
->deactivate
= python_plugin_deactivate
;
1359 klass
->finalize
= python_plugin_finalize
;
1360 klass
->dispose
= python_plugin_dispose
;
1365 ipreferences_merge (IAnjutaPreferences
* ipref
, AnjutaPreferences
* prefs
,
1368 /* Add preferences */
1369 PythonPlugin
* plugin
= ANJUTA_PLUGIN_PYTHON (ipref
);
1370 gchar
*objects
[] = {"python_preferences_dialog", NULL
};
1371 plugin
->bxml
= gtk_builder_new();
1372 gtk_builder_add_objects_from_file(plugin
->bxml
, PROPERTIES_FILE_UI
, objects
, NULL
);
1373 anjuta_preferences_add_from_builder (prefs
,
1376 "preferences", _("Python"),
1381 ipreferences_unmerge (IAnjutaPreferences
* ipref
, AnjutaPreferences
* prefs
,
1384 PythonPlugin
* plugin
= ANJUTA_PLUGIN_PYTHON (ipref
);
1385 anjuta_preferences_remove_page(prefs
, _("Python"));
1386 g_object_unref (plugin
->bxml
);
1390 ipreferences_iface_init (IAnjutaPreferencesIface
* iface
)
1392 iface
->merge
= ipreferences_merge
;
1393 iface
->unmerge
= ipreferences_unmerge
;
1396 //ANJUTA_PLUGIN_BOILERPLATE (PythonPlugin, python_plugin);
1398 ANJUTA_PLUGIN_BEGIN (PythonPlugin
, python_plugin
);
1399 ANJUTA_PLUGIN_ADD_INTERFACE(ipreferences
, IANJUTA_TYPE_PREFERENCES
);
1403 ANJUTA_SIMPLE_PLUGIN (PythonPlugin
, python_plugin
);