Skip to content

Commit c1acaca

Browse files
Error Handling, Documentation and More (#30)
2 parents 7dab71f + bef206c commit c1acaca

File tree

18 files changed

+422
-65
lines changed

18 files changed

+422
-65
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
"@labcatr/labcommitr": patch
3+
---
4+
5+
fix: include emoji placeholder in generated config template
6+
7+
- Add {emoji} placeholder to template in buildConfig function
8+
- Generated configs now include {emoji} in format.template field
9+
- Fixes issue where emojis didn't appear in commits even when enabled
10+
- Template now matches default config structure with emoji support
11+
- Ensures formatCommitMessage can properly replace emoji placeholder
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
"@labcatr/labcommitr": patch
3+
---
4+
5+
fix: show actual commit message with emojis in preview
6+
7+
- Preview now displays the exact commit message as it will be stored in Git
8+
- Removed emoji stripping from preview display logic
9+
- Users can see emojis even if terminal doesn't support emoji display
10+
- Ensures preview accurately reflects what will be committed to Git/GitHub
11+
- Fixes issue where emojis were hidden in preview on non-emoji terminals
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
"@labcatr/labcommitr": minor
3+
---
4+
5+
feat: implement terminal emoji detection and display adaptation
6+
7+
- Add emoji detection utility with industry-standard heuristics (CI, TERM, NO_COLOR, Windows Terminal)
8+
- Implement automatic emoji stripping for non-emoji terminals in Labcommitr UI
9+
- Always store Unicode emojis in Git commits regardless of terminal support
10+
- Update commit, preview, and revert commands to adapt display based on terminal capabilities
11+
- Ensure GitHub and emoji-capable terminals always show emojis correctly
12+
- Improve user experience by cleaning up broken emoji symbols on non-emoji terminals

.npmignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ docs/
2424

2525
# Exclude build artifacts
2626
*.map
27+
**/*.map
28+
dist/**/*.map
2729
tsconfig.json
2830
.prettierrc*
2931

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# @labcatr/labcommitr
22

3-
## 0.2.0
3+
## 0.3.0
44

55
### Minor Changes
66

README.md

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,8 @@ See [`docs/CONFIG_SCHEMA.md`](docs/CONFIG_SCHEMA.md) for complete configuration
316316
**Configuration discovery:**
317317

318318
- Searches from current directory up to project root
319-
- Falls back to global configuration if available
320319
- Uses sensible defaults if no configuration found
320+
- Global configuration support is planned for future releases (see [Planned Features](#planned-features))
321321

322322
---
323323

@@ -404,10 +404,6 @@ Before implementing any changes, please follow this process:
404404
- Follow the project's development guidelines
405405
- Ensure your commits follow the project's commit message format (you can set up using `lab init`)
406406

407-
### Development Guidelines
408-
409-
For detailed development guidelines, coding standards, and architecture information, see [`docs/DEVELOPMENT_GUIDELINES.md`](docs/DEVELOPMENT_GUIDELINES.md).
410-
411407
### Questions?
412408

413409
If you have questions or need clarification, feel free to open a discussion or issue.
@@ -416,4 +412,27 @@ If you have questions or need clarification, feel free to open a discussion or i
416412

417413
## Planned Features
418414

419-
_No planned features at this time. Check back later or open an issue to suggest new features!_
415+
### Global Configuration
416+
417+
Support for user-level global configuration files to enable consistent commit conventions across multiple projects. This will allow you to:
418+
419+
- Set default commit types and preferences in a single location
420+
- Apply your preferred commit conventions to all projects automatically
421+
- Override global settings on a per-project basis when needed
422+
423+
**Use cases:**
424+
425+
- Developers working across multiple repositories who want consistent commit message formats
426+
- Teams that want to standardize commit conventions organization-wide
427+
- Personal projects where you want the same commit types everywhere
428+
429+
The global configuration will be stored in OS-specific locations:
430+
431+
- **macOS/Linux**: `~/.labcommitr.config.yaml` or XDG config directory
432+
- **Windows**: `%USERPROFILE%\.labcommitr.config.yaml` or AppData directory
433+
434+
Project-specific configurations will always take precedence over global settings.
435+
436+
---
437+
438+
_Have a feature idea? Open an issue to suggest new features!_

package.json

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
{
22
"name": "@labcatr/labcommitr",
3-
"version": "0.2.0",
3+
"version": "0.3.0",
44
"description": "Labcommitr is a solution for building standardized git commits, hassle-free!",
55
"main": "dist/index.js",
66
"scripts": {
77
"test": "echo \"Error: no test specified\" && exit 1",
88
"build": "npx tsc",
9+
"build:prod": "npx tsc && pnpm run clean:maps",
10+
"clean:maps": "node scripts/clean-maps.js",
911
"format": "pnpm run format:code",
1012
"format:ci": "pnpm run format:code",
1113
"format:code": "prettier -w \"**/*\" --ignore-unknown --cache",
1214
"version": "changeset version && pnpm install --no-frozen-lockfile && pnpm run format",
13-
"dev:cli": "node dist/index-dev.js"
15+
"dev:cli": "node dist/index-dev.js",
16+
"prepublishOnly": "pnpm run build:prod"
1417
},
1518
"type": "module",
1619
"bin": {
@@ -29,6 +32,9 @@
2932
"homepage": "https://github.com/labcatr/labcommitr#readme",
3033
"author": "Trevor Fox",
3134
"license": "ISC",
35+
"engines": {
36+
"node": ">=18.0.0"
37+
},
3238
"dependencies": {
3339
"@changesets/cli": "^2.29.7",
3440
"@clack/prompts": "^0.11.0",
@@ -56,7 +62,10 @@
5662
"dist/cli/commands/revert",
5763
"dist/cli/commands/shared",
5864
"dist/cli/utils",
59-
"dist/lib"
65+
"dist/lib",
66+
"README.md",
67+
"CHANGELOG.md",
68+
"TESTING.md"
6069
],
6170
"publishConfig": {
6271
"access": "public"

scripts/clean-maps.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* Remove all .map files from dist directory
5+
* Cross-platform solution for cleaning source maps before publishing
6+
*/
7+
8+
import { readdir, stat, unlink } from "fs/promises";
9+
import { join } from "path";
10+
11+
async function removeMaps(dir) {
12+
try {
13+
const entries = await readdir(dir, { withFileTypes: true });
14+
15+
for (const entry of entries) {
16+
const fullPath = join(dir, entry.name);
17+
18+
if (entry.isDirectory()) {
19+
await removeMaps(fullPath);
20+
} else if (entry.isFile() && entry.name.endsWith(".map")) {
21+
await unlink(fullPath);
22+
console.log(`Removed: ${fullPath}`);
23+
}
24+
}
25+
} catch (error) {
26+
if (error.code !== "ENOENT") {
27+
throw error;
28+
}
29+
}
30+
}
31+
32+
const distDir = join(process.cwd(), "dist");
33+
removeMaps(distDir).catch((error) => {
34+
console.error("Error removing source maps:", error);
35+
process.exit(1);
36+
});

src/cli/commands/commit/editor.ts

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,75 @@ import {
1111
unlinkSync,
1212
mkdtempSync,
1313
rmdirSync,
14+
accessSync,
15+
constants,
1416
} from "fs";
1517
import { join, dirname } from "path";
16-
import { tmpdir } from "os";
18+
import { tmpdir, platform } from "os";
1719
import { Logger } from "../../../lib/logger.js";
1820

21+
/**
22+
* Cross-platform command resolver
23+
* On Windows: uses 'where' command
24+
* On Unix: uses 'which' command
25+
*
26+
* @param command - Command name to find
27+
* @returns Full path to command or null if not found
28+
*/
29+
function findCommand(command: string): string | null {
30+
const isWindows = platform() === "win32";
31+
const findCommand = isWindows ? "where" : "which";
32+
33+
try {
34+
const result = spawnSync(findCommand, [command], {
35+
encoding: "utf-8",
36+
stdio: ["ignore", "pipe", "ignore"],
37+
});
38+
39+
if (result.status === 0 && result.stdout) {
40+
// On Windows, 'where' may return multiple paths, take the first one
41+
const path = result.stdout.trim().split("\n")[0].trim();
42+
return path || null;
43+
}
44+
} catch {
45+
// Command not found or error occurred
46+
}
47+
48+
return null;
49+
}
50+
1951
/**
2052
* Detect available editor in priority order: nvim → vim → vi
2153
* Also checks $EDITOR and $VISUAL environment variables
54+
* Cross-platform: works on Windows, macOS, and Linux
2255
*/
2356
export function detectEditor(): string | null {
2457
// Check environment variables first (user preference)
2558
const envEditor = process.env.EDITOR || process.env.VISUAL;
2659
if (envEditor) {
27-
// Verify the editor exists
28-
const check = spawnSync("which", [envEditor], { encoding: "utf-8" });
29-
if (check.status === 0) {
30-
return envEditor.trim();
60+
// If it's already a full path, verify it exists
61+
if (envEditor.includes("/") || envEditor.includes("\\")) {
62+
try {
63+
accessSync(envEditor, constants.F_OK);
64+
return envEditor.trim();
65+
} catch {
66+
// Path doesn't exist, try to find it as a command
67+
}
68+
}
69+
70+
// Try to find it as a command in PATH
71+
const found = findCommand(envEditor);
72+
if (found) {
73+
return found;
3174
}
3275
}
3376

3477
// Try nvim, vim, vi in order
3578
const editors = ["nvim", "vim", "vi"];
3679
for (const editor of editors) {
37-
const check = spawnSync("which", [editor], { encoding: "utf-8" });
38-
if (check.status === 0) {
39-
return editor;
80+
const found = findCommand(editor);
81+
if (found) {
82+
return found;
4083
}
4184
}
4285

@@ -58,9 +101,11 @@ export function editInEditor(
58101

59102
if (!editorCommand) {
60103
Logger.error("No editor found");
104+
const isWindows = platform() === "win32";
105+
const envVar = isWindows ? "%EDITOR%" : "$EDITOR";
61106
console.error("\n No editor available (nvim, vim, or vi)");
62107
console.error(
63-
" Set $EDITOR environment variable to your preferred editor\n",
108+
` Set ${envVar} environment variable to your preferred editor\n`,
64109
);
65110
return null;
66111
}

src/cli/commands/commit/index.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import { loadConfig, ConfigError } from "../../../lib/config/index.js";
1515
import type { LabcommitrConfig } from "../../../lib/config/types.js";
1616
import { Logger } from "../../../lib/logger.js";
17+
import { formatForDisplay } from "../../../lib/util/emoji.js";
1718
import { isGitRepository } from "./git.js";
1819
import {
1920
stageAllTrackedFiles,
@@ -193,6 +194,7 @@ export async function commitAction(options: {
193194
}
194195

195196
const config = configResult.config;
197+
const emojiModeActive = configResult.emojiModeActive;
196198

197199
// Step 2: Verify git repository
198200
if (!isGitRepository()) {
@@ -353,7 +355,11 @@ export async function commitAction(options: {
353355
);
354356

355357
console.log(`${success("✓")} Commit created successfully!`);
356-
console.log(` ${commitHash} ${formattedMessage}`);
358+
const displayMessage = formatForDisplay(
359+
formattedMessage,
360+
emojiModeActive,
361+
);
362+
console.log(` ${commitHash} ${displayMessage}`);
357363
} catch (error: unknown) {
358364
// Cleanup on failure
359365
await cleanup({
@@ -441,7 +447,12 @@ export async function commitAction(options: {
441447
);
442448

443449
// Show preview and get user action
444-
action = await displayPreview(formattedMessage, body, config);
450+
action = await displayPreview(
451+
formattedMessage,
452+
body,
453+
config,
454+
emojiModeActive,
455+
);
445456

446457
// Handle edit actions
447458
if (action === "edit-type") {
@@ -508,7 +519,11 @@ export async function commitAction(options: {
508519
);
509520

510521
console.log(`${success("✓")} Commit created successfully!`);
511-
console.log(` ${commitHash} ${formattedMessage}`);
522+
const displayMessage = formatForDisplay(
523+
formattedMessage,
524+
emojiModeActive,
525+
);
526+
console.log(` ${commitHash} ${displayMessage}`);
512527
} catch (error: unknown) {
513528
// Cleanup on failure
514529
await cleanup({

0 commit comments

Comments
 (0)