SF.net SVN: geany:[5729] trunk
ntrel at users.sourceforge.net
ntrel at xxxxx
Tue Apr 19 16:04:31 UTC 2011
Revision: 5729
http://geany.svn.sourceforge.net/geany/?rev=5729&view=rev
Author: ntrel
Date: 2011-04-19 16:04:31 +0000 (Tue, 19 Apr 2011)
Log Message:
-----------
Fix multiple snippet cursor positions for Tabs + Spaces mode.
Simplify editor_insert_snippet() code now we use cursor marker
strings.
Modified Paths:
--------------
trunk/ChangeLog
trunk/src/editor.c
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2011-04-17 13:41:54 UTC (rev 5728)
+++ trunk/ChangeLog 2011-04-19 16:04:31 UTC (rev 5729)
@@ -1,3 +1,11 @@
+2011-04-19 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
+
+ * src/editor.c:
+ Fix multiple snippet cursor positions for Tabs + Spaces mode.
+ Simplify editor_insert_snippet() code now we use cursor marker
+ strings.
+
+
2011-04-17 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
* src/plugindata.h, src/document.c, src/plugins.c, src/document.h,
@@ -4,7 +12,7 @@
plugins/geanyfunctions.h:
Add document_compare_by_tab_order() and
document_compare_by_tab_order_reverse() to the plugin API.
- * src/ui_uitls.c:
+ * src/ui_utils.c:
Use document_compare_by_tab_order() as default compare function
to sort the document list in the document notebook tab menu, this
fixes the currently broken default ordering.
Modified: trunk/src/editor.c
===================================================================
--- trunk/src/editor.c 2011-04-17 13:41:54 UTC (rev 5728)
+++ trunk/src/editor.c 2011-04-19 16:04:31 UTC (rev 5729)
@@ -117,8 +117,8 @@
const gchar *wc, gboolean stem);
static gsize count_indent_size(GeanyEditor *editor, const gchar *base_indent);
static const gchar *snippets_find_completion_by_name(const gchar *type, const gchar *name);
-static gssize snippets_make_replacements(GeanyEditor *editor, GString *pattern,
- gsize indent_size);
+static void snippets_make_replacements(GeanyEditor *editor, GString *pattern);
+static gssize replace_cursor_markers(GeanyEditor *editor, GString *pattern);
void editor_snippets_free(void)
@@ -2309,56 +2309,85 @@
}
-/* this only works with spaces only indentation on the lines */
-static void fix_line_indents(GeanyEditor *editor, gint line_start, gint line_end)
+static gboolean utils_regex_find(regex_t *regex, const gchar *haystack, gsize start,
+ gsize nmatches, regmatch_t *matches)
{
- ScintillaObject *sci = editor->sci;
- gint line, cur_line, cur_col, pos;
+ gint eflags = 0;
- /* get the line, col position as fixing indentation will move cursor to start of line */
- pos = sci_get_current_position(sci);
- cur_col = sci_get_col_from_position(sci, pos);
- cur_line = sci_get_current_line(sci);
-
- for (line = line_start; line <= line_end; line++)
+ if (start > 0)
{
- gint size = sci_get_line_indentation(sci, line);
+ gchar c = haystack[start - 1];
- /* set to 0 first to trigger proper indent creation */
- sci_set_line_indentation(sci, line, 0);
- sci_set_line_indentation(sci, line, size);
+ if (c == '\n' || c == '\r')
+ eflags = REG_NOTBOL;
}
- pos = scintilla_send_message(sci, SCI_FINDCOLUMN, cur_line, cur_col);
- sci_set_current_position(sci, pos, FALSE);
+ return regexec(regex, haystack + start, nmatches, matches, eflags) == 0;
}
-static void replace_leading_tabs(GString *str, const gchar *whitespace)
+/* match_index: which match to replace, 0 for whole regex.
+ * note: this doesn't support backreferences in replacements */
+static guint utils_string_regex_replace_all(GString *haystack,
+ regex_t *regex, guint match_index, const gchar *replace)
{
- regex_t regex;
gssize pos;
- regmatch_t matches[2];
- gchar *ptr;
+ regmatch_t matches[10];
+ guint ret = 0;
- if (regcomp(®ex, "^ *(\t)", 0) != 0)
+ g_return_val_if_fail(match_index < 10, 0);
+
+ /* ensure haystack->str is not null */
+ if (haystack->len == 0)
+ return 0;
+
+ pos = 0;
+ while (utils_regex_find(regex, haystack->str, pos, G_N_ELEMENTS(matches), matches))
{
- g_return_if_fail(FALSE);
+ regmatch_t *match = &matches[match_index];
+
+ g_return_val_if_fail(match->rm_so >= 0, FALSE);
+ pos += match->rm_so;
+ g_string_erase(haystack, pos, match->rm_eo - match->rm_so);
+ g_string_insert(haystack, pos, replace);
+ pos += strlen(replace);
+ ret++;
}
- ptr = str->str;
- while (ptr)
+ return ret;
+}
+
+
+static void fix_indentation(GeanyEditor *editor, GString *buf)
+{
+ const GeanyIndentPrefs *iprefs = editor_get_indent_prefs(editor);
+ gchar *whitespace;
+ regex_t regex;
+ gint cflags = REG_EXTENDED | REG_NEWLINE;
+
+ /* transform leading tabs into indent widths (in spaces) */
+ whitespace = g_strnfill(iprefs->width, ' ');
+ regcomp(®ex, "^ *(\t)", cflags);
+ while (utils_string_regex_replace_all(buf, ®ex, 1, whitespace));
+ regfree(®ex);
+
+ /* remaining tabs are for alignment */
+ if (iprefs->type != GEANY_INDENT_TYPE_TABS)
+ utils_string_replace_all(buf, "\t", whitespace);
+
+ /* use leading tabs */
+ if (iprefs->type != GEANY_INDENT_TYPE_SPACES)
{
- if (regexec(®ex, ptr,
- G_N_ELEMENTS(matches), matches, 0) != 0)
- break;
+ gchar *str;
- pos = matches[1].rm_so;
- g_return_if_fail(pos >= 0);
- pos += ptr - str->str;
- g_string_erase(str, pos, 1);
- g_string_insert(str, pos, whitespace);
- ptr = str->str + pos + strlen(whitespace);
+ /* for tabs+spaces mode we want the real tab width, not indent width */
+ setptr(whitespace, g_strnfill(sci_get_tab_width(editor->sci), ' '));
+ str = g_strdup_printf("^\t*(%s)", whitespace);
+
+ regcomp(®ex, str, cflags);
+ while (utils_string_regex_replace_all(buf, ®ex, 1, "\t"));
+ regfree(®ex);
+ g_free(str);
}
- regfree(®ex);
+ g_free(whitespace);
}
@@ -2385,11 +2414,10 @@
{
ScintillaObject *sci = editor->sci;
gint line_start = sci_get_line_from_position(sci, insert_pos);
- gint line_end;
gchar *whitespace;
GString *buf;
const gchar *eol = editor_get_eol_char(editor);
- const GeanyIndentPrefs *iprefs = editor_get_indent_prefs(editor);
+ gint idx;
g_return_if_fail(text);
g_return_if_fail(editor != NULL);
@@ -2405,7 +2433,8 @@
/* count indent size up to insert_pos instead of asking sci
* because there may be spaces after it */
gchar *tmp = sci_get_line(sci, line_start);
- gint idx = insert_pos - sci_get_position_from_line(sci, line_start);
+
+ idx = insert_pos - sci_get_position_from_line(sci, line_start);
tmp[idx] = '\0';
newline_indent_size = count_indent_size(editor, tmp);
g_free(tmp);
@@ -2424,32 +2453,19 @@
if (replace_newlines)
utils_string_replace_all(buf, "\n", eol);
- /* transform leading tabs into indent widths (in spaces) */
- whitespace = g_strnfill(iprefs->width, ' ');
- replace_leading_tabs(buf, whitespace);
- /* remaining tabs are for alignment */
- if (iprefs->type != GEANY_INDENT_TYPE_TABS)
- utils_string_replace_all(buf, "\t", whitespace);
- g_free(whitespace);
+ fix_indentation(editor, buf);
- sci_start_undo_action(sci);
-
- if (cursor_index >= 0)
+ idx = replace_cursor_markers(editor, buf);
+ if (idx >= 0)
{
- gint idx = utils_string_replace(buf, 0, -1, geany_cursor_marker, NULL);
-
sci_insert_text(sci, insert_pos, buf->str);
sci_set_current_position(sci, insert_pos + idx, FALSE);
}
else
sci_insert_text(sci, insert_pos, buf->str);
- /* fixup indentation (very useful for Tabs & Spaces indent type) */
- line_end = sci_get_line_from_position(sci, insert_pos + buf->len);
- fix_line_indents(editor, line_start, line_end);
snippet_cursor_insert_pos = sci_get_current_position(sci);
- sci_end_undo_action(sci);
g_string_free(buf, TRUE);
}
@@ -2480,13 +2496,9 @@
}
-static gssize replace_cursor_markers(GeanyEditor *editor, GString *pattern, gsize indent_size);
-
-static gssize snippets_make_replacements(GeanyEditor *editor, GString *pattern, gsize indent_size)
+static void snippets_make_replacements(GeanyEditor *editor, GString *pattern)
{
- gchar *whitespace;
GHashTable *specials;
- const GeanyIndentPrefs *iprefs = editor_get_indent_prefs(editor);
/* replace 'special' completions */
specials = g_hash_table_lookup(snippet_hash, "Special");
@@ -2498,20 +2510,9 @@
}
/* now transform other wildcards */
-
utils_string_replace_all(pattern, "%newline%", "\n");
+ utils_string_replace_all(pattern, "%ws%", "\t");
- /* if spaces are used, replace tabs with spaces
- * otherwise replace all %ws% by \t */
- if (iprefs->type == GEANY_INDENT_TYPE_SPACES)
- utils_string_replace_all(pattern, "\t", "%ws%");
- else
- utils_string_replace_all(pattern, "%ws%", "\t");
-
- whitespace = g_strnfill(iprefs->width, ' '); /* use spaces for indentation, will be fixed up */
- utils_string_replace_all(pattern, "%ws%", whitespace);
- g_free(whitespace);
-
/* replace %cursor% by a very unlikely string marker */
utils_string_replace_all(pattern, "%cursor%", geany_cursor_marker);
@@ -2520,62 +2521,36 @@
/* replace any template {foo} wildcards */
templates_replace_common(pattern, editor->document->file_name, editor->document->file_type, NULL);
-
- return replace_cursor_markers(editor, pattern, indent_size);
}
-static gssize replace_cursor_markers(GeanyEditor *editor, GString *pattern, gsize indent_size)
+static gssize replace_cursor_markers(GeanyEditor *editor, GString *pattern)
{
gssize cur_index = -1;
- gint i, idx, nl_count = 0;
+ gint i;
GList *temp_list = NULL;
- gint cursor_steps, old_cursor = 0;
+ gint cursor_steps = 0, old_cursor = 0;
i = 0;
- idx = 0;
- while ((cursor_steps = utils_strpos(pattern->str, geany_cursor_marker)) >= 0)
+ while (1)
{
- /* replace every newline (up to next cursor) with EOL,
- * count newlines and update cursor_steps after */
- while (1)
- {
- idx = utils_string_replace(pattern, idx, cursor_steps, "\n", editor_get_eol_char(editor));
- if (idx == -1)
- break;
+ cursor_steps = utils_string_replace(pattern, cursor_steps, -1, geany_cursor_marker, NULL);
+ if (cursor_steps == -1)
+ break;
- nl_count++;
- idx += editor_get_eol_char_len(editor);
-
- cursor_steps = utils_strpos(pattern->str, geany_cursor_marker);
- }
- utils_string_replace_first(pattern, geany_cursor_marker, "");
- idx = cursor_steps;
-
if (i++ > 0)
{
/* save the relative offset to each cursor position */
- cursor_steps += (nl_count * indent_size);
temp_list = g_list_prepend(temp_list, GINT_TO_POINTER(cursor_steps - old_cursor));
}
else
{
/* first cursor already includes newline positions */
- nl_count = 0;
cur_index = cursor_steps;
}
old_cursor = cursor_steps;
}
- /* replace remaining \n which may occur after the last cursor */
- while (1)
- {
- idx = utils_string_replace(pattern, idx, -1, "\n", editor_get_eol_char(editor));
- if (idx == -1)
- break;
- idx += editor_get_eol_char_len(editor);
- }
-
/* put the cursor positions for the most recent
* parsed snippet first, followed by any remaining positions */
i = 0;
@@ -5110,12 +5085,10 @@
*/
void editor_insert_snippet(GeanyEditor *editor, gint pos, const gchar *snippet)
{
- gint cursor_pos;
GString *pattern;
pattern = g_string_new(snippet);
- read_indent(editor, pos);
- cursor_pos = snippets_make_replacements(editor, pattern, strlen(indent));
- editor_insert_text_block(editor, pattern->str, pos, cursor_pos, -1, FALSE);
+ snippets_make_replacements(editor, pattern);
+ editor_insert_text_block(editor, pattern->str, pos, -1, -1, FALSE);
g_string_free(pattern, TRUE);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Commits
mailing list