mirror of
https://github.com/danieljharvey/tmux-mate.git
synced 2024-09-11 16:46:40 +03:00
More things
This commit is contained in:
parent
1963e77dc2
commit
e2f1195f8b
109
src/TmuxMate.hs
109
src/TmuxMate.hs
@ -8,6 +8,7 @@ module TmuxMate
|
||||
createWindowPanes,
|
||||
removeWindowPanes,
|
||||
removeWindows,
|
||||
attachToSession,
|
||||
)
|
||||
where
|
||||
|
||||
@ -21,38 +22,35 @@ import TmuxMate.Commands
|
||||
import TmuxMate.Running
|
||||
import TmuxMate.Types
|
||||
|
||||
getCommands :: Session -> [Running] -> [Command]
|
||||
getCommands sesh running =
|
||||
concatMap createActualCommand (getTmuxCommands sesh running)
|
||||
getCommands :: [TmuxCommand] -> [Command]
|
||||
getCommands =
|
||||
concatMap createActualCommand
|
||||
|
||||
getTmuxCommands :: Session -> [Running] -> [TmuxCommand]
|
||||
getTmuxCommands sesh running =
|
||||
maybeToList (createSession (sessionTitle sesh) running)
|
||||
<> ( concatMap
|
||||
(maybeToList . createWindow (sessionTitle sesh) running)
|
||||
(windowTitle <$> sessionWindows sesh)
|
||||
)
|
||||
<> ( concatMap
|
||||
(createWindowPanes (sessionTitle sesh) running)
|
||||
(sessionWindows sesh)
|
||||
)
|
||||
<> (removeWindowPanes (sessionTitle sesh) running (sessionWindows sesh))
|
||||
<> (removeWindows (sessionTitle sesh) running (sessionWindows sesh))
|
||||
where
|
||||
|
||||
{-startSession isNewSession (sessionTitle sesh)
|
||||
<> concatMap (addPane (sessionTitle sesh)) filteredPanes
|
||||
<> concatMap (removePane (sessionTitle sesh)) filteredRunning
|
||||
<> attach isNewSession (sessionTitle sesh)-}
|
||||
|
||||
{-filteredPanes =
|
||||
filterPanes (sessionTitle sesh) running (sessionPanes sesh)
|
||||
filteredRunning =
|
||||
filterRunning (sessionTitle sesh) (sessionPanes sesh) running
|
||||
isNewSession =
|
||||
if length running > 0
|
||||
then IsOldSession
|
||||
else IsNewSession-}
|
||||
getTmuxCommands :: Session -> TmuxState -> [TmuxCommand]
|
||||
getTmuxCommands sesh tmuxState =
|
||||
let runningPanes =
|
||||
running tmuxState
|
||||
runningSessions =
|
||||
sessions tmuxState
|
||||
runningInTmux =
|
||||
inSession tmuxState
|
||||
sTitle =
|
||||
sessionTitle sesh
|
||||
sWindows =
|
||||
sessionWindows sesh
|
||||
in (createSession runningInTmux sTitle runningSessions)
|
||||
<> ( concatMap
|
||||
(maybeToList . createWindow sTitle runningPanes)
|
||||
(windowTitle <$> sWindows)
|
||||
)
|
||||
<> ( concatMap
|
||||
(createWindowPanes sTitle runningPanes)
|
||||
(sessionWindows sesh)
|
||||
)
|
||||
<> (removeWindowPanes sTitle runningPanes sWindows)
|
||||
<> (removeWindows sTitle runningPanes sWindows)
|
||||
<> (removeAdminPane sTitle)
|
||||
<> (attachToSession runningInTmux sTitle runningSessions)
|
||||
|
||||
runCommands :: [Command] -> IO ()
|
||||
runCommands =
|
||||
@ -73,20 +71,32 @@ testSession =
|
||||
Pane (PaneCommand "yes 'Pane 3'") (PaneTitle "Three"),
|
||||
Pane (PaneCommand "yes 'Pane 4'") (PaneTitle "Four")
|
||||
]
|
||||
},
|
||||
Window
|
||||
{ windowTitle = WindowName "second-window",
|
||||
windowPanes =
|
||||
[ Pane (PaneCommand "yes 'Second Window - Pane 1'") (PaneTitle "2One"),
|
||||
Pane (PaneCommand "yes 'Second Window - Pane 2'") (PaneTitle "2Two"),
|
||||
Pane (PaneCommand "yes 'Second Window - Pane 3'") (PaneTitle "2Three"),
|
||||
Pane (PaneCommand "yes 'Second Window - Pane 4'") (PaneTitle "2Four")
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
-- create a new session if required
|
||||
createSession :: SessionName -> [Running] -> Maybe TmuxCommand
|
||||
createSession seshName running =
|
||||
if sessionExists seshName running
|
||||
then Nothing
|
||||
else Just (NewSession seshName)
|
||||
createSession :: InTmuxSession -> SessionName -> [SessionName] -> [TmuxCommand]
|
||||
createSession inTmux seshName runningSessions =
|
||||
if sessionExists seshName runningSessions
|
||||
then case inTmux of
|
||||
InTmuxSession _ -> [SwitchToSession seshName]
|
||||
NotInTmuxSession -> []
|
||||
else case inTmux of
|
||||
InTmuxSession _ -> [NewSession seshName, SwitchToSession seshName]
|
||||
NotInTmuxSession -> [NewSession seshName]
|
||||
|
||||
sessionExists :: SessionName -> [Running] -> Bool
|
||||
sessionExists seshName running =
|
||||
length (filter (\a -> sessionName a == seshName) running) > 0
|
||||
sessionExists :: SessionName -> [SessionName] -> Bool
|
||||
sessionExists = elem
|
||||
|
||||
-- do we need to create this window?
|
||||
createWindow :: SessionName -> [Running] -> WindowName -> Maybe TmuxCommand
|
||||
@ -186,12 +196,17 @@ removeWindows seshName running windows =
|
||||
nub $ windowName <$> filter (\(Running sesh' win' _ _) -> sesh' == seshName) running
|
||||
|
||||
--- attaching or switching to session
|
||||
|
||||
-- if the stuff we've made is running, switch to it
|
||||
-- attach sometimes?
|
||||
attachToSession :: InTmuxSession -> SessionName -> [SessionName] -> [TmuxCommand]
|
||||
attachToSession inTmux seshName runningSessions =
|
||||
case inTmux of
|
||||
InTmuxSession sesh -> [SwitchToSession sesh]
|
||||
_ -> [AttachToSession seshName]
|
||||
|
||||
-- remove admin window (always)
|
||||
|
||||
removeAdminPane :: SessionName -> [TmuxCommand]
|
||||
removeAdminPane seshName = pure (KillAdminPane seshName)
|
||||
|
||||
---- load dhall file and let's get cracking
|
||||
|
||||
loadTestSession :: FilePath -> IO ()
|
||||
@ -199,10 +214,12 @@ loadTestSession path = do
|
||||
--let (decoder :: Dhall.Decoder Session) = Dhall.auto
|
||||
--- config <- Dhall.inputFile decoder path
|
||||
let config = testSession
|
||||
running <- askRunning (sessionTitle config)
|
||||
print running
|
||||
let tmuxCommands = getTmuxCommands config running
|
||||
tmuxState <- askTmuxState (sessionTitle config)
|
||||
print tmuxState
|
||||
let tmuxCommands = getTmuxCommands config tmuxState
|
||||
putStrLn "Tmux Commands"
|
||||
print tmuxCommands
|
||||
let commands = (getCommands config running)
|
||||
let commands = getCommands tmuxCommands
|
||||
putStrLn "Shell commands"
|
||||
print commands
|
||||
runCommands commands
|
||||
|
@ -18,7 +18,9 @@ createActualCommand (CreateAdminPane (SessionName seshName)) =
|
||||
createActualCommand (KillAdminPane seshName) =
|
||||
pure $ sendKeys seshName "exit"
|
||||
createActualCommand (CreatePane seshName winName cmd) =
|
||||
pure $ sendKeys seshName ("tmux split-window -h -d " <> (getCommand cmd))
|
||||
[ Command $ "tmux select-window -t '" <> (getWindowName winName) <> "'",
|
||||
sendKeys seshName ("tmux split-window -h -d " <> (getCommand cmd))
|
||||
]
|
||||
createActualCommand (KillPane seshName index) =
|
||||
pure $ sendKeys seshName ("tmux kill-pane -t " <> show index)
|
||||
createActualCommand (AttachToSession (SessionName seshName)) =
|
||||
@ -30,4 +32,4 @@ createActualCommand (KillSession (SessionName seshName)) =
|
||||
createActualCommand (NewSession (SessionName seshName)) =
|
||||
pure $ Command $ "tmux new-session -d -s " <> seshName
|
||||
createActualCommand (CreateWindow (SessionName seshName) (WindowName winName)) =
|
||||
pure $ Command $ "tmux new-window -n '" <> seshName <> "'"
|
||||
pure $ Command $ "tmux new-window -n '" <> winName <> "'"
|
||||
|
@ -5,10 +5,30 @@ module TmuxMate.Running where
|
||||
import Control.Exception
|
||||
import Data.List (intercalate, isPrefixOf)
|
||||
import Data.Maybe (catMaybes, listToMaybe)
|
||||
import System.Environment
|
||||
import System.Process
|
||||
import Text.Read
|
||||
import TmuxMate.Types
|
||||
|
||||
buildTmuxState :: SessionName -> IO TmuxState
|
||||
buildTmuxState seshName = do
|
||||
sessions <- askRunningSessions
|
||||
running <- askRunning seshName
|
||||
inTmux <- askIfWeAreInTmux
|
||||
pure $ TmuxState inTmux running sessions
|
||||
|
||||
askTmuxState :: SessionName -> IO TmuxState
|
||||
askTmuxState seshName =
|
||||
catch
|
||||
(buildTmuxState seshName)
|
||||
(\(e :: IOError) -> pure def)
|
||||
where
|
||||
def = TmuxState
|
||||
{ inSession = NotInTmuxSession,
|
||||
running = mempty,
|
||||
sessions = mempty
|
||||
}
|
||||
|
||||
-- "foo:yes Pane 2\nfoo:yes Pane 1\n"
|
||||
|
||||
askRunning :: SessionName -> IO [Running]
|
||||
@ -23,6 +43,36 @@ readTmuxProcess =
|
||||
(shell "tmux list-pane -as -F '#{session_name}:#{window_name}:#{pane_index}:#{pane_start_command}'")
|
||||
""
|
||||
|
||||
-- "foo/npoo/n0/n"
|
||||
askRunningSessions :: IO [SessionName]
|
||||
askRunningSessions = do
|
||||
str <- catch readTmuxSessions (\(e :: IOError) -> pure "")
|
||||
pure $ SessionName <$> lines str
|
||||
|
||||
readTmuxSessions :: IO String
|
||||
readTmuxSessions =
|
||||
readCreateProcess
|
||||
(shell "tmux list-sessions -F '#{session_name}'")
|
||||
""
|
||||
|
||||
-- are we currently in a tmux session? (if so, don't nest)
|
||||
|
||||
askIfWeAreInTmux :: IO InTmuxSession
|
||||
askIfWeAreInTmux = do
|
||||
tmuxEnv <- lookupEnv "TMUX"
|
||||
seshName <- askCurrentSessionName
|
||||
case tmuxEnv of
|
||||
Nothing -> pure NotInTmuxSession
|
||||
Just "" -> pure NotInTmuxSession
|
||||
Just a -> pure $ InTmuxSession seshName
|
||||
|
||||
askCurrentSessionName :: IO SessionName
|
||||
askCurrentSessionName =
|
||||
SessionName
|
||||
<$> readCreateProcess
|
||||
(shell "tmux display-message -p '#S'")
|
||||
""
|
||||
|
||||
-- stop unrequired
|
||||
|
||||
removeQuotes :: PaneCommand -> PaneCommand
|
||||
|
@ -8,6 +8,19 @@ module TmuxMate.Types where
|
||||
import Dhall (Decoder, FromDhall, ToDhall, autoWith)
|
||||
import GHC.Generics
|
||||
|
||||
data InTmuxSession
|
||||
= InTmuxSession SessionName
|
||||
| NotInTmuxSession
|
||||
deriving (Eq, Ord, Show)
|
||||
|
||||
data TmuxState
|
||||
= TmuxState
|
||||
{ inSession :: InTmuxSession,
|
||||
running :: [Running],
|
||||
sessions :: [SessionName]
|
||||
}
|
||||
deriving (Eq, Ord, Show)
|
||||
|
||||
data IsNewSession
|
||||
= IsNewSession
|
||||
| IsOldSession
|
||||
|
24
test/Spec.hs
24
test/Spec.hs
@ -10,6 +10,7 @@ import TmuxMate
|
||||
import TmuxMate.Running
|
||||
import TmuxMate.Types
|
||||
( Command (..),
|
||||
InTmuxSession (..),
|
||||
Pane (..),
|
||||
PaneCommand (..),
|
||||
Running (..),
|
||||
@ -24,15 +25,23 @@ main = hspec $ do
|
||||
describe "createSession" $ do
|
||||
it "Creates a session if needed" $ do
|
||||
createSession
|
||||
( InTmuxSession
|
||||
(SessionName "horses")
|
||||
)
|
||||
(SessionName "horses")
|
||||
[]
|
||||
`shouldBe` Just
|
||||
(NewSession (SessionName "horses"))
|
||||
`shouldBe` [ NewSession (SessionName "horses"),
|
||||
SwitchToSession (SessionName "horses")
|
||||
]
|
||||
it "Creates a session but does not switch to it if we're outside tmux" $ do
|
||||
createSession NotInTmuxSession (SessionName "horses") []
|
||||
`shouldBe` [NewSession (SessionName "horses")]
|
||||
it "Does nothing if one already exists" $ do
|
||||
createSession
|
||||
(InTmuxSession (SessionName "horses"))
|
||||
(SessionName "horses")
|
||||
[Running (SessionName "horses") undefined undefined 0]
|
||||
`shouldBe` Nothing
|
||||
[SessionName "horses"]
|
||||
`shouldBe` [SwitchToSession (SessionName "horses")]
|
||||
describe "createWindow" $ do
|
||||
it "Creates a window if needed" $ do
|
||||
createWindow
|
||||
@ -126,6 +135,13 @@ main = hspec $ do
|
||||
)
|
||||
]
|
||||
`shouldBe` [KillWindow (SessionName "horses") (WindowName "window2")]
|
||||
describe "attachToSession" $ do
|
||||
it "Attaches to new session if just created" $ do
|
||||
attachToSession NotInTmuxSession (SessionName "new-session") []
|
||||
`shouldBe` [AttachToSession (SessionName "new-session")]
|
||||
it "Switches back to old session if we're already in tmux" $ do
|
||||
attachToSession (InTmuxSession (SessionName "old-session")) (SessionName "new-session") []
|
||||
`shouldBe` [SwitchToSession (SessionName "old-session")]
|
||||
describe "ParseRunning" $ do
|
||||
it "Rejects nonsense" $ do
|
||||
parseSingle "sdfdsf" `shouldBe` Nothing
|
||||
|
Loading…
Reference in New Issue
Block a user