Created
June 12, 2025 12:04
-
-
Save loopmode/6c2e876b764888b72f8b7f6e93f6c7a9 to your computer and use it in GitHub Desktop.
codemod bash
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
# codemod function generated by codemod AI to allow using ast-grep with autocomplete for local rules | |
# opted for macos + zshell | |
# use some AI to make it work on bash/linux/windows?? | |
codemod() { | |
local start_time=$(date +%s.%N) | |
local write_mode=false | |
local args=() | |
# Parse all arguments, extracting --write and keeping others | |
while [[ $# -gt 0 ]]; do | |
case $1 in | |
--write) | |
write_mode=true | |
shift | |
;; | |
*) | |
args+=("$1") | |
shift | |
;; | |
esac | |
done | |
# Need at least 2 arguments (1 rule + 1 target directory) | |
if [[ ${#args[@]} -lt 2 ]]; then | |
echo "Usage: codemod [--write] rule1 [rule2 ...] targetfolder [--write]" | |
echo "Examples:" | |
echo " codemod remove-prop-types-imports src/ # Single rule preview" | |
echo " codemod remove-prop-types-imports comment-out-proptypes src/ # Multiple rules preview" | |
echo " codemod --write remove-prop-types-imports comment-out-proptypes src/ # Apply all changes" | |
return 1 | |
fi | |
# Last argument is target directory, everything else is rule names | |
local targetdir="${args[-1]}" | |
local rules=("${args[@]:0:${#args[@]}-1}") | |
if [ ! -d "$targetdir" ]; then | |
echo "Error: Target directory not found: $targetdir" | |
return 1 | |
fi | |
# Get absolute path of target directory | |
local abs_targetdir=$(realpath "$targetdir" 2>/dev/null || echo $(cd "$targetdir" && pwd)) | |
# Show what we're going to do | |
local mode_text="PREVIEW MODE" | |
if [[ "$write_mode" == true ]]; then | |
mode_text="APPLYING CHANGES" | |
fi | |
echo "Running ${#rules[@]} codemod(s) on $abs_targetdir ($mode_text)" | |
if [[ "$write_mode" == false ]]; then | |
echo "Add --write to apply changes" | |
fi | |
echo "" | |
# Execute each rule | |
for rulename in "${rules[@]}"; do | |
local rule_start_time=$(date +%s.%N) | |
local rulefile="$HOME/Projects/codemods/${rulename}" | |
# Try with .yml extension if not provided | |
if [[ ! "$rulename" == *.yml ]]; then | |
rulefile="${rulefile}.yml" | |
fi | |
if [ ! -f "$rulefile" ]; then | |
echo "Error: Rule file not found: $rulefile" | |
continue | |
fi | |
echo "→ Running rule: $rulename" | |
if [[ "$write_mode" == true ]]; then | |
ast-grep scan --rule "$rulefile" --update-all "$targetdir" | |
else | |
ast-grep scan --rule "$rulefile" "$targetdir" | |
fi | |
local rule_end_time=$(date +%s.%N) | |
local rule_duration=$(echo "$rule_end_time - $rule_start_time" | bc -l 2>/dev/null || echo "0") | |
printf " ✓ Completed in %.3f seconds\n" "$rule_duration" | |
echo "" | |
done | |
local end_time=$(date +%s.%N) | |
local total_duration=$(echo "$end_time - $start_time" | bc -l 2>/dev/null || echo "0") | |
if [[ "$write_mode" == true ]]; then | |
printf "All changes applied in %.3f seconds.\n" "$total_duration" | |
else | |
printf "Preview completed in %.3f seconds. Use --write to apply changes.\n" "$total_duration" | |
fi | |
} | |
# Zsh completion for codemod | |
_codemod() { | |
local -a rules | |
local rules_dir="$HOME/Projects/codemods" | |
# Get available rules | |
if [[ -d "$rules_dir" ]]; then | |
for file in "$rules_dir"/*.yml; do | |
[[ -f "$file" ]] && rules+=($(basename "$file" .yml)) | |
done | |
fi | |
# Remove --write from consideration | |
local filtered_words=() | |
local write_flag_count=0 | |
for word in "${words[@]:1}"; do | |
if [[ "$word" == "--write" ]]; then | |
((write_flag_count++)) | |
else | |
filtered_words+=("$word") | |
fi | |
done | |
local effective_current=$((CURRENT - write_flag_count)) | |
local word_count=${#filtered_words[@]} | |
# If we're on the last incomplete word and there are already 2+ words, | |
# and the current word looks like a directory, complete directories | |
if [[ $effective_current -gt 1 ]] && [[ -d "${words[CURRENT]}" || "${words[CURRENT]}" =~ ^[./] ]]; then | |
_directories | |
else | |
# Otherwise, complete rule names and directories | |
local -a all_completions | |
((${#rules[@]})) && all_completions+=("${rules[@]}") | |
# Add some common directory patterns | |
# all_completions+=(src/ js/ lib/ components/) | |
compadd -a all_completions | |
_directories | |
fi | |
} | |
# Initialize completion system | |
autoload -Uz compinit | |
compinit -i # The -i flag ignores insecure directories/files | |
compdef _codemod codemod |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment