packages feed

chromatin (empty) → 0.1.0.0

raw patch · 41 files changed

+1382/−0 lines, 41 filesdep +Globdep +HTFdep +basesetup-changed

Dependencies added: Glob, HTF, base, bytestring, chromatin, conduit, containers, data-default-class, deepseq, directory, filepath, hslogger, lens, messagepack, nvim-hs, parsec, prettyprinter, resourcet, ribosome, split, stm-chans, stm-conduit, transformers, typed-process, unliftio

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Author name here (c) 2018++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Author name here nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,1 @@+# chromatin
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ app/Main.hs view
@@ -0,0 +1,6 @@+import Neovim++import Chromatin.Plugin (plugin)++main :: IO ()+main = neovim defaultConfig {plugins = [plugin]}
+ chromatin.cabal view
@@ -0,0 +1,199 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.31.1.+--+-- see: https://github.com/sol/hpack+--+-- hash: 560b0a26d65a7e63d7c566631d1a3e83822116adb9958225a42bbb595604065f++name:           chromatin+version:        0.1.0.0+synopsis:       neovim package manager+description:    Please see the README on GitHub at <https://github.com/tek/chromatin-hs>+category:       Neovim+homepage:       https://github.com/tek/chromatin-hs#readme+bug-reports:    https://github.com/tek/chromatin-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/chromatin-hs++library+  exposed-modules:+      Chromatin.Config+      Chromatin.Data.ActiveRplugin+      Chromatin.Data.Chromatin+      Chromatin.Data.Env+      Chromatin.Data.InstallResult+      Chromatin.Data.RebuildControl+      Chromatin.Data.RebuildTask+      Chromatin.Data.Rplugin+      Chromatin.Data.RpluginConfig+      Chromatin.Data.RpluginName+      Chromatin.Data.Rplugins+      Chromatin.Data.RpluginSource+      Chromatin.Data.RpluginState+      Chromatin.Data.RunBuiltResult+      Chromatin.Data.RunExistingResult+      Chromatin.Diag+      Chromatin.Init+      Chromatin.Log+      Chromatin.Plugin+      Chromatin.Rebuild+      Chromatin.Rebuild.Build+      Chromatin.Rebuild.Existing+      Chromatin.Rebuild.Nonexisting+      Chromatin.Run+      Chromatin.Settings+      Chromatin.Test.Config+      Chromatin.Test.Unit+      Chromatin.Unload+  other-modules:+      Paths_chromatin+  hs-source-dirs:+      lib+  build-depends:+      Glob+    , base >=4.7 && <5+    , bytestring+    , conduit+    , containers+    , data-default-class+    , deepseq+    , directory+    , filepath+    , hslogger+    , lens+    , messagepack+    , nvim-hs+    , parsec+    , prettyprinter+    , resourcet+    , ribosome+    , split+    , stm-chans+    , stm-conduit+    , transformers+    , typed-process+    , unliftio+  default-language: Haskell2010++executable chromatin+  main-is: Main.hs+  other-modules:+      Paths_chromatin+  hs-source-dirs:+      app+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      Glob+    , base >=4.7 && <5+    , bytestring+    , chromatin+    , conduit+    , containers+    , data-default-class+    , deepseq+    , directory+    , filepath+    , hslogger+    , lens+    , messagepack+    , nvim-hs+    , parsec+    , prettyprinter+    , resourcet+    , ribosome+    , split+    , stm-chans+    , stm-conduit+    , transformers+    , typed-process+    , unliftio+  default-language: Haskell2010++test-suite chromatin-functional+  type: exitcode-stdio-1.0+  main-is: SpecMain.hs+  other-modules:+      Paths_chromatin+  hs-source-dirs:+      test/f+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      Glob+    , HTF+    , base >=4.7 && <5+    , bytestring+    , chromatin+    , conduit+    , containers+    , data-default-class+    , deepseq+    , directory+    , filepath+    , hslogger+    , lens+    , messagepack+    , nvim-hs+    , parsec+    , prettyprinter+    , resourcet+    , ribosome+    , split+    , stm-chans+    , stm-conduit+    , transformers+    , typed-process+    , unliftio+  default-language: Haskell2010++test-suite chromatin-unit+  type: exitcode-stdio-1.0+  main-is: SpecMain.hs+  other-modules:+      BuildSpec+      Config+      ConfigSpec+      DiagSpec+      RebuildSpec+      RunSpec+      Paths_chromatin+  hs-source-dirs:+      test/u+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      Glob+    , HTF+    , base >=4.7 && <5+    , bytestring+    , chromatin+    , conduit+    , containers+    , data-default-class+    , deepseq+    , directory+    , filepath+    , hslogger+    , lens+    , messagepack+    , nvim-hs+    , parsec+    , prettyprinter+    , resourcet+    , ribosome+    , split+    , stm-chans+    , stm-conduit+    , transformers+    , typed-process+    , unliftio+  default-language: Haskell2010
+ lib/Chromatin/Config.hs view
@@ -0,0 +1,95 @@+module Chromatin.Config(+  readConfig,+  analyzeConfig,+  RpluginModification(..),+  analyzeConfigIO,+) where++import Data.Maybe (fromMaybe)+import Data.Foldable (find)+import Text.ParserCombinators.Parsec+import System.FilePath (takeFileName)+import qualified Ribosome.Control.Ribo as Ribo (inspect)+import Ribosome.Config.Setting (setting)+import Chromatin.Data.Chromatin (Chromatin)+import qualified Chromatin.Data.Env as Env (rplugins)+import Chromatin.Data.Rplugin (Rplugin(Rplugin))+import Chromatin.Data.RpluginName (RpluginName(RpluginName))+import Chromatin.Data.RpluginSource (RpluginSource(..), HackageDepspec(HackageDepspec), PypiDepspec(PypiDepspec))+import Chromatin.Data.Rplugins (Rplugins(Rplugins))+import Chromatin.Data.RpluginConfig (RpluginConfig(RpluginConfig))+import qualified Chromatin.Settings as S (rplugins)++readConfig :: Chromatin Rplugins+readConfig = setting S.rplugins++data RpluginModification =+  RpluginNew RpluginName RpluginSource+  |+  RpluginRemove Rplugin+  |+  RpluginUpdate Rplugin RpluginSource+  |+  RpluginKeep Rplugin+  deriving (Eq, Show)++data ParsedSpec =+  PrefixedSpec String String+  |+  PlainSpec String++parsePrefixed :: GenParser Char st ParsedSpec+parsePrefixed = do+  prefix <- many $ noneOf ":"+  _ <- char ':'+  spec <- many anyChar+  return $ PrefixedSpec prefix spec++specParser :: GenParser Char st ParsedSpec+specParser = try parsePrefixed <|> fmap PlainSpec (many anyChar)++parseSpec :: String -> Either ParseError ParsedSpec+parseSpec = parse specParser "none"++sourceFromSpec :: String -> Either String RpluginSource+sourceFromSpec spec =+  case parseSpec spec of+    Right (PrefixedSpec prefix spec') -> case prefix of+      "pip" -> Right $ Pypi (PypiDepspec spec')+      "hackage" -> Right $ Hackage (HackageDepspec spec')+      "stack" -> Right $ Stack spec'+      a -> Left $ "unknown rplugin prefix `" ++ a ++ "` in `" ++ spec ++ "`"+    Right (PlainSpec name') ->+      Right $ Hackage (HackageDepspec name')+    Left _ -> Left $ "failed to parse `" ++ spec ++ "`"++rpluginHasName :: RpluginName -> Rplugin -> Bool+rpluginHasName target (Rplugin name _) = target == name++nameFromSource :: RpluginSource -> RpluginName+nameFromSource (Hackage (HackageDepspec n)) = RpluginName n+nameFromSource (Stack fp) = RpluginName (takeFileName fp)+nameFromSource (Pypi (PypiDepspec n)) = RpluginName n++modifyExisting :: RpluginSource -> Rplugin -> RpluginModification+modifyExisting _ _ = undefined++modification :: [Rplugin] -> RpluginConfig -> Either String RpluginModification+modification current (RpluginConfig spec explicitName) = do+  source <- sourceFromSpec spec+  let name = fromMaybe (nameFromSource source) explicitName+  let sameName = find (rpluginHasName name) current+  return $ maybe (RpluginNew name source) (modifyExisting source) sameName++removals :: [RpluginModification] -> [RpluginModification]+removals _ = []++analyzeConfig :: [Rplugin] -> Rplugins -> Either String [RpluginModification]+analyzeConfig current (Rplugins rplugins) = do+  let mods = traverse (modification current) rplugins+  fmap (\m -> m ++ removals m) mods++analyzeConfigIO :: Rplugins -> Chromatin (Either String [RpluginModification])+analyzeConfigIO rplugins = do+  current <- Ribo.inspect Env.rplugins+  return $ analyzeConfig current rplugins
+ lib/Chromatin/Data/ActiveRplugin.hs view
@@ -0,0 +1,12 @@+module Chromatin.Data.ActiveRplugin(+  ActiveRplugin(..),+) where++import Chromatin.Data.Rplugin (Rplugin)++data ActiveRplugin =+  ActiveRplugin {+    arChannelId :: Int,+    arRplugin :: Rplugin+  }+  deriving (Show, Eq)
+ lib/Chromatin/Data/Chromatin.hs view
@@ -0,0 +1,9 @@+module Chromatin.Data.Chromatin(+  Chromatin,+) where++import UnliftIO.STM (TVar)+import Ribosome.Control.Ribo (Ribo)+import Chromatin.Data.Env (Env)++type Chromatin a = Ribo (TVar Env) a
+ lib/Chromatin/Data/Env.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE TemplateHaskell #-}++module Chromatin.Data.Env(+  Env(..),+  _rplugins,+  _errors,+  _installerChan,+) where++import Control.Concurrent.STM.TBMChan (TBMChan)+import Control.Lens (makeClassy_)+import Data.Default.Class (Default(def))+import Ribosome.Data.Errors (Errors)+import Chromatin.Data.Rplugin (Rplugin)+import Chromatin.Data.RebuildControl (RebuildControl)++data Env =+  Env {+    rplugins :: [Rplugin],+    errors :: Errors,+    installerChan :: Maybe (TBMChan RebuildControl)+  }++makeClassy_ ''Env++instance Default Env where+  def = Env def def def
+ lib/Chromatin/Data/InstallResult.hs view
@@ -0,0 +1,14 @@+module Chromatin.Data.InstallResult(+  InstallResult(..),+) where++import Chromatin.Data.Rplugin (Rplugin)+import Chromatin.Data.RebuildTask (RebuildTask)++data InstallResult =+  Success Rplugin+  |+  Failure RebuildTask+  |+  PreviousFailure String RebuildTask+  deriving Show
+ lib/Chromatin/Data/RebuildControl.hs view
@@ -0,0 +1,11 @@+module Chromatin.Data.RebuildControl(+  RebuildControl(..),+) where++import Chromatin.Data.RebuildTask (RebuildTask)++data RebuildControl =+  Continue RebuildTask+  |+  Stop+  deriving Show
+ lib/Chromatin/Data/RebuildTask.hs view
@@ -0,0 +1,10 @@+module Chromatin.Data.RebuildTask(+  RebuildTask(..),+) where++import Chromatin.Data.RpluginName (RpluginName)+import Chromatin.Data.RpluginSource (RpluginSource)++data RebuildTask =+  RebuildTask RpluginName RpluginSource+  deriving Show
+ lib/Chromatin/Data/Rplugin.hs view
@@ -0,0 +1,13 @@+module Chromatin.Data.Rplugin(+  Rplugin(..),+) where++import Chromatin.Data.RpluginName (RpluginName)+import Chromatin.Data.RpluginSource (RpluginSource)++data Rplugin =+  Rplugin {+    name :: RpluginName,+    source :: RpluginSource+  }+  deriving (Show, Eq)
+ lib/Chromatin/Data/RpluginConfig.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}++module Chromatin.Data.RpluginConfig(+  RpluginConfig(..),+) where++import GHC.Generics (Generic)+import qualified Data.Map as Map (fromList)+import Data.Text.Prettyprint.Doc ((<+>), viaShow)+import Control.DeepSeq (NFData)+import Neovim (NvimObject(..), Dictionary, Object(ObjectMap))+import Ribosome.Internal.NvimObject (extractObject)+import Chromatin.Data.RpluginName (RpluginName)++data RpluginConfig =+  RpluginConfig {+    rpluginConfigSpec :: String,+    rpluginConfigName :: Maybe RpluginName+  }+  deriving (Show, Generic, NFData)++instance NvimObject RpluginConfig where+  toObject RpluginConfig {..} =+    (toObject :: Dictionary -> Object) . Map.fromList $+    [+      ("spec", toObject rpluginConfigSpec),+      ("name", toObject rpluginConfigName)+    ]+  fromObject (ObjectMap o) = do+    spec' <- extractObject "spec" o+    name' <- extractObject "name" o+    return $ RpluginConfig spec' name'+  fromObject o = Left ("invalid type for RpluginConfig: " <+> viaShow o)
+ lib/Chromatin/Data/RpluginName.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-}++module Chromatin.Data.RpluginName(+  RpluginName(..),+) where++import GHC.Generics (Generic)+import Control.DeepSeq (NFData)+import Neovim.Classes (NvimObject(..))+import Ribosome.Internal.NvimObject (deriveString)++newtype RpluginName = RpluginName String+  deriving (Eq, Show, Generic, NFData)++instance NvimObject RpluginName where+  toObject (RpluginName s) = toObject s+  fromObject = deriveString RpluginName
+ lib/Chromatin/Data/RpluginSource.hs view
@@ -0,0 +1,27 @@+module Chromatin.Data.RpluginSource(+  HackageDepspec(..),+  PypiDepspec(..),+  RpluginSource(..),+) where++newtype HackageDepspec =+  HackageDepspec String+  deriving (Show, Eq)++newtype PypiDepspec =+  PypiDepspec String+  deriving (Show, Eq)++data RpluginSource =+  Hackage {+    hackageSpec :: HackageDepspec+  }+  |+  Stack {+    stackProject :: FilePath+  }+  |+  Pypi {+    pypiSpec :: PypiDepspec+  }+  deriving (Show, Eq)
+ lib/Chromatin/Data/RpluginState.hs view
@@ -0,0 +1,11 @@+module Chromatin.Data.RpluginState(+  RpluginState(..),+) where++data RpluginState =+  Broken String+  |+  Ready+  |+  Incomplete+  deriving Show
+ lib/Chromatin/Data/Rplugins.hs view
@@ -0,0 +1,20 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-}++module Chromatin.Data.Rplugins(+  Rplugins(..),+) where++import GHC.Generics (Generic)+import Data.Default.Class (Default)+import Control.DeepSeq (NFData)+import Neovim.Classes (NvimObject(..))+import Chromatin.Data.RpluginConfig (RpluginConfig)++newtype Rplugins =+  Rplugins [RpluginConfig]+  deriving (Generic, NFData, Default)++instance NvimObject Rplugins where+  toObject (Rplugins cs) = toObject cs+  fromObject o = fmap Rplugins (fromObject o)
+ lib/Chromatin/Data/RunBuiltResult.hs view
@@ -0,0 +1,21 @@+module Chromatin.Data.RunBuiltResult(+  RunBuiltResult(..),+) where++import Chromatin.Data.ActiveRplugin (ActiveRplugin)+import Chromatin.Data.RebuildTask (RebuildTask)++data RunBuiltResult =+  Success ActiveRplugin+  |+  Failure {+    task :: RebuildTask,+    errors :: [String]+    }+  |+  PreviousFailure {+    stage :: String,+    task :: RebuildTask,+    errors :: [String]+  }+  deriving Show
+ lib/Chromatin/Data/RunExistingResult.hs view
@@ -0,0 +1,14 @@+module Chromatin.Data.RunExistingResult(+  RunExistingResult(..),+) where++import Chromatin.Data.ActiveRplugin (ActiveRplugin)+import Chromatin.Data.RebuildTask (RebuildTask)++data RunExistingResult =+  Success ActiveRplugin+  |+  Failure RebuildTask [String]+  |+  NotReady RebuildTask+  deriving Show
+ lib/Chromatin/Diag.hs view
@@ -0,0 +1,17 @@+module Chromatin.Diag(+  crmDiag,+) where++import Data.Functor (void)+import Neovim (CommandArguments)+import Ribosome.Data.ScratchOptions (defaultScratchOptions)+import Ribosome.Scratch (showInScratch)+import Chromatin.Data.Chromatin (Chromatin)++diagnostics :: Chromatin [String]+diagnostics = return ["Diagnostics", ""]++crmDiag :: CommandArguments -> Chromatin ()+crmDiag _ = do+  content <- diagnostics+  void $ showInScratch content (defaultScratchOptions "chromatin-diagnostics")
+ lib/Chromatin/Init.hs view
@@ -0,0 +1,26 @@+module Chromatin.Init(+  initialize,+) where++import Data.Default.Class (Default(def))+import System.Log.Logger (updateGlobalLogger, setLevel, Priority(ERROR))+import Control.Monad.IO.Class (liftIO)+import UnliftIO.STM (TVar)+import Neovim (Neovim)+import Neovim.Context.Internal (Config(customConfig), asks')+import Ribosome.Control.Ribosome (newRibosome, Ribosome)+import Ribosome.Internal.IO (retypeNeovim)+import Chromatin.Data.Chromatin (Chromatin)+import Chromatin.Data.Env (Env)+import Chromatin.Rebuild (crmRebuild)++initialize' :: Chromatin (Ribosome (TVar Env))+initialize' = do+  crmRebuild def+  asks' customConfig++initialize :: Neovim e (Ribosome (TVar Env))+initialize = do+  liftIO $ updateGlobalLogger "Neovim.Plugin" (setLevel ERROR)+  ribo <- newRibosome "chromatin" def+  retypeNeovim (const ribo) initialize'
+ lib/Chromatin/Log.hs view
@@ -0,0 +1,22 @@+module Chromatin.Log(+  debug,+  info,+  debugS,+  infoS,+  R.p,+) where++import Ribosome.Control.Ribo (Ribo)+import qualified Ribosome.Log as R (debug, info, p)++debug :: String -> Ribo e ()+debug = R.debug "chromatin"++info :: String -> Ribo e ()+info = R.info "chromatin"++debugS :: Show a => a -> Ribo e ()+debugS = R.debug "chromatin"++infoS :: Show a => a -> Ribo e ()+infoS = R.info "chromatin"
+ lib/Chromatin/Plugin.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE OverloadedStrings #-}++module Chromatin.Plugin(+  plugin,+)+where++import UnliftIO.STM (TVar)+import Neovim (+  Plugin(..),+  command',+  Neovim,+  StartupConfig,+  NeovimConfig,+  NeovimPlugin,+  wrapPlugin,+  )+import Ribosome.Control.Ribosome (Ribosome)+import Chromatin.Init (initialize)+import Chromatin.Data.Env (Env)+import Chromatin.Diag (crmDiag)+import Chromatin.Rebuild (crmRebuild)++plugin' :: Ribosome (TVar Env) -> Plugin (Ribosome (TVar Env))+plugin' env =+  Plugin {+    environment = env,+    exports = [+      $(command' 'crmDiag) [],+      $(command' 'crmRebuild) []+    ]+  }++plugin :: Neovim (StartupConfig NeovimConfig) NeovimPlugin+plugin = do+  env <- initialize+  wrapPlugin $ plugin' env
+ lib/Chromatin/Rebuild.hs view
@@ -0,0 +1,121 @@+module Chromatin.Rebuild(+  crmRebuild,+) where++import Conduit (ConduitT, (.|), runConduit, mapMC, sinkList, await, yield)+import Control.Concurrent.STM.TBMChan (TBMChan, newTBMChan, writeTBMChan, closeTBMChan)+import qualified Control.Lens as Lens (set)+import Control.Monad.Trans.Class (lift)+import Data.Conduit.TMChan (sourceTBMChan)+import Data.Foldable (traverse_)+import Data.Functor (void)+import Data.Void (Void)+import UnliftIO (atomically)+import UnliftIO.STM (TVar, STM)+import Neovim (CommandArguments)+import Ribosome.Control.Ribo (Ribo)+import qualified Ribosome.Control.Ribo as Ribo (inspect, modify)+import Ribosome.Data.ScratchOptions (defaultScratchOptions)+import Ribosome.Internal.IO (forkNeovim)+import Ribosome.Scratch (showInScratch)+import Chromatin.Data.Chromatin (Chromatin)+import Chromatin.Data.Env (Env)+import qualified Chromatin.Data.Env as Env (installerChan, _installerChan)+import Chromatin.Data.RebuildTask (RebuildTask(..))+import Chromatin.Data.RebuildControl (RebuildControl)+import qualified Chromatin.Data.RebuildControl as RebuildControl (RebuildControl(..))+import Chromatin.Data.RunExistingResult (RunExistingResult)+import Chromatin.Data.RunBuiltResult (RunBuiltResult)+import qualified Chromatin.Data.RunBuiltResult as RunBuiltResult (RunBuiltResult(..))+import Chromatin.Data.RpluginName (RpluginName(RpluginName))+import Chromatin.Data.RpluginSource (RpluginSource)+import Chromatin.Config (readConfig, analyzeConfigIO, RpluginModification(RpluginNew))+import Chromatin.Rebuild.Existing (handleExisting)+import Chromatin.Rebuild.Nonexisting (handleNonexisting)+import qualified Chromatin.Log as Log++mapMChan :: Chromatin a -> (TBMChan RebuildControl -> Chromatin a) -> Chromatin a+mapMChan fEmpty f = do+  storedChan <- Ribo.inspect Env.installerChan+  maybe fEmpty f storedChan++stopRebuilder :: Chromatin ()+stopRebuilder =+  mapMChan (return ()) $ \c -> do+    Ribo.modify $ Lens.set Env._installerChan Nothing+    atomically $ closeTBMChan c+    Log.debug "stopped installer conduit"++createChan :: STM (TBMChan RebuildControl)+createChan = newTBMChan 64++extractFailure :: RunBuiltResult -> [String]+extractFailure (RunBuiltResult.Failure (RebuildTask (RpluginName name) _) err) =+  ("error when runnning plugin `" ++ name ++ "`:") : err+extractFailure (RunBuiltResult.Success _) = []+extractFailure (RunBuiltResult.PreviousFailure stage (RebuildTask (RpluginName name) _) err) =+  ("error in stage `" ++ stage ++ "` for plugin `" ++ name ++ "`:") : err++controlC :: ConduitT RebuildControl RebuildTask (Ribo (TVar Env)) ()+controlC = do+  ctrl <- await+  case ctrl of+    Just RebuildControl.Stop -> lift stopRebuilder+    Just (RebuildControl.Continue task) -> yield task >> controlC+    Nothing -> controlC++handleExistingC :: ConduitT RebuildTask RunExistingResult (Ribo (TVar Env)) ()+handleExistingC = mapMC handleExisting++handleNonexistingC :: ConduitT RunExistingResult RunBuiltResult (Ribo (TVar Env)) ()+handleNonexistingC = mapMC handleNonexisting++rebuilder :: TBMChan RebuildControl -> ConduitT () Void (Ribo (TVar Env)) [RunBuiltResult]+rebuilder chan = sourceTBMChan chan+  .| controlC+  .| handleExistingC+  .| handleNonexistingC+  .| sinkList++runRebuilder :: TBMChan RebuildControl -> Chromatin ()+runRebuilder chan = do+  result <- runConduit $ rebuilder chan+  case concatMap extractFailure result of+    err@(_:_) -> void $ showInScratch err (defaultScratchOptions "chromatin-rebuild-error")+    _ -> return ()+  Log.debug $ "installer terminated: " ++ show result++forkRebuilder :: Chromatin (TBMChan RebuildControl)+forkRebuilder = do+  chan <- atomically createChan+  Ribo.modify $ Lens.set Env._installerChan (Just chan)+  forkNeovim $ runRebuilder chan+  return chan++enqueue :: RebuildControl -> TBMChan RebuildControl -> Chromatin ()+enqueue ctrl chan = atomically $ writeTBMChan chan ctrl++executeRpluginNew :: RpluginName -> RpluginSource -> Chromatin ()+executeRpluginNew name source = do+  chan <- mapMChan forkRebuilder return+  enqueue (RebuildControl.Continue (RebuildTask name source)) chan++executeModification :: RpluginModification -> Chromatin ()+executeModification (RpluginNew name source) = executeRpluginNew name source+executeModification _ = return ()++executeModifications :: [RpluginModification] -> Chromatin ()+executeModifications mods = do+  traverse_ executeModification mods+  mapMChan (return ()) (enqueue RebuildControl.Stop)++analysisError :: String -> Chromatin ()+analysisError _ = return ()++crmRebuild :: CommandArguments -> Chromatin ()+crmRebuild _ = do+  config <- readConfig+  analysis <- analyzeConfigIO config+  case analysis of+    Right mods -> executeModifications mods+    Left e -> analysisError e
+ lib/Chromatin/Rebuild/Build.hs view
@@ -0,0 +1,124 @@+module Chromatin.Rebuild.Build(+  installRplugin,+  InstallResult(..),+  venvDir,+) where++import Control.Monad.IO.Class (MonadIO)+import Data.List.Split (linesBy)+import GHC.IO.Exception (ExitCode(ExitFailure))+import GHC.IO.Handle.Types (Handle)+import qualified Data.ByteString.Lazy.Internal as B (unpackChars)+import System.FilePath ((</>))+import System.Process.Typed (ProcessConfig, setStdout, useHandleClose, readProcessStderr, proc, setWorkingDir)+import UnliftIO.Temporary (withSystemTempFile)+import UnliftIO.Directory (+  getXdgDirectory,+  XdgDirectory(XdgData, XdgCache),+  createDirectoryIfMissing,+  removePathForcibly,+  )+import Neovim (Buffer, vim_command', vim_get_current_buffer', vim_command, buffer_get_number')+import Ribosome.Api.Echo (echom)+import Chromatin.Data.Rplugin (Rplugin(Rplugin))+import Chromatin.Data.RpluginName (RpluginName(..))+import Chromatin.Data.RpluginSource (RpluginSource(Hackage, Stack, Pypi), HackageDepspec(..), PypiDepspec(..))+import Chromatin.Data.Chromatin (Chromatin)++data InstallResult =+  Success Rplugin+  |+  Failure [String]+  deriving (Show, Eq)++tailInTerminal :: FilePath -> Chromatin Buffer+tailInTerminal path = do+  vim_command' $ "15split term://tail -f " ++ path+  vim_get_current_buffer'++closeTerminal :: Buffer -> Chromatin ()+closeTerminal buf = do+  num <- buffer_get_number' buf+  _ <- vim_command $ "silent! " ++ show num ++ "bwipeout!"+  return ()++processWithStdoutFile :: MonadIO m => ProcessConfig stdin stdout stderr -> Handle -> m (Either String ())+processWithStdoutFile processConfig logHandle = do+  let pipe = setStdout (useHandleClose logHandle)+  (code, err) <- readProcessStderr $ pipe processConfig+  return $ case code of+    ExitFailure _ -> Left (B.unpackChars err)+    _ -> Right ()++hackageProcess :: FilePath -> HackageDepspec -> ProcessConfig () () ()+hackageProcess bindir (HackageDepspec spec) =+  proc "cabal" ["new-install", "--symlink-bindir", bindir, spec]++stackProcess :: FilePath -> ProcessConfig () () ()+stackProcess path =+  setWorkingDir path $ proc "stack" ["build"]++processWithLog :: RpluginName -> ProcessConfig stdin stdout sderr -> Chromatin (Either String ())+processWithLog (RpluginName name) processConfig =+  withSystemTempFile "test-chromatin" $ \logFile logHandle -> do+    buf <- tailInTerminal logFile+    result <- processWithStdoutFile processConfig logHandle+    case result of+      Right _ -> do+        echom $ "installed `" ++ name ++ "`"+        closeTerminal buf+      Left _ -> echom $  "failed to install `" ++ name ++ "`"+    return result++installHackageProcess :: RpluginName -> FilePath -> HackageDepspec -> Chromatin (Either String ())+installHackageProcess name bindir spec =+  processWithLog name $ hackageProcess bindir spec++installStackProcess :: RpluginName -> FilePath -> Chromatin (Either String ())+installStackProcess name path =+  processWithLog name $ stackProcess path++venvProcess :: FilePath -> ProcessConfig () () ()+venvProcess dir =+  proc "python3" ["-m", "venv", dir, "--upgrade"]++venvDir :: RpluginName -> Chromatin FilePath+venvDir (RpluginName name) = getXdgDirectory XdgCache ("chromatin-hs" </> "venvs" </> name)++createVenvProcess :: RpluginName -> Chromatin (Either String FilePath)+createVenvProcess name = do+  dir <- venvDir name+  removePathForcibly dir+  r <- processWithLog name (venvProcess dir)+  return $ dir <$ r++pipProcess :: PypiDepspec -> FilePath -> ProcessConfig () () ()+pipProcess (PypiDepspec spec) venv =+  proc (venv </> "bin" </> "pip") ["install", "--no-cache", "--upgrade", spec]++installPypiProcess :: RpluginName -> PypiDepspec -> FilePath -> Chromatin (Either String ())+installPypiProcess name spec venv =+  processWithLog name (pipProcess spec venv)++binaryDir :: Chromatin FilePath+binaryDir = getXdgDirectory XdgData ("chromatin" </> "bin")++installRpluginFromSource :: RpluginName -> RpluginSource -> Chromatin (Either String ())+installRpluginFromSource name (Hackage spec) = do+  bindir <- binaryDir+  createDirectoryIfMissing True bindir+  installHackageProcess name bindir spec+installRpluginFromSource name (Stack path) =+  installStackProcess name path+installRpluginFromSource name (Pypi spec) = do+  dir <- createVenvProcess name+  case dir of+    Right d -> installPypiProcess name spec d+    Left e -> return $ Left e++installRplugin :: RpluginName -> RpluginSource -> Chromatin InstallResult+installRplugin name source = do+  result <- installRpluginFromSource name source+  return $ case result of+    Right _ -> Success $ Rplugin name source+    Left err -> Failure $ linesBy (=='\n') err
+ lib/Chromatin/Rebuild/Existing.hs view
@@ -0,0 +1,56 @@+module Chromatin.Rebuild.Existing(+  handleExisting,+) where++import GHC.IO.Exception (IOException)+import qualified Data.ByteString.Lazy.Internal as B (unpackChars)+import Data.List.Split (linesBy)+import System.Process.Typed (readProcessStderr, proc, setWorkingDir)+import UnliftIO (tryIO)+import Chromatin.Data.Chromatin (Chromatin)+import Chromatin.Data.RebuildTask (RebuildTask(..))+import Chromatin.Data.RunExistingResult (RunExistingResult)+import qualified Chromatin.Data.RunExistingResult as RunExistingResult (RunExistingResult(..))+import Chromatin.Data.Rplugin (Rplugin(Rplugin))+import Chromatin.Data.RpluginName (RpluginName)+import Chromatin.Data.RpluginSource (RpluginSource(Stack, Pypi))+import Chromatin.Data.RpluginState (RpluginState)+import qualified Chromatin.Data.RpluginState as RpluginState (RpluginState(..))+import Chromatin.Run (runRplugin, RunRpluginResult, pypiPluginPackage)+import qualified Chromatin.Run as RunRpluginResult (RunRpluginResult(..))++runPreexistingResult :: RebuildTask -> RunRpluginResult -> RunExistingResult+runPreexistingResult _ (RunRpluginResult.Success active) = RunExistingResult.Success active+runPreexistingResult task (RunRpluginResult.Failure err) = RunExistingResult.Failure task err++unsafeStackDryRun :: FilePath -> Chromatin [String]+unsafeStackDryRun path = do+  (_, output) <- readProcessStderr $ setWorkingDir path $ proc "stack" ["build", "--dry-run"]+  return $ linesBy (=='\n') $ B.unpackChars output++stackDryRun :: FilePath -> Chromatin (Either IOException [String])+stackDryRun path =+  tryIO $ unsafeStackDryRun path++rpluginReady :: RpluginName -> RpluginSource -> Chromatin RpluginState+rpluginReady _ (Stack path) = do+  output <- stackDryRun path+  return $ case output of+    Right lines' -> if "Would build:" `elem` lines' then RpluginState.Incomplete else RpluginState.Ready+    Left err -> RpluginState.Broken $ "could not execute `stack build` in " ++ path ++ ": " ++ show err+rpluginReady name (Pypi _) = do+  package <- pypiPluginPackage name+  return $ maybe RpluginState.Incomplete (const RpluginState.Ready) package+rpluginReady _ _ = return $ RpluginState.Broken "NI"++runPreexisting :: RebuildTask -> Chromatin RunExistingResult+runPreexisting task@(RebuildTask name source) =+  runPreexistingResult task <$> runRplugin (Rplugin name source)++handleExisting :: RebuildTask -> Chromatin RunExistingResult+handleExisting task@(RebuildTask name source) = do+  state <- rpluginReady name source+  case state of+    RpluginState.Ready -> runPreexisting task+    RpluginState.Incomplete -> return $ RunExistingResult.NotReady task+    RpluginState.Broken reason -> return $ RunExistingResult.Failure task [reason]
+ lib/Chromatin/Rebuild/Nonexisting.hs view
@@ -0,0 +1,35 @@+module Chromatin.Rebuild.Nonexisting(+  handleNonexisting,+) where++import Chromatin.Data.Chromatin (Chromatin)+import Chromatin.Data.Rplugin (Rplugin)+import Chromatin.Data.RunExistingResult (RunExistingResult)+import qualified Chromatin.Data.RunExistingResult as RunExistingResult (RunExistingResult(..))+import Chromatin.Data.RunBuiltResult (RunBuiltResult)+import qualified Chromatin.Data.RunBuiltResult as RunBuiltResult (RunBuiltResult(..))+import Chromatin.Data.RebuildTask (RebuildTask(..))+import Chromatin.Rebuild.Build (InstallResult, installRplugin)+import qualified Chromatin.Rebuild.Build as InstallResult (InstallResult(Success, Failure))+import Chromatin.Run (runRplugin, RunRpluginResult)+import qualified Chromatin.Run as RunRpluginResult (RunRpluginResult(..))++runBuiltResult :: RebuildTask -> RunRpluginResult -> RunBuiltResult+runBuiltResult _ (RunRpluginResult.Success active) = RunBuiltResult.Success active+runBuiltResult task (RunRpluginResult.Failure err) = RunBuiltResult.Failure task err++installSuccess :: RebuildTask -> Rplugin -> Chromatin RunBuiltResult+installSuccess task rplugin =+  fmap (runBuiltResult task) (runRplugin rplugin)++installResult :: RebuildTask -> InstallResult -> Chromatin RunBuiltResult+installResult task (InstallResult.Success rplugin) = installSuccess task rplugin+installResult task (InstallResult.Failure err) = return $ RunBuiltResult.Failure task err++handleNonexisting :: RunExistingResult -> Chromatin RunBuiltResult+handleNonexisting (RunExistingResult.Success active) = return $ RunBuiltResult.Success active+handleNonexisting (RunExistingResult.Failure task err) =+  return $ RunBuiltResult.PreviousFailure "run-existing" task err+handleNonexisting (RunExistingResult.NotReady task@(RebuildTask name source)) = do+  result <- installRplugin name source+  installResult task result
+ lib/Chromatin/Run.hs view
@@ -0,0 +1,87 @@+module Chromatin.Run(+  runRplugin,+  RunRpluginResult(..),+  pypiPluginPackage,+) where++import Control.Monad.IO.Class (liftIO)+import Data.List.Split (linesBy)+import Data.MessagePack (Object)+import UnliftIO.Exception (catch)+import System.FilePath ((</>))+import qualified System.FilePath.Glob as Glob (globDir1, compile)+import Neovim (NeovimException, toObject, fromObject', vim_call_function')+import qualified Neovim as NeovimException (NeovimException(ErrorMessage, ErrorResult))+import qualified Data.Map as Map (fromList)+import Chromatin.Data.Rplugin (Rplugin(Rplugin))+import Chromatin.Data.RpluginName (RpluginName(RpluginName))+import Chromatin.Data.ActiveRplugin (ActiveRplugin(ActiveRplugin))+import Chromatin.Data.RpluginSource (RpluginSource(Stack, Pypi))+import Chromatin.Data.Chromatin (Chromatin)+import Chromatin.Rebuild.Build (venvDir)++data RunRpluginResult =+  Success ActiveRplugin+  |+  Failure [String]+  deriving (Show, Eq)++jobstartFailure :: NeovimException -> Either String a+jobstartFailure (NeovimException.ErrorMessage doc) = Left (show doc)+jobstartFailure (NeovimException.ErrorResult obj) = Left (show obj)++unsafeJobstart :: [Object] -> Chromatin Int+unsafeJobstart args = do+  result <- vim_call_function' "jobstart" args+  fromObject' result++jobstart :: [Object] -> Chromatin (Either String Int)+jobstart args =+  catch (Right <$> unsafeJobstart args) (return . jobstartFailure)++runRpluginStack :: RpluginName -> FilePath -> Chromatin (Either String Int)+runRpluginStack (RpluginName name) path = do+  let opts = Map.fromList [("cwd", toObject path), ("rpc", toObject True)]+  jobstart [toObject $ "stack exec " ++ name, toObject opts]++pypiPluginExecutable :: RpluginName -> Chromatin FilePath+pypiPluginExecutable name = do+  dir <- venvDir name+  return $ dir </> "bin" </> "ribosome_start_plugin"++pypiSiteDir :: RpluginName -> Chromatin (Maybe FilePath)+pypiSiteDir name = do+  venv <- venvDir name+  matches <- liftIO $ Glob.globDir1 (Glob.compile "python3.?") (venv </> "lib")+  return $ case matches of+    dir : _ -> Just $ dir </> "site-packages"+    _ -> Nothing++pypiPluginPackage :: RpluginName -> Chromatin (Maybe FilePath)+pypiPluginPackage rpluginName@(RpluginName name) = do+  dir <- pypiSiteDir rpluginName+  return $ fmap (</> name) dir++runRpluginPypi :: RpluginName -> Chromatin (Either String Int)+runRpluginPypi rpluginName@(RpluginName name) = do+  dir <- venvDir rpluginName+  let exe = dir </> "bin" </> "python"+  let opts = Map.fromList [("rpc", toObject True)]+  start <- pypiPluginExecutable rpluginName+  mayPackage <- pypiPluginPackage rpluginName+  case mayPackage of+    Just package ->+      jobstart [toObject [toObject exe, toObject start, toObject package], toObject opts]+    Nothing -> return $ Left $ "no `lib/python` directory in virtualenv for `" ++ name ++ "`"++runRplugin' :: RpluginName -> RpluginSource -> Chromatin (Either String Int)+runRplugin' name (Stack path) = runRpluginStack name path+runRplugin' name (Pypi _) = runRpluginPypi name+runRplugin' _ _ = return (Left "NI")++runRplugin :: Rplugin -> Chromatin RunRpluginResult+runRplugin rplugin@(Rplugin name source) = do+  result <- runRplugin' name source+  return $ case result of+    Right channelId -> Success (ActiveRplugin channelId rplugin)+    Left err -> Failure (linesBy (=='\n') err)
+ lib/Chromatin/Settings.hs view
@@ -0,0 +1,10 @@+module Chromatin.Settings(+  rplugins,+) where++import Data.Default.Class (Default(def))+import Ribosome.Config.Setting+import Chromatin.Data.Rplugins (Rplugins)++rplugins :: Setting Rplugins+rplugins = Setting "rplugins" True (Just def)
+ lib/Chromatin/Test/Config.hs view
@@ -0,0 +1,13 @@+module Chromatin.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 "chromatin"++defaultTestConfig :: TestConfig+defaultTestConfig = E.defaultTestConfig "chromatin"
+ lib/Chromatin/Test/Unit.hs view
@@ -0,0 +1,32 @@+module Chromatin.Test.Unit(+  spec,+  specWith,+  specWithDef,+  specConfig,+) where++import Data.Default.Class (def)+import UnliftIO.STM (newTVarIO)+import Ribosome.Test.Embed (Vars, TestConfig)+import Ribosome.Test.Unit (unitSpec)+import Chromatin.Data.Chromatin (Chromatin)+import Chromatin.Data.Env (Env)+import Chromatin.Test.Config (defaultTestConfig, defaultTestConfigWith)++specConfig :: TestConfig -> Env -> Chromatin () -> IO ()+specConfig conf e s = do+  t <- newTVarIO e+  unitSpec conf t s++spec :: Env -> Chromatin () -> IO ()+spec =+  specConfig defaultTestConfig++specWith :: Env -> Chromatin () -> Vars -> IO ()+specWith e s vars = do+  t <- newTVarIO e+  unitSpec (defaultTestConfigWith vars) t s++specWithDef :: Chromatin () -> Vars -> IO ()+specWithDef =+  specWith def
+ lib/Chromatin/Unload.hs view
@@ -0,0 +1,18 @@+module Chromatin.Unload(+  unloadRplugins,+) where++import Data.Foldable (traverse_)+import qualified Control.Lens as Lens (over)+import qualified Ribosome.Control.Ribo as Ribo (modify)+import Chromatin.Data.Rplugin (Rplugin)+import Chromatin.Data.Chromatin (Chromatin)+import qualified Chromatin.Data.Env as Env (_rplugins)++unloadRplugin :: Rplugin -> Chromatin ()+unloadRplugin rplugin =+  Ribo.modify $ Lens.over Env._rplugins $ filter (rplugin ==)++unloadRplugins :: [Rplugin] -> Chromatin ()+unloadRplugins =+  traverse_ unloadRplugin
+ test/f/SpecMain.hs view
@@ -0,0 +1,11 @@+{-# OPTIONS_GHC -F -pgmF htfpp #-}++module Main where++import Test.Framework+import Test.Framework.BlackBoxTest ()++main :: IO ()+main =+  return ()+  -- htfMain htf_importedTests
+ test/u/BuildSpec.hs view
@@ -0,0 +1,46 @@+{-# OPTIONS_GHC -F -pgmF htfpp #-}++module BuildSpec(+  htf_thisModulesTests+) where++import Control.Monad.IO.Class (liftIO)+import Data.Default.Class (def)+import Test.Framework+import UnliftIO.Directory (getCurrentDirectory)+import Ribosome.Test.Embed (TestConfig(tcTimeout))+import Chromatin.Data.Chromatin (Chromatin)+import Chromatin.Data.Rplugin (Rplugin(Rplugin))+import Chromatin.Data.RpluginName (RpluginName(RpluginName))+import Chromatin.Data.RpluginSource (RpluginSource(Stack, Pypi), PypiDepspec(..))+import Chromatin.Test.Unit (specWithDef, specConfig)+import Chromatin.Test.Config (defaultTestConfig)+import Chromatin.Rebuild.Build (installRplugin)+import qualified Chromatin.Rebuild.Build as InstallResult (InstallResult(Success))+import Config (vars)++stackSpec :: Chromatin ()+stackSpec = do+  cwd <- getCurrentDirectory+  let name = RpluginName "chromatin"+  let source = Stack cwd+  result <- installRplugin name source+  liftIO $ assertEqual (InstallResult.Success (Rplugin name source)) result++test_stack :: IO ()+test_stack =+  vars >>= specWithDef stackSpec++pypiSpec :: Chromatin ()+pypiSpec = do+  let name = RpluginName "myo"+  let source = Pypi (PypiDepspec "myo~=1.0.0a")+  result <- installRplugin name source+  liftIO $ assertEqual (InstallResult.Success (Rplugin name source)) result++testConfig :: TestConfig+testConfig = defaultTestConfig { tcTimeout = 30 }++test_pypi :: IO ()+test_pypi =+  specConfig testConfig def pypiSpec
+ test/u/Config.hs view
@@ -0,0 +1,9 @@+module Config(+  vars,+) where++import Ribosome.Test.Embed (Vars(..))++vars :: IO Vars+vars =+  return $ Vars []
+ test/u/ConfigSpec.hs view
@@ -0,0 +1,28 @@+{-# OPTIONS_GHC -F -pgmF htfpp #-}++module ConfigSpec(+  htf_thisModulesTests+) where++import Test.Framework+import Chromatin.Data.Rplugins (Rplugins(Rplugins))+import Chromatin.Data.RpluginName (RpluginName(RpluginName))+import Chromatin.Data.RpluginConfig (RpluginConfig(RpluginConfig))+import Chromatin.Data.RpluginSource (RpluginSource(Hackage), HackageDepspec(HackageDepspec))+import Chromatin.Config (analyzeConfig, RpluginModification(RpluginNew))++rplugins :: Rplugins+rplugins = Rplugins [+  RpluginConfig "hackage:proteome-0.1.0.0" (Just (RpluginName "proteome")),+  RpluginConfig "hackage:flagellum" Nothing+  ]++target :: Either String [RpluginModification]+target = Right [+  RpluginNew (RpluginName "proteome") (Hackage (HackageDepspec "proteome-0.1.0.0")),+  RpluginNew (RpluginName "flagellum") (Hackage (HackageDepspec "flagellum"))+  ]++test_analyzeConfig :: IO ()+test_analyzeConfig =+  assertEqual target (analyzeConfig [] rplugins)
+ test/u/DiagSpec.hs view
@@ -0,0 +1,30 @@+{-# OPTIONS_GHC -F -pgmF htfpp #-}++module DiagSpec(+  htf_thisModulesTests+) where++import Control.Monad.IO.Class (liftIO)+import Data.Default.Class (Default(def))+import Test.Framework+import Ribosome.Api.Buffer (currentBufferContent)+import Chromatin.Data.Chromatin (Chromatin)+import Chromatin.Test.Unit (specWithDef)+import Chromatin.Diag (crmDiag)+import Config (vars)++target :: [String]+target = [+  "Diagnostics",+  ""+  ]++diagSpec :: Chromatin ()+diagSpec = do+  crmDiag def+  content <- currentBufferContent+  liftIO $ assertEqual target content++test_diag :: IO ()+test_diag =+  vars >>= specWithDef diagSpec
+ test/u/RebuildSpec.hs view
@@ -0,0 +1,36 @@+{-# OPTIONS_GHC -F -pgmF htfpp #-}++module RebuildSpec(+  htf_thisModulesTests+) where++import Data.Default.Class (Default(def))+import Control.Monad.IO.Class (liftIO)+import Test.Framework+import Neovim (vim_command')+import Ribosome.Config.Setting (updateSetting)+import Chromatin.Data.Chromatin (Chromatin)+import Chromatin.Data.Rplugins (Rplugins(Rplugins))+import Chromatin.Data.RpluginName (RpluginName(RpluginName))+import Chromatin.Data.RpluginConfig (RpluginConfig(RpluginConfig))+import Chromatin.Rebuild (crmRebuild)+import Chromatin.Test.Unit (specWithDef)+import qualified Chromatin.Settings as S (rplugins)+import Config (vars)++rplugins :: Rplugins+rplugins = Rplugins [+  RpluginConfig "hackage:proteome-0.1.0.0" (Just (RpluginName "proteome")),+  RpluginConfig "hackage:flagellum" Nothing+  ]++rebuildSpec :: Chromatin ()+rebuildSpec = do+  updateSetting S.rplugins rplugins+  crmRebuild def+  vim_command' "sleep 1"+  liftIO $ assertEqual [""] [""]++test_rebuild :: IO ()+test_rebuild =+  vars >>= specWithDef rebuildSpec
+ test/u/RunSpec.hs view
@@ -0,0 +1,33 @@+{-# OPTIONS_GHC -F -pgmF htfpp #-}++module RunSpec(+  htf_thisModulesTests+) where++import Control.Monad.IO.Class (liftIO)+import Neovim (vim_call_function', toObject, vim_command)+import Test.Framework+import UnliftIO.Directory (getCurrentDirectory)+import Chromatin.Data.Chromatin (Chromatin)+import Chromatin.Data.ActiveRplugin (ActiveRplugin(ActiveRplugin))+import Chromatin.Data.Rplugin (Rplugin(Rplugin))+import Chromatin.Data.RpluginName (RpluginName(RpluginName))+import Chromatin.Data.RpluginSource (RpluginSource(Stack))+import Chromatin.Test.Unit (specWithDef)+import Chromatin.Run (runRplugin)+import qualified Chromatin.Run as RunRpluginResult (RunRpluginResult(Success))+import Config (vars)++runSpec :: Chromatin ()+runSpec = do+  cwd <- getCurrentDirectory+  let rplugin = Rplugin (RpluginName "chromatin") (Stack cwd)+  result <- runRplugin rplugin+  _ <- vim_command "sleep 500m"+  exists <- vim_call_function' "exists" [toObject ":CrmDiag"]+  liftIO $ assertEqual (RunRpluginResult.Success (ActiveRplugin 3 rplugin)) result+  liftIO $ assertEqual (toObject (2 :: Int)) exists++test_run :: IO ()+test_run =+  vars >>= specWithDef runSpec
+ test/u/SpecMain.hs view
@@ -0,0 +1,14 @@+{-# OPTIONS_GHC -F -pgmF htfpp #-}++module Main where++import {-@ HTF_TESTS @-} DiagSpec+import {-@ HTF_TESTS @-} RebuildSpec+import {-@ HTF_TESTS @-} ConfigSpec+import {-@ HTF_TESTS @-} BuildSpec+import {-@ HTF_TESTS @-} RunSpec+import Test.Framework+import Test.Framework.BlackBoxTest ()++main :: IO ()+main = htfMain htf_importedTests