tldr 0.3.0 → 0.3.1
raw patch · 11 files changed
+241/−20 lines, 11 filesdep +tastydep +tasty-goldenPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: tasty, tasty-golden
API changes (from Hackage documentation)
- Tldr: renderNode :: NodeType -> IO ()
+ Tldr: renderNode :: NodeType -> Handle -> IO ()
- Tldr: renderPage :: FilePath -> IO ()
+ Tldr: renderPage :: FilePath -> Handle -> IO ()
Files
- CHANGELOG.md +6/−0
- app/Main.hs +2/−1
- src/Tldr.hs +36/−16
- test/Spec.hs +37/−1
- test/data/grep.golden +26/−0
- test/data/grep.md +36/−0
- test/data/ls.golden +20/−0
- test/data/ls.md +27/−0
- test/data/ps.golden +20/−0
- test/data/ps.md +27/−0
- tldr.cabal +4/−2
CHANGELOG.md view
@@ -1,3 +1,9 @@+# 0.3.1++* Add golden testing using tasty+* Fix grep render [#11](https://github.com/psibi/tldr-hs/issues/11)+* Fixes [#2](https://github.com/psibi/tldr-hs/issues/2)+ # 0.3.0 * Add default completion support from optparse-applicative
app/Main.hs view
@@ -11,6 +11,7 @@ import System.FilePath import System.Process.Typed import System.Environment (getArgs, withArgs)+import GHC.IO.Handle.FD (stdout) import Paths_tldr (version) import Data.Version (showVersion) @@ -106,5 +107,5 @@ initializeTldrPages let page = pageName opts fname <- getPagePath page- maybe (putStrLn ("No tldr entry for " <> page)) renderPage fname+ maybe (putStrLn ("No tldr entry for " <> page)) (flip renderPage stdout) fname compOpts@(CompletionInvoked _) -> handleParseResult compOpts >> return ()
src/Tldr.hs view
@@ -12,10 +12,12 @@ ) where import Data.Text+import qualified Data.Text as T import qualified Data.Text.IO as TIO import CMark import System.Console.ANSI import Data.Monoid ((<>))+import GHC.IO.Handle (Handle) data ConsoleSetting = ConsoleSetting { italic :: Bool@@ -54,15 +56,15 @@ , SetColor Foreground (fgIntensity cons) (fgColor cons) ] -renderNode :: NodeType -> IO ()-renderNode (TEXT txt) = TIO.putStrLn txt-renderNode (HTML_BLOCK txt) = TIO.putStrLn txt-renderNode (CODE_BLOCK _ txt) = TIO.putStrLn txt-renderNode (HTML_INLINE txt) = TIO.putStrLn txt-renderNode (CODE txt) = TIO.putStrLn (" " <> txt)-renderNode LINEBREAK = TIO.putStrLn ""-renderNode (LIST _) = TIO.putStrLn "" >> TIO.putStr " - "-renderNode _ = return ()+renderNode :: NodeType -> Handle -> IO ()+renderNode (TEXT txt) handle = TIO.hPutStrLn handle txt+renderNode (HTML_BLOCK txt) handle = TIO.hPutStrLn handle txt+renderNode (CODE_BLOCK _ txt) handle = TIO.hPutStrLn handle txt+renderNode (HTML_INLINE txt) handle = TIO.hPutStrLn handle txt+renderNode (CODE txt) handle = TIO.hPutStrLn handle (" " <> txt)+renderNode LINEBREAK handle = TIO.hPutStrLn handle ""+renderNode (LIST _) handle = TIO.hPutStrLn handle "" >> TIO.hPutStr handle " - "+renderNode _ _ = return () changeConsoleSetting :: NodeType -> IO () changeConsoleSetting (HEADING _) = setSGR $ toSGR headingSetting@@ -81,11 +83,29 @@ } changeConsoleSetting _ = return () -handleNode :: Node -> IO ()-handleNode (Node _ ntype xs) = do+handleSubsetNodeType :: NodeType -> Text+handleSubsetNodeType (HTML_BLOCK txt) = txt+handleSubsetNodeType (CODE_BLOCK _ txt) = txt+handleSubsetNodeType (TEXT txt) = txt+handleSubsetNodeType (HTML_INLINE txt) = txt+handleSubsetNodeType (CODE txt) = txt+handleSubsetNodeType _ = mempty+++handleSubsetNode :: Node -> Text+handleSubsetNode (Node _ ntype xs) = handleSubsetNodeType ntype <> (T.concat $ Prelude.map handleSubsetNode xs)++handleParagraph :: [Node] -> Handle -> IO ()+handleParagraph xs handle = TIO.hPutStrLn handle $ T.concat $ Prelude.map handleSubsetNode xs+++handleNode :: Node -> Handle -> IO ()+handleNode (Node _ PARAGRAPH xs) handle = handleParagraph xs handle+handleNode (Node _ ITEM xs) handle = handleParagraph xs handle+handleNode (Node _ ntype xs) handle = do changeConsoleSetting ntype- renderNode ntype- mapM_ (\(Node _ ntype' ns) -> renderNode ntype' >> mapM_ handleNode ns) xs+ renderNode ntype handle+ mapM_ (\(Node _ ntype' ns) -> renderNode ntype' handle >> mapM_ (flip handleNode $ handle) ns) xs setSGR [Reset] parsePage :: FilePath -> IO Node@@ -94,7 +114,7 @@ let node = commonmarkToNode [] page return node -renderPage :: FilePath -> IO ()-renderPage fname = do+renderPage :: FilePath -> Handle -> IO ()+renderPage fname handle = do node <- parsePage fname- handleNode node+ handleNode node handle
test/Spec.hs view
@@ -1,2 +1,38 @@+import Tldr+import Test.Tasty+import Test.Tasty.Golden (goldenVsFile)+import System.IO (withBinaryFile, IOMode(..))+import Data.Monoid ((<>))++tests :: TestTree+tests = testGroup "tldr Tests" [goldenTests]++goldenTests :: TestTree+goldenTests = testGroup "Golden tests" [gtests]++renderPageToFile :: FilePath -> FilePath -> IO ()+renderPageToFile mdfile opfile = do+ withBinaryFile opfile WriteMode (\handle -> renderPage mdfile handle)++-- For adding new command, you need to add:+-- A new ".md" file for that command+-- A new ".golden" file for the expected output++commandTest :: String -> TestTree+commandTest str = goldenVsFile (str <> " test") (golden str) (output str) (renderPageToFile (md str) (output str))+ where+ prefix = "test/data/"+ golden cmd = prefix <> cmd <> ".golden"+ output cmd = prefix <> cmd <> ".output"+ md cmd = prefix <> cmd <> ".md"++gtests :: TestTree+gtests = testGroup "(render test)" + [+ commandTest "ls"+ , commandTest "ps"+ , commandTest "grep"+ ]+ main :: IO ()-main = putStrLn "Test suite not yet implemented"+main = defaultMain tests
+ test/data/grep.golden view
@@ -0,0 +1,26 @@+grep+Matches patterns in input text.Supports simple patterns and regular expressions.++ - Search for an exact string:+ grep {{search_string}} {{path/to/file}}++ - Search in case-insensitive mode:+ grep -i {{search_string}} {{path/to/file}}++ - Search recursively (ignoring non-text files) in current directory for an exact string:+ grep -RI {{search_string}} .++ - Use extended regular expressions (supporting ?, +, {}, () and |):+ grep -E {{^regex$}} {{path/to/file}}++ - Print 3 lines of [C]ontext around, [B]efore, or [A]fter each match:+ grep -{{C|B|A}} 3 {{search_string}} {{path/to/file}}++ - Print file name with the corresponding line number for each match:+ grep -Hn {{search_string}} {{path/to/file}}++ - Use the standard input instead of a file:+ cat {{path/to/file}} | grep {{search_string}}++ - Invert match for excluding specific strings:+ grep -v {{search_string}}
+ test/data/grep.md view
@@ -0,0 +1,36 @@+# grep++> Matches patterns in input text.+> Supports simple patterns and regular expressions.++- Search for an exact string:++`grep {{search_string}} {{path/to/file}}`++- Search in case-insensitive mode:++`grep -i {{search_string}} {{path/to/file}}`++- Search recursively (ignoring non-text files) in current directory for an exact string:++`grep -RI {{search_string}} .`++- Use extended regular expressions (supporting `?`, `+`, `{}`, `()` and `|`):++`grep -E {{^regex$}} {{path/to/file}}`++- Print 3 lines of [C]ontext around, [B]efore, or [A]fter each match:++`grep -{{C|B|A}} 3 {{search_string}} {{path/to/file}}`++- Print file name with the corresponding line number for each match:++`grep -Hn {{search_string}} {{path/to/file}}`++- Use the standard input instead of a file:++`cat {{path/to/file}} | grep {{search_string}}`++- Invert match for excluding specific strings:++`grep -v {{search_string}}`
+ test/data/ls.golden view
@@ -0,0 +1,20 @@+ls+List directory contents.++ - List files one per line:+ ls -1++ - List all files, including hidden files:+ ls -a++ - Long format list (permissions, ownership, size and modification date) of all files:+ ls -la++ - Long format list with size displayed using human readable units (KB, MB, GB):+ ls -lh++ - Long format list sorted by size (descending):+ ls -lS++ - Long format list of all files, sorted by modification date (oldest first):+ ls -ltr
+ test/data/ls.md view
@@ -0,0 +1,27 @@+# ls++> List directory contents.++- List files one per line:++`ls -1`++- List all files, including hidden files:++`ls -a`++- Long format list (permissions, ownership, size and modification date) of all files:++`ls -la`++- Long format list with size displayed using human readable units (KB, MB, GB):++`ls -lh`++- Long format list sorted by size (descending):++`ls -lS`++- Long format list of all files, sorted by modification date (oldest first):++`ls -ltr`
+ test/data/ps.golden view
@@ -0,0 +1,20 @@+ps+Information about running processes.++ - List all running processes:+ ps aux++ - List all running processes including the full command string:+ ps auxww++ - Search for a process that matches a string:+ ps aux | grep {{string}}++ - List all processes of the current user in extra full format:+ ps --user $(id -u) -F++ - List all processes of the current user as a tree:+ ps --user $(id -u) f++ - Get the parent pid of a process:+ ps -o ppid= -p {{pid}}
+ test/data/ps.md view
@@ -0,0 +1,27 @@+# ps++> Information about running processes.++- List all running processes:++`ps aux`++- List all running processes including the full command string:++`ps auxww`++- Search for a process that matches a string:++`ps aux | grep {{string}}`++- List all processes of the current user in extra full format:++`ps --user $(id -u) -F`++- List all processes of the current user as a tree:++`ps --user $(id -u) f`++- Get the parent pid of a process:++`ps -o ppid= -p {{pid}}`
tldr.cabal view
@@ -1,5 +1,5 @@ name: tldr-version: 0.3.0+version: 0.3.1 synopsis: Haskell tldr client description: Haskell tldr client with support for updating and viewing tldr pages. homepage: https://github.com/psibi/tldr-hs#readme@@ -10,7 +10,7 @@ copyright: 2017 Sibi category: Web build-type: Simple-extra-source-files: README.md, CHANGELOG.md+extra-source-files: README.md, CHANGELOG.md, test/data/*.golden, test/data/*.md cabal-version: >=1.10 library@@ -43,6 +43,8 @@ main-is: Spec.hs build-depends: base , tldr+ , tasty+ , tasty-golden ghc-options: -threaded -rtsopts -with-rtsopts=-N default-language: Haskell2010