Grimoire is a Python library for creating interactive fiction as hyperlinked html.

Overview

Grimoire

Grimoire is a Python library for creating interactive fiction as hyperlinked html.

tests

Installation

pip install grimoire-if

Usage

Check out the tutorial created in Grimoire itself (source).

Get started

Create an instance of a Grimoire app.

from grimoire import Grimoire


app = Grimoire()

Add your first page

Create a function decorated by your app's page method. Pass the keyword argument, start=True for the first page.

@app.page(start=True)
def start(state):
    return "This is my first grimoire app.", state

Render your story

You can render our (rather boring) story right now by calling the app's render method.

# will create all the file in the /site directory

app.render()

# optionally pass an alternate path

app.render("docs/")

Inline html

The content your page function returns is rendered using Python's built-in str function, so you can include html directly in a string if you'd like.

Alternativley, Grimoire comes with a small library for creating html called hype. Import hype's classes and create html using only Python!

from hype import H1, P


@app.page(start=True)
def start(state):
    return Div(
        H1("My First Grimoire Story"),
        "<p>Inline html as a string<p>",
        P("Html using the Hype library")
    ), state

Add an option to your first page

Create another page function (we don't need start=True this time). To add this as an option to an existing page, pass an argument to the parent page which has the same name as the new page function. Use Grimoire's builtin link function to create a link to the page.

You can add as many options as you like by continuing to add arguments to a parent page's function signature.

from grimoire.templates import link


@app.page(start=True)
def start(state, second):
    return Div(
        P("Hello, Grimoire!"),
        Ul(Li(link("Go to the second page", second)))
    ), state


@app.page()
def second(state):
    return Div(
        P("I'm the second page.")
    ), state

Manage your stories state

The state object passed to your page function can be read and updated to manage the state of your application. By default it's a dictionary.

Notice how the we access the message from the first page in the second page.

@app.page(start=True)
def start(state, second):
    state["message"] = "Hello, traveller"
    return Div(
        P("Hello, Grimoire!"),
        Ul(Li(link("Go to the second page", second)))
    ), state


@app.page()
def second(state):
    return Div(
        P(f"message: {state['message']}")
    ), state

Use a custom state class

Dictionaries are cool, but often a custom class will make writing our code much more enjoyable. You can add a custom state class when creating your app.

from dataclasses import dataclass


@dataclass
class State:
    message: str = ""


app = Grimoire(State)


@app.page(start=True)
def start(state, second):
    state.message = "Hello, traveller"
    return Div(
        P("Hello, Grimoire!"),
        Ul(Li(link("Go to the second page", second)))
    ), state


@app.page()
def second(state):
    return Div(
        P(f"message: {state.message}")
    ), state

Back to the beginning

Circular references are easy in Grimoire. Just add the option argument for an eariler page.

Warning: Be careful about creating infinite loops. Grimoire will continue rendering pages as long as it's seeing a version of the state that hasn't previously been rendered.

@app.page(start=True)
def start(state, second):
    state.message = "Hello, traveller"
    return Div(
        P("Hello, Grimoire!"),
        Ul(Li(link("Go to the second page", second)))
    ), state


@app.page()
def second(state, start):
    return Div(
        P(f"message: {state.message}"),
        Ul(Li(link("Start over", start)))
    ), state

Default page function

Grimoire comes packaged with a function to style your page and render your options by default. It returns a decorator which can be applied to your page functions.

from grimoire.templates import default_page


@app.page(start=True)
@default_page("Minimal Example")
def start(state, second):
    state.message = "Hello, traveller"
    return Div(
        P("Hello, Grimoire!")
    ), [("Go to the second page", second)], state

# Also try changing up some of the colors

@app.page()
default_page(
    "Minimal Example",
    primary_bg_color="#ff0000",
    secondary_bg_color="#00ff00"
    font_color="#bbbbbb"
)
def second(state, start):
    return Div(
        P(f"message: {state.message}")
    ), [("Start over", start)], state

Next Steps

That's it! You've completed the Grimoire tutoiral. As you can see, there's not much to it. Grimiore is purposeley very minimal and our belief is that many features can be easily implemented using plain old vanilla Python on top of Grimoire.

Check some further examples:

Number calculator application.

Number calculator application.

Michael J Bailey 3 Oct 08, 2021
Basic infrastructure for writing scripts in Python

Base Script Python is an excellent language that makes writing scripts very straightforward. Over the course of writing many scripts, we realized that

Deep Compute, LLC 9 Jan 07, 2023
Procedurally generated Oblique Strategies for writing your own Oblique Strategies

Procedurally generated Oblique Strategies for writing your own Oblique Strategies.

Gordon Brander 13 Aug 17, 2022
8 Nov 04, 2022
Tracing and Observability with OpenFaaS

Tracing and Observability with OpenFaaS Today we will walk through how to add OpenTracing or OpenTelemetry with Grafana's Tempo. For this walk-through

Lucas Roesler 8 Nov 17, 2022
This is a fork of the BakeTool with some improvements that I did to have better workflow.

blender-bake-tool This is a fork of the BakeTool with some improvements that I did to have better workflow. 99.99% of work was done by BakeTool team.

Acvarium 3 Oct 04, 2022
Data 25 Star Wars Project With Python

Data 25 Star Wars Project Instructions The character data in your MongoDB database has been pulled from https://swapi.tech/. As well as 'people', the

1 Dec 24, 2021
Make pack up python files easier.

python-easy-pack make pack up python files easier. 目前只提供了中文环境 如何使用? 将index.py复制到你的项目文件夹,或者把.py文件拷贝到这个文件夹。 打开你的cmd或者powershell 切换到程序所在目录,输入python index

2 Dec 15, 2021
Anki Cards for the HSK vocabulary Chinese-German

Anki-HanyuShuipingKaoshi Anki Cards for the HSK vocabulary Chinese-German Das Deck baut auf folgenden Quellen auf: China Endecken Wortschatz von wohok

1 Jan 07, 2022
A Python wrapper for Matrix Synapse admin API

Synapse-admin-api-python A Python wrapper for Matrix Synapse admin API. Versioning This library now supports up to Synapse 1.45.0, any Admin API intro

Knugi 9 Sep 28, 2022
Awesome Casino is simple offline casino made on python.

Awesome-Casino Awesome Casino is simple offline casino made on python. I found bug, what can i do? If you find any bug or want to suggest any idea, al

Herman 1 Feb 04, 2022
Yet another basic python package.

ironmelts A basic python package. Easy to use. Minimum requirements. Installing Linux python3 -m pip install -U ironmelts macOS python3 -m pip install

IRONMELTS 1 Oct 26, 2021
Script to quickly get the metrics from Github repos to analyze.

commit-prefix-analysis Script to quickly get the metrics from Github repos to analyze. Setup Install the Github CLI. You'll know its working when runn

David Carpenter 1 Dec 17, 2022
Apache Airflow - A platform to programmatically author, schedule, and monitor workflows

Apache Airflow Apache Airflow (or simply Airflow) is a platform to programmatically author, schedule, and monitor workflows. When workflows are define

The Apache Software Foundation 28.6k Dec 28, 2022
Automated, progress quest-inspired procedural adventuring

Tales of an Endless Journey (TEJ) Automated, progress quest-inspired procedural adventuring What is this project? Journey is the result of many, many

8 Dec 14, 2021
It was created to conveniently respond to events such as donation, follow, and hosting using the Alert Box provided by twip to streamers

This library is not an official library of twip. It was created to conveniently respond to events such as donation, follow, and hosting using the Alert Box provided by twip to streamers.

junah201 8 Nov 19, 2022
Gives you more advanced math in python.

AdvancedPythonMath Gives you more advanced math in python. Functions .simplex(args: {number}) .circ(args: {raidus}) .pytha(args: {leg_a + leg_2}) .slo

Voidy Devleoper 1 Dec 25, 2021
🤞 Website-Survival-Detection

- 🤞 Website-Survival-Detection It can help you to detect the survival status of the website in batches and return the status code! - 📜 Instructions

B0kd1 4 Nov 14, 2022
firefox session recovery

firefox session recovery

Ahmad Sadraei 5 Nov 29, 2022
1cak - An Indonesian web that provide lot of fun.

An unofficial API of 1cak.com 1cak - An Indonesian web that provide lot of fun. Endpoint Lol - 10 Recent stored posts on database Example: https://on

Dicky Mulia Fiqri 5 Sep 27, 2022