Indent selected lines
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
144
src/text_editor/title_bar.cpp
Normal file
144
src/text_editor/title_bar.cpp
Normal 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, {});
|
||||
}
|
||||
}
|
||||
@@ -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?
|
||||
|
||||
Reference in New Issue
Block a user