bashitup 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 sudo-self
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the “Software”), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,145 @@
1
+ # bashitup
2
+
3
+ Interactive Bash menu system generator.
4
+
5
+ ---
6
+
7
+ ## Repository
8
+
9
+ https://github.com/sudo-self/bashitup.sh.git
10
+
11
+ ---
12
+
13
+ ## Features
14
+
15
+ * Interactive CLI workflow
16
+ * ASCII banners using figlet
17
+ * Dynamic menu builder (add, edit, delete options)
18
+ * Optional logging and confirmation prompts
19
+ * Generates reusable Bash scripts
20
+ * Works on macOS and Linux
21
+
22
+ ---
23
+
24
+ ## Installation
25
+
26
+ Install globally with npm:
27
+
28
+ ```bash
29
+ npm install -g bashitup
30
+ ```
31
+
32
+ Run:
33
+
34
+ ```bash
35
+ bashitup
36
+ ```
37
+
38
+ ---
39
+
40
+ ## Requirements
41
+
42
+ This tool depends on `figlet`.
43
+
44
+ ### macOS
45
+
46
+ ```bash
47
+ brew install figlet
48
+ ```
49
+
50
+ ### Ubuntu / Debian
51
+
52
+ ```bash
53
+ sudo apt install figlet
54
+ ```
55
+
56
+ ---
57
+
58
+ ## Usage
59
+
60
+ Run the CLI:
61
+
62
+ ```bash
63
+ bashitup
64
+ ```
65
+
66
+ Follow the prompts to:
67
+
68
+ 1. Set script name
69
+ 2. Define banner text
70
+ 3. Choose font
71
+ 4. Configure options
72
+ 5. Add menu items
73
+
74
+ ---
75
+
76
+ ## Example Output
77
+
78
+ ```bash
79
+ ./manager.sh
80
+ ```
81
+
82
+ Example menu:
83
+
84
+ ```
85
+ 1) Update System
86
+ 2) Install Dependencies
87
+ q) Exit
88
+ ```
89
+
90
+ ---
91
+
92
+ ## Project Structure
93
+
94
+ ```
95
+ bashitup/
96
+ ├── bashitup.sh
97
+ ├── bin/
98
+ │ └── bashitup
99
+ ├── package.json
100
+ └── README.md
101
+ ```
102
+
103
+ ---
104
+
105
+ ## Development
106
+
107
+ Clone the repository:
108
+
109
+ ```bash
110
+ git clone https://github.com/sudo-self/bashitup.sh.git
111
+ cd bashitup.sh
112
+ ```
113
+
114
+ Link locally:
115
+
116
+ ```bash
117
+ npm link
118
+ ```
119
+
120
+ Run:
121
+
122
+ ```bash
123
+ bashitup
124
+ ```
125
+
126
+ ---
127
+
128
+ ## Notes
129
+
130
+ * npm installs a global command (`bashitup`)
131
+ * No build step required
132
+ * Implemented entirely in Bash
133
+
134
+ ---
135
+
136
+ ## License
137
+
138
+ MIT
139
+
140
+ ---
141
+
142
+ ## Contributing
143
+
144
+ Pull requests are welcome.
145
+
package/bashitup.sh ADDED
@@ -0,0 +1,389 @@
1
+ #!/bin/bash
2
+ # ScriptBuilder — Interactive Menu System Generator
3
+ # Builds fully-featured bash menu scripts interactively
4
+
5
+ set -euo pipefail
6
+
7
+ # --- COLORS & FORMATTING ---
8
+ GREEN='\033[0;32m'
9
+ CYAN='\033[0;36m'
10
+ YELLOW='\033[1;33m'
11
+ RED='\033[0;31m'
12
+ BLUE='\033[0;34m'
13
+ BOLD='\033[1m'
14
+ DIM='\033[2m'
15
+ NC='\033[0m'
16
+
17
+ # --- HELPERS ---
18
+ info() { echo -e "${CYAN} ▸ $*${NC}"; }
19
+ success() { echo -e "${GREEN} ✔ $*${NC}"; }
20
+ warn() { echo -e "${YELLOW} ⚠ $*${NC}"; }
21
+ error() { echo -e "${RED} ✖ $*${NC}"; }
22
+ divider() { echo -e "${DIM}────────────────────────────────────────────────────${NC}"; }
23
+ step() { echo -e "\n${BOLD}${YELLOW}[ Step $1 ] $2${NC}"; divider; }
24
+
25
+ # --- DEPENDENCY CHECK ---
26
+ check_deps() {
27
+ local missing=()
28
+ for cmd in figlet; do
29
+ command -v "$cmd" &>/dev/null || missing+=("$cmd")
30
+ done
31
+ if (( ${#missing[@]} > 0 )); then
32
+ error "Missing required tools: ${missing[*]}"
33
+ echo -e " Install with: ${CYAN}sudo apt install ${missing[*]}${NC} (Debian/Ubuntu)"
34
+ echo -e " or: ${CYAN}brew install ${missing[*]}${NC} (macOS)"
35
+ exit 1
36
+ fi
37
+ }
38
+
39
+ # --- STARTUP LOGO ---
40
+ show_logo() {
41
+ clear
42
+ echo -e "${RED}"
43
+ cat << "EOF"
44
+ d8888b. .d8b. .d8888. db db d888888b d888888b db db d8888b.
45
+ 88 `8D d8' `8b 88' YP 88 88 `88' `~~88~~' 88 88 88 `8D
46
+ 88oooY' 88ooo88 `8bo. 88ooo88 88 88 88 88 88oodD'
47
+ 88~~~b. 88~~~88 `Y8b. 88~~~88 88 88 88 88 88~~~
48
+ 88 8D 88 88 db 8D 88 88 .88. 88 88b d88 88
49
+ Y8888P' YP YP `8888Y' YP YP Y888888P YP ~Y8888P' 88
50
+
51
+ EOF
52
+ echo -e "${DIM} >> github.com/sudo-self/bashitup.sh v2.0${NC}"
53
+ echo -e "${NC}"
54
+ }
55
+
56
+ # --- PROMPT WITH DEFAULT ---
57
+ # Usage: prompt_with_default VAR "Prompt text" "default value"
58
+ # Compatible with bash 3.2+ (no nameref)
59
+ prompt_with_default() {
60
+ local _var="$1"
61
+ local _prompt="$2"
62
+ local _default="${3:-}"
63
+ local _input=""
64
+ if [[ -n "$_default" ]]; then
65
+ read -rp " ${_prompt} [${_default}]: " _input
66
+ _input="${_input:-$_default}"
67
+ eval "${_var}=$(printf '%q' "$_input")"
68
+ else
69
+ while [[ -z "$_input" ]]; do
70
+ read -rp " ${_prompt}: " _input
71
+ [[ -z "$_input" ]] && warn "This field is required."
72
+ done
73
+ eval "${_var}=$(printf '%q' "$_input")"
74
+ fi
75
+ }
76
+
77
+ # --- CONFIRM PROMPT ---
78
+ confirm() {
79
+ local msg="$1"
80
+ local default="${2:-y}"
81
+ local yn_hint="Y/n"
82
+ [[ "$default" == "n" ]] && yn_hint="y/N"
83
+ read -rp " ${msg} [${yn_hint}]: " answer
84
+ answer="${answer:-$default}"
85
+ # tr for bash 3.2 compat (no ${,,} lowercase expansion)
86
+ answer=$(echo "$answer" | tr '[:upper:]' '[:lower:]')
87
+ [[ "$answer" == "y" ]]
88
+ }
89
+
90
+ # --- FIGLET FONT PICKER ---
91
+ pick_figlet_font() {
92
+ local available_fonts
93
+ available_fonts=$(figlet -l 2>/dev/null | tr ' ' '\n' | grep -v '^$' | head -20 || echo "standard")
94
+ echo -e "\n${DIM} Available fonts (sample):${NC}"
95
+ local i=1
96
+ local font_list=()
97
+ while IFS= read -r font; do
98
+ font_list+=("$font")
99
+ printf " ${CYAN}%2d)${NC} %-20s" "$i" "$font"
100
+ (( i % 3 == 0 )) && echo
101
+ ((i++))
102
+ done <<< "$available_fonts"
103
+ echo -e "\n"
104
+ read -rp " Choose font number (or press Enter for 'standard'): " font_choice
105
+ if [[ -n "$font_choice" && "$font_choice" =~ ^[0-9]+$ ]]; then
106
+ CHOSEN_FONT="${font_list[$((font_choice-1))]:-standard}"
107
+ else
108
+ CHOSEN_FONT="standard"
109
+ fi
110
+ info "Using font: ${CHOSEN_FONT}"
111
+ }
112
+
113
+ # --- EDIT MENU ITEMS ---
114
+ edit_menu_items() {
115
+ while true; do
116
+ echo -e "\n${BOLD} Current menu items:${NC}"
117
+ if (( ${#MENU_LABELS[@]} == 0 )); then
118
+ echo -e " ${DIM}(none yet)${NC}"
119
+ else
120
+ for i in "${!MENU_LABELS[@]}"; do
121
+ echo -e " ${CYAN}$((i+1)))${NC} ${MENU_LABELS[$i]} ${DIM}→ ${MENU_COMMANDS[$i]}${NC}"
122
+ done
123
+ fi
124
+ echo
125
+ echo -e " ${GREEN}a)${NC} Add item ${YELLOW}e)${NC} Edit item ${RED}d)${NC} Delete item ${CYAN}done)${NC} Finish"
126
+ read -rp " Action: " action
127
+ action=$(echo "$action" | tr '[:upper:]' '[:lower:]')
128
+ case "$action" in
129
+ a|add)
130
+ echo -e "\n ${CYAN}Option #$((${#MENU_LABELS[@]}+1))${NC}"
131
+ label=""; cmd=""
132
+ prompt_with_default label "Label (e.g., Update System)"
133
+ prompt_with_default cmd "Command to run (e.g., sudo apt update)"
134
+ MENU_LABELS+=("$label")
135
+ MENU_COMMANDS+=("$cmd")
136
+ success "Added: ${label}"
137
+ ;;
138
+ e|edit)
139
+ read -rp " Edit item number: " num
140
+ if [[ "$num" =~ ^[0-9]+$ ]] && (( num >= 1 && num <= ${#MENU_LABELS[@]} )); then
141
+ local idx=$((num-1))
142
+ new_label=""; new_cmd=""
143
+ prompt_with_default new_label "New label" "${MENU_LABELS[$idx]}"
144
+ prompt_with_default new_cmd "New command" "${MENU_COMMANDS[$idx]}"
145
+ MENU_LABELS[$idx]="$new_label"
146
+ MENU_COMMANDS[$idx]="$new_cmd"
147
+ success "Updated item $num."
148
+ else
149
+ warn "Invalid item number."
150
+ fi
151
+ ;;
152
+ d|delete)
153
+ read -rp " Delete item number: " num
154
+ if [[ "$num" =~ ^[0-9]+$ ]] && (( num >= 1 && num <= ${#MENU_LABELS[@]} )); then
155
+ local idx=$((num-1))
156
+ warn "Removed: ${MENU_LABELS[$idx]}"
157
+ MENU_LABELS=("${MENU_LABELS[@]:0:$idx}" "${MENU_LABELS[@]:$((idx+1))}")
158
+ MENU_COMMANDS=("${MENU_COMMANDS[@]:0:$idx}" "${MENU_COMMANDS[@]:$((idx+1))}")
159
+ else
160
+ warn "Invalid item number."
161
+ fi
162
+ ;;
163
+ done|"")
164
+ if (( ${#MENU_LABELS[@]} == 0 )); then
165
+ warn "You need at least one menu item."
166
+ else
167
+ break
168
+ fi
169
+ ;;
170
+ *)
171
+ warn "Unknown action."
172
+ ;;
173
+ esac
174
+ done
175
+ }
176
+
177
+ # --- GENERATE SCRIPT ---
178
+ generate_script() {
179
+ local filename="$1"
180
+ local banner_text="$2"
181
+ local intro_msg="$3"
182
+ local font="$4"
183
+ local log_enabled="$5"
184
+ local confirm_enabled="$6"
185
+
186
+ local generated_art
187
+ generated_art=$(figlet -f "$font" "$banner_text" 2>/dev/null || figlet "$banner_text")
188
+
189
+ cat > "$filename" << 'SCRIPT_HEADER'
190
+ #!/bin/bash
191
+ # Generated by ScriptBuilder v2.0
192
+ # DO NOT EDIT THE HEADER — re-run scriptbuilder to regenerate
193
+
194
+ set -euo pipefail
195
+ trap 'echo -e "\n${RED}Unexpected error on line $LINENO. Exiting.${NC}"; exit 1' ERR
196
+
197
+ # --- COLORS ---
198
+ CYAN='\033[0;36m'
199
+ GREEN='\033[0;32m'
200
+ YELLOW='\033[1;33m'
201
+ RED='\033[0;31m'
202
+ BOLD='\033[1m'
203
+ DIM='\033[2m'
204
+ NC='\033[0m'
205
+
206
+ SCRIPT_HEADER
207
+
208
+ # Inject runtime config
209
+ cat >> "$filename" << SCRIPT_CONFIG
210
+ # --- RUNTIME CONFIG ---
211
+ LOG_ENABLED="${log_enabled}"
212
+ CONFIRM_ACTIONS="${confirm_enabled}"
213
+ LOG_FILE="\${HOME}/.$(basename "${filename}" .sh).log"
214
+ SCRIPT_CONFIG
215
+
216
+ # Inject generated art as a variable (safer than heredoc in generated code)
217
+ {
218
+ echo ""
219
+ echo "# --- BANNER ART ---"
220
+ echo "BANNER_ART=$(printf '%q' "$generated_art")"
221
+ echo ""
222
+ } >> "$filename"
223
+
224
+ cat >> "$filename" << 'SCRIPT_FUNCS'
225
+ # --- LOGGING ---
226
+ log() {
227
+ if [[ "$LOG_ENABLED" == "true" ]]; then
228
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG_FILE"
229
+ fi
230
+ }
231
+
232
+ # --- BANNER ---
233
+ show_banner() {
234
+ clear
235
+ echo -e "${CYAN}"
236
+ echo "$BANNER_ART"
237
+ echo -e "${NC}"
238
+ SCRIPT_FUNCS
239
+
240
+ echo " echo -e \"\${YELLOW}${intro_msg}\${NC}\"" >> "$filename"
241
+ echo " echo -e \"\${DIM}────────────────────────────────────────────────────\${NC}\"" >> "$filename"
242
+ echo "}" >> "$filename"
243
+
244
+ cat >> "$filename" << 'SCRIPT_MENU_START'
245
+
246
+ # --- MENU ---
247
+ show_menu() {
248
+ show_banner
249
+ echo -e " ${BOLD}Please choose an option:${NC}\n"
250
+ SCRIPT_MENU_START
251
+
252
+ for i in "${!MENU_LABELS[@]}"; do
253
+ printf " echo -e \" ${CYAN}%d)${NC} %s\"\n" "$((i+1))" "${MENU_LABELS[$i]}" >> "$filename"
254
+ done
255
+ echo " echo -e \" \${DIM}────────────────\${NC}\"" >> "$filename"
256
+ echo " echo -e \" q) Exit\"" >> "$filename"
257
+ echo "}" >> "$filename"
258
+
259
+ cat >> "$filename" << 'SCRIPT_LOOP'
260
+
261
+ # --- RUN COMMAND WITH OPTIONAL CONFIRM ---
262
+ run_cmd() {
263
+ local label="$1"
264
+ local cmd="$2"
265
+ if [[ "$CONFIRM_ACTIONS" == "true" ]]; then
266
+ read -rp " Run '${label}'? [Y/n]: " yn
267
+ yn="${yn:-y}"
268
+ [[ "${yn,,}" != "y" ]] && echo " Skipped." && return
269
+ fi
270
+ log "Running: $label ($cmd)"
271
+ echo -e "${CYAN} ▸ Executing: ${label}...${NC}"
272
+ echo ""
273
+ if eval "$cmd"; then
274
+ log "Success: $label"
275
+ echo -e "\n${GREEN} ✔ Done.${NC}"
276
+ else
277
+ log "Failed: $label (exit $?)"
278
+ echo -e "\n${RED} ✖ Command exited with an error.${NC}"
279
+ fi
280
+ echo ""
281
+ read -rp " Press Enter to continue..."
282
+ }
283
+
284
+ # --- MAIN LOOP ---
285
+ while true; do
286
+ show_menu
287
+ echo ""
288
+ read -rp " Selection: " choice
289
+ case "$choice" in
290
+ SCRIPT_LOOP
291
+
292
+ for i in "${!MENU_COMMANDS[@]}"; do
293
+ printf ' %d)\n' "$((i+1))" >> "$filename"
294
+ printf ' run_cmd %q %q\n' "${MENU_LABELS[$i]}" "${MENU_COMMANDS[$i]}" >> "$filename"
295
+ printf ' ;;\n' >> "$filename"
296
+ done
297
+
298
+ cat >> "$filename" << 'SCRIPT_FOOTER'
299
+ q|Q)
300
+ echo -e "\n Goodbye!\n"
301
+ log "Session ended."
302
+ exit 0
303
+ ;;
304
+ *)
305
+ echo -e "${RED} Invalid option: '$choice'${NC}"
306
+ sleep 1
307
+ ;;
308
+ esac
309
+ done
310
+ SCRIPT_FOOTER
311
+ }
312
+
313
+ # ============================================================
314
+ # MAIN
315
+ # ============================================================
316
+ check_deps
317
+ show_logo
318
+
319
+ # --- STEP 1: SCRIPT INFO ---
320
+ step 1 "Script Info"
321
+
322
+ FILENAME=""
323
+ prompt_with_default FILENAME "Output filename (without .sh)" "manager"
324
+ [[ "$FILENAME" != *.sh ]] && FILENAME="${FILENAME}.sh"
325
+
326
+ # Warn if file exists
327
+ if [[ -f "$FILENAME" ]]; then
328
+ warn "File '${FILENAME}' already exists."
329
+ confirm "Overwrite it?" || { info "Aborted."; exit 0; }
330
+ fi
331
+
332
+ BANNER_TEXT=""
333
+ prompt_with_default BANNER_TEXT "Banner text (ASCII art)"
334
+
335
+ INTRO_MSG=""
336
+ prompt_with_default INTRO_MSG "Welcome / intro message" "Welcome to your script"
337
+
338
+ # --- STEP 2: FONT ---
339
+ step 2 "Banner Font"
340
+ if confirm "Pick a figlet font interactively?" "n"; then
341
+ pick_figlet_font
342
+ else
343
+ CHOSEN_FONT="standard"
344
+ info "Using default font: standard"
345
+ fi
346
+
347
+ # --- STEP 3: OPTIONS ---
348
+ step 3 "Script Options"
349
+
350
+ LOG_ENABLED="false"
351
+ confirm "Enable action logging to ~/.$(basename "$FILENAME" .sh).log?" "n" && LOG_ENABLED="true"
352
+
353
+ CONFIRM_ENABLED="false"
354
+ confirm "Prompt for confirmation before each action?" "n" && CONFIRM_ENABLED="true"
355
+
356
+ # --- STEP 4: MENU ITEMS ---
357
+ step 4 "Menu Items"
358
+ MENU_LABELS=()
359
+ MENU_COMMANDS=()
360
+ info "Add your menu items. You can also edit/delete them."
361
+ edit_menu_items
362
+
363
+ # --- PREVIEW ---
364
+ echo ""
365
+ step 5 "Preview & Generate"
366
+ echo -e " ${BOLD}Summary:${NC}"
367
+ echo -e " ${DIM}File:${NC} ${YELLOW}${FILENAME}${NC}"
368
+ echo -e " ${DIM}Banner:${NC} ${CYAN}${BANNER_TEXT}${NC} (font: ${CHOSEN_FONT})"
369
+ echo -e " ${DIM}Intro:${NC} ${INTRO_MSG}"
370
+ echo -e " ${DIM}Logging:${NC} ${LOG_ENABLED} ${DIM}Confirm actions:${NC} ${CONFIRM_ENABLED}"
371
+ echo -e " ${DIM}Items:${NC} ${#MENU_LABELS[@]}"
372
+ for i in "${!MENU_LABELS[@]}"; do
373
+ echo -e " ${CYAN}$((i+1)))${NC} ${MENU_LABELS[$i]} ${DIM}→ ${MENU_COMMANDS[$i]}${NC}"
374
+ done
375
+ echo ""
376
+
377
+ confirm "Generate '${FILENAME}'?" || { info "Aborted."; exit 0; }
378
+
379
+ generate_script "$FILENAME" "$BANNER_TEXT" "$INTRO_MSG" "$CHOSEN_FONT" "$LOG_ENABLED" "$CONFIRM_ENABLED"
380
+ chmod +x "$FILENAME"
381
+
382
+ # --- DONE ---
383
+ echo ""
384
+ divider
385
+ success "Created ${YELLOW}${FILENAME}${NC}"
386
+ info "Run it now: ${CYAN}./${FILENAME}${NC}"
387
+ [[ "$LOG_ENABLED" == "true" ]] && info "Logs will be written to: ~/.$(basename "$FILENAME" .sh).log"
388
+ divider
389
+ echo ""
package/bin/bashitup ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env bash
2
+
3
+ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
4
+ bash "$DIR/../bashitup.sh" "$@"
package/package.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "bashitup",
3
+ "version": "1.0.0",
4
+ "description": "Interactive bash menu builder",
5
+ "bin": {
6
+ "bashitup": "./bin/bashitup"
7
+ },
8
+ "files": [
9
+ "bin",
10
+ "bashitup.sh"
11
+ ],
12
+ "keywords": ["bash", "cli"],
13
+ "license": "MIT"
14
+ }