s      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~     Safe/0123459:;<=?DKLQRT[\1Safe/0123459:;<=?DKLQRT[\None*/0123459:;<=?DKLQRT[\b&a "cross-platform" keyboard, that has:*all keys that exist on standard keyboards.plus,  and ?: virtual modifiers to abstract over common keyboard shortcuts.(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).fake key: Alt on Linux/Windows, Command on OSXSfake key: Control on Linux/Windows, Command on OSX Control/Command both have C/O/NY*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 ].Z3fake modifier: Alt on Linux/Windows, Command on OSX[7fake modifier: Control on Linux/Windows, Command on OSX`drepresents joitly holding down all the modifiers while individually press each key down and back up.Naming: %https://www.emacswiki.org/emacs/Chorda4a sequence of key chords make up a keyboard shortcutNaming: +https://www.emacswiki.org/emacs/KeySequenceb3Mouse wheel scrolling, vertically and horizontally.c:/scrolls up when "natural scrolling" is disabled0scrolls down when "natural scrolling" is enabled TODO checkgAOperating systems always (?) support at least these mouse events.>Most mice have these three buttons, trackpads have left/right.oconcrete monad.pconcrete transformer.q(without failability)rabstract interface.5a monad constraint for "workflow effects" (just like  MonadStateW is for "state effects"). Can be used in any monad transformer stack that handles them.| holds the effects. supports:, if the user's syntax is wrongCerror messages from the underlying system calls (TODO e.g. Win32's GetLastError())sthe non-monadic subset of |. i.e. all cases that return ()', preserving the previous continuation.*Naming: "unit workflow", like "traverse_".|Tplatform-agnostic workflows, which can be interpreted by platform-specific bindings.Naming:  WorkflowF for "Workflow Functor".3NOTE: currently, no error codes are returned (only ()f)). 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.} press the  while the Ys 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~na logical grouping for: (1) unicode support (2) efficiency and (3) debugging. sent to the current application.click the button, some number of times, holding down the modifiers derived, make method, not constructor. sent to the current application.Aspin the wheel, some number of units*, holding down the modifiers like getter like setterinterpreted as  threadDelay+ on all platforms; included for convenience pattern KeyChord ms k = (ms,k)All modifiers are keys. expansion: MCoWorkflow a ~ Cofree CoWorkflowF a ~ (a, CoWorkflow (Cofree CoWorkflowF a)) since: &data Cofree f a = a :< f (Cofree f a) e.g. @ expansion: CoWorkflowT w a ~ CofreeT CoWorkflowF w a ~ w (CofreeF CoWorkflowF a (CofreeT CoWorkflowF w a)) ~ w (a, CoWorkflowF (CofreeT CoWorkflowF w a)) @since: 5data CofreeT f w a = w (CofreeF f a (CofreeT f w a)) Naming: induces a CoMonad, see 2http://dlaing.org/cofun/posts/free_and_cofree.html|, , and runWorkflowWithT are analogous to:Either (a -> c) (b,c) , "get an a , or set a b"((a,c), (b -> c))#, "a handler for the getting of an a%, and a handler for the setting of a b"@ handle :: ((a,c), (b -> c))> (Either (a -> c) (b,c))8> c handle (aHasBeenGotten, bHasBeenSet) = either TODO @background: see 2http://dlaing.org/cofun/posts/free_and_cofree.html =   uncurried ħ  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ѧ|}~stuvwxyz{rqponmlkghijbcdefa`YZ[\]^_  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX)T  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{| }~ None!"/0123459:;<=?DKLOQRT[\6An explicit "typeclass dictionary" for interpreting a r.6i.e. a generic handler/interpreter (product type) for | effects (a sum type).e.g.  WorkflowD IO  template: rmyDictionary :: (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 9 is elided, as its implementation can use cross-platform  ().see e.g. HshellDictionary :: WorkflowD IO shellDictionary = WorkflowD{..} where  = shell $ "pbpaste" j s = shell $ "echo "++(shellEscape s)++"| pbcopy" >> return () ... runWorkflowByShell :: (MonadIO m) => pm m a -> m a runWorkflowByShell = runWorkflowByT shellDictionary -- specializeable: -- runWorkflowByShell :: o a -> IO a  None!"#/0123459:;<=?DKLQRT[\2A table for parsing strings of modifiers and keys..Parses and executes a keyboard shortcut. (via  and ).+more convenient than manually constructing Ys and s.but, (safely) partial e.g. compare: press "H-S-t H-l" to:   [ ` [[, ^] 3 , ` [[) + ] <(a keyboard shortcut to "re-open tab, then jump to url bar")s on a "syntax error"(The default syntax is inspired by Emacs: press =    readEmacsKeySequence "H-S-t H-l"BJust [([HyperModifier,ShiftModifier],TKey),([HyperModifier],LKey)] = readEmacsKeyChord "H-S-t")Just ([HyperModifier,ShiftModifier],TKey) = readEmacsModifier "H"Just HyperModifier = readEmacsKey "<tab>" Just TabKey = Build your own . e.g. import  Workflow.Core hiding (press) press = press' KeyChordSyntax{..} modifierSyntax :: ModifierSyntax modifierSyntax = defaultModifierSyntax -- defaulting keySyntax :: KeySyntax -- overriding keySyntax = Map.fromList [ ... ] surjective, non-injective. =  =  =  =    (see source)follows  +http://emacswiki.org/emacs/EmacsKeyNotationEmacs keybinding syntax, with some differences:Nnon-modifier uppercase alphabetic characters are not shifted, for consistency: e.g. use M-S-a, not M-A e.g. but M-: and "M-S-;" can both be used5non-alphanumeric characters can be in angle brackets: e.g. use C-<tab>, not C-TAB e.g. but C-\t can be used (see source)appends modifiersappends a modifier<>2 overrides (i.e. right-biased i.e. pick the last). None/0123459:;<=?DKLQRT[\  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~None/0123459:;<=?DKLOQRT[\ Gprefix with a number to pause (for that many seconds) before execution.<prefix with "stay" to disable "alt-tab"ing before execution.e.g. > help ... > stay paste > copy # (Having selected some text topmost (besides the current) window) > 1000 paste # Wait a second before pasting > quit                      None/0123459:;<=?DKLQRT[\   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~n       !"#$%&'&()*+ ,-./012345+workflow-types-0.0.0-K0EoQCaTrIdFAFcwhnivNQWorkflow.ReexportsWorkflow.ExtraWorkflow.TypesWorkflow.Execute Workflow.KeysWorkflow.ParserWorkflow.Examplepress Workflow.Core'exceptions-0.8.3-5OTPYzRazb4DJ75sPncYEhControl.Monad.Catch MonadThrow"free-4.12.4-LgcX9hrtnan8i9EaOvHXkRControl.Monad.Free.Class MonadFree-:failedKeyMetaKeyHyperKey ControlKey CapsLockKeyShiftKey OptionKey FunctionKeyGraveKeyMinusKeyEqualKey DeleteKeyForwardDeleteKeyLeftBracketKeyRightBracketKey BackslashKey SemicolonKeyQuoteKeyCommaKey PeriodKeySlashKeyTabKeySpaceKey ReturnKey LeftArrowKey RightArrowKey DownArrowKey UpArrowKeyAKeyBKeyCKeyDKeyEKeyFKeyGKeyHKeyIKeyJKeyKKeyLKeyMKeyNKeyOKeyPKeyQKeyRKeySKeyTKeyUKeyVKeyWKeyXKeyYKeyZKeyZeroKeyOneKeyTwoKeyThreeKeyFourKeyFiveKeySixKeySevenKeyEightKeyNineKey EscapeKeyF1KeyF2KeyF3KeyF4KeyF5KeyF6KeyF7KeyF8KeyF9KeyF10KeyF11KeyF12KeyF13KeyF14KeyF15KeyF16KeyF17KeyF18KeyF19KeyF20KeyModifier MetaModifier HyperModifierControlModifierOptionModifier ShiftModifierFunctionModifierKeyChord KeySequence MouseScroll ScrollTowards ScrollAway ScrollLeft ScrollRight MouseButton LeftButton MiddleButton RightButton MilliSecondsURL Application ClipboardWorkflow WorkflowTMonadWorkflow_ MonadWorkflow Workflow_ SendKeyChord_ SendText_SendMouseClick_SendMouseScroll_ SetClipboard_OpenApplication_OpenURL_Delay_ WorkflowF SendKeyChordSendTextSendMouseClickSendMouseScroll GetClipboard SetClipboardCurrentApplicationOpenApplicationOpenURLDelaySimpleKeyChord modifier2key $fNFDataKey$fNFDataModifier$fNFDataMouseScroll$fNFDataMouseButton$fNFDataWorkflow_$fShowMouseButton$fReadMouseButton$fEqMouseButton$fOrdMouseButton$fEnumMouseButton$fBoundedMouseButton$fDataMouseButton$fGenericMouseButton$fShowMouseScroll$fReadMouseScroll$fEqMouseScroll$fOrdMouseScroll$fEnumMouseScroll$fBoundedMouseScroll$fDataMouseScroll$fGenericMouseScroll$fShowModifier$fReadModifier $fEqModifier $fOrdModifier$fBoundedModifier$fEnumModifier$fDataModifier$fGenericModifier $fShowKey $fReadKey$fEqKey$fOrdKey $fBoundedKey $fEnumKey $fDataKey $fGenericKey$fShowWorkflow_$fReadWorkflow_ $fEqWorkflow_$fOrdWorkflow_$fDataWorkflow_$fGenericWorkflow_$fFunctorWorkflowF CoWorkflow CoWorkflowT CoWorkflowF _SendKeyChord _SendText_SendMouseClick_SendMouseScroll _GetClipboard _SetClipboard_CurrentApplication_OpenApplication_OpenURL_Delay sendKeyChordsendTextsendMouseClicksendMouseScroll getClipboard setClipboardcurrentApplicationopenApplicationopenURLdelaysendKeySequence sendKeyChord'fromWorkflows_ fromWorkflow_$fFunctorCoWorkflowF WorkflowD _sendKeyChord _sendText_sendMouseClick_sendMouseScroll _getClipboard _setClipboard_currentApplication_openApplication_openURLrunWorkflowByTdelayMilliseconds delaySeconds KeySyntaxModifierSyntaxKeyChordSyntaxmodifierSyntax keySyntaxreadEmacsKeySequencereadEmacsKeyChordreadEmacsModifier readEmacsKeypress'readKeySequence readKeyChord readModifierreadKeydefaultKeyChordSyntaxdefaultModifierSyntaxdefaultKeySyntaxemacsKeyChordSyntaxemacsModifierSyntaxemacsKeySyntaxaddModsaddMod char2keychord$fMonoidKeyChordSyntax$fNFDataKeyChordSyntax$fShowKeyChordSyntax$fReadKeyChordSyntax$fEqKeyChordSyntax$fOrdKeyChordSyntax$fDataKeyChordSyntax$fGenericKeyChordSyntaxActionQuitHelpStayPause Workflow'ExecuteWorkflowcmdln evalAction runActionhelp parseActiongActionmainbase Data.DataData GHC.GenericsGenericData.Semigroup Semigroup Control.Monad>=>Control.Category>>> Data.Foldable traverse_ Data.Function&ondeepseq-1.4.2.0Control.DeepSeqNFDatathrowM'hashable-1.2.4.0-Ctl752zbguF6QanxurLOm2Data.Hashable.ClassHashableghc-prim GHC.TypesIO GHC.Conc.IO threadDelay