Package

purescript-blessed

Repository
shamansir/purescript-blessed
License
MIT
Uploaded by
pacchettibotti
Published on
2025-07-10T18:05:55Z

What is Blessed

This is the draft implementation of Blessed Node.JS library in PureScript. The library provides you as a developer with windows-driven GUI (including basic components) to the terminal applications.

There are windows a.k.a. boxes with support of dragging, lists of items, a file manager, buttons, and many more, see for yourself.

What is moved

  • All the components from the basic repository;
  • Most of the options, properties and methods;
  • Most of the events;
  • Most of the component styles;
  • Tagging the text;

Not yet translated/implemented:

  • The subjects of the events handlers, so it would be easy for you to subscribe to the event of the component and get the corresponding object decoded from JSON;
  • A lot of things...

Installation

It is crucial to install with npm install or npm install -g beforehand and ensure to have the latest version of node.js, or just the best one of the latest versions.

It requires only two libraries:

  • npm install @shamansir/everblessed (almost identical to git@github.com:kenan238/reblessed.git, with few changes to make it work on NixOS)
  • npm install terminal-size (from git@github.com:sindresorhus/terminal-size.git)

The library is not distributed (yet?) so there's no spago install, sorry. But you may add it to packages.dhall using custom git link, just name it blessed or something.

To test it: run spago run, or spago run -m Blessed.Demo. It is the PureScript version of the demo in the README.md of chjj/blessed repository.

Quick intro to the API

The key in this PureScript implementation is the Key... and Subject :). Subject. NodeKey.

There are type-level values for every kind of component in blessed, called Subject, and this way the library verifies if you specify the property that really belongs to this component (or its parent) or call a method that really belongs to this component and so on.

Every component instance should have an unique Key. Using this key you may call any method of this particular instance, that belongs to the components of this Subject. You may either define all of them in some separate module (e.g. MyApp.Keys) or create them on the fly or define them in the modules of your components. On the type-level, Key contains a Subject and some Symbol (type-level String) that identifies your family of components. On the value-level, there is a hash UUID inside so that you would be able to create many unique keys from the same family if you need. That's what NodeKey.next is for. If you don't have the requirement to spawn several instances of the same component in your application, then it's very probable that you won't need it.

There is a free monad BlessedOp in which you may perform any effects, access and modify the global state (there are no per-component states for the moment, at least it could require some tricks), since it implements State monad, and call methods of your components using keys. BlessedOp.

This monad is where your initial code is performed as well as the code for every handler.

Components are defined this way:

Blessed.box <yourKey>
	[ Box.<someOption> <someValue>
	, Box.<someOption> <someValue>
	, Box.mouse true -- for example
	, Box.tags true -- for example
	, Element.<someOption> <someValue> -- since Element is parent for box
	, Blessed.on Event.Click $ do
		 <yourKey> >~ Box.<someMethod> <arg1> <arg2>
		 val <- <yourKey> >~ Box.<someProperty> -- get value of the property
		 top <- <yourKey> >~ Box.top -- for example
		 state <- State.get
		 State.modify (\state -> <some code>)
	     ...
	     pure unit
	]

Where Blessed.box could be Blessed.list or Blessed.fileManager etc.

Or, this way:

Blessed.boxAnd <yourKey>
	[ Box.<someOption> <someValue>
	, Box.<someOption> <someValue>
	, Box.mouse true -- for example
	, Box.tags true -- for example
	, Element.<someOption> <someValue> -- since Element is parent for box
	, Blessed.on Event.Click $ do
		 <yourKey> >~ Box.<someMethod> <arg1> <arg2>
		 val <- <yourKey> >~ Box.<someProperty> -- get value of the property
		 top <- <yourKey> >~ Box.top -- for example
		 state <- State.get
		 State.modify (\state -> <some code>)
	     ...
	     pure unit
	]
	$ do
		 <initial code below>
		 <yourKey> >~ Box.<someMethod> <arg1> <arg2>
		 val <- <yourKey> >~ Box.<someProperty> -- get value of the property
		 top <- <yourKey> >~ Box.top -- for example
		 state <- State.get
		 State.modify (\state -> <some code>)
	     ...
	     pure unit

Where Blessed.boxAnd could be Blessed.listAnd or Blessed.fileManagerAnd etc.

>~ is actually just the # operator in disguise. Just to distinguish the parts that work with blessed component from other function calls.

All the components are of type Blessed m where m is usually just the Effect monad, or it can be something else that has instance of MonadEffect. Blessed definition.

BlessedOp state m is the free monad for handlers and initialisation code, where m should be the same as above, and state is the global state of your components.

To run the application, use Blessed.run <initialState> <rootComponent> or Blessed.runAnd <initialState> <rootComponent> $ do .....

Examples

There is a demo in the repository src/Blessed/Demo.purs which mirrors the original example from Blessed and can give you the impression on how the API translates to PureScript.

To run it, just call spago run and that should be it. But spago can spawn the process in the terminal differently to the simple node execution, so if you see the black screen (which is actually 1x1 window), try creating the bundle and then run it:

spago bundle --bundle-type app --platform node --outfile index.js
node index.js

Also try:

spago run --quiet --censor-stats

You may see many examples of its usage in the Noodle/Cli application, and currently this repo is just the extract from there. Noodle CLI components.

To tag your text so that it is coloured you may use Blessed.Tagger, here's an example.

As the example shows, it is possible to use these bindings and they do really work in most of the cases. Still, this library is made for a specific project to satisfy its specific needs and lacks a lot of features of node.js-version of blessed. That's why I have no intention to publish it to Pursuit yet, at least until the events system is moved and all of the methods are implemented for basic components, and more documentation to be in the code.`

Modules
Blessed
Blessed.Core.Align
Blessed.Core.Border
Blessed.Core.Callback
Blessed.Core.Color
Blessed.Core.Coord
Blessed.Core.Cursor
Blessed.Core.Dimension
Blessed.Core.EndStyle
Blessed.Core.Flex
Blessed.Core.Helpers
Blessed.Core.Key
Blessed.Core.Label
Blessed.Core.ListStyle
Blessed.Core.Offset
Blessed.Core.Orientation
Blessed.Core.Padding
Blessed.Core.Style
Blessed.Core.Terminal
Blessed.Demo
Blessed.Internal.ArgonautCodecExtra
Blessed.Internal.BlessedOp
Blessed.Internal.BlessedSubj
Blessed.Internal.Codec
Blessed.Internal.Command
Blessed.Internal.Core
Blessed.Internal.Dump
Blessed.Internal.Emitter
Blessed.Internal.Foreign
Blessed.Internal.JsApi
Blessed.Internal.NodeKey
Blessed.UI.Base.Element.Event
Blessed.UI.Base.Element.Method
Blessed.UI.Base.Element.Method.Content
Blessed.UI.Base.Element.Option
Blessed.UI.Base.Element.Property
Blessed.UI.Base.Element.PropertySet
Blessed.UI.Base.Node.Event
Blessed.UI.Base.Node.Method
Blessed.UI.Base.Node.Option
Blessed.UI.Base.Node.Property
Blessed.UI.Base.Screen
Blessed.UI.Base.Screen.Event
Blessed.UI.Base.Screen.Method
Blessed.UI.Base.Screen.Option
Blessed.UI.Base.Screen.Property
Blessed.UI.Boxes.BigText.Option
Blessed.UI.Boxes.Box
Blessed.UI.Boxes.Box.Event
Blessed.UI.Boxes.Box.Method
Blessed.UI.Boxes.Box.Option
Blessed.UI.Boxes.Box.Property
Blessed.UI.Boxes.Line
Blessed.UI.Boxes.Line.Event
Blessed.UI.Boxes.Line.Option
Blessed.UI.Boxes.Text.Option
Blessed.UI.DataDisplay.Log
Blessed.UI.DataDisplay.Log.Event
Blessed.UI.DataDisplay.Log.Method
Blessed.UI.DataDisplay.Log.Option
Blessed.UI.DataDisplay.Log.Property
Blessed.UI.DataDisplay.ProgressBar.Event
Blessed.UI.DataDisplay.ProgressBar.Method
Blessed.UI.DataDisplay.ProgressBar.Option
Blessed.UI.DataDisplay.Table.Method
Blessed.UI.DataDisplay.Table.Option
Blessed.UI.Forms.Button
Blessed.UI.Forms.Button.Event
Blessed.UI.Forms.Button.Method
Blessed.UI.Forms.Button.Option
Blessed.UI.Forms.Checkbox
Blessed.UI.Forms.Checkbox.Event
Blessed.UI.Forms.Checkbox.Method
Blessed.UI.Forms.Checkbox.Option
Blessed.UI.Forms.Checkbox.Property
Blessed.UI.Forms.Form.Event
Blessed.UI.Forms.Form.Method
Blessed.UI.Forms.Form.Option
Blessed.UI.Forms.Form.Property
Blessed.UI.Forms.TextArea
Blessed.UI.Forms.TextArea.Event
Blessed.UI.Forms.TextArea.Method
Blessed.UI.Forms.TextArea.Option
Blessed.UI.Forms.TextArea.Property
Blessed.UI.Forms.TextBox
Blessed.UI.Forms.TextBox.Event
Blessed.UI.Forms.TextBox.Option
Blessed.UI.Forms.TextBox.Property
Blessed.UI.Lists.FileManager.Event
Blessed.UI.Lists.FileManager.Method
Blessed.UI.Lists.FileManager.Option
Blessed.UI.Lists.FileManager.Property
Blessed.UI.Lists.List
Blessed.UI.Lists.List.Event
Blessed.UI.Lists.List.Method
Blessed.UI.Lists.List.Option
Blessed.UI.Lists.List.Property
Blessed.UI.Lists.ListBar
Blessed.UI.Lists.ListBar.Event
Blessed.UI.Lists.ListBar.Method
Blessed.UI.Lists.ListBar.Option
Blessed.UI.Lists.ListTable.Method
Blessed.UI.Lists.ListTable.Option
Blessed.UI.Prompts.Loading.Method
Blessed.UI.Prompts.Message.Method
Blessed.UI.Prompts.Prompt.Method
Blessed.UI.Prompts.Question.Method
Blessed.UI.Special.Terminal.Option
Data.Unfoldable1.Extra
Dependencies