packages feed

yi-0.8.0: src/library/Yi/Mode/Shim.hs

module Yi.Mode.Shim where

import Control.Monad.State
import Data.Char
import Data.List
import qualified Data.List.PointedList.Circular as PL
import FastString
import Outputable hiding (char)

import Shim.Hsinfo as Hsinfo
import SrcLoc
import Yi
import Yi.Buffer
import Yi.GHC

import qualified Shim.Hsinfo as Hsinfo

jumpToSrcLoc :: SrcLoc -> YiM ()
jumpToSrcLoc locn =
    if isGoodSrcLoc locn
       then jumpToE (unpackFS $ srcLocFile locn) (srcLocLine locn) (srcLocCol locn)
       else msgEditor $ show (ppr locn defaultUserStyle)

jumpToNextNote :: YiM ()
jumpToNextNote = do
  note <- withEditor $ do
    (%=) notesA (fmap PL.next)
    uses notesA (fmap PL.focus)
  case note of
    Nothing -> msgEditor "No note!"
    Just n -> jumpToSrcLoc $ srcSpanStart $ srcSpan n

-- | Position of the cursor
cursorPos :: BufferM (Maybe String, Int, Int)
cursorPos = (,,) <$> gets file <*> curLn <*> curCol

-- | Type of the symbol at current position
typeAtPos :: YiM String
typeAtPos = do
  (Just filename,line,col) <- withBuffer cursorPos
  withShim $ Hsinfo.findTypeOfPos filename line col Nothing

-- | Annotate the current function with its type
annotType :: YiM ()
annotType = do
  t <- typeAtPos
  withBuffer $ do
     moveToSol
     insertN $ t ++ "\n"

-- | Update a line of the form "-- expr = value" with the new value of expr
annotValue :: YiM ()
annotValue = do
  lnReg <- withBuffer $ regionOfB Yi.Line
  Just sourcefile <- withBuffer $ gets file
  ln <- withBuffer $ readRegionB lnReg
  let lhs = takeWhile (/= '=') $ dropWhile (== '-') $ dropWhile isSpace ln
  newVal <- withShim $ do
               ses <- getSessionFor sourcefile
               evaluate ses lhs
  withBuffer $ replaceRegionB lnReg ("--" ++ lhs ++ "= " ++ newVal)

jumpToDefinition :: YiM ()
jumpToDefinition = do
  (Just filename,line,col) <- withBuffer cursorPos
  locn <- withShim $ Hsinfo.findDefinition filename line col Nothing
  jumpToSrcLoc locn

-- NOTE: source argument to Hsinfo functions can be used to provide
-- source text, apparently.
minorMode :: Mode syntax -> Mode syntax
minorMode m = m
   {
    modeName = modeName m ++ "+shim",
    modeKeymap = modeKeymap m . (<||)
      ((ctrl (char 'c') ?>> choice
       [ctrl (char 't') ?>>! typeAtPos,
        char '!' ?>> char 't' ?>>! annotType,
        char '!' ?>> char '=' ?>>! annotType,
        ctrl (char 'd') ?>>! jumpToDefinition,
        ctrl (char 'l') ?>>! do
            withEditor $ withOtherWindow $ switchToBufferWithNameE "*messages*"
            msgEditor "Loading..."
            Just filename <- withBuffer $ gets file
            runShimThread $ void (Hsinfo.load filename True Nothing)
            return ()
         ]
       ) <|> (ctrl (char 'x') ?>> char '`' ?>>! jumpToNextNote))
   }