a little more behind the scenes stuff

pull/8675/merge^2
mattwparas 2 years ago
parent 798c6a5180
commit c0ea1ebbf4

120
Cargo.lock generated

@ -93,6 +93,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]] [[package]]
name = "beef" name = "beef"
version = "0.5.2" version = "0.5.2"
@ -2022,6 +2028,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]] [[package]]
name = "pretty" name = "pretty"
version = "0.11.3" version = "0.11.3"
@ -2112,6 +2124,18 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [ dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core", "rand_core",
] ]
@ -2191,6 +2215,21 @@ version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
[[package]]
name = "ring"
version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
dependencies = [
"cc",
"libc",
"once_cell",
"spin",
"untrusted",
"web-sys",
"winapi",
]
[[package]] [[package]]
name = "ropey" name = "ropey"
version = "1.6.0" version = "1.6.0"
@ -2215,6 +2254,18 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "rustls"
version = "0.20.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f"
dependencies = [
"log",
"ring",
"sct",
"webpki",
]
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.13" version = "1.0.13"
@ -2242,6 +2293,16 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
[[package]]
name = "sct"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
dependencies = [
"ring",
"untrusted",
]
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.160" version = "1.0.160"
@ -2402,6 +2463,12 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]] [[package]]
name = "static_assertions" name = "static_assertions"
version = "1.1.0" version = "1.1.0"
@ -2431,6 +2498,7 @@ dependencies = [
"once_cell", "once_cell",
"pretty", "pretty",
"quickscope", "quickscope",
"rand",
"serde", "serde",
"serde_derive", "serde_derive",
"serde_json", "serde_json",
@ -2440,6 +2508,7 @@ dependencies = [
"steel-parser", "steel-parser",
"termimad", "termimad",
"thiserror", "thiserror",
"ureq",
"weak-table", "weak-table",
] ]
@ -2824,6 +2893,28 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "ureq"
version = "2.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "338b31dd1314f68f3aabf3ed57ab922df95ffcd902476ca7ba3c4ce7b908c46d"
dependencies = [
"base64",
"flate2",
"log",
"once_cell",
"rustls",
"url",
"webpki",
"webpki-roots",
]
[[package]] [[package]]
name = "url" name = "url"
version = "2.3.1" version = "2.3.1"
@ -2924,6 +3015,35 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "323f4da9523e9a669e1eaf9c6e763892769b1d38c623913647bfdc1532fe4549" checksum = "323f4da9523e9a669e1eaf9c6e763892769b1d38c623913647bfdc1532fe4549"
[[package]]
name = "web-sys"
version = "0.3.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "webpki"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "webpki-roots"
version = "0.22.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
dependencies = [
"webpki",
]
[[package]] [[package]]
name = "which" name = "which"
version = "4.4.0" version = "4.4.0"

@ -132,6 +132,10 @@ pub fn helix_module_file() -> PathBuf {
config_dir().join("helix.scm") config_dir().join("helix.scm")
} }
pub fn steel_init_file() -> PathBuf {
config_dir().join("init.scm")
}
pub fn workspace_config_file() -> PathBuf { pub fn workspace_config_file() -> PathBuf {
find_workspace().0.join(".helix").join("config.toml") find_workspace().0.join(".helix").join("config.toml")
} }

@ -67,7 +67,7 @@ grep-regex = "0.1.11"
grep-searcher = "0.1.11" grep-searcher = "0.1.11"
# plugin support # plugin support
steel-core = { path = "../../../steel/crates/steel-core", version = "0.2.0", features = ["modules", "anyhow"] } steel-core = { path = "../../../steel/crates/steel-core", version = "0.2.0", features = ["modules", "anyhow", "blocking_requests"] }
[target.'cfg(not(windows))'.dependencies] # https://github.com/vorner/signal-hook/issues/100 [target.'cfg(not(windows))'.dependencies] # https://github.com/vorner/signal-hook/issues/100
signal-hook-tokio = { version = "0.3", features = ["futures-v0_3"] } signal-hook-tokio = { version = "0.3", features = ["futures-v0_3"] }

@ -233,7 +233,7 @@ impl Application {
let signals = Signals::new([signal::SIGTSTP, signal::SIGCONT, signal::SIGUSR1]) let signals = Signals::new([signal::SIGTSTP, signal::SIGCONT, signal::SIGUSR1])
.context("build signal handler")?; .context("build signal handler")?;
let app = Self { let mut app = Self {
compositor, compositor,
terminal, terminal,
editor, editor,
@ -249,10 +249,18 @@ impl Application {
last_render: Instant::now(), last_render: Instant::now(),
}; };
// // Initialize the engine before we boot up! {
// crate::commands::ENGINE.with(|x| { let mut cx = crate::commands::Context {
// let _ = x.borrow().globals(); register: None,
// }); count: std::num::NonZeroUsize::new(1),
editor: &mut app.editor,
callback: None,
on_next_key_callback: None,
jobs: &mut app.jobs,
};
crate::commands::run_initialization_script(&mut cx);
}
Ok(app) Ok(app)
} }

@ -7,7 +7,7 @@ pub use dap::*;
use helix_vcs::Hunk; use helix_vcs::Hunk;
pub use lsp::*; pub use lsp::*;
pub use engine::initialize_engine; pub use engine::{initialize_engine, run_initialization_script};
use steel::rvals::IntoSteelVal; use steel::rvals::IntoSteelVal;
use tokio::sync::oneshot; use tokio::sync::oneshot;
use tui::widgets::Row; use tui::widgets::Row;

@ -40,12 +40,57 @@ pub fn initialize_engine() {
ENGINE.with(|x| x.borrow().globals().first().copied()); ENGINE.with(|x| x.borrow().globals().first().copied());
} }
/// Run the initialization script located at `$helix_config/init.scm`
/// This runs the script in the global environment, and does _not_ load it as a module directly
pub fn run_initialization_script(cx: &mut Context) {
log::info!("Loading init.scm...");
let helix_module_path = helix_loader::steel_init_file();
if let Ok(contents) = std::fs::read_to_string(&helix_module_path) {
ENGINE.with(|x| {
x.borrow_mut()
.run_with_reference::<Context, Context>(cx, "*helix.cx*", &contents)
.unwrap()
});
log::info!("Finished loading init.scm!")
} else {
log::info!("No init.scm found, skipping loading.")
}
// Start the worker thread - i.e. message passing to the workers
configure_background_thread()
}
pub static KEYBINDING_QUEUE: Lazy<SharedKeyBindingsEventQueue> = pub static KEYBINDING_QUEUE: Lazy<SharedKeyBindingsEventQueue> =
Lazy::new(|| SharedKeyBindingsEventQueue::new()); Lazy::new(|| SharedKeyBindingsEventQueue::new());
pub static EXPORTED_IDENTIFIERS: Lazy<ExportedIdentifiers> = pub static EXPORTED_IDENTIFIERS: Lazy<ExportedIdentifiers> =
Lazy::new(|| ExportedIdentifiers::default()); Lazy::new(|| ExportedIdentifiers::default());
pub static STATUS_LINE_MESSAGE: Lazy<StatusLineMessage> = Lazy::new(|| StatusLineMessage::new());
pub struct StatusLineMessage {
message: Arc<RwLock<Option<String>>>,
}
impl StatusLineMessage {
pub fn new() -> Self {
Self {
message: std::sync::Arc::new(std::sync::RwLock::new(None)),
}
}
pub fn set(message: String) {
*STATUS_LINE_MESSAGE.message.write().unwrap() = Some(message);
}
pub fn get() -> Option<String> {
STATUS_LINE_MESSAGE.message.read().unwrap().clone()
}
}
/// In order to send events from the engine back to the configuration, we can created a shared /// In order to send events from the engine back to the configuration, we can created a shared
/// queue that the engine and the config push and pull from. Alternatively, we could use a channel /// queue that the engine and the config push and pull from. Alternatively, we could use a channel
/// directly, however this was easy enough to set up. /// directly, however this was easy enough to set up.
@ -95,6 +140,27 @@ fn get_editor<'a>(cx: &'a mut Context<'a>) -> &'a mut Editor {
cx.editor cx.editor
} }
fn get_themes(cx: &mut Context) -> Vec<String> {
ui::completers::theme(cx.editor, "")
.into_iter()
.map(|x| x.1.to_string())
.collect()
}
fn configure_background_thread() {
std::thread::spawn(move || {
let mut engine = steel::steel_vm::engine::Engine::new();
engine.register_fn("set-status-line!", StatusLineMessage::set);
let helix_module_path = helix_loader::config_dir().join("background.scm");
if let Ok(contents) = std::fs::read_to_string(&helix_module_path) {
engine.run(&contents).ok();
}
});
}
fn configure_engine() -> std::rc::Rc<std::cell::RefCell<steel::steel_vm::engine::Engine>> { fn configure_engine() -> std::rc::Rc<std::cell::RefCell<steel::steel_vm::engine::Engine>> {
let mut engine = steel::steel_vm::engine::Engine::new(); let mut engine = steel::steel_vm::engine::Engine::new();
@ -112,6 +178,9 @@ fn configure_engine() -> std::rc::Rc<std::cell::RefCell<steel::steel_vm::engine:
helix_view::Editor, helix_view::Editor,
>::register_fn(&mut engine, "cx-editor!", get_editor); >::register_fn(&mut engine, "cx-editor!", get_editor);
engine.register_fn("cx->themes", get_themes);
engine.register_fn("set-status-line!", StatusLineMessage::set);
engine.register_module(module); engine.register_module(module);
let mut module = BuiltInModule::new("helix/core/typable".to_string()); let mut module = BuiltInModule::new("helix/core/typable".to_string());
@ -154,6 +223,7 @@ fn configure_engine() -> std::rc::Rc<std::cell::RefCell<steel::steel_vm::engine:
module.register_fn("current-highlighted-text!", get_highlighted_text); module.register_fn("current-highlighted-text!", get_highlighted_text);
module.register_fn("run-in-engine!", run_in_engine); module.register_fn("run-in-engine!", run_in_engine);
module.register_fn("get-helix-scm-path", get_helix_scm_path); module.register_fn("get-helix-scm-path", get_helix_scm_path);
module.register_fn("get-init-scm-path", get_init_scm_path);
engine.register_module(module); engine.register_module(module);
@ -338,3 +408,10 @@ fn get_helix_scm_path() -> String {
.unwrap() .unwrap()
.to_string() .to_string()
} }
fn get_init_scm_path() -> String {
helix_loader::steel_init_file()
.to_str()
.unwrap()
.to_string()
}

@ -2074,6 +2074,43 @@ fn pipe_impl(
Ok(()) Ok(())
} }
fn run_shell_command_text(
cx: &mut compositor::Context,
args: &[Cow<str>],
event: PromptEvent,
) -> anyhow::Result<()> {
if event != PromptEvent::Validate {
return Ok(());
}
let shell = cx.editor.config().shell.clone();
let args = args.join(" ");
let callback = async move {
let (output, success) = shell_impl_async(&shell, &args, None).await?;
let call: job::Callback = Callback::EditorCompositor(Box::new(
move |editor: &mut Editor, compositor: &mut Compositor| {
if !output.is_empty() {
let contents = ui::Text::new(format!("{}", output));
let popup = Popup::new("shell", contents).position(Some(
helix_core::Position::new(editor.cursor().0.unwrap_or_default().row, 2),
));
compositor.replace_or_push("shell", popup);
}
if success {
editor.set_status("Command succeeded");
} else {
editor.set_error("Command failed");
}
},
));
Ok(call)
};
cx.jobs.callback(callback);
Ok(())
}
fn run_shell_command( fn run_shell_command(
cx: &mut compositor::Context, cx: &mut compositor::Context,
args: &[Cow<str>], args: &[Cow<str>],
@ -2746,6 +2783,13 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
fun: run_shell_command, fun: run_shell_command,
signature: CommandSignature::all(completers::filename) signature: CommandSignature::all(completers::filename)
}, },
TypableCommand {
name: "run-shell-command-text",
aliases: &["sh"],
doc: "Run a shell command",
fun: run_shell_command_text,
signature: CommandSignature::all(completers::filename)
},
TypableCommand { TypableCommand {
name: "reset-diff-change", name: "reset-diff-change",
aliases: &["diffget", "diffg"], aliases: &["diffget", "diffg"],
@ -2875,6 +2919,9 @@ pub(super) fn command_mode(cx: &mut Context) {
// We're finalizing the event - we actually want to call the function // We're finalizing the event - we actually want to call the function
if event == PromptEvent::Validate { if event == PromptEvent::Validate {
// TODO: @Matt - extract this whole API cal here to just be inside the engine module
// For what its worth, also explore a more elegant API for calling apply with some arguments,
// this does work, but its a little opaque.
if let Err(e) = ENGINE.with(|x| { if let Err(e) = ENGINE.with(|x| {
let args = steel::List::from( let args = steel::List::from(
args[1..] args[1..]

@ -127,7 +127,7 @@ FLAGS:
helix_loader::initialize_config_file(args.config_file.clone()); helix_loader::initialize_config_file(args.config_file.clone());
// Initialize the engine before we boot up! // Initialize the engine before we boot up!
let _ = helix_term::commands::initialize_engine(); helix_term::commands::initialize_engine();
let config = match Config::load_default() { let config = match Config::load_default() {
Ok(config) => config, Ok(config) => config,

@ -8,7 +8,10 @@ use helix_view::{
Document, Editor, View, Document, Editor, View,
}; };
use crate::ui::ProgressSpinners; use crate::{
commands::engine::{StatusLineMessage, STATUS_LINE_MESSAGE},
ui::ProgressSpinners,
};
use helix_view::editor::StatusLineElement as StatusLineElementID; use helix_view::editor::StatusLineElement as StatusLineElementID;
use tui::buffer::Buffer as Surface; use tui::buffer::Buffer as Surface;
@ -160,6 +163,7 @@ where
helix_view::editor::StatusLineElement::Separator => render_separator, helix_view::editor::StatusLineElement::Separator => render_separator,
helix_view::editor::StatusLineElement::Spacer => render_spacer, helix_view::editor::StatusLineElement::Spacer => render_spacer,
helix_view::editor::StatusLineElement::VersionControl => render_version_control, helix_view::editor::StatusLineElement::VersionControl => render_version_control,
helix_view::editor::StatusLineElement::Custom => render_custom_text,
} }
} }
@ -490,3 +494,12 @@ where
write(context, head, None); write(context, head, None);
} }
fn render_custom_text<F>(context: &mut RenderContext, write: F)
where
F: Fn(&mut RenderContext, String, Option<Style>) + Copy,
{
if let Some(message) = StatusLineMessage::get() {
write(context, message, None);
}
}

@ -46,7 +46,7 @@ which = "4.4"
parking_lot = "0.12.1" parking_lot = "0.12.1"
# plugin support # plugin support
steel-core = { path = "../../../steel/crates/steel-core", version = "0.2.0", features = ["modules", "anyhow"] } steel-core = { path = "../../../steel/crates/steel-core", version = "0.2.0", features = ["modules", "anyhow", "blocking_requests"] }
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]

@ -484,6 +484,9 @@ pub enum StatusLineElement {
/// Current version control information /// Current version control information
VersionControl, VersionControl,
/// Custom
Custom,
} }
// Cursor shape is read and used on every rendered frame and so needs // Cursor shape is read and used on every rendered frame and so needs

Loading…
Cancel
Save