Expose IDs to be used for parsing component names

This is just the picker for now but could be expanded to other
components.
md-compositor-key-remapping-idea
Michael Davis 1 year ago
parent 21169c77fd
commit 5ca3ed3ef8
No known key found for this signature in database

@ -2591,7 +2591,8 @@ fn buffer_picker(cx: &mut Context) {
.primary() .primary()
.cursor_line(doc.text().slice(..)); .cursor_line(doc.text().slice(..));
Some((meta.id.into(), Some((line, line)))) Some((meta.id.into(), Some((line, line))))
}); })
.with_id("buffer-picker");
cx.push_layer(Box::new(overlaid(picker))); cx.push_layer(Box::new(overlaid(picker)));
} }

@ -279,6 +279,34 @@ pub enum Domain {
Component(&'static str), Component(&'static str),
} }
const REMAPPABLE_COMPONENTS: [&'static str; 3] = [
crate::ui::DYNAMIC_PICKER_ID,
crate::ui::PICKER_ID,
// TODO: make it a constant
"buffer-picker",
];
impl<'de> Deserialize<'de> for Domain {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
if let Ok(mode) = s.parse::<Mode>() {
return Ok(Domain::Mode(mode));
} else if let Some(name) = REMAPPABLE_COMPONENTS
.iter()
.find(|name| **name == s.as_str())
{
Ok(Domain::Component(name))
} else {
Err(serde::de::Error::custom(format!(
"Unknown keymap domain {s}. Expected a mode or component name"
)))
}
}
}
pub struct Keymaps { pub struct Keymaps {
pub map: Box<dyn DynAccess<HashMap<Domain, KeyTrie>>>, pub map: Box<dyn DynAccess<HashMap<Domain, KeyTrie>>>,
/// Stores pending keys waiting for the next key. This is relative to a /// Stores pending keys waiting for the next key. This is relative to a

@ -7,7 +7,7 @@ pub mod lsp;
mod markdown; mod markdown;
pub mod menu; pub mod menu;
pub mod overlay; pub mod overlay;
mod picker; pub mod picker;
pub mod popup; pub mod popup;
mod prompt; mod prompt;
mod spinner; mod spinner;
@ -21,7 +21,7 @@ pub use completion::{Completion, CompletionItem};
pub use editor::EditorView; pub use editor::EditorView;
pub use markdown::Markdown; pub use markdown::Markdown;
pub use menu::Menu; pub use menu::Menu;
pub use picker::{DynamicPicker, FileLocation, Picker}; pub use picker::{DynamicPicker, FileLocation, Picker, DYNAMIC_PICKER_ID, PICKER_ID};
pub use popup::Popup; pub use popup::Popup;
pub use prompt::{Prompt, PromptEvent}; pub use prompt::{Prompt, PromptEvent};
pub use spinner::{ProgressSpinners, Spinner}; pub use spinner::{ProgressSpinners, Spinner};

@ -114,6 +114,8 @@ impl Preview<'_, '_> {
} }
} }
pub const PICKER_ID: &'static str = "picker";
pub struct Picker<T: Item> { pub struct Picker<T: Item> {
options: Vec<T>, options: Vec<T>,
editor_data: T::Data, editor_data: T::Data,
@ -141,6 +143,9 @@ pub struct Picker<T: Item> {
read_buffer: Vec<u8>, read_buffer: Vec<u8>,
/// Given an item in the picker, return the file path and line number to display. /// Given an item in the picker, return the file path and line number to display.
file_fn: Option<FileCallback<T>>, file_fn: Option<FileCallback<T>>,
/// A unique identifier for the picker as a Component
id: &'static str,
} }
impl<T: Item + 'static> Picker<T> { impl<T: Item + 'static> Picker<T> {
@ -172,6 +177,7 @@ impl<T: Item + 'static> Picker<T> {
preview_cache: HashMap::new(), preview_cache: HashMap::new(),
read_buffer: Vec::with_capacity(1024), read_buffer: Vec::with_capacity(1024),
file_fn: None, file_fn: None,
id: PICKER_ID,
}; };
picker.calculate_column_widths(); picker.calculate_column_widths();
@ -205,6 +211,11 @@ impl<T: Item + 'static> Picker<T> {
self self
} }
pub fn with_id(mut self, id: &'static str) -> Self {
self.id = id;
self
}
pub fn set_options(&mut self, new_options: Vec<T>) { pub fn set_options(&mut self, new_options: Vec<T>) {
self.options = new_options; self.options = new_options;
self.cursor = 0; self.cursor = 0;
@ -871,6 +882,10 @@ impl<T: Item + 'static> Component for Picker<T> {
self.completion_height = height.saturating_sub(4); self.completion_height = height.saturating_sub(4);
Some((width, height)) Some((width, height))
} }
fn id(&self) -> Option<&'static str> {
Some(self.id)
}
} }
#[derive(PartialEq, Eq, Debug)] #[derive(PartialEq, Eq, Debug)]
@ -905,6 +920,8 @@ type PickerCallback<T> = Box<dyn Fn(&mut Context, &T, Action)>;
pub type DynQueryCallback<T> = pub type DynQueryCallback<T> =
Box<dyn Fn(String, &mut Editor) -> BoxFuture<'static, anyhow::Result<Vec<T>>>>; Box<dyn Fn(String, &mut Editor) -> BoxFuture<'static, anyhow::Result<Vec<T>>>>;
pub const DYNAMIC_PICKER_ID: &'static str = "dynamic-picker";
/// A picker that updates its contents via a callback whenever the /// A picker that updates its contents via a callback whenever the
/// query string changes. Useful for live grep, workspace symbols, etc. /// query string changes. Useful for live grep, workspace symbols, etc.
pub struct DynamicPicker<T: ui::menu::Item + Send> { pub struct DynamicPicker<T: ui::menu::Item + Send> {
@ -914,8 +931,6 @@ pub struct DynamicPicker<T: ui::menu::Item + Send> {
} }
impl<T: ui::menu::Item + Send> DynamicPicker<T> { impl<T: ui::menu::Item + Send> DynamicPicker<T> {
pub const ID: &'static str = "dynamic-picker";
pub fn new(file_picker: Picker<T>, query_callback: DynQueryCallback<T>) -> Self { pub fn new(file_picker: Picker<T>, query_callback: DynQueryCallback<T>) -> Self {
Self { Self {
file_picker, file_picker,
@ -947,10 +962,11 @@ impl<T: Item + Send + 'static> Component for DynamicPicker<T> {
let callback = Callback::EditorCompositor(Box::new(move |editor, compositor| { let callback = Callback::EditorCompositor(Box::new(move |editor, compositor| {
// Wrapping of pickers in overlay is done outside the picker code, // Wrapping of pickers in overlay is done outside the picker code,
// so this is fragile and will break if wrapped in some other widget. // so this is fragile and will break if wrapped in some other widget.
let picker = match compositor.find_id::<Overlay<DynamicPicker<T>>>(Self::ID) { let picker =
Some(overlay) => &mut overlay.content.file_picker, match compositor.find_id::<Overlay<DynamicPicker<T>>>(DYNAMIC_PICKER_ID) {
None => return, Some(overlay) => &mut overlay.content.file_picker,
}; None => return,
};
picker.set_options(new_options); picker.set_options(new_options);
editor.reset_idle_timer(); editor.reset_idle_timer();
})); }));
@ -968,6 +984,6 @@ impl<T: Item + Send + 'static> Component for DynamicPicker<T> {
} }
fn id(&self) -> Option<&'static str> { fn id(&self) -> Option<&'static str> {
Some(Self::ID) Some(DYNAMIC_PICKER_ID)
} }
} }

Loading…
Cancel
Save