diff --git a/.gitignore b/.gitignore index 5b64b26..5797ce2 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,6 @@ package/ *.spall *.sublime-workspace te.exe -te.pdb \ No newline at end of file +te.pdb +te +te_debug \ No newline at end of file diff --git a/build.sh b/build.sh index ce3ac31..fa688f6 100644 --- a/build.sh +++ b/build.sh @@ -47,9 +47,13 @@ if [ ! -f "lbaselib.o" ]; then -c fi -cp ../data/*.ttf . -clang ../src/text_editor/text_editor.cpp ../src/basic/unix.cpp \ - -o te_linux.exe \ +clang ../src/metaprogram/metaprogram.cpp -o metaprogram.exe \ + -nostdlib++ -fno-exceptions -fdiagnostics-absolute-paths -g \ + -Wno-writable-strings \ + -I../src +./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 \ @@ -59,45 +63,17 @@ clang ../src/text_editor/text_editor.cpp ../src/basic/unix.cpp \ -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 \ + 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 ~/bin/te - echo written ~/bin/te + cp te_linux.exe ../data/te + echo written ../data/te else - cp te_linux.exe ~/bin/te_debug - echo written ~/bin/te_debug + cp te_linux.exe ../data/te_debug + echo written ../data/te_debug fi diff --git a/src/metaprogram/metaprogram.cpp b/src/metaprogram/metaprogram.cpp new file mode 100644 index 0000000..203b283 --- /dev/null +++ b/src/metaprogram/metaprogram.cpp @@ -0,0 +1,17 @@ +#define BASIC_IMPL +#include "basic/basic.h" +#include "basic/filesystem.h" +#include "basic/unix.cpp" +int main() { + InitScratch(); + + Scratch scratch; + String data = ReadFile(scratch, "../data/init.lua"); + Array array = {scratch}; + + Add(&array, String{"String BaseLuaConfig = R\"==(\n"}); + Add(&array, data); + Add(&array, String{"\n)==\";\n"}); + String result = Merge(scratch, array, ""); + WriteFile("../src/text_editor/generated_config.cpp", result); +} \ No newline at end of file diff --git a/src/text_editor/generated.cpp b/src/text_editor/generated.cpp index 183f92f..7e7f1b6 100644 --- a/src/text_editor/generated.cpp +++ b/src/text_editor/generated.cpp @@ -1,496 +1,3 @@ -String BaseLuaConfig = R"==( -local GruvboxDark0Hard = 0x1d2021ff -local GruvboxDark0 = 0x282828ff -local GruvboxDark0Soft = 0x32302fff -local GruvboxDark1 = 0x3c3836ff -local GruvboxDark2 = 0x504945ff -local GruvboxDark3 = 0x665c54ff -local GruvboxDark4 = 0x7c6f64ff -local GruvboxGray245 = 0x928374ff -local GruvboxGray244 = 0x928374ff -local GruvboxLight0Hard = 0xf9f5d7ff -local GruvboxLight0 = 0xfbf1c7ff -local GruvboxLight0Soft = 0xf2e5bcff -local GruvboxLight1 = 0xebdbb2ff -local GruvboxLight2 = 0xd5c4a1ff -local GruvboxLight3 = 0xbdae93ff -local GruvboxLight4 = 0xa89984ff -local GruvboxBrightRed = 0xfb4934ff -local GruvboxBrightGreen = 0xb8bb26ff -local GruvboxBrightYellow = 0xfabd2fff -local GruvboxBrightBlue = 0x83a598ff -local GruvboxBrightPurple = 0xd3869bff -local GruvboxBrightAqua = 0x8ec07cff -local GruvboxBrightOrange = 0xfe8019ff -local GruvboxNeutralRed = 0xcc241dff -local GruvboxNeutralGreen = 0x98971aff -local GruvboxNeutralYellow = 0xd79921ff -local GruvboxNeutralBlue = 0x458588ff -local GruvboxNeutralPurple = 0xb16286ff -local GruvboxNeutralAqua = 0x689d6aff -local GruvboxNeutralOrange = 0xd65d0eff -local GruvboxFadedRed = 0x9d0006ff -local GruvboxFadedGreen = 0x79740eff -local GruvboxFadedYellow = 0xb57614ff -local GruvboxFadedBlue = 0x076678ff -local GruvboxFadedPurple = 0x8f3f71ff -local GruvboxFadedAqua = 0x427b58ff -local GruvboxFadedOrange = 0xaf3a03ff -Color = {} -Color.Text = GruvboxDark0Hard -Color.LoadTextHighlight = 0x0000000F -Color.Background = GruvboxLight0Hard -Color.InactiveWindow = 0x0000000F -Color.TextLineNumbers = GruvboxDark4 -Color.LineHighlight = GruvboxLight0Soft -Color.MainCaret = GruvboxDark0Hard -Color.SubCaret = GruvboxGray245 -Color.Selection = GruvboxLight1 -Color.WhitespaceDuringSelection = GruvboxLight4 -Color.MouseUnderline = GruvboxDark0Hard -Color.CaretUnderline = GruvboxGray245 -Color.FuzzySearchLineHighlight = GruvboxDark0 -Color.ScrollbarBackground = GruvboxLight2 -Color.ScrollbarScroller = GruvboxLight1 -Color.ScrollbarScrollerSelected = GruvboxLight0Hard -Color.TitleBarText = GruvboxDark2 -Color.TitleBarBackground = GruvboxLight1 -Color.TitleBarActiveBackground = 0xfefefefe -Color.TitleBarSelection = GruvboxLight3 -Color.ResizerBackground = GruvboxLight0Hard -Color.ResizerOutline = GruvboxLight3 -Style = {} -Style.WaitForEvents = 1 -Style.DrawLineNumbers = 1 -Style.DrawScrollbar = 1 -Style.IndentSize = 4 -Style.FontSize = 15 -Style.FontFilter = 0 -Style.Font = GetExeDir().."/CascadiaMono.ttf" -Style.VCVarsall = "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat" -Style.TrimWhitespaceOnSave = true -Style.ClangFormatOnSave = false - -if OS_WINDOWS then - INTERNET_BROWSER = '"C:/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe"' -else - INTERNET_BROWSER = "firefox" -end -OS_WINDOWS = 0 -OS_UNIX = 1 - -SDLK_CTRL = 1073742048 -SDLK_PAGE_DOWN = 1073741902 -SDLK_PAGE_UP = 1073741899 -SDLK_DOWN = 1073741905 -- 0x40000051 -SDLK_UP = 1073741906 -- 0x40000052u -SDLK_RIGHT = 1073741903 -SDLK_LEFT = 1073741904 -SDLK_Q = 113 -SDLK_BACKSLASH = 0x5c -SDLK_RETURN = 13 - -SDLK_EQUALS = 0x0000003d -SDLK_MINUS = 0x0000002d - -SDLK_F1 = 0x4000003a -SDLK_F2 = 0x4000003b -SDLK_F3 = 0x4000003c -SDLK_F4 = 0x4000003d -SDLK_F5 = 0x4000003e -SDLK_F6 = 0x4000003f -SDLK_F7 = 0x40000040 -SDLK_F8 = 0x40000041 -SDLK_F9 = 0x40000042 -SDLK_F10 = 0x40000043 -SDLK_F11 = 0x40000044 -SDLK_F12 = 0x40000045 - -SDLK_A = 0x00000061 -SDLK_B = 0x00000062 -SDLK_C = 0x00000063 -SDLK_D = 0x00000064 -SDLK_E = 0x00000065 -SDLK_F = 0x00000066 -SDLK_G = 0x00000067 -SDLK_H = 0x00000068 -SDLK_I = 0x00000069 -SDLK_J = 0x0000006a -SDLK_K = 0x0000006b -SDLK_L = 0x0000006c -SDLK_M = 0x0000006d -SDLK_N = 0x0000006e -SDLK_O = 0x0000006f -SDLK_P = 0x00000070 -SDLK_Q = 0x00000071 -SDLK_R = 0x00000072 -SDLK_S = 0x00000073 -SDLK_T = 0x00000074 -SDLK_U = 0x00000075 -SDLK_V = 0x00000076 -SDLK_W = 0x00000077 -SDLK_X = 0x00000078 -SDLK_Y = 0x00000079 -SDLK_Z = 0x0000007a - -VERTICAL = 1 -HORIZONTAL = 2 - -function IsAlpha(a) - if a == nil then - return false - end - local x = string.byte(a) - local result = (x >= string.byte('a') and x <= string.byte('z')) or (x >= string.byte('A') and x <= string.byte('Z')) - return result -end - -function SkipLineAndColumn(s) - local line, col = "-1", "-1" - - function parse_line_and_column(line_and_col, delimiter) - ic, jc = line_and_col:find(delimiter) - line = line_and_col:sub(1, ic - 1) - col = line_and_col:sub(ic + 1) - return line, col - end - - do -- :line:column - local i, j = s:find("^:%d+:%d+") - if i then - skip_pattern = s:sub(j + 1) - line, col = parse_line_and_column(s:sub(2, j), ":") - return line, col, skip_pattern - end - end - - do -- :line - local i, j = s:find("^:%d+") - if i then - skip_pattern = s:sub(j + 1) - line = s:sub(2, j) - return line, col, skip_pattern - end - end - - do -- (line,column) - local i, j = s:find("^%(%d+,%d+%)") - if i then - skip_pattern = s:sub(j + 1) - line, col = parse_line_and_column(s:sub(2, j - 1), ",") - return line, col, skip_pattern - end - end - - do -- (line) - local i, j = s:find("^%(%d+%)") - if i then - skip_pattern = s:sub(j + 1) - line = s:sub(2, j - 1) - return line, col, skip_pattern - end - end - - return line, col, s -end - -function SkipSlashes(s) - found_slash = false - while s:sub(1,1) == '/' or s:sub(1,1) == '\\' do - s = s:sub(2) - found_slash = true - end - return s, found_slash -end - -function SkipDrive(s) - local i, j = s:find("^%a:") - if not i then - return s, nil, true - end - - local drive = s:sub(i, j) - local new_s = s:sub(j + 1) - - new_s, found_slash = SkipSlashes(new_s) - if not found_slash then - return s, drive, false - end - - return new_s, drive, true -end - -function WindowsSkipPathCell(s) - local i, j = s:find("^[%w_%.-% +]+") - if not i then return s, nil, false end - - local word = s:sub(i, j) - local new_s = s:sub(j + 1) - local new_s, found_slash = SkipSlashes(new_s) - - return new_s, word, found_slash -end - -function WindowsSkipPath(s) - local input_s = s - local s, drive, ok = SkipDrive(s) - if not ok then return s end - - local cells = {} - if drive ~= nil then - table.insert(cells, drive) - end - - while true do - s, word, slash_eaten = WindowsSkipPathCell(s) - if word then cells[#cells + 1] = word end - if not slash_eaten then break end - end - - if #cells == 0 then return s end - - local skip_size = input_s:len() - s:len() - local path = input_s:sub(1, skip_size) - return s, path, drive, cells -end - -function MatchWindowsPath(_s, meta) - local s, file_path, drive = WindowsSkipPath(_s) - - if not file_path and FileExists(drive) then - return {kind = "text", file_path = drive, line = line, col = col} - end - - if not file_path then - return nil - end - - if not drive then - local d = GetMainDir() - file_path = d..'/'..file_path - end - local line, col, s = SkipLineAndColumn(s) - - local exists = FileExists(file_path) or BufferExists(file_path) - if not exists then return nil end - - return {kind = "text", file_path = file_path, line = line, col = col} -end - -function MatchUnixPath(s, meta) - local i, j = s:find("^[%w_%.-% %/]+") - local path = s:sub(i, j) - local rest = s:sub(j + 1, -1) - local line, col, s = SkipLineAndColumn(rest) - - return {kind = "text", file_path = path, line = line, col = col} -end - -if OS_VALUE == OS_WINDOWS then - MatchPath = MatchWindowsPath -else - MatchPath = MatchUnixPath -end - -function MatchGitCommit(s, meta) - local i, j = string.find(s, "^commit ([a-zA-Z0-9]+)") - if i then - s = s:sub(8) - local command = "git --no-pager show "..s - return {kind = "exec", cmd = command, working_dir = GetMainDir()} - end - return nil -end - -function MatchURL(s, meta) - local i, j = string.find(s, "^https://") - if i then - return {kind = "exec_console", cmd = INTERNET_BROWSER.." "..s, working_dir = GetMainDir()} - end - return nil -end - -function MatchGotoBuild(s, meta) - if meta ~= "goto_build" then - return nil - end - - local windows_path = IsAlpha(s:sub(1,1)) and s:sub(2,2) == ':' - local windows_rela = s:sub(1,1) == '.' and s:sub(2,2) == '\\' - local unix_path = s:sub(1,1) == '/' - local unix_rela = s:sub(1,1) == '.' and s:sub(2,2) == '/' - - if not windows_path and not windows_rela and not unix_path and not unix_rela then - return {kind = "skip"} - end - - return nil -end - -function MatchExec(s, meta) - if meta ~= "exec" then - return nil - end - - if s:match("^%$") then - Print(""); - return {kind = "exec_console", cmd = s:sub(2, -1), working_dir = GetMainDir()} - end - - if s:match(".exe$") or s:match(".bat$") or s:match(".sh$") then - Print(""); - return {kind = "exec_console", cmd = s, working_dir = GetMainDir()} - end - - Eval(s) - return {kind = "skip"} -end - -BuiltinOnOpenMatchers = { - MatchPath, - MatchGitCommit, - MatchURL, - - MatchGotoBuild, - - MatchExec, -} -OnOpenMatchers = BuiltinOnOpenMatchers - -function OnOpen(path, meta) - for i = #OnOpenMatchers,1,-1 do - rule = OnOpenMatchers[i] - result = rule(path, meta) - if result then - return result - end - end - return nil -end - -Coroutines = {} -function AddCo(f) - local i = #Coroutines + 1 - Coroutines[i] = coroutine.create(f) - coroutine.resume(Coroutines[i]) - return Coroutines[i] -end - -function OnUpdate(e) - local new_co_list = {} - for key, co in pairs(Coroutines) do - local status = coroutine.status(co) - if status ~= "dead" then - coroutine.resume(co, e) - new_co_list[#new_co_list + 1] = co - end - end - Coroutines = new_co_list -end - - -function KeybindsBasic(e) - if e.key == SDLK_F and e.ctrl == 1 and e.shift == 1 then - C("git -C "..GetMainDir().." grep -n "..GetLoadWord().." :/") - return true - end - return false -end - -FKey = {"build.bat", "", "", "", "", "", "", "", "", "", ToggleFullscreen, ""} -FKeySDLK = {SDLK_F1, SDLK_F2, SDLK_F3, SDLK_F4, SDLK_F5, SDLK_F6, SDLK_F7, SDLK_F8, SDLK_F9, SDLK_F10, SDLK_F11, SDLK_F12} - -if OS_VALUE == OS_WINDOWS then - FKey[1] = "build.bat" -else - FKey[1] = "./build.sh" -end - -function KeybindsFKeys(e) - for i = #FKey,1,-1 do - if FKey[i] ~= "" then - if e.key == FKeySDLK[i] then - local cmdline = FKey[i] - if type(cmdline) == "function" then - cmdline = FKey[i]() - end - if cmdline ~= nil then - Cmd { working_dir = GetWorkDir(), kind = "console", cmd = cmdline } - end - return true - end - end - end - return false -end - -BuiltinOnCommandCallbacks = { - KeybindsBasic, - KeybindsFKeys, -} -OnCommandCallbacks = BuiltinOnCommandCallbacks - -function OnCommand(e) - for i = #OnCommandCallbacks,1,-1 do - on_command = OnCommandCallbacks[i] - local result = on_command(e) - if result then - return true - end - end - return false -end - -function OnInit() -end - -function OnSave(buffer_id) - local dont_trim_lines_with_caret = false - ConvertLineEndingsToLF(buffer_id, dont_trim_lines_with_caret) - if Style.TrimWhitespaceOnSave then - TrimTrailingWhitespace(buffer_id, dont_trim_lines_with_caret) - end - - local name = GetBufferNameByID(buffer_id) - if Style.ClangFormatOnSave and (name:match(".c$") or name:match(".h$") or name:match(".cpp$") or name:match(".hpp$")) then - ApplyClangFormat(buffer_id) - end -end - -function IsCodeExclude(s, meta) - if s:match("/%.git$") or s:match("\\%.git$") or - s:match("%.exe$") or - s:match("%.bin$") or - s:match("%.obj$") or - s:match("%.o$") or - s:match("%.lib$") or - s:match("%.ilk$") or - s:match("%.cache$") or - s:match("%.exp$") or - s:match("%.pdb$") or - s:match("/external/") or s:match("\\external\\") - then - return false - end - return true -end - -BuiltinIsCodeMatchers = { - IsCodeExclude, -} -IsCodeMatchers = BuiltinIsCodeMatchers - -function IsCode(path, meta) - for i = #IsCodeMatchers,1,-1 do - rule = IsCodeMatchers[i] - result = rule(path, meta) - if result then - return result - end - end - return false -end -)=="; void ReloadStyle() { ColorText = GetColor("Text", ColorText); ColorLoadTextHighlight = GetColor("LoadTextHighlight", ColorLoadTextHighlight); diff --git a/src/text_editor/generated_config.cpp b/src/text_editor/generated_config.cpp new file mode 100644 index 0000000..9333f7f --- /dev/null +++ b/src/text_editor/generated_config.cpp @@ -0,0 +1,410 @@ +String BaseLuaConfig = R"==( +Style.TrimWhitespaceOnSave = true +Style.ClangFormatOnSave = false + +INTERNET_BROWSER = 'C:/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe' +OS_WINDOWS = 0 +OS_UNIX = 1 + +SDLK_CTRL = 1073742048 +SDLK_PAGE_DOWN = 1073741902 +SDLK_PAGE_UP = 1073741899 +SDLK_DOWN = 1073741905 -- 0x40000051 +SDLK_UP = 1073741906 -- 0x40000052u +SDLK_RIGHT = 1073741903 +SDLK_LEFT = 1073741904 +SDLK_Q = 113 +SDLK_BACKSLASH = 0x5c +SDLK_RETURN = 13 + +SDLK_EQUALS = 0x0000003d +SDLK_MINUS = 0x0000002d + +SDLK_F1 = 0x4000003a +SDLK_F2 = 0x4000003b +SDLK_F3 = 0x4000003c +SDLK_F4 = 0x4000003d +SDLK_F5 = 0x4000003e +SDLK_F6 = 0x4000003f +SDLK_F7 = 0x40000040 +SDLK_F8 = 0x40000041 +SDLK_F9 = 0x40000042 +SDLK_F10 = 0x40000043 +SDLK_F11 = 0x40000044 +SDLK_F12 = 0x40000045 + +SDLK_A = 0x00000061 +SDLK_B = 0x00000062 +SDLK_C = 0x00000063 +SDLK_D = 0x00000064 +SDLK_E = 0x00000065 +SDLK_F = 0x00000066 +SDLK_G = 0x00000067 +SDLK_H = 0x00000068 +SDLK_I = 0x00000069 +SDLK_J = 0x0000006a +SDLK_K = 0x0000006b +SDLK_L = 0x0000006c +SDLK_M = 0x0000006d +SDLK_N = 0x0000006e +SDLK_O = 0x0000006f +SDLK_P = 0x00000070 +SDLK_Q = 0x00000071 +SDLK_R = 0x00000072 +SDLK_S = 0x00000073 +SDLK_T = 0x00000074 +SDLK_U = 0x00000075 +SDLK_V = 0x00000076 +SDLK_W = 0x00000077 +SDLK_X = 0x00000078 +SDLK_Y = 0x00000079 +SDLK_Z = 0x0000007a + +VERTICAL = 1 +HORIZONTAL = 2 + +function IsAlpha(a) + if a == nil then + return false + end + local x = string.byte(a) + local result = (x >= string.byte('a') and x <= string.byte('z')) or (x >= string.byte('A') and x <= string.byte('Z')) + return result +end + +function SkipLineAndColumn(s) + local line, col = "-1", "-1" + + function parse_line_and_column(line_and_col, delimiter) + ic, jc = line_and_col:find(delimiter) + line = line_and_col:sub(1, ic - 1) + col = line_and_col:sub(ic + 1) + return line, col + end + + do -- :line:column + local i, j = s:find("^:%d+:%d+") + if i then + skip_pattern = s:sub(j + 1) + line, col = parse_line_and_column(s:sub(2, j), ":") + return line, col, skip_pattern + end + end + + do -- :line + local i, j = s:find("^:%d+") + if i then + skip_pattern = s:sub(j + 1) + line = s:sub(2, j) + return line, col, skip_pattern + end + end + + do -- (line,column) + local i, j = s:find("^%(%d+,%d+%)") + if i then + skip_pattern = s:sub(j + 1) + line, col = parse_line_and_column(s:sub(2, j - 1), ",") + return line, col, skip_pattern + end + end + + do -- (line) + local i, j = s:find("^%(%d+%)") + if i then + skip_pattern = s:sub(j + 1) + line = s:sub(2, j - 1) + return line, col, skip_pattern + end + end + + return line, col, s +end + +function SkipSlashes(s) + found_slash = false + while s:sub(1,1) == '/' or s:sub(1,1) == '\\' do + s = s:sub(2) + found_slash = true + end + return s, found_slash +end + +function SkipDrive(s) + local i, j = s:find("^%a:") + if not i then + return s, nil, true + end + + local drive = s:sub(i, j) + local new_s = s:sub(j + 1) + + new_s, found_slash = SkipSlashes(new_s) + if not found_slash then + return s, drive, false + end + + return new_s, drive, true +end + +function WindowsSkipPathCell(s) + local i, j = s:find("^[%w_%.-% +]+") + if not i then return s, nil, false end + + local word = s:sub(i, j) + local new_s = s:sub(j + 1) + local new_s, found_slash = SkipSlashes(new_s) + + return new_s, word, found_slash +end + +function WindowsSkipPath(s) + local input_s = s + local s, drive, ok = SkipDrive(s) + if not ok then return s end + + local cells = {} + if drive ~= nil then + table.insert(cells, drive) + end + + while true do + s, word, slash_eaten = WindowsSkipPathCell(s) + if word then cells[#cells + 1] = word end + if not slash_eaten then break end + end + + if #cells == 0 then return s end + + local skip_size = input_s:len() - s:len() + local path = input_s:sub(1, skip_size) + return s, path, drive, cells +end + +function MatchWindowsPath(_s, meta) + local s, file_path, drive = WindowsSkipPath(_s) + + if not file_path and FileExists(drive) then + return {kind = "text", file_path = drive, line = line, col = col} + end + + if not file_path then + return nil + end + + if not drive then + local d = GetMainDir() + file_path = d..'/'..file_path + end + local line, col, s = SkipLineAndColumn(s) + + local exists = FileExists(file_path) or BufferExists(file_path) + if not exists then return nil end + + return {kind = "text", file_path = file_path, line = line, col = col} +end + +function MatchUnixPath(s, meta) + local i, j = s:find("^[%w_%.-% %/]+") + local path = s:sub(i, j) + local rest = s:sub(j + 1, -1) + local line, col, s = SkipLineAndColumn(rest) + Print(path, rest, line, col) + + return {kind = "text", file_path = path, line = line, col = col} +end + +if OS_VALUE == OS_WINDOWS then + MatchPath = MatchWindowsPath +else + MatchPath = MatchUnixPath +end + +function MatchGitCommit(s, meta) + local i, j = string.find(s, "^commit ([a-zA-Z0-9]+)") + if i then + s = s:sub(8) + local command = "git --no-pager show "..s + return {kind = "exec", cmd = command, working_dir = GetMainDir()} + end + return nil +end + +function MatchURL(s, meta) + local i, j = string.find(s, "^https://") + if i then + return {kind = "exec_console", cmd = '"'..INTERNET_BROWSER..'" '..s, working_dir = GetMainDir()} + end + return nil +end + +function MatchGotoBuild(s, meta) + if meta ~= "goto_build" then + return nil + end + + local windows_path = IsAlpha(s:sub(1,1)) and s:sub(2,2) == ':' + local windows_rela = s:sub(1,1) == '.' and s:sub(2,2) == '\\' + local unix_path = s:sub(1,1) == '/' + local unix_rela = s:sub(1,1) == '.' and s:sub(2,2) == '/' + + if not windows_path and not windows_rela and not unix_path and not windows_rela then + return {kind = "skip"} + end + + return nil +end + +function MatchExec(s, meta) + if meta ~= "exec" then + return nil + end + + if s:match(".exe$") or s:match(".bat$") or s:match(".sh$") then + return {kind = "exec_console", cmd = s, working_dir = GetMainDir()} + end + + if s:match("^%$") then + Print(s:sub(2, -1)) + return {kind = "exec_console", cmd = s:sub(2, -1), working_dir = GetMainDir()} + end + + Eval(s) + return {kind = "skip"} +end + +BuiltinOnOpenMatchers = { + MatchPath, + MatchGitCommit, + MatchURL, + + MatchGotoBuild, + + MatchExec, +} +OnOpenMatchers = BuiltinOnOpenMatchers + +function OnOpen(path, meta) + for i = #OnOpenMatchers,1,-1 do + rule = OnOpenMatchers[i] + result = rule(path, meta) + if result then + return result + end + end + return nil +end + +Coroutines = {} +function AddCo(f) + local i = #Coroutines + 1 + Coroutines[i] = coroutine.create(f) + coroutine.resume(Coroutines[i]) + return Coroutines[i] +end + +function OnUpdate(e) + local new_co_list = {} + for key, co in pairs(Coroutines) do + local status = coroutine.status(co) + if status ~= "dead" then + coroutine.resume(co, e) + new_co_list[#new_co_list + 1] = co + end + end + Coroutines = new_co_list +end + + +function KeybindsBasic(e) + if e.key == SDLK_F and e.ctrl == 1 and e.shift == 1 then + C("git grep -n "..GetLoadWord().." :/") + return true + end + return false +end + +FKey = {"build.bat", "", "", "", "", "", "", "", "", "", "", ""} +FKeySDLK = {SDLK_F1, SDLK_F2, SDLK_F3, SDLK_F4, SDLK_F5, SDLK_F6, SDLK_F7, SDLK_F8, SDLK_F9, SDLK_F10, SDLK_F11, SDLK_F12} + +function KeybindsFKeys(e) + for i = #FKey,1,-1 do + if FKey[i] ~= "" then + if e.key == FKeySDLK[i] then + local cmdline = FKey[i] + if type(cmdline) == "function" then cmdline = FKey[i]() end + Cmd { working_dir = GetWorkDir(), kind = "console", cmd = cmdline } + return true + end + end + end + return false +end + +BuiltinOnCommandCallbacks = { + KeybindsBasic, + KeybindsFKeys, +} +OnCommandCallbacks = BuiltinOnCommandCallbacks + +function OnCommand(e) + for i = #OnCommandCallbacks,1,-1 do + on_command = OnCommandCallbacks[i] + local result = on_command(e) + if result then + return true + end + end + return false +end + +function OnInit() +end + +function OnSave(buffer_id) + local dont_trim_lines_with_caret = false + ConvertLineEndingsToLF(buffer_id, dont_trim_lines_with_caret) + if Style.TrimWhitespaceOnSave then + TrimTrailingWhitespace(buffer_id, dont_trim_lines_with_caret) + end + + local name = GetBufferNameByID(buffer_id) + if Style.ClangFormatOnSave and (name:match(".c$") or name:match(".h$") or name:match(".cpp$") or name:match(".hpp$")) then + ApplyClangFormat(buffer_id) + end +end + +function IsCodeExclude(s, meta) + if s:match("/.git$") or s:match("\\.git$") or + s:match(".exe$") or + s:match(".bin$") or + s:match(".obj$") or + s:match(".o$") or + s:match(".lib$") or + s:match(".ilk$") or + s:match(".cache$") or + s:match(".exp$") or + s:match(".pdb$") or + s:match("/external/") or s:match("\\external\\") + then + return false + end + return true +end + +BuiltinIsCodeMatchers = { + IsCodeExclude, +} +IsCodeMatchers = BuiltinIsCodeMatchers + +function IsCode(path, meta) + for i = #IsCodeMatchers,1,-1 do + rule = IsCodeMatchers[i] + result = rule(path, meta) + if result then + return result + end + end + return false +end +)=="; diff --git a/src/text_editor/lua_api.cpp b/src/text_editor/lua_api.cpp index 80e8aac..be7a989 100644 --- a/src/text_editor/lua_api.cpp +++ b/src/text_editor/lua_api.cpp @@ -417,22 +417,32 @@ void InitLuaConfig() { } // Init user config + Buffer *lua_buffer = NULL; + Scratch scratch; - String lua_config_path = Format(scratch, "%.*s/init.lua", FmtString(ConfigDir)); - -#if DEBUG_BUILD - // WARNING! Delete config to make sure we are running this code more frequently - SDL_RemovePath(lua_config_path.data); - ReportConsolef("deleting config for debug purposes!"); -#endif - - Buffer *lua_buffer = BufferOpenFile(lua_config_path); - if (lua_buffer->len == 0) { - String16 string16 = ToString16(scratch, BaseLuaConfig); - RawReplaceText(lua_buffer, {}, string16); - ReportConsolef("no config at: %.*s - creating config buffer", FmtString(lua_config_path)); + String lua_config_exe = Format(scratch, "%.*s/init.lua", FmtString(GetExeDir(scratch))); + if (FileExists(lua_config_exe)) { + lua_buffer = BufferOpenFile(lua_config_exe); } + if (lua_buffer == NULL) { + String lua_config_remote = Format(scratch, "%.*s/init.lua", FmtString(ConfigDir)); +// #if DEBUG_BUILD +// // WARNING! Delete config to make sure we are running this code more frequently +// SDL_RemovePath(lua_config_remote.data); +// ReportConsolef("deleting config for debug purposes!"); +// #endif + lua_buffer = BufferOpenFile(lua_config_remote); + if (lua_buffer->len == 0) { + String16 string16 = ToString16(scratch, BaseLuaConfig); + RawReplaceText(lua_buffer, {}, string16); + ReportConsolef("no config at: %.*s - creating config buffer", FmtString(lua_config_remote)); + } + } + + + + LuaConfigBuffer = lua_buffer; ReloadLuaConfigs(true); CallLuaOnInit(); diff --git a/src/text_editor/text_editor.cpp b/src/text_editor/text_editor.cpp index e33a0f7..715fdfe 100644 --- a/src/text_editor/text_editor.cpp +++ b/src/text_editor/text_editor.cpp @@ -45,6 +45,7 @@ int FullScreenPositionX, FullScreenPositionY; #include "title_bar.cpp" #include "lua_api_generated.cpp" +#include "generated_config.cpp" #include "generated.cpp" #include "window_draw.cpp" diff --git a/src/text_editor/todo.txt b/src/text_editor/todo.txt index e6e56ac..5ce6708 100644 --- a/src/text_editor/todo.txt +++ b/src/text_editor/todo.txt @@ -1,5 +1,7 @@ -- DESIGN We want a better workflow, one init.lua that would be applied automatically and then baked into the executable also - How to decrease build complexity? Should the variables be used maybe better to do the lookup? +- DESIGN Config file versions, when loading should be checked, at the top of the file, what to do when old version? +BUILD Collapse the separate unit (unix, win32) into single build - DESIGN Prev search change hotkey to Ctrl+Shift instead of Alt+N - DESIGN Moving vertically between splits, which keys??? @@ -9,6 +11,7 @@ - FEATURE KillConsole, or maybe some window targetting but how?? - FEATURE SaveAll dirty files which are saved on disk already but dirty +- ISSUE Cursor changes every frame and it causes stutter on screen NOT GOOD! - ISSUE I hit a case where GC tried deleting a buffer which was not attached to the buffer list, it had zeroed next, prev. It happened after iterating through directories using the ctrl + period - ISSUE Ctrl + L or Exec shouldn't involve the last new line!