diff --git a/hledger-ui/Hledger/UI/AccountsScreen.hs b/hledger-ui/Hledger/UI/AccountsScreen.hs index 5ddf44636..ab06e8568 100644 --- a/hledger-ui/Hledger/UI/AccountsScreen.hs +++ b/hledger-ui/Hledger/UI/AccountsScreen.hs @@ -40,6 +40,7 @@ import Hledger.UI.Editor import Hledger.UI.RegisterScreen import Hledger.UI.ErrorScreen + accountsScreen :: Screen accountsScreen = AccountsScreen{ sInit = asInit @@ -277,6 +278,7 @@ asHandle ui0@UIState{ VtyEvent (EvKey KEnter []) -> continue $ regenerateScreens j d $ setFilter s $ closeMinibuffer ui where s = chomp $ unlines $ map strip $ getEditContents ed VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui + VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui VtyEvent ev -> do ed' <- handleEditorEvent ev ed continue $ ui{aMode=Minibuffer ed'} AppEvent _ -> continue ui @@ -287,6 +289,7 @@ asHandle ui0@UIState{ case ev of VtyEvent (EvKey (KChar 'q') []) -> halt ui VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui + VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui _ -> helpHandle ui ev Normal -> @@ -340,6 +343,7 @@ asHandle ui0@UIState{ VtyEvent (EvKey k []) | k `elem` [KBS, KDel] -> (continue $ regenerateScreens j d $ resetFilter ui) VtyEvent e | e `elem` moveLeftEvents -> continue $ popScreen ui VtyEvent (EvKey (KChar 'l') [MCtrl]) -> scrollSelectionToMiddle _asList >> redraw ui + VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui -- enter register screen for selected account (if there is one), -- centering its selected transaction if possible diff --git a/hledger-ui/Hledger/UI/ErrorScreen.hs b/hledger-ui/Hledger/UI/ErrorScreen.hs index 46b0f47f1..10352375b 100644 --- a/hledger-ui/Hledger/UI/ErrorScreen.hs +++ b/hledger-ui/Hledger/UI/ErrorScreen.hs @@ -86,6 +86,7 @@ esHandle ui@UIState{aScreen=ErrorScreen{..} case ev of VtyEvent (EvKey (KChar 'q') []) -> halt ui VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui + VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui _ -> helpHandle ui ev _ -> do @@ -107,6 +108,7 @@ esHandle ui@UIState{aScreen=ErrorScreen{..} -- Right j' -> continue $ regenerateScreens j' d $ popScreen ui -- return to previous screen, and reload it VtyEvent (EvKey (KChar 'I') []) -> continue $ uiCheckBalanceAssertions d (popScreen $ toggleIgnoreBalanceAssertions ui) VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui + VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui _ -> continue ui esHandle _ _ = error "event handler called with wrong screen type, should not happen" diff --git a/hledger-ui/Hledger/UI/RegisterScreen.hs b/hledger-ui/Hledger/UI/RegisterScreen.hs index 593c4c169..b9f4da063 100644 --- a/hledger-ui/Hledger/UI/RegisterScreen.hs +++ b/hledger-ui/Hledger/UI/RegisterScreen.hs @@ -282,6 +282,7 @@ rsHandle ui@UIState{ VtyEvent (EvKey KEnter []) -> continue $ regenerateScreens j d $ setFilter s $ closeMinibuffer ui where s = chomp $ unlines $ map strip $ getEditContents ed VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui + VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui VtyEvent ev -> do ed' <- handleEditorEvent ev ed continue $ ui{aMode=Minibuffer ed'} AppEvent _ -> continue ui @@ -292,6 +293,7 @@ rsHandle ui@UIState{ case ev of VtyEvent (EvKey (KChar 'q') []) -> halt ui VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui + VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui _ -> helpHandle ui ev Normal -> @@ -336,6 +338,7 @@ rsHandle ui@UIState{ VtyEvent (EvKey k []) | k `elem` [KBS, KDel] -> (continue $ regenerateScreens j d $ resetFilter ui) VtyEvent e | e `elem` moveLeftEvents -> continue $ popScreen ui VtyEvent (EvKey (KChar 'l') [MCtrl]) -> scrollSelectionToMiddle rsList >> redraw ui + VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui -- enter transaction screen for selected transaction VtyEvent e | e `elem` moveRightEvents -> do diff --git a/hledger-ui/Hledger/UI/TransactionScreen.hs b/hledger-ui/Hledger/UI/TransactionScreen.hs index 86c397c51..871a3cc43 100644 --- a/hledger-ui/Hledger/UI/TransactionScreen.hs +++ b/hledger-ui/Hledger/UI/TransactionScreen.hs @@ -120,6 +120,7 @@ tsHandle ui@UIState{aScreen=s@TransactionScreen{tsTransaction=(i,t) case ev of VtyEvent (EvKey (KChar 'q') []) -> halt ui VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui + VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui _ -> helpHandle ui ev _ -> do @@ -180,6 +181,7 @@ tsHandle ui@UIState{aScreen=s@TransactionScreen{tsTransaction=(i,t) ui'@UIState{aScreen=scr} = popScreen ui ui'' = ui'{aScreen=rsSelect (fromIntegral i) scr} VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui + VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui _ -> continue ui tsHandle _ _ = error "event handler called with wrong screen type, should not happen" diff --git a/hledger-ui/Hledger/UI/UIUtils.hs b/hledger-ui/Hledger/UI/UIUtils.hs index ad62cf9fd..4dbe87825 100644 --- a/hledger-ui/Hledger/UI/UIUtils.hs +++ b/hledger-ui/Hledger/UI/UIUtils.hs @@ -21,6 +21,8 @@ module Hledger.UI.UIUtils ( ,renderToggle ,replaceHiddenAccountsNameWith ,scrollSelectionToMiddle + ,suspend + ,suspendAndRedraw ,redraw ) where @@ -50,6 +52,35 @@ import Hledger.Cli.DocFiles import Hledger.UI.UITypes import Hledger.UI.UIState +-- | On posix platforms, suspend the program using the system STOP signal +-- (as control-z usually does in bash). On windows, does nothing. +#ifdef mingw32_HOST_OS +suspend :: IO () +suspend = return () +#else +import System.Posix.Signals +suspend :: IO () +suspend = raiseSignal sigSTOP +#endif + +-- | On posix platforms, suspend the program using the system STOP +-- signal, returning to the original shell prompt +-- (TODO: and restore the original terminal attributes). +-- When the program is resumed, redraw the screen and continue. +-- On windows, just redraws the screen. +suspendAndRedraw :: s -> EventM a (Next s) +suspendAndRedraw ui = do + -- reset terminal attributes using vty ? + -- Vty{outputIface=output} <- getVtyHandle + -- r <- displayBounds output + -- DisplayContext{writeDefaultAttr=_reset} <- liftIO $ (mkDisplayContext output) output r + -- runWrite (reset True) _someptr + + -- suspend.. + liftIO suspend + + -- ..and resume + redraw ui -- | Tell vty to redraw the whole screen, and continue. redraw :: s -> EventM a (Next s) @@ -74,7 +105,7 @@ helpDialog _copts = render $ withDefAttr "help" $ renderDialog (dialog (Just "Help (?/LEFT/ESC to close)") Nothing (c^.availWidthL)) $ -- (Just (0,[("ok",())])) - padAll 1 $ + padTop (Pad 1) $ padLeft (Pad 1) $ padRight (Pad 1) $ vBox [ hBox [ padRight (Pad 1) $ @@ -120,8 +151,9 @@ helpDialog _copts = ,renderKey ("A ", "add transaction (hledger-iadd)") ,renderKey ("E ", "open editor") ,renderKey ("I ", "toggle balance assertions") - ,renderKey ("C-l ", "redraw & recenter") ,renderKey ("g ", "reload data") + ,renderKey ("C-l ", "redraw & recenter") + ,renderKey ("C-z ", "suspend") ,renderKey ("q ", "quit") ] ] diff --git a/hledger-ui/hledger-ui.cabal b/hledger-ui/hledger-ui.cabal index c328302df..96e525c1a 100644 --- a/hledger-ui/hledger-ui.cabal +++ b/hledger-ui/hledger-ui.cabal @@ -4,7 +4,7 @@ cabal-version: 1.12 -- -- see: https://github.com/sol/hpack -- --- hash: 9e7f4d999a8b69e7adb4b03f99c96b7ae47113f1b11fe7ddb289e352b2632e7c +-- hash: cb5960060c369ce0540af1659e44ad678d26cbc9dca2e8481fe8657bc8fc13ab name: hledger-ui version: 1.12.99 @@ -95,6 +95,7 @@ executable hledger-ui else build-depends: brick >=0.12 + , unix , vty >=5.5 if flag(threaded) ghc-options: -threaded diff --git a/hledger-ui/package.yaml b/hledger-ui/package.yaml index 51cb6a5e7..ee400f748 100644 --- a/hledger-ui/package.yaml +++ b/hledger-ui/package.yaml @@ -82,6 +82,7 @@ when: else: dependencies: - brick >=0.12 + - unix - vty >=5.5 executables: