Fix file permissions
This commit is contained in:
Executable → Regular
Executable → Regular
Executable → Regular
@@ -20,7 +20,7 @@ CFLAGS_DEBUG :=\
|
|||||||
-O0 -fno-inline -gsplit-dwarf \
|
-O0 -fno-inline -gsplit-dwarf \
|
||||||
-g -fno-omit-frame-pointer \
|
-g -fno-omit-frame-pointer \
|
||||||
-Wno-unused-command-line-argument \
|
-Wno-unused-command-line-argument \
|
||||||
-I./include -I./libs -I/home/syed/main/crib/libs/mruby/include
|
-I./include -I./libs -I./libs/mruby/include
|
||||||
|
|
||||||
# C_SANITIZER := -fsanitize=address
|
# C_SANITIZER := -fsanitize=address
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ CFLAGS_RELEASE :=\
|
|||||||
-fomit-frame-pointer -DNDEBUG -s \
|
-fomit-frame-pointer -DNDEBUG -s \
|
||||||
-mllvm -vectorize-loops \
|
-mllvm -vectorize-loops \
|
||||||
-Wno-unused-command-line-argument \
|
-Wno-unused-command-line-argument \
|
||||||
-I./include -I./libs -I/home/syed/main/crib/libs/mruby/include
|
-I./include -I./libs -I./libs/mruby/include
|
||||||
|
|
||||||
PCH_CFLAGS_DEBUG := $(CFLAGS_DEBUG) -x c++-header
|
PCH_CFLAGS_DEBUG := $(CFLAGS_DEBUG) -x c++-header
|
||||||
PCH_CFLAGS_RELEASE := $(CFLAGS_RELEASE) -x c++-header
|
PCH_CFLAGS_RELEASE := $(CFLAGS_RELEASE) -x c++-header
|
||||||
|
|||||||
@@ -2,33 +2,42 @@ Copyright 2025 Syed Daanish
|
|||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
|
- Fix bug where scroll up at top of screen first line jumps to bottom
|
||||||
|
|
||||||
|
- Make completions work with new system
|
||||||
- And factorize renderer into its own class
|
- And factorize renderer into its own class
|
||||||
- which is just managed by the renderer
|
- which is just managed by the renderer
|
||||||
- and adjusment.cc will call it
|
- and adjusment.cc will call it
|
||||||
- which is reused by scrollers/ensurers too (for knowing screen wrapped end)
|
- which is reused by scrollers/ensurers too (for knowing screen wrapped end)
|
||||||
- this will then allow inlay hints to be possible
|
- this will then allow inlay hints to be possible
|
||||||
- and also make VAI easier to implement
|
- and also make VAI easier to implement (probably as inlay hints)
|
||||||
|
- and also allow code lens to work too
|
||||||
|
- and an api to allow line skipping / virtual text which allows for folding logic as extention
|
||||||
|
|
||||||
|
- Also time extentions and disable if they take too long / for larger files with options to force
|
||||||
|
|
||||||
* Allow keybinds to be set in ruby
|
* Allow keybinds to be set in ruby
|
||||||
|
|
||||||
* ruby file for project specific runs alongside any system wide ones
|
* ruby file for project specific runs alongside any system wide ones
|
||||||
|
|
||||||
- Seperate system functions into a class that branches to support local / ssh / server modes.
|
- Seperate system functions into a class that branches to support local / ssh / server modes.
|
||||||
- Even lsp shouldnt be directly controlled because it can branch on local and server modes
|
- Even lsp shouldnt be directly controlled because it can branch on local and server modes
|
||||||
- check libssh2 or child process stuff for remote editing (remote mode)
|
- check libssh2 or child process stuff for remote editing (remote mode)
|
||||||
- Thick and thin mode (server mode) (through ssh or port) (for website only port + webhook)
|
- Thick and thin mode (server mode) (through ssh or port) (for website only port + webhook)
|
||||||
- thin mode only shares screen diffing over the network - uses server settings / themes / shell
|
- thin mode only shares screen diffing over the network - uses server settings / themes / shell
|
||||||
- only one user connects at a time
|
- only one user connects at a time
|
||||||
- provides data as a websocket with tui or gui/online modes where tui shares diffing as is (can be connected to by gui or website)
|
- provides data as a websocket with tui or gui/online modes where tui shares diffing as is (can be connected to by gui or website)
|
||||||
- and gui/online modes try to (if not then render onto a canvas) forward window.render_gui() and dedicated windowing system (i.e windowing is html divs)
|
- and gui/online modes try to (if not then render onto a canvas) forward window.render_gui() and dedicated windowing system (i.e windowing is html divs)
|
||||||
- and window.render_gui() returns a markup code (custom markup)
|
- and window.render_gui() returns a markup code (custom markup)
|
||||||
- and for events i could either leave tui as-is and for markup have special event handling or i
|
- and for events i could either leave tui as-is and for markup have special event handling or i
|
||||||
- implement the widget system in both and have the same event handling then
|
- implement the widget system in both and have the same event handling then
|
||||||
- actually for true cross platform i need to make a ui lib with widgets etc. so it is workable on all platforms (so they all need only a single ui lib)
|
- actually for true cross platform i need to make a ui lib with widgets etc. so it is workable on all platforms (so they all need only a single ui lib)
|
||||||
- thick only shared fileio and lsp data with local used for all else - uses local settings / themes
|
- thick only shared fileio and lsp data with local used for all else - uses local settings / themes
|
||||||
- multiple users connect at once but maybe either make them not be allowed to open same file or make vscode like multiediting (unsure how exactly)
|
- multiple users connect at once but maybe either make them not be allowed to open same file or make vscode like multiediting (unsure how exactly)
|
||||||
- they all share same lsp instances
|
- they all share same lsp instances
|
||||||
- they all have the same shell access
|
- they all have the same shell access
|
||||||
- allow having an instance that forwards thick mode to thin mode (to connect online mode to a thick server for code collaboration)
|
- allow having an instance that forwards thick mode to thin mode (to connect online mode to a thick server for code collaboration)
|
||||||
|
|
||||||
* Then allow ruby code to create and handle windows as extentions
|
* Then allow ruby code to create and handle windows as extentions
|
||||||
* Then 3 inbuilt extentions being file manager, theme picker, tab selector
|
* Then 3 inbuilt extentions being file manager, theme picker, tab selector
|
||||||
|
|
||||||
@@ -37,8 +46,8 @@ Copyright 2025 Syed Daanish
|
|||||||
* also implement info strings for all the stuff that take focus
|
* also implement info strings for all the stuff that take focus
|
||||||
|
|
||||||
* Mode is a feild on a editor and there is no global "mode system" except in editors (enxtentions do their own thing)
|
* Mode is a feild on a editor and there is no global "mode system" except in editors (enxtentions do their own thing)
|
||||||
* make mode normal and not atomic if it is truly unused across threads
|
- make mode normal and not atomic if it is truly unused across threads
|
||||||
* this means keybinds can be set to use the editor as insert mode only and so behave like vscode
|
- this means keybinds can be set to use the editor as insert mode only and so behave like vscode
|
||||||
|
|
||||||
* split lsp stuff into multiple files (not a monolithic class as it is now)
|
* split lsp stuff into multiple files (not a monolithic class as it is now)
|
||||||
* Extentions can also be used as file openers (for like databases . diffing . images . audio etc)
|
* Extentions can also be used as file openers (for like databases . diffing . images . audio etc)
|
||||||
@@ -59,10 +68,10 @@ Copyright 2025 Syed Daanish
|
|||||||
* Add a file picker suggestion while typing a path (including stuff like ~ and .. and $HOME etc)
|
* Add a file picker suggestion while typing a path (including stuff like ~ and .. and $HOME etc)
|
||||||
* allow opening directory after filemanger is sorted out.
|
* allow opening directory after filemanger is sorted out.
|
||||||
* commands to:
|
* commands to:
|
||||||
change pwd
|
change pwd
|
||||||
load a rb file
|
load a rb file
|
||||||
run a ruby command
|
run a ruby command
|
||||||
close a window etc.
|
close a window etc.
|
||||||
* [ ] Add mgems for most common things and a ruby library to allow combining true ruby with mruby
|
* [ ] Add mgems for most common things and a ruby library to allow combining true ruby with mruby
|
||||||
* add command to set and use a file type at runtime
|
* add command to set and use a file type at runtime
|
||||||
* [ ] color alpha in ini files
|
* [ ] color alpha in ini files
|
||||||
@@ -70,12 +79,12 @@ Copyright 2025 Syed Daanish
|
|||||||
* [ ] **LSP Bug:** Check why `fish-lsp` is behaving so off with completions filtering.
|
* [ ] **LSP Bug:** Check why `fish-lsp` is behaving so off with completions filtering.
|
||||||
* [ ] **Line move:** fix the move line functions to work without the calculations from folds as folds are removed.
|
* [ ] **Line move:** fix the move line functions to work without the calculations from folds as folds are removed.
|
||||||
* [ ] **Editor Indentation Fix:** - Main : merger indentation with the parser for more accurate results.
|
* [ ] **Editor Indentation Fix:** - Main : merger indentation with the parser for more accurate results.
|
||||||
* [ ] Ignore comments/strings from parser when auto-indenting.
|
- [ ] Ignore comments/strings from parser when auto-indenting.
|
||||||
* [ ] Support for stuff like bash \ and math operators in other languages and comma and line starting with a dot (like in ruby)
|
- [ ] Support for stuff like bash \ and math operators in other languages and comma and line starting with a dot (like in ruby)
|
||||||
etc.
|
etc.
|
||||||
* [ ] **Readme:** Update readme to show ruby based config in detail.
|
* [ ] **Readme:** Update readme to show ruby based config in detail.
|
||||||
* [ ] **UI Refinement:**
|
* [ ] **UI Refinement:**
|
||||||
* [ ] Finish autocomplete box style functions.
|
- [ ] Finish autocomplete box style functions.
|
||||||
* [ ] **Documentation UI:** Capture `Ctrl+h` / `Ctrl+l` for scrolling documentation windows.
|
* [ ] **Documentation UI:** Capture `Ctrl+h` / `Ctrl+l` for scrolling documentation windows.
|
||||||
* Cap line_tree data limit for large files and just store about a thousand previous lines maybe? (lazily loaded)
|
* Cap line_tree data limit for large files and just store about a thousand previous lines maybe? (lazily loaded)
|
||||||
|
|
||||||
@@ -88,17 +97,17 @@ Copyright 2025 Syed Daanish
|
|||||||
* allow flushing functions in ruby to tell c++ to refresh keybinds/themes etc.
|
* allow flushing functions in ruby to tell c++ to refresh keybinds/themes etc.
|
||||||
|
|
||||||
* [ ] **LSP:**
|
* [ ] **LSP:**
|
||||||
support snippets in completion properly
|
support snippets in completion properly
|
||||||
check::
|
check::
|
||||||
pull diagnostics for ruby-lsp
|
pull diagnostics for ruby-lsp
|
||||||
lsp selection range - use to highlight start / end of range maybe?
|
lsp selection range - use to highlight start / end of range maybe?
|
||||||
goto definiton
|
goto definiton
|
||||||
signature help
|
signature help
|
||||||
document symbol for the top bar maybe? (or workspace symbol)
|
document symbol for the top bar maybe? (or workspace symbol)
|
||||||
also setup workspaces
|
also setup workspaces
|
||||||
Semantic highlighting
|
Semantic highlighting
|
||||||
Quick fixes
|
Quick fixes
|
||||||
Rename symbols
|
Rename symbols
|
||||||
|
|
||||||
* Allow ruby to config lsp capabilities
|
* Allow ruby to config lsp capabilities
|
||||||
|
|
||||||
@@ -122,49 +131,45 @@ Copyright 2025 Syed Daanish
|
|||||||
|
|
||||||
### UX
|
### UX
|
||||||
|
|
||||||
* [ ] **Completion Filtering:**
|
- [ ] **Completion Filtering:**
|
||||||
* [ ] Stop filtering case-sensitive.
|
- [ ] Stop filtering case-sensitive.
|
||||||
* [ ] Normalize completion edits if local filtering is used.
|
- [ ] Normalize completion edits if local filtering is used.
|
||||||
|
|
||||||
* [ ] **Basic Autocomplete:** Keep a list of words in the current buffer for non-LSP fallback.
|
- [ ] **Basic Autocomplete:** Keep a list of words in the current buffer for non-LSP fallback.
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* [ ] **Search & Replace:**
|
- [ ] **Search & Replace:**
|
||||||
* [ ] Add Search/Replace UI.
|
- [ ] Add Search/Replace UI.
|
||||||
* [ ] Support capture groups (`$1`, `$2`) or allow Perl regex directly.
|
- [ ] Support capture groups (`$1`, `$2`) or allow Perl regex directly.
|
||||||
* [ ] Ensure virtual cursors are included in search positions.
|
- [ ] Ensure virtual cursors are included in search positions.
|
||||||
|
|
||||||
* [ ] **Multi-Cursor:**
|
- [ ] **Multi-Cursor:**
|
||||||
* [ ] Add virtual cursor support (edits apply to all locations).
|
- [ ] Add virtual cursor support (edits apply to all locations).
|
||||||
* [ ] Add `Alt+Click` to set multiple cursors.
|
- [ ] Add `Alt+Click` to set multiple cursors.
|
||||||
* [ ] Allow search and place cursor at all matches.
|
- [ ] Allow search and place cursor at all matches.
|
||||||
|
|
||||||
* [ ] **Block Selection:**
|
- [ ] **Block Selection:**
|
||||||
* [ ] Double-clicking a bracket selects the whole block and sets mode to `WORD`.
|
- [ ] Double-clicking a bracket selects the whole block and sets mode to `WORD`.
|
||||||
|
|
||||||
### Visuals, UI & Extensions?
|
### Visuals, UI & Extensions?
|
||||||
|
|
||||||
* [ ] Add color picker/palette (as a floating extention).
|
- [ ] Add color picker/palette (as a floating extention).
|
||||||
|
|
||||||
* [ ] **Git:** Add Git integration (status, diffs).
|
- [ ] **Git:** Add Git integration (status, diffs).
|
||||||
* [ ] **AI/Snippets:**
|
- [ ] **AI/Snippets:**
|
||||||
* [ ] Add snippets support (LuaSnip/VSnip style).
|
- [ ] Add snippets support (LuaSnip/VSnip style).
|
||||||
* [ ] Add Codeium/Copilot support (using VAI virtual text) as a test phase.
|
- [ ] Add Codeium/Copilot support (using VAI virtual text) as a test phase.
|
||||||
|
|
||||||
* [ ] **SQL:** Add SQL support (Viewer and Basic Editor) (as ruby extension).
|
|
||||||
* [ ] **Prolly?:** Add Splash Screen / Minigame.
|
|
||||||
|
|
||||||
|
- [ ] **SQL:** Add SQL support (Viewer and Basic Editor) (as ruby extension).
|
||||||
|
- [ ] **Prolly?:** Add Splash Screen / Minigame.
|
||||||
|
|
||||||
### Unimportant optimizations
|
### Unimportant optimizations
|
||||||
|
|
||||||
* [ ] **Performance:**
|
- [ ] **Performance:**
|
||||||
* [ ] Switch JSON parser to `RapidJSON` (or similar high-performance lib).
|
- [ ] Switch JSON parser to `RapidJSON` (or similar high-performance lib).
|
||||||
* [ ] Decrease usage of `std::string` in UI, LSP, warnings etc.
|
- [ ] Decrease usage of `std::string` in UI, LSP, warnings etc.
|
||||||
* [ ] Also for vectors into managed memory especially for completions/lsp-stuff.
|
- [ ] Also for vectors into managed memory especially for completions/lsp-stuff.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- The pits of hell: -->
|
<!-- The pits of hell: -->
|
||||||
<!-- * Replace perfectly working superfast rope with a structure that stores for small files everything -->
|
<!-- * Replace perfectly working superfast rope with a structure that stores for small files everything -->
|
||||||
@@ -173,3 +178,59 @@ Copyright 2025 Syed Daanish
|
|||||||
<!-- - also for the line mode still go through entire file to get and store line offsets -->
|
<!-- - also for the line mode still go through entire file to get and store line offsets -->
|
||||||
<!-- - also it stores everything prolly still as rope tho (rope of lines) (or sparse map) -->
|
<!-- - also it stores everything prolly still as rope tho (rope of lines) (or sparse map) -->
|
||||||
<!-- - it stores the line text as-is which is only unicode / crlf normalized during usage -->
|
<!-- - it stores the line text as-is which is only unicode / crlf normalized during usage -->
|
||||||
|
|
||||||
|
whyy is visible returnint x1,y2 and x2, 2y2 instead of x1,y1 and x2,y2
|
||||||
|
|
||||||
|
Render H: 1, Cursor: 0,0, Visible: 0,26 - 0,52
|
||||||
|
Render H: 2, Cursor: 0,0, Visible: 1,0 - 1,0
|
||||||
|
Render H: 3, Cursor: 0,0, Visible: 2,30 - 2,60
|
||||||
|
Render H: 4, Cursor: 0,0, Visible: 3,36 - 3,72
|
||||||
|
Render H: 5, Cursor: 0,0, Visible: 4,32 - 4,64
|
||||||
|
Render H: 6, Cursor: 0,0, Visible: 5,40 - 5,80
|
||||||
|
Render H: 7, Cursor: 0,0, Visible: 6,11 - 6,22
|
||||||
|
Render H: 8, Cursor: 0,0, Visible: 7,3 - 7,6
|
||||||
|
Render H: 9, Cursor: 0,0, Visible: 8,19 - 8,38
|
||||||
|
Render H: 10, Cursor: 0,0, Visible: 9,76 - 9,152
|
||||||
|
Render H: 11, Cursor: 0,0, Visible: 10,50 - 10,100
|
||||||
|
Render H: 12, Cursor: 0,0, Visible: 11,29 - 11,58
|
||||||
|
Render H: 13, Cursor: 0,0, Visible: 12,49 - 12,98
|
||||||
|
Render H: 14, Cursor: 0,0, Visible: 13,32 - 13,64
|
||||||
|
Render H: 15, Cursor: 0,0, Visible: 14,30 - 14,60
|
||||||
|
Render H: 16, Cursor: 0,0, Visible: 15,56 - 15,112
|
||||||
|
Render H: 17, Cursor: 0,0, Visible: 16,42 - 16,84
|
||||||
|
Render H: 18, Cursor: 0,0, Visible: 17,20 - 17,40
|
||||||
|
Render H: 19, Cursor: 0,0, Visible: 18,31 - 18,62
|
||||||
|
Render H: 20, Cursor: 0,0, Visible: 19,77 - 19,154
|
||||||
|
Render H: 21, Cursor: 0,0, Visible: 20,77 - 20,154
|
||||||
|
Render H: 22, Cursor: 0,0, Visible: 21,44 - 21,88
|
||||||
|
Render H: 23, Cursor: 0,0, Visible: 22,56 - 22,112
|
||||||
|
Render H: 24, Cursor: 0,0, Visible: 23,13 - 23,26
|
||||||
|
Render H: 25, Cursor: 0,0, Visible: 24,3 - 24,6
|
||||||
|
Render H: 26, Cursor: 0,0, Visible: 25,24 - 25,48
|
||||||
|
Render H: 27, Cursor: 0,0, Visible: 26,32 - 26,64
|
||||||
|
Render H: 28, Cursor: 0,0, Visible: 27,38 - 27,76
|
||||||
|
Render H: 29, Cursor: 0,0, Visible: 28,1 - 28,2
|
||||||
|
Render H: 30, Cursor: 0,0, Visible: 29,0 - 29,0
|
||||||
|
Render H: 31, Cursor: 0,0, Visible: 30,30 - 30,60
|
||||||
|
Render H: 32, Cursor: 0,0, Visible: 31,19 - 31,38
|
||||||
|
Render H: 33, Cursor: 0,0, Visible: 32,76 - 32,152
|
||||||
|
Render H: 34, Cursor: 0,0, Visible: 33,50 - 33,100
|
||||||
|
Render H: 35, Cursor: 0,0, Visible: 34,36 - 34,72
|
||||||
|
Render H: 36, Cursor: 0,0, Visible: 35,66 - 35,132
|
||||||
|
Render H: 37, Cursor: 0,0, Visible: 36,12 - 36,24
|
||||||
|
Render H: 38, Cursor: 0,0, Visible: 37,13 - 37,26
|
||||||
|
Render H: 39, Cursor: 0,0, Visible: 38,17 - 38,34
|
||||||
|
Render H: 40, Cursor: 0,0, Visible: 39,37 - 39,74
|
||||||
|
Render H: 41, Cursor: 0,0, Visible: 40,16 - 40,32
|
||||||
|
Render H: 42, Cursor: 0,0, Visible: 41,23 - 41,46
|
||||||
|
Render H: 43, Cursor: 0,0, Visible: 42,15 - 42,30
|
||||||
|
Render H: 44, Cursor: 0,0, Visible: 43,13 - 43,26
|
||||||
|
Render H: 45, Cursor: 0,0, Visible: 44,5 - 44,10
|
||||||
|
Render H: 46, Cursor: 0,0, Visible: 45,41 - 45,82
|
||||||
|
Render H: 47, Cursor: 0,0, Visible: 46,12 - 46,24
|
||||||
|
Render H: 48, Cursor: 0,0, Visible: 47,22 - 47,44
|
||||||
|
Render H: 49, Cursor: 0,0, Visible: 48,24 - 48,48
|
||||||
|
Render H: 50, Cursor: 0,0, Visible: 49,28 - 49,56
|
||||||
|
Render H: 51, Cursor: 0,0, Visible: 50,26 - 50,52
|
||||||
|
Render H: 52, Cursor: 0,0, Visible: 51,20 - 51,40
|
||||||
|
Render H: 53, Cursor: 0,0, Visible: 52,74 - 52,148
|
||||||
|
|||||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
+5
@@ -1,6 +1,7 @@
|
|||||||
#ifndef EDITOR_H
|
#ifndef EDITOR_H
|
||||||
#define EDITOR_H
|
#define EDITOR_H
|
||||||
|
|
||||||
|
#include "editor/decl.h"
|
||||||
#include "editor/hooks.h"
|
#include "editor/hooks.h"
|
||||||
#include "editor/indents.h"
|
#include "editor/indents.h"
|
||||||
#include "editor/visual.h"
|
#include "editor/visual.h"
|
||||||
@@ -101,6 +102,10 @@ struct Editor : Window {
|
|||||||
void lsp_handle(json msg);
|
void lsp_handle(json msg);
|
||||||
void apply_lsp_edits(std::vector<TextEdit> edits, bool move);
|
void apply_lsp_edits(std::vector<TextEdit> edits, bool move);
|
||||||
|
|
||||||
|
// Not used by core editor, but can be used by
|
||||||
|
// extentions (due to cursor movement complexity)
|
||||||
|
void format_full(int version);
|
||||||
|
|
||||||
Coord move_left(Coord cursor, uint32_t number);
|
Coord move_left(Coord cursor, uint32_t number);
|
||||||
Coord move_right(Coord cursor, uint32_t number);
|
Coord move_right(Coord cursor, uint32_t number);
|
||||||
|
|
||||||
|
|||||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
+19
-9
@@ -1,10 +1,11 @@
|
|||||||
#ifndef EDITOR_COMPLETIONS_H
|
#ifndef EXTENTION_COMPLETION_H
|
||||||
#define EDITOR_COMPLETIONS_H
|
#define EXTENTION_COMPLETION_H
|
||||||
|
|
||||||
|
#include "editor/decl.h"
|
||||||
|
#include "io/sysio.h"
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "ui/completionbox.h"
|
|
||||||
#include "ui/hover.h"
|
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
|
#include "windows/decl.h"
|
||||||
|
|
||||||
struct CompletionItem {
|
struct CompletionItem {
|
||||||
std::string label;
|
std::string label;
|
||||||
@@ -22,12 +23,19 @@ struct CompletionItem {
|
|||||||
std::vector<char> end_chars;
|
std::vector<char> end_chars;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CompletionBox : Popup {
|
||||||
|
struct CompletionSession *session;
|
||||||
|
CompletionBox() { this->hidden = true; }
|
||||||
|
void render(std::vector<ScreenCell> &buffer, Coord size, Coord pos) override;
|
||||||
|
void handle_click(KeyEvent, Coord) override { this->hidden = true; }
|
||||||
|
~CompletionBox() {}
|
||||||
|
};
|
||||||
|
|
||||||
struct CompletionSession {
|
struct CompletionSession {
|
||||||
struct Editor *editor;
|
struct Editor *editor;
|
||||||
std::shared_mutex mtx;
|
std::shared_mutex mtx;
|
||||||
bool active = false;
|
bool active = false;
|
||||||
Coord hook;
|
Coord hook;
|
||||||
std::optional<std::string> prefix;
|
|
||||||
uint32_t select = 0;
|
uint32_t select = 0;
|
||||||
uint32_t scroll = 0;
|
uint32_t scroll = 0;
|
||||||
std::vector<CompletionItem> items;
|
std::vector<CompletionItem> items;
|
||||||
@@ -35,14 +43,12 @@ struct CompletionSession {
|
|||||||
bool complete = true;
|
bool complete = true;
|
||||||
std::optional<char> trigger_char;
|
std::optional<char> trigger_char;
|
||||||
uint8_t trigger = 0;
|
uint8_t trigger = 0;
|
||||||
CompletionBox box;
|
CompletionBox *box = nullptr;
|
||||||
HoverBox hover;
|
|
||||||
uint32_t doc = UINT32_MAX;
|
uint32_t doc = UINT32_MAX;
|
||||||
std::atomic<bool> hover_dirty = false;
|
std::atomic<bool> hover_dirty = false;
|
||||||
int version;
|
int version;
|
||||||
|
|
||||||
CompletionSession(Editor *editor) : editor(editor), box(this) {}
|
CompletionSession(Editor *editor) : editor(editor) {}
|
||||||
|
|
||||||
void resolve_doc();
|
void resolve_doc();
|
||||||
void accept();
|
void accept();
|
||||||
void next();
|
void next();
|
||||||
@@ -51,4 +57,8 @@ struct CompletionSession {
|
|||||||
void handle(KeyEvent event);
|
void handle(KeyEvent event);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CompletionBox *init_completion_box(CompletionSession *session);
|
||||||
|
void completion_request(Editor *editor);
|
||||||
|
void completion_filter(Editor *editor);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
@@ -1,21 +0,0 @@
|
|||||||
// #ifndef UI_COMPLETIONBOX_H
|
|
||||||
// #define UI_COMPLETIONBOX_H
|
|
||||||
//
|
|
||||||
// #include "io/sysio.h"
|
|
||||||
// #include "pch.h"
|
|
||||||
// #include "utils/utils.h"
|
|
||||||
//
|
|
||||||
// struct CompletionBox {
|
|
||||||
// std::shared_mutex mtx;
|
|
||||||
// struct CompletionSession *session;
|
|
||||||
// bool hidden = true;
|
|
||||||
// std::vector<ScreenCell> cells;
|
|
||||||
// Coord size;
|
|
||||||
// Coord position;
|
|
||||||
//
|
|
||||||
// CompletionBox(CompletionSession *s) : session(s) {}
|
|
||||||
// void render_update();
|
|
||||||
// void render(Coord pos);
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// #endif
|
|
||||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
+4
-1
@@ -17,7 +17,10 @@ void Editor::ensure_cursor() {
|
|||||||
render_height < this->size.row) {
|
render_height < this->size.row) {
|
||||||
render_height++;
|
render_height++;
|
||||||
last_visible = vline.first;
|
last_visible = vline.first;
|
||||||
if (cursor >= vline.first && cursor < vline.second)
|
log("Render H: %d, Cursor: %d,%d, Visible: %d,%d - %d,%d", render_height,
|
||||||
|
this->cursor.row, this->cursor.col, vline.first.row, vline.first.col,
|
||||||
|
vline.second.row, vline.second.col);
|
||||||
|
if (cursor >= vline.first && cursor <= vline.second)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cursor = last_visible;
|
cursor = last_visible;
|
||||||
|
|||||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
+456
-458
@@ -1,458 +1,456 @@
|
|||||||
// #include "editor/decl.h"
|
/* #include "editor/editor.h"
|
||||||
// #include "editor/editor.h"
|
#include "io/knot.h"
|
||||||
// #include "io/knot.h"
|
#include "io/sysio.h"
|
||||||
// #include "io/sysio.h"
|
#include "main.h"
|
||||||
// #include "lsp/lsp.h"
|
#include "ui/completionbox.h"
|
||||||
// #include "main.h"
|
#include "utils/utils.h"
|
||||||
// #include "ui/completionbox.h"
|
|
||||||
// #include "utils/utils.h"
|
inline static std::string completion_prefix(Editor *editor) {
|
||||||
//
|
Coord hook = editor->completion.hook;
|
||||||
// inline static std::string completion_prefix(Editor *editor) {
|
Coord cur = editor->cursor;
|
||||||
// Coord hook = editor->completion.hook;
|
if (hook.row != cur.row || cur.col < hook.col)
|
||||||
// Coord cur = editor->cursor;
|
return "";
|
||||||
// if (hook.row != cur.row || cur.col < hook.col)
|
LineIterator *it = begin_l_iter(editor->root, hook.row);
|
||||||
// return "";
|
uint32_t line_len;
|
||||||
// LineIterator *it = begin_l_iter(editor->root, hook.row);
|
char *line = next_line(it, &line_len);
|
||||||
// uint32_t line_len;
|
if (!line) {
|
||||||
// char *line = next_line(it, &line_len);
|
free(it->buffer);
|
||||||
// if (!line) {
|
free(it);
|
||||||
// free(it->buffer);
|
return "";
|
||||||
// free(it);
|
}
|
||||||
// return "";
|
std::string prefix(line + hook.col, cur.col - hook.col);
|
||||||
// }
|
free(it->buffer);
|
||||||
// std::string prefix(line + hook.col, cur.col - hook.col);
|
free(it);
|
||||||
// free(it->buffer);
|
return prefix;
|
||||||
// free(it);
|
}
|
||||||
// return prefix;
|
|
||||||
// }
|
inline static void completion_adjust_scroll(CompletionSession &s) {
|
||||||
//
|
if (s.visible.empty())
|
||||||
// inline static void completion_adjust_scroll(CompletionSession &s) {
|
return;
|
||||||
// if (s.visible.empty())
|
int vi = -1;
|
||||||
// return;
|
for (size_t i = 0; i < s.visible.size(); i++)
|
||||||
// int vi = -1;
|
if (s.visible[i] == s.select) {
|
||||||
// for (size_t i = 0; i < s.visible.size(); i++)
|
vi = (int)i;
|
||||||
// if (s.visible[i] == s.select) {
|
break;
|
||||||
// vi = (int)i;
|
}
|
||||||
// break;
|
if (vi < 0)
|
||||||
// }
|
return;
|
||||||
// if (vi < 0)
|
if ((uint32_t)vi < s.scroll)
|
||||||
// return;
|
s.scroll = vi;
|
||||||
// if ((uint32_t)vi < s.scroll)
|
else if ((uint32_t)vi >= s.scroll + 8)
|
||||||
// s.scroll = vi;
|
s.scroll = vi - 7;
|
||||||
// else if ((uint32_t)vi >= s.scroll + 8)
|
}
|
||||||
// s.scroll = vi - 7;
|
|
||||||
// }
|
void completion_filter(Editor *editor) {
|
||||||
//
|
auto &session = editor->completion;
|
||||||
// void completion_filter(Editor *editor) {
|
std::string prefix = completion_prefix(editor);
|
||||||
// auto &session = editor->completion;
|
session.visible.clear();
|
||||||
// std::string prefix = completion_prefix(editor);
|
for (size_t i = 0; i < session.items.size(); ++i) {
|
||||||
// session.visible.clear();
|
const auto &item = session.items[i];
|
||||||
// for (size_t i = 0; i < session.items.size(); ++i) {
|
const std::string &key = item.filter;
|
||||||
// const auto &item = session.items[i];
|
if (key.size() >= prefix.size() &&
|
||||||
// const std::string &key = item.filter;
|
key.compare(0, prefix.size(), prefix) == 0)
|
||||||
// if (key.size() >= prefix.size() &&
|
session.visible.push_back(i);
|
||||||
// key.compare(0, prefix.size(), prefix) == 0)
|
}
|
||||||
// session.visible.push_back(i);
|
if (session.visible.empty()) {
|
||||||
// }
|
session.box.hidden = true;
|
||||||
// if (session.visible.empty()) {
|
return;
|
||||||
// session.box.hidden = true;
|
}
|
||||||
// return;
|
if (std::find(session.visible.begin(), session.visible.end(),
|
||||||
// }
|
session.select) == session.visible.end())
|
||||||
// if (std::find(session.visible.begin(), session.visible.end(),
|
session.select = session.visible[0];
|
||||||
// session.select) == session.visible.end())
|
session.box.hidden = false;
|
||||||
// session.select = session.visible[0];
|
session.scroll = 0;
|
||||||
// session.box.hidden = false;
|
completion_adjust_scroll(session);
|
||||||
// session.scroll = 0;
|
session.box.render_update();
|
||||||
// completion_adjust_scroll(session);
|
}
|
||||||
// session.box.render_update();
|
|
||||||
// }
|
void completion_request(Editor *editor) {
|
||||||
//
|
Coord hook = editor->cursor;
|
||||||
// void completion_request(Editor *editor) {
|
editor->word_boundaries(editor->cursor, &hook.col, nullptr, nullptr,
|
||||||
// Coord hook = editor->cursor;
|
nullptr); editor->completion.hook = hook; editor->completion.complete =
|
||||||
// editor->word_boundaries(editor->cursor, &hook.col, nullptr, nullptr,
|
false; editor->completion.active = false; editor->completion.items.clear();
|
||||||
// nullptr); editor->completion.hook = hook; editor->completion.complete =
|
editor->completion.visible.clear();
|
||||||
// false; editor->completion.active = false; editor->completion.items.clear();
|
editor->completion.select = 0;
|
||||||
// editor->completion.visible.clear();
|
editor->completion.version = editor->lsp_version;
|
||||||
// editor->completion.select = 0;
|
LSPPending *pending = new LSPPending();
|
||||||
// editor->completion.version = editor->lsp_version;
|
pending->editor = editor;
|
||||||
// LSPPending *pending = new LSPPending();
|
pending->callback = [](Editor *editor, const json &message) {
|
||||||
// pending->editor = editor;
|
auto &session = editor->completion;
|
||||||
// pending->callback = [](Editor *editor, const json &message) {
|
std::unique_lock lock(session.mtx);
|
||||||
// auto &session = editor->completion;
|
std::vector<json> items_json;
|
||||||
// std::unique_lock lock(session.mtx);
|
std::vector<char> end_chars_def;
|
||||||
// std::vector<json> items_json;
|
int insert_text_format = 1;
|
||||||
// std::vector<char> end_chars_def;
|
int insert_text_mode = 1;
|
||||||
// int insert_text_format = 1;
|
if (message.contains("result")) {
|
||||||
// int insert_text_mode = 1;
|
auto &result = message["result"];
|
||||||
// if (message.contains("result")) {
|
if (result.is_array()) {
|
||||||
// auto &result = message["result"];
|
items_json = result.get<std::vector<json>>();
|
||||||
// if (result.is_array()) {
|
session.complete = true;
|
||||||
// items_json = result.get<std::vector<json>>();
|
if (items_json.empty())
|
||||||
// session.complete = true;
|
return;
|
||||||
// if (items_json.empty())
|
editor->completion.active = true;
|
||||||
// return;
|
} else if (result.is_object() && result.contains("items")) {
|
||||||
// editor->completion.active = true;
|
auto &list = result;
|
||||||
// } else if (result.is_object() && result.contains("items")) {
|
items_json = list["items"].get<std::vector<json>>();
|
||||||
// auto &list = result;
|
if (items_json.empty())
|
||||||
// items_json = list["items"].get<std::vector<json>>();
|
return;
|
||||||
// if (items_json.empty())
|
editor->completion.active = true;
|
||||||
// return;
|
session.complete = !list.value("isIncomplete", false);
|
||||||
// editor->completion.active = true;
|
if (list.contains("itemDefaults") &&
|
||||||
// session.complete = !list.value("isIncomplete", false);
|
list["itemDefaults"].is_object()) {
|
||||||
// if (list.contains("itemDefaults") &&
|
auto &defs = list["itemDefaults"];
|
||||||
// list["itemDefaults"].is_object()) {
|
if (defs.contains("insertTextFormat") &&
|
||||||
// auto &defs = list["itemDefaults"];
|
defs["insertTextFormat"].is_number())
|
||||||
// if (defs.contains("insertTextFormat") &&
|
insert_text_format = defs["insertTextFormat"].get<int>();
|
||||||
// defs["insertTextFormat"].is_number())
|
if (defs.contains("insertTextMode") &&
|
||||||
// insert_text_format = defs["insertTextFormat"].get<int>();
|
defs["insertTextMode"].is_number())
|
||||||
// if (defs.contains("insertTextMode") &&
|
insert_text_mode = defs["insertTextMode"].get<int>();
|
||||||
// defs["insertTextMode"].is_number())
|
if (defs.contains("textEdit"))
|
||||||
// insert_text_mode = defs["insertTextMode"].get<int>();
|
if (defs["textEdit"].is_array())
|
||||||
// if (defs.contains("textEdit"))
|
for (auto &c : defs["textEdit"]) {
|
||||||
// if (defs["textEdit"].is_array())
|
if (!c.is_string())
|
||||||
// for (auto &c : defs["textEdit"]) {
|
continue;
|
||||||
// if (!c.is_string())
|
std::string str = c.get<std::string>();
|
||||||
// continue;
|
if (str.size() != 1)
|
||||||
// std::string str = c.get<std::string>();
|
continue;
|
||||||
// if (str.size() != 1)
|
end_chars_def.push_back(str[0]);
|
||||||
// continue;
|
}
|
||||||
// end_chars_def.push_back(str[0]);
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
session.items.reserve(items_json.size() + 1);
|
||||||
// }
|
session.visible.reserve(items_json.size() + 1);
|
||||||
// session.items.reserve(items_json.size() + 1);
|
for (auto &item_json : items_json) {
|
||||||
// session.visible.reserve(items_json.size() + 1);
|
CompletionItem item;
|
||||||
// for (auto &item_json : items_json) {
|
item.original = item_json;
|
||||||
// CompletionItem item;
|
item.label = item_json.value("label", "");
|
||||||
// item.original = item_json;
|
item.kind = item_json.value("kind", 0);
|
||||||
// item.label = item_json.value("label", "");
|
if (item_json.contains("detail") && item_json["detail"].is_string())
|
||||||
// item.kind = item_json.value("kind", 0);
|
item.detail = item_json["detail"].get<std::string>();
|
||||||
// if (item_json.contains("detail") && item_json["detail"].is_string())
|
if (item_json.contains("documentation")) {
|
||||||
// item.detail = item_json["detail"].get<std::string>();
|
if (item_json["documentation"].is_string()) {
|
||||||
// if (item_json.contains("documentation")) {
|
item.documentation = item_json["documentation"].get<std::string>();
|
||||||
// if (item_json["documentation"].is_string()) {
|
} else if (item_json["documentation"].contains("value") &&
|
||||||
// item.documentation = item_json["documentation"].get<std::string>();
|
item_json["documentation"]["value"].is_string()) {
|
||||||
// } else if (item_json["documentation"].contains("value") &&
|
item.is_markup =
|
||||||
// item_json["documentation"]["value"].is_string()) {
|
item_json["documentation"]["kind"].get<std::string>() ==
|
||||||
// item.is_markup =
|
"markdown";
|
||||||
// item_json["documentation"]["kind"].get<std::string>() ==
|
std::string documentation =
|
||||||
// "markdown";
|
item_json["documentation"]["value"].get<std::string>();
|
||||||
// std::string documentation =
|
if (documentation.size() > 1024)
|
||||||
// item_json["documentation"]["value"].get<std::string>();
|
item.is_markup = false;
|
||||||
// if (documentation.size() > 1024)
|
if (item.is_markup) {
|
||||||
// item.is_markup = false;
|
item.documentation =
|
||||||
// if (item.is_markup) {
|
substitute_fence(documentation, editor->lang.name);
|
||||||
// item.documentation =
|
} else {
|
||||||
// substitute_fence(documentation, editor->lang.name);
|
item.documentation = documentation;
|
||||||
// } else {
|
}
|
||||||
// item.documentation = documentation;
|
}
|
||||||
// }
|
}
|
||||||
// }
|
if (item_json.contains("deprecated") &&
|
||||||
// }
|
item_json["deprecated"].is_boolean())
|
||||||
// if (item_json.contains("deprecated") &&
|
item.deprecated = item_json["deprecated"].get<bool>();
|
||||||
// item_json["deprecated"].is_boolean())
|
auto tags = item_json.value("tags", std::vector<int>());
|
||||||
// item.deprecated = item_json["deprecated"].get<bool>();
|
for (auto tag : tags)
|
||||||
// auto tags = item_json.value("tags", std::vector<int>());
|
if (tag == 1)
|
||||||
// for (auto tag : tags)
|
item.deprecated = true;
|
||||||
// if (tag == 1)
|
item.sort = item_json.value("sortText", item.label);
|
||||||
// item.deprecated = true;
|
item.filter = item_json.value("filterText", item.label);
|
||||||
// item.sort = item_json.value("sortText", item.label);
|
if (item_json.contains("preselect") &&
|
||||||
// item.filter = item_json.value("filterText", item.label);
|
item_json["preselect"].is_boolean() &&
|
||||||
// if (item_json.contains("preselect") &&
|
item_json["preselect"].get<bool>())
|
||||||
// item_json["preselect"].is_boolean() &&
|
session.select = session.items.size() - 1;
|
||||||
// item_json["preselect"].get<bool>())
|
TextEdit edit;
|
||||||
// session.select = session.items.size() - 1;
|
if (item_json.contains("textEdit")) {
|
||||||
// TextEdit edit;
|
auto &te = item_json["textEdit"];
|
||||||
// if (item_json.contains("textEdit")) {
|
if (te.contains("newText")) {
|
||||||
// auto &te = item_json["textEdit"];
|
edit.text = te.value("newText", "");
|
||||||
// if (te.contains("newText")) {
|
if (te.contains("replace")) {
|
||||||
// edit.text = te.value("newText", "");
|
edit.start.row = te["replace"]["start"]["line"];
|
||||||
// if (te.contains("replace")) {
|
edit.start.col = te["replace"]["start"]["character"];
|
||||||
// edit.start.row = te["replace"]["start"]["line"];
|
edit.end.row = te["replace"]["end"]["line"];
|
||||||
// edit.start.col = te["replace"]["start"]["character"];
|
edit.end.col = te["replace"]["end"]["character"];
|
||||||
// edit.end.row = te["replace"]["end"]["line"];
|
} else if (te.contains("insert")) {
|
||||||
// edit.end.col = te["replace"]["end"]["character"];
|
edit.start.row = te["insert"]["start"]["line"];
|
||||||
// } else if (te.contains("insert")) {
|
edit.start.col = te["insert"]["start"]["character"];
|
||||||
// edit.start.row = te["insert"]["start"]["line"];
|
edit.end.row = te["insert"]["end"]["line"];
|
||||||
// edit.start.col = te["insert"]["start"]["character"];
|
edit.end.col = te["insert"]["end"]["character"];
|
||||||
// edit.end.row = te["insert"]["end"]["line"];
|
} else if (te.contains("range")) {
|
||||||
// edit.end.col = te["insert"]["end"]["character"];
|
edit.start.row = te["range"]["start"]["line"];
|
||||||
// } else if (te.contains("range")) {
|
edit.start.col = te["range"]["start"]["character"];
|
||||||
// edit.start.row = te["range"]["start"]["line"];
|
edit.end.row = te["range"]["end"]["line"];
|
||||||
// edit.start.col = te["range"]["start"]["character"];
|
edit.end.col = te["range"]["end"]["character"];
|
||||||
// edit.end.row = te["range"]["end"]["line"];
|
} else {
|
||||||
// edit.end.col = te["range"]["end"]["character"];
|
edit.start = session.hook;
|
||||||
// } else {
|
edit.end = editor->cursor;
|
||||||
// edit.start = session.hook;
|
}
|
||||||
// edit.end = editor->cursor;
|
}
|
||||||
// }
|
} else if (item_json.contains("insertText") &&
|
||||||
// }
|
item_json["insertText"].is_string()) {
|
||||||
// } else if (item_json.contains("insertText") &&
|
edit.text = item_json["insertText"].get<std::string>();
|
||||||
// item_json["insertText"].is_string()) {
|
edit.start = session.hook;
|
||||||
// edit.text = item_json["insertText"].get<std::string>();
|
edit.end = editor->cursor;
|
||||||
// edit.start = session.hook;
|
} else {
|
||||||
// edit.end = editor->cursor;
|
edit.text = item.label;
|
||||||
// } else {
|
edit.start = session.hook;
|
||||||
// edit.text = item.label;
|
edit.end = editor->cursor;
|
||||||
// edit.start = session.hook;
|
}
|
||||||
// edit.end = editor->cursor;
|
editor->utf8_normalize_edit(&edit);
|
||||||
// }
|
item.edits.push_back(edit);
|
||||||
// editor->utf8_normalize_edit(&edit);
|
if (item_json.contains("additionalTextEdits")) {
|
||||||
// item.edits.push_back(edit);
|
for (auto &te : item_json["additionalTextEdits"]) {
|
||||||
// if (item_json.contains("additionalTextEdits")) {
|
TextEdit edit;
|
||||||
// for (auto &te : item_json["additionalTextEdits"]) {
|
edit.text = te.value("newText", "");
|
||||||
// TextEdit edit;
|
edit.start.row = te["range"]["start"]["line"];
|
||||||
// edit.text = te.value("newText", "");
|
edit.start.col = te["range"]["start"]["character"];
|
||||||
// edit.start.row = te["range"]["start"]["line"];
|
edit.end.row = te["range"]["end"]["line"];
|
||||||
// edit.start.col = te["range"]["start"]["character"];
|
edit.end.col = te["range"]["end"]["character"];
|
||||||
// edit.end.row = te["range"]["end"]["line"];
|
editor->utf8_normalize_edit(&edit);
|
||||||
// edit.end.col = te["range"]["end"]["character"];
|
item.edits.push_back(edit);
|
||||||
// editor->utf8_normalize_edit(&edit);
|
}
|
||||||
// item.edits.push_back(edit);
|
}
|
||||||
// }
|
item.snippet = insert_text_format == 2;
|
||||||
// }
|
if (item_json.contains("insertTextFormat"))
|
||||||
// item.snippet = insert_text_format == 2;
|
item.snippet = item_json["insertTextFormat"].get<int>() == 2;
|
||||||
// if (item_json.contains("insertTextFormat"))
|
if (item_json.contains("insertTextMode"))
|
||||||
// item.snippet = item_json["insertTextFormat"].get<int>() == 2;
|
item.asis = item_json["insertTextMode"].get<int>() == 1;
|
||||||
// if (item_json.contains("insertTextMode"))
|
if (item_json.contains("commitCharacters"))
|
||||||
// item.asis = item_json["insertTextMode"].get<int>() == 1;
|
for (auto &c : item_json["commitCharacters"])
|
||||||
// if (item_json.contains("commitCharacters"))
|
if (c.is_string() && c.get<std::string>().size() == 1)
|
||||||
// for (auto &c : item_json["commitCharacters"])
|
item.end_chars.push_back(c.get<std::string>()[0]);
|
||||||
// if (c.is_string() && c.get<std::string>().size() == 1)
|
session.items.push_back(std::move(item));
|
||||||
// item.end_chars.push_back(c.get<std::string>()[0]);
|
session.visible.push_back(session.items.size() - 1);
|
||||||
// session.items.push_back(std::move(item));
|
}
|
||||||
// session.visible.push_back(session.items.size() - 1);
|
session.box.hidden = false;
|
||||||
// }
|
session.box.render_update();
|
||||||
// session.box.hidden = false;
|
};
|
||||||
// session.box.render_update();
|
LineIterator *it = begin_l_iter(editor->root, hook.row);
|
||||||
// };
|
uint32_t length;
|
||||||
// LineIterator *it = begin_l_iter(editor->root, hook.row);
|
char *line = next_line(it, &length);
|
||||||
// uint32_t length;
|
if (!line) {
|
||||||
// char *line = next_line(it, &length);
|
free(it->buffer);
|
||||||
// if (!line) {
|
free(it);
|
||||||
// free(it->buffer);
|
return;
|
||||||
// free(it);
|
}
|
||||||
// return;
|
uint32_t col = utf8_offset_to_utf16(line, length, editor->cursor.col);
|
||||||
// }
|
free(it->buffer);
|
||||||
// uint32_t col = utf8_offset_to_utf16(line, length, editor->cursor.col);
|
free(it);
|
||||||
// free(it->buffer);
|
json message = {
|
||||||
// free(it);
|
{"jsonrpc", "2.0"},
|
||||||
// json message = {
|
{"method", "textDocument/completion"},
|
||||||
// {"jsonrpc", "2.0"},
|
{"params",
|
||||||
// {"method", "textDocument/completion"},
|
{{"textDocument", {{"uri", editor->uri}}},
|
||||||
// {"params",
|
{"position", {{"line", editor->cursor.row}, {"character", col}}}}}};
|
||||||
// {{"textDocument", {{"uri", editor->uri}}},
|
if (editor->completion.trigger > 0) {
|
||||||
// {"position", {{"line", editor->cursor.row}, {"character", col}}}}}};
|
json context = {{"triggerKind", editor->completion.trigger}};
|
||||||
// if (editor->completion.trigger > 0) {
|
if (editor->completion.trigger == 2 && editor->completion.trigger_char)
|
||||||
// json context = {{"triggerKind", editor->completion.trigger}};
|
context["triggerCharacter"] =
|
||||||
// if (editor->completion.trigger == 2 && editor->completion.trigger_char)
|
std::string(1, *editor->completion.trigger_char);
|
||||||
// context["triggerCharacter"] =
|
message["params"]["context"] = context;
|
||||||
// std::string(1, *editor->completion.trigger_char);
|
}
|
||||||
// message["params"]["context"] = context;
|
lsp_send(editor->lsp, message, pending);
|
||||||
// }
|
}
|
||||||
// lsp_send(editor->lsp, message, pending);
|
|
||||||
// }
|
Move this into the box and merge the box and this guy
|
||||||
//
|
void CompletionSession::handle(KeyEvent event) {
|
||||||
// // Move this into the box and merge the box and this guy
|
if (!editor->lsp || !editor->lsp->allow_completion)
|
||||||
// void CompletionSession::handle(KeyEvent event) {
|
return;
|
||||||
// if (!editor->lsp || !editor->lsp->allow_completion)
|
if (mode != INSERT) {
|
||||||
// return;
|
this->active = false;
|
||||||
// if (mode != INSERT) {
|
return;
|
||||||
// this->active = false;
|
}
|
||||||
// return;
|
std::unique_lock lock(this->mtx);
|
||||||
// }
|
if (event.key_type == KEY_PASTE) {
|
||||||
// std::unique_lock lock(this->mtx);
|
this->active = false;
|
||||||
// if (event.key_type == KEY_PASTE) {
|
return;
|
||||||
// this->active = false;
|
} else if (event.key_type == KEY_CHAR) {
|
||||||
// return;
|
char ch = *event.c;
|
||||||
// } else if (event.key_type == KEY_CHAR) {
|
if (!this->active) {
|
||||||
// char ch = *event.c;
|
for (char c : editor->lsp->trigger_chars)
|
||||||
// if (!this->active) {
|
if (c == ch) {
|
||||||
// for (char c : editor->lsp->trigger_chars)
|
this->trigger = 2;
|
||||||
// if (c == ch) {
|
this->trigger_char = c;
|
||||||
// this->trigger = 2;
|
completion_request(editor);
|
||||||
// this->trigger_char = c;
|
return;
|
||||||
// completion_request(editor);
|
}
|
||||||
// return;
|
} else {
|
||||||
// }
|
if (!editor->completion.items.empty()) {
|
||||||
// } else {
|
const auto &item =
|
||||||
// if (!editor->completion.items.empty()) {
|
editor->completion.items[editor->completion.select]; const
|
||||||
// const auto &item =
|
std::vector<char> &end_chars =
|
||||||
// editor->completion.items[editor->completion.select]; const
|
item.end_chars.empty() ? editor->lsp->end_chars : item.end_chars;
|
||||||
// std::vector<char> &end_chars =
|
for (char c : end_chars)
|
||||||
// item.end_chars.empty() ? editor->lsp->end_chars : item.end_chars;
|
if (c == ch) {
|
||||||
// for (char c : end_chars)
|
this->accept();
|
||||||
// if (c == ch) {
|
return;
|
||||||
// this->accept();
|
}
|
||||||
// return;
|
}
|
||||||
// }
|
}
|
||||||
// }
|
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
|
||||||
// }
|
(ch >= '0' && ch <= '9') || ch == '_') {
|
||||||
// if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
|
if (this->active) {
|
||||||
// (ch >= '0' && ch <= '9') || ch == '_') {
|
if (this->complete)
|
||||||
// if (this->active) {
|
completion_filter(editor);
|
||||||
// if (this->complete)
|
else
|
||||||
// completion_filter(editor);
|
completion_request(editor);
|
||||||
// else
|
} else {
|
||||||
// completion_request(editor);
|
this->trigger = 3;
|
||||||
// } else {
|
completion_request(editor);
|
||||||
// this->trigger = 3;
|
}
|
||||||
// completion_request(editor);
|
} else if (ch == CTRL('\\')) {
|
||||||
// }
|
if (this->active && !this->visible.empty()) {
|
||||||
// } else if (ch == CTRL('\\')) {
|
this->accept();
|
||||||
// if (this->active && !this->visible.empty()) {
|
} else {
|
||||||
// this->accept();
|
this->trigger = 1;
|
||||||
// } else {
|
completion_request(editor);
|
||||||
// this->trigger = 1;
|
}
|
||||||
// completion_request(editor);
|
} else if (ch == CTRL('p')) {
|
||||||
// }
|
if (this->active)
|
||||||
// } else if (ch == CTRL('p')) {
|
this->next();
|
||||||
// if (this->active)
|
} else if (ch == CTRL('o')) {
|
||||||
// this->next();
|
if (this->active)
|
||||||
// } else if (ch == CTRL('o')) {
|
this->prev();
|
||||||
// if (this->active)
|
} else if (ch == 0x7F || ch == 0x08 || ch == CTRL('W')) {
|
||||||
// this->prev();
|
if (this->active) {
|
||||||
// } else if (ch == 0x7F || ch == 0x08 || ch == CTRL('W')) {
|
if (this->complete) {
|
||||||
// if (this->active) {
|
if (editor->cursor <= this->hook)
|
||||||
// if (this->complete) {
|
this->active = false;
|
||||||
// if (editor->cursor <= this->hook)
|
else
|
||||||
// this->active = false;
|
completion_filter(editor);
|
||||||
// else
|
} else {
|
||||||
// completion_filter(editor);
|
if (editor->cursor <= this->hook)
|
||||||
// } else {
|
this->active = false;
|
||||||
// if (editor->cursor <= this->hook)
|
else
|
||||||
// this->active = false;
|
completion_request(editor);
|
||||||
// else
|
}
|
||||||
// completion_request(editor);
|
}
|
||||||
// }
|
} else {
|
||||||
// }
|
this->active = false;
|
||||||
// } else {
|
}
|
||||||
// this->active = false;
|
} else if (event.key_type == KEY_MOUSE && event.mouse_modifier == 0) {
|
||||||
// }
|
Prolly add mouse support here
|
||||||
// } else if (event.key_type == KEY_MOUSE && event.mouse_modifier == 0) {
|
auto &box = this->box;
|
||||||
// // Prolly add mouse support here
|
if (event.mouse_y >= box.position.row &&
|
||||||
// // auto &box = this->box;
|
event.mouse_x >= box.position.col) {
|
||||||
// // if (event.mouse_y >= box.position.row &&
|
uint32_t row = event.mouse_y - box.position.row;
|
||||||
// // event.mouse_x >= box.position.col) {
|
uint32_t col = event.mouse_x - box.position.col;
|
||||||
// // uint32_t row = event.mouse_y - box.position.row;
|
if (row < box.size.row && col < box.size.col) {
|
||||||
// // uint32_t col = event.mouse_x - box.position.col;
|
uint8_t idx = 0;
|
||||||
// // if (row < box.size.row && col < box.size.col) {
|
complete_select(editor, idx);
|
||||||
// // uint8_t idx = 0;
|
}
|
||||||
// // /* TODO: fix index relative to scroll */
|
}
|
||||||
// // complete_select(editor, idx);
|
if it is being implemented then stop main event handler from
|
||||||
// // }
|
processing
|
||||||
// // }
|
when click inside the box
|
||||||
// // if it is being implemented then stop main event handler from
|
this->active = false;
|
||||||
// processing
|
} else {
|
||||||
// // when click inside the box
|
this->active = false;
|
||||||
// this->active = false;
|
}
|
||||||
// } else {
|
}
|
||||||
// this->active = false;
|
|
||||||
// }
|
void CompletionSession::resolve_doc() {
|
||||||
// }
|
auto &item = this->items[this->select];
|
||||||
//
|
if (item.documentation)
|
||||||
// void CompletionSession::resolve_doc() {
|
return;
|
||||||
// auto &item = this->items[this->select];
|
item.documentation = "";
|
||||||
// if (item.documentation)
|
LSPPending *pending = new LSPPending();
|
||||||
// return;
|
pending->editor = editor;
|
||||||
// item.documentation = "";
|
pending->callback = [](Editor *editor, const json &message) {
|
||||||
// LSPPending *pending = new LSPPending();
|
std::unique_lock lock(editor->completion.mtx);
|
||||||
// pending->editor = editor;
|
auto &item = editor->completion.items[editor->completion.select];
|
||||||
// pending->callback = [](Editor *editor, const json &message) {
|
if (message["result"].contains("documentation")) {
|
||||||
// std::unique_lock lock(editor->completion.mtx);
|
if (message["result"]["documentation"].is_string()) {
|
||||||
// auto &item = editor->completion.items[editor->completion.select];
|
item.documentation =
|
||||||
// if (message["result"].contains("documentation")) {
|
message["result"]["documentation"].get<std::string>();
|
||||||
// if (message["result"]["documentation"].is_string()) {
|
} else if (message["result"]["documentation"].contains("value") &&
|
||||||
// item.documentation =
|
message["result"]["documentation"]["value"].is_string()) {
|
||||||
// message["result"]["documentation"].get<std::string>();
|
item.is_markup =
|
||||||
// } else if (message["result"]["documentation"].contains("value") &&
|
message["result"]["documentation"]["kind"].get<std::string>() ==
|
||||||
// message["result"]["documentation"]["value"].is_string()) {
|
"markdown";
|
||||||
// item.is_markup =
|
std::string documentation =
|
||||||
// message["result"]["documentation"]["kind"].get<std::string>() ==
|
message["result"]["documentation"]["value"].get<std::string>();
|
||||||
// "markdown";
|
if (documentation.size() > 1024)
|
||||||
// std::string documentation =
|
item.is_markup = false;
|
||||||
// message["result"]["documentation"]["value"].get<std::string>();
|
if (item.is_markup) {
|
||||||
// if (documentation.size() > 1024)
|
item.documentation =
|
||||||
// item.is_markup = false;
|
substitute_fence(documentation, editor->lang.name);
|
||||||
// if (item.is_markup) {
|
} else {
|
||||||
// item.documentation =
|
item.documentation = documentation;
|
||||||
// substitute_fence(documentation, editor->lang.name);
|
}
|
||||||
// } else {
|
}
|
||||||
// item.documentation = documentation;
|
}
|
||||||
// }
|
editor->completion.box.render_update();
|
||||||
// }
|
};
|
||||||
// }
|
json message = {{"jsonrpc", "2.0"},
|
||||||
// editor->completion.box.render_update();
|
{"method", "completionItem/resolve"},
|
||||||
// };
|
{"params", item.original}};
|
||||||
// json message = {{"jsonrpc", "2.0"},
|
lsp_send(editor->lsp, message, pending);
|
||||||
// {"method", "completionItem/resolve"},
|
}
|
||||||
// {"params", item.original}};
|
|
||||||
// lsp_send(editor->lsp, message, pending);
|
void CompletionSession::accept() {
|
||||||
// }
|
if (!this->active || this->box.hidden)
|
||||||
//
|
return;
|
||||||
// void CompletionSession::accept() {
|
auto &item = this->items[this->select];
|
||||||
// if (!this->active || this->box.hidden)
|
TODO: support snippets and asis here
|
||||||
// return;
|
once indentation engine is implemented
|
||||||
// auto &item = this->items[this->select];
|
if (this->version != editor->lsp_version) {
|
||||||
// // TODO: support snippets and asis here
|
int delta_col = 0;
|
||||||
// // once indentation engine is implemented
|
TextEdit &e = item.edits[0];
|
||||||
// if (this->version != editor->lsp_version) {
|
if (e.end.row == editor->cursor.row) {
|
||||||
// int delta_col = 0;
|
delta_col = editor->cursor.col - e.end.col;
|
||||||
// TextEdit &e = item.edits[0];
|
e.end.col = editor->cursor.col;
|
||||||
// if (e.end.row == editor->cursor.row) {
|
for (size_t i = 1; i < item.edits.size(); ++i) {
|
||||||
// delta_col = editor->cursor.col - e.end.col;
|
TextEdit &e = item.edits[i];
|
||||||
// e.end.col = editor->cursor.col;
|
if (e.start.row == editor->cursor.row) {
|
||||||
// for (size_t i = 1; i < item.edits.size(); ++i) {
|
e.start.col += delta_col;
|
||||||
// TextEdit &e = item.edits[i];
|
if (e.end.row == editor->cursor.row)
|
||||||
// if (e.start.row == editor->cursor.row) {
|
e.end.col += delta_col;
|
||||||
// e.start.col += delta_col;
|
}
|
||||||
// if (e.end.row == editor->cursor.row)
|
}
|
||||||
// e.end.col += delta_col;
|
}
|
||||||
// }
|
}
|
||||||
// }
|
editor->apply_lsp_edits(item.edits, true);
|
||||||
// }
|
this->active = false;
|
||||||
// }
|
}
|
||||||
// editor->apply_lsp_edits(item.edits, true);
|
|
||||||
// this->active = false;
|
inline static int visible_index(const CompletionSession &s) {
|
||||||
// }
|
for (size_t i = 0; i < s.visible.size(); ++i)
|
||||||
//
|
if (s.visible[i] == s.select)
|
||||||
// inline static int visible_index(const CompletionSession &s) {
|
return (int)i;
|
||||||
// for (size_t i = 0; i < s.visible.size(); ++i)
|
return -1;
|
||||||
// if (s.visible[i] == s.select)
|
}
|
||||||
// return (int)i;
|
|
||||||
// return -1;
|
void CompletionSession::next() {
|
||||||
// }
|
if (!this->active || this->box.hidden || this->visible.empty())
|
||||||
//
|
return;
|
||||||
// void CompletionSession::next() {
|
int vi = visible_index(*this);
|
||||||
// if (!this->active || this->box.hidden || this->visible.empty())
|
if (vi < 0)
|
||||||
// return;
|
vi = 0;
|
||||||
// int vi = visible_index(*this);
|
else
|
||||||
// if (vi < 0)
|
vi = (vi + 1) % this->visible.size();
|
||||||
// vi = 0;
|
this->select = this->visible[vi];
|
||||||
// else
|
this->resolve_doc();
|
||||||
// vi = (vi + 1) % this->visible.size();
|
completion_adjust_scroll(*this);
|
||||||
// this->select = this->visible[vi];
|
this->box.render_update();
|
||||||
// this->resolve_doc();
|
}
|
||||||
// completion_adjust_scroll(*this);
|
|
||||||
// this->box.render_update();
|
void CompletionSession::prev() {
|
||||||
// }
|
if (!this->active || this->box.hidden || this->visible.empty())
|
||||||
//
|
return;
|
||||||
// void CompletionSession::prev() {
|
int vi = visible_index(*this);
|
||||||
// if (!this->active || this->box.hidden || this->visible.empty())
|
if (vi < 0)
|
||||||
// return;
|
vi = 0;
|
||||||
// int vi = visible_index(*this);
|
else
|
||||||
// if (vi < 0)
|
vi = (vi + this->visible.size() - 1) % this->visible.size();
|
||||||
// vi = 0;
|
this->select = this->visible[vi];
|
||||||
// else
|
this->resolve_doc();
|
||||||
// vi = (vi + this->visible.size() - 1) % this->visible.size();
|
completion_adjust_scroll(*this);
|
||||||
// this->select = this->visible[vi];
|
this->box.render_update();
|
||||||
// this->resolve_doc();
|
}
|
||||||
// completion_adjust_scroll(*this);
|
|
||||||
// this->box.render_update();
|
void CompletionSession::choose(uint8_t index) {
|
||||||
// }
|
this->select = index;
|
||||||
//
|
this->accept();
|
||||||
// void CompletionSession::choose(uint8_t index) {
|
}
|
||||||
// this->select = index;
|
*/
|
||||||
// this->accept();
|
|
||||||
// }
|
|
||||||
Executable → Regular
Executable → Regular
Executable → Regular
-68
@@ -1,5 +1,4 @@
|
|||||||
#include "editor/editor.h"
|
#include "editor/editor.h"
|
||||||
#include "editor/decl.h"
|
|
||||||
#include "lsp/lsp.h"
|
#include "lsp/lsp.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "syntax/langs.h"
|
#include "syntax/langs.h"
|
||||||
@@ -58,7 +57,6 @@ Editor::~Editor() {
|
|||||||
void Editor::save() {
|
void Editor::save() {
|
||||||
if (!this->root)
|
if (!this->root)
|
||||||
return;
|
return;
|
||||||
int version = this->lsp_version;
|
|
||||||
uint32_t char_count = this->root->char_count;
|
uint32_t char_count = this->root->char_count;
|
||||||
char *str = read(this->root, 0, char_count);
|
char *str = read(this->root, 0, char_count);
|
||||||
if (!str)
|
if (!str)
|
||||||
@@ -77,70 +75,4 @@ void Editor::save() {
|
|||||||
free(str);
|
free(str);
|
||||||
ui::bar.log("Written " + std::to_string(char_count) + " bytes to " +
|
ui::bar.log("Written " + std::to_string(char_count) + " bytes to " +
|
||||||
this->filename);
|
this->filename);
|
||||||
auto lsp = this->lsp.load();
|
|
||||||
if (lsp) {
|
|
||||||
log("Saving %s", this->filename.c_str());
|
|
||||||
auto message = std::make_unique<LSPMessage>();
|
|
||||||
message->message = {{"method", "textDocument/didSave"},
|
|
||||||
{"params", {{"textDocument", {{"uri", this->uri}}}}}};
|
|
||||||
lsp->send(std::move(message));
|
|
||||||
if (lsp->allow_formatting) {
|
|
||||||
log("Formatting %s", this->filename.c_str());
|
|
||||||
json s_msg = {{"method", "textDocument/formatting"},
|
|
||||||
{"params",
|
|
||||||
{{"textDocument", {{"uri", this->uri}}},
|
|
||||||
{"options",
|
|
||||||
{{"tabSize", 2},
|
|
||||||
{"insertSpaces", true},
|
|
||||||
{"trimTrailingWhitespace", true},
|
|
||||||
{"trimFinalNewlines", true}}}}}};
|
|
||||||
auto save_msg = std::make_unique<LSPMessage>();
|
|
||||||
save_msg->editor = this;
|
|
||||||
save_msg->message = s_msg;
|
|
||||||
save_msg->callback = [s_msg, version](const LSPMessage &msg) {
|
|
||||||
log("Formattin");
|
|
||||||
if (version != msg.editor->lsp_version)
|
|
||||||
return;
|
|
||||||
auto &edits = msg.message["result"];
|
|
||||||
if (edits.is_array()) {
|
|
||||||
std::vector<TextEdit> t_edits;
|
|
||||||
t_edits.reserve(edits.size());
|
|
||||||
for (auto &edit : edits) {
|
|
||||||
TextEdit t_edit;
|
|
||||||
t_edit.text = edit.value("newText", "");
|
|
||||||
t_edit.start.row = edit["range"]["start"]["line"];
|
|
||||||
t_edit.start.col = edit["range"]["start"]["character"];
|
|
||||||
t_edit.end.row = edit["range"]["end"]["line"];
|
|
||||||
t_edit.end.col = edit["range"]["end"]["character"];
|
|
||||||
msg.editor->utf8_normalize_edit(&t_edit);
|
|
||||||
t_edits.push_back(t_edit);
|
|
||||||
}
|
|
||||||
msg.editor->apply_lsp_edits(t_edits, false);
|
|
||||||
msg.editor->ensure_cursor();
|
|
||||||
uint32_t char_count = msg.editor->root->char_count;
|
|
||||||
char *str = read(msg.editor->root, 0, char_count);
|
|
||||||
if (!str)
|
|
||||||
return;
|
|
||||||
std::ofstream out(msg.editor->filename);
|
|
||||||
if (!msg.editor->unix_eol) {
|
|
||||||
for (uint32_t i = 0; i < char_count; ++i) {
|
|
||||||
if (str[i] == '\n')
|
|
||||||
out.put('\r');
|
|
||||||
out.put(str[i]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
out.write(str, char_count);
|
|
||||||
}
|
|
||||||
out.close();
|
|
||||||
free(str);
|
|
||||||
auto save_msg = std::make_unique<LSPMessage>();
|
|
||||||
save_msg->editor = msg.editor;
|
|
||||||
save_msg->message = s_msg;
|
|
||||||
save_msg->callback = [](const LSPMessage &) {};
|
|
||||||
msg.editor->lsp.load()->send(std::move(save_msg));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
lsp->send(std::move(save_msg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Executable → Regular
Executable → Regular
Executable → Regular
+69
-8
@@ -238,6 +238,73 @@ void Editor::insert_char(char c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Editor::format_full(int version) {
|
||||||
|
auto lsp = this->lsp.load();
|
||||||
|
if (lsp) {
|
||||||
|
log("Saving %s", this->filename.c_str());
|
||||||
|
auto message = std::make_unique<LSPMessage>();
|
||||||
|
message->message = {{"method", "textDocument/didSave"},
|
||||||
|
{"params", {{"textDocument", {{"uri", this->uri}}}}}};
|
||||||
|
lsp->send(std::move(message));
|
||||||
|
if (lsp->allow_formatting) {
|
||||||
|
json s_msg = {{"method", "textDocument/formatting"},
|
||||||
|
{"params",
|
||||||
|
{{"textDocument", {{"uri", this->uri}}},
|
||||||
|
{"options",
|
||||||
|
{{"tabSize", 2},
|
||||||
|
{"insertSpaces", true},
|
||||||
|
{"trimTrailingWhitespace", true},
|
||||||
|
{"trimFinalNewlines", true}}}}}};
|
||||||
|
auto save_msg = std::make_unique<LSPMessage>();
|
||||||
|
save_msg->editor = this;
|
||||||
|
save_msg->message = s_msg;
|
||||||
|
save_msg->callback = [s_msg, version](const LSPMessage &msg) {
|
||||||
|
if (version != msg.editor->lsp_version)
|
||||||
|
return;
|
||||||
|
auto &edits = msg.message["result"];
|
||||||
|
if (edits.is_array()) {
|
||||||
|
std::vector<TextEdit> t_edits;
|
||||||
|
t_edits.reserve(edits.size());
|
||||||
|
for (auto &edit : edits) {
|
||||||
|
TextEdit t_edit;
|
||||||
|
t_edit.text = edit.value("newText", "");
|
||||||
|
t_edit.start.row = edit["range"]["start"]["line"];
|
||||||
|
t_edit.start.col = edit["range"]["start"]["character"];
|
||||||
|
t_edit.end.row = edit["range"]["end"]["line"];
|
||||||
|
t_edit.end.col = edit["range"]["end"]["character"];
|
||||||
|
msg.editor->utf8_normalize_edit(&t_edit);
|
||||||
|
t_edits.push_back(t_edit);
|
||||||
|
}
|
||||||
|
msg.editor->apply_lsp_edits(t_edits, false);
|
||||||
|
msg.editor->ensure_cursor();
|
||||||
|
uint32_t char_count = msg.editor->root->char_count;
|
||||||
|
char *str = read(msg.editor->root, 0, char_count);
|
||||||
|
if (!str)
|
||||||
|
return;
|
||||||
|
std::ofstream out(msg.editor->filename);
|
||||||
|
if (!msg.editor->unix_eol) {
|
||||||
|
for (uint32_t i = 0; i < char_count; ++i) {
|
||||||
|
if (str[i] == '\n')
|
||||||
|
out.put('\r');
|
||||||
|
out.put(str[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.write(str, char_count);
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
free(str);
|
||||||
|
auto save_msg = std::make_unique<LSPMessage>();
|
||||||
|
save_msg->editor = msg.editor;
|
||||||
|
save_msg->message = s_msg;
|
||||||
|
save_msg->callback = [](const LSPMessage &) {};
|
||||||
|
msg.editor->lsp.load()->send(std::move(save_msg));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
lsp->send(std::move(save_msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Editor::normal_mode() {
|
void Editor::normal_mode() {
|
||||||
Coord prev_pos = this->cursor;
|
Coord prev_pos = this->cursor;
|
||||||
mode = NORMAL;
|
mode = NORMAL;
|
||||||
@@ -431,19 +498,13 @@ void Editor::handle_click(KeyEvent event, Coord size) {
|
|||||||
case SCROLL:
|
case SCROLL:
|
||||||
switch (event.mouse_direction) {
|
switch (event.mouse_direction) {
|
||||||
case SCROLL_UP:
|
case SCROLL_UP:
|
||||||
this->scroll_up(4);
|
this->scroll_up(1);
|
||||||
this->ensure_cursor();
|
this->ensure_cursor();
|
||||||
break;
|
break;
|
||||||
case SCROLL_DOWN:
|
case SCROLL_DOWN:
|
||||||
this->scroll_down(4);
|
this->scroll_down(1);
|
||||||
this->ensure_cursor();
|
this->ensure_cursor();
|
||||||
break;
|
break;
|
||||||
case SCROLL_LEFT:
|
|
||||||
this->cursor_left(10);
|
|
||||||
break;
|
|
||||||
case SCROLL_RIGHT:
|
|
||||||
this->cursor_right(10);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PRESS:
|
case PRESS:
|
||||||
|
|||||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
+1
-1
@@ -9,7 +9,7 @@ void Editor::render(std::vector<ScreenCell> &buffer, Coord size, Coord pos) {
|
|||||||
uint32_t sel_start = 0, sel_end = 0;
|
uint32_t sel_start = 0, sel_end = 0;
|
||||||
uint32_t numlen =
|
uint32_t numlen =
|
||||||
EXTRA_META + static_cast<int>(std::log10(this->root->line_count + 1));
|
EXTRA_META + static_cast<int>(std::log10(this->root->line_count + 1));
|
||||||
uint32_t render_width = size.col - numlen;
|
uint32_t render_width = size.col - numlen - 1;
|
||||||
uint32_t render_x = pos.col + numlen + 1;
|
uint32_t render_x = pos.col + numlen + 1;
|
||||||
this->hooks.start_iter(this->scroll.row);
|
this->hooks.start_iter(this->scroll.row);
|
||||||
auto warn_it = this->warnings.begin();
|
auto warn_it = this->warnings.begin();
|
||||||
|
|||||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
+3
-2
@@ -1,5 +1,4 @@
|
|||||||
#include "extentions/diagnostics.h"
|
#include "extentions/diagnostics.h"
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
DiagnosticBox *init_diagnostic() {
|
DiagnosticBox *init_diagnostic() {
|
||||||
auto diagnostic = std::make_unique<DiagnosticBox>();
|
auto diagnostic = std::make_unique<DiagnosticBox>();
|
||||||
@@ -11,6 +10,8 @@ DiagnosticBox *init_diagnostic() {
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Make this code more readable, It works fine tho.
|
||||||
|
|
||||||
void DiagnosticBox::render(std::vector<ScreenCell> &buffer, Coord n_size,
|
void DiagnosticBox::render(std::vector<ScreenCell> &buffer, Coord n_size,
|
||||||
Coord n_pos) {
|
Coord n_pos) {
|
||||||
pos = n_pos;
|
pos = n_pos;
|
||||||
@@ -158,7 +159,7 @@ void DiagnosticBox::render(std::vector<ScreenCell> &buffer, Coord n_size,
|
|||||||
set(r + 1, i, " ", 0x81cdc6, base_bg, 0, 1);
|
set(r + 1, i, " ", 0x81cdc6, base_bg, 0, 1);
|
||||||
for (; i < see_also.length() + 5 && i < content_width; i++) {
|
for (; i < see_also.length() + 5 && i < content_width; i++) {
|
||||||
set(r + 1, i, (char[2]){see_also[i - 5], 0}, fg, base_bg, 0, 1);
|
set(r + 1, i, (char[2]){see_also[i - 5], 0}, fg, base_bg, 0, 1);
|
||||||
if (see_also[i] == ':')
|
if (see_also[i - 5] == ':')
|
||||||
colon_count++;
|
colon_count++;
|
||||||
if (colon_count == 2)
|
if (colon_count == 2)
|
||||||
fg = 0xFFFFFF;
|
fg = 0xFFFFFF;
|
||||||
|
|||||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
+5
-1
@@ -7,7 +7,7 @@ std::unordered_set<std::string> opened;
|
|||||||
Queue<std::string> need_opening;
|
Queue<std::string> need_opening;
|
||||||
std::vector<Editor *> new_editors;
|
std::vector<Editor *> new_editors;
|
||||||
Queue<std::unique_ptr<LSPMessage>> response_queue;
|
Queue<std::unique_ptr<LSPMessage>> response_queue;
|
||||||
} // namespace lsp
|
}
|
||||||
|
|
||||||
void lsp_worker() {
|
void lsp_worker() {
|
||||||
std::lock_guard lock(lsp::lsp_mutex);
|
std::lock_guard lock(lsp::lsp_mutex);
|
||||||
@@ -22,6 +22,10 @@ void lsp_worker() {
|
|||||||
for (auto it = lsp::new_editors.begin(); it != lsp::new_editors.end();) {
|
for (auto it = lsp::new_editors.begin(); it != lsp::new_editors.end();) {
|
||||||
auto ed = *it;
|
auto ed = *it;
|
||||||
auto lsp_id = ed->lang.lsp_name;
|
auto lsp_id = ed->lang.lsp_name;
|
||||||
|
if (lsp_id.empty()) {
|
||||||
|
it = lsp::new_editors.erase(it);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (lsp::opened.contains(lsp_id)) {
|
if (lsp::opened.contains(lsp_id)) {
|
||||||
auto a_it = lsp::active_lsps.find(lsp_id);
|
auto a_it = lsp::active_lsps.find(lsp_id);
|
||||||
if (a_it != lsp::active_lsps.end())
|
if (a_it != lsp::active_lsps.end())
|
||||||
|
|||||||
Executable → Regular
Executable → Regular
+1
@@ -1,6 +1,7 @@
|
|||||||
#include "ruby/decl.h"
|
#include "ruby/decl.h"
|
||||||
|
|
||||||
mrb_value get_config_file(mrb_state *mrb, mrb_value self) {
|
mrb_value get_config_file(mrb_state *mrb, mrb_value self) {
|
||||||
|
UNUSED(self);
|
||||||
return mrb_str_new_cstr(mrb, ruby_config_path.string().c_str());
|
return mrb_str_new_cstr(mrb, ruby_config_path.string().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user