Fructure: A structured interaction engine in Racket
Updated July 2019 : Installation instructions & mini-guide below
Fructure is a prototype structure editor, which can currently be used to write & edit small programs in a small subset of scheme/racket. This is a personal project where I'm playing with ideas in editing, programming languages, and interaction design.
Note: now that this is getting some traffic I wanted to put up a disclaimer that some of the code is currently in a bit of a state: I've commented out some things and hacked up some others to smoothen the demo. My immediate plans are - after taking a post-racketcon break and aside from general cleanup - to unhackify the way transforms currently work, properly re-instate variadic parameters for binding forms, and do some profiling and address the current sluggishness.
I wrote a bit about my then-current direction in September 2018, just before beginning my current implementation attempt. I've completed most of what I talk about there, with varying levels of success: Fructure 1 of 2 Fructure 2 of 2. There will soon be some slightly more up-to-date notes via my racketcon slides. For more updates cyberfollow @twitter and @elsewhere. Here's an ongoing dev screenshot dump; check out the chronological overview:
Basically, you need to install racket, a couple libraries, and a font if you don't want thing to look screwy.
- brew cask install racket
- brew tap caskroom/fonts && brew cask install font-iosevka
- raco pkg install memoize
- raco pkg install rackjure
- git clone https://github.com/disconcision/fructure.git
Linux, Windows: (under construction)
- cd fructure
- racket src/fructure.rkt
FAQ: Q: Is it suppose to be this slow? A: It's open source.
STEP 0: What to do if you're stuck / Speedrun instructions
- How to win: There are modes, but pressing ESC enough times should always get you to the base mode. From there, press SPACE to enter command mode. From here, PRESS "q" then RIGHT-ARROW to quit.
- Check the terminal for silent crashes (aka 'bonus' victory conditions)
STEP 1: mini tutorial
Fructure starts in NAV(igation) mode. The selector (red) encloses a hole (yellow).
ENTERtoggles TRANSFORM mode
A transform (red) maps the source (the hole) to (->) the target (selection (outlined in red) in menu (also outlined in red))
DOWNmove menu / selector: find and select an "if" expression)
ENTERperforms selected transform, toggles NAV mode: transform the hole to the if
NAV keybindings (continued)
LEFT/RIGHTmove selector in preorder tree traversal: go right thrice and left twice to cycle the selection, settling on the first child
These keys (almost) suffice to build/delete arbitrary syntax, though not terribly conveniently. Build a tiny program this way. I say almost because you can't (yet, owing to a bug) input new identifiers in this way. Doing so (currently) requires being in the menu and pressing RIGHT on a lambda or define (see next step).
Approximating standard text-entry
UP/DOWNselector to parent/first child
ESCswitch to NAV mode without performing transformation
RIGHTstep into current transform: (essentially) perform selected transform, and then advance the selector/menu to the first created hole. (unless last action was an undo, in which case RIGHT is a redo)
LEFTundo (back to state at last step, delimited by entering transform mode)
SPACEin current implementation the same as RIGHT, minus the redo part. eventually, it should be part of alphanumerics
)filter menu by search buffer prefix match
BACKSPACEerase most recent character in search buffer
DELETEerase search buffer
RIGHTun/fold transform display
DOWNextend/contract displayed menu options
Simple settings scrubber
SPACEswitch to COMMAND mode
SHIFT-SPACEswitch to COMMAND mode
- alphanumerics/BACKSPACE/DELETE : filter/unfilter property
ESCreturn to NAV or TRANSFORM mode
BOITE DIABOLIQUE: housing the 19 forbidden keybindings
EXPERIMENTAL & FICTIONAL keybindings: lies at best, trouble at worst
F2dump current structure to stdin
F12save structure to disk
F12load structure from disk
RIGHTselector to sibling
DOWNstep into capture
alphanumerics(restrict selector traversal to search buffer hits aka find as you type) TRANSFORM
F2dump current structure to stdin
RCTRLshortcut to select/insert parens