<commit_before>{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances #-}
-- --------------------------------------------------------------------------
-- -- |
-- -- Module      :  TilePrime.hs
-- -- Copyright   :  (c) <NAME> 2007
-- -- License     :  BSD3-style (see LICENSE)
-- --
-- -- Maintainer  :  <EMAIL>
-- -- Stability   :  unstable
-- -- Portability :  not portable
-- --
-- -- TilePrime. Tile windows filling gaps created by resize hints
-- --
-- -----------------------------------------------------------------------------
--

module XMonadContrib.TilePrime (
    -- * Usage
    -- $usage
    TilePrime(TilePrime)
    ) where

import Control.Monad (mplus)
import Data.List (genericLength)
import Graphics.X11.Xlib
import Graphics.X11.Xlib.Extras (getWMNormalHints)
import Operations
import XMonad hiding (trace)
import qualified StackSet as W
import {-#SOURCE#-} Config (borderWidth)

-- $usage
-- You can use this module with the following in your Config.hs file:
--
-- > import XMonadContrib.TilePrime
--
-- and add the following line to your 'layouts'
--
-- > , Layout $ TilePrime nmaster delta ratio False
--
-- Use True as the last argument to get a wide layout.

-- %import XMonadContrib.TilePrime
-- %layout , Layout $ TilePrime nmaster delta ratio False

data TilePrime a = TilePrime
                         { nmaster     :: Int
                         , delta, frac :: Rational
                         , flipped     :: Bool
                         } deriving (Show, Read)

instance LayoutClass TilePrime Window where
  description _ = "TilePrime"

  pureMessage c m = fmap resize (fromMessage m) `mplus`
                    fmap incmastern (fromMessage m)
    where
    resize Shrink = c { frac = max 0 $ frac c - delta c }
    resize Expand = c { frac = min 1 $ frac c + delta c }
    incmastern (IncMasterN d) = c { nmaster = max 0 $ nmaster c + d }

  doLayout c rect s = do
    let flp = flipped c
    let xs = W.integrate s
    hints <- withDisplay $ \ disp -> io (mapM (getWMNormalHints disp) xs)
    let xs' = zip xs hints
        (leftRect, rightRect)
          | null (drop 1 xs) = (rect, Rectangle 0 0 0 0)
          | flp       = splitVerticallyBy (frac c) rect
          | otherwise = splitHorizontallyBy (frac c) rect
        masters = fillWindows flp leftRect (take (nmaster c) xs')
        slaves  = fillWindows flp rightRect (drop (nmaster c) xs')
    return (masters ++ slaves, Nothing)

    where

    fillWindows _ _ [] = []
    fillWindows flp r ((x,hint):xs) = (x,r') : fillWindows flp rest xs
      where
      n = 1 + genericLength xs :: Rational

      (alloca, _) | flp       = splitHorizontallyBy (recip n) r
                  | otherwise = splitVerticallyBy (recip n) r

      (w,h) = applySizeHints hint `underBorders` (rect_width alloca, rect_height alloca)

      r'   = r { rect_width = w, rect_height = h }

      rest | flp       = r { rect_x      = rect_x r + toEnum (fromEnum w)
                           , rect_width  = rect_width r - w }
           | otherwise = r { rect_y      = rect_y r + toEnum (fromEnum h)
                           , rect_height = rect_height r - h }

-- | Transform a function on dimensions into one without regard for borders
underBorders :: (D -> D) -> D -> D
underBorders f = adjBorders 1 . f . adjBorders (-1)

-- | Modify dimensions by a multiple of the current borders
adjBorders             :: Dimension -> D -> D
adjBorders mult (w,h)  = (w+2*mult*borderWidth, h+2*mult*borderWidth)<commit_msg>TilePrime.hs: Correct behavior when number of windows <= nmaster<commit_after>{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances #-}
-- --------------------------------------------------------------------------
-- -- |
-- -- Module      :  TilePrime.hs
-- -- Copyright   :  (c) <NAME> 2007
-- -- License     :  BSD3-style (see LICENSE)
-- --
-- -- Maintainer  :  <EMAIL>
-- -- Stability   :  unstable
-- -- Portability :  not portable
-- --
-- -- TilePrime. Tile windows filling gaps created by resize hints
-- --
-- -----------------------------------------------------------------------------
--

module XMonadContrib.TilePrime (
    -- * Usage
    -- $usage
    TilePrime(TilePrime)
    ) where

import Control.Monad (mplus)
import Data.List (mapAccumL)
import Graphics.X11.Xlib
import Graphics.X11.Xlib.Extras (getWMNormalHints)
import Operations
import XMonad hiding (trace)
import qualified StackSet as W
import {-#SOURCE#-} Config (borderWidth)

-- $usage
-- You can use this module with the following in your Config.hs file:
--
-- > import XMonadContrib.TilePrime
--
-- and add the following line to your 'layouts'
--
-- > , Layout $ TilePrime nmaster delta ratio False
--
-- Use True as the last argument to get a wide layout.

-- %import XMonadContrib.TilePrime
-- %layout , Layout $ TilePrime nmaster delta ratio False

data TilePrime a = TilePrime
                         { nmaster     :: Int
                         , delta, frac :: Rational
                         , flipped     :: Bool
                         } deriving (Show, Read)

instance LayoutClass TilePrime Window where
  description _ = "TilePrime"

  pureMessage c m = fmap resize (fromMessage m) `mplus`
                    fmap incmastern (fromMessage m)
    where
    resize Shrink = c { frac = max 0 $ frac c - delta c }
    resize Expand = c { frac = min 1 $ frac c + delta c }
    incmastern (IncMasterN d) = c { nmaster = max 0 $ nmaster c + d }

  doLayout TilePrime { frac = f, nmaster = m, flipped = flp } rect s = do
    let xs = W.integrate s
    hints <- withDisplay $ \ disp -> io (mapM (getWMNormalHints disp) xs)
    let xs' = zip xs hints
        (leftRect, rightRect)
          | null (drop m xs) = (rect, Rectangle 0 0 0 0)
          | flp       = splitVerticallyBy f rect
          | otherwise = splitHorizontallyBy f rect
        (leftXs, rightXs) = splitAt m xs'
        masters = fillWindows leftRect leftXs
        slaves  = fillWindows rightRect rightXs
    return (masters ++ slaves, Nothing)

    where
    fillWindows r xs = snd $ mapAccumL aux (r,n) xs
      where n = fromIntegral (length xs) :: Rational

    aux (r,n) (x,hint) = ((rest,n-1),(x,r'))
      where
      (allocated, _) | flp       = splitHorizontallyBy (recip n) r
                     | otherwise = splitVerticallyBy (recip n) r

      (w,h) = applySizeHints hint `underBorders` rect_D allocated

      r'   = r { rect_width = w, rect_height = h }

      rest | flp       = r { rect_x      = rect_x r + toEnum (fromEnum w)
                           , rect_width  = rect_width r - w }
           | otherwise = r { rect_y      = rect_y r + toEnum (fromEnum h)
                           , rect_height = rect_height r - h }

rect_D :: Rectangle -> D
rect_D Rectangle { rect_width = w, rect_height = h } = (w,h)

-- | Transform a function on dimensions into one without regard for borders
underBorders :: (D -> D) -> D -> D
underBorders f = adjBorders 1 . f . adjBorders (-1)

-- | Modify dimensions by a multiple of the current borders
adjBorders             :: Dimension -> D -> D
adjBorders mult (w,h)  = (w+2*mult*borderWidth, h+2*mult*borderWidth)
{'fraction_non_alphanumeric': 0.14570466030320045, 'fraction_numerical': 0.006035934868051656, 'mean_word_length': 1.8637459807073955, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2037428', 'n_tokens_mistral': 2264, 'n_tokens_neox': 2115, 'n_words': 716}