{-# 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,
toInput,
inEditor,
inTerm,
termInDir,
inProgram,
(>->),
(>-$),
(>&&>),
(>||>),
inWorkingDir,
eval,
execute,
executeNoQuote,
setXClass,
asString,
EmacsLib (..),
setFrameName,
withEmacsLibs,
inEmacs,
elispFun,
asBatch,
require,
progn,
quote,
findFile,
list,
saveExcursion,
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 :: forall (m :: * -> *).
MonadIO m =>
String -> [String] -> String -> m String
runProcessWithInput String
cmd [String]
args String
input = IO String -> m String
forall (m :: * -> *) a. MonadIO m => IO a -> m a
io (IO String -> m String) -> IO String -> m String
forall a b. (a -> b) -> a -> b
$ do
(Handle
pin, Handle
pout, Handle
perr, ProcessHandle
_) <- String
-> [String]
-> Maybe String
-> Maybe [(String, String)]
-> IO (Handle, Handle, Handle, ProcessHandle)
runInteractiveProcess (Input
encodeString String
cmd)
(Input -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Input
encodeString [String]
args) Maybe String
forall a. Maybe a
Nothing Maybe [(String, String)]
forall a. Maybe a
Nothing
Handle -> String -> IO ()
hPutStr Handle
pin String
input
Handle -> IO ()
hClose Handle
pin
String
output <- Handle -> IO String
hGetContents Handle
pout
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (String
output String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
output) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Handle -> IO ()
hClose Handle
pout
Handle -> IO ()
hClose Handle
perr
String -> IO String
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return String
output
runProcessWithInputAndWait :: MonadIO m => FilePath -> [String] -> String -> Int -> m ()
runProcessWithInputAndWait :: forall (m :: * -> *).
MonadIO m =>
String -> [String] -> String -> Int -> m ()
runProcessWithInputAndWait String
cmd [String]
args String
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
_) <- String
-> [String]
-> Maybe String
-> Maybe [(String, String)]
-> IO (Handle, Handle, Handle, ProcessHandle)
runInteractiveProcess (Input
encodeString String
cmd)
(Input -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Input
encodeString [String]
args) Maybe String
forall a. Maybe a
Nothing Maybe [(String, String)]
forall a. Maybe a
Nothing
Handle -> String -> IO ()
hPutStr Handle
pin String
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 a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
() -> IO ()
forall a. a -> IO a
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 :: forall (m :: * -> *). MonadIO m => String -> [String] -> m ()
safeSpawn String
prog [String]
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
String -> Bool -> [String] -> Maybe [(String, String)] -> IO ()
forall a.
String -> Bool -> [String] -> Maybe [(String, String)] -> IO a
executeFile (Input
encodeString String
prog) Bool
True (Input -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Input
encodeString [String]
args) Maybe [(String, String)]
forall a. Maybe a
Nothing
where void_ :: IO a -> IO ()
void_ = (IO a -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ())
safeSpawnProg :: MonadIO m => FilePath -> m ()
safeSpawnProg :: forall (m :: * -> *). MonadIO m => String -> m ()
safeSpawnProg = (String -> [String] -> m ()) -> [String] -> String -> m ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip String -> [String] -> m ()
forall (m :: * -> *). MonadIO m => String -> [String] -> m ()
safeSpawn []
unsafeSpawn :: MonadIO m => String -> m ()
unsafeSpawn :: forall (m :: * -> *). MonadIO m => String -> m ()
unsafeSpawn = String -> m ()
forall (m :: * -> *). MonadIO m => String -> m ()
spawn
unsafeRunInTerm, runInTerm :: String -> String -> X ()
unsafeRunInTerm :: String -> String -> X ()
unsafeRunInTerm String
options String
command = (XConf -> String) -> X String
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (XConfig Layout -> String
forall (l :: * -> *). XConfig l -> String
terminal (XConfig Layout -> String)
-> (XConf -> XConfig Layout) -> XConf -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XConf -> XConfig Layout
config) X String -> (String -> X ()) -> X ()
forall a b. X a -> (a -> X b) -> X b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \String
t -> String -> X ()
forall (m :: * -> *). MonadIO m => String -> m ()
unsafeSpawn (String -> X ()) -> String -> X ()
forall a b. (a -> b) -> a -> b
$ String
t String -> Input
forall a. [a] -> [a] -> [a]
++ String
" " String -> Input
forall a. [a] -> [a] -> [a]
++ String
options String -> Input
forall a. [a] -> [a] -> [a]
++ String
" -e " String -> Input
forall a. [a] -> [a] -> [a]
++ String
command
runInTerm :: String -> String -> X ()
runInTerm = String -> String -> X ()
unsafeRunInTerm
safeRunInTerm :: String -> String -> X ()
safeRunInTerm :: String -> String -> X ()
safeRunInTerm String
options String
command = (XConf -> String) -> X String
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (XConfig Layout -> String
forall (l :: * -> *). XConfig l -> String
terminal (XConfig Layout -> String)
-> (XConf -> XConfig Layout) -> XConf -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XConf -> XConfig Layout
config) X String -> (String -> X ()) -> X ()
forall a b. X a -> (a -> X b) -> X b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \String
t -> String -> [String] -> X ()
forall (m :: * -> *). MonadIO m => String -> [String] -> m ()
safeSpawn String
t [String
options, String
" -e " String -> Input
forall a. [a] -> [a] -> [a]
++ String
command]
spawnPipe :: MonadIO m => String -> m Handle
spawnPipe :: forall (m :: * -> *). MonadIO m => String -> m Handle
spawnPipe = String -> m Handle
forall (m :: * -> *). MonadIO m => String -> m Handle
spawnPipeWithLocaleEncoding
spawnPipeWithLocaleEncoding :: MonadIO m => String -> m Handle
spawnPipeWithLocaleEncoding :: forall (m :: * -> *). MonadIO m => String -> m Handle
spawnPipeWithLocaleEncoding = TextEncoding -> String -> m Handle
forall (m :: * -> *).
MonadIO m =>
TextEncoding -> String -> m Handle
spawnPipe' TextEncoding
localeEncoding
spawnPipeWithUtf8Encoding :: MonadIO m => String -> m Handle
spawnPipeWithUtf8Encoding :: forall (m :: * -> *). MonadIO m => String -> m Handle
spawnPipeWithUtf8Encoding = TextEncoding -> String -> m Handle
forall (m :: * -> *).
MonadIO m =>
TextEncoding -> String -> m Handle
spawnPipe' TextEncoding
utf8
spawnPipeWithNoEncoding :: MonadIO m => String -> m Handle
spawnPipeWithNoEncoding :: forall (m :: * -> *). MonadIO m => String -> m Handle
spawnPipeWithNoEncoding = TextEncoding -> String -> m Handle
forall (m :: * -> *).
MonadIO m =>
TextEncoding -> String -> m Handle
spawnPipe' TextEncoding
char8
spawnPipe' :: MonadIO m => TextEncoding -> String -> m Handle
spawnPipe' :: forall (m :: * -> *).
MonadIO m =>
TextEncoding -> String -> m Handle
spawnPipe' TextEncoding
encoding String
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
String -> Bool -> [String] -> Maybe [(String, String)] -> IO ()
forall a.
String -> Bool -> [String] -> Maybe [(String, String)] -> IO a
executeFile String
"/bin/sh" Bool
False [String
"-c", Input
encodeString String
x] Maybe [(String, String)]
forall a. Maybe a
Nothing
Fd -> IO ()
closeFd Fd
rd
Handle -> IO Handle
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Handle
h
data ProcessConfig = ProcessConfig
{ ProcessConfig -> String
editor :: !String
, ProcessConfig -> String
emacsLispDir :: !FilePath
, ProcessConfig -> String
emacsElpaDir :: !FilePath
, ProcessConfig -> String
emacs :: !String
}
spawnExternalProcess :: ProcessConfig -> XConfig l -> XConfig l
spawnExternalProcess :: forall (l :: * -> *). 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
{ editor :: String
editor = String
"emacsclient -c -a ''"
, emacsLispDir :: String
emacsLispDir = String
"~/.config/emacs/lisp/"
, emacsElpaDir :: String
emacsElpaDir = String
"~/.config/emacs/elpa/"
, emacs :: String
emacs = String
"emacs"
}
type Input = ShowS
(>->) :: X Input -> X Input -> X Input
>-> :: X Input -> X Input -> X Input
(>->) = X Input -> X Input -> X Input
forall a. Semigroup a => a -> a -> a
(<>)
infixr 3 >->
(>-$) :: X Input -> X String -> X Input
>-$ :: X Input -> X String -> X Input
(>-$) X Input
xi X String
xs = X Input
xi X Input -> X Input -> X Input
>-> (String -> Input) -> X String -> X Input
forall a b. (a -> b) -> X a -> X b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> Input
mkDList X String
xs
infixr 3 >-$
(>&&>) :: X Input -> X Input -> X Input
X Input
a >&&> :: X Input -> X Input -> X Input
>&&> X Input
b = X Input
a X Input -> X Input -> X Input
forall a. Semigroup a => a -> a -> a
<> String -> X Input
toInput String
" && " X Input -> X Input -> X Input
forall a. Semigroup a => a -> a -> a
<> X Input
b
infixr 2 >&&>
(>||>) :: X Input -> X Input -> X Input
X Input
a >||> :: X Input -> X Input -> X Input
>||> X Input
b = X Input
a X Input -> X Input -> X Input
forall a. Semigroup a => a -> a -> a
<> String -> X Input
toInput String
" || " X Input -> X Input -> X Input
forall a. Semigroup a => a -> a -> a
<> X Input
b
infixr 2 >||>
proc :: X Input -> X ()
proc :: X Input -> X ()
proc X Input
xi = String -> X ()
forall (m :: * -> *). MonadIO m => String -> m ()
spawn (String -> X ()) -> X String -> X ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< X Input -> X String
getInput X Input
xi
toInput :: String -> X Input
toInput :: String -> X Input
toInput = Input -> X Input
forall a. a -> X a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Input -> X Input) -> (String -> Input) -> String -> X Input
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Input
mkDList
getInput :: X Input -> X String
getInput :: X Input -> X String
getInput X Input
xi = X Input
xi X Input -> (Input -> String) -> X String
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> (Input -> Input
forall a b. (a -> b) -> a -> b
$ String
"")
inEditor :: X Input
inEditor :: X Input
inEditor = (ProcessConfig -> X Input) -> X Input
forall (m :: * -> *) a b.
(MonadReader XConf m, Typeable a, Default a) =>
(a -> m b) -> m b
XC.withDef ((ProcessConfig -> X Input) -> X Input)
-> (ProcessConfig -> X Input) -> X Input
forall a b. (a -> b) -> a -> b
$ \ProcessConfig{String
editor :: ProcessConfig -> String
editor :: String
editor} -> Input -> X Input
forall a. a -> X a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Input -> X Input) -> Input -> X Input
forall a b. (a -> b) -> a -> b
$ String -> Input
mkDList String
editor
inTerm :: X Input
inTerm :: X Input
inTerm = (XConf -> Input) -> X Input
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks ((XConf -> Input) -> X Input) -> (XConf -> Input) -> X Input
forall a b. (a -> b) -> a -> b
$ String -> Input
mkDList (String -> Input) -> (XConf -> String) -> XConf -> Input
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XConfig Layout -> String
forall (l :: * -> *). XConfig l -> String
terminal (XConfig Layout -> String)
-> (XConf -> XConfig Layout) -> XConf -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XConf -> XConfig Layout
config
execute :: String -> X Input
execute :: String -> X Input
execute String
this = Input -> X Input
forall a. a -> X a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((String
" -e " String -> Input
forall a. Semigroup a => a -> a -> a
<> Input
tryQuote String
this) String -> Input
forall a. Semigroup a => a -> a -> a
<>)
executeNoQuote :: String -> X Input
executeNoQuote :: String -> X Input
executeNoQuote String
this = Input -> X Input
forall a. a -> X a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((String
" -e " String -> Input
forall a. Semigroup a => a -> a -> a
<> String
this) String -> Input
forall a. Semigroup a => a -> a -> a
<>)
eval :: String -> X Input
eval :: String -> X Input
eval String
this = Input -> X Input
forall a. a -> X a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((String
" --eval " String -> Input
forall a. Semigroup a => a -> a -> a
<> Input
tryQuote String
this) String -> Input
forall a. Semigroup a => a -> a -> a
<>)
inEmacs :: X Input
inEmacs :: X Input
inEmacs = (ProcessConfig -> X Input) -> X Input
forall (m :: * -> *) a b.
(MonadReader XConf m, Typeable a, Default a) =>
(a -> m b) -> m b
XC.withDef ((ProcessConfig -> X Input) -> X Input)
-> (ProcessConfig -> X Input) -> X Input
forall a b. (a -> b) -> a -> b
$ \ProcessConfig{String
emacs :: ProcessConfig -> String
emacs :: String
emacs} -> Input -> X Input
forall a. a -> X a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Input -> X Input) -> Input -> X Input
forall a b. (a -> b) -> a -> b
$ String -> Input
mkDList String
emacs
inProgram :: String -> X Input
inProgram :: String -> X Input
inProgram = Input -> X Input
forall a. a -> X a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Input -> X Input) -> (String -> Input) -> String -> X Input
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Input
mkDList
inWorkingDir :: X Input
inWorkingDir :: X Input
inWorkingDir = Input -> X Input
forall a. a -> X a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String
" --working-directory " String -> Input
forall a. Semigroup a => a -> a -> a
<>)
setFrameName :: String -> X Input
setFrameName :: String -> X Input
setFrameName String
n = Input -> X Input
forall a. a -> X a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((String
" -F '(quote (name . \"" String -> Input
forall a. Semigroup a => a -> a -> a
<> String
n String -> Input
forall a. Semigroup a => a -> a -> a
<> String
"\"))' ") String -> Input
forall a. Semigroup a => a -> a -> a
<>)
setXClass :: String -> X Input
setXClass :: String -> X Input
setXClass = Input -> X Input
forall a. a -> X a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Input -> X Input) -> (String -> Input) -> String -> X Input
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Input
mkDList (String -> Input) -> Input -> String -> Input
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
" --class " String -> Input
forall a. Semigroup a => a -> a -> a
<>)
termInDir :: X Input
termInDir :: X Input
termInDir = X Input
inTerm X Input -> X Input -> X Input
>-> X Input
inWorkingDir
elispFun :: String -> String
elispFun :: Input
elispFun String
f = String
" '( " String -> Input
forall a. Semigroup a => a -> a -> a
<> String
f String -> Input
forall a. Semigroup a => a -> a -> a
<> String
" )' "
asString :: String -> String
asString :: Input
asString String
s = String
" \"" String -> Input
forall a. Semigroup a => a -> a -> a
<> String
s String -> Input
forall a. Semigroup a => a -> a -> a
<> String
"\" "
progn :: [String] -> String
progn :: [String] -> String
progn = Input
inParens Input -> ([String] -> String) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"progn " String -> Input
forall a. Semigroup a => a -> a -> a
<>) Input -> ([String] -> String) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
unwords ([String] -> String)
-> ([String] -> [String]) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Input -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Input
inParens
require :: String -> String
require :: Input
require = Input
inParens Input -> Input -> Input
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"require " String -> Input
forall a. Semigroup a => a -> a -> a
<>) Input -> Input -> Input
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Input
quote
quote :: String -> String
quote :: Input
quote = Input
inParens Input -> Input -> Input
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"quote " String -> Input
forall a. Semigroup a => a -> a -> a
<>)
findFile :: String -> String
findFile :: Input
findFile = Input
inParens Input -> Input -> Input
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"find-file" String -> Input
forall a. Semigroup a => a -> a -> a
<>) Input -> Input -> Input
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Input
asString
list :: [String] -> String
list :: [String] -> String
list = Input
inParens Input -> ([String] -> String) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"list " String -> Input
forall a. Semigroup a => a -> a -> a
<>) Input -> ([String] -> String) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
unwords
saveExcursion :: [String] -> String
saveExcursion :: [String] -> String
saveExcursion = Input
inParens Input -> ([String] -> String) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"save-excursion " String -> Input
forall a. Semigroup a => a -> a -> a
<>) Input -> ([String] -> String) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
unwords ([String] -> String)
-> ([String] -> [String]) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Input -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Input
inParens
asBatch :: X Input
asBatch :: X Input
asBatch = Input -> X Input
forall a. a -> X a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String
" --batch " String -> Input
forall a. Semigroup a => a -> a -> a
<>)
data EmacsLib
= OwnFile !String
| ElpaLib !String
| Special !String
withEmacsLibs :: [EmacsLib] -> X Input
withEmacsLibs :: [EmacsLib] -> X Input
withEmacsLibs [EmacsLib]
libs = (ProcessConfig -> X Input) -> X Input
forall (m :: * -> *) a b.
(MonadReader XConf m, Typeable a, Default a) =>
(a -> m b) -> m b
XC.withDef ((ProcessConfig -> X Input) -> X Input)
-> (ProcessConfig -> X Input) -> X Input
forall a b. (a -> b) -> a -> b
$ \ProcessConfig{String
emacsLispDir :: ProcessConfig -> String
emacsLispDir :: String
emacsLispDir, String
emacsElpaDir :: ProcessConfig -> String
emacsElpaDir :: String
emacsElpaDir} -> do
String
lispDir <- String -> X String
forall (m :: * -> *). MonadIO m => String -> m String
mkAbsolutePath String
emacsLispDir
String
elpaDir <- String -> X String
forall (m :: * -> *). MonadIO m => String -> m String
mkAbsolutePath String
emacsElpaDir
[String]
lisp <- IO [String] -> X [String]
forall a. IO a -> X a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [String] -> X [String]) -> IO [String] -> X [String]
forall a b. (a -> b) -> a -> b
$ String -> IO [String]
getDirectoryContents String
lispDir
[String]
elpa <- IO [String] -> X [String]
forall a. IO a -> X a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [String] -> X [String]) -> IO [String] -> X [String]
forall a b. (a -> b) -> a -> b
$ String -> IO [String]
getDirectoryContents String
elpaDir
let EmacsLib -> Maybe String
getLib :: EmacsLib -> Maybe String = \case
OwnFile String
f -> ((String
"-l " String -> Input
forall a. Semigroup a => a -> a -> a
<> String
lispDir) String -> Input
forall a. Semigroup a => a -> a -> a
<>) Input -> Maybe String -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (String -> Bool) -> [String] -> Maybe String
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (String
f String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf`) [String]
lisp
ElpaLib String
d -> ((String
"-L " String -> Input
forall a. Semigroup a => a -> a -> a
<> String
elpaDir) String -> Input
forall a. Semigroup a => a -> a -> a
<>) Input -> Maybe String -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (String -> Bool) -> [String] -> Maybe String
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ((String
d String -> Input
forall a. Semigroup a => a -> a -> a
<> String
"-") String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf`) [String]
elpa
Special String
f -> String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ String
" -l " String -> Input
forall a. Semigroup a => a -> a -> a
<> String
f
Input -> X Input
forall a. a -> X a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Input -> X Input)
-> ([EmacsLib] -> Input) -> [EmacsLib] -> X Input
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Input
mkDList (String -> Input) -> ([EmacsLib] -> String) -> [EmacsLib] -> Input
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
unwords ([String] -> String)
-> ([EmacsLib] -> [String]) -> [EmacsLib] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (EmacsLib -> Maybe String) -> [EmacsLib] -> [String]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe EmacsLib -> Maybe String
getLib ([EmacsLib] -> X Input) -> [EmacsLib] -> X Input
forall a b. (a -> b) -> a -> b
$ [EmacsLib]
libs
mkDList :: String -> ShowS
mkDList :: String -> Input
mkDList = String -> Input
forall a. Semigroup a => a -> a -> a
(<>) (String -> Input) -> Input -> String -> Input
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Input
forall a. Semigroup a => a -> a -> a
<> String
" ")
inParens :: String -> String
inParens :: Input
inParens String
s = case String
s of
Char
'(' : String
_ -> String
s
String
_ -> String
"(" String -> Input
forall a. Semigroup a => a -> a -> a
<> String
s String -> Input
forall a. Semigroup a => a -> a -> a
<> String
")"
tryQuote :: String -> String
tryQuote :: Input
tryQuote String
s = case (Char -> Bool) -> Input
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
' ') String
s of
Char
'\'' : String
_ -> String
s
String
_ -> String
"'" String -> Input
forall a. Semigroup a => a -> a -> a
<> String
s String -> Input
forall a. Semigroup a => a -> a -> a
<> String
"'"