Safe Haskell | Safe |
---|---|
Language | Haskell98 |
- Basic data types
- Cursor movement by character
- Cursor movement by line
- Directly changing cursor position
- Saving, restoring and reporting cursor position
- Clearing parts of the screen
- Scrolling the screen
- Select Graphic Rendition mode: colors and other whizzy stuff
- Cursor visibilty changes
- Changing the title
- Checking if handle supports ANSI (not portable: GHC only)
- Getting the cursor position
Through this module, this library provides platform-independent support for control character sequences following the 'ANSI' standards (see further below) for terminal software that supports those sequences, running on a Unix-like operating system or Windows.
The sequences of control characters (also referred to as 'escape' sequences or codes) provide a rich range of functionality for terminal control, which includes:
- Colored text output, with control over both foreground and background colors
- Clearing parts of a line or the screen
- Hiding or showing the cursor
- Moving the cursor around
- Reporting the position of the cursor
- Scrolling the screen up or down
- Changing the title of the terminal
The native terminal software on Windows is 'Command Prompt' or `PowerShell`. Before Windows 10 version 1511 (known as the 'November [2015] Update' or 'Threshold 2') that software did not support such control sequences. For that software, this library also provides support for such sequences by using emulation.
Terminal software other than the native software exists for Windows. One example is the 'mintty' terminal emulator for 'Cygwin', 'MSYS' or 'MSYS2', and dervied projects, and for 'WSL' (Windows Subsystem for Linux).
The 'ANSI' standards refer to (1) standard ECMA-48 `Control Functions for Coded Character Sets' (5th edition, 1991); (2) extensions in ITU-T Recommendation (previously CCITT Recommendation) T.416 (03/93) 'Information Technology – Open Document Architecture (ODA) and Interchange Format: Character Content Architectures` (also published as ISO/IEC International Standard 8613-6); and (3) further extensions used by 'XTerm', a terminal emulator for the X Window System. The escape codes are described in a Wikipedia article at http://en.wikipedia.org/wiki/ANSI_escape_code and those codes supported on current versions of Windows at https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences.
The whole of the 'ANSI' standards are not supported by this library but most (if not all) of the parts that are popular and well-supported by terminal software are supported. Every function exported by this module comes in three variants, namely:
- A variant that has an
IO ()
type and doesn't take aHandle
(for example,clearScreen :: IO ()
). This variant just outputs the `ANSI` command directly to the standard output channel (stdout
) and any terminal corresponding to it. Commands issued like this should work as you expect on both Unix-like operating systems and Windows. - An '
h
...' variant that has anIO ()
type but takes aHandle
(for example,hClearScreen :: Handle -> IO ()
). This variant outputs the `ANSI` command to the supplied handle and any terminal corresponding to it. Commands issued like this should also work as you expect on both Unix-like operating systems and Windows. - A '...
Code
' variant that has aString
type (for example,clearScreenCode :: String
). This variant outputs the sequence of control characters as aString
, which can be added to any other bit of text before being output. The use of these codes is generally discouraged because they will not work on legacy versions of Windows where the terminal in use is not ANSI-enabled (see further above). On Windows, where emulation has been necessary, these variants will always output the empty string. That is done so that it is possible to use them portably; for example, coloring console output on the understanding that you will see colors only if you are running on a Unix-like operating system or a version of Windows where emulation has not been necessary. If the control characters are always required, see module System.Console.ANSI.Codes.
Example:
module Main where import System.Console.ANSI -- Set colors and write some text in those colors. 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."
For many more examples, see the project's extensive Example.hs file.
- module System.Console.ANSI.Types
- cursorUp :: Int -> IO ()
- cursorDown :: Int -> IO ()
- cursorForward :: Int -> IO ()
- cursorBackward :: Int -> IO ()
- hCursorUp :: Handle -> Int -> IO ()
- hCursorDown :: Handle -> Int -> IO ()
- hCursorForward :: Handle -> Int -> IO ()
- hCursorBackward :: Handle -> Int -> IO ()
- cursorUpCode :: Int -> String
- cursorDownCode :: Int -> String
- cursorForwardCode :: Int -> String
- cursorBackwardCode :: Int -> String
- cursorUpLine :: Int -> IO ()
- cursorDownLine :: Int -> IO ()
- hCursorUpLine :: Handle -> Int -> IO ()
- hCursorDownLine :: Handle -> Int -> IO ()
- cursorUpLineCode :: Int -> String
- cursorDownLineCode :: Int -> String
- setCursorColumn :: Int -> IO ()
- hSetCursorColumn :: Handle -> Int -> IO ()
- setCursorColumnCode :: Int -> String
- setCursorPosition :: Int -> Int -> IO ()
- hSetCursorPosition :: Handle -> Int -> Int -> IO ()
- setCursorPositionCode :: Int -> Int -> String
- saveCursor :: IO ()
- hSaveCursor :: Handle -> IO ()
- saveCursorCode :: String
- restoreCursor :: IO ()
- hRestoreCursor :: Handle -> IO ()
- restoreCursorCode :: String
- reportCursorPosition :: IO ()
- hReportCursorPosition :: Handle -> IO ()
- reportCursorPositionCode :: String
- clearFromCursorToScreenEnd :: IO ()
- clearFromCursorToScreenBeginning :: IO ()
- clearScreen :: IO ()
- hClearFromCursorToScreenEnd :: Handle -> IO ()
- hClearFromCursorToScreenBeginning :: Handle -> IO ()
- hClearScreen :: Handle -> IO ()
- clearFromCursorToScreenEndCode :: String
- clearFromCursorToScreenBeginningCode :: String
- clearScreenCode :: String
- clearFromCursorToLineEnd :: IO ()
- clearFromCursorToLineBeginning :: IO ()
- clearLine :: IO ()
- hClearFromCursorToLineEnd :: Handle -> IO ()
- hClearFromCursorToLineBeginning :: Handle -> IO ()
- hClearLine :: Handle -> IO ()
- clearFromCursorToLineEndCode :: String
- clearFromCursorToLineBeginningCode :: String
- clearLineCode :: String
- scrollPageUp :: Int -> IO ()
- scrollPageDown :: Int -> IO ()
- hScrollPageUp :: Handle -> Int -> IO ()
- hScrollPageDown :: Handle -> Int -> IO ()
- scrollPageUpCode :: Int -> String
- scrollPageDownCode :: Int -> String
- setSGR :: [SGR] -> IO ()
- hSetSGR :: Handle -> [SGR] -> IO ()
- setSGRCode :: [SGR] -> String
- hideCursor :: IO ()
- showCursor :: IO ()
- hHideCursor :: Handle -> IO ()
- hShowCursor :: Handle -> IO ()
- hideCursorCode :: String
- showCursorCode :: String
- setTitle :: String -> IO ()
- hSetTitle :: Handle -> String -> IO ()
- setTitleCode :: String -> String
- hSupportsANSI :: Handle -> IO Bool
- getCursorPosition :: IO (Maybe (Int, Int))
- getReportedCursorPosition :: IO String
- cursorPosition :: ReadP (Int, Int)
Basic data types
module System.Console.ANSI.Types
Cursor movement by character
Cursor movement by line
The difference between movements "by character" and "by line" is
that *Line
functions additionally move the cursor to the start of the
line, while functions like cursorUp
and cursorDown
keep the column
the same.
Also keep in mind that *Line
functions are not as portable. See
https://github.com/feuerbach/ansi-terminal/issues/10 for the details.
Directly changing cursor position
Saving, restoring and reporting cursor position
saveCursor :: IO () Source #
Save the cursor position in memory. The only way to access the saved value
is with the restoreCursor
command.
hSaveCursor :: Handle -> IO () Source #
restoreCursor :: IO () Source #
Restore the cursor position from memory. There will be no value saved in
memory until the first use of the saveCursor
command.
hRestoreCursor :: Handle -> IO () Source #
reportCursorPosition :: IO () Source #
Looking for a way to get the cursors position? See
getCursorPosition
.
Emit the cursor position into the console input stream, immediately after
being recognised on the output stream, as:
ESC [ <cursor row> ; <cursor column> R
In isolation of getReportedCursorPosition
or getCursorPosition
, this
function may be of limited use on Windows operating systems because of
difficulties in obtaining the data emitted into the console input stream.
The function hGetBufNonBlocking
in module System.IO does not work on
Windows. This has been attributed to the lack of non-blocking primatives in
the operating system (see the GHC bug report #806 at
https://ghc.haskell.org/trac/ghc/ticket/806).
hReportCursorPosition :: Handle -> IO () Source #
Clearing parts of the screen
Note that these functions only clear parts of the screen. They do not move the cursor.
clearFromCursorToScreenEnd :: IO () Source #
clearScreen :: IO () Source #
hClearFromCursorToScreenEnd :: Handle -> IO () Source #
hClearFromCursorToScreenBeginning :: Handle -> IO () Source #
hClearScreen :: Handle -> IO () Source #
clearFromCursorToLineEnd :: IO () Source #
hClearFromCursorToLineEnd :: Handle -> IO () Source #
hClearFromCursorToLineBeginning :: Handle -> IO () Source #
hClearLine :: Handle -> IO () Source #
Scrolling the screen
Scroll the displayed information up or down the terminal: not widely supported
Scroll the displayed information up or down the terminal: not widely supported
Scroll the displayed information up or down the terminal: not widely supported
Scroll the displayed information up or down the terminal: not widely supported
Select Graphic Rendition mode: colors and other whizzy stuff
:: [SGR] | Commands: these will typically be applied on top of the
current console SGR mode. An empty list of commands is
equivalent to the list |
-> IO () |
Set the Select Graphic Rendition mode
:: Handle | |
-> [SGR] | Commands: these will typically be applied on top of the
current console SGR mode. An empty list of commands is
equivalent to the list |
-> IO () |
Set the Select Graphic Rendition mode
Cursor visibilty changes
hideCursor :: IO () Source #
showCursor :: IO () Source #
hHideCursor :: Handle -> IO () Source #
hShowCursor :: Handle -> IO () Source #
Changing the title
XTerm control sequence to set the Icon Name and Window Title.
Checking if handle supports ANSI (not portable: GHC only)
hSupportsANSI :: Handle -> IO Bool Source #
Use heuristics to determine whether the functions defined in this package will work with a given handle.
For Unix-like operating systems, the current implementation checks
that: (1) the handle is a terminal; and (2) a TERM
environment variable is not set to dumb
(which is what the GNU Emacs text
editor sets for its integrated terminal).
For Windows, the current implementation performs the same checks as for
Unix-like operating systems and, as an alternative, checks whether the
handle is connected to a 'mintty' terminal. (That is because the function
hIsTerminalDevice
is used to check if the handle is a
terminal. However, where a non-native Windows terminal (such as 'mintty')
is implemented using redirection, that function will not identify a
handle to the terminal as a terminal.)
Getting the cursor position
getCursorPosition :: IO (Maybe (Int, Int)) Source #
Attempts to get the reported cursor position, combining the functions
reportCursorPosition
, getReportedCursorPosition
and cursorPosition
.
Returns Nothing
if any data emitted by reportCursorPosition
, 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.)
getReportedCursorPosition :: IO String Source #
Attempts to get the reported cursor position data from the console input
stream. The function is intended to be called immediately after
reportCursorPosition
(or related functions) have caused characters to be
emitted into the stream.
For example, on a Unix-like operating system:
hSetBuffering stdin NoBuffering -- set no buffering (the contents of the -- 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 input <- getReportedCursorPosition
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.)
cursorPosition :: ReadP (Int, Int) Source #
Parses the characters emitted by reportCursorPosition
into the console
input stream. Returns the cursor row and column as a tuple.
For example, if the characters emitted by reportCursorPosition
are in
String
input
then the parser could be applied like this:
let result = readP_to_S cursorPosition input case result of [] -> putStrLn $ "Error: could not parse " ++ show input [((row, column), _)] -> putStrLn $ "The cursor was at row " ++ show row ++ " and column" ++ show column ++ "." (_:_) -> putStrLn $ "Error: parse not unique"