Trim whitespace on save and skip lines with cursor

This commit is contained in:
Krzosa Karol
2024-08-03 10:30:35 +02:00
parent ee863e3b09
commit 7f85f8348e
5 changed files with 75 additions and 30 deletions

View File

@@ -398,6 +398,7 @@ void GenerateConfig() {
style.add({"DrawLineNumbers", "1"});
style.add({"DrawScrollbar", "1"});
style.add({"IndentSize", "2"});
style.add({"TrimWhitespaceOnSave", "1"});
{
MA_Scratch scratch;

View File

@@ -31,6 +31,34 @@ void Command_DuplicateLine(View *view, int direction) {
For(view->carets) it = MakeCaret(MovePos(*buffer, it.range.min, direction, false));
}
Array<Range> GetSortedSelectedLines(Allocator allocator, View *view) {
Scratch scratch(allocator);
Buffer *buffer = GetBuffer(view->active_buffer);
Array<Caret> caret_copy = TightCopy(scratch, view->carets);
Array<Caret> temp = TightCopy(scratch, view->carets);
MergeSort(view->carets.len, caret_copy.data, temp.data);
Array<Range> result = {allocator};
For(caret_copy) {
Int min_line = PosToLine(*buffer, it.range.min);
Int max_line = PosToLine(*buffer, it.range.max);
Range line_range = {min_line, max_line + 1};
if (result.len == 0) {
Add(&result, line_range);
continue;
}
Range *last = GetLast(result);
if (AreOverlapping(*last, line_range)) {
last->max = Max(last->max, line_range.max);
} else {
Add(&result, line_range);
}
}
return result;
}
void Command_IndentSelectedLines(View *view, bool shift = false) {
Scratch scratch;
Buffer *buffer = GetBuffer(view->active_buffer);
@@ -38,32 +66,10 @@ void Command_IndentSelectedLines(View *view, bool shift = false) {
BeforeEdit(buffer, view->carets);
MergeCarets(view);
Array<Caret> caret_copy = TightCopy(scratch, view->carets);
Array<Caret> temp = TightCopy(scratch, view->carets);
MergeSort(view->carets.len, caret_copy.data, temp.data);
Array<Range> line_ranges_to_indent = {scratch};
For(caret_copy) {
Int min_line = PosToLine(*buffer, it.range.min);
Int max_line = PosToLine(*buffer, it.range.max);
Range line_range = {min_line, max_line};
if (line_ranges_to_indent.len == 0) {
Add(&line_ranges_to_indent, line_range);
continue;
}
Range *last = GetLast(line_ranges_to_indent);
if (AreOverlapping(*last, line_range)) {
last->max = Max(last->max, line_range.max);
} else {
Add(&line_ranges_to_indent, line_range);
}
}
Array<Edit> edits = {scratch};
Array<Range> line_ranges_to_indent = GetSortedSelectedLines(scratch, view);
Array<Edit> edits = {scratch};
For(line_ranges_to_indent) {
for (Int i = it.min; i <= it.max; i += 1) {
for (Int i = it.min; i < it.max; i += 1) {
Range pos_range_of_line = GetLineRange(*buffer, i);
if (!shift) {
@@ -86,15 +92,45 @@ void Command_IndentSelectedLines(View *view, bool shift = false) {
view->update_scroll = false;
}
void Command_TrimTrailingWhitespace(View *view) {
Int FindRangeByPos(Array<Range> &ranges, Int pos) {
// binary search
Int low = 0;
Int high = ranges.len - 1;
Int result = -1;
while (low <= high) {
Int mid = low + (high - low) / 2;
Range range = ranges[mid];
if (pos >= range.min && pos < range.max) {
result = mid;
break;
}
if (range.min < pos) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return result;
}
void Command_TrimTrailingWhitespace(View *view, bool dont_trim_lines_with_cursor) {
Scratch scratch;
Buffer *buffer = GetBuffer(view->active_buffer);
BeforeEdit(buffer, view->carets);
MergeCarets(view);
Array<Range> lines_to_skip_triming = {};
if (dont_trim_lines_with_cursor) lines_to_skip_triming = GetSortedSelectedLines(scratch, view);
Array<Edit> edits = {scratch};
for (Int i = 0; i < buffer->line_starts.len; i += 1) {
Int range_index = FindRangeByPos(lines_to_skip_triming, i);
if (range_index != -1) continue;
Range range = GetLineRangeWithoutNL(*buffer, i);
Int whitespace_end = range.max;
for (; whitespace_end > range.min; whitespace_end -= 1) {
@@ -448,7 +484,7 @@ void WindowCommand(Event event, Window *window, View *view) {
}
if (Ctrl(SDLK_W)) {
Command_TrimTrailingWhitespace(view);
Command_TrimTrailingWhitespace(view, false);
}
if (Ctrl(SDLK_BACKSPACE)) {
@@ -570,6 +606,11 @@ void WindowCommand(Event event, Window *window, View *view) {
}
if (Ctrl(SDLK_S)) {
if (StyleTrimWhitespaceOnSave) {
bool dont_trim_lines_with_cursor = true;
Command_TrimTrailingWhitespace(view, dont_trim_lines_with_cursor);
}
String16 string16 = GetString(*buffer);
Scratch scratch;
String string = ToString(scratch, string16);

View File

@@ -58,6 +58,7 @@ Style = {}
Style.DrawLineNumbers = 1
Style.DrawScrollbar = 1
Style.IndentSize = 2
Style.TrimWhitespaceOnSave = 1
-- @todo: should we rewrite linux paths to windows on windows and vice-versa?
@@ -217,4 +218,5 @@ void ReloadStyle() {
StyleDrawLineNumbers = GetStyle("DrawLineNumbers", StyleDrawLineNumbers);
StyleDrawScrollbar = GetStyle("DrawScrollbar", StyleDrawScrollbar);
StyleIndentSize = GetStyle("IndentSize", StyleIndentSize);
StyleTrimWhitespaceOnSave = GetStyle("TrimWhitespaceOnSave", StyleTrimWhitespaceOnSave);
}

View File

@@ -54,4 +54,5 @@ Color ColorTitleBarBackground = GruvboxLight1;
Color ColorTitleBarSelection = GruvboxLight3;
Int StyleDrawLineNumbers = 1;
Int StyleDrawScrollbar = 1;
Int StyleIndentSize = 2;
Int StyleIndentSize = 2;
Int StyleTrimWhitespaceOnSave = 1;

View File

@@ -4,10 +4,10 @@
- don't trim lines with cursor or selection on it
- fix history of ctrl + enter
- option trim trailing whitespace before save and dont' trim on cursor
- improve cursor movement, it's too clunky, too much stopping
- kill selected lines
- better enclosures
- kill selected lines
- should be able click on title bar of windows which disappear on losing focus
- search backwards
- load selected string or auto enclosed word when midclick?, ctrl + click, ctrl + e?
- experiment with using multiple cursors to select command and it's input