a576fc3b12
When displaying a ByteString like "💕", safeOutput operates on
individual bytes like "\240\159\146\149" and isControl '\146' = True,
so it got truncated to just "\240".
So, only treat the low control characters, and DEL, as control
characters.
Also split Utility.Terminal out of Utility.SafeOutput. The latter needs
win32, but Utility.SafeOutput is used by Control.Exception, which is
used by Setup.
Sponsored-by: Nicholas Golder-Manning on Patreon
47 lines
980 B
Haskell
47 lines
980 B
Haskell
{- Determining if output is to a terminal.
|
|
-
|
|
- Copyright 2023 Joey Hess <id@joeyh.name>
|
|
-
|
|
- License: BSD-2-clause
|
|
-}
|
|
|
|
{-# LANGUAGE CPP #-}
|
|
{-# OPTIONS_GHC -fno-warn-tabs #-}
|
|
|
|
module Utility.Terminal (
|
|
IsTerminal(..),
|
|
checkIsTerminal,
|
|
) where
|
|
|
|
import Data.Char
|
|
import qualified Data.ByteString as S
|
|
import System.IO
|
|
#ifdef mingw32_HOST_OS
|
|
import System.Win32.MinTTY (isMinTTYHandle)
|
|
import System.Win32.File
|
|
import System.Win32.Types
|
|
import Graphics.Win32.Misc
|
|
import Control.Exception
|
|
#endif
|
|
|
|
newtype IsTerminal = IsTerminal Bool
|
|
|
|
checkIsTerminal :: Handle -> IO IsTerminal
|
|
checkIsTerminal h = do
|
|
#ifndef mingw32_HOST_OS
|
|
b <- hIsTerminalDevice h
|
|
return (IsTerminal b)
|
|
#else
|
|
b <- hIsTerminalDevice h
|
|
if b
|
|
then return (IsTerminal b)
|
|
else do
|
|
h' <- getStdHandle sTD_OUTPUT_HANDLE
|
|
`catch` \(_ :: IOError) ->
|
|
return nullHANDLE
|
|
if h == nullHANDLE
|
|
then return (IsTerminal False)
|
|
else do
|
|
b' <- isMinTTYHandle h'
|
|
return (IsTerminal b)
|
|
#endif
|