pull/8675/merge^2
mattwparas 1 year ago
parent ca346b1416
commit 1fb2df48e1

329
Cargo.lock generated

@ -157,6 +157,15 @@ dependencies = [
"syn 1.0.109", "syn 1.0.109",
] ]
[[package]]
name = "async-ffi"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ed5a937a789391ebc1c77d3a15b060e0d100e6d7c483a2af3f250d6b8dc2a23"
dependencies = [
"abi_stable",
]
[[package]] [[package]]
name = "atty" name = "atty"
version = "0.2.14" version = "0.2.14"
@ -189,12 +198,6 @@ dependencies = [
"rustc-demangle", "rustc-demangle",
] ]
[[package]]
name = "base64"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
[[package]] [[package]]
name = "beef" name = "beef"
version = "0.5.2" version = "0.5.2"
@ -313,10 +316,7 @@ checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5"
dependencies = [ dependencies = [
"android-tzdata", "android-tzdata",
"iana-time-zone", "iana-time-zone",
"js-sys",
"num-traits", "num-traits",
"time 0.1.45",
"wasm-bindgen",
"winapi", "winapi",
] ]
@ -382,15 +382,6 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "coolor"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af4d7a805ca0d92f8c61a31c809d4323fdaa939b0b440e544d21db7797c5aaad"
dependencies = [
"crossterm 0.23.2",
]
[[package]] [[package]]
name = "core-foundation-sys" name = "core-foundation-sys"
version = "0.8.4" version = "0.8.4"
@ -421,20 +412,6 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "crossbeam"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c"
dependencies = [
"cfg-if",
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-epoch",
"crossbeam-queue",
"crossbeam-utils",
]
[[package]] [[package]]
name = "crossbeam-channel" name = "crossbeam-channel"
version = "0.5.8" version = "0.5.8"
@ -445,40 +422,6 @@ dependencies = [
"crossbeam-utils", "crossbeam-utils",
] ]
[[package]]
name = "crossbeam-deque"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-queue"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.16" version = "0.8.16"
@ -488,22 +431,6 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "crossterm"
version = "0.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2102ea4f781910f8a5b98dd061f4c2023f479ce7bb1236330099ceb5a93cf17"
dependencies = [
"bitflags 1.3.2",
"crossterm_winapi",
"libc",
"mio",
"parking_lot",
"signal-hook",
"signal-hook-mio",
"winapi",
]
[[package]] [[package]]
name = "crossterm" name = "crossterm"
version = "0.26.1" version = "0.26.1"
@ -702,31 +629,6 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "futures"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]] [[package]]
name = "futures-core" name = "futures-core"
version = "0.3.28" version = "0.3.28"
@ -744,12 +646,6 @@ dependencies = [
"futures-util", "futures-util",
] ]
[[package]]
name = "futures-io"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
[[package]] [[package]]
name = "futures-macro" name = "futures-macro"
version = "0.3.28" version = "0.3.28"
@ -761,12 +657,6 @@ dependencies = [
"syn 2.0.23", "syn 2.0.23",
] ]
[[package]]
name = "futures-sink"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
[[package]] [[package]]
name = "futures-task" name = "futures-task"
version = "0.3.28" version = "0.3.28"
@ -779,13 +669,9 @@ version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
dependencies = [ dependencies = [
"futures-channel",
"futures-core", "futures-core",
"futures-io",
"futures-macro", "futures-macro",
"futures-sink",
"futures-task", "futures-task",
"memchr",
"pin-project-lite", "pin-project-lite",
"pin-utils", "pin-utils",
"slab", "slab",
@ -826,7 +712,7 @@ checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"wasi 0.11.0+wasi-snapshot-preview1", "wasi",
] ]
[[package]] [[package]]
@ -1015,7 +901,7 @@ dependencies = [
"bstr", "bstr",
"itoa", "itoa",
"thiserror", "thiserror",
"time 0.3.22", "time",
] ]
[[package]] [[package]]
@ -1625,7 +1511,7 @@ dependencies = [
"arc-swap", "arc-swap",
"chrono", "chrono",
"content_inspector", "content_inspector",
"crossterm 0.26.1", "crossterm",
"dlopen", "dlopen",
"dlopen_derive", "dlopen_derive",
"fern", "fern",
@ -1665,7 +1551,7 @@ version = "0.6.0"
dependencies = [ dependencies = [
"bitflags 2.3.3", "bitflags 2.3.3",
"cassowary", "cassowary",
"crossterm 0.26.1", "crossterm",
"helix-core", "helix-core",
"helix-view", "helix-view",
"log", "log",
@ -1700,7 +1586,7 @@ dependencies = [
"bitflags 2.3.3", "bitflags 2.3.3",
"chardetng", "chardetng",
"clipboard-win", "clipboard-win",
"crossterm 0.26.1", "crossterm",
"futures-util", "futures-util",
"helix-core", "helix-core",
"helix-dap", "helix-dap",
@ -1889,15 +1775,6 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.6" version = "1.0.6"
@ -2047,24 +1924,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "memoffset"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
dependencies = [
"autocfg",
]
[[package]]
name = "minimad"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed1b13e2000bd8e238d97a97de6fc30224f89a08b0aa5aaa09ed1bd68ba2fa1"
dependencies = [
"once_cell",
]
[[package]] [[package]]
name = "minimal-lexical" name = "minimal-lexical"
version = "0.2.1" version = "0.2.1"
@ -2088,7 +1947,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
dependencies = [ dependencies = [
"libc", "libc",
"log", "log",
"wasi 0.11.0+wasi-snapshot-preview1", "wasi",
"windows-sys", "windows-sys",
] ]
@ -2268,12 +2127,11 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]] [[package]]
name = "pretty" name = "pretty"
version = "0.11.3" version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83f3aa1e3ca87d3b124db7461265ac176b40c277f37e503eaa29c9c75c037846" checksum = "563c9d701c3a31dfffaaf9ce23507ba09cbe0b9125ba176d15e629b0235e9acc"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"log",
"typed-arena", "typed-arena",
"unicode-segmentation", "unicode-segmentation",
] ]
@ -2350,6 +2208,12 @@ dependencies = [
"proc-macro2 1.0.63", "proc-macro2 1.0.63",
] ]
[[package]]
name = "radix_fmt"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce082a9940a7ace2ad4a8b7d0b1eac6aa378895f18be598230c5f2284ac05426"
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.8.5" version = "0.8.5"
@ -2445,21 +2309,6 @@ dependencies = [
"tstr", "tstr",
] ]
[[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"
@ -2499,28 +2348,6 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "rustls"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e32ca28af694bc1bbf399c33a516dbdf1c90090b8ab23c2bc24f834aa2247f5f"
dependencies = [
"log",
"ring",
"rustls-webpki",
"sct",
]
[[package]]
name = "rustls-webpki"
version = "0.100.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b"
dependencies = [
"ring",
"untrusted",
]
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.13" version = "1.0.13"
@ -2542,16 +2369,6 @@ 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 = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[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 = "semver" name = "semver"
version = "1.0.17" version = "1.0.17"
@ -2718,12 +2535,6 @@ 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"
@ -2732,48 +2543,43 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]] [[package]]
name = "steel-core" name = "steel-core"
version = "0.4.0" version = "0.5.0"
dependencies = [ dependencies = [
"abi_stable", "abi_stable",
"anyhow", "anyhow",
"async-ffi",
"bincode", "bincode",
"chrono", "chrono",
"codespan-reporting", "codespan-reporting",
"colored", "colored",
"dlopen", "futures-task",
"dlopen_derive", "futures-util",
"futures",
"fxhash", "fxhash",
"im-lists", "im-lists",
"im-rc", "im-rc",
"itertools",
"lasso", "lasso",
"lazy_static",
"log", "log",
"logos", "logos",
"num", "num",
"once_cell", "once_cell",
"pretty", "pretty",
"quickscope", "quickscope",
"radix_fmt",
"rand", "rand",
"serde", "serde",
"serde_derive", "serde_derive",
"serde_json", "serde_json",
"slotmap", "slotmap",
"smallvec",
"steel-derive", "steel-derive",
"steel-gen", "steel-gen",
"steel-parser", "steel-parser",
"termimad",
"thiserror",
"ureq",
"weak-table", "weak-table",
"which", "which",
] ]
[[package]] [[package]]
name = "steel-derive" name = "steel-derive"
version = "0.2.0" version = "0.4.0"
dependencies = [ dependencies = [
"proc-macro2 1.0.63", "proc-macro2 1.0.63",
"quote 1.0.29", "quote 1.0.29",
@ -2785,14 +2591,13 @@ name = "steel-gen"
version = "0.2.0" version = "0.2.0"
dependencies = [ dependencies = [
"codegen", "codegen",
"itertools",
"serde", "serde",
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "steel-parser" name = "steel-parser"
version = "0.2.0" version = "0.4.0"
dependencies = [ dependencies = [
"logos", "logos",
"num-bigint", "num-bigint",
@ -2868,20 +2673,6 @@ dependencies = [
"winapi-util", "winapi-util",
] ]
[[package]]
name = "termimad"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8743d628f9b0eb33087c1e1c4915d91efca23ae69f7c81981489128a0e17d300"
dependencies = [
"coolor",
"crossbeam",
"crossterm 0.23.2",
"minimad",
"thiserror",
"unicode-width",
]
[[package]] [[package]]
name = "termini" name = "termini"
version = "1.0.0" version = "1.0.0"
@ -2941,17 +2732,6 @@ dependencies = [
"num_cpus", "num_cpus",
] ]
[[package]]
name = "time"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
dependencies = [
"libc",
"wasi 0.10.0+wasi-snapshot-preview1",
"winapi",
]
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.22" version = "0.3.22"
@ -3179,30 +2959,6 @@ 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.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b11c96ac7ee530603dcdf68ed1557050f374ce55a5a07193ebf8cbc9f8927e9"
dependencies = [
"base64",
"flate2",
"log",
"once_cell",
"rustls",
"rustls-webpki",
"serde",
"serde_json",
"url",
"webpki-roots",
]
[[package]] [[package]]
name = "url" name = "url"
version = "2.4.0" version = "2.4.0"
@ -3231,12 +2987,6 @@ dependencies = [
"winapi-util", "winapi-util",
] ]
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.11.0+wasi-snapshot-preview1" version = "0.11.0+wasi-snapshot-preview1"
@ -3303,25 +3053,6 @@ 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.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "webpki-roots"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338"
dependencies = [
"rustls-webpki",
]
[[package]] [[package]]
name = "which" name = "which"
version = "4.4.0" version = "4.4.0"

@ -17,7 +17,7 @@ default-members = [
] ]
[workspace.dependencies] [workspace.dependencies]
steel-core = { path = "../../steel/crates/steel-core", version = "0.4.0", features = ["modules", "anyhow", "blocking_requests"] } steel-core = { path = "../../steel/crates/steel-core", version = "0.5.0", features = ["modules", "anyhow", "dylibs", "colors"] }
[profile.release] [profile.release]
lto = "thin" lto = "thin"

@ -960,7 +960,6 @@ pub fn custom_indent_for_newline(
let line = text_up_to_cursor.line(cursor); let line = text_up_to_cursor.line(cursor);
// We want to ignore comments // We want to ignore comments
let l = std::borrow::Cow::from(line); let l = std::borrow::Cow::from(line);
if l.trim_start().starts_with(";") { if l.trim_start().starts_with(";") {
if cursor == 0 { if cursor == 0 {
@ -972,8 +971,6 @@ pub fn custom_indent_for_newline(
continue; continue;
} }
// log::info!("Line: {}", line);
for (index, char) in line.chars_at(line.len_chars()).reversed().enumerate() { for (index, char) in line.chars_at(line.len_chars()).reversed().enumerate() {
match char { match char {
')' | ']' | '}' => { ')' | ']' | '}' => {

@ -266,7 +266,7 @@ impl Application {
jobs: &mut app.jobs, jobs: &mut app.jobs,
}; };
crate::commands::run_initialization_script(&mut cx); crate::commands::ScriptingEngine::run_initialization_script(&mut cx);
} }
Ok(app) Ok(app)

@ -8,8 +8,7 @@ pub use dap::*;
use helix_vcs::Hunk; use helix_vcs::Hunk;
pub use lsp::*; pub use lsp::*;
pub use engine::{initialize_engine, run_initialization_script}; pub use engine::ScriptingEngine;
use steel::rvals::IntoSteelVal;
use tokio::sync::oneshot; use tokio::sync::oneshot;
use tui::widgets::Row; use tui::widgets::Row;
pub use typed::*; pub use typed::*;
@ -55,7 +54,6 @@ use movement::Movement;
use crate::{ use crate::{
args, args,
commands::engine::{CallbackQueue, ScriptingEngine},
compositor::{self, Component, Compositor}, compositor::{self, Component, Compositor},
filter_picker_entry, filter_picker_entry,
job::Callback, job::Callback,
@ -214,7 +212,7 @@ impl MappableCommand {
cx.editor.set_error(format!("{}", e)); cx.editor.set_error(format!("{}", e));
} }
} else { } else {
ScriptingEngine::call_function_if_global_exists(cx, name, args) ScriptingEngine::call_function_if_global_exists(cx, name, args);
} }
} }
Self::Static { fun, .. } => (fun)(cx), Self::Static { fun, .. } => (fun)(cx),
@ -2558,6 +2556,7 @@ fn buffer_picker(cx: &mut Context) {
struct BufferMeta { struct BufferMeta {
id: DocumentId, id: DocumentId,
path: Option<PathBuf>, path: Option<PathBuf>,
name: Option<String>,
is_modified: bool, is_modified: bool,
is_current: bool, is_current: bool,
focused_at: std::time::Instant, focused_at: std::time::Instant,
@ -2571,7 +2570,11 @@ fn buffer_picker(cx: &mut Context) {
.path .path
.as_deref() .as_deref()
.map(helix_core::path::get_relative_path); .map(helix_core::path::get_relative_path);
let path = match path.as_deref().and_then(Path::to_str) { let path = match path
.as_deref()
.and_then(Path::to_str)
.or_else(|| self.name.as_ref().map(|x| x.as_str()))
{
Some(path) => path, Some(path) => path,
None => SCRATCH_BUFFER_NAME, None => SCRATCH_BUFFER_NAME,
}; };
@ -2591,6 +2594,7 @@ fn buffer_picker(cx: &mut Context) {
let new_meta = |doc: &Document| BufferMeta { let new_meta = |doc: &Document| BufferMeta {
id: doc.id(), id: doc.id(),
path: doc.path().cloned(), path: doc.path().cloned(),
name: doc.name.clone(),
is_modified: doc.is_modified(), is_modified: doc.is_modified(),
is_current: doc.id() == current, is_current: doc.id() == current,
focused_at: doc.focused_at, focused_at: doc.focused_at,

@ -77,6 +77,125 @@ pub trait PluginSystem {
fn get_doc_for_identifier(ident: &str) -> Option<String>; fn get_doc_for_identifier(ident: &str) -> Option<String>;
} }
// APIs / Modules that need to be accepted by the plugin system
// Without these, the core functionality cannot operate
pub struct DocumentApi;
pub struct EditorApi;
pub struct ComponentApi;
pub struct TypedCommandsApi;
pub struct StaticCommandsApi;
pub struct KeyMapApi {
get_keymap: fn() -> EmbeddedKeyMap,
default_keymap: fn() -> EmbeddedKeyMap,
empty_keymap: fn() -> EmbeddedKeyMap,
string_to_embedded_keymap: fn(String) -> EmbeddedKeyMap,
merge_keybindings: fn(&mut EmbeddedKeyMap, EmbeddedKeyMap),
}
impl KeyMapApi {
fn new() -> Self {
KeyMapApi {
get_keymap,
default_keymap,
empty_keymap,
string_to_embedded_keymap,
merge_keybindings,
}
}
}
thread_local! {
pub static BUFFER_OR_EXTENSION_KEYBINDING_MAP: SteelVal =
SteelVal::boxed(SteelVal::empty_hashmap());
pub static REVERSE_BUFFER_MAP: SteelVal =
SteelVal::boxed(SteelVal::empty_hashmap());
}
fn load_keymap_api(engine: &mut Engine, api: KeyMapApi) {
let mut module = BuiltInModule::new("helix/core/keymaps");
module.register_fn("helix-current-keymap", api.get_keymap);
module.register_fn("helix-empty-keymap", api.empty_keymap);
module.register_fn("helix-default-keymap", api.default_keymap);
module.register_fn("helix-merge-keybindings", api.merge_keybindings);
module.register_fn("helix-string->keymap", api.string_to_embedded_keymap);
// This should be associated with a corresponding scheme module to wrap this up
module.register_value(
"*buffer-or-extension-keybindings*",
BUFFER_OR_EXTENSION_KEYBINDING_MAP.with(|x| x.clone()),
);
module.register_value(
"*reverse-buffer-map*",
REVERSE_BUFFER_MAP.with(|x| x.clone()),
);
engine.register_module(module);
}
fn load_static_commands(engine: &mut Engine) {
let mut module = BuiltInModule::new("helix/core/static");
for command in TYPABLE_COMMAND_LIST {
let func = |cx: &mut Context| {
let mut cx = compositor::Context {
editor: cx.editor,
scroll: None,
jobs: cx.jobs,
};
(command.fun)(&mut cx, &[], PromptEvent::Validate)
};
module.register_fn(command.name, func);
}
// Register everything in the static command list as well
// These just accept the context, no arguments
for command in MappableCommand::STATIC_COMMAND_LIST {
if let MappableCommand::Static { name, fun, .. } = command {
module.register_fn(name, fun);
}
}
engine.register_module(module);
}
fn load_typed_commands(engine: &mut Engine) {
let mut module = BuiltInModule::new("helix/core/typable".to_string());
// Register everything in the typable command list. Now these are all available
for command in TYPABLE_COMMAND_LIST {
let func = |cx: &mut Context, args: &[Cow<str>], event: PromptEvent| {
let mut cx = compositor::Context {
editor: cx.editor,
scroll: None,
jobs: cx.jobs,
};
(command.fun)(&mut cx, args, event)
};
module.register_fn(command.name, func);
}
engine.register_module(module);
}
fn load_editor_api(engine: &mut Engine, api: EditorApi) {
todo!()
}
fn load_document_api(engine: &mut Engine, api: DocumentApi) {
todo!()
}
fn load_component_api(engine: &mut Engine, api: ComponentApi) {
todo!()
}
impl ScriptingEngine { impl ScriptingEngine {
pub fn initialize() { pub fn initialize() {
initialize_engine(); initialize_engine();
@ -111,11 +230,8 @@ impl ScriptingEngine {
}; };
if let Some(extension) = extension { if let Some(extension) = extension {
let special_buffer_map = "*buffer-or-extension-keybindings*"; if let SteelVal::HashMapV(map) = BUFFER_OR_EXTENSION_KEYBINDING_MAP.with(|x| x.clone())
{
let value = ENGINE.with(|x| x.borrow().extract_value(special_buffer_map).clone());
if let Ok(SteelVal::HashMapV(map)) = value {
if let Some(value) = map.get(&SteelVal::StringV(extension.into())) { if let Some(value) = map.get(&SteelVal::StringV(extension.into())) {
if let SteelVal::Custom(inner) = value { if let SteelVal::Custom(inner) = value {
if let Some(_) = steel::rvals::as_underlying_type::<EmbeddedKeyMap>( if let Some(_) = steel::rvals::as_underlying_type::<EmbeddedKeyMap>(
@ -128,16 +244,12 @@ impl ScriptingEngine {
} }
} }
// reverse-buffer-map -> label -> keybinding map // TODO: Remove these clones
let value = ENGINE.with(|x| x.borrow().extract_value("*reverse-buffer-map*").clone()); if let SteelVal::HashMapV(map) = REVERSE_BUFFER_MAP.with(|x| x.clone()) {
if let Ok(SteelVal::HashMapV(map)) = value {
if let Some(label) = map.get(&SteelVal::IntV(document_id_to_usize(doc_id) as isize)) { if let Some(label) = map.get(&SteelVal::IntV(document_id_to_usize(doc_id) as isize)) {
let special_buffer_map = "*buffer-or-extension-keybindings*"; if let SteelVal::HashMapV(map) =
BUFFER_OR_EXTENSION_KEYBINDING_MAP.with(|x| x.clone())
let value = ENGINE.with(|x| x.borrow().extract_value(special_buffer_map).clone()); {
if let Ok(SteelVal::HashMapV(map)) = value {
if let Some(value) = map.get(label) { if let Some(value) = map.get(label) {
if let SteelVal::Custom(inner) = value { if let SteelVal::Custom(inner) = value {
if let Some(_) = steel::rvals::as_underlying_type::<EmbeddedKeyMap>( if let Some(_) = steel::rvals::as_underlying_type::<EmbeddedKeyMap>(
@ -154,7 +266,11 @@ impl ScriptingEngine {
None None
} }
pub fn call_function_if_global_exists(cx: &mut Context, name: &str, args: Vec<Cow<str>>) { pub fn call_function_if_global_exists(
cx: &mut Context,
name: &str,
args: Vec<Cow<str>>,
) -> bool {
if ENGINE.with(|x| x.borrow().global_exists(name)) { if ENGINE.with(|x| x.borrow().global_exists(name)) {
let args = steel::List::from( let args = steel::List::from(
args.iter() args.iter()
@ -181,6 +297,9 @@ impl ScriptingEngine {
}) { }) {
cx.editor.set_error(format!("{}", e)); cx.editor.set_error(format!("{}", e));
} }
true
} else {
false
} }
} }
@ -230,21 +349,9 @@ impl ScriptingEngine {
guard.register_value("_helix_args", steel::rvals::SteelVal::Void); guard.register_value("_helix_args", steel::rvals::SteelVal::Void);
// if let Some(callback) = cx.callback.take() {
// panic!("Found a callback!");
// maybe_callback = Some(callback);
// }
res res
}; };
// TODO: Recursively (or otherwise) keep retrying until we're back
// into the engine context, executing a function. We might need to set up
// some sort of fuel or something
// if let Some(callback) = maybe_callback {
// (callback)(_, cx);
// }
res res
}) { }) {
compositor_present_error(cx, e); compositor_present_error(cx, e);
@ -431,7 +538,7 @@ pub fn merge_keybindings(left: &mut EmbeddedKeyMap, right: EmbeddedKeyMap) {
/// Run the initialization script located at `$helix_config/init.scm` /// 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 /// 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) { fn run_initialization_script(cx: &mut Context) {
log::info!("Loading init.scm..."); log::info!("Loading init.scm...");
let helix_module_path = helix_loader::steel_init_file(); let helix_module_path = helix_loader::steel_init_file();
@ -440,7 +547,12 @@ pub fn run_initialization_script(cx: &mut Context) {
if let Ok(contents) = std::fs::read_to_string(&helix_module_path) { if let Ok(contents) = std::fs::read_to_string(&helix_module_path) {
let res = ENGINE.with(|x| { let res = ENGINE.with(|x| {
x.borrow_mut() x.borrow_mut()
.run_with_reference::<Context, Context>(cx, "*helix.cx*", &contents) .run_with_reference_from_path::<Context, Context>(
cx,
"*helix.cx*",
&contents,
helix_module_path,
)
}); });
match res { match res {
@ -452,18 +564,11 @@ pub fn run_initialization_script(cx: &mut Context) {
} else { } else {
log::info!("No init.scm found, skipping loading.") log::info!("No init.scm found, skipping loading.")
} }
// Start the worker thread - i.e. message passing to the workers
// configure_background_thread()
} }
// pub static MINOR_MODES: Lazy<Arc<RwLock<HashMap<String,
pub static KEYBINDING_QUEUE: Lazy<SharedKeyBindingsEventQueue> = pub static KEYBINDING_QUEUE: Lazy<SharedKeyBindingsEventQueue> =
Lazy::new(|| SharedKeyBindingsEventQueue::new()); Lazy::new(|| SharedKeyBindingsEventQueue::new());
// pub static CALLBACK_QUEUE: Lazy<CallBackQueue> = Lazy::new(|| )
pub static CALLBACK_QUEUE: Lazy<CallbackQueue> = Lazy::new(|| CallbackQueue::new()); pub static CALLBACK_QUEUE: Lazy<CallbackQueue> = Lazy::new(|| CallbackQueue::new());
pub static EXPORTED_IDENTIFIERS: Lazy<ExportedIdentifiers> = pub static EXPORTED_IDENTIFIERS: Lazy<ExportedIdentifiers> =
@ -715,6 +820,9 @@ fn configure_engine() -> std::rc::Rc<std::cell::RefCell<steel::steel_vm::engine:
// ); // );
engine.register_fn("enqueue-callback!", CallbackQueue::enqueue); engine.register_fn("enqueue-callback!", CallbackQueue::enqueue);
load_keymap_api(&mut engine, KeyMapApi::new());
engine.register_fn("helix-current-keymap", get_keymap); engine.register_fn("helix-current-keymap", get_keymap);
engine.register_fn("helix-empty-keymap", empty_keymap); engine.register_fn("helix-empty-keymap", empty_keymap);
engine.register_fn("helix-default-keymap", default_keymap); engine.register_fn("helix-default-keymap", default_keymap);
@ -776,21 +884,21 @@ fn configure_engine() -> std::rc::Rc<std::cell::RefCell<steel::steel_vm::engine:
// engine.register_fn("WrappedComponent", WrappedDynComponent::new) // engine.register_fn("WrappedComponent", WrappedDynComponent::new)
engine.register_fn( // engine.register_fn(
"Popup::new", // "Popup::new",
|contents: &mut WrappedDynComponent, // |contents: &mut WrappedDynComponent,
position: helix_core::Position| // position: helix_core::Position|
-> WrappedDynComponent { // -> WrappedDynComponent {
let inner = contents.inner.take().unwrap(); // Panic, for now // let inner = contents.inner.take().unwrap(); // Panic, for now
WrappedDynComponent { // WrappedDynComponent {
inner: Some(Box::new( // inner: Some(Box::new(
Popup::<BoxDynComponent>::new("popup", BoxDynComponent::new(inner)) // Popup::<BoxDynComponent>::new("popup", BoxDynComponent::new(inner))
.position(Some(position)), // .position(Some(position)),
)), // )),
} // }
}, // },
); // );
engine.register_fn( engine.register_fn(
"Prompt::new", "Prompt::new",
@ -915,6 +1023,8 @@ 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("set-scratch-buffer-name!", set_scratch_buffer_name);
engine.register_fn("editor-focus", current_focus); engine.register_fn("editor-focus", current_focus);
engine.register_fn("editor->doc-id", get_document_id); engine.register_fn("editor->doc-id", get_document_id);
engine.register_fn("doc-id->usize", document_id_to_usize); engine.register_fn("doc-id->usize", document_id_to_usize);
@ -1015,58 +1125,6 @@ fn configure_engine() -> std::rc::Rc<std::cell::RefCell<steel::steel_vm::engine:
module.register_fn(command.name, func); module.register_fn(command.name, func);
} }
// // Load the plugins with respect to the extensions directory.
// EXTERNAL_DYLIBS
// .write()
// .unwrap()
// .load_modules_from_directory(Some(
// helix_loader::config_dir()
// .join("extensions")
// .to_str()tor // .unwrap()
// .to_string(),
// ));
// let commands = EXTERNAL_DYLIBS.read().unwrap().create_commands();
// TODO: @Matt - these commands need to get loaded into their _own_ module, and registered as such.
// for dylib in &EXTERNAL_DYLIBS.read().unwrap().modules {
// let mut module = BuiltInModule::new(dylib.name.to_string());
// println!("{}", dylib.get_name());
// // println!("{}", dylib.name);
// for command in dylib.commands.iter() {
// // TODO: The name needs to be registered for static - but we shouldn't _need_ it to be
// // registered for static. We can probably get away with accepting an owned string and pay the price,
// // if need be.
// let inner = command.fun.clone();
// let func = move |cx: &mut Context,
// args: Box<[Box<str>]>,
// event: PromptEvent|
// -> anyhow::Result<()> {
// // Ensure the lifetime of these variables
// let _config = cx.editor.config.clone();
// let _theme_loader = cx.editor.theme_loader.clone();
// let _syn_loader = cx.editor.syn_loader.clone();
// println!("{}", Arc::strong_count(&_config));
// println!("{}", Arc::strong_count(&_theme_loader));
// println!("{}", Arc::strong_count(&_syn_loader));
// // println!("{:p}", _theme_loader);
// // println!("{:p}", _syn_loader);
// (inner)(cx, &_theme_loader, &_syn_loader, args, &event)
// };
// module.register_owned_fn(command.name.to_string(), func);
// }
// engine.register_module(module);
// }
engine.register_module(module); engine.register_module(module);
let mut module = BuiltInModule::new("helix/core/static".to_string()); let mut module = BuiltInModule::new("helix/core/static".to_string());
@ -1113,6 +1171,12 @@ fn configure_engine() -> std::rc::Rc<std::cell::RefCell<steel::steel_vm::engine:
engine.register_fn("push-component!", push_component); engine.register_fn("push-component!", push_component);
engine.register_fn("enqueue-thread-local-callback", enqueue_command); engine.register_fn("enqueue-thread-local-callback", enqueue_command);
engine.register_fn(
"enqueue-thread-local-callback-with-delay",
enqueue_command_with_delay,
);
engine.register_fn("helix-await-callback", await_value);
// Create directory since we can't do that in the current state // Create directory since we can't do that in the current state
engine.register_fn("hx.create-directory", create_directory); engine.register_fn("hx.create-directory", create_directory);
@ -1343,6 +1407,18 @@ fn current_path(cx: &mut Context) -> Option<String> {
current_doc.and_then(|x| x.path().and_then(|x| x.to_str().map(|x| x.to_string()))) current_doc.and_then(|x| x.path().and_then(|x| x.to_str().map(|x| x.to_string())))
} }
fn set_scratch_buffer_name(cx: &mut Context, name: String) {
let current_focus = cx.editor.tree.focus;
let view = cx.editor.tree.get(current_focus);
let doc = &view.doc;
// Lifetime of this needs to be tied to the existing document
let current_doc = cx.editor.documents.get_mut(doc);
if let Some(current_doc) = current_doc {
current_doc.name = Some(name);
}
}
fn cx_current_focus(cx: &mut Context) -> helix_view::ViewId { fn cx_current_focus(cx: &mut Context) -> helix_view::ViewId {
cx.editor.tree.focus cx.editor.tree.focus
} }
@ -1477,6 +1553,87 @@ fn enqueue_command(cx: &mut Context, callback_fn: SteelVal) {
cx.jobs.local_callback(callback); cx.jobs.local_callback(callback);
} }
// Apply arbitrary delay for update rate...
fn enqueue_command_with_delay(cx: &mut Context, delay: SteelVal, callback_fn: SteelVal) {
let callback = async move {
let delay = delay.int_or_else(|| panic!("FIX ME")).unwrap();
tokio::time::sleep(tokio::time::Duration::from_millis(delay as u64)).await;
let call: Box<dyn FnOnce(&mut Editor, &mut Compositor, &mut job::Jobs)> = Box::new(
move |editor: &mut Editor, _compositor: &mut Compositor, jobs: &mut job::Jobs| {
let mut ctx = Context {
register: None,
count: None,
editor,
callback: None,
on_next_key_callback: None,
jobs,
};
let cloned_func = callback_fn.clone();
if let Err(e) = ENGINE.with(|x| {
x.borrow_mut()
.with_mut_reference::<Context, Context>(&mut ctx)
.consume(move |engine, args| {
engine.call_function_with_args(cloned_func.clone(), args)
})
}) {
present_error(&mut ctx, e);
}
},
);
Ok(call)
};
cx.jobs.local_callback(callback);
}
// value _must_ be a future here. Otherwise awaiting will cause problems!
fn await_value(cx: &mut Context, value: SteelVal, callback_fn: SteelVal) {
if !value.is_future() {
return;
}
let callback = async move {
let future_value = value.as_future().unwrap().await;
let call: Box<dyn FnOnce(&mut Editor, &mut Compositor, &mut job::Jobs)> = Box::new(
move |editor: &mut Editor, _compositor: &mut Compositor, jobs: &mut job::Jobs| {
let mut ctx = Context {
register: None,
count: None,
editor,
callback: None,
on_next_key_callback: None,
jobs,
};
let cloned_func = callback_fn.clone();
match future_value {
Ok(inner) => {
let callback = move |engine: &mut Engine, mut args: Vec<SteelVal>| {
args.push(inner);
engine.call_function_with_args(cloned_func.clone(), args)
};
if let Err(e) = ENGINE.with(|x| {
x.borrow_mut()
.with_mut_reference::<Context, Context>(&mut ctx)
.consume_once(callback)
}) {
present_error(&mut ctx, e);
}
}
Err(e) => {
present_error(&mut ctx, e);
}
}
},
);
Ok(call)
};
cx.jobs.local_callback(callback);
}
// Check that we successfully created a directory? // Check that we successfully created a directory?
fn create_directory(path: String) { fn create_directory(path: String) {
let path = helix_core::path::get_canonicalized_path(&PathBuf::from(path)).unwrap(); let path = helix_core::path::get_canonicalized_path(&PathBuf::from(path)).unwrap();

@ -636,6 +636,8 @@ pub(super) fn buffers_remaining_impl(editor: &mut Editor) -> anyhow::Result<()>
let (modified_ids, modified_names): (Vec<_>, Vec<_>) = editor let (modified_ids, modified_names): (Vec<_>, Vec<_>) = editor
.documents() .documents()
.filter(|doc| doc.is_modified()) .filter(|doc| doc.is_modified())
// Named scratch documents should not be included here
.filter(|doc| doc.name.is_none())
.map(|doc| (doc.id(), doc.display_name())) .map(|doc| (doc.id(), doc.display_name()))
.unzip(); .unzip();
if let Some(first) = modified_ids.first() { if let Some(first) = modified_ids.first() {

@ -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!
helix_term::commands::initialize_engine(); helix_term::commands::ScriptingEngine::initialize();
let config = match Config::load_default() { let config = match Config::load_default() {
Ok(config) => config, Ok(config) => config,

@ -6,7 +6,7 @@ use helix_core::str_utils::char_to_byte_idx;
use helix_core::syntax::Highlight; use helix_core::syntax::Highlight;
use helix_core::syntax::HighlightEvent; use helix_core::syntax::HighlightEvent;
use helix_core::text_annotations::TextAnnotations; use helix_core::text_annotations::TextAnnotations;
use helix_core::{visual_offset_from_block, Position, RopeSlice}; use helix_core::{visual_offset_from_block, Position, RopeSlice, Range};
use helix_view::editor::{WhitespaceConfig, WhitespaceRenderValue}; use helix_view::editor::{WhitespaceConfig, WhitespaceRenderValue};
use helix_view::graphics::Rect; use helix_view::graphics::Rect;
use helix_view::theme::Style; use helix_view::theme::Style;
@ -64,6 +64,7 @@ impl<H: Iterator<Item = HighlightEvent>> Iterator for StyleIter<'_, H> {
.fold(self.text_style, |acc, span| { .fold(self.text_style, |acc, span| {
acc.patch(self.theme.highlight(span.0)) acc.patch(self.theme.highlight(span.0))
}); });
return Some((style, end)); return Some((style, end));
} }
} }
@ -72,6 +73,55 @@ impl<H: Iterator<Item = HighlightEvent>> Iterator for StyleIter<'_, H> {
} }
} }
/// A wrapper around a HighlightIterator
/// that merges the layered highlights to create the final text style
/// and yields the active text style and the char_idx where the active
/// style will have to be recomputed.
struct RawStyleIter<'a, H: Iterator<Item = (Range, Style)>> {
text_style: Style,
active_highlights: Vec<Highlight>,
highlight_iter: H,
theme: &'a Theme,
}
impl<H: Iterator<Item = (Range, Style)>> Iterator for RawStyleIter<'_, H> {
type Item = (Style, usize);
fn next(&mut self) -> Option<(Style, usize)> {
while let Some(event) = self.highlight_iter.next() {
// let style = self.active_highlights.iter().fold(self.text_style, |acc, span| {
// acc.patch(event.1)
// });
return Some((self.text_style.patch(event.1), event.0.head))
// match event {
// HighlightEvent::HighlightStart(highlights) => {
// self.active_highlights.push(highlights)
// }
// HighlightEvent::HighlightEnd => {
// self.active_highlights.pop();
// }
// HighlightEvent::Source { start, end } => {
// if start == end {
// continue;
// }
// let style = self
// .active_highlights
// .iter()
// .fold(self.text_style, |acc, span| {
// acc.patch(self.theme.highlight(span.0))
// });
// return Some((style, end));
// }
// }
}
None
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct LinePos { pub struct LinePos {
/// Indicates whether the given visual line /// Indicates whether the given visual line
@ -103,6 +153,7 @@ pub fn render_document(
translated_positions: &mut [TranslatedPosition], translated_positions: &mut [TranslatedPosition],
) { ) {
let mut renderer = TextRenderer::new(surface, doc, theme, offset.horizontal_offset, viewport); let mut renderer = TextRenderer::new(surface, doc, theme, offset.horizontal_offset, viewport);
render_text( render_text(
&mut renderer, &mut renderer,
doc.text().slice(..), doc.text().slice(..),
@ -113,6 +164,7 @@ pub fn render_document(
theme, theme,
line_decoration, line_decoration,
translated_positions, translated_positions,
&doc.highlights,
) )
} }
@ -161,6 +213,7 @@ pub fn render_text<'t>(
theme: &Theme, theme: &Theme,
line_decorations: &mut [Box<dyn LineDecoration + '_>], line_decorations: &mut [Box<dyn LineDecoration + '_>],
translated_positions: &mut [TranslatedPosition], translated_positions: &mut [TranslatedPosition],
highlight_overrides: &[(helix_core::Range, Style)],
) { ) {
let ( let (
Position { Position {
@ -178,6 +231,7 @@ pub fn render_text<'t>(
let (mut formatter, mut first_visible_char_idx) = let (mut formatter, mut first_visible_char_idx) =
DocumentFormatter::new_at_prev_checkpoint(text, text_fmt, text_annotations, offset.anchor); DocumentFormatter::new_at_prev_checkpoint(text, text_fmt, text_annotations, offset.anchor);
let mut styles = StyleIter { let mut styles = StyleIter {
text_style: renderer.text_style, text_style: renderer.text_style,
active_highlights: Vec::with_capacity(64), active_highlights: Vec::with_capacity(64),
@ -215,7 +269,7 @@ pub fn render_text<'t>(
renderer, renderer,
last_pos, last_pos,
); );
} }
break; break;
}; };
@ -286,6 +340,8 @@ pub fn render_text<'t>(
style_span.0 style_span.0
}; };
// log::info!("Grapheme style: {:?}", grapheme_style);
let virt = grapheme.is_virtual(); let virt = grapheme.is_virtual();
renderer.draw_grapheme( renderer.draw_grapheme(
grapheme.grapheme, grapheme.grapheme,
@ -301,6 +357,170 @@ pub fn render_text<'t>(
for line_decoration in &mut *line_decorations { for line_decoration in &mut *line_decorations {
line_decoration.render_foreground(renderer, last_line_pos, char_pos); line_decoration.render_foreground(renderer, last_line_pos, char_pos);
} }
// If we have nothing... don't continue
// if highlight_overrides.is_empty() {
// return;
// }
// {
// let (
// Position {
// row: mut row_off, ..
// },
// mut char_pos,
// ) = visual_offset_from_block(
// text,
// offset.anchor,
// offset.anchor,
// text_fmt,
// text_annotations,
// );
// row_off += offset.vertical_offset;
// let (mut formatter, mut first_visible_char_idx) =
// DocumentFormatter::new_at_prev_checkpoint(text, text_fmt, text_annotations, offset.anchor);
// let mut styles = RawStyleIter {
// text_style: renderer.text_style,
// active_highlights: Vec::with_capacity(64),
// highlight_iter: std::iter::once((
// helix_core::Range::new(0, highlight_overrides[0].0.anchor),
// Style::default(),
// )).chain(highlight_overrides.iter().cloned()),
// theme
// };
// // StyleIter {
// // text_style: renderer.text_style,
// // active_highlights: Vec::with_capacity(64),
// // highlight_iter,
// // theme,
// // };
// // .chain(
// // highlight_overrides
// // .iter()
// // .map(|(range, style)| (*style, range.anchor));
// // );
// let mut last_line_pos = LinePos {
// first_visual_line: false,
// doc_line: usize::MAX,
// visual_line: u16::MAX,
// start_char_idx: usize::MAX,
// };
// let mut is_in_indent_area = true;
// let mut last_line_indent_level = 0;
// let mut style_span = styles
// .next()
// .unwrap_or_else(|| (Style::default(), usize::MAX));
// loop {
// // formattter.line_pos returns to line index of the next grapheme
// // so it must be called before formatter.next
// let doc_line = formatter.line_pos();
// let Some((grapheme, mut pos)) = formatter.next() else {
// let mut last_pos = formatter.visual_pos();
// if last_pos.row >= row_off {
// last_pos.col -= 1;
// last_pos.row -= row_off;
// // check if any positions translated on the fly (like cursor) are at the EOF
// translate_positions(
// char_pos + 1,
// first_visible_char_idx,
// translated_positions,
// text_fmt,
// renderer,
// last_pos,
// );
// }
// break;
// };
// // skip any graphemes on visual lines before the block start
// if pos.row < row_off {
// if char_pos >= style_span.1 {
// style_span = if let Some(style_span) = styles.next() {
// style_span
// } else {
// break;
// }
// }
// char_pos += grapheme.doc_chars();
// first_visible_char_idx = char_pos + 1;
// continue;
// }
// pos.row -= row_off;
// // if the end of the viewport is reached stop rendering
// if pos.row as u16 >= renderer.viewport.height {
// break;
// }
// // apply decorations before rendering a new line
// if pos.row as u16 != last_line_pos.visual_line {
// if pos.row > 0 {
// renderer.draw_indent_guides(last_line_indent_level, last_line_pos.visual_line);
// is_in_indent_area = true;
// for line_decoration in &mut *line_decorations {
// line_decoration.render_foreground(renderer, last_line_pos, char_pos);
// }
// }
// last_line_pos = LinePos {
// first_visual_line: doc_line != last_line_pos.doc_line,
// doc_line,
// visual_line: pos.row as u16,
// start_char_idx: char_pos,
// };
// for line_decoration in &mut *line_decorations {
// line_decoration.render_background(renderer, last_line_pos);
// }
// }
// // acquire the correct grapheme style
// if char_pos >= style_span.1 {
// style_span = styles.next().unwrap_or((Style::default(), usize::MAX));
// }
// char_pos += grapheme.doc_chars();
// // check if any positions translated on the fly (like cursor) has been reached
// translate_positions(
// char_pos,
// first_visible_char_idx,
// translated_positions,
// text_fmt,
// renderer,
// pos,
// );
// let grapheme_style = if let GraphemeSource::VirtualText { highlight } = grapheme.source {
// let style = renderer.text_style;
// if let Some(highlight) = highlight {
// style.patch(theme.highlight(highlight.0))
// } else {
// style
// }
// } else {
// style_span.0
// };
// let virt = grapheme.is_virtual();
// renderer.draw_grapheme(
// grapheme.grapheme,
// grapheme_style,
// virt,
// &mut last_line_indent_level,
// &mut is_in_indent_area,
// pos,
// );
// }
// renderer.draw_indent_guides(last_line_indent_level, last_line_pos.visual_line);
// for line_decoration in &mut *line_decorations {
// line_decoration.render_foreground(renderer, last_line_pos, char_pos);
// }
// }
} }
#[derive(Debug)] #[derive(Debug)]

@ -221,6 +221,13 @@ impl EditorView {
statusline::RenderContext::new(editor, doc, view, is_focused, &self.spinners); statusline::RenderContext::new(editor, doc, view, is_focused, &self.spinners);
statusline::render(&mut context, statusline_area, surface); statusline::render(&mut context, statusline_area, surface);
// Custom rendering table?
// for x in 0..20 {
// if let Some(cell) = surface.get_mut(x, 0) {
// cell.fg = Color::Green;
// }
// }
} }
pub fn render_rulers( pub fn render_rulers(

@ -425,6 +425,7 @@ where
let path = rel_path let path = rel_path
.as_ref() .as_ref()
.map(|p| p.to_string_lossy()) .map(|p| p.to_string_lossy())
.or_else(|| context.doc.name.as_ref().map(|x| x.into()))
.unwrap_or_else(|| SCRATCH_BUFFER_NAME.into()); .unwrap_or_else(|| SCRATCH_BUFFER_NAME.into());
format!(" {} ", path) format!(" {} ", path)
}; };
@ -455,6 +456,7 @@ where
let path = rel_path let path = rel_path
.as_ref() .as_ref()
.and_then(|p| p.as_path().file_name().map(|s| s.to_string_lossy())) .and_then(|p| p.as_path().file_name().map(|s| s.to_string_lossy()))
.or_else(|| context.doc.name.as_ref().map(|x| x.into()))
.unwrap_or_else(|| SCRATCH_BUFFER_NAME.into()); .unwrap_or_else(|| SCRATCH_BUFFER_NAME.into());
format!(" {} ", path) format!(" {} ", path)
}; };

@ -185,6 +185,14 @@ pub struct Document {
// when document was used for most-recent-used buffer picker // when document was used for most-recent-used buffer picker
pub focused_at: std::time::Instant, pub focused_at: std::time::Instant,
// TODO: This is not really something we _want_, but more seeing if it is
// enough to get away with custom applications of colors.
// Selection -> Style to apply for that selection AFTER rendering.
pub highlights: Vec<(Range, crate::graphics::Style)>,
// A name separate from the file name
pub name: Option<String>,
} }
/// Inlay hints for a single `(Document, View)` combo. /// Inlay hints for a single `(Document, View)` combo.
@ -634,6 +642,25 @@ where
use helix_lsp::{lsp, Client, LanguageServerName}; use helix_lsp::{lsp, Client, LanguageServerName};
use url::Url; use url::Url;
#[derive(Clone, PartialEq, Eq)]
struct RawHighlight {
pub start: usize,
pub end: usize,
pub style: crate::graphics::Style,
}
impl PartialOrd for RawHighlight {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.end.partial_cmp(&other.start)
}
}
impl Ord for RawHighlight {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.end.cmp(&other.start)
}
}
impl Document { impl Document {
pub fn from( pub fn from(
text: Rope, text: Rope,
@ -673,6 +700,11 @@ impl Document {
config, config,
version_control_head: None, version_control_head: None,
focused_at: std::time::Instant::now(), focused_at: std::time::Instant::now(),
highlights: vec![(
helix_core::Range::new(10, 20),
crate::graphics::Style::default().fg(crate::graphics::Color::Green),
)],
name: None,
} }
} }
@ -1623,6 +1655,7 @@ impl Document {
pub fn display_name(&self) -> Cow<'static, str> { pub fn display_name(&self) -> Cow<'static, str> {
self.relative_path() self.relative_path()
.map(|path| path.to_string_lossy().to_string().into()) .map(|path| path.to_string_lossy().to_string().into())
.or_else(|| self.name.as_ref().map(|x| Cow::Owned(x.clone())))
.unwrap_or_else(|| SCRATCH_BUFFER_NAME.into()) .unwrap_or_else(|| SCRATCH_BUFFER_NAME.into())
} }

Loading…
Cancel
Save