From 1ebe8d9929573985bb729801a7c5ac61375b6819 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Sat, 3 Aug 2024 10:05:43 +0200 Subject: [PATCH] buffer_ops.cpp unify MoveOnWhitespaceBoundary --- src/text_editor/buffer_ops.cpp | 154 +++++++++++++++++++++++++++ src/text_editor/commands.cpp | 183 -------------------------------- src/text_editor/text_editor.cpp | 1 + src/text_editor/todo.txt | 5 + 4 files changed, 160 insertions(+), 183 deletions(-) create mode 100644 src/text_editor/buffer_ops.cpp diff --git a/src/text_editor/buffer_ops.cpp b/src/text_editor/buffer_ops.cpp new file mode 100644 index 0000000..37718ce --- /dev/null +++ b/src/text_editor/buffer_ops.cpp @@ -0,0 +1,154 @@ +const int DIR_RIGHT = 0; +const int DIR_LEFT = 1; +const int DIR_DOWN = 2; +const int DIR_UP = 3; + +const bool CTRL_PRESSED = true; + +Int MoveOnWhitespaceBoundary(Buffer &buffer, Int pos, int direction) { + Assert(direction == DIR_RIGHT || direction == DIR_LEFT); + + pos = Clamp(pos, (Int)0, buffer.len); + bool standing_on_whitespace = IsWhitespace(buffer.str[pos]); + bool standing_on_symbol = IsSymbol(buffer.str[pos]); + bool standing_on_word = !standing_on_whitespace && !standing_on_symbol; + bool seek_whitespace = standing_on_whitespace == false; + bool seek_word = standing_on_whitespace || standing_on_symbol; + bool seek_symbol = standing_on_whitespace || standing_on_word; + + Int result = direction == DIR_RIGHT ? buffer.len : 0; + Int delta = direction == DIR_RIGHT ? 1 : -1; + Int prev_pos = pos; + for (Int i = pos; direction == DIR_RIGHT ? i < buffer.len : i >= 0; i += delta) { + bool is_whitespace = IsWhitespace(buffer.str[i]); + bool is_symbol = IsSymbol(buffer.str[i]); + bool is_word = !is_whitespace && !is_symbol; + Int r = direction == DIR_RIGHT ? i : prev_pos; + if (seek_word && is_word) { + result = r; + break; + } + if (seek_whitespace && is_whitespace) { + result = r; + break; + } + if (seek_symbol && is_symbol) { + result = r; + break; + } + prev_pos = i; + } + return result; +} + +Int MoveOnWhitespaceBoundaryDown(Buffer &buffer, Int pos) { + Int result = pos; + Int next_line = PosToLine(buffer, pos) + 1; + for (Int line = next_line; line < buffer.line_starts.len; line += 1) { + Range line_range = GetLineRange(buffer, line); + result = line_range.min; + + bool whitespace_line = true; + for (Int i = line_range.min; i < line_range.max; i += 1) { + if (!IsWhitespace(buffer.str[i])) { + whitespace_line = false; + break; + } + } + if (whitespace_line) break; + } + return result; +} + +Int MoveOnWhitespaceBoundaryUp(Buffer &buffer, Int pos) { + Int result = pos; + Int next_line = PosToLine(buffer, pos) - 1; + for (Int line = next_line; line >= 0; line -= 1) { + Range line_range = GetLineRange(buffer, line); + result = line_range.min; + + bool whitespace_line = true; + for (Int i = line_range.min; i < line_range.max; i += 1) { + if (!IsWhitespace(buffer.str[i])) { + whitespace_line = false; + break; + } + } + if (whitespace_line) break; + } + return result; +} + +Int MovePosByXY(Buffer &buffer, Int pos, XY offset) { + XY xy = PosToXY(buffer, pos); + Int result = XYToPosWithoutNL(buffer, {xy.col + offset.col, xy.line + offset.line}); + return result; +} + +Int MovePos(Buffer &buffer, Int pos, int direction, bool ctrl_pressed = false) { + ProfileFunction(); + Assert(direction >= 0 && direction <= 3); + if (ctrl_pressed) { + switch (direction) { + case DIR_RIGHT: return MoveOnWhitespaceBoundary(buffer, pos, direction); + case DIR_LEFT: return MoveOnWhitespaceBoundary(buffer, pos - 1, direction); + case DIR_DOWN: return MoveOnWhitespaceBoundaryDown(buffer, pos); + case DIR_UP: return MoveOnWhitespaceBoundaryUp(buffer, pos); + default: return pos; + } + } else { + switch (direction) { + case DIR_RIGHT: return Clamp(pos + 1, (Int)0, buffer.len); + case DIR_LEFT: return Clamp(pos - 1, (Int)0, buffer.len); + case DIR_DOWN: return MovePosByXY(buffer, pos, {0, 1}); + case DIR_UP: return MovePosByXY(buffer, pos, {0, -1}); + default: return pos; + } + } +} + +Range EncloseWord(Buffer &buffer, Int pos) { + Range result = {}; + result.min = MoveOnWhitespaceBoundary(buffer, pos, DIR_LEFT); + result.max = MoveOnWhitespaceBoundary(buffer, pos, DIR_RIGHT); + return result; +} + +Caret FindInBuffer(Buffer *buffer, String16 needle, Caret caret, bool find_next = false) { + Int pos = caret.range.min; + String16 medium = GetString(*buffer, {pos, INT64_MAX}); + + Caret result = {}; + Int index = 0; + if (Seek(medium, needle, &index)) { + result = MakeCaret(pos + index + needle.len, pos + index); + } else { + medium = GetString(*buffer); + if (Seek(medium, needle, &index)) { + result = MakeCaret(index + needle.len, index); + } + } + + if (find_next && AreEqual(result, caret)) { + caret.range.min = Clamp(*buffer, caret.range.min + 1); + caret.range.max = Clamp(*buffer, caret.range.max + 1); + result = FindInBuffer(buffer, needle, caret, false); + } + + return result; +} + +Array FindAllInBuffer(Allocator allocator, Buffer *buffer, String16 needle) { + Array result = {allocator}; + String16 string_buffer = GetString(*buffer); + for (Int pos = 0;;) { + Int index = 0; + String16 medium = Skip(string_buffer, pos); + if (!Seek(medium, needle, &index)) { + break; + } + Add(&result, Rng(pos + index, pos + index + needle.len)); + pos += needle.len; + } + return result; +} diff --git a/src/text_editor/commands.cpp b/src/text_editor/commands.cpp index 6ec74d4..3accb94 100644 --- a/src/text_editor/commands.cpp +++ b/src/text_editor/commands.cpp @@ -53,189 +53,6 @@ struct Event { #define Mouse(x) (event.kind == EVENT_MOUSE_##x) #define MousePress() (Mouse(LEFT) || Mouse(RIGHT) || Mouse(MIDDLE)) -Int MoveOnWhitespaceBoundaryForward(Buffer &buffer, Int pos) { - pos = Clamp(pos, (Int)0, buffer.len); - bool standing_on_whitespace = IsWhitespace(buffer.str[pos]); - bool standing_on_symbol = IsSymbol(buffer.str[pos]); - bool standing_on_word = !standing_on_whitespace && !standing_on_symbol; - bool seek_whitespace = standing_on_whitespace == false; - bool seek_word = standing_on_whitespace || standing_on_symbol; - bool seek_symbol = standing_on_whitespace || standing_on_word; - - Int result = buffer.len; - Int prev_pos = pos; - for (Int i = pos; i < buffer.len; i += 1) { - bool is_whitespace = IsWhitespace(buffer.str[i]); - bool is_symbol = IsSymbol(buffer.str[i]); - bool is_word = !is_whitespace && !is_symbol; - if (seek_word && is_word) { - result = i; - break; - } - if (seek_whitespace && is_whitespace) { - result = i; - break; - } - if (seek_symbol && is_symbol) { - result = i; - break; - } - prev_pos = i; - } - return result; -} - -Int MoveOnWhitespaceBoundaryBackward(Buffer &buffer, Int pos) { - pos = Clamp(pos, (Int)0, buffer.len); - bool standing_on_whitespace = IsWhitespace(buffer.str[pos]); - bool standing_on_symbol = IsSymbol(buffer.str[pos]); - bool standing_on_word = !standing_on_whitespace && !standing_on_symbol; - bool seek_whitespace = standing_on_whitespace == false; - bool seek_word = standing_on_whitespace || standing_on_symbol; - bool seek_symbol = standing_on_whitespace || standing_on_word; - - Int result = 0; - Int prev_pos = pos; - for (Int i = pos; i >= 0; i -= 1) { - bool is_whitespace = IsWhitespace(buffer.str[i]); - bool is_symbol = IsSymbol(buffer.str[i]); - bool is_word = !is_whitespace && !is_symbol; - if (seek_word && is_word) { - result = prev_pos; - break; - } - if (seek_whitespace && is_whitespace) { - result = prev_pos; - break; - } - if (seek_symbol && is_symbol) { - result = prev_pos; - break; - } - prev_pos = i; - } - return result; -} - -Int MoveOnWhitespaceBoundaryDown(Buffer &buffer, Int pos) { - Int result = pos; - Int next_line = PosToLine(buffer, pos) + 1; - for (Int line = next_line; line < buffer.line_starts.len; line += 1) { - Range line_range = GetLineRange(buffer, line); - result = line_range.min; - - bool whitespace_line = true; - for (Int i = line_range.min; i < line_range.max; i += 1) { - if (!IsWhitespace(buffer.str[i])) { - whitespace_line = false; - break; - } - } - if (whitespace_line) break; - } - return result; -} - -Int MoveOnWhitespaceBoundaryUp(Buffer &buffer, Int pos) { - Int result = pos; - Int next_line = PosToLine(buffer, pos) - 1; - for (Int line = next_line; line >= 0; line -= 1) { - Range line_range = GetLineRange(buffer, line); - result = line_range.min; - - bool whitespace_line = true; - for (Int i = line_range.min; i < line_range.max; i += 1) { - if (!IsWhitespace(buffer.str[i])) { - whitespace_line = false; - break; - } - } - if (whitespace_line) break; - } - return result; -} - -Int MovePosByXY(Buffer &buffer, Int pos, XY offset) { - XY xy = PosToXY(buffer, pos); - Int result = XYToPosWithoutNL(buffer, {xy.col + offset.col, xy.line + offset.line}); - return result; -} - -const int DIR_RIGHT = 0; -const int DIR_LEFT = 1; -const int DIR_DOWN = 2; -const int DIR_UP = 3; - -const bool CTRL_PRESSED = true; - -Int MovePos(Buffer &buffer, Int pos, int direction, bool ctrl_pressed = false) { - ProfileFunction(); - Assert(direction >= 0 && direction <= 3); - if (ctrl_pressed) { - switch (direction) { - case DIR_RIGHT: return MoveOnWhitespaceBoundaryForward(buffer, pos); - case DIR_LEFT: return MoveOnWhitespaceBoundaryBackward(buffer, pos); - case DIR_DOWN: return MoveOnWhitespaceBoundaryDown(buffer, pos); - case DIR_UP: return MoveOnWhitespaceBoundaryUp(buffer, pos); - default: return pos; - } - } else { - switch (direction) { - case DIR_RIGHT: return Clamp(pos + 1, (Int)0, buffer.len); - case DIR_LEFT: return Clamp(pos - 1, (Int)0, buffer.len); - case DIR_DOWN: return MovePosByXY(buffer, pos, {0, 1}); - case DIR_UP: return MovePosByXY(buffer, pos, {0, -1}); - default: return pos; - } - } -} - -Range EncloseWord(Buffer &buffer, Int pos) { - Range result = {}; - result.min = MoveOnWhitespaceBoundaryBackward(buffer, pos); - result.max = MoveOnWhitespaceBoundaryForward(buffer, pos); - return result; -} - -Caret FindInBuffer(Buffer *buffer, String16 needle, Caret caret, bool find_next = false) { - Int pos = caret.range.min; - String16 medium = GetString(*buffer, {pos, INT64_MAX}); - - Caret result = {}; - Int index = 0; - if (Seek(medium, needle, &index)) { - result = MakeCaret(pos + index + needle.len, pos + index); - } else { - medium = GetString(*buffer); - if (Seek(medium, needle, &index)) { - result = MakeCaret(index + needle.len, index); - } - } - - if (find_next && AreEqual(result, caret)) { - caret.range.min = Clamp(*buffer, caret.range.min + 1); - caret.range.max = Clamp(*buffer, caret.range.max + 1); - result = FindInBuffer(buffer, needle, caret, false); - } - - return result; -} - -Array FindAllInBuffer(Allocator allocator, Buffer *buffer, String16 needle) { - Array result = {allocator}; - String16 string_buffer = GetString(*buffer); - for (Int pos = 0;;) { - Int index = 0; - String16 medium = Skip(string_buffer, pos); - if (!Seek(medium, needle, &index)) { - break; - } - Add(&result, Rng(pos + index, pos + index + needle.len)); - pos += needle.len; - } - return result; -} - void ToggleFullscreen() { if (IsInFullscreen) { SDL_SetWindowSize(SDLWindow, FullScreenSizeX, FullScreenSizeY); diff --git a/src/text_editor/text_editor.cpp b/src/text_editor/text_editor.cpp index 4d02632..d356a34 100644 --- a/src/text_editor/text_editor.cpp +++ b/src/text_editor/text_editor.cpp @@ -26,6 +26,7 @@ int FullScreenPositionX, FullScreenPositionY; #include "buffer_helpers.cpp" #include "buffer.cpp" #include "buffer_multi_cursor.cpp" +#include "buffer_ops.cpp" #include "buffer_history.cpp" #include "buffer_fuzzy_search.cpp" #include "buffer_test_load.cpp" diff --git a/src/text_editor/todo.txt b/src/text_editor/todo.txt index 584ece4..1a93ef7 100644 --- a/src/text_editor/todo.txt +++ b/src/text_editor/todo.txt @@ -2,7 +2,12 @@ - page up and down should also scroll and leave you in exactly same scroll - I think the way sublime text and we display line highlights is confusing with multiple cursors (line highlight can be confused with selection) - 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 - 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