Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor picker/menu logic into an options manager which can be fed with multiple different item sources (async, sync, refetch) #5991

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion helix-lsp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub enum Error {
Other(#[from] anyhow::Error),
}

#[derive(Clone, Copy, Debug, Default)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum OffsetEncoding {
/// UTF-8 code units aka bytes
Utf8,
Expand Down
4 changes: 2 additions & 2 deletions helix-term/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,11 +348,11 @@ impl Application {
self.handle_signals(signal).await;
}
Some(callback) = self.jobs.futures.next() => {
self.jobs.handle_callback(&mut self.editor, &mut self.compositor, callback);
self.jobs.handle_callback(&mut self.editor, &mut self.compositor, &self.jobs, callback);
self.render().await;
}
Some(callback) = self.jobs.wait_futures.next() => {
self.jobs.handle_callback(&mut self.editor, &mut self.compositor, callback);
self.jobs.handle_callback(&mut self.editor, &mut self.compositor, &self.jobs, callback);
self.render().await;
}
event = self.editor.wait_event() => {
Expand Down
84 changes: 55 additions & 29 deletions helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,16 @@ use crate::{
filter_picker_entry,
job::Callback,
keymap::ReverseKeymap,
ui::{self, overlay::overlayed, FilePicker, Picker, Popup, Prompt, PromptEvent},
ui::{
self,
menu::{ItemSource, OptionsManager},
overlay::overlayed,
FilePicker, Picker, Popup, Prompt, PromptEvent,
},
};

use crate::job::{self, Jobs};
use futures_util::StreamExt;
use futures_util::{FutureExt, StreamExt};
use std::{collections::HashMap, fmt, future::Future};
use std::{collections::HashSet, num::NonZeroUsize};

Expand Down Expand Up @@ -2097,9 +2102,9 @@ fn global_search(cx: &mut Context) {
return;
}

let option_manager = OptionsManager::create_from_items(all_matches, current_path);
let picker = FilePicker::new(
all_matches,
current_path,
option_manager,
move |cx, FileResult { path, line_num }, action| {
match cx.editor.open(path, action) {
Ok(_) => {}
Expand Down Expand Up @@ -2473,13 +2478,16 @@ fn buffer_picker(cx: &mut Context) {
is_current: doc.id() == current,
};

let picker = FilePicker::new(
let option_manager = OptionsManager::create_from_items(
cx.editor
.documents
.values()
.map(|doc| new_meta(doc))
.collect(),
(),
);
let picker = FilePicker::new(
option_manager,
|cx, meta, action| {
cx.editor.switch(meta.id, action);
},
Expand Down Expand Up @@ -2551,7 +2559,7 @@ fn jumplist_picker(cx: &mut Context) {
}
};

let picker = FilePicker::new(
let option_manager = OptionsManager::create_from_items(
cx.editor
.tree
.views()
Expand All @@ -2562,6 +2570,9 @@ fn jumplist_picker(cx: &mut Context) {
})
.collect(),
(),
);
let picker = FilePicker::new(
option_manager,
|cx, meta, action| {
cx.editor.switch(meta.id, action);
let config = cx.editor.config();
Expand Down Expand Up @@ -2623,7 +2634,8 @@ pub fn command_palette(cx: &mut Context) {
}
}));

let picker = Picker::new(commands, keymap, move |cx, command, _action| {
let option_manager = OptionsManager::create_from_items(commands, keymap);
let picker = Picker::new(option_manager, move |cx, command, _action| {
let mut ctx = Context {
register: None,
count: std::num::NonZeroUsize::new(1),
Expand Down Expand Up @@ -4169,6 +4181,7 @@ pub fn completion(cx: &mut Context) {
None => return,
};

let language_server_id = language_server.id();
let offset_encoding = language_server.offset_encoding();
let text = doc.text().slice(..);
let cursor = doc.selection(view.id).primary().cursor(text);
Expand All @@ -4191,39 +4204,52 @@ pub fn completion(cx: &mut Context) {
let offset = iter.take_while(|ch| chars::char_is_word(*ch)).count();
let start_offset = cursor.saturating_sub(offset);

cx.callback(
future,
move |editor, compositor, response: Option<lsp::CompletionResponse>| {
if editor.mode != Mode::Insert {
// we're not in insert mode anymore
return;
}
let completion_item_source = ItemSource::from_async_data(
async move {
let json = future.await?;
let response: helix_lsp::lsp::CompletionResponse = serde_json::from_value(json)?;

let items = match response {
Some(lsp::CompletionResponse::Array(items)) => items,
let mut items = match response {
lsp::CompletionResponse::Array(items) => items,
// TODO: do something with is_incomplete
Some(lsp::CompletionResponse::List(lsp::CompletionList {
lsp::CompletionResponse::List(helix_lsp::lsp::CompletionList {
is_incomplete: _is_incomplete,
items,
})) => items,
None => Vec::new(),
}) => items,
};

if items.is_empty() {
// editor.set_error("No completion available");
// Sort completion items according to their preselect status (given by the LSP server)
items.sort_by_key(|item| !item.preselect.unwrap_or(false));
Ok(items
.into_iter()
.map(|item| ui::CompletionItem::LSP {
item,
language_server_id,
offset_encoding,
})
.collect())
}
.boxed(),
(),
);

OptionsManager::create_from_item_sources(
vec![completion_item_source],
cx.editor,
cx.jobs,
move |editor, compositor, option_manager| {
if editor.mode != Mode::Insert {
// we're not in insert mode anymore
return;
}

let size = compositor.size();
let ui = compositor.find::<ui::EditorView>().unwrap();
ui.set_completion(
editor,
items,
offset_encoding,
start_offset,
trigger_offset,
size,
);
ui.set_completion(editor, option_manager, start_offset, trigger_offset, size);
},
Some(Box::new(|editor: &mut Editor| {
editor.set_error("No completion available")
})),
);
}

Expand Down
46 changes: 31 additions & 15 deletions helix-term/src/commands/dap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@ use super::{Context, Editor};
use crate::{
compositor::{self, Compositor},
job::{Callback, Jobs},
ui::{self, overlay::overlayed, FilePicker, Picker, Popup, Prompt, PromptEvent, Text},
ui::{
self,
menu::{ItemSource, OptionsManager},
overlay::overlayed,
FilePicker, Picker, Popup, Prompt, PromptEvent, Text,
},
};
use dap::{StackFrame, Thread, ThreadStates};
use futures_util::FutureExt;
use helix_core::syntax::{DebugArgumentValue, DebugConfigCompletion, DebugTemplate};
use helix_dap::{self as dap, Client};
use helix_lsp::block_on;
Expand Down Expand Up @@ -61,21 +67,30 @@ fn thread_picker(
let debugger = debugger!(cx.editor);

let future = debugger.threads();
dap_callback(

let thread_states = debugger!(cx.editor).thread_states.clone();
let item_source = ItemSource::from_async_data(
async move {
let response: dap::requests::ThreadsResponse = serde_json::from_value(future.await?)?;

Ok(response.threads)
}
.boxed(),
thread_states,
);

OptionsManager::create_from_item_sources(
vec![item_source],
cx.editor,
cx.jobs,
future,
move |editor, compositor, response: dap::requests::ThreadsResponse| {
let threads = response.threads;
if threads.len() == 1 {
callback_fn(editor, &threads[0]);
move |editor, compositor, option_manager| {
if option_manager.options_len() == 1 {
callback_fn(editor, option_manager.options().next().unwrap().0);
return;
}
let debugger = debugger!(editor);

let thread_states = debugger.thread_states.clone();
let picker = FilePicker::new(
threads,
thread_states,
option_manager,
move |cx, thread, _action| callback_fn(cx.editor, thread),
move |editor, thread| {
let frames = editor.debugger.as_ref()?.stack_frames.get(&thread.id)?;
Expand All @@ -90,6 +105,7 @@ fn thread_picker(
);
compositor.push(Box::new(picker));
},
None,
);
}

Expand Down Expand Up @@ -270,9 +286,9 @@ pub fn dap_launch(cx: &mut Context) {

let templates = config.templates.clone();

let option_manager = OptionsManager::create_from_items(templates, ());
cx.push_layer(Box::new(overlayed(Picker::new(
templates,
(),
option_manager,
|cx, template, _action| {
let completions = template.completion.clone();
let name = template.name.clone();
Expand Down Expand Up @@ -681,9 +697,9 @@ pub fn dap_switch_stack_frame(cx: &mut Context) {

let frames = debugger.stack_frames[&thread_id].clone();

let option_manager = OptionsManager::create_from_items(frames, ());
let picker = FilePicker::new(
frames,
(),
option_manager,
move |cx, frame, _action| {
let debugger = debugger!(cx.editor);
// TODO: this should be simpler to find
Expand Down
Loading