reflex-frp / reflex-vty Goto Github PK
View Code? Open in Web Editor NEWBuild terminal applications using functional reactive programming (FRP) with Reflex FRP.
Home Page: https://reflex-frp.org
License: BSD 3-Clause "New" or "Revised" License
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
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.
Create a new parameter _vtyWidgetCtx_defaultAttr
in VtyWidgetCtx
that's used instead of V.defAttr across all built-in widgets.
Sample implementation #42
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.
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.
Add Constraint_Fit
and corresponding fit
function.
To reproduce:
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.
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.
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.
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.
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.
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!
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:
A small network consisting of two widgets, one of them affecting the other:
Enter
(when focused) or mouse clicksSince the list content is subordinate to the text input's filter definition, the network configuration requires switching, so enters networkHold
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.
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.
reflex-vty/src/Reflex/Vty/Widget/Input.hs
Line 147 in cf146f5
Perhaps we should make it vty >= 5.28 && < 5.34
?
TLDR; see draft PR
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:
row1
and someWidget2
someWidget<n>
to someWidget<n+1 mod 6>
and switch focus between row1
and row2
as necessaryHowever, instead we have:
row2
and someWidget2
tab
again will focus row1
and someWidget2
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:
runLayout
needs to be aware of nested layout nodes in order to focus the correct tiletile
needs to be aware of when a particular nested node index should be focusLayoutTree
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
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.
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.
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.
I've opened up the following draft PR that implements most of the above for discussion.
Would love to use this for my project which is already half written in 0.7.0.0.
I noticed when using Alacritty that scrolling in reflex-ghci
didn't work unless I set TERM=xterm
. I would guess this means that reflex-vty
isn't doing some terminfo black magic.
I meant git clone [email protected]:obsidian.systems/reflex-vty
in README.md
It would be nice if the buttons could be disabled from events and had a "greyed out" style when deactivated.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.