Project is a cross-platform CLI program to execute commands defined in the Project.yml. Each command is a Lua script. The main different from just is Project focus on cross-platform scripting instead of rely on the other tools.
Warning
There is a plan to upgrade to Lua 5.5 so don't write your script in such a way that it is not compatible with it.
- Batteries included.
- Small and lightweight.
- Easy to install on Linux, macOS and Windows.
- Single executable with only system dependencies.
- Lua 5.4 as scripting language.
- Non-blocking concurrent execution with Lua thread.
- Simple APIs designed for project automation.
- Project are easy lightweight to install (especially if you already have Rust or on Windows).
- No additional steps to install external dependencies required by your scripts.
- APIs designed for project automation.
- Declarative command.
There are 3 ways to install Project:
- Via cargo (recommended if you have Rust).
- Via automated script (recommended if you don't have Rust).
- Manual download.
If you have Rust installed you can use cargo install to install Project:
cargo install projectOr from Git for development version:
cargo install --git https://github.com/ultimaweapon/project.gitTry running Project to see if you have Cargo installation directory in the PATH:
projectIt should output something like:
Failed to open Project.yml: No such file or directory (os error 2).
If it error with command not found you need to add Cargo installation directory to PATH manually. You can find this directory in the outputs of cargo install on the above.
TBA
TBA
Create Project.yml in the root of your repository with the following content:
commands:
build:
description: Build the project
args:
release:
description: Enable optimization
long: release
short: r
type: bool
script: scripts/build.luaThen create scripts/build.lua with the following content:
if args['release'] then
print('Start building release build!')
else
print('Start building debug build!')
endThen run:
project --helpIt will outputs something like:
Run a command defined in Project.yml
Usage: project <COMMAND>
Commands:
build Build the project
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
Notice the build command that loaded from your Project.yml. Run the following command to see how to use your build command:
project build --helpIt will outputs something like:
Build the project
Usage: project build [OPTIONS]
Options:
-r, --release Enable optimization
-h, --help Print help
If you run project build it will run scripts/build.lua, which output the following text to the console:
Start building debug build!
Lua implementation used here is Tsuki. There are some differences with vanilla Lua, which you can see in Tsuki's README. The following is a list of additional changes from Project:
- No
pcall. - No
os.execute. - No
os.exit. - No
os.remove.
A global variable contains all command arguments. If argument name does not present it will return false for bool argument or nil for the other type.
Cause Project process to exit immediately. Unlike os.exit, this function always close all to-be-closed variables.
Parse a JSON string and return a corresponding value (e.g. the result will be a table for JSON object).
Architecture of the OS. The value will be one of aarch64 and x86_64.
Run prog with the remaining arguments as its arguments and return its outputs, which is stdout by default. This does not use OS shell to run prog. The returned string will have LF and/or CR at the end removed by default. This function will raise an error by default if prog exit with non-zero code. By default, stdin will be a null stream and a non-captured stream will be inherits from Project process. Working directory will be the directory that contains Project.yml by default.
All nil in the arguments will be removed (e.g. os.capture('echo', 'abc', nil, 'def') will invoke echo with abc and def as arguments).
If prog is a table the item at index #1 must be the name of program to run and it can contains the following additional items:
Can be either stdout, stderr or both. If this key does not present it will default to stdout. With both this function will return a table contains stdout and stderr fields.
Copy a file from src to directory dst. This function will overwrite file with the same name in dst. mode can be either:
content: Copy only content, not permissions. This is default ifmodeis absent.all: Copy both content and permissions. This use tokio::fs::copy under the hood.
Returns number of bytes copied.
Copy a file from src to dst. This function will overwrite the contents of dst. Note that dst always treat as a destination file, not a destination directory. mode can be either:
content: Copy only content, not permissions. This is default ifmodeis absent.all: Copy both content and permissions. This use tokio::fs::copy under the hood.
Returns number of bytes copied.
Recursively create a directory and all of its parent components if they are missing. Path will be joined together with native path separator to form a path to directory so:
local r = os.createdir('abc', 'def')
if t[1] then
-- 'abc' does not exists before and was created by the call
endWill result in abc/def on *nix and abc\def on Windows as a path to create. This use PathBuf::push to create the path so if any arguments is an absolute path it will discard the path that was created by previous arguments.
Returns a table consist of argument number as a key and boolean as a value indicated if the component was created by the call (that is, not exists before the call).
Kind of the OS. The value will be one of linux, macos and windows.
Remove a directory and its content, which mean it will always remove the directory even if the directory is not empty. Path will be joined together with native path separator to form a path to directory so:
os.removedir('abc', 'def')Will result in abc/def on *nix and abc\def on Windows as a path to remove. This use PathBuf::push to create the path so if any arguments is an absolute path it will discard the path that was created by previous arguments.
Run prog with the remaining arguments as its arguments. Unlike os.execute, this does not use OS shell to run prog. This function will raise an error by default if prog exit with non-zero code. By default, stdin will be a null stream and stdout/stderr will be inherits from Project process and working directory will be the directory that contains Project.yml.
All nil in the arguments will be removed (e.g. os.run('echo', 'abc', nil, 'def') will invoke echo with only 2 arguments).
Run prog with the remaining arguments as its arguments and return a process object to manipulate it. This does not use OS shell to run prog. By default, stdin will be a null stream and a non-captured stream will be inherits from Project process. Working directory will be the directory that contains Project.yml by default.
All nil in the arguments will be removed (e.g. os.spawn('echo', 'abc', nil, 'def') will spawn echo with only 2 arguments).
The process object can be a to-be-closed variable, which will kill the process when the object goes out of scope. If the variable does not have close attribute the process will get killed when the object is freed by Lua GC.
If prog is a table the item at index #1 must be the name of program to run and it can contains the following additional items:
Working directory for the process. If this key does not present it will default to the directory that contains Project.yml.
Can be either null, inherit or pipe. If this key does not present it will default to inherit. For pipe the process object will have stdout property, which have read method.
Returns the final component of the path, if there is one. This use Path::file_name under the hood.
Returns path without its final component, if there is one. This use Path::parent under the hood.
Returns a joined path components so:
path.join('abc', 'def')Will result in abc/def on *nix and abc\def on Windows. This use PathBuf::push to create the path so if any arguments is an absolute path it will discard the path that was created by previous arguments.
Capitalize str and return it. mode can be either:
first: Capitalize only the first letter. This is default ifmodeis absent.
Create an instance of Url class from url. This class has the following properties and methods:
Returns the path for the URL, as a percent-encoded ASCII string.
Project will exit with exit code 0 when all operations completed successfully. The script can use exit to exit with a custom exit code. The code 100 and above are reserved for Project use and have the following meaning:
The script exit with an error. This is runtime error, not compile time.
Project process was panic. This indicate an underlying bug on Project itself to please report this!
Project unable to open Project.yml.
Project unable to parse Project.yml.
No action is defined for some commands.
Project unable to read Lua script for the command.
Project unable to load Lua script for the command.
Project unable to setup Tokio.
List of commands.
A command definition.
Description of the command.
Description of the argument.
Long name of the argument (e.g. help).
Shot name of the argument (e.g. h).
Type of the argument. Can be either bool or string.
Placeholer of argument's value.
Default value if argument presented but the value is missing.
Path to Lua script to execute when this command is invoked. Path separator always is / even on Windows and Project will convert to native path.
This project is licensed under either of
- Apache License, Version 2.0,
- MIT license
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.