diff --git a/plugins/markdown-actions/markdown-actions.vala b/plugins/markdown-actions/markdown-actions.vala index a446edaee..bd1da8b4b 100644 --- a/plugins/markdown-actions/markdown-actions.vala +++ b/plugins/markdown-actions/markdown-actions.vala @@ -76,25 +76,32 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services } if (evt.keyval == Gdk.Key.Return) { - char ul_marker; - int ol_number = 1; - string item_text; + // Get line text on which return was pressed var line = get_current_line (); - if (parse_unordered_list_item (line, out ul_marker)) { - if (line.length <= 3) { // empty item + if (line.strip () == "") { + return false; + } + + string ul_marker; + int indent_spaces, ol_number; + string item_text = ""; + if (parse_unordered_list_item (line, out ul_marker, out item_text)) { + if (item_text.strip () == "") { // empty list item delete_empty_item (); } else { - string to_insert = "\n%c ".printf (ul_marker); + string to_insert = "\n%s".printf (ul_marker); current_source.buffer.insert_at_cursor (to_insert, to_insert.length); } + return true; - } else if (parse_ordered_list_item (line, ref ol_number, out item_text)) { + } else if (parse_ordered_list_item (line, out ol_number, out item_text, out indent_spaces, null)) { if (item_text.length == 0) { delete_empty_item (); } else { - string to_insert = "\n%d. ".printf (ol_number + 1); + string to_insert = "\n%s%d. ".printf (string.nfill (indent_spaces, ' '), ++ol_number); current_source.buffer.insert_at_cursor (to_insert, to_insert.length); - fix_ordered_list_numbering (); + // Check following lines to see if renumbering required + fix_ordered_list_numbering (indent_spaces, ol_number); } return true; } @@ -111,36 +118,43 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services end.forward_to_line_end (); current_buffer.delete (ref start, ref end); current_buffer.insert_at_cursor ("\n", 1); + current_buffer.get_iter_at_offset (out start, current_buffer.cursor_position); } - private void fix_ordered_list_numbering () { + // Starting on the line where a numered list item was inserted, check if renumbering required + private void fix_ordered_list_numbering (int indent_spaces, int inserted_number) { Gtk.TextIter next; - var count = 1; - var item_text = ""; var current_buffer = current_source.buffer; current_buffer.get_iter_at_offset (out next, current_buffer.cursor_position); - var line = get_current_line (next).strip (); - // Get list item number from current line - parse_ordered_list_item (line, ref count, out item_text); - // Start checking following lines - next.forward_line (); - line = get_current_line (next).strip (); - while (parse_ordered_list_item (line, ref count, out item_text)) { - count++; - var next_mark = current_buffer.create_mark (null, next, true); - var point_offset = line.index_of_char ('.'); - var start = next; - var end = start; - end.forward_chars (point_offset); - - current_buffer.delete (ref start, ref end); - current_buffer.get_iter_at_mark (out next, next_mark); - - var to_insert = "%d".printf (count); - current_buffer.insert (ref next, to_insert, to_insert.length); - next.forward_line (); - line = get_current_line (next).strip (); + int point_offset = 0, next_indent_spaces = 0, count = inserted_number, next_count = 0; + string item_text = ""; + // Search for ordered list lines at the same level until level falls below or end of doc + while (next.forward_line () && + parse_ordered_list_item ( + get_current_line (next), + out next_count, + out item_text, + out next_indent_spaces, + out point_offset + ) && + next_indent_spaces >= indent_spaces + ) { + // Only update lines at same indent within same block + if (next_indent_spaces == indent_spaces) { + count++; + next.forward_chars (indent_spaces); + var next_mark = current_buffer.create_mark (null, next, true); + var start = next; + var end = start; + end.forward_chars (point_offset); + + current_buffer.delete (ref start, ref end); + current_buffer.get_iter_at_mark (out next, next_mark); + + var to_insert = "%d".printf (count); + current_buffer.insert (ref next, to_insert, to_insert.length); + } } } @@ -159,28 +173,46 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services return current_buffer.get_text (start, end, false); } - private bool parse_ordered_list_item (string line, ref int current_number, out string item_text) { + private bool parse_ordered_list_item ( + string line, + out int current_number, + out string item_text, + out int indent_spaces, + out int first_point_pos + ) { + item_text = ""; - int first_point_character = line.index_of_char ('.'); - if (first_point_character < 0) { + indent_spaces = -1; + current_number = -1; + first_point_pos = line.index_of_char ('.'); //TODO Handle ")" Ignored escaped? + + if (first_point_pos < 0) { return false; } - item_text = line.substring (first_point_character + 1).strip (); - var line_start = line.substring (0, first_point_character); + item_text = line.substring (first_point_pos + 1).strip (); + + var line_start = line.substring (0, first_point_pos); + indent_spaces = line_start.last_index_of_char (' ') + 1; if (!int.try_parse (line_start, out current_number)) { return false; } - return true; + + return indent_spaces >= 0 && current_number >= 1; } - private bool parse_unordered_list_item (string line, out char ul_marker) { - if ((line[0] == '*' || line[0] == '-') && line[1] == ' ') { - ul_marker = line[0]; + private bool parse_unordered_list_item (string line, out string ul_marker, out string item_text) { + var chugged_line = line.chug (); + if ((chugged_line[0] == '*' || chugged_line[0] == '-') && + chugged_line[1] == ' ') { + var ul_marker_index = line.index_of_char (chugged_line[0]); + ul_marker = "%s%c ".printf (string.nfill (ul_marker_index, ' '), chugged_line[0]); + item_text = chugged_line.substring (2, -1); return true; } - ul_marker = '\0'; + + ul_marker = ""; return false; }