fix(lint): fix all sonarcloud detected issues (#279)

* fix(ci): replace broad permissions with specific scopes in workflows

Replace read-all/write-all with minimum required permission scopes
across all GitHub Actions workflows to follow the principle of least
privilege (SonarCloud rule githubactions:S8234).

* fix(shell): use [[ instead of [ for conditional tests

Replace single brackets with double brackets in bash conditional
expressions across 14 files (28 changes). All scripts use bash
shebangs so [[ is safe everywhere (SonarCloud rule shelldre:S7688).

* fix(shell): add explicit return statements to functions

Add return 0 as the last statement in ~46 shell functions across
17 files that previously relied on implicit return codes
(SonarCloud rule shelldre:S7682).

* fix(shell): assign positional parameters to local variables

Replace direct $1/$2/$3 usage with named local variables in _log(),
msg(), msg_err(), msg_done(), msg_run(), msg_ok(), and array_diff()
(SonarCloud rule shelldre:S7679).

* fix(python): replace dict() constructor with literal

Use {} instead of dict() for empty dictionary initialization
(SonarCloud rule python:S7498).

* fix(shell): fix husky shebang and tolerate npm outdated exit code

* docs(shell): add function docstring comments

* fix(shell): fix heredoc indentation in x-sonarcloud

* feat(python): add ruff linter and formatter configuration

* fix(ci): align megalinter config with biome, ruff, and shfmt settings

* fix(ci): disable black and yaml-prettier in megalinter config

* chore(ci): update ruff-pre-commit to v0.15.0 and fix hook name

* fix(scripts): check for .git dir before skipping clone in install-fonts

* fix(shell): address code review issues in scripts and shared.sh

- Guard wezterm show-keys failure in create-wezterm-keymaps.sh
- Stop masking git failures with return 0 in install-cheat-purebashbible.sh
- Add missing shared.sh source in install-xcode-cli-tools.sh
- Replace exit 1 with return 1 in sourced shared.sh

* fix(scripts): address code review and security findings

- Guard wezterm show-keys failure in create-wezterm-keymaps.sh
- Stop masking git failures with return 0 in install-cheat-purebashbible.sh
- Add missing shared.sh source in install-xcode-cli-tools.sh
- Replace exit 1 with return 1 in sourced shared.sh
- Remove shell=True subprocess calls in x-git-largest-files.py

* style(shell): apply shfmt formatting and add args to pre-commit hook

* fix(python): suppress bandit false positives in x-git-largest-files

* fix(python): add nosemgrep suppression for check_output call

* feat(format): add prettier for YAML formatting

Install prettier, add .prettierrc.json config (200-char width, 2-space
indent, LF endings), .prettierignore, yarn scripts (lint:prettier,
fix:prettier, format:yaml), and pre-commit hook scoped to YAML files.

* style(yaml): apply prettier formatting

* fix(scripts): address remaining code review findings

- Python: use list comprehension to filter empty strings instead of
  slicing off the last element
- create-wezterm-keymaps: write to temp file and mv for atomic updates
- install-xcode-cli-tools: fix shellcheck source directive path

* fix(python): sort imports alphabetically in x-git-largest-files

* fix(lint): disable PYTHON_ISORT in MegaLinter, ruff handles it

* chore(git): add __pycache__ to gitignore

* fix(python): rename ambiguous variable l to line (E741)

* style: remove trailing whitespace and blank lines

* style(fzf): apply shfmt formatting

* style(shell): apply shfmt formatting

* docs(plans): add design documents

* style(docs): add language specifier to fenced code block

* feat(lint): add markdown-table-formatter to dev tooling

Add markdown-table-formatter as a dev dependency with yarn scripts
(lint:md-table, fix:md-table) and a local pre-commit hook to
automatically format markdown tables on commit.
This commit is contained in:
2026-02-07 19:01:02 +02:00
committed by GitHub
parent cff3d1dd8a
commit 6d72003446
86 changed files with 1264 additions and 425 deletions

View File

@@ -7,6 +7,7 @@ set -euo pipefail
source "${DOTFILES}/config/shared.sh"
DEST="$HOME/.dotfiles/docs/nvim-keybindings.md"
# Generate Neovim keybindings documentation
main()
{
msg "Generating Neovim keybindings documentation"
@@ -28,6 +29,7 @@ main()
&& mv "${DEST}.tmp" "$DEST"
msg "Neovim keybindings documentation generated at $DEST"
return 0
}
main "$@"

View File

@@ -6,20 +6,30 @@
source "${DOTFILES}/config/shared.sh"
DEST="$HOME/.dotfiles/docs/wezterm-keybindings.md"
# Generate wezterm keybindings documentation
main()
{
msg "Generating wezterm keybindings documentation"
local tmp
tmp="$(mktemp)"
trap 'rm -f "$tmp"' RETURN
{
printf "# wezterm keybindings\n\n"
printf "\`\`\`txt\n"
} > "$DEST"
} > "$tmp"
wezterm show-keys >> "$DEST"
if ! wezterm show-keys >> "$tmp"; then
msg "Failed to run 'wezterm show-keys'"
return 1
fi
printf "\`\`\`\n\n- Generated on %s\n" "$(date)" >> "$DEST"
printf "\`\`\`\n\n- Generated on %s\n" "$(date)" >> "$tmp"
mv "$tmp" "$DEST"
msg "wezterm keybindings documentation generated at $DEST"
return 0
}
main "$@"

View File

@@ -14,33 +14,34 @@ fi
packages=(
# Build essentials
build-essential # gcc, g++, make
cmake # Cross-platform build system
pkg-config # Helper for compiling against libraries
autoconf # Automatic configure script builder
automake # Makefile generator
libtool # Generic library support script
build-essential # gcc, g++, make
cmake # Cross-platform build system
pkg-config # Helper for compiling against libraries
autoconf # Automatic configure script builder
automake # Makefile generator
libtool # Generic library support script
# Libraries for compiling languages
libssl-dev # SSL development headers
libffi-dev # Foreign function interface
zlib1g-dev # Compression library
libreadline-dev # Command-line editing
libbz2-dev # Bzip2 compression
libsqlite3-dev # SQLite database
libncurses-dev # Terminal UI library
libssl-dev # SSL development headers
libffi-dev # Foreign function interface
zlib1g-dev # Compression library
libreadline-dev # Command-line editing
libbz2-dev # Bzip2 compression
libsqlite3-dev # SQLite database
libncurses-dev # Terminal UI library
# CLI utilities (not in cargo/go/npm)
jq # JSON processor
tmux # Terminal multiplexer
tree # Directory listing
unzip # Archive extraction
shellcheck # Shell script linter
socat # Multipurpose network relay
gnupg # GPG encryption/signing
software-properties-common # add-apt-repository command
jq # JSON processor
tmux # Terminal multiplexer
tree # Directory listing
unzip # Archive extraction
shellcheck # Shell script linter
socat # Multipurpose network relay
gnupg # GPG encryption/signing
software-properties-common # add-apt-repository command
)
# Install apt packages that are not already present
install_packages()
{
local to_install=()
@@ -64,12 +65,15 @@ install_packages()
else
msgr ok "All packages already installed"
fi
return 0
}
# Install all apt packages and report completion
main()
{
install_packages
msgr yay "apt package installations complete"
return 0
}
main "$@"

View File

@@ -25,18 +25,18 @@ fi
# Cargo packages to install
packages=(
cargo-update # A cargo subcommand for checking and applying updates to installed executables
cargo-cache # Cargo cache management utility
tree-sitter-cli # An incremental parsing system for programming tools
bkt # A subprocess caching utility
difftastic # A structural diff that understands syntax
fd-find # A simple, fast and user-friendly alternative to 'find'
ripgrep # Recursively searches directories for a regex pattern while respecting your gitignore
bob-nvim # A version manager for neovim
bottom # A cross-platform graphical process/system monitor
eza # A modern alternative to ls
tmux-sessionizer # A tool for opening git repositories as tmux sessions
zoxide # A smarter cd command
cargo-update # A cargo subcommand for checking and applying updates to installed executables
cargo-cache # Cargo cache management utility
tree-sitter-cli # An incremental parsing system for programming tools
bkt # A subprocess caching utility
difftastic # A structural diff that understands syntax
fd-find # A simple, fast and user-friendly alternative to 'find'
ripgrep # Recursively searches directories for a regex pattern while respecting your gitignore
bob-nvim # A version manager for neovim
bottom # A cross-platform graphical process/system monitor
eza # A modern alternative to ls
tmux-sessionizer # A tool for opening git repositories as tmux sessions
zoxide # A smarter cd command
)
# Number of jobs to run in parallel, this helps to keep the system responsive
@@ -57,6 +57,7 @@ install_packages()
msgr run_done "Done installing $pkg"
echo ""
done
return 0
}
# Function to perform additional steps for installed cargo packages
@@ -72,13 +73,16 @@ post_install_steps()
msgr run "Removing cargo cache"
cargo cache --autoclean
msgr "done" "Done removing cargo cache"
return 0
}
# Install cargo packages and run post-install steps
main()
{
install_packages
msgr "done" "Installed cargo packages!"
post_install_steps
return 0
}
main "$@"

View File

@@ -12,6 +12,7 @@ PBB_SYNTAX="syntax: bash"
PBB_TAGS="tags: [bash]"
PBB_TEMP_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/cheat/pbb"
# Verify required tools are installed
check_required_tools()
{
for t in "${PBB_REQUIRED_TOOLS[@]}"; do
@@ -20,32 +21,37 @@ check_required_tools()
exit 1
fi
done
return 0
}
# Clone or update the pure-bash-bible repository
clone_or_update_repo()
{
if [ ! -d "$PBB_TEMP_DIR/.git" ]; then
if [[ ! -d "$PBB_TEMP_DIR/.git" ]]; then
msg_run "Starting to clone $PBB_GIT"
git clone --depth 1 --single-branch -q "$PBB_GIT" "$PBB_TEMP_DIR" \
&& msg_yay "Cloned $PBB_GIT"
git clone --depth 1 --single-branch -q "$PBB_GIT" "$PBB_TEMP_DIR"
msg_yay "Cloned $PBB_GIT"
else
msg_run "Starting to update $PBB_GIT"
git -C "$PBB_TEMP_DIR" reset --hard origin/master
git -C "$PBB_TEMP_DIR" pull -q \
&& msgr yay "Updated $PBB_GIT"
git -C "$PBB_TEMP_DIR" pull -q
msg_yay "Updated $PBB_GIT"
fi
return 0
}
# Get the cheat destination directory for pure-bash-bible
prepare_cheat_dest()
{
local cheat_dest
cheat_dest="$(cheat -d | grep pure-bash-bible | head -1 | awk '{print $2}')"
if [ ! -d "$cheat_dest" ]; then
if [[ ! -d "$cheat_dest" ]]; then
mkdir -p "$cheat_dest"
fi
echo "$cheat_dest"
return 0
}
# Processes chapter files from the pure-bash-bible repository and generates or updates corresponding cheat sheets.
@@ -83,19 +89,22 @@ process_chapters()
LC_ALL=C perl -pi.bak -e 's/\<\!-- CHAPTER END --\>//' "$cheat_file"
rm "$cheat_file.bak"
if [ '---' != "$(head -1 < "$cheat_file")" ]; then
if [[ '---' != "$(head -1 < "$cheat_file")" ]]; then
local metadata
metadata="$PBB_SYNTAX\n$PBB_TAGS\n$PBB_SOURCE\n"
printf '%s\n%b%s\n%s' "---" "$metadata" "---" "$(cat "$cheat_file")" > "$cheat_file"
fi
done
return 0
}
# Install pure-bash-bible cheatsheets
main()
{
check_required_tools
clone_or_update_repo
process_chapters
return 0
}
main "$@"

View File

@@ -14,7 +14,7 @@ EXPECTED_CHECKSUM="$(php -r 'copy("https://composer.github.io/installer.sig", "p
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]; then
if [[ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]]; then
echo >&2 'ERROR: Invalid installer checksum'
rm composer-setup.php
exit 1
@@ -23,7 +23,7 @@ fi
php composer-setup.php --quiet
RESULT=$?
rm composer-setup.php
if [ $RESULT -eq 0 ]; then
if [[ $RESULT -eq 0 ]]; then
mv composer.phar ~/.local/bin/composer
fi
exit $RESULT

View File

@@ -14,41 +14,44 @@ fi
packages=(
# Build essentials (individual packages, group handled separately)
cmake # Cross-platform build system
pkgconfig # Helper for compiling against libraries
autoconf # Automatic configure script builder
automake # Makefile generator
libtool # Generic library support script
cmake # Cross-platform build system
pkgconfig # Helper for compiling against libraries
autoconf # Automatic configure script builder
automake # Makefile generator
libtool # Generic library support script
# Libraries for compiling languages
openssl-devel # SSL development headers
libffi-devel # Foreign function interface
zlib-devel # Compression library
readline-devel # Command-line editing
bzip2-devel # Bzip2 compression
sqlite-devel # SQLite database
ncurses-devel # Terminal UI library
openssl-devel # SSL development headers
libffi-devel # Foreign function interface
zlib-devel # Compression library
readline-devel # Command-line editing
bzip2-devel # Bzip2 compression
sqlite-devel # SQLite database
ncurses-devel # Terminal UI library
# CLI utilities (not in cargo/go/npm)
jq # JSON processor
tmux # Terminal multiplexer
tree # Directory listing
unzip # Archive extraction
ShellCheck # Shell script linter
socat # Multipurpose network relay
gnupg2 # GPG encryption/signing
jq # JSON processor
tmux # Terminal multiplexer
tree # Directory listing
unzip # Archive extraction
ShellCheck # Shell script linter
socat # Multipurpose network relay
gnupg2 # GPG encryption/signing
)
# Install the Development Tools dnf group
install_dev_tools_group()
{
if dnf group list installed 2>/dev/null | grep -q "Development Tools"; then
if dnf group list installed 2> /dev/null | grep -q "Development Tools"; then
msgr ok "@development-tools group already installed"
else
msgr run "Installing @development-tools group"
sudo dnf group install -y "Development Tools"
fi
return 0
}
# Install dnf packages that are not already present
install_packages()
{
local to_install=()
@@ -71,13 +74,16 @@ install_packages()
else
msgr ok "All packages already installed"
fi
return 0
}
# Install all dnf packages and report completion
main()
{
install_dev_tools_group
install_packages
msgr yay "dnf package installations complete"
return 0
}
main "$@"

View File

@@ -18,11 +18,16 @@ fonts=(
# Function to clone or update the NerdFonts repository
clone_or_update_repo()
{
if [ ! -d "$TMP_PATH" ]; then
if [[ ! -d "$TMP_PATH/.git" ]]; then
rm -rf "$TMP_PATH"
git clone --quiet --filter=blob:none --sparse --depth=1 "$GIT_REPO" "$TMP_PATH"
fi
cd "$TMP_PATH" || { msgr err "No such folder $TMP_PATH"; exit 1; }
cd "$TMP_PATH" || {
msgr err "No such folder $TMP_PATH"
exit 1
}
return 0
}
# Function to add fonts to sparse-checkout
@@ -38,6 +43,7 @@ add_fonts_to_sparse_checkout()
git sparse-checkout add "patched-fonts/$font"
echo ""
done
return 0
}
# Function to install NerdFonts
@@ -47,19 +53,24 @@ install_fonts()
# shellcheck disable=SC2048,SC2086
./install.sh -q -s ${fonts[*]}
msgr run_done "Done"
return 0
}
# Remove the temporary nerd-fonts clone directory
remove_tmp_path()
{
rm -rf "$TMP_PATH"
return 0
}
# Clone, sparse-checkout, install fonts, and clean up
main()
{
clone_or_update_repo
add_fonts_to_sparse_checkout
install_fonts
remove_tmp_path
return 0
}
main "$@"

View File

@@ -45,12 +45,15 @@ install_extensions()
gh extension install "$ext"
echo ""
done
return 0
}
# Install all GitHub CLI extensions
main()
{
install_extensions
msgr run_done "Done"
return 0
}
main "$@"

View File

@@ -15,9 +15,15 @@ if ! command -v git-crypt &> /dev/null; then
BUILD_PATH="$(mktemp -d)"
trap 'rm -rf "$BUILD_PATH"' EXIT
if [ ! -f "$CHECK_PATH" ]; then
git clone --depth 1 "$REPO_URL" "$BUILD_PATH" || { msgr err "Failed to clone $REPO_URL"; exit 1; }
cd "$BUILD_PATH" || { msgr err "$BUILD_PATH not found"; exit 1; }
if [[ ! -f "$CHECK_PATH" ]]; then
git clone --depth 1 "$REPO_URL" "$BUILD_PATH" || {
msgr err "Failed to clone $REPO_URL"
exit 1
}
cd "$BUILD_PATH" || {
msgr err "$BUILD_PATH not found"
exit 1
}
make && make install PREFIX="$HOME/.local"
else
msgr run_done "git-crypt ($CHECK_PATH) already installed"

View File

@@ -11,13 +11,13 @@ msgr run "Installing go packages"
# Go packages to install
packages=(
github.com/dotzero/git-profile@latest # Switch between git user profiles
github.com/google/yamlfmt/cmd/yamlfmt@latest # Format yaml files
github.com/cheat/cheat/cmd/cheat@latest # Interactive cheatsheets on the CLI
github.com/charmbracelet/glow@latest # Render markdown on the CLI
github.com/junegunn/fzf@latest # General-purpose fuzzy finder
github.com/charmbracelet/gum@latest # Glamorous shell scripts
github.com/joshmedeski/sesh/v2@latest # Terminal session manager
github.com/dotzero/git-profile@latest # Switch between git user profiles
github.com/google/yamlfmt/cmd/yamlfmt@latest # Format yaml files
github.com/cheat/cheat/cmd/cheat@latest # Interactive cheatsheets on the CLI
github.com/charmbracelet/glow@latest # Render markdown on the CLI
github.com/junegunn/fzf@latest # General-purpose fuzzy finder
github.com/charmbracelet/gum@latest # Glamorous shell scripts
github.com/joshmedeski/sesh/v2@latest # Terminal session manager
)
# Function to install go packages
@@ -33,6 +33,7 @@ install_packages()
go install "$pkg"
echo ""
done
return 0
}
# Function to install completions and run actions for selected packages
@@ -44,6 +45,7 @@ post_install()
git-profile completion zsh > "$ZSH_CUSTOM_COMPLETION_PATH/_git-profile" \
&& msgr run_done "Installed completions for git-profile"
fi
return 0
}
# Function to clear go cache
@@ -51,14 +53,17 @@ clear_go_cache()
{
msgr run "Clearing go cache"
go clean -cache -modcache
return 0
}
# Install go packages, completions, and clear cache
main()
{
install_packages
post_install
clear_go_cache
msgr run_done "Done"
return 0
}
main "$@"

View File

@@ -5,7 +5,7 @@ set -uo pipefail
# This script contains large portions from following scripts:
# - https://github.com/freekmurze/dotfiles/blob/main/macos/set-defaults.sh
[ "$(uname)" != "Darwin" ] && echo "Not a macOS system" && exit 0
[[ "$(uname)" != "Darwin" ]] && echo "Not a macOS system" && exit 0
# shellcheck source=shared.sh
source "$DOTFILES/config/shared.sh"

View File

@@ -13,10 +13,10 @@ if ! command -v npm &> /dev/null; then
fi
packages=(
editorconfig-checker # Check files against .editorconfig rules
github-release-notes # Create release notes from tags and issues
neovim # Neovim node client
corepack # Node.js package manager version management
editorconfig-checker # Check files against .editorconfig rules
github-release-notes # Create release notes from tags and issues
neovim # Neovim node client
corepack # Node.js package manager version management
)
# Function to install npm packages
@@ -36,14 +36,16 @@ install_packages()
fi
echo ""
done
return 0
}
# Function to upgrade all global npm packages
upgrade_global_packages()
{
msgr run "Upgrading all global packages"
npm -g --no-progress --no-timing --no-fund outdated
npm -g --no-progress --no-timing --no-fund outdated || true
npm -g --no-timing --no-fund upgrade
return 0
}
# Function to clean npm cache
@@ -53,14 +55,17 @@ clean_npm_cache()
npm cache verify
npm cache clean --force
npm cache verify
return 0
}
# Install, upgrade, and clean npm packages
main()
{
install_packages
upgrade_global_packages
clean_npm_cache
msgr yay "npm package installations complete"
return 0
}
main "$@"

View File

@@ -43,15 +43,18 @@ install_ntfy()
mkdir -p ~/.config/ntfy
# Copy config only if it does not exist
if [ ! -f "$HOME/.config/ntfy/client.yml" ]; then
if [[ ! -f "$HOME/.config/ntfy/client.yml" ]]; then
cp "$tmpdir/${NTFY_DIR}/client/client.yml" ~/.config/ntfy/client.yml
fi
return 0
}
# Download and install ntfy
main()
{
install_ntfy
msgr "done" "ntfy installation complete"
return 0
}
main "$@"

View File

@@ -16,14 +16,15 @@ fi
# CLI tools — installed isolated with `uv tool install`
tools=(
ansible # IT automation and configuration management
openapi-python-client # Generate Python API clients from OpenAPI specs
ansible # IT automation and configuration management
openapi-python-client # Generate Python API clients from OpenAPI specs
ruff # Fast Python linter and formatter
)
# Library packages — installed into system Python with `uv pip install --system`
libraries=(
libtmux # Python API for tmux
pynvim # Neovim Python client
libtmux # Python API for tmux
pynvim # Neovim Python client
)
# Function to install CLI tools via uv tool install
@@ -40,6 +41,7 @@ install_tools()
uv tool install --upgrade "$pkg"
echo ""
done
return 0
}
# Function to install library packages via uv pip install
@@ -56,6 +58,7 @@ install_libraries()
uv pip install --system --upgrade "$pkg"
echo ""
done
return 0
}
# Function to upgrade all uv-managed tools
@@ -63,14 +66,17 @@ upgrade_tools()
{
msgr run "Upgrading all uv-managed tools"
uv tool upgrade --all
return 0
}
# Install Python tools, libraries, and upgrade all
main()
{
install_tools
install_libraries
upgrade_tools
msgr yay "Python package installations complete"
return 0
}
main "$@"

View File

@@ -3,9 +3,11 @@ set -euo pipefail
# @description Install XCode CLI Tools with osascript magic.
# Ismo Vuorinen <https://github.com/ivuorinen> 2018
#
# shellcheck source=../config/shared.sh
source "${DOTFILES}/config/shared.sh"
# Check if the script is running on macOS
if [ "$(uname)" != "Darwin" ]; then
if [[ "$(uname)" != "Darwin" ]]; then
msgr warn "Not a macOS system"
exit 0
fi
@@ -27,6 +29,7 @@ keep_alive_sudo()
sleep 60
kill -0 "$$" || exit
done 2> /dev/null &
return 0
}
XCODE_TOOLS_PATH="$(xcode-select -p)"
@@ -40,12 +43,13 @@ prompt_xcode_install()
'tell app "System Events" to display dialog "Please click install when Command Line Developer Tools appears"'
)"
if [ "$XCODE_MESSAGE" = "button returned:OK" ]; then
if [[ "$XCODE_MESSAGE" = "button returned:OK" ]]; then
xcode-select --install
else
msgr warn "You have cancelled the installation, please rerun the installer."
exit 1
fi
return 0
}
# Main function
@@ -53,16 +57,17 @@ main()
{
keep_alive_sudo
if [ -x "$XCODE_SWIFT_PATH" ]; then
if [[ -x "$XCODE_SWIFT_PATH" ]]; then
msgr run "You have swift from xcode-select. Continuing..."
else
prompt_xcode_install
fi
until [ -f "$XCODE_SWIFT_PATH" ]; do
until [[ -f "$XCODE_SWIFT_PATH" ]]; do
echo -n "."
sleep 1
done
return 0
}
main "$@"

View File

@@ -14,18 +14,20 @@ clone_z_repo()
local git_path=$1
local bin_path=$2
if [ ! -d "$bin_path" ]; then
if [[ ! -d "$bin_path" ]]; then
git clone "$git_path" "$bin_path"
msgr run_done "z installed at $bin_path"
else
msgr ok "z ($bin_path/) already installed"
fi
return 0
}
# Main function
main()
{
clone_z_repo "$Z_GIT_PATH" "$Z_BIN_PATH"
return 0
}
main "$@"

View File

@@ -5,7 +5,7 @@
: "${VERBOSE:=0}"
# Source the main shared config if not already loaded
if [ -z "${SHARED_SCRIPTS_SOURCED:-}" ]; then
if [[ -z "${SHARED_SCRIPTS_SOURCED:-}" ]]; then
source "${DOTFILES}/config/shared.sh"
export SHARED_SCRIPTS_SOURCED=1
fi