From f6ff15144f88328ff1699d44cd727eb095ffd45e Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Mon, 14 Oct 2024 17:24:33 +0100 Subject: [PATCH 1/9] Ensure only list lines are renumbered --- .../markdown-actions/markdown-actions.vala | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/plugins/markdown-actions/markdown-actions.vala b/plugins/markdown-actions/markdown-actions.vala index 024e97c3b6..48006675bf 100644 --- a/plugins/markdown-actions/markdown-actions.vala +++ b/plugins/markdown-actions/markdown-actions.vala @@ -115,20 +115,19 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Peas.Activatable private void fix_ordered_list_numbering () { 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 (); - int count = 1; - string item_text; + // Get list item number from current line parse_ordered_list_item (line, ref count, out item_text); - - while (next.forward_line ()) { + // 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++; - line = get_current_line (next).strip (); - if (line.length == 0) { - break; - } - var next_mark = current_buffer.create_mark (null, next, true); var point_offset = line.index_of_char ('.'); var start = next; @@ -140,6 +139,8 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Peas.Activatable 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 (); } } From 901d71585e5aa3498f5132b3506cf973d1fbafdd Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Mon, 14 Oct 2024 17:24:45 +0100 Subject: [PATCH 2/9] Fix code style --- plugins/markdown-actions/markdown-actions.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/markdown-actions/markdown-actions.vala b/plugins/markdown-actions/markdown-actions.vala index 48006675bf..29e5fb4d40 100644 --- a/plugins/markdown-actions/markdown-actions.vala +++ b/plugins/markdown-actions/markdown-actions.vala @@ -144,7 +144,7 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Peas.Activatable } } - private string get_current_line (Gtk.TextIter? start=null) { + private string get_current_line (Gtk.TextIter? start = null) { var current_buffer = current_source.buffer; Gtk.TextIter end; From 3bf1719363162dc23d3ef5883248b1255fa1ef55 Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Tue, 15 Oct 2024 14:31:04 +0100 Subject: [PATCH 3/9] Handle indents when appending or inserting ordered lines --- .../markdown-actions/markdown-actions.vala | 74 ++++++++++++------- 1 file changed, 47 insertions(+), 27 deletions(-) diff --git a/plugins/markdown-actions/markdown-actions.vala b/plugins/markdown-actions/markdown-actions.vala index 29e5fb4d40..7094405f43 100644 --- a/plugins/markdown-actions/markdown-actions.vala +++ b/plugins/markdown-actions/markdown-actions.vala @@ -77,7 +77,7 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Peas.Activatable if (evt.keyval == Gdk.Key.Return) { char ul_marker; - int ol_number = 1; + int indent_spaces, ol_number; string item_text; var line = get_current_line (); if (parse_unordered_list_item (line, out ul_marker)) { @@ -88,13 +88,13 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Peas.Activatable 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)) { 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 + 1); current_source.buffer.insert_at_cursor (to_insert, to_insert.length); - fix_ordered_list_numbering (); + fix_ordered_list_numbering (indent_spaces); } return true; } @@ -111,36 +111,44 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Peas.Activatable 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 () { + private void fix_ordered_list_numbering (int indent_spaces) { 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 (); + var line = get_current_line (next); // Get list item number from current line - parse_ordered_list_item (line, ref count, out item_text); + int next_indent_spaces, count, next_count; + string item_text; + parse_ordered_list_item (line, out count, out item_text, out next_indent_spaces); // 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); + line = get_current_line (next); // Next now at line start + // Search for ordered list lines at the same level until level falls below + while (parse_ordered_list_item (line, out next_count, out item_text, out next_indent_spaces) && + 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 point_offset = line.strip ().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 (); + line = get_current_line (next); } } @@ -159,8 +167,16 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Peas.Activatable 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) { + item_text = ""; + indent_spaces = -1; + current_number = -1; + int first_point_character = line.index_of_char ('.'); if (first_point_character < 0) { return false; @@ -169,17 +185,21 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Peas.Activatable item_text = line.substring (first_point_character + 1).strip (); var line_start = line.substring (0, first_point_character); + 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) { + line.chug (); // Remove leading spaces if ((line[0] == '*' || line[0] == '-') && line[1] == ' ') { ul_marker = line[0]; return true; } + ul_marker = '\0'; return false; } From 67d9a6a8cca880fafc3035b5a64e14b4cb37a875 Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Wed, 9 Jul 2025 12:40:16 +0100 Subject: [PATCH 4/9] Rework --- .../markdown-actions/markdown-actions.vala | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/plugins/markdown-actions/markdown-actions.vala b/plugins/markdown-actions/markdown-actions.vala index 80617cce71..ca70dc71b0 100644 --- a/plugins/markdown-actions/markdown-actions.vala +++ b/plugins/markdown-actions/markdown-actions.vala @@ -88,13 +88,14 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services current_source.buffer.insert_at_cursor (to_insert, to_insert.length); } return true; - } else if (parse_ordered_list_item (line, out ol_number, out item_text, out indent_spaces)) { + } 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%s%d. ".printf (string.nfill (indent_spaces, ' '), 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 (indent_spaces); + // Check following lines to see if renumbering required + fix_ordered_list_numbering (indent_spaces, ol_number); } return true; } @@ -114,31 +115,30 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services current_buffer.get_iter_at_offset (out start, current_buffer.cursor_position); } - private void fix_ordered_list_numbering (int indent_spaces) { + // 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); - // Get list item number from current line - int next_indent_spaces, count, next_count; - string item_text; - parse_ordered_list_item (line, out count, out item_text, out next_indent_spaces); - // Start checking following lines - next.forward_line (); - line = get_current_line (next); // Next now at line start - // Search for ordered list lines at the same level until level falls below - while (parse_ordered_list_item (line, out next_count, out item_text, out next_indent_spaces) && - next_indent_spaces >= indent_spaces) { - + 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 point_offset = line.strip ().index_of_char ('.'); var start = next; var end = start; end.forward_chars (point_offset); @@ -149,9 +149,6 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services var to_insert = "%d".printf (count); current_buffer.insert (ref next, to_insert, to_insert.length); } - - next.forward_line (); - line = get_current_line (next); } } @@ -174,20 +171,23 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services string line, out int current_number, out string item_text, - out int indent_spaces) { + out int indent_spaces, + out int first_point_pos + ) { item_text = ""; indent_spaces = -1; current_number = -1; + first_point_pos = line.index_of_char ('.'); //TODO Handle ")" Ignored escaped? - int first_point_character = line.index_of_char ('.'); - if (first_point_character < 0) { + 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; From c79651bd5c49d20c8c1b14f8ed0e9ddf90398616 Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Wed, 5 Aug 2026 18:34:35 +0100 Subject: [PATCH 5/9] Maintain indent for unorder list --- plugins/markdown-actions/markdown-actions.vala | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/plugins/markdown-actions/markdown-actions.vala b/plugins/markdown-actions/markdown-actions.vala index ec91ba936a..344a801b9d 100644 --- a/plugins/markdown-actions/markdown-actions.vala +++ b/plugins/markdown-actions/markdown-actions.vala @@ -97,11 +97,11 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services int indent_spaces, ol_number; string item_text; var line = get_current_line (); - if (parse_unordered_list_item (line, out ul_marker)) { + if (parse_unordered_list_item (line, out ul_marker, out indent_spaces)) { if (line.length <= 3) { // empty item delete_empty_item (); } else { - string to_insert = "\n%c ".printf (ul_marker); + string to_insert = "\n%s%c ".printf (string.nfill (indent_spaces, ' '), ul_marker); current_source.buffer.insert_at_cursor (to_insert, to_insert.length); } return true; @@ -214,10 +214,12 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services return indent_spaces >= 0 && current_number >= 1; } - private bool parse_unordered_list_item (string line, out char ul_marker) { - line.chug (); // Remove leading spaces - if ((line[0] == '*' || line[0] == '-') && line[1] == ' ') { - ul_marker = line[0]; + private bool parse_unordered_list_item (string line, out char ul_marker, out int indent_spaces) { + indent_spaces = -1; + var _line = line.chug (); // Remove leading spaces + if ((_line[0] == '*' || _line[0] == '-') && _line[1] == ' ') { + ul_marker = _line[0]; + indent_spaces = line.index_of_char (ul_marker); return true; } From ff8fae5474608eef29d53965665c5a920f56509c Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Wed, 5 Aug 2026 21:50:38 +0100 Subject: [PATCH 6/9] Allow both unordered and ordered list marker like Github --- .../markdown-actions/markdown-actions.vala | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/plugins/markdown-actions/markdown-actions.vala b/plugins/markdown-actions/markdown-actions.vala index 344a801b9d..0b93ec1d1a 100644 --- a/plugins/markdown-actions/markdown-actions.vala +++ b/plugins/markdown-actions/markdown-actions.vala @@ -95,24 +95,26 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services if (keyval == Gdk.Key.Return) { char ul_marker; int indent_spaces, ol_number; + string prefix; string item_text; var line = get_current_line (); - if (parse_unordered_list_item (line, out ul_marker, out indent_spaces)) { - if (line.length <= 3) { // empty item + + if (parse_ordered_list_item (line, out ol_number, out item_text, out prefix, null)) { + if (item_text.length == 0) { delete_empty_item (); } else { - string to_insert = "\n%s%c ".printf (string.nfill (indent_spaces, ' '), ul_marker); + string to_insert = "\n%s%d. ".printf (prefix, ++ol_number); current_source.buffer.insert_at_cursor (to_insert, to_insert.length); + // Check following lines to see if renumbering required + fix_ordered_list_numbering (prefix.length, ol_number); } return true; - } else if (parse_ordered_list_item (line, out ol_number, out item_text, out indent_spaces, null)) { - if (item_text.length == 0) { + } else if (parse_unordered_list_item (line, out ul_marker, out indent_spaces)) { + if (line.length <= 3) { // empty item delete_empty_item (); } else { - string to_insert = "\n%s%d. ".printf (string.nfill (indent_spaces, ' '), ++ol_number); + string to_insert = "\n%s%c ".printf (string.nfill (indent_spaces, ' '), ul_marker); current_source.buffer.insert_at_cursor (to_insert, to_insert.length); - // Check following lines to see if renumbering required - fix_ordered_list_numbering (indent_spaces, ol_number); } return true; } @@ -139,27 +141,27 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services var current_buffer = current_source.buffer; current_buffer.get_iter_at_offset (out next, current_buffer.cursor_position); - int point_offset = 0, next_indent_spaces = 0, count = inserted_number, next_count = 0; - string item_text = ""; + int point_offset = 0, count = inserted_number, next_count = 0; + string item_text = "", next_prefix = ""; // 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 next_prefix, out point_offset ) && - next_indent_spaces >= indent_spaces + next_prefix.length >= indent_spaces ) { // Only update lines at same indent within same block - if (next_indent_spaces == indent_spaces) { + if (next_prefix.length == 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); + end.forward_chars (point_offset - indent_spaces); current_buffer.delete (ref start, ref end); current_buffer.get_iter_at_mark (out next, next_mark); @@ -182,19 +184,19 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services end = start; end.forward_to_line_end (); - return current_buffer.get_text (start, end, false); + var cl = current_buffer.get_text (start, end, false); + return cl; } private bool parse_ordered_list_item ( string line, out int current_number, out string item_text, - out int indent_spaces, + out string prefix, out int first_point_pos ) { - item_text = ""; - indent_spaces = -1; + prefix = ""; current_number = -1; first_point_pos = line.index_of_char ('.'); //TODO Handle ")" Ignored escaped? @@ -206,12 +208,13 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services 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; + line_start = line_start.replace ("-", " ").replace ("*", " "); + prefix = line.substring (0, line_start.last_index_of_char (' ') + 1); if (!int.try_parse (line_start, out current_number)) { return false; } - return indent_spaces >= 0 && current_number >= 1; + return current_number >= 1; } private bool parse_unordered_list_item (string line, out char ul_marker, out int indent_spaces) { From bf0eae7cae3d3fa8b189b57a47b82e51d769c72a Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Wed, 5 Aug 2026 22:04:35 +0100 Subject: [PATCH 7/9] Maintain non-empty prefix in delete empty item --- .../markdown-actions/markdown-actions.vala | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/plugins/markdown-actions/markdown-actions.vala b/plugins/markdown-actions/markdown-actions.vala index 0b93ec1d1a..b06dcd5adf 100644 --- a/plugins/markdown-actions/markdown-actions.vala +++ b/plugins/markdown-actions/markdown-actions.vala @@ -101,7 +101,7 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services if (parse_ordered_list_item (line, out ol_number, out item_text, out prefix, null)) { if (item_text.length == 0) { - delete_empty_item (); + delete_empty_item (prefix); } else { string to_insert = "\n%s%d. ".printf (prefix, ++ol_number); current_source.buffer.insert_at_cursor (to_insert, to_insert.length); @@ -123,7 +123,7 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services return false; } - private void delete_empty_item () { + private void delete_empty_item (string prefix = "") { Gtk.TextIter start, end; var current_buffer = current_source.buffer; current_buffer.get_iter_at_offset (out start, current_buffer.cursor_position); @@ -131,7 +131,12 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services end = start; end.forward_to_line_end (); current_buffer.delete (ref start, ref end); - current_buffer.insert_at_cursor ("\n", 1); + if (prefix != "") { + current_buffer.insert_at_cursor ("%s".printf (prefix), prefix.length); + } else { + current_buffer.insert_at_cursor ("\n", 1); + } + current_buffer.get_iter_at_offset (out start, current_buffer.cursor_position); } @@ -200,16 +205,16 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services 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_pos + 1).strip (); var line_start = line.substring (0, first_point_pos); line_start = line_start.replace ("-", " ").replace ("*", " "); prefix = line.substring (0, line_start.last_index_of_char (' ') + 1); + + // if (first_point_pos < 0) { + // return false; + // } + if (!int.try_parse (line_start, out current_number)) { return false; } From 56ad35392063b8aa68b20cc0c30bb2a4c209f1f3 Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Thu, 6 Aug 2026 10:21:08 +0100 Subject: [PATCH 8/9] Do not insert new line when deleting empty (following Github) --- plugins/markdown-actions/markdown-actions.vala | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/plugins/markdown-actions/markdown-actions.vala b/plugins/markdown-actions/markdown-actions.vala index b06dcd5adf..2477e33c6c 100644 --- a/plugins/markdown-actions/markdown-actions.vala +++ b/plugins/markdown-actions/markdown-actions.vala @@ -131,16 +131,11 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services end = start; end.forward_to_line_end (); current_buffer.delete (ref start, ref end); - if (prefix != "") { - current_buffer.insert_at_cursor ("%s".printf (prefix), prefix.length); - } else { - current_buffer.insert_at_cursor ("\n", 1); - } - + current_buffer.insert_at_cursor ("%s".printf (prefix), prefix.length); current_buffer.get_iter_at_offset (out start, current_buffer.cursor_position); } - // Starting on the line where a numered list item was inserted, check if renumbering required + // Starting on the line where a numbered list item was inserted, check if renumbering required private void fix_ordered_list_numbering (int indent_spaces, int inserted_number) { Gtk.TextIter next; var current_buffer = current_source.buffer; From 651391f7dc44c666f8ed8e2647fa859854464e0f Mon Sep 17 00:00:00 2001 From: Jeremy Wootten Date: Thu, 6 Aug 2026 12:25:58 +0100 Subject: [PATCH 9/9] Deal with unordered sublist --- .../markdown-actions/markdown-actions.vala | 81 ++++++++++++++----- 1 file changed, 60 insertions(+), 21 deletions(-) diff --git a/plugins/markdown-actions/markdown-actions.vala b/plugins/markdown-actions/markdown-actions.vala index 2477e33c6c..d15e0335fa 100644 --- a/plugins/markdown-actions/markdown-actions.vala +++ b/plugins/markdown-actions/markdown-actions.vala @@ -94,13 +94,13 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services if (keyval == Gdk.Key.Return) { char ul_marker; - int indent_spaces, ol_number; + int ol_number; string prefix; string item_text; var line = get_current_line (); if (parse_ordered_list_item (line, out ol_number, out item_text, out prefix, null)) { - if (item_text.length == 0) { + if (item_text.strip () == "") { delete_empty_item (prefix); } else { string to_insert = "\n%s%d. ".printf (prefix, ++ol_number); @@ -109,13 +109,14 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services fix_ordered_list_numbering (prefix.length, ol_number); } return true; - } else if (parse_unordered_list_item (line, out ul_marker, out indent_spaces)) { - if (line.length <= 3) { // empty item - delete_empty_item (); - } else { - string to_insert = "\n%s%c ".printf (string.nfill (indent_spaces, ' '), ul_marker); + } else if (parse_unordered_list_item (line, out ul_marker, out item_text, out prefix)) { + if (item_text.strip () == "") { + delete_empty_item (prefix); + } else { // ul_marker is not null here + string to_insert = "\n%s%c ".printf (prefix, ul_marker); current_source.buffer.insert_at_cursor (to_insert, to_insert.length); } + return true; } } @@ -131,7 +132,11 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services end = start; end.forward_to_line_end (); current_buffer.delete (ref start, ref end); - current_buffer.insert_at_cursor ("%s".printf (prefix), prefix.length); + var _prefix = prefix; + if (prefix.strip () == "") { + _prefix = ""; + } + current_buffer.insert_at_cursor ("%s".printf (_prefix), _prefix.length); current_buffer.get_iter_at_offset (out start, current_buffer.cursor_position); } @@ -198,6 +203,8 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services item_text = ""; prefix = ""; current_number = -1; + // Github does not automatically handle sublists in numbered lists so neither do we for now + // We assume the first number point is the only one. first_point_pos = line.index_of_char ('.'); //TODO Handle ")" Ignored escaped? item_text = line.substring (first_point_pos + 1).strip (); @@ -206,10 +213,6 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services line_start = line_start.replace ("-", " ").replace ("*", " "); prefix = line.substring (0, line_start.last_index_of_char (' ') + 1); - // if (first_point_pos < 0) { - // return false; - // } - if (!int.try_parse (line_start, out current_number)) { return false; } @@ -217,17 +220,53 @@ public class Code.Plugins.MarkdownActions : Peas.ExtensionBase, Scratch.Services return current_number >= 1; } - private bool parse_unordered_list_item (string line, out char ul_marker, out int indent_spaces) { - indent_spaces = -1; - var _line = line.chug (); // Remove leading spaces - if ((_line[0] == '*' || _line[0] == '-') && _line[1] == ' ') { - ul_marker = _line[0]; - indent_spaces = line.index_of_char (ul_marker); - return true; + private bool parse_unordered_list_item ( + string line, + out char ul_marker, + out string item_text, + out string prefix + ) { + prefix = ""; + item_text = ""; + ul_marker = ' '; + + // Scan line for last unordered list marker + unichar uc = 0; + int index = 0; + uint spaces = 0; + char? last_marker = null; + while (line.get_next_char (ref index, out uc)) { + string buf = " "; + var i = uc.to_utf8 (buf); + if (i != 1) { + break; + } + + var c = buf[0]; + if (c.isspace ()) { + spaces++; + // Only allow one space between or after markers but any number before the first + if (last_marker != null && spaces > 1) { + break; + } + } else if (c == '-' || c == '*') { + spaces = 0; + last_marker = c; + } else { // text item starts here + break; + } } - ul_marker = '\0'; - return false; + if (last_marker == null) { + return false; + } + + ul_marker = last_marker; + item_text = line.substring (index - 1); + // The item text might contain marker characters so take care to ignore those + prefix = line.substring (0, index - 1); + prefix = prefix.substring (0, prefix.last_index_of_char (ul_marker)); + return true; } private void insert_link () {