2023-08-25 09:12:15 +08:00
|
|
|
use helix_view::{document::Mode, input::KeyEvent};
|
2023-05-08 12:53:19 +08:00
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
use std::borrow::Cow;
|
2023-05-08 12:53:19 +08:00
|
|
|
|
|
|
|
use crate::{
|
2023-08-25 09:12:15 +08:00
|
|
|
compositor,
|
|
|
|
keymap::KeymapResult,
|
|
|
|
ui::{self, PromptEvent},
|
2023-05-08 12:53:19 +08:00
|
|
|
};
|
|
|
|
|
2023-08-25 11:01:49 +08:00
|
|
|
use super::{shell_impl, Context, MappableCommand, TYPABLE_COMMAND_LIST};
|
2023-05-08 12:53:19 +08:00
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
#[cfg(feature = "steel")]
|
2023-06-06 12:09:27 +08:00
|
|
|
mod components;
|
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
// TODO: Change this visibility to pub(crate) probably, and adjust the status line message to not refer to the one
|
|
|
|
// in the scheme module directly. Probably create some kind of object here to refer to instead
|
2023-08-10 13:24:29 +08:00
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
#[cfg(feature = "steel")]
|
|
|
|
pub mod scheme;
|
2023-08-10 13:24:29 +08:00
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
// For now, we will allow _one_ embedded scripting engine to live inside of helix.
|
|
|
|
// In theory, we could allow multiple, with some kind of hierarchy where we check
|
|
|
|
// each one, with some kind of precedence.
|
|
|
|
struct PluginEngine<T: PluginSystem>(T);
|
2023-08-10 13:24:29 +08:00
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
// This is where we can configure our system to use the correct one
|
|
|
|
#[cfg(feature = "steel")]
|
|
|
|
static PLUGIN_SYSTEM: PluginEngine<scheme::SteelScriptingEngine> =
|
|
|
|
PluginEngine(scheme::SteelScriptingEngine);
|
2023-08-10 13:24:29 +08:00
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
#[cfg(not(feature = "steel"))]
|
|
|
|
static PLUGIN_SYSTEM: PluginEngine<NoEngine> = PluginEngine(NoEngine);
|
2023-08-10 13:24:29 +08:00
|
|
|
|
2023-08-25 11:01:49 +08:00
|
|
|
// enum PluginSystemTypes {
|
|
|
|
// None,
|
|
|
|
// Steel,
|
|
|
|
// }
|
2023-08-10 13:24:29 +08:00
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
// The order in which the plugins will be evaluated against - if we wanted to include, lets say `rhai`,
|
2023-08-25 11:01:49 +08:00
|
|
|
// we would have to order the precedence for searching for exported commands, or somehow merge them?
|
|
|
|
// static PLUGIN_PRECEDENCE: &[PluginSystemTypes] = &[PluginSystemTypes::Steel];
|
2023-08-10 13:24:29 +08:00
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
pub struct NoEngine;
|
2023-08-10 13:24:29 +08:00
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
// This will be the boundary layer between the editor and the engine.
|
|
|
|
pub struct ScriptingEngine;
|
2023-08-10 13:24:29 +08:00
|
|
|
|
2023-07-12 12:23:03 +08:00
|
|
|
impl ScriptingEngine {
|
|
|
|
pub fn initialize() {
|
2023-08-25 09:12:15 +08:00
|
|
|
PLUGIN_SYSTEM.0.initialize();
|
2023-07-12 12:23:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn run_initialization_script(cx: &mut Context) {
|
2023-08-25 09:12:15 +08:00
|
|
|
PLUGIN_SYSTEM.0.run_initialization_script(cx);
|
2023-07-12 12:23:03 +08:00
|
|
|
}
|
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
pub fn handle_keymap_event(
|
|
|
|
editor: &mut ui::EditorView,
|
|
|
|
mode: Mode,
|
|
|
|
cxt: &mut Context,
|
|
|
|
event: KeyEvent,
|
|
|
|
) -> KeymapResult {
|
|
|
|
PLUGIN_SYSTEM
|
|
|
|
.0
|
|
|
|
.handle_keymap_event(editor, mode, cxt, event)
|
2023-07-12 12:23:03 +08:00
|
|
|
}
|
|
|
|
|
2023-08-10 13:24:29 +08:00
|
|
|
pub fn call_function_if_global_exists(
|
|
|
|
cx: &mut Context,
|
|
|
|
name: &str,
|
|
|
|
args: Vec<Cow<str>>,
|
|
|
|
) -> bool {
|
2023-08-25 09:12:15 +08:00
|
|
|
PLUGIN_SYSTEM
|
|
|
|
.0
|
|
|
|
.call_function_if_global_exists(cx, name, args)
|
2023-07-12 12:23:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn call_typed_command_if_global_exists<'a>(
|
|
|
|
cx: &mut compositor::Context,
|
|
|
|
input: &'a str,
|
|
|
|
parts: &'a [&'a str],
|
|
|
|
event: PromptEvent,
|
|
|
|
) -> bool {
|
2023-08-25 09:12:15 +08:00
|
|
|
PLUGIN_SYSTEM
|
|
|
|
.0
|
|
|
|
.call_typed_command_if_global_exists(cx, input, parts, event)
|
2023-07-12 12:23:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_doc_for_identifier(ident: &str) -> Option<String> {
|
2023-08-25 09:12:15 +08:00
|
|
|
PLUGIN_SYSTEM.0.get_doc_for_identifier(ident)
|
2023-07-12 12:23:03 +08:00
|
|
|
}
|
2023-07-12 12:37:40 +08:00
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
pub fn fuzzy_match<'a>(
|
2023-07-12 12:37:40 +08:00
|
|
|
fuzzy_matcher: &'a fuzzy_matcher::skim::SkimMatcherV2,
|
|
|
|
input: &'a str,
|
|
|
|
) -> Vec<(String, i64)> {
|
2023-08-25 09:12:15 +08:00
|
|
|
PLUGIN_SYSTEM.0.fuzzy_match(fuzzy_matcher, input)
|
2023-07-12 12:37:40 +08:00
|
|
|
}
|
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
pub fn is_exported(ident: &str) -> bool {
|
|
|
|
PLUGIN_SYSTEM.0.is_exported(ident)
|
2023-07-12 12:37:40 +08:00
|
|
|
}
|
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
pub fn engine_get_doc(ident: &str) -> Option<String> {
|
|
|
|
PLUGIN_SYSTEM.0.engine_get_doc(ident)
|
2023-07-12 12:37:40 +08:00
|
|
|
}
|
2023-07-12 12:23:03 +08:00
|
|
|
}
|
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
impl PluginSystem for NoEngine {}
|
2023-05-30 12:41:13 +08:00
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
/// These methods are the main entry point for interaction with the rest of
|
|
|
|
/// the editor system.
|
|
|
|
pub trait PluginSystem {
|
|
|
|
fn initialize(&self) {}
|
2023-05-30 12:41:13 +08:00
|
|
|
|
2023-08-25 11:01:49 +08:00
|
|
|
fn run_initialization_script(&self, _cx: &mut Context) {}
|
2023-05-30 12:41:13 +08:00
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
fn handle_keymap_event(
|
2023-05-30 12:41:13 +08:00
|
|
|
&self,
|
2023-08-25 09:12:15 +08:00
|
|
|
editor: &mut ui::EditorView,
|
|
|
|
mode: Mode,
|
2023-08-25 11:01:49 +08:00
|
|
|
_cxt: &mut Context,
|
2023-08-25 09:12:15 +08:00
|
|
|
event: KeyEvent,
|
|
|
|
) -> KeymapResult {
|
|
|
|
editor.keymaps.get(mode, event)
|
2023-05-30 12:41:13 +08:00
|
|
|
}
|
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
fn call_function_if_global_exists(
|
|
|
|
&self,
|
2023-08-25 11:01:49 +08:00
|
|
|
_cx: &mut Context,
|
|
|
|
_name: &str,
|
|
|
|
_args: Vec<Cow<str>>,
|
2023-08-25 09:12:15 +08:00
|
|
|
) -> bool {
|
|
|
|
false
|
2023-05-30 12:41:13 +08:00
|
|
|
}
|
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
fn call_typed_command_if_global_exists<'a>(
|
|
|
|
&self,
|
2023-08-25 11:01:49 +08:00
|
|
|
_cx: &mut compositor::Context,
|
|
|
|
_input: &'a str,
|
|
|
|
_parts: &'a [&'a str],
|
|
|
|
_event: PromptEvent,
|
2023-08-25 09:12:15 +08:00
|
|
|
) -> bool {
|
|
|
|
false
|
2023-05-30 12:41:13 +08:00
|
|
|
}
|
|
|
|
|
2023-08-25 11:01:49 +08:00
|
|
|
fn get_doc_for_identifier(&self, _ident: &str) -> Option<String> {
|
2023-05-30 12:41:13 +08:00
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2023-08-25 09:12:15 +08:00
|
|
|
fn fuzzy_match<'a>(
|
|
|
|
&self,
|
2023-08-25 11:01:49 +08:00
|
|
|
_fuzzy_matcher: &'a fuzzy_matcher::skim::SkimMatcherV2,
|
|
|
|
_input: &'a str,
|
2023-05-08 12:53:19 +08:00
|
|
|
) -> Vec<(String, i64)> {
|
2023-08-25 09:12:15 +08:00
|
|
|
Vec::new()
|
2023-05-08 12:53:19 +08:00
|
|
|
}
|
|
|
|
|
2023-08-25 11:01:49 +08:00
|
|
|
fn is_exported(&self, _ident: &str) -> bool {
|
2023-08-25 09:12:15 +08:00
|
|
|
false
|
2023-07-13 12:39:27 +08:00
|
|
|
}
|
|
|
|
|
2023-08-25 11:01:49 +08:00
|
|
|
fn engine_get_doc(&self, _ident: &str) -> Option<String> {
|
2023-08-25 09:12:15 +08:00
|
|
|
None
|
2023-07-13 12:39:27 +08:00
|
|
|
}
|
2023-08-20 13:13:56 +08:00
|
|
|
}
|