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

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

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

    import           Control.Applicative              (Alternative ((<|>)))
    import           Control.Monad                    (void, when)
    import qualified Data.Attoparsec.Text             as P (anyChar, many', many1, space, string, try)
    import           Data.Monoid                      ((<>))
    import qualified Data.Text                        as T (Text, pack)
    import           Yi.Buffer                        (BufferRef)
    import           Yi.Editor                        (printMsg)
    import           Yi.File                          (fwriteBufferE, viWrite, viWriteTo)
    import           Yi.Keymap                        (Action (YiA), YiM)
    import           Yi.Keymap.Vim.Common             (EventString)
    import qualified Yi.Keymap.Vim.Ex.Commands.Common as Common (forAllBuffers, impureExCommand, needsSaving, parse)
    import           Yi.Keymap.Vim.Ex.Types           (ExCommand (cmdAction, cmdShow))

    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
    $
                   (Parser Text Text -> Parser Text Text
    forall i a. Parser i a -> Parser i a
    P.try (Text -> Parser Text Text
    P.string Text
    "write") Parser Text Text -> Parser Text Text -> Parser Text Text
    forall a. Parser Text a -> Parser Text a -> Parser Text a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> Text -> Parser Text Text
    P.string Text
    "w")
                Parser Text Text -> Parser ExCommand -> Parser ExCommand
    forall a b. Parser Text a -> Parser Text b -> Parser Text b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> (Parser ExCommand
    parseWriteAs 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
    parseWrite)
        where parseWrite :: Parser ExCommand
    parseWrite = do
                alls <- Parser Text Text -> Parser Text [Text]
    forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
    P.many' (Parser Text Text -> Parser Text Text
    forall i a. Parser i a -> Parser i a
    P.try ( Text -> Parser Text Text
    P.string Text
    "all") Parser Text Text -> Parser Text Text -> Parser Text Text
    forall a. Parser Text a -> Parser Text a -> Parser Text a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> Text -> Parser Text Text
    P.string Text
    "a")
                return $! writeCmd $ not (null alls)

              parseWriteAs :: Parser ExCommand
    parseWriteAs = 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
                filename <- String -> Text
    T.pack (String -> Text) -> Parser Text String -> Parser Text Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Parser Text Char -> Parser Text String
    forall (f :: * -> *) a. Alternative f => f a -> f [a]
    P.many1 Parser Text Char
    P.anyChar
                return $! writeAsCmd filename

    writeCmd :: Bool -> ExCommand
    writeCmd :: Bool -> ExCommand
    writeCmd Bool
    allFlag = ExCommand
    Common.impureExCommand {
        cmdShow = "write" <> if allFlag then "all" else ""
      , cmdAction = YiA $ if allFlag
          then Common.forAllBuffers tryWriteBuffer >> printMsg "All files written"
          else viWrite
      }

    writeAsCmd :: T.Text -> ExCommand
    writeAsCmd :: Text -> ExCommand
    writeAsCmd Text
    filename = ExCommand
    Common.impureExCommand {
        cmdShow = "write " <> filename
      , cmdAction = YiA $ viWriteTo filename
      }

    tryWriteBuffer :: BufferRef -> YiM ()
    tryWriteBuffer :: BufferRef -> YiM ()
    tryWriteBuffer BufferRef
    buf = do
        ns <- BufferRef -> YiM Bool
    Common.needsSaving BufferRef
    buf
        when ns . void $ fwriteBufferE buf