module DMenu.Options where
import Control.Lens
import DMenu.Color
data Options = Options
{
_binaryPath :: FilePath
, _displayAtBottom :: Bool
, _grabKeyboardBeforeStdin :: Bool
, _caseInsensitive :: Bool
, _spawnOnMonitor :: Int
, _numLines :: Int
, _prompt :: String
, _font :: String
, _normalBGColor :: Color
, _normalFGColor :: Color
, _selectedBGColor :: Color
, _selectedFGColor :: Color
, _printVersionAndExit :: Bool
, _dmenu2 :: Options2
, _noDMenu2 :: Bool
}
data Options2 = Options2
{
_displayNoItemsIfEmpty :: Bool
, _filterMode :: Bool
, _fuzzyMatching :: Bool
, _tokenMatching :: Bool
, _maskInputWithStar :: Bool
, _ignoreStdin :: Bool
, _spawnOnScreen :: Int
, _windowName :: String
, _windowClass :: String
, _windowOpacity :: Double
, _windowDimOpacity :: Double
, _windowDimColor :: Color
, _heightInPixels :: Int
, _underlineHeightInPixels :: Int
, _windowOffsetX :: Int
, _windowOffsetY :: Int
, _width :: Int
, _underlineColor :: Color
, _historyFile :: FilePath
}
makeLenses ''Options
makeLenses ''Options2
defOptions :: Options
defOptions = Options
{ _binaryPath = "dmenu"
, _displayAtBottom = False
, _grabKeyboardBeforeStdin = False
, _caseInsensitive = False
, _numLines = (1)
, _prompt = ""
, _font = ""
, _spawnOnMonitor = (1)
, _normalBGColor = HexColor (1)
, _normalFGColor = HexColor (1)
, _selectedBGColor = HexColor (1)
, _selectedFGColor = HexColor (1)
, _printVersionAndExit = False
, _dmenu2 = defOptions2
, _noDMenu2 = False
}
defOptions2 :: Options2
defOptions2 = Options2
{ _filterMode = False
, _fuzzyMatching = False
, _displayNoItemsIfEmpty = False
, _tokenMatching = False
, _maskInputWithStar = False
, _ignoreStdin = False
, _spawnOnScreen = (1)
, _windowName = ""
, _windowClass = ""
, _windowOpacity = (1)
, _windowDimOpacity = (1)
, _windowDimColor = HexColor (1)
, _heightInPixels = (1)
, _underlineHeightInPixels = (1)
, _windowOffsetX = (1)
, _windowOffsetY = (1)
, _width = (1)
, _underlineColor = HexColor (1)
, _historyFile = ""
}
optionsToArgs :: Options → [String]
optionsToArgs (Options{..}) = concat $ concat $
[ [ [ "-b" ] | _displayAtBottom ]
, [ [ "-f" ] | _grabKeyboardBeforeStdin ]
, [ [ "-i" ] | _caseInsensitive ]
, [ [ "-m", show _spawnOnMonitor ] | _spawnOnMonitor /= (1) ]
, [ [ "-l", show _numLines ] | _numLines /= (1) ]
, [ [ "-p", _prompt ] | _prompt /= "" ]
, [ [ "-fn", _font ] | _font /= "" ]
, [ [ "-nb", showColorAsHex _normalBGColor ] | _normalBGColor /= HexColor (1) ]
, [ [ "-nf", showColorAsHex _normalFGColor ] | _normalFGColor /= HexColor (1) ]
, [ [ "-sb", showColorAsHex _selectedBGColor ] | _selectedBGColor /= HexColor (1) ]
, [ [ "-sf", showColorAsHex _selectedFGColor ] | _selectedFGColor /= HexColor (1) ]
, [ [ "-v" ] | _printVersionAndExit ]
] ++ if _noDMenu2 then [] else options2ToArgs _dmenu2
options2ToArgs :: Options2 → [[[String]]]
options2ToArgs (Options2{..}) =
[ [ [ "-q" ] | _displayNoItemsIfEmpty ]
, [ [ "-r" ] | _filterMode ]
, [ [ "-z" ] | _fuzzyMatching ]
, [ [ "-t" ] | _tokenMatching ]
, [ [ "-mask" ] | _maskInputWithStar ]
, [ [ "-noinput" ] | _ignoreStdin ]
, [ [ "-s", show _spawnOnScreen ] | _spawnOnScreen /= (1) ]
, [ [ "-name", show _windowName ] | _windowName /= "" ]
, [ [ "-class", show _windowClass ] | _windowClass /= "" ]
, [ [ "-o", show _windowOpacity ] | _windowOpacity /= (1) ]
, [ [ "-dim" ] | _windowDimOpacity /= (1) ]
, [ [ "-dc", showColorAsHex _windowDimColor ] | _windowDimColor /= HexColor (1) ]
, [ [ "-h", show _heightInPixels ] | _heightInPixels /= (1) ]
, [ [ "-uh", show _underlineHeightInPixels ] | _underlineHeightInPixels /= (1) ]
, [ [ "-x", show _windowOffsetX ] | _windowOffsetX /= (1) ]
, [ [ "-y", show _windowOffsetY ] | _windowOffsetY /= (1) ]
, [ [ "-w", show _width ] | _width /= (1) ]
, [ [ "-uc", showColorAsHex _underlineColor ] | _underlineColor /= HexColor (1) ]
, [ [ "-hist", show _historyFile ] | _historyFile /= "" ]
]
parseOptions :: String → Options
parseOptions = foldl f defOptions . map splitFirstWord . lines where
f :: Options → (String, String) → Options
f opts (cmd, args) = opts & case cmd of
"binaryPath" → binaryPath .~ args
"displayAtBottom" → displayAtBottom .~ read args
"displayNoItemsIfEmpty" → dmenu2 . displayNoItemsIfEmpty .~ read args
"grabKeyboardBeforeStdin" → grabKeyboardBeforeStdin .~ read args
"filterMode" → dmenu2 . filterMode .~ read args
"caseInsensitive" → caseInsensitive .~ read args
"fuzzyMatching" → dmenu2 . fuzzyMatching .~ read args
"tokenMatching" → dmenu2 . tokenMatching .~ read args
"maskInputWithStar" → dmenu2 . maskInputWithStar .~ read args
"ignoreStdin" → dmenu2 . ignoreStdin .~ read args
"spawnOnScreen" → dmenu2 . spawnOnScreen .~ read args
"spawnOnMonitor" → spawnOnMonitor .~ read args
"windowName" → dmenu2 . windowName .~ args
"windowClass" → dmenu2 . windowClass .~ args
"windowOpacity" → dmenu2 . windowOpacity .~ read args
"windowDimOpacity" → dmenu2 . windowDimOpacity .~ read args
"windowDimColor" → dmenu2 . windowDimColor .~ read args
"numLines" → numLines .~ read args
"heightInPixels" → dmenu2 . heightInPixels .~ read args
"underlineHeightInPixels" → dmenu2 . underlineHeightInPixels .~ read args
"prompt" → prompt .~ args
"font" → font .~ args
"windowOffsetX" → dmenu2 . windowOffsetX .~ read args
"windowOffsetY" → dmenu2 . windowOffsetY .~ read args
"width" → dmenu2 . width .~ read args
"normalBGColor" → normalBGColor .~ read args
"normalFGColor" → normalFGColor .~ read args
"selectedBGColor" → selectedBGColor .~ read args
"selectedFGColor" → selectedFGColor .~ read args
"underlineColor" → dmenu2 . underlineColor .~ read args
"historyFile" → dmenu2 . historyFile .~ args
"printVersionAndExit" → printVersionAndExit .~ read args
"noDMenu2" → noDMenu2 .~ read args
"" → id
_ → error $ "Invalid command found when parsing dmenu config file: " ++ cmd
splitFirstWord :: String → (String, String)
splitFirstWord = go "" where
go s [] = (s, [])
go s (c:cs) | c `elem` [' ','\t'] = (s, dropWhile (`elem` [' ','\t']) cs)
| otherwise = go (s++[c]) cs