Indent selected lines
This commit is contained in:
@@ -102,7 +102,8 @@ void BeforeEdit(Buffer *buffer, Array<Caret> &carets) {
|
|||||||
ClearRedoStack(buffer);
|
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();
|
ProfileFunction();
|
||||||
Assert(buffer->debug_edit_phase == 2);
|
Assert(buffer->debug_edit_phase == 2);
|
||||||
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 &old_cursor = carets->data[i];
|
||||||
Caret &new_cursor = new_carets.data[i];
|
Caret &new_cursor = new_carets.data[i];
|
||||||
if (old_cursor.range.min == edit.range.min) {
|
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) {
|
} 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));
|
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;
|
bool SHIFT_PRESSED = true;
|
||||||
void Command_MoveCursorsByPageSize(Window *window, int direction, bool shift = false) {
|
void Command_MoveCursorsByPageSize(Window *window, int direction, bool shift = false) {
|
||||||
Assert(direction == DIR_UP || direction == DIR_DOWN);
|
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.
|
// make sure overlapping edits won't happen.
|
||||||
//
|
//
|
||||||
// mouse_selection_anchor is special case for mouse handling !
|
// mouse_selection_anchor is special case for mouse handling !
|
||||||
|
|
||||||
void MergeCarets(View *view, Range *mouse_selection_anchor) {
|
void MergeCarets(View *view, Range *mouse_selection_anchor) {
|
||||||
ProfileFunction();
|
ProfileFunction();
|
||||||
|
|
||||||
@@ -210,151 +254,6 @@ void MergeCarets(View *view, Range *mouse_selection_anchor) {
|
|||||||
Swap(&view->carets[first_caret_index], &view->carets[0]);
|
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) {
|
void WindowCommand(Event event, Window *window, View *view) {
|
||||||
ProfileFunction();
|
ProfileFunction();
|
||||||
Buffer *buffer = GetBuffer(view->active_buffer);
|
Buffer *buffer = GetBuffer(view->active_buffer);
|
||||||
@@ -503,7 +402,8 @@ void WindowCommand(Event event, Window *window, View *view) {
|
|||||||
|
|
||||||
bool search = false;
|
bool search = false;
|
||||||
if (Press(SDLK_TAB)) {
|
if (Press(SDLK_TAB)) {
|
||||||
Command_Replace(view, L" ");
|
// Command_Replace(view, L" ");
|
||||||
|
Command_IndentSelectedLines(view);
|
||||||
search = true;
|
search = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ int FullScreenPositionX, FullScreenPositionY;
|
|||||||
#include "commands.cpp"
|
#include "commands.cpp"
|
||||||
#include "commands_clipboard.cpp"
|
#include "commands_clipboard.cpp"
|
||||||
#include "commands_window.cpp"
|
#include "commands_window.cpp"
|
||||||
|
#include "title_bar.cpp"
|
||||||
|
|
||||||
#include "lua.hpp"
|
#include "lua.hpp"
|
||||||
#include "lua_api.cpp"
|
#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
|
- be careful about globals
|
||||||
|
|
||||||
- Windows
|
- Windows
|
||||||
|
- layout using a tree!!
|
||||||
- search as part of title window?
|
- search as part of title window?
|
||||||
- layouting, resize windows
|
- layouting, resize windows
|
||||||
- maybe we can use first line number to use the window?
|
- maybe we can use first line number to use the window?
|
||||||
|
|||||||
Reference in New Issue
Block a user