Lua and better cursor movement
This commit is contained in:
@@ -3,17 +3,17 @@ https://code.visualstudio.com/blogs/2018/03/23/text-buffer-reimplementation
|
||||
*/
|
||||
#define BUFFER_DEBUG 0
|
||||
|
||||
void InitBuffer(Allocator allocator, Buffer *buffer) {
|
||||
void InitBuffer(Allocator allocator, Buffer *buffer, Int size = 4096) {
|
||||
buffer->id = AllocBufferID();
|
||||
buffer->cap = 4096;
|
||||
buffer->cap = size;
|
||||
buffer->data = AllocArray(allocator, U16, buffer->cap);
|
||||
buffer->line_starts.allocator = allocator;
|
||||
Add(&buffer->line_starts, (Int)0);
|
||||
}
|
||||
|
||||
Buffer *CreateBuffer(Allocator allocator) {
|
||||
Buffer *CreateBuffer(Allocator allocator, Int size = 4096) {
|
||||
Buffer *result = Alloc(&Buffers);
|
||||
InitBuffer(allocator, result);
|
||||
InitBuffer(allocator, result, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -188,6 +188,49 @@ void ReplaceText(Buffer *buffer, Range range, String16 string) {
|
||||
#endif
|
||||
}
|
||||
|
||||
Buffer *OpenFile(String path) {
|
||||
Scratch scratch;
|
||||
String string = ReadFile(scratch, path);
|
||||
|
||||
Allocator sys_allocator = GetSystemAllocator();
|
||||
Buffer *buffer = CreateBuffer(sys_allocator, string.len * 4);
|
||||
|
||||
for (Int i = 0; i < string.len;) {
|
||||
if (string.data[i] == '\r') {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
if (string.data[i] == '\t') {
|
||||
// @WARNING: DONT INCREASE THE SIZE CARELESSLY, WE NEED TO ADJUST BUFFER SIZE
|
||||
for (Int i = 0; i < 4; i += 1) buffer->data[buffer->len++] = L' ';
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t u32 = '?';
|
||||
UTF32Result decode = UTF8ToUTF32(string.data + i, (int64_t)(string.len - i));
|
||||
if (!decode.error) {
|
||||
i += decode.advance;
|
||||
u32 = decode.out_str;
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
|
||||
UTF16Result encode = UTF32ToUTF16(decode.out_str);
|
||||
if (!encode.error) {
|
||||
for (int64_t encode_i = 0; encode_i < encode.len; encode_i += 1) {
|
||||
buffer->data[buffer->len++] = encode.out_str[encode_i];
|
||||
Assert(buffer->len < buffer->cap);
|
||||
}
|
||||
} else {
|
||||
buffer->data[buffer->len++] = L'?';
|
||||
}
|
||||
}
|
||||
UpdateLines(buffer, {}, String16{(wchar_t *)buffer->data, buffer->len});
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void TestBuffer() {
|
||||
Scratch scratch;
|
||||
{
|
||||
|
||||
@@ -63,18 +63,27 @@ bool IsDoubleClick() {
|
||||
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;
|
||||
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 whitespace = IsWhitespace(buffer.str[i]);
|
||||
if (seek_word && !whitespace) {
|
||||
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 && whitespace) {
|
||||
if (seek_whitespace && is_whitespace) {
|
||||
result = i;
|
||||
break;
|
||||
}
|
||||
if (seek_symbol && is_symbol) {
|
||||
result = i;
|
||||
break;
|
||||
}
|
||||
@@ -86,18 +95,27 @@ Int MoveOnWhitespaceBoundaryForward(Buffer &buffer, Int pos) {
|
||||
Int MoveOnWhitespaceBoundaryBackward(Buffer &buffer, Int pos) {
|
||||
pos = Clamp(pos - 1, (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;
|
||||
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 whitespace = IsWhitespace(buffer.str[i]);
|
||||
if (seek_word && !whitespace) {
|
||||
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 && whitespace) {
|
||||
if (seek_whitespace && is_whitespace) {
|
||||
result = prev_pos;
|
||||
break;
|
||||
}
|
||||
if (seek_symbol && is_symbol) {
|
||||
result = prev_pos;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -271,7 +271,12 @@ void HandleActiveWindowBindings(Window *window) {
|
||||
Command_MoveCursorsToSide(window, DIR_RIGHT);
|
||||
}
|
||||
|
||||
if (window->banish_new_lines == false && Press(KEY_ENTER)) {
|
||||
if (CtrlPress(KEY_ENTER)) {
|
||||
Int line = PosToLine(*buffer, GetFront(view.carets[0]));
|
||||
Range range = GetLineRange(*buffer, line);
|
||||
String16 string = GetString(*buffer, range);
|
||||
EvalString(string);
|
||||
} else if (window->banish_new_lines == false && Press(KEY_ENTER)) {
|
||||
Command_Replace(&view, L"\n");
|
||||
}
|
||||
|
||||
|
||||
32
src/text_editor/lua_api.cpp
Normal file
32
src/text_editor/lua_api.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
lua_State *LuaState = NULL;
|
||||
|
||||
int LuaOpenFile(lua_State *L) {
|
||||
const char *text = luaL_checkstring(L, 1);
|
||||
String string = text;
|
||||
Buffer *buffer = OpenFile(string);
|
||||
View *view = CreateView(buffer->id);
|
||||
Window *window = GetWindow({1});
|
||||
AddView(window, view->id);
|
||||
window->active_view = view->id;
|
||||
SetActiveWindow(window->id);
|
||||
return 0; // number of results
|
||||
}
|
||||
|
||||
void InitLua() {
|
||||
LuaState = luaL_newstate();
|
||||
luaL_openlibs(LuaState);
|
||||
|
||||
lua_pushcfunction(LuaState, LuaOpenFile);
|
||||
lua_setglobal(LuaState, "open");
|
||||
}
|
||||
|
||||
void EvalString(String16 string16) {
|
||||
if (!LuaState) InitLua();
|
||||
Scratch scratch;
|
||||
String string = ToString(scratch, string16);
|
||||
if (luaL_dostring(LuaState, string.data) != LUA_OK) {
|
||||
const char *text = lua_tostring(LuaState, -1);
|
||||
printf("lua error: %s", text);
|
||||
}
|
||||
// @todo: send error or data to some buffer
|
||||
}
|
||||
@@ -13,6 +13,11 @@ bool IsWhitespace(wchar_t w) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool IsSymbol(wchar_t w) {
|
||||
bool result = (w >= '!' && w <= '/') || (w >= ':' && w <= '@') || (w >= '[' && w <= '`') || (w >= '{' && w <= '~');
|
||||
return result;
|
||||
}
|
||||
|
||||
bool IsAlphabetic(wchar_t a) {
|
||||
bool result = (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z');
|
||||
return result;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#define BASIC_IMPL
|
||||
#include "../basic/basic.h"
|
||||
#include "../basic/filesystem.h"
|
||||
#include "../profiler/profiler.cpp"
|
||||
#include "new_basic.cpp"
|
||||
#include "string16.cpp"
|
||||
@@ -24,17 +25,25 @@
|
||||
#include "window.cpp"
|
||||
#include "window_draw.cpp"
|
||||
|
||||
#include "lua.hpp"
|
||||
#include "lua_api.cpp"
|
||||
|
||||
/*
|
||||
- Open file (utf8->utf16), process determine line endings, tabs to spaces?, Save file (utf16->utf8)
|
||||
- line endings
|
||||
- resize windows
|
||||
- command window
|
||||
- maybe use lua and have there be lua commands that you choose with cursor
|
||||
- open "asd/asd/asd/asd"
|
||||
- file dock on left side
|
||||
- We can actually combine this with command window and lua, it's just going to be a buffer of
|
||||
- open "asd/asd/asd/asd"
|
||||
|
||||
- Ctrl + F
|
||||
- Better enclosure and word hopping
|
||||
|
||||
- line endings
|
||||
- word completion
|
||||
- Colored strings
|
||||
- file dock on left side
|
||||
|
||||
- move off raylib
|
||||
- Adjust text position a little bit down?
|
||||
@@ -79,7 +88,7 @@ int main(void) {
|
||||
View *view = CreateView(buffer->id);
|
||||
Window *window = CreateWindow();
|
||||
window->visible = false;
|
||||
AddView(window->id, view->id);
|
||||
AddView(window, view->id);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -87,7 +96,7 @@ int main(void) {
|
||||
Buffer *b = CreateBuffer(sys_allocator);
|
||||
View *v = CreateView(b->id);
|
||||
LoadTextA(b);
|
||||
AddView(w->id, v->id);
|
||||
AddView(w, v->id);
|
||||
}
|
||||
ActiveWindow.id = 1;
|
||||
|
||||
@@ -96,14 +105,13 @@ int main(void) {
|
||||
Buffer *b = CreateBuffer(sys_allocator);
|
||||
View *v = CreateView(b->id);
|
||||
LoadUnicode(b);
|
||||
AddView(w->id, v->id);
|
||||
AddView(w, v->id);
|
||||
}
|
||||
{
|
||||
Window *w = CreateWindow();
|
||||
Buffer *b = CreateBuffer(sys_allocator);
|
||||
Buffer *b = OpenFile("C:/Work/text_editor/src/text_editor/text_editor.cpp");
|
||||
View *v = CreateView(b->id);
|
||||
LoadLine(b);
|
||||
AddView(w->id, v->id);
|
||||
AddView(w, v->id);
|
||||
}
|
||||
{
|
||||
Window *w = CreateWindow();
|
||||
@@ -114,7 +122,7 @@ int main(void) {
|
||||
Buffer *b = CreateBuffer(sys_allocator);
|
||||
View *v = CreateView(b->id);
|
||||
LoadLine(b);
|
||||
AddView(w->id, v->id);
|
||||
AddView(w, v->id);
|
||||
CommandWindowID = w->id;
|
||||
}
|
||||
|
||||
|
||||
@@ -134,3 +134,5 @@ inline View *GetActiveView(Window *window) {
|
||||
if (window->active_view.id == 0) return GetView(window->views[0]);
|
||||
else return GetView(window->active_view);
|
||||
}
|
||||
|
||||
void EvalString(String16 string16);
|
||||
@@ -8,8 +8,7 @@ Window *CreateWindow() {
|
||||
return w;
|
||||
}
|
||||
|
||||
void AddView(WindowID window, ViewID view) {
|
||||
Window *w = GetWindow(window);
|
||||
void AddView(Window *w, ViewID view) {
|
||||
if (w->active_view.id == 0) w->active_view = view;
|
||||
For(w->views) if (it.id == view.id) return;
|
||||
Add(&w->views, view);
|
||||
|
||||
@@ -52,6 +52,7 @@ void DrawVisibleText(Window &window) {
|
||||
Vec2I pos = {visible.min.x * (Int)FontCharSpacing, line_index * (Int)FontLineSpacing};
|
||||
pos -= view.scroll;
|
||||
pos += window.document_rect.min;
|
||||
// pos.y += (Int)(0.3 * (double)FontSize); // @todo: descent
|
||||
|
||||
float text_offset_x = 0;
|
||||
for (Int col_index = visible.min.x; col_index < visible.max.x && col_index >= 0 && col_index < line_string.len; col_index += 1) {
|
||||
|
||||
Reference in New Issue
Block a user