Git Product home page Git Product logo

rant's Introduction

Rant Logo

Crates.io Docs.rs Discord

Rant is a dynamically-typed, multi-paradigm templating language designed primarily for procedural generation. It is designed with scalability in mind: it can handle tasks ranging from simple randomized string generation to more complex workloads such as procedural dialogue, character generation, and worldbuilding.


Prerelease notice

This project is in alpha. This means that the API is unstable, functionality may be broken/missing, and everything is subject to change.

Please dont hesitate to try it out and give feedback; however, do not use in production environments until a stable version is released.

Features may appear/disappear at any time for any reason. Assume that every alpha release will have breaking changes.

Introducing Rant 4

Rant is the result of a long-standing desire for an all-in-one data templating tool made especially for creative applications like games and interactive art.

Rant 4 is the next leap forward in achieving this goal: the syntax, standard library, and interpreter have all been completely reimagined from the ground up.

Features

๐Ÿงฐ Painless API
Rant has a no-nonsense API designed for ease of use. No getting lost in configuration hell. Integrating Rant into your project only takes a few lines of code.

๐Ÿ’ป Cross-platform
Write once, run anywhere! The runtime works the same across Windows, Mac, Linux, and WebAssembly.

โœ Templating that does more
Rant is all about "printing": each lexical scope has an output to print (append values) to, which then prints itself to the parent output, and so on. This enables you to intuitively build strings, collections, and more in a familiar templating setting.

๐ŸŽจ Now intentionally Turing-complete!
In addition to being a templating language, Rant adopts declarative and imperative programming concepts with design influences from many other popular languages.

โœจ Generate anything โ€” not just text
Unlike older Rant versions that could only generate strings, Rant 4 can output arbitrary data structures using any of the built-in data types. Enjoy first-class support for common primitives like strings, numbers, collections, closures, and more.

๐ŸŽฒ Built with โ™ฅ for RNG
Rant is made with random generation in mind as a major use-case.

Make use of a wide array of built-in utilities for generating random numbers, strings, booleans, lists, list subsets, and much more for all your randomization needs. The internal RNG can be manually seeded to produce repeatable outputs.

๐Ÿ”ฑ Branching and beyond
Augment regular control flow behavior with a multitude of configuration options for iterative, randomized, and weighted branch selection.

๐Ÿงฌ Delightful combinatorics
Perform nested mappings, filters, zips, combinations, and more with minimal effort. Rant's powerful piping syntax lets you perform complex operations with shorter, more readable code.

๐Ÿ“ Automatic text formatting
Passively format text output with automatic capitalization, whitespace normalization, and number formatting โ€” including built-in support for numerous writing systems.

๐Ÿ“ฆ Data sources
Attach custom data sources to your Rant execution context to give your scripts controlled access to external resources.

๐Ÿงฉ Simple module system
Sharing code between Rant programs is trivial. Just write your module script and @require it elsewhere.

Need custom module resolution logic? No problem. You can write your own resolver and just plug it in.

๐Ÿ“š Rant Standard Library
A comprehensive standard library provides the tools needed to quickly iterate on your ideas.

๐Ÿงช Use integrated or standalone
Whether you want to integrate Rant directly into a product or use it as a standalone tool to assist with writing, Rant has a place in any part of your workflow.

Getting started

Rant is written in Rust, so you'll need to install the toolchain in order to build it.

CLI

Rant's CLI can run Rant code from files or the command line. Install it from Cargo with:

$ cargo install rant --version 4.0.0-alpha.33 --features cli

Then run it:

# Launch the REPL
$ rant

# Get a full list of options
$ rant -h

# Run an inline script and display output
$ rant -e '[rep:3] [sep:\s] {b{ee|i|o|u}bbity}'

# Run hello_world.rant and send output to result.txt
$ rant hello_world.rant > result.txt

Library

To use Rant in a Rust project, add the rant crate to Cargo.toml:

[dependencies]
rant = "*"

You can run a Rant program with just a few lines of code:

use rant::Rant;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
  // Create a default Rant context
  let mut rant = Rant::new();

  // Compile a simple program
  let program = rant.compile_quiet(r#"
  [$greet:name] {
    {Hello|Hi|Hey} <name>!
  }
  [greet:world]
  "#)?;

  // Run the program and print the output
  let output = rant.run(&program)?;
  println!("{}", output);

  Ok(())
}

This repository includes a collection of example Rant scripts for you to learn from. Check them out!

Documentation

The latest reference documentation can be found at docs.rant-lang.org.

Since Rant 4 is early in development, some documentation may be outdated/incomplete, but it is actively updated to ensure that it reflects current features with reasonable accuracy.

The changelog is updated constantly throughout the development process, providing a complete summary of upcoming changes at a glance even before the next release.

License

Licensed under either of

at your option.

rant's People

Contributors

lanice avatar tamschi avatar theberkin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

rant's Issues

Boolean operations via printing

Add a set of keywords to make a printable sequence perform a short-circuiting boolean operation:

Proposal

Make sequences configurable to perform various boolean operations by prefixing them with any of several special @is-keywords. Each printed value acts as a separate operand; whitespace is ignored.

Short-circuiting

Some operations are "short-circuiting"-- meaning that Rant may not evaluate the entire sequence in the scope if the result can be determined early. For example, if the first operand of a short-circuiting AND operation evaluates to false, we know that the result will be false, so we can skip evaluating the rest of the operands.

Eagerness

The + token can be placed after the operator keyword (e.g. @isany+) to disable short-circuiting and make the sequence eagerly evaluated.

@isany

The @isany keyword creates a short-circuiting boolean OR expression.

Truth table

@isany A B A = true A = false
B = true true true
B = false true false

@isall

The @isall keyword creates a short-circuiting boolean AND expression.
Its complement is @isntall.

Truth table

@isall A B A = true A = false
B = true true false
B = false false false

@isntall

The @isntall keyword creates a short-circuiting boolean NAND expression.

Truth table

@isntall A B A = true A = false
B = true false true
B = false true true

@isnone

The @isnone keyword creates a short-circuiting boolean NOR expression.
Its complement is @isany.

Truth table

@isnone A B A = true A = false
B = true false false
B = false false true

@isone

The @isone keyword creates a short-circuiting boolean XOR expression.

Truth table

@isone A B A = true A = false
B = true false true
B = false true false

@ismany

The @ismany keyword creates a short-circuiting expression that evaluates to true if more than one of the operands evaluates to true; otherwise, it evaluates to false.

Truth table

@ismany A B C A = true A = false
B = false, C = false false false
B = true, C = false true false
B = false, C = true true false
B = true, C = true true true

@issame

The @issame keyword creates a short-circuiting equality expression.
Its complement is @isdiff.

Although the truth table shows boolean inputs, this operation accepts all types.

Truth table

@issame A B C A = true A = false
B = false, C = false false true
B = true, C = false false false
B = false, C = true false false
B = true, C = true true false

@isdiff

The @isdiff keyword creates a short-circuiting inequality expression.
Its complement is @issame.

Although the truth table shows boolean inputs, this operation accepts all types.

Truth table

@isdiff A B C A = true A = false
B = false, C = false true false
B = true, C = false true true
B = false, C = true true true
B = true, C = true false true

Default values on optional parameters

Optional parameters in user function signatures should accept an optional default value. This value populates the parameter if the caller does not provide a value for it.

Syntax

The default value should appear directly after the ? modifier and be a compile-time, immutable constant (e.g. any atomic or immutable collection type)

[%opt-func: a ? foo] {
  <a>
}
[opt-func] # should print 'foo'
[opt-func: bar] @ should print 'bar'

Any of the following tokens should be accepted as a fallback:

  • String literal
  • Single fragment
  • Number literal
  • Stored block
  • Boolean literal
  • Lambdas

unix cli file pipe turns into endless loop

trying to pipe a file into rant-cli with '<' operator causes weird endless loop.

rant < public/rant.rant 
>> Heads
Tails
Heads
Heads
Heads
Tails
Heads
Heads
Heads
Heads

>> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>

First-class conditional expressions

Add if-else expressions to the language itself to simplify boolean branching

Proposal

Introduce the @if, @elseif, and @else keywords.

@if

@if is non-contextual and requires two parts: a condition and a body. Both can be any Rant expression (not a sequence).

In contrast to the existing [if] behavior, the body is not required to be (but can still be) a block.

# General structure
@if <condition> <body>

# Examples
@if [eq: <a>; <b>] "It's a match!"

@if [eq: <a>; <b>] {
  "It's a match!"
}

@elseif

@elseif behaves the same as @if but only runs if the previous @if or @elseif condition was not met.

@elseif has the same syntax as @if but is contextual: it must directly follow an @if or @elseif body.

<$a = 2>
@if [eq: <a>; 1] "one"
@elseif [eq: <a>; 2] "two"

# should print "two"

@else

@else runs an expression if the penultimate @if or @elseif condition in the current chain was not met.

@else must follow the body of an @if or @elseif and only requires the body component.

<$a = 3>
@if [eq: <a>; 1] "one"
@elseif [eq: <a>; 2] "two"
@else "neither one nor two"

# should print "neither one nor two"

Allow trailing semicolon in list initializers

List initializers should allow a trailing semicolon at the end of the element list without automatically creating an empty at the end of the list.

Proposal

The following rules should apply when parsing semicolons in a list initializer context:

An empty list initializer with no semicolons produces an empty list

This is the current behavior, but it is worth noting that this should remain the case.

() # empty list

A semicolon only guarantees a value to its left

Even if there is nothing before the semicolon, it should signal to the compiler that there should be an empty element.

(;) # same as (~)

A final value with a terminating semicolon acts the same one without it

If a list ends with a value and no trailing semicolon, it should compile to the same list as one with the semicolon.

# 2-item list without trailing semi
(a; b) 
# Same 2-item list with trailing semi
(a; b;)

Prototypes

Add support for prototype functions to map objects for OOP workflows, custom access logic, etc.

This is a WIP issue for ongoing design work on prototypes.

Getting and setting prototypes

Map prototypes can be retrieved and assigned with [proto] and [set-proto] respectively:

<$myobj = @()>
<$myproto = @(proto-method = [?]{foo})>
[set-proto:<myobj>;<myproto>]
[proto:<myobj>] # [map(1)]

Prototype methods

Elements of a map's prototype act like elements of the owning map.

<$myobj = @()>
<$myproto = @()>

[$myobj/test] { foo }
[$myproto/test] { bar }

[set-proto: <myobj>; <myproto>]

[myobj/test] # bar

Pattern matching

Implement the @on keyword to allow blocks to be used for pattern matching.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.