module Yi.Keymap.Vim.Ex.Commands.Buffer (parse) where
import Control.Applicative (Alternative ((<|>)), Applicative ((*>)), (<$>))
import Control.Monad (void)
import Control.Monad.State (gets)
import qualified Data.Text as T (pack)
import qualified Text.ParserCombinators.Parsec as P (GenParser, anyChar,
digit, eof, many, many1,
parse, space, string,
try)
import Yi.Buffer.Basic (BufferRef (..))
import Yi.Buffer.Misc (bkey, isUnchangedBuffer)
import Yi.Editor
import Yi.Keymap (Action (EditorA))
import Yi.Keymap.Vim.Common (EventString)
import qualified Yi.Keymap.Vim.Ex.Commands.Common as Common (errorNoWrite, parseWithBangAndCount, pureExCommand)
import Yi.Keymap.Vim.Ex.Types (ExCommand (cmdAction, cmdShow))
parse :: EventString -> Maybe ExCommand
parse = Common.parseWithBangAndCount nameParser $ \ _ bang mcount -> do
bufIdent <- P.try ( P.many1 P.digit <|> bufferSymbol) <|>
P.many1 P.space *> P.many P.anyChar <|>
P.eof *> return ""
return $ Common.pureExCommand {
cmdShow = "buffer"
, cmdAction = EditorA $ do
unchanged <- withCurrentBuffer $ gets isUnchangedBuffer
if bang || unchanged
then case mcount of
Nothing -> switchToBuffer bufIdent
Just i -> switchByRef $ BufferRef i
else Common.errorNoWrite
}
where
bufferSymbol = P.string "%" <|> P.string "#"
nameParser :: P.GenParser Char () ()
nameParser =
void $ P.try ( P.string "buffer") <|>
P.try ( P.string "buf") <|>
P.try ( P.string "bu") <|>
P.try ( P.string "b")
switchToBuffer :: String -> EditorM ()
switchToBuffer s =
case P.parse bufferRef "" s of
Right ref -> switchByRef ref
Left _e -> switchByName s
where
bufferRef = BufferRef . read <$> P.many1 P.digit
switchByName :: String -> EditorM ()
switchByName "" = return ()
switchByName "%" = return ()
switchByName "#" = switchToBufferWithNameE ""
switchByName bufName = switchToBufferWithNameE (T.pack bufName)
switchByRef :: BufferRef -> EditorM ()
switchByRef ref = do
mBuf <- findBuffer ref
maybe (return ()) (switchToBufferE . bkey) mBuf