mirror of https://github.com/helix-editor/helix
clean up
parent
4550faf50f
commit
0b5501d175
|
@ -1720,9 +1720,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "im-lists"
|
name = "im-lists"
|
||||||
version = "0.4.0"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08f93ebe9d5265409edc0b5c2ebd96bf7dcd4125c1626bff0ece34b9300e490a"
|
checksum = "dbe1ea6399f751563e6f5d88bff90a5c7418f8e7abbdd34708412be793a73949"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "im-rc"
|
name = "im-rc"
|
||||||
|
@ -2593,6 +2593,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "steel-core"
|
name = "steel-core"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
|
source = "git+https://github.com/mattwparas/steel.git#11c124dbc8ee890429215bd5963e9a56cac7b923"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"abi_stable",
|
"abi_stable",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
@ -2629,6 +2630,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "steel-derive"
|
name = "steel-derive"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
source = "git+https://github.com/mattwparas/steel.git#11c124dbc8ee890429215bd5963e9a56cac7b923"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -2638,6 +2640,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "steel-gen"
|
name = "steel-gen"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
source = "git+https://github.com/mattwparas/steel.git#11c124dbc8ee890429215bd5963e9a56cac7b923"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"codegen",
|
"codegen",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -2647,6 +2650,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "steel-parser"
|
name = "steel-parser"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
source = "git+https://github.com/mattwparas/steel.git#11c124dbc8ee890429215bd5963e9a56cac7b923"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"logos",
|
"logos",
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
|
|
|
@ -18,7 +18,9 @@ default-members = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
steel-core = { path = "../../steel/crates/steel-core", version = "0.5.0", features = ["modules", "anyhow", "dylibs", "colors"] }
|
# If working locally, use the local path dependency
|
||||||
|
# steel-core = { path = "../../steel/crates/steel-core", version = "0.5.0", features = ["modules", "anyhow", "dylibs", "colors"] }
|
||||||
|
steel-core = { git = "https://github.com/mattwparas/steel.git", version = "0.5.0", features = ["modules", "anyhow", "dylibs", "colors"] }
|
||||||
tree-sitter = { version = "0.20", git = "https://github.com/tree-sitter/tree-sitter", rev = "ab09ae20d640711174b8da8a654f6b3dec93da1a" }
|
tree-sitter = { version = "0.20", git = "https://github.com/tree-sitter/tree-sitter", rev = "ab09ae20d640711174b8da8a654f6b3dec93da1a" }
|
||||||
nucleo = "0.2.0"
|
nucleo = "0.2.0"
|
||||||
|
|
||||||
|
|
|
@ -381,6 +381,18 @@ impl Application {
|
||||||
pub fn handle_config_events(&mut self, config_event: ConfigEvent) {
|
pub fn handle_config_events(&mut self, config_event: ConfigEvent) {
|
||||||
match config_event {
|
match config_event {
|
||||||
ConfigEvent::Refresh => self.refresh_config(),
|
ConfigEvent::Refresh => self.refresh_config(),
|
||||||
|
ConfigEvent::UpdateLanguageConfiguration => match self.refresh_language_config() {
|
||||||
|
Ok(_) => {
|
||||||
|
// If we don't stash the theme here, the syntax highlighting is broken
|
||||||
|
let current_theme = std::mem::take(&mut self.editor.theme);
|
||||||
|
self.editor.set_theme(current_theme);
|
||||||
|
|
||||||
|
self.editor.set_status("Language config refreshed");
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
self.editor.set_error(err.to_string());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// Since only the Application can make changes to Editor's config,
|
// Since only the Application can make changes to Editor's config,
|
||||||
// the Editor must send up a new copy of a modified config so that
|
// the Editor must send up a new copy of a modified config so that
|
||||||
|
@ -409,7 +421,8 @@ impl Application {
|
||||||
|
|
||||||
/// refresh language config after config change
|
/// refresh language config after config change
|
||||||
fn refresh_language_config(&mut self) -> Result<(), Error> {
|
fn refresh_language_config(&mut self) -> Result<(), Error> {
|
||||||
let syntax_config = helix_core::config::user_syntax_loader()
|
let syntax_config = crate::commands::engine::ScriptingEngine::load_language_configuration()
|
||||||
|
.unwrap_or_else(|| helix_core::config::user_syntax_loader())
|
||||||
.map_err(|err| anyhow::anyhow!("Failed to load language config: {}", err))?;
|
.map_err(|err| anyhow::anyhow!("Failed to load language config: {}", err))?;
|
||||||
|
|
||||||
self.syn_loader = std::sync::Arc::new(syntax::Loader::new(syntax_config));
|
self.syn_loader = std::sync::Arc::new(syntax::Loader::new(syntax_config));
|
||||||
|
@ -427,15 +440,19 @@ impl Application {
|
||||||
let theme = config
|
let theme = config
|
||||||
.theme
|
.theme
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|theme| {
|
.and_then(|theme| crate::commands::engine::ScriptingEngine::load_theme(theme))
|
||||||
self.theme_loader
|
.or_else(|| {
|
||||||
.load(theme)
|
// Check the name again
|
||||||
.map_err(|e| {
|
config.theme.as_ref().and_then(|theme| {
|
||||||
log::warn!("failed to load theme `{}` - {}", theme, e);
|
self.theme_loader
|
||||||
e
|
.load(theme)
|
||||||
})
|
.map_err(|e| {
|
||||||
.ok()
|
log::warn!("failed to load theme `{}` - {}", theme, e);
|
||||||
.filter(|theme| (true_color || theme.is_16_color()))
|
e
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
.filter(|theme| (true_color || theme.is_16_color()))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| self.theme_loader.default_theme(true_color));
|
.unwrap_or_else(|| self.theme_loader.default_theme(true_color));
|
||||||
|
|
||||||
|
@ -443,7 +460,6 @@ impl Application {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: @Matt - consider querying the engine for keybindings
|
|
||||||
fn refresh_config(&mut self) {
|
fn refresh_config(&mut self) {
|
||||||
let mut refresh_config = || -> Result<(), Error> {
|
let mut refresh_config = || -> Result<(), Error> {
|
||||||
let default_config = Config::load_default()
|
let default_config = Config::load_default()
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use helix_view::{document::Mode, input::KeyEvent};
|
use helix_core::syntax::Configuration;
|
||||||
|
use helix_view::{document::Mode, input::KeyEvent, Theme};
|
||||||
|
|
||||||
use std::{borrow::Cow, collections::HashMap};
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
compositor,
|
compositor,
|
||||||
keymap::{KeyTrie, KeymapResult},
|
keymap::KeymapResult,
|
||||||
ui::{self, PromptEvent},
|
ui::{self, PromptEvent},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,6 +42,7 @@ pub struct NoEngine;
|
||||||
// This will be the boundary layer between the editor and the engine.
|
// This will be the boundary layer between the editor and the engine.
|
||||||
pub struct ScriptingEngine;
|
pub struct ScriptingEngine;
|
||||||
|
|
||||||
|
// Macro to automatically dispatch to hopefully get some inlining
|
||||||
macro_rules! manual_dispatch {
|
macro_rules! manual_dispatch {
|
||||||
($kind:expr, $raw:tt ($($args:expr),* $(,)?) ) => {
|
($kind:expr, $raw:tt ($($args:expr),* $(,)?) ) => {
|
||||||
match $kind {
|
match $kind {
|
||||||
|
@ -131,6 +133,42 @@ impl ScriptingEngine {
|
||||||
.flat_map(|kind| manual_dispatch!(kind, available_commands()))
|
.flat_map(|kind| manual_dispatch!(kind, available_commands()))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn load_theme(name: &str) -> Option<Theme> {
|
||||||
|
for kind in PLUGIN_PRECEDENCE {
|
||||||
|
let theme = manual_dispatch!(kind, load_theme(name));
|
||||||
|
|
||||||
|
if theme.is_some() {
|
||||||
|
return theme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn themes() -> Option<Vec<String>> {
|
||||||
|
for kind in PLUGIN_PRECEDENCE {
|
||||||
|
let themes = manual_dispatch!(kind, themes());
|
||||||
|
|
||||||
|
if themes.is_some() {
|
||||||
|
return themes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_language_configuration() -> Option<Result<Configuration, toml::de::Error>> {
|
||||||
|
for kind in PLUGIN_PRECEDENCE {
|
||||||
|
let config = manual_dispatch!(kind, load_language_configuration());
|
||||||
|
|
||||||
|
if config.is_some() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PluginSystem for NoEngine {
|
impl PluginSystem for NoEngine {
|
||||||
|
@ -155,6 +193,7 @@ pub trait PluginSystem {
|
||||||
/// Allow the engine to directly handle a keymap event. This is some of the tightest integration
|
/// Allow the engine to directly handle a keymap event. This is some of the tightest integration
|
||||||
/// with the engine, directly intercepting any keymap events. By default, this just delegates to the
|
/// with the engine, directly intercepting any keymap events. By default, this just delegates to the
|
||||||
/// editors default keybindings.
|
/// editors default keybindings.
|
||||||
|
#[inline(always)]
|
||||||
fn handle_keymap_event(
|
fn handle_keymap_event(
|
||||||
&self,
|
&self,
|
||||||
_editor: &mut ui::EditorView,
|
_editor: &mut ui::EditorView,
|
||||||
|
@ -167,6 +206,7 @@ pub trait PluginSystem {
|
||||||
|
|
||||||
/// This attempts to call a function in the engine with the name `name` using the args `args`. The context
|
/// This attempts to call a function in the engine with the name `name` using the args `args`. The context
|
||||||
/// is available here. Returns a bool indicating whether the function exists or not.
|
/// is available here. Returns a bool indicating whether the function exists or not.
|
||||||
|
#[inline(always)]
|
||||||
fn call_function_if_global_exists(
|
fn call_function_if_global_exists(
|
||||||
&self,
|
&self,
|
||||||
_cx: &mut Context,
|
_cx: &mut Context,
|
||||||
|
@ -179,6 +219,7 @@ pub trait PluginSystem {
|
||||||
/// This is explicitly for calling a function via the typed command interface, e.g. `:vsplit`. The context here
|
/// This is explicitly for calling a function via the typed command interface, e.g. `:vsplit`. The context here
|
||||||
/// that is available is more limited than the context available in `call_function_if_global_exists`. This also
|
/// that is available is more limited than the context available in `call_function_if_global_exists`. This also
|
||||||
/// gives the ability to handle in progress commands with `PromptEvent`.
|
/// gives the ability to handle in progress commands with `PromptEvent`.
|
||||||
|
#[inline(always)]
|
||||||
fn call_typed_command_if_global_exists<'a>(
|
fn call_typed_command_if_global_exists<'a>(
|
||||||
&self,
|
&self,
|
||||||
_cx: &mut compositor::Context,
|
_cx: &mut compositor::Context,
|
||||||
|
@ -190,12 +231,35 @@ pub trait PluginSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given an identifier, extract the documentation from the engine.
|
/// Given an identifier, extract the documentation from the engine.
|
||||||
|
#[inline(always)]
|
||||||
fn get_doc_for_identifier(&self, _ident: &str) -> Option<String> {
|
fn get_doc_for_identifier(&self, _ident: &str) -> Option<String> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fuzzy match the input against the fuzzy matcher, used for handling completions on typed commands
|
/// Fuzzy match the input against the fuzzy matcher, used for handling completions on typed commands
|
||||||
|
#[inline(always)]
|
||||||
fn available_commands<'a>(&self) -> Vec<Cow<'a, str>> {
|
fn available_commands<'a>(&self) -> Vec<Cow<'a, str>> {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieve a theme for a given name
|
||||||
|
#[inline(always)]
|
||||||
|
fn load_theme(&self, _name: &str) -> Option<Theme> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve the list of themes that exist within the runtime
|
||||||
|
#[inline(always)]
|
||||||
|
fn themes(&self) -> Option<Vec<String>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch the language configuration as monitored by the plugin system.
|
||||||
|
///
|
||||||
|
/// For now - this maintains backwards compatibility with the existing toml configuration,
|
||||||
|
/// and as such the toml error is exposed here.
|
||||||
|
#[inline(always)]
|
||||||
|
fn load_language_configuration(&self) -> Option<Result<Configuration, toml::de::Error>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,185 +13,10 @@ use crate::{
|
||||||
ui::{Popup, Prompt, PromptEvent},
|
ui::{Popup, Prompt, PromptEvent},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: Move the main configuration function to use this instead
|
||||||
pub fn helix_component_module() -> BuiltInModule {
|
pub fn helix_component_module() -> BuiltInModule {
|
||||||
let mut module = BuiltInModule::new("helix/components".to_string());
|
let mut module = BuiltInModule::new("helix/components".to_string());
|
||||||
|
|
||||||
module.register_fn("new-component!", SteelDynamicComponent::new_dyn);
|
|
||||||
|
|
||||||
module.register_fn("SteelDynamicComponent?", |object: SteelVal| {
|
|
||||||
if let SteelVal::Custom(v) = object {
|
|
||||||
if let Some(wrapped) = v.borrow().as_any_ref().downcast_ref::<BoxDynComponent>() {
|
|
||||||
return wrapped.inner.as_any().is::<SteelDynamicComponent>();
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.register_fn(
|
|
||||||
"SteelDynamicComponent-state",
|
|
||||||
SteelDynamicComponent::get_state,
|
|
||||||
);
|
|
||||||
module.register_fn(
|
|
||||||
"SteelDynamicComponent-render",
|
|
||||||
SteelDynamicComponent::get_render,
|
|
||||||
);
|
|
||||||
module.register_fn(
|
|
||||||
"SteelDynamicComponent-handle-event",
|
|
||||||
SteelDynamicComponent::get_handle_event,
|
|
||||||
);
|
|
||||||
module.register_fn(
|
|
||||||
"SteelDynamicComponent-should-update",
|
|
||||||
SteelDynamicComponent::should_update,
|
|
||||||
);
|
|
||||||
module.register_fn(
|
|
||||||
"SteelDynamicComponent-cursor",
|
|
||||||
SteelDynamicComponent::cursor,
|
|
||||||
);
|
|
||||||
module.register_fn(
|
|
||||||
"SteelDynamicComponent-required-size",
|
|
||||||
SteelDynamicComponent::get_required_size,
|
|
||||||
);
|
|
||||||
|
|
||||||
// engine.register_fn("WrappedComponent", WrappedDynComponent::new)
|
|
||||||
|
|
||||||
module.register_fn(
|
|
||||||
"Popup::new",
|
|
||||||
|contents: &mut WrappedDynComponent,
|
|
||||||
position: helix_core::Position|
|
|
||||||
-> WrappedDynComponent {
|
|
||||||
let inner = contents.inner.take().unwrap(); // Panic, for now
|
|
||||||
|
|
||||||
WrappedDynComponent {
|
|
||||||
inner: Some(Box::new(
|
|
||||||
Popup::<BoxDynComponent>::new("popup", BoxDynComponent::new(inner))
|
|
||||||
.position(Some(position)),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
// prompt: Cow<'static, str>,
|
|
||||||
// history_register: Option<char>,
|
|
||||||
// completion_fn: impl FnMut(&Editor, &str) -> Vec<Completion> + 'static,
|
|
||||||
// callback_fn: impl FnMut(&mut Context, &str, PromptEvent) + 'static,
|
|
||||||
module.register_fn(
|
|
||||||
"Prompt::new",
|
|
||||||
|prompt: String, callback_fn: SteelVal| -> WrappedDynComponent {
|
|
||||||
let prompt = Prompt::new(
|
|
||||||
prompt.into(),
|
|
||||||
None,
|
|
||||||
|_, _| Vec::new(),
|
|
||||||
move |cx, input, prompt_event| {
|
|
||||||
if prompt_event != PromptEvent::Validate {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut ctx = Context {
|
|
||||||
register: None,
|
|
||||||
count: None,
|
|
||||||
editor: cx.editor,
|
|
||||||
callback: Vec::new(),
|
|
||||||
on_next_key_callback: None,
|
|
||||||
jobs: cx.jobs,
|
|
||||||
};
|
|
||||||
|
|
||||||
let cloned_func = callback_fn.clone();
|
|
||||||
// let thunk = move |engine: &mut Engine, cx, input| {
|
|
||||||
// engine.call_function_with_args(
|
|
||||||
// cloned_func,
|
|
||||||
// vec![cx, input],
|
|
||||||
|
|
||||||
// )
|
|
||||||
|
|
||||||
// };
|
|
||||||
|
|
||||||
ENGINE
|
|
||||||
.with(|x| {
|
|
||||||
x.borrow_mut()
|
|
||||||
.with_mut_reference::<Context, Context>(&mut ctx)
|
|
||||||
.consume(move |engine, mut args| {
|
|
||||||
// Add the string as an argument to the callback
|
|
||||||
args.push(input.into_steelval().unwrap());
|
|
||||||
|
|
||||||
engine.call_function_with_args(cloned_func.clone(), args)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
WrappedDynComponent {
|
|
||||||
inner: Some(Box::new(prompt)),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
module.register_fn("Picker::new", |values: Vec<String>| todo!());
|
|
||||||
|
|
||||||
// engine.register_fn(
|
|
||||||
// "Picker::new",
|
|
||||||
// |contents: &mut Wrapped
|
|
||||||
// )
|
|
||||||
|
|
||||||
module.register_fn("Component::Text", |contents: String| WrappedDynComponent {
|
|
||||||
inner: Some(Box::new(crate::ui::Text::new(contents))),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Separate this out into its own component module - This just lets us call the underlying
|
|
||||||
// component, not sure if we can go from trait object -> trait object easily but we'll see!
|
|
||||||
module.register_fn(
|
|
||||||
"Component::render",
|
|
||||||
|t: &mut WrappedDynComponent,
|
|
||||||
area: helix_view::graphics::Rect,
|
|
||||||
frame: &mut tui::buffer::Buffer,
|
|
||||||
ctx: &mut Context| {
|
|
||||||
t.inner.as_mut().unwrap().render(
|
|
||||||
area,
|
|
||||||
frame,
|
|
||||||
&mut compositor::Context {
|
|
||||||
jobs: ctx.jobs,
|
|
||||||
editor: ctx.editor,
|
|
||||||
scroll: None,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
module.register_fn(
|
|
||||||
"Component::handle-event",
|
|
||||||
|s: &mut WrappedDynComponent, event: &helix_view::input::Event, ctx: &mut Context| {
|
|
||||||
s.inner.as_mut().unwrap().handle_event(
|
|
||||||
event,
|
|
||||||
&mut compositor::Context {
|
|
||||||
jobs: ctx.jobs,
|
|
||||||
editor: ctx.editor,
|
|
||||||
scroll: None,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
module.register_fn("Component::should-update", |s: &mut WrappedDynComponent| {
|
|
||||||
s.inner.as_mut().unwrap().should_update()
|
|
||||||
});
|
|
||||||
|
|
||||||
module.register_fn(
|
|
||||||
"Component::cursor",
|
|
||||||
|s: &WrappedDynComponent, area: helix_view::graphics::Rect, ctx: &Editor| {
|
|
||||||
s.inner.as_ref().unwrap().cursor(area, ctx)
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
module.register_fn(
|
|
||||||
"Component::required-size",
|
|
||||||
|s: &mut WrappedDynComponent, viewport: (u16, u16)| {
|
|
||||||
s.inner.as_mut().unwrap().required_size(viewport)
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
module
|
module
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,6 +67,7 @@ impl SteelDynamicComponent {
|
||||||
) -> WrappedDynComponent {
|
) -> WrappedDynComponent {
|
||||||
let s = Self::new(name, state, render, h);
|
let s = Self::new(name, state, render, h);
|
||||||
|
|
||||||
|
// TODO: Add guards here for the
|
||||||
WrappedDynComponent {
|
WrappedDynComponent {
|
||||||
inner: Some(Box::new(s)),
|
inner: Some(Box::new(s)),
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -892,7 +892,10 @@ fn theme(
|
||||||
// Ensures that a preview theme gets cleaned up if the user backspaces until the prompt is empty.
|
// Ensures that a preview theme gets cleaned up if the user backspaces until the prompt is empty.
|
||||||
cx.editor.unset_theme_preview();
|
cx.editor.unset_theme_preview();
|
||||||
} else if let Some(theme_name) = args.first() {
|
} else if let Some(theme_name) = args.first() {
|
||||||
if let Ok(theme) = cx.editor.theme_loader.load(theme_name) {
|
if let Ok(theme) = crate::commands::engine::ScriptingEngine::load_theme(theme_name)
|
||||||
|
.map(|x| Ok(x))
|
||||||
|
.unwrap_or_else(|| cx.editor.theme_loader.load(theme_name))
|
||||||
|
{
|
||||||
if !(true_color || theme.is_16_color()) {
|
if !(true_color || theme.is_16_color()) {
|
||||||
bail!("Unsupported theme: theme requires true color support");
|
bail!("Unsupported theme: theme requires true color support");
|
||||||
}
|
}
|
||||||
|
@ -902,15 +905,25 @@ fn theme(
|
||||||
}
|
}
|
||||||
PromptEvent::Validate => {
|
PromptEvent::Validate => {
|
||||||
if let Some(theme_name) = args.first() {
|
if let Some(theme_name) = args.first() {
|
||||||
let theme = cx
|
// let theme = cx
|
||||||
.editor
|
// .editor
|
||||||
.theme_loader
|
// .theme_loader
|
||||||
.load(theme_name)
|
// .load(theme_name)
|
||||||
.map_err(|err| anyhow::anyhow!("Could not load theme: {}", err))?;
|
// .map_err(|err| anyhow::anyhow!("Could not load theme: {}", err))?;
|
||||||
if !(true_color || theme.is_16_color()) {
|
// if !(true_color || theme.is_16_color()) {
|
||||||
bail!("Unsupported theme: theme requires true color support");
|
// bail!("Unsupported theme: theme requires true color support");
|
||||||
}
|
// }
|
||||||
cx.editor.set_theme(theme);
|
// cx.editor.set_theme(theme);
|
||||||
|
|
||||||
|
if let Ok(theme) = crate::commands::engine::ScriptingEngine::load_theme(theme_name)
|
||||||
|
.map(|x| Ok(x))
|
||||||
|
.unwrap_or_else(|| cx.editor.theme_loader.load(theme_name))
|
||||||
|
{
|
||||||
|
if !(true_color || theme.is_16_color()) {
|
||||||
|
bail!("Unsupported theme: theme requires true color support");
|
||||||
|
}
|
||||||
|
cx.editor.set_theme(theme);
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
let name = cx.editor.theme.name().to_string();
|
let name = cx.editor.theme.name().to_string();
|
||||||
|
|
||||||
|
@ -3087,28 +3100,6 @@ pub(super) fn command_mode(cx: &mut Context) {
|
||||||
let words = shellwords.words();
|
let words = shellwords.words();
|
||||||
|
|
||||||
if words.is_empty() || (words.len() == 1 && !shellwords.ends_with_whitespace()) {
|
if words.is_empty() || (words.len() == 1 && !shellwords.ends_with_whitespace()) {
|
||||||
// let globals =
|
|
||||||
// crate::commands::engine::ScriptingEngine::fuzzy_match(&FUZZY_MATCHER, input)
|
|
||||||
// .into_iter()
|
|
||||||
// .map(|x| (Cow::from(x.0), x.1))
|
|
||||||
// .collect::<Vec<_>>();
|
|
||||||
|
|
||||||
// // If the command has not been finished yet, complete commands.
|
|
||||||
// let mut matches: Vec<_> = typed::TYPABLE_COMMAND_LIST
|
|
||||||
// .iter()
|
|
||||||
// .filter_map(|command| {
|
|
||||||
// FUZZY_MATCHER
|
|
||||||
// .fuzzy_match(command.name, input)
|
|
||||||
// .map(|score| (Cow::from(command.name), score))
|
|
||||||
// })
|
|
||||||
// .chain(globals)
|
|
||||||
// .collect();
|
|
||||||
|
|
||||||
// matches.sort_unstable_by_key(|(_file, score)| std::cmp::Reverse(*score));
|
|
||||||
// matches
|
|
||||||
// .into_iter()
|
|
||||||
// .map(|(name, _)| (0.., name.into()))
|
|
||||||
// .collect()
|
|
||||||
fuzzy_match(
|
fuzzy_match(
|
||||||
input,
|
input,
|
||||||
TYPABLE_COMMAND_LIST
|
TYPABLE_COMMAND_LIST
|
||||||
|
|
|
@ -22,7 +22,7 @@ fn rope_ends_with(text: &str, rope: RopeSlice<'_>) -> bool {
|
||||||
.map_or(false, |end| end == text)
|
.map_or(false, |end| end == text)
|
||||||
}
|
}
|
||||||
|
|
||||||
mod completion;
|
pub(crate) mod completion;
|
||||||
mod signature_help;
|
mod signature_help;
|
||||||
|
|
||||||
pub fn setup(config: Arc<ArcSwap<Config>>) -> Handlers {
|
pub fn setup(config: Arc<ArcSwap<Config>>) -> Handlers {
|
||||||
|
|
|
@ -32,20 +32,31 @@ use crate::ui::{self, CompletionItem, Popup};
|
||||||
use super::Handlers;
|
use super::Handlers;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
enum TriggerKind {
|
pub(crate) enum TriggerKind {
|
||||||
Auto,
|
Auto,
|
||||||
TriggerChar,
|
TriggerChar,
|
||||||
Manual,
|
Manual,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
struct Trigger {
|
pub(crate) struct Trigger {
|
||||||
pos: usize,
|
pos: usize,
|
||||||
view: ViewId,
|
view: ViewId,
|
||||||
doc: DocumentId,
|
doc: DocumentId,
|
||||||
kind: TriggerKind,
|
kind: TriggerKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Trigger {
|
||||||
|
pub(crate) fn new(pos: usize, view: ViewId, doc: DocumentId, kind: TriggerKind) -> Self {
|
||||||
|
Self {
|
||||||
|
pos,
|
||||||
|
view,
|
||||||
|
doc,
|
||||||
|
kind,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) struct CompletionHandler {
|
pub(super) struct CompletionHandler {
|
||||||
/// currently active trigger which will cause a
|
/// currently active trigger which will cause a
|
||||||
|
@ -284,7 +295,7 @@ fn request_completion(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_completion(
|
pub(crate) fn show_completion(
|
||||||
editor: &mut Editor,
|
editor: &mut Editor,
|
||||||
compositor: &mut Compositor,
|
compositor: &mut Compositor,
|
||||||
items: Vec<CompletionItem>,
|
items: Vec<CompletionItem>,
|
||||||
|
|
|
@ -151,13 +151,6 @@ impl Jobs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub async fn next_job(&mut self) -> Option<anyhow::Result<Option<Callback>>> {
|
|
||||||
// tokio::select! {
|
|
||||||
// event = self.futures.next() => { event }
|
|
||||||
// event = self.wait_futures.next() => { event }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub fn add(&self, j: Job) {
|
pub fn add(&self, j: Job) {
|
||||||
if j.wait {
|
if j.wait {
|
||||||
self.wait_futures.push(j.future);
|
self.wait_futures.push(j.future);
|
||||||
|
|
|
@ -278,22 +278,36 @@ impl Completion {
|
||||||
// always present here
|
// always present here
|
||||||
let mut item = item.unwrap().clone();
|
let mut item = item.unwrap().clone();
|
||||||
|
|
||||||
let language_server = language_server!(item);
|
// let language_server = language_server!(item);
|
||||||
let offset_encoding = language_server.offset_encoding();
|
// let offset_encoding = language_server.offset_encoding();
|
||||||
|
|
||||||
let language_server = editor
|
// let language_server = editor
|
||||||
.language_servers
|
// .language_servers
|
||||||
.get_by_id(item.language_server_id)
|
// .get_by_id(item.language_server_id)
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
|
|
||||||
|
let mut language_server_option = None;
|
||||||
|
|
||||||
// resolve item if not yet resolved
|
// resolve item if not yet resolved
|
||||||
if !item.resolved {
|
if !item.resolved {
|
||||||
|
let language_server = language_server!(item);
|
||||||
|
// let offset_encoding = language_server.offset_encoding();
|
||||||
|
|
||||||
if let Some(resolved) =
|
if let Some(resolved) =
|
||||||
Self::resolve_completion_item(language_server, item.item.clone())
|
Self::resolve_completion_item(language_server, item.item.clone())
|
||||||
{
|
{
|
||||||
item.item = resolved;
|
item.item = resolved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
language_server_option = Some(language_server);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// let language_server = language_server!(item);
|
||||||
|
let offset_encoding = language_server_option
|
||||||
|
.as_ref()
|
||||||
|
.map(|x| x.offset_encoding())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
// if more text was entered, remove it
|
// if more text was entered, remove it
|
||||||
doc.restore(view, &savepoint, true);
|
doc.restore(view, &savepoint, true);
|
||||||
// save an undo checkpoint before the completion
|
// save an undo checkpoint before the completion
|
||||||
|
|
|
@ -270,6 +270,11 @@ pub mod completers {
|
||||||
for rt_dir in helix_loader::runtime_dirs() {
|
for rt_dir in helix_loader::runtime_dirs() {
|
||||||
names.extend(theme::Loader::read_names(&rt_dir.join("themes")));
|
names.extend(theme::Loader::read_names(&rt_dir.join("themes")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(themes) = crate::commands::engine::ScriptingEngine::themes() {
|
||||||
|
names.extend(themes);
|
||||||
|
}
|
||||||
|
|
||||||
names.push("default".into());
|
names.push("default".into());
|
||||||
names.push("base16_default".into());
|
names.push("base16_default".into());
|
||||||
names.sort();
|
names.sort();
|
||||||
|
|
|
@ -971,6 +971,7 @@ pub enum EditorEvent {
|
||||||
pub enum ConfigEvent {
|
pub enum ConfigEvent {
|
||||||
Refresh,
|
Refresh,
|
||||||
Update(Box<Config>),
|
Update(Box<Config>),
|
||||||
|
UpdateLanguageConfiguration,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ThemeAction {
|
enum ThemeAction {
|
||||||
|
|
Loading…
Reference in New Issue