4 releases

0.2.1 Feb 22, 2023
0.2.0 Jan 28, 2023
0.1.2 Dec 23, 2022
0.1.0 Dec 20, 2022

#266 in Text processing

37 downloads per month

Custom license

551 lines

Ranting ╰(°Д°)/

github crates.io docs.rs

This library provides Ranting, a trait for inflection within say!() litteral string placeholders.

ranting = "0.2"


  • A say!() macro produces a String similar to format!(), but with placeholder markers a pronouns can be received. A verb alongside, always specified in plural, inflects accordingly.
use ranting::*;
use ranting_derive::*;

fn say_this(who: Noun, title: &Noun) -> String {
    say!("{=who do} say {`who title are} {who}.")

fn main() {
    let title = Noun::new("name", "it");
        say_this(Noun::new("Jane", "I"), &title),
        "I do say my name is Jane.".to_string()
        say_this(Noun::new("Tarzan", "he"), &title),
        "He does say his name is Tarzan.".to_string()
  • Noun is a struct with the Ranting trait. You can use #[derive(Ranting)] on a struct or enum for similar behavior. To specify the subject use I .. they, thou or ye.

  • A placeholder to display a Ranting variable has a structure like:

``{[,^]?(verb )?(article |`noun )?([+-]|([#$]|\?$)var )?[`=@~?*]?noun( verb):fmt}``
  • With , and ^ lower- and uppercase are enforced, but a placeholder at sentence start is uppercase by default. Also an article or verb with an uppercase causess an uppercase for the first character.
fn state<T: Ranting>(who: T, liberty: &str) -> String {
    say!("{haven't =who} a {liberty} to say {a who's} land is {~who}?")

#[ranting(subject = "he")]
struct Earl {}

#[ranting(subject = "they")]
struct Farmers {}

fn main() {
        state(Earl {}, "right"),
        "Hasn't he a right to say an earl's land is his?".to_string()
        state(Farmers {}, "right"),
        "Haven't they a right to say some farmers' land is theirs?".to_string()
  • An article, possesive 's or verbs before the noun are also adapted. Normal placeholders just follow their Display or Debug traits within say!().

  • A given Ranting Enum or Struct can also be inflected to plural or singular. To force plurality use +, for a singular use -. If prependeded by $var or #var, plurality of the noun is adapted to the numeric variable var. Which is displayed, unless prepended with a '?'. The number is converted to a word for #var. Other words within the placeholder are adapted accordingly as well.

  • A Noun or pronoun is displayed dependent on its leading character or string marker.

    • ? - subject in inflection, but neither variable nor its space is displayed.
    • = - subject
    • @ - object
    • ` - possesive
    • ~ - adjective
    • * - display the name (as is the default) but also mark this word as the Ranting element in the placeholder. "A {*can can} contain water." (removed the mutname variant)
  • If a Noun or numeric plurality has a leading question mark, it is hidden but its inferred inflection does apply.

  • An 'article' can be one of a, an, some, the, those or these. These and those are converted to this and that if the pronoun is singular. A question mark indicates its display dependends (see no_article).

  • ack!() and nay!() provide an Ok() / Err() return with a say!() formatted string included. Intended for allow or deny ranting responses. Not for error handling, because true errors should be easy to search in code.

  • A struct can receive via attributes:

    • subject ["it"] - indicates the pronoun, if "$", the struct is assumed to contain a String 'subject'
    • name [Struct or Enum name; lowercase] - the display name. when "$' the struct contains a name String.
    • singular_end [""] - for inflection, what name + singular_end if the plurality is '-'? can also be "$"
    • plural_end ["s"] - likewise, name end if plurality is '+' or #var != 1.
    • is_plural [as subject] - if subject is "you", this indicates whether that means plural or not.
    • uc [false] - indicate if the word should always start with an uppercase.
    • no_article [false] - indicate that the word should be without article if the article if prepended with a '?'. say!("{?the 0} was great!", activity) // e.g. for activity = tennis with no_article=true. (The latter two do not yet have the "$" variant)

Positional argument and numeric references are supported, but named arguments or empty arguments are not, currecntly.

fn main() {
    let thing = Noun::new("thing", "it");

    assert_eq!(say!("this is {=thing}."), "this is it.".to_string());
    assert_eq!(say!("this is {=0}.", thing), "this is it.".to_string());

    // won't work:
    //assert_eq!("{}", say!("this is {=x}.", x = thing), "this is it.".to_string());
    //assert_eq!("{}", say!("this is {=}.", thing), "this is it.".to_string());


~83K SLoC