module Yi.Keymap.Vim.Ex.Commands.Quit (parse) where
import Control.Applicative
import Control.Lens
import Control.Monad
import Data.Foldable (find)
import qualified Data.List.PointedList.Circular as PL
import Data.Monoid
import qualified Data.Text as T
import qualified Text.ParserCombinators.Parsec as P
import Yi.Buffer
import Yi.Core (quitEditor, errorEditor, closeWindow)
import Yi.Editor
import Yi.File
import Yi.Keymap
import Yi.Keymap.Vim.Common
import qualified Yi.Keymap.Vim.Ex.Commands.Common as Common
import Yi.Keymap.Vim.Ex.Types
import Yi.Monad
import Yi.String (showT)
import Yi.Window (bufkey)
parse :: EventString -> Maybe ExCommand
parse = Common.parse $ P.choice
[ do
_ <- (P.try ( P.string "xit") <|> P.string "x")
bangs <- P.many (P.char '!')
return (quit True (not $ null bangs) False)
, do
ws <- P.many (P.char 'w')
void $ P.try ( P.string "quit") <|> P.string "q"
as <- P.many (P.try ( P.string "all") <|> P.string "a")
bangs <- P.many (P.char '!')
return $! quit (not $ null ws) (not $ null bangs) (not $ null as)
]
quit :: Bool -> Bool -> Bool -> ExCommand
quit w f a = Common.impureExCommand {
cmdShow = (if w then "w" else "")
`T.append` "quit"
`T.append` (if a then "all" else "")
`T.append` (if f then "!" else "")
, cmdAction = YiA $ action w f a
}
action :: Bool -> Bool -> Bool -> YiM ()
action False False False = quitWindowE
action False False True = quitAllE
action True False False = viWrite >> closeWindow
action True False True = saveAndQuitAllE
action False True False = closeWindow
action False True True = quitEditor
action True True False = viWrite >> closeWindow
action True True True = saveAndQuitAllE
quitWindowE :: YiM ()
quitWindowE = do
nw <- gets currentBuffer >>= Common.needsSaving
ws <- withEditor $ use currentWindowA >>= windowsOnBufferE . bufkey
if length ws == 1 && nw
then errorEditor "No write since last change (add ! to override)"
else do
winCount <- withEditor $ uses windowsA PL.length
tabCount <- withEditor $ uses tabsA PL.length
if winCount == 1 && tabCount == 1
then quitAllE
else closeWindow
quitAllE :: YiM ()
quitAllE = do
let needsWindow b = (b,) <$> deservesSave b
bs <- readEditor bufferSet >>= mapM needsWindow
case find snd bs of
Nothing -> quitEditor
Just (b, _) -> do
bufferName <- withEditor $ withGivenBuffer (bkey b) $ gets file
errorEditor $ "No write since last change for buffer "
<> showT bufferName
<> " (add ! to override)"
saveAndQuitAllE :: YiM ()
saveAndQuitAllE = Common.forAllBuffers fwriteBufferE >> quitEditor