A simple CPU rendered GUI IDE experience.
insert
| -rw-r--r-- | src/com.rs | 44 | ||||
| -rw-r--r-- | src/lsp.rs | 33 | ||||
| -rw-r--r-- | src/main.rs | 22 | ||||
| -rw-r--r-- | src/text.rs | 9 |
4 files changed, 67 insertions, 41 deletions
@@ -31,6 +31,10 @@ impl Complete { } } + pub fn sel(&self, f: &str) -> &CompletionItem { + score(filter(self, f), f)[self.selection].1 + } + pub fn back(&mut self, f: &str) { let n = filter(self, f).count(); if self.selection == 0 { @@ -47,7 +51,7 @@ impl Complete { fn score<'a>( x: impl Iterator<Item = &'a CompletionItem>, filter: &'_ str, -) -> impl Iterator<Item = (u32, &'a CompletionItem, Vec<u32>)> { +) -> Vec<(u32, &'a CompletionItem, Vec<u32>)> { #[thread_local] static mut MATCHER: LazyLock<nucleo::Matcher> = LazyLock::new(|| nucleo::Matcher::new(nucleo::Config::DEFAULT)); @@ -57,23 +61,28 @@ fn score<'a>( nucleo::pattern::CaseMatching::Smart, nucleo::pattern::Normalization::Smart, ); - x.map(move |y| { - let mut utf32 = vec![]; + let mut v = x + .map(move |y| { + let mut utf32 = vec![]; - let hay = y.filter_text.as_deref().unwrap_or(&y.label); - let mut indices = vec![]; - let score = p - .indices( - nucleo::Utf32Str::new(hay, &mut utf32), - unsafe { &mut *MATCHER }, - &mut indices, - ) - .unwrap_or(0); - indices.sort_unstable(); - indices.dedup(); + let hay = y.filter_text.as_deref().unwrap_or(&y.label); + let mut indices = vec![]; + let score = p + .indices( + nucleo::Utf32Str::new(hay, &mut utf32), + unsafe { &mut *MATCHER }, + &mut indices, + ) + .unwrap_or(0); + indices.sort_unstable(); + indices.dedup(); - (score, y, indices) - }) + (score, y, indices) + }) + .collect::<Vec<_>>(); + v.sort_by_key(|x| x.0); + v.reverse(); + v } fn filter<'a>( completion: &'a Complete, @@ -101,8 +110,7 @@ fn filter<'a>( pub fn s(completion: &Complete, c: usize, f: &str) -> Vec<Cell> { let mut out = vec![]; let i = score(filter(completion, f), f) - .sorted_by_key(|x| x.0) - .rev() + .into_iter() .zip(0..) .skip(completion.vo) .take(N); @@ -278,6 +278,11 @@ pub fn run( value_set: vec![CompletionItemTag::DEPRECATED], }), + insert_replace_support: Some(false), + insert_text_mode_support:Some(InsertTextModeSupport{ + value_set: vec![InsertTextMode::AS_IS] + }), + resolve_support: Some(CompletionItemCapabilityResolveSupport { properties: vec!["documentation".into()] } ), label_details_support: None, ..default() }), @@ -285,29 +290,29 @@ pub fn run( CompletionItemKindCapability { value_set: Some( vec![CompletionItemKind::TEXT, -CompletionItemKind::METHOD, // () -CompletionItemKind::FUNCTION, // () -CompletionItemKind::CONSTRUCTOR, // -> -CompletionItemKind::FIELD, // x. -CompletionItemKind::VARIABLE, // x +CompletionItemKind::METHOD, +CompletionItemKind::FUNCTION, +CompletionItemKind::CONSTRUCTOR, +CompletionItemKind::FIELD, +CompletionItemKind::VARIABLE, CompletionItemKind::CLASS, CompletionItemKind::INTERFACE, -CompletionItemKind::MODULE, // :: -CompletionItemKind::PROPERTY, // x. +CompletionItemKind::MODULE, +CompletionItemKind::PROPERTY, CompletionItemKind::UNIT, -CompletionItemKind::VALUE, // 4 -CompletionItemKind::ENUM, // un +CompletionItemKind::VALUE, +CompletionItemKind::ENUM, CompletionItemKind::KEYWORD, -CompletionItemKind::SNIPPET, // ! +CompletionItemKind::SNIPPET, CompletionItemKind::COLOR, CompletionItemKind::FILE, -CompletionItemKind::REFERENCE, // & +CompletionItemKind::REFERENCE, CompletionItemKind::FOLDER, CompletionItemKind::ENUM_MEMBER, -CompletionItemKind::CONSTANT, // N -CompletionItemKind::STRUCT, // X +CompletionItemKind::CONSTANT, +CompletionItemKind::STRUCT, CompletionItemKind::EVENT, -CompletionItemKind::OPERATOR, // + +CompletionItemKind::OPERATOR, CompletionItemKind::TYPE_PARAMETER] ), diff --git a/src/main.rs b/src/main.rs index 68d46fb..a3e2b5b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,12 +45,9 @@ use diff_match_patch_rs::PatchInput; use dsb::cell::Style; use dsb::{Cell, F}; use fimg::{Image, OverlayAt}; -use lsp_types::request::{Completion, HoverRequest}; +use lsp_types::request::{ HoverRequest}; use lsp_types::{ - CompletionContext, CompletionResponse, CompletionTriggerKind, Hover, - HoverParams, MarkedString, Position, SemanticTokensOptions, - SemanticTokensServerCapabilities, ServerCapabilities, - TextDocumentIdentifier, TextDocumentPositionParams, WorkspaceFolder, + CompletionContext, CompletionResponse, CompletionTextEdit, CompletionTriggerKind, Hover, HoverParams, MarkedString, Position, SemanticTokensOptions, SemanticTokensServerCapabilities, ServerCapabilities, TextDocumentIdentifier, TextDocumentPositionParams, WorkspaceFolder }; use parking_lot::Mutex; use regex::Regex; @@ -335,7 +332,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { r:x,start:c,selection:0,vo:0, } ); if let Some(x) = o { - // std::fs::write("complete_", serde_json::to_string_pretty(&x.r).unwrap()).unwrap(); + std::fs::write("complete_", serde_json::to_string_pretty(&x.r).unwrap()).unwrap(); // println!("resolved") } // println!("{complete:#?}"); @@ -867,6 +864,12 @@ RUNNING.remove(&hover,&RUNNING.guard()); let CompletionState::Complete(Some(c), x) = &mut complete else { panic!()}; c.back(&filter(&text)); } + Some(CDo::Finish(x)) => { + let Some(CompletionTextEdit::Edit(ed)) = x.sel(&filter(&text)).clone().text_edit else { panic!() }; + text.apply(ed.clone()).unwrap(); + text.cursor = text.l_position(ed.range.start).unwrap() + ed.new_text.chars().count(); + if hist.record(&text) { change!();} + } Some(CDo::Abort(())) => {} None => {return}, @@ -1244,14 +1247,17 @@ rust_fsm::state_machine! { // exit cases Complete((_x, None)) => Click => None, + Complete((_x, Some((y, _))))=> K(Key::Named(Escape)) => None [Abort(((),) => y.abort())], + Complete((_x, None)) => K(Key::Named(Escape)) => None, Complete((_x, Some((y, _)))) => Click => None [Abort(((),) => y.abort())], Complete((_x, Some((y, _)))) => K(Key::Character(x) if !x.chars().all(is_word)) => None [Abort(y.abort())], Complete((_x, None)) => K(Key::Character(x) if !x.chars().all(is_word)) => None, - Complete((_x, _y)) => K(_) => _ [Request(CompletionContext { trigger_kind: CompletionTriggerKind::TRIGGER_FOR_INCOMPLETE_COMPLETIONS, trigger_character:None })], Complete((Some(x), task)) => K(Key::Named(NamedKey::Enter)) => None [Finish(Complete => { task.map(|(task, _)| task.abort()); x - })] + })], + + Complete((_x, _y)) => K(_) => _ [Request(CompletionContext { trigger_kind: CompletionTriggerKind::TRIGGER_FOR_INCOMPLETE_COMPLETIONS, trigger_character:None })], } use com::Complete; impl Default for CompletionState { diff --git a/src/text.rs b/src/text.rs index e37c8c7..293244f 100644 --- a/src/text.rs +++ b/src/text.rs @@ -17,7 +17,7 @@ use helix_core::Syntax; use helix_core::syntax::{HighlightEvent, Loader}; use implicit_fn::implicit_fn; use log::error; -use lsp_types::{Position, SemanticToken, SemanticTokensLegend}; +use lsp_types::{Position, SemanticToken, SemanticTokensLegend, TextEdit}; use ropey::{Rope, RopeSlice}; use tree_house::Language; use winit::keyboard::{NamedKey, SmolStr}; @@ -308,6 +308,13 @@ impl TextArea { self.set_ho(); } + pub fn apply(&mut self, x: TextEdit) -> Result<(), ropey::Error> { + let begin = self.l_position(x.range.start)?; + let end = self.l_position(x.range.end)?; + self.rope.try_remove(begin..end)?; + self.rope.try_insert(begin, &x.new_text)?; + Ok(()) + } pub fn cursor(&self) -> (usize, usize) { self.xy(self.cursor) } |