    {-# LANGUAGE OverloadedStrings #-}
    {-# OPTIONS_HADDOCK show-extensions #-}

    -- |
    -- Module      :  Yi.Keymap.Vim.Ex.Commands.Tag
    -- License     :  GPL-2
    -- Maintainer  :  yi-devel@googlegroups.com
    -- Stability   :  experimental
    -- Portability :  portable

    module Yi.Keymap.Vim.Ex.Commands.Tag (parse) where

    import           Control.Applicative              (Alternative ((<|>)))
    import           Control.Monad                    (void)
    import qualified Data.Attoparsec.Text             as P (Parser, anyChar, endOfInput,
                                                            many1, option,
                                                            space, string)
    import           Data.Monoid                      ((<>))
    import qualified Data.Text                        as T (pack)
    import           Yi.Keymap                        (Action (YiA))
    import           Yi.Keymap.Vim.Common             (EventString)
    import qualified Yi.Keymap.Vim.Ex.Commands.Common as Common (impureExCommand, parse)
    import           Yi.Keymap.Vim.Ex.Types           (ExCommand (cmdAction, cmdComplete, cmdShow))
    import           Yi.Keymap.Vim.Tag                (completeVimTag, gotoTag, nextTag, unpopTag)
    import           Yi.Tag                           (Tag (Tag))

    parse :: EventString -> Maybe ExCommand
    parse :: EventString -> Maybe ExCommand
    parse = Parser ExCommand -> EventString -> Maybe ExCommand
    Common.parse (Parser ExCommand -> EventString -> Maybe ExCommand)
    -> Parser ExCommand -> EventString -> Maybe ExCommand
    forall a b. (a -> b) -> a -> b
    $ do
        Parser Text Text -> Parser Text ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (Parser Text Text -> Parser Text ())
    -> Parser Text Text -> Parser Text ()
    forall a b. (a -> b) -> a -> b
    $ Text -> Parser Text Text
    P.string Text
    "t"
        Parser ExCommand
    parseTag Parser ExCommand -> Parser ExCommand -> Parser ExCommand
    forall a. Parser Text a -> Parser Text a -> Parser Text a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> Parser ExCommand
    parseNext

    parseTag :: P.Parser ExCommand
    parseTag :: Parser ExCommand
    parseTag = do
      Parser Text Text -> Parser Text ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (Parser Text Text -> Parser Text ())
    -> Parser Text Text -> Parser Text ()
    forall a b. (a -> b) -> a -> b
    $ Text -> Parser Text Text
    P.string Text
    "a"
      Parser Text (Maybe Text) -> Parser Text ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (Parser Text (Maybe Text) -> Parser Text ())
    -> (Parser Text (Maybe Text) -> Parser Text (Maybe Text))
    -> Parser Text (Maybe Text)
    -> Parser Text ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Maybe Text -> Parser Text (Maybe Text) -> Parser Text (Maybe Text)
    forall (f :: * -> *) a. Alternative f => a -> f a -> f a
    P.option Maybe Text
    forall a. Maybe a
    Nothing (Parser Text (Maybe Text) -> Parser Text ())
    -> Parser Text (Maybe Text) -> Parser Text ()
    forall a b. (a -> b) -> a -> b
    $ Text -> Maybe Text
    forall a. a -> Maybe a
    Just (Text -> Maybe Text)
    -> Parser Text Text -> Parser Text (Maybe Text)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Text -> Parser Text Text
    P.string Text
    "g"
      t <- Maybe String
    -> Parser Text (Maybe String) -> Parser Text (Maybe String)
    forall (f :: * -> *) a. Alternative f => a -> f a -> f a
    P.option Maybe String
    forall a. Maybe a
    Nothing (Parser Text (Maybe String) -> Parser Text (Maybe String))
    -> Parser Text (Maybe String) -> Parser Text (Maybe String)
    forall a b. (a -> b) -> a -> b
    $ String -> Maybe String
    forall a. a -> Maybe a
    Just (String -> Maybe String)
    -> Parser Text String -> Parser Text (Maybe String)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> do
          Parser Text String -> Parser Text ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (Parser Text String -> Parser Text ())
    -> Parser Text String -> Parser Text ()
    forall a b. (a -> b) -> a -> b
    $ Parser Text Char -> Parser Text String
    forall (f :: * -> *) a. Alternative f => f a -> f [a]
    P.many1 Parser Text Char
    P.space
          Parser Text Char -> Parser Text String
    forall (f :: * -> *) a. Alternative f => f a -> f [a]
    P.many1 Parser Text Char
    P.anyChar
      case t of
        Maybe String
    Nothing -> Parser Text ()
    forall t. Chunk t => Parser t ()
    P.endOfInput Parser Text () -> Parser ExCommand -> Parser ExCommand
    forall a b. Parser Text a -> Parser Text b -> Parser Text b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> ExCommand -> Parser ExCommand
    forall a. a -> Parser Text a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe Tag -> ExCommand
    tag Maybe Tag
    forall a. Maybe a
    Nothing)
        Just String
    t' -> ExCommand -> Parser ExCommand
    forall a. a -> Parser Text a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ExCommand -> Parser ExCommand) -> ExCommand -> Parser ExCommand
    forall a b. (a -> b) -> a -> b
    $! Maybe Tag -> ExCommand
    tag (Tag -> Maybe Tag
    forall a. a -> Maybe a
    Just (Text -> Tag
    Tag (String -> Text
    T.pack String
    t')))

    parseNext :: P.Parser ExCommand
    parseNext :: Parser ExCommand
    parseNext = do
      Parser Text Text -> Parser Text ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (Parser Text Text -> Parser Text ())
    -> Parser Text Text -> Parser Text ()
    forall a b. (a -> b) -> a -> b
    $ Text -> Parser Text Text
    P.string Text
    "next"
      ExCommand -> Parser ExCommand
    forall a. a -> Parser Text a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ExCommand
    next

    tag :: Maybe Tag -> ExCommand
    tag :: Maybe Tag -> ExCommand
    tag Maybe Tag
    Nothing = ExCommand
    Common.impureExCommand {
        cmdShow = "tag"
      , cmdAction = YiA unpopTag
      , cmdComplete = return ["tag"]
      }
    tag (Just (Tag Text
    t)) = ExCommand
    Common.impureExCommand {
        cmdShow = "tag " <> t
      , cmdAction = YiA $ gotoTag (Tag t) 0 Nothing
      , cmdComplete = map ("tag " <>) <$> completeVimTag t
      }

    next :: ExCommand
    next :: ExCommand
    next = ExCommand
    Common.impureExCommand {
        cmdShow = "tnext"
      , cmdAction = YiA nextTag
      , cmdComplete = return ["tnext"]
      }