]> glassweightruler.freedombox.rocks Git - xdg-ninja.git/blob - xdg-ninja.sh
Exit status = amount of fixable files
[xdg-ninja.git] / xdg-ninja.sh
1 #!/usr/bin/env sh
2
3 has_command() {
4 command -v "$1" >/dev/null 2>/dev/null
5 return $?
6 }
7
8 auto_set_decoder() {
9 DECODER="cat"
10 if has_command glow; then
11 DECODER="glow -"
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"
24 else
25 printf "Install glow for easier reading & copy-paste.\n"
26 fi
27 }
28 auto_set_decoder
29
30 unalias -a
31
32 init_constants() {
33 FX_RESET="\033[0m"
34 FX_BOLD="\033[1m"
35 FX_ITALIC="\033[3m"
36
37 FG_RED="\033[31m"
38 FG_GREEN="\033[32m"
39 FG_YELLOW="\033[33m"
40 FG_CYAN="\033[36m"
41 FG_WHITE="\033[37m"
42
43 BG_MAGENTA="\033[45m"
44 }
45 init_constants
46
47 help() {
48 init_constants
49 HELPSTRING="""\
50
51
52 ${FG_WHITE}${BG_MAGENTA}${FX_BOLD}xdg-ninja${FX_RESET}
53
54 ${FX_BOLD}${FX_ITALIC}Check your \$HOME for unwanted files.${FX_RESET}
55
56 ────────────────────────────────────
57
58 ${FX_ITALIC}--help${FX_RESET} ${FX_BOLD}This help menu${FX_RESET}
59 ${FX_ITALIC}-h\033${FX_RESET}
60
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}
63
64 ${FX_ITALIC}--skip-ok${FX_RESET} ${FX_BOLD}Don't display anything for files that do not exist (default)${FX_RESET}
65
66 """
67 printf "%b" "$HELPSTRING"
68 }
69
70 SKIP_OK=true
71 for i in "$@"; do
72 if [ "$i" = "--help" ] || [ "$i" = "-h" ]; then
73 help
74 exit
75 elif [ "$i" = "--skip-ok" ]; then
76 SKIP_OK=true
77 elif [ "$i" = "--no-skip-ok" ]; then
78 SKIP_OK=false
79 elif [ "$i" = "-v" ]; then
80 SKIP_OK=false
81 fi
82 done
83
84 if [ -z "${XDG_DATA_HOME}" ]; then
85 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}"
86 printf "%b ⤷ The recommended value is: %b\$HOME/.local/share%b\n" "${FX_BOLD}${FG_CYAN}" "${FX_BOLD}${FX_ITALIC}" "${FX_RESET}"
87 fi
88 if [ -z "${XDG_CONFIG_HOME}" ]; then
89 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}"
90 printf "%b ⤷ The recommended value is: %b\$HOME/.config%b\n" "${FX_BOLD}${FG_CYAN}" "${FX_BOLD}${FX_ITALIC}" "${FX_RESET}"
91 fi
92 if [ -z "${XDG_STATE_HOME}" ]; then
93 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}"
94 printf "%b ⤷ The recommended value is: %b\$HOME/.local/state%b\n" "${FX_BOLD}${FG_CYAN}" "${FX_BOLD}${FX_ITALIC}" "${FX_RESET}"
95 fi
96 if [ -z "${XDG_CACHE_HOME}" ]; then
97 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}"
98 printf "%b ⤷ The recommended value is: %b\$HOME/.cache%b\n" "${FX_BOLD}${FG_CYAN}" "${FX_BOLD}${FX_ITALIC}" "${FX_RESET}"
99 fi
100 if [ -z "${XDG_RUNTIME_DIR}" ]; then
101 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}"
102 printf "%b ⤷ The recommended value is: %b/run/user/\$UID%b\n" "${FX_BOLD}${FG_CYAN}" "${FX_BOLD}${FX_ITALIC}" "${FX_RESET}"
103 fi
104
105 if ! command -v jq >/dev/null 2>/dev/null; then
106 printf "jq is needed to run this script, but it wasn't found. Please install it to be able to use this script.\n"
107 exit
108 fi
109
110 printf "\n"
111
112 # Function to expand environment variables in string
113 # https://stackoverflow.com/a/20316582/11110290
114 apply_shell_expansion() {
115 data="$1"
116 delimiter="__apply_shell_expansion_delimiter__"
117 command=$(printf "cat <<%s\n%s\n%s" "$delimiter" "$data" "$delimiter")
118 eval "$command"
119 }
120
121 # Returns 0 if the path doesn't lead anywhere
122 # Returns 1 if the path leads to something
123 check_if_file_exists() {
124 FILE_PATH=$(apply_shell_expansion "$1")
125 if [ -e "$FILE_PATH" ]; then
126 return 1
127 else
128 return 0
129 fi
130 }
131
132 decode_string() {
133 printf "%s" "$1" | sed -e 's/\\n/\
134 /g' -e 's/\\\"/\"/g' -e '$ s/\n*$/\
135 \
136 /' # Replace \n with literal newline and \" with ", normalize number of trailing newlines to 2
137 }
138
139 # Counter to keep track of how many files can be moved
140 FIXABLE=0
141
142 # Function to handle the formatting of output
143 log() {
144 MODE="$1"
145 NAME="$2"
146 FILENAME="$3"
147 HELP="$4"
148
149 case "$MODE" in
150
151 ERR)
152 printf '[%b%s%b]: %b%s%b\n' "${FX_BOLD}${FG_RED}" "$NAME" "${FX_RESET}" "${FX_BOLD}${FX_ITALIC}" "$FILENAME" "${FX_RESET}"
153 FIXABLE=$((FIXABLE+1))
154 ;;
155
156 WARN)
157 printf '[%b%s%b]: %b%s%b\n' "${FX_BOLD}${FG_YELLOW}" "$NAME" "${FX_RESET}" "${FX_BOLD}${FX_ITALIC}" "$FILENAME" "${FX_RESET}"
158 ;;
159
160 INFO)
161 printf '[%b%s%b]: %b%s%b\n' "${FX_BOLD}${FG_CYAN}" "$NAME" "${FX_RESET}" "${FX_BOLD}${FX_ITALIC}" "$FILENAME" "${FX_RESET}"
162 ;;
163
164 SUCS)
165 [ "$SKIP_OK" = false ] &&
166 printf '[%b%s%b]: %b%s%b\n' "${FX_BOLD}${FG_GREEN}" "$NAME" "${FX_RESET}" "${FX_BOLD}${FX_ITALIC}" "$FILENAME" "${FX_RESET}"
167 ;;
168
169 HELP)
170 decode_string "$HELP" | PAGER="cat" $DECODER
171 ;;
172
173 esac
174 }
175
176 # Checks that the given file does not exist, otherwise outputs help
177 check_file() {
178 NAME="$1"
179 FILENAME="$2"
180 MOVABLE="$3"
181 HELP="$4"
182
183 check_if_file_exists "$FILENAME"
184
185 case $? in
186
187 0)
188 log SUCS "$NAME" "$FILENAME" "$HELP"
189 ;;
190
191 1)
192 if [ "$MOVABLE" = true ]; then
193 log ERR "$NAME" "$FILENAME" "$HELP"
194 else
195 log WARN "$NAME" "$FILENAME" "$HELP"
196 fi
197 if [ "$HELP" ]; then
198 log HELP "$NAME" "$FILENAME" "$HELP"
199 else
200 log HELP "$NAME" "$FILENAME" "_No help available._"
201 fi
202 ;;
203
204 esac
205 }
206
207 # Reads files from programs/, calls check_file on each file specified for each program
208 do_check_programs() {
209 while IFS="
210 " read -r name; read -r filename; read -r movable; read -r help; do
211 check_file "$name" "$filename" "$movable" "$help"
212 done <<EOF
213 $(jq 'inputs as $input | $input.files[] as $file | $input.name, $file.path, $file.movable, $file.help' "$(realpath "$0" | xargs dirname)"/programs/* | sed -e 's/^"//' -e 's/"$//')
214 EOF
215 # sed is to trim quotes
216 }
217
218 check_programs() {
219 printf "%bStarting to check your %b\$HOME%b.\n" "${FX_BOLD}${FX_ITALIC}" "${FG_CYAN}" "${FX_RESET}"
220 printf "\n"
221 do_check_programs
222 printf "%bDone checking your %b\$HOME.%b\n" "${FX_BOLD}${FX_ITALIC}" "${FG_CYAN}" "${FX_RESET}"
223 printf "\n"
224 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}"
225 printf "\n"
226 }
227
228
229 check_programs
230 exit $FIXABLE