reimplemented ex-mode widget/function execution
This commit is contained in:
12
Cargo.lock
generated
12
Cargo.lock
generated
@@ -224,6 +224,17 @@ version = "2.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fnmatch-regex"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f319c7da34eac5f0b8c7220a4afb2e1ddde0c24ae87c7435a8e36dcd62a43a3"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"itertools",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foldhash"
|
name = "foldhash"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
@@ -568,6 +579,7 @@ dependencies = [
|
|||||||
"bitflags",
|
"bitflags",
|
||||||
"clap",
|
"clap",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
"fnmatch-regex",
|
||||||
"glob",
|
"glob",
|
||||||
"itertools",
|
"itertools",
|
||||||
"log",
|
"log",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ ariadne = "0.6.0"
|
|||||||
bitflags = "2.8.0"
|
bitflags = "2.8.0"
|
||||||
clap = { version = "4.5.38", features = ["derive"] }
|
clap = { version = "4.5.38", features = ["derive"] }
|
||||||
env_logger = "0.11.9"
|
env_logger = "0.11.9"
|
||||||
|
fnmatch-regex = "0.3.0"
|
||||||
glob = "0.3.2"
|
glob = "0.3.2"
|
||||||
itertools = "0.14.0"
|
itertools = "0.14.0"
|
||||||
log = "0.4.29"
|
log = "0.4.29"
|
||||||
|
|||||||
@@ -865,15 +865,15 @@ impl QueryEditor {
|
|||||||
self.available_width = width;
|
self.available_width = width;
|
||||||
}
|
}
|
||||||
pub fn update_scroll_offset(&mut self) {
|
pub fn update_scroll_offset(&mut self) {
|
||||||
let cursor_pos = self.linebuf.cursor.get();
|
let cursor_pos = self.linebuf.cursor_to_flat();
|
||||||
if cursor_pos < self.scroll_offset + 1 {
|
if cursor_pos < self.scroll_offset + 1 {
|
||||||
self.scroll_offset = self.linebuf.cursor.ret_sub(1);
|
self.scroll_offset = self.linebuf.cursor_to_flat().saturating_sub(1)
|
||||||
}
|
}
|
||||||
if cursor_pos >= self.scroll_offset + self.available_width.saturating_sub(1) {
|
if cursor_pos >= self.scroll_offset + self.available_width.saturating_sub(1) {
|
||||||
self.scroll_offset = self
|
self.scroll_offset = self
|
||||||
.linebuf
|
.linebuf
|
||||||
.cursor
|
.cursor_to_flat()
|
||||||
.ret_sub(self.available_width.saturating_sub(1));
|
.saturating_sub(self.available_width.saturating_sub(1));
|
||||||
}
|
}
|
||||||
let max_offset = self
|
let max_offset = self
|
||||||
.linebuf
|
.linebuf
|
||||||
@@ -1257,8 +1257,7 @@ impl FuzzySelector {
|
|||||||
let cursor_in_window = self
|
let cursor_in_window = self
|
||||||
.query
|
.query
|
||||||
.linebuf
|
.linebuf
|
||||||
.cursor
|
.cursor_to_flat()
|
||||||
.get()
|
|
||||||
.saturating_sub(self.query.scroll_offset);
|
.saturating_sub(self.query.scroll_offset);
|
||||||
let cursor_col = (cursor_in_window + 4) as u16;
|
let cursor_col = (cursor_in_window + 4) as u16;
|
||||||
write!(buf, "\x1b[{}A\r\x1b[{}C", lines_below_prompt, cursor_col).unwrap();
|
write!(buf, "\x1b[{}A\r\x1b[{}C", lines_below_prompt, cursor_col).unwrap();
|
||||||
|
|||||||
@@ -317,7 +317,7 @@ impl History {
|
|||||||
|
|
||||||
pub fn update_pending_cmd(&mut self, buf: (&str, usize)) {
|
pub fn update_pending_cmd(&mut self, buf: (&str, usize)) {
|
||||||
let cursor_pos = if let Some(pending) = &self.pending {
|
let cursor_pos = if let Some(pending) = &self.pending {
|
||||||
pending.cursor.get()
|
pending.cursor_to_flat()
|
||||||
} else {
|
} else {
|
||||||
buf.1
|
buf.1
|
||||||
};
|
};
|
||||||
@@ -329,7 +329,7 @@ impl History {
|
|||||||
|
|
||||||
if let Some(pending) = &mut self.pending {
|
if let Some(pending) = &mut self.pending {
|
||||||
pending.set_buffer(cmd);
|
pending.set_buffer(cmd);
|
||||||
pending.cursor.set(cursor_pos);
|
pending.set_cursor_from_flat(cursor_pos);
|
||||||
} else {
|
} else {
|
||||||
self.pending = Some(LineBuf::new().with_initial(&cmd, cursor_pos));
|
self.pending = Some(LineBuf::new().with_initial(&cmd, cursor_pos));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fmt::Display,
|
collections::HashSet, fmt::Display, ops::{Index, IndexMut}, slice::SliceIndex
|
||||||
ops::{Index, IndexMut},
|
|
||||||
slice::SliceIndex,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
@@ -14,11 +12,11 @@ use super::vicmd::{
|
|||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
expand::expand_cmd_sub,
|
expand::expand_cmd_sub,
|
||||||
libsh::error::ShResult,
|
libsh::{error::ShResult, guards::{RawModeGuard, var_ctx_guard}},
|
||||||
parse::{
|
parse::{
|
||||||
Redir, RedirType,
|
Redir, RedirType,
|
||||||
execute::exec_input,
|
execute::exec_input,
|
||||||
lex::{LexFlags, LexStream, Tk, TkFlags, TkRule},
|
lex::{LexFlags, LexStream, Tk, TkFlags},
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
procio::{IoFrame, IoMode, IoStack},
|
procio::{IoFrame, IoMode, IoStack},
|
||||||
@@ -26,7 +24,7 @@ use crate::{
|
|||||||
markers,
|
markers,
|
||||||
register::RegisterContent, vicmd::{ReadSrc, VerbCmd, WriteDest},
|
register::RegisterContent, vicmd::{ReadSrc, VerbCmd, WriteDest},
|
||||||
},
|
},
|
||||||
state::{read_vars, write_meta},
|
state::{VarFlags, VarKind, read_vars, write_meta, write_vars},
|
||||||
};
|
};
|
||||||
|
|
||||||
const PUNCTUATION: [&str; 3] = ["?", "!", "."];
|
const PUNCTUATION: [&str; 3] = ["?", "!", "."];
|
||||||
@@ -298,32 +296,6 @@ impl From<&Grapheme> for CharClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_whitespace(a: &Grapheme) -> bool {
|
|
||||||
CharClass::from(a) == CharClass::Whitespace
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_other_class(a: &Grapheme, b: &Grapheme) -> bool {
|
|
||||||
let a = CharClass::from(a);
|
|
||||||
let b = CharClass::from(b);
|
|
||||||
a != b
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_other_class_not_ws(a: &Grapheme, b: &Grapheme) -> bool {
|
|
||||||
if is_whitespace(a) || is_whitespace(b) {
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
is_other_class(a, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_other_class_or_is_ws(a: &Grapheme, b: &Grapheme) -> bool {
|
|
||||||
if is_whitespace(a) || is_whitespace(b) {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
is_other_class(a, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
pub enum SelectMode {
|
pub enum SelectMode {
|
||||||
Char(Pos),
|
Char(Pos),
|
||||||
@@ -343,7 +315,10 @@ impl Pos {
|
|||||||
row: usize::MAX,
|
row: usize::MAX,
|
||||||
col: usize::MAX,
|
col: usize::MAX,
|
||||||
};
|
};
|
||||||
pub const MIN: Self = Pos { row: 0, col: 0 };
|
pub const MIN: Self = Pos {
|
||||||
|
row: usize::MIN, // just in case we discover something smaller than '0'
|
||||||
|
col: usize::MIN,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn row_col_add(&self, row: isize, col: isize) -> Self {
|
pub fn row_col_add(&self, row: isize, col: isize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -412,21 +387,6 @@ pub struct Cursor {
|
|||||||
pub exclusive: bool,
|
pub exclusive: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cursor {
|
|
||||||
/// Compat shim: returns the flat column position (col on row 0 in single-line mode)
|
|
||||||
pub fn get(&self) -> usize {
|
|
||||||
self.pos.col
|
|
||||||
}
|
|
||||||
/// Compat shim: sets the flat column position
|
|
||||||
pub fn set(&mut self, col: usize) {
|
|
||||||
self.pos.col = col;
|
|
||||||
}
|
|
||||||
/// Compat shim: returns cursor.col - n without mutating, clamped to 0
|
|
||||||
pub fn ret_sub(&self, n: usize) -> usize {
|
|
||||||
self.pos.col.saturating_sub(n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Clone, Debug)]
|
#[derive(Default, Clone, Debug)]
|
||||||
pub struct Edit {
|
pub struct Edit {
|
||||||
pub old_cursor: Pos,
|
pub old_cursor: Pos,
|
||||||
@@ -715,7 +675,66 @@ impl LineBuf {
|
|||||||
col,
|
col,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
fn verb_shell_cmd(&self, cmd: &str) -> ShResult<()> {
|
fn verb_shell_cmd(&mut self, cmd: &str) -> ShResult<()> {
|
||||||
|
let mut vars = HashSet::new();
|
||||||
|
vars.insert("_BUFFER".into());
|
||||||
|
vars.insert("_CURSOR".into());
|
||||||
|
vars.insert("_ANCHOR".into());
|
||||||
|
let _guard = var_ctx_guard(vars);
|
||||||
|
|
||||||
|
let mut buf = self.joined();
|
||||||
|
let mut cursor = self.cursor_to_flat();
|
||||||
|
let mut anchor = self.select_mode.map(|r| {
|
||||||
|
match r {
|
||||||
|
SelectMode::Char(pos) |
|
||||||
|
SelectMode::Block(pos) |
|
||||||
|
SelectMode::Line(pos) => {
|
||||||
|
self.pos_to_flat(pos).to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).unwrap_or_default();
|
||||||
|
|
||||||
|
write_vars(|v| {
|
||||||
|
v.set_var("_BUFFER", VarKind::Str(buf.clone()), VarFlags::EXPORT)?;
|
||||||
|
v.set_var(
|
||||||
|
"_CURSOR",
|
||||||
|
VarKind::Str(cursor.to_string()),
|
||||||
|
VarFlags::EXPORT,
|
||||||
|
)?;
|
||||||
|
v.set_var(
|
||||||
|
"_ANCHOR",
|
||||||
|
VarKind::Str(anchor.clone()),
|
||||||
|
VarFlags::EXPORT,
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
RawModeGuard::with_cooked_mode(|| exec_input(cmd.to_string(), None, true, Some("<ex-mode-cmd>".into())))?;
|
||||||
|
|
||||||
|
let keys = write_vars(|v| {
|
||||||
|
buf = v.take_var("_BUFFER");
|
||||||
|
cursor = v.take_var("_CURSOR").parse().unwrap_or(cursor);
|
||||||
|
anchor = v.take_var("_ANCHOR");
|
||||||
|
v.take_var("_KEYS")
|
||||||
|
});
|
||||||
|
|
||||||
|
self.set_buffer(buf);
|
||||||
|
self.set_cursor_from_flat(cursor);
|
||||||
|
if let Ok(pos) = anchor.parse()
|
||||||
|
&& pos != cursor
|
||||||
|
&& self.select_mode.is_some() {
|
||||||
|
let new_pos = self.pos_from_flat(pos);
|
||||||
|
match self.select_mode.as_mut() {
|
||||||
|
Some(SelectMode::Line(pos)) |
|
||||||
|
Some(SelectMode::Block(pos)) |
|
||||||
|
Some(SelectMode::Char(pos)) => {
|
||||||
|
*pos = new_pos
|
||||||
|
}
|
||||||
|
None => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !keys.is_empty() {
|
||||||
|
write_meta(|m| m.set_pending_widget_keys(&keys))
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn insert_at(&mut self, pos: Pos, gr: Grapheme) {
|
fn insert_at(&mut self, pos: Pos, gr: Grapheme) {
|
||||||
@@ -1064,10 +1083,15 @@ impl LineBuf {
|
|||||||
match obj {
|
match obj {
|
||||||
// text structures
|
// text structures
|
||||||
TextObj::Word(word, bound) => self.text_obj_word(count, word, obj, bound),
|
TextObj::Word(word, bound) => self.text_obj_word(count, word, obj, bound),
|
||||||
TextObj::Sentence(direction) => todo!(),
|
TextObj::Sentence(_) |
|
||||||
TextObj::Paragraph(direction) => todo!(),
|
TextObj::Paragraph(_) |
|
||||||
TextObj::WholeSentence(bound) => todo!(),
|
TextObj::WholeSentence(_) |
|
||||||
TextObj::WholeParagraph(bound) => todo!(),
|
TextObj::Tag(_) |
|
||||||
|
TextObj::Custom(_) |
|
||||||
|
TextObj::WholeParagraph(_) => {
|
||||||
|
log::warn!("{:?} text objects are not implemented yet", obj);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
// quote stuff
|
// quote stuff
|
||||||
TextObj::DoubleQuote(bound) |
|
TextObj::DoubleQuote(bound) |
|
||||||
@@ -1081,9 +1105,6 @@ impl LineBuf {
|
|||||||
| TextObj::Bracket(bound)
|
| TextObj::Bracket(bound)
|
||||||
| TextObj::Brace(bound)
|
| TextObj::Brace(bound)
|
||||||
| TextObj::Angle(bound) => self.text_obj_delim(count, obj, bound),
|
| TextObj::Angle(bound) => self.text_obj_delim(count, obj, bound),
|
||||||
|
|
||||||
TextObj::Tag(bound) => todo!(),
|
|
||||||
TextObj::Custom(_) => todo!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn text_obj_word(
|
fn text_obj_word(
|
||||||
@@ -1736,10 +1757,13 @@ impl LineBuf {
|
|||||||
let (s, e) = ordered(*s, *e);
|
let (s, e) = ordered(*s, *e);
|
||||||
Some(MotionKind::Block { start: s, end: e })
|
Some(MotionKind::Block { start: s, end: e })
|
||||||
}
|
}
|
||||||
Motion::RepeatMotion => todo!(),
|
Motion::RepeatMotion |
|
||||||
Motion::RepeatMotionRev => todo!(),
|
Motion::RepeatMotionRev => unreachable!("Repeat motions should have been resolved in readline/mod.rs"),
|
||||||
Motion::Global(val) => todo!(),
|
Motion::Global(val) |
|
||||||
Motion::NotGlobal(val) => todo!(),
|
Motion::NotGlobal(val) => {
|
||||||
|
log::warn!("Global motions are not implemented yet (val: {:?})", val);
|
||||||
|
None
|
||||||
|
}
|
||||||
Motion::Null => None,
|
Motion::Null => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1748,11 +1772,11 @@ impl LineBuf {
|
|||||||
}
|
}
|
||||||
fn move_to_start(&mut self, motion: MotionKind) {
|
fn move_to_start(&mut self, motion: MotionKind) {
|
||||||
match motion {
|
match motion {
|
||||||
MotionKind::Char { start, end, inclusive } => {
|
MotionKind::Char { start, end, .. } => {
|
||||||
let (s,_) = ordered(start, end);
|
let (s,_) = ordered(start, end);
|
||||||
self.set_cursor(s);
|
self.set_cursor(s);
|
||||||
}
|
}
|
||||||
MotionKind::Line { start, end, inclusive } => {
|
MotionKind::Line { start, end, .. } => {
|
||||||
let (s,_) = ordered(start, end);
|
let (s,_) = ordered(start, end);
|
||||||
self.set_cursor(Pos { row: s, col: 0 });
|
self.set_cursor(Pos { row: s, col: 0 });
|
||||||
}
|
}
|
||||||
@@ -2250,7 +2274,7 @@ impl LineBuf {
|
|||||||
let line_len = self.line(row).len();
|
let line_len = self.line(row).len();
|
||||||
|
|
||||||
// we are going to calculate the level twice, once at column = 0 and once at column = line.len()
|
// we are going to calculate the level twice, once at column = 0 and once at column = line.len()
|
||||||
// "b-b-b-b-but the performance" i dont care. open a pull request genius
|
// "b-b-b-b-but the performance" i dont care
|
||||||
// the number of tabs we use for the line is the lesser of these two calculations
|
// the number of tabs we use for the line is the lesser of these two calculations
|
||||||
// if level_start > level_end, the line has an closer
|
// if level_start > level_end, the line has an closer
|
||||||
// if level_end > level_start, the line has a opener
|
// if level_end > level_start, the line has a opener
|
||||||
@@ -2758,10 +2782,28 @@ impl LineBuf {
|
|||||||
offset + pos.col.min(self.lines[row].len())
|
offset + pos.col.min(self.lines[row].len())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pos_from_flat(&self, mut flat: usize) -> Pos {
|
||||||
|
for (i, line) in self.lines.iter().enumerate() {
|
||||||
|
if flat <= line.len() {
|
||||||
|
return Pos { row: i, col: flat };
|
||||||
|
}
|
||||||
|
flat = flat.saturating_sub(line.len() + 1); // +1 for '\n'
|
||||||
|
}
|
||||||
|
// If we exceed the total length, clamp to end
|
||||||
|
let last_row = self.lines.len().saturating_sub(1);
|
||||||
|
let last_col = self.lines[last_row].len();
|
||||||
|
Pos { row: last_row, col: last_col }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn cursor_to_flat(&self) -> usize {
|
pub fn cursor_to_flat(&self) -> usize {
|
||||||
self.pos_to_flat(self.cursor.pos)
|
self.pos_to_flat(self.cursor.pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_cursor_from_flat(&mut self, flat: usize) {
|
||||||
|
self.cursor.pos = self.pos_from_flat(flat);
|
||||||
|
self.fix_cursor();
|
||||||
|
}
|
||||||
|
|
||||||
/// Compat shim: attempt history expansion. Stub that returns false.
|
/// Compat shim: attempt history expansion. Stub that returns false.
|
||||||
pub fn attempt_history_expansion(&mut self, _history: &super::history::History) -> bool {
|
pub fn attempt_history_expansion(&mut self, _history: &super::history::History) -> bool {
|
||||||
// TODO: implement history expansion for 2D buffer
|
// TODO: implement history expansion for 2D buffer
|
||||||
|
|||||||
@@ -343,7 +343,7 @@ impl ShedVi {
|
|||||||
self.editor = LineBuf::new().with_initial(initial, 0);
|
self.editor = LineBuf::new().with_initial(initial, 0);
|
||||||
{
|
{
|
||||||
let s = self.editor.joined();
|
let s = self.editor.joined();
|
||||||
let c = self.editor.cursor.get();
|
let c = self.editor.cursor_to_flat();
|
||||||
self.history.update_pending_cmd((&s, c));
|
self.history.update_pending_cmd((&s, c));
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
@@ -486,7 +486,7 @@ impl ShedVi {
|
|||||||
|
|
||||||
self
|
self
|
||||||
.history
|
.history
|
||||||
.update_pending_cmd((&self.editor.joined(), self.editor.cursor.get()));
|
.update_pending_cmd((&self.editor.joined(), self.editor.cursor_to_flat()));
|
||||||
self.editor.set_hint(None);
|
self.editor.set_hint(None);
|
||||||
{
|
{
|
||||||
let mut writer = std::mem::take(&mut self.writer);
|
let mut writer = std::mem::take(&mut self.writer);
|
||||||
@@ -548,7 +548,7 @@ impl ShedVi {
|
|||||||
let new_cursor = span_start + candidate.len();
|
let new_cursor = span_start + candidate.len();
|
||||||
let line = self.completer.get_completed_line(&candidate);
|
let line = self.completer.get_completed_line(&candidate);
|
||||||
self.focused_editor().set_buffer(line);
|
self.focused_editor().set_buffer(line);
|
||||||
self.focused_editor().cursor.set(new_cursor);
|
self.focused_editor().set_cursor_from_flat(new_cursor);
|
||||||
// Don't reset yet — clear() needs old_layout to erase the selector.
|
// Don't reset yet — clear() needs old_layout to erase the selector.
|
||||||
|
|
||||||
if !self.history.at_pending() {
|
if !self.history.at_pending() {
|
||||||
@@ -556,7 +556,7 @@ impl ShedVi {
|
|||||||
}
|
}
|
||||||
self
|
self
|
||||||
.history
|
.history
|
||||||
.update_pending_cmd((&self.editor.joined(), self.editor.cursor.get()));
|
.update_pending_cmd((&self.editor.joined(), self.editor.cursor_to_flat()));
|
||||||
let hint = self.history.get_hint();
|
let hint = self.history.get_hint();
|
||||||
self.editor.set_hint(hint);
|
self.editor.set_hint(hint);
|
||||||
self.completer.clear(&mut self.writer)?;
|
self.completer.clear(&mut self.writer)?;
|
||||||
@@ -684,7 +684,7 @@ impl ShedVi {
|
|||||||
}
|
}
|
||||||
self
|
self
|
||||||
.history
|
.history
|
||||||
.update_pending_cmd((&self.editor.joined(), self.editor.cursor.get()));
|
.update_pending_cmd((&self.editor.joined(), self.editor.cursor_to_flat()));
|
||||||
self.needs_redraw = true;
|
self.needs_redraw = true;
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
@@ -728,14 +728,14 @@ impl ShedVi {
|
|||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
self.focused_editor().set_buffer(line.clone());
|
self.focused_editor().set_buffer(line.clone());
|
||||||
self.focused_editor().cursor.set(new_cursor);
|
self.focused_editor().set_cursor_from_flat(new_cursor);
|
||||||
|
|
||||||
if !self.history.at_pending() {
|
if !self.history.at_pending() {
|
||||||
self.history.reset_to_pending();
|
self.history.reset_to_pending();
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
.history
|
.history
|
||||||
.update_pending_cmd((&self.editor.joined(), self.editor.cursor.get()));
|
.update_pending_cmd((&self.editor.joined(), self.editor.cursor_to_flat()));
|
||||||
let hint = self.history.get_hint();
|
let hint = self.history.get_hint();
|
||||||
self.editor.set_hint(hint);
|
self.editor.set_hint(hint);
|
||||||
write_vars(|v| {
|
write_vars(|v| {
|
||||||
@@ -804,7 +804,7 @@ impl ShedVi {
|
|||||||
self.focused_editor().move_cursor_to_end();
|
self.focused_editor().move_cursor_to_end();
|
||||||
self
|
self
|
||||||
.history
|
.history
|
||||||
.update_pending_cmd((&self.editor.joined(), self.editor.cursor.get()));
|
.update_pending_cmd((&self.editor.joined(), self.editor.cursor_to_flat()));
|
||||||
self.editor.set_hint(None);
|
self.editor.set_hint(None);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@@ -880,7 +880,7 @@ impl ShedVi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.editor.set_hint(None);
|
self.editor.set_hint(None);
|
||||||
self.editor.cursor.set(self.editor.cursor_max());
|
self.editor.set_cursor_from_flat(self.editor.cursor_max());
|
||||||
self.print_line(true)?;
|
self.print_line(true)?;
|
||||||
self.writer.flush_write("\n")?;
|
self.writer.flush_write("\n")?;
|
||||||
let buf = self.editor.take_buf();
|
let buf = self.editor.take_buf();
|
||||||
@@ -931,7 +931,7 @@ impl ShedVi {
|
|||||||
if before != after {
|
if before != after {
|
||||||
self
|
self
|
||||||
.history
|
.history
|
||||||
.update_pending_cmd((&self.editor.joined(), self.editor.cursor.get()));
|
.update_pending_cmd((&self.editor.joined(), self.editor.cursor_to_flat()));
|
||||||
} else if before == after && has_edit_verb {
|
} else if before == after && has_edit_verb {
|
||||||
self.writer.send_bell().ok();
|
self.writer.send_bell().ok();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,11 +42,10 @@ struct ExEditor {
|
|||||||
|
|
||||||
impl ExEditor {
|
impl ExEditor {
|
||||||
pub fn new(history: History) -> Self {
|
pub fn new(history: History) -> Self {
|
||||||
let mut new = Self {
|
Self {
|
||||||
history,
|
history,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
}
|
||||||
new
|
|
||||||
}
|
}
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
*self = Self::default()
|
*self = Self::default()
|
||||||
@@ -169,7 +168,7 @@ impl ViMode for ViEx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn pending_cursor(&self) -> Option<usize> {
|
fn pending_cursor(&self) -> Option<usize> {
|
||||||
Some(self.pending_cmd.buf.cursor.get())
|
Some(self.pending_cmd.buf.cursor_to_flat())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_cursor_on_undo(&self) -> bool {
|
fn move_cursor_on_undo(&self) -> bool {
|
||||||
@@ -229,9 +228,6 @@ fn parse_ex_cmd(raw: &str) -> Result<Option<ViCmd>, Option<String>> {
|
|||||||
|
|
||||||
/// Unescape shell command arguments
|
/// Unescape shell command arguments
|
||||||
fn unescape_shell_cmd(cmd: &str) -> String {
|
fn unescape_shell_cmd(cmd: &str) -> String {
|
||||||
// The pest grammar uses double quotes for vicut commands
|
|
||||||
// So shell commands need to escape double quotes
|
|
||||||
// We will be removing a single layer of escaping from double quotes
|
|
||||||
let mut result = String::new();
|
let mut result = String::new();
|
||||||
let mut chars = cmd.chars().peekable();
|
let mut chars = cmd.chars().peekable();
|
||||||
while let Some(ch) = chars.next() {
|
while let Some(ch) = chars.next() {
|
||||||
|
|||||||
Reference in New Issue
Block a user