ghcid 0.8.7 → 0.8.8
raw patch · 11 files changed
+58/−30 lines, 11 filesdep ~fsnotifyPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: fsnotify
API changes (from Hackage documentation)
Files
- CHANGES.txt +4/−0
- LICENSE +1/−1
- README.md +4/−2
- ghcid.cabal +6/−5
- src/Ghcid.hs +18/−12
- src/Language/Haskell/Ghcid.hs +2/−2
- src/Test.hs +1/−1
- src/Test/API.hs +2/−1
- src/Test/Common.hs +13/−0
- src/Test/Ghcid.hs +3/−2
- src/Wait.hs +4/−4
CHANGES.txt view
@@ -1,5 +1,9 @@ Changelog for ghcid (* = breaking change) +0.8.8, released 2022-09-17+ #365, support fsnotify 0.4+ #348, improve the no files loaded message+ #321, print Ghcide has stopped to the output file. 0.8.7, released 2020-06-06 #319, allow eval multiline commands 0.8.6, released 2020-04-13
LICENSE view
@@ -1,4 +1,4 @@-Copyright Neil Mitchell 2014-2020.+Copyright Neil Mitchell 2014-2022. All rights reserved. Redistribution and use in source and binary forms, with or without
README.md view
@@ -1,4 +1,4 @@-# ghcid [](https://hackage.haskell.org/package/ghcid) [](https://www.stackage.org/package/ghcid) [](https://travis-ci.org/ndmitchell/ghcid) [](https://ci.appveyor.com/project/ndmitchell/ghcid)+# ghcid [](https://hackage.haskell.org/package/ghcid) [](https://www.stackage.org/package/ghcid) [](https://github.com/ndmitchell/ghcid/actions) Either "GHCi as a daemon" or "GHC + a bit of an IDE". To a first approximation, it opens `ghci` and runs `:reload` whenever your source code changes, formatting the output to fit a fixed height console. Unlike other Haskell development tools, `ghcid` is intended to be _incredibly simple_. In particular, it doesn't integrate with any editors, doesn't provide access to the `ghci` it starts, doesn't depend on GHC the library and doesn't start web servers. @@ -62,6 +62,8 @@ exprN <$ -} +Expressions that read from standard input are likely to hang, given that Ghcid already uses the standard input to interact with Ghci.+ ### FAQ #### This isn't as good as full IDE@@ -103,6 +105,6 @@ `ghcid ... --test Main.main --setup ":set args myargs"` -#### Why do I get "addWatch: resource exhausted (No space left on device)" on my Mac?+#### Why do I get "addWatch: resource exhausted (No space left on device)" or "openFile: resource exhausted (Too many open files)" on my Mac? The Mac has a fairly low limit on the number of file handles available. You can increase it with: `sudo sysctl -w fs.inotify.max_user_watches=262144; sudo sysctl -p`
ghcid.cabal view
@@ -1,19 +1,19 @@-cabal-version: >= 1.18+cabal-version: 1.18 build-type: Simple name: ghcid-version: 0.8.7+version: 0.8.8 license: BSD3 license-file: LICENSE category: Development author: Neil Mitchell <ndmitchell@gmail.com>, jpmoresmau maintainer: Neil Mitchell <ndmitchell@gmail.com>-copyright: Neil Mitchell 2014-2020+copyright: Neil Mitchell 2014-2022 synopsis: GHCi based bare bones IDE description: Either \"GHCi as a daemon\" or \"GHC + a bit of an IDE\". A very simple Haskell development tool which shows you the errors in your project and updates them whenever you save. Run @ghcid --topmost --command=ghci@, where @--topmost@ makes the window on top of all others (Windows only) and @--command@ is the command to start GHCi on your project (defaults to @ghci@ if you have a @.ghci@ file, or else to @cabal repl@). homepage: https://github.com/ndmitchell/ghcid#readme bug-reports: https://github.com/ndmitchell/ghcid/issues-tested-with: GHC==8.10.1, GHC==8.8.3, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2+tested-with: GHC==9.0, GHC==8.10, GHC==8.8, GHC==8.6 extra-doc-files: CHANGES.txt README.md@@ -55,7 +55,7 @@ time >= 1.5, directory >= 1.2, containers,- fsnotify,+ fsnotify >= 0.4, extra >= 1.6.20, process >= 1.1, cmdargs >= 0.10,@@ -111,6 +111,7 @@ Paths_ghcid Session Test.API+ Test.Common Test.Ghcid Test.Parser Test.Util
src/Ghcid.hs view
@@ -94,7 +94,7 @@ ,topmost = False &= name "t" &= help "Set window topmost (Windows only)" ,no_title = False &= help "Don't update the shell title/icon" ,project = "" &= typ "NAME" &= help "Name of the project, defaults to current directory"- ,restart = [] &= typ "PATH" &= help "Restart the command when the given file or directory contents change (defaults to .ghci and any .cabal file)"+ ,restart = [] &= typ "PATH" &= help "Restart the command when the given file or directory contents change (defaults to .ghci and any .cabal file, unless when using stack or a custom command)" ,reload = [] &= typ "PATH" &= help "Reload when the given file or directory contents change (defaults to none)" ,directory = "." &= typDir &= name "C" &= help "Set the current directory" ,outputfile = [] &= typFile &= name "o" &= help "File to write the full output to"@@ -201,10 +201,23 @@ Nothing -> "" exitFailure +printStopped :: Options -> IO ()+printStopped opts =+ forM_ (outputfile opts) $ \file -> do+ writeFile file "Ghcid has stopped.\n"++ -- | Like 'main', but run with a fake terminal for testing mainWithTerminal :: IO TermSize -> ([String] -> IO ()) -> IO ()-mainWithTerminal termSize termOutput =- handleErrors $+mainWithTerminal termSize termOutput = do+ opts <- withGhcidArgs $ cmdArgsRun options+ whenLoud $ do+ outStrLn $ "%OS: " ++ os+ outStrLn $ "%ARCH: " ++ arch+ outStrLn $ "%VERSION: " ++ showVersion version+ args <- getArgs+ outStrLn $ "%ARGUMENTS: " ++ show args+ flip finally (printStopped opts) $ handleErrors $ forever $ withWindowIcon $ withSession $ \session -> do setVerbosity Normal -- undo any --verbose flags @@ -212,13 +225,6 @@ hSetBuffering stdout LineBuffering hSetBuffering stderr NoBuffering origDir <- getCurrentDirectory- opts <- withGhcidArgs $ cmdArgsRun options- whenLoud $ do- outStrLn $ "%OS: " ++ os- outStrLn $ "%ARCH: " ++ arch- outStrLn $ "%VERSION: " ++ showVersion version- args <- getArgs- outStrLn $ "%ARGUMENTS: " ++ show args withCurrentDirectory (directory opts) $ do opts <- autoOptions opts opts <- pure $ opts{restart = nubOrd $ (origDir </> ".ghcid") : restart opts, reload = nubOrd $ reload opts}@@ -274,7 +280,7 @@ data ReloadMode = Reload | Restart deriving (Show, Ord, Eq) --- If we pure successfully, we restart the whole process+-- If we return successfully, we restart the whole process -- Use Continue not () so that inadvertant exits don't restart runGhcid :: Session -> Waiter -> IO TermSize -> ([String] -> IO ()) -> Options -> IO Continue runGhcid session waiter termSize termOutput opts@Options{..} = do@@ -320,7 +326,7 @@ map (":set " ++) (ghciFlagsUseful ++ ghciFlagsUsefulVersioned) ++ setup when (null loaded && not ignoreLoaded) $ do- putStrLn $ "\nNo files loaded, GHCi is not working properly.\nCommand: " ++ command+ putStrLn $ "\nNo files loaded, meaning ghcid will never refresh, so aborting.\nCommand: " ++ command exitFailure restart <- pure $ nubOrd $ restart ++ [x | LoadConfig x <- messages]
src/Language/Haskell/Ghcid.hs view
@@ -75,8 +75,8 @@ -- Send them an empty line hPutStrLn inp "" - -- I'd like the GHCi prompt to go away, but that's not possible, so I set it to a special- -- string and filter that out.+ -- We don't use the GHCi prompt, so set it to a special string and filter that out.+ -- It could be removed as per https://github.com/ndmitchell/ghcid/issues/333 let ghcid_prefix = "#~GHCID-START~#" let removePrefix = dropPrefixRepeatedly ghcid_prefix
src/Test.hs view
@@ -17,7 +17,7 @@ defaultMain tests tests :: TestTree-tests = testGroup "Tests"+tests = testGroup "Tests" $ take 3 -- TEMPORARY [utilsTests ,parserTests ,apiTests
src/Test/API.hs view
@@ -8,6 +8,7 @@ import System.Time.Extra import Language.Haskell.Ghcid import Language.Haskell.Ghcid.Util+import Test.Common apiTests :: TestTree@@ -20,7 +21,7 @@ exec ghci "nub \"test\"" >>= (@?= ["\"tes\""]) stopGhci ghci - ,testCase "Load file" $ withTempDir $ \dir -> do+ ,disable19650 $ testCase "Load file" $ withTempDir $ \dir -> do writeFile (dir </> "File.hs") "module A where\na = 123" (ghci, load) <- startGhci "ghci -ignore-dot-ghci File.hs" (Just dir) $ const putStrLn load @?= [Loading "A" "File.hs"]
+ src/Test/Common.hs view
@@ -0,0 +1,13 @@++module Test.Common(disable19650) where++import Test.Tasty+import System.Info+import Data.Version++-- Tests which are disabled due to https://gitlab.haskell.org/ghc/ghc/-/issues/19650+-- readily resetting which packages are loaded+disable19650 :: TestTree -> TestTree+disable19650 x+ | compilerVersion < makeVersion [9] = x+ | otherwise = testGroup "Disabled" []
src/Test/Ghcid.hs view
@@ -22,6 +22,7 @@ import Ghcid import Language.Haskell.Ghcid.Escape import Language.Haskell.Ghcid.Util+import Test.Common import Data.Functor import Prelude @@ -116,7 +117,7 @@ -- ACTUAL TEST SUITE basicTest :: TestTree-basicTest = testCase "Ghcid basic" $ freshDir $ do+basicTest = disable19650 $ testCase "Ghcid basic" $ freshDir $ do write "Main.hs" "main = print 1" withGhcid ["-cghci -fwarn-unused-binds Main.hs"] $ \require -> do require [allGoodMessage]@@ -169,7 +170,7 @@ cdTest :: TestTree-cdTest = testCase "Cd basic" $ freshDir $ do+cdTest = disable19650 $ testCase "Cd basic" $ freshDir $ do write "foo/Main.hs" "main = print 1" write "foo/Util.hs" "import Bob" write "foo/.ghci" ":load Main"
src/Wait.hs view
@@ -29,7 +29,7 @@ withWaiterPoll x f = f $ WaiterPoll x withWaiterNotify :: (Waiter -> IO a) -> IO a-withWaiterNotify f = withManagerConf defaultConfig{confDebounce=NoDebounce} $ \manager -> do+withWaiterNotify f = withManagerConf defaultConfig $ \manager -> do mvar <- newEmptyMVar var <- newVar Map.empty f $ WaiterNotify manager mvar var@@ -54,7 +54,7 @@ -- This continues as soon as either @File1.hs@ or @File2.hs@ changes, -- starting from when 'waitFiles' was initially called. ----- pures a message about why you are continuing (usually a file name).+-- returns a message about why you are continuing (usually a file name). waitFiles :: forall a. Ord a => Waiter -> IO ([(FilePath, a)] -> IO (Either String [(FilePath, a)])) waitFiles waiter = do base <- getCurrentTime@@ -66,7 +66,7 @@ go :: UTCTime -> [(FilePath, a)] -> IO (Either String [(FilePath, a)]) go base files = do whenLoud $ outStrLn $ "%WAITING: " ++ unwords (map fst files)- -- As listContentsInside pures directories, we are waiting on them explicitly and so+ -- As listContentsInside returns directories, we are waiting on them explicitly and so -- will pick up new files, as creating a new file changes the containing directory's modtime. files <- concatForM files $ \(file, a) -> ifM (doesDirectoryExist file) (fmap (,a) <$> listContentsInside (pure . not . isPrefixOf "." . takeFileName) file) (pure [(file, a)])@@ -109,7 +109,7 @@ -- typically caused by VIM -- but try not to whenLoud $ outStrLn $ "%WAITING: Waiting max of 1s due to file removal, " ++ unwords (nubOrd (map fst disappeared))- -- at most 20 iterations, but stop as soon as the file pures+ -- at most 20 iterations, but stop as soon as the file returns void $ flip firstJustM (replicate 20 ()) $ \_ -> do sleep 0.05 new <- mapM (getModTime . fst) files