{-# 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 (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 :: Text
cmdShow = Text
"bdelete"
      , cmdAction :: Action
cmdAction = YiM () -> Action
forall a. Show a => YiM a -> Action
YiA (YiM () -> Action) -> YiM () -> Action
forall a b. (a -> b) -> a -> b
$ do
            BufferRef
buffer <- case (# Maybe Int
mcount, Parser BufferRef -> Text -> Either String BufferRef
forall a. Parser a -> Text -> Either String a
P.parseOnly Parser BufferRef
bufferRef Text
bufIdent #) of
                (# Just Int
i, Either String BufferRef
_ #) -> BufferRef -> YiM BufferRef
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 (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 (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
            Bool
q <- if Bool
bang then Bool -> YiM Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True else Bool -> Bool
not (Bool -> Bool) -> YiM Bool -> YiM Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> BufferRef -> YiM Bool
Common.needsSaving BufferRef
buffer
            if Bool
q
                then do
                    BufferRef -> YiM ()
forall (m :: * -> *). MonadEditor m => BufferRef -> m ()
deleteBuffer BufferRef
buffer
                    Bool -> YiM () -> YiM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Text -> Bool
T.null Text
bufIdent) (YiM () -> YiM ()) -> YiM () -> YiM ()
forall a b. (a -> b) -> a -> b
$ YiM ()
closeWindow -- Because this function closed the window before I started altering it
                else Text -> YiM ()
errorEditor Text
"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 (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 (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"]