Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #36 from mgajda/xdg

Move from .yi to XDG-style .config/yi and .local/share/yi directory paths
  • Loading branch information...
commit bf5b4595f296e08e7313cbf1a7838181a2c044d4 2 parents 32c136a + 890bcb7
@ethercrow ethercrow authored
View
3  yi/src/library/Yi/Boot.hs
@@ -17,6 +17,7 @@ import Yi.Editor
import Yi.Keymap
import Yi.Main
import qualified Yi.UI.Common as UI
+import qualified Yi.Paths(getConfigDir)
-- | once the custom yi is compiled this restores the editor state (if requested) then proceeds to
-- run the editor.
@@ -52,7 +53,7 @@ yiDriver cfg = do
{ Dyre.projectName = "yi"
, Dyre.realMain = realMain
, Dyre.showError = showErrorsInConf
- , Dyre.configDir = Just . getAppUserDataDirectory $ "yi"
+ , Dyre.configDir = Just Yi.Paths.getConfigDir
, Dyre.hidePackages = ["mtl"]
, Dyre.ghcOpts = (["-threaded", "-O2"] ++
#ifdef PROFILING
View
10 yi/src/library/Yi/Config/Default.hs
@@ -16,6 +16,7 @@ import Yi.Command (cabalBuildE, cabalConfigureE, grepFind, makeBuild, reloadProj
import {-# source #-} Yi.Boot
import Yi.Config
import Yi.Config.Misc
+import Yi.Paths(getConfigFilename)
import Yi.Core
import Yi.Eval(publishedActions)
import Yi.File
@@ -233,16 +234,13 @@ nilKeymap = choice [
where configHelp = newBufferE (Left "configuration help") $ R.fromString $ unlines $
["This instance of Yi is not configured.",
"To get a standard reasonable keymap, you can run yi with either --as=cua, --as=vim or --as=emacs.",
- "You should however create your own ~/.yi/yi.hs file: ",
+ "You should however create your own ~/.config/yi/yi.hs file: ",
"You can type 'c', 'e' or 'v' now to create and edit it using a temporary cua, emacs or vim keymap."]
openCfg km kmName = write $ do
dataDir <- io getDataDir
let exampleCfg = dataDir </> "example-configs" </> kmName
- homeDir <- io getHomeDirectory
- cfgDir <- io $ getAppUserDataDirectory "yi"
- let cfgFile = cfgDir </> "yi.hs"
- cfgExists <- io $ doesFileExist cfgDir
- io $ createDirectoryIfMissing True cfgDir -- so that the file can be saved
+ cfgFile <- getConfigFilename -- automatically creates directory, if missing
+ cfgExists <- io $ doesFileExist cfgFile
discard $ editFile cfgFile -- load config file
-- locally override the keymap to the user choice
withBuffer $ modifyMode (\m -> m { modeKeymap = const km })
View
7 yi/src/library/Yi/Eval.hs
@@ -23,8 +23,7 @@ import Data.List
import Data.Monoid
import Prelude hiding (error, (.))
import qualified Language.Haskell.Interpreter as LHI
-import System.FilePath
-import System.Directory
+import System.Directory(doesFileExist)
import qualified Data.HashMap.Strict as M
import Yi.Config.Simple.Types
@@ -32,6 +31,7 @@ import Yi.Core hiding (concatMap)
import Yi.File
import Yi.Hooks
import Yi.Regex
+import qualified Yi.Paths(getEvaluatorContextFilename)
-- | Runs the action, as written by the user.
--
@@ -85,8 +85,7 @@ ghciEvaluator :: Evaluator
ghciEvaluator = Evaluator{..} where
execEditorActionImpl :: String -> YiM ()
execEditorActionImpl s = do
- contextPath <- (</> ".yi" </> "local") <$> io getHomeDirectory
- let contextFile = contextPath </> "Env.hs"
+ contextFile <- Yi.Paths.getEvaluatorContextFilename
haveUserContext <- io $ doesFileExist contextFile
res <- io $ LHI.runInterpreter $ do
LHI.set [LHI.searchPath LHI.:= []]
View
11 yi/src/library/Yi/IReader.hs
@@ -23,6 +23,7 @@ import Yi.Buffer.Region (readRegionB)
import Yi.Dynamic
import Yi.Keymap (withBuffer, YiM)
import Yi.Prelude (getA, putA, io, discard, Initializable(..))
+import Yi.Paths(getArticleDbFilename)
type Article = B.ByteString
newtype ArticleDB = ADB { unADB :: Seq Article }
@@ -64,21 +65,17 @@ insertArticle (ADB adb) new = ADB (new <| adb)
-- | Serialize given 'ArticleDB' out.
writeDB :: ArticleDB -> YiM ()
-writeDB adb = discard $ io . join . fmap (flip encodeFile adb) $ dbLocation
+writeDB adb = discard $ io . join . fmap (flip encodeFile adb) $ getArticleDbFilename
--- | Read in database from 'dbLocation' and then parse it into an 'ArticleDB'.
+-- | Read in database from 'getArticleDbFilename' and then parse it into an 'ArticleDB'.
readDB :: YiM ArticleDB
-readDB = io $ (dbLocation >>= r) `catch` returnDefault
+readDB = io $ (getArticleDbFilename >>= r) `catch` returnDefault
where r = fmap (decode . BL.fromChunks . return) . B.readFile
-- We read in with strict bytestrings to guarantee the file is closed,
-- and then we convert it to the lazy bytestring data.binary expects.
-- This is inefficient, but alas...
returnDefault (_ :: SomeException) = return initial
--- | The canonical location. We assume \~\/.yi has been set up already.
-dbLocation :: IO FilePath
-dbLocation = getHomeDirectory >>= \home -> return (home ++ "/.yi/articles.db")
-
-- | Returns the database as it exists on the disk, and the current Yi buffer contents.
-- Note that the Initializable typeclass gives us an empty Seq. So first we try the buffer
-- state in the hope we can avoid a very expensive read from disk, and if we find nothing
View
65 yi/src/library/Yi/Paths.hs
@@ -0,0 +1,65 @@
+{-# LANGUAGE NoMonomorphismRestriction #-}
+module Yi.Paths(
+ getEvaluatorContextFilename
+ ,getConfigFilename
+ ,getArticleDbFilename
+ ,getPersistentStateFilename
+ ,getConfigDir
+
+ ,getConfigPath
+ ,getDataPath
+) where
+
+import System.Directory(getHomeDirectory, getAppUserDataDirectory, -- TODO: phase out in favour of xdg-dir
+ doesFileExist, doesDirectoryExist,
+ createDirectoryIfMissing)
+import System.FilePath((</>), takeDirectory, FilePath)
+import Control.Applicative((<$>))
+import Control.Monad(filterM, Monad)
+import Control.Monad.Trans(liftIO, MonadIO)
+import qualified System.Environment.XDG.BaseDir as XDG
+
+appUserDataCond dirQuery = liftIO $
+ do oldDir <- getAppUserDataDirectory "yi"
+ newDir <- dirQuery "yi"
+ oldDirExists <- doesDirectoryExist oldDir
+ newDirExists <- doesDirectoryExist newDir
+ if newDirExists -- overrides old-style
+ then return newDir
+ else if oldDirExists -- old-style exists, use it
+ then return oldDir
+ else do createDirectoryIfMissing True newDir -- none exists, use new style, but create it
+ return newDir
+
+-- TODO: These would be replaced by xdg-basedir equivalents
+getConfigDir = appUserDataCond XDG.getUserConfigDir
+getDataDir = appUserDataCond XDG.getUserDataDir
+
+-- | Given a path relative to application data directory,
+-- this function finds a path to a given data file.
+getDataPath :: (MonadIO m) => FilePath -> m FilePath
+getDataPath fp = getDataDir >>= (return . (</> fp))
+-- | Given a path relative to application configuration directory,
+-- this function finds a path to a given configuration file.
+getConfigPath :: (MonadIO m) => FilePath -> m FilePath
+getConfigPath fp = getConfigDir >>= (return . (</> fp))
+
+-- Note: Dyre also uses XDG cache dir - that would be:
+--getCachePath = getPathHelper XDG.getUserCacheDirectory
+
+-- Below are all points that are used in Yi code (to keep it clean.)
+getEvaluatorContextFilename, getConfigFilename, getArticleDbFilename, getPersistentStateFilename :: (MonadIO m) => m FilePath
+
+-- | Get Yi master configuration script.
+getConfigFilename = getConfigPath "yi.hs"
+
+-- | Get articles.db database of locations to visit (for Yi.IReader.)
+getArticleDbFilename = getConfigPath "articles.db"
+
+-- | Get path to Yi history that stores state between runs.
+getPersistentStateFilename = getDataPath "history"
+
+-- | Get path to environment file that defines namespace used by Yi
+-- command evaluator.
+getEvaluatorContextFilename = getConfigPath $ "local" </> "Env.hs"
+
View
9 yi/src/library/Yi/PersistentState.hs
@@ -15,8 +15,7 @@ import Prelude hiding ((.))
import Data.Binary
import Data.DeriveTH
import Data.Accessor.Template(nameDeriveAccessors)
-import System.FilePath((</>))
-import System.Directory(getAppUserDataDirectory, doesFileExist)
+import System.Directory(doesFileExist)
import qualified Data.Map as M
import Control.Exc(ignoringException)
@@ -32,6 +31,7 @@ import Yi.Keymap.Vim.TagStack(VimTagStack(..), getTagStack, setTagStack)
import Yi.KillRing(Killring(..))
import Yi.Search(getRegexE, setRegexE)
import Yi.Regex(SearchExp(..))
+import Yi.Paths(getPersistentStateFilename)
data PersistentState = PersistentState { histories :: !Histories
@@ -55,11 +55,6 @@ $(nameDeriveAccessors ''MaxHistoryEntries (\n -> Just (n ++ "A")))
maxHistoryEntries :: Field Int
maxHistoryEntries = unMaxHistoryEntriesA . customVariable
--- | Finds a path of history file.
-getPersistentStateFilename :: YiM String
-getPersistentStateFilename = do cfgDir <- io $ getAppUserDataDirectory "yi"
- return $ cfgDir </> "history"
-
-- | Trims per-command histories to contain at most N completions each.
trimHistories :: Int -> Histories -> Histories
trimHistories maxHistory = M.map trimH
View
4 yi/yi.cabal
@@ -167,6 +167,7 @@ library
Yi.Mode.Latex
Yi.Modes
Yi.Monad
+ Yi.Paths
Yi.PersistentState
Yi.Prelude
Yi.Process
@@ -239,7 +240,8 @@ library
utf8-string >= 0.3.1,
uniplate,
unix-compat >=0.1 && <0.4,
- unordered-containers >= 0.1.3 && < 0.3
+ unordered-containers >= 0.1.3 && < 0.3,
+ xdg-basedir >= 0.2.1 && < 0.3
build-tools: alex >= 3
ghc-options: -Wall -fno-warn-orphans
Please sign in to comment.
Something went wrong with that request. Please try again.