Code Monkey home page Code Monkey logo

tui.el's Introduction

tui.el

https://img.shields.io/badge/license-GPL_3-green.svg https://api.travis-ci.org/ebpa/tui.el.svg?branch=master

Requires emacs version 26.1 or higher

Introduction

This is an experiment in building purely text-based user interfaces (TUI’s). The ultimate goal is to explore new paradigms for user interface design and development using Emacs. To this end, tui.el implements an API based on the popular React JavaScript framework in order to reduce the demands involved with designing and building complex text-based UI’s.

This is all currently experimental! Expect things to change as I get feedback about what works, what does not!

Installing

Using Straight.el

(straight-use-package
 '(tui :type git :host github :repo "ebpa/tui.el" :files ("*.el" "components" "layout" "demo" "snippets")))

Manually

The package hasn’t been submitted to Melpa yet. To install the package manually: clone the repository, add the folder to your load path and install the dependencies with the following:

git clone [email protected]:ebpa/tui.el.git
(add-to-list 'load-path "~/path/to/tui.el")

(require 'package)
(add-to-list 'package-archives
             '("melpa" . "http://melpa.org/packages/") t)

(package-initialize)
(package-refresh-contents)

;; Manually install package dependencies
(package-install 'dash)
(package-install 's)

Getting started

Tic Tac Toe

Tui contains a tic tac toe game as a demonstration component. You can play the game with `M-x tui-play-tic-tac-toe`. Check out the source code with `M-x find-function “tui-play-tic-tac-toe”`.

Rendering content

If all goes well you should be able to require the library and render something to the buffer. The following will render a greeting at the point.

(tui-render-element "Hello world!")

Defining a component

Tui components are defined using `tui-define-component`.

Overview

Some familiarity with React should prove extremely helpful in using tui.el. I recommend checking out the introductory material on the React website. In particular- be sure to read the short primer on Thinking in React and the component lifecycle model (diagram).

Syntax

Tui offers an terse syntax for expressing content that roughly resembles the form of JSX. For instance, an expander control consists of a header and some content that is hidden when collapsed by the user:
(tui-expander
  :heading "A label for the following collapsible lorem ipsum content"
  "Curabitur lacinia pulvinar nibh. "
  "Fusce suscipit, wisi nec facilisis facilisis, est dui fermentum leo, quis tempor ligula erat quis odio. "
  "Sed id ligula quis est convallis tempor. ")

Inititial arguments as parsed key-value pairs and are passed as a plist to an element. A non-keyword-symbol following the property list and all following elements are treated as child elements. They are implicitly passed with the preceding plist properties as a value for :children. This avoids unnecessary repetition in typing :children.

(COMPONENT-NAME
  [[KEYWORD-PROP VALUE] ...]
  [CHILD-1 CHILD-2 ...])

The verbose equivalent to this syntax explicitly expresses the :children property. Note that multiple items must be enclosed by a single list or other element to follow the paired plist structure. The resulting content tree is identical to the previous example.

(tui-expander
  :heading "A label for the following collapsible lorem ipsum content"
  :children
  (list
    "Curabitur lacinia pulvinar nibh. "
    "Fusce suscipit, wisi nec facilisis facilisis, est dui fermentum leo, quis tempor ligula erat quis odio. "
    "Sed id ligula quis est convallis tempor. "))

Lists (and nil)

For convenience, lists may be used to arbitrarily group content. All lists are converted to tui-element nodes when the content is mounted. Null values may also be used arbitrarily. They are ignored at render time, so conditional code may return nil. Content is inserted in-order without separation, so while (list "foo" "bar" "baz") and (list (list "foo") nil (list "bar" "baz")) result in different content trees, they both render ~”foobarbaz”~.

The various forms of improper lists are currently not supported and are reserved for future use.

Text properties

To simplify styling, text properties may be applied to elements using the keyword :text-props. This property value should be a plist of text properties and their values. For example:
(tui-heading
  :text-props '(help-echo "Yup! This is a heading")
  "A heading!")

Comparison with React

ReactJS equivalents

ReactJStui.el
React.Componenttui-component
React.PureComponentTODO
createElement()tui-create-element
createFactory()tui-define-component
cloneElement()TODO
isValidElement()tui-valid-element-p
React.Childrenunnecessary (use tui-child-nodes)

Components

HTML-like components

(tui-div &key children)
(tui-heading &key children)
(tui-section &key children)
(tui-span &key children)

Other components

(tui-link &key target children)
(tui-icon &key icon-set icon-name)
(tui-buffer &key buffer children)
(tui-line &key children)
(tui-fixed-width &key children)
(tui-expander &key header initially-expanded children)

Future Work

Things I’m currently working on:

  • [ ] Grid layout
  • [ ] TUI Developer tools

Contributing

If you feel inspired by this little library, contact me on Twitter and let me know! The door is wide open for collaboration! If you have ideas for components I’d love to hear them.

Ideas

Here are a few things I have in mind in case you’re looking for an excuse to explore Emacs’ many features:

org-agenda

There are a lot of opportunities for customizing the org-mode agenda view that could be made possible with components designed for org-mode. Org-super-agenda offers striking examples of grouping agenda content into meaningful elements.

Structure editors

Structure editors are an exciting approach for editing source code and structured data. Build a set of components for representing and interacting with a syntax conceivably eliminates syntax errors altogether!

Charts and graphs

It would be very handy to have a variety of charts and graphs to visualize data within Emacs itself. Emacs already has a good start with the built-in chart.el for bar charts (examples). This would be a good application for drawille.el. Fancy animated charts like blessed-contrib anyone?

Virtual windows

There are circumstances where it would be useful to create divisions within a buffer/window without the behavior associated with additional windows. Imagine various tiled/floating window behavior demonstrated by blessed within a single buffer.

Touch-based interfaces

Why not give Emacs some big blocky buttons and sliders, so we can use our pervasive touchscreens with Emacs too? Or even: design progressive Emacs apps?

Running Tests

cask exec buttercup -L

Feedback

Requesting components

Suggestions

Button
Calendar
Dropdown
GitHub-style punchcard
Graphs/charts
Sparkline
Week

Related Projects

tui.el's People

Contributors

ebpa avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tui.el's Issues

Request for Assistance with tui.el Component Not Redrawing Despite State Change.

Hi ebpa,

Thank you for creating the tui.el library. I have a question about its usage:

I expect to force update the component with a timer, then reassign the time-string value, and have the interface automatically redrawn, but it did not automatically re-render. Here is an example code:

(tui-defun-2 time-test (&state (time-string (current-time-string))
                           (timer (tui-run-with-timer
                                   component 1 1 t
                                   (lambda ()
                                     (tui-force-update component)))))
  "A basic timer test"
  (tui-span
   (format "\ntime: %s" time-string)))

(setq time-test-comp (time-test))
(tui-render-element time-test-comp)

I have tried to solve this issue on my own, but have been unsuccessful so far. Can you please provide some guidance or suggest a solution?

Thank you for your time and help.

Magit?

Hi there,

Just a wild, crazy, huge, vague thought: what if Magit could be implemented with this package? Or to put it another way, what if this package implemented the same kind of components that Magit has? That would be pretty cool. :)

Screenshots?

A picture is worth a thousand words, and screenshots are certainly the first thing I look for when I am looking at a UI package. If you like I can load up your demos and make a PR?

`(require 'tui)` fails

Hi, I saw your EmacsConf talk on tui.el and thought I'd give it a whirl, as I'm trying to build more interactive tooling on Emacs.

Based on the README, I eval'd this code:

(straight-use-package
 '(tui :type git :host github :repo "ebpa/tui.el" :files ("*.el" "components" "layout" "demo" "snippets")))

(require 'tui)

The require fails with an error:

Debugger entered--Lisp error: (void-variable tui-element-outline)
  byte-code("\302\10\301 \303\304\11!$\207" [tui-element-outline element tui-defun "Structure outline of ELEMENT and its children." tui-element-outline-string] 6)
  require(tui-dev)
  load-with-code-conversion("/home/ieure/.emacs.d/straight/build/tui/tui.el" "/home/ieure/.emacs.d/straight/build/tui/tui.el" nil t)
  require(tui)
  pp-eval-expression((require 'tui))
  pp-eval-last-sexp(nil)
  funcall-interactively(pp-eval-last-sexp nil)
  command-execute(pp-eval-last-sexp)

I assume this isn't expected behavior. Is the README current?

Is reconciling really make sense?

Hi ebpa! I' m interesting on your project because I' m looking for a framework to create extensible UI program.

I am wondering dom node reconciling doesn't worth its overhead while rendering. I have to claim that I'm not a regular frontend developer, but I investigate some famouse frontend UI framework like React, Preact, Vue, etc.

These framework do the Vdom reconciling because directly rewrite real DOM is expensive. Vdom diff can help reduce operation on real DOM.

However, we present our UI in Emacs buffer. operating Emacs buffer is lightweight because buffer data structure is tightly integrated with Elisp VM(unlike DOM object, which is far away from JS engine). We just need one call to "insert" and "delete-region" to update the buffer no matter how large the content is. What's worse, reconciling algorithm must implemented in Elisp, which is more complicated and slower than a native function call.

My guess is: Reconciling is over-complicated, We just delete original content and insert new one. It must be admitted that my argument lacks performance test data, so I'd like to dicuss this with you. Do you have any ideas on this? Thanks a lot!

Tic Tac Toe not required by any file

Hi Erik,

I have installed the package with Spacemacs integrated Quelpa, which may be culprit. I have loaded the package with use-package.
(tui :location
     (recipe :fetcher github
             :repo "ebpa/tui.el"
             :files ("*.el"
                     "components"
                     "layout"
                     "demo"
                     "snippets")))

I can't find Tic Tac Toe with find-function or with describe-function. I verified that the file was downloaded and installed, even compiled (I do see tui-tic-tac-toe.elc)...

...I looked through tui.el and demo/tui-demo.el, neither of which (require 'tui-tic-tac-toe)...

...some further searching with Helm dir smart search revealed that only tui-demos.el requires Tic Tac Toe, itself not required by tui.el or demo/tui-demo.el.

It looks like you just need to pop that require line from tui-demos.el to demo/tui-demo.el and that should fix the issue.

Otherwise Tic Tac Toe is unavailable in 0.4.0 0.0.4 (semv-ver would say the prior, btw).

Random button dashboard

(tui-define-component tui-random
  :get-initial-state
  (lambda ()
    `(:current-number ,(random 100)))
  :render
  (lambda ()
    (tui-let (&state current-number)
      (tui-div
       (tui-line
        "Random number: "
        current-number)
       (tui-link
        :target
        (lambda ()
          (tui--set-state
           component
           `(:current-number ,(number-to-string (random 100)))))
        "Regenerate")))))

Suggestion for comparison between TUI and The Widget Library

I was able to get TUI to render a timer in IELM, which is impressive enough for me.

I think it would be a good idea to compare this library and its goals with the built-in Widget Library, as there are differences that would be interesting to see when someone is looking for a TUI-like library, or a component library for making interfaces and forms of some sort... application programming within Emacs in general, I suppose.

At the moment, I'm using the Widget Library, but I'm having difficulty with some of its documentation and some of its behaviour, but otherwise I think it meets my needs more appropriately than TUI. I may be wrong, however!

If TUI provides buttons, editable fields, lists, most of what Widget provides, then I might try implementing my setup-buffer in TUI instead.

What do you think, Erik? I think it'd be good for the README section where you mention other similar projects, Emacs and non-Emacs.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.