forked from sanbuphy/learn-coding-agent
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmotions.ts
More file actions
82 lines (77 loc) · 1.86 KB
/
motions.ts
File metadata and controls
82 lines (77 loc) · 1.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/**
* Vim Motion Functions
*
* Pure functions for resolving vim motions to cursor positions.
*/
import type { Cursor } from '../utils/Cursor.js'
/**
* Resolve a motion to a target cursor position.
* Does not modify anything - pure calculation.
*/
export function resolveMotion(
key: string,
cursor: Cursor,
count: number,
): Cursor {
let result = cursor
for (let i = 0; i < count; i++) {
const next = applySingleMotion(key, result)
if (next.equals(result)) break
result = next
}
return result
}
/**
* Apply a single motion step.
*/
function applySingleMotion(key: string, cursor: Cursor): Cursor {
switch (key) {
case 'h':
return cursor.left()
case 'l':
return cursor.right()
case 'j':
return cursor.downLogicalLine()
case 'k':
return cursor.upLogicalLine()
case 'gj':
return cursor.down()
case 'gk':
return cursor.up()
case 'w':
return cursor.nextVimWord()
case 'b':
return cursor.prevVimWord()
case 'e':
return cursor.endOfVimWord()
case 'W':
return cursor.nextWORD()
case 'B':
return cursor.prevWORD()
case 'E':
return cursor.endOfWORD()
case '0':
return cursor.startOfLogicalLine()
case '^':
return cursor.firstNonBlankInLogicalLine()
case '$':
return cursor.endOfLogicalLine()
case 'G':
return cursor.startOfLastLine()
default:
return cursor
}
}
/**
* Check if a motion is inclusive (includes character at destination).
*/
export function isInclusiveMotion(key: string): boolean {
return 'eE$'.includes(key)
}
/**
* Check if a motion is linewise (operates on full lines when used with operators).
* Note: gj/gk are characterwise exclusive per `:help gj`, not linewise.
*/
export function isLinewiseMotion(key: string): boolean {
return 'jkG'.includes(key) || key === 'gg'
}