diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,5 @@
+# Revision history for TaskMonad
+
+## 1.0.0 -- 2019-03-30
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2019, Max Magorsch
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* Neither the name of the copyright holder nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,150 @@
+
+# TaskMonad
+
+[![GHC Version](https://img.shields.io/badge/ghc-8.4.1%2B-blue.svg)](https://www.haskell.org/ghc/)
+[![Build](https://api.travis-ci.org/mmagorsc/taskmonad.svg?branch=master)](https://travis-ci.org/mmagorsc/taskmonad)
+[![Hackage](https://img.shields.io/badge/hackage-1.0.0-brightgreen.svg)](http://hackage.haskell.org/package/TaskMonad-1.0.0)
+[![CodeClimate](https://api.codeclimate.com/v1/badges/e4de6996bf5bb710d0e7/maintainability)](https://codeclimate.com/github/mmagorsc/taskmonad)
+[![Contributing](https://img.shields.io/badge/contributions-welcome-orange.svg)](#contributing)
+[![License](https://img.shields.io/badge/license-BSD-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
+
+## Table Of Contents 
+
+- [Basic Overview](#basic-overview)
+- [Installation](#installation)
+- [Usage](#usage)
+- [Features](#features)
+- [Documentation](#documentation)
+- [Contributing](#contributing)
+
+## Basic Overview
+
+Basically, TaskMonad provides a collection of tools which can be used to access taskwarrior from xmonad. For further information please refer to [the project site](https://taskmonad.magorsch.de)
+
+[![Screencast](https://raw.githubusercontent.com/mmagorsc/taskmonad/master/docs/images/taskmonad-screencast.gif)](https://taskmonad.magorsch.de)
+
+## Installation
+
+### Using cabal
+
+To install TaskMonad from hackage just execute:
+
+``` shell
+$ cabal update
+$ cabal install TaskMonad
+```
+
+Afterwards import TaskMonad in your `xmonad.hs`  
+
+``` haskell
+import TaskMonad
+```
+
+### Without cabal
+
+To install Taskmonad without using cabal just download and copy the source code into your `~/.xmonad/lib/` folder. The folder structure should afterwards look like this:
+
+``` shell
+.xmonad 
+|-- lib
+|   |-- Taskmonad.hs
+|   |-- Taskmonad
+|   |   |-- GridSelect.hs
+|   |   |-- Prompt.hs
+|   |   |-- ScratchPad.hs
+|   |   `-- Utils.hs
+|   |-- GridSelect
+|   |   `-- Extras.hs
+|   `-- ...
+|-- xmonad.hs
+```
+
+Afterwards import TaskMonad in your `xmonad.hs`  
+
+``` haskell
+import TaskMonad
+```
+
+## Usage
+To get started, add a manage hook for the taskwarrior scratchpad:
+
+``` haskell
+-- ...
+
+... , manageHook = namedScratchpadManageHook taskwarriorScratchpads
+```
+
+After that you can bind the taskwarrior prompt to a key to get started: 
+
+``` haskell
+... , ("M-p",     taskwarriorPrompt [(\x -> x == "processInbox", processInbox)])
+```
+
+You can also bind any other TaskMonad action to a key. For example:
+
+``` haskell
+... , ("M-S-p",   taskwarriorScratchpad)       -- Opens the taskwarrior scratchpad
+
+... , ("M-C-p",   taskSelect "status:pending") -- Displays all pending tasks
+
+... , ("M-C-S-p", tagSelect)                   -- Displays all tags using a gridselect
+```
+
+In general you can customize the tools ad libitum. A good way to get started is to implement custom actions for the taskwarrior prompt. Please refer to taskwarriorPrompt for further information. 
+
+## Features 
+
+Basically TaskMonad implements a few methods which can be used to follow the GTD principles. However you can customize these methods or even implement completely different workflows. Please refer to [the documentation](https://taskmonad.magorsch.de) and [Customizing](#customizing) for further details. 
+
+### Step 1: Capture
+
+You can easily capture tasks, ideas or notes using the `taskwarriorPrompt` like this:
+
+[![Capture](https://raw.githubusercontent.com/mmagorsc/taskmonad/master/docs/images/capture.png)](https://taskmonad.magorsch.de)
+
+### Step 2 & 3: Clarify & Organize
+
+You can clarify and organize your tasks using processInbox. It implements the typical Getting Things Done workflow using GridSelects:
+
+[![Clarify and Organize](https://raw.githubusercontent.com/mmagorsc/taskmonad/master/docs/images/workflow.png)](https://taskmonad.magorsch.de)
+
+
+### Step 4: Reflect
+
+You can implement your own custom daily- and weeklyreview routines. For example you can use togglePriority to adjust the priority of tasks during the daily- / weeklyreview like this:
+
+[![Reflect](https://raw.githubusercontent.com/mmagorsc/taskmonad/master/docs/images/taskmonad-gridselect.png)](https://taskmonad.magorsch.de)
+
+### Step 5: Engage
+
+To decide which task to do next, you can use a collection of gridselects. You can use tagSelect, projectSelect, dueSelect to display a gridselect to filter the tasks by tag, project or due date. However you can also display all pending tasks using taskSelect like this:
+
+[![Engage](https://raw.githubusercontent.com/mmagorsc/taskmonad/master/docs/images/engage.png)](https://taskmonad.magorsch.de)
+
+### Scratchpad
+
+The taskwarrior scratchpad is used to display taskwarrior reports that have been invoked using the taskwarrior prompt. However, you can use the scratchpad at your convenience. After you have added a manage hook as described in _Installation_, you can bind a key to taskwarriorScratchpad. The Scratchpad will look like this
+
+[![Scratchpad](https://raw.githubusercontent.com/mmagorsc/taskmonad/master/docs/images/taskmonad-scratchpad.png)](https://taskmonad.magorsch.de)
+
+## Customizing 
+
+TaskMonad.hs implements a few methods which are useful to use GTD. However you don't have to use any of these methods if you don't use GTD or just don't like to use them. 
+
+TaskMonad exposes four modules which can be used to implement your own custom workflow:
+
+- [TaskMonad.Prompt](https://taskmonad.magorsch.de/TaskMonad-Prompt.html) --      provides wrappers around XMonad.Prompt.Input for usage with taskwarrior 
+- [TaskMonad.ScratchPad](https://taskmonad.magorsch.de/TaskMonad-Scratchpad.html) --  TaskMonad.ScratchPad provides a wrapper around XMonad.Util.NamedScratchpad that can be used to display taskwarrior commands 
+- [TaskMonad.GridSelect](https://taskmonad.magorsch.de/TaskMonad-GridSelect.html) --  uses GridSelect.Extras to display various information from taskwarrior. 
+- [TaskMonad.Utils](https://taskmonad.magorsch.de/TaskMonad-Utils.html) --       is used to communicate with taskwarrior from haskell.
+
+You can use these modules at your convenience. However, in case please consider creating an issue or submitting a pull request so that others can also benefit from your changes.
+
+
+## Documentation
+
+The documentation of TaskMonad is generated using haddock. You can find the latest version [here](https://taskmonad.magorsch.de).
+
+## Contributing
+
+Contributions are welcome. You have an idea, suggestion for improvement or have found a bug? Just create an issue or send a pull request. 
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/TaskMonad.cabal b/TaskMonad.cabal
new file mode 100644
--- /dev/null
+++ b/TaskMonad.cabal
@@ -0,0 +1,49 @@
+-- Initial TaskMonad.cabal generated by cabal init.  For further
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                TaskMonad
+version:             1.0.0
+synopsis:            A collection of tools which can be used to access taskwarrior from xmonad.
+description:         TaskMonad is a collection of tools which can be used to access taskwarrior from xmonad.
+homepage:            https://taskmonad.magorsch.de
+bug-reports:         https://github.com/mmagorsc/taskmonad/issues
+tested-with:         GHC ==8.6.4 || ==8.4.4 || ==8.4.1
+license:             BSD3
+license-file:        LICENSE
+author:              Max Magorsch
+maintainer:          max@magorsch.de
+-- copyright:
+category:            XMonad
+build-type:          Simple
+extra-source-files:  README.md
+                     ChangeLog.md
+cabal-version:       >=1.10
+
+
+source-repository head
+  type:     git
+  location: https://github.com/mmagorsc/taskmonad
+
+
+
+
+library
+  exposed-modules: TaskMonad
+                   TaskMonad.GridSelect
+                   TaskMonad.Prompt
+                   TaskMonad.Utils
+                   TaskMonad.ScratchPad
+                   GridSelect.Extras
+  -- other-modules:   Paths_xmonad
+  build-depends:   base                  >= 4.11 && < 5
+                 , X11                   >= 1.8 && < 1.10
+                 , X11-xft               >= 0.3.1 && < 0.4
+                 , mtl                   >= 2.2.2 && < 2.3
+                 , random                >= 1.1 && < 1.2
+                 , containers            >= 0.5.11 && < 0.6
+                 , unix                  >= 2.7.2 && < 2.8
+                 , process               >= 1.6.3 && < 1.7
+                 , xmonad                >= 0.14.2 && <= 0.15
+                 , xmonad-contrib        >= 0.14 && <= 0.15
+  hs-source-dirs:  src
+  default-language: Haskell2010
diff --git a/src/GridSelect/Extras.hs b/src/GridSelect/Extras.hs
new file mode 100644
--- /dev/null
+++ b/src/GridSelect/Extras.hs
@@ -0,0 +1,972 @@
+{-# LANGUAGE ScopedTypeVariables, TupleSections, GeneralizedNewtypeDeriving, TypeSynonymInstances, FlexibleInstances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  GridSelect.Extras
+-- Copyright   :  Clemens Fruhwirth <clemens@endorphin.org>, Max Magorsch <max@magorsch.de>
+-- License     :  BSD-style (see LICENSE)
+--
+-- Maintainer  :  Max Magorsch <max@magorsch.de>
+-- Stability   :  unstable
+-- Portability :  unportable
+--
+-- GridSelect.Extras adds a method to [XMonad.Actions.GridSelect]
+-- (http://hackage.haskell.org/package/xmonad-contrib-0.15/docs/XMonad-Actions-GridSelect.html)
+-- that displays a message at the top of the screen while using the normal GridSelect. 
+--
+-----------------------------------------------------------------------------
+
+module GridSelect.Extras
+  (
+    -- * Usage
+    -- $usage
+    runSelectedActionWithMessageAndIcon
+  ,
+
+    -- ** Screenshots
+    -- $screenshots
+
+    -- ** Customizing
+    -- $customizing
+
+    -- * Configuration
+    GSConfig(..)
+  , def
+  , buildDefaultGSConfig
+  , defaultNavigation
+  )
+where
+import           Data.Maybe
+import           Data.Bits
+import           Data.Char
+import qualified Data.Foldable
+import           Data.Ord                       ( comparing )
+import           Control.Applicative
+import           Control.Monad.State
+import           Control.Arrow
+import           Data.List                     as L
+import qualified Data.Map                      as M
+import           XMonad                  hiding ( liftX )
+import           XMonad.Util.Font
+import           XMonad.Prompt                  ( mkUnmanagedWindow )
+import           XMonad.StackSet               as W
+import           XMonad.Layout.Decoration
+import           XMonad.Util.Image
+import           XMonad.Util.NamedWindows
+import           XMonad.Util.XUtils
+import           XMonad.Actions.WindowBringer   ( bringWindow )
+import           Text.Printf
+import           System.Random                  ( mkStdGen
+                                                , genRange
+                                                , next
+                                                )
+import           Data.Word                      ( Word8 )
+
+-- $usage
+--
+-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
+--
+-- >    import qualified GridSelect.Extras
+--
+-- Then add a keybinding, e.g.
+--
+-- >    , ((modm, xK_g), gridselect gsconfig message actions)
+-- >         where
+-- >            gridselect = GridSelect.Extras.runSelectedActionWithMessage
+-- >            gsconfig   = GridSelect.Extras.def
+-- >            message    = "Please choose an option:"
+-- >            actions    = [ ("Option #1", unsafeSpawn "notify-send 'Option #1'"),
+-- >                           ("Option #2", unsafeSpawn "notify-send 'Option #2'") ]
+--
+--
+-- This module also supports displaying an icon in the message window. To do so, just use 'runSelectedActionWithMessageAndIcon' like so:
+--
+-- >    , ((modm, xK_g), gridselect gsconfig message icon actions)
+-- >         where
+-- >             gridselect = GridSelect.Extras.runSelectedActionWithMessageAndIcon
+-- >             icon       = [[True,  False, False],
+-- >                           [False, True,  False],
+-- >                           [True,  False, True ]]
+-- >             -- ...  
+--
+--
+-- $screenshots
+--
+-- Selecting an action:
+--
+-- <<https://raw.githubusercontent.com/mmagorsc/taskmonad/master/docs/images/gridselect-extras.png>>
+--
+--
+--
+-- $customizing
+--
+-- It is possible to customize GridSelect.Extras the same way GridSelect is customized. Please refer to the [GridSelect Documentation](http://hackage.haskell.org/package/xmonad-contrib-0.15/docs/XMonad-Actions-GridSelect.html) for further information.
+
+-- | The 'Default' instance gives a basic configuration for 'gridselect', with
+-- the colorizer chosen based on the type.
+--
+-- If you want to replace the 'gs_colorizer' field, use 'buildDefaultGSConfig'
+-- instead of 'def' to avoid ambiguous type variables.
+data GSConfig a = GSConfig {
+      gs_cellheight :: Integer,
+      gs_cellwidth :: Integer,
+      gs_cellpadding :: Integer,
+      gs_colorizer :: a -> Bool -> X (String, String),
+      gs_font :: String,
+      gs_navigate :: TwoD a (Maybe a),
+      gs_rearranger :: Rearranger a,
+      gs_originFractX :: Double,
+      gs_originFractY :: Double,
+      gs_bordercolor :: String
+}
+
+-- | That is 'fromClassName' if you are selecting a 'Window', or
+-- 'defaultColorizer' if you are selecting a 'String'. The catch-all instance
+-- @HasColorizer a@ uses the 'focusedBorderColor' and 'normalBorderColor'
+-- colors.
+class HasColorizer a where
+    defaultColorizer :: a -> Bool -> X (String, String)
+
+instance {-# OVERLAPPING #-} HasColorizer Window where
+    defaultColorizer = fromClassName
+
+instance {-# OVERLAPPING #-} HasColorizer String where
+    defaultColorizer = stringColorizer
+
+instance {-# OVERLAPPING #-} HasColorizer a where
+    defaultColorizer _ isFg =
+        let getColor = if isFg then focusedBorderColor else normalBorderColor
+        in asks $ (, "black") . getColor . config
+
+instance {-# OVERLAPPING #-} HasColorizer a => Default (GSConfig a) where
+    def = buildDefaultGSConfig defaultColorizer
+
+{-# DEPRECATED defaultGSConfig "Use def (from Data.Default, and re-exported from XMonad.Actions.GridSelect) instead." #-}
+defaultGSConfig :: HasColorizer a => GSConfig a
+defaultGSConfig = def
+
+type TwoDPosition = (Integer, Integer)
+
+type TwoDElementMap a = [(TwoDPosition,(String,a))]
+
+data TwoDState a = TwoDState { td_curpos :: TwoDPosition
+                             , td_availSlots :: [TwoDPosition]
+                             , td_elements :: [(String,a)]
+                             , td_gsconfig :: GSConfig a
+                             , td_font :: XMonadFont
+                             , td_paneX :: Integer
+                             , td_paneY :: Integer
+                             , td_drawingWin :: Window
+                             , td_searchString :: String
+                             , td_elementmap :: TwoDElementMap a
+                             }
+
+generateElementmap :: TwoDState a -> X (TwoDElementMap a)
+generateElementmap s = do
+  rearrangedElements <- rearranger searchString sortedElements
+  return $ zip positions rearrangedElements
+ where
+  TwoDState { td_availSlots = positions, td_gsconfig = gsconfig, td_searchString = searchString }
+    = s
+  GSConfig { gs_rearranger = rearranger } = gsconfig
+  -- Filter out any elements that don't contain the searchString (case insensitive)
+  filteredElements =
+    L.filter ((searchString `isInfixOfI`) . fst) (td_elements s)
+  -- Sorts the elementmap
+  sortedElements = orderElementmap searchString filteredElements
+  -- Case Insensitive version of isInfixOf
+  needle `isInfixOfI` haystack = upper needle `isInfixOf` upper haystack
+  upper = map toUpper
+
+
+-- | We enforce an ordering such that we will always get the same result. If the
+-- elements position changes from call to call of gridselect, then the shown
+-- positions will also change when you search for the same string. This is
+-- especially the case when using gridselect for showing and switching between
+-- workspaces, as workspaces are usually shown in order of last visited.  The
+-- chosen ordering is "how deep in the haystack the needle is" (number of
+-- characters from the beginning of the string and the needle).
+orderElementmap :: String -> [(String, a)] -> [(String, a)]
+orderElementmap searchString elements = if not $ null searchString
+  then sortedElements
+  else elements
+ where
+  upper = map toUpper
+  -- Calculates a (score, element) tuple where the score is the depth of the (case insensitive) needle.
+  calcScore element =
+    ( length $ takeWhile (not . isPrefixOf (upper searchString))
+                         (tails . upper . fst $ element)
+    , element
+    )
+  -- Use the score and then the string as the parameters for comparing, making
+  -- it consistent even when two strings that score the same, as it will then be
+  -- sorted by the strings, making it consistent.
+  compareScore   = comparing (\(score, (str, _)) -> (score, str))
+  sortedElements = map snd . sortBy compareScore $ map calcScore elements
+
+
+newtype TwoD a b = TwoD { unTwoD :: StateT (TwoDState a) X b }
+    deriving (Monad,Functor,MonadState (TwoDState a))
+
+instance Applicative (TwoD a) where
+    (<*>) = ap
+    pure = return
+
+liftX :: X a1 -> TwoD a a1
+liftX = TwoD . lift
+
+evalTwoD :: TwoD a1 a -> TwoDState a1 -> X a
+evalTwoD m s = flip evalStateT s $ unTwoD m
+
+diamondLayer :: (Enum a, Num a, Eq a) => a -> [(a, a)]
+diamondLayer 0 = [(0, 0)]
+diamondLayer n =
+  -- tr = top right
+  --  r = ur ++ 90 degree clock-wise rotation of ur
+  let tr = [ (x, n - x) | x <- [0 .. n - 1] ]
+      r  = tr ++ map (\(x, y) -> (y, -x)) tr
+  in  r ++ map (negate *** negate) r
+
+diamond :: (Enum a, Num a, Eq a) => [(a, a)]
+diamond = concatMap diamondLayer [0 ..]
+
+diamondRestrict
+  :: Integer -> Integer -> Integer -> Integer -> [(Integer, Integer)]
+diamondRestrict x y originX originY =
+  L.filter (\(x', y') -> abs x' <= x && abs y' <= y)
+    . map (\(x', y') -> (x' + fromInteger originX, y' + fromInteger originY))
+    . take 1000
+    $ diamond
+
+findInElementMap :: (Eq a) => a -> [(a, b)] -> Maybe (a, b)
+findInElementMap pos = find ((== pos) . fst)
+
+drawWinBox
+  :: Window
+  -> XMonadFont
+  -> (String, String)
+  -> String
+  -> Integer
+  -> Integer
+  -> String
+  -> Integer
+  -> Integer
+  -> Integer
+  -> X ()
+drawWinBox win font (fg, bg) bc ch cw text x y cp = withDisplay $ \dpy -> do
+  gc       <- liftIO $ createGC dpy win
+  bordergc <- liftIO $ createGC dpy win
+  liftIO $ do
+    Just fgcolor     <- initColor dpy fg
+    Just bgcolor     <- initColor dpy bg
+    Just bordercolor <- initColor dpy bc
+    setForeground dpy gc fgcolor
+    setBackground dpy gc bgcolor
+    setForeground dpy bordergc bordercolor
+    fillRectangle dpy
+                  win
+                  gc
+                  (fromInteger x)
+                  (fromInteger y)
+                  (fromInteger cw)
+                  (fromInteger ch)
+    drawRectangle dpy
+                  win
+                  bordergc
+                  (fromInteger x)
+                  (fromInteger y)
+                  (fromInteger cw)
+                  (fromInteger ch)
+  stext <- shrinkWhile
+    (shrinkIt shrinkText)
+    (\n -> do
+      size <- liftIO $ textWidthXMF dpy font n
+      return $ size > fromInteger (cw - (2 * cp))
+    )
+    text
+  -- calculate the offset to vertically centre the text based on the ascender and descender
+  (asc, desc) <- liftIO $ textExtentsXMF font stext
+  let offset = ((ch - fromIntegral (asc + desc)) `div` 2) + fromIntegral asc
+  printStringXMF dpy
+                 win
+                 font
+                 gc
+                 bg
+                 fg
+                 (fromInteger (x + cp))
+                 (fromInteger (y + offset))
+                 stext
+  liftIO $ freeGC dpy gc
+  liftIO $ freeGC dpy bordergc
+
+updateAllElements :: TwoD a ()
+updateAllElements = do
+  s <- get
+  updateElements (td_elementmap s)
+
+grayoutElements :: Int -> TwoD a ()
+grayoutElements skip = do
+  s <- get
+  updateElementsWithColorizer grayOnly $ drop skip (td_elementmap s)
+  where grayOnly _ _ = return ("#808080", "#808080")
+
+updateElements :: TwoDElementMap a -> TwoD a ()
+updateElements elementmap = do
+  s <- get
+  updateElementsWithColorizer (gs_colorizer (td_gsconfig s)) elementmap
+
+updateElementsWithColorizer
+  :: (a -> Bool -> X (String, String)) -> TwoDElementMap a -> TwoD a ()
+updateElementsWithColorizer colorizer elementmap = do
+  TwoDState { td_curpos = curpos, td_drawingWin = win, td_gsconfig = gsconfig, td_font = font, td_paneX = paneX, td_paneY = paneY } <-
+    get
+  let cellwidth  = gs_cellwidth gsconfig
+      cellheight = gs_cellheight gsconfig
+      paneX'     = div (paneX - cellwidth) 2
+      paneY'     = div (paneY - cellheight) 2
+      updateElement (pos@(x, y), (text, element)) = liftX $ do
+        colors <- colorizer element (pos == curpos)
+        drawWinBox win
+                   font
+                   colors
+                   (gs_bordercolor gsconfig)
+                   cellheight
+                   cellwidth
+                   text
+                   (paneX' + x * cellwidth)
+                   (paneY' + y * cellheight)
+                   (gs_cellpadding gsconfig)
+  mapM_ updateElement elementmap
+
+stdHandle :: Event -> TwoD a (Maybe a) -> TwoD a (Maybe a)
+stdHandle ButtonEvent { ev_event_type = t, ev_x = x, ev_y = y } contEventloop
+  | t == buttonRelease = do
+    s@TwoDState { td_paneX = px, td_paneY = py, td_gsconfig = (GSConfig ch cw _ _ _ _ _ _ _ _) } <-
+      get
+    let gridX = (fi x - (px - cw) `div` 2) `div` cw
+        gridY = (fi y - (py - ch) `div` 2) `div` ch
+    case lookup (gridX, gridY) (td_elementmap s) of
+      Just (_, el) -> return (Just el)
+      Nothing      -> contEventloop
+  | otherwise = contEventloop
+
+stdHandle ExposeEvent{} contEventloop = updateAllElements2 >> contEventloop
+
+stdHandle _             contEventloop = contEventloop
+
+-- | Embeds a key handler into the X event handler that dispatches key
+-- events to the key handler, while non-key event go to the standard
+-- handler.
+makeXEventhandler
+  :: ((KeySym, String, KeyMask) -> TwoD a (Maybe a)) -> TwoD a (Maybe a)
+makeXEventhandler keyhandler =
+  fix
+    $ \me -> join $ liftX $ withDisplay $ \d -> liftIO $ allocaXEvent $ \e -> do
+        maskEvent d (exposureMask .|. keyPressMask .|. buttonReleaseMask) e
+        ev <- getEvent e
+        if ev_event_type ev == keyPress
+          then do
+            (ks, s) <- lookupString $ asKeyEvent e
+            return $ do
+              mask <- liftX $ cleanMask (ev_state ev)
+              keyhandler (fromMaybe xK_VoidSymbol ks, s, mask)
+          else return $ stdHandle ev me
+
+-- | When the map contains (KeySym,KeyMask) tuple for the given event,
+-- the associated action in the map associated shadows the default key
+-- handler
+shadowWithKeymap
+  :: M.Map (KeyMask, KeySym) a
+  -> ((KeySym, String, KeyMask) -> a)
+  -> (KeySym, String, KeyMask)
+  -> a
+shadowWithKeymap keymap dflt keyEvent@(ks, _, m') =
+  fromMaybe (dflt keyEvent) (M.lookup (m', ks) keymap)
+
+-- Helper functions to use for key handler functions
+
+-- | Closes gridselect returning the element under the cursor
+select :: TwoD a (Maybe a)
+select = do
+  s <- get
+  return $ snd . snd <$> findInElementMap (td_curpos s) (td_elementmap s)
+
+-- | Closes gridselect returning no element.
+cancel :: TwoD a (Maybe a)
+cancel = return Nothing
+
+-- | Sets the absolute position of the cursor.
+setPos :: (Integer, Integer) -> TwoD a ()
+setPos newPos = do
+  s <- get
+  let elmap         = td_elementmap s
+      newSelectedEl = findInElementMap newPos (td_elementmap s)
+      oldPos        = td_curpos s
+  when (isJust newSelectedEl && newPos /= oldPos) $ do
+    put s { td_curpos = newPos }
+    updateElements2 (catMaybes [findInElementMap oldPos elmap, newSelectedEl])
+
+-- | Moves the cursor by the offsets specified
+move :: (Integer, Integer) -> TwoD a ()
+move (dx, dy) = do
+  s <- get
+  let (x, y) = td_curpos s
+      newPos = (x + dx, y + dy)
+  setPos newPos
+
+moveNext :: TwoD a ()
+moveNext = do
+  position <- gets td_curpos
+  elems    <- gets td_elementmap
+  let n = length elems
+      m = case findIndex (\p -> fst p == position) elems of
+        Nothing -> Nothing
+        Just k | k == n - 1 -> Just 0
+               | otherwise  -> Just (k + 1)
+  whenJust m $ \i -> setPos (fst $ elems !! i)
+
+movePrev :: TwoD a ()
+movePrev = do
+  position <- gets td_curpos
+  elems    <- gets td_elementmap
+  let n = length elems
+      m = case findIndex (\p -> fst p == position) elems of
+        Nothing -> Nothing
+        Just 0  -> Just (n - 1)
+        Just k  -> Just (k - 1)
+  whenJust m $ \i -> setPos (fst $ elems !! i)
+
+-- | Apply a transformation function the current search string
+transformSearchString :: (String -> String) -> TwoD a ()
+transformSearchString f = do
+  s <- get
+  let oldSearchString = td_searchString s
+      newSearchString = f oldSearchString
+  when (newSearchString /= oldSearchString) $ do
+    -- FIXME curpos might end up outside new bounds
+    let s' = s { td_searchString = newSearchString }
+    m <- liftX $ generateElementmap s'
+    let s''    = s' { td_elementmap = m }
+        oldLen = length $ td_elementmap s
+        newLen = length $ td_elementmap s''
+    -- All the elements in the previous element map should be
+    -- grayed out, except for those which will be covered by
+    -- elements in the new element map.
+    when (newLen < oldLen) $ grayoutElements newLen
+    put s''
+    updateAllElements
+
+-- | By default gridselect used the defaultNavigation action, which
+-- binds left,right,up,down and vi-style h,l,j,k navigation. Return
+-- quits gridselect, returning the selected element, while Escape
+-- cancels the selection. Slash enters the substring search mode. In
+-- substring search mode, every string-associated keystroke is
+-- added to a search string, which narrows down the object
+-- selection. Substring search mode comes back to regular navigation
+-- via Return, while Escape cancels the search. If you want that
+-- navigation style, add 'defaultNavigation' as 'gs_navigate' to your
+-- 'GSConfig' object. This is done by 'buildDefaultGSConfig' automatically.
+defaultNavigation :: TwoD a (Maybe a)
+defaultNavigation = makeXEventhandler
+  $ shadowWithKeymap navKeyMap navDefaultHandler
+ where
+  navKeyMap = M.fromList
+    [ ((0, xK_Escape)     , cancel)
+    , ((0, xK_Return)     , select)
+    , ((0, xK_slash)      , substringSearch defaultNavigation)
+    , ((0, xK_Left)       , move (-1, 0) >> defaultNavigation)
+    , ((0, xK_h)          , move (-1, 0) >> defaultNavigation)
+    , ((0, xK_Right)      , move (1, 0) >> defaultNavigation)
+    , ((0, xK_l)          , move (1, 0) >> defaultNavigation)
+    , ((0, xK_Down)       , move (0, 1) >> defaultNavigation)
+    , ((0, xK_j)          , move (0, 1) >> defaultNavigation)
+    , ((0, xK_Up)         , move (0, -1) >> defaultNavigation)
+    , ((0, xK_k)          , move (0, -1) >> defaultNavigation)
+    , ((0, xK_Tab)        , moveNext >> defaultNavigation)
+    , ((0, xK_n)          , moveNext >> defaultNavigation)
+    , ((shiftMask, xK_Tab), movePrev >> defaultNavigation)
+    , ((0, xK_p)          , movePrev >> defaultNavigation)
+    ]
+  -- The navigation handler ignores unknown key symbols, therefore we const
+  navDefaultHandler = const defaultNavigation
+
+-- | This navigation style combines navigation and search into one mode at the cost of losing vi style
+-- navigation. With this style, there is no substring search submode,
+-- but every typed character is added to the substring search.
+navNSearch :: TwoD a (Maybe a)
+navNSearch = makeXEventhandler
+  $ shadowWithKeymap navNSearchKeyMap navNSearchDefaultHandler
+ where
+  navNSearchKeyMap = M.fromList
+    [ ((0, xK_Escape)     , cancel)
+    , ((0, xK_Return)     , select)
+    , ((0, xK_Left)       , move (-1, 0) >> navNSearch)
+    , ((0, xK_Right)      , move (1, 0) >> navNSearch)
+    , ((0, xK_Down)       , move (0, 1) >> navNSearch)
+    , ((0, xK_Up)         , move (0, -1) >> navNSearch)
+    , ((0, xK_Tab)        , moveNext >> navNSearch)
+    , ((shiftMask, xK_Tab), movePrev >> navNSearch)
+    , ( (0, xK_BackSpace)
+      , transformSearchString (\s -> if s == "" then "" else init s)
+        >> navNSearch
+      )
+    ]
+  -- The navigation handler ignores unknown key symbols, therefore we const
+  navNSearchDefaultHandler (_, s, _) = do
+    transformSearchString (++ s)
+    navNSearch
+
+-- | Navigation submode used for substring search. It returns to the
+-- first argument navigation style when the user hits Return.
+substringSearch :: TwoD a (Maybe a) -> TwoD a (Maybe a)
+substringSearch returnNavigation = fix $ \me ->
+  let searchKeyMap = M.fromList
+        [ ((0, xK_Escape), transformSearchString (const "") >> returnNavigation)
+        , ((0, xK_Return), returnNavigation)
+        , ( (0, xK_BackSpace)
+          , transformSearchString (\s -> if s == "" then "" else init s) >> me
+          )
+        ]
+      searchDefaultHandler (_, s, _) = do
+        transformSearchString (++ s)
+        me
+  in  makeXEventhandler $ shadowWithKeymap searchKeyMap searchDefaultHandler
+
+
+-- FIXME probably move that into Utils?
+-- Conversion scheme as in http://en.wikipedia.org/wiki/HSV_color_space
+hsv2rgb :: Fractional a => (Integer, a, a) -> (a, a, a)
+hsv2rgb (h, s, v) =
+  let hi = div h 60 `mod` 6 :: Integer
+      f  = ((fromInteger h / 60) - fromInteger hi) :: Fractional a => a
+      q  = v * (1 - f)
+      p  = v * (1 - s)
+      t  = v * (1 - (1 - f) * s)
+  in  case hi of
+        0 -> (v, t, p)
+        1 -> (q, v, p)
+        2 -> (p, v, t)
+        3 -> (p, q, v)
+        4 -> (t, p, v)
+        5 -> (v, p, q)
+        _ -> error "The world is ending. x mod a >= a."
+
+-- | Default colorizer for Strings
+stringColorizer :: String -> Bool -> X (String, String)
+stringColorizer s active =
+  let seed x = toInteger (sum $ map ((* x) . fromEnum) s) :: Integer
+      (r, g, b) = hsv2rgb
+        ( seed 83 `mod` 360
+        , fromInteger (seed 191 `mod` 1000) / 2500 + 0.4
+        , fromInteger (seed 121 `mod` 1000) / 2500 + 0.4
+        )
+  in  if active
+        then return ("#faff69", "black")
+        else return
+          ( "#" ++ concatMap
+            (twodigitHex . (round :: Double -> Word8) . (* 256))
+            [r, g, b]
+          , "white"
+          )
+
+-- | Colorize a window depending on it's className.
+fromClassName :: Window -> Bool -> X (String, String)
+fromClassName w active = runQuery className w >>= flip defaultColorizer active
+
+twodigitHex :: Word8 -> String
+twodigitHex = printf "%02x"
+
+-- | A colorizer that picks a color inside a range,
+-- and depending on the window's class.
+colorRangeFromClassName
+  :: (Word8, Word8, Word8) -- ^ Beginning of the color range
+  -> (Word8, Word8, Word8) -- ^ End of the color range
+  -> (Word8, Word8, Word8) -- ^ Background of the active window
+  -> (Word8, Word8, Word8) -- ^ Inactive text color
+  -> (Word8, Word8, Word8) -- ^ Active text color
+  -> Window
+  -> Bool
+  -> X (String, String)
+colorRangeFromClassName startC endC activeC inactiveT activeT w active = do
+  classname <- runQuery className w
+  if active
+    then return (rgbToHex activeC, rgbToHex activeT)
+    else return
+      (rgbToHex $ mix startC endC $ stringToRatio classname, rgbToHex inactiveT)
+ where
+  rgbToHex :: (Word8, Word8, Word8) -> String
+  rgbToHex (r, g, b) = '#' : twodigitHex r ++ twodigitHex g ++ twodigitHex b
+
+-- | Creates a mix of two colors according to a ratio
+-- (1 -> first color, 0 -> second color).
+mix
+  :: (Word8, Word8, Word8)
+  -> (Word8, Word8, Word8)
+  -> Double
+  -> (Word8, Word8, Word8)
+mix (r1, g1, b1) (r2, g2, b2) r = (mix' r1 r2, mix' g1 g2, mix' b1 b2)
+  where mix' a b = truncate $ (fi a * r) + (fi b * (1 - r))
+
+-- | Generates a Double from a string, trying to
+-- achieve a random distribution.
+-- We create a random seed from the sum of all characters
+-- in the string, and use it to generate a ratio between 0 and 1
+stringToRatio :: String -> Double
+stringToRatio "" = 0
+stringToRatio s =
+  let gen       = mkStdGen $ sum $ map fromEnum s
+      range     = (\(a, b) -> b - a) $ genRange gen
+      randomInt = foldr1 combine $ replicate 20 next
+      combine f1 f2 g = let (_, g') = f1 g in f2 g'
+  in  fi (fst $ randomInt gen) / fi range
+
+-- | Brings up a 2D grid of elements in the center of the screen, and one can
+-- select an element with cursors keys. The selected element is returned.
+gridselect :: GSConfig a -> [(String, a)] -> X (Maybe a)
+gridselect _        []       = return Nothing
+gridselect gsconfig elements = withDisplay $ \dpy -> do
+  rootw <- asks theRoot
+  scr   <- gets $ screenRect . W.screenDetail . W.current . windowset
+  win   <- liftIO $ mkUnmanagedWindow dpy
+                                      (defaultScreenOfDisplay dpy)
+                                      rootw
+                                      (rect_x scr)
+                                      (rect_y scr)
+                                      (rect_width scr)
+                                      (rect_height scr)
+  liftIO $ mapWindow dpy win
+  liftIO $ selectInput dpy
+                       win
+                       (exposureMask .|. keyPressMask .|. buttonReleaseMask)
+  status <- io
+    $ grabKeyboard dpy win True grabModeAsync grabModeAsync currentTime
+  io $ grabPointer dpy
+                   win
+                   True
+                   buttonReleaseMask
+                   grabModeAsync
+                   grabModeAsync
+                   none
+                   none
+                   currentTime
+  font <- initXMF (gs_font gsconfig)
+  let screenWidth  = toInteger $ rect_width scr
+      screenHeight = toInteger $ rect_height scr
+  selectedElement <- if status == grabSuccess
+    then do
+      let
+        restriction ss cs =
+          (fromInteger ss / fromInteger (cs gsconfig) - 1) / 2 :: Double
+        restrictX = floor $ restriction screenWidth gs_cellwidth
+        restrictY = floor $ restriction screenHeight gs_cellheight
+        originPosX =
+          floor
+            $ (gs_originFractX gsconfig - (1 / 2))
+            * 2
+            * fromIntegral restrictX
+        originPosY =
+          floor
+            $ (gs_originFractY gsconfig - (1 / 2))
+            * 2
+            * fromIntegral restrictY
+        coords = diamondRestrict restrictX restrictY originPosX originPosY
+        s      = TwoDState
+          { td_curpos       = head coords
+          , td_availSlots   = coords
+          , td_elements     = elements
+          , td_gsconfig     = gsconfig
+          , td_font         = font
+          , td_paneX        = screenWidth
+          , td_paneY        = screenHeight
+          , td_drawingWin   = win
+          , td_searchString = ""
+          , td_elementmap   = []
+          }
+      m <- generateElementmap s
+      evalTwoD (updateAllElements >> gs_navigate gsconfig)
+               (s { td_elementmap = m })
+    else return Nothing
+  liftIO $ do
+    unmapWindow dpy win
+    destroyWindow dpy win
+    ungrabPointer dpy currentTime
+    sync dpy False
+  releaseXMF font
+  return selectedElement
+
+-- | Like `gridSelect' but with the current windows and their titles as elements
+gridselectWindow :: GSConfig Window -> X (Maybe Window)
+gridselectWindow gsconf = windowMap >>= gridselect gsconf
+
+-- | Brings up a 2D grid of windows in the center of the screen, and one can
+-- select a window with cursors keys. The selected window is then passed to
+-- a callback function.
+withSelectedWindow :: (Window -> X ()) -> GSConfig Window -> X ()
+withSelectedWindow callback conf = do
+  mbWindow <- gridselectWindow conf
+  Data.Foldable.forM_ mbWindow callback
+--    case mbWindow of
+--        Just w -> callback w
+--        Nothing -> return ()
+
+windowMap :: X [(String, Window)]
+windowMap = do
+  ws <- gets windowset
+  mapM keyValuePair (W.allWindows ws)
+  where keyValuePair w = (, w) `fmap` decorateName' w
+
+decorateName' :: Window -> X String
+decorateName' w = show <$> getName w
+
+-- | Builds a default gs config from a colorizer function.
+buildDefaultGSConfig :: (a -> Bool -> X (String, String)) -> GSConfig a
+buildDefaultGSConfig col = GSConfig 50
+                                    130
+                                    10
+                                    col
+                                    "xft:Sans-8"
+                                    defaultNavigation
+                                    noRearranger
+                                    (1 / 2)
+                                    (1 / 2)
+                                    "white"
+
+-- | Brings selected window to the current workspace.
+bringSelected :: GSConfig Window -> X ()
+bringSelected = withSelectedWindow $ \w -> do
+  windows (bringWindow w)
+  XMonad.focus w
+  windows W.shiftMaster
+
+-- | Switches to selected window's workspace and focuses that window.
+goToSelected :: GSConfig Window -> X ()
+goToSelected = withSelectedWindow $ windows . W.focusWindow
+
+-- | Select an application to spawn from a given list
+spawnSelected :: GSConfig String -> [String] -> X ()
+spawnSelected conf lst = gridselect conf (zip lst lst) >>= flip whenJust spawn
+
+-- | Select an action and run it in the X monad
+runSelectedAction :: GSConfig (X ()) -> [(String, X ())] -> X ()
+runSelectedAction conf actions = do
+  selectedActionM <- gridselect conf actions
+  fromMaybe (return ()) selectedActionM
+--    case selectedActionM of
+--        Just selectedAction -> selectedAction
+--        Nothing -> return ()
+
+-- | Select a workspace and view it using the given function
+-- (normally 'W.view' or 'W.greedyView')
+--
+-- Another option is to shift the current window to the selected workspace:
+--
+-- > gridselectWorkspace (\ws -> W.greedyView ws . W.shift ws)
+gridselectWorkspace
+  :: GSConfig WorkspaceId -> (WorkspaceId -> WindowSet -> WindowSet) -> X ()
+gridselectWorkspace conf viewFunc =
+  gridselectWorkspace' conf (windows . viewFunc)
+
+-- | Select a workspace and run an arbitrary action on it.
+gridselectWorkspace' :: GSConfig WorkspaceId -> (WorkspaceId -> X ()) -> X ()
+gridselectWorkspace' conf func = withWindowSet $ \ws -> do
+  let wss =
+        map W.tag $ W.hidden ws ++ map W.workspace (W.current ws : W.visible ws)
+  gridselect conf (zip wss wss) >>= flip whenJust func
+
+-- $rearrangers
+--
+-- Rearrangers allow for arbitrary post-filter rearranging of the grid
+-- elements.
+--
+-- For example, to be able to switch to a new dynamic workspace by typing
+-- in its name, you can use the following keybinding action:
+--
+-- > import XMonad.Actions.DynamicWorkspaces (addWorkspace)
+-- >
+-- > gridselectWorkspace' defaultGSConfig
+-- >                          { gs_navigate   = navNSearch
+-- >                          , gs_rearranger = searchStringRearrangerGenerator id
+-- >                          }
+-- >                      addWorkspace
+
+-- | A function taking the search string and a list of elements, and
+-- returning a potentially rearranged list of elements.
+type Rearranger a = String -> [(String, a)] -> X [(String, a)]
+
+-- | A rearranger that leaves the elements unmodified.
+noRearranger :: Rearranger a
+noRearranger _ = return
+
+-- | A generator for rearrangers that append a single element based on the
+-- search string, if doing so would not be redundant (empty string or value
+-- already present).
+searchStringRearrangerGenerator :: (String -> a) -> Rearranger a
+searchStringRearrangerGenerator f =
+  let r "" xs = return xs
+      r s xs | s `elem` map fst xs = return xs
+             | otherwise           = return $ xs ++ [(s, f s)]
+  in  r
+
+
+
+----------------------------------------------------------------------------------------------
+--                                        custom part                                       --
+----------------------------------------------------------------------------------------------
+
+
+-- | A custom colorizer that colors depending on the title of the grid column
+myCustomColorizer :: String -> a -> Bool -> X (String, String)
+myCustomColorizer text _ p
+  | p = pure ("#f44336", "#1a1a1a")
+  | otherwise = if "MIT" `isInfixOf` text
+    then pure ("#4caf50", "#1a1a1a")
+    else if "BIG" `isInfixOf` text
+      then pure ("#2196f3", "#1a1a1a")
+      else pure ("#1a1a1a", "gray")
+
+
+-- | Select an action and run it in the X monad. Furthermore display a message on top of the screen.
+runSelectedActionWithMessageAndIcon
+  :: GSConfig (X ()) -> String -> [[Bool]] -> [(String, X ())] -> X ()
+runSelectedActionWithMessageAndIcon conf message icon actions = do
+  selectedActionM <- gridselectWithMessageAndIcon conf message icon actions
+  fromMaybe (return ()) selectedActionM
+--    case selectedActionM of
+--        Just selectedAction -> selectedAction
+--        Nothing -> return ()
+
+
+-- | Brings up a 2D grid of elements in the center of the screen, and one can
+-- select an element with cursors keys. The selected element is returned.
+gridselectWithMessageAndIcon
+  :: GSConfig a -> String -> [[Bool]] -> [(String, a)] -> X (Maybe a)
+gridselectWithMessageAndIcon _ _ _ [] = return Nothing
+gridselectWithMessageAndIcon gsconfig message icon elements =
+  withDisplay $ \dpy -> do
+    rootw <- asks theRoot
+    scr   <- gets $ screenRect . W.screenDetail . W.current . windowset
+    win   <- liftIO $ mkUnmanagedWindow dpy
+                                        (defaultScreenOfDisplay dpy)
+                                        rootw
+                                        (rect_x scr)
+                                        (rect_y scr)
+                                        (rect_width scr)
+                                        (rect_height scr)
+    liftIO $ mapWindow dpy win
+
+    message_win <- createNewWindow (Rectangle 450 50 1000 60) Nothing "" True
+    liftIO $ mapWindow dpy message_win
+    fs <- initXMF "xft:Inconsolata:size=14"
+    paintTextAndIcons message_win
+                      fs
+                      1000
+                      60
+                      1
+                      "#1a1a1a"
+                      "gray"
+                      "gray"
+                      "#1a1a1a"
+                      [AlignCenter]
+                      [message]
+                      [CenterLeft 10]
+                      [icon]
+
+    liftIO $ selectInput dpy
+                         win
+                         (exposureMask .|. keyPressMask .|. buttonReleaseMask)
+    status <- io
+      $ grabKeyboard dpy win True grabModeAsync grabModeAsync currentTime
+    io $ grabPointer dpy
+                     win
+                     True
+                     buttonReleaseMask
+                     grabModeAsync
+                     grabModeAsync
+                     none
+                     none
+                     currentTime
+    font <- initXMF (gs_font gsconfig)
+    let screenWidth  = toInteger $ rect_width scr
+        screenHeight = toInteger $ rect_height scr
+    selectedElement <- if status == grabSuccess
+      then do
+        let
+          restriction ss cs =
+            (fromInteger ss / fromInteger (cs gsconfig) - 1) / 2 :: Double
+          restrictX = floor $ restriction screenWidth gs_cellwidth
+          restrictY = floor $ restriction screenHeight gs_cellheight
+          originPosX =
+            floor
+              $ (gs_originFractX gsconfig - (1 / 2))
+              * 2
+              * fromIntegral restrictX
+          originPosY =
+            floor
+              $ (gs_originFractY gsconfig - (1 / 2))
+              * 2
+              * fromIntegral restrictY
+          coords = diamondRestrict restrictX restrictY originPosX originPosY
+          s      = TwoDState
+            { td_curpos       = head coords
+            , td_availSlots   = coords
+            , td_elements     = elements
+            , td_gsconfig     = gsconfig
+            , td_font         = font
+            , td_paneX        = screenWidth
+            , td_paneY        = screenHeight
+            , td_drawingWin   = win
+            , td_searchString = ""
+            , td_elementmap   = []
+            }
+        m <- generateElementmap s
+        evalTwoD (updateAllElements2 >> gs_navigate gsconfig)
+                 (s { td_elementmap = m })
+      else return Nothing
+    liftIO $ do
+--      unmapWindow dpy message_win
+      destroyWindow dpy message_win
+
+      unmapWindow dpy win
+      destroyWindow dpy win
+      ungrabPointer dpy currentTime
+      sync dpy False
+    releaseXMF font
+    return selectedElement
+
+
+updateAllElements2 :: TwoD a ()
+updateAllElements2 = do
+  s <- get
+  updateElements2 (td_elementmap s)
+
+
+updateElements2 :: TwoDElementMap a -> TwoD a ()
+updateElements2 elementmap = do
+  s <- get
+  updateElementsWithColorizer2 myCustomColorizer elementmap
+
+
+updateElementsWithColorizer2
+  :: (String -> a -> Bool -> X (String, String))
+  -> TwoDElementMap a
+  -> TwoD a ()
+updateElementsWithColorizer2 colorizer elementmap = do
+  TwoDState { td_curpos = curpos, td_drawingWin = win, td_gsconfig = gsconfig, td_font = font, td_paneX = paneX, td_paneY = paneY } <-
+    get
+  let cellwidth  = gs_cellwidth gsconfig
+      cellheight = gs_cellheight gsconfig
+      paneX'     = div (paneX - cellwidth) 2
+      paneY'     = div (paneY - cellheight) 2
+      updateElement (pos@(x, y), (text, element)) = liftX $ do
+--            colors <- colorizer element (pos == curpos)
+        colors <- colorizer text element (pos == curpos)
+        drawWinBox win
+                   font
+                   colors
+                   (gs_bordercolor gsconfig)
+                   cellheight
+                   cellwidth
+                   text
+                   (paneX' + x * cellwidth)
+                   (paneY' + y * cellheight)
+                   (gs_cellpadding gsconfig)
+  mapM_ updateElement elementmap
diff --git a/src/TaskMonad.hs b/src/TaskMonad.hs
new file mode 100644
--- /dev/null
+++ b/src/TaskMonad.hs
@@ -0,0 +1,366 @@
+{-# LANGUAGE ScopedTypeVariables, TypeSynonymInstances, FlexibleInstances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  TaskMonad
+-- Copyright   :  Max magorsch <max@magorsch.de>
+-- License     :  BSD-style (see LICENSE)
+--
+-- Maintainer  :  Max Magorsch <max@magorsch.de>
+-- Stability   :  unstable
+-- Portability :  unportable
+--
+-- TaskMonad bundles a number of tools that can be used to directly interact
+-- with taskwarrior from within xmonad. Furthermore, workflows following the
+-- Getting Things Done principles are implemented.
+--
+--
+-----------------------------------------------------------------------------
+
+module TaskMonad
+  (
+       -- * Usage
+       -- $usage
+    
+       -- * Step 1: Capture
+       -- $capture
+    taskwarriorPrompt
+  ,
+
+       -- * Step 2 & 3: Clarify & Organize
+       -- $organize
+    processInbox
+  ,
+
+       -- * Step 4: Reflect
+       -- $reflect
+    togglePriority
+  ,
+
+       -- * Step 5: Engage
+       -- $engage
+    taskSelect
+  , dueSelect
+  , tagSelect
+  , projectSelect
+  ,
+
+       -- * Scratchpad
+       -- $scratchpad
+    taskwarriorScratchpads
+  , taskwarriorScratchpad
+
+       -- * All Components
+       -- $components
+  )
+where
+
+import           Data.List
+import           Data.Maybe
+import           System.Process
+import           System.IO
+import           Control.Monad                  ( filterM )
+
+import           XMonad                  hiding ( liftX )
+import           XMonad.Util.Font
+import qualified XMonad.StackSet               as W
+import           XMonad.Layout.Decoration
+import           XMonad.Prompt
+import           XMonad.Prompt.Input
+import           XMonad.Util.Image
+import           XMonad.Util.NamedWindows
+import           XMonad.Util.XUtils
+import           XMonad.Util.NamedScratchpad
+import           XMonad.Util.Run
+import           XMonad.Actions.GridSelect
+
+import qualified GridSelect.Extras
+
+import           TaskMonad.Prompt
+import           TaskMonad.ScratchPad
+import           TaskMonad.Utils
+import           TaskMonad.GridSelect
+
+-- $usage
+-- To install Taskmonad just copy the source code into your @~/.xmonad/lib/@ folder.
+-- The folder structure should afterwards look like this:
+--
+-- > .xmonad 
+-- > |-- lib
+-- > |   |-- Taskmonad.hs
+-- > |   |-- Taskmonad
+-- > |   |   |-- GridSelect.hs
+-- > |   |   |-- Prompt.hs
+-- > |   |   |-- ScratchPad.hs
+-- > |   |   `-- Utils.hs
+-- > |   |-- GridSelect
+-- > |   |   `-- Extras.hs
+-- > |   `-- ...
+-- > |-- xmonad.hs
+--
+-- Afterwards import TaskMonad and add a manage hook for the taskwarrior scratchpad:
+--
+-- > import TaskMonad
+-- > 
+-- > -- ...
+-- >
+-- > ... , manageHook = namedScratchpadManageHook taskwarriorScratchpads
+--
+-- After that you can bind the taskwarrior prompt to a key to get started: 
+--
+-- > ... , ("M-p",     taskwarriorPrompt [(\x -> x == "processInbox", processInbox)])
+--
+-- You can also bind any other TaskMonad action to a key. For example:
+--
+-- > ... , ("M-S-p",   taskwarriorScratchpad)       -- Opens the taskwarrior scratchpad
+-- >
+-- > ... , ("M-C-p",   taskSelect "status:pending") -- Displays all pending tasks
+-- >
+-- > ... , ("M-C-S-p", tagSelect)                   -- Displays all tags
+--
+-- In general you can customize the tools ad libitum. A good way to get started is to implement custom actions for the taskwarrior prompt. Please refer to 'taskwarriorPrompt' for further information.  
+
+
+-- $capture
+--
+-- You can easily capture tasks, ideas or notes using the 'taskwarriorPrompt' like this:
+--
+-- << https://raw.githubusercontent.com/mmagorsc/taskmonad/master/docs/images/capture.png >>
+--
+
+-- $organize
+-- You can clarify and organize your tasks using 'processInbox'.
+-- It implements the typical Getting Things Done workflow using GridSelects:
+-- 
+-- << https://raw.githubusercontent.com/mmagorsc/taskmonad/master/docs/images/workflow.png >>
+--
+
+-- $reflect
+-- You can implement your own custom daily- and weeklyreview routines.
+-- For example you can use 'togglePriority' to adjust the priority of tasks
+-- during the daily- / weeklyreview like this:
+--
+-- << https://raw.githubusercontent.com/mmagorsc/taskmonad/master/docs/images/taskmonad-gridselect.png >>
+
+-- $engage
+-- To decide which task to do next, you can use a collection of gridselects.
+-- You can use 'tagSelect', 'projectSelect', 'dueSelect' to display a gridselect
+-- to filter the tasks by tag, project or due date. However you can also display
+-- all pending tasks using 'taskSelect' like this:
+--
+-- << https://raw.githubusercontent.com/mmagorsc/taskmonad/master/docs/images/engage.png >>
+
+-- $scratchpad
+-- The taskwarrior scratchpad is used to display taskwarrior reports that
+-- have been invoked using the taskwarrior prompt. However, you can use the
+-- scratchpad at your convenience. Just add a manage hook:
+--
+-- > ... , manageHook = namedScratchpadManageHook taskwarriorScratchpads
+--
+-- Afterwards you can bind a key to 'taskwarriorScratchpad'. The Scratchpad will look like this
+--
+-- << https://raw.githubusercontent.com/mmagorsc/taskmonad/master/docs/images/taskmonad-scratchpad.png >>
+
+-- $components
+-- * 'TaskMonad'
+--
+--     * 'TaskMonad.Prompt'
+--     * 'TaskMonad.Scratchpad'
+--     * 'TaskMonad.GridSelect'
+--     * 'TaskMonad.Utils'
+--
+-- * 'GridSelect.Extras'
+
+
+-- | Opens a set of gridselects used to process the inbox using the Getting Things Done workflow
+processInbox :: X ()
+processInbox = io (getTaskwarriorTaskList "+INBOX" ["id", "description"])
+  >>= \ts -> startInboxProcessing ts
+
+
+-- | Recursively processes a given list of tasks using the typical GTD workflow. 
+startInboxProcessing :: [[String]] -> X ()
+startInboxProcessing []       = dummyAction
+startInboxProcessing (t : ts) = twgs
+  ("Actionable?  " ++ t !! 1, [("YES", actionable), ("NO", not_actionable)])
+ where
+  not_actionable = twgs
+    ( "Next Steps: " ++ t !! 1
+    , [ ("[Back]"         , startInboxProcessing (t : ts))
+      , ("Reference"      , moveToFile t ts)
+      , ("Project Support", moveToFile t ts)
+      , ("Someday/Later"  , somedayLater t ts)
+      , ("Trash"          , trash t ts)
+      ]
+    )
+
+  actionable = twgs
+    ( "Does it take multiple steps?"
+    , [ ("[Back]", startInboxProcessing (t : ts))
+      , ("YES"   , makeProject t ts)
+      , ("NO"    , single_step)
+      ]
+    )
+
+  single_step = twgs
+    ( "Does it take less than 2 minutes?"
+    , [("[Back]", actionable), ("YES", do_it), ("NO", more_than_2_min)]
+    )
+
+  do_it =
+    twgs ("Do it now!", [("[Back]", single_step), ("Finished", done t ts)])
+
+  more_than_2_min = twgs
+    ( "Next Steps: " ++ t !! 1
+    , [ ("[Back]"          , single_step)
+      , ("Move to calendar", calendar t ts)
+      , ("Waiting For"     , waitingFor t ts)
+      , ("Edit Task"       , edit_task)
+      ]
+    )
+
+  edit_task = twgs
+    ( "How to process task: " ++ head t
+    , [ ("[Back]"         , more_than_2_min)
+      , ("[Finish]"       , startInboxProcessing ts)
+      , ("Free Editing"   , editTaskAction t ts)
+      , ("Set Tags"       , editTaskAction t ts)
+      , ("Set Description", editTaskAction t ts)
+      , ("Set Due Date"   , editTaskAction t ts)
+      , ("Set Project"    , editTaskAction t ts)
+      , ("Set Context"    , editTaskAction t ts)
+      ]
+    )
+
+
+-- | Sends a message to the notification daemon 
+notify :: MonadIO m => String -> m ()
+notify message = unsafeSpawn $ "notify-send '" ++ message ++ "'"
+
+
+-- | Opens a GridSelect with a custom message and the taskwarrior icon
+twgs :: (String, [(String, X ())]) -> X ()
+twgs (message, actions) = GridSelect.Extras.runSelectedActionWithMessageAndIcon
+  defaultTWGSExtraConfig
+  message
+  twicon
+  actions
+
+
+-- | Deletes the current task. Afterwards the remaining tasks will be processed.
+trash
+  :: [String] -- ^ the current task
+  -> [[String]] -- ^ the remaining tasks
+  -> X ()
+trash t ts = do
+  runTmuxCommand $ "echo 'yes' | task " ++ head t ++ " delete"
+  notify $ "Deleted Task:\n\n " ++ (t !! 1)
+  startInboxProcessing ts
+
+
+-- | Sets a task to done. Afterwards the remaining tasks will be processed.
+done
+  :: [String] -- ^ the current task
+  -> [[String]] -- ^ the remaining tasks
+  -> X ()
+done t ts = do
+  runTmuxCommand $ "echo 'yes' | task " ++ head t ++ " done"
+  notify $ "Done Task:\n\n " ++ (t !! 1)
+  startInboxProcessing ts
+
+
+-- | Changes the tag of the current task from INBOX to SOMEDAY
+-- Afterwards the task will be set as done and the remaining tasks will be processed.
+somedayLater
+  :: [String] -- ^ the current task
+  -> [[String]] -- ^ the remaining tasks
+  -> X ()
+somedayLater t ts = do
+  runTmuxCommand $ "task " ++ head t ++ " modify -INBOX +SOMEDAY"
+  notify $ "Changed Task:\n\n " ++ (t !! 1) ++ "\n\n to Somday/Maybe"
+  startInboxProcessing ts
+
+
+-- | Changes the tag of the current task from INBOX to WAITINGFOR
+-- Afterwards the remaining tasks will be processed.
+waitingFor
+  :: [String] -- ^ the current task
+  -> [[String]] -- ^ the remaining tasks
+  -> X ()
+waitingFor t ts = do
+  runTmuxCommand $ "task " ++ head t ++ " modify -INBOX +WAITINGFOR"
+  notify $ "Changed Task:\n\n  " ++ (t !! 1) ++ "\n\n to Waiting For"
+  startInboxProcessing ts
+
+
+-- | Moves the information of the current task to a markdown file. 
+-- Afterwards the task will be set as done and the remaining tasks will be processed.
+moveToFile
+  :: [String] -- ^ the current task
+  -> [[String]] -- ^ the remaining tasks
+  -> X ()
+moveToFile t ts = do
+  runTmuxCommand
+    $  "task information "
+    ++ head t
+    ++ " >> ~/reference/inbox.md && echo 'yes' | task "
+    ++ head t
+    ++ " done"
+  notify
+    $ "Moved the task:\n\n "
+    ++ (t !! 1)
+    ++ "\n\n to the file: \n\n ~/reference/inbox.md.\n \n Please consider editing the file."
+  startInboxProcessing ts
+
+
+-- | Opens a customPrompt to create an appointment using
+-- [gcalcli](https://github.com/insanum/gcalcli)
+-- Afterwards the task will be set as done and the remaining tasks will be processed.
+calendar
+  :: [String] -- ^ the current task
+  -> [[String]] -- ^ the remaining tasks
+  -> X ()
+calendar t ts = customPrompt "gcalcli add" [] (addAndContinue t ts)
+ where
+  addAndContinue t ts x = do
+    runTmuxCommand ("gcalcli add --noprompt " ++ x)
+    notify "Created Appointment."
+    done t ts
+
+
+-- | Opens a customPrompt to create a project for a given task
+-- Afterwards the task will be set as done and the remaining tasks will be processed.
+makeProject
+  :: [String] -- ^ the current task
+  -> [[String]] -- ^ the remaining tasks
+  -> X ()
+makeProject t ts = do
+  notify ("Please create your first task for the project: \n\n " ++ t !! 1)
+  customPrompt "task add" [] (addAndContinue t ts)
+ where
+  addAndContinue t ts x = do
+    runTmuxCommand ("task add " ++ x)
+    done t ts
+
+
+-- | Opens a customPrompt in order to modify the current taskwarrior task.
+-- Afterwards the remaining tasks will be processed.
+editTaskAction
+  :: [String] -- ^ the current task
+  -> [[String]] -- ^ the remaining tasks
+  -> X ()
+editTaskAction t ts = do
+  notify "Please edit your task."
+  customPrompt ("task " ++ head t ++ " modify") [] (addAndContinue t ts)
+ where
+  addAndContinue t ts x = do
+    runTmuxCommand ("task " ++ head t ++ " modify " ++ x)
+    notify "Edited the task"
+    startInboxProcessing ts
+
+
+-- | A dummy action for testing purposes
+dummyAction :: X ()
+dummyAction = createTWwindow >>= deleteWindow
+ where
+  createTWwindow =
+    createNewWindow (Rectangle 450 150 1000 60) Nothing "Test" True
diff --git a/src/TaskMonad/GridSelect.hs b/src/TaskMonad/GridSelect.hs
new file mode 100644
--- /dev/null
+++ b/src/TaskMonad/GridSelect.hs
@@ -0,0 +1,270 @@
+{-# LANGUAGE ScopedTypeVariables, TypeSynonymInstances, FlexibleInstances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  TaskMonad.GridSelect
+-- Copyright   :  Max Magorsch <max@magorsch.de>
+-- License     :  BSD-style (see LICENSE)
+--
+-- Maintainer  :  Max Magorsch <max@magorsch.de>
+-- Stability   :  unstable
+-- Portability :  unportable
+--
+-- TaskMonad.GridSelect uses 'GridSelect.Extras' to display various information from taskwarrior. 
+--
+-----------------------------------------------------------------------------
+
+module TaskMonad.GridSelect
+  (
+       -- * Screenshot
+       -- $screenshots
+       -- 
+
+       -- * Possible GridSelects
+    taskSelect
+  , taskSelectWithConfig
+  , tagSelect
+  , tagSelectWithConfig
+  , projectSelect
+  , projectSelectWithConfig
+  , dueSelect
+  , dueSelectWithConfig
+  , togglePriority
+  , togglePriorityWithConfig
+  ,
+
+       -- * Configuration
+    buildTWGSExtraConfig
+  , buildTWGSConfig
+  , defaultTWGSConfig
+  , defaultTWGSExtraConfig
+  )
+where
+
+import           Data.List
+import           Data.Maybe
+import           System.Process
+import           System.IO
+import           Control.Monad                  ( filterM )
+
+import           XMonad                  hiding ( liftX )
+import           XMonad.Util.Font
+import qualified XMonad.StackSet               as W
+import           XMonad.Layout.Decoration
+import           XMonad.Prompt
+import           XMonad.Prompt.Input
+import           XMonad.Util.Image
+import           XMonad.Util.NamedWindows
+import           XMonad.Util.XUtils
+import           XMonad.Util.NamedScratchpad
+import           XMonad.Util.Run
+import           XMonad.Actions.GridSelect
+
+import qualified GridSelect.Extras
+
+import           TaskMonad.Utils
+import           TaskMonad.ScratchPad
+
+-- $screenshots
+-- 'togglePriority' in action:
+-- 
+-- << https://raw.githubusercontent.com/mmagorsc/taskmonad/master/docs/images/taskmonad-gridselect.png >>
+
+
+-- | A GridSelect displaying a filtered list of all taskwarrior tasks
+taskSelectWithConfig
+  :: String -- ^ a filter to be applied, please refer to [TaskWarrior Filter](https://taskwarrior.org/docs/filter.html) for further information
+  -> GSConfig (X ()) -- ^ the GridSelect config to be used
+  -> X () -- ^ the gridselect displaying all filtered tasks
+taskSelectWithConfig filter gsConfig =
+  io (getTaskwarriorTaskList filter ["id", "description"]) >>= \bs -> case bs of
+    [] -> safeSpawn "firefox" []
+    _  -> runSelectedAction gsConfig . finishGS $ fmap openBuffer bs
+ where
+  finishGS = (("[Finish]", unsafeSpawn "") :)
+  openBuffer x = (x !! 1, twscratchpad (head x ++ " information"))
+
+
+-- | A wrapper around 'taskSelectWithConfig' using the default GSConfig
+taskSelect
+  :: String -- ^ a filter to be applied, please refer to [TaskWarrior Filter](https://taskwarrior.org/docs/filter.html) for further information
+  -> X () -- ^ the gridselect displaying all filtered tasks
+taskSelect filter = taskSelectWithConfig filter (buildTWGSConfig 300)
+
+
+-- | A GridSelect displaying a list of the tags of all pending taskwarrior tasks. After a tag has been selected, a second gridselect showing a filtered list of taskwarrior tasks that have the selected tag will be displayed. 
+tagSelectWithConfig
+  :: (GSConfig (X ()), GSConfig (X ())) -- ^ A tuple containing two GSConfigs. The first one is used to configure the gridselect displaying the list of tags. The second one is used to configure the gridselect displaying the resulting fitlered list of tasks. 
+  -> X () -- ^ a gridSelect displaying a list of the tags of all pending taskwarrior tasks
+tagSelectWithConfig (fstGsConfig, sndGsConfig) =
+  io (getTaskwarriorIds "status:pending" "tags") >>= \bs -> case bs of
+    [] -> safeSpawn "firefox" []
+    _  -> runSelectedAction fstGsConfig . finishGS $ fmap openBuffer
+                                                          (filteredTags bs)
+ where
+  finishGS = (("[Finish]", unsafeSpawn "") :)
+  openBuffer x = (x, taskSelectWithConfig ("+" ++ x) sndGsConfig)
+  filteredTags bs = [ x | x <- bs, x `notElem` hiddenTags ]
+  hiddenTags =
+    [ "BLOCKED"
+    , "UNBLOCKED"
+    , "UNBLOCKED"
+    , "DUE"
+    , "DUETODAY"
+    , "TODAY"
+    , "OVERDUE"
+    , "WEEK"
+    , "MONTH"
+    , "QUARTER"
+    , "YEAR"
+    , "ACTIVE"
+    , "SCHEDULED"
+    , "PARENT"
+    , "CHILD"
+    , "UNTIL"
+    , "WAITING"
+    , "ANNOTATED"
+    , "READY"
+    , "YESTERDAY"
+    , "TOMORROW"
+    , "TAGGED"
+    , "PENDING"
+    , "COMPLETED"
+    , "DELETED"
+    , "UDA"
+    , "ORPHAN"
+    , "PRIORITY"
+    , "PROJECT"
+    , "LATEST"
+    , "nocal"
+    , "nonag"
+    , "nocolor"
+    ]
+
+
+-- | A wrapper around 'tagSelectWithConfig' using the default GSConfig
+tagSelect :: X ()
+tagSelect = tagSelectWithConfig (defaultTWGSConfig, buildTWGSConfig 300)
+
+
+-- | A GridSelect displaying a list of all pending projects. After a project has been selected, a second gridselect showing a filtered list of taskwarrior tasks that belong to the selected project  will be displayed.
+projectSelectWithConfig
+  :: (GSConfig (X ()), GSConfig (X ())) -- ^ A tuple containing two GSConfigs. The first one is used to configure the gridselect displaying the list of pending projects. The second one is used to configure the gridselect displaying the resulting filtered list of tasks. 
+  -> X () -- ^ a GridSelect displaying a list of all pending projects
+projectSelectWithConfig (fstGsConfig, sndGsConfig) =
+  io (getTaskwarriorIds "status:pending" "projects") >>= \bs -> case bs of
+    [] -> safeSpawn "firefox" []
+    _  -> runSelectedAction fstGsConfig . finishGS $ fmap openBuffer bs
+ where
+  finishGS = (("[Finish]", unsafeSpawn "") :)
+  openBuffer x = (x, taskSelectWithConfig ("project:" ++ x) sndGsConfig)
+
+
+-- | A wrapper around 'projectSelectWithConfig' using the default GSConfig
+projectSelect :: X ()
+projectSelect =
+  projectSelectWithConfig (defaultTWGSConfig, buildTWGSConfig 300)
+
+
+-- | A GridSelect displaying a list of due dates. After a due date has been selected, a second gridselect showing a filtered list of taskwarrior tasks will be displayed.
+dueSelectWithConfig
+  :: (GSConfig (X ()), GSConfig (X ()))  -- ^ A tuple containing two GSConfigs. The first one is used to configure the gridselect displaying the list of due dates. The second one is used to configure the gridselect displaying the resulting filtered list of tasks.
+  -> X () -- ^ a GridSelect displaying a list of all due dates
+dueSelectWithConfig (fstGsConfig, sndGsConfig) = runSelectedAction
+  fstGsConfig
+  actions
+ where
+  actions =
+    [ ("overdue" , taskSelectWithConfig "+OVERDUE" sndGsConfig)
+    , ("today"   , taskSelectWithConfig "+TODAY" sndGsConfig)
+    , ("tomorrow", taskSelectWithConfig "+TOMORROW" sndGsConfig)
+    , ("week"    , taskSelectWithConfig "+WEEK" sndGsConfig)
+    , ("month"   , taskSelectWithConfig "+MONTH" sndGsConfig)
+    , ("year"    , taskSelectWithConfig "+YEAR" sndGsConfig)
+    ]
+
+
+-- | A wrapper around 'dueSelectWithConfig' using the default GSConfig
+dueSelect :: X ()
+dueSelect = dueSelectWithConfig (defaultTWGSConfig, buildTWGSConfig 300)
+
+
+-- | A wrapper around 'togglePriorityWithConfig' using the default GridSelect.Extras.GSConfig
+togglePriority
+  :: String -- ^ the priority that should be toggled
+  -> X () -- ^ the resulting gridselect
+togglePriority = togglePriorityWithConfig (buildTWGSExtraConfig 300)
+
+
+-- | A gridselect showing all pending tasks. The tasks are colored according to their priority. Selecting a task toggles its priority. 
+togglePriorityWithConfig
+  :: GridSelect.Extras.GSConfig (X ()) -- ^ a GridSelect.Extras.GSConfig used for the gridselect
+  -> String -- ^ the priority that should be toggled
+  -> X () -- ^ the resulting gridselect
+togglePriorityWithConfig gsConfig priority =
+  io (getTaskwarriorTaskList "+INBOX" ["id", "description", "priority"])
+    >>= \bs -> case bs of
+          [] -> safeSpawn "firefox" []
+          _ ->
+            GridSelect.Extras.runSelectedActionWithMessageAndIcon
+                gsConfig
+                ("Select " ++ priority ++ "s")
+                twicon
+              . startEmacs
+              $ fmap (openBuffer priority) bs
+ where
+  startEmacs = (("[Finish]", safeSpawn "task" []) :)
+  openBuffer priority x =
+    ( if x !! 2 /= "" then x !! 2 ++ ": " ++ x !! 1 else x !! 1
+    , toggleP priority x
+    )
+  toggleP priority x = if x !! 2 == priority
+    then unsafeSpawn ("task " ++ head x ++ " modify priority:")
+      >> togglePriority priority
+    else unsafeSpawn ("task " ++ head x ++ " modify priority:" ++ priority)
+      >> togglePriority priority
+
+
+-- | Method used to build a GridSelect.Extra.GSConfig by specifying a custom cellwidth
+buildTWGSExtraConfig
+  :: Integer -- ^ the cellwidth
+  -> GridSelect.Extras.GSConfig (X ()) -- ^ the resulting GridSelect.Extra.GSConfig
+buildTWGSExtraConfig cellwidth = GridSelect.Extras.def
+  { GridSelect.Extras.gs_cellheight   = 50
+  , GridSelect.Extras.gs_cellwidth    = cellwidth
+  , GridSelect.Extras.gs_cellpadding  = 10
+  , GridSelect.Extras.gs_font = "xft:Liberation Mono:size=9:antialias=true"
+  , GridSelect.Extras.gs_navigate     = GridSelect.Extras.defaultNavigation
+  , GridSelect.Extras.gs_originFractX = 1 / 2
+  , GridSelect.Extras.gs_originFractY = 1 / 2
+  }
+
+
+-- | Method used to build a GSConfig by specifying a custom cellwidth 
+buildTWGSConfig
+  :: Integer -- ^ the cellwidth
+  -> GSConfig (X ()) -- ^  the resulting GSConfig
+buildTWGSConfig cellwidth = (buildDefaultGSConfig myColorizer)
+  { gs_cellheight   = 50
+  , gs_cellwidth    = cellwidth
+  , gs_cellpadding  = 10
+  , gs_font         = "xft:Liberation Mono:size=9:antialias=true"
+  , gs_navigate     = defaultNavigation
+  , gs_originFractX = 1 / 2
+  , gs_originFractY = 1 / 2
+  }
+ where
+  myColorizer :: a -> Bool -> X (String, String)
+  myColorizer _ p | p         = pure ("#f44336", "#1a1a1a")
+                  | otherwise = pure ("#1a1a1a", "gray")
+
+
+-- | The default GridSelect.Extra.GSConfig used for taskwarrior GridSelects
+defaultTWGSExtraConfig :: GridSelect.Extras.GSConfig (X ())
+defaultTWGSExtraConfig = buildTWGSExtraConfig 130
+
+
+-- | The default GSConfig used for taskwarrior GridSelects
+defaultTWGSConfig :: GSConfig (X ())
+defaultTWGSConfig = buildTWGSConfig 130
+
+
diff --git a/src/TaskMonad/Prompt.hs b/src/TaskMonad/Prompt.hs
new file mode 100644
--- /dev/null
+++ b/src/TaskMonad/Prompt.hs
@@ -0,0 +1,116 @@
+{-# LANGUAGE ScopedTypeVariables, TypeSynonymInstances, FlexibleInstances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  TaskMonad.Prompt
+-- Copyright   :  Max Magorsch <max@magorsch.de>
+-- License     :  BSD-style (see LICENSE)
+--
+-- Maintainer  :  Max Magorsch <max@magorsch.de>
+-- Stability   :  unstable
+-- Portability :  unportable
+--
+-- TaskMonad.Prompt provides wrappers around [XMonad.Prompt.Input]
+-- (https://hackage.haskell.org/package/xmonad-contrib/docs/XMonad-Prompt-Input.html)
+-- for usage with taskwarrior
+--
+-----------------------------------------------------------------------------
+
+module TaskMonad.Prompt
+  ( taskwarriorPrompt
+  ,
+       -- * Screenshots
+       -- $screenshots
+    customPrompt
+  )
+where
+
+import           Data.List
+import           Data.Maybe
+import           System.Process
+import           System.IO
+import           Control.Monad                  ( filterM )
+
+import           XMonad                  hiding ( liftX )
+import           XMonad.Util.Font
+import qualified XMonad.StackSet               as W
+import           XMonad.Layout.Decoration
+import           XMonad.Prompt
+import           XMonad.Prompt.Input
+import           XMonad.Util.Image
+import           XMonad.Util.NamedWindows
+import           XMonad.Util.XUtils
+import           XMonad.Util.NamedScratchpad
+import           XMonad.Util.Run
+
+import qualified GridSelect.Extras
+
+import           TaskMonad.ScratchPad
+import           TaskMonad.Utils
+import           TaskMonad.GridSelect           ( togglePriority
+                                                , defaultTWGSExtraConfig
+                                                )
+
+
+-- $screenshots
+--
+-- TaskMonad.Prompt in action:
+--
+-- <<https://raw.githubusercontent.com/mmagorsc/taskmonad/master/docs/images/taskmonad-prompt.png>>
+
+
+-- | A wrapper around [XMonad.Prompt.Input]
+-- (https://hackage.haskell.org/package/xmonad-contrib/docs/XMonad-Prompt-Input.html)
+-- using a custom 'XPconfig'
+customPrompt
+  :: String -- ^ title that will be displayed in the prompt 
+  -> [String] -- ^ completion list 
+  -> (String -> X ()) -- ^ action that takes the input of the prompt and returns and X ()
+  -> X () -- ^ the action that shows the prompt
+customPrompt name completeList action =
+  inputPromptWithCompl myXPConfig name (mkComplFunFromList completeList)
+    ?+ action
+ where
+  myXPConfig = def { position          = CenteredAt 0.5 0.4
+                   , alwaysHighlight   = True
+                   , height            = 60
+                   , promptBorderWidth = 1
+                   , font              = "xft:Inconsolata:size=14"
+                   , borderColor       = "#555555"
+                   , bgColor           = "#111111"
+                   }
+
+
+-- | A wrapper around 'customPrompt' that can be used to execute taskwarrior
+-- as well as custom commands.
+--
+-- You can specify a list of tuples which contain
+-- custom actions as well as conditions for the custom actions, like this:
+--
+-- > taskwarriorPrompt [(\x -> x == "processInput", processInput)]
+--
+-- However, if none of the specified actions is true, a default action will be executed.
+-- The default action shows taskwarrior reports in a scratchpad and executes all the other commands silently.  
+taskwarriorPrompt
+  :: [(String -> Bool, X ())] -- ^ a list of tuples which contain a condition for an action as well as the action
+  -> X () -- ^ the resulting TaskWarrior prompt
+taskwarriorPrompt possibleActions =
+  customPrompt "task" defaulttwreports (possiblePromptAction possibleActions)
+
+
+-- | Recursively goes through a list of conditional actions. If a condition is fulfilled, the
+-- related action will be executed, otherwise the next condition in the list will be evaluated.
+-- In case no condition is fulfilled the 'defaultTWPromptAction' will finally be executed.
+possiblePromptAction [] command = defaultTWPromptAction command
+possiblePromptAction (p : ps) command =
+  if fst p command then snd p else possiblePromptAction ps command
+
+
+-- | The default action that will be execute in the 'taskwarriorPrompt', if no other action was executed.
+defaultTWPromptAction :: String -> X ()
+defaultTWPromptAction command = if isTWReport command
+  then twscratchpad command
+  else twcommand command
+ where
+  twcommand command = io (execCommandWithOutput "task" command)
+    >>= \bs -> unsafeSpawn $ "notify-send '" ++ bs ++ "'"
+
diff --git a/src/TaskMonad/ScratchPad.hs b/src/TaskMonad/ScratchPad.hs
new file mode 100644
--- /dev/null
+++ b/src/TaskMonad/ScratchPad.hs
@@ -0,0 +1,138 @@
+{-# LANGUAGE ScopedTypeVariables, TypeSynonymInstances, FlexibleInstances #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  TaskMonad.ScratchPad
+-- Copyright   :  Max Magorsch <max@magorsch.de>
+-- License     :  BSD-style (see LICENSE)
+--
+-- Maintainer  :  Max Magorsch <max@magorsch.de>
+-- Stability   :  unstable
+-- Portability :  unportable
+--
+-- A wrapper around [XMonad.Util.NamedScratchpad]
+-- (hackage.haskell.org/package/xmonad-contrib/docs/XMonad-Util-NamedScratchpad.html)
+-- that can be used to display taskwarrior commands 
+--
+-----------------------------------------------------------------------------
+
+module TaskMonad.ScratchPad
+  (
+       -- * Usage
+       -- $usage
+
+       -- * Screenshots
+       -- $screenshots
+    taskwarriorScratchpad
+  , taskwarriorScratchpads
+  , hideScratchpadAction
+  , twscratchpad
+  , runTmuxCommand
+  )
+where
+
+import           Data.List
+import           Data.Maybe
+import           System.Process
+import           System.IO
+import           Control.Monad                  ( filterM )
+
+import           XMonad                  hiding ( liftX )
+import           XMonad.Util.Font
+import qualified XMonad.StackSet               as W
+import           XMonad.Layout.Decoration
+import           XMonad.Prompt
+import           XMonad.Prompt.Input
+import           XMonad.Util.Image
+import           XMonad.Util.NamedWindows
+import           XMonad.Util.XUtils
+import           XMonad.Util.NamedScratchpad
+import           XMonad.Util.Run
+import           XMonad.Actions.GridSelect
+
+import qualified GridSelect.Extras
+
+-- $usage
+--
+-- Just add a manage hook:
+--
+-- > , manageHook = namedScratchpadManageHook taskwarriorScratchpads
+--
+
+
+
+-- $screenshots
+--
+-- TaskMonad.Scratchpad in action:
+--
+-- <<https://raw.githubusercontent.com/mmagorsc/taskmonad/master/docs/images/taskmonad-scratchpad.png>>
+
+
+-- | Open the TaskWarrior-ScratchPad
+taskwarriorScratchpad :: X ()
+taskwarriorScratchpad =
+  namedScratchpadAction taskwarriorScratchpads "taskwarrior"
+
+-- | The TaskWarrior-Scratchpad which contains a tmux session
+taskwarriorScratchpads :: [NamedScratchpad]
+taskwarriorScratchpads =
+  [NS "taskwarrior" spawnTaskwarrior findTerm manageTerm] -- and a second ]
+ where
+  spawnTaskwarrior =
+    "xterm" ++ " -name scratchpad" ++ " -e tmux new -A -s tw-scratch"
+  findTerm   = appName =? "scratchpad" -- its window will be named "scratchpad" (see above)
+  manageTerm = customFloating $ W.RationalRect 0.25 0 0.5 0.6 -- l t w h
+
+
+-- | Finds named scratchpad configuration by name
+findByName :: NamedScratchpads -> String -> Maybe NamedScratchpad
+findByName c s = listToMaybe $ filter ((s ==) . name) c
+
+
+-- | Runs application which should appear in specified scratchpad
+runApplication :: NamedScratchpad -> X ()
+runApplication = spawn . cmd
+
+
+-- | Modified version of XMonad.Util.NamedScratchpad.hideScratchpadAction
+-- which can be used to just show a scratchpad and don't hide it
+-- in case it is already shown
+hideScratchpadAction
+  :: NamedScratchpads -- ^ Named scratchpads configuration
+  -> String           -- ^ Scratchpad name
+  -> X ()
+hideScratchpadAction confs n
+  | Just conf <- findByName confs n = withWindowSet $ \s -> do
+        -- try to find it on the current workspace
+    filterCurrent <- filterM
+      (runQuery (query conf))
+      ((maybe [] W.integrate . W.stack . W.workspace . W.current) s)
+    case filterCurrent of
+--            {- The following part is commented out, as it would hide the scratchpad -}                
+--            (x:_) -> do
+--                -- create hidden workspace if it doesn't exist
+--                if null (filter ((== scratchpadWorkspaceTag) . W.tag) (W.workspaces s))
+--                    then addHiddenWorkspace scratchpadWorkspaceTag
+--                    else return ()
+--                -- push window there
+--                windows $ W.shiftWin scratchpadWorkspaceTag x
+      [] -> do
+          -- try to find it on all workspaces
+        filterAll <- filterM (runQuery (query conf)) (W.allWindows s)
+        case filterAll of
+          (x : _) -> windows $ W.shiftWin (W.currentTag s) x
+          []      -> runApplication conf
+  | otherwise = return ()
+
+
+-- | Send a taskwarrior command to the taskwarrior tmux session and open the taskwarrior scratchpad
+twscratchpad :: String -> X ()
+twscratchpad command =
+  runTmuxCommand ("clear && task " ++ command)
+    >> hideScratchpadAction taskwarriorScratchpads "taskwarrior"
+
+
+-- | Send a command to the taskwarrior tmux session
+runTmuxCommand :: MonadIO m => String -> m ()
+runTmuxCommand command =
+  unsafeSpawn $ "tmux send-keys -t tw-scratch.0 '" ++ command ++ "' ENTER"
diff --git a/src/TaskMonad/Utils.hs b/src/TaskMonad/Utils.hs
new file mode 100644
--- /dev/null
+++ b/src/TaskMonad/Utils.hs
@@ -0,0 +1,2743 @@
+{-# LANGUAGE ScopedTypeVariables, TypeSynonymInstances, FlexibleInstances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  TaskMonad.Utils
+-- Copyright   :  Max Magorsch <max@magorsch.de>
+-- License     :  BSD-style (see LICENSE)
+--
+-- Maintainer  :  Max Magorsch <max@magorsch.de>
+-- Stability   :  unstable
+-- Portability :  unportable
+--
+-- TaskMonad.Utils bundles a number of help functions that can be used to
+-- interact with the taskwarrior command line application. 
+--
+-----------------------------------------------------------------------------
+
+module TaskMonad.Utils
+  ( getTaskwarriorTaskList
+  , getTaskwarriorIds
+  , isTWReport
+  , defaulttwreports
+  , execCommand
+  , execCommandWithOutput
+  , twicon
+  )
+where
+
+import           Data.List
+import           Data.Maybe
+import           System.Process
+import           System.IO
+import           Control.Monad                  ( filterM )
+
+import           XMonad                  hiding ( liftX )
+import           XMonad.Util.Font
+import qualified XMonad.StackSet               as W
+import           XMonad.Layout.Decoration
+import           XMonad.Prompt
+import           XMonad.Prompt.Input
+import           XMonad.Util.Image
+import           XMonad.Util.NamedWindows
+import           XMonad.Util.XUtils
+import           XMonad.Util.NamedScratchpad
+import           XMonad.Util.Run
+import           XMonad.Actions.GridSelect
+
+
+
+
+-- | Returns a filtered list of all properties that belong to a given category. For example
+--
+-- > getTaskwarriorIds "status:pending" "tags"
+--
+-- returns a list of all tags of the pending tasks. Likewise
+--
+-- > getTaskwarriorIds "status:pending" "ids"
+--
+-- returns the ids of all pending tasks.
+getTaskwarriorIds
+  :: String -- ^ A filter that is applied, e.g. "+INBOX" or "status:pending". Please refer to the [taskwarrior documentation](https://taskwarrior.org/docs/filter.html) for further information.
+  -> String -- ^ The category of properties that should be returned, e.g. "ids" or "tags"
+  -> IO [String] -- ^ A filtered list of all properties that belong to the specified category
+getTaskwarriorIds filter category = do
+  result <- execCommandWithOutput "task" (filter ++ " _" ++ category)
+  return $ lines result
+
+
+-- | Get a tuple containing the id and the description of a task with a specified id
+getTaskwarriorTaskDescription
+  :: String -- ^ the id of the task 
+  -> IO (String, String) -- ^ (the id of the task, the description)
+getTaskwarriorTaskDescription id = do
+  result <- execCommandWithOutput "task" ("_get " ++ id ++ ".description")
+  return (id, result)
+
+
+-- | Get the description of a task with a specified id
+getTaskDescription
+  :: String -- ^ the id of the task
+  -> IO String -- ^ the description of the task
+getTaskDescription id =
+  execCommandWithOutput "task" ("_get " ++ id ++ ".description")
+
+
+-- | Returns a filtered list of tasks that contains the specified properties of each task
+getTaskwarriorTaskList
+  :: String -- ^ A filter that is applied, e.g. "+INBOX" or "status:pending". Please refer to the [taskwarrior documentation](https://taskwarrior.org/docs/filter.html) for further information.
+  -> [String] -- ^ A list of properties that should be retrieved for each task, e.g. ["id", "description", "tags"] 
+  -> IO [[String]] -- ^ A filtered list of tasks that contains the specified properties of each task
+getTaskwarriorTaskList filter taskproperties = do
+  ids <- getTaskwarriorIds filter "ids"
+  traverse (getTaskwarriorTaskProperties taskproperties) ids
+
+
+-- | Get a list of specified properties of a task with a specified id
+getTaskwarriorTaskProperties
+  :: Traversable t
+  => t String -- ^ a list of properties
+  -> String -- ^ the id of the task
+  -> IO (t String) -- ^ the list containing the values of the specified properties
+getTaskwarriorTaskProperties properties id =
+  traverse (getTaskwarriorTaskProperty id) properties
+
+
+-- | Get a specified property of a task with a specified id
+getTaskwarriorTaskProperty
+  :: String -- ^ the id of the task
+  -> String -- ^ the desired property
+  -> IO String -- ^ the value of the desired property of the specified task
+getTaskwarriorTaskProperty id property = do
+  result <- execCommandWithOutput "task" ("_get " ++ id ++ "." ++ property)
+  return $ filter (/= '\n') result
+
+
+-- | Checks whether a given taskwarrior command is a report or not
+isTWReport :: String -> Bool
+isTWReport command = head (words command) `elem` defaulttwreports
+
+
+-- | A list containing all taskwarrior reports. For further information, please refer to [https://taskwarrior.org/docs/report.html](https://taskwarrior.org/docs/report.html) 
+defaulttwreports :: [String]
+defaulttwreports =
+  [ "dailyreview"
+  , "weeklyreview"
+  , "inbox"
+  , "processInbox"
+  , "process"
+  , "active"
+  , "all"
+  , "blocked"
+  , "blocking"
+  , "completed"
+  , "done"
+  , "list"
+  , "long"
+  , "ls"
+  , "minimal"
+  , "newest"
+  , "next"
+  , "oldest"
+  , "overdue"
+  , "ready"
+  , "recurring"
+  , "unblocked"
+  , "waiting"
+  , "burndown.daily"
+  , "burndown.monthly"
+  , "burndown.weekly"
+  , "calendar"
+  , "colors"
+  , "columns"
+  , "commands"
+  , "diagnostics"
+  , "ghistory.annual"
+  , "ghistory.monthly"
+  , "ghistory.weekly"
+  , "ghistory.daily"
+  , "history.annual"
+  , "history.monthly"
+  , "history.weekly"
+  , "history.daily"
+  , "ids"
+  , "information"
+  , "projects"
+  , "reports"
+  , "show"
+  , "stats"
+  , "summary"
+  , "tags"
+  , "timesheet"
+  , "udas"
+  , "uuids"
+  ]
+
+
+-- | Executes a shell command.
+execCommand :: MonadIO m => String -> m ()
+execCommand = unsafeSpawn
+
+
+-- | Executes an executable with args and returns the output.
+execCommandWithOutput :: FilePath -> String -> IO String
+execCommandWithOutput executable args = do
+  (_, Just hout, _, _) <- createProcess (proc executable (words args))
+    { std_out = CreatePipe
+    }
+  hGetContents hout
+
+
+-- | The Taskwarrior icon
+twicon :: [[Bool]]
+twicon =
+  [ [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , True
+    , True
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , True
+    , False
+    , False
+    , False
+    , False
+    , True
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  , [ False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    , False
+    ]
+  ]
