marcelgross90
4/9/2015 - 8:11 PM

bash script to create new projects from project skeletons

bash script to create new projects from project skeletons

#!/usr/bin/env bash

# List available skeletons
list()
{
	local SKELETON N=0
	for SKELETON in ${SKELETONS}/*
	do
		[ -d "$SKELETON" ] || continue
		printf "%2d %s\n" $(( ++N )) "${SKELETON##*/}"
	done
}

# Create a new project from a skeleton
#
# @param 1 - skeleton name or number
# @param 2 - name of new project
new()
{
	(( $# < 2 )) && return 1

	local SKELETON=$1
	if (( SKELETON > 0 ))
	then
		local N=$SKELETON
		for SKELETON in ${SKELETONS}/*
		do
			[ -d "$SKELETON" ] || continue
			(( --N )) || break
		done
		SKELETON=${SKELETON##*/}
	fi

	if [ -r "$2" ]
	then
		echo "error: $2 already exists" >&2
		return $?
	fi

	cp -ri "$SKELETONS/$SKELETON" "$2" || return $?

	# preserve working directory when sourced
	(
		cd "$2" || return $?

		local INIT=${0##*/}.sh
		if [ -f "$INIT" ]
		then
			bash "$INIT" || return $?
			rm -f "$INIT"
		fi
	)
}

# Create an init script for a new skeleton
init()
{
	cat << EOF > "${0##*/}.sh"
#!/usr/bin/env bash
# Run this script to initialize the template or use skel to do it for you:
# https://gist.github.com/markusfisch/5e73a372241231a3a7c8

# Refactor in file contents and file/directory names
#
# @param 1 - case-sensitive pattern to replace
# @param 2 - replacement string
# @param 3 - working directory (optional)
refactor()
{
	local PATTERN=\$1
	local REPLACEMENT=\$2
	local DIR=\${3:-.}

	(( \$# < 2 )) && return 1

	# rename directories before files
	local TYPE
	for TYPE in d f
	do
		find "\$DIR" -type "\$TYPE" -name "*\$PATTERN*" | while read -r
		do
			mv "\$REPLY" "\${REPLY//\$PATTERN/\$REPLACEMENT}"
		done
	done

	local BASH_SOURCE_FILE=\${0##*/}
	local TMP="\$0-\$\$"
	grep -rl "\$PATTERN" "\$DIR"/* | while read -r
	do
		[ "\${REPLY##*/}" == "\$BASH_SOURCE_FILE" ] && continue
		[ "\$REPLY" == "\$0" ] && continue

		sed -e "s/\$PATTERN/\$REPLACEMENT/g" < "\$REPLY" > "\$TMP" &&
			cat "\$TMP" > "\$REPLY"

		rm -f "\$TMP"
	done
}

#refactor 'AppName' "\${PWD##*/}"
EOF
}

# Print help
help()
{
	cat << EOF
            ___
          ´     \`             ___
          ( ) ( )           ´     \`
          \`.(").´           ( ) ( )
           |===|            \`.(").´
           \`---´             |===|
             o               \`---´
       _--.--o--.--_            o
      ()\.-- o --./()     _--.--o--.--_
      |  .-- o --.  |    ()\.-- o --./()
      |  .-- o --.  |    |  .-- o --.  |

usage: ${0##*/} COMMAND [ARGUMENT...]

COMMAND may be one of:

EOF

	local DESC=

	while read -r
	do
		case $REPLY in
			''|refactor*)
				DESC=
				;;
			\#\ *)
				[ "$DESC" ] && continue
				DESC=${REPLY#*#}
				;;
			*\(\))
				[ "$DESC" ] || continue
				echo "${REPLY%(*} -$DESC"
				DESC=
				;;
		esac
	done < "$0"
}

readonly SKELETONS=${SKELETONS:-$HOME/src/${0##*/}}

if [ "${BASH_SOURCE[0]}" == "$0" ]
then
	"${@:-list}"
fi

Skeletons

Create new projects from project skeletons.

This script is for you if you create nontrivial projects that can be derived from a common base.

Sample

$ skel new android Happy

This creates a new "Happy" project from the skeleton "android".

Details

By default, skeletons live in ~/src/skel. If you want another location:

export SKELETONS=/path/to/skeletons

Refactoring

To refactor a skeleton after creation, put a file named skel.sh into the root of your skeleton directory. This file is run immediately after the new project has been set up.

You may generate a blank skel.sh by running

$ skel init

This template contains a refactor function to refactor in files as well as in file and directory names.

For example, if your skeleton contains the literal "AppName" and you want to replace it, say with the directory name of the new project, you may put

refactor 'AppName' "${PWD##*/}"

into skel.sh in the skeleton root directory.

More

For more info use:

$ skel help