Index: README.md ================================================================== --- README.md +++ README.md @@ -1,33 +1,229 @@ -# ScalpiEditor - text editor for linux terminals (console) writed from zig language. - ⚠️ display only ansi symbols - ⚠️ no undo/redo - ⚠️ does not offer to save the file on exit (until it stabilizes) -### download: -[latest stable](https://chiselapp.com/user/sergey6661313/repository/ScalpiEditor/info/0e61348c984cbb77) -### usage: - ScalpiEditor FILENAME -tip: use f1 for help inside program -### If you're lucky you can try compile latest unstable version: - fossil clone https://chiselapp.com/user/sergey6661313/repository/ScalpiEditor ScalpiEditor.fossil - mkdir ScalpiEditor - cd ScalpiEditor - fossil open ../ScalpiEditor.fossil - zig build # use zig version 0.10 https://ziglang.org/download/ -and find binary in "zig-out/bin"... -#### you may rename and copy binary to "~/bin/se" like this: - cp ./zig-out/bin/ScalpiEditor ~/bin/se -#### and add this lines to config (".bashrc" file for bash) for easy use: - export EDITOR="~/bin/se" - export PATH="~/bin:$PATH" -### videos: -[version 0.2](https://www.youtube.com/watch?v=51ao2416ioE&t=60s) -### to support me: - monero: 87T7qGbATrM3a6BrDyeCjQQfNWtUu3iZbHVBMC6WmEbNNE13QrrtKhBbe4vF58NR8PTFdYk2SozcHexX4Q69jbdQAsrsP7B -### old releases on github: [sergey6661313/ScalpiEditor/releases](https://github.com/sergey6661313/ScalpiEditor/releases) -### FAQ: - * why did I refuse to parse the colon in the file name? - In the linux operating system, files with a colon in the name are often created. - * nothing work. - Use only stable version, or green commits. - * mouse not work - Grab mouse - bad idea. I use scroling for view terminal history. +## licenze: + This code and its derivatives can be used under the following conditions: + - Do not attack other countries. + - Jerk off on public at least 1 time per day. + - maintain hygiene. + - check my other projects https://chiselapp.com/user/sergey6661313 + +## about: + # ScalpiEditor - ansi-only text editor + killer features: no. its just editor. + writed from zig language for linux terminals. + + Initially I wrote the editor exclusively in zig, but then I wanted to rewrite it to just C in future. + + error system: + zig: The error system in zig is good, but it does not help with segfaults. + I still have to look for the error with binary search, stupidly placing debugging in the program. + C: no error system - less asm output code. + + unwraping: + zig: I need stupid explicit casting or unwraping for "[*c]" and "?" + c: i can write "*ptr" or ptr[0] and its just work. + No matter to real pointer value - null or not. + and i can write "if (ptr) {...}" for just check it. + Moreover, in some libraries "-1" is sometimes returned as an error value instead of a pointer, + which completely breaks the innovation of mandatory null checks. + + tagged unions: + zig: Types like Tagged union are generally confusing. zig hust hided tag. + c: It is much easier to use structures with a EXPLICIT tag and data. + + ## Editor Functionality: + Handles input/output operations, including reading from and writing to the terminal. + Supports text manipulation features such as inserting, deleting, and navigating through text. + Includes clipboard operations, marking lines, and easy motion for quick navigation. + Provides functionality to fold and unfold sections of the text based on indentation. + Supports saving and loading files, including external copying using a temporary file. + Implements a macro recording and playback system for repetitive tasks. + Provides support for commentary highlighting and setting various font styles for text. (in src) + + ## Noteworthy Features + Easy Motion: A mode for quick navigation within the text using key shortcuts. + Macro Recording: Allows recording sequences of key presses to be replayed later. + Text Folding: Automatically folds sections of text based on indentation levels. + Clipboard Integration: Supports external clipboard operations via a temporary file. + + ## videos (not tutorials. deprecated. many keys remaped. But idea of navigating is showed...): + https://www.youtube.com/watch?v=8sJJOQeyOTE + https://www.youtube.com/watch?v=8qQlMbE8Zmw + https://www.youtube.com/watch?v=51ao2416ioE&t=60s + + ## main dev page: + https://chiselapp.com/user/sergey6661313/repository/ScalpiEditor/ + + ## Download src: + select version: + https://chiselapp.com/user/sergey6661313/repository/ScalpiEditor/ + just open file main.c/main.zig in repo and press download. + +## FAQ: + * pasta from system clipboard makes the text move apart + try change new_line mode: [alt] + [b] + try paste multiline text only in folded mode: [ctrl] + [e] + + * copy to file not work + copy to file copyid only cutted lines... + first clear "cut" buffer with [Alt] + [z] + then copy blocks with ctrl + c to "cut" buffer + and then use [Alt]+[c] + + * Why did I refuse to parse the colon in the file name? + In the linux operating system, files with a colon in the name are often created. + + * Nothing work or crash on start + try download earleer version by timeline in repo. i mark not work version as red. + Use terminal only with monospaced fonts. crazy fonts giving crazy resaults. + + * Does not offer to save the file on exit. + Idiot protection does not work, if the fool is used to pressing "y" on every programm. + + * Why i not support UTF? why display only ansi symbols? + just help me write this :)) + I search in network how to determine - terminal work with unicode or not. + And i not find how to check this. + Some times terminal work with unicode partially - how to check this? + + * no history + partialy undo work - only for current line. + the editor doesn't have to keep the whole history, it's a job for csv. + like fossil, git or any you want (jj is simpliest for this). + do not make many changes to the code at once. It's unhealthy. + + * how to open and close multiple files? + just use multiple tabs in your terminal. (if terminal can this) + or use multiple terminals (if you use graphical mode) + or use any terminal multiplexer. + and use [Alt]+[c] and [Alt]+[v] for copy paste + + * Mouse not work + I use scroling for view terminal history. + I don not ability to catch only buttons without catch scrolling. + +## to support me + with boosty: + https://boosty.to/cutloosedev + + with monero: + 87T7 qGbA TrM3 a6Br + DyeC jQQf NWtU u3iZ + bHVB MC6W mEbN NE13 + Qrrt KhBb e4vF 58NR + 8PTF dYk2 Sozc HexX + 4Q69 jbdQ Asrs P7B + +## additional tips for linux: + i use "sakura" terminal. There no work "ctrl+shift+left" key-sequence but other thing work norm. + previously i try terminals: zutty, kitty, alacritty, Terminology - all good (not perfect) work. + + ## you may rename and copy binary to "~/bin/se" like this: + cp ./main ~/bin/se + + ## and add this lines to config (".bashrc" file for bash) for easy use: + export EDITOR="~/bin/se" + export PATH="~/bin:$PATH" + +## additional tips for windows: + in windows i recommend use alacritty. + it does not overload the system. + but sometimes you have to use shift+ins instead of the usual ctrl+shift+v. + it can just freeze if change keyboar layout many times. Or just disable keys like "{". + + ## you can try add folder with bin file to system path like this: + + ## temporaly: + $env:path += ";$($pwd.Path)" + + ## temporally for your custom folder + $env:path += ";C:\TopSecret\Bin" + + ## or + $addPath = 'C:\TopSecret\Bin' + + ## or for not temporally: + [Environment]::SetEnvironmentVariable("Path", $env:Path + ";$($pwd.Path)", "User") + +## list of bindings: + warning! the operation of certain key combinations depends on the terminal and not on me. + if key combination not work try another terminal. + (for reference: in some programs all key combinations work, + not because their code is correct, but because they use dirty hacks. + For example, they intercept the keyboard through root access. + Such programs need to be installed into the system, instead of just copying. + I don't like installers - that won't happen in my text editor.) + + basic keys: + help [F1] + save [Ctrl] + [s] + exit [Ctrl] + [q] + + navigation: + use arrows for navigation + + enter block [Tab] + leave block [Esc] + go to start of line [Home] or [Ctrl] + [Shift] + [Left] + go to end of line [End] or [Ctrl] + [Shift] + [Right] + go to line from number [Ctrl] + [g] + go to left word [Ctrl] + [Left] + go to right word [Ctrl] + [Right] + go to prev block [Ctrl] + [up] + go to next block [Ctrl] + [Down] + + symbol interacting: + insert as prev [any symbol] + delete prev [BackSpace] + delete next [Del] + + lines/blocks interacting: + split line [Enter] + join lines [Ctrl] + [j] // also sometimes [Ctrl] + [enter] work. and you can try [num_enter] + move up [Alt] + [Up] // not work on some terminals... + move down [Alt] + [Down] + clear line [Shift] + [Del] + duplicate [Ctrl] + [d] + + word interactig: + delete current word: [ctrl] + [w] + copy current word to find buffer: [Alt] + [1] + + mark: + mark [Alt] + [m] + jump to mark [Alt] + [g] + move out current block [Alt] + [8] + move block outside mark [Alt] + [0] (only in folded mode) + move block inside mark [Alt] + [9] (only in folded mode) + move block before mark [Alt] + [0] + + macroses: + start record macro [F1] + stop record macro [F2] + play latest recorded macro [F3] + + also there are many buffers: + 1) buffer for blocks/lines: + cut [Ctrl] + [x] + copy [Ctrl] + [c] + paste [Ctrl] + [v] + discard cutted/coppied [Alt] + [z] + + 2) external buffer (file "clipboard.txt") + copy [Alt] + [c] + paste [Alt] + [v] + + 3) using buffer for finding text: + copy current word [Alt] + [1] + find prev: [Alt] + [2] + find next: [Alt] + [3] + paste [Alt] + [4] + replace finded: [Alt] + [6] // for replace need cursor placed on start of finding text + + change mode: + fold/unfold [Ctrl] + [e] + edit finding buffer [Ctrl] + [f] + edit replace buffer: [Alt] + [5] + auto space [alt] + [b] + + easy motion: + horizontal: [Alt] + [q] + vertical: [Alt] + [e] DELETED README.md.bak Index: README.md.bak ================================================================== --- README.md.bak +++ /dev/null DELETED build.zig Index: build.zig ================================================================== --- build.zig +++ /dev/null @@ -1,11 +0,0 @@ -const std = @import("std"); -pub fn build(b: *std.build.Builder) void { - var target = b.standardTargetOptions(.{}); - target.abi = .musl; - const mode = b.standardReleaseOptions(); - const exe = b.addExecutable("ScalpiEditor", "src/main.zig"); - exe.setTarget(target); - exe.setBuildMode(mode); - exe.linkLibC(); - exe.install(); -} ADDED main.c Index: main.c ================================================================== --- /dev/null +++ main.c @@ -0,0 +1,4988 @@ +// about + /* + licenze: + This code and its derivatives can be used under the following conditions: + - Do not attack other countries. + - Jerk off on public at least 1 time per day. + - Observe hygiene. + - check my other projects https://chiselapp.com/user/sergey6661313 + + about: + ScalpiEditor - ansi-only text editor for terminals. + killer features: no. its just editor. + + Compile: + this file is just part of zig version (for now) + current version used zig compiller for compile zig file. (unstructions inside zig file) + in future you can use any C compiller, but not now. + nevest C compillers is DUMB! + they insert thousands of checks of what I did not ask them to insert. Here is how you can avoid it: + -fno-stack-protector -fno-sanitize=undefined + also for debug use: + -Og -g + todo. alse try next keys for optimize size + -ffunction-sections -fdata-sections -Wl,--gc-sections + -nostdlib -Oz -Qn -m32 -static -s -N -Wl,--build-id=none -fno-asynchronous-unwind-tables + + to support me + with boosty: + https://boosty.to/cutloosedev + + with monero: + 87T7 qGbA TrM3 a6Br + DyeC jQQf NWtU u3iZ + bHVB MC6W mEbN NE13 + Qrrt KhBb e4vF 58NR + 8PTF dYk2 Sozc HexX + 4Q69 jbdQ Asrs P7B + + why i cancel use zig: + gabarages in output code. + + zig perfecly crash without printing stack trace in non standart situations. (main feature of zig) + Zig does not try fix console flags before print stack trace. + zig can crash to segfault like c. + + tagged enum does not sense. + c: tagged_enum.tag = ANOTHER_TAG; + zig: tagged_enum = .{.ANOTHER_TAG = tagged_enum.LAST_USED_TAG.data}; + + operator ".?" does not sense: + c: while(link) { i++; link = link->next; } + zig: while(link) |_| { i += 1; link = link.?.next; } + zig idiomatic: while(link) |unwrapped_link|{ i += 1; link = unwrapped_link.next; } + + nullable types are inconvenient. + c: if (link) i++; + zig idiomatic: if (link) |_| i += 1; + zig but C pointer: if (@intFromPtr(link) != @intFromPtr(c.NULL)) i += 1; + */ +// TODO + /* + remove name buffer_len. use buffer_max_size and buffer_used instead. + */ +// desctiptions + // # __AlignedPtr__ + /* its a virtual struct becouse C not have "anytype" type. + struct __AlignedPtr__ { + char gap[gap_size] // padding for aligning data. gap_size can be 0. + anytype your_data // <- the pointer that the alloc function returns will be pointed here. + uint8_t gap_size + } + */ + // AP - its hex like but use from 'a' to 'p' values for symbols + // __NetworkTcpHttpWebSocketHeader__ + // real struct of web socket header: + // fin_flag: u1 = 1, + // rsv: [3]u1 = .{0,0,0}, + // opcode: Opcode = .binary, // may be text + // mask_flag: u1 = 0, + // payload_len: u7 = 0, + // extended_payload_len: u16 or u64 or void (optional) + // masking_key: u64 or void (optional) + // 2 bytes (__NetworkTcpHttpWebSocketHeaderSmall__) header for sizes 1 ... 125 + // 4 bytes (__NetworkTcpHttpWebSocketHeaderMedium__) header for sizes 126 ... 65535 + // 10 bytes (__NetworkTcpHttpWebSocketHeaderLong__) header for sizes more than 65535 +// enums + // # __LoggerWriter__ + #define __LoggerWriter_toFallback__ 0 + #define __LoggerWriter_toFile__ 1 + #define __LoggerWriter_toConsole__ 2 + #define __LoggerWriter_toTerminal__ 3 + // # __MemTree_fix_counts_Action__ + #define __MemTree_fix_counts_Action_plus__ 'p' + #define __MemTree_fix_counts_Action_minus__ 'm' + // # __MemTree_fix_nested_Action__ + #define __MemTree_fix_nested_Action_plus__ 'p' + #define __MemTree_fix_nested_Action_minus__ 'm' + // # __OsNetworkTcpSocketConnectResult__ (char) + #define __OsNetworkTcpSocketConnectResult_error__ -1 + #define __OsNetworkTcpSocketConnectResult_inProgress__ 0 + #define __OsNetworkTcpSocketConnectResult_success__ 1 + // # __TargetMemoryType__ + #define __TargetMemoryType_endiansLittle__ 1 + #define __TargetMemoryType_endiansBig__ 2 + // # __TargetOs__ + #define __TargetOs_windows__ 1 + #define __TargetOs_linux__ 2 +// settings + // # __AppEditorLineLen_max__ + #define __AppEditorLineLen_max__ (1024 * 8) + // # __AppEditorTheme_arrows__ + #define __AppEditorTheme_arrows__ \ + __ConsoleAnsiOutputFontStyle_start__ \ + __ConsoleAnsiOutputFontStyle_unbold__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_bg_color_zero__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_color_yellow__ \ + __ConsoleAnsiOutputFontStyle_end__ + // # __AppEditorTheme_commentary__ + #define __AppEditorTheme_commentary__ \ + __ConsoleAnsiOutputFontStyle_start__ \ + __ConsoleAnsiOutputFontStyle_bg_color_zero__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_color_yellow__ \ + __ConsoleAnsiOutputFontStyle_end__ + // # __AppEditorTheme_current__ + #define __AppEditorTheme_current__ \ + __ConsoleAnsiOutputFontStyle_start__ \ + __ConsoleAnsiOutputFontStyle_bg_color_zero__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_color_light_green__ \ + __ConsoleAnsiOutputFontStyle_end__ + // # __AppEditorTheme_current_commentary__ + #define __AppEditorTheme_current_commentary__ \ + __ConsoleAnsiOutputFontStyle_start__ \ + __ConsoleAnsiOutputFontStyle_bg_color_zero__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_color_yellow__ \ + __ConsoleAnsiOutputFontStyle_end__ + // # __AppEditorTheme_current_disabled__ + #define __AppEditorTheme_current_disabled__ \ + __ConsoleAnsiOutputFontStyle_start__ \ + __ConsoleAnsiOutputFontStyle_bg_color_zero__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_color_light_green__ \ + __ConsoleAnsiOutputFontStyle_end__ + // # __AppEditorTheme_current_folded__ + #define __AppEditorTheme_current_folded__ \ + __ConsoleAnsiOutputFontStyle_start__ \ + __ConsoleAnsiOutputFontStyle_bold__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_bg_color_zero__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_color_light_green__ \ + __ConsoleAnsiOutputFontStyle_end__ + // # __AppEditorTheme_current_rune__ + #define __AppEditorTheme_current_rune__ \ + __ConsoleAnsiOutputFontStyle_start__ \ + __ConsoleAnsiOutputFontStyle_bg_color_zero__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_color_magenta__ \ + __ConsoleAnsiOutputFontStyle_end__ + // # __AppEditorTheme_disabled__ + #define __AppEditorTheme_disabled__ \ + __ConsoleAnsiOutputFontStyle_start__ \ + __ConsoleAnsiOutputFontStyle_bg_color_zero__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_color_magenta__ \ + __ConsoleAnsiOutputFontStyle_end__ + // # __AppEditorTheme_easy_motion__ + #define __AppEditorTheme_easy_motion__ \ + __ConsoleAnsiOutputFontStyle_start__ \ + __ConsoleAnsiOutputFontStyle_bg_color_zero__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_color_yellow__ \ + __ConsoleAnsiOutputFontStyle_end__ + // # __AppEditorTheme_folded__ + #define __AppEditorTheme_folded__ \ + __ConsoleAnsiOutputFontStyle_start__ \ + __ConsoleAnsiOutputFontStyle_bold__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_bg_color_zero__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_color_zero__ \ + __ConsoleAnsiOutputFontStyle_end__ + // # __AppEditorTheme_folded_arrows__ + #define __AppEditorTheme_folded_arrows__ \ + __ConsoleAnsiOutputFontStyle_start__ \ + __ConsoleAnsiOutputFontStyle_bold__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_bg_color_gray__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_color_yellow__ \ + __ConsoleAnsiOutputFontStyle_end__ + // # __AppEditorTheme_headers__ + #define __AppEditorTheme_headers__ \ + __ConsoleAnsiOutputFontStyle_start__ \ + __ConsoleAnsiOutputFontStyle_bold__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_bg_color_zero__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_color_cyan__ \ + __ConsoleAnsiOutputFontStyle_end__ + // # __AppEditorTheme_notification__ + #define __AppEditorTheme_notification__ \ + __ConsoleAnsiOutputFontStyle_start__ \ + __ConsoleAnsiOutputFontStyle_bg_color_zero__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_color_red__ \ + __ConsoleAnsiOutputFontStyle_end__ + // # __AppEditorTheme_reset__ + #define __AppEditorTheme_reset__ \ + __ConsoleAnsiOutputFontStyle_start__ \ + __ConsoleAnsiOutputFontStyle_reset__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_bg_color_zero__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_color_zero__ \ + __ConsoleAnsiOutputFontStyle_end__ + // # __AppEditorViewsEasyMotionHorizontal_step__ + #define __AppEditorViewsEasyMotionHorizontal_step__ 3 + // # __AppEditorViewsEasyMotionVertical_step__ + #define __AppEditorViewsEasyMotionVertical_step__ 2 + // # __App_expectedFps__ + #define __App_expectedFps__ 30 + // # __OsFilePathLen_max__ + #define __OsFilePathLen_max__ 1024 + // # __OsNetworkTcpHttp_maxHeaders__ + #define __OsNetworkTcpHttp_maxHeaders__ 48 + // # __OsNetworkTcp_maxClientCount__ + #define __OsNetworkTcp_maxClientCount__ 8 + // # __TerminalInput_size__ + #define __TerminalInput_size__ 32 + // # __target_memoryType__ + #define __target_memoryType__ __TargetMemoryType_endiansLittle__ + // # __target_os__ + //#define __target_os__ __TargetOs_linux__ + #ifndef __target_os__ + #ifdef _WIN32 + #define __target_os__ __TargetOs_windows__ + #elif defined(__linux__) + #define __target_os__ __TargetOs_linux__ + #endif + #endif + // # __with_network__ + #define __with_network__ 0 +// macro + // types and structs + // # __Size__ + #define __Size__ __Type_getSize__(size_t) + // # __Ptr__ + #define __Ptr__ __Type_getSize__(uintptr_t) + // # __Slice__ + // # __Slice_ptr__ + #define __SlicePtr__ __Ptr__ + #define __Slice_ptr__ 0 + // # __Slice_len__ + #define __SliceLen__ __Size__ + #define __Slice_len__ __Align_up__(__Slice_ptr__ + __SlicePtr__, __Size__) + // c + // # __Addr_fromPtr__ + #define __Addr_fromPtr__(ptr) ((uintptr_t)(ptr)) + // # __Align_up__ + #define __Align_up__(offset, align) (((offset) + (align) - 1) & ~((align) - 1)) + // # __CText_len__ + #define __CText_len__(str) (__arrayLen__(str) - 1) + // # __CText_write__ + #define __CText_write__(buffer, text) (__Mem_copy__(buffer, text, __CText_len__(text)), __CText_len__(text)) + // # __Instance_fromPtr__ + #define __Instance_fromPtr__(ptr) (*(ptr)) + // # __Struct_getFieldOffset__ + #define __Struct_getFieldOffset__(type, field) (__Addr_fromPtr__(__TypedPtr_getFieldPtr__(__TypedPtr_virtual__(type), field))) + // # __Type_getAlign__ + #define __Type_getAlign__(type) (__Struct_getFieldOffset__(struct {char c; type t;}, t)) + // # __Type_getSize__ + #define __Type_getSize__(type) (__Struct_getFieldOffset__(struct {type t; char c;}, c)) + // # __TypedPtr_fromAddr__ + #define __TypedPtr_fromAddr__(type, addr) ((type*)(addr)) + // # __TypedPtr_getFieldPtr__ + #define __TypedPtr_getFieldPtr__( ptr, field_name) (&(ptr)->field_name) + // # __TypedPtr_getParentPtrFromFieldPtr__ + #define __TypedPtr_getParentPtrFromFieldPtr__( type, field_name, field_ptr) (__TypedPtr_fromAddr__(type, __Addr_fromPtr__((field_ptr)) - __Struct_getFieldOffset__(type, field_name))) + // # __TypedPtr_virtual__ + #define __TypedPtr_virtual__( type) (__TypedPtr_fromAddr__(type, 0)) + // # __arrayLen__ + #define __arrayLen__( array) (sizeof((array)) / sizeof((array[0]))) + // # __len_and_text__ + #define __len_and_text__( str) __CText_len__(str), str + // # __text_and_len__ + #define __text_and_len__( str) str, __CText_len__(str) + // # and + #define and && + // # or + #define or || + // os + // # __OsConsoleOutput_writeCText__ + #define __OsConsoleOutput_writeCText__( ctx, text) \ + __OsConsoleOutput_write__( ctx, text, __CText_len__(text)) + // # __OsFile_readToAny__ + #define __OsFile_readToAny__( file, buffer, buffer_len, offset ) \ + __OsFile_readToBuffer__( file, (char*) (buffer), buffer_len, offset ) + // # __OsMem_allocAny__ + #define __OsMem_allocAny__( ret_data_addr, size) \ + __OsMem_alloc__( (uintptr_t*) (ret_data_addr), size) + // # __OsMem_freeAny__ + #define __OsMem_freeAny__( ret_data_addr) \ + __OsMem_free__( (uintptr_t) (ret_data_addr)) + // # __OsNetworkTcp_maxAllowedListenPort__ + #define __OsNetworkTcp_maxAllowedListenPort__ 49151 + // Os specific + #if __target_os__ == __TargetOs_windows__ + #define WSA_SUCCESS 0 + #elif __target_os__ == __TargetOs_linux__ + #else + #error "__target_os__ not implemented" + #endif + // # breakpoint + #if __target_os__ == __TargetOs_windows__ + #define breakpoint() DebugBreak() + #elif __target_os__ == __TargetOs_linux__ + #define breakpoint() raise(SIGTRAP) + #else + #error "__target_os__ not implemented" + #endif + // lib + // # Sha1_digest_length + #define Sha1_digest_length 20 + // # __AlignedPtr_allocAny__ + #define __AlignedPtr_allocAny__( ret_data_addr, mem_align, size) \ + __AlignedPtr_alloc__( (uintptr_t*) (ret_data_addr), mem_align, size) + // # __AlignedPtr_freeAny__ + #define __AlignedPtr_freeAny__( ret_data_addr, size) \ + __AlignedPtr_free__( (uintptr_t) (ret_data_addr), size) + // # __ConsoleAnsiInputKey_alt_0__ + #define __ConsoleAnsiInputKey_alt_0__ ('0' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_1__ + #define __ConsoleAnsiInputKey_alt_1__ ('1' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_2__ + #define __ConsoleAnsiInputKey_alt_2__ ('2' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_3__ + #define __ConsoleAnsiInputKey_alt_3__ ('3' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_4__ + #define __ConsoleAnsiInputKey_alt_4__ ('4' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_5__ + #define __ConsoleAnsiInputKey_alt_5__ ('5' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_6__ + #define __ConsoleAnsiInputKey_alt_6__ ('6' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_7__ + #define __ConsoleAnsiInputKey_alt_7__ ('7' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_8__ + #define __ConsoleAnsiInputKey_alt_8__ ('8' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_9__ + #define __ConsoleAnsiInputKey_alt_9__ ('9' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_M__ + #define __ConsoleAnsiInputKey_alt_M__ ('M' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_N__ + #define __ConsoleAnsiInputKey_alt_N__ ('N' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt__ + #define __ConsoleAnsiInputKey_alt__ (1 << 11) + // # __ConsoleAnsiInputKey_alt_a__ + #define __ConsoleAnsiInputKey_alt_a__ ('a' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_apostrophe__ + #define __ConsoleAnsiInputKey_alt_apostrophe__ ('`' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_b__ + #define __ConsoleAnsiInputKey_alt_b__ ('b' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_c__ + #define __ConsoleAnsiInputKey_alt_c__ ('c' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_close_bracket__ + #define __ConsoleAnsiInputKey_alt_close_bracket__ (']' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_comma__ + #define __ConsoleAnsiInputKey_alt_comma__ (',' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_d__ + #define __ConsoleAnsiInputKey_alt_d__ ('d' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_dot__ + #define __ConsoleAnsiInputKey_alt_dot__ ('.' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_down__ + #define __ConsoleAnsiInputKey_alt_down__ (__ConsoleAnsiInputKey_down__ + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_e__ + #define __ConsoleAnsiInputKey_alt_e__ ('e' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_f__ + #define __ConsoleAnsiInputKey_alt_f__ ('f' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_g__ + #define __ConsoleAnsiInputKey_alt_g__ ('g' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_h__ + #define __ConsoleAnsiInputKey_alt_h__ ('h' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_i__ + #define __ConsoleAnsiInputKey_alt_i__ ('i' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_j__ + #define __ConsoleAnsiInputKey_alt_j__ ('j' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_k__ + #define __ConsoleAnsiInputKey_alt_k__ ('k' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_l__ + #define __ConsoleAnsiInputKey_alt_l__ ('l' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_left__ + #define __ConsoleAnsiInputKey_alt_left__ (__ConsoleAnsiInputKey_left__ + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_m__ + #define __ConsoleAnsiInputKey_alt_m__ ('m' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_n__ + #define __ConsoleAnsiInputKey_alt_n__ ('n' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_o__ + #define __ConsoleAnsiInputKey_alt_o__ ('o' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_open_bracket__ + #define __ConsoleAnsiInputKey_alt_open_bracket__ ('[' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_p__ + #define __ConsoleAnsiInputKey_alt_p__ ('p' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_q__ + #define __ConsoleAnsiInputKey_alt_q__ ('q' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_r__ + #define __ConsoleAnsiInputKey_alt_r__ ('r' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_right__ + #define __ConsoleAnsiInputKey_alt_right__ (__ConsoleAnsiInputKey_right__ + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_s__ + #define __ConsoleAnsiInputKey_alt_s__ ('s' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_semicolon__ + #define __ConsoleAnsiInputKey_alt_semicolon__ (';' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_t__ + #define __ConsoleAnsiInputKey_alt_t__ ('t' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_u__ + #define __ConsoleAnsiInputKey_alt_u__ ('u' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_up__ + #define __ConsoleAnsiInputKey_alt_up__ (__ConsoleAnsiInputKey_up__ + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_v__ + #define __ConsoleAnsiInputKey_alt_v__ ('v' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_w__ + #define __ConsoleAnsiInputKey_alt_w__ ('w' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_x__ + #define __ConsoleAnsiInputKey_alt_x__ ('x' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_y__ + #define __ConsoleAnsiInputKey_alt_y__ ('y' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_alt_z__ + #define __ConsoleAnsiInputKey_alt_z__ ('z' + __ConsoleAnsiInputKey_alt__) + // # __ConsoleAnsiInputKey_ascii_ctrl__ + #define __ConsoleAnsiInputKey_ascii_ctrl__ (-'a' + 1) /* do not use externally */ + // # __ConsoleAnsiInputKey_back_space__ + #define __ConsoleAnsiInputKey_back_space__ 127 /* sometime delete */ + // # __ConsoleAnsiInputKey_ctrl__ + #define __ConsoleAnsiInputKey_ctrl__ (1 << 10) + // # __ConsoleAnsiInputKey_ctrl_a__ start_of_heading __ConsoleAnsiInputKey_ctrl_a__ + #define __ConsoleAnsiInputKey_ctrl_a__ ('a' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_alt_v__ + #define __ConsoleAnsiInputKey_ctrl_alt_v__ ('v' + __ConsoleAnsiInputKey_alt__ + __ConsoleAnsiInputKey_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_b__ + #define __ConsoleAnsiInputKey_ctrl_b__ ('b' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_bs__ also ctrl_h + #define __ConsoleAnsiInputKey_ctrl_bs__ 8 + // # __ConsoleAnsiInputKey_ctrl_c__ + #define __ConsoleAnsiInputKey_ctrl_c__ ('c' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_d__ + #define __ConsoleAnsiInputKey_ctrl_d__ ('d' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_down__ + #define __ConsoleAnsiInputKey_ctrl_down__ (__ConsoleAnsiInputKey_down__ + __ConsoleAnsiInputKey_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_e__ + #define __ConsoleAnsiInputKey_ctrl_e__ ('e' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_enter__ + #define __ConsoleAnsiInputKey_ctrl_enter__ (__ConsoleAnsiInputKey_enter__ + __ConsoleAnsiInputKey_special__ + __ConsoleAnsiInputKey_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_f__ + #define __ConsoleAnsiInputKey_ctrl_f__ ('f' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_g__ + #define __ConsoleAnsiInputKey_ctrl_g__ ('g' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_h__ also ctrl_bs + #define __ConsoleAnsiInputKey_ctrl_bs__ 8 + #define __ConsoleAnsiInputKey_ctrl_h__ ('h' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_i__ also # __ConsoleAnsiInputKey_tab__ + #define __ConsoleAnsiInputKey_tab__ 9 + #define __ConsoleAnsiInputKey_ctrl_i__ ('i' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_j__ + #define __ConsoleAnsiInputKey_ctrl_j__ ('j' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_k__ vertical_tab + #define __ConsoleAnsiInputKey_ctrl_k__ ('k' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_l__ formFeed + #define __ConsoleAnsiInputKey_ctrl_l__ ('l' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_left__ + #define __ConsoleAnsiInputKey_ctrl_left__ (__ConsoleAnsiInputKey_left__ + __ConsoleAnsiInputKey_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_m__ also # __ConsoleAnsiInputKey_enter__ + #define __ConsoleAnsiInputKey_enter__ 13 + #define __ConsoleAnsiInputKey_ctrl_m__ ('m' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_n__ + #define __ConsoleAnsiInputKey_ctrl_n__ ('n' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_o__ + #define __ConsoleAnsiInputKey_ctrl_o__ ('o' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_p__ + #define __ConsoleAnsiInputKey_ctrl_p__ ('p' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_q__ + #define __ConsoleAnsiInputKey_ctrl_q__ ('q' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_r__ + #define __ConsoleAnsiInputKey_ctrl_r__ ('r' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_right__ + #define __ConsoleAnsiInputKey_ctrl_right__ (__ConsoleAnsiInputKey_right__ + __ConsoleAnsiInputKey_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_s__ + #define __ConsoleAnsiInputKey_ctrl_s__ ('s' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_shift_left__ + #define __ConsoleAnsiInputKey_ctrl_shift_left__ (__ConsoleAnsiInputKey_left__ + __ConsoleAnsiInputKey_ctrl__ + __ConsoleAnsiInputKey_shift__) + // # __ConsoleAnsiInputKey_ctrl_shift_right__ + #define __ConsoleAnsiInputKey_ctrl_shift_right__ (__ConsoleAnsiInputKey_right__ + __ConsoleAnsiInputKey_ctrl__ + __ConsoleAnsiInputKey_shift__) + // # __ConsoleAnsiInputKey_ctrl_t__ + #define __ConsoleAnsiInputKey_ctrl_t__ ('t' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_triangular_close_quotation_mark__ + #define __ConsoleAnsiInputKey_ctrl_triangular_close_quotation_mark__ ('>' + __ConsoleAnsiInputKey_special__ + __ConsoleAnsiInputKey_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_triangular_open_quotation_mark__ + #define __ConsoleAnsiInputKey_ctrl_triangular_open_quotation_mark__ ('<' + __ConsoleAnsiInputKey_special__ + __ConsoleAnsiInputKey_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_u__ + #define __ConsoleAnsiInputKey_ctrl_u__ ('u' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_up__ + #define __ConsoleAnsiInputKey_ctrl_up__ (__ConsoleAnsiInputKey_up__ + __ConsoleAnsiInputKey_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_v__ + #define __ConsoleAnsiInputKey_ctrl_v__ ('v' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_w__ + #define __ConsoleAnsiInputKey_ctrl_w__ ('w' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_x__ + #define __ConsoleAnsiInputKey_ctrl_x__ ('x' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_y__ + #define __ConsoleAnsiInputKey_ctrl_y__ ('y' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_ctrl_z__ + #define __ConsoleAnsiInputKey_ctrl_z__ ('z' + __ConsoleAnsiInputKey_ascii_ctrl__) + // # __ConsoleAnsiInputKey_delete__ + #define __ConsoleAnsiInputKey_delete__ (5 + __ConsoleAnsiInputKey_special__) + // # __ConsoleAnsiInputKey_down__ + #define __ConsoleAnsiInputKey_down__ (4 + __ConsoleAnsiInputKey_special__) + // # __ConsoleAnsiInputKey_end__ + #define __ConsoleAnsiInputKey_end__ (8 + __ConsoleAnsiInputKey_special__) + // # __ConsoleAnsiInputKey_escape__ + #define __ConsoleAnsiInputKey_escape__ 27 + // # __ConsoleAnsiInputKey_f10__ + #define __ConsoleAnsiInputKey_f10__ (10 + __ConsoleAnsiInputKey_functional__) + // # __ConsoleAnsiInputKey_f11__ + #define __ConsoleAnsiInputKey_f11__ (11 + __ConsoleAnsiInputKey_functional__) + // # __ConsoleAnsiInputKey_f12__ + #define __ConsoleAnsiInputKey_f12__ (12 + __ConsoleAnsiInputKey_functional__) + // # __ConsoleAnsiInputKey_f1__ + #define __ConsoleAnsiInputKey_f1__ (1 + __ConsoleAnsiInputKey_functional__) + // # __ConsoleAnsiInputKey_f2__ + #define __ConsoleAnsiInputKey_f2__ (2 + __ConsoleAnsiInputKey_functional__) + // # __ConsoleAnsiInputKey_f3__ + #define __ConsoleAnsiInputKey_f3__ (3 + __ConsoleAnsiInputKey_functional__) + // # __ConsoleAnsiInputKey_f4__ + #define __ConsoleAnsiInputKey_f4__ (4 + __ConsoleAnsiInputKey_functional__) + // # __ConsoleAnsiInputKey_f5__ + #define __ConsoleAnsiInputKey_f5__ (5 + __ConsoleAnsiInputKey_functional__) + // # __ConsoleAnsiInputKey_f6__ + #define __ConsoleAnsiInputKey_f6__ (6 + __ConsoleAnsiInputKey_functional__) + // # __ConsoleAnsiInputKey_f7__ + #define __ConsoleAnsiInputKey_f7__ (7 + __ConsoleAnsiInputKey_functional__) + // # __ConsoleAnsiInputKey_f8__ + #define __ConsoleAnsiInputKey_f8__ (8 + __ConsoleAnsiInputKey_functional__) + // # __ConsoleAnsiInputKey_f9__ + #define __ConsoleAnsiInputKey_f9__ (9 + __ConsoleAnsiInputKey_functional__) + // # __ConsoleAnsiInputKey_functional__ + #define __ConsoleAnsiInputKey_functional__ (1 << 9) + // # __ConsoleAnsiInputKey_home__ + #define __ConsoleAnsiInputKey_home__ (9 + __ConsoleAnsiInputKey_special__) + // # __ConsoleAnsiInputKey_left__ + #define __ConsoleAnsiInputKey_left__ (1 + __ConsoleAnsiInputKey_special__) + // # __ConsoleAnsiInputKey_mouse__ + #define __ConsoleAnsiInputKey_mouse__ (1 << 13) + // # __ConsoleAnsiInputKey_page_down__ + #define __ConsoleAnsiInputKey_page_down__ (7 + __ConsoleAnsiInputKey_special__) + // # __ConsoleAnsiInputKey_page_up__ + #define __ConsoleAnsiInputKey_page_up__ (6 + __ConsoleAnsiInputKey_special__) + // # __ConsoleAnsiInputKey_right__ + #define __ConsoleAnsiInputKey_right__ (2 + __ConsoleAnsiInputKey_special__) + // # __ConsoleAnsiInputKey_shift__ + #define __ConsoleAnsiInputKey_shift__ (1 << 12) + // # __ConsoleAnsiInputKey_shift_delete__ + #define __ConsoleAnsiInputKey_shift_delete__ (__ConsoleAnsiInputKey_delete__ + __ConsoleAnsiInputKey_shift__) + // # __ConsoleAnsiInputKey_shift_down__ + #define __ConsoleAnsiInputKey_shift_down__ (__ConsoleAnsiInputKey_down__ + __ConsoleAnsiInputKey_shift__) + // # __ConsoleAnsiInputKey_shift_left__ + #define __ConsoleAnsiInputKey_shift_left__ (__ConsoleAnsiInputKey_left__ + __ConsoleAnsiInputKey_shift__) + // # __ConsoleAnsiInputKey_shift_right__ + #define __ConsoleAnsiInputKey_shift_right__ (__ConsoleAnsiInputKey_right__ + __ConsoleAnsiInputKey_shift__) + // # __ConsoleAnsiInputKey_shift_up__ + #define __ConsoleAnsiInputKey_shift_up__ (__ConsoleAnsiInputKey_up__ + __ConsoleAnsiInputKey_shift__) + // # __ConsoleAnsiInputKey_special__ + #define __ConsoleAnsiInputKey_special__ (1 << 8) + // # __ConsoleAnsiInputKey_up__ + #define __ConsoleAnsiInputKey_up__ (3 + __ConsoleAnsiInputKey_special__) + // # __CryptoScalpiHash_doAny__ + #define __CryptoScalpiHash_doAny__( hasher, data_ptr, data_len, dest, dest_size) \ + __CryptoScalpiHash_do__( hasher, (char*)data_ptr, data_len, dest, dest_size) + // # __FileComplete_readToAny__ + #define __FileComplete_readToAny__( ret_data_ptr, ret_file_data_size, file_name, file_name_len, align ) \ + __FileComplete_read__( (uintptr_t*)ret_data_ptr, ret_file_data_size, file_name, file_name_len, align ) + // # __Hex_bytesLenFromHex__ + #define __Hex_bytesLenFromHex__(len) (len >> 1) + // # __Hex_lenFromBytesLen__ + #define __Hex_lenFromBytesLen__(len) (len * 2) + // # __MemSize_gb__ + #define __MemSize_gb__ (1024 * __MemSize_mb__) + // # __MemSize_kb__ + #define __MemSize_kb__ 1024 + // # __MemSize_mb__ + #define __MemSize_mb__ (1024 * __MemSize_kb__) + // # __Mem_fillAny__ + #define __Mem_fillAny__( dest, symbol, len) \ + __Mem_fill__( (char*)dest, symbol, len) + // # __Mem_nativeToBig__ + #if __target_memoryType__ == __TargetMemoryType_endiansBig__ + #define __Mem_nativeToBig__(dest, src, size) __Mem_copy__(dest, src, size) + #elif __target_memoryType__ == __TargetMemoryType_endiansLittle__ + #define __Mem_nativeToBig__(dest, src, size) __Mem_reverse__(dest, src, size) + #else + #error "please define __target_memoryType__ with __TargetMemoryType_ (you can test endings with cpu_checkNumberFormat function)" + #endif + // # __Mem_nativeToLittle__ + #if __target_memoryType__ == __TargetMemoryType_endiansBig__ + #define __Mem_nativeToLittle__(dest, src, size) __Mem_reverse__(dest, src, size) + #elif __target_memoryType__ == __TargetMemoryType_endiansLittle__ + #define __Mem_nativeToLittle__(dest, src, size) __Mem_copy__(dest, src, size) + #else + #error "please define __target_memoryType__ with __TargetMemoryType_ (you can test endings with cpu_checkNumberFormat function)" + #endif + // # __NetworkTcpHttpWebSocketHandShake_encoded_len__ + #define __NetworkTcpHttpWebSocketHandShake_encoded_len__ 28 + // # __NetworkTcpHttpWebSocketHeaderLongExtendedPayloadLen_size__ + #define __NetworkTcpHttpWebSocketHeaderLongExtendedPayloadLen_size__ 8 + // # __NetworkTcpHttpWebSocketHeaderLong__ + #define __NetworkTcpHttpWebSocketHeaderLong__ 2 + // # __NetworkTcpHttpWebSocketHeaderLong_flag__ + #define __NetworkTcpHttpWebSocketHeaderLong_flag__ 127 + // # __NetworkTcpHttpWebSocketHeaderLong_size__ + #define __NetworkTcpHttpWebSocketHeaderLong_size__ (__NetworkTcpHttpWebSocketHeaderSmall_size__ + __NetworkTcpHttpWebSocketHeaderLongExtendedPayloadLen_size__) + // # __NetworkTcpHttpWebSocketHeaderMask_size__ + #define __NetworkTcpHttpWebSocketHeaderMask_size__ 4 + // # __NetworkTcpHttpWebSocketHeaderMediumExtendedPayloadLen_size__ + #define __NetworkTcpHttpWebSocketHeaderMediumExtendedPayloadLen_size__ 2 + // # __NetworkTcpHttpWebSocketHeaderMedium__ + #define __NetworkTcpHttpWebSocketHeaderMedium__ 1 + // # __NetworkTcpHttpWebSocketHeaderMedium_flag__ + #define __NetworkTcpHttpWebSocketHeaderMedium_flag__ 126 + // # __NetworkTcpHttpWebSocketHeaderMedium_size__ + #define __NetworkTcpHttpWebSocketHeaderMedium_size__ (__NetworkTcpHttpWebSocketHeaderSmall_size__ + __NetworkTcpHttpWebSocketHeaderMediumExtendedPayloadLen_size__) + // # __NetworkTcpHttpWebSocketHeaderOpcode_binary__ + #define __NetworkTcpHttpWebSocketHeaderOpcode_binary__ 2 + // # __NetworkTcpHttpWebSocketHeaderOpcode_close__ + #define __NetworkTcpHttpWebSocketHeaderOpcode_close__ 8 + // # __NetworkTcpHttpWebSocketHeaderOpcode_continuation__ + #define __NetworkTcpHttpWebSocketHeaderOpcode_continuation__ 0 + // # __NetworkTcpHttpWebSocketHeaderOpcode_ping__ + #define __NetworkTcpHttpWebSocketHeaderOpcode_ping__ 9 + // # __NetworkTcpHttpWebSocketHeaderOpcode_pong__ + #define __NetworkTcpHttpWebSocketHeaderOpcode_pong__ 10 + // # __NetworkTcpHttpWebSocketHeaderOpcode_text__ + #define __NetworkTcpHttpWebSocketHeaderOpcode_text__ 1 + // # __NetworkTcpHttpWebSocketHeaderSmallExtendedPayloadLen_size__ + #define __NetworkTcpHttpWebSocketHeaderSmallExtendedPayloadLen_size__ 0 + // # __NetworkTcpHttpWebSocketHeaderSmall__ + #define __NetworkTcpHttpWebSocketHeaderSmall__ 0 + // # __NetworkTcpHttpWebSocketHeaderSmall_size__ + #define __NetworkTcpHttpWebSocketHeaderSmall_size__ 2 + // # __Sha1Block_size__ + #define __Sha1Block_size__ 64 + // # __Terminal_setFontStyleCText__ + #define __Terminal_setFontStyleCText__( ctx, text) \ + __Terminal_setFontStyle__( ctx, text, __CText_len__(text)) + // # __TextCharsDecFromU64_lenMax__ + //#define __TextCharsDecFromU64_lenMax__ __CText_len__("18446744073709551615") + #define __TextCharsDecFromU64_lenMax__ 20 + // # __TimeStamp_len__ + // for write time stamp like "00:00:00" as "HH:MM:SS" where HH - hours, MM - minuts, SS - seconds + #define __TimeStamp_len__ 8 + // # __Time_daysPerWeek__ + #define __Time_daysPerWeek__ 7 + // # __Time_hourPerDay__ + #define __Time_hourPerDay__ 24 + // # __Time_minPerHour__ + #define __Time_minPerHour__ 60 + // # __Time_msPerFsec__ + #define __Time_msPerFsec__ 0.001 + // # __Time_msPerS__ + #define __Time_msPerS__ 1000 + // # __Time_msPerSec__ + #define __Time_msPerSec__ 1000 + // # __Time_nsPerFsec__ + #define __Time_nsPerFsec__ 0.000_000_001 + // # __Time_secPerMin__ + #define __Time_secPerMin__ 60 + // # __Time_usPerFsec__ + #define __Time_usPerFsec__ 0.000_001 + // # __u64FromTextDec_maxLen__ + //#define __u64FromTextDec_maxLen__ __CText_len__("18446744073709551615") + #define __u64FromTextDec_maxLen__ 20 + // app + #define __AppEditor_changeStatusCText__(text) __AppEditor_changeStatus__(text, __CText_len__(text)) +// imports + // libC + #include + #include + #include + #include + #include + #include + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + #include + #include + #include + #include + #include + + #if __target_os__ == __TargetOs_windows__ + // posix + #include + // Windows + #if __with_network__ + #include // include before windows.h + //#include + #include + #endif + + #include + #include + #include + #include + #include + #include + + #ifdef __COMPILED_FROM_ZIG_FILE__ + #define INVALID_HANDLE_VALUE (HANDLE)0xFFFFFFFF + #endif + #elif __target_os__ == __TargetOs_linux__ + #include + #include + #include + #include + #include + #include + + #if __with_network__ + #include + #include + #include + #include + #endif + #endif +// strings + // # __Base64StandardAlphabet_chars__ + #define __Base64StandardAlphabet_chars__ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + // # __ConsoleAnsiOutputCursorStyle_reset__ + #define __ConsoleAnsiOutputCursorStyle_reset__ __ConsoleAnsi_control__ "0 q" + // # __ConsoleAnsiOutputFontStyle_bg_color_black__ + #define __ConsoleAnsiOutputFontStyle_bg_color_black__ "40" + // # __ConsoleAnsiOutputFontStyle_bg_color_blue__ + #define __ConsoleAnsiOutputFontStyle_bg_color_blue__ "44" + // # __ConsoleAnsiOutputFontStyle_bg_color_cyan__ + #define __ConsoleAnsiOutputFontStyle_bg_color_cyan__ "46" + // # __ConsoleAnsiOutputFontStyle_bg_color_gold__ + #define __ConsoleAnsiOutputFontStyle_bg_color_gold__ "43" + // # __ConsoleAnsiOutputFontStyle_bg_color_gray__ + #define __ConsoleAnsiOutputFontStyle_bg_color_gray__ "100" + // # __ConsoleAnsiOutputFontStyle_bg_color_green__ + #define __ConsoleAnsiOutputFontStyle_bg_color_green__ "42" + // # __ConsoleAnsiOutputFontStyle_bg_color_light_blue__ + #define __ConsoleAnsiOutputFontStyle_bg_color_light_blue__ "104" + // # __ConsoleAnsiOutputFontStyle_bg_color_light_cyan__ + #define __ConsoleAnsiOutputFontStyle_bg_color_light_cyan__ "106" + // # __ConsoleAnsiOutputFontStyle_bg_color_light_gray__ + #define __ConsoleAnsiOutputFontStyle_bg_color_light_gray__ "47" + // # __ConsoleAnsiOutputFontStyle_bg_color_light_green__ + #define __ConsoleAnsiOutputFontStyle_bg_color_light_green__ "102" + // # __ConsoleAnsiOutputFontStyle_bg_color_light_magenta__ + #define __ConsoleAnsiOutputFontStyle_bg_color_light_magenta__ "105" + // # __ConsoleAnsiOutputFontStyle_bg_color_magenta__ + #define __ConsoleAnsiOutputFontStyle_bg_color_magenta__ "45" + // # __ConsoleAnsiOutputFontStyle_bg_color_pink__ + #define __ConsoleAnsiOutputFontStyle_bg_color_pink__ "101" + // # __ConsoleAnsiOutputFontStyle_bg_color_red__ + #define __ConsoleAnsiOutputFontStyle_bg_color_red__ "41" + // # __ConsoleAnsiOutputFontStyle_bg_color_white__ + #define __ConsoleAnsiOutputFontStyle_bg_color_white__ "107" + // # __ConsoleAnsiOutputFontStyle_bg_color_yellow__ + #define __ConsoleAnsiOutputFontStyle_bg_color_yellow__ "103" + // # __ConsoleAnsiOutputFontStyle_bg_color_zero__ + #define __ConsoleAnsiOutputFontStyle_bg_color_zero__ "49" + // # __ConsoleAnsiOutputFontStyle_bold__ + #define __ConsoleAnsiOutputFontStyle_bold__ "1" + // # __ConsoleAnsiOutputFontStyle_color_black__ + #define __ConsoleAnsiOutputFontStyle_color_black__ "30" + // # __ConsoleAnsiOutputFontStyle_color_blue__ + #define __ConsoleAnsiOutputFontStyle_color_blue__ "34" + // # __ConsoleAnsiOutputFontStyle_color_cyan__ + #define __ConsoleAnsiOutputFontStyle_color_cyan__ "36" + // # __ConsoleAnsiOutputFontStyle_color_gold__ + #define __ConsoleAnsiOutputFontStyle_color_gold__ "33" + // # __ConsoleAnsiOutputFontStyle_color_gray__ + #define __ConsoleAnsiOutputFontStyle_color_gray__ "90" + // # __ConsoleAnsiOutputFontStyle_color_green__ + #define __ConsoleAnsiOutputFontStyle_color_green__ "32" + // # __ConsoleAnsiOutputFontStyle_color_light_blue__ + #define __ConsoleAnsiOutputFontStyle_color_light_blue__ "94" + // # __ConsoleAnsiOutputFontStyle_color_light_cyan__ + #define __ConsoleAnsiOutputFontStyle_color_light_cyan__ "96" + // # __ConsoleAnsiOutputFontStyle_color_light_gray__ + #define __ConsoleAnsiOutputFontStyle_color_light_gray__ "37" + // # __ConsoleAnsiOutputFontStyle_color_light_green__ + #define __ConsoleAnsiOutputFontStyle_color_light_green__ "92" + // # __ConsoleAnsiOutputFontStyle_color_light_magenta__ + #define __ConsoleAnsiOutputFontStyle_color_light_magenta__ "95" + // # __ConsoleAnsiOutputFontStyle_color_magenta__ + #define __ConsoleAnsiOutputFontStyle_color_magenta__ "35" + // # __ConsoleAnsiOutputFontStyle_color_pink__ + #define __ConsoleAnsiOutputFontStyle_color_pink__ "91" + // # __ConsoleAnsiOutputFontStyle_color_red__ + #define __ConsoleAnsiOutputFontStyle_color_red__ "31" + // # __ConsoleAnsiOutputFontStyle_color_white__ + #define __ConsoleAnsiOutputFontStyle_color_white__ "97" + // # __ConsoleAnsiOutputFontStyle_color_yellow__ + #define __ConsoleAnsiOutputFontStyle_color_yellow__ "93" + // # __ConsoleAnsiOutputFontStyle_color_zero__ + #define __ConsoleAnsiOutputFontStyle_color_zero__ "39" + // # __ConsoleAnsiOutputFontStyle_command_reset__ + #define __ConsoleAnsiOutputFontStyle_command_reset__ \ + __ConsoleAnsiOutputFontStyle_start__ \ + __ConsoleAnsiOutputFontStyle_reset__ \ + __ConsoleAnsiOutputFontStyle_end__ + // # __ConsoleAnsiOutputFontStyle_conceal__ + #define __ConsoleAnsiOutputFontStyle_conceal__ "8" + // # __ConsoleAnsiOutputFontStyle_dim__ + #define __ConsoleAnsiOutputFontStyle_dim__ "2" + // # __ConsoleAnsiOutputFontStyle_end__ + #define __ConsoleAnsiOutputFontStyle_end__ "m" + // # __ConsoleAnsiOutputFontStyle_fraktur__ + #define __ConsoleAnsiOutputFontStyle_fraktur__ "20" + // # __ConsoleAnsiOutputFontStyle_italic__ + #define __ConsoleAnsiOutputFontStyle_italic__ "3" + // # __ConsoleAnsiOutputFontStyle_reset__ + #define __ConsoleAnsiOutputFontStyle_reset__ "0" + // # __ConsoleAnsiOutputFontStyle_sep__ + #define __ConsoleAnsiOutputFontStyle_sep__ ";" + // # __ConsoleAnsiOutputFontStyle_set_bg_color__ + #define __ConsoleAnsiOutputFontStyle_set_bg_color__ "48" + // # __ConsoleAnsiOutputFontStyle_set_color__ + #define __ConsoleAnsiOutputFontStyle_set_color__ "38" + // # __ConsoleAnsiOutputFontStyle_start__ + #define __ConsoleAnsiOutputFontStyle_start__ __ConsoleAnsi_control__ + // # __ConsoleAnsiOutputFontStyle_unbold__ + #define __ConsoleAnsiOutputFontStyle_unbold__ "21;24" + // # __ConsoleAnsiOutputFontStyle_underline__ + #define __ConsoleAnsiOutputFontStyle_underline__ "4" + // # __ConsoleAnsiOutputSettings_disableLineWrap__ + #define __ConsoleAnsiOutputSettings_disableLineWrap__ __ConsoleAnsi_control__ "?7l" + // # __ConsoleAnsiOutputSettings_enableLineWrap__ + #define __ConsoleAnsiOutputSettings_enableLineWrap__ __ConsoleAnsi_control__ "?7h" + // # __ConsoleAnsi_control__ + #define __ConsoleAnsi_control__ __ConsoleAnsi_esc__ "[" + // # __ConsoleAnsi_esc__ + #define __ConsoleAnsi_esc__ "\x1B" + // # __ConsoleAnsi_output_clear_line__ + #define __ConsoleAnsi_output_clear_line__ __ConsoleAnsi_control__ "2K" + // # __ConsoleAnsi_output_clear_to_end_line__ + #define __ConsoleAnsi_output_clear_to_end_line__ __ConsoleAnsi_control__ "0K" + // # __ConsoleAnsi_output_clear_to_start_line__ + #define __ConsoleAnsi_output_clear_to_start_line__ __ConsoleAnsi_control__ "1K" + // # __ConsoleAnsi_output_cursor_hide__ + #define __ConsoleAnsi_output_cursor_hide__ __ConsoleAnsi_control__ "?25l" + // # __ConsoleAnsi_output_cursor_show__ + #define __ConsoleAnsi_output_cursor_show__ __ConsoleAnsi_control__ "?25h" + // # __ConsoleAnsi_output_cursor_style_blinking_I_beam__ + #define __ConsoleAnsi_output_cursor_style_blinking_I_beam__ __ConsoleAnsi_control__ "5 q" + // # __ConsoleAnsi_output_cursor_style_blinking_block__ + #define __ConsoleAnsi_output_cursor_style_blinking_block__ __ConsoleAnsi_control__ "1 q" + // # __ConsoleAnsi_output_cursor_style_blinking_underline__ + #define __ConsoleAnsi_output_cursor_style_blinking_underline__ __ConsoleAnsi_control__ "3 q" + // # __ConsoleAnsi_output_cursor_style_steady_I_beam__ + #define __ConsoleAnsi_output_cursor_style_steady_I_beam__ __ConsoleAnsi_control__ "6 q" + // # __ConsoleAnsi_output_cursor_style_steady_block__ + #define __ConsoleAnsi_output_cursor_style_steady_block__ __ConsoleAnsi_control__ "2 q" + // # __ConsoleAnsi_output_cursor_style_steady_underline__ + #define __ConsoleAnsi_output_cursor_style_steady_underline__ __ConsoleAnsi_control__ "4 q" + // # __OsFilePath_separator__ + #if __target_os__ == __TargetOs_windows__ + #define __OsFilePath_separator__ "\\" + #elif __target_os__ == __TargetOs_linux__ + #define __OsFilePath_separator__ "/" + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + // # ansi_input_mouse_grab + #define ansi_input_mouse_grab __ConsoleAnsi_control__ "?1000h" + // # ansi_input_mouse_release + #define ansi_input_mouse_release __ConsoleAnsi_control__ "?1000l" +// basic types + // C + // # __Float32__ + typedef float __Float32__; + // # __Float64__ + typedef double __Float64__; + // # __FloatExtraSize__ + typedef long double __FloatExtraSize__; + // # __ConsoleAnsiInputKey__ + typedef + uint64_t + __ConsoleAnsiInputKey__ + ; + // # __FSec__ + typedef __Float64__ __FSec__; + // # __OsConsoleInputHandle__ + #if __target_os__ == __TargetOs_windows__ + typedef void* __OsConsoleInputHandle__; + #elif __target_os__ == __TargetOs_linux__ + typedef FILE* __OsConsoleInputHandle__; + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + // # __OsConsoleOutputHandle__ + #if __target_os__ == __TargetOs_windows__ + typedef HANDLE __OsConsoleOutputHandle__; + #elif __target_os__ == __TargetOs_linux__ + typedef int __OsConsoleOutputHandle__; + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + // # __OsFileHandle__ + #if __target_os__ == __TargetOs_windows__ + typedef HANDLE __OsFileHandle__; + #elif __target_os__ == __TargetOs_linux__ + typedef int __OsFileHandle__; + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + // # __OsNetworkTcpHandle__ + #if __target_os__ == __TargetOs_windows__ + typedef SOCKET __OsNetworkTcpHandle__; + #elif __target_os__ == __TargetOs_linux__ + typedef int __OsNetworkTcpHandle__; + #else + typedef void* __OsNetworkTcpHandle__; + #warning "__target_os__ not implemented" + #endif + // # __WriteFnPtrVoid__ + typedef + void + (*__WriteFnPtrVoid__) + (void* context, const char* bytes, size_t bytes_len) + ; + // # __WriteFnPtr__ + typedef + size_t + (*__WriteFnPtr__) + (void* context, const char* bytes, size_t bytes_len) + ; +// struct prototypes + struct __ConsoleAnsi_input_Key_SequenceParser_fromBytes_parser__; + struct __Console__; +// structs + // universal + // # Slice + struct Slice { + char* ptr; + size_t len; + }; + // # __Math2dPosU__ + struct __Math2dPosU__ { + size_t x; + size_t y; + }; + // # __Writer__ + struct __Writer__ { + void* context; + __WriteFnPtr__ write; + }; + // # network_tcp_Ip + struct network_tcp_Ip { + uint16_t port; + uint8_t address[4]; + }; + // Os + // system specifics + #if __target_os__ == __TargetOs_windows__ + #elif __target_os__ == __TargetOs_linux__ + // # __OsLinux_timespec__ + struct __OsLinux_timespec__ { + time_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ + }; + #else + #error "__target_os__ not implemented" + #endif + // # __OsConsoleFlags__ + struct __OsConsoleFlags__ { + bool inited; + + #if __target_os__ == __TargetOs_windows__ + DWORD input_mode; + DWORD output_mode; + #elif __target_os__ == __TargetOs_linux__ + struct termios termios; + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + }; + // # __OsConsoleInput__ + struct __OsConsoleInput__ { + __OsConsoleInputHandle__ handle; + + #if __target_os__ == __TargetOs_windows__ + #elif __target_os__ == __TargetOs_linux__ + int fileno; + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + }; + // # __OsConsoleOutput__ + struct __OsConsoleOutput__ { + __OsConsoleOutputHandle__ __OsConsoleOutput_handle__; + #if __target_os__ == __TargetOs_windows__ + #elif __target_os__ == __TargetOs_linux__ + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + }; + // # __OsHelper__ + struct __OsHelper__ { + #if __target_os__ == __TargetOs_windows__ + HINSTANCE instance; + void* console_input_handle; + __OsConsoleOutputHandle__ console_output_handle; + + #if __with_network__ + bool network_inited; + WSADATA wsdata; + #endif + #elif __target_os__ == __TargetOs_linux__ + FILE* console_input_handle; + __OsConsoleOutputHandle__ console_output_handle; + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + }; + // lib + // # Finder + struct Finder { + struct Slice text; + struct Slice desired; + size_t pos; + }; + // # RoundParam (SHA1) + struct RoundParam {uint32_t a; uint32_t b; uint32_t c; uint32_t d; uint32_t e; uint32_t i;}; + // # Sha1_Streaming + struct Sha1_Streaming { + uint32_t state[5]; + char block[__Sha1Block_size__]; + size_t buf_len; // current? filling level of block + uint64_t total_len; + }; + // # __ConsoleAnsiInputKey_SequenceParser__ + struct __ConsoleAnsiInputKey_SequenceParser__ { + __ConsoleAnsiInputKey__ sequence; + size_t used; + }; + // # __ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo__ + struct __ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo__ { + const char* __ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__; + __ConsoleAnsiInputKey__ key; + }; + // # __ConsoleAnsi_input_Key_SequenceParser_fromBytes_parser__ + struct __ConsoleAnsi_input_Key_SequenceParser_fromBytes_parser__ { + size_t text_len; + size_t len; + const struct __ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo__ *ptr; + }; + // # __Console__ + struct __Console__ { + struct __OsConsoleInput__ input; + struct __OsConsoleOutput__ output; + }; + // # __CryptoRandom__ + struct __CryptoRandom__ { + size_t seed; + }; + // # __CryptoScalpiHash__ + struct __CryptoScalpiHash__ { + uint8_t mask; // value with 4 ones and 4 zeros like: 0b00001111 + uint8_t a; + uint8_t b; + }; + // # __Logger__ + struct __Logger__ { + // write to terminal, console, file or to all together, but no real check "bytes is writen" + struct __Writer__ writers[4]; // __LoggerWriters__ + }; + // # __Math2dAreaU__ + struct __Math2dAreaU__ { + struct __Math2dPosU__ from; + struct __Math2dPosU__ to; + }; + // # __MemListLink__ + struct __MemListLink__ { + struct __MemListLink__* prev; + struct __MemListLink__* next; + struct __MemList__* list; + }; + // # __MemList__ + struct __MemList__ { + struct __MemListLink__* first; + struct __MemListLink__* last; + size_t count; + }; + // # __MemTree__ + struct __MemTree__ { + struct __MemList__ childs; + struct __MemListLink__ link; + size_t count; // recurse. for get non recurse use childs.count + size_t nested; + }; + // # __NetworkTcpIpToText__ + struct __NetworkTcpIpToText__ { + /// 255.255.255.255:65535 + /// 127. 0. 0. 1:27015 + /// 0. 0. 0. 1: 0 + char buffer[25]; + size_t len; + }; + // # __NetworkTcpServer__ + #if __with_network__ + struct __NetworkTcpServer__ { + bool __NetworkTcpServer_ready__; + __OsNetworkTcpHandle__ __NetworkTcpServer_socketHandle__; + size_t __NetworkTcpServer_maxWaitingClients__; + uint16_t port; + }; + #endif + // # __NetworkTcpVisitor__ + #if __with_network__ + struct __NetworkTcpVisitor__ { + __OsNetworkTcpHandle__ socket_handle; + struct network_tcp_Ip ip; + struct sockaddr_in addr; + }; + #endif + // # __TerminalInput__ + struct __TerminalInput__ { + // usage: + // call __TerminalInput_updateBuffer__ for update unreaded + // use __TerminalInput_grab__ in loop for get keys + + size_t ungrabed; + char buffer[__TerminalInput_size__]; + }; + // # __TerminalOutput__ + struct __TerminalOutput__ { + struct __Math2dPosU__ cursor_pos; + const char* font_style; + size_t __TerminalOutput_fontStyleLen__; + struct __Math2dPosU__ size; + bool convert_n_to_rn; + bool apply_r; + bool apply_n; + }; + // # __Terminal__ + struct __Terminal__ { + struct __Console__ *console; + struct __OsConsoleFlags__ system_flags; + struct __TerminalInput__ input; + struct __TerminalOutput__ output; + }; + // # __TextFormatU64__ + struct __TextFormatU64__ { + char buffer [__TextCharsDecFromU64_lenMax__]; + char *ptr; + size_t len; + }; + // # __Text_Splitter__ + struct __Text_Splitter__ { + struct Finder finder; + bool stop; + size_t last_pos; + }; + // # __TimeClock__ + struct __TimeClock__ { + uint64_t ms; + uint64_t sec; + uint64_t min; + uint64_t hour; + }; + // # __TimeTotal__ + struct __TimeTotal__ { + int64_t ms; + int64_t sec; + int64_t min; + int64_t hour; + int64_t day; + }; + // # __Trace__ + struct __Trace__ { + struct __Trace__ *__Trace_prevTrace__; + size_t __Trace_line__; + }; + // # network_tcp_http_WebSocket_Parser + struct network_tcp_http_WebSocket_Parser { + char* message; // no null + size_t frame_len; + size_t header_len; + size_t message_len; + }; + // App + // # __AppEditorHistoryNote__ + struct __AppEditorHistoryNote__ { + __ConsoleAnsiInputKey__ key; + struct __MemListLink__ link; + }; + // # __AppEditorLine__ + struct __AppEditorLine__ { + struct __MemListLink__ link; // used in Views.Flat.lines for iterating + struct __MemTree__ tree; // used in Views.Fold.lines + char text[__AppEditorLineLen_max__]; // todo use ptr to allocated data + size_t text_len; + }; + // # __AppEditorViewsFind__ + struct __AppEditorViewsFind__ { + struct __Math2dPosU__ offset; + struct __AppEditorLine__ line; + const struct __AppEditorViewsVTable__ *context_vtable; + void *context; + size_t symbol; + bool need_redraw; + }; + // # __AppEditorViewsFlat__ + struct __AppEditorViewsFlat__ { + struct __AppEditorLine__ *line; // current working line - is setted by outside. + struct __AppEditorLine__ *marked_line; // can be null + struct __MemList__ lines; + struct __MemList__ cutted; + struct __AppEditorLine__ bakup_line; + struct __Math2dPosU__ offset; + size_t symbol; + bool __AppEditorViewsFlat_autoSpace__; + bool need_redraw; + bool need_draw_line_num; + }; + // # __AppEditorViewsFolded__ + struct __AppEditorViewsFolded__ { + struct __AppEditorLine__ *line; + struct __AppEditorLine__ *marked_line; + struct __MemTree__ lines; + struct __MemTree__ cutted; + struct __AppEditorLine__ bakup_line; + struct __Math2dPosU__ offset; + size_t symbol; // pos of cursor on current line. + bool need_redraw; + bool need_draw_line_num; + }; + // # __AppEditorViewsGoToLine__ + struct __AppEditorViewsGoToLine__ { + struct __AppEditorLine__ line; + const struct __AppEditorViewsVTable__ *context_vtable; + void *context; + size_t symbol; + struct __Math2dPosU__ offset; + bool need_redraw; + }; + // # __AppEditorViewsReplace__ + struct __AppEditorViewsReplace__ { + struct __AppEditorLine__ line; + struct __Math2dPosU__ offset; + const struct __AppEditorViewsVTable__ *context_vtable; + void *context; + size_t symbol; + bool need_redraw; + }; + // # __AppEditorViewsVTable__ + struct __AppEditorViewsVTable__ { + size_t (*getOffsetX) (void *t); + size_t (*getOffsetY) (void *t); + size_t (*getSymbolPosX) (void *t); + size_t (*countLineNum) (void *t); + void (*setAsView) (void *t); + void (*goToPrevLine) (void *t); + void (*goToNextLine) (void *t); + void (*goToSymbolPosX) (void *t, size_t pos); + void (*goToLineFromNumber) (void *t, size_t num); + }; + // # __AppEditorViews__ + struct __AppEditorViews__ { + struct __AppEditorViewsReplace__ replace; + struct __AppEditorViewsFind__ find; + struct __AppEditorViewsGoToLine__ go_to_line; + struct __AppEditorViewsFlat__ flat; + struct __AppEditorViewsFolded__ folded; + }; + // # __AppEditor__ + struct __AppEditor__ { + struct __MemList__ history; + struct __AppEditorViews__ views; + const char *__AppEditor_endLine__; + struct __MemListLink__ *stop_record_link; + struct __MemListLink__ *start_record_link; + void (*do_ptr) (void *ctx); // can be null + void (*onKey_ptr) (void *ctx, __ConsoleAnsiInputKey__ key); // can be null + void *current_ctx; // can be null + const struct __AppEditorViewsVTable__ *current_vtable; // can be null + size_t __AppEditor_fileName_len__; + size_t __AppEditor_pathToClipboard_len__; + size_t __AppEditor_endLine_len__; + size_t lines_drawing; + char __AppEditor_fileName__ [__OsFilePathLen_max__]; + char __AppEditor_pathToClipboard__ [__OsFilePathLen_max__]; + bool working; + bool recording_macro; + bool inited; + }; + // # __App__ + struct __App__ { + struct __OsHelper__ __App_osHelper__; + struct __Logger__ __App_logger__; + struct __Console__ console; + struct __Terminal__ terminal; + struct __AppEditor__ editor; + int64_t tick; // time ms + bool working; + }; +// typedef to fn_ptrs +// function prototypes + // @ __Ap_fromNibble__ + uint8_t __Ap_fromNibble__ (char data); + // @ __Buffer_push__ + void __Buffer_push__ ( char *buffer, size_t *buffer_used, size_t pos, char item); + // @ __Buffer_setIndent__ + bool __Buffer_setIndent__ ( char *buffer, size_t *buffer_used, size_t buffer_max, size_t new_indent); + // @ __ConsoleOutput_cursorHide__ + void __ConsoleOutput_cursorHide__ ( struct __OsConsoleOutput__* console_output); + // @ __Console_showCursor__ + void __Console_showCursor__ ( struct __Console__ *console); + // @ __CryptoScalpiHash_do__ + void __CryptoScalpiHash_do__ ( struct __CryptoScalpiHash__ *t, const char *src, size_t src_size, char *dest, size_t dest_size); + // @ __CryptoScalpiHash_reset__ + void __CryptoScalpiHash_reset__ ( struct __CryptoScalpiHash__ *t); + // @ __CryptoScalpiHash_swapTwoBit__ + void __CryptoScalpiHash_swapTwoBit__ ( struct __CryptoScalpiHash__ *t); + // @ __Crypto_sumBytes__ + uint8_t __Crypto_sumBytes__ ( const char *data, size_t data_len); + // @ __Crypto_xorBytes__ + uint8_t __Crypto_xorBytes__ ( const char *data, size_t data_len); + // @ __Crypto_xorCyclic__ + void __Crypto_xorCyclic__ ( char *dest, const char *a, size_t dest_len, const char *b, size_t b_len); + // @ __FileComplete_clear__ + bool __FileComplete_clear__( + const char* file_name, + size_t file_name_len + ); + // @ __FileComplete_write__ + bool __FileComplete_write__( + const char* file_name, + size_t file_name_len, + const char* bytes, + size_t bytes_len + ); + // @ __HexCapital_fromNibble__ + char __HexCapital_fromNibble__ ( char data); + // @ __Hex_fromByte__ + void __Hex_fromByte__ ( char *buffer, uint8_t data); + // @ __Hex_fromNibble__ + char __Hex_fromNibble__ ( uint8_t data); + // @ __Logger_init__ + void __Logger_init__ (struct __Logger__* t); + // @ __Math_ceilDiv32__ + uint32_t __Math_ceilDiv32__ ( uint32_t a, uint32_t b); + // @ __MemListLink_init__ + void __MemListLink_init__ ( struct __MemListLink__* link); + // @ __MemListLink_resetLinks__ + void __MemListLink_resetLinks__ ( struct __MemListLink__* link); + // @ __MemList_init__ + void __MemList_init__ ( struct __MemList__* list); + // @ __MemList_pushLast__ + void __MemList_pushLast__ ( struct __MemList__ *list, struct __MemListLink__ *item); + // @ __MemTree_fix_counts__ + void __MemTree_fix_counts__ ( struct __MemTree__ *t, size_t delta_count, char action); + // @ __MemTree_fix_nested__ + void __MemTree_fix_nested__ ( struct __MemTree__ *t, size_t nested_delta, char action); + // @ __MemTree_getParentOrNull__ + struct __MemTree__* __MemTree_getParentOrNull__ ( struct __MemTree__ *tree); + // @ __MemTree_getParent__ + void __MemTree_getParent__ ( struct __MemTree__ **ret, struct __MemTree__ *tree); + // @ __MemTree_init__ + void __MemTree_init__ ( struct __MemTree__ *t); + // @ __MemTree_popFirstChild__ + struct __MemTree__* __MemTree_popFirstChild__ ( struct __MemTree__ *tree); + // @ __MemTree_pushNext__ + void __MemTree_pushNext__ ( struct __MemTree__ *t, struct __MemTree__ *item); + // @ __MemTree_traverse__ + struct __MemTree__* __MemTree_traverse__ ( struct __MemTree__ *tree); + // @ __Mem_copyBackward__ + void __Mem_copyBackward__ ( char* dest, const char* src, size_t size); + // @ __Mem_copy__ + void __Mem_copy__ ( char *dest, const char *src, size_t size); + // @ __Mem_find__ + bool __Mem_find__ ( size_t *ret_pos, const char *data, size_t data_len, const char *desired, size_t desired_len); + // @ __Mem_isEql__ + bool __Mem_isEql__ ( const char a[], const char b[], size_t len); + // @ __Nibble_fromAp__ + uint8_t __Nibble_fromAp__ (char data); + // @ __Nibble_fromHexNibble__ + char __Nibble_fromHexNibble__ ( char nibble); + // @ __OsConsoleInput_init__ + void __OsConsoleInput_init__ ( struct __OsConsoleInput__* t, __OsConsoleInputHandle__ input_hanle); + // @ __OsConsoleOutput_init__ + void __OsConsoleOutput_init__ ( struct __OsConsoleOutput__* output, __OsConsoleOutputHandle__ handle); + // @ __OsConsoleOutput_write__ + bool __OsConsoleOutput_write__ ( struct __OsConsoleOutput__* os_console_output, const char* data, size_t _len); + // @ __OsFallbackConsole_write__ + size_t __OsFallbackConsole_write__ ( void* unused_ctx, char* data, size_t len); + // @ __OsFile_clear__ + void __OsFile_clear__ ( __OsFileHandle__ file); + // @ __OsFile_close__ + void __OsFile_close__ ( __OsFileHandle__ file); + // @ __OsFile_create__ + bool __OsFile_create__ ( __OsFileHandle__ *ret, const char file_name[], size_t file_name_len); + // @ __OsFile_exist__ + bool __OsFile_exist__ ( const char* file_name, size_t file_name_len); + // @ __OsFile_getSize__ + size_t __OsFile_getSize__ ( __OsFileHandle__ file); + // @ __OsFile_open__ + bool __OsFile_open__ (__OsFileHandle__ *ret, const char file_name[], size_t file_name_len); + // @ __OsFile_readToBuffer__ + bool __OsFile_readToBuffer__ ( __OsFileHandle__ file, char *buffer, size_t buffer_len, size_t offset); + // @ __OsFile_setPos__ + void __OsFile_setPos__ ( __OsFileHandle__ file, size_t pos); + // @ __OsFile_truncate__ + void __OsFile_truncate__ ( __OsFileHandle__ file); + // @ __OsFile_write__ + bool __OsFile_write__ ( __OsFileHandle__ file, const char* data, size_t data_len, size_t offset); + // @ __OsHelper_deinit__ + void __OsHelper_deinit__ ( struct __OsHelper__*t); + // @ __OsHelper_init__ + bool __OsHelper_init__ ( struct __OsHelper__* t); + // @ __OsHelper_process__ + void __OsHelper_process__ ( struct __OsHelper__* t); + // @ __OsMem_alloc__ + bool __OsMem_alloc__ ( uintptr_t *ret_data_addr, size_t size); + // @ __OsMem_free__ + void __OsMem_free__ ( uintptr_t ret_data_addr); + // @ __Os_getTick__ + uint64_t __Os_getTick__ (); + // @ __Os_sleep__ + void __Os_sleep__( uint64_t ms); + // @ __TerminalInput_shift__ + void __TerminalInput_shift__ ( struct __TerminalInput__ *t, size_t val); + // @ __Terminal_Output_Cursor_shiftDown__ + void __Terminal_Output_Cursor_shiftDown__(struct __Terminal__ *terminal, size_t delta); + // @ __Terminal_Output_Cursor_shiftLeft__ + void __Terminal_Output_Cursor_shiftLeft__(struct __Terminal__ *terminal, size_t delta); + // @ __Terminal_Output_Cursor_shiftRight__ + void __Terminal_Output_Cursor_shiftRight__(struct __Terminal__ *terminal, size_t delta); + // @ __Terminal_Output_Cursor_shiftUp__ + void __Terminal_Output_Cursor_shiftUp__(struct __Terminal__ *terminal, size_t delta); + // @ __Terminal_cursorMove__ + void __Terminal_cursorMove__ ( struct __Terminal__ *terminal, size_t pos_x, size_t pos_y); + // @ __Terminal_moveCursorToStartOfLine__ + void __Terminal_moveCursorToStartOfLine__ ( struct __Terminal__ *terminal); + // @ __Terminal_resetColors__ + void __Terminal_resetColors__ ( struct __Terminal__ *terminal); + // @ __Terminal_setFontStyle__ + void __Terminal_setFontStyle__ ( struct __Terminal__ *terminal, const char* font_style, size_t font_style_len); + // @ __Terminal_updateOutputSize__ + void __Terminal_updateOutputSize__ ( struct __Terminal__ *terminal); + // @ __Terminal_writeToOutput__ + void __Terminal_writeToOutput__ ( struct __Terminal__ *terminal, const char *bytes, size_t bytes_len); + // @ __Terminal_writeToOutput__ + void __Terminal_writeToOutput__ ( struct __Terminal__ *terminal, const char *bytes, size_t bytes_len); + // @ __TextAsciiSymbol_isBreakWord__ + bool __TextAsciiSymbol_isBreakWord__ ( char symbol); + // @ __TextAsciiSymbol_isWord__ + bool __TextAsciiSymbol_isWord__ ( char symbol); + // @ __TextAscii_countIndent__ + size_t __TextAscii_countIndent__ ( const char *text, size_t text_len, size_t tabsize); + // @ __TextAscii_isVisible__ + bool __TextAscii_isVisible__ ( char byte); + // @ __Text_countIndent__ + size_t __Text_countIndent__ ( char* text, size_t text_len, size_t tab_size); + // @ __Text_formatU64ToBuffer__ + size_t __Text_formatU64ToBuffer__ ( char *buffer, uint64_t number, size_t min_width); + // @ __ZText_countLen__ + size_t __ZText_countLen__ ( const char text[]); + // @ print_trace_example + void print_trace_example ( int anyarg, struct __Trace__* prev_trace); + // @ real_main + bool real_main(int args_len, char** args_ptr); + // @ tests + bool tests (); +// globals + // # __AppEditorViewsEasyMotionHorizontalContext_vtable__ + const struct __AppEditorViewsVTable__* __AppEditorViewsEasyMotionHorizontalContext_vtable__; + // # __AppEditorViewsEasyMotionHorizontal_context__ + void* __AppEditorViewsEasyMotionHorizontal_context__; + // # __AppEditorViewsEasyMotionVertical_context__ + void* __AppEditorViewsEasyMotionVertical_context__; + // # __AppEditorViewsEasyMotionVertical_context_vtable__ + const struct __AppEditorViewsVTable__* __AppEditorViewsEasyMotionVertical_context_vtable__; + // # __AppEditorViewsVtable_flat__ + struct __AppEditorViewsVTable__ __AppEditorViewsVtable_flat__; + // # __AppEditorViewsVtable_folded__ + struct __AppEditorViewsVTable__ __AppEditorViewsVtable_folded__; + // # __ConsoleAnsi_input_Key_SequenceParser_sequences_1__ + struct __ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo__ __ConsoleAnsi_input_Key_SequenceParser_sequences_1__[] = { + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x16", .key = __ConsoleAnsiInputKey_ctrl_alt_v__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x27", .key = __ConsoleAnsiInputKey_alt_apostrophe__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x2C", .key = __ConsoleAnsiInputKey_alt_comma__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x2E", .key = __ConsoleAnsiInputKey_alt_dot__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x30", .key = __ConsoleAnsiInputKey_alt_0__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x31", .key = __ConsoleAnsiInputKey_alt_1__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x32", .key = __ConsoleAnsiInputKey_alt_2__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x33", .key = __ConsoleAnsiInputKey_alt_3__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x34", .key = __ConsoleAnsiInputKey_alt_4__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x35", .key = __ConsoleAnsiInputKey_alt_5__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x36", .key = __ConsoleAnsiInputKey_alt_6__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x37", .key = __ConsoleAnsiInputKey_alt_7__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x38", .key = __ConsoleAnsiInputKey_alt_8__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x39", .key = __ConsoleAnsiInputKey_alt_9__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x3B", .key = __ConsoleAnsiInputKey_alt_semicolon__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x4D", .key = __ConsoleAnsiInputKey_alt_M__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x61", .key = __ConsoleAnsiInputKey_alt_a__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x62", .key = __ConsoleAnsiInputKey_alt_b__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x63", .key = __ConsoleAnsiInputKey_alt_c__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x64", .key = __ConsoleAnsiInputKey_alt_d__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x65", .key = __ConsoleAnsiInputKey_alt_e__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x66", .key = __ConsoleAnsiInputKey_alt_f__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x67", .key = __ConsoleAnsiInputKey_alt_g__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x68", .key = __ConsoleAnsiInputKey_alt_h__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x69", .key = __ConsoleAnsiInputKey_alt_i__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x6A", .key = __ConsoleAnsiInputKey_alt_j__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x6B", .key = __ConsoleAnsiInputKey_alt_k__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x6C", .key = __ConsoleAnsiInputKey_alt_l__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x6E", .key = __ConsoleAnsiInputKey_alt_n__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x6F", .key = __ConsoleAnsiInputKey_alt_o__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x6D", .key = __ConsoleAnsiInputKey_alt_m__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x70", .key = __ConsoleAnsiInputKey_alt_p__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x71", .key = __ConsoleAnsiInputKey_alt_q__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x72", .key = __ConsoleAnsiInputKey_alt_r__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x73", .key = __ConsoleAnsiInputKey_alt_s__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x74", .key = __ConsoleAnsiInputKey_alt_t__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x75", .key = __ConsoleAnsiInputKey_alt_u__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x76", .key = __ConsoleAnsiInputKey_alt_v__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x77", .key = __ConsoleAnsiInputKey_alt_w__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x78", .key = __ConsoleAnsiInputKey_alt_x__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x79", .key = __ConsoleAnsiInputKey_alt_y__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x7A", .key = __ConsoleAnsiInputKey_alt_z__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B", .key = __ConsoleAnsiInputKey_alt_open_bracket__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5D", .key = __ConsoleAnsiInputKey_alt_close_bracket__ }, + }; + // # __ConsoleAnsi_input_Key_SequenceParser_sequences_2__ + struct __ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo__ __ConsoleAnsi_input_Key_SequenceParser_sequences_2__[] = { + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x4F\x50", .key = __ConsoleAnsiInputKey_f1__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x4F\x51", .key = __ConsoleAnsiInputKey_f2__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x4F\x52", .key = __ConsoleAnsiInputKey_f3__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x4F\x53", .key = __ConsoleAnsiInputKey_f4__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x4F\x64", .key = __ConsoleAnsiInputKey_ctrl_left__ }, // rxvt + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x4F\x63", .key = __ConsoleAnsiInputKey_ctrl_right__ }, // rxvt + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x41", .key = __ConsoleAnsiInputKey_up__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x42", .key = __ConsoleAnsiInputKey_down__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x43", .key = __ConsoleAnsiInputKey_right__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x44", .key = __ConsoleAnsiInputKey_left__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x46", .key = __ConsoleAnsiInputKey_end__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x48", .key = __ConsoleAnsiInputKey_home__ }, + }; + // # __ConsoleAnsi_input_Key_SequenceParser_sequences_3__ + struct __ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo__ __ConsoleAnsi_input_Key_SequenceParser_sequences_3__[] = { + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x5B\x41", .key = __ConsoleAnsiInputKey_f1__ }, // tty + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x5B\x42", .key = __ConsoleAnsiInputKey_f2__ }, // tty + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x5B\x43", .key = __ConsoleAnsiInputKey_f3__ }, // tty + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x5B\x44", .key = __ConsoleAnsiInputKey_f4__ }, // tty + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x33\x7E", .key = __ConsoleAnsiInputKey_delete__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x35\x7E", .key = __ConsoleAnsiInputKey_page_up__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x36\x7E", .key = __ConsoleAnsiInputKey_page_down__ }, + }; + // # __ConsoleAnsi_input_Key_SequenceParser_sequences_4__ + struct __ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo__ __ConsoleAnsi_input_Key_SequenceParser_sequences_4__[] = { + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x31\x7E", .key = __ConsoleAnsiInputKey_f1__ }, // rxvt + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x32\x7E", .key = __ConsoleAnsiInputKey_f2__ }, // rxvt + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x35\x7E", .key = __ConsoleAnsiInputKey_f5__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x37\x7E", .key = __ConsoleAnsiInputKey_f6__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x38\x7E", .key = __ConsoleAnsiInputKey_f7__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x39\x7E", .key = __ConsoleAnsiInputKey_f8__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x32\x30\x7E", .key = __ConsoleAnsiInputKey_f9__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x32\x31\x7E", .key = __ConsoleAnsiInputKey_f10__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x32\x33\x7E", .key = __ConsoleAnsiInputKey_f11__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x32\x34\x7E", .key = __ConsoleAnsiInputKey_f12__ }, + }; + // # __ConsoleAnsi_input_Key_SequenceParser_sequences_5__ + struct __ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo__ __ConsoleAnsi_input_Key_SequenceParser_sequences_5__[] = { + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x3B\x32\x41", .key = __ConsoleAnsiInputKey_shift_up__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x3B\x33\x41", .key = __ConsoleAnsiInputKey_alt_up__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x3B\x35\x41", .key = __ConsoleAnsiInputKey_ctrl_up__ }, + + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x3B\x32\x42", .key = __ConsoleAnsiInputKey_shift_down__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x3B\x33\x42", .key = __ConsoleAnsiInputKey_alt_down__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x3B\x35\x42", .key = __ConsoleAnsiInputKey_ctrl_down__ }, + + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x3B\x32\x43", .key = __ConsoleAnsiInputKey_shift_right__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x3B\x33\x43", .key = __ConsoleAnsiInputKey_alt_right__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x3B\x35\x43", .key = __ConsoleAnsiInputKey_ctrl_right__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x3B\x36\x43", .key = __ConsoleAnsiInputKey_ctrl_shift_right__ }, + + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x3B\x35\x44", .key = __ConsoleAnsiInputKey_ctrl_left__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x3B\x36\x44", .key = __ConsoleAnsiInputKey_ctrl_shift_left__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x3B\x32\x44", .key = __ConsoleAnsiInputKey_shift_left__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x31\x3B\x33\x44", .key = __ConsoleAnsiInputKey_alt_left__ }, + + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x33\x3B\x32\x7E", .key = __ConsoleAnsiInputKey_shift_delete__ }, + }; + // # __ConsoleAnsi_input_Key_SequenceParser_sequences_9__ + struct __ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo__ __ConsoleAnsi_input_Key_SequenceParser_sequences_9__[] = { + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "\x5B\x32\x37\x3B\x35\x3B\x31\x33\x7E", .key = __ConsoleAnsiInputKey_ctrl_enter__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "[27;5;44~", .key = __ConsoleAnsiInputKey_ctrl_triangular_open_quotation_mark__ }, + { .__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__ = "[27;5;46~", .key = __ConsoleAnsiInputKey_ctrl_triangular_close_quotation_mark__ }, + }; + // # __ConsoleAnsi_input_Key_SequenceParser_fromBytes_parsers__ + struct __ConsoleAnsi_input_Key_SequenceParser_fromBytes_parser__ __ConsoleAnsi_input_Key_SequenceParser_fromBytes_parsers__[] = { + { .text_len = 9, .len = __arrayLen__(__ConsoleAnsi_input_Key_SequenceParser_sequences_9__), .ptr = &__ConsoleAnsi_input_Key_SequenceParser_sequences_9__[0] }, + { .text_len = 5, .len = __arrayLen__(__ConsoleAnsi_input_Key_SequenceParser_sequences_5__), .ptr = &__ConsoleAnsi_input_Key_SequenceParser_sequences_5__[0] }, + { .text_len = 4, .len = __arrayLen__(__ConsoleAnsi_input_Key_SequenceParser_sequences_4__), .ptr = &__ConsoleAnsi_input_Key_SequenceParser_sequences_4__[0] }, + { .text_len = 3, .len = __arrayLen__(__ConsoleAnsi_input_Key_SequenceParser_sequences_3__), .ptr = &__ConsoleAnsi_input_Key_SequenceParser_sequences_3__[0] }, + { .text_len = 2, .len = __arrayLen__(__ConsoleAnsi_input_Key_SequenceParser_sequences_2__), .ptr = &__ConsoleAnsi_input_Key_SequenceParser_sequences_2__[0] }, + { .text_len = 1, .len = __arrayLen__(__ConsoleAnsi_input_Key_SequenceParser_sequences_1__), .ptr = &__ConsoleAnsi_input_Key_SequenceParser_sequences_1__[0] }, + }; + // # __ConsoleAnsi_input_Key_SequenceParser_fromBytes__ + bool __ConsoleAnsi_input_Key_SequenceParser_fromBytes__( + struct __ConsoleAnsiInputKey_SequenceParser__ *out, + const char *data, + size_t data_len + ) { + if (data[0] == '\x1B') { + const char* user_sequence = &data[1]; + size_t user_sequence_len = data_len - 1; + + if (user_sequence_len >= 5 and __Mem_isEql__(user_sequence, "\x5B\x4D", 2)) { // mouse + out->sequence = __ConsoleAnsiInputKey_mouse__; + out->used = 6; + return true; + } + + // reverse iterating about __ConsoleAnsi_input_Key_SequenceParser_fromBytes_parsers__ + for (size_t parser_id = 0; parser_id < __arrayLen__(__ConsoleAnsi_input_Key_SequenceParser_fromBytes_parsers__); parser_id++) { + struct __ConsoleAnsi_input_Key_SequenceParser_fromBytes_parser__ *parser = &__ConsoleAnsi_input_Key_SequenceParser_fromBytes_parsers__[parser_id]; + size_t check_len = parser->text_len; + if (user_sequence_len >= check_len) { + size_t seq_count = parser->len; + const struct __ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo__ *seq_list = parser->ptr; + for (size_t seq_id = 0; seq_id < seq_count; seq_id++) { + const struct __ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo__* seq = &seq_list[seq_id]; + if (__Mem_isEql__(user_sequence, &seq->__ConsoleAnsi_input_Key_SequenceParser_fromBytes_SequenceInfo_text__[0], check_len)) { + out->sequence = seq->key; + out->used = check_len + 1; + return true; + } + } + } + } + } + + return false; + } + // # __app__ + struct __App__ __app__; +// functions + // # Base64_getEncodeSize + uint32_t Base64_getEncodeSize(uint32_t src_len) { + int blocks = __Math_ceilDiv32__(src_len, 3); + return blocks * 4; + } + // # Slice_debug + void Slice_debug(struct Slice* slice, char* name, size_t line) { + if (slice->len == 0) { + printf("%zu: %s is NULL. \r\n", line, name); + } else { + printf("%zu: %s (%zu): \"%.*s", line, name, slice->len, (int)slice->len, slice->ptr); + } + } + // # __AlignedPtr_alloc__ + bool __AlignedPtr_alloc__( + uintptr_t *ret_data_addr, + uint8_t data_align, // expected >= 1 + size_t data_size // expected >= 1 + ) { + bool ok = true; + uint8_t gap_size = 0; + size_t allocated_size = data_size + (data_align - 1) + sizeof(gap_size); + uintptr_t allocated_addr; + if (__OsMem_allocAny__(&allocated_addr, allocated_size)) { + // calc size of gap + uint8_t nodled = allocated_addr % data_align; + if (nodled) { + gap_size = data_align - nodled; + } + + // write ret_data_addr + uintptr_t data_addr = allocated_addr + gap_size; + *ret_data_addr = data_addr; + + // save gap size + * (uint8_t*) (data_addr + data_size) = gap_size; + + if (!ok) __OsMem_freeAny__(allocated_addr); + } else { + ok = false; + } + return ok; + } + // # __AlignedPtr_free__ + void __AlignedPtr_free__( + uintptr_t data_addr, + size_t data_size + ) { + uint8_t gap_size = * (uint8_t*) (data_addr + data_size); + __OsMem_freeAny__(data_addr - gap_size); + } + // # __Ap_fromByte__ + void __Ap_fromByte__( + char *buffer, // expected len >= 2 + char byte + ) { + buffer[0] = __Ap_fromNibble__((byte & 0xF0) >> 4); + buffer[1] = __Ap_fromNibble__(byte & 0x0F); + } + // # __Ap_fromBytesReversed__ + void __Ap_fromBytesReversed__( + char *buffer, // expected len >= data_len << 1 + const char *data, + size_t data_len + ) { + size_t writed = data_len << 1; + for (size_t readed = 0; readed < data_len; readed++) { + writed -= 2; + __Ap_fromByte__(&buffer[writed], data[readed]); + } + } + // # __Ap_fromBytes__ + void __Ap_fromBytes__( + char *buffer, // expected len >= data_len << 1 + const char *data, + size_t data_len + ) { + size_t writed = 0; + for(size_t pos = 0; pos < data_len; pos++) { + __Ap_fromByte__(&buffer[writed], data[pos]); + writed += 2; + } + } + // # __Ap_fromNibble__ + uint8_t __Ap_fromNibble__( + char data + ) { + if (data <= 16) { + return 'A' + data; + } + return 0; + } + // # __AppEditorHistoryNote_alloc__ + bool __AppEditorHistoryNote_alloc__( + struct __AppEditorHistoryNote__ **ptr + ) { + return __AlignedPtr_allocAny__( ptr, __Type_getAlign__(struct __AppEditorHistoryNote__), sizeof(struct __AppEditorHistoryNote__) ); + } + // # __AppEditorHistoryNote_free__ + void __AppEditorHistoryNote_free__( + struct __AppEditorHistoryNote__* ptr + ) { + __AlignedPtr_freeAny__(ptr, sizeof(struct __AppEditorHistoryNote__)); + } + // # __AppEditorLine_alloc__ + bool __AppEditorLine_alloc__(struct __AppEditorLine__ **ptr) { + return __AlignedPtr_allocAny__(ptr, __Type_getAlign__(struct __AppEditorLine__), __Type_getSize__(struct __AppEditorLine__) ); + } + // # __AppEditorLine_free__ + void __AppEditorLine_free__(struct __AppEditorLine__ *line) { + __AlignedPtr_freeAny__(line, __Type_getSize__(struct __AppEditorLine__)); + } + // # __AppEditorLine_init__ + void __AppEditorLine_init__( + struct __AppEditorLine__ *t + ) { + __MemListLink_init__(&t->link); + __MemTree_init__(&t->tree); + t->text_len = 0; + } + // # __AppEditorLine_setIndent__ + bool __AppEditorLine_setIndent__( // TODO check all uses this fn + struct __AppEditorLine__ *line, + size_t new_indent // expected < __AppEditorLineLen_max__ - line->text_len + ) { + return __Buffer_setIndent__(&line->text[0], &line->text_len, __AppEditorLineLen_max__, new_indent); + } + // # __AppEditorLine_setText__ + void __AppEditorLine_setText__ ( + struct __AppEditorLine__ *line, + char *text_ptr, + size_t text_len // expected < __AppEditorLineLen_max__ + ) { + line->text_len = text_len; + __Mem_copy__(&line->text[0], text_ptr, text_len); + } + // # __AppEditorListOfLine_writeToFile__ + bool + __AppEditorListOfLine_writeToFile__( + struct __MemList__ *lines, + const char* file_name, + size_t file_name_len + ) { + bool ok = true; + if (lines->count == 0) { + ok = __FileComplete_clear__(file_name, file_name_len); + + } else if (lines->count == 1) { + struct __MemListLink__* link = lines->first; + struct __AppEditorLine__* line = __TypedPtr_getParentPtrFromFieldPtr__(struct __AppEditorLine__, link, link); + if (line->text_len > 0) { + ok = __FileComplete_write__(file_name, file_name_len, &line->text[0], line->text_len); + } else { + ok = __FileComplete_clear__(file_name, file_name_len); + } + + } else { // lines > 1 + const char* end_line = __app__.editor.__AppEditor_endLine__; + size_t end_line_len = __app__.editor.__AppEditor_endLine_len__; + size_t full_len = 0; // garanty > 0 becouse lines > 1 + { // count fill len + struct __MemListLink__* link = lines->first; + struct __AppEditorLine__* line = __TypedPtr_getParentPtrFromFieldPtr__(struct __AppEditorLine__, link, link); + full_len += line->text_len; + + link = link->next; + while (link) { + struct __AppEditorLine__* line = __TypedPtr_getParentPtrFromFieldPtr__(struct __AppEditorLine__, link, link); + full_len += end_line_len + line->text_len; + link = link->next; + } + } + + char* buffer; + if (__AlignedPtr_allocAny__(&buffer, 4, full_len)) { // use aligned just for speed + // save to buffer + size_t writed = 0; + { // convert lines to one buffer + struct __MemListLink__* link = lines->first; // garanty not null by lines > 1 + + // write first line + struct __AppEditorLine__* first_line = __TypedPtr_getParentPtrFromFieldPtr__(struct __AppEditorLine__, link, link); + if (first_line->text_len > 0) { + __Mem_copy__(&buffer[writed], &first_line->text[0], first_line->text_len); + writed += first_line->text_len; + } + link = link->next; + + // write other lines + while (link) { + __Mem_copy__(&buffer[writed], end_line, end_line_len); + writed += end_line_len; + + struct __AppEditorLine__* line = __TypedPtr_getParentPtrFromFieldPtr__(struct __AppEditorLine__, link, link); + if (line->text_len > 0) { + __Mem_copy__(&buffer[writed], &line->text[0], line->text_len); + writed += line->text_len; + } + + link = link->next; + } + } + + // write to file + if (__FileComplete_write__(file_name, file_name_len, buffer, writed)) { + } else { // file not rewrited + ok = false; + } + + __AlignedPtr_freeAny__(buffer, full_len); + } else { // memory not allocated + ok = false; + } + } + return ok; + } + // # __AppEditorViewsEasyMotionHorizontal_draw__ + void __AppEditorViewsEasyMotionHorizontal_draw__() { + struct __Terminal__* terminal = &__app__.terminal; + __Terminal_setFontStyle__(&__app__.terminal, __AppEditorTheme_easy_motion__, __CText_len__(__AppEditorTheme_easy_motion__)); + size_t voy = __AppEditorViewsEasyMotionHorizontalContext_vtable__->getOffsetY(__AppEditorViewsEasyMotionHorizontal_context__); + + size_t pos = 0; + char rune = 'a'; + while (true) { + if (pos >= terminal->output.size.x - 1 - __AppEditorViewsEasyMotionHorizontal_step__) break; + + __Terminal_cursorMove__(terminal, pos, voy); + __Terminal_writeToOutput__(terminal, &rune, 1); + + if (rune == '9') { + break; + } else if (rune == 'z') { + rune = '0'; + } else { + rune += 1; + } + + pos += __AppEditorViewsEasyMotionHorizontal_step__; + } + } + // # __AppEditorViewsEasyMotionHorizontal_moveTo__ + void __AppEditorViewsEasyMotionHorizontal_moveTo__( + size_t pos + ) { + size_t spx = __AppEditorViewsEasyMotionHorizontalContext_vtable__->getSymbolPosX(__AppEditorViewsEasyMotionHorizontal_context__); + size_t vox = __AppEditorViewsEasyMotionHorizontalContext_vtable__->getOffsetX(__AppEditorViewsEasyMotionHorizontal_context__); + __AppEditorViewsEasyMotionHorizontalContext_vtable__->goToSymbolPosX(__AppEditorViewsEasyMotionHorizontal_context__, spx - vox + pos); + __AppEditorViewsEasyMotionHorizontalContext_vtable__->setAsView(__AppEditorViewsEasyMotionHorizontal_context__); + } + // # __AppEditor_addKeyToHistory__ + bool __AppEditor_addKeyToHistory__( + struct __AppEditor__ *editor, + __ConsoleAnsiInputKey__ key + ) { + bool ok = true; + struct __AppEditorHistoryNote__ *hn; + if ( __AppEditorHistoryNote_alloc__(&hn)) { + hn->key = key; + struct __MemListLink__ *link = &hn->link; + __MemListLink_init__(link); + __MemList_pushLast__(&editor->history, link); + if (!ok) __AppEditorHistoryNote_free__(hn); + } else { + ok = false; + } + return ok; + } + // # __AppEditor_changeStatus__ + void __AppEditor_changeStatus__( + const char *text, + size_t text_len + ) { + __ConsoleOutput_cursorHide__(&__app__.console.output); + __Terminal_cursorMove__(&__app__.terminal, 0, __app__.terminal.output.size.y - 1); + __Terminal_setFontStyleCText__(&__app__.terminal, __AppEditorTheme_notification__); + __Terminal_writeToOutput__(&__app__.terminal, text, text_len); + __OsConsoleOutput_write__(&__app__.console.output, __ConsoleAnsi_output_clear_to_end_line__, 0); + __Terminal_resetColors__(&__app__.terminal); + __Console_showCursor__(&__app__.console); + } + // # __AppEditor_playMacro__ + /* // use me after port fn __AppEditor_onKey__ + bool __AppEditor_playMacro__(struct __AppEditor__ *t) { + bool ok = true; + if (t->recording_macro != true) { + struct __MemListLink__ *start = t->start_record_link; + struct __MemListLink__ *end = t->stop_record_link; + if ( start and end ) { + struct __MemListLink__ *next_link = start->next; // skipped start recording itself + while ( next_link and (next_link != stop)) { + struct __AppEditorHistoryNote__ *history_note = __TypedPtr_getParentPtrFromFieldPtr__(struct __AppEditorHistoryNote__, link, next_link)); + struct __ConsoleAnsiInputKey__ key = history_note->key; + __AppEditor_onKey__(t, key); + next_link = next_link->next; + } + } else { + ok = false; + __AppEditor_changeStatusCText__("macro not recorded."); + } + } else { + ok = false; + __AppEditor_changeStatusCText__("not aviable while recording"); + } + return ok; + } + */ + // # __AppEditor_startRecordMacro__ + bool __AppEditor_startRecordMacro__( + struct __AppEditor__ *t + ) { + bool ok = true; + if (t->recording_macro != true) { + if (__AppEditor_addKeyToHistory__(t, 0)) { + t->recording_macro = true; + t->start_record_link = t->history.last; + t->stop_record_link = NULL; + __AppEditor_changeStatusCText__("start recording macro."); + } else { + ok = false; + __AppEditor_changeStatusCText__("Unexpected error"); // todo add line + } + } else { + ok = false; + __AppEditor_changeStatusCText__("macro is recording right now"); // todo add line + } + return ok; + } + // # __AppEditor_stopRecordMacro__ + bool __AppEditor_stopRecordMacro__(struct __AppEditor__ *t) { + bool ok = true; + if (t->recording_macro == true) { + if (__AppEditor_addKeyToHistory__(t, 0)) { + t->stop_record_link = t->history.last; + t->recording_macro = false; + __AppEditor_changeStatusCText__("stop recording macro."); + } else { + ok = false; + } + } else { + ok = false; + __AppEditor_changeStatusCText__("macro not recording right now."); + } + return ok; + } + // # __AppEditor_stop__ + void __AppEditor_stop__(struct __AppEditor__ *t) { + __Terminal_cursorMove__(&__app__.terminal, 0, t->lines_drawing); + __OsConsoleOutput_write__(&__app__.console.output, "\n", 0); + printf("file: {%.*s}", t->__AppEditor_fileName_len__ , &t->__AppEditor_fileName__[0]); + + { // draw_line_num + void *ctx = t->current_ctx; if (ctx) { + const struct __AppEditorViewsVTable__ *vt = t->current_vtable; if (vt) { + size_t (*cln) (void *t) = vt->countLineNum; if (cln) { + size_t current_line = cln(ctx); + printf(" {%d}", current_line); + } + } + } + } + + __OsConsoleOutput_write__(&__app__.console.output, "\r\n", 0); + t->working = false; + } + // # __App_deinit__ + void __App_deinit__(struct __App__* app) { + __OsHelper_deinit__(&app->__App_osHelper__); + } + // # __App_init__ + bool __App_init__(struct __App__* t) { + bool ok = true; + __Logger_init__(&t->__App_logger__); // preinit console output for debug + + if (__OsHelper_init__(&t->__App_osHelper__)) { + t->tick = __Os_getTick__(); + + if (!ok) __OsHelper_deinit__(&t->__App_osHelper__); + } else { + ok = false; + printf("%d app.__App_osHelper__ not inited\r\n", __LINE__); + } + + return ok; + } + // # __App_process__ + bool __App_process__(struct __App__* t) { + bool ok = true; + __OsHelper_process__(&t->__App_osHelper__); + return ok; + } + // # __App_waitToNextFrame__ + void __App_waitToNextFrame__(struct __App__* t) { + uint64_t expected_frame_end_time = t->tick + __Time_msPerS__ / __App_expectedFps__; + uint64_t resulting_frame_end_time = __Os_getTick__(); + if (resulting_frame_end_time > expected_frame_end_time + 120) { + uint64_t delta = resulting_frame_end_time - expected_frame_end_time; + printf("%d \t hitch detection: %zu delta: %zu ms \r\n", __LINE__, t->tick, delta); + } + uint64_t delay_sleep = 1; + if (resulting_frame_end_time < expected_frame_end_time) { + delay_sleep = expected_frame_end_time - resulting_frame_end_time; + } + __Os_sleep__(delay_sleep); + t->tick = resulting_frame_end_time + delay_sleep; + } + // # __Ascii_getFirstVisibleCharOrEnd__ + size_t __Ascii_getFirstVisibleCharOrEnd__( + const char *ptr, + size_t len // expected > 0 + ) { + size_t pos = 0; + for (;pos < len; pos++) { + char byte = ptr[pos]; + if (__TextAscii_isVisible__(byte)) break; + } + return pos; + } + // # __Ascii_isEmpty__ + bool __Ascii_isEmpty__( + const char *ptr, + size_t len // expected > 0 + ) { + return __Ascii_getFirstVisibleCharOrEnd__(ptr, len) < len; + } + // # __Base64_encode3Bytes__ + void __Base64_encode3Bytes__(unsigned char in[3], char out[4]) { + out[0] = __Base64StandardAlphabet_chars__[(in[0] & 0b11111100) >> 2]; + out[1] = __Base64StandardAlphabet_chars__[((in[0] & 0b00000011) << 4) | ((in[1] & 0b11110000) >> 4)]; + out[2] = __Base64StandardAlphabet_chars__[((in[1] & 0b00001111) << 2) | ((in[2] & 0b11000000) >> 6)]; + out[3] = __Base64StandardAlphabet_chars__[(in[2] & 0b00111111)]; + } + // # __Base64_encode__ + void __Base64_encode__(char* src, size_t src_len, char* out) { + // EXAMPLE + // Source ASCII text: "Ma" + // Character M a + // Octets 77 (0x4d) 97 (0x61) + // Bits 0 1 0 0 1 1 0 1|0 1 1 0 0 0 0 1|0 0 _ _ _ _ _ _| + // Base64 0 1 0 0 1 1|0 1 0 1 1 0|0 0 0 1 0 0|_ _ _ _ _ _| + // Sextets 19 22 4 Padding + // Character T W E = + // Octets 84 (0x54) 87 (0x57) 69 (0x45) 61 (0x3D) + + + // parse normal octets + char* end_of_src = src + src_len; + while(true) { + if (src + 3 > end_of_src) break; + __Base64_encode3Bytes__((void*) src, out); + src += 3; + out += 4; + } + + // parse extra_bytes + size_t extra_bytes = end_of_src - src; + if (extra_bytes > 0 ) { + char b[3] = {0}; + __Mem_copy__(b, src, extra_bytes); + __Base64_encode3Bytes__((void*)b, out); + out += 4; + + // add padding + size_t pads = 3 - extra_bytes; + for (char* pad = out - pads ;pad < out; pad++) {*pad = '=';} + } + } + // # __BitsU32_disable__ + uint32_t __BitsU32_disable__(uint32_t value, uint32_t mask) { + return value & (~mask); + } + // # __BitsU32_enable__ + uint32_t __BitsU32_enable__(uint32_t value, uint32_t mask) { + return value | mask; + } + // # __BitsU32_toggle__ + uint32_t __BitsU32_toggle__(uint32_t value, uint32_t mask, bool new_state) { + if (new_state) { + return __BitsU32_enable__(value, mask); + } else { + return __BitsU32_disable__(value, mask); + } + } + // # __Buffer_addIndent__ + void __Buffer_addIndent__( + char *buffer, + size_t *buffer_used, + size_t count // expected < (buffer_max - *buffer_used) + ) { + size_t pos = 0; + while (pos < count) { + __Buffer_push__(buffer, buffer_used, 0, ' '); + pos = pos + 1; + } + } + // # __Buffer_addIndent_check__ + bool + __Buffer_addIndent_check__( + char *buffer, + size_t *buffer_used, + size_t buffer_max, + size_t count + ) { + size_t space = buffer_max - *buffer_used; + return space > count; + } + // # __Buffer_pop__ + char __Buffer_pop__( + char *buffer, + size_t *buffer_used, // expected (*) > 0 + size_t pos // expected <= buffer_used + ) { + char ret = buffer[pos]; + (*buffer_used)--; + if (pos < *buffer_used) { + __Mem_copy__(&buffer[pos], &buffer[pos + 1], *buffer_used - pos); + } + return ret; + } + // # __Buffer_pop_check__ + bool __Buffer_pop_check__( + size_t buffer_used, + size_t pos + ) { + return ((buffer_used > 0) and (pos < buffer_used)); + } + // # __Buffer_push__ + void __Buffer_push__( + char *buffer, + size_t *buffer_used, // expected < allocated + size_t pos, // expected < allocated + char item + ) { + if (pos < *buffer_used) { // shiftSymbolsToRight + __Mem_copyBackward__(&buffer[pos + 1], &buffer[pos], *buffer_used - pos); + } + buffer[pos] = item; + (*buffer_used)++; + } + // # __Buffer_removeIndent__ + void + __Buffer_removeIndent__( + char *buffer, + size_t *buffer_used, // expected >= count + size_t count // expected <= buffer_used + ) { + size_t pos = 0; + while (pos < count) { + __Buffer_pop__( + buffer, + buffer_used, // (*) > 0 becouse expected *buffer_used >= loop_count + 0 + ); + pos += 1; + } + } + // # __Buffer_setIndent__ + bool + __Buffer_setIndent__( + char *buffer, + size_t *buffer_used, + size_t buffer_max, + size_t new_indent // expected < buffer_max + ) { + bool ok = true; + size_t indent = __Text_countIndent__(buffer, *buffer_used, 1); + if (new_indent != indent) { + if (new_indent > indent) { + size_t delta = new_indent - indent; + if (__Buffer_addIndent_check__(buffer, buffer_used, buffer_max, delta)) { + __Buffer_addIndent__(buffer, buffer_used, delta); + } else { + ok = false; + } + } else { // new_indent < indent + size_t delta = indent - new_indent; + __Buffer_removeIndent__(buffer, buffer_used, delta); + } + } + return ok; + } + // # __Byte_fromAp__ + uint8_t __Byte_fromAp__( + const char* data // expected len >= 2 + ) { + char fo = __Nibble_fromAp__(data[0]); + char of = __Nibble_fromAp__(data[1]); + return (fo << 4) | of; + } + // # __Byte_fromHex__ + char __Byte_fromHex__(char* hex_byte) { + char b_F0 = __Nibble_fromHexNibble__(hex_byte[0]); + char b_0F = __Nibble_fromHexNibble__(hex_byte[1]); + return (b_F0 << 4) | b_0F; + } + // # __Bytes_fromApReversed__ + void __Bytes_fromApReversed__( + char *buffer, // expected len >= ap_len >> 1 + const char *ap, + size_t ap_len // expected >= 2, expected odd + ) { + size_t ap_pos = ap_len; + size_t writed = 0; + while (ap_pos > 0) { + ap_pos -= 2; // garanty ap_pos < ap_len + buffer[writed] = __Byte_fromAp__(&ap[ap_pos]); + writed += 1; + } + } + // # __Bytes_fromAp__ + void __Bytes_fromAp__( + char *buffer, // expected len >= ap_len >> 1 + const char *ap, + size_t ap_len + ) { + size_t readed = 0; + size_t writed = 0; + while(readed < ap_len) { + buffer[writed] = __Byte_fromAp__(&ap[readed]); + writed += 1; + readed += 2; + } + } + // # __Bytes_fromHex__ // REPLACED ARG ORDER! + void __Bytes_fromHex__( + char* buffer_ptr, // expected len >= hex_len >> 2 + char* hex, + size_t hex_len + ) { + size_t end_pos = hex_len >> 1; + for(size_t pos = 0; pos < end_pos; pos++) { + buffer_ptr[pos] = __Byte_fromHex__(&hex[pos*2]); + } + } + // # __ConsoleOutput_cursorHide__ + void __ConsoleOutput_cursorHide__(struct __OsConsoleOutput__* console_output) { + __OsConsoleOutput_write__(console_output, __ConsoleAnsi_output_cursor_hide__, 0); + } + // # __Console_clearLine__ + void __Console_clearLine__(struct __Console__ *console) { + __OsConsoleOutput_writeCText__(&console->output, __ConsoleAnsi_output_clear_line__); + } + // # __Console_init__ + void __Console_init__( + struct __Console__ *t, + __OsConsoleInputHandle__ input_handle, + __OsConsoleOutputHandle__ output_handle + ) { + __OsConsoleInput_init__(&t->input, input_handle); + __OsConsoleOutput_init__(&t->output, output_handle); + } + // # __Console_showCursor__ + void __Console_showCursor__(struct __Console__ *console) { + __OsConsoleOutput_writeCText__(&console->output, __ConsoleAnsi_output_cursor_show__); + } + // # __CryptoRandom_do__ + void __CryptoRandom_do__( + struct __CryptoRandom__ *t, + char *out_buffer, + size_t buffer_len + ) { + struct __CryptoScalpiHash__ hasher; + __CryptoScalpiHash_reset__(&hasher); + __CryptoScalpiHash_doAny__(&hasher, &t->seed, sizeof(t->seed), out_buffer, buffer_len); + t->seed += 1; + } + // # __CryptoScalpiHash_doBit__ + void __CryptoScalpiHash_doBit__( + struct __CryptoScalpiHash__* t, + uint8_t bit, + char *dest, // canbe not zeroed + size_t dest_len + ) { + uint8_t bb = 2 - bit; + for (int i = 0; i < dest_len; i++) { + uint8_t *output_byte = (uint8_t*) &dest[i]; + t->a += *output_byte; + t->b += bb; + __CryptoScalpiHash_swapTwoBit__(t); + *output_byte += t->mask; + } + } + // # __CryptoScalpiHash_doByte__ + void __CryptoScalpiHash_doByte__( + struct __CryptoScalpiHash__ *t, + uint8_t byte, + char *dest, + size_t size + ) { + uint8_t pos = 0; + while (true) { + uint8_t bit = (byte >> pos) & 1; + __CryptoScalpiHash_doBit__(t, bit, dest, size); + if (pos == 7) break; + pos += 1; + } + } + // # __CryptoScalpiHash_do__ + void __CryptoScalpiHash_do__( + struct __CryptoScalpiHash__ *t, + const char *src, + size_t src_size, + char *dest, + size_t dest_size + ) { + for (int i = 0; i < src_size; i++) { + __CryptoScalpiHash_doByte__(t, src[i], dest, dest_size); + } + } + // # __CryptoScalpiHash_reset__ + void __CryptoScalpiHash_reset__( + struct __CryptoScalpiHash__ *t + ) { + t->mask = 0b00001111; + t->a = 0; + t->b = 0; + } + // # __CryptoScalpiHash_swapTwoBit__ + void __CryptoScalpiHash_swapTwoBit__(struct __CryptoScalpiHash__ *t) { + // truncate a and b to 3 bit. + uint8_t a = t->a & 0b111; + uint8_t b = t->b & 0b111; + + // save bits with swap + uint8_t tmp_a = (t->mask & 1 << a) >> a << b; + uint8_t tmp_b = (t->mask & 1 << b) >> b << a; + uint8_t tmp = tmp_a | tmp_b; + + // clear bits + t->mask &= 255 - (1 << a); + t->mask &= 255 - (1 << b); + + // set last bits + t->mask |= tmp; + } + // # __Crypto_sumBytes__ + uint8_t __Crypto_sumBytes__( + const char *data, + size_t data_len + ) { + char ret = 0; + for (size_t pos = 0; pos < data_len; pos++) { + ret += data[pos]; + } + return ret; + } + // # __Crypto_xorBytes__ + uint8_t __Crypto_xorBytes__( + const char *data, + size_t data_len + ) { + char ret = 0; + for (size_t pos = 0; pos < data_len; pos++) { + ret ^= data[pos]; + } + return ret; + } + // # __Crypto_xorCyclic__ + void __Crypto_xorCyclic__( + char *dest, + const char *a, + size_t dest_len, + const char *b, + size_t b_len + ) { + // expected dest_len == a.len + size_t ci = 0; // cyclical iterator + for (size_t pos = 0; pos < dest_len; pos++) { + dest[pos] = a[pos] ^ b[ci]; + ci += 1; + if (ci == b_len) ci = 0; + } + } + // # __FileComplete_clear__ + bool __FileComplete_clear__( + const char* file_name, + size_t file_name_len + ) { + bool ok = true; + __OsFileHandle__ file; + if (__OsFile_open__(&file, file_name, file_name_len)) { + __OsFile_clear__(file); + __OsFile_close__(file); + } else { + ok = false; + } + return ok; + } + // # __FileComplete_read__ + bool __FileComplete_read__( + uintptr_t *ret_data_ptr, + size_t *ret_file_data_size, // not zeroed by this func. increment instead. + const char* file_name, + size_t file_name_len, + uint8_t align + ) { + bool ok = true; + __OsFileHandle__ file; + + if(__OsFile_exist__(file_name, file_name_len)) { + ok = __OsFile_open__(&file, file_name, file_name_len); + } else { + ok = __OsFile_create__(&file, file_name, file_name_len); + } + + if (ok) { + size_t file_size = __OsFile_getSize__(file); + *ret_file_data_size += file_size; + + char* file_data; + if (__AlignedPtr_allocAny__(ret_data_ptr, align, file_size)) { + if ( __OsFile_readToAny__( file, ret_data_ptr, file_size, 0 )) { + } else { + ok = false; + } + } else { + ok = false; + } + __OsFile_close__(file); + } + return ok; + } + // # __FileComplete_write__ + bool __FileComplete_write__( + const char* file_name, + size_t file_name_len, + const char* bytes, + size_t bytes_len + ) { + bool ok = true; + __OsFileHandle__ file; + + if(__OsFile_exist__(file_name, file_name_len)) { + ok = __OsFile_open__(&file, file_name, file_name_len); + } else { + ok = __OsFile_create__(&file, file_name, file_name_len); + } + + if (ok) { + if (__OsFile_write__(file, bytes, bytes_len, 0)) { + __OsFile_truncate__(file); + } else { + ok = false; + } + __OsFile_close__(file); + } + return ok; + } + // # __File_clear__ + void __File_clear__( + __OsFileHandle__ file + ) { + __OsFile_setPos__(file, 0); + __OsFile_truncate__(file); + } + // # __Finder_init__ + void __Finder_init__( + struct Finder* t, + char* text, + size_t text_len, + char* desired, + size_t desired_len + ) { + t->pos = 0; + t->text.ptr = text; + t->text.len = text_len; + t->desired.ptr = desired; + t->desired.len = desired_len; + } + // # __Finder_next__ + bool __Finder_next__( + struct Finder* t, + size_t* out_pos + ) { + if (t->pos != t->text.len) { + char *data = &t->text.ptr[t->pos]; + size_t data_len = t->text.len - t->pos; + size_t finded = 0; + if ( true + and t->desired.len > 0 + and data_len >= t->desired.len + and __Mem_find__( + &finded, + data, + data_len, + t->desired.ptr, + t->desired.len + ) + ) { + size_t new_pos = t->pos + finded; + t->pos = new_pos + t->desired.len; + *out_pos = new_pos; + return true; + } + } + return false; + } + // # __FormatsHex_packBytesReverse__ + void __FormatsHex_packBytesReverse__( + char *hex, // expected len >= __Hex_lenFromBytesLen__(data_len) + char *data, + size_t data_len // expected >= 1 + ) { + size_t hex_pos = data_len << 1; + for (size_t data_pos = 0; data_pos < data_len; data_pos++) { + hex_pos -= 2; + __Hex_fromByte__(&hex[hex_pos], data[data_pos]); + } + } + // # __HexCapital_fromByte__ + void Hex_packByte_H(char data, char* hex_byte) { + hex_byte[0] = __HexCapital_fromNibble__((data & 0xF0) >> 4); + hex_byte[1] = __HexCapital_fromNibble__(data & 0x0F); + } + // # __HexCapital_fromBytes__ + void Hex_pack_H(char* hex, char* data, size_t data_len) { + // expected hex.len is __Hex_lenFromBytesLen__(len) + for(size_t pos = 0; pos < data_len; pos++) { + Hex_packByte_H(data[pos], &hex[pos * 2]); + } + } + // # __HexCapital_fromNibble__ + char __HexCapital_fromNibble__(char data) { + if (data <= 9) return '0' + data; + if (data <= 15) return 'A' + data - 10; + return 0; + } + // # __Hex_fromByte__ + void __Hex_fromByte__( + char *buffer, + uint8_t data + ) { + buffer[0] = __Hex_fromNibble__((data & 0xF0) >> 4); + buffer[1] = __Hex_fromNibble__(data & 0x0F); + } + // # __Hex_fromBytes__ + void __Hex_fromBytes__( + char *hex, // expected len >= __Hex_lenFromBytesLen__(data_len) + char *data, + size_t data_len + ) { + for(size_t pos = 0; pos < data_len; pos++) { + __Hex_fromByte__(&hex[pos << 1], data[pos]); + } + } + // # __Hex_fromNibble__ + char __Hex_fromNibble__(uint8_t data) { + if (data <= 9) return (uint8_t)'0' + data; + if (data <= 15) return (uint8_t)'a' + data - 10; + return 0; + } + // # __Logger_init__ + void __Logger_init__ (struct __Logger__* t) { + for (int i = 0; i < __arrayLen__(t->writers); i++) { + struct __Writer__* w = &t->writers[i]; + w->context = 0; + w->write = 0; + } + } + // # __Logger_writeToSelf__ + void __Logger_writeToSelf__(struct __Logger__* t, const char bytes[], size_t len) { + for (size_t i = 0; i < __arrayLen__(t->writers); i++) { + struct __Writer__* w = &t->writers[i]; + if (w->write) { + size_t writed = w->write(w->context, bytes, len); + } + } + } + // # __Math_ceilDiv32__ + uint32_t __Math_ceilDiv32__(uint32_t a, uint32_t b) { + return (a + b - 1) / b; + } + // # __Math_linearInterpolationWithCoef__ + __Float32__ __Math_linearInterpolationWithCoef__( + __Float32__ r1, + __Float32__ r2, + __Float32__ coef + ) { + return r1 + coef * (r2 - r1); + } + // # __Math_linearInterpolation__ + __Float32__ __Math_linearInterpolation__( + __Float32__ v1, + __Float32__ v2, + __Float32__ r1, + __Float32__ r2, + __Float32__ vx + ) { + return r1 + (vx - v1) / (v2 - v1) * (r2 - r1); + } + // # __MemListLink_init__ + void __MemListLink_init__( + struct __MemListLink__* link + ) { + __MemListLink_resetLinks__(link); + } + // # __MemListLink_isFirst__ + bool + __MemListLink_isFirst__( + struct __MemListLink__* link + ) { + struct __MemListLink__* prev = link->prev; + bool prev_is_null = (link->prev) == NULL; + return prev_is_null; + } + // # __MemListLink_resetLinks__ + void __MemListLink_resetLinks__(struct __MemListLink__* link) { + link->prev = NULL; + link->next = NULL; + link->list = NULL; + } + // # __MemList_init__ + void __MemList_init__( + struct __MemList__* list + ) { + list->first = NULL; + list->last = NULL; + list->count = 0; + } + // # __MemList_pop__ + void __MemList_pop__( + struct __MemList__ *list, + struct __MemListLink__ *item // expected item linked to list + ) { + if (list->count == 1) { + list->first = NULL; + list->last = NULL; + __MemListLink_resetLinks__(item); + } else { // count > 1 becouse != 1 and item is linked to list + if (item == list->first) { + struct __MemListLink__ *next = item->next; // not null becouse item is first and count > 1 + list->first = next; + next->prev = NULL; + + if (list->count == 2) { + list->last = next; + } + } else if (item == list->last) { + struct __MemListLink__ *prev = item->prev; // cannot be null becouse item is last and count > 1 + list->last = prev; + prev->next = NULL; + + if (list->count == 2) { + list->first = prev; + } + } else { // non first or last + // flatten prev and next + struct __MemListLink__ *next = item->next; // item is not last + struct __MemListLink__ *prev = item->prev; // item is not first + next->prev = prev; + prev->next = next; + } + __MemListLink_resetLinks__(item); + } + list->count -= 1; + } + // # __MemList_pushAfter__ + void __MemList_pushAfter__( + struct __MemList__* list, + struct __MemListLink__* after, + struct __MemListLink__* item + ) { + struct __MemListLink__* next = after->next; + if (next) { + next->prev = item; + } else { // after is last + list->last = item; + } + item->next = next; + after->next = item; + item->prev = after; + item->list = list; + list->count += 1; + } + // # __MemList_pushBefore__ + void __MemList_pushBefore__( + struct __MemList__* list, + struct __MemListLink__* before, + struct __MemListLink__* item + ) { + struct __MemListLink__* prev = before->prev; + if (prev) { // non firts + prev->next = item; + } else { // is first + list->first = item; + } + item->prev = prev; + before->prev = item; + item->next = before; + item->list = list; + list->count += 1; + } + // # __MemList_pushFirst__ + void __MemList_pushFirst__( + struct __MemList__ *list, + struct __MemListLink__ *item // expected freed item + ) { + struct __MemListLink__* first = list->first; + if (first) { // list not empty + first->prev = item; + item->next = first; + } else { // list is empty + list->last = item; + } + list->first = item; + item->list = list; + list->count += 1; + } + // # __MemList_pushLast__ + void __MemList_pushLast__( + struct __MemList__ *list, + struct __MemListLink__ *item + ) { + struct __MemListLink__* last = list->last; + if (last) { + last->next = item; + item->prev = last; + } else { // list empty + list->first = item; + } + list->last = item; + item->list = list; + list->count += 1; + } + // # __MemTree_fix_counts__ + void __MemTree_fix_counts__( + struct __MemTree__ *t, + size_t delta_count, + char action // __MemTree_fix_counts_Action__ + ) { + struct __MemTree__ *tree = t; + if (action == __MemTree_fix_counts_Action_plus__) { + while (tree) { + tree->count += delta_count; + tree = __MemTree_getParentOrNull__(tree); + } + } else { // minus + while (tree) { + tree->count -= delta_count; + tree = __MemTree_getParentOrNull__(tree); + } + } + } + // # __MemTree_getParentOrNull__ + struct __MemTree__* // can be null + __MemTree_getParentOrNull__ ( + struct __MemTree__ *tree + ) { + struct __MemList__ *list = tree->link.list; + if (list) { + struct __MemTree__ *parent = __TypedPtr_getParentPtrFromFieldPtr__(struct __MemTree__, childs, list); + return parent; + } + return NULL; + }; + // # __MemTree_getParent__ + void __MemTree_getParent__ ( + struct __MemTree__ **ret, + struct __MemTree__ *tree // expected child + ) { + struct __MemList__ *list = tree->link.list; + *ret = __TypedPtr_getParentPtrFromFieldPtr__(struct __MemTree__, childs, list); + }; + // # __MemTree_getPrev__ + struct __MemTree__* + __MemTree_getPrev__( + struct __MemTree__ *tree // expected __MemTree_isFirst__(tree) = false; + ) { + struct __MemListLink__ *prev_link = tree->link.prev; + return __TypedPtr_getParentPtrFromFieldPtr__(struct __MemTree__, link, prev_link); + } + // # __MemTree_growChilds__ + // convert childs to siblings + void __MemTree_growChilds__( + struct __MemTree__ *tree // expected tree with tree.childs.count > 0 and __MemTree_isChild__(tree) == true + ) { + struct __MemList__ *childs = &tree->childs; + size_t *childs_count = &childs->count; + while(*childs_count > 0) { + struct __MemTree__ *child = __MemTree_popFirstChild__(tree); + __MemTree_pushNext__(tree, child); + } + } + // # __MemTree_init__ + void __MemTree_init__( + struct __MemTree__ *t + ) { + t->count = 0; + t->nested = 0; + __MemList_init__ (&t->childs); + __MemListLink_init__ (&t->link); + } + // # __MemTree_isChild__ + bool __MemTree_isChild__ ( + struct __MemTree__ *tree + ) { + return tree->link.list != NULL; + }; + // # __MemTree_isFirst__ + bool __MemTree_isFirst__( + struct __MemTree__ *tree + ) { + return tree->link.prev == NULL; + } + // # __MemTree_popFirstChild__ + struct __MemTree__* + __MemTree_popFirstChild__( + struct __MemTree__ *tree // expected tree.childs.count > 0 + ) { + struct __MemListLink__ *child_link = tree->childs.first; + __MemList_pop__(&tree->childs, child_link); + return __TypedPtr_getParentPtrFromFieldPtr__(struct __MemTree__, link, child_link); + } + // # __MemTree_pop__ + // pop self from parent + void __MemTree_pop__( + struct __MemTree__ *t // expected __MemTree_isChild__(tree) == true + ) { + struct __MemTree__ *parent; + __MemTree_getParent__(&parent, t); + __MemList_pop__(&parent->childs, &t->link); + __MemTree_fix_counts__(parent, t->count + 1, __MemTree_fix_counts_Action_minus__); + __MemTree_fix_nested__(t, t->nested, __MemTree_fix_nested_Action_minus__); + } + // # __MemTree_pushChild__ + void __MemTree_pushChild__( + struct __MemTree__ *t, + struct __MemTree__ *item + ) { + __MemTree_fix_nested__(item, t->nested + 1, __MemTree_fix_nested_Action_plus__); + __MemList_pushLast__(&t->childs, &item->link); + __MemTree_fix_counts__(t, item->count + 1, __MemTree_fix_counts_Action_plus__); + } + // # __MemTree_fix_nested__ + void __MemTree_fix_nested__( + struct __MemTree__ *t, + size_t nested_delta, + char action // __MemTree_fix_nested_Action__ + ) { + struct __MemTree__ *tree = t; + if (action == __MemTree_fix_nested_Action_plus__) { + while (tree) { + tree->nested += nested_delta; + tree = __MemTree_traverse__(tree); + } + } else { // minus + while (tree) { + tree->nested -= nested_delta; + tree = __MemTree_traverse__(tree); + } + } + } + // # __MemTree_pushNext__ + void __MemTree_pushNext__( + struct __MemTree__ *t, // expected as child of another tree + struct __MemTree__ *item + ) { + struct __MemTree__ *parent; + __MemTree_getParent__(&parent, t); + __MemTree_fix_nested__(item, t->nested, __MemTree_fix_nested_Action_plus__); + __MemList_pushAfter__(&parent->childs, &t->link, &item->link); + __MemTree_fix_counts__(parent, item->count + 1, __MemTree_fix_counts_Action_plus__); + } + // # __MemTree_pushPrev__ + void __MemTree_pushPrev__( + struct __MemTree__ *t, // expected t is child + struct __MemTree__ *item + ) { + struct __MemTree__ *parent; + __MemTree_getParent__(&parent, t); // expected true by right argument + __MemTree_fix_nested__(item, t->nested, __MemTree_fix_nested_Action_plus__); + __MemList_pushBefore__(&parent->childs, &t->link, &item->link); + __MemTree_fix_counts__(parent, item->count + 1, __MemTree_fix_counts_Action_plus__); + } + // # __MemTree_traverse__ + struct __MemTree__* // return first_child or next or find next_parental or null + __MemTree_traverse__( + struct __MemTree__ *tree + ) { + if (tree->childs.first) { + struct __MemListLink__ *first = tree->childs.first; + return __TypedPtr_getParentPtrFromFieldPtr__(struct __MemTree__, link, first); + } else { + struct __MemListLink__ *next = tree->link.next; + if (next) { + return __TypedPtr_getParentPtrFromFieldPtr__(struct __MemTree__, link, next); + } else { + struct __MemTree__ *parent = __MemTree_getParentOrNull__(tree); + while (parent) { + struct __MemListLink__ *next_of_parent = parent->link.next; + if (next_of_parent) { + return __TypedPtr_getParentPtrFromFieldPtr__(struct __MemTree__, link, next_of_parent); + } + parent = __MemTree_getParentOrNull__(parent); + } + } + } + return NULL; + } + // # __Mem_copyBackward__ + void __Mem_copyBackward__(char* dest, const char* src, size_t size) { + size_t pos = size; + while(pos > 0) { + pos-=1; + dest[pos] = src[pos]; + } + } + // # __Mem_copy__ + void __Mem_copy__( // todo create macros __Mem_copyAny__ + char *dest, + const char *src, + size_t size + ) { + // i use this instead memcpy becouse clang-in-zig just replace memcpy to crash-zig-bloated-version code + size_t pos = 0; + while(pos < size) { + dest[pos] = src[pos]; + pos++; + } + } + // # __Mem_fill__ + void __Mem_fill__( + char *dest, + char symbol, + size_t len + ) { + for (size_t pos = 0; pos < len; pos++) { + dest[pos] = symbol; + } + } + // # __Mem_findDiffOrLen__ + size_t __Mem_findDiffOrLen__(const char a[], const char b[], size_t len) { + size_t pos = 0; + while(pos < len) { + if (a[pos] != b[pos]) break; + pos++; + } + + return pos; + } + // # __Mem_findFast__ + bool __Mem_findFast__( + size_t *ret_pos, // expected value 0 + const char *data, + size_t data_len, // expected > 0 + const char *desired, + size_t desired_len // expected > 0 // expected <= data_len // optimal > 4 + ) { + bool finded = false; + if (desired_len <= 4) { + if (data_len >= desired_len and __Mem_find__(ret_pos, data, data_len, desired, desired_len)) { + finded = true; + } + } else { + size_t final_check_pos = data_len - desired_len; + uint8_t target_sum = __Crypto_sumBytes__(desired, desired_len); + uint8_t target_xor = __Crypto_xorBytes__(desired, desired_len); + uint8_t hash_sum = __Crypto_sumBytes__(data, desired_len); + uint8_t hash_xor = __Crypto_xorBytes__(data, desired_len); + + for (size_t pos = 0; pos <= final_check_pos; pos++) { + if (true + and hash_xor == target_xor + and hash_sum == target_sum + ) { + if (__Mem_isEql__(&data[pos], desired, desired_len)) { + finded = true; + *ret_pos += pos; + break; + } + } + + uint8_t last_start_byte = data[pos]; + hash_xor ^= last_start_byte; + hash_sum -= last_start_byte; + + uint8_t new_byte_end = data[pos + desired_len]; + hash_xor ^= new_byte_end; + hash_sum += new_byte_end; + } + } + return finded; + } + // # __Mem_find__ + bool __Mem_find__( + size_t *ret_pos, // this value increment by this func + const char *data, + size_t data_len, // expected >= desired_len + const char *desired, + size_t desired_len // expected >= 1 + ) { + bool finded = false; + size_t last_pos = data_len - desired_len; + for (uintptr_t pos = 0; pos <= last_pos; pos++) { + size_t slice_len = data_len - pos; + if (slice_len >= desired_len) { + if (__Mem_isEql__(&data[pos], desired, desired_len)) { + *ret_pos = pos; + finded = true; + break; + } + } else { + break; + } + } + return finded; + } + // # __Mem_isEql__ + bool __Mem_isEql__( + const char* a, + const char* b, + size_t len + ) { + return __Mem_findDiffOrLen__(a, b, len) == len; + } + // # __Mem_isEql_test__ + bool __Mem_isEql_test__() { + return true + and (__Mem_isEql__("abcd", "abcd", 4)) + and (__Mem_isEql__("abcd", "abce", 4) == false) + and (__Mem_isEql__("abcdasdasd", "asd", 3) == false) + ; + } + // # __Mem_reverse__ + void __Mem_reverse__( + char *dest, + const char *src, + size_t len + ) { + src = &src[len - 1]; + size_t iter = 0; + for(; iter < len; iter++, dest++, src--) { + *dest = *src; + } + } + // # __Nibble_fromAp__ + uint8_t __Nibble_fromAp__(char data) { + if (data >= 'A' && data <= 'P') { + return data - 'A'; + } else if (data >= 'a' && data <= 'p') { + return data - 'a'; + } + return 0; + } + // # __Nibble_fromHexNibble__ + char __Nibble_fromHexNibble__(char nibble) { + if (nibble >= 'a') return 10 + nibble - 'a'; + if (nibble >= 'A') return 10 + nibble - 'A'; + return nibble - '0'; + } + // # __OsConsoleFlags_apply__ + bool __OsConsoleFlags_apply__( + struct __OsConsoleFlags__ *t, + struct __OsConsoleInput__ *input, + struct __OsConsoleOutput__ *output + ) { + // expected inited + + bool ok = true; + #if __target_os__ == __TargetOs_windows__ + int result1 = SetConsoleMode(input->handle, t->input_mode); + if (result1 == 0) { + ok = false; + // todo GetLastError(); + } + + int result2 = SetConsoleMode(output->__OsConsoleOutput_handle__, t->output_mode); + if (result2 == 0) { + ok = false; + // todo GetLastError(); + } + #elif __target_os__ == __TargetOs_linux__ + tcsetattr(input->fileno, TCSANOW, &t->termios); + tcsetattr(output->__OsConsoleOutput_handle__, TCSANOW, &t->termios); + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + return ok; + } + // # __OsConsoleFlags_init__ + bool __OsConsoleFlags_init__(struct __OsConsoleFlags__ *t, struct __OsConsoleInput__* input, struct __OsConsoleOutput__ *output) { + bool ok = true; + #if __target_os__ == __TargetOs_windows__ + bool result1 = GetConsoleMode(input->handle, &t->input_mode); + if (result1 != 0) { + bool result2 = GetConsoleMode(output->__OsConsoleOutput_handle__, &t->output_mode); + if (result2 != 0) { + t->inited = true; + } else { + ok = false; + } + } else { + ok = false; + } + #elif __target_os__ == __TargetOs_linux__ + int result = tcgetattr(input->fileno, &t->termios); + if (result == 0) { + t->inited = true; + } else { + ok = false; + } + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + return ok; + } + // # __OsConsoleFlags_setNonCanonicalMode__ + bool __OsConsoleFlags_setNonCanonicalMode__(struct __OsConsoleFlags__ *t) { + bool ok = true; + #if __target_os__ == __TargetOs_windows__ + uint32_t input = t->input_mode; + input = __BitsU32_toggle__(input, ENABLE_EXTENDED_FLAGS, true); + input = __BitsU32_toggle__(input, ENABLE_ECHO_INPUT, false); // print pressed keys + input = __BitsU32_toggle__(input, ENABLE_LINE_INPUT, false); // wait '\n' (buffering on enter) + input = __BitsU32_toggle__(input, ENABLE_VIRTUAL_TERMINAL_INPUT, true); + input = __BitsU32_toggle__(input, ENABLE_PROCESSED_INPUT, false); // CTRL+C + input = __BitsU32_toggle__(input, ENABLE_MOUSE_INPUT, false); + input = __BitsU32_toggle__(input, ENABLE_QUICK_EDIT_MODE, true); // enable mouse select and copy + input = __BitsU32_toggle__(input, ENABLE_WINDOW_INPUT, false); // reported of change size of the console screen buffer + input = __BitsU32_toggle__(input, ENABLE_INSERT_MODE, true); // When enabled, text entered in a console window will be inserted at the current cursor location and all text following that location will not be overwritten. When disabled, all following text will be overwritten. + t->input_mode = input; + + uint32_t output = t->output_mode; + output = __BitsU32_toggle__(output, ENABLE_LVB_GRID_WORLDWIDE, true); // enable colors + output = __BitsU32_toggle__(output, ENABLE_VIRTUAL_TERMINAL_PROCESSING, true); // emulate VT100 + output = __BitsU32_toggle__(output, ENABLE_PROCESSED_OUTPUT, true); // Backspace, tab, bell, carriage return, and line feed characters are processed + output = __BitsU32_toggle__(output, ENABLE_WRAP_AT_EOL_OUTPUT, false); // disable line wrap + output = __BitsU32_toggle__(output, DISABLE_NEWLINE_AUTO_RETURN, true); + t->output_mode = output; + #elif __target_os__ == __TargetOs_linux__ + // clear c_cc + cc_t* cc = &t->termios.c_cc[0]; // cc_t c_cc[NCCS] + for (int i = 0; i < NCCS ; i++) { + cc[i] = 0; + } + + // timers off + cc = &t->termios.c_cc[0]; + cc[VTIME] = 0; + cc[VMIN] = 1; + + uint32_t cflag = t->termios.c_cflag; + cflag = __BitsU32_toggle__(cflag, CS8, true); // use 8 bit + cflag = __BitsU32_toggle__(cflag, CSTOPB, false); // two stops bits + cflag = __BitsU32_toggle__(cflag, PARENB, false); // parity check + cflag = __BitsU32_toggle__(cflag, PARODD, false); // parity check + t->termios.c_cflag = cflag; + + uint32_t lflag = t->termios.c_lflag; + lflag = __BitsU32_toggle__(lflag, ISIG, false); // disable react to Ctrl+C + lflag = __BitsU32_toggle__(lflag, ICANON, false); // no wait '\n' + lflag = __BitsU32_toggle__(lflag, ECHO, false); // print pressed keys + lflag = __BitsU32_toggle__(lflag, ECHOE, false); // mashing + lflag = __BitsU32_toggle__(lflag, ECHONL, false); // print NL + lflag = __BitsU32_toggle__(lflag, ECHOK, false); // nl after clear line + lflag = __BitsU32_toggle__(lflag, ECHOKE, false); // print NL after BS + lflag = __BitsU32_toggle__(lflag, ECHOPRT, false); // print BS (BS SP BS) + lflag = __BitsU32_toggle__(lflag, IEXTEN, false); // special funcs + t->termios.c_lflag = lflag; + + uint32_t iflag = t->termios.c_iflag; + iflag = __BitsU32_toggle__(iflag, IGNBRK, true); // ignore break control + iflag = __BitsU32_toggle__(iflag, BRKINT, true); // do not delete all data after break control + iflag = __BitsU32_toggle__(iflag, IXON, false); // disable react to Ctrl+S Ctlr+Q + iflag = __BitsU32_toggle__(iflag, ISTRIP, false); // strip + iflag = __BitsU32_toggle__(iflag, INLCR, false); // convert NL to CR + iflag = __BitsU32_toggle__(iflag, ICRNL, false); // convert CR to NL + iflag = __BitsU32_toggle__(iflag, XCASE, false); // convert register to UP + iflag = __BitsU32_toggle__(iflag, IUCLC, false); // convert register to down + iflag = __BitsU32_toggle__(iflag, IGNPAR, true); // ignore framing or parity errors + iflag = __BitsU32_toggle__(iflag, IMAXBEL, false); // no bell + t->termios.c_iflag = iflag; + + uint32_t oflag = t->termios.c_oflag; + oflag = __BitsU32_toggle__(oflag, ONOCR, false); // on start line // Auto CR + oflag = __BitsU32_toggle__(oflag, ONLRET, false); // on end line // Auto CR + oflag = __BitsU32_toggle__(oflag, OPOST, true); // \_(O_o)_/ + oflag = __BitsU32_toggle__(oflag, ONLCR, true); // NL to CR + oflag = __BitsU32_toggle__(oflag, OCRNL, false); // CR to NL + oflag = __BitsU32_toggle__(oflag, OLCUC, false); // convert to CAPS + oflag = __BitsU32_toggle__(oflag, XTABS, false); // convert tab + oflag = __BitsU32_toggle__(oflag, TAB3, false); // convert tab + oflag = __BitsU32_toggle__(oflag, OFDEL, false); // use null for deleted symbol + t->termios.c_oflag = oflag; + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + return ok; + } + // # __OsConsoleInput_getCountOfUnreaded__ + bool __OsConsoleInput_getCountOfUnreaded__(struct __OsConsoleInput__* t, size_t *ret_unreaded) { + bool ok = true; + #if __target_os__ == __TargetOs_windows__ + DWORD unreaded = 0; + if ( GetNumberOfConsoleInputEvents(t->handle, &unreaded) ) { + *ret_unreaded += unreaded; + } else { + ok = false; + } + #elif __target_os__ == __TargetOs_linux__ + int unreaded = 0; + int result = ioctl(t->fileno, FIONREAD, &unreaded); + *ret_unreaded += unreaded; + #else + #error "__target_os__ not implemented" + #endif + return ok; + } + // # __OsConsoleInput_init__ + void __OsConsoleInput_init__( + struct __OsConsoleInput__* t, + __OsConsoleInputHandle__ input_hanle + ) { + #if __target_os__ == __TargetOs_windows__ + t->handle = input_hanle; + #elif __target_os__ == __TargetOs_linux__ + t->handle = input_hanle; + t->fileno = fileno(t->handle); + #else + #error "__target_os__ not implemented" + #endif + } + // # __OsConsoleInput_readByte__ + bool __OsConsoleInput_readByte__( + char *ret_byte, + struct __OsConsoleInput__ *t + ) { + bool ok = true; + #if __target_os__ == __TargetOs_windows__ + INPUT_RECORD key; + DWORD picked = 0; + if ( ReadConsoleInputA(t->handle, &key, 1, &picked) ) { + if (picked != 0) { + if (key.EventType == KEY_EVENT) { + KEY_EVENT_RECORD *event = &key.Event.KeyEvent; + if (event->bKeyDown != 0) { + if (event->uChar.AsciiChar != 0) { + *ret_byte = event->uChar.AsciiChar; + } else {ok = false;} + } else {ok = false;} + } else {ok = false;} + } else {ok = false;} + } else {ok = false;} + #elif __target_os__ == __TargetOs_linux__ + ssize_t result = read(t->fileno, ret_byte, 1); + if (result != 1) {ok = false;} + #else + #error "__target_os__ not implemented" + #endif + return ok; + } + // # __OsConsoleOutput_getSize__ + void __OsConsoleOutput_getSize__ ( + struct __OsConsoleOutput__ *t, + struct __Math2dPosU__ *ret_pos + ) { + #if __target_os__ == __TargetOs_windows__ + CONSOLE_SCREEN_BUFFER_INFO csbi; + GetConsoleScreenBufferInfo(t->__OsConsoleOutput_handle__, &csbi); + int x = csbi.srWindow.Right - csbi.srWindow.Left + 1; + int y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; + ret_pos->x = x; + ret_pos->y = y; + // printf("%d, %d x %d\n", __LINE__, x, y); + #elif __target_os__ == __TargetOs_linux__ + struct winsize w; + ioctl(t->__OsConsoleOutput_handle__, TIOCGWINSZ, &w); + ret_pos->x = w.ws_col; + ret_pos->y = w.ws_row; + #else + #error "__target_os__ not implemented" + #endif + } + // # __OsConsoleOutput_init__ + void __OsConsoleOutput_init__(struct __OsConsoleOutput__* output, __OsConsoleOutputHandle__ handle) { + output->__OsConsoleOutput_handle__ = handle; + #if __target_os__ == __TargetOs_windows__ + #elif __target_os__ == __TargetOs_linux__ + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + } + // # __OsConsoleOutput_write__ + bool __OsConsoleOutput_write__( + struct __OsConsoleOutput__* os_console_output, + const char* data, + size_t _len + ) { + bool ok = true; + // support null-string // todo remove me + size_t len = _len; + if (len == 0) { + while(data[len] != 0) len += 1; + } + + #if __target_os__ == __TargetOs_windows__ + unsigned long writed = 0; + WriteConsoleA(os_console_output->__OsConsoleOutput_handle__, data, len, &writed, NULL); + len = writed; + #elif __target_os__ == __TargetOs_linux__ + // stdin = 0 + // stdout = 1 + // stderr = 2 + if (write(1, data, len) == len) { + } else { + ok = false; + } + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + + return ok; + } + // # __OsEnvHome_getLen__ + size_t __OsEnvHome_getLen__() { + size_t len = 0; + #if __target_os__ == __TargetOs_windows__ + char* home_drive = getenv("HOMEDRIVE"); + len += __ZText_countLen__(home_drive); + char* home_path = getenv("HOMEPATH"); + len += __ZText_countLen__(home_path); + #elif __target_os__ == __TargetOs_linux__ + char* home = getenv("HOME"); + len += __ZText_countLen__(home); + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + return len; + } + // # __OsEnvHome_write__ + void __OsEnvHome_write__( + char* buffer // expected len >= __OsEnvHome_getLen__() + ) { + #if __target_os__ == __TargetOs_windows__ + size_t writed = 0; + + // write HOMEDRIVE + char* home_drive = getenv("HOMEDRIVE"); + size_t home_drive_len = __ZText_countLen__(home_drive); + __Mem_copy__(&buffer[writed], home_drive, home_drive_len); + writed += home_drive_len; + + // write HOMEPATH + char* home_path = getenv("HOMEPATH"); + size_t home_path_len = __ZText_countLen__(home_path); + __Mem_copy__(&buffer[writed], home_path, home_path_len); + writed += home_path_len; + #elif __target_os__ == __TargetOs_linux__ + char* home = getenv("HOME"); + size_t len = __ZText_countLen__(home); + __Mem_copy__(buffer, home, len); + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + } + // # __OsFallbackConsole_write__ + size_t + __OsFallbackConsole_write__ ( + void* unused_ctx, + char* data, + size_t len + ) { + #if __target_os__ == __TargetOs_windows__ + struct __OsConsoleOutput__ console_output; + __OsConsoleOutput_init__(&console_output, GetStdHandle(STD_OUTPUT_HANDLE)); + __OsConsoleOutput_write__(&console_output, data, len); + #elif __target_os__ == __TargetOs_linux__ + __OsConsoleOutput_write__ (NULL, data, len); + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + return len; + } + // # __OsFile_clear__ + void __OsFile_clear__( + __OsFileHandle__ file + ) { + __OsFile_setPos__(file, 0); + __OsFile_truncate__(file); + } + // # __OsFile_close__ + void __OsFile_close__( + __OsFileHandle__ file + ) { + #if __target_os__ == __TargetOs_windows__ + CloseHandle(file); + #elif __target_os__ == __TargetOs_linux__ + close(file); + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + } + // # __OsFile_create__ + bool __OsFile_create__( + __OsFileHandle__ *ret, + const char file_name[], + size_t file_name_len // expected < __OsFilePathLen_max__ + ) { + bool ok = true; + #if __target_os__ == __TargetOs_windows__ + char file_name_z[__OsFilePathLen_max__ + 1]; // null terminated string + __Mem_copy__(file_name_z, file_name, file_name_len); + file_name_z[file_name_len] = 0; + + HANDLE file = CreateFile( // open + file_name_z, // [in] LPCSTR lpFileName, + GENERIC_WRITE | GENERIC_READ, // [in] DWORD dwDesiredAccess, + 0, // [in] DWORD dwShareMode, // TODO also try FILE_SHARE_WRITE + NULL, // [in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes, + OPEN_ALWAYS, // [in] DWORD dwCreationDisposition, + FILE_ATTRIBUTE_NORMAL, // [in] DWORD dwFlagsAndAttributes, + NULL // [in, optional] HANDLE hTemplateFile + ); + if (file != INVALID_HANDLE_VALUE) { + *ret = file; + } else { + ok = false; + } + #elif __target_os__ == __TargetOs_linux__ + char file_name_z[__OsFilePathLen_max__ + 1]; // create null terminated string + __Mem_copy__(file_name_z, file_name, file_name_len); + file_name_z[file_name_len] = 0; + + int file = creat(file_name_z, 0777); + if (file != -1) { + *ret = file; + } else { + ok = false; + } + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + return ok; + } + // # __OsFile_exist__ + bool __OsFile_exist__( + const char* file_name, + size_t file_name_len // expected < __OsFilePathLen_max__ + ) { + bool ok = true; + #if __target_os__ == __TargetOs_windows__ + char file_name_z[__OsFilePathLen_max__ + 1]; // create null terminated string + __Mem_copy__(file_name_z, file_name, file_name_len); + file_name_z[file_name_len] = 0; + + DWORD attrs = GetFileAttributesA(file_name_z); + if (true + and (attrs != INVALID_FILE_ATTRIBUTES) + and (!(attrs & FILE_ATTRIBUTE_DIRECTORY)) + ) { + } else { + ok = false; + } + #elif __target_os__ == __TargetOs_linux__ + char file_name_z[__OsFilePathLen_max__ + 1]; // create null terminated string + __Mem_copy__(file_name_z, file_name, file_name_len); + file_name_z[file_name_len] = 0; + + struct stat buffer; + if (stat(file_name_z, &buffer) == 0) { + } else { + ok = false; + } + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + return ok; + } + // # __OsFile_getPos__ + size_t __OsFile_getPos__( + __OsFileHandle__ file + ) { + #if __target_os__ == __TargetOs_windows__ + LARGE_INTEGER liPosition = {0}; + LARGE_INTEGER liNewPosition = {0}; + BOOL sfp_result = SetFilePointerEx ( + file, + liPosition, + &liNewPosition, + FILE_CURRENT + ); + if (sfp_result == FALSE) { + // unexpected + int err = GetLastError(); + printf("%d SetFilePointerEx error: %d", __LINE__, err); + } + return liNewPosition.QuadPart; + #elif __target_os__ == __TargetOs_linux__ + return lseek(file, 0, SEEK_CUR); + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + } + // # __OsFile_getSize__ + size_t __OsFile_getSize__( + __OsFileHandle__ file + ) { + #if __target_os__ == __TargetOs_windows__ + LARGE_INTEGER size; + if (GetFileSizeEx(file, &size)) { + return size.QuadPart; + } else { + // unexpected + return 0; + } + #elif __target_os__ == __TargetOs_linux__ + struct stat st; + fstat(file, &st); + return st.st_size; + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + } + // # __OsFile_openOrCreate__ + bool __OsFile_openOrCreate__( + __OsFileHandle__ *ret, + const char file_name[], + size_t file_name_len // expected < __OsFilePathLen_max__ + ) { + if (__OsFile_exist__(file_name, file_name_len)) { + return __OsFile_open__(ret, file_name, file_name_len); + } else { + return __OsFile_create__(ret, file_name, file_name_len); + } + } + // # __OsFile_open__ + bool __OsFile_open__( + __OsFileHandle__ *ret, + const char file_name[], + size_t file_name_len // expected < __OsFilePathLen_max__ + ) { + bool ok = true; + #if __target_os__ == __TargetOs_windows__ + char file_name_z[__OsFilePathLen_max__ + 1]; // null terminated string + __Mem_copy__(file_name_z, file_name, file_name_len); + file_name_z[file_name_len] = 0; + + HANDLE file = CreateFile( // open + file_name_z, // [in] LPCSTR lpFileName, + GENERIC_WRITE | GENERIC_READ, // [in] DWORD dwDesiredAccess, + 0, // [in] DWORD dwShareMode, // TODO also try FILE_SHARE_WRITE + NULL, // [in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes, + OPEN_EXISTING, // [in] DWORD dwCreationDisposition, + FILE_ATTRIBUTE_NORMAL, // [in] DWORD dwFlagsAndAttributes, + NULL // [in, optional] HANDLE hTemplateFile + ); + if (file != INVALID_HANDLE_VALUE) { + *ret = file; + } else { + ok = false; + } + #elif __target_os__ == __TargetOs_linux__ + char file_name_z[__OsFilePathLen_max__ + 1]; // null terminated string + __Mem_copy__(file_name_z, file_name, file_name_len); + file_name_z[file_name_len] = 0; + + // open + int file = open(file_name_z, O_RDWR); + if (file != -1) { + *ret = file; + } else { + ok = false; + } + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + return ok; + } + // # __OsFile_readToBuffer__ + bool __OsFile_readToBuffer__( + __OsFileHandle__ file, + char *buffer, + size_t buffer_len, + size_t offset + ) { + bool ok = true; + size_t readed = 0; + while (ok and (readed < buffer_len)) { + __OsFile_setPos__(file, offset + readed); + #if __target_os__ == __TargetOs_windows__ + __OsFile_setPos__(file, offset + readed); + LPDWORD readed_atom = 0; + if (ReadFile(file, &buffer[readed], buffer_len - readed, &readed_atom, NULL)) { + readed += (size_t) readed_atom; + } else { + ok = false; + } + #elif __target_os__ == __TargetOs_linux__ + __OsFile_setPos__(file, offset + readed); + ssize_t read_result = read(file, &buffer[readed], buffer_len - readed); + if (read_result >= 0) { + readed += read_result; + } else { + ok = false; + } + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + } + return ok; + } + // # __OsFile_setPos__ + void __OsFile_setPos__( + __OsFileHandle__ file, + size_t pos + ) { + #if __target_os__ == __TargetOs_windows__ + LARGE_INTEGER liPosition = {0}; + liPosition.QuadPart = pos; + + BOOL sfp_result = SetFilePointerEx(file, liPosition, NULL, FILE_BEGIN); + if (sfp_result == FALSE) { + // unexpeced + printf("%d, unexpected SetFilePointer result", __LINE__); + } + #elif __target_os__ == __TargetOs_linux__ + lseek(file, pos, SEEK_SET); + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + } + // # __OsFile_truncate__ + void __OsFile_truncate__( + __OsFileHandle__ file + ) { + #if __target_os__ == __TargetOs_windows__ + bool ok = true; + if (FlushFileBuffers(file)) { + if (SetEndOfFile(file)) { + if (FlushFileBuffers(file)) { + } else { // unexpected + ok = false; + printf("%d unexpected retusult of FlushFileBuffers", __LINE__); + } + } else { // unexpected + ok = false; + printf("%d unexpected retusult of SetEndOfFile", __LINE__); + } + } else { // unexpected + ok = false; + printf("%d unexpected retusult of FlushFileBuffers", __LINE__); + } + if (!ok) printf("%d failue", __LINE__); + // return ok; not needed to real return ok state becouse expected posibly truncate any file without errors. + #elif __target_os__ == __TargetOs_linux__ + size_t current_pos = __OsFile_getPos__(file); + ftruncate(file, current_pos); + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + } + // # __OsFile_write__ + bool __OsFile_write__( + __OsFileHandle__ file, + const char* data, + size_t data_len, + size_t offset + ) { + bool ok = true; + size_t writed = 0; + while (ok and (writed < data_len)) { + __OsFile_setPos__(file, offset + writed); + #if __target_os__ == __TargetOs_windows__ + DWORD atom_writed = 0; + if ( WriteFile(file, &data[writed], data_len - writed, &atom_writed, NULL) ) { + writed += atom_writed; + ok = FlushFileBuffers(file); + } else { + ok = false; + } + #elif __target_os__ == __TargetOs_linux__ + ssize_t atom_write = write(file, &data[writed], data_len - writed); + if (atom_write != -1) { + writed += atom_write; + } else { + ok = false; + } + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + } + return ok; + } + // # __OsHelper_deinit__ + void __OsHelper_deinit__(struct __OsHelper__*t) { + #if __target_os__ == __TargetOs_windows__ + #if __with_network__ + WSACleanup(); + #endif + FreeLibrary(t->instance); + #elif __target_os__ == __TargetOs_linux__ + // nothing to do + #else + #error "__target_os__ not implemented" + #endif + } + // # __OsHelper_init__ + bool __OsHelper_init__(struct __OsHelper__* t) { + bool ok = true; + #if __target_os__ == __TargetOs_windows__ + HMODULE instance = GetModuleHandleA(NULL); + if (instance != NULL) { + t->instance = instance; + + HANDLE console_input_handle = GetStdHandle(STD_INPUT_HANDLE); + if (console_input_handle != INVALID_HANDLE_VALUE) { + t->console_input_handle = console_input_handle; + + HANDLE console_output_handle = GetStdHandle(STD_OUTPUT_HANDLE); + if (console_output_handle != INVALID_HANDLE_VALUE) { + t->console_output_handle = console_output_handle; + + #if __with_network__ + if ( + WSAStartup( + 514, // wVersionRequested ver 2.2 + &t->wsdata + ) == 0 + ) { } else { + ok = false; + } + #endif + } else { + ok = false; + } + } else { + ok = false; + } + } else { + ok = false; + } + #elif __target_os__ == __TargetOs_linux__ + t->console_input_handle = stdin; + t->console_output_handle = 1; // standart output + #else + #error "__target_os__ not implemented" + #endif + return ok; + } + // # __OsHelper_process__ + void __OsHelper_process__(struct __OsHelper__* t) { + #if __target_os__ == __TargetOs_windows__ + MSG msg; + if (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessageA(&msg); + } + #elif __target_os__ == __TargetOs_linux__ + // nothing to do + #else + #error "__target_os__ not implemented" + #endif + } + // # __OsMem_alloc__ + bool __OsMem_alloc__( // TODO use real system alloc? + uintptr_t *ret, + size_t size + ) { + bool ok = true; + char* ptr = malloc(size); + if (ptr) { + *ret = (uintptr_t) ptr; + } else { + ok = false; + // TODO print debug + } + return ok; + } + // # __OsMem_free__ + void __OsMem_free__(uintptr_t ptr) { + free((void*) ptr); + } + // # __Os_getTick__ + uint64_t __Os_getTick__() { + #if __target_os__ == __TargetOs_windows__ + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + uint64_t ft64; + __Mem_copy__((char*) &ft64, (char*) &ft, 8); + return ft64 / 10000; // in ft is intervals * 100 ns. to ms need * 100 / 1000000 + #elif __target_os__ == __TargetOs_linux__ + // NOT TESTED + struct timespec ts; + clock_gettime(CLOCK_REALTIME, (void*)&ts); + uint64_t ms = ts.tv_sec * 1000 + ts.tv_nsec / 1000000; + return ms; + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + } + // # __Os_sleep__ + void __Os_sleep__(uint64_t ms) { + int a = 10; + #if __target_os__ == __TargetOs_windows__ + Sleep(ms); + #elif __target_os__ == __TargetOs_linux__ + struct timespec delay; + delay.tv_sec = ms / 1000; + delay.tv_nsec = (ms % 1000) * 1000000; + nanosleep(&delay, NULL); + #elif __target_os__ == __TargetOs_linuxOld__ + if (milliseconds >= 1000) { + sleep(milliseconds / 1000); + } + usleep((milliseconds % 1000) * 1000); + #else + #error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)" + #endif + } + // # __TerminalInput_grab__ + bool __TerminalInput_grab__( + __ConsoleAnsiInputKey__ *ret_key, + struct __TerminalInput__ *t + ) { + if (t->ungrabed > 0) { + char* bytes = &t->buffer[0]; + size_t bytes_len = t->ungrabed; + struct __ConsoleAnsiInputKey_SequenceParser__ parsed; + if (__ConsoleAnsi_input_Key_SequenceParser_fromBytes__(&parsed, bytes, bytes_len)) { + __TerminalInput_shift__(t, parsed.used); + *ret_key = parsed.sequence; + return true; + } else { + __ConsoleAnsiInputKey__ key = bytes[0]; + __TerminalInput_shift__(t, 1); + *ret_key = key; + return true; + } + } + return false; + } + // # __TerminalInput_init__ + void __TerminalInput_init__( + struct __TerminalInput__ *t + ) { + t->ungrabed = 0; + } + // # __TerminalInput_shift__ + void __TerminalInput_shift__( + struct __TerminalInput__ *t, + size_t val + ) { + __Mem_copy__(&t->buffer[0], &t->buffer[val], __TerminalInput_size__ - val); + t->ungrabed -= val; + } + // # __TerminalOutputCursorPos_init__ + void __TerminalOutputCursorPos_init__( + struct __Math2dPosU__ *cursor_pos + ) { + cursor_pos->x = 0; + cursor_pos->y = 0; + } + // # __TerminalOutputCursorPos_move__ + // not use me directly. use __Terminal_cursorMove__ instead + void __TerminalOutputCursorPos_move__( + struct __Terminal__ *terminal, + size_t new_pos_x, + size_t new_pos_y + ) { + struct __Math2dPosU__ *cursor_pos = &terminal->output.cursor_pos; + if (new_pos_x != cursor_pos->x) { // move_from_x + // reset x pos + __OsConsoleOutput_write__(&terminal->console->output, "\r", 0); + cursor_pos->x = 0; + + if (new_pos_x != 0) { + __Terminal_Output_Cursor_shiftRight__(terminal, new_pos_x - cursor_pos->x); + } + } + + if (new_pos_y != cursor_pos->y) { // move_from_y + if (new_pos_y > cursor_pos->y) { + __Terminal_Output_Cursor_shiftDown__(terminal, new_pos_y - cursor_pos->y); + } else { + __Terminal_Output_Cursor_shiftUp__(terminal, cursor_pos->y - new_pos_y); + } + } + } + // # __Terminal_Output_Cursor_shiftDown__ + void __Terminal_Output_Cursor_shiftDown__( + struct __Terminal__ *terminal, + size_t delta + ) { + struct __Math2dPosU__ *cursor_pos = &terminal->output.cursor_pos; + if (delta != 0){ + // print_to_console(__ConsoleAnsi_control__ + delta + "B"); + char buffer[1024]; + size_t writed = 0; + writed += __CText_write__(&buffer[0], __ConsoleAnsi_control__); + writed += __Text_formatU64ToBuffer__(&buffer[writed], delta, 1); + writed += __CText_write__(&buffer[writed], "B"); + __OsConsoleOutput_write__(&terminal->console->output, &buffer[0], writed); + cursor_pos->y += delta; + } + } + // # __Terminal_Output_Cursor_shiftLeft__ + void __Terminal_Output_Cursor_shiftLeft__( + struct __Terminal__ *terminal, + size_t delta + ) { + struct __Math2dPosU__ *cursor_pos = &terminal->output.cursor_pos; + if (delta != 0) { + // print_to_console(__ConsoleAnsi_control__ + delta + "D"); + char buffer[1024]; + size_t writed = 0; + writed += __CText_write__(&buffer[0], __ConsoleAnsi_control__); + writed += __Text_formatU64ToBuffer__(&buffer[writed], delta, 1); + writed += __CText_write__(&buffer[writed], "D"); + __OsConsoleOutput_write__(&terminal->console->output, &buffer[0], writed); + cursor_pos->x -= delta; + } + } + // # __Terminal_Output_Cursor_shiftRight__ + void __Terminal_Output_Cursor_shiftRight__( + struct __Terminal__ *terminal, + size_t delta + ) { + struct __Math2dPosU__ *cursor_pos = &terminal->output.cursor_pos; + if (delta != 0) { + // print_to_console(__ConsoleAnsi_control__ + delta + "C"); + char buffer[1024]; + size_t writed = 0; + writed += __CText_write__(&buffer[0], __ConsoleAnsi_control__); + writed += __Text_formatU64ToBuffer__(&buffer[writed], delta, 1); + writed += __CText_write__(&buffer[writed], "C"); + __OsConsoleOutput_write__(&terminal->console->output, &buffer[0], writed); + cursor_pos->x += delta; + } + } + // # __Terminal_Output_Cursor_shiftUp__ + void __Terminal_Output_Cursor_shiftUp__( + struct __Terminal__ *terminal, + size_t delta + ) { + struct __Math2dPosU__ *cursor_pos = &terminal->output.cursor_pos; + if (delta != 0) { + // print_to_console(__ConsoleAnsi_control__ + delta + "A"); + char buffer[1024]; + size_t writed = 0; + writed += __CText_write__(&buffer[0], __ConsoleAnsi_control__); + writed += __Text_formatU64ToBuffer__(&buffer[writed], delta, 1); + writed += __CText_write__(&buffer[writed], "A"); + __OsConsoleOutput_write__(&terminal->console->output, &buffer[0], writed); + cursor_pos->y -= delta; + } + } + // # __Terminal_clearOutput__ + void __Terminal_clearOutput__(struct __Terminal__ *terminal) { + struct __Console__* console = terminal->console; + __ConsoleOutput_cursorHide__(&terminal->console->output); + size_t pos_y = 0; + while (pos_y < terminal->output.size.y) { + __Terminal_cursorMove__(terminal, 0, pos_y); + __OsConsoleOutput_writeCText__(&console->output, __ConsoleAnsi_output_clear_line__); + pos_y += 1; + } + __Console_showCursor__(console); + } + // # __Terminal_cursorMove__ + void __Terminal_cursorMove__( // todo rename to cursorMoveOrReset + struct __Terminal__ *terminal, + size_t pos_x, + size_t pos_y + ) { + if ((pos_x > terminal->output.size.x) or (pos_y > terminal->output.size.y)) { + terminal->output.cursor_pos.x = terminal->output.size.x - 1; + terminal->output.cursor_pos.y = terminal->output.size.y - 1; + __Terminal_moveCursorToStartOfLine__(terminal); + } else { + __TerminalOutputCursorPos_move__(terminal, pos_x, pos_y); + } + } + // # __Terminal_deinitOutput__ + void __Terminal_deinitOutput__(struct __Terminal__ *terminal) { + struct __Console__ *console = terminal->console; + struct __OsConsoleOutput__ *console_output = &console->output; + __OsConsoleOutput_writeCText__(console_output, __ConsoleAnsiOutputSettings_enableLineWrap__); + __Terminal_resetColors__(terminal); + __OsConsoleOutput_writeCText__(console_output, __ConsoleAnsiOutputFontStyle_command_reset__); + __OsConsoleOutput_writeCText__(console_output, "\r\n"); + __Console_showCursor__(console); + } + // # __Terminal_deinit__ + bool __Terminal_deinit__(struct __Terminal__ *terminal) { + bool ok = true; + struct __Console__* console = terminal->console; + __Terminal_deinitOutput__(terminal); + if (__OsConsoleFlags_apply__(&terminal->system_flags, &console->input, &console->output)) { + } else { + ok = false; + } + return ok; + } + // # __Terminal_initBlankLinesToOutput__ + void __Terminal_initBlankLinesToOutput__(struct __Terminal__ *terminal) { + struct __Console__ *console = terminal->console; + __OsConsoleOutput_writeCText__(&console->output, "\r\n"); + __Terminal_cursorMove__(terminal, 0, 0); + size_t pos_y = 0; + while (pos_y < terminal->output.size.y - 2) { + __OsConsoleOutput_writeCText__(&console->output, "\r\n"); + pos_y += 1; + terminal->output.cursor_pos.y += 1; + } + } + // # __Terminal_initOutput__ + void __Terminal_initOutput__(struct __Terminal__ *terminal) { + struct __TerminalOutput__ *output = &terminal->output; + + __TerminalOutputCursorPos_init__(&output->cursor_pos); + output->font_style = ""; + output->__TerminalOutput_fontStyleLen__ = 0; + output->size.x = 1; + output->size.y = 1; + output->convert_n_to_rn = false; + output->apply_r = false; + output->apply_n = false; + + __Terminal_updateOutputSize__(terminal); + __Terminal_resetColors__(terminal); + __Terminal_initBlankLinesToOutput__(terminal); + __Terminal_clearOutput__(terminal); + __Terminal_cursorMove__(terminal, 0, 0); + } + // # __Terminal_init__ + bool __Terminal_init__( + struct __Terminal__ *t, + struct __Console__ *console + ) { + bool ok = true; + t->console = console; + __TerminalInput_init__(&t->input); + __Terminal_initOutput__(t); + + // configure console + // save flags before change + if (__OsConsoleFlags_init__(&t->system_flags, &console->input, &console->output)) { + // go to interactive mode ("non canonical mode" or "raw mode") + struct __OsConsoleFlags__ flags; + if (__OsConsoleFlags_init__(&flags, &console->input, &console->output)) { + __OsConsoleFlags_setNonCanonicalMode__(&flags); + if (__OsConsoleFlags_apply__(&flags, &console->input, &console->output)) { + __OsConsoleOutput_writeCText__(&console->output, __ConsoleAnsiOutputSettings_disableLineWrap__); + } else { + ok = false; + } + } else { + ok = false; + } + } else { + ok = false; + } + return ok; + } + // # __Terminal_moveCursorToNextLine__ + void __Terminal_moveCursorToNextLine__(struct __Terminal__ *terminal) { + if (terminal->output.cursor_pos.y < terminal->output.size.y) { + __TerminalOutputCursorPos_move__(terminal, terminal->output.cursor_pos.x, terminal->output.cursor_pos.y + 1); + } else { + __OsConsoleOutput_write__(&terminal->console->output, "\n", 0); + } + } + // # __Terminal_moveCursorToStartOfLine__ + void __Terminal_moveCursorToStartOfLine__(struct __Terminal__ *terminal) { + __OsConsoleOutput_write__(&terminal->console->output, "\r", 0); + terminal->output.cursor_pos.x = 0; + } + // # __Terminal_moveCursorToStartOfNextLine__ + void __Terminal_moveCursorToStartOfNextLine__(struct __Terminal__ *terminal) { // \r\n + __Terminal_moveCursorToNextLine__(terminal); + __Terminal_moveCursorToStartOfLine__(terminal); + } + // # __Terminal_resetColors__ + void __Terminal_resetColors__(struct __Terminal__ *terminal) { + __Terminal_setFontStyleCText__(terminal, __ConsoleAnsiOutputFontStyle_command_reset__); + } + // # __Terminal_setFontStyle__ + void __Terminal_setFontStyle__( + struct __Terminal__ *terminal, + const char* font_style, + size_t font_style_len + ) { + terminal->output.font_style = font_style; + terminal->output.__TerminalOutput_fontStyleLen__ = font_style_len; + __OsConsoleOutput_write__(&terminal->console->output, font_style, font_style_len); + } + // # __Terminal_updateInputBuffer__ + void __Terminal_updateInputBuffer__( + struct __Terminal__ *terminal + ) { + struct __Console__ *console = terminal->console; + size_t unreaded = 0; + if (__OsConsoleInput_getCountOfUnreaded__(&console->input, &unreaded)) { + while (terminal->input.ungrabed < __TerminalInput_size__ and unreaded > 0) { // get new byte + char byte; + if (__OsConsoleInput_readByte__(&byte, &console->input)) { + terminal->input.buffer[terminal->input.ungrabed] = byte; + terminal->input.ungrabed += 1; + } + unreaded -= 1; + } + } else { + // ok = false; + } + } + // # __Terminal_updateOutputSize__ + void __Terminal_updateOutputSize__(struct __Terminal__ *terminal) { + struct __Math2dPosU__ size; + __OsConsoleOutput_getSize__(&terminal->console->output, &size); + + // x + if (size.x >= 6) { + terminal->output.size.x = size.x - 3; + } else { + terminal->output.size.x = size.x; + } + + // y + if (size.y >= 6) { + terminal->output.size.y = size.y - 3; + } else { + terminal->output.size.y = size.y; + } + } + // # __Terminal_writeColoredErrorSymbolToOutput__ + void __Terminal_writeColoredErrorSymbolToOutput__( + struct __Terminal__ *t + ) { + struct __Console__ *console = t->console; + + #define __TerminalErrorSymbol_color__ \ + __ConsoleAnsiOutputFontStyle_start__ \ + __ConsoleAnsiOutputFontStyle_bg_color_yellow__ \ + __ConsoleAnsiOutputFontStyle_sep__ \ + __ConsoleAnsiOutputFontStyle_color_red__ \ + __ConsoleAnsiOutputFontStyle_end__ + + __OsConsoleOutput_writeCText__(&console->output, __TerminalErrorSymbol_color__); + __OsConsoleOutput_writeCText__(&console->output, "#"); + __OsConsoleOutput_write__(&console->output, t->output.font_style, t->output.__TerminalOutput_fontStyleLen__); + + t->output.cursor_pos.x += 1; + } + // # __Terminal_writeToOutput__ + void __Terminal_writeToOutput__( + struct __Terminal__ *terminal, + const char *bytes, + size_t bytes_len + ) { + for (size_t readed = 0; readed < bytes_len; readed += 1) { + char byte = bytes[readed]; + + if (byte >= ' ' and byte <= '~') { + struct __Console__ * console = terminal->console; + __OsConsoleOutput_write__(&console->output, &bytes[readed], 1); + terminal->output.cursor_pos.x += 1; + + } else if (byte == '\r') { + if (terminal->output.apply_r) { + __Terminal_moveCursorToStartOfLine__(terminal); + } else { + __Terminal_writeColoredErrorSymbolToOutput__(terminal); + } + + } else if (byte == '\t') { + __Terminal_writeColoredErrorSymbolToOutput__(terminal); + + } else if (byte == '\n') { + if (terminal->output.apply_n) { + if (terminal->output.convert_n_to_rn) __Terminal_moveCursorToStartOfLine__(terminal); + __Terminal_moveCursorToNextLine__(terminal); + } else { + __Terminal_writeColoredErrorSymbolToOutput__(terminal); + } + + } else { + __Terminal_writeColoredErrorSymbolToOutput__(terminal); + + } + } + } + // # __TextAsciiSymbol_isBreakWord__ + bool __TextAsciiSymbol_isBreakWord__(char symbol) { + return __TextAsciiSymbol_isWord__(symbol) == false; + } + // # __TextAsciiSymbol_isWordSymbol__ + bool __TextAsciiSymbol_isWordSymbol__(char symbol) { + return false + or (symbol >= '0' and symbol <= '9') + or (symbol >= 'a' and symbol <= 'z') + or (symbol >= 'A' and symbol <= 'Z') + ; + } + // # __TextAsciiSymbol_isWord__ + bool __TextAsciiSymbol_isWord__(char symbol) { + return false + or (symbol == '_') + or __TextAsciiSymbol_isWordSymbol__(symbol) + ; + } + // # __TextAscii_compare__ + char // return -1, 0 or 1 where -1 mean less, 0 mean eql and 1 is more. + __TextAscii_compare__( + const char* text1, + const char* text2, + size_t text_len + ) { + for (size_t pos = 0; pos < text_len; pos++) { + uint8_t t1 = *(uint8_t*) &text1[pos]; + uint8_t t2 = *(uint8_t*) &text2[pos]; + if (t1 != t2) { + if (t1 < t2) return -1; + return 1; + } + } + + return 0; + } + // # __TextAscii_countIndentReverse__ + size_t __TextAscii_countIndentReverse__( + const char *text, + size_t text_len, + size_t tabsize + ) { + size_t count = 0; + if (text_len > 0) { + size_t pos = text_len - 1; + while(true) { + char r = text[pos]; + if (r == 0 ) { + count += 1; + + } else if (r == ' ') { + count += 1; + + } else if (r == '\t') { + count += tabsize; + + } else if (r == '\r') { + count += 1; + + } else break; + + if (pos == 0) break; + pos -= 1; + } + } + return count; + } + // # __TextAscii_countIndent__ + size_t __TextAscii_countIndent__( + const char *text, + size_t text_len, + size_t tabsize + ) { + size_t count = 0; + for (size_t pos = 0; pos < text_len; pos++) { + char r = text[pos]; + if ( r == 0) { count += 1; + } else if ( r == ' ') { count += 1; + } else if ( r == '\t') { count += tabsize; + } else if ( r == '\r') { count += 1; + } else break; + } + return count; + } + // # __TextAscii_countNonIndent__ + size_t __TextAscii_countNonIndent__( + const char *text, + size_t text_len + ) { + size_t indent = __TextAscii_countIndent__(text, text_len, 1); + return text_len - indent; + } + // # __TextAscii_cutIndents__ + bool __TextAscii_cutIndents__( + size_t *ret_pos, // incremented by fn + size_t *ret_len, // incremented by fn + const char *bytes, + size_t bytes_len + ) { + bool ok = true; + if (bytes_len > 0) { // cut from left + size_t start = 0; + while (true) { + if (start < bytes_len) { + if (bytes[start] != ' ') { + break; + } + start += 1; + } else { // TextIsEmpty + ok = false; + break; + } + } + + if (ok) { // cut from right + size_t end = bytes_len - 1; + while (true) { + if (bytes[end] != ' ') { + break; + } + end -= 1; + } + + *ret_pos += start; + *ret_len += end+1 - start; + } + } else { + ok = false; + } + return ok; + } + // # __TextAscii_findBreakOfWordReverse__ + size_t __TextAscii_findBreakOfWordReverse__( + const char *text, + size_t text_len // expected text_len > 0 + ) { + if (text_len == 1) return 0; + for (size_t pos = text_len - 1; pos > 0; pos--) { + char symbol = text[pos]; + if (__TextAsciiSymbol_isBreakWord__(symbol)) return pos; + } + return 0; + } + // # __TextAscii_findBreakOfWord__ + size_t __TextAscii_findBreakOfWord__( + const char* text, + size_t text_len + ) { + if (text_len == 1) return 1; + for (size_t pos = 1; pos < text_len; pos++) { + char symbol = text[pos]; + if (__TextAsciiSymbol_isBreakWord__(symbol)) return pos; + } + return text_len; + } + // # __TextAscii_getNonIndent__ + bool + __TextAscii_getNonIndent__( + const char **ret_ptr, + size_t *ret_size, + const char *text, + size_t text_len + ) { + size_t indent = __TextAscii_countIndent__(text, text_len, 1); + if (indent == text_len) return false; + *ret_ptr = &text[indent]; + *ret_size = text_len - indent; + return true; + } + // # __TextAscii_getStartOfText__ + bool __TextAscii_getStartOfText__( + size_t *ret_pos, // increment by fn + const char *text, + size_t text_len + ) { + bool ok = true; + bool finded = false; + size_t pos = 0; + for (; pos < text_len; pos++) { + char symbol = text[pos]; + if (true + and symbol != ' ' + and symbol != '\t' + ) { + finded = true; + break; + } + } + *ret_pos += pos; + ok = ok and finded; + return ok; + } + // # __TextAscii_isLetter__ + bool __TextAscii_isLetter__(char rune) { + return false + or rune < ' ' + or __TextAsciiSymbol_isWord__(rune) + or rune >= 127 + ; + } + // # __TextAscii_isVisible__ + bool __TextAscii_isVisible__(char byte) { + return (byte >= 33) and (byte <= 126); + } + // # __TextFormatU64_do__ + void __TextFormatU64_do__( + struct __TextFormatU64__ *t, + uint64_t number, + size_t min_width + ) { + size_t len = 0; + uintptr_t buffer_start = (uintptr_t) &t->buffer[0]; + uintptr_t buffer_end = buffer_start + __TextCharsDecFromU64_lenMax__; + + // write utoa + uintptr_t addr = buffer_end; + for (uint64_t num = number; num > 0; num = num / 10) { + uint8_t remainder = num % 10; + addr = addr - 1; + *(char*) addr = '0' + (char) remainder; + } + len = buffer_end - addr; + + // fill zeroes to min_width + if (min_width > len) { + size_t fill_len = min_width - len; + addr = addr - fill_len; + __Mem_fillAny__(addr, '0', fill_len); + len = len + fill_len; + } + + t->ptr = (char*) addr; + t->len = len; + } + // # __TextSplitter_init__ + void __TextSplitter_init__(struct __Text_Splitter__* t, char* text, size_t text_len, char* delim, size_t delim_len) { + t->stop = false; + t->last_pos = 0; + __Finder_init__(&t->finder, text, text_len, delim, delim_len); + } + // # __TextSplitter_next__ + bool __TextSplitter_next__(struct __Text_Splitter__* t, struct Slice* out_slice) { + if (t->stop == false) { + size_t finded; + if (__Finder_next__(&t->finder, &finded)) { + out_slice->ptr = &t->finder.text.ptr[t->last_pos]; // slice = t->finder.text[t->last_pos..finded]; + out_slice->len = finded - t->last_pos; + t->last_pos = t->finder.pos; + return true; + } else { + t->stop = true; + out_slice->ptr = &t->finder.text.ptr[t->last_pos]; // slice = t->finder.text[t->last_pos..]; + out_slice->len = t->finder.text.len - t->last_pos; + t->last_pos = t->finder.pos; + return true; + } + } + return false; + } + // # __Text_countIndent__ + size_t + __Text_countIndent__( + char* text, + size_t text_len, // can be 0 + size_t tab_size + ) { + size_t counted = 0; + size_t pos = 0; + while (pos < text_len) { + char symbol = text[pos]; + if (symbol == ' ') { + counted = counted + 1; + } else if (symbol == '\t') { + counted = counted + tab_size; + } else { + break; + } + pos = pos + 1; + } + return counted; + } + // # __Text_formatU64ToBuffer__ + size_t __Text_formatU64ToBuffer__( + char *buffer, // expected len >= __TextCharsDecFromU64_lenMax__ + uint64_t number, + size_t min_width + ) { + struct __TextFormatU64__ format; + __TextFormatU64_do__(&format, number, min_width); + if (format.len > 0) { + __Mem_copy__(buffer, format.ptr, format.len); + } + return format.len; + } + // # __Text_formatU64__ + size_t __Text_formatU64__(__WriteFnPtrVoid__ fn_write, void* context, uint64_t number, size_t min_width) { + struct __TextFormatU64__ format; + __TextFormatU64_do__(&format, number, min_width); + fn_write(context, format.ptr, format.len); + return format.len; + } + // # __Trace_init__ + void __Trace_init__( + struct __Trace__ *trace, + struct __Trace__ *prev_trace, // can be null + size_t line + ) { + trace->__Trace_prevTrace__ = prev_trace; + trace->__Trace_line__ = line; + } + // # __Trace_print__ + void __Trace_print__( + struct __Trace__ *trace + ) { + if (trace) { + printf("%zu", trace->__Trace_line__); + trace = trace->__Trace_prevTrace__; + + while (trace) { + printf("|%zu", trace->__Trace_line__); + trace = trace->__Trace_prevTrace__; + } + } else { + printf("nil"); + } + } + // # __ZText_countLen__ + size_t __ZText_countLen__(const char text[]) { + size_t len = 0; + while(text[len] != 0) len++; + return len; + } + // # __ZText_fromBytes__ + void __ZText_fromBytes__(char* buffer, const char bytes[], size_t bytes_len) { + // expected buffer_len >= bytes_len + 1 + + __Mem_copy__(buffer, bytes, bytes_len); + buffer[bytes_len] = 0; + } + // # __ZText_writeToBuffer__ + size_t __ZText_writeToBuffer__(char buffer[], const char data[]) { + const size_t len = __ZText_countLen__(data); + __Mem_copy__(buffer, data, len); + return len; + } + // # __ZText_writeToWriteFn__ + size_t __ZText_writeToWriteFn__(__WriteFnPtr__ fn_write, void* context, const char text[]) { + const size_t len = __ZText_countLen__(text); + fn_write(context, text, len); + return len; + } + // # __mem_findFastReverse__ + bool __mem_findFastReverse__( + size_t *ret_pos, // func increment this + const char *data, + size_t data_len, // expected >= 1 + const char *desired, + size_t desired_len // expected <= data_len + ) { + bool finded = false; + size_t final_check_pos = data_len - desired_len; + if (desired_len <= 4) { + for (size_t pos = 0; pos <= final_check_pos + 1; pos++) { + size_t rpos = final_check_pos - pos; + if (__Mem_isEql__(&data[rpos], desired, desired_len)) { + *ret_pos += rpos; + finded = true; + break; + } + } + } else { + const char* final_check_ptr = &data[final_check_pos]; + if (__Mem_isEql__(final_check_ptr, desired, desired_len)) { + finded = true; + *ret_pos += final_check_pos; + } else { + uint8_t target_sum = __Crypto_sumBytes__(desired, desired_len); + uint8_t target_xor = __Crypto_xorBytes__(desired, desired_len); + + uint8_t hash_sum = __Crypto_sumBytes__(final_check_ptr, desired_len); + uint8_t hash_xor = __Crypto_xorBytes__(final_check_ptr, desired_len); + + for (size_t pos = 1; pos <= final_check_pos + 1; pos++) { + size_t rpos = final_check_pos - pos; + + uint8_t last_final_byte = data[rpos + desired_len]; + hash_xor ^= last_final_byte; + hash_sum -= last_final_byte; + + uint8_t new_byte = data[rpos]; + hash_xor ^= new_byte; + hash_sum += new_byte; + + if ( + (hash_xor == target_xor) + and (hash_sum == target_sum) + and (__Mem_isEql__(&data[rpos], desired, desired_len)) + ) { + *ret_pos += rpos; + finded = true; + break; + } + } + } + } + return finded; + } + // # __u64FromTextDec__ atoi atou + uint64_t + __u64FromTextDec__( + const char *bytes, // expected bytes only with numbers from '0' to '9' + size_t len // expected > 0; expected <= __u64FromTextDec_maxLen__ + ) { + uint64_t result = 0; + size_t numerical_place = 1; + size_t pos = len - 1; // last symbol + while (true) { + char byte = bytes[pos]; + uint64_t value = (uint64_t) ((uint8_t)byte - (uint8_t)'0'); + result += value * numerical_place; + + if (pos == 0) break; + numerical_place *= 10; + pos -= 1; + } + return result; + } + // # bits_rotl16 + uint16_t bits_rotl16(uint16_t value, unsigned int shift) { + shift %= 16; + return (value << shift) | (value >> (16 - shift)); + } + // # bits_rotl32 + uint32_t bits_rotl32(uint32_t value, unsigned int shift) { + shift %= 32; + return (value << shift) | (value >> (32 - shift)); + } + // # bits_rotl64 + uint64_t bits_rotl64(uint64_t value, unsigned int shift) { + shift %= 64; + return (value << shift) | (value >> (64 - shift)); + } + // # bits_rotl8 + uint8_t bits_rotl8(uint8_t value, unsigned int shift) { + shift %= 8; + return (value << shift) | (value >> (8 - shift)); + } + // # call_other_trace_example + void call_other_trace_example( + struct __Trace__* prev_trace // can be null + ) { + struct __Trace__ trace; __Trace_init__(&trace, prev_trace, __LINE__); + trace.__Trace_line__ = __LINE__; print_trace_example(0, &trace); + } + // # cpu_checkNumberFormat + bool cpu_checkNumberFormat() { + char current_endians = 0; + int n = 1; + if (* (char *) &n == 1) { + current_endians = __TargetMemoryType_endiansLittle__; + } else { + current_endians = __TargetMemoryType_endiansBig__; + } + + if (__target_memoryType__ == current_endians) { + return true; + } else { + printf("%d wrong MEMORY_TYPE !\r\n", __LINE__); + } + return false; + } + // # isStartWith + bool isStartWith(struct Slice* a, struct Slice* b) { + return (a->len >= b->len) && __Mem_isEql__(a->ptr, b->ptr, b->len); + } + // # main + #ifndef __COMPILED_FROM_ZIG_FILE__ + int main(int args_len, char** args_ptr) { + if (real_main(args_len, args_ptr)) return 0; + return 1; + } + #endif + // # printHex + void printHex(char* buffer_ptr, uintptr_t buffer_len) { + for (int i = 0; i < buffer_len; i++) { + printf(" %02X ", buffer_ptr[i]); + } + } + // # print_trace_example + void print_trace_example( + int anyarg, + struct __Trace__* prev_trace + ) { + struct __Trace__ trace; __Trace_init__(&trace, prev_trace, __LINE__); + trace.__Trace_line__ = __LINE__; __Trace_print__(&trace); + } + // # readBig16 + uint16_t readBig16(char* src) { + uint16_t ret; + __Mem_nativeToBig__( (char*) &ret, src, 2); + return ret; + } + // # readBig32 + uint32_t readBig32(char* src) { + uint32_t ret; + __Mem_nativeToBig__( (char*) &ret, src, 4); + return ret; + } + // # readBig64 + uint64_t readBig64(char* src) { + uint64_t ret; + __Mem_nativeToBig__( (char*) &ret, src, 8); + return ret; + } + // # readLittle16 + uint16_t readLittle16(char* src) { + uint16_t ret; + __Mem_nativeToLittle__( (char*) &ret, src, 2); + return ret; + } + // # readLittle32 + uint32_t readLittle32(char* src) { + uint32_t ret; + __Mem_nativeToLittle__( (char*) &ret, src, 4); + return ret; + } + // # readLittle64 + uint64_t readLittle64(char* src) { + uint64_t ret; + __Mem_nativeToLittle__( (char*) &ret, src, 8); + return ret; + } + // # real_main + bool real_main(int args_len, char** args_ptr) { + struct __Trace__ trace; __Trace_init__(&trace, NULL, __LINE__); + + bool ok = true; + trace.__Trace_line__ = __LINE__; + if (tests()) { + trace.__Trace_line__ = __LINE__; + printf("%d success tests \r\n", __LINE__); + if (false and __App_init__(&__app__)) { + trace.__Trace_line__ = __LINE__; __Trace_print__(&trace); + while(true) { + if (!__App_process__(&__app__)) break; + __App_waitToNextFrame__(&__app__); + } + __App_deinit__(&__app__); + } else { + ok = false; + printf("%d fail: __App_init__\r\n", __LINE__); + } + } else { + ok = false; + printf("%d fail tests \r\n", __LINE__); + } + return ok; + } + // # test_rot + bool test_rot() { + char a = 0b11111100 >> 2; + if (a == 0b00111111) { + return true; + } else { + printf("%d: failed test_rot.", __LINE__); + } + return false; + } + // # tests + bool tests() { + // const char* test_file_name = "scalpi_testing_file.txt"; + // size_t test_file_name_len = __ZText_countLen__(test_file_name); + if ( true + and cpu_checkNumberFormat() + and __Mem_isEql_test__() + // and __FileComplete_write__(test_file_name, test_file_name_len, "abcd", 4) + // and __FileComplete_write__(test_file_name, test_file_name_len, "efgh", 4) + // and __FileComplete_write__(test_file_name, test_file_name_len, "ijkm", 4) + // and etc... + ) { + return true; + } else { + printf("%d fail tests \r\n", __LINE__); + return false; + } + + return true; + } + // # writeBig16 + void writeBig16( + char *dest, + uint16_t value + ) { + __Mem_nativeToBig__( dest, (char*)&value, 2); + } + // # writeBig32 + void writeBig32( + char *dest, + uint32_t value + ) { + __Mem_nativeToBig__(dest, (char*)&value, 4); + } + // # writeBig64 + void writeBig64( + char *dest, + uint64_t value + ) { + __Mem_nativeToBig__(dest, (char*)&value, 8); + } + // # writeLittle16 + void writeLittle16( + char *dest, + uint16_t value + ) { + __Mem_nativeToLittle__(dest, (char*)&value, 2); + } + // # writeLittle32 + void writeLittle32( + char *dest, + uint32_t value + ) { + __Mem_nativeToLittle__(dest, (char*)&value, 4); + } + // # writeLittle64 + void writeLittle64( + char *dest, + uint64_t value + ) { + __Mem_nativeToLittle__(dest, (char*)&value, 8); + } + // # writeWithOffset + void writeWithOffset( + char *dest, + size_t *writed, + char *data, + size_t data_len // increment by fn + ) { + __Mem_copy__(&dest[*writed], data, data_len); + *writed += data_len; + } +// TODO port this zig code to C + /* + const Utf8 = struct { + const BytesIterator = struct { + const Parsed = struct { + num: u64 = 0, + bytes: []const u8 = &.{}, + + fn is_connector(t: *Parsed) bool { + if (t.num == 0x200D) return true; + return false; + } + }; + + const Iterator = struct { + bytes: []const u8, + pos: usize = 0, + + fn next(t: *Iterator) ?Parsed { + // Masks: + //| 1 byte | 2 byte | 3 byte | 4 byte + // + // 0xxxxxxx + // 110xxxxx 10xxxxxx + // 1110xxxx 10xxxxxx 10xxxxxx + // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + + // example "?" + // 208 -- 110 10000 + // 159 -- 10 011111 + // is + // 1055 -- 000 10000011111 + + parse: { + var parsed: Parsed = .{}; + + // 1 byte + if (t.bytes.len <= t.pos) break :parse; + const b1 = t.bytes[t.pos]; + const c1: u64 = @intCast(b1); + if (checkMask(b1, 0, 0b10000000)) { // 0xxxxxxx + parsed.num = b1 & 0b01111111; + parsed.bytes = t.bytes[t.pos .. t.pos + 1]; + t.pos += 1; + return parsed; + } + + // 2 byte + if (t.bytes.len <= t.pos + 1) break :parse; + const b2 = t.bytes[t.pos + 1]; + const c2: u64 = @intCast(b2); + if (checkMask(b1, 0b11000000, 0b11100000)) { // 110xxxxx + parsed.num = ((c1 & 31) << 6) + (c2 & 63); + parsed.bytes = t.bytes[t.pos .. t.pos + 2]; + t.pos += 2; + return parsed; + } + + // 3 byte + if (t.bytes.len <= t.pos + 2) break :parse; + const b3 = t.bytes[t.pos + 2]; + const c3: u64 = @intCast(b3); + if (checkMask(b1, 0b11100000, 0b11110000)) { // 1110xxxx + parsed.num = ((c1 & 15) << 12) + ((c2 & 63) << 6) + (c3 & 63); + parsed.bytes = t.bytes[t.pos .. t.pos + 3]; + t.pos += 3; + return parsed; + } + + // 4 byte + if (t.bytes.len <= t.pos + 3) break :parse; + const b4 = t.bytes[t.pos + 3]; + const c4: u64 = @intCast(b4); + if (checkMask(b1, 0b11110000, 0b11111000)) { // 11110xxx + parsed.num = ((c1 & 7) << 21) + ((c2 & 63) << 12) + ((c3 & 63) << 6) + (c4 & 63); + parsed.bytes = t.bytes[t.pos .. t.pos + 4]; + t.pos += 4; + return parsed; + } + } + t.pos += 1; + return null; + } + }; + + fn checkMask(num: u8, mask: u8, used_bits: u8) bool { + if (num & used_bits == mask) { + return true; + } else { + return false; + } + } + + fn fromDo(bytes: []const u8) Iterator { + return Iterator{ .bytes = bytes }; + } + }; + }; + */ ADDED main.zig Index: main.zig ================================================================== --- /dev/null +++ main.zig @@ -0,0 +1,5704 @@ +// about + // ScalpiEditor - ansi-only text editor for terminals. + // killer features: no. its just editor. + // licenze: + // This code and its derivatives can be used under the following conditions: + // - Do not attack other countries. + // - Jerk off on public at least 1 time per day. + // - maintain hygiene. + // - check my other projects https://chiselapp.com/user/sergey6661313 + // Compile: + // latest release tested with zig ver 0.15.1 downloaded from https://ziglang.org/download/ + // for generate executable file use: + // linux: zig build-exe -lc -O ReleaseSmall -target x86_64-linux-gnu -mcpu baseline ./main.zig -I "." + // x86_64-linux-musl not work, becouse zig ^_^ + // windows: zig build-exe -lc -O ReleaseSmall -target x86_64-windows -mcpu baseline ./main.zig -I "." + // known bugs in windows: + // f5 - f12 not work in windows in some terminals. (i use Alacritty) + // some time brackets not are not written + // its not editor bug. + // this happened if you try press ctrl+r in prompt shell with non english keyboard. + // this action just crack your terminal session. + // just restart your terminal session and it will be ok. + // to support me + // with boosty: + // https://boosty.to/cutloosedev + + // with monero: + // 87T7 qGbA TrM3 a6Br + // DyeC jQQf NWtU u3iZ + // bHVB MC6W mEbN NE13 + // Qrrt KhBb e4vF 58NR + // 8PTF dYk2 Sozc HexX + // 4Q69 jbdQ Asrs P7B + // tested in terminals: + // linux + // Alacritty + // WezTerm + // sakura + + // windows + // Alacritty-v0.13.2-portable + // tabby-1.0.207-portable-x64 + // WezTerm-windows-20240520-135708-b8f94c47. + // contour-0.4.3.6442-win64 + // hyper_4.0.0-canary.5 + // windows_terminal - need some unbind keys to work. + + // not tested in terminals: + // extratermqt-0.77.0-windows-x64 - not run in my system. +// todo + // find way to remove __AppEditorHistoryNote_alloc__ (zig not compiled without it) + // all func uses this is dependence on AppEditor. first move AppEditor to C + // remove from fn c.__OsConsoleOutput_write__ null len variant + // add ability to read part of file for work with extra big files. +// import + const std = @import("std"); + const builtin = @import("builtin"); + + const c = @cImport({ + @cDefine("__COMPILED_FROM_ZIG_FILE__", "1"); + @cDefine("_NO_CRT_STDIO_INLINE", "1"); // https://github.com/ziglang/zig/issues/515 + switch(builtin.os.tag) { + .windows => @cDefine("_WIN32", "1"), + .linux => @cDefine("__linux__", "1"), + else => {}, + } + @cInclude("main.c"); + }); +// functions + // # __AppEditorViewsEasyMotionHorizontal_onKey__ + fn __AppEditorViewsEasyMotionHorizontal_onKey__(ctx: ?*anyopaque, cik: c.__ConsoleAnsiInputKey__) callconv(.c) void { __zig_fuck__(ctx); + + if ( cik == c.__ConsoleAnsiInputKey_escape__ ) { + c.__AppEditorViewsEasyMotionHorizontalContext_vtable__.*.setAsView.?(c.__AppEditorViewsEasyMotionHorizontal_context__); + + } else if ( cik == c.__ConsoleAnsiInputKey_ctrl_q__ ) { + c.__AppEditor_stop__(&c.__app__.editor); + + } else { + const byte: u8 = @truncate(cik); + + if ( byte >= '0' and byte <= '9' ) { + const pos: usize = byte - '0' + ('z' - 'a') + 1; + c.__AppEditorViewsEasyMotionHorizontal_moveTo__(pos * c.__AppEditorViewsEasyMotionHorizontal_step__); + + } else if (byte >= 'a' and byte <= 'z' ) { + const pos: usize = byte - 'a'; + c.__AppEditorViewsEasyMotionHorizontal_moveTo__(pos * c.__AppEditorViewsEasyMotionHorizontal_step__); + + } + + } + } + // # __AppEditorViewsEasyMotionHorizontal_setAsView__ + fn __AppEditorViewsEasyMotionHorizontal_setAsView__(last_context: *anyopaque, last_vtable: *const c.__AppEditorViewsVTable__) callconv(.c) void { + c.__AppEditorViewsEasyMotionHorizontal_context__ = last_context; + c.__AppEditorViewsEasyMotionHorizontalContext_vtable__ = last_vtable; + c.__app__.editor.do_ptr = null; + c.__app__.editor.onKey_ptr = &__AppEditorViewsEasyMotionHorizontal_onKey__; + c.__app__.editor.current_ctx = null; + c.__AppEditorViewsEasyMotionHorizontal_draw__(); + } + // # __AppEditorViewsEasyMotionVertical_draw__ + fn __AppEditorViewsEasyMotionVertical_draw__() !void { + const terminal = &c.__app__.terminal; + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_easy_motion__, c.__AppEditorTheme_easy_motion__.len); + + const vox = c.__AppEditorViewsEasyMotionVertical_context_vtable__.*.getOffsetX.?(c.__AppEditorViewsEasyMotionVertical_context__); + var pos: usize = 0; + var rune: u8 = 'a'; + while (true) { + if (pos >= terminal.output.size.y - 1 - c.__AppEditorViewsEasyMotionVertical_step__) break; + + c.__Terminal_cursorMove__(terminal, vox, pos); + c.__Terminal_writeToOutput__(terminal, &rune, 1); + + if (rune == '9') { + break; + } else if (rune == 'z') { + rune = '0'; + } else { + rune += 1; + } + + pos += c.__AppEditorViewsEasyMotionVertical_step__; + } + } + // # __AppEditorViewsEasyMotionVertical_moveTo__ + fn __AppEditorViewsEasyMotionVertical_moveTo__(pos: u8) !void { + const voy = c.__AppEditorViewsEasyMotionVertical_context_vtable__.*.getOffsetY.?(c.__AppEditorViewsEasyMotionVertical_context__); + + if (voy > pos) { + const gtpl = c.__AppEditorViewsEasyMotionVertical_context_vtable__.*.goToPrevLine.?; + var i = voy - pos; + while (i > 0) : (i -= 1) { + gtpl(c.__AppEditorViewsEasyMotionVertical_context__); + } + + } else if (voy < pos) { + const gtnl = c.__AppEditorViewsEasyMotionVertical_context_vtable__.*.goToNextLine.?; + var i = pos - voy; + while (i > 0) : (i -= 1) { + gtnl(c.__AppEditorViewsEasyMotionVertical_context__); + } + } + + else { // (voy == pos) + } + + c.__AppEditorViewsEasyMotionVertical_context_vtable__.*.setAsView.?(c.__AppEditorViewsEasyMotionVertical_context__); + } + // # __AppEditorViewsEasyMotionVertical_onKey__ + fn __AppEditorViewsEasyMotionVertical_onKey__(ctx: ?*anyopaque, cik: c.__ConsoleAnsiInputKey__) callconv(.c) void { __zig_fuck__(ctx); + if (cik == c.__ConsoleAnsiInputKey_escape__) { + c.__AppEditorViewsEasyMotionVertical_context_vtable__.*.setAsView.?(c.__AppEditorViewsEasyMotionVertical_context__); + } else if (cik == c.__ConsoleAnsiInputKey_ctrl_q__) { + c.__AppEditor_stop__(&c.__app__.editor); + } else { + const byte: u8 = @truncate(cik); + + if (byte >= '0' and byte <= '9') { + const pos: u8 = byte - '0' + ('z' - 'a') + 1; + __AppEditorViewsEasyMotionVertical_moveTo__(pos * @as(u8, @intCast(c.__AppEditorViewsEasyMotionVertical_step__))) catch {}; + + } else if (byte >= 'a' and byte <= 'z') { + const pos: u8 = byte - 'a'; + __AppEditorViewsEasyMotionVertical_moveTo__(pos * @as(u8, @intCast(c.__AppEditorViewsEasyMotionVertical_step__))) catch {}; + + } + } + } + // # __AppEditorViewsEasyMotionVertical_setAsView__ + fn __AppEditorViewsEasyMotionVertical_setAsView__(last_context: *anyopaque, last_vtable: *const c.__AppEditorViewsVTable__) callconv(.c) void { + c.__AppEditorViewsEasyMotionVertical_context__ = last_context; + c.__AppEditorViewsEasyMotionVertical_context_vtable__ = last_vtable; + c.__app__.editor.do_ptr = null; + c.__app__.editor.onKey_ptr = &__AppEditorViewsEasyMotionVertical_onKey__; + c.__app__.editor.current_ctx = null; + __AppEditorViewsEasyMotionVertical_draw__() catch unreachable; + } + // # __AppEditorViewsFind_CtrlShiftLeft__ + fn __AppEditorViewsFind_CtrlShiftLeft__(t: *c.__AppEditorViewsFind__) callconv(.c) void { + const line: *c.__AppEditorLine__ = t.line; + if (line.text_len > 0) { + const indent = c.__TextAscii_countIndent__(line.text, line.text_len, 1); + if (t.symbol > indent) { + t.goToSymbol(indent); + } else { + t.goToStartOfLine(); + } + } else { + t.goToStartOfLine(); + } + t.need_redraw = true; + } + // # __AppEditorViewsFind_CtrlShiftRight__ + fn __AppEditorViewsFind_CtrlShiftRight__(t: *c.__AppEditorViewsFind__) callconv(.c) void { + const line: *c.__AppEditorLine__ = t.line; + if (line.text_len > 0) { + const indent = c.__TextAscii_countIndent__(line.text, line.text_len, 1); + if (t.symbol < indent) t.goToSymbol(indent) else t.goToEndOfLine(); + t.need_redraw = true; + } + } + // # __AppEditorViewsFind_cancel__ + fn __AppEditorViewsFind_cancel__(t: *c.__AppEditorViewsFind__) !void { + t.context_vtable.*.setAsView.?(t.context); + } + // # __AppEditorViewsFind_clearLine__ + fn __AppEditorViewsFind_clearLine__(t: *c.__AppEditorViewsFind__) callconv(.c) void { + t.line.text_len = 0; + __AppEditorViewsFind_goToStartOfText__(t); + t.need_redraw = true; + } + // # __AppEditorViewsFind_correctOffset__ + fn __AppEditorViewsFind_correctOffset__(t: *c.__AppEditorViewsFind__) callconv(.c) void { + const predel = (c.__app__.terminal.output.size.y >> 1) - (c.__app__.terminal.output.size.y >> 4); + if (t.symbol >= predel) t.offset.x = predel; + } + // # __AppEditorViewsFind_ctrlLeft__ + fn __AppEditorViewsFind_ctrlLeft__(t: *c.__AppEditorViewsFind__) callconv(.c) void { + __AppEditorViewsFind_goToPrevSymbol__(t); + if (t.symbol == 0) return; + if (t.line.text_len > 0) { + const line: *c.__AppEditorLine__ = &t.line; + const full_text = line.text[0..line.text_len]; + const text = full_text[0 .. t.symbol]; + const spaces = c.__TextAscii_countIndentReverse__(text.ptr, text.len, 1); + if (spaces > 0) { + __AppEditorViewsFind_goToSymbol__(t, t.symbol - spaces); + t.need_redraw = true; + return; + } + const dest_pos = c.__TextAscii_findBreakOfWordReverse__(text.ptr, text.len) + 1; + __AppEditorViewsFind_goToSymbol__(t, dest_pos); + } else { + __AppEditorViewsFind_goToSymbol__(t, 0); + } + t.need_redraw = true; + } + // # __AppEditorViewsFind_ctrlRight__ + fn __AppEditorViewsFind_ctrlRight__(t: *c.__AppEditorViewsFind__) callconv(.c) void { + __AppEditorViewsFind_goToNextSymbol__(t); + if (t.line.text_len > 0) { + const full_text = t.line.text[0..t.line.text_len]; + if (t.symbol >= full_text.len) return; + const text = full_text[t.symbol..]; + const indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + if (indent > 0) { + __AppEditorViewsFind_goToSymbol__(t, t.symbol + indent); + t.need_redraw = true; + return; + } + __AppEditorViewsFind_goToSymbol__(t, c.__TextAscii_findBreakOfWord__(text.ptr, text.len) + t.symbol); + t.need_redraw = true; + } + } + // # __AppEditorViewsFind_cursorMoveToCurrent__ + fn __AppEditorViewsFind_cursorMoveToCurrent__(t: *c.__AppEditorViewsFind__) !void { + c.__Terminal_cursorMove__(&c.__app__.terminal, t.offset.x, t.offset.y); + } + // # __AppEditorViewsFind_deletePrevSymbol__ + fn __AppEditorViewsFind_deletePrevSymbol__(t: *c.__AppEditorViewsFind__) !void { + if (t.symbol == 0) { + return; + } else if (t.symbol > t.line.text_len) { + __AppEditorViewsFind_goToPrevSymbol__(t); + } else { + if (t.line.text_len == 0) return; + __AppEditorViewsFind_goToPrevSymbol__(t); + __AppEditorViewsFind_deleteSymbol__(t); + } + t.need_redraw = true; + } + // # __AppEditorViewsFind_deleteSymbol__ + fn __AppEditorViewsFind_deleteSymbol__(t: *c.__AppEditorViewsFind__) callconv(.c) void { + if (t.line.text_len == 0) return; + + if (c.__Buffer_pop_check__(t.line.text_len, t.symbol)) { + _=c.__Buffer_pop__(&t.line.text[0], &t.line.text_len, t.symbol); + } + + t.need_redraw = true; + } + // # __AppEditorViewsFind_deleteWord__ + fn __AppEditorViewsFind_deleteWord__(t: *c.__AppEditorViewsFind__) !void { + if (t.symbol > t.line.text_len) { + return; + } + while (true) { // delete current symbol + if (t.symbol == t.line.text_len) { + break; + } + const next_symbol = t.line.text[t.symbol]; + if (c.__TextAscii_isLetter__(next_symbol)) { + __AppEditorViewsFind_deleteSymbol__(t); + } else { + break; + } + } + while (true) { // delete prev symbol + if (t.symbol == 0) { + break; + } + const prev_symbol = t.line.text[t.symbol - 1]; + if (c.__TextAscii_isLetter__(prev_symbol)) { + try __AppEditorViewsFind_deletePrevSymbol__(t); + } else { + break; + } + } + t.need_redraw = true; + } + // # __AppEditorViewsFind_do__ + fn __AppEditorViewsFind_do__(ctx: *anyopaque) callconv(.c) void { + const t = __AppEditorViewsFind_getModel__(ctx); + + if (t.need_redraw == true) { + t.need_redraw = false; + __AppEditorViewsFind_draw__(t) catch unreachable; + __AppEditorViewsFind_cursorMoveToCurrent__(t) catch unreachable; + } + } + // # __AppEditorViewsFind_drawEditedLine__ + fn __AppEditorViewsFind_drawEditedLine__(t: *c.__AppEditorViewsFind__) !void { + c.__Terminal_resetColors__(&c.__app__.terminal); + + if (t.line.text_len > 0) { + const text = t.line.text[0 .. t.line.text_len]; + // draw left-to-right from first visible rune + c.__Terminal_moveCursorToStartOfLine__(&c.__app__.terminal); + var pos: usize = t.symbol - t.offset.x; + var offset_x: usize = 0; + // left arrow + if (pos > 0) { // draw '<' + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_arrows__, c.__AppEditorTheme_arrows__.len); + _=__writeTextToWriteFnVoid__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, "<"); + pos += 1; + offset_x += 1; + } + // left symbols + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_current__, c.__AppEditorTheme_current__.len); + while (true) { + if (offset_x >= t.offset.x) break; + if (offset_x >= c.__app__.terminal.output.size.x - 1) break; + if (pos >= text.len) break; + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[pos], 1); + pos += 1; + offset_x += 1; + } + // current symbol. maybe inverse cursour? + if (offset_x < c.__app__.terminal.output.size.x - 2) { + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_current_rune__, c.__AppEditorTheme_current_rune__.len); + if (pos < text.len) { + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[pos], 1); + } + pos += 1; + offset_x += 1; + // right symbols + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_current__, c.__AppEditorTheme_current__.len); + while (true) { + if (offset_x >= c.__app__.terminal.output.size.x - 2) break; + if (pos >= text.len) break; + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[pos], 1); + pos += 1; + offset_x += 1; + } + // right arrow + if (pos < text.len) { // draw '>' + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_arrows__, c.__AppEditorTheme_arrows__.len); + _=__writeTextToWriteFnVoid__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, ">"); + } else { + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_to_end_line__, 0); + } + } + } else { + c.__Console_clearLine__(&c.__app__.console); + } + + } + // # __AppEditorViewsFind_draw__ + fn __AppEditorViewsFind_draw__(t: *c.__AppEditorViewsFind__) !void { + defer __AppEditorViewsFind_cursorMoveToCurrent__(t) catch {}; + + __AppEditorViewsFind_correctOffset__(t); + if (t.offset.x >= c.__app__.terminal.output.size.x) t.offset.x = 0; + if (t.offset.y >= c.__app__.terminal.output.size.y) t.offset.y = 0; + if (t.symbol < t.offset.x) { // unexpected + t.offset.x = 0; + t.symbol = 0; + } + + c.__ConsoleOutput_cursorHide__(&c.__app__.console.output); + defer c.__Console_showCursor__(&c.__app__.console); + + t.offset.y = 1; + { // draw banner + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, 0); + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_headers__, c.__AppEditorTheme_headers__.len); + _=__writeTextToWriteFnVoid__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, "text for find:"); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_to_end_line__, 0); + } + { // draw edit line + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, 1); + try __AppEditorViewsFind_drawEditedLine__(t); + } + var pos_y: usize = 2; + while (true) { // clear other downer lines + if (pos_y >= c.__app__.terminal.output.size.y) break; + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, pos_y); + c.__Console_clearLine__(&c.__app__.console); + pos_y += 1; + } + } + // # __AppEditorViewsFind_find__ + fn __AppEditorViewsFind_find__(t: *c.__AppEditorViewsFind__) !void { + t.context_vtable.*.setAsView.?(t.context); + } + // # __AppEditorViewsFind_getModel__ + fn __AppEditorViewsFind_getModel__(ptr: *anyopaque) callconv(.c) *c.__AppEditorViewsFind__ { + return @alignCast(@ptrCast(ptr)); + } + // # __AppEditorViewsFind_get__ + fn __AppEditorViewsFind_get__(t: *c.__AppEditorViewsFind__) ?[]const u8 { + if (t.*.line.text_len > 0) { + return t.*.line.text[0..t.*.line.text_len]; + } + return null; + } + // # __AppEditorViewsFind_goToEndOfLine__ + fn goToEndOfLine(t: *c.__AppEditorViewsFind__) callconv(.c) void { + t.symbol = t.line.text_len; + if (t.symbol > c.__app__.terminal.output.size.x - 2) { + t.offset.x = c.__app__.terminal.output.size.x - 2; + } else { + t.offset.x = t.symbol; + } + t.need_redraw = true; + } + // # __AppEditorViewsFind_goToNextSymbol__ + fn __AppEditorViewsFind_goToNextSymbol__(t: *c.__AppEditorViewsFind__) callconv(.c) void { + const used = t.line.text_len; + if (t.symbol >= used) { + if (true) return; + if (t.line.next) |_| { + t.goToNextLine(); + t.goToStartOfText(); + } + return; + } + if (t.symbol < c.__AppEditorLineLen_max__ - 1) t.symbol += 1; + if (used - t.symbol >= 10) { + if (t.offset.x < c.__app__.terminal.output.size.x - 12) t.offset.x += 1; + } else { + if (t.offset.x < c.__app__.terminal.output.size.x - 2) t.offset.x += 1; + } + t.need_redraw = true; + } + // # __AppEditorViewsFind_goToPrevSymbol__ + fn __AppEditorViewsFind_goToPrevSymbol__(t: *c.__AppEditorViewsFind__) callconv(.c) void { + const used = t.line.text_len; + if (t.symbol == 0) { + if (true) return; + if (t.line.prev) |_| { + t.goToPrevLine(); + t.goToEndOfLine(); + } + return; + } + if (t.symbol > used) { + t.symbol = used; + if (used < c.__app__.terminal.output.size.x - 1) t.offset.x = t.line.text_len; + t.need_redraw = true; + return; + } + if (t.symbol > 0) t.symbol -= 1; + if (t.symbol >= 10) { + if (t.offset.x > 10) { + t.offset.x -= 1; + } + } else { + if (t.offset.x > 0) t.offset.x -= 1; + } + t.need_redraw = true; + } + // # __AppEditorViewsFind_goToStartOfLine__ + fn __AppEditorViewsFind_goToStartOfLine__(t: *c.__AppEditorViewsFind__) callconv(.c) void { + t.symbol = 0; + t.offset.x = 0; + t.need_redraw = true; + } + // # __AppEditorViewsFind_goToStartOfText__ + fn __AppEditorViewsFind_goToStartOfText__(t: *c.__AppEditorViewsFind__) callconv(.c) void { + if (t.line.text_len > 0) { + const indent = c.__TextAscii_countIndent__(&t.line.text[0], t.line.text_len, 1); + __AppEditorViewsFind_goToSymbol__(t, indent); + } else { + __AppEditorViewsFind_goToSymbol__(t, 0); + } + } + // # __AppEditorViewsFind_goToSymbol__ + fn __AppEditorViewsFind_goToSymbol__(t: *c.__AppEditorViewsFind__, pos: usize) callconv(.c) void { + t.symbol = pos; + if (t.symbol > c.__app__.terminal.output.size.x - 3) { + t.offset.x = 8; + } else { + t.offset.x = t.symbol; + } + t.need_redraw = true; + } + // # __AppEditorViewsFind_init__ + fn __AppEditorViewsFind_init__(t: *c.__AppEditorViewsFind__) !void { + t.offset.x = 0; + t.offset.y = 3; + t.need_redraw = true; + t.symbol = 0; + c.__AppEditorLine_init__(&t.line); + } + // # __AppEditorViewsFind_insertSymbol__ + fn __AppEditorViewsFind_insertSymbol__(t: *c.__AppEditorViewsFind__, rune: u8) !void { + if (t.symbol > t.line.text_len) __AppEditorViewsFind_goToSymbol__(t, t.line.text_len); + if (t.line.text_len < c.__AppEditorLineLen_max__) { + c.__Buffer_push__(&t.line.text[0], &t.line.text_len, t.symbol, rune); + __AppEditorViewsFind_goToNextSymbol__(t); + } + t.need_redraw = true; + } + // # __AppEditorViewsFind_onKey__ + fn __AppEditorViewsFind_onKey__(t: *c.__AppEditorViewsFind__, cik: c.__ConsoleAnsiInputKey__) callconv(.c) void { + __AppEditorViewsFind_onkeyWrap__(t, cik) catch {}; + } + // # __AppEditorViewsFind_onkeyWrap__ + fn __AppEditorViewsFind_onkeyWrap__(t: *c.__AppEditorViewsFind__, cik: c.__ConsoleAnsiInputKey__) !void { + switch (cik) { + c.__ConsoleAnsiInputKey_ctrl_left__ => __AppEditorViewsFind_ctrlLeft__(t), + c.__ConsoleAnsiInputKey_ctrl_right__ => __AppEditorViewsFind_ctrlRight__(t), + c.__ConsoleAnsiInputKey_delete__ => __AppEditorViewsFind_deleteSymbol__(t), + c.__ConsoleAnsiInputKey_shift_delete__ => __AppEditorViewsFind_clearLine__(t), + c.__ConsoleAnsiInputKey_left__ => __AppEditorViewsFind_goToPrevSymbol__(t), + c.__ConsoleAnsiInputKey_right__ => __AppEditorViewsFind_goToNextSymbol__(t), + c.__ConsoleAnsiInputKey_escape__ => try __AppEditorViewsFind_cancel__(t), + c.__ConsoleAnsiInputKey_ctrl_q__ => try __AppEditorViewsFind_cancel__(t), + c.__ConsoleAnsiInputKey_back_space__ => try __AppEditorViewsFind_deletePrevSymbol__(t), + c.__ConsoleAnsiInputKey_ctrl_bs__ => try __AppEditorViewsFind_deletePrevSymbol__(t), + c.__ConsoleAnsiInputKey_ctrl_j__ => try __AppEditorViewsFind_find__(t), + c.__ConsoleAnsiInputKey_enter__ => try __AppEditorViewsFind_find__(t), + c.__ConsoleAnsiInputKey_ctrl_w__ => try __AppEditorViewsFind_deleteWord__(t), + + else => { + const byte: u8 = @truncate(cik); + __AppEditorViewsFind_insertSymbol__(t, byte) catch {}; + }, + } + } + // # __AppEditorViewsFind_setAsView__ + fn __AppEditorViewsFind_setAsView__(t: *c.__AppEditorViewsFind__, last_context: *anyopaque, last_vtable: *const c.__AppEditorViewsVTable__) callconv(.c) void { + t.context = last_context; + t.context_vtable = last_vtable; + + c.__app__.editor.do_ptr = @ptrCast(&__AppEditorViewsFind_do__); + c.__app__.editor.onKey_ptr = @ptrCast(&__AppEditorViewsFind_onKey__); + c.__app__.editor.current_ctx = t; + t.need_redraw = true; + } + // # __AppEditorViewsFlatVtable_countLineNum__ + fn __AppEditorViewsFlatVtable_countLineNum__(ctx: *anyopaque) callconv(.c) usize { + const view: *c.__AppEditorViewsFlat__ = @alignCast(@ptrCast(ctx)); + return __AppEditorViewsFlat_countLineNum__(view, view.line); + } + // # __AppEditorViewsFlatVtable_getOffsetX__ + fn __AppEditorViewsFlatVtable_getOffsetX__(ctx: *anyopaque) callconv(.c) usize { + const view: *c.__AppEditorViewsFlat__ = @alignCast(@ptrCast(ctx)); + return view.offset.x; + } + // # __AppEditorViewsFlatVtable_getOffsetY__ + fn __AppEditorViewsFlatVtable_getOffsetY__(ctx: *anyopaque) callconv(.c) usize { + const view: *c.__AppEditorViewsFlat__ = @alignCast(@ptrCast(ctx)); + return view.offset.y; + } + // # __AppEditorViewsFlatVtable_getSymbolPosX__ + fn __AppEditorViewsFlatVtable_getSymbolPosX__(ctx: *anyopaque) callconv(.c) usize { + const view: *c.__AppEditorViewsFlat__ = @alignCast(@ptrCast(ctx)); + return view.symbol; + } + // # __AppEditorViewsFlatVtable_goToLineFromNumber__ + fn __AppEditorViewsFlatVtable_goToLineFromNumber__(ctx: *anyopaque, _num: usize) callconv(.c) void { + const view: *c.__AppEditorViewsFlat__ = @alignCast(@ptrCast(ctx)); + return __AppEditorViewsFlat_goToLineFromNumber__(view, _num); + } + // # __AppEditorViewsFlatVtable_goToNextLine__ + fn __AppEditorViewsFlatVtable_goToNextLine__(ctx: *anyopaque) callconv(.c) void { + const view: *c.__AppEditorViewsFlat__ = @alignCast(@ptrCast(ctx)); + _=__AppEditorViewsFlat_goToNextLine__(view); + } + // # __AppEditorViewsFlatVtable_goToPrevLine__ + fn __AppEditorViewsFlatVtable_goToPrevLine__(ctx: *anyopaque) callconv(.c) void { + const view: *c.__AppEditorViewsFlat__ = @alignCast(@ptrCast(ctx)); + _=__AppEditorViewsFlat_goToPrevLine__(view); + } + // # __AppEditorViewsFlatVtable_goToSymbolPosX__ + fn __AppEditorViewsFlatVtable_goToSymbolPosX__(ctx: *anyopaque, pos: usize) callconv(.c) void { + const view: *c.__AppEditorViewsFlat__ = @alignCast(@ptrCast(ctx)); + __AppEditorViewsFlat_goToSymbol__(view, pos); + } + // # __AppEditorViewsFlatVtable_init__ + fn __AppEditorViewsFlatVtable_init__(t: *c.__AppEditorViewsVTable__) void { + t.setAsView = @ptrCast(&__AppEditorViewsFlatVtable_setAsView__); + t.goToPrevLine = @ptrCast(&__AppEditorViewsFlatVtable_goToPrevLine__); + t.goToNextLine = @ptrCast(&__AppEditorViewsFlatVtable_goToNextLine__); + t.getOffsetX = @ptrCast(&__AppEditorViewsFlatVtable_getOffsetX__); + t.getOffsetY = @ptrCast(&__AppEditorViewsFlatVtable_getOffsetY__); + t.goToSymbolPosX = @ptrCast(&__AppEditorViewsFlatVtable_goToSymbolPosX__); + t.getSymbolPosX = @ptrCast(&__AppEditorViewsFlatVtable_getSymbolPosX__); + t.countLineNum = @ptrCast(&__AppEditorViewsFlatVtable_countLineNum__); + t.goToLineFromNumber = @ptrCast(&__AppEditorViewsFlatVtable_goToLineFromNumber__); + } + // # __AppEditorViewsFlatVtable_setAsView__ + fn __AppEditorViewsFlatVtable_setAsView__(ctx: *anyopaque) callconv(.c) void { + const view: *c.__AppEditorViewsFlat__ = @alignCast(@ptrCast(ctx)); + __AppEditorViewsFlat_setAsView__(view) catch unreachable; + c.__app__.editor.current_vtable = &c.__AppEditorViewsVtable_flat__; + } + // # __AppEditorViewsFlat_addIndent__ + fn __AppEditorViewsFlat_addIndent__(t: *c.__AppEditorViewsFlat__) !void { + var text: []u8 = ""; + if (t.line.text_len > 0) text = t.line.text[0 .. t.line.text_len]; + const indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + if (c.__AppEditorLine_setIndent__(t.line, indent + 4) == false) return error.Unexpected; + t.need_redraw = true; + } + // # __AppEditorViewsFlat_addNextLine__ + fn __AppEditorViewsFlat_addNextLine__(t: *c.__AppEditorViewsFlat__) !void { + var ok: bool = true; + var new_line: *c.__AppEditorLine__ = undefined; + if ( c.__AppEditorLine_alloc__( @ptrCast(&new_line) ) ) { + c.__AppEditorLine_init__(new_line); + c.__MemList_pushAfter__(&t.lines, &t.line.*.link, &new_line.link); + _=__AppEditorViewsFlat_goToNextLine__(t); + __AppEditorViewsFlat_goToStartOfText__(t); + t.need_redraw = true; + + if (!ok) c.__AppEditorLine_free__(new_line); + } else { + ok = false; + } + if (!ok) return error.Unexpected; + } + // # __AppEditorViewsFlat_addPrevLine__ + fn __AppEditorViewsFlat_addPrevLine__(t: *c.__AppEditorViewsFlat__) !void { + var ok: bool = true; + var new_line: *c.__AppEditorLine__ = undefined; + if ( c.__AppEditorLine_alloc__( @ptrCast(&new_line) ) ) { + c.__AppEditorLine_init__(new_line); + c.__MemList_pushBefore__(&t.lines, &t.line.*.link, &new_line.link); + _=__AppEditorViewsFlat_goToPrevLine__(t); + __AppEditorViewsFlat_goToStartOfText__(t); + t.need_redraw = true; + + if (!ok) c.__AppEditorLine_free__(new_line); + } else { + ok = false; + } + + if (!ok) return error.Unexpected; + } + // # __AppEditorViewsFlat_bakupTextOnCurrentLine__ + fn __AppEditorViewsFlat_bakupTextOnCurrentLine__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + if (t.line.*.text_len > 0) { + t.bakup_line.text_len = t.line.*.text_len; + c.__Mem_copy__(&t.bakup_line.text[0], &t.line.*.text[0], t.line.*.text_len); + } + } + // # __AppEditorViewsFlat_changeOffsetX__ + fn __AppEditorViewsFlat_changeOffsetX__(t: *c.__AppEditorViewsFlat__, pos: usize) callconv(.c) void { + t.offset.x = pos; + __AppEditorViewsFlat_correctOffsetX__(t); + } + // # __AppEditorViewsFlat_clearLine__ + fn __AppEditorViewsFlat_clearLine__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + t.line.*.text_len = 0; + __AppEditorViewsFlat_goToStartOfText__(t); + t.need_redraw = true; + } + // # __AppEditorViewsFlat_copyDownIntervals__ + fn __AppEditorViewsFlat_copyDownIntervals__(t: *c.__AppEditorViewsFlat__) !void { + const next_line_link: *c.__MemListLink__ = t.line.*.link.next orelse return; + const next_line: *c.__AppEditorLine__ = @fieldParentPtr("link", next_line_link); + + try t.copyIntervalsAfterDC(next_line); + try t.copyIntervalsBeforeEQ(next_line); + t.need_redraw = true; + } + // # __AppEditorViewsFlat_copyUpIntervals__ + fn __AppEditorViewsFlat_copyUpIntervals__(t: *c.__AppEditorViewsFlat__) !void { + const prev_line_link: *c.__MemListLink__ = t.line.*.link.prev orelse return; + const prev_line: *c.__AppEditorLine__ = @fieldParentPtr("link", prev_line_link); + + try t.copyIntervalsAfterDC(prev_line); + try t.copyIntervalsBeforeEQ(prev_line); + t.need_redraw = true; + } + // # __AppEditorViewsFlat_copyWordToFind__ + fn __AppEditorViewsFlat_copyWordToFind__(t: *c.__AppEditorViewsFlat__) !void { + const line = t.line; + if (line.*.text_len > 0) { + const text = t.line.*.text[0 .. t.line.*.text_len]; + if (t.symbol < line.*.text_len) { + const sow: usize = blk: { // start_of_word + var pos: usize = t.symbol; + while (true) { + if (pos == 0) break; + const prev_symbol = text[pos - 1]; + if (c.__TextAscii_isLetter__(prev_symbol) == false) break; + pos -= 1; + } + break :blk pos; + }; + const eow: usize = blk: { // end_of_word + var pos: usize = t.symbol; + while (true) { + if (pos >= t.line.*.text_len - 1) { + break; + } + const next_symbol = text[pos + 1]; + if (c.__TextAscii_isLetter__(next_symbol) == false) break; + pos += 1; + } + break :blk pos; + }; + const word = text[sow .. eow + 1]; + { // copy to find_line + // current word cannot be bigger than __AppEditorLineLen_max__, but when lines size be dynamic allocated then need recheck + const find_line: *c.__AppEditorLine__ = &c.__app__.editor.views.find.line; + find_line.text_len = word.len; + c.__Mem_copy__(&find_line.text[0], word.ptr, word.len); + } + __AppEditor_changeStatus__("word copied"); + } else { + __AppEditor_changeStatus__("cursor not an word"); + } + } + } + // # __AppEditorViewsFlat_correctOffsetX__ + fn __AppEditorViewsFlat_correctOffsetX__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + const tsx = c.__app__.terminal.output.size.x; + if (t.offset.x >= tsx) t.offset.x = 0; + + const predel = (tsx >> 1) - (tsx >> 4); + if (t.symbol >= predel) t.offset.x = predel; + } + // # __AppEditorViewsFlat_correctOffsetY__ + fn __AppEditorViewsFlat_correctOffsetY__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + // { correct offset_y: + const tsy = c.__app__.terminal.output.size.y; + if (t.offset.y >= tsy) t.offset.y = 0; + if (tsy <= 5) return; + + // count downest_lines + var count_to_downest_line: usize = 0; + var line: *c.__MemListLink__ = &t.line.*.link; + while (count_to_downest_line < 5) { + if (line.next) |down_next| { + count_to_downest_line += 1; + line = down_next; + } else { + break; + } + } + + if (tsy - t.offset.y < count_to_downest_line) { + t.offset.y = tsy - count_to_downest_line; + } + //} + } + // # __AppEditorViewsFlat_countLineNum__ + fn __AppEditorViewsFlat_countLineNum__(t: *c.__AppEditorViewsFlat__, line: *c.__AppEditorLine__) callconv(.c) usize { + _ = t; + var pos: usize = 1; + var link: [*c]c.__MemListLink__ = &line.link; + while (c.__MemListLink_isFirst__(link) == false) { // todo just use while prev + pos += 1; + link = link.*.prev; + } + return pos; + } + // # __AppEditorViewsFlat_ctrlDown__ + fn __AppEditorViewsFlat_ctrlDown__ (t: *c.__AppEditorViewsFlat__) callconv(.c) void { + var last_text: []const u8 = ""; + if (t.line.*.text_len > 0) last_text = t.line.*.text[0 .. t.line.*.text_len]; + const last_indent = c.__TextAscii_countIndent__(last_text.ptr, last_text.len, 1); + while(__AppEditorViewsFlat_goToNextLine__(t)) { + var new_text: []u8 = ""; + if (t.line.*.text_len > 0) new_text = t.line.*.text[0 .. t.line.*.text_len]; + const new_indent = c.__TextAscii_countIndent__(new_text.ptr, new_text.len, 1); + if (true // line not empty and indent <= last_indent + // line not empty + and new_text.len > new_indent + and c.__TextAscii_isVisible__(new_text[new_indent]) + and new_indent <= last_indent + ) { + break; + } + } + } + // # __AppEditorViewsFlat_ctrlLeft__ + fn __AppEditorViewsFlat_ctrlLeft__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + __AppEditorViewsFlat_goToPrevSymbol__(t); + if (t.symbol > 0) { + const line: *c.__AppEditorLine__ = t.line; + if (line.text_len > 0) { + const text: []u8 = line.text[0 .. t.symbol]; + const spaces: usize = c.__TextAscii_countIndentReverse__(text.ptr, text.len, 1); + var dest_pos: usize = 0; + if (spaces > 0) { + dest_pos = t.symbol - spaces; + } else { + dest_pos = c.__TextAscii_findBreakOfWordReverse__(text.ptr, text.len); + if (dest_pos > 0) dest_pos += 1; + } + __AppEditorViewsFlat_goToSymbol__(t, dest_pos); + } else { + __AppEditorViewsFlat_goToSymbol__(t, 0); + } + } + t.need_redraw = true; + } + // # __AppEditorViewsFlat_ctrlRight__ + fn __AppEditorViewsFlat_ctrlRight__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + __AppEditorViewsFlat_goToNextSymbol__(t); + if (t.line.*.text_len > 0) { + const full_text = t.line.*.text[0 .. t.line.*.text_len]; + if (t.symbol >= full_text.len) return; + const text = full_text[t.symbol..]; + const spaces = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + if (spaces > 0) { + __AppEditorViewsFlat_goToSymbol__(t, t.symbol + spaces); + t.need_redraw = true; + return; + } + const dest_pos = c.__TextAscii_findBreakOfWord__(text.ptr, text.len) + t.symbol; + __AppEditorViewsFlat_goToSymbol__(t, dest_pos); + } + t.need_redraw = true; + } + // # __AppEditorViewsFlat_ctrlShiftLeft__ + fn __AppEditorViewsFlat_ctrlShiftLeft__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + var text: []u8 = ""; + if (t.line.*.text_len > 0) { + text = t.line.*.text[0 .. t.line.*.text_len]; + const indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + if (t.symbol > indent) { + __AppEditorViewsFlat_goToSymbol__(t, indent); + } else { + __AppEditorViewsFlat_goToStartOfLine__(t); + } + } + t.need_redraw = true; + } + // # __AppEditorViewsFlat_ctrlShiftRight__ + fn __AppEditorViewsFlat_ctrlShiftRight__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + var text: []u8 = ""; + if (t.line.*.text_len > 0) {text = t.line.*.text[0 .. t.line.*.text_len];} + const indent: usize = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + if (t.symbol < indent) __AppEditorViewsFlat_goToSymbol__(t, indent) else __AppEditorViewsFlat_goToEndOfLine__(t); + t.need_redraw = true; + } + // # __AppEditorViewsFlat_ctrlUp__ + fn __AppEditorViewsFlat_ctrlUp__ (t: *c.__AppEditorViewsFlat__) callconv(.c) void { + var last_text: []u8 = ""; + if (t.line.*.text_len > 0) last_text = t.line.*.text[0 .. t.line.*.text_len]; + const last_indent = c.__TextAscii_countIndent__(last_text.ptr, last_text.len, 1); + while(__AppEditorViewsFlat_goToPrevLine__(t)) { + var new_text: []u8 = ""; + if (t.line.*.text_len > 0) new_text = t.line.*.text[0 .. t.line.*.text_len]; + const new_indent = c.__TextAscii_countIndent__(new_text.ptr, new_text.len, 1); + if (true // line not empty and indent <= last_indent + // line not empty + and new_text.len > new_indent + and c.__TextAscii_isVisible__(new_text[new_indent]) + // + and new_indent <= last_indent + ) { + break; + } + } + } + // # __AppEditorViewsFlat_ctrl_t__ + fn __AppEditorViewsFlat_ctrl_t__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + const text = "__scalpi__.__print__(__TRACE__(), )"; + for (text) |symbol| { + __AppEditorViewsFlat_insertSymbol__(t, symbol) catch {}; + } + __AppEditorViewsFlat_goToPrevSymbol__(t); + } + // # __AppEditorViewsFlat_cursorMoveToCurrent__ + fn __AppEditorViewsFlat_cursorMoveToCurrent__(t: *c.__AppEditorViewsFlat__) !void { + c.__Terminal_cursorMove__(&c.__app__.terminal, t.offset.x, t.offset.y); + } + // # __AppEditorViewsFlat_cutLine__ + fn __AppEditorViewsFlat_cutLine__(t: *c.__AppEditorViewsFlat__) !void { + var ok: bool = true; + const current_link = &t.line.*.link; + var next_link: *c.__MemListLink__ = undefined; + if (current_link.next) |_next_link| { + next_link = _next_link; + } else if (current_link.prev) |prev_link| { + next_link = prev_link; + } else { + // create prev line + var new_empty_line: *c.__AppEditorLine__ = undefined; + if ( c.__AppEditorLine_alloc__( @ptrCast(&new_empty_line) ) ) { + c.__AppEditorLine_init__(new_empty_line); + c.__MemList_pushFirst__(&t.lines, &new_empty_line.link); { + next_link = &new_empty_line.link; + if (!ok) c.__MemList_pop__(&t.lines, &new_empty_line.link); + } + + if (!ok) c.__AppEditorLine_free__(new_empty_line); + } else { + ok = false; + } + } + + if (ok) { + // move to cut + c.__MemList_pop__(&t.lines, current_link); + c.__MemList_pushLast__(&t.cutted, current_link); + + // update screen + const line: *c.__AppEditorLine__ = @fieldParentPtr("link", next_link); + t.line = line; + t.need_redraw = true; + __AppEditorViewsFlat_bakupTextOnCurrentLine__(t); + } + + if (!ok) return error.Unexpected; + } + // # __AppEditorViewsFlat_deleteCutted__ + fn __AppEditorViewsFlat_deleteCutted__(t: *c.__AppEditorViewsFlat__) !void { + while (t.cutted.count > 0) { + const link: *c.__MemListLink__ = t.cutted.first orelse unreachable; + c.__MemList_pop__(&t.cutted, link); + const line: *c.__AppEditorLine__ = @fieldParentPtr("link", link); + c.__AppEditorLine_free__(line); + } + __AppEditor_changeStatus__("cutted lines is gone :)"); + __AppEditorViewsFlat_cursorMoveToCurrent__(t) catch {}; + } + // # __AppEditorViewsFlat_deleteIndent__ + fn __AppEditorViewsFlat_deleteIndent__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + _=c.__AppEditorLine_setIndent__(t.line, 0); + t.need_redraw = true; + } + // # __AppEditorViewsFlat_deletePrevSymbol__ + fn __AppEditorViewsFlat_deletePrevSymbol__(t: *c.__AppEditorViewsFlat__) !void { + __AppEditorViewsFlat_goToPrevSymbol__(t); + if (t.line.*.text_len > t.symbol) { + __AppEditorViewsFlat_deleteSymbol__(t); + } + t.need_redraw = true; + } + // # __AppEditorViewsFlat_deleteSymbol__ + fn __AppEditorViewsFlat_deleteSymbol__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + if (t.line.*.text_len == 0) return; + + if (c.__Buffer_pop_check__(t.line.*.text_len, t.symbol)) { + _=c.__Buffer_pop__(&t.line.*.text[0], &t.line.*.text_len, t.symbol); + } + + t.need_redraw = true; + } + // # __AppEditorViewsFlat_deleteWord__ + fn __AppEditorViewsFlat_deleteWord__(t: *c.__AppEditorViewsFlat__) !void { + if (t.symbol > t.line.*.text_len) { + return; + } + while (true) { // delete current symbol + if (t.symbol == t.line.*.text_len) { + break; + } + const next_symbol = t.line.*.text[t.symbol]; + if (c.__TextAscii_isLetter__(next_symbol)) { + __AppEditorViewsFlat_deleteSymbol__(t); + } else { + break; + } + } + while (true) { // delete prev symbol + if (t.symbol == 0) { + break; + } + const prev_symbol = t.line.*.text[t.symbol - 1]; + if (c.__TextAscii_isLetter__(prev_symbol)) { + try __AppEditorViewsFlat_deletePrevSymbol__(t); + } else { + break; + } + } + t.need_redraw = true; + } + // # __AppEditorViewsFlat_divideLine__ + fn __AppEditorViewsFlat_divideLine__(t: *c.__AppEditorViewsFlat__) !void { + if (t.line.*.text_len > 0) { + const current_text: []u8 = t.line.*.text[0 .. t.line.*.text_len]; + const indent = c.__TextAscii_countIndent__(current_text.ptr, current_text.len, 1); + if (t.symbol <= indent) { // just add prev line + const last_symbol = t.symbol; + const last_offset = t.offset.x; + try __AppEditorViewsFlat_addPrevLine__(t); + + // copy indent + for (t.line.*.text[0..indent], current_text[0..indent]) + |*rune, indent_symbol| + rune.* = indent_symbol + ; + t.line.*.text_len = indent; + + t.symbol = last_symbol; + t.offset.x = last_offset; + } else if (t.symbol >= t.line.*.text_len) { + try __AppEditorViewsFlat_addNextLine__(t); + + // copy indent + if (t.__AppEditorViewsFlat_autoSpace__) { + for (t.line.*.text[0..indent], current_text[0..indent]) |*rune, indent_symbol| rune.* = indent_symbol; + t.line.*.text_len = indent; + } + + } else { // separate text to 2 line + const parent = t.line; + const pos = t.symbol; + const copy_text = current_text[pos..]; + try __AppEditorViewsFlat_addNextLine__(t); + t.line.*.text_len = indent + current_text.len; + + // copy indent + if (t.__AppEditorViewsFlat_autoSpace__) { + for (t.line.*.text[0..indent], current_text[0..indent]) |*rune, indent_symbol| rune.* = indent_symbol; + t.line.*.text_len = indent; + std.mem.copyForwards(u8, t.line.*.text[indent..], copy_text); + parent.*.text_len = pos; + t.line.*.text_len = indent + copy_text.len; + } else { + std.mem.copyForwards(u8, t.line.*.text[0..], copy_text); + parent.*.text_len = pos; + t.line.*.text_len = copy_text.len; + } + } + } else { + try __AppEditorViewsFlat_addNextLine__(t); + } + __AppEditorViewsFlat_goToStartOfText__(t); + t.need_redraw = true; + } + // # __AppEditorViewsFlat_do__ + fn __AppEditorViewsFlat_do__(ctx: *anyopaque) callconv(.c) void { + var ok: bool = true; + const t: *c.__AppEditorViewsFlat__ = @alignCast(@ptrCast(ctx)); + + if (t.need_redraw) { + t.need_redraw = false; + if (__AppEditorViewsFlat_draw__(t)) { + if (__AppEditorViewsFlat_cursorMoveToCurrent__(t)) { + } else |_| { + ok = false; + } + } else |_| { + ok = false; + } + } + + if (t.need_draw_line_num) { + t.need_draw_line_num = false; + if (__AppEditorViewsFlat_drawCountLineNum__(t)) { + if (__AppEditorViewsFlat_cursorMoveToCurrent__(t)) { + } else |_| { + ok = false; + } + } else |_| { + ok = false; + } + } + if (!ok) unreachable; + //return ok; + } + // # __AppEditorViewsFlat_drawCountLineNum__ + fn __AppEditorViewsFlat_drawCountLineNum__(t: *c.__AppEditorViewsFlat__) !void { + const pos: usize = __AppEditorViewsFlat_countLineNum__(t, t.line); + + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, c.__app__.terminal.output.size.y - 1); + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_notification__, c.__AppEditorTheme_notification__.len); + + //print("line number = {pos}"); + _=__writeTextToWriteFnVoid__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, " line number = "); + _=c.__Text_formatU64__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, pos, 1); + + c.__Terminal_resetColors__(&c.__app__.terminal); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_to_end_line__, 0); + try __AppEditorViewsFlat_cursorMoveToCurrent__(t); + t.need_redraw = false; + } + // # __AppEditorViewsFlat_drawDownerLines__ + fn __AppEditorViewsFlat_drawDownerLines__(t: *c.__AppEditorViewsFlat__) !void { + // change color + c.__Terminal_resetColors__(&c.__app__.terminal); + + var pos_y: usize = t.offset.y + 1; + c.__app__.editor.lines_drawing = pos_y; + if (pos_y >= c.__app__.terminal.output.size.y) return; + var link = &t.line.*.link; + while (true) { // draw + link = link.next orelse break; + const line: *c.__AppEditorLine__ = @fieldParentPtr("link", link); + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, pos_y); + try __AppEditorViewsFlat_drawLine__(t, line); + if (pos_y >= c.__app__.terminal.output.size.y - 1) { + c.__app__.editor.lines_drawing = c.__app__.terminal.output.size.y; + return; + } + pos_y += 1; + } + c.__app__.editor.lines_drawing = pos_y; + c.__Terminal_resetColors__(&c.__app__.terminal); + while (true) { // clear other downer lines + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, pos_y); + c.__Console_clearLine__(&c.__app__.console); + if (pos_y >= c.__app__.terminal.output.size.y - 1) return; + pos_y += 1; + } + } + // # __AppEditorViewsFlat_drawEditedLine__ + fn __AppEditorViewsFlat_drawEditedLine__(t: *c.__AppEditorViewsFlat__) !void { + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, t.offset.y); + + if (t.line.*.text_len > 0) { + const text = t.line.*.text[0 .. t.line.*.text_len]; + try __AppEditorViewsFlat_drawLine__(t, t.line); + + const screen_start: usize = t.symbol - t.offset.x; // first visible rune + const screen_end: usize = screen_start + c.__app__.terminal.output.size.x; + + // draw left arrow '<' + if (screen_start > 0) { + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, t.offset.y); + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_arrows__, c.__AppEditorTheme_arrows__.len); + _=__writeTextToWriteFnVoid__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, "<"); + } + + // draw right arrow '>' + if (screen_end < text.len) { + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_arrows__, c.__AppEditorTheme_arrows__.len); + c.__Terminal_cursorMove__(&c.__app__.terminal, c.__app__.terminal.output.size.x - 1, t.offset.y); + _=__writeTextToWriteFnVoid__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, ">"); + } + + // redraw current symbol + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_current_rune__, c.__AppEditorTheme_current_rune__.len); + c.__Terminal_cursorMove__(&c.__app__.terminal, t.offset.x, t.offset.y); + if (t.symbol < text.len) { + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[t.symbol], 1); + } else { + c.__Terminal_writeToOutput__(&c.__app__.terminal, "#", 1); + } + } else { + c.__Terminal_resetColors__(&c.__app__.terminal); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_line__, 0); + } + } + // # __AppEditorViewsFlat_drawLine__ + fn __AppEditorViewsFlat_drawLine__(t: *c.__AppEditorViewsFlat__, line: *c.__AppEditorLine__) !void { + c.__Terminal_moveCursorToStartOfLine__(&c.__app__.terminal); + if (line.text_len > 0) { + const text = line.text[0 .. line.text_len]; + // draw left-to-right from first visible rune + const screen_start: usize = t.symbol - t.offset.x; // first visible rune + const screen_end: usize = screen_start + c.__app__.terminal.output.size.x; + if (text.len > screen_start) { + c.__Terminal_resetColors__(&c.__app__.terminal); + var visible_text_ptr: [*c]const u8 = undefined; _=&visible_text_ptr; + var visible_text_len: usize = undefined; _=&visible_text_len; + if (c.__TextAscii_getNonIndent__(&visible_text_ptr, &visible_text_len, text.ptr, text.len)) { + const visible_text: []const u8 = visible_text_ptr[0..visible_text_len]; + var is_comment: u8 = 0; // 0 - false, 1 - commentary, 2 - disabled commentary + if (false // comment with space + or std.mem.startsWith(u8, visible_text, "# ") + or std.mem.startsWith(u8, visible_text, "// ") + or std.mem.startsWith(u8, visible_text, "; ") + or std.mem.startsWith(u8, visible_text, "-- ") + ) { // is commentary + is_comment = 1; + } else if (false // commant without space + or std.mem.startsWith(u8, visible_text, "#") + or std.mem.startsWith(u8, visible_text, "//") + or std.mem.startsWith(u8, visible_text, ";") + or std.mem.startsWith(u8, visible_text, "--") + ) { // is disabled commentary + is_comment = 2; + } + // draw + var text_end: usize = text.len; + if (text.len > screen_end) text_end = screen_end; + const draw_len = text_end - screen_start; + + if (is_comment == 2) { + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_disabled__, c.__AppEditorTheme_disabled__.len); + const draw_ptr = &text[screen_start]; + c.__Terminal_writeToOutput__(&c.__app__.terminal, draw_ptr, draw_len); + } else if (is_comment == 1) { + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_commentary__, c.__AppEditorTheme_commentary__.len); + const draw_ptr = &text[screen_start]; + c.__Terminal_writeToOutput__(&c.__app__.terminal, draw_ptr, draw_len); + } else { // coloring ^_^ + var color: [5]u8 = "\x1B[90m".*; + var last_pos: usize = 0; + var pos: usize = 0; + var hash_summ: u8 = 0; + var last_symbol_is_word: bool = false; + while (pos < draw_len) { + const symbol: u8 = text[screen_start + pos]; + if (c.__TextAsciiSymbol_isWordSymbol__(symbol)) { + if (last_symbol_is_word == false) { + last_symbol_is_word = true; + + color[3] = '0' + ((hash_summ & 0b111)); + c.__Terminal_setFontStyle__(&c.__app__.terminal, &color[0], color.len); + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[screen_start + last_pos], pos - last_pos); + last_pos = pos; + hash_summ = 0; + } + + hash_summ +%= symbol; + pos += 1; + } else { + color[3] = '0' + ((hash_summ & 0b111)); + c.__Terminal_setFontStyle__(&c.__app__.terminal, &color[0], color.len); + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[screen_start + last_pos], pos - last_pos); + last_pos = pos; + + hash_summ = symbol; + pos += 1; + + if (false) { // spaces + if (symbol == ' ') { + while(pos < draw_len-1) { + if (text[screen_start + pos+1] != ' ') { + break; + } + pos += 1; + } + } + c.__Terminal_setFontStyle__(&c.__app__.terminal, &color[0], color.len); + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[screen_start + last_pos], pos - last_pos); + last_pos = pos; + } + last_symbol_is_word = false; + } + } + if (last_pos < draw_len) { + color[3] = '0' + (hash_summ & 0b111); + c.__Terminal_setFontStyle__(&c.__app__.terminal, &color[0], color.len); + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[screen_start + last_pos], draw_len - last_pos); + } + } + } + } + } + + // clear other line space + c.__Terminal_resetColors__(&c.__app__.terminal); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_to_end_line__, 0); + } + // # __AppEditorViewsFlat_drawUpperLines__ + fn __AppEditorViewsFlat_drawUpperLines__(t: *c.__AppEditorViewsFlat__) !void { + // change color + c.__Terminal_resetColors__(&c.__app__.terminal); + + if (t.offset.y == 0) return; + var pos_y: usize = t.offset.y - 1; + var link = &t.line.*.link; + while (true) { // draw + link = link.prev orelse break; + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, pos_y); + const line: *c.__AppEditorLine__ = @fieldParentPtr("link", link); + try __AppEditorViewsFlat_drawLine__(t, line); + if (pos_y == 0) return; + pos_y -= 1; + } + + c.__Terminal_resetColors__(&c.__app__.terminal); + while (true) { // clear other upp lines + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, pos_y); + c.__Console_clearLine__(&c.__app__.console); + if (pos_y == 0) return; + pos_y -= 1; + } + } + // # __AppEditorViewsFlat_draw__ + fn __AppEditorViewsFlat_draw__(t: *c.__AppEditorViewsFlat__) !void { + defer __AppEditorViewsFlat_cursorMoveToCurrent__(t) catch {}; + + __AppEditorViewsFlat_correctOffsetX__(t); + __AppEditorViewsFlat_correctOffsetY__(t); + c.__ConsoleOutput_cursorHide__(&c.__app__.console.output); + defer c.__Console_showCursor__(&c.__app__.console); + + // draw edit line + try __AppEditorViewsFlat_drawEditedLine__(t); + + // draw other lines + if (c.__app__.terminal.output.size.y <= 1) return; + try __AppEditorViewsFlat_drawUpperLines__(t); + try __AppEditorViewsFlat_drawDownerLines__(t); + } + // # __AppEditorViewsFlat_duplicateLineAndCut__ + fn __AppEditorViewsFlat_duplicateLineAndCut__(t: *c.__AppEditorViewsFlat__) !void { + try __AppEditorViewsFlat_duplicateLine__(t); + try __AppEditorViewsFlat_cutLine__(t); + __AppEditor_changeStatus__("copied."); + __AppEditorViewsFlat_cursorMoveToCurrent__(t) catch {}; + } + // # __AppEditorViewsFlat_duplicateLine__ + fn __AppEditorViewsFlat_duplicateLine__(t: *c.__AppEditorViewsFlat__) !void { + var ok: bool = true; + var copy: *c.__AppEditorLine__ = undefined; + if ( c.__AppEditorLine_alloc__( @ptrCast(©) ) ) { + c.__AppEditorLine_init__(copy); + copy.text_len = t.line.*.text_len; + if (t.line.*.text_len > 0) c.__Mem_copy__(©.text[0], &t.line.*.text[0], t.line.*.text_len); + c.__MemList_pushAfter__(&t.lines, &t.line.*.link, ©.link); + t.line = copy; + t.need_redraw = true; + + if (!ok) c.__AppEditorLine_free__(copy); + } else { + ok = false; + } + if (!ok) return error.Unexpected; + } + // # __AppEditorViewsFlat_easyMotionH__ + fn __AppEditorViewsFlat_easyMotionH__(t: *c.__AppEditorViewsFlat__) !void { + __AppEditorViewsEasyMotionHorizontal_setAsView__(t, &c.__AppEditorViewsVtable_flat__); + } + // # __AppEditorViewsFlat_easyMotionV__ + fn __AppEditorViewsFlat_easyMotionV__(t: *c.__AppEditorViewsFlat__) !void { + __AppEditorViewsEasyMotionVertical_setAsView__(t, &c.__AppEditorViewsVtable_flat__); + } + // # __AppEditorViewsFlat_enterToBlock__ + fn __AppEditorViewsFlat_enterToBlock__ (t: *c.__AppEditorViewsFlat__) callconv(.c) void { + var last_text: []u8 = ""; + if (t.line.*.text_len > 0) last_text = t.line.*.text[0 .. t.line.*.text_len]; + const last_indent = c.__TextAscii_countIndent__(last_text.ptr, last_text.len, 1); + while(__AppEditorViewsFlat_goToNextLine__(t)) { + var new_text: []u8 = ""; + if (t.line.*.text_len > 0) new_text = t.line.*.text[0 .. t.line.*.text_len]; + const new_indent = c.__TextAscii_countIndent__(new_text.ptr, new_text.len, 1); + if ( true + // line not empty + and new_text.len > new_indent + and c.__TextAscii_isVisible__(new_text[new_indent]) + and new_indent != last_indent + ) { + break; + } + } + __AppEditorViewsFlat_moveCursorToStartOfLine__(t); + } + // # __AppEditorViewsFlat_externalCopy__ + fn __AppEditorViewsFlat_externalCopy__(t: *c.__AppEditorViewsFlat__) !bool { + const path = &c.__app__.editor.__AppEditor_pathToClipboard__[0]; + const path_len = c.__app__.editor.__AppEditor_pathToClipboard_len__; + + var ok: bool = true; + if (t.cutted.count == 0) { + try __AppEditorViewsFlat_duplicateLine__(t); + try __AppEditorViewsFlat_cutLine__(t); + } + __AppEditor_changeStatus__("saving ..."); + if (c.__AppEditorListOfLine_writeToFile__( &t.cutted, path, path_len ) ) { + // print "saved to {clipboard}" + var buffer: [1024]u8 = undefined; + var writed: usize = 0; + writed += __zig_writeToBuffer__(&buffer[writed], "clipboard saved to "); + c.__Mem_copy__(&buffer[writed], path, path_len); + writed += path_len; + __AppEditor_changeStatus__(buffer[0..writed]); + } else { + ok = false; + // print "NOT saved to {clipboard}" + var buffer: [1024]u8 = undefined; + var writed: usize = 0; + writed += __zig_writeToBuffer__(&buffer[writed], "clipboard NOT saved to "); + c.__Mem_copy__(&buffer[writed], path, path_len); + writed += path_len; + __AppEditor_changeStatus__(buffer[0..writed]); + } + + t.need_redraw = false; + return ok; + } + // # __AppEditorViewsFlat_externalPaste__ + fn __AppEditorViewsFlat_externalPaste__(t: *c.__AppEditorViewsFlat__) !void { + t.__AppEditorViewsFlat_autoSpace__ = false; + var ok: bool = true; + // read file + const path = c.__app__.editor.__AppEditor_pathToClipboard__; + const path_len = c.__app__.editor.__AppEditor_pathToClipboard_len__; + var file: c.__OsFileHandle__ = undefined; + if (c.__OsFile_open__(&file, &path[0], path_len)) { + const file_size: usize = c.__OsFile_getSize__(file); + var file_data: [*]u8 = undefined; + if (c.__OsMem_allocAny__(&file_data, file_size)) { + if (c.__OsFile_readToBuffer__(file, file_data, file_size, 0)) { + // paste + const line = t.line; + try __AppEditorViewsFlat_addPrevLine__(t); + for (file_data[0..file_size]) |rune| { // parse lines + switch (rune) { + 13 => {}, + 10 => { + try __AppEditorViewsFlat_addNextLine__(t); + }, + else => { + try __AppEditorViewsFlat_insertSymbol__(t, rune); + }, + } + if (!ok) break; + } + if (ok) { + t.line = line; + t.need_redraw = true; + } + } else { + ok = false; + } + + c.__OsMem_freeAny__(file_data); + } else { + ok = false; + } + } else { + ok = false; + } + if (!ok) { // print error + c.__Terminal_resetColors__(&c.__app__.terminal); + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_notification__, c.__AppEditorTheme_notification__.len); + + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, 0); + _=__writeTextToWriteFnVoid__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, "file ~/clipboard.tmp not reedable."); + + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, 1); + _=__writeTextToWriteFnVoid__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, path[0..path_len]); + + c.__Terminal_resetColors__(&c.__app__.terminal); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_to_end_line__, 0); + } + t.__AppEditorViewsFlat_autoSpace__ = true; + if (!ok) return error.Unexpected; + } + // # __AppEditorViewsFlat_findNextAndDraw__ + fn __AppEditorViewsFlat_findNextAndDraw__(t: *c.__AppEditorViewsFlat__) !void { + try __AppEditorViewsFlat_findNext__(t); + t.need_redraw = true; + t.need_draw_line_num = true; + } + // # __AppEditorViewsFlat_findNext__ + fn __AppEditorViewsFlat_findNext__( + t: *c.__AppEditorViewsFlat__ + ) !void { + const finding_text: []const u8 = __AppEditorViewsFind_get__(&c.__app__.editor.views.find) orelse return; + if (finding_text.len > 0){ + var finded: bool = false; + if (t.line.*.text_len > 0) { // try find on current line + const text = t.line.*.text[0 .. t.line.*.text_len]; + if (t.symbol < text.len) { + const start_find_pos: usize = t.symbol + 1; + const find_data: [*]const u8 = text.ptr[start_find_pos..]; + const find_data_len: usize = text.len - (start_find_pos); + var pos: usize = 0; + if (find_data_len >= finding_text.len and c.__Mem_findFast__(&pos, find_data, find_data_len, finding_text.ptr, finding_text.len)){ + t.symbol += pos + 1; + finded = true; + } + } + } + if (finded == false) { // find on next lines + var current: *c.__MemListLink__ = &t.line.*.link; + while (true) { + if (current == t.lines.last) break; + + if (current.next) |nl| { + current = nl; + } + const line: *c.__AppEditorLine__ = @fieldParentPtr("link", current); + if (line.text_len > 0) { + var pos: usize = 0; + if (line.text_len >= finding_text.len and c.__Mem_findFast__(&pos, line.text[0..].ptr, line.text_len, finding_text.ptr, finding_text.len)) { + t.line = line; + t.offset.y = (c.__app__.terminal.output.size.y >> 1) + (c.__app__.terminal.output.size.y >> 3); + t.symbol = pos; + __AppEditorViewsFlat_changeOffsetX__(t, pos); + __AppEditorViewsFlat_bakupTextOnCurrentLine__(t); + break; + } + } + } + + } + } + } + // # __AppEditorViewsFlat_findPrevAndDraw__ + fn __AppEditorViewsFlat_findPrevAndDraw__(t: *c.__AppEditorViewsFlat__) !void { + try __AppEditorViewsFlat_findPrev__(t); + t.need_redraw = true; + t.need_draw_line_num = true; + } + // # __AppEditorViewsFlat_findPrev__ + fn __AppEditorViewsFlat_findPrev__(t: *c.__AppEditorViewsFlat__) !void { + const finding_text: []const u8 = __AppEditorViewsFind_get__(&c.__app__.editor.views.find) orelse return; + + find_on_current_line: { + var current_text: []u8 = ""; + if (t.line.*.text_len > 0) { + current_text = t.line.*.text[0 .. t.line.*.text_len]; + } else { + break :find_on_current_line; + } + if (t.symbol > current_text.len) __AppEditorViewsFlat_goToSymbol__(t, current_text.len); + var pos: usize = 0; + if (t.symbol >= finding_text.len and c.__mem_findFastReverse__(&pos, current_text.ptr, t.symbol, finding_text.ptr, finding_text.len)) { + t.symbol = pos; + __AppEditorViewsFlat_changeOffsetX__(t, pos); + __AppEditorViewsFlat_bakupTextOnCurrentLine__(t); + t.need_redraw = true; + t.need_draw_line_num = true; + return; + } else { + break :find_on_current_line; + } + } + + var current = &t.line.*.link; + while (true) { + const prev_link = current.prev orelse break; + current = prev_link; + + var line: *c.__AppEditorLine__ = @fieldParentPtr("link", current); + var line_text: []u8 = ""; + if (line.text_len > 0) { + line_text = line.text[0 .. line.text_len]; + } else { + continue; + } + var pos: usize = 0; + if (line_text.len >= finding_text.len and c.__mem_findFastReverse__(&pos, line_text.ptr, line_text.len, finding_text.ptr, finding_text.len)) { + t.line = line; + t.offset.y = (c.__app__.terminal.output.size.y >> 1) - (c.__app__.terminal.output.size.y >> 3); + __AppEditorViewsFlat_goToStartOfText__(t); + t.symbol = pos; + __AppEditorViewsFlat_changeOffsetX__(t, pos); + break; + } else { + continue; + } + } + __AppEditorViewsFlat_bakupTextOnCurrentLine__(t); + } + // # __AppEditorViewsFlat_fold__ + fn __AppEditorViewsFlat_fold__(t: *c.__AppEditorViewsFlat__) !void { + const vf = &c.__app__.editor.views.folded; + + { // fold (set links in tree) + var blanked_lines: c.__MemList__ = undefined; + c.__MemList_init__(&blanked_lines); + + const tree_root = &vf.lines; + var current: *c.__MemTree__ = tree_root; + while (t.lines.count > 0) { + const next_line_link: *c.__MemListLink__ = t.lines.first.?; // flat link. not null. garanty by count > 0 + c.__MemList_pop__(&t.lines, next_line_link); + const next_line: *c.__AppEditorLine__ = @fieldParentPtr("link", next_line_link); + const next_line_tree: *c.__MemTree__ = &next_line.tree; + var next_text: []u8 = ""; + if (next_line.text_len > 0) next_text = next_line.text[0 .. next_line.text_len]; + const next_indent: usize = c.__TextAscii_countIndent__(next_text.ptr, next_text.len, 1); + const next_non_indent: usize = c.__TextAscii_countNonIndent__(next_text.ptr, next_text.len); + + if (next_non_indent == 0) { + c.__MemList_pushLast__(&blanked_lines, next_line_link); + } else { + while (current != tree_root) { // findLineWithLessIndent + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", current); + + var line_text: []u8 = ""; + if (line.text_len > 0) line_text = line.text[0 .. line.text_len]; + const non_indent = c.__TextAscii_countNonIndent__(line_text.ptr, line_text.len); + const indent = c.__TextAscii_countIndent__(line_text.ptr, line_text.len, 1); + if (non_indent != 0 and indent < next_indent) break; + + c.__MemTree_getParent__(@ptrCast(¤t), current); // current not null - garanty by loop. current is child of tree_root + } + c.__MemTree_pushChild__(current, next_line_tree); + current = next_line_tree; + + while (blanked_lines.count > 0) { + const blank_link: *c.__MemListLink__ = blanked_lines.first.?; + c.__MemList_pop__(&blanked_lines, blank_link); + const blank_line: *c.__AppEditorLine__ = @fieldParentPtr("link", blank_link); + c.__MemTree_pushPrev__(current, &blank_line.tree); + } + } + } + + while (blanked_lines.count > 0) { + const blank_link: *c.__MemListLink__ = blanked_lines.first.?; // non nil - garanty by count > 0 + c.__MemList_pop__(&blanked_lines, blank_link); + const blank_line: *c.__AppEditorLine__ = @fieldParentPtr("link", blank_link); + c.__MemTree_pushChild__(tree_root, &blank_line.tree); + } + } + + { // changeView + vf.line = t.line; + vf.offset = t.offset; + vf.symbol = t.symbol; + vf.marked_line = t.marked_line; + vf.need_redraw = true; + try __AppEditorViewsFolded_setAsView__(vf); + } + } + // # __AppEditorViewsFlat_goToEndOfLine__ + fn __AppEditorViewsFlat_goToEndOfLine__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + t.symbol = t.line.*.text_len; + __AppEditorViewsFlat_changeOffsetX__(t, t.symbol); + t.need_redraw = true; + } + // # __AppEditorViewsFlat_goToFirstLine__ + fn __AppEditorViewsFlat_goToFirstLine__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + const link = t.lines.first orelse unreachable; + t.line = @fieldParentPtr("link", link); + t.goToStartOfText(); + t.offset.y = (c.__app__.terminal.output.size.y >> 1) - (c.__app__.terminal.output.size.y >> 2); + t.need_redraw = true; + t.bakup(); + } + // # __AppEditorViewsFlat_goToLastLine__ + fn __AppEditorViewsFlat_goToLastLine__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + const link = t.lines.last orelse unreachable; + + t.line = @fieldParentPtr("link", link); + t.goToStartOfText(); + t.offset.y = (c.__app__.terminal.output.size.y >> 1) + (c.__app__.terminal.output.size.y >> 2); + t.need_redraw = true; + t.bakup(); + } + // # __AppEditorViewsFlat_goToLineFromNumber__ + fn __AppEditorViewsFlat_goToLineFromNumber__(t: *c.__AppEditorViewsFlat__, _num: usize) callconv(.c) void { + if (_num == 0) return; + __AppEditorViewsFlat_goToRoot__(t); + var pos: usize = 1; + while (pos < _num and __AppEditorViewsFlat_goToNextLine__(t)) { + pos += 1; + } + var indent: usize = 0; + const text_len = t.line.*.text_len; + if (text_len > 0) { + const text = &t.line.*.text[0]; + indent = c.__TextAscii_countIndent__(text, text_len, 1); + } + __AppEditorViewsFlat_goToSymbol__(t, indent); + t.offset.y = c.__app__.terminal.output.size.y >> 1; + __AppEditorViewsFlat_bakupTextOnCurrentLine__(t); + t.need_redraw = true; + } + // # __AppEditorViewsFlat_goToMarked__ + fn __AppEditorViewsFlat_goToMarked__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + if (t.marked_line) |mark| { + t.line = mark; + t.need_redraw = true; + __AppEditorViewsFlat_bakupTextOnCurrentLine__(t); + } + } + // # __AppEditorViewsFlat_goToNextLine__ + fn __AppEditorViewsFlat_goToNextLine__(t: *c.__AppEditorViewsFlat__) callconv(.c) bool { + var ok: bool = true; + const last_line: *c.__AppEditorLine__ = t.line; + if (@intFromPtr(t.line.*.link.next) != @intFromPtr(c.NULL)) { + const next_link: *c.__MemListLink__ = @ptrCast(t.line.*.link.next); + + // set current line to prev line + const next_line: *c.__AppEditorLine__ = @fieldParentPtr("link", next_link); + t.line = next_line; + __AppEditorViewsFlat_bakupTextOnCurrentLine__(t); + t.need_redraw = true; + if (t.offset.y < c.__app__.terminal.output.size.y - 1) t.offset.y += 1; + + // if cursor on start of text - move cursor to new start of text + var last_text: []u8 = ""; + if (last_line.text_len > 0) { + last_text = last_line.text[0 .. last_line.text_len]; + } + if (t.symbol == c.__TextAscii_countIndent__(last_text.ptr, last_text.len, 1)) { + var next_text: []u8 = ""; + if (next_line.text_len > 0) next_text = next_line.text[0 .. next_line.text_len]; + __AppEditorViewsFlat_goToSymbol__(t, c.__TextAscii_countIndent__(next_text.ptr, next_text.len, 1)); + } + + } else { + ok = false; + } + + return ok; + } + // # __AppEditorViewsFlat_goToNextSymbol__ + fn __AppEditorViewsFlat_goToNextSymbol__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + if (t.symbol < t.line.*.text_len) { + // inc symbol + if (t.symbol >= c.__AppEditorLineLen_max__ - 1) return; // todo rewrite lines to use allocator for lines. and remove this check. + t.symbol += 1; + t.need_redraw = true; + + __AppEditorViewsFlat_changeOffsetX__(t, t.symbol); + } + } + // # __AppEditorViewsFlat_goToPrevLine__ + fn __AppEditorViewsFlat_goToPrevLine__(t: *c.__AppEditorViewsFlat__) callconv(.c) bool { + var ok: bool = true; + const last_line = t.line; + if (@intFromPtr(t.line.*.link.prev) != @intFromPtr(c.NULL)) { + const prev_link: *c.__MemListLink__ = @ptrCast(t.line.*.link.prev); + + // set current line to prev line + const prev_line: *c.__AppEditorLine__ = @fieldParentPtr("link", prev_link); + t.need_redraw = true; + t.line = prev_line; + if (t.offset.y > 5) { + t.offset.y -= 1; + } + __AppEditorViewsFlat_bakupTextOnCurrentLine__(t); + + // if cursor on start of text - move cursor to new start of text + var last_indent: usize = 0; + if (last_line.*.text_len > 0) { + last_indent = c.__TextAscii_countIndent__(&last_line.*.text[0], last_line.*.text_len, 1); + } + if (t.symbol == last_indent) { + __AppEditorViewsFlat_moveCursorToStartOfLine__(t); + } + } else { + ok = false; + } + return ok; + } + // # __AppEditorViewsFlat_goToPrevSymbol__ + fn __AppEditorViewsFlat_goToPrevSymbol__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + const used = t.line.*.text_len; + + if (t.symbol > used) { + t.symbol = used; + } else if (t.symbol > 0) { + t.symbol -= 1; + } + + __AppEditorViewsFlat_changeOffsetX__(t, t.symbol); + t.need_redraw = true; + } + // # __AppEditorViewsFlat_goToRoot__ + fn __AppEditorViewsFlat_goToRoot__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + const first_line_link: *c.__MemListLink__ = t.lines.first orelse unreachable; + const line: *c.__AppEditorLine__ = @fieldParentPtr("link", first_line_link); + t.line = line; + t.offset.y = 5; + __AppEditorViewsFlat_goToStartOfText__(t); + t.need_redraw = true; + __AppEditorViewsFlat_bakupTextOnCurrentLine__(t); + } + // # __AppEditorViewsFlat_goToStartOfLine__ + fn __AppEditorViewsFlat_goToStartOfLine__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + t.symbol = 0; + t.offset.x = 0; + t.need_redraw = true; + } + // # __AppEditorViewsFlat_goToStartOfText__ + fn __AppEditorViewsFlat_goToStartOfText__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + var text: []u8 = ""; + if (t.line.*.text_len > 0) text = t.line.*.text[0 .. t.line.*.text_len]; + const indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + __AppEditorViewsFlat_goToSymbol__(t, indent); + } + // # __AppEditorViewsFlat_goToSymbol__ + fn __AppEditorViewsFlat_goToSymbol__(t: *c.__AppEditorViewsFlat__, pos: usize) callconv(.c) void { + t.symbol = pos; + __AppEditorViewsFlat_changeOffsetX__(t, t.symbol); + t.need_redraw = true; + } + // # __AppEditorViewsFlat_init__ + fn __AppEditorViewsFlat_init__(t: *c.__AppEditorViewsFlat__) !void { + c.__MemList_init__(&t.lines); + c.__MemList_init__(&t.cutted); + c.__AppEditorLine_init__(&t.bakup_line); + t.need_redraw = true; + t.need_draw_line_num = true; + t.marked_line = null; + t.offset = .{ .x = 0, .y = 3 }; + t.symbol = 0; + t.__AppEditorViewsFlat_autoSpace__ = true; + // t.line - is setted by outside + } + // # __AppEditorViewsFlat_insertFindedText__ + fn __AppEditorViewsFlat_insertFindedText__(t: *c.__AppEditorViewsFlat__) !void { + const text: []const u8 = __AppEditorViewsFind_get__(&c.__app__.editor.views.find) orelse return; + for (text) |rune| { + __AppEditorViewsFlat_insertSymbol__(t, rune) catch {}; + } + t.need_redraw = true; + } + // # __AppEditorViewsFlat_insertSymbol__ + fn __AppEditorViewsFlat_insertSymbol__(t: *c.__AppEditorViewsFlat__, rune: u8) !void { + if (t.symbol > t.line.*.text_len) __AppEditorViewsFlat_goToSymbol__(t, t.line.*.text_len); + if (t.line.*.text_len < c.__AppEditorLineLen_max__) { + c.__Buffer_push__(&t.line.*.text[0], &t.line.*.text_len, t.symbol, rune); + __AppEditorViewsFlat_goToNextSymbol__(t); + } + t.need_redraw = true; + } + // # __AppEditorViewsFlat_joinLines__ + fn __AppEditorViewsFlat_joinLines__(t: *c.__AppEditorViewsFlat__) !void { + //var ok: bool = true + + if (@intFromPtr(t.line.*.link.prev) != @intFromPtr(c.NULL)) { + const prev_link: *c.__MemListLink__ = t.line.*.link.prev; + const prev_line: *c.__AppEditorLine__ = @fieldParentPtr("link", prev_link); + + if (t.line.*.text_len > 0) { + if (prev_line.text_len > 0) { + // count non indent text len + const prev_indent: usize = c.__Text_countIndent__(&prev_line.text[0], prev_line.text_len, 1); + const prev_non_indent: usize = prev_line.text_len - prev_indent; + + if (prev_non_indent > 0) { + const line_indent: usize = c.__Text_countIndent__(&t.line.*.text[0], t.line.*.text_len, 1); + const line_non_indent: usize = t.line.*.text_len - line_indent; + + if (line_non_indent > 0) { + // copy text + const space_len: usize = @as(usize, c.__AppEditorLineLen_max__) - prev_line.text_len; // TODO use allocator for realocating. Maybe create virtual lines for too big text? + if (space_len > line_non_indent) { // size checked + const prev_len: usize = prev_line.text_len; + c.__Mem_copy__(&prev_line.text[prev_line.text_len], &t.line.*.text[line_indent], line_non_indent); + prev_line.text_len += line_non_indent; + + // delete line + c.__MemList_pop__(&t.lines, &t.line.*.link); + c.__AppEditorLine_free__(t.line); + + // replace to prev line + t.line = prev_line; + __AppEditorViewsFlat_goToSymbol__(t, prev_len); + } else { + __AppEditor_changeStatus__("line is too big"); + } + } else { // current line text is nil (only spaces) + // remove current line + c.__MemList_pop__(&t.lines, &t.line.*.link); + c.__AppEditorLine_free__(t.line); + + // replace to prev line + t.line = prev_line; + __AppEditorViewsFlat_goToSymbol__(t, prev_line.text_len); + } + } else { // prev_text is nil + c.__MemList_pop__(&t.lines, prev_link); + c.__AppEditorLine_free__(prev_line); + } + } else { + c.__MemList_pop__(&t.lines, prev_link); + c.__AppEditorLine_free__(prev_line); + } + } else { + // delete current line + c.__MemList_pop__(&t.lines, &t.line.*.link); + c.__AppEditorLine_free__(t.line); + + // replace to prev line + t.line = prev_line; + __AppEditorViewsFlat_goToSymbol__(t, prev_line.text_len); + } + } + t.need_redraw = true; + } + // # __AppEditorViewsFlat_jumpToOutOfBlock__ + fn __AppEditorViewsFlat_jumpToOutOfBlock__ (t: *c.__AppEditorViewsFlat__) callconv(.c) void { + var last_text: []u8 = ""; + if (t.line.*.text_len > 0) last_text = t.line.*.text[0 .. t.line.*.text_len]; + const last_indent = c.__TextAscii_countIndent__(last_text.ptr, last_text.len, 1); + while(__AppEditorViewsFlat_goToPrevLine__(t)) { + var new_text: []u8 = ""; + if (t.line.*.text_len > 0) new_text = t.line.*.text[0 .. t.line.*.text_len]; + const new_indent = c.__TextAscii_countIndent__(new_text.ptr, new_text.len, 1); + if ( true + // line not empty + and new_text.len > new_indent + and c.__TextAscii_isVisible__(new_text[new_indent]) + and new_indent < last_indent + ) { + break; + } + } + __AppEditorViewsFlat_moveCursorToStartOfLine__(t); + } + // # __AppEditorViewsFlat_manyIndent__ + fn __AppEditorViewsFlat_manyIndent__(t: *c.__AppEditorViewsFlat__) !void { // todo rename to __AppEditorFlat_lessIndent__ + var text: []u8 = ""; + if (t.line.text_len > 0) text = t.line.text[0 .. t.line.text_len]; + const indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + if (indent < 4) return; + if (c.__AppEditorLine_setIndent__(t.line, indent - 4) == false) return error.Unexpected; + t.need_redraw = true; + } + // # __AppEditorViewsFlat_markThisLine__ + fn __AppEditorViewsFlat_markThisLine__(t: *c.__AppEditorViewsFlat__) !void { + t.marked_line = t.line; + __AppEditor_changeStatus__("marked."); + } + // # __AppEditorViewsFlat_moveBlockToMarkedOut__ + fn __AppEditorViewsFlat_moveBlockToMarkedOut__(t: *c.__AppEditorViewsFlat__) !void { + var ok: bool = true; + const marked = t.marked_line orelse return; + if (marked == t.line) return; + + // move + var next_link: *c.__MemListLink__ = undefined; { // select next_link + const current_link = &t.line.*.link; + if (current_link.next) |_next_link| { + next_link = _next_link; + } else if (current_link.prev) |prev_link| { + next_link = prev_link; + } else { + ok = false; + } + } + if (ok) { + const line_link = &t.line.*.link; + c.__MemList_pop__(&t.lines, line_link); + c.__MemList_pushBefore__(&t.lines, &marked.*.link, line_link); + const line: *c.__AppEditorLine__ = @fieldParentPtr("link", next_link); + t.line = line; + t.need_redraw = true; + __AppEditor_changeStatus__("moved to marked."); + + } + if (!ok) return error.Unexpected; + } + // # __AppEditorViewsFlat_moveCursorToStartOfLine__ + fn __AppEditorViewsFlat_moveCursorToStartOfLine__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + var indent: usize = 0; + if (t.line.*.text.len > 0) {indent = c.__TextAscii_countIndent__(&t.line.*.text[0], t.line.*.text_len, 1);} + __AppEditorViewsFlat_goToSymbol__(t, indent); + } + // # __AppEditorViewsFlat_moveFoldedBlockToMarkedIn__ + fn __AppEditorViewsFlat_moveFoldedBlockToMarkedIn__(t: *c.__AppEditorViewsFlat__) !void { + const vf = &c.__app__.editor.views.folded; + try __AppEditorViewsFlat_fold__(t); + try __AppEditorViewsFolded_moveBlockToMarkedInWithAddIndent__(vf); + try __AppEditorViewsFolded_unFold__(vf); + } + // # __AppEditorViewsFlat_onKey__ + fn __AppEditorViewsFlat_onKey__(ctx: *c.__AppEditorViewsFlat__, cik: c.__ConsoleAnsiInputKey__) callconv(.c) void { + __AppEditorViewsFlat_onkeyWrap__(ctx, cik) catch {}; + } + // # __AppEditorViewsFlat_onkeyWrap__ + fn __AppEditorViewsFlat_onkeyWrap__(ctx: ?*anyopaque, cik: c.__ConsoleAnsiInputKey__) !void { + const t: *c.__AppEditorViewsFlat__ = @alignCast(@ptrCast(ctx)); + + switch (cik) { + c.__ConsoleAnsiInputKey_ctrl_q__ => {c.__AppEditor_stop__(&c.__app__.editor);}, + c.__ConsoleAnsiInputKey_ctrl_s__ => {__AppEditorViewsFlat_save__(t) catch {};}, + // change view + c.__ConsoleAnsiInputKey_alt_e__ => {try __AppEditorViewsFlat_easyMotionV__(t);}, + c.__ConsoleAnsiInputKey_alt_q__ => {try __AppEditorViewsFlat_easyMotionH__(t);}, + c.__ConsoleAnsiInputKey_ctrl_e__ => {try __AppEditorViewsFlat_fold__(t);}, + c.__ConsoleAnsiInputKey_ctrl_f__ => {__AppEditorViewsFlat_toFind__(t);}, + c.__ConsoleAnsiInputKey_ctrl_g__ => {__AppEditorViewsFlat_toGoTo__(t);}, + c.__ConsoleAnsiInputKey_alt_5__ => {__AppEditorViewsFlat_toReplace__(t);}, + // navigation + // blocks + c.__ConsoleAnsiInputKey_escape__ => {__AppEditorViewsFlat_jumpToOutOfBlock__(t);}, + c.__ConsoleAnsiInputKey_tab__ => {__AppEditorViewsFlat_enterToBlock__(t);}, + c.__ConsoleAnsiInputKey_alt_0__ => {try __AppEditorViewsFlat_moveBlockToMarkedOut__(t);}, + c.__ConsoleAnsiInputKey_alt_9__ => {__AppEditorViewsFlat_moveFoldedBlockToMarkedIn__(t) catch {};}, + // lines + c.__ConsoleAnsiInputKey_up__ => {_=__AppEditorViewsFlat_goToPrevLine__(t);}, + c.__ConsoleAnsiInputKey_down__ => {_=__AppEditorViewsFlat_goToNextLine__(t);}, + c.__ConsoleAnsiInputKey_page_up__ => {__AppEditorViewsFlat_pageUp__(t);}, + c.__ConsoleAnsiInputKey_page_down__ => {__AppEditorViewsFlat_pageDown__(t);}, + c.__ConsoleAnsiInputKey_alt_g__ => {__AppEditorViewsFlat_goToMarked__(t);}, + c.__ConsoleAnsiInputKey_alt_m__ => {try __AppEditorViewsFlat_markThisLine__(t);}, + // text + c.__ConsoleAnsiInputKey_left__ => {__AppEditorViewsFlat_goToPrevSymbol__(t);}, + c.__ConsoleAnsiInputKey_right__ => {__AppEditorViewsFlat_goToNextSymbol__(t);}, + c.__ConsoleAnsiInputKey_ctrl_up__ => {__AppEditorViewsFlat_ctrlUp__(t);}, + c.__ConsoleAnsiInputKey_ctrl_down__ => {__AppEditorViewsFlat_ctrlDown__(t);}, + c.__ConsoleAnsiInputKey_ctrl_shift_left__ => {__AppEditorViewsFlat_ctrlShiftLeft__(t);}, + c.__ConsoleAnsiInputKey_ctrl_shift_right__ => {__AppEditorViewsFlat_ctrlShiftRight__(t);}, + c.__ConsoleAnsiInputKey_ctrl_left__ => {__AppEditorViewsFlat_ctrlLeft__(t);}, + c.__ConsoleAnsiInputKey_ctrl_right__ => {__AppEditorViewsFlat_ctrlRight__(t);}, + c.__ConsoleAnsiInputKey_end__ => {__AppEditorViewsFlat_goToEndOfLine__(t);}, + c.__ConsoleAnsiInputKey_home__ => {__AppEditorViewsFlat_goToStartOfLine__(t);}, + // edit + // blocks + // lines + c.__ConsoleAnsiInputKey_alt_up__ => {try __AppEditorViewsFlat_swapWithUpper__(t);}, + c.__ConsoleAnsiInputKey_alt_down__ => {try __AppEditorViewsFlat_swapWithBottom__(t);}, + c.__ConsoleAnsiInputKey_shift_delete__ => {__AppEditorViewsFlat_clearLine__(t);}, + c.__ConsoleAnsiInputKey_ctrl_d__ => {try __AppEditorViewsFlat_duplicateLine__(t);}, + c.__ConsoleAnsiInputKey_enter__ => {__AppEditorViewsFlat_divideLine__(t) catch {};}, + c.__ConsoleAnsiInputKey_ctrl_j__ => {try __AppEditorViewsFlat_joinLines__(t);}, + c.__ConsoleAnsiInputKey_ctrl_enter__ => {try __AppEditorViewsFlat_joinLines__(t);}, + // text + c.__ConsoleAnsiInputKey_alt_6__ => {__AppEditorViewsFlat_replace__(t) catch {};}, + c.__ConsoleAnsiInputKey_alt_1__ => {try __AppEditorViewsFlat_copyWordToFind__(t);}, + c.__ConsoleAnsiInputKey_alt_2__ => {try __AppEditorViewsFlat_findPrevAndDraw__(t);}, + c.__ConsoleAnsiInputKey_alt_3__ => {try __AppEditorViewsFlat_findNextAndDraw__(t);}, + c.__ConsoleAnsiInputKey_alt_4__ => {try __AppEditorViewsFlat_insertFindedText__(t);}, + c.__ConsoleAnsiInputKey_delete__ => {__AppEditorViewsFlat_deleteSymbol__(t);}, + c.__ConsoleAnsiInputKey_ctrl_z__ => {try __AppEditorViewsFlat_restoreTextOnCurrentLine__(t);}, + c.__ConsoleAnsiInputKey_ctrl_w__ => {try __AppEditorViewsFlat_deleteWord__(t);}, + //c.__ConsoleAnsiInputKey_ctrl_t__ => {__AppEditorViewsFlat_insertSymbol__(t, '\t') catch {};}, + c.__ConsoleAnsiInputKey_back_space__ => {try __AppEditorViewsFlat_deletePrevSymbol__(t);}, + c.__ConsoleAnsiInputKey_ctrl_bs__ => {try __AppEditorViewsFlat_deletePrevSymbol__(t);}, + // copy paste + c.__ConsoleAnsiInputKey_ctrl_x__ => {try __AppEditorViewsFlat_cutLine__(t);}, + c.__ConsoleAnsiInputKey_ctrl_c__ => {try __AppEditorViewsFlat_duplicateLineAndCut__(t);}, + c.__ConsoleAnsiInputKey_ctrl_v__ => {__AppEditorViewsFlat_pasteLine__(t) catch {};}, + c.__ConsoleAnsiInputKey_alt_z__ => {try __AppEditorViewsFlat_deleteCutted__(t);}, + c.__ConsoleAnsiInputKey_alt_b__ => { + t.__AppEditorViewsFlat_autoSpace__ = !t.__AppEditorViewsFlat_autoSpace__; + if (t.__AppEditorViewsFlat_autoSpace__) { + __AppEditor_changeStatus__("auto space enabled"); + } else { + __AppEditor_changeStatus__("auto space disabled"); + } + }, + // external + c.__ConsoleAnsiInputKey_alt_c__ => {_=__AppEditorViewsFlat_externalCopy__(t) catch {};}, + c.__ConsoleAnsiInputKey_alt_v__ => {__AppEditorViewsFlat_externalPaste__(t) catch {};}, + c.__ConsoleAnsiInputKey_ctrl_t__ => __AppEditorViewsFlat_ctrl_t__(t), + else => { + if (cik > 255) return; + const byte: u8 = @truncate(cik); + __AppEditorViewsFlat_insertSymbol__(t, byte) catch {}; + t.need_redraw = true; + }, + } + } + // # __AppEditorViewsFlat_pageDown__ + fn __AppEditorViewsFlat_pageDown__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + var pos: usize = 0; + while (pos < 10) : (pos += 1) { + if (!__AppEditorViewsFlat_goToNextLine__(t)) break; + } + } + // # __AppEditorViewsFlat_pageUp__ + fn __AppEditorViewsFlat_pageUp__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + var pos: usize = 0; + while (pos < 10) : (pos += 1) { + if (!__AppEditorViewsFlat_goToPrevLine__(t)) break; + } + } + // # __AppEditorViewsFlat_pasteLine__ + fn __AppEditorViewsFlat_pasteLine__(t: *c.__AppEditorViewsFlat__) !void { + if (t.cutted.count == 0) return; + + const indent = count_indent: { + var text: []u8 = ""; + if (t.line.*.text_len > 0) text = t.line.*.text[0 .. t.line.*.text_len]; + const current_indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + + const prev_line_link: *c.__MemListLink__ = t.line.*.link.prev orelse break :count_indent current_indent; + const prev_line: *c.__AppEditorLine__ = @fieldParentPtr("link", prev_line_link); + var prev_text: []u8 = ""; + if (prev_line.text_len > 0) prev_text = prev_line.text[0 .. prev_line.text_len]; + const prev_indent = c.__TextAscii_countIndent__(prev_text.ptr, prev_text.len, 1); + + break :count_indent @max(current_indent, prev_indent); + }; + const link: *c.__MemListLink__ = t.cutted.last orelse unreachable; + c.__MemList_pop__(&t.cutted, link); + c.__MemList_pushBefore__(&t.lines, &t.line.*.link, link); + t.offset.y += 1; + _=__AppEditorViewsFlat_goToPrevLine__(t); + if (c.__AppEditorLine_setIndent__(t.line, indent) == false) return error.Unexpected; + t.need_redraw = true; + } + // # __AppEditorViewsFlat_replace__ + fn __AppEditorViewsFlat_replace__(t: *c.__AppEditorViewsFlat__) !void { + const find_line = &c.__app__.editor.views.find.line; + const replace_line = &c.__app__.editor.views.replace.line; + const current_line = t.line; + const check_len = find_line.text_len; + if (true + and current_line.*.text_len - t.symbol >= check_len + and c.__Mem_isEql__(¤t_line.*.text[t.symbol], &find_line.text[0], find_line.text_len) + ) { + // delete old text + var pos: usize = 0; + while (pos < check_len):(pos += 1) { + __AppEditorViewsFlat_deleteSymbol__(t); + } + // insert new_text + pos = 0; + while (pos < replace_line.text_len):(pos += 1) { + const rune = replace_line.text[pos]; + __AppEditorViewsFlat_insertSymbol__(t, rune) catch {}; + } + t.need_redraw = true; + } + } + // # __AppEditorViewsFlat_restoreTextOnCurrentLine__ + fn __AppEditorViewsFlat_restoreTextOnCurrentLine__(t: *c.__AppEditorViewsFlat__) !void { + var text: []u8 = ""; + if (t.bakup_line.text_len > 0) text = t.bakup_line.text[0 .. t.bakup_line.text_len]; + c.__AppEditorLine_setText__(t.line, text.ptr, text.len); + t.need_redraw = true; + } + // # __AppEditorViewsFlat_save__ + fn __AppEditorViewsFlat_save__(t: *c.__AppEditorViewsFlat__) !void { + var ok: bool = true; + __AppEditor_changeStatus__("saving ..."); + ok = c.__AppEditorListOfLine_writeToFile__( + &t.lines, + &c.__app__.editor.__AppEditor_fileName__[0], + c.__app__.editor.__AppEditor_fileName_len__ + ); + if (ok) { + __AppEditor_changeStatus__("saved ..."); + } else { + __AppEditor_changeStatus__("NOT saved ..."); + ok = false; + } + t.need_redraw = false; + + if (!ok) return error.Unexpected; + // return ok; + } + // # __AppEditorViewsFlat_setAsView__ + fn __AppEditorViewsFlat_setAsView__(t: *c.__AppEditorViewsFlat__) !void { + c.__app__.editor.do_ptr = @ptrCast(&__AppEditorViewsFlat_do__); + c.__app__.editor.onKey_ptr = @ptrCast(&__AppEditorViewsFlat_onKey__); + c.__app__.editor.current_ctx = t; + c.__app__.editor.current_vtable = &c.__AppEditorViewsVtable_flat__; + __AppEditorViewsFlat_bakupTextOnCurrentLine__(t); + t.need_redraw = true; + __AppEditor_changeStatus__("Flat mode."); + __AppEditorViewsFlat_cursorMoveToCurrent__(t) catch {}; + } + // # __AppEditorViewsFlat_swapWithBottom__ + fn __AppEditorViewsFlat_swapWithBottom__(t: *c.__AppEditorViewsFlat__) !void { + try __AppEditorViewsFlat_cutLine__(t); + var text: []u8 = ""; + if (t.line.*.text_len > 0) text = t.line.*.text[0 .. t.line.*.text_len]; + const indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + + const link: *c.__MemListLink__ = t.cutted.last orelse unreachable; + c.__MemList_pop__(&t.cutted, link); + c.__MemList_pushAfter__(&t.lines, &t.line.*.link, link); + _=__AppEditorViewsFlat_goToNextLine__(t); + if (c.__AppEditorLine_setIndent__(t.line, indent) == false) return error.Unexpected; + t.need_redraw = true; + } + // # __AppEditorViewsFlat_swapWithUpper__ + fn __AppEditorViewsFlat_swapWithUpper__(t: *c.__AppEditorViewsFlat__) !void { + if (t.line.*.link.next == null) { + try __AppEditorViewsFlat_cutLine__(t); + try __AppEditorViewsFlat_pasteLine__(t); + } else { + try __AppEditorViewsFlat_cutLine__(t); + _=__AppEditorViewsFlat_goToPrevLine__(t); + try __AppEditorViewsFlat_pasteLine__(t); + } + t.need_redraw = true; + } + // # __AppEditorViewsFlat_toFind__ + fn __AppEditorViewsFlat_toFind__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + __AppEditorViewsFind_setAsView__(&c.__app__.editor.views.find, t, &c.__AppEditorViewsVtable_flat__); + } + // # __AppEditorViewsFlat_toGoTo__ + fn __AppEditorViewsFlat_toGoTo__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { __zig_fuck__(t); + __AppEditorViewsGoToLine_setAsView__(&c.__app__.editor.views.go_to_line, t, &c.__AppEditorViewsVtable_flat__); + } + // # __AppEditorViewsFlat_toReplace__ + fn __AppEditorViewsFlat_toReplace__(t: *c.__AppEditorViewsFlat__) callconv(.c) void { + __AppEditorViewsReplace_setAsView__(&c.__app__.editor.views.replace, t, &c.__AppEditorViewsVtable_flat__); + } + // # __AppEditorViewsFoldedVtable_countLineNum__ + fn __AppEditorViewsFoldedVtable_countLineNum__(model: *c.__AppEditorViewsFolded__) callconv(.c) usize { + const view = __AppEditorViewsFoldedVtable_getModel__(model); + return __AppEditorViewsFolded_countLineNum__(view); + } + // # __AppEditorViewsFoldedVtable_getModel__ + fn __AppEditorViewsFoldedVtable_getModel__(ptr: *anyopaque) callconv(.c) *c.__AppEditorViewsFolded__ { + const ret_ptr: *c.__AppEditorViewsFolded__ = @ptrFromInt(@intFromPtr(ptr)); + return ret_ptr; + } + // # __AppEditorViewsFoldedVtable_getOffsetX__ + fn __AppEditorViewsFoldedVtable_getOffsetX__(model: *anyopaque) callconv(.c) usize { + const view = __AppEditorViewsFoldedVtable_getModel__(model); + return view.offset.x; + } + // # __AppEditorViewsFoldedVtable_getOffsetY__ + fn __AppEditorViewsFoldedVtable_getOffsetY__(model: *anyopaque) callconv(.c) usize { + const view = __AppEditorViewsFoldedVtable_getModel__(model); + return view.offset.y; + } + // # __AppEditorViewsFoldedVtable_getSymbolPosX__ + fn __AppEditorViewsFoldedVtable_getSymbolPosX__(model: *c.__AppEditorViewsFolded__) callconv(.c) usize { + const view = __AppEditorViewsFoldedVtable_getModel__(model); + return view.symbol; + } + // # __AppEditorViewsFoldedVtable_goToLineFromNumber__ + fn __AppEditorViewsFoldedVtable_goToLineFromNumber__(ctx: *c.__AppEditorViewsFolded__, _num: usize) callconv(.c) void { + const view = __AppEditorViewsFoldedVtable_getModel__(ctx); + return __AppEditorViewsFolded_goToLineFromNumber__(view, _num); + } + // # __AppEditorViewsFoldedVtable_goToNextLine__ + fn __AppEditorViewsFoldedVtable_goToNextLine__(model: *anyopaque) callconv(.c) void { + const view = __AppEditorViewsFoldedVtable_getModel__(model); + __AppEditorViewsFolded_goToNextLine__(view); + } + // # __AppEditorViewsFoldedVtable_goToPrevLine__ + fn __AppEditorViewsFoldedVtable_goToPrevLine__(model: *anyopaque) callconv(.c) void { + const view = __AppEditorViewsFoldedVtable_getModel__(model); + __AppEditorViewsFolded_goToPrevLine__(view); + } + // # __AppEditorViewsFoldedVtable_goToSymbolPosX__ + fn __AppEditorViewsFoldedVtable_goToSymbolPosX__(model: *anyopaque, pos: usize) callconv(.c) void { + const view = __AppEditorViewsFoldedVtable_getModel__(model); + __AppEditorViewsFolded_goToSymbol__(view, pos); + } + // # __AppEditorViewsFoldedVtable_init__ + fn __AppEditorViewsFoldedVtable_init__(t: *c.__AppEditorViewsVTable__) void { + t.setAsView = @ptrCast(&__AppEditorViewsFoldedVtable_setAsView__); + t.goToPrevLine = @ptrCast(&__AppEditorViewsFoldedVtable_goToPrevLine__); + t.goToNextLine = @ptrCast(&__AppEditorViewsFoldedVtable_goToNextLine__); + t.getOffsetX = @ptrCast(&__AppEditorViewsFoldedVtable_getOffsetX__); + t.getOffsetY = @ptrCast(&__AppEditorViewsFoldedVtable_getOffsetY__); + t.goToSymbolPosX = @ptrCast(&__AppEditorViewsFoldedVtable_goToSymbolPosX__); + t.getSymbolPosX = @ptrCast(&__AppEditorViewsFoldedVtable_getSymbolPosX__); + t.countLineNum = @ptrCast(&__AppEditorViewsFoldedVtable_countLineNum__); + t.goToLineFromNumber = @ptrCast(&__AppEditorViewsFoldedVtable_goToLineFromNumber__); + } + // # __AppEditorViewsFoldedVtable_setAsView__ + fn __AppEditorViewsFoldedVtable_setAsView__(model: *anyopaque) callconv(.c) void { + const view = __AppEditorViewsFoldedVtable_getModel__(model); + __AppEditorViewsFolded_setAsView__(view) catch unreachable; + c.__app__.editor.current_vtable = &c.__AppEditorViewsVtable_folded__; + } + // # __AppEditorViewsFolded_CtrlShiftLeft__ + fn __AppEditorViewsFolded_CtrlShiftLeft__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + const line = t.line; + if (line.*.text_len > 0) { + const indent = c.__TextAscii_countIndent__(&line.*.text[0], line.*.text_len, 1); + if (t.symbol > indent) { + __AppEditorViewsFolded_goToSymbol__(t, indent); + } else { + __AppEditorViewsFolded_goToStartOfLine__(t); + } + t.need_redraw = true; + } + } + // # __AppEditorViewsFolded_CtrlShiftRight__ + fn __AppEditorViewsFolded_CtrlShiftRight__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + const line = t.line; + if (line.*.text_len > 0) { + const indent = c.__TextAscii_countIndent__(&line.*.text[0], line.*.text_len, 1); + if (t.symbol < indent) { + __AppEditorViewsFolded_goToSymbol__(t, indent); + } else { + __AppEditorViewsFolded_goToEndOfLine__(t); + } + t.need_redraw = true; + } + } + // # __AppEditorViewsFolded_Line_GetLastByte__ + fn __AppEditorViewsFolded_Line_GetLastByte__(t: *c.__AppEditorViewsFolded__, line: *c.__AppEditorLine__) callconv(.c) ?u8 { __zig_fuck__(t); + if (line.text_len < 1) return null; + return line.text[line.text_len - 1]; + } + // # __AppEditorViewsFolded_Line_getFirstChildLine__ + fn __AppEditorViewsFolded_Line_getFirstChildLine__(t: *c.__AppEditorViewsFolded__, line: *c.__AppEditorLine__) callconv(.c) ?*c.__AppEditorLine__ { __zig_fuck__(t); + const link: *c.__MemListLink__ = line.tree.childs orelse return null; + const tree: *c.__MemTree__ = @fieldParentPtr("link", link); + return @fieldParentPtr("tree", tree); + } + // # __AppEditorViewsFolded_Line_getFirstSibling__ + fn __AppEditorViewsFolded_Line_getFirstSibling__(t: *c.__AppEditorViewsFolded__, line: *c.__AppEditorLine__) callconv(.c) ?*c.__AppEditorLine__ { __zig_fuck__(t); + // maybe return self + const parent = __AppEditorViewsFolded_Line_getFirstChildLine__(t, line) orelse return null; + return __AppEditorViewsFolded_Line_getFirstChildLine__(t, parent) orelse return null; + } + // # __AppEditorViewsFolded_Line_getNearestUncleLine__ + fn __AppEditorViewsFolded_Line_getNearestUncleLine__(t: *c.__AppEditorViewsFolded__, line: *c.__AppEditorLine__) callconv(.c) ?*c.__AppEditorLine__ { + var current = line; + while(true) { + const parent = __AppEditorViewsFolded_Line_getParentLine__(t, current) orelse return null; + const uncle = __AppEditorViewsFolded_Line_getNextLine__(t, parent) orelse { + current = parent; + continue; + }; + return uncle; + } + } + // # __AppEditorViewsFolded_Line_getNextLine__ + fn __AppEditorViewsFolded_Line_getNextLine__(t: *c.__AppEditorViewsFolded__, line: *c.__AppEditorLine__) callconv(.c) ?*c.__AppEditorLine__ { __zig_fuck__(t); + const link: *c.__MemListLink__ = line.tree.link.next orelse return null; + const tree: *c.__MemTree__ = @fieldParentPtr("link", link); + return @fieldParentPtr("tree", tree); + } + // # __AppEditorViewsFolded_Line_getParentLine__ + fn __AppEditorViewsFolded_Line_getParentLine__(t: *c.__AppEditorViewsFolded__, line: *c.__AppEditorLine__) callconv(.c) ?*c.__AppEditorLine__ { + if (c.__MemTree_isChild__(@ptrCast(&line.tree))) { + var tree: *c.__MemTree__ = undefined; + c.__MemTree_getParent__(@ptrCast(&tree), &line.tree); + if (tree == &t.lines) return null; + return @fieldParentPtr("tree", tree); + } + return null; + } + // # __AppEditorViewsFolded_Line_getPrevLine__ + fn __AppEditorViewsFolded_Line_getPrevLine__(t: *c.__AppEditorViewsFolded__, line: *c.__AppEditorLine__) callconv(.c) ?*c.__AppEditorLine__ { + const link: *c.__MemListLink__ = line.tree.link.prev orelse return null; + const tree: *c.__MemTree__ = @fieldParentPtr("link", link); + if (tree == &t.lines) return null; + return @fieldParentPtr("tree", tree); + } + // # __AppEditorViewsFolded_addIndent__ + fn __AppEditorViewsFolded_addIndent__(t: *c.__AppEditorViewsFolded__) !void { + var ok: bool = true; + var indent: usize = 0; + if (t.line.*.text_len > 0) { + indent = c.__TextAscii_countIndent__(&t.line.*.text[0], t.line.*.text_len, 1); + } + if (c.__AppEditorLine_setIndent__(t.line, indent + 4)) { + } else { + ok = false; + } + t.need_redraw = true; + if (!ok) return error.Unexpected; + } + // # __AppEditorViewsFolded_addNextLine__ + fn __AppEditorViewsFolded_addNextLine__(t: *c.__AppEditorViewsFolded__) !void { + var status = false; + + var new_line: *c.__AppEditorLine__ = undefined; + if ( c.__AppEditorLine_alloc__( @ptrCast(&new_line) ) ) { + c.__AppEditorLine_init__(new_line); + c.__MemTree_pushNext__(&t.line.*.tree, &new_line.tree); + __AppEditorViewsFolded_goToNextLine__(t); + __AppEditorViewsFolded_goToStartOfText__(t); + t.need_redraw = true; + + status = true; + if (status == false) c.__AppEditorLine_free__(new_line); + } else { + // TODO debug + } + + if (status == false) return error.Unexpected; + } + // # __AppEditorViewsFolded_addPrevLine__ + fn __AppEditorViewsFolded_addPrevLine__(t: *c.__AppEditorViewsFolded__) !void { + var ok: bool = true; + + var new_line: *c.__AppEditorLine__ = undefined; + if ( c.__AppEditorLine_alloc__( @ptrCast(&new_line) ) ) { + c.__AppEditorLine_init__(new_line); + c.__MemTree_pushPrev__(&t.line.*.tree, &new_line.tree); + __AppEditorViewsFolded_goToPrevLine__(t); + __AppEditorViewsFolded_goToStartOfText__(t); + t.need_redraw = true; + if (!ok) c.__AppEditorLine_free__(new_line); + } else { + ok = true; + } + if (!ok) return error.Unexpected; + } + // # __AppEditorViewsFolded_alt2__ + fn __AppEditorViewsFolded_alt2__(t: *c.__AppEditorViewsFolded__) !void { + try __AppEditorViewsFolded_unFold__(t); + const flat = &c.__app__.editor.views.flat; + try __AppEditorViewsFlat_findPrev__(flat); + try __AppEditorViewsFlat_fold__(flat); + } + // # __AppEditorViewsFolded_alt3__ + fn __AppEditorViewsFolded_alt3__(t: *c.__AppEditorViewsFolded__) !void { + try __AppEditorViewsFolded_unFold__(t); + const flat = &c.__app__.editor.views.flat; + try __AppEditorViewsFlat_findNext__(flat); + try __AppEditorViewsFlat_fold__(flat); + } + // # __AppEditorViewsFolded_bakup__ + fn __AppEditorViewsFolded_bakup__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + t.bakup_line.text_len = t.line.*.text_len; + c.__Mem_copy__(&t.bakup_line.text[0], &t.line.*.text[0], t.line.*.text_len); + } + // # __AppEditorViewsFolded_clearLine__ + fn __AppEditorViewsFolded_clearLine__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + t.line.*.text_len = 0; + __AppEditorViewsFolded_goToStartOfText__(t); + t.need_redraw = true; + } + // # __AppEditorViewsFolded_copyWordToFind__ + fn __AppEditorViewsFolded_copyWordToFind__(t: *c.__AppEditorViewsFolded__) !void { + if (t.line.*.text_len > 0) { + const text = t.line.*.text[0..t.line.*.text_len]; + if (t.symbol < text.len) { + const sow: usize = blk: { // start_of_word + const buffer = t.line.*.text[0..]; + var pos: usize = t.symbol; + while (true) { + if (pos == 0) break; + const prev_symbol = buffer[pos - 1]; + if (c.__TextAscii_isLetter__(prev_symbol) == false) break; + pos -= 1; + } + break :blk pos; + }; + const eow: usize = blk: { // end_of_word + const buffer = t.line.*.text[0..]; + var pos: usize = t.symbol; + while (true) { + if (pos >= t.line.*.text_len - 1) { + break; + } + const next_symbol = buffer[pos + 1]; + if (c.__TextAscii_isLetter__(next_symbol) == false) break; + pos += 1; + } + break :blk pos; + }; + const word = t.line.*.text[sow .. eow + 1]; + + c.__AppEditorLine_setText__(&c.__app__.editor.views.find.line, word.ptr, word.len); + + __AppEditor_changeStatus__(word); + } else { + __AppEditor_changeStatus__("cursor not an word"); + } + __AppEditorViewsFolded_cursorMoveToCurrent__(t) catch {}; + } + } + // # __AppEditorViewsFolded_correctOffsetX__ + fn __AppEditorViewsFolded_correctOffsetX__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + const tsx = c.__app__.terminal.output.size.x; + if (t.offset.x >= tsx) t.offset.x = 0; + const predel = (tsx >> 1) - (tsx >> 4); + if (t.symbol >= predel) t.offset.x = predel; + } + // # __AppEditorViewsFolded_correctOffsetY__ + fn __AppEditorViewsFolded_correctOffsetY__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + const tsy = c.__app__.terminal.output.size.y; + if (t.offset.y >= tsy) t.offset.y = 0; + if (tsy <= 5) return; + + // count downest_lines + var count_to_downest_line: usize = 0; + var current_tree_link: *c.__MemListLink__ = &t.line.*.tree.link; + while (count_to_downest_line < 5) { + count_to_downest_line += 1; + current_tree_link = current_tree_link.next orelse break; + } + + if (tsy - t.offset.y < count_to_downest_line) { + t.offset.y = tsy - count_to_downest_line; + } + } + // # __AppEditorViewsFolded_countLineNum__ + fn __AppEditorViewsFolded_countLineNum__(t: *c.__AppEditorViewsFolded__) callconv(.c) usize { + var pos: usize = 0; + var current: *c.__MemTree__ = &t.line.*.tree; + while (true) { + if (c.__MemTree_isFirst__(current) == false) { + const prev_tree: *c.__MemTree__ = c.__MemTree_getPrev__(current); + pos += prev_tree.count; + current = prev_tree; + pos += 1; + } else if (c.__MemTree_isChild__(current)) { + c.__MemTree_getParent__(@ptrCast(¤t), current); + pos += 1; + } else { + break; + } + } + return pos; + } + // # __AppEditorViewsFolded_ctrlLeft__ + fn __AppEditorViewsFolded_ctrlLeft__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + __AppEditorViewsFolded_goToPrevSymbol__(t); + if (t.symbol > 0) { + var dest_pos: usize = 0; + if (t.line.*.text_len > 0) { + const full_text = t.line.*.text[0..t.line.*.text_len]; + const text = full_text[0 .. t.symbol]; + const spaces = c.__TextAscii_countIndentReverse__(text.ptr, text.len, 1); + if (spaces > 0) { + dest_pos = t.symbol - spaces; + } else { + dest_pos = c.__TextAscii_findBreakOfWordReverse__(text.ptr, text.len) + 1; + } + } + __AppEditorViewsFolded_goToSymbol__(t, dest_pos); + t.need_redraw = true; + } + } + // # __AppEditorViewsFolded_ctrlRight__ + fn __AppEditorViewsFolded_ctrlRight__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + __AppEditorViewsFolded_goToNextSymbol__(t); + if (t.line.*.text_len > 0) { + const full_text = t.line.*.text[0..t.line.*.text_len]; + if (t.symbol < full_text.len) { + const text = full_text[t.symbol..]; + const indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + if (indent > 0) { + __AppEditorViewsFolded_goToSymbol__(t, t.symbol + indent); + t.need_redraw = true; + return; + } + __AppEditorViewsFolded_goToSymbol__(t, c.__TextAscii_findBreakOfWord__(text.ptr, text.len) + t.symbol); + t.need_redraw = true; + } + } + } + // # __AppEditorViewsFolded_cursorMoveToCurrent__ + fn __AppEditorViewsFolded_cursorMoveToCurrent__(t: *c.__AppEditorViewsFolded__) !void { + c.__Terminal_cursorMove__(&c.__app__.terminal, t.offset.x, t.offset.y); + } + // # __AppEditorViewsFolded_cut__ + fn __AppEditorViewsFolded_cut__(t: *c.__AppEditorViewsFolded__) !void { + var ok: bool = true; + const current_tree: *c.__MemTree__ = &t.line.*.tree; + var next_tree: *c.__MemTree__ = select: { + if (@intFromPtr(current_tree.link.next) != @intFromPtr(c.NULL)) { + const next_link: *c.__MemListLink__ = current_tree.link.next; + break :select @fieldParentPtr("link", next_link); + } else if (@intFromPtr(current_tree.link.prev) != @intFromPtr(c.NULL)) { + const prev_link: *c.__MemListLink__ = current_tree.link.prev; + break :select @fieldParentPtr("link", prev_link); + } else { + var parent: *c.__MemTree__ = undefined; + c.__MemTree_getParent__(@ptrCast(&parent), current_tree); + break :select @ptrCast(parent); + } + }; + + if (next_tree == &t.lines) { + // create prev line + var new_empty_line: *c.__AppEditorLine__ = undefined; + if ( c.__AppEditorLine_alloc__( @ptrCast(&new_empty_line) ) ) { + c.__AppEditorLine_init__(new_empty_line); + c.__MemTree_pushPrev__(&t.line.*.tree, &new_empty_line.tree); + + // copy indent + var indent: usize = 0; + if (t.line.*.text_len > 0) { + indent = c.__TextAscii_countIndent__(&t.line.*.text[0], t.line.*.text_len, 1); + } + if (c.__AppEditorLine_setIndent__(new_empty_line, indent)) { + // cut current + c.__MemTree_pop__(&t.line.*.tree); + c.__MemTree_pushChild__(&t.cutted, &t.line.*.tree); + + // set as next + next_tree = &new_empty_line.tree; + + } else { + ok = false; + } + } else { + // TODO debug + ok = false; + } + + if (!ok) c.__AppEditorLine_free__(new_empty_line); + } + + if (ok) { + // move to cut + c.__MemTree_pop__(current_tree); + c.__MemTree_pushChild__(&t.cutted, current_tree); + + // update screen + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", next_tree); + t.line = line; + t.need_redraw = true; + __AppEditorViewsFolded_bakup__(t); + } + if (!ok) return error.Unexpected; + } + // # __AppEditorViewsFolded_deleteCutted__ + fn __AppEditorViewsFolded_deleteCutted__(t: *c.__AppEditorViewsFolded__) !void { + var tree_a: *allowzero c.__MemTree__ = c.__MemTree_traverse__(&t.cutted); + while(@intFromPtr(tree_a) != @intFromPtr(c.NULL)) { + if (@intFromPtr(tree_a) == @intFromPtr(&t.cutted)) unreachable; + const tree: *c.__MemTree__ = @ptrCast(tree_a); + const next: *allowzero c.__MemTree__ = c.__MemTree_traverse__(tree); + + if (tree.childs.count > 0) { + c.__MemTree_growChilds__(tree); // root skipped by first traverse + } + + + c.__MemTree_pop__(tree); + + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", tree); + c.__AppEditorLine_free__(line); + + tree_a = next; + } + + // clear t.cutted + t.cutted.childs.count = 0; + t.cutted.childs.first = 0; + t.cutted.childs.last = 0; + t.cutted.count = 0; + + __AppEditor_changeStatus__("cutted lines is gone :)"); + } + // # __AppEditorViewsFolded_deleteIndent__ + fn __AppEditorViewsFolded_deleteIndent__(t: *c.__AppEditorViewsFolded__) !void { + t.need_redraw = true; + if(c.__AppEditorLine_setIndent__(t.line, 0) == false) return error.Unexpected; + + // traversal + const start_tree = &t.line.*.tree; + const end_tree_link = start_tree.link.next orelse return; + const end_tree: *c.__MemTree__ = @fieldParentPtr("link", end_tree_link); + var wlkr = start_tree.walker(); + while (wlkr.next()) |tree| { + if (tree == end_tree) break; + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", tree); + if(c.__AppEditorLine_setIndent__(line, 0) == false) return error.Unexpected; + } + } + // # __AppEditorViewsFolded_deletePrevSymbol__ + fn __AppEditorViewsFolded_deletePrevSymbol__(t: *c.__AppEditorViewsFolded__, ) !void { + if (t.symbol == 0) { + if (t.line.*.tree.childs.count > 0) return; + if (&t.line.*.tree.link == t.lines.childs.first) return; + const prev_link: *c.__MemListLink__ = t.line.*.tree.link.prev orelse return; + const prev_tree: *c.__MemTree__ = @fieldParentPtr("link", prev_link); + const prev_line: *c.__AppEditorLine__ = @fieldParentPtr("tree", prev_tree); + + // maybe just delete current line? + const current_line_non_indent: usize = blk: { + var indent: usize = 0; + if (t.line.*.text_len > 0){ + indent = c.__TextAscii_countNonIndent__(&t.line.*.text[0], t.line.*.text_len); + } + break :blk indent; + }; + if (current_line_non_indent == 0) { // delete t line + const line_to_delete: *c.__AppEditorLine__ = t.line; + const tree_to_delete: *c.__MemTree__ = &line_to_delete.tree; + c.__MemTree_pop__(tree_to_delete); + c.__AppEditorLine_free__(line_to_delete); + t.line = prev_line; + t.need_redraw = true; + __AppEditorViewsFolded_goToEndOfLine__(t); + return; + } + + // or just delete prev line + const prev_non_indent: usize = blk: { + var indent: usize = 0; + if (prev_line.text_len > 0) { + indent = c.__TextAscii_countNonIndent__(&prev_line.text[0], prev_line.text_len); + } + break :blk indent; + }; + if (prev_non_indent == 0) { + c.__MemTree_pop__(&prev_line.tree); + c.__AppEditorLine_free__(prev_line); + t.need_redraw = true; + return; + } + } else if (t.symbol > t.line.*.text_len) { + __AppEditorViewsFolded_goToPrevSymbol__(t); + } else { + if (t.line.*.text_len == 0) return; + __AppEditorViewsFolded_goToPrevSymbol__(t); + __AppEditorViewsFolded_deleteSymbol__(t); + } + t.need_redraw = true; + } + // # __AppEditorViewsFolded_deleteSymbol__ + fn __AppEditorViewsFolded_deleteSymbol__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + if (t.line.*.text_len == 0) return; + + if (c.__Buffer_pop_check__(t.line.*.text_len, t.symbol)) { + _=c.__Buffer_pop__(&t.line.*.text[0], &t.line.*.text_len, t.symbol); + } + + t.need_redraw = true; + } + // # __AppEditorViewsFolded_deleteWord__ + fn __AppEditorViewsFolded_deleteWord__(t: *c.__AppEditorViewsFolded__) !void { + if (t.symbol > t.line.*.text_len) { + return; + } + while (true) { // delete current symbol + if (t.symbol == t.line.*.text_len) { + break; + } + const next_symbol = t.line.*.text[t.symbol]; + if (c.__TextAscii_isLetter__(next_symbol)) { + __AppEditorViewsFolded_deleteSymbol__(t); + } else { + break; + } + } + while (true) { // delete prev symbol + if (t.symbol == 0) { + break; + } + const prev_symbol = t.line.*.text[t.symbol - 1]; + if (c.__TextAscii_isLetter__(prev_symbol)) { + try __AppEditorViewsFolded_deletePrevSymbol__(t); + } else { + break; + } + } + t.need_redraw = true; + } + // # __AppEditorViewsFolded_divide__ + fn __AppEditorViewsFolded_divide__(t: *c.__AppEditorViewsFolded__) !void { + try __AppEditorViewsFolded_unFold__(t); + const flat = &c.__app__.editor.views.flat; + try __AppEditorViewsFlat_divideLine__(flat); + } + // # __AppEditorViewsFolded_doWrap__ + fn __AppEditorViewsFolded_doWrap__(ctx: *anyopaque) !void { + const t = __AppEditorViewsFoldedVtable_getModel__(ctx); + + if (t.need_redraw == true) { + t.need_redraw = false; + __AppEditorViewsFolded_draw__(t) catch unreachable; + __AppEditorViewsFolded_cursorMoveToCurrent__(t) catch unreachable; + } + + if (t.need_draw_line_num) { + t.need_draw_line_num = false; + try __AppEditorViewsFolded_drawCountLineNum__(t); + __AppEditorViewsFolded_cursorMoveToCurrent__(t) catch unreachable; + } + } + // # __AppEditorViewsFolded_do__ + fn __AppEditorViewsFolded_do__(ctx: *anyopaque) callconv(.c) void { + __AppEditorViewsFolded_doWrap__(ctx) catch unreachable; + } + // # __AppEditorViewsFolded_drawCountLineNum__ + fn __AppEditorViewsFolded_drawCountLineNum__(t: *c.__AppEditorViewsFolded__) !void { + const pos = __AppEditorViewsFolded_countLineNum__(t); + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, c.__app__.terminal.output.size.y - 1); + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_notification__, c.__AppEditorTheme_notification__.len); + // print("line number = {pos}"); + const tt: []const u8 = "line_number = "; + c.__Terminal_writeToOutput__(&c.__app__.terminal, tt.ptr, tt.len); + + _=c.__Text_formatU64__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, pos, 1); + c.__Terminal_resetColors__(&c.__app__.terminal); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_to_end_line__, 0); + try __AppEditorViewsFolded_cursorMoveToCurrent__(t); + t.need_redraw = false; + } + // # __AppEditorViewsFolded_drawDownerLines__ + fn __AppEditorViewsFolded_drawDownerLines__(t: *c.__AppEditorViewsFolded__) !void { + var pos_y: usize = t.offset.y + 1; + c.__app__.editor.lines_drawing = pos_y; + if (pos_y >= c.__app__.terminal.output.size.y) return; + var current_tree = &t.line.*.tree; + while (true) { // draw lines + c.__Terminal_resetColors__(&c.__app__.terminal); + const next_tree_link: *c.__MemListLink__ = current_tree.link.next orelse break; + const next_tree: *c.__MemTree__ = @fieldParentPtr("link", next_tree_link); + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", next_tree); + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, pos_y); + try __AppEditorViewsFolded_drawLine__(t, line); + if (pos_y >= c.__app__.terminal.output.size.y - 1) { + c.__app__.editor.lines_drawing = c.__app__.terminal.output.size.y; + return; + } + pos_y += 1; + current_tree = next_tree; + } + c.__app__.editor.lines_drawing = pos_y; + c.__Terminal_resetColors__(&c.__app__.terminal); + while (true) { // clear other downer lines + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, pos_y); + c.__Console_clearLine__(&c.__app__.console); + if (pos_y >= c.__app__.terminal.output.size.y - 1) return; + pos_y += 1; + } + } + // # __AppEditorViewsFolded_drawEditedLine__ + fn __AppEditorViewsFolded_drawEditedLine__(t: *c.__AppEditorViewsFolded__) !void { + const line = t.line; + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, t.offset.y); + // reset color and bold + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_reset__, c.__AppEditorTheme_reset__.len); + c.__Terminal_resetColors__(&c.__app__.terminal); + + if (line.*.text_len > 0) { + const text = line.*.text[0 .. line.*.text_len]; + try __AppEditorViewsFolded_drawLine__(t, line); + const screen_start: usize = t.symbol - t.offset.x; // first visible rune + const screen_end: usize = screen_start + c.__app__.terminal.output.size.x; + // draw fold indicator + if (t.line.*.tree.childs.count > 0) { + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, t.offset.y); + var symbol: u8 = ' '; + if (screen_start < text.len) { + symbol = text[screen_start]; + } + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_folded__, c.__AppEditorTheme_folded__.len); + c.__Terminal_writeToOutput__(&c.__app__.terminal, &symbol, 1); + } + // draw left arrow '<' + if (screen_start != 0) { // this means cursor_pos.x > 0 + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, t.offset.y); + if (t.line.*.tree.childs.count > 0) { + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_folded_arrows__, c.__AppEditorTheme_folded_arrows__.len); + } else { + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_arrows__, c.__AppEditorTheme_arrows__.len); + } + c.__Terminal_writeToOutput__(&c.__app__.terminal, "<", 1); + } + // draw right arrow '>' + if (screen_end < text.len) { + c.__Terminal_cursorMove__(&c.__app__.terminal, c.__app__.terminal.output.size.x - 1, t.offset.y); + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_arrows__, c.__AppEditorTheme_arrows__.len); + c.__Terminal_writeToOutput__(&c.__app__.terminal, ">", 1); + } + // current symbol + c.__Terminal_cursorMove__(&c.__app__.terminal, t.offset.x, t.offset.y); + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_current_rune__, c.__AppEditorTheme_current_rune__.len); + if (t.symbol < text.len) { + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[t.symbol], 1); + } else { + c.__Terminal_writeToOutput__(&c.__app__.terminal, " ", 1); + } + } else { + c.__Terminal_resetColors__(&c.__app__.terminal); + c.__Console_clearLine__(&c.__app__.console); + } + } + // # __AppEditorViewsFolded_drawLine__ + fn __AppEditorViewsFolded_drawLine__(t: *c.__AppEditorViewsFolded__, line: *c.__AppEditorLine__) !void { + const screen_start: usize = t.symbol - t.offset.x; // first visible rune + const screen_end: usize = screen_start + c.__app__.terminal.output.size.x; + // draw left-to-right from first visible rune + c.__Terminal_moveCursorToStartOfLine__(&c.__app__.terminal); + // reset color and bold + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_reset__, c.__AppEditorTheme_reset__.len); + c.__Terminal_resetColors__(&c.__app__.terminal); + if (line.text_len > screen_start) { + const text = line.text[0 .. line.text_len]; + var visible_text_ptr: [*c]const u8 = undefined; _=&visible_text_ptr; + var visible_text_len: usize = undefined; _=&visible_text_len; + if (c.__TextAscii_getNonIndent__(&visible_text_ptr, &visible_text_len, text.ptr, text.len)) { + const visible_text: []const u8 = visible_text_ptr[0..visible_text_len]; + if (text.len > screen_start) { + const text_end = if (text.len > screen_end) screen_end else text.len; + const draw_len = text_end - screen_start; + // bold if childs + if (line.tree.childs.count > 0) { + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_folded__, c.__AppEditorTheme_folded__.len); + } + var is_comment: usize = 0; + if (false + or std.mem.startsWith(u8, visible_text, "# ") + or std.mem.startsWith(u8, visible_text, "// ") + or std.mem.startsWith(u8, visible_text, "; ") + or std.mem.startsWith(u8, visible_text, "-- ") + ) { // if is commentary + is_comment = 1; + } else if (false + or std.mem.startsWith(u8, visible_text, "#") + or std.mem.startsWith(u8, visible_text, "//") + or std.mem.startsWith(u8, visible_text, ";") + or std.mem.startsWith(u8, visible_text, "--") + ) { // if is disabled commentary + is_comment = 2; + } + // draw text + // const to_draw = text[screen_start..text_end]; + // c.__Terminal_writeToOutput__(&c.__app__.terminal, to_draw.ptr, to_draw.len); + + if (is_comment == 2) { + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_disabled__, c.__AppEditorTheme_disabled__.len); + const draw_ptr = &text[screen_start]; + c.__Terminal_writeToOutput__(&c.__app__.terminal, draw_ptr, draw_len); + } else if (is_comment == 1) { + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_commentary__, c.__AppEditorTheme_commentary__.len); + const draw_ptr = &text[screen_start]; + c.__Terminal_writeToOutput__(&c.__app__.terminal, draw_ptr, draw_len); + } else { // coloring ^_^ + var color: [5]u8 = "\x1B[90m".*; + var last_pos: usize = 0; + var pos: usize = 0; + var hash_summ: u8 = 0; + var last_symbol_is_word: bool = false; + while (pos < draw_len) { + const symbol: u8 = text[screen_start + pos]; + if (c.__TextAsciiSymbol_isWordSymbol__(symbol)) { + if (last_symbol_is_word == false) { + last_symbol_is_word = true; + + color[3] = '0' + ((hash_summ & 0b111)); + c.__Terminal_setFontStyle__(&c.__app__.terminal, &color[0], color.len); + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[screen_start + last_pos], pos - last_pos); + last_pos = pos; + hash_summ = 0; + } + + hash_summ +%= symbol; + pos += 1; + } else { + color[3] = '0' + ((hash_summ & 0b111)); + c.__Terminal_setFontStyle__(&c.__app__.terminal, &color[0], color.len); + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[screen_start + last_pos], pos - last_pos); + last_pos = pos; + + hash_summ = symbol; + pos += 1; + + if (false) { // spaces + if (symbol == ' ') { + while(pos < draw_len-1) { + if (text[screen_start + pos+1] != ' ') { + break; + } + pos += 1; + } + } + c.__Terminal_setFontStyle__(&c.__app__.terminal, &color[0], color.len); + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[screen_start + last_pos], pos - last_pos); + last_pos = pos; + } + last_symbol_is_word = false; + } + } + if (last_pos < draw_len) { + color[3] = '0' + (hash_summ & 0b111); + c.__Terminal_setFontStyle__(&c.__app__.terminal, &color[0], color.len); + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[screen_start + last_pos], draw_len - last_pos); + } + } + } else { + // draw "#" if childs + if (line.tree.childs.count > 0) { + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_folded__, c.__AppEditorTheme_folded__.len); + c.__Terminal_writeToOutput__(&c.__app__.terminal, "#", 1); + } + } + } + // clear other + c.__Terminal_resetColors__(&c.__app__.terminal); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_to_end_line__, 0); + // draw folded indicator + if (line.tree.childs.count > 0) { + c.__Terminal_moveCursorToStartOfLine__(&c.__app__.terminal); + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_folded__, c.__AppEditorTheme_folded__.len); + var symbol: u8 = '>'; + if (text.len > screen_start) symbol = text[screen_start]; + c.__Terminal_writeToOutput__(&c.__app__.terminal, &symbol, 1); + } + // reset color and bold + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_reset__, c.__AppEditorTheme_reset__.len); + c.__Terminal_resetColors__(&c.__app__.terminal); + } else { + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_to_end_line__, 0); + } + } + // # __AppEditorViewsFolded_drawParentLine__ + fn __AppEditorViewsFolded_drawParentLine__(t: *c.__AppEditorViewsFolded__, parent: *c.__AppEditorLine__) !void { + c.__Terminal_moveCursorToStartOfLine__(&c.__app__.terminal); + if (parent.text_len > 0) { + const text = parent.text[0.. parent.text_len]; + const indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + var symbol: usize = indent; + if (indent >= t.symbol - t.offset.x) { + symbol = t.symbol - t.offset.x; + } + var offset_x: usize = 0; + while (true) { + if (symbol >= text.len) { + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_to_end_line__, 0); + break; + } + if (offset_x >= c.__app__.terminal.output.size.x - 2) break; + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[symbol], 1); + + symbol += 1; + offset_x += 1; + } + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_to_end_line__, 0); + } else { + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_to_end_line__, 0); + } + } + // # __AppEditorViewsFolded_drawUpperLines__ + fn __AppEditorViewsFolded_drawUpperLines__(t: *c.__AppEditorViewsFolded__) !void { + const nested = t.line.*.tree.nested; + + if (t.offset.y == 0) return; + var pos_y: usize = t.offset.y - 1; + var current_tree = &t.line.*.tree; + c.__Terminal_resetColors__(&c.__app__.terminal); + while (true) { // draw lines + // draw upper arrow + const term_1_3 = (c.__app__.terminal.output.size.y >> 3) * 3; + const upperest_line = if (nested > term_1_3) term_1_3 else nested; + if (t.offset.y > upperest_line and pos_y < upperest_line) { + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, pos_y + 1); + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_commentary__, c.__AppEditorTheme_commentary__.len); + c.__Terminal_writeToOutput__(&c.__app__.terminal, "^", 1); + break; + } + + // + const prev_tree_link: *c.__MemListLink__ = current_tree.link.prev orelse break; + const prev_tree: *c.__MemTree__ = @fieldParentPtr("link", prev_tree_link); + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", prev_tree); + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, pos_y); + try __AppEditorViewsFolded_drawLine__(t, line); + if (pos_y == 0) return; + pos_y -= 1; + current_tree = prev_tree; + } + + // draw headers (parents) + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_headers__, c.__AppEditorTheme_headers__.len); + while (c.__MemTree_isChild__(current_tree)) { + var parent_tree: *c.__MemTree__ = undefined; + c.__MemTree_getParent__(@ptrCast(&parent_tree), current_tree); + if (parent_tree == &t.lines) break; + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", parent_tree); + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, pos_y); + try __AppEditorViewsFolded_drawParentLine__(t, line); + if (pos_y == 0) return; + pos_y -= 1; + current_tree = parent_tree; + } + + // clear other up lines + c.__Terminal_resetColors__(&c.__app__.terminal); + while (true) { + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, pos_y); + c.__Console_clearLine__(&c.__app__.console); + if (pos_y == 0) return; + pos_y -= 1; + } + } + // # __AppEditorViewsFolded_draw__ + fn __AppEditorViewsFolded_draw__(t: *c.__AppEditorViewsFolded__) !void { + defer __AppEditorViewsFolded_cursorMoveToCurrent__(t) catch {}; + + __AppEditorViewsFolded_correctOffsetX__(t); + __AppEditorViewsFolded_correctOffsetY__(t); + if (t.symbol < t.offset.x) { // unexpected + unreachable; + //t.offset.x = 0; + //t.symbol = 0; + } + c.__ConsoleOutput_cursorHide__(&c.__app__.console.output); + defer c.__Console_showCursor__(&c.__app__.console); + + // draw edit line + try __AppEditorViewsFolded_drawEditedLine__(t); + + // draw other lines + if (c.__app__.terminal.output.size.y <= 1) return; + try __AppEditorViewsFolded_drawUpperLines__(t); + try __AppEditorViewsFolded_drawDownerLines__(t); + } + // # __AppEditorViewsFolded_duplicateAndCut__ + fn __AppEditorViewsFolded_duplicateAndCut__(t: *c.__AppEditorViewsFolded__) !void { + try __AppEditorViewsFolded_duplicate__(t); + try __AppEditorViewsFolded_cut__(t); + __AppEditor_changeStatus__("copied."); + } + // # __AppEditorViewsFolded_duplicate__ + fn __AppEditorViewsFolded_duplicate__(t: *c.__AppEditorViewsFolded__) !void { + // copy roots + const copy_line = try __AppEditorViewsFolded_duplicate_line__(t.line); + const copy_root = ©_line.tree; + c.__MemTree_pushNext__(&t.line.*.tree, copy_root); + + // copy trees + var current_tree: *c.__MemTree__ = &t.line.*.tree; + var copy_tree: *c.__MemTree__ = copy_root; + while (true) { + if (@intFromPtr(current_tree.childs.first) != @intFromPtr(c.NULL)) { + const child_link: *c.__MemListLink__ = current_tree.childs.first; + + // duplicate + const child_tree: *c.__MemTree__ = @fieldParentPtr("link", child_link); + const child_line: *c.__AppEditorLine__ = @fieldParentPtr("tree", child_tree); + const copy_child_line = try __AppEditorViewsFolded_duplicate_line__(child_line); + + // place + const copy_child_tree = ©_child_line.tree; + c.__MemTree_pushChild__(copy_tree, copy_child_tree); + + // update currents + current_tree = child_tree; + copy_tree = copy_child_tree; + } else if (@intFromPtr(current_tree.link.next) != @intFromPtr(c.NULL)) { + const next_link: *c.__MemListLink__ = current_tree.link.next; + const next_tree: *c.__MemTree__ = @fieldParentPtr("link", next_link); + if (next_tree == copy_root) break; + + // duplicate + const next_line: *c.__AppEditorLine__ = @fieldParentPtr("tree", next_tree); + const copy_next_line = try __AppEditorViewsFolded_duplicate_line__(next_line); + + // place + const copy_next_tree = ©_next_line.tree; + c.__MemTree_pushNext__(copy_tree, copy_next_tree); + + // update currents + current_tree = next_tree; + copy_tree = copy_next_tree; + } else { // find parent with next + + // find parent with next + var next_tree: *c.__MemTree__ = copy_root; + while (true) { + if (@intFromPtr(current_tree.link.next) != @intFromPtr(c.NULL)) { + const next_link: *c.__MemListLink__ = current_tree.link.next; + next_tree = @fieldParentPtr("link", next_link); + break; + } + + if (c.__MemTree_isChild__(current_tree)) { + c.__MemTree_getParent__(@ptrCast(¤t_tree), current_tree); + c.__MemTree_getParent__(@ptrCast(©_tree), copy_tree); + } else { + break; + } + } + if (next_tree == copy_root) break; + + // duplicate + const next_line: *c.__AppEditorLine__ = @fieldParentPtr("tree", next_tree); + const copy_next_line = try __AppEditorViewsFolded_duplicate_line__(next_line); + + // place + const copy_next_tree = ©_next_line.tree; + c.__MemTree_pushNext__(copy_tree, copy_next_tree); + + // update currents + current_tree = next_tree; + copy_tree = copy_next_tree; + } + } + + // update current working line and screen + t.line = copy_line; + t.need_redraw = true; + } + // # __AppEditorViewsFolded_duplicate_line__ + fn __AppEditorViewsFolded_duplicate_line__(line: *c.__AppEditorLine__) !*c.__AppEditorLine__ { + var new_line: *c.__AppEditorLine__ = undefined; + if (c.__AppEditorLine_alloc__( @ptrCast(&new_line) ) ) { + c.__AppEditorLine_init__(new_line); + if (line.text_len > 0) { + const old_text = line.text[0 .. line.text_len]; + c.__AppEditorLine_setText__(new_line, old_text.ptr, old_text.len); + } + return new_line; + // if (status == false) c.__AppEditorLine_free__(new_line); + } else { + return error.LineNotAllocated; + } + } + // # __AppEditorViewsFolded_easyMotionH__ + fn __AppEditorViewsFolded_easyMotionH__(t: *c.__AppEditorViewsFolded__) !void { + __AppEditorViewsEasyMotionHorizontal_setAsView__(t, &c.__AppEditorViewsVtable_folded__); + } + // # __AppEditorViewsFolded_easyMotionV__ + fn __AppEditorViewsFolded_easyMotionV__(t: *c.__AppEditorViewsFolded__) !void { + __AppEditorViewsEasyMotionVertical_setAsView__(t, &c.__AppEditorViewsVtable_folded__); + } + // # __AppEditorViewsFolded_externalCopy__ + fn __AppEditorViewsFolded_externalCopy__(t: *c.__AppEditorViewsFolded__) !void { + const path_len = c.__app__.editor.__AppEditor_pathToClipboard_len__; + const path_buffer = c.__app__.editor.__AppEditor_pathToClipboard__; + const path_slice = path_buffer[0..path_len]; + const path = &c.__app__.editor.__AppEditor_pathToClipboard__[0]; + + const tree = &t.cutted; + if (t.cutted.childs.count > 0) { + try __AppEditorViewsFolded_saveTreeToFile__(tree, path_slice, .skip_root); + t.need_redraw = false; + // print "saved to {clipboard}" + var buffer: [1024]u8 = undefined; + var writed: usize = 0; + writed += __zig_writeToBuffer__(&buffer[writed], "clipboard saved to "); + c.__Mem_copy__(&buffer[writed], path, path_len); + writed += path_len; + __AppEditor_changeStatus__(buffer[0..writed]); + } else { + try __AppEditorViewsFolded_saveTreeToFile__(tree, path_slice, .not_skip_root); + // print "saved to {clipboard}" + var buffer: [1024]u8 = undefined; + var writed: usize = 0; + writed += __zig_writeToBuffer__(&buffer[writed], "clipboard saved to "); + c.__Mem_copy__(&buffer[writed], path, path_len); + writed += path_len; + __AppEditor_changeStatus__(buffer[0..writed]); + } + t.need_redraw = false; + } + // # __AppEditorViewsFolded_externalPaste__ + fn __AppEditorViewsFolded_externalPaste__(t: *c.__AppEditorViewsFolded__) !void { + var ok: bool = true; + + // read file + const path = &c.__app__.editor.__AppEditor_pathToClipboard__[0]; + const path_len = c.__app__.editor.__AppEditor_pathToClipboard_len__; + var file: c.__OsFileHandle__ = undefined; + if (c.__OsFile_open__(&file, path, path_len)) { + // read file + const file_size: usize = c.__OsFile_getSize__(file); + var file_data: [*c]u8 = undefined; + if (c.__OsMem_allocAny__(&file_data, file_size)) { + if (c.__OsFile_readToBuffer__(file, file_data, file_size, 0)) { + // paste + const line = t.line; + try __AppEditorViewsFolded_addPrevLine__(t); + for (file_data[0..file_size]) |rune| { // parse lines + switch (rune) { + 13 => {}, + 10 => {try __AppEditorViewsFolded_addNextLine__(t); }, + else => {try __AppEditorViewsFolded_insertSymbol__(t, rune); }, + } + } + t.line = line; + t.need_redraw = true; + } else { + ok = false; + } + + c.__OsMem_freeAny__(file_data); + } else { + ok = false; + } + + c.__OsFile_close__(file); + } else { + ok = false; + } + + if (!ok) { + t.need_redraw = false; + + // print error + { // moving cursor + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, 0); + { // set text color + c.__Terminal_resetColors__(&c.__app__.terminal); + c.__Terminal_setFontStyle__( + &c.__app__.terminal, + c.__AppEditorTheme_notification__, + c.__AppEditorTheme_notification__.len + ); + + { // write text + const tt: []const u8 = " file ~/clipboard.tmp not reedable."; + c.__Terminal_writeToOutput__(&c.__app__.terminal, tt.ptr, tt.len); + } + + c.__Terminal_resetColors__(&c.__app__.terminal); + } + } + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_to_end_line__, 0); + } + + if (!ok) return error.Unexpected; + } + // # __AppEditorViewsFolded_findNext__ + fn __AppEditorViewsFolded_findNext__(t: *c.__AppEditorViewsFolded__) !void { + const finding_text: []const u8 = c.__app__.editor.views.find.get() orelse return; + if (finding_text.len == 0) { + var finded = true; + if (t.line.text_len > 0) { // try find on current line + const text = t.line.text[0 .. t.line.text_len]; + if (t.symbol + 1 <= text.len) { + const data: [*]const u8 = &text[t.symbol + 1]; + const data_len: usize = text.len - (t.symbol + 1); + const pos: usize = 0; + if (data_len >= finding_text.len and c.__Mem_findFast__(&pos, data, data_len, finding_text.ptr, finding_text.len)) { + finded = true; + __AppEditorViewsFolded_goToSymbol__(t, t.symbol + pos + 1); + } + } + } + + if (finded == false) { // find on next lines + var maybe_current: *allowzero c.__MemTree__ = c.__MemTree_traverse__(&t.line.*.tree); + while (@intFromPtr(maybe_current) != 0) { + { + const current: *c.__MemTree__ = maybe_current.?; + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", current); + if (line.text_len > 0) { + const line_text: []const u8 = line.text[0 .. line.text_len]; + const pos: usize = 0; + if (line_text.len >= finding_text.len and c.__Mem_findFast__(&pos, line_text.ptr, line_text.len, finding_text.ptr, finding_text.len)) { + t.line = line; + t.need_redraw = true; + t.offset.y = (c.__app__.terminal.output.size.y >> 1) + (c.__app__.terminal.output.size.y >> 3); + __AppEditorViewsFolded_goToSymbol__(t, pos); + finded = true; + break; + } + } + } + + maybe_current = c.__MemTree_traverse__(maybe_current); + } + } + if (finded) { + t.need_redraw = true; + t.bakup(); + try __AppEditorViewsFolded_draw__(t); + try __AppEditorViewsFolded_drawCountLineNum__(t); + } + } + } + // # __AppEditorViewsFolded_findPrev__ + fn __AppEditorViewsFolded_findPrev__(t: *c.__AppEditorViewsFolded__) !void { + const find_line = &c.__app__.editor.views.find.text; + if (find_line.text_len > 0) { + const finding_text: []const u8 = find_line.text[0 .. find_line.text_len]; + { // find_on_current_line + if (t.line.text_len > 0) { + const current_text: []const u8 = t.line.text[0 .. t.line.text_len]; + if (t.symbol > current_text.len) t.goToSymbol(finding_text.len); + var pos: usize = 0; + if (t.symbol >= finding_text.len and c.__mem_findFastReverse__(&pos, current_text.ptr, t.symbol, finding_text.ptr, finding_text.len)) { + __AppEditorViewsFolded_goToSymbol__(t, pos); + __AppEditorViewsFolded_bakup__(t); + t.need_redraw = true; + t.need_draw_line_num = true; + return; + } + } + } + + var current = &t.line.*.tree; + while (true) { + const prev_link = current.link.prev orelse return; + const prev_tree: *c.__MemTree__ = @fieldParentPtr("link", prev_link); + current = prev_tree; + + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", current); + if (line.text_len > 0) { + const line_text = line.text[0..line.text_len]; + var pos: usize = 0; + if (line_text.len >= finding_text and c.__mem_findFastReverse__(&pos, line_text.ptr, line_text.len, finding_text.ptr, finding_text.len)) { + t.line = line; + t.need_redraw = true; + t.goToSymbol(pos); + break; + } + } + } + t.bakup(); + try t.draw(); + try t.drawCountLineNum(); + } + } + // # __AppEditorViewsFolded_fixIndent__ + fn __AppEditorViewsFolded_fixIndent__(t: *c.__AppEditorViewsFolded__, first_line: *c.__AppEditorLine__, indent_delta: isize) !void { + if (indent_delta == 0) return; + t.need_redraw = true; + + const end_tree: ?*c.__MemTree__ = blk: { + if (__AppEditorViewsFolded_Line_getNextLine__(t, first_line)) |next_line| { + break: blk &next_line.tree; + } else if (__AppEditorViewsFolded_Line_getNearestUncleLine__(t, first_line)) |uncle_line| { + break: blk &uncle_line.tree; + } + break: blk null; + }; + + var maybe_tree: ?*c.__MemTree__ = &first_line.tree; + while (maybe_tree) |tree| { + if (tree == end_tree) break; + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", tree); + + // count indents + var current_indent: usize = 0; + if (line.text_len > 0) { + const line_text = line.text[0..line.text_len]; + current_indent = c.__TextAscii_countIndent__(line_text.ptr, line_text.len, 1); + } + const new_indent: usize = blk: { + if (indent_delta > 0) { + break: blk current_indent + @as(usize, @intCast(indent_delta)); + } else { // indent_delta < 0 + const abs_delta: usize = @intCast(indent_delta * -1); + if (abs_delta > current_indent) { + break: blk 0; + } else { // abs_delta <= current_indent + break: blk current_indent - abs_delta; + } + } + }; + + if (c.__AppEditorLine_setIndent__(line, new_indent) == false) return error.Unexpected; + maybe_tree = c.__MemTree_traverse__(tree); + } + } + // # __AppEditorViewsFolded_goToEndOfLine__ + fn __AppEditorViewsFolded_goToEndOfLine__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + t.symbol = t.line.*.text_len; + if (t.symbol > c.__app__.terminal.output.size.x - 2) { + t.offset.x = c.__app__.terminal.output.size.x - 2; + } else { + t.offset.x = t.symbol; + } + t.need_redraw = true; + } + // # __AppEditorViewsFolded_goToFirstLine__ + fn __AppEditorViewsFolded_goToFirstLine__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + const current = &t.line.*.tree; + if (c.__MemTree_isChild__(current)) { + var parent: *c.__MemTree__ = undefined; + c.__MemTree_getParent__(@ptrCast(&parent), current); + const list: *c.__MemList__ = &parent.childs; + const link: *c.__MemListLink__ = list.first orelse unreachable; + const tree: *c.__MemTree__ = @fieldParentPtr("link", link); + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", tree); + + t.line = line; + __AppEditorViewsFolded_goToStartOfText__(t); + t.offset.y = (c.__app__.terminal.output.size.y >> 1) - (c.__app__.terminal.output.size.y >> 2); + t.need_redraw = true; + __AppEditorViewsFolded_bakup__(t); + } + } + // # __AppEditorViewsFolded_goToIn__ + fn __AppEditorViewsFolded_goToIn__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + const child_tree_link: *c.__MemListLink__ = t.line.*.tree.childs.first orelse return; + const child_tree: *c.__MemTree__ = @fieldParentPtr("link", child_tree_link); + const child: *c.__AppEditorLine__ = @fieldParentPtr("tree", child_tree); + + t.line = child; + + var child_indent: usize = 0; + if (child.text_len > 0) { + const text = child.text[0..child.text_len]; + child_indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + } + __AppEditorViewsFolded_goToSymbol__(t, child_indent); + + t.offset.y = (c.__app__.terminal.output.size.y >> 1) - (c.__app__.terminal.output.size.y >> 3); + __AppEditorViewsFolded_bakup__(t); + t.need_redraw = true; + } + // # __AppEditorViewsFolded_goToLastLine__ + fn __AppEditorViewsFolded_goToLastLine__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + const current = &t.line.*.tree; + if (c.__MemTree_isChild__(current)) { + var parent: *c.__MemTree__ = undefined; + c.__MemTree_getParent__(@ptrCast(&parent), current); + const list: *c.__MemList__ = &parent.childs; + const link: *c.__MemListLink__ = list.last orelse unreachable; + const tree: *c.__MemTree__ = @fieldParentPtr("link", link); + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", tree); + + t.line = line; + __AppEditorViewsFolded_goToStartOfText__(t); + t.offset.y = (c.__app__.terminal.output.size.y >> 1) + (c.__app__.terminal.output.size.y >> 2); + t.need_redraw = true; + __AppEditorViewsFolded_bakup__(t); + } + } + // # __AppEditorViewsFolded_goToLineFromNumber__ + fn __AppEditorViewsFolded_goToLineFromNumber__(t: *c.__AppEditorViewsFolded__, _num: usize) callconv(.c) void { + switch (_num) { + 0 => { + return; + }, + + 1 => { + const first_link: *c.__MemListLink__ = t.lines.childs.first.?; + const tree_link: *c.__MemTree__ = @fieldParentPtr("link", first_link); + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", tree_link); + t.line = line; + if (t.line.*.text_len > 0) { + const text = t.line.*.text[0..t.line.*.text_len]; + __AppEditorViewsFolded_goToSymbol__(t, c.__TextAscii_countIndent__(text.ptr, text.len, 1)); + } else { + __AppEditorViewsFolded_goToSymbol__(t, 0); + } + }, + + else => { + var pos: usize = 1; + const first_link: *c.__MemListLink__ = t.lines.childs.first.?; + var current: *c.__MemTree__ = @fieldParentPtr("link", first_link); + while (true) { + if (_num == pos + current.count) { + const next_link: *c.__MemListLink__ = current.childs.last orelse break; + current = @fieldParentPtr("link", next_link); + break; + } + + if (_num > pos + current.count) { + pos += current.count + 1; + const next_link: *c.__MemListLink__ = current.link.next orelse break; + current = @fieldParentPtr("link", next_link); + if (pos >= _num) break; + continue; + } + + const link: *c.__MemListLink__ = current.childs.first.?; + current = @fieldParentPtr("link", link); + pos += 1; + if (pos >= _num) break; + } + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", current); + t.line = line; + if (t.line.*.text_len > 0) { + const text = t.line.*.text[0..t.line.*.text_len]; + __AppEditorViewsFolded_goToSymbol__(t, c.__TextAscii_countIndent__(text.ptr, text.len, 1)); + } else { + __AppEditorViewsFolded_goToSymbol__(t, 0); + } + }, + } + + t.need_redraw = true; + t.need_draw_line_num = true; + } + // # __AppEditorViewsFolded_goToMarked__ + fn __AppEditorViewsFolded_goToMarked__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + if (t.marked_line) |mark| { + t.line = mark; + t.need_redraw = true; + __AppEditorViewsFolded_bakup__(t); + } + } + // # __AppEditorViewsFolded_goToNextComment__ + fn __AppEditorViewsFolded_goToNextComment__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + var last_line = t.line; + while (true) { + __AppEditorViewsFolded_goToNextLine__(t); + if (last_line == t.line) break; + last_line = t.line; + + if (t.line.*.text_len > 0) { + const text = t.line.*.text[0..t.line.*.text_len]; + var visible_text_ptr: [*c]const u8 = undefined; _=&visible_text_ptr; + var visible_text_len: usize = undefined; _=&visible_text_len; + if (c.__TextAscii_getNonIndent__(&visible_text_ptr, &visible_text_len, text.ptr, text.len)) { + const visible_text: []const u8 = visible_text_ptr[0..visible_text_len]; + if (std.mem.startsWith(u8, visible_text, "#")) { + break; + } else if (std.mem.startsWith(u8, visible_text, "//")) { + break; + } + } + } + } + t.offset.y = (c.__app__.terminal.output.size.y >> 1) - (c.__app__.terminal.output.size.y >> 2); + } + // # __AppEditorViewsFolded_goToNextLine__ + fn __AppEditorViewsFolded_goToNextLine__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + const next_tree_link: *c.__MemListLink__ = t.line.*.tree.link.next orelse return; + const next_tree: *c.__MemTree__ = @fieldParentPtr("link", next_tree_link); + const next: *c.__AppEditorLine__ = @fieldParentPtr("tree", next_tree); + + t.line = next; + __AppEditorViewsFolded_bakup__(t); + t.need_redraw = true; + if (t.offset.y < c.__app__.terminal.output.size.y - 1) t.offset.y += 1; + } + // # __AppEditorViewsFolded_goToNextParagraph__ + fn __AppEditorViewsFolded_goToNextParagraph__(t: *c.__AppEditorViewsFolded__) !void { + // go to next line while not empty line + while (true) { + __AppEditorViewsFolded_goToNextLine__(t); + if (t.line.*.text_len > 0) { + const text = t.line.*.text[0..t.line.*.text_len]; + var visible_text_ptr: [*c]const u8 = undefined; _=&visible_text_ptr; + var visible_text_len: usize = undefined; _=&visible_text_len; + if (c.__TextAscii_getNonIndent__(&visible_text_ptr, &visible_text_len, text.ptr, text.len) == false) break; + if (t.line.*.tree.link.next == null) return; + } else { + break; + } + } + + // go to next line while empty line + while (true) { + __AppEditorViewsFolded_goToNextLine__(t); + if (t.line.*.text_len > 0) { + const text = t.line.*.text[0..t.line.*.text_len]; + var visible_text_ptr: [*c]const u8 = undefined; _=&visible_text_ptr; + var visible_text_len: usize = undefined; _=&visible_text_len; + if (c.__TextAscii_getNonIndent__(&visible_text_ptr, &visible_text_len, text.ptr, text.len) != false) break; + } + if (t.line.*.tree.link.next == null) return; + } + } + // # __AppEditorViewsFolded_goToNextSymbol__ + fn __AppEditorViewsFolded_goToNextSymbol__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + const used = t.line.*.text_len; + + // inc symbol + if (t.symbol >= c.__AppEditorLineLen_max__ - 1) return; + if (t.symbol >= used) return; + t.symbol += 1; + t.need_redraw = true; + + // inc offset + const rs = c.__app__.terminal.output.size.x - (c.__app__.terminal.output.size.x >> 2); + if (t.offset.x >= rs) return; + t.offset.x += 1; + } + // # __AppEditorViewsFolded_goToOut__ + fn __AppEditorViewsFolded_goToOut__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + const parent_tree: *allowzero c.__MemTree__ = c.__MemTree_getParentOrNull__(&t.line.*.tree); + if (@intFromPtr(parent_tree) != @intFromPtr(c.NULL)) { + if (parent_tree == &t.lines) { + __AppEditorViewsFolded_goToRoot__(t); + __AppEditorViewsFolded_bakup__(t); + t.need_redraw = true; + return; + } + const parent: *c.__MemTree__ = @ptrCast(parent_tree); + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", parent); + t.line = line; + var indent: usize = 0; + if (line.text_len > 0) { + const text = line.text[0..line.text_len]; + indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + } + __AppEditorViewsFolded_goToSymbol__(t, indent); + t.offset.y = (c.__app__.terminal.output.size.y >> 1) - (c.__app__.terminal.output.size.y >> 3); + __AppEditorViewsFolded_bakup__(t); + t.need_redraw = true; + } else { + return; + } + } + // # __AppEditorViewsFolded_goToPrevComment__ + fn __AppEditorViewsFolded_goToPrevComment__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + var last_line = t.line; + while (true) { + __AppEditorViewsFolded_goToPrevLine__(t); + if (last_line == t.line) return; + last_line = t.line; + + if (t.line.*.text_len > 0) { + const text = t.line.*.text[0..t.line.*.text_len]; + var visible_text_ptr: [*c]const u8 = undefined; _=&visible_text_ptr; + var visible_text_len: usize = undefined; _=&visible_text_len; + if (c.__TextAscii_getNonIndent__(&visible_text_ptr, &visible_text_len, text.ptr, text.len)) { + const visible_text: []const u8 = visible_text_ptr[0..visible_text_len]; + if (std.mem.startsWith(u8, visible_text, "#")) { + return; + } else if (std.mem.startsWith(u8, visible_text, "//")) { + return; + } + } + } + } + } + // # __AppEditorViewsFolded_goToPrevLine__ + fn __AppEditorViewsFolded_goToPrevLine__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + const prev_tree_link: *c.__MemListLink__ = t.line.*.tree.link.prev orelse return; + const prev_tree: *c.__MemTree__ = @fieldParentPtr("link", prev_tree_link); + const prev: *c.__AppEditorLine__ = @fieldParentPtr("tree", prev_tree); + + t.line = prev; + t.need_redraw = true; + + if (t.offset.y > 10) { + t.offset.y -= 1; + } + __AppEditorViewsFolded_bakup__(t); + } + // # __AppEditorViewsFolded_goToPrevParagraph__ + fn __AppEditorViewsFolded_goToPrevParagraph__(t: *c.__AppEditorViewsFolded__) !void { + while (true) { // go to prev line while empty line + const prev_tree_link: *c.__MemListLink__ = t.line.*.tree.link.prev orelse return; + const prev_tree: *c.__MemTree__ = @fieldParentPtr("link", prev_tree_link); + const prev: *c.__AppEditorLine__ = @fieldParentPtr("tree", prev_tree); + if (prev.text_len > 0) { + const prev_text = prev.text[0..prev.text_len]; + var visible_text_ptr: [*c]const u8 = undefined; _=&visible_text_ptr; + var visible_text_len: usize = undefined; _=&visible_text_len; + if (c.__TextAscii_getNonIndent__(&visible_text_ptr, &visible_text_len, prev_text.ptr, prev_text.len)) { + // const visible_text: []const u8 = visible_text_ptr[0..visible_text_len]; + break; + } + } + __AppEditorViewsFolded_goToPrevLine__(t); + } + + while (true) { // go to prev line while not empty line + const prev_tree_link: *c.__MemListLink__ = t.line.*.tree.link.prev orelse return; + const prev_tree: *c.__MemTree__ = @fieldParentPtr("link", prev_tree_link); + const prev: *c.__AppEditorLine__ = @fieldParentPtr("tree", prev_tree); + if (prev.text_len > 0) { + const prev_text = prev.text[0..prev.text_len]; + var visible_text_ptr: [*c]const u8 = undefined; _=&visible_text_ptr; + var visible_text_len: usize = undefined; _=&visible_text_len; + if (c.__TextAscii_getNonIndent__(&visible_text_ptr, &visible_text_len, prev_text.ptr, prev_text.len) == false) break; + __AppEditorViewsFolded_goToPrevLine__(t); + } else { + break; + } + } + } + // # __AppEditorViewsFolded_goToPrevSymbol__ + fn __AppEditorViewsFolded_goToPrevSymbol__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + const used = t.line.*.text_len; + + // inc symbol + if (t.symbol == 0) return; + if (t.symbol > used) { + t.symbol = used; + if (used < c.__app__.terminal.output.size.x - 1) t.offset.x = t.line.*.text_len; + t.need_redraw = true; + return; + } + if (t.symbol > 0) t.symbol -= 1; + t.need_redraw = true; + + // inc offset + const rs = c.__app__.terminal.output.size.x >> 2; + if (t.offset.x == 0) return; + if (t.symbol >= t.offset.x and t.offset.x < rs) return; + t.offset.x -= 1; + } + // # __AppEditorViewsFolded_goToRoot__ + fn __AppEditorViewsFolded_goToRoot__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + const r_tree_link: *c.__MemListLink__ = t.lines.childs.first orelse return; + const r_tree: *c.__MemTree__ = @fieldParentPtr("link", r_tree_link); + const r: *c.__AppEditorLine__ = @fieldParentPtr("tree", r_tree); + t.line = r; + t.offset.y = 5; + __AppEditorViewsFolded_goToStartOfText__(t); + t.need_redraw = true; + __AppEditorViewsFolded_bakup__(t); + } + // # __AppEditorViewsFolded_goToStartOfLine__ + fn __AppEditorViewsFolded_goToStartOfLine__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + t.symbol = 0; + t.offset.x = 0; + t.need_redraw = true; + } + // # __AppEditorViewsFolded_goToStartOfText__ + fn __AppEditorViewsFolded_goToStartOfText__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + if (t.line.*.text_len > 0) { + const text = t.line.*.text[0..t.line.*.text_len]; + __AppEditorViewsFolded_goToSymbol__(t, c.__TextAscii_countIndent__(text.ptr, text.len, 1)); + } else { + __AppEditorViewsFolded_goToSymbol__(t, 0); + } + } + // # __AppEditorViewsFolded_goToSymbol__ + fn __AppEditorViewsFolded_goToSymbol__(t: *c.__AppEditorViewsFolded__, pos: usize) callconv(.c) void { + t.symbol = pos; + if (t.symbol > c.__app__.terminal.output.size.x - 3) { + t.offset.x = 8; + } else { + t.offset.x = t.symbol; + } + t.need_redraw = true; + } + // # __AppEditorViewsFolded_indentToCutieLine__ + fn __AppEditorViewsFolded_indentToCutieLine__( + t: *c.__AppEditorViewsFolded__, + line: *c.__AppEditorLine__ + ) !void { // todo not bool + var new_indent: usize = 0; + if (@intFromPtr(line.tree.parent) != @intFromPtr(c.NULL)) { + const parent_tree: *c.__MemTree__ = @ptrCast(line.tree.parent); + if (parent_tree != &t.lines) { + const parent: *c.__AppEditorLine__ = @fieldParentPtr("tree", parent_tree); + new_indent = 0; + if (parent.text_len > 0) { + const text = parent.text[0..parent.text_len]; + new_indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1) + 4; + } + } + if (c.__AppEditorLine_setIndent__(line, new_indent) == false) return error.Unexpected; + } + } + // # __AppEditorViewsFolded_indentToCutie__ + fn __AppEditorViewsFolded_indentToCutie__(t: *c.__AppEditorViewsFolded__, line: *c.__AppEditorLine__) !void { + t.need_redraw = true; + + // get indent_delta + var indent_delta: isize = 0; + var line_indent: usize = 0; + if (line.text_len > 0) { + const line_text: []const u8 = line.text[0..line.text_len]; + line_indent = c.__TextAscii_countIndent__(line_text.ptr, line_text.len, 1); + } + var around_indent: usize = 0; + { + if (__AppEditorViewsFolded_Line_getNextLine__(t, line)) |next_line| { + if (next_line.text_len > 0) { + const next_line_text = next_line.text[0..next_line.text_len]; + around_indent = c.__TextAscii_countIndent__(next_line_text.ptr, next_line_text.len, 1); + } + } else if (__AppEditorViewsFolded_Line_getPrevLine__(t, line)) |prev_line| { + if (prev_line.text_len > 0) { + const prev_line_text = prev_line.text[0..prev_line.text_len]; + around_indent = c.__TextAscii_countIndent__(prev_line_text.ptr, prev_line_text.len, 1); // i can take in last symbol and add indent but its bad for indent specific languages + } + } else if (__AppEditorViewsFolded_Line_getParentLine__(t, line)) |parent_line| { + if (parent_line.text_len > 0) { + const parent_line_text = parent_line.text[0..parent_line.text_len]; + around_indent = c.__TextAscii_countIndent__(parent_line_text.ptr, parent_line_text.len, 1); // do not add automate indent inside blocks. use empty line with needed indents + } + } + } + indent_delta = @as(isize, @intCast(around_indent)) - @as(isize, @intCast(line_indent)); + if (indent_delta == 0) return; + try __AppEditorViewsFolded_fixIndent__(t, line, indent_delta); + } + // # __AppEditorViewsFolded_init__ + fn __AppEditorViewsFolded_init__(t: *c.__AppEditorViewsFolded__) !void { + t.need_redraw = true; + t.need_draw_line_num = true; + t.marked_line = null; + t.symbol = 0; + t.offset = .{ .x = 0, .y = 0 }; // __math_d2_U_Pos__ + + c.__MemTree_init__(&t.lines); + c.__MemTree_init__(&t.cutted); + c.__AppEditorLine_init__(&t.bakup_line); + } + // # __AppEditorViewsFolded_insertFindedText__ + fn __AppEditorViewsFolded_insertFindedText__(t: *c.__AppEditorViewsFolded__) !void { + const text: []const u8 = __AppEditorViewsFind_get__(&c.__app__.editor.views.find) orelse return; + for (text) |rune| { + __AppEditorViewsFolded_insertSymbol__(t, rune) catch {}; + } + t.need_redraw = true; + } + // # __AppEditorViewsFolded_insertSymbol__ + fn __AppEditorViewsFolded_insertSymbol__(t: *c.__AppEditorViewsFolded__, rune: u8) !void { + if (t.symbol > t.line.*.text_len) { + __AppEditorViewsFolded_goToSymbol__(t, t.line.*.text_len); + } + if (t.line.*.text_len < c.__AppEditorLineLen_max__) { + c.__Buffer_push__(&t.line.*.text[0], &t.line.*.text_len, t.symbol, rune); + __AppEditorViewsFolded_goToNextSymbol__(t); + } + t.need_redraw = true; + } + // # __AppEditorViewsFolded_joinLines__ + fn __AppEditorViewsFolded_joinLines__(t: *c.__AppEditorViewsFolded__) !void { + try __AppEditorViewsFolded_unFold__(t); + const flat = &c.__app__.editor.views.flat; + try __AppEditorViewsFlat_joinLines__(flat); + } + // # __AppEditorViewsFolded_manyIndent__ + fn __AppEditorViewsFolded_manyIndent__(t: *c.__AppEditorViewsFolded__) !void { // TODO rename to decrease indent + var indent: usize = 0; + if (t.line.*.text_len > 0) { + const text = t.line.*.text[0..t.line.*.text_len]; + indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + } + if (indent < 4) return; + if (c.__AppEditorLine_setIndent__(t.line, indent - 4) == false) return error.Unexpected; + t.need_redraw = true; + } + // # __AppEditorViewsFolded_markThisLine__ + fn __AppEditorViewsFolded_markThisLine__(t: *c.__AppEditorViewsFolded__) !void { + t.marked_line = t.line; + __AppEditor_changeStatus__("marked."); + } + // # __AppEditorViewsFolded_moveBlockOutside__ + fn __AppEditorViewsFolded_moveBlockOutside__(t: *c.__AppEditorViewsFolded__) !void { + const current_tree = &t.line.*.tree; + if (c.__MemTree_isChild__(current_tree)) { + var parent_tree: *c.__MemTree__ = undefined; + c.__MemTree_getParent__(@ptrCast(&parent_tree), current_tree); + const next_tree: *c.__MemTree__ = select: { + if (@intFromPtr(current_tree.link.next) != @intFromPtr(c.NULL)) { + const next_link: *c.__MemListLink__ = current_tree.link.next; + break :select @fieldParentPtr("link", next_link); + } else if (@intFromPtr(current_tree.link.prev) != @intFromPtr(c.NULL)) { + const prev_link: *c.__MemListLink__ = current_tree.link.prev; + break :select @fieldParentPtr("link", prev_link); + } else { + c.__MemTree_getParent__(@ptrCast(&parent_tree), current_tree); + break :select parent_tree; + } + }; + + // move + c.__MemTree_pop__(current_tree); + c.__MemTree_pushPrev__(parent_tree, current_tree); + try __AppEditorViewsFolded_indentToCutie__(t, t.line); + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", next_tree); + t.line = line; + + __AppEditor_changeStatus__("moved up"); + __AppEditorViewsFolded_cursorMoveToCurrent__(t) catch {}; + } + } + // # __AppEditorViewsFolded_moveBlockToMarkedInWithAddIndent__ + fn __AppEditorViewsFolded_moveBlockToMarkedInWithAddIndent__(t: *c.__AppEditorViewsFolded__) !void { + const block = t.line; + try __AppEditorViewsFolded_moveBlockToMarkedIn__(t); + try __AppEditorViewsFolded_fixIndent__(t, block, 4); + } + // # __AppEditorViewsFolded_moveBlockToMarkedIn__ + fn __AppEditorViewsFolded_moveBlockToMarkedIn__(t: *c.__AppEditorViewsFolded__) !void { + if (@intFromPtr(t.marked_line) != @intFromPtr(c.NULL)) { + const marked: *c.__AppEditorLine__ = @ptrCast(t.marked_line); + if (marked == t.line) return; + { // check current block is not a parent of marked: + var parent_tree: *c.__MemTree__ = &marked.tree; + const line_tree: *c.__MemTree__ = &t.line.*.tree; + if (parent_tree == line_tree) return; + while (true) { + if (c.__MemTree_isChild__(parent_tree)) { + c.__MemTree_getParent__(@ptrCast(&parent_tree), parent_tree); + if (parent_tree == line_tree) return; + } else { + break; + } + } + } + + // move + const next_line = blk: { + const last_line = t.line; + if (__AppEditorViewsFolded_Line_getNextLine__(t, last_line)) |ptr| { + break: blk ptr; + } else if (__AppEditorViewsFolded_Line_getPrevLine__(t, last_line)) |ptr| { + break: blk ptr; + } else if (__AppEditorViewsFolded_Line_getParentLine__(t, last_line)) |ptr| { + break: blk ptr; + } else return; + }; + + c.__MemTree_pop__(&t.line.*.tree); + c.__MemTree_pushChild__(&marked.tree, &t.line.*.tree); + + // fix indent + var indent: usize = 0; + if (t.line.*.text_len > 0) { + const text = t.line.*.text[0.. t.line.*.text_len]; + indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + } + var marked_indent: usize = 0; + if (marked.text_len > 0) { + const marked_text = marked.text[0..marked.text_len]; + marked_indent = c.__TextAscii_countIndent__(marked_text.ptr, marked_text.len, 1); + } + const indent_delta: isize = @as(isize, @intCast(marked_indent)) - @as(isize, @intCast(indent)); + try __AppEditorViewsFolded_fixIndent__(t, t.line, indent_delta); + + t.line = next_line; + t.need_redraw = true; + __AppEditor_changeStatus__("block moved to in marked."); + __AppEditorViewsFolded_cursorMoveToCurrent__(t) catch {}; + } + } + // # __AppEditorViewsFolded_moveBlockToMarkedOut__ + fn __AppEditorViewsFolded_moveBlockToMarkedOut__(t: *c.__AppEditorViewsFolded__) !void { + const marked = t.marked_line orelse return; + if (marked == t.line) return; + { // check block is not a parent of marked: + var parent_tree = &marked.*.tree; + const line_tree = &t.line.*.tree; + if (parent_tree == line_tree) return; + while (true) { + if (c.__MemTree_isChild__(parent_tree)) { + c.__MemTree_getParent__(@ptrCast(&parent_tree), parent_tree); + if (parent_tree == line_tree) return; + } else { + break; + } + } + } + + // move + var next_tree: *c.__MemTree__ = undefined; { + const current_tree = &t.line.*.tree; + if (@intFromPtr(current_tree.link.next) != @intFromPtr(c.NULL)) { + const next_link: *c.__MemListLink__ = current_tree.link.next; + next_tree = @fieldParentPtr("link", next_link); + } else if (@intFromPtr(current_tree.link.prev) != @intFromPtr(c.NULL)) { + const prev_link: *c.__MemListLink__ = current_tree.link.prev; + next_tree = @fieldParentPtr("link", prev_link); + } else { + c.__MemTree_getParent__(@ptrCast(&next_tree), current_tree); + } + } + const line_tree = &t.line.*.tree; + c.__MemTree_pop__(line_tree); + c.__MemTree_pushPrev__(&marked.*.tree, line_tree); + + try __AppEditorViewsFolded_indentToCutie__(t, t.line); + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", next_tree); + t.line = line; + t.need_redraw = true; + __AppEditor_changeStatus__("moved to marked."); + __AppEditorViewsFolded_cursorMoveToCurrent__(t) catch {}; + } + // # __AppEditorViewsFolded_moveDownToSort__ + fn __AppEditorViewsFolded_moveDownToSort__(t: *c.__AppEditorViewsFolded__) !void { + const cursor_pos_x = t.symbol; + const base_line = t.line; + const base_line_text = base_line.*.text_len; + if (cursor_pos_x <= base_line_text) { + const base_text = &base_line.*.text[cursor_pos_x]; + const base_text_len = base_line_text - cursor_pos_x; + const base_end_of_word = c.__TextAscii_findBreakOfWord__(base_text, base_text_len); + if (base_end_of_word > 0) { + var iter_count: usize = 0; + var next_line_link: [*c]c.__MemListLink__ = base_line.*.tree.link.next; + while(next_line_link != 0) { + const next_line = next_line_link.*.next; + { + const line_tree: *c.__MemTree__ = @fieldParentPtr("link", @as(*c.__MemListLink__, @ptrCast(next_line_link))); + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", line_tree); + if (line.text_len >= cursor_pos_x) { + const line_text = &line.text[cursor_pos_x]; + const line_text_len = line.text_len - cursor_pos_x; + const line_end_of_word = c.__TextAscii_findBreakOfWord__(line_text, line_text_len); + if (line_end_of_word > 0) { + const compare_size = if (base_end_of_word < line_end_of_word) base_end_of_word else line_end_of_word; // just min + const compare_result: i8 = @bitCast(c.__TextAscii_compare__(base_text, line_text, compare_size)); + if (compare_result > 0) { + try __AppEditorViewsFolded_swapWithBottom__(t); + } else { + break; + } + } else { + break; + } + } else { + break; + } + } + iter_count+=1; + next_line_link = next_line; + } + while(iter_count > 0):(iter_count -= 1) { + __AppEditorViewsFolded_goToPrevLine__(t); + } + } + } + } + // # __AppEditorViewsFolded_moveUpToSort__ + fn __AppEditorViewsFolded_moveUpToSort__(t: *c.__AppEditorViewsFolded__) !void { + const cursor_pos_x = t.symbol; + const base_line = t.line; + const base_line_text = base_line.*.text_len; + if (cursor_pos_x <= base_line_text) { + const base_text = &base_line.*.text[cursor_pos_x]; + const base_text_len = base_line_text - cursor_pos_x; + const base_end_of_word = c.__TextAscii_findBreakOfWord__(base_text, base_text_len); + if (base_end_of_word > 0) { + var iter_count: usize = 0; + var next_line_link: [*c]c.__MemListLink__ = base_line.*.tree.link.prev; + while(next_line_link != 0) { + const prev_line = next_line_link.*.prev; + { + const line_tree: *c.__MemTree__ = @fieldParentPtr("link", @as(*c.__MemListLink__, @ptrCast(next_line_link))); + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", line_tree); + if (line.text_len >= cursor_pos_x) { + const line_text = &line.text[cursor_pos_x]; + const line_text_len = line.text_len - cursor_pos_x; + const line_end_of_word = c.__TextAscii_findBreakOfWord__(line_text, line_text_len); + if (line_end_of_word > 0) { + const compare_size = if (base_end_of_word < line_end_of_word) base_end_of_word else line_end_of_word; + const compare_result: i8 = @bitCast(c.__TextAscii_compare__(base_text, line_text, compare_size)); + if (compare_result < 0) { + try __AppEditorViewsFolded_swapWithUpper__(t); + } else { + break; + } + } else { + break; + } + } else { + break; + } + } + iter_count+=1; + next_line_link = prev_line; + } + while(iter_count > 0):(iter_count -= 1) { + __AppEditorViewsFolded_goToNextLine__(t); + } + } + } + } + // # __AppEditorViewsFolded_onKey__ + fn __AppEditorViewsFolded_onKey__(t: *c.__AppEditorViewsFolded__, cik: c.__ConsoleAnsiInputKey__) callconv(.c) void { + __AppEditorViewsFolded_onkeyWrap__(t, cik) catch {}; + } + // # __AppEditorViewsFolded_onkeyWrap__ + fn __AppEditorViewsFolded_onkeyWrap__(t: *c.__AppEditorViewsFolded__, cik: c.__ConsoleAnsiInputKey__) !void { + switch (cik) { + c.__ConsoleAnsiInputKey_alt_w__ => __AppEditorViewsFolded_moveUpToSort__(t) catch {}, + c.__ConsoleAnsiInputKey_alt_s__ => __AppEditorViewsFolded_moveDownToSort__(t) catch {}, + c.__ConsoleAnsiInputKey_escape__ => __AppEditorViewsFolded_goToOut__(t), + c.__ConsoleAnsiInputKey_tab__ => __AppEditorViewsFolded_goToIn__(t), + c.__ConsoleAnsiInputKey_ctrl_e__ => try __AppEditorViewsFolded_unFold__(t), + c.__ConsoleAnsiInputKey_ctrl_q__ => c.__AppEditor_stop__(&c.__app__.editor), + c.__ConsoleAnsiInputKey_ctrl_s__ => __AppEditorViewsFolded_save__(t) catch {}, + c.__ConsoleAnsiInputKey_ctrl_j__ => try __AppEditorViewsFolded_joinLines__(t), + c.__ConsoleAnsiInputKey_enter__ => __AppEditorViewsFolded_divide__(t) catch {}, + c.__ConsoleAnsiInputKey_back_space__ => try __AppEditorViewsFolded_deletePrevSymbol__(t), + c.__ConsoleAnsiInputKey_ctrl_bs__ => try __AppEditorViewsFolded_deletePrevSymbol__(t), + c.__ConsoleAnsiInputKey_ctrl_d__ => try __AppEditorViewsFolded_duplicate__(t), + c.__ConsoleAnsiInputKey_ctrl_x__ => try __AppEditorViewsFolded_cut__(t), + c.__ConsoleAnsiInputKey_ctrl_c__ => try __AppEditorViewsFolded_duplicateAndCut__(t), + c.__ConsoleAnsiInputKey_ctrl_v__ => __AppEditorViewsFolded_pasteLine__(t) catch {}, + c.__ConsoleAnsiInputKey_ctrl_t__ => __AppEditorViewsFolded_insertSymbol__(t, '\t') catch {}, + c.__ConsoleAnsiInputKey_ctrl_w__ => try __AppEditorViewsFolded_deleteWord__(t), + c.__ConsoleAnsiInputKey_ctrl_z__ => try __AppEditorViewsFolded_restore__(t), + c.__ConsoleAnsiInputKey_ctrl_f__ => __AppEditorViewsFolded_toFind__(t) catch {}, + c.__ConsoleAnsiInputKey_ctrl_g__ => __AppEditorViewsFolded_toGoTo__(t), + c.__ConsoleAnsiInputKey_up__ => __AppEditorViewsFolded_goToPrevLine__(t), + c.__ConsoleAnsiInputKey_down__ => __AppEditorViewsFolded_goToNextLine__(t), + c.__ConsoleAnsiInputKey_left__ => __AppEditorViewsFolded_goToPrevSymbol__(t), + c.__ConsoleAnsiInputKey_right__ => __AppEditorViewsFolded_goToNextSymbol__(t), + c.__ConsoleAnsiInputKey_ctrl_shift_left__ => __AppEditorViewsFolded_CtrlShiftLeft__(t), + c.__ConsoleAnsiInputKey_ctrl_shift_right__ => __AppEditorViewsFolded_CtrlShiftRight__(t), + c.__ConsoleAnsiInputKey_ctrl_left__ => __AppEditorViewsFolded_ctrlLeft__(t), + c.__ConsoleAnsiInputKey_ctrl_right__ => __AppEditorViewsFolded_ctrlRight__(t), + c.__ConsoleAnsiInputKey_ctrl_up__ => __AppEditorViewsFolded_goToFirstLine__(t), + c.__ConsoleAnsiInputKey_ctrl_down__ => __AppEditorViewsFolded_goToLastLine__(t), + c.__ConsoleAnsiInputKey_page_up__ => __AppEditorViewsFolded_pageUp__(t), + c.__ConsoleAnsiInputKey_page_down__ => __AppEditorViewsFolded_pageDown__(t), + c.__ConsoleAnsiInputKey_alt_e__ => try __AppEditorViewsFolded_easyMotionV__(t), + c.__ConsoleAnsiInputKey_alt_q__ => try __AppEditorViewsFolded_easyMotionH__(t), + c.__ConsoleAnsiInputKey_delete__ => __AppEditorViewsFolded_deleteSymbol__(t), + c.__ConsoleAnsiInputKey_shift_delete__ => __AppEditorViewsFolded_clearLine__(t), + c.__ConsoleAnsiInputKey_end__ => __AppEditorViewsFolded_goToEndOfLine__(t), + c.__ConsoleAnsiInputKey_home__ => __AppEditorViewsFolded_goToStartOfLine__(t), + c.__ConsoleAnsiInputKey_alt_up__ => try __AppEditorViewsFolded_swapWithUpper__(t), + c.__ConsoleAnsiInputKey_alt_down__ => try __AppEditorViewsFolded_swapWithBottom__(t), + c.__ConsoleAnsiInputKey_alt_1__ => try __AppEditorViewsFolded_copyWordToFind__(t), + c.__ConsoleAnsiInputKey_alt_2__ => __AppEditorViewsFolded_alt2__(t) catch {}, + c.__ConsoleAnsiInputKey_alt_3__ => __AppEditorViewsFolded_alt3__(t) catch {}, + c.__ConsoleAnsiInputKey_alt_4__ => try __AppEditorViewsFolded_insertFindedText__(t), + c.__ConsoleAnsiInputKey_alt_5__ => __AppEditorViewsFolded_toReplace__(t), + c.__ConsoleAnsiInputKey_alt_6__ => __AppEditorViewsFolded_replace__(t) catch {}, + c.__ConsoleAnsiInputKey_alt_g__ => __AppEditorViewsFolded_goToMarked__(t), + c.__ConsoleAnsiInputKey_alt_m__ => try __AppEditorViewsFolded_markThisLine__(t), + c.__ConsoleAnsiInputKey_alt_o__ => try __AppEditorViewsFolded_moveBlockOutside__(t), + c.__ConsoleAnsiInputKey_alt_8__ => try __AppEditorViewsFolded_moveBlockToMarkedIn__(t), + c.__ConsoleAnsiInputKey_alt_9__ => try __AppEditorViewsFolded_moveBlockToMarkedInWithAddIndent__(t), + c.__ConsoleAnsiInputKey_alt_0__ => try __AppEditorViewsFolded_moveBlockToMarkedOut__(t), + c.__ConsoleAnsiInputKey_alt_c__ => __AppEditorViewsFolded_externalCopy__(t) catch {}, + c.__ConsoleAnsiInputKey_alt_v__ => __AppEditorViewsFolded_externalPaste__(t) catch {}, + c.__ConsoleAnsiInputKey_alt_z__ => try __AppEditorViewsFolded_deleteCutted__(t), + c.__ConsoleAnsiInputKey_ctrl_enter__ => try __AppEditorViewsFolded_joinLines__(t), + c.__ConsoleAnsiInputKey_alt_open_bracket__ => __AppEditorViewsFolded_goToPrevComment__(t), + c.__ConsoleAnsiInputKey_alt_close_bracket__ => __AppEditorViewsFolded_goToNextComment__(t), + c.__ConsoleAnsiInputKey_ctrl_triangular_open_quotation_mark__ => __AppEditorViewsFolded_manyIndent__(t) catch {}, + c.__ConsoleAnsiInputKey_ctrl_triangular_close_quotation_mark__ => __AppEditorViewsFolded_addIndent__(t) catch {}, + c.__ConsoleAnsiInputKey_alt_semicolon__ => try __AppEditorViewsFolded_goToPrevParagraph__(t), + c.__ConsoleAnsiInputKey_alt_apostrophe__ => try __AppEditorViewsFolded_goToNextParagraph__(t), + c.__ConsoleAnsiInputKey_f4__ => try __AppEditorViewsFolded_drawCountLineNum__(t), + else => { + if (cik > 255) return; + const byte: u8 = @truncate(cik); + __AppEditorViewsFolded_insertSymbol__(t, byte) catch {}; + t.need_redraw = true; + }, + } + } + // # __AppEditorViewsFolded_pageDown__ + fn __AppEditorViewsFolded_pageDown__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + var pos: usize = 0; + while (pos < 10) : (pos += 1) { + __AppEditorViewsFolded_goToNextLine__(t); + } + } + // # __AppEditorViewsFolded_pageUp__ + fn __AppEditorViewsFolded_pageUp__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + var pos: usize = 0; + while (pos < 10) : (pos += 1) { + __AppEditorViewsFolded_goToPrevLine__(t); + } + } + // # __AppEditorViewsFolded_pasteLine__ + fn __AppEditorViewsFolded_pasteLine__(t: *c.__AppEditorViewsFolded__) !void { + const line_tree_link: *c.__MemListLink__ = t.cutted.childs.last orelse return; + const line_tree: *c.__MemTree__ = @fieldParentPtr("link", line_tree_link); + c.__MemTree_pop__(line_tree); + c.__MemTree_pushPrev__(&t.line.*.tree, line_tree); + + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", line_tree); + try __AppEditorViewsFolded_indentToCutie__(t, line); + + t.offset.y += 1; + __AppEditorViewsFolded_goToPrevLine__(t); + t.need_redraw = true; + } + // # __AppEditorViewsFolded_replace__ + fn __AppEditorViewsFolded_replace__(t: *c.__AppEditorViewsFolded__) !void { + const find_line = &c.__app__.editor.views.find.line; + if (find_line.text_len > 0) { + const find_text = find_line.text[0..find_line.text_len]; + + const replace_line: *c.__AppEditorLine__ = &c.__app__.editor.views.replace.line; + const replace_text = replace_line.text[0..replace_line.text_len]; + + if (t.line.*.text_len - t.symbol < find_text.len) return; + const dest = t.line.*.text[t.symbol .. t.symbol + find_text.len]; + if (std.mem.eql(u8, find_text, dest) == false) return; + + // delete old text + for (find_text) |_| { + __AppEditorViewsFolded_deleteSymbol__(t); + } + + for (replace_text) |rune| { + __AppEditorViewsFolded_insertSymbol__(t, rune) catch {}; + } + + t.need_redraw = true; + } + } + // # __AppEditorViewsFolded_restore__ + fn __AppEditorViewsFolded_restore__(t: *c.__AppEditorViewsFolded__) !void { + const bakup_line = &t.bakup_line; + if (bakup_line.text_len > 0) { + const text = bakup_line.text[0..bakup_line.text_len]; + c.__AppEditorLine_setText__(t.line, text.ptr, text.len); + t.need_redraw = true; + } + } + // # __AppEditorViewsFolded_saveTreeToFile__ + fn __AppEditorViewsFolded_saveTreeToFile__(root: *c.__MemTree__, file_name: []const u8, root_skip: enum { not_skip_root, skip_root }) !void { + var ok: bool = true; + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_notification__, c.__AppEditorTheme_notification__.len); { + c.__ConsoleOutput_cursorHide__(&c.__app__.console.output); + __AppEditor_changeStatus__("saving file..."); + var full_len: usize = 0; + { // count full len + __AppEditor_changeStatus__("counting..."); + var maybe_tree: ?*c.__MemTree__ = root; // tree in c.__AppEditorLine__.tree + if (root_skip == .skip_root) { + maybe_tree = c.__MemTree_traverse__(root); + } + + if (maybe_tree) |first_tree| { // first line + const first_line: *c.__AppEditorLine__ = @fieldParentPtr("tree", first_tree); + if (first_line.text_len > 0) { + const first_line_text: []const u8 = first_line.text[0..first_line.text_len]; + full_len += first_line_text.len; + } + + maybe_tree = c.__MemTree_traverse__(first_tree); // go to next + while (maybe_tree) |tree| { // write any other lines with "\n" in start + full_len += c.__app__.editor.__AppEditor_endLine_len__; + + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", tree); + if (line.text_len > 0) { + const text = line.text[0..line.text_len]; + full_len += text.len; + } + + maybe_tree = c.__MemTree_traverse__(tree); + } // end while + } + } + + if (full_len > 0) { // write + __AppEditor_changeStatus__("allocating..."); + var buffer: [*c]u8 = undefined; + if (c.__AlignedPtr_allocAny__(&buffer, 4, full_len)) { // use aligned just for speed + // save to buffer + __AppEditor_changeStatus__("defragmentation..."); + var writed: usize = 0; + var maybe_tree: ?*c.__MemTree__ = root; // tree in c.__AppEditorLine__.tree + if (root_skip == .skip_root) { + maybe_tree = c.__MemTree_traverse__(root); + } + + if (maybe_tree) |first_tree| { // just write first line + const first_line: *c.__AppEditorLine__ = @fieldParentPtr("tree", first_tree); + if (first_line.text_len > 0) { + const first_line_text: []const u8 = first_line.text[0..first_line.text_len]; + c.__Mem_copy__(&buffer[writed], first_line_text.ptr, first_line_text.len); + writed += first_line_text.len; + } + + maybe_tree = c.__MemTree_traverse__(first_tree); // go to next + while (maybe_tree) |tree| { // write any other lines with "\n" in start + c.__Mem_copy__(&buffer[writed], c.__app__.editor.__AppEditor_endLine__, c.__app__.editor.__AppEditor_endLine_len__); + writed += c.__app__.editor.__AppEditor_endLine_len__; + + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", tree); + if (line.text_len > 0) { + const text = line.text[0..line.text_len]; + c.__Mem_copy__(&buffer[writed], text.ptr, text.len); + writed += text.len; + } + + maybe_tree = c.__MemTree_traverse__(tree); + } // end while + } + + // writing + __AppEditor_changeStatus__("writing..."); + if (c.__FileComplete_write__(file_name.ptr, file_name.len, buffer, writed)) { + } else { // file not writed + __AppEditor_changeStatus__("file not writed"); + ok = false; + } + + c.__AlignedPtr_freeAny__(buffer, full_len); + } else { // memory not allocated + __AppEditor_changeStatus__("memory not allocated"); + ok = false; + } + } else { // clear + ok = c.__FileComplete_clear__(file_name.ptr, file_name.len); + } + + __AppEditor_changeStatus__("file saved"); + c.__Console_showCursor__(&c.__app__.console); + c.__Terminal_resetColors__(&c.__app__.terminal); + } + if (!ok) return error.Unexpected; + //return ok; + } + // # __AppEditorViewsFolded_save__ + fn __AppEditorViewsFolded_save__(t: *c.__AppEditorViewsFolded__) !void { + { // write text + const tt: []const u8 = "- - unfolding... - -"; + c.__Terminal_writeToOutput__(&c.__app__.terminal, tt.ptr, tt.len); + } + try __AppEditorViewsFolded_unFold__(t); + const flat = &c.__app__.editor.views.flat; + try __AppEditorViewsFlat_save__(flat); + flat.need_redraw = true; + } + // # __AppEditorViewsFolded_setAsView__ + fn __AppEditorViewsFolded_setAsView__(t: *c.__AppEditorViewsFolded__) !void { + c.__app__.editor.do_ptr = @ptrCast(&__AppEditorViewsFolded_do__); + c.__app__.editor.onKey_ptr = @ptrCast(&__AppEditorViewsFolded_onKey__); + c.__app__.editor.current_ctx = t; + c.__app__.editor.current_vtable = &c.__AppEditorViewsVtable_folded__; + __AppEditorViewsFolded_bakup__(t); + if (t.offset.y < 10) t.offset.y = 10; + try __AppEditorViewsFolded_draw__(t); + __AppEditor_changeStatus__("Views.Folded mode."); + } + // # __AppEditorViewsFolded_swapWithBottom__ + fn __AppEditorViewsFolded_swapWithBottom__(t: *c.__AppEditorViewsFolded__) !void { + if (t.line.*.tree.link.next == null) { + return; + } + __AppEditorViewsFolded_goToNextLine__(t); + try __AppEditorViewsFolded_swapWithUpper__(t); + __AppEditorViewsFolded_goToNextLine__(t); + } + // # __AppEditorViewsFolded_swapWithUpper__ + fn __AppEditorViewsFolded_swapWithUpper__(t: *c.__AppEditorViewsFolded__) !void { + if (t.line.*.tree.link.next == null) { + try __AppEditorViewsFolded_cut__(t); + try __AppEditorViewsFolded_pasteLine__(t); + } else { + try __AppEditorViewsFolded_cut__(t); + __AppEditorViewsFolded_goToPrevLine__(t); + try __AppEditorViewsFolded_pasteLine__(t); + } + t.need_redraw = true; + } + // # __AppEditorViewsFolded_toFind__ + fn __AppEditorViewsFolded_toFind__(t: *c.__AppEditorViewsFolded__) !void { + __AppEditorViewsFind_setAsView__(&c.__app__.editor.views.find, t, &c.__AppEditorViewsVtable_folded__); + } + // # __AppEditorViewsFolded_toGoTo__ + fn __AppEditorViewsFolded_toGoTo__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + __AppEditorViewsGoToLine_setAsView__(&c.__app__.editor.views.go_to_line, t, &c.__AppEditorViewsVtable_folded__); + } + // # __AppEditorViewsFolded_toReplace__ + fn __AppEditorViewsFolded_toReplace__(t: *c.__AppEditorViewsFolded__) callconv(.c) void { + __AppEditorViewsReplace_setAsView__(&c.__app__.editor.views.replace, t, &c.__AppEditorViewsVtable_folded__); + } + // # __AppEditorViewsFolded_unFold__ + fn __AppEditorViewsFolded_unFold__(t: *c.__AppEditorViewsFolded__) !void { + const vf = &c.__app__.editor.views.flat; + const lines = &vf.lines; + if (lines.count > 0) unreachable; + + { // move to flat (from tree to link) + const root: *c.__MemTree__ = &t.lines; + var tree: ?*c.__MemTree__ = c.__MemTree_traverse__(root); // skip root // maybe more skip? + while (tree) |tree_r| { + const line: *c.__AppEditorLine__ = @fieldParentPtr("tree", tree_r); + c.__MemList_pushLast__(&vf.lines, &line.link); + tree = c.__MemTree_traverse__(tree_r); + } + } + + { // pop all lines from tree + var link_r: *allowzero c.__MemListLink__ = lines.first; + while (@intFromPtr(link_r) != @intFromPtr(c.NULL)) { + const link: *c.__MemListLink__ = @ptrCast(link_r); + const line: *c.__AppEditorLine__ = @fieldParentPtr("link", link); + c.__MemTree_pop__(&line.tree); + link_r = link.next; + } + } + + { // change Views.Flat + vf.line = t.line; + vf.symbol = t.symbol; + vf.offset = t.offset; + vf.marked_line = t.marked_line; + try __AppEditorViewsFlat_setAsView__(vf); + } + } + // # __AppEditorViewsGoToLine_CtrlShiftLeft__ + fn __AppEditorViewsGoToLine_CtrlShiftLeft__(t: *c.__AppEditorViewsGoToLine__) callconv(.c) void { + if (t.line.text_len > 0) { + const text = t.line.text[0..t.line.text_len]; + const indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + if (t.symbol > indent) { + t.goToSymbol(indent); + } else t.goToStartOfLine(); + } else t.goToStartOfLine(); + t.need_redraw = true; + } + // # __AppEditorViewsGoToLine_CtrlShiftRight__ + fn __AppEditorViewsGoToLine_CtrlShiftRight__(t: *c.__AppEditorViewsGoToLine__) callconv(.c) void { + if (t.line.text_len > 0) { + const text = t.line.text[0..t.line.text_len]; + const indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + if (t.symbol < indent) t.goToSymbol(indent) else t.goToEndOfLine(); + t.need_redraw = true; + } + } + // # __AppEditorViewsGoToLine_cancel__ + fn __AppEditorViewsGoToLine_cancel__(t: *c.__AppEditorViewsGoToLine__) !void { + t.context_vtable.*.setAsView.?(t.context); + } + // # __AppEditorViewsGoToLine_clearLine__ + fn __AppEditorViewsGoToLine_clearLine__(t: *c.__AppEditorViewsGoToLine__) callconv(.c) void { + t.line.text_len = 0; + __AppEditorViewsGoToLine_goToStartOfText__(t); + t.need_redraw = true; + } + // # __AppEditorViewsGoToLine_correctOffset__ + fn __AppEditorViewsGoToLine_correctOffset__(t: *c.__AppEditorViewsGoToLine__) callconv(.c) void { + const predel = (c.__app__.terminal.output.size.y >> 1) - (c.__app__.terminal.output.size.y >> 4); + if (t.symbol >= predel) t.offset.x = predel; + } + // # __AppEditorViewsGoToLine_ctrlLeft__ + fn __AppEditorViewsGoToLine_ctrlLeft__(t: *c.__AppEditorViewsGoToLine__) callconv(.c) void { + __AppEditorViewsGoToLine_goToSymbol__(t, 0); + t.need_redraw = true; + } + // # __AppEditorViewsGoToLine_ctrlRight__ + fn __AppEditorViewsGoToLine_ctrlRight__(t: *c.__AppEditorViewsGoToLine__) callconv(.c) void { + if (t.line.text_len > 0) { + const full_text = t.line.text[0..t.line.text_len]; + __AppEditorViewsGoToLine_goToSymbol__(t, full_text.len); + t.need_redraw = true; + } + } + // # __AppEditorViewsGoToLine_cursorMoveToCurrent__ + fn __AppEditorViewsGoToLine_cursorMoveToCurrent__(t: *c.__AppEditorViewsGoToLine__) !void { + c.__Terminal_cursorMove__(&c.__app__.terminal, t.offset.x, t.offset.y); + } + // # __AppEditorViewsGoToLine_deletePrevSymbol__ + fn __AppEditorViewsGoToLine_deletePrevSymbol__(t: *c.__AppEditorViewsGoToLine__) !void { + if (t.symbol == 0) { + return; + } else if (t.symbol > t.line.text_len) { + __AppEditorViewsGoToLine_goToPrevSymbol__(t); + } else { + if (t.line.text_len == 0) return; + __AppEditorViewsGoToLine_goToPrevSymbol__(t); + __AppEditorViewsGoToLine_deleteSymbol__(t); + } + t.need_redraw = true; + } + // # __AppEditorViewsGoToLine_deleteSymbol__ + fn __AppEditorViewsGoToLine_deleteSymbol__(t: *c.__AppEditorViewsGoToLine__) callconv(.c) void { + if (t.line.text_len == 0) return; + + if (c.__Buffer_pop_check__(t.line.text_len, t.symbol)) { + _=c.__Buffer_pop__(&t.line.text[0], &t.line.text_len, t.symbol); + } + + t.need_redraw = true; + } + // # __AppEditorViewsGoToLine_deleteWord__ + fn __AppEditorViewsGoToLine_deleteWord__(t: *c.__AppEditorViewsGoToLine__) !void { + if (t.symbol > t.line.text_len) { + return; + } + while (true) { // delete current symbol + if (t.symbol == t.line.text_len) { + break; + } + const next_symbol = t.line.text[t.symbol]; + if (c.__TextAscii_isLetter__(next_symbol)) { + t.deleteSymbol(); + } else { + break; + } + } + while (true) { // delete prev symbol + if (t.symbol == 0) { + break; + } + const prev_symbol = t.line.text[t.symbol - 1]; + if (c.__TextAscii_isLetter__(prev_symbol)) { + try t.deletePrevSymbol(); + } else { + break; + } + } + t.need_redraw = true; + } + // # __AppEditorViewsGoToLine_do__ + fn __AppEditorViewsGoToLine_do__(ctx: *anyopaque) callconv(.c) void { + const t = __AppEditorViewsGoToLine_getModel__(ctx); + + if (t.need_redraw == true) { + t.need_redraw = false; + __AppEditorViewsGoToLine_draw__(t) catch unreachable; + __AppEditorViewsGoToLine_cursorMoveToCurrent__(t) catch unreachable; + } + } + // # __AppEditorViewsGoToLine_drawEditedLine__ + fn __AppEditorViewsGoToLine_drawEditedLine__(t: *c.__AppEditorViewsGoToLine__) !void { + // change color + c.__Terminal_resetColors__(&c.__app__.terminal); + + if (t.line.text_len > 0) { + const text = t.line.text[0..t.line.text_len]; + // draw left-to-right from first visible rune + c.__Terminal_moveCursorToStartOfLine__(&c.__app__.terminal); + var pos: usize = t.symbol - t.offset.x; + var offset_x: usize = 0; + // left arrow + if (pos > 0) { // draw '<' + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_arrows__, c.__AppEditorTheme_arrows__.len); + _=__writeTextToWriteFnVoid__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, "<"); + pos += 1; + offset_x += 1; + } + // left symbols + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_current__, c.__AppEditorTheme_current__.len); + while (true) { + if (offset_x >= t.offset.x) break; + if (offset_x >= c.__app__.terminal.output.size.x - 1) break; + if (pos >= text.len) break; + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[pos], 1); + pos += 1; + offset_x += 1; + } + // current symbol. maybe inverse cursour? + if (offset_x >= c.__app__.terminal.output.size.x - 2) return; + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_current_rune__, c.__AppEditorTheme_current_rune__.len); + if (pos < text.len) { + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[pos], 1); + } + pos += 1; + offset_x += 1; + // right symbols + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_current__, c.__AppEditorTheme_current__.len); + while (true) { + if (offset_x >= c.__app__.terminal.output.size.x - 2) break; + if (pos >= text.len) break; + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[pos], 1); + pos += 1; + offset_x += 1; + } + // right arrow + if (pos < text.len) { // draw '>' + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_arrows__, c.__AppEditorTheme_arrows__.len); + _=__writeTextToWriteFnVoid__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, ">"); + } else { + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_to_end_line__, 0); + } + } else { + c.__Console_clearLine__(&c.__app__.console); + } + } + // # __AppEditorViewsGoToLine_draw__ + fn __AppEditorViewsGoToLine_draw__(t: *c.__AppEditorViewsGoToLine__) !void { + defer { + __AppEditorViewsGoToLine_cursorMoveToCurrent__(t) catch {}; + } + + __AppEditorViewsGoToLine_correctOffset__(t); + if (t.offset.x >= c.__app__.terminal.output.size.x) t.offset.x = 0; + if (t.offset.y >= c.__app__.terminal.output.size.y) t.offset.y = 0; + if (t.symbol < t.offset.x) { // unexpected + t.offset.x = 0; + t.symbol = 0; + } + + c.__ConsoleOutput_cursorHide__(&c.__app__.console.output); + defer c.__Console_showCursor__(&c.__app__.console); + + t.offset.y = 1; + { // draw banner + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, 0); + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_headers__, c.__AppEditorTheme_headers__.len); + const tt = "enter the line you want to jump to:"; + _=c.__Terminal_writeToOutput__(&c.__app__.terminal, tt.ptr, tt.len); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_to_end_line__, 0); + } + { // draw edit line + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, 1); + try __AppEditorViewsGoToLine_drawEditedLine__(t); + } + var pos_y: usize = 2; + while (true) { // clear other downer lines + if (pos_y >= c.__app__.terminal.output.size.y) return; + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, pos_y); + c.__Console_clearLine__(&c.__app__.console); + pos_y += 1; + } + } + // # __AppEditorViewsGoToLine_getModel__ + fn __AppEditorViewsGoToLine_getModel__(ptr: *anyopaque) callconv(.c) *c.__AppEditorViewsGoToLine__ { + return @alignCast(@ptrCast(ptr)); + } + // # __AppEditorViewsGoToLine_goToEndOfLine__ + fn __AppEditorViewsGoToLine_goToEndOfLine__(t: *c.__AppEditorViewsGoToLine__) callconv(.c) void { + t.symbol = t.line.text_len; + if (t.symbol > c.__app__.terminal.output.size.x - 2) { + t.offset.x = c.__app__.terminal.output.size.x - 2; + } else { + t.offset.x = t.symbol; + } + t.need_redraw = true; + } + // # __AppEditorViewsGoToLine_goToLineFromInput__ + fn __AppEditorViewsGoToLine_goToLineFromInput__(t: *c.__AppEditorViewsGoToLine__) !void { + var ok: bool = true; + if (t.line.text_len > 0) { + if (t.line.text_len > 0) { + const text = t.line.text[0..t.line.text_len]; + if (true + and text.len > 0 + and text.len <= c.__u64FromTextDec_maxLen__ + ) { + const num: usize = @truncate(c.__u64FromTextDec__(text.ptr, text.len)); + t.context_vtable.*.goToLineFromNumber.?(t.context, num); + try __AppEditorViewsGoToLine_cancel__(t); + } else { + ok = false; + } + } else { + ok = false; + } + } else { + ok = false; + } + if (!ok) { + t.context_vtable.*.goToLineFromNumber.?(t.context, 0); + try __AppEditorViewsGoToLine_cancel__(t); + return error.Unexpected; + } + } + // # __AppEditorViewsGoToLine_goToNextSymbol__ + fn __AppEditorViewsGoToLine_goToNextSymbol__(t: *c.__AppEditorViewsGoToLine__) callconv(.c) void { + const used = t.line.text_len; + if (t.symbol >= used) { + if (true) return; + if (t.line.next) |_| { + t.goToNextLine(); + t.goToStartOfText(); + } + return; + } + if (t.symbol < c.__AppEditorLineLen_max__ - 1) t.symbol += 1; + if (used - t.symbol >= 10) { + if (t.offset.x < c.__app__.terminal.output.size.x - 12) t.offset.x += 1; + } else { + if (t.offset.x < c.__app__.terminal.output.size.x - 2) t.offset.x += 1; + } + t.need_redraw = true; + } + // # __AppEditorViewsGoToLine_goToPrevSymbol__ + fn __AppEditorViewsGoToLine_goToPrevSymbol__(t: *c.__AppEditorViewsGoToLine__) callconv(.c) void { + const used = t.line.text_len; + if (t.symbol == 0) { + if (true) return; + if (t.line.prev) |_| { + t.goToPrevLine(); + t.goToEndOfLine(); + } + return; + } + if (t.symbol > used) { + t.symbol = used; + if (used < c.__app__.terminal.output.size.x - 1) t.offset.x = t.line.text_len; + t.need_redraw = true; + return; + } + if (t.symbol > 0) t.symbol -= 1; + if (t.symbol >= 10) { + if (t.offset.x > 10) { + t.offset.x -= 1; + } + } else { + if (t.offset.x > 0) t.offset.x -= 1; + } + t.need_redraw = true; + } + // # __AppEditorViewsGoToLine_goToStartOfLine__ + fn __AppEditorViewsGoToLine_goToStartOfLine__(t: *c.__AppEditorViewsGoToLine__) callconv(.c) void { + t.symbol = 0; + t.offset.x = 0; + t.need_redraw = true; + } + // # __AppEditorViewsGoToLine_goToStartOfText__ + fn __AppEditorViewsGoToLine_goToStartOfText__(t: *c.__AppEditorViewsGoToLine__) callconv(.c) void { + if (t.line.text_len > 0) { + const text = t.line.text[0..t.line.text_len]; + const indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + __AppEditorViewsGoToLine_goToSymbol__(t, indent); + } else __AppEditorViewsGoToLine_goToSymbol__(t, 0); + } + // # __AppEditorViewsGoToLine_goToSymbol__ + fn __AppEditorViewsGoToLine_goToSymbol__(t: *c.__AppEditorViewsGoToLine__, pos: usize) callconv(.c) void { + t.symbol = pos; + if (t.symbol > c.__app__.terminal.output.size.x - 3) { + t.offset.x = 8; + } else { + t.offset.x = t.symbol; + } + t.need_redraw = true; + } + // # __AppEditorViewsGoToLine_init__ + fn __AppEditorViewsGoToLine_init__(t: *c.__AppEditorViewsGoToLine__) !void { + t.need_redraw = true; + t.offset.x = 0; + t.offset.y = 3; + t.symbol = 0; + c.__AppEditorLine_init__(&t.line); + } + // # __AppEditorViewsGoToLine_insertSymbol__ + fn __AppEditorViewsGoToLine_insertSymbol__(t: *c.__AppEditorViewsGoToLine__, rune: u8) !void { + if (t.symbol > t.line.text_len) __AppEditorViewsGoToLine_goToSymbol__(t, t.line.text_len); + if (t.line.text_len < c.__AppEditorLineLen_max__) { + c.__Buffer_push__(&t.line.text[0], &t.line.text_len, t.symbol, rune); + __AppEditorViewsGoToLine_goToNextSymbol__(t); + } + t.need_redraw = true; + } + // # __AppEditorViewsGoToLine_onKey__ + fn __AppEditorViewsGoToLine_onKey__(ctx: ?*anyopaque, cik: c.__ConsoleAnsiInputKey__) callconv(.c) void { + __AppEditorViewsGoToLine_onkeyWrap__(ctx, cik) catch {}; + } + // # __AppEditorViewsGoToLine_onkeyWrap__ + fn __AppEditorViewsGoToLine_onkeyWrap__(ctx: ?*anyopaque, cik: c.__ConsoleAnsiInputKey__) !void { + const t = __AppEditorViewsGoToLine_getModel__(ctx.?); + switch (cik) { + c.__ConsoleAnsiInputKey_ctrl_left__ => __AppEditorViewsGoToLine_ctrlLeft__(t), + c.__ConsoleAnsiInputKey_ctrl_right__ => __AppEditorViewsGoToLine_ctrlRight__(t), + c.__ConsoleAnsiInputKey_delete__ => __AppEditorViewsGoToLine_deleteSymbol__(t), + c.__ConsoleAnsiInputKey_shift_delete__ => __AppEditorViewsGoToLine_clearLine__(t), + c.__ConsoleAnsiInputKey_ctrl_w__ => __AppEditorViewsGoToLine_clearLine__(t), + c.__ConsoleAnsiInputKey_left__ => __AppEditorViewsGoToLine_goToPrevSymbol__(t), + c.__ConsoleAnsiInputKey_right__ => __AppEditorViewsGoToLine_goToNextSymbol__(t), + c.__ConsoleAnsiInputKey_escape__ => try __AppEditorViewsGoToLine_cancel__(t), + c.__ConsoleAnsiInputKey_ctrl_q__ => try __AppEditorViewsGoToLine_cancel__(t), + c.__ConsoleAnsiInputKey_back_space__ => try __AppEditorViewsGoToLine_deletePrevSymbol__(t), + c.__ConsoleAnsiInputKey_ctrl_bs__ => try __AppEditorViewsGoToLine_deletePrevSymbol__(t), + c.__ConsoleAnsiInputKey_ctrl_j__ => try __AppEditorViewsGoToLine_goToLineFromInput__(t), + c.__ConsoleAnsiInputKey_enter__ => try __AppEditorViewsGoToLine_goToLineFromInput__(t), + + else => { + const byte: u8 = @truncate(cik); + switch (byte) { + '0'...'9' => __AppEditorViewsGoToLine_insertSymbol__(t, byte) catch {}, + else => {}, + } + }, + } + } + // # __AppEditorViewsGoToLine_setAsView__ + fn __AppEditorViewsGoToLine_setAsView__(t: *c.__AppEditorViewsGoToLine__, last_context: *anyopaque, last_vtable: *const c.__AppEditorViewsVTable__) callconv(.c) void { + t.context = last_context; + t.context_vtable = last_vtable; + + c.__app__.editor.do_ptr = @ptrCast(&__AppEditorViewsGoToLine_do__); + c.__app__.editor.onKey_ptr = &__AppEditorViewsGoToLine_onKey__; + c.__app__.editor.current_ctx = t; + t.need_redraw = true; + } + // # __AppEditorViewsReplace_CtrlShiftLeft__ + fn __AppEditorViewsReplace_CtrlShiftLeft__(t: *c.__AppEditorViewsReplace__) callconv(.c) void { + if (t.line.text_len > 0) { + const text = t.line.text[0..t.line.text_len]; + const indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + if (t.symbol > indent) { + t.goToSymbol(indent); + } else t.goToStartOfLine(); + } else t.goToSymbol(0); + t.need_redraw = true; + } + // # __AppEditorViewsReplace_CtrlShiftRight__ + fn __AppEditorViewsReplace_CtrlShiftRight__(t: *c.__AppEditorViewsReplace__) callconv(.c) void { + if (t.line.text_len > 0) { + const text = t.line.text[0..t.line.text_len]; + const indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + if (t.symbol < indent) t.goToSymbol(indent) else t.goToEndOfLine(); + } else t.goToSymbol(0); + t.need_redraw = true; + } + // # __AppEditorViewsReplace_cancel__ + fn __AppEditorViewsReplace_cancel__(t: *c.__AppEditorViewsReplace__) !void { + t.context_vtable.*.setAsView.?(t.context); + } + // # __AppEditorViewsReplace_clearLine__ + fn __AppEditorViewsReplace_clearLine__(t: *c.__AppEditorViewsReplace__) callconv(.c) void { + t.line.text_len = 0; + __AppEditorViewsReplace_goToStartOfText__(t); + t.need_redraw = true; + } + // # __AppEditorViewsReplace_correctOffset__ + fn __AppEditorViewsReplace_correctOffset__(t: *c.__AppEditorViewsReplace__) callconv(.c) void { + const predel = (c.__app__.terminal.output.size.y >> 1) - (c.__app__.terminal.output.size.y >> 4); + if (t.symbol >= predel) t.offset.x = predel; + } + // # __AppEditorViewsReplace_ctrlLeft__ + fn __AppEditorViewsReplace_ctrlLeft__(t: *c.__AppEditorViewsReplace__) callconv(.c) void { + __AppEditorViewsReplace_goToPrevSymbol__(t); + if (t.symbol > 0) { + var jump_symbol: usize = 0; + const line: *c.__AppEditorLine__ = &t.line; + if (line.text_len > 0) { + const full_text = line.text[0..line.text_len]; + const text = full_text[0 .. t.symbol]; + const spaces = c.__TextAscii_countIndentReverse__(text.ptr, text.len, 1); + if (spaces > 0) { + __AppEditorViewsReplace_goToSymbol__(t, t.symbol - spaces); + t.need_redraw = true; + return; + } + const dest_pos = c.__TextAscii_findBreakOfWordReverse__(text.ptr, text.len) + 1; + jump_symbol = dest_pos; + } + __AppEditorViewsReplace_goToSymbol__(t, jump_symbol); + t.need_redraw = true; + } + } + // # __AppEditorViewsReplace_ctrlRight__ + fn __AppEditorViewsReplace_ctrlRight__(t: *c.__AppEditorViewsReplace__) callconv(.c) void { + __AppEditorViewsReplace_goToNextSymbol__(t); + if (t.line.text_len > 0) { + const full_text = t.line.text[0..t.line.text_len]; + if (t.symbol >= full_text.len) return; + const text = full_text[t.symbol..]; + const indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + if (indent > 0) { + __AppEditorViewsReplace_goToSymbol__(t, t.symbol + indent); + t.need_redraw = true; + return; + } + __AppEditorViewsReplace_goToSymbol__(t, c.__TextAscii_findBreakOfWord__(text.ptr, text.len) + t.symbol); + t.need_redraw = true; + } + } + // # __AppEditorViewsReplace_cursorMoveToCurrent__ + fn __AppEditorViewsReplace_cursorMoveToCurrent__(t: *c.__AppEditorViewsReplace__) !void { + c.__Terminal_cursorMove__(&c.__app__.terminal, t.offset.x, t.offset.y); + } + // # __AppEditorViewsReplace_deletePrevSymbol__ + fn __AppEditorViewsReplace_deletePrevSymbol__(t: *c.__AppEditorViewsReplace__) !void { + if (t.symbol == 0) { + return; + } else if (t.symbol > t.line.text_len) { + __AppEditorViewsReplace_goToPrevSymbol__(t); + } else { + if (t.line.text_len == 0) return; + __AppEditorViewsReplace_goToPrevSymbol__(t); + __AppEditorViewsReplace_deleteSymbol__(t); + } + t.need_redraw = true; + } + // # __AppEditorViewsReplace_deleteSymbol__ + fn __AppEditorViewsReplace_deleteSymbol__(t: *c.__AppEditorViewsReplace__) callconv(.c) void { + if (t.line.text_len == 0) return; + + if (c.__Buffer_pop_check__(t.line.text_len, t.symbol)) { + _=c.__Buffer_pop__(&t.line.text[0], &t.line.text_len, t.symbol); + } + + t.need_redraw = true; + } + // # __AppEditorViewsReplace_deleteWord__ + fn __AppEditorViewsReplace_deleteWord__(t: *c.__AppEditorViewsReplace__) !void { + if (t.symbol > t.line.text_len) { + return; + } + while (true) { // delete current symbol + if (t.symbol == t.line.text_len) { + break; + } + const next_symbol = t.line.text[t.symbol]; + if (c.__TextAscii_isLetter__(next_symbol)) { + __AppEditorViewsReplace_deleteSymbol__(t); + } else { + break; + } + } + while (true) { // delete prev symbol + if (t.symbol == 0) { + break; + } + const prev_symbol = t.line.text[t.symbol - 1]; + if (c.__TextAscii_isLetter__(prev_symbol)) { + try __AppEditorViewsReplace_deletePrevSymbol__(t); + } else { + break; + } + } + t.need_redraw = true; + } + // # __AppEditorViewsReplace_do__ + fn __AppEditorViewsReplace_do__(ctx: *anyopaque) callconv(.c) void { + const t = __AppEditorViewsReplace_getModel__(ctx); + + if (t.need_redraw == true) { + t.need_redraw = false; + __AppEditorViewsReplace_draw__(t) catch unreachable; + __AppEditorViewsReplace_cursorMoveToCurrent__(t) catch unreachable; + } + } + // # __AppEditorViewsReplace_drawEditedLine__ + fn __AppEditorViewsReplace_drawEditedLine__(t: *c.__AppEditorViewsReplace__) !void { + if (t.line.text_len > 0) { + const text = t.line.text[0..t.line.text_len]; + c.__Terminal_moveCursorToStartOfLine__(&c.__app__.terminal); + + // change color + c.__Terminal_resetColors__(&c.__app__.terminal); + const text_color: [*]const u8 = c.__AppEditorTheme_current__; + const text_color_len: usize = c.__AppEditorTheme_current__.len; + + // draw left-to-right from first visible rune + var pos: usize = t.symbol - t.offset.x; + var offset_x: usize = 0; + + // left arrow + if (pos > 0) { // draw '<' + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_arrows__, c.__AppEditorTheme_arrows__.len); + _=__writeTextToWriteFnVoid__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, "<"); + pos += 1; + offset_x += 1; + } + + // left symbols + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, text_color, text_color_len); + while (true) { + if (offset_x >= t.offset.x) break; + if (offset_x >= c.__app__.terminal.output.size.x - 1) break; + if (pos >= text.len) break; + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[pos], 1); + pos += 1; + offset_x += 1; + } + + // current symbol. maybe inverse cursour? + if (offset_x >= c.__app__.terminal.output.size.x - 2) return; + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_current_rune__, c.__AppEditorTheme_current_rune__.len); + if (pos < text.len) { + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[pos], 1); + } + pos += 1; + offset_x += 1; + + // right symbols + c.__Terminal_setFontStyle__(&c.__app__.terminal, text_color, text_color_len); + while (true) { + if (offset_x >= c.__app__.terminal.output.size.x - 2) break; + if (pos >= text.len) break; + c.__Terminal_writeToOutput__(&c.__app__.terminal, &text[pos], 1); + pos += 1; + offset_x += 1; + } + + // right arrow + if (pos < text.len) { // draw '>' + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_arrows__, c.__AppEditorTheme_arrows__.len); + const tt: []const u8 = ">"; + _=c.__Terminal_writeToOutput__(&c.__app__.terminal, tt.ptr, tt.len); + } else { + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_to_end_line__, 0); + } + } else { + c.__Terminal_resetColors__(&c.__app__.terminal); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_line__, 0); + } + } + // # __AppEditorViewsReplace_draw__ + fn __AppEditorViewsReplace_draw__(t: *c.__AppEditorViewsReplace__) !void { + defer __AppEditorViewsReplace_cursorMoveToCurrent__(t) catch {}; + + __AppEditorViewsReplace_correctOffset__(t); + if (t.offset.x >= c.__app__.terminal.output.size.x) t.offset.x = 0; + if (t.offset.y >= c.__app__.terminal.output.size.y) t.offset.y = 0; + if (t.symbol < t.offset.x) { // unexpected + t.offset.x = 0; + t.symbol = 0; + } + c.__ConsoleOutput_cursorHide__(&c.__app__.console.output); + defer c.__Console_showCursor__(&c.__app__.console); + + t.offset.y = 1; + { // draw banner + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, 0); + c.__Terminal_setFontStyle__(&c.__app__.terminal, c.__AppEditorTheme_headers__, c.__AppEditorTheme_headers__.len); + _=__writeTextToWriteFnVoid__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, "text for replace:"); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_to_end_line__, 0); + } + { // draw edit line + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, 1); + defer __AppEditorViewsReplace_cursorMoveToCurrent__(t) catch {}; + try __AppEditorViewsReplace_drawEditedLine__(t); + } + var pos_y: usize = 2; + while (true) { // clear other downer lines + if (pos_y >= c.__app__.terminal.output.size.y) return; + c.__Terminal_cursorMove__(&c.__app__.terminal, 0, pos_y); + c.__Console_clearLine__(&c.__app__.console); + pos_y += 1; + } + } + // # __AppEditorViewsReplace_find__ + fn __AppEditorViewsReplace_find__(t: *c.__AppEditorViewsReplace__) !void { + _ = t; + const view = &c.__app__.editor.views.flat; + try view.setAsView(); + try view.findNext(); + } + // # __AppEditorViewsReplace_getModel__ + fn __AppEditorViewsReplace_getModel__(ptr: *anyopaque) callconv(.c) *c.__AppEditorViewsReplace__ { + return @alignCast(@ptrCast(ptr)); + } + // # __AppEditorViewsReplace_get__ + fn __AppEditorViewsReplace_get__(t: *c.__AppEditorViewsReplace__) callconv(.c) []const u8 { + return t.line.text[0 .. t.line.text_len]; + } + // # __AppEditorViewsReplace_goToEndOfLine__ + fn __AppEditorViewsReplace_goToEndOfLine__(t: *c.__AppEditorViewsReplace__) callconv(.c) void { + t.symbol = t.line.text_len; + if (t.symbol > c.__app__.terminal.output.size.x - 2) { + t.offset.x = c.__app__.terminal.output.size.x - 2; + } else { + t.offset.x = t.symbol; + } + t.need_redraw = true; + } + // # __AppEditorViewsReplace_goToNextSymbol__ + fn __AppEditorViewsReplace_goToNextSymbol__(t: *c.__AppEditorViewsReplace__) callconv(.c) void { + const used = t.line.text_len; + if (t.symbol >= used) { + if (true) return; + if (t.line.next) |_| { + t.goToNextLine(); + t.goToStartOfText(); + } + return; + } + if (t.symbol < c.__AppEditorLineLen_max__ - 1) t.symbol += 1; + if (used - t.symbol >= 10) { + if (t.offset.x < c.__app__.terminal.output.size.x - 12) t.offset.x += 1; + } else { + if (t.offset.x < c.__app__.terminal.output.size.x - 2) t.offset.x += 1; + } + t.need_redraw = true; + } + // # __AppEditorViewsReplace_goToPrevSymbol__ + fn __AppEditorViewsReplace_goToPrevSymbol__(t: *c.__AppEditorViewsReplace__) callconv(.c) void { + const used = t.line.text_len; + if (t.symbol == 0) { + if (true) return; + if (t.line.prev) |_| { + t.goToPrevLine(); + t.goToEndOfLine(); + } + return; + } + if (t.symbol > used) { + t.symbol = used; + if (used < c.__app__.terminal.output.size.x - 1) t.offset.x = t.line.text_len; + t.need_redraw = true; + return; + } + if (t.symbol > 0) t.symbol -= 1; + if (t.symbol >= 10) { + if (t.offset.x > 10) { + t.offset.x -= 1; + } + } else { + if (t.offset.x > 0) t.offset.x -= 1; + } + t.need_redraw = true; + } + // # __AppEditorViewsReplace_goToStartOfLine__ + fn __AppEditorViewsReplace_goToStartOfLine__(t: *c.__AppEditorViewsReplace__) callconv(.c) void { + t.symbol = 0; + t.offset.x = 0; + t.need_redraw = true; + } + // # __AppEditorViewsReplace_goToStartOfText__ + fn __AppEditorViewsReplace_goToStartOfText__(t: *c.__AppEditorViewsReplace__) callconv(.c) void { + if (t.line.text_len > 0) { + const text = t.line.text[0..t.line.text_len]; + const indent = c.__TextAscii_countIndent__(text.ptr, text.len, 1); + __AppEditorViewsReplace_goToSymbol__(t, indent); + } else __AppEditorViewsReplace_goToSymbol__(t, 0); + } + // # __AppEditorViewsReplace_goToSymbol__ + fn __AppEditorViewsReplace_goToSymbol__(t: *c.__AppEditorViewsReplace__, pos: usize) callconv(.c) void { + t.symbol = pos; + if (t.symbol > c.__app__.terminal.output.size.x - 3) { + t.offset.x = 8; + } else { + t.offset.x = t.symbol; + } + t.need_redraw = true; + } + // # __AppEditorViewsReplace_init__ + fn __AppEditorViewsReplace_init__(t: *c.__AppEditorViewsReplace__) !void { + t.offset.x = 0; + t.offset.y = 3; + t.symbol = 0; + t.need_redraw = true; + c.__AppEditorLine_init__(&t.line); + } + // # __AppEditorViewsReplace_insertFindedText__ + fn __AppEditorViewsReplace_insertFindedText__(t: *c.__AppEditorViewsReplace__) !void { + const text: []const u8 = __AppEditorViewsFind_get__(&c.__app__.editor.views.find) orelse return; + for (text) |rune| { + __AppEditorViewsReplace_insertSymbol__(t, rune) catch {}; + } + t.need_redraw = true; + } + // # __AppEditorViewsReplace_insertSymbol__ + fn __AppEditorViewsReplace_insertSymbol__(t: *c.__AppEditorViewsReplace__, rune: u8) !void { + if (t.symbol > t.line.text_len) __AppEditorViewsReplace_goToSymbol__(t, t.line.text_len); + if (t.line.text_len < c.__AppEditorLineLen_max__) { + c.__Buffer_push__(&t.line.text[0], &t.line.text_len, t.symbol, rune); + __AppEditorViewsReplace_goToNextSymbol__(t); + } + t.need_redraw = true; + } + // # __AppEditorViewsReplace_onKey__ + fn __AppEditorViewsReplace_onKey__(ctx: ?*anyopaque, cik: c.__ConsoleAnsiInputKey__) callconv(.c) void { + __AppEditorViewsReplace_onkeyWrap__(ctx, cik) catch {}; + } + // # __AppEditorViewsReplace_onkeyWrap__ + fn __AppEditorViewsReplace_onkeyWrap__(ctx: ?*anyopaque, cik: c.__ConsoleAnsiInputKey__) !void { + const t: *c.__AppEditorViewsReplace__ = @ptrCast(@alignCast(ctx)); + switch (cik) { + c.__ConsoleAnsiInputKey_ctrl_left__ => __AppEditorViewsReplace_ctrlLeft__(t), + c.__ConsoleAnsiInputKey_ctrl_right__ => __AppEditorViewsReplace_ctrlRight__(t), + c.__ConsoleAnsiInputKey_delete__ => __AppEditorViewsReplace_deleteSymbol__(t), + c.__ConsoleAnsiInputKey_shift_delete__ => __AppEditorViewsReplace_clearLine__(t), + c.__ConsoleAnsiInputKey_left__ => __AppEditorViewsReplace_goToPrevSymbol__(t), + c.__ConsoleAnsiInputKey_right__ => __AppEditorViewsReplace_goToNextSymbol__(t), + c.__ConsoleAnsiInputKey_escape__ => try __AppEditorViewsReplace_cancel__(t), + c.__ConsoleAnsiInputKey_ctrl_w__ => try __AppEditorViewsReplace_deleteWord__(t), + c.__ConsoleAnsiInputKey_back_space__ => try __AppEditorViewsReplace_deletePrevSymbol__(t), + c.__ConsoleAnsiInputKey_ctrl_bs__ => try __AppEditorViewsReplace_deletePrevSymbol__(t), + c.__ConsoleAnsiInputKey_ctrl_j__ => try __AppEditorViewsReplace_cancel__(t), + c.__ConsoleAnsiInputKey_ctrl_q__ => try __AppEditorViewsReplace_cancel__(t), + c.__ConsoleAnsiInputKey_enter__ => try __AppEditorViewsReplace_cancel__(t), + c.__ConsoleAnsiInputKey_alt_4__ => try __AppEditorViewsReplace_insertFindedText__(t), + else => { + const byte: u8 = @truncate(cik); + __AppEditorViewsReplace_insertSymbol__(t, byte) catch {}; + }, + } + } + // # __AppEditorViewsReplace_setAsView__ + fn __AppEditorViewsReplace_setAsView__(t: *c.__AppEditorViewsReplace__, last_context: *anyopaque, last_vtable: *const c.__AppEditorViewsVTable__) callconv(.c) void { + t.context = last_context; + t.context_vtable = last_vtable; + c.__app__.editor.do_ptr = @ptrCast(&__AppEditorViewsReplace_do__); + c.__app__.editor.onKey_ptr = &__AppEditorViewsReplace_onKey__; + c.__app__.editor.current_ctx = t; + t.need_redraw = true; + } + // # __AppEditorViews_deinit__ + fn __AppEditorViews_deinit__(t: *c.__AppEditorViews__) callconv(.c) void { + __zig_fuck__(t); + //t.find.deinit(); // todo + //t.go_to_line.deinit(); + //t.replace.deinit(); + //t.folded.deinit(); + //t.flat.deinit(); + } + // # __AppEditorViews_init__ + fn __AppEditorViews_init__(views: *c.__AppEditorViews__) !void { + try __AppEditorViewsFlat_init__ (&views.flat); + try __AppEditorViewsFolded_init__(&views.folded); + try __AppEditorViewsGoToLine_init__(&views.go_to_line); + try __AppEditorViewsReplace_init__(&views.replace); + try __AppEditorViewsFind_init__(&views.find); + } + // # __AppEditor_changeStatus__ + fn __AppEditor_changeStatus__(text: []const u8) void { + c.__AppEditor_changeStatus__(text.ptr, text.len); + } + // # __AppEditor_deinit__ + fn __AppEditor_deinit__(t: *c.__AppEditor__) callconv(.c) void { + if (t.inited == false) return; + __AppEditorViews_deinit__(&t.views); + } + // # __AppEditor_do__ + fn __AppEditor_do__(t: *c.__AppEditor__) !bool { + if (t.do_ptr) |do_ptr| do_ptr(t.current_ctx.?); + if (t.working == false) return false; + return true; + } + // # __AppEditor_init__ + fn __AppEditor_init__(t: *c.__AppEditor__) !void { + __AppEditorViewsFlatVtable_init__(&c.__AppEditorViewsVtable_flat__); + __AppEditorViewsFoldedVtable_init__(&c.__AppEditorViewsVtable_folded__); + + t.do_ptr = null; + t.onKey_ptr = null; + t.current_ctx = &t.views.flat; + t.current_vtable = &c.__AppEditorViewsVtable_flat__; + t.working = true; + t.__AppEditor_endLine__ = "\n"; + t.__AppEditor_endLine_len__ = "\n".len; + + t.lines_drawing = 0; + c.__MemList_init__(&t.history); + t.start_record_link = @alignCast(@ptrCast(c.NULL)); + t.stop_record_link = @alignCast(@ptrCast(c.NULL)); + t.recording_macro = false; + + try __AppEditor_updatePathToClipboard__(t); + try __AppEditorViews_init__(&t.views); + t.inited = true; + } + // # __AppEditor_onKey__ + fn __AppEditor_onKey__(t: *c.__AppEditor__, key: c.__ConsoleAnsiInputKey__) callconv(.c) void { + __AppEditor_onKeyWrap__(t, key) catch {}; + } + + fn __AppEditor_onKeyWrap__(t: *c.__AppEditor__, key: c.__ConsoleAnsiInputKey__) !void { + switch (key) { + c.__ConsoleAnsiInputKey_f1__ => _=c.__AppEditor_startRecordMacro__(t), + c.__ConsoleAnsiInputKey_f2__ => _=c.__AppEditor_stopRecordMacro__(t), // ignore error + c.__ConsoleAnsiInputKey_f3__ => try __AppEditor_playMacro__(t), + + else => { + if (c.__AppEditor_addKeyToHistory__(t, key)) { + const on_key = t.onKey_ptr orelse return; + on_key(t.current_ctx, key); + } else { + return error.Unexpected; + } + }, + } + } + // # __AppEditor_parse_text_to_lines__ + fn __AppEditor_parse_text_to_lines__( + t: *c.__AppEditor__, + list: *c.__MemList__, // list for store c.__AppEditorLine__.link + text_ptr: [*]const u8, + text_len: usize + ) !void { + var ok: bool = true; + var line_num: usize = 0; + var unparsed_len: usize = text_len; + while (ok and unparsed_len > 0) { + line_num += 1; + const line_pos: usize = text_len - unparsed_len; + + var line_text_len: usize = 0; + if (unparsed_len > "\n".len and c.__Mem_findFast__(&line_text_len, text_ptr[line_pos..], unparsed_len, "\n", 1)) { + unparsed_len -= line_text_len + "\n".len; + + const line_text: []const u8 = text_ptr[line_pos .. line_pos + line_text_len]; + if (line_text_len > 0 and line_text[line_text_len - 1] == '\r') { + t.__AppEditor_endLine__ = "\r\n"; + t.__AppEditor_endLine_len__ = "\r\n".len; + line_text_len -= "\r".len; + } + } else { + line_text_len = unparsed_len; + unparsed_len = 0; + } + + const line_text: []const u8 = text_ptr[line_pos .. line_pos + line_text_len]; + if (line_text_len < c.__AppEditorLineLen_max__) { + var line: *c.__AppEditorLine__ = undefined; + if ( c.__AppEditorLine_alloc__(@ptrCast(&line)) ) { + c.__AppEditorLine_init__(line); + line.text_len = line_text_len; + c.__Mem_copy__(&line.text[0], line_text.ptr, line_text_len); + c.__MemList_pushLast__(list, &line.link); + if (!ok) { + const link: *c.__MemListLink__ = list.last.?; + c.__MemList_pop__(list, link); + } + //if (!ok) c.__AppEditorLine_free__(line); + } else { + _=c.printf("%d, line not allocated", @src().line, line_num); + ok = false; + } + } else { + _=c.printf("%d, line %d is too long", @src().line, line_num); + ok = false; + } + } + + if (!ok) { + while(list.count > 0) { // deallocating lines + const link: *c.__MemListLink__ = list.first.?; + c.__MemList_pop__(list, link); + const line: *c.__AppEditorLine__ = @fieldParentPtr("link", link); + c.__AppEditorLine_free__(line); + } + } + if (!ok) return error.Unexpected; + return; // ok; + } + // # __AppEditor_playMacro__ + fn __AppEditor_playMacro__(t: *c.__AppEditor__) !void { + if (t.recording_macro != true) { + if ( true + and (@intFromPtr(t.start_record_link) != @intFromPtr(c.NULL)) + and (@intFromPtr(t.stop_record_link) != @intFromPtr(c.NULL)) + ) { + const sr: *c.__MemListLink__ = @ptrCast(t.start_record_link); + // const lr: *c.__MemListLink__ = @ptrCast(t.stop_record_link); + + var next_link: *allowzero c.__MemListLink__ = sr.next; // skipped start recording itself + while ( true + and ( @intFromPtr(next_link) != @intFromPtr(c.NULL) ) + and (next_link != t.stop_record_link) + ) { + const next_r: *c.__MemListLink__ = @ptrCast(next_link); + const history_note: *c.__AppEditorHistoryNote__ = @alignCast(@fieldParentPtr("link", next_r)); + const key: c.__ConsoleAnsiInputKey__ = history_note.key; + __AppEditor_onKey__(t, key); + next_link = next_r.next; + } + } else { + __AppEditor_changeStatus__("macro not recorded."); + } + } else { + __AppEditor_changeStatus__("not aviable while recording"); + } + } + // # __AppEditor_updatePathToClipboard__ + fn __AppEditor_updatePathToClipboard__(t: *c.__AppEditor__) !void { + var ok: bool = true; + + // full path: "{HOME}/clipboard.tmp" + var writed: usize = 0; + const buffer: [*c]u8 = &t.__AppEditor_pathToClipboard__[0]; + + const home_len = c.__OsEnvHome_getLen__(); + if (home_len < c.__OsFilePathLen_max__) { + c.__OsEnvHome_write__(&buffer[writed]); + writed += home_len; + + if ((@as(usize, c.__OsFilePathLen_max__) - writed) > c.__OsFilePath_separator__.len) { + c.__Mem_copy__(&buffer[writed], c.__OsFilePath_separator__.ptr, c.__OsFilePath_separator__.len); + writed += c.__OsFilePath_separator__.len; + + const t2: []const u8 = "clipboard.tmp"; + if ((@as(usize, c.__OsFilePathLen_max__) - writed) > t2.len) { + c.__Mem_copy__(&buffer[writed], t2.ptr, t2.len); + writed += t2.len; + t.__AppEditor_pathToClipboard_len__ = writed; + } else { + ok = false; + } + } else { + ok = false; + } + } else { + ok = false; + } + if (!ok) return error.NotOk; + } + // # __App_deinit__ + fn __App_deinit__(app: *c.__App__) callconv(.c) bool { + var ok: bool = true; + __AppEditor_deinit__(&app.editor); + if (c.__Terminal_deinit__(&app.terminal)) { + c.__OsHelper_deinit__(&app.__App_osHelper__); + } else {ok = false;} + return ok; + } + // # __App_init__ + fn __App_init__(app: *c.__App__) callconv(.c) bool { + var ok: bool = true; + + if(c.__OsHelper_init__(&app.__App_osHelper__)) { + c.__Console_init__(&app.console, app.__App_osHelper__.console_input_handle, app.__App_osHelper__.console_output_handle); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, c.__ConsoleAnsi_output_clear_line__, 0); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, "\r", 0); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, "- - - OwO - - -", 0); + const flat = &app.editor.views.flat; + const folded = &app.editor.views.folded; + if (c.__Terminal_init__(&app.terminal, &app.console)) { + if (__AppEditor_init__(&app.editor)) { + if (__App_parseArgsAndDo__(app)) { + if (__AppEditorViewsFlat_setAsView__(flat)){ + if (__AppEditorViewsFlat_fold__(flat)) { + if (__AppEditorViewsFolded_markThisLine__(folded)) { + app.working = true; + } else |_| { + ok = false; + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " fail markThisLine\r\n", 0); + } + } else |_| { + ok = false; + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " fail flat.fold\r\n", 0); + } + } else |_| { + ok = false; + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " fail flat.setAsView\r\n", 0); + } + } else |_| { + ok = false; + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " fail parse args\r\n", 0); + } + + if (!ok) __AppEditor_deinit__(&app.editor); + } else |_| { + ok = false; + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " fail __AppEditor_init__\r\n", 0); + } + + if (!ok) { + if (c.__Terminal_deinit__(&app.terminal)) { + } else { + ok = false; + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " fail c.__Terminal_deinit__\r\n", 0); + } + } + } else { + ok = false; + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " fail c.__Terminal_init__\r\n", 0); + } + + if (!ok) c.__OsHelper_deinit__(&app.__App_osHelper__); + } else { + ok = false; + _=c.__Text_formatU64__(@ptrCast(&c.__OsFallbackConsole_write__), null, @src().line, 1); + _=c.__ZText_writeToWriteFn__(@ptrCast(&c.__OsFallbackConsole_write__), null, " fail App_Os_Helper_init...\r\n".ptr); + } + + return ok; + } + // # __App_loop__ + fn __App_loop__(app: *c.__App__) !void { + app.tick = std.time.milliTimestamp(); + while (app.working) { + // app.__App_osHelper__ + c.__OsHelper_process__(&app.__App_osHelper__); + if (app.working == false) break; + + // update terminal + c.__Terminal_updateOutputSize__(&app.terminal); + + // terminal keyboard + while(true) { + c.__Terminal_updateInputBuffer__(&app.terminal); + var key: c.__ConsoleAnsiInputKey__ = undefined; + if (c.__TerminalInput_grab__(&key, &app.terminal.input)) { + __AppEditor_onKey__(&app.editor, key); // todo rename to onConsoleKey + } else { + break; + } + } + + const editor_result = try __AppEditor_do__(&app.editor); + if (editor_result != true) break; + + // sleep to next frame + const expected_frame_end_time = app.tick + c.__Time_msPerS__ / c.__App_expectedFps__; + const resulting_frame_end_time = std.time.milliTimestamp(); + const delay_sleep = if (resulting_frame_end_time < expected_frame_end_time) expected_frame_end_time - resulting_frame_end_time else 1; + c.__Os_sleep__(@intCast(delay_sleep)); + app.tick = resulting_frame_end_time + delay_sleep; + } + } + // # __App_parseArgsAndDo__ + fn __App_parseArgsAndDo__(t: *c.__App__) !void { + var ok: bool = true; + var argIterator = std.process.ArgIteratorPosix.init(); + _ = argIterator.skip(); // skip name of programm + + if (argIterator.next()) |name_arg| { // first arg: file name + c.__Console_clearLine__(&c.__app__.console); + c.__Terminal_moveCursorToStartOfLine__(&t.terminal); + // print("opening file {name_arg}"); + _=__writeTextToWriteFnVoid__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, "opening file "); + c.__Terminal_writeToOutput__(&c.__app__.terminal, name_arg.ptr, name_arg.len); + + if (name_arg.len < c.__OsFilePathLen_max__) { + c.__Mem_copy__(&t.editor.__AppEditor_fileName__[0], name_arg.ptr, name_arg.len); + t.editor.__AppEditor_fileName_len__ = name_arg.len; + + if (c.__OsFile_exist__(name_arg.ptr, name_arg.len)) { + var file: c.__OsFileHandle__ = undefined; + if (c.__OsFile_open__(&file, name_arg.ptr, name_arg.len)) { + const file_size: usize = c.__OsFile_getSize__(file); + if (file_size < c.__MemSize_gb__) { + c.__Console_clearLine__(&c.__app__.console); + c.__Terminal_moveCursorToStartOfLine__(&t.terminal); + _=__writeTextToWriteFnVoid__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, "file opened... "); + + var text_ptr: [*c]u8 = undefined; + if (c.__OsMem_allocAny__(&text_ptr, file_size)) { + c.__Console_clearLine__(&c.__app__.console); + c.__Terminal_moveCursorToStartOfLine__(&t.terminal); + _=__writeTextToWriteFnVoid__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, "memory allocated... "); + + if (c.__OsFile_readToBuffer__(file, text_ptr, file_size, 0)) { + c.__Console_clearLine__(&c.__app__.console); + c.__Terminal_moveCursorToStartOfLine__(&t.terminal); + _=__writeTextToWriteFnVoid__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, "readed to memory... "); + + if (__AppEditor_parse_text_to_lines__(&t.editor, &t.editor.views.flat.lines, text_ptr, file_size)) { + c.__Console_clearLine__(&c.__app__.console); + c.__Terminal_moveCursorToStartOfLine__(&t.terminal); + _=__writeTextToWriteFnVoid__(@ptrCast(&c.__Terminal_writeToOutput__), &c.__app__.terminal, "parsed to lines... "); + + const fll: *c.__MemListLink__ = t.editor.views.flat.lines.first; + if (@intFromPtr(fll) != @intFromPtr(c.NULL)) { + const line: *c.__AppEditorLine__ = @fieldParentPtr("link", fll); + t.editor.views.flat.line = line; + } else { + var line: *c.__AppEditorLine__ = undefined; + if (c.__AppEditorLine_alloc__( @ptrCast(&line) ) ) { + t.editor.views.flat.line = line; + c.__AppEditorLine_init__(line); + c.__MemList_pushLast__(&t.editor.views.flat.lines, &t.editor.views.flat.line.*.link); + if (!ok) c.__AppEditorLine_free__(line); + } + } + + if (ok) { // second arg: line number + if (argIterator.next()) |number_arg| { + // write to go_to_line.line + const line: *c.__AppEditorLine__ = &t.editor.views.go_to_line.line; + line.text_len = number_arg.len; + c.__Mem_copy__(&line.text[0], number_arg.ptr, number_arg.len); + + if (number_arg.len > 0 and number_arg.len <= c.__u64FromTextDec_maxLen__) { + const line_number = c.__u64FromTextDec__(number_arg.ptr, number_arg.len); + __AppEditorViewsFlat_goToLineFromNumber__(&t.editor.views.flat, @intCast(line_number)); + } else { + ok = false; + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " \r\n", 0); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " second argument used only for set LINE_NUMBER\r\n", 0); + } + } + } + } else |err| { + ok = false; + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " \r\n", 0); + _=c.printf(" error: {%s}\r\n", @errorName(err).ptr); + _=c.printf(" line num: {%d}\r\n", t.editor.views.flat.lines.count); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " \r\n", 0); + } + + if (!ok) { // free editor lines + const list_lines: *c.__MemList__ = &t.editor.views.flat.lines; + while (list_lines.count > 0) { + const link: *c.__MemListLink__ = list_lines.first orelse unreachable; + c.__MemList_pop__(list_lines, link); + const line: *c.__AppEditorLine__ = @fieldParentPtr("link", link); + c.__AppEditorLine_free__(line); + } + } + } else { + ok = false; + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " \r\n", 0); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " ScalpiEditor not have super cow power.\r\n", 0); + } + + c.__OsMem_freeAny__(text_ptr); + } else { + ok = false; + } + } else { + ok = false; + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " \r\n", 0); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " error: file is too large\r\n", 0); + } + + c.__OsFile_close__(file); + } else { + ok = false; + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " \r\n", 0); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " error: file not opened\r\n", 0); + } + } else { + ok = false; + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " \r\n", 0); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " error: file not exist.\r\n", 0); + } + } else { + ok = false; + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " \r\n", 0); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " error: strange file path\r\n", 0); + } + } else { + ok = false; + } + + if (!ok) { + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " \r\n", 0); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " usage: $ ScalpiEditor FILE_NAME LINE_NUMBER\r\n", 0); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " Insert coin and try again!\r\n", 0); + _=c.__OsConsoleOutput_write__(&c.__app__.console.output, " \r\n", 0); + } + + if (!ok) return error.Unexpected; + } + // # __writeTextToWriteFnVoid__ + fn __writeTextToWriteFnVoid__(write: c.__WriteFnPtrVoid__, context: *anyopaque, text: []const u8) usize { + // use callconv(.c) for target function + write.?(context, text.ptr, text.len); + return text.len; + } + // # __zig_fuck__ + fn __zig_fuck__(whom: anytype) void { + _ = whom; + } + // # __zig_writeToBuffer__ + fn __zig_writeToBuffer__(buffer: [*c]u8, text: []const u8) usize { + c.__Mem_copy__(buffer, text.ptr, text.len); + return text.len; + } + // # main + pub fn main() u8 { + @setRuntimeSafety(false); + const ok: bool = real_main(); + if (ok) {return 0;} + return 1; + } + // # real_main + fn real_main() callconv(.c) bool { + var ok: bool = true; + _=c.__Text_formatU64__(@ptrCast(&c.__OsFallbackConsole_write__), null, @src().line, 1); + _=c.__ZText_writeToWriteFn__(@ptrCast(&c.__OsFallbackConsole_write__), null, " testing...\r".ptr); + + if (c.tests()) { + if (__App_init__(&c.__app__)) { + __App_loop__(&c.__app__) catch return; + if (__App_deinit__(&c.__app__)) { + } else { + ok = false; + // print("%d: app_deinit failed \r\n", @src().line); + _=c.__Text_formatU64__(@ptrCast(&c.__OsFallbackConsole_write__), null, @src().line, 1); + _=c.__ZText_writeToWriteFn__(@ptrCast(&c.__OsFallbackConsole_write__), null, " app deinit failed...\r\n".ptr); + } + } else { + ok = false; + // c.printf("%d: fail __App_init__\r\n", @src().line); + _=c.__Text_formatU64__(@ptrCast(&c.__OsFallbackConsole_write__), null, @src().line, 1); + _=c.__ZText_writeToWriteFn__(@ptrCast(&c.__OsFallbackConsole_write__), null, " fail __App_init__\r\n".ptr); + } + } else { + ok = false; + // _=c.printf("%d: tests failed \r\n", @src().line); + _=c.__Text_formatU64__(@ptrCast(&c.__OsFallbackConsole_write__), null, @src().line, 1); + _=c.__ZText_writeToWriteFn__(@ptrCast(&c.__OsFallbackConsole_write__), null, " tests fail\r\n".ptr); + } + return ok; + } DELETED src/Glyph.zig Index: src/Glyph.zig ================================================================== --- src/Glyph.zig +++ /dev/null @@ -1,8 +0,0 @@ -const Self = @This(); - -buffer: [16]u8 = undefined, -used: usize = 0, - -pub fn getText(self: *Self) []u8 { - return self.buffer[0..self.used]; -} DELETED src/Line.zig Index: src/Line.zig ================================================================== --- src/Line.zig +++ /dev/null @@ -1,107 +0,0 @@ - -const G = @import("root"); -const T = @This(); - -pub const Rune = @import("Rune.zig"); -pub const Text = @import("Text.zig"); - -// { fields - text: Text = .{}, - - tree: G.Tree = .{}, - chain_link: G.LinkedList.Link = .{}, - - next: ?*T = null, - prev: ?*T = null, - parent: ?*T = null, - child: ?*T = null, - - len: usize = 0, - runes: ?*Rune = null, -// } -// { methods - // chain_link methods - pub fn unlink (link: *G.LinkedList.Link) *T { - return @fieldParentPtr(T, "chain_link", link); - } - - // tree methods - pub fn untree (tree: *G.Tree.Node) *T { - return @fieldParentPtr(T, "tree", tree); - } - pub fn pushPrev (self: *T, new_line: *T) void { - { // update chain - if (self.prev) |prev| { - prev.next = new_line; - new_line.prev = prev; - } // end if - self.prev = new_line; - new_line.next = self; - } - { // update tree - if (self.parent) |parent| { - self.parent = null; - parent.child = new_line; - new_line.parent = parent; - } - } - } // end fn - pub fn pushNext (self: *T, new_line: *T) void { - { // update chain - if (self.next) |next| { - next.prev = new_line; - new_line.next = next; - } // end if - self.next = new_line; - new_line.prev = self; - } // update chain - } // end fn add - pub fn getFirst (self: *T) *T { - var first = self; - while(first.prev) |prev| first = prev; - return first; - } - pub fn getParent (self: *T) ?*T { - var first = self.getFirst(); - return first.parent; - } - pub fn getLastChild (self: *T) ?*T { - if (self.child) |first| { - var current = first; - while (current.next) |next| current = next; - return current; - } else return null; - } - pub fn pop (t: *T) !void { - if (t.prev) |prev| { - prev.next = t.next; - } - if (t.next) |next| { - next.prev = t.prev; - } - if (t.parent) |parent| { - parent.child = t.next; - if (t.next) |next| { - next.parent = parent; - } - } - t.prev = null; - t.next = null; - t.parent = null; - } - - - // todo: move this to view (tree and flat) - pub fn toPos (self: *T) usize { - var pos = 0; - var itr = self.chain_link.iterReverse(); - while(itr.next()) |_| {pos += 1;} - return pos; - } - pub fn changeIndentToCutie (self: *T) !void { - var new_indent: usize = 0; - if (self.prev) |prev| {new_indent = prev.text.countIndent(1);} - else if (self.parent) |parent| {new_indent = parent.text.countIndent(1) + 4;} - try self.text.changeIndent(new_indent); - } -// } DELETED src/LinkedLine.zig Index: src/LinkedLine.zig ================================================================== --- src/LinkedLine.zig +++ /dev/null @@ -1,59 +0,0 @@ - -const G = @import("root"); -const T = @This(); - -pub const Rune = @import("Rune.zig"); -pub const Text = @import("Text.zig"); - -// { fields - text: Text = .{}, - - tree: G.Tree = .{}, - chain_link: G.LinkedList.Link = .{}, - - len: usize = 0, - runes: ?*Rune = null, -// } -// { methods - // chain_link methods - pub fn unlink (link: *G.LinkedList.Link) *T { - return @fieldParentPtr(T, "chain_link", link); - } - - // tree methods - pub fn untree (tree: *G.Tree.Node) *T { - return @fieldParentPtr(T, "tree", tree); - } - pub fn getFirst (self: *T) *T { - const parent = self.tree.parent.?; - const first_link = parent.childs.first.?; - const first_tree = Tree.unlink(first_link); - const first = Self.untree(first_tree); - return first; - } - pub fn getParent (self: *T) ?*T { - const parent_tree = self.tree.parent orelse return null; - return Self.untree(parent_tree); - } - pub fn getLastChild (self: *T) ?*T { - const link = self.tree.childs.last orelse return null; - const tree = Tree.unlink(link); - const line = Self.untree(tree); - return line; - } - - -// todo: move this to view (tree and flat) - pub fn toPos (self: *T) usize { - var pos = 0; - var itr = self.chain_link.iterReverse(); - while(itr.next()) |_| {pos += 1;} - return pos; - } - pub fn changeIndentToCutie (self: *T) !void { - var new_indent: usize = 0; - if (self.prev) |prev| {new_indent = prev.text.countIndent(1);} - else if (self.parent) |parent| {new_indent = parent.text.countIndent(1) + 4;} - try self.text.changeIndent(new_indent); - } -// } DELETED src/Rune.zig Index: src/Rune.zig ================================================================== --- src/Rune.zig +++ /dev/null @@ -1,13 +0,0 @@ -const G = @import("root"); -const T = @This(); - -pub const Glyph = @import("Glyph.zig"); - -glyph: Glyph = .{}, -color: ?[]u8 = null, -node: G.Tree = .{}, -link: G.LinkedList.Link = .{}, - -pub fn unlink (link: *G.LinkedList.Link) *T { - return @fieldParentPtr(T, "link", link); -} DELETED src/ScalpiEditor.zig Index: src/ScalpiEditor.zig ================================================================== --- src/ScalpiEditor.zig +++ /dev/null @@ -1,176 +0,0 @@ -const G = @import("root"); -const T = @This(); - -pub const draw_lag = 0; //std.time.ns_per_ms; //for debug; - - // modules - pub const Text = @import("Text.zig"); // old - pub const Line = @import("Line.zig"); - pub const Rune = @import("Rune.zig"); - pub const Glyph = @import("Glyph.zig"); - - // allocators -// TODO: -pub const LineBufferedAllocator = G.lba.Init(Line, 100, "chain_link"); - // WordBufferedAllocator - // ViewLinkBufferedAllocator - // TextBufferedAllocator - - - -pub const ViewLink = struct { - base: usize, - address_do: usize, - _type: FoldMode, - chain_link: LinkedList.Link, - - pub fn do (t: *ViewLink) void { - @call(.{ .modifier = .always_inline }, t.address_do, .{t.base}); - } -}; - - -pub const Window = struct { - size: G.lib.Coor2u = .{}, - pos: G.lib.Coor2u = .{}, -}; -pub const Theme = struct { - pub const current_rune = G.ansi.color.magenta; - pub const current = G.ansi.color.green; - pub const folded = G.ansi.bg_color.black2; - pub const headers = G.ansi.color.cyan; - pub const save = G.ansi.color.red; -}; -pub const CommandLine = struct { - text: [254]u8 = undefined, - used: usize = 0, -}; -pub const Debug = struct { - visible: bool = false, - pub fn draw (self: *Debug) !void { - if (self.visible == false) {return;} - const debug_lines = 3; - var buffer: [254]u8 = undefined; - try G.ansi.do(G.ansi.reset); - try G.ansi.do(G.ansi.cyrsor_style.hide); - try G.console.changeColor(G.ansi.color.blue2); - defer {G.ansi.do(G.ansi.cyrsor_style.show) catch {};} - - var print_offset: usize = G.console.size.y - 1 - debug_lines; - try G.console.cursorMove(.{ .x = 0, .y = print_offset }); - - { // view.offset - try G.console.rn(); - try G.console.out.print("view.offset .x = {d}, .y = {d}", .{G.editor.view.offset.x, G.editor.view.offset.y}); - try G.ansi.do(G.ansi.clear_to_end_line); - } - { // symbol - try G.console.rn(); - const used = G.editor.view.line.text.used; - if (G.editor.view.symbol >= used) {try G.console.out.print("symbol = {d} (null)", .{G.editor.view.symbol});} - else {try G.console.out.print("symbol = {d} ({c})", .{G.editor.view.symbol, G.editor.view.line.text.get()[G.editor.view.symbol]});} - try G.ansi.do(G.ansi.clear_to_end_line); - } - { // input - try G.console.rn(); - var buffer_pos: usize = 0; - var pos: usize = 0; - while (pos < 8) { - _ = G.lib.c.sprintf(&buffer[buffer_pos], "%02X", G.console.input.debug_buffer[pos]); - buffer_pos += 2; - pos += 1; - } - try G.console.out.writeAll(buffer[0..buffer_pos]); - try G.ansi.do(G.ansi.clear_to_end_line); - } - } - pub fn toggle (t: *Debug) void { - t.visible = !t.visible; - const editor = @fieldParentPtr(T, "debug", t); - editor.need_redraw = true; - } -}; - -// views -pub const View = @import("ViewFlat.zig"); -//pub const ViewFlat = @import("ViewFlat.zig"); -//pub const ViewTreeByBrackets = @import("ViewTreeByBrackets.zig"); -//pub const ViewTreeByIndent = @import("ViewTreeByIndent.zig"); -//pub const ViewEasyMotionH = @import("ViewEasyMotionH.zig"); -//pub const ViewEasyMotionV = @import("ViewEasyMotionV.zig"); -//pub const ViewFind = @import("ViewFind.zig"); -//pub const ViewGoTo = @import("ViewRunes.zig"); -//pub const ViewRunes = @import("ViewRunes.zig"); -//pub const ViewVim = @import("ViewVim.zig"); -//pub const ViewSelect = @import("ViewSelect.zig"); -//pub const ViewMultiCursor = @import("ViewSelect.zig"); -//pub const ViewHistory = @import("ViewHistory.zig"); -//pub const ViewDiff = @import("ViewHistory.zig"); - -// mem -arena_allocator: G.std.heap.ArenaAllocator, -arena: G.std.mem.Allocator, - -// beffers TODO: use bufferedLinkedAllocator -buffer_lines: LineBufferedAllocator = .{}, -//buffer_runes: BufferRunes, -//buffer_glyphs: BufferGlyphs, -//buffer_views: BufferViews, - -working: bool, -debug: Debug, -need_redraw: bool, -view: View, -path_to_clipboard: Line.Text, -usage_line: *Line, // TODO change to helpView -//current_view: *BufferView.Link - - -pub fn init (t: *T) !void { - t.arena_allocator = G.std.heap.ArenaAllocator.init(G.std.heap.page_allocator); - t.arena = t.arena_allocator.allocator(); - t.working = true; - t.need_redraw = true; - t.debug = .{}; - t.buffer_lines = .{}; - try t.buffer_lines.init(); - { // load usage text - const path = "help.txt"; - const text = @embedFile(path); - t.view.init(path, text) catch return error.ViewNotInit; - t.usage_line = t.view.lines; - } - t.updatePathToClipboard(); -} -pub fn deinit (t: *T) !void { - try t.buffer_lines.deinit(); - t.arena_allocator.deinit(); - try G.ansi.do(G.ansi.mouse.release); -} -pub fn do (t: *T) !bool { - try G.console.updateSize(); - try t.updateKeys(); - if (t.working == false) return false; - if (t.need_redraw == true) { - t.need_redraw = false; - try t.view.draw(); - try t.view.cursorMoveToCurrent(); - } - if (t.debug.visible == true) { - try G.editor.debug.draw(); - try t.view.cursorMoveToCurrent(); - } - G.std.time.sleep(draw_lag); - return true; -} -pub fn stop (t: *T) !void { - try G.console.cursorMove(.{.x = 0, .y = t.view.lines_drawing}); - t.need_redraw = false; - t.working = false; -} - -pub fn updatePathToClipboard (t: *T) void { - var len_c_int = G.lib.c.sprintf(&t.path_to_clipboard.buffer, "%s/clipboard.tmp", G.lib.c.getenv("HOME")); - var len = @intCast(usize, len_c_int); - t.path_to_clipboard.used = len; -} DELETED src/TODO.txt Index: src/TODO.txt ================================================================== --- src/TODO.txt +++ /dev/null @@ -1,28 +0,0 @@ -fix "go to line from number" to work without '&' (use loop from first line and flat_next in loop) { - add field num for Line struct; -} - -last changes: - abadoned: create "flat_next" and "flat_prev" fix used functions and test this - if I use ViewTree I still have to switch between different modes of operation. To do this, I have already separated Views and no additional complications are needed. - - -important: - use runes instead of lines - UTF-8 - fix ViewIndent - -improve usability: - one line mode - selections - text finding - -improve speed: - Change BufferedLinkedAllocator to just use allocated data as is. This no need push to linked list. - use buffer for file saving - -improve stability: - defragmentate lines in memory for deinit (if need free) - -not to do: - mouse scrolling - bad idea becouse i use scroling for view terminal history DELETED src/Text.zig Index: src/Text.zig ================================================================== --- src/Text.zig +++ /dev/null @@ -1,136 +0,0 @@ - -const G = @import("root"); -const T = @This(); - -const Self = @This(); -const std = @import("std"); -const Prog = @import("root"); -const Rune = @import("Rune.zig"); -const prog = Prog.prog; -const lib = Prog.lib; - -pub const size = 512; - -used: usize = 0, -buffer: [size]u8 = undefined, - -pub fn fromText (text: []const u8) !Self { - var self: Self = undefined; - self.used = 0; - try self.set(text); - return self; -} -pub fn get (self: *const T) []const u8 { - return self.buffer[0 .. self.used]; -} -pub fn getRunesCount (self: *const T, rune: u8) usize { // used for folding on brackets - var count: usize = 0; - var text: []const u8 = self.get(); - for (text) |r| { - if (r == rune) count += 1; - } - return count; -} -pub fn find (self: *const T, text: []const u8, start_pos: usize) ?usize { // pos - const self_text = self.get(); - if (self.used < text.len) return null; - if (self.used < start_pos) return null; - var pos: usize = start_pos; - while (true) { - if (self.used - pos < text.len) return null; - if (G.textLib.cmp(self_text, text) == .equal) return pos; - pos += 1; - if (pos >= self.used) return null; - } -} -pub fn add (self: *T, rune: u8) !void { - if (self.used >= size) unreachable; - if (self.used == size - 1) return error.LineIsFull; - self.buffer[self.used] = rune; - self.used += 1; -} -pub fn set (self: *T, text: []const u8) !void { - if (text.len > size) return error.TextIsToLong; - std.mem.copy(u8, self.buffer[0..], text); - self.used = text.len; -} -pub fn insert (self: *T, pos: usize, rune: u8) !void { - if (self.used > size) unreachable; - if (pos > size) unreachable; - if (self.used == size - 1) return error.LineIsFull; - if (pos > self.used) return error.UnexpectedPos; - if (pos < self.used) { // shiftSymbolsToRight - const from = self.buffer[pos .. self.used ]; - const dest = self.buffer[pos + 1 .. self.used + 1]; - std.mem.copyBackwards(u8, dest, from); - } - self.buffer[pos] = rune; - self.used += 1; -} -pub fn delete (self: *T, pos: usize) !void { - if (self.used > size) unreachable; - if (self.used == 0) return error.LineIsEmpty; - if (pos > size - 1) unreachable; - if (pos > self.used - 1) return error.UnexpectedPos; - if (pos != self.used - 1) { // shiftSymbolsToLeft - const from = self.buffer[pos + 1 .. self.used ]; - const dest = self.buffer[pos .. self.used - 1]; - std.mem.copy(u8, dest, from); - } - self.used -= 1; -} // end fn -pub fn getSantieled (self: *T) [:0]const u8 { - self.buffer[self.used] = 0; - return self.buffer[0 .. self.used :0]; -} -// { indents - pub fn countIndent (self: *const T, tabsize: usize) usize { - var count: usize = 0; - var text = self.get(); - for (text) |r| { - switch(r) { - ' ' => count += 1, - '\t' => count += tabsize, - else => break, - } - } - return count; - } - pub fn countNonIndent (self: *const T) usize { - const indent = self.countIndent(1); - return self.used - indent; - } - pub fn addIndent (self: *T, count: usize) !void { - const last_indent = self.countIndent(1); - const last_start = last_indent; - const last_end = self.used; - const new_start = last_indent + count; - const new_end = self.used + count; - if (new_end > size - 1) return error.LineIsFull; - std.mem.copyBackwards(u8, self.buffer[new_start .. new_end], self.buffer[last_start .. last_end]); - for (self.buffer[last_indent .. last_indent + count]) |*rune| rune.* = ' '; // fill spaces - self.used = new_end; - } - pub fn removeIndent (self: *T, count: usize) !void { - const last_indent = self.countIndent(1); - if (last_indent < count) return error.CountIsBiggerThanExistIndent; - const last_start = last_indent; - const last_end = self.used; - const new_start = last_indent - count; - const new_end = self.used - count; - std.mem.copy(u8, self.buffer[new_start .. new_end], self.buffer[last_start .. last_end]); - self.used = new_end; - } - pub fn changeIndent (self: *T, new_indent: usize) !void { - const indent = self.countIndent(1); - if (new_indent == indent) {return;} - else if (new_indent > indent) { - const delta = new_indent - indent; - try self.addIndent(delta); - } - else { // new_indent < indent - const delta = indent - new_indent; - try self.removeIndent(delta); - } - } -// } DELETED src/View.zig.bak Index: src/View.zig.bak ================================================================== --- src/View.zig.bak +++ /dev/null @@ -1,1517 +0,0 @@ - -const G = @import("root"); -const T = @This(); - -const Text = G.ScalpiEditor.Text; -const Window = G.ScalpiEditor.Window; -const Line = G.ScalpiEditor.Line; -const Rune = G.ScalpiEditor.Rune; -const Theme = G.ScalpiEditor.Theme; -const draw_lag = G.ScalpiEditor.draw_lag; - -// todo: replace this: -const Self = @This(); -const View = @This(); -const lib = G.lib; -const ansi = G.ansi; -const std = G.std; -const Console = G.Console; - -pub const Indent = struct { - pub const IndentType = enum { - space, - tab, - }; - indent_type: IndentType = .space, - size: usize = 4, -}; -pub const Mode = enum { - edit, - to_find, - to_line, - history, - select, - normal, - easy_motion_vertical, - easy_motion_horizontal, -}; -pub const FoldMode = enum { - byNone, - byBrackets, - byIndent, -}; - -// { fields - file_name: Text = .{}, - window: Window = .{.size = .{.x=3, .y=1}, .pos = .{.x=0, .y=0}}, - - // modes - mode: Mode = .edit, - foldMode: FoldMode = .byNone, - indent: Indent = .{}, - - selected: usize = 0, - - lines: *Line = undefined, - line: *Line = undefined, // current working line - bakup_line: *Line = undefined, - last_working_line: ?*Line = null, - marked_line: ?*Line = null, - lines_drawing: usize = 0, - - // current pos - offset: lib.Coor2u = .{.x = 0, .y = 3 }, - symbol: usize = 0, - - to_find: ?*Line = null, - to_goto: ?*Line = null, - cutted: ?*Line = null, -// } -// { methods - pub fn correntOffset (t: *T) void { - if (t.symbol >= 8) t.offset.x = 8; - } - pub fn fromAlloc () !*View { - const allocated = lib.c.aligned_alloc(8, @sizeOf(View)) orelse return error.NeedMoreMemory; - var view: *View = @ptrCast(*View, @alignCast(8, allocated)); - return view; - } - pub fn init (self: *T, file_name: []const u8, text: []const u8) !void { - self.* = .{}; - self.file_name.set(file_name) catch unreachable; - self.lines = try G.editor.buffer_lines.create(); - parse_text_to_lines: { - if (text.len == 0) break :parse_text_to_lines; - var line_num: usize = 0; - var line: *Line = self.lines; - var start_line: usize = 0; - var data_pos: usize = 0; - while (true) { // find first '\n' - if (data_pos > text.len - 1) { - const end_line: usize = data_pos; - line.text.set(text[start_line..end_line]) catch { - return error.LineIsToLong; - }; - line_num += 1; - break :parse_text_to_lines; - } - else if (text[data_pos] == '\n') { - const end_line: usize = data_pos; - if (end_line > start_line) { - line.text.set(text[start_line..end_line]) catch { - return error.LineIsToLong; - }; - } - start_line = end_line + 1; - line_num += 1; - data_pos += 1; - break; - } - data_pos += 1; - } - while (true) { // find other '\n' - if (data_pos > text.len - 1) { - const end_line: usize = data_pos; - if (end_line > start_line) { - const new_line = try G.editor.buffer_lines.create(); - new_line.text.set(text[start_line..end_line]) catch { - return error.LineIsToLong; - }; - line.pushNext(new_line); - line = new_line; - } - start_line = end_line + 1; - line_num += 1; - break; - } - else if (text[data_pos] == '\n') { - const end_line: usize = data_pos; - if (end_line > start_line) { - const new_line = try G.editor.buffer_lines.create(); - new_line.text.set(text[start_line..end_line]) catch { - return error.LineIsToLong; - }; - line.pushNext(new_line); - line = new_line; - } - else { - const new_line = try G.editor.buffer_lines.create(); - line.pushNext(new_line); - line = new_line; - } - start_line = end_line + 1; - line_num += 1; - } - data_pos += 1; - } // end while - } - self.line = self.lines; - self.bakup_line = try G.editor.buffer_lines.create(); - } // end fn loadLines - pub fn save (self: *T) !void { - try ansi.do(ansi.cyrsor_style.hide); - defer ansi.do(ansi.cyrsor_style.show) catch {}; - G.editor.need_redraw = false; - - { // change status - try G.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(Theme.save); - try G.console.out.writeAll("saving..."); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - // { create file - var cwd = std.fs.cwd(); - var file = try cwd.createFile(self.file_name.get(), .{}); - defer file.close(); - const writer = file.writer(); - // } - // { write - try ansi.do(Theme.save); - var line: *Line = self.lines; - var count: usize = 0; - writing: while (true) { - { // change status - try G.console.cursorMove(.{ .x = 0, .y = 0 }); - try G.console.out.print("{} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - const text = line.text.get(); - try writer.writeAll(text); - count += 1; - if (line.child) |child| { - try writer.writeAll("\n"); - line = child; - } - else if (line.next) |next| { - try writer.writeAll("\n"); - line = next; - } - else { // get parent with next - while (true) { - line = line.getParent() orelse break :writing; - line = line.next orelse continue; - try writer.writeAll("\n"); - break; - } // end while - } // end else - } // end while - // } - { // change status - try G.console.cursorMove(.{ .x = 0, .y = 0 }); - defer self.cursorMoveToCurrent() catch {}; - - try ansi.do(Theme.save); - defer ansi.do(ansi.reset) catch {}; - - try G.console.out.print("file saved. {} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - } - pub fn changeMode (t: *T, mode: Mode) !void { - switch (mode) { - .edit => {}, - .to_find => { - t.last_working_line = t.line; - }, - .to_line => { - t.last_working_line = t.line; - if (t.to_goto == null) { // create - const new_line = G.editor.buffer_lines.create() catch return; - t.to_goto = new_line; - } - t.line = t.to_goto.?; - t.goToEndOfLine(); - G.editor.need_redraw = true; - }, - .history => {}, - .select => {}, - .normal => {}, - .easy_motion_vertical => { - try t.draw_vertical_help_motion(); - }, - .easy_motion_horizontal => { - try t.draw_horizontal_help_motion(); - }, - } - t.mode = mode; - } - pub fn cursorMoveToCurrent (self: *T) !void { - try G.console.cursorMove(.{ .x = self.offset.x, .y = self.offset.y }); - } - pub fn goToHelp (self: *T) !void { - self.line = G.editor.usage_line; - self.offset.y = 0; - G.editor.need_redraw = true; - } - // { mark - pub fn markThisLine (self: *Self) void { - self.marked_line = self.line; - } - pub fn goToMarked (self: *Self) void { - if (self.marked_line) |mark| { - self.line = mark; - G.editor.need_redraw = true; - } - } - // } - // { edit - // block - pub fn duplicate (self: *T) void { - const first = self.line; - const copy_first = G.editor.buffer_lines.create() catch return; - copy_first.text.set(first.text.get()) catch unreachable; - self.line.pushNext(copy_first); - if (first.child) |first_child| { - var current = first_child; - var copy_current = G.editor.buffer_lines.create() catch return; - copy_current.text.set(current.text.get()) catch unreachable; - copy_current.parent = copy_first; - copy_first.child = copy_current; - copying: while (true) { - if (current.child) |child| { - var copy_child = G.editor.buffer_lines.create() catch return; - copy_child.text.set(child.text.get()) catch unreachable; - copy_child.parent = copy_current; - copy_current.child = copy_child; - current = child; - copy_current = copy_child; - } - else if (current.next) |next| { - var copy_next = G.editor.buffer_lines.create() catch return; - copy_next.text.set(next.text.get()) catch unreachable; - copy_next.prev = copy_current; - copy_current.next = copy_next; - current = next; - copy_current = copy_next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - if (current == first) break: copying; - copy_current = copy_current.getParent() orelse unreachable; - next = current.next orelse continue; - break; - } - var copy_next = G.editor.buffer_lines.create() catch return; - copy_next.text.set(next.text.get()) catch unreachable; - copy_next.prev = copy_current; - copy_current.next = copy_next; - current = next; - copy_current = copy_next; - } - } - } - self.line = copy_first; - G.editor.need_redraw = true; - } - pub fn cut (self: *T) !void { - const t = self; - - // fix parent - if (self.line.parent) |parent| { - parent.child = self.line.next; - } - - // get next_selected_line - var next_selected_line: *Line = undefined; - // { select next selected line - if (self.line.next) |next| { - next_selected_line = next; - } - else if (self.line.prev) |prev| { - next_selected_line = prev; - } - else if (self.line.parent) |parent| { - next_selected_line = parent; - } - else { - // create empty prev line - const last_symbol = self.symbol; - const last_offset = self.offset.x; - try self.addPrevLine(); - try self.line.changeIndentToCutie(); - next_selected_line = self.line; - self.goToNextLine(); - self.symbol = last_symbol; - self.offset.x = last_offset; - } - // } - if (self.lines == self.line) self.lines = next_selected_line; - - // cut - const line = self.line; - //{ change links - if (line.prev) |prev| { - prev.next = line.next; - } - if (line.next) |next| { - next.prev = line.prev; - } - if (line.parent) |parent| { - parent.child = line.next; - if (line.next) |next| { - next.parent = parent; - } - } - line.prev = null; - line.next = null; - line.parent = null; - //} - //{ add to cutted - line.next = t.cutted; - t.cutted = line; - //} - - // - self.line = next_selected_line; - G.editor.need_redraw = true; - self.bakup(); - } - pub fn pasteLine (t: *T) void { - if (t.cutted) |cutted| { // todo: change this to *cutted - t.cutted = cutted.next; - cutted.next = null; - t.line.pushPrev(cutted); - if (t.lines == t.line) t.lines = cutted; - t.offset.y += 1; - t.goToPrevLine(); - t.indentToCutie(); - } - G.editor.need_redraw = true; - } - - // line - pub fn joinLines (self: *T) !void { - if (self.line.child) |_| return; - const next = self.line; - const prev = self.line.prev orelse return; - - self.deleteIndent(); - - const next_used = next.text.used; - const prev_used = prev.text.used; - - if (prev_used + next_used > Line.Text.size - 3) return; - std.mem.copy(u8, prev.text.buffer[prev.text.used..], next.text.get()); - prev.text.used += next_used; - try self.line.pop(); - try G.editor.buffer_lines.free(self.line); - self.line = prev; - self.goToSymbol(prev_used); - } - pub fn clearLine (self: *T) void { - self.line.text.used = 0; - self.goToStartOfLine(); - G.editor.need_redraw = true; - } - pub fn addPrevLine (self: *T) !void { - const new_line = try G.editor.buffer_lines.create(); - self.line.pushPrev(new_line); - if (self.lines == self.line) self.lines = new_line; - self.goToPrevLine(); - self.goToStartOfLine(); - G.editor.need_redraw = true; - } - pub fn addNextLine (self: *T) !void { - const new_line = try G.editor.buffer_lines.create(); - self.line.pushNext(new_line); - self.goToNextLine(); - self.goToStartOfLine(); - G.editor.need_redraw = true; - } - pub fn divide (self: *T) !void { - const indent = self.line.text.countIndent(1); - if (self.symbol <= indent) { // just add prev line - const last_symbol = self.symbol; - const last_offset = self.offset.x; - try self.addPrevLine(); - try self.line.changeIndentToCutie(); - self.goToNextLine(); - self.symbol = last_symbol; - self.offset.x = last_offset; - } - else if (self.symbol >= self.line.text.used) { // just add next line - if (self.line.text.buffer[self.symbol - 1] == ':') { - if (self.line.child) |_| return; - const new_line = G.editor.buffer_lines.create() catch return; - // { link - self.line.child = new_line; - new_line.parent = self.line; - // } - self.goToIn(); - } - else { - try self.addNextLine(); - } - } - else if (self.line.text.buffer[self.symbol] == '}' and self.line.text.buffer[self.symbol - 1] == '{') { - if (self.line.child != null) return; - const pos = self.symbol; - const last_line = self.line; - - const new_line = G.editor.buffer_lines.create() catch return; - // { link - self.line.child = new_line; - new_line.parent = self.line; - // } - // { copy text and fill spaces - const text_to_new_line = last_line.text.get()[pos..]; - std.mem.copy(u8, new_line.text.buffer[indent..], text_to_new_line); - for (new_line.text.buffer[0 .. indent]) |*rune| rune.* = ' '; // spam spaces - new_line.text.used = indent + text_to_new_line.len; - last_line.text.used = pos; - // } - - self.line = new_line; - try self.addPrevLine(); - } - else { - if (self.line.child) |_| return; - var parent = self.line; - var pos = self.symbol; - const text = self.line.text.get()[pos..]; - try self.addNextLine(); - self.line.text.used = indent + text.len; - std.mem.copy(u8, self.line.text.buffer[indent..], text); - for (self.line.text.buffer[0..indent]) |*rune| rune.* = ' '; - parent.text.used = pos; - } - self.indentToCutie(); - self.goToStartOfText(); - if (false) { // change status (debug) - const last_cursor_pos: lib.Coor2u = G.console.cursor.pos; - defer { // reset color, clear line, restore cursor pos and flush - defer Console.Output.print(ansi.reset); - Console.Output.print(ansi.clear_to_end_line); - defer G.console.cursorMove(last_cursor_pos); - Console.Output.flush(); - } - - G.console.cursorMove(.{ .x = 0, .y = 0 }); - Console.Output.print(ansi.color.red2); - - var buffer: [254]u8 = undefined; - var text_len: usize = 0; - var sprintf_result = lib.c.sprintf(&buffer, "line used = %d", self.line.text.used); - text_len += @intCast(usize, sprintf_result); - G.console.print(buffer[0 .. text_len]); - } - self.correntOffset(); - G.editor.need_redraw = true; - } - pub fn swapWithBottom (self: *T) !void { - if (self.line.next) |_| { - try self.cut(); - self.goToNextLine(); - self.pasteLine(); - } - G.editor.need_redraw = true; - } - pub fn swapWithUpper (self: *T) !void { - if (self.line.prev) |_| { - try self.cut(); - self.goToPrevLine(); - self.pasteLine(); - } - G.editor.need_redraw = true; - } - pub fn deleteLine (self: *T) void { - const line = self.line; - - // get next_selected_line - var next_selected_line: *Line = undefined; - if (line.next) |next| { - next_selected_line = next; - } - else if (line.prev) |prev| { - next_selected_line = prev; - } - else if (line.parent) |parent| { - next_selected_line = parent; - } - else { // clear and exit - self.clearLine(); - G.editor.need_redraw = true; - return; - } - self.clearLine(); - if (self.lines == self.line) self.lines = next_selected_line; - - line.pop(); - try G.buffer_lines.free(line); - - self.line = next_selected_line; - G.editor.need_redraw = true; - } - - // word - pub fn deleteWord (self: *T) !void { - if (self.symbol > self.line.text.used) {return;} - while(true) { // delete current symbol - if (self.symbol == self.line.text.used) {break;} - const next_symbol = self.line.text.buffer[self.symbol]; - if (G.textLib.isLetter(next_symbol)) {self.deleteSymbol();} else {break;} - } - while(true) { // delete prev symbol - if (self.symbol == 0) {break;} - const prev_symbol = self.line.text.buffer[self.symbol - 1]; - if (G.textLib.isLetter(prev_symbol)) { - try self.deletePrevSymbol(); - } - else {break;} - } - G.editor.need_redraw = true; - } - - // symbol - pub fn insertSymbol (self: *T, rune: u8) !void { - if (self.symbol > self.line.text.used) self.goToSymbol(self.line.text.used); - try self.line.text.insert(self.symbol, rune); - self.goToNextSymbol(); - G.editor.need_redraw = true; - } // end fn - pub fn deleteSymbol (self: *T) void { - if (self.line.text.used == 0) return; - self.line.text.delete(self.symbol) catch return; - G.editor.need_redraw = true; - } - pub fn deletePrevSymbol (self: *T) !void { - switch (self.symbol) { - 0 => { - if (self.line.parent) |_| return; - if (self.line.child) |_| return; - if (self.line == self.lines) return; - - const prev = self.line.prev orelse return; - - const non_indent = self.line.text.countNonIndent(); - if (non_indent == 0) { // delete self line - try self.line.pop(); - try G.editor.buffer_lines.free(self.line); - self.line = prev; - G.editor.need_redraw = true; - return; - } - - const prev_count = prev.text.countNonIndent(); - switch (prev_count) { - 0 => { // delete prev - if (self.lines == prev) self.lines = self.line; - try prev.pop(); - try G.editor.buffer_lines.free(prev); - G.editor.need_redraw = true; - return; - }, - else => { // join line - try self.joinLines(); - }, - } - }, - else => { - if (self.line.text.used == 0) return; - self.goToPrevSymbol(); - self.deleteSymbol(); - }, - } - G.editor.need_redraw = true; - } - //} - // { draw - pub fn draw (self: *Self) !void { - if (self.offset.x >= G.console.size.x) self.offset.x = 0; - if (self.offset.y >= G.console.size.y) self.offset.y = 0; - if (self.symbol < self.offset.x) { // unexpected - self.offset.x = 0; - self.symbol = 0; - } - try ansi.do(ansi.cyrsor_style.hide); - defer ansi.do(ansi.cyrsor_style.show) catch {}; - switch (self.mode) { - .easy_motion_vertical, - .easy_motion_horizontal, - .edit => { - defer self.cursorMoveToCurrent() catch {}; - - // draw edit line - try G.console.cursorMove(.{ .x = 0, .y = self.offset.y }); - defer self.cursorMoveToCurrent() catch {}; - try self.drawEditedLine(); - - // draw other lines - if (G.console.size.y <= 1) return; - try self.drawUpperLines(); - try self.drawDownerLines(); - }, - .to_line => { - self.offset.y = 1; - - // draw banner - try G.console.changeColor(Theme.headers); - try G.console.cursorMove(.{ .x = 0, .y = 0}); - try G.console.out.writeAll("enter the line you want to jump to:"); - try ansi.do(ansi.clear_to_end_line); - - // draw edit line - try G.console.cursorMove(.{ .x = 0, .y = 1}); - defer self.cursorMoveToCurrent() catch {}; - try self.drawEditedLine(); - - var pos_y: usize = 2; - while (true) { // clear other downer lines - if (pos_y >= G.console.size.y) return; - try G.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - pos_y += 1; - std.time.sleep(draw_lag); - } - }, - //.to_find, - //.history, - //.select, - //.normal, - else => {}, - } - } // end draw lines - pub fn drawUpperLines (self: *Self) !void { - if (self.offset.y == 0) return; - var pos_y: usize = self.offset.y - 1; - var line: *Line = self.line; - while (true) { // draw lines - line = line.prev orelse break; - try G.console.cursorMove(.{ .x = 0, .y = pos_y }); - try self.drawLine(line); - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - while (true) { // draw parents - line = line.getParent() orelse break; - try G.console.cursorMove(.{ .x = 0, .y = pos_y }); - try self.drawParentLine(line); - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - try ansi.do(ansi.reset); - while (true) { // clear other upp lines - try G.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - } - pub fn drawDownerLines (self: *Self) !void { - var pos_y: usize = self.offset.y + 1; - var line: *Line = self.line; - if (pos_y >= G.console.size.y) return; - while (true) { // draw lines - line = line.next orelse break; - try G.console.cursorMove(.{ .x = 0, .y = pos_y }); - try self.drawLine(line); - if (pos_y >= G.console.size.y - 1) { - self.lines_drawing = G.console.size.y; - return; - } - pos_y += 1; - std.time.sleep(draw_lag); - } - self.lines_drawing = pos_y; - try ansi.do(ansi.reset); - while (true) { // clear other downer lines - try G.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y >= G.console.size.y - 1) return; - pos_y += 1; - std.time.sleep(draw_lag); - } - } - pub fn drawLine (self: *Self, line: *Line) !void { - - // change color - try ansi.do(ansi.reset); - if (line.child) |_| {try G.console.changeBgColor(ansi.bg_color.black2);} - - - if (line.text.used == 0) { - try ansi.do(ansi.clear_line); - return; - } - - // draw left-to-right from first visible rune - try G.console.cr(); - const text = line.text.get(); - if (self.symbol < self.offset.x) { // unexpected - self.offset.x = 0; - self.symbol = 0; - G.editor.need_redraw = true; - return; - } - var pos: usize = self.symbol - self.offset.x; // first visible rune - var offset_x: usize = 0; - while (true) { - if (pos >= text.len) break; - if (offset_x >= G.console.size.x - 1) break; - try G.console.out.writeByte(text[pos]); - pos += 1; - offset_x += 1; - } - try ansi.do(ansi.clear_to_end_line); - - } - pub fn drawEditedLine (self: *Self) !void { - //const editor = @fieldParentPtr(G.ScalpiEditor, "view", self); - // change color - try ansi.do(ansi.reset); - var text_color: []const u8 = Theme.current; - if (self.line.child) |_| {try ansi.do(ansi.bg_color.black2);} - - if (self.line.text.used == 0) { - try ansi.do(ansi.clear_line); - return; - } - - // draw left-to-right from first visible rune - try G.console.cr(); - const text = self.line.text.get(); - var pos: usize = self.symbol - self.offset.x; - var offset_x: usize = 0; - if (pos > 0) { // draw '<' - try ansi.do(ansi.color.magenta); - try G.console.out.writeByte('<'); - pos += 1; - offset_x += 1; - } - //{ left symbols - try ansi.do(text_color); - while (true) { - if (offset_x >= self.offset.x) break; - if (offset_x >= G.console.size.x - 1) break; - if (pos >= text.len) break; - try G.console.out.writeByte(text[pos]); - pos += 1; - offset_x += 1; - } - //} - //{ current symbol. maybe inverse cursour? - if (offset_x >= G.console.size.x - 2) return; - try G.console.changeColor(Theme.current_rune); - if (pos < text.len) {try G.console.out.writeByte(text[pos]);} - pos += 1; - offset_x += 1; - //} - //{ right symbols - try G.console.changeColor(text_color); - while (true) { - if (offset_x >= G.console.size.x - 2) break; - if (pos >= text.len) break; - try G.console.out.writeByte(text[pos]); - pos += 1; - offset_x += 1; - } - //} - if (pos < text.len) { // draw '>' - try G.console.changeColor(ansi.color.magenta); - try G.console.out.writeByte('>'); - } - else { - try ansi.do(ansi.clear_to_end_line); - } - - } // drawEditedLine - pub fn drawParentLine (self: *Self, parent: *Line) !void { - // change color - try ansi.do(ansi.reset); - try G.console.changeColor(Theme.headers); - - // draw - try G.console.cr(); - const text = parent.text.get(); - var indent = parent.text.countIndent(1); - var symbol: usize = indent; - if (indent >= self.symbol - self.offset.x) {symbol = self.symbol - self.offset.x;} - var offset_x: usize = 0; - while (true) { - if (symbol >= text.len) { - try ansi.do(ansi.clear_to_end_line); - break; - } - if (offset_x >= G.console.size.x - 2) break; - try G.console.out.writeByte(text[symbol]); - - symbol += 1; - offset_x += 1; - } - try ansi.do(ansi.clear_to_end_line); - } - // } - // { navigation - // over lines - pub fn goToRoot (self: *Self) void { - self.line = self.lines; - self.offset.y = 5; - self.goToStartOfLine(); - G.editor.need_redraw = true; - self.bakup(); - } - pub fn goToPrevLine (self: *Self) void { - if (self.line.prev) |prev| { - self.line = prev; - G.editor.need_redraw = true; - } - else {return;} - if (self.offset.y > 5) {self.offset.y -= 1;} - self.bakup(); - } // end fn - pub fn goToNextLine (self: *Self) void { - self.line = self.line.next orelse return; - self.bakup(); - G.editor.need_redraw = true; - if (self.offset.y < G.console.size.y - 1) self.offset.y += 1; - // { correct offset_y: - if (G.console.size.y <= 5) return; - // count downest_lines - var count_to_downest_line: usize = 0; - var line: *Line = self.line; - while (count_to_downest_line < 5) { - if (line.next) |down_next| { - count_to_downest_line += 1; - line = down_next; - } - else {break;} - } - - if (G.console.size.y - self.offset.y < count_to_downest_line) { - self.offset.y = G.console.size.y - count_to_downest_line; - } - //} - } // end fn - pub fn goToFirstLine (self: *Self) void { - while (self.line.prev) |_| self.goToPrevLine(); - self.goToStartOfLine(); - G.editor.need_redraw = true; - self.bakup(); - } - pub fn goToLastLine (self: *Self) void { - while (self.line.next) |_| self.goToNextLine(); - G.editor.need_redraw = true; - self.bakup(); - } - // { go to line from number - pub fn getLineNum (self: *View) usize { - return (@ptrToInt(self.line) - @ptrToInt(&G.editor.buffer.lines)) / @sizeOf(Line); - } - pub fn goToLineFromNumber (self: *View, _num: usize) void { - var num: usize = _num + G.editor.buffer_lines.lineToPos(self.lines) - 1; - self.line = &G.editor.buffer_lines.lines[num]; - self.goToSymbol(self.line.text.countIndent(1)); - self.correntOffset(); - self.offset.y = 6; - G.editor.need_redraw = true; - self.bakup(); - } - pub fn goToLineFromInput (self: *View) !void { - if (self.line.text.used == 0) return; - var num: usize = @truncate(usize, G.textLib.u64FromCharsDec(self.line.text.get()) catch return); - try self.changeMode(.edit); - self.goToLineFromNumber(num); - } - // } - - // over line - pub fn goToStartOfLine (self: *Self) void { - self.symbol = 0; - self.offset.x = 0; - G.editor.need_redraw = true; - } - pub fn goToEndOfLine (self: *Self) void { - self.symbol = self.line.text.used; - if (self.symbol > G.console.size.x - 2) {self.offset.x = G.console.size.x - 2;} - else {self.offset.x = self.symbol;} - G.editor.need_redraw = true; - } - pub fn goToStartOfText (self: *Self) void { - const indent = self.line.text.countIndent(1); - self.goToSymbol(indent); - } - pub fn CtrlShiftLeft (self: *Self) void { - const indent = self.line.text.countIndent(1); - if (self.symbol > indent) { - self.goToSymbol(indent); - self.correntOffset(); - } - else self.goToStartOfLine(); - G.editor.need_redraw = true; - } - pub fn CtrlShiftRight (self: *Self) void { - const indent = self.line.text.countIndent(1); - if (self.symbol < indent) self.goToSymbol(indent) - else self.goToEndOfLine(); - G.editor.need_redraw = true; - } - - // over word - pub fn goToStartOfWord (self: *Self) void { - if (self.symbol == 0) {return;} - if (self.symbol > self.line.text.used) {self.goToSymbol(self.line.text.used);} - const first_rune = self.line.text.buffer[self.symbol]; - if (first_rune == ' ') { - self.goToPrevSymbol(); - while (true) { - if (self.symbol == 0) {break;} - const rune = self.line.text.buffer[self.symbol]; - if (rune != ' ') break; - self.goToPrevSymbol(); - } - } - else { - self.goToPrevSymbol(); - while(true) { - if (self.symbol == 0) {break;} - const next_symbol = self.line.text.buffer[self.symbol - 1]; - switch(next_symbol){ - ' ', '\t', '\\', - '=', '+', '-', '/', '*', '^', - '!', '@', '#', '$', '%', '&', - '(', ')', '[', ']', '{', '}', - '"', '\'', - ';', ':', '.', ',' - => {break;}, - else => {}, - } - self.goToPrevSymbol(); - } - } - G.editor.need_redraw = true; - } - pub fn goToEndOfWord (self: *Self) void { - if (self.symbol >= self.line.text.used) {return;} - const first_rune = self.line.text.buffer[self.symbol]; - if (first_rune == ' ') { - while(true) { - self.goToNextSymbol(); - if (self.symbol >= self.line.text.used) {break;} - const rune = self.line.text.buffer[self.symbol]; - if (rune != ' ') break; - } - } - else while(true) { - self.goToNextSymbol(); - if (self.symbol >= self.line.text.used) {break;} - const rune = self.line.text.buffer[self.symbol]; - switch(rune){ - ' ', '\t', '\\', - '=', '+', '-', '/', '*', '^', - '(', ')', '[', ']', '{', '}', - '!', '@', '#', '$', '%', '&', - '"', '\'', - ';', ':', '.', ',' - => {break;}, - else => {}, - } - } - G.editor.need_redraw = true; - } - - // over symbols - pub fn goToSymbol (self: *Self, pos: usize) void { - self.symbol = pos; - if (self.symbol > G.console.size.x - 2) { - self.offset.x = G.console.size.x - 2; - } - else {self.offset.x = self.symbol;} - } - pub fn goToPrevSymbol (self: *Self) void { - const used = self.line.text.used; - if (self.symbol == 0) { - if (true) return; - if (self.line.prev) |_| { - self.goToPrevLine(); - self.goToEndOfLine(); - } - return; - } - if (self.symbol > used) { - self.symbol = used; - if (used < G.console.size.x - 1) self.offset.x = self.line.text.used; - G.editor.need_redraw = true; - return; - } - if (self.symbol > 0) self.symbol -= 1; - if (self.symbol >= 10) {if (self.offset.x > 10) {self.offset.x -= 1;}} - else {if (self.offset.x > 0) self.offset.x -= 1;} - G.editor.need_redraw = true; - } - pub fn goToNextSymbol (self: *Self) void { - const used = self.line.text.used; - if (self.symbol >= used) { - if (true) return; - if (self.line.next) |_| { - self.goToNextLine(); - self.goToStartOfLine(); - } - return; - } - if (self.symbol < Line.Text.size - 1) self.symbol += 1; - if (used - self.symbol >= 10) { - if (self.offset.x < G.console.size.x - 12) self.offset.x += 1; - } - else { - if (self.offset.x < G.console.size.x - 2) self.offset.x += 1; - } - G.editor.need_redraw = true; - } - - // { easy motion - pub fn draw_horizontal_help_motion (self: *Self) !void { - var pos: usize = 0; - var rune: u8 = 0x61; - try ansi.do(ansi.color.magenta); - while(true) { - try G.console.cursorMove(.{ .x = pos, .y = self.offset.y }); - try G.console.out.writeByte(rune); - if (rune >= 0x7A) break; rune += 1; - if (pos >= G.console.size.x - 3) break; pos += 3; - } - try self.cursorMoveToCurrent(); - } - pub fn draw_vertical_help_motion (self: *Self) !void { - var pos: usize = 0; - try ansi.do(ansi.color.magenta); - while(true) { - try G.console.cursorMove(.{ .x = self.offset.x, .y = pos }); - try G.console.out.writeByte(0x61 + @truncate(u8, pos)); - if (pos >= 0x7A - 0x61) break; - if (pos == G.console.size.y - 1) break; - pos += 1; - } - try self.cursorMoveToCurrent(); - } - pub fn easyMotionHorizontal (self: *Self, key: u8) !void { - var pos = key - 0x61; - self.goToSymbol(self.symbol - self.offset.x + pos * 3); - try self.changeMode(.edit); - G.editor.need_redraw = true; - } - pub fn easyMotionVertical (self: *Self, key: u8) !void { - var pos = key - 0x61; - if (self.offset.y == pos) {} - else if (self.offset.y > pos) { - var i = self.offset.y - pos; - while (i > 0) : (i -= 1) { - self.goToPrevLine(); - } - } - else { // (self.offset.y < pos) - var i = pos - self.offset.y; - while (i > 0) : (i -= 1) { - self.goToNextLine(); - } - } - try self.changeMode(.edit); - G.editor.need_redraw = true; - } - // } - //} - // { folding - pub fn unFold (self: *Self) void { - var current = self.lines; - while (true) { - if (current.child) |child| { - current.child = null; - child.parent = null; - //{ insert range child..last into current and current.next - if (current.next) |current_next| { // tie last_child <-> current_next - var last_child: *Line = child; - while (true) { // find last_child - if (last_child.next) |next| { - last_child = next; - } else break; - } // end while - last_child.next = current_next; - current_next.prev = last_child; - } // end if - //{ tie child <-> current - child.prev = current; - current.next = child; - //} - //} end insert into last and current.next - } // end if current_line.child - if (current.next) |next| { - current = next; - continue; - } - break; - } // end while - G.editor.need_redraw = true; - } // end fn - pub fn foldFromBrackets (self: *Self) void { - self.unFold(); - var current: ?*Line = self.lines; - while (current) |line| { - var close_count = line.text.getRunesCount('}'); // **{ - var open_count = line.text.getRunesCount('{'); // **} - if (open_count == close_count) { - current = line.next; - } - else if (open_count > close_count) { - if (line.next) |next| { - next.parent = line; - line.child = next; - line.next = null; - next.prev = null; - } - current = line.child; - } - else { // for close_count > open_count - if (line.getParent()) |parent| { - if (line.next) |next| { - next.prev = parent; - } - parent.next = line.next; - current = line.next; - line.next = null; - } - else { // unexpected - current = line.next; - continue; - } - } - } - G.editor.need_redraw = true; - self.foldMode = .byBrackets; - } - pub fn foldFromIndent (self: *Self) !void { - self.unFold(); - - // printing - try G.console.changeColor(Theme.save); - defer ansi.do(ansi.reset) catch {}; - try G.console.cursorMove(.{ .x = 0, .y = 0 }); - try G.console.out.writeAll("folding... FIX ME!!"); - try ansi.do(ansi.clear_to_end_line); - - // iterate over flat items layer - var current = self.line; - while(true) { - const next = current.next orelse break; - current = next; - } - - self.foldMode = .byIndent; - G.editor.need_redraw = false; - } - - pub fn goToIn (self: *Self) void { - const child = self.line.child orelse return; - const child_indent = child.text.countIndent(1); - self.goToSymbol(child_indent); - self.symbol = child_indent; - self.line = child; - if (G.console.size.y > 6) {self.offset.y = 6;} - else if (G.console.size.y > 3) {self.offset.y = 3;} - else if (G.console.size.y > 1) {self.offset.y = 1;} - else {self.offset.y = 0;} - self.bakup(); - self.correntOffset(); - G.editor.need_redraw = true; - } - pub fn goToOut (self: *Self) void { - if (self.line.getParent()) |parent| { - const parent_indent = parent.text.countIndent(1); - self.line = parent; - self.goToSymbol(parent_indent); - self.offset.y = 6; - self.correntOffset(); - } - else { - self.goToRoot(); - } - self.bakup(); - G.editor.need_redraw = true; - } - //} - // { clipboard - pub fn externalCopy (self: *T) !void { - const t = self; - G.editor.need_redraw = false; - // { create file - var cwd = std.fs.cwd(); - var file = try cwd.createFile(G.editor.path_to_clipboard.get(), .{}); - defer file.close(); - const writer = file.writer(); - // } - if (t.cutted) |cutted| { - // { working with lines - var current: *Line = cutted; - try writer.writeAll(current.text.get()); - copying: while (true) { - if (current.child) |child| { - try writer.writeAll("\n"); - try writer.writeAll(child.text.get()); - current = child; - } - else if (current.next) |next| { - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - next = current.next orelse continue; - break; - } - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - } - // } - { // change status - G.editor.need_redraw = false; - try G.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.blue2); - try G.console.out.writeAll("cutted lines saved to ~/clipboard.tmp"); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - } - else { - // { working with lines - const first = self.line; - try writer.writeAll(first.text.get()); - if (first.child) |first_child| { - var current: *Line = first_child; - try writer.writeAll("\n"); - try writer.writeAll(current.text.get()); - copying: while (true) { - if (current.child) |child| { - try writer.writeAll("\n"); - try writer.writeAll(child.text.get()); - current = child; - } - else if (current.next) |next| { - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - if (current == first) break: copying; - next = current.next orelse continue; - break; - } - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - } - } - // } - { // change status - G.editor.need_redraw = false; - try G.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.blue2); - try G.console.out.writeAll("this block saved to ~/clipboard.tmp"); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - } - } - pub fn externalPaste (self: *T) !void { - // read file - var file_data: []const u8 = undefined; - const allocator = G.std.heap.c_allocator; - const loaded = lib.fileRead(allocator, G.editor.path_to_clipboard.get()); - defer if (loaded) |data| {allocator.free(data);} else |_| {}; - if (loaded) |data| {file_data = data;} else |err| { - { // change status - try G.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.red2); - try G.console.out.writeAll("file ~/clipboard.tmp not reedable."); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - return err; - } - - // paste - const line = self.line; - try self.addPrevLine(); - for (file_data) |rune| { // parse lines - switch(rune) { - 10, 13 => {try self.addNextLine();}, - else => {try self.insertSymbol(rune);}, - } - } - self.line = line; - G.editor.need_redraw = true; - } - //} - // { bakup - pub fn bakup (self: *Self) void { - self.bakup_line.text.set(self.line.text.get()) catch {}; - } - pub fn restore (self: *Self) void { - self.line.text.set(self.bakup_line.text.get()) catch {}; - G.editor.need_redraw = true; - } - // } - // { indent - pub fn indentToCutie (self: *Self) void { - var current = self.line; - current.changeIndentToCutie() catch {}; - var first = current; - if (first.child) |first_child| { - current = first_child; - traversal: while (true) { - if (current.child) |child| { - current.changeIndentToCutie() catch {}; - current = child; - } - else if (current.next) |next| { - current.changeIndentToCutie() catch {}; - current = next; - } - else { - if (self.foldMode == .byBrackets) { - const parent = current.getParent() orelse break :traversal; - const indent = parent.text.countIndent(1); - current.text.changeIndent(indent) catch {}; - } - else { - current.changeIndentToCutie() catch {}; - } - while (true) { // find parent with next - current = current.getParent() orelse break :traversal; - if (current == first) break :traversal; - if (current.next) |next| { - current = next; - break; - } - } - } - } - } - G.editor.need_redraw = true; - } - pub fn deleteIndent (self: *Self) void { - var current = self.line; - current.text.changeIndent(0) catch {}; - var first = current; - if (first.child) |first_child| { - current = first_child; - traversal: while (true) { - if (current.child) |child| { - current.text.changeIndent(0) catch {}; - current = child; - } - else if (current.next) |next| { - current.text.changeIndent(0) catch {}; - current = next; - } - else { - current.text.changeIndent(0) catch {}; - while (true) { // find parent with next - current = current.getParent() orelse break :traversal; - if (current == first) break :traversal; - if (current.next) |next| { - current = next; - break; - } - } - } - } - } - G.editor.need_redraw = true; - } - // } - - // being developed - pub fn drawRunes (self: *T) !void { - try G.console.cursorMove(.{.x = 0, .y = self.offset.y}); - defer self.cursorMoveToCurrent() catch {}; - - try ansi.do(ansi.color.red); - defer ansi.do(ansi.reset) catch {}; - - draw: { - var screen_pos_x: usize = 0; - var text_pos: usize = self.offset.x; // TODO skip first text_pos runes - const runes = self.line.runes orelse break: draw; - var link = &runes.link; - while(true) { - if (screen_pos_x >= G.console.size.x - 3) break; - const rune = Rune.unlink(link); - try G.console.out.writeAll(rune.glyph.getText()); - screen_pos_x += 1; - text_pos += 1; - link = link.next orelse break; - } - } - defer ansi.do(ansi.clear_to_end_line) catch {}; - - G.editor.need_redraw = false; - } - pub fn goToNextFlatLine (self: *T) void { - const line_link = self.line.chain_link.next orelse return; - self.line = Line.unlink(line_link); - } - pub fn goToPrevFlatLine (self: *T) void { - const line_link = self.line.chain_link.prev orelse return; - self.line = Line.unlink(line_link); - } - // { selection - // } - // { find - pub fn findNext (self: *Self) void { - const text = self.line.text.get(); - var line = self.line; - if (line.text.find(text, self.symbol)) |pos| { // goto pos and return - self.line = line; - self.goToSymbol(pos); - return; - } - else { // iterate and find - while(true) { - // iterate - if (line.child) |child| { // goto child - line = child; - } - else if (line.next) |next| { // goto next - line = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - line = line.getParent() orelse return; - next = line.next orelse continue; - break; - } - line = next; - } - - // find - if (line.text.find(text, 0)) |pos| { // goto pos and return - self.line = line; - self.goToSymbol(pos); - return; - } - } - } - self.changeMode(.edit); - G.editor.need_clear = true; - G.editor.need_redraw = true; - self.bakup(); - } - // } -// } DELETED src/ViewEasyMotionH.zig Index: src/ViewEasyMotionH.zig ================================================================== --- src/ViewEasyMotionH.zig +++ /dev/null @@ -1,1303 +0,0 @@ -// this file is just gabarage. -// i rewrite this in future. - -const Self = @This(); -// { fields - file_name: Text = .{}, - - // modes - mode: Mode = .edit, - indent: Indent = .{}, - - lines: linkedList.Chain = .{}, - - bakup_line: *Line = undefined, - last_working_line: ?*Line = null, - marked_line: ?*Line = null, - lines_drawing: usize = 0, - - // current pos - current_line: *Line, - offset: lib.Coor2u = .{.x = 0, .y = 0 }, - symbol: usize = 0, -// } -// { methods - pub fn onKey (self: *Self, cik: Console.Input.Key) !void { - switch (self.view.mode) { - .edit => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .mouse => {try self.onMouse();}, - .f1 => {try self.view.goToHelp();}, - .f1_rxvt => {try self.view.goToHelp();}, - .f1_tty => {try self.view.goToHelp();}, - .f2 => {self.debug.toggle();}, - .f2_rxvt => {self.debug.toggle();}, - .f2_tty => {self.debug.toggle();}, - .f3 => {self.view.goToPrevFlatLine();}, - .f4 => {self.view.goToNextFlatLine();}, - .f5 => {try self.view.drawRunes();}, - .f9 => {try self.view.changeMode(.normal);}, - .f10 => {self.stop();}, - - .delete => {self.view.deleteSymbol();}, - .shift_delete => {self.view.clearLine();}, - - .end => {self.view.goToEndOfLine();}, - .home => {self.view.goToStartOfLine();}, - - .down => {self.view.goToNextLine();}, - .up => {self.view.goToPrevLine();}, - .left => {self.view.goToPrevSymbol();}, - .right => {self.view.goToNextSymbol();}, - .ctrl_shift_left => {self.view.CtrlShiftLeft();}, - .ctrl_shift_right => {self.view.CtrlShiftRight();}, - .ctrl_left => {self.view.goToStartOfWord();}, - .ctrl_left_rxvt => {self.view.goToStartOfWord();}, - .ctrl_right => {self.view.goToEndOfWord();}, - .ctrl_right_rxvt => {self.view.goToEndOfWord();}, - .ctrl_up => {self.view.goToFirstLine();}, - .ctrl_down => {self.view.goToLastLine();}, - .alt_up => {self.view.swapWithUpper();}, - .alt_down => {self.view.swapWithBottom();}, - - .alt_n => {self.view.insertSymbol('\n') catch {};}, - .alt_r => {self.view.insertSymbol('\r') catch {};}, - .alt_v => {self.view.externalPaste() catch {};}, - .alt_m => {self.view.markThisLine();}, - .alt_j => {self.view.goToMarked();}, - .alt_p => {self.view.deleteIndent();}, - - else => {self.need_redraw = true;}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - self.need_redraw = true; - }, - .ascii_key => |key| { - switch (key) { - .ctrl_q => {self.stop();}, - .ctrl_s => {self.view.save() catch {};}, - .ctrl_g => {try self.view.changeMode(.to_line);}, - .ctrl_f => {try self.view.changeMode(.to_find);}, - .ctrl_u => {self.view.unFold();}, - .ctrl_r => {try self.view.foldFromIndent();}, - .ctrl_e => {self.view.foldFromBrackets();}, - .ctrl_j => {self.view.joinLines();}, - .enter => { - switch (self.console.input.is_paste) { - true => {self.view.addNextLine() catch {};}, - false => {self.view.divide() catch {};}, - } - }, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_p => {self.view.indentToCutie();}, - .ctrl_d => {self.view.duplicate();}, - .ctrl_x => {self.view.cut();}, - .ctrl_c => {self.view.externalCopy() catch {};}, - .ctrl_v => {self.view.pasteLine();}, - .ctrl_t => {self.view.insertSymbol('\t') catch {};}, - .escape => {self.view.goToOut();}, - .tab => {self.view.goToIn();}, - .ctrl_w => {self.view.deleteWord();}, - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .ctrl_z => {self.view.restore();}, - .ctrl_o => {try self.view.drawRunes();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .to_find => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .ctrl_left => self.view.goToStartOfLine(), - .ctrl_right => self.view.goToEndOfLine(), - .delete => self.view.deleteSymbol(), - .shift_delete => {self.view.clearLine();}, - else => {}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - }, - .ascii_key => |key| { - switch (key) { - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_j => {self.view.findNext();}, - .enter => {self.view.findNext();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .to_line => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .ctrl_left => self.view.goToStartOfLine(), - .ctrl_right => self.view.goToEndOfLine(), - .delete => self.view.deleteSymbol(), - .shift_delete => {self.view.clearLine();}, - else => {}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - }, - .ascii_key => |key| { - switch (key) { - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_j => {try self.view.goToLineFromInput();}, - .enter => {try self.view.goToLineFromInput();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .history => {}, - .select => {}, - .normal => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .delete => {self.view.deleteSymbol();}, - .shift_delete => {self.view.clearLine();}, - .end => {self.view.goToEndOfLine();}, - .home => {self.view.goToStartOfLine();}, - .down => {self.view.goToNextLine();}, - .up => {self.view.goToPrevLine();}, - .left => {self.view.goToPrevSymbol();}, - .right => {self.view.goToNextSymbol();}, - else => {}, - } - }, - .byte => |_| {}, - .ascii_key => |key| { - switch (key) { - .code_q => {self.stop();}, - .code_s => {self.view.save() catch {};}, - .code_i => {try self.view.changeMode(.edit);}, - .code_g => {try self.view.changeMode(.to_line);}, - .code_u => {self.view.unFold();}, - .code_r => {try self.view.foldFromIndent();}, - .code_e => {self.view.foldFromBrackets();}, - .code_j => {self.view.divide() catch {};}, - .enter => {self.view.divide() catch {};}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .code_p => {self.view.line.changeIndentToCutie() catch {};}, - .code_d => {self.view.duplicate();}, - .code_x => {self.view.cut();}, - .code_c => {self.view.externalCopy() catch {};}, - .code_v => {self.view.pasteLine();}, - .code_t => {self.view.insertSymbol('\t') catch {};}, - .escape => {self.view.goToOut();}, - .tab => {self.view.goToIn();}, - .code_l => {self.view.goToLastLine();}, - else => {}, - } - }, - } - }, - .easy_motion_vertical => { - switch (cik) { - .sequence => |_| {}, - .byte => |_| {}, - .ascii_key => |key| { - const num = @enumToInt(key); - if (num >= 0x61 and num <= 0x7A) {try self.view.easyMotionVertical(num);} - else switch (key) { - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - else => {}, - } - }, - } - }, - .easy_motion_horizontal => { - switch (cik) { - .sequence => |_| {}, - .byte => |_| {}, - .ascii_key => |key| { - const num = @enumToInt(key); - if (num >= 0x61 and num <= 0x7A) {try self.view.easyMotionHorizontal(num);} - else switch (key) { - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - else => {}, - } - }, - } - }, - } - } - pub fn fromAlloc () !*View { - const allocated = lib.c.aligned_alloc(8, @sizeOf(View)) orelse return error.NeedMoreMemory; - var view: *View = @ptrCast(*View, @alignCast(8, allocated)); - return view; - } - pub fn init (self: *Self, file_name: []const u8, text: []const u8) !void { - self.* = .{}; - self.file_name.set(file_name) catch unreachable; - { // parse_text_to_lines - var iter = std.mem.split(u8, text, "\n"); - while(iter.next()) |line| { - const new_line = try prog.buffer_lines.create(); - new_line.text.set(line) catch { - return error.LineIsToLong; - }; - self.lines.pushLast(&new_line.chain_link); - } - } - const link = self.lines.first.?; - self.current_line = Line.unlink(link); - self.bakup_line = try prog.buffer_lines.create(); - } // end fn loadLines - pub fn changeMode (self: *Self, mode: Mode) !void { - switch (mode) { - .edit => {}, - .to_find => { - self.last_working_line = self.current_line; - }, - .to_line => { - self.last_working_line = self.current_line; - if (prog.buffer_lines.to_goto == null) { // create - const new_line = prog.buffer_lines.create() catch return; - prog.buffer_lines.to_goto = new_line; - } - self.current_line = prog.buffer_lines.to_goto.?; - self.goToEndOfLine(); - prog.need_redraw = true; - }, - .history => {}, - .select => {}, - .normal => {}, - .easy_motion_vertical => { - try self.draw_vertical_help_motion(); - }, - .easy_motion_horizontal => { - try self.draw_horizontal_help_motion(); - }, - } - self.mode = mode; - } - pub fn cursorMoveToCurrent (self: *Self) !void { - try prog.console.cursorMove(.{ .x = self.offset.x, .y = self.offset.y }); - } - // { draw - pub fn draw (self: *Self) !void { - try ansi.do(ansi.cyrsor_style.hide); - defer ansi.do(ansi.cyrsor_style.show) catch {}; - defer self.cursorMoveToCurrent() catch {}; - if (self.symbol < self.offset.x) { // unexpected - self.offset = .{}; - self.symbol = 0; - } - switch (self.mode) { - .edit => { - switch (self.fold_mode) { - .flat => { - Theme.line.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - try self.drawLine(); - if (self.offset.y > 0) { // draw upper lines - var iter = self.line.link.iterReverse(); - - // skip current; - var pos_y = self.offset.y - 1; - _ = iter.next(); - - while(iter.next()) |link| { - const line = Line.unlink(link); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y}); - self.drawLine(line); - if (pos_y == 0) break; - pos_y -= 1; - } - } - if (self.offset.y < prog.console.size.y) { // draw downer lines - var iter = self.line.link.iter(); - - // skip current; - var pos_y = self.offset.y + 1; - _ = iter.next(); - - while(iter.next()) |link| { - const line = Line.unlink(link); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y}); - self.drawLine(line); - if (pos_y == 0) break; - pos_y += 1; - } - while (true) { // clear other downer lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y >= prog.console.size.y - 1) return; - pos_y += 1; - std.time.sleep(draw_lag); - } - } - try self.drawEdited(); - }, - else => { - // draw other lines - try self.drawUpperLines(); - try self.drawDownerLines(); - - // draw edit line - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y }); - if (self.line.tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(self.line); - try self.drawEditedF(); - } - else { - try Theme.line.apply(); - try self.drawLine(self.line); - try self.drawEdited(); - } - }, - } - }, - .to_line => { - self.offset.y = 1; - - // draw banner - try prog.console.changeColor(Theme.headers); - try prog.console.cursorMove(.{ .x = 0, .y = 0}); - try prog.console.out.writeAll("enter the line you want to jump to:"); - try ansi.do(ansi.clear_to_end_line); - - // draw edit line - try prog.console.cursorMove(.{ .x = 0, .y = 1}); - defer self.cursorMoveToCurrent() catch {}; - try self.drawEditedLine(); - - var pos_y: usize = 2; - while (true) { // clear other downer lines - if (pos_y >= prog.console.size.y) return; - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - pos_y += 1; - std.time.sleep(draw_lag); - - } - }, - .easy_motion_vertical, - .easy_motion_horizontal, - .to_find, - .history, - .select, - .normal, - => {}, - } - } // end draw lines - pub fn drawLine (self: *Self, line: *Line) !void { - // move to start - defer ansi.do(ansi.clear_to_end_line) catch {}; - try prog.console.cr(); - if (line.text.used == 0) {return;} - - // draw left-to-right - const text = line.text.get(); - var text_pos: usize = self.symbol - self.offset.x; // first visible rune - var offset_x: usize = 0; - while (true) { - if (text_pos >= text.len) break; - if (offset_x >= prog.console.size.x - 1) break; - prog.console.writeByte(text[text_pos]) catch unreachable; - text_pos += 1; - offset_x += 1; - } - } - pub fn drawParentLine (self: *Self, parent: *Line) !void { - // draw - try prog.console.cr(); - const text = parent.text.get(); - var indent = parent.text.countIndent(1); - var symbol: usize = indent; - if (indent >= self.symbol - self.offset.x) {symbol = self.symbol - self.offset.x;} - var offset_x: usize = 0; - while (true) { - if (symbol >= text.len) { - try ansi.do(ansi.clear_to_end_line); - break; - } - if (offset_x >= prog.console.size.x) break; - prog.console.writeByte(text[symbol]) catch unreachable; - - symbol += 1; - offset_x += 1; - } - } - pub fn drawEdited (self: *Self) !void { - const text: []u8 = self.line.text.get(); - const pos: usize = self.symbol - self.offset.x; - const end_pos: usize = pos + prog.console.size.x; - - if (pos > 0) { // draw '<' - try Theme.outLine.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - prog.console.writeByte('<') catch unreachable; - } - if (text.len > end_pos) { // draw '>' - try Theme.outLine.apply(); - try prog.console.cursorMove(.{ .x = prog.console.size.x - 1, .y = self.offset.y}); - prog.console.writeByte('>') catch unreachable; - } - if (pos < text.len) { // draw symbol about cursor - try self.cursorMoveToCurrent(); - try Theme.currentRune.apply(); - try prog.console.writeByte(text[pos]); - } - } // drawEdited - pub fn drawEditedF (self: *Self) !void { - const text: []u8 = self.line.text.get(); - const pos: usize = self.symbol - self.offset.x; - const end_pos: usize = pos + prog.console.size.x; - - if (pos > 0) { // draw '<' - try Theme.outLineF.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - prog.console.writeByte('<') catch unreachable; - } - if (text.len > end_pos) { // draw '>' - try Theme.outLineF.apply(); - try prog.console.cursorMove(.{ .x = prog.console.size.x - 1, .y = self.offset.y}); - prog.console.writeByte('>') catch unreachable; - } - if (pos < text.len) { // draw symbol about cursor - try self.cursorMoveToCurrent(); - try Theme.currentRuneF.apply(); - try prog.console.writeByte(text[pos]); - } - } // drawEdited - // draw tree - pub fn drawUpperLines (self: *Self) !void { - //TODO: apply self.max_draw_parent_lines = 2; - - // draw lines - if (self.offset.y == 0) return; - var iter = self.line.tree.link.iteratorReverse(); - // skip current - var pos_y: usize = self.offset.y - 1; - _ = iter.next(); - while(iter.next()) |link| { - const tree = Tree.unlink(link); - const line = Line.unTree(tree); - - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - if (tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(line); - } - else { - try Theme.line.apply(); - try self.drawLine(self.line); - } - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - while (true) { // draw parents - try Theme.headers.apply(); - const tree = self.line.tree.parent orelse break; - if (tree == self.tree) break; - const line = Line.untree(tree); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try self.drawParentLine(line); - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - while (true) { // clear other upp lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - } - pub fn drawDownerLines (self: *Self) !void { - var iter = self.line.tree.link.iterator(); - // skip current - var pos_y: usize = self.offset.y + 1; - _ = iter.next(); - - if (pos_y >= prog.console.size.y) return; - while (iter.next) |tree_link| { // draw lines - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - if (line.tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(line); - } - else { - try Theme.line.apply(); - try drawLine(self.line); - } - if (pos_y >= prog.console.size.y - 1) { - self.lines_drawing = prog.console.size.y; - return; - } - pos_y += 1; - std.time.sleep(draw_lag); - } - - self.lines_drawing = pos_y; - while (true) { // clear other downer lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y >= prog.console.size.y - 1) return; - pos_y += 1; - std.time.sleep(draw_lag); - } - } - // } - // { navigation - // over lines - pub fn goToRoot (self: *Self) void { - self.line = self.lines; - self.offset.y = 5; - self.goToStartOfLine(); - prog.need_redraw = true; - self.bakup(); - } - pub fn goToPrevLine (self: *Self) void { - switch(self.fold_mode) { - .flat => { - if (self.link.prev) |prev| { - const line = Line.unlink(prev); - self.line = line; - } - }, - else => { - if (self.line.tree.link.prev) |tree_link| { - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - self.line = line; - prog.need_redraw = true; - } - }, - } - if (self.offset.y > 5) {self.offset.y -= 1;} - self.bakup(); - } // end fn - pub fn goToNextLine (self: *Self) void { - switch(self.fold_mode) { - .flat => { - if (self.link.next) |prev| { - const line = Line.unlink(prev); - self.line = line; - } - }, - else => { - if (self.line.tree.link.next) |tree_link| { - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - self.line = line; - prog.need_redraw = true; - } - }, - } - self.bakup(); - - if (self.offset.y < prog.console.size.y - 1) self.offset.y += 1; - // { correct offset_y: - // count downest_lines - var count_to_downest_line: usize = 0; - var iter = if (self.fold_mode == .flat) self.line.link.iterator() else self.line.tree.chain_link.iterator(); - _ = iter.next(); - while (count_to_downest_line < 5) { - _ = iter.next() orelse break; - count_to_downest_line += 1; - } - - if (prog.console.size.y - self.offset.y < count_to_downest_line) { - self.offset.y = prog.console.size.y - count_to_downest_line; - } - //} - prog.need_redraw = true; - } // end fn - pub fn goToFirstLine (self: *Self) void { - while (self.line.prev) |_| self.goToPrevLine(); - self.goToStartOfLine(); - prog.need_redraw = true; - self.bakup(); - } - pub fn goToLastLine (self: *Self) void { - while (self.line.next) |_| self.goToNextLine(); - prog.need_redraw = true; - self.bakup(); - } - // { go to line from number - pub fn goToLineFromNumber (self: *View, num: usize) void { - if (self.fold_mode != .flat) self.unfold(); - var iter = self.lines.first.iterator(); - var pos = 0; - while(iter.next()) |_| { - if (pos == num) break; - pos += 1; - } - self.line = Line.unlink(iter.current); - - self.offset.y = 6; - self.goToSymbol(self.line.text.countIndent(1)); - if (self.symbol >= 4) self.offset.x = 4; - prog.need_redraw = true; - self.bakup(); - } - pub fn goToLineFromInput (self: *View) !void { - if (self.line.text.used == 0) return; - var num: usize = @truncate(usize, textlib.u64FromCharsDec(self.line.text.get()) catch return); - try self.changeMode(.edit); - self.goToLineFromNumber(num); - } - // } - - // over line - pub fn goToStartOfLine (self: *Self) void { - self.symbol = 0; - self.offset.x = 0; - prog.need_redraw = true; - } - pub fn goToEndOfLine (self: *Self) void { - self.symbol = self.line.text.used; - if (self.symbol > prog.console.size.x - 2) {self.offset.x = prog.console.size.x - 2;} - else {self.offset.x = self.symbol;} - prog.need_redraw = true; - } - pub fn goToStartOfText (self: *Self) void { - const indent = self.line.text.countIndent(1); - self.goToSymbol(indent); - } - pub fn CtrlShiftLeft (self: *Self) void { - const indent = self.line.text.countIndent(1); - if (self.symbol > indent) { - self.goToSymbol(indent); - if (self.symbol >= 4) self.offset.x = 4; - } - else self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn CtrlShiftRight (self: *Self) void { - const indent = self.line.text.countIndent(1); - if (self.symbol < indent) self.goToSymbol(indent) - else self.goToEndOfLine(); - prog.need_redraw = true; - } - - // over word - pub fn goToStartOfWord (self: *Self) void { - if (self.symbol == 0) {return;} - if (self.symbol > self.line.text.used) {self.goToSymbol(self.line.text.used);} - const first_rune = self.line.text.buffer[self.symbol]; - if (first_rune == ' ') { - self.goToPrevSymbol(); - while (true) { - if (self.symbol == 0) {break;} - const rune = self.line.text.buffer[self.symbol]; - if (rune != ' ') break; - self.goToPrevSymbol(); - } - } - else { - self.goToPrevSymbol(); - while(true) { - if (self.symbol == 0) {break;} - const next_symbol = self.line.text.buffer[self.symbol - 1]; - switch(next_symbol){ - ' ', '\t', '\\', - '=', '+', '-', '/', '*', '^', - '!', '@', '#', '$', '%', '&', - '(', ')', '[', ']', '{', '}', - '"', '\'', - ';', ':', '.', ',' - => {break;}, - else => {}, - } - self.goToPrevSymbol(); - } - } - prog.need_redraw = true; - } - pub fn goToEndOfWord (self: *Self) void { - if (self.symbol >= self.line.text.used) {return;} - const first_rune = self.line.text.buffer[self.symbol]; - if (first_rune == ' ') { - while(true) { - self.goToNextSymbol(); - if (self.symbol >= self.line.text.used) {break;} - const rune = self.line.text.buffer[self.symbol]; - if (rune != ' ') break; - } - } - else while(true) { - self.goToNextSymbol(); - if (self.symbol >= self.line.text.used) {break;} - const rune = self.line.text.buffer[self.symbol]; - switch(rune){ - ' ', '\t', '\\', - '=', '+', '-', '/', '*', '^', - '(', ')', '[', ']', '{', '}', - '!', '@', '#', '$', '%', '&', - '"', '\'', - ';', ':', '.', ',' - => {break;}, - else => {}, - } - } - prog.need_redraw = true; - } - - // over symbols - pub fn goToSymbol (self: *Self, pos: usize) void { - self.symbol = pos; - if (self.symbol > prog.console.size.x - 2) { - self.offset.x = prog.console.size.x - 2; - } - else {self.offset.x = self.symbol;} - } - pub fn goToPrevSymbol (self: *Self) void { - const used = self.line.text.used; - if (self.symbol == 0) { - if (true) return; - if (self.line.prev) |_| { - self.goToPrevLine(); - self.goToEndOfLine(); - } - return; - } - if (self.symbol > used) { - self.symbol = used; - if (used < prog.console.size.x - 1) self.offset.x = self.line.text.used; - prog.need_redraw = true; - return; - } - if (self.symbol > 0) self.symbol -= 1; - if (self.symbol >= 10) {if (self.offset.x > 10) {self.offset.x -= 1;}} - else {if (self.offset.x > 0) self.offset.x -= 1;} - prog.need_redraw = true; - } - pub fn goToNextSymbol (self: *Self) void { - const used = self.line.text.used; - if (self.symbol >= used) { - if (true) return; - if (self.line.next) |_| { - self.goToNextLine(); - self.goToStartOfLine(); - } - return; - } - if (self.symbol < Line.Text.size - 1) self.symbol += 1; - if (used - self.symbol >= 10) { - if (self.offset.x < prog.console.size.x - 12) self.offset.x += 1; - } - else { - if (self.offset.x < prog.console.size.x - 2) self.offset.x += 1; - } - prog.need_redraw = true; - } - - //} - // { folding - pub fn unFold (self: *Self) void { - if (self.foldMode == .flat) return; - - // add to chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - self.lines.pushLast(&line.link); - } - - // clear tree - self.tree = .{}; - var iter = self.lines.iter(); - while(iter.next()) |link| { - const line = Line.unlink(link); - line.tree = .{}; - } - - prog.need_redraw = true; - self.foldMode = .byNone; - } // end fn - pub fn foldFromBrackets (self: *Self) void { - self.unFold(); - - // add to tree - var iter = self.lines.iter(); - var current = iter.next() orelse return; - self.tree.addChild(current); - while(iter.next()) |link| { - const line = Line.unlink(link); - const close_count = line.text.getRunesCount('}'); // **{ - const open_count = line.text.getRunesCount('{'); // **} - - if (open_count == close_count) { - current.tree.pushNext(&line.tree); - } - else if (open_count > close_count) { - current.tree.pushChild(&line.tree); - } - else { // for close_count > open_count - var parent = current.tree.parent.?; - if (parent == &self.tree) parent = ¤t.tree; - parent.pushNext(&line.tree); - } - - current = line; - } - - // remove from chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - line.link = .{}; - } - self.lines = .{}; - - prog.need_redraw = true; - self.foldMode = .byBrackets; - } - pub fn foldFromIndent (self: *Self) !void { - self.unFold(); - - var iter = self.lines.iter(); - var current_link = iter.next() orelse return; - var current = Line.unlink(current_link); - var last_indent = current.text.countIndent(4); - self.tree.addChild(¤t.tree); - while(iter.next()) |link| { - const line = Line.unlink(link); - const indent = line.text.countIndent(4); - if (indent == last_indent) { - current.tree.pushNext(&line.tree); - } - else if (indent > last_indent) { - current.tree.pushChild(&line.tree); - } - else { // for last_indent > indent - // find parent with indent > indent - var parent = current.tree.parent.?; - while (true) { - if (parent == &self.tree) {parent = ¤t.tree; break;} - const parent_line = Line.untree(parent); - const parent_indent = parent_line.text.countIndent(4); - if (parent_indent > indent) break; - parent = current.tree.parent.?; - } - parent.pushChild(&line.tree); - } - - current = line; - last_indent = indent; - } - - // remove from chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - line.link = .{}; - } - self.lines = .{}; - - prog.need_redraw = true; - self.foldMode = .byIndent; - } - - pub fn goToIn (self: *Self) void { - if (self.fold_mode == .flat) return; - const child = self.line.child orelse return; - const child_indent = child.text.countIndent(1); - self.goToSymbol(child_indent); - self.symbol = child_indent; - self.line = child; - if (prog.console.size.y > 6) {self.offset.y = 6;} - else if (prog.console.size.y > 3) {self.offset.y = 3;} - else if (prog.console.size.y > 1) {self.offset.y = 1;} - else {self.offset.y = 0;} - self.bakup(); - if (self.symbol >= 4) self.offset.x = 4; - prog.need_redraw = true; - } - pub fn goToOut (self: *Self) void { - if (self.fold_mode == .flat) return; - if (self.line.getParent()) |parent| { - const parent_indent = parent.text.countIndent(1); - self.line = parent; - self.goToSymbol(parent_indent); - self.offset.y = 6; - if (self.symbol >= 4) self.offset.x = 4; - } - else { - self.goToRoot(); - } - self.bakup(); - prog.need_redraw = true; - } - //} - // { clipboard - pub fn externalCopy (self: *Self) !void { - prog.need_redraw = false; - // { create file - var cwd = std.fs.cwd(); - var file = try cwd.createFile(prog.path_to_clipboard.get(), .{}); - defer file.close(); - const writer = file.writer(); - // } - if (prog.buffer_lines.cutted) |cutted| { - // { working with lines - var current: *Line = cutted; - try writer.writeAll(current.text.get()); - copying: while (true) { - if (current.child) |child| { - try writer.writeAll("\n"); - try writer.writeAll(child.text.get()); - current = child; - } - else if (current.next) |next| { - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - next = current.next orelse continue; - break; - } - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - } - // } - { // change status - prog.need_redraw = false; - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.blue2); - try prog.console.out.writeAll("cutted lines saved to ~/clipboard.tmp"); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - } - else { - // { working with lines - const first = self.line; - try writer.writeAll(first.text.get()); - if (first.child) |first_child| { - var current: *Line = first_child; - try writer.writeAll("\n"); - try writer.writeAll(current.text.get()); - copying: while (true) { - if (current.child) |child| { - try writer.writeAll("\n"); - try writer.writeAll(child.text.get()); - current = child; - } - else if (current.next) |next| { - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - if (current == first) break: copying; - next = current.next orelse continue; - break; - } - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - } - } - // } - { // change status - prog.need_redraw = false; - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.blue2); - try prog.console.writeAll("this block saved to ~/clipboard.tmp"); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - } - } - pub fn externalPaste (self: *Self) !void { - // read file - var file_data: []const u8 = undefined; - const loaded = lib.fileRead(prog.allocator, prog.path_to_clipboard.get()); - defer if (loaded) |data| {prog.allocator.free(data);} else |_| {}; - if (loaded) |data| {file_data = data;} else |err| { - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.red2); - try prog.console.writeAll("file ~/clipboard.tmp not reedable."); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - return err; - } - - // paste - const line = self.current_line; - try self.addPrevLine(); - for (file_data) |rune| { // parse lines - switch(rune) { - 10, 13 => {try self.addNextLine();}, - else => {try self.insertSymbol(rune);}, - } - } - self.line = line; - prog.need_redraw = true; - } - //} - // { bakup - pub fn bakup (self: *Self) void { - self.bakup_line.text.set(self.line.text.get()) catch {}; - } - pub fn restore (self: *Self) void { - self.line.text.set(self.bakup_line.text.get()) catch {}; - prog.need_redraw = true; - } - // } - // { indent - pub fn indentToCutie (self: *Self) void { - var current = self.line; - current.changeIndentToCutie() catch {}; - var first = current; - if (first.child) |first_child| { - current = first_child; - traversal: while (true) { - if (current.child) |child| { - current.changeIndentToCutie() catch {}; - current = child; - } - else if (current.next) |next| { - current.changeIndentToCutie() catch {}; - current = next; - } - else { - if (self.foldMode == .byBrackets) { - const parent = current.getParent() orelse break :traversal; - const indent = parent.text.countIndent(1); - current.text.changeIndent(indent) catch {}; - } - else { - current.changeIndentToCutie() catch {}; - } - while (true) { // find parent with next - current = current.getParent() orelse break :traversal; - if (current == first) break :traversal; - if (current.next) |next| { - current = next; - break; - } - } - } - } - } - prog.need_redraw = true; - } - pub fn deleteIndent (self: *Self) void { - var current = self.line; - current.text.changeIndent(0) catch {}; - var first = current; - if (first.child) |first_child| { - current = first_child; - traversal: while (true) { - if (current.child) |child| { - current.text.changeIndent(0) catch {}; - current = child; - } - else if (current.next) |next| { - current.text.changeIndent(0) catch {}; - current = next; - } - else { - current.text.changeIndent(0) catch {}; - while (true) { // find parent with next - current = current.getParent() orelse break :traversal; - if (current == first) break :traversal; - if (current.next) |next| { - current = next; - break; - } - } - } - } - } - prog.need_redraw = true; - } - // } - // { easy motion - pub fn draw_horizontal_help_motion (self: *Self) !void { - var pos: usize = 0; - var rune: u8 = 0x61; - try ansi.do(ansi.color.magenta); - while(true) { - try prog.console.cursorMove(.{ .x = pos, .y = self.offset.y }); - prog.console.writeByte(rune) catch unreachable; - if (rune >= 0x7A) break; rune += 1; - if (pos >= prog.console.size.x - 3) break; pos += 3; - } - try self.cursorMoveToCurrent(); - } - pub fn draw_vertical_help_motion (self: *Self) !void { - var pos: usize = 0; - try ansi.do(ansi.color.magenta); - while(true) { - try prog.console.cursorMove(.{ .x = self.offset.x, .y = pos }); - prog.console.writeByte(0x61 + @truncate(u8, pos)) catch unreachable; - if (pos >= 0x7A - 0x61) break; - if (pos == prog.console.size.y - 1) break; - pos += 1; - } - try self.cursorMoveToCurrent(); - } - pub fn easyMotionHorizontal (self: *Self, key: u8) !void { - var pos = key - 0x61; - self.goToSymbol(self.symbol - self.offset.x + pos * 3); - try self.changeMode(.edit); - prog.need_redraw = true; - } - pub fn easyMotionVertical (self: *Self, key: u8) !void { - var pos = key - 0x61; - if (self.offset.y == pos) {} - else if (self.offset.y > pos) { - var i = self.offset.y - pos; - while (i > 0) : (i -= 1) { - self.goToPrevLine(); - } - } - else { // (self.offset.y < pos) - var i = pos - self.offset.y; - while (i > 0) : (i -= 1) { - self.goToNextLine(); - } - } - try self.changeMode(.edit); - prog.need_redraw = true; - } - // } - - // being developed - pub fn drawRunes (self: *Self) !void { - try prog.console.cursorMove(.{.x = 0, .y = self.offset.y}); - defer self.cursorMoveToCurrent() catch {}; - - try ansi.do(ansi.color.red); - defer ansi.do(ansi.reset) catch {}; - - draw: { - var screen_pos_x: usize = 0; - var text_pos: usize = self.offset.x; // TODO skip first text_pos runes - const runes = self.current_line.runes orelse break: draw; - var link = &runes.link; - while(true) { - if (screen_pos_x >= prog.console.size.x - 3) break; - const rune = Rune.unlink(link); - try prog.console.writeAll(rune.glyph.getText()); - screen_pos_x += 1; - text_pos += 1; - link = link.next orelse break; - } - } - defer ansi.do(ansi.clear_to_end_line) catch {}; - - prog.need_redraw = false; - } - pub fn goToNextFlatLine (self: *Self) void { - const line_link = self.line.chain_link.next orelse return; - self.line = Line.unlink(line_link); - } - pub fn goToPrevFlatLine (self: *Self) void { - const line_link = self.line.chain_link.prev orelse return; - self.line = Line.unlink(line_link); - } - // { selection - // TODO - // } - // { find - pub fn findNext (self: *Self) void { - const text = self.line.text.get(); - var line = self.line; - if (line.text.find(text, self.symbol)) |pos| { // goto pos and return - self.line = line; - self.goToSymbol(pos); - return; - } - else { // iterate and find - while(true) { - // iterate - if (line.child) |child| { // goto child - line = child; - } - else if (line.next) |next| { // goto next - line = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - line = line.getParent() orelse return; - next = line.next orelse continue; - break; - } - line = next; - } - - // find - if (line.text.find(text, 0)) |pos| { // goto pos and return - self.line = line; - self.goToSymbol(pos); - return; - } - } - } - self.changeMode(.edit); - prog.need_clear = true; - prog.need_redraw = true; - self.bakup(); - } - // } -// } DELETED src/ViewEasyMotionV.zig Index: src/ViewEasyMotionV.zig ================================================================== --- src/ViewEasyMotionV.zig +++ /dev/null @@ -1,1303 +0,0 @@ -// this file is just gabarage. -// i rewrite this in future. - -const Self = @This(); -// { fields - file_name: Text = .{}, - - // modes - mode: Mode = .edit, - indent: Indent = .{}, - - lines: linkedList.Chain = .{}, - - bakup_line: *Line = undefined, - last_working_line: ?*Line = null, - marked_line: ?*Line = null, - lines_drawing: usize = 0, - - // current pos - current_line: *Line, - offset: lib.Coor2u = .{.x = 0, .y = 0 }, - symbol: usize = 0, -// } -// { methods - pub fn onKey (self: *Self, cik: Console.Input.Key) !void { - switch (self.view.mode) { - .edit => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .mouse => {try self.onMouse();}, - .f1 => {try self.view.goToHelp();}, - .f1_rxvt => {try self.view.goToHelp();}, - .f1_tty => {try self.view.goToHelp();}, - .f2 => {self.debug.toggle();}, - .f2_rxvt => {self.debug.toggle();}, - .f2_tty => {self.debug.toggle();}, - .f3 => {self.view.goToPrevFlatLine();}, - .f4 => {self.view.goToNextFlatLine();}, - .f5 => {try self.view.drawRunes();}, - .f9 => {try self.view.changeMode(.normal);}, - .f10 => {self.stop();}, - - .delete => {self.view.deleteSymbol();}, - .shift_delete => {self.view.clearLine();}, - - .end => {self.view.goToEndOfLine();}, - .home => {self.view.goToStartOfLine();}, - - .down => {self.view.goToNextLine();}, - .up => {self.view.goToPrevLine();}, - .left => {self.view.goToPrevSymbol();}, - .right => {self.view.goToNextSymbol();}, - .ctrl_shift_left => {self.view.CtrlShiftLeft();}, - .ctrl_shift_right => {self.view.CtrlShiftRight();}, - .ctrl_left => {self.view.goToStartOfWord();}, - .ctrl_left_rxvt => {self.view.goToStartOfWord();}, - .ctrl_right => {self.view.goToEndOfWord();}, - .ctrl_right_rxvt => {self.view.goToEndOfWord();}, - .ctrl_up => {self.view.goToFirstLine();}, - .ctrl_down => {self.view.goToLastLine();}, - .alt_up => {self.view.swapWithUpper();}, - .alt_down => {self.view.swapWithBottom();}, - - .alt_n => {self.view.insertSymbol('\n') catch {};}, - .alt_r => {self.view.insertSymbol('\r') catch {};}, - .alt_v => {self.view.externalPaste() catch {};}, - .alt_m => {self.view.markThisLine();}, - .alt_j => {self.view.goToMarked();}, - .alt_p => {self.view.deleteIndent();}, - - else => {self.need_redraw = true;}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - self.need_redraw = true; - }, - .ascii_key => |key| { - switch (key) { - .ctrl_q => {self.stop();}, - .ctrl_s => {self.view.save() catch {};}, - .ctrl_g => {try self.view.changeMode(.to_line);}, - .ctrl_f => {try self.view.changeMode(.to_find);}, - .ctrl_u => {self.view.unFold();}, - .ctrl_r => {try self.view.foldFromIndent();}, - .ctrl_e => {self.view.foldFromBrackets();}, - .ctrl_j => {self.view.joinLines();}, - .enter => { - switch (self.console.input.is_paste) { - true => {self.view.addNextLine() catch {};}, - false => {self.view.divide() catch {};}, - } - }, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_p => {self.view.indentToCutie();}, - .ctrl_d => {self.view.duplicate();}, - .ctrl_x => {self.view.cut();}, - .ctrl_c => {self.view.externalCopy() catch {};}, - .ctrl_v => {self.view.pasteLine();}, - .ctrl_t => {self.view.insertSymbol('\t') catch {};}, - .escape => {self.view.goToOut();}, - .tab => {self.view.goToIn();}, - .ctrl_w => {self.view.deleteWord();}, - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .ctrl_z => {self.view.restore();}, - .ctrl_o => {try self.view.drawRunes();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .to_find => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .ctrl_left => self.view.goToStartOfLine(), - .ctrl_right => self.view.goToEndOfLine(), - .delete => self.view.deleteSymbol(), - .shift_delete => {self.view.clearLine();}, - else => {}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - }, - .ascii_key => |key| { - switch (key) { - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_j => {self.view.findNext();}, - .enter => {self.view.findNext();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .to_line => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .ctrl_left => self.view.goToStartOfLine(), - .ctrl_right => self.view.goToEndOfLine(), - .delete => self.view.deleteSymbol(), - .shift_delete => {self.view.clearLine();}, - else => {}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - }, - .ascii_key => |key| { - switch (key) { - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_j => {try self.view.goToLineFromInput();}, - .enter => {try self.view.goToLineFromInput();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .history => {}, - .select => {}, - .normal => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .delete => {self.view.deleteSymbol();}, - .shift_delete => {self.view.clearLine();}, - .end => {self.view.goToEndOfLine();}, - .home => {self.view.goToStartOfLine();}, - .down => {self.view.goToNextLine();}, - .up => {self.view.goToPrevLine();}, - .left => {self.view.goToPrevSymbol();}, - .right => {self.view.goToNextSymbol();}, - else => {}, - } - }, - .byte => |_| {}, - .ascii_key => |key| { - switch (key) { - .code_q => {self.stop();}, - .code_s => {self.view.save() catch {};}, - .code_i => {try self.view.changeMode(.edit);}, - .code_g => {try self.view.changeMode(.to_line);}, - .code_u => {self.view.unFold();}, - .code_r => {try self.view.foldFromIndent();}, - .code_e => {self.view.foldFromBrackets();}, - .code_j => {self.view.divide() catch {};}, - .enter => {self.view.divide() catch {};}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .code_p => {self.view.line.changeIndentToCutie() catch {};}, - .code_d => {self.view.duplicate();}, - .code_x => {self.view.cut();}, - .code_c => {self.view.externalCopy() catch {};}, - .code_v => {self.view.pasteLine();}, - .code_t => {self.view.insertSymbol('\t') catch {};}, - .escape => {self.view.goToOut();}, - .tab => {self.view.goToIn();}, - .code_l => {self.view.goToLastLine();}, - else => {}, - } - }, - } - }, - .easy_motion_vertical => { - switch (cik) { - .sequence => |_| {}, - .byte => |_| {}, - .ascii_key => |key| { - const num = @enumToInt(key); - if (num >= 0x61 and num <= 0x7A) {try self.view.easyMotionVertical(num);} - else switch (key) { - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - else => {}, - } - }, - } - }, - .easy_motion_horizontal => { - switch (cik) { - .sequence => |_| {}, - .byte => |_| {}, - .ascii_key => |key| { - const num = @enumToInt(key); - if (num >= 0x61 and num <= 0x7A) {try self.view.easyMotionHorizontal(num);} - else switch (key) { - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - else => {}, - } - }, - } - }, - } - } - pub fn fromAlloc () !*View { - const allocated = lib.c.aligned_alloc(8, @sizeOf(View)) orelse return error.NeedMoreMemory; - var view: *View = @ptrCast(*View, @alignCast(8, allocated)); - return view; - } - pub fn init (self: *Self, file_name: []const u8, text: []const u8) !void { - self.* = .{}; - self.file_name.set(file_name) catch unreachable; - { // parse_text_to_lines - var iter = std.mem.split(u8, text, "\n"); - while(iter.next()) |line| { - const new_line = try prog.buffer_lines.create(); - new_line.text.set(line) catch { - return error.LineIsToLong; - }; - self.lines.pushLast(&new_line.chain_link); - } - } - const link = self.lines.first.?; - self.current_line = Line.unlink(link); - self.bakup_line = try prog.buffer_lines.create(); - } // end fn loadLines - pub fn changeMode (self: *Self, mode: Mode) !void { - switch (mode) { - .edit => {}, - .to_find => { - self.last_working_line = self.current_line; - }, - .to_line => { - self.last_working_line = self.current_line; - if (prog.buffer_lines.to_goto == null) { // create - const new_line = prog.buffer_lines.create() catch return; - prog.buffer_lines.to_goto = new_line; - } - self.current_line = prog.buffer_lines.to_goto.?; - self.goToEndOfLine(); - prog.need_redraw = true; - }, - .history => {}, - .select => {}, - .normal => {}, - .easy_motion_vertical => { - try self.draw_vertical_help_motion(); - }, - .easy_motion_horizontal => { - try self.draw_horizontal_help_motion(); - }, - } - self.mode = mode; - } - pub fn cursorMoveToCurrent (self: *Self) !void { - try prog.console.cursorMove(.{ .x = self.offset.x, .y = self.offset.y }); - } - // { draw - pub fn draw (self: *Self) !void { - try ansi.do(ansi.cyrsor_style.hide); - defer ansi.do(ansi.cyrsor_style.show) catch {}; - defer self.cursorMoveToCurrent() catch {}; - if (self.symbol < self.offset.x) { // unexpected - self.offset = .{}; - self.symbol = 0; - } - switch (self.mode) { - .edit => { - switch (self.fold_mode) { - .flat => { - Theme.line.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - try self.drawLine(); - if (self.offset.y > 0) { // draw upper lines - var iter = self.line.link.iterReverse(); - - // skip current; - var pos_y = self.offset.y - 1; - _ = iter.next(); - - while(iter.next()) |link| { - const line = Line.unlink(link); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y}); - self.drawLine(line); - if (pos_y == 0) break; - pos_y -= 1; - } - } - if (self.offset.y < prog.console.size.y) { // draw downer lines - var iter = self.line.link.iter(); - - // skip current; - var pos_y = self.offset.y + 1; - _ = iter.next(); - - while(iter.next()) |link| { - const line = Line.unlink(link); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y}); - self.drawLine(line); - if (pos_y == 0) break; - pos_y += 1; - } - while (true) { // clear other downer lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y >= prog.console.size.y - 1) return; - pos_y += 1; - std.time.sleep(draw_lag); - } - } - try self.drawEdited(); - }, - else => { - // draw other lines - try self.drawUpperLines(); - try self.drawDownerLines(); - - // draw edit line - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y }); - if (self.line.tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(self.line); - try self.drawEditedF(); - } - else { - try Theme.line.apply(); - try self.drawLine(self.line); - try self.drawEdited(); - } - }, - } - }, - .to_line => { - self.offset.y = 1; - - // draw banner - try prog.console.changeColor(Theme.headers); - try prog.console.cursorMove(.{ .x = 0, .y = 0}); - try prog.console.out.writeAll("enter the line you want to jump to:"); - try ansi.do(ansi.clear_to_end_line); - - // draw edit line - try prog.console.cursorMove(.{ .x = 0, .y = 1}); - defer self.cursorMoveToCurrent() catch {}; - try self.drawEditedLine(); - - var pos_y: usize = 2; - while (true) { // clear other downer lines - if (pos_y >= prog.console.size.y) return; - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - pos_y += 1; - std.time.sleep(draw_lag); - - } - }, - .easy_motion_vertical, - .easy_motion_horizontal, - .to_find, - .history, - .select, - .normal, - => {}, - } - } // end draw lines - pub fn drawLine (self: *Self, line: *Line) !void { - // move to start - defer ansi.do(ansi.clear_to_end_line) catch {}; - try prog.console.cr(); - if (line.text.used == 0) {return;} - - // draw left-to-right - const text = line.text.get(); - var text_pos: usize = self.symbol - self.offset.x; // first visible rune - var offset_x: usize = 0; - while (true) { - if (text_pos >= text.len) break; - if (offset_x >= prog.console.size.x - 1) break; - prog.console.writeByte(text[text_pos]) catch unreachable; - text_pos += 1; - offset_x += 1; - } - } - pub fn drawParentLine (self: *Self, parent: *Line) !void { - // draw - try prog.console.cr(); - const text = parent.text.get(); - var indent = parent.text.countIndent(1); - var symbol: usize = indent; - if (indent >= self.symbol - self.offset.x) {symbol = self.symbol - self.offset.x;} - var offset_x: usize = 0; - while (true) { - if (symbol >= text.len) { - try ansi.do(ansi.clear_to_end_line); - break; - } - if (offset_x >= prog.console.size.x) break; - prog.console.writeByte(text[symbol]) catch unreachable; - - symbol += 1; - offset_x += 1; - } - } - pub fn drawEdited (self: *Self) !void { - const text: []u8 = self.line.text.get(); - const pos: usize = self.symbol - self.offset.x; - const end_pos: usize = pos + prog.console.size.x; - - if (pos > 0) { // draw '<' - try Theme.outLine.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - prog.console.writeByte('<') catch unreachable; - } - if (text.len > end_pos) { // draw '>' - try Theme.outLine.apply(); - try prog.console.cursorMove(.{ .x = prog.console.size.x - 1, .y = self.offset.y}); - prog.console.writeByte('>') catch unreachable; - } - if (pos < text.len) { // draw symbol about cursor - try self.cursorMoveToCurrent(); - try Theme.currentRune.apply(); - try prog.console.writeByte(text[pos]); - } - } // drawEdited - pub fn drawEditedF (self: *Self) !void { - const text: []u8 = self.line.text.get(); - const pos: usize = self.symbol - self.offset.x; - const end_pos: usize = pos + prog.console.size.x; - - if (pos > 0) { // draw '<' - try Theme.outLineF.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - prog.console.writeByte('<') catch unreachable; - } - if (text.len > end_pos) { // draw '>' - try Theme.outLineF.apply(); - try prog.console.cursorMove(.{ .x = prog.console.size.x - 1, .y = self.offset.y}); - prog.console.writeByte('>') catch unreachable; - } - if (pos < text.len) { // draw symbol about cursor - try self.cursorMoveToCurrent(); - try Theme.currentRuneF.apply(); - try prog.console.writeByte(text[pos]); - } - } // drawEdited - // draw tree - pub fn drawUpperLines (self: *Self) !void { - //TODO: apply self.max_draw_parent_lines = 2; - - // draw lines - if (self.offset.y == 0) return; - var iter = self.line.tree.link.iteratorReverse(); - // skip current - var pos_y: usize = self.offset.y - 1; - _ = iter.next(); - while(iter.next()) |link| { - const tree = Tree.unlink(link); - const line = Line.unTree(tree); - - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - if (tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(line); - } - else { - try Theme.line.apply(); - try self.drawLine(self.line); - } - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - while (true) { // draw parents - try Theme.headers.apply(); - const tree = self.line.tree.parent orelse break; - if (tree == self.tree) break; - const line = Line.untree(tree); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try self.drawParentLine(line); - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - while (true) { // clear other upp lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - } - pub fn drawDownerLines (self: *Self) !void { - var iter = self.line.tree.link.iterator(); - // skip current - var pos_y: usize = self.offset.y + 1; - _ = iter.next(); - - if (pos_y >= prog.console.size.y) return; - while (iter.next) |tree_link| { // draw lines - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - if (line.tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(line); - } - else { - try Theme.line.apply(); - try drawLine(self.line); - } - if (pos_y >= prog.console.size.y - 1) { - self.lines_drawing = prog.console.size.y; - return; - } - pos_y += 1; - std.time.sleep(draw_lag); - } - - self.lines_drawing = pos_y; - while (true) { // clear other downer lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y >= prog.console.size.y - 1) return; - pos_y += 1; - std.time.sleep(draw_lag); - } - } - // } - // { navigation - // over lines - pub fn goToRoot (self: *Self) void { - self.line = self.lines; - self.offset.y = 5; - self.goToStartOfLine(); - prog.need_redraw = true; - self.bakup(); - } - pub fn goToPrevLine (self: *Self) void { - switch(self.fold_mode) { - .flat => { - if (self.link.prev) |prev| { - const line = Line.unlink(prev); - self.line = line; - } - }, - else => { - if (self.line.tree.link.prev) |tree_link| { - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - self.line = line; - prog.need_redraw = true; - } - }, - } - if (self.offset.y > 5) {self.offset.y -= 1;} - self.bakup(); - } // end fn - pub fn goToNextLine (self: *Self) void { - switch(self.fold_mode) { - .flat => { - if (self.link.next) |prev| { - const line = Line.unlink(prev); - self.line = line; - } - }, - else => { - if (self.line.tree.link.next) |tree_link| { - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - self.line = line; - prog.need_redraw = true; - } - }, - } - self.bakup(); - - if (self.offset.y < prog.console.size.y - 1) self.offset.y += 1; - // { correct offset_y: - // count downest_lines - var count_to_downest_line: usize = 0; - var iter = if (self.fold_mode == .flat) self.line.link.iterator() else self.line.tree.chain_link.iterator(); - _ = iter.next(); - while (count_to_downest_line < 5) { - _ = iter.next() orelse break; - count_to_downest_line += 1; - } - - if (prog.console.size.y - self.offset.y < count_to_downest_line) { - self.offset.y = prog.console.size.y - count_to_downest_line; - } - //} - prog.need_redraw = true; - } // end fn - pub fn goToFirstLine (self: *Self) void { - while (self.line.prev) |_| self.goToPrevLine(); - self.goToStartOfLine(); - prog.need_redraw = true; - self.bakup(); - } - pub fn goToLastLine (self: *Self) void { - while (self.line.next) |_| self.goToNextLine(); - prog.need_redraw = true; - self.bakup(); - } - // { go to line from number - pub fn goToLineFromNumber (self: *View, num: usize) void { - if (self.fold_mode != .flat) self.unfold(); - var iter = self.lines.first.iterator(); - var pos = 0; - while(iter.next()) |_| { - if (pos == num) break; - pos += 1; - } - self.line = Line.unlink(iter.current); - - self.offset.y = 6; - self.goToSymbol(self.line.text.countIndent(1)); - if (self.symbol >= 4) self.offset.x = 4; - prog.need_redraw = true; - self.bakup(); - } - pub fn goToLineFromInput (self: *View) !void { - if (self.line.text.used == 0) return; - var num: usize = @truncate(usize, textlib.u64FromCharsDec(self.line.text.get()) catch return); - try self.changeMode(.edit); - self.goToLineFromNumber(num); - } - // } - - // over line - pub fn goToStartOfLine (self: *Self) void { - self.symbol = 0; - self.offset.x = 0; - prog.need_redraw = true; - } - pub fn goToEndOfLine (self: *Self) void { - self.symbol = self.line.text.used; - if (self.symbol > prog.console.size.x - 2) {self.offset.x = prog.console.size.x - 2;} - else {self.offset.x = self.symbol;} - prog.need_redraw = true; - } - pub fn goToStartOfText (self: *Self) void { - const indent = self.line.text.countIndent(1); - self.goToSymbol(indent); - } - pub fn CtrlShiftLeft (self: *Self) void { - const indent = self.line.text.countIndent(1); - if (self.symbol > indent) { - self.goToSymbol(indent); - if (self.symbol >= 4) self.offset.x = 4; - } - else self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn CtrlShiftRight (self: *Self) void { - const indent = self.line.text.countIndent(1); - if (self.symbol < indent) self.goToSymbol(indent) - else self.goToEndOfLine(); - prog.need_redraw = true; - } - - // over word - pub fn goToStartOfWord (self: *Self) void { - if (self.symbol == 0) {return;} - if (self.symbol > self.line.text.used) {self.goToSymbol(self.line.text.used);} - const first_rune = self.line.text.buffer[self.symbol]; - if (first_rune == ' ') { - self.goToPrevSymbol(); - while (true) { - if (self.symbol == 0) {break;} - const rune = self.line.text.buffer[self.symbol]; - if (rune != ' ') break; - self.goToPrevSymbol(); - } - } - else { - self.goToPrevSymbol(); - while(true) { - if (self.symbol == 0) {break;} - const next_symbol = self.line.text.buffer[self.symbol - 1]; - switch(next_symbol){ - ' ', '\t', '\\', - '=', '+', '-', '/', '*', '^', - '!', '@', '#', '$', '%', '&', - '(', ')', '[', ']', '{', '}', - '"', '\'', - ';', ':', '.', ',' - => {break;}, - else => {}, - } - self.goToPrevSymbol(); - } - } - prog.need_redraw = true; - } - pub fn goToEndOfWord (self: *Self) void { - if (self.symbol >= self.line.text.used) {return;} - const first_rune = self.line.text.buffer[self.symbol]; - if (first_rune == ' ') { - while(true) { - self.goToNextSymbol(); - if (self.symbol >= self.line.text.used) {break;} - const rune = self.line.text.buffer[self.symbol]; - if (rune != ' ') break; - } - } - else while(true) { - self.goToNextSymbol(); - if (self.symbol >= self.line.text.used) {break;} - const rune = self.line.text.buffer[self.symbol]; - switch(rune){ - ' ', '\t', '\\', - '=', '+', '-', '/', '*', '^', - '(', ')', '[', ']', '{', '}', - '!', '@', '#', '$', '%', '&', - '"', '\'', - ';', ':', '.', ',' - => {break;}, - else => {}, - } - } - prog.need_redraw = true; - } - - // over symbols - pub fn goToSymbol (self: *Self, pos: usize) void { - self.symbol = pos; - if (self.symbol > prog.console.size.x - 2) { - self.offset.x = prog.console.size.x - 2; - } - else {self.offset.x = self.symbol;} - } - pub fn goToPrevSymbol (self: *Self) void { - const used = self.line.text.used; - if (self.symbol == 0) { - if (true) return; - if (self.line.prev) |_| { - self.goToPrevLine(); - self.goToEndOfLine(); - } - return; - } - if (self.symbol > used) { - self.symbol = used; - if (used < prog.console.size.x - 1) self.offset.x = self.line.text.used; - prog.need_redraw = true; - return; - } - if (self.symbol > 0) self.symbol -= 1; - if (self.symbol >= 10) {if (self.offset.x > 10) {self.offset.x -= 1;}} - else {if (self.offset.x > 0) self.offset.x -= 1;} - prog.need_redraw = true; - } - pub fn goToNextSymbol (self: *Self) void { - const used = self.line.text.used; - if (self.symbol >= used) { - if (true) return; - if (self.line.next) |_| { - self.goToNextLine(); - self.goToStartOfLine(); - } - return; - } - if (self.symbol < Line.Text.size - 1) self.symbol += 1; - if (used - self.symbol >= 10) { - if (self.offset.x < prog.console.size.x - 12) self.offset.x += 1; - } - else { - if (self.offset.x < prog.console.size.x - 2) self.offset.x += 1; - } - prog.need_redraw = true; - } - - //} - // { folding - pub fn unFold (self: *Self) void { - if (self.foldMode == .flat) return; - - // add to chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - self.lines.pushLast(&line.link); - } - - // clear tree - self.tree = .{}; - var iter = self.lines.iter(); - while(iter.next()) |link| { - const line = Line.unlink(link); - line.tree = .{}; - } - - prog.need_redraw = true; - self.foldMode = .byNone; - } // end fn - pub fn foldFromBrackets (self: *Self) void { - self.unFold(); - - // add to tree - var iter = self.lines.iter(); - var current = iter.next() orelse return; - self.tree.addChild(current); - while(iter.next()) |link| { - const line = Line.unlink(link); - const close_count = line.text.getRunesCount('}'); // **{ - const open_count = line.text.getRunesCount('{'); // **} - - if (open_count == close_count) { - current.tree.pushNext(&line.tree); - } - else if (open_count > close_count) { - current.tree.pushChild(&line.tree); - } - else { // for close_count > open_count - var parent = current.tree.parent.?; - if (parent == &self.tree) parent = ¤t.tree; - parent.pushNext(&line.tree); - } - - current = line; - } - - // remove from chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - line.link = .{}; - } - self.lines = .{}; - - prog.need_redraw = true; - self.foldMode = .byBrackets; - } - pub fn foldFromIndent (self: *Self) !void { - self.unFold(); - - var iter = self.lines.iter(); - var current_link = iter.next() orelse return; - var current = Line.unlink(current_link); - var last_indent = current.text.countIndent(4); - self.tree.addChild(¤t.tree); - while(iter.next()) |link| { - const line = Line.unlink(link); - const indent = line.text.countIndent(4); - if (indent == last_indent) { - current.tree.pushNext(&line.tree); - } - else if (indent > last_indent) { - current.tree.pushChild(&line.tree); - } - else { // for last_indent > indent - // find parent with indent > indent - var parent = current.tree.parent.?; - while (true) { - if (parent == &self.tree) {parent = ¤t.tree; break;} - const parent_line = Line.untree(parent); - const parent_indent = parent_line.text.countIndent(4); - if (parent_indent > indent) break; - parent = current.tree.parent.?; - } - parent.pushChild(&line.tree); - } - - current = line; - last_indent = indent; - } - - // remove from chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - line.link = .{}; - } - self.lines = .{}; - - prog.need_redraw = true; - self.foldMode = .byIndent; - } - - pub fn goToIn (self: *Self) void { - if (self.fold_mode == .flat) return; - const child = self.line.child orelse return; - const child_indent = child.text.countIndent(1); - self.goToSymbol(child_indent); - self.symbol = child_indent; - self.line = child; - if (prog.console.size.y > 6) {self.offset.y = 6;} - else if (prog.console.size.y > 3) {self.offset.y = 3;} - else if (prog.console.size.y > 1) {self.offset.y = 1;} - else {self.offset.y = 0;} - self.bakup(); - if (self.symbol >= 4) self.offset.x = 4; - prog.need_redraw = true; - } - pub fn goToOut (self: *Self) void { - if (self.fold_mode == .flat) return; - if (self.line.getParent()) |parent| { - const parent_indent = parent.text.countIndent(1); - self.line = parent; - self.goToSymbol(parent_indent); - self.offset.y = 6; - if (self.symbol >= 4) self.offset.x = 4; - } - else { - self.goToRoot(); - } - self.bakup(); - prog.need_redraw = true; - } - //} - // { clipboard - pub fn externalCopy (self: *Self) !void { - prog.need_redraw = false; - // { create file - var cwd = std.fs.cwd(); - var file = try cwd.createFile(prog.path_to_clipboard.get(), .{}); - defer file.close(); - const writer = file.writer(); - // } - if (prog.buffer_lines.cutted) |cutted| { - // { working with lines - var current: *Line = cutted; - try writer.writeAll(current.text.get()); - copying: while (true) { - if (current.child) |child| { - try writer.writeAll("\n"); - try writer.writeAll(child.text.get()); - current = child; - } - else if (current.next) |next| { - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - next = current.next orelse continue; - break; - } - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - } - // } - { // change status - prog.need_redraw = false; - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.blue2); - try prog.console.out.writeAll("cutted lines saved to ~/clipboard.tmp"); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - } - else { - // { working with lines - const first = self.line; - try writer.writeAll(first.text.get()); - if (first.child) |first_child| { - var current: *Line = first_child; - try writer.writeAll("\n"); - try writer.writeAll(current.text.get()); - copying: while (true) { - if (current.child) |child| { - try writer.writeAll("\n"); - try writer.writeAll(child.text.get()); - current = child; - } - else if (current.next) |next| { - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - if (current == first) break: copying; - next = current.next orelse continue; - break; - } - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - } - } - // } - { // change status - prog.need_redraw = false; - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.blue2); - try prog.console.writeAll("this block saved to ~/clipboard.tmp"); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - } - } - pub fn externalPaste (self: *Self) !void { - // read file - var file_data: []const u8 = undefined; - const loaded = lib.fileRead(prog.allocator, prog.path_to_clipboard.get()); - defer if (loaded) |data| {prog.allocator.free(data);} else |_| {}; - if (loaded) |data| {file_data = data;} else |err| { - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.red2); - try prog.console.writeAll("file ~/clipboard.tmp not reedable."); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - return err; - } - - // paste - const line = self.current_line; - try self.addPrevLine(); - for (file_data) |rune| { // parse lines - switch(rune) { - 10, 13 => {try self.addNextLine();}, - else => {try self.insertSymbol(rune);}, - } - } - self.line = line; - prog.need_redraw = true; - } - //} - // { bakup - pub fn bakup (self: *Self) void { - self.bakup_line.text.set(self.line.text.get()) catch {}; - } - pub fn restore (self: *Self) void { - self.line.text.set(self.bakup_line.text.get()) catch {}; - prog.need_redraw = true; - } - // } - // { indent - pub fn indentToCutie (self: *Self) void { - var current = self.line; - current.changeIndentToCutie() catch {}; - var first = current; - if (first.child) |first_child| { - current = first_child; - traversal: while (true) { - if (current.child) |child| { - current.changeIndentToCutie() catch {}; - current = child; - } - else if (current.next) |next| { - current.changeIndentToCutie() catch {}; - current = next; - } - else { - if (self.foldMode == .byBrackets) { - const parent = current.getParent() orelse break :traversal; - const indent = parent.text.countIndent(1); - current.text.changeIndent(indent) catch {}; - } - else { - current.changeIndentToCutie() catch {}; - } - while (true) { // find parent with next - current = current.getParent() orelse break :traversal; - if (current == first) break :traversal; - if (current.next) |next| { - current = next; - break; - } - } - } - } - } - prog.need_redraw = true; - } - pub fn deleteIndent (self: *Self) void { - var current = self.line; - current.text.changeIndent(0) catch {}; - var first = current; - if (first.child) |first_child| { - current = first_child; - traversal: while (true) { - if (current.child) |child| { - current.text.changeIndent(0) catch {}; - current = child; - } - else if (current.next) |next| { - current.text.changeIndent(0) catch {}; - current = next; - } - else { - current.text.changeIndent(0) catch {}; - while (true) { // find parent with next - current = current.getParent() orelse break :traversal; - if (current == first) break :traversal; - if (current.next) |next| { - current = next; - break; - } - } - } - } - } - prog.need_redraw = true; - } - // } - // { easy motion - pub fn draw_horizontal_help_motion (self: *Self) !void { - var pos: usize = 0; - var rune: u8 = 0x61; - try ansi.do(ansi.color.magenta); - while(true) { - try prog.console.cursorMove(.{ .x = pos, .y = self.offset.y }); - prog.console.writeByte(rune) catch unreachable; - if (rune >= 0x7A) break; rune += 1; - if (pos >= prog.console.size.x - 3) break; pos += 3; - } - try self.cursorMoveToCurrent(); - } - pub fn draw_vertical_help_motion (self: *Self) !void { - var pos: usize = 0; - try ansi.do(ansi.color.magenta); - while(true) { - try prog.console.cursorMove(.{ .x = self.offset.x, .y = pos }); - prog.console.writeByte(0x61 + @truncate(u8, pos)) catch unreachable; - if (pos >= 0x7A - 0x61) break; - if (pos == prog.console.size.y - 1) break; - pos += 1; - } - try self.cursorMoveToCurrent(); - } - pub fn easyMotionHorizontal (self: *Self, key: u8) !void { - var pos = key - 0x61; - self.goToSymbol(self.symbol - self.offset.x + pos * 3); - try self.changeMode(.edit); - prog.need_redraw = true; - } - pub fn easyMotionVertical (self: *Self, key: u8) !void { - var pos = key - 0x61; - if (self.offset.y == pos) {} - else if (self.offset.y > pos) { - var i = self.offset.y - pos; - while (i > 0) : (i -= 1) { - self.goToPrevLine(); - } - } - else { // (self.offset.y < pos) - var i = pos - self.offset.y; - while (i > 0) : (i -= 1) { - self.goToNextLine(); - } - } - try self.changeMode(.edit); - prog.need_redraw = true; - } - // } - - // being developed - pub fn drawRunes (self: *Self) !void { - try prog.console.cursorMove(.{.x = 0, .y = self.offset.y}); - defer self.cursorMoveToCurrent() catch {}; - - try ansi.do(ansi.color.red); - defer ansi.do(ansi.reset) catch {}; - - draw: { - var screen_pos_x: usize = 0; - var text_pos: usize = self.offset.x; // TODO skip first text_pos runes - const runes = self.current_line.runes orelse break: draw; - var link = &runes.link; - while(true) { - if (screen_pos_x >= prog.console.size.x - 3) break; - const rune = Rune.unlink(link); - try prog.console.writeAll(rune.glyph.getText()); - screen_pos_x += 1; - text_pos += 1; - link = link.next orelse break; - } - } - defer ansi.do(ansi.clear_to_end_line) catch {}; - - prog.need_redraw = false; - } - pub fn goToNextFlatLine (self: *Self) void { - const line_link = self.line.chain_link.next orelse return; - self.line = Line.unlink(line_link); - } - pub fn goToPrevFlatLine (self: *Self) void { - const line_link = self.line.chain_link.prev orelse return; - self.line = Line.unlink(line_link); - } - // { selection - // TODO - // } - // { find - pub fn findNext (self: *Self) void { - const text = self.line.text.get(); - var line = self.line; - if (line.text.find(text, self.symbol)) |pos| { // goto pos and return - self.line = line; - self.goToSymbol(pos); - return; - } - else { // iterate and find - while(true) { - // iterate - if (line.child) |child| { // goto child - line = child; - } - else if (line.next) |next| { // goto next - line = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - line = line.getParent() orelse return; - next = line.next orelse continue; - break; - } - line = next; - } - - // find - if (line.text.find(text, 0)) |pos| { // goto pos and return - self.line = line; - self.goToSymbol(pos); - return; - } - } - } - self.changeMode(.edit); - prog.need_clear = true; - prog.need_redraw = true; - self.bakup(); - } - // } -// } DELETED src/ViewFind.zig Index: src/ViewFind.zig ================================================================== --- src/ViewFind.zig +++ /dev/null @@ -1,1649 +0,0 @@ -// this file is just gabarage. -// i rewrite this in future. - -// { fields - file_name: Text = .{}, - - // modes - mode: Mode = .edit, - indent: Indent = .{}, - - lines: linkedList.Chain = .{}, - - bakup_line: *Line = undefined, - last_working_line: ?*Line = null, - marked_line: ?*Line = null, - lines_drawing: usize = 0, - - // current pos - current_line: *Line, - offset: lib.Coor2u = .{.x = 0, .y = 0 }, - symbol: usize = 0, - to_goto: ?*Line, - to_find: ?*Line, -// } -// { methods - pub fn onKey (self: *Self, cik: Console.Input.Key) !void { - switch (self.view.mode) { - .edit => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .mouse => {try self.onMouse();}, - .f1 => {try self.view.goToHelp();}, - .f1_rxvt => {try self.view.goToHelp();}, - .f1_tty => {try self.view.goToHelp();}, - .f2 => {self.debug.toggle();}, - .f2_rxvt => {self.debug.toggle();}, - .f2_tty => {self.debug.toggle();}, - .f3 => {self.view.goToPrevFlatLine();}, - .f4 => {self.view.goToNextFlatLine();}, - .f5 => {try self.view.drawRunes();}, - .f9 => {try self.view.changeMode(.normal);}, - .f10 => {self.stop();}, - - .delete => {self.view.deleteSymbol();}, - .shift_delete => {self.view.clearLine();}, - - .end => {self.view.goToEndOfLine();}, - .home => {self.view.goToStartOfLine();}, - - .down => {self.view.goToNextLine();}, - .up => {self.view.goToPrevLine();}, - .left => {self.view.goToPrevSymbol();}, - .right => {self.view.goToNextSymbol();}, - .ctrl_shift_left => {self.view.CtrlShiftLeft();}, - .ctrl_shift_right => {self.view.CtrlShiftRight();}, - .ctrl_left => {self.view.goToStartOfWord();}, - .ctrl_left_rxvt => {self.view.goToStartOfWord();}, - .ctrl_right => {self.view.goToEndOfWord();}, - .ctrl_right_rxvt => {self.view.goToEndOfWord();}, - .ctrl_up => {self.view.goToFirstLine();}, - .ctrl_down => {self.view.goToLastLine();}, - .alt_up => {self.view.swapWithUpper();}, - .alt_down => {self.view.swapWithBottom();}, - - .alt_n => {self.view.insertSymbol('\n') catch {};}, - .alt_r => {self.view.insertSymbol('\r') catch {};}, - .alt_v => {self.view.externalPaste() catch {};}, - .alt_m => {self.view.markThisLine();}, - .alt_j => {self.view.goToMarked();}, - .alt_p => {self.view.deleteIndent();}, - - else => {self.need_redraw = true;}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - self.need_redraw = true; - }, - .ascii_key => |key| { - switch (key) { - .ctrl_q => {self.stop();}, - .ctrl_s => {self.view.save() catch {};}, - .ctrl_g => {try self.view.changeMode(.to_line);}, - .ctrl_f => {try self.view.changeMode(.to_find);}, - .ctrl_u => {self.view.unFold();}, - .ctrl_r => {try self.view.foldFromIndent();}, - .ctrl_e => {self.view.foldFromBrackets();}, - .ctrl_j => {self.view.joinLines();}, - .enter => { - switch (self.console.input.is_paste) { - true => {self.view.addNextLine() catch {};}, - false => {self.view.divide() catch {};}, - } - }, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_p => {self.view.indentToCutie();}, - .ctrl_d => {self.view.duplicate();}, - .ctrl_x => {self.view.cut();}, - .ctrl_c => {self.view.externalCopy() catch {};}, - .ctrl_v => {self.view.pasteLine();}, - .ctrl_t => {self.view.insertSymbol('\t') catch {};}, - .escape => {self.view.goToOut();}, - .tab => {self.view.goToIn();}, - .ctrl_w => {self.view.deleteWord();}, - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .ctrl_z => {self.view.restore();}, - .ctrl_o => {try self.view.drawRunes();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .to_find => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .ctrl_left => self.view.goToStartOfLine(), - .ctrl_right => self.view.goToEndOfLine(), - .delete => self.view.deleteSymbol(), - .shift_delete => {self.view.clearLine();}, - else => {}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - }, - .ascii_key => |key| { - switch (key) { - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_j => {self.view.findNext();}, - .enter => {self.view.findNext();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .to_line => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .ctrl_left => self.view.goToStartOfLine(), - .ctrl_right => self.view.goToEndOfLine(), - .delete => self.view.deleteSymbol(), - .shift_delete => {self.view.clearLine();}, - else => {}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - }, - .ascii_key => |key| { - switch (key) { - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_j => {try self.view.goToLineFromInput();}, - .enter => {try self.view.goToLineFromInput();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .history => {}, - .select => {}, - .normal => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .delete => {self.view.deleteSymbol();}, - .shift_delete => {self.view.clearLine();}, - .end => {self.view.goToEndOfLine();}, - .home => {self.view.goToStartOfLine();}, - .down => {self.view.goToNextLine();}, - .up => {self.view.goToPrevLine();}, - .left => {self.view.goToPrevSymbol();}, - .right => {self.view.goToNextSymbol();}, - else => {}, - } - }, - .byte => |_| {}, - .ascii_key => |key| { - switch (key) { - .code_q => {self.stop();}, - .code_s => {self.view.save() catch {};}, - .code_i => {try self.view.changeMode(.edit);}, - .code_g => {try self.view.changeMode(.to_line);}, - .code_u => {self.view.unFold();}, - .code_r => {try self.view.foldFromIndent();}, - .code_e => {self.view.foldFromBrackets();}, - .code_j => {self.view.divide() catch {};}, - .enter => {self.view.divide() catch {};}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .code_p => {self.view.line.changeIndentToCutie() catch {};}, - .code_d => {self.view.duplicate();}, - .code_x => {self.view.cut();}, - .code_c => {self.view.externalCopy() catch {};}, - .code_v => {self.view.pasteLine();}, - .code_t => {self.view.insertSymbol('\t') catch {};}, - .escape => {self.view.goToOut();}, - .tab => {self.view.goToIn();}, - .code_l => {self.view.goToLastLine();}, - else => {}, - } - }, - } - }, - .easy_motion_vertical => { - switch (cik) { - .sequence => |_| {}, - .byte => |_| {}, - .ascii_key => |key| { - const num = @enumToInt(key); - if (num >= 0x61 and num <= 0x7A) {try self.view.easyMotionVertical(num);} - else switch (key) { - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - else => {}, - } - }, - } - }, - .easy_motion_horizontal => { - switch (cik) { - .sequence => |_| {}, - .byte => |_| {}, - .ascii_key => |key| { - const num = @enumToInt(key); - if (num >= 0x61 and num <= 0x7A) {try self.view.easyMotionHorizontal(num);} - else switch (key) { - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - else => {}, - } - }, - } - }, - } - } - pub fn fromAlloc () !*View { - const allocated = lib.c.aligned_alloc(8, @sizeOf(View)) orelse return error.NeedMoreMemory; - var view: *View = @ptrCast(*View, @alignCast(8, allocated)); - return view; - } - pub fn init (self: *Self, file_name: []const u8, text: []const u8) !void { - self.* = .{}; - self.file_name.set(file_name) catch unreachable; - { // parse_text_to_lines - var iter = std.mem.split(u8, text, "\n"); - while(iter.next()) |line| { - const new_line = try prog.buffer_lines.create(); - new_line.text.set(line) catch { - return error.LineIsToLong; - }; - self.lines.pushLast(&new_line.chain_link); - } - } - const link = self.lines.first.?; - self.current_line = Line.unlink(link); - self.bakup_line = try prog.buffer_lines.create(); - } // end fn loadLines - pub fn save (self: *Self) !void { - prog.need_redraw = false; - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(Theme.save); - try prog.console.writeAll("saving..."); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - // { create file - var cwd = std.fs.cwd(); - var file = try cwd.createFile(self.file_name.get(), .{}); - defer file.close(); - const writer = file.writer(); - // } - var count: usize = 0; // lines - write: { //write - switch(self.fold_mode) { - .flat => { - var iter = self.lines.iter(); - - // write first line - const first_link = iter.next() orelse break: write; - const first_line = Line.unLink(first_link); - count += 1; - try writer.writeAll(first_line.text.get()); - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try prog.console.out.print("{} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - - // write other lines - while(iter.next()) |link| { - try writer.writeAll("\n"); - const line = Line.unlink(link); - count += 1; - try writer.writeAll(line.text.get()); - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try prog.console.out.print("{} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - } - }, - else => { - var walker = self.tree.walker(); - _ = walker.next(); // skip root - - // save first line (without "\n") - const first_tree = walker.next() orelse break: write; - const first_line = Line.untree(first_tree); - count += 1; - try writer.writeAll(first_line.text.get()); - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try prog.console.out.print("{} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - - // save other lines (with "\n") - while(walker.next()) |tree| { - try writer.writeAll("\n"); - const line = Line.untree(tree); - count += 1; - try writer.writeAll(line.text.get()); - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try prog.console.out.print("{} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - } - }, - } - } - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - defer self.cursorMoveToCurrent() catch {}; - - try ansi.do(Theme.save); - defer ansi.do(ansi.reset) catch {}; - - try prog.console.out.print("file saved. {} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - } - pub fn changeMode (self: *Self, mode: Mode) !void { - switch (mode) { - .edit => {}, - .to_find => { - self.last_working_line = self.current_line; - }, - .to_line => { - self.last_working_line = self.current_line; - if (prog.buffer_lines.to_goto == null) { // create - const new_line = prog.buffer_lines.create() catch return; - prog.buffer_lines.to_goto = new_line; - } - self.current_line = prog.buffer_lines.to_goto.?; - self.goToEndOfLine(); - prog.need_redraw = true; - }, - .history => {}, - .select => {}, - .normal => {}, - .easy_motion_vertical => { - try self.draw_vertical_help_motion(); - }, - .easy_motion_horizontal => { - try self.draw_horizontal_help_motion(); - }, - } - self.mode = mode; - } - pub fn cursorMoveToCurrent (self: *Self) !void { - try prog.console.cursorMove(.{ .x = self.offset.x, .y = self.offset.y }); - } - pub fn goToHelp (self: *Self) !void { - self.current_line = prog.usage_line; - prog.need_redraw = true; - } - // { edit - pub fn paste (self: *Self) void { - if (prog.buffer_lines.cutted) |cutted| { - prog.buffer_lines.cutted = cutted.next; - cutted.next = null; - self.line.pushPrev(cutted); - if (self.lines == self.line) self.lines = cutted; - self.offset.y += 1; - self.goToPrevLine(); - self.indentToCutie(); - } - prog.need_redraw = true; - } - - // line - pub fn joinLines (self: *Self) void { - if (self.line.child) |_| return; - const next = self.line; - const prev = self.line.prev orelse return; - - self.deleteIndent(); - - const next_used = next.text.used; - const prev_used = prev.text.used; - - if (prev_used + next_used > Line.Text.size - 3) return; - std.mem.copy(u8, prev.text.buffer[prev.text.used..], next.text.get()); - prev.text.used += next_used; - prog.buffer_lines.delete(self.line); - self.line = prev; - self.goToSymbol(prev_used); - } - pub fn clearLine (self: *Self) void { - self.line.text.used = 0; - self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn addPrevLine (self: *Self) !void { - const new_line = try prog.buffer_lines.create(); - switch(self.fold_mode) { - .flat => { - self.lines.pushPrev(self.current_line, &new_line.link); - }, - else => { - var tree = &self.current_line.tree; - tree.link.pushPrev(&new_line.tree); - }, - } - self.current_line = new_line; - self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn addNextLine (self: *Self) !void { - const new_line = try prog.buffer_lines.create(); - switch(self.fold_mode) { - .flat => { - self.lines.pushNext(self.current_line, &new_line.link); - }, - else => { - var tree = &self.current_line.tree; - tree.link.pushNext(&new_line.tree); - }, - } - self.current_line = new_line; - self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn divide (self: *Self) !void { - const indent = self.line.text.countIndent(1); - if (self.symbol <= indent) { // just add prev line - const last_symbol = self.symbol; - const last_offset = self.offset.x; - try self.addPrevLine(); - try self.line.changeIndentToCutie(); - self.goToNextLine(); - self.symbol = last_symbol; - self.offset.x = last_offset; - } - else if (self.symbol >= self.line.text.used) { // just add next line - if (self.line.text.buffer[self.symbol - 1] == ':') { - if (self.line.child) |_| return; - const new_line = prog.buffer_lines.create() catch return; - // { link - self.line.child = new_line; - new_line.parent = self.line; - // } - self.goToIn(); - } - else { - try self.addNextLine(); - } - } - else if (self.line.text.buffer[self.symbol] == '}' and self.line.text.buffer[self.symbol - 1] == '{') { - if (self.line.child != null) return; - const pos = self.symbol; - const last_line = self.line; - - const new_line = prog.buffer_lines.create() catch return; - // { link - self.line.child = new_line; - new_line.parent = self.line; - // } - // { copy text and fill spaces - const text_to_new_line = last_line.text.get()[pos..]; - std.mem.copy(u8, new_line.text.buffer[indent..], text_to_new_line); - for (new_line.text.buffer[0 .. indent]) |*rune| rune.* = ' '; // spam spaces - new_line.text.used = indent + text_to_new_line.len; - last_line.text.used = pos; - // } - - self.line = new_line; - try self.addPrevLine(); - } - else { - if (self.line.child) |_| return; - var parent = self.line; - var pos = self.symbol; - const text = self.line.text.get()[pos..]; - try self.addNextLine(); - self.line.text.used = indent + text.len; - std.mem.copy(u8, self.line.text.buffer[indent..], text); - for (self.line.text.buffer[0..indent]) |*rune| rune.* = ' '; - parent.text.used = pos; - } - self.indentToCutie(); - self.goToStartOfText(); - if (false) { // change status (debug) - const last_cursor_pos: lib.Coor2u = prog.console.cursor.pos; - defer { // reset color, clear line, restore cursor pos and flush - defer Console.Output.print(ansi.reset); - Console.Output.print(ansi.clear_to_end_line); - defer prog.console.cursorMove(last_cursor_pos); - Console.Output.flush(); - } - - prog.console.cursorMove(.{ .x = 0, .y = 0 }); - Console.Output.print(ansi.color.red2); - - var buffer: [254]u8 = undefined; - var text_len: usize = 0; - var sprintf_result = lib.c.sprintf(&buffer, "line used = %d", self.line.text.used); - text_len += @intCast(usize, sprintf_result); - prog.console.print(buffer[0 .. text_len]); - } - if (self.symbol >= 4) self.offset.x = 4; - prog.need_redraw = true; - } - pub fn swapWithBottom (self: *Self) void { - const current_link = &self.current_line.link; - if (self.current_line.next) |_| { - self.cut(); - self.goToNextLine(); - self.pasteLine(); - } - prog.need_redraw = true; - } - pub fn swapWithUpper (self: *Self) void { - if (self.line.prev) |_| { - self.cut(); - self.goToPrevLine(); - self.pasteLine(); - } - prog.need_redraw = true; - } - pub fn deleteLine (self: *Self) void { - const line = self.line; - var next_selected_line: *Line = undefined; - if (line.next) |next| { - next_selected_line = next; - } - else if (line.prev) |prev| { - next_selected_line = prev; - } - else if (line.parent) |parent| { - next_selected_line = parent; - } - else { // clear and exit - self.clearLine(); - return; - } - self.clearLine(); - if (self.lines == self.line) self.lines = next_selected_line; - prog.buffer_lines.delete(self.line); - self.line = next_selected_line; - prog.need_redraw = true; - } - - // word - pub fn deleteWord (self: *Self) void { - if (self.symbol > self.line.text.used) {return;} - while(true) { // delete current symbol - if (self.symbol == self.line.text.used) {break;} - const next_symbol = self.line.text.buffer[self.symbol]; - if (textlib.isLetter(next_symbol)) {self.deleteSymbol();} else {break;} - } - while(true) { // delete prev symbol - if (self.symbol == 0) {break;} - const prev_symbol = self.line.text.buffer[self.symbol - 1]; - if (textlib.isLetter(prev_symbol)) {self.deletePrevSymbol();} else {break;} - } - prog.need_redraw = true; - } - - // symbol - pub fn insertSymbol (self: *Self, rune: u8) !void { - const t = &self.current_line.text; - if (self.symbol > t.used) self.goToSymbol(t.used); - try t.insert(self.symbol, rune); - self.goToNextSymbol(); - prog.need_redraw = true; - } // end fn - pub fn deleteSymbol (self: *Self) void { - if (self.line.text.used == 0) return; - self.line.text.delete(self.symbol) catch return; - prog.need_redraw = true; - } - pub fn deletePrevSymbol (self: *Self) void { - switch (self.symbol) { - 0 => { - if (self.line.parent) |_| return; - if (self.line.child) |_| return; - if (self.line == self.lines) return; - - const prev = self.line.prev orelse return; - - const non_indent = self.line.text.countNonIndent(); - if (non_indent == 0) { // delete self line - prog.buffer_lines.delete(self.line); - self.line = prev; - prog.need_redraw = true; - return; - } - - const prev_count = prev.text.countNonIndent(); - switch (prev_count) { - 0 => { // delete prev - if (self.lines == prev) self.lines = self.line; - prog.buffer_lines.delete(prev); - prog.need_redraw = true; - return; - }, - else => { // join line - self.joinLines(); - }, - } - }, - else => { - if (self.line.text.used == 0) return; - self.goToPrevSymbol(); - self.deleteSymbol(); - }, - } - prog.need_redraw = true; - } - //} - // { draw - pub fn draw (self: *Self) !void { - try ansi.do(ansi.cyrsor_style.hide); - defer ansi.do(ansi.cyrsor_style.show) catch {}; - defer self.cursorMoveToCurrent() catch {}; - if (self.symbol < self.offset.x) { // unexpected - self.offset = .{}; - self.symbol = 0; - } - switch (self.mode) { - .edit => { - switch (self.fold_mode) { - .flat => { - Theme.line.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - try self.drawLine(); - if (self.offset.y > 0) { // draw upper lines - var iter = self.line.link.iterReverse(); - - // skip current; - var pos_y = self.offset.y - 1; - _ = iter.next(); - - while(iter.next()) |link| { - const line = Line.unlink(link); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y}); - self.drawLine(line); - if (pos_y == 0) break; - pos_y -= 1; - } - } - if (self.offset.y < prog.console.size.y) { // draw downer lines - var iter = self.line.link.iter(); - - // skip current; - var pos_y = self.offset.y + 1; - _ = iter.next(); - - while(iter.next()) |link| { - const line = Line.unlink(link); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y}); - self.drawLine(line); - if (pos_y == 0) break; - pos_y += 1; - } - while (true) { // clear other downer lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y >= prog.console.size.y - 1) return; - pos_y += 1; - std.time.sleep(draw_lag); - } - } - try self.drawEdited(); - }, - else => { - // draw other lines - try self.drawUpperLines(); - try self.drawDownerLines(); - - // draw edit line - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y }); - if (self.line.tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(self.line); - try self.drawEditedF(); - } - else { - try Theme.line.apply(); - try self.drawLine(self.line); - try self.drawEdited(); - } - }, - } - }, - .to_line => { - self.offset.y = 1; - - // draw banner - try prog.console.changeColor(Theme.headers); - try prog.console.cursorMove(.{ .x = 0, .y = 0}); - try prog.console.out.writeAll("enter the line you want to jump to:"); - try ansi.do(ansi.clear_to_end_line); - - // draw edit line - try prog.console.cursorMove(.{ .x = 0, .y = 1}); - defer self.cursorMoveToCurrent() catch {}; - try self.drawEditedLine(); - - var pos_y: usize = 2; - while (true) { // clear other downer lines - if (pos_y >= prog.console.size.y) return; - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - pos_y += 1; - std.time.sleep(draw_lag); - - } - }, - .easy_motion_vertical, - .easy_motion_horizontal, - .to_find, - .history, - .select, - .normal, - => {}, - } - } // end draw lines - pub fn drawLine (self: *Self, line: *Line) !void { - // move to start - defer ansi.do(ansi.clear_to_end_line) catch {}; - try prog.console.cr(); - if (line.text.used == 0) {return;} - - // draw left-to-right - const text = line.text.get(); - var text_pos: usize = self.symbol - self.offset.x; // first visible rune - var offset_x: usize = 0; - while (true) { - if (text_pos >= text.len) break; - if (offset_x >= prog.console.size.x - 1) break; - prog.console.writeByte(text[text_pos]) catch unreachable; - text_pos += 1; - offset_x += 1; - } - } - pub fn drawParentLine (self: *Self, parent: *Line) !void { - // draw - try prog.console.cr(); - const text = parent.text.get(); - var indent = parent.text.countIndent(1); - var symbol: usize = indent; - if (indent >= self.symbol - self.offset.x) {symbol = self.symbol - self.offset.x;} - var offset_x: usize = 0; - while (true) { - if (symbol >= text.len) { - try ansi.do(ansi.clear_to_end_line); - break; - } - if (offset_x >= prog.console.size.x) break; - prog.console.writeByte(text[symbol]) catch unreachable; - - symbol += 1; - offset_x += 1; - } - } - pub fn drawEdited (self: *Self) !void { - const text: []u8 = self.line.text.get(); - const pos: usize = self.symbol - self.offset.x; - const end_pos: usize = pos + prog.console.size.x; - - if (pos > 0) { // draw '<' - try Theme.outLine.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - prog.console.writeByte('<') catch unreachable; - } - if (text.len > end_pos) { // draw '>' - try Theme.outLine.apply(); - try prog.console.cursorMove(.{ .x = prog.console.size.x - 1, .y = self.offset.y}); - prog.console.writeByte('>') catch unreachable; - } - if (pos < text.len) { // draw symbol about cursor - try self.cursorMoveToCurrent(); - try Theme.currentRune.apply(); - try prog.console.writeByte(text[pos]); - } - } // drawEdited - pub fn drawEditedF (self: *Self) !void { - const text: []u8 = self.line.text.get(); - const pos: usize = self.symbol - self.offset.x; - const end_pos: usize = pos + prog.console.size.x; - - if (pos > 0) { // draw '<' - try Theme.outLineF.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - prog.console.writeByte('<') catch unreachable; - } - if (text.len > end_pos) { // draw '>' - try Theme.outLineF.apply(); - try prog.console.cursorMove(.{ .x = prog.console.size.x - 1, .y = self.offset.y}); - prog.console.writeByte('>') catch unreachable; - } - if (pos < text.len) { // draw symbol about cursor - try self.cursorMoveToCurrent(); - try Theme.currentRuneF.apply(); - try prog.console.writeByte(text[pos]); - } - } // drawEdited - // draw tree - pub fn drawUpperLines (self: *Self) !void { - //TODO: apply self.max_draw_parent_lines = 2; - - // draw lines - if (self.offset.y == 0) return; - var iter = self.line.tree.link.iteratorReverse(); - // skip current - var pos_y: usize = self.offset.y - 1; - _ = iter.next(); - while(iter.next()) |link| { - const tree = Tree.unlink(link); - const line = Line.unTree(tree); - - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - if (tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(line); - } - else { - try Theme.line.apply(); - try self.drawLine(self.line); - } - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - while (true) { // draw parents - try Theme.headers.apply(); - const tree = self.line.tree.parent orelse break; - if (tree == self.tree) break; - const line = Line.untree(tree); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try self.drawParentLine(line); - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - while (true) { // clear other upp lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - } - pub fn drawDownerLines (self: *Self) !void { - var iter = self.line.tree.link.iterator(); - // skip current - var pos_y: usize = self.offset.y + 1; - _ = iter.next(); - - if (pos_y >= prog.console.size.y) return; - while (iter.next) |tree_link| { // draw lines - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - if (line.tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(line); - } - else { - try Theme.line.apply(); - try drawLine(self.line); - } - if (pos_y >= prog.console.size.y - 1) { - self.lines_drawing = prog.console.size.y; - return; - } - pos_y += 1; - std.time.sleep(draw_lag); - } - - self.lines_drawing = pos_y; - while (true) { // clear other downer lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y >= prog.console.size.y - 1) return; - pos_y += 1; - std.time.sleep(draw_lag); - } - } - // } - // { navigation - // over lines - pub fn goToRoot (self: *Self) void { - self.line = self.lines; - self.offset.y = 5; - self.goToStartOfLine(); - prog.need_redraw = true; - self.bakup(); - } - pub fn goToPrevLine (self: *Self) void { - switch(self.fold_mode) { - .flat => { - if (self.link.prev) |prev| { - const line = Line.unlink(prev); - self.line = line; - } - }, - else => { - if (self.line.tree.link.prev) |tree_link| { - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - self.line = line; - prog.need_redraw = true; - } - }, - } - if (self.offset.y > 5) {self.offset.y -= 1;} - self.bakup(); - } // end fn - pub fn goToNextLine (self: *Self) void { - switch(self.fold_mode) { - .flat => { - if (self.link.next) |prev| { - const line = Line.unlink(prev); - self.line = line; - } - }, - else => { - if (self.line.tree.link.next) |tree_link| { - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - self.line = line; - prog.need_redraw = true; - } - }, - } - self.bakup(); - - if (self.offset.y < prog.console.size.y - 1) self.offset.y += 1; - // { correct offset_y: - // count downest_lines - var count_to_downest_line: usize = 0; - var iter = if (self.fold_mode == .flat) self.line.link.iterator() else self.line.tree.chain_link.iterator(); - _ = iter.next(); - while (count_to_downest_line < 5) { - _ = iter.next() orelse break; - count_to_downest_line += 1; - } - - if (prog.console.size.y - self.offset.y < count_to_downest_line) { - self.offset.y = prog.console.size.y - count_to_downest_line; - } - //} - prog.need_redraw = true; - } // end fn - pub fn goToFirstLine (self: *Self) void { - while (self.line.prev) |_| self.goToPrevLine(); - self.goToStartOfLine(); - prog.need_redraw = true; - self.bakup(); - } - pub fn goToLastLine (self: *Self) void { - while (self.line.next) |_| self.goToNextLine(); - prog.need_redraw = true; - self.bakup(); - } - // { go to line from number - pub fn goToLineFromNumber (self: *View, num: usize) void { - if (self.fold_mode != .flat) self.unfold(); - var iter = self.lines.first.iterator(); - var pos = 0; - while(iter.next()) |_| { - if (pos == num) break; - pos += 1; - } - self.line = Line.unlink(iter.current); - - self.offset.y = 6; - self.goToSymbol(self.line.text.countIndent(1)); - if (self.symbol >= 4) self.offset.x = 4; - prog.need_redraw = true; - self.bakup(); - } - pub fn goToLineFromInput (self: *View) !void { - if (self.line.text.used == 0) return; - var num: usize = @truncate(usize, textlib.u64FromCharsDec(self.line.text.get()) catch return); - try self.changeMode(.edit); - self.goToLineFromNumber(num); - } - // } - - // over line - pub fn goToStartOfLine (self: *Self) void { - self.symbol = 0; - self.offset.x = 0; - prog.need_redraw = true; - } - pub fn goToEndOfLine (self: *Self) void { - self.symbol = self.line.text.used; - if (self.symbol > prog.console.size.x - 2) {self.offset.x = prog.console.size.x - 2;} - else {self.offset.x = self.symbol;} - prog.need_redraw = true; - } - pub fn goToStartOfText (self: *Self) void { - const indent = self.line.text.countIndent(1); - self.goToSymbol(indent); - } - pub fn CtrlShiftLeft (self: *Self) void { - const indent = self.line.text.countIndent(1); - if (self.symbol > indent) { - self.goToSymbol(indent); - if (self.symbol >= 4) self.offset.x = 4; - } - else self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn CtrlShiftRight (self: *Self) void { - const indent = self.line.text.countIndent(1); - if (self.symbol < indent) self.goToSymbol(indent) - else self.goToEndOfLine(); - prog.need_redraw = true; - } - - // over word - pub fn goToStartOfWord (self: *Self) void { - if (self.symbol == 0) {return;} - if (self.symbol > self.line.text.used) {self.goToSymbol(self.line.text.used);} - const first_rune = self.line.text.buffer[self.symbol]; - if (first_rune == ' ') { - self.goToPrevSymbol(); - while (true) { - if (self.symbol == 0) {break;} - const rune = self.line.text.buffer[self.symbol]; - if (rune != ' ') break; - self.goToPrevSymbol(); - } - } - else { - self.goToPrevSymbol(); - while(true) { - if (self.symbol == 0) {break;} - const next_symbol = self.line.text.buffer[self.symbol - 1]; - switch(next_symbol){ - ' ', '\t', '\\', - '=', '+', '-', '/', '*', '^', - '!', '@', '#', '$', '%', '&', - '(', ')', '[', ']', '{', '}', - '"', '\'', - ';', ':', '.', ',' - => {break;}, - else => {}, - } - self.goToPrevSymbol(); - } - } - prog.need_redraw = true; - } - pub fn goToEndOfWord (self: *Self) void { - if (self.symbol >= self.line.text.used) {return;} - const first_rune = self.line.text.buffer[self.symbol]; - if (first_rune == ' ') { - while(true) { - self.goToNextSymbol(); - if (self.symbol >= self.line.text.used) {break;} - const rune = self.line.text.buffer[self.symbol]; - if (rune != ' ') break; - } - } - else while(true) { - self.goToNextSymbol(); - if (self.symbol >= self.line.text.used) {break;} - const rune = self.line.text.buffer[self.symbol]; - switch(rune){ - ' ', '\t', '\\', - '=', '+', '-', '/', '*', '^', - '(', ')', '[', ']', '{', '}', - '!', '@', '#', '$', '%', '&', - '"', '\'', - ';', ':', '.', ',' - => {break;}, - else => {}, - } - } - prog.need_redraw = true; - } - - // over symbols - pub fn goToSymbol (self: *Self, pos: usize) void { - self.symbol = pos; - if (self.symbol > prog.console.size.x - 2) { - self.offset.x = prog.console.size.x - 2; - } - else {self.offset.x = self.symbol;} - } - pub fn goToPrevSymbol (self: *Self) void { - const used = self.line.text.used; - if (self.symbol == 0) { - if (true) return; - if (self.line.prev) |_| { - self.goToPrevLine(); - self.goToEndOfLine(); - } - return; - } - if (self.symbol > used) { - self.symbol = used; - if (used < prog.console.size.x - 1) self.offset.x = self.line.text.used; - prog.need_redraw = true; - return; - } - if (self.symbol > 0) self.symbol -= 1; - if (self.symbol >= 10) {if (self.offset.x > 10) {self.offset.x -= 1;}} - else {if (self.offset.x > 0) self.offset.x -= 1;} - prog.need_redraw = true; - } - pub fn goToNextSymbol (self: *Self) void { - const used = self.line.text.used; - if (self.symbol >= used) { - if (true) return; - if (self.line.next) |_| { - self.goToNextLine(); - self.goToStartOfLine(); - } - return; - } - if (self.symbol < Line.Text.size - 1) self.symbol += 1; - if (used - self.symbol >= 10) { - if (self.offset.x < prog.console.size.x - 12) self.offset.x += 1; - } - else { - if (self.offset.x < prog.console.size.x - 2) self.offset.x += 1; - } - prog.need_redraw = true; - } - - //} - // { folding - pub fn unFold (self: *Self) void { - if (self.foldMode == .flat) return; - - // add to chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - self.lines.pushLast(&line.link); - } - - // clear tree - self.tree = .{}; - var iter = self.lines.iter(); - while(iter.next()) |link| { - const line = Line.unlink(link); - line.tree = .{}; - } - - prog.need_redraw = true; - self.foldMode = .byNone; - } // end fn - pub fn foldFromBrackets (self: *Self) void { - self.unFold(); - - // add to tree - var iter = self.lines.iter(); - var current = iter.next() orelse return; - self.tree.addChild(current); - while(iter.next()) |link| { - const line = Line.unlink(link); - const close_count = line.text.getRunesCount('}'); // **{ - const open_count = line.text.getRunesCount('{'); // **} - - if (open_count == close_count) { - current.tree.pushNext(&line.tree); - } - else if (open_count > close_count) { - current.tree.pushChild(&line.tree); - } - else { // for close_count > open_count - var parent = current.tree.parent.?; - if (parent == &self.tree) parent = ¤t.tree; - parent.pushNext(&line.tree); - } - - current = line; - } - - // remove from chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - line.link = .{}; - } - self.lines = .{}; - - prog.need_redraw = true; - self.foldMode = .byBrackets; - } - pub fn foldFromIndent (self: *Self) !void { - self.unFold(); - - var iter = self.lines.iter(); - var current_link = iter.next() orelse return; - var current = Line.unlink(current_link); - var last_indent = current.text.countIndent(4); - self.tree.addChild(¤t.tree); - while(iter.next()) |link| { - const line = Line.unlink(link); - const indent = line.text.countIndent(4); - if (indent == last_indent) { - current.tree.pushNext(&line.tree); - } - else if (indent > last_indent) { - current.tree.pushChild(&line.tree); - } - else { // for last_indent > indent - // find parent with indent > indent - var parent = current.tree.parent.?; - while (true) { - if (parent == &self.tree) {parent = ¤t.tree; break;} - const parent_line = Line.untree(parent); - const parent_indent = parent_line.text.countIndent(4); - if (parent_indent > indent) break; - parent = current.tree.parent.?; - } - parent.pushChild(&line.tree); - } - - current = line; - last_indent = indent; - } - - // remove from chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - line.link = .{}; - } - self.lines = .{}; - - prog.need_redraw = true; - self.foldMode = .byIndent; - } - - pub fn goToIn (self: *Self) void { - if (self.fold_mode == .flat) return; - const child = self.line.child orelse return; - const child_indent = child.text.countIndent(1); - self.goToSymbol(child_indent); - self.symbol = child_indent; - self.line = child; - if (prog.console.size.y > 6) {self.offset.y = 6;} - else if (prog.console.size.y > 3) {self.offset.y = 3;} - else if (prog.console.size.y > 1) {self.offset.y = 1;} - else {self.offset.y = 0;} - self.bakup(); - if (self.symbol >= 4) self.offset.x = 4; - prog.need_redraw = true; - } - pub fn goToOut (self: *Self) void { - if (self.fold_mode == .flat) return; - if (self.line.getParent()) |parent| { - const parent_indent = parent.text.countIndent(1); - self.line = parent; - self.goToSymbol(parent_indent); - self.offset.y = 6; - if (self.symbol >= 4) self.offset.x = 4; - } - else { - self.goToRoot(); - } - self.bakup(); - prog.need_redraw = true; - } - //} - // { clipboard - pub fn externalCopy (self: *Self) !void { - prog.need_redraw = false; - // { create file - var cwd = std.fs.cwd(); - var file = try cwd.createFile(prog.path_to_clipboard.get(), .{}); - defer file.close(); - const writer = file.writer(); - // } - if (prog.buffer_lines.cutted) |cutted| { - // { working with lines - var current: *Line = cutted; - try writer.writeAll(current.text.get()); - copying: while (true) { - if (current.child) |child| { - try writer.writeAll("\n"); - try writer.writeAll(child.text.get()); - current = child; - } - else if (current.next) |next| { - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - next = current.next orelse continue; - break; - } - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - } - // } - { // change status - prog.need_redraw = false; - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.blue2); - try prog.console.out.writeAll("cutted lines saved to ~/clipboard.tmp"); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - } - else { - // { working with lines - const first = self.line; - try writer.writeAll(first.text.get()); - if (first.child) |first_child| { - var current: *Line = first_child; - try writer.writeAll("\n"); - try writer.writeAll(current.text.get()); - copying: while (true) { - if (current.child) |child| { - try writer.writeAll("\n"); - try writer.writeAll(child.text.get()); - current = child; - } - else if (current.next) |next| { - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - if (current == first) break: copying; - next = current.next orelse continue; - break; - } - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - } - } - // } - { // change status - prog.need_redraw = false; - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.blue2); - try prog.console.writeAll("this block saved to ~/clipboard.tmp"); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - } - } - pub fn externalPaste (self: *Self) !void { - // read file - var file_data: []const u8 = undefined; - const loaded = lib.fileRead(prog.allocator, prog.path_to_clipboard.get()); - defer if (loaded) |data| {prog.allocator.free(data);} else |_| {}; - if (loaded) |data| {file_data = data;} else |err| { - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.red2); - try prog.console.writeAll("file ~/clipboard.tmp not reedable."); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - return err; - } - - // paste - const line = self.current_line; - try self.addPrevLine(); - for (file_data) |rune| { // parse lines - switch(rune) { - 10, 13 => {try self.addNextLine();}, - else => {try self.insertSymbol(rune);}, - } - } - self.line = line; - prog.need_redraw = true; - } - //} - // { bakup - pub fn bakup (self: *Self) void { - self.bakup_line.text.set(self.line.text.get()) catch {}; - } - pub fn restore (self: *Self) void { - self.line.text.set(self.bakup_line.text.get()) catch {}; - prog.need_redraw = true; - } - // } - // { indent - pub fn indentToCutie (self: *Self) void { - var current = self.line; - current.changeIndentToCutie() catch {}; - var first = current; - if (first.child) |first_child| { - current = first_child; - traversal: while (true) { - if (current.child) |child| { - current.changeIndentToCutie() catch {}; - current = child; - } - else if (current.next) |next| { - current.changeIndentToCutie() catch {}; - current = next; - } - else { - if (self.foldMode == .byBrackets) { - const parent = current.getParent() orelse break :traversal; - const indent = parent.text.countIndent(1); - current.text.changeIndent(indent) catch {}; - } - else { - current.changeIndentToCutie() catch {}; - } - while (true) { // find parent with next - current = current.getParent() orelse break :traversal; - if (current == first) break :traversal; - if (current.next) |next| { - current = next; - break; - } - } - } - } - } - prog.need_redraw = true; - } - pub fn deleteIndent (self: *Self) void { - var current = self.line; - current.text.changeIndent(0) catch {}; - var first = current; - if (first.child) |first_child| { - current = first_child; - traversal: while (true) { - if (current.child) |child| { - current.text.changeIndent(0) catch {}; - current = child; - } - else if (current.next) |next| { - current.text.changeIndent(0) catch {}; - current = next; - } - else { - current.text.changeIndent(0) catch {}; - while (true) { // find parent with next - current = current.getParent() orelse break :traversal; - if (current == first) break :traversal; - if (current.next) |next| { - current = next; - break; - } - } - } - } - } - prog.need_redraw = true; - } - // } - // { easy motion - pub fn draw_horizontal_help_motion (self: *Self) !void { - var pos: usize = 0; - var rune: u8 = 0x61; - try ansi.do(ansi.color.magenta); - while(true) { - try prog.console.cursorMove(.{ .x = pos, .y = self.offset.y }); - prog.console.writeByte(rune) catch unreachable; - if (rune >= 0x7A) break; rune += 1; - if (pos >= prog.console.size.x - 3) break; pos += 3; - } - try self.cursorMoveToCurrent(); - } - pub fn draw_vertical_help_motion (self: *Self) !void { - var pos: usize = 0; - try ansi.do(ansi.color.magenta); - while(true) { - try prog.console.cursorMove(.{ .x = self.offset.x, .y = pos }); - prog.console.writeByte(0x61 + @truncate(u8, pos)) catch unreachable; - if (pos >= 0x7A - 0x61) break; - if (pos == prog.console.size.y - 1) break; - pos += 1; - } - try self.cursorMoveToCurrent(); - } - pub fn easyMotionHorizontal (self: *Self, key: u8) !void { - var pos = key - 0x61; - self.goToSymbol(self.symbol - self.offset.x + pos * 3); - try self.changeMode(.edit); - prog.need_redraw = true; - } - pub fn easyMotionVertical (self: *Self, key: u8) !void { - var pos = key - 0x61; - if (self.offset.y == pos) {} - else if (self.offset.y > pos) { - var i = self.offset.y - pos; - while (i > 0) : (i -= 1) { - self.goToPrevLine(); - } - } - else { // (self.offset.y < pos) - var i = pos - self.offset.y; - while (i > 0) : (i -= 1) { - self.goToNextLine(); - } - } - try self.changeMode(.edit); - prog.need_redraw = true; - } - // } - - // being developed - pub fn drawRunes (self: *Self) !void { - try prog.console.cursorMove(.{.x = 0, .y = self.offset.y}); - defer self.cursorMoveToCurrent() catch {}; - - try ansi.do(ansi.color.red); - defer ansi.do(ansi.reset) catch {}; - - draw: { - var screen_pos_x: usize = 0; - var text_pos: usize = self.offset.x; // TODO skip first text_pos runes - const runes = self.current_line.runes orelse break: draw; - var link = &runes.link; - while(true) { - if (screen_pos_x >= prog.console.size.x - 3) break; - const rune = Rune.unlink(link); - try prog.console.writeAll(rune.glyph.getText()); - screen_pos_x += 1; - text_pos += 1; - link = link.next orelse break; - } - } - defer ansi.do(ansi.clear_to_end_line) catch {}; - - prog.need_redraw = false; - } - pub fn goToNextFlatLine (self: *Self) void { - const line_link = self.line.chain_link.next orelse return; - self.line = Line.unlink(line_link); - } - pub fn goToPrevFlatLine (self: *Self) void { - const line_link = self.line.chain_link.prev orelse return; - self.line = Line.unlink(line_link); - } - // { selection - // TODO - // } - // { find - pub fn findNext (self: *Self) void { - const text = self.line.text.get(); - var line = self.line; - if (line.text.find(text, self.symbol)) |pos| { // goto pos and return - self.line = line; - self.goToSymbol(pos); - return; - } - else { // iterate and find - while(true) { - // iterate - if (line.child) |child| { // goto child - line = child; - } - else if (line.next) |next| { // goto next - line = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - line = line.getParent() orelse return; - next = line.next orelse continue; - break; - } - line = next; - } - - // find - if (line.text.find(text, 0)) |pos| { // goto pos and return - self.line = line; - self.goToSymbol(pos); - return; - } - } - } - self.changeMode(.edit); - prog.need_clear = true; - prog.need_redraw = true; - self.bakup(); - } - // } -// } DELETED src/ViewFlat.zig Index: src/ViewFlat.zig ================================================================== --- src/ViewFlat.zig +++ /dev/null @@ -1,1788 +0,0 @@ -// this file is just gabarage. -// i rewrite this in future. - -const G = @import("root"); -const T = @This(); - -const Text = G.ScalpiEditor.Text; -const Window = G.ScalpiEditor.Window; -const Line = G.ScalpiEditor.Line; -const Rune = G.ScalpiEditor.Rune; -const Theme = G.ScalpiEditor.Theme; -const draw_lag = G.ScalpiEditor.draw_lag; - -// todo: replace this: -const Self = @This(); -const View = @This(); -const lib = G.lib; -const ansi = G.ansi; -const std = G.std; -const Console = G.Console; - -file_name: *Text = .{}, -bakup_line: ?*G.Line = null, -last_working_line: ?*G.Line = null, -marked_line: ?*G.Line = null, - -lines: G.LinkedList = .{}, -current_line: ?*G.Line = null, -symbol: usize = 0, - -offset: G.lib.Coor2u = .{.x = 0, .y = 0 }, // current pos -lines_drawing: usize = 0, - -pub fn do (t: *T) { - try self.updateSize(); -} -// { methods - pub fn onMouse (self: *Self) !void { - const mode = prog.console.input.buffer[3]; - if (mode != ' ') return; - - var coor_x = prog.console.input.buffer[4]; - if (coor_x < 33) { - try ansi.do(ansi.color.yellow); - try prog.console.out.print("x = {d}", .{coor_x}); - return; - } - coor_x -= 33; - self.view.goToSymbol(self.view.symbol - self.view.offset.x + coor_x); - - var coor_y = prog.console.input.buffer[5]; - if (coor_y < 35) { - try ansi.do(ansi.color.yellow); - try prog.console.out.print("x = {d}", .{coor_x}); - return; - } - coor_y -= 35; - if (self.view.offset.y == coor_y) {} - else if (self.view.offset.y > coor_y) { - var i = self.view.offset.y - coor_y; - while (i > 0) : (i -= 1) { - self.view.goToPrevLine(); - } - } - else { // (self.view.offset.y < coor_y) - var i = coor_y - self.view.offset.y; - while (i > 0) : (i -= 1) { - self.view.goToNextLine(); - } - } - - prog.need_redraw = true; - } - pub fn onKey (self: *Self, cik: Console.Input.Key) !void { - switch (self.view.mode) { - .edit => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .mouse => {try self.onMouse();}, - .f1 => {try self.view.goToHelp();}, - .f1_rxvt => {try self.view.goToHelp();}, - .f1_tty => {try self.view.goToHelp();}, - .f2 => {self.debug.toggle();}, - .f2_rxvt => {self.debug.toggle();}, - .f2_tty => {self.debug.toggle();}, - .f3 => {self.view.goToPrevFlatLine();}, - .f4 => {self.view.goToNextFlatLine();}, - .f5 => {try self.view.drawRunes();}, - .f9 => {try self.view.changeMode(.normal);}, - .f10 => {self.stop();}, - - .delete => {self.view.deleteSymbol();}, - .shift_delete => {self.view.clearLine();}, - - .end => {self.view.goToEndOfLine();}, - .home => {self.view.goToStartOfLine();}, - - .down => {self.view.goToNextLine();}, - .up => {self.view.goToPrevLine();}, - .left => {self.view.goToPrevSymbol();}, - .right => {self.view.goToNextSymbol();}, - .ctrl_shift_left => {self.view.CtrlShiftLeft();}, - .ctrl_shift_right => {self.view.CtrlShiftRight();}, - .ctrl_left => {self.view.goToStartOfWord();}, - .ctrl_left_rxvt => {self.view.goToStartOfWord();}, - .ctrl_right => {self.view.goToEndOfWord();}, - .ctrl_right_rxvt => {self.view.goToEndOfWord();}, - .ctrl_up => {self.view.goToFirstLine();}, - .ctrl_down => {self.view.goToLastLine();}, - .alt_up => {self.view.swapWithUpper();}, - .alt_down => {self.view.swapWithBottom();}, - - .alt_n => {self.view.insertSymbol('\n') catch {};}, - .alt_r => {self.view.insertSymbol('\r') catch {};}, - .alt_v => {self.view.externalPaste() catch {};}, - .alt_m => {self.view.markThisLine();}, - .alt_j => {self.view.goToMarked();}, - .alt_p => {self.view.deleteIndent();}, - - else => {self.need_redraw = true;}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - self.need_redraw = true; - }, - .ascii_key => |key| { - switch (key) { - .ctrl_q => {self.stop();}, - .ctrl_s => {self.view.save() catch {};}, - .ctrl_g => {try self.view.changeMode(.to_line);}, - .ctrl_f => {try self.view.changeMode(.to_find);}, - .ctrl_u => {self.view.unFold();}, - .ctrl_r => {try self.view.foldFromIndent();}, - .ctrl_e => {self.view.foldFromBrackets();}, - .ctrl_j => {self.view.joinLines();}, - .enter => { - switch (self.console.input.is_paste) { - true => {self.view.addNextLine() catch {};}, - false => {self.view.divide() catch {};}, - } - }, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_p => {self.view.indentToCutie();}, - .ctrl_d => {self.view.duplicate();}, - .ctrl_x => {self.view.cut();}, - .ctrl_c => {self.view.externalCopy() catch {};}, - .ctrl_v => {self.view.pasteLine();}, - .ctrl_t => {self.view.insertSymbol('\t') catch {};}, - .escape => {self.view.goToOut();}, - .tab => {self.view.goToIn();}, - .ctrl_w => {self.view.deleteWord();}, - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .ctrl_z => {self.view.restore();}, - .ctrl_o => {try self.view.drawRunes();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .to_find => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .ctrl_left => self.view.goToStartOfLine(), - .ctrl_right => self.view.goToEndOfLine(), - .delete => self.view.deleteSymbol(), - .shift_delete => {self.view.clearLine();}, - else => {}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - }, - .ascii_key => |key| { - switch (key) { - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_j => {self.view.findNext();}, - .enter => {self.view.findNext();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .to_line => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .ctrl_left => self.view.goToStartOfLine(), - .ctrl_right => self.view.goToEndOfLine(), - .delete => self.view.deleteSymbol(), - .shift_delete => {self.view.clearLine();}, - else => {}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - }, - .ascii_key => |key| { - switch (key) { - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_j => {try self.view.goToLineFromInput();}, - .enter => {try self.view.goToLineFromInput();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .history => {}, - .select => {}, - .normal => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .delete => {self.view.deleteSymbol();}, - .shift_delete => {self.view.clearLine();}, - .end => {self.view.goToEndOfLine();}, - .home => {self.view.goToStartOfLine();}, - .down => {self.view.goToNextLine();}, - .up => {self.view.goToPrevLine();}, - .left => {self.view.goToPrevSymbol();}, - .right => {self.view.goToNextSymbol();}, - else => {}, - } - }, - .byte => |_| {}, - .ascii_key => |key| { - switch (key) { - .code_q => {self.stop();}, - .code_s => {self.view.save() catch {};}, - .code_i => {try self.view.changeMode(.edit);}, - .code_g => {try self.view.changeMode(.to_line);}, - .code_u => {self.view.unFold();}, - .code_r => {try self.view.foldFromIndent();}, - .code_e => {self.view.foldFromBrackets();}, - .code_j => {self.view.divide() catch {};}, - .enter => {self.view.divide() catch {};}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .code_p => {self.view.line.changeIndentToCutie() catch {};}, - .code_d => {self.view.duplicate();}, - .code_x => {self.view.cut();}, - .code_c => {self.view.externalCopy() catch {};}, - .code_v => {self.view.pasteLine();}, - .code_t => {self.view.insertSymbol('\t') catch {};}, - .escape => {self.view.goToOut();}, - .tab => {self.view.goToIn();}, - .code_l => {self.view.goToLastLine();}, - else => {}, - } - }, - } - }, - .easy_motion_vertical => { - switch (cik) { - .sequence => |_| {}, - .byte => |_| {}, - .ascii_key => |key| { - const num = @enumToInt(key); - if (num >= 0x61 and num <= 0x7A) {try self.view.easyMotionVertical(num);} - else switch (key) { - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - else => {}, - } - }, - } - }, - .easy_motion_horizontal => { - switch (cik) { - .sequence => |_| {}, - .byte => |_| {}, - .ascii_key => |key| { - const num = @enumToInt(key); - if (num >= 0x61 and num <= 0x7A) {try self.view.easyMotionHorizontal(num);} - else switch (key) { - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - else => {}, - } - }, - } - }, - } - } - pub fn fromAlloc () !*View { - const allocated = lib.c.aligned_alloc(8, @sizeOf(View)) orelse return error.NeedMoreMemory; - var view: *View = @ptrCast(*View, @alignCast(8, allocated)); - return view; - } - pub fn init (self: *Self, file_name: []const u8, text: []const u8) !void { - self.* = .{}; - self.file_name.set(file_name) catch unreachable; - { // parse_text_to_lines - var iter = std.mem.split(u8, text, "\n"); - while(iter.next()) |line| { - const new_line = try prog.buffer_lines.create(); - new_line.text.set(line) catch { - return error.LineIsToLong; - }; - self.lines.pushLast(&new_line.chain_link); - } - } - const link = self.lines.first.?; - self.current_line = Line.unlink(link); - self.bakup_line = try prog.buffer_lines.create(); - } // end fn loadLines - pub fn save (self: *Self) !void { - prog.need_redraw = false; - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(Theme.save); - try prog.console.writeAll("saving..."); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - // { create file - var cwd = std.fs.cwd(); - var file = try cwd.createFile(self.file_name.get(), .{}); - defer file.close(); - const writer = file.writer(); - // } - var count: usize = 0; // lines - write: { //write - switch(self.fold_mode) { - .flat => { - var iter = self.lines.iter(); - - // write first line - const first_link = iter.next() orelse break: write; - const first_line = Line.unLink(first_link); - count += 1; - try writer.writeAll(first_line.text.get()); - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try prog.console.out.print("{} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - - // write other lines - while(iter.next()) |link| { - try writer.writeAll("\n"); - const line = Line.unlink(link); - count += 1; - try writer.writeAll(line.text.get()); - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try prog.console.out.print("{} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - } - }, - else => { - var walker = self.tree.walker(); - _ = walker.next(); // skip root - - // save first line (without "\n") - const first_tree = walker.next() orelse break: write; - const first_line = Line.untree(first_tree); - count += 1; - try writer.writeAll(first_line.text.get()); - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try prog.console.out.print("{} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - - // save other lines (with "\n") - while(walker.next()) |tree| { - try writer.writeAll("\n"); - const line = Line.untree(tree); - count += 1; - try writer.writeAll(line.text.get()); - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try prog.console.out.print("{} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - } - }, - } - } - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - defer self.cursorMoveToCurrent() catch {}; - - try ansi.do(Theme.save); - defer ansi.do(ansi.reset) catch {}; - - try prog.console.out.print("file saved. {} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - } - pub fn changeMode (self: *Self, mode: Mode) !void { - switch (mode) { - .edit => {}, - .to_find => { - self.last_working_line = self.current_line; - }, - .to_line => { - self.last_working_line = self.current_line; - if (prog.buffer_lines.to_goto == null) { // create - const new_line = prog.buffer_lines.create() catch return; - prog.buffer_lines.to_goto = new_line; - } - self.current_line = prog.buffer_lines.to_goto.?; - self.goToEndOfLine(); - prog.need_redraw = true; - }, - .history => {}, - .select => {}, - .normal => {}, - .easy_motion_vertical => { - try self.draw_vertical_help_motion(); - }, - .easy_motion_horizontal => { - try self.draw_horizontal_help_motion(); - }, - } - self.mode = mode; - } - pub fn cursorMoveToCurrent (self: *Self) !void { - try prog.console.cursorMove(.{ .x = self.offset.x, .y = self.offset.y }); - } - pub fn goToHelp (self: *Self) !void { - self.current_line = prog.usage_line; - prog.need_redraw = true; - } - // { mark - pub fn markThisLine (self: *Self) void { - self.marked_line = self.line; - } - pub fn goToMarked (self: *Self) void { - if (self.marked_line) |mark| { - self.line = mark; - prog.need_redraw = true; - } - } - // } - // { edit - // block - pub fn duplicate (self: *Self) void { - const first = self.line; - const copy_first = prog.buffer_lines.create() catch return; - copy_first.text.set(first.text.get()) catch unreachable; - self.line.pushNext(copy_first); - if (first.child) |first_child| { - var current = first_child; - var copy_current = prog.buffer_lines.create() catch return; - copy_current.text.set(current.text.get()) catch unreachable; - copy_current.parent = copy_first; - copy_first.child = copy_current; - copying: while (true) { - if (current.child) |child| { - var copy_child = prog.buffer_lines.create() catch return; - copy_child.text.set(child.text.get()) catch unreachable; - copy_child.parent = copy_current; - copy_current.child = copy_child; - current = child; - copy_current = copy_child; - } - else if (current.next) |next| { - var copy_next = prog.buffer_lines.create() catch return; - copy_next.text.set(next.text.get()) catch unreachable; - copy_next.prev = copy_current; - copy_current.next = copy_next; - current = next; - copy_current = copy_next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - if (current == first) break: copying; - copy_current = copy_current.getParent() orelse unreachable; - next = current.next orelse continue; - break; - } - var copy_next = prog.buffer_lines.create() catch return; - copy_next.text.set(next.text.get()) catch unreachable; - copy_next.prev = copy_current; - copy_current.next = copy_next; - current = next; - copy_current = copy_next; - } - } - } - self.line = copy_first; - prog.need_redraw = true; - } - pub fn cut (self: *Self) void { - if (self.line.parent) |parent| { - parent.child = self.line.next; - } - var next_selected_line: *Line = undefined; - // { select next selected line - if (self.line.next) |next| { - next_selected_line = next; - } else if (self.line.prev) |prev| { - next_selected_line = prev; - } else if (self.line.parent) |parent| { - next_selected_line = parent; - } else { - self.line.text.set("") catch unreachable; - return; - } - // } - if (self.lines == self.line) self.lines = next_selected_line; - prog.buffer_lines.cut(self.line); - self.line = next_selected_line; - prog.need_redraw = true; - self.bakup(); - } - pub fn pasteLine (self: *Self) void { - if (prog.buffer_lines.cutted) |cutted| { - prog.buffer_lines.cutted = cutted.next; - cutted.next = null; - self.line.pushPrev(cutted); - if (self.lines == self.line) self.lines = cutted; - self.offset.y += 1; - self.goToPrevLine(); - self.indentToCutie(); - } - prog.need_redraw = true; - } - - // line - pub fn joinLines (self: *Self) void { - if (self.line.child) |_| return; - const next = self.line; - const prev = self.line.prev orelse return; - - self.deleteIndent(); - - const next_used = next.text.used; - const prev_used = prev.text.used; - - if (prev_used + next_used > Line.Text.size - 3) return; - std.mem.copy(u8, prev.text.buffer[prev.text.used..], next.text.get()); - prev.text.used += next_used; - prog.buffer_lines.delete(self.line); - self.line = prev; - self.goToSymbol(prev_used); - } - pub fn clearLine (self: *Self) void { - self.line.text.used = 0; - self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn addPrevLine (self: *Self) !void { - const new_line = try prog.buffer_lines.create(); - switch(self.fold_mode) { - .flat => { - self.lines.pushPrev(self.current_line, &new_line.link); - }, - else => { - var tree = &self.current_line.tree; - tree.link.pushPrev(&new_line.tree); - }, - } - self.current_line = new_line; - self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn addNextLine (self: *Self) !void { - const new_line = try prog.buffer_lines.create(); - switch(self.fold_mode) { - .flat => { - self.lines.pushNext(self.current_line, &new_line.link); - }, - else => { - var tree = &self.current_line.tree; - tree.link.pushNext(&new_line.tree); - }, - } - self.current_line = new_line; - self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn divide (self: *Self) !void { - const indent = self.line.text.countIndent(1); - if (self.symbol <= indent) { // just add prev line - const last_symbol = self.symbol; - const last_offset = self.offset.x; - try self.addPrevLine(); - try self.line.changeIndentToCutie(); - self.goToNextLine(); - self.symbol = last_symbol; - self.offset.x = last_offset; - } - else if (self.symbol >= self.line.text.used) { // just add next line - if (self.line.text.buffer[self.symbol - 1] == ':') { - if (self.line.child) |_| return; - const new_line = prog.buffer_lines.create() catch return; - // { link - self.line.child = new_line; - new_line.parent = self.line; - // } - self.goToIn(); - } - else { - try self.addNextLine(); - } - } - else if (self.line.text.buffer[self.symbol] == '}' and self.line.text.buffer[self.symbol - 1] == '{') { - if (self.line.child != null) return; - const pos = self.symbol; - const last_line = self.line; - - const new_line = prog.buffer_lines.create() catch return; - // { link - self.line.child = new_line; - new_line.parent = self.line; - // } - // { copy text and fill spaces - const text_to_new_line = last_line.text.get()[pos..]; - std.mem.copy(u8, new_line.text.buffer[indent..], text_to_new_line); - for (new_line.text.buffer[0 .. indent]) |*rune| rune.* = ' '; // spam spaces - new_line.text.used = indent + text_to_new_line.len; - last_line.text.used = pos; - // } - - self.line = new_line; - try self.addPrevLine(); - } - else { - if (self.line.child) |_| return; - var parent = self.line; - var pos = self.symbol; - const text = self.line.text.get()[pos..]; - try self.addNextLine(); - self.line.text.used = indent + text.len; - std.mem.copy(u8, self.line.text.buffer[indent..], text); - for (self.line.text.buffer[0..indent]) |*rune| rune.* = ' '; - parent.text.used = pos; - } - self.indentToCutie(); - self.goToStartOfText(); - if (false) { // change status (debug) - const last_cursor_pos: lib.Coor2u = prog.console.cursor.pos; - defer { // reset color, clear line, restore cursor pos and flush - defer Console.Output.print(ansi.reset); - Console.Output.print(ansi.clear_to_end_line); - defer prog.console.cursorMove(last_cursor_pos); - Console.Output.flush(); - } - - prog.console.cursorMove(.{ .x = 0, .y = 0 }); - Console.Output.print(ansi.color.red2); - - var buffer: [254]u8 = undefined; - var text_len: usize = 0; - var sprintf_result = lib.c.sprintf(&buffer, "line used = %d", self.line.text.used); - text_len += @intCast(usize, sprintf_result); - prog.console.print(buffer[0 .. text_len]); - } - if (self.symbol >= 4) self.offset.x = 4; - prog.need_redraw = true; - } - pub fn swapWithBottom (self: *Self) void { - const current_link = &self.current_line.link; - if (self.current_line.next) |_| { - self.cut(); - self.goToNextLine(); - self.pasteLine(); - } - prog.need_redraw = true; - } - pub fn swapWithUpper (self: *Self) void { - if (self.line.prev) |_| { - self.cut(); - self.goToPrevLine(); - self.pasteLine(); - } - prog.need_redraw = true; - } - pub fn deleteLine (self: *Self) void { - const line = self.line; - var next_selected_line: *Line = undefined; - if (line.next) |next| { - next_selected_line = next; - } - else if (line.prev) |prev| { - next_selected_line = prev; - } - else if (line.parent) |parent| { - next_selected_line = parent; - } - else { // clear and exit - self.clearLine(); - return; - } - self.clearLine(); - if (self.lines == self.line) self.lines = next_selected_line; - prog.buffer_lines.delete(self.line); - self.line = next_selected_line; - prog.need_redraw = true; - } - - // word - pub fn deleteWord (self: *Self) void { - if (self.symbol > self.line.text.used) {return;} - while(true) { // delete current symbol - if (self.symbol == self.line.text.used) {break;} - const next_symbol = self.line.text.buffer[self.symbol]; - if (textlib.isLetter(next_symbol)) {self.deleteSymbol();} else {break;} - } - while(true) { // delete prev symbol - if (self.symbol == 0) {break;} - const prev_symbol = self.line.text.buffer[self.symbol - 1]; - if (textlib.isLetter(prev_symbol)) {self.deletePrevSymbol();} else {break;} - } - prog.need_redraw = true; - } - - // symbol - pub fn insertSymbol (self: *Self, rune: u8) !void { - const t = &self.current_line.text; - if (self.symbol > t.used) self.goToSymbol(t.used); - try t.insert(self.symbol, rune); - self.goToNextSymbol(); - prog.need_redraw = true; - } // end fn - pub fn deleteSymbol (self: *Self) void { - if (self.line.text.used == 0) return; - self.line.text.delete(self.symbol) catch return; - prog.need_redraw = true; - } - pub fn deletePrevSymbol (self: *Self) void { - switch (self.symbol) { - 0 => { - if (self.line.parent) |_| return; - if (self.line.child) |_| return; - if (self.line == self.lines) return; - - const prev = self.line.prev orelse return; - - const non_indent = self.line.text.countNonIndent(); - if (non_indent == 0) { // delete self line - prog.buffer_lines.delete(self.line); - self.line = prev; - prog.need_redraw = true; - return; - } - - const prev_count = prev.text.countNonIndent(); - switch (prev_count) { - 0 => { // delete prev - if (self.lines == prev) self.lines = self.line; - prog.buffer_lines.delete(prev); - prog.need_redraw = true; - return; - }, - else => { // join line - self.joinLines(); - }, - } - }, - else => { - if (self.line.text.used == 0) return; - self.goToPrevSymbol(); - self.deleteSymbol(); - }, - } - prog.need_redraw = true; - } - //} - // { draw - pub fn draw (self: *Self) !void { - try ansi.do(ansi.cyrsor_style.hide); - defer ansi.do(ansi.cyrsor_style.show) catch {}; - defer self.cursorMoveToCurrent() catch {}; - if (self.symbol < self.offset.x) { // unexpected - self.offset = .{}; - self.symbol = 0; - } - switch (self.mode) { - .edit => { - switch (self.fold_mode) { - .flat => { - Theme.line.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - try self.drawLine(); - if (self.offset.y > 0) { // draw upper lines - var iter = self.line.link.iterReverse(); - - // skip current; - var pos_y = self.offset.y - 1; - _ = iter.next(); - - while(iter.next()) |link| { - const line = Line.unlink(link); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y}); - self.drawLine(line); - if (pos_y == 0) break; - pos_y -= 1; - } - } - if (self.offset.y < prog.console.size.y) { // draw downer lines - var iter = self.line.link.iter(); - - // skip current; - var pos_y = self.offset.y + 1; - _ = iter.next(); - - while(iter.next()) |link| { - const line = Line.unlink(link); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y}); - self.drawLine(line); - if (pos_y == 0) break; - pos_y += 1; - } - while (true) { // clear other downer lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y >= prog.console.size.y - 1) return; - pos_y += 1; - std.time.sleep(draw_lag); - } - } - try self.drawEdited(); - }, - else => { - // draw other lines - try self.drawUpperLines(); - try self.drawDownerLines(); - - // draw edit line - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y }); - if (self.line.tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(self.line); - try self.drawEditedF(); - } - else { - try Theme.line.apply(); - try self.drawLine(self.line); - try self.drawEdited(); - } - }, - } - }, - .to_line => { - self.offset.y = 1; - - // draw banner - try prog.console.changeColor(Theme.headers); - try prog.console.cursorMove(.{ .x = 0, .y = 0}); - try prog.console.out.writeAll("enter the line you want to jump to:"); - try ansi.do(ansi.clear_to_end_line); - - // draw edit line - try prog.console.cursorMove(.{ .x = 0, .y = 1}); - defer self.cursorMoveToCurrent() catch {}; - try self.drawEditedLine(); - - var pos_y: usize = 2; - while (true) { // clear other downer lines - if (pos_y >= prog.console.size.y) return; - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - pos_y += 1; - std.time.sleep(draw_lag); - - } - }, - .easy_motion_vertical, - .easy_motion_horizontal, - .to_find, - .history, - .select, - .normal, - => {}, - } - } // end draw lines - pub fn drawLine (self: *Self, line: *Line) !void { - // move to start - defer ansi.do(ansi.clear_to_end_line) catch {}; - try prog.console.cr(); - if (line.text.used == 0) {return;} - - // draw left-to-right - const text = line.text.get(); - var text_pos: usize = self.symbol - self.offset.x; // first visible rune - var offset_x: usize = 0; - while (true) { - if (text_pos >= text.len) break; - if (offset_x >= prog.console.size.x - 1) break; - prog.console.writeByte(text[text_pos]) catch unreachable; - text_pos += 1; - offset_x += 1; - } - } - pub fn drawParentLine (self: *Self, parent: *Line) !void { - // draw - try prog.console.cr(); - const text = parent.text.get(); - var indent = parent.text.countIndent(1); - var symbol: usize = indent; - if (indent >= self.symbol - self.offset.x) {symbol = self.symbol - self.offset.x;} - var offset_x: usize = 0; - while (true) { - if (symbol >= text.len) { - try ansi.do(ansi.clear_to_end_line); - break; - } - if (offset_x >= prog.console.size.x) break; - prog.console.writeByte(text[symbol]) catch unreachable; - - symbol += 1; - offset_x += 1; - } - } - pub fn drawEdited (self: *Self) !void { - const text: []u8 = self.line.text.get(); - const pos: usize = self.symbol - self.offset.x; - const end_pos: usize = pos + prog.console.size.x; - - if (pos > 0) { // draw '<' - try Theme.outLine.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - prog.console.writeByte('<') catch unreachable; - } - if (text.len > end_pos) { // draw '>' - try Theme.outLine.apply(); - try prog.console.cursorMove(.{ .x = prog.console.size.x - 1, .y = self.offset.y}); - prog.console.writeByte('>') catch unreachable; - } - if (pos < text.len) { // draw symbol about cursor - try self.cursorMoveToCurrent(); - try Theme.currentRune.apply(); - try prog.console.writeByte(text[pos]); - } - } // drawEdited - pub fn drawEditedF (self: *Self) !void { - const text: []u8 = self.line.text.get(); - const pos: usize = self.symbol - self.offset.x; - const end_pos: usize = pos + prog.console.size.x; - - if (pos > 0) { // draw '<' - try Theme.outLineF.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - prog.console.writeByte('<') catch unreachable; - } - if (text.len > end_pos) { // draw '>' - try Theme.outLineF.apply(); - try prog.console.cursorMove(.{ .x = prog.console.size.x - 1, .y = self.offset.y}); - prog.console.writeByte('>') catch unreachable; - } - if (pos < text.len) { // draw symbol about cursor - try self.cursorMoveToCurrent(); - try Theme.currentRuneF.apply(); - try prog.console.writeByte(text[pos]); - } - } // drawEdited - // draw tree - pub fn drawUpperLines (self: *Self) !void { - //TODO: apply self.max_draw_parent_lines = 2; - - // draw lines - if (self.offset.y == 0) return; - var iter = self.line.tree.link.iteratorReverse(); - // skip current - var pos_y: usize = self.offset.y - 1; - _ = iter.next(); - while(iter.next()) |link| { - const tree = Tree.unlink(link); - const line = Line.unTree(tree); - - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - if (tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(line); - } - else { - try Theme.line.apply(); - try self.drawLine(self.line); - } - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - while (true) { // draw parents - try Theme.headers.apply(); - const tree = self.line.tree.parent orelse break; - if (tree == self.tree) break; - const line = Line.untree(tree); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try self.drawParentLine(line); - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - while (true) { // clear other upp lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - } - pub fn drawDownerLines (self: *Self) !void { - var iter = self.line.tree.link.iterator(); - // skip current - var pos_y: usize = self.offset.y + 1; - _ = iter.next(); - - if (pos_y >= prog.console.size.y) return; - while (iter.next) |tree_link| { // draw lines - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - if (line.tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(line); - } - else { - try Theme.line.apply(); - try drawLine(self.line); - } - if (pos_y >= prog.console.size.y - 1) { - self.lines_drawing = prog.console.size.y; - return; - } - pos_y += 1; - std.time.sleep(draw_lag); - } - - self.lines_drawing = pos_y; - while (true) { // clear other downer lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y >= prog.console.size.y - 1) return; - pos_y += 1; - std.time.sleep(draw_lag); - } - } - // } - // { navigation - // over lines - pub fn goToRoot (self: *Self) void { - self.line = self.lines; - self.offset.y = 5; - self.goToStartOfLine(); - prog.need_redraw = true; - self.bakup(); - } - pub fn goToPrevLine (self: *Self) void { - switch(self.fold_mode) { - .flat => { - if (self.link.prev) |prev| { - const line = Line.unlink(prev); - self.line = line; - } - }, - else => { - if (self.line.tree.link.prev) |tree_link| { - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - self.line = line; - prog.need_redraw = true; - } - }, - } - if (self.offset.y > 5) {self.offset.y -= 1;} - self.bakup(); - } // end fn - pub fn goToNextLine (self: *Self) void { - switch(self.fold_mode) { - .flat => { - if (self.link.next) |prev| { - const line = Line.unlink(prev); - self.line = line; - } - }, - else => { - if (self.line.tree.link.next) |tree_link| { - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - self.line = line; - prog.need_redraw = true; - } - }, - } - self.bakup(); - - if (self.offset.y < prog.console.size.y - 1) self.offset.y += 1; - // { correct offset_y: - // count downest_lines - var count_to_downest_line: usize = 0; - var iter = if (self.fold_mode == .flat) self.line.link.iterator() else self.line.tree.chain_link.iterator(); - _ = iter.next(); - while (count_to_downest_line < 5) { - _ = iter.next() orelse break; - count_to_downest_line += 1; - } - - if (prog.console.size.y - self.offset.y < count_to_downest_line) { - self.offset.y = prog.console.size.y - count_to_downest_line; - } - //} - prog.need_redraw = true; - } // end fn - pub fn goToFirstLine (self: *Self) void { - while (self.line.prev) |_| self.goToPrevLine(); - self.goToStartOfLine(); - prog.need_redraw = true; - self.bakup(); - } - pub fn goToLastLine (self: *Self) void { - while (self.line.next) |_| self.goToNextLine(); - prog.need_redraw = true; - self.bakup(); - } - // { go to line from number - pub fn goToLineFromNumber (self: *View, num: usize) void { - if (self.fold_mode != .flat) self.unfold(); - var iter = self.lines.first.iterator(); - var pos = 0; - while(iter.next()) |_| { - if (pos == num) break; - pos += 1; - } - self.line = Line.unlink(iter.current); - - self.offset.y = 6; - self.goToSymbol(self.line.text.countIndent(1)); - if (self.symbol >= 4) self.offset.x = 4; - prog.need_redraw = true; - self.bakup(); - } - pub fn goToLineFromInput (self: *View) !void { - if (self.line.text.used == 0) return; - var num: usize = @truncate(usize, textlib.u64FromCharsDec(self.line.text.get()) catch return); - try self.changeMode(.edit); - self.goToLineFromNumber(num); - } - // } - - // over line - pub fn goToStartOfLine (self: *Self) void { - self.symbol = 0; - self.offset.x = 0; - prog.need_redraw = true; - } - pub fn goToEndOfLine (self: *Self) void { - self.symbol = self.line.text.used; - if (self.symbol > prog.console.size.x - 2) {self.offset.x = prog.console.size.x - 2;} - else {self.offset.x = self.symbol;} - prog.need_redraw = true; - } - pub fn goToStartOfText (self: *Self) void { - const indent = self.line.text.countIndent(1); - self.goToSymbol(indent); - } - pub fn CtrlShiftLeft (self: *Self) void { - const indent = self.line.text.countIndent(1); - if (self.symbol > indent) { - self.goToSymbol(indent); - if (self.symbol >= 4) self.offset.x = 4; - } - else self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn CtrlShiftRight (self: *Self) void { - const indent = self.line.text.countIndent(1); - if (self.symbol < indent) self.goToSymbol(indent) - else self.goToEndOfLine(); - prog.need_redraw = true; - } - - // over word - pub fn goToStartOfWord (self: *Self) void { - if (self.symbol == 0) {return;} - if (self.symbol > self.line.text.used) {self.goToSymbol(self.line.text.used);} - const first_rune = self.line.text.buffer[self.symbol]; - if (first_rune == ' ') { - self.goToPrevSymbol(); - while (true) { - if (self.symbol == 0) {break;} - const rune = self.line.text.buffer[self.symbol]; - if (rune != ' ') break; - self.goToPrevSymbol(); - } - } - else { - self.goToPrevSymbol(); - while(true) { - if (self.symbol == 0) {break;} - const next_symbol = self.line.text.buffer[self.symbol - 1]; - switch(next_symbol){ - ' ', '\t', '\\', - '=', '+', '-', '/', '*', '^', - '!', '@', '#', '$', '%', '&', - '(', ')', '[', ']', '{', '}', - '"', '\'', - ';', ':', '.', ',' - => {break;}, - else => {}, - } - self.goToPrevSymbol(); - } - } - prog.need_redraw = true; - } - pub fn goToEndOfWord (self: *Self) void { - if (self.symbol >= self.line.text.used) {return;} - const first_rune = self.line.text.buffer[self.symbol]; - if (first_rune == ' ') { - while(true) { - self.goToNextSymbol(); - if (self.symbol >= self.line.text.used) {break;} - const rune = self.line.text.buffer[self.symbol]; - if (rune != ' ') break; - } - } - else while(true) { - self.goToNextSymbol(); - if (self.symbol >= self.line.text.used) {break;} - const rune = self.line.text.buffer[self.symbol]; - switch(rune){ - ' ', '\t', '\\', - '=', '+', '-', '/', '*', '^', - '(', ')', '[', ']', '{', '}', - '!', '@', '#', '$', '%', '&', - '"', '\'', - ';', ':', '.', ',' - => {break;}, - else => {}, - } - } - prog.need_redraw = true; - } - - // over symbols - pub fn goToSymbol (self: *Self, pos: usize) void { - self.symbol = pos; - if (self.symbol > prog.console.size.x - 2) { - self.offset.x = prog.console.size.x - 2; - } - else {self.offset.x = self.symbol;} - } - pub fn goToPrevSymbol (self: *Self) void { - const used = self.line.text.used; - if (self.symbol == 0) { - if (true) return; - if (self.line.prev) |_| { - self.goToPrevLine(); - self.goToEndOfLine(); - } - return; - } - if (self.symbol > used) { - self.symbol = used; - if (used < prog.console.size.x - 1) self.offset.x = self.line.text.used; - prog.need_redraw = true; - return; - } - if (self.symbol > 0) self.symbol -= 1; - if (self.symbol >= 10) {if (self.offset.x > 10) {self.offset.x -= 1;}} - else {if (self.offset.x > 0) self.offset.x -= 1;} - prog.need_redraw = true; - } - pub fn goToNextSymbol (self: *Self) void { - const used = self.line.text.used; - if (self.symbol >= used) { - if (true) return; - if (self.line.next) |_| { - self.goToNextLine(); - self.goToStartOfLine(); - } - return; - } - if (self.symbol < Line.Text.size - 1) self.symbol += 1; - if (used - self.symbol >= 10) { - if (self.offset.x < prog.console.size.x - 12) self.offset.x += 1; - } - else { - if (self.offset.x < prog.console.size.x - 2) self.offset.x += 1; - } - prog.need_redraw = true; - } - - //} - // { folding - pub fn unFold (self: *Self) void { - if (self.foldMode == .flat) return; - - // add to chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - self.lines.pushLast(&line.link); - } - - // clear tree - self.tree = .{}; - var iter = self.lines.iter(); - while(iter.next()) |link| { - const line = Line.unlink(link); - line.tree = .{}; - } - - prog.need_redraw = true; - self.foldMode = .byNone; - } // end fn - pub fn foldFromBrackets (self: *Self) void { - self.unFold(); - - // add to tree - var iter = self.lines.iter(); - var current = iter.next() orelse return; - self.tree.addChild(current); - while(iter.next()) |link| { - const line = Line.unlink(link); - const close_count = line.text.getRunesCount('}'); // **{ - const open_count = line.text.getRunesCount('{'); // **} - - if (open_count == close_count) { - current.tree.pushNext(&line.tree); - } - else if (open_count > close_count) { - current.tree.pushChild(&line.tree); - } - else { // for close_count > open_count - var parent = current.tree.parent.?; - if (parent == &self.tree) parent = ¤t.tree; - parent.pushNext(&line.tree); - } - - current = line; - } - - // remove from chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - line.link = .{}; - } - self.lines = .{}; - - prog.need_redraw = true; - self.foldMode = .byBrackets; - } - pub fn foldFromIndent (self: *Self) !void { - self.unFold(); - - var iter = self.lines.iter(); - var current_link = iter.next() orelse return; - var current = Line.unlink(current_link); - var last_indent = current.text.countIndent(4); - self.tree.addChild(¤t.tree); - while(iter.next()) |link| { - const line = Line.unlink(link); - const indent = line.text.countIndent(4); - if (indent == last_indent) { - current.tree.pushNext(&line.tree); - } - else if (indent > last_indent) { - current.tree.pushChild(&line.tree); - } - else { // for last_indent > indent - // find parent with indent > indent - var parent = current.tree.parent.?; - while (true) { - if (parent == &self.tree) {parent = ¤t.tree; break;} - const parent_line = Line.untree(parent); - const parent_indent = parent_line.text.countIndent(4); - if (parent_indent > indent) break; - parent = current.tree.parent.?; - } - parent.pushChild(&line.tree); - } - - current = line; - last_indent = indent; - } - - // remove from chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - line.link = .{}; - } - self.lines = .{}; - - prog.need_redraw = true; - self.foldMode = .byIndent; - } - - pub fn goToIn (self: *Self) void { - if (self.fold_mode == .flat) return; - const child = self.line.child orelse return; - const child_indent = child.text.countIndent(1); - self.goToSymbol(child_indent); - self.symbol = child_indent; - self.line = child; - if (prog.console.size.y > 6) {self.offset.y = 6;} - else if (prog.console.size.y > 3) {self.offset.y = 3;} - else if (prog.console.size.y > 1) {self.offset.y = 1;} - else {self.offset.y = 0;} - self.bakup(); - if (self.symbol >= 4) self.offset.x = 4; - prog.need_redraw = true; - } - pub fn goToOut (self: *Self) void { - if (self.fold_mode == .flat) return; - if (self.line.getParent()) |parent| { - const parent_indent = parent.text.countIndent(1); - self.line = parent; - self.goToSymbol(parent_indent); - self.offset.y = 6; - if (self.symbol >= 4) self.offset.x = 4; - } - else { - self.goToRoot(); - } - self.bakup(); - prog.need_redraw = true; - } - //} - // { clipboard - pub fn externalCopy (self: *Self) !void { - prog.need_redraw = false; - // { create file - var cwd = std.fs.cwd(); - var file = try cwd.createFile(prog.path_to_clipboard.get(), .{}); - defer file.close(); - const writer = file.writer(); - // } - if (prog.buffer_lines.cutted) |cutted| { - // { working with lines - var current: *Line = cutted; - try writer.writeAll(current.text.get()); - copying: while (true) { - if (current.child) |child| { - try writer.writeAll("\n"); - try writer.writeAll(child.text.get()); - current = child; - } - else if (current.next) |next| { - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - next = current.next orelse continue; - break; - } - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - } - // } - { // change status - prog.need_redraw = false; - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.blue2); - try prog.console.out.writeAll("cutted lines saved to ~/clipboard.tmp"); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - } - else { - // { working with lines - const first = self.line; - try writer.writeAll(first.text.get()); - if (first.child) |first_child| { - var current: *Line = first_child; - try writer.writeAll("\n"); - try writer.writeAll(current.text.get()); - copying: while (true) { - if (current.child) |child| { - try writer.writeAll("\n"); - try writer.writeAll(child.text.get()); - current = child; - } - else if (current.next) |next| { - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - if (current == first) break: copying; - next = current.next orelse continue; - break; - } - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - } - } - // } - { // change status - prog.need_redraw = false; - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.blue2); - try prog.console.writeAll("this block saved to ~/clipboard.tmp"); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - } - } - pub fn externalPaste (self: *Self) !void { - // read file - var file_data: []const u8 = undefined; - const loaded = lib.fileRead(prog.allocator, prog.path_to_clipboard.get()); - defer if (loaded) |data| {prog.allocator.free(data);} else |_| {}; - if (loaded) |data| {file_data = data;} else |err| { - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.red2); - try prog.console.writeAll("file ~/clipboard.tmp not reedable."); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - return err; - } - - // paste - const line = self.current_line; - try self.addPrevLine(); - for (file_data) |rune| { // parse lines - switch(rune) { - 10, 13 => {try self.addNextLine();}, - else => {try self.insertSymbol(rune);}, - } - } - self.line = line; - prog.need_redraw = true; - } - //} - // { bakup - pub fn bakup (self: *Self) void { - self.bakup_line.text.set(self.line.text.get()) catch {}; - } - pub fn restore (self: *Self) void { - self.line.text.set(self.bakup_line.text.get()) catch {}; - prog.need_redraw = true; - } - // } - // { indent - pub fn indentToCutie (self: *Self) void { - var current = self.line; - current.changeIndentToCutie() catch {}; - var first = current; - if (first.child) |first_child| { - current = first_child; - traversal: while (true) { - if (current.child) |child| { - current.changeIndentToCutie() catch {}; - current = child; - } - else if (current.next) |next| { - current.changeIndentToCutie() catch {}; - current = next; - } - else { - if (self.foldMode == .byBrackets) { - const parent = current.getParent() orelse break :traversal; - const indent = parent.text.countIndent(1); - current.text.changeIndent(indent) catch {}; - } - else { - current.changeIndentToCutie() catch {}; - } - while (true) { // find parent with next - current = current.getParent() orelse break :traversal; - if (current == first) break :traversal; - if (current.next) |next| { - current = next; - break; - } - } - } - } - } - prog.need_redraw = true; - } - pub fn deleteIndent (self: *Self) void { - var current = self.line; - current.text.changeIndent(0) catch {}; - var first = current; - if (first.child) |first_child| { - current = first_child; - traversal: while (true) { - if (current.child) |child| { - current.text.changeIndent(0) catch {}; - current = child; - } - else if (current.next) |next| { - current.text.changeIndent(0) catch {}; - current = next; - } - else { - current.text.changeIndent(0) catch {}; - while (true) { // find parent with next - current = current.getParent() orelse break :traversal; - if (current == first) break :traversal; - if (current.next) |next| { - current = next; - break; - } - } - } - } - } - prog.need_redraw = true; - } - // } - // { easy motion - pub fn draw_horizontal_help_motion (self: *Self) !void { - var pos: usize = 0; - var rune: u8 = 0x61; - try ansi.do(ansi.color.magenta); - while(true) { - try prog.console.cursorMove(.{ .x = pos, .y = self.offset.y }); - prog.console.writeByte(rune) catch unreachable; - if (rune >= 0x7A) break; rune += 1; - if (pos >= prog.console.size.x - 3) break; pos += 3; - } - try self.cursorMoveToCurrent(); - } - pub fn draw_vertical_help_motion (self: *Self) !void { - var pos: usize = 0; - try ansi.do(ansi.color.magenta); - while(true) { - try prog.console.cursorMove(.{ .x = self.offset.x, .y = pos }); - prog.console.writeByte(0x61 + @truncate(u8, pos)) catch unreachable; - if (pos >= 0x7A - 0x61) break; - if (pos == prog.console.size.y - 1) break; - pos += 1; - } - try self.cursorMoveToCurrent(); - } - pub fn easyMotionHorizontal (self: *Self, key: u8) !void { - var pos = key - 0x61; - self.goToSymbol(self.symbol - self.offset.x + pos * 3); - try self.changeMode(.edit); - prog.need_redraw = true; - } - pub fn easyMotionVertical (self: *Self, key: u8) !void { - var pos = key - 0x61; - if (self.offset.y == pos) {} - else if (self.offset.y > pos) { - var i = self.offset.y - pos; - while (i > 0) : (i -= 1) { - self.goToPrevLine(); - } - } - else { // (self.offset.y < pos) - var i = pos - self.offset.y; - while (i > 0) : (i -= 1) { - self.goToNextLine(); - } - } - try self.changeMode(.edit); - prog.need_redraw = true; - } - // } - - // being developed - pub fn drawRunes (self: *Self) !void { - try prog.console.cursorMove(.{.x = 0, .y = self.offset.y}); - defer self.cursorMoveToCurrent() catch {}; - - try ansi.do(ansi.color.red); - defer ansi.do(ansi.reset) catch {}; - - draw: { - var screen_pos_x: usize = 0; - var text_pos: usize = self.offset.x; // TODO skip first text_pos runes - const runes = self.current_line.runes orelse break: draw; - var link = &runes.link; - while(true) { - if (screen_pos_x >= prog.console.size.x - 3) break; - const rune = Rune.unlink(link); - try prog.console.writeAll(rune.glyph.getText()); - screen_pos_x += 1; - text_pos += 1; - link = link.next orelse break; - } - } - defer ansi.do(ansi.clear_to_end_line) catch {}; - - prog.need_redraw = false; - } - pub fn goToNextFlatLine (self: *Self) void { - const line_link = self.line.chain_link.next orelse return; - self.line = Line.unlink(line_link); - } - pub fn goToPrevFlatLine (self: *Self) void { - const line_link = self.line.chain_link.prev orelse return; - self.line = Line.unlink(line_link); - } - // { selection - // TODO - // } - // { find - pub fn findNext (self: *Self) void { - const text = self.line.text.get(); - var line = self.line; - if (line.text.find(text, self.symbol)) |pos| { // goto pos and return - self.line = line; - self.goToSymbol(pos); - return; - } - else { // iterate and find - while(true) { - // iterate - if (line.child) |child| { // goto child - line = child; - } - else if (line.next) |next| { // goto next - line = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - line = line.getParent() orelse return; - next = line.next orelse continue; - break; - } - line = next; - } - - // find - if (line.text.find(text, 0)) |pos| { // goto pos and return - self.line = line; - self.goToSymbol(pos); - return; - } - } - } - self.changeMode(.edit); - prog.need_clear = true; - prog.need_redraw = true; - self.bakup(); - } - // } -// } - -pub fn updateKeys () !void { - self.console.input.updateUnreaded(); - while (G.console.input.grab()) |key| { - try self.onKey(key); - } -} // end fn updateKeys DELETED src/ViewGoTo.zig Index: src/ViewGoTo.zig ================================================================== --- src/ViewGoTo.zig +++ /dev/null @@ -1,2 +0,0 @@ -// this file is just gabarage. -// i rewrite this in future. DELETED src/ViewRunes.zig Index: src/ViewRunes.zig ================================================================== --- src/ViewRunes.zig +++ /dev/null @@ -1,2 +0,0 @@ -// this file is just gabarage. -// i rewrite this in future. DELETED src/ViewTreeByBrackets.zig Index: src/ViewTreeByBrackets.zig ================================================================== --- src/ViewTreeByBrackets.zig +++ /dev/null @@ -1,1827 +0,0 @@ -// this file is just gabarage. -// i rewrite this in future. - -const G = @import("root"); -const T = @This(); - -const Text = G.ScalpiEditor.Text; -const Window = G.ScalpiEditor.Window; -const Line = G.ScalpiEditor.Line; -const Rune = G.ScalpiEditor.Rune; -const Theme = G.ScalpiEditor.Theme; -const draw_lag = G.ScalpiEditor.draw_lag; - -// todo: replace this: -const Self = @This(); -const View = @This(); -const lib = G.lib; -const ansi = G.ansi; -const std = G.std; -const Console = G.Console; - -pub const Pallete = struct { - color: []u8, - bg: []u8, - - pub fn apply(self: *Pallete) !void { - try prog.console.changeColor (self.color); - try prog.console.changeBgColor(self.bg); - } -}; - - -pub const Theme = struct { -// const currentRune: Pallete = .{.color=ansi.color.yellow, .bg=ansi.bg_color.black}; -// const currentRuneF: Pallete = .{.color=ansi.color.magenta, .bg=ansi.bg_color.black2}; -// const currentLine: Pallete = .{.color=ansi.color.green, .bg=ansi.bg_color.black}; -// const currentFolded: Pallete = .{.color=ansi.color.green, .bg=ansi.bg_color.black2}; -// const line: Pallete = .{.color=ansi.color.white, .bg=ansi.bg_color.black}; -// const lineFolded: Pallete = .{.color=ansi.color.white, .bg=ansi.bg_color.black2}; -// const outLine: Pallete = .{.color=ansi.color.magenta, .bg=ansi.bg_color.black}; -// const outLineF: Pallete = .{.color=ansi.color.magenta, .bg=ansi.bg_color.black2}; -// const headers: Pallete = .{.color=ansi.color.cyan, .bg=ansi.bg_color.black}; -// const save: Pallete = .{.color=ansi.color.red, .bg=ansi.bg_color.black}; -}; - -const Self = @This(); -// { fields - file_name: Text = .{}, - - // modes - mode: Mode = .edit, - indent: Indent = .{}, - selected: usize = 0, - - tree: Tree = .{}, - cutted: Tree = .{}, - - bakup_line: *Line = undefined, - last_working_line: ?*Line = null, - marked_line: ?*Line = null, - lines_drawing: usize = 0, - max_draw_parent_lines: usize = 0, - - // current pos - current_line: *Line, - offset: lib.Coor2u = .{.x = 0, .y = 0 }, - symbol: usize = 0, -// } -// { methods - pub fn onMouse (t: *T) !void { - const mode = prog.console.input.buffer[3]; - if (mode != ' ') return; - - var coor_x = prog.console.input.buffer[4]; - if (coor_x < 33) { - try ansi.do(ansi.color.yellow); - try prog.console.out.print("x = {d}", .{coor_x}); - return; - } - coor_x -= 33; - self.view.goToSymbol(self.view.symbol - self.view.offset.x + coor_x); - - var coor_y = prog.console.input.buffer[5]; - if (coor_y < 35) { - try ansi.do(ansi.color.yellow); - try prog.console.out.print("x = {d}", .{coor_x}); - return; - } - coor_y -= 35; - if (self.view.offset.y == coor_y) {} - else if (self.view.offset.y > coor_y) { - var i = self.view.offset.y - coor_y; - while (i > 0) : (i -= 1) { - self.view.goToPrevLine(); - } - } - else { // (self.view.offset.y < coor_y) - var i = coor_y - self.view.offset.y; - while (i > 0) : (i -= 1) { - self.view.goToNextLine(); - } - } - - prog.need_redraw = true; - } - pub fn onKey (t: *T, cik: Console.Input.Key) !void { - switch (self.view.mode) { - .edit => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .mouse => {try self.onMouse();}, - .f1 => {try self.view.goToHelp();}, - .f1_rxvt => {try self.view.goToHelp();}, - .f1_tty => {try self.view.goToHelp();}, - .f2 => {self.debug.toggle();}, - .f2_rxvt => {self.debug.toggle();}, - .f2_tty => {self.debug.toggle();}, - .f3 => {self.view.goToPrevFlatLine();}, - .f4 => {self.view.goToNextFlatLine();}, - .f5 => {try self.view.drawRunes();}, - .f9 => {try self.view.changeMode(.normal);}, - .f10 => {self.stop();}, - - .delete => {self.view.deleteSymbol();}, - .shift_delete => {self.view.clearLine();}, - - .end => {self.view.goToEndOfLine();}, - .home => {self.view.goToStartOfLine();}, - - .down => {self.view.goToNextLine();}, - .up => {self.view.goToPrevLine();}, - .left => {self.view.goToPrevSymbol();}, - .right => {self.view.goToNextSymbol();}, - .ctrl_shift_left => {self.view.CtrlShiftLeft();}, - .ctrl_shift_right => {self.view.CtrlShiftRight();}, - .ctrl_left => {self.view.goToStartOfWord();}, - .ctrl_left_rxvt => {self.view.goToStartOfWord();}, - .ctrl_right => {self.view.goToEndOfWord();}, - .ctrl_right_rxvt => {self.view.goToEndOfWord();}, - .ctrl_up => {self.view.goToFirstLine();}, - .ctrl_down => {self.view.goToLastLine();}, - .alt_up => {self.view.swapWithUpper();}, - .alt_down => {self.view.swapWithBottom();}, - - .alt_n => {self.view.insertSymbol('\n') catch {};}, - .alt_r => {self.view.insertSymbol('\r') catch {};}, - .alt_v => {self.view.externalPaste() catch {};}, - .alt_m => {self.view.markThisLine();}, - .alt_j => {self.view.goToMarked();}, - .alt_p => {self.view.deleteIndent();}, - - else => {self.need_redraw = true;}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - self.need_redraw = true; - }, - .ascii_key => |key| { - switch (key) { - .ctrl_q => {self.stop();}, - .ctrl_s => {self.view.save() catch {};}, - .ctrl_g => {try self.view.changeMode(.to_line);}, - .ctrl_f => {try self.view.changeMode(.to_find);}, - .ctrl_u => {self.view.unFold();}, - .ctrl_r => {try self.view.foldFromIndent();}, - .ctrl_e => {self.view.foldFromBrackets();}, - .ctrl_j => {self.view.joinLines();}, - .enter => { - switch (self.console.input.is_paste) { - true => {self.view.addNextLine() catch {};}, - false => {self.view.divide() catch {};}, - } - }, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_p => {self.view.indentToCutie();}, - .ctrl_d => {self.view.duplicate();}, - .ctrl_x => {self.view.cut();}, - .ctrl_c => {self.view.externalCopy() catch {};}, - .ctrl_v => {self.view.pasteLine();}, - .ctrl_t => {self.view.insertSymbol('\t') catch {};}, - .escape => {self.view.goToOut();}, - .tab => {self.view.goToIn();}, - .ctrl_w => {self.view.deleteWord();}, - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .ctrl_z => {self.view.restore();}, - .ctrl_o => {try self.view.drawRunes();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .to_find => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .ctrl_left => self.view.goToStartOfLine(), - .ctrl_right => self.view.goToEndOfLine(), - .delete => self.view.deleteSymbol(), - .shift_delete => {self.view.clearLine();}, - else => {}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - }, - .ascii_key => |key| { - switch (key) { - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_j => {self.view.findNext();}, - .enter => {self.view.findNext();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .to_line => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .ctrl_left => self.view.goToStartOfLine(), - .ctrl_right => self.view.goToEndOfLine(), - .delete => self.view.deleteSymbol(), - .shift_delete => {self.view.clearLine();}, - else => {}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - }, - .ascii_key => |key| { - switch (key) { - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_j => {try self.view.goToLineFromInput();}, - .enter => {try self.view.goToLineFromInput();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .history => {}, - .select => {}, - .normal => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .delete => {self.view.deleteSymbol();}, - .shift_delete => {self.view.clearLine();}, - .end => {self.view.goToEndOfLine();}, - .home => {self.view.goToStartOfLine();}, - .down => {self.view.goToNextLine();}, - .up => {self.view.goToPrevLine();}, - .left => {self.view.goToPrevSymbol();}, - .right => {self.view.goToNextSymbol();}, - else => {}, - } - }, - .byte => |_| {}, - .ascii_key => |key| { - switch (key) { - .code_q => {self.stop();}, - .code_s => {self.view.save() catch {};}, - .code_i => {try self.view.changeMode(.edit);}, - .code_g => {try self.view.changeMode(.to_line);}, - .code_u => {self.view.unFold();}, - .code_r => {try self.view.foldFromIndent();}, - .code_e => {self.view.foldFromBrackets();}, - .code_j => {self.view.divide() catch {};}, - .enter => {self.view.divide() catch {};}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .code_p => {self.view.line.changeIndentToCutie() catch {};}, - .code_d => {self.view.duplicate();}, - .code_x => {self.view.cut();}, - .code_c => {self.view.externalCopy() catch {};}, - .code_v => {self.view.pasteLine();}, - .code_t => {self.view.insertSymbol('\t') catch {};}, - .escape => {self.view.goToOut();}, - .tab => {self.view.goToIn();}, - .code_l => {self.view.goToLastLine();}, - else => {}, - } - }, - } - }, - .easy_motion_vertical => { - switch (cik) { - .sequence => |_| {}, - .byte => |_| {}, - .ascii_key => |key| { - const num = @enumToInt(key); - if (num >= 0x61 and num <= 0x7A) {try self.view.easyMotionVertical(num);} - else switch (key) { - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - else => {}, - } - }, - } - }, - .easy_motion_horizontal => { - switch (cik) { - .sequence => |_| {}, - .byte => |_| {}, - .ascii_key => |key| { - const num = @enumToInt(key); - if (num >= 0x61 and num <= 0x7A) {try self.view.easyMotionHorizontal(num);} - else switch (key) { - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - else => {}, - } - }, - } - }, - } - } - - pub fn fromAlloc () !*View { - const allocated = lib.c.aligned_alloc(8, @sizeOf(View)) orelse return error.NeedMoreMemory; - var view: *View = @ptrCast(*View, @alignCast(8, allocated)); - return view; - } - pub fn init (t: *T, file_name: []const u8, text: []const u8) !void { - self.* = .{}; - self.file_name.set(file_name) catch unreachable; - { // parse_text_to_lines - var iter = std.mem.split(u8, text, "\n"); - while(iter.next()) |line| { - const new_line = try prog.buffer_lines.create(); - new_line.text.set(line) catch { - return error.LineIsToLong; - }; - self.lines.pushLast(&new_line.chain_link); - } - } - const link = self.lines.first.?; - self.current_line = Line.unlink(link); - self.bakup_line = try prog.buffer_lines.create(); - } // end fn loadLines - pub fn save (t: *T) !void { - prog.need_redraw = false; - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(Theme.save); - try prog.console.writeAll("saving..."); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - // { create file - var cwd = std.fs.cwd(); - var file = try cwd.createFile(self.file_name.get(), .{}); - defer file.close(); - const writer = file.writer(); - // } - var count: usize = 0; // lines - write: { //write - switch(self.fold_mode) { - .flat => { - var iter = self.lines.iter(); - - // write first line - const first_link = iter.next() orelse break: write; - const first_line = Line.unLink(first_link); - count += 1; - try writer.writeAll(first_line.text.get()); - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try prog.console.out.print("{} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - - // write other lines - while(iter.next()) |link| { - try writer.writeAll("\n"); - const line = Line.unlink(link); - count += 1; - try writer.writeAll(line.text.get()); - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try prog.console.out.print("{} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - } - }, - else => { - var walker = self.tree.walker(); - _ = walker.next(); // skip root - - // save first line (without "\n") - const first_tree = walker.next() orelse break: write; - const first_line = Line.untree(first_tree); - count += 1; - try writer.writeAll(first_line.text.get()); - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try prog.console.out.print("{} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - - // save other lines (with "\n") - while(walker.next()) |tree| { - try writer.writeAll("\n"); - const line = Line.untree(tree); - count += 1; - try writer.writeAll(line.text.get()); - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try prog.console.out.print("{} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - } - }, - } - } - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - defer self.cursorMoveToCurrent() catch {}; - - try ansi.do(Theme.save); - defer ansi.do(ansi.reset) catch {}; - - try prog.console.out.print("file saved. {} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - } - pub fn changeMode (t: *T, mode: Mode) !void { - switch (mode) { - .edit => {}, - .to_find => { - self.last_working_line = self.current_line; - }, - .to_line => { - self.last_working_line = self.current_line; - if (prog.buffer_lines.to_goto == null) { // create - const new_line = prog.buffer_lines.create() catch return; - prog.buffer_lines.to_goto = new_line; - } - self.current_line = prog.buffer_lines.to_goto.?; - self.goToEndOfLine(); - prog.need_redraw = true; - }, - .history => {}, - .select => {}, - .normal => {}, - .easy_motion_vertical => { - try self.draw_vertical_help_motion(); - }, - .easy_motion_horizontal => { - try self.draw_horizontal_help_motion(); - }, - } - self.mode = mode; - } - pub fn cursorMoveToCurrent (t: *T) !void { - try prog.console.cursorMove(.{ .x = self.offset.x, .y = self.offset.y }); - } - pub fn goToHelp (t: *T) !void { - self.current_line = prog.usage_line; - prog.need_redraw = true; - } - // { mark - pub fn markThisLine (t: *T) void { - self.marked_line = self.line; - } - pub fn goToMarked (t: *T) void { - if (self.marked_line) |mark| { - self.line = mark; - prog.need_redraw = true; - } - } - // } - // { edit - // block - pub fn duplicate (t: *T) void { - const first = self.line; - const copy_first = prog.buffer_lines.create() catch return; - copy_first.text.set(first.text.get()) catch unreachable; - self.line.pushNext(copy_first); - if (first.child) |first_child| { - var current = first_child; - var copy_current = prog.buffer_lines.create() catch return; - copy_current.text.set(current.text.get()) catch unreachable; - copy_current.parent = copy_first; - copy_first.child = copy_current; - copying: while (true) { - if (current.child) |child| { - var copy_child = prog.buffer_lines.create() catch return; - copy_child.text.set(child.text.get()) catch unreachable; - copy_child.parent = copy_current; - copy_current.child = copy_child; - current = child; - copy_current = copy_child; - } - else if (current.next) |next| { - var copy_next = prog.buffer_lines.create() catch return; - copy_next.text.set(next.text.get()) catch unreachable; - copy_next.prev = copy_current; - copy_current.next = copy_next; - current = next; - copy_current = copy_next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - if (current == first) break: copying; - copy_current = copy_current.getParent() orelse unreachable; - next = current.next orelse continue; - break; - } - var copy_next = prog.buffer_lines.create() catch return; - copy_next.text.set(next.text.get()) catch unreachable; - copy_next.prev = copy_current; - copy_current.next = copy_next; - current = next; - copy_current = copy_next; - } - } - } - self.line = copy_first; - prog.need_redraw = true; - } - pub fn cut (t: *T) void { - if (self.line.parent) |parent| { - parent.child = self.line.next; - } - var next_selected_line: *Line = undefined; - // { select next selected line - if (self.line.next) |next| { - next_selected_line = next; - } else if (self.line.prev) |prev| { - next_selected_line = prev; - } else if (self.line.parent) |parent| { - next_selected_line = parent; - } else { - self.line.text.set("") catch unreachable; - return; - } - // } - if (self.lines == self.line) self.lines = next_selected_line; - prog.buffer_lines.cut(self.line); - self.line = next_selected_line; - prog.need_redraw = true; - self.bakup(); - } - pub fn pasteLine (t: *T) void { - if (prog.buffer_lines.cutted) |cutted| { - prog.buffer_lines.cutted = cutted.next; - cutted.next = null; - self.line.pushPrev(cutted); - if (self.lines == self.line) self.lines = cutted; - self.offset.y += 1; - self.goToPrevLine(); - self.indentToCutie(); - } - prog.need_redraw = true; - } - - // line - pub fn joinLines (t: *T) void { - if (self.line.child) |_| return; - const next = self.line; - const prev = self.line.prev orelse return; - - self.deleteIndent(); - - const next_used = next.text.used; - const prev_used = prev.text.used; - - if (prev_used + next_used > Line.Text.size - 3) return; - std.mem.copy(u8, prev.text.buffer[prev.text.used..], next.text.get()); - prev.text.used += next_used; - prog.buffer_lines.delete(self.line); - self.line = prev; - self.goToSymbol(prev_used); - } - pub fn clearLine (t: *T) void { - self.line.text.used = 0; - self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn addPrevLine (t: *T) !void { - const new_line = try prog.buffer_lines.create(); - switch(self.fold_mode) { - .flat => { - self.lines.pushPrev(self.current_line, &new_line.link); - }, - else => { - var tree = &self.current_line.tree; - tree.link.pushPrev(&new_line.tree); - }, - } - self.current_line = new_line; - self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn addNextLine (t: *T) !void { - const new_line = try prog.buffer_lines.create(); - switch(self.fold_mode) { - .flat => { - self.lines.pushNext(self.current_line, &new_line.link); - }, - else => { - var tree = &self.current_line.tree; - tree.link.pushNext(&new_line.tree); - }, - } - self.current_line = new_line; - self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn divide (t: *T) !void { - const indent = self.line.text.countIndent(1); - if (self.symbol <= indent) { // just add prev line - const last_symbol = self.symbol; - const last_offset = self.offset.x; - try self.addPrevLine(); - try self.line.changeIndentToCutie(); - self.goToNextLine(); - self.symbol = last_symbol; - self.offset.x = last_offset; - } - else if (self.symbol >= self.line.text.used) { // just add next line - if (self.line.text.buffer[self.symbol - 1] == ':') { - if (self.line.child) |_| return; - const new_line = prog.buffer_lines.create() catch return; - // { link - self.line.child = new_line; - new_line.parent = self.line; - // } - self.goToIn(); - } - else { - try self.addNextLine(); - } - } - else if (self.line.text.buffer[self.symbol] == '}' and self.line.text.buffer[self.symbol - 1] == '{') { - if (self.line.child != null) return; - const pos = self.symbol; - const last_line = self.line; - - const new_line = prog.buffer_lines.create() catch return; - // { link - self.line.child = new_line; - new_line.parent = self.line; - // } - // { copy text and fill spaces - const text_to_new_line = last_line.text.get()[pos..]; - std.mem.copy(u8, new_line.text.buffer[indent..], text_to_new_line); - for (new_line.text.buffer[0 .. indent]) |*rune| rune.* = ' '; // spam spaces - new_line.text.used = indent + text_to_new_line.len; - last_line.text.used = pos; - // } - - self.line = new_line; - try self.addPrevLine(); - } - else { - if (self.line.child) |_| return; - var parent = self.line; - var pos = self.symbol; - const text = self.line.text.get()[pos..]; - try self.addNextLine(); - self.line.text.used = indent + text.len; - std.mem.copy(u8, self.line.text.buffer[indent..], text); - for (self.line.text.buffer[0..indent]) |*rune| rune.* = ' '; - parent.text.used = pos; - } - self.indentToCutie(); - self.goToStartOfText(); - if (false) { // change status (debug) - const last_cursor_pos: lib.Coor2u = prog.console.cursor.pos; - defer { // reset color, clear line, restore cursor pos and flush - defer Console.Output.print(ansi.reset); - Console.Output.print(ansi.clear_to_end_line); - defer prog.console.cursorMove(last_cursor_pos); - Console.Output.flush(); - } - - prog.console.cursorMove(.{ .x = 0, .y = 0 }); - Console.Output.print(ansi.color.red2); - - var buffer: [254]u8 = undefined; - var text_len: usize = 0; - var sprintf_result = lib.c.sprintf(&buffer, "line used = %d", self.line.text.used); - text_len += @intCast(usize, sprintf_result); - prog.console.print(buffer[0 .. text_len]); - } - if (self.symbol >= 4) self.offset.x = 4; - prog.need_redraw = true; - } - pub fn swapWithBottom (t: *T) void { - const current_link = &self.current_line.link; - if (self.current_line.next) |_| { - self.cut(); - self.goToNextLine(); - self.pasteLine(); - } - prog.need_redraw = true; - } - pub fn swapWithUpper (t: *T) void { - if (self.line.prev) |_| { - self.cut(); - self.goToPrevLine(); - self.pasteLine(); - } - prog.need_redraw = true; - } - pub fn deleteLine (t: *T) void { - const line = self.line; - var next_selected_line: *Line = undefined; - if (line.next) |next| { - next_selected_line = next; - } - else if (line.prev) |prev| { - next_selected_line = prev; - } - else if (line.parent) |parent| { - next_selected_line = parent; - } - else { // clear and exit - self.clearLine(); - return; - } - self.clearLine(); - if (self.lines == self.line) self.lines = next_selected_line; - prog.buffer_lines.delete(self.line); - self.line = next_selected_line; - prog.need_redraw = true; - } - - // word - pub fn deleteWord (t: *T) void { - if (self.symbol > self.line.text.used) {return;} - while(true) { // delete current symbol - if (self.symbol == self.line.text.used) {break;} - const next_symbol = self.line.text.buffer[self.symbol]; - if (textlib.isLetter(next_symbol)) {self.deleteSymbol();} else {break;} - } - while(true) { // delete prev symbol - if (self.symbol == 0) {break;} - const prev_symbol = self.line.text.buffer[self.symbol - 1]; - if (textlib.isLetter(prev_symbol)) {self.deletePrevSymbol();} else {break;} - } - prog.need_redraw = true; - } - - // symbol - pub fn insertSymbol (t: *T, rune: u8) !void { - const t = &self.current_line.text; - if (self.symbol > t.used) self.goToSymbol(t.used); - try t.insert(self.symbol, rune); - self.goToNextSymbol(); - prog.need_redraw = true; - } // end fn - pub fn deleteSymbol (t: *T) void { - if (self.line.text.used == 0) return; - self.line.text.delete(self.symbol) catch return; - prog.need_redraw = true; - } - pub fn deletePrevSymbol (t: *T) void { - switch (self.symbol) { - 0 => { - if (self.line.parent) |_| return; - if (self.line.child) |_| return; - if (self.line == self.lines) return; - - const prev = self.line.prev orelse return; - - const non_indent = self.line.text.countNonIndent(); - if (non_indent == 0) { // delete self line - prog.buffer_lines.delete(self.line); - self.line = prev; - prog.need_redraw = true; - return; - } - - const prev_count = prev.text.countNonIndent(); - switch (prev_count) { - 0 => { // delete prev - if (self.lines == prev) self.lines = self.line; - prog.buffer_lines.delete(prev); - prog.need_redraw = true; - return; - }, - else => { // join line - self.joinLines(); - }, - } - }, - else => { - if (self.line.text.used == 0) return; - self.goToPrevSymbol(); - self.deleteSymbol(); - }, - } - prog.need_redraw = true; - } - //} - // { draw - pub fn draw (t: *T) !void { - switch (G.console.size.y) { - 0 => unreachable, - 1 => { - t.max_draw_parent_lines = 0; - }, - 2, 3 => { - t.max_draw_parent_lines = 1; - }, - 4, 5 => { - t.max_draw_parent_lines = 2; - }, - else => { - t.max_draw_parent_lines = 5; - }, - } - - try ansi.do(ansi.cyrsor_style.hide); - defer ansi.do(ansi.cyrsor_style.show) catch {}; - defer self.cursorMoveToCurrent() catch {}; - if (self.symbol < self.offset.x) { // unexpected - self.offset = .{}; - self.symbol = 0; - } - switch (self.mode) { - .edit => { - switch (self.fold_mode) { - .flat => { - Theme.line.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - try self.drawLine(); - if (self.offset.y > 0) { // draw upper lines - var iter = self.line.link.iterReverse(); - - // skip current; - var pos_y = self.offset.y - 1; - _ = iter.next(); - - while(iter.next()) |link| { - const line = Line.unlink(link); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y}); - self.drawLine(line); - if (pos_y == 0) break; - pos_y -= 1; - } - } - if (self.offset.y < prog.console.size.y) { // draw downer lines - var iter = self.line.link.iter(); - - // skip current; - var pos_y = self.offset.y + 1; - _ = iter.next(); - - while(iter.next()) |link| { - const line = Line.unlink(link); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y}); - self.drawLine(line); - if (pos_y == 0) break; - pos_y += 1; - } - while (true) { // clear other downer lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y >= prog.console.size.y - 1) return; - pos_y += 1; - std.time.sleep(draw_lag); - } - } - try self.drawEdited(); - }, - else => { - // draw other lines - try self.drawUpperLines(); - try self.drawDownerLines(); - - // draw edit line - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y }); - if (self.line.tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(self.line); - try self.drawEditedF(); - } - else { - try Theme.line.apply(); - try self.drawLine(self.line); - try self.drawEdited(); - } - }, - } - }, - .to_line => { - self.offset.y = 1; - - // draw banner - try prog.console.changeColor(Theme.headers); - try prog.console.cursorMove(.{ .x = 0, .y = 0}); - try prog.console.out.writeAll("enter the line you want to jump to:"); - try ansi.do(ansi.clear_to_end_line); - - // draw edit line - try prog.console.cursorMove(.{ .x = 0, .y = 1}); - defer self.cursorMoveToCurrent() catch {}; - try self.drawEditedLine(); - - var pos_y: usize = 2; - while (true) { // clear other downer lines - if (pos_y >= prog.console.size.y) return; - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - pos_y += 1; - std.time.sleep(draw_lag); - - } - }, - .easy_motion_vertical, - .easy_motion_horizontal, - .to_find, - .history, - .select, - .normal, - => {}, - } - } // end draw lines - pub fn drawLine (t: *T, line: *Line) !void { - // move to start - defer ansi.do(ansi.clear_to_end_line) catch {}; - try prog.console.cr(); - if (line.text.used == 0) {return;} - - // draw left-to-right - const text = line.text.get(); - var text_pos: usize = self.symbol - self.offset.x; // first visible rune - var offset_x: usize = 0; - while (true) { - if (text_pos >= text.len) break; - if (offset_x >= prog.console.size.x - 1) break; - prog.console.writeByte(text[text_pos]) catch unreachable; - text_pos += 1; - offset_x += 1; - } - } - pub fn drawParentLine (t: *T, parent: *Line) !void { - // draw - try prog.console.cr(); - const text = parent.text.get(); - var indent = parent.text.countIndent(1); - var symbol: usize = indent; - if (indent >= self.symbol - self.offset.x) {symbol = self.symbol - self.offset.x;} - var offset_x: usize = 0; - while (true) { - if (symbol >= text.len) { - try ansi.do(ansi.clear_to_end_line); - break; - } - if (offset_x >= prog.console.size.x) break; - prog.console.writeByte(text[symbol]) catch unreachable; - - symbol += 1; - offset_x += 1; - } - } - pub fn drawEdited (t: *T) !void { - const text: []u8 = self.line.text.get(); - const pos: usize = self.symbol - self.offset.x; - const end_pos: usize = pos + prog.console.size.x; - - if (pos > 0) { // draw '<' - try Theme.outLine.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - prog.console.writeByte('<') catch unreachable; - } - if (text.len > end_pos) { // draw '>' - try Theme.outLine.apply(); - try prog.console.cursorMove(.{ .x = prog.console.size.x - 1, .y = self.offset.y}); - prog.console.writeByte('>') catch unreachable; - } - if (pos < text.len) { // draw symbol about cursor - try self.cursorMoveToCurrent(); - try Theme.currentRune.apply(); - try prog.console.writeByte(text[pos]); - } - } // drawEdited - pub fn drawEditedF (t: *T) !void { - const text: []u8 = self.line.text.get(); - const pos: usize = self.symbol - self.offset.x; - const end_pos: usize = pos + prog.console.size.x; - - if (pos > 0) { // draw '<' - try Theme.outLineF.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - prog.console.writeByte('<') catch unreachable; - } - if (text.len > end_pos) { // draw '>' - try Theme.outLineF.apply(); - try prog.console.cursorMove(.{ .x = prog.console.size.x - 1, .y = self.offset.y}); - prog.console.writeByte('>') catch unreachable; - } - if (pos < text.len) { // draw symbol about cursor - try self.cursorMoveToCurrent(); - try Theme.currentRuneF.apply(); - try prog.console.writeByte(text[pos]); - } - } // drawEdited - // draw tree - pub fn drawUpperLines (t: *T) !void { - //TODO: apply self.max_draw_parent_lines = 2; - - // draw lines - if (self.offset.y == 0) return; - var iter = self.line.tree.link.iteratorReverse(); - // skip current - var pos_y: usize = self.offset.y - 1; - _ = iter.next(); - while(iter.next()) |link| { - const tree = Tree.unlink(link); - const line = Line.unTree(tree); - - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - if (tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(line); - } - else { - try Theme.line.apply(); - try self.drawLine(self.line); - } - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - while (true) { // draw parents - try Theme.headers.apply(); - const tree = self.line.tree.parent orelse break; - if (tree == self.tree) break; - const line = Line.untree(tree); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try self.drawParentLine(line); - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - while (true) { // clear other upp lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - } - pub fn drawDownerLines (t: *T) !void { - var iter = self.line.tree.link.iterator(); - // skip current - var pos_y: usize = self.offset.y + 1; - _ = iter.next(); - - if (pos_y >= prog.console.size.y) return; - while (iter.next) |tree_link| { // draw lines - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - if (line.tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(line); - } - else { - try Theme.line.apply(); - try drawLine(self.line); - } - if (pos_y >= prog.console.size.y - 1) { - self.lines_drawing = prog.console.size.y; - return; - } - pos_y += 1; - std.time.sleep(draw_lag); - } - - self.lines_drawing = pos_y; - while (true) { // clear other downer lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y >= prog.console.size.y - 1) return; - pos_y += 1; - std.time.sleep(draw_lag); - } - } - // } - // { navigation - // over lines - pub fn goToRoot (t: *T) void { - self.line = self.lines; - self.offset.y = 5; - self.goToStartOfLine(); - prog.need_redraw = true; - self.bakup(); - } - pub fn goToPrevLine (t: *T) void { - switch(self.fold_mode) { - .flat => { - if (self.link.prev) |prev| { - const line = Line.unlink(prev); - self.line = line; - } - }, - else => { - if (self.line.tree.link.prev) |tree_link| { - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - self.line = line; - prog.need_redraw = true; - } - }, - } - if (self.offset.y > 5) {self.offset.y -= 1;} - self.bakup(); - } // end fn - pub fn goToNextLine (t: *T) void { - switch(self.fold_mode) { - .flat => { - if (self.link.next) |prev| { - const line = Line.unlink(prev); - self.line = line; - } - }, - else => { - if (self.line.tree.link.next) |tree_link| { - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - self.line = line; - prog.need_redraw = true; - } - }, - } - self.bakup(); - - if (self.offset.y < prog.console.size.y - 1) self.offset.y += 1; - // { correct offset_y: - // count downest_lines - var count_to_downest_line: usize = 0; - var iter = if (self.fold_mode == .flat) self.line.link.iterator() else self.line.tree.chain_link.iterator(); - _ = iter.next(); - while (count_to_downest_line < 5) { - _ = iter.next() orelse break; - count_to_downest_line += 1; - } - - if (prog.console.size.y - self.offset.y < count_to_downest_line) { - self.offset.y = prog.console.size.y - count_to_downest_line; - } - //} - prog.need_redraw = true; - } // end fn - pub fn goToFirstLine (t: *T) void { - while (self.line.prev) |_| self.goToPrevLine(); - self.goToStartOfLine(); - prog.need_redraw = true; - self.bakup(); - } - pub fn goToLastLine (t: *T) void { - while (self.line.next) |_| self.goToNextLine(); - prog.need_redraw = true; - self.bakup(); - } - // { go to line from number - pub fn goToLineFromNumber (self: *View, num: usize) void { - if (self.fold_mode != .flat) self.unfold(); - var iter = self.lines.first.iterator(); - var pos = 0; - while(iter.next()) |_| { - if (pos == num) break; - pos += 1; - } - self.line = Line.unlink(iter.current); - - self.offset.y = 6; - self.goToSymbol(self.line.text.countIndent(1)); - if (self.symbol >= 4) self.offset.x = 4; - prog.need_redraw = true; - self.bakup(); - } - pub fn goToLineFromInput (self: *View) !void { - if (self.line.text.used == 0) return; - var num: usize = @truncate(usize, textlib.u64FromCharsDec(self.line.text.get()) catch return); - try self.changeMode(.edit); - self.goToLineFromNumber(num); - } - // } - - // over line - pub fn goToStartOfLine (t: *T) void { - self.symbol = 0; - self.offset.x = 0; - prog.need_redraw = true; - } - pub fn goToEndOfLine (t: *T) void { - self.symbol = self.line.text.used; - if (self.symbol > prog.console.size.x - 2) {self.offset.x = prog.console.size.x - 2;} - else {self.offset.x = self.symbol;} - prog.need_redraw = true; - } - pub fn goToStartOfText (t: *T) void { - const indent = self.line.text.countIndent(1); - self.goToSymbol(indent); - } - pub fn CtrlShiftLeft (t: *T) void { - const indent = self.line.text.countIndent(1); - if (self.symbol > indent) { - self.goToSymbol(indent); - if (self.symbol >= 4) self.offset.x = 4; - } - else self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn CtrlShiftRight (t: *T) void { - const indent = self.line.text.countIndent(1); - if (self.symbol < indent) self.goToSymbol(indent) - else self.goToEndOfLine(); - prog.need_redraw = true; - } - - // over word - pub fn goToStartOfWord (t: *T) void { - if (self.symbol == 0) {return;} - if (self.symbol > self.line.text.used) {self.goToSymbol(self.line.text.used);} - const first_rune = self.line.text.buffer[self.symbol]; - if (first_rune == ' ') { - self.goToPrevSymbol(); - while (true) { - if (self.symbol == 0) {break;} - const rune = self.line.text.buffer[self.symbol]; - if (rune != ' ') break; - self.goToPrevSymbol(); - } - } - else { - self.goToPrevSymbol(); - while(true) { - if (self.symbol == 0) {break;} - const next_symbol = self.line.text.buffer[self.symbol - 1]; - switch(next_symbol){ - ' ', '\t', '\\', - '=', '+', '-', '/', '*', '^', - '!', '@', '#', '$', '%', '&', - '(', ')', '[', ']', '{', '}', - '"', '\'', - ';', ':', '.', ',' - => {break;}, - else => {}, - } - self.goToPrevSymbol(); - } - } - prog.need_redraw = true; - } - pub fn goToEndOfWord (t: *T) void { - if (self.symbol >= self.line.text.used) {return;} - const first_rune = self.line.text.buffer[self.symbol]; - if (first_rune == ' ') { - while(true) { - self.goToNextSymbol(); - if (self.symbol >= self.line.text.used) {break;} - const rune = self.line.text.buffer[self.symbol]; - if (rune != ' ') break; - } - } - else while(true) { - self.goToNextSymbol(); - if (self.symbol >= self.line.text.used) {break;} - const rune = self.line.text.buffer[self.symbol]; - switch(rune){ - ' ', '\t', '\\', - '=', '+', '-', '/', '*', '^', - '(', ')', '[', ']', '{', '}', - '!', '@', '#', '$', '%', '&', - '"', '\'', - ';', ':', '.', ',' - => {break;}, - else => {}, - } - } - prog.need_redraw = true; - } - - // over symbols - pub fn goToSymbol (t: *T, pos: usize) void { - self.symbol = pos; - if (self.symbol > prog.console.size.x - 2) { - self.offset.x = prog.console.size.x - 2; - } - else {self.offset.x = self.symbol;} - } - pub fn goToPrevSymbol (t: *T) void { - const used = self.line.text.used; - if (self.symbol == 0) { - if (true) return; - if (self.line.prev) |_| { - self.goToPrevLine(); - self.goToEndOfLine(); - } - return; - } - if (self.symbol > used) { - self.symbol = used; - if (used < prog.console.size.x - 1) self.offset.x = self.line.text.used; - prog.need_redraw = true; - return; - } - if (self.symbol > 0) self.symbol -= 1; - if (self.symbol >= 10) {if (self.offset.x > 10) {self.offset.x -= 1;}} - else {if (self.offset.x > 0) self.offset.x -= 1;} - prog.need_redraw = true; - } - pub fn goToNextSymbol (t: *T) void { - const used = self.line.text.used; - if (self.symbol >= used) { - if (true) return; - if (self.line.next) |_| { - self.goToNextLine(); - self.goToStartOfLine(); - } - return; - } - if (self.symbol < Line.Text.size - 1) self.symbol += 1; - if (used - self.symbol >= 10) { - if (self.offset.x < prog.console.size.x - 12) self.offset.x += 1; - } - else { - if (self.offset.x < prog.console.size.x - 2) self.offset.x += 1; - } - prog.need_redraw = true; - } - - //} - // { folding - pub fn unFold (t: *T) void { - if (self.foldMode == .flat) return; - - // add to chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - self.lines.pushLast(&line.link); - } - - // clear tree - self.tree = .{}; - var iter = self.lines.iter(); - while(iter.next()) |link| { - const line = Line.unlink(link); - line.tree = .{}; - } - - prog.need_redraw = true; - self.foldMode = .byNone; - } // end fn - pub fn foldFromBrackets (t: *T) void { - self.unFold(); - - // add to tree - var iter = self.lines.iter(); - var current = iter.next() orelse return; - self.tree.addChild(current); - while(iter.next()) |link| { - const line = Line.unlink(link); - const close_count = line.text.getRunesCount('}'); // **{ - const open_count = line.text.getRunesCount('{'); // **} - - if (open_count == close_count) { - current.tree.pushNext(&line.tree); - } - else if (open_count > close_count) { - current.tree.pushChild(&line.tree); - } - else { // for close_count > open_count - var parent = current.tree.parent.?; - if (parent == &self.tree) parent = ¤t.tree; - parent.pushNext(&line.tree); - } - - current = line; - } - - // remove from chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - line.link = .{}; - } - self.lines = .{}; - - prog.need_redraw = true; - self.foldMode = .byBrackets; - } - pub fn foldFromIndent (t: *T) !void { - self.unFold(); - - var iter = self.lines.iter(); - var current_link = iter.next() orelse return; - var current = Line.unlink(current_link); - var last_indent = current.text.countIndent(4); - self.tree.addChild(¤t.tree); - while(iter.next()) |link| { - const line = Line.unlink(link); - const indent = line.text.countIndent(4); - if (indent == last_indent) { - current.tree.pushNext(&line.tree); - } - else if (indent > last_indent) { - current.tree.pushChild(&line.tree); - } - else { // for last_indent > indent - // find parent with indent > indent - var parent = current.tree.parent.?; - while (true) { - if (parent == &self.tree) {parent = ¤t.tree; break;} - const parent_line = Line.untree(parent); - const parent_indent = parent_line.text.countIndent(4); - if (parent_indent > indent) break; - parent = current.tree.parent.?; - } - parent.pushChild(&line.tree); - } - - current = line; - last_indent = indent; - } - - // remove from chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - line.link = .{}; - } - self.lines = .{}; - - prog.need_redraw = true; - self.foldMode = .byIndent; - } - - pub fn goToIn (t: *T) void { - if (self.fold_mode == .flat) return; - const child = self.line.child orelse return; - const child_indent = child.text.countIndent(1); - self.goToSymbol(child_indent); - self.symbol = child_indent; - self.line = child; - if (prog.console.size.y > 6) {self.offset.y = 6;} - else if (prog.console.size.y > 3) {self.offset.y = 3;} - else if (prog.console.size.y > 1) {self.offset.y = 1;} - else {self.offset.y = 0;} - self.bakup(); - if (self.symbol >= 4) self.offset.x = 4; - prog.need_redraw = true; - } - pub fn goToOut (t: *T) void { - if (self.fold_mode == .flat) return; - if (self.line.getParent()) |parent| { - const parent_indent = parent.text.countIndent(1); - self.line = parent; - self.goToSymbol(parent_indent); - self.offset.y = 6; - if (self.symbol >= 4) self.offset.x = 4; - } - else { - self.goToRoot(); - } - self.bakup(); - prog.need_redraw = true; - } - //} - // { clipboard - pub fn externalCopy (t: *T) !void { - prog.need_redraw = false; - // { create file - var cwd = std.fs.cwd(); - var file = try cwd.createFile(prog.path_to_clipboard.get(), .{}); - defer file.close(); - const writer = file.writer(); - // } - if (prog.buffer_lines.cutted) |cutted| { - // { working with lines - var current: *Line = cutted; - try writer.writeAll(current.text.get()); - copying: while (true) { - if (current.child) |child| { - try writer.writeAll("\n"); - try writer.writeAll(child.text.get()); - current = child; - } - else if (current.next) |next| { - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - next = current.next orelse continue; - break; - } - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - } - // } - { // change status - prog.need_redraw = false; - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.blue2); - try prog.console.out.writeAll("cutted lines saved to ~/clipboard.tmp"); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - } - else { - // { working with lines - const first = self.line; - try writer.writeAll(first.text.get()); - if (first.child) |first_child| { - var current: *Line = first_child; - try writer.writeAll("\n"); - try writer.writeAll(current.text.get()); - copying: while (true) { - if (current.child) |child| { - try writer.writeAll("\n"); - try writer.writeAll(child.text.get()); - current = child; - } - else if (current.next) |next| { - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - if (current == first) break: copying; - next = current.next orelse continue; - break; - } - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - } - } - // } - { // change status - prog.need_redraw = false; - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.blue2); - try prog.console.writeAll("this block saved to ~/clipboard.tmp"); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - } - } - pub fn externalPaste (t: *T) !void { - // read file - var file_data: []const u8 = undefined; - const loaded = lib.fileRead(prog.allocator, prog.path_to_clipboard.get()); - defer if (loaded) |data| {prog.allocator.free(data);} else |_| {}; - if (loaded) |data| {file_data = data;} else |err| { - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.red2); - try prog.console.writeAll("file ~/clipboard.tmp not reedable."); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - return err; - } - - // paste - const line = self.current_line; - try self.addPrevLine(); - for (file_data) |rune| { // parse lines - switch(rune) { - 10, 13 => {try self.addNextLine();}, - else => {try self.insertSymbol(rune);}, - } - } - self.line = line; - prog.need_redraw = true; - } - //} - // { bakup - pub fn bakup (t: *T) void { - self.bakup_line.text.set(self.line.text.get()) catch {}; - } - pub fn restore (t: *T) void { - self.line.text.set(self.bakup_line.text.get()) catch {}; - prog.need_redraw = true; - } - // } - // { indent - pub fn indentToCutie (t: *T) void { - var current = self.line; - current.changeIndentToCutie() catch {}; - var first = current; - if (first.child) |first_child| { - current = first_child; - traversal: while (true) { - if (current.child) |child| { - current.changeIndentToCutie() catch {}; - current = child; - } - else if (current.next) |next| { - current.changeIndentToCutie() catch {}; - current = next; - } - else { - if (self.foldMode == .byBrackets) { - const parent = current.getParent() orelse break :traversal; - const indent = parent.text.countIndent(1); - current.text.changeIndent(indent) catch {}; - } - else { - current.changeIndentToCutie() catch {}; - } - while (true) { // find parent with next - current = current.getParent() orelse break :traversal; - if (current == first) break :traversal; - if (current.next) |next| { - current = next; - break; - } - } - } - } - } - prog.need_redraw = true; - } - pub fn deleteIndent (t: *T) void { - var current = self.line; - current.text.changeIndent(0) catch {}; - var first = current; - if (first.child) |first_child| { - current = first_child; - traversal: while (true) { - if (current.child) |child| { - current.text.changeIndent(0) catch {}; - current = child; - } - else if (current.next) |next| { - current.text.changeIndent(0) catch {}; - current = next; - } - else { - current.text.changeIndent(0) catch {}; - while (true) { // find parent with next - current = current.getParent() orelse break :traversal; - if (current == first) break :traversal; - if (current.next) |next| { - current = next; - break; - } - } - } - } - } - prog.need_redraw = true; - } - // } - // { easy motion - pub fn draw_horizontal_help_motion (t: *T) !void { - var pos: usize = 0; - var rune: u8 = 0x61; - try ansi.do(ansi.color.magenta); - while(true) { - try prog.console.cursorMove(.{ .x = pos, .y = self.offset.y }); - prog.console.writeByte(rune) catch unreachable; - if (rune >= 0x7A) break; rune += 1; - if (pos >= prog.console.size.x - 3) break; pos += 3; - } - try self.cursorMoveToCurrent(); - } - pub fn draw_vertical_help_motion (t: *T) !void { - var pos: usize = 0; - try ansi.do(ansi.color.magenta); - while(true) { - try prog.console.cursorMove(.{ .x = self.offset.x, .y = pos }); - prog.console.writeByte(0x61 + @truncate(u8, pos)) catch unreachable; - if (pos >= 0x7A - 0x61) break; - if (pos == prog.console.size.y - 1) break; - pos += 1; - } - try self.cursorMoveToCurrent(); - } - pub fn easyMotionHorizontal (t: *T, key: u8) !void { - var pos = key - 0x61; - self.goToSymbol(self.symbol - self.offset.x + pos * 3); - try self.changeMode(.edit); - prog.need_redraw = true; - } - pub fn easyMotionVertical (t: *T, key: u8) !void { - var pos = key - 0x61; - if (self.offset.y == pos) {} - else if (self.offset.y > pos) { - var i = self.offset.y - pos; - while (i > 0) : (i -= 1) { - self.goToPrevLine(); - } - } - else { // (self.offset.y < pos) - var i = pos - self.offset.y; - while (i > 0) : (i -= 1) { - self.goToNextLine(); - } - } - try self.changeMode(.edit); - prog.need_redraw = true; - } - // } - - // being developed - pub fn drawRunes (t: *T) !void { - try prog.console.cursorMove(.{.x = 0, .y = self.offset.y}); - defer self.cursorMoveToCurrent() catch {}; - - try ansi.do(ansi.color.red); - defer ansi.do(ansi.reset) catch {}; - - draw: { - var screen_pos_x: usize = 0; - var text_pos: usize = self.offset.x; // TODO skip first text_pos runes - const runes = self.current_line.runes orelse break: draw; - var link = &runes.link; - while(true) { - if (screen_pos_x >= prog.console.size.x - 3) break; - const rune = Rune.unlink(link); - try prog.console.writeAll(rune.glyph.getText()); - screen_pos_x += 1; - text_pos += 1; - link = link.next orelse break; - } - } - defer ansi.do(ansi.clear_to_end_line) catch {}; - - prog.need_redraw = false; - } - pub fn goToNextFlatLine (t: *T) void { - const line_link = self.line.chain_link.next orelse return; - self.line = Line.unlink(line_link); - } - pub fn goToPrevFlatLine (t: *T) void { - const line_link = self.line.chain_link.prev orelse return; - self.line = Line.unlink(line_link); - } - // { find - pub fn findNext (t: *T) void { - const text = self.line.text.get(); - var line = self.line; - if (line.text.find(text, self.symbol)) |pos| { // goto pos and return - self.line = line; - self.goToSymbol(pos); - return; - } - else { // iterate and find - while(true) { - // iterate - if (line.child) |child| { // goto child - line = child; - } - else if (line.next) |next| { // goto next - line = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - line = line.getParent() orelse return; - next = line.next orelse continue; - break; - } - line = next; - } - - // find - if (line.text.find(text, 0)) |pos| { // goto pos and return - self.line = line; - self.goToSymbol(pos); - return; - } - } - } - self.changeMode(.edit); - prog.need_clear = true; - prog.need_redraw = true; - self.bakup(); - } - // } -// } DELETED src/ViewTreeByIndent.zig Index: src/ViewTreeByIndent.zig ================================================================== --- src/ViewTreeByIndent.zig +++ /dev/null @@ -1,1771 +0,0 @@ -// this file is just gabarage. -// i rewrite this in future. - -const Self = @This(); -// { fields - file_name: Text = .{}, - - // modes - mode: Mode = .edit, - indent: Indent = .{}, - selected: usize = 0, - - tree: Tree = .{}, - cutted: Tree = .{}, - - bakup_line: *Line = undefined, - last_working_line: ?*Line = null, - marked_line: ?*Line = null, - lines_drawing: usize = 0, - - // current pos - current_line: *Line, - offset: lib.Coor2u = .{.x = 0, .y = 0 }, - symbol: usize = 0, -// } -// { methods - pub fn onMouse (self: *Self) !void { - const mode = prog.console.input.buffer[3]; - if (mode != ' ') return; - - var coor_x = prog.console.input.buffer[4]; - if (coor_x < 33) { - try ansi.do(ansi.color.yellow); - try prog.console.out.print("x = {d}", .{coor_x}); - return; - } - coor_x -= 33; - self.view.goToSymbol(self.view.symbol - self.view.offset.x + coor_x); - - var coor_y = prog.console.input.buffer[5]; - if (coor_y < 35) { - try ansi.do(ansi.color.yellow); - try prog.console.out.print("x = {d}", .{coor_x}); - return; - } - coor_y -= 35; - if (self.view.offset.y == coor_y) {} - else if (self.view.offset.y > coor_y) { - var i = self.view.offset.y - coor_y; - while (i > 0) : (i -= 1) { - self.view.goToPrevLine(); - } - } - else { // (self.view.offset.y < coor_y) - var i = coor_y - self.view.offset.y; - while (i > 0) : (i -= 1) { - self.view.goToNextLine(); - } - } - - prog.need_redraw = true; - } - pub fn onKey (self: *Self, cik: Console.Input.Key) !void { - switch (self.view.mode) { - .edit => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .mouse => {try self.onMouse();}, - .f1 => {try self.view.goToHelp();}, - .f1_rxvt => {try self.view.goToHelp();}, - .f1_tty => {try self.view.goToHelp();}, - .f2 => {self.debug.toggle();}, - .f2_rxvt => {self.debug.toggle();}, - .f2_tty => {self.debug.toggle();}, - .f3 => {self.view.goToPrevFlatLine();}, - .f4 => {self.view.goToNextFlatLine();}, - .f5 => {try self.view.drawRunes();}, - .f9 => {try self.view.changeMode(.normal);}, - .f10 => {self.stop();}, - - .delete => {self.view.deleteSymbol();}, - .shift_delete => {self.view.clearLine();}, - - .end => {self.view.goToEndOfLine();}, - .home => {self.view.goToStartOfLine();}, - - .down => {self.view.goToNextLine();}, - .up => {self.view.goToPrevLine();}, - .left => {self.view.goToPrevSymbol();}, - .right => {self.view.goToNextSymbol();}, - .ctrl_shift_left => {self.view.CtrlShiftLeft();}, - .ctrl_shift_right => {self.view.CtrlShiftRight();}, - .ctrl_left => {self.view.goToStartOfWord();}, - .ctrl_left_rxvt => {self.view.goToStartOfWord();}, - .ctrl_right => {self.view.goToEndOfWord();}, - .ctrl_right_rxvt => {self.view.goToEndOfWord();}, - .ctrl_up => {self.view.goToFirstLine();}, - .ctrl_down => {self.view.goToLastLine();}, - .alt_up => {self.view.swapWithUpper();}, - .alt_down => {self.view.swapWithBottom();}, - - .alt_n => {self.view.insertSymbol('\n') catch {};}, - .alt_r => {self.view.insertSymbol('\r') catch {};}, - .alt_v => {self.view.externalPaste() catch {};}, - .alt_m => {self.view.markThisLine();}, - .alt_j => {self.view.goToMarked();}, - .alt_p => {self.view.deleteIndent();}, - - else => {self.need_redraw = true;}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - self.need_redraw = true; - }, - .ascii_key => |key| { - switch (key) { - .ctrl_q => {self.stop();}, - .ctrl_s => {self.view.save() catch {};}, - .ctrl_g => {try self.view.changeMode(.to_line);}, - .ctrl_f => {try self.view.changeMode(.to_find);}, - .ctrl_u => {self.view.unFold();}, - .ctrl_r => {try self.view.foldFromIndent();}, - .ctrl_e => {self.view.foldFromBrackets();}, - .ctrl_j => {self.view.joinLines();}, - .enter => { - switch (self.console.input.is_paste) { - true => {self.view.addNextLine() catch {};}, - false => {self.view.divide() catch {};}, - } - }, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_p => {self.view.indentToCutie();}, - .ctrl_d => {self.view.duplicate();}, - .ctrl_x => {self.view.cut();}, - .ctrl_c => {self.view.externalCopy() catch {};}, - .ctrl_v => {self.view.pasteLine();}, - .ctrl_t => {self.view.insertSymbol('\t') catch {};}, - .escape => {self.view.goToOut();}, - .tab => {self.view.goToIn();}, - .ctrl_w => {self.view.deleteWord();}, - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .ctrl_z => {self.view.restore();}, - .ctrl_o => {try self.view.drawRunes();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .to_find => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .ctrl_left => self.view.goToStartOfLine(), - .ctrl_right => self.view.goToEndOfLine(), - .delete => self.view.deleteSymbol(), - .shift_delete => {self.view.clearLine();}, - else => {}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - }, - .ascii_key => |key| { - switch (key) { - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_j => {self.view.findNext();}, - .enter => {self.view.findNext();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .to_line => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .ctrl_left => self.view.goToStartOfLine(), - .ctrl_right => self.view.goToEndOfLine(), - .delete => self.view.deleteSymbol(), - .shift_delete => {self.view.clearLine();}, - else => {}, - } - }, - .byte => |byte| { - self.view.insertSymbol(byte) catch {}; - }, - .ascii_key => |key| { - switch (key) { - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .ctrl_j => {try self.view.goToLineFromInput();}, - .enter => {try self.view.goToLineFromInput();}, - else => { - var byte = @enumToInt(key); - self.view.insertSymbol(byte) catch {}; - }, - } - }, - } - }, - .history => {}, - .select => {}, - .normal => { - switch (cik) { - .sequence => |sequence| { - switch (sequence) { - .delete => {self.view.deleteSymbol();}, - .shift_delete => {self.view.clearLine();}, - .end => {self.view.goToEndOfLine();}, - .home => {self.view.goToStartOfLine();}, - .down => {self.view.goToNextLine();}, - .up => {self.view.goToPrevLine();}, - .left => {self.view.goToPrevSymbol();}, - .right => {self.view.goToNextSymbol();}, - else => {}, - } - }, - .byte => |_| {}, - .ascii_key => |key| { - switch (key) { - .code_q => {self.stop();}, - .code_s => {self.view.save() catch {};}, - .code_i => {try self.view.changeMode(.edit);}, - .code_g => {try self.view.changeMode(.to_line);}, - .code_u => {self.view.unFold();}, - .code_r => {try self.view.foldFromIndent();}, - .code_e => {self.view.foldFromBrackets();}, - .code_j => {self.view.divide() catch {};}, - .enter => {self.view.divide() catch {};}, - .back_space => {self.view.deletePrevSymbol();}, - .ctrl_bs => {self.view.deletePrevSymbol();}, - .code_p => {self.view.line.changeIndentToCutie() catch {};}, - .code_d => {self.view.duplicate();}, - .code_x => {self.view.cut();}, - .code_c => {self.view.externalCopy() catch {};}, - .code_v => {self.view.pasteLine();}, - .code_t => {self.view.insertSymbol('\t') catch {};}, - .escape => {self.view.goToOut();}, - .tab => {self.view.goToIn();}, - .code_l => {self.view.goToLastLine();}, - else => {}, - } - }, - } - }, - .easy_motion_vertical => { - switch (cik) { - .sequence => |_| {}, - .byte => |_| {}, - .ascii_key => |key| { - const num = @enumToInt(key); - if (num >= 0x61 and num <= 0x7A) {try self.view.easyMotionVertical(num);} - else switch (key) { - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - else => {}, - } - }, - } - }, - .easy_motion_horizontal => { - switch (cik) { - .sequence => |_| {}, - .byte => |_| {}, - .ascii_key => |key| { - const num = @enumToInt(key); - if (num >= 0x61 and num <= 0x7A) {try self.view.easyMotionHorizontal(num);} - else switch (key) { - .ctrl_l => {try self.view.changeMode(.easy_motion_horizontal);}, - .ctrl_k => {try self.view.changeMode(.easy_motion_vertical);}, - .escape => {try self.view.changeMode(.edit);}, - .ctrl_q => {self.stop();}, - else => {}, - } - }, - } - }, - } - } - - pub fn fromAlloc () !*View { - const allocated = lib.c.aligned_alloc(8, @sizeOf(View)) orelse return error.NeedMoreMemory; - var view: *View = @ptrCast(*View, @alignCast(8, allocated)); - return view; - } - pub fn init (self: *Self, file_name: []const u8, text: []const u8) !void { - self.* = .{}; - self.file_name.set(file_name) catch unreachable; - { // parse_text_to_lines - var iter = std.mem.split(u8, text, "\n"); - while(iter.next()) |line| { - const new_line = try prog.buffer_lines.create(); - new_line.text.set(line) catch { - return error.LineIsToLong; - }; - self.lines.pushLast(&new_line.chain_link); - } - } - const link = self.lines.first.?; - self.current_line = Line.unlink(link); - self.bakup_line = try prog.buffer_lines.create(); - } // end fn loadLines - pub fn save (self: *Self) !void { - prog.need_redraw = false; - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(Theme.save); - try prog.console.writeAll("saving..."); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - // { create file - var cwd = std.fs.cwd(); - var file = try cwd.createFile(self.file_name.get(), .{}); - defer file.close(); - const writer = file.writer(); - // } - var count: usize = 0; // lines - write: { //write - switch(self.fold_mode) { - .flat => { - var iter = self.lines.iter(); - - // write first line - const first_link = iter.next() orelse break: write; - const first_line = Line.unLink(first_link); - count += 1; - try writer.writeAll(first_line.text.get()); - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try prog.console.out.print("{} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - - // write other lines - while(iter.next()) |link| { - try writer.writeAll("\n"); - const line = Line.unlink(link); - count += 1; - try writer.writeAll(line.text.get()); - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try prog.console.out.print("{} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - } - }, - else => { - var walker = self.tree.walker(); - _ = walker.next(); // skip root - - // save first line (without "\n") - const first_tree = walker.next() orelse break: write; - const first_line = Line.untree(first_tree); - count += 1; - try writer.writeAll(first_line.text.get()); - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try prog.console.out.print("{} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - - // save other lines (with "\n") - while(walker.next()) |tree| { - try writer.writeAll("\n"); - const line = Line.untree(tree); - count += 1; - try writer.writeAll(line.text.get()); - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try prog.console.out.print("{} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - } - }, - } - } - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - defer self.cursorMoveToCurrent() catch {}; - - try ansi.do(Theme.save); - defer ansi.do(ansi.reset) catch {}; - - try prog.console.out.print("file saved. {} lines writed.", .{count}); - try ansi.do(ansi.clear_to_end_line); - } - } - pub fn changeMode (self: *Self, mode: Mode) !void { - switch (mode) { - .edit => {}, - .to_find => { - self.last_working_line = self.current_line; - }, - .to_line => { - self.last_working_line = self.current_line; - if (prog.buffer_lines.to_goto == null) { // create - const new_line = prog.buffer_lines.create() catch return; - prog.buffer_lines.to_goto = new_line; - } - self.current_line = prog.buffer_lines.to_goto.?; - self.goToEndOfLine(); - prog.need_redraw = true; - }, - .history => {}, - .select => {}, - .normal => {}, - .easy_motion_vertical => { - try self.draw_vertical_help_motion(); - }, - .easy_motion_horizontal => { - try self.draw_horizontal_help_motion(); - }, - } - self.mode = mode; - } - pub fn cursorMoveToCurrent (self: *Self) !void { - try prog.console.cursorMove(.{ .x = self.offset.x, .y = self.offset.y }); - } - pub fn goToHelp (self: *Self) !void { - self.current_line = prog.usage_line; - prog.need_redraw = true; - } - // { mark - pub fn markThisLine (self: *Self) void { - self.marked_line = self.line; - } - pub fn goToMarked (self: *Self) void { - if (self.marked_line) |mark| { - self.line = mark; - prog.need_redraw = true; - } - } - // } - // { edit - // block - pub fn duplicate (self: *Self) void { - const first = self.line; - const copy_first = prog.buffer_lines.create() catch return; - copy_first.text.set(first.text.get()) catch unreachable; - self.line.pushNext(copy_first); - if (first.child) |first_child| { - var current = first_child; - var copy_current = prog.buffer_lines.create() catch return; - copy_current.text.set(current.text.get()) catch unreachable; - copy_current.parent = copy_first; - copy_first.child = copy_current; - copying: while (true) { - if (current.child) |child| { - var copy_child = prog.buffer_lines.create() catch return; - copy_child.text.set(child.text.get()) catch unreachable; - copy_child.parent = copy_current; - copy_current.child = copy_child; - current = child; - copy_current = copy_child; - } - else if (current.next) |next| { - var copy_next = prog.buffer_lines.create() catch return; - copy_next.text.set(next.text.get()) catch unreachable; - copy_next.prev = copy_current; - copy_current.next = copy_next; - current = next; - copy_current = copy_next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - if (current == first) break: copying; - copy_current = copy_current.getParent() orelse unreachable; - next = current.next orelse continue; - break; - } - var copy_next = prog.buffer_lines.create() catch return; - copy_next.text.set(next.text.get()) catch unreachable; - copy_next.prev = copy_current; - copy_current.next = copy_next; - current = next; - copy_current = copy_next; - } - } - } - self.line = copy_first; - prog.need_redraw = true; - } - pub fn cut (self: *Self) void { - if (self.line.parent) |parent| { - parent.child = self.line.next; - } - var next_selected_line: *Line = undefined; - // { select next selected line - if (self.line.next) |next| { - next_selected_line = next; - } else if (self.line.prev) |prev| { - next_selected_line = prev; - } else if (self.line.parent) |parent| { - next_selected_line = parent; - } else { - self.line.text.set("") catch unreachable; - return; - } - // } - if (self.lines == self.line) self.lines = next_selected_line; - prog.buffer_lines.cut(self.line); - self.line = next_selected_line; - prog.need_redraw = true; - self.bakup(); - } - pub fn pasteLine (self: *Self) void { - if (prog.buffer_lines.cutted) |cutted| { - prog.buffer_lines.cutted = cutted.next; - cutted.next = null; - self.line.pushPrev(cutted); - if (self.lines == self.line) self.lines = cutted; - self.offset.y += 1; - self.goToPrevLine(); - self.indentToCutie(); - } - prog.need_redraw = true; - } - - // line - pub fn joinLines (self: *Self) void { - if (self.line.child) |_| return; - const next = self.line; - const prev = self.line.prev orelse return; - - self.deleteIndent(); - - const next_used = next.text.used; - const prev_used = prev.text.used; - - if (prev_used + next_used > Line.Text.size - 3) return; - std.mem.copy(u8, prev.text.buffer[prev.text.used..], next.text.get()); - prev.text.used += next_used; - prog.buffer_lines.delete(self.line); - self.line = prev; - self.goToSymbol(prev_used); - } - pub fn clearLine (self: *Self) void { - self.line.text.used = 0; - self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn addPrevLine (self: *Self) !void { - const new_line = try prog.buffer_lines.create(); - switch(self.fold_mode) { - .flat => { - self.lines.pushPrev(self.current_line, &new_line.link); - }, - else => { - var tree = &self.current_line.tree; - tree.link.pushPrev(&new_line.tree); - }, - } - self.current_line = new_line; - self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn addNextLine (self: *Self) !void { - const new_line = try prog.buffer_lines.create(); - switch(self.fold_mode) { - .flat => { - self.lines.pushNext(self.current_line, &new_line.link); - }, - else => { - var tree = &self.current_line.tree; - tree.link.pushNext(&new_line.tree); - }, - } - self.current_line = new_line; - self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn divide (self: *Self) !void { - const indent = self.line.text.countIndent(1); - if (self.symbol <= indent) { // just add prev line - const last_symbol = self.symbol; - const last_offset = self.offset.x; - try self.addPrevLine(); - try self.line.changeIndentToCutie(); - self.goToNextLine(); - self.symbol = last_symbol; - self.offset.x = last_offset; - } - else if (self.symbol >= self.line.text.used) { // just add next line - if (self.line.text.buffer[self.symbol - 1] == ':') { - if (self.line.child) |_| return; - const new_line = prog.buffer_lines.create() catch return; - // { link - self.line.child = new_line; - new_line.parent = self.line; - // } - self.goToIn(); - } - else { - try self.addNextLine(); - } - } - else if (self.line.text.buffer[self.symbol] == '}' and self.line.text.buffer[self.symbol - 1] == '{') { - if (self.line.child != null) return; - const pos = self.symbol; - const last_line = self.line; - - const new_line = prog.buffer_lines.create() catch return; - // { link - self.line.child = new_line; - new_line.parent = self.line; - // } - // { copy text and fill spaces - const text_to_new_line = last_line.text.get()[pos..]; - std.mem.copy(u8, new_line.text.buffer[indent..], text_to_new_line); - for (new_line.text.buffer[0 .. indent]) |*rune| rune.* = ' '; // spam spaces - new_line.text.used = indent + text_to_new_line.len; - last_line.text.used = pos; - // } - - self.line = new_line; - try self.addPrevLine(); - } - else { - if (self.line.child) |_| return; - var parent = self.line; - var pos = self.symbol; - const text = self.line.text.get()[pos..]; - try self.addNextLine(); - self.line.text.used = indent + text.len; - std.mem.copy(u8, self.line.text.buffer[indent..], text); - for (self.line.text.buffer[0..indent]) |*rune| rune.* = ' '; - parent.text.used = pos; - } - self.indentToCutie(); - self.goToStartOfText(); - if (false) { // change status (debug) - const last_cursor_pos: lib.Coor2u = prog.console.cursor.pos; - defer { // reset color, clear line, restore cursor pos and flush - defer Console.Output.print(ansi.reset); - Console.Output.print(ansi.clear_to_end_line); - defer prog.console.cursorMove(last_cursor_pos); - Console.Output.flush(); - } - - prog.console.cursorMove(.{ .x = 0, .y = 0 }); - Console.Output.print(ansi.color.red2); - - var buffer: [254]u8 = undefined; - var text_len: usize = 0; - var sprintf_result = lib.c.sprintf(&buffer, "line used = %d", self.line.text.used); - text_len += @intCast(usize, sprintf_result); - prog.console.print(buffer[0 .. text_len]); - } - if (self.symbol >= 4) self.offset.x = 4; - prog.need_redraw = true; - } - pub fn swapWithBottom (self: *Self) void { - const current_link = &self.current_line.link; - if (self.current_line.next) |_| { - self.cut(); - self.goToNextLine(); - self.pasteLine(); - } - prog.need_redraw = true; - } - pub fn swapWithUpper (self: *Self) void { - if (self.line.prev) |_| { - self.cut(); - self.goToPrevLine(); - self.pasteLine(); - } - prog.need_redraw = true; - } - pub fn deleteLine (self: *Self) void { - const line = self.line; - var next_selected_line: *Line = undefined; - if (line.next) |next| { - next_selected_line = next; - } - else if (line.prev) |prev| { - next_selected_line = prev; - } - else if (line.parent) |parent| { - next_selected_line = parent; - } - else { // clear and exit - self.clearLine(); - return; - } - self.clearLine(); - if (self.lines == self.line) self.lines = next_selected_line; - prog.buffer_lines.delete(self.line); - self.line = next_selected_line; - prog.need_redraw = true; - } - - // word - pub fn deleteWord (self: *Self) void { - if (self.symbol > self.line.text.used) {return;} - while(true) { // delete current symbol - if (self.symbol == self.line.text.used) {break;} - const next_symbol = self.line.text.buffer[self.symbol]; - if (textlib.isLetter(next_symbol)) {self.deleteSymbol();} else {break;} - } - while(true) { // delete prev symbol - if (self.symbol == 0) {break;} - const prev_symbol = self.line.text.buffer[self.symbol - 1]; - if (textlib.isLetter(prev_symbol)) {self.deletePrevSymbol();} else {break;} - } - prog.need_redraw = true; - } - - // symbol - pub fn insertSymbol (self: *Self, rune: u8) !void { - const t = &self.current_line.text; - if (self.symbol > t.used) self.goToSymbol(t.used); - try t.insert(self.symbol, rune); - self.goToNextSymbol(); - prog.need_redraw = true; - } // end fn - pub fn deleteSymbol (self: *Self) void { - if (self.line.text.used == 0) return; - self.line.text.delete(self.symbol) catch return; - prog.need_redraw = true; - } - pub fn deletePrevSymbol (self: *Self) void { - switch (self.symbol) { - 0 => { - if (self.line.parent) |_| return; - if (self.line.child) |_| return; - if (self.line == self.lines) return; - - const prev = self.line.prev orelse return; - - const non_indent = self.line.text.countNonIndent(); - if (non_indent == 0) { // delete self line - prog.buffer_lines.delete(self.line); - self.line = prev; - prog.need_redraw = true; - return; - } - - const prev_count = prev.text.countNonIndent(); - switch (prev_count) { - 0 => { // delete prev - if (self.lines == prev) self.lines = self.line; - prog.buffer_lines.delete(prev); - prog.need_redraw = true; - return; - }, - else => { // join line - self.joinLines(); - }, - } - }, - else => { - if (self.line.text.used == 0) return; - self.goToPrevSymbol(); - self.deleteSymbol(); - }, - } - prog.need_redraw = true; - } - //} - // { draw - pub fn draw (self: *Self) !void { - try ansi.do(ansi.cyrsor_style.hide); - defer ansi.do(ansi.cyrsor_style.show) catch {}; - defer self.cursorMoveToCurrent() catch {}; - if (self.symbol < self.offset.x) { // unexpected - self.offset = .{}; - self.symbol = 0; - } - switch (self.mode) { - .edit => { - switch (self.fold_mode) { - .flat => { - Theme.line.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - try self.drawLine(); - if (self.offset.y > 0) { // draw upper lines - var iter = self.line.link.iterReverse(); - - // skip current; - var pos_y = self.offset.y - 1; - _ = iter.next(); - - while(iter.next()) |link| { - const line = Line.unlink(link); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y}); - self.drawLine(line); - if (pos_y == 0) break; - pos_y -= 1; - } - } - if (self.offset.y < prog.console.size.y) { // draw downer lines - var iter = self.line.link.iter(); - - // skip current; - var pos_y = self.offset.y + 1; - _ = iter.next(); - - while(iter.next()) |link| { - const line = Line.unlink(link); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y}); - self.drawLine(line); - if (pos_y == 0) break; - pos_y += 1; - } - while (true) { // clear other downer lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y >= prog.console.size.y - 1) return; - pos_y += 1; - std.time.sleep(draw_lag); - } - } - try self.drawEdited(); - }, - else => { - // draw other lines - try self.drawUpperLines(); - try self.drawDownerLines(); - - // draw edit line - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y }); - if (self.line.tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(self.line); - try self.drawEditedF(); - } - else { - try Theme.line.apply(); - try self.drawLine(self.line); - try self.drawEdited(); - } - }, - } - }, - .to_line => { - self.offset.y = 1; - - // draw banner - try prog.console.changeColor(Theme.headers); - try prog.console.cursorMove(.{ .x = 0, .y = 0}); - try prog.console.out.writeAll("enter the line you want to jump to:"); - try ansi.do(ansi.clear_to_end_line); - - // draw edit line - try prog.console.cursorMove(.{ .x = 0, .y = 1}); - defer self.cursorMoveToCurrent() catch {}; - try self.drawEditedLine(); - - var pos_y: usize = 2; - while (true) { // clear other downer lines - if (pos_y >= prog.console.size.y) return; - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - pos_y += 1; - std.time.sleep(draw_lag); - - } - }, - .easy_motion_vertical, - .easy_motion_horizontal, - .to_find, - .history, - .select, - .normal, - => {}, - } - } // end draw lines - pub fn drawLine (self: *Self, line: *Line) !void { - // move to start - defer ansi.do(ansi.clear_to_end_line) catch {}; - try prog.console.cr(); - if (line.text.used == 0) {return;} - - // draw left-to-right - const text = line.text.get(); - var text_pos: usize = self.symbol - self.offset.x; // first visible rune - var offset_x: usize = 0; - while (true) { - if (text_pos >= text.len) break; - if (offset_x >= prog.console.size.x - 1) break; - prog.console.writeByte(text[text_pos]) catch unreachable; - text_pos += 1; - offset_x += 1; - } - } - pub fn drawParentLine (self: *Self, parent: *Line) !void { - // draw - try prog.console.cr(); - const text = parent.text.get(); - var indent = parent.text.countIndent(1); - var symbol: usize = indent; - if (indent >= self.symbol - self.offset.x) {symbol = self.symbol - self.offset.x;} - var offset_x: usize = 0; - while (true) { - if (symbol >= text.len) { - try ansi.do(ansi.clear_to_end_line); - break; - } - if (offset_x >= prog.console.size.x) break; - prog.console.writeByte(text[symbol]) catch unreachable; - - symbol += 1; - offset_x += 1; - } - } - pub fn drawEdited (self: *Self) !void { - const text: []u8 = self.line.text.get(); - const pos: usize = self.symbol - self.offset.x; - const end_pos: usize = pos + prog.console.size.x; - - if (pos > 0) { // draw '<' - try Theme.outLine.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - prog.console.writeByte('<') catch unreachable; - } - if (text.len > end_pos) { // draw '>' - try Theme.outLine.apply(); - try prog.console.cursorMove(.{ .x = prog.console.size.x - 1, .y = self.offset.y}); - prog.console.writeByte('>') catch unreachable; - } - if (pos < text.len) { // draw symbol about cursor - try self.cursorMoveToCurrent(); - try Theme.currentRune.apply(); - try prog.console.writeByte(text[pos]); - } - } // drawEdited - pub fn drawEditedF (self: *Self) !void { - const text: []u8 = self.line.text.get(); - const pos: usize = self.symbol - self.offset.x; - const end_pos: usize = pos + prog.console.size.x; - - if (pos > 0) { // draw '<' - try Theme.outLineF.apply(); - try prog.console.cursorMove(.{ .x = 0, .y = self.offset.y}); - prog.console.writeByte('<') catch unreachable; - } - if (text.len > end_pos) { // draw '>' - try Theme.outLineF.apply(); - try prog.console.cursorMove(.{ .x = prog.console.size.x - 1, .y = self.offset.y}); - prog.console.writeByte('>') catch unreachable; - } - if (pos < text.len) { // draw symbol about cursor - try self.cursorMoveToCurrent(); - try Theme.currentRuneF.apply(); - try prog.console.writeByte(text[pos]); - } - } // drawEdited - // draw tree - pub fn drawUpperLines (self: *Self) !void { - //TODO: apply self.max_draw_parent_lines = 2; - - // draw lines - if (self.offset.y == 0) return; - var iter = self.line.tree.link.iteratorReverse(); - // skip current - var pos_y: usize = self.offset.y - 1; - _ = iter.next(); - while(iter.next()) |link| { - const tree = Tree.unlink(link); - const line = Line.unTree(tree); - - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - if (tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(line); - } - else { - try Theme.line.apply(); - try self.drawLine(self.line); - } - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - while (true) { // draw parents - try Theme.headers.apply(); - const tree = self.line.tree.parent orelse break; - if (tree == self.tree) break; - const line = Line.untree(tree); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try self.drawParentLine(line); - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - while (true) { // clear other upp lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y == 0) return; - pos_y -= 1; - std.time.sleep(draw_lag); - } - } - pub fn drawDownerLines (self: *Self) !void { - var iter = self.line.tree.link.iterator(); - // skip current - var pos_y: usize = self.offset.y + 1; - _ = iter.next(); - - if (pos_y >= prog.console.size.y) return; - while (iter.next) |tree_link| { // draw lines - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - if (line.tree.childs.count > 0) { - try Theme.lineFolded.apply(); - try self.drawLineF(line); - } - else { - try Theme.line.apply(); - try drawLine(self.line); - } - if (pos_y >= prog.console.size.y - 1) { - self.lines_drawing = prog.console.size.y; - return; - } - pos_y += 1; - std.time.sleep(draw_lag); - } - - self.lines_drawing = pos_y; - while (true) { // clear other downer lines - try ansi.do(ansi.reset); - try prog.console.cursorMove(.{ .x = 0, .y = pos_y }); - try ansi.do(ansi.clear_line); - if (pos_y >= prog.console.size.y - 1) return; - pos_y += 1; - std.time.sleep(draw_lag); - } - } - // } - // { navigation - // over lines - pub fn goToRoot (self: *Self) void { - self.line = self.lines; - self.offset.y = 5; - self.goToStartOfLine(); - prog.need_redraw = true; - self.bakup(); - } - pub fn goToPrevLine (self: *Self) void { - switch(self.fold_mode) { - .flat => { - if (self.link.prev) |prev| { - const line = Line.unlink(prev); - self.line = line; - } - }, - else => { - if (self.line.tree.link.prev) |tree_link| { - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - self.line = line; - prog.need_redraw = true; - } - }, - } - if (self.offset.y > 5) {self.offset.y -= 1;} - self.bakup(); - } // end fn - pub fn goToNextLine (self: *Self) void { - switch(self.fold_mode) { - .flat => { - if (self.link.next) |prev| { - const line = Line.unlink(prev); - self.line = line; - } - }, - else => { - if (self.line.tree.link.next) |tree_link| { - const tree = Tree.unlink(tree_link); - const line = Line.untree(tree); - self.line = line; - prog.need_redraw = true; - } - }, - } - self.bakup(); - - if (self.offset.y < prog.console.size.y - 1) self.offset.y += 1; - // { correct offset_y: - // count downest_lines - var count_to_downest_line: usize = 0; - var iter = if (self.fold_mode == .flat) self.line.link.iterator() else self.line.tree.chain_link.iterator(); - _ = iter.next(); - while (count_to_downest_line < 5) { - _ = iter.next() orelse break; - count_to_downest_line += 1; - } - - if (prog.console.size.y - self.offset.y < count_to_downest_line) { - self.offset.y = prog.console.size.y - count_to_downest_line; - } - //} - prog.need_redraw = true; - } // end fn - pub fn goToFirstLine (self: *Self) void { - while (self.line.prev) |_| self.goToPrevLine(); - self.goToStartOfLine(); - prog.need_redraw = true; - self.bakup(); - } - pub fn goToLastLine (self: *Self) void { - while (self.line.next) |_| self.goToNextLine(); - prog.need_redraw = true; - self.bakup(); - } - // { go to line from number - pub fn goToLineFromNumber (self: *View, num: usize) void { - if (self.fold_mode != .flat) self.unfold(); - var iter = self.lines.first.iterator(); - var pos = 0; - while(iter.next()) |_| { - if (pos == num) break; - pos += 1; - } - self.line = Line.unlink(iter.current); - - self.offset.y = 6; - self.goToSymbol(self.line.text.countIndent(1)); - if (self.symbol >= 4) self.offset.x = 4; - prog.need_redraw = true; - self.bakup(); - } - pub fn goToLineFromInput (self: *View) !void { - if (self.line.text.used == 0) return; - var num: usize = @truncate(usize, textlib.u64FromCharsDec(self.line.text.get()) catch return); - try self.changeMode(.edit); - self.goToLineFromNumber(num); - } - // } - - // over line - pub fn goToStartOfLine (self: *Self) void { - self.symbol = 0; - self.offset.x = 0; - prog.need_redraw = true; - } - pub fn goToEndOfLine (self: *Self) void { - self.symbol = self.line.text.used; - if (self.symbol > prog.console.size.x - 2) {self.offset.x = prog.console.size.x - 2;} - else {self.offset.x = self.symbol;} - prog.need_redraw = true; - } - pub fn goToStartOfText (self: *Self) void { - const indent = self.line.text.countIndent(1); - self.goToSymbol(indent); - } - pub fn CtrlShiftLeft (self: *Self) void { - const indent = self.line.text.countIndent(1); - if (self.symbol > indent) { - self.goToSymbol(indent); - if (self.symbol >= 4) self.offset.x = 4; - } - else self.goToStartOfLine(); - prog.need_redraw = true; - } - pub fn CtrlShiftRight (self: *Self) void { - const indent = self.line.text.countIndent(1); - if (self.symbol < indent) self.goToSymbol(indent) - else self.goToEndOfLine(); - prog.need_redraw = true; - } - - // over word - pub fn goToStartOfWord (self: *Self) void { - if (self.symbol == 0) {return;} - if (self.symbol > self.line.text.used) {self.goToSymbol(self.line.text.used);} - const first_rune = self.line.text.buffer[self.symbol]; - if (first_rune == ' ') { - self.goToPrevSymbol(); - while (true) { - if (self.symbol == 0) {break;} - const rune = self.line.text.buffer[self.symbol]; - if (rune != ' ') break; - self.goToPrevSymbol(); - } - } - else { - self.goToPrevSymbol(); - while(true) { - if (self.symbol == 0) {break;} - const next_symbol = self.line.text.buffer[self.symbol - 1]; - switch(next_symbol){ - ' ', '\t', '\\', - '=', '+', '-', '/', '*', '^', - '!', '@', '#', '$', '%', '&', - '(', ')', '[', ']', '{', '}', - '"', '\'', - ';', ':', '.', ',' - => {break;}, - else => {}, - } - self.goToPrevSymbol(); - } - } - prog.need_redraw = true; - } - pub fn goToEndOfWord (self: *Self) void { - if (self.symbol >= self.line.text.used) {return;} - const first_rune = self.line.text.buffer[self.symbol]; - if (first_rune == ' ') { - while(true) { - self.goToNextSymbol(); - if (self.symbol >= self.line.text.used) {break;} - const rune = self.line.text.buffer[self.symbol]; - if (rune != ' ') break; - } - } - else while(true) { - self.goToNextSymbol(); - if (self.symbol >= self.line.text.used) {break;} - const rune = self.line.text.buffer[self.symbol]; - switch(rune){ - ' ', '\t', '\\', - '=', '+', '-', '/', '*', '^', - '(', ')', '[', ']', '{', '}', - '!', '@', '#', '$', '%', '&', - '"', '\'', - ';', ':', '.', ',' - => {break;}, - else => {}, - } - } - prog.need_redraw = true; - } - - // over symbols - pub fn goToSymbol (self: *Self, pos: usize) void { - self.symbol = pos; - if (self.symbol > prog.console.size.x - 2) { - self.offset.x = prog.console.size.x - 2; - } - else {self.offset.x = self.symbol;} - } - pub fn goToPrevSymbol (self: *Self) void { - const used = self.line.text.used; - if (self.symbol == 0) { - if (true) return; - if (self.line.prev) |_| { - self.goToPrevLine(); - self.goToEndOfLine(); - } - return; - } - if (self.symbol > used) { - self.symbol = used; - if (used < prog.console.size.x - 1) self.offset.x = self.line.text.used; - prog.need_redraw = true; - return; - } - if (self.symbol > 0) self.symbol -= 1; - if (self.symbol >= 10) {if (self.offset.x > 10) {self.offset.x -= 1;}} - else {if (self.offset.x > 0) self.offset.x -= 1;} - prog.need_redraw = true; - } - pub fn goToNextSymbol (self: *Self) void { - const used = self.line.text.used; - if (self.symbol >= used) { - if (true) return; - if (self.line.next) |_| { - self.goToNextLine(); - self.goToStartOfLine(); - } - return; - } - if (self.symbol < Line.Text.size - 1) self.symbol += 1; - if (used - self.symbol >= 10) { - if (self.offset.x < prog.console.size.x - 12) self.offset.x += 1; - } - else { - if (self.offset.x < prog.console.size.x - 2) self.offset.x += 1; - } - prog.need_redraw = true; - } - - //} - // { folding - pub fn unFold (self: *Self) void { - if (self.foldMode == .flat) return; - - // add to chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - self.lines.pushLast(&line.link); - } - - // clear tree - self.tree = .{}; - var iter = self.lines.iter(); - while(iter.next()) |link| { - const line = Line.unlink(link); - line.tree = .{}; - } - - prog.need_redraw = true; - self.foldMode = .byNone; - } // end fn - pub fn foldFromBrackets (self: *Self) void { - self.unFold(); - - // add to tree - var iter = self.lines.iter(); - var current = iter.next() orelse return; - self.tree.addChild(current); - while(iter.next()) |link| { - const line = Line.unlink(link); - const close_count = line.text.getRunesCount('}'); // **{ - const open_count = line.text.getRunesCount('{'); // **} - - if (open_count == close_count) { - current.tree.pushNext(&line.tree); - } - else if (open_count > close_count) { - current.tree.pushChild(&line.tree); - } - else { // for close_count > open_count - var parent = current.tree.parent.?; - if (parent == &self.tree) parent = ¤t.tree; - parent.pushNext(&line.tree); - } - - current = line; - } - - // remove from chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - line.link = .{}; - } - self.lines = .{}; - - prog.need_redraw = true; - self.foldMode = .byBrackets; - } - pub fn foldFromIndent (self: *Self) !void { - self.unFold(); - - var iter = self.lines.iter(); - var current_link = iter.next() orelse return; - var current = Line.unlink(current_link); - var last_indent = current.text.countIndent(4); - self.tree.addChild(¤t.tree); - while(iter.next()) |link| { - const line = Line.unlink(link); - const indent = line.text.countIndent(4); - if (indent == last_indent) { - current.tree.pushNext(&line.tree); - } - else if (indent > last_indent) { - current.tree.pushChild(&line.tree); - } - else { // for last_indent > indent - // find parent with indent > indent - var parent = current.tree.parent.?; - while (true) { - if (parent == &self.tree) {parent = ¤t.tree; break;} - const parent_line = Line.untree(parent); - const parent_indent = parent_line.text.countIndent(4); - if (parent_indent > indent) break; - parent = current.tree.parent.?; - } - parent.pushChild(&line.tree); - } - - current = line; - last_indent = indent; - } - - // remove from chain - var walker = self.tree.walker(); - _ = walker.next(); // skip root; - while(walker.next()) |tree| { - const line = Line.untree(tree); - line.link = .{}; - } - self.lines = .{}; - - prog.need_redraw = true; - self.foldMode = .byIndent; - } - - pub fn goToIn (self: *Self) void { - if (self.fold_mode == .flat) return; - const child = self.line.child orelse return; - const child_indent = child.text.countIndent(1); - self.goToSymbol(child_indent); - self.symbol = child_indent; - self.line = child; - if (prog.console.size.y > 6) {self.offset.y = 6;} - else if (prog.console.size.y > 3) {self.offset.y = 3;} - else if (prog.console.size.y > 1) {self.offset.y = 1;} - else {self.offset.y = 0;} - self.bakup(); - if (self.symbol >= 4) self.offset.x = 4; - prog.need_redraw = true; - } - pub fn goToOut (self: *Self) void { - if (self.fold_mode == .flat) return; - if (self.line.getParent()) |parent| { - const parent_indent = parent.text.countIndent(1); - self.line = parent; - self.goToSymbol(parent_indent); - self.offset.y = 6; - if (self.symbol >= 4) self.offset.x = 4; - } - else { - self.goToRoot(); - } - self.bakup(); - prog.need_redraw = true; - } - //} - // { clipboard - pub fn externalCopy (self: *Self) !void { - prog.need_redraw = false; - // { create file - var cwd = std.fs.cwd(); - var file = try cwd.createFile(prog.path_to_clipboard.get(), .{}); - defer file.close(); - const writer = file.writer(); - // } - if (prog.buffer_lines.cutted) |cutted| { - // { working with lines - var current: *Line = cutted; - try writer.writeAll(current.text.get()); - copying: while (true) { - if (current.child) |child| { - try writer.writeAll("\n"); - try writer.writeAll(child.text.get()); - current = child; - } - else if (current.next) |next| { - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - next = current.next orelse continue; - break; - } - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - } - // } - { // change status - prog.need_redraw = false; - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.blue2); - try prog.console.out.writeAll("cutted lines saved to ~/clipboard.tmp"); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - } - else { - // { working with lines - const first = self.line; - try writer.writeAll(first.text.get()); - if (first.child) |first_child| { - var current: *Line = first_child; - try writer.writeAll("\n"); - try writer.writeAll(current.text.get()); - copying: while (true) { - if (current.child) |child| { - try writer.writeAll("\n"); - try writer.writeAll(child.text.get()); - current = child; - } - else if (current.next) |next| { - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - current = current.getParent() orelse break :copying; - if (current == first) break: copying; - next = current.next orelse continue; - break; - } - try writer.writeAll("\n"); - try writer.writeAll(next.text.get()); - current = next; - } - } - } - // } - { // change status - prog.need_redraw = false; - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.blue2); - try prog.console.writeAll("this block saved to ~/clipboard.tmp"); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - } - } - pub fn externalPaste (self: *Self) !void { - // read file - var file_data: []const u8 = undefined; - const loaded = lib.fileRead(prog.allocator, prog.path_to_clipboard.get()); - defer if (loaded) |data| {prog.allocator.free(data);} else |_| {}; - if (loaded) |data| {file_data = data;} else |err| { - { // change status - try prog.console.cursorMove(.{ .x = 0, .y = 0 }); - try ansi.do(ansi.reset); - try ansi.do(ansi.color.red2); - try prog.console.writeAll("file ~/clipboard.tmp not reedable."); - try ansi.do(ansi.clear_to_end_line); - try ansi.do(ansi.reset); - } - return err; - } - - // paste - const line = self.current_line; - try self.addPrevLine(); - for (file_data) |rune| { // parse lines - switch(rune) { - 10, 13 => {try self.addNextLine();}, - else => {try self.insertSymbol(rune);}, - } - } - self.line = line; - prog.need_redraw = true; - } - //} - // { bakup - pub fn bakup (self: *Self) void { - self.bakup_line.text.set(self.line.text.get()) catch {}; - } - pub fn restore (self: *Self) void { - self.line.text.set(self.bakup_line.text.get()) catch {}; - prog.need_redraw = true; - } - // } - // { indent - pub fn indentToCutie (self: *Self) void { - var current = self.line; - current.changeIndentToCutie() catch {}; - var first = current; - if (first.child) |first_child| { - current = first_child; - traversal: while (true) { - if (current.child) |child| { - current.changeIndentToCutie() catch {}; - current = child; - } - else if (current.next) |next| { - current.changeIndentToCutie() catch {}; - current = next; - } - else { - if (self.foldMode == .byBrackets) { - const parent = current.getParent() orelse break :traversal; - const indent = parent.text.countIndent(1); - current.text.changeIndent(indent) catch {}; - } - else { - current.changeIndentToCutie() catch {}; - } - while (true) { // find parent with next - current = current.getParent() orelse break :traversal; - if (current == first) break :traversal; - if (current.next) |next| { - current = next; - break; - } - } - } - } - } - prog.need_redraw = true; - } - pub fn deleteIndent (self: *Self) void { - var current = self.line; - current.text.changeIndent(0) catch {}; - var first = current; - if (first.child) |first_child| { - current = first_child; - traversal: while (true) { - if (current.child) |child| { - current.text.changeIndent(0) catch {}; - current = child; - } - else if (current.next) |next| { - current.text.changeIndent(0) catch {}; - current = next; - } - else { - current.text.changeIndent(0) catch {}; - while (true) { // find parent with next - current = current.getParent() orelse break :traversal; - if (current == first) break :traversal; - if (current.next) |next| { - current = next; - break; - } - } - } - } - } - prog.need_redraw = true; - } - // } - // { easy motion - pub fn draw_horizontal_help_motion (self: *Self) !void { - var pos: usize = 0; - var rune: u8 = 0x61; - try ansi.do(ansi.color.magenta); - while(true) { - try prog.console.cursorMove(.{ .x = pos, .y = self.offset.y }); - prog.console.writeByte(rune) catch unreachable; - if (rune >= 0x7A) break; rune += 1; - if (pos >= prog.console.size.x - 3) break; pos += 3; - } - try self.cursorMoveToCurrent(); - } - pub fn draw_vertical_help_motion (self: *Self) !void { - var pos: usize = 0; - try ansi.do(ansi.color.magenta); - while(true) { - try prog.console.cursorMove(.{ .x = self.offset.x, .y = pos }); - prog.console.writeByte(0x61 + @truncate(u8, pos)) catch unreachable; - if (pos >= 0x7A - 0x61) break; - if (pos == prog.console.size.y - 1) break; - pos += 1; - } - try self.cursorMoveToCurrent(); - } - pub fn easyMotionHorizontal (self: *Self, key: u8) !void { - var pos = key - 0x61; - self.goToSymbol(self.symbol - self.offset.x + pos * 3); - try self.changeMode(.edit); - prog.need_redraw = true; - } - pub fn easyMotionVertical (self: *Self, key: u8) !void { - var pos = key - 0x61; - if (self.offset.y == pos) {} - else if (self.offset.y > pos) { - var i = self.offset.y - pos; - while (i > 0) : (i -= 1) { - self.goToPrevLine(); - } - } - else { // (self.offset.y < pos) - var i = pos - self.offset.y; - while (i > 0) : (i -= 1) { - self.goToNextLine(); - } - } - try self.changeMode(.edit); - prog.need_redraw = true; - } - // } - - // being developed - pub fn drawRunes (self: *Self) !void { - try prog.console.cursorMove(.{.x = 0, .y = self.offset.y}); - defer self.cursorMoveToCurrent() catch {}; - - try ansi.do(ansi.color.red); - defer ansi.do(ansi.reset) catch {}; - - draw: { - var screen_pos_x: usize = 0; - var text_pos: usize = self.offset.x; // TODO skip first text_pos runes - const runes = self.current_line.runes orelse break: draw; - var link = &runes.link; - while(true) { - if (screen_pos_x >= prog.console.size.x - 3) break; - const rune = Rune.unlink(link); - try prog.console.writeAll(rune.glyph.getText()); - screen_pos_x += 1; - text_pos += 1; - link = link.next orelse break; - } - } - defer ansi.do(ansi.clear_to_end_line) catch {}; - - prog.need_redraw = false; - } - pub fn goToNextFlatLine (self: *Self) void { - const line_link = self.line.chain_link.next orelse return; - self.line = Line.unlink(line_link); - } - pub fn goToPrevFlatLine (self: *Self) void { - const line_link = self.line.chain_link.prev orelse return; - self.line = Line.unlink(line_link); - } - // { selection - // TODO - // } - // { find - pub fn findNext (self: *Self) void { - const text = self.line.text.get(); - var line = self.line; - if (line.text.find(text, self.symbol)) |pos| { // goto pos and return - self.line = line; - self.goToSymbol(pos); - return; - } - else { // iterate and find - while(true) { - // iterate - if (line.child) |child| { // goto child - line = child; - } - else if (line.next) |next| { // goto next - line = next; - } - else { // find parent with next - var next: *Line = undefined; - while (true) { - line = line.getParent() orelse return; - next = line.next orelse continue; - break; - } - line = next; - } - - // find - if (line.text.find(text, 0)) |pos| { // goto pos and return - self.line = line; - self.goToSymbol(pos); - return; - } - } - } - self.changeMode(.edit); - prog.need_clear = true; - prog.need_redraw = true; - self.bakup(); - } - // } -// } DELETED src/external/Console/build.zig Index: src/external/Console/build.zig ================================================================== --- src/external/Console/build.zig +++ /dev/null @@ -1,11 +0,0 @@ -const std = @import("std"); -pub fn build(b: *std.build.Builder) void { - var target = b.standardTargetOptions(.{}); - target.abi = .musl; - const mode = b.standardReleaseOptions(); - const exe = b.addExecutable("Console", "src/main.zig"); - exe.setTarget(target); - exe.setBuildMode(mode); - exe.linkLibC(); - exe.install(); -} DELETED src/external/Console/src/Cursor.zig Index: src/external/Console/src/Cursor.zig ================================================================== --- src/external/Console/src/Cursor.zig +++ /dev/null @@ -1,42 +0,0 @@ - -const G = @import("root"); -const T = @This(); - -pos: G.Coor2u = .{}, - -pub fn move (t: *T, new_pos: G.Coor2u) !void { - move_from_x: { - if (new_pos.x == t.pos.x) break :move_from_x; - if (new_pos.x > t.pos.x) { - try t.shiftRight(new_pos.x - t.pos.x); - } - else { - try t.shiftLeft(t.pos.x - new_pos.x); - } - } - move_from_y: { - if (new_pos.y == t.pos.y) break :move_from_y; - if (new_pos.y > t.pos.y) { - try t.shiftDown(new_pos.y - t.pos.y); - } - else { - try t.shiftUp(t.pos.y - new_pos.y); - } - } -} -pub fn shiftLeft (t: *T, pos: usize) !void { - try G.out.print(G.ansi.control ++ "{d}D",.{pos}); - t.pos.x -= pos; -} -pub fn shiftRight (t: *T, pos: usize) !void { - try G.out.print(G.ansi.control ++ "{d}C",.{pos}); - t.pos.x += pos; -} -pub fn shiftUp (t: *T, pos: usize) !void { - try G.out.print(G.ansi.control ++ "{d}A",.{pos}); - t.pos.y -= pos; -} -pub fn shiftDown (t: *T, pos: usize) !void { - try G.out.print(G.ansi.control ++ "{d}B",.{pos}); - t.pos.y += pos; -} DELETED src/external/Console/src/Flags.zig Index: src/external/Console/src/Flags.zig ================================================================== --- src/external/Console/src/Flags.zig +++ /dev/null @@ -1,116 +0,0 @@ -const G = @import("root"); -const T = @This(); -const c = @cImport({ - // canonical c - @cInclude("stdio.h"); - @cInclude("stdlib.h"); - - // linux - @cInclude("locale.h"); - @cInclude("fcntl.h"); - @cInclude("termios.h"); - @cInclude("sys/ioctl.h"); - @cInclude("sys/socket.h"); - @cInclude("unistd.h"); - @cInclude("signal.h"); -}); -const toggle = G.lib.toggleU32; - -termios: c.struct_termios = undefined, - -pub fn init () T { - var t: T = .{}; - _ = c.tcgetattr(0, &t.termios); - return t; -} -pub fn apply (t: *T) void { - _ = c.tcsetattr(0, c.TCSANOW, &t.termios); -} - -// false = disable -pub fn setFlowControl (t: *T, b: bool) void { - const iflag = &t.termios.c_iflag; - const lflag = &t.termios.c_lflag; - - toggle(iflag, c.IGNBRK, !b); // ignore break control - toggle(iflag, c.BRKINT, b); // do not delete all data after break control - toggle(iflag, c.IXON, b); // disable react to Ctrl+S Ctlr+Q - toggle(lflag, c.ISIG, b); // disable react to Ctrl+C -} -pub fn set8bit (t: *T, b: bool) void { - const cflag = &t.termios.c_cflag; - const iflag = &t.termios.c_iflag; - toggle(cflag, c.CS8, b); // use 8 bit - toggle(iflag, c.ISTRIP, !b); // strip - toggle(cflag, c.CSTOPB, !b); // two stops bits -} -pub fn setWait (t: *T, b: bool) void { - const lflag = &t.termios.c_lflag; - const c_cc = &t.termios.c_cc; - toggle(lflag, c.ICANON, b); // no wait '\n' - - // timers off - for (c_cc) |*conf| conf.* = 0; // clear c_cc - c_cc[c.VTIME] = 1; - c_cc[c.VMIN] = 0; -} -pub fn setAutoCR (t: *T, b: bool) void { - const oflag = &t.termios.c_oflag; - toggle(oflag, c.ONOCR, b); // on start line - toggle(oflag, c.ONLRET, b); // on end line -} -pub fn setChecking (t: *T, b: bool) void { - const cflag = &t.termios.c_cflag; - const iflag = &t.termios.c_iflag; - toggle(iflag, c.IGNPAR, !b); // ignore framing or parity errors - toggle(cflag, c.PARENB, b); // parity check - toggle(cflag, c.PARODD, b); // parity check -} -pub fn setEcho (t: *T, b: bool) void { - const lflag = &t.termios.c_lflag; - toggle(lflag, c.ECHO, b); // print pressed keys - toggle(lflag, c.ECHOE, b); // mashing - toggle(lflag, c.ECHOK, b); // nl after clear line - toggle(lflag, c.ECHOKE, b); // print NL after BS - toggle(lflag, c.ECHONL, b); // print NL - toggle(lflag, c.ECHOPRT, b); // print BS (BS SP BS) - toggle(lflag, c.IEXTEN, b); // special funcs -} -pub fn setBell (t: *T, b: bool) void { - const iflag = &t.termios.c_iflag; - toggle(iflag, c.IMAXBEL, b); // no bel -} -pub fn setConvertForInput (t: *T, b: bool) void { - const iflag = &t.termios.c_iflag; - toggle(iflag, c.INLCR, !b); // convert NL to CR - toggle(iflag, c.ICRNL, !b); // convert CR to NL - toggle(iflag, c.XCASE, !b); // convert register to UP - toggle(iflag, c.IUCLC, !b); // convert register to down - -} -pub fn setConvertForOutput (t: *T, b: bool) void { - const oflag = &t.termios.c_oflag; - toggle(oflag, c.OPOST, b); // \_(O_o)_/ - toggle(oflag, c.ONLCR, b); // NL to CR - toggle(oflag, c.OCRNL, b); // CR to NL - toggle(oflag, c.OLCUC, b); // --//-- - toggle(oflag, c.XTABS, b); // convert tab - toggle(oflag, c.TAB3, b); // convert tab -} -pub fn setNullForDeleted (t: *T, b: bool) void { - const oflag = &t.termios.c_oflag; - toggle(oflag, c.OFDEL, b); // use null for deleted symbol -} - -pub fn setCanonicalMode (t: *T, b: bool) void { - t.setFlowControl(b); - t.set8bit(b); - t.setWait(b); - t.setAutoCR(b); - t.setConvertForInput(b); - t.setConvertForOutput(b); - t.setChecking(b); - t.setEcho(b); - t.setBell(b); - t.setNullForDeleted(b); -} DELETED src/external/Console/src/Input.zig Index: src/external/Console/src/Input.zig ================================================================== --- src/external/Console/src/Input.zig +++ /dev/null @@ -1,72 +0,0 @@ -// { usage: - // just call update unreaded - // and use grab in loop for get keys -// } - - -const G = @import("root"); -const T = @This(); -const ansi = @import("external/ansi/src/ansi.zig"); - -pub const c = @cImport({ - @cInclude("stdio.h"); - @cInclude("sys/ioctl.h"); - @cInclude("unistd.h"); -}); - -pub const KeyTag = enum { - sequence, - byte, - ascii_key, -}; -pub const Key = union(KeyTag) { - sequence: ansi.Sequence, - byte: u8, - ascii_key: ansi.AsciiKey, -}; - -ungrabed: usize = 0, -unreaded: usize = 0, -buffer: [8]u8 = .{0}**8, -debug_buffer: [8]u8 = .{0}**8, -is_paste: bool = false, - -fn shift (t: *T, val: usize) void { - G.std.mem.copy(u8, t.debug_buffer[0..], t.debug_buffer[val..]); - G.std.mem.copy(u8, t.debug_buffer[8-val..], t.buffer [0..val]); - G.std.mem.copy(u8, t.buffer [0..], t.buffer [val..]); - t.ungrabed -= val; -} -pub fn updateUnreaded (t: *T) void { - var bytesWaiting: c_int = undefined; - _ = c.ioctl(0, c.FIONREAD, &bytesWaiting); - var count = @intCast(usize, bytesWaiting); - t.unreaded = count; - if (t.unreaded > 8) {t.is_paste = true;} - else {t.is_paste = false;} -} -pub fn grab (t: *T) ?Key { - while (t.ungrabed < 8 and t.unreaded > 0) { - _ = c.read(0, &t.buffer[t.ungrabed], 1); - t.ungrabed += 1; - t.unreaded -= 1; - } - if (t.ungrabed == 0) return null; - if (ansi.Sequence.Parser.fromDo(t.buffer[0..t.ungrabed])) |parser| { - t.shift(parser.used); - const key: Key = .{.sequence = parser.sequence}; - return key; - } - else if (t.buffer[0] > 127) { - const byte = t.buffer[0]; - t.shift(1); - const key: Key = .{.byte = byte}; - return key; - } - else { // return ascii - const ascii_key = @intToEnum(ansi.AsciiKey, t.buffer[0]); - t.shift(1); - const key: Key = .{.ascii_key = ascii_key}; - return key; - } -} DELETED src/external/Console/src/external/ansi/README.md Index: src/external/Console/src/external/ansi/README.md ================================================================== --- src/external/Console/src/external/ansi/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# ansi -this is just defined ansi codes DELETED src/external/Console/src/external/ansi/build.zig Index: src/external/Console/src/external/ansi/build.zig ================================================================== --- src/external/Console/src/external/ansi/build.zig +++ /dev/null @@ -1,34 +0,0 @@ -const std = @import("std"); - -pub fn build(b: *std.build.Builder) void { - // Standard target options allows the person running `zig build` to choose - // what target to build for. Here we do not override the defaults, which - // means any target is allowed, and the default is native. Other options - // for restricting supported target set are available. - const target = b.standardTargetOptions(.{}); - - // Standard release options allow the person running `zig build` to select - // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. - const mode = b.standardReleaseOptions(); - - const exe = b.addExecutable("ansi", "src/main.zig"); - exe.setTarget(target); - exe.setBuildMode(mode); - exe.install(); - - const run_cmd = exe.run(); - run_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - run_cmd.addArgs(args); - } - - const run_step = b.step("run", "Run the app"); - run_step.dependOn(&run_cmd.step); - - const exe_tests = b.addTest("src/main.zig"); - exe_tests.setTarget(target); - exe_tests.setBuildMode(mode); - - const test_step = b.step("test", "Run unit tests"); - test_step.dependOn(&exe_tests.step); -} DELETED src/external/Console/src/external/ansi/src/ansi.zig Index: src/external/Console/src/external/ansi/src/ansi.zig ================================================================== --- src/external/Console/src/external/ansi/src/ansi.zig +++ /dev/null @@ -1,655 +0,0 @@ -const Self = @This(); -const std = @import("std"); -const eql = std.mem.eql; -const out = std.io.getStdOut().writer(); - -pub const esc = "\x1B"; -pub const control = esc ++ "["; -pub const reset = control ++ "0m"; -pub const bold = control ++ "1m"; -pub const dim = control ++ "2m"; - -pub const clear_to_end_line = control ++ "0K"; -pub const clear_to_start_line = control ++ "1K"; -pub const clear_line = control ++ "2K"; - -pub const cyrsor_style = struct { - pub const hide = control ++ "?25l"; - pub const show = control ++ "?25h"; - pub const reset = control ++ "0 q"; - pub const blinking_block = control ++ "1 q"; - pub const steady_block = control ++ "2 q"; - pub const blinking_underline = control ++ "3 q"; - pub const steady_underline = control ++ "4 q"; - pub const blinking_I_beam = control ++ "5 q"; - pub const steady_I_beam = control ++ "6 q"; -}; -pub const color = struct { - pub const black = control ++ "30;1m"; - pub const red = control ++ "31;1m"; - pub const green = control ++ "32;1m"; - pub const yellow = control ++ "33;1m"; - pub const blue = control ++ "34;1m"; - pub const magenta = control ++ "35;1m"; - pub const cyan = control ++ "36;1m"; - pub const white = control ++ "37;1m"; - pub const zero = control ++ "39;1m"; - pub const black2 = control ++ "90;1m"; - pub const red2 = control ++ "91;1m"; - pub const green2 = control ++ "92;1m"; - pub const yellow2 = control ++ "93;1m"; - pub const blue2 = control ++ "94;1m"; - pub const magenta2 = control ++ "95;1m"; - pub const cyan2 = control ++ "96;1m"; - pub const white2 = control ++ "97;1m"; -}; -pub const bg_color = struct { - pub const black = control ++ "40;1m"; - pub const red = control ++ "41;1m"; - pub const green = control ++ "42;1m"; - pub const yellow = control ++ "43;1m"; - pub const blue = control ++ "44;1m"; - pub const magenta = control ++ "45;1m"; - pub const cyan = control ++ "46;1m"; - pub const white = control ++ "47;1m"; - pub const zero = control ++ "49;1m"; - pub const black2 = control ++ "100;1m"; - pub const red2 = control ++ "101;1m"; - pub const green2 = control ++ "102;1m"; - pub const yellow2 = control ++ "103;1m"; - pub const blue2 = control ++ "104;1m"; - pub const magenta2 = control ++ "105;1m"; - pub const cyan2 = control ++ "106;1m"; - pub const white2 = control ++ "107;1m"; -}; -pub const mouse = struct { - pub const grab = control ++ "?1000h"; - pub const release = control ++ "?1000l"; -}; - -pub const Ascii = enum(u7) { - // { specials - NUL, - start_of_heading, - star_of_text, - end_of_text, - end_of_transmission, - enquiry, - acknowledge, - bell, - back_space, - tab, - line_feed, - vertical_tab, - formFeed, - carriage_return, - shift_out, - shift_in, - data_link_escape, - device_control_1, - device_control_2, - device_control_3, - device_control_4, - negative_acknowledge, - synchrinius_idle, - end_of_trans_block, - cancel, - end_of_medium, - substitute, - escape, - file_separator, - group_separetor, - record_separator, - unit_separator, - //} - // { signs - space, // ' ' - exclamation, // '!' - double_cuotes, // '"' - number_sign, // '#' - dollar_sign, // '$' - percent_sign, // '%' - ampersand, // '&' - apostrophe, // '\'' - round_bracket_open, - round_bracket_close, - asterisk, // '*' - plus_sign, // '+' - comma, // ',' - minus_sign, // '-' - dot, // '.' - slash, // '/' - // } - // { numbers - code_0, - code_1, - code_2, - code_3, - code_4, - code_5, - code_6, - code_7, - code_8, - code_9, - // } - // { signs2 - colon, // ':' - semi_colon, // ';' - less_sign, // '<' - equals_sign, // '=' - greater_sign, // '>' - question_mark, // '?' - at, // '@' - // } - // { capitals - code_A, - code_B, - code_C, - code_D, - code_E, - code_F, - code_G, - code_H, - code_I, - code_J, - code_K, - code_L, - code_M, - code_N, - code_O, - code_P, - code_Q, - code_R, - code_S, - code_T, - code_U, - code_V, - code_W, - code_X, - code_Y, - code_Z, - //} - // { signs 3 - open_bracket, // '[' - back_slash, // '\\' - close_bracket, // ']' - caret, // '^' - under_score, // '_' - grave_accent, // '`' - // } - // { non_capitals - code_a, - code_b, - code_c, - code_d, - code_e, - code_f, - code_g, - code_h, - code_i, - code_j, - code_k, - code_l, - code_m, - code_n, - code_o, - code_p, - code_q, - code_r, - code_s, - code_t, - code_u, - code_v, - code_w, - code_x, - code_y, - code_z, - //} - // { signs 4 - open_figure_bracket, - vertical_bar, - close_figure_bracket, - tilda, - delete, - // } -}; -pub const AsciiKey = enum(u7) { - // { specials - NUL, - ctrl_a, // start_of_heading, - ctrl_b, // star_of_text, - ctrl_c, // end_of_text, - ctrl_d, // end_of_transmission, - ctrl_e, // enquiry, - ctrl_f, // acknowledge, - ctrl_g, // bell, - ctrl_bs, // ctrl backspace, - tab, // horizontal_tab, - enter, // line_feed, - ctrl_k, // vertical_tab, - ctrl_l, // formFeed, - ctrl_j, // carriage_return, o_O - ctrl_n, // shift_out, - ctrl_o, // shift_in, - ctrl_p, // data_link_escape, - ctrl_q, // device_control_1, - ctrl_r, // device_control_2, - ctrl_s, // device_control_3, - ctrl_t, // device_control_4, - ctrl_u, // negative_acknowledge, - ctrl_v, // synchrinius_idle, - ctrl_w, // end_of_trans_block, - ctrl_x, // cancel, - ctrl_y, // end_of_medium, - ctrl_z, // substitute, - escape, - file_separator, - group_separetor, - record_separator, - unit_separator, - //} - // { signs - space, // ' ' - exclamation, // '!' - double_cuotes, // '"' - number_sign, // '#' - dollar_sign, // '$' - percent_sign, // '%' - ampersand, // '&' - apostrophe, // '\'' - round_bracket_open, - round_bracket_close, - asterisk, // '*' - plus_sign, // '+' - comma, // ',' - minus_sign, // '-' - dot, // '.' - slash, // '/' - // } - // { numbers - code_0, - code_1, - code_2, - code_3, - code_4, - code_5, - code_6, - code_7, - code_8, - code_9, - // } - // { signs2 - colon, // ':' - semi_colon, // ';' - less_sign, // '<' - equals_sign, // '=' - greater_sign, // '>' - question_mark, // '?' - at, // '@' - // } - // { capitals - code_A, - code_B, - code_C, - code_D, - code_E, - code_F, - code_G, - code_H, - code_I, - code_J, - code_K, - code_L, - code_M, - code_N, - code_O, - code_P, - code_Q, - code_R, - code_S, - code_T, - code_U, - code_V, - code_W, - code_X, - code_Y, - code_Z, - //} - // { signs 3 - open_bracket, // '[' - back_slash, // '\\' - close_bracket, // ']' - caret, // '^' - under_score, // '_' - grave_accent, // '`' - // } - // { non_capitals - code_a, - code_b, - code_c, - code_d, - code_e, - code_f, - code_g, - code_h, - code_i, - code_j, - code_k, - code_l, - code_m, - code_n, - code_o, - code_p, - code_q, - code_r, - code_s, - code_t, - code_u, - code_v, - code_w, - code_x, - code_y, - code_z, - //} - // { signs 4 - open_figure_bracket, - vertical_bar, - close_figure_bracket, - tilda, - back_space, // delete, - // } -}; -pub const Sequence = enum(u64) { - // { enum - mouse, - - f1_rxvt, - f2_rxvt, - f1_tty, - f2_tty, - - f1, - f2, - f3, - f4, - f5, - f6, - f7, - f8, - f9, - f10, - f11, - f12, - - delete, - left, - right, - up, - down, - end, - home, - ctrl_alt_v, - shift_delete, - - // left - ctrl_left, - ctrl_left_rxvt, - ctrl_shift_left, - shift_left, - alt_left, - - // right - ctrl_right, - ctrl_right_rxvt, - ctrl_shift_right, - shift_right, - alt_right, - - // up - ctrl_up, - shift_up, - alt_up, - - // down - ctrl_down, - shift_down, - alt_down, - - alt_v, - alt_m, - alt_M, - alt_n, - alt_j, - alt_p, - alt_r, - alt_o, - // } - pub const Parser = struct { - sequence: Sequence = null, - used: usize = 0, - pub fn fromDo(buffer: []u8) ?Parser { - // return null or sequence - var parser: ?Parser = null; - if (buffer.len >= 6) { - if (false) {} - else if (eql(u8, buffer[0..3], "\x1B\x5B\x4D")) { // mouse - parser = .{.sequence = .mouse, .used = 6}; - return parser; - } - else if (eql(u8, buffer[0..6], "\x1B\x5B\x31\x3B\x36\x44")) { // ctrl_shift_left - parser = .{.sequence = .ctrl_shift_left, .used = 6}; - return parser; - } - else if (eql(u8, buffer[0..6], "\x1B\x5B\x31\x3B\x35\x44")) { // ctrl_left - parser = .{.sequence = .ctrl_left, .used = 6}; - return parser; - } - else if (eql(u8, buffer[0..6], "\x1B\x5B\x31\x3B\x35\x43")) { // ctrl_right - parser = .{.sequence = .ctrl_right, .used = 6}; - return parser; - } - else if (eql(u8, buffer[0..6], "\x1B\x5B\x31\x3B\x35\x41")) { // ctrl_up - parser = .{.sequence = .ctrl_up, .used = 6}; - return parser; - } - else if (eql(u8, buffer[0..6], "\x1B\x5B\x31\x3B\x35\x42")) { // ctrl_down - parser = .{.sequence = .ctrl_down, .used = 6}; - return parser; - } - else if (eql(u8, buffer[0..6], "\x1B\x5B\x33\x3B\x32\x7E")) { // shift_delete - parser = .{.sequence = .shift_delete, .used = 6}; - return parser; - } - else if (eql(u8, buffer[0..6], "\x1B\x5B\x31\x3B\x32\x41")) { // shift_up - parser = .{.sequence = .shift_up, .used = 6}; - return parser; - } - else if (eql(u8, buffer[0..6], "\x1B\x5B\x31\x3B\x32\x42")) { // shift_down - parser = .{.sequence = .shift_down, .used = 6}; - return parser; - } - else if (eql(u8, buffer[0..6], "\x1B\x5B\x31\x3B\x32\x44")) { // shift_left - parser = .{.sequence = .shift_left, .used = 6}; - return parser; - } - else if (eql(u8, buffer[0..6], "\x1B\x5B\x31\x3B\x32\x43")) { // shift_right - parser = .{.sequence = .shift_right, .used = 6}; - return parser; - } - else if (eql(u8, buffer[0..6], "\x1B\x5B\x31\x3B\x33\x44")) { // alt_left - parser = .{.sequence = .alt_left, .used = 6}; - return parser; - } - else if (eql(u8, buffer[0..6], "\x1B\x5B\x31\x3B\x33\x43")) { // alt_right - parser = .{.sequence = .alt_right, .used = 6}; - return parser; - } - else if (eql(u8, buffer[0..6], "\x1B\x5B\x31\x3B\x33\x41")) { // alt_up - parser = .{.sequence = .alt_up, .used = 6}; - return parser; - } - else if (eql(u8, buffer[0..6], "\x1B\x5B\x31\x3B\x33\x42")) { // alt_down - parser = .{.sequence = .alt_down, .used = 6}; - return parser; - } - else if (eql(u8, buffer[0..6], "\x1B\x5B\x31\x3B\x36\x43")) { // ctrl_shift_right - parser = .{.sequence = .ctrl_shift_right, .used = 6}; - return parser; - } - } - if (buffer.len >= 5) { - if (false) {} - else if (eql(u8, buffer[0..5], "\x1B\x5B\x31\x31\x7E")) { // f1_rxvt - parser = .{.sequence = .f1_rxvt, .used = 5}; - return parser; - } - else if (eql(u8, buffer[0..5], "\x1B\x5B\x31\x32\x7E")) { // f2_rxvt - parser = .{.sequence = .f2_rxvt, .used = 5}; - return parser; - } - else if (eql(u8, buffer[0..5], "\x1B\x5B\x31\x35\x7E")) { // f5 - parser = .{.sequence = .f5, .used = 5}; - return parser; - } - else if (eql(u8, buffer[0..5], "\x1B\x5B\x31\x37\x7E")) { // f6 - parser = .{.sequence = .f6, .used = 5}; - return parser; - } - else if (eql(u8, buffer[0..5], "\x1B\x5B\x31\x38\x7E")) { // f7 - parser = .{.sequence = .f7, .used = 5}; - return parser; - } - else if (eql(u8, buffer[0..5], "\x1B\x5B\x31\x39\x7E")) { // f8 - parser = .{.sequence = .f8, .used = 5}; - return parser; - } - else if (eql(u8, buffer[0..5], "\x1B\x5B\x32\x30\x7E")) { // f9 - parser = .{.sequence = .f9, .used = 5}; - return parser; - } - else if (eql(u8, buffer[0..5], "\x1B\x5B\x32\x31\x7E")) { // f10 - parser = .{.sequence = .f10, .used = 5}; - return parser; - } - else if (eql(u8, buffer[0..5], "\x1B\x5B\x32\x33\x7E")) { // f11 - parser = .{.sequence = .f11, .used = 5}; - return parser; - } - else if (eql(u8, buffer[0..5], "\x1B\x5B\x32\x34\x7E")) { // f12 - parser = .{.sequence = .f12, .used = 5}; - return parser; - } - } - if (buffer.len >= 4) { - if(false) {} - else if (eql(u8, buffer[0..4], "\x1B\x5B\x5B\x41")) { // f1_tty - parser = .{.sequence = .f1_tty, .used = 4}; - return parser; - } - else if (eql(u8, buffer[0..4], "\x1B\x5B\x5B\x42")) { // f2_tty - parser = .{.sequence = .f2_tty, .used = 4}; - return parser; - } - else if (eql(u8, buffer[0..4], "\x1B\x5B\x33\x7E")) { // del - parser = .{.sequence = .delete, .used = 4}; - return parser; - } - } - if (buffer.len >= 3) { - if (false) {} - else if (eql(u8, buffer[0..3], "\x1B\x4F\x50")) { // f1 - parser = .{.sequence = .f1, .used = 3}; - return parser; - } - else if (eql(u8, buffer[0..3], "\x1B\x4F\x51")) { // f2 - parser = .{.sequence = .f2, .used = 3}; - return parser; - } - else if (eql(u8, buffer[0..3], "\x1B\x4F\x52")) { // f3 - parser = .{.sequence = .f3, .used = 3}; - return parser; - } - else if (eql(u8, buffer[0..3], "\x1B\x4F\x53")) { // f4 - parser = .{.sequence = .f4, .used = 3}; - return parser; - } - else if (eql(u8, buffer[0..3], "\x1B\x4F\x64")) { // ctrl_left_rxvt - parser = .{.sequence = .ctrl_left_rxvt, .used = 3}; - return parser; - } - else if (eql(u8, buffer[0..3], "\x1B\x4F\x63")) { // ctrl_right_rxvt - parser = .{.sequence = .ctrl_right_rxvt, .used = 3}; - return parser; - } - else if (eql(u8, buffer[0..3], "\x1B\x5B\x44")) { // left - parser = .{.sequence = .left, .used = 3}; - return parser; - } - else if (eql(u8, buffer[0..3], "\x1B\x5B\x43")) { // right - parser = .{.sequence = .right, .used = 3}; - return parser; - } - else if (eql(u8, buffer[0..3], "\x1B\x5B\x41")) { // up - parser = .{.sequence = .up, .used = 3}; - return parser; - } - else if (eql(u8, buffer[0..3], "\x1B\x5B\x42")) { // down - parser = .{.sequence = .down, .used = 3}; - return parser; - } - else if (eql(u8, buffer[0..3], "\x1B\x5B\x46")) { // end - parser = .{.sequence = .end, .used = 3}; - return parser; - } - else if (eql(u8, buffer[0..3], "\x1B\x5B\x48")) { // home - parser = .{.sequence = .home, .used = 3}; - return parser; - } - } - if (buffer.len >= 2) { - if (false) {} - else if (eql(u8, buffer[0..2], "\x1B\x6A")) { // alt_j - parser = .{.sequence = .alt_j, .used = 2}; - return parser; - } - else if (eql(u8, buffer[0..2], "\x1B\x70")) { // alt_p - parser = .{.sequence = .alt_p, .used = 2}; - return parser; - } - else if (eql(u8, buffer[0..2], "\x1B\x76")) { // alt_v - parser = .{.sequence = .alt_v, .used = 2}; - return parser; - } - else if (eql(u8, buffer[0..2], "\x1B\x6D")) { // alt_m - parser = .{.sequence = .alt_m, .used = 2}; - return parser; - } - else if (eql(u8, buffer[0..2], "\x1B\x4D")) { // alt_M - parser = .{.sequence = .alt_M, .used = 2}; - return parser; - } - else if (eql(u8, buffer[0..2], "\x1B\x6E")) { // alt_n - parser = .{.sequence = .alt_n, .used = 2}; - return parser; - } - else if (eql(u8, buffer[0..2], "\x1B\x72")) { // alt_r - parser = .{.sequence = .alt_r, .used = 2}; - return parser; - } - else if (eql(u8, buffer[0..2], "\x1B\x6F")) { // alt_o - parser = .{.sequence = .alt_o, .used = 2}; - return parser; - } - else if (eql(u8, buffer[0..2], "\x1B\x16")) { // ctrl_alt_v - parser = .{.sequence = .ctrl_alt_v, .used = 2}; - return parser; - } - } - return parser; - } - }; -}; - -pub fn do (command: []const u8) !void { - try out.writeAll(command); -} DELETED src/external/Console/src/external/ansi/src/main.zig Index: src/external/Console/src/external/ansi/src/main.zig ================================================================== --- src/external/Console/src/external/ansi/src/main.zig +++ /dev/null @@ -1,33 +0,0 @@ -const std = @import("std"); -const out = std.io.getStdOut().writer(); -const ansi = @import("ansi.zig"); - -pub fn main() anyerror!void { - try out.print("Test color: {s} *** {s}\r\n", .{ansi.color.black, ansi.reset}); - try out.print("Test color: {s} *** {s}\r\n", .{ansi.color.red, ansi.reset}); - try out.print("Test color: {s} *** {s}\r\n", .{ansi.color.green, ansi.reset}); - try out.print("Test color: {s} *** {s}\r\n", .{ansi.color.yellow, ansi.reset}); - try out.print("Test color: {s} *** {s}\r\n", .{ansi.color.magenta, ansi.reset}); - try out.print("Test color: {s} *** {s}\r\n", .{ansi.color.blue, ansi.reset}); - try out.print("Test color: {s} *** {s}\r\n", .{ansi.color.cyan, ansi.reset}); - try out.print("Test color: {s} *** {s}\r\n", .{ansi.color.white, ansi.reset}); - try out.print("Test color: {s} *** {s}\r\n", .{ansi.color.zero, ansi.reset}); - try out.print("Test color: {s} *** {s}\r\n", .{ansi.color.black2, ansi.reset}); - try out.print("Test color: {s} *** {s}\r\n", .{ansi.color.red2, ansi.reset}); - try out.print("Test color: {s} *** {s}\r\n", .{ansi.color.green2, ansi.reset}); - try out.print("Test color: {s} *** {s}\r\n", .{ansi.color.yellow2, ansi.reset}); - try out.print("Test color: {s} *** {s}\r\n", .{ansi.color.blue2, ansi.reset}); - try out.print("Test color: {s} *** {s}\r\n", .{ansi.color.magenta2, ansi.reset}); - try out.print("Test color: {s} *** {s}\r\n", .{ansi.color.cyan2, ansi.reset}); - try out.print("Test color: {s} *** {s}\r\n", .{ansi.color.white2, ansi.reset}); - - try out.writeAll("\r\n"); - try out.print("Test color: {s} *** {s} {s}deleted line\r\n", .{ansi.color.green, ansi.reset, ansi.clear_line}); - try out.print("Test color: {s} *** {s} {s}\rdeleted line 2\r\n", .{ansi.color.magenta, ansi.reset, ansi.clear_line}); - - try out.writeAll("do test:"); - try ansi.do(ansi.color.red); - try out.writeAll("***"); - try ansi.do(ansi.reset); - try out.writeAll("\r\n"); -} DELETED src/external/Console/src/external/lib/build.zig Index: src/external/Console/src/external/lib/build.zig ================================================================== --- src/external/Console/src/external/lib/build.zig +++ /dev/null @@ -1,34 +0,0 @@ -const std = @import("std"); - -pub fn build(b: *std.build.Builder) void { - // Standard target options allows the person running `zig build` to choose - // what target to build for. Here we do not override the defaults, which - // means any target is allowed, and the default is native. Other options - // for restricting supported target set are available. - const target = b.standardTargetOptions(.{}); - - // Standard release options allow the person running `zig build` to select - // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. - const mode = b.standardReleaseOptions(); - - const exe = b.addExecutable("lib", "src/main.zig"); - exe.setTarget(target); - exe.setBuildMode(mode); - exe.install(); - - const run_cmd = exe.run(); - run_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - run_cmd.addArgs(args); - } - - const run_step = b.step("run", "Run the app"); - run_step.dependOn(&run_cmd.step); - - const exe_tests = b.addTest("src/main.zig"); - exe_tests.setTarget(target); - exe_tests.setBuildMode(mode); - - const test_step = b.step("test", "Run unit tests"); - test_step.dependOn(&exe_tests.step); -} DELETED src/external/Console/src/external/lib/src/lib.zig Index: src/external/Console/src/external/lib/src/lib.zig ================================================================== --- src/external/Console/src/external/lib/src/lib.zig +++ /dev/null @@ -1,81 +0,0 @@ -const std = @import("std"); -pub const c = @cImport({ - // canonical c - @cInclude("stdio.h"); - @cInclude("stdlib.h"); - - // linux - @cInclude("locale.h"); - @cInclude("fcntl.h"); - @cInclude("termios.h"); - @cInclude("sys/ioctl.h"); - @cInclude("sys/socket.h"); - @cInclude("unistd.h"); - @cInclude("signal.h"); -}); -pub const Coor2u = struct { - x: usize = 0, - y: usize = 0, - - pub fn isNotSmaller (self: *Coor2u, target: *Coor2u) bool { - if (self.x < target.x) return false; - if (self.y < target.y) return false; - return true; - } - pub fn isBigger (self: *Coor2u, target: *Coor2u) bool { - if (self.x > target.x) return true; - if (self.y > target.y) return true; - return false; - } -}; -pub const Range = struct { - start: usize = 0, - end: usize = 0, -}; - -const do_not_compile_todo = false; -pub fn todo () void { - if (do_not_compile_todo) @compileError("TODO: implement me"); - if (std.builtin.mode == .Debug) {std.log.warn("todo this.", .{});} -} - -// bool -pub fn toggleU32 (ptr: *u32, flag: u32, state: bool) void { - switch(state) { - true => ptr.* |= flag, - false => ptr.* &= ~flag, - } -} - -// console -pub fn printRune (rune: u8) void { - _ = c.fputc(rune, c.stdout); - _ = c.fflush(c.stdout); -} -pub fn print (text: []const u8) void { - for (text) |ch| { - printRune(ch); - } -} - -// file -pub fn fileRead (allocator: std.mem.Allocator, name: []const u8) ![]const u8 { - var cwd = std.fs.cwd(); - var file = try cwd.openFile(name, .{.mode = .read_only}); - defer file.close(); - const size = try file.getEndPos(); - if (size == 0) return error.FileIsEmpty; - if (size > std.math.maxInt(usize)) return error.FileSizeIsBiggerThatRam; - const truncate_size = @truncate(usize, size); - const buffer = try allocator.alloc(u8, truncate_size); - const readed = try file.readAll(buffer); - if (readed < size) unreachable; - return buffer[0..]; -} -pub fn fileSave (data: []const u8, name: []const u8) !void { - var cwd = std.fs.cwd(); - var file = try cwd.createFile(name, .{}); - defer file.close(); - const writer = file.writer(); - try writer.writeAll(data); -} DELETED src/external/Console/src/external/lib/src/main.zig Index: src/external/Console/src/external/lib/src/main.zig ================================================================== --- src/external/Console/src/external/lib/src/main.zig +++ /dev/null @@ -1,19 +0,0 @@ -const std = @import("std"); -const lib = @import("lib.zig"); - -pub fn main() anyerror!void { - // read data example: - var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena.deinit(); - const allocator = arena.allocator(); - - var file_data: []const u8 = undefined; - const loaded = lib.fileRead(allocator, "src/main.zig"); - defer if (loaded) |data| {allocator.free(data);} else |_| {}; - if (loaded) |data| {file_data = data;} - else |err| { - std.log.info("error = {}", .{err}); - return; - } - std.log.info("\n{s}", .{file_data}); -} DELETED src/external/Console/src/lib Index: src/external/Console/src/lib ================================================================== --- src/external/Console/src/lib +++ /dev/null @@ -1,194 +0,0 @@ -const G = @import("root"); -const T = @This(); - -//TODO: replace this: -const asBytes = G.std.mem.asBytes; -const lib = G.lib; - -pub const ansi = @import("external/ansi/src/ansi.zig"); -pub const Cursor = @import("Cursor.zig"); -pub const Input = @import("Input.zig"); // TODO use std.io.getStdin().reader() unbuffered; -pub const Flags = @import("Flags.zig"); - -const c = @cImport({ - // canonical c - @cInclude("stdio.h"); - @cInclude("stdlib.h"); - - // linux - @cInclude("locale.h"); - @cInclude("fcntl.h"); - @cInclude("termios.h"); - @cInclude("sys/ioctl.h"); - @cInclude("sys/socket.h"); - @cInclude("unistd.h"); - @cInclude("signal.h"); -}); - -pub const WriteError = anyerror || error { - CursorOverflow, -}; -const Writer = G.std.io.Writer(*T, WriteError, write); - -// { fields - // output - out: Writer = undefined, - cursor: Cursor = .{}, - bg_color: []const u8 = undefined, - color: []const u8 = undefined, - size: G.Coor2u = .{ .x = 1, .y = 1 }, - - // input - input: Input = .{}, -// } -// { methods - pub fn init (t: *T) !void { - t.out = t.writer(); - try ansi.do(ansi.reset); - try t.changeColor(ansi.color.white); - try t.changeBgColor(ansi.bg_color.black); - try ansi.do(ansi.cyrsor_style.blinking_I_beam); // change cursour type - - try t.updateSize(); - try t.initBlankLines(); - try t.clear(); - try t.cursorMove(.{.x = 0, .y = 0}); - } - pub fn deInit (t: *T) !void { - _ = t; - ansi.do(ansi.bg_color.zero) catch {}; - ansi.do(ansi.reset) catch {}; - G.out.writeAll("\r\n") catch {}; - //try ansi.do(ansi.mouse.release); - } - pub fn updateSize (t: *T) !void { - var w: c.winsize = undefined; - _ = c.ioctl(c.STDOUT_FILENO, c.TIOCGWINSZ, &w); - - if (w.ws_col >= 6) {t.size.x = w.ws_col - 3;} - else t.size.x = w.ws_col; - - if (w.ws_col >= 6) {t.size.y = w.ws_row - 3;} - else t.size.y = w.ws_row; - } - pub fn changeColor (t: *T, color: []const u8) !void { - t.color = color; - try ansi.do(t.color); - } - pub fn changeBgColor (t: *T, bg_color: []const u8) !void { - t.bg_color = bg_color; - try ansi.do(t.bg_color); - } - pub fn initBlankLines (t: *T) !void { - try G.out.writeAll("\r\n"); - try t.cursorMove(.{.x = 0, .y = 0}); - var pos_y: usize = 0; - while (pos_y < t.size.y) { - try G.out.writeAll("\n"); - pos_y += 1; - t.cursor.pos.y += 1; - } // end while - } // end fn clear - - // cursor - pub fn cursorMove (t: *T, pos: G.Coor2u) !void { // cursor teleport - if (pos.x > t.size.x) unreachable; - if (pos.y > t.size.y) unreachable; - try t.cursor.move(pos); - } - pub fn lf (t: *T) !void { // line feed (go to next line) - if (t.cursor.pos.y < t.size.y) { - try t.cursor.move(.{.x = t.cursor.pos.x, .y = t.cursor.pos.y + 1}); - } - else { - try G.out.writeAll("\n"); - } - } - pub fn cr (t: *T) !void { // carret return (to start of line) - try t.cursor.move(.{.x = 0, .y = t.cursor.pos.y}); - } - pub fn rn (t: *T) !void { // \r\n - try t.lf(); - try t.cr(); - } - - // write - pub fn write (t: *T, text: []const u8) WriteError!usize { - if (t.cursor.pos.x > t.size.x) return error.CursorOverflow; - if (t.cursor.pos.y > t.size.y) return error.CursorOverflow; - const space = t.size.x - 1 - t.cursor.pos.x; - const len = if (text.len > space) space else text.len; - for (text[0..len]) |byte| { - switch (byte) { - 10 => { - const last_color = t.color; - const last_bg_color = t.bg_color; - try t.changeColor(ansi.color.blue); - try t.changeBgColor(ansi.bg_color.blue); - try G.out.writeAll(" "); - try t.changeColor(last_color); - try t.changeBgColor(last_bg_color); - }, - 13 => { - const last_color = t.color; - const last_bg_color = t.bg_color; - try t.changeColor(ansi.color.green); - try t.changeBgColor(ansi.bg_color.blue); - try G.out.writeAll(" "); - try t.changeColor(last_color); - try t.changeBgColor(last_bg_color); - }, - 27 => { - const last_color = t.color; - const last_bg_color = t.bg_color; - try t.changeColor(ansi.color.red); - try t.changeBgColor(ansi.bg_color.blue); - try G.out.writeAll(" "); - try t.changeColor(last_color); - try t.changeBgColor(last_bg_color); - }, - 0...9, - 11...12, - 14...26, - 28...31 - => { - const last_color = t.color; - const last_bg_color = t.bg_color; - try t.changeColor(ansi.color.yellow); - try t.changeBgColor(ansi.bg_color.yellow); - try G.out.writeAll(" "); - try t.changeColor(last_color); - try t.changeBgColor(last_bg_color); - }, - 127...255 - => { - const last_color = t.color; - const last_bg_color = t.bg_color; - try t.changeColor(ansi.color.yellow); - try t.changeBgColor(ansi.bg_color.green); - try G.out.writeAll(" "); - try t.changeColor(last_color); - try t.changeBgColor(last_bg_color); - }, - else => { - try G.out.writeByte(byte); - }, - } - } - t.cursor.pos.x += len; - return len; - } - pub fn writer (t: *T) Writer { - return .{.context = t}; - } - pub fn clear (t: *T) !void { - try ansi.do(ansi.cyrsor_style.hide); - defer {ansi.do(ansi.cyrsor_style.show) catch {};} - var pos_y: usize = 0; - while (pos_y < t.size.y) { - try t.cursorMove(.{.x = 0, .y = pos_y}); - try ansi.do(ansi.clear_line); - pos_y += 1; - } // end while - } // end fn clear -// } DELETED src/external/Console/src/main.zig Index: src/external/Console/src/main.zig ================================================================== --- src/external/Console/src/main.zig +++ /dev/null @@ -1,55 +0,0 @@ - -const G = @import("root"); -const T = @This(); - -pub const std = @import("std"); -pub const out = std.io.getStdOut().writer(); - -pub const Console = @import("Console.zig"); -pub const lib = @import("external/lib/src/lib.zig"); -pub const ansi = @import("external/ansi/src/ansi.zig"); - -pub const Coor2u = lib.Coor2u; -pub const Flags = Console.Flags; - -var console: Console = .{}; - -pub fn main () !void { - try console.init(); - defer {console.deInit() catch {};} - - var system_flags = Flags.init(); - defer system_flags.apply(); - - var flags = Flags.init(); - flags.setCanonicalMode(false); - flags.apply(); - - // test prints - try console.out.writeAll("out write func"); - try console.rn(); - - try console.changeColor(G.ansi.color.blue); - try console.out.writeAll("Blue text"); - try console.rn(); - try console.changeColor(G.ansi.color.red); - try console.out.writeAll("red text"); - try console.rn(); - try console.changeColor(G.ansi.reset); - - try console.out.print("Out print func. {s}",.{"ok."}); - try console.rn(); - - // test clear screen - try console.rn(); - std.time.sleep(std.time.ns_per_s * 2); - try console.updateSize(); - try console.clear(); - - // print pressed keys - console.input.updateUnreaded(); - while (console.input.grab()) |key| { - try console.out.print("{d}",.{key}); - try console.rn(); - } -} // end fn main DELETED src/external/Coor2u.zig Index: src/external/Coor2u.zig ================================================================== --- src/external/Coor2u.zig +++ /dev/null @@ -1,20 +0,0 @@ - - -const G = @import("root"); -const T = @This(); - -x: usize = 0, -y: usize = 0, - -pub const Range = struct { - from: T, - to: T, -}; - -pub fn isInRange(t: *const T, range: *const Range) bool { - if(t.x < range.from.x) return false; - if(t.x > range.to.x) return false; - if(t.y < range.from.y) return false; - if(t.y > range.to.y) return false; - return true; -} DELETED src/external/LinkedList/build.zig Index: src/external/LinkedList/build.zig ================================================================== --- src/external/LinkedList/build.zig +++ /dev/null @@ -1,34 +0,0 @@ -const std = @import("std"); - -pub fn build(b: *std.build.Builder) void { - // Standard target options allows the person running `zig build` to choose - // what target to build for. Here we do not override the defaults, which - // means any target is allowed, and the default is native. Other options - // for restricting supported target set are available. - const target = b.standardTargetOptions(.{}); - - // Standard release options allow the person running `zig build` to select - // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. - const mode = b.standardReleaseOptions(); - - const exe = b.addExecutable("ChainedList", "src/main.zig"); - exe.setTarget(target); - exe.setBuildMode(mode); - exe.install(); - - const run_cmd = exe.run(); - run_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - run_cmd.addArgs(args); - } - - const run_step = b.step("run", "Run the app"); - run_step.dependOn(&run_cmd.step); - - const exe_tests = b.addTest("src/main.zig"); - exe_tests.setTarget(target); - exe_tests.setBuildMode(mode); - - const test_step = b.step("test", "Run unit tests"); - test_step.dependOn(&exe_tests.step); -} DELETED src/external/LinkedList/src/Iterator.zig Index: src/external/LinkedList/src/Iterator.zig ================================================================== --- src/external/LinkedList/src/Iterator.zig +++ /dev/null @@ -1,9 +0,0 @@ -const T = @This(); -const G = @import("root"); - -_next: ?*G.LinkedList.Link, -pub fn next(t: *T) ?*G.LinkedList.Link { - const link = t._next orelse return null; - t._next = link.next; - return link; -} DELETED src/external/LinkedList/src/IteratorReversed.zig Index: src/external/LinkedList/src/IteratorReversed.zig ================================================================== --- src/external/LinkedList/src/IteratorReversed.zig +++ /dev/null @@ -1,9 +0,0 @@ -const T = @This(); -const G = @import("root"); - -_prev: ?*G.LinkedList.Link, -pub fn next(t: *T) ?*G.LinkedList.Link { - const link = t._prev orelse return null; - t._prev = link.prev; - return link; -} DELETED src/external/LinkedList/src/Link.zig Index: src/external/LinkedList/src/Link.zig ================================================================== --- src/external/LinkedList/src/Link.zig +++ /dev/null @@ -1,20 +0,0 @@ - -const T = @This(); -const G = @import("root"); - -const List = G.LinkedList; - -prev: ?*T = null, -next: ?*T = null, -list: ?*List = null, - -pub fn pop (t: *T) !void { - const list = t.list orelse return error.NonInChain; - try list.pop(t); -} -pub fn iterator (t: *T) List.Iterator { - return .{._next = t}; -} -pub fn iteratorReversed (t: *T) List.IteratorReversed { - return .{._prev = t}; -} DELETED src/external/LinkedList/src/LinkedList.zig Index: src/external/LinkedList/src/LinkedList.zig ================================================================== --- src/external/LinkedList/src/LinkedList.zig +++ /dev/null @@ -1,183 +0,0 @@ -const T = @This(); -const G = @import("root"); - -pub const Link = @import("Link.zig"); -pub const Iterator = @import("Iterator.zig"); -pub const IteratorReversed = @import("IteratorReversed.zig"); - -first: ?*Link = null, -last: ?*Link = null, -count: usize = 0, - -pub fn debug (t: *T) !void { - try G.out.writeAll("- - debug - -\r\n"); - - try G.out.print("first: = {*}\r\n",.{t.first}); - try G.out.print("last: = {*}\r\n",.{t.last}); - try G.out.print("count = {d}\r\n",.{t.count}); - - var count: usize = 0; - { // iterate - try G.out.writeAll("- - debug (normal order): - -\r\n"); - const first = t.first orelse return; - var iter = first.iterator(); - while(iter.next()) |link| { - try G.out.print("link = {*}\r\n",.{link}); - count += 1; - } - } - try G.out.print("counted = {}\r\n", .{count}); - count = 0; - - { // reverse - try G.out.writeAll("- - debug reverse: - -\r\n"); - const last = t.last orelse return; - var iter: IteratorReversed = last.iteratorReversed(); - while(iter.next()) |link| { - try G.out.print("link = {*}\r\n",.{link}); - count += 1; - } - } - try G.out.print("counted = {}\r\n", .{count}); - try G.out.writeAll("- - end debug - -\r\n"); -} - -// push -pub fn pushAfter (t: *T, after: *Link, item: *Link) void { - if (item.chain != null) {unreachable;} - if (t.last) |last| { - if (after == last) t.last = item; - } - if (after.next) |next| { - next.prev = item; - item.next = next; - } - after.next = item; - item.prev = after; - item.chain = t; - t.count += 1; -} -pub fn pushBefore (t: *T, before: *Link, item: *Link) void { - if (item.chain != null) {unreachable;} - if (t.first) |first| { - if (before == first) t.first = item; - } - if (before.prev) |prev| { - prev.next = item; - item.prev = prev; - } - before.prev = item; - item.next = before; - item.chain = t; - t.count += 1; -} -pub fn pushFirst (t: *T, item: *Link) void { - if (item.chain != null) {unreachable;} - if (t.first) |first| { - first.prev = item; - item.next = first; - t.first = item; - } - else { - t.first = item; - t.last = item; - } - item.chain = t; - t.count += 1; -} -pub fn pushLast (t: *T, item: *Link) void { - if (item.list != null) {unreachable;} - if (t.last) |last| { - last.next = item; - item.prev = last; - t.last = item; - } - else { - t.first = item; - t.last = item; - } - item.list = t; - t.count += 1; -} - -// pop -pub fn popFirst (t: *T) ?*Link { - if (t.count == 0) {return null;} - if (t.count == 1) { - const item = t.first.?; - - t.first = null; - t.last = null; - t.count = 0; - - item.* = .{}; // clear links - return item; - } - else { // t.count > 1 - const item = t.first.?; - const next = item.next.?; - - t.first = next; - next.prev = null; - t.count -= 1; - - item.* = .{}; // clear links - return item; - } -} -pub fn popLast (t: *T) ?*Link { - if (t.count == 0) {return null;} - if (t.count == 1) { - const item = t.last.?; - - t.first = null; - t.last = null; - t.count = 0; - - item.* = .{}; // clear links - return item; - } - else { // t.count > 1 - const item = t.last.?; - const prev = item.prev.?; - - prev.next = null; - t.last = prev; - t.count -= 1; - - item.* = .{}; // clear links - return item; - } -} -pub fn pop (t: *T, item: *Link) !void { - if (item.list.? != t) unreachable; - if (t.count == 0) {return error.ChainIsEmpty;} - else if (t.count == 1) { - if (t.first.? != item) unreachable; - if (t.last.? != item) unreachable; - t.first = null; - t.last = null; - item.* = .{}; // clear links - t.count = 0; - } - else { // t.count > 1 - if (t.first.? == item) {_ = t.popFirst();} - else if (t.last.? == item) {_ = t.popLast();} - else { // non first or last - // flatten prev and next - const next = item.next orelse unreachable; // item is not last - const prev = item.prev orelse unreachable; // item is not first - next.prev = prev; - prev.next = next; - - item.* = .{}; - t.count -= 1; - } - } -} -pub fn iterator (t: *T) Iterator { - return .{._next = t.first}; -} -pub fn iteratorReverse(t: *T) IteratorReversed { - return .{._prev = t.last}; -} DELETED src/external/LinkedList/src/Sample.zig Index: src/external/LinkedList/src/Sample.zig ================================================================== --- src/external/LinkedList/src/Sample.zig +++ /dev/null @@ -1,11 +0,0 @@ -const G = @import("root"); -const T = @This(); - -const Link = G.LinkedList.Link; - -link: Link = .{}, -num: usize = 0, - -pub fn unlink (link: *Link) *T { - return @fieldParentPtr(T, "link", link); -} DELETED src/external/LinkedList/src/Samples.zig Index: src/external/LinkedList/src/Samples.zig ================================================================== --- src/external/LinkedList/src/Samples.zig +++ /dev/null @@ -1,45 +0,0 @@ -const G = @import("root"); -const T = @This(); - -const Link = G.LinkedList.Link; - -pub const Sample = @import("Sample.zig"); - -frees: G.LinkedList = .{}, -used: G.LinkedList = .{}, - -pub fn add (t: *T, num: usize) ?*Sample { - const link = t.frees.popFirst() orelse return null; - t.used.pushLast(link); - const sample = Sample.unlink(link); - sample.num = num; - return sample; -} -pub fn find (t: *T, num: usize) ?*Sample { - var iter = t.used.iterator(); - while(iter.next()) |link| { - const sample = Sample.unlink(link); - if (sample.num == num) return sample; - } - return null; -} -pub fn print (t: *T) !void { - var link = t.used.first orelse return; - while(true) { - const sample = Sample.unlink(link); - try G.out.print("num: {}\r\n",.{sample.num}); - link = link.next orelse return; - } -} -pub fn debug (t: *T) !void { - try t.print(); - try G.out.writeAll("used:"); - try t.used.debug(); - try G.out.writeAll("frees:"); - try t.frees.debug(); -} -pub fn addBlanks (t: *T, blanks: []Sample) void { - for (blanks) |*blank| { // add blanks - t.frees.pushLast(&blank.link); - } -} DELETED src/external/LinkedList/src/linkedList.zig Index: src/external/LinkedList/src/linkedList.zig ================================================================== --- src/external/LinkedList/src/linkedList.zig +++ /dev/null @@ -1,183 +0,0 @@ -const T = @This(); -const G = @import("root"); - -pub const Link = @import("Link.zig"); -pub const Iterator = @import("Iterator.zig"); -pub const IteratorReversed = @import("IteratorReversed.zig"); - -first: ?*Link = null, -last: ?*Link = null, -count: usize = 0, - -pub fn debug (t: *T) !void { - try G.out.writeAll("- - debug - -\r\n"); - - try G.out.print("first: = {*}\r\n",.{t.first}); - try G.out.print("last: = {*}\r\n",.{t.last}); - try G.out.print("count = {d}\r\n",.{t.count}); - - var count: usize = 0; - { // iterate - try G.out.writeAll("- - debug (normal order): - -\r\n"); - const first = t.first orelse return; - var iter = first.iterator(); - while(iter.next()) |link| { - try G.out.print("link = {*}\r\n",.{link}); - count += 1; - } - } - try G.out.print("counted = {}\r\n", .{count}); - count = 0; - - { // reverse - try G.out.writeAll("- - debug reverse: - -\r\n"); - const last = t.last orelse return; - var iter: IteratorReversed = last.iteratorReversed(); - while(iter.next()) |link| { - try G.out.print("link = {*}\r\n",.{link}); - count += 1; - } - } - try G.out.print("counted = {}\r\n", .{count}); - try G.out.writeAll("- - end debug - -\r\n"); -} - -// push -pub fn pushAfter (t: *T, after: *Link, item: *Link) void { - if (item.chain != null) {unreachable;} - if (t.last) |last| { - if (after == last) t.last = item; - } - if (after.next) |next| { - next.prev = item; - item.next = next; - } - after.next = item; - item.prev = after; - item.chain = t; - t.count += 1; -} -pub fn pushBefore (t: *T, before: *Link, item: *Link) void { - if (item.chain != null) {unreachable;} - if (t.first) |first| { - if (before == first) t.first = item; - } - if (before.prev) |prev| { - prev.next = item; - item.prev = prev; - } - before.prev = item; - item.next = before; - item.chain = t; - t.count += 1; -} -pub fn pushFirst (t: *T, item: *Link) void { - if (item.chain != null) {unreachable;} - if (t.first) |first| { - first.prev = item; - item.next = first; - t.first = item; - } - else { - t.first = item; - t.last = item; - } - item.chain = t; - t.count += 1; -} -pub fn pushLast (t: *T, item: *Link) void { - if (item.list != null) {unreachable;} - if (t.last) |last| { - last.next = item; - item.prev = last; - t.last = item; - } - else { - t.first = item; - t.last = item; - } - item.list = t; - t.count += 1; -} - -// pop -pub fn popFirst (t: *T) ?*Link { - if (t.count == 0) {return null;} - if (t.count == 1) { - const item = t.first.?; - - t.first = null; - t.last = null; - t.count = 0; - - item.* = .{}; // clear links - return item; - } - else { // t.count > 1 - const item = t.first.?; - const next = item.next.?; - - t.first = next; - next.prev = null; - t.count -= 1; - - item.* = .{}; // clear links - return item; - } -} -pub fn popLast (t: *T) ?*Link { - if (t.count == 0) {return null;} - if (t.count == 1) { - const item = t.last.?; - - t.first = null; - t.last = null; - t.count = 0; - - item.* = .{}; // clear links - return item; - } - else { // t.count > 1 - const item = t.last.?; - const prev = item.prev.?; - - prev.next = null; - t.last = prev; - t.count -= 1; - - item.* = .{}; // clear links - return item; - } -} -pub fn pop (t: *T, item: *Link) !void { - if (item.list.? != t) unreachable; - if (t.count == 0) {return error.ChainIsEmpty;} - else if (t.count == 1) { - if (t.first.? != item) unreachable; - if (t.last.? != item) unreachable; - t.first = null; - t.last = null; - item.* = .{}; // clear links - t.count = 0; - } - else { // t.count > 1 - if (t.first.? == item) {_ = t.popFirst();} - else if (t.last.? == item) {_ = t.popLast();} - else { // non first or last - // flatten prev and next - const next = item.next orelse unreachable; // item is not last - const prev = item.prev orelse unreachable; // item is not first - next.prev = prev; - prev.next = next; - - item.* = .{}; - t.count -= 1; - } - } -} -pub fn iterator (t: *T) Iterator { - return .{._next = t.first}; -} -pub fn iteratorReverse(t: *T) IteratorReversed { - return .{._prev = t.last}; -} DELETED src/external/LinkedList/src/main.zig Index: src/external/LinkedList/src/main.zig ================================================================== --- src/external/LinkedList/src/main.zig +++ /dev/null @@ -1,42 +0,0 @@ -const G = @import("root"); -const T = @This(); - -pub const std = @import("std"); -pub const out = std.io.getStdOut().writer(); - -pub const LinkedList = @import("LinkedList.zig"); -pub const Sample = @import("Sample.zig"); -pub const Samples = @import("Samples.zig"); - -var samples: Samples = .{}; -var buffer: [10]Sample = undefined; - -pub fn main() !void { - try G.out.writeAll("main started..."); - - for (buffer) |*blank| { // init blanks - blank.* = .{}; - } - samples.addBlanks(buffer[0..]); - try G.out.writeAll(" - - buffer inited...\r\n"); - try samples.print(); - - try G.out.writeAll(" - - add 6... \r\n"); - _ = samples.add(6) orelse return error.UnplanedError; - try samples.print(); - - try G.out.writeAll(" - - add 4 {*}...\r\n"); - var n4 = samples.add(4) orelse return error.UnplanedError; - try samples.print(); - - try G.out.writeAll(" - - pop 4 {*}...\r\n"); - try n4.link.pop(); - samples.frees.pushLast(&n4.link); - try samples.print(); - - try G.out.writeAll(" - - add 2 {*}...\r\n"); - _ = samples.add(2) orelse return error.UnplanedError; - try samples.print(); - - try G.out.writeAll("main ended...\r\n"); -} DELETED src/external/Ranges/build.zig Index: src/external/Ranges/build.zig ================================================================== --- src/external/Ranges/build.zig +++ /dev/null @@ -1,34 +0,0 @@ -const std = @import("std"); - -pub fn build(b: *std.build.Builder) void { - // Standard target options allows the person running `zig build` to choose - // what target to build for. Here we do not override the defaults, which - // means any target is allowed, and the default is native. Other options - // for restricting supported target set are available. - const target = b.standardTargetOptions(.{}); - - // Standard release options allow the person running `zig build` to select - // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. - const mode = b.standardReleaseOptions(); - - const exe = b.addExecutable("Ranges", "src/main.zig"); - exe.setTarget(target); - exe.setBuildMode(mode); - exe.install(); - - const run_cmd = exe.run(); - run_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - run_cmd.addArgs(args); - } - - const run_step = b.step("run", "Run the app"); - run_step.dependOn(&run_cmd.step); - - const exe_tests = b.addTest("src/main.zig"); - exe_tests.setTarget(target); - exe_tests.setBuildMode(mode); - - const test_step = b.step("test", "Run unit tests"); - test_step.dependOn(&exe_tests.step); -} DELETED src/external/Ranges/src/RangeU.zig Index: src/external/Ranges/src/RangeU.zig ================================================================== --- src/external/Ranges/src/RangeU.zig +++ /dev/null @@ -1,67 +0,0 @@ -const G = @import("root"); -const T = @This(); - -start: usize = 0, -end: usize = 0, - -pub fn countLen (t: *const T) !usize { - var delta: usize = 0; - if (t.isReversed()) {delta = t.start - t.end;} - else {delta = t.end - t.start;} - if (delta == G.std.maxInt(usize)) {return error.OverFlow;} - else {return delta + 1;} -} -pub fn isReversed (t: *const T) bool { - if(t.start >= t.end) return false; - return true; -} -pub fn cutLeft (t: *const T, pos: usize) !T { - // cheks - const len = try t.countLen(); - if(pos >= len) return error.Overflow; - - var ret = t.*; - ret.start = t.start + pos; - return ret; -} -pub fn cutRight (t: *const T, pos: usize) !T { - const len = t.countLen(); - if(pos >= len) return error.Overflow; - - var ret = t.*; - ret.end = t.start + pos; - return ret; -} -pub fn cut (t: *const T, start: usize, end: usize) !T { - var ret = t.*; - ret = try ret.cutRight(end); - ret = try ret.cutLeft (start); - return ret; -} -pub fn cutRange (t: *const T, target: *const T) !T { - var ret = t.*; - ret = try ret.cutRight(target.end); - ret = try ret.cutLeft (target.start); - return ret; -} -pub fn shiftRight (t: *const T, pos: usize) !T { - if (pos > G.std.math.maxInt(usize) - t.end) return error.Overflow; - var new: T = .{}; - new.start = t.start + pos; - new.end = t.end + pos; - return new; -} -pub fn shiftLeft (t: *const T, pos: usize) !T { - if (t.start < pos) return error.Overflow; - var new: T = .{}; - new.start = t.start - pos; - new.end = t.end - pos; - return new; -} -pub fn move (t: *const T, pos: usize) !T { - const min = @minimum(t.start, t.end); - var new: T = .{}; - new.start = t.start - min + pos; - new.end = t.end - min + pos; - return new; -} DELETED src/external/Ranges/src/main.zig Index: src/external/Ranges/src/main.zig ================================================================== --- src/external/Ranges/src/main.zig +++ /dev/null @@ -1,15 +0,0 @@ -const G = @import("root"); -const T = @This(); - -pub const std = @import("std"); -pub const out = std.io.getStdOut().writer(); - -pub const RangeU = @import("RangeU.zig"); - -pub fn main() anyerror!void { - var range: RangeU = .{.start=1, .end=10}; - var iter = range.iterator(); - while(iter.next()) |n| { - G.out.print("n = {d}/r/n",.{n}); - } -} DELETED src/external/Tree/build.zig Index: src/external/Tree/build.zig ================================================================== --- src/external/Tree/build.zig +++ /dev/null @@ -1,26 +0,0 @@ -const std = @import("std"); - -pub fn build(b: *std.build.Builder) void { - const target = b.standardTargetOptions(.{}); - const mode = b.standardReleaseOptions(); - const exe = b.addExecutable("Tree", "src/main.zig"); - exe.setTarget(target); - exe.setBuildMode(mode); - exe.install(); - - const run_cmd = exe.run(); - run_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - run_cmd.addArgs(args); - } - - const run_step = b.step("run", "Run the app"); - run_step.dependOn(&run_cmd.step); - - const exe_tests = b.addTest("src/main.zig"); - exe_tests.setTarget(target); - exe_tests.setBuildMode(mode); - - const test_step = b.step("test", "Run unit tests"); - test_step.dependOn(&exe_tests.step); -} DELETED src/external/Tree/src/LinkedList/build.zig Index: src/external/Tree/src/LinkedList/build.zig ================================================================== --- src/external/Tree/src/LinkedList/build.zig +++ /dev/null @@ -1,34 +0,0 @@ -const std = @import("std"); - -pub fn build(b: *std.build.Builder) void { - // Standard target options allows the person running `zig build` to choose - // what target to build for. Here we do not override the defaults, which - // means any target is allowed, and the default is native. Other options - // for restricting supported target set are available. - const target = b.standardTargetOptions(.{}); - - // Standard release options allow the person running `zig build` to select - // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. - const mode = b.standardReleaseOptions(); - - const exe = b.addExecutable("ChainedList", "src/main.zig"); - exe.setTarget(target); - exe.setBuildMode(mode); - exe.install(); - - const run_cmd = exe.run(); - run_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - run_cmd.addArgs(args); - } - - const run_step = b.step("run", "Run the app"); - run_step.dependOn(&run_cmd.step); - - const exe_tests = b.addTest("src/main.zig"); - exe_tests.setTarget(target); - exe_tests.setBuildMode(mode); - - const test_step = b.step("test", "Run unit tests"); - test_step.dependOn(&exe_tests.step); -} DELETED src/external/Tree/src/LinkedList/src/Iterator.zig Index: src/external/Tree/src/LinkedList/src/Iterator.zig ================================================================== --- src/external/Tree/src/LinkedList/src/Iterator.zig +++ /dev/null @@ -1,9 +0,0 @@ -const T = @This(); -const G = @import("root"); - -_next: ?*G.LinkedList.Link, -pub fn next(t: *T) ?*G.LinkedList.Link { - const link = t._next orelse return null; - t._next = link.next; - return link; -} DELETED src/external/Tree/src/LinkedList/src/IteratorReversed.zig Index: src/external/Tree/src/LinkedList/src/IteratorReversed.zig ================================================================== --- src/external/Tree/src/LinkedList/src/IteratorReversed.zig +++ /dev/null @@ -1,9 +0,0 @@ -const T = @This(); -const G = @import("root"); - -_prev: ?*G.LinkedList.Link, -pub fn next(t: *T) ?*G.LinkedList.Link { - const link = t._prev orelse return null; - t._prev = link.prev; - return link; -} DELETED src/external/Tree/src/LinkedList/src/Link.zig Index: src/external/Tree/src/LinkedList/src/Link.zig ================================================================== --- src/external/Tree/src/LinkedList/src/Link.zig +++ /dev/null @@ -1,20 +0,0 @@ - -const T = @This(); -const G = @import("root"); - -const List = G.LinkedList; - -prev: ?*T = null, -next: ?*T = null, -list: ?*List = null, - -pub fn pop (t: *T) !void { - const list = t.list orelse return error.NonInChain; - try list.pop(t); -} -pub fn iterator (t: *T) List.Iterator { - return .{._next = t}; -} -pub fn iteratorReversed (t: *T) List.IteratorReversed { - return .{._prev = t}; -} DELETED src/external/Tree/src/LinkedList/src/LinkedList.zig Index: src/external/Tree/src/LinkedList/src/LinkedList.zig ================================================================== --- src/external/Tree/src/LinkedList/src/LinkedList.zig +++ /dev/null @@ -1,183 +0,0 @@ -const T = @This(); -const G = @import("root"); - -pub const Link = @import("Link.zig"); -pub const Iterator = @import("Iterator.zig"); -pub const IteratorReversed = @import("IteratorReversed.zig"); - -first: ?*Link = null, -last: ?*Link = null, -count: usize = 0, - -pub fn debug (t: *T) !void { - try G.out.writeAll("- - debug - -\r\n"); - - try G.out.print("first: = {*}\r\n",.{t.first}); - try G.out.print("last: = {*}\r\n",.{t.last}); - try G.out.print("count = {d}\r\n",.{t.count}); - - var count: usize = 0; - { // iterate - try G.out.writeAll("- - debug (normal order): - -\r\n"); - const first = t.first orelse return; - var iter = first.iterator(); - while(iter.next()) |link| { - try G.out.print("link = {*}\r\n",.{link}); - count += 1; - } - } - try G.out.print("counted = {}\r\n", .{count}); - count = 0; - - { // reverse - try G.out.writeAll("- - debug reverse: - -\r\n"); - const last = t.last orelse return; - var iter: IteratorReversed = last.iteratorReversed(); - while(iter.next()) |link| { - try G.out.print("link = {*}\r\n",.{link}); - count += 1; - } - } - try G.out.print("counted = {}\r\n", .{count}); - try G.out.writeAll("- - end debug - -\r\n"); -} - -// push -pub fn pushAfter (t: *T, after: *Link, item: *Link) void { - if (item.chain != null) {unreachable;} - if (t.last) |last| { - if (after == last) t.last = item; - } - if (after.next) |next| { - next.prev = item; - item.next = next; - } - after.next = item; - item.prev = after; - item.chain = t; - t.count += 1; -} -pub fn pushBefore (t: *T, before: *Link, item: *Link) void { - if (item.chain != null) {unreachable;} - if (t.first) |first| { - if (before == first) t.first = item; - } - if (before.prev) |prev| { - prev.next = item; - item.prev = prev; - } - before.prev = item; - item.next = before; - item.chain = t; - t.count += 1; -} -pub fn pushFirst (t: *T, item: *Link) void { - if (item.chain != null) {unreachable;} - if (t.first) |first| { - first.prev = item; - item.next = first; - t.first = item; - } - else { - t.first = item; - t.last = item; - } - item.chain = t; - t.count += 1; -} -pub fn pushLast (t: *T, item: *Link) void { - if (item.list != null) {unreachable;} - if (t.last) |last| { - last.next = item; - item.prev = last; - t.last = item; - } - else { - t.first = item; - t.last = item; - } - item.list = t; - t.count += 1; -} - -// pop -pub fn popFirst (t: *T) ?*Link { - if (t.count == 0) {return null;} - if (t.count == 1) { - const item = t.first.?; - - t.first = null; - t.last = null; - t.count = 0; - - item.* = .{}; // clear links - return item; - } - else { // t.count > 1 - const item = t.first.?; - const next = item.next.?; - - t.first = next; - next.prev = null; - t.count -= 1; - - item.* = .{}; // clear links - return item; - } -} -pub fn popLast (t: *T) ?*Link { - if (t.count == 0) {return null;} - if (t.count == 1) { - const item = t.last.?; - - t.first = null; - t.last = null; - t.count = 0; - - item.* = .{}; // clear links - return item; - } - else { // t.count > 1 - const item = t.last.?; - const prev = item.prev.?; - - prev.next = null; - t.last = prev; - t.count -= 1; - - item.* = .{}; // clear links - return item; - } -} -pub fn pop (t: *T, item: *Link) !void { - if (item.list.? != t) unreachable; - if (t.count == 0) {return error.ChainIsEmpty;} - else if (t.count == 1) { - if (t.first.? != item) unreachable; - if (t.last.? != item) unreachable; - t.first = null; - t.last = null; - item.* = .{}; // clear links - t.count = 0; - } - else { // t.count > 1 - if (t.first.? == item) {_ = t.popFirst();} - else if (t.last.? == item) {_ = t.popLast();} - else { // non first or last - // flatten prev and next - const next = item.next orelse unreachable; // item is not last - const prev = item.prev orelse unreachable; // item is not first - next.prev = prev; - prev.next = next; - - item.* = .{}; - t.count -= 1; - } - } -} -pub fn iterator (t: *T) Iterator { - return .{._next = t.first}; -} -pub fn iteratorReverse(t: *T) IteratorReversed { - return .{._prev = t.last}; -} DELETED src/external/Tree/src/LinkedList/src/Sample.zig Index: src/external/Tree/src/LinkedList/src/Sample.zig ================================================================== --- src/external/Tree/src/LinkedList/src/Sample.zig +++ /dev/null @@ -1,11 +0,0 @@ -const G = @import("root"); -const T = @This(); - -const Link = G.LinkedList.Link; - -link: Link = .{}, -num: usize = 0, - -pub fn unlink (link: *Link) *T { - return @fieldParentPtr(T, "link", link); -} DELETED src/external/Tree/src/LinkedList/src/Samples.zig Index: src/external/Tree/src/LinkedList/src/Samples.zig ================================================================== --- src/external/Tree/src/LinkedList/src/Samples.zig +++ /dev/null @@ -1,45 +0,0 @@ -const G = @import("root"); -const T = @This(); - -const Link = G.LinkedList.Link; - -pub const Sample = @import("Sample.zig"); - -frees: G.LinkedList = .{}, -used: G.LinkedList = .{}, - -pub fn add (t: *T, num: usize) ?*Sample { - const link = t.frees.popFirst() orelse return null; - t.used.pushLast(link); - const sample = Sample.unlink(link); - sample.num = num; - return sample; -} -pub fn find (t: *T, num: usize) ?*Sample { - var iter = t.used.iterator(); - while(iter.next()) |link| { - const sample = Sample.unlink(link); - if (sample.num == num) return sample; - } - return null; -} -pub fn print (t: *T) !void { - var link = t.used.first orelse return; - while(true) { - const sample = Sample.unlink(link); - try G.out.print("num: {}\r\n",.{sample.num}); - link = link.next orelse return; - } -} -pub fn debug (t: *T) !void { - try t.print(); - try G.out.writeAll("used:"); - try t.used.debug(); - try G.out.writeAll("frees:"); - try t.frees.debug(); -} -pub fn addBlanks (t: *T, blanks: []Sample) void { - for (blanks) |*blank| { // add blanks - t.frees.pushLast(&blank.link); - } -} DELETED src/external/Tree/src/LinkedList/src/main.zig Index: src/external/Tree/src/LinkedList/src/main.zig ================================================================== --- src/external/Tree/src/LinkedList/src/main.zig +++ /dev/null @@ -1,42 +0,0 @@ -const G = @import("root"); -const T = @This(); - -pub const std = @import("std"); -pub const out = std.io.getStdOut().writer(); - -pub const LinkedList = @import("LinkedList.zig"); -pub const Sample = @import("Sample.zig"); -pub const Samples = @import("Samples.zig"); - -var samples: Samples = .{}; -var buffer: [10]Sample = undefined; - -pub fn main() !void { - try G.out.writeAll("main started..."); - - for (buffer) |*blank| { // init blanks - blank.* = .{}; - } - samples.addBlanks(buffer[0..]); - try G.out.writeAll(" - - buffer inited...\r\n"); - try samples.print(); - - try G.out.writeAll(" - - add 6... \r\n"); - _ = samples.add(6) orelse return error.UnplanedError; - try samples.print(); - - try G.out.writeAll(" - - add 4 {*}...\r\n"); - var n4 = samples.add(4) orelse return error.UnplanedError; - try samples.print(); - - try G.out.writeAll(" - - pop 4 {*}...\r\n"); - try n4.link.pop(); - samples.frees.pushLast(&n4.link); - try samples.print(); - - try G.out.writeAll(" - - add 2 {*}...\r\n"); - _ = samples.add(2) orelse return error.UnplanedError; - try samples.print(); - - try G.out.writeAll("main ended...\r\n"); -} DELETED src/external/Tree/src/Sample.zig Index: src/external/Tree/src/Sample.zig ================================================================== --- src/external/Tree/src/Sample.zig +++ /dev/null @@ -1,28 +0,0 @@ -const Self = @This(); -const Sample = @This(); -const std = @import("std"); -const Tree = @import("Tree.zig"); -const Prog = @import("root"); - -tree: Tree = .{}, -name_buffer: [16]u8 = undefined, -name_len: usize = 0, - -pub fn setName (self: *Self, text: []const u8) void { - std.mem.copy(u8, self.name_buffer[0..], text); - self.name_len = text.len; -} -pub fn getName (self: *Self) []u8 { - return self.name_buffer[0..self.name_len]; -} -pub fn debug (self: *Self) !void { - const out = std.io.getStdOut().writer(); _ = out; - try out.writeAll("debug: \r\n"); - var walker = self.tree.walker(); - while (walker.next()) |node| { - _ = node.parent orelse break; // if parent is not exist - it's probably root. - const sample = @fieldParentPtr(Self, "tree", node); - try out.print("({d}) {s}\r\n",.{node.nested, sample.getName()}); - } - try out.writeAll("end debug.\r\n"); -} DELETED src/external/Tree/src/Tree.zig Index: src/external/Tree/src/Tree.zig ================================================================== --- src/external/Tree/src/Tree.zig +++ /dev/null @@ -1,117 +0,0 @@ - -const T = @This(); -const G = @import("root"); - -pub const Walker = @import("Walker.zig"); - -parent: ?*T = null, -childs: G.LinkedList = .{}, -chain_link: G.LinkedList.Link = .{}, -count: usize = 0, // recurse. for get non recurse use childs.count -nested: usize = 0, - -pub fn debug (t: *T) !void { - var wlkr = t.walker(); - while (wlkr.next()) |node| { - try G.out.print("({d})\r\n",.{node.nested}); - } -} -pub fn pop (t: *T) !void { - const parent = t.parent orelse return error.NotParented; - try parent.childs.pop(&t.chain_link); - t.parent = null; - { // dec count on all parents - var current = parent; - while(true) { - current.count -= t.count; - current = current.parent orelse break; - } - } - { // recurse fix nested - const nested_delta: usize = t.nested; - var wlkr = t.walker(); - while(wlkr.next()) |node| { - node.nested -= nested_delta; - } - } -} -pub fn pushChild (t: *T, item: *T) !void { - if (item.parent != null) return error.UsePopBeforePush; - if (item.chain_link.prev != null) return error.UsePopBeforePush; - if (item.chain_link.next != null) return error.UsePopBeforePush; - - { // recurse fix nested - const nested_delta: usize = t.nested + 1; - var wlkr = item.walker(); - while(wlkr.next()) |node| { - node.nested += nested_delta; - } - } - t.childs.pushLast(&item.chain_link); - item.parent = t; - { // increment counts - var current = t; - while(true) { - current.count += item.count; - current = current.parent orelse break; - } - } -} -pub fn pushNext (t: *T, item: *T) !void { - if (item.parent != null) return error.UsePopBeforePush; - if (item.chain_link.prev != null) return error.UsePopBeforePush; - if (item.chain_link.next != null) return error.UsePopBeforePush; - - const parent = t.parent orelse return error.SelfNotParented; - { // recurse fix nested - const nested_delta: usize = t.nested; - var wlkr = item.walker(); - while(wlkr.next) |node| { - node.nested += nested_delta; - } - } - const chain = parent.chain; - chain.pushAfter(&t.link, &item.link); - item.parent = parent; - { // increment counts - var current = parent; - while(true) { - current.count += item.count; - current = current.parent orelse break; - } - } -} -pub fn pushPrev (t: *T, item: *T) !void { - if (item.parent != null) return error.UsePopBeforePush; - if (item.chain_link.prev != null) return error.UsePopBeforePush; - if (item.chain_link.next != null) return error.UsePopBeforePush; - - const parent = t.parent orelse return error.SelfNotParented; - { // recurse fix nested - const nested_delta: usize = t.nested; - var wlkr = item.walker(); - while(wlkr.next) |node| { - node.nested += nested_delta; - } - } - const chain = parent.chain; - chain.pushBefore(&t.link, &item.link); - item.parent = parent; - { // increment counts - var current = parent; - while(true) { - current.count += item.count; - current = current.parent orelse break; - } - } -} -pub fn outNext (t: *T) ?*T { // function for walking about tree; - var parent = t.parent orelse return null; - while(true) { - if (parent.chain_link.next) |next| return @fieldParentPtr(T, "chain_link", next); - parent = parent.parent orelse return null; - } -} -pub fn walker (t: *T) Walker { - return .{.current = t}; -} DELETED src/external/Tree/src/Walker.zig Index: src/external/Tree/src/Walker.zig ================================================================== --- src/external/Tree/src/Walker.zig +++ /dev/null @@ -1,18 +0,0 @@ -const T = @This(); -const G = @import("root"); - -current: ?*G.Tree = null, -pub fn next(t: *T) ?*G.Tree { - const current = t.current orelse return null; - if (current.childs.first) |first| { - t.current = @fieldParentPtr(G.Tree, "chain_link", first); - } - else if (current.chain_link.next) |chain_link| { - t.current = @fieldParentPtr(G.Tree, "chain_link", chain_link); - } - else if (current.outNext()) |tree| { - t.current = tree; - } - else t.current = null; - return current; -} DELETED src/external/Tree/src/main.zig Index: src/external/Tree/src/main.zig ================================================================== --- src/external/Tree/src/main.zig +++ /dev/null @@ -1,47 +0,0 @@ - - - -const G = @import("root"); -const T = @This(); - -pub const std = @import("std"); -pub const out = std.io.getStdOut().writer(); - -pub const LinkedList = @import("LinkedList/src/LinkedList.zig"); -pub const Tree = @import("Tree.zig"); -pub const Sample = @import("Sample.zig"); - -var buffer: [10]Sample = undefined; -var tree: Tree = .{}; -var grabbed: usize = 0; - -// methods -pub fn main() !void { - var t1 = grabOne() orelse unreachable; - t1.setName("t1"); - - var t2 = grabOne() orelse unreachable; - t2.setName("t2"); - - var t3 = grabOne() orelse unreachable; - t3.setName("t3"); - - var t2_1 = grabOne() orelse unreachable; - t2_1.setName("t2_1"); - - try tree.pushChild(&t1.tree); - try tree.pushChild(&t2.tree); - try tree.pushChild(&t3.tree); - try t2.tree.pushChild(&t2_1.tree); - try t2.tree.pop(); - try tree.pushChild(&t2.tree); - - try t1.debug(); -} - -pub fn grabOne() ?*Sample { - if (grabbed >= buffer.len) return null; - const grab = &buffer[grabbed]; - grabbed += 1; - return grab; -} DELETED src/external/lib/build.zig Index: src/external/lib/build.zig ================================================================== --- src/external/lib/build.zig +++ /dev/null @@ -1,34 +0,0 @@ -const std = @import("std"); - -pub fn build(b: *std.build.Builder) void { - // Standard target options allows the person running `zig build` to choose - // what target to build for. Here we do not override the defaults, which - // means any target is allowed, and the default is native. Other options - // for restricting supported target set are available. - const target = b.standardTargetOptions(.{}); - - // Standard release options allow the person running `zig build` to select - // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. - const mode = b.standardReleaseOptions(); - - const exe = b.addExecutable("lib", "src/main.zig"); - exe.setTarget(target); - exe.setBuildMode(mode); - exe.install(); - - const run_cmd = exe.run(); - run_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - run_cmd.addArgs(args); - } - - const run_step = b.step("run", "Run the app"); - run_step.dependOn(&run_cmd.step); - - const exe_tests = b.addTest("src/main.zig"); - exe_tests.setTarget(target); - exe_tests.setBuildMode(mode); - - const test_step = b.step("test", "Run unit tests"); - test_step.dependOn(&exe_tests.step); -} DELETED src/external/lib/src/lib.zig Index: src/external/lib/src/lib.zig ================================================================== --- src/external/lib/src/lib.zig +++ /dev/null @@ -1,81 +0,0 @@ -const std = @import("std"); -pub const c = @cImport({ - // canonical c - @cInclude("stdio.h"); - @cInclude("stdlib.h"); - - // linux - @cInclude("locale.h"); - @cInclude("fcntl.h"); - @cInclude("termios.h"); - @cInclude("sys/ioctl.h"); - @cInclude("sys/socket.h"); - @cInclude("unistd.h"); - @cInclude("signal.h"); -}); -pub const Coor2u = struct { - x: usize = 0, - y: usize = 0, - - pub fn isNotSmaller (self: *Coor2u, target: *Coor2u) bool { - if (self.x < target.x) return false; - if (self.y < target.y) return false; - return true; - } - pub fn isBigger (self: *Coor2u, target: *Coor2u) bool { - if (self.x > target.x) return true; - if (self.y > target.y) return true; - return false; - } -}; -pub const Range = struct { - start: usize = 0, - end: usize = 0, -}; - -const do_not_compile_todo = false; -pub fn todo () void { - if (do_not_compile_todo) @compileError("TODO: implement me"); - if (std.builtin.mode == .Debug) {std.log.warn("todo this.", .{});} -} - -// bool -pub fn toggleU32 (ptr: *u32, flag: u32, state: bool) void { - switch(state) { - true => ptr.* |= flag, - false => ptr.* &= ~flag, - } -} - -// console -pub fn printRune (rune: u8) void { - _ = c.fputc(rune, c.stdout); - _ = c.fflush(c.stdout); -} -pub fn print (text: []const u8) void { - for (text) |ch| { - printRune(ch); - } -} - -// file -pub fn fileRead (allocator: std.mem.Allocator, name: []const u8) ![]const u8 { - var cwd = std.fs.cwd(); - var file = try cwd.openFile(name, .{.mode = .read_only}); - defer file.close(); - const size = try file.getEndPos(); - if (size == 0) return error.FileIsEmpty; - if (size > std.math.maxInt(usize)) return error.FileSizeIsBiggerThatRam; - const truncate_size = @truncate(usize, size); - const buffer = try allocator.alloc(u8, truncate_size); - const readed = try file.readAll(buffer); - if (readed < size) unreachable; - return buffer[0..]; -} -pub fn fileSave (data: []const u8, name: []const u8) !void { - var cwd = std.fs.cwd(); - var file = try cwd.createFile(name, .{}); - defer file.close(); - const writer = file.writer(); - try writer.writeAll(data); -} DELETED src/external/lib/src/main.zig Index: src/external/lib/src/main.zig ================================================================== --- src/external/lib/src/main.zig +++ /dev/null @@ -1,19 +0,0 @@ -const std = @import("std"); -const lib = @import("lib.zig"); - -pub fn main() anyerror!void { - // read data example: - var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena.deinit(); - const allocator = arena.allocator(); - - var file_data: []const u8 = undefined; - const loaded = lib.fileRead(allocator, "src/main.zig"); - defer if (loaded) |data| {allocator.free(data);} else |_| {}; - if (loaded) |data| {file_data = data;} - else |err| { - std.log.info("error = {}", .{err}); - return; - } - std.log.info("\n{s}", .{file_data}); -} DELETED src/external/linkedBufferedAllocator.zig Index: src/external/linkedBufferedAllocator.zig ================================================================== --- src/external/linkedBufferedAllocator.zig +++ /dev/null @@ -1,37 +0,0 @@ -pub fn Init(comptime TT: type, comptime chunk_size: usize, comptime link_field_name: []const u8) type { - return struct { - const T = @This(); - const G = @import("root"); - - allocator: G.std.mem.Allocator = undefined, - arena: G.std.heap.ArenaAllocator = undefined, - array: G.LinkedList = .{}, - - pub fn init (t: *T) !void { - t.arena = G.std.heap.ArenaAllocator.init(G.std.heap.c_allocator); - t.allocator = t.arena.allocator(); - } - pub fn deinit (t: *T) !void { - t.arena.deinit(); - } - pub fn alloc (t: *T) !*TT { - if (t.array.count == 0) { - var new_frees = try t.allocator.alloc(TT, chunk_size); - for (new_frees) |*one| { - const link = &@field(one, link_field_name); - link.* = .{}; - t.array.pushLast(link); - } - } - const link = t.array.popFirst().?; - const fpp = @fieldParentPtr(TT, link_field_name, link); - fpp.* = .{}; - return fpp; - } - - /// this is not real free. just push to array for future use. - pub fn free (t: *T, fpp: *TT) void { - t.array.pushLast(&@field(fpp, link_field_name)); - } - }; -} DELETED src/external/textLib/build.zig Index: src/external/textLib/build.zig ================================================================== --- src/external/textLib/build.zig +++ /dev/null @@ -1,34 +0,0 @@ -const std = @import("std"); - -pub fn build(b: *std.build.Builder) void { - // Standard target options allows the person running `zig build` to choose - // what target to build for. Here we do not override the defaults, which - // means any target is allowed, and the default is native. Other options - // for restricting supported target set are available. - const target = b.standardTargetOptions(.{}); - - // Standard release options allow the person running `zig build` to select - // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. - const mode = b.standardReleaseOptions(); - - const exe = b.addExecutable("text", "src/main.zig"); - exe.setTarget(target); - exe.setBuildMode(mode); - exe.install(); - - const run_cmd = exe.run(); - run_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - run_cmd.addArgs(args); - } - - const run_step = b.step("run", "Run the app"); - run_step.dependOn(&run_cmd.step); - - const exe_tests = b.addTest("src/main.zig"); - exe_tests.setTarget(target); - exe_tests.setBuildMode(mode); - - const test_step = b.step("test", "Run unit tests"); - test_step.dependOn(&exe_tests.step); -} DELETED src/external/textLib/src/CharsDecFromI64.zig Index: src/external/textLib/src/CharsDecFromI64.zig ================================================================== --- src/external/textLib/src/CharsDecFromI64.zig +++ /dev/null @@ -1,77 +0,0 @@ - -const G = @import("root"); -const T = @This(); - -const expect = G.std.testing.expect; - -pub const MAX_LEN = "-9223372036854775808".len; // INT64_MIN -pub const last_digit = MAX_LEN - 1; -pub const hex_table = "0123456789abcdef".*; -pub const zeroed = "00000000000000000000"; - -buff: [MAX_LEN]u8 = zeroed.*, -start: usize = last_digit, -end: usize = last_digit, - -pub fn reset (t: *T) void { - t.* = .{}; -} -pub fn set (t: *T, _num: i64) void { - t.reset(); - - var num: u64 = G.std.math.absCast(_num); - while(true) { - const remainder = @truncate(u8, num % 10); - t.buff[t.start] = hex_table[remainder]; - num = num / 10; - if (num == 0) break; - t.start -= 1; - } - - if(_num < 0) { - t.start -= 1; - t.buff[t.start] = '-'; - } -} -pub fn get (t: *T) []u8 { - if (t.start > t.end) unreachable; - if (t.end > last_digit) unreachable; - return t.buff[t.start .. t.end + 1]; -} -pub fn do (t: *T, _num: i64) []u8 { - t.set(_num); - return t.get(); -} -pub fn getDigit (t: *T, wigth: usize) []u8 { - if (t.start > t.end) unreachable; - if (t.end > last_digit) unreachable; - if (wigth > MAX_LEN) unreachable; - return t.buff[MAX_LEN - wigth .. MAX_LEN]; -} -pub fn getMinWidth (t: *T, wigth: usize) []u8 { - if (wigth < t.end - t.start + 1) return t.get(); - return t.getDigit(wigth); -} -fn printedTest (expected: []const u8, data: i64) !void { - var itoa: T = undefined; - const result = itoa.do(data); - G.out.print("expected {s} received {s}", .{expected, result}); - try expect(G.std.mem.eql(u8, expected, result)); -} -test "using CharsDecFromU64" { - try printedTest( "0", 0); - try printedTest( "1", 1); - try printedTest( "10", 10); - try printedTest( "-2", -2); - try printedTest( "-20", -20); - try printedTest("-200", -200); - try printedTest( "8", 8); - try printedTest( "16", 16); - try printedTest( "32", 32); - try printedTest( "64", 64); - try printedTest( "128", 128); - try printedTest( "256", 256); - try printedTest("-9223372036854775807", -9223372036854775807); - try printedTest("-9223372036854775808", -9223372036854775808); - try printedTest( "9223372036854775807", 9223372036854775807); -} DELETED src/external/textLib/src/CharsDecFromU64.zig Index: src/external/textLib/src/CharsDecFromU64.zig ================================================================== --- src/external/textLib/src/CharsDecFromU64.zig +++ /dev/null @@ -1,71 +0,0 @@ - -const G = @import("root"); -const T = @This(); - -const expect = G.std.testing.expect; - -pub const MAX_LEN = "18446744073709551615".len; // UINT64_MAX -pub const last_digit = MAX_LEN - 1; -pub const hex_table = "0123456789abcdef".*; -pub const zeroed = "00000000000000000000"; - -buff: [MAX_LEN]u8 = zeroed.*, -start: usize = last_digit, -end: usize = last_digit, - -pub fn reset (t: *T) void { - t.* = .{}; -} -pub fn set (t: *T, _num: u64) void { - t.reset(); - var num = _num; - while (true) { - const remainder = @truncate(u8, num % 10); - t.buff[t.start] = hex_table[remainder]; - num = num / 10; - if (num == 0) break; - t.start -= 1; - } -} -pub fn get (t: *T) []u8 { - if (t.start > t.end) unreachable; - if (t.end > last_digit) unreachable; - return t.buff[t.start .. t.end + 1]; -} -pub fn do (t: *T, _num: u64) []u8 { - t.set(_num); - return t.get(); -} -pub fn getDigit (t: *T, wigth: usize) []u8 { - if (t.start > t.end) unreachable; - if (t.end > last_digit) unreachable; - if (wigth > MAX_LEN) unreachable; - return t.buff[MAX_LEN - wigth .. MAX_LEN]; -} -pub fn getMinWidth(t: *T, wigth: usize) []u8 { - if (wigth < t.end - t.start + 1) return t.get(); - return t.getDigit(wigth); -} -fn printedTest (expected: []const u8, data: u64) !void { - var itoa: T = undefined; - const result = itoa.do(data); - G.out.print("expected {s} received {s}", .{expected, result}); - try expect(G.std.mem.eql(u8, expected, result)); -} -pub fn tests() !void { - try printedTest("0", 0); - try printedTest("1", 1); - try printedTest("10", 10); - try printedTest("2", 2); - try printedTest("20", 20); - try printedTest("200", 200); - try printedTest("8", 8); - try printedTest("16", 16); - try printedTest("32", 32); - try printedTest("64", 64); - try printedTest("128", 128); - try printedTest("256", 256); - try printedTest("9223372036854775807", 9223372036854775807); - try printedTest("9223372036854775808", 9223372036854775808); - try printedTest("18446744073709551615", 18446744073709551615); -} DELETED src/external/textLib/src/external/Ranges/build.zig Index: src/external/textLib/src/external/Ranges/build.zig ================================================================== --- src/external/textLib/src/external/Ranges/build.zig +++ /dev/null @@ -1,34 +0,0 @@ -const std = @import("std"); - -pub fn build(b: *std.build.Builder) void { - // Standard target options allows the person running `zig build` to choose - // what target to build for. Here we do not override the defaults, which - // means any target is allowed, and the default is native. Other options - // for restricting supported target set are available. - const target = b.standardTargetOptions(.{}); - - // Standard release options allow the person running `zig build` to select - // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. - const mode = b.standardReleaseOptions(); - - const exe = b.addExecutable("Ranges", "src/main.zig"); - exe.setTarget(target); - exe.setBuildMode(mode); - exe.install(); - - const run_cmd = exe.run(); - run_cmd.step.dependOn(b.getInstallStep()); - if (b.args) |args| { - run_cmd.addArgs(args); - } - - const run_step = b.step("run", "Run the app"); - run_step.dependOn(&run_cmd.step); - - const exe_tests = b.addTest("src/main.zig"); - exe_tests.setTarget(target); - exe_tests.setBuildMode(mode); - - const test_step = b.step("test", "Run unit tests"); - test_step.dependOn(&exe_tests.step); -} DELETED src/external/textLib/src/external/Ranges/src/RangeU.zig Index: src/external/textLib/src/external/Ranges/src/RangeU.zig ================================================================== --- src/external/textLib/src/external/Ranges/src/RangeU.zig +++ /dev/null @@ -1,75 +0,0 @@ -const G = @import("root"); -const T = @This(); - -start: usize = 0, -end: usize = 0, - -/// len maybe eq than usize.max + 1 -pub fn countLen (t: *const T) !usize { - var delta: usize = 0; - //G.out.print("range = {}\r\n",.{t}) catch {}; - if (t.isReversed()) {delta = t.start - t.end;} - else {delta = t.end - t.start;} - if (delta == G.std.math.maxInt(usize)) {return error.OverFlow;} - else {return delta + 1;} -} -pub fn isReversed (t: *const T) bool { - if(t.start > t.end) { - //G.out.print("this IS reversed\r\n",.{}) catch {}; - return true; - } - else { - //G.out.print("this is NOT reversed\r\n",.{}) catch {}; - return false; - } -} -pub fn cutLeft (t: *const T, pos: usize) !T { - // cheks - const len = t.countLen() catch pos - 1; - if(len <= pos) return error.Overflow; - - var ret = t.*; - ret.start = t.start + pos; - return ret; -} -pub fn cutRight (t: *const T, pos: usize) !T { - const len = t.countLen() catch pos - 1; - if(len <= pos) return error.Overflow; - - var ret = t.*; - ret.end = t.start + pos; - return ret; -} -pub fn cut (t: *const T, start: usize, end: usize) !T { - var ret = t.*; - ret = try ret.cutRight(end); - ret = try ret.cutLeft (start); - return ret; -} -pub fn cutRange (t: *const T, target: *const T) !T { - var ret = t.*; - ret = try ret.cutRight(target.end); - ret = try ret.cutLeft (target.start); - return ret; -} -pub fn shiftRight (t: *const T, pos: usize) !T { - if (pos > G.std.math.maxInt(usize) - t.end) return error.Overflow; - var new: T = .{}; - new.start = t.start + pos; - new.end = t.end + pos; - return new; -} -pub fn shiftLeft (t: *const T, pos: usize) !T { - if (t.start < pos) return error.Overflow; - var new: T = .{}; - new.start = t.start - pos; - new.end = t.end - pos; - return new; -} -pub fn move (t: *const T, pos: usize) !T { - const min = @minimum(t.start, t.end); - var new: T = .{}; - new.start = t.start - min + pos; - new.end = t.end - min + pos; - return new; -} DELETED src/external/textLib/src/external/Ranges/src/main.zig Index: src/external/textLib/src/external/Ranges/src/main.zig ================================================================== --- src/external/textLib/src/external/Ranges/src/main.zig +++ /dev/null @@ -1,15 +0,0 @@ -const G = @import("root"); -const T = @This(); - -pub const std = @import("std"); -pub const out = std.io.getStdOut().writer(); - -pub const RangeU = @import("RangeU.zig"); - -pub fn main() anyerror!void { - var range: RangeU = .{.start=1, .end=10}; - var iter = range.iterator(); - while(iter.next()) |n| { - G.out.print("n = {d}/r/n",.{n}); - } -} DELETED src/external/textLib/src/main.zig Index: src/external/textLib/src/main.zig ================================================================== --- src/external/textLib/src/main.zig +++ /dev/null @@ -1,60 +0,0 @@ - -const G = @import("root"); -const T = @This(); - -pub const std = @import("std"); -pub const out = std.io.getStdOut().writer(); - -pub const RangeU = @import("external/Ranges/src/RangeU.zig"); -pub const textLib = @import("textLib.zig"); - -const text = - \\ just line 1 - \\ just line 2 -; - -pub fn main() !void { - var test_line = "zzzabdddabqqq"[0..]; - var iter = textLib.split(test_line[0..], "ab"); - while(iter.next()) |r| { - try out.print("{s}\r\n",.{r}); - } - try out.writeAll("\r\n"); - - try test_parseToLines(); -} -pub fn test_u64FromCharsDec() !void { - try out.print("test u64FromCharsDec: \r\n",.{}); - try out.print("0 = {}\r\n", .{textLib.u64FromCharsDec("0")}); - try out.print("1 = {}\r\n", .{textLib.u64FromCharsDec("1")}); - try out.print("2 = {}\r\n", .{textLib.u64FromCharsDec("2")}); - try out.print("4 = {}\r\n", .{textLib.u64FromCharsDec("4")}); - try out.print("8 = {}\r\n", .{textLib.u64FromCharsDec("8")}); - try out.print("10 = {}\r\n", .{textLib.u64FromCharsDec("10")}); - try out.print("54 = {}\r\n", .{textLib.u64FromCharsDec("54")}); -} -pub fn test_cutIndents() !void { - try out.writeAll("test cutIndents:\r\n"); - try out.print("text = \"{s}\"\r\n",.{textLib.cutIndents([]const u8, " test ") catch unreachable}); - - try out.print("text: {s}\r\n", .{text}); - try out.print("lines: {d}\r\n", .{textLib.countLines(text)}); - const example_1 = " test "; - try out.print("cut indent test: \"{s}\"\r\n",.{textLib.cutIndents([]const u8, example_1)}); -} -pub fn test_parseToLines() !void { - var arena = G.std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena.deinit(); - const allocator = arena.allocator(); - const lines = try textLib.parseToLines(text, allocator); - for (lines) |line, num| { - try out.print("line: {d} {s}\r\n", .{num, line}); - } -} -pub fn test_CopyHelper() !void { - var buffer: [1024]u8 = undefined; - var ch = textLib.CopyHelper.init(buffer[0..]); - //var w = ch.writer(); - _ = try ch.write("test"); - try out.print("ch.get = \"{s}\"\r\n", .{ch.get()}); -} DELETED src/external/textLib/src/textLib.zig Index: src/external/textLib/src/textLib.zig ================================================================== --- src/external/textLib/src/textLib.zig +++ /dev/null @@ -1,232 +0,0 @@ - -const G = @import("root"); -const T = @This(); - -const std = @import("std"); -pub const CmpResult = enum { - equal, - various, -}; -pub const CharsDecFromU64 = @import("CharsDecFromU64.zig"); -pub const CharsDecFromI64 = @import("CharsDecFromI64.zig"); - -const SplitByRuneIterator = struct { - const SI = @This(); - - delimiter: u8, - text: []const u8, - pos: ?usize = 0, - pub fn next(si: *SI) ?[]const u8 { - var n = si.pos orelse return null; - var start = n; - while(true) { - if (si.text.len - n < 1) { - si.pos = null; - return si.text[start .. si.text.len]; - } - if (si.text[n] == si.delimiter) { - si.pos = n + 1; - return si.text[start..n]; - } - n += 1; - } - } -}; -const SplitIterator = struct { - const SI = @This(); - - text: []const u8, - delimiter: []const u8, - pos: ?usize = 0, - pub fn next(si: *SI) ?[]const u8 { - var n = si.pos orelse return null; - var start = n; - while(true) { - if (si.text.len - n < si.delimiter.len) { - si.pos = null; - return si.text[start..]; - } - const ranged_slice = si.text[n..n+si.delimiter.len]; - if (G.std.mem.eql(u8, ranged_slice, si.delimiter)) { - si.pos = n + si.delimiter.len; - return si.text[start..n]; - } - n += 1; - } - } -}; -const FindRuneIterator = struct { - const FR = @This(); - text: []const u8, - rune: u8, - pos: ?usize = 0, - pub fn next(fr: *FR) ?usize { - var n = fr.pos orelse return null; - while(true) { - if (fr.text.len - n < 1) return null; - if (fr.text[n] == fr.rune) { - fr.pos = n + 1; - return n; - } - n += 1; - } - } -}; -const FindIterator = struct { - const FR = @This(); - text: []const u8, - desired: []const u8, - pos: ?usize = 0, - pub fn next(fr: *FR) ?usize { - // todo maybe fast from cmp xor and add? - var n = fr.pos orelse return null; - while(true) { - if (fr.text.len - n < fr.desired.len) return null; - const ranged_slice = fr.text[n..n+fr.desired.len]; - if (G.std.mem.eql(u8, ranged_slice, fr.desired)) { - fr.pos = n + fr.desired.len; - return n; - } - n += 1; - } - } -}; - -pub fn cmp (text: []const u8, target: []const u8) CmpResult { - if (text.len != target.len) return .various; - var pos: usize = 0; - const last = text.len - 1; - while (true) { - if (text[pos] != target[pos]) return .various; - if (pos == last) return .equal; - pos += 1; - } -} - -pub fn findRune (text: []const u8, rune: u8) FindRuneIterator { - return .{ - .text = text, - .rune = rune, - }; -} -pub fn find (text: []const u8, desired: []const u8) FindIterator { - return .{ - .text = text, - .desired = desired, - }; -} - -pub fn splitByRune (text: []const u8, rune: u8) SplitByRuneIterator { - return .{ - .text = text, - .delimiter = rune, - }; -} -pub fn split (text: []const u8, delimiter: []const u8) SplitIterator { - return .{ - .text = text, - .delimiter = delimiter, - }; -} - -// counts -pub fn countSymbol (text: []const u8, symbol: u8) usize { - var count: usize = 0; - for(text) |rune| { - if (rune == symbol) count += 1; - } - return count; -} -pub fn countLines (text: []const u8) usize { - return countNewLinesSymbols(text) + 1; -} -pub fn countNewLinesSymbols (text: []const u8) usize { - var num: usize = 0; - for (text) |rune| { - if (rune == '\n') {num += 1;} - } - return num; -} - -pub fn cutIndents (comptime TT: type, text: TT) !TT { - if (text.len == 0) unreachable; - - // cut from left - var start: usize = 0; - while(true) { - if (start >= text.len) return error.TextIsEmpty; - const rune = text[start]; - if (rune != ' ') {break;} - start += 1; - } - - // cut from right - var end: usize = text.len - 1; - while(true) { - const rune = text[end]; - if (rune != ' ') {break;} - end -= 1; - } - - return text[start .. end + 1]; -} -pub fn u64FromCharsDec (text: []const u8) error{NotNumber, Unexpected,}!u64 { - const MAX_LEN = "18446744073709551615".len; // UINT64_MAX - if (text.len > MAX_LEN) return error.Unexpected; - var result: u64 = 0; - var numerical_place: usize = 1; - var pos: usize = text.len - 1; // last symbol - while(true) { - const value: usize = switch(text[pos]) { - '0' => 0, - '1' => 1, - '2' => 2, - '3' => 3, - '4' => 4, - '5' => 5, - '6' => 6, - '7' => 7, - '8' => 8, - '9' => 9, - else => return error.NotNumber, - }; - result += value * numerical_place; - if (pos == 0) return result; - numerical_place *= 10; - pos -= 1; - } -} -pub fn u8ToSlice (num: *u8) []u8 { - return @ptrCast([1]u8, num)[0..1]; -} -pub fn isLetter (rune: u8) bool { - switch(rune) { - ' ', '\t', '\\', - '+', '-', '/', '*', '^', - '(', ')', '[', ']', '{', '}', '<', '>', - '?', '!', '@', '#', '$', '%', '&','|', - ';', ':', '"', '\'', - ',', '.' - => {return false;}, - else => {return true;}, - } -} -// todo -// delete parseToLines -// create find function. - -// deprecated -pub fn parseToLines (text: []const u8, allocator: std.mem.Allocator) ![]const []const u8 { - const nl_count = countSymbol(text, '\n'); - - // get lines - const lines = try allocator.alloc([]const u8, nl_count + 1); - var iter = splitByRune(text, '\n'); - for (lines) |*one| { - const line = iter.next() orelse break; - one.* = line; - } - - // do not forget allocator.free(lines.ptr) after use; - return lines[0..]; -} DELETED src/help.txt Index: src/help.txt ================================================================== --- src/help.txt +++ /dev/null @@ -1,63 +0,0 @@ -This is ScalpiEditor - "heirarhy" text editor. - -for open existing file just write file name as argument: -$ ScalpiEditor "~/.bashrc" - -main key bindings { - exit [Ctrl] + [q] or [F10] - save [Ctrl] + [s] - move cursour: just use arrows -} -folding { - parse from brackets [Ctrl] + [e] - parse from indent [Ctrl] + [r] - unparse [Ctrl] + [u] - enter block [Tab] - leave block [Esc] -} -navigation { - go to start of line [Home] or [Ctrl] + [Shift] + [Left] - go to end of line [End] or [Ctrl] + [Shift] + [Right] - go to first line [Ctrl] + [Up] - go to last line [Ctrl] + [Down] - go to line from number [Ctrl] + [g] - go to left word [Ctrl] + [Left] - go to right word [Ctrl] + [Right] -} -edit { - insert symbol [any symbol] - new line / divide line [Enter] - delete prev char [BackSpace] - delete next char [Del] - clear line [Shift] + [Del] - cut [Ctrl] + [x] - duplicate [Ctrl] + [c] - paste [Ctrl] + [v] - move line down [Alt] + [Down] - move line up [Alt] + [Up] - join lines [Ctrl] + [j] -} -clipboard.txt { - copy [Ctrl] + [y] - paste [Ctrl] + [p] -} -mark { - mark [Alt] + [m] - jump to mark [Alt] + [j] -} -indent { - auto fix indent: [Ctrl] + [o] // not ctrl+i becouse its TAB on ansi... - remove indent: [alt] + [o] -} -to support me: monero { - 87T7 qGbA TrM3 a6Br - DyeC jQQf NWtU u3iZ - bHVB MC6W mEbN NE13 - Qrrt KhBb e4vF 58NR - 8PTF dYk2 Sozc HexX - 4Q69 jbdQ Asrs P7B -} -not implemented yet { - select left symbol [Shift] + [Left] - select right symbol [Shift] + [Right] -} DELETED src/main.zig Index: src/main.zig ================================================================== --- src/main.zig +++ /dev/null @@ -1,76 +0,0 @@ -// TODO delete Console.writeAll and MORE test programm on freezes :( - -const G = @import("root"); -const T = @This(); - -pub const std = @import("std"); -pub const out = std.io.getStdOut().writer(); - -// libs -pub const lib = @import("external/lib/src/lib.zig"); -pub const textLib = @import("external/textLib/src/textLib.zig"); -pub const LinkedList = @import("external/LinkedList/src/LinkedList.zig"); -pub const Tree = @import("external/Tree/src/Tree.zig"); -pub const Console = @import("external/Console/src/Console.zig"); -pub const lba = @import("external/linkedBufferedAllocator.zig"); -pub const ScalpiEditor = @import("ScalpiEditor.zig"); -pub const ansi = Console.ansi; -pub const Coor2u = lib.Coor2u; - -pub var console: Console = .{}; -pub var editor: *ScalpiEditor = undefined; -pub var arena: std.mem.Allocator = undefined; - - -pub fn main () !void { - try out.writeAll(" - - - - - - - - - - - - - - \r\n"); - - // console init - try G.console.init(); - defer {G.console.deInit() catch unreachable;} - - // console flags - var system_flags = G.Console.Flags.init(); - defer system_flags.apply(); - var flags = G.Console.Flags.init(); - flags.setCanonicalMode(false); - flags.apply(); - - // arena init - var arena_allocator = std.heap.ArenaAllocator.init(std.heap.c_allocator); - defer arena_allocator.deinit(); - arena = arena_allocator.allocator(); - - // editor init - editor = try arena.create(ScalpiEditor); - try editor.init(); - defer {editor.deinit() catch unreachable;} - - parse_args: { // work with arguments - var argIterator = G.std.process.ArgIteratorPosix.init(); - _ = argIterator.skip(); // skip name of programm - - // first arg: file name - const file_name: []const u8 = argIterator.next() orelse break: parse_args; - var text: []const u8 = undefined; - if (G.lib.fileRead(arena, file_name)) |data| {text = data;} - else |err| switch (err) { - error.FileIsEmpty => {text = "";}, - else => { - try out.writeAll(" File not exist or blocked by system.\r\n"); - try out.writeAll(" ScalpiEditor does not create files itself.\r\n"); - try out.writeAll(" You can create file with \"touch\" command:\r\n"); - try out.writeAll(" touch file_name\r\n"); - try out.writeAll("\r\n"); - return; - }, - } - editor.view.init(file_name, text) catch return error.ViewNotInit; - - // second arg: line number - const number_as_text: []const u8 = argIterator.next() orelse break: parse_args; - const number = try textLib.u64FromCharsDec(number_as_text); - editor.view.goToLineFromNumber(number); - } - while(try editor.do()) {} -} DELETED src/main.zig.bak Index: src/main.zig.bak ================================================================== --- src/main.zig.bak +++ /dev/null @@ -1,69 +0,0 @@ -// TODO delete Console.writeAll and MORE test programm on freezes :( - -const G = @import("root"); -const T = @This(); - -pub const std = @import("std"); -pub const out = std.io.getStdOut().writer(); - -// libs -pub const lib = @import("external/lib/src/lib.zig"); -pub const textLib = @import("external/textLib/src/textLib.zig"); -pub const LinkedList = @import("external/LinkedList/src/LinkedList.zig"); -pub const Tree = @import("external/Tree/src/Tree.zig"); -pub const Console = @import("external/Console/src/Console.zig"); -pub const lba = @import("external/linkedBufferedAllocator.zig"); -pub const ScalpiEditor = @import("ScalpiEditor.zig"); -pub const ansi = Console.ansi; -pub const Coor2u = lib.Coor2u; - -pub var console: Console = .{}; -pub var editor: *ScalpiEditor = undefined; -pub var arena: std.mem.Allocator = undefined; - - -pub fn main () !void { - try out.writeAll(" - - - - - - - - - - - - - - \r\n"); - - // console init - try G.console.init(); - defer {G.console.deInit() catch unreachable;} - - // arena init - var arena_allocator = std.heap.ArenaAllocator.init(std.heap.c_allocator); - defer arena_allocator.deinit(); - arena = arena_allocator.allocator(); - - // editor init - editor = try arena.create(ScalpiEditor); - try editor.init(); - defer {editor.deinit() catch unreachable;} - - parse_args: { // work with arguments - var argIterator = G.std.process.ArgIteratorPosix.init(); - _ = argIterator.skip(); // skip name of programm - - // first arg: file name - const file_name: []const u8 = argIterator.next() orelse break: parse_args; - var text: []const u8 = undefined; - if (G.lib.fileRead(arena, file_name)) |data| {text = data;} - else |err| switch (err) { - error.FileIsEmpty => {text = "";}, - else => { - try out.writeAll(" File not exist or blocked by system.\r\n"); - try out.writeAll(" ScalpiEditor does not create files itself.\r\n"); - try out.writeAll(" You can create file with \"touch\" command:\r\n"); - try out.writeAll(" touch file_name\r\n"); - try out.writeAll("\r\n"); - return; - }, - } - editor.view.init(file_name, text) catch return error.ViewNotInit; - - // second arg: line number - const number_as_text: []const u8 = argIterator.next() orelse break: parse_args; - const number = try textLib.u64FromCharsDec(number_as_text); - editor.view.goToLineFromNumber(number); - } - while(try editor.do()) {} -}