From 7597b7cb0f1f9552cfce515b7c9a9c590b17d015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ondr=CC=8Cej=20S=CC=8Cebek?= Date: Thu, 1 Aug 2024 00:10:42 +0200 Subject: [PATCH] POC: Multiline REPL --- src/swarm-tui/Swarm/TUI/Controller.hs | 9 +++++++-- src/swarm-tui/Swarm/TUI/Model/Repl.hs | 4 ++-- src/swarm-tui/Swarm/TUI/View.hs | 22 +++++++++++++++++++--- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/swarm-tui/Swarm/TUI/Controller.hs b/src/swarm-tui/Swarm/TUI/Controller.hs index ce10116bbd..a9b55805ce 100644 --- a/src/swarm-tui/Swarm/TUI/Controller.hs +++ b/src/swarm-tui/Swarm/TUI/Controller.hs @@ -569,6 +569,9 @@ handleREPLEventTyping = \case -- On any other key event, jump to the bottom of the REPL then handle the event vScrollToEnd replScroll case k of + MetaChar 'm' -> + Brick.zoom (uiState . uiGameplay . uiREPL . replPromptEditor) $ + handleEditorEvent (Key V.KEnter) Key V.KEnter -> do s <- get let theRepl = s ^. uiState . uiGameplay . uiREPL @@ -741,8 +744,8 @@ validateREPLForm s = let env = s ^. gameState . baseEnv (theType, errSrcLoc) = case readTerm' defaultParserConfig uinput of Left err -> - let ((_y1, x1), (_y2, x2), _msg) = showErrorPos err - in (Nothing, Left (SrcLoc x1 x2)) + let ((y1, x1), (y2, x2), _msg) = showErrorPos err + in (Nothing, Left (SrcLoc (y2x y1 + x1) (y2x y2 + x2))) Right Nothing -> (Nothing, Right ()) Right (Just theTerm) -> case processParsedTerm' env theTerm of Right t -> (Just (t ^. sType), Right ()) @@ -754,6 +757,8 @@ validateREPLForm s = where uinput = s ^. uiState . uiGameplay . uiREPL . replPromptText replPrompt = s ^. uiState . uiGameplay . uiREPL . replPromptType + uLineCounts = T.length <$> T.lines uinput + y2x n = n + sum (take n uLineCounts) -- | Update our current position in the REPL history. adjReplHistIndex :: TimeDir -> AppState -> AppState diff --git a/src/swarm-tui/Swarm/TUI/Model/Repl.hs b/src/swarm-tui/Swarm/TUI/Model/Repl.hs index 1673194f0d..4a175d3be3 100644 --- a/src/swarm-tui/Swarm/TUI/Model/Repl.hs +++ b/src/swarm-tui/Swarm/TUI/Model/Repl.hs @@ -329,7 +329,7 @@ data REPLState = REPLState } newREPLEditor :: Text -> Editor Text Name -newREPLEditor t = applyEdit gotoEnd $ editorText REPLInput (Just 1) t +newREPLEditor t = applyEdit gotoEnd $ editorText REPLInput (Just 5) t where ls = T.lines t pos = (length ls - 1, T.length (last ls)) @@ -360,7 +360,7 @@ replPromptEditor :: Lens' REPLState (Editor Text Name) replPromptText :: Lens' REPLState Text replPromptText = lens g s where - g r = r ^. replPromptEditor . to getEditContents . to T.concat + g r = r ^. replPromptEditor . to getEditContents . to T.unlines s r t = r & replPromptEditor .~ newREPLEditor t -- | Whether the prompt text is a valid 'Swarm.Language.Syntax.Term'. diff --git a/src/swarm-tui/Swarm/TUI/View.hs b/src/swarm-tui/Swarm/TUI/View.hs index 775c088724..6118456700 100644 --- a/src/swarm-tui/Swarm/TUI/View.hs +++ b/src/swarm-tui/Swarm/TUI/View.hs @@ -1425,7 +1425,8 @@ drawRecipe me inv (Recipe ins outs reqs time _weight) = hBox [ padRight (Pad 1) $ str (show n) -- how many? , fmtEntityName missing ingr -- name of the input - , padLeft (Pad 1) $ -- a connecting line: ─────┬ + , padLeft (Pad 1) $ -- a connecting line: ─────┬ -- a connecting line: ─────┬ + -- a connecting line: ─────┬ hBorder <+> ( joinableBorder (Edges (i /= 0) (i /= inLen - 1) True False) -- ...maybe plus vert ext: │ <=> if i /= inLen - 1 @@ -1568,13 +1569,28 @@ renderREPLPrompt focus theRepl = ps1 <+> replE Right () -> txt t Left NoLoc -> withAttr redAttr (txt t) Left (SrcLoc s e) | s == e || s >= T.length t -> withAttr redAttr (txt t) + -- TODO: ABSOLUTE HELL OF BUGS, NEEDS LINE NUMBERS Left (SrcLoc s e) -> let (validL, (invalid, validR)) = T.splitAt (e - s) <$> T.splitAt s t - in hBox [txt validL, withAttr redAttr (txt invalid), txt validR] + (validLs, validLl) = fromMaybe ([], validL) . unsnoc $ T.splitOn "\n" validL + (validRl, validRs) = fromMaybe (validR, []) . uncons $ T.splitOn "\n" validR + redLines = case T.lines invalid of + [] -> [withAttr redAttr $ txt validLl <+> txt validRl] -- should not happen + [i1] -> [txt validLl <+> withAttr redAttr (txt i1) <+> txt validRl] + [i1, i2] -> + [ txt validLl <+> withAttr redAttr (txt i1) + , withAttr redAttr (txt i2) <+> txt validRl + ] + (i1 : iss) -> + [ txt validLl <+> withAttr redAttr (txt i1) + , withAttr redAttr (txt . T.unlines $ init iss) + , withAttr redAttr (txt $ last iss) <+> txt validRl + ] + in vBox $ map txt validLs <> redLines <> map txt validRs ps1 = replPromptAsWidget (T.concat $ getEditContents replEditor) prompt replE = renderEditor - (vBox . map color) + (color . T.unlines) (focusGetCurrent focus `elem` [Nothing, Just (FocusablePanel REPLPanel), Just REPLInput]) replEditor