'9      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Safe/0123459:;<=?DKLQRT[\None/0123459:;<=?DKLQRT[\      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~None*/0123459:;<=?DIKLQRT[\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/NX (really, a Set)Y*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 SendChordna 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 modifierslike a getter.idempotent. like a setter.interpreted as  threadDelay+ on all platforms; included for convenience pattern KeyChord ms k = (ms,k)All modifiers are keys.  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|stuvwxyz{rqponmlkghijbcdefa`YZ[\]^_X  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW#T  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ None*/0123459:;<=?DKLQRT[\b =   uncurried 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:   [ ` [[, ^] 2 , ` [[) * ] <(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 modifier2 overrides (i.e. right-biased i.e. pick the last).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 1a function that can exectue any workflow, via IO.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[\  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~None/0123459:;<=?DKLQRT[\   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~{n                 !" # $% $& $' $( $) $* $+ $, $- $. $/010203 45 46 47 48 49 4: 4; 4< 4= 4> 4? 4@ 4A 4B 4C 4D 4E 4F 4G H I J K L M N O P Q R S T U V W X YZ [ \ ] ^_ ^` ^a ^b ^c ^d ^e ^f0g0h0i0j0k0l mn mo mp q r 4s 4t 4u 4v 4w 4x 4y 4z 4{ 4| 4} 4~ 4 4 4                                                       ! ! ! ! ! ! ! ! ! ! ! ! ! !                                                                   ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O mP mQ RS TU TV WX WY Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~        ^                             000        !"#$%$%&'()*+,-./01"#23 456+workflow-types-0.0.1-JGyare4oGoo9KhFQEKiUmlWorkflow.ReexportsWorkflow.ExtraWorkflow.Types Workflow.Lens Workflow.KeysWorkflow.ExecuteWorkflow.Examplepress Workflow.Core'exceptions-0.8.3-5OTPYzRazb4DJ75sPncYEhControl.Monad.Catch MonadThrow"free-4.12.4-K2p2e1h70JEH5CGntMFpUIControl.Monad.Free.Class MonadFreefailedKeyMetaKeyHyperKey ControlKey CapsLockKeyShiftKey OptionKey FunctionKeyGraveKeyMinusKeyEqualKey DeleteKeyForwardDeleteKeyLeftBracketKeyRightBracketKey BackslashKey SemicolonKeyQuoteKeyCommaKey PeriodKeySlashKeyTabKeySpaceKey ReturnKey LeftArrowKey RightArrowKey DownArrowKey UpArrowKeyAKeyBKeyCKeyDKeyEKeyFKeyGKeyHKeyIKeyJKeyKKeyLKeyMKeyNKeyOKeyPKeyQKeyRKeySKeyTKeyUKeyVKeyWKeyXKeyYKeyZKeyZeroKeyOneKeyTwoKeyThreeKeyFourKeyFiveKeySixKeySevenKeyEightKeyNineKey EscapeKeyF1KeyF2KeyF3KeyF4KeyF5KeyF6KeyF7KeyF8KeyF9KeyF10KeyF11KeyF12KeyF13KeyF14KeyF15KeyF16KeyF17KeyF18KeyF19KeyF20Key ModifiersModifier 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_ApplicationExecutableApplicationNameApplicationExecutable'ApplicationName' Application'getApplication WorkflowF SendKeyChordSendTextSendMouseClickSendMouseScroll GetClipboard SetClipboardCurrentApplicationOpenApplicationOpenURLDelaySimpleKeyChord modifier2key isModifierKey isAlphaNumKeyisAlphabeticKey isNumericKey displayKey $fNFDataKey$fNFDataModifier$fNFDataMouseScroll$fNFDataMouseButton$fNFDataWorkflow_$fSemigroupApplication'$fMonoidApplication'$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 sendKeyChordsendTextsendMouseClicksendMouseScroll getClipboard setClipboardcurrentApplicationopenApplicationopenURLdelaysendKeySequence sendKeyChord'fromWorkflows_ fromWorkflow_ KeySyntaxModifierSyntaxKeyChordSyntaxmodifierSyntax keySyntaxreadEmacsKeySequencereadEmacsKeyChordreadEmacsModifier readEmacsKeypress'readKeySequence readKeyChord readModifierreadKeydefaultKeyChordSyntaxdefaultModifierSyntaxdefaultKeySyntaxemacsKeyChordSyntaxemacsModifierSyntaxemacsKeySyntaxaddModsaddMod char2keychord$fMonoidKeyChordSyntax$fNFDataKeyChordSyntax$fShowKeyChordSyntax$fReadKeyChordSyntax$fEqKeyChordSyntax$fOrdKeyChordSyntax$fDataKeyChordSyntax$fGenericKeyChordSyntax WorkflowD _sendKeyChord _sendText_sendMouseClick_sendMouseScroll _getClipboard _setClipboard_currentApplication_openApplication_openURLExecuteWorkflowgetExecuteWorkflowrunWorkflowByTdelayMilliseconds delaySecondsmainbaseGHC.Base++ghc-primGHC.PrimseqGHC.Listfilterzip System.IOprint Data.Tuplefstsnd otherwisemap$GHC.Real fromIntegral realToFrac Control.MonadguardjoinGHC.EnumBoundedminBoundmaxBoundEnumenumFrom enumFromThenenumFromThenTo enumFromTofromEnumsuccpred GHC.ClassesEq==/= GHC.FloatFloatingpiexplogsqrt**logBasesincostanasinacosatansinhcoshtanhasinhacoshatanh Fractional fromRational/recipIntegral toIntegerquotremdivmodquotRemdivModMonad>>=>>returnfail Data.DataDataFunctorfmap<$GHC.NumNum*+-negate fromIntegerabssignumOrd>=minmax<=compareGHC.ReadRead readsPrecreadListReal toRational RealFloat floatRadix floatDigits floatRange decodeFloat encodeFloatexponent significand scaleFloatisNaN isInfiniteisDenormalizedisNegativeZeroisIEEEatan2RealFracproperFractiontruncateroundceilingfloorGHC.ShowShow showsPrecshowshowList Applicativepure<*>*><* Data.FoldableFoldablefoldrfoldMapnulllengthfoldlfoldl'foldl1sumproductfoldr1maximumminimumelemData.Traversable TraversabletraversemapM sequenceAsequence GHC.GenericsGenericData.Semigroup Semigroup<>sconcatstimesMonoidmemptymappendmconcat GHC.TypesBoolFalseTrueCharDoubleFloatInt integer-gmpGHC.Integer.TypeIntegerMaybeNothingJustOrderingLTEQGTRationalIOWord Data.EitherEitherLeftRight GHC.NaturalNaturalControl.Monad.IO.ClassMonadIOliftIO Data.ListisSubsequenceOfmfilter<$!>unless replicateM_ replicateMfoldM_foldM zipWithM_zipWithM mapAndUnzipMforever<=<>=>filterM mapAccumR mapAccumLforMControl.Applicativeoptional WrappedMonad WrapMonad unwrapMonad WrappedArrow WrapArrow unwrapArrowZipList getZipListControl.Category>>><<<readIOreadLn appendFile writeFilereadFileinteract getContentsgetLinegetCharputStrLnputStrputChar Text.ReadreadsGHC.IO.ExceptionioErrorData.Functor.ConstConstgetConstnotElemallanyorand concatMapconcatmsum sequence_forM_mapM_ traverse_GHC.IOFilePath userErrorIOErroreither Data.ProxyProxy Data.OldListunwordswordsunlineslinesunfoldrsortOnsortBysort permutations subsequencestailsinitsgroupBygroupdeleteFirstsByunzip7unzip6unzip5unzip4zipWith7zipWith6zipWith5zipWith4zip7zip6zip5zip4genericReplicate genericIndexgenericSplitAt genericDrop genericTake genericLengthinsertByinsert partition transpose intercalate intersperse intersectBy intersectunionByunion\\deleteBydeletenubBynub isInfixOf isSuffixOf isPrefixOf findIndices findIndex elemIndices elemIndex stripPrefix dropWhileEndlex readParenText.ParserCombinators.ReadPReadS Data.Function&on Data.Functorvoid<$>lcmgcd^^^oddeven showParen showStringshowCharshowsShowSunzip3unzipzipWith3zipWithzip3!!lookupreversebreakspansplitAtdroptake dropWhile takeWhilecycle replicaterepeatiteratescanr1scanrscanl'scanl1scanlfoldl1'initlasttailunconshead Data.MaybemaybeuncurrycurrysubtractasTypeOfuntil$!flip.constidapliftM5liftM4liftM3liftM2liftMwhen=<<liftA3liftA2liftA<**> Alternativeempty<|>somemany MonadPlusmzeromplusStringGHC.ErrerrorWithoutStackTrace&&||notcontainers-0.5.7.1 Data.Map.BaseMap Data.Set.BaseSet1data-default-class-0.1.2.0-FYQpjIylblBDctdkHAFeXAData.Default.ClassDefaultdefdeepseq-1.4.2.0Control.DeepSeqNFDatarnfthrowM'hashable-1.2.6.0-EikjbjmXLfl2FtsVIjLwnCData.Hashable.ClassHashable hashWithSalthash"safe-0.3.14-ALdwhNEer7fKnF5VYCbXfHSafepredSafepredNotepredDefpredMaysuccSafesuccNotesuccDefsuccMay toEnumSafe toEnumNote toEnumDef toEnumMayfindIndexJustNotefindIndexJustDef findIndexJustelemIndexJustNoteelemIndexJustDef elemIndexJust findJustNote findJustDeffindJustlookupJustNote lookupJustDef lookupJustreadNotereadDefreadMayreadEitherSafeatNoteatDefatMayat assertNote fromJustNote fromJustDef cycleNotecycleDefcycleMay scanl1Note scanr1Note scanl1Def scanr1Def scanl1May scanr1May foldl1Note' foldl1Note foldr1Note foldl1Def' foldl1Def foldr1Def foldl1May' foldl1May foldr1May maximumByNote minimumByNote maximumByDef minimumByDef maximumByMay minimumByMay maximumNote minimumNote maximumDef minimumDef maximumMay minimumMaylastNoteheadNotelastDefheadDeflastMayheadMayinitSafeinitNoteinitDefinitMaytailSafetailNotetailDeftailMayabort#text-1.2.2.1-9Yh8rJoh8fO2JMLWffT3QsData.Text.Internal.LazyText#spiros-0.0.0-1m4EQOVufCI2o9MHC7fcFUSpiros.Utilitiesiorstriplstripstripforkever forkever_ list2maybe maybe2list either2bool either2maybe maybe2either maybe2boolnothing__BUG__todoICP:*::.<&>indextoInt$>snoc-: greaterThanlessThan<>CanInterpolate:~>:.: GHC.Conc.IO threadDelay