packages feed

terminal-size 0.2.1.0 → 0.3.0

raw patch · 9 files changed

+218/−104 lines, 9 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- System.Console.Terminal.Size: instance Functor Window
- System.Console.Terminal.Size: instance Read a => Read (Window a)
- System.Console.Terminal.Size: instance Show a => Show (Window a)
- System.Console.Terminal.Size: instance Storable CWin

Files

+ CHANGELOG.markdown view
@@ -0,0 +1,6 @@+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-2014, Matvey Aksenov  All rights reserved. 
+ README.markdown view
@@ -0,0 +1,16 @@+terminal-size+=============++[![Hackage](https://budueba.com/hackage/terminal-size)](https://hackage.haskell.org/package/terminal-size)+[![Build Status](https://travis-ci.org/biegunka/terminal-size.png)](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})+```
+ src/System/Console/Terminal/Common.hs view
@@ -0,0 +1,24 @@++module System.Console.Terminal.Common+  ( Window(..)+  ) where++import Control.Applicative+import Data.Foldable (Foldable(..))+import Data.Traversable (Traversable(..))+import Data.Monoid (mappend)++-- | Terminal window width and height+data Window a = Window+  { height :: !a+  , width  :: !a+  } deriving (Show, Eq, Read)++instance Functor Window where+  fmap f (Window { height = h, width = w }) = Window { height = f h, width = f w }++instance Foldable Window where+  foldMap f (Window { height = h, width = w }) = f h `mappend` f w++instance Traversable Window where+  traverse f (Window { height = h, width = w }) = Window <$> f h <*> f w
+ src/System/Console/Terminal/Posix.hsc view
@@ -0,0 +1,64 @@++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>+++#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+++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++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,56 @@+{-# 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, hSize+#endif+  ) 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)+import System.IO(Handle)+#endif+++-- | 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++-- | /Not available on Windows:/+--   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 = Host.hSize+#endif
− 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,41 @@++module System.Console.Terminal.Windows(size) where++import System.Console.Terminal.Common++import Control.Monad+import Data.Word+import Foreign.Ptr+import Foreign.Storable+import Foreign.Marshal.Alloc++type HANDLE = Ptr ()++data CONSOLE_SCREEN_BUFFER_INFO++sizeCONSOLE_SCREEN_BUFFER_INFO :: Int+sizeCONSOLE_SCREEN_BUFFER_INFO = 22++posCONSOLE_SCREEN_BUFFER_INFO_srWindow :: Int+posCONSOLE_SCREEN_BUFFER_INFO_srWindow = 10 -- 4 x Word16 Left,Top,Right,Bottom++c_STD_OUTPUT_HANDLE :: Word32+c_STD_OUTPUT_HANDLE = -11++foreign import stdcall unsafe "windows.h GetConsoleScreenBufferInfo"+    c_GetConsoleScreenBufferInfo :: HANDLE -> Ptr CONSOLE_SCREEN_BUFFER_INFO -> IO Bool++foreign import stdcall unsafe "windows.h GetStdHandle"+    c_GetStdHandle :: Word32 -> IO HANDLE+++size :: Integral n => IO (Maybe (Window n))+size = do+    hdl <- c_GetStdHandle c_STD_OUTPUT_HANDLE+    allocaBytes sizeCONSOLE_SCREEN_BUFFER_INFO $ \p -> do+        b <- c_GetConsoleScreenBufferInfo hdl p+        if not b then return Nothing else do+            [left,top,right,bottom] <- forM [0..3] $ \i -> do+                v <- peekByteOff p ((i*2) + posCONSOLE_SCREEN_BUFFER_INFO_srWindow)+                return $ fromIntegral (v :: Word16)+            return $ Just $ Window (1+bottom-top) (1+right-left)
terminal-size.cabal view
@@ -1,10 +1,8 @@ name:                terminal-size-version:             0.2.1.0+version:             0.3.0 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,6 +10,9 @@ category:            System build-type:          Simple cabal-version:       >= 1.10+extra-source-files:+  README.markdown+  CHANGELOG.markdown  library   default-language:  Haskell2010@@ -19,6 +20,11 @@   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