|
|
@ -21,17 +21,19 @@ use helix_view::{
|
|
|
|
Document, DocumentId, Editor, ViewId,
|
|
|
|
Document, DocumentId, Editor, ViewId,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
use once_cell::sync::Lazy;
|
|
|
|
use once_cell::sync::Lazy;
|
|
|
|
use serde_json::Value;
|
|
|
|
|
|
|
|
use steel::{
|
|
|
|
use steel::{
|
|
|
|
gc::unsafe_erased_pointers::CustomReference,
|
|
|
|
gc::unsafe_erased_pointers::CustomReference,
|
|
|
|
rerrs::ErrorKind,
|
|
|
|
rerrs::ErrorKind,
|
|
|
|
rvals::{as_underlying_type, FromSteelVal, IntoSteelVal, SteelString},
|
|
|
|
rvals::{as_underlying_type, FromSteelVal, IntoSteelVal, SteelString},
|
|
|
|
steel_vm::{engine::Engine, register_fn::RegisterFn},
|
|
|
|
steel_vm::{engine::Engine, register_fn::RegisterFn},
|
|
|
|
steelerr, List, SteelErr, SteelVal,
|
|
|
|
steelerr, SteelErr, SteelVal,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
use std::{
|
|
|
|
use std::{
|
|
|
|
borrow::Cow, collections::HashMap, ops::Deref, path::PathBuf, sync::atomic::AtomicUsize,
|
|
|
|
borrow::Cow,
|
|
|
|
|
|
|
|
collections::HashMap,
|
|
|
|
|
|
|
|
path::PathBuf,
|
|
|
|
|
|
|
|
sync::atomic::{AtomicUsize, Ordering},
|
|
|
|
time::Duration,
|
|
|
|
time::Duration,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
use std::{
|
|
|
|
use std::{
|
|
|
@ -56,13 +58,20 @@ use components::SteelDynamicComponent;
|
|
|
|
use super::{components, Context, MappableCommand, TYPABLE_COMMAND_LIST};
|
|
|
|
use super::{components, Context, MappableCommand, TYPABLE_COMMAND_LIST};
|
|
|
|
use insert::{insert_char, insert_string};
|
|
|
|
use insert::{insert_char, insert_string};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static ENGINE_COUNT: AtomicUsize = AtomicUsize::new(0);
|
|
|
|
|
|
|
|
|
|
|
|
// TODO:
|
|
|
|
// TODO:
|
|
|
|
// I'm not entirely sure this is correct, however from observation it seems that
|
|
|
|
// I'm not entirely sure this is correct, however from observation it seems that
|
|
|
|
// interactions with this really only happen on one thread. I haven't yet found
|
|
|
|
// interactions with this really only happen on one thread. I haven't yet found
|
|
|
|
// multiple instances of the engine getting created. I'll need to go observe how
|
|
|
|
// multiple instances of the engine getting created. I'll need to go observe how
|
|
|
|
// and when the engine gets accessed.
|
|
|
|
// and when the engine gets accessed.
|
|
|
|
thread_local! {
|
|
|
|
thread_local! {
|
|
|
|
pub static ENGINE: std::rc::Rc<std::cell::RefCell<steel::steel_vm::engine::Engine>> = configure_engine();
|
|
|
|
pub static ENGINE: std::rc::Rc<std::cell::RefCell<steel::steel_vm::engine::Engine>> = {
|
|
|
|
|
|
|
|
if ENGINE_COUNT.fetch_add(1, Ordering::SeqCst) != 0 {
|
|
|
|
|
|
|
|
panic!("More than one instance of the steel runtime is not allowed!");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
configure_engine()
|
|
|
|
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub struct KeyMapApi {
|
|
|
|
pub struct KeyMapApi {
|
|
|
@ -94,7 +103,8 @@ impl KeyMapApi {
|
|
|
|
// and can instead just refer to the single configuration object.
|
|
|
|
// and can instead just refer to the single configuration object.
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Possibly also introduce buffer / language specific keybindings
|
|
|
|
// Possibly also introduce buffer / language specific keybindings
|
|
|
|
// there as well.
|
|
|
|
// there as well, however how that interaction is done is still up
|
|
|
|
|
|
|
|
// for debate.
|
|
|
|
thread_local! {
|
|
|
|
thread_local! {
|
|
|
|
pub static BUFFER_OR_EXTENSION_KEYBINDING_MAP: SteelVal =
|
|
|
|
pub static BUFFER_OR_EXTENSION_KEYBINDING_MAP: SteelVal =
|
|
|
|
SteelVal::boxed(SteelVal::empty_hashmap());
|
|
|
|
SteelVal::boxed(SteelVal::empty_hashmap());
|
|
|
@ -135,11 +145,14 @@ fn load_keymap_api(engine: &mut Engine, api: KeyMapApi) {
|
|
|
|
engine.register_module(module);
|
|
|
|
engine.register_module(module);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn load_static_commands(engine: &mut Engine) {
|
|
|
|
fn load_static_commands(engine: &mut Engine, generate_sources: bool) {
|
|
|
|
let mut module = BuiltInModule::new("helix/core/static");
|
|
|
|
let mut module = BuiltInModule::new("helix/core/static");
|
|
|
|
|
|
|
|
|
|
|
|
let mut builtin_static_command_module =
|
|
|
|
let mut builtin_static_command_module = if generate_sources {
|
|
|
|
"(require-builtin helix/core/static as helix.static.)".to_string();
|
|
|
|
"(require-builtin helix/core/static as helix.static.)".to_string()
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
"".to_string()
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
for command in TYPABLE_COMMAND_LIST {
|
|
|
|
for command in TYPABLE_COMMAND_LIST {
|
|
|
|
let func = |cx: &mut Context| {
|
|
|
|
let func = |cx: &mut Context| {
|
|
|
@ -161,6 +174,7 @@ fn load_static_commands(engine: &mut Engine) {
|
|
|
|
if let MappableCommand::Static { name, fun, .. } = command {
|
|
|
|
if let MappableCommand::Static { name, fun, .. } = command {
|
|
|
|
module.register_fn(name, fun);
|
|
|
|
module.register_fn(name, fun);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if generate_sources {
|
|
|
|
builtin_static_command_module.push_str(&format!(
|
|
|
|
builtin_static_command_module.push_str(&format!(
|
|
|
|
r#"
|
|
|
|
r#"
|
|
|
|
(provide {})
|
|
|
|
(provide {})
|
|
|
@ -171,8 +185,10 @@ fn load_static_commands(engine: &mut Engine) {
|
|
|
|
));
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let mut template_function_arity_1 = |name: &str| {
|
|
|
|
let mut template_function_arity_1 = |name: &str| {
|
|
|
|
|
|
|
|
if generate_sources {
|
|
|
|
builtin_static_command_module.push_str(&format!(
|
|
|
|
builtin_static_command_module.push_str(&format!(
|
|
|
|
r#"
|
|
|
|
r#"
|
|
|
|
(provide {})
|
|
|
|
(provide {})
|
|
|
@ -181,6 +197,7 @@ fn load_static_commands(engine: &mut Engine) {
|
|
|
|
"#,
|
|
|
|
"#,
|
|
|
|
name, name, name
|
|
|
|
name, name, name
|
|
|
|
));
|
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Adhoc static commands that probably needs evaluating
|
|
|
|
// Adhoc static commands that probably needs evaluating
|
|
|
@ -209,6 +226,7 @@ fn load_static_commands(engine: &mut Engine) {
|
|
|
|
template_function_arity_1("cx->current-file");
|
|
|
|
template_function_arity_1("cx->current-file");
|
|
|
|
|
|
|
|
|
|
|
|
let mut template_function_arity_0 = |name: &str| {
|
|
|
|
let mut template_function_arity_0 = |name: &str| {
|
|
|
|
|
|
|
|
if generate_sources {
|
|
|
|
builtin_static_command_module.push_str(&format!(
|
|
|
|
builtin_static_command_module.push_str(&format!(
|
|
|
|
r#"
|
|
|
|
r#"
|
|
|
|
(provide {})
|
|
|
|
(provide {})
|
|
|
@ -217,6 +235,7 @@ fn load_static_commands(engine: &mut Engine) {
|
|
|
|
"#,
|
|
|
|
"#,
|
|
|
|
name, name, name
|
|
|
|
name, name, name
|
|
|
|
));
|
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Arity 0
|
|
|
|
// Arity 0
|
|
|
@ -242,6 +261,7 @@ fn load_static_commands(engine: &mut Engine) {
|
|
|
|
template_function_arity_0("move-window-far-right");
|
|
|
|
template_function_arity_0("move-window-far-right");
|
|
|
|
|
|
|
|
|
|
|
|
let mut template_function_no_context = |name: &str| {
|
|
|
|
let mut template_function_no_context = |name: &str| {
|
|
|
|
|
|
|
|
if generate_sources {
|
|
|
|
builtin_static_command_module.push_str(&format!(
|
|
|
|
builtin_static_command_module.push_str(&format!(
|
|
|
|
r#"
|
|
|
|
r#"
|
|
|
|
(provide {})
|
|
|
|
(provide {})
|
|
|
@ -249,6 +269,7 @@ fn load_static_commands(engine: &mut Engine) {
|
|
|
|
"#,
|
|
|
|
"#,
|
|
|
|
name, name, name
|
|
|
|
name, name, name
|
|
|
|
))
|
|
|
|
))
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
module.register_fn("get-helix-scm-path", get_helix_scm_path);
|
|
|
|
module.register_fn("get-helix-scm-path", get_helix_scm_path);
|
|
|
@ -257,6 +278,7 @@ fn load_static_commands(engine: &mut Engine) {
|
|
|
|
template_function_no_context("get-helix-scm-path");
|
|
|
|
template_function_no_context("get-helix-scm-path");
|
|
|
|
template_function_no_context("get-init-scm-path");
|
|
|
|
template_function_no_context("get-init-scm-path");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if generate_sources {
|
|
|
|
let mut target_directory = helix_runtime_search_path();
|
|
|
|
let mut target_directory = helix_runtime_search_path();
|
|
|
|
|
|
|
|
|
|
|
|
if !target_directory.exists() {
|
|
|
|
if !target_directory.exists() {
|
|
|
@ -266,40 +288,20 @@ fn load_static_commands(engine: &mut Engine) {
|
|
|
|
target_directory.push("static.scm");
|
|
|
|
target_directory.push("static.scm");
|
|
|
|
|
|
|
|
|
|
|
|
std::fs::write(target_directory, builtin_static_command_module).unwrap();
|
|
|
|
std::fs::write(target_directory, builtin_static_command_module).unwrap();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
engine.register_module(module);
|
|
|
|
engine.register_module(module);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn load_typed_commands(engine: &mut Engine) {
|
|
|
|
fn load_typed_commands(engine: &mut Engine, generate_sources: bool) {
|
|
|
|
let mut module = BuiltInModule::new("helix/core/typable".to_string());
|
|
|
|
let mut module = BuiltInModule::new("helix/core/typable".to_string());
|
|
|
|
let mut builtin_typable_command_module =
|
|
|
|
|
|
|
|
"(require-builtin helix/core/typable as helix.)".to_string();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
let mut builtin_typable_command_module = if generate_sources {
|
|
|
|
let func = |cx: &mut Context, args: &[Cow<str>]| {
|
|
|
|
"(require-builtin helix/core/typable as helix.)".to_string()
|
|
|
|
let mut cx = compositor::Context {
|
|
|
|
} else {
|
|
|
|
editor: cx.editor,
|
|
|
|
"".to_string()
|
|
|
|
scroll: None,
|
|
|
|
|
|
|
|
jobs: cx.jobs,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set_options(&mut cx, args, PromptEvent::Validate)
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
module.register_fn("set-options", func);
|
|
|
|
|
|
|
|
let name = "set-options";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
builtin_typable_command_module.push_str(&format!(
|
|
|
|
|
|
|
|
r#"
|
|
|
|
|
|
|
|
(provide {})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define ({} . args)
|
|
|
|
|
|
|
|
(helix.{} *helix.cx* args))
|
|
|
|
|
|
|
|
"#,
|
|
|
|
|
|
|
|
name, name, name
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Register everything in the typable command list. Now these are all available
|
|
|
|
// Register everything in the typable command list. Now these are all available
|
|
|
|
for command in TYPABLE_COMMAND_LIST {
|
|
|
|
for command in TYPABLE_COMMAND_LIST {
|
|
|
|
let func = |cx: &mut Context, args: &[Cow<str>]| {
|
|
|
|
let func = |cx: &mut Context, args: &[Cow<str>]| {
|
|
|
@ -314,6 +316,7 @@ fn load_typed_commands(engine: &mut Engine) {
|
|
|
|
|
|
|
|
|
|
|
|
module.register_fn(command.name, func);
|
|
|
|
module.register_fn(command.name, func);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if generate_sources {
|
|
|
|
// Create an ephemeral builtin module to reference until I figure out how
|
|
|
|
// Create an ephemeral builtin module to reference until I figure out how
|
|
|
|
// to wrap the functions with a reference to the engine context better.
|
|
|
|
// to wrap the functions with a reference to the engine context better.
|
|
|
|
builtin_typable_command_module.push_str(&format!(
|
|
|
|
builtin_typable_command_module.push_str(&format!(
|
|
|
@ -340,7 +343,9 @@ fn load_typed_commands(engine: &mut Engine) {
|
|
|
|
command.name
|
|
|
|
command.name
|
|
|
|
));
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if generate_sources {
|
|
|
|
let mut target_directory = helix_runtime_search_path();
|
|
|
|
let mut target_directory = helix_runtime_search_path();
|
|
|
|
if !target_directory.exists() {
|
|
|
|
if !target_directory.exists() {
|
|
|
|
std::fs::create_dir(&target_directory).unwrap();
|
|
|
|
std::fs::create_dir(&target_directory).unwrap();
|
|
|
@ -349,6 +354,7 @@ fn load_typed_commands(engine: &mut Engine) {
|
|
|
|
target_directory.push("commands.scm");
|
|
|
|
target_directory.push("commands.scm");
|
|
|
|
|
|
|
|
|
|
|
|
std::fs::write(target_directory, builtin_typable_command_module).unwrap();
|
|
|
|
std::fs::write(target_directory, builtin_typable_command_module).unwrap();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
engine.register_module(module);
|
|
|
|
engine.register_module(module);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -389,7 +395,27 @@ fn fp_max_depth(config: &mut FilePickerConfig, option: Option<usize>) {
|
|
|
|
config.max_depth = option;
|
|
|
|
config.max_depth = option;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn load_configuration_api(engine: &mut Engine) {
|
|
|
|
fn sw_enable(config: &mut SoftWrap, option: Option<bool>) {
|
|
|
|
|
|
|
|
config.enable = option;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn sw_max_wrap(config: &mut SoftWrap, option: Option<u16>) {
|
|
|
|
|
|
|
|
config.max_wrap = option;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn sw_max_indent_retain(config: &mut SoftWrap, option: Option<u16>) {
|
|
|
|
|
|
|
|
config.max_indent_retain = option;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn sw_wrap_indicator(config: &mut SoftWrap, option: Option<String>) {
|
|
|
|
|
|
|
|
config.wrap_indicator = option;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn wrap_at_text_width(config: &mut SoftWrap, option: Option<bool>) {
|
|
|
|
|
|
|
|
config.wrap_at_text_width = option;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn load_configuration_api(engine: &mut Engine, generate_sources: bool) {
|
|
|
|
let mut module = BuiltInModule::new("helix/core/configuration");
|
|
|
|
let mut module = BuiltInModule::new("helix/core/configuration");
|
|
|
|
|
|
|
|
|
|
|
|
module.register_fn("update-configuration!", |ctx: &mut Context| {
|
|
|
|
module.register_fn("update-configuration!", |ctx: &mut Context| {
|
|
|
@ -400,6 +426,96 @@ fn load_configuration_api(engine: &mut Engine) {
|
|
|
|
.unwrap();
|
|
|
|
.unwrap();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
module
|
|
|
|
|
|
|
|
.register_fn("raw-file-picker", || FilePickerConfig::default())
|
|
|
|
|
|
|
|
.register_fn("register-file-picker", HelixConfiguration::file_picker)
|
|
|
|
|
|
|
|
.register_fn("fp-hidden", fp_hidden)
|
|
|
|
|
|
|
|
.register_fn("fp-follow-symlinks", fp_follow_symlinks)
|
|
|
|
|
|
|
|
.register_fn("fp-deduplicate-links", fp_deduplicate_links)
|
|
|
|
|
|
|
|
.register_fn("fp-parents", fp_parents)
|
|
|
|
|
|
|
|
.register_fn("fp-ignore", fp_ignore)
|
|
|
|
|
|
|
|
.register_fn("fp-git-ignore", fp_git_ignore)
|
|
|
|
|
|
|
|
.register_fn("fp-git-global", fp_git_global)
|
|
|
|
|
|
|
|
.register_fn("fp-git-exclude", fp_git_exclude)
|
|
|
|
|
|
|
|
.register_fn("fp-max-depth", fp_max_depth);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
module
|
|
|
|
|
|
|
|
.register_fn("raw-soft-wrap", || SoftWrap::default())
|
|
|
|
|
|
|
|
.register_fn("register-soft-wrap", HelixConfiguration::soft_wrap)
|
|
|
|
|
|
|
|
.register_fn("sw-enable", sw_enable)
|
|
|
|
|
|
|
|
.register_fn("sw-max-wrap", sw_max_wrap)
|
|
|
|
|
|
|
|
.register_fn("sw-max-indent-retain", sw_max_indent_retain)
|
|
|
|
|
|
|
|
.register_fn("sw-wrap-indicator", sw_wrap_indicator)
|
|
|
|
|
|
|
|
.register_fn("sw-wrap-at-text-width", wrap_at_text_width);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
module
|
|
|
|
|
|
|
|
.register_fn("scrolloff", HelixConfiguration::scrolloff)
|
|
|
|
|
|
|
|
.register_fn("scroll_lines", HelixConfiguration::scroll_lines)
|
|
|
|
|
|
|
|
.register_fn("mouse", HelixConfiguration::mouse)
|
|
|
|
|
|
|
|
.register_fn("shell", HelixConfiguration::shell)
|
|
|
|
|
|
|
|
.register_fn("line-number", HelixConfiguration::line_number)
|
|
|
|
|
|
|
|
.register_fn("cursorline", HelixConfiguration::cursorline)
|
|
|
|
|
|
|
|
.register_fn("cursorcolumn", HelixConfiguration::cursorcolumn)
|
|
|
|
|
|
|
|
.register_fn("middle-click-paste", HelixConfiguration::middle_click_paste)
|
|
|
|
|
|
|
|
.register_fn("auto-pairs", HelixConfiguration::auto_pairs)
|
|
|
|
|
|
|
|
// Specific constructors for the auto pairs configuration
|
|
|
|
|
|
|
|
.register_fn("auto-pairs-default", |enabled: bool| {
|
|
|
|
|
|
|
|
AutoPairConfig::Enable(enabled)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.register_fn("auto-pairs-map", |map: HashMap<char, char>| {
|
|
|
|
|
|
|
|
AutoPairConfig::Pairs(map)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.register_fn("auto-completion", HelixConfiguration::auto_completion)
|
|
|
|
|
|
|
|
.register_fn("auto-format", HelixConfiguration::auto_format)
|
|
|
|
|
|
|
|
.register_fn("auto-save", HelixConfiguration::auto_save)
|
|
|
|
|
|
|
|
.register_fn("text-width", HelixConfiguration::text_width)
|
|
|
|
|
|
|
|
.register_fn("idle-timeout", HelixConfiguration::idle_timeout)
|
|
|
|
|
|
|
|
.register_fn("completion-timeout", HelixConfiguration::completion_timeout)
|
|
|
|
|
|
|
|
.register_fn(
|
|
|
|
|
|
|
|
"preview-completion-insert",
|
|
|
|
|
|
|
|
HelixConfiguration::preview_completion_insert,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.register_fn(
|
|
|
|
|
|
|
|
"completion-trigger-len",
|
|
|
|
|
|
|
|
HelixConfiguration::completion_trigger_len,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.register_fn("completion-replace", HelixConfiguration::completion_replace)
|
|
|
|
|
|
|
|
.register_fn("auto-info", HelixConfiguration::auto_info)
|
|
|
|
|
|
|
|
.register_fn("cursor-shape", HelixConfiguration::cursor_shape)
|
|
|
|
|
|
|
|
.register_fn("true-color", HelixConfiguration::true_color)
|
|
|
|
|
|
|
|
.register_fn(
|
|
|
|
|
|
|
|
"insert-final-newline",
|
|
|
|
|
|
|
|
HelixConfiguration::insert_final_newline,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.register_fn("color-modes", HelixConfiguration::color_modes)
|
|
|
|
|
|
|
|
.register_fn("gutters", HelixConfiguration::gutters)
|
|
|
|
|
|
|
|
// .register_fn("file-picker", HelixConfiguration::file_picker)
|
|
|
|
|
|
|
|
.register_fn("statusline", HelixConfiguration::statusline)
|
|
|
|
|
|
|
|
.register_fn("undercurl", HelixConfiguration::undercurl)
|
|
|
|
|
|
|
|
.register_fn("search", HelixConfiguration::search)
|
|
|
|
|
|
|
|
.register_fn("lsp", HelixConfiguration::lsp)
|
|
|
|
|
|
|
|
.register_fn("terminal", HelixConfiguration::terminal)
|
|
|
|
|
|
|
|
.register_fn("rulers", HelixConfiguration::rulers)
|
|
|
|
|
|
|
|
.register_fn("whitespace", HelixConfiguration::whitespace)
|
|
|
|
|
|
|
|
.register_fn("bufferline", HelixConfiguration::bufferline)
|
|
|
|
|
|
|
|
.register_fn("indent-guides", HelixConfiguration::indent_guides)
|
|
|
|
|
|
|
|
.register_fn("soft-wrap", HelixConfiguration::soft_wrap)
|
|
|
|
|
|
|
|
.register_fn(
|
|
|
|
|
|
|
|
"workspace-lsp-roots",
|
|
|
|
|
|
|
|
HelixConfiguration::workspace_lsp_roots,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.register_fn(
|
|
|
|
|
|
|
|
"default-line-ending",
|
|
|
|
|
|
|
|
HelixConfiguration::default_line_ending,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.register_fn("smart-tab", HelixConfiguration::smart_tab);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Keybinding stuff
|
|
|
|
|
|
|
|
module
|
|
|
|
|
|
|
|
.register_fn("keybindings", HelixConfiguration::keybindings)
|
|
|
|
|
|
|
|
.register_fn("get-keybindings", HelixConfiguration::get_keybindings);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if generate_sources {
|
|
|
|
let mut builtin_configuration_module =
|
|
|
|
let mut builtin_configuration_module =
|
|
|
|
"(require-builtin helix/core/configuration as helix.)".to_string();
|
|
|
|
"(require-builtin helix/core/configuration as helix.)".to_string();
|
|
|
|
|
|
|
|
|
|
|
@ -411,6 +527,40 @@ fn load_configuration_api(engine: &mut Engine) {
|
|
|
|
"#,
|
|
|
|
"#,
|
|
|
|
));
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Register the get keybindings function
|
|
|
|
|
|
|
|
builtin_configuration_module.push_str(&format!(
|
|
|
|
|
|
|
|
r#"
|
|
|
|
|
|
|
|
(provide get-keybindings)
|
|
|
|
|
|
|
|
(define (get-keybindings)
|
|
|
|
|
|
|
|
(helix.get-keybindings *helix.cx*))
|
|
|
|
|
|
|
|
"#,
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut template_soft_wrap = |name: &str| {
|
|
|
|
|
|
|
|
builtin_configuration_module.push_str(&format!(
|
|
|
|
|
|
|
|
r#"
|
|
|
|
|
|
|
|
(provide {})
|
|
|
|
|
|
|
|
(define ({} arg)
|
|
|
|
|
|
|
|
(lambda (picker)
|
|
|
|
|
|
|
|
(helix.{} picker arg)
|
|
|
|
|
|
|
|
picker))
|
|
|
|
|
|
|
|
"#,
|
|
|
|
|
|
|
|
name, name, name
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let soft_wrap_functions = &[
|
|
|
|
|
|
|
|
"sw-enable",
|
|
|
|
|
|
|
|
"sw-max-wrap",
|
|
|
|
|
|
|
|
"sw-max-indent-retain",
|
|
|
|
|
|
|
|
"sw-wrap-indicator",
|
|
|
|
|
|
|
|
"sw-wrap-at-text-width",
|
|
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for name in soft_wrap_functions {
|
|
|
|
|
|
|
|
template_soft_wrap(name);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let mut template_file_picker_function = |name: &str| {
|
|
|
|
let mut template_file_picker_function = |name: &str| {
|
|
|
|
builtin_configuration_module.push_str(&format!(
|
|
|
|
builtin_configuration_module.push_str(&format!(
|
|
|
|
r#"
|
|
|
|
r#"
|
|
|
@ -450,18 +600,15 @@ fn load_configuration_api(engine: &mut Engine) {
|
|
|
|
"#,
|
|
|
|
"#,
|
|
|
|
));
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
module
|
|
|
|
builtin_configuration_module.push_str(&format!(
|
|
|
|
.register_fn("raw-file-picker", || FilePickerConfig::default())
|
|
|
|
r#"
|
|
|
|
.register_fn("register-file-picker", HelixConfiguration::file_picker)
|
|
|
|
(provide soft-wrap)
|
|
|
|
.register_fn("fp-hidden", fp_hidden)
|
|
|
|
(define (soft-wrap . args)
|
|
|
|
.register_fn("fp-follow-symlinks", fp_follow_symlinks)
|
|
|
|
(helix.register-soft-wrap
|
|
|
|
.register_fn("fp-deduplicate-links", fp_deduplicate_links)
|
|
|
|
*helix.config*
|
|
|
|
.register_fn("fp-parents", fp_parents)
|
|
|
|
(foldl (lambda (func config) (func config)) (helix.raw-soft-wrap) args)))
|
|
|
|
.register_fn("fp-ignore", fp_ignore)
|
|
|
|
"#,
|
|
|
|
.register_fn("fp-git-ignore", fp_git_ignore)
|
|
|
|
));
|
|
|
|
.register_fn("fp-git-global", fp_git_global)
|
|
|
|
|
|
|
|
.register_fn("fp-git-exclude", fp_git_exclude)
|
|
|
|
|
|
|
|
.register_fn("fp-max-depth", fp_max_depth);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut template_function_arity_1 = |name: &str| {
|
|
|
|
let mut template_function_arity_1 = |name: &str| {
|
|
|
|
builtin_configuration_module.push_str(&format!(
|
|
|
|
builtin_configuration_module.push_str(&format!(
|
|
|
@ -513,74 +660,13 @@ fn load_configuration_api(engine: &mut Engine) {
|
|
|
|
"workspace-lsp-roots",
|
|
|
|
"workspace-lsp-roots",
|
|
|
|
"default-line-ending",
|
|
|
|
"default-line-ending",
|
|
|
|
"smart-tab",
|
|
|
|
"smart-tab",
|
|
|
|
|
|
|
|
"keybindings",
|
|
|
|
];
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
for func in functions {
|
|
|
|
for func in functions {
|
|
|
|
template_function_arity_1(func);
|
|
|
|
template_function_arity_1(func);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
module
|
|
|
|
|
|
|
|
.register_fn("scrolloff", HelixConfiguration::scrolloff)
|
|
|
|
|
|
|
|
.register_fn("scroll_lines", HelixConfiguration::scroll_lines)
|
|
|
|
|
|
|
|
.register_fn("mouse", HelixConfiguration::mouse)
|
|
|
|
|
|
|
|
.register_fn("shell", HelixConfiguration::shell)
|
|
|
|
|
|
|
|
.register_fn("line-number", HelixConfiguration::line_number)
|
|
|
|
|
|
|
|
.register_fn("cursorline", HelixConfiguration::cursorline)
|
|
|
|
|
|
|
|
.register_fn("cursorcolumn", HelixConfiguration::cursorcolumn)
|
|
|
|
|
|
|
|
.register_fn("middle-click-paste", HelixConfiguration::middle_click_paste)
|
|
|
|
|
|
|
|
.register_fn("auto-pairs", HelixConfiguration::auto_pairs)
|
|
|
|
|
|
|
|
// Specific constructors for the auto pairs configuration
|
|
|
|
|
|
|
|
.register_fn("auto-pairs-default", |enabled: bool| {
|
|
|
|
|
|
|
|
AutoPairConfig::Enable(enabled)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.register_fn("auto-pairs-map", |map: HashMap<char, char>| {
|
|
|
|
|
|
|
|
AutoPairConfig::Pairs(map)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.register_fn("auto-completion", HelixConfiguration::auto_completion)
|
|
|
|
|
|
|
|
.register_fn("auto-format", HelixConfiguration::auto_format)
|
|
|
|
|
|
|
|
.register_fn("auto-save", HelixConfiguration::auto_save)
|
|
|
|
|
|
|
|
.register_fn("text-width", HelixConfiguration::text_width)
|
|
|
|
|
|
|
|
.register_fn("idle-timeout", HelixConfiguration::idle_timeout)
|
|
|
|
|
|
|
|
.register_fn("completion-timeout", HelixConfiguration::completion_timeout)
|
|
|
|
|
|
|
|
.register_fn(
|
|
|
|
|
|
|
|
"preview-completion-insert",
|
|
|
|
|
|
|
|
HelixConfiguration::preview_completion_insert,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.register_fn(
|
|
|
|
|
|
|
|
"completion-trigger-len",
|
|
|
|
|
|
|
|
HelixConfiguration::completion_trigger_len,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.register_fn("completion-replace", HelixConfiguration::completion_replace)
|
|
|
|
|
|
|
|
.register_fn("auto-info", HelixConfiguration::auto_info)
|
|
|
|
|
|
|
|
.register_fn("cursor-shape", HelixConfiguration::cursor_shape)
|
|
|
|
|
|
|
|
.register_fn("true-color", HelixConfiguration::true_color)
|
|
|
|
|
|
|
|
.register_fn(
|
|
|
|
|
|
|
|
"insert-final-newline",
|
|
|
|
|
|
|
|
HelixConfiguration::insert_final_newline,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.register_fn("color-modes", HelixConfiguration::color_modes)
|
|
|
|
|
|
|
|
.register_fn("gutters", HelixConfiguration::gutters)
|
|
|
|
|
|
|
|
// .register_fn("file-picker", HelixConfiguration::file_picker)
|
|
|
|
|
|
|
|
.register_fn("statusline", HelixConfiguration::statusline)
|
|
|
|
|
|
|
|
.register_fn("undercurl", HelixConfiguration::undercurl)
|
|
|
|
|
|
|
|
.register_fn("search", HelixConfiguration::search)
|
|
|
|
|
|
|
|
.register_fn("lsp", HelixConfiguration::lsp)
|
|
|
|
|
|
|
|
.register_fn("terminal", HelixConfiguration::terminal)
|
|
|
|
|
|
|
|
.register_fn("rulers", HelixConfiguration::rulers)
|
|
|
|
|
|
|
|
.register_fn("whitespace", HelixConfiguration::whitespace)
|
|
|
|
|
|
|
|
.register_fn("bufferline", HelixConfiguration::bufferline)
|
|
|
|
|
|
|
|
.register_fn("indent-guides", HelixConfiguration::indent_guides)
|
|
|
|
|
|
|
|
// .register_fn("soft-wrap", HelixConfiguration::soft_wrap)
|
|
|
|
|
|
|
|
.register_fn(
|
|
|
|
|
|
|
|
"workspace-lsp-roots",
|
|
|
|
|
|
|
|
HelixConfiguration::workspace_lsp_roots,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.register_fn(
|
|
|
|
|
|
|
|
"default-line-ending",
|
|
|
|
|
|
|
|
HelixConfiguration::default_line_ending,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.register_fn("smart-tab", HelixConfiguration::smart_tab);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut target_directory = helix_runtime_search_path();
|
|
|
|
let mut target_directory = helix_runtime_search_path();
|
|
|
|
|
|
|
|
|
|
|
|
if !target_directory.exists() {
|
|
|
|
if !target_directory.exists() {
|
|
|
@ -590,13 +676,46 @@ fn load_configuration_api(engine: &mut Engine) {
|
|
|
|
target_directory.push("configuration.scm");
|
|
|
|
target_directory.push("configuration.scm");
|
|
|
|
|
|
|
|
|
|
|
|
std::fs::write(target_directory, builtin_configuration_module).unwrap();
|
|
|
|
std::fs::write(target_directory, builtin_configuration_module).unwrap();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
engine.register_module(module);
|
|
|
|
engine.register_module(module);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn load_editor_api(engine: &mut Engine) {
|
|
|
|
fn load_editor_api(engine: &mut Engine, generate_sources: bool) {
|
|
|
|
let mut module = BuiltInModule::new("helix/core/editor");
|
|
|
|
let mut module = BuiltInModule::new("helix/core/editor");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Arity 0
|
|
|
|
|
|
|
|
module.register_fn("editor-focus", cx_current_focus);
|
|
|
|
|
|
|
|
module.register_fn("editor-mode", cx_get_mode);
|
|
|
|
|
|
|
|
module.register_fn("cx->themes", get_themes);
|
|
|
|
|
|
|
|
module.register_fn("editor-all-documents", cx_editor_all_documents);
|
|
|
|
|
|
|
|
module.register_fn("cx->cursor", |cx: &mut Context| cx.editor.cursor());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Arity 1
|
|
|
|
|
|
|
|
module.register_fn("editor->doc-id", cx_get_document_id);
|
|
|
|
|
|
|
|
module.register_fn("editor-switch!", cx_switch);
|
|
|
|
|
|
|
|
module.register_fn("editor-set-focus!", |cx: &mut Context, view_id: ViewId| {
|
|
|
|
|
|
|
|
cx.editor.focus(view_id)
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
module.register_fn("editor-set-mode!", cx_set_mode);
|
|
|
|
|
|
|
|
module.register_fn("editor-doc-in-view?", cx_is_document_in_view);
|
|
|
|
|
|
|
|
module.register_fn("set-scratch-buffer-name!", set_scratch_buffer_name);
|
|
|
|
|
|
|
|
module.register_fn("editor-doc-exists?", cx_document_exists);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Arity 1
|
|
|
|
|
|
|
|
RegisterFn::<
|
|
|
|
|
|
|
|
_,
|
|
|
|
|
|
|
|
steel::steel_vm::register_fn::MarkerWrapper8<(
|
|
|
|
|
|
|
|
Context,
|
|
|
|
|
|
|
|
DocumentId,
|
|
|
|
|
|
|
|
Document,
|
|
|
|
|
|
|
|
Document,
|
|
|
|
|
|
|
|
Context,
|
|
|
|
|
|
|
|
)>,
|
|
|
|
|
|
|
|
Document,
|
|
|
|
|
|
|
|
>::register_fn(&mut module, "editor->get-document", cx_get_document); // I do not like this
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if generate_sources {
|
|
|
|
let mut builtin_editor_command_module =
|
|
|
|
let mut builtin_editor_command_module =
|
|
|
|
"(require-builtin helix/core/editor as helix.)".to_string();
|
|
|
|
"(require-builtin helix/core/editor as helix.)".to_string();
|
|
|
|
|
|
|
|
|
|
|
@ -611,13 +730,6 @@ fn load_editor_api(engine: &mut Engine) {
|
|
|
|
));
|
|
|
|
));
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Arity 0
|
|
|
|
|
|
|
|
module.register_fn("editor-focus", cx_current_focus);
|
|
|
|
|
|
|
|
module.register_fn("editor-mode", cx_get_mode);
|
|
|
|
|
|
|
|
module.register_fn("cx->themes", get_themes);
|
|
|
|
|
|
|
|
module.register_fn("editor-all-documents", cx_editor_all_documents);
|
|
|
|
|
|
|
|
module.register_fn("cx->cursor", |cx: &mut Context| cx.editor.cursor());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template_function_arity_0("editor-focus");
|
|
|
|
template_function_arity_0("editor-focus");
|
|
|
|
template_function_arity_0("editor-mode");
|
|
|
|
template_function_arity_0("editor-mode");
|
|
|
|
template_function_arity_0("cx->themes");
|
|
|
|
template_function_arity_0("cx->themes");
|
|
|
@ -635,17 +747,6 @@ fn load_editor_api(engine: &mut Engine) {
|
|
|
|
));
|
|
|
|
));
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Arity 1
|
|
|
|
|
|
|
|
module.register_fn("editor->doc-id", cx_get_document_id);
|
|
|
|
|
|
|
|
module.register_fn("editor-switch!", cx_switch);
|
|
|
|
|
|
|
|
module.register_fn("editor-set-focus!", |cx: &mut Context, view_id: ViewId| {
|
|
|
|
|
|
|
|
cx.editor.focus(view_id)
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
module.register_fn("editor-set-mode!", cx_set_mode);
|
|
|
|
|
|
|
|
module.register_fn("editor-doc-in-view?", cx_is_document_in_view);
|
|
|
|
|
|
|
|
module.register_fn("set-scratch-buffer-name!", set_scratch_buffer_name);
|
|
|
|
|
|
|
|
module.register_fn("editor-doc-exists?", cx_document_exists);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template_function_arity_1("editor->doc-id");
|
|
|
|
template_function_arity_1("editor->doc-id");
|
|
|
|
template_function_arity_1("editor-switch!");
|
|
|
|
template_function_arity_1("editor-switch!");
|
|
|
|
template_function_arity_1("editor-set-focus!");
|
|
|
|
template_function_arity_1("editor-set-focus!");
|
|
|
@ -655,41 +756,6 @@ fn load_editor_api(engine: &mut Engine) {
|
|
|
|
template_function_arity_1("editor-doc-exists?");
|
|
|
|
template_function_arity_1("editor-doc-exists?");
|
|
|
|
template_function_arity_1("editor->get-document");
|
|
|
|
template_function_arity_1("editor->get-document");
|
|
|
|
|
|
|
|
|
|
|
|
// Doesn't use the context
|
|
|
|
|
|
|
|
// module.register_fn("doc-id->usize", document_id_to_usize);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Arity 1
|
|
|
|
|
|
|
|
RegisterFn::<
|
|
|
|
|
|
|
|
_,
|
|
|
|
|
|
|
|
steel::steel_vm::register_fn::MarkerWrapper8<(
|
|
|
|
|
|
|
|
Context,
|
|
|
|
|
|
|
|
DocumentId,
|
|
|
|
|
|
|
|
Document,
|
|
|
|
|
|
|
|
Document,
|
|
|
|
|
|
|
|
Context,
|
|
|
|
|
|
|
|
)>,
|
|
|
|
|
|
|
|
Document,
|
|
|
|
|
|
|
|
>::register_fn(&mut module, "editor->get-document", cx_get_document); // I do not like this
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// module.register_fn("Document-path", document_path);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// module.register_fn("helix.context?", is_context);
|
|
|
|
|
|
|
|
// module.register_type::<DocumentId>("DocumentId?");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO:
|
|
|
|
|
|
|
|
// Position related functions. These probably should be defined alongside the actual impl for Custom in the core crate
|
|
|
|
|
|
|
|
// module.register_fn("position", helix_core::Position::new);
|
|
|
|
|
|
|
|
// module.register_fn("position-default", helix_core::Position::default);
|
|
|
|
|
|
|
|
// module.register_fn("position-row", |position: helix_core::Position| {
|
|
|
|
|
|
|
|
// position.row
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// module.register_fn("cx->themes", get_themes);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Not the best usage here, duplicating it in a bunch of spots for now
|
|
|
|
|
|
|
|
// let mut target_directory = PathBuf::from(std::env::var("HELIX_RUNTIME").unwrap());
|
|
|
|
|
|
|
|
// target_directory.push("cogs");
|
|
|
|
|
|
|
|
// target_directory.push("helix");
|
|
|
|
|
|
|
|
let mut target_directory = helix_runtime_search_path();
|
|
|
|
let mut target_directory = helix_runtime_search_path();
|
|
|
|
|
|
|
|
|
|
|
|
if !target_directory.exists() {
|
|
|
|
if !target_directory.exists() {
|
|
|
@ -699,6 +765,7 @@ fn load_editor_api(engine: &mut Engine) {
|
|
|
|
target_directory.push("editor.scm");
|
|
|
|
target_directory.push("editor.scm");
|
|
|
|
|
|
|
|
|
|
|
|
std::fs::write(target_directory, builtin_editor_command_module).unwrap();
|
|
|
|
std::fs::write(target_directory, builtin_editor_command_module).unwrap();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
engine.register_module(module);
|
|
|
|
engine.register_module(module);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -853,6 +920,12 @@ impl super::PluginSystem for SteelScriptingEngine {
|
|
|
|
.map(|x| x.clone().into())
|
|
|
|
.map(|x| x.clone().into())
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn generate_sources(&self) {
|
|
|
|
|
|
|
|
// Generate sources directly with a fresh engine
|
|
|
|
|
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
|
|
|
configure_builtin_sources(&mut engine, true);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl SteelScriptingEngine {
|
|
|
|
impl SteelScriptingEngine {
|
|
|
@ -1089,6 +1162,17 @@ impl HelixConfiguration {
|
|
|
|
self.configuration.store(Arc::new(config));
|
|
|
|
self.configuration.store(Arc::new(config));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Overlay new keybindings
|
|
|
|
|
|
|
|
fn keybindings(&self, keybindings: EmbeddedKeyMap) {
|
|
|
|
|
|
|
|
let mut app_config = self.load_config();
|
|
|
|
|
|
|
|
merge_keys(&mut app_config.keys, keybindings.0);
|
|
|
|
|
|
|
|
self.store_config(app_config);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn get_keybindings(&self) -> EmbeddedKeyMap {
|
|
|
|
|
|
|
|
EmbeddedKeyMap(self.load_config().keys.clone())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn scrolloff(&self, lines: usize) {
|
|
|
|
fn scrolloff(&self, lines: usize) {
|
|
|
|
let mut app_config = self.load_config();
|
|
|
|
let mut app_config = self.load_config();
|
|
|
|
app_config.editor.scrolloff = lines;
|
|
|
|
app_config.editor.scrolloff = lines;
|
|
|
@ -1424,9 +1508,6 @@ fn run_initialization_script(cx: &mut Context, configuration: Arc<ArcSwapAny<Arc
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// pub static KEYBINDING_QUEUE: Lazy<SharedKeyBindingsEventQueue> =
|
|
|
|
|
|
|
|
// Lazy::new(|| SharedKeyBindingsEventQueue::new());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub static EXPORTED_IDENTIFIERS: Lazy<ExportedIdentifiers> =
|
|
|
|
pub static EXPORTED_IDENTIFIERS: Lazy<ExportedIdentifiers> =
|
|
|
|
Lazy::new(|| ExportedIdentifiers::default());
|
|
|
|
Lazy::new(|| ExportedIdentifiers::default());
|
|
|
|
|
|
|
|
|
|
|
@ -1648,7 +1729,7 @@ impl SteelEngine {
|
|
|
|
pub fn call_function_by_name(
|
|
|
|
pub fn call_function_by_name(
|
|
|
|
&mut self,
|
|
|
|
&mut self,
|
|
|
|
function_name: SteelString,
|
|
|
|
function_name: SteelString,
|
|
|
|
args: List<SteelVal>,
|
|
|
|
args: Vec<SteelVal>,
|
|
|
|
) -> steel::rvals::Result<SteelVal> {
|
|
|
|
) -> steel::rvals::Result<SteelVal> {
|
|
|
|
self.0
|
|
|
|
self.0
|
|
|
|
.call_function_by_name_with_args(function_name.as_str(), args.into_iter().collect())
|
|
|
|
.call_function_by_name_with_args(function_name.as_str(), args.into_iter().collect())
|
|
|
@ -1659,7 +1740,7 @@ impl SteelEngine {
|
|
|
|
pub fn call_function(
|
|
|
|
pub fn call_function(
|
|
|
|
&mut self,
|
|
|
|
&mut self,
|
|
|
|
function: SteelVal,
|
|
|
|
function: SteelVal,
|
|
|
|
args: List<SteelVal>,
|
|
|
|
args: Vec<SteelVal>,
|
|
|
|
) -> steel::rvals::Result<SteelVal> {
|
|
|
|
) -> steel::rvals::Result<SteelVal> {
|
|
|
|
self.0
|
|
|
|
self.0
|
|
|
|
.call_function_with_args(function, args.into_iter().collect())
|
|
|
|
.call_function_with_args(function, args.into_iter().collect())
|
|
|
@ -1716,12 +1797,17 @@ fn load_engine_api(engine: &mut Engine) {
|
|
|
|
.register_fn("helix.controller.id->engine", id_to_engine);
|
|
|
|
.register_fn("helix.controller.id->engine", id_to_engine);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn load_misc_api(engine: &mut Engine) {
|
|
|
|
fn load_misc_api(engine: &mut Engine, generate_sources: bool) {
|
|
|
|
let mut module = BuiltInModule::new("helix/core/misc");
|
|
|
|
let mut module = BuiltInModule::new("helix/core/misc");
|
|
|
|
|
|
|
|
|
|
|
|
let mut builtin_misc_module = "(require-builtin helix/core/misc as helix.)".to_string();
|
|
|
|
let mut builtin_misc_module = if generate_sources {
|
|
|
|
|
|
|
|
"(require-builtin helix/core/misc as helix.)".to_string()
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
"".to_string()
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let mut template_function_arity_0 = |name: &str| {
|
|
|
|
let mut template_function_arity_0 = |name: &str| {
|
|
|
|
|
|
|
|
if generate_sources {
|
|
|
|
builtin_misc_module.push_str(&format!(
|
|
|
|
builtin_misc_module.push_str(&format!(
|
|
|
|
r#"
|
|
|
|
r#"
|
|
|
|
(provide {})
|
|
|
|
(provide {})
|
|
|
@ -1730,6 +1816,7 @@ fn load_misc_api(engine: &mut Engine) {
|
|
|
|
"#,
|
|
|
|
"#,
|
|
|
|
name, name, name
|
|
|
|
name, name, name
|
|
|
|
));
|
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Arity 0
|
|
|
|
// Arity 0
|
|
|
@ -1738,6 +1825,7 @@ fn load_misc_api(engine: &mut Engine) {
|
|
|
|
template_function_arity_0("hx.cx->pos");
|
|
|
|
template_function_arity_0("hx.cx->pos");
|
|
|
|
|
|
|
|
|
|
|
|
let mut template_function_arity_1 = |name: &str| {
|
|
|
|
let mut template_function_arity_1 = |name: &str| {
|
|
|
|
|
|
|
|
if generate_sources {
|
|
|
|
builtin_misc_module.push_str(&format!(
|
|
|
|
builtin_misc_module.push_str(&format!(
|
|
|
|
r#"
|
|
|
|
r#"
|
|
|
|
(provide {})
|
|
|
|
(provide {})
|
|
|
@ -1746,6 +1834,7 @@ fn load_misc_api(engine: &mut Engine) {
|
|
|
|
"#,
|
|
|
|
"#,
|
|
|
|
name, name, name
|
|
|
|
name, name, name
|
|
|
|
));
|
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Arity 1
|
|
|
|
// Arity 1
|
|
|
@ -1758,6 +1847,7 @@ fn load_misc_api(engine: &mut Engine) {
|
|
|
|
template_function_arity_1("enqueue-thread-local-callback");
|
|
|
|
template_function_arity_1("enqueue-thread-local-callback");
|
|
|
|
|
|
|
|
|
|
|
|
let mut template_function_arity_2 = |name: &str| {
|
|
|
|
let mut template_function_arity_2 = |name: &str| {
|
|
|
|
|
|
|
|
if generate_sources {
|
|
|
|
builtin_misc_module.push_str(&format!(
|
|
|
|
builtin_misc_module.push_str(&format!(
|
|
|
|
r#"
|
|
|
|
r#"
|
|
|
|
(provide {})
|
|
|
|
(provide {})
|
|
|
@ -1766,6 +1856,7 @@ fn load_misc_api(engine: &mut Engine) {
|
|
|
|
"#,
|
|
|
|
"#,
|
|
|
|
name, name, name
|
|
|
|
name, name, name
|
|
|
|
));
|
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Arity 2
|
|
|
|
// Arity 2
|
|
|
@ -1780,6 +1871,7 @@ fn load_misc_api(engine: &mut Engine) {
|
|
|
|
template_function_arity_2("enqueue-thread-local-callback-with-delay");
|
|
|
|
template_function_arity_2("enqueue-thread-local-callback-with-delay");
|
|
|
|
template_function_arity_2("helix-await-callback");
|
|
|
|
template_function_arity_2("helix-await-callback");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if generate_sources {
|
|
|
|
let mut target_directory = helix_runtime_search_path();
|
|
|
|
let mut target_directory = helix_runtime_search_path();
|
|
|
|
|
|
|
|
|
|
|
|
if !target_directory.exists() {
|
|
|
|
if !target_directory.exists() {
|
|
|
@ -1789,6 +1881,7 @@ fn load_misc_api(engine: &mut Engine) {
|
|
|
|
target_directory.push("misc.scm");
|
|
|
|
target_directory.push("misc.scm");
|
|
|
|
|
|
|
|
|
|
|
|
std::fs::write(target_directory, builtin_misc_module).unwrap();
|
|
|
|
std::fs::write(target_directory, builtin_misc_module).unwrap();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
engine.register_module(module);
|
|
|
|
engine.register_module(module);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1797,6 +1890,19 @@ fn helix_runtime_search_path() -> PathBuf {
|
|
|
|
helix_loader::config_dir().join("helix")
|
|
|
|
helix_loader::config_dir().join("helix")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn configure_builtin_sources(engine: &mut Engine, generate_sources: bool) {
|
|
|
|
|
|
|
|
load_editor_api(engine, generate_sources);
|
|
|
|
|
|
|
|
load_configuration_api(engine, generate_sources);
|
|
|
|
|
|
|
|
load_typed_commands(engine, generate_sources);
|
|
|
|
|
|
|
|
load_static_commands(engine, generate_sources);
|
|
|
|
|
|
|
|
if !generate_sources {
|
|
|
|
|
|
|
|
// Note: This is going to be completely revamped soon.
|
|
|
|
|
|
|
|
load_keymap_api(engine, KeyMapApi::new());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
load_rope_api(engine);
|
|
|
|
|
|
|
|
load_misc_api(engine, generate_sources);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn configure_engine_impl(mut engine: Engine) -> Engine {
|
|
|
|
fn configure_engine_impl(mut engine: Engine) -> Engine {
|
|
|
|
log::info!("Loading engine!");
|
|
|
|
log::info!("Loading engine!");
|
|
|
|
|
|
|
|
|
|
|
@ -1805,13 +1911,8 @@ fn configure_engine_impl(mut engine: Engine) -> Engine {
|
|
|
|
engine.register_value("*helix.cx*", SteelVal::Void);
|
|
|
|
engine.register_value("*helix.cx*", SteelVal::Void);
|
|
|
|
engine.register_value("*helix.config*", SteelVal::Void);
|
|
|
|
engine.register_value("*helix.config*", SteelVal::Void);
|
|
|
|
|
|
|
|
|
|
|
|
load_editor_api(&mut engine);
|
|
|
|
// Don't generate source directories here
|
|
|
|
load_configuration_api(&mut engine);
|
|
|
|
configure_builtin_sources(&mut engine, false);
|
|
|
|
load_typed_commands(&mut engine);
|
|
|
|
|
|
|
|
load_static_commands(&mut engine);
|
|
|
|
|
|
|
|
load_keymap_api(&mut engine, KeyMapApi::new());
|
|
|
|
|
|
|
|
load_rope_api(&mut engine);
|
|
|
|
|
|
|
|
load_misc_api(&mut engine);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Hooks
|
|
|
|
// Hooks
|
|
|
|
engine.register_fn("register-hook!", register_hook);
|
|
|
|
engine.register_fn("register-hook!", register_hook);
|
|
|
@ -1922,9 +2023,7 @@ fn configure_engine_impl(mut engine: Engine) -> Engine {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
engine.register_fn(
|
|
|
|
engine.register_fn("picker", |values: Vec<String>| -> WrappedDynComponent {
|
|
|
|
"picker",
|
|
|
|
|
|
|
|
|values: steel::List<String>| -> WrappedDynComponent {
|
|
|
|
|
|
|
|
let picker = ui::Picker::new(
|
|
|
|
let picker = ui::Picker::new(
|
|
|
|
Vec::new(),
|
|
|
|
Vec::new(),
|
|
|
|
PathBuf::from(""),
|
|
|
|
PathBuf::from(""),
|
|
|
@ -1952,8 +2051,7 @@ fn configure_engine_impl(mut engine: Engine) -> Engine {
|
|
|
|
WrappedDynComponent {
|
|
|
|
WrappedDynComponent {
|
|
|
|
inner: Some(Box::new(ui::overlay::overlaid(picker))),
|
|
|
|
inner: Some(Box::new(ui::overlay::overlaid(picker))),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
});
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
engine.register_fn("Component::Text", |contents: String| WrappedDynComponent {
|
|
|
|
engine.register_fn("Component::Text", |contents: String| WrappedDynComponent {
|
|
|
|
inner: Some(Box::new(crate::ui::Text::new(contents))),
|
|
|
|
inner: Some(Box::new(crate::ui::Text::new(contents))),
|
|
|
@ -2017,7 +2115,7 @@ fn configure_engine_impl(mut engine: Engine) -> Engine {
|
|
|
|
engine
|
|
|
|
engine
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn configure_engine() -> std::rc::Rc<std::cell::RefCell<steel::steel_vm::engine::Engine>> {
|
|
|
|
pub fn configure_engine() -> std::rc::Rc<std::cell::RefCell<steel::steel_vm::engine::Engine>> {
|
|
|
|
let engine = configure_engine_impl(steel::steel_vm::engine::Engine::new());
|
|
|
|
let engine = configure_engine_impl(steel::steel_vm::engine::Engine::new());
|
|
|
|
|
|
|
|
|
|
|
|
std::rc::Rc::new(std::cell::RefCell::new(engine))
|
|
|
|
std::rc::Rc::new(std::cell::RefCell::new(engine))
|
|
|
@ -2366,53 +2464,6 @@ fn create_directory(path: String) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Change config at runtime. Access nested values by dot syntax, for
|
|
|
|
|
|
|
|
/// example to disable smart case search, use `:set search.smart-case false`.
|
|
|
|
|
|
|
|
fn set_options(
|
|
|
|
|
|
|
|
cx: &mut compositor::Context,
|
|
|
|
|
|
|
|
args: &[Cow<str>],
|
|
|
|
|
|
|
|
event: PromptEvent,
|
|
|
|
|
|
|
|
) -> anyhow::Result<()> {
|
|
|
|
|
|
|
|
if event != PromptEvent::Validate {
|
|
|
|
|
|
|
|
return Ok(());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if args.len() % 2 != 0 {
|
|
|
|
|
|
|
|
anyhow::bail!("Bad arguments. Usage: `:set key field`");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut config = serde_json::json!(&cx.editor.config().deref());
|
|
|
|
|
|
|
|
// let key_error = || anyhow::anyhow!("Unknown key `{}`", key);
|
|
|
|
|
|
|
|
// let field_error = |_| anyhow::anyhow!("Could not parse field `{}`", arg);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for args in args.chunks_exact(2) {
|
|
|
|
|
|
|
|
let (key, arg) = (&args[0].to_lowercase(), &args[1]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let key_error = || anyhow::anyhow!("Unknown key `{}`", key);
|
|
|
|
|
|
|
|
let field_error = |_| anyhow::anyhow!("Could not parse field `{}`", arg);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// let mut config = serde_json::json!(&cx.editor.config().deref());
|
|
|
|
|
|
|
|
let pointer = format!("/{}", key.replace('.', "/"));
|
|
|
|
|
|
|
|
let value = config.pointer_mut(&pointer).ok_or_else(key_error)?;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*value = if value.is_string() {
|
|
|
|
|
|
|
|
// JSON strings require quotes, so we can't .parse() directly
|
|
|
|
|
|
|
|
Value::String(arg.to_string())
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
arg.parse().map_err(field_error)?
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let config =
|
|
|
|
|
|
|
|
serde_json::from_value(config).map_err(|_| anyhow::anyhow!("Could not parse config"))?;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cx.editor
|
|
|
|
|
|
|
|
.config_events
|
|
|
|
|
|
|
|
.0
|
|
|
|
|
|
|
|
.send(ConfigEvent::Update(config))?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn cx_pos_within_text(cx: &mut Context) -> usize {
|
|
|
|
pub fn cx_pos_within_text(cx: &mut Context) -> usize {
|
|
|
|
let (view, doc) = current_ref!(cx.editor);
|
|
|
|
let (view, doc) = current_ref!(cx.editor);
|
|
|
|
|
|
|
|
|
|
|
|