interp: Tracery-like randomized text interpolation

[ bsd3, interpolation, library, program, text ] [ Propose Tags ]

Please see the README on GitHub at https://github.com/swizzard/interp#readme


[Skip to Readme]
Versions [faq] 1.0.0.0, 1.0.0.1, 1.0.0.2
Dependencies aeson, base (>=4.7 && <5), bytestring, containers, hspec, interp, megaparsec, mtl, optparse-applicative, parser-combinators, random-fu, rvar, semigroups, text, transformers, unordered-containers, vector [details]
License BSD-3-Clause
Copyright (c) 2019 sam raker
Author sam raker
Maintainer sam.raker@gmail.com
Category Text, Interpolation
Home page https://github.com/swizzard/interp#readme
Bug tracker https://github.com/swizzard/interp/issues
Source repo head: git clone https://github.com/swizzard/interp
Uploaded by swizzard at Mon Feb 18 20:38:43 UTC 2019
Distributions NixOS:1.0.0.2
Executables interp
Downloads 398 total (54 in the last 30 days)
Rating (no votes yet) [estimated by rule of succession]
Your Rating
  • λ
  • λ
  • λ
Status Hackage Matrix CI
Docs available [build log]
Last success reported on 2019-02-18 [all 1 reports]

Modules

[Index] [Quick Jump]

Downloads

Maintainer's Corner

For package maintainers and hackage trustees


Readme for interp-1.0.0.2

[back to package description]

interp

A randomized text-interpolation tool inspired by Tracery, in Haskell.

Installation

Prerequisites

  • Haskell
  • Stack, unless you can work Cabal yourself

Clone this repo, cd into it, and then:

  • if you want to use the CLI, run stack install
  • if you want to use it as a library, just run stack build

Development

Fork this repo, make some changes, run stack test to make sure everything's ok, then (if you want) submit a PR. Thank you!

Use

CLI

Usage: interp (--substitutions ARG | SUBST) (--interpolations ARG | INTERP)
  Randomly interpolate values into a template

Available options:
  --substitutions ARG      JSON file containing map of substitutions
  SUBST                    JSON file containing map of substitutions
  --interpolations ARG     file containing text to interpolate
  INTERP                   file containing text to interpolate
  -h,--help                Show this help text

substitutions is the (path to the) file containing the JSON map of substitutions. interpolations is (path to the) file containing the text to interpolate. See below for more on both.

Library

Data.Text.Interp.Interpolate.interp is probably what you'll want to use. It takes a Subst object (usually parsed from JSON, but you can make one yourself) and a NonEmpty list of ITexts. Check out Data.Text.Interp.Types for more on those types.

Syntax

In both substitution and interpolation files, keys can be comprised of any letter or number, or the characters "_" or "-". Spaces and other punctuation are not allowed and will give you Problems.

Substitutions

{"coolThings": [
   {"name": "computers",
    "reason": "you can do haskell on them"
   },
   {"name": "dogs",
    "reason": "they're good"
   }
 ],
 "badThings": [
  {"name": "flat tires",
   "reason": "they make you late"
  },
  {"name": "jobs",
   "reason": "they make you tired"
  }
 ],
 "sam": {
   "likes": "computers"
}

The substitutions file is a JSON file. JSON maps are treated how one would expect. The values in a JSON array are chosen among randomly (but see also below on binding). Regular values are treated regularly, but note:

  • because of how JSON is parsed, all numeric literals are treated as floating-point, so a 1 will be interpolated as "1.0". If this is an issue, just wrap your numbers in quotes and they'll be treated as strings.
  • null values are explicitly forbidden; empty lists and maps should be avoided.

Interpolations

{{ ... }} sets off a thing to interpolate. Keys, corresponding to keys in the substitutions file, can be period-separated to 'dig into' nested maps. Thus, in the example above, sam.likes will be have the value "computers".

Binding

Within braces, values can be bound to variables using the syntax (varToBind#keys.to.bind).other.keys. When a variable is bound, references to that variable will be interpolated with that same value. Thus, given the interpolation template

{{ (cool#coolThings).name }} are cool because {{ cool.reason }}. {{ (bad#badThings).name }} are bad because {{ bad.reason }}.

cool in the first interpolation will be the same as cool in the second. Note that keys within the parentheses are part of the binding, while those after the closing parentheses are interpolated normally--{{ (cool#coolThings).name }} will be either "computers" or "dogs", while {{ cool.reason }} will be "you can do haskell on them" or "they're good", depending on which sub-map was randomly chosen to be bound to cool.

Binding is primarily useful for map values. It's possible to bind arrays, but since array elements are chosen randomly evey time, there's not much of a point. Similarly, there's no real difference between binding a simple value and just using the full path to it, unless you're trying to save characters.

Etc.

To-Do

  • [x] Haddock documentation/comments
  • [x] Add positional args in CLI
  • [ ] Other formats (e.g. YAML) for substitutions file
  • [ ] More features
    • [ ] Preprocessing (prepending "a(n)", title casing, etc.)
    • [ ] Other stuff??
      • [ ] Check Tracery documentation for stuff to steal
    • [ ] Web interface??
  • [ ] Come up with a better name
  • [x] Publish to Hackage

Contributing

PRs, issues, feature requests, etc. are always more than welcome! Feel free to hit me up on twitter or email me at sam dot raker at gmail dot com. Let me know if you like this, hate this, wish it were better, wish it were worse, whatever.