yi-core-0.19.4: Yi editor core library

Safe Haskell | None
Language | Haskell2010

Yi.Hooks

Contents

- Convenience function `runHook`
- Re-exports from Yi.Config.Simple

Description

This module provides assistance in implementing "hooks" in Yi. This module provides no major new functionality -- only assistance in using `YiConfigVariable`s more easily to implement hooks.

We consider a simple example. Suppose we have a function

    promptForFile :: Maybe FilePath -> YiM FilePath

which prompts the user to select a file from their file system, starting with the provided directory (if actually provided). Since this is a frequent task in Yi, it is important for it to be as user-friendly as possible. If opinions vary on the meaning of "user-friendly", then we would really like to provide multiple implementations of `promptForFile`, and allow users to select which implementation to use in their config files.

A way to achieve this is using hooks, as follows:

    -- create a new type
    newtype FilePrompter = FilePrompter
      { runFilePrompter :: Maybe FilePath -> YiM FilePath }
      deriving (Typeable)
    $(nameDeriveAccessors ''FilePrompter (n -> Just (n ++ "A")))

    -- give some implementations
    filePrompter1, filePrompter2, filePrompter3 :: FilePrompter
    ...

    -- declare FilePrompter as a YiConfigVariable (so it can go in the Config)
    instance YiConfigVariable FilePrompter

    -- specify the default FilePrompter
    instance Default FilePrompter where
       def = filePrompter1

    -- replace the old promptForFile function with a shim
    promptForFile :: Maybe FilePath -> YiM FilePath
    promptForFile = runHook runFilePrompter

    -- provide a custom-named Field for Yi.Config.Simple (not
    -- strictly necessary, but user-friendly)
    filePrompter :: Field FilePrompter
    filePrompter = customVariable

The user can write

    ...
       filePrompter %= filePrompter2
    ...

in their config file, and calls to `promptForFile` will now use the different prompter. Library code which called `promptForFile` does not need to be changed, but it gets the new `filePrompter2` behaviour automatically.

See Yi.Eval for a real example of hooks.

Synopsis

- runHook :: (HookType ty, YiConfigVariable var) => (var -> ty) -> ty
- class HookType ty
- customVariable :: YiConfigVariable a => Field a
- type Field a = Lens' Config a

# Convenience function `runHook`

runHook :: (HookType ty, YiConfigVariable var) => (var -> ty) -> ty Source #

Looks up the configured value for the hook, and runs it. The argument to `runHook` will typically be a record accessor. See `HookType` for the valid hook types.

class HookType ty Source #

The class of "valid hooks". This class is exported abstractly, but the instances can be phrased quite simply: the functions (of arbitrarily many arguments, including zero) which run in either the `EditorM` or `YiM` monads.

A typical example would be something like

`Int -> String -> `EditorM` String`.

Minimal complete definition

runHookImpl

#### Instances

Instances details

HookType (EditorM a) Source # |
Instance details Defined in Yi.Hooks Methods runHookImpl :: YiConfigVariable var => (var -> EditorM a) -> EditorM a
HookType (YiM a) Source # |
Instance details Defined in Yi.Hooks Methods runHookImpl :: YiConfigVariable var => (var -> YiM a) -> YiM a
HookType b => HookType (a -> b) Source # |
Instance details Defined in Yi.Hooks Methods runHookImpl :: YiConfigVariable var => (var -> a -> b) -> a -> b

# Re-exports from Yi.Config.Simple

customVariable :: YiConfigVariable a => Field a Source #

Accessor for any `YiConfigVariable`, to be used by modules defining `YiConfigVariable`s. Such modules should provide a custom-named field. For instance, take the following hypothetical `YiConfigVariable`:

@newtype UserName = UserName { unUserName :: String } deriving(Typeable, Binary, Default) instance YiConfigVariable UserName

$(nameDeriveAccessors ''UserName (n -> Just (n ++ "A")))

userName :: `Field` `String` userName = unUserNameA `.` `customVariable`@

Here, the hypothetical library would provide the field `userName` to be used in preference to `customVariable`.

type Field a = Lens' Config a Source #

Fields that can be modified with all lens machinery.