Skip to content

Commit

Permalink
Pretty much finished the OptionsManager
Browse files Browse the repository at this point in the history
  • Loading branch information
Philipp-M committed Feb 14, 2023
1 parent 63218dd commit d9cb447
Show file tree
Hide file tree
Showing 10 changed files with 397 additions and 418 deletions.
23 changes: 15 additions & 8 deletions helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ use crate::{
keymap::ReverseKeymap,
ui::{
self,
menu::{ItemsSource, OptionManager},
menu::{ItemSource, OptionsManager},
overlay::overlayed,
FilePicker, Picker, Popup, Prompt, PromptEvent,
},
Expand Down Expand Up @@ -2103,9 +2103,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 @@ -2479,13 +2479,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 @@ -2557,7 +2560,7 @@ fn jumplist_picker(cx: &mut Context) {
}
};

let picker = FilePicker::new(
let option_manager = OptionsManager::create_from_items(
cx.editor
.tree
.views()
Expand All @@ -2568,6 +2571,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 @@ -2629,7 +2635,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 @@ -4198,7 +4205,7 @@ 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);

let completion_item_source = ItemsSource::from_async_data(
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)?;
Expand Down Expand Up @@ -4227,7 +4234,7 @@ pub fn completion(cx: &mut Context) {
(),
);

OptionManager::request_items_new(
OptionsManager::request_items_new(
vec![completion_item_source],
cx.editor,
cx.jobs,
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::request_items_new(
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
111 changes: 52 additions & 59 deletions helix-term/src/commands/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ use crate::{
ui::{
self,
lsp::SignatureHelp,
menu::{ItemsSource, Menu, OptionManager},
menu::{ItemSource, Menu, OptionsManager},
overlay::overlayed,
DynamicPicker, FileLocation, FilePicker, Popup, PromptEvent,
FileLocation, FilePicker, Popup, PromptEvent,
},
};

Expand Down Expand Up @@ -208,14 +208,13 @@ fn jump_to_location(
}

fn sym_picker(
symbols: Vec<lsp::SymbolInformation>,
option_manager: OptionsManager<lsp::SymbolInformation>,
current_path: Option<lsp::Url>,
offset_encoding: OffsetEncoding,
) -> FilePicker<lsp::SymbolInformation> {
// TODO: drop current_path comparison and instead use workspace: bool flag?
FilePicker::new(
symbols,
current_path.clone(),
option_manager,
move |cx, symbol, action| {
let (view, doc) = current!(cx.editor);
push_jump(view, doc);
Expand Down Expand Up @@ -288,9 +287,9 @@ fn diag_picker(
error: cx.editor.theme.get("error"),
};

let option_manager = OptionsManager::create_from_items(flat_diag, (styles, format));
FilePicker::new(
flat_diag,
(styles, format),
option_manager,
move |cx, PickerDiagnostic { url, diag }, action| {
if current_path.as_ref() == Some(url) {
let (view, doc) = current!(cx.editor);
Expand Down Expand Up @@ -369,7 +368,9 @@ pub fn symbol_picker(cx: &mut Context) {
}
};

let picker = sym_picker(symbols, current_url, offset_encoding);
let option_manager =
OptionsManager::create_from_items(symbols, current_url.clone());
let picker = sym_picker(option_manager, current_url, offset_encoding);
compositor.push(Box::new(overlayed(picker)))
}
},
Expand All @@ -380,58 +381,50 @@ pub fn workspace_symbol_picker(cx: &mut Context) {
let doc = doc!(cx.editor);
let current_url = doc.url();
let language_server = language_server!(cx.editor, doc);
let language_server_id = language_server.id();
let offset_encoding = language_server.offset_encoding();
let future = match language_server.workspace_symbols("".to_string()) {
Some(future) => future,
None => {
cx.editor
.set_error("Language server does not support workspace symbols");
return;
}
};

cx.callback(
future,
move |_editor, compositor, response: Option<Vec<lsp::SymbolInformation>>| {
let symbols = response.unwrap_or_default();
let picker = sym_picker(symbols, current_url, offset_encoding);
let get_symbols = |query: String, editor: &mut Editor| {
let doc = doc!(editor);
let language_server = match doc.language_server() {
Some(s) => s,
None => {
// This should not generally happen since the picker will not
// even open in the first place if there is no server.
return async move { Err(anyhow::anyhow!("LSP not active")) }.boxed();
}
};
let symbol_request = match language_server.workspace_symbols(query) {
Some(future) => future,
None => {
// This should also not happen since the language server must have
// supported workspace symbols before to reach this block.
return async move {
Err(anyhow::anyhow!(
"Language server does not support workspace symbols"
))
}
.boxed();
}
};
let workspace_symbols_fetcher = Box::new(move |pattern: &str, editor: &mut Editor| {
let language_server = match editor.language_servers.get_by_id(language_server_id) {
Some(language_server) => language_server,
None => {
editor.set_error("Language server is not available");
return async { Ok(vec![]) }.boxed()
},
};
let symbol_request = match language_server.workspace_symbols(pattern.to_string()) {
Some(future) => future,
None => {
editor.set_error("Language server does not support workspace symbols");
return async { Ok(vec![]) }.boxed();
}
};
async move {
let json = symbol_request.await?;
let response: Option<Vec<lsp::SymbolInformation>> = serde_json::from_value(json)?;

let future = async move {
let json = symbol_request.await?;
let response: Option<Vec<lsp::SymbolInformation>> =
serde_json::from_value(json)?;
Ok(response.unwrap_or_default())
}
.boxed()
});
let item_source = ItemSource::from_async_refetch_on_idle_timeout_with_pattern(
workspace_symbols_fetcher,
current_url.clone(),
);

Ok(response.unwrap_or_default())
};
future.boxed()
};
let dyn_picker = DynamicPicker::new(picker, Box::new(get_symbols));
compositor.push(Box::new(overlayed(dyn_picker)))
OptionsManager::request_items_new(
vec![item_source],
cx.editor,
cx.jobs,
move |_editor, compositor, option_manager| {
compositor.push(Box::new(overlayed(sym_picker(
option_manager,
current_url,
offset_encoding,
))))
},
)
None,
);
}

pub fn diagnostics_picker(cx: &mut Context) {
Expand Down Expand Up @@ -644,8 +637,8 @@ pub fn code_action(cx: &mut Context) {
}
.boxed();

OptionManager::request_items_new(
vec![ItemsSource::from_async_data(item_source, ())],
OptionsManager::request_items_new(
vec![ItemSource::from_async_data(item_source, ())],
cx.editor,
cx.jobs,
move |_editor, compositor, options_manager| {
Expand Down Expand Up @@ -911,9 +904,9 @@ fn goto_impl(
editor.set_error("No definition found.");
}
_locations => {
let option_manager = OptionsManager::create_from_items(locations, cwdir);
let picker = FilePicker::new(
locations,
cwdir,
option_manager,
move |cx, location, action| {
jump_to_location(cx.editor, location, offset_encoding, action)
},
Expand Down
3 changes: 2 additions & 1 deletion helix-term/src/commands/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1289,7 +1289,8 @@ fn lsp_workspace_command(
let callback = async move {
let call: job::Callback = Callback::EditorCompositor(Box::new(
move |_editor: &mut Editor, compositor: &mut Compositor| {
let picker = ui::Picker::new(commands, (), |cx, command, _action| {
let option_manager = OptionsManager::create_from_items(commands, ());
let picker = ui::Picker::new(option_manager, |cx, command, _action| {
execute_lsp_command(cx.editor, command.clone());
});
compositor.push(Box::new(overlayed(picker)))
Expand Down
3 changes: 0 additions & 3 deletions helix-term/src/job.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@ use futures_util::stream::{FuturesUnordered, StreamExt};

pub type EditorCompositorCallback = Box<dyn FnOnce(&mut Editor, &mut Compositor) + Send>;
pub type EditorCompositorJobsCallback = Box<dyn FnOnce(&mut Editor, &mut Compositor, &Jobs) + Send>;
pub type JobsCallback = Box<dyn FnOnce(&Jobs) + Send>;
pub type EditorCallback = Box<dyn FnOnce(&mut Editor) + Send>;

pub enum Callback {
EditorCompositor(EditorCompositorCallback),
EditorCompositorJobs(EditorCompositorJobsCallback),
Jobs(JobsCallback),
Editor(EditorCallback),
}

Expand Down Expand Up @@ -81,7 +79,6 @@ impl Jobs {
Callback::EditorCompositorJobs(call) => call(editor, compositor, jobs),
Callback::EditorCompositor(call) => call(editor, compositor),
Callback::Editor(call) => call(editor),
Callback::Jobs(call) => call(jobs),
},
Err(e) => {
editor.set_error(format!("Async job failed: {}", e));
Expand Down
4 changes: 2 additions & 2 deletions helix-term/src/ui/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use helix_view::{
};

use crate::commands;
use crate::ui::{menu, menu::OptionManager, Markdown, Menu, Popup, PromptEvent};
use crate::ui::{menu, menu::OptionsManager, Markdown, Menu, Popup, PromptEvent};

use helix_lsp::{lsp, util, OffsetEncoding};

Expand Down Expand Up @@ -116,7 +116,7 @@ impl Completion {

pub fn new(
editor: &Editor,
option_manager: OptionManager<CompletionItem>,
option_manager: OptionsManager<CompletionItem>,
start_offset: usize,
trigger_offset: usize,
) -> Self {
Expand Down
Loading

0 comments on commit d9cb447

Please sign in to comment.