Extend selection commands.
This commit is contained in:
parent
fbe313779e
commit
3020077da8
13 changed files with 182 additions and 45 deletions
46
Cargo.lock
generated
46
Cargo.lock
generated
|
@ -52,9 +52,9 @@ checksum = "e1ba68f4276a778591e36a0c348a269888f3a177c8d2054969389e3b59611ff5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-barrier"
|
name = "async-barrier"
|
||||||
version = "1.0.1"
|
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 = "c06293698675eb72e1155867e5982f199d6b6c230dca35bc5ffd9852f470c22a"
|
checksum = "04b50fe84d0aea412a4e751cb01b9e26e2be533b2708607c2a2a739b192ee45a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-mutex",
|
"async-mutex",
|
||||||
"event-listener",
|
"event-listener",
|
||||||
|
@ -97,9 +97,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-io"
|
name = "async-io"
|
||||||
version = "1.1.2"
|
version = "1.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "64c629684e697f58c0e99e5e2d84a840e3b336afbcfdbac7b44c3b1e222c2fd8"
|
checksum = "a9951f92a2b4f7793f8fc06a80bdb89b62c618c993497d4606474fb8c34941b5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"concurrent-queue",
|
"concurrent-queue",
|
||||||
"fastrand",
|
"fastrand",
|
||||||
|
@ -115,9 +115,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-lock"
|
name = "async-lock"
|
||||||
version = "2.1.3"
|
version = "2.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ab3ad7fb4345397e57c19566844b0eba274b92e5d2d2791bb0664cc441697b95"
|
checksum = "76000290eb3c67dfe4e2bdf6b6155847f8e16fc844377a7bd0b5e97622656362"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-barrier",
|
"async-barrier",
|
||||||
"async-mutex",
|
"async-mutex",
|
||||||
|
@ -127,9 +127,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-mutex"
|
name = "async-mutex"
|
||||||
version = "1.3.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "66941c2577c4fa351e4ce5fdde8f86c69b88d623f3b955be1bc7362a23434632"
|
checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"event-listener",
|
"event-listener",
|
||||||
]
|
]
|
||||||
|
@ -164,9 +164,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-rwlock"
|
name = "async-rwlock"
|
||||||
version = "1.2.1"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "806b1cc0828c2b1611ccbdd743fc0cc7af09009e62c95a0501c1e5da7b142a22"
|
checksum = "261803dcc39ba9e72760ba6e16d0199b1eef9fc44e81bffabbebb9f5aea3906c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-mutex",
|
"async-mutex",
|
||||||
"event-listener",
|
"event-listener",
|
||||||
|
@ -174,18 +174,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-semaphore"
|
name = "async-semaphore"
|
||||||
version = "1.1.0"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "66d2be5973230861689460806b8db059bbd8bcb507cabaa71646ae89f5b2f2ee"
|
checksum = "538c756e85eb6ffdefaec153804afb6da84b033e2e5ec3e9d459c34b4bf4d3f6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"event-listener",
|
"event-listener",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-task"
|
name = "async-task"
|
||||||
version = "4.0.1"
|
version = "4.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6725e96011a83fae25074a8734932e8d67763522839be7473dcfe8a0d6a378b1"
|
checksum = "8ab27c1aa62945039e44edaeee1dc23c74cc0c303dd5fe0fb462a184f1c3a518"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atomic-waker"
|
name = "atomic-waker"
|
||||||
|
@ -306,9 +306,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "event-listener"
|
name = "event-listener"
|
||||||
version = "2.4.0"
|
version = "2.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e1cd41440ae7e4734bbd42302f63eaba892afc93a3912dad84006247f0dedb0e"
|
checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
|
@ -340,9 +340,9 @@ checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-lite"
|
name = "futures-lite"
|
||||||
version = "1.7.0"
|
version = "1.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b77e08e656f472d8ea84c472fa8b0a7a917883048e1cf2d4e34a323cd0aaf63"
|
checksum = "0db18c5f58083b54b0c416638ea73066722c2815c1e54dd8ba85ee3def593c3a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
@ -387,6 +387,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"helix-syntax",
|
"helix-syntax",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"regex",
|
||||||
"ropey",
|
"ropey",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"tendril",
|
"tendril",
|
||||||
|
@ -425,6 +426,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
"helix-core",
|
"helix-core",
|
||||||
|
"once_cell",
|
||||||
"tui",
|
"tui",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -774,9 +776,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tree-sitter"
|
name = "tree-sitter"
|
||||||
version = "0.16.1"
|
version = "0.17.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1df33680edb07e4fb76edcbdd9c7b849b96709fb878afcf0ada678d6bda167af"
|
checksum = "70ee7370fec3aecde3862a7d64c571048f70a7298daef1815e8fc68b9de54b5c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"regex",
|
"regex",
|
||||||
|
@ -784,9 +786,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tui"
|
name = "tui"
|
||||||
version = "0.10.0"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a977b0bb2e2033a6fef950f218f13622c3c34e59754b704ce3492dedab1dfe95"
|
checksum = "36626dee5ede9fd34015e9fb4fd7eedf3f3d05bdf1436aaef15b7d0a24233778"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cassowary",
|
"cassowary",
|
||||||
|
|
|
@ -9,12 +9,13 @@ edition = "2018"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
helix-syntax = { path = "../helix-syntax" }
|
helix-syntax = { path = "../helix-syntax" }
|
||||||
|
|
||||||
ropey = "1.2.0"
|
ropey = "1.2"
|
||||||
anyhow = "1.0.31"
|
anyhow = "1"
|
||||||
smallvec = "1.4.0"
|
smallvec = "1.4"
|
||||||
tendril = { git = "https://github.com/servo/tendril" }
|
tendril = { git = "https://github.com/servo/tendril" }
|
||||||
unicode-segmentation = "1.6.0"
|
unicode-segmentation = "1.6"
|
||||||
unicode-width = "0.1.7"
|
unicode-width = "0.1"
|
||||||
# slab = "0.4.2"
|
# slab = "0.4.2"
|
||||||
tree-sitter = "0.16.1"
|
tree-sitter = "0.17"
|
||||||
once_cell = "1.4.1"
|
once_cell = "1.4"
|
||||||
|
regex = "1"
|
||||||
|
|
|
@ -8,6 +8,7 @@ pub mod syntax;
|
||||||
mod transaction;
|
mod transaction;
|
||||||
|
|
||||||
pub use ropey::{Rope, RopeSlice};
|
pub use ropey::{Rope, RopeSlice};
|
||||||
|
|
||||||
pub use tendril::StrTendril as Tendril;
|
pub use tendril::StrTendril as Tendril;
|
||||||
|
|
||||||
pub use position::Position;
|
pub use position::Position;
|
||||||
|
|
|
@ -60,6 +60,18 @@ impl Range {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn contains(&self, pos: usize) -> bool {
|
||||||
|
if self.is_empty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.anchor < self.head {
|
||||||
|
self.anchor <= pos && pos < self.head
|
||||||
|
} else {
|
||||||
|
self.head < pos && pos <= self.anchor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Map a range through a set of changes. Returns a new range representing the same position
|
/// Map a range through a set of changes. Returns a new range representing the same position
|
||||||
/// after the changes are applied.
|
/// after the changes are applied.
|
||||||
pub fn map(self, changes: &ChangeSet) -> Self {
|
pub fn map(self, changes: &ChangeSet) -> Self {
|
||||||
|
@ -283,4 +295,21 @@ mod test {
|
||||||
|
|
||||||
assert_eq!(res, "8/10,10/12");
|
assert_eq!(res, "8/10,10/12");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_contains() {
|
||||||
|
let range = Range::new(10, 12);
|
||||||
|
|
||||||
|
assert_eq!(range.contains(9), false);
|
||||||
|
assert_eq!(range.contains(10), true);
|
||||||
|
assert_eq!(range.contains(11), true);
|
||||||
|
assert_eq!(range.contains(12), false);
|
||||||
|
assert_eq!(range.contains(13), false);
|
||||||
|
|
||||||
|
let range = Range::new(9, 6);
|
||||||
|
assert_eq!(range.contains(9), true);
|
||||||
|
assert_eq!(range.contains(7), true);
|
||||||
|
assert_eq!(range.contains(6), false);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ impl LanguageConfiguration {
|
||||||
if highlights_query.is_empty() {
|
if highlights_query.is_empty() {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
} else {
|
} else {
|
||||||
let language = get_language(&self.language_id);
|
let language = get_language(self.language_id);
|
||||||
let mut config = HighlightConfiguration::new(
|
let mut config = HighlightConfiguration::new(
|
||||||
language,
|
language,
|
||||||
&highlights_query,
|
&highlights_query,
|
||||||
|
@ -1456,7 +1456,7 @@ fn test_parser() {
|
||||||
.map(String::from)
|
.map(String::from)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let language = get_language(&LANG::Rust);
|
let language = get_language(LANG::Rust);
|
||||||
let mut config = HighlightConfiguration::new(
|
let mut config = HighlightConfiguration::new(
|
||||||
language,
|
language,
|
||||||
&std::fs::read_to_string(
|
&std::fs::read_to_string(
|
||||||
|
@ -1478,7 +1478,7 @@ fn test_parser() {
|
||||||
fn main() {}
|
fn main() {}
|
||||||
",
|
",
|
||||||
);
|
);
|
||||||
let syntax = Syntax::new(LANG::Rust, &source, config);
|
let syntax = Syntax::new(&source, Arc::new(config));
|
||||||
let tree = syntax.root_layer.tree.unwrap();
|
let tree = syntax.root_layer.tree.unwrap();
|
||||||
let root = tree.root_node();
|
let root = tree.root_node();
|
||||||
assert_eq!(root.kind(), "source_file");
|
assert_eq!(root.kind(), "source_file");
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::{Range, Rope, Selection, State, Tendril};
|
use crate::{Range, Rope, Selection, State, Tendril};
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
/// (from, to, replacement)
|
/// (from, to, replacement)
|
||||||
pub type Change = (usize, usize, Option<Tendril>);
|
pub type Change = (usize, usize, Option<Tendril>);
|
||||||
|
@ -112,7 +113,7 @@ impl ChangeSet {
|
||||||
let (pos, _) = s.char_indices().nth(len - j).unwrap();
|
let (pos, _) = s.char_indices().nth(len - j).unwrap();
|
||||||
// calculate the difference
|
// calculate the difference
|
||||||
let to_drop = s.len() - pos;
|
let to_drop = s.len() - pos;
|
||||||
s.pop_back(to_drop as u32);
|
s.pop_back(u32::try_from(to_drop).unwrap());
|
||||||
head_a = Some(Insert(s));
|
head_a = Some(Insert(s));
|
||||||
head_b = changes_b.next();
|
head_b = changes_b.next();
|
||||||
}
|
}
|
||||||
|
@ -136,7 +137,7 @@ impl ChangeSet {
|
||||||
let (pos, _) = s.char_indices().nth(j).unwrap();
|
let (pos, _) = s.char_indices().nth(j).unwrap();
|
||||||
// calculate the difference
|
// calculate the difference
|
||||||
let to_drop = s.len() - pos;
|
let to_drop = s.len() - pos;
|
||||||
s.pop_back(to_drop as u32);
|
s.pop_back(u32::try_from(to_drop).unwrap());
|
||||||
head_a = Some(Insert(s));
|
head_a = Some(Insert(s));
|
||||||
head_b = changes_b.next();
|
head_b = changes_b.next();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ edition = "2018"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tree-sitter = "0.16"
|
tree-sitter = "0.17"
|
||||||
enum-iterator = "0.6"
|
enum-iterator = "0.6"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
|
|
@ -13,7 +13,7 @@ macro_rules! mk_extern {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! mk_enum {
|
macro_rules! mk_enum {
|
||||||
( $( $camel:ident ),* ) => {
|
( $( $camel:ident ),* ) => {
|
||||||
#[derive(Clone, Debug, IntoEnumIterator, PartialEq)]
|
#[derive(Clone, Copy, Debug, IntoEnumIterator, PartialEq)]
|
||||||
pub enum LANG {
|
pub enum LANG {
|
||||||
$(
|
$(
|
||||||
$camel,
|
$camel,
|
||||||
|
@ -25,7 +25,8 @@ macro_rules! mk_enum {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! mk_get_language {
|
macro_rules! mk_get_language {
|
||||||
( $( ($camel:ident, $name:ident) ),* ) => {
|
( $( ($camel:ident, $name:ident) ),* ) => {
|
||||||
pub fn get_language(lang: &LANG) -> Language {
|
#[must_use]
|
||||||
|
pub fn get_language(lang: LANG) -> Language {
|
||||||
unsafe {
|
unsafe {
|
||||||
match lang {
|
match lang {
|
||||||
$(
|
$(
|
||||||
|
@ -40,7 +41,8 @@ macro_rules! mk_get_language {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! mk_get_language_name {
|
macro_rules! mk_get_language_name {
|
||||||
( $( $camel:ident ),* ) => {
|
( $( $camel:ident ),* ) => {
|
||||||
pub fn get_language_name(lang: &LANG) -> &'static str {
|
#[must_use]
|
||||||
|
pub const fn get_language_name(lang: LANG) -> &'static str {
|
||||||
match lang {
|
match lang {
|
||||||
$(
|
$(
|
||||||
LANG::$camel => stringify!($camel),
|
LANG::$camel => stringify!($camel),
|
||||||
|
|
|
@ -15,9 +15,9 @@ helix-core = { path = "../helix-core" }
|
||||||
helix-view = { path = "../helix-view", features = ["term"]}
|
helix-view = { path = "../helix-view", features = ["term"]}
|
||||||
|
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
argh = "0.1.3"
|
argh = "0.1"
|
||||||
|
|
||||||
smol = "1"
|
smol = "1"
|
||||||
num_cpus = "1.13.0"
|
num_cpus = "1.13"
|
||||||
tui = { version = "0.10.0", default-features = false, features = ["crossterm"] }
|
tui = { version = "0.11", default-features = false, features = ["crossterm"] }
|
||||||
crossterm = { version = "0.17", features = ["event-stream"] }
|
crossterm = { version = "0.17", features = ["event-stream"] }
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use crate::Args;
|
use crate::Args;
|
||||||
use helix_core::{state::coords_at_pos, state::Mode, syntax::HighlightEvent, State};
|
use helix_core::{state::coords_at_pos, state::Mode, syntax::HighlightEvent, Range, State};
|
||||||
use helix_view::{commands, keymap, View};
|
use helix_view::{commands, keymap, View};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
io::{self, stdout, Write},
|
io::{self, stdout, Write},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
|
@ -120,6 +121,16 @@ impl Editor {
|
||||||
let mut visual_x = 0;
|
let mut visual_x = 0;
|
||||||
let mut line = 0u16;
|
let mut line = 0u16;
|
||||||
|
|
||||||
|
let visible_selections: Vec<Range> = view
|
||||||
|
.state
|
||||||
|
.selection()
|
||||||
|
.ranges()
|
||||||
|
.iter()
|
||||||
|
// TODO: limit selection to one in viewport
|
||||||
|
.filter(|range| !range.is_empty()) // && range.overlaps(&Range::new(start, end + 1))
|
||||||
|
.copied()
|
||||||
|
.collect();
|
||||||
|
|
||||||
'outer: for event in highlights {
|
'outer: for event in highlights {
|
||||||
match event.unwrap() {
|
match event.unwrap() {
|
||||||
HighlightEvent::HighlightStart(span) => {
|
HighlightEvent::HighlightStart(span) => {
|
||||||
|
@ -149,6 +160,8 @@ impl Editor {
|
||||||
// way if only the selection/cursor changes we can copy from cache
|
// way if only the selection/cursor changes we can copy from cache
|
||||||
// and paint the new cursor.
|
// and paint the new cursor.
|
||||||
|
|
||||||
|
let mut char_index = start;
|
||||||
|
|
||||||
// iterate over range char by char
|
// iterate over range char by char
|
||||||
for grapheme in RopeGraphemes::new(&text) {
|
for grapheme in RopeGraphemes::new(&text) {
|
||||||
// TODO: track current char_index
|
// TODO: track current char_index
|
||||||
|
@ -164,8 +177,21 @@ impl Editor {
|
||||||
} else {
|
} else {
|
||||||
// Cow will prevent allocations if span contained in a single slice
|
// Cow will prevent allocations if span contained in a single slice
|
||||||
// which should really be the majority case
|
// which should really be the majority case
|
||||||
let grapheme = std::borrow::Cow::from(grapheme);
|
let grapheme = Cow::from(grapheme);
|
||||||
let width = grapheme_width(&grapheme) as u16;
|
let width = grapheme_width(&grapheme) as u16;
|
||||||
|
|
||||||
|
let style = if visible_selections
|
||||||
|
.iter()
|
||||||
|
.any(|range| range.contains(char_index))
|
||||||
|
{
|
||||||
|
// cedar
|
||||||
|
style.clone().bg(Color::Rgb(128, 47, 0))
|
||||||
|
} else {
|
||||||
|
style
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: paint cursor heads except primary
|
||||||
|
|
||||||
self.surface.set_string(
|
self.surface.set_string(
|
||||||
offset + visual_x,
|
offset + visual_x,
|
||||||
line,
|
line,
|
||||||
|
@ -176,6 +202,8 @@ impl Editor {
|
||||||
visual_x += width;
|
visual_x += width;
|
||||||
}
|
}
|
||||||
// if grapheme == "\t"
|
// if grapheme == "\t"
|
||||||
|
|
||||||
|
char_index += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,10 @@ edition = "2018"
|
||||||
term = ["tui", "crossterm"]
|
term = ["tui", "crossterm"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.32"
|
anyhow = "1"
|
||||||
helix-core = { path = "../helix-core" }
|
helix-core = { path = "../helix-core" }
|
||||||
|
|
||||||
# Conversion traits
|
# Conversion traits
|
||||||
tui = { version = "0.10.0", default-features = false, features = ["crossterm"], optional = true}
|
tui = { version = "0.11", default-features = false, features = ["crossterm"], optional = true}
|
||||||
crossterm = { version = "0.17", features = ["event-stream"], optional = true}
|
crossterm = { version = "0.17", features = ["event-stream"], optional = true}
|
||||||
|
once_cell = "1.4"
|
||||||
|
|
|
@ -115,6 +115,46 @@ pub fn move_next_word_end(view: &mut View, count: usize) {
|
||||||
|
|
||||||
// avoid select by default by having a visual mode switch that makes movements into selects
|
// avoid select by default by having a visual mode switch that makes movements into selects
|
||||||
|
|
||||||
|
pub fn extend_char_left(view: &mut View, count: usize) {
|
||||||
|
// TODO: use a transaction
|
||||||
|
let selection = view
|
||||||
|
.state
|
||||||
|
.extend_selection(Direction::Backward, Granularity::Character, count);
|
||||||
|
view.state.selection = selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extend_char_right(view: &mut View, count: usize) {
|
||||||
|
// TODO: use a transaction
|
||||||
|
view.state.selection =
|
||||||
|
view.state
|
||||||
|
.extend_selection(Direction::Forward, Granularity::Character, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extend_line_up(view: &mut View, count: usize) {
|
||||||
|
// TODO: use a transaction
|
||||||
|
view.state.selection =
|
||||||
|
view.state
|
||||||
|
.extend_selection(Direction::Backward, Granularity::Line, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extend_line_down(view: &mut View, count: usize) {
|
||||||
|
// TODO: use a transaction
|
||||||
|
view.state.selection =
|
||||||
|
view.state
|
||||||
|
.extend_selection(Direction::Forward, Granularity::Line, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete_selection(view: &mut View, _count: usize) {
|
||||||
|
let transaction =
|
||||||
|
Transaction::change_by_selection(&view.state, |range| (range.from(), range.to(), None));
|
||||||
|
transaction.apply(&mut view.state);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn change_selection(view: &mut View, count: usize) {
|
||||||
|
delete_selection(view, count);
|
||||||
|
insert_mode(view, count);
|
||||||
|
}
|
||||||
|
|
||||||
// insert mode:
|
// insert mode:
|
||||||
// first we calculate the correct cursors/selections
|
// first we calculate the correct cursors/selections
|
||||||
// then we just append at each cursor
|
// then we just append at each cursor
|
||||||
|
|
|
@ -7,7 +7,9 @@ use std::collections::HashMap;
|
||||||
// normal = {
|
// normal = {
|
||||||
// q = record_macro
|
// q = record_macro
|
||||||
// w = (next) word
|
// w = (next) word
|
||||||
|
// W = next WORD
|
||||||
// e = end of word
|
// e = end of word
|
||||||
|
// E = end of WORD
|
||||||
// r =
|
// r =
|
||||||
// t = 'till char
|
// t = 'till char
|
||||||
// y = yank
|
// y = yank
|
||||||
|
@ -55,6 +57,12 @@ use std::collections::HashMap;
|
||||||
// & = align cursor
|
// & = align cursor
|
||||||
// ? = extend to next given regex match (alt = to prev)
|
// ? = extend to next given regex match (alt = to prev)
|
||||||
//
|
//
|
||||||
|
// in kakoune these are alt-h alt-l / gh gl
|
||||||
|
// select from curs to begin end / move curs to begin end
|
||||||
|
// 0 = start of line
|
||||||
|
// ^ = start of line (first non blank char)
|
||||||
|
// $ = end of line
|
||||||
|
//
|
||||||
// z = save selections
|
// z = save selections
|
||||||
// Z = restore selections
|
// Z = restore selections
|
||||||
// x = select line
|
// x = select line
|
||||||
|
@ -110,6 +118,22 @@ pub fn default() -> Keymaps {
|
||||||
code: KeyCode::Char('l'),
|
code: KeyCode::Char('l'),
|
||||||
modifiers: Modifiers::NONE
|
modifiers: Modifiers::NONE
|
||||||
}] => commands::move_char_right as Command,
|
}] => commands::move_char_right as Command,
|
||||||
|
vec![Key {
|
||||||
|
code: KeyCode::Char('H'),
|
||||||
|
modifiers: Modifiers::SHIFT
|
||||||
|
}] => commands::extend_char_left as Command,
|
||||||
|
vec![Key {
|
||||||
|
code: KeyCode::Char('J'),
|
||||||
|
modifiers: Modifiers::SHIFT
|
||||||
|
}] => commands::extend_line_down as Command,
|
||||||
|
vec![Key {
|
||||||
|
code: KeyCode::Char('K'),
|
||||||
|
modifiers: Modifiers::SHIFT
|
||||||
|
}] => commands::extend_line_up as Command,
|
||||||
|
vec![Key {
|
||||||
|
code: KeyCode::Char('L'),
|
||||||
|
modifiers: Modifiers::SHIFT
|
||||||
|
}] => commands::extend_char_right as Command,
|
||||||
vec![Key {
|
vec![Key {
|
||||||
code: KeyCode::Char('w'),
|
code: KeyCode::Char('w'),
|
||||||
modifiers: Modifiers::NONE
|
modifiers: Modifiers::NONE
|
||||||
|
@ -142,6 +166,14 @@ pub fn default() -> Keymaps {
|
||||||
code: KeyCode::Char('o'),
|
code: KeyCode::Char('o'),
|
||||||
modifiers: Modifiers::NONE
|
modifiers: Modifiers::NONE
|
||||||
}] => commands::open_below as Command,
|
}] => commands::open_below as Command,
|
||||||
|
vec![Key {
|
||||||
|
code: KeyCode::Char('d'),
|
||||||
|
modifiers: Modifiers::NONE
|
||||||
|
}] => commands::delete_selection as Command,
|
||||||
|
vec![Key {
|
||||||
|
code: KeyCode::Char('c'),
|
||||||
|
modifiers: Modifiers::NONE
|
||||||
|
}] => commands::change_selection as Command,
|
||||||
vec![Key {
|
vec![Key {
|
||||||
code: KeyCode::Esc,
|
code: KeyCode::Esc,
|
||||||
modifiers: Modifiers::NONE
|
modifiers: Modifiers::NONE
|
||||||
|
|
Loading…
Add table
Reference in a new issue