packages feed

ribosome-0.4.0.0: lib/Ribosome/Menu/Nvim.hs

module Ribosome.Menu.Nvim where

import Control.Lens (view)
import qualified Data.Map as Map (fromList)
import qualified Data.Text as Text (cons, snoc)

import Ribosome.Api.Window (redraw, setLine)
import Ribosome.Control.Monad.Ribo (MonadRibo, NvimE)
import Ribosome.Data.List (mapSelectors)
import Ribosome.Data.Scratch (Scratch(scratchWindow))
import Ribosome.Data.ScratchOptions (ScratchOptions)
import Ribosome.Data.Syntax (
  HiLink(..),
  Syntax(Syntax),
  SyntaxItem(..),
  syntaxMatch,
  )
import Ribosome.Log (logDebug)
import qualified Ribosome.Menu.Data.FilteredMenuItem as FilteredMenuItem (item)
import Ribosome.Menu.Data.Menu (Menu(Menu))
import qualified Ribosome.Menu.Data.MenuItem as MenuItem (abbreviated)
import Ribosome.Menu.Data.MenuRenderEvent (MenuRenderEvent)
import qualified Ribosome.Menu.Data.MenuRenderEvent as MenuRenderEvent (MenuRenderEvent(..))
import Ribosome.Scratch (killScratch, setScratchContent)

marker :: Char
marker =
  '†'

markerConceal :: SyntaxItem
markerConceal =
  item { siOptions = options, siParams = params }
  where
    item = syntaxMatch "RibosomeMenuMarker" (Text.snoc "^" marker)
    options = ["conceal"]
    params = Map.fromList [("nextgroup", "RibosomeMenuMarkedLine")]

markedLine :: SyntaxItem
markedLine =
  item { siOptions = options }
  where
    item = syntaxMatch "RibosomeMenuMarkedLine" ".*$"
    options = ["contained"]

hlMarkedLine :: HiLink
hlMarkedLine =
  HiLink "RibosomeMenuMarkedLine" "Tag"

menuSyntax :: Syntax
menuSyntax =
  Syntax [markerConceal, markedLine] [] [hlMarkedLine]

withMarks :: [Int] -> [Text] -> [Text]
withMarks =
  mapSelectors (Text.cons marker)

renderNvimMenu ::
  MonadRibo m =>
  NvimE e m =>
  ScratchOptions ->
  Scratch ->
  MenuRenderEvent m a i ->
  m ()
renderNvimMenu _ scratch (MenuRenderEvent.Quit _) =
  killScratch scratch
renderNvimMenu options scratch (MenuRenderEvent.Render changed (Menu _ allItems selected marked _ maxItems)) =
  when changed (setScratchContent options scratch (reverse text)) *>
  logDebug @Text logMsg *>
  updateCursor *>
  redraw
  where
    lineNumber =
      max 0 $ length items - selected - 1
    text =
      withMarks marked (view (FilteredMenuItem.item . MenuItem.abbreviated) <$> items)
    items =
      limit allItems
    limit =
      maybe id take maxItems
    updateCursor =
      setLine (scratchWindow scratch) lineNumber
    logMsg =
      "updating menu cursor to line " <> show lineNumber <> "; " <> show selected <> "/" <> show (length items)