packages feed

anitomata-aseprite 0.1.0.0 → 0.1.1.0

raw patch · 4 files changed

+88/−64 lines, 4 filesdep −attoparsecdep −string-interpolatePVP ok

version bump matches the API change (PVP)

Dependencies removed: attoparsec, string-interpolate

API changes (from Hackage documentation)

+ Anitomata.Aseprite.Preprocessor: instance GHC.Show.Show Anitomata.Aseprite.Preprocessor.TagNameField
+ Anitomata.Aseprite.Preprocessor: instance GHC.Show.Show Anitomata.Aseprite.Preprocessor.TagRepeat

Files

CHANGELOG.md view
@@ -1,3 +1,7 @@+## 0.1.1.0++* Drop dependencies on `attoparsec` and `string-interpolate`+ ## 0.1.0.0  * Initial release
anitomata-aseprite.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           anitomata-aseprite-version:        0.1.0.0+version:        0.1.1.0 synopsis:       Code gen for Aseprite animations description:    @anitomata@ Haskell code generation for Aseprite animations. category:       Game@@ -41,13 +41,11 @@   ghc-options: -Weverything -Wno-missing-local-signatures -Wno-missing-exported-signatures -Wno-missing-import-lists -Wno-missed-specializations -Wno-all-missed-specializations -Wno-unsafe -Wno-safe -Wno-missing-safe-haskell-mode   build-depends:       aeson >=2.1.2.1 && <2.3-    , attoparsec >=0.14.4 && <0.15     , base >=4.17 && <4.20     , directory >=1.3.7.1 && <1.4     , filepath >=1.4.2.2 && <1.6     , module-munging ==0.1.*     , optparse-applicative >=0.17.1.0 && <0.19-    , string-interpolate >=0.3.2.1 && <0.4     , text >=2.0.2 && <2.2   default-language: GHC2021 
library/Anitomata/Aseprite/Preprocessor.hs view
@@ -3,7 +3,6 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE StrictData #-} module Anitomata.Aseprite.Preprocessor   ( preprocessor@@ -16,18 +15,20 @@ import Control.Applicative ((<**>)) import Data.Aeson (FromJSON) import Data.Kind (Type)-import Data.String.Interpolate (__i, i) import GHC.Generics (Generic) import GHC.Records (HasField(getField)) import ModuleMunging   ( DeclBody(..), DeclName(..), ModuleDeclaration(..), ModuleFragment(..), ModuleImport(..)   , ModuleImportStyle(..), ModuleName(..), buildModule, displayModule   )+import Text.ParserCombinators.ReadP (ReadP)+import Text.Printf (printf)+import Type.Reflection (Typeable, typeRep)  import Control.Monad qualified as Monad import Data.Aeson qualified as Aeson import Data.Aeson.Types qualified as Aeson.Types-import Data.Attoparsec.Text qualified as Attoparsec+import Data.Char qualified as Char import Data.List qualified as List import Data.Maybe qualified as Maybe import Data.Text (Text)@@ -37,6 +38,8 @@ import System.Directory qualified as Directory import System.Exit qualified as Exit import System.FilePath qualified as FilePath+import Text.Read qualified as Read+import Text.ParserCombinators.ReadP qualified as ReadP  preprocessor :: IO () preprocessor = do@@ -52,7 +55,7 @@     let atlasPath = dir ++ FilePath.addExtension baseName ".json"     atlasExists <- Directory.doesFileExist atlasPath     Monad.unless atlasExists do-      Exit.die [i|aseprite2haskell: Aseprite atlas JSON does not exist at "#{atlasPath}"|]+      Exit.die $ printf "aseprite2haskell: Aseprite atlas JSON does not exist at %s" atlasPath     pure atlasPath   atlas <- Aeson.eitherDecodeFileStrict atlasPath >>= \case     Left decodeErr -> Exit.die $ "aseprite2haskell: failed to parse JSON - " <> show decodeErr@@ -78,7 +81,7 @@     [] -> []     (FrameInfo { filename }, frameIdx) : xs ->       let builderName = mkBuilderName filename-          sliceName = [i|#{builderName}_slice|] :: String+          sliceName = printf "%s_slice" builderName :: String           (dir, mTagRepeat) = dirAndRepeatFromTags filename        in [ ModuleFragment               { moduleFragmentImports =@@ -105,25 +108,24 @@                   [ ModuleDeclaration True (DeclName builderName) $ DeclBody                       case mTagRepeat of                         Nothing ->-                          [__i|-                            #{builderName} :: AnimBuilder-                            #{builderName} = #{builderFn dir} #{sliceName}-                          |]+                          List.intercalate "\n"+                            [ printf "%s :: AnimBuilder" builderName+                            , printf "%s = %s %s" builderName (builderFn dir) sliceName+                            ]                         Just (TagRepeat n) ->-                          [__i|-                            #{builderName} :: AnimBuilder-                            #{builderName} = repeatAnim (AnimRepeatCount #{n}) $ #{builderFn dir} #{sliceName}-                          |]-                  , ModuleDeclaration True (DeclName sliceName) $ DeclBody-                      [__i|-                        #{sliceName} :: AnimSlice-                        #{sliceName} =-                          AnimSlice-                            { animSliceDir = #{toAnimDir dir}-                            , animSliceFrameDurs = U.slice #{frameIdx} #{1 + length xs} #{durationsVecName}-                            , animSliceFrames = U.slice #{frameIdx} #{1 + length xs} #{framesVecName}-                            }-                      |]+                          List.intercalate "\n"+                            [ printf "%s :: AnimBuilder" builderName+                            , printf "%s = repeatAnim (AnimRepeatCount %d) $ %s %s" builderName n (builderFn dir) sliceName+                            ]+                  , ModuleDeclaration True (DeclName sliceName) $ DeclBody $ List.intercalate "\n"+                      [ printf "%s :: AnimSlice" sliceName+                      , printf "%s =" sliceName+                      ,        "  AnimSlice"+                      , printf "    { animSliceDir = %s" (toAnimDir dir)+                      , printf "    , animSliceFrameDurs = U.slice %d %d %s" frameIdx (1 + length xs) durationsVecName+                      , printf "    , animSliceFrames = U.slice %d %d %s" frameIdx (1 + length xs) framesVecName+                      ,        "    }"+                      ]                   ]               }           ]@@ -174,17 +176,17 @@           ]       , moduleFragmentDeclarations =           [ ModuleDeclaration False (DeclName framesVecName) $ DeclBody $ List.intercalate "\n"-              [ [i|#{framesVecName} :: U.Vector AnimFrame|]-              , [i|#{framesVecName} = U.fromListN #{length xs}|]-              , "  [ " <> List.intercalate "\n  , " (sourceRect . frame <$> xs)-              , "  ]"+              [ printf "%s :: U.Vector AnimFrame" framesVecName+              , printf "%s = U.fromListN %d" framesVecName $ length xs+              , printf "  [ %s" $ List.intercalate "\n  , " (sourceRect . frame <$> xs)+              ,        "  ]"               ]           ]       }   where   sourceRect :: Frame -> String   sourceRect Frame { x, y, w, h } =-    [i|AnimFrame { animFrameX = #{x}, animFrameY = #{y}, animFrameW = #{w}, animFrameH = #{h} }|]+    printf "AnimFrame { animFrameX = %d, animFrameY = %d, animFrameW = %d, animFrameH = %d }" x y w h  mkDurations :: [FrameInfo] -> ModuleFragment mkDurations = \case@@ -203,10 +205,10 @@           ]       , moduleFragmentDeclarations =           [ ModuleDeclaration False (DeclName durationsVecName) $ DeclBody $ List.intercalate "\n"-              [ [i|#{durationsVecName} :: U.Vector Double|]-              , [i|#{durationsVecName} = U.fromListN #{length xs}|]-              , "  [ " <> List.intercalate "\n  , " (show . toSeconds . duration <$> xs)-              , "  ]"+              [ printf "%s :: U.Vector Double" durationsVecName+              , printf "%s = U.fromListN %d" durationsVecName $ length xs+              , printf "  [ %s" $ List.intercalate "\n  , " (show . toSeconds . duration <$> xs)+              ,        "  ]"               ]           ]       }@@ -241,34 +243,33 @@ data TagNameField = TagNameField   { file :: Text   , tag :: Text-  }+  } deriving stock (Show)  instance FromJSON TagNameField where   parseJSON :: Aeson.Value -> Aeson.Types.Parser TagNameField-  parseJSON = Aeson.withText "FromJSON TagNameField" \t -> do-    case Attoparsec.parseOnly tagnameFieldParser t of-      Left err -> fail err-      Right x -> pure x+  parseJSON = parseJSONViaReadP tagnameFieldParser -tagnameFieldParser :: Attoparsec.Parser TagNameField+tagnameFieldParser :: ReadP TagNameField tagnameFieldParser = do-  file <- Attoparsec.takeWhile1 (/= '|')-  _ <- Attoparsec.char '|'-  tag <- Attoparsec.takeWhile1 (/= '|')+  file <- Text.pack <$> ReadP.munch1 (/= '|')+  _ <- ReadP.char '|'+  tag <- Text.pack <$> ReadP.munch1 (/= '|')+  ReadP.eof   pure TagNameField { file, tag }  type TagRepeat :: Type newtype TagRepeat = TagRepeat Int+  deriving stock (Show)  instance FromJSON TagRepeat where   parseJSON :: Aeson.Value -> Aeson.Types.Parser TagRepeat-  parseJSON = Aeson.withText "FromJSON TagRepeat" \t -> do-    case Attoparsec.parseOnly tagRepeatParser t of-      Left err -> fail err-      Right x -> pure x+  parseJSON = parseJSONViaReadP tagRepeatParser -tagRepeatParser :: Attoparsec.Parser TagRepeat-tagRepeatParser = TagRepeat <$> Attoparsec.decimal+tagRepeatParser :: ReadP TagRepeat+tagRepeatParser = do+  count <- intParser+  ReadP.eof+  pure $ TagRepeat count  type Direction :: Type data Direction@@ -311,22 +312,20 @@   } deriving stock (Show)  mkBuilderName :: FilenameField -> String-mkBuilderName FilenameField { file, tag } = [i|#{file}_#{tag}|]+mkBuilderName FilenameField { file, tag } = printf "%s_%s" file tag  instance FromJSON FilenameField where   parseJSON :: Aeson.Value -> Aeson.Types.Parser FilenameField-  parseJSON = Aeson.withText "FromJSON FilenameField" \t -> do-    case Attoparsec.parseOnly filenameFieldParser t of-      Left err -> fail err-      Right x -> pure x+  parseJSON = parseJSONViaReadP filenameFieldParser -filenameFieldParser :: Attoparsec.Parser FilenameField+filenameFieldParser :: ReadP FilenameField filenameFieldParser = do-  file <- Text.map sanitize <$> Attoparsec.takeWhile1 (/= '|')-  _ <- Attoparsec.char '|'-  tag <- Text.map sanitize <$> Attoparsec.takeWhile1 (/= '|')-  _ <- Attoparsec.char '|'-  frameIndex <- Attoparsec.decimal+  file <- Text.pack . map sanitize <$> ReadP.munch1 (/= '|')+  _ <- ReadP.char '|'+  tag <- Text.pack . map sanitize <$> ReadP.munch1 (/= '|')+  _ <- ReadP.char '|'+  frameIndex <- intParser+  ReadP.eof   pure FilenameField { file, tag, frameIndex }   where   sanitize :: Char -> Char@@ -376,3 +375,28 @@     { preprocessorOptsOrigSourceFile     , preprocessorOptsOutputFile     }++parseJSONViaReadP+  :: forall a+   . (Show a, Typeable a)+  => ReadP a+  -> Aeson.Types.Value+  -> Aeson.Types.Parser a+parseJSONViaReadP parser =+  Aeson.withText (printf "FromJSON %s" $ show $ typeRep @a) \case+    t -> case ReadP.readP_to_S parser s of+      [] -> fail $ printf "Parse failed on input: %s" s+      [(x, _)] -> pure x+      xs -> fail $ printf "Produced too many parses - input: %s, parses: %s" s $ show xs+      where+      s = Text.unpack t++intParser :: ReadP Int+intParser = do+  digitChars <- ReadP.many1 digitParser+  case Read.readMaybe digitChars of+    Nothing -> fail $ printf "Failed to read digits as Int: %s" digitChars+    Just x -> pure x++digitParser :: ReadP Char+digitParser = ReadP.satisfy Char.isDigit
package.yaml view
@@ -1,5 +1,5 @@ name: anitomata-aseprite-version: 0.1.0.0+version: 0.1.1.0 homepage: https://sr.ht/~jship/anitomata/ git: https://git.sr.ht/~jship/anitomata/ license: MIT@@ -40,13 +40,11 @@ library:   dependencies:   - aeson >= 2.1.2.1 && <2.3-  - attoparsec >= 0.14.4 && <0.15   - base >= 4.17 && <4.20   - directory >= 1.3.7.1 && <1.4   - filepath >= 1.4.2.2 && <1.6   - module-munging >= 0.1 && <0.2   - optparse-applicative >= 0.17.1.0 && <0.19-  - string-interpolate >=0.3.2.1 && <0.4   - text >=2.0.2 && <2.2   source-dirs: library