Skip to content
Commits on Source (6)
......@@ -4,3 +4,5 @@ _build/
/setup.log
/setup.exe
/setup-dev.exe
.merlin
*.install
\ No newline at end of file
language: c
sudo: required
install: wget https://raw.githubusercontent.com/ocaml/ocaml-ci-scripts/master/.travis-opam.sh
script: bash -ex .travis-opam.sh
env:
- OCAML_VERSION=4.02
- OCAML_VERSION=4.03
- OCAML_VERSION=4.04
- OCAML_VERSION=4.05
- OCAML_VERSION=4.06
- OCAML_VERSION=4.07
os:
- linux
- osx
2.0.3 (2019-08-09)
------------------
* Zed\_string
* `exception Invalid of string * string` raised when an invalid Zed\_char sequence is encounted
* `next_ofs : t -> int -> int` returns the offset of the next zchar in `t`
* `prev_ofs : t -> int -> int` returns the offset of the prev zchar in `t`
2.0.2 (2019-06-21)
------------------
* Zed\_utf8: fix an ofs-stepping bug in function `unsafe_extract_prev`
2.0.1 (2019-06-04)
------------------
* Zed\_char: add an `indv_combining` option to the transforming
functions(`of_uChars, zChars_of_uChars, of_utf8`) to determine whether
to extract individual combining marks from the parameter (#18)
* Zed\_char: clarify some documentation comments (#18)
2.0 (2019-05-17)
----------------
### Additions
* module Zed\_char
* module Zed\_string
* Zed\_cursor
* `column_display: Zed_cursor.t -> int React.signal`
* `get_column: Zed_cursor.t -> int`
* `coordinates_display: Zed_cursor.t -> (int * int) React.signal`
* `get_coordinates: Zed_cursor.t -> int * int`
* Zed\_edit
* `regexp_word_core: Zed_re.Core.t`
* `regexp_word_raw: Zed_re.raw.t`
* `match_by_regexp_core`
* `match_by_regexp_raw`
### Breaking
* Zed\_rope
* Zed\_rope.empty is a function now
* Other functions in this module take `Zed_char.t` or `Zed_string.t` as arguemnts instead of `UChar.t` or `Zed_utf8.t`
* module Zipper is divided into two modules, Zip and Zip\_raw, to navigate over a rope by Zed\_char.t or UChar.t, respectively
* module Text is divided into three modules, Text, Text\_core, Text\_raw, to manager Zed\_rope by Zed\_char.t, the core UChar.t of a `Zed_char.t` and raw `UChar.t`, respectively
* Zed\_re is therefore divided into two modules: Core and Raw
* Zed\_cursor: the type `changes` is defined as a structure and has two more fields: `added_width` and `removed_width`
### General
* README: Add Travis badge (Kevin Ji, #11)
* Add travis config (Anurag Soni, #10)
* Switch to dune (Anurag Soni, #9)
1.6 (2017-11-05)
----------------
* safe-string compatibility (#8)
1.5 (2017-04-26)
----------------
* Switch to jbuilder (Rudi Gringberg, #4)
* Make `{delete_,kill_,}{next,prev}_word` consistent near the
start/end of the buffer (Fabian (github use copy), #5)
1.4 (2015-01-07)
----------------
......
# Makefile
# --------
# Copyright : (c) 2012, Jeremie Dimino <jeremie@dimino.org>
# Licence : BSD3
#
# Generic Makefile for oasis project
build:
dune build
# Set to setup.exe for the release
SETUP := setup.exe
test:
dune runtest
# Default rule
default: build
all-supported-ocaml-versions:
dune build @install @runtest --workspace dune-workspace.dev
# Setup for the development version
setup-dev.exe: _oasis setup.ml
sed '/^#/D' setup.ml > setup_dev.ml
ocamlfind ocamlopt -o $@ -linkpkg -package ocamlbuild,oasis.dynrun setup_dev.ml || \
ocamlfind ocamlc -o $@ -linkpkg -package ocamlbuild,oasis.dynrun setup_dev.ml || true
rm -f setup_dev.*
clean:
dune clean
# Setup for the release
setup.exe: setup.ml
ocamlopt.opt -o $@ $< || ocamlopt -o $@ $< || ocamlc -o $@ $<
rm -f setup.cmx setup.cmi setup.o setup.obj setup.cmo
build: $(SETUP) setup.data
./$(SETUP) -build $(BUILDFLAGS)
doc: $(SETUP) setup.data build
./$(SETUP) -doc $(DOCFLAGS)
test: $(SETUP) setup.data build
./$(SETUP) -test $(TESTFLAGS)
all: $(SETUP)
./$(SETUP) -all $(ALLFLAGS)
install: $(SETUP) setup.data
./$(SETUP) -install $(INSTALLFLAGS)
uninstall: $(SETUP) setup.data
./$(SETUP) -uninstall $(UNINSTALLFLAGS)
reinstall: $(SETUP) setup.data
./$(SETUP) -reinstall $(REINSTALLFLAGS)
clean: $(SETUP)
./$(SETUP) -clean $(CLEANFLAGS)
distclean: $(SETUP)
./$(SETUP) -distclean $(DISTCLEANFLAGS)
configure: $(SETUP)
./$(SETUP) -configure $(CONFIGUREFLAGS)
setup.data: $(SETUP)
./$(SETUP) -configure $(CONFIGUREFLAGS)
.PHONY: default build doc test all install uninstall reinstall clean distclean configure
.PHONY: build all-supported-ocaml-versions clean test
Zed
===
[![Build Status](https://travis-ci.org/ocaml-community/zed.svg?branch=master)](https://travis-ci.org/ocaml-community/zed)
Zed is an abstract engine for text edition. It can be used to write
text editors, edition widgets, readlines, ... You just have to
_connect_ an engine to your inputs and rendering functions to get an
......@@ -13,40 +15,12 @@ Zed provides:
* key-binding helpers,
* general purpose unicode rope manipulation functions.
Dependencies
------------
* [OCaml](http://caml.inria.fr/ocaml/) (>= 3.12)
* [findlib](http://projects.camlcity.org/projects/findlib.html)
* [Camomile](http://github.com/yoriyuki/Camomile) (>= 0.8)
* [react](http://erratique.ch/software/react)
For building the development version, you also need to install
[oasis](http://oasis.forge.ocamlcore.org/) (>= 0.3.0).
Installation
------------
To build and install zed:
$ ./configure
$ make
$ make install
### Documentation _(optional)_
To build the documentation:
$ make doc
It will then be installed by `make install`.
### Tests _(optionnal)_
To build and execute tests:
To build and install zed, use opam:
$ ./configure --enable-tests
$ make test
$ opam install zed
Modules
-------
......@@ -59,3 +33,5 @@ Modules
* `Zed_macro`: helpers for writing macro systems.
* `Zed_utf8`: general purpose UTF-8 strings manipulation.
* `Zed_rope`: general purpose unicode ropes manipulation.
* `Zed_char`: general purpose unicode characters manipulation.
* `Zed_string`: general purpose unicode strings manipulation.
# +-------------------------------------------------------------------+
# | Package parameters |
# +-------------------------------------------------------------------+
OASISFormat: 0.3
OCamlVersion: >= 3.12
Name: zed
Version: 1.4
LicenseFile: LICENSE
License: BSD-3-clause
Authors: Jeremie Dimino
Maintainers: Jeremie Dimino <jeremie@dimino.org>
Homepage: http://zed.forge.ocamlcore.org/
BuildTools: ocamlbuild
Plugins: DevFiles (0.3), META (0.3)
XDevFilesEnableMakefile: false
Synopsis: Abstract engine for text edition in OCaml
Description:
Zed is an abstract engine for text edition. It can be used to
write text editors, edition widgets, readlines, ...
.
Zed uses Camomile to fully support the Unicode specification, and
implements an UTF-8 encoded string type with validation, and a rope
datastructure to achieve efficient operations on large Unicode
buffers. Zed also features a regular expression search on ropes.
.
To support efficient text edition capabilities, Zed provides macro
recording and cursor management facilities.
# +-------------------------------------------------------------------+
# | The library |
# +-------------------------------------------------------------------+
Library zed
FindlibName: zed
BuildDepends: bytes, react, camomile (>= 0.8)
XMETADescription: Edition engine
Path: src
Install: true
Modules:
Zed_utf8,
Zed_rope,
Zed_edit,
Zed_cursor,
Zed_lines,
Zed_re,
Zed_input,
Zed_macro
# +-------------------------------------------------------------------+
# | Doc |
# +-------------------------------------------------------------------+
Document "zed-api"
Title: API reference for Zed
Type: ocamlbuild (0.3)
Install: true
InstallDir: $htmldir/api
DataFiles: style.css
BuildTools: ocamldoc
XOCamlbuildPath: ./
XOCamlbuildLibraries: zed
# +-------------------------------------------------------------------+
# | Misc |
# +-------------------------------------------------------------------+
SourceRepository head
Type: git
Location: https://github.com/diml/zed.git
Browser: https://github.com/diml/zed
# OASIS_START
# DO NOT EDIT (digest: bf9a998597fdf67b0b4fae25145f3bc3)
# Ignore VCS directories, you can use the same kind of rule outside
# OASIS_START/STOP if you want to exclude directories that contains
# useless stuff for the build process
true: annot, bin_annot
<**/.svn>: -traverse
<**/.svn>: not_hygienic
".bzr": -traverse
".bzr": not_hygienic
".hg": -traverse
".hg": not_hygienic
".git": -traverse
".git": not_hygienic
"_darcs": -traverse
"_darcs": not_hygienic
# Library zed
"src/zed.cmxs": use_zed
<src/*.ml{,i,y}>: pkg_bytes
<src/*.ml{,i,y}>: pkg_camomile
<src/*.ml{,i,y}>: pkg_react
# OASIS_STOP
#!/bin/sh
# OASIS_START
# DO NOT EDIT (digest: dc86c2ad450f91ca10c931b6045d0499)
set -e
FST=true
for i in "$@"; do
if $FST; then
set --
FST=false
fi
case $i in
--*=*)
ARG=${i%%=*}
VAL=${i##*=}
set -- "$@" "$ARG" "$VAL"
;;
*)
set -- "$@" "$i"
;;
esac
done
ocaml setup.ml -configure "$@"
# OASIS_STOP
(lang dune 1.1)
(name zed)
(lang dune 1.1)
;; This file is used by `make all-supported-ocaml-versions`
(context (opam (switch 4.02.3)))
(context (opam (switch 4.03.0)))
(context (opam (switch 4.04.2)))
(context (opam (switch 4.05.0)))
(context (opam (switch 4.06.1)))
(context (opam (switch 4.07.0)))
(* OASIS_START *)
(* DO NOT EDIT (digest: b10f2078af5a5fb2b4945766c99d8884) *)
module OASISGettext = struct
(* # 22 "src/oasis/OASISGettext.ml" *)
let ns_ str =
str
let s_ str =
str
let f_ (str: ('a, 'b, 'c, 'd) format4) =
str
let fn_ fmt1 fmt2 n =
if n = 1 then
fmt1^^""
else
fmt2^^""
let init =
[]
end
module OASISExpr = struct
(* # 22 "src/oasis/OASISExpr.ml" *)
open OASISGettext
type test = string
type flag = string
type t =
| EBool of bool
| ENot of t
| EAnd of t * t
| EOr of t * t
| EFlag of flag
| ETest of test * string
type 'a choices = (t * 'a) list
let eval var_get t =
let rec eval' =
function
| EBool b ->
b
| ENot e ->
not (eval' e)
| EAnd (e1, e2) ->
(eval' e1) && (eval' e2)
| EOr (e1, e2) ->
(eval' e1) || (eval' e2)
| EFlag nm ->
let v =
var_get nm
in
assert(v = "true" || v = "false");
(v = "true")
| ETest (nm, vl) ->
let v =
var_get nm
in
(v = vl)
in
eval' t
let choose ?printer ?name var_get lst =
let rec choose_aux =
function
| (cond, vl) :: tl ->
if eval var_get cond then
vl
else
choose_aux tl
| [] ->
let str_lst =
if lst = [] then
s_ "<empty>"
else
String.concat
(s_ ", ")
(List.map
(fun (cond, vl) ->
match printer with
| Some p -> p vl
| None -> s_ "<no printer>")
lst)
in
match name with
| Some nm ->
failwith
(Printf.sprintf
(f_ "No result for the choice list '%s': %s")
nm str_lst)
| None ->
failwith
(Printf.sprintf
(f_ "No result for a choice list: %s")
str_lst)
in
choose_aux (List.rev lst)
end
# 132 "myocamlbuild.ml"
module BaseEnvLight = struct
(* # 22 "src/base/BaseEnvLight.ml" *)
module MapString = Map.Make(String)
type t = string MapString.t
let default_filename =
Filename.concat
(Sys.getcwd ())
"setup.data"
let load ?(allow_empty=false) ?(filename=default_filename) () =
if Sys.file_exists filename then
begin
let chn =
open_in_bin filename
in
let st =
Stream.of_channel chn
in
let line =
ref 1
in
let st_line =
Stream.from
(fun _ ->
try
match Stream.next st with
| '\n' -> incr line; Some '\n'
| c -> Some c
with Stream.Failure -> None)
in
let lexer =
Genlex.make_lexer ["="] st_line
in
let rec read_file mp =
match Stream.npeek 3 lexer with
| [Genlex.Ident nm; Genlex.Kwd "="; Genlex.String value] ->
Stream.junk lexer;
Stream.junk lexer;
Stream.junk lexer;
read_file (MapString.add nm value mp)
| [] ->
mp
| _ ->
failwith
(Printf.sprintf
"Malformed data file '%s' line %d"
filename !line)
in
let mp =
read_file MapString.empty
in
close_in chn;
mp
end
else if allow_empty then
begin
MapString.empty
end
else
begin
failwith
(Printf.sprintf
"Unable to load environment, the file '%s' doesn't exist."
filename)
end
let rec var_expand str env =
let buff =
Buffer.create ((String.length str) * 2)
in
Buffer.add_substitute
buff
(fun var ->
try
var_expand (MapString.find var env) env
with Not_found ->
failwith
(Printf.sprintf
"No variable %s defined when trying to expand %S."
var
str))
str;
Buffer.contents buff
let var_get name env =
var_expand (MapString.find name env) env
let var_choose lst env =
OASISExpr.choose
(fun nm -> var_get nm env)
lst
end
# 237 "myocamlbuild.ml"
module MyOCamlbuildFindlib = struct
(* # 22 "src/plugins/ocamlbuild/MyOCamlbuildFindlib.ml" *)
(** OCamlbuild extension, copied from
* http://brion.inria.fr/gallium/index.php/Using_ocamlfind_with_ocamlbuild
* by N. Pouillard and others
*
* Updated on 2009/02/28
*
* Modified by Sylvain Le Gall
*)
open Ocamlbuild_plugin
type conf =
{ no_automatic_syntax: bool;
}
(* these functions are not really officially exported *)
let run_and_read =
Ocamlbuild_pack.My_unix.run_and_read
let blank_sep_strings =
Ocamlbuild_pack.Lexers.blank_sep_strings
let exec_from_conf exec =
let exec =
let env_filename = Pathname.basename BaseEnvLight.default_filename in
let env = BaseEnvLight.load ~filename:env_filename ~allow_empty:true () in
try
BaseEnvLight.var_get exec env
with Not_found ->
Printf.eprintf "W: Cannot get variable %s\n" exec;
exec
in
let fix_win32 str =
if Sys.os_type = "Win32" then begin
let buff = Buffer.create (String.length str) in
(* Adapt for windowsi, ocamlbuild + win32 has a hard time to handle '\\'.
*)
String.iter
(fun c -> Buffer.add_char buff (if c = '\\' then '/' else c))
str;
Buffer.contents buff
end else begin
str
end
in
fix_win32 exec
let split s ch =
let buf = Buffer.create 13 in
let x = ref [] in
let flush () =
x := (Buffer.contents buf) :: !x;
Buffer.clear buf
in
String.iter
(fun c ->
if c = ch then
flush ()
else
Buffer.add_char buf c)
s;
flush ();
List.rev !x
let split_nl s = split s '\n'
let before_space s =
try
String.before s (String.index s ' ')
with Not_found -> s
(* ocamlfind command *)
let ocamlfind x = S[Sh (exec_from_conf "ocamlfind"); x]
(* This lists all supported packages. *)
let find_packages () =
List.map before_space (split_nl & run_and_read (exec_from_conf "ocamlfind" ^ " list"))
(* Mock to list available syntaxes. *)
let find_syntaxes () = ["camlp4o"; "camlp4r"]
let well_known_syntax = [
"camlp4.quotations.o";
"camlp4.quotations.r";
"camlp4.exceptiontracer";
"camlp4.extend";
"camlp4.foldgenerator";
"camlp4.listcomprehension";
"camlp4.locationstripper";
"camlp4.macro";
"camlp4.mapgenerator";
"camlp4.metagenerator";
"camlp4.profiler";
"camlp4.tracer"
]
let dispatch conf =
function
| After_options ->
(* By using Before_options one let command line options have an higher
* priority on the contrary using After_options will guarantee to have
* the higher priority override default commands by ocamlfind ones *)
Options.ocamlc := ocamlfind & A"ocamlc";
Options.ocamlopt := ocamlfind & A"ocamlopt";
Options.ocamldep := ocamlfind & A"ocamldep";
Options.ocamldoc := ocamlfind & A"ocamldoc";
Options.ocamlmktop := ocamlfind & A"ocamlmktop";
Options.ocamlmklib := ocamlfind & A"ocamlmklib"
| After_rules ->
(* When one link an OCaml library/binary/package, one should use
* -linkpkg *)
flag ["ocaml"; "link"; "program"] & A"-linkpkg";
if not (conf.no_automatic_syntax) then begin
(* For each ocamlfind package one inject the -package option when
* compiling, computing dependencies, generating documentation and
* linking. *)
List.iter
begin fun pkg ->
let base_args = [A"-package"; A pkg] in
(* TODO: consider how to really choose camlp4o or camlp4r. *)
let syn_args = [A"-syntax"; A "camlp4o"] in
let (args, pargs) =
(* Heuristic to identify syntax extensions: whether they end in
".syntax"; some might not.
*)
if Filename.check_suffix pkg "syntax" ||
List.mem pkg well_known_syntax then
(syn_args @ base_args, syn_args)
else
(base_args, [])
in
flag ["ocaml"; "compile"; "pkg_"^pkg] & S args;
flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S args;
flag ["ocaml"; "doc"; "pkg_"^pkg] & S args;
flag ["ocaml"; "link"; "pkg_"^pkg] & S base_args;
flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S args;
(* TODO: Check if this is allowed for OCaml < 3.12.1 *)
flag ["ocaml"; "compile"; "package("^pkg^")"] & S pargs;
flag ["ocaml"; "ocamldep"; "package("^pkg^")"] & S pargs;
flag ["ocaml"; "doc"; "package("^pkg^")"] & S pargs;
flag ["ocaml"; "infer_interface"; "package("^pkg^")"] & S pargs;
end
(find_packages ());
end;
(* Like -package but for extensions syntax. Morover -syntax is useless
* when linking. *)
List.iter begin fun syntax ->
flag ["ocaml"; "compile"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
flag ["ocaml"; "doc"; "syntax_"^syntax] & S[A"-syntax"; A syntax];
flag ["ocaml"; "infer_interface"; "syntax_"^syntax] &
S[A"-syntax"; A syntax];
end (find_syntaxes ());
(* The default "thread" tag is not compatible with ocamlfind.
* Indeed, the default rules add the "threads.cma" or "threads.cmxa"
* options when using this tag. When using the "-linkpkg" option with
* ocamlfind, this module will then be added twice on the command line.
*
* To solve this, one approach is to add the "-thread" option when using
* the "threads" package using the previous plugin.
*)
flag ["ocaml"; "pkg_threads"; "compile"] (S[A "-thread"]);
flag ["ocaml"; "pkg_threads"; "doc"] (S[A "-I"; A "+threads"]);
flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]);
flag ["ocaml"; "pkg_threads"; "infer_interface"] (S[A "-thread"]);
flag ["ocaml"; "package(threads)"; "compile"] (S[A "-thread"]);
flag ["ocaml"; "package(threads)"; "doc"] (S[A "-I"; A "+threads"]);
flag ["ocaml"; "package(threads)"; "link"] (S[A "-thread"]);
flag ["ocaml"; "package(threads)"; "infer_interface"] (S[A "-thread"]);
| _ ->
()
end
module MyOCamlbuildBase = struct
(* # 22 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
(** Base functions for writing myocamlbuild.ml
@author Sylvain Le Gall
*)
open Ocamlbuild_plugin
module OC = Ocamlbuild_pack.Ocaml_compiler
type dir = string
type file = string
type name = string
type tag = string
(* # 62 "src/plugins/ocamlbuild/MyOCamlbuildBase.ml" *)
type t =
{
lib_ocaml: (name * dir list * string list) list;
lib_c: (name * dir * file list) list;
flags: (tag list * (spec OASISExpr.choices)) list;
(* Replace the 'dir: include' from _tags by a precise interdepends in
* directory.
*)
includes: (dir * dir list) list;
}
let env_filename =
Pathname.basename
BaseEnvLight.default_filename
let dispatch_combine lst =
fun e ->
List.iter
(fun dispatch -> dispatch e)
lst
let tag_libstubs nm =
"use_lib"^nm^"_stubs"
let nm_libstubs nm =
nm^"_stubs"
let dispatch t e =
let env =
BaseEnvLight.load
~filename:env_filename
~allow_empty:true
()
in
match e with
| Before_options ->
let no_trailing_dot s =
if String.length s >= 1 && s.[0] = '.' then
String.sub s 1 ((String.length s) - 1)
else
s
in
List.iter
(fun (opt, var) ->
try
opt := no_trailing_dot (BaseEnvLight.var_get var env)
with Not_found ->
Printf.eprintf "W: Cannot get variable %s\n" var)
[
Options.ext_obj, "ext_obj";
Options.ext_lib, "ext_lib";
Options.ext_dll, "ext_dll";
]
| After_rules ->
(* Declare OCaml libraries *)
List.iter
(function
| nm, [], intf_modules ->
ocaml_lib nm;
let cmis =
List.map (fun m -> (String.uncapitalize m) ^ ".cmi")
intf_modules in
dep ["ocaml"; "link"; "library"; "file:"^nm^".cma"] cmis
| nm, dir :: tl, intf_modules ->
ocaml_lib ~dir:dir (dir^"/"^nm);
List.iter
(fun dir ->
List.iter
(fun str ->
flag ["ocaml"; "use_"^nm; str] (S[A"-I"; P dir]))
["compile"; "infer_interface"; "doc"])
tl;
let cmis =
List.map (fun m -> dir^"/"^(String.uncapitalize m)^".cmi")
intf_modules in
dep ["ocaml"; "link"; "library"; "file:"^dir^"/"^nm^".cma"]
cmis)
t.lib_ocaml;
(* Declare directories dependencies, replace "include" in _tags. *)
List.iter
(fun (dir, include_dirs) ->
Pathname.define_context dir include_dirs)
t.includes;
(* Declare C libraries *)
List.iter
(fun (lib, dir, headers) ->
(* Handle C part of library *)
flag ["link"; "library"; "ocaml"; "byte"; tag_libstubs lib]
(S[A"-dllib"; A("-l"^(nm_libstubs lib)); A"-cclib";
A("-l"^(nm_libstubs lib))]);
flag ["link"; "library"; "ocaml"; "native"; tag_libstubs lib]
(S[A"-cclib"; A("-l"^(nm_libstubs lib))]);
flag ["link"; "program"; "ocaml"; "byte"; tag_libstubs lib]
(S[A"-dllib"; A("dll"^(nm_libstubs lib))]);
(* When ocaml link something that use the C library, then one
need that file to be up to date.
This holds both for programs and for libraries.
*)
dep ["link"; "ocaml"; tag_libstubs lib]
[dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)];
dep ["compile"; "ocaml"; tag_libstubs lib]
[dir/"lib"^(nm_libstubs lib)^"."^(!Options.ext_lib)];
(* TODO: be more specific about what depends on headers *)
(* Depends on .h files *)
dep ["compile"; "c"]
headers;
(* Setup search path for lib *)
flag ["link"; "ocaml"; "use_"^lib]
(S[A"-I"; P(dir)]);
)
t.lib_c;
(* Add flags *)
List.iter
(fun (tags, cond_specs) ->
let spec = BaseEnvLight.var_choose cond_specs env in
let rec eval_specs =
function
| S lst -> S (List.map eval_specs lst)
| A str -> A (BaseEnvLight.var_expand str env)
| spec -> spec
in
flag tags & (eval_specs spec))
t.flags
| _ ->
()
let dispatch_default conf t =
dispatch_combine
[
dispatch t;
MyOCamlbuildFindlib.dispatch conf;
]
end
# 606 "myocamlbuild.ml"
open Ocamlbuild_plugin;;
let package_default =
{
MyOCamlbuildBase.lib_ocaml = [("zed", ["src"], [])];
lib_c = [];
flags = [];
includes = []
}
;;
let conf = {MyOCamlbuildFindlib.no_automatic_syntax = false}
let dispatch_default = MyOCamlbuildBase.dispatch_default conf package_default;;
# 622 "myocamlbuild.ml"
(* OASIS_STOP *)
Ocamlbuild_plugin.dispatch dispatch_default;;
#use "topfind"
#require "topkg-jbuilder.auto"
This diff is collapsed.
# OASIS_START
# DO NOT EDIT (digest: 6385b5511b372175e2f554771063b58a)
version = "1.4"
description = "Edition engine"
requires = "bytes react camomile"
archive(byte) = "zed.cma"
archive(byte, plugin) = "zed.cma"
archive(native) = "zed.cmxa"
archive(native, plugin) = "zed.cmxs"
exists_if = "zed.cma"
# OASIS_STOP
(library
(name zed)
(public_name zed)
(wrapped false)
(flags (:standard -safe-string))
(libraries bytes react camomile result charInfo_width))
# OASIS_START
# DO NOT EDIT (digest: c22b9ff32b957e4d6413268196f6b213)
Zed_utf8
Zed_rope
Zed_edit
Zed_cursor
Zed_lines
Zed_re
Zed_input
Zed_macro
# OASIS_STOP
# OASIS_START
# DO NOT EDIT (digest: c22b9ff32b957e4d6413268196f6b213)
Zed_utf8
Zed_rope
Zed_edit
Zed_cursor
Zed_lines
Zed_re
Zed_input
Zed_macro
# OASIS_STOP
(*
* zed_char.ml
* -----------
* Copyright : (c) 2019, ZAN DoYe <zandoye@gmail.com>
* Licence : BSD3
*
* This file is a part of Zed, an editor engine.
*)
open CamomileLibraryDefault.Camomile
open Result
type t= Zed_utf8.t
type char_prop=
| Printable of int
| Other
| Null
let to_raw= Zed_utf8.explode
let to_array t= Array.of_list (Zed_utf8.explode t)
let zero= String.make 1 (Char.chr 0)
let core t= Zed_utf8.unsafe_extract t 0
let combined t= List.tl (Zed_utf8.explode t)
let prop_uChar uChar=
match CharInfo_width.width uChar with
| -1 -> Other
| 0->
if UChar.code uChar = 0
then Null
else Printable 0
| w-> Printable w
let prop t= prop_uChar (Zed_utf8.unsafe_extract t 0)
let is_printable uChar=
match prop_uChar uChar with
| Printable _ -> true
| _-> false
let is_printable_core uChar=
match prop_uChar uChar with
| Printable w when w > 0 -> true
| _-> false
let is_combining_mark uChar=
match prop_uChar uChar with
| Printable w when w = 0 -> true
| _-> false
let length= Zed_utf8.length
let size= length
let width t= CharInfo_width.width (Zed_utf8.unsafe_extract t 0)
let out_of_range t i= i < 0 || i >= size t
let get= Zed_utf8.get
let get_opt t i=
try Some (get t i)
with _-> None
let append ch mark=
match prop_uChar mark with
| Printable 0-> ch ^ (Zed_utf8.singleton mark)
| _-> failwith "combining mark expected"
let compare_core t1 t2=
let core1= Zed_utf8.unsafe_extract t1 0
and core2= Zed_utf8.unsafe_extract t2 0 in
UChar.compare core1 core2
let compare_raw= Zed_utf8.compare
let compare= compare_raw
let mix_uChar zChar uChar=
match prop_uChar uChar with
| Printable 0->
Ok (zChar ^ (Zed_utf8.singleton uChar))
| _->
Error (Zed_utf8.singleton uChar)
let first_core ?(trim=false) uChars=
let rec aux uChars=
match uChars with
| []-> None, []
| uChar::tl->
let prop= prop_uChar uChar in
match prop with
| Printable w->
if w > 0
then Some (prop, uChar), tl
else aux tl
| Other-> Some (prop, uChar), tl
| Null-> Some (prop, uChar), tl
in
match uChars with
| []-> None, []
| uChar::_->
if not trim && is_combining_mark uChar then
None, uChars
else
aux uChars
let rec subsequent uChars=
match uChars with
| []-> [], []
| uChar::tl->
let prop= prop_uChar uChar in
match prop with
| Printable w->
if w > 0 then
[], uChars
else
let seq, remain= subsequent tl in
uChar :: seq, remain
| _-> [], uChars
let of_uChars ?(trim=false) ?(indv_combining=true) uChars=
match uChars with
| []-> None, []
| uChar::tl->
match first_core ~trim uChars with
| None, _->
if indv_combining then
Some (Zed_utf8.singleton uChar), tl
else
None, uChars
| Some (Printable _w, uChar), tl->
let combined, tl= subsequent tl in
Some (Zed_utf8.implode (uChar::combined)), tl
| Some (Null, uChar), tl->
Some (Zed_utf8.singleton uChar) ,tl
| Some (Other, uChar), tl->
Some (Zed_utf8.singleton uChar) ,tl
let zChars_of_uChars ?(trim=false) ?(indv_combining=true) uChars=
let rec aux zChars uChars=
match of_uChars ~trim ~indv_combining uChars with
| None, tl-> List.rev zChars, tl
| Some zChar, tl-> aux (zChar::zChars) tl
in
aux [] uChars
external id : 'a -> 'a = "%identity"
let unsafe_of_utf8 : string -> t=
fun str-> if String.length str > 0
then str
else failwith "malformed Zed_char sequence"
let of_utf8 ?(indv_combining=true) str=
match of_uChars ~indv_combining (Zed_utf8.explode str) with
| Some zChar, []-> zChar
| _-> failwith "malformed Zed_char sequence"
let to_utf8 : t -> string= id
let unsafe_of_char c=
Zed_utf8.singleton (UChar.of_char c)
let unsafe_of_uChar uChar= Zed_utf8.singleton uChar
let for_all= Zed_utf8.for_all
let iter= Zed_utf8.iter
module US(US:UnicodeString.Type) = struct
module Convert = Zed_utils.Convert(US)
let of_t t= Zed_utf8.explode t |> Convert.of_list
let to_t us=
let len= US.length us in
let rec create i=
if i < len
then US.get us i :: create (i+1)
else []
in
let uChars= create 0 in
of_uChars uChars
let to_t_exn us=
match to_t us with
| Some t, _-> t
| _-> failwith "to_t_exn"
end
(*
* zed_char.mli
* ------------
* Copyright : (c) 2019, ZAN DoYe <zandoye@gmail.com>
* Licence : BSD3
*
* This file is a part of Zed, an editor engine.
*)
open CamomileLibrary
open Result
(** The type for glyphs. *)
type t
(**
To represent a grapheme in unicode is a bit more complicated than what
is expected: a printable UChar. For example, diacritics are added to
IPA(international phonetic alphabet) letter to produce a modified
pronunciation. Variation selectors are added to a CJK character to
specify a specific glyph variant for the character.
Therefore the logical type definition of [Zed_char.t] can be seen as
{[
type Zed_char.t= {
core: UChar.t;
combined: UChar.t list;
}
]}
*)
type char_prop =
Printable of int | Other | Null
(** The property of a character. It can be either [Printable of width],
[Other](unprintable character) or [Null](code 0). *)
val to_raw : t -> UChar.t list
val to_array : t -> UChar.t array
val core : t -> UChar.t
(** [core char] returns the core of the [char] *)
val combined : t -> UChar.t list
(** [combined char] returns the combining marks of the [char] *)
val unsafe_of_utf8 : string -> t
(** [unsafe_of_utf8 str] returns a [zed_char] from utf8 encoded [str] without any validation. *)
val of_utf8 : ?indv_combining:bool -> string -> t
(** [of_utf8 str] returns a [zed_char] from utf8 encoded [str].
This function checks whether [str] represents a single [UChar] or a
legal grapheme, i.e. a printable core with optional combining marks.
It will raise [Failure "malformed Zed_char sequence"] If the validation
is not passed.
@param indv_combining allow to create a [Zed_char.t] from a single
combining mark, default to [true]
*)
val to_utf8 : t -> string
(** [to_utf8 chr] converts a [chr] to a string encoded in UTF-8. *)
val zero : t
(** The Character 0. *)
val prop_uChar : UChar.t -> char_prop
(** [prop_uChar uChar] returns the char_prop of [uChar] *)
val prop : t -> char_prop
(** [prop ch] returns the char_prop of [ch] *)
val is_printable : UChar.t -> bool
(** Returns whether a [UChar.t] is a printable character or not. *)
val is_printable_core : UChar.t -> bool
(** Returns whether a [UChar.t] is a printable character and its width is not zero. *)
val is_combining_mark : UChar.t -> bool
(** Returns whether a [UChar.t] is a combining mark. *)
val size : t -> int
(** [size ch] returns the size (number of characters) of [ch]. *)
val length : t -> int
(** Aliase of size *)
val width : t -> int
(** [width ch] returns the width of [ch]. *)
val out_of_range : t -> int -> bool
(** [out_of_range ch idx] returns whether [idx] is out of range of [ch]. *)
val get : t -> int -> UChar.t
(** [get ch n] returns the [n]-th character of [ch]. *)
val get_opt : t -> int -> UChar.t option
(** [get ch n] returns an optional value of the [n]-th character of [ch]. *)
val append : t -> UChar.t -> t
(** [append ch cm] append the combining mark [cm] to ch and returns it. If [cm] is not a combining mark, then the original [ch] is returned. *)
val compare_core : t -> t -> int
(** [compare_core ch1 ch2] compares the core components of ch1 and ch2*)
val compare_raw : t -> t -> int
(** [compare_raw ch1 ch2] compares over the internal characters of ch1 and ch2 sequentially *)
val compare : t -> t -> int
(** Alias of compare_raw *)
val mix_uChar : t -> UChar.t -> (t, t) result
(** [mix_uChar chr uChar] tries to append [uChar] to [chr] and returns
[Ok result]. If [uChar] is not a combining mark, then an
[Error (Zed_char.t consists of uChar)] is returned. *)
val of_uChars : ?trim:bool -> ?indv_combining:bool -> UChar.t list -> t option * UChar.t list
(** [of_uChars uChars] transforms [uChars] to a tuple. The first value
is an optional [Zed_char.t] and the second is a list of remaining
uChars. The optional [Zed_char.t] is either a legal grapheme(a core
printable char with optinal combining marks) or a wrap for an
arbitrary UChar.t. After that, all remaining uChars returned as the
second value in the tuple.
@param trim trim leading combining marks before transforming, default to [false]
@param indv_combining create a [Zed_char] from an individual dissociated combining mark, default to [true]
*)
val zChars_of_uChars : ?trim:bool -> ?indv_combining:bool -> UChar.t list -> t list * UChar.t list
(** [zChars of_uChars uChars] transforms [uChars] to a tuple. The first
value is a list of [Zed_char.t] and the second is a list of remaining uChars.
@param trim trim leading combining marks before transforming, default to [false]
@param indv_combining create a [Zed_char] from an individual dissociated combining mark, default to [true]
*)
val for_all : (UChar.t -> bool) -> t -> bool
(** [for_all p zChar] checks if all elements of [zChar]
satisfy the predicate [p]. *)
val iter : (UChar.t -> unit) -> t -> unit
(** [iter f char] applies [f] on all characters of [char]. *)
(** The prefix 'unsafe_' of [unsafe_of_char] and [unsafe_of_uChar] means
the two functions do not check if [char] or [uChar] being transformed
is a valid grapheme. There is no 'safe_' version, because the scenario
we should deal with a single [char] or [uChar] is when the char
sequence are individual, incomplete. For example, when we are reading
user input. Even if a user wants to input a legal grapheme, say,
'a' with a hat(a combining mark) on top. the user will input 'a' and
then '^' individually, the later combining mark is always illegal.
What we should do is to invoke [unsafe_of_uChar user_input] and send
the result to the edit engine. Other modules in zed, like Zed_string,
Zed_lines, Zed_edit ... are already well designed to deal with such a
situation. They will do combining mark joining, grapheme validation for
you automatically. Use the two 'unsafe_' functions directly,
you're doing things the right way. *)
val unsafe_of_char : char -> t
(** [unsafe_of_char ch] returns a [Zed_char] whose core is [ch]. *)
val unsafe_of_uChar : UChar.t -> t
(** [unsafe_of_uChar ch] returns a [Zed_char] whose core is [ch]. *)
(** Converting between [UnicodeString.Type] and [Zed_char.t] *)
module US :
functor (US : UnicodeString.Type) ->
sig
module Convert :
sig
val of_list : UChar.t list -> US.t
val of_array : UChar.t array -> US.t
val to_uChars : US.t -> UChar.t list
end
val of_t : t -> US.t
val to_t : US.t -> t option * UChar.t list
val to_t_exn : US.t -> t
end