Ledit with OCamlMakefile

Ledit with OCamlMakefile

The Ledit readline-replacement program can be built into a library automatically for use in your own projects with the following Makefile:

OCAMLMAKEFILE = OCamlMakefile

RESULT = ledit
SOURCES = cursor.mli cursor.ml ledit.mli ledit.ml
PRE_TARGETS = pa_local.cmo
USE_CAMLP4 = yes
LIBS = unix

all: byte-code-library native-code-library

include $(OCAMLMAKEFILE)

This Makefile makes use of the OCamlMakefile script. More information about this script can be found here: Compiling with GNU make

You will need to add a few preprocessor hints to the source code for this to work. This is due to Ledit's use of camlp4 syntax extensions and the revised syntax. These hints should be added as the first line. OCamlMakefile will detect them and add the appropriate preprocessor commands during compilation.

To the top of cursor.ml, cursor.mli, and ledit.mli, add:

(*pp camlp4r *)

To the top of ledit.ml:

(*pp camlp4r ./pa_local.cmo *)

And to the top of pa_local.ml:

(*pp camlp4r pa_extend.cmo q_MLast.cmo -loc loc *)

With this setup, a simple "make" will build ledit.cma and ledit.cmxa.

Installing using findlib

If you are using findlib, you can install Ledit as a site-wide library. The only remaining step is to create a file named META with the following contents:

name = "ledit"
version = "1.11"
description = "Interactive line editor"
requires = "unix"
archive(byte) = "ledit.cma"
archive(native) = "ledit.cmxa"

Now, as root, type:

make libinstall

This will install the Ledit libraries using ocamlfind. If all goes well, you can test your installation with the ocaml toplevel:

$ ocaml
         Objective Caml version 3.09.2

# #use "topfind";;
- : unit = ()
Findlib has been successfully loaded. Additional directives:
  #require "package";;      to load a package
  #list;;                   to list the available packages
  #camlp4o;;                to load camlp4 (standard syntax)
  #camlp4r;;                to load camlp4 (revised syntax)
  #predicates "p,q,...";;   to set these predicates
  Topfind.reset();;         to force that packages will be reloaded
  #thread;;                 to enable threads

- : unit = ()
# #require "ledit";;
/usr/local/lib/ocaml/3.09.2/ledit: added to search path
/usr/local/lib/ocaml/3.09.2/ledit/ledit.cma: loaded
# module M = Ledit;;
module M :
  sig
    val input_char : in_channel -> char
    val set_prompt : string -> unit
    val get_prompt : unit -> string
    val open_histfile : bool -> string -> unit
    val close_histfile : unit -> unit
    val set_max_len : int -> unit
    val set_son : int -> unit
  end
# Ledit.input_char stdin;;
test
- : char = 't'

Note that you cannot mix the ledit wrapper with the ledit library, or you will get the following error:

$ ledit ocaml
...
# #require "ledit";;
/usr/local/lib/ocaml/3.09.2/ledit: added to search path
/usr/local/lib/ocaml/3.09.2/ledit/ledit.cma: loaded
Error: standard input is not a terminal