tasklite 0.3.0.0 → 0.5.0.0
raw patch · 6 files changed
+192/−58 lines, 6 filesdep +template-haskelldep +temporarydep ~directorydep ~filepathdep ~hspec
Dependencies added: template-haskell, temporary
Dependency ranges changed: directory, filepath, hspec, optparse-applicative, protolude, text, yaml
Files
- app/Main.hs +3/−2
- example-config.yaml +0/−35
- tasklite.cabal +14/−12
- test/CliSpec.hs +141/−7
- test/Spec.hs +4/−2
- test/Utils.hs +30/−0
app/Main.hs view
@@ -7,6 +7,7 @@ Bool (True), Either (..), IO,+ Maybe (Nothing), die, writeFile, ($),@@ -49,7 +50,7 @@ case configResult2 of Left error2 -> die $ T.pack $ prettyPrintParseException error2- Right configUser -> printOutput appName configUser+ Right configUser -> printOutput appName Nothing configUser else die $ T.pack $ prettyPrintParseException error Right configUser ->- printOutput appName configUser+ printOutput appName Nothing configUser
− example-config.yaml
@@ -1,35 +0,0 @@-tableName: tasks-idWidth: 4-idStyle: green-priorityStyle: magenta-dateStyle: dull black-bodyStyle: white-bodyClosedStyle: black-closedStyle: dull black-dueStyle: yellow-overdueStyle: red-tagStyle: blue-utcFormat: YYYY-MM-DD H:MI:S-#| FIXME: Blocked by https://github.com/vincenthz/hs-hourglass/issue-# utcFormatShort: YYYY-DDD H:MI-utcFormatShort: YYYY-MM-DD H:MI--#| Optional, uses the XDG directory per default-#| https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html-# dataDir: /custom/path/tasklite--dbName: main.db-dateWidth: 10-bodyWidth: 10-prioWidth: 4-headCount: 20-maxWidth: 120-progressBarWidth: 24--# hooks:-# #| Is per default the "hooks" directory in the `dataDir`-# # directory: /custom/path/hooks-# launch:-# pre:-# - interpreter: python3-# body: print('Python test')
tasklite.cabal view
@@ -1,11 +1,11 @@ cabal-version: 2.2 --- This file has been generated from package.yaml by hpack version 0.36.0.+-- This file has been generated from package.yaml by hpack version 0.38.0. -- -- see: https://github.com/sol/hpack name: tasklite-version: 0.3.0.0+version: 0.5.0.0 synopsis: CLI task / todo list manager with SQLite backend description: TaskLite is a CLI task / todo list manager with a SQLite backend. It is designed to be simple and easy to use,@@ -24,8 +24,6 @@ build-type: Simple extra-source-files: README.md-data-files:- example-config.yaml source-repository head type: git@@ -52,12 +50,12 @@ ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wno-orphans -Wredundant-constraints -Wunused-packages build-depends: base >=4.18 && <5- , directory- , filepath- , protolude >=0.3+ , directory ==1.3.*+ , filepath >=1.4 && <1.6+ , protolude ==0.3.* , tasklite-core- , text- , yaml+ , text >=1.2 && <2.2+ , yaml ==0.11.* default-language: GHC2021 test-suite tasklite-test@@ -65,6 +63,7 @@ main-is: Spec.hs other-modules: CliSpec+ Utils Paths_tasklite autogen-modules: Paths_tasklite@@ -83,8 +82,11 @@ ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wno-orphans -Wredundant-constraints -Wunused-packages build-depends: base >=4.18 && <5- , hspec- , optparse-applicative- , protolude >=0.3+ , directory+ , hspec >=2.11 && <3.0+ , optparse-applicative >=0.16 && <0.19+ , protolude ==0.3.* , tasklite-core+ , template-haskell >=2.17 && <2.23+ , temporary ==1.3.* default-language: GHC2021
test/CliSpec.hs view
@@ -1,6 +1,8 @@+{-# LANGUAGE QuasiQuotes #-}+ module CliSpec where -import Protolude (($), (&))+import Protolude (Maybe (Just, Nothing), ($), (&), (<>)) import Protolude qualified as P import Options.Applicative (@@ -11,16 +13,36 @@ parserFailure, renderFailure, )-import Test.Hspec (Spec, describe, it, shouldContain)+import Test.Hspec (Spec, describe, it, shouldBe, shouldContain) -import Cli (commandParserInfo)-import Config (defaultConfig)+import Cli (commandParserInfo, printOutput)+import Config (Config, Hook (Hook), HookSet (HookSet), defaultConfig)+import Config qualified+import System.Directory (+ Permissions (executable, readable),+ emptyPermissions,+ setPermissions,+ )+import Utils (raw) -spec :: Spec-spec = do+createHook :: Config -> P.FilePath -> P.Text -> P.IO ()+createHook conf name content = do+ let filePath = conf.hooks.directory <> "/" <> name+ P.writeFile filePath content+ setPermissions+ filePath+ ( emptyPermissions+ { executable = P.True+ , readable = P.True+ }+ )+++spec :: P.FilePath -> Spec+spec tmpDirPath = do describe "CLI" $ do- it "should include header, body, and footer in help output" $ do+ it "includes header, body, and footer in help output" $ do let failure :: ParserFailure ParserHelp = parserFailure@@ -33,3 +55,115 @@ helpText `shouldContain` "Usage: xxx" helpText `shouldContain` "developed by"++ it "prints current version" $ do+ _ <- printOutput "test-app" (Just ["version"]) defaultConfig+ () `shouldBe` ()++ it "calls task lifecycle hooks (add, modify) stored in config" $ do+ let+ getLuaHook body =+ Hook+ { Config.filePath = Nothing+ , Config.interpreter = "lua"+ , Config.body = body+ }+ preAddHook =+ getLuaHook+ [raw|+ io.stderr:write("🏃 Executing pre-add script …\n")+ io.stderr:write(+ "ℹ️ Receives an object with arguments:\n",+ io.read("*a"),+ "\n"+ )+ -- print("{}")+ |]+ postAddHook =+ getLuaHook+ [raw|+ io.stderr:write("🏃 Executing post-add script …\n")+ io.stderr:write(+ "ℹ️ Receives an object with arguments:\n",+ io.read("*a"),+ "\n"+ )+ -- print("{}")+ |]+ preModifyHook =+ getLuaHook+ [raw|+ io.stderr:write("🏃 Executing pre-modify script …\n")+ io.stderr:write(+ "ℹ️ Receives an object with arguments:\n",+ io.read("*a"),+ "\n"+ )+ -- print("{}")+ |]+ postModifyHook =+ getLuaHook+ [raw|+ io.stderr:write("🏃 Executing post-modify script …\n")+ io.stderr:write(+ "ℹ️ Receives an object with arguments:\n",+ io.read("*a"),+ "\n"+ )+ -- print("{}")+ |]+ testConf =+ defaultConfig+ { Config.hooks =+ defaultConfig.hooks+ { Config.add =+ HookSet+ { pre = [preAddHook]+ , post = [postAddHook]+ }+ , Config.modify =+ HookSet+ { pre = [preModifyHook]+ , post = [postModifyHook]+ }+ }+ }++ _ <- printOutput "test-app" (Just ["add", "buy milk"]) testConf++ () `shouldBe` ()++ it "calls launch hooks stored in files" $ do+ let+ testConf =+ defaultConfig+ { Config.hooks =+ defaultConfig.hooks{Config.directory = tmpDirPath}+ }+ hookFor = createHook testConf++ hookFor+ "pre-launch.lua"+ [raw|+ io.stderr:write("🏃 Executing pre-launch script …\n")+ io.stderr:write(+ "ℹ️ Receives no input:",+ io.read("*a"),+ "\n"+ )+ |]++ hookFor+ "post-launch.lua"+ [raw|+ io.stderr:write("🏃 Executing post-launch script …\n")+ io.stderr:write(+ "ℹ️ Receives an object with arguments:",+ io.read("*a"),+ "\n"+ )+ |]++ _ <- printOutput "test-app" (Just ["head"]) testConf++ () `shouldBe` ()
test/Spec.hs view
@@ -1,4 +1,5 @@-import Protolude (IO)+import Protolude (IO, ($))+import System.IO.Temp (withSystemTempDirectory) import Test.Hspec (hspec) import CliSpec qualified@@ -6,4 +7,5 @@ main :: IO () main = do- hspec CliSpec.spec+ withSystemTempDirectory "tasklite-test" $ \dirPath -> do+ hspec $ CliSpec.spec dirPath
+ test/Utils.hs view
@@ -0,0 +1,30 @@+{-# OPTIONS_GHC -Wno-deprecations #-}++module Utils where++import Protolude (pure, (.))+import Protolude.Error (error)++import Language.Haskell.TH (Exp (LitE), Lit (StringL))+import Language.Haskell.TH.Quote (+ QuasiQuoter (QuasiQuoter, quoteDec, quoteExp, quotePat, quoteType),+ )+++raw :: QuasiQuoter+raw =+ QuasiQuoter+ { quoteExp = pure . LitE . StringL+ , quotePat = \_ ->+ error+ "Illegal raw string QuasiQuote \+ \(allowed as expression only, used as a pattern)"+ , quoteType = \_ ->+ error+ "Illegal raw string QuasiQuote \+ \(allowed as expression only, used as a type)"+ , quoteDec = \_ ->+ error+ "Illegal raw string QuasiQuote \+ \(allowed as expression only, used as a declaration)"+ }