imp: ui: Display an error message on invalid regexp, rather than

silently ignoring. (#1394)
This commit is contained in:
Stephen Morgan 2021-11-16 12:22:05 +11:00 committed by Simon Michael
parent e0dc028374
commit 59b4968929
5 changed files with 34 additions and 27 deletions

View File

@ -180,7 +180,7 @@ asDraw UIState{aopts=_uopts@UIOpts{uoCliOpts=copts@CliOpts{reportspec_=rspec}}
nonblanks = V.takeWhile (not . T.null . asItemAccountName) $ s ^. asList . listElementsL nonblanks = V.takeWhile (not . T.null . asItemAccountName) $ s ^. asList . listElementsL
bottomlabel = case mode of bottomlabel = case mode of
Minibuffer ed -> minibuffer ed Minibuffer label ed -> minibuffer label ed
_ -> quickhelp _ -> quickhelp
where where
quickhelp = borderKeysStr' [ quickhelp = borderKeysStr' [
@ -242,15 +242,18 @@ asHandle ui0@UIState{
ui = ui0{aScreen=scr & asSelectedAccount .~ selacct} ui = ui0{aScreen=scr & asSelectedAccount .~ selacct}
case mode of case mode of
Minibuffer ed -> Minibuffer _ ed ->
case ev of case ev of
VtyEvent (EvKey KEsc []) -> continue $ closeMinibuffer ui VtyEvent (EvKey KEsc []) -> continue $ closeMinibuffer ui
VtyEvent (EvKey KEnter []) -> continue $ regenerateScreens j d $ setFilter s $ closeMinibuffer ui VtyEvent (EvKey KEnter []) -> continue $ regenerateScreens j d $
case setFilter s $ closeMinibuffer ui of
Left bad -> showMinibuffer "Cannot compile regular expression" (Just bad) ui
Right ui' -> 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]) -> suspend ui VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspend ui
VtyEvent ev -> do ed' <- handleEditorEvent ev ed VtyEvent ev -> do ed' <- handleEditorEvent ev ed
continue $ ui{aMode=Minibuffer ed'} continue $ ui{aMode=Minibuffer "filter" ed'}
AppEvent _ -> continue ui AppEvent _ -> continue ui
MouseDown{} -> continue ui MouseDown{} -> continue ui
MouseUp{} -> continue ui MouseUp{} -> continue ui
@ -311,7 +314,7 @@ asHandle ui0@UIState{
VtyEvent (EvKey (KUp) [MShift]) -> continue $ regenerateScreens j d $ growReportPeriod d ui VtyEvent (EvKey (KUp) [MShift]) -> continue $ regenerateScreens j d $ growReportPeriod d ui
VtyEvent (EvKey (KRight) [MShift]) -> continue $ regenerateScreens j d $ nextReportPeriod journalspan ui VtyEvent (EvKey (KRight) [MShift]) -> continue $ regenerateScreens j d $ nextReportPeriod journalspan ui
VtyEvent (EvKey (KLeft) [MShift]) -> continue $ regenerateScreens j d $ previousReportPeriod journalspan ui VtyEvent (EvKey (KLeft) [MShift]) -> continue $ regenerateScreens j d $ previousReportPeriod journalspan ui
VtyEvent (EvKey (KChar '/') []) -> continue $ regenerateScreens j d $ showMinibuffer ui VtyEvent (EvKey (KChar '/') []) -> continue $ regenerateScreens j d $ showMinibuffer "filter" Nothing ui
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

View File

@ -227,7 +227,7 @@ rsDraw UIState{aopts=_uopts@UIOpts{uoCliOpts=copts@CliOpts{reportspec_=rspec}}
-- query = query_ $ reportopts_ $ cliopts_ opts -- query = query_ $ reportopts_ $ cliopts_ opts
bottomlabel = case mode of bottomlabel = case mode of
Minibuffer ed -> minibuffer ed Minibuffer label ed -> minibuffer label ed
_ -> quickhelp _ -> quickhelp
where where
quickhelp = borderKeysStr' [ quickhelp = borderKeysStr' [
@ -288,15 +288,19 @@ rsHandle ui@UIState{
lastnonblankidx = max 0 (length nonblanks - 1) lastnonblankidx = max 0 (length nonblanks - 1)
case mode of case mode of
Minibuffer ed -> Minibuffer _ ed ->
case ev of case ev of
VtyEvent (EvKey KEsc []) -> continue $ closeMinibuffer ui VtyEvent (EvKey KEsc []) -> continue $ closeMinibuffer ui
VtyEvent (EvKey KEnter []) -> continue $ regenerateScreens j d $ setFilter s $ closeMinibuffer ui VtyEvent (EvKey KEnter []) -> continue $ regenerateScreens j d $
where s = chomp $ unlines $ map strip $ getEditContents ed case setFilter s $ closeMinibuffer ui of
Left bad -> showMinibuffer "Cannot compile regular expression" (Just bad) ui
Right ui' -> ui'
where s = chomp . unlines . map strip $ getEditContents ed
-- VtyEvent (EvKey (KChar '/') []) -> continue $ regenerateScreens j d $ showMinibuffer ui
VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw ui
VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspend ui VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspend ui
VtyEvent ev -> do ed' <- handleEditorEvent ev ed VtyEvent ev -> do ed' <- handleEditorEvent ev ed
continue $ ui{aMode=Minibuffer ed'} continue $ ui{aMode=Minibuffer "filter" ed'}
AppEvent _ -> continue ui AppEvent _ -> continue ui
MouseDown{} -> continue ui MouseDown{} -> continue ui
MouseUp{} -> continue ui MouseUp{} -> continue ui
@ -342,7 +346,7 @@ rsHandle ui@UIState{
VtyEvent (EvKey (KChar 'C') []) -> rsCenterAndContinue $ regenerateScreens j d $ toggleCleared ui VtyEvent (EvKey (KChar 'C') []) -> rsCenterAndContinue $ regenerateScreens j d $ toggleCleared ui
VtyEvent (EvKey (KChar 'F') []) -> rsCenterAndContinue $ regenerateScreens j d $ toggleForecast d ui VtyEvent (EvKey (KChar 'F') []) -> rsCenterAndContinue $ regenerateScreens j d $ toggleForecast d ui
VtyEvent (EvKey (KChar '/') []) -> continue $ regenerateScreens j d $ showMinibuffer ui VtyEvent (EvKey (KChar '/') []) -> continue $ regenerateScreens j d $ showMinibuffer "filter" Nothing ui
VtyEvent (EvKey (KDown) [MShift]) -> continue $ regenerateScreens j d $ shrinkReportPeriod d ui VtyEvent (EvKey (KDown) [MShift]) -> continue $ regenerateScreens j d $ shrinkReportPeriod d ui
VtyEvent (EvKey (KUp) [MShift]) -> continue $ regenerateScreens j d $ growReportPeriod d ui VtyEvent (EvKey (KUp) [MShift]) -> continue $ regenerateScreens j d $ growReportPeriod d ui
VtyEvent (EvKey (KRight) [MShift]) -> continue $ regenerateScreens j d $ nextReportPeriod journalspan ui VtyEvent (EvKey (KRight) [MShift]) -> continue $ regenerateScreens j d $ nextReportPeriod journalspan ui

View File

@ -7,9 +7,11 @@ module Hledger.UI.UIState
where where
import Brick.Widgets.Edit import Brick.Widgets.Edit
import Data.Bifunctor (first)
import Data.Foldable (asum) import Data.Foldable (asum)
import Data.Either (fromRight) import Data.Either (fromRight)
import Data.List ((\\), foldl', sort) import Data.List ((\\), foldl', sort)
import Data.Maybe (fromMaybe)
import Data.Semigroup (Max(..)) import Data.Semigroup (Max(..))
import qualified Data.Text as T import qualified Data.Text as T
import Data.Text.Zipper (gotoEOL) import Data.Text.Zipper (gotoEOL)
@ -205,11 +207,9 @@ updateReportPeriod :: (Period -> Period) -> UIState -> UIState
updateReportPeriod updatePeriod = fromRight err . overEither period updatePeriod -- PARTIAL: updateReportPeriod updatePeriod = fromRight err . overEither period updatePeriod -- PARTIAL:
where err = error "updateReportPeriod: updating period should not result in an error" where err = error "updateReportPeriod: updating period should not result in an error"
-- | Apply a new filter query. -- | Apply a new filter query, or return the failing query.
setFilter :: String -> UIState -> UIState setFilter :: String -> UIState -> Either String UIState
setFilter s = over reportSpec update setFilter s = first (const s) . setEither querystring (words'' prefixes $ T.pack s)
where
update rspec = fromRight rspec $ setEither querystring (words'' prefixes $ T.pack s) rspec -- XXX silently ignores an error
-- | Reset some filters & toggles. -- | Reset some filters & toggles.
resetFilter :: UIState -> UIState resetFilter :: UIState -> UIState
@ -264,11 +264,11 @@ updateReportDepth updateDepth ui = over reportSpec update ui
| otherwise = Just d | otherwise = Just d
-- | Open the minibuffer, setting its content to the current query with the cursor at the end. -- | Open the minibuffer, setting its content to the current query with the cursor at the end.
showMinibuffer :: UIState -> UIState showMinibuffer :: T.Text -> Maybe String -> UIState -> UIState
showMinibuffer ui = setMode (Minibuffer e) ui showMinibuffer label moldq ui = setMode (Minibuffer label e) ui
where where
e = applyEdit gotoEOL $ editor MinibufferEditor (Just 1) oldq e = applyEdit gotoEOL $ editor MinibufferEditor (Just 1) oldq
oldq = T.unpack . T.unwords . map textQuoteIfNeeded $ ui^.querystring oldq = fromMaybe (T.unpack . T.unwords . map textQuoteIfNeeded $ ui^.querystring) moldq
-- | Close the minibuffer, discarding any edit in progress. -- | Close the minibuffer, discarding any edit in progress.
closeMinibuffer :: UIState -> UIState closeMinibuffer :: UIState -> UIState

View File

@ -69,7 +69,7 @@ data UIState = UIState {
data Mode = data Mode =
Normal Normal
| Help | Help
| Minibuffer (Editor String Name) | Minibuffer Text (Editor String Name)
deriving (Show,Eq) deriving (Show,Eq)
-- Ignore the editor when comparing Modes. -- Ignore the editor when comparing Modes.

View File

@ -176,11 +176,11 @@ helpHandle ui ev = do
ui' = setMode Normal ui ui' = setMode Normal ui
closeHelpEvents = moveLeftEvents ++ [EvKey KEsc [], EvKey (KChar '?') [], EvKey (KChar 'q') []] closeHelpEvents = moveLeftEvents ++ [EvKey KEsc [], EvKey (KChar '?') [], EvKey (KChar 'q') []]
-- | Draw the minibuffer. -- | Draw the minibuffer with the given label.
minibuffer :: Editor String Name -> Widget Name minibuffer :: T.Text -> Editor String Name -> Widget Name
minibuffer ed = minibuffer string ed =
forceAttr ("border" <> "minibuffer") $ forceAttr ("border" <> "minibuffer") $
hBox [txt "filter: ", renderEditor (str . unlines) True ed] hBox [txt $ string <> ": ", renderEditor (str . unlines) True ed]
borderQueryStr :: String -> Widget Name borderQueryStr :: String -> Widget Name
borderQueryStr "" = str "" borderQueryStr "" = str ""