{-# 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
(pin, pout, perr, _) <- 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
hPutStr pin input
hClose pin
output <- hGetContents pout
when (output == output) $ return ()
hClose pout
hClose perr
return 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
_ <- 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
(pin, pout, perr, _) <- 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
hPutStr pin input
hFlush pin
threadDelay timeout
hClose pin
hClose pout
hClose perr
return ()
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
_ <- IO ProcessID
createSession
executeFile (encodeString prog) True (map encodeString args) 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
(rd, wr) <- IO (Fd, Fd)
createPipe
setFdOption wr CloseOnExec True
h <- fdToHandle wr
hSetEncoding h encoding
hSetBuffering h LineBuffering
_ <- xfork $ do
_ <- dupTo rd stdInput
executeFile "/bin/sh" False ["-c", encodeString x] Nothing
closeFd rd
return 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
lispDir <- String -> X String
forall (m :: * -> *). MonadIO m => String -> m String
mkAbsolutePath String
emacsLispDir
elpaDir <- mkAbsolutePath emacsElpaDir
lisp <- liftIO $ getDirectoryContents lispDir
elpa <- liftIO $ getDirectoryContents elpaDir
let 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
pure . mkDList . unwords . mapMaybe getLib $ 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
"'"