mirror of
https://github.com/vishapoberon/vix.git
synced 2026-04-05 20:32:24 +00:00
418 lines
7.9 KiB
Bash
Executable file
418 lines
7.9 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
|
|
# set global variables
|
|
PROGNAME=${0##*/}
|
|
VERSION="0.1.4"
|
|
|
|
COLOUR_SET_R="\033[0;31m"
|
|
COLOUR_SET_G="\033[0;32m"
|
|
COLOUR_SET_B="\033[0;34m"
|
|
COLOUR_END="\033[0m"
|
|
|
|
PROJECT_ROOT=$(pwd)
|
|
host_os=$(uname -s)
|
|
host_arch=$(uname -m)
|
|
|
|
: "${VIX_TARGET_DIR:=build/${host_os}-${host_arch}}"
|
|
|
|
|
|
help_usage(){
|
|
cat <<EOT
|
|
Usage: vix ...
|
|
help
|
|
version
|
|
new PATH [--module MODULE] [--app APP]
|
|
run
|
|
build
|
|
test
|
|
clean
|
|
release [--tarball]
|
|
EOT
|
|
exit 0
|
|
}
|
|
|
|
help_version(){
|
|
printf "%s: v%s\n" "${PROGNAME}" "${VERSION}"
|
|
}
|
|
|
|
help_tbd(){
|
|
printf "This feature is not implemented yet...\n"
|
|
}
|
|
|
|
perror(){
|
|
printf "${COLOUR_SET_R}[-] ${COLOUR_END} %s\n" "${@}" >&2
|
|
exit 1
|
|
}
|
|
|
|
pinfo(){
|
|
printf "${COLOUR_SET_B}[+] ${COLOUR_END} %s\n" "${@}" >&2
|
|
}
|
|
|
|
paction(){
|
|
printf "${COLOUR_SET_G}[*] ${COLOUR_END} %s\n" "${@}" >&2
|
|
}
|
|
|
|
|
|
confirm_create_path(){
|
|
perror "The directory \"${PATH_ARG}\" already exists."
|
|
}
|
|
|
|
check_path(){
|
|
stat "$PATH_ARG" >/dev/null 2>&1 && confirm_create_path
|
|
}
|
|
|
|
create_path(){
|
|
paction "Creating ${PATHBASE}"
|
|
mkdir -p "${PATH_ARG}"
|
|
}
|
|
|
|
create_readme(){
|
|
paction "Creating ${PATHBASE}/README.md"
|
|
cat <<EOF > "${PATH_ARG}"/README.md
|
|
# ${APP}
|
|
|
|
**TODO: Add description**
|
|
|
|
## Building
|
|
|
|
\`\`\`
|
|
vix build
|
|
\`\`\`
|
|
|
|
## Testing
|
|
|
|
\`\`\`
|
|
vix test
|
|
\`\`\`
|
|
|
|
EOF
|
|
}
|
|
|
|
create_gitattributes(){
|
|
paction "Creating ${PATHBASE}/.gitattributes"
|
|
cat <<EOF > "${PATH_ARG}"/.gitattributes
|
|
# Set the language to Oberon
|
|
*.Mod linguist-language=Oberon
|
|
*.mod linguist-language=Oberon
|
|
EOF
|
|
}
|
|
|
|
create_gitignore(){
|
|
paction "Creating ${PATHBASE}/.gitignore"
|
|
cat <<EOF > "${PATH_ARG}"/.gitignore
|
|
build
|
|
release
|
|
EOF
|
|
}
|
|
|
|
create_vipakfile(){
|
|
paction "Creating ${PATHBASE}/vipakfile"
|
|
cat <<EOF > "${PATH_ARG}"/vipakfile
|
|
NAME = ${APP}
|
|
VERSION = 0.1.0
|
|
|
|
AUTHOR =
|
|
LICENSE =
|
|
|
|
DEPS =
|
|
|
|
RUN = ./${MODULE}Main
|
|
MAIN = %projdir%/src/${MODULE}Main.Mod
|
|
BUILD = %projdir%/src/${MODULE}.Mod
|
|
|
|
TEST_RUN = ./${MODULE}Test
|
|
TEST_MAIN = %projdir%/test/${MODULE}Test.Mod
|
|
TEST =
|
|
EOF
|
|
}
|
|
|
|
create_src(){
|
|
paction "Creating ${PATHBASE}/src"
|
|
mkdir -p "${PATH_ARG}/src"
|
|
}
|
|
|
|
create_src_prog(){
|
|
paction "Creating ${PATHBASE}/src/${MODULE}.Mod"
|
|
cat <<EOF > "${PATH_ARG}"/src/${MODULE}.Mod
|
|
MODULE ${MODULE};
|
|
|
|
IMPORT Out;
|
|
|
|
PROCEDURE Run*(): INTEGER;
|
|
BEGIN
|
|
RETURN 42
|
|
END Run;
|
|
|
|
END ${MODULE}.
|
|
EOF
|
|
}
|
|
|
|
create_src_progmain(){
|
|
paction "Creating ${PATHBASE}/src/${MODULE}Main.Mod"
|
|
cat <<EOF > "${PATH_ARG}"/src/${MODULE}Main.Mod
|
|
MODULE ${MODULE}Main;
|
|
|
|
IMPORT ${MODULE}, Out;
|
|
|
|
BEGIN
|
|
Out.Int(${MODULE}.Run(), 0); Out.Ln;
|
|
END ${MODULE}Main.
|
|
EOF
|
|
}
|
|
|
|
|
|
create_test(){
|
|
paction "Creating ${PATHBASE}/test"
|
|
mkdir -p "${PATH_ARG}/test"
|
|
}
|
|
|
|
create_test_progtest(){
|
|
paction "Creating ${PATHBASE}/test/${MODULE}Test.Mod"
|
|
cat <<EOF > "${PATH_ARG}"/test/${MODULE}Test.Mod
|
|
MODULE ${MODULE}Test;
|
|
|
|
IMPORT ${MODULE}, Out;
|
|
|
|
BEGIN
|
|
IF ${MODULE}.Run() = 42 THEN
|
|
Out.String("All works!");
|
|
Out.Ln;
|
|
ELSE
|
|
Out.String("Test Failed...");
|
|
Out.Ln;
|
|
HALT(1)
|
|
END;
|
|
END ${MODULE}Test.
|
|
EOF
|
|
}
|
|
|
|
success_msg(){
|
|
pinfo 'All good!'
|
|
|
|
cat <<EOF
|
|
|
|
Your Oberon project was created successfully.
|
|
You can use "vix" to build it, test it, and more:
|
|
|
|
cd ${PATHBASE}
|
|
vix build && vix test
|
|
vix run
|
|
|
|
Run "vix help" for more commands.
|
|
EOF
|
|
}
|
|
|
|
|
|
new_proj() {
|
|
shift
|
|
|
|
if [ $# -lt 1 ]; then
|
|
perror "missing PATH argument for '${PROGNAME} new'"
|
|
fi
|
|
|
|
PATH_ARG="$1"
|
|
PATHBASE=$(basename "${PATH_ARG}")
|
|
shift
|
|
|
|
MODULE=""
|
|
APP=""
|
|
|
|
# Parse optional flags
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--module)
|
|
shift
|
|
MODULE="$1"
|
|
;;
|
|
--app)
|
|
shift
|
|
APP="$1"
|
|
;;
|
|
*)
|
|
perror "unknown option '${1}'"
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# --module is required if PATH is '.'
|
|
if [ -z "$MODULE" ]; then
|
|
if [ "$PATH_ARG" = "." ]; then
|
|
perror "--module is required when PATH is '.'"
|
|
fi
|
|
|
|
# Derive PascalCase module name from path
|
|
MODULE=$(printf "%s" "$PATHBASE" | awk -F'[_-]' '{
|
|
for (i = 1; i <= NF; i++)
|
|
{
|
|
$i = toupper(substr($i,1,1)) substr($i,2)
|
|
}
|
|
print $0
|
|
}' OFS='')
|
|
fi
|
|
|
|
# Validate MODULE as Oberon identifier
|
|
if ! printf "%s" "$MODULE" | grep -Eq '^[A-Za-z][A-Za-z0-9]*$'; then
|
|
perror "Invalid module name: '${MODULE}'" \
|
|
"Must match: letter {letter | digit}" \
|
|
"(no underscores, dashes, or leading digits)"
|
|
fi
|
|
|
|
# Default APP to basename of path
|
|
if [ -z "$APP" ]; then
|
|
APP="${PATHBASE}"
|
|
fi
|
|
|
|
pinfo "PATH : $PATH_ARG"
|
|
pinfo "MODULE : $MODULE"
|
|
pinfo "APP : $APP"
|
|
|
|
check_path
|
|
create_path
|
|
create_readme
|
|
create_gitattributes
|
|
create_gitignore
|
|
create_vipakfile
|
|
create_src
|
|
create_src_prog
|
|
create_src_progmain
|
|
create_test
|
|
create_test_progtest
|
|
success_msg
|
|
}
|
|
|
|
_process_mods() {
|
|
key=$1; mode=$2
|
|
[ -f vipakfile ] || perror "vipakfile not found"
|
|
|
|
# grab & massage the RHS
|
|
line=$(
|
|
grep -E "^${key}[[:space:]]*=" vipakfile \
|
|
| cut -d= -f2- \
|
|
| sed -e 's/^[[:space:]]*//' \
|
|
-e "s|%projdir%|${PROJECT_ROOT}|g"
|
|
)
|
|
|
|
paction "Processing ${key} (${mode}) in '${VIX_TARGET_DIR}/'"
|
|
mkdir -p "${VIX_TARGET_DIR}"
|
|
cd "${VIX_TARGET_DIR}" || perror "cd to ${VIX_TARGET_DIR} failed"
|
|
|
|
oldIFS=$IFS; IFS=';'
|
|
for entry in $line; do
|
|
# trim
|
|
entry=$(printf "%s" "$entry" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
|
|
[ -z "$entry" ] && continue
|
|
|
|
paction "voc ${mode} ${entry}"
|
|
voc "${mode}" "${entry}" 2>/dev/null \
|
|
|| perror "${key} step failed: ${entry}"
|
|
done
|
|
IFS=$oldIFS
|
|
cd -
|
|
}
|
|
|
|
_run_cmds() {
|
|
key=$1
|
|
[ -f vipakfile ] || perror "vipakfile not found"
|
|
|
|
run_line=$(
|
|
grep -E "^${key}[[:space:]]*=" vipakfile \
|
|
| cut -d= -f2- \
|
|
| sed -e 's/^[[:space:]]*//' \
|
|
-e "s|%projdir%|${PROJECT_ROOT}|g"
|
|
)
|
|
[ -n "$run_line" ] || perror "${key} not set in vipakfile"
|
|
|
|
paction "Running ${key} in '${VIX_TARGET_DIR}/'"
|
|
cd "${VIX_TARGET_DIR}" || perror "cd to ${VIX_TARGET_DIR} failed"
|
|
|
|
oldIFS=$IFS; IFS=';'
|
|
for cmd in $run_line; do
|
|
cmd=$(printf "%s" "$cmd" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
|
|
[ -z "$cmd" ] && continue
|
|
|
|
paction "Executing: ${cmd}"
|
|
eval "${cmd}" \
|
|
|| perror "execution failed: ${cmd}"
|
|
done
|
|
IFS=$oldIFS
|
|
cd -
|
|
}
|
|
|
|
# now the four subcommands:
|
|
build_proj() {
|
|
_process_mods BUILD -s
|
|
_process_mods MAIN -m
|
|
pinfo "Build complete"
|
|
}
|
|
|
|
run_proj() {
|
|
_run_cmds RUN
|
|
}
|
|
|
|
test_proj() {
|
|
_process_mods TEST -s
|
|
_process_mods TEST_MAIN -m
|
|
_run_cmds TEST_RUN
|
|
pinfo "All tests passed"
|
|
}
|
|
|
|
release_proj() {
|
|
[ -f vipakfile ] || perror "vipakfile not found in current directory"
|
|
_process_mods BUILD -s
|
|
_process_mods MAIN -M
|
|
|
|
release_subdir="${VIX_TARGET_DIR}/release"
|
|
paction "Creating release directory '${release_subdir}'"
|
|
mkdir -p "${release_subdir}"
|
|
|
|
# 4) copy each MAIN binary into release/
|
|
main_line=$(
|
|
grep -E '^MAIN[[:space:]]*=' vipakfile \
|
|
| cut -d= -f2- \
|
|
| sed -e 's/^[[:space:]]*//' \
|
|
-e "s|%projdir%|${PROJECT_ROOT}|g"
|
|
)
|
|
|
|
oldIFS=$IFS; IFS=';'
|
|
for entry in $main_line; do
|
|
entry=$(printf "%s" "$entry" \
|
|
| sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
|
|
[ -z "$entry" ] && continue
|
|
|
|
bin=$(basename "$entry" .Mod)
|
|
paction "Copying '${bin}' → '${release_subdir}/'"
|
|
cp "${VIX_TARGET_DIR}/${bin}" "${release_subdir}/" \
|
|
|| perror "failed to install release binary: ${bin}"
|
|
done
|
|
IFS=$oldIFS
|
|
|
|
pinfo "Release ready in '${release_subdir}'"
|
|
}
|
|
|
|
clean_proj() {
|
|
paction "Removing build artifacts in '${VIX_TARGET_DIR}'"
|
|
rm -rf "${VIX_TARGET_DIR}" \
|
|
|| perror "failed to remove '${VIX_TARGET_DIR}'"
|
|
pinfo "Clean complete"
|
|
}
|
|
|
|
|
|
vix_main(){
|
|
[ $# -eq 0 ] && help_usage
|
|
|
|
case "$1" in
|
|
help) help_usage ;;
|
|
version) help_version ;;
|
|
new) new_proj "$@" ;;
|
|
build) build_proj ;;
|
|
test) test_proj ;;
|
|
run) run_proj ;;
|
|
release) release_proj ;;
|
|
clean) clean_proj ;;
|
|
*) help_usage ;;
|
|
esac
|
|
}
|
|
|
|
vix_main "$@"
|