;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,12 +74,16 @@ 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
-- Check if arguments could be interpreted as files. isTerminal <- hIsTerminalDevice stdin
-- If not, assume that they are commands specified directly on the command line if args == [] && not isTerminal
allAreFiles <- and <$> mapM (doesFileExist . snd . splitReaderPrefix) args then runREPL j findBuiltinCommand
case allAreFiles of else do
True -> runFromFiles j findBuiltinCommand args -- Check if arguments could be interpreted as files.
False -> runFromArgs j findBuiltinCommand args -- If not, assume that they are commands specified directly on the command line
allAreFiles <- and <$> mapM (doesFileExist . snd . splitReaderPrefix) args
case allAreFiles of
True -> runFromFiles j findBuiltinCommand args
False -> runFromArgs j findBuiltinCommand args
-- | The actual repl command. -- | The actual repl command.
repl :: (String -> Maybe (Mode RawOpts, CliOpts -> Journal -> IO ())) -> CliOpts -> IO () repl :: (String -> Maybe (Mode RawOpts, CliOpts -> Journal -> IO ())) -> CliOpts -> IO ()
@ -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
putStrLn "Enter hledger commands. To exit, enter 'quit' or 'exit', or send EOF." isTerminal <- hIsTerminalDevice stdin
runInputT defaultSettings loop if not isTerminal
then runInputT defaultSettings (loop "")
else do
putStrLn "Enter hledger commands. To exit, enter 'quit' or 'exit', or send EOF."
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.