mirror of
https://github.com/helix-editor/helix.git
synced 2024-11-22 01:16:18 +04:00
Move ui, keymap & commands to helix-view
This commit is contained in:
parent
11b8f068da
commit
1aa2b027d7
15
Cargo.lock
generated
15
Cargo.lock
generated
@ -878,24 +878,17 @@ dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
"chrono",
|
||||
"content_inspector",
|
||||
"crossterm",
|
||||
"fern",
|
||||
"futures-util",
|
||||
"fuzzy-matcher",
|
||||
"grep-regex",
|
||||
"grep-searcher",
|
||||
"helix-core",
|
||||
"helix-dap",
|
||||
"helix-loader",
|
||||
"helix-lsp",
|
||||
"helix-tui",
|
||||
"helix-view",
|
||||
"ignore",
|
||||
"log",
|
||||
"once_cell",
|
||||
"pulldown-cmark",
|
||||
"retain_mut",
|
||||
"ropey",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -942,15 +935,23 @@ dependencies = [
|
||||
"bitflags",
|
||||
"chardetng",
|
||||
"clipboard-win",
|
||||
"content_inspector",
|
||||
"crossterm",
|
||||
"futures-util",
|
||||
"fuzzy-matcher",
|
||||
"grep-regex",
|
||||
"grep-searcher",
|
||||
"helix-core",
|
||||
"helix-dap",
|
||||
"helix-graphics",
|
||||
"helix-loader",
|
||||
"helix-lsp",
|
||||
"helix-tui",
|
||||
"ignore",
|
||||
"log",
|
||||
"once_cell",
|
||||
"pulldown-cmark",
|
||||
"retain_mut",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"slotmap",
|
||||
|
@ -51,27 +51,12 @@ fern = "0.6"
|
||||
chrono = { version = "0.4", default-features = false, features = ["clock"] }
|
||||
log = "0.4"
|
||||
|
||||
# File picker
|
||||
fuzzy-matcher = "0.3"
|
||||
ignore = "0.4"
|
||||
# markdown doc rendering
|
||||
pulldown-cmark = { version = "0.9", default-features = false }
|
||||
# file type detection
|
||||
content_inspector = "0.2.4"
|
||||
|
||||
# config
|
||||
toml = "0.5"
|
||||
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
||||
# ripgrep for global search
|
||||
grep-regex = "0.1.9"
|
||||
grep-searcher = "0.1.8"
|
||||
|
||||
# Remove once retain_mut lands in stable rust
|
||||
retain_mut = "0.1.7"
|
||||
|
||||
[target.'cfg(not(windows))'.dependencies] # https://github.com/vorner/signal-hook/issues/100
|
||||
signal-hook-tokio = { version = "0.3", features = ["futures-v0_3"] }
|
||||
|
||||
|
@ -4,18 +4,20 @@
|
||||
pos_at_coords, syntax, Selection,
|
||||
};
|
||||
|
||||
#[cfg(feature = "lsp")]
|
||||
use crate::commands::apply_workspace_edit;
|
||||
#[cfg(feature = "lsp")]
|
||||
use helix_lsp::{lsp, util::lsp_pos_to_pos, LspProgressMap};
|
||||
#[cfg(feature = "lsp")]
|
||||
use helix_view::commands::apply_workspace_edit;
|
||||
#[cfg(feature = "lsp")]
|
||||
use serde_json::json;
|
||||
|
||||
use helix_view::{align_view, editor::ConfigEvent, graphics::Rect, theme, Align, Editor};
|
||||
use helix_view::{
|
||||
align_view, editor::ConfigEvent, graphics::Rect, theme, true_color, Align, Editor,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
args::Args,
|
||||
config::Config,
|
||||
use crate::{args::Args, config::Config};
|
||||
|
||||
use helix_view::{
|
||||
keymap::Keymaps,
|
||||
ui::{self, overlay::overlayed},
|
||||
};
|
||||
@ -96,7 +98,7 @@ pub fn new(args: Args) -> Result<Self, Error> {
|
||||
&helix_loader::runtime_dir(),
|
||||
));
|
||||
|
||||
let true_color = config.editor.true_color || crate::true_color();
|
||||
let true_color = config.editor.true_color || true_color();
|
||||
let theme = config
|
||||
.theme
|
||||
.as_ref()
|
||||
@ -358,7 +360,7 @@ fn refresh_config(&mut self) {
|
||||
}
|
||||
|
||||
fn true_color(&self) -> bool {
|
||||
self.config.load().editor.true_color || crate::true_color()
|
||||
self.config.load().editor.true_color || true_color()
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
|
@ -1,6 +1,7 @@
|
||||
use anyhow::Result;
|
||||
use helix_core::Position;
|
||||
use std::path::{Path, PathBuf};
|
||||
use helix_view::args::parse_file;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Args {
|
||||
@ -65,37 +66,3 @@ pub fn parse_args() -> Result<Args> {
|
||||
Ok(args)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse arg into [`PathBuf`] and position.
|
||||
pub(crate) fn parse_file(s: &str) -> (PathBuf, Position) {
|
||||
let def = || (PathBuf::from(s), Position::default());
|
||||
if Path::new(s).exists() {
|
||||
return def();
|
||||
}
|
||||
split_path_row_col(s)
|
||||
.or_else(|| split_path_row(s))
|
||||
.unwrap_or_else(def)
|
||||
}
|
||||
|
||||
/// Split file.rs:10:2 into [`PathBuf`], row and col.
|
||||
///
|
||||
/// Does not validate if file.rs is a file or directory.
|
||||
fn split_path_row_col(s: &str) -> Option<(PathBuf, Position)> {
|
||||
let mut s = s.rsplitn(3, ':');
|
||||
let col: usize = s.next()?.parse().ok()?;
|
||||
let row: usize = s.next()?.parse().ok()?;
|
||||
let path = s.next()?.into();
|
||||
let pos = Position::new(row.saturating_sub(1), col.saturating_sub(1));
|
||||
Some((path, pos))
|
||||
}
|
||||
|
||||
/// Split file.rs:10 into [`PathBuf`] and row.
|
||||
///
|
||||
/// Does not validate if file.rs is a file or directory.
|
||||
fn split_path_row(s: &str) -> Option<(PathBuf, Position)> {
|
||||
let (path, row) = s.rsplit_once(':')?;
|
||||
let row: usize = row.parse().ok()?;
|
||||
let path = path.into();
|
||||
let pos = Position::new(row.saturating_sub(1), 0);
|
||||
Some((path, pos))
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::keymap::{default::default, merge_keys, Keymap};
|
||||
use helix_view::document::Mode;
|
||||
use helix_view::keymap::{default::default, Keymap};
|
||||
use serde::Deserialize;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Display;
|
||||
@ -27,6 +27,15 @@ fn default() -> Config {
|
||||
}
|
||||
}
|
||||
|
||||
/// Merge default config keys with user overwritten keys for custom user config.
|
||||
pub fn merge_keys(mut config: Config) -> Config {
|
||||
let mut delta = std::mem::replace(&mut config.keys, default());
|
||||
for (mode, keys) in &mut config.keys {
|
||||
keys.merge(delta.remove(mode).unwrap_or_default())
|
||||
}
|
||||
config
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ConfigLoadError {
|
||||
BadConfig(TomlError),
|
||||
@ -63,10 +72,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn parsing_keymaps_config_file() {
|
||||
use crate::keymap;
|
||||
use crate::keymap::Keymap;
|
||||
use helix_core::hashmap;
|
||||
use helix_view::document::Mode;
|
||||
use helix_view::keymap::{self, Keymap};
|
||||
|
||||
let sample_keymaps = r#"
|
||||
[keys.insert]
|
||||
@ -104,4 +112,104 @@ fn keys_resolve_to_correct_defaults() {
|
||||
let default_keys = Config::default().keys;
|
||||
assert_eq!(default_keys, default());
|
||||
}
|
||||
|
||||
use arc_swap::access::Constant;
|
||||
use helix_core::hashmap;
|
||||
|
||||
#[test]
|
||||
fn merge_partial_keys() {
|
||||
let config = Config {
|
||||
keys: hashmap! {
|
||||
Mode::Normal => Keymap::new(
|
||||
keymap!({ "Normal mode"
|
||||
"i" => normal_mode,
|
||||
"无" => insert_mode,
|
||||
"z" => jump_backward,
|
||||
"g" => { "Merge into goto mode"
|
||||
"$" => goto_line_end,
|
||||
"g" => delete_char_forward,
|
||||
},
|
||||
})
|
||||
)
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
let mut merged_config = merge_keys(config.clone());
|
||||
assert_ne!(config, merged_config);
|
||||
|
||||
let mut keymap = Keymaps::new(Box::new(Constant(merged_config.keys.clone())));
|
||||
assert_eq!(
|
||||
keymap.get(Mode::Normal, key!('i')),
|
||||
KeymapResult::Matched(MappableCommand::normal_mode),
|
||||
"Leaf should replace leaf"
|
||||
);
|
||||
assert_eq!(
|
||||
keymap.get(Mode::Normal, key!('无')),
|
||||
KeymapResult::Matched(MappableCommand::insert_mode),
|
||||
"New leaf should be present in merged keymap"
|
||||
);
|
||||
// Assumes that z is a node in the default keymap
|
||||
assert_eq!(
|
||||
keymap.get(Mode::Normal, key!('z')),
|
||||
KeymapResult::Matched(MappableCommand::jump_backward),
|
||||
"Leaf should replace node"
|
||||
);
|
||||
|
||||
let keymap = merged_config.keys.get_mut(&Mode::Normal).unwrap();
|
||||
// Assumes that `g` is a node in default keymap
|
||||
assert_eq!(
|
||||
keymap.root().search(&[key!('g'), key!('$')]).unwrap(),
|
||||
&KeyTrie::Leaf(MappableCommand::goto_line_end),
|
||||
"Leaf should be present in merged subnode"
|
||||
);
|
||||
// Assumes that `gg` is in default keymap
|
||||
assert_eq!(
|
||||
keymap.root().search(&[key!('g'), key!('g')]).unwrap(),
|
||||
&KeyTrie::Leaf(MappableCommand::delete_char_forward),
|
||||
"Leaf should replace old leaf in merged subnode"
|
||||
);
|
||||
// Assumes that `ge` is in default keymap
|
||||
assert_eq!(
|
||||
keymap.root().search(&[key!('g'), key!('e')]).unwrap(),
|
||||
&KeyTrie::Leaf(MappableCommand::goto_last_line),
|
||||
"Old leaves in subnode should be present in merged node"
|
||||
);
|
||||
|
||||
assert!(merged_config.keys.get(&Mode::Normal).unwrap().len() > 1);
|
||||
assert!(merged_config.keys.get(&Mode::Insert).unwrap().len() > 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn order_should_be_set() {
|
||||
let config = Config {
|
||||
keys: hashmap! {
|
||||
Mode::Normal => Keymap::new(
|
||||
keymap!({ "Normal mode"
|
||||
"space" => { ""
|
||||
"s" => { ""
|
||||
"v" => vsplit,
|
||||
"c" => hsplit,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
let mut merged_config = merge_keys(config.clone());
|
||||
assert_ne!(config, merged_config);
|
||||
let keymap = merged_config.keys.get_mut(&Mode::Normal).unwrap();
|
||||
// Make sure mapping works
|
||||
assert_eq!(
|
||||
keymap
|
||||
.root()
|
||||
.search(&[key!(' '), key!('s'), key!('v')])
|
||||
.unwrap(),
|
||||
&KeyTrie::Leaf(MappableCommand::vsplit),
|
||||
"Leaf should be present in merged subnode"
|
||||
);
|
||||
// Make sure an order was set during merge
|
||||
let node = keymap.root().search(&[helix_view::key!(' ')]).unwrap();
|
||||
assert!(!node.node().unwrap().order().is_empty())
|
||||
}
|
||||
}
|
||||
|
@ -1,127 +0,0 @@
|
||||
#[macro_export]
|
||||
macro_rules! key {
|
||||
($key:ident) => {
|
||||
::helix_view::input::KeyEvent {
|
||||
code: ::helix_view::keyboard::KeyCode::$key,
|
||||
modifiers: ::helix_view::keyboard::KeyModifiers::NONE,
|
||||
}
|
||||
};
|
||||
($($ch:tt)*) => {
|
||||
::helix_view::input::KeyEvent {
|
||||
code: ::helix_view::keyboard::KeyCode::Char($($ch)*),
|
||||
modifiers: ::helix_view::keyboard::KeyModifiers::NONE,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! shift {
|
||||
($key:ident) => {
|
||||
::helix_view::input::KeyEvent {
|
||||
code: ::helix_view::keyboard::KeyCode::$key,
|
||||
modifiers: ::helix_view::keyboard::KeyModifiers::SHIFT,
|
||||
}
|
||||
};
|
||||
($($ch:tt)*) => {
|
||||
::helix_view::input::KeyEvent {
|
||||
code: ::helix_view::keyboard::KeyCode::Char($($ch)*),
|
||||
modifiers: ::helix_view::keyboard::KeyModifiers::SHIFT,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! ctrl {
|
||||
($key:ident) => {
|
||||
::helix_view::input::KeyEvent {
|
||||
code: ::helix_view::keyboard::KeyCode::$key,
|
||||
modifiers: ::helix_view::keyboard::KeyModifiers::CONTROL,
|
||||
}
|
||||
};
|
||||
($($ch:tt)*) => {
|
||||
::helix_view::input::KeyEvent {
|
||||
code: ::helix_view::keyboard::KeyCode::Char($($ch)*),
|
||||
modifiers: ::helix_view::keyboard::KeyModifiers::CONTROL,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! alt {
|
||||
($key:ident) => {
|
||||
::helix_view::input::KeyEvent {
|
||||
code: ::helix_view::keyboard::KeyCode::$key,
|
||||
modifiers: ::helix_view::keyboard::KeyModifiers::ALT,
|
||||
}
|
||||
};
|
||||
($($ch:tt)*) => {
|
||||
::helix_view::input::KeyEvent {
|
||||
code: ::helix_view::keyboard::KeyCode::Char($($ch)*),
|
||||
modifiers: ::helix_view::keyboard::KeyModifiers::ALT,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Macro for defining the root of a `Keymap` object. Example:
|
||||
///
|
||||
/// ```
|
||||
/// # use helix_core::hashmap;
|
||||
/// # use helix_term::keymap;
|
||||
/// # use helix_term::keymap::Keymap;
|
||||
/// let normal_mode = keymap!({ "Normal mode"
|
||||
/// "i" => insert_mode,
|
||||
/// "g" => { "Goto"
|
||||
/// "g" => goto_file_start,
|
||||
/// "e" => goto_file_end,
|
||||
/// },
|
||||
/// "j" | "down" => move_line_down,
|
||||
/// });
|
||||
/// let keymap = Keymap::new(normal_mode);
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! keymap {
|
||||
(@trie $cmd:ident) => {
|
||||
$crate::keymap::KeyTrie::Leaf($crate::commands::MappableCommand::$cmd)
|
||||
};
|
||||
|
||||
(@trie
|
||||
{ $label:literal $(sticky=$sticky:literal)? $($($key:literal)|+ => $value:tt,)+ }
|
||||
) => {
|
||||
keymap!({ $label $(sticky=$sticky)? $($($key)|+ => $value,)+ })
|
||||
};
|
||||
|
||||
(@trie [$($cmd:ident),* $(,)?]) => {
|
||||
$crate::keymap::KeyTrie::Sequence(vec![$($crate::commands::Command::$cmd),*])
|
||||
};
|
||||
|
||||
(
|
||||
{ $label:literal $(sticky=$sticky:literal)? $($($key:literal)|+ => $value:tt,)+ }
|
||||
) => {
|
||||
// modified from the hashmap! macro
|
||||
{
|
||||
let _cap = hashmap!(@count $($($key),+),*);
|
||||
let mut _map = ::std::collections::HashMap::with_capacity(_cap);
|
||||
let mut _order = ::std::vec::Vec::with_capacity(_cap);
|
||||
$(
|
||||
$(
|
||||
let _key = $key.parse::<::helix_view::input::KeyEvent>().unwrap();
|
||||
let _duplicate = _map.insert(
|
||||
_key,
|
||||
keymap!(@trie $value)
|
||||
);
|
||||
assert!(_duplicate.is_none(), "Duplicate key found: {:?}", _duplicate.unwrap());
|
||||
_order.push(_key);
|
||||
)+
|
||||
)*
|
||||
let mut _node = $crate::keymap::KeyTrieNode::new($label, _map, _order);
|
||||
$( _node.is_sticky = $sticky; )?
|
||||
$crate::keymap::KeyTrie::Node(_node)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub use alt;
|
||||
pub use ctrl;
|
||||
pub use key;
|
||||
pub use keymap;
|
||||
pub use shift;
|
@ -3,20 +3,5 @@
|
||||
|
||||
pub mod application;
|
||||
pub mod args;
|
||||
pub mod commands;
|
||||
pub mod config;
|
||||
pub mod health;
|
||||
pub mod keymap;
|
||||
pub mod ui;
|
||||
pub use keymap::macros::*;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn true_color() -> bool {
|
||||
std::env::var("COLORTERM")
|
||||
.map(|v| matches!(v.as_str(), "truecolor" | "24bit"))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
#[cfg(windows)]
|
||||
fn true_color() -> bool {
|
||||
true
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ helix-core = { version = "0.6", path = "../helix-core" }
|
||||
helix-graphics = { version = "0.6", path = "../helix-graphics" }
|
||||
helix-lsp = { version = "0.6", path = "../helix-lsp", optional = true }
|
||||
helix-dap = { version = "0.6", path = "../helix-dap", optional = true }
|
||||
helix-loader = { version = "0.6", path = "../helix-loader" }
|
||||
tokio-stream = { version = "0.1", optional = true }
|
||||
tokio = { version = "1", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot", "sync"], optional = true }
|
||||
|
||||
@ -46,6 +47,23 @@ serde_json = "1.0"
|
||||
toml = "0.5"
|
||||
log = "~0.4"
|
||||
|
||||
# Command dependencies
|
||||
|
||||
# File picker
|
||||
fuzzy-matcher = "0.3"
|
||||
ignore = "0.4"
|
||||
# markdown doc rendering
|
||||
pulldown-cmark = { version = "0.9", default-features = false }
|
||||
# file type detection
|
||||
content_inspector = "0.2.4"
|
||||
|
||||
# ripgrep for global search
|
||||
grep-regex = "0.1.9"
|
||||
grep-searcher = "0.1.8"
|
||||
|
||||
# Remove once retain_mut lands in stable rust
|
||||
retain_mut = "0.1.7"
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
which = "4.2"
|
||||
|
||||
|
36
helix-view/src/args.rs
Normal file
36
helix-view/src/args.rs
Normal file
@ -0,0 +1,36 @@
|
||||
use helix_core::Position;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// Parse arg into [`PathBuf`] and position.
|
||||
pub fn parse_file(s: &str) -> (PathBuf, Position) {
|
||||
let def = || (PathBuf::from(s), Position::default());
|
||||
if Path::new(s).exists() {
|
||||
return def();
|
||||
}
|
||||
split_path_row_col(s)
|
||||
.or_else(|| split_path_row(s))
|
||||
.unwrap_or_else(def)
|
||||
}
|
||||
|
||||
/// Split file.rs:10:2 into [`PathBuf`], row and col.
|
||||
///
|
||||
/// Does not validate if file.rs is a file or directory.
|
||||
fn split_path_row_col(s: &str) -> Option<(PathBuf, Position)> {
|
||||
let mut s = s.rsplitn(3, ':');
|
||||
let col: usize = s.next()?.parse().ok()?;
|
||||
let row: usize = s.next()?.parse().ok()?;
|
||||
let path = s.next()?.into();
|
||||
let pos = Position::new(row.saturating_sub(1), col.saturating_sub(1));
|
||||
Some((path, pos))
|
||||
}
|
||||
|
||||
/// Split file.rs:10 into [`PathBuf`] and row.
|
||||
///
|
||||
/// Does not validate if file.rs is a file or directory.
|
||||
fn split_path_row(s: &str) -> Option<(PathBuf, Position)> {
|
||||
let (path, row) = s.rsplit_once(':')?;
|
||||
let row: usize = row.parse().ok()?;
|
||||
let path = path.into();
|
||||
let pos = Position::new(row.saturating_sub(1), 0);
|
||||
Some((path, pos))
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
use super::{Context, Editor};
|
||||
use crate::editor::Breakpoint;
|
||||
use crate::ui::{self, overlay::overlayed, FilePicker, Picker, Popup, Prompt, PromptEvent, Text};
|
||||
use helix_core::syntax::{DebugArgumentValue, DebugConfigCompletion};
|
||||
use helix_dap::{self as dap, Client};
|
||||
use helix_lsp::block_on;
|
||||
use helix_view::editor::Breakpoint;
|
||||
use helix_view::{
|
||||
use crate::{
|
||||
compositor::{self, Compositor},
|
||||
job::{Callback, Jobs},
|
||||
};
|
||||
use helix_core::syntax::{DebugArgumentValue, DebugConfigCompletion};
|
||||
use helix_dap::{self as dap, Client};
|
||||
use helix_lsp::block_on;
|
||||
|
||||
use serde_json::{to_value, Value};
|
||||
use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||
@ -18,7 +18,8 @@
|
||||
|
||||
use anyhow::{anyhow, bail};
|
||||
|
||||
use helix_view::handlers::dap::{breakpoints_changed, jump_to_stack_frame, select_thread_id};
|
||||
use crate::debugger;
|
||||
use crate::handlers::dap::{breakpoints_changed, jump_to_stack_frame, select_thread_id};
|
||||
|
||||
fn thread_picker(
|
||||
cx: &mut Context,
|
||||
@ -474,7 +475,7 @@ pub fn dap_variables(cx: &mut Context) {
|
||||
let text_style = theme.get("ui.text.focus");
|
||||
|
||||
for scope in scopes.iter() {
|
||||
// use helix_view::graphics::Style;
|
||||
// use crate::graphics::Style;
|
||||
use tui::text::{Span, Spans};
|
||||
let response = block_on(debugger.variables(scope.variables_reference));
|
||||
|
@ -7,10 +7,10 @@
|
||||
use super::{align_view, push_jump, Align, Context, Editor};
|
||||
|
||||
use helix_core::Selection;
|
||||
use helix_view::editor::Action;
|
||||
use crate::editor::Action;
|
||||
|
||||
use crate::ui::{self, overlay::overlayed, FileLocation, FilePicker, Popup, PromptEvent};
|
||||
use helix_view::compositor::{self, Compositor};
|
||||
use crate::compositor::{self, Compositor};
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
@ -255,7 +255,7 @@ pub fn code_action(cx: &mut Context) {
|
||||
});
|
||||
picker.move_down(); // pre-select the first item
|
||||
|
||||
let popup = Popup::new("code-action", picker).margin(helix_view::graphics::Margin {
|
||||
let popup = Popup::new("code-action", picker).margin(crate::graphics::Margin {
|
||||
vertical: 1,
|
||||
horizontal: 1,
|
||||
});
|
@ -10,6 +10,16 @@
|
||||
pub use lsp::*;
|
||||
pub use typed::*;
|
||||
|
||||
use crate::{
|
||||
clipboard::ClipboardType,
|
||||
document::{Mode, SCRATCH_BUFFER_NAME},
|
||||
editor::{Action, Motion},
|
||||
info::Info,
|
||||
input::KeyEvent,
|
||||
keyboard::KeyCode,
|
||||
view::View,
|
||||
Document, DocumentId, Editor, ViewId,
|
||||
};
|
||||
use helix_core::{
|
||||
comment, coords_at_pos, find_first_non_whitespace_char, find_root, graphemes,
|
||||
history::UndoKind,
|
||||
@ -29,18 +39,8 @@
|
||||
LineEnding, Position, Range, Rope, RopeGraphemes, RopeSlice, Selection, SmallVec, Tendril,
|
||||
Transaction,
|
||||
};
|
||||
use helix_view::{
|
||||
clipboard::ClipboardType,
|
||||
document::{Mode, SCRATCH_BUFFER_NAME},
|
||||
editor::{Action, Motion},
|
||||
info::Info,
|
||||
input::KeyEvent,
|
||||
keyboard::KeyCode,
|
||||
view::View,
|
||||
Document, DocumentId, Editor, ViewId,
|
||||
};
|
||||
|
||||
use helix_view::{
|
||||
use crate::{
|
||||
compositor::{self, Component, Compositor},
|
||||
job::{self, Job, Jobs},
|
||||
};
|
||||
@ -56,8 +56,13 @@
|
||||
};
|
||||
|
||||
use futures_util::{FutureExt, StreamExt};
|
||||
use std::{collections::HashMap, fmt, future::Future};
|
||||
use std::{collections::HashSet, num::NonZeroUsize};
|
||||
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
fmt,
|
||||
future::Future,
|
||||
num::NonZeroUsize,
|
||||
};
|
||||
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
@ -77,7 +82,7 @@ pub struct Context<'a> {
|
||||
pub count: Option<NonZeroUsize>,
|
||||
pub editor: &'a mut Editor,
|
||||
|
||||
pub callback: Option<helix_view::compositor::Callback>,
|
||||
pub callback: Option<crate::compositor::Callback>,
|
||||
pub on_next_key_callback: Option<Box<dyn FnOnce(&mut Context, KeyEvent)>>,
|
||||
pub jobs: &'a mut Jobs,
|
||||
}
|
||||
@ -126,7 +131,7 @@ pub fn count(&self) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
use helix_view::{align_view, Align};
|
||||
use crate::{align_view, Align};
|
||||
|
||||
/// A MappableCommand is either a static command like "jump_view_up" or a Typable command like
|
||||
/// :format. It causes a side-effect on the state (usually by creating and applying a transaction).
|
||||
@ -4397,8 +4402,8 @@ fn shell_prompt(cx: &mut Context, prompt: Cow<'static, str>, behavior: ShellBeha
|
||||
}
|
||||
|
||||
fn suspend(_cx: &mut Context) {
|
||||
#[cfg(not(windows))]
|
||||
signal_hook::low_level::raise(signal_hook::consts::signal::SIGTSTP).unwrap();
|
||||
// #[cfg(not(windows))]
|
||||
// signal_hook::low_level::raise(signal_hook::consts::signal::SIGTSTP).unwrap();
|
||||
}
|
||||
|
||||
fn add_newline_above(cx: &mut Context) {
|
||||
@ -4557,7 +4562,7 @@ fn record_macro(cx: &mut Context) {
|
||||
fn replay_macro(cx: &mut Context) {
|
||||
let reg = cx.register.unwrap_or('@');
|
||||
let keys: Vec<KeyEvent> = if let Some([keys_str]) = cx.editor.registers.read(reg) {
|
||||
match helix_view::input::parse_macro(keys_str) {
|
||||
match crate::input::parse_macro(keys_str) {
|
||||
Ok(keys) => keys,
|
||||
Err(err) => {
|
||||
cx.editor.set_error(format!("Invalid macro: {}", err));
|
@ -1,6 +1,6 @@
|
||||
use super::*;
|
||||
|
||||
use helix_view::editor::{Action, ConfigEvent};
|
||||
use crate::editor::{Action, ConfigEvent};
|
||||
use ui::completers::{self, Completer};
|
||||
|
||||
#[derive(Clone)]
|
@ -2,12 +2,11 @@
|
||||
pub mod macros;
|
||||
|
||||
pub use crate::commands::MappableCommand;
|
||||
use crate::config::Config;
|
||||
use crate::{document::Mode, info::Info, input::KeyEvent};
|
||||
use arc_swap::{
|
||||
access::{DynAccess, DynGuard},
|
||||
ArcSwap,
|
||||
};
|
||||
use helix_view::{document::Mode, info::Info, input::KeyEvent};
|
||||
use serde::Deserialize;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
@ -361,20 +360,10 @@ fn default() -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
/// Merge default config keys with user overwritten keys for custom user config.
|
||||
pub fn merge_keys(mut config: Config) -> Config {
|
||||
let mut delta = std::mem::replace(&mut config.keys, default());
|
||||
for (mode, keys) in &mut config.keys {
|
||||
keys.merge(delta.remove(mode).unwrap_or_default())
|
||||
}
|
||||
config
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::macros::keymap;
|
||||
use super::*;
|
||||
use arc_swap::access::Constant;
|
||||
use helix_core::hashmap;
|
||||
|
||||
#[test]
|
||||
@ -392,103 +381,6 @@ fn check_duplicate_keys_in_default_keymap() {
|
||||
Keymaps::default();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merge_partial_keys() {
|
||||
let config = Config {
|
||||
keys: hashmap! {
|
||||
Mode::Normal => Keymap::new(
|
||||
keymap!({ "Normal mode"
|
||||
"i" => normal_mode,
|
||||
"无" => insert_mode,
|
||||
"z" => jump_backward,
|
||||
"g" => { "Merge into goto mode"
|
||||
"$" => goto_line_end,
|
||||
"g" => delete_char_forward,
|
||||
},
|
||||
})
|
||||
)
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
let mut merged_config = merge_keys(config.clone());
|
||||
assert_ne!(config, merged_config);
|
||||
|
||||
let mut keymap = Keymaps::new(Box::new(Constant(merged_config.keys.clone())));
|
||||
assert_eq!(
|
||||
keymap.get(Mode::Normal, key!('i')),
|
||||
KeymapResult::Matched(MappableCommand::normal_mode),
|
||||
"Leaf should replace leaf"
|
||||
);
|
||||
assert_eq!(
|
||||
keymap.get(Mode::Normal, key!('无')),
|
||||
KeymapResult::Matched(MappableCommand::insert_mode),
|
||||
"New leaf should be present in merged keymap"
|
||||
);
|
||||
// Assumes that z is a node in the default keymap
|
||||
assert_eq!(
|
||||
keymap.get(Mode::Normal, key!('z')),
|
||||
KeymapResult::Matched(MappableCommand::jump_backward),
|
||||
"Leaf should replace node"
|
||||
);
|
||||
|
||||
let keymap = merged_config.keys.get_mut(&Mode::Normal).unwrap();
|
||||
// Assumes that `g` is a node in default keymap
|
||||
assert_eq!(
|
||||
keymap.root().search(&[key!('g'), key!('$')]).unwrap(),
|
||||
&KeyTrie::Leaf(MappableCommand::goto_line_end),
|
||||
"Leaf should be present in merged subnode"
|
||||
);
|
||||
// Assumes that `gg` is in default keymap
|
||||
assert_eq!(
|
||||
keymap.root().search(&[key!('g'), key!('g')]).unwrap(),
|
||||
&KeyTrie::Leaf(MappableCommand::delete_char_forward),
|
||||
"Leaf should replace old leaf in merged subnode"
|
||||
);
|
||||
// Assumes that `ge` is in default keymap
|
||||
assert_eq!(
|
||||
keymap.root().search(&[key!('g'), key!('e')]).unwrap(),
|
||||
&KeyTrie::Leaf(MappableCommand::goto_last_line),
|
||||
"Old leaves in subnode should be present in merged node"
|
||||
);
|
||||
|
||||
assert!(merged_config.keys.get(&Mode::Normal).unwrap().len() > 1);
|
||||
assert!(merged_config.keys.get(&Mode::Insert).unwrap().len() > 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn order_should_be_set() {
|
||||
let config = Config {
|
||||
keys: hashmap! {
|
||||
Mode::Normal => Keymap::new(
|
||||
keymap!({ "Normal mode"
|
||||
"space" => { ""
|
||||
"s" => { ""
|
||||
"v" => vsplit,
|
||||
"c" => hsplit,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
let mut merged_config = merge_keys(config.clone());
|
||||
assert_ne!(config, merged_config);
|
||||
let keymap = merged_config.keys.get_mut(&Mode::Normal).unwrap();
|
||||
// Make sure mapping works
|
||||
assert_eq!(
|
||||
keymap
|
||||
.root()
|
||||
.search(&[key!(' '), key!('s'), key!('v')])
|
||||
.unwrap(),
|
||||
&KeyTrie::Leaf(MappableCommand::vsplit),
|
||||
"Leaf should be present in merged subnode"
|
||||
);
|
||||
// Make sure an order was set during merge
|
||||
let node = keymap.root().search(&[crate::key!(' ')]).unwrap();
|
||||
assert!(!node.node().unwrap().order().is_empty())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aliased_modes_are_same_in_default_keymap() {
|
||||
let keymaps = Keymaps::default().map();
|
60
helix-view/src/keymap/macros.rs
Normal file
60
helix-view/src/keymap/macros.rs
Normal file
@ -0,0 +1,60 @@
|
||||
/// Macro for defining the root of a `Keymap` object. Example:
|
||||
///
|
||||
/// ```
|
||||
/// # use helix_core::hashmap;
|
||||
/// # use helix_term::keymap;
|
||||
/// # use helix_term::keymap::Keymap;
|
||||
/// let normal_mode = keymap!({ "Normal mode"
|
||||
/// "i" => insert_mode,
|
||||
/// "g" => { "Goto"
|
||||
/// "g" => goto_file_start,
|
||||
/// "e" => goto_file_end,
|
||||
/// },
|
||||
/// "j" | "down" => move_line_down,
|
||||
/// });
|
||||
/// let keymap = Keymap::new(normal_mode);
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! keymap {
|
||||
(@trie $cmd:ident) => {
|
||||
$crate::keymap::KeyTrie::Leaf($crate::commands::MappableCommand::$cmd)
|
||||
};
|
||||
|
||||
(@trie
|
||||
{ $label:literal $(sticky=$sticky:literal)? $($($key:literal)|+ => $value:tt,)+ }
|
||||
) => {
|
||||
keymap!({ $label $(sticky=$sticky)? $($($key)|+ => $value,)+ })
|
||||
};
|
||||
|
||||
(@trie [$($cmd:ident),* $(,)?]) => {
|
||||
$crate::keymap::KeyTrie::Sequence(vec![$($crate::commands::Command::$cmd),*])
|
||||
};
|
||||
|
||||
(
|
||||
{ $label:literal $(sticky=$sticky:literal)? $($($key:literal)|+ => $value:tt,)+ }
|
||||
) => {
|
||||
// modified from the hashmap! macro
|
||||
{
|
||||
let _cap = hashmap!(@count $($($key),+),*);
|
||||
let mut _map = ::std::collections::HashMap::with_capacity(_cap);
|
||||
let mut _order = ::std::vec::Vec::with_capacity(_cap);
|
||||
$(
|
||||
$(
|
||||
let _key = $key.parse::<$crate::input::KeyEvent>().unwrap();
|
||||
let _duplicate = _map.insert(
|
||||
_key,
|
||||
keymap!(@trie $value)
|
||||
);
|
||||
assert!(_duplicate.is_none(), "Duplicate key found: {:?}", _duplicate.unwrap());
|
||||
_order.push(_key);
|
||||
)+
|
||||
)*
|
||||
let mut _node = $crate::keymap::KeyTrieNode::new($label, _map, _order);
|
||||
$( _node.is_sticky = $sticky; )?
|
||||
$crate::keymap::KeyTrie::Node(_node)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub use crate::{alt, ctrl, key, shift};
|
||||
pub use keymap;
|
@ -1,17 +1,22 @@
|
||||
#[macro_use]
|
||||
pub mod macros;
|
||||
|
||||
pub mod args;
|
||||
pub mod backend {
|
||||
#[cfg(feature = "term")]
|
||||
pub mod term;
|
||||
}
|
||||
pub mod clipboard;
|
||||
pub mod commands;
|
||||
pub mod compositor;
|
||||
pub mod document;
|
||||
pub mod editor;
|
||||
pub mod ui;
|
||||
pub use helix_graphics as graphics;
|
||||
pub mod gutter;
|
||||
pub mod job;
|
||||
pub mod keymap;
|
||||
pub use keymap::macros::*;
|
||||
pub mod handlers {
|
||||
#[cfg(feature = "dap")]
|
||||
pub mod dap;
|
||||
@ -47,6 +52,17 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
pub struct ViewId;
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub fn true_color() -> bool {
|
||||
std::env::var("COLORTERM")
|
||||
.map(|v| matches!(v.as_str(), "truecolor" | "24bit"))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
#[cfg(windows)]
|
||||
pub fn true_color() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
pub enum Align {
|
||||
Top,
|
||||
Center,
|
||||
|
@ -61,3 +61,69 @@ macro_rules! doc {
|
||||
$crate::current_ref!($editor).1
|
||||
}};
|
||||
}
|
||||
|
||||
// Keymap macros
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! key {
|
||||
($key:ident) => {
|
||||
$crate::input::KeyEvent {
|
||||
code: $crate::keyboard::KeyCode::$key,
|
||||
modifiers: $crate::keyboard::KeyModifiers::NONE,
|
||||
}
|
||||
};
|
||||
($($ch:tt)*) => {
|
||||
$crate::input::KeyEvent {
|
||||
code: $crate::keyboard::KeyCode::Char($($ch)*),
|
||||
modifiers: $crate::keyboard::KeyModifiers::NONE,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! shift {
|
||||
($key:ident) => {
|
||||
$crate::input::KeyEvent {
|
||||
code: $crate::keyboard::KeyCode::$key,
|
||||
modifiers: $crate::keyboard::KeyModifiers::SHIFT,
|
||||
}
|
||||
};
|
||||
($($ch:tt)*) => {
|
||||
$crate::input::KeyEvent {
|
||||
code: $crate::keyboard::KeyCode::Char($($ch)*),
|
||||
modifiers: $crate::keyboard::KeyModifiers::SHIFT,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! ctrl {
|
||||
($key:ident) => {
|
||||
$crate::input::KeyEvent {
|
||||
code: $crate::keyboard::KeyCode::$key,
|
||||
modifiers: $crate::keyboard::KeyModifiers::CONTROL,
|
||||
}
|
||||
};
|
||||
($($ch:tt)*) => {
|
||||
$crate::input::KeyEvent {
|
||||
code: $crate::keyboard::KeyCode::Char($($ch)*),
|
||||
modifiers: $crate::keyboard::KeyModifiers::CONTROL,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! alt {
|
||||
($key:ident) => {
|
||||
$crate::input::KeyEvent {
|
||||
code: $crate::keyboard::KeyCode::$key,
|
||||
modifiers: $crate::keyboard::KeyModifiers::ALT,
|
||||
}
|
||||
};
|
||||
($($ch:tt)*) => {
|
||||
$crate::input::KeyEvent {
|
||||
code: $crate::keyboard::KeyCode::Char($($ch)*),
|
||||
modifiers: $crate::keyboard::KeyModifiers::ALT,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
use helix_view::compositor::{Component, Context, Event, EventResult, RenderContext};
|
||||
use helix_view::editor::CompleteAction;
|
||||
use crate::compositor::{Component, Context, Event, EventResult, RenderContext};
|
||||
use crate::editor::CompleteAction;
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
use helix_core::{Change, Transaction};
|
||||
use helix_view::{
|
||||
use crate::{
|
||||
graphics::Rect,
|
||||
input::{KeyCode, KeyEvent},
|
||||
Document, Editor,
|
@ -4,7 +4,7 @@
|
||||
ui::{Completion, ProgressSpinners},
|
||||
};
|
||||
|
||||
use helix_view::compositor::{Component, Context, Event, EventResult, RenderContext};
|
||||
use crate::compositor::{Component, Context, Event, EventResult, RenderContext};
|
||||
|
||||
use helix_core::{
|
||||
coords_at_pos, encoding,
|
||||
@ -17,7 +17,7 @@
|
||||
unicode::width::UnicodeWidthStr,
|
||||
LineEnding, Position, Range, Selection, Transaction,
|
||||
};
|
||||
use helix_view::{
|
||||
use crate::{
|
||||
document::{Mode, SCRATCH_BUFFER_NAME},
|
||||
editor::{CompleteAction, CursorShapeConfig},
|
||||
graphics::{CursorKind, Modifier, Rect, Style},
|
||||
@ -928,7 +928,7 @@ pub fn clear_completion(&mut self, editor: &mut Editor) {
|
||||
editor.clear_idle_timer(); // don't retrigger
|
||||
}
|
||||
|
||||
pub fn handle_idle_timeout(&mut self, cx: &mut helix_view::compositor::Context) -> EventResult {
|
||||
pub fn handle_idle_timeout(&mut self, cx: &mut crate::compositor::Context) -> EventResult {
|
||||
if self.completion.is_some()
|
||||
|| !cx.editor.config().auto_completion
|
||||
|| doc!(cx.editor).mode != Mode::Insert
|
||||
@ -1163,7 +1163,7 @@ impl Component for EditorView {
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
context: &mut helix_view::compositor::Context,
|
||||
context: &mut crate::compositor::Context,
|
||||
) -> EventResult {
|
||||
let mut cx = commands::Context {
|
||||
editor: context.editor,
|
||||
@ -1314,7 +1314,7 @@ fn render(&mut self, area: Rect, cx: &mut RenderContext<'_>) {
|
||||
// render status msg
|
||||
if let Some((status_msg, severity)) = &cx.editor.status_msg {
|
||||
status_msg_width = status_msg.width();
|
||||
use helix_view::editor::Severity;
|
||||
use crate::editor::Severity;
|
||||
let style = if *severity == Severity::Error {
|
||||
cx.editor.theme.get("error")
|
||||
} else {
|
||||
@ -1361,7 +1361,7 @@ fn render(&mut self, area: Rect, cx: &mut RenderContext<'_>) {
|
||||
if let Some((reg, _)) = cx.editor.macro_recording {
|
||||
let disp = format!("[{}]", reg);
|
||||
let style = style
|
||||
.fg(helix_view::graphics::Color::Yellow)
|
||||
.fg(crate::graphics::Color::Yellow)
|
||||
.add_modifier(Modifier::BOLD);
|
||||
cx.surface.set_string(
|
||||
area.x + area.width.saturating_sub(3),
|
@ -1,4 +1,4 @@
|
||||
use helix_view::compositor::{Component, RenderContext};
|
||||
use crate::compositor::{Component, RenderContext};
|
||||
use tui::text::{Span, Spans, Text};
|
||||
|
||||
use std::sync::Arc;
|
||||
@ -9,7 +9,7 @@
|
||||
syntax::{self, HighlightEvent, Syntax},
|
||||
Rope,
|
||||
};
|
||||
use helix_view::{
|
||||
use crate::{
|
||||
graphics::{Margin, Rect, Style},
|
||||
Theme,
|
||||
};
|
@ -1,5 +1,5 @@
|
||||
use crate::{ctrl, key, shift};
|
||||
use helix_view::compositor::{
|
||||
use crate::compositor::{
|
||||
Callback, Component, Compositor, Context, Event, EventResult, RenderContext,
|
||||
};
|
||||
use tui::widgets::Table;
|
||||
@ -9,7 +9,7 @@
|
||||
use fuzzy_matcher::skim::SkimMatcherV2 as Matcher;
|
||||
use fuzzy_matcher::FuzzyMatcher;
|
||||
|
||||
use helix_view::{graphics::Rect, Editor};
|
||||
use crate::{graphics::Rect, Editor};
|
||||
use tui::layout::Constraint;
|
||||
|
||||
pub trait Item {
|
@ -19,9 +19,9 @@
|
||||
pub use spinner::{ProgressSpinners, Spinner};
|
||||
pub use text::Text;
|
||||
|
||||
use crate::{Document, Editor, View};
|
||||
use helix_core::regex::Regex;
|
||||
use helix_core::regex::RegexBuilder;
|
||||
use helix_view::{Document, Editor, View};
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
@ -30,7 +30,7 @@ pub fn prompt(
|
||||
prompt: std::borrow::Cow<'static, str>,
|
||||
history_register: Option<char>,
|
||||
completion_fn: impl FnMut(&Editor, &str) -> Vec<prompt::Completion> + 'static,
|
||||
callback_fn: impl FnMut(&mut helix_view::compositor::Context, &str, PromptEvent) + 'static,
|
||||
callback_fn: impl FnMut(&mut crate::compositor::Context, &str, PromptEvent) + 'static,
|
||||
) {
|
||||
let mut prompt = Prompt::new(prompt, history_register, completion_fn, callback_fn);
|
||||
// Calculate initial completion
|
||||
@ -55,7 +55,7 @@ pub fn regex_prompt(
|
||||
prompt,
|
||||
history_register,
|
||||
completion_fn,
|
||||
move |cx: &mut helix_view::compositor::Context, input: &str, event: PromptEvent| {
|
||||
move |cx: &mut crate::compositor::Context, input: &str, event: PromptEvent| {
|
||||
match event {
|
||||
PromptEvent::Abort => {
|
||||
let (view, doc) = current!(cx.editor);
|
||||
@ -111,7 +111,7 @@ pub fn regex_prompt(
|
||||
cx.push_layer(Box::new(prompt));
|
||||
}
|
||||
|
||||
pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> FilePicker<PathBuf> {
|
||||
pub fn file_picker(root: PathBuf, config: &crate::editor::Config) -> FilePicker<PathBuf> {
|
||||
use ignore::{types::TypesBuilder, WalkBuilder};
|
||||
use std::time::Instant;
|
||||
|
||||
@ -188,12 +188,12 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> FilePi
|
||||
}
|
||||
|
||||
pub mod completers {
|
||||
use crate::document::SCRATCH_BUFFER_NAME;
|
||||
use crate::theme;
|
||||
use crate::ui::prompt::Completion;
|
||||
use crate::{editor::Config, Editor};
|
||||
use fuzzy_matcher::skim::SkimMatcherV2 as Matcher;
|
||||
use fuzzy_matcher::FuzzyMatcher;
|
||||
use helix_view::document::SCRATCH_BUFFER_NAME;
|
||||
use helix_view::theme;
|
||||
use helix_view::{editor::Config, Editor};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::borrow::Cow;
|
||||
use std::cmp::Reverse;
|
@ -1,10 +1,10 @@
|
||||
use helix_core::Position;
|
||||
use helix_view::{
|
||||
use crate::{
|
||||
graphics::{CursorKind, Rect},
|
||||
Editor,
|
||||
};
|
||||
|
||||
use helix_view::compositor::{Component, Context, Event, EventResult, RenderContext};
|
||||
use crate::compositor::{Component, Context, Event, EventResult, RenderContext};
|
||||
|
||||
/// Contains a component placed in the center of the parent component
|
||||
pub struct Overlay<T> {
|
@ -2,7 +2,7 @@
|
||||
ctrl, key, shift,
|
||||
ui::{self, EditorView},
|
||||
};
|
||||
use helix_view::compositor::{Component, Compositor, Context, Event, EventResult, RenderContext};
|
||||
use crate::compositor::{Component, Compositor, Context, Event, EventResult, RenderContext};
|
||||
use tui::widgets::{Block, BorderType, Borders};
|
||||
|
||||
use fuzzy_matcher::skim::SkimMatcherV2 as Matcher;
|
||||
@ -20,7 +20,7 @@
|
||||
|
||||
use crate::ui::{Prompt, PromptEvent};
|
||||
use helix_core::{movement::Direction, Position};
|
||||
use helix_view::{
|
||||
use crate::{
|
||||
editor::Action,
|
||||
graphics::{Color, CursorKind, Margin, Modifier, Rect, Style},
|
||||
Document, Editor,
|
@ -1,8 +1,8 @@
|
||||
use crate::{ctrl, key};
|
||||
use helix_view::compositor::{Callback, Component, Context, Event, EventResult, RenderContext};
|
||||
use crate::compositor::{Callback, Component, Context, Event, EventResult, RenderContext};
|
||||
|
||||
use helix_core::Position;
|
||||
use helix_view::{
|
||||
use crate::{
|
||||
graphics::{Margin, Rect},
|
||||
Editor,
|
||||
};
|
@ -1,17 +1,17 @@
|
||||
use helix_view::compositor::{Component, Compositor, Context, Event, EventResult, RenderContext};
|
||||
use crate::compositor::{Component, Compositor, Context, Event, EventResult, RenderContext};
|
||||
use crate::input::KeyEvent;
|
||||
use crate::keyboard::KeyCode;
|
||||
use crate::{alt, ctrl, key, shift, ui};
|
||||
use helix_view::input::KeyEvent;
|
||||
use helix_view::keyboard::KeyCode;
|
||||
use std::{borrow::Cow, ops::RangeFrom};
|
||||
use tui::widgets::{Block, Borders, Widget};
|
||||
|
||||
use helix_core::{
|
||||
unicode::segmentation::GraphemeCursor, unicode::width::UnicodeWidthStr, Position,
|
||||
};
|
||||
use helix_view::{
|
||||
use crate::{
|
||||
graphics::{CursorKind, Margin, Rect},
|
||||
Editor,
|
||||
};
|
||||
use helix_core::{
|
||||
unicode::segmentation::GraphemeCursor, unicode::width::UnicodeWidthStr, Position,
|
||||
};
|
||||
|
||||
pub type Completion = (RangeFrom<usize>, Cow<'static, str>);
|
||||
|
@ -1,6 +1,5 @@
|
||||
use helix_view::compositor::{Component, RenderContext};
|
||||
|
||||
use helix_view::graphics::Rect;
|
||||
use crate::compositor::{Component, RenderContext};
|
||||
use crate::graphics::Rect;
|
||||
|
||||
pub struct Text {
|
||||
pub(crate) contents: tui::text::Text<'static>,
|
Loading…
Reference in New Issue
Block a user