yait

Yet Another Init Tool
Log | Files | Refs | README | LICENSE

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