feat: Add hk util trailing-whitespace command#319
Merged
Conversation
Introduces a new `hk util` subcommand for utility operations, starting with
trailing-whitespace detection and fixing.
## Features
- **hk util trailing-whitespace <files>** - Check for trailing whitespace
- **hk util trailing-whitespace --fix <files>** - Remove trailing whitespace
- Automatically skips non-text files
- Exit code 1 if issues found/fixed, 0 if clean
## Implementation
- New `src/cli/util.rs` module with extensible subcommand structure
- Rust implementation replaces bash scripts for better:
- Testability (unit tests in Rust)
- Readability (no complex bash escaping)
- Cross-platform compatibility
- `trailing_whitespace` builtin now calls `hk util trailing-whitespace`
## Testing
**Rust unit tests** (4 tests in src/cli/util.rs):
- test_has_trailing_whitespace
- test_no_trailing_whitespace
- test_fix_trailing_whitespace
- test_fix_already_clean
**Bats integration tests** (9 tests in test/util_trailing_whitespace.bats):
- Detection of trailing whitespace
- Fixing trailing whitespace
- Multiple files support
- Binary file skipping
- Various whitespace types (space, tab, mixed)
- Builtin integration with hk check/fix
## Example Usage
```bash
# Check files
hk util trailing-whitespace file1.txt file2.txt
# Fix files
hk util trailing-whitespace --fix *.txt
# Via builtin
hk.pkl:
hooks {
["check"] {
steps {
["trailing-ws"] = Builtins.trailing_whitespace
}
}
}
```
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
Replace unix-specific 'file' command with cross-platform Rust implementation. ## Changes - Replace `file -b --mime-type` with pure Rust heuristics: - Read first 8KB of file - Check for null bytes (binary indicator) - Validate UTF-8 encoding - Empty files treated as text ## Benefits - ✅ Works on Windows (no dependency on 'file' command) - ✅ Works on macOS and Linux - ✅ Faster (no subprocess spawn) - ✅ More consistent behavior across platforms ## Testing Added 3 new unit tests: - test_is_text_file_with_text - test_is_text_file_with_binary - test_is_text_file_with_empty Total: 7 Rust unit tests 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Owner
Author
Windows Compatibility Fixed ✅Problem: The original implementation used the unix Solution: Replaced with pure Rust implementation that:
Benefits:
Testing: #[test]
fn test_is_text_file_with_text() { ... }
#[test]
fn test_is_text_file_with_binary() { ... }
#[test]
fn test_is_text_file_with_empty() { ... }The implementation now works across all platforms! 🎉 |
Fixes docs-sync CI failure by adding missing documentation.
## Changes
- **docs/builtins.md**: Add trailing_whitespace entry in Special Purpose section
- **docs/cli/util.md**: New file documenting hk util command
- **docs/cli/index.md**: Add util subcommand to CLI reference
## Details
### trailing_whitespace builtin
- Files: All text files
- Features: Detect and remove trailing whitespace
- Commands: hk util trailing-whitespace [--fix] {{files}}
- Cross-platform Rust implementation
### util command
- New utility command framework
- Starting with trailing-whitespace subcommand
- Designed for extensibility (future: end-of-file, mixed-line-ending, etc.)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
Bug fix: The fix_trailing_whitespace function was unconditionally adding a final newline to all files, even if they didn't originally end with one. ## Changes - Check if file originally ends with newline - Only add final newline if original file had one - Use write! instead of writeln! for last line if no original newline ## Testing Added 2 new unit tests: - test_fix_preserves_no_final_newline - test_fix_preserves_final_newline Total: 9 Rust unit tests ## Example Before fix: ``` echo -n "trailing " > file.txt hk util trailing-whitespace --fix file.txt cat file.txt # Output: "trailing\n" (added newline!) ``` After fix: ``` echo -n "trailing " > file.txt hk util trailing-whitespace --fix file.txt cat file.txt # Output: "trailing" (no newline added!) ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Owner
Author
All CI Failures Fixed ✅Issues Resolved
Test Summary9 Rust Unit Tests:
9 Bats Integration Tests (in test/util_trailing_whitespace.bats) All issues resolved, PR ready for review! 🎉 |
The builtin integration test was failing because it tried to import Builtins.trailing_whitespace from the released package (v1.2.0), which doesn't have this new builtin yet. ## Change Use local pkl files via $PKL_PATH instead of package imports: - amends "$PKL_PATH/Config.pkl" - import "$PKL_PATH/Builtins.pkl" This allows the test to use the newly created trailing_whitespace builtin that's being added in this PR. ## Fix Resolves CI failure in ubuntu tests: ``` Cannot find property `trailing_whitespace` in module `Builtins`. ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Changes: - Fix bats test PATH to respect CARGO_TARGET_DIR env var (set by mise) - Change fix mode to exit 0 on success (standard formatter behavior) - Fix builtin test expectations to use 'code' instead of 'status' - Add 'fix' hook to builtin integration test This resolves the "hk: command not found" issue when running mise run ci locally and ensures the utility works correctly in hk fix hooks. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Use tera template syntax to dynamically set PATH based on CARGO_TARGET_DIR env var (set by mise to /tmp/mise/target for shared build cache). Falls back to 'target' when CARGO_TARGET_DIR is not set. This fixes the "Permission denied" errors when running mise tasks like lint that execute the hk binary, as the binary location now matches where cargo actually builds it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Fixes the eslint step in hk check which uses 'bun run eslint'. Also ran 'bun install' to install all node dependencies. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Clarify that fix mode exits 0 on success (standard formatter behavior), while check mode exits 1 when issues are found. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Use the same CARGO_TARGET_DIR logic as common_setup.bash to find the hk binary. This fixes the BW01 warnings about command not found. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1. builtin_json.bats: Update to match actual jq error message format
- Changed from "jq: parse error" to just "parse error" to match
current jq output format
2. pre_commit_prettier_restaging.bats: Remove -l flag from bash calls
- Login shells (-l) don't inherit PATH, causing "hk: command not found"
- Changed "bash -lc" to "bash -c" to preserve PATH from test setup
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
Merged
jdx
added a commit
that referenced
this pull request
Oct 5, 2025
## [1.17.0](https://github.com/jdx/hk/compare/v1.16.0..v1.17.0) - 2025-10-05 ### 🚀 Features - Add hk util trailing-whitespace command by [@jdx](https://github.com/jdx) in [#319](#319) - add mixed_line_ending builtin by [@jdx](https://github.com/jdx) in [#324](#324) - add check_symlinks builtin by [@jdx](https://github.com/jdx) in [#326](#326) - add check_executables_have_shebangs builtin by [@jdx](https://github.com/jdx) in [#325](#325) - Add check-merge-conflict util command and builtin by [@jdx](https://github.com/jdx) in [#322](#322) - add check_case_conflict builtin by [@jdx](https://github.com/jdx) in [#323](#323) - add detect_private_key builtin by [@jdx](https://github.com/jdx) in [#332](#332) - add check_added_large_files builtin by [@jdx](https://github.com/jdx) in [#329](#329) - add python_debug_statements builtin by [@jdx](https://github.com/jdx) in [#331](#331) - add python_check_ast builtin by [@jdx](https://github.com/jdx) in [#330](#330) - add no_commit_to_branch builtin by [@jdx](https://github.com/jdx) in [#333](#333) - add check_byte_order_marker and fix_byte_order_marker builtins by [@jdx](https://github.com/jdx) in [#328](#328) - add regex pattern support for glob and exclude by [@jdx](https://github.com/jdx) in [#336](#336) - automatically batch large file lists to prevent ARG_MAX errors by [@jdx](https://github.com/jdx) in [#338](#338) ### 🐛 Bug Fixes - Add validation for stage attribute requiring fix command by [@jdx](https://github.com/jdx) in [#327](#327) - display stderr when check_list_files returns empty list by [@jdx](https://github.com/jdx) in [#334](#334) - added new builtins to Builtins.pkl by [@jdx](https://github.com/jdx) in [b8a2b17](b8a2b17) - enable experimental settings in mise.toml for swift support by [@jdx](https://github.com/jdx) in [#342](#342) - correct airflow migration test to expect local imports by [@jdx](https://github.com/jdx) in [#343](#343) - make final CI check always run and fail if dependencies fail by [@jdx](https://github.com/jdx) in [#344](#344) - add ruff format to ruff builtin by [@jdx](https://github.com/jdx) in [#340](#340) ### 🚜 Refactor - Split util module into separate files by [@jdx](https://github.com/jdx) in [#321](#321) ### 🛡️ Security - migrate pre-commit by [@jdx](https://github.com/jdx) in [#318](#318) ### 🔍 Other Changes - split CI runs into parallel jobs and add docs-sync mise task by [@jdx](https://github.com/jdx) in [#337](#337) - remove v0 pkl files from docs/public by [@jdx](https://github.com/jdx) in [#341](#341) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Release 1.17.0 with new migrate command, many util subcommands, refreshed docs, and dependency updates. > > - **Version**: bump `hk` to `1.17.0` (Cargo.toml, usage specs, docs). > - **CLI**: > - **New Command**: `migrate pre-commit` with flags (`--config`, `--output`, `--force`, `--hk-pkl-root`). > - **Util Subcommands**: add `check-added-large-files`, `check-byte-order-marker`, `fix-byte-order-marker`, `check-case-conflict`, `check-executables-have-shebangs`, `check-merge-conflict`, `check-symlinks`, `detect-private-key`, `end-of-file-fixer`, `mixed-line-ending`, `no-commit-to-branch`, `python-check-ast`, `python-debug-statements`, `trailing-whitespace`. > - **Docs**: > - Update `docs/cli/index.md`, regenerate `docs/cli/commands.json`, and `hk.usage.kdl`. > - Split `util` docs into per-command pages and add `migrate` docs. > - **Dependencies**: update `Cargo.lock` crate versions and set `hk` crate version to `1.17.0`. > - **Changelog**: add `CHANGELOG.md` entry for `1.17.0` with features/bug fixes. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 75b972a. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: mise-en-dev <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduces a new
hk utilsubcommand system for utility operations, starting withhk util trailing-whitespacefor detecting and fixing trailing whitespace in files.Motivation
Replace bash scripts in builtins with Rust implementations for:
Features
Command Usage
Behavior
filecommandBuiltin Integration
The builtin now calls
hk util trailing-whitespaceinstead of bash scripts.Implementation
New Files
src/cli/util.rs- Util subcommand module with trailing-whitespace implementationpkl/builtins/trailing_whitespace.pkl- Builtin that calls the util commandtest/util_trailing_whitespace.bats- Bats integration testsCode Structure
Designed for easy extension with additional utilities.
Testing
Rust Unit Tests (4 tests)
Located in
src/cli/util.rs:Run with:
cargo testBats Integration Tests (9 tests)
Located in
test/util_trailing_whitespace.bats:Run with:
mise run test:bats test/util_trailing_whitespace.batsBefore/After Comparison
Old Builtin (bash)
New Builtin (Rust)
Future Utilities
The
hk utilframework is designed to support additional utilities:hk util end-of-file- Ensure files end with newlinehk util mixed-line-ending- Detect/fix mixed line endingshk util check-merge-conflict- Detect merge conflict markershk util detect-private-key- Detect private keysThese can all be migrated from bash to Rust incrementally.
Testing Instructions
🤖 Generated with Claude Code
Co-Authored-By: Claude [email protected]
Note
Introduces a Rust-based
hk util trailing-whitespacecommand with builtin integration, updates docs, and adds tests; also tweaks path handling and docs/scripts.hk utilwithtrailing-whitespacesubcommand (src/cli/util.rs), including detection/fix logic and unit tests; wire into CLI (src/cli/mod.rs).Builtins.trailing_whitespaceand implementation (pkl/builtins/trailing_whitespace.pkl), export inpkl/Builtins.pkl.hk utilpage (docs/cli/util.md) and link from CLI index; addeslintscript indocs/package.json.test/util_trailing_whitespace.bats).CARGO_TARGET_DIR, shell usage, and error output matching.mise.tomland test helpers to prefer{{ env.CARGO_TARGET_DIR }}/debugin PATH.Written by Cursor Bugbot for commit 00dbac2. This will update automatically on new commits. Configure here.