Skip to content

Instantly share code, notes, and snippets.

@pmarreck
Last active September 19, 2024 01:37
Show Gist options
  • Save pmarreck/522d68be93e97606ffeef776cd0d4488 to your computer and use it in GitHub Desktop.
Save pmarreck/522d68be93e97606ffeef776cd0d4488 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# OK, why tabs? Why resurrect this age-old nerd debate again?
# Very simple: It's an accessibility issue:
# https://adamtuttle.codes/blog/2021/tabs-vs-spaces-its-an-accessibility-issue/
# To set the default tab width on your terminal (which unfortunately defaults to 8),
# run: `tabs -2` (or whatever width you want), possibly in your dotfiles.
# is AWK set to anything? If not, prefer frawk, then gawk, then awk
[ -z "${AWK}" ] && export AWK=$(command -v frawk || command -v gawk || command -v awk)
reformat_spaces_to_tabs() {
local file="$1"
function determine_tab_size_in_spaces() {
$AWK '
{
# Match the leading spaces and count the occurrences
match($0, /^ */);
indents[RLENGTH]++;
}
END {
# Find the 3 most common indentation levels
max_count = 0;
max_indent = 0;
second_max_indent = 0;
third_max_indent = 0;
for (indent in indents) {
if (indents[indent] > max_count && indent > 0) {
third_max_indent = second_max_indent;
second_max_indent = max_indent;
max_indent = indent;
max_count = indents[indent];
}
}
# Determine what the greatest common divisor is for the most common indentation levels,
# handling up to 8 spaces (which is what my terminal outputs, which is ridiculous)
# There is undoubtedly a less janky way to do this
if (max_indent % 8 == 0 && second_max_indent % 8 == 0 && third_max_indent % 8 == 0) {
print 8;
} else if (max_indent % 7 == 0 && second_max_indent % 7 == 0 && third_max_indent % 7 == 0) {
print 7;
} else if (max_indent % 6 == 0 && second_max_indent % 6 == 0 && third_max_indent % 6 == 0) {
print 6;
} else if (max_indent % 5 == 0 && second_max_indent % 5 == 0 && third_max_indent % 5 == 0) {
print 5;
} else if (max_indent % 4 == 0 && second_max_indent % 4 == 0 && third_max_indent % 4 == 0) {
print 4;
} else if (max_indent % 3 == 0 && second_max_indent % 3 == 0 && third_max_indent % 3 == 0) {
print 3;
} else if (max_indent % 2 == 0 && second_max_indent % 2 == 0 && third_max_indent % 2 == 0) {
print 2;
} else if (max_indent == 0) {
print 0;
} else {
print 1;
}
}
' "$1"
}
local indent=$(determine_tab_size_in_spaces "$file")
if (( indent > 0 )); then
# >&2 echo "Indent size: $indent"
indent_spaces=$(printf "%${indent}s")
$AWK -v indent="$indent_spaces" '
{
while (match($0, "^\t*"indent)) {
$0 = gensub("^(\t*)"indent, "\\1\t", "g");
}
print;
}' "$file" #> "$file.tmp" && mv "$file.tmp" "$file"
else
# >&2 echo "Indent size: 0"
cat "$file"
fi
}
# Export the function so it can be used by find -exec
export -f reformat_spaces_to_tabs
# Run the function, passing along any args, if this file was run directly (such as via sudo) instead of as an include
# Sometimes, $0 contains a leading dash to indicate an interactive (or is it login?) shell,
# which is apparently an old convention (which also broke the basename call on OS X)
_me=$(basename "${0##\-}")
if [ "$_me" = "reformat_spaces_to_tabs" ]; then
$_me "$@"
fi
unset _me
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment