implemented support for the 'sentence' text object in the line editor
This commit is contained in:
@@ -235,6 +235,9 @@ impl ClampedUsize {
|
||||
pub fn get(self) -> usize {
|
||||
self.value
|
||||
}
|
||||
pub fn cap(&self) -> usize {
|
||||
self.max
|
||||
}
|
||||
pub fn upper_bound(&self) -> usize {
|
||||
if self.exclusive {
|
||||
self.max.saturating_sub(1)
|
||||
@@ -935,21 +938,8 @@ impl LineBuf {
|
||||
let mut closer_count: u32 = 0;
|
||||
while let Some(idx) = backward_indices.next() {
|
||||
let gr = self.grapheme_at(idx)?.to_string();
|
||||
if gr != closer && gr != opener { continue }
|
||||
if (gr != closer && gr != opener) || self.grapheme_is_escaped(idx) { continue }
|
||||
|
||||
let mut escaped = false;
|
||||
while let Some(idx) = backward_indices.next() {
|
||||
// Keep consuming indices as long as they refer to a backslash
|
||||
let Some("\\") = self.grapheme_at(idx) else {
|
||||
break
|
||||
};
|
||||
// On each backslash, flip this boolean
|
||||
escaped = !escaped
|
||||
}
|
||||
|
||||
// If there are an even number of backslashes (or none), we are not escaped
|
||||
// Therefore, we have found the start position
|
||||
if !escaped {
|
||||
if gr == closer {
|
||||
closer_count += 1;
|
||||
} else if closer_count == 0 {
|
||||
@@ -959,7 +949,6 @@ impl LineBuf {
|
||||
closer_count = closer_count.saturating_sub(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (mut start, mut end) = if let Some(pos) = start_pos {
|
||||
let start = pos;
|
||||
@@ -968,8 +957,8 @@ impl LineBuf {
|
||||
let mut opener_count: u32 = 0;
|
||||
|
||||
while let Some(idx) = forward_indices.next() {
|
||||
if self.grapheme_is_escaped(idx) { continue }
|
||||
match self.grapheme_at(idx)? {
|
||||
"\\" => { forward_indices.next(); }
|
||||
gr if gr == opener => opener_count += 1,
|
||||
gr if gr == closer => {
|
||||
if opener_count == 0 {
|
||||
@@ -991,8 +980,8 @@ impl LineBuf {
|
||||
let mut opener_count: u32 = 0;
|
||||
|
||||
while let Some(idx) = forward_indices.next() {
|
||||
if self.grapheme_is_escaped(idx) { continue }
|
||||
match self.grapheme_at(idx)? {
|
||||
"\\" => { forward_indices.next(); }
|
||||
gr if gr == opener => {
|
||||
if opener_count == 0 {
|
||||
start = Some(idx);
|
||||
@@ -1022,6 +1011,19 @@ impl LineBuf {
|
||||
Bound::Around => {
|
||||
// End excludes the quote, so push it forward
|
||||
end += 1;
|
||||
|
||||
// We also need to include any trailing whitespace
|
||||
let end_of_line = self.end_of_line();
|
||||
let remainder = end..end_of_line;
|
||||
for idx in remainder {
|
||||
let Some(gr) = self.grapheme_at(idx) else { break };
|
||||
flog!(DEBUG, gr);
|
||||
if is_whitespace(gr) {
|
||||
end += 1;
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1704,11 +1706,23 @@ impl LineBuf {
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
||||
MotionKind::Inclusive((start,end))
|
||||
TextObj::Word(_, bound) |
|
||||
TextObj::WholeSentence(bound) |
|
||||
TextObj::WholeParagraph(bound) => {
|
||||
match bound {
|
||||
Bound::Inside => MotionKind::Inclusive((start,end)),
|
||||
Bound::Around => MotionKind::Exclusive((start,end)),
|
||||
}
|
||||
}
|
||||
TextObj::DoubleQuote(_) |
|
||||
TextObj::SingleQuote(_) |
|
||||
TextObj::BacktickQuote(_) |
|
||||
TextObj::Paren(_) |
|
||||
TextObj::Bracket(_) |
|
||||
TextObj::Brace(_) |
|
||||
TextObj::Angle(_) => MotionKind::Exclusive((start,end)),
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
MotionCmd(_,Motion::ToDelimMatch) => {
|
||||
// Just ignoring the count here, it does some really weird stuff in Vim
|
||||
@@ -1927,7 +1941,7 @@ impl LineBuf {
|
||||
}
|
||||
|
||||
final_end = final_end.min(self.cursor.max);
|
||||
MotionKind::Inclusive((start,final_end))
|
||||
MotionKind::Exclusive((start,final_end))
|
||||
}
|
||||
MotionCmd(count,Motion::RepeatMotion) => todo!(),
|
||||
MotionCmd(count,Motion::RepeatMotionRev) => todo!(),
|
||||
@@ -2041,7 +2055,15 @@ impl LineBuf {
|
||||
let end = end.min(col);
|
||||
self.cursor.set(start + end)
|
||||
}
|
||||
MotionKind::Inclusive((start,end)) |
|
||||
MotionKind::Inclusive((start,end)) => {
|
||||
if self.select_range().is_none() {
|
||||
self.cursor.set(start)
|
||||
} else {
|
||||
self.cursor.set(end);
|
||||
self.select_mode = Some(SelectMode::Char(SelectAnchor::End));
|
||||
self.select_range = Some((start,end));
|
||||
}
|
||||
}
|
||||
MotionKind::Exclusive((start,end)) => {
|
||||
if self.select_range().is_none() {
|
||||
self.cursor.set(start)
|
||||
@@ -2081,11 +2103,11 @@ impl LineBuf {
|
||||
ordered(self.cursor.get(), pos)
|
||||
}
|
||||
MotionKind::InclusiveWithTargetCol((start,end),_) |
|
||||
MotionKind::Inclusive((start,end)) => ordered(*start, *end),
|
||||
MotionKind::Exclusive((start,end)) => ordered(*start, *end),
|
||||
MotionKind::ExclusiveWithTargetCol((start,end),_) |
|
||||
MotionKind::Exclusive((start,end)) => {
|
||||
MotionKind::Inclusive((start,end)) => {
|
||||
let (start, mut end) = ordered(*start, *end);
|
||||
end = end.saturating_sub(1);
|
||||
end = ClampedUsize::new(end,self.cursor.max,false).ret_add(1);
|
||||
(start,end)
|
||||
}
|
||||
MotionKind::Null => return None
|
||||
@@ -2463,7 +2485,7 @@ impl LineBuf {
|
||||
.map(|m| self.eval_motion(verb_ref.as_ref(), m))
|
||||
.unwrap_or({
|
||||
self.select_range
|
||||
.map(MotionKind::Inclusive)
|
||||
.map(MotionKind::Exclusive)
|
||||
.unwrap_or(MotionKind::Null)
|
||||
})
|
||||
};
|
||||
|
||||
@@ -941,6 +941,8 @@ impl ViNormal {
|
||||
let obj = match chars_clone.next().unwrap() {
|
||||
'w' => TextObj::Word(Word::Normal,bound),
|
||||
'W' => TextObj::Word(Word::Big,bound),
|
||||
's' => TextObj::WholeSentence(bound),
|
||||
'p' => TextObj::WholeParagraph(bound),
|
||||
'"' => TextObj::DoubleQuote(bound),
|
||||
'\'' => TextObj::SingleQuote(bound),
|
||||
'`' => TextObj::BacktickQuote(bound),
|
||||
@@ -1602,6 +1604,8 @@ impl ViVisual {
|
||||
let obj = match chars_clone.next().unwrap() {
|
||||
'w' => TextObj::Word(Word::Normal,bound),
|
||||
'W' => TextObj::Word(Word::Big,bound),
|
||||
's' => TextObj::WholeSentence(bound),
|
||||
'p' => TextObj::WholeParagraph(bound),
|
||||
'"' => TextObj::DoubleQuote(bound),
|
||||
'\'' => TextObj::SingleQuote(bound),
|
||||
'`' => TextObj::BacktickQuote(bound),
|
||||
|
||||
18
thing.md
18
thing.md
@@ -1,18 +0,0 @@
|
||||
Welcome to the vicut wiki!
|
||||
|
||||
Table of contents:
|
||||
- [🚀 Advanced Usage](https://github.com/km-clay/vicut/wiki/Advanced-Usage)
|
||||
- [🌀 Nested Repeats](https://github.com/km-clay/vicut/wiki/Advanced-Usage#-nested-repeats)
|
||||
- [🏷️ Naming Fields](https://github.com/km-clay/vicut/wiki/Advanced-Usage#%EF%B8%8F-naming-fields)
|
||||
- [🧹 Editing the Input](https://github.com/km-clay/vicut/wiki/Advanced-Usage#-editing-the-input)
|
||||
- [🎛️ Switching Modes](https://github.com/km-clay/vicut/wiki/Advanced-Usage#%EF%B8%8F-switching-modes)
|
||||
- [✍️ Insert Mode](https://github.com/km-clay/vicut/wiki/Advanced-Usage#%EF%B8%8F-insert-mode)
|
||||
- [👁️ Visual Mode](https://github.com/km-clay/vicut/wiki/Advanced-Usage#%EF%B8%8F-visual-mode)
|
||||
- [🪄 Control Sequence Aliases](https://github.com/km-clay/vicut/wiki/Control-Sequence-Aliases)
|
||||
- [🔑 Special Key Aliases](https://github.com/km-clay/vicut/wiki/Control-Sequence-Aliases#-special-key-aliases)
|
||||
- [🧩 Modifier Keys](https://github.com/km-clay/vicut/wiki/Control-Sequence-Aliases#-modifier-keys)
|
||||
- [💡 Usage Examples](https://github.com/km-clay/vicut/wiki/Usage-Examples)
|
||||
- [📡 Exhibit A: `speedtest-cli --list`](https://github.com/km-clay/vicut/wiki/Usage-Examples#-exhibit-a-speedtest-cli---list)
|
||||
- [📊 Tool Comparison](https://github.com/km-clay/vicut/wiki/Usage-Examples#-tool-comparison)
|
||||
- [🌐 Exhibit B: `nmcli dev`](https://github.com/km-clay/vicut/wiki/Usage-Examples#-exhibit-b-nmcli-dev)
|
||||
- [📊 Tool Comparison](https://github.com/km-clay/vicut/wiki/Usage-Examples#-tool-comparison-1)
|
||||
Reference in New Issue
Block a user