Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

[Experimental] Twee-like syntax for Twine 2 output (Twine 2 stories in your favourite text editor)

I've been experimentally making a compiler than converts source files in a "Twee-like" syntax to Twine 2 output files. Let me explain what that means (with apologies to anybody who knows all of this already: just scroll down to the 'Twee2' section).

Twine 1 & Twee

There's an alternate way of making Twine 1 stories: instead of using the visual tool where you drag and drop passages around, you could write "Twee" files in your favourite text editor, which looked a bit like this:
A Wonderful Adventure

You begin your wonderful adventure. But who will you go with?

* [[My friend Jill|Jill]], who's resourceful and smart.
* [[My buddy Jack|Jack]], who's brave and strong.

You decide that Jill would be a great travelling companion...

You take your friend Jack by the hand and begin your adventure...

Using a text editor rather than the visual tool provided several benefits. It made it easier for multiple people to work concurrently on the same story (because you could easily "cut up" the files, or use source control to automatically synchronise changes), for example. It made it possible to use smart "search/replace" tools, among others, to manage your text. And, of course, you could edit your story anywhere that you could type, even where the editor won't work (even on your phone!).

Twine 2

Twine 2 made huge improvements to the output produced. The new story formats are so much better than the TiddlyWiki-powered stories that came out of Twine 1. But, of course, there's no equivalent to "Twee" for Twine 2, so all of those potential benefits listed above are lost. And personally, it bugs me that I can't choose where to save each story I work on (I want to be carrying them around on my pendrive, and it's a pain to have to keep remembering to copy them every time I finish working).

It's not that I don't love Twine. It's just not the best way for me to work.


So: I wrote some experimental code that brings Twee-like features to Twine 2. Here it is. It's probably not for everyone, yet, but here's the basics: you'll need Ruby installed, after which you can install Twee2 by typing:
gem install twee2

Then, you can write Twee-style story files and compile them with:
twee2 build mystory.twee myoutput.html

(try the ultra-basic story skeleton above if you like - save it as "mystory.twee" and give it a go)

It's also possible to make Twee2 automatically build your story into a web page every time you change the source file: just substitute "build" with "watch".

Twee2 supports any Twine 2 story format, but uses a text-based syntax similar to Twee. But that's when I started thinking: perhaps it can do more than this. I've started adding some experimental extra-functionality to it (HAML and Coffeescript support, so far), but what I'd really like to add next is the capability to 'include' story file fragments within one another, which would facilitate collaborative working, organisation, and potentially even pluggable 'modules' that add specific functionality (via Javascript/Coffeescript) to stories.

I've been playing with this for a while, but I thought it was time I shared it with you, the community, in case anybody has any thoughts or ideas about this project or how it would (or wouldn't) be useful to them. Let me know what you think.

There's also a bit of a discussion going on about it over on Reddit, if you're interested.


  • edited August 2015
    Error in openSUSE 13.2:
    /usr/lib64/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- bundler/setup (LoadError)
    	from /usr/lib64/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    	from /usr/lib64/ruby/gems/2.1.0/gems/twee2-0.2.0/lib/twee2.rb:8:in `<top (required)>'
    	from /usr/lib64/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    	from /usr/lib64/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    	from /usr/lib64/ruby/gems/2.1.0/gems/twee2-0.2.0/bin/twee2:3:in `<top (required)>'
    	from /usr/bin/twee2.ruby2.1:23:in `load'
    	from /usr/bin/twee2.ruby2.1:23:in `<main>'

    Any idea about the cause? I've never done anything at all wih Ruby. I intend to write a Twine for Ludum Dare and this would be a great help.

    This is a great idea that I'd like to see developed, and even merged into Twine proper (as an official text-based format or whatever). Specially, I would like the ability to create one Twine output from several source files.

  • Thanks for the feedback, Menti. That's entirely my fault: I forgot to include a dependency list in the packaged version of Twee2, so you'll have been missing some key bits of code. I've fixed this in v0.2.2, so if you run:
    gem install twee2

    again it should update and fix the problem.

    If that doesn't do it (please let me know!), the following should:
    gem install bundler thor builder filewatcher haml coffee-script
    Specially, I would like the ability to create one Twine output from several source files.

    Me too! That's the very next feature I plan to add to Twee2.
  • is there any way we can include other story formats?
    a quick
    twee2 formats
    I understand the following output formats:
     * Harlowe
     * Paperthin
     * Snowman
     * SugarCube

    so in case this is Sugarcube1, is it possible to add Sugarcube2 myself?

    Not too proficient in Ruby so not sure if I'd have to rebuild twee2 with SC2 in the folder or if there's any place on my mac where I could just add the format files :-)

  • edited August 2015
    No reason why not, GroZaV, and you shouldn't have to rebuild Twee2. The challenge is working out the right place to put the files! If you type in:
    gem environment

    And look at the GEM PATHS section, you'll find a list of candidate folders. Inside one of those folders you'll find a "gems" folder in which you'll find a "twee2-0.3.0" (or whatever version you're using) folder, in which you'll find a "storyFormats" folder. That's where the story formats go! I've never tried Sugarcube2, but it might well work!

    I'll add an option in a future to allow story formats to be included from anywhere.
  • I'd add to the instructions that you need to have a Ruby development environment (ruby-devel for me in openSUSE) and a Javascript runtime (I installed nodejs).

    After a bit of googling that took me to those two prerequisites, I finally could test it and it worked perfectly, generating a playable html that I then imported into Twine. All was perfect as far as I could see.


  • Dan_Q wrote: »
    Specially, I would like the ability to create one Twine output from several source files.

    Me too! That's the very next feature I plan to add to Twee2.
    You may want to look at the old StoryIncludes special passage functionality in Twee 1, it supported the inclusion of child twee/txt files.
  • greyelf wrote: »
    inclusion of child twee/txt files.

    It is now implemented, though experimental (as per the github page).

    However I stumbled upon a bug that may be linked either to Sugarcube (found this thread referencing it already) or my poor understanding of how twee2 handles CSS and JS.

    I have the StoryIncludes passage in my main Twee file as such

    and the file is as such (I put in random values for testing):
    :: Monster Style [stylesheet]
    body {
        background-color: blue;
    #ui-bar {

    However the command line reports that the StoryIncludes passage is ignored.
    Compiling Repositories/twine-stories/LD33/ld33.html
    WARNING: ignoring passage 'StoryIncludes'

    I know you said it shouldn't be used in production but I really like typing my story straight from my text editor and not having to use the GUI :-)
  • GroZaV wrote: »
    However I stumbled upon a bug that may be linked either to Sugarcube (found this thread referencing it already) or my poor understanding of how twee2 handles CSS and JS.
    1. Neither the linked issue nor this one have anything to do with SugarCube. Story formats should never even see the StoryIncludes passage, it has meaning only to the compiler.

    2. Either you're not using the latest version or a version reflecting that change hasn't been released, because the warning message you received is from an older version where StoryIncludes was being ignored.
  • As pointed out by TheMadExile some of the special passages should not be included in the passage data you insert into the story format header.

    If you look at the Twine 1 rebuild() function code you will see that both StoryIncludes and any passage marked with a tag within the TiddlyWiki.NOINCLUDE_TAGS list are excluded.
  • Just wanted to thank you again. I wrote most of my Ludum Dare entry, Truth be untold, on your Twee2 tool. It may be more usable than Twine proper for certain users in certain cases. If I may insist, I think this could be considered for inclusion in Twine as native functionality.
  • As others have noted: yes, "includes" work, but only in the latest versions of the gem (I've been pushing out new versions thick and fast and it's really starting to get close to a stable state now). Run "gem install twee2" to upgrade to the latest version, if you need to. It also now supports decompilation of compiled Twine 2 HTML output back into Twee2 (Twee-like) format (but not on Windows) and will later today support non-bundled story formats (so you can easily use any story format you like).

    After that, I'd like to expand the ability to change the options including the story format from within settings in the story file itself (so that compilation is more understandable), improve CSS and JS handling (so it's easily possible to separate out your central CSS/JS into separate files, if you like, using "includes"), and then I'm going to start on some documentation. That'll probably put me at about version 0.5, which sounds like as good a point as any to call it "beta"-ready and let the world start playing with it in earnest.

    Thanks for your feedback, all!
Sign In or Register to comment.