diff options
-rw-r--r-- | anissue.cabal | 2 | ||||
-rw-r--r-- | app/Issue/GroupBy.hs | 65 | ||||
-rw-r--r-- | app/Main.hs | 67 |
3 files changed, 90 insertions, 44 deletions
diff --git a/anissue.cabal b/anissue.cabal index 188a418..4b068e6 100644 --- a/anissue.cabal +++ b/anissue.cabal @@ -78,6 +78,7 @@ executable anissue History.PartialCommitInfo Issue Issue.Filter + Issue.GroupBy Issue.Provenance Issue.Sort Issue.Tag @@ -99,6 +100,7 @@ executable anissue attoparsec, binary, bytestring, + containers, directory, filepath, optparse-applicative, diff --git a/app/Issue/GroupBy.hs b/app/Issue/GroupBy.hs new file mode 100644 index 0000000..0e8941f --- /dev/null +++ b/app/Issue/GroupBy.hs @@ -0,0 +1,65 @@ +module Issue.GroupBy + ( groupByArg, + groupIssuesBy, + ) +where + +import Data.Map (Map) +import Data.Map qualified as M +import Data.Maybe (mapMaybe) +import Data.Text qualified as T +import Issue (Issue (..)) +import Issue.Tag (Tag (..)) +import Issue.Tag qualified as I +import Options.Applicative qualified as O + + +-- FIXME Parse group by using @topic syntax + +-- TODO Display number of issues within one group +-- +-- ``` +-- Issue D +-- Issue E +-- +-- @topic tags (2 issues) +-- Issue A +-- Issue B @topic ids +-- +-- @topic ids (2 issues) +-- Issue B @topic tags +-- Issue C +-- ``` + +-- TODO Add issues marker as internal tags +-- +-- The internal makers `TODO`, `FIXME`, etc. should be available via the +-- internal tag @type + +-- TODO Add author and editor as internal tags + +groupByArg :: O.Parser (Maybe T.Text) +groupByArg = + O.optional + ( O.strOption + ( O.long "group-by" + <> O.metavar "TAG" + <> O.help "Group selected issues." + ) + ) + +groupIssuesBy :: T.Text -> [Issue] -> Map T.Text [Issue] +groupIssuesBy groupBy issues = + foldl + ( \collected issue -> + foldl + (flip $ M.alter (Just . maybe [issue] (issue :))) + collected + (groupsOfIssue groupBy issue) + ) + M.empty + issues + where + groupsOfIssue group issue = + mapMaybe I.tagValue $ + filter (\(Tag key _) -> key == group) (issue.tags ++ issue.internalTags) diff --git a/app/Main.hs b/app/Main.hs index 3e9dc1d..ee9e850 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -249,48 +249,6 @@ -- allow that). The first marker should have priority in case we have to pick -- one. --- TODO Add option to group issue list --- --- When running `anissue list` with the `--group-by` option, the output --- will be grouped. E.g. running `anissue list --group-by topic` would --- produce --- --- ``` --- Issue D --- Issue E --- --- @topic tags (2 issues) --- Issue A --- Issue B @topic ids --- --- @topic ids (2 issues) --- Issue B @topic tags --- Issue C --- ``` --- --- Other possible grouping options could be --- --- type --- : the issue type, i.e. `TODO`, `FIXME`, `QUESTION`, etc. --- --- priority --- : the priority, groups should be sorted with the highest priority --- first --- --- author --- : the person which created the issue --- --- editor --- : the person who updated the issue last --- --- @topic options --- --- COMMENT For consistency, I would like the option to use `--group-by @topic`. --- Arbitrary tag grouping seems sufficient for this, assuming we add the --- respective *internal tags*. --- --- COMMENT Sounds good! - -- TODO Support issue comments -- Currently, comments do not get picked up in issue descriptions; see the -- issue below. @@ -437,6 +395,7 @@ module Main where import Control.Applicative ((<|>)) import Data.Function ((&)) import Data.List (find, isPrefixOf) +import Data.Map qualified as M import Data.Maybe (catMaybes) import Data.Text qualified as T import Data.Text.IO qualified as T @@ -450,6 +409,7 @@ import Issue (Issue (..)) import Issue qualified as I import Issue.Filter (Filter, applyFilters) import Issue.Filter qualified as I +import Issue.GroupBy qualified as I import Issue.Provenance qualified as I import Issue.Sort (Sort, applySorts) import Issue.Sort qualified as I @@ -539,7 +499,8 @@ data Command = List { files :: [String], filters :: [Filter], - sort :: [Sort] + sort :: [Sort], + groupBy :: Maybe T.Text } | Log | Show @@ -565,6 +526,7 @@ listCmd = <$> filesArg <*> I.filterArg <*> I.sortArg + <*> I.groupByArg logCmd :: O.Parser Command logCmd = @@ -603,7 +565,24 @@ main :: IO () main = do settings <- readSettings O.execParser (O.info (options <**> O.helper) O.idm) >>= \case - Options {colorize, noPager, width, command = List {sort, filters, files}} -> do + Options {colorize, noPager, width, command = List {sort, filters, files, groupBy = Just groupBy}} -> do + let withinPath issue = if null files then True else any (\file -> file `isPrefixOf` issue.file) files + ungroupedIssues <- applySorts sort . applyFilters filters . filter withinPath . fst <$> getHistory + let groupedIssues = I.groupIssuesBy groupBy ungroupedIssues + putDoc colorize noPager width . P.vsep $ + map + ( \(name, issues) -> + P.vsep $ + P.hardline + : P.annotate (P.color P.Red) (P.pretty name) + : map + ( \issue -> + P.indent 4 $ P.annotate P.bold $ P.pretty issue.title + ) + issues + ) + (M.toList groupedIssues) + Options {colorize, noPager, width, command = List {sort, filters, files, groupBy = Nothing}} -> do let withinPath issue = if null files then True else any (\file -> file `isPrefixOf` issue.file) files issues <- applySorts sort . applyFilters filters . filter withinPath . fst <$> getHistory putDoc colorize noPager width . P.vsep $ |