packages feed

epub-tools 2.1.1 → 2.2

raw patch · 20 files changed

+551/−521 lines, 20 filesdep ~epub-metadata

Dependency ranges changed: epub-metadata

Files

epub-tools.cabal view
@@ -1,6 +1,6 @@ name:                epub-tools cabal-version:       >= 1.8-version:             2.1.1+version:             2.2 build-type:          Simple license:             BSD3 license-file:        LICENSE@@ -12,11 +12,7 @@ synopsis:            Command line utilities for working with epub files description:         A suite of command-line utilities for creating and manipulating epub book files. Included are: epubmeta, epubname, epubzip category:            Application, Console-tested-with:         GHC >= 7.6.1--data-dir:            resources-data-files:          default.rules,-                     epubname-dsl-docs+tested-with:         GHC >= 7.6.2  extra-source-files:  testsuite/EpubTools/*.hs                      testsuite/EpubTools/Test/EpubName/*.hs@@ -28,7 +24,7 @@ executable           epubmeta    main-is:          EpubTools/epubmeta.hs    build-depends:    base >= 3 && < 5, bytestring, directory,-                     epub-metadata >= 2.3.2, filepath, mtl, process,+                     epub-metadata >= 3.0, filepath, mtl, process,                      zip-archive    hs-source-dirs:   src    other-modules:    EpubTools.EpubMeta.Display@@ -41,10 +37,12 @@  executable           epubname    main-is:          EpubTools/epubname.hs-   build-depends:    base >= 3 && < 5, directory, epub-metadata >= 2.3.2,+   build-depends:    base >= 3 && < 5, directory, epub-metadata >= 3.0,                      filepath, mtl, parsec, regex-compat    hs-source-dirs:   src-   other-modules:    EpubTools.EpubName.Format.Author+   other-modules:    EpubTools.EpubName.Doc.Dsl+                     EpubTools.EpubName.Doc.Rules+                     EpubTools.EpubName.Format.Author                      EpubTools.EpubName.Format.Compile                      EpubTools.EpubName.Format.Format                      EpubTools.EpubName.Format.PubYear@@ -59,14 +57,14 @@ test-suite           epubname-tests    type:             exitcode-stdio-1.0    main-is:          EpubTools/test-epubname.hs-   build-depends:    base, directory, epub-metadata >= 2.3.2, filepath,+   build-depends:    base, directory, epub-metadata >= 3.0, filepath,                      HUnit, mtl, parsec, regex-compat    hs-source-dirs:   src testsuite    ghc-options:      -Wall -rtsopts -with-rtsopts=-K32m  executable           epubzip    main-is:          EpubTools/epubzip.hs-   build-depends:    base >= 3 && < 5, directory, epub-metadata >= 2.3.2,+   build-depends:    base >= 3 && < 5, directory, epub-metadata >= 3.0,                      filepath, mtl, parsec, regex-compat    hs-source-dirs:   src    other-modules:    EpubTools.EpubZip.Opts
− resources/default.rules
@@ -1,102 +0,0 @@-magAeon-   titlePat "^A[eE]on ([^ ]+)$"-   name "AeonMagazine(wordNum 2 1)"--magAnalog-   titlePat "^(A[^ ]*).*, ([^ ]+) ([0-9]{4})$"-   name "(scrub 1)SF(3)-(monthNum 2)"--magApex-   titlePat "^(Apex)[^0-9]*([0-9]+)$"-   name "(scrub 1)Magazine(pad 3 2)"--magBcs-   titlePat "(Beneath Ceaseless.*) #([0-9]+).*"-   name "(scrub 1)_Issue(pad 3 2)"--magBlackStatic-   titlePat "^(Black Static Horror Magazine)[^0-9]*([0-9]+)$"-   name "(scrub 1)(pad 2 2)"--magChallengingDestiny-   titlePat "^(Challenging Destiny) #([0-9]+).*"-   name "(scrub 1)Magazine(pad 3 2)"--magClarkesworld-   titlePat "^(Clarkesworld)[^0-9]*([0-9]+)$"-   name "(1)(pad 3 2)"--magFantasyMag-   titlePat "^(Fantasy Magazine)[^0-9]+([0-9]+).*"-   name "(scrub 1)(pad 3 2)"--magEclipse_word-   titlePat "^(Eclipse) +([a-zA-Z]+)$"-   name "(1)(wordNum 2 2)"--magEclipse_num-   titlePat "^(Eclipse) +([0-9]+):.*"-   name "(1)(pad 2 2)"--magFsf-   authorMatch "Spilogale"-   titlePat ".* ([^ ]+) ([0-9]{4})$"-   name "FantasyScienceFiction(2)-(monthNum 1)"--magFutureOrbits-   titlePat "(Future Orbits) Issue ([0-9]+), ([^ ]+) ([0-9]{4})$"-   name "(scrub 1)Magazine(pad 2 2)_(4)-(monthNum 3)"--magGud-   authorMatch "GUD Magazine Authors"-   titlePat ".* Magazine Issue ([0-9]+) ::.*"-   name "GUDMagazine(pad 2 1)"--magInterzone_old-   titlePat "^(Interzone)[^0-9]*([0-9]+)$"-   name "(1)SFF(pad 3 2)"--magInterzone-   titlePat "^(Interzone) ([0-9]+).*$"-   name "(1)SFF(pad 3 2)"--magLightspeed_date-   titlePat "(Lightspeed) Magazine, (.*) (.*)"-   name "(1)(3)-(monthNum 2)"--magLightspeed_issue-   titlePat "(Lightspeed).* Issue (.*)"-   name "(1)(pad 3 2)"--magNemesis-   titlePat "(Nemesis Mag)azine #([0-9]+).*"-   name "(scrub 1)(pad 3 2)"--magRageMachine-   titlePat "(Rage Machine.*)--([^ ]+) ([0-9]{4})$"-   name "(scrub 1)_(3)-(monthNum 2)"--magSomethingWicked-   titlePat "^(Something Wicked)[^0-9]*([0-9]+)"-   name "(scrub 1)(pad 3 2)"--magUniverse-   titlePat "^(Jim Baen's Universe)-Vol ([^ ]+) Num ([^ ]+)"-   name "(scrub 1)Vol(pad 2 2)Num(pad 2 3)"--magWeirdTales-   titlePat "^(Weird Tales)[^0-9]*([0-9]+)$"-   name "(scrub 1)(pad 3 2)"--magLocus-   titlePat "^(Locus), ([a-zA-Z]+) ([0-9]{4})$"-   name "(scrub 1)Magazine(3)-(monthNum 2)"--anthology-   subjectMatch "anthology"-   titlePat "(.*)"-   name "(scrub 1)(year)"--ordinary_book-   titlePat "(.*)"-   name "(authors)(scrub 1)(year)"
− resources/epubname-dsl-docs
@@ -1,171 +0,0 @@-epubname rules documentation-------------------------------Book naming is controlled by a set of rules loaded from a file --At runtime, a rules file is searched for, first in the user's home directory and then in the installed files for epubname. The paths of these files specific to your system are listed in --help output.--The rules are checked, from first to last, for each file being renamed. The first rule that succeeds is used.---Rules have the following format:--   label-      authorMatch "..."-      subjectMatch "..."-      titlePat "..."-      name "..."--label is to identify what the rule is for to the user and also for verbose output (helpful for debugging rules)--The indented fields are rule commands and consist of:--   authorMatch - Optional. If present, it's a regexp pattern that must-      match an author in the book's metadata. If it doesn't match, this-      rule is rejected. This may be a partial match, "bar" will match if-      any author looks like "foo bar baz"--   subjectMatch - Optional. If present, it's a regexp pattern that must-      match an subject in the book's metadata. If it doesn't match, this-      rule is rejected. This may be a partial match, "bar" will match if-      any subject looks like "foo bar baz"--   titlePat - a regular expression for picking apart the title string in-      the book's metadata. The pieces in capture groups ( ) are exposed -      as numbered matches in the name construction field. If this match-      fails, this rule is rejected.--   name - instructions for building up a new book filename, most often-      using the parts extracted in titlePat. More on this below---In the name command, there are several functions that can be used. These functions are delimited with parenthesis in the name command's expression.--   authors - Get formatted authors from the metadata. If there are any-      authors, a hyphen will be placed after them in the resulting string.--      syntax: (authors)--   INT - Retrieve the text of a specific numbered item from the title-      pattern match results--      syntax: (INT)--   monthNum INDEX - Construct a numeric month from a variety of English-      months strings. Including abbreviations and ranges--      syntax: (monthNum INT)--      examples:-         "January"           -> "01"-         "Feb"               -> "02"-         "Mar-Apr"           -> "03_04"-         "September/October" -> "09_10"--   pad WIDTH INDEX - Pad a numeric value from the pattern match results--      syntax: (pad INT INT)--      examples:-         2 "3"    -> "03"-         3 "10"   -> "010"--   publisher - Get the formatted publisher file-as string from the-      metadata--      syntax: (publisher)--   scrub INDEX - Clean up an item from the pattern match results. A-      large number of punctuation is removed and/or converted into-      other characters, and the string is CamelCased. In the end, only-      alphanumerics, - and _ are used.--      syntax: (scrub INT)--   wordNum WIDTH INDEX - Construct a numeric string from an English word-      for a number, with padding. Works on strings from "One" to "Twenty"--      syntax: (wordNum INT INT)--      example:-         2 "One"    -> "01"-         3 "Twenty" -> "020"--   year - Get the formatted publication year from the metadata--      syntax: (year)--   Anything else, not in parenthesis, is a string literal to be used at-   that position in the resulting string.---This probably seems confusing, some examples may help.--This one is a fictitious magazine with issue and date info in the title:--   original book metadata:-      title: Adventurer's Weekly Issue 53, May 2008--   epubname rule:-      magAdventureWeekly-         titlePat "(Adventurer's Weekly) Issue ([0-9]+), ([^ ]+) ([0-9]{4})$"-         name "(scrub 1)Magazine(pad 3 2)_(4)-(monthNum 3)"--   resulting title:-      "AdventurersWeeklyMagazine053_2008-05"---Here's one using some more functions:--   original book metadata:-      title: Thrilling Journeys Three-      creator-         role: aut-         text: The Thrilling Authors--   epubname rule:-      compThrillingJourneys-         author "Thrilling Authors"-         titlePat "(Thrilling Journeys) (.*)"-         name "(scrub 1)(wordNum 2 2)"--   resulting title:-      "ThrillingJourneys03"---And here's what happens when an ordinary (non-periodical) book is formatted:--   original book metadata:-      title: Springtime in the Village-      creator-         role: aut-         file-as: Dandridge, Suzanne-         text: Suzanne Dandridge-      date-         event: publication-         text: 2012-10-09--   epubname rule:-      ordinary_book-         titlePat "(.*)"-         name "(authors)(scrub 1)(year)"--   resulting title:-      "DandridgeSuzanne-SpringtimeInTheVillage_2012"---The last rule in default.rules, ordinary_book is very important, and looks like this:--   ordinary_book-      titlePat "(.*)"-      name "(authors)(scrub 1)(year)"--This rule will match any book and is used to format all simple author-title situations. This rules is responsible for the basic epubname behavior and should always be present and always be last.---Preceding a rule label with ! will "switch off" the entire rule. It's a simple way to comment out a single rule in its entirety. example:--   !compThrillingJourneys-      author "Thrilling Authors"-      titlePat "(Thrilling Journeys) (.*)"-      name "(scrub 1)(wordNum 2 2)"
src/EpubTools/EpubMeta/Display.hs view
@@ -5,8 +5,8 @@ module EpubTools.EpubMeta.Display    where -import Codec.Epub.Opf.Format.Package-import Codec.Epub.Opf.Parse+import Codec.Epub2.Opf.Format.Package+import Codec.Epub2.Opf.Parse  import EpubTools.EpubMeta.Opts import EpubTools.EpubMeta.Util@@ -14,5 +14,5 @@  display :: Options -> FilePath -> EM () display opts zipPath = do-   meta <- parseEpubOpf zipPath+   meta <- parseEpub2Opf zipPath    liftIO $ putStr $ formatPackage (optVerbose opts) meta
src/EpubTools/EpubMeta/Export.hs view
@@ -6,7 +6,7 @@    ( exportOpf )    where -import Codec.Epub.IO+import Codec.Epub2.IO import System.FilePath  import EpubTools.EpubMeta.Opts
src/EpubTools/EpubMeta/Import.hs view
@@ -7,8 +7,8 @@    where  import Codec.Archive.Zip ( Entry (..), addEntryToArchive, readEntry, toArchive )-import Codec.Epub.Archive ( writeArchive )-import Codec.Epub.IO ( opfContentsFromBS )+import Codec.Epub2.Archive ( writeArchive )+import Codec.Epub2.IO ( opfContentsFromBS ) import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BL import Data.Maybe ( fromJust )
src/EpubTools/EpubMeta/Opts.hs view
@@ -92,7 +92,7 @@    where       header = init $ unlines          [ "Usage: epubmeta [OPTIONS] EPUBFILE"-         , "View or edit EPUB OPF package data"+         , "View or edit EPUB2 OPF package data"          , ""          , "Options:"          ]@@ -103,5 +103,5 @@          , ""          , "For more information please see the IDPF OPF specification found here: http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm"          , ""-         , "Version 2.1.1  Dino Morelli <dino@ui3.info>"+         , "Version 2.2  Dino Morelli <dino@ui3.info>"          ]
+ src/EpubTools/EpubName/Doc/Dsl.hs view
@@ -0,0 +1,184 @@+-- Copyright: 2013 Dino Morelli+-- License: BSD3 (see LICENSE)+-- Author: Dino Morelli <dino@ui3.info>++module EpubTools.EpubName.Doc.Dsl+   ( docs+   )+   where+++docs :: String+docs = unlines+   [ "epubname rules documentation"+   , "----------------------------"+   , ""+   , "Book naming is controlled by a set of rules loaded from a file "+   , ""+   , "At runtime, a rules file is searched for, first in the user's home directory and then in the installed files for epubname. The paths of these files specific to your system are listed in --help output."+   , ""+   , "The rules are checked, from first to last, for each file being renamed. The first rule that succeeds is used."+   , ""+   , ""+   , "Rules have the following format:"+   , ""+   , "   label"+   , "      authorMatch \"...\""+   , "      subjectMatch \"...\""+   , "      titlePat \"...\""+   , "      name \"...\""+   , ""+   , "label is to identify what the rule is for to the user and also for verbose output (helpful for debugging rules)"+   , ""+   , "The indented fields are rule commands and consist of:"+   , ""+   , "   authorMatch - Optional. If present, it's a regexp pattern that must"+   , "      match an author in the book's metadata. If it doesn't match, this"+   , "      rule is rejected. This may be a partial match, \"bar\" will match if"+   , "      any author looks like \"foo bar baz\""+   , ""+   , "   subjectMatch - Optional. If present, it's a regexp pattern that must"+   , "      match a subject in the book's metadata. If it doesn't match, this"+   , "      rule is rejected. This may be a partial match, \"bar\" will match if"+   , "      any subject looks like \"foo bar baz\""+   , ""+   , "   titlePat - a regular expression for picking apart the title string in"+   , "      the book's metadata. The pieces in capture groups ( ) are exposed "+   , "      as numbered matches in the name construction field. If this match"+   , "      fails, this rule is rejected."+   , ""+   , "   name - instructions for building up a new book filename, most often"+   , "      using the parts extracted in titlePat. More on this below"+   , ""+   , ""+   , "In the name command, there are several functions that can be used. These functions are delimited with parenthesis in the name command's expression."+   , ""+   , "   authors - Get formatted authors from the metadata. If there are any"+   , "      authors, a hyphen will be placed after them in the resulting string."+   , ""+   , "      syntax: (authors)"+   , ""+   , "   INT - Retrieve the text of a specific numbered item from the title"+   , "      pattern match results"+   , ""+   , "      syntax: (INT)"+   , ""+   , "   monthNum INDEX - Construct a numeric month from a variety of English"+   , "      months strings. Including abbreviations and ranges"+   , ""+   , "      syntax: (monthNum INT)"+   , ""+   , "      examples:"+   , "         \"January\"           -> \"01\""+   , "         \"Feb\"               -> \"02\""+   , "         \"Mar-Apr\"           -> \"03_04\""+   , "         \"September/October\" -> \"09_10\""+   , ""+   , "   pad WIDTH INDEX - Pad a numeric value from the pattern match results"+   , ""+   , "      syntax: (pad INT INT)"+   , ""+   , "      examples:"+   , "         2 \"3\"    -> \"03\""+   , "         3 \"10\"   -> \"010\""+   , ""+   , "   publisher - Get the formatted publisher file-as string from the"+   , "      metadata"+   , ""+   , "      syntax: (publisher)"+   , ""+   , "   scrub INDEX - Clean up an item from the pattern match results. A"+   , "      large number of punctuation is removed and/or converted into"+   , "      other characters, and the string is CamelCased. In the end, only"+   , "      alphanumerics, - and _ are used."+   , ""+   , "      syntax: (scrub INT)"+   , ""+   , "   wordNum WIDTH INDEX - Construct a numeric string from an English word"+   , "      for a number, with padding. Works on strings from \"One\" to \"Twenty\""+   , ""+   , "      syntax: (wordNum INT INT)"+   , ""+   , "      example:"+   , "         2 \"One\"    -> \"01\""+   , "         3 \"Twenty\" -> \"020\""+   , ""+   , "   year - Get the formatted publication year from the metadata"+   , ""+   , "      syntax: (year)"+   , ""+   , "   Anything else, not in parenthesis, is a string literal to be used at"+   , "   that position in the resulting string."+   , ""+   , ""+   , "This probably seems confusing, some examples may help."+   , ""+   , "This one is a fictitious magazine with issue and date info in the title:"+   , ""+   , "   original book metadata:"+   , "      title: Adventurer's Weekly Issue 53, May 2008"+   , ""+   , "   epubname rule:"+   , "      magAdventureWeekly"+   , "         titlePat \"(Adventurer's Weekly) Issue ([0-9]+), ([^ ]+) ([0-9]{4})$\""+   , "         name \"(scrub 1)Magazine(pad 3 2)_(4)-(monthNum 3)\""+   , ""+   , "   resulting title:"+   , "      \"AdventurersWeeklyMagazine053_2008-05\""+   , ""+   , ""+   , "Here's one using some more functions:"+   , ""+   , "   original book metadata:"+   , "      title: Thrilling Journeys Three"+   , "      creator"+   , "         role: aut"+   , "         text: The Thrilling Authors"+   , ""+   , "   epubname rule:"+   , "      compThrillingJourneys"+   , "         author \"Thrilling Authors\""+   , "         titlePat \"(Thrilling Journeys) (.*)\""+   , "         name \"(scrub 1)(wordNum 2 2)\""+   , ""+   , "   resulting title:"+   , "      \"ThrillingJourneys03\""+   , ""+   , ""+   , "And here's what happens when an ordinary (non-periodical) book is formatted:"+   , ""+   , "   original book metadata:"+   , "      title: Springtime in the Village"+   , "      creator"+   , "         role: aut"+   , "         file-as: Dandridge, Suzanne"+   , "         text: Suzanne Dandridge"+   , "      date"+   , "         event: publication"+   , "         text: 2012-10-09"+   , ""+   , "   epubname rule:"+   , "      ordinary_book"+   , "         titlePat \"(.*)\""+   , "         name \"(authors)(scrub 1)(year)\""+   , ""+   , "   resulting title:"+   , "      \"DandridgeSuzanne-SpringtimeInTheVillage_2012\""+   , ""+   , ""+   , "The last rule in the built-in rules, ordinary_book is very important, and looks like this:"+   , ""+   , "   ordinary_book"+   , "      titlePat \"(.*)\""+   , "      name \"(authors)(scrub 1)(year)\""+   , ""+   , "This rule will match any book and is used to format all simple author-title situations. This rules is responsible for the basic epubname behavior and should always be present and always be last."+   , ""+   , ""+   , "Preceding a rule label with ! will \"switch off\" the entire rule. It's a simple way to comment out a single rule in its entirety. example:"+   , ""+   , "   !compThrillingJourneys"+   , "      author \"Thrilling Authors\""+   , "      titlePat \"(Thrilling Journeys) (.*)\""+   , "      name \"(scrub 1)(wordNum 2 2)\""+   ]
+ src/EpubTools/EpubName/Doc/Rules.hs view
@@ -0,0 +1,115 @@+-- Copyright: 2013 Dino Morelli+-- License: BSD3 (see LICENSE)+-- Author: Dino Morelli <dino@ui3.info>++module EpubTools.EpubName.Doc.Rules+   ( defaults+   )+   where+++defaults :: String+defaults = unlines+   [ "magAeon"+   , "   titlePat \"^A[eE]on ([^ ]+)$\""+   , "   name \"AeonMagazine(wordNum 2 1)\""+   , ""+   , "magAnalog"+   , "   titlePat \"^(A[^ ]*).*, ([^ ]+) ([0-9]{4})$\""+   , "   name \"(scrub 1)SF(3)-(monthNum 2)\""+   , ""+   , "magApex"+   , "   titlePat \"^(Apex)[^0-9]*([0-9]+)$\""+   , "   name \"(scrub 1)Magazine(pad 3 2)\""+   , ""+   , "magBcs"+   , "   titlePat \"(Beneath Ceaseless.*) #([0-9]+).*\""+   , "   name \"(scrub 1)_Issue(pad 3 2)\""+   , ""+   , "magBlackStatic"+   , "   titlePat \"^(Black Static Horror Magazine)[^0-9]*([0-9]+)$\""+   , "   name \"(scrub 1)(pad 2 2)\""+   , ""+   , "magChallengingDestiny"+   , "   titlePat \"^(Challenging Destiny) #([0-9]+).*\""+   , "   name \"(scrub 1)Magazine(pad 3 2)\""+   , ""+   , "magClarkesworld"+   , "   titlePat \"^(Clarkesworld)[^0-9]*([0-9]+)$\""+   , "   name \"(1)(pad 3 2)\""+   , ""+   , "magFantasyMag"+   , "   titlePat \"^(Fantasy Magazine)[^0-9]+([0-9]+).*\""+   , "   name \"(scrub 1)(pad 3 2)\""+   , ""+   , "magEclipse_word"+   , "   titlePat \"^(Eclipse) +([a-zA-Z]+)$\""+   , "   name \"(1)(wordNum 2 2)\""+   , ""+   , "magEclipse_num"+   , "   titlePat \"^(Eclipse) +([0-9]+):.*\""+   , "   name \"(1)(pad 2 2)\""+   , ""+   , "magFsf"+   , "   authorMatch \"Spilogale\""+   , "   titlePat \".* ([^ ]+) ([0-9]{4})$\""+   , "   name \"FantasyScienceFiction(2)-(monthNum 1)\""+   , ""+   , "magFutureOrbits"+   , "   titlePat \"(Future Orbits) Issue ([0-9]+), ([^ ]+) ([0-9]{4})$\""+   , "   name \"(scrub 1)Magazine(pad 2 2)_(4)-(monthNum 3)\""+   , ""+   , "magGud"+   , "   authorMatch \"GUD Magazine Authors\""+   , "   titlePat \".* Magazine Issue ([0-9]+) ::.*\""+   , "   name \"GUDMagazine(pad 2 1)\""+   , ""+   , "magInterzone_old"+   , "   titlePat \"^(Interzone)[^0-9]*([0-9]+)$\""+   , "   name \"(1)SFF(pad 3 2)\""+   , ""+   , "magInterzone"+   , "   titlePat \"^(Interzone) ([0-9]+).*$\""+   , "   name \"(1)SFF(pad 3 2)\""+   , ""+   , "magLightspeed_date"+   , "   titlePat \"(Lightspeed) Magazine, (.*) (.*)\""+   , "   name \"(1)(3)-(monthNum 2)\""+   , ""+   , "magLightspeed_issue"+   , "   titlePat \"(Lightspeed).* Issue (.*)\""+   , "   name \"(1)(pad 3 2)\""+   , ""+   , "magNemesis"+   , "   titlePat \"(Nemesis Mag)azine #([0-9]+).*\""+   , "   name \"(scrub 1)(pad 3 2)\""+   , ""+   , "magRageMachine"+   , "   titlePat \"(Rage Machine.*)--([^ ]+) ([0-9]{4})$\""+   , "   name \"(scrub 1)_(3)-(monthNum 2)\""+   , ""+   , "magSomethingWicked"+   , "   titlePat \"^(Something Wicked)[^0-9]*([0-9]+)\""+   , "   name \"(scrub 1)(pad 3 2)\""+   , ""+   , "magUniverse"+   , "   titlePat \"^(Jim Baen's Universe)-Vol ([^ ]+) Num ([^ ]+)\""+   , "   name \"(scrub 1)Vol(pad 2 2)Num(pad 2 3)\""+   , ""+   , "magWeirdTales"+   , "   titlePat \"^(Weird Tales)[^0-9]*([0-9]+)$\""+   , "   name \"(scrub 1)(pad 3 2)\""+   , ""+   , "magLocus"+   , "   titlePat \"^(Locus), ([a-zA-Z]+) ([0-9]{4})$\""+   , "   name \"(scrub 1)Magazine(3)-(monthNum 2)\""+   , ""+   , "anthology"+   , "   subjectMatch \"anthology\""+   , "   titlePat \"(.*)\""+   , "   name \"(scrub 1)(year)\""+   , ""+   , "ordinary_book"+   , "   titlePat \"(.*)\""+   , "   name \"(authors)(scrub 1)(year)\""+   ]
src/EpubTools/EpubName/Format/Author.hs view
@@ -8,7 +8,7 @@    )    where -import Codec.Epub.Opf.Package+import Codec.Epub2.Opf.Package import Control.Monad import Data.List ( intercalate ) import Data.Maybe ( isJust )@@ -28,27 +28,27 @@       fmtAuthor cs = (formatMultiAuthors cs) ++ "-"  -separateCombined :: [MetaCreator] -> [MetaCreator]+separateCombined :: [Creator] -> [Creator] separateCombined = concatMap separateOne  -separateOne :: MetaCreator -> [MetaCreator]-separateOne c@(MetaCreator r _ di) =+separateOne :: Creator -> [Creator]+separateOne c@(Creator r _ di) =    case (splitRegex (mkRegex " (&|and) ") di) of       -- If there was only one, leave the file-as alone!       [_] -> [c]-      -- Otherwise, explode them into separate MetaCreatorS-      ss  -> map (MetaCreator r Nothing) ss+      -- Otherwise, explode them into separate CreatorS+      ss  -> map (Creator r Nothing) ss  -formatSingleAuthor :: MetaCreator -> String+formatSingleAuthor :: Creator -> String -formatSingleAuthor (MetaCreator _ (Just fa) di) = +formatSingleAuthor (Creator _ (Just fa) di) =     if ((fa == di) && all (/= ',') fa)-      then formatSingleAuthor $ MetaCreator Nothing Nothing di+      then formatSingleAuthor $ Creator Nothing Nothing di       else authorSingle [fa] -formatSingleAuthor (MetaCreator _ _         di) = +formatSingleAuthor (Creator _ _         di) =     authorSingle . reverse . nameParts $ di  @@ -70,20 +70,20 @@          , matchRegex (mkRegex "(.*)") s          ] -lastName :: MetaCreator -> String-lastName (MetaCreator _ (Just fa) _ ) = lastName' fa-lastName (MetaCreator _ _         di) = lastName' di+lastName :: Creator -> String+lastName (Creator _ (Just fa) _ ) = lastName' fa+lastName (Creator _ _         di) = lastName' di  -formatMultiAuthors :: [MetaCreator] -> String+formatMultiAuthors :: [Creator] -> String formatMultiAuthors = (intercalate "_") . (map lastName)  -justAuthors :: Metadata -> [MetaCreator]+justAuthors :: Metadata -> [Creator] justAuthors = (filter isAut) . metaCreators    where-      isAut (MetaCreator (Just "aut") _ _) = True-      isAut (MetaCreator Nothing      _ _) = True+      isAut (Creator (Just "aut") _ _) = True+      isAut (Creator Nothing      _ _) = True       isAut _                              = False  @@ -100,7 +100,7 @@ -} authorMatches :: String -> EN () authorMatches re = do-   let authorMatches' (MetaCreator _ _ di) =+   let authorMatches' (Creator _ _ di) =          matchRegex (mkRegex re) di     md <- asks gMetadata
src/EpubTools/EpubName/Format/Compile.hs view
@@ -14,8 +14,8 @@ import EpubTools.EpubName.Format.Format  -parseRules :: FilePath -> IO (Either ParseError [Formatter])-parseRules = parseFromFile pFormatters+parseRules :: SourceName -> String -> Either ParseError [Formatter]+parseRules name = runParser pFormatters () name   pFormatters :: Parser [Formatter]
src/EpubTools/EpubName/Format/Format.hs view
@@ -15,7 +15,7 @@    )    where -import Codec.Epub.Opf.Package+import Codec.Epub2.Opf.Package import Control.Monad.Error import Data.List ( isPrefixOf ) import Data.Maybe ( isJust )@@ -158,7 +158,7 @@ extractTitle re = do    md <- asks gMetadata -   (MetaTitle _ oldTitle) <- case metaTitles md of+   (Title _ oldTitle) <- case metaTitles md of       [] -> throwError "format failed, no title present"       ts -> return . head $ ts @@ -202,7 +202,7 @@    (foldr mplus Nothing (map maybePub $ metaContributors md))     where-      maybePub (MetaCreator (Just "bkp") (Just fa) _ ) = Just fa+      maybePub (Creator (Just "bkp") (Just fa) _ ) = Just fa       maybePub _                                       = Nothing  
src/EpubTools/EpubName/Format/PubYear.hs view
@@ -8,7 +8,7 @@    )    where -import Codec.Epub.Opf.Package+import Codec.Epub2.Opf.Package import Control.Monad import Text.Regex @@ -38,16 +38,16 @@          ]  -getDateWithAttr :: String -> [MetaDate] -> Maybe String+getDateWithAttr :: String -> [Date] -> Maybe String getDateWithAttr attrVal mds = foldr mplus Nothing $ map getPublication' mds    where-      getPublication' (MetaDate (Just av) d)+      getPublication' (Date (Just av) d)          | av == attrVal = extractYear d       getPublication' _  = Nothing  -getFirstDate :: [MetaDate] -> Maybe String-getFirstDate ((MetaDate _ d) : _) = extractYear d+getFirstDate :: [Date] -> Maybe String+getFirstDate ((Date _ d) : _) = extractYear d getFirstDate _                    = Nothing  
src/EpubTools/EpubName/Format/Util.hs view
@@ -12,7 +12,7 @@    )    where -import Codec.Epub.Opf.Package+import Codec.Epub2.Opf.Package import Control.Monad.Error import Control.Monad.Identity import Control.Monad.Reader
src/EpubTools/EpubName/Main.hs view
@@ -11,10 +11,11 @@    where  import Control.Monad.Error-import Data.List ( intercalate ) import System.Directory ( doesFileExist ) import System.Exit+import Text.Printf +import qualified EpubTools.EpubName.Doc.Rules as Rules import EpubTools.EpubName.Format.Compile import EpubTools.EpubName.Format.Format import EpubTools.EpubName.Opts@@ -31,18 +32,24 @@  initialize :: (MonadError ExitCode m, MonadIO m) =>    Options -> m [Formatter]-initialize opts = (locateRules opts) >>= loadFormatters+initialize opts = (locateRules $ optRulesPaths opts)+   >>= (loadFormatters $ optVerbose opts)   locateRules :: (MonadError ExitCode m, MonadIO m) =>-   Options -> m FilePath-locateRules opts = do-   let paths = optRulesPaths opts+   [FilePath] -> m (String, String)+locateRules paths = do    mbResult <- liftIO $ foldl (liftM2 mplus) (return Nothing)       $ map mbExists paths-   maybe (errNoRules paths) return mbResult+   maybe (return ("built-in", Rules.defaults))+      loadRules mbResult +   where+      loadRules p = do+         contents <- liftIO $ readFile p+         return (p, contents) + mbExists :: FilePath -> IO (Maybe FilePath) mbExists p = do    e <- doesFileExist p@@ -51,23 +58,18 @@       else return Nothing  -errNoRules :: (MonadError ExitCode m, MonadIO m) =>-   [FilePath] -> m FilePath-errNoRules paths = do-   liftIO $ do-      putStrLn "Unable to find rules file. Paths searched:"-      let indentedPaths = map ((++) "   ") paths-      putStrLn $ intercalate "\n" indentedPaths-   throwError exitInitFailure-- loadFormatters :: (MonadError ExitCode m, MonadIO m) =>-   FilePath -> m [Formatter]-loadFormatters rulesPath = do-   parseResult <- liftIO $ parseRules rulesPath+   (Maybe Int) -> (String, String) -> m [Formatter]+loadFormatters verbosity (name, contents) = case parseRules name contents of+   Left err  -> do+      _ <- liftIO $ printf "%s:\n%s" name (show err)+      throwError exitInitFailure+   Right fs  -> do+      liftIO $ showRulesSource verbosity name+      return fs -   case parseResult of-      Left err  -> do-         liftIO $ print err-         throwError exitInitFailure-      Right fs  -> return fs++showRulesSource :: (Monad m, PrintfType (t -> m ())) =>+   Maybe Int -> t -> m ()+showRulesSource (Just 1) name = printf "Rules loaded from: %s\n" name+showRulesSource _        _    = return ()
src/EpubTools/EpubName/Opts.hs view
@@ -18,7 +18,6 @@ import System.Exit import System.FilePath -import Paths_epub_tools import EpubTools.EpubName.Util  @@ -29,7 +28,8 @@   data Options = Options-   { optHelp         :: Bool+   { optDumpRules    :: Bool+   , optHelp         :: Bool    , optHelpRules    :: Bool    , optInteractive  :: Bool    , optNoAction     :: Bool@@ -49,22 +49,19 @@    homeDir <- getEnv"HOME"    return $ homeDir </> ".epubtools" </> defaultRulesFile -stockRulesPath :: IO FilePath-stockRulesPath = getDataFileName defaultRulesFile - defaultOptions :: IO Options defaultOptions = do    urp <- userRulesPath-   srp <- stockRulesPath     return Options-      { optHelp            = False+      { optDumpRules       = False+      , optHelp            = False       , optHelpRules       = False       , optInteractive     = False       , optNoAction        = False       , optPublisher       = False-      , optRulesPaths      = [ urp, srp ]+      , optRulesPaths      = [ urp ]       , optTargetDir       = "."       , optVerbose         = Nothing       , optPubYear         = Publication@@ -79,6 +76,9 @@    , Option ['D'] ["no-date"]       (NoArg (\opts -> opts { optPubYear = NoDate } ))        "Suppress inclusion of original publication year"+   , Option [] ["dump-rules"] +      (NoArg (\opts -> opts { optDumpRules = True } ))+      "Output built-in rules definitions, use to make your own"    , Option ['h'] ["help"]        (NoArg (\opts -> opts { optHelp = True } ))       "This help text"@@ -129,20 +129,16 @@   usageText :: IO String-usageText = do-   urp <- userRulesPath-   srp <- stockRulesPath-   return $ (usageInfo header options) ++ "\n" ++ footer urp srp-+usageText = return $ (usageInfo header options) ++ "\n" ++ footer    where       header = init $ unlines          [ "USAGE: epubname [OPTIONS] FILES"-         , "Rename EPUB book files with clear names based on their metadata"+         , "Rename EPUB2 book files with clear names based on their metadata"          , ""          , "OPTIONS:"          , ""          ]-      footer urp srp = init $ unlines+      footer = init $ unlines          [ "VERBOSITY LEVELS:"          , ""          , "   1 - Output which formatter processed the file"@@ -181,18 +177,21 @@          , ""          , "This software ships with a set of rules to properly name over 20 magazines and compilations that are commonly purchased by the developer. These default rules can be extended to add new publications, and used as an example."          , ""+         , "Another case is anthologies, which is to say: collections of works by multiple authors but not necessarily in periodical form. There is an anthology rule in the default rules that's set to look for any <dc:subject>anthology</dc:subject> tag in the metadata. In this case, the authors will be ignored and the title along with a publication year will be used (see above re: dc:date)"+         , ""          , "epubname will search the following locations for a rules file, in this order:"          , ""-         , "   " ++ urp-         , "   " ++ srp+         , "   Path specified in a --rules switch"+         , "   $HOME/.epubtools/default.rules"+         , "   Built-in rules, a comprehensive stock set of naming rules"          , ""-         , "Use the last one, in share, as a model for a custom file for your ~"+         , "Use the built-in rules as a model for a custom file. See --dump-rules above"          , ""          , "Please see --help-rules for more information on the syntax of the DSL in the rules file."          , ""          , ""-         , "For more information on the EPUB format, please see the IDPF OPF specification found here: http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm"+         , "For more information on the EPUB2 format, please see the IDPF OPF specification found here: http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm"          , ""          , ""-         , "Version 2.1.1  Dino Morelli <dino@ui3.info>"+         , "Version 2.2  Dino Morelli <dino@ui3.info>"          ]
src/EpubTools/EpubZip/Opts.hs view
@@ -48,7 +48,7 @@       header = init $ unlines          [ "Usage: epubzip [OPTIONS] DESTDIR"          , "       epubzip [OPTIONS] DESTDIR/EPUBFILE"-         , "Construct an epub zip archive from files in the current directory"+         , "Construct an EPUB2 zip archive from files in the current directory"          , ""          , "Options:"          ]@@ -68,5 +68,5 @@          , ""          , "For more information please see the IDPF OPF specification found here: http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm"          , ""-         , "Version 2.1.1  Dino Morelli <dino@ui3.info>"+         , "Version 2.2  Dino Morelli <dino@ui3.info>"          ]
src/EpubTools/epubname.hs view
@@ -4,9 +4,9 @@  {-# LANGUAGE FlexibleContexts #-} -import Codec.Epub.Opf.Format.Package-import Codec.Epub.Opf.Package-import Codec.Epub.Opf.Parse+import Codec.Epub2.Opf.Format.Package+import Codec.Epub2.Opf.Package+import Codec.Epub2.Opf.Parse import Control.Monad import Control.Monad.Error import System.Directory ( doesDirectoryExist, doesFileExist, renameFile )@@ -18,12 +18,13 @@                  ) import Text.Printf +import qualified EpubTools.EpubName.Doc.Dsl as Dsl+import qualified EpubTools.EpubName.Doc.Rules as Rules import EpubTools.EpubName.Format.Format ( Formatter (..), tryFormatting ) import EpubTools.EpubName.Main import EpubTools.EpubName.Opts ( Options (..), parseOpts, usageText ) import EpubTools.EpubName.Prompt ( PromptResult (..), prompt, continue ) import EpubTools.EpubName.Util-import Paths_epub_tools   {- Construct additional verbose output@@ -69,7 +70,7 @@          file path. Failures here will otherwise get lost in the output          when multiple books are processed at once.       -}-      epkg <- runErrorT $ parseEpubOpf oldPath+      epkg <- runErrorT $ parseEpub2Opf oldPath       pkg <- either          ( \msg -> throwError             $ printf "ERROR: File %s: %s" oldPath msg@@ -120,9 +121,13 @@        -- User asked for rules help, this is a special termination case       when (optHelpRules opts) $ do-         liftIO $ do-            rulesHelpPath <- getDataFileName "epubname-dsl-docs"-            readFile rulesHelpPath >>= putStrLn+         liftIO $ putStrLn Dsl.docs+         throwError ExitSuccess++      -- User asked for a dump of the built-in rules,+      -- this is a special termination case+      when (optDumpRules opts) $ do+         liftIO $ putStr Rules.defaults          throwError ExitSuccess        -- User asked for help, this is a special termination case
src/EpubTools/epubzip.hs view
@@ -2,10 +2,10 @@ -- License: BSD3 (see LICENSE) -- Author: Dino Morelli <dino@ui3.info> -import Codec.Epub.Archive-import Codec.Epub.IO-import Codec.Epub.Opf.Package-import Codec.Epub.Opf.Parse+import Codec.Epub2.Archive ( mkEpubArchive, writeArchive )+import Codec.Epub2.IO+import Codec.Epub2.Opf.Package+import Codec.Epub2.Opf.Parse import Control.Monad import Control.Monad.Error import System.Directory
testsuite/EpubTools/Test/EpubName/Format.hs view
@@ -7,7 +7,7 @@    )    where -import Codec.Epub.Opf.Package+import Codec.Epub2.Opf.Package import Control.Monad.Error import Test.HUnit ( Test (..), assertEqual ) import Test.HUnit.Base ( Assertion )@@ -96,8 +96,8 @@    assertNewName opts fs "minimal author" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing "Herman Melville"]-         , metaTitles = [MetaTitle Nothing "Moby Dick"]+         { metaCreators = [Creator Nothing Nothing "Herman Melville"]+         , metaTitles = [Title Nothing "Moby Dick"]          }       expected =          ( "ordinary_book"@@ -110,8 +110,8 @@    assertNewName opts fs "author is a single word" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing "Melville"]-         , metaTitles = [MetaTitle Nothing "Moby Dick"]+         { metaCreators = [Creator Nothing Nothing "Melville"]+         , metaTitles = [Title Nothing "Moby Dick"]          }       expected =          ( "ordinary_book"@@ -124,9 +124,9 @@    assertNewName opts fs "author with role" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator (Just "aut") Nothing+         { metaCreators = [Creator (Just "aut") Nothing             "Herman Melville"]-         , metaTitles = [MetaTitle Nothing "Moby Dick"]+         , metaTitles = [Title Nothing "Moby Dick"]          }       expected =          ( "ordinary_book"@@ -139,10 +139,10 @@    assertNewName opts fs "author with file-as" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing+         { metaCreators = [Creator Nothing             (Just "Melville, Herman")             "Herman Melville"]-         , metaTitles = [MetaTitle Nothing "Moby Dick"]+         , metaTitles = [Title Nothing "Moby Dick"]          }       expected =          ( "ordinary_book"@@ -155,10 +155,10 @@    assertNewName opts fs "author fully filled out" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator (Just "aut")+         { metaCreators = [Creator (Just "aut")             (Just "Melville, Herman")             "Herman Melville"]-         , metaTitles = [MetaTitle Nothing "Moby Dick"]+         , metaTitles = [Title Nothing "Moby Dick"]          }       expected =          ( "ordinary_book"@@ -172,14 +172,14 @@    where       meta = emptyMetadata          { metaCreators =-            [ MetaCreator (Just "aut") Nothing+            [ Creator (Just "aut") Nothing                "James Patrick Kelly"-            , MetaCreator (Just "aut") (Just "Kessel, John")+            , Creator (Just "aut") (Just "Kessel, John")                "John Kessel"-            , MetaCreator (Just "aut") Nothing+            , Creator (Just "aut") Nothing                "Jonathan Lethem"             ]-         , metaTitles = [MetaTitle Nothing+         , metaTitles = [Title Nothing             "Ninety Percent of Everything"]          }       expected =@@ -194,7 +194,7 @@    where       meta = emptyMetadata          { metaCreators = []-         , metaTitles = [MetaTitle Nothing+         , metaTitles = [Title Nothing             "Some Collection of Fine Stories, Volume 1"]          }       expected =@@ -209,12 +209,12 @@    where       meta = emptyMetadata          { metaCreators =-            [ MetaCreator (Just "edt") Nothing+            [ Creator (Just "edt") Nothing                "Graham Spindlewest"-            , MetaCreator (Just "ill") Nothing+            , Creator (Just "ill") Nothing                "Eva Tunglewacker"             ]-         , metaTitles = [MetaTitle Nothing+         , metaTitles = [Title Nothing             "Some Collection of Fine Stories, Volume 1"]          }       expected =@@ -230,14 +230,14 @@    where       meta = emptyMetadata          { metaCreators =-            [ MetaCreator (Just "edt") Nothing+            [ Creator (Just "edt") Nothing                "Graham Spindlewest"-            , MetaCreator (Just "ill") Nothing+            , Creator (Just "ill") Nothing                "Eva Tunglewacker"             ]-         , metaTitles = [MetaTitle Nothing+         , metaTitles = [Title Nothing             "Some Collection of Fine Stories, Volume 1"]-         , metaDates = [MetaDate (Just "publication")+         , metaDates = [Date (Just "publication")             "2008"]          }       expected =@@ -251,9 +251,9 @@    assertNewName opts fs "more than one author separated by & and/or and" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing+         { metaCreators = [Creator Nothing Nothing             "Yvonne Q. Anderson & Eva Tunglewacker and Jefferson Milner"]-         , metaTitles = [MetaTitle Nothing "Big Trouble"]+         , metaTitles = [Title Nothing "Big Trouble"]          }       expected =          ( "ordinary_book"@@ -266,8 +266,8 @@    assertNewName opts fs "title all caps" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing "Greg Bear"]-         , metaTitles = [MetaTitle Nothing "EON"]+         { metaCreators = [Creator Nothing Nothing "Greg Bear"]+         , metaTitles = [Title Nothing "EON"]          }       expected =          ( "ordinary_book"@@ -280,8 +280,8 @@    assertNewName opts fs "colon becomes underscore" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing "Ed Howdershelt"]-         , metaTitles = [MetaTitle Nothing +         { metaCreators = [Creator Nothing Nothing "Ed Howdershelt"]+         , metaTitles = [Title Nothing              "Book 1: 3rd World Products, Inc."]          }       expected =@@ -295,8 +295,8 @@    assertNewName opts fs "title with brackets" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing "Mercedes Lackey"]-         , metaTitles = [MetaTitle Nothing "SKitty [Shipscat series #1]"]+         { metaCreators = [Creator Nothing Nothing "Mercedes Lackey"]+         , metaTitles = [Title Nothing "SKitty [Shipscat series #1]"]          }       expected =          ( "ordinary_book"@@ -309,7 +309,7 @@    assertNewName opts fs "missing title" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing+         { metaCreators = [Creator Nothing Nothing             "Nobody McCrankypants"]          }       expected =@@ -323,9 +323,9 @@    assertNewName opts fs "big test of all punctuation" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing+         { metaCreators = [Creator Nothing Nothing             "Dino Morelli"]-         , metaTitles = [MetaTitle Nothing+         , metaTitles = [Title Nothing             "The *crazy*: Sand-box. Of Smedley's discontent/loathing, fear & Malnourishment? (Maybe not!); [Part #2]"]          }       expected =@@ -339,9 +339,9 @@    assertNewName opts fs "book with a publication year" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing "Jim Jones"]-         , metaTitles = [MetaTitle Nothing "A Timeless Story"]-         , metaDates = [MetaDate (Just "publication") "2003"]+         { metaCreators = [Creator Nothing Nothing "Jim Jones"]+         , metaTitles = [Title Nothing "A Timeless Story"]+         , metaDates = [Date (Just "publication") "2003"]          }       expected =          ( "ordinary_book"@@ -357,9 +357,9 @@    where       testOpts = opts { optPubYear = AnyDate }       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing "Jim Jones"]-         , metaTitles = [MetaTitle Nothing "A Timeless Story"]-         , metaDates = [MetaDate (Just "original-publication") "2003"]+         { metaCreators = [Creator Nothing Nothing "Jim Jones"]+         , metaTitles = [Title Nothing "A Timeless Story"]+         , metaDates = [Date (Just "original-publication") "2003"]          }       expected =          ( "ordinary_book"@@ -375,9 +375,9 @@    where       testOpts = opts { optPubYear = NoDate }       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing "Jim Jones"]-         , metaTitles = [MetaTitle Nothing "A Timeless Story"]-         , metaDates = [MetaDate (Just "original-publication") "2003"]+         { metaCreators = [Creator Nothing Nothing "Jim Jones"]+         , metaTitles = [Title Nothing "A Timeless Story"]+         , metaDates = [Date (Just "original-publication") "2003"]          }       expected =          ( "ordinary_book"@@ -390,8 +390,8 @@    assertNewName opts fs "Aeon magazine" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing "Aeon Authors"]-         , metaTitles = [MetaTitle Nothing "Aeon Eight"]+         { metaCreators = [Creator Nothing Nothing "Aeon Authors"]+         , metaTitles = [Title Nothing "Aeon Eight"]          }       expected =          ( "magAeon"@@ -404,8 +404,8 @@    assertNewName opts fs "AEon magazine" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing "AEon Authors"]-         , metaTitles = [MetaTitle Nothing "Aeon Thirteen"]+         { metaCreators = [Creator Nothing Nothing "AEon Authors"]+         , metaTitles = [Title Nothing "Aeon Thirteen"]          }       expected =          ( "magAeon"@@ -418,9 +418,9 @@    assertNewName opts fs "Apex Magazine, older, long title" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator (Just "aut") Nothing+         { metaCreators = [Creator (Just "aut") Nothing             "Apex Authors"]-         , metaTitles = [MetaTitle Nothing+         , metaTitles = [Title Nothing             "Apex Science Fiction and Horror Digest #9"]          }       expected =@@ -434,9 +434,9 @@    assertNewName opts fs "Apex Magazine, newer, short title" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator (Just "aut") Nothing+         { metaCreators = [Creator (Just "aut") Nothing             "Apex Authors"]-         , metaTitles = [MetaTitle Nothing+         , metaTitles = [Title Nothing             "Apex Magazine Issue 17"]          }       expected =@@ -451,9 +451,9 @@       "Challenging Destiny Magazine, short title" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing+         { metaCreators = [Creator Nothing Nothing             "Crystalline Sphere Authors"]-         , metaTitles = [MetaTitle Nothing+         , metaTitles = [Title Nothing             "Challenging Destiny #23"]          }       expected =@@ -468,9 +468,9 @@       "Challenging Destiny Magazine, long title" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing +         { metaCreators = [Creator Nothing Nothing              "Crystalline Sphere Authors"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Challenging Destiny #24: August 2007"]          }       expected =@@ -484,9 +484,9 @@    assertNewName opts fs "Analog" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing+         { metaCreators = [Creator Nothing Nothing             "Dell Magazine Authors"]-         , metaTitles = [MetaTitle Nothing+         , metaTitles = [Title Nothing             "Analog SFF, July-August 2003"]          }       expected =@@ -500,9 +500,9 @@    assertNewName opts fs "Asimovs" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing+         { metaCreators = [Creator Nothing Nothing             "Dell Magazine Authors"]-         , metaTitles = [MetaTitle Nothing+         , metaTitles = [Title Nothing             "Asimov's SF, August 2003"]          }       expected =@@ -516,15 +516,15 @@    where       meta = emptyMetadata          { metaCreators =-            [ MetaCreator (Just "aut") (Just "Howard, Kat & Tanzer, Molly & Beagle, Peter S. & Howard, Jonathan L. & Valentine, Genevieve & Vaughn, Carrie & Pilinovsky, Helen") "Kat Howard"-            , MetaCreator (Just "aut") Nothing "Molly Tanzer"-            , MetaCreator (Just "aut") Nothing "Peter S. Beagle"-            , MetaCreator (Just "aut") Nothing "Jonathan L. Howard"-            , MetaCreator (Just "aut") Nothing "Genevieve Valentine"-            , MetaCreator (Just "aut") Nothing "Carrie Vaughn"-            , MetaCreator (Just "aut") Nothing "Helen Pilinovsky"+            [ Creator (Just "aut") (Just "Howard, Kat & Tanzer, Molly & Beagle, Peter S. & Howard, Jonathan L. & Valentine, Genevieve & Vaughn, Carrie & Pilinovsky, Helen") "Kat Howard"+            , Creator (Just "aut") Nothing "Molly Tanzer"+            , Creator (Just "aut") Nothing "Peter S. Beagle"+            , Creator (Just "aut") Nothing "Jonathan L. Howard"+            , Creator (Just "aut") Nothing "Genevieve Valentine"+            , Creator (Just "aut") Nothing "Carrie Vaughn"+            , Creator (Just "aut") Nothing "Helen Pilinovsky"             ]-         , metaTitles = [MetaTitle Nothing+         , metaTitles = [Title Nothing             "Fantasy Magazine Issue 49"]          }       expected =@@ -538,9 +538,9 @@    assertNewName opts fs "FSF Magazine, short" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing+         { metaCreators = [Creator Nothing Nothing             "Spilogale Authors"]-         , metaTitles = [MetaTitle Nothing "FSF Oct/Nov 2003"]+         , metaTitles = [Title Nothing "FSF Oct/Nov 2003"]          }       expected =          ( "magFsf"@@ -553,9 +553,9 @@    assertNewName opts fs "FSF Magazine, short, comma" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing+         { metaCreators = [Creator Nothing Nothing             "Spilogale Authors"]-         , metaTitles = [MetaTitle Nothing "FSF, April 2008"]+         , metaTitles = [Title Nothing "FSF, April 2008"]          }       expected =          ( "magFsf"@@ -568,9 +568,9 @@    assertNewName opts fs "FSF Magazine, long" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing +         { metaCreators = [Creator Nothing Nothing              "Spilogale Authors"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "FSF Magazine, April 2006"]          }       expected =@@ -584,9 +584,9 @@    assertNewName opts fs "FSF Magazine, ampersand" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing+         { metaCreators = [Creator Nothing Nothing             "Spilogale"]-         , metaTitles = [MetaTitle Nothing "F&SF, Apr 2004"]+         , metaTitles = [Title Nothing "F&SF, Apr 2004"]          }       expected =          ( "magFsf"@@ -599,9 +599,9 @@    assertNewName opts fs "FSF Magazine, ampersand, spaces" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing+         { metaCreators = [Creator Nothing Nothing             "Spilogale"]-         , metaTitles = [MetaTitle Nothing "F & SF Dec 2003"]+         , metaTitles = [Title Nothing "F & SF Dec 2003"]          }       expected =          ( "magFsf"@@ -614,9 +614,9 @@    assertNewName opts fs "testMagFutureOrbits" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing +         { metaCreators = [Creator Nothing Nothing              "Vander Neut Publications, L.L.C."]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Future Orbits Issue 5, June/July 2002"]          }       expected =@@ -630,9 +630,9 @@    assertNewName opts fs "Gud Magazine, short" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing +         { metaCreators = [Creator Nothing Nothing              "GUD Magazine Authors"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "GUD Magazine Issue 0 :: Spring 2007"]          }       expected =@@ -646,9 +646,9 @@    assertNewName opts fs "Gud Magazine, long" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing +         { metaCreators = [Creator Nothing Nothing              "GUD Magazine Authors, Jeff Somers, Jeremy Shipp"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "GUD Magazine Issue 2 :: Spring 2008"]          }       expected =@@ -662,9 +662,9 @@    assertNewName opts fs "Gud Magazine, very long" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing +         { metaCreators = [Creator Nothing Nothing              "GUD Magazine Authors"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Greatest Uncommon Denominator Magazine Issue 4 :: Spring 2009"]          }       expected =@@ -678,9 +678,9 @@    assertNewName opts fs "Interzone Magazine, old style, short" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing +         { metaCreators = [Creator Nothing Nothing              "TTA Press Authors"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Interzone SFF #212"]          }       expected =@@ -694,9 +694,9 @@    assertNewName opts fs "Interzone Magazine, old style, long" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing +         { metaCreators = [Creator Nothing Nothing              "TTA Press Authors"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Interzone Science Fiction and Fantasy Magazine #216"]          }       expected =@@ -710,9 +710,9 @@    assertNewName opts fs "Interzone Magazine, Smashwords style" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing +         { metaCreators = [Creator Nothing Nothing              "TTA Press"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Interzone 233 Mar - Apr 2011"]          }       expected =@@ -726,9 +726,9 @@    assertNewName opts fs "Nemesis Magazine, short" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing +         { metaCreators = [Creator Nothing Nothing              "Stephen Adams"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Nemesis Magazine #2"]          }       expected =@@ -742,9 +742,9 @@    assertNewName opts fs "Nemesis Magazine, long" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing +         { metaCreators = [Creator Nothing Nothing              "Stephen Adams"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Nemesis Magazine #7: Featuring Victory Rose in Death Stalks the Ruins"]          }       expected =@@ -758,9 +758,9 @@    assertNewName opts fs "Something Wicked Magazine" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing +         { metaCreators = [Creator Nothing Nothing              "Something Wicked Authors"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Something Wicked SF and Horror Magazine #5"]          }       expected =@@ -774,10 +774,10 @@    assertNewName opts fs "Something Wicked Magazine, month in title" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator (Just "aut")+         { metaCreators = [Creator (Just "aut")             (Just "Authors, Something Wicked")             "Something Wicked Authors"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Something Wicked #14 (October 2011)"]          }       expected =@@ -791,9 +791,9 @@    assertNewName opts fs "Science Fiction: The Best of the Year" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing +         { metaCreators = [Creator Nothing Nothing              "Rich Horton"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Science Fiction: The Best of the Year, 2007 Edition"]          , metaSubjects = ["anthology"]          }@@ -809,10 +809,10 @@       meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator (Just "aut")+         { metaCreators = [Creator (Just "aut")             (Just "Strahan, Jonathan")             "Jonathan Strahan"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "The Best Science Fiction and Fantasy of the Year: Volume 2"]          , metaSubjects = ["anthology"]          }@@ -827,9 +827,9 @@    assertNewName opts fs "The Year's Best SF" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator (Just "aut") Nothing +         { metaCreators = [Creator (Just "aut") Nothing              "Rich Horton, Michael Swanwick, Karen Joy Fowler"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "The Year's Best Science Fiction: 2008 Edition"]          , metaSubjects = ["anthology"]          }@@ -844,9 +844,9 @@    assertNewName opts fs "Black Static Magazine" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator Nothing Nothing +         { metaCreators = [Creator Nothing Nothing              "TTA Press Authors"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Black Static Horror Magazine #5"]          }       expected =@@ -860,9 +860,9 @@    assertNewName opts fs "Rage Machine Magazine" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator (Just "edt") Nothing +         { metaCreators = [Creator (Just "edt") Nothing              "G. W. Thomas"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Rage Machine Magazine #1--December 2005"]          }       expected =@@ -876,10 +876,10 @@    assertNewName opts fs "Eclipse Magazine" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator (Just "aut")+         { metaCreators = [Creator (Just "aut")             (Just "Strahan, Jonathan")             "Jonathan Strahan"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Eclipse One"]          }       expected =@@ -893,10 +893,10 @@    assertNewName opts fs "Eclipse Magazine" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator (Just "aut")+         { metaCreators = [Creator (Just "aut")             (Just "Strahan, Jonathan")             "Jonathan Strahan"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Eclipse 4: New Science Fiction and Fantasy"]          }       expected =@@ -911,14 +911,14 @@    where       meta = emptyMetadata          { metaCreators = -            [ MetaCreator (Just "aut")+            [ Creator (Just "aut")                (Just "Tidwell, Erin A.")                "Hoover, Kenneth Mark"-            , MetaCreator (Just "aut")+            , Creator (Just "aut")                (Just "Tidwell, Erin A.")                "Tidwell, Erin A."             ]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Beneath Ceaseless Skies #32"]          }       expected =@@ -935,11 +935,11 @@    where       testOpts = opts { optPublisher = True }       meta = emptyMetadata-         { metaCreators = [MetaCreator (Just "aut") Nothing+         { metaCreators = [Creator (Just "aut") Nothing             "Herman Melville"]-         , metaContributors = [MetaCreator (Just "bkp") (Just "acme") +         , metaContributors = [Creator (Just "bkp") (Just "acme")              "Acme Publishing, Inc."]-         , metaTitles = [MetaTitle Nothing "Moby Dick"]+         , metaTitles = [Title Nothing "Moby Dick"]          }       expected =          ( "ordinary_book"@@ -955,11 +955,11 @@    where       testOpts = opts { optPublisher = True }       meta = emptyMetadata-         { metaCreators = [MetaCreator (Just "aut") Nothing+         { metaCreators = [Creator (Just "aut") Nothing             "Herman Melville"]-         , metaContributors = [MetaCreator (Just "bkp") Nothing+         , metaContributors = [Creator (Just "bkp") Nothing             "Acme Publishing, Inc."]-         , metaTitles = [MetaTitle Nothing "Moby Dick"]+         , metaTitles = [Title Nothing "Moby Dick"]          }       expected =          ( "ordinary_book"@@ -975,9 +975,9 @@    where       testOpts = opts { optPublisher = True }       meta = emptyMetadata-         { metaCreators = [MetaCreator (Just "aut") Nothing+         { metaCreators = [Creator (Just "aut") Nothing             "Herman Melville"]-         , metaTitles = [MetaTitle Nothing "Moby Dick"]+         , metaTitles = [Title Nothing "Moby Dick"]          }       expected =          ( "ordinary_book"@@ -993,9 +993,9 @@    where       testOpts = opts { optPublisher = True }       meta = emptyMetadata-         { metaCreators = [MetaCreator (Just "aut") Nothing+         { metaCreators = [Creator (Just "aut") Nothing             "Jim Baen's Universe"]-         , metaTitles = [MetaTitle Nothing "Jim Baen's Universe-Vol 4 Num 6"]+         , metaTitles = [Title Nothing "Jim Baen's Universe-Vol 4 Num 6"]          }       expected =          ( "magUniverse"@@ -1008,10 +1008,10 @@    assertNewName opts fs "Clarkesworld Magazine" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator (Just "aut")+         { metaCreators = [Creator (Just "aut")             (Just "Kowal, Mary Robinette")             "Mary Robinette Kowal"]-         , metaTitles = [MetaTitle Nothing+         , metaTitles = [Title Nothing             "Clarkesworld Magazine - Issue 21"]          }       expected =@@ -1025,9 +1025,9 @@    assertNewName opts fs "Lightspeed Magazine, date in title" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator (Just "aut") Nothing+         { metaCreators = [Creator (Just "aut") Nothing             "Edited by John Joseph Adams"]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Lightspeed Magazine, June 2010"]          }       expected =@@ -1042,8 +1042,8 @@       "Lightspeed Magazine, issue number in title" meta expected    where       meta = emptyMetadata-         { metaCreators = [MetaCreator (Just "aut") (Just "Magazine, Lightspeed & Clark, Maggie & Valentine, Genevieve & Baxter, Stephen & Okorafor, Nnedi & Wilison, Daniel H. & Reed, Robert & Sedia, Ekaterina") "Lightspeed Magazine"]-         , metaTitles = [MetaTitle Nothing +         { metaCreators = [Creator (Just "aut") (Just "Magazine, Lightspeed & Clark, Maggie & Valentine, Genevieve & Baxter, Stephen & Okorafor, Nnedi & Wilison, Daniel H. & Reed, Robert & Sedia, Ekaterina") "Lightspeed Magazine"]+         , metaTitles = [Title Nothing              "Lightspeed Magazine Issue 10"]          }       expected =@@ -1058,7 +1058,7 @@       "Lightspeed Magazine, issue number in title" meta expected    where       meta = emptyMetadata-         { metaTitles = [MetaTitle Nothing +         { metaTitles = [Title Nothing              "Lightspeed Issue 33"]          }       expected =@@ -1073,12 +1073,12 @@    where       meta = emptyMetadata          { metaCreators =-            [ MetaCreator (Just "aut") Nothing "VanderMeer"-            , MetaCreator (Just "aut") Nothing "Ann"-            , MetaCreator (Just "aut") Nothing "Spinrad"-            , MetaCreator (Just "aut") Nothing "Norman"+            [ Creator (Just "aut") Nothing "VanderMeer"+            , Creator (Just "aut") Nothing "Ann"+            , Creator (Just "aut") Nothing "Spinrad"+            , Creator (Just "aut") Nothing "Norman"             ]-         , metaTitles = [MetaTitle Nothing +         , metaTitles = [Title Nothing              "Weird Tales #350"]          }       expected =@@ -1092,14 +1092,14 @@    assertNewName opts fs "anthology" meta expected    where       meta = emptyMetadata-         { metaTitles = [MetaTitle Nothing "Creepy Secrets"]+         { metaTitles = [Title Nothing "Creepy Secrets"]          , metaCreators =-            [ MetaCreator (Just "aut") (Just "Snively, Mortimer")+            [ Creator (Just "aut") (Just "Snively, Mortimer")                "Mortimer Snively"-            , MetaCreator (Just "aut") (Just "Baxter, Joanne")+            , Creator (Just "aut") (Just "Baxter, Joanne")                "Joanne Baxter"             ]-         , metaDates = [MetaDate (Just "publication") "2010-11-01"]+         , metaDates = [Date (Just "publication") "2010-11-01"]          , metaSubjects = ["fantasy and horror anthology"]          }       expected =