Skip to content

Instantly share code, notes, and snippets.

@markusfisch
Last active May 2, 2017 08:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save markusfisch/5e73a372241231a3a7c8 to your computer and use it in GitHub Desktop.
Save markusfisch/5e73a372241231a3a7c8 to your computer and use it in GitHub Desktop.
bash script to create new projects from project skeletons

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
#!/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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment