summaryrefslogtreecommitdiff
path: root/compiler/GHC/SysTools/Terminal.hs
diff options
context:
space:
mode:
authorSylvain Henry <sylvain@haskus.fr>2020-04-05 17:39:13 +0200
committerSylvain Henry <sylvain@haskus.fr>2020-04-18 20:04:46 +0200
commit15312bbb53f247c9ed2c5cf75100a9f44c1c7227 (patch)
tree8306dcc04a5b7c82464f903044dfdd589e7fdcd7 /compiler/GHC/SysTools/Terminal.hs
parent3ca52151881451ce5b3a7740d003e811b586140d (diff)
downloadhaskell-15312bbb53f247c9ed2c5cf75100a9f44c1c7227.tar.gz
Modules (#13009)
* SysTools * Parser * GHC.Builtin * GHC.Iface.Recomp * Settings Update Haddock submodule Metric Decrease: Naperian parsing001
Diffstat (limited to 'compiler/GHC/SysTools/Terminal.hs')
-rw-r--r--compiler/GHC/SysTools/Terminal.hs104
1 files changed, 104 insertions, 0 deletions
diff --git a/compiler/GHC/SysTools/Terminal.hs b/compiler/GHC/SysTools/Terminal.hs
new file mode 100644
index 0000000000..69c605bc73
--- /dev/null
+++ b/compiler/GHC/SysTools/Terminal.hs
@@ -0,0 +1,104 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+module GHC.SysTools.Terminal (stderrSupportsAnsiColors) where
+
+import GhcPrelude
+
+#if defined(MIN_VERSION_terminfo)
+import Control.Exception (catch)
+import Data.Maybe (fromMaybe)
+import System.Console.Terminfo (SetupTermError, Terminal, getCapability,
+ setupTermFromEnv, termColors)
+import System.Posix (queryTerminal, stdError)
+#elif defined(mingw32_HOST_OS)
+import Control.Exception (catch, try)
+import Data.Bits ((.|.), (.&.))
+import Foreign (Ptr, peek, with)
+import qualified Graphics.Win32 as Win32
+import qualified System.Win32 as Win32
+#endif
+
+import System.IO.Unsafe
+
+#if defined(mingw32_HOST_OS) && !defined(WINAPI)
+# if defined(i386_HOST_ARCH)
+# define WINAPI stdcall
+# elif defined(x86_64_HOST_ARCH)
+# define WINAPI ccall
+# else
+# error unknown architecture
+# endif
+#endif
+
+-- | Does the controlling terminal support ANSI color sequences?
+-- This memoized to avoid thread-safety issues in ncurses (see #17922).
+stderrSupportsAnsiColors :: Bool
+stderrSupportsAnsiColors = unsafePerformIO stderrSupportsAnsiColors'
+{-# NOINLINE stderrSupportsAnsiColors #-}
+
+-- | Check if ANSI escape sequences can be used to control color in stderr.
+stderrSupportsAnsiColors' :: IO Bool
+stderrSupportsAnsiColors' = do
+#if defined(MIN_VERSION_terminfo)
+ stderr_available <- queryTerminal stdError
+ if stderr_available then
+ fmap termSupportsColors setupTermFromEnv
+ `catch` \ (_ :: SetupTermError) -> pure False
+ else
+ pure False
+ where
+ termSupportsColors :: Terminal -> Bool
+ termSupportsColors term = fromMaybe 0 (getCapability term termColors) > 0
+
+#elif defined(mingw32_HOST_OS)
+ h <- Win32.getStdHandle Win32.sTD_ERROR_HANDLE
+ `catch` \ (_ :: IOError) ->
+ pure Win32.nullHANDLE
+ if h == Win32.nullHANDLE
+ then pure False
+ else do
+ eMode <- try (getConsoleMode h)
+ case eMode of
+ Left (_ :: IOError) -> Win32.isMinTTYHandle h
+ -- Check if the we're in a MinTTY terminal
+ -- (e.g., Cygwin or MSYS2)
+ Right mode
+ | modeHasVTP mode -> pure True
+ | otherwise -> enableVTP h mode
+
+ where
+
+ enableVTP :: Win32.HANDLE -> Win32.DWORD -> IO Bool
+ enableVTP h mode = do
+ setConsoleMode h (modeAddVTP mode)
+ modeHasVTP <$> getConsoleMode h
+ `catch` \ (_ :: IOError) ->
+ pure False
+
+ modeHasVTP :: Win32.DWORD -> Bool
+ modeHasVTP mode = mode .&. eNABLE_VIRTUAL_TERMINAL_PROCESSING /= 0
+
+ modeAddVTP :: Win32.DWORD -> Win32.DWORD
+ modeAddVTP mode = mode .|. eNABLE_VIRTUAL_TERMINAL_PROCESSING
+
+eNABLE_VIRTUAL_TERMINAL_PROCESSING :: Win32.DWORD
+eNABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
+
+getConsoleMode :: Win32.HANDLE -> IO Win32.DWORD
+getConsoleMode h = with 64 $ \ mode -> do
+ Win32.failIfFalse_ "GetConsoleMode" (c_GetConsoleMode h mode)
+ peek mode
+
+setConsoleMode :: Win32.HANDLE -> Win32.DWORD -> IO ()
+setConsoleMode h mode = do
+ Win32.failIfFalse_ "SetConsoleMode" (c_SetConsoleMode h mode)
+
+foreign import WINAPI unsafe "windows.h GetConsoleMode" c_GetConsoleMode
+ :: Win32.HANDLE -> Ptr Win32.DWORD -> IO Win32.BOOL
+
+foreign import WINAPI unsafe "windows.h SetConsoleMode" c_SetConsoleMode
+ :: Win32.HANDLE -> Win32.DWORD -> IO Win32.BOOL
+
+#else
+ pure False
+#endif