4 command -v "$1" >/dev
/null
2>/dev
/null
10 if has_command glow
; then
12 elif has_command batcat
; then
13 DECODER
="batcat -pp --decorations=always --color=always --language markdown"
14 printf "Markdown rendering will be done by bat. (Glow is recommended)\n"
15 elif has_command bat
; then
16 DECODER
="bat -pp --decorations=always --color=always --language markdown"
17 printf "Markdown rendering will be done by bat. (Glow is recommended)\n"
18 elif has_command pygmentize
; then
19 DECODER
="pygmentize -l markdown"
20 printf "Markdown rendering will be done by pygmentize. (Glow is recommended)\n"
21 elif has_command highlight
; then
22 DECODER
="highlight --out-format ansi --syntax markdown"
23 printf "Markdown rendering will be done by highlight. (Glow is recommended)\n"
25 printf "Install glow for easier reading & copy-paste.\n"
52 ${FG_WHITE}${BG_MAGENTA}${FX_BOLD}xdg-ninja${FX_RESET}
54 ${FX_BOLD}${FX_ITALIC}Check your \$HOME for unwanted files.${FX_RESET}
56 ────────────────────────────────────
58 ${FX_ITALIC}--help${FX_RESET} ${FX_BOLD}This help menu${FX_RESET}
59 ${FX_ITALIC}-h\033${FX_RESET}
61 ${FX_ITALIC}--no-skip-ok${FX_RESET} ${FX_BOLD}Display messages for all files checked (verbose)${FX_RESET}
62 ${FX_ITALIC}-v${FX_RESET}
64 ${FX_ITALIC}--skip-ok${FX_RESET} ${FX_BOLD}Don't display anything for files that do not exist (default)${FX_RESET}
66 ${FX_ITALIC}--skip-unsupported${FX_RESET} ${FX_BOLD}Don't display anything for files that do not have fixes available${FX_RESET}
69 printf "%b" "$HELPSTRING"
73 SKIP_UNSUPPORTED
=false
75 if [ "$i" = "--help" ] || [ "$i" = "-h" ]; then
78 elif [ "$i" = "--skip-ok" ]; then
80 elif [ "$i" = "--no-skip-ok" ]; then
82 elif [ "$i" = "--skip-unsupported" ]; then
84 elif [ "$i" = "-v" ]; then
89 if [ -z "${XDG_DATA_HOME}" ]; then
90 printf '%b%s%b\n' "${FX_BOLD}${FG_CYAN}" "The \$XDG_DATA_HOME environment variable is not set, make sure to add it to your shell's configuration before setting any of the other environment variables!" "${FX_RESET}"
91 printf "%b ⤷ The recommended value is: %b\$HOME/.local/share%b\n" "${FX_BOLD}${FG_CYAN}" "${FX_BOLD}${FX_ITALIC}" "${FX_RESET}"
93 if [ -z "${XDG_CONFIG_HOME}" ]; then
94 printf '%b%s%b\n' "${FX_BOLD}${FG_CYAN}" "The \$XDG_CONFIG_HOME environment variable is not set, make sure to add it to your shell's configuration before setting any of the other environment variables!" "${FX_RESET}"
95 printf "%b ⤷ The recommended value is: %b\$HOME/.config%b\n" "${FX_BOLD}${FG_CYAN}" "${FX_BOLD}${FX_ITALIC}" "${FX_RESET}"
97 if [ -z "${XDG_STATE_HOME}" ]; then
98 printf '%b%s%b\n' "${FX_BOLD}${FG_CYAN}" "The \$XDG_STATE_HOME environment variable is not set, make sure to add it to your shell's configuration before setting any of the other environment variables!" "${FX_RESET}"
99 printf "%b ⤷ The recommended value is: %b\$HOME/.local/state%b\n" "${FX_BOLD}${FG_CYAN}" "${FX_BOLD}${FX_ITALIC}" "${FX_RESET}"
101 if [ -z "${XDG_CACHE_HOME}" ]; then
102 printf '%b%s%b\n' "${FX_BOLD}${FG_CYAN}" "The \$XDG_CACHE_HOME environment variable is not set, make sure to add it to your shell's configuration before setting any of the other environment variables!" "${FX_RESET}"
103 printf "%b ⤷ The recommended value is: %b\$HOME/.cache%b\n" "${FX_BOLD}${FG_CYAN}" "${FX_BOLD}${FX_ITALIC}" "${FX_RESET}"
105 if [ -z "${XDG_RUNTIME_DIR}" ]; then
106 printf '%b%s%b\n' "${FX_BOLD}${FG_CYAN}" "The \$XDG_RUNTIME_DIR environment variable is not set, make sure to add it to your shell's configuration before setting any of the other environment variables!" "${FX_RESET}"
107 printf "%b ⤷ The recommended value is: %b/run/user/\$UID%b\n" "${FX_BOLD}${FG_CYAN}" "${FX_BOLD}${FX_ITALIC}" "${FX_RESET}"
110 if ! command -v jq
>/dev
/null
2>/dev
/null
; then
111 printf "jq is needed to run this script, but it wasn't found. Please install it to be able to use this script.\n"
117 # Function to expand environment variables in string
118 # https://stackoverflow.com/a/20316582/11110290
119 apply_shell_expansion
() {
121 delimiter
="__apply_shell_expansion_delimiter__"
122 command=$(printf "cat <<%s\n%s\n%s" "$delimiter" "$data" "$delimiter")
126 # Function to check if a string contains shell pattern matching
129 *\
** | *\?* | *\
[*\
]*)
138 # Returns the actual name of the given file that is on the user's disk
139 # This command applies shell pattern matching and return the actual filename
140 retrieve_existing_filename
() {
141 FILE_PATH
=$(apply_shell_expansion "$1")
143 # return filename if found, nothing else
144 if has_pattern
"$FILE_PATH"; then
145 dir
="$(dirname "$FILE_PATH")"
146 part
="$(basename "$FILE_PATH")"
147 find "$dir" -maxdepth 1 -name "$part" -print -quit 2>/dev
/null
149 if [ -e "$FILE_PATH" ]; then
150 printf "%s" "$FILE_PATH"
156 printf "%s" "$1" | sed -e 's/\\n/\
157 /g' -e 's/\\\"/\"/g' -e '$ s/\n*$/\
159 /' # Replace \n with literal newline and \" with ", normalize number of trailing newlines to 2
162 # Counter to keep track of how many files can be moved
165 # Function to handle the formatting of output
175 printf '[%b%s%b]: %b%s%b\n' "${FX_BOLD}${FG_RED}" "$NAME" "${FX_RESET}" "${FX_BOLD}${FX_ITALIC}" "$FILENAME" "${FX_RESET}"
176 FIXABLE
=$((FIXABLE+1))
180 [ "$SKIP_UNSUPPORTED" = false
] &&
181 printf '[%b%s%b]: %b%s%b\n' "${FX_BOLD}${FG_YELLOW}" "$NAME" "${FX_RESET}" "${FX_BOLD}${FX_ITALIC}" "$FILENAME" "${FX_RESET}"
185 printf '[%b%s%b]: %b%s%b\n' "${FX_BOLD}${FG_CYAN}" "$NAME" "${FX_RESET}" "${FX_BOLD}${FX_ITALIC}" "$FILENAME" "${FX_RESET}"
189 [ "$SKIP_OK" = false
] &&
190 printf '[%b%s%b]: %b%s%b\n' "${FX_BOLD}${FG_GREEN}" "$NAME" "${FX_RESET}" "${FX_BOLD}${FX_ITALIC}" "$FILENAME" "${FX_RESET}"
194 decode_string
"$HELP" | PAGER
="cat" $DECODER
200 # Checks that the given file does not exist, otherwise outputs help
207 file=$(retrieve_existing_filename "$FILENAME")
210 if [ "$MOVABLE" = true
]; then
211 log ERR
"$NAME" "$file" "$HELP"
213 log WARN
"$NAME" "$file" "$HELP"
216 if [ "$MOVABLE" = true
] || [ "$SKIP_UNSUPPORTED" = false
]; then
217 log HELP
"$NAME" "$file" "$HELP"
220 log HELP
"$NAME" "$file" "_No help available._"
223 log SUCS
"$NAME" "$file" "$HELP"
227 # Reads files from programs/, calls check_file on each file specified for each program
228 do_check_programs
() {
230 " read -r name
; read -r filename
; read -r movable
; read -r help; do
231 check_file
"$name" "$filename" "$movable" "$help"
233 $(jq '.files[] as $file | .name, $file.path, $file.movable, $file.help' "$XN_PROGRAMS_DIR"/* | sed -e 's/^"//' -e 's/"$//')
235 # sed is to trim quotes
239 printf "%bStarting to check your %b\$HOME%b.\n" "${FX_BOLD}${FX_ITALIC}" "${FG_CYAN}" "${FX_RESET}"
242 printf "%bDone checking your %b\$HOME.%b\n" "${FX_BOLD}${FX_ITALIC}" "${FG_CYAN}" "${FX_RESET}"
244 printf "%bIf you have files in your %b\$HOME%b that shouldn't be there, but weren't recognised by xdg-ninja, please consider creating a configuration file for it and opening a pull request on github.%b\n" "${FX_ITALIC}" "${FG_CYAN}" "${FX_RESET}${FX_ITALIC}" "${FX_RESET}"
248 [ "$XN_PROGRAMS_DIR" ] ||
249 XN_PROGRAMS_DIR
="$(realpath "$0" | xargs dirname | sed 's:/bin$:/share/xdg-ninja:g')/programs"
252 if [ $FIXABLE -gt 100 ]; then