aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--helix-lsp/src/client.rs43
-rw-r--r--helix-term/src/application.rs8
-rw-r--r--helix-term/src/commands.rs29
-rw-r--r--helix-term/src/compositor.rs1
-rw-r--r--helix-term/src/keymap.rs2
-rw-r--r--helix-term/src/ui/editor.rs1
-rw-r--r--helix-term/src/ui/picker.rs5
7 files changed, 86 insertions, 3 deletions
diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs
index 160dd93b..c3bcddd2 100644
--- a/helix-lsp/src/client.rs
+++ b/helix-lsp/src/client.rs
@@ -196,6 +196,12 @@ impl Client {
root_uri: None, // set to project root in the future
initialization_options: None,
capabilities: lsp::ClientCapabilities {
+ // text_document:
+ // { completion: {
+ // dynamic_registration: bool
+ // completion_item: { snippet, documentation_format, ... }
+ // completion_item_kind: { }
+ // } }
..Default::default()
},
trace: None,
@@ -358,4 +364,41 @@ impl Client {
pub async fn text_document_did_save(&self) -> anyhow::Result<()> {
unimplemented!()
}
+
+ pub async fn completion(&self, doc: &Document) -> anyhow::Result<Vec<lsp::CompletionItem>> {
+ // TODO: figure out what should happen when you complete with multiple cursors
+
+ let params = lsp::CompletionParams {
+ text_document_position: lsp::TextDocumentPositionParams {
+ text_document: text_document_identifier(doc),
+ position: crate::util::pos_to_lsp_pos(
+ &doc.text().slice(..),
+ doc.selection().cursor(),
+ ),
+ },
+ // TODO: support these tokens by async receiving and updating the choice list
+ work_done_progress_params: lsp::WorkDoneProgressParams {
+ work_done_token: None,
+ },
+ partial_result_params: lsp::PartialResultParams {
+ partial_result_token: None,
+ },
+ context: None,
+ // lsp::CompletionContext { trigger_kind: , trigger_character: Some(), }
+ };
+
+ let response = self.request::<lsp::request::Completion>(params).await?;
+
+ let items = match response {
+ Some(lsp::CompletionResponse::Array(items)) => items,
+ // TODO: do something with is_incomplete
+ Some(lsp::CompletionResponse::List(lsp::CompletionList {
+ is_incomplete: _is_incomplete,
+ items,
+ })) => items,
+ None => Vec::new(),
+ };
+
+ Ok(items)
+ }
}
diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index e15f21c6..138f55c2 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -69,10 +69,15 @@ impl Application {
fn render(&mut self) {
let executor = &self.executor;
+ let language_servers = &self.language_servers;
let editor = &mut self.editor;
let compositor = &self.compositor;
- let mut cx = crate::compositor::Context { editor, executor };
+ let mut cx = crate::compositor::Context {
+ editor,
+ executor,
+ language_servers,
+ };
let area = self.terminal.size().unwrap();
compositor.render(area, self.terminal.current_buffer_mut(), &mut cx);
@@ -113,6 +118,7 @@ impl Application {
let mut cx = crate::compositor::Context {
editor: &mut self.editor,
executor: &self.executor,
+ language_servers: &self.language_servers,
};
// Handle key events
let should_redraw = match event {
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index b4b64249..eb23041c 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -22,6 +22,7 @@ pub struct Context<'a, 'b> {
pub count: usize,
pub view: &'a mut View,
pub executor: &'a smol::Executor<'b>,
+ pub language_servers: &'a helix_lsp::Registry,
pub callback: Option<crate::compositor::Callback>,
}
@@ -831,3 +832,31 @@ pub fn save(cx: &mut Context) {
// TODO: handle save errors somehow?
cx.executor.spawn(cx.view.doc.save()).detach();
}
+
+pub fn completion(cx: &mut Context) {
+ let language_server = cx.language_servers.get("rust", &cx.executor).unwrap();
+ use log::info;
+
+ // TODO: blocking here is not ideal
+ let res = smol::block_on(language_server.completion(&cx.view.doc)).expect("completion failed!");
+
+ let picker = ui::Picker::new(
+ res,
+ |item| {
+ // format_fn
+ item.label.as_str().into()
+ },
+ |editor: &mut Editor, item| {
+ //
+ },
+ );
+
+ cx.callback = Some(Box::new(
+ move |compositor: &mut Compositor, editor: &mut Editor| {
+ compositor.push(Box::new(picker));
+ },
+ ));
+
+ // TODO: when iterating over items, show the docs in popup
+ // language server client needs to be accessible via a registry of some sort
+}
diff --git a/helix-term/src/compositor.rs b/helix-term/src/compositor.rs
index b1b92a71..c507b174 100644
--- a/helix-term/src/compositor.rs
+++ b/helix-term/src/compositor.rs
@@ -39,6 +39,7 @@ use helix_view::{Editor, View};
// shared with commands.rs
pub struct Context<'a> {
pub editor: &'a mut Editor,
+ pub language_servers: &'a helix_lsp::Registry,
pub executor: &'static smol::Executor<'static>,
}
diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs
index c1677847..132c81d0 100644
--- a/helix-term/src/keymap.rs
+++ b/helix-term/src/keymap.rs
@@ -208,6 +208,8 @@ pub fn default() -> Keymaps {
code: KeyCode::Tab,
modifiers: Modifiers::NONE
}] => commands::insert::insert_tab,
+
+ vec![ctrl!('x')] => commands::completion,
),
Mode::Goto => hashmap!(
vec![Key {
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index 1bab2eef..25221922 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -263,6 +263,7 @@ impl Component for EditorView {
let mut cx = commands::Context {
view,
executor: cx.executor,
+ language_servers: cx.language_servers,
count: 1,
callback: None,
};
diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs
index d4e4d46d..a46886ee 100644
--- a/helix-term/src/ui/picker.rs
+++ b/helix-term/src/ui/picker.rs
@@ -196,12 +196,13 @@ impl<T> Component for Picker<T> {
// -- Render the frame:
- // clear area
+ // clear area
let background = cx.editor.theme.get("ui.background");
for y in area.top()..area.bottom() {
for x in area.left()..area.right() {
let cell = surface.get_mut(x, y);
- cell.symbol.clear();
+ cell.reset();
+ // cell.symbol.clear();
cell.set_style(background);
}
}