feat: switch to biome, apply formatting, shellcheck (#227)

* feat: switch to biome, apply formatting, shellcheck
* chore: apply cr comments
* chore: few config tweaks, shellcheck hook now py-based
* chore: lint fixes and pr comments
* chore(lint): megalinter, and other fixes

Signed-off-by: Ismo Vuorinen <ismo@ivuorinen.net>
This commit is contained in:
2025-12-17 16:03:29 +02:00
committed by GitHub
parent 4b0e38ffd2
commit 961efec364
69 changed files with 782 additions and 1089 deletions

View File

@@ -103,9 +103,9 @@ fetch_keys_if_missing()
if [[ ! -f "$KEYS_FILE" ]]; then
log_message "Keys file '$KEYS_FILE' not found. Attempting to fetch from $KEYS_SOURCE..."
mkdir -p "$(dirname "$KEYS_FILE")"
curl -s "$KEYS_SOURCE" -o "$KEYS_FILE"
if [[ $? -ne 0 || ! -s "$KEYS_FILE" ]]; then
if ! curl -s "$KEYS_SOURCE" -o "$KEYS_FILE" || [[ ! -s "$KEYS_FILE" ]]; then
rm -f "$KEYS_FILE" 2> /dev/null || true
log_message "Error: Failed to fetch keys from $KEYS_SOURCE"
exit 1
fi
@@ -126,10 +126,12 @@ encrypt_file_or_directory()
elif [[ -f "$file" ]]; then
fetch_keys_if_missing
local output_file="${file}.age"
age -R "$KEYS_FILE" "$file" > "$output_file"
if [[ $? -eq 0 ]]; then
local temp_file
temp_file="$(mktemp -p "$(dirname "$file")")"
if age -R "$KEYS_FILE" "$file" > "$temp_file" && mv "$temp_file" "$output_file"; then
log_message "File encrypted successfully: $output_file"
else
rm -f "$temp_file"
log_message "Error: Failed to encrypt file '$file'."
exit 1
fi
@@ -147,10 +149,12 @@ decrypt_file_or_directory()
elif [[ -f "$file" ]]; then
fetch_keys_if_missing
local output_file="${file%.age}"
age -d -i "$KEYS_FILE" "$file" > "$output_file"
if [[ $? -eq 0 ]]; then
local temp_file
temp_file="$(mktemp -p "$(dirname "$file")")"
if age -d -i "$KEYS_FILE" "$file" > "$temp_file" && mv "$temp_file" "$output_file"; then
log_message "File decrypted successfully: $output_file"
else
rm -f "$temp_file"
log_message "Error: Failed to decrypt file '$file'."
exit 1
fi

View File

@@ -36,9 +36,8 @@ if [[ ! -f "$KEYS_FILE" ]]; then
mkdir -p "$(dirname "$KEYS_FILE")"
# Fetch the keys and save to the file
curl -s "$KEYS_SOURCE" -o "$KEYS_FILE"
if [[ $? -ne 0 || ! -s "$KEYS_FILE" ]]; then
if ! curl -s "$KEYS_SOURCE" -o "$KEYS_FILE" || [[ ! -s "$KEYS_FILE" ]]; then
rm -f "$KEYS_FILE" 2> /dev/null || true
echo "Error: Failed to fetch keys from $KEYS_SOURCE"
exit 1
fi
@@ -50,11 +49,11 @@ fi
# Decrypt the file
OUTPUT_FILE="${FILE%.age}"
age -d -i "$KEYS_FILE" "$FILE" > "$OUTPUT_FILE"
if [[ $? -eq 0 ]]; then
TEMP_FILE="$(mktemp -p "$(dirname "$OUTPUT_FILE")")"
if age -d -i "$KEYS_FILE" "$FILE" > "$TEMP_FILE" && mv "$TEMP_FILE" "$OUTPUT_FILE"; then
echo "File decrypted successfully: $OUTPUT_FILE"
else
rm -f "$TEMP_FILE"
echo "Error: Failed to decrypt file."
exit 1
fi

View File

@@ -37,9 +37,7 @@ if [[ ! -f "$KEYS_FILE" ]]; then
mkdir -p "$(dirname "$KEYS_FILE")"
# Fetch the keys and save to the file
curl -s "$KEYS_SOURCE" -o "$KEYS_FILE"
if [[ $? -ne 0 || ! -s "$KEYS_FILE" ]]; then
if ! curl -s "$KEYS_SOURCE" -o "$KEYS_FILE" || [[ ! -s "$KEYS_FILE" ]]; then
echo "Error: Failed to fetch keys from $KEYS_SOURCE"
exit 1
fi
@@ -51,9 +49,7 @@ fi
# Encrypt the file
OUTPUT_FILE="${FILE}.age"
age -R "$KEYS_FILE" "$FILE" > "$OUTPUT_FILE"
if [[ $? -eq 0 ]]; then
if age -R "$KEYS_FILE" "$FILE" > "$OUTPUT_FILE"; then
echo "File encrypted successfully: $OUTPUT_FILE"
else
echo "Error: Failed to encrypt file."

View File

@@ -25,6 +25,7 @@ source_file()
case "$CURRENT_SHELL" in
fish)
if [[ -f "$file.fish" ]]; then
# shellcheck disable=SC1090
source "$file.fish"
else
echo "Fish shell file not found: $file.fish"
@@ -32,6 +33,7 @@ source_file()
fi
;;
sh | bash | zsh)
# shellcheck disable=SC1090
source "$file"
;;
*)

View File

@@ -142,7 +142,7 @@ if [[ ! "$opt" =~ "-E" ]] && tmux list-panes -F '#F' | grep -q Z; then
zoomed_without_popup=1
original_window=$(tmux display-message -p "#{window_id}")
tmp_window=$(tmux new-window -d -P -F "#{window_id}" "bash -c 'while :; do for c in \\| / - '\\;' do sleep 0.2; printf \"\\r\$c fzf-tmux is running\\r\"; done; done'")
tmux swap-pane -t $tmp_window \; select-window -t $tmp_window
tmux swap-pane -t "$tmp_window" \; select-window -t "$tmp_window"
fi
set -e
@@ -154,15 +154,16 @@ fifo1="${TMPDIR:-/tmp}/fzf-fifo1-$id"
fifo2="${TMPDIR:-/tmp}/fzf-fifo2-$id"
fifo3="${TMPDIR:-/tmp}/fzf-fifo3-$id"
if tmux_win_opts=$(tmux show-options -p remain-on-exit \; show-options -p synchronize-panes 2> /dev/null); then
tmux_win_opts=($(sed '/ off/d; s/synchronize-panes/set-option -p synchronize-panes/; s/remain-on-exit/set-option -p remain-on-exit/; s/$/ \\;/' <<< "$tmux_win_opts"))
mapfile -t tmux_win_opts < <(sed '/ off/d; s/synchronize-panes/set-option -p synchronize-panes/; s/remain-on-exit/set-option -p remain-on-exit/; s/$/ \\;/' <<< "$tmux_win_opts")
tmux_off_opts='; set-option -p synchronize-panes off ; set-option -p remain-on-exit off'
else
tmux_win_opts=($(tmux show-window-options remain-on-exit \; show-window-options synchronize-panes | sed '/ off/d; s/^/set-window-option /; s/$/ \\;/'))
mapfile -t tmux_win_opts < <(tmux show-window-options remain-on-exit \; show-window-options synchronize-panes | sed '/ off/d; s/^/set-window-option /; s/$/ \\;/')
tmux_off_opts='; set-window-option synchronize-panes off ; set-window-option remain-on-exit off'
fi
# shellcheck disable=SC2329
cleanup()
{
\rm -f $argsf $fifo1 $fifo2 $fifo3
\rm -f "$argsf" "$fifo1" "$fifo2" "$fifo3"
# Restore tmux window options
if [[ "${#tmux_win_opts[@]}" -gt 0 ]]; then
@@ -172,9 +173,9 @@ cleanup()
# Remove temp window if we were zoomed without popup options
if [[ -n "$zoomed_without_popup" ]]; then
tmux display-message -p "#{window_id}" > /dev/null
tmux swap-pane -t $original_window \; \
select-window -t $original_window \; \
kill-window -t $tmp_window \; \
tmux swap-pane -t "$original_window" \; \
select-window -t "$original_window" \; \
kill-window -t "$tmp_window" \; \
resize-pane -Z
fi
@@ -209,39 +210,40 @@ echo "$envs;" > "$argsf"
opts=$(printf "%q " "${args[@]}")
pppid=$$
echo -n "trap 'kill -SIGUSR1 -$pppid' EXIT SIGINT SIGTERM;" >> $argsf
echo -n "trap 'kill -SIGUSR1 -$pppid' EXIT SIGINT SIGTERM;" >> "$argsf"
close="; trap - EXIT SIGINT SIGTERM $close"
export TMUX=$(cut -d , -f 1,2 <<< "$TMUX")
mkfifo -m o+w $fifo2
export TMUX
TMUX=$(cut -d , -f 1,2 <<< "$TMUX")
mkfifo -m o+w "$fifo2"
if [[ "$opt" =~ "-E" ]]; then
cat $fifo2 &
cat "$fifo2" &
if [[ -n "$term" ]] || [[ -t 0 ]]; then
cat <<< "\"$fzf\" $opts > $fifo2; out=\$? $close; exit \$out" >> $argsf
cat <<< "\"$fzf\" $opts > $fifo2; out=\$? $close; exit \$out" >> "$argsf"
else
mkfifo $fifo1
cat <<< "\"$fzf\" $opts < $fifo1 > $fifo2; out=\$? $close; exit \$out" >> $argsf
cat <&0 > $fifo1 &
mkfifo "$fifo1"
cat <<< "\"$fzf\" $opts < $fifo1 > $fifo2; out=\$? $close; exit \$out" >> "$argsf"
cat <&0 > "$fifo1" &
fi
tmux popup -d "$PWD" $opt "bash $argsf" > /dev/null 2>&1
tmux popup -d "$PWD" "$opt" "bash $argsf" > /dev/null 2>&1
exit $?
fi
mkfifo -m o+w $fifo3
mkfifo -m o+w "$fifo3"
if [[ -n "$term" ]] || [[ -t 0 ]]; then
cat <<< "\"$fzf\" $opts > $fifo2; echo \$? > $fifo3 $close" >> $argsf
cat <<< "\"$fzf\" $opts > $fifo2; echo \$? > $fifo3 $close" >> "$argsf"
else
mkfifo $fifo1
cat <<< "\"$fzf\" $opts < $fifo1 > $fifo2; echo \$? > $fifo3 $close" >> $argsf
cat <&0 > $fifo1 &
mkfifo "$fifo1"
cat <<< "\"$fzf\" $opts < $fifo1 > $fifo2; echo \$? > $fifo3 $close" >> "$argsf"
cat <&0 > "$fifo1" &
fi
tmux \
split-window -c "$PWD" $opt "bash -c 'exec -a fzf bash $argsf'" $swap \
$tmux_off_opts \
split-window -c "$PWD" "$opt" "bash -c 'exec -a fzf bash $argsf'" "$swap" \
"$tmux_off_opts" \
> /dev/null 2>&1 || {
"$fzf" "${args[@]}"
exit $?
}
cat $fifo2
exit "$(cat $fifo3)"
cat "$fifo2"
exit "$(cat "$fifo3")"

View File

@@ -25,27 +25,27 @@ fi
# Output functions
msg_err()
{
echo -e "\e[31m$@\e[0m" >&2
echo -e "\e[31m$*\e[0m" >&2
}
msg_success()
{
echo -e "\e[32m$@\e[0m"
echo -e "\e[32m$*\e[0m"
}
msg_warn()
{
echo -e "\e[33m$@\e[0m" >&2
echo -e "\e[33m$*\e[0m" >&2
}
msg_info()
{
echo -e "\e[36m$@\e[0m"
echo -e "\e[36m$*\e[0m"
}
msg_debug()
{
[[ $VERBOSE -eq 1 ]] && echo -e "\e[35m$@\e[0m"
[[ $VERBOSE -eq 1 ]] && echo -e "\e[35m$*\e[0m"
}
show_help()
@@ -180,7 +180,8 @@ format_rule()
get_file_extension()
{
local file="$1"
local basename=$(basename "$file")
local basename
basename=$(basename "$file")
local extension=""
# Check if file has no extension or is a dotfile
@@ -231,8 +232,8 @@ suggest_rule()
# If file path contains .d/ pattern, we need special handling
if [[ "$file" =~ \.d/ ]]; then
# Extract the pattern part that includes the .d/ directory
local dir_part=$(dirname "$file")
local base_name=$(basename "$file")
local dir_part
dir_part=$(dirname "$file")
# Check if it's a config directory pattern worth capturing
if [[ "$dir_part" =~ /(\.d|[^/]+\.d)$ ]]; then
@@ -430,7 +431,8 @@ detect_shell_scripts()
fi
# Skip if file extension already covered
local extension=$(get_file_extension "$rel_path")
local extension
extension=$(get_file_extension "$rel_path")
if [[ "$extension" != "$rel_path" ]] && grep -q "^\*\.$extension " <<< "$existing_rules"; then
msg_debug "Script covered by extension rule: $rel_path (*.$extension)"
continue
@@ -458,7 +460,8 @@ detect_shell_scripts()
fi
# Group by directory
local dir=$(dirname "$rel_path")
local dir
dir=$(dirname "$rel_path")
if [[ "$dir" == "." ]]; then
dir="root"
fi
@@ -480,7 +483,8 @@ detect_shell_scripts()
# Check if we can use directory-based rules instead of individual files
for dir in "${!scripts_by_dir[@]}"; do
local files_in_dir=$(echo -e "${scripts_by_dir[$dir]}" | wc -l)
local files_in_dir
files_in_dir=$(echo -e "${scripts_by_dir[$dir]}" | wc -l)
local dir_path="$dir"
if [[ "$dir" == "root" ]]; then
@@ -575,7 +579,8 @@ suggest_gitattributes()
declare -A seen_patterns=()
while IFS= read -r file; do
local suggestion=$(suggest_rule "$file")
local suggestion
suggestion=$(suggest_rule "$file")
if [[ -n "$suggestion" ]]; then
IFS=':' read -r pattern attributes <<< "$suggestion"
@@ -639,7 +644,8 @@ suggest_gitattributes()
formatted_suggestions+="$pattern\n"
echo "$pattern"
else
local formatted_rule=$(printf "%-${format_width}s %s\n" "$pattern" "$attributes")
local formatted_rule
formatted_rule=$(printf "%-${format_width}s %s\n" "$pattern" "$attributes")
formatted_suggestions+="$formatted_rule\n"
echo "$formatted_rule"
fi

1
local/bin/iterm2_shell_integration.zsh Executable file → Normal file
View File

@@ -1,3 +1,4 @@
# shellcheck disable=all
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2

View File

@@ -142,7 +142,7 @@ if [ ! -x "${CURL}" ]; then
exit 1
fi
devices="$(printf "${devices}" | xargs -n1 | sort -u | uniq)\n"
devices="$(printf "%s" "${devices}" | xargs -n1 | sort -u)"
if [ -z "${devices}" ]; then
__pushover_send_message

View File

@@ -126,11 +126,11 @@ if [[ -f "$CONFIG_FILE" ]]; then
PROTECTED_KEYS+=("$key")
done <<< "$CUSTOM_KEYS"
SKIPPED+=("$(yq '.skipped_keys[]' "$CONFIG_FILE")")
while IFS= read -r key; do
mapfile -t SKIPPED < <(yq '.skipped_keys[]' "$CONFIG_FILE")
for key in "${SKIPPED[@]}"; do
# Add to default_skipped_keys
SKIPPED_KEYS+=("$key")
done <<< "$SKIPPED"
done
CUSTOM_GROUPS=$(yq '.custom_grouping[]' "$CONFIG_FILE")
while IFS= read -r group; do
@@ -159,6 +159,7 @@ is_protected()
return 0
fi
# Wildcard match (protected_key contains '*')
# shellcheck disable=SC2053 # Intentional glob matching - protected_key contains wildcard patterns
if [[ "$protected_key" == *"*"* ]] && [[ "$key" == $protected_key ]]; then
return 0
fi
@@ -198,6 +199,7 @@ is_skipped()
return 0
fi
# Wildcard match (skipped_key contains '*')
# shellcheck disable=SC2053 # Intentional glob matching - skipped_key contains wildcard patterns
if [[ "$skipped_key" == *"*"* ]] && [[ "$key" == $skipped_key ]]; then
return 0
fi
@@ -244,8 +246,15 @@ while IFS='=' read -r key value; do
value="[protected value]"
fi
# Update group data
if [[ ! " ${all_groups[*]} " =~ " $group " ]]; then
# Update group data - check if group already exists
group_exists=false
for existing_group in "${all_groups[@]}"; do
if [[ "$existing_group" == "$group" ]]; then
group_exists=true
break
fi
done
if [[ "$group_exists" == false ]]; then
all_groups+=("$group")
fi

View File

@@ -30,10 +30,9 @@ config_msg()
{
# if $1 is empty, return
[ -z "$1" ] && return
[ -z "$2" ] && $2=""
local msg_type="$1"
local msg_content="$2"
local msg_content="${2:-}"
[[ "$VERBOSE" -eq 1 ]] && printf 'x-load-configs: %s %s\n' "$msg_type" "$msg_content"
return 0
}
@@ -50,7 +49,8 @@ source_config()
{
local config_file=$1
if [ -f "$config_file" ]; then
eval "$config_file"
# shellcheck disable=SC1090
source "$config_file"
config_msg "Sourced" "$config_file"
else
msg "Config file $config_file not found"

View File

@@ -60,7 +60,7 @@ log_debug()
filter_coderabbit_addressed_comments()
{
local input_data="$1"
local is_wrapped="$2" # true for {comments: [...]}, false for [...]
local is_wrapped="$2" # true for {comments: [...]}, false for [...]
local jq_filter='select(
(.user.login | contains("coderabbit") | not) or
@@ -68,9 +68,9 @@ filter_coderabbit_addressed_comments()
)'
if [[ "$is_wrapped" == "true" ]]; then
echo "$input_data" | jq "{comments: [.comments[] | $jq_filter]}" 2>/dev/null || echo "$input_data"
echo "$input_data" | jq "{comments: [.comments[] | $jq_filter]}" 2> /dev/null || echo "$input_data"
else
echo "$input_data" | jq "[.[] | $jq_filter]" 2>/dev/null || echo "$input_data"
echo "$input_data" | jq "[.[] | $jq_filter]" 2> /dev/null || echo "$input_data"
fi
}
@@ -79,13 +79,13 @@ fetch_and_filter_data()
{
local endpoint="$1"
local data_name="$2"
local is_wrapped="$3" # true/false
local is_wrapped="$3" # true/false
local data
data=$(gh api "$endpoint" 2>/dev/null || echo "[]")
data=$(gh api "$endpoint" 2> /dev/null || echo "[]")
if [[ "$is_wrapped" == "true" ]]; then
data=$(echo "$data" | jq '{comments: .}' 2>/dev/null || echo '{"comments":[]}')
data=$(echo "$data" | jq '{comments: .}' 2> /dev/null || echo '{"comments":[]}')
fi
data=$(filter_coderabbit_addressed_comments "$data" "$is_wrapped")
@@ -94,14 +94,12 @@ fetch_and_filter_data()
[[ "$is_wrapped" == "true" ]] && count_field=".comments | length"
local count
count=$(echo "$data" | jq -r "$count_field" 2>/dev/null || echo "0")
count=$(echo "$data" | jq -r "$count_field" 2> /dev/null || echo "0")
log_debug "$data_name count: $count"
echo "$data"
}
# Format file-specific comments grouped by review
format_grouped_review_comments()
{
@@ -110,7 +108,7 @@ format_grouped_review_comments()
local repo="$3"
local count
count=$(echo "$review_comments" | jq -r 'length' 2>/dev/null || echo "0")
count=$(echo "$review_comments" | jq -r 'length' 2> /dev/null || echo "0")
if [[ "$count" -eq 0 ]]; then
echo "No file-specific comments found."
@@ -143,7 +141,7 @@ Review ID: \($review.id) - API: gh api /repos/'"$repo"'/pulls/1/reviews/\($revie
"] | join("")) + "
---
"
' 2>/dev/null || {
' 2> /dev/null || {
log_debug "Error grouping review comments by review ID"
echo "Error parsing grouped review comments."
}
@@ -244,7 +242,7 @@ EOF
**URL:** \(.url)
**Number:** '"$pr_number"'
**Repository:** '"$repo"'
"' 2>/dev/null || {
"' 2> /dev/null || {
echo "**Error:** Could not parse PR information"
return 1
}

2
local/bin/x-ssh-audit Normal file → Executable file
View File

@@ -350,7 +350,7 @@ ssh_with_retry()
log_message "INFO" "Trying SSH agent/default authentication"
fi
# shellcheck disable=SC2086
# shellcheck disable=SC2086,SC2029
if ssh $ssh_opts "${username}@${host}" "$command" 2> /dev/null; then
if [ "$try_key" != "NO_KEY" ]; then
log_message "SUCCESS" "Connected using SSH key: $try_key"

View File

@@ -52,17 +52,18 @@ fi
for name in "$@"; do
# Make a temporary file
# Test if we have BSD or GNU version of mktemp
if (strings "$(which mktemp)" | grep -q GNU); then
# We have the GNU version
tmp=$(mktemp)
# Try GNU syntax first, fall back to BSD
if tmp=$(mktemp 2> /dev/null) && [ -f "$tmp" ]; then
# GNU mktemp succeeded
:
else
# We have the BSD version
# Try BSD syntax
tmp=$(mktemp -t tmp)
fi
# Download the certificate
if (! echo "" | openssl s_client -connect "$name:$port" > "$tmp" 2> /dev/null); then
rm -f "$tmp"
echo "Failed to get cert from https://$name:$port/"
exit 3
fi
@@ -74,26 +75,26 @@ for name in "$@"; do
rm -f "$tmp"
# Convert the expiry date + todays date to seconds-past epoch
# Check if we have the BSD or the GNU version of date
if (strings "$(which date)" | grep -q GNU); then
# We have GNU this is easy
then=$(date --date "$date" +%s)
# Try GNU syntax first, fall back to BSD
if then=$(date --date "$date" +%s 2> /dev/null); then
# GNU date succeeded
:
else
# We have BSD now it is getting complicated
# BSD date requires manual parsing
year=$(echo "$date" | awk '{print $4}')
month=$(echo "$date" | awk '{print $1}')
day=$(echo "$date" | awk '{print $2}')
hour=$(echo "$date" | awk '{print $3}' | awk -F: '{print $1}')
minute=$(echo "$date" | awk '{print $3}' | awk -F: '{print $2}')
second=$(echo "$date" | awk '{print $3}' | awk -F: '{print $3}')
then=$(date -v${year}y -v${month} -v${day}d -v${hour}H -v${minute}M -v${second}S -u +%s)
then=$(date -v"${year}"y -v"${month}" -v"${day}"d -v"${hour}"H -v"${minute}"M -v"${second}"S -u +%s)
fi
now=$(date +%s)
# Day diff
diff=$(("$then" - "$now"))
diff=$($diff / 86400)
diff=$((diff / 86400))
# All done
if [ "$days" = "1" ]; then

View File

@@ -24,10 +24,10 @@ resetOutput()
# ranging between 0 and 255 inclusive
rainbowColor()
{
let h=$1/43
let f=$1-43*$h
let t=$f*255/43
let q=255-t
((h = $1 / 43))
((f = $1 - 43 * h))
((t = f * 255 / 43))
((q = 255 - t))
if [ $h -eq 0 ]; then
echo "255 $t 0"
@@ -81,11 +81,13 @@ done
resetOutput
for i in $(seq 0 127); do
# shellcheck disable=SC2046 # Intentional word splitting to pass 3 RGB values as separate args
setBackgroundColor $(rainbowColor "$i")
echo -n " "
done
resetOutput
for i in $(seq 255 128); do
# shellcheck disable=SC2046 # Intentional word splitting to pass 3 RGB values as separate args
setBackgroundColor $(rainbowColor "$i")
echo -n " "
done

View File

@@ -126,8 +126,8 @@ parse_options()
# Generate thumbnails recursively using find and filtering by MIME type
generate_thumbnails()
{
local source_dir=$1
local output_dir=$2
local source_dir="$1"
local output_dir="$2"
# Ensure the output directory exists (create if necessary)
if [ ! -d "$output_dir" ]; then
@@ -144,7 +144,7 @@ generate_thumbnails()
fi
# Determine the relative path with respect to the source directory.
rel_path="${file#$source_dir/}"
rel_path="${file#"$source_dir"/}"
dir="$(dirname "$rel_path")"
base="$(basename "$rel_path")"
filename="${base%.*}"