diff options
author | Will Thompson <will@willthompson.co.uk> | 2018-07-04 10:42:21 +0000 |
---|---|---|
committer | Will Thompson <will@willthompson.co.uk> | 2018-07-04 10:42:21 +0000 |
commit | 457834d718c89f05659f2d2fe92a85596270fe5c (patch) | |
tree | d74453ee71078bc9f3d7070d0f8758938977a5d7 | |
parent | 89bafbc61e726b0befcc3ef03e0ce432a53497a0 (diff) | |
parent | 0193b332d6d42d1820c16a616239aa66b06984a8 (diff) |
Merge branch 'master' into 'master'
Add stack build, gitlab CI with stack and hlint
See merge request bustle/bustle!1
-rw-r--r-- | .gitlab-ci.yml | 29 | ||||
-rw-r--r-- | .hlint.yaml | 2 | ||||
-rw-r--r-- | Bustle/Application/Monad.hs | 2 | ||||
-rw-r--r-- | Bustle/Diagram.hs | 15 | ||||
-rw-r--r-- | Bustle/Loader.hs | 4 | ||||
-rw-r--r-- | Bustle/Loader/Pcap.hs | 27 | ||||
-rw-r--r-- | Bustle/Marquee.hs | 4 | ||||
-rw-r--r-- | Bustle/Monitor.hs | 2 | ||||
-rw-r--r-- | Bustle/Noninteractive.hs | 4 | ||||
-rw-r--r-- | Bustle/Regions.hs | 8 | ||||
-rw-r--r-- | Bustle/Renderer.hs | 60 | ||||
-rw-r--r-- | Bustle/StatisticsPane.hs | 5 | ||||
-rw-r--r-- | Bustle/Stats.hs | 18 | ||||
-rw-r--r-- | Bustle/UI.hs | 57 | ||||
-rw-r--r-- | Bustle/UI/Canvas.hs | 9 | ||||
-rw-r--r-- | Bustle/UI/DetailsView.hs | 2 | ||||
-rw-r--r-- | Bustle/UI/FilterDialog.hs | 12 | ||||
-rw-r--r-- | Bustle/UI/OpenTwoDialog.hs | 5 | ||||
-rw-r--r-- | Bustle/Util.hs | 11 | ||||
-rw-r--r-- | GetText.hs | 41 | ||||
-rw-r--r-- | Setup.hs | 2 | ||||
-rw-r--r-- | Test/PcapCrash.hs | 3 | ||||
-rw-r--r-- | Test/Regions.hs | 16 | ||||
-rw-r--r-- | bustle.cabal | 8 | ||||
-rw-r--r-- | stack.yaml | 10 |
25 files changed, 189 insertions, 167 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..4723a15 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,29 @@ +image: zenhaskell/gtk:nightly-2018-06-29 + +before_script: +- apt install -y libpcap-dev + +cache: + key: "stack-work" + paths: + - .stack-work + +stages: + - build + - lint + - test + +lint: + stage: lint + script: + - hlint . + +build: + stage: build + script: + - stack build + +test: + stage: test + script: + - stack test diff --git a/.hlint.yaml b/.hlint.yaml new file mode 100644 index 0000000..132528b --- /dev/null +++ b/.hlint.yaml @@ -0,0 +1,2 @@ +- ignore: {name: Use camelCase} +- ignore: {name: Reduce duplication} diff --git a/Bustle/Application/Monad.hs b/Bustle/Application/Monad.hs index 7a5f749..e326f7d 100644 --- a/Bustle/Application/Monad.hs +++ b/Bustle/Application/Monad.hs @@ -94,7 +94,7 @@ embedIO act = B $ do liftIO $ act r makeCallback :: Bustle config state a -> BustleEnv config state -> IO a -makeCallback (B act) x = runReaderT act x +makeCallback (B act) = runReaderT act runB :: config -> state -> Bustle config state a -> IO a runB config s (B act) = do diff --git a/Bustle/Diagram.hs b/Bustle/Diagram.hs index c4bdd4b..0f35658 100644 --- a/Bustle/Diagram.hs +++ b/Bustle/Diagram.hs @@ -49,7 +49,6 @@ where import Data.List (unzip4) import Control.Arrow ((&&&)) -import Control.Applicative ((<$>), (<*>)) import Control.Monad.Reader @@ -131,15 +130,15 @@ memberLabel :: ObjectPath -> Bool -- ^ True if this is a return; False if it's a call -> Double -- ^ y-coordinate -> Shape -memberLabel p i m isReturn y = MemberLabel p i m isReturn memberx y +memberLabel p i m isReturn = MemberLabel p i m isReturn memberx timestampLabel :: String -> Double -> Shape -timestampLabel s y = TimestampLabel s timestampx y +timestampLabel s = TimestampLabel s timestampx type Diagram = [Shape] arcControlPoints :: Shape -> (Point, Point) -arcControlPoints (Arc { topx=x1, topy=y1, bottomx=x2, bottomy=y2, arcside=s }) = +arcControlPoints Arc { topx=x1, topy=y1, bottomx=x2, bottomy=y2, arcside=s } = let (+-) = offset s cp1 = (x1 +- 60, y1 + 10) cp2 = (x2 +- 60, y2 - 10) @@ -230,11 +229,11 @@ bounds s = case s of in (x1, y1, x2, y2) SignalArrow {} -> let (x1, x2) = xMinMax s - (y1, y2) = (subtract 5) &&& (+5) $ shapey s + (y1, y2) = subtract 5 &&& (+5) $ shapey s in (x1, y1, x2, y2) DirectedSignalArrow {} -> let (x1, x2) = minMax (epicentre s, shapex s) - (y1, y2) = (subtract 5) &&& (+5) $ shapey s + (y1, y2) = subtract 5 &&& (+5) $ shapey s in (x1, y1, x2, y2) Arc { topx=x1, bottomx=x2, topy=y1, bottomy=y2 } -> let ((cx, _), (dx, _)) = arcControlPoints s @@ -406,13 +405,13 @@ drawSignalArrow e mleft mright y = do arc e y 5 0 (2 * pi) stroke - maybeM mleft $ \left -> do + forM_ mleft $ \left -> do moveTo left y arrowHead False lineTo (e - 5) y stroke - maybeM mright $ \right -> do + forM_ mright $ \right -> do moveTo (e + 5) y lineTo right y arrowHead True diff --git a/Bustle/Loader.hs b/Bustle/Loader.hs index 821bf44..8fd40c8 100644 --- a/Bustle/Loader.hs +++ b/Bustle/Loader.hs @@ -26,7 +26,7 @@ module Bustle.Loader where import Control.Monad.Except -import Control.Arrow ((***)) +import Control.Arrow (second) import qualified Bustle.Loader.Pcap as Pcap import Bustle.Types @@ -43,7 +43,7 @@ readLog :: MonadIO io readLog f = do pcapResult <- io $ Pcap.readPcap f case pcapResult of - Right ms -> return $ (id *** filter (isRelevant . deEvent)) ms + Right ms -> return $ second (filter (isRelevant . deEvent)) ms Left ioe -> throwError $ LoadError f (show ioe) isRelevant :: Event diff --git a/Bustle/Loader/Pcap.hs b/Bustle/Loader/Pcap.hs index a707b39..bed6f31 100644 --- a/Bustle/Loader/Pcap.hs +++ b/Bustle/Loader/Pcap.hs @@ -118,10 +118,10 @@ isNOC (Just sender) s | looksLikeNOC = names = map fromVariant $ signalBody s looksLikeNOC = - and [ sender == B.dbusName - , signalInterface s == B.dbusInterface - , formatMemberName (signalMember s) == "NameOwnerChanged" - ] + (sender == B.dbusName) && + (signalInterface s == B.dbusInterface) && + (formatMemberName (signalMember s) == "NameOwnerChanged") + isNOC _ _ = Nothing @@ -152,10 +152,10 @@ tryBustlifyGetNameOwnerReply maybeCall mr = do -- • don't crash if the body of the call or reply doesn't contain one bus name. (rawCall, _) <- maybeCall guard (formatMemberName (methodCallMember rawCall) == "GetNameOwner") - ownedName <- fromVariant $ (methodCallBody rawCall !! 0) + ownedName <- fromVariant (head (methodCallBody rawCall)) return $ bustlifyNOC ( ownedName , Nothing - , fromVariant $ (methodReturnBody mr !! 0) + , fromVariant (head (methodReturnBody mr)) ) bustlify :: Monad m @@ -209,8 +209,7 @@ bustlify µs bytes m = do | otherwise -> return $ B.MessageEvent $ B.Signal { B.sender = wrappedSender , B.member = convertMember signalPath (Just . signalInterface) signalMember sig - , B.signalDestination = fmap stupifyBusName - $ signalDestination sig + , B.signalDestination = stupifyBusName <$> signalDestination sig } _ -> error "woah there! someone added a new message type." @@ -222,7 +221,7 @@ convert :: Monad m convert µs body = case unmarshal body of Left e -> return $ Left $ unmarshalErrorMessage e - Right m -> liftM Right $ bustlify µs (BS.length body) m + Right m -> Right <$> bustlify µs (BS.length body) m data Result e a = EOF @@ -242,7 +241,7 @@ readOne p f = do -- or something? if hdrCaptureLength hdr == 0 then return EOF - else liftM Packet $ f (fromIntegral (hdrTime hdr)) body + else Packet <$> f (fromIntegral (hdrTime hdr)) body -- This shows up as the biggest thing on the heap profile. Which is kind of a -- surprise. It's supposedly the list. @@ -253,7 +252,7 @@ mapBodies :: (Monad m, MonadIO m) mapBodies p f = do ret <- readOne p f case ret of - EOF -> return $ [] + EOF -> return [] Packet x -> do xs <- mapBodies p f return $ x:xs @@ -266,11 +265,11 @@ readPcap path = try $ do dlt <- datalink p -- DLT_NULL for extremely old logs. -- DLT_DBUS is missing: https://github.com/bos/pcap/pull/8 - when (not $ elem dlt [DLT_NULL, DLT_UNKNOWN 231]) $ do + unless (dlt `elem` [DLT_NULL, DLT_UNKNOWN 231]) $ do let message = "Incorrect link type " ++ show dlt ioError $ mkIOError userErrorType message Nothing (Just path) - liftM partitionEithers $ evalStateT (mapBodies p convert) Map.empty + partitionEithers <$> evalStateT (mapBodies p convert) Map.empty where snaplenErrorString = "invalid file capture length 134217728, bigger than maximum of 262144" snaplenBugReference = __ "libpcap 1.8.0 and 1.8.1 are incompatible with Bustle. See \ @@ -280,6 +279,6 @@ readPcap path = try $ do \Bustle from Flathub, which already includes the necessary \ \patches: https://flathub.org/apps/details/org.freedesktop.Bustle" matchSnaplenBug e = - if isUserError e && (snaplenErrorString `isSuffixOf` (ioeGetErrorString e)) + if isUserError e && (snaplenErrorString `isSuffixOf` ioeGetErrorString e) then Just $ ioeSetErrorString e snaplenBugReference else Nothing diff --git a/Bustle/Marquee.hs b/Bustle/Marquee.hs index 365a72d..77a9db5 100644 --- a/Bustle/Marquee.hs +++ b/Bustle/Marquee.hs @@ -50,9 +50,11 @@ newtype Marquee = Marquee { unMarquee :: String } toPangoMarkup :: Marquee -> String toPangoMarkup = unMarquee +instance Semigroup Marquee where + Marquee x <> Marquee y = Marquee (x <> y) + instance Monoid Marquee where mempty = Marquee "" - mappend x y = Marquee (unMarquee x `mappend` unMarquee y) mconcat = Marquee . mconcat . map unMarquee tag :: String -> Marquee -> Marquee diff --git a/Bustle/Monitor.hs b/Bustle/Monitor.hs index 53369a9..cb9d4ef 100644 --- a/Bustle/Monitor.hs +++ b/Bustle/Monitor.hs @@ -95,7 +95,7 @@ monitorNew target filename = monitorStop :: Monitor -> IO () -monitorStop monitor = do +monitorStop monitor = withForeignPtr (unMonitor monitor) bustle_pcap_monitor_stop messageLoggedHandler :: (Microseconds -> BS.ByteString -> IO ()) diff --git a/Bustle/Noninteractive.hs b/Bustle/Noninteractive.hs index b96b87f..215fc28 100644 --- a/Bustle/Noninteractive.hs +++ b/Bustle/Noninteractive.hs @@ -48,7 +48,7 @@ process filepath analyze format = do warn $ printf (__ "Couldn't parse '%s': %s") filepath err exitFailure Right (warnings, log) -> do - mapM warn warnings + mapM_ warn warnings mapM_ (putStrLn . format) $ analyze log formatInterface :: Maybe InterfaceName -> String @@ -82,5 +82,5 @@ runDot filepath = process filepath makeDigraph id | (s, d) <- nub . mapMaybe (methodCall . deEvent) $ log ] - methodCall (MessageEvent (MethodCall {sender = s, destination = d})) = Just (s, d) + methodCall (MessageEvent MethodCall {sender = s, destination = d}) = Just (s, d) methodCall _ = Nothing diff --git a/Bustle/Regions.hs b/Bustle/Regions.hs index 43b4e06..09b6f16 100644 --- a/Bustle/Regions.hs +++ b/Bustle/Regions.hs @@ -86,15 +86,15 @@ hits y stripe = y `relativeTo` stripe == EQ nonOverlapping :: [Stripe] -> Bool nonOverlapping [] = True -nonOverlapping (_:[]) = True +nonOverlapping [_] = True nonOverlapping (s1:s2:ss) = stripeBottom s1 <= stripeTop s2 && nonOverlapping (s2:ss) regionSelectionNew :: Regions a -> RegionSelection a regionSelectionNew rs - | sorted /= map fst rs = error $ "regionSelectionNew: unsorted regions" - | not (nonOverlapping sorted) = error $ "regionSelectionNew: overlapping regions" + | sorted /= map fst rs = error "regionSelectionNew: unsorted regions" + | not (nonOverlapping sorted) = error "regionSelectionNew: overlapping regions" | otherwise = RegionSelection [] 0 Nothing rs where sorted = sort (map fst rs) @@ -169,7 +169,7 @@ regionSelectionDown = invert . regionSelectionUp . invert regionSelectionFirst :: RegionSelection a -> RegionSelection a regionSelectionFirst rs = - case (reverse (rsBefore rs) ++ maybeToList (rsCurrent rs) ++ rsAfter rs) of + case reverse (rsBefore rs) ++ maybeToList (rsCurrent rs) ++ rsAfter rs of [] -> rs (first:others) -> RegionSelection [] (midpoint (fst first)) diff --git a/Bustle/Renderer.hs b/Bustle/Renderer.hs index 42a282f..2771c17 100644 --- a/Bustle/Renderer.hs +++ b/Bustle/Renderer.hs @@ -35,21 +35,18 @@ module Bustle.Renderer ) where -import Prelude hiding (log) - import Bustle.Types import Bustle.Diagram import Bustle.Regions -import Bustle.Util (maybeM, NonEmpty(..)) +import Bustle.Util (NonEmpty(..)) import qualified Data.Set as Set import Data.Set (Set) import qualified Data.Map as Map import Data.Map (Map) -import Control.Applicative (Applicative(..), (<$>), (<*>)) -import Control.Arrow ((***)) -import Control.Monad.Except +import Control.Arrow (first) +import Control.Monad import Control.Monad.Identity import Control.Monad.State import Control.Monad.Writer @@ -76,17 +73,19 @@ data Participants = deriving (Show, Eq) -instance Monoid Participants where - mempty = Participants Map.empty Map.empty - mappend (Participants sess1 sys1) (Participants sess2 sys2) = - Participants (f sess1 sess2) - (f sys1 sys2) +instance Semigroup Participants where + (<>) (Participants sess1 sys1) (Participants sess2 sys2) = + Participants (f sess1 sess2) + (f sys1 sys2) where f = Map.unionWith Set.union +instance Monoid Participants where + mempty = Participants Map.empty Map.empty + sessionParticipants :: Participants -> [(UniqueName, Set OtherName)] -- ^ sorted by column -sessionParticipants = map (snd *** id) . Map.toAscList . pSession +sessionParticipants = map (first snd) . Map.toAscList . pSession data RendererResult apps = RendererResult { rrCentreOffset :: Double @@ -109,9 +108,9 @@ data RendererResult apps = -- -- This is extremely unpleasant but it's a Monday. There's a test case in -- Test/Renderer.hs because I don't trust myself. -instance Monoid apps => Monoid (RendererResult apps) where - mempty = RendererResult 0 0 [] [] mempty [] - mappend rr1 rr2 = RendererResult centreOffset topOffset shapes regions applications warnings + +instance Semigroup apps => Semigroup (RendererResult apps) where + rr1 <> rr2 = RendererResult centreOffset topOffset shapes regions applications warnings where centreOffset = rrCentreOffset rr1 `max` rrCentreOffset rr2 topOffset = rrTopOffset rr1 `max` rrTopOffset rr2 @@ -136,15 +135,19 @@ instance Monoid apps => Monoid (RendererResult apps) where regions = translatedRegions rr1 ++ translatedRegions rr2 - applications = rrApplications rr1 `mappend` rrApplications rr2 - warnings = rrWarnings rr1 `mappend` rrWarnings rr2 + applications = rrApplications rr1 <> rrApplications rr2 + warnings = rrWarnings rr1 <> rrWarnings rr2 + + +instance Monoid apps => Monoid (RendererResult apps) where + mempty = RendererResult 0 0 [] [] mempty [] processWithFilters :: (Log, Set UniqueName) -> (Log, Set UniqueName) -> RendererResult () processWithFilters (sessionBusLog, sessionFilter) (systemBusLog, systemFilter ) = - fmap (const ()) $ fst $ processSome sessionBusLog systemBusLog rs + void $ fst $ processSome sessionBusLog systemBusLog rs where rs = initialState sessionFilter systemFilter @@ -229,12 +232,13 @@ data RendererOutput = deriving (Show) -instance Monoid RendererOutput where - mempty = RendererOutput [] [] [] - mappend (RendererOutput s1 r1 w1) - (RendererOutput s2 r2 w2) = RendererOutput (s1 ++ s2) +instance Semigroup RendererOutput where + (<>) (RendererOutput s1 r1 w1) + (RendererOutput s2 r2 w2) = RendererOutput (s1 ++ s2) (r1 ++ r2) (w1 ++ w2) +instance Monoid RendererOutput where + mempty = RendererOutput [] [] [] data BusState = BusState { apps :: Applications @@ -466,7 +470,7 @@ remUnique bus n = do ai <- lookupUniqueName bus n let mcolumn = aiCurrentColumn ai modifyApps bus $ Map.insert n (ai { aiColumn = FormerColumn mcolumn }) - maybeM mcolumn $ \x -> + forM_ mcolumn $ \x -> modifyBusState bus $ \bs -> bs { columnsInUse = Set.delete x (columnsInUse bs) } @@ -541,7 +545,7 @@ advanceBy d = do ] let (height, ss) = headers xs' (current' + 20) tellShapes ss - modify $ \bs -> bs { mostRecentLabels = (current' + height + 10) + modify $ \bs -> bs { mostRecentLabels = current' + height + 10 , row = row bs + height + 10 } current <- gets row @@ -563,7 +567,7 @@ advanceBy d = do bestNames :: UniqueName -> Set OtherName -> [String] bestNames u os | Set.null os = [unUniqueName u] - | otherwise = reverse . sortBy (comparing length) . map readable $ Set.toList os + | otherwise = (sortBy (flip (comparing length)) . map readable) $ Set.toList os where readable = reverse . takeWhile (/= '.') . reverse . unOtherName edgemostApp :: Bus -> Renderer (Maybe Double) @@ -633,7 +637,7 @@ returnArc bus mr callx cally duration = do shape $ Arc { topx = callx, topy = cally , bottomx = currentx, bottomy = currenty - , arcside = if (destinationx > currentx) then L else R + , arcside = if destinationx > currentx then L else R , caption = show (µsToMs duration) ++ "ms" } @@ -703,7 +707,7 @@ processNOC :: Bus -> Renderer () processNOC bus noc = case noc of - Connected { actor = u } -> addUnique bus u >> return () + Connected { actor = u } -> void (addUnique bus u) Disconnected { actor = u } -> remUnique bus u NameChanged { changedName = n , change = c @@ -734,7 +738,7 @@ signal bus dm = do mtarget <- signalDestinationCoordinate bus dm case mtarget of - Just target -> do + Just target -> shape $ DirectedSignalArrow emitter target t Nothing -> do -- fromJust is safe here because we must have an app to have a diff --git a/Bustle/StatisticsPane.hs b/Bustle/StatisticsPane.hs index 2838b16..3e4d3b5 100644 --- a/Bustle/StatisticsPane.hs +++ b/Bustle/StatisticsPane.hs @@ -23,7 +23,6 @@ module Bustle.StatisticsPane ) where -import Control.Applicative ((<$>)) import Control.Monad (forM_) import Text.Printf import Graphics.UI.Gtk @@ -157,9 +156,9 @@ newCountView = do countBar <- cellRendererProgressNew cellLayoutPackStart countColumn countBar True cellLayoutSetAttributes countColumn countBar countStore $ - \(FrequencyInfo {fiFrequency = count}) -> + \FrequencyInfo {fiFrequency = count} -> [ cellProgressValue :=> do - upperBound <- (maximum . map fiFrequency) <$> + upperBound <- maximum . map fiFrequency <$> listStoreToList countStore -- ensure that we always show *something* return $ 2 + (count * 98 `div` upperBound) diff --git a/Bustle/Stats.hs b/Bustle/Stats.hs index 0ef7b19..30fb221 100644 --- a/Bustle/Stats.hs +++ b/Bustle/Stats.hs @@ -31,7 +31,7 @@ module Bustle.Stats where import Control.Monad (guard) -import Data.List (sort, sortBy) +import Data.List (sortBy) import Data.Maybe (mapMaybe) import Data.Ord (comparing) @@ -62,9 +62,7 @@ data FrequencyInfo = deriving (Show, Eq, Ord) frequencies :: Log -> [FrequencyInfo] -frequencies = reverse - . sort - . map (\((t, i, m), c) -> FrequencyInfo c t i m) +frequencies = sortBy (flip compare) . map (\((t, i, m), c) -> FrequencyInfo c t i m) . Map.toList . foldr (Map.alter alt) Map.empty . mapMaybe repr @@ -86,9 +84,7 @@ data TimeInfo = methodTimes :: Log -> [TimeInfo] -methodTimes = reverse - . sortBy (comparing tiTotalTime) - . map summarize +methodTimes = sortBy (flip (comparing tiTotalTime)) . map summarize . Map.toList . foldr (\(i, method, time) -> Map.alter (alt time) (i, method)) Map.empty @@ -101,7 +97,7 @@ methodTimes = reverse Just (newtime + total, newtime : times) isReturn :: Message -> Bool - isReturn (MethodReturn {}) = True + isReturn MethodReturn {} = True isReturn _ = False methodReturn :: Detailed Message @@ -109,7 +105,7 @@ methodTimes = reverse methodReturn dm = do let m = deEvent dm guard (isReturn m) - Detailed start (call@(MethodCall {})) _ _ <- inReplyTo m + Detailed start call@MethodCall {} _ _ <- inReplyTo m return ( iface (member call) , membername (member call) , deTimestamp dm - start @@ -120,7 +116,7 @@ methodTimes = reverse , tiMethodName = method , tiTotalTime = fromIntegral total / 1000 , tiCallFrequency = length times - , tiMeanCallTime = (mean $ map fromIntegral times) / 1000 + , tiMeanCallTime = mean (map fromIntegral times) / 1000 } -- FIXME: really? again? @@ -145,7 +141,7 @@ data SizeInfo = messageSizes :: Log -> [SizeInfo] messageSizes messages = - reverse . sort . map summarize $ Map.assocs sizeTable + sortBy (flip compare) . map summarize $ Map.assocs sizeTable where summarize :: ((SizeType, Maybe InterfaceName, MemberName), [Int]) -> SizeInfo summarize ((t, i, m), sizes) = diff --git a/Bustle/UI.hs b/Bustle/UI.hs index d2d95f4..44abafb 100644 --- a/Bustle/UI.hs +++ b/Bustle/UI.hs @@ -111,7 +111,7 @@ data WindowInfo = , wiLogDetails :: IORef (Maybe LogDetails) } -data BConfig = +newtype BConfig = BConfig { debugEnabled :: Bool } @@ -175,7 +175,7 @@ consumeInitialWindow = do putInitialWindow :: WindowInfo -> B () -putInitialWindow wi = do +putInitialWindow wi = modify $ \s -> s { initialWindow = Just wi } loadInInitialWindow :: LogDetails -> B () @@ -225,7 +225,7 @@ loadLogWith getWindow logDetails = do let title = printf (__ "Could not read '%s'") f io $ displayError windowInfo title (Just e) putInitialWindow windowInfo - Right () -> do + Right () -> io $ hideError windowInfo io $ windowPresent (wiWindow windowInfo) @@ -235,7 +235,7 @@ updateRecordingSubtitle :: WindowInfo -> Int -> IO () updateRecordingSubtitle wi j = do - let message = (printf (__ "Logged <b>%u</b> messages") j :: String) + let message = printf (__ "Logged <b>%u</b> messages") j :: String labelSetMarkup (wiSubtitle wi) message @@ -253,7 +253,7 @@ processBatch pendingRef n wi = do pending <- readIORef pendingRef writeIORef pendingRef [] - when (not (null pending)) $ do + unless (null pending) $ do rr <- atomicModifyIORef' rendererStateRef $ \s -> swap $ processSome (reverse pending) [] s @@ -261,7 +261,7 @@ processBatch pendingRef n wi = do let rr' = oldRR `mappend` rr writeIORef rendererResultRef rr' - when (not (null (rrShapes rr))) $ do + unless (null (rrShapes rr)) $ do -- If the renderer produced some visible output, count it as a -- message from the user's perspective. modifyIORef' n (+ length pending) @@ -292,7 +292,7 @@ recorderRun wi target filename r = C.handle newFailed $ do case m of Left e -> warn e Right message - | isRelevant (deEvent message) -> do + | isRelevant (deEvent message) -> modifyIORef' pendingRef (message:) | otherwise -> return () @@ -300,7 +300,7 @@ recorderRun wi target filename r = C.handle newFailed $ do processor <- processBatch pendingRef n wi processorId <- timeoutAdd processor 200 - stopActivatedId <- (wiStop wi) `on` buttonActivated $ monitorStop monitor + stopActivatedId <- wiStop wi `on` buttonActivated $ monitorStop monitor handlerId <- monitor `on` monitorMessageLogged $ updateLabel _stoppedId <- monitor `on` monitorStopped $ \domain code message -> do handleError domain code message @@ -312,7 +312,7 @@ recorderRun wi target filename r = C.handle newFailed $ do timeoutRemove processorId processor - hadOutput <- liftM (/= 0) (readIORef n) + hadOutput <- fmap (/= 0) (readIORef n) finished hadOutput return () @@ -330,7 +330,7 @@ recorderRun wi target filename r = C.handle newFailed $ do handleError domain code message = do gIoErrorQuark <- quarkFromString "g-io-error-quark" let cancelled = fromEnum IoErrorCancelled - when (not (domain == gIoErrorQuark && code == cancelled)) $ do + unless (domain == gIoErrorQuark && code == cancelled) $ displayError wi (Marquee.toString message) Nothing @@ -339,11 +339,11 @@ startRecording :: Either BusType String startRecording target = do wi <- consumeInitialWindow - zt <- io $ getZonedTime + zt <- io getZonedTime -- I hate time manipulation let yyyy_mm_dd_hh_mm_ss = takeWhile (/= '.') (show zt) - cacheDir <- io $ getCacheDir + cacheDir <- io getCacheDir let filename = cacheDir </> yyyy_mm_dd_hh_mm_ss <.> "bustle" let title = printf (__ "Recording %s…") $ case target of @@ -377,8 +377,7 @@ onMenuItemActivate :: MenuItemClass menuItem => menuItem -> IO () -> IO (ConnectId menuItem) -onMenuItemActivate mi act = - on mi menuItemActivate act +onMenuItemActivate mi = on mi menuItemActivate finishedRecording :: WindowInfo -> FilePath @@ -408,8 +407,8 @@ finishedRecording wi tempFilePath producedOutput = do putInitialWindow wi updateDisplayedLog wi (mempty :: RendererResult ()) io $ do - (wiTitle wi) `set` [ labelText := "" ] - (wiSubtitle wi) `set` [ labelText := "" ] + wiTitle wi `set` [ labelText := "" ] + wiSubtitle wi `set` [ labelText := "" ] showSaveDialog :: WindowInfo -> IO () @@ -431,10 +430,10 @@ showSaveDialog wi savedCb = do hideError wi savedCb Left (GError _ _ msg) -> do - let title = (__ "Couldn't save log: ") ++ (Marquee.toString msg) + let title = __ "Couldn't save log: " ++ Marquee.toString msg secondary = printf (__ "You might want to manually recover the log from the temporary file at \ - \\"%s\".") (tempFilePath) + \\"%s\".") tempFilePath displayError wi title (Just secondary) -- | Show a confirmation dialog if the log is unsaved. Suitable for use as a @@ -509,7 +508,7 @@ emptyWindow = do errorBarTitle <- getW castToLabel "errorBarTitle" errorBarDetails <- getW castToLabel "errorBarDetails" - io $ errorBar `on` infoBarResponse $ \_ -> do + io $ errorBar `on` infoBarResponse $ \_ -> widgetHide errorBar stack <- getW castToStack "diagramOrNot" @@ -587,9 +586,9 @@ emptyWindow = do updateDetailsView :: DetailsView -> Maybe (Detailed Message) -> IO () -updateDetailsView detailsView newMessage = do +updateDetailsView detailsView newMessage = case newMessage of - Nothing -> do + Nothing -> widgetHide $ detailsViewGetTop detailsView Just m -> do detailsViewUpdate detailsView m @@ -644,9 +643,9 @@ wiSetLogDetails :: WindowInfo wiSetLogDetails wi logDetails = do writeIORef (wiLogDetails wi) (Just logDetails) let (title, subtitle) = logWindowTitle logDetails - (wiWindow wi) `set` [ windowTitle := title ] - (wiTitle wi) `set` [ labelText := title ] - (wiSubtitle wi) `set` [ labelText := subtitle ] + wiWindow wi `set` [ windowTitle := title ] + wiTitle wi `set` [ labelText := title ] + wiSubtitle wi `set` [ labelText := subtitle ] setPage :: MonadIO io => WindowInfo @@ -660,7 +659,7 @@ displayLog :: WindowInfo -> Log -> RendererResult Participants -> B () -displayLog wi@(WindowInfo { wiWindow = window +displayLog wi@WindowInfo { wiWindow = window , wiExport = exportItem , wiViewStatistics = viewStatistics , wiFilterNames = filterNames @@ -668,7 +667,7 @@ displayLog wi@(WindowInfo { wiWindow = window , wiSidebarHeader = sidebarHeader , wiSidebarStack = sidebarStack , wiStatsPane = statsPane - }) + } logDetails sessionMessages systemMessages @@ -755,7 +754,7 @@ saveToPDFDialogue wi shapes = do RecordedLog _ -> Nothing SingleLog p -> Just $ takeDirectory p TwoLogs p _ -> Just $ takeDirectory p - maybeM mdirectory $ fileChooserSetCurrentFolder chooser + forM_ mdirectory $ fileChooserSetCurrentFolder chooser chooser `after` response $ \resp -> do when (resp == ResponseAccept) $ do @@ -766,9 +765,9 @@ saveToPDFDialogue wi shapes = do renderWith surface $ drawDiagram False shapes case r of Left (e :: C.IOException) -> do - let title = (__ "Couldn't export log as PDF: ") ++ show e + let title = __ "Couldn't export log as PDF: " ++ show e displayError wi title Nothing - Right () -> do + Right () -> hideError wi widgetDestroy chooser diff --git a/Bustle/UI/Canvas.hs b/Bustle/UI/Canvas.hs index 2bfd87b..51d69f4 100644 --- a/Bustle/UI/Canvas.hs +++ b/Bustle/UI/Canvas.hs @@ -32,7 +32,7 @@ where import Data.Maybe (isNothing) import Data.IORef -import Control.Monad (when) +import Control.Monad (forM_, when) import Graphics.UI.Gtk import Graphics.Rendering.Cairo (Render, translate) @@ -206,10 +206,10 @@ canvasUpdateSelection canvas f = do writeIORef regionSelectionRef rs' when (newMessage /= currentMessage) $ do - maybeM currentMessage $ \(r, _) -> + forM_ currentMessage $ \(r, _) -> canvasInvalidateStripe canvas r - maybeM newMessage $ \(r, _) -> do + forM_ newMessage $ \(r, _) -> do canvasInvalidateStripe canvas r canvasClampAroundSelection canvas @@ -281,8 +281,7 @@ canvasDraw canvas = do canvasFocus :: Canvas a -> IO () -canvasFocus canvas = do - (canvasLayout canvas) `set` [ widgetIsFocus := True ] +canvasFocus canvas = canvasLayout canvas `set` [ widgetIsFocus := True ] canvasScrollToBottom :: Canvas a -> IO () diff --git a/Bustle/UI/DetailsView.hs b/Bustle/UI/DetailsView.hs index e60d311..8a28367 100644 --- a/Bustle/UI/DetailsView.hs +++ b/Bustle/UI/DetailsView.hs @@ -77,7 +77,7 @@ getMember (Detailed _ m _ _) = case m of MethodReturn {} -> callMember Error {} -> callMember where - callMember = fmap (member . deEvent) $ inReplyTo m + callMember = member . deEvent <$> inReplyTo m getDestination :: Detailed Message -> Maybe TaggedBusName getDestination (Detailed _ m _ _) = case m of diff --git a/Bustle/UI/FilterDialog.hs b/Bustle/UI/FilterDialog.hs index 6658d22..32d95d4 100644 --- a/Bustle/UI/FilterDialog.hs +++ b/Bustle/UI/FilterDialog.hs @@ -23,7 +23,7 @@ module Bustle.UI.FilterDialog ) where -import Data.List (intercalate, groupBy, findIndices) +import Data.List (intercalate, groupBy, elemIndices) import qualified Data.Set as Set import Data.Set (Set) import qualified Data.Function as F @@ -35,7 +35,7 @@ import Bustle.Types namespace :: String -> (String, String) -namespace name = case reverse (findIndices (== '.') name) of +namespace name = case reverse (elemIndices '.' name) of [] -> ("", name) (i:_) -> splitAt (i + 1) name @@ -51,17 +51,17 @@ formatNames (u, os) groupGroup xs@((ns, _):_) = (ns, map snd xs) formatGroup (ns, [y]) = ns ++ y - formatGroup (ns, ys) = ns ++ "{" ++ (intercalate "," ys) ++ "}" + formatGroup (ns, ys) = ns ++ "{" ++ intercalate "," ys ++ "}" type NameStore = ListStore (Bool, (UniqueName, Set OtherName)) makeStore :: [(UniqueName, Set OtherName)] -> Set UniqueName -> IO NameStore -makeStore names currentlyHidden = do +makeStore names currentlyHidden = listStoreNew $ map toPair names where - toPair (name@(u, _)) = (not (Set.member u currentlyHidden), name) + toPair name@(u, _) = (not (Set.member u currentlyHidden), name) makeView :: NameStore -> IO ScrolledWindow @@ -111,7 +111,7 @@ runFilterDialog parent names currentlyHidden = do windowSetDefaultSize d (windowWidth * 7 `div` 8) (windowHeight `div` 2) d `set` [ windowTransientFor := parent ] dialogAddButton d stockClose ResponseClose - vbox <- fmap castToBox $ dialogGetContentArea d + vbox <- castToBox <$> dialogGetContentArea d boxSetSpacing vbox 6 nameStore <- makeStore names currentlyHidden diff --git a/Bustle/UI/OpenTwoDialog.hs b/Bustle/UI/OpenTwoDialog.hs index 440abc6..afb2217 100644 --- a/Bustle/UI/OpenTwoDialog.hs +++ b/Bustle/UI/OpenTwoDialog.hs @@ -42,10 +42,7 @@ propagateCurrentFolder d1 d2 = d1 `on` currentFolderChanged $ do f1 <- fileChooserGetCurrentFolder d1 f2 <- fileChooserGetCurrentFolder d2 otherFile <- fileChooserGetFilename d2 - when (and [ isNothing otherFile - , f1 /= f2 - , isJust f1 - ]) $ do + when (isNothing otherFile && f1 /= f2 && isJust f1) $ do fileChooserSetCurrentFolder d2 (fromJust f1) return () diff --git a/Bustle/Util.hs b/Bustle/Util.hs index 5ac76a2..f0d1990 100644 --- a/Bustle/Util.hs +++ b/Bustle/Util.hs @@ -22,8 +22,6 @@ module Bustle.Util io , warn - , maybeM - , getCacheDir -- You probably don't actually want to use this function. @@ -50,19 +48,12 @@ traceM x = trace (show x) $ return () -- Log a warning which isn't worth showing to the user, but which might -- interest someone debugging the application. warn :: String -> IO () -warn = hPutStrLn stderr . ((__ "Warning: ") ++) +warn = hPutStrLn stderr . (__ "Warning: " ++) -- Shorthand for liftIO. io :: MonadIO m => IO a -> m a io = liftIO -maybeM :: Monad m - => Maybe a - -> (a -> m b) - -> m () -maybeM Nothing _ = return () -maybeM (Just x) act = act x >> return () - foreign import ccall "g_get_user_cache_dir" g_get_user_cache_dir :: IO CString @@ -73,7 +73,7 @@ -- see https://github.com/fpco/stackage/issues/746 -- -module GetText +module GetText ( -- | /TODO:/ upstream exporting the individual hooks? installPOFiles, @@ -118,18 +118,17 @@ gettextDefaultMain = defaultMainWithHooks $ installGetTextHooks simpleUserHooks installGetTextHooks :: UserHooks -- ^ initial user hooks -> UserHooks -- ^ patched user hooks installGetTextHooks uh = uh{ - confHook = \a b -> - (confHook uh) a b >>= - return . updateLocalBuildInfo, + confHook = \a b -> + updateLocalBuildInfo <$> confHook uh a b, - postInst = \a b c d -> - (postInst uh) a b c d >> + postInst = \a b c d -> + postInst uh a b c d >> installPOFiles a b c d } updateLocalBuildInfo :: LocalBuildInfo -> LocalBuildInfo -updateLocalBuildInfo l = +updateLocalBuildInfo l = let sMap = getCustomFields l [domDef, catDef] = map ($ sMap) [getDomainDefine, getMsgCatalogDefine] dom = getDomainNameDefault sMap (getPackageName l) @@ -138,7 +137,7 @@ updateLocalBuildInfo l = in (appendCPPOptions [domMS,catMS] . appendExtension [EnableExtension CPP]) l installPOFiles :: Args -> InstallFlags -> PackageDescription -> LocalBuildInfo -> IO () -installPOFiles _ _ _ l = +installPOFiles _ _ _ l = let sMap = getCustomFields l destDir = targetDataDir l dom = getDomainNameDefault sMap (getPackageName l) @@ -148,43 +147,43 @@ installPOFiles _ _ _ l = let targetDir = destDir </> bname </> "LC_MESSAGES" -- ensure we have directory destDir/{loc}/LC_MESSAGES createDirectoryIfMissing True targetDir - system $ "msgfmt --output-file=" ++ - (targetDir </> dom <.> "mo") ++ + system $ "msgfmt --output-file=" ++ + (targetDir </> dom <.> "mo") ++ " " ++ file in do filelist <- getPoFilesDefault sMap -- copy all whose name is in the form of dir/{loc}.po to the -- destDir/{loc}/LC_MESSAGES/dom.mo -- with the 'msgfmt' tool - mapM_ installFile filelist + mapM_ installFile filelist forBuildInfo :: LocalBuildInfo -> (BuildInfo -> BuildInfo) -> LocalBuildInfo -forBuildInfo l f = +forBuildInfo l f = let a = l{localPkgDescr = updPkgDescr (localPkgDescr l)} - updPkgDescr x = x{library = updLibrary (library x), + updPkgDescr x = x{library = updLibrary (library x), executables = updExecs (executables x)} updLibrary Nothing = Nothing updLibrary (Just x) = Just $ x{libBuildInfo = f (libBuildInfo x)} - updExecs x = map updExec x + updExecs = map updExec updExec x = x{buildInfo = f (buildInfo x)} in a appendExtension :: [Extension] -> LocalBuildInfo -> LocalBuildInfo -appendExtension exts l = +appendExtension exts l = forBuildInfo l updBuildInfo where updBuildInfo x = x{defaultExtensions = updExts (defaultExtensions x)} updExts s = nub (s ++ exts) appendCPPOptions :: [String] -> LocalBuildInfo -> LocalBuildInfo -appendCPPOptions opts l = +appendCPPOptions opts l = forBuildInfo l updBuildInfo where updBuildInfo x = x{cppOptions = updOpts (cppOptions x)} updOpts s = nub (s ++ opts) -formatMacro name value = "-D" ++ name ++ "=" ++ (show value) +formatMacro name value = "-D" ++ name ++ "=" ++ show value targetDataDir :: LocalBuildInfo -> FilePath -targetDataDir l = +targetDataDir l = let dirTmpls = installDirTemplates l prefix' = prefix dirTmpls data' = datadir dirTmpls @@ -201,7 +200,7 @@ findInParametersDefault :: [(String, String)] -> String -> String -> String findInParametersDefault al name def = (fromMaybe def . lookup name) al getDomainNameDefault :: [(String, String)] -> String -> String -getDomainNameDefault al d = findInParametersDefault al "x-gettext-domain-name" d +getDomainNameDefault al = findInParametersDefault al "x-gettext-domain-name" getDomainDefine :: [(String, String)] -> String getDomainDefine al = findInParametersDefault al "x-gettext-domain-def" "__MESSAGE_CATALOG_DOMAIN__" @@ -212,8 +211,8 @@ getMsgCatalogDefine al = findInParametersDefault al "x-gettext-msg-cat-def" "__M getPoFilesDefault :: [(String, String)] -> IO [String] getPoFilesDefault al = toFileList $ findInParametersDefault al "x-gettext-po-files" "" where toFileList "" = return [] - toFileList x = liftM concat $ mapM matchFileGlob $ split' x + toFileList x = fmap concat $ mapM matchFileGlob $ split' x -- from Blow your mind (HaskellWiki) -- splits string by newline, space and comma - split' x = concatMap lines $ concatMap words $ unfoldr (\b -> fmap (const . (second $ drop 1) . break (==',') $ b) . listToMaybe $ b) x + split' x = concatMap lines $ concatMap words $ unfoldr (\b -> fmap (const . second (drop 1) . break (==',') $ b) . listToMaybe $ b) x @@ -12,7 +12,7 @@ import Distribution.Text ( display ) import Distribution.ModuleName (ModuleName) import qualified Distribution.ModuleName as ModuleName -import qualified GetText as GetText +import qualified GetText main :: IO () main = defaultMainWithHooks $ installBustleHooks simpleUserHooks diff --git a/Test/PcapCrash.hs b/Test/PcapCrash.hs index e28a69c..4d03ae1 100644 --- a/Test/PcapCrash.hs +++ b/Test/PcapCrash.hs @@ -17,5 +17,4 @@ main = do exitFailure -- TODO: check there are no warnings (but there are because we don't -- understand 'h', so we just skip it) - Right _ -> do - return () + Right _ -> return () diff --git a/Test/Regions.hs b/Test/Regions.hs index d4b46b0..720b2d3 100644 --- a/Test/Regions.hs +++ b/Test/Regions.hs @@ -4,7 +4,6 @@ import Test.QuickCheck.All import Data.List (sort, group) import Data.Maybe (isNothing, isJust) -import Control.Applicative ((<$>), (<*>)) import Bustle.Regions @@ -15,7 +14,7 @@ newtype NonOverlappingStripes = NonOverlappingStripes [Stripe] instance Arbitrary NonOverlappingStripes where arbitrary = do -- listOf2 - tops <- sort <$> ((:) <$> arbitrary <*> (listOf1 arbitrary)) + tops <- sort <$> ((:) <$> arbitrary <*> listOf1 arbitrary) -- Generate dense stripes sometimes let g :: Gen Double @@ -37,7 +36,7 @@ instance (Eq a, Arbitrary a) => Arbitrary (ValidRegions a) where values <- vector (length stripes) `suchThat` unique return $ ValidRegions (zip stripes values) where - unique xs = all (== 1) . map length . group $ xs + unique = all (== 1) . map length . group instance (Eq a, Arbitrary a) => Arbitrary (RegionSelection a) where arbitrary = do @@ -46,8 +45,8 @@ instance (Eq a, Arbitrary a) => Arbitrary (RegionSelection a) where prop_NonOverlapping_generator_works (NonOverlappingStripes ss) = nonOverlapping ss -prop_InitiallyUnselected = \rs -> isNothing $ rsCurrent rs -prop_UpDoesNothing = \rs -> isNothing $ rsCurrent $ regionSelectionUp rs +prop_InitiallyUnselected rs = isNothing $ rsCurrent rs +prop_UpDoesNothing rs = isNothing $ rsCurrent $ regionSelectionUp rs prop_DownDoesNothing vr@(ValidRegions regions) = withRegions vr $ \rs -> @@ -130,11 +129,10 @@ randomMutation = do ] randomMutations :: Gen (RegionSelection a -> RegionSelection a) -randomMutations = do - fs <- listOf randomMutation - return $ foldr (.) id fs +randomMutations = + foldr (.) id <$> listOf randomMutation -prop_ClickAlwaysInSelection = \rs -> +prop_ClickAlwaysInSelection rs = forAll (fmap Blind randomMutations) $ \(Blind f) -> let rs' = f rs diff --git a/bustle.cabal b/bustle.cabal index 125d8b1..26c22ca 100644 --- a/bustle.cabal +++ b/bustle.cabal @@ -1,7 +1,7 @@ Name: bustle Category: Network, Desktop Version: 0.7.1.1 -Cabal-Version: >= 1.24 +Cabal-Version: >= 2.0 Tested-With: GHC == 8.2.2, GHC == 8.4.3 Synopsis: Draw sequence diagrams of D-Bus traffic Description: Draw sequence diagrams of D-Bus traffic @@ -56,8 +56,8 @@ x-gettext-domain-name: bustle custom-setup setup-depends: - base >= 4 && < 5, - Cabal >= 1.24, + base >= 4.11 && < 5, + Cabal >= 2.0, filepath, directory, process @@ -114,7 +114,7 @@ Executable bustle cc-options: -fPIC -g pkgconfig-depends: glib-2.0 >= 2.54, gio-unix-2.0 - Build-Depends: base >= 4 && < 5 + Build-Depends: base >= 4.11 && < 5 , bytestring , cairo , containers diff --git a/stack.yaml b/stack.yaml new file mode 100644 index 0000000..6d13ece --- /dev/null +++ b/stack.yaml @@ -0,0 +1,10 @@ +resolver: nightly-2018-06-29 +packages: +- . +allow-newer: true +extra-deps: +- gio-0.13.5.0 +- gtk3-0.14.9 +- hgettext-0.1.31.0 +- pcap-0.4.5.2 + |