{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ScopedTypeVariables #-}
module XMonad.Util.Run (
runProcessWithInput,
runProcessWithInputAndWait,
safeSpawn,
safeSpawnProg,
unsafeSpawn,
runInTerm,
safeRunInTerm,
seconds,
spawnPipe,
spawnPipeWithLocaleEncoding,
spawnPipeWithUtf8Encoding,
spawnPipeWithNoEncoding,
ProcessConfig (..),
Input,
spawnExternalProcess,
proc,
getInput,
inEditor,
inTerm,
termInDir,
inProgram,
(>->),
(>-$),
inWorkingDir,
execute,
eval,
setXClass,
asString,
EmacsLib (..),
setFrameName,
withEmacsLibs,
inEmacs,
elispFun,
asBatch,
require,
progn,
quote,
hPutStr,
hPutStrLn,
) where
import XMonad
import XMonad.Prelude
import qualified XMonad.Util.ExtensibleConf as XC
import Codec.Binary.UTF8.String (encodeString)
import Control.Concurrent (threadDelay)
import System.Directory (getDirectoryContents)
import System.IO
import System.Posix.IO
import System.Posix.Process (createSession, executeFile, forkProcess)
import System.Process (runInteractiveProcess)
runProcessWithInput :: MonadIO m => FilePath -> [String] -> String -> m String
runProcessWithInput :: FilePath -> [FilePath] -> FilePath -> m FilePath
runProcessWithInput FilePath
cmd [FilePath]
args FilePath
input = IO FilePath -> m FilePath
forall (m :: * -> *) a. MonadIO m => IO a -> m a
io (IO FilePath -> m FilePath) -> IO FilePath -> m FilePath
forall a b. (a -> b) -> a -> b
$ do
(Handle
pin, Handle
pout, Handle
perr, ProcessHandle
_) <- FilePath
-> [FilePath]
-> Maybe FilePath
-> Maybe [(FilePath, FilePath)]
-> IO (Handle, Handle, Handle, ProcessHandle)
runInteractiveProcess (FilePath -> FilePath
encodeString FilePath
cmd)
((FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map FilePath -> FilePath
encodeString [FilePath]
args) Maybe FilePath
forall a. Maybe a
Nothing Maybe [(FilePath, FilePath)]
forall a. Maybe a
Nothing
Handle -> FilePath -> IO ()
hPutStr Handle
pin FilePath
input
Handle -> IO ()
hClose Handle
pin
FilePath
output <- Handle -> IO FilePath
hGetContents Handle
pout
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (FilePath
output FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
output) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Handle -> IO ()
hClose Handle
pout
Handle -> IO ()
hClose Handle
perr
FilePath -> IO FilePath
forall (m :: * -> *) a. Monad m => a -> m a
return FilePath
output
runProcessWithInputAndWait :: MonadIO m => FilePath -> [String] -> String -> Int -> m ()
runProcessWithInputAndWait :: FilePath -> [FilePath] -> FilePath -> Int -> m ()
runProcessWithInputAndWait FilePath
cmd [FilePath]
args FilePath
input Int
timeout = IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
io (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ do
ProcessID
_ <- IO () -> IO ProcessID
forall (m :: * -> *). MonadIO m => IO () -> m ProcessID
xfork (IO () -> IO ProcessID) -> IO () -> IO ProcessID
forall a b. (a -> b) -> a -> b
$ do
(Handle
pin, Handle
pout, Handle
perr, ProcessHandle
_) <- FilePath
-> [FilePath]
-> Maybe FilePath
-> Maybe [(FilePath, FilePath)]
-> IO (Handle, Handle, Handle, ProcessHandle)
runInteractiveProcess (FilePath -> FilePath
encodeString FilePath
cmd)
((FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map FilePath -> FilePath
encodeString [FilePath]
args) Maybe FilePath
forall a. Maybe a
Nothing Maybe [(FilePath, FilePath)]
forall a. Maybe a
Nothing
Handle -> FilePath -> IO ()
hPutStr Handle
pin FilePath
input
Handle -> IO ()
hFlush Handle
pin
Int -> IO ()
threadDelay Int
timeout
Handle -> IO ()
hClose Handle
pin
Handle -> IO ()
hClose Handle
pout
Handle -> IO ()
hClose Handle
perr
() -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
() -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
seconds :: Rational -> Int
seconds :: Rational -> Int
seconds = Rational -> Int
forall a. Enum a => a -> Int
fromEnum (Rational -> Int) -> (Rational -> Rational) -> Rational -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
1000000)
safeSpawn :: MonadIO m => FilePath -> [String] -> m ()
safeSpawn :: FilePath -> [FilePath] -> m ()
safeSpawn FilePath
prog [FilePath]
args = IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
io (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ IO ProcessID -> IO ()
forall a. IO a -> IO ()
void_ (IO ProcessID -> IO ()) -> IO ProcessID -> IO ()
forall a b. (a -> b) -> a -> b
$ IO () -> IO ProcessID
forkProcess (IO () -> IO ProcessID) -> IO () -> IO ProcessID
forall a b. (a -> b) -> a -> b
$ do
IO ()
forall (m :: * -> *). MonadIO m => m ()
uninstallSignalHandlers
ProcessID
_ <- IO ProcessID
createSession
FilePath
-> Bool -> [FilePath] -> Maybe [(FilePath, FilePath)] -> IO ()
forall a.
FilePath
-> Bool -> [FilePath] -> Maybe [(FilePath, FilePath)] -> IO a
executeFile (FilePath -> FilePath
encodeString FilePath
prog) Bool
True ((FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map FilePath -> FilePath
encodeString [FilePath]
args) Maybe [(FilePath, FilePath)]
forall a. Maybe a
Nothing
where void_ :: IO a -> IO ()
void_ = (IO a -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ())
safeSpawnProg :: MonadIO m => FilePath -> m ()
safeSpawnProg :: FilePath -> m ()
safeSpawnProg = (FilePath -> [FilePath] -> m ()) -> [FilePath] -> FilePath -> m ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip FilePath -> [FilePath] -> m ()
forall (m :: * -> *). MonadIO m => FilePath -> [FilePath] -> m ()
safeSpawn []
unsafeSpawn :: MonadIO m => String -> m ()
unsafeSpawn :: FilePath -> m ()
unsafeSpawn = FilePath -> m ()
forall (m :: * -> *). MonadIO m => FilePath -> m ()
spawn
unsafeRunInTerm, runInTerm :: String -> String -> X ()
unsafeRunInTerm :: FilePath -> FilePath -> X ()
unsafeRunInTerm FilePath
options FilePath
command = (XConf -> FilePath) -> X FilePath
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (XConfig Layout -> FilePath
forall (l :: * -> *). XConfig l -> FilePath
terminal (XConfig Layout -> FilePath)
-> (XConf -> XConfig Layout) -> XConf -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XConf -> XConfig Layout
config) X FilePath -> (FilePath -> X ()) -> X ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \FilePath
t -> FilePath -> X ()
forall (m :: * -> *). MonadIO m => FilePath -> m ()
unsafeSpawn (FilePath -> X ()) -> FilePath -> X ()
forall a b. (a -> b) -> a -> b
$ FilePath
t FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
options FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" -e " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
command
runInTerm :: FilePath -> FilePath -> X ()
runInTerm = FilePath -> FilePath -> X ()
unsafeRunInTerm
safeRunInTerm :: String -> String -> X ()
safeRunInTerm :: FilePath -> FilePath -> X ()
safeRunInTerm FilePath
options FilePath
command = (XConf -> FilePath) -> X FilePath
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (XConfig Layout -> FilePath
forall (l :: * -> *). XConfig l -> FilePath
terminal (XConfig Layout -> FilePath)
-> (XConf -> XConfig Layout) -> XConf -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XConf -> XConfig Layout
config) X FilePath -> (FilePath -> X ()) -> X ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \FilePath
t -> FilePath -> [FilePath] -> X ()
forall (m :: * -> *). MonadIO m => FilePath -> [FilePath] -> m ()
safeSpawn FilePath
t [FilePath
options, FilePath
" -e " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
command]
spawnPipe :: MonadIO m => String -> m Handle
spawnPipe :: FilePath -> m Handle
spawnPipe = FilePath -> m Handle
forall (m :: * -> *). MonadIO m => FilePath -> m Handle
spawnPipeWithLocaleEncoding
spawnPipeWithLocaleEncoding :: MonadIO m => String -> m Handle
spawnPipeWithLocaleEncoding :: FilePath -> m Handle
spawnPipeWithLocaleEncoding = TextEncoding -> FilePath -> m Handle
forall (m :: * -> *).
MonadIO m =>
TextEncoding -> FilePath -> m Handle
spawnPipe' TextEncoding
localeEncoding
spawnPipeWithUtf8Encoding :: MonadIO m => String -> m Handle
spawnPipeWithUtf8Encoding :: FilePath -> m Handle
spawnPipeWithUtf8Encoding = TextEncoding -> FilePath -> m Handle
forall (m :: * -> *).
MonadIO m =>
TextEncoding -> FilePath -> m Handle
spawnPipe' TextEncoding
utf8
spawnPipeWithNoEncoding :: MonadIO m => String -> m Handle
spawnPipeWithNoEncoding :: FilePath -> m Handle
spawnPipeWithNoEncoding = TextEncoding -> FilePath -> m Handle
forall (m :: * -> *).
MonadIO m =>
TextEncoding -> FilePath -> m Handle
spawnPipe' TextEncoding
char8
spawnPipe' :: MonadIO m => TextEncoding -> String -> m Handle
spawnPipe' :: TextEncoding -> FilePath -> m Handle
spawnPipe' TextEncoding
encoding FilePath
x = IO Handle -> m Handle
forall (m :: * -> *) a. MonadIO m => IO a -> m a
io (IO Handle -> m Handle) -> IO Handle -> m Handle
forall a b. (a -> b) -> a -> b
$ do
(Fd
rd, Fd
wr) <- IO (Fd, Fd)
createPipe
Fd -> FdOption -> Bool -> IO ()
setFdOption Fd
wr FdOption
CloseOnExec Bool
True
Handle
h <- Fd -> IO Handle
fdToHandle Fd
wr
Handle -> TextEncoding -> IO ()
hSetEncoding Handle
h TextEncoding
encoding
Handle -> BufferMode -> IO ()
hSetBuffering Handle
h BufferMode
LineBuffering
ProcessID
_ <- IO () -> IO ProcessID
forall (m :: * -> *). MonadIO m => IO () -> m ProcessID
xfork (IO () -> IO ProcessID) -> IO () -> IO ProcessID
forall a b. (a -> b) -> a -> b
$ do
Fd
_ <- Fd -> Fd -> IO Fd
dupTo Fd
rd Fd
stdInput
FilePath
-> Bool -> [FilePath] -> Maybe [(FilePath, FilePath)] -> IO ()
forall a.
FilePath
-> Bool -> [FilePath] -> Maybe [(FilePath, FilePath)] -> IO a
executeFile FilePath
"/bin/sh" Bool
False [FilePath
"-c", FilePath -> FilePath
encodeString FilePath
x] Maybe [(FilePath, FilePath)]
forall a. Maybe a
Nothing
Fd -> IO ()
closeFd Fd
rd
Handle -> IO Handle
forall (m :: * -> *) a. Monad m => a -> m a
return Handle
h
data ProcessConfig = ProcessConfig
{ ProcessConfig -> FilePath
editor :: !String
, ProcessConfig -> FilePath
emacsLispDir :: !FilePath
, ProcessConfig -> FilePath
emacsElpaDir :: !FilePath
, ProcessConfig -> FilePath
emacs :: !String
}
spawnExternalProcess :: ProcessConfig -> XConfig l -> XConfig l
spawnExternalProcess :: ProcessConfig -> XConfig l -> XConfig l
spawnExternalProcess = (ProcessConfig -> ProcessConfig) -> XConfig l -> XConfig l
forall a (l :: * -> *).
(Default a, Typeable a) =>
(a -> a) -> XConfig l -> XConfig l
XC.modifyDef ((ProcessConfig -> ProcessConfig) -> XConfig l -> XConfig l)
-> (ProcessConfig -> ProcessConfig -> ProcessConfig)
-> ProcessConfig
-> XConfig l
-> XConfig l
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProcessConfig -> ProcessConfig -> ProcessConfig
forall a b. a -> b -> a
const
instance Default ProcessConfig where
def :: ProcessConfig
def :: ProcessConfig
def = ProcessConfig :: FilePath -> FilePath -> FilePath -> FilePath -> ProcessConfig
ProcessConfig
{ editor :: FilePath
editor = FilePath
"emacsclient -c -a ''"
, emacsLispDir :: FilePath
emacsLispDir = FilePath
"~/.config/emacs/lisp/"
, emacsElpaDir :: FilePath
emacsElpaDir = FilePath
"~/.config/emacs/elpa/"
, emacs :: FilePath
emacs = FilePath
"emacs"
}
type Input = ShowS
(>->) :: X Input -> X Input -> X Input
>-> :: X (FilePath -> FilePath)
-> X (FilePath -> FilePath) -> X (FilePath -> FilePath)
(>->) = X (FilePath -> FilePath)
-> X (FilePath -> FilePath) -> X (FilePath -> FilePath)
forall a. Semigroup a => a -> a -> a
(<>)
infixr 3 >->
(>-$) :: X Input -> X String -> X Input
>-$ :: X (FilePath -> FilePath) -> X FilePath -> X (FilePath -> FilePath)
(>-$) X (FilePath -> FilePath)
xi X FilePath
xs = X (FilePath -> FilePath)
xi X (FilePath -> FilePath)
-> X (FilePath -> FilePath) -> X (FilePath -> FilePath)
>-> (FilePath -> FilePath -> FilePath)
-> X FilePath -> X (FilePath -> FilePath)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap FilePath -> FilePath -> FilePath
mkDList X FilePath
xs
infixr 3 >-$
proc :: X Input -> X ()
proc :: X (FilePath -> FilePath) -> X ()
proc X (FilePath -> FilePath)
xi = FilePath -> X ()
forall (m :: * -> *). MonadIO m => FilePath -> m ()
spawn (FilePath -> X ()) -> X FilePath -> X ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< X (FilePath -> FilePath) -> X FilePath
getInput X (FilePath -> FilePath)
xi
getInput :: X Input -> X String
getInput :: X (FilePath -> FilePath) -> X FilePath
getInput X (FilePath -> FilePath)
xi = X (FilePath -> FilePath)
xi X (FilePath -> FilePath)
-> ((FilePath -> FilePath) -> FilePath) -> X FilePath
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> ((FilePath -> FilePath) -> FilePath -> FilePath
forall a b. (a -> b) -> a -> b
$ FilePath
"")
inEditor :: X Input
inEditor :: X (FilePath -> FilePath)
inEditor = (ProcessConfig -> X (FilePath -> FilePath))
-> X (FilePath -> FilePath)
forall (m :: * -> *) a b.
(MonadReader XConf m, Typeable a, Default a) =>
(a -> m b) -> m b
XC.withDef ((ProcessConfig -> X (FilePath -> FilePath))
-> X (FilePath -> FilePath))
-> (ProcessConfig -> X (FilePath -> FilePath))
-> X (FilePath -> FilePath)
forall a b. (a -> b) -> a -> b
$ \ProcessConfig{FilePath
editor :: FilePath
editor :: ProcessConfig -> FilePath
editor} -> (FilePath -> FilePath) -> X (FilePath -> FilePath)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((FilePath -> FilePath) -> X (FilePath -> FilePath))
-> (FilePath -> FilePath) -> X (FilePath -> FilePath)
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> FilePath
mkDList FilePath
editor
inTerm :: X Input
inTerm :: X (FilePath -> FilePath)
inTerm = (XConf -> FilePath -> FilePath) -> X (FilePath -> FilePath)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks ((XConf -> FilePath -> FilePath) -> X (FilePath -> FilePath))
-> (XConf -> FilePath -> FilePath) -> X (FilePath -> FilePath)
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> FilePath
mkDList (FilePath -> FilePath -> FilePath)
-> (XConf -> FilePath) -> XConf -> FilePath -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XConfig Layout -> FilePath
forall (l :: * -> *). XConfig l -> FilePath
terminal (XConfig Layout -> FilePath)
-> (XConf -> XConfig Layout) -> XConf -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XConf -> XConfig Layout
config
execute :: String -> X Input
execute :: FilePath -> X (FilePath -> FilePath)
execute FilePath
this = (FilePath -> FilePath) -> X (FilePath -> FilePath)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((FilePath
" -e " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
this) FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<>)
eval :: String -> X Input
eval :: FilePath -> X (FilePath -> FilePath)
eval FilePath
this = (FilePath -> FilePath) -> X (FilePath -> FilePath)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((FilePath
" --eval " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
this) FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<>)
inEmacs :: X Input
inEmacs :: X (FilePath -> FilePath)
inEmacs = (ProcessConfig -> X (FilePath -> FilePath))
-> X (FilePath -> FilePath)
forall (m :: * -> *) a b.
(MonadReader XConf m, Typeable a, Default a) =>
(a -> m b) -> m b
XC.withDef ((ProcessConfig -> X (FilePath -> FilePath))
-> X (FilePath -> FilePath))
-> (ProcessConfig -> X (FilePath -> FilePath))
-> X (FilePath -> FilePath)
forall a b. (a -> b) -> a -> b
$ \ProcessConfig{FilePath
emacs :: FilePath
emacs :: ProcessConfig -> FilePath
emacs} -> (FilePath -> FilePath) -> X (FilePath -> FilePath)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((FilePath -> FilePath) -> X (FilePath -> FilePath))
-> (FilePath -> FilePath) -> X (FilePath -> FilePath)
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> FilePath
mkDList FilePath
emacs
inProgram :: String -> X Input
inProgram :: FilePath -> X (FilePath -> FilePath)
inProgram = (FilePath -> FilePath) -> X (FilePath -> FilePath)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((FilePath -> FilePath) -> X (FilePath -> FilePath))
-> (FilePath -> FilePath -> FilePath)
-> FilePath
-> X (FilePath -> FilePath)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath -> FilePath
mkDList
inWorkingDir :: X Input
inWorkingDir :: X (FilePath -> FilePath)
inWorkingDir = (FilePath -> FilePath) -> X (FilePath -> FilePath)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FilePath
" --working-directory " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<>)
setFrameName :: String -> X Input
setFrameName :: FilePath -> X (FilePath -> FilePath)
setFrameName FilePath
n = (FilePath -> FilePath) -> X (FilePath -> FilePath)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((FilePath
" -F '(quote (name . \"" FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
n FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
"\"))' ") FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<>)
setXClass :: String -> X Input
setXClass :: FilePath -> X (FilePath -> FilePath)
setXClass = (FilePath -> FilePath) -> X (FilePath -> FilePath)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((FilePath -> FilePath) -> X (FilePath -> FilePath))
-> (FilePath -> FilePath -> FilePath)
-> FilePath
-> X (FilePath -> FilePath)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath -> FilePath
mkDList (FilePath -> FilePath -> FilePath)
-> (FilePath -> FilePath) -> FilePath -> FilePath -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath
" --class " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<>)
termInDir :: X Input
termInDir :: X (FilePath -> FilePath)
termInDir = X (FilePath -> FilePath)
inTerm X (FilePath -> FilePath)
-> X (FilePath -> FilePath) -> X (FilePath -> FilePath)
>-> X (FilePath -> FilePath)
inWorkingDir
elispFun :: String -> String
elispFun :: FilePath -> FilePath
elispFun FilePath
f = FilePath
" '( " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
f FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
" )' "
asString :: String -> String
asString :: FilePath -> FilePath
asString FilePath
s = FilePath
" \"" FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
s FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
"\" "
progn :: [String] -> String
progn :: [FilePath] -> FilePath
progn [FilePath]
cmds = FilePath -> FilePath
elispFun (FilePath -> FilePath) -> FilePath -> FilePath
forall a b. (a -> b) -> a -> b
$ FilePath
"progn " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> [FilePath] -> FilePath
unwords ((FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map FilePath -> FilePath
inParens [FilePath]
cmds)
require :: String -> String
require :: FilePath -> FilePath
require = FilePath -> FilePath
inParens (FilePath -> FilePath)
-> (FilePath -> FilePath) -> FilePath -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath
"require " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<>) (FilePath -> FilePath)
-> (FilePath -> FilePath) -> FilePath -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath
quote
quote :: String -> String
quote :: FilePath -> FilePath
quote = FilePath -> FilePath
inParens (FilePath -> FilePath)
-> (FilePath -> FilePath) -> FilePath -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath
"quote " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<>)
asBatch :: X Input
asBatch :: X (FilePath -> FilePath)
asBatch = (FilePath -> FilePath) -> X (FilePath -> FilePath)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FilePath
" --batch " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<>)
data EmacsLib
= OwnFile !String
| ElpaLib !String
| Special !String
withEmacsLibs :: [EmacsLib] -> X Input
withEmacsLibs :: [EmacsLib] -> X (FilePath -> FilePath)
withEmacsLibs [EmacsLib]
libs = (ProcessConfig -> X (FilePath -> FilePath))
-> X (FilePath -> FilePath)
forall (m :: * -> *) a b.
(MonadReader XConf m, Typeable a, Default a) =>
(a -> m b) -> m b
XC.withDef ((ProcessConfig -> X (FilePath -> FilePath))
-> X (FilePath -> FilePath))
-> (ProcessConfig -> X (FilePath -> FilePath))
-> X (FilePath -> FilePath)
forall a b. (a -> b) -> a -> b
$ \ProcessConfig{FilePath
emacsLispDir :: FilePath
emacsLispDir :: ProcessConfig -> FilePath
emacsLispDir, FilePath
emacsElpaDir :: FilePath
emacsElpaDir :: ProcessConfig -> FilePath
emacsElpaDir} -> do
FilePath
lispDir <- FilePath -> X FilePath
forall (m :: * -> *). MonadIO m => FilePath -> m FilePath
mkAbsolutePath FilePath
emacsLispDir
FilePath
elpaDir <- FilePath -> X FilePath
forall (m :: * -> *). MonadIO m => FilePath -> m FilePath
mkAbsolutePath FilePath
emacsElpaDir
[FilePath]
lisp <- IO [FilePath] -> X [FilePath]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [FilePath] -> X [FilePath]) -> IO [FilePath] -> X [FilePath]
forall a b. (a -> b) -> a -> b
$ FilePath -> IO [FilePath]
getDirectoryContents FilePath
lispDir
[FilePath]
elpa <- IO [FilePath] -> X [FilePath]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [FilePath] -> X [FilePath]) -> IO [FilePath] -> X [FilePath]
forall a b. (a -> b) -> a -> b
$ FilePath -> IO [FilePath]
getDirectoryContents FilePath
elpaDir
let EmacsLib -> Maybe FilePath
getLib :: EmacsLib -> Maybe String = \case
OwnFile FilePath
f -> ((FilePath
"-l " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
lispDir) FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<>) (FilePath -> FilePath) -> Maybe FilePath -> Maybe FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (FilePath -> Bool) -> [FilePath] -> Maybe FilePath
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (FilePath
f FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf`) [FilePath]
lisp
ElpaLib FilePath
d -> ((FilePath
"-L " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
elpaDir) FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<>) (FilePath -> FilePath) -> Maybe FilePath -> Maybe FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (FilePath -> Bool) -> [FilePath] -> Maybe FilePath
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ((FilePath
d FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
"-") FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf`) [FilePath]
elpa
Special FilePath
f -> FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just (FilePath -> Maybe FilePath) -> FilePath -> Maybe FilePath
forall a b. (a -> b) -> a -> b
$ FilePath
" -l " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
f
(FilePath -> FilePath) -> X (FilePath -> FilePath)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((FilePath -> FilePath) -> X (FilePath -> FilePath))
-> ([EmacsLib] -> FilePath -> FilePath)
-> [EmacsLib]
-> X (FilePath -> FilePath)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath -> FilePath
mkDList (FilePath -> FilePath -> FilePath)
-> ([EmacsLib] -> FilePath) -> [EmacsLib] -> FilePath -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> FilePath
unwords ([FilePath] -> FilePath)
-> ([EmacsLib] -> [FilePath]) -> [EmacsLib] -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (EmacsLib -> Maybe FilePath) -> [EmacsLib] -> [FilePath]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe EmacsLib -> Maybe FilePath
getLib ([EmacsLib] -> X (FilePath -> FilePath))
-> [EmacsLib] -> X (FilePath -> FilePath)
forall a b. (a -> b) -> a -> b
$ [EmacsLib]
libs
mkDList :: String -> ShowS
mkDList :: FilePath -> FilePath -> FilePath
mkDList = FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
(<>) (FilePath -> FilePath -> FilePath)
-> (FilePath -> FilePath) -> FilePath -> FilePath -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
" ")
inParens :: String -> String
inParens :: FilePath -> FilePath
inParens FilePath
s = case FilePath
s of
Char
'(' : FilePath
_ -> FilePath
s
FilePath
_ -> FilePath
"(" FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
s FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
")"