hmp3-ng 2.16.2 → 2.17.0
raw patch · 10 files changed
+43/−60 lines, 10 files
Files
- Base.hs +1/−1
- Core.hs +20/−31
- FastIO.hs +12/−19
- Keymap.hs +1/−1
- Lexer.hs +3/−3
- State.hs +1/−1
- Syntax.hs +1/−1
- Tree.hs +1/−1
- UI.hs +2/−1
- hmp3-ng.cabal +1/−1
Base.hs view
@@ -35,7 +35,7 @@ import Data.Foldable as X import Data.Functor as X hiding (unzip) import Data.IORef as X-import Data.List as X ((\\), group, groupBy, isPrefixOf, sort, sortBy, intersperse)+import Data.List as X import Data.Maybe as X import Data.String as X import Data.Traversable as X
Core.hs view
@@ -66,7 +66,6 @@ import System.Clock (TimeSpec(..), diffTimeSpec) import System.Random (randomIO) import System.FilePath ((</>))-import Data.List (isInfixOf, tails) import System.Posix.Process (exitImmediately) @@ -115,7 +114,7 @@ loadConfig when (0 <= (snd . bounds $ fs)) do- if mode == Random then playRandom else playCur+ if mode == Random then modifySTM jumpToRandom else playCur when (not playNow) pause run -- won't restart if this fails!@@ -405,11 +404,6 @@ let fe = music st ! cursor st in P.intercalate (P.singleton '/') [dname $ folders st ! fdir fe, fbase fe] ---- | Play a random song-playRandom :: IO ()-playRandom = modifySTM jumpToRandom- -- | Jump to a random song jumpToRandom :: HState -> IO HState jumpToRandom st = do@@ -421,29 +415,25 @@ -- If we're at the beginning, and loop mode is on, then loop to the end -- If we're in random mode, play the next random track playPrev :: IO ()-playPrev = do- md <- getsST mode- if md == Random then playRandom else- modifySTM $ \st -> do- let i = current st- if- | i > 0 -> playAtN st (subtract 1) -- just the prev track- | mode st == Loop -> playAtN st (const (size st - 1)) -- maybe loop- | otherwise -> pure st -- else stop at end+playPrev = modifySTM \st -> case mode st of+ Random -> jumpToRandom st+ Single -> pure st+ _ | current st > 0+ -> playAtN st (subtract 1)+ Loop -> playAtN st (const (size st - 1))+ Once -> pure st -- | Play the song following the current song, if we're not at the end -- If we're at the end, and loop mode is on, then loop to the start -- If we're in random mode, play the next random track playNext :: IO ()-playNext = do- md <- getsST mode- if md == Random then playRandom else- modifySTM $ \st -> do- let i = current st- if- | i < size st - 1 -> playAtN st (+ 1) -- just the next track- | mode st == Loop -> playAtN st (const 0) -- maybe loop- | otherwise -> pure st -- else stop at end+playNext = modifySTM \st -> case mode st of+ Random -> jumpToRandom st+ Single -> pure st+ _ | current st < size st - 1+ -> playAtN st (+ 1)+ Loop -> playAtN st (const 0)+ Once -> pure st -- | Generic next song selection -- If the cursor and current are currently the same, continue that.@@ -647,12 +637,11 @@ if b then do str' <- readFile f str <- let (old, new) = ("hmp3_helpscreen", "hmp3_modals") in- if old `isInfixOf` str'- then do- warnA $ old ++ " is now " ++ new ++ " in style.conf"- let (ix, rest) = head $ filter (\ (_, s) -> old `isPrefixOf` s) $ zip [0..] $ tails str'- pure $ take ix str' ++ new ++ drop (length old) rest- else pure str'+ case findIndex (old `isPrefixOf`) $ tails str' of+ Just ix -> do+ warnA $ old ++ " is now " ++ new ++ " in style.conf"+ pure $ take ix str' ++ new ++ drop (ix + length old) str'+ _ -> pure str' case readMaybe str of Nothing -> do warnA "Parse error in style.conf"
FastIO.hs view
@@ -26,9 +26,7 @@ import Syntax (Pretty(ppr)) -import qualified Data.ByteString.Char8 as P-import qualified Data.ByteString as B-import qualified Data.ByteString.Internal as B+import qualified Data.ByteString.Char8 as B import System.Posix.Files.ByteString import System.Posix.Directory.ByteString@@ -43,22 +41,22 @@ -- | Packed string version of basename basenameP :: ByteString -> ByteString-basenameP fps = case P.elemIndexEnd '/' fps of+basenameP fps = case B.elemIndexEnd '/' fps of Nothing -> fps- Just i -> P.drop (i+1) fps+ Just i -> B.drop (i+1) fps {-# INLINE basenameP #-} dirnameP :: ByteString -> ByteString-dirnameP fps = case P.elemIndexEnd '/' fps of+dirnameP fps = case B.elemIndexEnd '/' fps of Nothing -> "."- Just i -> P.take i fps+ Just i -> B.take i fps {-# INLINE dirnameP #-} -- | Packed version of listDirectory packedGetDirectoryContents :: ByteString -> IO [ByteString] packedGetDirectoryContents fp = bracket (openDirStream fp) closeDirStream $ \ds -> fmap (filter (\p -> p/="." && p/=".."))- $ sequenceWhile (not . P.null) $ repeat $ readDirStream ds+ $ sequenceWhile (not . B.null) $ repeat $ readDirStream ds doesFileExist :: ByteString -> IO Bool doesFileExist fp = catch @SomeException@@ -72,7 +70,7 @@ packedFileNameEndClean :: ByteString -> ByteString packedFileNameEndClean name =- case P.unsnoc name of+ case B.unsnoc name of Just (name', ec) | ec == '\\' || ec == '/' -> packedFileNameEndClean name' _ -> name@@ -105,17 +103,12 @@ -- --------------------------------------------------------------------- -- | Send a msg over the channel to the decoder send :: Pretty a => Handle -> a -> IO ()-send h m = P.hPut h (ppr m) >> P.hPut h "\n" >> hFlush h+send h m = B.hPut h (ppr m) >> B.hPut h "\n" >> hFlush h ------------------------------------------------------------------------ --- | 'dropSpaceEnd' efficiently returns the 'ByteString' argument with--- white space removed from the end. I.e.,--- --- > reverse . (dropWhile isSpace) . reverse == dropSpaceEnd-dropSpaceEnd :: ByteString -> ByteString-{-# INLINE dropSpaceEnd #-}-dropSpaceEnd bs = P.take (P.length bs - count) bs where- count = B.foldl' go 0 bs- go n c = if B.isSpaceWord8 c then n+1 else 0+-- ---------------------------------------------------------------------+trim :: ByteString -> ByteString+{-# INLINE trim #-}+trim = B.dropWhileEnd isSpace . B.dropSpace
Keymap.hs view
@@ -33,7 +33,7 @@ module Keymap where import Prelude ()-import Base hiding (all)+import Base hiding (all, delete) import Core import Config (package)
Lexer.hs view
@@ -25,7 +25,7 @@ import Base import Syntax (Msg(..),Status(..),Frame(..),Info(..),Id3(..),File(..),Tag(..))-import FastIO (FiltHandle(..), checkF, getPacket, dropSpaceEnd)+import FastIO (FiltHandle(..), checkF, getPacket, trim) import qualified Data.ByteString.Char8 as P import qualified Data.ByteString.UTF8 as UTF8@@ -93,7 +93,7 @@ -- Track info if ID fields are in the file, otherwise file name. -- 30 chars per field? doI :: ByteString -> Msg-doI s = let f = dropSpaceEnd . P.dropWhile isSpace $ s+doI s = let f = trim s in case P.take 4 f of cs | cs == "ID3:" -> F . File $ let ttl = toId id3 . splitUp . P.drop 4 $ f@@ -137,7 +137,7 @@ -- strip spaces, and decide if UTF-8 or ISO-8859-1 normalise :: ByteString -> ByteString normalise raw =- let bs = P.dropWhile isSpace . dropSpaceEnd $ raw+ let bs = trim raw in if UTF8.replacement_char `elem` UTF8.toString bs then UTF8.fromString $ P.unpack bs else bs
State.hs view
@@ -119,7 +119,7 @@ ,config = Config.defaultStyle ,boottime = 0 ,status = Stopped- ,mode = Normal+ ,mode = Once ,minibuffer = Fast mempty defaultSty ,uptime = mempty ,drawLock = unsafePerformIO (newMVar ())
Syntax.hs view
@@ -139,7 +139,7 @@ | Playing deriving stock (Eq, Show) -data Mode = Normal | Loop | Random+data Mode = Once | Loop | Random | Single deriving stock (Eq, Bounded, Enum, Show, Read) ------------------------------------------------------------------------
Tree.hs view
@@ -25,7 +25,7 @@ module Tree where -import Base+import Base hiding (partition) import FastIO import qualified Data.ByteString.Char8 as P
UI.hs view
@@ -414,7 +414,8 @@ draw dd = PMode2 case mode $ drawState dd of Random -> "rand" Loop -> "loop"- Normal -> "once"+ Once -> "once"+ Single -> "sing" ------------------------------------------------------------------------
hmp3-ng.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.2 name: hmp3-ng-version: 2.16.2+version: 2.17.0 synopsis: A 2019 fork of an ncurses mp3 player written in Haskell description: An mp3 player with a curses frontend. Playlists are populated by passing file and directory names on the command line. 'h' displays