Remove State from a few more signatures.
This commit is contained in:
parent
dbcc099f48
commit
59e6024186
@ -1,4 +1,6 @@
|
||||
use crate::{find_first_non_whitespace_char2, Change, RopeSlice, State, Tendril, Transaction};
|
||||
use crate::{
|
||||
find_first_non_whitespace_char2, Change, Rope, RopeSlice, Selection, Tendril, Transaction,
|
||||
};
|
||||
use core::ops::Range;
|
||||
use std::borrow::Cow;
|
||||
|
||||
@ -35,14 +37,14 @@ fn find_line_comment(
|
||||
(commented, skipped, min)
|
||||
}
|
||||
|
||||
pub fn toggle_line_comments(state: &State) -> Transaction {
|
||||
let text = state.doc.slice(..);
|
||||
pub fn toggle_line_comments(doc: &Rope, selection: &Selection) -> Transaction {
|
||||
let text = doc.slice(..);
|
||||
let mut changes: Vec<Change> = Vec::new();
|
||||
|
||||
let token = "//";
|
||||
let comment = Tendril::from(format!("{} ", token));
|
||||
|
||||
for selection in state.selection.ranges() {
|
||||
for selection in selection.ranges() {
|
||||
let start = text.char_to_line(selection.from());
|
||||
let end = text.char_to_line(selection.to());
|
||||
let lines = start..end + 1;
|
||||
@ -67,7 +69,7 @@ pub fn toggle_line_comments(state: &State) -> Transaction {
|
||||
}
|
||||
}
|
||||
}
|
||||
Transaction::change(&state.doc, changes.into_iter())
|
||||
Transaction::change(doc, changes.into_iter())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -76,7 +78,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_find_line_comment() {
|
||||
use crate::{Rope, Selection};
|
||||
use crate::State;
|
||||
|
||||
// four lines, two space indented, except for line 1 which is blank.
|
||||
let doc = Rope::from(" 1\n\n 2\n 3");
|
||||
@ -92,13 +94,13 @@ fn test_find_line_comment() {
|
||||
assert_eq!(res, (false, vec![1], 2));
|
||||
|
||||
// comment
|
||||
let transaction = toggle_line_comments(&state);
|
||||
let transaction = toggle_line_comments(&state.doc, &state.selection);
|
||||
transaction.apply(&mut state);
|
||||
|
||||
assert_eq!(state.doc, " // 1\n\n // 2\n // 3");
|
||||
|
||||
// uncomment
|
||||
let transaction = toggle_line_comments(&state);
|
||||
let transaction = toggle_line_comments(&state.doc, &state.selection);
|
||||
transaction.apply(&mut state);
|
||||
assert_eq!(state.doc, " 1\n\n 2\n 3");
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
find_first_non_whitespace_char,
|
||||
syntax::Syntax,
|
||||
tree_sitter::{Node, Tree},
|
||||
Rope, RopeSlice, State,
|
||||
Rope, RopeSlice,
|
||||
};
|
||||
|
||||
/// To determine indentation of a newly inserted line, figure out the indentation at the last col
|
||||
@ -162,12 +162,12 @@ fn calculate_indentation(node: Option<Node>, newline: bool) -> usize {
|
||||
increment as usize
|
||||
}
|
||||
|
||||
fn suggested_indent_for_line(syntax: Option<&Syntax>, state: &State, line_num: usize) -> usize {
|
||||
let line = state.doc.line(line_num);
|
||||
fn suggested_indent_for_line(syntax: Option<&Syntax>, text: RopeSlice, line_num: usize) -> usize {
|
||||
let line = text.line(line_num);
|
||||
let current = indent_level_for_line(line);
|
||||
|
||||
if let Some(start) = find_first_non_whitespace_char(state.doc.slice(..), line_num) {
|
||||
return suggested_indent_for_pos(syntax, state, start, false);
|
||||
if let Some(start) = find_first_non_whitespace_char(text, line_num) {
|
||||
return suggested_indent_for_pos(syntax, text, start, false);
|
||||
};
|
||||
|
||||
// if the line is blank, indent should be zero
|
||||
@ -179,12 +179,12 @@ fn suggested_indent_for_line(syntax: Option<&Syntax>, state: &State, line_num: u
|
||||
// - it should look up the wrapper node and count it too when we press o/O
|
||||
pub fn suggested_indent_for_pos(
|
||||
syntax: Option<&Syntax>,
|
||||
state: &State,
|
||||
text: RopeSlice,
|
||||
pos: usize,
|
||||
new_line: bool,
|
||||
) -> usize {
|
||||
if let Some(syntax) = syntax {
|
||||
let byte_start = state.doc.char_to_byte(pos);
|
||||
let byte_start = text.char_to_byte(pos);
|
||||
let node = get_highest_syntax_node_at_bytepos(syntax, byte_start);
|
||||
|
||||
// TODO: special case for comments
|
||||
@ -279,7 +279,7 @@ impl<A, D> MyTrait<A, D> for YourType
|
||||
1
|
||||
}}}
|
||||
|
||||
pub fn change<I>(state: &State, changes: I) -> Self
|
||||
pub fn change<I>(document: &Document, changes: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = Change> + ExactSizeIterator,
|
||||
{
|
||||
@ -288,20 +288,19 @@ pub fn change<I>(state: &State, changes: I) -> Self
|
||||
",
|
||||
);
|
||||
|
||||
let state = State::new(doc);
|
||||
// TODO: set_language
|
||||
let doc = Rope::from(doc);
|
||||
let language_config = crate::syntax::LOADER
|
||||
.language_config_for_scope("source.rust")
|
||||
.unwrap();
|
||||
let highlight_config = language_config.highlight_config(&[]).unwrap();
|
||||
let syntax = Syntax::new(&state.doc, highlight_config.clone());
|
||||
let text = state.doc.slice(..);
|
||||
let syntax = Syntax::new(&doc, highlight_config.clone());
|
||||
let text = doc.slice(..);
|
||||
|
||||
for i in 0..state.doc.len_lines() {
|
||||
for i in 0..doc.len_lines() {
|
||||
let line = text.line(i);
|
||||
let indent = indent_level_for_line(line);
|
||||
assert_eq!(
|
||||
suggested_indent_for_line(Some(&syntax), &state, i),
|
||||
suggested_indent_for_line(Some(&syntax), text, i),
|
||||
indent,
|
||||
"line {}: {}",
|
||||
i,
|
||||
|
@ -409,9 +409,9 @@ pub struct Transaction {
|
||||
|
||||
impl Transaction {
|
||||
/// Create a new, empty transaction.
|
||||
pub fn new(state: &mut State) -> Self {
|
||||
pub fn new(doc: &Rope) -> Self {
|
||||
Self {
|
||||
changes: ChangeSet::new(&state.doc),
|
||||
changes: ChangeSet::new(doc),
|
||||
selection: None,
|
||||
}
|
||||
}
|
||||
@ -490,16 +490,18 @@ pub fn change<I>(doc: &Rope, changes: I) -> Self
|
||||
}
|
||||
|
||||
/// Generate a transaction with a change per selection range.
|
||||
pub fn change_by_selection<F>(state: &State, f: F) -> Self
|
||||
pub fn change_by_selection<F>(doc: &Rope, selection: &Selection, f: F) -> Self
|
||||
where
|
||||
F: FnMut(&Range) -> Change,
|
||||
{
|
||||
Self::change(&state.doc, state.selection.ranges().iter().map(f))
|
||||
Self::change(doc, selection.ranges().iter().map(f))
|
||||
}
|
||||
|
||||
/// Insert text at each selection head.
|
||||
pub fn insert(state: &State, text: Tendril) -> Self {
|
||||
Self::change_by_selection(state, |range| (range.head, range.head, Some(text.clone())))
|
||||
pub fn insert(doc: &Rope, selection: &Selection, text: Tendril) -> Self {
|
||||
Self::change_by_selection(doc, selection, |range| {
|
||||
(range.head, range.head, Some(text.clone()))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -628,15 +630,15 @@ fn transaction_change() {
|
||||
#[test]
|
||||
fn optimized_composition() {
|
||||
let mut state = State::new("".into());
|
||||
let t1 = Transaction::insert(&state, Tendril::from_char('h'));
|
||||
let t1 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('h'));
|
||||
t1.apply(&mut state);
|
||||
let t2 = Transaction::insert(&state, Tendril::from_char('e'));
|
||||
let t2 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('e'));
|
||||
t2.apply(&mut state);
|
||||
let t3 = Transaction::insert(&state, Tendril::from_char('l'));
|
||||
let t3 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('l'));
|
||||
t3.apply(&mut state);
|
||||
let t4 = Transaction::insert(&state, Tendril::from_char('l'));
|
||||
let t4 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('l'));
|
||||
t4.apply(&mut state);
|
||||
let t5 = Transaction::insert(&state, Tendril::from_char('o'));
|
||||
let t5 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('o'));
|
||||
t5.apply(&mut state);
|
||||
|
||||
assert_eq!(state.doc, Rope::from_str("hello"));
|
||||
|
@ -30,7 +30,7 @@ pub enum Error {
|
||||
|
||||
pub mod util {
|
||||
use super::*;
|
||||
use helix_core::{Range, RopeSlice, State, Transaction};
|
||||
use helix_core::{Range, Rope, RopeSlice, Transaction};
|
||||
|
||||
pub fn lsp_pos_to_pos(doc: RopeSlice, pos: lsp::Position) -> usize {
|
||||
let line = doc.line_to_char(pos.line as usize);
|
||||
@ -52,13 +52,10 @@ pub fn range_to_lsp_range(doc: RopeSlice, range: Range) -> lsp::Range {
|
||||
lsp::Range::new(start, end)
|
||||
}
|
||||
|
||||
pub fn generate_transaction_from_edits(
|
||||
state: &State,
|
||||
edits: Vec<lsp::TextEdit>,
|
||||
) -> Transaction {
|
||||
let doc = state.doc.slice(..);
|
||||
pub fn generate_transaction_from_edits(doc: &Rope, edits: Vec<lsp::TextEdit>) -> Transaction {
|
||||
let text = doc.slice(..); // would be unnecessary if Transaction::change took Rope | RopeSlice
|
||||
Transaction::change(
|
||||
&state.doc,
|
||||
doc,
|
||||
edits.into_iter().map(|edit| {
|
||||
// simplify "" into None for cleaner changesets
|
||||
let replacement = if !edit.new_text.is_empty() {
|
||||
@ -67,8 +64,8 @@ pub fn generate_transaction_from_edits(
|
||||
None
|
||||
};
|
||||
|
||||
let start = lsp_pos_to_pos(doc, edit.range.start);
|
||||
let end = lsp_pos_to_pos(doc, edit.range.end);
|
||||
let start = lsp_pos_to_pos(text, edit.range.start);
|
||||
let end = lsp_pos_to_pos(text, edit.range.end);
|
||||
(start, end, replacement)
|
||||
}),
|
||||
)
|
||||
|
@ -4,8 +4,8 @@
|
||||
movement, object, pos_at_coords,
|
||||
regex::{self, Regex},
|
||||
register, search, selection,
|
||||
state::{Direction, Granularity, State},
|
||||
Change, ChangeSet, Position, Range, RopeSlice, Selection, Tendril, Transaction,
|
||||
state::{Direction, Granularity},
|
||||
Change, ChangeSet, Position, Range, Rope, RopeSlice, Selection, Tendril, Transaction,
|
||||
};
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
@ -107,7 +107,7 @@ pub fn move_line_down(cx: &mut Context) {
|
||||
|
||||
pub fn move_line_end(cx: &mut Context) {
|
||||
let doc = cx.doc();
|
||||
let lines = selection_lines(&doc.state);
|
||||
let lines = selection_lines(doc.text(), doc.selection());
|
||||
|
||||
let positions = lines
|
||||
.into_iter()
|
||||
@ -127,7 +127,7 @@ pub fn move_line_end(cx: &mut Context) {
|
||||
|
||||
pub fn move_line_start(cx: &mut Context) {
|
||||
let doc = cx.doc();
|
||||
let lines = selection_lines(&doc.state);
|
||||
let lines = selection_lines(doc.text(), doc.selection());
|
||||
|
||||
let positions = lines
|
||||
.into_iter()
|
||||
@ -586,8 +586,9 @@ pub fn extend_line(cx: &mut Context) {
|
||||
// heuristic: append changes to history after each command, unless we're in insert mode
|
||||
|
||||
fn _delete_selection(doc: &mut Document) {
|
||||
let transaction =
|
||||
Transaction::change_by_selection(&doc.state, |range| (range.from(), range.to() + 1, None));
|
||||
let transaction = Transaction::change_by_selection(doc.text(), doc.selection(), |range| {
|
||||
(range.from(), range.to() + 1, None)
|
||||
});
|
||||
doc.apply(&transaction);
|
||||
}
|
||||
|
||||
@ -722,12 +723,11 @@ pub fn buffer_picker(cx: &mut Context) {
|
||||
}
|
||||
|
||||
// calculate line numbers for each selection range
|
||||
fn selection_lines(state: &State) -> Vec<usize> {
|
||||
let mut lines = state
|
||||
.selection
|
||||
fn selection_lines(doc: &Rope, selection: &Selection) -> Vec<usize> {
|
||||
let mut lines = selection
|
||||
.ranges()
|
||||
.iter()
|
||||
.map(|range| state.doc.char_to_line(range.head))
|
||||
.map(|range| doc.char_to_line(range.head))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
lines.sort_unstable(); // sorting by usize so _unstable is preferred
|
||||
@ -758,19 +758,21 @@ pub fn open_below(cx: &mut Context) {
|
||||
let doc = cx.doc();
|
||||
enter_insert_mode(doc);
|
||||
|
||||
let lines = selection_lines(&doc.state);
|
||||
let lines = selection_lines(doc.text(), doc.selection());
|
||||
|
||||
let positions = lines.into_iter().map(|index| {
|
||||
// adjust all positions to the end of the line (next line minus one)
|
||||
doc.text().line_to_char(index + 1).saturating_sub(1)
|
||||
});
|
||||
|
||||
let text = doc.text().slice(..);
|
||||
|
||||
let changes: Vec<Change> = positions
|
||||
.map(|index| {
|
||||
// TODO: share logic with insert_newline for indentation
|
||||
let indent_level = helix_core::indent::suggested_indent_for_pos(
|
||||
doc.syntax.as_ref(),
|
||||
&doc.state,
|
||||
text,
|
||||
index,
|
||||
true,
|
||||
);
|
||||
@ -955,7 +957,7 @@ pub mod insert {
|
||||
pub fn insert_char(cx: &mut Context, c: char) {
|
||||
let doc = cx.doc();
|
||||
let c = Tendril::from_char(c);
|
||||
let transaction = Transaction::insert(&doc.state, c);
|
||||
let transaction = Transaction::insert(doc.text(), doc.selection(), c);
|
||||
|
||||
doc.apply(&transaction);
|
||||
}
|
||||
@ -966,10 +968,11 @@ pub fn insert_tab(cx: &mut Context) {
|
||||
|
||||
pub fn insert_newline(cx: &mut Context) {
|
||||
let doc = cx.doc();
|
||||
let transaction = Transaction::change_by_selection(&doc.state, |range| {
|
||||
let text = doc.text().slice(..);
|
||||
let transaction = Transaction::change_by_selection(doc.text(), doc.selection(), |range| {
|
||||
let indent_level = helix_core::indent::suggested_indent_for_pos(
|
||||
doc.syntax.as_ref(),
|
||||
&doc.state,
|
||||
text,
|
||||
range.head,
|
||||
true,
|
||||
);
|
||||
@ -987,7 +990,7 @@ pub fn delete_char_backward(cx: &mut Context) {
|
||||
let count = cx.count;
|
||||
let doc = cx.doc();
|
||||
let text = doc.text().slice(..);
|
||||
let transaction = Transaction::change_by_selection(&doc.state, |range| {
|
||||
let transaction = Transaction::change_by_selection(doc.text(), doc.selection(), |range| {
|
||||
(
|
||||
graphemes::nth_prev_grapheme_boundary(text, range.head, count),
|
||||
range.head,
|
||||
@ -1001,7 +1004,7 @@ pub fn delete_char_forward(cx: &mut Context) {
|
||||
let count = cx.count;
|
||||
let doc = cx.doc();
|
||||
let text = doc.text().slice(..);
|
||||
let transaction = Transaction::change_by_selection(&doc.state, |range| {
|
||||
let transaction = Transaction::change_by_selection(doc.text(), doc.selection(), |range| {
|
||||
(
|
||||
range.head,
|
||||
graphemes::nth_next_grapheme_boundary(text, range.head, count),
|
||||
@ -1076,12 +1079,12 @@ pub fn paste(cx: &mut Context) {
|
||||
// paste on the next line
|
||||
// TODO: can simply take a range + modifier and compute the right pos without ifs
|
||||
let text = doc.text();
|
||||
Transaction::change_by_selection(&doc.state, |range| {
|
||||
Transaction::change_by_selection(doc.text(), doc.selection(), |range| {
|
||||
let line_end = text.line_to_char(text.char_to_line(range.head) + 1);
|
||||
(line_end, line_end, Some(values.next().unwrap()))
|
||||
})
|
||||
} else {
|
||||
Transaction::change_by_selection(&doc.state, |range| {
|
||||
Transaction::change_by_selection(doc.text(), doc.selection(), |range| {
|
||||
(range.head + 1, range.head + 1, Some(values.next().unwrap()))
|
||||
})
|
||||
};
|
||||
@ -1190,7 +1193,7 @@ pub fn format_selections(cx: &mut Context) {
|
||||
))
|
||||
.unwrap_or_default();
|
||||
|
||||
let transaction = helix_lsp::util::generate_transaction_from_edits(&doc.state, edits);
|
||||
let transaction = helix_lsp::util::generate_transaction_from_edits(doc.text(), edits);
|
||||
|
||||
doc.apply(&transaction);
|
||||
}
|
||||
@ -1352,7 +1355,7 @@ pub fn completion(cx: &mut Context) {
|
||||
|
||||
// TODO: <-- if state has changed by further input, transaction will panic on len
|
||||
let transaction =
|
||||
util::generate_transaction_from_edits(&doc.state, vec![edit]);
|
||||
util::generate_transaction_from_edits(doc.text(), vec![edit]);
|
||||
doc.apply(&transaction);
|
||||
// TODO: doc.append_changes_to_history(); if not in insert mode?
|
||||
}
|
||||
@ -1421,7 +1424,7 @@ pub fn next_view(cx: &mut Context) {
|
||||
// comments
|
||||
pub fn toggle_comments(cx: &mut Context) {
|
||||
let doc = cx.doc();
|
||||
let transaction = comment::toggle_line_comments(&doc.state);
|
||||
let transaction = comment::toggle_line_comments(doc.text(), doc.selection());
|
||||
|
||||
doc.apply(&transaction);
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
use helix_core::{
|
||||
indent::TAB_WIDTH,
|
||||
syntax::{self, HighlightEvent},
|
||||
Position, Range, State,
|
||||
Position, Range,
|
||||
};
|
||||
use helix_view::{document::Mode, Document, Editor, Theme, View};
|
||||
use std::borrow::Cow;
|
||||
|
@ -346,7 +346,7 @@ fn changeset_to_changes() {
|
||||
|
||||
// insert
|
||||
|
||||
let transaction = Transaction::insert(&doc.state, " world".into());
|
||||
let transaction = Transaction::insert(doc.text(), doc.selection(), " world".into());
|
||||
let old_doc = doc.state.clone();
|
||||
doc.apply(&transaction);
|
||||
let changes = Client::changeset_to_changes(&old_doc.doc, doc.text(), transaction.changes());
|
||||
|
Loading…
Reference in New Issue
Block a user