add code to dump selection location into register

pull/10905/head
Sam Vente 6 months ago
parent 1b6d61767d
commit 148f1c7c68
No known key found for this signature in database

@ -18,6 +18,7 @@ integration = []
[dependencies] [dependencies]
helix-stdx = { path = "../helix-stdx" } helix-stdx = { path = "../helix-stdx" }
helix-loader = { path = "../helix-loader" } helix-loader = { path = "../helix-loader" }
helix-parsec = { path = "../helix-parsec" }
ropey = { version = "1.6.1", default-features = false, features = ["simd"] } ropey = { version = "1.6.1", default-features = false, features = ["simd"] }
smallvec = "1.13" smallvec = "1.13"

@ -0,0 +1,8 @@
use std::num::NonZeroUsize;
use crate::Selection;
pub struct Mark {
doc_id: NonZeroUsize,
selection: Selection,
}

@ -11,6 +11,7 @@ use crate::{
movement::Direction, movement::Direction,
Assoc, ChangeSet, RopeGraphemes, RopeSlice, Assoc, ChangeSet, RopeGraphemes, RopeSlice,
}; };
use helix_parsec::{seq, take_until, Parser};
use helix_stdx::rope::{self, RopeSliceExt}; use helix_stdx::rope::{self, RopeSliceExt};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use std::{borrow::Cow, iter, slice}; use std::{borrow::Cow, iter, slice};
@ -389,6 +390,32 @@ impl Range {
pub fn into_byte_range(&self, text: RopeSlice) -> (usize, usize) { pub fn into_byte_range(&self, text: RopeSlice) -> (usize, usize) {
(text.char_to_byte(self.from()), text.char_to_byte(self.to())) (text.char_to_byte(self.from()), text.char_to_byte(self.to()))
} }
pub fn to_string(self) -> String {
format!("({},{})", self.anchor, self.head)
}
}
impl TryFrom<&str> for Range {
type Error = String;
fn try_from(value: &str) -> Result<Self, Self::Error> {
let parser = seq!(
"(",
take_until(|c| c == ','),
",",
take_until(|c| c == ')'),
")"
);
match parser.parse(value) {
Ok((_tail, (_, anchor, _, head, _))) => Ok(Self {
anchor: anchor.parse::<usize>().map_err(|e| e.to_string())?,
head: head.parse::<usize>().map_err(|e| e.to_string())?,
old_visual_position: None,
}),
Err(e) => Err(e.to_string()),
}
}
} }
impl From<(usize, usize)> for Range { impl From<(usize, usize)> for Range {
@ -888,6 +915,54 @@ mod test {
use super::*; use super::*;
use crate::Rope; use crate::Rope;
#[test]
fn parse_range() -> Result<(), String> {
// sometimes we want Ok, someteimes we want Err, but we never want a panic
assert_eq!(
Range::try_from("(0,28)"),
Ok(Range {
anchor: 0,
head: 28,
old_visual_position: None
})
);
assert_eq!(
Range::try_from("(3456789,123456789)"),
Ok(Range {
anchor: 3456789,
head: 123456789,
old_visual_position: None
})
);
assert_eq!(Range::try_from("(,)"), Err("(,)".to_string()));
assert_eq!(
Range::try_from("(asdf,asdf)"),
Err("invalid digit found in string".to_string())
);
assert_eq!(Range::try_from("()"), Err("()".to_string()));
assert_eq!(
Range::try_from("(-4,ALSK)"),
Err("invalid digit found in string".to_string())
);
assert_eq!(
Range::try_from("(⦡⓼␀⍆ⴉ├⺶⍄⾨,⦡⓼␀⍆ⴉ├⺶⍄⾨)"),
Err("invalid digit found in string".to_string())
);
Ok(())
}
#[test]
fn display_range() {
assert_eq!(
Range {
anchor: 72,
head: 28,
old_visual_position: None,
}
.to_string(),
"(72,28)".to_string(),
);
}
#[test] #[test]
#[should_panic] #[should_panic]
fn test_new_empty() { fn test_new_empty() {

@ -17,7 +17,7 @@ pub use typed::*;
use helix_core::{ use helix_core::{
char_idx_at_visual_offset, char_idx_at_visual_offset,
chars::char_is_word, chars::char_is_word,
comment, comment, coords_at_pos,
doc_formatter::TextFormat, doc_formatter::TextFormat,
encoding, find_workspace, encoding, find_workspace,
graphemes::{self, next_grapheme_boundary, RevRopeGraphemes}, graphemes::{self, next_grapheme_boundary, RevRopeGraphemes},
@ -567,14 +567,7 @@ impl MappableCommand {
command_palette, "Open command palette", command_palette, "Open command palette",
goto_word, "Jump to a two-character label", goto_word, "Jump to a two-character label",
extend_to_word, "Extend to a two-character label", extend_to_word, "Extend to a two-character label",
add_mark_file, "Bookmark a file", register_mark, "Register a bookmark",
add_mark_line, "Bookmark a perticular line in a file",
remove_mark_file, "Remove current file Bookmark if it exists",
remove_mark_line, "Remove current line Bookmark if it exists",
goto_nth_mark, "Move cursor to the Nth bookmark",
goto_next_mark, "Move cursor to the next bookmark",
goto_prev_mark, "Move cursor to the prev bookmark",
mark_picker, "Open mark picker",
); );
} }
@ -6129,30 +6122,29 @@ fn goto_word(cx: &mut Context) {
fn extend_to_word(cx: &mut Context) { fn extend_to_word(cx: &mut Context) {
jump_to_word(cx, Movement::Extend) jump_to_word(cx, Movement::Extend)
} }
fn add_mark_file(cx: &mut Context) {
todo!();
}
fn add_mark_line(cx: &mut Context) {
todo!();
}
fn remove_mark_file(cx: &mut Context) {
todo!();
}
fn remove_mark_line(cx: &mut Context) {
todo!();
}
fn goto_nth_mark(cx: &mut Context) {
todo!();
}
fn goto_next_mark(cx: &mut Context) {
todo!();
}
fn goto_prev_mark(cx: &mut Context) {
todo!();
}
fn mark_picker(cx: &mut Context) { fn register_mark(cx: &mut Context) {
todo!(); let register_name = cx.register.unwrap_or('^').clone();
let (view, doc) = current!(cx.editor);
let primary_selection = doc.selection(view.id).primary().clone();
let range_start_pos = match primary_selection.direction() {
Direction::Forward => coords_at_pos(doc.text().slice(0..), primary_selection.anchor),
Direction::Backward => coords_at_pos(doc.text().slice(0..), primary_selection.head),
};
cx.editor
.registers
.write(
register_name,
vec![format!("{}:{}", doc.id(), primary_selection.to_string())],
)
.unwrap();
cx.editor.set_status(format!(
"Saved location line {}, row {} to [{}]",
range_start_pos.row + 1,
range_start_pos.col + 1,
register_name
));
} }
fn jump_to_label(cx: &mut Context, labels: Vec<Range>, behaviour: Movement) { fn jump_to_label(cx: &mut Context, labels: Vec<Range>, behaviour: Movement) {

@ -332,6 +332,9 @@ pub fn default() -> HashMap<Mode, KeyTrie> {
"C-a" => increment, "C-a" => increment,
"C-x" => decrement, "C-x" => decrement,
// just for debugging I'll find something better later
"1" => register_mark,
}); });
let mut select = normal.clone(); let mut select = normal.clone();
select.merge_nodes(keymap!({ "Select mode" select.merge_nodes(keymap!({ "Select mode"

@ -24,54 +24,8 @@ use std::{
}; };
const JUMP_LIST_CAPACITY: usize = 30; const JUMP_LIST_CAPACITY: usize = 30;
const MARK_LIST_CAPACITY: usize = 30;
type Jump = (DocumentId, Selection); type Jump = (DocumentId, Selection);
type Mark = (DocumentId, Selection);
#[derive(Debug, Clone)]
pub struct MarkList {
marks: VecDeque<Mark>,
current: usize,
}
impl MarkList {
pub fn new(initial: Jump) -> Self {
todo!();
}
pub fn push(&mut self, jump: Jump) {
todo!()
}
pub fn forward(&mut self, count: usize) -> Option<&Jump> {
todo!();
}
// Taking view and doc to prevent unnecessary cloning when jump is not required.
pub fn backward(&mut self, view_id: ViewId, doc: &mut Document, count: usize) -> Option<&Jump> {
todo!();
}
pub fn nth(&mut self, view_id: ViewId, doc: &mut Document, count: usize) -> Option<&Jump> {
todo!();
}
pub fn remove(&mut self, doc_id: &DocumentId) {
todo!();
}
pub fn iter(&self) -> impl DoubleEndedIterator<Item = &Jump> {
self.marks.iter()
}
/// Applies a [`Transaction`] of changes to the jumplist.
/// This is necessary to ensure that changes to documents do not leave jump-list
/// selections pointing to parts of the text which no longer exist.
fn apply(&mut self, transaction: &Transaction, doc: &Document) {
todo!();
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct JumpList { pub struct JumpList {
@ -177,7 +131,6 @@ pub struct View {
pub area: Rect, pub area: Rect,
pub doc: DocumentId, pub doc: DocumentId,
pub jumps: JumpList, pub jumps: JumpList,
pub marks: MarkList,
// documents accessed from this view from the oldest one to last viewed one // documents accessed from this view from the oldest one to last viewed one
pub docs_access_history: Vec<DocumentId>, pub docs_access_history: Vec<DocumentId>,
/// the last modified files before the current one /// the last modified files before the current one
@ -221,7 +174,6 @@ impl View {
doc, doc,
area: Rect::default(), // will get calculated upon inserting into tree area: Rect::default(), // will get calculated upon inserting into tree
jumps: JumpList::new((doc, Selection::point(0))), // TODO: use actual sel jumps: JumpList::new((doc, Selection::point(0))), // TODO: use actual sel
marks: MarkList::new((doc, Selection::point(0))), // TODO: use actual sel
docs_access_history: Vec::new(), docs_access_history: Vec::new(),
last_modified_docs: [None, None], last_modified_docs: [None, None],
object_selections: Vec::new(), object_selections: Vec::new(),

Loading…
Cancel
Save