-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Automate keyboard\/mouse\/clipboard\/application interaction. -- -- a platform-independent interface for scripting your manual computer -- workflows. -- -- documention at Workflow.Core. -- -- see the source of Workflow.Example for an example. -- -- transitive dependencies: -- @package workflow-types @version 0.0.1 module Workflow.Reexports -- | A class for monads in which exceptions may be thrown. -- -- Instances should obey the following law: -- --
--   throwM e >> x = throwM e
--   
-- -- In other words, throwing an exception short-circuits the rest of the -- monadic computation. class Monad m => MonadThrow (m :: * -> *) -- | Monads provide substitution (fmap) and renormalization -- (join): -- --
--   m >>= f = join (fmap f m)
--   
-- -- A free Monad is one that does no work during the normalization -- step beyond simply grafting the two monadic values together. -- -- [] is not a free Monad (in this sense) because -- join [[a]] smashes the lists flat. -- -- On the other hand, consider: -- --
--   data Tree a = Bin (Tree a) (Tree a) | Tip a
--   
-- --
--   instance Monad Tree where
--     return = Tip
--     Tip a >>= f = f a
--     Bin l r >>= f = Bin (l >>= f) (r >>= f)
--   
-- -- This Monad is the free Monad of Pair: -- --
--   data Pair a = Pair a a
--   
-- -- And we could make an instance of MonadFree for it directly: -- --
--   instance MonadFree Pair Tree where
--      wrap (Pair l r) = Bin l r
--   
-- -- Or we could choose to program with Free Pair instead -- of Tree and thereby avoid having to define our own -- Monad instance. -- -- Moreover, Control.Monad.Free.Church provides a MonadFree -- instance that can improve the asymptotic complexity of code -- that constructs free monads by effectively reassociating the use of -- (>>=). You may also want to take a look at the -- kan-extensions package -- (http://hackage.haskell.org/package/kan-extensions). -- -- See Free for a more formal definition of the free Monad -- for a Functor. class Monad m => MonadFree (f :: * -> *) (m :: * -> *) | m -> f module Workflow.Extra failed :: (MonadThrow m) => String -> m a module Workflow.Types -- | platform-agnostic workflows, which can be interpreted by -- platform-specific bindings. -- -- Naming: WorkflowF for "Workflow Functor". -- -- NOTE: currently, no error codes are returned (only ())). this -- (1) simplifies bindings and (2) saves the user from explicitly -- ignoring action results (e.g. _ <- getClipboard). later, -- they can be supported, alongside wrappers that return () and -- throw SomeException and provide the same simple API. since -- the intented usage of workflows are as user-facing (often -- user-written) scripts, and the monad that satisifes MonadWorkflow will -- often satisify MonadIO too, convenient partial functions that throw a -- helpful error message to stdout (the error codes should be converted -- to their error messages) should suffice. and either way, is strictly -- better for the user than ignoring, as the exceptions can always be -- caught, or not displayed. data WorkflowF k -- | press the Key while the Modifiers are held down. sent to -- the current application. TODO | SendKeyChordTo Application [Modifier] -- Key k -- ^ TODO | SendKeyChordTo Window [Modifier] Key k -- ^ versus -- unary: ([Modifier], Key) rn SendChord SendKeyChord :: [Modifier] -> Key -> k -> WorkflowF k -- | a logical grouping for: (1) unicode support (2) efficiency and (3) -- debugging. sent to the current application. SendText :: String -> k -> WorkflowF k -- | click the button, some number of times, holding down the modifiers -- derived, make method, not constructor. sent to the current -- application. SendMouseClick :: [Modifier] -> Natural -> MouseButton -> k -> WorkflowF k -- | spin the wheel, some number of units*, holding down the modifiers SendMouseScroll :: [Modifier] -> MouseScroll -> Natural -> k -> WorkflowF k GetClipboard :: (Clipboard -> k) -> WorkflowF k SetClipboard :: Clipboard -> k -> WorkflowF k -- | like a getter. CurrentApplication :: (Application -> k) -> WorkflowF k -- | idempotent. like a setter. OpenApplication :: Application -> k -> WorkflowF k OpenURL :: URL -> k -> WorkflowF k -- | interpreted as threadDelay on all platforms; included for -- convenience Delay :: MilliSeconds -> k -> WorkflowF k newtype Application' Application :: ApplicationName' -> Application' [getApplication] :: Application' -> ApplicationName' type ApplicationName' = Text type ApplicationExecutable' = Text type ApplicationName = String type ApplicationExecutable = FilePath -- | the non-monadic subset of WorkflowF. i.e. all cases that return -- (), preserving the previous continuation. -- -- Naming: "unit workflow", like "traverse_". data Workflow_ SendKeyChord_ :: [Modifier] -> Key -> Workflow_ SendText_ :: String -> Workflow_ SendMouseClick_ :: [Modifier] -> Natural -> MouseButton -> Workflow_ SendMouseScroll_ :: [Modifier] -> MouseScroll -> Natural -> Workflow_ SetClipboard_ :: Clipboard -> Workflow_ OpenApplication_ :: Application -> Workflow_ OpenURL_ :: URL -> Workflow_ Delay_ :: MilliSeconds -> Workflow_ -- | abstract interface. -- -- a monad constraint for "workflow effects" (just like -- MonadState is for "state effects"). Can be used in any monad -- transformer stack that handles them. -- -- WorkflowF holds the effects. -- -- MonadThrow supports: -- -- type MonadWorkflow m = (MonadFree WorkflowF m, MonadThrow m) -- | (without failability) type MonadWorkflow_ = MonadFree WorkflowF -- | concrete transformer. type WorkflowT = FreeT WorkflowF -- | concrete monad. type Workflow = Free WorkflowF type Clipboard = String type Application = String type URL = String type MilliSeconds = Int -- | Operating systems always (?) support at least these mouse events. -- -- Most mice have these three buttons, trackpads have left/right. data MouseButton LeftButton :: MouseButton MiddleButton :: MouseButton RightButton :: MouseButton -- | Mouse wheel scrolling, vertically and horizontally. -- -- ScrollTowards: -- -- -- -- TODO check data MouseScroll ScrollTowards :: MouseScroll ScrollAway :: MouseScroll ScrollLeft :: MouseScroll ScrollRight :: MouseScroll -- | a sequence of key chords make up a keyboard shortcut -- -- Naming: https://www.emacswiki.org/emacs/KeySequence type KeySequence = [KeyChord] -- | represents joitly holding down all the modifiers while individually -- press each key down and back up. -- -- Naming: https://www.emacswiki.org/emacs/Chord type KeyChord = ([Modifier], Key) -- |
--   pattern KeyChord ms k = (ms,k)
--   
-- | modifier keys are keys that can be "held". -- -- NOTE the escape key tends to be "pressed", not "held", it seems. -- (possibly explains its behavior in your terminal emulator?) -- -- alt is OptionModifier. data Modifier -- | fake modifier: Alt on Linux/Windows, Command on OSX MetaModifier :: Modifier -- | fake modifier: Control on Linux/Windows, Command on OSX HyperModifier :: Modifier ControlModifier :: Modifier OptionModifier :: Modifier ShiftModifier :: Modifier FunctionModifier :: Modifier -- | (really, a Set) type Modifiers = [Modifier] -- | a "cross-platform" keyboard, that has: -- -- -- -- (let me know if you want a type to support cross-platform -- international keyboards, i haven't looked into it. you can still use -- the platform-specific virtual-key-codes in the dependent packages: -- workflow-linux, workflow-osx, and -- workflow-windows) data Key -- | fake key: Alt on Linux/Windows, Command on OSX MetaKey :: Key -- | fake key: Control on Linux/Windows, Command on OSX Control/Command -- both have C/O/N HyperKey :: Key ControlKey :: Key CapsLockKey :: Key ShiftKey :: Key OptionKey :: Key FunctionKey :: Key GraveKey :: Key MinusKey :: Key EqualKey :: Key DeleteKey :: Key ForwardDeleteKey :: Key LeftBracketKey :: Key RightBracketKey :: Key BackslashKey :: Key SemicolonKey :: Key QuoteKey :: Key CommaKey :: Key PeriodKey :: Key SlashKey :: Key TabKey :: Key SpaceKey :: Key ReturnKey :: Key LeftArrowKey :: Key RightArrowKey :: Key DownArrowKey :: Key UpArrowKey :: Key AKey :: Key BKey :: Key CKey :: Key DKey :: Key EKey :: Key FKey :: Key GKey :: Key HKey :: Key IKey :: Key JKey :: Key KKey :: Key LKey :: Key MKey :: Key NKey :: Key OKey :: Key PKey :: Key QKey :: Key RKey :: Key SKey :: Key TKey :: Key UKey :: Key VKey :: Key WKey :: Key XKey :: Key YKey :: Key ZKey :: Key ZeroKey :: Key OneKey :: Key TwoKey :: Key ThreeKey :: Key FourKey :: Key FiveKey :: Key SixKey :: Key SevenKey :: Key EightKey :: Key NineKey :: Key EscapeKey :: Key F1Key :: Key F2Key :: Key F3Key :: Key F4Key :: Key F5Key :: Key F6Key :: Key F7Key :: Key F8Key :: Key F9Key :: Key F10Key :: Key F11Key :: Key F12Key :: Key F13Key :: Key F14Key :: Key F15Key :: Key F16Key :: Key F17Key :: Key F18Key :: Key F19Key :: Key F20Key :: Key -- | All modifiers are keys. modifier2key :: Modifier -> Key isModifierKey :: Key -> Maybe Modifier isAlphaNumKey :: Key -> Bool isAlphabeticKey :: Key -> Bool isNumericKey :: Key -> Bool displayKey :: Key -> String instance GHC.Base.Functor Workflow.Types.WorkflowF instance GHC.Generics.Generic Workflow.Types.Workflow_ instance Data.Data.Data Workflow.Types.Workflow_ instance GHC.Classes.Ord Workflow.Types.Workflow_ instance GHC.Classes.Eq Workflow.Types.Workflow_ instance GHC.Read.Read Workflow.Types.Workflow_ instance GHC.Show.Show Workflow.Types.Workflow_ instance GHC.Generics.Generic Workflow.Types.Key instance Data.Data.Data Workflow.Types.Key instance GHC.Enum.Enum Workflow.Types.Key instance GHC.Enum.Bounded Workflow.Types.Key instance GHC.Classes.Ord Workflow.Types.Key instance GHC.Classes.Eq Workflow.Types.Key instance GHC.Read.Read Workflow.Types.Key instance GHC.Show.Show Workflow.Types.Key instance GHC.Generics.Generic Workflow.Types.Modifier instance Data.Data.Data Workflow.Types.Modifier instance GHC.Enum.Enum Workflow.Types.Modifier instance GHC.Enum.Bounded Workflow.Types.Modifier instance GHC.Classes.Ord Workflow.Types.Modifier instance GHC.Classes.Eq Workflow.Types.Modifier instance GHC.Read.Read Workflow.Types.Modifier instance GHC.Show.Show Workflow.Types.Modifier instance GHC.Generics.Generic Workflow.Types.MouseScroll instance Data.Data.Data Workflow.Types.MouseScroll instance GHC.Enum.Bounded Workflow.Types.MouseScroll instance GHC.Enum.Enum Workflow.Types.MouseScroll instance GHC.Classes.Ord Workflow.Types.MouseScroll instance GHC.Classes.Eq Workflow.Types.MouseScroll instance GHC.Read.Read Workflow.Types.MouseScroll instance GHC.Show.Show Workflow.Types.MouseScroll instance GHC.Generics.Generic Workflow.Types.MouseButton instance Data.Data.Data Workflow.Types.MouseButton instance GHC.Enum.Bounded Workflow.Types.MouseButton instance GHC.Enum.Enum Workflow.Types.MouseButton instance GHC.Classes.Ord Workflow.Types.MouseButton instance GHC.Classes.Eq Workflow.Types.MouseButton instance GHC.Read.Read Workflow.Types.MouseButton instance GHC.Show.Show Workflow.Types.MouseButton instance GHC.Base.Monoid Workflow.Types.Application' instance Data.Semigroup.Semigroup Workflow.Types.Application' instance Control.DeepSeq.NFData Workflow.Types.Workflow_ instance Control.DeepSeq.NFData Workflow.Types.MouseButton instance Control.DeepSeq.NFData Workflow.Types.MouseScroll instance Control.DeepSeq.NFData Workflow.Types.Modifier instance Control.DeepSeq.NFData Workflow.Types.Key module Workflow.Lens delay :: forall m_aDQj. MonadFree WorkflowF m_aDQj => MilliSeconds -> m_aDQj () openURL :: forall m_aDQg. MonadFree WorkflowF m_aDQg => URL -> m_aDQg () openApplication :: forall m_aDQd. MonadFree WorkflowF m_aDQd => Application -> m_aDQd () currentApplication :: forall m_aDQa. MonadFree WorkflowF m_aDQa => m_aDQa Application setClipboard :: forall m_aDQ7. MonadFree WorkflowF m_aDQ7 => Clipboard -> m_aDQ7 () getClipboard :: forall m_aDQ4. MonadFree WorkflowF m_aDQ4 => m_aDQ4 Clipboard sendMouseScroll :: forall m_aDPZ. MonadFree WorkflowF m_aDPZ => [Modifier] -> MouseScroll -> Natural -> m_aDPZ () sendMouseClick :: forall m_aDPU. MonadFree WorkflowF m_aDPU => [Modifier] -> Natural -> MouseButton -> m_aDPU () sendText :: forall m_aDPR. MonadFree WorkflowF m_aDPR => String -> m_aDPR () sendKeyChord :: forall m_aDPN. MonadFree WorkflowF m_aDPN => [Modifier] -> Key -> m_aDPN () -- |
--   = traverse_ sendKeyChord'
--   
sendKeySequence :: (MonadWorkflow m) => KeySequence -> m () -- | uncurried sendKeyChord sendKeyChord' :: (MonadWorkflow m) => KeyChord -> m () fromWorkflows_ :: (MonadWorkflow m) => [Workflow_] -> m () fromWorkflow_ :: Workflow_ -> WorkflowF () module Workflow.Keys -- | Parses and executes a keyboard shortcut. (via readKeySequence -- and sendKeyChord). -- -- -- -- e.g. compare: -- --
--   press "H-S-t H-l"
--   
-- -- to: -- --
--   traverse_ sendKeyChord'
--    [ KeyChord [HyperModifier, ShiftModifier] TKey
--    , KeyChord [HyperModifier) LKey
--    ]
--   
-- -- (a keyboard shortcut to "re-open tab, then jump to url bar") -- -- throwMs on a "syntax error" -- -- The default syntax is inspired by Emacs: -- --
--   press = press' defaultKeyChordSyntax
--   
press :: (MonadWorkflow m, MonadThrow m) => String -> m () -- |
--   >>> readEmacsKeySequence "H-S-t H-l"
--   Just [([HyperModifier,ShiftModifier],TKey),([HyperModifier],LKey)]
--   
-- --
--   =readEmacsKeySequence emacsKeyChordSyntax
--   
readEmacsKeySequence :: String -> Maybe KeySequence -- |
--   >>> readEmacsKeyChord "H-S-t"
--   Just ([HyperModifier,ShiftModifier],TKey)
--   
-- --
--   =readEmacsKeyChord emacsKeyChordSyntax
--   
readEmacsKeyChord :: String -> Maybe KeySequence -- |
--   >>> readEmacsModifier "H"
--   Just HyperModifier
--   
-- --
--   =readModifier emacsModifierSyntax
--   
readEmacsModifier :: String -> Maybe Modifier -- |
--   >>> readEmacsKey "<tab>"
--   Just TabKey
--   
-- --
--   =readKey emacsKeySyntax
--   
readEmacsKey :: String -> Maybe KeyChord -- | Build your own press. e.g. -- --
--   import Workflow.Core hiding (press)
--   
--   press = press' KeyChordSyntax{..}
--   
--   modifierSyntax :: ModifierSyntax
--   modifierSyntax = defaultModifierSyntax -- defaulting
--   
--   keySyntax :: KeySyntax     -- overriding
--   keySyntax = Map.fromList
--    [ ...
--    ]
--   
press' :: (MonadWorkflow m, MonadThrow m) => KeyChordSyntax -> String -> m () readKeySequence :: KeyChordSyntax -> String -> Maybe KeySequence readKeyChord :: KeyChordSyntax -> [String] -> Maybe KeyChord -- | surjective, non-injective. readModifier :: ModifierSyntax -> String -> Maybe Modifier readKey :: KeySyntax -> String -> Maybe KeyChord -- | A table for parsing strings of modifiers and keys. data KeyChordSyntax KeyChordSyntax :: ModifierSyntax -> KeySyntax -> KeyChordSyntax [modifierSyntax] :: KeyChordSyntax -> ModifierSyntax [keySyntax] :: KeyChordSyntax -> KeySyntax -- | <> overrides (i.e. right-biased i.e. pick the last). type ModifierSyntax = Map String Modifier type KeySyntax = Map String KeyChord -- |
--   = emacsKeyChordSyntax
--   
defaultKeyChordSyntax :: KeyChordSyntax -- |
--   = emacsModifierSyntax
--   
defaultModifierSyntax :: ModifierSyntax -- |
--   = emacsKeySyntax
--   
defaultKeySyntax :: KeySyntax -- |
--   = KeyChordSyntax defaultModifierSyntax defaultKeySyntax
--   
emacsKeyChordSyntax :: KeyChordSyntax -- | (see source) emacsModifierSyntax :: ModifierSyntax -- | follows Emacs keybinding syntax, with some differences: -- -- -- -- (see source) emacsKeySyntax :: KeySyntax -- | appends modifiers addMods :: [Modifier] -> KeyChord -> KeyChord -- | appends a modifier addMod :: Modifier -> KeyChord -> KeyChord char2keychord :: (MonadThrow m) => Char -> m KeyChord instance GHC.Generics.Generic Workflow.Keys.KeyChordSyntax instance Data.Data.Data Workflow.Keys.KeyChordSyntax instance GHC.Classes.Ord Workflow.Keys.KeyChordSyntax instance GHC.Classes.Eq Workflow.Keys.KeyChordSyntax instance GHC.Read.Read Workflow.Keys.KeyChordSyntax instance GHC.Show.Show Workflow.Keys.KeyChordSyntax instance Control.DeepSeq.NFData Workflow.Keys.KeyChordSyntax instance GHC.Base.Monoid Workflow.Keys.KeyChordSyntax module Workflow.Execute -- | a function that can exectue any workflow, via IO. newtype ExecuteWorkflow ExecuteWorkflow :: (forall n x. (MonadIO n) => WorkflowT n x -> n x) -> ExecuteWorkflow [getExecuteWorkflow] :: ExecuteWorkflow -> (forall n x. (MonadIO n) => WorkflowT n x -> n x) -- | An explicit "typeclass dictionary" for interpreting a -- MonadWorkflow. -- -- i.e. a generic handler/interpreter (product type) for WorkflowF -- effects (a sum type). -- -- e.g. -- --
--   WorkflowD IO
--   
-- -- template: -- --
--   myDictionary :: (MonadIO m) => WorkflowD m
--   myDictionary = WorkflowD{..}
--    where
--     _sendKeyChord =
--     _sendText     =
--   
--     _sendMouseClick  =
--     _sendMouseScroll =
--   
--     _getClipboard =
--     _setClipboard =
--   
--     _currentApplication =
--     _openApplication    =
--     _openURL            =
--   
--   runWorkflowByMy :: (MonadIO m) => WorkflowT m a -> m a
--   runWorkflowByMy = runWorkflowByT myDictionary
--   
-- -- Delay is elided, as its implementation can use cross-platform -- IO (threadDelay). -- -- see runWorkflowByT data WorkflowD m WorkflowD :: ([Modifier] -> Key -> m ()) -> (String -> m ()) -> ([Modifier] -> Natural -> MouseButton -> m ()) -> ([Modifier] -> MouseScroll -> Natural -> m ()) -> m Clipboard -> (Clipboard -> m ()) -> m Application -> (Application -> m ()) -> (URL -> m ()) -> WorkflowD m [_sendKeyChord] :: WorkflowD m -> [Modifier] -> Key -> m () [_sendText] :: WorkflowD m -> String -> m () [_sendMouseClick] :: WorkflowD m -> [Modifier] -> Natural -> MouseButton -> m () [_sendMouseScroll] :: WorkflowD m -> [Modifier] -> MouseScroll -> Natural -> m () [_getClipboard] :: WorkflowD m -> m Clipboard [_setClipboard] :: WorkflowD m -> (Clipboard -> m ()) [_currentApplication] :: WorkflowD m -> m Application [_openApplication] :: WorkflowD m -> Application -> m () [_openURL] :: WorkflowD m -> URL -> m () -- | e.g. -- --
--   shellDictionary :: WorkflowD IO
--   shellDictionary = WorkflowD{..}
--    where
--    _getClipboard = shell $ "pbpaste"
--    _setClipboard s = shell $ "echo "++(shellEscape s)++"| pbcopy" >> return ()
--    ...
--   
--   runWorkflowByShell :: (MonadIO m) => WorkflowT m a -> m a
--   runWorkflowByShell = runWorkflowByT shellDictionary
--   
--   -- specializeable:
--   -- runWorkflowByShell :: Workflow a -> IO a
--   
runWorkflowByT :: forall m a. (MonadIO m) => WorkflowD m -> WorkflowT m a -> m a delayMilliseconds :: (MonadIO m) => Int -> m () delaySeconds :: (MonadIO m) => Int -> m () -- | Automate keyboard/mouse/clipboard/application interaction. -- -- the core types that define platform-diagnostic workflows, as well as -- helpers for parsing keychords and implementing backends. -- -- (see WorkflowF, MonadWorkflow, Key, press, -- WorkflowD) module Workflow.Core module Workflow.Example main :: IO ()