Fix uncommenting multi-line comments when cursor is on a delimiter

If the cursor was inside one of the comment's delimiters, the code used
to look for another delimiter, leading to removing previous comment's
start.  Moreover, the code assumed the delimiter will always be found,
leading to improper deletions if a delimiter could not be found (either
because of the above problem or because the comment wasn't terminated).

Also, the code used document_find_text() which, if the searched text
cannot be found on the requested direction, either wraps or asks the
user whether to wrap.  Wrapping is wrong if there is more than one
single comment in the file, and the dialog is confusing for the use
since she didn't ask for it.

So, rework the code for it to correctly find the delimiters, and not
to wrap search or ask the user.  It is also simpler by reusing some
already existing code.
This commit is contained in:
Colomban Wendling 2012-10-12 20:40:38 +02:00
parent 206c39cb6a
commit 220ace841c

View File

@ -109,6 +109,7 @@ static const gchar *snippets_find_completion_by_name(const gchar *type, const gc
static void snippets_make_replacements(GeanyEditor *editor, GString *pattern); static void snippets_make_replacements(GeanyEditor *editor, GString *pattern);
static gssize replace_cursor_markers(GeanyEditor *editor, GString *pattern); static gssize replace_cursor_markers(GeanyEditor *editor, GString *pattern);
static GeanyFiletype *editor_get_filetype_at_current_pos(GeanyEditor *editor); static GeanyFiletype *editor_get_filetype_at_current_pos(GeanyEditor *editor);
static gboolean sci_is_blank_line(ScintillaObject *sci, gint line);
void editor_snippets_free(void) void editor_snippets_free(void)
@ -2820,47 +2821,68 @@ static void real_comment_multiline(GeanyEditor *editor, gint line_start, gint la
} }
static void real_uncomment_multiline(GeanyEditor *editor) /* find @p text inside the range of the current style */
static gint find_in_current_style(ScintillaObject *sci, const gchar *text, gboolean backwards)
{
gint start = sci_get_current_position(sci);
gint end = start;
gint len = sci_get_length(sci);
gint current_style = sci_get_style_at(sci, start);
struct Sci_TextToFind ttf;
while (start > 0 && sci_get_style_at(sci, start - 1) == current_style)
start -= 1;
while (end < len && sci_get_style_at(sci, end + 1) == current_style)
end += 1;
ttf.lpstrText = (gchar*) text;
ttf.chrg.cpMin = backwards ? end + 1 : start;
ttf.chrg.cpMax = backwards ? start : end + 1;
return sci_find_text(sci, 0, &ttf);
}
static void sci_delete_line(ScintillaObject *sci, gint line)
{
gint start = sci_get_position_from_line(sci, line);
gint len = sci_get_line_length(sci, line);
SSM(sci, SCI_DELETERANGE, start, len);
}
static gboolean real_uncomment_multiline(GeanyEditor *editor)
{ {
/* find the beginning of the multi line comment */ /* find the beginning of the multi line comment */
gint pos, line, len, x; gint start, end, start_line, end_line;
gchar *linebuf;
GeanyDocument *doc;
GeanyFiletype *ft; GeanyFiletype *ft;
const gchar *co, *cc; const gchar *co, *cc;
g_return_if_fail(editor != NULL && editor->document->file_type != NULL); g_return_val_if_fail(editor != NULL && editor->document->file_type != NULL, FALSE);
doc = editor->document;
ft = editor_get_filetype_at_current_pos(editor); ft = editor_get_filetype_at_current_pos(editor);
if (! filetype_get_comment_open_close(ft, FALSE, &co, &cc)) if (! filetype_get_comment_open_close(ft, FALSE, &co, &cc))
g_return_if_reached(); g_return_val_if_reached(FALSE);
/* remove comment open chars */ start = find_in_current_style(editor->sci, co, TRUE);
pos = document_find_text(doc, co, NULL, 0, TRUE, FALSE, NULL); end = find_in_current_style(editor->sci, cc, FALSE);
SSM(editor->sci, SCI_DELETEBACK, 0, 0);
/* check whether the line is empty and can be deleted */ if (start < 0 || end < 0 || start > end /* who knows */)
line = sci_get_line_from_position(editor->sci, pos); return FALSE;
len = sci_get_line_length(editor->sci, line);
linebuf = sci_get_line(editor->sci, line); start_line = sci_get_line_from_position(editor->sci, start);
x = 0; end_line = sci_get_line_from_position(editor->sci, end);
while (linebuf[x] != '\0' && isspace(linebuf[x])) x++;
if (x == len) SSM(editor->sci, SCI_LINEDELETE, 0, 0);
g_free(linebuf);
/* remove comment close chars */ /* remove comment close chars */
pos = document_find_text(doc, cc, NULL, 0, FALSE, FALSE, NULL); SSM(editor->sci, SCI_DELETERANGE, end, strlen(cc));
SSM(editor->sci, SCI_DELETEBACK, 0, 0); if (sci_is_blank_line(editor->sci, end_line))
sci_delete_line(editor->sci, end_line);
/* check whether the line is empty and can be deleted */ /* remove comment open chars (do it last since it would move the end position) */
line = sci_get_line_from_position(editor->sci, pos); SSM(editor->sci, SCI_DELETERANGE, start, strlen(co));
len = sci_get_line_length(editor->sci, line); if (sci_is_blank_line(editor->sci, start_line))
linebuf = sci_get_line(editor->sci, line); sci_delete_line(editor->sci, start_line);
x = 0;
while (linebuf[x] != '\0' && isspace(linebuf[x])) x++; return TRUE;
if (x == len) SSM(editor->sci, SCI_LINEDELETE, 0, 0);
g_free(linebuf);
} }
@ -2993,7 +3015,7 @@ gint editor_do_uncomment(GeanyEditor *editor, gint line, gboolean toggle)
style_comment = get_multiline_comment_style(editor, line_start); style_comment = get_multiline_comment_style(editor, line_start);
if (sci_get_style_at(editor->sci, line_start + x) == style_comment) if (sci_get_style_at(editor->sci, line_start + x) == style_comment)
{ {
real_uncomment_multiline(editor); if (real_uncomment_multiline(editor))
count = 1; count = 1;
} }
@ -3116,7 +3138,7 @@ void editor_do_comment_toggle(GeanyEditor *editor)
style_comment = get_multiline_comment_style(editor, line_start); style_comment = get_multiline_comment_style(editor, line_start);
if (sci_get_style_at(editor->sci, line_start + x) == style_comment) if (sci_get_style_at(editor->sci, line_start + x) == style_comment)
{ {
real_uncomment_multiline(editor); if (real_uncomment_multiline(editor))
count_uncommented++; count_uncommented++;
} }
else else