ui: on posix, support ctrl-z to suspend the program
This commit is contained in:
		
							parent
							
								
									c02647d05e
								
							
						
					
					
						commit
						cc0764eac2
					
				| @ -40,6 +40,7 @@ import Hledger.UI.Editor | |||||||
| import Hledger.UI.RegisterScreen | import Hledger.UI.RegisterScreen | ||||||
| import Hledger.UI.ErrorScreen | import Hledger.UI.ErrorScreen | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| accountsScreen :: Screen | accountsScreen :: Screen | ||||||
| accountsScreen = AccountsScreen{ | accountsScreen = AccountsScreen{ | ||||||
|    sInit   = asInit |    sInit   = asInit | ||||||
| @ -277,6 +278,7 @@ asHandle ui0@UIState{ | |||||||
|         VtyEvent (EvKey KEnter []) -> continue $ regenerateScreens j d $ setFilter s $ closeMinibuffer ui |         VtyEvent (EvKey KEnter []) -> continue $ regenerateScreens j d $ setFilter s $ closeMinibuffer ui | ||||||
|                             where s = chomp $ unlines $ map strip $ getEditContents ed |                             where s = chomp $ unlines $ map strip $ getEditContents ed | ||||||
|         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui |         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui | ||||||
|  |         VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui | ||||||
|         VtyEvent ev        -> do ed' <- handleEditorEvent ev ed |         VtyEvent ev        -> do ed' <- handleEditorEvent ev ed | ||||||
|                                  continue $ ui{aMode=Minibuffer ed'} |                                  continue $ ui{aMode=Minibuffer ed'} | ||||||
|         AppEvent _        -> continue ui |         AppEvent _        -> continue ui | ||||||
| @ -287,6 +289,7 @@ asHandle ui0@UIState{ | |||||||
|       case ev of |       case ev of | ||||||
|         VtyEvent (EvKey (KChar 'q') []) -> halt ui |         VtyEvent (EvKey (KChar 'q') []) -> halt ui | ||||||
|         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui |         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui | ||||||
|  |         VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui | ||||||
|         _                    -> helpHandle ui ev |         _                    -> helpHandle ui ev | ||||||
| 
 | 
 | ||||||
|     Normal -> |     Normal -> | ||||||
| @ -340,6 +343,7 @@ asHandle ui0@UIState{ | |||||||
|         VtyEvent (EvKey k           []) | k `elem` [KBS, KDel] -> (continue $ regenerateScreens j d $ resetFilter ui) |         VtyEvent (EvKey k           []) | k `elem` [KBS, KDel] -> (continue $ regenerateScreens j d $ resetFilter ui) | ||||||
|         VtyEvent e | e `elem` moveLeftEvents -> continue $ popScreen ui |         VtyEvent e | e `elem` moveLeftEvents -> continue $ popScreen ui | ||||||
|         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> scrollSelectionToMiddle _asList >> redraw 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),  |         -- enter register screen for selected account (if there is one),  | ||||||
|         -- centering its selected transaction if possible |         -- centering its selected transaction if possible | ||||||
|  | |||||||
| @ -86,6 +86,7 @@ esHandle ui@UIState{aScreen=ErrorScreen{..} | |||||||
|       case ev of |       case ev of | ||||||
|         VtyEvent (EvKey (KChar 'q') []) -> halt ui |         VtyEvent (EvKey (KChar 'q') []) -> halt ui | ||||||
|         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui |         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui | ||||||
|  |         VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui | ||||||
|         _                    -> helpHandle ui ev |         _                    -> helpHandle ui ev | ||||||
| 
 | 
 | ||||||
|     _ -> do |     _ -> 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 | --             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 'I') []) -> continue $ uiCheckBalanceAssertions d (popScreen $ toggleIgnoreBalanceAssertions ui) | ||||||
|         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui |         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui | ||||||
|  |         VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui | ||||||
|         _ -> continue ui |         _ -> continue ui | ||||||
| 
 | 
 | ||||||
| esHandle _ _ = error "event handler called with wrong screen type, should not happen" | esHandle _ _ = error "event handler called with wrong screen type, should not happen" | ||||||
|  | |||||||
| @ -282,6 +282,7 @@ rsHandle ui@UIState{ | |||||||
|         VtyEvent (EvKey KEnter []) -> continue $ regenerateScreens j d $ setFilter s $ closeMinibuffer ui |         VtyEvent (EvKey KEnter []) -> continue $ regenerateScreens j d $ setFilter s $ closeMinibuffer ui | ||||||
|                             where s = chomp $ unlines $ map strip $ getEditContents ed |                             where s = chomp $ unlines $ map strip $ getEditContents ed | ||||||
|         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui |         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui | ||||||
|  |         VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui | ||||||
|         VtyEvent ev              -> do ed' <- handleEditorEvent ev ed |         VtyEvent ev              -> do ed' <- handleEditorEvent ev ed | ||||||
|                                        continue $ ui{aMode=Minibuffer ed'} |                                        continue $ ui{aMode=Minibuffer ed'} | ||||||
|         AppEvent _        -> continue ui |         AppEvent _        -> continue ui | ||||||
| @ -292,6 +293,7 @@ rsHandle ui@UIState{ | |||||||
|       case ev of |       case ev of | ||||||
|         VtyEvent (EvKey (KChar 'q') []) -> halt ui |         VtyEvent (EvKey (KChar 'q') []) -> halt ui | ||||||
|         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui |         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui | ||||||
|  |         VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui | ||||||
|         _                    -> helpHandle ui ev |         _                    -> helpHandle ui ev | ||||||
| 
 | 
 | ||||||
|     Normal -> |     Normal -> | ||||||
| @ -336,6 +338,7 @@ rsHandle ui@UIState{ | |||||||
|         VtyEvent (EvKey k           []) | k `elem` [KBS, KDel] -> (continue $ regenerateScreens j d $ resetFilter ui) |         VtyEvent (EvKey k           []) | k `elem` [KBS, KDel] -> (continue $ regenerateScreens j d $ resetFilter ui) | ||||||
|         VtyEvent e | e `elem` moveLeftEvents  -> continue $ popScreen ui |         VtyEvent e | e `elem` moveLeftEvents  -> continue $ popScreen ui | ||||||
|         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> scrollSelectionToMiddle rsList >> redraw ui |         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> scrollSelectionToMiddle rsList >> redraw ui | ||||||
|  |         VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui | ||||||
| 
 | 
 | ||||||
|         -- enter transaction screen for selected transaction |         -- enter transaction screen for selected transaction | ||||||
|         VtyEvent e | e `elem` moveRightEvents -> do |         VtyEvent e | e `elem` moveRightEvents -> do | ||||||
|  | |||||||
| @ -120,6 +120,7 @@ tsHandle ui@UIState{aScreen=s@TransactionScreen{tsTransaction=(i,t) | |||||||
|       case ev of |       case ev of | ||||||
|         VtyEvent (EvKey (KChar 'q') []) -> halt ui |         VtyEvent (EvKey (KChar 'q') []) -> halt ui | ||||||
|         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui |         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui | ||||||
|  |         VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui | ||||||
|         _                    -> helpHandle ui ev |         _                    -> helpHandle ui ev | ||||||
| 
 | 
 | ||||||
|     _ -> do |     _ -> do | ||||||
| @ -180,6 +181,7 @@ tsHandle ui@UIState{aScreen=s@TransactionScreen{tsTransaction=(i,t) | |||||||
|             ui'@UIState{aScreen=scr} = popScreen ui |             ui'@UIState{aScreen=scr} = popScreen ui | ||||||
|             ui'' = ui'{aScreen=rsSelect (fromIntegral i) scr} |             ui'' = ui'{aScreen=rsSelect (fromIntegral i) scr} | ||||||
|         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui |         VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui | ||||||
|  |         VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspendAndRedraw ui | ||||||
|         _ -> continue ui |         _ -> continue ui | ||||||
| 
 | 
 | ||||||
| tsHandle _ _ = error "event handler called with wrong screen type, should not happen" | tsHandle _ _ = error "event handler called with wrong screen type, should not happen" | ||||||
|  | |||||||
| @ -21,6 +21,8 @@ module Hledger.UI.UIUtils ( | |||||||
|   ,renderToggle |   ,renderToggle | ||||||
|   ,replaceHiddenAccountsNameWith |   ,replaceHiddenAccountsNameWith | ||||||
|   ,scrollSelectionToMiddle |   ,scrollSelectionToMiddle | ||||||
|  |   ,suspend | ||||||
|  |   ,suspendAndRedraw | ||||||
|   ,redraw |   ,redraw | ||||||
| ) | ) | ||||||
| where | where | ||||||
| @ -50,6 +52,35 @@ import Hledger.Cli.DocFiles | |||||||
| import Hledger.UI.UITypes | import Hledger.UI.UITypes | ||||||
| import Hledger.UI.UIState | 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. | -- | Tell vty to redraw the whole screen, and continue. | ||||||
| redraw :: s -> EventM a (Next s) | redraw :: s -> EventM a (Next s) | ||||||
| @ -74,7 +105,7 @@ helpDialog _copts = | |||||||
|     render $ |     render $ | ||||||
|       withDefAttr "help" $ |       withDefAttr "help" $ | ||||||
|       renderDialog (dialog (Just "Help (?/LEFT/ESC to close)") Nothing (c^.availWidthL)) $ -- (Just (0,[("ok",())])) |       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 [ |         vBox [ | ||||||
|            hBox [ |            hBox [ | ||||||
|               padRight (Pad 1) $ |               padRight (Pad 1) $ | ||||||
| @ -120,8 +151,9 @@ helpDialog _copts = | |||||||
|                   ,renderKey ("A   ", "add transaction (hledger-iadd)") |                   ,renderKey ("A   ", "add transaction (hledger-iadd)") | ||||||
|                   ,renderKey ("E   ", "open editor") |                   ,renderKey ("E   ", "open editor") | ||||||
|                   ,renderKey ("I   ", "toggle balance assertions") |                   ,renderKey ("I   ", "toggle balance assertions") | ||||||
|                   ,renderKey ("C-l ", "redraw & recenter") |  | ||||||
|                   ,renderKey ("g   ", "reload data") |                   ,renderKey ("g   ", "reload data") | ||||||
|  |                   ,renderKey ("C-l ", "redraw & recenter") | ||||||
|  |                   ,renderKey ("C-z ", "suspend") | ||||||
|                   ,renderKey ("q   ", "quit") |                   ,renderKey ("q   ", "quit") | ||||||
|                 ] |                 ] | ||||||
|              ] |              ] | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ cabal-version: 1.12 | |||||||
| -- | -- | ||||||
| -- see: https://github.com/sol/hpack | -- see: https://github.com/sol/hpack | ||||||
| -- | -- | ||||||
| -- hash: 9e7f4d999a8b69e7adb4b03f99c96b7ae47113f1b11fe7ddb289e352b2632e7c | -- hash: cb5960060c369ce0540af1659e44ad678d26cbc9dca2e8481fe8657bc8fc13ab | ||||||
| 
 | 
 | ||||||
| name:           hledger-ui | name:           hledger-ui | ||||||
| version:        1.12.99 | version:        1.12.99 | ||||||
| @ -95,6 +95,7 @@ executable hledger-ui | |||||||
|   else |   else | ||||||
|     build-depends: |     build-depends: | ||||||
|         brick >=0.12 |         brick >=0.12 | ||||||
|  |       , unix | ||||||
|       , vty >=5.5 |       , vty >=5.5 | ||||||
|   if flag(threaded) |   if flag(threaded) | ||||||
|     ghc-options: -threaded |     ghc-options: -threaded | ||||||
|  | |||||||
| @ -82,6 +82,7 @@ when: | |||||||
|    else: |    else: | ||||||
|      dependencies: |      dependencies: | ||||||
|        - brick >=0.12 |        - brick >=0.12 | ||||||
|  |        - unix | ||||||
|        - vty >=5.5 |        - vty >=5.5 | ||||||
| 
 | 
 | ||||||
| executables: | executables: | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user