    {-# 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 a b. YiM a -> (a -> YiM b) -> YiM b
    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
    $cdef :: HelpBuffer
    def :: 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
    $cput :: HelpBuffer -> Put
    put :: HelpBuffer -> Put
    $cget :: Get HelpBuffer
    get :: Get HelpBuffer
    $cputList :: [HelpBuffer] -> Put
    putList :: [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 a. EditorM a -> YiM a
    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
       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
       putEditorDyn $ HelpBuffer $ Just b