Coder Social home page Coder Social logo

reflex-frp / reflex-vty Goto Github PK

View Code? Open in Web Editor NEW
137.0 23.0 25.0 785 KB

Build terminal applications using functional reactive programming (FRP) with Reflex FRP.

Home Page: https://reflex-frp.org

License: BSD 3-Clause "New" or "Revised" License

Haskell 95.67% Nix 4.33%
terminal vty functional-reactive-programming frp reflex-frp haskell tui

reflex-vty's Introduction

reflex-vty's People

Contributors

3noch avatar ali-abrar avatar benkolera avatar cgibbard avatar elvecent avatar ericson2314 avatar fendor avatar matthewbauer avatar mightybyte avatar minimapletinytools avatar ners avatar thekk avatar tomsmalley avatar wheatwizard 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  avatar  avatar  avatar  avatar  avatar

reflex-vty's Issues

V.defAttr Behavior in VtyWidgetCtx

Problem

Currently, it's difficult to apply a styling to all widgets. Adhering to the widgets provided, it requires manually calling styled variants like text' (which don't exist for all widgets e.g. boxTitle) with a "default" V.attr Behavior that must be passed in throughout the program.

Proposed Solution

Create a new parameter _vtyWidgetCtx_defaultAttr in VtyWidgetCtxthat's used instead of V.defAttr across all built-in widgets.

Sample implementation #42

Issues

Notably, a little awkward if the user wants to specify a default "cursor" attribute or default "clicked" attribute (say). These could be hardwired into VtyWidgetCtx as with _vtyWidgetCtx_defaultAttr. Perhaps something like a V.Attr map would be appropriate? It kind of sucks to wrap VtyWidget in a Reader Monad for user defined attribute groups as well so it's nice to have some built-in.

Support a "fixed" size constraint that corresponds to the size of Image

Why

Current options make it so that rendering fixed size TUI images requires us to know the size they'll take up.

It seems to me that it's possible to compute this size by using imageHeight and imageWidth from vty.

I believe this is how brick does it.

Proposed solution:

Add Constraint_Fit and corresponding fit function.

Text cursor isn't visible when pointing to the end of a line

To reproduce:

  • Start the example app
  • Open the text editor or todo example
  • Click somewhere in the middle of a line
  • Observe that the text cursor is visible
  • Press the right arrow key until you are inserting text at the end of the line
  • Observe that no cursor is visible

How to use this package as a dependency?

I'm using Nix to manage dependencies and Cabal to build my packages inside a Nix shell. This package is marked as broken in nixpkgs (as reflex-related packages normally are) so I've tried to use a local copy cloned from this repository. However, I can't figure out which Nix expression exactly describes the package so I can put it in package overrides. I understand it is somehow generated with cabal2nix as described in release.nix?

This is what I've tried:

config = {
    packageOverrides  = p: rec {
      haskellPackages = p.haskellPackages.override {
        overrides = self: super: rec {
          reflex-vty = import ../reflex-vty/release.nix {};
        };
      };
    };
  };

This normally works with other packages, but reflex-vty isn't found inside the shell.

Why is there no horizontal version of `splitV`?

I cannot find a version of splitV that splits horizontally. Why is there none? You can achieve the same functionality with layouts, but if seems if that were a reason splitV would be deprecated.

tick with variable rate

Hi,

I am using reflex-platform and reflex-vty checked out at 3863af6.

My apologies in advance if this is the wrong place to ask this.

I have been trying to figure how to vary the rate of a tick in my experimental reflex-vty app. After much digging I found reflex-dom's tickWithSpeedSelector example, which seems to perfectly fit the bill. Unfortunately, the implementation of tickWithSpeedSelector is dependent on dyn/widgetHold, which I can't seem to find any equivalent for in reflex-vty.

Applying tickLossyFromPostBuildTime gets us (Event t NominalDiffTime) -> (Event t (m (Event t TickInfo))), and switchHold never would let us (Event t (Event t TickInfo)) -> m (Event t TickInfo), but without widgetHold I can't figure out how to plumb these together.

I also think that the general behaviour of widgetHold is very useful, and think it would be neat to see a more generic (Event t (m a)) -> m (Event t a) implementation if such a thing is possible.

I had a look at how I might go about implementing this myself, but I think I am truly in over my head (I am very new to reflex).

In case it is interesting or useful, I found a vaguely similar problem here.

In summary, I am looking for a way to have a tick at a variable rate that can be updated by another event. This is currently possible in reflex-dom thanks to widgetHold, but I am at a loss for how to do it without reflex-dom.

Feature Request: Password Text Field

I'm coming from the brick world where one can modify an text input to display the entered text as all "****"s for entering passwords.

I would like to do the same thing with textInput but I can't figure how. Hopefully there is a way and I just missed it, but I think I would need to be able to alter how the displayLines operates.

brick implements it's text editor with a generic function that allows one to pass in a [T.Text] -> Widget n to control the rendering of the text. I suppose reflex-vty do something similar (although with different types)

I don't have a strong opinion on whether this is a good approach or not. I mostly want to be able to type passwords with '*' somehow.

Thanks for making this by the way. I'm enjoying creating my simple form thus far.

`Missing (or bad) C libraries: icuuc, icui18n, icudata` when running cabal

Running both cabal v2-build and cabal build gives the following error:

~/kitchen/faucet/reflex-vty:mychanges2$ cabal v2-build
Warning: The package list for 'hackage.haskell.org' is 46 days old.
Run 'cabal update' to get the latest list of available packages.
Resolving dependencies...
Build profile: -w ghc-8.6.5 -O1
In order, the following will be built (use -v for more details):
 - ansi-terminal-0.10.3 (lib) (requires build)
 - text-icu-0.7.0.1 (lib) (requires build)
 - vty-5.28.2 (lib) (requires build)
 - reflex-vty-0.1.4.0 (lib) (first run)
 - reflex-vty-0.1.4.0 (exe:example) (first run)
Starting     ansi-terminal-0.10.3 (lib)
Starting     text-icu-0.7.0.1 (lib)
Building     ansi-terminal-0.10.3 (lib)
Installing   ansi-terminal-0.10.3 (lib)
Completed    ansi-terminal-0.10.3 (lib)

Failed to build text-icu-0.7.0.1. The failure occurred during the configure
step.
Build log ( /Users/user/.cabal/logs/ghc-8.6.5/txt-c-0.7.0.1-b2a9d4f5.log ):
Configuring library for text-icu-0.7.0.1..
cabal: Missing dependencies on foreign libraries:
* Missing (or bad) C libraries: icuuc, icui18n, icudata
This problem can usually be solved by installing the system packages that
provide these libraries (you may need the "-dev" versions). If the libraries
are already installed but in a non-standard location then you can use the
flags --extra-include-dirs= and --extra-lib-dirs= to specify where they are.If
the library files do exist, it may contain errors that are caught by the C
compiler at the preprocessing stage. In this case you can re-run configure
with the verbosity flag -v3 to see the error messages.

cabal: Failed to build text-icu-0.7.0.1 (which is required by exe:example from
reflex-vty-0.1.4.0). See the build log above for details.

I've followed some of the suggestions here but was not able to get it to work agda/agda#3017

I was however able to get it working after switching everything to stack by adding the following to my stack.yaml

extra-include-dirs:
- /usr/local/opt/icu4c/include
extra-lib-dirs:
- /usr/local/opt/icu4c/lib

I would however like to use cabal only for my projects (some of which are open source reflex-vty modules) to be consistent with reflex's current tooling.

Installation trouble

Following the readme instructions, I get (when running nix-shell):

error: attribute 'stdenv' missing

       at /nix/store/bblbjmnzbzfib5q0r7xbk1c920bsabbw-source/pkgs/build-support/cc-wrapper/default.nix:62:8:

           61|   expand-response-params =
           62|     if buildPackages.stdenv.hasCC && buildPackages.stdenv.cc != "/dev/null"
             |        ^
           63|     then import ../expand-response-params { inherit (buildPackages) stdenv; }

If I try to install with stack, I get other errors.

Are these installation methods working for other people (i.e. is it a problem on my end) or is the repo out of date?

Thanks so much!

Focus event lossage with self-referential networkHold

Two exhibits from https://gist.github.com/deepfire-pusher/fe13848dc810ada606e79964b3549418

The problem, roughly: focus events are not delivered, when a networkHold expression's output Event is looped unto the network being switched to (but of course, without a true circular data dependency). The lack of focus change events is relieved, when this loop is broken.

First, setting:

  1. A small network consisting of two widgets, one of them affecting the other:

    • a menu-like list of button-like, focusable widgets, emitting individual events of the same type -- in response to Enter (when focused) or mouse clicks
    • a text input that defines a simple filter for the list
  2. Since the list content is subordinate to the text input's filter definition, the network configuration requires switching, so enters networkHold

  3. Since both elements -- the menu and the text are supposed to consume input at the same time, they both need to have focus -- so they need to reside in separate panes that both need to have focus, when their parent does.

This is seemingly is what https://gist.github.com/deepfire-pusher/fe13848dc810ada606e79964b3549418#file-exhibits-hs-L56-L61 should have provided.

However that exhibit (runnable by runhaskell exhibit.hs 2) ignores the Tab/Shift+Tab keypresses.

What works (in terms of focus changes), instead is https://gist.github.com/deepfire-pusher/fe13848dc810ada606e79964b3549418#file-exhibits-hs-L32-L42 (runnable by runhaskell exhibit.hs 1), which breaks the not-really-a-loop (?) in the definition, and simulates user input with externally supplied events.

So, I was wondering if I am misunderstanding things, or if this is really a bug.

bound of vty might cause compilation failure

Currently the bound on vty is vty >= 5.28 && < 5.37, which accepts 5.34 and above.

According to the code and changelog of vty, they removed the Monoid instance from Attr

Removed Monoid and Semigroup instances for Attr and MaybeDefault.

But reflex-vty is still assuming Monoid Attr somewhere, which makes compilation failed.

let bold = V.withStyle mempty V.bold

Perhaps we should make it vty >= 5.28 && < 5.34 ?

Layout does not support tab focus shifting on nested layouts

TLDR; see draft PR

Problem Outline

Tab navigation in the current Layout system does not work when Layouts are nested

For example:

col $ do
  -- row 1
  fixed 5 $ row $ do
    fixed 1 $ someWidget1
    fixed 1 $ someWidget2
    fixed 1 $ someWidget3
  -- row 2
  fixed 5 $ row $ do
    fixed 1 $ someWidget4
    fixed 1 $ someWidget5
    fixed 1 $ someWidget6

assume row1 + someWidget1 are in focus

The desired behavior is:

  • pressing "tab" will focus row1 and someWidget2
  • pressing "tab" will switch focus from someWidget<n> to someWidget<n+1 mod 6> and switch focus between row1 and row2 as necessary

However, instead we have:

  • pressing "tab" will focus row2 and someWidget2
  • in addition, pressing tab again will focus row1 and someWidget2

Challenges

Broadly speaking, Layout alternates between Layout and VtyWidget and we need to pass data across this boundary in order for tabbing to work as desired.

Using the existing Layout module as a starting point, there are 2 major challenges to support the desired behavior outlined above:

  1. runLayout needs to be aware of nested layout nodes in order to focus the correct tile
  2. tile needs to be aware of when a particular nested node index should be focus

Solution

  1. is addressed by introducing the new class below. NOTE, LayoutTree is discussed later.
class IsLayoutReturn t b a where
  getLayoutResult :: b -> a
  getLayoutNumChildren :: b -> Int
  getLayoutFocussedDyn :: b -> Dynamic t (Maybe Int)
  getLayoutTree :: b -> LayoutTree t

instance IsLayoutReturn t (LayouTree t, Dynamic t (Maybe Int), Int, a) a where
  getLayoutResult (_,_,_,a) = a
  getLayoutNumChildren (_,_,d,_) = d
  getLayoutFocussedDyn (_,d,_,_) = d
  getLayoutTree (tree,_,_,_) = tree

instance Reflex t => IsLayoutReturn t a a where
  getLayoutResult = id
  getLayoutNumChildren _ = 1
  getLayoutFocussedDyn _ = constDyn Nothing
  getLayoutTree _ = emptyLayoutTree
  1. is address by wrapping the VtyWidget monad with additional contextual information
class IsLayoutVtyWidget l t (m :: * -> *) where
  runIsLayoutVtyWidget :: l t m a -> Event t (Maybe Int) -> VtyWidget t m a

newtype LayoutVtyWidget t m a = LayoutVtyWidget {
    unLayoutVtyWidget :: ReaderT (Event t (Maybe Int)) (VtyWidget t m) a
  } deriving (...)

instance MonadTrans (LayoutVtyWidget t) where
  lift x = LayoutVtyWidget $ lift $ lift x

instance IsLayoutVtyWidget VtyWidget t m where
  runIsLayoutVtyWidget w _ = w

instance IsLayoutVtyWidget LayoutVtyWidget t m where
  runIsLayoutVtyWidget = runReaderT . unLayoutVtyWidget

Note that since we have instance LayoutReturn t a a in 1. and instance IsLayoutVtyWidget VtyWidget t m in 2. they work with both layout and non-layout nodes.

Interface Changes

Since focus events now come from the top level layout node, a new method is needed:

beginLayout :: LayoutVtyWidget -> VtyWidget
beginLayout child = do
  tab <- tabNavigation
  runLayoutVtyWidget child tab

Unfortunately, the interface is not seamless in the case of 1. as the desired monadic return value type is ambiguous as we have both

IsLayoutReturn t (LayoutTree t, Dynamic t (Maybe Int), Int, a) a
IsLayoutReturn t (LayoutTree t, Dynamic t (Maybe Int), Int, a) (LayoutTree t, Dynamic t (Maybe Int), Int, a)

So we introduce new variants fixedD and stretchD that make the type deductions above explicit.

Testing

LayoutTree is an optional returned object of type Dynamic t (Tree Region) objects of all the children. The intent is to use for automated testing (e.g. get me the absolute coordinates of (5,7) in relative coordinates of the third node of the second node of some LayoutTree). You can see an example of this here. I imagine it might be useful in non-testing scenarios as well.

Code

I've opened up the following draft PR that implements most of the above for discussion.

Disabled Button Style

It would be nice if the buttons could be disabled from events and had a "greyed out" style when deactivated.

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.