-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Prompt.Input
-- Copyright : (c) 2007 Brent Yorgey
-- License : BSD-style (see LICENSE)
--
-- Maintainer : <byorgey@gmail.com>
-- Stability : stable
-- Portability : unportable
--
-- A generic framework for prompting the user for input and passing it
-- along to some other action.
--
-----------------------------------------------------------------------------
module XMonad.Prompt.Input (
-- * Usage
-- $usage
inputPrompt,
inputPromptWithCompl,
(?+)
) where
import XMonad.Core
import XMonad.Prompt
-- $usage
--
-- To use this module, import it along with "XMonad.Prompt":
--
-- > import XMonad.Prompt
-- > import XMonad.Prompt.Input
--
-- This module provides no useful functionality in isolation, but
-- is intended for use in building other actions which require user
-- input.
--
-- For example, suppose Mr. Big wants a way to easily fire his
-- employees. We'll assume that he already has a function
--
-- > fireEmployee :: String -> X ()
--
-- which takes as input the name of an employee, and fires them. He
-- just wants a convenient way to provide the input for this function
-- from within xmonad. Here is where the "XMonad.Prompt.Input" module
-- comes into play. He can use the 'inputPrompt' function to create a
-- prompt, and the '?+' operator to compose the prompt with the
-- @fireEmployee@ action, like so:
--
-- > firingPrompt :: X ()
-- > firingPrompt = inputPrompt defaultXPConfig \"Fire\" ?+ fireEmployee
--
-- If @employees@ contains a list of all his employees, he could also
-- create an autocompleting version, like this:
--
-- > firingPrompt' = inputPromptWithCompl defaultXPConfig \"Fire\"
-- > (mkComplFunFromList employees) ?+ fireEmployee
--
-- Now all he has to do is add a keybinding to @firingPrompt@ (or
-- @firingPrompt'@), such as
--
-- > , ((modMask x .|. controlMask, xK_f), firingPrompt)
--
-- Now when Mr. Big hits mod-ctrl-f, a prompt will pop up saying
-- \"Fire: \", waiting for him to type the name of someone to fire.
-- If he thinks better of it after hitting mod-ctrl-f and cancels the
-- prompt (e.g. by hitting Esc), the @fireEmployee@ action will not be
-- invoked.
--
-- (For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".)
--
-- "XMonad.Prompt.Input" is also intended to ease the process of
-- developing other modules which require user input. For an example
-- of a module developed using this functionality, see
-- "XMonad.Prompt.Email", which prompts the user for a recipient,
-- subject, and one-line body, and sends a quick email.
data InputPrompt = InputPrompt String
instance XPrompt InputPrompt where
showXPrompt (InputPrompt s) = s ++ ": "
-- | Given a prompt configuration and some prompt text, create an X
-- action which pops up a prompt waiting for user input, and returns
-- whatever they type. Note that the type of the action is @X
-- (Maybe String)@, which reflects the fact that the user might
-- cancel the prompt (resulting in @Nothing@), or enter an input
-- string @s@ (resulting in @Just s@).
inputPrompt :: XPConfig -> String -> X (Maybe String)
inputPrompt c p = inputPromptWithCompl c p (const (return []))
-- | The same as 'inputPrompt', but with a completion function. The
-- type @ComplFunction@ is @String -> IO [String]@, as defined in
-- "XMonad.Prompt". The 'mkComplFunFromList' utility function, also
-- defined in "XMonad.Prompt", is useful for creating such a
-- function from a known list of possibilities.
inputPromptWithCompl :: XPConfig -> String -> ComplFunction -> X (Maybe String)
inputPromptWithCompl c p compl = mkXPromptWithReturn (InputPrompt p) c compl return
infixr 1 ?+
-- | A combinator for hooking up an input prompt action to a function
-- which can take the result of the input prompt and produce another
-- action. If the user cancels the input prompt, the
-- second function will not be run.
--
-- The astute student of types will note that this is actually a
-- very general combinator and has nothing in particular to do
-- with input prompts. If you find a more general use for it and
-- want to move it to a different module, be my guest.
(?+) :: (Monad m) => m (Maybe a) -> (a -> m ()) -> m ()
x ?+ k = x >>= maybe (return ()) k