;run: accept commands on stdin, repl hides prompt when non-interactive

This commit is contained in:
Dmitry Astapov 2025-02-28 12:18:58 +00:00 committed by Simon Michael
parent 2f348f787b
commit ef6b6ecc1b

View File

@ -33,6 +33,7 @@ import Control.Monad.Extra (concatMapM)
import System.Console.CmdArgs.Explicit (expandArgsAt) import System.Console.CmdArgs.Explicit (expandArgsAt)
import System.Directory (doesFileExist) import System.Directory (doesFileExist)
import System.IO (stdin, hIsTerminalDevice)
import System.IO.Unsafe (unsafePerformIO) import System.IO.Unsafe (unsafePerformIO)
import System.Console.Haskeline import System.Console.Haskeline
@ -73,6 +74,10 @@ run :: Maybe Journal -> (String -> Maybe (Mode RawOpts, CliOpts -> Journal -> IO
run defaultJournalOverride findBuiltinCommand cliopts@CliOpts{rawopts_=rawopts} = do run defaultJournalOverride findBuiltinCommand cliopts@CliOpts{rawopts_=rawopts} = do
withJournalCached defaultJournalOverride cliopts $ \j -> do withJournalCached defaultJournalOverride cliopts $ \j -> do
let args = dbg1 "args" $ listofstringopt "args" rawopts let args = dbg1 "args" $ listofstringopt "args" rawopts
isTerminal <- hIsTerminalDevice stdin
if args == [] && not isTerminal
then runREPL j findBuiltinCommand
else do
-- Check if arguments could be interpreted as files. -- Check if arguments could be interpreted as files.
-- If not, assume that they are commands specified directly on the command line -- If not, assume that they are commands specified directly on the command line
allAreFiles <- and <$> mapM (doesFileExist . snd . splitReaderPrefix) args allAreFiles <- and <$> mapM (doesFileExist . snd . splitReaderPrefix) args
@ -135,12 +140,16 @@ runCommand defaultJrnl findBuiltinCommand cmdline = do
-- | Run an interactive REPL. -- | Run an interactive REPL.
runREPL :: Journal -> (String -> Maybe (Mode RawOpts, CliOpts -> Journal -> IO ())) -> IO () runREPL :: Journal -> (String -> Maybe (Mode RawOpts, CliOpts -> Journal -> IO ())) -> IO ()
runREPL defaultJrnl findBuiltinCommand = do runREPL defaultJrnl findBuiltinCommand = do
isTerminal <- hIsTerminalDevice stdin
if not isTerminal
then runInputT defaultSettings (loop "")
else do
putStrLn "Enter hledger commands. To exit, enter 'quit' or 'exit', or send EOF." putStrLn "Enter hledger commands. To exit, enter 'quit' or 'exit', or send EOF."
runInputT defaultSettings loop runInputT defaultSettings (loop "% ")
where where
loop :: InputT IO () loop :: String -> InputT IO ()
loop = do loop prompt = do
minput <- getInputLine "% " minput <- getInputLine prompt
case minput of case minput of
Nothing -> return () Nothing -> return ()
Just "quit" -> return () Just "quit" -> return ()
@ -148,6 +157,7 @@ runREPL defaultJrnl findBuiltinCommand = do
Just input -> do Just input -> do
liftIO $ (runCommand defaultJrnl findBuiltinCommand $ parseCommand input) liftIO $ (runCommand defaultJrnl findBuiltinCommand $ parseCommand input)
`catch` (\(e::ErrorCall) -> putStr $ show e) `catch` (\(e::ErrorCall) -> putStr $ show e)
loop prompt
-- | Cache of all journals that have been read by commands given to "run", -- | Cache of all journals that have been read by commands given to "run",
-- keyed by the fully-expanded filename. -- keyed by the fully-expanded filename.