Skip to content

Instantly share code, notes, and snippets.

@olefasting
Last active May 19, 2019 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save olefasting/6e8263471887eadaa4e11921c66a6dcd to your computer and use it in GitHub Desktop.
Save olefasting/6e8263471887eadaa4e11921c66a6dcd to your computer and use it in GitHub Desktop.
Script for managing a VSCode project, based on Haxe, Heaps.io and CastleDB
#!/usr/bin/env bash
set -e
function on_error() {
echo "exit 1"
exit 1
}
trap on_error ERR
function add_spaces() {
local to_s="$1"
local s="${to_s//./ }"
local s="${s//_/ }"
echo "$s"
unset to_s
unset s
return 0
}
function uppercase_first() {
local to_uc="$1"
local arr=($(echo $to_uc | tr " " "\n"))
for w in "${arr[@]}"; do
local uc="${uc}"$(echo ${w}|cut -c1|tr [a-z] [A-Z])
local uc="${uc}"$(echo ${w}|cut -c2-)
done
echo "$uc"
unset to_uc
unset arr
unset uc
return 0
}
function to_camel_case() {
local to_cc="$1"
local cc=$(add_spaces "${to_cc}")
local cc=$(uppercase_first "${cc}")
local cc="${cc// /}"
echo "$cc"
unset cc
unset to_cc
return 0
}
function create_file() {
local body="$1"
local path="$2"
[ -z "$body" ] && echo "Warning: No body specified when calling 'create_file' function for file '$path'"
if [ -z "$path" ]; then
echo "Error: No file path specified when calling 'create_file' function"
return 1
fi
local dir="${path%/*}"
if [ "$path" != "$dir" ] && [ ! -e "$dir" ]; then
mkdir -p "$dir"
fi
echo "$body" > "$path"
unset dir
unset path
unset body
return 0
}
function gen_js_vscode_launch_json() {
local body="\
{
// $APEX_CREATED_FILE_HEADER
\"version\": \"0.2.0\",
\"configurations\": [
{
\"type\": \"chrome\",
\"request\": \"launch\",
\"name\": \"Launch Chrome against localhost\",
\"url\": \"file://\${workspaceFolder}/$APEX_DIST_DIR/js/index.html\",
\"webRoot\": \"\${workspaceFolder}\"
}
]
}"
echo "$body"
unset body
return 0
}
function gen_js_vscode_tasks_json() {
local body="\
{
// $APEX_CREATED_FILE_HEADER
\"version\": \"2.0.0\",
\"tasks\": [
{
\"type\": \"haxe\",
\"args\": \"active configuration\",
\"problemMatcher\": [
\"\$haxe-absolute\",
\"\$haxe\",
\"\$haxe-error\",
\"\$haxe-trace\"
],
\"group\": {
\"kind\": \"build\",
\"isDefault\": true
}
}
]
}"
echo "$body"
unset body
return 0
}
function gen_hl_vscode_launch_json() {
if [ "$APEX_HL_DEBUG_ATTACH" == "true" ]; then
local name="Attach to HashLink process"
local request=attach
else
local name="Launch with HashLink"
local request=launch
fi
local body="\
{
// $APEX_CREATED_FILE_HEADER
\"version\": \"0.2.0\",
\"configurations\": [
{
\"name\": \"$name\",
\"request\": \"$request\",
\"port\": $APEX_HL_DEBUG_PORT,
\"type\": \"hl\",
\"hxml\": \"$APEX_HXML_FNAME\",
\"cwd\": \"\${workspaceFolder}\",
\"preLaunchTask\": {
\"type\" : \"haxe\",
\"args\" : \"active configuration\"
}
}
]
}"
echo "$body"
unset body
unset request
unset name
return 0
}
function gen_hl_vscode_tasks_json() {
local body="\
{
// $APEX_CREATED_FILE_HEADER
\"version\": \"2.0.0\",
\"tasks\": [
{
\"type\": \"hxml\",
\"file\": \"$APEX_HXML_FNAME\",
\"problemMatcher\": [
\"\$haxe-absolute\",
\"\$haxe\",
\"\$haxe-error\",
\"\$haxe-trace\"
],
\"group\": {
\"kind\": \"build\",
\"isDefault\": true
}
}
]
}"
echo "$body"
unset body
return 0
}
function create_vscode_config() {
[ -e .vscode ] && mkdir -p .vscode
case "$APEX_TARGET" in
"js")
create_file "$(gen_js_vscode_launch_json)" ".vscode/launch.json"
create_file "$(gen_js_vscode_tasks_json)" ".vscode/tasks.json"
;;
"hl")
create_file "$(gen_hl_vscode_launch_json)" ".vscode/launch.json"
create_file "$(gen_hl_vscode_tasks_json)" ".vscode/tasks.json"
;;
*)
echo "Error: Invalid or no target specified ($APEX_TARGET)"
esac
echo "!!! remember to install the Haxe Extension Pack for vscode !!!"
return 0
}
function create_cdb_src() {
local mpath="$APEX_SRC_DIR"
[ ! -z "$APEX_CDB_SRC_PACKAGE" ] && local mpath="$mpath/$APEX_CDB_SRC_PACKAGE"
[ ! -e "$mpath" ] && mkdir -p "$mpath"
local loader_body="\
/* $APEX_CREATED_FILE_HEADER */"
[ ! -z "$APEX_CDB_SRC_PACKAGE" ] && local loader_body="\
$loader_body
package $APEX_CDB_SRC_PACKAGE;"
local loader_body="\
$loader_body
class Loader {
public static function loadAll() {"
for f in "${APEX_CDB_FILES[@]}"; do
local body="\
/* $APEX_CREATED_FILE_HEADER */"
[ ! -z "$APEX_CDB_SRC_PACKAGE" ] && local body="\
$body
package $APEX_CDB_SRC_PACKAGE;"
local body="\
$body
private typedef Init = haxe.macro.MacroType<[cdb.Module.build(\"$f\")]>;"
local fname="${f##*/}"
local mfname="${fname%.*}"
local mfname=$(to_camel_case "${mfname}")
create_file "$body" "$mpath/$mfname.hx"
local loader_body="$loader_body
$mfname.load(haxe.Resource.getString(\"$f\"));"
unset body
unset mfname
unset fname
done
local loader_body="$loader_body
}
}"
create_file "$loader_body" "$mpath/Loader.hx"
create_target_files
echo "!!! remember to call '$([ ! -z $APEX_CDB_SRC_PACKAGE ] && echo $APEX_CDB_SRC_PACKAGE.)Loader.loadAll' before accessing castledb data in code !!!"
echo
unset loader_body
unset mpath
return 0
}
function gen_js_css() {
if [ -z "$APEX_WINDOW_SIZE" ]; then
local width="100%"
local height="100%"
else
local width="${APEX_WINDOW_SIZE%x*}px"
local height="${APEX_WINDOW_SIZE##*x}px"
fi
local body="\
/* $APEX_CREATED_FILE_HEADER */
html, body {
height: 100%;
}
body {
margin: 0;
padding: 0;
background-color: #000000;
}
#body-container {
height: 100%;
padding: 0;
margin: 0;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
align-items: center;
justify-content: center;
}
#canvas-container {
width: $width;
}
canvas#webgl {
width: $width;
height: $height;
}"
echo "$body"
unset body
return 0
}
function gen_js_html() {
local page_title="$APEX_NAME"
local js_fname="$APEX_SHORTNAME.js"
local body="\
<!-- $APEX_CREATED_FILE_HEADER -->
<!DOCTYPE>
<html>
<head>
<meta charset=\"utf-8\" />
<title>$page_title</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div id=\"body-container\">
<div id=\"canvas-container\">
<canvas id=\"webgl\"></canvas>
<script type=\"text/javascript\" src=\"./$js_fname\"></script>
</div>
</div>
</body>
</html>"
echo "$body"
unset body
unset css
unset fname
unset page_title
return 0
}
function gen_common_hxml() {
local common="\
-cp $APEX_SRC_DIR
-D resourcePath=\"$APEX_RES_DIR\""
[ "$APEX_ENV" == "production" ] && local common="\
$common
-D analyzer-optimize"
[ -z "$APEX_WINDOW_SIZE" ] || local common="\
$common
-D windowSize=$APEX_WINDOW_SIZE"
if [ "$APEX_USE_CDB" != "false" ]; then
for fname in "${APEX_CDB_FILES[@]}"; do
local common="\
$common
-resource $fname"
done
fi
local common="\
$common
-lib $APEX_LIBS
-main $APEX_ENTRY_FUNCTION"
echo "$common"
unset common
return 0
}
function gen_js_hxml() {
local body=$(gen_common_hxml)
local body="\
$body
--js $APEX_DIST_DIR/js/$APEX_SHORTNAME.js"
[ "$APEX_ENV" == "development" ] && local body="\
$body
-debug"
echo "$body"
unset body
return 0
}
function gen_hl_hxml() {
local body=$(gen_common_hxml)
local body="\
$body
-hl $APEX_DIST_DIR/hl/$APEX_SHORTNAME.hl"
echo "$body"
unset body
return 0
}
function setup_haxelib_repo() {
if [ ! -e $(which haxelib) ]; then
echo "Warning: The haxelib binary could not be found in \$PATH, please prepare haxelib repo manually, or install haxelib and run this script again"
else
echo "creating new haxelib repo"
haxelib newrepo
echo "installing dependencies"
local arr=( $APEX_LIBS )
for lib in "${arr[@]}"; do
haxelib install "$lib"
done
fi
unset arr
return 0
}
function create_target_files() {
case "$APEX_TARGET" in
"js")
[ ! -e "$APEX_DIST_DIR/$APEX_TARGET" ] && mkdir -p "$APEX_DIST_DIR/$APEX_TARGET"
create_file "$(gen_js_hxml)" "$APEX_HXML_FNAME"
create_file "$(gen_js_css)" "$APEX_DIST_DIR/js/style.css"
create_file "$(gen_js_html)" "$APEX_DIST_DIR/js/index.html"
return 0
;;
"hl")
create_file "$(gen_hl_hxml)" "$APEX_HXML_FNAME"
return 0
;;
*)
echo "Error: Invalid or no target specified ($APEX_TARGET)"
return 1
esac
}
[ -f .env ] && source .env
[ -z "$APEX_SHORTNAME" ] && APEX_SHORTNAME="${PWD##*/}"
[ -z "$APEX_NAME" ] && APEX_NAME=$(to_camel_case "${APEX_SHORTNAME}")
case "$APEX_ENV" in
"prod"|"production")
APEX_ENV="production"
;;
#"dev"|"devel"|"development")
#;;
*)
APEX_ENV="development"
;;
esac
[ -z "$APEX_TARGET" ] && APEX_TARGET="js"
if [ -z "$APEX_LIBS" ]; then
APEX_LIBS="heaps"
[ "$APEX_TARGET" == "hl" ] && APEX_LIBS="hlsdl $APEX_LIBS"
fi
[ -z "$APEX_ENTRY_FUNCTION" ] && APEX_ENTRY_FUNCTION="Main"
[ -z "$APEX_HXML_FNAME" ] && APEX_HXML_FNAME="build.hxml"
[ -z "$APEX_SRC_DIR" ] && APEX_SRC_DIR="src"
[ ! -e "$APEX_SRC_DIR" ] && mkdir -p "$APEX_SRC_DIR"
[ -z "$APEX_DIST_DIR" ] && APEX_DIST_DIR="dist"
[ ! -e "$APEX_DIST_DIR" ] && mkdir -p "$APEX_DIST_DIR"
[ -z "$APEX_RES_DIR" ] && APEX_RES_DIR="res"
[ ! -e "$APEX_RES_DIR" ] && mkdir -p "$APEX_RES_DIR"
[ -z "$APEX_DATA_DIR" ] && APEX_DATA_DIR="data"
[ ! -e "$APEX_DATA_DIR" ] && mkdir -p "$APEX_DATA_DIR"
[ "$APEX_USE_CDB" != "false" ] && APEX_USE_CDB="true"
if [ "$APEX_USE_CDB" != "false" ]; then
[ -z "$APEX_CDB_SRC_PACKAGE" ] && APEX_CDB_SRC_PACKAGE="db"
APEX_CDB_FILES=( $(find "$APEX_DATA_DIR" -type f | grep .cdb) )
[[ "$APEX_LIBS" =~ (castle) ]] || APEX_LIBS="$APEX_LIBS castle"
else
unset APEX_CDB_FILES
fi
[[ "$APEX_WINDOW_SIZE" =~ ^[0-9]{2,6}x[0-9]{2,6}$ ]] || unset APEX_WINDOW_SIZE
[ -z "$APEX_CREATED_FILE_HEADER" ] && APEX_CREATED_FILE_HEADER="This file was autogenerated by the $APEX_NAME management script, and it should not be modified"
[[ "$APEX_HL_DEBUG_PORT" =~ ^[0-9]{1,8}$ ]] || APEX_HL_DEBUG_PORT=6112
[ "$APEX_HL_DEBUG_ATTACH" != "true" ] && APEX_HL_DEBUG_ATTACH=false
echo "'$APEX_NAME' project setup utility"
echo
case "$1" in
"vscode")
echo "starting vscode config setup"
echo
create_vscode_config
;;
"haxe")
echo "starting haxelib repo setup"
echo
rm -rf .haxelib
setup_haxelib_repo
echo
echo "haxelib repo setup successful!"
;;
"cdb")
if [ "$APEX_USE_CDB" != "true" ]; then
echo "cdb must be enabled by setting the env var 'APEX_USE_CDB' to \"true\" before cdb setup can be performed"
else
echo "starting cdb setup"
echo
create_cdb_src
case "$APEX_TARGET" in
"js")
create_file "$(gen_js_hxml)" "$APEX_HXML_FNAME"
;;
"hl")
create_file "$(gen_hl_hxml)" "$APEX_HXML_FNAME"
;;
*)
echo "Warning: Unable to determine target, so a new hxml file could not be generated"
;;
esac
echo "cdb setup successful!"
fi
;;
"full")
echo "starting full project setup"
echo
create_vscode_config
[ ! -e .haxelib ] && setup_haxelib_repo
[ "$APEX_USE_CDB" == "true" ] && create_cdb_src
create_target_files
echo "full project setup successful!"
;;
"cfg")
echo "env config (examine script src for more):"
echo " APEX_NAME = '$APEX_NAME'"
echo " APEX_ENV = '$APEX_ENV'"
echo " APEX_TARGET = '$APEX_TARGET'"
echo " APEX_HXML_FNAME = '$APEX_HXML_FNAME'"
echo " APEX_DIST_DIR = '$APEX_DIST_DIR'"
echo " APEX_RES_DIR = '$APEX_RES_DIR'"
[ -z "$APEX_CDB_FILES" ] || echo " APEX_CDB_FILES = '$APEX_CDB_FILES'"
[ -z "$APEX_WINDOW_SIZE" ] || echo " APEX_WINDOW_SIZE = '$APEX_WINDOW_SIZE'"
if [ "$APEX_TARGET" == "hl" ]; then
echo " APEX_HL_DEBUG_PORT = '$APEX_HL_DEBUG_PORT'"
echo " APEX_HL_DEBUG_ATTACH = '$APEX_HL_DEBUG_ATTACH'"
_hl_path=$(which hl)
if [ -e "$_hl_path" ]; then
echo
echo "hashlink appears to be installed ($_hl_path)"
else
echo
echo "WARNING: hashlink not found in PATH"
fi
unset _hl_path
fi
;;
*)
echo "management script for Visual Studio Code projects, based on"
echo "Haxe, Heaps.io and CastleDB"
echo
echo "usage:"
echo " $0 <command>"
echo
echo "commands:"
echo " vscode: visual studio code settings for building and debugging"
echo " haxe: haxelib repo setup (overwrites any existing repo)"
echo " cdb: castledb setup"
echo " full: full setup"
echo " cfg: show a summary of the env configuration"
echo
echo "copyright 2019 (c) Ole A. Sjo Fasting <oafasting@gmail.com>"
echo
echo "license: MIT"
;;
esac
echo
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment