feat: better api to move input cursor to bol/eol

This commit is contained in:
darcy 2025-01-02 19:04:08 +11:00 committed by sxyazi
parent 8c92fa9f53
commit 5ce55232f7
No known key found for this signature in database
2 changed files with 91 additions and 32 deletions

View file

@ -232,13 +232,13 @@ keymap = [
{ on = "<C-[>", run = "escape", desc = "Go back the normal mode, or cancel input" },
# Mode
{ on = "i", run = "insert", desc = "Enter insert mode" },
{ on = "a", run = "insert --append", desc = "Enter append mode" },
{ on = "I", run = [ "move -999", "insert" ], desc = "Move to the BOL, and enter insert mode" },
{ on = "A", run = [ "move 999", "insert --append" ], desc = "Move to the EOL, and enter append mode" },
{ on = "v", run = "visual", desc = "Enter visual mode" },
{ on = "V", run = [ "move -999", "visual", "move 999" ], desc = "Enter visual mode and select all" },
{ on = "r", run = "replace", desc = "Replace a single character" },
{ on = "i", run = "insert", desc = "Enter insert mode" },
{ on = "a", run = "insert --append", desc = "Enter append mode" },
{ on = "I", run = [ "move first-char", "insert" ], desc = "Move to the BOL, and enter insert mode" },
{ on = "A", run = [ "move eol", "insert --append" ], desc = "Move to the EOL, and enter append mode" },
{ on = "v", run = "visual", desc = "Enter visual mode" },
{ on = "V", run = [ "move first-char", "visual", "move eol" ], desc = "Enter visual mode and select all" },
{ on = "r", run = "replace", desc = "Replace a single character" },
# Character-wise movement
{ on = "h", run = "move -1", desc = "Move back a character" },
@ -256,12 +256,14 @@ keymap = [
{ on = "<A-f>", run = "forward --end-of-word", desc = "Move forward to the end of the current or next word" },
# Line-wise movement
{ on = "0", run = "move -999", desc = "Move to the BOL" },
{ on = "$", run = "move 999", desc = "Move to the EOL" },
{ on = "<C-a>", run = "move -999", desc = "Move to the BOL" },
{ on = "<C-e>", run = "move 999", desc = "Move to the EOL" },
{ on = "<Home>", run = "move -999", desc = "Move to the BOL" },
{ on = "<End>", run = "move 999", desc = "Move to the EOL" },
{ on = "0", run = "move bol", desc = "Move to the BOL" },
{ on = "_", run = "move first-char", desc = "Move to the first non-whitespace character" },
{ on = "^", run = "move first-char", desc = "Move to the first non-whitespace character" },
{ on = "$", run = "move eol", desc = "Move to the EOL" },
{ on = "<C-a>", run = "move first-char", desc = "Move to the BOL" },
{ on = "<C-e>", run = "move eol", desc = "Move to the EOL" },
{ on = "<Home>", run = "move first-char", desc = "Move to the BOL" },
{ on = "<End>", run = "move eol", desc = "Move to the EOL" },
# Delete
{ on = "<Backspace>", run = "backspace", desc = "Delete the character before the cursor" },
@ -276,14 +278,14 @@ keymap = [
{ on = "<A-d>", run = "kill forward", desc = "Kill forwards to the end of the current word" },
# Cut/Yank/Paste
{ on = "d", run = "delete --cut", desc = "Cut the selected characters" },
{ on = "D", run = [ "delete --cut", "move 999" ], desc = "Cut until the EOL" },
{ on = "c", run = "delete --cut --insert", desc = "Cut the selected characters, and enter insert mode" },
{ on = "C", run = [ "delete --cut --insert", "move 999" ], desc = "Cut until the EOL, and enter insert mode" },
{ on = "x", run = [ "delete --cut", "move 1 --in-operating" ], desc = "Cut the current character" },
{ on = "y", run = "yank", desc = "Copy the selected characters" },
{ on = "p", run = "paste", desc = "Paste the copied characters after the cursor" },
{ on = "P", run = "paste --before", desc = "Paste the copied characters before the cursor" },
{ on = "d", run = "delete --cut", desc = "Cut the selected characters" },
{ on = "D", run = [ "delete --cut", "move eol" ], desc = "Cut until the EOL" },
{ on = "c", run = "delete --cut --insert", desc = "Cut the selected characters, and enter insert mode" },
{ on = "C", run = [ "delete --cut --insert", "move eol" ], desc = "Cut until the EOL, and enter insert mode" },
{ on = "x", run = [ "delete --cut", "move 1 --in-operating" ], desc = "Cut the current character" },
{ on = "y", run = "yank", desc = "Copy the selected characters" },
{ on = "p", run = "paste", desc = "Paste the copied characters after the cursor" },
{ on = "P", run = "paste --before", desc = "Paste the copied characters before the cursor" },
# Undo/Redo
{ on = "u", run = "undo", desc = "Undo the last operation" },

View file

@ -5,20 +5,56 @@ use yazi_shared::event::{CmdCow, Data};
use crate::input::{Input, op::InputOp, snap::InputSnap};
struct Opt {
step: isize,
step: Step,
in_operating: bool,
}
enum Step {
Offset(isize),
Bol,
Eol,
FirstChar,
LastChar,
}
impl TryFrom<&Data> for Step {
type Error = ();
fn try_from(d: &Data) -> Result<Self, Self::Error> {
if let Some(offset) = d.as_isize() {
return Ok(Step::Offset(offset));
};
if let Some(s) = d.as_str() {
if let Ok(offset) = s.parse() {
return Ok(Step::Offset(offset));
};
match s.as_ref() {
"bol" => return Ok(Step::Bol),
"eol" => return Ok(Step::Eol),
"first-char" => return Ok(Step::FirstChar),
"last-char" => return Ok(Step::LastChar),
_ => (),
}
}
Err(())
}
}
impl From<CmdCow> for Opt {
fn from(c: CmdCow) -> Self {
Self {
step: c.first().and_then(Data::as_isize).unwrap_or(0),
step: c.get(0).unwrap().try_into().unwrap(),
in_operating: c.bool("in-operating"),
}
}
}
impl From<isize> for Opt {
fn from(step: isize) -> Self { Self { step, in_operating: false } }
fn from(step: isize) -> Self {
Self {
step: Step::Offset(step),
in_operating: false,
}
}
}
impl Input {
@ -29,14 +65,35 @@ impl Input {
return;
}
render!(self.handle_op(
if opt.step <= 0 {
snap.cursor.saturating_sub(opt.step.unsigned_abs())
} else {
snap.count().min(snap.cursor + opt.step as usize)
},
false,
));
let position = match opt.step {
Step::Offset(offset) =>
if offset <= 0 {
snap.cursor.saturating_sub(offset.unsigned_abs())
} else {
snap.count().min(snap.cursor + offset as usize)
},
Step::Bol => 0,
Step::Eol => snap.count(),
Step::FirstChar => snap
.value
.chars()
.enumerate()
.filter(|(_, ch)| !ch.is_whitespace())
.map(|(i, _)| i)
.next()
.unwrap_or(0),
Step::LastChar => snap
.value
.chars()
.rev()
.enumerate()
.filter(|(_, ch)| !ch.is_whitespace())
.map(|(i, _)| i)
.next()
.unwrap_or(0),
};
render!(self.handle_op(position, false));
let (limit, snap) = (self.limit(), self.snap_mut());
if snap.offset > snap.cursor {