ghcid 0.6.8 → 0.6.9
raw patch · 7 files changed
+78/−58 lines, 7 filesdep ~timePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: time
API changes (from Hackage documentation)
Files
- CHANGES.txt +30/−26
- LICENSE +1/−1
- ghcid.cabal +6/−10
- src/Ghcid.hs +14/−8
- src/Language/Haskell/Ghcid/Util.hs +13/−1
- src/Test/Ghcid.hs +9/−7
- src/Wait.hs +5/−5
CHANGES.txt view
@@ -1,17 +1,22 @@ Changelog for ghcid -0.6.8+0.6.9, released 2018-01-26+ #121, add a --poll flag to use polling instead of notifiers+ Require time-1.5 or above+ #124, add timestamp to "All good" message+ After the test completes write a message+0.6.8, released 2017-11-10 #110, work even if -v0 is passed to ghci Read additional arguments from .ghcid file if present-0.6.7+0.6.7, released 2017-09-17 #104, add --ignore-loaded flag for use with -fobject-code #103, deal with new GHC error formatting-0.6.6+0.6.6, released 2016-11-11 #89, exit sooner when the child process exits unexpectedly Add Eq instance for Ghci #88, add a --project flag Rename --notitle flag to --no-title-0.6.5+0.6.5, released 2016-08-10 #82, properly deal with warning messages including spans #78, support boot files better Better support for dealing with GHC 8.0 call stack messages@@ -19,11 +24,11 @@ #71, improve multi-project stack support #74, make sure Cygwin terminals flush output properly If the test exits then exit ghcid-0.6.4+0.6.4, released 2016-05-13 #69, fix up for stack project with file arguments-0.6.3+0.6.3, released 2016-05-11 #68, add --no-status to avoid printing the reloading message-0.6.2+0.6.2, released 2016-04-25 #63, detect test failures and update the titlebar/icon #66, add --warnings to run tests even in there are warnings #62, find stack.yaml in the parent directory@@ -32,17 +37,17 @@ #67, make --reload/--restart recurse through directories #61, deal with drive letters in files (for stack on Windows) #58, improve the --help message-0.6.1+0.6.1, released 2016-04-06 Add --reload to add files that reload, but do not restart #56, allow --restart to take directories-0.6+0.6, released 2016-04-06 #38, implement loading with stack Add process, quit and execStream to the API #29, add interrupt function Add Data instances for the types Make stopGhci more effective, now kills the underlying process Make startGhci take a function to write the buffer to-0.5.1+0.5.1, released 2016-03-02 #17, deal with recursive modules errors properly #50, use -fno-code when not running tests (about twice as fast) #44, abbreviate the redundant module import error@@ -50,18 +55,18 @@ #42, always show the first error in full #43, work even if people use break-on-exception flags #42, make the first error a minimum of 5 lines-0.5+0.5, released 2015-06-20 Add an extra boolean argument to startGhci Add the number of modules loaded after All good Print out messages until the prompt comes up #23, add arguments and change what commands get invoked #35, change the titlebar icon on Windows-0.4.2+0.4.2, released 2015-06-11 Fix a GHC 7.6 warning-0.4.1+0.4.1, released 2015-06-11 #37, add a --notitle flag Require extra-1.2-0.4+0.4, released 2015-06-07 #33, make Ctrl-C more robust #31, add an outputfile feature #32, make newer warnings first (save a file, view its warnings)@@ -70,43 +75,42 @@ Add a --directory flag to change directory first #26, use fs-notify to avoid excessive wakeups #25, detect console size just before using it-0.3.6+0.3.6, released 2015-03-09 #24, don't error out if error/putStrLn are not imported-0.3.5+0.3.5, released 2015-02-25 #19, put errors in bold #9, display interesting information in the title bar #7, reload if the .ghci or .cabal file changes Use nubOrd Require extra-1.1-0.3.4+0.3.4, released 2014-12-24 #21, if you aren't waiting for any files, exit-0.3.3+0.3.3, released 2014-12-21 #21, if the root file is missing, report an error #20, avoid an O(n^2) nub-0.3.2+0.3.2, released 2014-11-06 #18, reformat excessively long lines, add a --width flag-0.3.1+0.3.1, released 2014-10-28 Ensure if there are lots of warnings, the first error gets shown-0.3+0.3, released 2014-10-24 #11, ignore certain GHCi-only warnings #13, fix version printing #8, display Loading... when starting Require the extra library #14, figure out the terminal height automatically-0.2+0.2, released 2014-10-06 #6, rewrite as a library Remove duplicate error messages from cabal repl-0.1.3+0.1.3, released 2014-09-29 #2, handle files that get deleted while loaded #3, flesh out the test suite #4, give a polite error if ghci does not start #5, add --topmost flag to make the window topmost-0.1.2 Add a very simple test suite Default to cabal repl if there is no .ghci file #1, if there is an IOError just :reload Say why you are reloading-0.1.1+0.1.1, released 2014-09-27 Support arguments to --command-0.1+0.1, released 2014-09-27 Initial version
LICENSE view
@@ -1,4 +1,4 @@-Copyright Neil Mitchell 2014-2017.+Copyright Neil Mitchell 2014-2018. All rights reserved. Redistribution and use in source and binary forms, with or without
ghcid.cabal view
@@ -1,19 +1,19 @@ cabal-version: >= 1.18 build-type: Simple name: ghcid-version: 0.6.8+version: 0.6.9 license: BSD3 license-file: LICENSE category: Development author: Neil Mitchell <ndmitchell@gmail.com>, jpmoresmau maintainer: Neil Mitchell <ndmitchell@gmail.com>-copyright: Neil Mitchell 2014-2017+copyright: Neil Mitchell 2014-2018 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.2.1, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3+tested-with: GHC==8.2.2, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3 extra-doc-files: CHANGES.txt README.md@@ -28,15 +28,11 @@ build-depends: base >= 4, filepath,- time,+ time >= 1.5, directory, extra >= 1.2, process >= 1.1, cmdargs >= 0.10- if os(windows)- build-depends: Win32- else- build-depends: unix exposed-modules: Language.Haskell.Ghcid@@ -54,7 +50,7 @@ build-depends: base == 4.*, filepath,- time,+ time >= 1.5, directory, containers, fsnotify,@@ -86,7 +82,7 @@ build-depends: base >= 4, filepath,- time,+ time >= 1.5, directory, process, containers,
src/Ghcid.hs view
@@ -18,6 +18,7 @@ import System.Console.ANSI import System.Environment import System.Directory.Extra+import System.Time.Extra import System.Exit import System.FilePath import System.IO.Extra@@ -49,6 +50,7 @@ ,directory :: FilePath ,outputfile :: [FilePath] ,ignoreLoaded :: Bool+ ,poll :: Maybe Seconds } deriving (Data,Typeable,Show) @@ -69,6 +71,7 @@ ,directory = "." &= typDir &= name "C" &= help "Set the current directory" ,outputfile = [] &= typFile &= name "o" &= help "File to write the full output to" ,ignoreLoaded = False &= explicit &= name "ignore-loaded" &= help "Keep going if no files are loaded. Requires --reload to be set."+ ,poll = Nothing &= typ "SECONDS" &= opt "0.1" &= explicit &= name "poll" &= help "Use polling every N seconds (defaults to using notifiers)" } &= verbosity &= program "ghcid" &= summary ("Auto reloading GHCi daemon v" ++ showVersion version) @@ -158,7 +161,7 @@ -- so putStrLn width 'x' uses up two lines return (fromMaybe (pred $ fst term) w, fromMaybe (snd term) h) - withWaiterNotify $ \waiter ->+ maybe withWaiterNotify withWaiterPoll (poll opts) $ \waiter -> handle (\(UnexpectedExit cmd _) -> putStrLn $ "Command \"" ++ cmd ++ "\" exited unexpectedly") $ runGhcid session waiter termSize termOutput opts @@ -186,7 +189,8 @@ outputFill load msg = do (width, height) <- termSize let n = height - length msg- load <- return $ take (if isJust load then n else 0) $ prettyOutput (maybe 0 fst load)+ currTime <- getShortTime+ load <- return $ take (if isJust load then n else 0) $ prettyOutput currTime (maybe 0 fst load) [ m{loadMessage = concatMap (chunksOfWord width (width `div` 5)) $ loadMessage m} | m@Message{} <- maybe [] snd load] termOutput $ load ++ map (Plain,) msg ++ replicate (height - (length load + length msg)) (Plain,"")@@ -197,6 +201,7 @@ restartTimes <- mapM getModTime restart curdir <- getCurrentDirectory+ currTime <- getShortTime -- fire, given a waiter, the messages/loaded let fire nextWait (messages, loaded) = do@@ -216,7 +221,7 @@ let updateTitle extra = unless no_title $ setTitle $ let f n msg = if n == 0 then "" else show n ++ " " ++ msg ++ ['s' | n > 1]- in (if countErrors == 0 && countWarnings == 0 then allGoodMessage else f countErrors "error" +++ in (if countErrors == 0 && countWarnings == 0 then allGoodMessage ++ ", at " ++ currTime else f countErrors "error" ++ (if countErrors > 0 && countWarnings > 0 then ", " else "") ++ f countWarnings "warning") ++ " " ++ extra ++ [' ' | extra /= ""] ++ "- " ++ (if null project then takeFileName curdir else project)@@ -224,7 +229,7 @@ updateTitle $ if isJust test then "(running test)" else "" outputFill (Just (loadedCount, messages)) ["Running test..." | isJust test] forM_ outputfile $ \file ->- writeFile file $ unlines $ map snd $ prettyOutput loadedCount $ filter isMessage messages+ writeFile file $ unlines $ map snd $ prettyOutput currTime loadedCount $ filter isMessage messages when (null loaded && not ignoreLoaded) $ do putStrLn "No files loaded, nothing to wait for. Fix the last error and restart." exitFailure@@ -236,8 +241,9 @@ if "*** Exception: " `isPrefixOf` stderr then do updateTitle "(test failed)" setWindowIcon IconError- else+ else do updateTitle "(test done)"+ whenNormal $ outStrLn "\n...done" reason <- nextWait $ restart ++ reload ++ loaded unless no_status $ outputFill Nothing $ "Reloading..." : map (" " ++) reason@@ -257,8 +263,8 @@ -- | Given an available height, and a set of messages to display, show them as best you can.-prettyOutput :: Int -> [Load] -> [(Style,String)]-prettyOutput loaded [] = [(Plain,allGoodMessage ++ " (" ++ show loaded ++ " module" ++ ['s' | loaded /= 1] ++ ")")]-prettyOutput loaded xs = concat $ msg1:msgs+prettyOutput :: String -> Int -> [Load] -> [(Style,String)]+prettyOutput currTime loaded [] = [(Plain,allGoodMessage ++ " (" ++ show loaded ++ " module" ++ ['s' | loaded /= 1] ++ ", at " ++ currTime ++ ")")]+prettyOutput _ loaded xs = concat $ msg1:msgs where (err, warn) = partition ((==) Error . loadSeverity) xs msg1:msgs = map (map (Bold,) . loadMessage) err ++ map (map (Plain,) . loadMessage) warn
src/Language/Haskell/Ghcid/Util.hs view
@@ -5,7 +5,7 @@ chunksOfWord, outWith, outStrLn, allGoodMessage,- getModTime, getModTimeResolution+ getModTime, getModTimeResolution, getShortTime ) where import Control.Concurrent.Extra@@ -13,9 +13,13 @@ import System.IO.Unsafe import System.IO.Extra import System.FilePath+import System.Info.Extra+import Data.Version.Extra import Data.List.Extra import Data.Char import Data.Time.Clock+import Data.Time.Format+import Data.Time.LocalTime import System.IO.Error import System.Directory import Control.Exception@@ -62,7 +66,11 @@ (Just <$> getModificationTime file) +-- | Get the current time in the current timezone in HH:MM:SS format+getShortTime :: IO String+getShortTime = formatTime defaultTimeLocale "%H:%M:%S" <$> getZonedTime + -- | Get the smallest difference that can be reported by two modification times getModTimeResolution :: IO Seconds getModTimeResolution = return getModTimeResolutionCache@@ -82,6 +90,10 @@ writeFile file $ show (i,j) t2 <- getModificationTime file return $ if t1 == t2 then Left $ j+1 else Right ()++ -- GHC 7.6 and below only have 1 sec resolution timestamps+ mtime <- return $ if compilerVersion < makeVersion [7,8] then max mtime 1 else mtime+ putStrLn $ "Longest file modification time lag was " ++ show (ceiling (mtime * 1000)) ++ "ms" -- add a little bit of safety, but if it's really quick, don't make it that much slower return $ mtime + min 0.1 mtime
src/Test/Ghcid.hs view
@@ -49,11 +49,11 @@ withCurrentDirectory tdir act -whenStack :: IO a -> IO ()-whenStack act = do- v <- findExecutable "stack"+whenExecutable :: String -> IO a -> IO ()+whenExecutable exe act = do+ v <- findExecutable exe case v of- Nothing -> putStrLn "Couldn't run test because stack is missing"+ Nothing -> putStrLn $ "Couldn't run test because " ++ exe ++ " is missing" Just _ -> void act @@ -177,7 +177,7 @@ cabalTest :: TestTree-cabalTest = testCase "Ghcid Cabal" $ copyDir "test/bar" $ do+cabalTest = testCase "Ghcid Cabal" $ copyDir "test/bar" $ whenExecutable "cabal" $ do env <- getEnvironment let db = ["--package-db=" ++ x | x <- maybe [] splitSearchPath $ lookup "GHC_PACKAGE_PATH" env] (_, _, _, pid) <- createProcess $@@ -193,7 +193,7 @@ require [allGoodMessage] stackTest :: TestTree-stackTest = testCase "Ghcid Stack" $ copyDir "test/bar" $ whenStack $ do+stackTest = testCase "Ghcid Stack" $ copyDir "test/bar" $ whenExecutable "stack" $ do system_ "stack init" createDirectoryIfMissing True ".stack-work" @@ -201,8 +201,10 @@ require [allGoodMessage] append "src/Literate.lhs" "> x" require ["src/Literate.lhs:5:3","Parse error:"]-+{-+ -- Stack seems to have changed, and continues to do so - lets just test the basics withGhcid ["src/Boot.hs"] $ \require -> do require [allGoodMessage] writeFile "src/Boot.hs" "X" require ["src/Boot.hs:1:1","Parse error:"]+-}
src/Wait.hs view
@@ -21,11 +21,11 @@ import Language.Haskell.Ghcid.Util -data Waiter = WaiterPoll+data Waiter = WaiterPoll Seconds | WaiterNotify WatchManager (MVar ()) (Var (Map.Map FilePath StopListening)) -withWaiterPoll :: (Waiter -> IO a) -> IO a-withWaiterPoll f = f WaiterPoll+withWaiterPoll :: Seconds -> (Waiter -> IO a) -> IO a+withWaiterPoll x f = f $ WaiterPoll x withWaiterNotify :: (Waiter -> IO a) -> IO a withWaiterNotify f = withManagerConf defaultConfig{confDebounce=NoDebounce} $ \manager -> do@@ -52,7 +52,7 @@ files <- fmap concat $ forM files $ \file -> ifM (doesDirectoryExist file) (listFilesInside (return . not . isPrefixOf "." . takeFileName) file) (return [file]) case waiter of- WaiterPoll -> return ()+ WaiterPoll t -> sleep $ max 0 $ t - 0.1 -- subtract the initial 0.1 sleep from above WaiterNotify manager kick mp -> do dirs <- fmap Set.fromList $ mapM canonicalizePathSafe $ nubOrd $ map takeDirectory files modifyVar_ mp $ \mp -> do@@ -75,7 +75,7 @@ recheck files old = do sleep 0.1 case waiter of- WaiterPoll -> return ()+ WaiterPoll _ -> return () WaiterNotify _ kick _ -> do takeMVar kick whenLoud $ outStrLn "%WAITING: Notify signaled"