diff --git a/hledger/Hledger/Cli/Commands/Help.md b/hledger/Hledger/Cli/Commands/Help.md index c89d87376..79924b8ff 100644 --- a/hledger/Hledger/Cli/Commands/Help.md +++ b/hledger/Hledger/Cli/Commands/Help.md @@ -1,30 +1,30 @@ ## help -Show the hledger user manual in the terminal, with `info`, `man`, or a pager. -With a TOPIC argument, open it at that topic if possible. -TOPIC can be any heading in the manual, or a heading prefix, case insensitive. -Eg: `commands`, `print`, `forecast`, `journal`, `amount`, `"auto postings"`. +Show the hledger user manual with `info`, `man`, or a pager. +With a (case insensitive) TOPIC argument, try to open it at that section heading. _FLAGS -This command shows the hledger manual built in to your hledger version. +This command shows the hledger manual built in to your hledger executable. It can be useful when offline, or when you prefer the terminal to a web browser, -or when the appropriate hledger manual or viewing tools are not installed on your system. +or when the appropriate hledger manual or viewers are not installed properly on your system. -By default it chooses the best viewer found in $PATH, trying (in this order): -`info`, `man`, `$PAGER`, `less`, `more`. -You can force the use of info, man, or a pager with the `-i`, `-m`, or `-p` flags, -If no viewer can be found, or the command is run non-interactively, it just prints -the manual to stdout. +By default it chooses the best viewer found in $PATH, trying in this order: +`info`, `man`, `$PAGER`, `less`, `more`, stdout. +(If a TOPIC is specified, `$PAGER` and `more` are not tried.) +You can force the use of info, man, or a pager with the `-i`, `-m`, or `-p` flags. +If no viewer can be found, or if running non-interactively, it just prints the manual to stdout. -If using `info`, note that version 6 or greater is needed for TOPIC lookup. If you are -on mac you will likely have info 4.8, and should consider installing a newer version, -eg with `brew install texinfo` (#1770). +When using `info`, TOPIC can match either the full heading or a prefix. +If your `info --version` is < 6, you'll need to upgrade it, eg with '`brew install texinfo`' on mac. + +When using `man` or `less`, TOPIC must match the full heading. +For a prefix match, you can write '`TOPIC.*`'. Examples ```cli -$ hledger help --help # show how the help command works -$ hledger help # show the hledger manual with info, man or $PAGER -$ hledger help journal # show the journal topic in the hledger manual -$ hledger help -m journal # show it with man, even if info is installed +$ hledger help -h # show the help command's usage +$ hledger help # show the manual with info, man or $PAGER +$ hledger help 'time periods' # show the manual's "Time periods" topic +$ hledger help 'time periods' -m # use man, even if info is installed ``` diff --git a/hledger/Hledger/Cli/DocFiles.hs b/hledger/Hledger/Cli/DocFiles.hs index 9cd32611c..228e2b1ea 100644 --- a/hledger/Hledger/Cli/DocFiles.hs +++ b/hledger/Hledger/Cli/DocFiles.hs @@ -22,7 +22,7 @@ module Hledger.Cli.DocFiles ( import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as BC -import Data.Maybe (fromMaybe, isNothing) +import Data.Maybe (fromMaybe) import Data.String import System.IO import System.IO.Temp @@ -85,45 +85,9 @@ printHelpForTopic :: Tool -> Maybe Topic -> IO () printHelpForTopic tool _mtopic = BC.putStr (toolDocTxt tool) --- | Display plain text help for this tool, scrolled to the given topic --- if provided, using the given pager executable. --- Note when a topic is provided we ignore the provided pager and --- use the "less" executable in $PATH. -runPagerForTopic :: Tool -> Maybe Topic -> IO () -runPagerForTopic tool mtopic = do - -- avoids a temp file but different from the others and not sure how to make it scroll - -- pager <- fromMaybe "less" <$> lookupEnv "PAGER" - -- (Just inp, _, _, ph) <- createProcess (proc pager []){ - -- std_in=CreatePipe - -- } - -- BC.hPutStrLn inp (toolDocTxt tool) - -- _ <- waitForProcess ph - -- return () - - withSystemTempFile ("hledger-"++tool++".txt") $ \f h -> do - BC.hPutStrLn h $ toolDocTxt tool - hClose h - let defpager = "less -is" - envpager <- fromMaybe defpager <$> lookupEnv "PAGER" - -- force the use of less if a topic is provided, since we know how to scroll it - let pager = if isNothing mtopic then envpager else defpager - callCommand $ dbg1 "pager command" $ - pager ++ maybe "" (printf " +'/^( )?%s'") mtopic ++ " " ++ f - --- | Display a man page for this tool, scrolled to the given topic if provided, --- using the "man" executable in $PATH. Note when a topic is provided we force --- man to use the "less" executable in $PATH, ignoring $MANPAGER and $PAGER. -runManForTopic :: Tool -> Maybe Topic -> IO () -runManForTopic tool mtopic = - withSystemTempFile ("hledger-"++tool++".nroff") $ \f h -> do - BC.hPutStrLn h $ toolDocMan tool - hClose h - -- the temp file path will presumably have a slash in it, so man should read it - callCommand $ dbg1 "man command" $ - "man " ++ f ++ maybe "" (printf " -P \"less -is +'/^( )?%s'\"") mtopic - -- | Display an info manual for this topic, opened at the given topic if provided, -- using the "info" executable in $PATH. +-- Topic can be an exact heading or a heading prefix; info will favour an exact match. runInfoForTopic :: Tool -> Maybe Topic -> IO () runInfoForTopic tool mtopic = withSystemTempFile ("hledger-"++tool++".info") $ \f h -> do @@ -131,3 +95,38 @@ runInfoForTopic tool mtopic = hClose h callCommand $ dbg1 "info command" $ "info -f " ++ f ++ maybe "" (printf " -n '%s'") mtopic + +-- less with any vertical whitespace squashed, case-insensitive searching, the $ regex metacharacter accessible as \$. +less = "less -s -i --use-backslash" + +-- | Display plain text help for this tool, scrolled to the given topic if any, using the users $PAGER or "less". +-- When a topic is provided we always use less, ignoring $PAGER. +runPagerForTopic :: Tool -> Maybe Topic -> IO () +runPagerForTopic tool mtopic = do + withSystemTempFile ("hledger-"++tool++".txt") $ \f h -> do + BC.hPutStrLn h $ toolDocTxt tool + hClose h + envpager <- fromMaybe less <$> lookupEnv "PAGER" + let + exactmatch = True + (pager, searcharg) = + case mtopic of + Nothing -> (envpager, "") + Just t -> (less, "-p'^( )?" ++ t ++ if exactmatch then "\\$'" else "") + callCommand $ dbg1 "pager command" $ unwords [pager, searcharg, f] + +-- | Display a man page for this tool, scrolled to the given topic if provided, using "man". +-- When a topic is provided we force man to use "less", ignoring $MANPAGER and $PAGER. +runManForTopic :: Tool -> Maybe Topic -> IO () +runManForTopic tool mtopic = + -- This temp file path should have a slash in it, man requires at least one. + withSystemTempFile ("hledger-"++tool++".1") $ \f h -> do + BC.hPutStrLn h $ toolDocMan tool + hClose h + let + exactmatch = True + pagerarg = + case mtopic of + Nothing -> "" + Just t -> "-P \"" ++ less ++ " -p'^( )?" ++ t ++ (if exactmatch then "\\\\$" else "") ++ "'\"" + callCommand $ dbg1 "man command" $ unwords ["man", pagerarg, f]