Retrieve completion options on ctrl-x.
This commit is contained in:
parent
955cb81687
commit
56f2193811
7 changed files with 86 additions and 3 deletions
|
@ -196,6 +196,12 @@ impl Client {
|
||||||
root_uri: None, // set to project root in the future
|
root_uri: None, // set to project root in the future
|
||||||
initialization_options: None,
|
initialization_options: None,
|
||||||
capabilities: lsp::ClientCapabilities {
|
capabilities: lsp::ClientCapabilities {
|
||||||
|
// text_document:
|
||||||
|
// { completion: {
|
||||||
|
// dynamic_registration: bool
|
||||||
|
// completion_item: { snippet, documentation_format, ... }
|
||||||
|
// completion_item_kind: { }
|
||||||
|
// } }
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
trace: None,
|
trace: None,
|
||||||
|
@ -358,4 +364,41 @@ impl Client {
|
||||||
pub async fn text_document_did_save(&self) -> anyhow::Result<()> {
|
pub async fn text_document_did_save(&self) -> anyhow::Result<()> {
|
||||||
unimplemented!()
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,10 +69,15 @@ impl Application {
|
||||||
|
|
||||||
fn render(&mut self) {
|
fn render(&mut self) {
|
||||||
let executor = &self.executor;
|
let executor = &self.executor;
|
||||||
|
let language_servers = &self.language_servers;
|
||||||
let editor = &mut self.editor;
|
let editor = &mut self.editor;
|
||||||
let compositor = &self.compositor;
|
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();
|
let area = self.terminal.size().unwrap();
|
||||||
|
|
||||||
compositor.render(area, self.terminal.current_buffer_mut(), &mut cx);
|
compositor.render(area, self.terminal.current_buffer_mut(), &mut cx);
|
||||||
|
@ -113,6 +118,7 @@ impl Application {
|
||||||
let mut cx = crate::compositor::Context {
|
let mut cx = crate::compositor::Context {
|
||||||
editor: &mut self.editor,
|
editor: &mut self.editor,
|
||||||
executor: &self.executor,
|
executor: &self.executor,
|
||||||
|
language_servers: &self.language_servers,
|
||||||
};
|
};
|
||||||
// Handle key events
|
// Handle key events
|
||||||
let should_redraw = match event {
|
let should_redraw = match event {
|
||||||
|
|
|
@ -22,6 +22,7 @@ pub struct Context<'a, 'b> {
|
||||||
pub count: usize,
|
pub count: usize,
|
||||||
pub view: &'a mut View,
|
pub view: &'a mut View,
|
||||||
pub executor: &'a smol::Executor<'b>,
|
pub executor: &'a smol::Executor<'b>,
|
||||||
|
pub language_servers: &'a helix_lsp::Registry,
|
||||||
|
|
||||||
pub callback: Option<crate::compositor::Callback>,
|
pub callback: Option<crate::compositor::Callback>,
|
||||||
}
|
}
|
||||||
|
@ -831,3 +832,31 @@ pub fn save(cx: &mut Context) {
|
||||||
// TODO: handle save errors somehow?
|
// TODO: handle save errors somehow?
|
||||||
cx.executor.spawn(cx.view.doc.save()).detach();
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ use helix_view::{Editor, View};
|
||||||
// shared with commands.rs
|
// shared with commands.rs
|
||||||
pub struct Context<'a> {
|
pub struct Context<'a> {
|
||||||
pub editor: &'a mut Editor,
|
pub editor: &'a mut Editor,
|
||||||
|
pub language_servers: &'a helix_lsp::Registry,
|
||||||
pub executor: &'static smol::Executor<'static>,
|
pub executor: &'static smol::Executor<'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -208,6 +208,8 @@ pub fn default() -> Keymaps {
|
||||||
code: KeyCode::Tab,
|
code: KeyCode::Tab,
|
||||||
modifiers: Modifiers::NONE
|
modifiers: Modifiers::NONE
|
||||||
}] => commands::insert::insert_tab,
|
}] => commands::insert::insert_tab,
|
||||||
|
|
||||||
|
vec![ctrl!('x')] => commands::completion,
|
||||||
),
|
),
|
||||||
Mode::Goto => hashmap!(
|
Mode::Goto => hashmap!(
|
||||||
vec![Key {
|
vec![Key {
|
||||||
|
|
|
@ -263,6 +263,7 @@ impl Component for EditorView {
|
||||||
let mut cx = commands::Context {
|
let mut cx = commands::Context {
|
||||||
view,
|
view,
|
||||||
executor: cx.executor,
|
executor: cx.executor,
|
||||||
|
language_servers: cx.language_servers,
|
||||||
count: 1,
|
count: 1,
|
||||||
callback: None,
|
callback: None,
|
||||||
};
|
};
|
||||||
|
|
|
@ -196,12 +196,13 @@ impl<T> Component for Picker<T> {
|
||||||
|
|
||||||
// -- Render the frame:
|
// -- Render the frame:
|
||||||
|
|
||||||
// clear area
|
// clear area
|
||||||
let background = cx.editor.theme.get("ui.background");
|
let background = cx.editor.theme.get("ui.background");
|
||||||
for y in area.top()..area.bottom() {
|
for y in area.top()..area.bottom() {
|
||||||
for x in area.left()..area.right() {
|
for x in area.left()..area.right() {
|
||||||
let cell = surface.get_mut(x, y);
|
let cell = surface.get_mut(x, y);
|
||||||
cell.symbol.clear();
|
cell.reset();
|
||||||
|
// cell.symbol.clear();
|
||||||
cell.set_style(background);
|
cell.set_style(background);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue