motions.ts
vim/motions.ts
No strong subsystem tag
83
Lines
1902
Bytes
3
Exports
1
Imports
10
Keywords
What this is
This page documents one file from the repository and includes its full source so you can read it without leaving the docs site.
Beginner explanation
This file is one piece of the larger system. Its name, directory, imports, and exports show where it fits. Start by reading the exports and related files first.
How it is used
Start from the exports list and related files. Those are the easiest clues for where this file fits into the system.
Expert explanation
Architecturally, this file intersects with general runtime concerns. It contains 83 lines, 1 detected imports, and 3 detected exports.
Important relationships
Detected exports
resolveMotionisInclusiveMotionisLinewiseMotion
Keywords
cursorcasemotionresultnextincludesfunctionspurecountapplysinglemotion
Detected imports
../utils/Cursor.js
Source notes
This page embeds the full file contents. Small or leaf files are still indexed honestly instead of being over-explained.
Full source
/**
* 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'
}