Indent selected lines

This commit is contained in:
Krzosa Karol
2024-08-02 21:16:46 +02:00
parent cbf1cb8c4a
commit 03b6b80568
5 changed files with 205 additions and 150 deletions

View File

@@ -102,7 +102,8 @@ void BeforeEdit(Buffer *buffer, Array<Caret> &carets) {
ClearRedoStack(buffer);
}
void AfterEdit(Buffer *buffer, Array<Edit> *edits, Array<Caret> *carets) {
bool KILL_SELECTION = true;
void AfterEdit(Buffer *buffer, Array<Edit> *edits, Array<Caret> *carets, bool kill_selection = true) {
ProfileFunction();
Assert(buffer->debug_edit_phase == 2);
buffer->debug_edit_phase -= 2;
@@ -132,11 +133,19 @@ void AfterEdit(Buffer *buffer, Array<Edit> *edits, Array<Caret> *carets) {
Caret &old_cursor = carets->data[i];
Caret &new_cursor = new_carets.data[i];
if (old_cursor.range.min == edit.range.min) {
new_cursor.range.min = new_cursor.range.max = new_cursor.range.min + insert_size;
new_cursor.range.min += insert_size;
new_cursor.range.max += insert_size;
} else if (old_cursor.range.min > edit.range.min) {
new_cursor.range.min = new_cursor.range.max = new_cursor.range.min + offset;
new_cursor.range.min += offset;
new_cursor.range.max += offset;
}
}
}
for (Int i = 0; i < carets->len; i += 1) carets->data[i] = new_carets[i];
for (Int i = 0; i < carets->len; i += 1) {
carets->data[i] = new_carets[i];
if (kill_selection) {
carets->data[i].range.max = carets->data[i].range.min;
}
}
}

View File

@@ -31,6 +31,49 @@ void Command_DuplicateLine(View *view, int direction) {
For(view->carets) it = MakeCaret(MovePos(*buffer, it.range.min, direction, false));
}
void Command_IndentSelectedLines(View *view) {
Scratch scratch;
Buffer *buffer = GetBuffer(view->active_buffer);
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};
For(line_ranges_to_indent) {
for (Int i = it.min; i <= it.max; i += 1) {
Range pos_range_of_line = GetLineRange(*buffer, i);
AddEdit(&edits, {pos_range_of_line.min, pos_range_of_line.min}, L" ");
}
}
ApplyEdits(buffer, edits);
AfterEdit(buffer, &edits, &view->carets, !KILL_SELECTION);
view->update_scroll = false;
}
bool SHIFT_PRESSED = true;
void Command_MoveCursorsByPageSize(Window *window, int direction, bool shift = false) {
Assert(direction == DIR_UP || direction == DIR_DOWN);
@@ -179,6 +222,7 @@ void Command_EvalLua(View *view, String16 string) {
// make sure overlapping edits won't happen.
//
// mouse_selection_anchor is special case for mouse handling !
void MergeCarets(View *view, Range *mouse_selection_anchor) {
ProfileFunction();
@@ -210,151 +254,6 @@ void MergeCarets(View *view, Range *mouse_selection_anchor) {
Swap(&view->carets[first_caret_index], &view->carets[0]);
}
String DebugViewList(Allocator allocator) {
Scratch scratch((Arena *)allocator.object);
Array<String> strings = {scratch};
For(Views) {
Buffer *buffer = GetBuffer(it.active_buffer);
String string = Format(scratch, "view = %lld buffer = %lld name = %.*s", (long long)it.id.id, (long long)buffer->id.id, FmtString(buffer->name));
Add(&strings, string);
}
String result = Merge(allocator, strings, "\n");
return result;
}
String DebugWindowList(Allocator allocator) {
Scratch scratch((Arena *)allocator.object);
Array<String> strings = {scratch};
For(Windows) {
View *view = GetActiveView(&it);
Buffer *buffer = GetBuffer(view->active_buffer);
String string = Format(scratch, "window = %lld active_view = %lld buffer_name = %.*s", (long long)it.id.id, (long long)it.active_view.id, FmtString(buffer->name));
Add(&strings, string);
}
String result = Merge(allocator, strings, "\n");
return result;
}
void ReplaceDebugData() {
Buffer *buffer = GetBuffer("*debug*");
Window *window = GetActiveWindow();
View *view = GetActiveView(window);
if (view->active_buffer.id == buffer->id.id) return;
Window *last_window = GetWindow(GetLastActiveWindow());
View *last_view = GetActiveView(last_window);
Buffer *last_buffer = GetBuffer(last_view->active_buffer);
Scratch scratch;
String s = Format(scratch, "wid: %d\nvid: %d\nbid: %d\nframe: %lld\n", (int)last_window->id.id, (int)last_view->id.id, (int)last_buffer->id.id, (long long)FrameID);
String16 string = ToString16(scratch, s);
ReplaceText(buffer, GetRange(*buffer), string);
String view_list = DebugViewList(scratch);
Append(buffer, ToString16(scratch, view_list));
Append(buffer, L"\n");
String window_list = DebugWindowList(scratch);
Append(buffer, ToString16(scratch, window_list));
}
void ApplyTitleBarChangesToWindow(Window *window, View *view, Buffer *buffer) {
String16 buffer_string = GetString(*buffer);
Range replace_range = {0, buffer->len};
if (Seek(buffer_string, L" |", &replace_range.max)) {
}
buffer_string = GetString(*buffer, replace_range);
buffer_string = Trim(buffer_string);
String16 col = {};
for (int64_t i = buffer_string.len - 1; i >= 0; i -= 1) {
if (IsDigit(buffer_string.data[i])) {
col.data = buffer_string.data + i;
col.len += 1;
} else if (buffer_string.data[i] == L':') {
break;
} else {
return;
}
}
buffer_string = Chop(buffer_string, col.len + 1);
String16 line = {};
for (int64_t i = buffer_string.len - 1; i >= 0; i -= 1) {
if (IsDigit(buffer_string.data[i])) {
line.data = buffer_string.data + i;
line.len += 1;
} else if (buffer_string.data[i] == L':') {
break;
} else {
return;
}
}
buffer_string = Chop(buffer_string, line.len + 1);
Window *last_window = GetWindow(window->title_bar_window);
View *last_view = GetActiveView(last_window);
Buffer *last_buffer = GetBuffer(last_view->active_buffer);
Scratch scratch;
String filepath = ToString(scratch, buffer_string);
if (filepath != last_buffer->name && !BufferNameExists(filepath)) {
// @todo: maybe intern the filenames?
// @leak
last_buffer->name = Copy(Perm, filepath);
}
String line_string = ToString(scratch, line);
String col_string = ToString(scratch, col);
Int linei = strtoll(line_string.data, NULL, 10) - 1;
Int coli = strtoll(col_string.data, NULL, 10) - 1;
Int buffer_pos = XYToPos(*last_buffer, {coli, linei});
Caret &caret = last_view->carets[0];
if (GetFront(caret) != buffer_pos) {
caret = MakeCaret(buffer_pos);
}
window->title_bar_last_buffer_change_id = buffer->change_id;
}
void ReplaceTitleBarData(Window *window) {
View *view = GetView(window->active_view);
view->scroll.y = 0;
Buffer *buffer = GetBuffer(view->active_buffer);
if (IsActive(window)) {
if (buffer->change_id != window->title_bar_last_buffer_change_id) {
ApplyTitleBarChangesToWindow(window, view, buffer);
}
return;
}
Window *last_window = GetWindow(window->title_bar_window);
View *last_view = GetActiveView(last_window);
Buffer *last_buffer = GetBuffer(last_view->active_buffer);
Scratch scratch;
Caret caret = last_view->carets[0];
XY xy = PosToXY(*last_buffer, GetFront(caret));
String name = last_buffer->name;
String16 buffer_string = GetString(*buffer);
Range replace_range = {0, buffer->len};
if (!Seek(buffer_string, L" |", &replace_range.max)) {
Command_SelectRangeOneCursor(view, GetEndAsRange(*buffer));
Command_Replace(view, L" |");
}
String s = Format(scratch, "%.*s:%lld:%lld", FmtString(last_buffer->name), (long long)xy.line + 1ll, (long long)xy.col + 1ll);
String16 string = ToString16(scratch, s);
String16 string_to_replace = GetString(*buffer, replace_range);
if (string_to_replace != string) {
Command_SelectRangeOneCursor(view, replace_range);
Command_Replace(view, string);
Command_SelectRangeOneCursor(view, {});
}
}
void WindowCommand(Event event, Window *window, View *view) {
ProfileFunction();
Buffer *buffer = GetBuffer(view->active_buffer);
@@ -503,7 +402,8 @@ void WindowCommand(Event event, Window *window, View *view) {
bool search = false;
if (Press(SDLK_TAB)) {
Command_Replace(view, L" ");
// Command_Replace(view, L" ");
Command_IndentSelectedLines(view);
search = true;
}

View File

@@ -35,6 +35,7 @@ int FullScreenPositionX, FullScreenPositionY;
#include "commands.cpp"
#include "commands_clipboard.cpp"
#include "commands_window.cpp"
#include "title_bar.cpp"
#include "lua.hpp"
#include "lua_api.cpp"

View File

@@ -0,0 +1,144 @@
String DebugViewList(Allocator allocator) {
Scratch scratch((Arena *)allocator.object);
Array<String> strings = {scratch};
For(Views) {
Buffer *buffer = GetBuffer(it.active_buffer);
String string = Format(scratch, "view = %lld buffer = %lld name = %.*s", (long long)it.id.id, (long long)buffer->id.id, FmtString(buffer->name));
Add(&strings, string);
}
String result = Merge(allocator, strings, "\n");
return result;
}
String DebugWindowList(Allocator allocator) {
Scratch scratch((Arena *)allocator.object);
Array<String> strings = {scratch};
For(Windows) {
View *view = GetActiveView(&it);
Buffer *buffer = GetBuffer(view->active_buffer);
String string = Format(scratch, "window = %lld active_view = %lld buffer_name = %.*s", (long long)it.id.id, (long long)it.active_view.id, FmtString(buffer->name));
Add(&strings, string);
}
String result = Merge(allocator, strings, "\n");
return result;
}
void ReplaceDebugData() {
Buffer *buffer = GetBuffer("*debug*");
Window *window = GetActiveWindow();
View *view = GetActiveView(window);
if (view->active_buffer.id == buffer->id.id) return;
Window *last_window = GetWindow(GetLastActiveWindow());
View *last_view = GetActiveView(last_window);
Buffer *last_buffer = GetBuffer(last_view->active_buffer);
Scratch scratch;
String s = Format(scratch, "wid: %d\nvid: %d\nbid: %d\nframe: %lld\n", (int)last_window->id.id, (int)last_view->id.id, (int)last_buffer->id.id, (long long)FrameID);
String16 string = ToString16(scratch, s);
ReplaceText(buffer, GetRange(*buffer), string);
String view_list = DebugViewList(scratch);
Append(buffer, ToString16(scratch, view_list));
Append(buffer, L"\n");
String window_list = DebugWindowList(scratch);
Append(buffer, ToString16(scratch, window_list));
}
void ApplyTitleBarChangesToWindow(Window *window, View *view, Buffer *buffer) {
String16 buffer_string = GetString(*buffer);
Range replace_range = {0, buffer->len};
if (Seek(buffer_string, L" |", &replace_range.max)) {
}
buffer_string = GetString(*buffer, replace_range);
buffer_string = Trim(buffer_string);
String16 col = {};
for (int64_t i = buffer_string.len - 1; i >= 0; i -= 1) {
if (IsDigit(buffer_string.data[i])) {
col.data = buffer_string.data + i;
col.len += 1;
} else if (buffer_string.data[i] == L':') {
break;
} else {
return;
}
}
buffer_string = Chop(buffer_string, col.len + 1);
String16 line = {};
for (int64_t i = buffer_string.len - 1; i >= 0; i -= 1) {
if (IsDigit(buffer_string.data[i])) {
line.data = buffer_string.data + i;
line.len += 1;
} else if (buffer_string.data[i] == L':') {
break;
} else {
return;
}
}
buffer_string = Chop(buffer_string, line.len + 1);
Window *last_window = GetWindow(window->title_bar_window);
View *last_view = GetActiveView(last_window);
Buffer *last_buffer = GetBuffer(last_view->active_buffer);
Scratch scratch;
String filepath = ToString(scratch, buffer_string);
if (filepath != last_buffer->name && !BufferNameExists(filepath)) {
// @todo: maybe intern the filenames?
// @leak
last_buffer->name = Copy(Perm, filepath);
}
String line_string = ToString(scratch, line);
String col_string = ToString(scratch, col);
Int linei = strtoll(line_string.data, NULL, 10) - 1;
Int coli = strtoll(col_string.data, NULL, 10) - 1;
Int buffer_pos = XYToPos(*last_buffer, {coli, linei});
Caret &caret = last_view->carets[0];
if (GetFront(caret) != buffer_pos) {
caret = MakeCaret(buffer_pos);
}
window->title_bar_last_buffer_change_id = buffer->change_id;
}
void ReplaceTitleBarData(Window *window) {
View *view = GetView(window->active_view);
view->scroll.y = 0;
Buffer *buffer = GetBuffer(view->active_buffer);
if (IsActive(window)) {
if (buffer->change_id != window->title_bar_last_buffer_change_id) {
ApplyTitleBarChangesToWindow(window, view, buffer);
}
return;
}
Window *last_window = GetWindow(window->title_bar_window);
View *last_view = GetActiveView(last_window);
Buffer *last_buffer = GetBuffer(last_view->active_buffer);
Scratch scratch;
Caret caret = last_view->carets[0];
XY xy = PosToXY(*last_buffer, GetFront(caret));
String name = last_buffer->name;
String16 buffer_string = GetString(*buffer);
Range replace_range = {0, buffer->len};
if (!Seek(buffer_string, L" |", &replace_range.max)) {
Command_SelectRangeOneCursor(view, GetEndAsRange(*buffer));
Command_Replace(view, L" |");
}
String s = Format(scratch, "%.*s:%lld:%lld", FmtString(last_buffer->name), (long long)xy.line + 1ll, (long long)xy.col + 1ll);
String16 string = ToString16(scratch, s);
String16 string_to_replace = GetString(*buffer, replace_range);
if (string_to_replace != string) {
Command_SelectRangeOneCursor(view, replace_range);
Command_Replace(view, string);
Command_SelectRangeOneCursor(view, {});
}
}

View File

@@ -19,6 +19,7 @@
- be careful about globals
- Windows
- layout using a tree!!
- search as part of title window?
- layouting, resize windows
- maybe we can use first line number to use the window?