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 +6/−0
- LICENSE +1/−1
- README.markdown +16/−0
- src/System/Console/Terminal/Common.hs +24/−0
- src/System/Console/Terminal/Posix.hsc +64/−0
- src/System/Console/Terminal/Size.hs +56/−0
- src/System/Console/Terminal/Size.hsc +0/−99
- src/System/Console/Terminal/Windows.hs +41/−0
- terminal-size.cabal +10/−4
+ 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+=============++[](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})+```
+ 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