1-- Copyright 2009 Corey O'Connor
2{-# LANGUAGE ForeignFunctionInterface, BangPatterns, UnboxedTuples #-}
5-- Good sources of documentation for terminal programming are:
6-- vt100 control sequences: http://vt100.net/docs/vt100-ug/chapter3.html#S3.3.3
7-- Xterm control sequences: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
9module Graphics.Vty ( Vty(..)
12 , module Graphics.Vty.Terminal
13 , module Graphics.Vty.Picture
14 , module Graphics.Vty.DisplayRegion
23import Graphics.Vty.Terminal
24import Graphics.Vty.Picture
25import Graphics.Vty.DisplayRegion
26import Graphics.Vty.LLInput
30import Data.Maybe ( maybe )
32import qualified System.Console.Terminfo as Terminfo
35-- | The main object. At most one should be created.
36-- An alternative is to use unsafePerformIO to automatically create a singleton Vty instance when
39-- This does not assure any thread safety. In theory, as long as an update action is not executed
40-- when another update action is already then it's safe to call this on multiple threads.
42-- todo: Once the Terminal interface encompasses input this interface will be deprecated.
43-- Currently, just using the Terminal interface there is no support for input events.
45 { -- | Outputs the given Picture. Equivalent to output_picture applied to a display context
46 -- implicitly managed by Vty.
47 update :: Picture -> IO ()
48 -- | Get one Event object, blocking if necessary.
49 , next_event :: IO Event
50 -- | Handle to the terminal interface. See `Terminal`
52 -- The use of Vty typically follows this process:
56 -- 1. use the update equation of Vty to display a picture
62 -- todo: provide a similar abstraction to Graphics.Vty.Terminal for input. Use haskeline's
63 -- input backend for implementation.
65 -- todo: remove explicit `shutdown` requirement.
66 , terminal :: TerminalHandle
67 -- | Refresh the display. Normally the library takes care of refreshing. Nonetheless, some
68 -- other program might output to the terminal and mess the display. In that case the user
69 -- might want to force a refresh.
71 -- | Clean up after vty.
75-- | Set up the state object for using vty. At most one state object should be
78mkVty = mkVtyEscDelay 0
80mkVtyEscDelay :: Int -> IO Vty
81mkVtyEscDelay escDelay = do
82 term_info <- Terminfo.setupTermFromEnv
85 (kvar, endi) <- initTermInput escDelay term_info
86 intMkVty kvar ( endi >> release_display t >> release_terminal t ) t
88intMkVty :: IO Event -> IO () -> TerminalHandle -> IO Vty
89intMkVty kvar fend t = do
90 last_pic_ref <- newIORef undefined
91 last_update_ref <- newIORef Nothing
93 let inner_update in_pic = do
95 mlast_update <- readIORef last_update_ref
96 update_data <- case mlast_update of
98 d <- display_context t b
99 output_picture d in_pic
101 Just (last_bounds, last_context) -> do
104 d <- display_context t b
105 output_picture d in_pic
108 output_picture last_context in_pic
109 return (b, last_context)
110 writeIORef last_update_ref $ Just update_data
111 writeIORef last_pic_ref $ Just in_pic
114 = writeIORef last_update_ref Nothing
115 >> readIORef last_pic_ref
116 >>= maybe ( return () ) ( \pic -> inner_update pic )
118 let gkey = do k <- kvar
120 (EvResize _ _) -> inner_refresh
122 >>= return . ( \(DisplayRegion w h)
123 -> EvResize (fromEnum w) (fromEnum h)
127 return $ Vty { update = inner_update
130 , refresh = inner_refresh
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list