Created
August 26, 2021 20:09
-
-
Save brand-it/82f1864e4cf3ade5228307c6dc7131e8 to your computer and use it in GitHub Desktop.
This file contains 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
#!/bin/bash | |
set -e | |
# Instructions: | |
# | |
# This script is a Git pre-commit hook that spell checks any content you are about to commit. | |
# | |
# Place this script into the ".git/hooks/" directory in your repository. It must be called "pre-commit" and be | |
# executable. A Git hook only works in a single repository. You need to copy this hook into every repository you wish to | |
# use it in manually. Optionally, you can set up a symlink in the ".git/hooks/" directory pointing to the script. | |
# | |
# Each time you try to commit something, this script is run and spell checks the content you are committing. | |
# | |
# Should you want to bypass the pre-commit hook (though not recommended), you can commit with "git commit --no-verify". | |
# The following is a text file that represents your custom dictionary; edit as necessary. Add words to it that you wish | |
# to ignore for the spell check. | |
dict=~/Qsync/.git-spell-check | |
if [ ! -f $dict ]; then | |
touch ~/Qsync/.git-spell-check | |
dict=~/Qsync/.git-spell-check | |
printf "%s\n" "Custom dictionary not found. Created ~/Qsync/.git-spell-checkk..." | |
fi | |
# The following is a temporary dictionary (a binary file) created from the dict text file. It is deleted after the | |
# script finishes. | |
temp_dict=$(mktemp docs-dictionary-XXXXXX) | |
# Language of your doc. When using a non-English language, make sure you have the appropriate aspell libraries | |
# installed: "yum search aspell". For example, to spell check in Slovak, you must have the aspell-sk package installed. | |
lang=en | |
# Define an extension for any additional dictionaries (containing words that are ignored during the spell check) that | |
# are kept locally in your repository. These dictionaries will be loaded on top of the existing global dictionary (by | |
# default ~/.git-spell-check). | |
extension=pws | |
# Clean up if script is interrupted or terminated. | |
trap "cleanup" SIGINT SIGTERM | |
# Prepares the dictionary from scratch in case new words were added since last time. | |
function prepare_dictionary() { | |
local_dict=$(find . -name *.$extension -exec ls {} \;) | |
if [ -z "$local_dict" ]; then | |
sort -u $temp_dict -o $temp_dict | |
aspell --lang="$lang" create master "$temp_dict" < "$dict" | |
else | |
temp_file=$(mktemp temp_file-XXXXXX) | |
for file in $local_dict; do | |
cat $file >> $temp_file | |
done | |
cat $dict >> $temp_file | |
sort -u $temp_file -o $temp_file | |
aspell --lang="$lang" create master "$temp_dict" < "$temp_file" | |
/bin/rm -f "$temp_file" | |
fi | |
} | |
# Removes the temporary dictionary. | |
function cleanup() { | |
/bin/rm -f "$temp_dict" | |
} | |
# Spell checks content you're about to commit. Writes out words that are misspelled or exits with 0 (i.e. continues with | |
# commit). | |
function spell_check() { | |
words=$(git diff --cached | grep -e "^+[^+]" | aspell --mode=sgml list --add-sgml-skip={ulink,code,literal,firstname,parameter,option,package,replaceable,programlisting,userinput,screen,filename,command,computeroutput,abbrev,accel,orgname,surname,foreignphrase,acronym,hardware,keycap,systemitem,application} --lang="$lang" --extra-dicts="$temp_dict" | sort -u) | |
if [ ! "$words" ]; then | |
printf "%s\n" "No typos found. Proceeding with commit..." | |
cleanup; exit 0 | |
fi | |
printf "%s\n" "Spell check failed on the following words: | |
-------------------------------------------------" | |
echo $words | |
for word in $words; do | |
grep --color=always --exclude-dir={.git,tmp} -HIrone "\<$word\>" $(git diff --cached --name-only --diff-filter=ACMRTUXB) | awk -F ":" '{print "File: " $1 "\ton line: " $2 "\tTypo: " $3}' | |
printf "%s\n" "-------------------" | |
done | |
} | |
# Adds all, some, or none of the misspelled words to the custom dictionary. | |
function add_words_to_dict() { | |
printf "%s\n" " | |
Add any of the misspelled words into your custom dictionary? | |
* a[ll] (add all words into dict, continue with commit) | |
* s[ome] (add some words into dict, fix others, no commit) | |
* i[gnore] (add some words into dict, ignore rest, continue with commit) | |
* n[one] (no commit) | |
" | |
while true; do | |
exec < /dev/tty # Simply reading user input does not work because Git hooks have stdin detached. | |
read answer | |
shopt -s nocasematch | |
case "$answer" in | |
a|all) | |
add_all | |
cleanup; exit 0 | |
;; | |
s|some) | |
add_some | |
printf "%s\n" "Please fix remaining typos, use \"git add\" to add fixed files, and commit." | |
cleanup; exit 1 | |
;; | |
i|ignore) | |
add_some | |
cleanup; exit 0 | |
;; | |
n|none) | |
add_none | |
cleanup; exit 1 | |
;; | |
*) | |
printf "%s\n" "Incorrect answer. Try again." | |
continue | |
esac | |
shopt -u nocasematch | |
done | |
} | |
# Adds all words to the custom dictionary and continues with the commit. | |
function add_all() { | |
for word in $words; do | |
echo $word >> "$dict" | |
done | |
} | |
# Adds some (selected by user) of the words to the dictinary and exits with 1. | |
function add_some() { | |
for word in $words; do | |
printf "%s\n" "Do you want to add the following word to your custom dictionary: $word (y[es] or n[o])" | |
while true; do | |
exec < /dev/tty | |
read answer | |
shopt -s nocasematch | |
case "$answer" in | |
y|yes) | |
echo $word >> "$dict" | |
printf "%s\n" "\"$word\" added to your custom dictionary." | |
break ;; | |
n|no) | |
break ;; | |
*) | |
printf "%s\n" "Incorrect answer. Try again." | |
continue | |
esac | |
shopt -u nocasematch | |
done | |
done | |
} | |
# Adds none of the words and exits with 1. | |
function add_none() { | |
printf "%s\n" "No words were added to your custom dictionary." | |
printf "%s\n" "Please fix remaining typos, use \"git add\" to add fixed files, and commit." | |
} | |
prepare_dictionary | |
spell_check | |
add_words_to_dict |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment