1

我将 XMonad 与 xmobar 结合使用,但我遇到了 xmobar 上显示的工作区未按数字排序的问题。因为工作区 ID 最终是字符串,所以它们按字典顺序排序。因此,假设我有 12 个工作区,它们将被排序为1 10 11 12 3 4 5 6 7 8 9,而不是1 2 3 4 5 6 7 8 9 10 11 12。我认为marshallPP是罪魁祸首,因为在引入独立屏幕之前,工作区在没有ppSort. 我知道有mkWsSort从比较函数创建排序函数,但是,我不确定如何编写比较函数。这是我的配置:

import System.IO
import XMonad
import XMonad.Hooks.DynamicLog
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.ServerMode
import XMonad.Hooks.SetWMName
import XMonad.Layout.IndependentScreens
import XMonad.Layout.Gaps
import XMonad.Layout.Spacing
import XMonad.Util.EZConfig (additionalKeysP)
import XMonad.Util.Run (spawnPipe)
import Data.List
import Data.Function
import qualified XMonad.StackSet as W
import qualified Data.Map as M
import XMonad.Util.WorkspaceCompare

myLayout = gaps [(U, 10), (R, 10), (L, 10), (D, 10)] $ spacingRaw True (Border 0 10 10 10) True (Border 10 10 10 10) True $
             layoutHook def

myWorkspaces = 
  [ (xK_1, "1")
  , (xK_2, "2")
  , (xK_3, "3")
  , (xK_4, "4")
  , (xK_5, "5")
  , (xK_6, "6")
  , (xK_7, "7")
  , (xK_8, "8")
  , (xK_9, "9")
  , (xK_0, "10")
  , (xK_minus, "11")
  , (xK_equal, "12")
  ]

clickable' :: WorkspaceId -> String
clickable' w = xmobarAction ("xmonadctl view\\\"" ++ w ++ "\\\"") "1" w

myKeys conf@(XConfig {XMonad.modMask = modMask}) = M.fromList $
    [ ((modMask, key), windows $ onCurrentScreen W.greedyView ws)
      | (key, ws) <- myWorkspaces
    ]
    ++
    [ ((modMask .|. shiftMask, key), windows $ onCurrentScreen W.shift ws)
      | (key, ws) <- myWorkspaces
    ]
    ++
    [
    -- Spawn the terminal
      ((modMask .|. shiftMask, xK_Return), spawn $ XMonad.terminal conf)
    
    -- Spawn dmenu
    , ((modMask, xK_p), spawn "dmenu_run")

    -- Close focused window 
    , ((modMask .|. shiftMask, xK_c), kill)
 
     -- Rotate through the available layout algorithms
    , ((modMask, xK_space ), sendMessage NextLayout)
 
    --  Reset the layouts on the current workspace to default
    , ((modMask .|. shiftMask, xK_space), setLayout $ XMonad.layoutHook conf)
 
    -- Resize viewed windows to the correct size
    , ((modMask, xK_n), refresh)
 
    -- Move focus to the next window
    , ((modMask, xK_Tab), windows W.focusDown)
 
    -- Move focus to the next window
    , ((modMask, xK_j), windows W.focusDown)
 
    -- Move focus to the previous window
    , ((modMask, xK_k), windows W.focusUp)
 
    -- Move focus to the master window
    , ((modMask, xK_m), windows W.focusMaster)
 
    -- Swap the focused window and the master window
    , ((modMask, xK_Return), windows W.swapMaster)
 
    -- Swap the focused window with the next window
    , ((modMask .|. shiftMask, xK_j), windows W.swapDown)
 
    -- Swap the focused window with the previous window
    , ((modMask .|. shiftMask, xK_k), windows W.swapUp)
 
    -- Shrink the master area
    , ((modMask, xK_h), sendMessage Shrink)
 
    -- Expand the master area
    , ((modMask, xK_l), sendMessage Expand)
 
    -- Push window back into tiling
    , ((modMask, xK_t), withFocused $ windows . W.sink)
 
    -- Increment the number of windows in the master area
    , ((modMask, xK_comma), sendMessage (IncMasterN 1))
 
    -- Deincrement the number of windows in the master area
    , ((modMask, xK_period), sendMessage (IncMasterN (-1)))
 
    -- toggle the status bar gap
    , ((modMask, xK_b), sendMessage ToggleStruts)
 
    -- Restart xmonad
    , ((modMask,  xK_q), broadcastMessage ReleaseResources >> restart "xmonad" True)
    ]

myAdditionalKeysP =
    [
      ("M-<F2>", spawn "thunar")
    , ("M-<F3>", spawn "firefox")
    , ("M-<F4>", spawn "code")
    , ("M-<F5>", spawn "thunderbird")
    , ("M-<Escape>", spawn "xfce4-appfinder")
    , ("M4-<Print>", spawn "xfce4-screenshooter")
    , ("M4-<KP_Add>", spawn "amixer -D pulse sset Master 5%+")
    , ("M4-<KP_Subtract>", spawn "amixer -D pulse sset Master 5%-")
    , ("M-C-p", spawn "passmenu") 
    , ("M-C-c", spawn "clipmenu")
    , ("M-C-m", spawn "mailwatch_restart")
    , ("M-C-x", spawn "xfce4-panel -r")
    , ("M-C-<Left>", spawn "playerctl previous")
    , ("M-C-<Right>", spawn "playerctl next")
    , ("M-C-<Space>", spawn "playerctl play-pause")
    ]

main = do
    xmprocs <- mapM (\i -> spawnPipe $ "xmobar ~/.config/xmobar/xmobarrc-" ++ show i ++ " -x" ++ show i) [0..1]
    xmonad $ docks def
        {
          workspaces = withScreens 2 (map show [1..12])
          , keys = myKeys
          , borderWidth = 2
          , focusedBorderColor = "#226fa5"
          , normalBorderColor = "#191919"
          , handleEventHook = serverModeEventHookCmd
                            <+> serverModeEventHook
                            <+> serverModeEventHookF "XMONAD_PRINT" (io . putStrLn)
          , layoutHook = avoidStruts myLayout
          , logHook = mapM_ dynamicLogWithPP $ zipWith pp xmprocs [0..1]
          , startupHook = setWMName "LG3D"
          , manageHook = manageDocks
        } `additionalKeysP` myAdditionalKeysP

pp h s = marshallPP s def 
    { ppOutput = hPutStrLn h
    , ppCurrent = xmobarColor "blue" "" . wrap "[" "]"
    , ppHiddenNoWindows = xmobarColor "grey" "" . clickable'
    , ppVisible = wrap "(" ")"
    , ppUrgent  = xmobarColor "red" "yellow"
    , ppOrder = \(ws:_:_:_) -> [pad ws]
    , ppHidden = clickable'
    }

我试图硬编码一个有序列表,但它没有用。我还尝试workspaces使用此函数对传递给的内容进行排序:

sortNumeric = sortBy (compare `on` (read :: String -> Int))

然而,这也没有奏效。

我该如何克服这个问题?

4

1 回答 1

1

可以看到 的类型签名mkWsSortX WorkspaceCompare -> X WorkspaceSortppSort需要一个X WorkspaceSort,所以你只需要提供一个X WorkspaceCompareWorkspaceCompare是 的别名WorkspaceId -> WorkspaceId -> OrderingWorkspaceId是 的别名String。所以基本上,这只是说你需要一个字符串比较函数的冗长路径。您可以通过尝试先将字符串读入 Ints 来比较字符串,然后比较两者:

import Text.Read
import Data.Ord

compareNumbers :: String -> String -> Ordering
compareNumbers a b =
    case (readMaybe a :: Maybe Int, readMaybe b :: Maybe Int) of
        -- if they're both valid numbers then compare them
        (Just x, Just y) -> compare x y
        -- push numbers to the front of strings
        (Just _, Nothing) -> LT
        (Nothing, Just _) -> GT
        -- strings get normal string comparison
        (Nothing, Nothing) -> compare a b

如果您所有的工作区都是数字,那么compareNumbers可以减少到compareNumbers = comparing (read :: String -> Int),或者如果您想将非数字推到前面,那么它可以减少到comparing (readMaybe :: String -> Maybe Int)

然后,您将其包装在Xmonad 中return,并将其传递给mkWsSort然后设置ppSort为:

-- ...
, ppSort = mkWsSort $ return compareNumbers
-- ...
于 2020-12-09T22:45:29.990 回答