Compare commits
8 Commits
a351d2eb41
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7720176e60 | ||
|
|
29002c965c | ||
|
|
5e7acd4a20 | ||
|
|
4e5a0f6a9b | ||
|
|
f297006dcb | ||
|
|
85ca1a6a9e | ||
|
|
5a12ab8d8c | ||
|
|
2d79790d83 |
81
build.sh
Normal file → Executable file
81
build.sh
Normal file → Executable file
@@ -3,79 +3,10 @@
|
|||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
|
|
||||||
if [ "$1" = "release" ]; then
|
FLAGS="-nostdlib++ -fno-exceptions -fdiagnostics-absolute-paths -g -Wno-writable-strings -I../src -DDEBUG_BUILD=1"
|
||||||
profile_flags="-DDEBUG_BUILD=0 -O2"
|
# clang -o metaprogram $FLAGS ../src/metaprogram/metaprogram.cpp
|
||||||
else
|
# ./metaprogram
|
||||||
profile_flags="-DDEBUG_BUILD=1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "lbaselib.o" ]; then
|
I="-I../src/external/SDL/include -I../src/external/lua/src -I../src/external/glad"
|
||||||
clang -g -I../src/external/lua/src -I../src/external/glad \
|
clang -o te $FLAGS ../src/text_editor/text_editor.cpp $I -lSDL3 -lm -lbacktrace
|
||||||
../src/external/lua/src/lbaselib.c \
|
cp te ../data/te
|
||||||
../src/external/lua/src/lctype.c \
|
|
||||||
../src/external/lua/src/ldo.c \
|
|
||||||
../src/external/lua/src/lgc.c \
|
|
||||||
../src/external/lua/src/liolib.c \
|
|
||||||
../src/external/lua/src/lmem.c \
|
|
||||||
../src/external/lua/src/lopcodes.c \
|
|
||||||
../src/external/lua/src/lstate.c \
|
|
||||||
../src/external/lua/src/ltable.c \
|
|
||||||
../src/external/lua/src/lundump.c \
|
|
||||||
../src/external/lua/src/lzio.c \
|
|
||||||
../src/external/lua/src/lapi.c \
|
|
||||||
../src/external/lua/src/lcode.c \
|
|
||||||
../src/external/lua/src/ldblib.c \
|
|
||||||
../src/external/lua/src/ldump.c \
|
|
||||||
../src/external/lua/src/llex.c \
|
|
||||||
../src/external/lua/src/loadlib.c \
|
|
||||||
../src/external/lua/src/loslib.c \
|
|
||||||
../src/external/lua/src/lstring.c \
|
|
||||||
../src/external/lua/src/ltablib.c \
|
|
||||||
../src/external/lua/src/lutf8lib.c \
|
|
||||||
../src/external/lua/src/lauxlib.c \
|
|
||||||
../src/external/lua/src/lcorolib.c \
|
|
||||||
../src/external/lua/src/ldebug.c \
|
|
||||||
../src/external/lua/src/lfunc.c \
|
|
||||||
../src/external/lua/src/linit.c \
|
|
||||||
../src/external/lua/src/lmathlib.c \
|
|
||||||
../src/external/lua/src/lobject.c \
|
|
||||||
../src/external/lua/src/lparser.c \
|
|
||||||
../src/external/lua/src/lstrlib.c \
|
|
||||||
../src/external/lua/src/ltm.c \
|
|
||||||
../src/external/lua/src/lvm.c \
|
|
||||||
../src/external/glad/glad.c \
|
|
||||||
-c
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "metaprogram.exe" ]; then
|
|
||||||
clang ../src/metaprogram/metaprogram.cpp ../src/basic/unix.cpp -o metaprogram.exe \
|
|
||||||
-nostdlib++ -fno-exceptions -fdiagnostics-absolute-paths -g \
|
|
||||||
-Wno-writable-strings \
|
|
||||||
-I../src
|
|
||||||
fi
|
|
||||||
./metaprogram.exe
|
|
||||||
|
|
||||||
clang ../src/text_editor/text_editor.cpp ../src/basic/unix.cpp -o te_linux.exe \
|
|
||||||
-nostdlib++ -fno-exceptions -fdiagnostics-absolute-paths -g \
|
|
||||||
$profile_flags \
|
|
||||||
-Wno-writable-strings \
|
|
||||||
-I../src/external/SDL/include \
|
|
||||||
-I../src/external/lua/src \
|
|
||||||
-I../src/external/glad \
|
|
||||||
-I../src/ \
|
|
||||||
-lm \
|
|
||||||
../src/external/SDL/build/libSDL3.a \
|
|
||||||
lbaselib.o lctype.o ldo.o lgc.o liolib.o lmem.o \
|
|
||||||
lopcodes.o lstate.o ltable.o lundump.o lzio.o lapi.o lcode.o ldblib.o ldump.o \
|
|
||||||
llex.o loadlib.o loslib.o lstring.o ltablib.o lutf8lib.o lauxlib.o lcorolib.o ldebug.o \
|
|
||||||
lfunc.o linit.o lmathlib.o lobject.o lparser.o lstrlib.o ltm.o lvm.o \
|
|
||||||
glad.o \
|
|
||||||
|
|
||||||
|
|
||||||
if [ "$1" = "release" ]; then
|
|
||||||
cp te_linux.exe ../data/te
|
|
||||||
echo written ../data/te
|
|
||||||
else
|
|
||||||
cp te_linux.exe ../data/te_debug
|
|
||||||
echo written ../data/te_debug
|
|
||||||
fi
|
|
||||||
0
build_web.bat
Normal file → Executable file
0
build_web.bat
Normal file → Executable file
0
build_web.sh
Normal file → Executable file
0
build_web.sh
Normal file → Executable file
@@ -1,14 +0,0 @@
|
|||||||
FKey[2] = "remedybg.exe build\\te.exe"
|
|
||||||
FKey[5] = "remedybg.exe continue-execution"
|
|
||||||
FKey[9] = function () return 'remedybg.exe add-breakpoint-at-file '..GetFilename()..' '..tostring(GetLine()) end
|
|
||||||
FKey[10] = function () return 'remedybg.exe run-to-cursor '..GetFilename()..' '..tostring(GetLine()) end
|
|
||||||
|
|
||||||
|
|
||||||
function OnInit()
|
|
||||||
Open("init.project.lua")
|
|
||||||
Split(VERTICAL)
|
|
||||||
Open("src/text_editor/todo.txt")
|
|
||||||
Split(HORIZONTAL)
|
|
||||||
Open("src/text_editor/commands.cpp")
|
|
||||||
SplitSize(0.15)
|
|
||||||
end
|
|
||||||
@@ -1,12 +1,3 @@
|
|||||||
REDESIGN and DELETE CODE
|
|
||||||
- Reduce the amount of actions needed to navigate using keyboard
|
|
||||||
- Make mouse important but much less so
|
|
||||||
|
|
||||||
Needs to change:
|
|
||||||
- Make it more similar to sublime like editors
|
|
||||||
- Need Ctrl + P
|
|
||||||
- Clickable title bar may be cool or whatever but it's pretty bad
|
|
||||||
- Executing lua commands is clunky, need a real Ctrl+P and keybind actions, popups: remove a lot of the lua functionality, just for config files
|
|
||||||
- Window, View, Buffer + flags design (or is completely new kind based approach needed for Windows/Views?)
|
- Window, View, Buffer + flags design (or is completely new kind based approach needed for Windows/Views?)
|
||||||
- How to make non-editable, informative, with different font size, title bar. Which might also contain tabs
|
- How to make non-editable, informative, with different font size, title bar. Which might also contain tabs
|
||||||
- How to design clickable tree view in this way?
|
- How to design clickable tree view in this way?
|
||||||
@@ -14,22 +5,9 @@ Needs to change:
|
|||||||
- How to design popup view (input field)?
|
- How to design popup view (input field)?
|
||||||
- How to design search view? or search and replace view?
|
- How to design search view? or search and replace view?
|
||||||
|
|
||||||
Things I like:
|
|
||||||
- Basic editing
|
|
||||||
- Configurable Open
|
|
||||||
- Lua config files work pretty well
|
|
||||||
|
|
||||||
Splits:
|
Splits:
|
||||||
- Buffer16 Buffer8?
|
|
||||||
- Why constraint that name of buffer needs to be unique? For Open() and default behavior but is this required?
|
- Why constraint that name of buffer needs to be unique? For Open() and default behavior but is this required?
|
||||||
- Try to add Tracking Allocator and rewrite the app, free all memory at the end of the app and check all is well
|
- Try to add Tracking Allocator and rewrite the app, free all memory at the end of the app and check all is well
|
||||||
- move titlebar, search to splits?
|
|
||||||
|
|
||||||
|
|
||||||
Linux
|
|
||||||
- Add backtrace
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Commands TODO:
|
Commands TODO:
|
||||||
- Search
|
- Search
|
||||||
@@ -41,12 +19,13 @@ Commands TODO:
|
|||||||
- Console: OK concept but constrain
|
- Console: OK concept but constrain
|
||||||
- Turned off by default
|
- Turned off by default
|
||||||
- Special: non editable, hotkeys don't work etc.
|
- Special: non editable, hotkeys don't work etc.
|
||||||
|
- I'M SETTING ACTIVE WINDOW AFTER COMMAND!!! DO WE CONTINUE WITH THIS?
|
||||||
|
|
||||||
|
- CONSIDER AUTOMATING: CheckpointBeforeGoto
|
||||||
|
- GotoBackward how to handle that in case we want to automate and create on every move?
|
||||||
|
|
||||||
|
|
||||||
|
backlog
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DESIGN try to make console less special, make stuff reusable etc.
|
DESIGN try to make console less special, make stuff reusable etc.
|
||||||
DESIGN Config file versions, when loading should be checked, at the top of the file, what to do when old version?
|
DESIGN Config file versions, when loading should be checked, at the top of the file, what to do when old version?
|
||||||
ISSUE Ctrl+Alt+Down (DuplicateLine) doesn't work on ubuntu
|
ISSUE Ctrl+Alt+Down (DuplicateLine) doesn't work on ubuntu
|
||||||
@@ -79,7 +58,6 @@ FEATURE group history entries so the you can rollback through multiple ones at o
|
|||||||
- code sections, visual demarkation if beginning of line has a very specific text + goto next / goto prev section hotkey!
|
- code sections, visual demarkation if beginning of line has a very specific text + goto next / goto prev section hotkey!
|
||||||
- combine glyph and selection rendering
|
- combine glyph and selection rendering
|
||||||
|
|
||||||
backlog
|
|
||||||
- expose a coroutine based scripting enviorment where user can execute shell commands wait for them and perform actions in very linear manner
|
- expose a coroutine based scripting enviorment where user can execute shell commands wait for them and perform actions in very linear manner
|
||||||
- Test stdin writing code
|
- Test stdin writing code
|
||||||
- Implement shell interaction (the valid cmd lines should start with '>' or '$', user can add more lines like this to expand the command size maybe?, if we have a case where we have a line with '>' but the last line doesn't have (just a space) then it should execute?)
|
- Implement shell interaction (the valid cmd lines should start with '>' or '$', user can add more lines like this to expand the command size maybe?, if we have a case where we have a line with '>' but the last line doesn't have (just a space) then it should execute?)
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ API bool VDecommit(void *p, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#elif OS_LINUX || OS_MAC
|
#elif OS_LINUX || OS_MAC
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
|
||||||
API void *VReserve(size_t size) {
|
API void *VReserve(size_t size) {
|
||||||
void *result = mmap(0, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, (off_t)0);
|
void *result = mmap(0, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, (off_t)0);
|
||||||
|
|||||||
@@ -37,8 +37,6 @@ For(arr.reverse_iter()) {
|
|||||||
#define ForItem(it, array) for (auto &it : (array))
|
#define ForItem(it, array) for (auto &it : (array))
|
||||||
#define For(array) ForItem(it, array)
|
#define For(array) ForItem(it, array)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct Slice {
|
struct Slice {
|
||||||
T *data;
|
T *data;
|
||||||
|
|||||||
@@ -213,3 +213,8 @@ inline uint64_t GetRandomU64(RandomSeed *state) {
|
|||||||
x ^= x << 17;
|
x ^= x << 17;
|
||||||
return state->a = x;
|
return state->a = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define STRINGIFY_(x) x
|
||||||
|
#define STRINGIFY(x) STRINGIFY_(x)
|
||||||
|
#define CONCAT_(a, b) a ## b
|
||||||
|
#define CONCAT(a, b) CONCAT_(a, b)
|
||||||
|
|||||||
@@ -14,11 +14,58 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <spawn.h>
|
#include <spawn.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
#include <execinfo.h>
|
||||||
|
#include <backtrace.h>
|
||||||
|
|
||||||
API void (*Error)(const char *, ...);
|
API void (*Error)(const char *, ...);
|
||||||
|
|
||||||
|
struct backtrace_state *backtrace_state = NULL;
|
||||||
|
|
||||||
|
void BacktraceOnError(void *data, const char *msg, int errnum) {
|
||||||
|
Error("libbacktrace error: %s (errnum: %d)\n", msg, errnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
int BacktraceOnPrint(void *data, uintptr_t pc, const char *filename, int lineno, const char *function) {
|
||||||
|
bool printed = false;
|
||||||
|
if (filename != NULL) {
|
||||||
|
char buffer[512];
|
||||||
|
char *f = realpath(filename, buffer);
|
||||||
|
printf("%s:%d:1: ", f, lineno);
|
||||||
|
printed = true;
|
||||||
|
}
|
||||||
|
if (function != NULL) {
|
||||||
|
printf("%s", function);
|
||||||
|
printed = true;
|
||||||
|
}
|
||||||
|
if (printed) {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CrashHandler(int signal, siginfo_t* info, void* context) {
|
||||||
|
backtrace_full(backtrace_state, 2, BacktraceOnPrint, BacktraceOnError, NULL);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterCrashHandler(void) {
|
||||||
|
backtrace_state = backtrace_create_state(NULL, 1, BacktraceOnError, NULL);
|
||||||
|
|
||||||
|
struct sigaction sa;
|
||||||
|
sa.sa_sigaction = CrashHandler;
|
||||||
|
sigemptyset(&sa.sa_mask);
|
||||||
|
sa.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||||
|
|
||||||
|
sigaction(SIGSEGV, &sa, NULL);
|
||||||
|
sigaction(SIGABRT, &sa, NULL);
|
||||||
|
sigaction(SIGBUS, &sa, NULL);
|
||||||
|
sigaction(SIGILL, &sa, NULL);
|
||||||
|
sigaction(SIGFPE, &sa, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
API void InitOS(void (*error_proc)(const char *, ...)) {
|
API void InitOS(void (*error_proc)(const char *, ...)) {
|
||||||
Error = error_proc;
|
Error = error_proc;
|
||||||
|
RegisterCrashHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
API String ReadFile(Allocator al, String path) {
|
API String ReadFile(Allocator al, String path) {
|
||||||
@@ -171,9 +218,9 @@ API void Advance(FileIter *it) {
|
|||||||
|
|
||||||
const char *dir_char_ending = it->is_directory ? "/" : "";
|
const char *dir_char_ending = it->is_directory ? "/" : "";
|
||||||
const char *separator = it->path.data[it->path.len - 1] == '/' ? "" : "/";
|
const char *separator = it->path.data[it->path.len - 1] == '/' ? "" : "/";
|
||||||
it->relative_path = Format(it->allocator, "%.*s%s%s%s", FmtString(it->path), separator, file->d_name, dir_char_ending);
|
it->relative_path = Format(it->allocator, "%S%s%s%s", it->path, separator, file->d_name, dir_char_ending);
|
||||||
it->absolute_path = GetAbsolutePath(it->allocator, it->relative_path);
|
it->absolute_path = GetAbsolutePath(it->allocator, it->relative_path);
|
||||||
if (it->is_directory) it->absolute_path = Format(it->allocator, "%.*s/", FmtString(it->absolute_path));
|
if (it->is_directory) it->absolute_path = Format(it->allocator, "%S/", it->absolute_path);
|
||||||
it->is_valid = true;
|
it->is_valid = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,6 +93,16 @@ API Int GetBack(Caret caret) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
API Int GetMax(Caret caret) {
|
||||||
|
Int result = Max(caret.pos[0], caret.pos[1]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
API Int GetMin(Caret caret) {
|
||||||
|
Int result = Min(caret.pos[0], caret.pos[1]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
API Caret MakeCaret(Int pos) {
|
API Caret MakeCaret(Int pos) {
|
||||||
Caret result = {};
|
Caret result = {};
|
||||||
result.range.min = result.range.max = pos;
|
result.range.min = result.range.max = pos;
|
||||||
@@ -1400,7 +1410,7 @@ void RunBufferTest() {
|
|||||||
DeinitBuffer(&buffer);
|
DeinitBuffer(&buffer);
|
||||||
TrackingAllocatorCheck();
|
TrackingAllocatorCheck();
|
||||||
}
|
}
|
||||||
}
|
} RegisterFunction(&TestFunctions, RunBufferTest);
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
// Management
|
// Management
|
||||||
@@ -1467,13 +1477,11 @@ void InitBuffers() {
|
|||||||
Buffer *null_buffer = CreateBuffer(sys_allocator, GetUniqueBufferName(GetWorkingDir(scratch), "console"));
|
Buffer *null_buffer = CreateBuffer(sys_allocator, GetUniqueBufferName(GetWorkingDir(scratch), "console"));
|
||||||
View *null_view = CreateView(null_buffer->id);
|
View *null_view = CreateView(null_buffer->id);
|
||||||
Assert(null_buffer->id == NullBufferID && null_view->id == NullViewID);
|
Assert(null_buffer->id == NullBufferID && null_view->id == NullViewID);
|
||||||
|
|
||||||
TraceBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "trace"));
|
TraceBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "trace"));
|
||||||
TraceView = CreateView(TraceBuffer->id);
|
TraceView = CreateView(TraceBuffer->id);
|
||||||
GCInfoBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "gc"));
|
GCInfoBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "gc"));
|
||||||
EventBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "events"));
|
EventBuffer = CreateBuffer(sys_allocator, GetUniqueBufferName(WorkDir, "events"));
|
||||||
ScratchBuffer = BufferOpenFile(GetUniqueBufferName(WorkDir, "scratch"));
|
ScratchBuffer = BufferOpenFile(GetUniqueBufferName(WorkDir, "scratch"));
|
||||||
|
|
||||||
EventBuffer->no_history = true;
|
EventBuffer->no_history = true;
|
||||||
GCInfoBuffer->no_history = true;
|
GCInfoBuffer->no_history = true;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -46,29 +46,6 @@ void UpdateScroll(Window *window, bool update_caret_scrolling) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FuzzySearchOpen(BSet active) {
|
|
||||||
bool success = false;
|
|
||||||
Range range = active.view->carets[0].range;
|
|
||||||
if (GetSize(range) == 0) {
|
|
||||||
Int line = PosToLine(active.buffer, range.min);
|
|
||||||
if ((active.buffer->line_starts.len - 1) == line) {
|
|
||||||
line = ClampBottom(0ll, line - 1ll);
|
|
||||||
}
|
|
||||||
|
|
||||||
String16 string = GetLineStringWithoutNL(active.buffer, line);
|
|
||||||
Int idx = 0;
|
|
||||||
if (Seek(string, u"||", &idx)) {
|
|
||||||
string = Skip(string, idx + 3);
|
|
||||||
Open(string);
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
Open(FetchLoadWord());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnCommand(Event event) {
|
void OnCommand(Event event) {
|
||||||
ProfileFunction();
|
ProfileFunction();
|
||||||
//
|
//
|
||||||
@@ -125,8 +102,6 @@ void OnCommand(Event event) {
|
|||||||
} else if (IsDocumentSelectionValid()) {
|
} else if (IsDocumentSelectionValid()) {
|
||||||
Assert(ScrollbarSelected.id == -1);
|
Assert(ScrollbarSelected.id == -1);
|
||||||
BSet selected = GetBSet(DocumentSelected);
|
BSet selected = GetBSet(DocumentSelected);
|
||||||
|
|
||||||
|
|
||||||
Vec2I mouse = MouseVec2I();
|
Vec2I mouse = MouseVec2I();
|
||||||
// Special case for full-screen where we can have document
|
// Special case for full-screen where we can have document
|
||||||
// aligned with monitor screen in which case mouse cursor cannot
|
// aligned with monitor screen in which case mouse cursor cannot
|
||||||
@@ -134,6 +109,8 @@ void OnCommand(Event event) {
|
|||||||
if (mouse.y == 0 && selected.window->document_rect.min.y == 0) {
|
if (mouse.y == 0 && selected.window->document_rect.min.y == 0) {
|
||||||
float x, y;
|
float x, y;
|
||||||
SDL_GetGlobalMouseState(&x, &y);
|
SDL_GetGlobalMouseState(&x, &y);
|
||||||
|
x = roundf(DPIScale * x);
|
||||||
|
y = roundf(DPIScale * y);
|
||||||
if (y == 0) {
|
if (y == 0) {
|
||||||
mouse.y = -10;
|
mouse.y = -10;
|
||||||
}
|
}
|
||||||
@@ -179,21 +156,12 @@ void OnCommand(Event event) {
|
|||||||
}
|
}
|
||||||
bool mouse_in_document = AreOverlapping(mouse, it->document_rect);
|
bool mouse_in_document = AreOverlapping(mouse, it->document_rect);
|
||||||
if (mouse_in_document) {
|
if (mouse_in_document) {
|
||||||
NextActiveWindowID = it->id;
|
ActiveWindowID = it->id;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Mouse(X2)) {
|
|
||||||
BSet main = GetBSet(LastActiveLayoutWindowID);
|
|
||||||
GotoForward(main.window);
|
|
||||||
}
|
|
||||||
if (Mouse(X1)) {
|
|
||||||
BSet main = GetBSet(LastActiveLayoutWindowID);
|
|
||||||
GotoBackward(main.window);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Ctrl() && Shift() && Mouse(RIGHT)) {
|
if (Ctrl() && Shift() && Mouse(RIGHT)) {
|
||||||
|
|
||||||
} else if (Alt() && Ctrl() && Mouse(RIGHT)) {
|
} else if (Alt() && Ctrl() && Mouse(RIGHT)) {
|
||||||
@@ -237,7 +205,7 @@ void OnCommand(Event event) {
|
|||||||
Assert(ScrollbarSelected.id == -1);
|
Assert(ScrollbarSelected.id == -1);
|
||||||
Assert(DocumentSelected.id == -1);
|
Assert(DocumentSelected.id == -1);
|
||||||
|
|
||||||
BSet active = GetBSet(NextActiveWindowID); // using next to make sure mouse works on first click after switching the window
|
BSet active = GetBSet(ActiveWindowID); // using next to make sure mouse works on first click after switching the window
|
||||||
bool mouse_in_document = AreOverlapping(mouse, active.window->document_rect);
|
bool mouse_in_document = AreOverlapping(mouse, active.window->document_rect);
|
||||||
bool mouse_in_line_numbers = AreOverlapping(mouse, active.window->line_numbers_rect);
|
bool mouse_in_line_numbers = AreOverlapping(mouse, active.window->line_numbers_rect);
|
||||||
if (mouse_in_document || mouse_in_line_numbers) {
|
if (mouse_in_document || mouse_in_line_numbers) {
|
||||||
@@ -298,338 +266,54 @@ void OnCommand(Event event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CtrlPress(SDLK_W)) {
|
|
||||||
Command_KillWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlAltPress(SDLK_P)) {
|
|
||||||
} else if (CtrlShiftPress(SDLK_P)) {
|
|
||||||
Command_ShowCommandList();
|
|
||||||
} else if (CtrlPress(SDLK_P)) {
|
|
||||||
Command_ShowBufferList();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlPress(SDLK_0)) {
|
|
||||||
Command_ToggleDebug();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlPress(SDLK_1)) {
|
|
||||||
NextActiveWindowID = GetOverlappingWindow({0,0}, GetWindow(ActiveWindowID))->id;
|
|
||||||
}
|
|
||||||
if (CtrlPress(SDLK_2)) {
|
|
||||||
Window *first = GetOverlappingWindow({0,0}, GetWindow(ActiveWindowID));
|
|
||||||
Vec2I p = GetSideOfWindow(first, DIR_RIGHT);
|
|
||||||
NextActiveWindowID = GetOverlappingWindow(p, GetWindow(ActiveWindowID))->id;
|
|
||||||
}
|
|
||||||
if (CtrlPress(SDLK_3)) {
|
|
||||||
Window *first = GetOverlappingWindow({0,0});
|
|
||||||
if (first) {
|
|
||||||
Window *second = GetOverlappingWindow(GetSideOfWindow(first, DIR_RIGHT));
|
|
||||||
if (second) {
|
|
||||||
Window *third = GetOverlappingWindow(GetSideOfWindow(second, DIR_RIGHT));
|
|
||||||
if (third) {
|
|
||||||
NextActiveWindowID = third->id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BSet main = GetBSet(LastActiveLayoutWindowID);
|
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||||
BSet active = GetBSet(ActiveWindowID);
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
|
|
||||||
|
// @todo: somehow detect in post command that buffer changed but random buffer can get changed??? Not sure
|
||||||
|
// maybe we
|
||||||
Int buffer_change_id = active.buffer->change_id;
|
Int buffer_change_id = active.buffer->change_id;
|
||||||
|
String event_text = event.text;
|
||||||
|
|
||||||
bool skip = CallOnCommand(&event);
|
SkipRemainingCommands = false;
|
||||||
if (skip) {
|
For (CommandFunctions) {
|
||||||
// :OnCommandEnding
|
if (it.trigger && MatchEvent(it.trigger, &event)) {
|
||||||
MergeCarets(active.buffer, &active.view->carets);
|
it.function();
|
||||||
IF_DEBUG(AssertRanges(active.view->carets));
|
if (SkipRemainingCommands) {
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (active.view->fuzzy_search) {
|
|
||||||
if (Press(SDLK_RETURN)) {
|
|
||||||
FuzzySearchOpen(active);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.kind == EVENT_DROP_FILE) {
|
if (event.kind == EVENT_DROP_FILE) {
|
||||||
WindowOpenBufferView(active.window, event.text);
|
SkipRemainingCommands = false;
|
||||||
|
For (OnDropFileHooks) {
|
||||||
|
it.function(&event_text);
|
||||||
|
if (SkipRemainingCommands) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Press(SDLK_DOWN) || Press(SDLK_RIGHT) || Press(SDLK_LEFT) || Press(SDLK_UP)) {
|
|
||||||
CheckpointBeforeGoto(active.window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CtrlAltPress(SDLK_DOWN)) {
|
|
||||||
DuplicateLine(active.view, DIR_DOWN);
|
|
||||||
} else if (AltShiftPress(SDLK_DOWN)) {
|
|
||||||
CreateCursorVertical(active.view, DIR_DOWN);
|
|
||||||
} else if (CtrlShiftPress(SDLK_DOWN)) {
|
|
||||||
MoveCarets(active.view, DIR_DOWN, CTRL_PRESSED, SHIFT_PRESS);
|
|
||||||
} else if (AltPress(SDLK_DOWN)) {
|
|
||||||
MoveCaretsLine(active.view, DIR_DOWN);
|
|
||||||
} else if (CtrlPress(SDLK_DOWN)) {
|
|
||||||
MoveCarets(active.view, DIR_DOWN, CTRL_PRESSED);
|
|
||||||
} else if (ShiftPress(SDLK_DOWN)) {
|
|
||||||
MoveCarets(active.view, DIR_DOWN, false, SHIFT_PRESS);
|
|
||||||
} else if (Press(SDLK_DOWN)) {
|
|
||||||
MoveCarets(active.view, DIR_DOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlAltPress(SDLK_UP)) {
|
|
||||||
DuplicateLine(active.view, DIR_UP);
|
|
||||||
} else if (AltShiftPress(SDLK_UP)) {
|
|
||||||
CreateCursorVertical(active.view, DIR_UP);
|
|
||||||
} else if (CtrlShiftPress(SDLK_UP)) {
|
|
||||||
MoveCarets(active.view, DIR_UP, CTRL_PRESSED, SHIFT_PRESS);
|
|
||||||
} else if (AltPress(SDLK_UP)) {
|
|
||||||
MoveCaretsLine(active.view, DIR_UP);
|
|
||||||
} else if (CtrlPress(SDLK_UP)) {
|
|
||||||
MoveCarets(active.view, DIR_UP, CTRL_PRESSED);
|
|
||||||
} else if (ShiftPress(SDLK_UP)) {
|
|
||||||
MoveCarets(active.view, DIR_UP, false, SHIFT_PRESS);
|
|
||||||
} else if (Press(SDLK_UP)) {
|
|
||||||
MoveCarets(active.view, DIR_UP);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlShiftPress(SDLK_LEFT)) {
|
|
||||||
MoveCarets(active.view, DIR_LEFT, CTRL_PRESSED, SHIFT_PRESS);
|
|
||||||
} else if (CtrlPress(SDLK_LEFT)) {
|
|
||||||
MoveCarets(active.view, DIR_LEFT, CTRL_PRESSED);
|
|
||||||
} else if (ShiftPress(SDLK_LEFT)) {
|
|
||||||
MoveCarets(active.view, DIR_LEFT, false, SHIFT_PRESS);
|
|
||||||
} else if (AltPress(SDLK_LEFT)) {
|
|
||||||
NextActiveWindowID = SwitchWindow(DIR_LEFT)->id;
|
|
||||||
} else if (Press(SDLK_LEFT)) {
|
|
||||||
MoveCarets(active.view, DIR_LEFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlShiftPress(SDLK_RIGHT)) {
|
|
||||||
MoveCarets(active.view, DIR_RIGHT, CTRL_PRESSED, SHIFT_PRESS);
|
|
||||||
} else if (CtrlPress(SDLK_RIGHT)) {
|
|
||||||
MoveCarets(active.view, DIR_RIGHT, CTRL_PRESSED);
|
|
||||||
} else if (ShiftPress(SDLK_RIGHT)) {
|
|
||||||
MoveCarets(active.view, DIR_RIGHT, false, SHIFT_PRESS);
|
|
||||||
} else if (AltPress(SDLK_RIGHT)) {
|
|
||||||
NextActiveWindowID = SwitchWindow(DIR_RIGHT)->id;
|
|
||||||
} else if (Press(SDLK_RIGHT)) {
|
|
||||||
MoveCarets(active.view, DIR_RIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlShiftPress(SDLK_Z)) {
|
|
||||||
RedoEdit(active.buffer, &active.view->carets);
|
|
||||||
} else if (CtrlPress(SDLK_Z)) {
|
|
||||||
UndoEdit(active.buffer, &active.view->carets);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlPress(SDLK_C)) {
|
|
||||||
ClipboardCopy(active.view);
|
|
||||||
} else if (CtrlPress(SDLK_V)) {
|
|
||||||
ClipboardPaste(active.view);
|
|
||||||
} else if (CtrlPress(SDLK_X)) {
|
|
||||||
SaveCaretHistoryBeforeBeginEdit(active.buffer, active.view->carets);
|
|
||||||
ClipboardCopy(active.view);
|
|
||||||
Replace(active.view, u"");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlPress(SDLK_A)) {
|
|
||||||
SelectEntireBuffer(active.view);
|
|
||||||
active.view->update_scroll = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ShiftPress(SDLK_PAGEUP)) {
|
|
||||||
CheckpointBeforeGoto(active.window);
|
|
||||||
MoveCursorByPageSize(active.window, DIR_UP, SHIFT_PRESS);
|
|
||||||
} else if (CtrlPress(SDLK_PAGEUP)) {
|
|
||||||
CheckpointBeforeGoto(active.window);
|
|
||||||
SelectRange(active.view, MakeRange(0));
|
|
||||||
} else if (Press(SDLK_PAGEUP)) {
|
|
||||||
CheckpointBeforeGoto(active.window);
|
|
||||||
MoveCursorByPageSize(active.window, DIR_UP);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ShiftPress(SDLK_PAGEDOWN)) {
|
|
||||||
CheckpointBeforeGoto(active.window);
|
|
||||||
MoveCursorByPageSize(active.window, DIR_DOWN, SHIFT_PRESS);
|
|
||||||
} else if (CtrlPress(SDLK_PAGEDOWN)) {
|
|
||||||
CheckpointBeforeGoto(active.window);
|
|
||||||
SelectRange(active.view, MakeRange(active.buffer->len));
|
|
||||||
} else if (Press(SDLK_PAGEDOWN)) {
|
|
||||||
CheckpointBeforeGoto(active.window);
|
|
||||||
MoveCursorByPageSize(active.window, DIR_DOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ShiftPress(SDLK_HOME)) {
|
|
||||||
CheckpointBeforeGoto(active.window);
|
|
||||||
MoveCursorToSide(active.view, DIR_LEFT, SHIFT_PRESS);
|
|
||||||
} else if (Press(SDLK_HOME)) {
|
|
||||||
CheckpointBeforeGoto(active.window);
|
|
||||||
MoveCursorToSide(active.view, DIR_LEFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ShiftPress(SDLK_END)) {
|
|
||||||
CheckpointBeforeGoto(active.window);
|
|
||||||
MoveCursorToSide(active.view, DIR_RIGHT, SHIFT_PRESS);
|
|
||||||
} else if (Press(SDLK_END)) {
|
|
||||||
CheckpointBeforeGoto(active.window);
|
|
||||||
MoveCursorToSide(active.view, DIR_RIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlShiftPress(SDLK_TAB)) {
|
|
||||||
} else if (ShiftPress(SDLK_TAB)) {
|
|
||||||
IndentSelectedLines(active.view, SHIFT_PRESS);
|
|
||||||
} else if (CtrlPress(SDLK_TAB)) {
|
|
||||||
} else if (Press(SDLK_TAB)) {
|
|
||||||
IndentSelectedLines(active.view);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlPress(SDLK_LEFTBRACKET)) {
|
|
||||||
IndentSelectedLines(active.view, SHIFT_PRESS);
|
|
||||||
}
|
|
||||||
if (CtrlPress(SDLK_RIGHTBRACKET)) {
|
|
||||||
IndentSelectedLines(active.view);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlShiftPress(SDLK_K)) {
|
|
||||||
KillSelectedLines(active.view);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlPress(SDLK_BACKSPACE)) {
|
|
||||||
Delete(active.view, DIR_LEFT, CTRL_PRESSED);
|
|
||||||
} else if (Press(SDLK_BACKSPACE)) {
|
|
||||||
Delete(active.view, DIR_LEFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlPress(SDLK_DELETE)) {
|
|
||||||
Delete(active.view, DIR_RIGHT, CTRL_PRESSED);
|
|
||||||
} else if (Press(SDLK_DELETE)) {
|
|
||||||
Delete(active.view, DIR_RIGHT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.kind == EVENT_TEXT_INPUT) {
|
if (event.kind == EVENT_TEXT_INPUT) {
|
||||||
Scratch scratch;
|
SkipRemainingCommands = false;
|
||||||
String string = event.text;
|
For (OnTextInputHooks) {
|
||||||
String16 string16 = ToString16(scratch, string);
|
it.function(&event_text);
|
||||||
Replace(active.view, string16);
|
if (SkipRemainingCommands) {
|
||||||
}
|
break;
|
||||||
|
|
||||||
if (CtrlPress(SDLK_D)) {
|
|
||||||
CheckpointBeforeGoto(active.window);
|
|
||||||
String16 string = GetString(active.buffer, active.view->carets[0].range);
|
|
||||||
Caret caret = FindNext(active.buffer, string, active.view->carets[0]);
|
|
||||||
Insert(&active.view->carets, caret, 0);
|
|
||||||
MergeCarets(active.buffer, &active.view->carets);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlPress(SDLK_EQUALS)) {
|
|
||||||
StyleFontSize += 1;
|
|
||||||
ReloadFont(StyleFont, (U32)StyleFontSize);
|
|
||||||
}
|
|
||||||
if (CtrlPress(SDLK_MINUS)) {
|
|
||||||
if (StyleFontSize > 4) {
|
|
||||||
StyleFontSize -= 1;
|
|
||||||
ReloadFont(StyleFont, (U32)StyleFontSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlPress(SDLK_E)) {
|
|
||||||
} else if (AltPress(SDLK_E)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlShiftPress(SDLK_RETURN)) {
|
|
||||||
MoveCursorToSide(active.view, DIR_LEFT);
|
|
||||||
IdentedNewLine(active.view);
|
|
||||||
MoveCarets(active.view, DIR_UP);
|
|
||||||
} else if (CtrlPress(SDLK_RETURN)) {
|
|
||||||
MoveCursorToSide(active.view, DIR_RIGHT);
|
|
||||||
IdentedNewLine(active.view);
|
|
||||||
} else if (Press(SDLK_RETURN)) {
|
|
||||||
IdentedNewLine(active.view);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (active.view->fuzzy_search) {
|
|
||||||
if (!ProcessIsActive(active.view->id)) {
|
|
||||||
Scratch scratch;
|
|
||||||
String16 last_line_string = GetLineStringWithoutNL(active.buffer, active.buffer->line_starts.len - 1);
|
|
||||||
if (active.view->prev_search_line != last_line_string) {
|
|
||||||
active.view->prev_search_line = last_line_string;
|
|
||||||
Array<FuzzyPair> ratings = FuzzySearchLines(scratch, active.buffer, 0, active.buffer->line_starts.len - 1, last_line_string);
|
|
||||||
|
|
||||||
Buffer *temp_buffer = CreateTempBuffer(scratch, active.buffer->cap);
|
|
||||||
For(IterateInReverse(&ratings)) {
|
|
||||||
String16 s = GetLineStringWithoutNL(active.buffer, it.index);
|
|
||||||
if (s.len == 0) continue;
|
|
||||||
RawReplaceText(temp_buffer, GetBufferEndAsRange(temp_buffer), s);
|
|
||||||
RawReplaceText(temp_buffer, GetBufferEndAsRange(temp_buffer), u"\n");
|
|
||||||
}
|
|
||||||
RawReplaceText(temp_buffer, GetBufferEndAsRange(temp_buffer), last_line_string);
|
|
||||||
|
|
||||||
Caret caret = active.view->carets[0];
|
|
||||||
SaveCaretHistoryBeforeBeginEdit(active.buffer, active.view->carets);
|
|
||||||
SelectEntireBuffer(active.view);
|
|
||||||
Replace(active.view, GetString(temp_buffer));
|
|
||||||
active.view->carets[0] = caret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CtrlPress(SDLK_F)) {
|
|
||||||
Window *window = GetWindow(SearchBarWindowID);
|
|
||||||
window->visible = !window->visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlPress(SDLK_S)) {
|
|
||||||
SaveBuffer(active.buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlPress(SDLK_PERIOD)) {
|
|
||||||
String name = ChopLastSlash(main.buffer->name);
|
|
||||||
if (EndsWith(main.buffer->name, "dirlisting")) {
|
|
||||||
name = ChopLastSlash(name);
|
|
||||||
}
|
|
||||||
Open(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlShiftPress(SDLK_L)) {
|
|
||||||
EncloseSpace(active.view);
|
|
||||||
} else if (CtrlPress(SDLK_L)) {
|
|
||||||
EncloseLine(active.view);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CtrlShiftPress(SDLK_G)) {
|
|
||||||
} else if (CtrlPress(SDLK_G)) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AltPress(SDLK_Q)) {
|
|
||||||
GotoBackward(main.window);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (CtrlPress(SDLK_Q)) {
|
|
||||||
if (active.view->fuzzy_search) {
|
|
||||||
FuzzySearchOpen(active);
|
|
||||||
} else {
|
|
||||||
Open(FetchLoadWord());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Press(SDLK_ESCAPE)) {
|
|
||||||
active.view->carets.len = 1;
|
|
||||||
active.view->carets[0] = MakeCaret(GetFront(active.view->carets[0]));
|
|
||||||
|
|
||||||
if (active.window->lose_focus_on_escape && active.window->id == ActiveWindowID) {
|
|
||||||
if (active.window->layout) {
|
|
||||||
//
|
|
||||||
} else {
|
|
||||||
NextActiveWindowID = LastActiveLayoutWindowID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// :OnCommandEnding
|
|
||||||
MergeCarets(active.buffer, &active.view->carets);
|
MergeCarets(active.buffer, &active.view->carets);
|
||||||
IF_DEBUG(AssertRanges(active.view->carets));
|
IF_DEBUG(AssertRanges(active.view->carets));
|
||||||
|
MergeCarets(main.buffer, &main.view->carets);
|
||||||
|
IF_DEBUG(AssertRanges(main.view->carets));
|
||||||
|
|
||||||
|
SkipRemainingCommands = false;
|
||||||
|
For (PostCommandHooks) {
|
||||||
|
it.function(NULL);
|
||||||
|
if (SkipRemainingCommands) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,3 +86,20 @@ void ClipboardPaste(View *view) {
|
|||||||
}
|
}
|
||||||
EndEdit(buffer, &edits, &view->carets, KILL_SELECTION);
|
EndEdit(buffer, &edits, &view->carets, KILL_SELECTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Command_Paste() {
|
||||||
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
|
ClipboardPaste(active.view);
|
||||||
|
} RegisterCommand(Command_Paste, "ctrl-v");
|
||||||
|
|
||||||
|
void Command_Copy() {
|
||||||
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
|
ClipboardCopy(active.view);
|
||||||
|
} RegisterCommand(Command_Copy, "ctrl-c");
|
||||||
|
|
||||||
|
void Command_Cut() {
|
||||||
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
|
SaveCaretHistoryBeforeBeginEdit(active.buffer, active.view->carets);
|
||||||
|
ClipboardCopy(active.view);
|
||||||
|
Replace(active.view, u"");
|
||||||
|
} RegisterCommand(Command_Cut, "ctrl-x");
|
||||||
@@ -260,6 +260,91 @@ const char *SDLKeycodeToName(SDL_Keycode keycode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct { String string; EventKind value; } MouseConversionTable[] = {
|
||||||
|
{"mousex1", EVENT_MOUSE_X1},
|
||||||
|
{"mousex2", EVENT_MOUSE_X2},
|
||||||
|
{"mouseleft", EVENT_MOUSE_LEFT},
|
||||||
|
{"mouseright", EVENT_MOUSE_RIGHT},
|
||||||
|
{"mousemiddle", EVENT_MOUSE_MIDDLE},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct { String string; SDL_Keycode value; } SDLKeycodeConversionTable[] = {
|
||||||
|
{"enter", SDLK_RETURN},
|
||||||
|
{"escape", SDLK_ESCAPE},
|
||||||
|
{"backspace", SDLK_BACKSPACE},
|
||||||
|
{"tab", SDLK_TAB},
|
||||||
|
{"space", SDLK_SPACE},
|
||||||
|
{"minus", SDLK_MINUS},
|
||||||
|
{"period", SDLK_PERIOD},
|
||||||
|
{"slash", SDLK_SLASH},
|
||||||
|
{"0", SDLK_0},
|
||||||
|
{"1", SDLK_1},
|
||||||
|
{"2", SDLK_2},
|
||||||
|
{"3", SDLK_3},
|
||||||
|
{"4", SDLK_4},
|
||||||
|
{"5", SDLK_5},
|
||||||
|
{"6", SDLK_6},
|
||||||
|
{"7", SDLK_7},
|
||||||
|
{"8", SDLK_8},
|
||||||
|
{"9", SDLK_9},
|
||||||
|
{"semicolon", SDLK_SEMICOLON},
|
||||||
|
{"less", SDLK_LESS},
|
||||||
|
{"equals", SDLK_EQUALS},
|
||||||
|
{"greater", SDLK_GREATER},
|
||||||
|
{"leftbracket", SDLK_LEFTBRACKET},
|
||||||
|
{"backslash", SDLK_BACKSLASH},
|
||||||
|
{"rightbracket", SDLK_RIGHTBRACKET},
|
||||||
|
{"grave", SDLK_GRAVE},
|
||||||
|
{"a", SDLK_A},
|
||||||
|
{"b", SDLK_B},
|
||||||
|
{"c", SDLK_C},
|
||||||
|
{"d", SDLK_D},
|
||||||
|
{"e", SDLK_E},
|
||||||
|
{"f", SDLK_F},
|
||||||
|
{"g", SDLK_G},
|
||||||
|
{"h", SDLK_H},
|
||||||
|
{"i", SDLK_I},
|
||||||
|
{"j", SDLK_J},
|
||||||
|
{"k", SDLK_K},
|
||||||
|
{"l", SDLK_L},
|
||||||
|
{"m", SDLK_M},
|
||||||
|
{"n", SDLK_N},
|
||||||
|
{"o", SDLK_O},
|
||||||
|
{"p", SDLK_P},
|
||||||
|
{"q", SDLK_Q},
|
||||||
|
{"r", SDLK_R},
|
||||||
|
{"s", SDLK_S},
|
||||||
|
{"t", SDLK_T},
|
||||||
|
{"u", SDLK_U},
|
||||||
|
{"v", SDLK_V},
|
||||||
|
{"w", SDLK_W},
|
||||||
|
{"x", SDLK_X},
|
||||||
|
{"y", SDLK_Y},
|
||||||
|
{"z", SDLK_Z},
|
||||||
|
{"delete", SDLK_DELETE},
|
||||||
|
{"capslock", SDLK_CAPSLOCK},
|
||||||
|
{"f1", SDLK_F1},
|
||||||
|
{"f2", SDLK_F2},
|
||||||
|
{"f3", SDLK_F3},
|
||||||
|
{"f4", SDLK_F4},
|
||||||
|
{"f5", SDLK_F5},
|
||||||
|
{"f6", SDLK_F6},
|
||||||
|
{"f7", SDLK_F7},
|
||||||
|
{"f8", SDLK_F8},
|
||||||
|
{"f9", SDLK_F9},
|
||||||
|
{"f10", SDLK_F10},
|
||||||
|
{"f11", SDLK_F11},
|
||||||
|
{"f12", SDLK_F12},
|
||||||
|
{"insert", SDLK_INSERT},
|
||||||
|
{"home", SDLK_HOME},
|
||||||
|
{"pageup", SDLK_PAGEUP},
|
||||||
|
{"end", SDLK_END},
|
||||||
|
{"pagedown", SDLK_PAGEDOWN},
|
||||||
|
{"right", SDLK_RIGHT},
|
||||||
|
{"left", SDLK_LEFT},
|
||||||
|
{"down", SDLK_DOWN},
|
||||||
|
{"up", SDLK_UP},
|
||||||
|
};
|
||||||
|
|
||||||
void FillEventWithBasicData(Event *event) {
|
void FillEventWithBasicData(Event *event) {
|
||||||
SDL_Keymod mod = SDL_GetModState();
|
SDL_Keymod mod = SDL_GetModState();
|
||||||
@@ -270,11 +355,11 @@ void FillEventWithBasicData(Event *event) {
|
|||||||
|
|
||||||
float xmouse, ymouse;
|
float xmouse, ymouse;
|
||||||
SDL_GetMouseState(&xmouse, &ymouse);
|
SDL_GetMouseState(&xmouse, &ymouse);
|
||||||
event->xmouse = (int16_t)xmouse;
|
event->xmouse = (int16_t)roundf(DPIScale * xmouse);
|
||||||
event->ymouse = (int16_t)ymouse;
|
event->ymouse = (int16_t)roundf(DPIScale * ymouse);
|
||||||
|
|
||||||
int xwindow, ywindow;
|
int xwindow, ywindow;
|
||||||
SDL_GetWindowSize(SDLWindow, &xwindow, &ywindow);
|
SDL_GetWindowSizeInPixels(SDLWindow, &xwindow, &ywindow);
|
||||||
event->xwindow = xwindow;
|
event->xwindow = xwindow;
|
||||||
event->ywindow = ywindow;
|
event->ywindow = ywindow;
|
||||||
event->text = "";
|
event->text = "";
|
||||||
@@ -305,8 +390,8 @@ Event TranslateSDLEvent(SDL_Event *input_event) {
|
|||||||
|
|
||||||
case SDL_EVENT_MOUSE_BUTTON_DOWN: {
|
case SDL_EVENT_MOUSE_BUTTON_DOWN: {
|
||||||
SDL_MouseButtonEvent &b = input_event->button;
|
SDL_MouseButtonEvent &b = input_event->button;
|
||||||
event.xmouse = (int16_t)b.x;
|
event.xmouse = (int16_t)roundf(DPIScale * b.x);
|
||||||
event.ymouse = (int16_t)b.y;
|
event.ymouse = (int16_t)roundf(DPIScale * b.y);
|
||||||
event.clicks = b.clicks;
|
event.clicks = b.clicks;
|
||||||
if (b.button == SDL_BUTTON_LEFT) {
|
if (b.button == SDL_BUTTON_LEFT) {
|
||||||
event.kind = EVENT_MOUSE_LEFT;
|
event.kind = EVENT_MOUSE_LEFT;
|
||||||
@@ -326,8 +411,8 @@ Event TranslateSDLEvent(SDL_Event *input_event) {
|
|||||||
|
|
||||||
case SDL_EVENT_MOUSE_BUTTON_UP: {
|
case SDL_EVENT_MOUSE_BUTTON_UP: {
|
||||||
SDL_MouseButtonEvent &b = input_event->button;
|
SDL_MouseButtonEvent &b = input_event->button;
|
||||||
event.xmouse = (int16_t)b.x;
|
event.xmouse = (int16_t)roundf(DPIScale * b.x);
|
||||||
event.ymouse = (int16_t)b.y;
|
event.ymouse = (int16_t)roundf(DPIScale * b.y);
|
||||||
if (b.button == SDL_BUTTON_LEFT) {
|
if (b.button == SDL_BUTTON_LEFT) {
|
||||||
event.kind = EVENT_MOUSE_LEFT_UP;
|
event.kind = EVENT_MOUSE_LEFT_UP;
|
||||||
} else if (b.button == SDL_BUTTON_RIGHT) {
|
} else if (b.button == SDL_BUTTON_RIGHT) {
|
||||||
@@ -346,8 +431,8 @@ Event TranslateSDLEvent(SDL_Event *input_event) {
|
|||||||
case SDL_EVENT_MOUSE_WHEEL: {
|
case SDL_EVENT_MOUSE_WHEEL: {
|
||||||
event.kind = EVENT_MOUSE_WHEEL;
|
event.kind = EVENT_MOUSE_WHEEL;
|
||||||
SDL_MouseWheelEvent &b = input_event->wheel;
|
SDL_MouseWheelEvent &b = input_event->wheel;
|
||||||
event.xmouse = (int16_t)b.mouse_x;
|
event.xmouse = (int16_t)roundf(DPIScale * b.x);
|
||||||
event.ymouse = (int16_t)b.mouse_y;
|
event.ymouse = (int16_t)roundf(DPIScale * b.y);
|
||||||
event.xwheel = b.x;
|
event.xwheel = b.x;
|
||||||
event.ywheel = b.y;
|
event.ywheel = b.y;
|
||||||
} break;
|
} break;
|
||||||
@@ -468,14 +553,6 @@ void Serialize(Serializer *s, Event *e) {
|
|||||||
SerializeEnd(s);
|
SerializeEnd(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int DIR_RIGHT = 0;
|
|
||||||
const int DIR_LEFT = 1;
|
|
||||||
const int DIR_DOWN = 2;
|
|
||||||
const int DIR_UP = 3;
|
|
||||||
const int DIR_COUNT = 4;
|
|
||||||
const bool CTRL_PRESSED = true;
|
|
||||||
const bool SHIFT_PRESS = true;
|
|
||||||
|
|
||||||
#define Ctrl() event.ctrl
|
#define Ctrl() event.ctrl
|
||||||
#define Alt() event.alt
|
#define Alt() event.alt
|
||||||
#define Shift() event.shift
|
#define Shift() event.shift
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ ViewID SearchViewID;
|
|||||||
BufferID SearchBufferID;
|
BufferID SearchBufferID;
|
||||||
|
|
||||||
WindowID ActiveWindowID;
|
WindowID ActiveWindowID;
|
||||||
WindowID NextActiveWindowID;
|
|
||||||
WindowID LastActiveLayoutWindowID;
|
WindowID LastActiveLayoutWindowID;
|
||||||
WindowID ScrollbarSelected = {-1};
|
WindowID ScrollbarSelected = {-1};
|
||||||
WindowID DocumentSelected = {-1};
|
WindowID DocumentSelected = {-1};
|
||||||
@@ -50,11 +49,9 @@ View *TraceView;
|
|||||||
String WorkDir;
|
String WorkDir;
|
||||||
RandomSeed UniqueBufferNameSeed = {};
|
RandomSeed UniqueBufferNameSeed = {};
|
||||||
Array<Event> EventPlayback;
|
Array<Event> EventPlayback;
|
||||||
|
|
||||||
// lua
|
|
||||||
lua_State *LuaState = NULL;
|
lua_State *LuaState = NULL;
|
||||||
String16 LuaCommandResult = {};
|
BlockArena Perm;
|
||||||
extern luaL_Reg LuaFunctions[];
|
Event *OnCommandEvent;
|
||||||
|
|
||||||
// clipboard
|
// clipboard
|
||||||
BlockArena ClipboardArena;
|
BlockArena ClipboardArena;
|
||||||
@@ -185,3 +182,48 @@ void ReloadStyle() {
|
|||||||
StyleVCVarsall = GetStyleString("VCVarsall", StyleVCVarsall);
|
StyleVCVarsall = GetStyleString("VCVarsall", StyleVCVarsall);
|
||||||
StyleUndoMergeTimeout = GetStyleFloat("UndoMergeTimeout", StyleUndoMergeTimeout);
|
StyleUndoMergeTimeout = GetStyleFloat("UndoMergeTimeout", StyleUndoMergeTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef void Function();
|
||||||
|
typedef void PFunction(void *param);
|
||||||
|
typedef int LuaFunction(lua_State *state);
|
||||||
|
struct FunctionData { String name; Function *function; };
|
||||||
|
struct LuaFunctionData { String name; LuaFunction *function; };
|
||||||
|
struct CommandData { String name; String binding; Function *function; struct Trigger *trigger; };
|
||||||
|
struct PFunctionData { String name; PFunction *function; };
|
||||||
|
|
||||||
|
bool SkipRemainingCommands;
|
||||||
|
Array<CommandData> CommandFunctions;
|
||||||
|
Array<LuaFunctionData> LuaFunctions;
|
||||||
|
Array<FunctionData> TestFunctions;
|
||||||
|
|
||||||
|
Array<PFunctionData> PostCommandHooks;
|
||||||
|
Array<PFunctionData> OnTextInputHooks;
|
||||||
|
Array<PFunctionData> OnDropFileHooks;
|
||||||
|
|
||||||
|
struct Register_Function {
|
||||||
|
Register_Function(Array<FunctionData> *functions, String name, Function *f) {
|
||||||
|
int64_t pos = 0;
|
||||||
|
if (Seek(name, "_", &pos, 0)) {
|
||||||
|
name = Skip(name, pos + 1);
|
||||||
|
}
|
||||||
|
Add(functions, {name, f});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#define RegisterFunction(functions, name) Register_Function RF__##name(functions, #name, name)
|
||||||
|
|
||||||
|
struct Register_Lua { Register_Lua(LuaFunction *function, String name) { if (StartsWith(name, "Lua_")) name = Skip(name, 4); Add(&LuaFunctions, {name, function}); } };
|
||||||
|
#define RegisterLua(NAME) Register_Lua RL_##NAME(NAME, #NAME)
|
||||||
|
|
||||||
|
struct Register_Command { Register_Command(Function *function, String name, String binding) { if (StartsWith(name, "Command_")) name = Skip(name, 8); Add(&CommandFunctions, {name, binding, function}); } };
|
||||||
|
#define RegisterCommand(name, binding) Register_Command RC__##name(name, #name, binding)
|
||||||
|
|
||||||
|
struct Register_Hook { Register_Hook(Array<PFunctionData> *functions, PFunction *function, String name) { if (StartsWith(name, "Hook_")) name = Skip(name, 5); Add(functions, {name, function}); } };
|
||||||
|
#define RegisterHook(functions, name) Register_Hook RC__##name(functions, (PFunction *)name, #name)
|
||||||
|
|
||||||
|
const int DIR_RIGHT = 0;
|
||||||
|
const int DIR_LEFT = 1;
|
||||||
|
const int DIR_DOWN = 2;
|
||||||
|
const int DIR_UP = 3;
|
||||||
|
const int DIR_COUNT = 4;
|
||||||
|
const bool CTRL_PRESSED = true;
|
||||||
|
const bool SHIFT_PRESS = true;
|
||||||
@@ -86,61 +86,6 @@ API String GetFieldString(lua_State *L, String name) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Int GetFieldAInt(lua_State *L, const char *name) {
|
|
||||||
lua_getfield(L, -1, name);
|
|
||||||
lua_Integer num = lua_tointeger(L, -1);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
return (Int)num;
|
|
||||||
}
|
|
||||||
|
|
||||||
double GetFieldAFloat(lua_State *L, const char *name) {
|
|
||||||
lua_getfield(L, -1, name);
|
|
||||||
double num = lua_tonumber(L, -1);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *GetFieldAString(lua_State *L, const char *name) {
|
|
||||||
lua_getfield(L, -1, name);
|
|
||||||
const char *result = lua_tostring(L, -1);
|
|
||||||
|
|
||||||
lua_pop(L, 1);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
API void PushEvent(lua_State *L, Event *event) {
|
|
||||||
lua_createtable(L, 0, EVENT_FIELD_COUNT);
|
|
||||||
#define lua_pushInt lua_pushinteger
|
|
||||||
#define lua_pushString lua_pushstring
|
|
||||||
#define lua_pushFloat lua_pushnumber
|
|
||||||
#define X(TYPE, KIND, NAME) \
|
|
||||||
lua_push##KIND(L, event->NAME); \
|
|
||||||
lua_setfield(L, -2, #NAME);
|
|
||||||
EVENT_FIELDS
|
|
||||||
#undef X
|
|
||||||
}
|
|
||||||
|
|
||||||
// :Event
|
|
||||||
API int Lua_Play(lua_State *L) {
|
|
||||||
if (!lua_istable(L, -1)) luaL_error(L, "expected a table of events");
|
|
||||||
defer { lua_pop(L, 1); };
|
|
||||||
|
|
||||||
int size = (int)lua_rawlen(L, -1);
|
|
||||||
for (int i = 0; i < size; i += 1) {
|
|
||||||
lua_geti(L, -1, i + 1);
|
|
||||||
if (!lua_istable(L, -1)) luaL_error(L, "expected a table of events");
|
|
||||||
defer { lua_pop(L, 1); };
|
|
||||||
|
|
||||||
Event event = {};
|
|
||||||
#define X(TYPE, KIND, NAME) event.NAME = (TYPE)GetFieldA##KIND(L, #NAME);
|
|
||||||
EVENT_FIELDS
|
|
||||||
#undef X
|
|
||||||
Add(&EventPlayback, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReloadStyle();
|
void ReloadStyle();
|
||||||
extern String BaseLuaConfig;
|
extern String BaseLuaConfig;
|
||||||
|
|
||||||
@@ -206,9 +151,9 @@ API void InitLuaConfig() {
|
|||||||
luaL_openlibs(LuaState);
|
luaL_openlibs(LuaState);
|
||||||
lua_sethook(LuaState, HookLuaForceExit, LUA_MASKCOUNT, 100000000);
|
lua_sethook(LuaState, HookLuaForceExit, LUA_MASKCOUNT, 100000000);
|
||||||
|
|
||||||
for (int i = 0; LuaFunctions[i].name; i += 1) {
|
For(LuaFunctions) {
|
||||||
lua_pushcfunction(LuaState, LuaFunctions[i].func);
|
lua_pushcfunction(LuaState, it.function);
|
||||||
lua_setglobal(LuaState, LuaFunctions[i].name);
|
lua_setglobal(LuaState, it.name.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
@@ -253,3 +198,97 @@ API void InitLuaConfig() {
|
|||||||
ReloadLuaConfigs(true);
|
ReloadLuaConfigs(true);
|
||||||
CallLuaOnInit();
|
CallLuaOnInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct OnOpenResult {
|
||||||
|
String kind;
|
||||||
|
String file_path;
|
||||||
|
Int line, col;
|
||||||
|
String working_dir;
|
||||||
|
String cmd;
|
||||||
|
};
|
||||||
|
|
||||||
|
OnOpenResult CallOnOpen(Allocator allocator, String path, String meta) {
|
||||||
|
lua_getglobal(LuaState, "OnOpen");
|
||||||
|
lua_pushlstring(LuaState, path.data, path.len);
|
||||||
|
lua_pushlstring(LuaState, meta.data, meta.len);
|
||||||
|
if (!CallLuaFunc("OnOpen", 2, 1)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
String file_path = GetFieldString(LuaState, "file_path");
|
||||||
|
String line_string = GetFieldString(LuaState, "line");
|
||||||
|
String col_string = GetFieldString(LuaState, "col");
|
||||||
|
String cmd = GetFieldString(LuaState, "cmd");
|
||||||
|
String working_dir = GetFieldString(LuaState, "working_dir");
|
||||||
|
String kind = GetFieldString(LuaState, "kind");
|
||||||
|
|
||||||
|
OnOpenResult result = {};
|
||||||
|
result.cmd = cmd;
|
||||||
|
result.working_dir = working_dir;
|
||||||
|
result.file_path = file_path;
|
||||||
|
if (!IsAbsolute(result.file_path)) {
|
||||||
|
String GetMainDir();
|
||||||
|
String dir = GetMainDir();
|
||||||
|
result.file_path = Format(allocator, "%S/%S", dir, result.file_path);
|
||||||
|
}
|
||||||
|
if (col_string.len) {
|
||||||
|
result.col = strtoll(col_string.data, NULL, 10);
|
||||||
|
} else {
|
||||||
|
result.col = -1;
|
||||||
|
}
|
||||||
|
if (line_string.len) {
|
||||||
|
result.line = strtoll(line_string.data, NULL, 10);
|
||||||
|
} else {
|
||||||
|
result.line = -1;
|
||||||
|
}
|
||||||
|
result.kind = kind;
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CallIsCode(String path, String meta = "") {
|
||||||
|
lua_getglobal(LuaState, "IsCode");
|
||||||
|
lua_pushlstring(LuaState, path.data, path.len);
|
||||||
|
lua_pushlstring(LuaState, meta.data, meta.len);
|
||||||
|
if (!CallLuaFunc("IsCode", 2, 1)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool result = lua_toboolean(LuaState, -1);
|
||||||
|
lua_pop(LuaState, 1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallOnSave(BufferID buffer_id) {
|
||||||
|
lua_getglobal(LuaState, "OnSave");
|
||||||
|
lua_pushinteger(LuaState, buffer_id.id);
|
||||||
|
CallLuaFunc("OnSave", 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PushEvent(lua_State *L, Event *event) {
|
||||||
|
lua_createtable(L, 0, EVENT_FIELD_COUNT);
|
||||||
|
#define lua_pushInt lua_pushinteger
|
||||||
|
#define lua_pushString lua_pushstring
|
||||||
|
#define lua_pushFloat lua_pushnumber
|
||||||
|
#define X(TYPE, KIND, NAME) \
|
||||||
|
lua_push##KIND(L, event->NAME); \
|
||||||
|
lua_setfield(L, -2, #NAME);
|
||||||
|
EVENT_FIELDS
|
||||||
|
#undef X
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CallOnCommand(Event *event) {
|
||||||
|
lua_getglobal(LuaState, "OnCommand");
|
||||||
|
PushEvent(LuaState, event);
|
||||||
|
CallLuaFunc("OnCommand", 1, 1);
|
||||||
|
bool result = lua_toboolean(LuaState, -1);
|
||||||
|
lua_pop(LuaState, 1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallLuaOnUpdate(Event *event) {
|
||||||
|
lua_getglobal(LuaState, "OnUpdate");
|
||||||
|
PushEvent(LuaState, event);
|
||||||
|
CallLuaFunc("OnUpdate", 1, 0);
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ API Int GetStyleInt(String name, Int default_int);
|
|||||||
API String GetStyleString(String name, String default_string);
|
API String GetStyleString(String name, String default_string);
|
||||||
API Color GetColor(String name, Color default_color);
|
API Color GetColor(String name, Color default_color);
|
||||||
API String GetFieldString(lua_State *L, String name);
|
API String GetFieldString(lua_State *L, String name);
|
||||||
API int Lua_Play(lua_State *L);
|
|
||||||
API void LoadLuaBuffer(Buffer *lua_buffer);
|
API void LoadLuaBuffer(Buffer *lua_buffer);
|
||||||
API void ReloadLuaConfigs(bool reload = false);
|
API void ReloadLuaConfigs(bool reload = false);
|
||||||
API bool CallLuaFunc(char *func_name, int arg_count, int ret_count);
|
API bool CallLuaFunc(char *func_name, int arg_count, int ret_count);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ int Lua_print(lua_State *L) {
|
|||||||
Appendf(null_view, "\n");
|
Appendf(null_view, "\n");
|
||||||
lua_pop(L, nargs);
|
lua_pop(L, nargs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} RegisterLua(Lua_print);
|
||||||
|
|
||||||
int Lua_Print(lua_State *L) {
|
int Lua_Print(lua_State *L) {
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
@@ -21,7 +21,7 @@ int Lua_Print(lua_State *L) {
|
|||||||
Appendf(TraceView, "\n");
|
Appendf(TraceView, "\n");
|
||||||
lua_pop(L, nargs);
|
lua_pop(L, nargs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
} RegisterLua(Lua_Print);
|
||||||
|
|
||||||
int Lua_GetLoadWord(lua_State *L) {
|
int Lua_GetLoadWord(lua_State *L) {
|
||||||
BSet active = GetBSet(ActiveWindowID);
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
@@ -34,7 +34,7 @@ int Lua_GetLoadWord(lua_State *L) {
|
|||||||
String string = AllocCharString(scratch, active.buffer, range);
|
String string = AllocCharString(scratch, active.buffer, range);
|
||||||
lua_pushlstring(L, string.data, string.len);
|
lua_pushlstring(L, string.data, string.len);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} RegisterLua(Lua_GetLoadWord);
|
||||||
|
|
||||||
int Lua_BufferExists(lua_State *L) {
|
int Lua_BufferExists(lua_State *L) {
|
||||||
String string = lua_tostring(L, 1);
|
String string = lua_tostring(L, 1);
|
||||||
@@ -42,7 +42,7 @@ int Lua_BufferExists(lua_State *L) {
|
|||||||
Buffer *buffer = GetBuffer(string);
|
Buffer *buffer = GetBuffer(string);
|
||||||
lua_pushboolean(L, buffer != NULL);
|
lua_pushboolean(L, buffer != NULL);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} RegisterLua(Lua_BufferExists);
|
||||||
|
|
||||||
int Lua_GetSelection(lua_State *L) {
|
int Lua_GetSelection(lua_State *L) {
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
@@ -51,7 +51,7 @@ int Lua_GetSelection(lua_State *L) {
|
|||||||
String string = ToString(scratch, string16);
|
String string = ToString(scratch, string16);
|
||||||
lua_pushlstring(L, string.data, string.len);
|
lua_pushlstring(L, string.data, string.len);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} RegisterLua(Lua_GetSelection);
|
||||||
|
|
||||||
int Lua_GetEntireBuffer(lua_State *L) {
|
int Lua_GetEntireBuffer(lua_State *L) {
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
@@ -60,20 +60,20 @@ int Lua_GetEntireBuffer(lua_State *L) {
|
|||||||
String string = ToString(scratch, string16);
|
String string = ToString(scratch, string16);
|
||||||
lua_pushlstring(L, string.data, string.len);
|
lua_pushlstring(L, string.data, string.len);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} RegisterLua(Lua_GetEntireBuffer);
|
||||||
|
|
||||||
int Lua_GetClipboard(lua_State *L) {
|
int Lua_GetClipboard(lua_State *L) {
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
String string = ToString(scratch, SavedClipboardString);
|
String string = ToString(scratch, SavedClipboardString);
|
||||||
lua_pushlstring(L, string.data, string.len);
|
lua_pushlstring(L, string.data, string.len);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} RegisterLua(Lua_GetClipboard);
|
||||||
|
|
||||||
int Lua_GetFilename(lua_State *L) {
|
int Lua_GetFilename(lua_State *L) {
|
||||||
BSet main = GetBSet(LastActiveLayoutWindowID);
|
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||||
lua_pushlstring(L, main.buffer->name.data, main.buffer->name.len);
|
lua_pushlstring(L, main.buffer->name.data, main.buffer->name.len);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} RegisterLua(Lua_GetFilename);
|
||||||
|
|
||||||
int Lua_GetLine(lua_State *L) {
|
int Lua_GetLine(lua_State *L) {
|
||||||
BSet main = GetBSet(LastActiveLayoutWindowID);
|
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||||
@@ -82,7 +82,7 @@ int Lua_GetLine(lua_State *L) {
|
|||||||
Int line = PosToLine(main.buffer, front);
|
Int line = PosToLine(main.buffer, front);
|
||||||
lua_pushinteger(L, line + 1);
|
lua_pushinteger(L, line + 1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} RegisterLua(Lua_GetLine);
|
||||||
|
|
||||||
int Lua_FileExists(lua_State *L) {
|
int Lua_FileExists(lua_State *L) {
|
||||||
String path = luaL_checkstring(L, 1);
|
String path = luaL_checkstring(L, 1);
|
||||||
@@ -90,103 +90,213 @@ int Lua_FileExists(lua_State *L) {
|
|||||||
bool exists = FileExists(path);
|
bool exists = FileExists(path);
|
||||||
lua_pushboolean(L, exists);
|
lua_pushboolean(L, exists);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} RegisterLua(Lua_FileExists);
|
||||||
|
|
||||||
int Lua_GetWorkDir(lua_State *L) {
|
int Lua_GetWorkDir(lua_State *L) {
|
||||||
lua_pushlstring(L, WorkDir.data, WorkDir.len);
|
lua_pushlstring(L, WorkDir.data, WorkDir.len);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} RegisterLua(Lua_GetWorkDir);
|
||||||
|
|
||||||
int Lua_GetExeDir(lua_State *L) {
|
int Lua_GetExeDir(lua_State *L) {
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
String exe_dir = GetExeDir(scratch);
|
String exe_dir = GetExeDir(scratch);
|
||||||
lua_pushlstring(L, exe_dir.data, exe_dir.len);
|
lua_pushlstring(L, exe_dir.data, exe_dir.len);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
} RegisterLua(Lua_GetExeDir);
|
||||||
|
|
||||||
int Lua_GetMainDir(lua_State *L) {
|
int Lua_GetMainDir(lua_State *L) {
|
||||||
String name = GetMainDir();
|
String name = GetMainDir();
|
||||||
lua_pushlstring(L, name.data, name.len);
|
lua_pushlstring(L, name.data, name.len);
|
||||||
return 1;
|
return 1;
|
||||||
|
} RegisterLua(Lua_GetMainDir);
|
||||||
|
|
||||||
|
int Lua_ListCommands(lua_State *L) {
|
||||||
|
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||||
|
BeginJump(&main);
|
||||||
|
int i = 0;
|
||||||
|
For (LuaFunctions) {
|
||||||
|
Appendf(main.view, "%20S() ", it.name);
|
||||||
|
if (((i + 1) % 6) == 0) {
|
||||||
|
Appendf(main.view, "\n");
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
EndJump(main);
|
||||||
|
ActiveWindowID = main.window->id;
|
||||||
|
return 0;
|
||||||
|
} RegisterLua(Lua_ListCommands);
|
||||||
|
|
||||||
|
int Lua_GetBufferList(lua_State *L) {
|
||||||
|
lua_createtable(L, 0, (int)Buffers.len);
|
||||||
|
|
||||||
|
int i = 1;
|
||||||
|
For(Buffers) {
|
||||||
|
lua_pushinteger(L, i++);
|
||||||
|
lua_pushlstring(L, it->name.data, it->name.len);
|
||||||
|
lua_settable(L, -3); /* 3rd element from the stack top */
|
||||||
|
}
|
||||||
|
/* We still have table left on top of the Lua stack. */
|
||||||
|
return 1;
|
||||||
|
} RegisterLua(Lua_GetBufferList);
|
||||||
|
|
||||||
|
int Lua_Eval(lua_State *L) {
|
||||||
|
String string = lua_tostring(L, 1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
Eval(string);
|
||||||
|
return 0;
|
||||||
|
} RegisterLua(Lua_Eval);
|
||||||
|
|
||||||
|
int Lua_ApplyClangFormat(lua_State *L) {
|
||||||
|
lua_Integer buffer_id = luaL_checkinteger(L, 1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
Buffer *buffer = GetBuffer({buffer_id});
|
||||||
|
ApplyClangFormat(buffer);
|
||||||
|
return 0;
|
||||||
|
} RegisterLua(Lua_ApplyClangFormat);
|
||||||
|
|
||||||
|
int Lua_GetBufferNameByID(lua_State *L) {
|
||||||
|
lua_Integer buffer_id = luaL_checkinteger(L, 1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
Buffer *buffer = GetBuffer({buffer_id});
|
||||||
|
lua_pushlstring(L, buffer->name.data, buffer->name.len);
|
||||||
|
return 1;
|
||||||
|
} RegisterLua(Lua_GetBufferNameByID);
|
||||||
|
|
||||||
|
|
||||||
|
int Lua_ConvertLineEndingsToLF(lua_State *L) {
|
||||||
|
lua_Integer buffer_id = luaL_checkinteger(L, 1);
|
||||||
|
int trim_lines_with_caret = lua_toboolean(L, 2);
|
||||||
|
lua_pop(L, 2);
|
||||||
|
Buffer *buffer = GetBuffer({buffer_id});
|
||||||
|
ConvertLineEndingsToLF(buffer, trim_lines_with_caret);
|
||||||
|
return 0;
|
||||||
|
} RegisterLua(Lua_ConvertLineEndingsToLF);
|
||||||
|
|
||||||
|
int Lua_New(lua_State *L) {
|
||||||
|
String name = lua_tostring(L, 1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||||
|
New(main.window, name);
|
||||||
|
return 0;
|
||||||
|
} RegisterLua(Lua_New);
|
||||||
|
|
||||||
|
int Lua_NewDir(lua_State *L) {
|
||||||
|
String name = lua_tostring(L, 1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||||
|
NewDir(main.window, name);
|
||||||
|
return 0;
|
||||||
|
} RegisterLua(Lua_NewDir);
|
||||||
|
|
||||||
|
int Lua_C(lua_State *L) {
|
||||||
|
String string = lua_tostring(L, 1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
Exec(string, GetMainDir());
|
||||||
|
return 0;
|
||||||
|
} RegisterLua(Lua_C);
|
||||||
|
|
||||||
|
int Lua_Open(lua_State *L) {
|
||||||
|
Scratch scratch;
|
||||||
|
String path = luaL_checkstring(L, 1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
Open(path);
|
||||||
|
return 0;
|
||||||
|
} RegisterLua(Lua_Open);
|
||||||
|
|
||||||
|
int Lua_Cmd(lua_State *L) {
|
||||||
|
if (!lua_istable(L, -1)) luaL_error(L, "expected a table as argument");
|
||||||
|
defer { lua_pop(L, 1); };
|
||||||
|
|
||||||
|
lua_getfield(L, -1, "working_dir");
|
||||||
|
String working_dir = lua_tostring(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
if (working_dir == "") {
|
||||||
|
working_dir = GetMainDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OnOpenResult {
|
lua_getfield(L, -1, "cmd");
|
||||||
String kind;
|
if (!lua_isstring(L, -1)) luaL_error(L, "expected a string for cmd param");
|
||||||
String file_path;
|
String cmd = lua_tostring(L, -1);
|
||||||
Int line, col;
|
lua_pop(L, 1);
|
||||||
String working_dir;
|
|
||||||
String cmd;
|
|
||||||
};
|
|
||||||
|
|
||||||
OnOpenResult CallOnOpen(Allocator allocator, String path, String meta) {
|
lua_getfield(L, -1, "kind");
|
||||||
lua_getglobal(LuaState, "OnOpen");
|
String kind = lua_tostring(L, -1);
|
||||||
lua_pushlstring(LuaState, path.data, path.len);
|
lua_pop(L, 1);
|
||||||
lua_pushlstring(LuaState, meta.data, meta.len);
|
|
||||||
if (!CallLuaFunc("OnOpen", 2, 1)) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
String file_path = GetFieldString(LuaState, "file_path");
|
BSet main = GetBSet(LastActiveLayoutWindowID);
|
||||||
String line_string = GetFieldString(LuaState, "line");
|
if (kind == "console") {
|
||||||
String col_string = GetFieldString(LuaState, "col");
|
BSet set = GetConsoleSet();
|
||||||
String cmd = GetFieldString(LuaState, "cmd");
|
main.window->active_goto_list = set.view->id;
|
||||||
String working_dir = GetFieldString(LuaState, "working_dir");
|
main.window->goto_list_pos = set.buffer->len;
|
||||||
String kind = GetFieldString(LuaState, "kind");
|
SelectRange(set.view, MakeRange(set.buffer->len));
|
||||||
|
BeginJump(&set);
|
||||||
OnOpenResult result = {};
|
Exec(set.view->id, true, cmd, working_dir);
|
||||||
result.cmd = cmd;
|
EndJump(set);
|
||||||
result.working_dir = working_dir;
|
} else if (kind == "fuzzy") {
|
||||||
result.file_path = file_path;
|
JumpGarbageBuffer(&main);
|
||||||
if (!IsAbsolute(result.file_path)) {
|
Exec(main.view->id, true, cmd, working_dir);
|
||||||
String dir = GetMainDir();
|
main.view->fuzzy_search = true;
|
||||||
result.file_path = Format(allocator, "%S/%S", dir, result.file_path);
|
ActiveWindowID = main.window->id;
|
||||||
}
|
|
||||||
if (col_string.len) {
|
|
||||||
result.col = strtoll(col_string.data, NULL, 10);
|
|
||||||
} else {
|
} else {
|
||||||
result.col = -1;
|
JumpGarbageBuffer(&main);
|
||||||
|
main.window->active_goto_list = main.view->id;
|
||||||
|
main.window->goto_list_pos = 0;
|
||||||
|
Exec(main.view->id, true, cmd, working_dir);
|
||||||
|
ActiveWindowID = main.window->id;
|
||||||
}
|
}
|
||||||
if (line_string.len) {
|
|
||||||
result.line = strtoll(line_string.data, NULL, 10);
|
return 0;
|
||||||
} else {
|
} RegisterLua(Lua_Cmd);
|
||||||
result.line = -1;
|
|
||||||
|
Int GetFieldAInt(lua_State *L, const char *name) {
|
||||||
|
lua_getfield(L, -1, name);
|
||||||
|
lua_Integer num = lua_tointeger(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return (Int)num;
|
||||||
}
|
}
|
||||||
result.kind = kind;
|
|
||||||
|
|
||||||
|
double GetFieldAFloat(lua_State *L, const char *name) {
|
||||||
|
lua_getfield(L, -1, name);
|
||||||
|
double num = lua_tonumber(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *GetFieldAString(lua_State *L, const char *name) {
|
||||||
|
lua_getfield(L, -1, name);
|
||||||
|
const char *result = lua_tostring(L, -1);
|
||||||
|
|
||||||
|
lua_pop(L, 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CallIsCode(String path, String meta = "") {
|
// :Event
|
||||||
lua_getglobal(LuaState, "IsCode");
|
int Lua_Play(lua_State *L) {
|
||||||
lua_pushlstring(LuaState, path.data, path.len);
|
if (!lua_istable(L, -1)) luaL_error(L, "expected a table of events");
|
||||||
lua_pushlstring(LuaState, meta.data, meta.len);
|
defer { lua_pop(L, 1); };
|
||||||
if (!CallLuaFunc("IsCode", 2, 1)) {
|
|
||||||
return false;
|
int size = (int)lua_rawlen(L, -1);
|
||||||
|
for (int i = 0; i < size; i += 1) {
|
||||||
|
lua_geti(L, -1, i + 1);
|
||||||
|
if (!lua_istable(L, -1)) luaL_error(L, "expected a table of events");
|
||||||
|
defer { lua_pop(L, 1); };
|
||||||
|
|
||||||
|
Event event = {};
|
||||||
|
#define X(TYPE, KIND, NAME) event.NAME = (TYPE)GetFieldA##KIND(L, #NAME);
|
||||||
|
EVENT_FIELDS
|
||||||
|
#undef X
|
||||||
|
Add(&EventPlayback, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool result = lua_toboolean(LuaState, -1);
|
return 0;
|
||||||
lua_pop(LuaState, 1);
|
} RegisterLua(Lua_Play);
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CallOnSave(BufferID buffer_id) {
|
|
||||||
lua_getglobal(LuaState, "OnSave");
|
|
||||||
lua_pushinteger(LuaState, buffer_id.id);
|
|
||||||
CallLuaFunc("OnSave", 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CallOnCommand(Event *event) {
|
int Lua_TrimTrailingWhitespace(lua_State *L) {
|
||||||
lua_getglobal(LuaState, "OnCommand");
|
lua_Integer buffer_id = luaL_checkinteger(L, 1);
|
||||||
PushEvent(LuaState, event);
|
int trim_lines_with_caret = lua_toboolean(L, 2);
|
||||||
CallLuaFunc("OnCommand", 1, 1);
|
lua_pop(L, 2);
|
||||||
bool result = lua_toboolean(LuaState, -1);
|
Buffer *buffer = GetBuffer({buffer_id});
|
||||||
lua_pop(LuaState, 1);
|
TrimTrailingWhitespace(buffer, trim_lines_with_caret);
|
||||||
return result;
|
return 0;
|
||||||
}
|
} RegisterLua(Lua_TrimTrailingWhitespace);
|
||||||
|
|
||||||
void CallLuaOnUpdate(Event *event) {
|
|
||||||
lua_getglobal(LuaState, "OnUpdate");
|
|
||||||
PushEvent(LuaState, event);
|
|
||||||
CallLuaFunc("OnUpdate", 1, 0);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
luaL_Reg LuaFunctions[] = {
|
|
||||||
{"print", Lua_print},
|
|
||||||
{"Print", Lua_Print},
|
|
||||||
{"SaveAll", Lua_SaveAll},
|
|
||||||
{"KillProcess", Lua_KillProcess},
|
|
||||||
{"GetLoadWord", Lua_GetLoadWord},
|
|
||||||
{"BufferExists", Lua_BufferExists},
|
|
||||||
{"GetSelection", Lua_GetSelection},
|
|
||||||
{"GetEntireBuffer", Lua_GetEntireBuffer},
|
|
||||||
{"GetClipboard", Lua_GetClipboard},
|
|
||||||
{"GetFilename", Lua_GetFilename},
|
|
||||||
{"GetLine", Lua_GetLine},
|
|
||||||
{"FileExists", Lua_FileExists},
|
|
||||||
{"GetWorkDir", Lua_GetWorkDir},
|
|
||||||
{"GetExeDir", Lua_GetExeDir},
|
|
||||||
{"GetMainDir", Lua_GetMainDir},
|
|
||||||
{"KillWindow", Lua_KillWindow},
|
|
||||||
{"Play", Lua_Play},
|
|
||||||
{"TrimTrailingWhitespace", Lua_TrimTrailingWhitespace},
|
|
||||||
{"ConvertLineEndingsToLF", Lua_ConvertLineEndingsToLF},
|
|
||||||
{"ApplyClangFormat", Lua_ApplyClangFormat},
|
|
||||||
{"GetBufferNameByID", Lua_GetBufferNameByID},
|
|
||||||
{"Save", Lua_Save},
|
|
||||||
{"Reopen", Lua_Reopen},
|
|
||||||
{"New", Lua_New},
|
|
||||||
{"NewDir", Lua_NewDir},
|
|
||||||
{"ToggleFullscreen", Lua_ToggleFullscreen},
|
|
||||||
{"ListCode", Lua_ListCode},
|
|
||||||
{"C", Lua_C},
|
|
||||||
{"Open", Lua_Open},
|
|
||||||
{"Cmd", Lua_Cmd},
|
|
||||||
{"ListViews", Lua_ListViews},
|
|
||||||
{"Eval", Lua_Eval},
|
|
||||||
{"SetProjectFile", Lua_SetProjectFile},
|
|
||||||
{"SetWorkDir", Lua_SetWorkDir},
|
|
||||||
{"ListCommands", Lua_ListCommands},
|
|
||||||
{"GetBufferList", Lua_GetBufferList},
|
|
||||||
{NULL, NULL},
|
|
||||||
};
|
|
||||||
@@ -38,9 +38,6 @@ String GetMainDir() {
|
|||||||
void GarbageCollect() {
|
void GarbageCollect() {
|
||||||
Allocator sys_allocator = GetSystemAllocator();
|
Allocator sys_allocator = GetSystemAllocator();
|
||||||
|
|
||||||
|
|
||||||
ActiveWindowID = NextActiveWindowID;
|
|
||||||
|
|
||||||
For (Windows) {
|
For (Windows) {
|
||||||
if (it->sync_visibility_with_focus) {
|
if (it->sync_visibility_with_focus) {
|
||||||
if (it->id == ActiveWindowID) {
|
if (it->id == ActiveWindowID) {
|
||||||
@@ -51,8 +48,8 @@ void GarbageCollect() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ActiveWindowID.id != LastActiveLayoutWindowID.id) {
|
|
||||||
Window *window = GetWindow(ActiveWindowID);
|
Window *window = GetWindow(ActiveWindowID);
|
||||||
|
if (ActiveWindowID.id != LastActiveLayoutWindowID.id) {
|
||||||
if (window->layout) {
|
if (window->layout) {
|
||||||
LastActiveLayoutWindowID = ActiveWindowID;
|
LastActiveLayoutWindowID = ActiveWindowID;
|
||||||
}
|
}
|
||||||
|
|||||||
245
src/text_editor/parser.cpp
Normal file
245
src/text_editor/parser.cpp
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
struct Lexer {
|
||||||
|
Allocator allocator;
|
||||||
|
char *at;
|
||||||
|
char *start;
|
||||||
|
char *end;
|
||||||
|
char *name;
|
||||||
|
int line, column;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TriggerKind {
|
||||||
|
TriggerKind_Error,
|
||||||
|
TriggerKind_Key,
|
||||||
|
TriggerKind_Mouse,
|
||||||
|
TriggerKind_Binary,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Trigger {
|
||||||
|
TriggerKind kind;
|
||||||
|
Trigger *left;
|
||||||
|
Trigger *right;
|
||||||
|
SDL_Keycode key;
|
||||||
|
struct {
|
||||||
|
EventKind event_kind : 8;
|
||||||
|
U32 ctrl : 1;
|
||||||
|
U32 alt : 1;
|
||||||
|
U32 shift : 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
void Advance(Lexer *lex) {
|
||||||
|
if (lex->at < lex->end) {
|
||||||
|
if (lex->at[0] == '\n') {
|
||||||
|
lex->line += 1;
|
||||||
|
lex->column = 0;
|
||||||
|
} else {
|
||||||
|
lex->column += 1;
|
||||||
|
}
|
||||||
|
lex->at += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Advance(Lexer *lex, int n) {
|
||||||
|
for (int i = 0; i < n; i += 1) Advance(lex);
|
||||||
|
}
|
||||||
|
|
||||||
|
char At(Lexer *lex) {
|
||||||
|
if (lex->at < lex->end) {
|
||||||
|
return lex->at[0];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
String AsString(Lexer *lex) {
|
||||||
|
String result = {lex->at, lex->end - lex->at};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EatWhitespace(Lexer *lex) {
|
||||||
|
while (IsWhitespace(At(lex))) {
|
||||||
|
Advance(lex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Trigger *TriggerBinary(Lexer *lex, Trigger *left, Trigger *right, int key) {
|
||||||
|
Trigger *result = AllocType(lex->allocator, Trigger);
|
||||||
|
result->kind = TriggerKind_Binary;
|
||||||
|
result->key = key;
|
||||||
|
result->left = left;
|
||||||
|
result->right = right;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Trigger *ParseKeyAtom(Lexer *lex) {
|
||||||
|
Trigger *result = AllocType(lex->allocator, Trigger);
|
||||||
|
result->kind = TriggerKind_Key;
|
||||||
|
EatWhitespace(lex);
|
||||||
|
for (;;) {
|
||||||
|
String lex_string = AsString(lex);
|
||||||
|
if (StartsWith(lex_string, "ctrl")) {
|
||||||
|
result->ctrl = true;
|
||||||
|
Advance(lex, 4);
|
||||||
|
} else if (StartsWith(lex_string, "shift")) {
|
||||||
|
result->shift = true;
|
||||||
|
Advance(lex, 5);
|
||||||
|
} else if (StartsWith(lex_string, "alt")) {
|
||||||
|
result->alt = true;
|
||||||
|
Advance(lex, 3);
|
||||||
|
} else if (IsAlphanumeric(At(lex))) {
|
||||||
|
char *start = lex->at;
|
||||||
|
while (IsAlphanumeric(At(lex))) {
|
||||||
|
Advance(lex);
|
||||||
|
}
|
||||||
|
String a = {start, lex->at - start};
|
||||||
|
Advance(lex);
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
for (int i = 0; !found && i < Lengthof(MouseConversionTable); i += 1) {
|
||||||
|
if (a == MouseConversionTable[i].string) {
|
||||||
|
result->event_kind = MouseConversionTable[i].value;
|
||||||
|
result->kind = TriggerKind_Mouse;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; !found && i < Lengthof(SDLKeycodeConversionTable); i += 1) {
|
||||||
|
if (a == SDLKeycodeConversionTable[i].string) {
|
||||||
|
result->key = SDLKeycodeConversionTable[i].value;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
result->kind = TriggerKind_Error;
|
||||||
|
ReportErrorf("%s:%d:%d: Failed to parse key trigger, unexpected identifier: '%d'", lex->name, lex->line, lex->column, result->key);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result->kind = TriggerKind_Error;
|
||||||
|
ReportErrorf("%s:%d:%d: Failed to parse key trigger, unexpected character: '%c'", lex->name, lex->line, lex->column, At(lex));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (At(lex) == '-') {
|
||||||
|
Advance(lex);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Trigger *ParseKeyChord(Lexer *lex) {
|
||||||
|
Trigger *left = ParseKeyAtom(lex);
|
||||||
|
EatWhitespace(lex);
|
||||||
|
while (IsAlphanumeric(At(lex))) {
|
||||||
|
int op = At(lex);
|
||||||
|
left = TriggerBinary(lex, left, ParseKeyChord(lex), ' ');
|
||||||
|
EatWhitespace(lex);
|
||||||
|
}
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
Trigger *ParseKeyExpr(Lexer *lex) {
|
||||||
|
Trigger *left = ParseKeyChord(lex);
|
||||||
|
EatWhitespace(lex);
|
||||||
|
while (At(lex) == '|') {
|
||||||
|
Advance(lex);
|
||||||
|
left = TriggerBinary(lex, left, ParseKeyExpr(lex), '|');
|
||||||
|
EatWhitespace(lex);
|
||||||
|
}
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
Trigger *ParseKey(Allocator allocator, String key, char *debug_name) {
|
||||||
|
Lexer lex = {allocator, key.data, key.data, key.data + key.len, debug_name};
|
||||||
|
Trigger *result = ParseKeyExpr(&lex);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MatchEvent(Trigger *trigger, Event *event) {
|
||||||
|
if (trigger->kind == TriggerKind_Key) {
|
||||||
|
if (trigger->key == event->key && trigger->ctrl == event->ctrl && trigger->alt == event->alt && trigger->shift == event->shift) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (trigger->kind == TriggerKind_Mouse) {
|
||||||
|
if (trigger->event_kind == event->kind) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (trigger->kind == TriggerKind_Binary) {
|
||||||
|
if (trigger->key == ' ') {
|
||||||
|
return false;
|
||||||
|
} else if (trigger->key == '|') {
|
||||||
|
bool ok = MatchEvent(trigger->left, event);
|
||||||
|
if (ok) return ok;
|
||||||
|
ok = MatchEvent(trigger->right, event);
|
||||||
|
if (ok) return ok;
|
||||||
|
} ElseInvalidCodepath();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestParser() {
|
||||||
|
Scratch scratch;
|
||||||
|
{
|
||||||
|
char *cmd = "ctrl-b";
|
||||||
|
Lexer base_lex = {scratch, cmd, cmd, cmd + strlen(cmd), "keybinding"};
|
||||||
|
Trigger *trigger = ParseKeyExpr(&base_lex);
|
||||||
|
Assert(trigger->kind == TriggerKind_Key);
|
||||||
|
Assert(trigger->key == SDLK_B);
|
||||||
|
Assert(trigger->ctrl);
|
||||||
|
Assert(trigger->shift == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char *cmd = "ctrl-b shift-ctrl-a";
|
||||||
|
Lexer base_lex = {scratch, cmd, cmd, cmd + strlen(cmd), "keybinding"};
|
||||||
|
Trigger *trigger = ParseKeyExpr(&base_lex);
|
||||||
|
Assert(trigger->kind == TriggerKind_Binary);
|
||||||
|
Assert(trigger->key == ' ');
|
||||||
|
Assert(trigger->left->kind == TriggerKind_Key);
|
||||||
|
Assert(trigger->left->key == SDLK_B);
|
||||||
|
Assert(trigger->left->ctrl);
|
||||||
|
Assert(trigger->left->shift == 0);
|
||||||
|
Assert(trigger->right->kind == TriggerKind_Key);
|
||||||
|
Assert(trigger->right->key == SDLK_A);
|
||||||
|
Assert(trigger->right->ctrl);
|
||||||
|
Assert(trigger->right->shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char *cmd = "ctrl-b shift-ctrl-a | ctrl-c | ctrl-d";
|
||||||
|
Lexer base_lex = {scratch, cmd, cmd, cmd + strlen(cmd), "keybinding"};
|
||||||
|
Trigger *trigger = ParseKeyExpr(&base_lex);
|
||||||
|
Assert(trigger->kind == TriggerKind_Binary);
|
||||||
|
Assert(trigger->key == '|');
|
||||||
|
|
||||||
|
Assert(trigger->left->kind == TriggerKind_Binary);
|
||||||
|
Assert(trigger->left->key == ' ');
|
||||||
|
|
||||||
|
Assert(trigger->right->kind == TriggerKind_Binary);
|
||||||
|
Assert(trigger->right->key == '|');
|
||||||
|
|
||||||
|
|
||||||
|
Event event = {};
|
||||||
|
event.kind = EVENT_KEY_PRESS;
|
||||||
|
event.key = SDLK_D;
|
||||||
|
event.ctrl = 1;
|
||||||
|
bool ok = MatchEvent(trigger, &event);
|
||||||
|
Assert(ok);
|
||||||
|
|
||||||
|
event.key = SDLK_F1;
|
||||||
|
ok = MatchEvent(trigger, &event);
|
||||||
|
Assert(ok == 0);
|
||||||
|
|
||||||
|
event.ctrl = 1;
|
||||||
|
event.shift = 1;
|
||||||
|
event.key = SDLK_A;
|
||||||
|
ok = MatchEvent(trigger, &event);
|
||||||
|
Assert(!ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} RegisterFunction(&TestFunctions, TestParser);
|
||||||
@@ -7,6 +7,9 @@
|
|||||||
#include "external/glad/glad.h"
|
#include "external/glad/glad.h"
|
||||||
#include "external/stb_truetype.h"
|
#include "external/stb_truetype.h"
|
||||||
#include "external/stb_truetype.c"
|
#include "external/stb_truetype.c"
|
||||||
|
#if OS_LINUX
|
||||||
|
#define MCO_USE_UCONTEXT
|
||||||
|
#endif
|
||||||
#define MINICORO_IMPL
|
#define MINICORO_IMPL
|
||||||
#include "external/minicoro.h"
|
#include "external/minicoro.h"
|
||||||
#define LUA_USE_LONGJMP
|
#define LUA_USE_LONGJMP
|
||||||
@@ -30,14 +33,14 @@
|
|||||||
#include "management.cpp"
|
#include "management.cpp"
|
||||||
#include "process.cpp"
|
#include "process.cpp"
|
||||||
#include "event.cpp"
|
#include "event.cpp"
|
||||||
|
#include "parser.cpp"
|
||||||
|
|
||||||
#include "lua_api.cpp"
|
|
||||||
#include "commands.cpp"
|
#include "commands.cpp"
|
||||||
|
#include "lua_api.cpp"
|
||||||
#include "commands_clipboard.cpp"
|
#include "commands_clipboard.cpp"
|
||||||
#include "commands_bindings.cpp"
|
#include "commands_bindings.cpp"
|
||||||
#include "title_bar.cpp"
|
#include "title_bar.cpp"
|
||||||
|
|
||||||
#include "lua_api_generated.cpp"
|
|
||||||
#include "generated_config.cpp"
|
#include "generated_config.cpp"
|
||||||
|
|
||||||
#include "draw.cpp"
|
#include "draw.cpp"
|
||||||
@@ -117,9 +120,6 @@ void SetMouseCursor(Event event) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SetMouseCursor(SDL_SYSTEM_CURSOR_DEFAULT);
|
SetMouseCursor(SDL_SYSTEM_CURSOR_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +135,9 @@ void Update(Event event) {
|
|||||||
view->update_scroll = true;
|
view->update_scroll = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OnCommandEvent = &event;
|
||||||
OnCommand(event);
|
OnCommand(event);
|
||||||
|
OnCommandEvent = NULL;
|
||||||
UpdateProcesses();
|
UpdateProcesses();
|
||||||
CoUpdate(&event);
|
CoUpdate(&event);
|
||||||
ReloadLuaConfigs();
|
ReloadLuaConfigs();
|
||||||
@@ -198,7 +200,7 @@ void MainLoop() {
|
|||||||
|
|
||||||
if (it.xwindow == 0 || it.ywindow == 0) {
|
if (it.xwindow == 0 || it.ywindow == 0) {
|
||||||
int xwindow, ywindow;
|
int xwindow, ywindow;
|
||||||
SDL_GetWindowSize(SDLWindow, &xwindow, &ywindow);
|
SDL_GetWindowSizeInPixels(SDLWindow, &xwindow, &ywindow);
|
||||||
it.xwindow = xwindow;
|
it.xwindow = xwindow;
|
||||||
it.ywindow = ywindow;
|
it.ywindow = ywindow;
|
||||||
}
|
}
|
||||||
@@ -236,7 +238,6 @@ void MainLoop() {
|
|||||||
SDL_GL_SwapWindow(SDLWindow);
|
SDL_GL_SwapWindow(SDLWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
||||||
#else
|
#else
|
||||||
@@ -253,18 +254,21 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
if (1) {
|
if (1) {
|
||||||
RunArenaTest();
|
RunArenaTest();
|
||||||
RunBufferTest();
|
For (TestFunctions) {
|
||||||
|
it.function();
|
||||||
|
}
|
||||||
|
|
||||||
// ReportErrorf("Testing DONE\n");
|
// ReportErrorf("Testing DONE\n");
|
||||||
// return 0;
|
// return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !OS_WINDOWS
|
#if !OS_WINDOWS
|
||||||
for (int i = 0; environ[i]; i += 1) {
|
for (int i = 0; environ[i]; i += 1) {
|
||||||
Add(&Enviroment, Copy(GetSystemAllocator(), environ[i]));
|
Add(&Enviroment, Copy(Perm, environ[i]));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
WorkDir = GetWorkingDir(SysAllocator);
|
WorkDir = GetWorkingDir(Perm);
|
||||||
{
|
{
|
||||||
String sdl_config_path = SDL_GetPrefPath("krzosa", "text_editor");
|
String sdl_config_path = SDL_GetPrefPath("krzosa", "text_editor");
|
||||||
if (sdl_config_path.len && sdl_config_path.data[sdl_config_path.len - 1] == '\\') {
|
if (sdl_config_path.len && sdl_config_path.data[sdl_config_path.len - 1] == '\\') {
|
||||||
@@ -273,7 +277,7 @@ int main(int argc, char **argv)
|
|||||||
if (sdl_config_path.len && sdl_config_path.data[sdl_config_path.len - 1] == '/') {
|
if (sdl_config_path.len && sdl_config_path.data[sdl_config_path.len - 1] == '/') {
|
||||||
sdl_config_path = Chop(sdl_config_path, 1); // chop '/'
|
sdl_config_path = Chop(sdl_config_path, 1); // chop '/'
|
||||||
}
|
}
|
||||||
ConfigDir = NormalizePath(SysAllocator, sdl_config_path);
|
ConfigDir = NormalizePath(Perm, sdl_config_path);
|
||||||
SDL_free(sdl_config_path.data);
|
SDL_free(sdl_config_path.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,6 +354,11 @@ int main(int argc, char **argv)
|
|||||||
InitWindows();
|
InitWindows();
|
||||||
InitOS(ReportWarningf);
|
InitOS(ReportWarningf);
|
||||||
|
|
||||||
|
For (CommandFunctions) {
|
||||||
|
if (it.binding.len != 0) {
|
||||||
|
it.trigger = ParseKey(Perm, it.binding, it.name.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 1; i < argc; i += 1) {
|
for (int i = 1; i < argc; i += 1) {
|
||||||
String it = argv[i];
|
String it = argv[i];
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ void UpdateDebugBuffer() {
|
|||||||
|
|
||||||
float xmouse, ymouse;
|
float xmouse, ymouse;
|
||||||
SDL_GetMouseState(&xmouse, &ymouse);
|
SDL_GetMouseState(&xmouse, &ymouse);
|
||||||
RawAppendf(buffer, "mouse: [%f, %f]\n", xmouse, ymouse);
|
RawAppendf(buffer, "mouse: [%f, %f]\n", roundf(DPIScale * xmouse), roundf(DPIScale * ymouse));
|
||||||
|
|
||||||
RawAppendf(buffer, "BufferID id = %d\n", main.buffer->id.id);
|
RawAppendf(buffer, "BufferID id = %d\n", main.buffer->id.id);
|
||||||
RawAppendf(buffer, "String name = %S\n", main.buffer->name);
|
RawAppendf(buffer, "String name = %S\n", main.buffer->name);
|
||||||
|
|||||||
@@ -250,8 +250,8 @@ void LayoutWindows(int16_t wx, int16_t wy) {
|
|||||||
Rect2 screen_rect = Rect0Size(wx, wy);
|
Rect2 screen_rect = Rect0Size(wx, wy);
|
||||||
Vec2 size = GetSize(screen_rect);
|
Vec2 size = GetSize(screen_rect);
|
||||||
|
|
||||||
Rect2 a = CutLeft(&screen_rect, 0.3f * size.x);
|
Rect2 a = CutRight(&screen_rect, 0.3f * size.x);
|
||||||
Rect2 b = CutBottom(&a, 0.4f * size.y);
|
Rect2 b = CutTop(&a, 0.4f * size.y);
|
||||||
Rect2 c = Shrink(b, 20);
|
Rect2 c = Shrink(b, 20);
|
||||||
n->document_rect = n->total_rect = ToRect2I(c);
|
n->document_rect = n->total_rect = ToRect2I(c);
|
||||||
}
|
}
|
||||||
@@ -280,3 +280,40 @@ void LayoutWindows(int16_t wx, int16_t wy) {
|
|||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Window *GetOverlappingWindow(Vec2I p, Window *default_window = NULL) {
|
||||||
|
For(Windows) {
|
||||||
|
if (AreOverlapping(p, it->total_rect)) {
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return default_window;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2I GetSideOfWindow(Window *window, int direction) {
|
||||||
|
Vec2I p = {};
|
||||||
|
Rect2I rect = window->total_rect;
|
||||||
|
float resizer_size = (float)window->font->char_spacing*0.5f; // @check_codebase_when_changing
|
||||||
|
if (direction == DIR_LEFT) {
|
||||||
|
p.x = rect.min.x - (Int)(resizer_size + window->font->char_spacing);
|
||||||
|
p.y = rect.min.y + (rect.max.y / 2);
|
||||||
|
} else if (direction == DIR_RIGHT) {
|
||||||
|
p.x = rect.max.x + (Int)(resizer_size + window->font->char_spacing);
|
||||||
|
p.y = rect.min.y + (rect.max.y / 2);
|
||||||
|
} else if (direction == DIR_UP) {
|
||||||
|
p.x = rect.min.x + (rect.max.x / 2);
|
||||||
|
p.y = rect.min.y - (Int)(resizer_size + window->font->line_spacing);
|
||||||
|
} else {
|
||||||
|
Assert(direction == DIR_DOWN);
|
||||||
|
p.x = rect.min.x + (rect.max.x / 2);
|
||||||
|
p.y = rect.max.y + (Int)(resizer_size + window->font->line_spacing);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
Window *SwitchWindow(int direction) {
|
||||||
|
Window *window = GetWindow(ActiveWindowID);
|
||||||
|
Vec2I p = GetSideOfWindow(window, direction);
|
||||||
|
Window *result = GetOverlappingWindow(p, window);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ struct Window {
|
|||||||
bool sync_visibility_with_focus : 1;
|
bool sync_visibility_with_focus : 1;
|
||||||
bool lose_focus_on_escape : 1;
|
bool lose_focus_on_escape : 1;
|
||||||
bool jump_history : 1;
|
bool jump_history : 1;
|
||||||
|
bool eval_command : 1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user