Son aktivite 1 month ago

cmdctl е интерактивен мениджър за полезни команди с красив, модерен интерфейс.

urocibg bu gisti düzenledi 1 month ago. Düzenlemeye git

1 file changed, 6 insertions

cmdctl

@@ -1,5 +1,11 @@
1 1 #!/usr/bin/env bash
2 2
3 + # Автор: Федя Серафиев
4 + # Сайт / Проект: https://urocibg.eu
5 + # Версия: 2.0
6 + # Лиценз: Open Source
7 + # Платформа: Linux/Unix (Bash)
8 +
3 9 COMMANDS_FILE="$HOME/.fedya_commands"
4 10 EDITOR_CMD="${EDITOR:-nano}"
5 11

urocibg bu gisti düzenledi 1 month ago. Düzenlemeye git

1 file changed, 436 insertions

cmdctl(dosya oluşturuldu)

@@ -0,0 +1,436 @@
1 + #!/usr/bin/env bash
2 +
3 + COMMANDS_FILE="$HOME/.fedya_commands"
4 + EDITOR_CMD="${EDITOR:-nano}"
5 +
6 + # Модерна цветна палитра
7 + C_RESET=$'\033[0m'
8 + C_BOLD=$'\033[1m'
9 + C_DIM=$'\033[2m'
10 +
11 + # Основни цветове
12 + C_PRIMARY=$'\033[38;5;81m' # Светло синьо
13 + C_SUCCESS=$'\033[38;5;82m' # Зелено
14 + C_WARNING=$'\033[38;5;214m' # Оранжево
15 + C_ERROR=$'\033[38;5;196m' # Червено
16 + C_INFO=$'\033[38;5;147m' # Лавандула
17 +
18 + # Акцентни цветове
19 + C_TITLE=$'\033[38;5;213m' # Розово-лилаво
20 + C_KEY=$'\033[38;5;226m' # Жълто
21 + C_VAL=$'\033[38;5;153m' # Светло синьо
22 + C_DESC=$'\033[38;5;249m' # Светло сиво
23 + C_BORDER=$'\033[38;5;240m' # Сиво
24 +
25 + # Box drawing символи
26 + BOX_TL="╭"
27 + BOX_TR="╮"
28 + BOX_BL="╰"
29 + BOX_BR="╯"
30 + BOX_H="─"
31 + BOX_V="│"
32 + BOX_VR="├"
33 + BOX_VL="┤"
34 +
35 + ensure_file() {
36 + [ -f "$COMMANDS_FILE" ] || touch "$COMMANDS_FILE"
37 + }
38 +
39 + print_header() {
40 + local width=70
41 + clear
42 + echo
43 + printf "%b" "${C_PRIMARY}${C_BOLD}"
44 + printf "%s%${width}s%s\n" "$BOX_TL" "" "$BOX_TR" | tr ' ' "$BOX_H"
45 + printf "%s%-${width}s%s\n" "$BOX_V" " ⚡ CMDCTL - Мениджър за Полезни Команди" "$BOX_V"
46 + printf "%s%${width}s%s\n" "$BOX_BL" "" "$BOX_BR" | tr ' ' "$BOX_H"
47 + printf "%b\n" "${C_RESET}"
48 + }
49 +
50 + list_commands() {
51 + ensure_file
52 + print_header
53 +
54 + local count=$(grep -c '^#CMD:' "$COMMANDS_FILE" 2>/dev/null || echo 0)
55 +
56 + printf "%b%s %s%b\n" "${C_INFO}${C_BOLD}" "📦 Общо команди:" "$count" "${C_RESET}"
57 + printf "%b%s%b\n\n" "${C_DIM}" "Файл: $COMMANDS_FILE" "${C_RESET}"
58 +
59 + if [ "$count" -eq 0 ]; then
60 + printf "%b%s%b\n\n" "${C_WARNING}" " ⚠️ Няма запазени команди" "${C_RESET}"
61 + else
62 + local i=1
63 + while IFS= read -r line; do
64 + if [[ "$line" =~ ^#CMD: ]]; then
65 + local name="${line#\#CMD: }"
66 + read -r desc
67 + desc="${desc#\#DESC: }"
68 + read -r cmd
69 +
70 + printf "%b[%d]%b %b%s%b\n" "${C_KEY}${C_BOLD}" "$i" "${C_RESET}" "${C_PRIMARY}${C_BOLD}" "$name" "${C_RESET}"
71 + printf " %b%s%b\n" "${C_DESC}${C_DIM}" "$desc" "${C_RESET}"
72 + printf " %b➜%b %b%s%b\n\n" "${C_SUCCESS}" "${C_RESET}" "${C_VAL}" "$cmd" "${C_RESET}"
73 +
74 + ((i++))
75 + fi
76 + done < "$COMMANDS_FILE"
77 + fi
78 + }
79 +
80 + add_command() {
81 + ensure_file
82 + print_header
83 +
84 + printf "%b%s%b\n\n" "${C_SUCCESS}${C_BOLD}" "➕ Добавяне на нова команда" "${C_RESET}"
85 +
86 + printf "%b%s%b\n" "${C_DIM}" "Съвет: Използвай кратко и ясно име (напр: mikrotik-backup, ssh-keygen)" "${C_RESET}"
87 + printf "%b%s%b" "${C_INFO}" "Име на командата: " "${C_RESET}"
88 + read -r name
89 +
90 + if [ -z "$name" ]; then
91 + printf "\n%b%s%b\n" "${C_ERROR}" "❌ Името не може да бъде празно!" "${C_RESET}"
92 + sleep 2
93 + return
94 + fi
95 +
96 + # Проверка дали съществува
97 + if grep -q "^#CMD: $name$" "$COMMANDS_FILE" 2>/dev/null; then
98 + printf "\n%b%s%b\n" "${C_ERROR}" "❌ Команда '$name' вече съществува!" "${C_RESET}"
99 + sleep 2
100 + return
101 + fi
102 +
103 + printf "\n%b%s%b\n" "${C_DIM}" "Напиши кратко описание какво прави командата" "${C_RESET}"
104 + printf "%b%s%b" "${C_INFO}" "Описание: " "${C_RESET}"
105 + read -r desc
106 +
107 + if [ -z "$desc" ]; then
108 + printf "\n%b%s%b\n" "${C_ERROR}" "❌ Описанието не може да бъде празно!" "${C_RESET}"
109 + sleep 2
110 + return
111 + fi
112 +
113 + printf "\n%b%s%b\n" "${C_DIM}" "Въведи пълната команда (може да е многоредова)" "${C_RESET}"
114 + printf "%b%s%b" "${C_INFO}" "Команда: " "${C_RESET}"
115 + read -r cmd
116 +
117 + if [ -z "$cmd" ]; then
118 + printf "\n%b%s%b\n" "${C_ERROR}" "❌ Командата не може да бъде празна!" "${C_RESET}"
119 + sleep 2
120 + return
121 + fi
122 +
123 + # Запазване
124 + {
125 + echo "#CMD: $name"
126 + echo "#DESC: $desc"
127 + echo "$cmd"
128 + echo ""
129 + } >> "$COMMANDS_FILE"
130 +
131 + printf "\n%b%s%b %b%s%b\n" "${C_SUCCESS}${C_BOLD}" "✅ Успешно добавена:" "${C_RESET}" "${C_KEY}" "$name" "${C_RESET}"
132 + sleep 2
133 + }
134 +
135 + remove_command() {
136 + ensure_file
137 + print_header
138 +
139 + printf "%b%s%b\n\n" "${C_WARNING}${C_BOLD}" "🗑️ Премахване на команда" "${C_RESET}"
140 +
141 + local count=$(grep -c '^#CMD:' "$COMMANDS_FILE" 2>/dev/null || echo 0)
142 + if [ "$count" -eq 0 ]; then
143 + printf "%b%s%b\n" "${C_WARNING}" "⚠️ Няма команди за премахване" "${C_RESET}"
144 + sleep 2
145 + return
146 + fi
147 +
148 + printf "%b%s%b" "${C_INFO}" "Име на командата за премахване: " "${C_RESET}"
149 + read -r name
150 +
151 + if [ -z "$name" ]; then
152 + printf "\n%b%s%b\n" "${C_ERROR}" "❌ Не е въведено име!" "${C_RESET}"
153 + sleep 2
154 + return
155 + fi
156 +
157 + if grep -q "^#CMD: $name$" "$COMMANDS_FILE" 2>/dev/null; then
158 + # Изтриване на командата и следващите 3 реда (описание, команда, празен ред)
159 + sed -i "/^#CMD: $name$/,+3d" "$COMMANDS_FILE"
160 + printf "\n%b%s%b %b%s%b\n" "${C_SUCCESS}${C_BOLD}" "✅ Премахната:" "${C_RESET}" "${C_KEY}" "$name" "${C_RESET}"
161 + else
162 + printf "\n%b%s%b\n" "${C_ERROR}" "❌ Команда '$name' не съществува!" "${C_RESET}"
163 + fi
164 + sleep 2
165 + }
166 +
167 + view_command() {
168 + ensure_file
169 + print_header
170 +
171 + printf "%b%s%b\n\n" "${C_INFO}${C_BOLD}" "🔍 Преглед на конкретна команда" "${C_RESET}"
172 +
173 + local count=$(grep -c '^#CMD:' "$COMMANDS_FILE" 2>/dev/null || echo 0)
174 + if [ "$count" -eq 0 ]; then
175 + printf "%b%s%b\n" "${C_WARNING}" "⚠️ Няма запазени команди" "${C_RESET}"
176 + sleep 2
177 + return
178 + fi
179 +
180 + printf "%b%s%b" "${C_INFO}" "Име на командата: " "${C_RESET}"
181 + read -r name
182 +
183 + if [ -z "$name" ]; then
184 + printf "\n%b%s%b\n" "${C_ERROR}" "❌ Не е въведено име!" "${C_RESET}"
185 + sleep 2
186 + return
187 + fi
188 +
189 + local found=0
190 + while IFS= read -r line; do
191 + if [[ "$line" == "#CMD: $name" ]]; then
192 + found=1
193 + echo
194 + printf "%b%s%b\n" "${C_PRIMARY}${C_BOLD}" "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" "${C_RESET}"
195 + printf "%b%s%b %b%s%b\n" "${C_KEY}${C_BOLD}" "Име:" "${C_RESET}" "${C_PRIMARY}" "$name" "${C_RESET}"
196 +
197 + read -r desc
198 + desc="${desc#\#DESC: }"
199 + printf "%b%s%b %b%s%b\n" "${C_KEY}${C_BOLD}" "Описание:" "${C_RESET}" "${C_DESC}" "$desc" "${C_RESET}"
200 +
201 + read -r cmd
202 + printf "%b%s%b\n" "${C_KEY}${C_BOLD}" "Команда:" "${C_RESET}"
203 + printf " %b%s%b\n" "${C_VAL}" "$cmd" "${C_RESET}"
204 + printf "%b%s%b\n\n" "${C_PRIMARY}${C_BOLD}" "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" "${C_RESET}"
205 +
206 + printf "%b%s%b" "${C_WARNING}" "Копирай командата в клипборда? (y/n): " "${C_RESET}"
207 + read -r copy
208 + if [[ "$copy" == "y" || "$copy" == "Y" ]]; then
209 + if command -v xclip >/dev/null 2>&1; then
210 + echo "$cmd" | xclip -selection clipboard
211 + printf "%b%s%b\n" "${C_SUCCESS}" "✅ Копирано в клипборда!" "${C_RESET}"
212 + elif command -v xsel >/dev/null 2>&1; then
213 + echo "$cmd" | xsel --clipboard
214 + printf "%b%s%b\n" "${C_SUCCESS}" "✅ Копирано в клипборда!" "${C_RESET}"
215 + else
216 + printf "%b%s%b\n" "${C_WARNING}" "⚠️ xclip/xsel не са инсталирани" "${C_RESET}"
217 + fi
218 + fi
219 + break
220 + fi
221 + done < "$COMMANDS_FILE"
222 +
223 + if [ "$found" -eq 0 ]; then
224 + printf "\n%b%s%b\n" "${C_ERROR}" "❌ Команда '$name' не съществува!" "${C_RESET}"
225 + fi
226 +
227 + echo
228 + read -rp "Натисни Enter за продължаване..."
229 + }
230 +
231 + edit_commands() {
232 + ensure_file
233 + "$EDITOR_CMD" "$COMMANDS_FILE"
234 + }
235 +
236 + fzf_menu() {
237 + if ! command -v fzf >/dev/null; then
238 + print_header
239 + printf "%b%s%b\n" "${C_ERROR}" "❌ fzf не е инсталиран!" "${C_RESET}"
240 + printf "%b%s%b\n" "${C_INFO}" "Инсталирай с: sudo dnf install fzf" "${C_RESET}"
241 + sleep 3
242 + return
243 + fi
244 +
245 + ensure_file
246 +
247 + # Проверка дали има команди
248 + local count=$(grep -c '^#CMD:' "$COMMANDS_FILE" 2>/dev/null || echo 0)
249 + if [ "$count" -eq 0 ]; then
250 + print_header
251 + printf "%b%s%b\n" "${C_WARNING}" "⚠️ Няма запазени команди за преглед" "${C_RESET}"
252 + sleep 2
253 + return
254 + fi
255 +
256 + # Подготовка: Създаваме два файла - един за display, един за команди
257 + local display_file=$(mktemp)
258 + local cmd_file=$(mktemp)
259 + local line_num=0
260 +
261 + while IFS= read -r line; do
262 + if [[ "$line" =~ ^#CMD: ]]; then
263 + local name="${line#\#CMD: }"
264 + IFS= read -r desc_line
265 + local desc="${desc_line#\#DESC: }"
266 + IFS= read -r cmd_line
267 +
268 + # Display file - това виждаме в списъка
269 + printf "%3d) %-25s - %s\n" "$((++line_num))" "$name" "$desc" >> "$display_file"
270 +
271 + # Command file - съхраняваме командата на същия ред номер
272 + echo "$cmd_line" >> "$cmd_file"
273 + fi
274 + done < "$COMMANDS_FILE"
275 +
276 + # FZF избор
277 + local selected=$(cat "$display_file" | fzf \
278 + --height=60% \
279 + --border=rounded \
280 + --prompt="🔍 Търси: " \
281 + --header="↑↓ Навигация | Enter = Избор | ESC = Изход" \
282 + --color="fg:#d0d0d0,bg:#1e1e1e,hl:#5fd7ff" \
283 + --color="fg+:#ffffff,bg+:#2e2e2e,hl+:#ffaf00" \
284 + --color="info:#af87ff,prompt:#5fd7ff,pointer:#ff87d7" \
285 + --color="marker:#87ff00,spinner:#ff87d7,header:#87afaf")
286 +
287 + if [ -n "$selected" ]; then
288 + # Извличаме номера на реда
289 + local num=$(echo "$selected" | awk '{print $1}' | tr -d ')')
290 +
291 + # Взимаме командата от command file
292 + local cmd=$(sed -n "${num}p" "$cmd_file")
293 +
294 + rm -f "$display_file" "$cmd_file"
295 +
296 + print_header
297 + printf "%b%s%b\n\n" "${C_SUCCESS}${C_BOLD}" "✅ Избрана команда:" "${C_RESET}"
298 + printf "%b%s%b\n\n" "${C_VAL}" "$cmd" "${C_RESET}"
299 +
300 + printf "%b%s%b" "${C_WARNING}" "Копирай в клипборда? (y/n): " "${C_RESET}"
301 + read -r copy
302 + if [[ "$copy" == "y" || "$copy" == "Y" ]]; then
303 + if command -v xclip >/dev/null 2>&1; then
304 + echo "$cmd" | xclip -selection clipboard
305 + printf "\n%b%s%b\n" "${C_SUCCESS}" "✅ Копирано в клипборда!" "${C_RESET}"
306 + sleep 1
307 + elif command -v xsel >/dev/null 2>&1; then
308 + echo "$cmd" | xsel --clipboard
309 + printf "\n%b%s%b\n" "${C_SUCCESS}" "✅ Копирано в клипборда!" "${C_RESET}"
310 + sleep 1
311 + else
312 + printf "\n%b%s%b\n" "${C_WARNING}" "⚠️ Инсталирай xclip или xsel за копиране" "${C_RESET}"
313 + sleep 2
314 + fi
315 + fi
316 +
317 + echo
318 + read -rp "Натисни Enter за продължаване..."
319 + else
320 + rm -f "$display_file" "$cmd_file"
321 + fi
322 + }
323 +
324 + search_commands() {
325 + ensure_file
326 + print_header
327 +
328 + printf "%b%s%b\n\n" "${C_INFO}${C_BOLD}" "🔎 Търсене в командите" "${C_RESET}"
329 +
330 + printf "%b%s%b" "${C_INFO}" "Търси (име/описание/команда): " "${C_RESET}"
331 + read -r search_term
332 +
333 + if [ -z "$search_term" ]; then
334 + printf "\n%b%s%b\n" "${C_ERROR}" "❌ Въведи текст за търсене!" "${C_RESET}"
335 + sleep 2
336 + return
337 + fi
338 +
339 + echo
340 + printf "%b%s%b\n\n" "${C_SUCCESS}" "Резултати за: $search_term" "${C_RESET}"
341 +
342 + local found=0
343 + while IFS= read -r line; do
344 + if [[ "$line" =~ ^#CMD: ]]; then
345 + local name="${line#\#CMD: }"
346 + read -r desc
347 + desc="${desc#\#DESC: }"
348 + read -r cmd
349 +
350 + if [[ "$name" =~ $search_term ]] || [[ "$desc" =~ $search_term ]] || [[ "$cmd" =~ $search_term ]]; then
351 + found=1
352 + printf "%b●%b %b%s%b\n" "${C_SUCCESS}" "${C_RESET}" "${C_PRIMARY}${C_BOLD}" "$name" "${C_RESET}"
353 + printf " %b%s%b\n" "${C_DESC}${C_DIM}" "$desc" "${C_RESET}"
354 + printf " %b➜%b %b%s%b\n\n" "${C_KEY}" "${C_RESET}" "${C_VAL}" "$cmd" "${C_RESET}"
355 + fi
356 + fi
357 + done < "$COMMANDS_FILE"
358 +
359 + if [ "$found" -eq 0 ]; then
360 + printf "%b%s%b\n" "${C_WARNING}" "⚠️ Няма намерени резултати" "${C_RESET}"
361 + fi
362 +
363 + echo
364 + read -rp "Натисни Enter за продължаване..."
365 + }
366 +
367 + show_help() {
368 + print_header
369 +
370 + printf "%b%s%b\n\n" "${C_INFO}${C_BOLD}" "📖 Помощна информация" "${C_RESET}"
371 +
372 + printf "%b%s%b\n" "${C_PRIMARY}" "Файл с команди:" "${C_RESET}"
373 + printf " %b%s%b\n\n" "${C_VAL}" "$COMMANDS_FILE" "${C_RESET}"
374 +
375 + printf "%b%s%b\n" "${C_PRIMARY}" "Редактор:" "${C_RESET}"
376 + printf " %b%s%b\n\n" "${C_VAL}" "$EDITOR_CMD" "${C_RESET}"
377 +
378 + printf "%b%s%b\n" "${C_PRIMARY}" "Формат на командите:" "${C_RESET}"
379 + printf " %b%s%b\n" "${C_DESC}" "Всяка команда се съхранява с име, описание и самата команда" "${C_RESET}"
380 + printf " %b%s%b\n\n" "${C_DESC}" "Можете да търсите, прегледате и копирате команди лесно" "${C_RESET}"
381 +
382 + printf "%b%s%b\n" "${C_PRIMARY}" "Препоръки:" "${C_RESET}"
383 + printf " %b%s%b\n" "${C_DESC}" "• Използвай кратки и ясни имена" "${C_RESET}"
384 + printf " %b%s%b\n" "${C_DESC}" "• Пиши подробни описания" "${C_RESET}"
385 + printf " %b%s%b\n" "${C_DESC}" "• Групирай сходни команди с общ префикс (напр: mikrotik-*, docker-*)" "${C_RESET}"
386 + printf " %b%s%b\n\n" "${C_DESC}" "• За копиране в клипборда инсталирай xclip или xsel" "${C_RESET}"
387 +
388 + read -rp "Натисни Enter за продължаване..."
389 + }
390 +
391 + main_menu() {
392 + print_header
393 +
394 + printf "%b%s%b\n" "${C_BORDER}${C_DIM}" "Избери опция:" "${C_RESET}"
395 + echo
396 +
397 + printf " %b[1]%b 📋 Преглед на всички команди\n" "${C_KEY}${C_BOLD}" "${C_RESET}"
398 + printf " %b[2]%b ➕ Добавяне на нова команда\n" "${C_KEY}${C_BOLD}" "${C_RESET}"
399 + printf " %b[3]%b 🔍 Преглед на конкретна команда\n" "${C_KEY}${C_BOLD}" "${C_RESET}"
400 + printf " %b[4]%b 🔎 Търсене в командите\n" "${C_KEY}${C_BOLD}" "${C_RESET}"
401 + printf " %b[5]%b 🗑️ Премахване на команда\n" "${C_KEY}${C_BOLD}" "${C_RESET}"
402 + printf " %b[6]%b ✏️ Редактиране на файла\n" "${C_KEY}${C_BOLD}" "${C_RESET}"
403 + printf " %b[7]%b ⚡ FZF интерактивен преглед\n" "${C_KEY}${C_BOLD}" "${C_RESET}"
404 + printf " %b[8]%b 📖 Помощ\n" "${C_KEY}${C_BOLD}" "${C_RESET}"
405 + echo
406 + printf " %b[q]%b 🚪 Изход\n" "${C_ERROR}${C_BOLD}" "${C_RESET}"
407 + echo
408 +
409 + printf "%b%s%b " "${C_PRIMARY}" "➤" "${C_RESET}"
410 + read -r choice
411 +
412 + case "$choice" in
413 + 1) list_commands; read -rp "Натисни Enter за продължаване...";;
414 + 2) add_command;;
415 + 3) view_command;;
416 + 4) search_commands;;
417 + 5) remove_command;;
418 + 6) edit_commands;;
419 + 7) fzf_menu;;
420 + 8) show_help;;
421 + q|Q)
422 + clear
423 + printf "\n%b%s%b\n\n" "${C_SUCCESS}${C_BOLD}" "👋 Довиждане!" "${C_RESET}"
424 + exit 0
425 + ;;
426 + *)
427 + printf "\n%b%s%b\n" "${C_ERROR}" "❌ Невалидна опция!" "${C_RESET}"
428 + sleep 1
429 + ;;
430 + esac
431 + }
432 +
433 + # Главен цикъл
434 + while true; do
435 + main_menu
436 + done
Daha yeni Daha eski