    {-# LANGUAGE CPP #-}
    {- |
    Get terminal window height and width without ncurses dependency

    Based on answer by Andreas Hammar at <http://stackoverflow.com/a/12807521/972985>
    -}
    module System.Console.Terminal.Size
      ( Window(..)
      , size
    #if !defined(mingw32_HOST_OS)
      , fdSize
    #endif
      , hSize
      ) where

    import System.Console.Terminal.Common
    #if defined(mingw32_HOST_OS)
    import qualified System.Console.Terminal.Windows as Host
    #else
    import qualified System.Console.Terminal.Posix as Host
    import System.Posix.Types(Fd)
    #endif
    import System.IO(Handle)

    -- | Get terminal window width and height for @stdout@.
    --
    -- >>> import System.Console.Terminal.Size
    -- >>> size
    -- Just (Window {height = 60, width = 112})
    size :: Integral n => IO (Maybe (Window n))
    size :: forall n. Integral n => IO (Maybe (Window n))
    size = IO (Maybe (Window n))
    forall n. Integral n => IO (Maybe (Window n))
    Host.size

    #if !defined(mingw32_HOST_OS)
    -- | /Not available on Windows:/
    -- Get terminal window width and height for a specified file descriptor. If
    -- it's not attached to a terminal then 'Nothing' is returned.
    --
    -- >>> import System.Console.Terminal.Size
    -- >>> import System.Posix
    -- >>> fdSize stdOutput
    -- Just (Window {height = 56, width = 85})
    -- >>> fd <- openFd "foo" ReadWrite (Just stdFileMode) defaultFileFlags
    -- >>> fdSize fd
    -- Nothing
    fdSize :: Integral n => Fd -> IO (Maybe (Window n))
    fdSize :: forall n. Integral n => Fd -> IO (Maybe (Window n))
    fdSize = Fd -> IO (Maybe (Window n))
    forall n. Integral n => Fd -> IO (Maybe (Window n))
    Host.fdSize
    #endif

    -- | Same as 'fdSize', but takes 'Handle' instead of 'Fd' (file descriptor).
    --
    -- Note that on Windows with shells that use the native console API (cmd.exe,
    -- PowerShell) this works only for output handles like 'stdout' and 'stderr';
    -- for input handles like 'stdin' it always returns 'Nothing'.
    --
    -- >>> import System.Console.Terminal.Size
    -- >>> import System.IO
    -- >>> hSize stdout
    -- Just (Window {height = 56, width = 85})
    hSize :: Integral n => Handle -> IO (Maybe (Window n))
    hSize :: forall n. Integral n => Handle -> IO (Maybe (Window n))
    hSize = Handle -> IO (Maybe (Window n))
    forall n. Integral n => Handle -> IO (Maybe (Window n))
    Host.hSize