terminal-size 0.2.1.0 → 0.3.4
raw patch · 9 files changed
Files
- CHANGELOG.markdown +36/−0
- LICENSE +1/−1
- README.markdown +57/−0
- src/System/Console/Terminal/Common.hs +45/−0
- src/System/Console/Terminal/Posix.hsc +65/−0
- src/System/Console/Terminal/Size.hs +61/−0
- src/System/Console/Terminal/Size.hsc +0/−99
- src/System/Console/Terminal/Windows.hs +48/−0
- terminal-size.cabal +44/−13
+ CHANGELOG.markdown view
@@ -0,0 +1,36 @@+0.3.4+=====++ * Provided `hSize` on Windows. (https://github.com/biegunka/terminal-size/pull/18)++0.3.3+=====++ * Fixed ioctl foreign import. (https://github.com/biegunka/terminal-size/pull/16)++ * `#alignment` is a hsc2hs built-in since some unspecified GHC 7.x. (https://github.com/biegunka/terminal-size/pull/12)++ * Captured possible `stty` stderr output with a pipe. (https://github.com/biegunka/terminal-size/pull/13)+++0.3.2.1+=======++ * GHC 7.2 support (https://github.com/biegunka/terminal-size/pull/9)++0.3.2+=====++ * Cygwin/MSYS support (https://github.com/biegunka/terminal-size/pull/8)++0.3.1+=====++ * `Typeable`, `Data`, `Generic`, and `Generic1` instances for `Window`.++0.3.0+=====++ * Windows support (https://github.com/biegunka/terminal-size/pull/4)++ * Added `Eq`, `Foldable` and `Traversable` instances for `Window`
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2013, Matvey Aksenov+Copyright (c) 2013-2015, Matvey Aksenov All rights reserved.
+ README.markdown view
@@ -0,0 +1,57 @@+terminal-size+=============++[](https://hackage.haskell.org/package/terminal-size)+[](https://travis-ci.org/biegunka/terminal-size)++Get terminal window width and height++Usage+-----++```+>>> import System.Console.Terminal.Size+>>> size+Just (Window {height = 60, width = 112})+```++Test+----++Compile test.hs and run it in a terminal. Here is what I get on Linux:++```+> ghc test.hs+> ./test+With redirected stdin+ hSize stdin = Nothing+ hSize stdout = Just (Window {height = 19, width = 87})+ hSize stderr = Just (Window {height = 19, width = 87})+With redirected stdout+ hSize stdin = Just (Window {height = 19, width = 87})+ hSize stdout = Nothing+ hSize stderr = Just (Window {height = 19, width = 87})+With redirected stderr+ hSize stdin = Just (Window {height = 19, width = 87})+ hSize stdout = Just (Window {height = 19, width = 87})+ hSize stderr = Nothing+```++On MINGW/MSYS the output is the same.++On Windows with cmd.exe I get++```+With redirected stdin+ hSize stdin = Nothing+ hSize stdout = Just (Window {height = 40, width = 164})+ hSize stderr = Just (Window {height = 40, width = 164})+With redirected stdout+ hSize stdin = Nothing+ hSize stdout = Nothing+ hSize stderr = Just (Window {height = 40, width = 164})+With redirected stderr+ hSize stdin = Nothing+ hSize stdout = Just (Window {height = 40, width = 164})+ hSize stderr = Nothing+```
+ src/System/Console/Terminal/Common.hs view
@@ -0,0 +1,45 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveTraversable #-}++#if __GLASGOW_HASKELL__ >= 702+#define LANGUAGE_DeriveGeneric+{-# LANGUAGE DeriveGeneric #-}+#endif++module System.Console.Terminal.Common+ ( Window(..)+ ) where++import Data.Data (Typeable, Data)++#if __GLASGOW_HASKELL__ < 710+import Data.Foldable (Foldable)+import Data.Traversable (Traversable)+#endif++#ifdef LANGUAGE_DeriveGeneric+import GHC.Generics+ ( Generic+#if __GLASGOW_HASKELL__ >= 706+ , Generic1+#endif+ )+#endif++-- | Terminal window width and height+data Window a = Window+ { height :: !a+ , width :: !a+ } deriving+ ( Show, Eq, Read, Data, Typeable+ , Foldable, Functor, Traversable+#ifdef LANGUAGE_DeriveGeneric+ , Generic+#if __GLASGOW_HASKELL__ >= 706+ , Generic1+#endif+#endif+ )
+ src/System/Console/Terminal/Posix.hsc view
@@ -0,0 +1,65 @@+{-# LANGUAGE CApiFFI #-}++module System.Console.Terminal.Posix+ ( size, fdSize, hSize+ ) where++import System.Console.Terminal.Common+import Control.Exception (catch)+import Data.Typeable (cast)+import Foreign+import Foreign.C.Error+import Foreign.C.Types+import GHC.IO.FD (FD(FD, fdFD))+import GHC.IO.Handle.Internals (withHandle_)+import GHC.IO.Handle.Types (Handle, Handle__(Handle__, haDevice))+#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ < 706)+import Prelude hiding (catch)+#endif+import System.Posix.Types (Fd(Fd))++#include <sys/ioctl.h>+#include <unistd.h>++#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ < 800)+#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)+#endif++-- Interesting part of @struct winsize@+data CWin = CWin CUShort CUShort++instance Storable CWin where+ sizeOf _ = (#size struct winsize)+ alignment _ = (#alignment struct winsize)+ peek ptr = do+ row <- (#peek struct winsize, ws_row) ptr+ col <- (#peek struct winsize, ws_col) ptr+ return $ CWin row col+ poke ptr (CWin row col) = do+ (#poke struct winsize, ws_row) ptr row+ (#poke struct winsize, ws_col) ptr col+++fdSize :: Integral n => Fd -> IO (Maybe (Window n))+fdSize (Fd fd) = with (CWin 0 0) $ \ws -> do+ throwErrnoIfMinus1 "ioctl" $+ ioctl fd (#const TIOCGWINSZ) ws+ CWin row col <- peek ws+ return . Just $ Window (fromIntegral row) (fromIntegral col)+ `catch`+ handler+ where+ handler :: IOError -> IO (Maybe (Window h))+ handler _ = return Nothing++foreign import capi "sys/ioctl.h ioctl"+ ioctl :: CInt -> CULong -> Ptr CWin -> IO CInt++size :: Integral n => IO (Maybe (Window n))+size = fdSize (Fd (#const STDOUT_FILENO))++hSize :: Integral n => Handle -> IO (Maybe (Window n))+hSize h = withHandle_ "hSize" h $ \Handle__ { haDevice = dev } ->+ case cast dev of+ Nothing -> return Nothing+ Just FD { fdFD = fd } -> fdSize (Fd fd)
+ src/System/Console/Terminal/Size.hs view
@@ -0,0 +1,61 @@+{-# 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 = 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 = 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 = Host.hSize
− src/System/Console/Terminal/Size.hsc
@@ -1,99 +0,0 @@-{- |-Get terminal window height and width without ncurses dependency--Only tested to work on GNU/Linux systems--Based on answer by Andreas Hammar at <http://stackoverflow.com/a/12807521/972985>--}-module System.Console.Terminal.Size- ( Window(..), size, fdSize, hSize- ) where--import Control.Exception (catch)-import Data.Typeable (cast)-import Foreign-import Foreign.C.Error-import Foreign.C.Types-import GHC.IO.FD (FD(FD, fdFD))-import GHC.IO.Handle.Internals (withHandle_)-import GHC.IO.Handle.Types (Handle, Handle__(Handle__, haDevice))-#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ < 706)-import Prelude hiding (catch)-#endif-import System.Posix.Types (Fd(Fd))--#include <sys/ioctl.h>-#include <unistd.h>---#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)----- Interesting part of @struct winsize@-data CWin = CWin CUShort CUShort--instance Storable CWin where- sizeOf _ = (#size struct winsize)- alignment _ = (#alignment struct winsize)- peek ptr = do- row <- (#peek struct winsize, ws_row) ptr- col <- (#peek struct winsize, ws_col) ptr- return $ CWin row col- poke ptr (CWin row col) = do- (#poke struct winsize, ws_row) ptr row- (#poke struct winsize, ws_col) ptr col----- | Terminal window width and height-data Window a = Window- { height :: !a- , width :: !a- } deriving (Show, Read)--instance Functor Window where- fmap f (Window { height = h, width = w }) = Window { height = f h, width = f w }---- | 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 (Fd fd) = with (CWin 0 0) $ \ws -> do- throwErrnoIfMinus1 "ioctl" $- ioctl fd (#const TIOCGWINSZ) ws- CWin row col <- peek ws- return . Just $ Window (fromIntegral row) (fromIntegral col)- `catch`- handler- where- handler :: IOError -> IO (Maybe (Window h))- handler _ = return Nothing--foreign import ccall "sys/ioctl.h ioctl"- ioctl :: CInt -> CInt -> Ptr CWin -> IO CInt---- | 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 = fdSize (Fd (#const STDOUT_FILENO))---- | Same as 'fdSize', but takes 'Handle' instead of 'Fd' (file descriptor).------ >>> 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 h = withHandle_ "hSize" h $ \Handle__ { haDevice = dev } ->- case cast dev of- Nothing -> return Nothing- Just FD { fdFD = fd } -> fdSize (Fd fd)
+ src/System/Console/Terminal/Windows.hs view
@@ -0,0 +1,48 @@+module System.Console.Terminal.Windows(size, hSize) where++import System.Console.Terminal.Common++import System.Exit+import System.IO+import System.IO.Error (catchIOError)+import System.Process+import System.Win32.Console+ ( CONSOLE_SCREEN_BUFFER_INFO(srWindow)+ , SMALL_RECT(..)+ , getConsoleScreenBufferInfo+ )+import System.Win32.Types (HANDLE, withHandleToHANDLE)++size :: Integral n => IO (Maybe (Window n))+size = hSize stdout++hSize :: Integral n => Handle -> IO (Maybe (Window n))+hSize hdl =+ withHandleToHANDLE hdl nativeSize+ `catchIOError` \_ -> do+ -- Fallback to use for Cygwin or MSYS+ let stty = (shell "stty size") {+ std_in = UseHandle hdl+ , std_out = CreatePipe+ , std_err = CreatePipe+ }+ (_, mbStdout, _, rStty) <- createProcess stty+ exStty <- waitForProcess rStty+ case exStty of+ ExitFailure _ -> return Nothing+ ExitSuccess ->+ maybe (return Nothing)+ (\out -> do+ sizeStr <- hGetContents out+ let [r, c] = map read $ words sizeStr :: [Int]+ return $ Just $ Window (fromIntegral r) (fromIntegral c)+ )+ mbStdout++nativeSize :: Integral n => HANDLE -> IO (Maybe (Window n))+nativeSize hdl = do+ rect <- srWindow <$> getConsoleScreenBufferInfo hdl+ return $ Just $ Window+ { height = fromIntegral (1 + bottomPos rect - topPos rect)+ , width = fromIntegral (1 + rightPos rect - leftPos rect)+ }
terminal-size.cabal view
@@ -1,10 +1,8 @@ name: terminal-size-version: 0.2.1.0+version: 0.3.4 synopsis: Get terminal window height and width description:- Get terminal window height and width without ncurses dependency- .- Only tested to work on GNU/Linux systems+ Get terminal window height and width without ncurses dependency. license: BSD3 license-file: LICENSE author: Andreas Hammar, Matvey Aksenov@@ -12,16 +10,49 @@ category: System build-type: Simple cabal-version: >= 1.10--library- default-language: Haskell2010- build-depends: base >= 4 && < 5- build-tools: hsc2hs- hs-source-dirs: src- exposed-modules: System.Console.Terminal.Size- ghc-options: -Wall- -fno-warn-unused-do-bind+extra-source-files:+ README.markdown+ CHANGELOG.markdown source-repository head type: git location: https://github.com/biegunka/terminal-size++source-repository this+ type: git+ location: https://github.com/biegunka/terminal-size+ tag: 0.3.4++library+ default-language:+ Haskell2010++ build-depends:+ base >= 4 && < 5+ if impl(ghc >= 7.2 && < 7.6)+ build-depends:+ ghc-prim+ if os(windows)+ build-depends:+ process,+ Win32 >= 2.13.2.0 && < 2.14++ build-tools:+ hsc2hs+ hs-source-dirs:+ src+ exposed-modules:+ System.Console.Terminal.Size++ other-modules:+ System.Console.Terminal.Common+ if os(Windows)+ other-modules:+ System.Console.Terminal.Windows+ else+ other-modules:+ System.Console.Terminal.Posix++ ghc-options:+ -Wall+ -fno-warn-unused-do-bind