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)