queue-sheet 0.7.0.2 → 0.8.0.0
raw patch · 13 files changed
+264/−101 lines, 13 filesdep +prettyprinterdep ~aesondep ~ansi-wl-pprintdep ~base
Dependencies added: prettyprinter
Dependency ranges changed: aeson, ansi-wl-pprint, base, bytestring, directory, filepath, ginger, optparse-applicative, process, scientific, tasty, tasty-hunit, text, transformers, ttc, vector, yaml
Files
- CHANGELOG.md +25/−0
- LICENSE +1/−1
- README.md +38/−13
- app/LibOA.hs +67/−9
- app/queue-sheet.hs +1/−1
- queue-sheet.cabal +53/−46
- src/QueueSheet.hs +1/−1
- src/QueueSheet/Build.hs +1/−1
- src/QueueSheet/File.hs +1/−1
- src/QueueSheet/Template.hs +3/−2
- src/QueueSheet/Types.hs +20/−14
- test/QueueSheet/File/Test.hs +52/−11
- test/Spec.hs +1/−1
CHANGELOG.md view
@@ -24,6 +24,31 @@ [KaC]: <https://keepachangelog.com/en/1.0.0/> +## 0.8.0.0 (2025-01-03)++### Breaking++* Support whitespace-separated tags and items instead of CSV+* Remove support for GHC 8.6, constraining lower bounds+* Remove support for GHC 8.4, constraining lower bounds+* Remove support for GHC 8.2, constraining lower bounds+* Change minimal Cabal from 1.24 to 3.0++### Non-Breaking++* Bump `aeson` dependency version upper bound+* Bump `ansi-wl-pprint` dependency version upper bound+* Bump `base` dependency version upper bound+* Bump `bytestring` dependency version upper bound+* Bump `filepath` dependency version upper bound+* Add support for `optparse-applicative` `0.18`+* Bump `tasty` dependency version upper bound+* Bump `text` dependency version upper bound+* Bump `transformers` dependency version upper bound+* Bump `ttc` dependency version upper bound+* Bump `vector` dependency version upper bound+* Adjust dependency constraints to match tested versions+ ## 0.7.0.2 (2022-03-02) ### Non-Breaking
LICENSE view
@@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2020-2022 Travis Cardwell+Copyright (c) 2020-2025 Travis Cardwell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal
README.md view
@@ -40,10 +40,13 @@ Queue Sheet has only been tested on Linux. It *might* work on Windows and macOS. -Queue Sheet uses [XeTeX](https://tug.org/xetex/) to build PDFs. It is usually-installed as part of [TeX Live](https://www.tug.org/texlive/). The LaTeX-packages used depend entirely on the contents of the template.+Queue Sheet uses [XeTeX][] to build PDFs. It is usually installed as part of+[TeX Live][]. The LaTeX packages used depend entirely on the contents of the+template. +[XeTeX]: <https://tug.org/xetex/>+[TeX Live]: <https://www.tug.org/texlive/>+ ### Installation #### `.deb` Package Installation@@ -80,29 +83,49 @@ ### Usage -See the [`queue-sheet` man page](doc/queue-sheet.1.md) for usage information.+See the [`queue-sheet` man page][] for usage information. -See the [examples](examples) directory for example queue files, templates, and-built output.+See the [examples][] directory for example queue files, templates, and built+output. -## Project+[`queue-sheet` man page]: <doc/queue-sheet.1.md>+[examples]: <examples> -Queue Sheet was written quickly to solve a particular pain point. There are-no plans to put the package on Hackage.+## Project ### Links * Hackage: <https://hackage.haskell.org/package/queue-sheet> * Stackage: <https://www.stackage.org/package/queue-sheet>+* Flora: <https://flora.pm/packages/@hackage/queue-sheet> * GitHub: <https://github.com/ExtremaIS/queue-sheet-haskell> * GitHub Actions CI: <https://github.com/ExtremaIS/queue-sheet-haskell/actions> +### Branches++The `main` branch is reserved for releases. It may be considered stable, and+`HEAD` is always the latest release.++The `develop` branch is the primary development branch. It contains changes+that have not yet been released, and it is not necessarily stable.++[Hackage revisions][] are made for metadata changes, such as relaxation of+constraints when new versions of dependencies are released. The+`queue-sheet.cabal` metadata in the `main` branch may therefore not match that+of Hackage. The `queue-sheet.cabal` metadata in the `develop` branch may+match, *unless* work is being done on a new release that contains other+changes.++[Hackage revisions]: <https://github.com/haskell-infra/hackage-trustees/blob/master/revisions-information.md#hackage-metadata-revisions--what-they-are-how-they-work>+ ### Tags All releases are tagged in the `main` branch. Release tags are signed using the-[`security@extrema.is` GPG key](http://keys.gnupg.net/pks/lookup?op=vindex&fingerprint=on&search=0x1D484E4B4705FADF).+[`security@extrema.is` GPG key][]. +[`security@extrema.is` GPG key]: <https://keyserver.ubuntu.com/pks/lookup?search=0x1D484E4B4705FADF&fingerprint=on&op=index>+ ### Contribution Issues and feature requests are tracked on GitHub:@@ -112,6 +135,8 @@ ### License -This project is released under the-[MIT License](https://opensource.org/licenses/MIT) as specified in the-[`LICENSE`](LICENSE) file.+This project is released under the [MIT License][] as specified in the+[`LICENSE`][] file.++[MIT License]: <https://opensource.org/licenses/MIT>+[`LICENSE`]: <LICENSE>
app/LibOA.hs view
@@ -2,22 +2,28 @@ -- | -- Module : LibOA -- Description : supplementary functions for optparse-applicative--- Copyright : Copyright (c) 2019-2022 Travis Cardwell+-- Copyright : Copyright (c) 2019-2025 Travis Cardwell -- License : MIT -- -- This is a collection of functions that I often use with -- @optparse-applicative@. I do not feel that it is worth maintaining yet -- another helper package on Hackage, so I just copy the code to different -- projects as required. If the library grows to a substantial size or others--- with to use it, I will reconsider.+-- want to use it, I will reconsider. ----- Revision: 2022-01-02+-- Revision: 2023-05-26 ------------------------------------------------------------------------------ {-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE TupleSections #-} +#if defined(MIN_VERSION_ansi_wl_pprint)+#if MIN_VERSION_ansi_wl_pprint (1,0,2)+{-# OPTIONS_GHC -Wno-warnings-deprecations #-}+#endif+#endif+ module LibOA ( -- * Options -- $Options@@ -28,14 +34,23 @@ -- * Help , (<||>) , section+ , section' , table , table_ , vspace+ -- ** Compatibility+ , Doc+ , (<$$>)+ , empty+ , string+ , vcat ) where -- https://hackage.haskell.org/package/ansi-wl-pprint+#if !MIN_VERSION_optparse_applicative (0,18,0) import qualified Text.PrettyPrint.ANSI.Leijen as Doc import Text.PrettyPrint.ANSI.Leijen (Doc)+#endif -- https://hackage.haskell.org/package/base import Data.List (intersperse, transpose)@@ -50,8 +65,16 @@ import qualified Options.Applicative.Builder.Internal as OABI #endif import qualified Options.Applicative.Common as OAC+#if MIN_VERSION_optparse_applicative (0,18,0)+import Options.Applicative.Help.Pretty (Doc)+#endif import qualified Options.Applicative.Types as OAT +-- https://hackage.haskell.org/package/prettyprinter+#if MIN_VERSION_optparse_applicative (0,18,0)+import qualified Prettyprinter as Doc+#endif+ ------------------------------------------------------------------------------ -- $Options --@@ -103,8 +126,12 @@ commands :: OA.Parser a -> [String] commands = let go _ opt = case OAT.optMain opt of+#if MIN_VERSION_optparse_applicative (0,18,0)+ OAT.CmdReader _ cmdPs -> reverse $ fst <$> cmdPs+#else OAT.CmdReader _ cmds _ -> reverse cmds- _otherReader -> []+#endif+ _otherReader -> [] in concat . OAC.mapParser go ------------------------------------------------------------------------------@@ -115,22 +142,26 @@ d1 <||> d2 = d1 <> Doc.line <> Doc.line <> d2 infixr 5 <||> --- | Create a section with a title and indented body+-- | Create a section with a title and body indented by 2 spaces section :: String -> Doc -> Doc-section title = (Doc.text title Doc.<$$>) . Doc.indent 2+section = section' 2 +-- | Create a section with a title and body indented by specified spaces+section' :: Int -> String -> Doc -> Doc+section' numSpaces title = (string title <$$>) . Doc.indent numSpaces+ -- | Create a table, with formatting table :: Int -> [[(String, Doc -> Doc)]] -> Doc table sep rows = Doc.vcat $- map (fromMaybe Doc.empty . foldr go Nothing . zip lengths) rows+ map (fromMaybe empty . foldr go Nothing . zip lengths) rows where lengths :: [Int] lengths = map ((+) sep . maximum . map (length . fst)) $ transpose rows go :: (Int, (String, Doc -> Doc)) -> Maybe Doc -> Maybe Doc go (len, (s, f)) = Just . \case- Just doc -> Doc.fill len (f $ Doc.string s) <> doc- Nothing -> f $ Doc.string s+ Just doc -> Doc.fill len (f $ string s) <> doc+ Nothing -> f $ string s -- | Create a table, without formatting table_ :: Int -> [[String]] -> Doc@@ -139,3 +170,30 @@ -- | Vertically space documents with blank lines between them vspace :: [Doc] -> Doc vspace = mconcat . intersperse (Doc.line <> Doc.line)++------------------------------------------------------------------------------+-- $Compatibility++(<$$>) :: Doc -> Doc -> Doc+#if MIN_VERSION_optparse_applicative (0,18,0)+l <$$> r = l <> Doc.line <> r+#else+(<$$>) = (Doc.<$$>)+#endif++empty :: Doc+#if MIN_VERSION_optparse_applicative (0,18,0)+empty = Doc.emptyDoc+#else+empty = Doc.empty+#endif++string :: String -> Doc+#if MIN_VERSION_optparse_applicative (0,18,0)+string = Doc.pretty+#else+string = Doc.string+#endif++vcat :: [Doc] -> Doc+vcat = Doc.vcat
app/queue-sheet.hs view
@@ -2,7 +2,7 @@ -- | -- Module : Main -- Description : queue-sheet program--- Copyright : Copyright (c) 2020-2022 Travis Cardwell+-- Copyright : Copyright (c) 2020-2025 Travis Cardwell -- License : MIT ------------------------------------------------------------------------------
queue-sheet.cabal view
@@ -1,42 +1,44 @@-name: queue-sheet-version: 0.7.0.2-category: Utils-synopsis: queue sheet utility+cabal-version: 3.0+name: queue-sheet+version: 0.8.0.0+synopsis: queue sheet utility description: This package provides a utility for creating queue sheets. Please see the README on GitHub at <https://github.com/ExtremaIS/queue-sheet-haskell#readme>.+homepage: https://github.com/ExtremaIS/queue-sheet-haskell#readme+bug-reports: https://github.com/ExtremaIS/queue-sheet-haskell/issues+license: MIT+license-file: LICENSE+author: Travis Cardwell <travis.cardwell@extrema.is>+maintainer: Travis Cardwell <travis.cardwell@extrema.is>+copyright: Copyright (c) 2020-2025 Travis Cardwell+category: Utils+build-type: Simple -homepage: https://github.com/ExtremaIS/queue-sheet-haskell#readme-bug-reports: https://github.com/ExtremaIS/queue-sheet-haskell/issues-author: Travis Cardwell <travis.cardwell@extrema.is>-maintainer: Travis Cardwell <travis.cardwell@extrema.is>-copyright: Copyright (c) 2020-2022 Travis Cardwell-license: MIT-license-file: LICENSE+extra-doc-files:+ CHANGELOG.md+ README.md -cabal-version: 1.24-build-type: Simple tested-with:- GHC ==8.2.2- || ==8.4.4- || ==8.6.5- || ==8.8.4+ GHC ==8.8.4 || ==8.10.7 || ==9.0.2- || ==9.2.1--extra-source-files:- CHANGELOG.md- README.md+ || ==9.2.8+ || ==9.4.8+ || ==9.6.6+ || ==9.8.4+ || ==9.10.1 source-repository head type: git location: https://github.com/ExtremaIS/queue-sheet-haskell.git -flag write-hie- description: write .hie files+-- This flag is referenced in the Stack build-constraints.yaml configuration.+flag optparse-applicative_ge_0_18+ description: Use optparse-applicative 0.18 or newer default: False+ manual: False library hs-source-dirs: src@@ -48,25 +50,24 @@ , QueueSheet.Types other-modules: Paths_queue_sheet+ autogen-modules:+ Paths_queue_sheet build-depends:- aeson >= 1.2 && <2.1- , base >=4.7 && <5- , bytestring >=0.10.8 && <0.12- , directory >=1.3 && <1.4- , filepath >=1.4 && <1.5- , ginger >=0.7.3 && <0.11- , process >=1.6 && <1.7- , scientific >=0.3 && <0.4- , text >=1.2.3 && <2.1- , transformers >=0.5.2 && <0.6- , ttc >=1.1 && <1.2- , vector >=0.12 && <0.13- , yaml >=0.8 && <0.12+ aeson >= 1.4.7.1 && <2.3+ , base >=4.13 && <4.21+ , bytestring >=0.10.10.1 && <0.13+ , directory >=1.3.6 && <1.4+ , filepath >=1.4.2.1 && <1.6+ , ginger >=0.10.1 && <0.11+ , process >=1.6.9 && <1.7+ , scientific >=0.3.6.2 && <0.4+ , text >=1.2.4 && <2.2+ , transformers >=0.5.6.2 && <0.7+ , ttc >=1.1 && <1.6+ , vector >=0.12.1.2 && <0.14+ , yaml >=0.11.5 && <0.12 default-language: Haskell2010- if flag(write-hie)- ghc-options: -Wall -fwrite-ide-info -hiedir=.hie- else- ghc-options: -Wall+ ghc-options: -Wall executable queue-sheet hs-source-dirs: app@@ -74,10 +75,16 @@ other-modules: LibOA build-depends:- ansi-wl-pprint >=0.6 && <0.7- , base- , optparse-applicative >=0.14 && <0.18+ base , queue-sheet+ if flag(optparse-applicative_ge_0_18)+ build-depends:+ optparse-applicative >=0.18 && <0.19+ , prettyprinter >=1.7.1 && <1.8+ else+ build-depends:+ ansi-wl-pprint >=0.6.9 && <1.1+ , optparse-applicative >=0.15.1 && <0.18 default-language: Haskell2010 ghc-options: -Wall @@ -91,7 +98,7 @@ base , bytestring , queue-sheet- , tasty >=1.0 && <1.5- , tasty-hunit >=0.10 && <0.11+ , tasty >=1.2.3 && <1.6+ , tasty-hunit >=0.10.0.3 && <0.11 default-language: Haskell2010 ghc-options: -Wall
src/QueueSheet.hs view
@@ -2,7 +2,7 @@ -- | -- Module : QueueSheet -- Description : queue sheet metadata--- Copyright : Copyright (c) 2020-2022 Travis Cardwell+-- Copyright : Copyright (c) 2020-2025 Travis Cardwell -- License : MIT ------------------------------------------------------------------------------
src/QueueSheet/Build.hs view
@@ -2,7 +2,7 @@ -- | -- Module : QueueSheet.Build -- Description : queue sheet build functions--- Copyright : Copyright (c) 2020-2022 Travis Cardwell+-- Copyright : Copyright (c) 2020-2025 Travis Cardwell -- License : MIT ------------------------------------------------------------------------------
src/QueueSheet/File.hs view
@@ -2,7 +2,7 @@ -- | -- Module : QueueSheet.File -- Description : queue sheet file loading--- Copyright : Copyright (c) 2020-2022 Travis Cardwell+-- Copyright : Copyright (c) 2020-2025 Travis Cardwell -- License : MIT ------------------------------------------------------------------------------
src/QueueSheet/Template.hs view
@@ -2,7 +2,7 @@ -- | -- Module : QueueSheet.Template -- Description : queue sheet template functions--- Copyright : Copyright (c) 2020-2022 Travis Cardwell+-- Copyright : Copyright (c) 2020-2025 Travis Cardwell -- License : MIT ------------------------------------------------------------------------------ @@ -23,6 +23,7 @@ -- https://hackage.haskell.org/package/base import Data.Bifunctor (first)+import Data.Either (fromRight) #if !MIN_VERSION_base (4,11,0) import Data.Monoid ((<>)) #endif@@ -80,7 +81,7 @@ , date = queueDate , tags = queueTags , prevItem = either Just (const Nothing) =<< queueItems- , nextItems = maybe [] (either (const []) id) queueItems+ , nextItems = maybe [] (fromRight []) queueItems } ------------------------------------------------------------------------------
src/QueueSheet/Types.hs view
@@ -2,7 +2,7 @@ -- | -- Module : QueueSheet.Types -- Description : queue sheet types--- Copyright : Copyright (c) 2020-2022 Travis Cardwell+-- Copyright : Copyright (c) 2020-2025 Travis Cardwell -- License : MIT ------------------------------------------------------------------------------ @@ -159,7 +159,7 @@ instance FromJSON Tag where parseJSON = A.withText "Tag" $ \t -> do- when (T.null t) $ fail "empty tag"+ when (T.null t) $ fail "empty string" unless (T.all isValidChar t) $ fail ("invalid tag: " ++ T.unpack t) return $ Tag t where@@ -175,6 +175,8 @@ -- | Queue item --+-- Whitespace-separated tags are supported /instead of/ CSV from @0.8.0.0@.+-- -- @since 0.5.0.0 data Item = Item@@ -189,7 +191,7 @@ (A.Object o) -> do itemName <- o .: "name" itemUrl <- o .:? "url"- itemTags <- maybe (pure []) parseCSV =<< (o .:? "tags")+ itemTags <- maybe (pure []) parseSSV =<< (o .:? "tags") return Item{..} value -> do itemName <- Name <$> parseToString value@@ -208,6 +210,9 @@ -- | Queue information --+-- Whitespace-separated items and tags are supported /instead of/ CSV from+-- @0.8.0.0@.+-- -- @since 0.5.0.0 data Queue = Queue@@ -226,11 +231,11 @@ queueUrl <- o .:? "url" queueDate <- o .:? "date" queueSection <- o .:? "section" .!= defaultSection- queueTags <- maybe (pure []) parseCSV =<< (o .:? "tags")+ queueTags <- maybe (pure []) parseSSV =<< (o .:? "tags") mPrevItem <- o .:? "prev" mNextValue <- o .:? "next" queueItems <- case (mPrevItem, mNextValue) of- (_, Just nextValue) -> Just . Right <$> parseCSV nextValue+ (_, Just nextValue) -> Just . Right <$> parseSSV nextValue (Just item, Nothing) -> pure . Just $ Left item (Nothing, Nothing) -> pure Nothing return Queue{..}@@ -331,16 +336,17 @@ '~' -> acc <> "\\textasciitilde{}" c -> acc `T.snoc` c --- | Parse an array or string in simplified CSV format+-- | Parse an array or string in space-separated-value format ----- Strings are split on commas, and leading/trailing whitespace is removed--- from each item.-parseCSV :: A.FromJSON a => A.Value -> AT.Parser [a]-parseCSV = \case- (A.String t) -> mapM (parseJSON . A.String . T.strip) $ T.splitOn "," t- (A.Array v) -> mapM parseJSON $ V.toList v- A.Object{} -> fail "unexpected object"- value -> (: []) <$> parseJSON value+-- Strings are split on whitespace.+parseSSV :: A.FromJSON a => A.Value -> AT.Parser [a]+parseSSV = \case+ (A.String t)+ | T.null t -> fail "empty string"+ | otherwise -> mapM (parseJSON . A.String) $ T.words t+ (A.Array v) -> mapM parseJSON $ V.toList v+ A.Object{} -> fail "unexpected object"+ value -> (: []) <$> parseJSON value -- | Parse any scalar value as a string --
test/QueueSheet/File/Test.hs view
@@ -2,7 +2,7 @@ -- | -- Module : QueueSheet.File.Test -- Description : queues file tests--- Copyright : Copyright (c) 2020-2022 Travis Cardwell+-- Copyright : Copyright (c) 2020-2025 Travis Cardwell -- License : MIT ------------------------------------------------------------------------------ @@ -326,7 +326,7 @@ , testCase "empty" $ do let message = intercalate "\n" [ "error loading /tmp/test.yaml: Aeson exception:"- , "Error in $[0]: empty tag"+ , "Error in $[0]: empty string" ] Left message @=? loadYaml [ validFile "/tmp/test.yaml"@@ -366,7 +366,7 @@ ] unless (Left messageOld == eeq) $ Left message @=? eeq ]- , testGroup "csv"+ , testGroup "ssv" [ testCase "single" $ do let expected = defaultQueueSheet { qsQueues =@@ -394,13 +394,30 @@ Right expected @=? loadYaml [ validFile "/tmp/test.yaml" [ "- name: test"- , " tags: complete, partial"+ , " tags: complete partial" ] ]+ , testCase "folded" $ do+ let expected = defaultQueueSheet+ { qsQueues =+ [ defaultQueue+ { queueName = Name "test"+ , queueTags = [Tag "complete", Tag "partial"]+ }+ ]+ }+ Right expected @=? loadYaml+ [ validFile "/tmp/test.yaml"+ [ "- name: test"+ , " tags: >"+ , " complete"+ , " partial"+ ]+ ] , testCase "empty" $ do let message = intercalate "\n" [ "error loading /tmp/test.yaml: Aeson exception:"- , "Error in $[0]: empty tag"+ , "Error in $[0]: empty string" ] Left message @=? loadYaml [ validFile "/tmp/test.yaml"@@ -566,7 +583,7 @@ , " - two" ] ]- , testCase "csv" $ do+ , testCase "ssv" $ do let expected = defaultQueueSheet { qsQueues = [ defaultQueue@@ -583,7 +600,7 @@ [ "- name: test" , " prev:" , " name: 42"- , " tags: one, two"+ , " tags: one two" ] ] ]@@ -712,7 +729,7 @@ , " - two" ] ]- , testCase "csv" $ do+ , testCase "ssv" $ do let expected = defaultQueueSheet { qsQueues = [ defaultQueue@@ -731,7 +748,7 @@ [ "- name: test" , " next:" , " - name: one"- , " tags: one, two"+ , " tags: one two" ] ] ]@@ -811,7 +828,7 @@ ] ] ]- , testGroup "csv"+ , testGroup "ssv" [ testCase "single" $ do let expected = defaultQueueSheet { qsQueues =@@ -869,7 +886,31 @@ Right expected @=? loadYaml [ validFile "/tmp/test.yaml" [ "- name: test"- , " next: 11, 42"+ , " next: 11 42"+ ]+ ]+ , testCase "folded" $ do+ let expected = defaultQueueSheet+ { qsQueues =+ [ defaultQueue+ { queueName = Name "test"+ , queueItems = Just $ Right+ [ defaultItem+ { itemName = Name "11"+ }+ , defaultItem+ { itemName = Name "42"+ }+ ]+ }+ ]+ }+ Right expected @=? loadYaml+ [ validFile "/tmp/test.yaml"+ [ "- name: test"+ , " next: >"+ , " 11"+ , " 42" ] ] , testCase "empty" $ do
test/Spec.hs view
@@ -2,7 +2,7 @@ -- | -- Module : Main -- Description : queue sheet test runner--- Copyright : Copyright (c) 2020-2022 Travis Cardwell+-- Copyright : Copyright (c) 2020-2025 Travis Cardwell -- License : MIT ------------------------------------------------------------------------------