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

[ editor, emacs, gpl, library ] [ Propose Tags ]

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


[Skip to Readme]

Downloads

Note: This package has metadata revisions in the cabal description newer than included in the tarball. To unpack the package including the revisions, use 'cabal get'.

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.1.0.0, 0.1.0.1, 0.1.0.2, 0.1.0.3, 0.1.0.4, 0.1.0.5, 0.1.1.0
Dependencies base (>=4.8 && <5), containers (<0.6), mtl (<2.3), protolude (<0.2), text (<1.3) [details]
License GPL-3.0-only
Copyright 2016 Takenari Shinohara
Author Takenari Shinohara
Maintainer takenari.shinohara@gmail.com
Revised Revision 1 made by HerbertValerioRiedel at 2016-11-28T08:53:53Z
Category Editor, Emacs
Home page http://github.com/githubuser/haskelisp#readme
Source repo head: git clone https://github.com/githubuser/haskelisp
Uploaded by shintak at 2016-11-28T08:28:05Z
Distributions
Reverse Dependencies 1 direct, 0 indirect [details]
Downloads 4678 total (17 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2016-11-28 [all 1 reports]

Readme for haskelisp-0.1.1.0

[back to package description]

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)