yi-0.7.1: The Haskell-Scriptable Editor

Safe HaskellNone

Yi.Hooks

Contents

Description

This module provides assistance in implementing "hooks" in Yi. This module provides no major new functionality -- only assistance in using YiConfigVariables 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 Initializable FilePrompter where
    initial = 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

Convenience function runHook

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

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.

Instances

HookType (EditorM a) 
HookType (YiM a) 
HookType b => HookType (a -> b) 

Re-exports from Yi.Config.Simple

customVariable :: YiConfigVariable a => Field aSource

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

newtype UserName = UserName { unUserName :: String }
  deriving(Typeable, Binary, Initializable)
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 = Accessor Config aSource

Fields that can be modified with (%=), get and modify.