yait (10567B)
1 #! /bin/sh 2 # Highly opinionated C and SH project generator 3 4 scriptversion="0.3.0" 5 6 # 7 # Copyright (C) 2025-2026 fSD THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 9 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 10 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 11 # SOFTWARE. 12 13 me=$(basename "$0") 14 version="$me/fSD v$scriptversion 15 16 Copyright (C) 2025-2026 fSD. 17 This is free software; you are free to change and redistribute it. 18 There is NO WARRANTY, to the extent permitted by law." 19 20 usage="\ 21 Usage: $me [OPTION]... <version> <dir> 22 Highly opinionated C and SH project generator 23 24 Options: 25 --help print this help and exit 26 --version output version information 27 28 -x <language> set project type 29 -d <description> set a description 30 -S small project creation 31 -f overwrite existing files 32 -a <author> set project author 33 -r initialize Git repository for the project 34 -q surpress output" 35 36 x=c # language 37 d="Does a thing" # package description 38 S= # small project creation (bool) 39 f= # force (bool) 40 a=$(git config user.name) # author 41 r= # initialize repository (bool) 42 q= # surpress output 43 44 say() { 45 if [ -z "$q" ]; then 46 echo "$me: $*" 47 fi 48 } 49 50 lsay() { 51 if [ -z "$q" ]; then 52 echo " => $*" 53 fi 54 } 55 56 # main creation routine 57 create_project() { 58 name=$1 59 60 if ! echo "$name" | grep -qE '^[A-Za-z0-9_-]+$'; then 61 say "invalid name '$name'" 62 exit 1 63 fi 64 65 # creates a shell project 66 shell() { 67 outfile="$name" 68 69 if [ -z "$S" ]; then 70 if [ -d "$name" ]; then 71 if ! [ -z "$f" ]; then 72 rm -rf "$name" 73 fi 74 fi 75 76 mkdir "$name" || exit 1 77 cd "$name" || exit 1 78 79 cat <<EOF > LICENSE 80 ISC License 81 82 Copyright (c) $(date "+%Y") $a 83 84 Permission to use, copy, modify, and/or distribute this software for any 85 purpose with or without fee is hereby granted, provided that the above 86 copyright notice and this permission notice appear in all copies. 87 88 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 89 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 90 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 91 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 92 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 93 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 94 PERFORMANCE OF THIS SOFTWARE. 95 EOF 96 cat <<EOF > Makefile 97 all: 98 @echo "nothing to do" 99 100 install: 101 cp bin/$name /usr/local/bin 102 cp $name.1 /usr/local/share/man/man1/$name.1 103 chmod 644 /usr/local/share/man/man1/$name.1 104 105 uninstall: 106 \$(RM) /usr/local/bin/$name 107 \$(RM) /usr/local/share/man/man1/$name.1 108 EOF 109 cat <<EOF > README.md 110 # $name 111 112 YOUR_WEBSITE 113 114 $d: 115 116 - Feature 1 117 - Feature 2 118 * feature 2a 119 120 ## Install 121 122 #### Dependencies 123 124 - \`fzf\` - terminal fuzzy finder 125 126 **Note**: \`fzf\` is used as an example dependency 127 128 \`\`\`bash 129 git clone YOUR_REPO_URL 130 cd $name 131 sudo make install 132 \`\`\` 133 134 ## Usage 135 136 This tool runs via the command \`$name\`. 137 138 - \`$name -k\` -- Does option k 139 EOF 140 141 mkdir bin || exit 1 142 outfile="bin/$outfile" 143 fi 144 cat <<EOF > "$outfile" 145 #! /bin/sh 146 # $d 147 148 scriptversion="1" 149 150 # 151 # 152 # Copyright (C) $(date "+%Y") $a 153 # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 154 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 155 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 156 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 157 # SOFTWARE. 158 159 me=\$0 160 version="\$me/$a v\$scriptversion 161 162 Copyright (C) $(date "+%Y") $a. 163 This is free software; you are free to change and redistribute it. 164 There is NO WARRANTY, to the extent permitted by law." 165 166 usage="\ 167 Usage: \$me [OPTION]... <arg1> <arg2> 168 $d 169 170 Options: 171 --help print this help and exit 172 --version output version information" 173 174 say() { 175 if [ -z "\$q" ]; then 176 echo "\$me: \$*" 177 fi 178 } 179 180 lsay() { 181 if [ -z "\$q" ]; then 182 echo " => \$*" 183 fi 184 } 185 186 if ! [ \$# -gt 0 ]; then 187 echo "\$usage" 188 exit 0 189 fi 190 191 while [ \$# -gt 0 ]; do 192 case \$1 in 193 --help) echo "\$usage"; exit 0 ;; 194 --version) echo "\$version"; exit 0 ;; 195 -*) echo "\$me: Unknown option '\$1'." >&2; exit 1 ;; 196 esac 197 done 198 199 say hello world 200 EOF 201 chmod +x "$outfile" 202 } 203 204 # creates a C project 205 c() { 206 if [ -d "$name" ]; then 207 if ! [ -z "$f" ]; then 208 rm -rf "$name" 209 fi 210 fi 211 mkdir "$name" || exit 1 212 cd "$name" || exit 1 213 cat <<EOF > README 214 $name 215 $(echo "$name" | sed 's/./=/g') 216 $d 217 218 219 Requirements 220 ------------ 221 In order to build $name you need the LIBRARY header files. 222 223 224 Instillation 225 ------------ 226 Edit config.mk to match your local setup ($name is installed into 227 the /usr/local namesapce by default). 228 229 Afterwards enter the following command to build and install $name (if 230 necessary as root): 231 232 make clean install 233 234 Running $name 235 $(echo "Running $name" | sed 's/./=/g') 236 To run $name use the following command: 237 238 ./$name 239 240 Configuration 241 ------------- 242 The configuration of $name is done by creating a custom config.h 243 and (re)compiling the source code. 244 EOF 245 cat <<EOF > LICENSE 246 ISC License 247 248 Copyright (c) $(date "+%Y") $a 249 250 Permission to use, copy, modify, and/or distribute this software for any 251 purpose with or without fee is hereby granted, provided that the above 252 copyright notice and this permission notice appear in all copies. 253 254 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 255 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 256 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 257 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 258 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 259 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 260 PERFORMANCE OF THIS SOFTWARE. 261 EOF 262 cat <<EOF > Makefile 263 # $name 264 # See LICENSE file for copyright and license details. 265 266 include config.mk 267 268 SRC = $name.c 269 OBJ = \${SRC:.c=.o} 270 271 all: $name 272 273 .c.o: 274 \${CC} -c \${CFLAGS} \$< 275 276 \${OBJ}: config.h config.mk 277 278 config.h: 279 cp config.def.h \$@ 280 281 $name: \${OBJ} 282 \${CC} -o \$@ \${OBJ} \${LDFLAGS} 283 284 clean: 285 rm -f $name \${OBJ} $name-\${VERSION}.tar.gz 286 287 dist: clean 288 mkdir -p $name-\${VERSION} 289 cp -R LICENSE Makefile README config.def.h config.mk\ 290 $name.1 \${SRC} $name-\${VERSION} 291 tar -cf $name-\${VERSION}.tar $name-\${VERSION} 292 gzip $name-\${VERSION}.tar 293 rm -rf $name-\${VERSION} 294 295 install: all 296 mkdir -p \${DESTDIR}\${PREFIX}/bin 297 cp -f $name \${DESTDIR}\${PREFIX}/bin 298 chmod 755 \${DESTDIR}\${PREFIX}/bin/$name 299 mkdir -p \${DESTDIR}\${MANPREFIX}/man1 300 sed "s/VERSION/\${VERSION}/g" < $name.1 > \${DESTDIR}\${MANPREFIX}/man1/$name.1 301 chmod 644 \${DESTDIR}\${MANPREFIX}/man1/$name.1 302 303 uninstall: 304 rm -f \${DESTDIR}\${PREFIX}/bin/$name\ 305 \${DESTDIR}\${MANPREFIX}/man1/$name.1 306 307 .PHONY: all clean dist install uninstall 308 EOF 309 cat <<EOF > config.def.h 310 /* See LICENSE file for copyright and license details. */ 311 EOF 312 cat <<EOF > config.mk 313 # $name version 314 VERSION = 0.1 315 316 # Customize below to fit your system 317 318 # paths 319 PREFIX = /usr/local 320 MANPREFIX = \${PREFIX}/share/man 321 322 # includes and libs 323 INCS = 324 LIBS = 325 326 # flags 327 CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"\${VERSION}\" 328 CFLAGS = -g -std=c99 -pedantic -Wall -O0 \${INCS} \${CPPFLAGS} 329 CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os \${INCS} \${CPPFLAGS} 330 LDFLAGS = \${LIBS} 331 332 # compiler and linker 333 CC = cc 334 EOF 335 cat <<EOF > arg.h 336 /* 337 * Copy me if you can. 338 * by 20h 339 */ 340 341 #ifndef ARG_H__ 342 #define ARG_H__ 343 344 extern char *argv0; 345 346 /* use main(int argc, char *argv[]) */ 347 #define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ 348 argv[0] && argv[0][1]\\ 349 && argv[0][0] == '-';\\ 350 argc--, argv++) {\\ 351 char argc_;\\ 352 char **argv_;\\ 353 int brk_;\\ 354 if (argv[0][1] == '-' && argv[0][2] == '\\0') {\\ 355 argv++;\\ 356 argc--;\\ 357 break;\\ 358 }\\ 359 for (brk_ = 0, argv[0]++, argv_ = argv;\\ 360 argv[0][0] && !brk_;\\ 361 argv[0]++) {\\ 362 if (argv_ != argv)\\ 363 break;\\ 364 argc_ = argv[0][0];\\ 365 switch (argc_) 366 367 /* Handles obsolete -NUM syntax */ 368 #define ARGNUM case '0':\\ 369 case '1':\\ 370 case '2':\\ 371 case '3':\\ 372 case '4':\\ 373 case '5':\\ 374 case '6':\\ 375 case '7':\\ 376 case '8':\\ 377 case '9' 378 379 #define ARGEND }\\ 380 } 381 382 #define ARGC() argc_ 383 384 #define ARGNUMF(base) (brk_ = 1, estrtol(argv[0], (base))) 385 386 #define EARGF(x) ((argv[0][1] == '\\0' && argv[1] == NULL)?\\ 387 ((x), abort(), (char *)0) :\\ 388 (brk_ = 1, (argv[0][1] != '\\0')?\\ 389 (&argv[0][1]) :\\ 390 (argc--, argv++, argv[0]))) 391 392 #define ARGF() ((argv[0][1] == '\\0' && argv[1] == NULL)?\\ 393 (char *)0 :\\ 394 (brk_ = 1, (argv[0][1] != '\\0')?\\ 395 (&argv[0][1]) :\\ 396 (argc--, argv++, argv[0]))) 397 398 #endif 399 EOF 400 cat <<EOF > "$name.c" 401 /* See LICENSE file for license details. */ 402 #include <stdio.h> 403 #include <stdlib.h> 404 405 #include "arg.h" 406 #include "config.h" 407 408 char *argv0; 409 410 static void 411 usage(void) { 412 fprintf(stderr, "%s: usage: $name [-v]\\n", argv0); 413 exit(1); 414 } 415 416 int 417 main(int argc, char *argv[]) { 418 419 ARGBEGIN { 420 case 'v': 421 printf("$name/$a version %s\\n", VERSION); 422 exit(0); 423 default: 424 usage(); 425 } ARGEND; 426 427 puts("Hello, World!"); 428 429 return 0; 430 } 431 EOF 432 } 433 434 case $x in 435 sh) shell ;; 436 *) c ;; 437 esac 438 439 if ! [ -z "$r" ]; then 440 git init -q || echo "$me: error: could not initilzie git repository" >&2 441 fi 442 443 say "made $name at $(realpath "$name")" 444 cd .. 445 } 446 447 if ! [ $# -gt 0 ]; then 448 echo "$usage" 449 exit 0 450 fi 451 452 while [ $# -gt 0 ]; do 453 case $1 in 454 --help) echo "$usage"; exit 0 ;; 455 --version) echo "$version"; exit 0 ;; 456 -x) shift; x="$1"; shift ;; 457 -d) shift; d="$1"; shift ;; 458 -S) S=true; shift ;; 459 -f) f=true; shift ;; 460 -a) shift; a="$1"; shift ;; 461 -r) r=true; shift ;; 462 -q) q=true; shift ;; 463 -*) echo "$me: Unknown option '$1'." >&2; exit 1 ;; 464 *) create_project "$1"; shift ;; 465 esac 466 done