1-- Copyright 2009-2010 Corey O'Connor
2-- | Xterm output driver. This uses the Terminfo driver with some
3-- extensions for Xterm.
4module Graphics.Vty.Output.XTermColor
9import Graphics.Vty.Output.Interface
10import Graphics.Vty.Input.Mouse
11import Graphics.Vty.Input.Focus
12import qualified Graphics.Vty.Output.TerminfoBased as TerminfoBased
14import Blaze.ByteString.Builder (writeToByteString)
15import Blaze.ByteString.Builder.Word (writeWord8)
17import Control.Monad (void, when)
18import Control.Monad.Trans
21import System.Posix.IO (fdWrite)
22import System.Posix.Types (Fd)
23import System.Posix.Env (getEnv)
25import Data.List (isInfixOf)
26import Data.Maybe (catMaybes)
27import Data.Monoid ((<>))
29-- | Construct an Xterm output driver. Initialize the display to UTF-8.
30reserveTerminal :: ( Applicative m, MonadIO m ) => String -> Fd -> m Output
31reserveTerminal variant outFd = liftIO $ do
32 let flushedPut = void . fdWrite outFd
33 -- If the terminal variant is xterm-color use xterm instead since,
34 -- more often than not, xterm-color is broken.
35 let variant' = if variant == "xterm-color" then "xterm" else variant
38 when (not utf8a) $ flushedPut setUtf8CharSet
39 t <- TerminfoBased.reserveTerminal variant' outFd
41 mouseModeStatus <- newIORef False
42 focusModeStatus <- newIORef False
43 pasteModeStatus <- newIORef False
45 let xtermSetMode t' m newStatus = do
46 curStatus <- getModeStatus t' m
47 when (newStatus /= curStatus) $
51 True -> flushedPut requestFocusEvents
52 False -> flushedPut disableFocusEvents
53 writeIORef focusModeStatus newStatus
56 True -> flushedPut requestMouseEvents
57 False -> flushedPut disableMouseEvents
58 writeIORef mouseModeStatus newStatus
59 BracketedPaste -> liftIO $ do
61 True -> flushedPut enableBracketedPastes
62 False -> flushedPut disableBracketedPastes
63 writeIORef pasteModeStatus newStatus
64 Hyperlink -> setMode t Hyperlink newStatus
66 xtermGetMode Mouse = liftIO $ readIORef mouseModeStatus
67 xtermGetMode Focus = liftIO $ readIORef focusModeStatus
68 xtermGetMode BracketedPaste = liftIO $ readIORef pasteModeStatus
69 xtermGetMode Hyperlink = getModeStatus t Hyperlink
72 { terminalID = terminalID t ++ " (xterm-color)"
73 , releaseTerminal = do
74 when (not utf8a) $ liftIO $ flushedPut setDefaultCharSet
75 setMode t' BracketedPaste False
76 setMode t' Mouse False
77 setMode t' Focus False
79 , mkDisplayContext = \tActual r -> do
80 dc <- mkDisplayContext t tActual r
81 return $ dc { inlineHack = xtermInlineHack t' }
82 , supportsMode = const True
83 , getModeStatus = xtermGetMode
84 , setMode = xtermSetMode t'
90 let vars = ["LC_ALL", "LANG", "LC_CTYPE"]
91 results <- catMaybes <$> mapM getEnv vars
92 let matches = filter ("UTF8" `isInfixOf`) results <>
93 filter ("UTF-8" `isInfixOf`) results
94 return $ not $ null matches
96-- | Enable bracketed paste mode:
97-- http://cirw.in/blog/bracketed-paste
98enableBracketedPastes :: String
99enableBracketedPastes = "\ESC[?2004h"
101-- | Disable bracketed paste mode:
102disableBracketedPastes :: String
103disableBracketedPastes = "\ESC[?2004l"
105-- | These sequences set xterm based terminals to UTF-8 output.
107-- There is no known terminfo capability equivalent to this.
108setUtf8CharSet, setDefaultCharSet :: String
109setUtf8CharSet = "\ESC%G"
110setDefaultCharSet = "\ESC%@"
112-- | I think xterm is broken: Reseting the background color as the first
113-- bytes serialized on a new line does not effect the background color
114-- xterm uses to clear the line. Which is used *after* the next newline.
115xtermInlineHack :: Output -> IO ()
116xtermInlineHack t = do
117 let writeReset = foldMap (writeWord8.toEnum.fromEnum) "\ESC[K"
118 outputByteBuffer t $ writeToByteString writeReset
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