Here are some questions and answers about Chamo and its usage.
This means that you can fully customize Chamo with pieces of OCaml code,
the same way you can customize Emacs with lisp code. There are multiple ways to do so.
For example, you can place some code in your file
This file is evaluated when
is launched. In this file, you can access any part of Chamo.
the reference documentation
for information about the API of the available modules.
For example, to display the "about box" at launch time, simply add to
chamo_init.ml the following code:
The same effect could be achieved by calling the command "about" with no arguments.
To do so from OCaml code, you can use the function
Another way to evaluate OCaml code to add your own command or whatever you want is
to call the "eval" command. When called without argument, this command
prompts the user for OCaml code to evaluate. If an argument is given, it is evaluated
as OCaml code. See
for details on commands. So, putting the following code in your file
Ed_command.eval_command "eval \"let x = 1;;\"";;is the same as simply putting
let x = 1;;
Another way to perform some customization is to use the
command line option to indicate a file containing OCaml code to evaluate
at launch time.
From a technical point of view, the
chamo.byte executable includes the
OCaml library which offers functions to evaluate OCaml code.
Then, some initializations are done by the
to make the interpreter look for modules interfaces in the cameleon2 and lablgtk2
directories detected during configuration. This is done by evaluating some
All the answer above is true for the bytecode version of Chamo
It is false for the native code version
Commands are functions associated to a name. The name is a string. See
about how to define a command. The commands can take parameters,
which are strings too. The call to a command is then a string of the form:
command arg1 arg2 ....
Arguments are optional. Some commands require arguments, some don't.
Some commands will prompt the user for missing arguments.
By default, the A-x (Alt-x) keys are bound to the "prompt_command" command which uses the minibuffer of the active window to make the user type in a command (name and arguments). Then the text entered is given to the "command" command which parses its first argument to separate the command name from arguments and really launches the command. Quoting of arguments works the same way as in the shell (with simple or double quotes).
Commands are defined in OCaml using the functions in
They are composed of a name, a list of parameter names, an optional description for
remaining parameters and the OCaml function which is called when the command is launched.
This function is of type
string array -> unit.
The parameters of the command are passed in the string array.
The indications about parameters names can be used by higher level functions
to prompt the user for missing parameters, with the names of the
parameters, so that the user knows what to enter.
Here is an example of the creation of a command which displays the message in the first argument, or "Alert!" if there is no argument:
let alert_message args = let message = if Array.length args < 1 then "Alert!" else Ed_misc.to_utf8 args.(0) in GToolbox.message_box "Alert message" message;; let com = Ed_commands.create_com "alert_message" [| "Message to display" |] alert_message;; Ed_commands.register com;;
It is useful to name and make visible the function associated to the command, so that it is also directly available in OCaml code, rather than calling
Ed_commands.eval_command "alert_message my_message";;or
Ed_commands.launch_command "alert_message" [|"my_message"|];;Of course, calling directly the function which was first associated to the command "alert_message" will short-circuit any redefinition of the command.
It is also possible to complete existing commands, by adding some code to execute before or
after the original code of a command. This is done with the functions
For example, if we want alert messages to be logged, we could use something like
let log_message args = (* log the message(s) in the arguments *) ... ;; Ed_commands.register_before (Ed_commands.create_com "alert_message" [|"Message to display"|] log_message);;
The list of available command names can be obtained with
Then it is easy to obtain, for each command, the names of its parameters:
let f name = let com = Ed_commands.get_com_or_fail name in print_string com.Ed_commands.com_name; Array.iter (fun s -> Printf.printf " (%s)" s) com.Ed_commands.com_args; (match com.Ed_commands.com_more_args with None -> () | Some s -> Printf.printf " (%s...)" s ); print_newline () ;; List.iter f (Ed_commands.available_command_names());;
A naming convention is needed to get some consistency in command names. By now, general commands are not prefixed. The commands relative to a sourceview mode (for example the "ocaml" mode of the "sourceview" view) should be prefixed by the mode name (e.g. "ocaml_"). The commands relative to a view (like "sourceview" or "odoc") should be prefixed by the view name (e.g. "sourceview_" or "odoc_"). The convention is to separate words in command names by "_" and not "-".
The user's global configuration files of Chamo are stored in the
directory and are prefixed with "chamo.". The files are created if they don't exist.
They are human readable with an OCaml-like syntax.
There are also "local" configuration files, that is files stored in the directory where Chamo was launched. By now, we can find:
.chamo.sourceview.bufferswhich contains the list of open buffers in the "sourceview" view, and the position of the cursor in each of them,
.chamo.layout.xmlwhich describes the layout of all open windows. This file is created on demand by the "store_layout" command. When Chamo is launched and this file exists in the current directory, it is read and all windows and views are created accordingly, so that you keep all your views arranged like they were when you stored the layout.
.chamo_init.mlwhich is evaluated by
chamo.byteat launch time, after the
~/.chamo/chamo_init.mlfile of the user; it can be used to add some customization relative to a particular directory.
Indeed. But don't panic, there's a logical organisation.
chamo.core, you will find some values concerning internal details, like the default charset encoding used to read/write files and convert to/from UTF-8 (Gtk2 uses UTF-8).
chamo.guicontains some options common to all Chamo windows, like key bindings.
chamo_init.mlis evaluated when
chamo.byteis launched; it contains OCaml source code. Think of it as the
~/.emacsfile of Emacs.
chamo.viewsdefines some options about view management, in particular the associations between filename patterns and views, and the default view to use when opening a file.
chamo.sourceviewcontain respectively the options of the "odoc" and "sourceview" views. As you understand now, the standard name of the configuration file of a view is
chamo.sourceview.mode.<mode name>, for example
Views in Chamo are different ways to edit or display files. The most commonly used view in the "sourceview" view, which allows the edition of any text file. It is based on GtkSourceView and can highlight syntax elements. Other views are available for some kinds of files:
Views define also their own description of menus and key bindings. When a view has the input focus, the menus it describes are available in the menubar of the parent window of the view, and the key bindings it defines are handled, in addition to the key bindings common to all Chamo windows.
Chamo has no way to guess the view you want to use to edit a file. You have to
give some indications. This is done in the file
~/.chamo/chamo.views, in option
by giving pairs (regular expression, view name).
The regular expressions are tried in the given
order to match the name of the file to open.
When a regular expression matches, Chamo uses the view with the associated name
to open the file. A default view is used when none of the regular expressions
match the file name. The default view name can be set with option
The default value of
This file is read at launch time, so you must restart Chamo if you modified it, or evaluate the following OCaml code to reload the values of options:
Values of options can also be set using OCaml code. Refer to the documentation of the Config_file library to manipulate the options. For example, to add a new association between a filename pattern and a view name, use the following OCaml code (here we add a pattern so that files with ".ocamldoc" extension are open with the "odoc" view):
let l = Ed_view_rc.filename_view_patterns#get in Ed_view_rc.filename_view_patterns#set (("\\.*ocamldoc$", "odoc") :: l) ;;
It is also possible to store the values of options, this way:
This view can be used to edit any text file. It is based on the
As in Emacs, this view separates the buffers from the views on the screen. So a buffer
can be displayed in various views, and some buffers can be present but not visible.
There cannot be two different buffers on the same file. Since Gtk2 buffers uses UTF-8
strings, the contents of the edited files must be converted to UTF-8 when used in
a buffer and converted back to the file encoding when the file is saved. The default
encoding used is the one associated to the "LOCALE" environment variable, then if
it fails, the
default_charset option of the user's
file is used. If it still fails, the user is prompted to choose an encoding among the ones
found on the system at configuration and compilation time.
Prompting the user to choose an encoding when the default ones fail is not yet implemented.
Common manipulations of text are allowed through commands and are bound to keys.
file for what commands are bound. Sourceview specific commands begin with "sourceview_".
Syntax highlighting in a buffer is made by the GtkSourceView library according to the
language associated to the buffer. Check the
language_mime_from_filename_patterns option of your file
~/.chamo/chamo.sourceview: these are the
associations between filename patterns and mime types. Then, the mime type is used
to retrieve the language specification defining syntax elements. Since Chamo uses
the styles of the elements of each language are shared with the other applications
using this module (for example
Styles of the "sourceview" views and syntax highlighting can be modified
using the "Preferences" box accessible from the
menu "File/Preferences". The syntax mode of the buffer in a view is displayed
between square brackets below the view, next to the buffer name and the line and column
Chamo sourceview buffers can also have an associated mode. A mode is composed of
a name, a description of the menus to display and the keyboard bindings to handle when
the view of the buffer has the input focus. Associations between filename patterns
and mode names are defined in option
mode_from_filename_patterns of the user's file
~/.chamo/chamo.sourceview. This means that commands
"specific to a mode" are available even on buffers with another mode associated; it is
just a matter of key bindings and menus which give direct access to commands.
Options of modes, like key bindings, are stored (by convention) in a configuration
file specific to the mode. For example, the configuration options of the "ocaml" mode
are stored in the user's file
This is done with some OCaml code. Modes are represented by objects of class type
Then, an instance of your mode class must be registered with
Ed_sourceview.register_mode. Then, add some association between a filename
pattern and your mode name and it's ok. Have a look at the code of another mode, e.g.
the ocaml mode
(implementation is here,
implementation of the management of the configuration file is
By now, there are not a lot of modes. Here is a list of the available modes, with the commands it provides through a key binding indicated between parenthesis:
Contributions (new modes or new commands) are very welcome !
Vis the name of a view. So, the bindings of "sourceview" views are defined in the file
~/.chamo/chamo.sourceview. The bindings associated to a kind of view are active only when the active view is of this kind.
Mis the name of the mode, such as "ocaml".
All these files are created with default values if they don't exist when Chamo is launched.
The final set of active key bindings is the union of global key bindings and the ones of the active view (with eventually the ones of the active mode).
The key identifiers usable in configuration files can be found
You should be able to find the corresponding string; for example "page up" will
be referenced with the identifier "Page_Up".
Most of predefined commands are already bound to a key combination, so you can already have a look at the various configuration files for command names. If you don't find what you're looking for, you can execute the following command in a bytecode version of chamo:
eval "Ed_commands.available_command_names ()"
This command will evaluate the given ocaml expression, which returns the list of names of registered commands. The list is displayed in the ocaml evaluation output window.
Sourceviews in Chamo are based on
which uses language-specs files to know what to highlight (keywords, comments, ...).
GtkSourceView 2.X comes with a language description file for Objective Caml, but
this one may not be as you like. For example, you may prefer to have different
styles for definition keywords and expression keywords, or have identifiers containing
integers displayed correctly (without a different style for the integer part...).
In this case, you can copy the files below in your directory
ocaml.langis an alternative description of ocaml syntax elements. This description is called "OCaml" and differs from the "Objective-Caml" style coming with the GtkSourceView 2.X installation,
scheme_chamo.xmlis a gtksourceview2 style scheme called "Chamo" specifically handling ocaml styles defined in
ocaml.lang; you can customize it to fit your preferences. To activate this style sheme, choose this scheme in the Files/Preferences menu.
By default, Chamo considers that files are encoded as specified in file
(the default value when this file is created is ISO8859-1). When a file is
open, Chamo converts the contents of the file from this encoding to UTF-8 to
display it correctly in Gtk windows. If you want to open a file which is
in a different encoding, you can use the command
which will let you specify the encoding of the file to open. You can also
change the default encoding used, by modifying the value in the file