{-# LANGUAGE NumDecimals #-} {-# LANGUAGE OverloadedStrings #-} module Utils ( module Utils , Edit (..) ) where import Control.Concurrent (threadDelay) import Cornelis.Types import Cornelis.Offsets import Cornelis.Utils (withLocalEnv) import Cornelis.Vim import Data.Foldable.Levenshtein (levenshtein, Edit(..)) import qualified Data.Text as T import qualified Data.Vector as V import Lib import Neovim import Neovim.API.Text import Neovim.Test import Plugin import System.FilePath (takeBaseName) import System.IO (hFlush, hPutStr) import System.IO.Temp (withSystemTempFile) import Test.Hspec hiding (after, before) -- data Diff a -- = Insert a -- | Delete a -- | Modify a a -- deriving (Eq, Ord, Show, Functor) isCopy :: Edit a -> Bool isCopy Copy{} = True isCopy _ = False diff :: Show a => Eq a => [a] -> [a] -> [Edit a] diff = ((filter (not . isCopy) . snd) .) . levenshtein @_ @_ @_ @Int -- (snd .) . go -- where -- go ([]) as = (length as, fmap Insert as) -- go bs [] = (length bs, fmap Delete bs) -- go (b : bs) (a : as) -- | b == a = go bs as -- | otherwise = do -- let x = traceShowId $ bimap (+1) (Delete b :) $ go bs (a : as) -- y = traceShowId $ bimap (+1) (Insert a :) $ go (b : bs) as -- z = traceShowId $ bimap (+1) (Modify b a :) $ go bs as -- minimumBy (comparing fst) [z, x, y] differing :: Buffer -> Neovim env () -> Neovim env [Edit Text] differing b m = do before <- fmap V.toList $ buffer_get_lines b 0 (-1) False m liftIO $ threadDelay 1e6 after <- fmap V.toList $ buffer_get_lines b 0 (-1) False pure $ diff before after intervention :: Buffer -> [Edit Text] -> Neovim env () -> Neovim env () intervention b d m = do d' <- differing b m liftIO $ d' `shouldBe` d withVim :: Seconds -> (Window -> Buffer -> Neovim () ()) -> IO () withVim secs m = do let withNeovimEmbedded f = testWithEmbeddedNeovim f secs () withNeovimEmbedded Nothing $ do b <- nvim_create_buf False False w <- vim_get_current_window nvim_win_set_buf w b m w b diffSpec :: String -> Seconds -> FilePath -> [Edit Text] -> (Window -> Buffer -> Neovim CornelisEnv ()) -> Spec diffSpec name secs fp diffs m = vimSpec name secs fp $ \w b -> intervention b diffs $ m w b vimSpec :: String -> Seconds -> FilePath -> (Window -> Buffer -> Neovim CornelisEnv ()) -> Spec vimSpec name secs fp m = do let withNeovimEmbedded f = testWithEmbeddedNeovim f secs () it name $ do withSystemTempFile "test.agda" $ \fp' h -> do hPutStr h $ "module " <> takeBaseName fp' <> " where\n" hPutStr h . unlines . tail . lines =<< readFile fp hFlush h withNeovimEmbedded Nothing $ do env <- cornelisInit withLocalEnv env $ do vim_command $ "edit " <> T.pack fp' liftIO $ threadDelay 1e6 w <- vim_get_current_window b <- nvim_win_get_buf w load liftIO $ threadDelay 5e6 m w b goto :: Window -> Int -> Int -> Neovim env () goto w row col = setWindowCursor w $ Pos (toOneIndexed row) (toOneIndexed col)