lentil 0.1.2.6 → 0.1.2.7
raw patch · 15 files changed
+92/−70 lines, 15 files
Files
- changes.txt +7/−1
- doc/usr/page.rst +2/−0
- lentil.cabal +1/−1
- src/Lentil/Args.hs +5/−11
- src/Lentil/Export.hs +2/−2
- src/Lentil/Parse/Issue.hs +11/−6
- src/Lentil/Print.hs +1/−1
- src/Lentil/Query.hs +2/−4
- src/Lentil/Types.hs +4/−1
- src/Main.hs +1/−1
- test/Lentil/ArgsSpec.hs +2/−1
- test/Lentil/ExportSpec.hs +2/−2
- test/Lentil/Parse/IssueSpec.hs +32/−20
- test/Lentil/Parse/RunSpec.hs +9/−9
- test/Lentil/QuerySpec.hs +11/−10
changes.txt view
@@ -1,8 +1,14 @@+0.1.2.7+-------++- Released Mon 20 Jul 2015 19:38:12 CEST+- allowed naked todos (w/o desc) (requested by qptain nemo).+ 0.1.2.6 ------- - Released Mon 13 Jul 2015 12:24:24 CEST-- added shell script syntax (.sh) (requeste by qptain nemo).+- added shell script syntax (.sh) (requested by qptain nemo). 0.1.2.5 -------
doc/usr/page.rst view
@@ -118,6 +118,8 @@ /* Xxx: add to version control. Ask Timothy */ + -- FIXME+ You can optionally put tags at the end of your issue, like this:
lentil.cabal view
@@ -1,5 +1,5 @@ name: lentil-version: 0.1.2.6+version: 0.1.2.7 synopsis: frugal issue tracker description: minumum effort, cohesive issue tracker based on ubiquitous @TODO@s and @FIXME@s conventions.
src/Lentil/Args.hs view
@@ -143,22 +143,16 @@ help "filters for description NOT matching EXPR" ) tag :: Parser LFilter-tag = option optTxt ( short 't' <>- metavar "EXPR" <>- help "filter for tag matching EXPR" )+tag = option (filterTags <$> str)+ ( short 't' <>+ metavar "EXPR" <>+ help "filter for tag matching EXPR" ) notag :: Parser LFilter-notag = option (negFilter <$> optTxt)+notag = option (negFilter . filterTags <$> str) ( short 'T' <> metavar "EXPR" <> help "filter for tag NOT matching EXPR" )---optTxt :: ReadM LFilter-optTxt = str >>= \oStr ->- if oStr == "^"- then return filterTagless- else return (filterTags oStr) -----------------
src/Lentil/Export.hs view
@@ -22,14 +22,14 @@ issues2CSV is = printCSV (firstLine : map i2r is) where firstLine = ["Filepath", "Row", "Description", "Tags"] i2r i = [(prettyFP . iFile) i, show (iRow i),- iDesc i, tags2String (iTags i)]+ iPPDesc i, tags2String (iTags i)] -- compiler-like (gcc/ghc) warnings, parseable by emacs issues2Compiler :: [Issue] -> String issues2Compiler is = L.intercalate "\n" (map i2c is) where i2c i = (prettyFP . iFile) i ++ ":" ++ show (iRow i) ++ ":\n" ++- " " ++ iDesc i ++ " " +++ " " ++ iPPDesc i ++ " " ++ tags2StringPretty (iTags i) ++ "\n"
src/Lentil/Parse/Issue.hs view
@@ -103,10 +103,10 @@ -- incipit have to be bound at the beginning of line (won't pick up stuff -- in the middle of a sentence) incipit :: ParIssue FlagWord-incipit = char '\n' >> spaces >>- fwpar >>= \fw ->- optional (char ':') >>- many1 (char ' ') >>+incipit = char '\n' >> spaces >>+ fwpar >>= \fw ->+ optional (char ':') >>+ notFollowedBy alphaNum >> -- real todo, not todoodle return fw <?> "incipit" where@@ -142,8 +142,13 @@ -- any text. Since tags/fields at the end of the issue are optional, we need -- a way to delimit this. Delimiters are: eof, tags/fields, blank line-freeText :: ParIssue Description-freeText = fmap htmlify (manyTill anyChar end) <?> "free text"+freeText :: ParIssue (Maybe Description)+freeText = fmap htmlify (manyTill anyChar end) >>= \t ->+ case t of+ [] -> return Nothing+ _ -> return $ Just t++ <?> "free text" where vp p = try . parsecMap (const ()) $ p end = lookAhead $ choice [vp (spaces1 *> tag), vp blankline, -- \n\n or \neof
src/Lentil/Print.hs view
@@ -52,7 +52,7 @@ hang 0 (fillSep $ ppDescTags is)] ) where ppDescTags :: Issue -> [Doc]- ppDescTags i = map string (words (iDesc is)) +++ ppDescTags i = map string (words (iPPDesc is)) ++ map (ppTag Blue) (iTags i) spInd = indNum - ind
src/Lentil/Query.hs view
@@ -35,14 +35,12 @@ filterFilepath r is = filter ((=~ r) . iFile) is filterDescription :: RegExp -> [Issue] -> [Issue]-filterDescription r is = filter ((=~ r) . iDesc) is+filterDescription r is = filter ((=~ r) . mDesc . iDesc) is+ where mDesc md = maybe "" id md filterTags :: RegExp -> [Issue] -> [Issue] filterTags r is = filter (df . iTags) is where df ts = any ((=~ r) . tagString) ts--filterTagless :: [Issue] -> [Issue]-filterTagless is = filter (null . iTags) is negFilter :: ([Issue] -> [Issue]) -> [Issue] -> [Issue] negFilter f is = is L.\\ f is
src/Lentil/Types.hs view
@@ -15,7 +15,7 @@ data Issue = Issue { iFile :: FilePath, iRow :: Row,- iDesc :: Description,+ iDesc :: Maybe Description, iTags :: [Tag] } deriving (Eq, Show) @@ -40,4 +40,7 @@ prettyFP :: String -> String prettyFP fp | L.isPrefixOf "./" fp = drop 2 fp | otherwise = fp++iPPDesc :: Issue -> String+iPPDesc i = maybe "<no description>" id . iDesc $ i
src/Main.hs view
@@ -28,7 +28,7 @@ short 'v' <> help "show version and copyright info" ) where- versionCopy = "lentil - a frugal issue tracker, version 0.1.2.6\n\+ versionCopy = "lentil - a frugal issue tracker, version 0.1.2.7\n\ \(C) 2015 Francesco Ariis - http://www.ariis.it\n\ \released under the GNU General Public License 3\n"
test/Lentil/ArgsSpec.hs view
@@ -11,7 +11,7 @@ testOpt :: LOptions testOpt = LOptions (["alpha"], ["beta"]) Csv- [filterFilepath "al", filterTagless]+ [filterFilepath "al", negFilter . filterTags $ "."] [] (Just "foo.txt") ins :: [String]@@ -34,4 +34,5 @@ it "parses options" $ ins `shouldBe` ins --error "args" --out `shouldBe` Just testOpt+ -- TODO: real parsing testing options [test]
test/Lentil/ExportSpec.hs view
@@ -8,8 +8,8 @@ is :: [Issue]-is = [Issue "./file" 1 "da" [Tag "a", Tag "c"],- Issue "file" 2 "db" [Tag "e:f"]]+is = [Issue "./file" 1 (Just "da") [Tag "a", Tag "c"],+ Issue "file" 2 (Just "db") [Tag "e:f"]] csv :: String csv = "\"Filepath\",\"Row\",\"Description\",\"Tags\"\n\
test/Lentil/Parse/IssueSpec.hs view
@@ -62,6 +62,8 @@ sp incipit "\nXXX: " `shouldBe` Just Xxx it "doesn't work without previous newline" $ sp incipit "\nTODO:some" `shouldBe` Nothing+ it "doesn't work with longer matches (todoodle)" $+ sp incipit "\nTODOodle:some" `shouldBe` Nothing it "doesn't work if you don't add a space after :" $ sp incipit "\nTODO:some" `shouldBe` Nothing it "does allow you to omit the :" $@@ -83,58 +85,68 @@ describe "freeText" $ do it "parses a free form text" $- sp freeText "this is it\n\n" `shouldBe` Just "this is it"+ sp freeText "this is it\n\n" `shouldBe` Just (Just "this is it") it "can be ended by tags/fields" $- sp freeText "this is it [field:val]" `shouldBe` Just "this is it"+ sp freeText "this is it [field:val]" `shouldBe` Just (Just "this is it") it "trims extra whitespace" $- sp freeText "this is it [bug]" `shouldBe` Just "this is it"+ sp freeText "this is it [bug]" `shouldBe` Just (Just "this is it") it "cannot be ended by new issue on same line" $ sp freeText "this is it TODO: desc\n" `shouldBe`- Just "this is it TODO: desc"+ Just (Just "this is it TODO: desc") it "cannot be ended by new issue on new-but-not-beginning-of-line" $ sp freeText "this is it \nn TODO: desc\n" `shouldBe`- Just "this is it n TODO: desc"+ Just (Just "this is it n TODO: desc") it "can be ended by blank line" $- sp freeText "this is it\n\n TODO: desc" `shouldBe` Just "this is it"+ sp freeText "this is it\n\n TODO: desc" `shouldBe`+ Just (Just "this is it") it "can be ended by incomplete blank line (eof)" $- sp freeText "this is it\n" `shouldBe` Just "this is it"+ sp freeText "this is it\n" `shouldBe` Just (Just "this is it") describe "issue" $ do it "parses an issue" $ sp issue "\n fixMe this is it [t] [f:w]"- `shouldBe` (Just $ Issue "<f>" 2 "this is it"+ `shouldBe` (Just $ Issue "<f>" 2 (Just "this is it") [Tag "fixme", Tag "t", Tag "f:w"]) it "parses tagless/fieldless issues too" $ sp issue "\nTODO: this is it\n"- `shouldBe` (Just $ Issue "<f>" 2 "this is it" [])+ `shouldBe` (Just $ Issue "<f>" 2 (Just "this is it") []) it "parses an issue not ended by \\n" $ sp issue "\ntodo block1 "- `shouldBe` (Just $ Issue "<f>" 2 "block1" [])+ `shouldBe` (Just $ Issue "<f>" 2 (Just "block1") []) it "doesn't display the eventual \n at eof" $ sp issue "\nTOdO: this is it\n"- `shouldBe` (Just $ Issue "<f>" 2 "this is it" [])- it "doesn't accept a lone (naked) todo" $+ `shouldBe` (Just $ Issue "<f>" 2 (Just "this is it") [])+ it "does accept a lone (naked) todo" $ sp issue "\ntodo\n"- `shouldBe` Nothing+ `shouldBe` (Just $ Issue "<f>" 2 Nothing []) it "issues declared with fixme get a free [fixme] tag" $ sp issue "\nfixme blah\n"- `shouldBe` (Just $ Issue "<f>" 2 "blah" [Tag "fixme"])+ `shouldBe` (Just $ Issue "<f>" 2 (Just "blah") [Tag "fixme"]) it "doesn't parse tags non separated by a space" $ sp issue "\ntodo blah[f]\n"- `shouldBe` (Just $ Issue "<f>" 2 "blah[f]" [])+ `shouldBe` (Just $ Issue "<f>" 2 (Just "blah[f]") [])+ it "does parse an empty todo" $+ sp issue "\ntodo\n"+ `shouldBe` (Just $ Issue "<f>" 2 Nothing [])+ it "does parse an empty fixme" $+ sp issue "\nfixme \n"+ `shouldBe` (Just $ Issue "<f>" 2 Nothing [Tag "fixme"])+ it "does parse an empty todo + tags" $+ sp issue "\ntodo [alfa]\n"+ `shouldBe` (Just $ Issue "<f>" 2 Nothing [Tag "alfa"]) describe "issues" $ do it "parses multiple issues" $ sp issues "\nTODO: this is it [f:w]\n TODO: hey [t]"- `shouldBe` Just [Issue "<f>" 2 "this is it" [Tag "f:w"],- Issue "<f>" 3 "hey" [Tag "t"]]+ `shouldBe` Just [Issue "<f>" 2 (Just "this is it") [Tag "f:w"],+ Issue "<f>" 3 (Just "hey") [Tag "t"]] it "doesn't parse multiple issues if on the same line" $ sp issues "\nTODO: this is it [f:w] TODO: hey [t]"- `shouldBe` Just [Issue "<f>" 2 "this is it" [Tag "f:w"]]+ `shouldBe` Just [Issue "<f>" 2 (Just "this is it") [Tag "f:w"]] it "parses two issues, tagless, if the second starts on nl" $ sp issues "\nTODO: this is it \n todo hey [t]"- `shouldBe` Just [Issue "<f>" 2 "this is it" [],- Issue "<f>" 3 "hey" [Tag "t"]]+ `shouldBe` Just [Issue "<f>" 2 (Just "this is it") [],+ Issue "<f>" 3 (Just "hey") [Tag "t"]] it "doesn't pick issues in the middle of a sentence" $ sp issues "\nthis is not a todo as you can see" `shouldBe` (Just [])
test/Lentil/Parse/RunSpec.hs view
@@ -30,12 +30,12 @@ it "doesn't parse contiguous line/block as a single issue" $ fileParser "test/test-files/specific/contiguous.c" `shouldReturn` [Issue "test/test-files/specific/contiguous.c" 1- "issue1" []]+ (Just "issue1") []] - let spt fp = [Issue fp 1 "single comment" [],- Issue fp 3 "single2" [],- Issue fp 8 "block1" [],- Issue fp 9 "block2" [Tag "tog"]]+ let spt fp = [Issue fp 1 (Just "single comment") [],+ Issue fp 3 (Just "single2") [],+ Issue fp 8 (Just "block1") [],+ Issue fp 9 (Just "block2") [Tag "tog"]] describe "commentParser - languages" $ do it "parses a plain text source" $ fileParser "test/test-files/lang-comm/text.txt"@@ -69,8 +69,8 @@ it "reads a file (code or txt) for issues" $ let fp = "test/test-files/lang-comm/test.txt" in issueFinder [fp] >>= \i ->- i `shouldBe` [Issue fp 1 "palla" [],- Issue fp 3 "beta" [Tag "fixme"],- Issue fp 4 "gamma" [Tag "xxx"],- Issue fp 6 "qqq" [Tag "fixme", Tag "bug"]]+ i `shouldBe` [Issue fp 1 (Just "palla") [],+ Issue fp 3 (Just "beta") [Tag "fixme"],+ Issue fp 4 (Just "gamma") [Tag "xxx"],+ Issue fp 6 (Just "qqq") [Tag "fixme", Tag "bug"]]
test/Lentil/QuerySpec.hs view
@@ -14,10 +14,11 @@ spec :: Spec spec = do - let i1 = Issue "a.hs" 1 "issue 1" [Tag "ta", Tag "fl:va"]- i2 = Issue "a.hs" 2 "issue 12" [Tag "tb"]- i3 = Issue "b.hs" 1 "issue 3" [Tag "tb", Tag "fl:vb"]- ix = Issue "b.hs" 1 "issue n" []+ let i1 = Issue "a.hs" 1 (Just "issue 1") [Tag "ta", Tag "fl:va"]+ i2 = Issue "a.hs" 2 (Just "issue 12") [Tag "tb"]+ i3 = Issue "b.hs" 1 (Just "issue 3") [Tag "tb", Tag "fl:vb"]+ ix = Issue "b.hs" 1 (Just "issue n") []+ iz = Issue "b.hs" 1 Nothing [] is = [i1, i2, i3] describe "filter*" $ do@@ -32,16 +33,16 @@ it "filters by using regexps" $ filterTags "(ta|tb)" is `shouldBe` [i1, i2, i3] - describe "filterTagless" $ do- it "filters by empty values" $- filterTagless (ix:is) `shouldBe` [ix]- describe "negFilter" $ do it "negates a filter" $ negFilter (filterTags "fl:") is `shouldBe` [i2] it "cancels itself on a double negation" $ negFilter (negFilter (filterTags "fl:")) is `shouldBe` filterTags "fl:" is+ it "filters by empty values (description)" $+ negFilter (filterDescription ".") (iz:is) `shouldBe` [iz]+ it "filters by empty values (tags)" $+ negFilter (filterTags ".") (ix:is) `shouldBe` [ix] describe "filter(And|Or)" $ do it "chains (boolean and) multiple filters" $@@ -57,7 +58,7 @@ it "sorts Issues in descending order" $ sortIssues iFile Desc is `shouldBe` [i3, i2, i1] it "smart sorts strings containing naturals" $- sortIssues iDesc Asc is `shouldBe` [i1, i3, i2]+ sortIssues (maybe "" id . iDesc) Asc is `shouldBe` [i1, i3, i2] describe "sortTag" $ do it "sorts by partial tag, empty fields first" $@@ -66,7 +67,7 @@ describe "chainSorts" $ do it "sequences sort functions" $ chainSorts is [sortIssues iFile Desc,- sortIssues iDesc Desc]+ sortIssues (maybe "" id . iDesc) Desc] `shouldBe` [i3, i2, i1] describe "groupIssues" $ do