nvim-hs-0.0.2: library/Neovim/Plugin/ConfigHelper/Internal.hs
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RecordWildCards #-}
{- |
Module : Neovim.Plugin.ConfigHelper.Internal
Description : Internals for a config helper plugin that helps recompiling nvim-hs
Copyright : (c) Sebastian Witte
License : Apache-2.0
Maintainer : woozletoff@gmail.com
Stability : experimental
Portability : GHC
-}
module Neovim.Plugin.ConfigHelper.Internal
where
import Neovim.API.String (vim_command)
import Neovim.Config
import Neovim.Context
import Neovim.Plugin.Classes
import Neovim.Quickfix
import Neovim.RPC.FunctionCall
import Config.Dyre (Params)
import Config.Dyre.Compile
import Control.Applicative hiding (many, (<|>))
import Control.Monad (void)
import Data.Char
import Text.Parsec hiding (count)
import Text.Parsec.String
-- | Simple function that will return @"Pong"@ if the plugin provider is
-- running.
pingNvimhs :: Neovim' String
pingNvimhs = return "Pong"
-- | Recompile the plugin provider and put comile errors in the quickfix list.
recompileNvimhs :: Neovim (Params NeovimConfig) [QuickfixListItem String] ()
recompileNvimhs = do
cfg <- ask
mErrString <- liftIO (customCompile cfg >> getErrorString cfg)
let qs = maybe [] parseQuickfixItems mErrString
put qs
setqflist qs Replace
wait' $ vim_command "cwindow"
-- | Note that restarting the plugin provider implies compilation because Dyre
-- does this automatically. However, if the recompilation fails, the previously
-- compiled bynary is executed. This essentially means that restarting may take
-- more time then you might expect.
restartNvimhs :: CommandArguments
-> Neovim (Params NeovimConfig) [QuickfixListItem String] ()
restartNvimhs CommandArguments{..} = do
case bang of
Just True -> recompileNvimhs
_ -> return ()
restart
-- Parsing {{{1
-- See the tests in @test-suite\/Neovim\/Plugin\/ConfigHelperSpec.hs@ on how the
-- error messages look like.
parseQuickfixItems :: String -> [QuickfixListItem String]
parseQuickfixItems s =
case parse (many pQuickfixListItem) "Quickfix parser" s of
Right qs -> qs
Left _ -> []
pQuickfixListItem :: Parser (QuickfixListItem String)
pQuickfixListItem = do
_ <- many blankLine
(f,l,c) <- pLocation
desc <- try pShortDesrciption <|> pLongDescription
return $ (quickfixListItem (Right f) (Left l))
{ col = Just (c, True)
, text = desc
, errorType = "E" -- TODO determine actual type
}
pShortDesrciption :: Parser String
pShortDesrciption = (:)
<$> (many spaceChar *> notFollowedBy blankLine *> anyChar)
<*> anyChar `manyTill` (void (many1 blankLine) <|> eof)
pLongDescription :: Parser String
pLongDescription = anyChar `manyTill` (blank <|> eof)
where
blank = try (try newline *> try blankLine)
spaceChar :: Parser Char
spaceChar = satisfy $ \c -> c == ' ' || c == '\t'
blankLine :: Parser ()
blankLine = void . try $ many spaceChar >> newline
-- | Skip anything until the next location information appears.
--
-- The result will be a triple of filename, line number and column
-- | Try to parse location information.
--
-- @\/some\/path\/to\/a\/file.hs:42:88:@
pLocation :: Parser (String, Int, Int)
pLocation = (,,)
<$> many1 (noneOf ":\n\t\r") <* char ':'
<*> pInt <* char ':'
<*> pInt <* char ':' <* many spaceChar
pInt :: Parser Int
pInt = read <$> many1 (satisfy isDigit)
-- 1}}}