Lua and better cursor movement
This commit is contained in:
@@ -48,6 +48,32 @@ Library PrepareRaylib() {
|
|||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Library PrepareLua() {
|
||||||
|
Library l = {};
|
||||||
|
l.include_paths.add("../src/external/lua/src");
|
||||||
|
|
||||||
|
MA_Scratch scratch;
|
||||||
|
for (OS_FileIter it = OS_IterateFiles(scratch, "../src/external/lua/src"); OS_IsValid(it); OS_Advance(&it)) {
|
||||||
|
if (it.filename == "luac.c") continue;
|
||||||
|
if (it.filename == "lua.c") continue;
|
||||||
|
if (S8_EndsWith(it.filename, ".c", true)) {
|
||||||
|
l.sources.add(it.absolute_path);
|
||||||
|
S8_String file = S8_ChopLastPeriod(it.filename);
|
||||||
|
l.objects.add(Fmt("%.*s.obj", S8_Expand(file)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!OS_FileExists(l.objects[0])) {
|
||||||
|
Array<S8_String> cmd = {};
|
||||||
|
cmd.add("cl.exe -c");
|
||||||
|
AddCommonFlags(&cmd);
|
||||||
|
For(l.include_paths) cmd.add(S8_Format(Perm, "-I %.*s ", S8_Expand(it)));
|
||||||
|
cmd += l.sources;
|
||||||
|
Run(cmd);
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
Library PrepareGlad() {
|
Library PrepareGlad() {
|
||||||
Library l = {};
|
Library l = {};
|
||||||
l.sources.add("../src/external/glad/glad.c");
|
l.sources.add("../src/external/glad/glad.c");
|
||||||
@@ -69,6 +95,7 @@ int CompileTextEditor() {
|
|||||||
|
|
||||||
Array<Library> libs = {};
|
Array<Library> libs = {};
|
||||||
libs.add(PrepareRaylib());
|
libs.add(PrepareRaylib());
|
||||||
|
libs.add(PrepareLua());
|
||||||
|
|
||||||
Array<S8_String> cmd = {};
|
Array<S8_String> cmd = {};
|
||||||
cmd.add("cl.exe");
|
cmd.add("cl.exe");
|
||||||
|
|||||||
@@ -3,17 +3,17 @@ https://code.visualstudio.com/blogs/2018/03/23/text-buffer-reimplementation
|
|||||||
*/
|
*/
|
||||||
#define BUFFER_DEBUG 0
|
#define BUFFER_DEBUG 0
|
||||||
|
|
||||||
void InitBuffer(Allocator allocator, Buffer *buffer) {
|
void InitBuffer(Allocator allocator, Buffer *buffer, Int size = 4096) {
|
||||||
buffer->id = AllocBufferID();
|
buffer->id = AllocBufferID();
|
||||||
buffer->cap = 4096;
|
buffer->cap = size;
|
||||||
buffer->data = AllocArray(allocator, U16, buffer->cap);
|
buffer->data = AllocArray(allocator, U16, buffer->cap);
|
||||||
buffer->line_starts.allocator = allocator;
|
buffer->line_starts.allocator = allocator;
|
||||||
Add(&buffer->line_starts, (Int)0);
|
Add(&buffer->line_starts, (Int)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer *CreateBuffer(Allocator allocator) {
|
Buffer *CreateBuffer(Allocator allocator, Int size = 4096) {
|
||||||
Buffer *result = Alloc(&Buffers);
|
Buffer *result = Alloc(&Buffers);
|
||||||
InitBuffer(allocator, result);
|
InitBuffer(allocator, result, size);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,6 +188,49 @@ void ReplaceText(Buffer *buffer, Range range, String16 string) {
|
|||||||
#endif
|
#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() {
|
void TestBuffer() {
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -63,18 +63,27 @@ bool IsDoubleClick() {
|
|||||||
Int MoveOnWhitespaceBoundaryForward(Buffer &buffer, Int pos) {
|
Int MoveOnWhitespaceBoundaryForward(Buffer &buffer, Int pos) {
|
||||||
pos = Clamp(pos, (Int)0, buffer.len);
|
pos = Clamp(pos, (Int)0, buffer.len);
|
||||||
bool standing_on_whitespace = IsWhitespace(buffer.str[pos]);
|
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_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 result = buffer.len;
|
||||||
Int prev_pos = pos;
|
Int prev_pos = pos;
|
||||||
for (Int i = pos; i < buffer.len; i += 1) {
|
for (Int i = pos; i < buffer.len; i += 1) {
|
||||||
bool whitespace = IsWhitespace(buffer.str[i]);
|
bool is_whitespace = IsWhitespace(buffer.str[i]);
|
||||||
if (seek_word && !whitespace) {
|
bool is_symbol = IsSymbol(buffer.str[i]);
|
||||||
|
bool is_word = !is_whitespace && !is_symbol;
|
||||||
|
if (seek_word && is_word) {
|
||||||
result = i;
|
result = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (seek_whitespace && whitespace) {
|
if (seek_whitespace && is_whitespace) {
|
||||||
|
result = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (seek_symbol && is_symbol) {
|
||||||
result = i;
|
result = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -86,18 +95,27 @@ Int MoveOnWhitespaceBoundaryForward(Buffer &buffer, Int pos) {
|
|||||||
Int MoveOnWhitespaceBoundaryBackward(Buffer &buffer, Int pos) {
|
Int MoveOnWhitespaceBoundaryBackward(Buffer &buffer, Int pos) {
|
||||||
pos = Clamp(pos - 1, (Int)0, buffer.len);
|
pos = Clamp(pos - 1, (Int)0, buffer.len);
|
||||||
bool standing_on_whitespace = IsWhitespace(buffer.str[pos]);
|
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_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 result = 0;
|
||||||
Int prev_pos = pos;
|
Int prev_pos = pos;
|
||||||
for (Int i = pos; i >= 0; i -= 1) {
|
for (Int i = pos; i >= 0; i -= 1) {
|
||||||
bool whitespace = IsWhitespace(buffer.str[i]);
|
bool is_whitespace = IsWhitespace(buffer.str[i]);
|
||||||
if (seek_word && !whitespace) {
|
bool is_symbol = IsSymbol(buffer.str[i]);
|
||||||
|
bool is_word = !is_whitespace && !is_symbol;
|
||||||
|
if (seek_word && is_word) {
|
||||||
result = prev_pos;
|
result = prev_pos;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (seek_whitespace && whitespace) {
|
if (seek_whitespace && is_whitespace) {
|
||||||
|
result = prev_pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (seek_symbol && is_symbol) {
|
||||||
result = prev_pos;
|
result = prev_pos;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -271,7 +271,12 @@ void HandleActiveWindowBindings(Window *window) {
|
|||||||
Command_MoveCursorsToSide(window, DIR_RIGHT);
|
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");
|
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;
|
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 IsAlphabetic(wchar_t a) {
|
||||||
bool result = (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z');
|
bool result = (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z');
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#define BASIC_IMPL
|
#define BASIC_IMPL
|
||||||
#include "../basic/basic.h"
|
#include "../basic/basic.h"
|
||||||
|
#include "../basic/filesystem.h"
|
||||||
#include "../profiler/profiler.cpp"
|
#include "../profiler/profiler.cpp"
|
||||||
#include "new_basic.cpp"
|
#include "new_basic.cpp"
|
||||||
#include "string16.cpp"
|
#include "string16.cpp"
|
||||||
@@ -24,17 +25,25 @@
|
|||||||
#include "window.cpp"
|
#include "window.cpp"
|
||||||
#include "window_draw.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)
|
- Open file (utf8->utf16), process determine line endings, tabs to spaces?, Save file (utf16->utf8)
|
||||||
|
- line endings
|
||||||
- resize windows
|
- resize windows
|
||||||
- command window
|
- command window
|
||||||
- maybe use lua and have there be lua commands that you choose with cursor
|
- maybe use lua and have there be lua commands that you choose with cursor
|
||||||
- open "asd/asd/asd/asd"
|
- 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
|
- word completion
|
||||||
- Colored strings
|
- Colored strings
|
||||||
- file dock on left side
|
|
||||||
|
|
||||||
- move off raylib
|
- move off raylib
|
||||||
- Adjust text position a little bit down?
|
- Adjust text position a little bit down?
|
||||||
@@ -79,7 +88,7 @@ int main(void) {
|
|||||||
View *view = CreateView(buffer->id);
|
View *view = CreateView(buffer->id);
|
||||||
Window *window = CreateWindow();
|
Window *window = CreateWindow();
|
||||||
window->visible = false;
|
window->visible = false;
|
||||||
AddView(window->id, view->id);
|
AddView(window, view->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -87,7 +96,7 @@ int main(void) {
|
|||||||
Buffer *b = CreateBuffer(sys_allocator);
|
Buffer *b = CreateBuffer(sys_allocator);
|
||||||
View *v = CreateView(b->id);
|
View *v = CreateView(b->id);
|
||||||
LoadTextA(b);
|
LoadTextA(b);
|
||||||
AddView(w->id, v->id);
|
AddView(w, v->id);
|
||||||
}
|
}
|
||||||
ActiveWindow.id = 1;
|
ActiveWindow.id = 1;
|
||||||
|
|
||||||
@@ -96,14 +105,13 @@ int main(void) {
|
|||||||
Buffer *b = CreateBuffer(sys_allocator);
|
Buffer *b = CreateBuffer(sys_allocator);
|
||||||
View *v = CreateView(b->id);
|
View *v = CreateView(b->id);
|
||||||
LoadUnicode(b);
|
LoadUnicode(b);
|
||||||
AddView(w->id, v->id);
|
AddView(w, v->id);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
Window *w = CreateWindow();
|
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);
|
View *v = CreateView(b->id);
|
||||||
LoadLine(b);
|
AddView(w, v->id);
|
||||||
AddView(w->id, v->id);
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
Window *w = CreateWindow();
|
Window *w = CreateWindow();
|
||||||
@@ -114,7 +122,7 @@ int main(void) {
|
|||||||
Buffer *b = CreateBuffer(sys_allocator);
|
Buffer *b = CreateBuffer(sys_allocator);
|
||||||
View *v = CreateView(b->id);
|
View *v = CreateView(b->id);
|
||||||
LoadLine(b);
|
LoadLine(b);
|
||||||
AddView(w->id, v->id);
|
AddView(w, v->id);
|
||||||
CommandWindowID = w->id;
|
CommandWindowID = w->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -134,3 +134,5 @@ inline View *GetActiveView(Window *window) {
|
|||||||
if (window->active_view.id == 0) return GetView(window->views[0]);
|
if (window->active_view.id == 0) return GetView(window->views[0]);
|
||||||
else return GetView(window->active_view);
|
else return GetView(window->active_view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EvalString(String16 string16);
|
||||||
@@ -8,8 +8,7 @@ Window *CreateWindow() {
|
|||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddView(WindowID window, ViewID view) {
|
void AddView(Window *w, ViewID view) {
|
||||||
Window *w = GetWindow(window);
|
|
||||||
if (w->active_view.id == 0) w->active_view = view;
|
if (w->active_view.id == 0) w->active_view = view;
|
||||||
For(w->views) if (it.id == view.id) return;
|
For(w->views) if (it.id == view.id) return;
|
||||||
Add(&w->views, view);
|
Add(&w->views, view);
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ void DrawVisibleText(Window &window) {
|
|||||||
Vec2I pos = {visible.min.x * (Int)FontCharSpacing, line_index * (Int)FontLineSpacing};
|
Vec2I pos = {visible.min.x * (Int)FontCharSpacing, line_index * (Int)FontLineSpacing};
|
||||||
pos -= view.scroll;
|
pos -= view.scroll;
|
||||||
pos += window.document_rect.min;
|
pos += window.document_rect.min;
|
||||||
|
// pos.y += (Int)(0.3 * (double)FontSize); // @todo: descent
|
||||||
|
|
||||||
float text_offset_x = 0;
|
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) {
|
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