Copyright | (c) Sergey Vinokurov 2018 |
---|---|
License | Apache-2.0 (see LICENSE) |
Maintainer | serg.foo@gmail.com |
Safe Haskell | Safe-Inferred |
Language | GHC2021 |
This module is the entry point for writing Emacs extensions in Haskell.
This package, though provides a lot of wrapping around Emacs's bare C interface, still presumes some familiarity with said interface. Thus, when developnig Emacs modules it's recommended to keep a reference of the C interface around. One such reference is https://phst.github.io/emacs-modules.html.
Minimalistic example
Consider Emacs function
(defun foo (f x y z &optional w t &rest quux) (+ (funcall f (* x y z)) (* (or w 1) (or t 2)) (length quux)))
With help of this package, it may be defined as
{-# LANGUAGE DataKinds #-} {-# LANGUAGE QuasiQuotes #-} import Data.Maybe import Data.Emacs.Module.SymbolName.TH import Emacs.Module
foo :: MonadEmacs m v => EmacsFunction ('S ('S ('S ('S 'Z)))) ('S ('S 'Z)) 'True m v s foo (R f (R x (R y (R z (O w (O t (Rest quux))))))) = do x' <- extractInt x y' <- extractInt y z' <- extractInt z w' <- traverse extractInt w t' <- traverse extractInt t tmp <- makeInt (x' * y' * z') tmp' <- extractInt =<< funcallSym "funcall" [f, tmp] produceRef =<< makeInt (tmp' + fromMaybe 1 w' * fromMaybe 2 t' + length quux)
Creating Emacs dynamic module
In order to make shared object or dll callable from Emacs, a cabal project with foreign-library section has to be created. Please refer to https://github.com/sergv/emacs-module/tree/master/test for such a project.
Please note that this project will need a small C file for initialising Haskell runtime. In the project mentioned before it's present as https://github.com/sergv/emacs-module/blob/master/test/cbits/emacs_wrapper.c
Synopsis
- class (forall s. Monad (m s), forall s. MonadInterleave (m s), forall s. Unbox (v s), forall s. PrimMonad (m s)) => MonadEmacs (m :: k -> Type -> Type) (v :: k -> Type) | m -> v where
- makeGlobalRef :: WithCallStack => v s -> m s (RawValue 'Pinned)
- freeGlobalRef :: WithCallStack => RawValue 'Pinned -> m s ()
- nonLocalExitCheck :: WithCallStack => m s (FuncallExit ())
- nonLocalExitGet :: WithCallStack => m s (FuncallExit (v s, v s))
- nonLocalExitSignal :: (WithCallStack, Foldable f) => v s -> f (v s) -> m s ()
- nonLocalExitThrow :: WithCallStack => v s -> v s -> m s ()
- nonLocalExitClear :: WithCallStack => m s ()
- makeFunction :: (WithCallStack, EmacsInvocation req opt rest, GetArities req opt rest) => (forall s'. EmacsFunction req opt rest m v s') -> Doc -> m s (v s)
- funcall :: (WithCallStack, Foldable f) => v s -> f (v s) -> m s (v s)
- funcallPrimitive :: (WithCallStack, Foldable f) => v s -> f (v s) -> m s (v s)
- funcallPrimitiveUnchecked :: (WithCallStack, Foldable f) => v s -> f (v s) -> m s (v s)
- intern :: WithCallStack => SymbolName -> m s (v s)
- typeOf :: WithCallStack => v s -> m s (v s)
- isNotNil :: WithCallStack => v s -> m s Bool
- eq :: WithCallStack => v s -> v s -> m s Bool
- extractWideInteger :: WithCallStack => v s -> m s Int64
- makeWideInteger :: WithCallStack => Int64 -> m s (v s)
- extractDouble :: WithCallStack => v s -> m s Double
- makeDouble :: WithCallStack => Double -> m s (v s)
- extractText :: WithCallStack => v s -> m s Text
- extractShortByteString :: WithCallStack => v s -> m s ShortByteString
- makeString :: WithCallStack => ByteString -> m s (v s)
- makeBinaryString :: WithCallStack => ByteString -> m s (v s)
- extractUserPtr :: WithCallStack => v s -> m s (Ptr a)
- makeUserPtr :: WithCallStack => FinalizerPtr a -> Ptr a -> m s (v s)
- assignUserPtr :: WithCallStack => v s -> Ptr a -> m s ()
- extractUserPtrFinaliser :: WithCallStack => v s -> m s (FinalizerPtr a)
- assignUserPtrFinaliser :: WithCallStack => v s -> FinalizerPtr a -> m s ()
- vecGet :: WithCallStack => v s -> Int -> m s (v s)
- unsafeVecGet :: WithCallStack => v s -> Int -> m s (v s)
- vecSet :: WithCallStack => v s -> Int -> v s -> m s ()
- vecSize :: WithCallStack => v s -> m s Int
- processInput :: WithCallStack => m s Result
- type EmacsFunction req opt rest (m :: k -> Type -> Type) (v :: k -> Type) (s :: k) = EmacsArgs req opt rest (v s) -> m s (v s)
- data Nat
- data R a b = R !a !b
- data O a b = O !(Maybe a) !b
- newtype Rest a = Rest [a]
- data Stop a = Stop
- data EmacsError = EmacsError {}
- data EmacsInternalError = EmacsInternalError {}
- reportAllErrorsToEmacs :: Env -> IO a -> IO a -> IO a
- module Emacs.Module.Functions
- module Data.Emacs.Module.Value
- data Env
- class Monad m => MonadThrow (m :: Type -> Type) where
- throwM :: (HasCallStack, Exception e) => e -> m a
Basic bindings
class (forall s. Monad (m s), forall s. MonadInterleave (m s), forall s. Unbox (v s), forall s. PrimMonad (m s)) => MonadEmacs (m :: k -> Type -> Type) (v :: k -> Type) | m -> v where Source #
A mtl-style typeclass for interacting with Emacs. Typeclass functions are mostly direct translations of emacs interface provided by 'emacs-module.h'.
For more functions please refer to Emacs.Module.Functions module.
makeGlobalRef :: WithCallStack => v s -> m s (RawValue 'Pinned) Source #
Make a global reference to a value so that it will persist across different calls from Emacs into exposed functions.
freeGlobalRef :: WithCallStack => RawValue 'Pinned -> m s () Source #
Free a global reference.
nonLocalExitCheck :: WithCallStack => m s (FuncallExit ()) Source #
Check whether a non-local exit is pending.
nonLocalExitGet :: WithCallStack => m s (FuncallExit (v s, v s)) Source #
Check whether a non-local exit is pending and get detailed data in case it is.
:: (WithCallStack, Foldable f) | |
=> v s | Error symbol |
-> f (v s) | Error data, will be converted to a list as Emacs API expects. |
-> m s () |
Equivalent to Emacs's signal
function. Terminates current computation.
NB if a non-local exit is alredy pending, this function will not
overwrite it. In order to do that, first use nonLocalExitClear
.
:: WithCallStack | |
=> v s | Tag |
-> v s | Data |
-> m s () |
Equivalent to Emacs's throw
function. Terminates current computation.
NB if a non-local exit is alredy pending, this function will not
overwrite it. In order to do that, use nonLocalExitClear
.
nonLocalExitClear :: WithCallStack => m s () Source #
Clean any pending local exits.
:: (WithCallStack, EmacsInvocation req opt rest, GetArities req opt rest) | |
=> (forall s'. EmacsFunction req opt rest m v s') | Haskell function to export |
-> Doc | Documentation |
-> m s (v s) |
Make Haskell function available as an anonymous Emacs
function. In order to be able to use it later from Emacs it should
be fed into bindFunction
.
:: (WithCallStack, Foldable f) | |
=> v s | Function name |
-> f (v s) | Arguments |
-> m s (v s) |
Invoke an Emacs function that may call back into Haskell.
:: (WithCallStack, Foldable f) | |
=> v s | Function name |
-> f (v s) | Arguments |
-> m s (v s) |
Invoke an Emacs function. The function should be simple and must not call back into Haskell.
funcallPrimitiveUnchecked Source #
:: (WithCallStack, Foldable f) | |
=> v s | Function name |
-> f (v s) | Arguments |
-> m s (v s) |
Invoke an Emacs function. The function should be simple and must not call back into Haskell.
Exit status is not checked - function is expected to always
succeed. Consult Emacs side to make sure that's the case.
Examples of safe functions: cons
, list
, vector
, etc.
intern :: WithCallStack => SymbolName -> m s (v s) Source #
Convert a string to an Emacs symbol.
typeOf :: WithCallStack => v s -> m s (v s) Source #
Get type of an Emacs value as an Emacs symbol.
isNotNil :: WithCallStack => v s -> m s Bool Source #
Check whether Emacs value is not nil
.
eq :: WithCallStack => v s -> v s -> m s Bool Source #
Primitive equality. Tests whether two symbols, integers or characters are the equal, but not much more. For more complete equality comparison do
intern "equal" >>= \equal -> funcallPrimitiveUnchecked equal [x, y]
extractWideInteger :: WithCallStack => v s -> m s Int64 Source #
Try to unpack a wide integer from a value.
makeWideInteger :: WithCallStack => Int64 -> m s (v s) Source #
Pack a wide integer for Emacs.
extractDouble :: WithCallStack => v s -> m s Double Source #
Try to unpack a floating-point number from a value.
makeDouble :: WithCallStack => Double -> m s (v s) Source #
Convert a floating-point number into Emacs value.
extractText :: WithCallStack => v s -> m s Text Source #
Extract string contents from an Emacs value.
extractShortByteString :: WithCallStack => v s -> m s ShortByteString Source #
Extract string contents from an Emacs value as utf8-encoded short bytestring.
makeString :: WithCallStack => ByteString -> m s (v s) Source #
Convert a utf8-encoded ByteString into an Emacs value.
makeBinaryString :: WithCallStack => ByteString -> m s (v s) Source #
Convert any ByteString into an Emacs unibyte string.
extractUserPtr :: WithCallStack => v s -> m s (Ptr a) Source #
Extract a user pointer from an Emacs value.
:: WithCallStack | |
=> FinalizerPtr a | Finalisation action that will be executed when user pointer gets garbage-collected by Emacs. |
-> Ptr a | |
-> m s (v s) |
Pack a user pointer into an Emacs value.
assignUserPtr :: WithCallStack => v s -> Ptr a -> m s () Source #
Set user pointer to a new value
extractUserPtrFinaliser :: WithCallStack => v s -> m s (FinalizerPtr a) Source #
Extract a finaliser from an user_ptr.
assignUserPtrFinaliser :: WithCallStack => v s -> FinalizerPtr a -> m s () Source #
Assign new finaliser into an user_ptr.
vecGet :: WithCallStack => v s -> Int -> m s (v s) Source #
Extract an element from an Emacs vector.
unsafeVecGet :: WithCallStack => v s -> Int -> m s (v s) Source #
Extract an element from an Emacs vector without checking for errors.
:: WithCallStack | |
=> v s | Vector |
-> Int | Index |
-> v s | New value |
-> m s () |
Assign an element into an Emacs vector.
vecSize :: WithCallStack => v s -> m s Int Source #
Get size of an Emacs vector.
processInput :: WithCallStack => m s Result Source #
Check whether user pressed 'C-g' and we should abort our operation.
Instances
Define functions callable by Emacs
type EmacsFunction req opt rest (m :: k -> Type -> Type) (v :: k -> Type) (s :: k) = EmacsArgs req opt rest (v s) -> m s (v s) Source #
Basic Haskell function that can be called by Emacs.
Type-level Peano numbers.
Indented to be used with DataKinds
extension enabled.
Error types
data EmacsError Source #
A high-level error thrown when an Emacs function fails.
Instances
Exception EmacsError Source # | |
Defined in Emacs.Module.Errors toException :: EmacsError -> SomeException # fromException :: SomeException -> Maybe EmacsError # displayException :: EmacsError -> String # | |
Show EmacsError Source # | |
Defined in Emacs.Module.Errors showsPrec :: Int -> EmacsError -> ShowS # show :: EmacsError -> String # showList :: [EmacsError] -> ShowS # | |
Pretty EmacsError Source # | |
Defined in Emacs.Module.Errors pretty :: EmacsError -> Doc ann # prettyList :: [EmacsError] -> Doc ann # |
data EmacsInternalError Source #
A low-level error thrown when assumptions of this package are violated and it's not safe to proceed further.
E.g. Emacs returned value not specified in a C enum - cannot really process it in a meaningful way.
Instances
Exception EmacsInternalError Source # | |
Defined in Emacs.Module.Errors | |
Show EmacsInternalError Source # | |
Defined in Emacs.Module.Errors showsPrec :: Int -> EmacsInternalError -> ShowS # show :: EmacsInternalError -> String # showList :: [EmacsInternalError] -> ShowS # | |
Pretty EmacsInternalError Source # | |
Defined in Emacs.Module.Errors pretty :: EmacsInternalError -> Doc ann # prettyList :: [EmacsInternalError] -> Doc ann # |
reportAllErrorsToEmacs Source #
Catch all errors this package might throw in an IO action and make Emacs aware of them.
This is a convenience function intended to be used around exported
initialise
entry point into an Emacs module.
Reexports
module Emacs.Module.Functions
module Data.Emacs.Module.Value
Third-party reexports
class Monad m => MonadThrow (m :: Type -> Type) where #
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.
throwM :: (HasCallStack, Exception e) => e -> m a #
Throw an exception. Note that this throws when this action is run in
the monad m
, not when it is applied. It is a generalization of
Control.Exception's throwIO
.
Should satisfy the law:
throwM e >> f = throwM e