This manual documents the release 1.1 of the Cameleon environment.
After a short introduction, it explains the installation.
Then each tool is described, and the last chapter describes the other
libraries included in Cameleon.
If you install Cameleon from the sources, follow the explanations
below. If you install from a pre-compild package, you can ignore this
part.
Unpack the source archive with the following command : tar xfz cameleon_1_1.tar.gz
This will create a cameleon-1.1 directory, called the root directory.
Change to this directory.
Note for the impatient:
If you're used to install procedures, this one is not original, and
you can run the following commands to install Cameleon :
./configure [--includedir=/absolute/path/to/compiled/ocaml/sources]
(use the --includedir option if you have the compiled sources \\
of OCaml somewhere)
make depend
make
make doc
make install
In order to compile, you need to have OCaml 3.06 (or more)
and LablGtk 1.2.5 (or more) installed.
In order to compile the graphical toplevel and Epeire, you must
have the compiled sources of the OCaml compiler somewhere.
Use the ./configure script to configure the sources according
to your OCaml installation.
The configure script accepts the following options :
-prefix <dir>
Will make the files to be installed in subdirectories of <dir>
instead of in the OCaml directory.
-libdir <dir>
Will make the compiled libraries to be installed in <dir>
instead of the cameleon directory in the OCaml library directory.
-bindir <dir>
Will make the executables to be installed in <dir>
instead of the bin directory of the prefix directory.
-mandir <dir>
Will make the man pages to be installed in <dir>
instead of the man directory of the prefix directory.
--datadir=<dir>
Will use <dir> to store templates, plug-ins and pixmaps,
respectively in the templates, plugins and pixmaps directories.
The default directory is prefix/share.
--includedir=<dir>
Where <dir> must be the absolute path name to the OCaml compiled sources.
Use this option if you want to build the graphical toplevel and Epeire,
the graphical debugger, which both need to be linked with a part of the OCaml compiler.
Finally, if you have the permission to write in the
directories specified to the configure script,
the command make install
will install the executables, libraries, man pages, templates
and plugins.
The Report tool aims to make generation of XML documents from OCaml applications easier.
The main idea is to separate the structure of the document from the information
computed by the application and placed in the document.
For example, in the following document :
while computed information is ``Crepes'', ``flour'', ``eggs'' and ``sugar''.
To build our XML document, we must therefore describe its structure as well as
the way to fill it with information. Then, at runtime, the application will use
this description to generate the final XML document.
In practice, Report allows to graphically describe the document
(structure + information), and then to generate OCaml code which uses the Report
library. In particular, this library contains a function which computes a document
description to produce the final XML document.
An important point is that the way to compute the information needed in the document
is given in the form of OCaml code.
The Report library as well as the generated code are detailed in 3.2.
The description of document and the use of the report tool are explained in
3.3.
The Report module defines the types used to describe a document.
(** A report element. *)
type 'a report_ele =
| Leaf of (unit -> string)
| Tag of 'a tag
| List of 'a liste
| Cond of 'a cond
| Sub of (unit -> 'a report)
(** A tag. *)
and 'a tag = {
tag : string ;
atts : (string * (unit -> string)) list ;
tag_subs : 'a report_ele list
}
(** A list of substructures. *)
and 'a liste =
{ list_subs : 'a report_ele list ;
f : (unit -> 'a list) ;
mutable current : 'a ;
}
(** Conditional *)
and 'a cond =
{ cond : unit -> bool ;
subs_then : 'a report_ele list ;
subs_else : 'a report_ele list ;
}
(** A report description is a list of report elements. *)
and 'a report = {
rep_eles : 'a report_ele list ;
}
The type report_ele is the type of the tree nodes :
Leaf is used for the leafs of the tree and needs the code of a function
taking () and returning a string. While computing the document description,
() will be applied to this function in order to obtain the string to insert
into the final XML document.
This way of hiding OCaml code ``under'' fun () -> allows not to
compute the result until the computation of the leaf, thus allowing to use
values computed ``above'' the leaf.
Tag is used to define an XML node of the final XML document. It needs the
tag name, eventually a list of attributes and values, as well as subtrees of the
node. Values of attributes are OCaml code too, as for the leafs.
List allows to insert, while computing the final document, a list of subtrees
for each element in a list. The field f contains the OCaml function returning
the list of elements to iterate on.
The field current is used to store the current element while walking through
the subtrees. This way, the value of the field current can be used in the
functions which appear in the subtrees of the node.
Cond allows to use one list of subtrees or another, depending on the boolean
value returned by the given function.
Sub is used to insert another document in the current one.
The given function returns a document description which is computed too.
The document example of the introduction could be described by :
let rec report =
({
rep_eles = [
Tag { tag = "h1" ; atts = [] ;
tag_subs = [
Leaf (fun () -> "Crepes");
] } ;
Tag { tag = "list" ; atts = [] ;
tag_subs = [
( let rec ing =
{ f = (fun () -> ing_of_recipe "Crepes") ;
current = (Report.coerce 0) ;
list_subs = [
Tag { tag = "item" ; atts = [] ;
tag_subs = [ Leaf (fun () -> ing.current.ing_name) ] }
] }
in
List (Report.coerce ing))
]
}
]
} : int report)
The call to Report.coerce is necessary to force the type but type constraints
are already satisfied (notably the use of the current field) at this point.
As we can see, this structure can quickly become a pain to define and read.
To solve this problem, the report tool allows to graphically define
the document description and generate the OCaml code of this structure.
Moreover, the report value could have had parameters ; this is a
way to parametrize the final XML document.
The Report module contains the following functions :
(** Coerce report elements. *)
val coerce : 'a -> 'b
(** Compute a report and print it to the given formatter. *)
val compute : ?html: bool -> Format.formatter -> 'a report -> unit
(** Compute a report and print it in a file. *)
val compute_file : ?html: bool -> string -> 'a report -> unit
The coerce function is used to insert a 'a report_ele into
the node of a 'b report_ele, when 'a cannot be used as 'b.
This function must only be used for this purpose, as in the example above.
The compute function takes a formatter and a document
description and computes this description to generate the final XML document in
the given formatter. The html optional parameter allows not to
close some tags (like br) to generate HTML compliant documents.
The compute_file function acts like compute but writes in
the given file instead of a formatter.
The report.gui tool allows to describe a document (structure + code to fill it
with information), as well as the parameters of this document (these parameters
become parameters of the report value in the code example in 3.2).
The document is describe through a graphical user interface with a tree oriented view.
The report tool generates the OCaml code of the document description,
using the types defined in the Report library (cf. 3.2).
Here is the report command usage :
report [options]description_file
The following options are supported :
-gen
Generate the OCaml code for the document described in the given file.
The code is generated in a file whose name is function of description_file.
If description_file has an extension, the generated file as the same
name with the extension replaced by .ml. If description_file
has no extension, then the generated file has the same name, with the
.ml extension appended.
-ofile
Generate the OCaml code in file file, instead of the default file,
when the -gen option is given.
Zoggy is a graphical interface builder for LablGtk, the OCaml/GTK library.
Zoogy allows you to graphically build your windows and boxes, then
generate OCaml code which creates these windows and boxes.
We explain the use of Zoggy as in a tutorial, through two examples.
The ``Hello world'' example presented in section 4.3 is a simple first example
of the use of Zoggy. A more complex example is presented in section 4.4.
When Zoggy is launched, it loads the ~/.zoggy/templates file.
This file is a regular Zoggy file which can be edited with Zoggy. Each entity
in this file then appears in the Template menu of the entity edition window.
Selectionning a template insert it in the current entity.
So you can define your templates by editing your ~/.zoggy/templates file,
then use these templates when you use Zoggy to edit other files.
This example is a simple window with a button and a label. Clicking on the button
will display the text ``Hello world'' in the label. The final window is displayed on
figure 4.3.
Figure 4.1: The ``Hello world'' example window
The development process consists of the following steps:
We will describe the window in the file guibase.zog. This is done
by the following command: zoggy guibase.zog
The window of figure 4.3.1 appears. This window is used
to define entities. Each entity will become a class in the generated
code. The entity parameters will become class parameters. For each entity,
a hierarchy of widgets is defined, as explained later.
Each new instance of a class will build the widgets described in the entity
from which the class was generated.
Figure 4.2: The Zoggy main window
We need to add a new entity, corresponding to the window we want to build.
The Entity/Add entity command pops up a window where the entity name can be
given. We'll call it hello. After a click on the ``Ok'' button,
the main window now contains the new entity.
Click on the hello entity in the main window to open it.
The entity window appears, in which we can edit the widgets of the entity.
It is composed of
a menu bar, with common actions like save, copy, paste, ...
and some others we don't care about for the moment.
a frame on the left, which will contain the properties of
the selected widget,
a tree widget in the middle, showing the hierarchy of the widgets
of the entity,
a palette on the right, containing buttons. These buttons can be
used to add widgets to the entity widgets hierarchy.
For the moment, the widget hierarchy is empty, so the first thing to do
is to create a window: click on the ``window'' button in the palette.
Since buttons are ordered in the widget alphabetical order (top to
bottom and left to right), this button is at the end.
Two things occur:
a new empty window appears, it is the preview window. When you add
widgets to the widgets hierarchy, they will be displayed in this window,
and you will see them change when you change their properties.
This preview window can be hidden or shown by switching the ``preview''
check button in the entity window.
a node appears in the tree of the entity window.
Now click on the new item in the tree to edit the properties
of the window.
The ``Name'' field contains the OCaml identificator which will be
used for the widget in the code of the generated class. If it starts
with a '_', then this widget will not appear in the class interface
(but it will still be built for each new instance of the class).
Rename this widget to win.
Under the ``Name'' field, the properties of the window appear.
For each property, its name, its value, and the OCaml type of
its value are displayed.
The value can be changed, but in the end, it must be valid OCaml
code of the correct OCaml type.
For properties with integer
values, -1 means ``no value'' (or ``default value'').
Some properties have values of a variant type. In this case, a value
among the possible ones can be selected in the associated combo widget,
but OCaml code can still be used instead, to compute the value
at execution. In such a case, the preview will no be relevant for this
property, since the value will only be known at execution.
Here we will change the title of our window :
set the ``title'' value to ``Hello world''.
Note that the double quotes are important since this must be correct
OCaml code of type string.
You can see the preview window change as you modify the value.
Now we must add a vbox in our window, which will contain
one label and one button. Click on the ``vbox'' button in the
palette, select it in the tree and rename it to vbox.
Then click on the ``label'' button in the palette to add
our label widget. Select it in the tree, rename it to
wlabel, and set the ``text'' property to
``Nothing yet''.
As you added the widgets and changed properties of the label, you
may have noticed that the size of the window changed too. That's
because it adjusts itself to the widget it contains. When we
set the text of the label widget, this widget needed mode space,
so its parent widget (the vbox) needed more space and the window
grew. This behaviour can be changed with the properties
``allow_shrink'', ``allow_grow'' and ``auto_grow'' of the
window.
Now we must add a button to the vbox. Select the vbox item
in the widget tree, and click on the ``button'' button in the
palette. A menu appears, click on ``with label'' to create
a button with already a label in it. Enter ``Say it'' in
the window asking you the label text. As you can see in the widget
tree, two more widgets have been created, a button and a label in
it. The label has a name beginning with '_', to indicate that it
won't be in the interface of the generated class. Since we'll
need to access the button to specify what must be done when it is
clicked, select the button and rename it to wbutton.
Now you can save your description with the File/Save command,
and quit Zoggy.
The command camlp4o pa_zog.cma pr_o.cmo -impl guibase.zog > guibase.ml
will generate code to guibase.ml, according to the entities
found in guibase.zog.
Let's have a look at the generated code. Our ``hello'' entity
becomes the hello class:
class hello () =
The () parameter is important since without it (and no other
parameter) the widgets would be created only once, even with
various instances of the class.
Now we can see the creation of the widgets defined in the entity:
let win =
GWindow.window ~title:"Hello world" ~allow_shrink:true ~allow_grow:true
~auto_shrink:true ~modal:true ()
in
let vbox = GPack.vbox ~homogeneous:false ~packing:win#add () in
let wlabel =
GMisc.label ~text:"Nothing yet" ~justify:`LEFT ~line_wrap:true ~xpad:2
~ypad:2 ~packing:(vbox#pack ~expand:false ~fill:true) ()
in
let wbutton =
GButton.button ~packing:(vbox#pack ~expand:false ~fill:true) ()
in
let _5 =
GMisc.label ~text:"Say it" ~justify:`LEFT ~line_wrap:true
~packing:wbutton#add ()
in
We can find the OCaml code we typed, in some of the properties.
At last, the object is defined as :
object
val win = win
val vbox = vbox
val wlabel = wlabel
val wbutton = wbutton
method win = win
method vbox = vbox
method wlabel = wlabel
method wbutton = wbutton
end;;
As you can see, the class can be used in two ways:
by inheriting from this class, you can access the widget
directly by typing for example: win#show ()
by making a new instance of the class and then accessing
the widgets through the methods, like in : let c = new hello () in c#win#show ()
In the next step, we will use the first way to use this
generated class.
Now create a file hello.ml with the following code:
(* Gtk initializations *)
let _ = GMain.Main.init ()
class gui ()=
object
inherit Guibase.hello ()
initializer
(* Exit the event loop when the window is destroyed *)
ignore (win#connect#destroy GMain.Main.quit);
(* Display "Hello world" when the button is clicked. *)
ignore (wbutton#connect#clicked
(fun () -> wlabel#set_text "Hello world"));
(* Show the window *)
win#show ()
end
(* Build the window *)
let c = new gui ()
(* Enter event loop *)
let _ = GMain.Main.main ()
Now compile with the following command: ocamlc -o hello -I +lablgtk lablgtk.cma guibase.ml hello.ml
and execute : ./hello
Note that you can compile directly guibase.zog to
guibase.cmo and guibase.cmi with the following
command: ocamlc -c -pp "camlp4o pa_zog.cma -impl" -I +lablgtk -impl guibase.zog
Try adding other widgets and changing properties in this first example...
The tool is based on the following problem :
The creation of functions executing SQL queries
is repetitive:
translation of parameters into strings and concatenation of strings
to create the query, execution of the query, test on the return value,
translation of the returned data (for select queries) into
the correct OCaml type,
is error prone:
an error in the concatenation of strings to create the query
(for example a missing blank) or in the concatenated strings
will cause an error at run time,
does not allow a high maintainability: indeed, when the database
schema is modified, one must verify each query is still correct
against the new database schema.
To solve these problems, we want to
automatically generate the functions executing basic queries on each table,
allow the user to define complex queries, using the SQL language ;
the OCaml functions executing these queries being automatically
generated, we want to guarantee at compile time that execution
of these queries will not fail at run time
(because of errors like syntax errors or referencing a non-existent
column of a table),
automatically verify and invalidate some queries when the database schema
is modified.
To do so, we must have the following information about each colum of each table :
its name,
its type definition for the target DBMS,
some attributes like whether the column is nullable, whether it's a key
for this table,
its OCaml type in the source code we want to generate,
the functions to use to translate DBMS (resp. OCaml) values into OCaml
(resp. DBMS) values.
The list of tables with the above information for each column is what
we call the database schema.
We can note that:
The definition of the column and the translation functions are DBMS dependant.
The OCaml type, column name and some attributes are DBMS independant.
So we can have the same interface for accessing different underlying DBMS.
The application using this inteface can then be used for each DBMS
(if it does not use some DBMS specific functionalities, for example
the AUTO_INCREMENT attribute of MySQL).
The DBForge tool can be used to describe such a schema.
It does not allow yet the definition of complex queries and the verification
of these queries against the schema.
As an example, we will build a table with several columns, then use the
generated code to performs some actions on this table in a database.
The description of the schema is made with a graphical editor. A schema
is stored in a file. The following command launches the editor on the schema
in file base.sch: dbforge.gui base.sch
The edition window appears. From this window you can edit the tables
and columns, and define complex queries which will be encapsulated in
functions. (the definition of complex queries is not implemented yet).
Add a table with the menu Table/Add. Enter "foo" for the table name
and click on the "Ok" button. The table is then added to our schema. It does not
contain any column yet: as you can see when you select the table, the list
of columns remains empty.
We'll add three columns to our table. The first will be an integer used
as unique identifier, the second will be a float, and the third will be
a string.
Select the table "foo" and use the menu Columns/Add. The column edition
window appears. This window contains 4 tabs. The first ("Common") is used to
give information common to all DBMS. Each of the other tabs correspond to
a target library handled by DBForge: "ODBC" for OCamlODBC,
"MySQL" for OCaml-Mysql, et "PostgreSQL" for Postgres.
In the "Common" tab, type the following values in the fields :
"Name": id. This is the name of the column and also
of a field in a record type in the generated OCaml code. So this name
must a valid OCaml identifier.
"OCaml type": int. This is the OCaml type used to represent
the values of the column. If the column is ``nullable'' (see below), and
that the given type is t, then the type of the values for this column
will be t option, else it will be t. You can give any OCaml type,
but it must be valid, and known at compile time.
"Nullable": not activated. We indicate here whether the value
of a record for this column can be NULL. If it can be NULL,
the associated type in the generated OCaml code will be t option
instead of t, with t the type given in the field "OCaml type".
"Index": activated. We indicate that the table must contain an index
on this column. (not yet implemented in the code generation).
In each of the remaining tabs, you must indicate the SQL type of the column,
whether it's a key (primary key or just a key), and give translations
functions to convert SQL values (as strings) to and from OCaml values.
Some functions are available in the combo box of each function field,
but you can put your own instead.
At last, you can give a default SQL value, which will usually appear in the
DEFAULT clause of the column definition.
Here are the values to put in the fields of each tab :
"ODBC"
"MySQL"
"PostgreSQL"
"SQL type"
integer
INT
INT8
"Optional key type"
primary key
primary key
primary key
"sql ® OCaml"
int_of_string
Mysql.int2ml
int_of_string
"OCaml ® sql"
string_of_int
Mysql.ml2int
string_of_int
"Default SQL value"
Once this is done, click on the "Ok" to add the column to the table ``foo''.
In this column we want to store a comment text. This column is not a key
and we may have no value (that is we can have the NULL value).
Here are the values to fill the fields in "Common" with:
Field
Value
"Name"
comment
"OCaml type"
string
"nullable"
activated
"index"
not activated
And in the other tabs:
"ODBC"
"MySQL"
"PostgreSQL"
"SQL type"
varchar(255)
TEXT
TEXT
"Optional key type"
"sql ® OCaml"
string_of_sqlstring
Mysql.str2ml
string_of_sqlstring
"OCaml ® sql"
sqlstring_of_string
Mysql.ml2str
sqlstring_of_string
"Default SQL value"
Note: For the ``ODBC'' tab, we put vachar(255) as SQL type, which is far more
restrictive than the TEXT SQL type of the two other tabs, but this way we
ensure the portability of the application because this type is standard.
However, if we know that the underlying DBMS that the application will use through ODBC
supports another SQL type, we can use it. To do so, we can use the field ``Other'' with
the type to use, for example TEXT.
To compile the generated code, use the following commands, where DBDIR is the directory
where the library (OCamlODBC, OCaml-MySQL or Postgres) you want to use is : ocamlc -c -I DBDIR base.mli ocamlc -c -I DBDIR base.ml
You can also generate the documentation using ocamldoc : mkdir htmldoc ocamldoc -I DBDIR -html -d htmldoc base.mli
Then the documentation is in htmldoc/index.html.
You may have to add -I flags if you referenced other modules in the code in your
schema description (OCaml types and translation functions).
module B = Base
module F = B.Foo
let d = B.connect Sys.argv.(1) Sys.argv.(2)
let _ =
try F.create d
with Failure s -> prerr_endline s
let _ = F.delete d ()
let cpt = ref 0
let _ =
while (!cpt <= 1000) do
(
if !cpt mod 2 = 0 then
F.insert d ~id: !cpt ~length: None ()
else
F.insert d ~id: !cpt ~length: (Some (float_of_int !cpt))
~comment: (Some (string_of_int !cpt)) ();
incr cpt
)
done
let l = F.select d ()
let _ = List.iter (fun t ->
print_int t.F.id;
print_string "#";
(match t.F.length with
None -> print_string "NULL"
| Some f -> Printf.printf "%f" f);
print_string "#";
(match t.F.comment with
None -> print_string "NULL"
| Some text -> print_string text);
print_newline ()) l
let _ = F.drop d
The code above connects to a database, creates the table "foo",
deletes all records in it, fills it, reads it, prints the retrieved records
and destroys the table.
To compile this example : ocamlc -o example.x -I DBDIR ocamlodbc.cma base.cmo main.ml
This command works for OCamlODBC. For OCaml-MySQL, you must replace
ocamlodbc.cma by mysqlstatic.cma, et by postgres.cma for
the Postgres library.
Some other compilation options may be needed (-ccopt -l..., ...).
Next, launch the example this way (if your DBMS is well configured, launched,
and if the file ~/.odbc.ini is correct (for the OCamlODBC library)) : ./example.x <user> <database name>
The program should print a thousand records this way:
MLChat is a simple chat application. It does not use any server,
like usual chat applications, making it possible to use on a local
network. It supports a conference mode to have a discussion with
more than one person. The communication protocol is a text one,
so you can communicate with MLChat from applications not written
in OCaml.
At last, MLChat comes with a library which can be used to add chat
in other OCaml applications. The chat plug-in for Cameleon
(see ??) uses this library.
By default, MLChat uses the file ~/.mlchatrc,
but you can specify a different configuration file to use
with the -c option of the mlchat command.
The configuration window of MLChat is accessed through the
File/Options menu. You can specify your id, the
port to listen to, the colors, the people you know about, ...
Some of these options can be changed on the command line.
Try mlchat -h to get a list of the available options.
You launch MLChat with the following command: mlchat
The main window appears, displaying the list of people
you know about. The first time you launch MLChat (or you
specify a new configuration file), this list is empty.
You should first set some options, using File/Options.
Set your id and some other options.
You can add people to your list in the ``People'' tab or
with the File/Add people menu.
Some people can connect to you if they know your host and port.
If these people are already in your list, they will appear
as connected. If they don't they'll appear in your list
as connected but also as temporary people, i.e. people
which will disappear next time you launch MLChat. To
add these people permanently to your list, use the
File/Toggle temp flag for selected people menu.
You can also change a permanent friend to a temporary
friend with this command.
You can remove people (temporary or not) from your list
with File/Remove selected people.
To discuss with one person of your list, select the person
and use the File/Open dialog menu. You can also
double-click on a person. A chat window appears. You
type your message in the text widget at the bottom. Hitting
the Enter key sends your message. The text widget at the
top of the window shows the messages sent and received.
The title of the window indicates the person you're chatting with.
To create a chat room, just select various people in the list
and use the File/Open dialog menu. You're prompted for
a chat room name, then the chat window appears, with an
additionnal button to see who's in the room. The messages
you send in this window are sent to all the people in the room.
You can quickly close a dialog window with the CTRL-C shortcut.
When someone sends you a message and your dialog window
for this person is closed, the window is automatically open.
Meanwhile, if the person sending the message is not in
your list of permanent people, the window will pop up only
if you set the ``popup all'' option to true in the configuration
window.
People are identified by their hostname and port.
So you may have two people in your list referencing to the same
person, if you have two different host names for this person.
MLChat comes with mlchat_say, a command line utility which
can be used to send messages to a MLChat application.
Usage: mlchat_say [-h <host>] [-p <port>] [-i <id>] <message>.
You can use it to be warned about events, for example when
you receive an e-mail.
OCamlCVS is a graphical front end for the CVS configuration management
utility. It displays the file and directories handled by CVS and
offers CVS functionalities through menus.
OCamlCVS can also show differences between two revisions, and a
merge assistant can be used to resolve conflicts.
OCamlCVS comes with a library which can be used to manipulate
CVS handled files in other applications, like it is in Cameleon.
You launch OCamlCVS with the following command: ocamlcvs [dir1] [dir2] ...
Every directory you give on the command line will be a root
of the directory tree, on the left part of the main window.
If you do not give any directory, the current working directory
will be the only root.
When ocamlcvs is launched, the main window appears,
with the directory tree on the left, and the file view
on the right. The file view shows the files handled by CVS
in the selected directory.
The CVS menu offers commands to perform on the
selected directory or the selected files.
These commands are also available throught contextual menus,
when you click with the right button on a directory or a file.
The files in the file view are displayed in different colors,
according to their state (Up-to-date, Locally modified, ...).
You can customize the CVS commands that OCamlCVS launches,
through your ~/.ocamlcvsrc file. Each line of this file
must have the following syntax: <command>:<options>
For example, to make OCamlCVS pass options
to the cvs update command, use the following line: update :-d -P -A
The commands which can be parametrized are
add, commit, remove, status, update.
Please note that you should not use options which modify the output
of the CVS command, since this output is parsed by OCamlCVS.
Note: By default, the update command is used with the -d option,
and the status command is always used with the -l option.
To launch Epeire, use the following command: epeire [options] [-- program [arguments]] options are detailed below, program is the name of the
program to debug, and arguments are its command line arguments.
By default, Epeire uses the $HOME/.epeirerc configuration file
to store options, including the program name and its arguments. So you
don't have to give the program name and its arguments if they are already
in the configuration file.
A configuration file different from the default one can be specified
with the -c option.
Other options are:
-I <dir>
Add <dir> to the list of include directories, to search for source files.
-history_size <int>
Set the number of times to keep in the history (default is 30).
-checkpoints_on <true|false>
Select whether the debugger makes checkpoints or not (default is true).
-max_checkpoints_count <int>
Set the maximum number of simultaneously live checkpoints (default is 15).
-checkpoints_big_step <int>
Set the number of events between two checkpoints for long displacements (default is 10000).
-checkpoints_small_step <int>
Set the number of events between two checkpoints for small displacements (default is 1000).
Other options can be set with the File/Settings menu. They are automatically
saved in the configuration file (the default one or the one specified by the -c option).
See the ocamldebug manual, in the OCaml user manual, for an explanation on using the debugger.
The graphical interface should be quite intuitive, but here are some hints.
You can show or hide the various windows, either from the configuration window of with
the Display menu.
The console can be shown to type commands like in the
ocamldebug tool. You type commands in the entry widget, at the bottom of the console
and the result appears in the text widget above. You can use the up and down arrows to
walk through the history of commands (even the commands launched from menus or by clicking
on buttons).
You can record your commands, using the Misc/Record menu. Use the
Misc/Stop recording menu to save your recorded commands in a file.
You can execute recorded commands with the Misc/Play menu, which
lets you select a file from where commands are read. Adding and removing
an identificator in the list of identificators (in the value inspector window)
are also recorded and played.
The value inspector window lets you add identificators whose value and type will
be always displayed for the current time or stack frame.
Use the 'Add' and 'Remove' buttons to add or remove
an identificator to the list. You can also click on an identificator in the code window
to add it to the list. When an identificator is unbound for the current time, no value
is displayed. In the list of identificators, you can double-click on an identificator
to browse its value at the current time, in a tree-oriented view. A click on the right
button opens a menu to print its type and value or browse its value.
The breakpoints window displays the list of breakpoints. You can add a breakpoint
from the console, with the various break console commands,
with the Misc/Add break to current event and Misc/Add break to function
menus,
from the code window, from the menu displayed when you right-click in the code.
The buttons 'Show' and 'Remove' in the breakpoints window lets you respectively show
the code where the breakpoint is located and remove a breakpoint.
The call stack window lets you see the current call stack. The 'Show' and 'Select'
buttons lets you respectively show the code corresponding to the selected stack frame
and select the stack frame to show the values at this frame.
The code window shows the various files, and hilight the line corresponding
to the current time or stack frame. From this window you can add breakpoints and
add identificators to the list in the value inspector window, as explained above.
If a file is not open and you want to see it, for example to add a breakpoint in it,
you can open it with the File/Open source file... menu. Then you select
a module and the source file of this module is open in the code window.
The Execution menu offers the commands to run the program.
The Program management menu gives access to some commands to load
and kill the program, and lets you selects the loading mode. Again,
see the ocamldebug manual for more information.
Topcameleon is a graphical OCaml toplevel. It offers the same possibilities
as the ocaml toplevel, and adds the following features:
you can browse the values defined, in a tree-oriented view
(the same as in Epeire, see chapter 8),
easy access to definitions of values, modules, types, ...,
you can save your code in a file,
you can load a file, add code and save the whole code in a file.
As for the ocaml toplevel, you can also build your own
graphical toplevel, including more modules, using the cam-mktop
utility (see section 9.4 below).
See the ocaml utility user manual, in the OCaml user manual, for
details about using the toplevel.
Topcameleon is launched by the following command: topcameleon [options][object-files][source-file]
The options are the same as the ocaml toplevel, and files in arguments
are handled the same was as by ocaml, except that if a source-file
is given, Topcameleon does not exit after having evaluated the code in this
file, but rather shows the main window with the code in the file still present
like if the user had typed it. This way, you can type your code after the
loaded code, and when you're satisfied you can save the whole code in
one file (by default it is saved in the given source-file).
So topcameleon cannot be used as a script interpreter, but it
was not developed for such a purpose.
Figure 9.1 shows the Topcameleon main window. The left pane contains
a list of the defined elements (values, types, modules, ...). The second
pane shows the selected value, in a tree-oriented way.
The right pane is the console, with the result on top and the input text widget
at the bottom. The 'Execute' button executes the code in the input widget.
Each time you define a new element, it is added to the list of elements.
When you select an element is this list, its value is shown (if it is a value)
in the 'tree view', and the result box jumps to its definition so you
can see how it was defined, and eventually copy part of the code to re-use
it in the input field.
Errors in the input field are hilighted when you execute a phrase
(do not forget the ';;' at the end of your phrases).
You can use the File/Load file..., File/Save and File/Save as ...
menus to load and save files. Note that the current file you're using is displayed
in the title bar. It is the file your code will be saved into if you use the
File/Save menu.
The File/Configuration menu opens the configuration window where you can change
some colors, the font, and choose whether the values in the tree are automatically expanded
or not (default is true, but it can take some time and memory for very large values).
As for the ocaml toplevel, you have a command which lets you define
your own graphical toplevel. This command is cam-mktop and is used
the same way as the ocamlmktop command (see the OCaml manual for
more information). The only differences are:
you get a graphical toplevel instead of a text one,
it already contains the following libraries: Unix, LablGtk, Options, Configwin, Gpattern, Okey.
OCamlmake-o-matic (omom) is a set of two tools to easily generate Makefiles.
Makefiles are generated from a omom file containing templates.
Omom files can be edited through a graphical user interface.
Omom comes with a cameleon plugin for better integration and easier use.
An omom file contains templates. A template is a set of variables, i.e.
identifiers with their corresponding values. Each template is associated
to a file which contains a skeleton of the future Makefile.
When generating the Makefile, all occurences of idenfitiers (more
precisely of !(identifier)) in the chosen template will be remplaced
by their values.
Omom files and templates can be edited with
omom-edit this way:
$ omom-edit omom_file.cm
The tool to generate Makefile is omom-gen.
$ omom-gen omom_file.cm my_template > Makefile
where my_template is the name of the template contained in
omom_file.cm you want to use.
There are at least two templates in each omom file: ocaml and common.
Those two templates are special. They are not associated with a file (so they
cannot be used as a a template name passed through the command line
to omom-gen) and they cannot be edited as others templates.
In a way, they are part of all other templates since the variables they contain
are included in each template. The ocaml templates defines variables
which are directly related to ocaml (such as OCAMLC and OCAMLOPT). You can modify the values of its variables but you can't
add new variables. The common templates purpose is to share variables
between templates. Some variable are predefined but you can add your
own variables.
A variable can be activated or not. If it's not, the variable value
will be set as its name as all other unknown identifiers.
The last thing to know about variables is that they can be of two
types: string or list of strings. The type really matters because of the
associated action. An action is a kind of filter which is applied to the value of a
variable before the substitution in the skeleton file. An action
can do different things depending on the type. At the moment, the only
provided action is include which adds -I to each element of a
list.
The window of figure 10.1 appears. Each tab of the window
represents a template. You can inspect the two special templates.
To generate a Makefile, you must add at least another template.
Click on the Templates/New template menu. Enter
my_template as the template name and my_template.cmt as
the associated file.
A new tab appears. Now, let's add a variable to our template.
Select the new tab. Click on the Template/Add field menu.
Choose VERSION as your variable name. Click on the check box to
active the just created variable and enter 0.1 in
the corresponding field as in figure 10.2
Figure 10.2: omom-edit
Now quit. When omom-edit ask you to save, answer yes.
We are now going to write our associated skeleton file:
You can use the omom plug-in in Cameleon, which gives
access to the omom editor and the omom generator from within
cameleon. See section 11.16.5 for more detail.
Launch cameleon and select a CVS working directory. Add a file of type
OCamlmake-o-matic spefication. The filename must end with
.cm (it is the default pattern for omom files).
Cameleon launches mom-edit. Two additionals templates are
provided: configure.in and Makefile.in. Select
configure.in. The field (AC_INIT must be initialized with
the name of a .ml file of your project. Then select Makefile.in.
EXE is the name of your binary. CMO_FILES is the name of
your .cmo files and LIBS is the name of the libraries you
use. Save and quit.
To generate your makefile, you must now launch the omom cameleon
command. The easiest way is to click on List of internal
commands in the Display menu and then double-click on omom.
First generate configure.in. Choose the configure.in
template and enter configure.in as the target. Do the same for
Makefile.in. Now generate the configure script, launching
autoconf in your working directory.
The Cameleon tool is the glue between the other tools, to provide
an integrated development environment. Files are managed with CVS,
it includes various editors and a documentation browser.
Plug-ins can be loaded to add functionalities.
The following command launches Cameleon : cameleon [options] [dir1] ... [dirn]
You can use cameleon.opt instead of cameleon if the native code vers
ion is available on your system, but then you won't be able to use plug-ins.
The dir1 ...dirn arguments are a list of directories,
each one being called a root directory, usually the root directory of one
of your project. If you don't specify any directory, the current working directory
becomes the only root directory.
Note that you must use CVS[1] for the configuration management of your
files in order to be able to use Cameleon.
The available options are:
-v
Display the version number and exit.
-norep
Use this option when the CVS repository is not available (for example
when you are not connected to the network). You can then access your files
through Cameleon but you cannot perfom any CVS action on it.
-com <command>
Make Cameleon execute the given <command> at launch time.
Commands are described in section 11.4.
This option can be used several times to perform several commands,
in the order they appear on the command line.
-expand_dirs_at_start <true|false>
Indicate whether the directory trees in the tree view of the main window
must be expanded at start or not. The default value is the one in
your $HOME/.cameleon/gui configuration file
(see section 11.5).
-check_edited_files_delay nb
When you edit files from Cameleon using Efuns or Xemacs,
Cameleon check whether these files are still being edited,
every nb miliseconds. You can change the delay here.
The default value is the one in your $HOME/.cameleon/gui
configuration file (see section 11.5).
The main window of Cameleon is shown on figure 11.1.
The left part of this window shows directory trees, starting from the
root directories. The right part of the window displays the list of files
handled by CVS in the selected directory.
The toolbar below the menu can be configured.
Cameleon's functionalities are accessed through internal commands. We will
write a command in red bold font.
Since menus are totally customizable, we will refer to commands rather than
menu entries to indicate the command used to perform an action.
In addition to Cameleon internal commands, external commands can be used.
These commands are shell commands.
An internal command is a string, used as identificator to get the associated
callback. This string must not begin with the character # and must not
containt blanks, simple-quotes or double-quotes.
An external command is a string beginning with the character #. The
command which gets executed is the string after the first #. In these
commands, you can use some expressions to refer to the current state of Cameleon :
%f refers to the first selected file, or to the empty string if no
file is selected,
%F refers to the list of selected files, separated with a blank space,
or to the empty string if no file is selected,
%d refers to the selected directory, or to the empty string if
no directory is selected,
%s refers to a string asked to the user. If more than one %s
appear in the command, all strings are asked to the user in a single window,
in the order they appear in the command, i.e. the value for the first %s
in the command will be entered in the first field of the window.
All file and directory names are ``quoted'', with the Filename.quote function
of the OCaml standard library.
Commands can be launched through menu entries, buttons in the toolbar, or keyboard
shortcuts.
Some internal commands are defined in Cameleon but more commands can be made available
by loading plug-ins (see 11.16).
At last, internal commands can take parameters, the same way as shell commands
in a shell, i.e. the arguments are separated by blanks and quotes can be
used when an argument contains one or more blanks.
a regular expression (pattern), used to associate the file type to a file name,
a description of the file type : This is the string displayed in the
file type column of the main window (see 11.3),
a color name : This is the color used to display a file in the main window
(see 11.3); the color name can be given with a name like ``Red''
or with a RGB code like ``#O4F5D6'',
a ``Binary'' flag to indicate whether the files of this type are binary files or
text files; this is useful for some CVS commands,
an editor : Cameleon provides various editors and more can be made available
by plug-ins (see 11.7). The editor associated to a file type
is used to edit the selected files when the edit command is triggered,
a list of templates : a template is a file. The list of templates is used
when adding a new file from Cameleon, with the new_file command.
The user must then choose the type of the file he wants to create, among the
list of defined file types. The templates associated to the file type he choses
are copied in the new file, with the cat UNIX command.
The file types can be defined in the ``File types'' tab of the configuration window,
as shown in figure 11.2.
Figure 11.2: Edition of file types.
When looking for the type of a file according to its name, Cameleon tries each regular expression
in the order they appear in the list, and stops with the first regular expression matching
the filename.
Note : The given regular expressions are used to match against the complete name of a file,
starting from the root node name.
The available documentation is defined as a list of doc-files (see 11.11).
This list can be edited in the ``Documentation files'' tab of the configuration window.
You can customize the toolbar in the main window (see 11.3),
by adding your own buttons, associated to the commands of your choice
(internal or external, see 11.4). This is done through the
``Custom toolbar'' tab of the configuration window.
Each button of the toolbar is defined by :
an icon, which must be a pixmap file (usually .xpm),
a label, which appears as a tooltip when the mouse cursor is on the button,
Menus and menu entries can be configured, through the
``Menus'' tab of the configuration window, shown on figure 11.3.
Figure 11.3: Edition of menus.
You can create menus, menu commands and separators.
Menu commands are defined by a label (which will appear in the menu)
and a command (internal of external, see 11.4). Activating
a menu command launches the associated internal of external command.
Note: Associating an internal command which is not available to a menu command
will disable the menu command.
While editing menus, you will have to mark one of them as the Doc menu,
used to dynamically add entries, depending on the available doc-files
(see 11.11).
The ``Colors and fonts'' tab lets you choose the colors and fonts
used in
the documentation browser (see section 11.10),
the modules view (see section 11.9.2)
and the background command execution window.
The keyboard shortcuts can be configured to bind a key combination
to a command (internal or external, see 11.4).
You can also set the key bindings of the documentation browser
(see 11.10).
The edition of key bindings is done in the ``Key bindings'' tab
of the configuration window.
With the bytecode executable cameleon, you can load plug-ins,
to define new commands, new editors, new views, ...
The selected plug-ins are loaded at launch time.
There are two lists of available plug-ins: the shared plug-ins
(in the shared plug-ins directory, see 11.15)
and the personal plug-ins, in your $HOME/.cameleon/plugins
directory.
In the ``Plug-ins'' tab of the configuration window you can
select which plug-ins you want to load, among the list
of available plug-ins.
The selected plug-ins are then loaded when you close the configuration window
with the ``Ok'' button. Plug-ins already loaded are not loaded again.
The configuration window may contain other tabs. Indeed, a plug-in
can add a configuration tab when it offers some configuration
possibilities. See 11.16 for details.
CVS actions can be performed from the main window
with the following internal commands :
add_dir,
update_dir,
commit_dir,
tag_dir,
add_file,
add_binary_file,
commit_files,
tag_files,
tags_of_file,
remove_files,
last_diff,
diff_with,
diff_between,
resolve_conflicts.
The contextual menu which appears when you click with the third mouse button on a file
of the files view (see section 11.9) or a directory gives access
to these commands, as does the default CVS menu.
Note: You can use the $HOME/.ocamlcvsrc file to configure the CVS commands
used in background (see chapter 7).
Editing a file is made with the edit command, or with the contextual
menu which appears when you click with the third mouse button on a file.
A file can be edited by various editors. The used editor depends on the type of
each file.
See 11.5.1 about associating an editor to a file type.
Currently, six editors are supported by Cameleon : Efuns[2],
Emacs[3], XEmacs[5], DBForge, Report, Zoggy.
A custom editor can also be associated to each file type to use another editor.
In order to use Efuns as editor, efuns must be running as a server on the
same machine.
Cameleon communicates with the efuns process through sockets. When a file
is edited, Cameleon asks to the efuns process to open this file.
Cameleon can also ask Efuns if a file is saved, for example when a file is about
to be commited. If the file is not saved, the user is asked whether he wants to
save the file before committing or not.
Emacs (respectively XEmacs) can be used as editor if an emacs (resp. xemacs) ser
ver is running on the same machine. Cameleon communicates with Emacs (resp. XEmacs)
through the emacsclient (resp. gnuclient) command.
Cameleon can only ask to Emacs to open a file, so the user must take care himself
about saving files before commiting, etc ... On the other hand, Cameleon can ask
XEmacs if a file is being edited, if a file changed, ...
The DBForge editor can be used to edit DBForge schema descriptions.
See chapter 5 for details about these files. When a schema file is
edited with DBForge, a window appears with the same graphical interface as the
stand-alone DBForge tool. Closing this window closes the file. When using the
DBForge editor, Cameleon can ask the user to save the edited file
before committing, the same way as with Efuns.
The Report editor can be used to edit Report XML document descriptions.
See chapter 3 for details. The Report editor in Cameleon works the
same way as the DBforge editor (see above).
The Zoggy editor can be used to edit Zoggy graphical interface descriptions. See
chapter 4 for details. The Zoggy editor in Cameleon works the same way
as the DBforge editor (see above).
If none of the predefined editors fit the user's needs, a custom editor can be
defined and associated to a file type. Custom editors are defined by plug-ins
(see 11.16).
This is the case for the Omom editor (see chapter 10).
The directory tree shows the directories handled by CVS. You can
perform CVS actions on the selected directory using the right commands
(see section 11.6).
To choose whether the trees are expanded at start or not, you
can use the expand_dirs_at_start command line option
(see section 11.2.1).
The right pane of the main window contains a notebook with
different views of the selected directory. Two views are
defined by default but more views can be added by plug-ins
(see section 11.16).
The files view shows the files handled by CVS, in the selected directory.
In this view you can perform CVS actions like commit, add file, ...
The files are displayed according to their associated file type
(see section 11.5.1).
The modules view show the OCaml modules in the selected directory.
To do so, it looks for a file dump.odoc in the selected
directory. This file must be an OCamldoc dump file. It should
contain information on the modules in the selected directory
but you can put information on the modules you want in that file.
If the file does not exist, Cameleon try a make dump.odoc
to create the file. If it does not work, and there is not dump.odoc
file available, nothing is displayed.
When information is found, you can see the modules and classes trees
on the left of the view, and selecting a module, module type, class
or class type shows its elements on the right of the view. You
can click with the right button of an element in the tree or the
list to create a menu letting you edit the corresponding file
at the line corresponding to the element definition.
You can choose to open the implementation or the inferface file,
depending of whether the documentation was created from the
implementation file or the interface file, or both.
You can change the colors in this view in the configuration
window (see section 11.5.5).
The ``Refresh'' button launch the make dump.odoc command
and read the dump.odoc file to update the view.
The documentation which can be accessed from Cameleon consist in information
on OCaml modules. The user can choose these modules.
Let's see how to choose these modules and browse their documentation.
The available documentation is defined by the user (see 11.5.2)
as a list of doc-files.
A doc-file contains information on toplevel modules, and must have been produced by
the -dump option of ocamldoc (see [4]).
Each specified doc-file is loaded when Cameleon is launched.
If the doc-file does not exist, a warning message points this out.
All toplevel modules in the doc-files are sorted and the Doc menu is built from
these modules (see 11.5.4).
In order to avoid too big menus, menus are cascaded.
When a module is chosen in the Doc menu, its documentation is displayed in a
documentation browser, described in 11.10.
At last, a label and an action can be associated to each doc-file (see 11.5.2).
For each of these pairs of label and action, an entry is added to the Doc menu,
with the given label. When the menu entry is activated, the given action is triggered. This
action usually updates the corresponding doc-file. When the action is over, the Doc
menu is updated according to the doc-file modifications.
You can access the documentation on a module by selecting it in the
Doc menu. It opens the documentation browser on this module.
The Doc menu also contains two entries, Exact search and Regexp search
which allow the user to search for elements (as defined in [4])
by name, with the exact name or a regular expression.
The search is performed on complete names, so you will find the iter function
of the List module by using, for example, the Exact search command
with the ``List.iter'' string.
If only one element matched the search, the documentation browser is open
on this element, else a window appears showing all the results, and selecting
one opens the documentation browser on this element.
The display_modules_box command can be used to show the list
of available toplevel modules (it is created at launch time, but you
can close it). In this window, called the doc modules box,
you can double-click on a module to
browse its documentation. You can walk through the list with the up
and down arrows or use the 'A' .. 'Z' keys to go directly to the modules
beginning with the letter corresponding to the key you hit. The
``Return'' key opens the selected module.
You can also use the top field to enter a string and
perform an exact search on this string with the button below.
This field is a combo box, where you can add predefined strings.
These predefined strings are bookmarks: you select a bookmark
and then click the ``Exact Search'' button to go to the element
(or the list of elements mathcing the search).
To add a bookmark, use the add_bookmark command in the documentation
browser.
The documentation browser is a window showing the interface
of a module or a class, with the comments of the source.
It uses the information read from OCamldoc dump files.
You can click on some text to follow the link, for example
you can click on a type name to go to its definition if it
is available, like in a HTML document.
The following actions can be performed in the browser window:
next_element
Go to the next element or link in the window,
from the current position.
previous_element
Go to the previous element or link in the window,
from the current position.
follow_link
Follow the link on which we are.
follow_link_in_new
Open a new browser window to follow the link
on which we are.
close
Close the browser window.
search
Search for a string in the window. You type the string
in the field at the bottom of the window. Can be called several times
to go to the next elements matchting the searched string.
back_search
Same as search but search backward instead of
forward.
back
Go back to the previous page (like in a web browser).
add_bookmark
Add the element which was used to open
the current page to the list of predefined strings in the search
field of the doc modules box.
home
Go to the beginning of the page.
end
Go to the end of the page.
menu
Pop up a contextual menu.
These action are bound to keys, and you can edit these bindings
in the configuration window (see section 11.5.6).
The contextual menu, which appears with the menu command or
a click with the right button on an element, allow you to browse
the follow a link in a new window, or open the file from which
the documentation was created, by using the associated editor.
The file is open as the right line where the element is defined.
Colors and fonts of the browser can be changed in the configuration
window (see section 11.5.5).
The docbrowser command (or docbrowser.opt if the native code version
is installed) is a standalone documentation browser that you can
launch without using Cameleon. It takes as arguments the OCamldoc dump files
you want to browse. The colors, fonts and shortcuts are the ones defined
in Cameleon (same configuration file).
The cam-config utility can be (and must be) used to get
information on the installation of Cameleon, in
the Makefiles of your own Cameleon plug-ins or your tools
using the Cameleon tools and libraries.
Cameleon (bytecode version) can load plug-ins in the form
of OCaml object-files (.cmo or .cma files).
Plug-ins can add:
new internal commands,
new editors (custom editors),
new configuration boxes (when a plug-in can be configured,
its configuration box can be added to the tabs of the configuration
window),
new views for the selected directory,
embedded applications.
Some default plug-ins are available and are detailed below.
To develop new plug-ins, you must use the Cam_plug
module of Cameleon, as explained in subsection 11.17.
There are two kinds of plug-ins: shared and personal.
Shared plug-ins are available for everyone and are installed
in the Cameleon shared plug-ins directory. This directory
is printed by the following command: cam-config -p
Personal plug-ins are in the user's $HOME/.cameleon/plugins
directory.
Here are the default installed shared plug-ins.
Do not forget that you can choose which plug-ins you want to
use (see section 11.5.7).
Make the user give a Cameleon command name and execute it.
This comment is associated to the following command,
thanks to our custom ocamldoc generator.
mozilla
Make the user give an url and launch mozilla with this url.
If no url is given, make the user type it. In this case,
the default url begins with http:// or file:///, depending
on whether a directory is selected or not.
This plug-in adds an editor to edit OCamlmake-o-matic files.
Commands
Command
Description
omom
omom template target uses the selected OCamlmake-o-matic file
to generate the given template in the given target file.
omom does the same after having asked the template and the
target file to the user.
Editors
Editor
Description
omom
Edit OCamlmake-o-matic files in the graphical editor.
To develop a Cameleon plug-in, you will have to use the
Cam_Plug module, installed with Cameleon. This module
defines functions to add editors, embedded applications,
internal commands. Some functions are used to retrieve information
on Cameleon current state (selected files, ...), and some
utilities functions are also provided.
(* *) (* This program is distributed in the hope that it will be useful, *) (* but WITHOUT ANY WARRANTY; without even the implied warranty of *) (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) (* GNU General Public License for more details. *) (* *) (* You should have received a copy of the GNU General Public License *) (* along with this program; if not, write to the Free Software *) (* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *) (* 02111-1307 USA *) (* *) (* Contact: Maxence.Guesdon@inria.fr *)
(** Utils plugin. This plugin provides some basic commands
to show how to create your own plugin.*)
openCam_plug
(** Make the user give a Cameleon command name and execute it.
This comment is associated to the following command,
thanks to our custom ocamldoc generator.
@command exec
*)
let exec args = match args with | [] ->
( let coms = Cam_plug.available_commands () in let com = ref (tryList.hd coms with _ ->"") in let p = Configwin.combo
~f: (fun s -> com := s)
~new_allowed: true
~blank_allowed: false "Command : "
coms
!com in matchConfigwin.simple_get "execute" [p] with Configwin.Return_cancel|Configwin.Return_apply-> () |Configwin.Return_ok->Cam_plug.eval !com ()
) | l -> let com = String.concat " " l in Cam_plug.eval com ()
(** Make the user give an url and launch mozilla with this url.
If no url is given, make the user type it. In this case,
the default url begins with http:// or file:///, depending
on whether a directory is selected or not.
@command mozilla
*)
let mozilla args = let url_opt = match args with
url :: _ ->Some url | [] -> GToolbox.input_string ~title: "mozilla"
~text: (match selected_dir() withNone->"http://"|Some s ->"file:///"^s) "url: " in match url_opt with None-> () |Some s -> ignore (Sys.command ("mozilla "^(Filename.quote s)^" &"))
let _ = add_command "exec""execute a prompted command" exec let _ = add_command "mozilla""launch mozilla on a given url" mozilla
You can compile it with the following command: ocamlc -c -I +cameleon plugin.ml
Then place the resulting .cmo file in the shared plug-ins directory
or your personal plug-ins directory. Cameleon will let you choose this
new plug-in to load, in the ``Plug-ins'' tab of the configuration window
(see section 11.5.7).
If you develop such plug-ins and want to distribute them, please
e-mail maxence.guesdon@inria.fr, so your plug-ins can be referenced
on a Cameleon plug-ins page.
This library is used to manage the configuration file(s)
of an application. You simply define your options
and it performs the loading and saving of the options.
Each option is defined from an option class
(for example string_option) or from a combination of
classes (for example list_option string_option).
Values of options are read and written with the two
operators !! and =:=.
The format of the configuration file looks like OCaml code,
and is human readable.
The library interface is described below, then you can find
a commented example.
This example is inspired from the make plug-in of Cameleon.
open Options
(* We create an option file *)
let op_file = create_options_file "my_option_file"
(* We define a new option, named "targets" in the configuration file.
The name is a list of strings, to allows nested groups of options
in the configuration file. Try to give an option name with more
than one string, and you will see that the option appears as
a record field in the configuration file.*)
let op_targets = define_option op_file ["targets"]
"some help text" (* this help text will be saved in the configuration file
if you use the save_with_help function *)
(list_option string_option) (* our option is a list of strings *)
["all" ; "byte" ; "clean" ; "depend" ; "doc" ; "opt" ; "%s"]
(* and the list above is its default value *)
(* We load the file, reading the values of the defined options. *)
let _ = load op_file
(* We save the file, with the help text as comments in the file. *)
let _ = save_with_help op_file
(* We can read the op_targets value with the !! operator *)
let l = !!op_targets
(* We can set the value of op_targets with the =:= operator *)
let _ = op_targets =:= [ "my" ; "new" ; "liste"]
This library offers convenient functions to make the user edit values (lists, strings,
booleans, colors, fonts,...) in LablGtk applications.
Here is the library interface, followed by an example.
let _ = GMain.Main.init ()
open Configwin
let param1 = string ~help: "a string" "a string" "a value"
let param2 = bool ~help: "bool value" "a boolean" true
let param3 = filename ~help: "a file name" "a file name" "foo"
let param4 = strings
~help: "a list of strings"
~eq: (fun _ -> fun _ -> false)
~add: (fun () -> ["another string" ; "and another string"])
"a string list"
["foo" ; "bar"]
let param5 = color ~help: "a color" "a color" "Red"
let param6 = font ~help: "a font" "a font" "7x13bold"
let param7 = date ~help: "a date" "a date" (1, 0, 2002)
let n = ref 0
let param8 = list
~help: "a list of int"
~add: (fun () -> incr n; [!n])
~titles: ["n" ; "n * n"]
"an int list" (fun n -> [string_of_int n ; string_of_int (n*n)])
[1 ; 2 ; 3]
let param9 = filenames ~help: "a list of filenames" "filenames" []
let structure = Section_list
("Section 1",
[
Section ("Section 1.1",
[ param1 ; param2 ; param5 ; param6 ; param7 ; param9]);
Section ("Section 1.2",
[ param3 ; param4 ; param8])
]
)
let _ = Configwin.edit "Titre" [structure]
This library is included in Cameleon thanks to its author Daniel de Rauglaudre.
The following text comes from the README file of the IoXML distribution.
IoXML is a Camlp4 syntax extension for OCaml mli and ml files which
generates XML parsers and printers for all types you define.
The function xparse_bar takes a XML tree as parameter, defined in
IoXML.ast. To get it from a file (or any stream), the library
function IoXML.parse_xml_list reads XML input. Another function
IoXML.parse_xml reads just one XML item.
If the type has parameters, the parser and printer functions receive
as first parameters, the parser and printers for them.
The function xprint_bar takes a Format.formatter function as parameter.
This library offers convenient classes to use some LablGtk widgets.
by now it only has one class, allowing to quickly build a clist
with some events already bound and handling the selection of elements.
Prompt for a binary file name to add in the selected directory. Then perform
the cvs add command.
add_dir
Prompt to add a directory to the selected one. Then perform the cvs add command.
add_file.
Prompt for a file name to add in the selected directory. Then perform
the cvs add command.
commit_dir
cvs commit the selected directory.
commit_files
Prompt for a comment, then perform a cvs commit on the selected files.
config
Open the configuration window.
diff_between
Show the differences between two versions of the first selected file.
The user is promped to select the two versions to compare.
diff_with
Ask for a version of the first selected file, and show differences between
the current version and the selected version.
display_modules_box
Display or update the box with the list of top modules whose documentation
is available.
edit
Edit the selected files with their associated editor(s).
edit_with
Edit the selected files with an editor chossen among the vailable ones.
last_diff
Show the differences between the first selected file and its original
version in the repository.
list_commands
Display the list of available internal commands, with
their description.
quit
Quit Cameleon.
reload_plugin
Make the user select a loaded plug-in and reload it.
remove_files
Ask for confirmation then performs a cvs remove on the selected files.
resolve_conflicts
Launch the conflict resolving assistant on the first selected file.
tag_dir
Prompt for a tag and tag all files under the selected directory.
Before, it checks whether one or more files already have the given tag, and
ask for confirmation if is the case.
tag_files
Prompt for a tag and tag the selected files.
Before, it checks whether one or more files already have the given tag, and
ask for confirmation if is the case.