mirror of https://github.com/helix-editor/helix
add dynamic component names
parent
fb81eab093
commit
a1b13e570d
|
@ -2357,7 +2357,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
|||
[[package]]
|
||||
name = "steel-core"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/mattwparas/steel.git#c10339bcda9808c326d5aebda610d920fc436a1f"
|
||||
source = "git+https://github.com/mattwparas/steel.git#c5451eaf7fc8e4ba39eb0536b0ccc9b469c2e50b"
|
||||
dependencies = [
|
||||
"abi_stable",
|
||||
"anyhow",
|
||||
|
@ -2395,7 +2395,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "steel-derive"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/mattwparas/steel.git#c10339bcda9808c326d5aebda610d920fc436a1f"
|
||||
source = "git+https://github.com/mattwparas/steel.git#c5451eaf7fc8e4ba39eb0536b0ccc9b469c2e50b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -2405,7 +2405,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "steel-gen"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/mattwparas/steel.git#c10339bcda9808c326d5aebda610d920fc436a1f"
|
||||
source = "git+https://github.com/mattwparas/steel.git#c5451eaf7fc8e4ba39eb0536b0ccc9b469c2e50b"
|
||||
dependencies = [
|
||||
"codegen",
|
||||
"serde",
|
||||
|
@ -2415,7 +2415,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "steel-parser"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/mattwparas/steel.git#c10339bcda9808c326d5aebda610d920fc436a1f"
|
||||
source = "git+https://github.com/mattwparas/steel.git#c5451eaf7fc8e4ba39eb0536b0ccc9b469c2e50b"
|
||||
dependencies = [
|
||||
"fxhash",
|
||||
"lasso",
|
||||
|
|
|
@ -26,7 +26,6 @@ use crate::{
|
|||
Context,
|
||||
},
|
||||
compositor::{self, Component},
|
||||
ctrl, key,
|
||||
ui::overlay::overlaid,
|
||||
};
|
||||
|
||||
|
@ -40,8 +39,6 @@ struct AsyncReader {
|
|||
}
|
||||
|
||||
impl AsyncReader {
|
||||
// TODO: Add &mut references to these async functions
|
||||
// to avoid the cloning, and to ditch the arc and mutex
|
||||
async fn read_line(self) -> Option<String> {
|
||||
let mut buf = String::new();
|
||||
|
||||
|
@ -53,19 +50,34 @@ impl AsyncReader {
|
|||
|
||||
let fut = guard.recv();
|
||||
|
||||
match tokio::time::timeout(std::time::Duration::from_millis(2), fut).await {
|
||||
Ok(Some(v)) => {
|
||||
buf.push_str(&v);
|
||||
Some(buf)
|
||||
}
|
||||
Ok(None) => {
|
||||
if buf.is_empty() {
|
||||
None
|
||||
} else {
|
||||
// If we haven't found any characters, just wait until we have something.
|
||||
// Otherwise, we give this a 2 ms buffer to check if more things are
|
||||
// coming through the pipe.
|
||||
if buf.is_empty() {
|
||||
let next = fut.await;
|
||||
|
||||
match next {
|
||||
Some(v) => {
|
||||
buf.push_str(&v);
|
||||
Some(buf)
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
} else {
|
||||
match tokio::time::timeout(std::time::Duration::from_millis(2), fut).await {
|
||||
Ok(Some(v)) => {
|
||||
buf.push_str(&v);
|
||||
Some(buf)
|
||||
}
|
||||
Ok(None) => {
|
||||
if buf.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(buf)
|
||||
}
|
||||
}
|
||||
Err(_) => Some(buf),
|
||||
}
|
||||
Err(_) => Some(buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -254,6 +266,12 @@ pub fn helix_component_module() -> BuiltInModule {
|
|||
"event-result/consume",
|
||||
SteelEventResult::Consumed.into_steelval().unwrap(),
|
||||
)
|
||||
.register_value(
|
||||
"event-result/consume-without-rerender",
|
||||
SteelEventResult::ConsumedWithoutRerender
|
||||
.into_steelval()
|
||||
.unwrap(),
|
||||
)
|
||||
.register_value(
|
||||
"event-result/ignore",
|
||||
SteelEventResult::Ignored.into_steelval().unwrap(),
|
||||
|
@ -439,7 +457,7 @@ pub struct SteelDynamicComponent {
|
|||
// TODO: currently the component id requires using a &'static str,
|
||||
// however in a world with dynamic components that might not be
|
||||
// the case anymore
|
||||
_name: String,
|
||||
name: String,
|
||||
// This _should_ be a struct, but in theory can be whatever you want. It will be the first argument
|
||||
// passed to the functions in the remainder of the struct.
|
||||
state: SteelVal,
|
||||
|
@ -463,7 +481,7 @@ impl SteelDynamicComponent {
|
|||
h: HashMap<String, SteelVal>,
|
||||
) -> Self {
|
||||
Self {
|
||||
_name: name,
|
||||
name,
|
||||
state,
|
||||
render,
|
||||
handle_event: h.get("handle_event").cloned(),
|
||||
|
@ -522,11 +540,16 @@ enum SteelEventResult {
|
|||
Consumed,
|
||||
Ignored,
|
||||
Close,
|
||||
ConsumedWithoutRerender,
|
||||
}
|
||||
|
||||
impl Custom for SteelEventResult {}
|
||||
|
||||
impl Component for SteelDynamicComponent {
|
||||
fn name(&self) -> Option<&str> {
|
||||
Some(&self.name)
|
||||
}
|
||||
|
||||
fn render(
|
||||
&mut self,
|
||||
area: helix_view::graphics::Rect,
|
||||
|
@ -646,6 +669,9 @@ impl Component for SteelDynamicComponent {
|
|||
match value {
|
||||
Ok(SteelEventResult::Close) => close_fn,
|
||||
Ok(SteelEventResult::Consumed) => compositor::EventResult::Consumed(None),
|
||||
Ok(SteelEventResult::ConsumedWithoutRerender) => {
|
||||
compositor::EventResult::ConsumedWithoutRerender
|
||||
}
|
||||
Ok(SteelEventResult::Ignored) => compositor::EventResult::Ignored(None),
|
||||
_ => match event {
|
||||
// ctrl!('c') | key!(Esc) => close_fn,
|
||||
|
@ -715,7 +741,7 @@ impl Component for SteelDynamicComponent {
|
|||
Err(_e) => {
|
||||
log::info!("Error: {:?}", _e);
|
||||
(None, CursorKind::Block)
|
||||
},
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(None, helix_view::graphics::CursorKind::Hidden)
|
||||
|
|
|
@ -1527,7 +1527,11 @@ impl Component for BoxDynComponent {
|
|||
}
|
||||
|
||||
fn id(&self) -> Option<&'static str> {
|
||||
None
|
||||
Some(self.inner.type_name())
|
||||
}
|
||||
|
||||
fn name(&self) -> Option<&str> {
|
||||
self.inner.name()
|
||||
}
|
||||
|
||||
fn render(
|
||||
|
@ -1768,8 +1772,10 @@ fn load_misc_api(engine: &mut Engine, generate_sources: bool) {
|
|||
// Arity 1
|
||||
module.register_fn("hx.custom-insert-newline", custom_insert_newline);
|
||||
module.register_fn("push-component!", push_component);
|
||||
module.register_fn("pop-last-component!", pop_last_component_by_name);
|
||||
module.register_fn("enqueue-thread-local-callback", enqueue_command);
|
||||
|
||||
template_function_arity_1("pop-last-component!");
|
||||
template_function_arity_1("hx.custom-insert-newline");
|
||||
template_function_arity_1("push-component!");
|
||||
template_function_arity_1("enqueue-thread-local-callback");
|
||||
|
@ -2286,10 +2292,12 @@ fn push_component(cx: &mut Context, component: &mut WrappedDynComponent) {
|
|||
cx.jobs.local_callback(callback);
|
||||
}
|
||||
|
||||
fn render(cx: &mut Context) {
|
||||
fn pop_last_component_by_name(cx: &mut Context, name: SteelString) {
|
||||
let callback = async move {
|
||||
let call: Box<dyn FnOnce(&mut Editor, &mut Compositor, &mut job::Jobs)> = Box::new(
|
||||
move |_editor: &mut Editor, _compositor: &mut Compositor, _jobs: &mut job::Jobs| {},
|
||||
move |_editor: &mut Editor, compositor: &mut Compositor, _jobs: &mut job::Jobs| {
|
||||
compositor.remove_by_dynamic_name(&name);
|
||||
},
|
||||
);
|
||||
Ok(call)
|
||||
};
|
||||
|
|
|
@ -13,6 +13,7 @@ pub type SyncCallback = Box<dyn FnOnce(&mut Compositor, &mut Context) + Sync>;
|
|||
pub enum EventResult {
|
||||
Ignored(Option<Callback>),
|
||||
Consumed(Option<Callback>),
|
||||
ConsumedWithoutRerender,
|
||||
}
|
||||
|
||||
use crate::job::Jobs;
|
||||
|
@ -73,6 +74,10 @@ pub trait Component: Any + AnyComponent {
|
|||
fn id(&self) -> Option<&'static str> {
|
||||
None
|
||||
}
|
||||
|
||||
fn name(&self) -> Option<&str> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Compositor {
|
||||
|
@ -136,6 +141,14 @@ impl Compositor {
|
|||
Some(self.layers.remove(idx))
|
||||
}
|
||||
|
||||
pub fn remove_by_dynamic_name(&mut self, id: &str) -> Option<Box<dyn Component>> {
|
||||
let idx = self
|
||||
.layers
|
||||
.iter()
|
||||
.position(|layer| layer.name() == Some(id))?;
|
||||
Some(self.layers.remove(idx))
|
||||
}
|
||||
|
||||
pub fn handle_event(&mut self, event: &Event, cx: &mut Context) -> bool {
|
||||
// If it is a key event and a macro is being recorded, push the key event to the recording.
|
||||
if let (Event::Key(key), Some((_, keys))) = (event, &mut cx.editor.macro_recording) {
|
||||
|
@ -159,6 +172,10 @@ impl Compositor {
|
|||
consumed = true;
|
||||
break;
|
||||
}
|
||||
// Swallow the event, but don't trigger a re-render
|
||||
EventResult::ConsumedWithoutRerender => {
|
||||
break;
|
||||
}
|
||||
EventResult::Ignored(Some(callback)) => {
|
||||
callbacks.push(callback);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue