3-- Access to the current terminal or a specific terminal device.
7-- 1. "Graphics.Vty.Output": This instantiates an abtract interface to the terminal interface based
8-- on the TERM and COLORTERM environment variables.
10-- 2. "Graphics.Vty.Output.Interface": Defines the generic interface all terminals need to implement.
12-- 3. "Graphics.Vty.Output.TerminfoBased": Defines a terminal instance that uses terminfo for all
13-- control strings. No attempt is made to change the character set to UTF-8 for these terminals.
14-- I don't know a way to reliably determine if that is required or how to do so.
16-- 4. "Graphics.Vty.Output.XTermColor": This module contains an interface suitable for xterm-like
17-- terminals. These are the terminals where TERM == xterm. This does use terminfo for as many
18-- control codes as possible.
19module Graphics.Vty.Output ( module Graphics.Vty.Output
20 , Output(..) -- \todo hide constructors
22 , DisplayContext(..) -- \todo hide constructors
29import Graphics.Vty.Prelude
31import Graphics.Vty.Output.Interface
32import Graphics.Vty.Output.MacOSX as MacOSX
33import Graphics.Vty.Output.XTermColor as XTermColor
34import Graphics.Vty.Output.TerminfoBased as TerminfoBased
36import Control.Exception ( SomeException, try )
37import Control.Monad.Trans
39import Data.List ( isPrefixOf )
43import System.Environment
46-- | Returns a `Output` for the current terminal as determined by TERM.
48-- The specific Output implementation used is hidden from the API user. All terminal implementations
49-- are assumed to perform more, or less, the same. Currently all implementations use terminfo for at
50-- least some terminal specific information. This is why platforms without terminfo are not
51-- supported. However, as mentioned before, any specifics about it being based on terminfo are
52-- hidden from the API user. If a terminal implementation is developed for a terminal for a
53-- platform without terminfo support then Vty should work as expected on that terminal.
55-- Selection of a terminal is done as follows:
58-- then the terminal might be one of the Mac OS X .app terminals. Check if that might be
59-- the case and use MacOSX if so.
60-- otherwise use XTermColor.
62-- * for any other TERM value TerminfoBased is used.
64-- To differentiate between Mac OS X terminals this uses the TERM_PROGRAM environment variable.
65-- However, an xterm started by Terminal or iTerm *also* has TERM_PROGRAM defined since the
66-- environment variable is not reset/cleared by xterm. However a Terminal.app or iTerm.app started
67-- from an xterm under X11 on mac os x will likely be done via open. Since this does not propogate
68-- environment variables (I think?) this assumes that XTERM_VERSION will never be set for a true
69-- Terminal.app or iTerm.app session.
71-- The file descriptor used for output will a be a duplicate of the current stdout file descriptor.
73-- \todo add an implementation for windows that does not depend on terminfo. Should be installable
74-- with only what is provided in the haskell platform. Use ansi-terminal
75output_for_current_terminal :: ( Applicative m, MonadIO m ) => m Output
76output_for_current_terminal = do
77 term_type <- liftIO $ getEnv "TERM"
78 out_handle <- liftIO $ hDuplicate stdout
79 output_for_name_and_io term_type out_handle
81-- | gives an output method structure for a terminal with the given name and the given 'Handle'.
82output_for_name_and_io :: (Applicative m, MonadIO m) => String -> Handle -> m Output
83output_for_name_and_io term_type out_handle = do
84 t <- if "xterm" `isPrefixOf` term_type
86 maybe_terminal_app <- get_env "TERM_PROGRAM"
87 case maybe_terminal_app of
89 -> XTermColor.reserve_terminal term_type out_handle
90 Just v | v == "Apple_Terminal" || v == "iTerm.app"
92 maybe_xterm <- get_env "XTERM_VERSION"
94 Nothing -> MacOSX.reserve_terminal v out_handle
95 Just _ -> XTermColor.reserve_terminal term_type out_handle
96 -- Assume any other terminal that sets TERM_PROGRAM to not be an OS X terminal.app
98 _ -> XTermColor.reserve_terminal term_type out_handle
99 -- Not an xterm-like terminal. try for generic terminfo.
100 else TerminfoBased.reserve_terminal term_type out_handle
104 mv <- liftIO $ try $ getEnv var
106 Left (_e :: SomeException) -> return $ Nothing
107 Right v -> return $ Just v
109-- | Sets the cursor position to the given output column and row.
111-- This is not necessarially the same as the character position with the same coordinates.
112-- Characters can be a variable number of columns in width.
114-- Currently, the only way to set the cursor position to a given character coordinate is to specify
115-- the coordinate in the Picture instance provided to output_picture or refresh.
116set_cursor_pos :: MonadIO m => Output -> Int -> Int -> m ()
117set_cursor_pos t x y = do
118 bounds <- display_bounds t
119 when (x >= 0 && x < region_width bounds && y >= 0 && y < region_height bounds) $ do
120 dc <- display_context t bounds
121 liftIO $ send_to_terminal t (move_cursor_required_bytes dc x y) (serialize_move_cursor dc x y)
124hide_cursor :: MonadIO m => Output -> m ()
126 bounds <- display_bounds t
127 dc <- display_context t bounds
128 liftIO $ send_to_terminal t (hide_cursor_required_bytes dc) (serialize_hide_cursor dc)
131show_cursor :: MonadIO m => Output -> m ()
133 bounds <- display_bounds t
134 dc <- display_context t bounds
135 liftIO $ send_to_terminal t (show_cursor_required_bytes dc) (serialize_show_cursor dc)
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