proteome 0.1.0.0 → 0.2.0.0
raw patch · 42 files changed
+1424/−52 lines, 42 filesdep +HTFdep +MissingHdep +ansi-terminaldep ~nvim-hssetup-changednew-component:exe:proteome-exe
Dependencies added: HTF, MissingH, ansi-terminal, containers, data-default-class, deepseq, directory, filepath, hslogger, lens, messagepack, mtl, pretty-terminal, prettyprinter, process, proteome, resourcet, split, stm, strings, text, time, unliftio, utf8-string
Dependency ranges changed: nvim-hs
Files
- README.md +7/−1
- Setup.hs +2/−0
- app/Main.hs +6/−0
- lib/Proteome/Config.hs +72/−0
- lib/Proteome/Data/Env.hs +24/−0
- lib/Proteome/Data/Project.hs +86/−0
- lib/Proteome/Data/ProjectSpec.hs +41/−0
- lib/Proteome/Data/Proteome.hs +9/−0
- lib/Proteome/Init.hs +80/−10
- lib/Proteome/Log.hs +21/−0
- lib/Proteome/Plugin.hs +25/−12
- lib/Proteome/Project/Resolve.hs +74/−0
- lib/Proteome/Save.hs +8/−0
- lib/Proteome/Settings.hs +52/−0
- lib/Proteome/Tags.hs +91/−0
- lib/Proteome/Test/Config.hs +13/−0
- lib/Proteome/Test/Functional.hs +15/−0
- lib/Proteome/Test/Unit.hs +27/−0
- lib/Ribosome/Api/Option.hs +14/−0
- lib/Ribosome/Api/Response.hs +27/−0
- lib/Ribosome/Config/Settings.hs +47/−0
- lib/Ribosome/Data/Errors.hs +25/−0
- lib/Ribosome/Data/Maybe.hs +7/−0
- lib/Ribosome/Data/Ribo.hs +26/−0
- lib/Ribosome/Data/Ribosome.hs +18/−0
- lib/Ribosome/Internal/IO.hs +25/−0
- lib/Ribosome/Internal/NvimObject.hs +8/−0
- lib/Ribosome/Log.hs +14/−0
- lib/Ribosome/Test/Embed.hs +47/−0
- lib/Ribosome/Test/Exists.hs +44/−0
- lib/Ribosome/Test/File.hs +27/−0
- lib/Ribosome/Test/Functional.hs +60/−0
- lib/Ribosome/Test/Unit.hs +32/−0
- nvim.hs +0/−6
- proteome.cabal +200/−23
- test/f/Config.hs +15/−0
- test/f/ConfigSpec.hs +24/−0
- test/f/InitSpec.hs +26/−0
- test/f/SpecMain.hs +12/−0
- test/u/Config.hs +15/−0
- test/u/SpecMain.hs +10/−0
- test/u/TagsSpec.hs +48/−0
README.md view
@@ -1,3 +1,9 @@ # Intro -A neovim plugin that provides project-specific configuration file loading.+A neovim plugin that provides project-specific configuration file loading and performs runtime tasks on projects.++# Install++Use the [chromatin] plugin manager with the spec `hackage:proteome`.++[chromatin]: https://github.com/tek/chromatin.nvim
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ app/Main.hs view
@@ -0,0 +1,6 @@+import Neovim++import Proteome.Plugin (plugin)++main :: IO ()+main = neovim defaultConfig {plugins = [plugin]}
+ lib/Proteome/Config.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE RecordWildCards #-}++module Proteome.Config(+ proReadConfig,+ readConfig,+ ProjectConfig (..),+)+where++import GHC.Generics (Generic)+import Control.DeepSeq (NFData)+import qualified Data.Map as Map+import Data.Foldable (traverse_)+import Data.Map.Strict (Map)+import Neovim (NvimObject, toObject, Dictionary, Object, vim_command')+import Ribosome.Data.Ribo (Ribo)+import qualified Ribosome.Data.Ribo as Ribo (inspect)+import qualified Proteome.Data.Env as Env (mainProject)+import Proteome.Data.Project (+ Project(Project, types),+ ProjectType(ProjectType, projectType),+ ProjectName(ProjectName),+ ProjectMetadata(DirProject),+ )+import Proteome.Data.Proteome++newtype ProjectConfig =+ ProjectConfig {+ projectTypes :: Map ProjectType [FilePath]+ }+ deriving (Generic, NFData)++instance NvimObject ProjectConfig where+ toObject ProjectConfig {..} =+ (toObject :: Dictionary -> Object) . Map.fromList $+ [+ ("projectTypes", toObject projectTypes)+ ]++runtime :: FilePath -> Ribo a ()+runtime path = vim_command' $ "runtime " ++ path ++ ".vim"++runtimeConf :: FilePath -> String -> Ribo a ()+runtimeConf confDir path = runtime(confDir ++ "/" ++ path)++typeProjectConf :: FilePath -> ProjectName -> ProjectType -> Ribo a ()+typeProjectConf confDir (ProjectName name') (ProjectType tpe') = do+ runtimeConf confDir tpe'+ runtimeConf confDir $ tpe' ++ "/" ++ name'++readConfigMeta :: String -> Project -> Ribo a ()+readConfigMeta confDir (Project (DirProject name' _ tpe') _ _ _) =+ traverse_ (typeProjectConf confDir name') tpe'+readConfigMeta _ _ = return ()++readConfigProject :: String -> Project -> Ribo a ()+readConfigProject confDir project = do+ readConfigMeta confDir project+ traverse_ (runtimeConf confDir) (fmap projectType (types project))++readConfig :: String -> Project -> Ribo a ()+readConfig confDir project = do+ runtimeConf confDir "all/*"+ readConfigProject confDir project++proReadConfig :: Proteome ()+proReadConfig = do+ main <- Ribo.inspect Env.mainProject+ readConfig "project" main
+ lib/Proteome/Data/Env.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE TemplateHaskell #-}++module Proteome.Data.Env (+ Env(..),+ _mainProject,+ _projects,+ _errors,+) where++import Control.Lens (makeClassy_)+import Data.Default.Class (Default(def))+import Ribosome.Data.Errors (Errors)+import Proteome.Data.Project++data Env = Env {+ mainProject :: Project,+ projects :: [Project],+ errors :: Errors+}++makeClassy_ ''Env++instance Default Env where+ def = Env def def def
+ lib/Proteome/Data/Project.hs view
@@ -0,0 +1,86 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-}++module Proteome.Data.Project(+ ProjectMetadata (..),+ Project (..),+ ProjectType (..),+ ProjectLang (..),+ ProjectRoot (..),+ ProjectName (..),+ _meta,+ _lang,+ langOrType,+) where++import GHC.Generics (Generic)+import Control.Lens (makeClassy_)+import Control.DeepSeq+import Data.Default.Class (Default(def))+import Neovim.Classes (NvimObject(..))+import Ribosome.Internal.NvimObject (deriveString)++newtype ProjectName = ProjectName String+ deriving (Eq, Show, Generic, NFData)++instance NvimObject ProjectName where+ toObject (ProjectName s) = toObject s+ fromObject = deriveString ProjectName++newtype ProjectType =+ ProjectType {+ projectType :: String+ }+ deriving (Ord, Eq, Show, Generic, NFData)++instance NvimObject ProjectType where+ toObject (ProjectType s) = toObject s+ fromObject = deriveString ProjectType++newtype ProjectLang = ProjectLang String+ deriving (Eq, Show, Generic, NFData)++instance NvimObject ProjectLang where+ toObject (ProjectLang s) = toObject s+ fromObject = deriveString ProjectLang++newtype ProjectRoot = ProjectRoot FilePath+ deriving (Eq, Show, Generic, NFData)++instance NvimObject ProjectRoot where+ toObject (ProjectRoot s) = toObject s+ fromObject = deriveString ProjectRoot++data ProjectMetadata =+ DirProject {+ name :: ProjectName,+ root :: ProjectRoot,+ tpe :: Maybe ProjectType+ }+ | VirtualProject {+ name :: ProjectName+ }+ deriving (Eq, Show)++instance Default ProjectMetadata where+ def = VirtualProject (ProjectName "main")++data Project =+ Project {+ meta :: ProjectMetadata,+ types :: [ProjectType],+ lang :: Maybe ProjectLang,+ langs :: [ProjectLang]+ }+ deriving (Eq, Show)++makeClassy_ ''Project++instance Default Project where+ def = Project def def def def++langOrType :: Maybe ProjectLang -> Maybe ProjectType -> Maybe ProjectLang+langOrType (Just lang') _ = Just lang'+langOrType Nothing (Just (ProjectType tpe')) = Just (ProjectLang tpe')+langOrType _ _ = Nothing
+ lib/Proteome/Data/ProjectSpec.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE RecordWildCards #-}++module Proteome.Data.ProjectSpec(+ ProjectSpec (..),+) where++import GHC.Generics (Generic)+import Control.DeepSeq (NFData)+import qualified Data.Map as Map+import Data.Maybe (catMaybes)+import Data.MessagePack+import Neovim.Classes (NvimObject(..), Dictionary)+import Proteome.Data.Project (ProjectName, ProjectType, ProjectLang, ProjectRoot)++data ProjectSpec =+ ProjectSpec {+ name :: ProjectName,+ root :: ProjectRoot,+ tpe :: Maybe ProjectType,+ types :: [ProjectType],+ lang :: Maybe ProjectLang,+ langs :: [ProjectLang]+ }+ deriving (Generic, NFData)++instance NvimObject ProjectSpec where+ toObject ProjectSpec {..} =+ (toObject :: Dictionary -> Object) . Map.fromList $+ [+ ("name", toObject name),+ ("root", toObject root),+ ("types", toObject types),+ ("langs", toObject langs)+ ] ++ catMaybes+ [+ tpe >>= \a -> return ("tpe", toObject a),+ lang >>= \a -> return ("lang", toObject a)+ ]
+ lib/Proteome/Data/Proteome.hs view
@@ -0,0 +1,9 @@+module Proteome.Data.Proteome(+ Proteome+) where++import UnliftIO.STM (TVar)+import Ribosome.Data.Ribo (Ribo)+import Proteome.Data.Env (Env)++type Proteome a = Ribo (TVar Env) a
lib/Proteome/Init.hs view
@@ -1,15 +1,85 @@-{-# LANGUAGE TemplateHaskell #-}--module Proteome.Init-(+module Proteome.Init( initialize,- env+ proteomeStage2,+ proteomeStage4, ) where -import Neovim+import Control.Monad.Reader+import Data.Default.Class (Default(def))+import System.Directory (getCurrentDirectory, makeAbsolute)+import System.FilePath (takeFileName, takeDirectory)+import System.Log.Logger (updateGlobalLogger, setLevel, Priority(ERROR))+import Control.Monad.IO.Class (MonadIO)+import Neovim.Context.Internal (Neovim)+import UnliftIO.STM (TVar, newTVarIO)+import Ribosome.Config.Settings (setting, settingE, updateSetting)+import Ribosome.Data.Ribo+import Ribosome.Data.Ribosome (Ribosome(Ribosome))+import Ribosome.Internal.IO (retypeNeovim)+import Proteome.Data.Env (Env(Env))+import Proteome.Data.Proteome+import Proteome.Data.Project (+ Project(meta),+ ProjectName(..),+ ProjectRoot(..),+ ProjectType(..),+ ProjectMetadata(DirProject),+ )+import Proteome.Project.Resolve (resolveProject)+import qualified Proteome.Settings as S -env :: Neovim startupEnv ()-env = return ()+pathData :: MonadIO m => Either String FilePath -> m (ProjectRoot, ProjectName, ProjectType)+pathData override = do+ cwd <- liftIO $ either (const getCurrentDirectory) pure override+ absMainDir <- liftIO $ makeAbsolute cwd+ return (+ ProjectRoot absMainDir,+ ProjectName $ takeFileName absMainDir,+ ProjectType $ (takeFileName . takeDirectory) absMainDir+ ) -initialize :: Neovim startupEnv ()-initialize = return ()+mainProject :: Ribo e Project+mainProject = do+ mainDir <- settingE S.mainProjectDir+ (root, name, tpe) <- pathData mainDir+ baseDirs <- setting S.projectBaseDirs+ -- typeDirs <- setting S.projectTypeDirs+ explicit <- setting S.projects+ config <- setting S.projectConfig+ return $ resolveProject baseDirs explicit config root name (Just tpe)++loadPersistedBuffers :: Project -> Neovim e ()+loadPersistedBuffers _ = return ()++updateMainType :: Maybe ProjectType -> Ribo e ()+updateMainType (Just tpe) = updateSetting S.mainType tpe+updateMainType Nothing = return ()++setProjectVars :: ProjectMetadata -> Ribo e ()+setProjectVars (DirProject name _ tpe) = do+ updateSetting S.mainName name+ updateMainType tpe+setProjectVars _ = return ()++initWithMain :: Project -> Ribo e Env+initWithMain main = do+ loadPersistedBuffers main+ setProjectVars (meta main)+ return $ Env main [] def++initialize' :: Ribo e Env+initialize' = do+ main <- mainProject+ initWithMain main++initialize :: Neovim e (TVar Env)+initialize = do+ liftIO $ updateGlobalLogger "Neovim.Plugin" (setLevel ERROR)+ env <- retypeNeovim (Ribosome "proteome") initialize'+ newTVarIO env++proteomeStage2 :: Proteome ()+proteomeStage2 = return ()++proteomeStage4 :: Proteome ()+proteomeStage4 = return ()
+ lib/Proteome/Log.hs view
@@ -0,0 +1,21 @@+module Proteome.Log(+ debug,+ info,+ debugS,+ infoS,+) where++import Ribosome.Data.Ribo (Ribo)+import qualified Ribosome.Log as R (debug, info)++debug :: String -> Ribo e ()+debug = R.debug "proteome"++info :: String -> Ribo e ()+info = R.info "proteome"++debugS :: Show a => a -> Ribo e ()+debugS = R.debug "proteome"++infoS :: Show a => a -> Ribo e ()+infoS = R.info "proteome"
lib/Proteome/Plugin.hs view
@@ -1,23 +1,36 @@ {-# LANGUAGE TemplateHaskell #-} module Proteome.Plugin(- plugin+ plugin, ) where +import UnliftIO.STM (TVar) import Neovim--import Proteome.Init (initialize, env)+import Ribosome.Data.Ribosome (Ribosome(Ribosome))+import Proteome.Init+import Proteome.Data.Env import Proteome.Add (proAdd, proteomePoll)+import Proteome.Config (proReadConfig)+import Proteome.Tags (proTags)+import Proteome.Save (proSave) +plugin' :: TVar Env -> Plugin (Ribosome (TVar Env))+plugin' env =+ Plugin {+ environment = Ribosome "proteome" env,+ exports = [+ $(function' 'proteomePoll) Sync,+ $(function' 'proteomeStage2) Async,+ $(function' 'proteomeStage4) Async,+ $(function' 'proAdd) Async,+ $(function' 'proSave) Async,+ $(function' 'proTags) Async,+ $(function' 'proReadConfig) Sync+ ]+ }+ plugin :: Neovim (StartupConfig NeovimConfig) NeovimPlugin plugin = do- initialize- wrapPlugin- Plugin {- environment = env,- exports = [- $(function' 'proteomePoll) Sync,- $(function' 'proAdd) Async- ]- }+ env <- initialize+ wrapPlugin $ plugin' env
+ lib/Proteome/Project/Resolve.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE NamedFieldPuns #-}++module Proteome.Project.Resolve(+ resolveProject,+) where++import Data.List (find)+import Data.Maybe (fromMaybe)+import System.FilePath (takeDirectory)+import Ribosome.Data.Maybe (orElse)+import Proteome.Config (ProjectConfig)+import Proteome.Data.Project (+ Project(Project),+ ProjectName(..),+ ProjectRoot(..),+ ProjectType(..),+ ProjectLang(..),+ ProjectMetadata(DirProject, VirtualProject),+ )+import Proteome.Data.ProjectSpec (ProjectSpec(ProjectSpec))+import qualified Proteome.Data.ProjectSpec as PS (ProjectSpec(..))++projectFromSegments :: ProjectType -> ProjectName -> ProjectRoot -> Project+projectFromSegments tpe name root =+ Project (DirProject name root (Just tpe)) [] (Just (ProjectLang (projectType tpe))) []++projectFromSpec :: ProjectSpec -> Project+projectFromSpec (ProjectSpec name root tpe types lang langs) =+ Project (DirProject name root tpe) types lang langs++hasProjectRoot :: ProjectRoot -> ProjectSpec -> Bool+hasProjectRoot root spec = root == PS.root spec++hasProjectTypeName :: ProjectType -> ProjectName -> ProjectSpec -> Bool+hasProjectTypeName tpe' name' (ProjectSpec name _ (Just tpe) _ _ _) =+ name' == name && tpe' == tpe+hasProjectTypeName _ _ _ = False++byProjectTypeName :: [ProjectSpec] -> ProjectName -> ProjectType -> Maybe ProjectSpec+byProjectTypeName specs name tpe = find (hasProjectTypeName tpe name) specs++byProjectBases :: [FilePath] -> ProjectRoot -> Bool+byProjectBases baseDirs (ProjectRoot root) = elem ((takeDirectory . takeDirectory) root) baseDirs++virtualProject :: ProjectName -> Project+virtualProject name = Project (VirtualProject name) [] Nothing []++resolveByType :: [FilePath] -> [ProjectSpec] -> ProjectRoot -> ProjectName -> ProjectType -> Maybe Project+resolveByType baseDirs explicit root name tpe =+ orElse (if byPath then Just (projectFromSegments tpe name root) else Nothing) (fmap projectFromSpec byTypeName)+ where+ byTypeName = byProjectTypeName explicit name tpe+ byPath = byProjectBases baseDirs root++resolveByRoot :: [ProjectSpec] -> ProjectRoot -> Maybe Project+resolveByRoot explicit root =+ fmap projectFromSpec byRoot+ where+ byRoot = find (hasProjectRoot root) explicit++resolveProject ::+ [FilePath] ->+ [ProjectSpec] ->+ ProjectConfig ->+ ProjectRoot ->+ ProjectName ->+ Maybe ProjectType ->+ Project+resolveProject baseDirs explicit _ root name tpe =+ fromMaybe byTypeOrVirtual byRoot+ where+ byTypeOrVirtual = fromMaybe (virtualProject name) byType+ byType = tpe >>= resolveByType baseDirs explicit root name+ byRoot = resolveByRoot explicit root
+ lib/Proteome/Save.hs view
@@ -0,0 +1,8 @@+module Proteome.Save(+ proSave,+) where++import Proteome.Data.Proteome (Proteome)++proSave :: Proteome ()+proSave = return ()
+ lib/Proteome/Settings.hs view
@@ -0,0 +1,52 @@+module Proteome.Settings(+ mainProjectDir,+ projects,+ projectTypeDirs,+ projectBaseDirs,+ projectConfig,+ mainName,+ mainType,+ tagsCommand,+ tagsArgs,+ tagsFork,+ tagsFileName,+) where++import qualified Data.Map as Map+import Ribosome.Config.Settings+import Proteome.Data.Project (ProjectName, ProjectType)+import Proteome.Data.ProjectSpec (ProjectSpec)+import Proteome.Config++mainProjectDir :: Setting String+mainProjectDir = Setting "main_project_dir" True Nothing++projects :: Setting [ProjectSpec]+projects = Setting "projects" True (Just [])++projectBaseDirs :: Setting [FilePath]+projectBaseDirs = Setting "project_base_dirs" True (Just [])++projectTypeDirs :: Setting [FilePath]+projectTypeDirs = Setting "project_type_dirs" True (Just [])++projectConfig :: Setting ProjectConfig+projectConfig = Setting "project_config" True (Just (ProjectConfig Map.empty))++mainName :: Setting ProjectName+mainName = Setting "main_name" True Nothing++mainType :: Setting ProjectType+mainType = Setting "main_type" True Nothing++tagsCommand :: Setting String+tagsCommand = Setting "tags_command" True (Just "ctags")++tagsArgs :: Setting String+tagsArgs = Setting "tags_args" True (Just "-R --languages={langsComma} -f {tagFile} {root}")++tagsFork :: Setting Bool+tagsFork = Setting "tags_fork" True (Just True)++tagsFileName :: Setting FilePath+tagsFileName = Setting "tags_file_name" True (Just ".tags")
+ lib/Proteome/Tags.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE OverloadedStrings #-}++module Proteome.Tags(+ proTags,+) where++import GHC.IO.Exception (ExitCode(..))+import Control.Monad (when)+import Control.Monad.IO.Class (liftIO)+import Control.Lens (over)+import Data.List (intercalate)+import qualified Data.Map.Strict as Map (adjust)+import Data.Maybe (maybeToList)+import Data.String.Utils (replace)+import System.Process (readProcessWithExitCode)+import System.FilePath ((</>))+import System.Directory (setCurrentDirectory, doesFileExist, removePathForcibly)+import Ribosome.Config.Settings (setting)+import qualified Ribosome.Data.Ribo as Ribo (inspect, modify)+import Ribosome.Data.Errors (Errors(Errors), Error(Error), ComponentName(ComponentName))+import Ribosome.Internal.IO (forkNeovim)+import Proteome.Data.Env (Env(mainProject))+import qualified Proteome.Data.Env as Env (_errors)+import Proteome.Data.Proteome (Proteome)+import Proteome.Data.Project (+ Project (Project),+ ProjectLang(ProjectLang),+ ProjectRoot(ProjectRoot),+ ProjectMetadata (DirProject),+ langOrType,+ )+import qualified Proteome.Settings as S (tagsCommand, tagsArgs, tagsFork, tagsFileName)++replaceFormatItem :: String -> (String, String) -> String+replaceFormatItem original (placeholder, replacement) =+ replace ("{" ++ placeholder ++ "}") replacement original++formatTagsArgs :: [ProjectLang] -> ProjectRoot -> FilePath -> String -> String+formatTagsArgs langs (ProjectRoot root) fileName formatString =+ foldl replaceFormatItem formatString formats+ where+ formats = [+ ("langsComma", intercalate "," $ fmap (\(ProjectLang l) -> l) langs),+ ("tagFile", fileName),+ ("root", root)+ ]++deleteTags :: ProjectRoot -> Proteome ()+deleteTags (ProjectRoot root) = do+ name <- setting S.tagsFileName+ let path = root </> name+ exists <- liftIO $ doesFileExist path+ when exists $ liftIO $ removePathForcibly path++storeError :: ComponentName -> [String] -> Errors -> Errors+storeError name msg (Errors errors) =+ Errors (Map.adjust (err:) name errors)+ where+ err = Error time msg+ time = 0++notifyError :: String -> Proteome ()+notifyError e =+ Ribo.modify $ over Env._errors (storeError (ComponentName "ctags") [e])++executeTags :: ProjectRoot -> String -> String -> Proteome ()+executeTags (ProjectRoot root) cmd args = do+ liftIO $ setCurrentDirectory root+ deleteTags (ProjectRoot root)+ (exitcode, _, stderr) <- liftIO $ readProcessWithExitCode cmd [args] ""+ case exitcode of+ ExitSuccess -> return ()+ ExitFailure _ -> notifyError stderr++regenerateTags :: ProjectRoot -> [ProjectLang] -> Proteome ()+regenerateTags root langs = do+ cmd <- setting S.tagsCommand+ args <- setting S.tagsArgs+ fileName <- setting S.tagsFileName+ let thunk = executeTags root cmd (formatTagsArgs langs root fileName args)+ fork <- setting S.tagsFork+ _ <- if fork then forkNeovim thunk else thunk+ return ()++proTags :: Proteome ()+proTags = do+ main <- Ribo.inspect mainProject+ case main of+ Project (DirProject _ root tpe) _ lang langs ->+ regenerateTags root (maybeToList (langOrType lang tpe) ++ langs)+ _ -> return ()
+ lib/Proteome/Test/Config.hs view
@@ -0,0 +1,13 @@+module Proteome.Test.Config(+ defaultTestConfigWith,+ defaultTestConfig,+) where++import Ribosome.Test.Embed (TestConfig, Vars)+import qualified Ribosome.Test.Embed as E (defaultTestConfig, defaultTestConfigWith)++defaultTestConfigWith :: Vars -> TestConfig+defaultTestConfigWith = E.defaultTestConfigWith "proteome"++defaultTestConfig :: TestConfig+defaultTestConfig = E.defaultTestConfig "proteome"
+ lib/Proteome/Test/Functional.hs view
@@ -0,0 +1,15 @@+module Proteome.Test.Functional(+ spec,+ specWith,+) where++import Ribosome.Data.Ribo (Ribo)+import Ribosome.Test.Embed (Vars)+import Ribosome.Test.Functional (functionalSpec)+import Proteome.Test.Config (defaultTestConfig, defaultTestConfigWith)++spec :: Ribo () () -> IO ()+spec = functionalSpec defaultTestConfig++specWith :: Vars -> Ribo () () -> IO ()+specWith vars = functionalSpec $ defaultTestConfigWith vars
+ lib/Proteome/Test/Unit.hs view
@@ -0,0 +1,27 @@+module Proteome.Test.Unit(+ spec,+ specWith,+ specWithDef,+) where++import Data.Default.Class (def)+import UnliftIO.STM (newTVarIO)+import Ribosome.Test.Embed (Vars)+import Ribosome.Test.Unit (unitSpec)+import Proteome.Data.Proteome (Proteome)+import Proteome.Data.Env (Env)+import Proteome.Test.Config (defaultTestConfig, defaultTestConfigWith)++spec :: Env -> Proteome () -> IO ()+spec e s = do+ t <- newTVarIO e+ unitSpec defaultTestConfig t s++specWith :: Env -> Proteome () -> Vars -> IO ()+specWith e s vars = do+ t <- newTVarIO e+ unitSpec (defaultTestConfigWith vars) t s++specWithDef :: Proteome () -> Vars -> IO ()+specWithDef s v = do+ specWith def s v
+ lib/Ribosome/Api/Option.hs view
@@ -0,0 +1,14 @@+module Ribosome.Api.Option(+ optionCat,+ rtpCat+) where++import Neovim++optionCat :: String -> String -> Neovim env ()+optionCat name extra = do+ current <- vim_get_option' name >>= fromObject'+ vim_set_option' name $ toObject $ current ++ "," ++ extra++rtpCat :: String -> Neovim env ()+rtpCat = optionCat "runtimepath"
+ lib/Ribosome/Api/Response.hs view
@@ -0,0 +1,27 @@+module Ribosome.Api.Response(+ nvimFatal,+ nvimResponseString,+ nvimResponseStringArray,+ nvimValidateFatal+)+where++import Data.ByteString.UTF8+import Neovim++nvimFatal :: Either NeovimException a -> Neovim env a+nvimFatal (Right a) = return a+nvimFatal (Left e) = (liftIO . fail . show) e++nvimResponseString :: Object -> Neovim env String+nvimResponseString (ObjectString a) = return $ toString a+nvimResponseString a = liftIO . fail $ "invalid nvim type for String: " ++ (show a)++nvimResponseStringArray :: Object -> Neovim env [String]+nvimResponseStringArray (ObjectArray a) = traverse nvimResponseString a+nvimResponseStringArray a = liftIO . fail $ "invalid nvim type for Array: " ++ (show a)++nvimValidateFatal :: (Object -> Neovim env a) -> (Either NeovimException Object) -> Neovim env a+nvimValidateFatal validate response = do+ result <- nvimFatal response+ validate result
+ lib/Ribosome/Config/Settings.hs view
@@ -0,0 +1,47 @@+module Ribosome.Config.Settings(+ Setting (..),+ setting,+ settingE,+ updateSetting,+ settingVariableName,+) where++import Neovim+import Ribosome.Data.Ribo (Ribo)+import qualified Ribosome.Data.Ribosome as R (name)++data Setting a =+ Setting {+ name :: String,+ prefix :: Bool,+ fallback :: Maybe a+ }++settingVariableName :: Setting a -> Ribo e String+settingVariableName (Setting n False _) = return n+settingVariableName (Setting n True _) = do+ pluginName <- fmap R.name $ ask+ return $ pluginName ++ "_" ++ n++settingE :: NvimObject a => Setting a -> Ribo e (Either String a)+settingE s @ (Setting _ _ fallback') = do+ varName <- settingVariableName s+ raw <- vim_get_var varName+ case raw of+ Right o -> fromObject' o+ Left a -> return $ case fallback' of+ Just fb -> Right fb+ Nothing -> Left $ show a++setting :: NvimObject a => Setting a -> Ribo e a+setting s = do+ raw <- settingE s+ case raw of+ Right o -> return o+ Left e -> fail e++updateSetting :: NvimObject a => Setting a -> a -> Ribo e ()+updateSetting s a = do+ varName <- settingVariableName s+ _ <- vim_set_var' varName (toObject a)+ return ()
+ lib/Ribosome/Data/Errors.hs view
@@ -0,0 +1,25 @@+module Ribosome.Data.Errors(+ ComponentName(..),+ Error(..),+ Errors(..),+) where++import qualified Data.Map as Map+import Data.Default.Class (Default(def))+import Data.Map.Strict (Map)++newtype ComponentName =+ ComponentName String+ deriving (Eq, Ord)++data Error =+ Error {+ errorTimestamp :: Int,+ errorMessage :: [String]+ }++newtype Errors =+ Errors (Map ComponentName [Error])++instance Default Errors where+ def = Errors Map.empty
+ lib/Ribosome/Data/Maybe.hs view
@@ -0,0 +1,7 @@+module Ribosome.Data.Maybe(+ orElse,+) where++orElse :: Maybe a -> Maybe a -> Maybe a+orElse fallback Nothing = fallback+orElse _ a = a
+ lib/Ribosome/Data/Ribo.hs view
@@ -0,0 +1,26 @@+module Ribosome.Data.Ribo(+ Ribo,+ state,+ inspect,+ modify,+) where++import Control.Concurrent.STM.TVar (modifyTVar)+import UnliftIO.STM (TVar, atomically, readTVarIO)+import Neovim (Neovim, ask)+import Ribosome.Data.Ribosome++type Ribo e = Neovim (Ribosome e)++state :: Ribo (TVar e) e+state = do+ Ribosome _ t <- ask+ readTVarIO t++inspect :: (e -> a) -> Ribo (TVar e) a+inspect f = fmap f state++modify :: (e -> e) -> Ribo (TVar e) ()+modify f = do+ Ribosome _ t <- ask+ atomically $ modifyTVar t f
+ lib/Ribosome/Data/Ribosome.hs view
@@ -0,0 +1,18 @@+module Ribosome.Data.Ribosome(+ Ribosome (..),+ newRibosome,+) where++import UnliftIO.STM (TVar, newTVarIO)+import Control.Monad.IO.Class (MonadIO)++data Ribosome e =+ Ribosome {+ name :: String,+ env :: e+ }++newRibosome :: MonadIO m => String -> e -> m (Ribosome (TVar e))+newRibosome name' env' = do+ tv <- newTVarIO env'+ return $ Ribosome name' tv
+ lib/Ribosome/Internal/IO.hs view
@@ -0,0 +1,25 @@+module Ribosome.Internal.IO(+ retypeNeovim,+ forkNeovim,+) where++import GHC.Conc.Sync (forkIO)+import Control.Monad.IO.Class (liftIO)+import Control.Monad.Reader (ask, runReaderT, withReaderT)+import Control.Monad.Trans.Resource (runResourceT)+import Data.Functor (void)+import Neovim.Context.Internal (Neovim(..), Config(..), retypeConfig, runNeovim)++-- try using Contravariant with this+retypeNeovim :: (e0 -> e1) -> Neovim e1 a -> Neovim e0 a+retypeNeovim transform thunk = do+ env <- Neovim ask+ liftIO $ runReaderT (withReaderT (newEnv env) $ runResourceT $ unNeovim thunk) env+ where+ newEnv = retypeConfig . transform . customConfig++forkNeovim :: Neovim e () -> Neovim e ()+forkNeovim thunk = do+ env <- Neovim ask+ _ <- liftIO $ forkIO $ void $ runNeovim env thunk+ return ()
+ lib/Ribosome/Internal/NvimObject.hs view
@@ -0,0 +1,8 @@+module Ribosome.Internal.NvimObject(+ deriveString,+) where++import Neovim (Object, Doc, AnsiStyle, fromObject)++deriveString :: (String -> a) -> Object -> Either (Doc AnsiStyle) a+deriveString cons o = fmap cons ((fromObject o) :: Either (Doc AnsiStyle) String)
+ lib/Ribosome/Log.hs view
@@ -0,0 +1,14 @@+module Ribosome.Log(+ debug,+ info,+) where++import Control.Monad.IO.Class (liftIO)+import Neovim.Log (debugM, infoM)+import Ribosome.Data.Ribo (Ribo)++debug :: Show a => String -> a -> Ribo e ()+debug name message = liftIO $ debugM name $ show message++info :: Show a => String -> a -> Ribo e ()+info name message = liftIO $ infoM name $ show message
+ lib/Ribosome/Test/Embed.hs view
@@ -0,0 +1,47 @@+module Ribosome.Test.Embed(+ defaultTestConfig,+ defaultTestConfigWith,+ TestConfig (..),+ Vars(..),+ unsafeEmbeddedSpec,+ setVars,+ setupPluginEnv,+) where++import Data.Foldable (traverse_)+import Neovim (Neovim, Object, vim_set_var')+import Neovim.Test (testWithEmbeddedNeovim, Seconds(..))+import Ribosome.Data.Ribo (Ribo)+import Ribosome.Data.Ribosome (Ribosome(Ribosome))+import Ribosome.Api.Option (rtpCat)++type Runner env = TestConfig -> Neovim env () -> Neovim env ()++newtype Vars = Vars [(String, Object)]++data TestConfig =+ TestConfig {+ pluginName :: String,+ extraRtp :: String,+ logPath :: FilePath,+ variables :: Vars+ }++defaultTestConfigWith :: String -> Vars -> TestConfig+defaultTestConfigWith name = TestConfig name "test/f/fixtures/rtp" "test/f/temp/log"++defaultTestConfig :: String -> TestConfig+defaultTestConfig name = defaultTestConfigWith name (Vars [])++setVars :: Vars -> Neovim e ()+setVars (Vars vars) =+ traverse_ (uncurry vim_set_var') vars++setupPluginEnv :: TestConfig -> Neovim e ()+setupPluginEnv (TestConfig _ rtp _ vars) = do+ rtpCat rtp+ setVars vars++unsafeEmbeddedSpec :: Runner (Ribosome e) -> TestConfig -> e -> Ribo e () -> IO ()+unsafeEmbeddedSpec runner conf env spec =+ testWithEmbeddedNeovim Nothing (Seconds 5) (Ribosome (pluginName conf) env) $ runner conf spec
+ lib/Ribosome/Test/Exists.hs view
@@ -0,0 +1,44 @@+module Ribosome.Test.Exists(+ waitForPlugin,+ sleep,+) where++import Data.Time.Clock.POSIX+import Data.Strings (strCapitalize)+import Control.Monad.IO.Class+import Control.Concurrent (threadDelay)+import Neovim++epochSeconds :: MonadIO f => f Int+epochSeconds = liftIO $ fmap round getPOSIXTime++sleep :: MonadIO f => Double -> f ()+sleep seconds = liftIO $ threadDelay $ round $ seconds * 10e6++retry :: MonadIO f => Double -> Int -> f a -> (a -> f (Either String b)) -> f b+retry interval timeout thunk check = do+ start <- epochSeconds+ step start+ where+ step start = do+ result <- thunk+ checked <- check result+ recurse start checked+ recurse _ (Right b) = return b+ recurse start (Left e) = do+ current <- epochSeconds+ if (current - start) < timeout+ then do+ sleep interval+ step start+ else fail e++waitForPlugin :: String -> Double -> Int -> Neovim env ()+waitForPlugin name interval timeout = do+ retry interval timeout thunk check+ where+ thunk = vim_call_function "exists" [toObject $ "*" ++ (strCapitalize name) ++ "Poll"]+ check (Right (ObjectInt 1)) = return $ Right ()+ check (Right a) = return $ Left $ errormsg ++ "weird return type " ++ (show a)+ check (Left e) = return $ Left $ errormsg ++ (show e)+ errormsg = "plugin didn't start within " ++ (show timeout) ++ " seconds: "
+ lib/Ribosome/Test/File.hs view
@@ -0,0 +1,27 @@+module Ribosome.Test.File(+ tempDirIO,+ tempDir,+) where++import Control.Monad.IO.Class (liftIO)+import Neovim (Neovim)+import System.Directory (canonicalizePath, createDirectoryIfMissing, removePathForcibly)+import System.FilePath ((</>))++testDir :: String -> IO FilePath+testDir prefix = canonicalizePath $ "test" </> prefix++-- raises exception if cwd is not the package root so we don't damage anything+tempDirIO :: String -> FilePath -> IO FilePath+tempDirIO prefix path = do+ base <- testDir prefix+ let dir = base </> "temp"+ removePathForcibly dir+ createDirectoryIfMissing False dir+ let absPath = dir </> path+ createDirectoryIfMissing True absPath+ return absPath++tempDir :: String -> FilePath -> Neovim e FilePath+tempDir prefix path =+ liftIO $ tempDirIO prefix path
+ lib/Ribosome/Test/Functional.hs view
@@ -0,0 +1,60 @@+module Ribosome.Test.Functional(+ startPlugin,+ fSpec,+ functionalSpec,+) where++import Control.Monad (when)+import Control.Monad.IO.Class+import Control.Exception (finally)+import Data.Foldable (traverse_)+import System.Directory (getCurrentDirectory, createDirectoryIfMissing, removePathForcibly, doesFileExist)+import System.FilePath (takeDirectory)+import System.Console.ANSI (setSGR, SGR(SetColor, Reset), ConsoleLayer(Foreground), ColorIntensity(Dull), Color(Green))+import Neovim (Neovim, vim_command')+import Ribosome.Data.Ribo (Ribo)+import Ribosome.Test.Exists (waitForPlugin)+import Ribosome.Test.Embed (TestConfig(..), unsafeEmbeddedSpec, setupPluginEnv)++jobstart :: MonadIO f => String -> f String+jobstart cmd = do+ dir <- liftIO getCurrentDirectory+ return $ "call jobstart('" ++ cmd ++ "', { 'rpc': v:true, 'cwd': '" ++ dir ++ "' })"++logFile :: TestConfig -> FilePath+logFile conf = logPath conf ++ "-spec"++startPlugin :: TestConfig -> Neovim env ()+startPlugin conf = do+ liftIO $ createDirectoryIfMissing True (takeDirectory (logPath conf))+ liftIO $ removePathForcibly (logFile conf)+ setupPluginEnv conf+ cmd <- jobstart $ "stack run -- -l " ++ logFile conf ++ " -v INFO"+ vim_command' cmd+ waitForPlugin (pluginName conf) 0.1 3++fSpec :: TestConfig -> Neovim env () -> Neovim env ()+fSpec conf spec = startPlugin conf >> spec++showLog' :: String -> IO ()+showLog' output = do+ putStrLn ""+ setSGR [SetColor Foreground Dull Green]+ putStrLn "plugin output:"+ setSGR [Reset]+ traverse_ putStrLn (lines output)+ putStrLn ""++showLog :: TestConfig -> IO ()+showLog conf = do+ let file = logFile conf+ exists <- doesFileExist file+ when exists $ do+ output <- readFile file+ case output of+ [] -> return ()+ o -> showLog' o++functionalSpec :: TestConfig -> Ribo () () -> IO ()+functionalSpec conf spec =+ finally (unsafeEmbeddedSpec fSpec conf () spec) (showLog conf)
+ lib/Ribosome/Test/Unit.hs view
@@ -0,0 +1,32 @@+module Ribosome.Test.Unit(+ unitSpec,+ tempDir,+ tempFile,+ uPrefix,+) where++import System.FilePath (takeDirectory, takeFileName, (</>))+import Neovim (Neovim)+import Ribosome.Data.Ribo (Ribo)+import Ribosome.Test.Embed (TestConfig(..), setupPluginEnv, unsafeEmbeddedSpec)+import qualified Ribosome.Test.File as F (tempDir)++uPrefix :: String+uPrefix = "u"++uSpec :: TestConfig -> Neovim env () -> Neovim env ()+uSpec conf spec = do+ setupPluginEnv conf+ spec++unitSpec :: TestConfig -> e -> Ribo e () -> IO ()+unitSpec =+ unsafeEmbeddedSpec uSpec++tempDir :: FilePath -> Neovim e FilePath+tempDir = F.tempDir uPrefix++tempFile :: FilePath -> Neovim e FilePath+tempFile file = do+ absDir <- tempDir $ takeDirectory file+ return $ absDir </> takeFileName file
− nvim.hs
@@ -1,6 +0,0 @@-import Neovim--import Proteome.Plugin (plugin)--main :: IO ()-main = neovim defaultConfig {plugins = [plugin]}
proteome.cabal view
@@ -1,28 +1,205 @@-name: proteome-version: 0.1.0.0-synopsis: neovim project manager-description: neovim plugin for managing project-specific configuration and performing runtime tasks on projects-license: MIT-license-file: LICENSE-author: Torsten Schmits-maintainer: tek@tryp.io-copyright: 2018 Torsten Schmits-category: Neovim-build-type: Simple-extra-source-files: README.md-cabal-version: >=1.10-x-curation: uncurated-no-trustee-contact+cabal-version: 1.12 -executable proteome- main-is: nvim.hs+-- This file has been generated from package.yaml by hpack version 0.31.0.+--+-- see: https://github.com/sol/hpack+--+-- hash: aeb4f9fc4dda14d1efb906445e7ff9e84fd39b5cf2bcf984c395b23c604c14fb++name: proteome+version: 0.2.0.0+synopsis: neovim project manager+description: Please see the README on GitHub at <https://github.com/tek/proteome-hs>+category: Neovim+homepage: https://github.com/tek/proteome-hs#readme+bug-reports: https://github.com/tek/proteome-hs/issues+author: Torsten Schmits+maintainer: tek@tryp.io+copyright: 2018 Torsten Schmits+license: MIT+license-file: LICENSE+build-type: Simple+extra-source-files:+ README.md++source-repository head+ type: git+ location: https://github.com/tek/proteome-hs++library+ exposed-modules:+ Proteome.Add+ Proteome.Config+ Proteome.Data.Env+ Proteome.Data.Project+ Proteome.Data.ProjectSpec+ Proteome.Data.Proteome+ Proteome.Init+ Proteome.Log+ Proteome.Plugin+ Proteome.Project.Resolve+ Proteome.Save+ Proteome.Settings+ Proteome.Tags+ Proteome.Test.Config+ Proteome.Test.Functional+ Proteome.Test.Unit+ Ribosome.Api.Option+ Ribosome.Api.Response+ Ribosome.Config.Settings+ Ribosome.Data.Errors+ Ribosome.Data.Maybe+ Ribosome.Data.Ribo+ Ribosome.Data.Ribosome+ Ribosome.Internal.IO+ Ribosome.Internal.NvimObject+ Ribosome.Log+ Ribosome.Test.Embed+ Ribosome.Test.Exists+ Ribosome.Test.File+ Ribosome.Test.Functional+ Ribosome.Test.Unit+ other-modules:+ Paths_proteome hs-source-dirs:- .,- lib+ lib+ build-depends:+ MissingH+ , ansi-terminal+ , base >=4.7 && <5+ , containers+ , data-default-class+ , deepseq+ , directory+ , filepath+ , hslogger+ , lens+ , messagepack+ , mtl+ , nvim-hs+ , pretty-terminal+ , prettyprinter+ , process+ , resourcet+ , split+ , stm+ , strings+ , text+ , time+ , unliftio+ , utf8-string+ default-language: Haskell2010++executable proteome-exe+ main-is: Main.hs other-modules:- Proteome.Plugin,- Proteome.Init,- Proteome.Add+ Paths_proteome+ hs-source-dirs:+ app+ ghc-options: -threaded -rtsopts -with-rtsopts=-N build-depends:- base >= 4.7 && < 5,- nvim-hs >= 1 && < 2+ MissingH+ , ansi-terminal+ , base >=4.7 && <5+ , containers+ , data-default-class+ , deepseq+ , directory+ , filepath+ , hslogger+ , lens+ , messagepack+ , mtl+ , nvim-hs+ , pretty-terminal+ , prettyprinter+ , process+ , proteome+ , resourcet+ , split+ , stm+ , strings+ , text+ , time+ , unliftio+ , utf8-string+ default-language: Haskell2010++test-suite proteome-functional+ type: exitcode-stdio-1.0+ main-is: SpecMain.hs+ other-modules:+ Config+ ConfigSpec+ InitSpec+ Paths_proteome+ hs-source-dirs:+ test/f+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ HTF+ , MissingH+ , ansi-terminal+ , base >=4.7 && <5+ , containers+ , data-default-class+ , deepseq+ , directory+ , filepath+ , hslogger+ , lens+ , messagepack+ , mtl+ , nvim-hs+ , pretty-terminal+ , prettyprinter+ , process+ , proteome+ , resourcet+ , split+ , stm+ , strings+ , text+ , time+ , unliftio+ , utf8-string+ default-language: Haskell2010++test-suite proteome-unit+ type: exitcode-stdio-1.0+ main-is: SpecMain.hs+ other-modules:+ Config+ TagsSpec+ Paths_proteome+ hs-source-dirs:+ test/u+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends:+ HTF+ , MissingH+ , ansi-terminal+ , base >=4.7 && <5+ , containers+ , data-default-class+ , deepseq+ , directory+ , filepath+ , hslogger+ , lens+ , messagepack+ , mtl+ , nvim-hs+ , pretty-terminal+ , prettyprinter+ , process+ , proteome+ , resourcet+ , split+ , stm+ , strings+ , text+ , time+ , unliftio+ , utf8-string default-language: Haskell2010
+ test/f/Config.hs view
@@ -0,0 +1,15 @@+module Config(+ vars,+) where++import Neovim (toObject)+import System.Directory (getCurrentDirectory)+import Ribosome.Test.Embed (Vars(..))++vars :: IO Vars+vars = do+ base <- getCurrentDirectory+ return $ Vars [+ ("proteome_project_base_dirs", toObject [base ++ "/test/f/fixtures/config/projects"]),+ ("proteome_main_project_dir", toObject $ base ++ "/test/f/fixtures/config/projects/haskell/flagellum")+ ]
+ test/f/ConfigSpec.hs view
@@ -0,0 +1,24 @@+{-# OPTIONS_GHC -F -pgmF htfpp #-}++module ConfigSpec(+ htf_thisModulesTests+) where++import Control.Monad.IO.Class (liftIO)+import Test.Framework+import Data.MessagePack (Object(ObjectInt))+import Neovim (vim_call_function, vim_get_var')+import Ribosome.Data.Ribo (Ribo)+import Proteome.Test.Functional (specWith)+import Config (vars)++configSpec :: Ribo env ()+configSpec = do+ _ <- vim_call_function "ProReadConfig" []+ value <- vim_get_var' "flag"+ liftIO $ assertEqual value (ObjectInt 1)++test_config :: IO ()+test_config = do+ v <- vars+ specWith v configSpec
+ test/f/InitSpec.hs view
@@ -0,0 +1,26 @@+{-# OPTIONS_GHC -F -pgmF htfpp #-}++module InitSpec(+ htf_thisModulesTests+) where++import Control.Monad.IO.Class (liftIO)+import Test.Framework+import Ribosome.Data.Ribo (Ribo)+import Ribosome.Config.Settings (setting)+import qualified Proteome.Settings as S+import Proteome.Data.Project (ProjectName(ProjectName), ProjectType(ProjectType))+import Proteome.Test.Functional (specWith)+import Config (vars)++initSpec :: Ribo env ()+initSpec = do+ tpe <- setting S.mainType+ name <- setting S.mainName+ liftIO $ assertEqual name (ProjectName "flagellum")+ liftIO $ assertEqual tpe (ProjectType "haskell")++test_init :: IO ()+test_init = do+ v <- vars+ specWith v initSpec
+ test/f/SpecMain.hs view
@@ -0,0 +1,12 @@+{-# OPTIONS_GHC -F -pgmF htfpp #-}++module Main where++import {-@ HTF_TESTS @-} ConfigSpec+import {-@ HTF_TESTS @-} InitSpec+import Test.Framework+import Test.Framework.BlackBoxTest ()++main :: IO ()+main = do+ htfMain htf_importedTests
+ test/u/Config.hs view
@@ -0,0 +1,15 @@+module Config(+ vars,+) where++import Neovim (toObject)+import System.Directory (getCurrentDirectory)+import Ribosome.Test.Embed (Vars(..))++vars :: IO Vars+vars = do+ base <- getCurrentDirectory+ return $ Vars [+ ("proteome_project_base_dirs", toObject [base ++ "/test/u/fixtures/projects"]),+ ("proteome_main_project_dir", toObject $ base ++ "/test/u/fixtures/projects/haskell/flagellum")+ ]
+ test/u/SpecMain.hs view
@@ -0,0 +1,10 @@+{-# OPTIONS_GHC -F -pgmF htfpp #-}++module Main where++import {-@ HTF_TESTS @-} TagsSpec+import Test.Framework+import Test.Framework.BlackBoxTest ()++main :: IO ()+main = htfMain htf_importedTests
+ test/u/TagsSpec.hs view
@@ -0,0 +1,48 @@+{-# OPTIONS_GHC -F -pgmF htfpp #-}++module TagsSpec(+ htf_thisModulesTests+) where++import Control.Monad.IO.Class (liftIO)+import Control.Lens (set)+import System.FilePath ((</>))+import System.Directory (doesFileExist)+import Test.Framework+import Ribosome.Config.Settings (updateSetting)+import qualified Ribosome.Data.Ribo as Ribo (modify)+import Ribosome.Test.Unit (tempDir)+import Proteome.Data.Proteome (Proteome)+import Proteome.Data.Env (_mainProject)+import Proteome.Data.Project (+ ProjectName(..),+ ProjectRoot(..),+ ProjectType(..),+ ProjectLang(..),+ ProjectMetadata(DirProject),+ _meta,+ _lang,+ )+import qualified Proteome.Settings as S (tagsCommand, tagsArgs, tagsFork)+import Proteome.Tags (proTags)+import Proteome.Test.Unit (specWithDef)+import Config (vars)++main :: FilePath -> ProjectMetadata+main root = DirProject (ProjectName "flagellum") (ProjectRoot root) (Just (ProjectType "haskell"))++tagsSpec :: Proteome ()+tagsSpec = do+ root <- tempDir "projects/haskell/flagellum"+ Ribo.modify $ set (_mainProject._meta) (main root)+ Ribo.modify $ set (_mainProject._lang) (Just (ProjectLang "idris"))+ updateSetting S.tagsCommand "touch"+ updateSetting S.tagsArgs "tags-{langsComma}-{tagFile}"+ updateSetting S.tagsFork False+ proTags+ let tagsFile = root </> "tags-idris-.tags"+ exists <- liftIO $ doesFileExist tagsFile+ liftIO $ assertBool exists++test_tags :: IO ()+test_tags = vars >>= specWithDef tagsSpec