ENH use tree for static devices
This commit is contained in:
parent
0fcf836d1d
commit
8ae0637978
|
@ -20,7 +20,6 @@ import Data.Either
|
||||||
import Data.List
|
import Data.List
|
||||||
import Data.List.Split (splitOn)
|
import Data.List.Split (splitOn)
|
||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
-- import qualified Data.Map.Ordered as O
|
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.Vector as V
|
import qualified Data.Vector as V
|
||||||
|
@ -292,8 +291,8 @@ getGroups = do
|
||||||
removableActions <- mapM mkAction =<< getRemovableDevices
|
removableActions <- mapM mkAction =<< getRemovableDevices
|
||||||
mtpActions <- mapM mkAction =<< getMTPDevices
|
mtpActions <- mapM mkAction =<< getMTPDevices
|
||||||
return $ mapMaybe mkGroup
|
return $ mapMaybe mkGroup
|
||||||
$ groupBy (\(hx, _, _) (hy, _, _) -> hx == hy)
|
$ groupBy (\(hx, _) (hy, _) -> hx == hy)
|
||||||
$ sortBy (\(hx, _, _) (hy, _, _) -> compare hx hy)
|
$ sortBy (\(hx, _) (hy, _) -> compare hx hy)
|
||||||
$ staticActions ++ removableActions ++ mtpActions
|
$ staticActions ++ removableActions ++ mtpActions
|
||||||
|
|
||||||
mountByAlias :: Bool -> String -> RofiIO MountConf ()
|
mountByAlias :: Bool -> String -> RofiIO MountConf ()
|
||||||
|
@ -301,32 +300,29 @@ mountByAlias unmountFlag alias = do
|
||||||
static <- asks mountconfStaticDevs
|
static <- asks mountconfStaticDevs
|
||||||
mapM_ (`mount` unmountFlag) $ configToTree static <$> M.lookup alias static
|
mapM_ (`mount` unmountFlag) $ configToTree static <$> M.lookup alias static
|
||||||
|
|
||||||
mkGroup :: [(Header, String, RofiIO MountConf ())] -> Maybe (RofiGroup MountConf)
|
mkGroup :: [(Header, ProtoAction [String])] -> Maybe (RofiGroup MountConf)
|
||||||
mkGroup [] = Nothing
|
mkGroup [] = Nothing
|
||||||
mkGroup as = let ((Header title _, _, _):_) = as in
|
mkGroup as = let ((Header title _, _):_) = as in
|
||||||
-- Just $ titledGroup title $ alignEntries $ toRofiActions $ fmap (\(_, e, a) -> (e, a)) as
|
Just $ titledGroup title $ toRofiActions $ alignEntries $ fmap snd as
|
||||||
Just $ titledGroup title $ toRofiActions $ fmap (\(_, e, a) -> (e, a)) as
|
|
||||||
|
|
||||||
-- alignSep :: String
|
alignSep :: String
|
||||||
-- alignSep = " | "
|
alignSep = " | "
|
||||||
|
|
||||||
alignSepPre :: String
|
alignEntries :: [ProtoAction [String]] -> [(String, RofiIO MountConf ())]
|
||||||
alignSepPre = "@@@"
|
alignEntries = withEntries
|
||||||
|
where
|
||||||
-- alignEntries :: RofiActions c -> RofiActions c
|
withEntries as = let entries = fmap (\(ProtoAction e _) -> e) as in
|
||||||
-- alignEntries = O.fromList . withKeys . O.assocs
|
zipWith (\e (ProtoAction _ a) -> (e, a)) (align entries) as
|
||||||
-- where
|
align = fmap (intercalate alignSep)
|
||||||
-- withKeys as = let (ks, vs) = unzip as in zip (align ks) vs
|
. transpose
|
||||||
-- align = fmap (intercalate alignSep)
|
. mapToLast pad
|
||||||
-- . transpose
|
. transpose
|
||||||
-- . mapToLast pad
|
|
||||||
-- . transpose
|
|
||||||
-- . fmap (splitOn alignSepPre)
|
-- . fmap (splitOn alignSepPre)
|
||||||
-- pad xs = let m = getMax xs in fmap (\x -> take m (x ++ repeat ' ')) xs
|
pad xs = let m = getMax xs in fmap (\x -> take m (x ++ repeat ' ')) xs
|
||||||
-- getMax = maximum . fmap length
|
getMax = maximum . fmap length
|
||||||
-- mapToLast _ [] = []
|
mapToLast _ [] = []
|
||||||
-- mapToLast _ [x] = [x]
|
mapToLast _ [x] = [x]
|
||||||
-- mapToLast f (x:xs) = f x : mapToLast f xs
|
mapToLast f (x:xs) = f x : mapToLast f xs
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- | Removable devices
|
-- | Removable devices
|
||||||
|
@ -353,7 +349,7 @@ instance Mountable Removable where
|
||||||
getLabel Removable { label = l } = l
|
getLabel Removable { label = l } = l
|
||||||
|
|
||||||
instance Actionable Removable where
|
instance Actionable Removable where
|
||||||
fmtEntry Removable { deviceSpec = d, label = l } = l ++ alignSepPre ++ d
|
fmtEntry Removable { deviceSpec = d, label = l } = [l, d]
|
||||||
|
|
||||||
groupHeader _ = Header "Removable Devices" 3
|
groupHeader _ = Header "Removable Devices" 3
|
||||||
|
|
||||||
|
@ -419,10 +415,10 @@ instance Mountable MTPFS where
|
||||||
|
|
||||||
isMounted MTPFS { mountpoint = dir } = io $ isDirMounted dir
|
isMounted MTPFS { mountpoint = dir } = io $ isDirMounted dir
|
||||||
|
|
||||||
getLabel = fmtEntry
|
getLabel MTPFS { description = d } = d
|
||||||
|
|
||||||
instance Actionable MTPFS where
|
instance Actionable MTPFS where
|
||||||
fmtEntry MTPFS { description = d } = d
|
fmtEntry d = [getLabel d]
|
||||||
|
|
||||||
groupHeader _ = Header "MTP Devices" 5
|
groupHeader _ = Header "MTP Devices" 5
|
||||||
|
|
||||||
|
@ -463,7 +459,11 @@ data Tree a = Tree a [Tree a] deriving (Eq, Show)
|
||||||
type StaticConfigTree = Tree DeviceConfig
|
type StaticConfigTree = Tree DeviceConfig
|
||||||
|
|
||||||
instance Actionable (Tree DeviceConfig) where
|
instance Actionable (Tree DeviceConfig) where
|
||||||
fmtEntry (Tree p _) = getLabel p
|
fmtEntry (Tree p@DeviceConfig{ _deviceData = d } _) = [getLabel p, target d]
|
||||||
|
where
|
||||||
|
target CIFSConfig{ _cifsRemote = r } = r
|
||||||
|
target SSHFSConfig{ _sshfsRemote = r } = r
|
||||||
|
target VeracryptConfig{ _veracryptVolume = v } = v
|
||||||
|
|
||||||
groupHeader (Tree DeviceConfig{ _deviceData = d } _) =
|
groupHeader (Tree DeviceConfig{ _deviceData = d } _) =
|
||||||
case d of
|
case d of
|
||||||
|
@ -481,7 +481,7 @@ configToTree devMap TreeConfig{ _treeParent = p, _treeChildren = c } =
|
||||||
go ds = configToTree devMap <$> mapMaybe (`M.lookup` devMap) ds
|
go ds = configToTree devMap <$> mapMaybe (`M.lookup` devMap) ds
|
||||||
|
|
||||||
instance Mountable a => Mountable (Tree a) where
|
instance Mountable a => Mountable (Tree a) where
|
||||||
mount (Tree p cs) False = mapM_ (`mount` False) cs >> mount p False
|
mount (Tree p cs) False = mapM_ (`mountMaybe` False) cs >> mount p False
|
||||||
mount (Tree p _) True = mount p True
|
mount (Tree p _) True = mount p True
|
||||||
|
|
||||||
isMounted (Tree p _) = isMounted p
|
isMounted (Tree p _) = isMounted p
|
||||||
|
@ -496,12 +496,11 @@ instance Mountable DeviceConfig where
|
||||||
mount c@DeviceConfig{ _deviceMount = MountConfig { _mountMountPoint = m }
|
mount c@DeviceConfig{ _deviceMount = MountConfig { _mountMountPoint = m }
|
||||||
, _deviceData = devData
|
, _deviceData = devData
|
||||||
} False = do
|
} False = do
|
||||||
mountRoot <- asks mountconfVolatilePath
|
m' <- getAbsMountpoint m
|
||||||
let m' = appendRoot mountRoot m
|
|
||||||
bracketOnError_ (mkDirMaybe m') (rmDirMaybe m') $ mount' m'
|
bracketOnError_ (mkDirMaybe m') (rmDirMaybe m') $ mount' m'
|
||||||
where
|
where
|
||||||
mount' mountpoint = io $ case devData of
|
mount' mountpoint = io $ case devData of
|
||||||
SSHFSConfig{ _sshfsRemote = r } ->
|
SSHFSConfig{ _sshfsRemote = r } -> do
|
||||||
runMountNotify "sshfs" [r, mountpoint] (getLabel c) False
|
runMountNotify "sshfs" [r, mountpoint] (getLabel c) False
|
||||||
CIFSConfig{ _cifsPassword = p } -> do
|
CIFSConfig{ _cifsPassword = p } -> do
|
||||||
res <- case p of
|
res <- case p of
|
||||||
|
@ -521,13 +520,13 @@ instance Mountable DeviceConfig where
|
||||||
printf "Failed to get volume password for %s" l
|
printf "Failed to get volume password for %s" l
|
||||||
|
|
||||||
mount c@DeviceConfig{ _deviceMount = MountConfig{ _mountMountPoint = m }
|
mount c@DeviceConfig{ _deviceMount = MountConfig{ _mountMountPoint = m }
|
||||||
, _deviceData = VeracryptConfig{}
|
, _deviceData = VeracryptConfig{} } True = do
|
||||||
} True = io $ do
|
m' <- getAbsMountpoint m
|
||||||
res <- runVeraCrypt "" ["-d", m]
|
res <- io $ runVeraCrypt "" ["-d", m']
|
||||||
notifyMounted (isRight res) True (getLabel c)
|
io $ notifyMounted (isRight res) True (getLabel c)
|
||||||
|
|
||||||
mount c@DeviceConfig{ _deviceMount = MountConfig { _mountMountPoint = m }} True =
|
mount c@DeviceConfig{ _deviceMount = MountConfig { _mountMountPoint = m }} True =
|
||||||
umountNotify (getLabel c) m
|
umountNotify (getLabel c) =<< getAbsMountpoint m
|
||||||
|
|
||||||
allInstalled DeviceConfig{ _deviceData = devData } = io $ isJust
|
allInstalled DeviceConfig{ _deviceData = devData } = io $ isJust
|
||||||
<$> findExecutable (exe devData)
|
<$> findExecutable (exe devData)
|
||||||
|
@ -536,10 +535,14 @@ instance Mountable DeviceConfig where
|
||||||
exe CIFSConfig{} = "mount.cifs"
|
exe CIFSConfig{} = "mount.cifs"
|
||||||
exe VeracryptConfig{} = "veracrypt"
|
exe VeracryptConfig{} = "veracrypt"
|
||||||
|
|
||||||
isMounted DeviceConfig{ _deviceMount = MountConfig{ _mountMountPoint = m }} = io $ isDirMounted m
|
isMounted DeviceConfig{ _deviceMount = MountConfig{ _mountMountPoint = m }} =
|
||||||
|
(io . isDirMounted) =<< getAbsMountpoint m
|
||||||
|
|
||||||
getLabel DeviceConfig{ _deviceMount = MountConfig{ _mountMountPoint = p, _mountLabel = l }} =
|
getLabel DeviceConfig{ _deviceMount = MountConfig{ _mountMountPoint = p, _mountLabel = l }} =
|
||||||
fromMaybe (takeBaseName p) l
|
fromMaybe (takeFileName p) l
|
||||||
|
|
||||||
|
getAbsMountpoint :: FilePath -> RofiIO MountConf FilePath
|
||||||
|
getAbsMountpoint p = asks $ flip appendRoot p . mountconfVolatilePath
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- | Mountable typeclass
|
-- | Mountable typeclass
|
||||||
|
@ -572,26 +575,30 @@ class Mountable a where
|
||||||
|
|
||||||
data Header = Header String Integer deriving (Show, Eq)
|
data Header = Header String Integer deriving (Show, Eq)
|
||||||
|
|
||||||
|
data ProtoAction a = ProtoAction a (RofiIO MountConf ())
|
||||||
|
|
||||||
instance Ord Header where
|
instance Ord Header where
|
||||||
compare (Header _ x) (Header _ y) = compare x y
|
compare (Header _ x) (Header _ y) = compare x y
|
||||||
|
|
||||||
class Mountable a => Actionable a where
|
class Mountable a => Actionable a where
|
||||||
-- | Return a string to go in the Rofi menu for the given type
|
-- | Return a string to go in the Rofi menu for the given type
|
||||||
fmtEntry :: a -> String
|
fmtEntry :: a -> [String]
|
||||||
fmtEntry = getLabel
|
fmtEntry d = [getLabel d]
|
||||||
|
|
||||||
groupHeader :: a -> Header
|
groupHeader :: a -> Header
|
||||||
|
|
||||||
-- | Given a mountable type, return a rofi action (string to go in the
|
-- | Given a mountable type, return a rofi action (string to go in the
|
||||||
-- Rofi prompt and an action to perform when it is selected)
|
-- Rofi prompt and an action to perform when it is selected)
|
||||||
mkAction :: a -> RofiIO MountConf (Header, String, RofiIO MountConf ())
|
mkAction :: a -> RofiIO MountConf (Header, ProtoAction [String])
|
||||||
mkAction dev = do
|
mkAction dev = do
|
||||||
m <- isMounted dev
|
m <- isMounted dev
|
||||||
i <- allInstalled dev
|
i <- allInstalled dev
|
||||||
let h = groupHeader dev
|
let h = groupHeader dev
|
||||||
let a = when i $ mountMaybe dev m
|
let action = when i $ mountMaybe dev m
|
||||||
let s = mountedPrefix m i ++ fmtEntry dev
|
let entry = case fmtEntry dev of
|
||||||
return (h, s, a)
|
(e:es) -> (mountedPrefix m i ++ e):es
|
||||||
|
_ -> []
|
||||||
|
return (h, ProtoAction entry action)
|
||||||
where
|
where
|
||||||
mountedPrefix False True = " "
|
mountedPrefix False True = " "
|
||||||
mountedPrefix True True = "* "
|
mountedPrefix True True = "* "
|
||||||
|
|
Loading…
Reference in New Issue