0 works both ways now
This commit is contained in:
+7
-6
@@ -90,12 +90,13 @@ export type CursorManager = {
|
|||||||
moveToTop: () => void;
|
moveToTop: () => void;
|
||||||
moveToBottom: () => void;
|
moveToBottom: () => void;
|
||||||
repeatLastMotion: () => void;
|
repeatLastMotion: () => void;
|
||||||
resetCount: () => void;
|
resetCount: () => void;
|
||||||
getCount: () => string;
|
getCount: () => string;
|
||||||
setCount: (digit: string) => void;
|
hasCount: () => boolean;
|
||||||
setLastKey: (key: string) => void;
|
setCount: (digit: string) => void;
|
||||||
getLastKey: () => string;
|
setLastKey: (key: string) => void;
|
||||||
hero?: UseHeroType;
|
getLastKey: () => string;
|
||||||
|
hero?: UseHeroType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type HeroManager = {
|
export type HeroManager = {
|
||||||
|
|||||||
+79
-74
@@ -78,61 +78,61 @@ export function useCursor(board: BoardManager, gameStatusManager: GameStatusMana
|
|||||||
move(0, 1, count);
|
move(0, 1, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveToAnchor(target: 'start' | 'end' | 'top' | 'bottom'): void {
|
function moveToAnchor(target: 'start' | 'end' | 'top' | 'bottom'): void {
|
||||||
const currentPos = position.current;
|
const currentPos = position.current;
|
||||||
const direction = target === 'start' ? 'left' :
|
const direction = target === 'start' ? 'left' :
|
||||||
target === 'end' ? 'right' :
|
target === 'end' ? 'right' :
|
||||||
target === 'top' ? 'top' : 'bottom';
|
target === 'top' ? 'top' : 'bottom';
|
||||||
|
|
||||||
const anchorTarget = navigator.findAnchorTarget(currentPos, direction);
|
const anchorTarget = navigator.findAnchorTarget(currentPos, direction);
|
||||||
if (!anchorTarget) return;
|
if (!anchorTarget) return;
|
||||||
|
|
||||||
const dr = anchorTarget.row > currentPos.row ? 1 :
|
const dr = anchorTarget.row > currentPos.row ? 1 :
|
||||||
anchorTarget.row < currentPos.row ? -1 : 0;
|
anchorTarget.row < currentPos.row ? -1 : 0;
|
||||||
const dc = anchorTarget.col > currentPos.col ? 1 :
|
const dc = anchorTarget.col > currentPos.col ? 1 :
|
||||||
anchorTarget.col < currentPos.col ? -1 : 0;
|
anchorTarget.col < currentPos.col ? -1 : 0;
|
||||||
const steps = Math.abs(anchorTarget.row - currentPos.row) + Math.abs(anchorTarget.col - currentPos.col);
|
const steps = Math.abs(anchorTarget.row - currentPos.row) + Math.abs(anchorTarget.col - currentPos.col);
|
||||||
|
|
||||||
position.current = anchorTarget;
|
position.current = anchorTarget;
|
||||||
if (hero && hero.heroPos) {
|
if (hero && hero.heroPos) {
|
||||||
hero.moveTo(anchorTarget);
|
hero.moveTo(anchorTarget);
|
||||||
if (steps > 0) {
|
if (steps > 0) {
|
||||||
vimMotions.setLastMotion({ dr, dc, steps });
|
vimMotions.setLastMotion({ dr, dc, steps });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveToStart(): void {
|
function moveToStart(): void {
|
||||||
if (!validateAnchorMove('start', position.current, board)) {
|
if (!validateAnchorMove('start', position.current, board)) {
|
||||||
window.dispatchEvent(new Event("maze-invalid"));
|
window.dispatchEvent(new Event("maze-invalid"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
moveToAnchor('start');
|
moveToAnchor('start');
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveToEnd(): void {
|
function moveToEnd(): void {
|
||||||
if (!validateAnchorMove('end', position.current, board)) {
|
if (!validateAnchorMove('end', position.current, board)) {
|
||||||
window.dispatchEvent(new Event("maze-invalid"));
|
window.dispatchEvent(new Event("maze-invalid"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
moveToAnchor('end');
|
moveToAnchor('end');
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveToTop(): void {
|
function moveToTop(): void {
|
||||||
if (!validateAnchorMove('top', position.current, board)) {
|
if (!validateAnchorMove('top', position.current, board)) {
|
||||||
window.dispatchEvent(new Event("maze-invalid"));
|
window.dispatchEvent(new Event("maze-invalid"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
moveToAnchor('top');
|
moveToAnchor('top');
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveToBottom(): void {
|
function moveToBottom(): void {
|
||||||
if (!validateAnchorMove('bottom', position.current, board)) {
|
if (!validateAnchorMove('bottom', position.current, board)) {
|
||||||
window.dispatchEvent(new Event("maze-invalid"));
|
window.dispatchEvent(new Event("maze-invalid"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
moveToAnchor('bottom');
|
moveToAnchor('bottom');
|
||||||
}
|
}
|
||||||
|
|
||||||
function repeatLastMotion(): void {
|
function repeatLastMotion(): void {
|
||||||
const motion = vimMotions.repeatLastMotion();
|
const motion = vimMotions.repeatLastMotion();
|
||||||
@@ -156,13 +156,17 @@ export function useCursor(board: BoardManager, gameStatusManager: GameStatusMana
|
|||||||
vimMotions.resetCount();
|
vimMotions.resetCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCount(): string {
|
function getCount(): string {
|
||||||
return String(vimMotions.getCount());
|
return String(vimMotions.getCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCount(digit: string): void {
|
function hasCount(): boolean {
|
||||||
vimMotions.processKey(digit);
|
return vimMotions.hasCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setCount(digit: string): void {
|
||||||
|
vimMotions.processKey(digit);
|
||||||
|
}
|
||||||
|
|
||||||
function setLastKey(key: string): void {
|
function setLastKey(key: string): void {
|
||||||
lastKeyRef.current = key;
|
lastKeyRef.current = key;
|
||||||
@@ -172,26 +176,27 @@ export function useCursor(board: BoardManager, gameStatusManager: GameStatusMana
|
|||||||
return lastKeyRef.current;
|
return lastKeyRef.current;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cursor = {
|
const cursor = {
|
||||||
position: () => position.current,
|
position: () => position.current,
|
||||||
mode: () => mode.current,
|
mode: () => mode.current,
|
||||||
move,
|
move,
|
||||||
moveLeft,
|
moveLeft,
|
||||||
moveRight,
|
moveRight,
|
||||||
moveUp,
|
moveUp,
|
||||||
moveDown,
|
moveDown,
|
||||||
moveToStart,
|
moveToStart,
|
||||||
moveToEnd,
|
moveToEnd,
|
||||||
moveToTop,
|
moveToTop,
|
||||||
moveToBottom,
|
moveToBottom,
|
||||||
repeatLastMotion,
|
repeatLastMotion,
|
||||||
resetCount,
|
resetCount,
|
||||||
getCount,
|
getCount,
|
||||||
setCount,
|
hasCount,
|
||||||
setLastKey,
|
setCount,
|
||||||
getLastKey,
|
setLastKey,
|
||||||
hero,
|
getLastKey,
|
||||||
}
|
hero,
|
||||||
|
}
|
||||||
|
|
||||||
const keyManager = useGameKeys({ cursor, gameStatusManager });
|
const keyManager = useGameKeys({ cursor, gameStatusManager });
|
||||||
|
|
||||||
|
|||||||
@@ -34,17 +34,15 @@ export const useGameKeys = (props: UseGameKeysParams) => {
|
|||||||
const handler = (ev: KeyboardEvent) => {
|
const handler = (ev: KeyboardEvent) => {
|
||||||
if (["waiting", "game-over", "game-won"].includes(gameStatus)) return;
|
if (["waiting", "game-over", "game-won"].includes(gameStatus)) return;
|
||||||
|
|
||||||
// "0" behaves like Vim: beginning of line
|
if (ev.key === "0" && !cursor.hasCount()) {
|
||||||
if (ev.key === "0" && cursor.getCount() === "") {
|
recordKey("0");
|
||||||
recordKey("0");
|
cursor.resetCount();
|
||||||
cursor.resetCount();
|
cursor.moveToStart();
|
||||||
cursor.moveToStart();
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const isDigit = ev.key >= "0" && ev.key <= "9";
|
const isDigit = ev.key >= "0" && ev.key <= "9";
|
||||||
if (isDigit) {
|
if (isDigit) {
|
||||||
if (ev.key === "0" && cursor.getCount() === "") return;
|
|
||||||
recordKey(ev.key);
|
recordKey(ev.key);
|
||||||
cursor.setCount(ev.key);
|
cursor.setCount(ev.key);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export type VimMotionSystem = {
|
|||||||
processKey: (key: string) => { type: 'move'|'anchor'|'repeat'|'count', data: any } | null;
|
processKey: (key: string) => { type: 'move'|'anchor'|'repeat'|'count', data: any } | null;
|
||||||
resetCount: () => void;
|
resetCount: () => void;
|
||||||
getCount: () => number;
|
getCount: () => number;
|
||||||
|
hasCount: () => boolean;
|
||||||
setLastMotion: (motion: Motion) => void;
|
setLastMotion: (motion: Motion) => void;
|
||||||
repeatLastMotion: () => Motion | null;
|
repeatLastMotion: () => Motion | null;
|
||||||
};
|
};
|
||||||
@@ -98,10 +99,15 @@ export function useVimMotions(): VimMotionSystem {
|
|||||||
return lastMotionRef.current;
|
return lastMotionRef.current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hasCount(): boolean {
|
||||||
|
return countRef.current !== '';
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
processKey,
|
processKey,
|
||||||
resetCount,
|
resetCount,
|
||||||
getCount,
|
getCount,
|
||||||
|
hasCount,
|
||||||
setLastMotion,
|
setLastMotion,
|
||||||
repeatLastMotion
|
repeatLastMotion
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user