{-# LANGUAGE DeriveDataTypeable         #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings          #-}
-- |
-- Module      :  Yi.Command.Help
-- License     :  GPL-2
-- Maintainer  :  yi-devel@googlegroups.com
-- Stability   :  experimental
-- Portability :  portable
--
-- Help command support
-- This module uses Yi.Eval.describeNamedAction to
-- show whatever information about particular action is available
-- from current evaluator (ghciEvaluator currently presents only type.)
-- TODO: Would be nice to show excerpt from Haddock documentation in the future.
--
-- If given no arguments, the help index is shown (using @getAllNamesInScope@).
--
-- Please do not try to show descriptions for the whole index,
-- as our interface to GHCi is too slow.

module Yi.Command.Help(displayHelpFor) where

import           Data.Binary         (Binary)
import           Data.Default        (Default)
import qualified Data.Text           as T (Text, pack, unlines, unpack)
import           Data.Typeable       (Typeable)
import           Yi.Buffer           (BufferId (MemBuffer), BufferRef)
import           Yi.Editor
import           Yi.Eval             (describeNamedAction, getAllNamesInScope)
import           Yi.Keymap           (YiM)
import           Yi.Monad            (maybeM)
import qualified Yi.Rope             as R (fromText)
import           Yi.Types            (YiVariable)


-- | Displays help for a given name, or help index, if no name is given
displayHelpFor :: T.Text -> YiM ()
displayHelpFor :: Text -> YiM ()
displayHelpFor Text
name = Text -> YiM Text
helpFor Text
name YiM Text -> (Text -> YiM ()) -> YiM ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Text -> YiM ()
displayHelpBuffer

-- | Finds help text to display, given a command argument
helpFor :: T.Text -> YiM T.Text
helpFor :: Text -> YiM Text
helpFor Text
""    = ([Text] -> Text
T.unlines ([Text] -> Text) -> ([String] -> [Text]) -> [String] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Text) -> [String] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map String -> Text
T.pack) ([String] -> Text) -> YiM [String] -> YiM Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> YiM [String]
getAllNamesInScope
helpFor Text
name  = String -> Text
T.pack    (String -> Text) -> YiM String -> YiM Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> YiM String
describeNamedAction (Text -> String
T.unpack Text
name)

-- * To make help buffer unique:
-- | Dynamic YiVariable to store the help buffer reference.
newtype HelpBuffer = HelpBuffer { HelpBuffer -> Maybe BufferRef
helpBuffer :: Maybe BufferRef }
    deriving (HelpBuffer
HelpBuffer -> Default HelpBuffer
forall a. a -> Default a
def :: HelpBuffer
$cdef :: HelpBuffer
Default, Typeable, Get HelpBuffer
[HelpBuffer] -> Put
HelpBuffer -> Put
(HelpBuffer -> Put)
-> Get HelpBuffer -> ([HelpBuffer] -> Put) -> Binary HelpBuffer
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [HelpBuffer] -> Put
$cputList :: [HelpBuffer] -> Put
get :: Get HelpBuffer
$cget :: Get HelpBuffer
put :: HelpBuffer -> Put
$cput :: HelpBuffer -> Put
Binary)

instance YiVariable HelpBuffer

-- | Display help buffer with a given text...
displayHelpBuffer :: T.Text -> YiM ()
displayHelpBuffer :: Text -> YiM ()
displayHelpBuffer Text
text = EditorM () -> YiM ()
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor (EditorM () -> YiM ()) -> EditorM () -> YiM ()
forall a b. (a -> b) -> a -> b
$ EditorM () -> EditorM ()
forall (m :: * -> *) a. MonadEditor m => m a -> m a
withOtherWindow (EditorM () -> EditorM ()) -> EditorM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ do
   (BufferRef -> EditorM ()) -> Maybe BufferRef -> EditorM ()
forall (m :: * -> *) x. Monad m => (x -> m ()) -> Maybe x -> m ()
maybeM BufferRef -> EditorM ()
forall (m :: * -> *). MonadEditor m => BufferRef -> m ()
deleteBuffer (Maybe BufferRef -> EditorM ())
-> EditorM (Maybe BufferRef) -> EditorM ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< HelpBuffer -> Maybe BufferRef
helpBuffer (HelpBuffer -> Maybe BufferRef)
-> EditorM HelpBuffer -> EditorM (Maybe BufferRef)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> EditorM HelpBuffer
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
   BufferRef
b <- BufferId -> YiString -> EditorM BufferRef
newBufferE (Text -> BufferId
MemBuffer Text
"*help*") (YiString -> EditorM BufferRef) -> YiString -> EditorM BufferRef
forall a b. (a -> b) -> a -> b
$ Text -> YiString
R.fromText Text
text
   HelpBuffer -> EditorM ()
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Functor m) =>
a -> m ()
putEditorDyn (HelpBuffer -> EditorM ()) -> HelpBuffer -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Maybe BufferRef -> HelpBuffer
HelpBuffer (Maybe BufferRef -> HelpBuffer) -> Maybe BufferRef -> HelpBuffer
forall a b. (a -> b) -> a -> b
$ BufferRef -> Maybe BufferRef
forall a. a -> Maybe a
Just BufferRef
b