@@ -50,7 +50,9 @@ import Protolude (
5050 (<&>) ,
5151 (||) ,
5252 )
53+ import Protolude qualified as P
5354
55+ import Control.Monad.Catch (catchAll )
5456import Data.Aeson as Aeson (KeyValue ((.=) ), encode , object )
5557import Data.FileEmbed (embedStringFile , makeRelativeToProject )
5658import Data.Hourglass (
@@ -66,9 +68,6 @@ import Data.Text.Lazy.Encoding qualified as TL
6668import Data.Time.ISO8601.Duration qualified as Iso
6769import Data.Version (showVersion )
6870import Data.Yaml (decodeFileEither , prettyPrintParseException )
69-
70- -- Special module provided by Cabal
71-
7271import Database.SQLite.Simple (Connection (.. ))
7372import Database.SQLite.Simple qualified as SQLite
7473import GHC.IO.Encoding (setLocaleEncoding , utf8 )
@@ -154,6 +153,7 @@ import Options.Applicative (
154153 fullDesc ,
155154 headerDoc ,
156155 help ,
156+ helpHeader ,
157157 helper ,
158158 idm ,
159159 info ,
@@ -169,6 +169,7 @@ import Options.Applicative (
169169 subparser ,
170170 switch ,
171171 )
172+ import Options.Applicative.Help.Chunk (Chunk (Chunk ), (<<+>>) )
172173import Options.Applicative.Help.Core (parserHelp )
173174import Paths_tasklite_core (version )
174175import Prettyprinter (
@@ -185,10 +186,11 @@ import Prettyprinter (
185186 )
186187import Prettyprinter.Render.Terminal (
187188 AnsiStyle ,
188- Color (Black , Blue , Cyan , Yellow ),
189+ Color (Black , Blue , Cyan , Red , Yellow ),
189190 bold ,
190191 color ,
191192 colorDull ,
193+ hPutDoc ,
192194 putDoc ,
193195 )
194196import System.Directory (
@@ -202,6 +204,7 @@ import System.Directory (
202204 listDirectory ,
203205 )
204206import System.FilePath ((</>) )
207+ import System.Process (readProcess )
205208import Time.System (timeCurrentP )
206209
207210import Config (
@@ -342,13 +345,15 @@ data Command
342345 | Help
343346 | PrintConfig
344347 | UlidToUtc Text
348+ | ExternalCommand Text (Maybe [Text ])
345349 deriving (Show , Eq )
346350
347351
348352data CliArgs = CliArgs
349353 { cliCommand :: Command
350354 , runHelpCommand :: Bool
351355 }
356+ deriving (Show , Eq )
352357
353358
354359nameToAliasList :: [(Text , Text )]
@@ -944,26 +949,27 @@ commandParser conf =
944949 -- <> command "utc-quarter" -- … last day of the quarter
945950 -- <> command "utc-year" -- … last day of the year
946951 )
952+
953+ -- Catch-all parser for any external "tasklite-???" command
954+ -- Do not show in help
955+ <|> ExternalCommand
956+ <$> strArgument P. mempty
957+ <*> optional (some (strArgument P. mempty ))
947958 )
948959
949960{- FOURMOLU_ENABLE -}
950961
951962
952- runHelpSwitch :: Parser Bool
953- runHelpSwitch =
954- switch
955- ( long " help"
956- <> short ' h'
957- <> help " Display current help page"
958- <> internal
959- )
960-
961-
962963cliArgsParser :: Config -> Parser CliArgs
963964cliArgsParser conf =
964965 CliArgs
965966 <$> commandParser conf
966- <*> runHelpSwitch
967+ <*> switch
968+ ( long " help"
969+ <> short ' h'
970+ <> help " Display current help page"
971+ <> internal
972+ )
967973
968974
969975parserInfo :: Config -> ParserInfo CliArgs
@@ -1101,7 +1107,7 @@ executeCLiCommand conf now connection = do
11011107
11021108 if runHelpCommand cliArgs
11031109 then pure $ extendHelp $ parserHelp defaultPrefs $ cliArgsParser conf
1104- else case cliCommand cliArgs of
1110+ else case cliArgs. cliCommand of
11051111 ListAll -> listAll conf now connection
11061112 ListHead -> headTasks conf now connection
11071113 ListNew -> newTasks conf now connection
@@ -1191,6 +1197,40 @@ executeCLiCommand conf now connection = do
11911197 PrintConfig -> pure $ pretty conf
11921198 Alias alias _ -> pure $ aliasWarning alias
11931199 UlidToUtc ulid -> pure $ prettyUlid ulid
1200+ ExternalCommand cmd argsMb -> do
1201+ let
1202+ args =
1203+ argsMb & P. fromMaybe []
1204+
1205+ runCmd = do
1206+ output <-
1207+ readProcess
1208+ (" tasklite-" <> T. unpack cmd)
1209+ (args <&> T. unpack)
1210+ " "
1211+ pure $ pretty output
1212+
1213+ handleException exception = do
1214+ hPutDoc P. stderr $
1215+ if not $ exception & show & T. isInfixOf " does not exist"
1216+ then pretty (show exception :: Text )
1217+ else do
1218+ let
1219+ theHelp = parserHelp defaultPrefs $ cliArgsParser conf
1220+ newHeader =
1221+ Chunk
1222+ ( Just $
1223+ annotate (color Red ) $
1224+ " ERROR: Command \" "
1225+ <> pretty cmd
1226+ <> " \" does not exist"
1227+ )
1228+ <<+>> helpHeader theHelp
1229+ extendHelp theHelp{helpHeader = newHeader}
1230+
1231+ P. exitFailure
1232+
1233+ catchAll runCmd handleException
11941234
11951235
11961236printOutput :: [Char ] -> Config -> IO ()
0 commit comments