packages feed

yi-0.4: Yi/Mode/Shim.hs

{-# LANGUAGE DeriveDataTypeable #-}

module Yi.Mode.Shim where
    
import Data.List
import Yi
import Shim.Hsinfo as Hsinfo
import Yi.Buffer
import Yi.Modes
import Control.Monad.State

import qualified Shim.Hsinfo as Hsinfo

import SrcLoc
import FastString

import Control.Monad.State
import Yi.WindowSet as Robin
import Outputable hiding (char)
import Yi.Accessor
import Yi.Prelude
import Prelude ()
import Data.Char
import Yi.GHC
import qualified Yi.Lexer.Alex
import Yi.Syntax
import Yi.Syntax.Linear as Linear
import Yi.Lexer.Haskell

modeTable :: ReaderT String Maybe AnyMode
modeTable = ReaderT $ \fname -> case () of 
                        _ | ".hs" `isSuffixOf` fname -> Just (AnyMode mode)
                        _ ->  Nothing

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
    modifyA notesA (fmap forward)
    getsA notesA (fmap current)
  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 $ do
      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.
mode :: Mode (Linear.Result (Yi.Lexer.Alex.Tok Token))
mode = haskellMode
   {
    modeKeymap = (<||) 
      (((ctrl $ char 'c') ?>> choice
        [ctrl (char 't') ?>>! typeAtPos,
         char '!' ?>> char 't' ?>>! annotType,
         char '!' ?>> char '=' ?>>! annotType,
         ctrl (char 'd') ?>>! jumpToDefinition,
         ctrl (char 'l') ?>>! do
             withEditor $ do
                 withOtherWindow $ do
                     switchToBufferWithNameE "*messages*"
             msgEditor "Loading..."
             Just filename <- withBuffer $ gets file
             runShimThread (Hsinfo.load filename True Nothing >> return ())
             return ()
         ]
       ) <|> (ctrl (char 'x') ?>> char '`' ?>>! jumpToNextNote))
   }