packages feed

haskelisp-0.1.1.0: README.md

EXPERIMENTAL

Write Emacs module in Haskell, using Emacs 25's Dynamic Module feature.

* Only tested with linux.
* Only tested with Stack (LTS 6.26)
* You need to build emacs with --with-modules configuration options
* You need to specify some ghc-options to make it work

Sample:

    {-# LANGUAGE ForeignFunctionInterface,OverloadedStrings #-}
    module Main where

    import Emacs
    import Foreign.C.Types

    foreign export ccall "emacs_module_init" emacsModuleInit :: EmacsModule

    emacsModuleInit :: EmacsModule
    emacsModuleInit = defmodule "sample-module" $ do

      setVal "foo" (Symbol "bar")

      defun "square" $ \i -> do
        message "haskell squre function called"
        return $ (i*i :: Int)

    main :: IO ()
    main = undefined

# How to use

Explain using Stack and LTS 6.26 as premise.

## 1. Create a new project with Stack

    $ stack --resolver=lts-6.26 new mymodule

## 2. Change executable name to *.so and add haskelisp to the dependency

mymodule.cabal:

    executable mymodule.so
      hs-source-dirs:      app
      main-is:             Main.hs
      ghc-options:         -threaded -rtsopts -with-rtsopts=-N
      build-depends:       base
                         , mymodule
                         , haskelisp
      default-language:    Haskell2010

## 3. Change `ghc-options` and add `cc-options` to make shared library

mymodule.cabal:

    executable mymodule.so
      ...
      cc-options:          -fPIC
      ghc-options:         -shared -dynamic -fPIC -lHSrts-ghc7.10.3
      ...

## 4. Modules must be GPL compatible

The shared library must include `plugin_is_GPL_compatible` symbol to be loaded by Emacs.
Prepare a C source file and specify it with `c-sources` option.

    $ echo 'int plugin_is_GPL_compatible;' > plugin_is_GPL_compatible.c

mymodule.cabal:

    executable mymodule.so
      ...
      c-sources:           plugin_is_GPL_compatible.c
      ...

## 5. Write some code

Main.hs:

    {-# LANGUAGE ForeignFunctionInterface,OverloadedStrings #-}
    module Main where

    import Emacs
    import Foreign.C.Types

    foreign export ccall "emacs_module_init" emacsModuleInit :: EmacsModule

    emacsModuleInit :: EmacsModule
    emacsModuleInit = defmodule "mymodule" $ do

      defun "mysquare" $ \i -> do
        message "haskell squre function called"
        return $ (i*i :: Int)

    main :: IO ()
    main = undefined

We don't need `main` function, but without it cause a compile error,
so include a dummy one. It won't be called.

## 6. Build

    $ stack build

## 7. Copy the genereated shared library under `load-path`

For example, if `~/.emacs.d/lisp` is included in `load-path`:

    $ cp .stack-work/install/x86_64-linux/lts-6.26/7.10.3/bin/mymodule.so ~/.emacs.d/lisp/

## 8. Load your shared library

    (require 'mymodule)