packages feed

ansi-terminal 0.10 → 0.10.1

raw patch · 8 files changed

+105/−30 lines, 8 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ System.Console.ANSI: hGetCursorPosition :: Handle -> IO (Maybe (Int, Int))
+ System.Console.ANSI: hGetTerminalSize :: Handle -> IO (Maybe (Int, Int))

Files

CHANGELOG.md view
@@ -1,6 +1,15 @@ Changes
 =======
 
+Version 0.10.1
+--------------
+
+* Add `hGetCursorPosition` and `hGetTerminalSize`.
+* On Unix-like operating systems, fix a bug where `getReportedCursorPosition`
+  could block indefinitely if no information was forthcoming on the console
+  input stream.
+* Improvements to Haddock documentation.
+
 Version 0.10
 ------------
 
ansi-terminal.cabal view
@@ -1,5 +1,5 @@ Name:                ansi-terminal
-Version:             0.10
+Version:             0.10.1
 Cabal-Version:       >= 1.8
 Category:            User Interfaces
 Synopsis:            Simple ANSI terminal support, with Windows compatibility
src/System/Console/ANSI.hs view
@@ -23,6 +23,10 @@ 
  * Changing the title of the terminal
 
+A terminal that supports control character sequences acts on them when they
+are flushed from the output buffer (with a newline character @\"\\n\"@ or, for
+the standard output channel, @hFlush stdout@).
+
 The functions moving the cursor to an absolute position are 0-based (the
 top-left corner is considered to be at row 0 column 0) (see 'setCursorPosition')
 and so is 'getCursorPosition0'. The \'ANSI\' standards themselves are 1-based
@@ -88,12 +92,31 @@ > import System.Console.ANSI
 >
 > -- Set colors and write some text in those colors.
+> main :: IO ()
 > main = do
 >   setSGR [SetColor Foreground Vivid Red]
 >   setSGR [SetColor Background Vivid Blue]
 >   putStrLn "Red-On-Blue"
 >   setSGR [Reset]  -- Reset to default colour scheme
 >   putStrLn "Default colors."
+
+Another example:
+
+> module Main where
+>
+> import System.IO (hFlush, stdout)
+> import System.Console.ANSI
+>
+> main :: IO ()
+> main = do
+>   setSGR [SetColor Foreground Dull Blue]
+>   putStr "Enter your name: "
+>   setSGR [SetColor Foreground Dull Yellow]
+>   hFlush stdout  -- flush the output buffer before getLine
+>   name <- getLine
+>   setSGR [SetColor Foreground Dull Blue]
+>   putStrLn $ "Hello, " ++ name ++ "!"
+>   setSGR [Reset]  -- reset to default colour scheme
 
 For many more examples, see the project's extensive
 <https://github.com/feuerbach/ansi-terminal/blob/master/app/Example.hs Example.hs> file.
src/System/Console/ANSI/Unix.hs view
@@ -9,9 +9,11 @@ #include "Exports-Include.hs"
   ) where
 
+import Data.Maybe (fromMaybe)
 import Control.Exception.Base (bracket)
 import System.IO (BufferMode (..), Handle, hGetBuffering, hGetEcho,
   hIsTerminalDevice, hIsWritable, hPutStr, hSetBuffering, hSetEcho, stdin)
+import System.Timeout (timeout)
 import Text.ParserCombinators.ReadP (readP_to_S)
 
 import System.Console.ANSI.Codes
@@ -81,7 +83,10 @@ -- (See Common-Include.hs for Haddock documentation)
 getReportedCursorPosition = bracket (hGetEcho stdin) (hSetEcho stdin) $ \_ -> do
   hSetEcho stdin False   -- Turn echo off
-  get
+  -- If, unexpectedly, no data is available on the console input stream then
+  -- the timeout will prevent the getChar blocking. For consistency with the
+  -- Windows equivalent, returns "" if the expected information is unavailable.
+  fromMaybe "" <$> timeout 500000 get -- 500 milliseconds
  where
   get = do
     c <- getChar
@@ -98,9 +103,9 @@                       -- in order to avoid O(n^2) complexity.
       else return $ reverse (c:s) -- Reverse the order of the built list.
 
--- getCursorPosition0 :: IO (Maybe (Int, Int))
+-- hGetCursorPosition :: Handle -> IO (Maybe (Int, Int))
 -- (See Common-Include.hs for Haddock documentation)
-getCursorPosition0 = fmap to0base <$> getCursorPosition
+hGetCursorPosition h = fmap to0base <$> getCursorPosition
  where
   to0base (row, col) = (row - 1, col - 1)
   getCursorPosition = do
@@ -109,9 +114,9 @@                                       -- buffer will be discarded, so this needs
                                       -- to be done before the cursor positon is
                                       -- emitted)
-      reportCursorPosition
-      hFlush stdout -- ensure the report cursor position code is sent to the
-                    -- operating system
+      hReportCursorPosition h
+      hFlush h -- ensure the report cursor position code is sent to the
+               -- operating system
       getReportedCursorPosition
     case readP_to_S cursorPosition input of
       [] -> return Nothing
src/System/Console/ANSI/Windows.hs view
@@ -191,6 +191,6 @@ -- (See Common-Include.hs for Haddock documentation)
 getReportedCursorPosition = E.getReportedCursorPosition
 
--- getCursorPosition0 :: IO (Maybe (Int, Int))
+-- hGetCursorPosition :: Handle -> IO (Maybe (Int, Int))
 -- (See Common-Include.hs for Haddock documentation)
-getCursorPosition0 = E.getCursorPosition0
+hGetCursorPosition = E.hGetCursorPosition
src/System/Console/ANSI/Windows/Emulator.hs view
@@ -477,18 +477,18 @@       isKeyDown = keyEventKeyDown keyEventRecord
       isKeyDownEvent = eventType == 1 && isKeyDown
 
--- getCursorPosition0 :: IO (Maybe (Int, Int))
+-- hGetCursorPosition :: Handle -> IO (Maybe (Int, Int))
 -- (See Common-Include.hs for Haddock documentation)
-getCursorPosition0 = fmap to0base <$> getCursorPosition
+hGetCursorPosition h = fmap to0base <$> getCursorPosition
  where
   to0base (row, col) = (row - 1, col - 1)
   getCursorPosition = CE.catch getCursorPosition' getCPExceptionHandler
    where
     getCursorPosition' = do
       withHandleToHANDLE stdin flush -- Flush the console input buffer
-      reportCursorPosition
-      hFlush stdout -- ensure the report cursor position code is sent to the
-                    -- operating system
+      hReportCursorPosition h
+      hFlush h -- ensure the report cursor position code is sent to the
+               -- operating system
       input <- getReportedCursorPosition
       case readP_to_S cursorPosition input of
         [] -> return Nothing
src/includes/Common-Include.hs view
@@ -5,12 +5,12 @@ -- documentation.
 
 #if !MIN_VERSION_base(4,8,0)
-import Control.Applicative
+import Control.Applicative ((<*>))
+import Data.Functor ((<$>))
 #endif
 
 import Control.Monad (void)
 import Data.Char (isDigit)
-import Data.Functor ((<$>))
 import System.Environment (getEnvironment)
 import System.IO (hFlush, stdout)
 import Text.ParserCombinators.ReadP (char, many1, ReadP, satisfy)
@@ -227,10 +227,12 @@ -- 'reportCursorPosition', 'getReportedCursorPosition' and 'cursorPosition'. Any
 -- position @(row, column)@ is translated to be 0-based (that is, the top-left
 -- corner is at @(0, 0)@), consistent with `setCursorColumn` and
--- `setCursorPosition`. (Note that the information emitted by
--- 'reportCursorPosition' is 1-based.) Returns 'Nothing' if any data emitted by
--- 'reportCursorPosition', obtained by 'getReportedCursorPosition', cannot be
--- parsed by 'cursorPosition'.
+-- `setCursorPosition`. (Note that the information emitted into the console
+-- input stream by 'reportCursorPosition' is 1-based.) Returns 'Nothing' if any
+-- data emitted by 'reportCursorPosition', obtained by
+-- 'getReportedCursorPosition', cannot be parsed by 'cursorPosition'. Uses
+-- 'stdout'. If 'stdout' will be redirected, see 'hGetCursorPosition' for a more
+-- general function.
 --
 -- On Windows operating systems, the function is not supported on consoles, such
 -- as mintty, that are not based on the Win32 console of the Windows API.
@@ -238,10 +240,30 @@ --
 -- @since 0.8.2
 getCursorPosition0 :: IO (Maybe (Int, Int))
+getCursorPosition0 = hGetCursorPosition stdout
 
+-- | Attempts to get the reported cursor position, combining the functions
+-- 'hReportCursorPosition' (with the specified handle),
+-- 'getReportedCursorPosition' and 'cursorPosition'. Any position
+-- @(row, column)@ is translated to be 0-based (that is, the top-left corner is
+-- at @(0, 0)@), consistent with 'hSetCursorColumn' and 'hSetCursorPosition'.
+-- (Note that the information emitted into the console input stream by
+-- 'hReportCursorPosition' is 1-based.) Returns 'Nothing' if any data emitted by
+-- 'hReportCursorPosition', obtained by 'getReportedCursorPosition', cannot be
+-- parsed by 'cursorPosition'.
+--
+-- On Windows operating systems, the function is not supported on consoles, such
+-- as mintty, that are not based on the Win32 console of the Windows API.
+-- (Command Prompt and PowerShell are based on the Win32 console.)
+--
+-- @since 0.10.1
+hGetCursorPosition :: Handle -> IO (Maybe (Int, Int))
+
 -- | Attempts to get the current terminal size (height in rows, width in
--- columns), by using `getCursorPosition0` after attempting to set the cursor
--- position beyond the bottom right corner of the terminal.
+-- columns), by using 'getCursorPosition0' to query the console input stream
+-- after attempting to set the cursor position beyond the bottom right corner of
+-- the terminal. Uses 'stdout'. If 'stdout' will be redirected, see
+-- 'hGetTerminalSize' for a more general function.
 --
 -- On Windows operating systems, the function is not supported on consoles, such
 -- as mintty, that are not based on the Win32 console of the Windows API.
@@ -249,12 +271,26 @@ --
 -- @since 0.9
 getTerminalSize :: IO (Maybe (Int, Int))
-getTerminalSize = do
-  saveCursor
-  setCursorPosition 999 999  -- Attempt to set the cursor position beyond the
-                             -- bottom right corner of the terminal.
-  mPos <- getCursorPosition0
-  restoreCursor
-  hFlush stdout -- ensure the restore cursor position code is sent to the
-                -- operating system
+getTerminalSize = hGetTerminalSize stdout
+
+-- | Attempts to get the current terminal size (height in rows, width in
+-- columns), by writing control character sequences to the specified handle
+-- (which will typically be 'stdout' or 'stderr') and using 'hGetCursorPosition'
+-- to query the console input stream after attempting to set the cursor position
+-- beyond the bottom right corner of the terminal.
+--
+-- On Windows operating systems, the function is not supported on consoles, such
+-- as mintty, that are not based on the Win32 console of the Windows API.
+-- (Command Prompt and PowerShell are based on the Win32 console.)
+--
+-- @since 0.10.1
+hGetTerminalSize :: Handle -> IO (Maybe (Int, Int))
+hGetTerminalSize h = do
+  hSaveCursor h
+  hSetCursorPosition h 999 999  -- Attempt to set the cursor position beyond the
+                                -- bottom right corner of the terminal.
+  mPos <- hGetCursorPosition h
+  hRestoreCursor h
+  hFlush h -- ensure the restore cursor position code is sent to the
+           -- operating system
   return $ fmap (\(r, c) -> (r + 1, c + 1)) mPos
src/includes/Exports-Include.hs view
@@ -112,8 +112,10 @@ 
     -- * Getting the cursor position
   , getCursorPosition0
+  , hGetCursorPosition
   , getReportedCursorPosition
   , cursorPosition
 
     -- * Getting the terminal size
   , getTerminalSize
+  , hGetTerminalSize