aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBlaž Hrastnik2020-09-13 11:04:16 +0000
committerBlaž Hrastnik2020-09-13 11:04:16 +0000
commitb08278807ee51e279c07dd6b7955713455a4c654 (patch)
tree796ea4ecc8b316b4a1ecaa52122af7e5d9dc37f6
parentfb0f56b7472d221e57b2bec13c9c8668fe673e77 (diff)
Add 'A', 'I' commands.
-rw-r--r--helix-core/src/commands.rs78
-rw-r--r--helix-core/src/transaction.rs8
-rw-r--r--helix-term/src/keymap.rs8
3 files changed, 94 insertions, 0 deletions
diff --git a/helix-core/src/commands.rs b/helix-core/src/commands.rs
index 836667a1..914ca0fe 100644
--- a/helix-core/src/commands.rs
+++ b/helix-core/src/commands.rs
@@ -60,8 +60,86 @@ pub fn append_mode(state: &mut State, _count: usize) {
})
}
+// TODO: I, A, o and O can share a lot of the primitives.
+
// I inserts at the start of each line with a selection
+pub fn prepend_to_line(state: &mut State, _count: usize) {
+ state.mode = Mode::Insert;
+
+ // calculate line numbers for each selection range
+ let mut lines = state
+ .selection
+ .ranges()
+ .iter()
+ .map(|range| state.doc.char_to_line(range.head))
+ .collect::<Vec<_>>();
+
+ lines.sort();
+ lines.dedup();
+
+ let positions: Vec<_> = lines
+ .into_iter()
+ .map(|index| {
+ // adjust all positions to the end of the line.
+ let line_start = state.doc.line_to_char(index);
+ line_start
+ })
+ .collect();
+
+ let selection = Selection::new(
+ positions
+ .iter()
+ .copied()
+ .map(|pos| Range::new(pos, pos))
+ .collect(),
+ 0,
+ );
+
+ let transaction = Transaction::new(state).with_selection(selection);
+
+ transaction.apply(state);
+ // TODO: need to store into history if successful
+}
+
// A inserts at the end of each line with a selection
+pub fn append_to_line(state: &mut State, _count: usize) {
+ state.mode = Mode::Insert;
+
+ // calculate line numbers for each selection range
+ let mut lines = state
+ .selection
+ .ranges()
+ .iter()
+ .map(|range| state.doc.char_to_line(range.head))
+ .collect::<Vec<_>>();
+
+ lines.sort();
+ lines.dedup();
+
+ let positions: Vec<_> = lines
+ .into_iter()
+ .map(|index| {
+ // adjust all positions to the end of the line.
+ let line = state.doc.line(index);
+ let line_start = state.doc.line_to_char(index);
+ line_start + line.len_chars() - 1
+ })
+ .collect();
+
+ let selection = Selection::new(
+ positions
+ .iter()
+ .copied()
+ .map(|pos| Range::new(pos, pos))
+ .collect(),
+ 0,
+ );
+
+ let transaction = Transaction::new(state).with_selection(selection);
+
+ transaction.apply(state);
+ // TODO: need to store into history if successful
+}
// o inserts a new line after each line with a selection
pub fn open_below(state: &mut State, _count: usize) {
diff --git a/helix-core/src/transaction.rs b/helix-core/src/transaction.rs
index 3d03de19..12ed523e 100644
--- a/helix-core/src/transaction.rs
+++ b/helix-core/src/transaction.rs
@@ -322,6 +322,14 @@ pub struct Transaction {
}
impl Transaction {
+ /// Create a new, empty transaction.
+ pub fn new(state: &mut State) -> Self {
+ Self {
+ changes: ChangeSet::new(&state.doc),
+ selection: None,
+ }
+ }
+
/// Returns true if applied successfully.
pub fn apply(&self, state: &mut State) -> bool {
// apply changes to the document
diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs
index 32515761..5611e104 100644
--- a/helix-term/src/keymap.rs
+++ b/helix-term/src/keymap.rs
@@ -104,10 +104,18 @@ pub fn default() -> Keymap {
modifiers: Modifiers::NONE
} => commands::insert_mode as Command,
Key {
+ code: KeyCode::Char('I'),
+ modifiers: Modifiers::SHIFT,
+ } => commands::prepend_to_line as Command,
+ Key {
code: KeyCode::Char('a'),
modifiers: Modifiers::NONE
} => commands::append_mode as Command,
Key {
+ code: KeyCode::Char('A'),
+ modifiers: Modifiers::SHIFT,
+ } => commands::append_to_line as Command,
+ Key {
code: KeyCode::Char('o'),
modifiers: Modifiers::NONE
} => commands::open_below as Command,