Initial commit. Didn't realise I'd be using this in so many different places!

This commit is contained in:
Starbeamrainbowlabs 2018-06-07 15:15:23 +01:00
commit 826fb3ffe3
Signed by: sbrl
GPG Key ID: 1BE5172E637709C2
3 changed files with 481 additions and 0 deletions

193
README.md Normal file
View File

@ -0,0 +1,193 @@
# Lantern Build Engine
> A simple bash-based build engine for automating complex, fiddly, and boring development tasks.
Wow, this ran away from me! This was initially a simple bash script for a private project of mine, but it seems to have turned into a general-purpose engine all by itself. I guess that stealing it for a bunch of University projects had something to do with that.... :P
## Installing
The lantern build engine is meant to be included in your project as a git submodule.
1. Add this repository as a git submodule: `git submodule add {{clone-url}} {{path/to/destination-directory}}`
2. `source` the file `lantern.sh` into your build script.
An example build script can be found in this repository - it's called `build-example`.
## Usage
The lantern build engine basically exposes a set of utility function that make writing a flexible build script _much_ easier. Start by copying the example build script, and customising it to suit your own needs.
Each task is a function that's prefixed with `task_`, so you can wire up task dependencies as complex or as simple as you like! At the end of your build script, execute the provided `tasks_run` function like this to execute all the requested tasks: `tasks_run $@`
### `set-title "{{title name}}"`
Sets the title of the terminal the build script is running in. Has no effect if the build script isn't being run in a terminal as far as I'm aware.
```bash
set-title "Current item: ${item_name}";
```
### `cursor_position {{x}} {{y}}`
Sets the cursor's position on the screen.
```bash
cursor_position 10 20; # Sets the cursor's position to (10, 20)
```
### `cursor_up {{rows}}`
Moves the cursor up by a specified number of rows.
```bash
cursor_up 5;
```
### `cursor_down {{rows}}`
Moves the cursor down by a specified number of rows.
```bash
cursor_down 5;
```
### `cursor_left {{cols}}`
Moves the cursor left by a specified number of columns.
```bash
cursor_left 5;
```
### `cursor_right {{cols}}`
Moves the cursor right by a specified number of columns.
```bash
cursor_right 5;
```
### `cursor_save`
Saves the cursor's current position. Takes no arguments.
```bash
cursor_save;
```
### `cursor_restore`
Restores the cursor's position to the last saved position. Takes no arguments.
```bash
cursor_restore;
```
### `right_aligned_text {{width}} "{{text}}"`
Right-aligns the specified text such that it's on the the right-hand-side of the terminal when `echo`ed. The `{{width}}` parameter here is the width of the provided text, as ANSI colour escape codes throw the width calculations off (a pull request fixing this would be most welcome!).
```bash
right_aligned_text 12 "Hello, World!";
# Example output: " Hello, World!" (without quotes, of course)
```
### `task_status {{2-char-code}}`
Used internally. Generates a 2-character status code like OpenRC and others do in the terminal on startup. See the example for more details.
```bash
set_status "!!";
# Output: "[ !! ]" (With the square brackets in bright blue)
```
### `stage_begin "{{stage_name}}"`
Begins a build stage. The output will fill the terminal's width.
```bash
stage_begin "Building";
# Output for a 20 column wide terminal:
# ----[ Building ]----
```
### `stage_end {{exit_code}}`
Ends a stage, displaying either `ok` or `!!`, depending on whether the exit code provided is 0 or not (an exit code of 0 means success). The output will be coloured, of course - this isn't displayed below due to limitations in markdown.
```bash
echo "Testing";
stage_end $?;
# Output for a 20 column wide terminal:
# -------[ ok ]-------
```
### `task_begin "{{task_name}}"`
Begins a task. Works similarly to `stage_begin` - the visuals are just different.
```bash
task_begin "Checking environment";
# Output for:
# * Checking environment
```
### `task_end {{exit_code}}`
The same as `stage_end`, but the visuals are a bit different. The 2-character status code (` [ xy ] `) is displayed at the right-hand side on the line above the line that the cursor is currently on.
```bash
task_begin "Checking environment";
task_end 0;
# Output:
# " * Checking environment [ ok ] " (without quotes)
```
```bash
task_begin "Combobulating discombobulators";
# ......
task_end $?;
```
...might output something like this:
```
* Combobulating discombobulators
Output
More output
Even moar output
Yay for output [ ok ]
(cursor position is here)
```
### `subtask_begin "{{task_name}}"`
For splitting up your tasks even further! Generally, if you find yourself using a lot of these, try upgrading to stages and tasks instead of tasks and subtasks - particularly because these don't play so well with output, due to changing the colour of the asterisk (this may be fixed in the future, if the appropriate magic can be conjured :P).
```bash
subtask_begin "Checking git";
# Output: " * \tChecking git" (without quotes, and replacing "\t" with a tab character)
```
### `subtask_end {{exit_code}}`
The counterpart to `subtask_begin`, this changes the asterisk colour and outputs a 2-character status code to complete a subtask.
```bash
subtask_begin "Checking git";
which git 1>/dev/null 2>&1;
subtask_end $?;
# Output:
# * \tChecking git [ ok ]
# (replacing "\t" with a tab character)
```
### `check_command "{{binary_name}} {{subtask}}"`
Automagically checks for the presence of a command. Kills the process with an exit code of `2` if it can't be found. Setting `{{subtask}}` to a non-empty string causes `subtask_begin` / `subtask_end` to be called appropriately - otherwise it's invisible.
```bash
task_begin "Checking environment";
check_command "git" true;
check_command "msbuild" true;
task_end 0;
```
### `tasks_run {{task_name}} {{task_name}} .....`
Runs the specified tasks in the specified order. Call this at the bottom of your build script.
```bash
tasks_run setup; # Runs the task_setup function
tasks_run build package; # Runs the build and package tasks as above
tasks_run $@; # Passes all arguments (except the script name / path itself) to the task runner
```
## Contributing
Contributions are welcome! Simply fork this repository, make your changes, and submit a Pull Request (aka Merge Request).
All contributions must be declared to have the `Mozilla Public License 2.0` (the same license that this repository is under).
## License
The lantern build engine is licensed under the _Mozilla Public License 2.0_ (MPL-2.0). This license can be found in the _LICENSE_ file in this repository, along with a link to an easy-to-read summary.

124
build-example Executable file
View File

@ -0,0 +1,124 @@
#!/usr/bin/env bash
project_name=micro-lanterns;
build_output_folder="dist/";
###############################################################################
source $(dirname $0)/lantern.sh
if [[ "$#" -lt 1 ]]; then
echo -e "${FBLE}${project_name}${RS} build script";
echo -e " by Starbeamrainbowlabs";
echo -e "${LC}Powered by the lantern build engine, v${version}${RS}";
echo -e "";
echo -e "${CSECTION}Usage${RS}";
echo -e " ./build ${CTOKEN}{action}${RS} ${CTOKEN}{action}${RS} ${CTOKEN}{action}${RS} ...";
echo -e "";
echo -e "${CSECTION}Available actions${RS}";
echo -e " ${CACTION}setup${RS} - Perform initial setup";
echo -e " ${CACTION}main${RS} - Perform a regular build";
echo -e " ${CACTION}sprites${RS} - Build the spritesheet";
echo -e " ${CACTION}js${RS} - Build the javascript";
echo -e " ${CACTION}dev-server${RS} - Start a development server";
echo -e " ${CACTION}dev-server-stop${RS} - Stop the currently running development server";
echo -e "";
exit 1;
fi
###############################################################################
function task_setup {
task_begin "Setting up";
check_command git true;
check_command msbuild true;
check_command node true;
check_command npm true;
subtask_begin "Creating build output directory";
mkdir -p "${build_output_folder}";
subtask_end $?;
subtask_begin "Initialising submodules";
git submodule update --init;
subtask_end $?;
task_end 0;
}
function task_dev-server {
task_begin "Starting development server";
php -S [::1]:40482 -t "${build_output_folder}" &
exit_code=$?;
echo $! >/tmp/micro-lantern-dev-server.pid;
task_end $?; # Should be 0 unless php died for some reason
sleep 1;
}
function task_dev-server-stop {
task_begin "Stopping development server";
kill "$(cat /tmp/micro-lantern-dev-server.pid)";
rm /tmp/micro-lantern-dev-server.pid;
task_end $?;
}
function task_main {
run_task js;
task_begin "Copying html";
cp index.html "${build_output_folder}";
task_end $?;
task_begin "Copying css";
cp theme.css "${build_output_folder}";
task_end $?;
}
function task_js {
task_begin "Validating scripts";
scripts/validate.sh
task_end $?;
task_begin "Running webpack";
node_modules/webpack/bin/webpack.js --config webpack.config.js
exit_code=$?;
task_end ${exit_code};
if [[ "${exit_code}" -ne 0 ]]; then
exit 1;
fi
}
function task_sprites {
# Build SpritePacker if required
if [ ! -f "./tools/SpritePacker/SpritePacker-CLI/bin/Debug/SpritePackerCLI.exe" ]; then
task_begin "Building SpritePacker";
cd tools/SpritePacker;
msbuild; exit_code=$?;
task_end $exit_code;
if [[ "${exit_code}" -ne 0 ]]; then
exit ${exit_code};
fi
fi
task_begin "Building Sprites";
echo -e "Not implemented yet";
task_end 0;
}
###############################################################################
tasks_run $@;

164
lantern.sh Executable file
View File

@ -0,0 +1,164 @@
#!/usr/bin/env bash
version="0.5";
##########################
### Colour Definitions ###
#### ANSI color codes ####
RS="\033[0m" # reset
HC="\033[1m" # hicolor
UL="\033[4m" # underline
INV="\033[7m" # inverse background and foreground
LC="\033[2m" # locolor / dim
FBLK="\033[30m" # foreground black
FRED="\033[31m" # foreground red
FGRN="\033[32m" # foreground green
FYEL="\033[33m" # foreground yellow
FBLE="\033[34m" # foreground blue
FMAG="\033[35m" # foreground magenta
FCYN="\033[36m" # foreground cyan
FWHT="\033[37m" # foreground white
BBLK="\033[40m" # background black
BRED="\033[41m" # background red
BGRN="\033[42m" # background green
BYEL="\033[43m" # background yellow
BBLE="\033[44m" # background blue
BMAG="\033[45m" # background magenta
BCYN="\033[46m" # background cyan
BWHT="\033[47m" # background white
CSECTION=${HC}${FBLE};
CTOKEN=${FCYN};
CACTION=${FYEL};
##########################
# Sets the title of the terminal window.
# $1 - The new text to set the title to.
function set-title { echo -e '\033]2;'$1'\033\\'; }
#######################
### Cursor Movement ###
# http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x361.html
function cursor_position {
echo -ne "\033[$1;$2H";
}
function cursor_up {
echo -ne "\033[$1A";
}
function cursor_down {
echo -ne "\033[$1B";
}
function cursor_right {
echo -ne "\033[$1C";
}
function cursor_left {
echo -ne "\033[$1D";
}
function cursor_save {
echo -ne "\033[s";
}
function cursor_restore {
echo -e "\033[u"
}
#######################
# $1 - The width of the text to draw
# $2 - The text to draw
function right_aligned_text {
cursor_save
echo -ne "\r"; # Reset to the beginning of the line
location_start=$((( $(tput cols) - $1))); # Calculate where we need to draw at
cursor_right ${location_start}; # Jump ahead to the right place
echo -ne "$2"; # Draw the string
cursor_restore
}
# $1 - The 2-character status to show
function task_status {
right_aligned_text 6 "${HC}${FBLE}[${RS} $1 ${HC}${FBLE}]${RS}";
}
# $1 - The stage name
function stage_begin {
term_width=$(tput cols);
title_length=$(echo -ne "$1" | wc -m);
padding_length=$((term_width / 2 - title_length / 2 - 2 - 1));
echo -e "${HC}${FBLE}$(printf '%*s' ${padding_length} | tr ' ' '-')[${RS} $1 ${HC}${FBLE}]$(printf '%*s' ${padding_length} | tr ' ' '-')${RS}";
}
# $1 - The exit code
function stage_end {
display_text="${HC}${FGRN}ok${RS}"
if [[ $1 -ne 0 ]]; then
display_text="${HC}${FRED}!!${RS}";
fi
term_width=$(tput cols);
padding_length=$((term_width / 2 - 3 - 1));
echo -e "${HC}${FBLE}$(printf '%*s' ${padding_length} | tr ' ' '-')[${RS} ${display_text} ${HC}${FBLE}]$(printf '%*s' ${padding_length} | tr ' ' '-')${HC}${FBLE}";
}
# $1 - The task name
function task_begin {
echo -ne " ${FGRN}*${RS} $1";
echo -e "";
}
# $1 - Exit code
# $2 - Error message (only displayed if the exit code isn't 0)
function task_end {
cursor_up 1;
if [[ "$1" -ne "0" ]]; then
echo -ne " ${FRED}*${RS} $2";
task_status "${HC}${FRED}!!${RS}";
else
task_status "${HC}${FGRN}ok${RS}";
fi
echo -e "";
}
# $1 - Task name
function subtask_begin {
echo -ne " ${FBLE}*${RS} $1";
}
# $1 - exit code
# $2 - error message (only displayed if the exit code isn't 0)
function subtask_end {
if [[ "$1" -ne "0" ]]; then
echo -ne "$2";
echo -e "\r ${FRED}*${RS}";
else
echo -e "\r ${FGRN}*${RS}";
fi
}
# $1 - Command name to check for
# $2 - Whether to call subtask_begin/end
function check_command {
if [ "$2" != "" ]; then
subtask_begin "Checking for $1";
fi
which $1 >/dev/null 2>&1; exit_code=$?
if [[ "${exit_code}" -ne 0 ]]; then
task_end ${exit_code} "Error: Couldn't locate $1. Make sure it's installed and in your path.";
if [ "$3" != "optional" ]; then
exit 2;
fi
fi
if [ "$2" != "" ]; then
subtask_end 0;
fi
}
function tasks_run {
while test $# -gt 0
do
task_$1;
shift
done
}