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

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

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

import           Control.Applicative              (Alternative (some))
import           Control.Monad                    (void, when)
import qualified Data.Text                        as T (null)
import qualified Data.Attoparsec.Text             as P (Parser, choice, digit, parseOnly, string)
import           Lens.Micro.Platform              (use)
import           Yi.Buffer.Basic                  (BufferRef (..))
import           Yi.Core                          (closeWindow, errorEditor)
import           Yi.Editor                        (currentWindowA, deleteBuffer, getBufferWithName, withEditor)
import           Yi.Keymap                        (Action (YiA))
import           Yi.Keymap.Vim.Common             (EventString)
import           Yi.Keymap.Vim.Ex.Commands.Buffer (bufferIdentifier)
import qualified Yi.Keymap.Vim.Ex.Commands.Common as Common (needsSaving, parseWithBangAndCount, impureExCommand)
import           Yi.Keymap.Vim.Ex.Types           (ExCommand (cmdAction, cmdShow))
import           Yi.Window                        (bufkey)

parse :: EventString -> Maybe ExCommand
parse :: EventString -> Maybe ExCommand
parse = Parser ()
-> (() -> Bool -> Maybe Int -> Parser ExCommand)
-> EventString
-> Maybe ExCommand
forall a.
Parser a
-> (a -> Bool -> Maybe Int -> Parser ExCommand)
-> EventString
-> Maybe ExCommand
Common.parseWithBangAndCount Parser ()
nameParser ((() -> Bool -> Maybe Int -> Parser ExCommand)
 -> EventString -> Maybe ExCommand)
-> (() -> Bool -> Maybe Int -> Parser ExCommand)
-> EventString
-> Maybe ExCommand
forall a b. (a -> b) -> a -> b
$ \ ()
_ Bool
bang Maybe Int
mcount -> do
    Text
bufIdent <- Parser Text
bufferIdentifier
    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
$ ExCommand
Common.impureExCommand {
        cmdShow = "bdelete"
      , cmdAction = YiA $ do
            buffer <- case (# mcount, P.parseOnly bufferRef bufIdent #) of
                (# Just Int
i, Either String BufferRef
_ #) -> BufferRef -> YiM BufferRef
forall a. a -> YiM a
forall (m :: * -> *) a. Monad m => a -> m a
return (BufferRef -> YiM BufferRef) -> BufferRef -> YiM BufferRef
forall a b. (a -> b) -> a -> b
$ Int -> BufferRef
BufferRef Int
i
                (# Maybe Int, Either String BufferRef #)
_ | Text -> Bool
T.null Text
bufIdent -> EditorM BufferRef -> YiM BufferRef
forall a. EditorM a -> YiM a
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor (EditorM BufferRef -> YiM BufferRef)
-> EditorM BufferRef -> YiM BufferRef
forall a b. (a -> b) -> a -> b
$ Window -> BufferRef
bufkey (Window -> BufferRef) -> EditorM Window -> EditorM BufferRef
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Getting Window Editor Window -> EditorM Window
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting Window Editor Window
Lens' Editor Window
currentWindowA
                (# Maybe Int
_, Right BufferRef
ref #) -> BufferRef -> YiM BufferRef
forall a. a -> YiM a
forall (m :: * -> *) a. Monad m => a -> m a
return BufferRef
ref
                (# Maybe Int
_, Left String
_ #) -> Text -> YiM BufferRef
forall (m :: * -> *). MonadEditor m => Text -> m BufferRef
getBufferWithName Text
bufIdent
            q <- if bang then pure True else not <$> Common.needsSaving buffer
            if q
                then do
                    deleteBuffer buffer
                    when (T.null bufIdent) $ closeWindow -- Because this function closed the window before I started altering it
                else errorEditor "No write since last change (add ! to override)"
      }
  where
    bufferRef :: Parser BufferRef
bufferRef = Int -> BufferRef
BufferRef (Int -> BufferRef) -> (String -> Int) -> String -> BufferRef
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Int
forall a. Read a => String -> a
read (String -> BufferRef) -> Parser Text String -> Parser BufferRef
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall a. Parser Text a -> Parser Text [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some Parser Text Char
P.digit

nameParser :: P.Parser ()
nameParser :: Parser ()
nameParser = Parser Text -> Parser ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Parser Text -> Parser ())
-> ([Text] -> Parser Text) -> [Text] -> Parser ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Parser Text] -> Parser Text
forall (f :: * -> *) a. Alternative f => [f a] -> f a
P.choice ([Parser Text] -> Parser Text)
-> ([Text] -> [Parser Text]) -> [Text] -> Parser Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Parser Text) -> [Text] -> [Parser Text]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> Parser Text
P.string ([Text] -> Parser ()) -> [Text] -> Parser ()
forall a b. (a -> b) -> a -> b
$ [Text
"bdelete",Text
"bdel",Text
"bd"]