diff --git a/moo.kdevelop b/moo.kdevelop index dcbe0ff4..9c952df1 100644 --- a/moo.kdevelop +++ b/moo.kdevelop @@ -24,7 +24,7 @@ . false - + C @@ -39,7 +39,7 @@ ./medit executable / - + false false @@ -198,12 +198,12 @@ - + --g-fatal-warnings - - - - + + + + true false true @@ -268,16 +268,16 @@ - + A new empty GAP source file - + A new empty C++ file. - + A new empty header file for C/C++. - + A new empty C file. @@ -304,7 +304,7 @@ - + set m_,_ theValue diff --git a/moo/mooedit/mooedit.c b/moo/mooedit/mooedit.c index 802bf6a9..e1a6b80b 100644 --- a/moo/mooedit/mooedit.c +++ b/moo/mooedit/mooedit.c @@ -1320,3 +1320,306 @@ moo_edit_get_bookmarks_in_range (MooEdit *edit, return g_slist_reverse (range); } + + +/*****************************************************************************/ +/* Comment/uncomment + */ + +/* TODO: all this stuff, it's pretty lame */ + +static gboolean +has_comments (MooEdit *edit, + gboolean *single_line, + gboolean *multi_line) +{ + MooLang *lang; + + lang = moo_text_view_get_lang (MOO_TEXT_VIEW (edit)); + + *single_line = lang->line_comment != NULL; + *multi_line = lang->block_comment_start && + lang->block_comment_end; + + return *single_line || *multi_line; +} + + +static void +line_comment (GtkTextBuffer *buffer, + const char *comment_string, + GtkTextIter *start, + GtkTextIter *end) +{ + int first, last, i; + GtkTextIter iter; + char *comment_and_space; + + g_return_if_fail (comment_string && comment_string[0]); + + first = gtk_text_iter_get_line (start); + last = gtk_text_iter_get_line (end); + + if (!gtk_text_iter_equal (start, end) && gtk_text_iter_starts_line (end)) + last -= 1; + + comment_and_space = g_strdup_printf ("%s ", comment_string); + + for (i = first; i <= last; ++i) + { + gtk_text_buffer_get_iter_at_line (buffer, &iter, i); + + if (gtk_text_iter_ends_line (&iter)) + gtk_text_buffer_insert (buffer, &iter, comment_string, -1); + else + gtk_text_buffer_insert (buffer, &iter, comment_and_space, -1); + } + + g_free (comment_and_space); +} + + +static void +line_uncomment (GtkTextBuffer *buffer, + const char *comment_string, + GtkTextIter *start, + GtkTextIter *end) +{ + int first, last, i; + guint chars; + + g_return_if_fail (comment_string && comment_string[0]); + + first = gtk_text_iter_get_line (start); + last = gtk_text_iter_get_line (end); + + if (!gtk_text_iter_equal (start, end) && gtk_text_iter_starts_line (end)) + last -= 1; + + chars = g_utf8_strlen (comment_string, -1); + + for (i = first; i <= last; ++i) + { + char *text; + + gtk_text_buffer_get_iter_at_line (buffer, start, i); + *end = *start; + gtk_text_iter_forward_chars (end, chars); + text = gtk_text_iter_get_slice (start, end); + + if (!strcmp (comment_string, text)) + { + if (gtk_text_iter_get_char (end) == ' ') + gtk_text_iter_forward_char (end); + gtk_text_buffer_delete (buffer, start, end); + } + + g_free (text); + } +} + + +static void +iter_to_line_end (GtkTextIter *iter) +{ + if (!gtk_text_iter_ends_line (iter)) + gtk_text_iter_forward_to_line_end (iter); +} + +static void +block_comment (GtkTextBuffer *buffer, + const char *comment_start, + const char *comment_end, + GtkTextIter *start, + GtkTextIter *end) +{ + GtkTextMark *end_mark; + + g_return_if_fail (comment_start && comment_start[0]); + g_return_if_fail (comment_end && comment_end[0]); + + if (gtk_text_iter_equal (start, end)) + { + gtk_text_iter_set_line_offset (start, 0); + iter_to_line_end (end); + } + else + { + if (gtk_text_iter_starts_line (end)) + { + gtk_text_iter_backward_line (end); + iter_to_line_end (end); + } + } + + end_mark = gtk_text_buffer_create_mark (buffer, NULL, end, FALSE); + gtk_text_buffer_insert (buffer, start, comment_start, -1); + gtk_text_buffer_get_iter_at_mark (buffer, start, end_mark); + gtk_text_buffer_insert (buffer, start, comment_end, -1); + gtk_text_buffer_delete_mark (buffer, end_mark); +} + + +static void +block_uncomment (GtkTextBuffer *buffer, + const char *comment_start, + const char *comment_end, + GtkTextIter *start, + GtkTextIter *end) +{ + GtkTextIter start1, start2, end1, end2; + GtkTextMark *mark1, *mark2; + GtkTextIter limit; + gboolean found; + + g_return_if_fail (comment_start && comment_start[0]); + g_return_if_fail (comment_end && comment_end[0]); + + if (!gtk_text_iter_equal (start, end) && gtk_text_iter_starts_line (end)) + { + gtk_text_iter_backward_line (end); + iter_to_line_end (end); + } + + limit = *end; + found = moo_text_search_forward (start, comment_start, 0, + &start1, &start2, + &limit); + + if (!found) + { + gtk_text_iter_set_line_offset (&limit, 0); + found = gtk_text_iter_backward_search (start, comment_start, 0, + &start1, &start2, + &limit); + } + + if (!found) + return; + + limit = start2; + found = gtk_text_iter_backward_search (end, comment_end, 0, + &end1, &end2, &limit); + + if (!found) + { + limit = *end; + iter_to_line_end (&limit); + found = moo_text_search_forward (end, comment_end, 0, + &end1, &end2, &limit); + } + + if (!found) + return; + + g_assert (gtk_text_iter_compare (&start2, &end1) < 0); + + mark1 = gtk_text_buffer_create_mark (buffer, NULL, &end1, FALSE); + mark2 = gtk_text_buffer_create_mark (buffer, NULL, &end2, FALSE); + gtk_text_buffer_delete (buffer, &start1, &start2); + gtk_text_buffer_get_iter_at_mark (buffer, &end1, mark1); + gtk_text_buffer_get_iter_at_mark (buffer, &end2, mark2); + gtk_text_buffer_delete (buffer, &end1, &end2); + gtk_text_buffer_delete_mark (buffer, mark1); + gtk_text_buffer_delete_mark (buffer, mark2); +} + + +static void +begin_comment_action (MooEdit *edit) +{ + gtk_text_buffer_begin_user_action (get_buffer (edit)); + moo_text_buffer_begin_interactive_action (get_moo_buffer (edit)); +} + +static void +end_comment_action (MooEdit *edit) +{ + gtk_text_buffer_end_user_action (get_buffer (edit)); + moo_text_buffer_end_interactive_action (get_moo_buffer (edit)); +} + + +void +moo_edit_comment (MooEdit *edit) +{ + MooLang *lang; + GtkTextIter start, end; + GtkTextBuffer *buffer; + gboolean has_selection, single_line, multi_line; + gboolean adjust_selection = FALSE, move_insert = FALSE; + int sel_start_line, sel_start_offset; + + g_return_if_fail (MOO_IS_EDIT (edit)); + + lang = moo_text_view_get_lang (MOO_TEXT_VIEW (edit)); + + if (!has_comments (edit, &single_line, &multi_line)) + return; + + buffer = get_buffer (edit); + has_selection = gtk_text_buffer_get_selection_bounds (buffer, &start, &end); + + begin_comment_action (edit); + + if (has_selection) + { + GtkTextIter iter; + adjust_selection = TRUE; + gtk_text_buffer_get_iter_at_mark (buffer, &iter, + gtk_text_buffer_get_insert (buffer)); + move_insert = gtk_text_iter_equal (&iter, &start); + sel_start_line = gtk_text_iter_get_line (&start); + sel_start_offset = gtk_text_iter_get_line_offset (&start); + } + + /* FIXME */ + if (single_line) + line_comment (buffer, lang->line_comment, &start, &end); + else + block_comment (buffer, lang->block_comment_start, + lang->block_comment_end, &start, &end); + + + if (adjust_selection) + { + const char *mark = move_insert ? "insert" : "selection_bound"; + gtk_text_buffer_get_iter_at_line_offset (buffer, &start, + sel_start_line, + sel_start_offset); + gtk_text_buffer_move_mark_by_name (buffer, mark, &start); + } + + end_comment_action (edit); +} + + +void +moo_edit_uncomment (MooEdit *edit) +{ + MooLang *lang; + GtkTextIter start, end; + GtkTextBuffer *buffer; + gboolean single_line, multi_line; + + g_return_if_fail (MOO_IS_EDIT (edit)); + + lang = moo_text_view_get_lang (MOO_TEXT_VIEW (edit)); + + if (!has_comments (edit, &single_line, &multi_line)) + return; + + buffer = get_buffer (edit); + gtk_text_buffer_get_selection_bounds (buffer, &start, &end); + + begin_comment_action (edit); + + /* FIXME */ + if (single_line) + line_uncomment (buffer, lang->line_comment, &start, &end); + else + block_uncomment (buffer, lang->block_comment_start, + lang->block_comment_end, &start, &end); + + end_comment_action (edit); +} diff --git a/moo/mooedit/mooedit.h b/moo/mooedit/mooedit.h index 958e4595..918e3008 100644 --- a/moo/mooedit/mooedit.h +++ b/moo/mooedit/mooedit.h @@ -179,6 +179,9 @@ GSList *moo_edit_get_bookmarks_in_range(MooEdit *edit, int first_line, int last_line); +void moo_edit_comment (MooEdit *edit); +void moo_edit_uncomment (MooEdit *edit); + G_END_DECLS diff --git a/moo/mooedit/mooeditwindow.c b/moo/mooedit/mooeditwindow.c index fa8d1073..e7b097f4 100644 --- a/moo/mooedit/mooeditwindow.c +++ b/moo/mooedit/mooeditwindow.c @@ -561,6 +561,24 @@ static void moo_edit_window_class_init (MooEditWindowClass *klass) "condition::sensitive", "has-open-document", NULL); + moo_window_class_new_action (window_class, "Comment", + "name", "Comment", + "label", "Comment", + "tooltip", "Comment", + "closure-callback", moo_edit_comment, + "closure-proxy-func", moo_edit_window_get_active_doc, + "condition::sensitive", "has-open-document", + NULL); + + moo_window_class_new_action (window_class, "Uncomment", + "name", "Uncomment", + "label", "Uncomment", + "tooltip", "Uncomment", + "closure-callback", moo_edit_uncomment, + "closure-proxy-func", moo_edit_window_get_active_doc, + "condition::sensitive", "has-open-document", + NULL); + moo_window_class_new_action_custom (window_class, LANG_ACTION_ID, (MooWindowActionFunc) create_lang_action, NULL, NULL); diff --git a/moo/mooedit/moolang.c b/moo/mooedit/moolang.c index 6db77461..d95ff017 100644 --- a/moo/mooedit/moolang.c +++ b/moo/mooedit/moolang.c @@ -354,6 +354,9 @@ _moo_lang_free (MooLang *lang) g_free (lang->sample); g_free (lang->brackets); + g_free (lang->line_comment); + g_free (lang->block_comment_start); + g_free (lang->block_comment_end); g_slist_foreach (lang->mime_types, (GFunc) g_free, NULL); g_slist_free (lang->mime_types); diff --git a/moo/mooedit/moolang.h b/moo/mooedit/moolang.h index a4330b7b..d5e868f7 100644 --- a/moo/mooedit/moolang.h +++ b/moo/mooedit/moolang.h @@ -56,9 +56,9 @@ struct _MooLang { GSList *extensions; /* list of globs */ char *brackets; - char *single_line_comment; - char *multi_line_comment_start; - char *multi_line_comment_end; + char *line_comment; + char *block_comment_start; + char *block_comment_end; char *sample; diff --git a/moo/mooedit/moolangmgr.c b/moo/mooedit/moolangmgr.c index f6ca36dc..c5977016 100644 --- a/moo/mooedit/moolangmgr.c +++ b/moo/mooedit/moolangmgr.c @@ -636,8 +636,15 @@ moo_lang_finish_build (MooLang *lang, moo_lang_parse_mime_types (lang, xml->mimetypes); if (xml->extensions) moo_lang_parse_extensions (lang, xml->extensions); + if (xml->general) + { lang->brackets = g_strdup (xml->general->brackets); + lang->line_comment = g_strdup (xml->general->single_line_start); + lang->block_comment_start = g_strdup (xml->general->multi_line_start); + lang->block_comment_end = g_strdup (xml->general->multi_line_end); + } + lang->sample = g_strdup (xml->sample); for (l = xml->syntax->contexts; l != NULL; l = l->next) diff --git a/moo/moopython/mooedit-pygtk.defs b/moo/moopython/mooedit-pygtk.defs index e18a8c4c..4296f72c 100644 --- a/moo/moopython/mooedit-pygtk.defs +++ b/moo/moopython/mooedit-pygtk.defs @@ -98,9 +98,9 @@ '("GSList*" "mime_types") '("GSList*" "extensions") '("char*" "brackets") - '("char*" "single_line_comment") - '("char*" "multi_line_comment_start") - '("char*" "multi_line_comment_end") + '("char*" "line_comment") + '("char*" "block_comment_start") + '("char*" "block_comment_end") '("char*" "sample") ) ) diff --git a/tests/medit-ui.xml b/tests/medit-ui.xml index 599dc28d..49772d2b 100644 --- a/tests/medit-ui.xml +++ b/tests/medit-ui.xml @@ -34,6 +34,9 @@ + + +