[gnome-builder] python: improve unindent of else/elif positioning
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] python: improve unindent of else/elif positioning
- Date: Sat, 25 Apr 2015 20:58:48 +0000 (UTC)
commit 3fd0da4c37209f179961f7e2c09a9cc3acd5762c
Author: Christian Hergert <christian hergert me>
Date: Sat Apr 25 13:27:12 2015 -0700
python: improve unindent of else/elif positioning
This tries to handle tabs a bit better. Additionally, it tries to ignore
lines who's 'if' or 'for' are after the visual column we started on.
Hopefully I didn't break anything else!
libide/python/ide-python-indenter.c | 126 +++++++++++++++++++++++++++--------
1 files changed, 99 insertions(+), 27 deletions(-)
---
diff --git a/libide/python/ide-python-indenter.c b/libide/python/ide-python-indenter.c
index 30a0868..5cfe94a 100644
--- a/libide/python/ide-python-indenter.c
+++ b/libide/python/ide-python-indenter.c
@@ -21,6 +21,7 @@
#include <gtksourceview/gtksource.h>
#include <string.h>
+#include "ide-debug.h"
#include "ide-python-indenter.h"
struct _IdePythonIndenter
@@ -522,59 +523,130 @@ indent_for_pair (IdePythonIndenter *python,
return indent_colon (python, text_view, begin, end, iter);
}
+static gboolean
+move_first_nonspace_char (GtkTextIter *iter)
+{
+ g_assert (iter != NULL);
+
+ gtk_text_iter_set_line_offset (iter, 0);
+
+ while (TRUE)
+ {
+ gunichar ch;
+
+ ch = gtk_text_iter_get_char (iter);
+ if (!g_unichar_isspace (ch))
+ break;
+
+ if (gtk_text_iter_ends_line (iter))
+ break;
+
+ if (!gtk_text_iter_forward_char (iter))
+ break;
+ }
+
+ return g_unichar_isspace (gtk_text_iter_get_char (iter));
+}
+
+static gboolean
+move_to_visual_column (GtkSourceView *sv,
+ GtkTextIter *iter,
+ guint line_offset)
+{
+ gtk_text_iter_set_line_offset (iter, 0);
+
+ while (line_offset > gtk_source_view_get_visual_column (sv, iter))
+ {
+ if (gtk_text_iter_ends_line (iter))
+ break;
+ gtk_text_iter_forward_char (iter);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+move_previous_line (GtkSourceView *sv,
+ GtkTextIter *iter,
+ guint line_offset)
+{
+ guint line;
+
+ line = gtk_text_iter_get_line (iter);
+ if (line == 0)
+ return FALSE;
+
+ gtk_text_iter_set_line (iter, line - 1);
+
+ return move_to_visual_column (sv, iter, line_offset);
+}
+
static gchar *
maybe_unindent_else_or_elif (IdePythonIndenter *python,
- GtkTextIter *begin,
- GtkTextIter *end)
+ GtkTextView *tv,
+ GtkTextIter *begin,
+ GtkTextIter *end)
{
GtkTextIter copy = *begin;
+ GtkSourceView *sv;
gboolean matches;
gchar *slice;
+ IDE_ENTRY;
+
+ sv = GTK_SOURCE_VIEW (tv);
+
gtk_text_iter_backward_chars (©, 4);
slice = gtk_text_iter_get_slice (©, begin);
matches = g_str_equal (slice, "else") || g_str_equal (slice, "elif");
- /* paranoia check to make sure this isn't part of a word. */
+ /* only continue if this is the first word on the line */
if (matches)
- matches = (!gtk_text_iter_backward_char (©) ||
- g_unichar_isspace (gtk_text_iter_get_char (©)));
+ {
+ guint line_offset;
+
+ line_offset = gtk_text_iter_get_line_offset (©);
+ move_first_nonspace_char (©);
+ if (line_offset != gtk_text_iter_get_line_offset (©))
+ IDE_GOTO (failure);
+ }
if (matches)
{
- /*
- * TODO: This doesn't handle unindent properly for multi line
- * if or for blocks.
- */
- while (!(line_starts_with (©, "if ") || line_starts_with (©, "for ")) ||
- !line_ends_with (©, ":"))
+ guint line_offset;
+
+ line_offset = gtk_source_view_get_visual_column (sv, ©);
+
+ while (TRUE)
{
- guint if_line;
+ if (!move_previous_line (sv, ©, line_offset))
+ IDE_GOTO (failure);
- if (!(if_line = gtk_text_iter_get_line (©)))
- break;
+ move_first_nonspace_char (©);
- gtk_text_iter_set_line_offset (©, 0);
- gtk_text_iter_set_line (©, if_line - 1);
+ if (gtk_source_view_get_visual_column (sv, ©) > line_offset)
+ continue;
- while (g_unichar_isspace (gtk_text_iter_get_char (©)) &&
- !gtk_text_iter_ends_line (©))
- if (!gtk_text_iter_forward_char (©))
- break;
+ if (line_starts_with (©, "if ") || line_starts_with (©, "for "))
+ break;
}
- if ((line_starts_with (©, "if ") || line_starts_with (©, "for ")) &&
- line_ends_with (©, ":"))
+ move_first_nonspace_char (©);
+
+ if ((line_starts_with (©, "if ") || line_starts_with (©, "for ")))
{
- gtk_text_iter_set_line_offset (begin,
- gtk_text_iter_get_line_offset (©));
- return slice;
+ guint line_offset;
+
+ line_offset = gtk_source_view_get_visual_column (sv, ©);
+ move_to_visual_column (sv, begin, line_offset);
+ IDE_RETURN (slice);
}
}
+failure:
g_free (slice);
- return NULL;
+ IDE_RETURN (NULL);
}
static gchar *
@@ -596,7 +668,7 @@ ide_python_indenter_format (IdeIndenter *indenter,
gtk_text_iter_backward_char (&iter);
ch = gtk_text_iter_get_char (&iter);
if (ch == 'e' || ch == 'f')
- return maybe_unindent_else_or_elif (python, begin, end);
+ return maybe_unindent_else_or_elif (python, text_view, begin, end);
iter = *begin;
line = gtk_text_iter_get_line (&iter);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]