mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-21 18:05:11 +00:00
Fix snake border alignment using visibleWidth for proper ANSI length calculation
This commit is contained in:
parent
b47151a04f
commit
6977bc73ca
1 changed files with 7 additions and 12 deletions
|
|
@ -2,7 +2,7 @@
|
||||||
* Snake game hook - play snake with /snake command
|
* Snake game hook - play snake with /snake command
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { isArrowDown, isArrowLeft, isArrowRight, isArrowUp, isEscape } from "@mariozechner/pi-tui";
|
import { isArrowDown, isArrowLeft, isArrowRight, isArrowUp, isEscape, visibleWidth } from "@mariozechner/pi-tui";
|
||||||
import type { HookAPI } from "../../src/core/hooks/types.js";
|
import type { HookAPI } from "../../src/core/hooks/types.js";
|
||||||
|
|
||||||
const GAME_WIDTH = 40;
|
const GAME_WIDTH = 40;
|
||||||
|
|
@ -226,7 +226,8 @@ class SnakeComponent {
|
||||||
const boxWidth = effectiveWidth * cellWidth;
|
const boxWidth = effectiveWidth * cellWidth;
|
||||||
|
|
||||||
// Helper to pad content inside box
|
// Helper to pad content inside box
|
||||||
const boxLine = (content: string, contentLen: number) => {
|
const boxLine = (content: string) => {
|
||||||
|
const contentLen = visibleWidth(content);
|
||||||
const padding = Math.max(0, boxWidth - contentLen);
|
const padding = Math.max(0, boxWidth - contentLen);
|
||||||
return dim(" │") + content + " ".repeat(padding) + dim("│");
|
return dim(" │") + content + " ".repeat(padding) + dim("│");
|
||||||
};
|
};
|
||||||
|
|
@ -237,10 +238,8 @@ class SnakeComponent {
|
||||||
// Header with score
|
// Header with score
|
||||||
const scoreText = `Score: ${bold(yellow(String(this.state.score)))}`;
|
const scoreText = `Score: ${bold(yellow(String(this.state.score)))}`;
|
||||||
const highText = `High: ${bold(yellow(String(this.state.highScore)))}`;
|
const highText = `High: ${bold(yellow(String(this.state.highScore)))}`;
|
||||||
const title = `${bold(green("🐍 SNAKE"))} │ ${scoreText} │ ${highText}`;
|
const title = `${bold(green("SNAKE"))} │ ${scoreText} │ ${highText}`;
|
||||||
// Approximate visible length (emojis and formatting make this tricky)
|
lines.push(this.padLine(boxLine(title), width));
|
||||||
const titleLen = 8 + 3 + 7 + String(this.state.score).length + 3 + 6 + String(this.state.highScore).length;
|
|
||||||
lines.push(this.padLine(boxLine(title, titleLen), width));
|
|
||||||
|
|
||||||
// Separator
|
// Separator
|
||||||
lines.push(this.padLine(dim(` ├${"─".repeat(boxWidth)}┤`), width));
|
lines.push(this.padLine(dim(` ├${"─".repeat(boxWidth)}┤`), width));
|
||||||
|
|
@ -271,18 +270,14 @@ class SnakeComponent {
|
||||||
|
|
||||||
// Footer
|
// Footer
|
||||||
let footer: string;
|
let footer: string;
|
||||||
let footerLen: number;
|
|
||||||
if (this.paused) {
|
if (this.paused) {
|
||||||
footer = `${yellow(bold("PAUSED"))} Press any key to continue, ${bold("Q")} to quit`;
|
footer = `${yellow(bold("PAUSED"))} Press any key to continue, ${bold("Q")} to quit`;
|
||||||
footerLen = 42;
|
|
||||||
} else if (this.state.gameOver) {
|
} else if (this.state.gameOver) {
|
||||||
footer = `${red(bold("GAME OVER!"))} Press ${bold("R")} to restart, ${bold("Q")} to quit`;
|
footer = `${red(bold("GAME OVER!"))} Press ${bold("R")} to restart, ${bold("Q")} to quit`;
|
||||||
footerLen = 40;
|
|
||||||
} else {
|
} else {
|
||||||
footer = dim(`↑↓←→ or WASD to move, ${bold("ESC")} pause, ${bold("Q")} quit`);
|
footer = `↑↓←→ or WASD to move, ${bold("ESC")} pause, ${bold("Q")} quit`;
|
||||||
footerLen = 38;
|
|
||||||
}
|
}
|
||||||
lines.push(this.padLine(boxLine(footer, footerLen), width));
|
lines.push(this.padLine(boxLine(footer), width));
|
||||||
|
|
||||||
// Bottom border
|
// Bottom border
|
||||||
lines.push(this.padLine(dim(` ╰${"─".repeat(boxWidth)}╯`), width));
|
lines.push(this.padLine(dim(` ╰${"─".repeat(boxWidth)}╯`), width));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue