packages feed

zwirn-0.2.3.1: app/zwirnmill/Editor/Popup.hs

module Editor.Popup where

import Brick (Viewport (..), get, modify)
import Brick.Main (lookupViewport)
import Brick.Types (EventM)
import Control.Monad.RWS (MonadIO (..))
import qualified Data.Text as T
import Editor.Core
import Editor.Diagnostic
import Editor.Util
import Lens.Micro
import UI.Core (EditorEventEnv (..), Name (..), envEditorState)
import Zwirn.Language.Compiler (CIError, Environment, runCI)
import Zwirn.Language.LSP.Hover (parseAndGetInfoAt)
import Zwirn.Language.Location (Position (..), RealSrcLoc (..))

hintEvent :: EventM Name EditorEventEnv ()
hintEvent = do
  let fromName (Editor i) = EditorViewport i
      fromName x = x
  (EditorEventEnv _ name _ _ env es) <- get
  off <- maybe (0, 0) (\(VP l r _ _) -> (l, r)) <$> lookupViewport (fromName name)
  es' <- liftIO $ getPopup es env off
  modify $ envEditorState .~ es'
  return ()

getPopupInfo :: EditorState -> Environment -> IO (Either CIError (Maybe (T.Text, RealSrcLoc)))
getPopupInfo es env = runCI env (parseAndGetInfoAt False content (Position r (c + 1)))
  where
    content = getContent es
    (r, c) = currentCursor es

getPopup :: EditorState -> Environment -> (Int, Int) -> IO EditorState
getPopup es env (left, ro) = do
  res <- getPopupInfo es env
  ds <- getDiagnostics es env

  let cursor = currentCursor es
      mdiag = getAnyDiagnostic cursor $ rowDiagnostics (fst $ currentCursor es) ds
      mpopup = case mdiag of
        Just (Diagnostic (pos, _) diag) -> Just (diag, pos)
        Nothing -> case res of
          Right (Just (info, pos)) -> Just (T.unpack info, (rStartLine pos, rStartChar pos))
          _ -> Nothing

  case mpopup of
    (Just (cont, pos)) -> return $ es & esPopup ?~ Popup cont (screenCol, popupRow) -- {esPopup = Just $ Popup cont (screenCol, popupRow)}
      where
        infoWidth = length $ lines cont
        -- visRow = esScrollRow es
        screenCol = snd pos + lineNumberWidth es - left
        row = fst pos - ro
        popupRow = if row - (infoWidth + 2) < 0 then row + 1 else row - (infoWidth + 2)
    _ -> return $ clearPopup es