module Yi.File
(
editFile,
viWrite, viWriteTo, viSafeWriteTo,
fwriteE,
fwriteBufferE,
fwriteAllE,
fwriteToE,
backupE,
revertE,
setFileName,
) where
import Control.Applicative
import Control.Monad.Reader (asks)
import Control.Monad.Base
import Control.Lens
import Data.Time
import Data.Foldable (find)
import System.Directory
import System.FilePath
import System.FriendlyPath
import qualified Data.Rope as R
import Yi.Config
import Yi.Core
import Yi.Dired
import Yi.Regex
import Yi.Utils
import Yi.Monad
editFile :: FilePath -> YiM BufferRef
editFile filename = do
f <- io $ userToCanonPath filename
dupBufs <- filter (maybe False (equalFilePath f) . file) <$> gets bufferSet
dirExists <- io $ doesDirectoryExist f
fileExists <- io $ doesFileExist f
b <- case dupBufs of
[] -> if dirExists
then diredDirBuffer f
else setupMode f =<< if fileExists
then fileToNewBuffer f
else newEmptyBuffer f
(h:_) -> return $ bkey h
withEditor $ switchToBufferE b >> addJumpHereE
return b
where
fileToNewBuffer :: FilePath -> YiM BufferRef
fileToNewBuffer f = do
now <- io getCurrentTime
contents <- io $ R.readFile f
b <- withEditor $ stringToNewBuffer (Right f) contents
withGivenBuffer b $ markSavedB now
return b
newEmptyBuffer :: FilePath -> YiM BufferRef
newEmptyBuffer f =
withEditor $ stringToNewBuffer (Right f) (R.fromString "")
setupMode :: FilePath -> BufferRef -> YiM BufferRef
setupMode f b = do
tbl <- asks (modeTable . yiConfig)
content <- withGivenBuffer b elemsB
let header = take 1024 content
hmode = case header =~ "\\-\\*\\- *([^ ]*) *\\-\\*\\-" of
AllTextSubmatches [_,m] ->m
_ -> ""
Just mode = find (\(AnyMode m) -> modeName m == hmode) tbl <|>
find (\(AnyMode m) -> modeApplies m f header) tbl <|>
Just (AnyMode emptyMode)
case mode of
AnyMode newMode -> withGivenBuffer b $ setMode newMode
return b
revertE :: YiM ()
revertE = do
mfp <- withBuffer $ gets file
case mfp of
Just fp -> do
now <- io getCurrentTime
s <- liftBase $ R.readFile fp
withBuffer $ revertB s now
msgEditor ("Reverted from " ++ show fp)
Nothing -> do
msgEditor "Can't revert, no file associated with buffer."
return ()
viWrite :: YiM ()
viWrite = do
mf <- withBuffer $ gets file
case mf of
Nothing -> errorEditor "no file name associate with buffer"
Just f -> do
bufInfo <- withBuffer bufInfoB
let s = bufInfoFileName bufInfo
fwriteE
let message = (show f ++) (if f == s
then " written"
else " " ++ show s ++ " written")
msgEditor message
viWriteTo :: String -> YiM ()
viWriteTo f = do
bufInfo <- withBuffer bufInfoB
let s = bufInfoFileName bufInfo
fwriteToE f
let message = (show f ++) (if f == s
then " written"
else " " ++ show s ++ " written")
msgEditor message
viSafeWriteTo :: String -> YiM ()
viSafeWriteTo f = do
existsF <- liftBase $ doesFileExist f
if existsF
then errorEditor $ f ++ ": File exists (add '!' to override)"
else viWriteTo f
fwriteE :: YiM ()
fwriteE = fwriteBufferE =<< gets currentBuffer
fwriteBufferE :: BufferRef -> YiM ()
fwriteBufferE bufferKey =
do nameContents <- withGivenBuffer bufferKey ((,) <$> gets file <*> streamB Forward 0)
case nameContents of
(Just f, contents) -> do liftBase $ R.writeFile f contents
now <- io getCurrentTime
withGivenBuffer bufferKey (markSavedB now)
(Nothing, _c) -> msgEditor "Buffer not associated with a file"
fwriteToE :: String -> YiM ()
fwriteToE f = do
b <- gets currentBuffer
setFileName b f
fwriteBufferE b
fwriteAllE :: YiM ()
fwriteAllE =
do allBuffs <- gets bufferSet
let modifiedBuffers = filter (not . isUnchangedBuffer) allBuffs
mapM_ fwriteBufferE (fmap bkey modifiedBuffers)
backupE :: FilePath -> YiM ()
backupE = error "backupE not implemented"
setFileName :: BufferRef -> FilePath -> YiM ()
setFileName b filename = do
cfn <- liftBase $ userToCanonPath filename
withGivenBuffer b $ assign identA $ Right cfn