feat: implemented E and W, last is B, tested
This commit is contained in:
parent
b7234b4639
commit
37ad0ecb2b
@ -12,8 +12,8 @@
|
|||||||
- [x] `w` - Forward to start of word
|
- [x] `w` - Forward to start of word
|
||||||
- [x] `e` - Forward to end of word
|
- [x] `e` - Forward to end of word
|
||||||
- [x] `b` - Backward to start of word
|
- [x] `b` - Backward to start of word
|
||||||
- [ ] `W` - Forward to start of WORD (whitespace-delimited)
|
- [x] `W` - Forward to start of WORD (whitespace-delimited)
|
||||||
- [ ] `E` - Forward to end of WORD
|
- [x] `E` - Forward to end of WORD
|
||||||
- [ ] `B` - Backward to start of WORD
|
- [ ] `B` - Backward to start of WORD
|
||||||
- [ ] `ge` - Backward to end of word
|
- [ ] `ge` - Backward to end of word
|
||||||
|
|
||||||
@ -22,7 +22,7 @@
|
|||||||
- [x] `$` - Move to end of line
|
- [x] `$` - Move to end of line
|
||||||
- [x] `_` - Move to first non-whitespace
|
- [x] `_` - Move to first non-whitespace
|
||||||
- [x] `^` - Move to first non-whitespace (alias for `_`)
|
- [x] `^` - Move to first non-whitespace (alias for `_`)
|
||||||
- [ ] `|` - Move to column N
|
- [x] `|` - Move to column N
|
||||||
|
|
||||||
### File Movement
|
### File Movement
|
||||||
- [x] `G` - Move to bottom of file (or line N with count)
|
- [x] `G` - Move to bottom of file (or line N with count)
|
||||||
@ -410,7 +410,7 @@ Buffers are in-memory representations of files. A buffer exists for each open fi
|
|||||||
### Well Tested
|
### Well Tested
|
||||||
- [x] Basic motions (h, j, k, l)
|
- [x] Basic motions (h, j, k, l)
|
||||||
- [x] Word motions (w, e, b)
|
- [x] Word motions (w, e, b)
|
||||||
- [x] Jump motions (G, gg, 0, $, _, ^)
|
- [x] Jump motions (G, gg, 0, $, _, ^, |)
|
||||||
- [x] Scroll actions (ctrl+u, ctrl+d)
|
- [x] Scroll actions (ctrl+u, ctrl+d)
|
||||||
- [x] Delete operator (d, dd)
|
- [x] Delete operator (d, dd)
|
||||||
- [x] Yank operator (y, yy)
|
- [x] Yank operator (y, yy)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -28,7 +28,9 @@ func NewNormalKeymap() *Keymap {
|
|||||||
"^": motion.MoveToLineContentStart{},
|
"^": motion.MoveToLineContentStart{},
|
||||||
"|": motion.MoveToColumn{Count: 0},
|
"|": motion.MoveToColumn{Count: 0},
|
||||||
"w": motion.MoveForwardWord{Count: 1},
|
"w": motion.MoveForwardWord{Count: 1},
|
||||||
|
"W": motion.MoveForwardWORD{Count: 1},
|
||||||
"e": motion.MoveForwardWordEnd{Count: 1},
|
"e": motion.MoveForwardWordEnd{Count: 1},
|
||||||
|
"E": motion.MoveForwardWORDEnd{Count: 1},
|
||||||
"b": motion.MoveBackwardWord{Count: 1},
|
"b": motion.MoveBackwardWord{Count: 1},
|
||||||
"ctrl+u": motion.ScrollUpHalfPage{},
|
"ctrl+u": motion.ScrollUpHalfPage{},
|
||||||
"ctrl+d": motion.ScrollDownHalfPage{},
|
"ctrl+d": motion.ScrollDownHalfPage{},
|
||||||
@ -74,7 +76,9 @@ func NewVisualKeymap() *Keymap {
|
|||||||
"^": motion.MoveToLineContentStart{},
|
"^": motion.MoveToLineContentStart{},
|
||||||
"|": motion.MoveToColumn{Count: 0},
|
"|": motion.MoveToColumn{Count: 0},
|
||||||
"w": motion.MoveForwardWord{Count: 1},
|
"w": motion.MoveForwardWord{Count: 1},
|
||||||
|
"W": motion.MoveForwardWORD{Count: 1},
|
||||||
"e": motion.MoveForwardWordEnd{Count: 1},
|
"e": motion.MoveForwardWordEnd{Count: 1},
|
||||||
|
"E": motion.MoveForwardWORDEnd{Count: 1},
|
||||||
"b": motion.MoveBackwardWord{Count: 1},
|
"b": motion.MoveBackwardWord{Count: 1},
|
||||||
},
|
},
|
||||||
operators: map[string]action.Operator{
|
operators: map[string]action.Operator{
|
||||||
|
|||||||
@ -64,6 +64,45 @@ func nextWordStart(m action.Model, x, y int) (int, int) {
|
|||||||
return x, y
|
return x, y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func nextWORDStart(m action.Model, x, y int) (int, int) {
|
||||||
|
line := m.Line(y)
|
||||||
|
|
||||||
|
// Skip current WORD (all non-whitespace is one class for W)
|
||||||
|
for x < len(line) && line[x] != ' ' && line[x] != '\t' {
|
||||||
|
x++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip whitespace and cross lines if needed
|
||||||
|
for {
|
||||||
|
// Walk over white space
|
||||||
|
for x < len(line) && (line[x] == ' ' || line[x] == '\t') {
|
||||||
|
x++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Were on the new word, nothing else to do (no lines to cross
|
||||||
|
if x < len(line) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// If next line is the end of the file, exit now
|
||||||
|
if y+1 >= m.LineCount() {
|
||||||
|
return x, y
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move to first char of next line
|
||||||
|
y++
|
||||||
|
line = m.Line(y)
|
||||||
|
x = 0
|
||||||
|
|
||||||
|
// If the first char of the new line is no whitespace, stay here!
|
||||||
|
if len(line) > 0 && line[0] != ' ' && line[0] != '\t' {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return x, y
|
||||||
|
}
|
||||||
|
|
||||||
func nextWordEnd(m action.Model, x, y int) (int, int) {
|
func nextWordEnd(m action.Model, x, y int) (int, int) {
|
||||||
line := m.Line(y)
|
line := m.Line(y)
|
||||||
|
|
||||||
@ -121,6 +160,54 @@ func nextWordEnd(m action.Model, x, y int) (int, int) {
|
|||||||
return x, y
|
return x, y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func nextWORDEnd(m action.Model, x, y int) (int, int) {
|
||||||
|
line := m.Line(y)
|
||||||
|
|
||||||
|
// Advance once to avoid being stuck on the current end
|
||||||
|
x++
|
||||||
|
if x >= len(line) {
|
||||||
|
// At last line of file, pin cursor to end of file
|
||||||
|
if y+1 >= m.LineCount() {
|
||||||
|
return len(line) - 1, y
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, move to next line
|
||||||
|
y++
|
||||||
|
x = 0
|
||||||
|
line = m.Line(y)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip whitespace and cross lines if needed
|
||||||
|
for {
|
||||||
|
// Walk over white space
|
||||||
|
for x < len(line) && (line[x] == ' ' || line[x] == '\t') {
|
||||||
|
x++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Were on the new word, nothing else to do (no lines to cross
|
||||||
|
if x < len(line) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// If next line is the end of the file, exit now
|
||||||
|
if y+1 >= m.LineCount() {
|
||||||
|
return x, y
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move to first char of next line
|
||||||
|
y++
|
||||||
|
line = m.Line(y)
|
||||||
|
x = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move to end of current WORD (all non-whitespace is one class)
|
||||||
|
for x+1 < len(line) && line[x+1] != ' ' && line[x+1] != '\t' {
|
||||||
|
x++
|
||||||
|
}
|
||||||
|
|
||||||
|
return x, y
|
||||||
|
}
|
||||||
|
|
||||||
func prevWordStart(m action.Model, x, y int) (int, int) {
|
func prevWordStart(m action.Model, x, y int) (int, int) {
|
||||||
line := m.Line(y)
|
line := m.Line(y)
|
||||||
|
|
||||||
@ -193,6 +280,28 @@ func (a MoveForwardWord) WithCount(n int) action.Action {
|
|||||||
return MoveForwardWord{Count: n}
|
return MoveForwardWord{Count: n}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MoveForwardWORD implements Motion (W) - charwise
|
||||||
|
type MoveForwardWORD struct {
|
||||||
|
Count int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a MoveForwardWORD) Execute(m action.Model) tea.Cmd {
|
||||||
|
x := m.CursorX()
|
||||||
|
y := m.CursorY()
|
||||||
|
for i := 0; i < a.Count; i++ {
|
||||||
|
x, y = nextWORDStart(m, x, y)
|
||||||
|
}
|
||||||
|
m.SetCursorX(x)
|
||||||
|
m.SetCursorY(y)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a MoveForwardWORD) Type() action.MotionType { return action.CharwiseExclusive }
|
||||||
|
|
||||||
|
func (a MoveForwardWORD) WithCount(n int) action.Action {
|
||||||
|
return MoveForwardWORD{Count: n}
|
||||||
|
}
|
||||||
|
|
||||||
// MoveForwardWordEnd implements Motion (e) - charwise
|
// MoveForwardWordEnd implements Motion (e) - charwise
|
||||||
type MoveForwardWordEnd struct {
|
type MoveForwardWordEnd struct {
|
||||||
Count int
|
Count int
|
||||||
@ -215,6 +324,28 @@ func (a MoveForwardWordEnd) WithCount(n int) action.Action {
|
|||||||
return MoveForwardWordEnd{Count: n}
|
return MoveForwardWordEnd{Count: n}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MoveForwardWORDEnd implements Motion (E) - charwise
|
||||||
|
type MoveForwardWORDEnd struct {
|
||||||
|
Count int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a MoveForwardWORDEnd) Execute(m action.Model) tea.Cmd {
|
||||||
|
x := m.CursorX()
|
||||||
|
y := m.CursorY()
|
||||||
|
for i := 0; i < a.Count; i++ {
|
||||||
|
x, y = nextWORDEnd(m, x, y)
|
||||||
|
}
|
||||||
|
m.SetCursorX(x)
|
||||||
|
m.SetCursorY(y)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a MoveForwardWORDEnd) Type() action.MotionType { return action.CharwiseInclusive }
|
||||||
|
|
||||||
|
func (a MoveForwardWORDEnd) WithCount(n int) action.Action {
|
||||||
|
return MoveForwardWORDEnd{Count: n}
|
||||||
|
}
|
||||||
|
|
||||||
// MoveBackwardWord implements Motion (b) - charwise
|
// MoveBackwardWord implements Motion (b) - charwise
|
||||||
type MoveBackwardWord struct {
|
type MoveBackwardWord struct {
|
||||||
Count int
|
Count int
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user