hidden-char 0.1.0.1 → 0.1.0.2
raw patch · 9 files changed
+280/−246 lines, 9 filessetup-changedPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- LICENSE +20/−20
- README.md +49/−15
- Setup.hs +16/−16
- hidden-char.cabal +47/−47
- src/System/IO/HiddenChar.hs +26/−26
- src/System/IO/HiddenChar/Posix.hs +41/−41
- src/System/IO/HiddenChar/Windows.hs +26/−26
- test/HiddenCharSpec.hs +44/−44
- test/Main.hs +11/−11
LICENSE view
@@ -1,20 +1,20 @@-Copyright (c) 2017 Richard Cook--Permission is hereby granted, free of charge, to any person obtaining-a copy of this software and associated documentation files (the-"Software"), to deal in the Software without restriction, including-without limitation the rights to use, copy, modify, merge, publish,-distribute, sublicense, and/or sell copies of the Software, and to-permit persons to whom the Software is furnished to do so, subject to-the following conditions:--The above copyright notice and this permission notice shall be-included in all copies or substantial portions of the Software.--THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.+Copyright (c) 2017 Richard Cook + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
README.md view
@@ -1,15 +1,49 @@-# `hidden-char`--[](https://travis-ci.org/rcook/hidden-char)-[](http://hackage.haskell.org/package/hidden-char)-[](https://raw.githubusercontent.com/rcook/hidden-char/master/LICENSE)--Provides a `getHiddenChar` function that works on Windows, Linux and macOS--## Licence--[MIT License][licence]--Copyright © 2017, Richard Cook.--[licence]: LICENSE+# `hidden-char` + +[](https://travis-ci.org/rcook/hidden-char) +[](http://hackage.haskell.org/package/hidden-char) +[](https://raw.githubusercontent.com/rcook/hidden-char/master/LICENSE) + +Provides a `getHiddenChar` function that works on Windows, Linux and macOS + +## Dev guide + +This project is built using the [Stack][stack] build tool. + +### Build + +``` +stack build +``` + +### Test + +``` +stack test +``` + +### Upload package + +``` +stack upload . +``` + +### Upload documentation + +``` +script/upload-haddocks +``` + +## Releases + +[View change log for more information][change-log] + +## Licence + +[MIT License][licence] + +Copyright © 2017, Richard Cook. + +[change-log]: CHANGELOG.md +[licence]: LICENSE +[stack]: http://haskellstack.org/
Setup.hs view
@@ -1,16 +1,16 @@-{-|-Module : Main-Description : Setup entrypoint for @hidden-char@-Copyright : (C) Richard Cook, 2017-Licence : MIT-Maintainer : rcook@rcook.org-Stability : stable-Portability : portable--}--module Main (main) where--import Distribution.Simple--main :: IO ()-main = defaultMain+{-| +Module : Main +Description : Setup entrypoint for @hidden-char@ +Copyright : (C) Richard Cook, 2017 +Licence : MIT +Maintainer : rcook@rcook.org +Stability : stable +Portability : portable +-} + +module Main (main) where + +import Distribution.Simple + +main :: IO () +main = defaultMain
@@ -1,47 +1,47 @@-name: hidden-char-version: 0.1.0.1-synopsis: Provides getHiddenChar function-description: Provides a @getHiddenChar@ function that works on Windows, Linux and macOS-homepage: https://github.com/rcook/hidden-char#readme-license: MIT-license-file: LICENSE-author: Richard Cook-maintainer: rcook@rcook.org-copyright: 2017 Richard Cook-category: Command Line Tool-build-type: Simple-cabal-version: >= 1.10-extra-source-files: README.md--library- default-language: Haskell2010- ghc-options: -W -Wall- hs-source-dirs: src- build-depends: base >= 4.7 && < 5- exposed-modules: System.IO.HiddenChar- if os(linux)- cpp-options: -DOS_LINUX- other-modules: System.IO.HiddenChar.Posix- if os(windows)- cpp-options: -DOS_WINDOWS- other-modules: System.IO.HiddenChar.Windows- if os(darwin)- cpp-options: -DOS_MACOS- other-modules: System.IO.HiddenChar.Posix--test-suite hidden-char-test- type: exitcode-stdio-1.0- default-language: Haskell2010- ghc-options: -W -Wall -threaded- hs-source-dirs: test- main-is: Main.hs- build-depends: base >= 4.7 && < 5- , hidden-char- , hspec- if os(linux)- cpp-options: -DOS_LINUX- if os(windows)- cpp-options: -DOS_WINDOWS- if os(darwin)- cpp-options: -DOS_MACOS- other-modules: HiddenCharSpec+name: hidden-char +version: 0.1.0.2 +synopsis: Provides getHiddenChar function +description: Provides a @getHiddenChar@ function that works on Windows, Linux and macOS +homepage: https://github.com/rcook/hidden-char#readme +license: MIT +license-file: LICENSE +author: Richard Cook +maintainer: rcook@rcook.org +copyright: 2017 Richard Cook +category: Command Line Tool +build-type: Simple +cabal-version: >= 1.10 +extra-source-files: README.md + +library + default-language: Haskell2010 + ghc-options: -W -Wall + hs-source-dirs: src + build-depends: base >= 4.7 && < 5 + exposed-modules: System.IO.HiddenChar + if os(linux) + cpp-options: -DOS_LINUX + other-modules: System.IO.HiddenChar.Posix + if os(windows) + cpp-options: -DOS_WINDOWS + other-modules: System.IO.HiddenChar.Windows + if os(darwin) + cpp-options: -DOS_MACOS + other-modules: System.IO.HiddenChar.Posix + +test-suite hidden-char-test + type: exitcode-stdio-1.0 + default-language: Haskell2010 + ghc-options: -W -Wall -threaded + hs-source-dirs: test + main-is: Main.hs + build-depends: base >= 4.7 && < 5 + , hidden-char + , hspec + if os(linux) + cpp-options: -DOS_LINUX + if os(windows) + cpp-options: -DOS_WINDOWS + if os(darwin) + cpp-options: -DOS_MACOS + other-modules: HiddenCharSpec
src/System/IO/HiddenChar.hs view
@@ -1,26 +1,26 @@-{-|-Module : System.IO.HiddenChar-Description : Umbrella module for @System.IO.HiddenChar@-Copyright : (C) Richard Cook, 2017-Licence : MIT-Maintainer : rcook@rcook.org-Stability : stable-Portability : portable--This package provides a @getHiddenChar@ function which works reasonably-consistently across the Windows, Linux and macOS platforms. @getHiddenChar@-yields a single character from the standard input device with buffering and-echoing to standard output disabled.--}--{-# LANGUAGE CPP #-}--module System.IO.HiddenChar (getHiddenChar) where--#if defined(OS_LINUX) || defined(OS_MACOS)-import System.IO.HiddenChar.Posix-#elif defined(OS_WINDOWS)-import System.IO.HiddenChar.Windows-#else-#error Unsupported platform-#endif+{-| +Module : System.IO.HiddenChar +Description : Umbrella module for @System.IO.HiddenChar@ +Copyright : (C) Richard Cook, 2017 +Licence : MIT +Maintainer : rcook@rcook.org +Stability : stable +Portability : portable + +This package provides a @getHiddenChar@ function which works reasonably +consistently across the Windows, Linux and macOS platforms. @getHiddenChar@ +yields a single character from the standard input device with buffering and +echoing to standard output disabled. +-} + +{-# LANGUAGE CPP #-} + +module System.IO.HiddenChar (getHiddenChar) where + +#if defined(OS_LINUX) || defined(OS_MACOS) +import System.IO.HiddenChar.Posix +#elif defined(OS_WINDOWS) +import System.IO.HiddenChar.Windows +#else +#error Unsupported platform +#endif
src/System/IO/HiddenChar/Posix.hs view
@@ -1,41 +1,41 @@-{-|-Module : System.IO.HiddenChar.Posix-Description : Posix implementation of @getHiddenChar@-Copyright : (C) Richard Cook, 2017-Licence : MIT-Maintainer : rcook@rcook.org-Stability : stable-Portability : portable--}--module System.IO.HiddenChar.Posix (getHiddenChar) where--import Control.Exception-import System.IO--data HandleState = HandleState BufferMode Bool--hGetState :: Handle -> IO HandleState-hGetState h = do- bufferMode <- hGetBuffering h- isEcho <- hGetEcho h- return $ HandleState bufferMode isEcho--hSetState :: Handle -> HandleState -> IO ()-hSetState h (HandleState mode isEcho) = do- hSetEcho h isEcho- hSetBuffering h mode--bracketHandle :: Handle -> (IO a -> IO a)-bracketHandle h action = bracket- (hGetState h)- (hSetState h)- (const action)---- | Read a character from the standard input device with buffering and echoing disabled-getHiddenChar ::- IO Char -- ^ returned character-getHiddenChar = bracketHandle stdin $ do- hSetBuffering stdin NoBuffering- hSetEcho stdin False- getChar+{-| +Module : System.IO.HiddenChar.Posix +Description : Posix implementation of @getHiddenChar@ +Copyright : (C) Richard Cook, 2017 +Licence : MIT +Maintainer : rcook@rcook.org +Stability : stable +Portability : portable +-} + +module System.IO.HiddenChar.Posix (getHiddenChar) where + +import Control.Exception +import System.IO + +data HandleState = HandleState BufferMode Bool + +hGetState :: Handle -> IO HandleState +hGetState h = do + bufferMode <- hGetBuffering h + isEcho <- hGetEcho h + return $ HandleState bufferMode isEcho + +hSetState :: Handle -> HandleState -> IO () +hSetState h (HandleState mode isEcho) = do + hSetEcho h isEcho + hSetBuffering h mode + +bracketHandle :: Handle -> (IO a -> IO a) +bracketHandle h action = bracket + (hGetState h) + (hSetState h) + (const action) + +-- | Read a character from the standard input device with buffering and echoing disabled +getHiddenChar :: + IO Char -- ^ returned character +getHiddenChar = bracketHandle stdin $ do + hSetBuffering stdin NoBuffering + hSetEcho stdin False + getChar
src/System/IO/HiddenChar/Windows.hs view
@@ -1,26 +1,26 @@-{-|-Module : System.IO.HiddenChar.Windows-Description : Windows implementation of @getHiddenChar@-Copyright : (C) Richard Cook, 2017-Licence : MIT-Maintainer : rcook@rcook.org-Stability : stable-Portability : portable--}--{-# LANGUAGE ForeignFunctionInterface #-}--module System.IO.HiddenChar.Windows (getHiddenChar) where--import Data.Char-import Foreign.C.Types---- Must import as "safe" in order to prevent FFI call from blocking other threads--- https://github.com/rcook/hidden-char/issues/1-foreign import ccall safe "conio.h getch" c_getch :: IO CInt---- | Read a character from the standard input device with buffering and echoing disabled--- Hack based on http://stackoverflow.com/questions/2983974/haskell-read-input-character-from-console-immediately-not-after-newline-getHiddenChar ::- IO Char -- ^ returned character-getHiddenChar = fmap (chr . fromEnum) c_getch+{-| +Module : System.IO.HiddenChar.Windows +Description : Windows implementation of @getHiddenChar@ +Copyright : (C) Richard Cook, 2017 +Licence : MIT +Maintainer : rcook@rcook.org +Stability : stable +Portability : portable +-} + +{-# LANGUAGE ForeignFunctionInterface #-} + +module System.IO.HiddenChar.Windows (getHiddenChar) where + +import Data.Char +import Foreign.C.Types + +-- Must import as "safe" in order to prevent FFI call from blocking other threads +-- https://github.com/rcook/hidden-char/issues/1 +foreign import ccall safe "conio.h _getch" c_getch :: IO CInt + +-- | Read a character from the standard input device with buffering and echoing disabled +-- Hack based on http://stackoverflow.com/questions/2983974/haskell-read-input-character-from-console-immediately-not-after-newline +getHiddenChar :: + IO Char -- ^ returned character +getHiddenChar = fmap (chr . fromEnum) c_getch
test/HiddenCharSpec.hs view
@@ -1,45 +1,45 @@-{-|-Module : HiddenCharSpec-Description : Tests for @System.IO.HiddenChar@ module-Copyright : (C) Richard Cook, 2017-Licence : MIT-Maintainer : rcook@rcook.org-Stability : stable-Portability : portable--}--{-# LANGUAGE ScopedTypeVariables #-}--module HiddenCharSpec (spec) where--import Control.Concurrent-import Control.Exception-import System.IO.HiddenChar-import System.Timeout-import Test.Hspec--spec :: Spec-spec = do- describe "concurrent use of getHiddenChar" $- it "doesn't block other threads" $ do- -- Run getHiddenChar in a bound thread and swallow all exceptions- _ <- forkOS $ do- _ <- getHiddenChar `catch` (\(_ :: SomeException) -> return ' ')- return ()-- -- On another bound thread, count up to a given value with a small- -- delay at each step. runInBoundThread should terminate and return- -- the expected value if getHiddenChar works correctly. In the presence- -- of calls to functions via the "unsafe", then this thread will block.- -- This is a behaviour we would like to avoid.- -- https://github.com/rcook/hidden-char/issues/1- let countUpTo :: Int -> IO Int- countUpTo n = helper n n- where- helper n' i- | i == 0 = return n'- | otherwise = do- threadDelay 1- helper n' (i - 1)- result <- timeout 1000000 $ runInBoundThread (countUpTo 5)+{-| +Module : HiddenCharSpec +Description : Tests for @System.IO.HiddenChar@ module +Copyright : (C) Richard Cook, 2017 +Licence : MIT +Maintainer : rcook@rcook.org +Stability : stable +Portability : portable +-} + +{-# LANGUAGE ScopedTypeVariables #-} + +module HiddenCharSpec (spec) where + +import Control.Concurrent +import Control.Exception +import System.IO.HiddenChar +import System.Timeout +import Test.Hspec + +spec :: Spec +spec = do + describe "concurrent use of getHiddenChar" $ + it "doesn't block other threads" $ do + -- Run getHiddenChar in a bound thread and swallow all exceptions + _ <- forkOS $ do + _ <- getHiddenChar `catch` (\(_ :: SomeException) -> return ' ') + return () + + -- On another bound thread, count up to a given value with a small + -- delay at each step. runInBoundThread should terminate and return + -- the expected value if getHiddenChar works correctly. In the presence + -- of calls to functions via the "unsafe" FFI, then this thread will + -- block. This is a behaviour we would like to avoid. + -- https://github.com/rcook/hidden-char/issues/1 + let countUpTo :: Int -> IO Int + countUpTo n = helper n n + where + helper n' i + | i == 0 = return n' + | otherwise = do + threadDelay 1 + helper n' (i - 1) + result <- timeout 1000000 $ runInBoundThread (countUpTo 5) result `shouldBe` Just 5
test/Main.hs view
@@ -1,11 +1,11 @@-{-|-Module : Main-Description : Main entrypoint for @hidden-char@ tests-Copyright : (C) Richard Cook, 2017-Licence : MIT-Maintainer : rcook@rcook.org-Stability : stable-Portability : portable--}--{-# OPTIONS_GHC -F -pgmF hspec-discover #-}+{-| +Module : Main +Description : Main entrypoint for @hidden-char@ tests +Copyright : (C) Richard Cook, 2017 +Licence : MIT +Maintainer : rcook@rcook.org +Stability : stable +Portability : portable +-} + +{-# OPTIONS_GHC -F -pgmF hspec-discover #-}