terminal-size 0.3.3 → 0.3.4
raw patch · 5 files changed
+98/−63 lines, 5 filesdep +Win32
Dependencies added: Win32
Files
- CHANGELOG.markdown +5/−0
- README.markdown +42/−1
- src/System/Console/Terminal/Size.hs +8/−5
- src/System/Console/Terminal/Windows.hs +39/−54
- terminal-size.cabal +4/−3
CHANGELOG.markdown view
@@ -1,3 +1,8 @@+0.3.4+=====++ * Provided `hSize` on Windows. (https://github.com/biegunka/terminal-size/pull/18)+ 0.3.3 =====
README.markdown view
@@ -1,7 +1,7 @@ terminal-size ============= -[](https://hackage.haskell.org/package/terminal-size)+[](https://hackage.haskell.org/package/terminal-size) [](https://travis-ci.org/biegunka/terminal-size) Get terminal window width and height@@ -13,4 +13,45 @@ >>> 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/Size.hs view
@@ -9,8 +9,8 @@ , size #if !defined(mingw32_HOST_OS) , fdSize- , hSize #endif+ , hSize ) where import System.Console.Terminal.Common@@ -19,8 +19,8 @@ #else import qualified System.Console.Terminal.Posix as Host import System.Posix.Types(Fd)-import System.IO(Handle) #endif+import System.IO(Handle) -- | Get terminal window width and height for @stdout@.@@ -45,14 +45,17 @@ -- Nothing fdSize :: Integral n => Fd -> IO (Maybe (Window n)) fdSize = Host.fdSize+#endif --- | /Not available on Windows:/--- Same as 'fdSize', but takes 'Handle' instead of 'Fd' (file descriptor).+-- | 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-#endif
src/System/Console/Terminal/Windows.hs view
@@ -1,63 +1,48 @@--module System.Console.Terminal.Windows(size) where+module System.Console.Terminal.Windows(size, hSize) where import System.Console.Terminal.Common -import Control.Monad-import Data.Word-import Foreign.Ptr-import Foreign.Storable-import Foreign.Marshal.Alloc import System.Exit import System.IO+import System.IO.Error (catchIOError) import System.Process--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+import System.Win32.Console+ ( CONSOLE_SCREEN_BUFFER_INFO(srWindow)+ , SMALL_RECT(..)+ , getConsoleScreenBufferInfo+ )+import System.Win32.Types (HANDLE, withHandleToHANDLE) -foreign import stdcall unsafe "windows.h GetStdHandle"- c_GetStdHandle :: Word32 -> IO HANDLE+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 -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 do -- This could happen on Cygwin or MSYS- let stty = (shell "stty size") {- std_in = UseHandle stdin- , std_out = CreatePipe- , std_err = CreatePipe- }- (_, mbStdout, _, rStty) <- createProcess stty- exStty <- waitForProcess rStty- case exStty of- ExitFailure _ -> return Nothing- ExitSuccess ->- maybe (return Nothing)- (\hSize -> do- sizeStr <- hGetContents hSize- let [r, c] = map read $ words sizeStr :: [Int]- return $ Just $ Window (fromIntegral r) (fromIntegral c)- )- mbStdout- 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)+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,5 +1,5 @@ name: terminal-size-version: 0.3.3+version: 0.3.4 synopsis: Get terminal window height and width description: Get terminal window height and width without ncurses dependency.@@ -21,7 +21,7 @@ source-repository this type: git location: https://github.com/biegunka/terminal-size- tag: 0.3.3+ tag: 0.3.4 library default-language:@@ -34,7 +34,8 @@ ghc-prim if os(windows) build-depends:- process+ process,+ Win32 >= 2.13.2.0 && < 2.14 build-tools: hsc2hs