How to display potentially very large file with brick?

38 views
Skip to first unread message

Михаил Доронин

unread,
Dec 9, 2018, 11:27:48 AM12/9/18
to Brick Users
I'm trying to build a substitute for
less

pager

My current attempt is here.

Relevant lines.




data
TuiState = TuiState { lines :: V.Vector BC.ByteString , topLine :: Int } deriving (Show, Eq)



drawTui
:: TuiState -> [Widget Name]
drawTui
(TuiState lines topLine) = [viewport Viewport1 Vertical $ str $ BC.unpack $ BC.unlines $ V.toList $ V.drop topLine lines] handleTuiEvent :: TuiState -> BrickEvent Name e -> EventM Name (Next TuiState) handleTuiEvent s@(TuiState lines topLine) e = case e of VtyEvent vtye -> case vtye of EvKey (KChar 'q') [] -> halt s EvKey (KChar 'j') [] -> do let vp = viewportScroll Viewport1 vScrollBy vp 1 continue s EvKey (KChar 'k') [] -> do let vp = viewportScroll Viewport1 vScrollBy vp (-1) continue s EvKey (KChar 'g') [] -> do c <- getEnv "LINES" continue $ TuiState lines (topLine + (read c)) _ -> continue s _ -> continue s



I have troubles with how to show large file. Should I just use one str and a ViewPort? But I can't scroll ViewPort let's say to n'th line or half screen because I don't know how to know screen height.
I could use one str and implement scrolling by limiting by getting appropriate range of lines from all lines, but again I don't know to to get screen height.

Jonathan Daugherty

unread,
Dec 9, 2018, 1:52:25 PM12/9/18
to Михаил Доронин, brick...@googlegroups.com
Greetings,

> I have troubles with how to show large file. Should I just use one str
> and a ViewPort? But I can't scroll ViewPort let's say to n'th line or
> half screen because I don't know how to know screen height. I could
> use one str and implement scrolling by limiting by getting appropriate
> range of lines from all lines, but again I don't know to to get screen
> height.

This section of the User Guide details how to get the rendering area
height:

https://github.com/jtdaugherty/brick/blob/master/docs/guide.rst#implementing-custom-widgets

--
Jonathan Daugherty

Михаил Доронин

unread,
Dec 9, 2018, 2:21:35 PM12/9/18
to Brick Users
Thank you for your answer.

Yeah, I've read this, but where should I use it? I can't use it from event handler, but it's already in the event monad, so I can't use getContext from there. Maybe I need some monad transformer or something? Can you provide example?

Jonathan Daugherty

unread,
Dec 9, 2018, 2:50:32 PM12/9/18
to brick...@googlegroups.com
> Yeah, I've read this, but where should I use it? I can't use it
> from event handler, but it's already in the event monad, so I can't
> use getContext from there. Maybe I need some monad transformer or
> something? Can you provide example?

The rendering context is available in the rendering monad that is used
in the 'render' field of 'Widget'. So the source for any built-in
combinator can provide insight about how to get and use the context. For
example, 'fill' uses the context's available height and width fields to
create a character fill to fill available space:

http://hackage.haskell.org/package/brick-0.44.1/docs/src/Brick.Widgets.Core.html#fill

You might have something like

import qualified Data.Foldable as F
import qualified Data.Text as T
import qualified Data.Vector as V

renderPager :: Int -> V.Vector T.Text -> Widget n
renderPager lineOffset textLines =
Widget Greedy Greedy $ do
ctx <- getContext
let visibleLines = -- Take slice of lines from the vector starting at lineOffset,
-- of size (ctx^.availHeightL - lineOffset)
render $ txt $ T.unlines $ F.toList visibleLines

Then it would be up to you to mutate the line offset in your event
handler on e.g. arrow key events.

--
Jonathan Daugherty
Message has been deleted

Михаил Доронин

unread,
Dec 10, 2018, 4:01:34 PM12/10/18
to Brick Users
Yeah, I've already tried that actually. I think I wasn't clear enough.

Suppose I want to go half page down. In the event handler I don't know how much lines are 'half page'.
I can only know that inside the widget. Basically my next state depends on a widget state.
9 Dec

Jonathan Daugherty

unread,
Dec 10, 2018, 4:07:35 PM12/10/18
to Михаил Доронин, Brick Users
> Yeah, I've already tried that actually. I think I wasn't clear enough.
>
> Suppose I want to go half page down. In the event handler I don't
> know how much lines are 'half page'. I can only know that inside the
> widget. Basically my next state depends on a widget state.

You can get that information by looking up the viewport in EventM with

http://hackage.haskell.org/package/brick-0.44.1/docs/Brick-Main.html#v:lookupViewport

From that you'll have enough information to decide how much to scroll
using

http://hackage.haskell.org/package/brick-0.44.1/docs/Brick-Main.html#v:vScrollBy

or even

http://hackage.haskell.org/package/brick-0.44.1/docs/Brick-Main.html#v:hScrollPage

--
Jonathan Daugherty
Reply all
Reply to author
Forward
0 new messages