Table of Contents


mex is a modal editor, just like vi, elvis or vim. mex is different from other vi clones in the way I design it: I don’t aim for 100% vi compatibility because vi is a general purpose text editor and it binds some valuable keys to commands that are not of much use in editing source code.

mex uses lua for configuration. ->TODO<- In a future release, there will be a larger interface between mex and lua.

Terms of Use and Distribution

mex is distributed under the GPL.

About this document

This document is a manual, a reference guide, a TODO list and a list of open issues all in one. Designing a good user interface, especially for a tool that is used so frequently, depends heavily on using it and seeing how it works. Since usage and design are so closely related, I inserted arguments, descriptions of unimplemented features/commands when it seemed to fit. Also, there are some open issues in the design. These issues are open because either I don’t see the point in implementing a commonly implemented but rarely used feature or I don’t have enough information on user behaviour to make a decision about which way to go. These issues are marked as

All comments are welcome. The best place to post them is the developer forum in the sourceforge page. You may also contact me by email. the address is : cinarus at yahoo dot com

Since mex implements many commands in common with *vi* editors, I am not going to go into the details of the common commands and I will assume that you have some experience with such editors.

Anatomy of a Window

On the left side are the line numbers. mex does not display any indicator which tells that a line is wrapped other than identical line numbers on successive rows on display. There is no way to turn line numbers off :).

The darker area at the bottom is the command/status area. The status area contains the file name, the current mode being used for the buffer, a modified indicator (’*’), the number of the window, preceded with a w so that you don’t confuse it with the number of the buffer, which immediately follows.

The rest of the window is the text area, where the contents of the buffer is displayed. The yellow thing is the cursor as you may have guessed and the pink rectangles are insertion marks.

The Error Buffer

One of the internal buffers in mex is the error buffer. It’s number is zero. So, the command :e #0 would give you the buffer displaying all messages since mex has started. This can be useful when a command fails and you don’t know the reason, especially during I/O.

Movement Commands

Relative Movement

mex currently has only a small set of relative movement commands implemented, with the following modifications to the standard vi behaviour:
moveup     Binding: Up k
movedown     Binding: Down j
The cursor does not move to the same column as it currently is. ->TODO<- This should be fixed someday.
moveright     Binding: Right l
The cursor WILL move on the newline character. The newline character is rendered like any other character and it has a position in the window, so I think it’s only logical that the cursor should be able to move on it.
moveleft     Binding: Left h
No modifications on this one. Included for completeness.
movebegin     Binding: Home ^
When executed when the cursor is not on the first non-whitespace character on the line, it moves to that character. The cursor moves to the very first character in the same line if that fails or if it is already there. movebegin ignores a count.
moveend     Binding: End $
moveend will move to the last character in the line: the newline character. This will too ignore a count. This command is an object returning command. It will move to the character before the newline when given as an argument to an operator command.
movewordf     Binding: w
Moves the cursor to the beginning of the ’count’th word after the cursor. count defaults to 1. This command is an object returning command. It will move to the last character of ’count-1’th word after the cursor when the command is an argument to an operator command.
movewordb     Binding: W
Moves the cursor to the beginning of the ’count’th word before the cursor. count defaults to 1.
Note that the underscore is considered a punctuation character. ??

Absolute Movement: Marks, Global Marks and Bookmarks


vi has objects which remember positions in a buffer. These are called ’mark’s. mex provides a similar functionality, with extensions. In vi, all marks are local, meaning that, every buffer has its own set of marks which remember only positions in that buffer. mex uses global marks in addition to local marks; you can reach a global mark from any buffer, independent of the buffer you are currently editing.

There are three classes of marks in mex:

First and most used of them is the user defined marks. These are named from a to z (lowercase letters) and are global. You can set the position for a global mark using

setmark     Binding: m [a-z]
Sets the global mark named by the argument to the current position in the current buffer.
and then goto that position using
gotomark     Binding: ’ [a-z]
Go to the point remembered by the user defined mark, switching buffers if necessary.

The second class of marks are editing marks. These marks are editor-local meaning that, it is defined seperately for each (window,buffer) pair. i.e. if you edit a file in two windows, these windows have seperate editing-marks. Editing-marks are implicitly set to the position which you last (successfully / unsuccessfully) executed an editing command at.

goto_editing_mark     Binding:’’
Go to the last point the user edited in this buffer.

The third class of marks are bookmarks. These are not really marks, but are named so because they are used with the gotomark command. A bookmark is a position in a file which holds the string ’##X’ where X ranges from A to Z. The gotomark command searches for such a string when given an uppercase argument. The binding is what you would expect:

goto_bookmark     Binding:’ [A-Z]
Go to bookmark given by the argument letter.
This feature makes it very easy to mark places in a big file permanently and even form an easily browsable table of contents for big source files. Needless to say, bookmarks are local.

Another absolute movement command is the cursor-of-window command.

cursorofwindow     Binding: #
This command takes a count argument and will move the cursor to the position of the cursor in window ’count’. However, this command has no effect when not part of an operator command such as delete or change because it does not make sense to use it without another operation applied to it, since a Ctrl-tab or :focus will switch to a given window.
This command is implemented as an alternative to the visual selection mode found in many editors.

Of course the gotoline command is implemented:

gotoline     Binding: g
Go to the beginning of ’count’th line.
Note the difference to vi in the binding for this command.


mex provides the usual vi commands for searching strings: ’/’ , ’?’, ’N’ and ’n’. And also the character search commands: ’f’ ’F’ ’t’ ’T’.

The ’/’ and the ’?’ commands search for strings. If you would like to search for regular expression matches, use Ctrl-/ and Ctrl-? instead. The regular expression syntax is explained in the substitute command definition.


Moving in Source Code

The following commands are designed for moving in source.
blockbegin     Binding:{
Moves the cursor to the ’{’ character that encloses the cursor. If the cursor is on a ’}’ character, the matching ’{’ character is moved to instead. This command is an object returning command. It will move to one character past the enclosing ’{’ character when the cursor is not on a ’}’ character and the command is an argument to an operator command.
blockend     Binding:}
Moves the cursor to the ’}’ character that encloses the cursor. If the cursor is on a ’{’ character, the matching ’}’ character is moved to instead. This command is an object returning command. It will move to one character before the enclosing ’}’ character when the cursor is not on a ’{’ character and the command is an argument to an operator command.
matchparen     Binding:%
Moves the cursor to the matching parenthesis character if the character under the cursor is one of ’{[(<>)]}’.


Since version 3, mex has built-in tag searching. It supports multiple
tag files chosen on a per-buffer basis. Each buffer has a list of tagfiles given by the function tagfiles(filename). This function is called once during the life-time of a buffer. It should return the list of tag files associated with the given file. Example:
	function tagfiles(filename)
		if filename == "Makefile" then
			return { "mtags" , "tags" }
		return { "tags" }
The order of the returned tagfiles is significant. They are searched in the given order. If you give a relative path for a tagfile, it is relative to the file’s path.

When you request a tag for the first time, mex finds the tag using the current buffer’s tagfile list. When you request the next definition of a tag when the cursor is on the current definition of a tag, the original list of tagfiles will be used, not the tagfile list of the current buffer. This makes it easy to find a definition if it is defined multiple times in a tag file.

mex behaves a little differently when browsing thru tags. Each window has its own tag stack. This stack holds positions that correspond to different tags. In addition to this, each tag may be defined in multiple places. These places replace each other on the tagstack. We can visualise this as follows:

                 <----Prev Definition---------Next Definition---> 
   |                The Stack                      Alternative Definitions
   |            |                      | 
 New Tag        | error (in get.c)     |  [error() in buffer.c] [error() in file.c]
 /Push Tag      |                      |
   |            | main                 |
 Pop Tag        |                      |
   |            | readfile (in file.c) |  [readfile() in buffer.c]
   |            |                      |

The following commands may be used for browsing tags.
nexttag     Binding: Ctrl-Return
This command finds the definition of the word under the cursor. If this tag was the most recent tag searched in the current window, then it finds the next definition of the word.
prevtag     Binding: Shift-Return
Finds the previous definition of the word under the cursor. If the cursor is not on the searched word, then it goes to the current tag position.
poptag     Binding: Ctrl-\
Decrements the top-of-stack pointer by one and jumps to the tag at that position. Note that the stack is arranged to wrap around its ends.
pushtag     Binding: \
Increments the top-of-stack pointer by one and jumps to the tag at that position.
There is no good substitute for experimenting :)

Screen Based Movement and Scrolling

mex has the following commands to move on the screen and to scroll the window.
scrollup     Binding: PageUp Ctrl-b
scrolldown     Binding: PageDown Ctrl-f
These commands scroll the window by one less the height of the window in lines.
movescrhome     Binding: H
Moves the cursor to home position: left top corner. When given a count, it moves the cursor to the beginning of Nth physical line on the screen.
movescrend     Binding: L
Moves the cursor to end position: left bottom corner. When given a count, it moves the cursor to the beginning of Nth physical line on the screen from the bottom.
movescrmid     Binding: M
Moves the cursor to the beginning of the physical line in the middle of the screen. This command ignores counts.
Screen based movement and scrolling commands are not considered to be movement commands for the purposes of operator commands.

Editing Commands

Inserting Text

In addition to the usual ’iaIAOo’ commands, mex provides another insertion command for inserting text in an alternate language. This comes in pretty handy when writing a program that needs to give messages in a language other than English.
exc_altinsert     :altinsert (or :alt) lang Puts the current window to alternate insert mode with the mapping given by lang. Currently, only turkish (lang=tr) is supported as an alternate language, but it’s pretty easy to add others.

The alternate mode works as follows: The user maps some of the keys (in lang.c) to special characters he wants to use in the alternate mode. Then mex translates keys when the buffer is in alt-insert mode. This has been a great help for me because I mostly program in C and the keys for ’{’ ’[’ and such are in very odd places on a Turkish keyboard. So, I switched keyboard map to US English and started using the alternate mode whenever I need to insert Turkish messages.

When you insert text mex displays insertion marks to indicate what text has been inserted since the last insertion command. If you see only one of them, you may have moved one outside the window, started insertion at the first char of the buffer or you may have deleted all text that was between them. In the last case, there is no way to seperate them back. You may insert text, move to outside the insertion range, do some editing there and come back. These actions will not affect the repeat behaviour of the insert commands.

There are also two named cutbuffers i and I, which holds the the last inserted text. So you can repeat an insertion by pasting from these two cutbuffers if you have executed other repeatable commands in between.

Deleting and Changing Text

mex provides the two character delete commands of vi:
del_char_prev     Binding:X
del_char_next     Binding:x
These commands delete ’count’ chars preceding or succeeding the insertion point (left edge of cursor).

The delete command in mex is an operator command. There are two forms:

delete_lines     Binding: d
Deletes whole lines when you give it two positions in the buffer that are on different lines. Deletes chars otherwise.
delete     Binding: Ctrl-d
Deletes the characters between the given positions independent of whether they are on the same line.
The change command too has two such variations:
change_lines     Binding:c
change_text     Binding: Ctrl-c

Note on Operator Commands

Since these commands take a movement argument, they are called ’operator commands’. Other operator commands are shift_left, shift_right,yank, quote and comment. Some movement commands will move the cursor to a different position than the normal operation when given as an argument to operator commands. These commands are marked as ’This command is an object returning command’.

Cut Buffers

When you cut or copy text using delete, change or yank, it is saved to a cutbuffer along with it’s type . The type of copied or cut text determines whether the text should be pasted as whole lines or as a sequence of characters. If you cut text using a line-oriented command such as delete_lines, the text is pasted as whole lines if it contains newline characters. Otherwise it is pasted as a sequence of characters. When you paste whole lines, the text is inserted before/after the beginning/end of the current line. Otherwise, the text is inserted before/after the cursor.

Yanking and Pasting

The yank command has two variations like the change and delete commands:
yank_lines     Binding:y
Yank whole lines when the given range spans multiple lines.
yank_text     Binding: Ctrl-y
Yank characters even when the given range spans multiple lines.
The key ’Y’ is an alias for ’y<End>’ in consistence with C and D. vi defines it to be an alias for ’yy’ which has disappointed me every time I used it.

When yanking or deleting some text, you may choose to save it in a cutbuffer other than the default. This is done by

cutbuffersel     Binding: " [a-zA-Z]
This command chooses which cutbuffer to yank into or paste from. A lowercase letter and it’s uppercase counterpart refer to the same cutbuffer. Using a lowercase letter will erase the contents of the cutbuffer before yanking into it. Using an uppercase letter will not.
After you’re done yanking, you can use the same command to reach the yanked content during pasting. Three of these named cutbuffers are handled specially: Note that there is no support for generally implemented ’killbuffers’, These are cutbuffers that are named from 0 to 9 and cut into every time a delete operation occurs.

Replacing Text

The :substitute command (which may be uniquely abbreviated as :s) provides substituion functions. The regular expression syntax accepts the usual ’?’ ’*’ ’+’ ’|’ operators and the grouping characters ’(’ and ’)’. To record what text matches a given part of the regular expression, you shall enclose the regular expression part between ’\<’ and ’\>’ pairs. In the ’replacement’ part of the command string, the strings \1, \2 .. \9 expand to the string which matched the contents of the corresponding \< \> pair. \0 gives the string which matched the whole r.e. mex currently does not recognize any named character classes. So, [:digit:] and similar will not work. ->TODO<- This limitation will be removed in the future.

You may give the following options to the :substitute command.

Replace all occurences in a line, instead of only the first one.
Ask for confirmation for each substitution. When a match is found, a prompt is displayed for the action to take. ’y’ will do the substitution, ’n’ will skip the current match, ’c’ will cancel the command and ’a’ will assume ’y’ for the current and all following matches.
The command will not differentiate between uppercase and lowercase letters if this option is given.
This option unsets magic. All characters in the ’search’ part of the command are taken literally and the search becomes a string search. The strings \1 \2 .. \9 will expand to the null string and \0 will expand to the matched string in the ’replacement’ part of the command.
Please note that mex lacks the commonly implemented options magic and ignorecase.

Undoing and Redoing

mex has an unlimited undo-redo capability (limited by memory that is). The commands to undo and redo changes are:
undo     Binding:u
multi_undo     Binding: BackSpace
These commands will undo the last operation. The difference between them is their granularity. ’undo’ will undo one simple operation. A simple operation is an insertion done at once (by inserting a character is insert mode or by pasting characters in command mode) or a deletion done at once (i.e. backspace in insert mode or something like 3dd in command mode). A ’multi-undo’ will undo a whole command. For example, when you multi-undo a change command, mex will both delete the newly inserted text and restore the original text where undo will only delete the last character of the inserted text.
redo     Binding: U
multi_redo     Binding: Ctrl-BackSpace
These commands are counterparts to undo and multi-undo. Note that the commands that were used to generate the undone content are not re-executed to restore them. Only the changes to the buffer are recorded and replayed. So, a :read operation will not be repeated when you redo it, the recorded contents will be re-inserted.

Similar to the redo command, mex also provides

repeat     Binding:.
This command repeats the last editing command such as delete, insert etc.. Note that the command is re-executed. Therefore, it may have different effects depending on the position of the file (i.e. if it contains a search command).

Editing Source Code

The following commands are designed for editing source code:
comment     Binding:-
This operator command will enclose the characters in the given range with the strings ’/*’ and ’*/’. It will also re-encode comment delimiters in the range to enable correct reverse operation. Example:

is transformed into (using -- for example)


is transformed into

/*/1* hello*1/ */

is transformed into

/*/1* /2*  hello*2/  *1/ */

uncomment     Binding:+
This command will remove the comment delimiters from the next comment it finds, starting search at the cursor position. It will also restore comment delimiters within the uncommented text, doing the reverse of the comment command.
delcomment     Binding:Ctrl--
This command deletes the next comment it finds. It’s useful in conjunction with the comment command. Using this pair, you can comment out some code, then remove it if the commented version works.
quote     Binding:q
This operator command will encode the given range using C’s string literal encoding and then enclose the encoded range with double-quote characters. Like the autocomment command, this command has no lines version; it always operates on characters.
unquote     Binding:Q
This command unquotes the next string literal it finds after the cursor. quote and unquote commands are particularly useful for writing string literals that contain code or regular expressions.
togglecase     Binding:~
This command toggles the case of the character under the cursor. When given a count it will toggle the case of next count characters. Case is toggled according to toupper() rules.
togglecase_oper     Binding:`
This command is the operator version of the togglecase command.

Automatic Indentation

An automatic indenter is implemented in mex. It is activated by the option
autoindent. Automatic indentation does something different than the normal insert mode only when you insert newline characters. It will not break lines for you, align comments or anything. The following commands may be used for manual indentation:
shift_left     Binding:<
shift_right     Binding:>
These commands are operator commands. They will insert or remove a level of indentation from the beginning of the given lines. A level of indentation is a tab character or the equivalent number of space characters.
The option tabstop tells mex how many columns a tab character should occupy.

Other Editing Commands

The following command was fun to write, and is fun to use.
enlarge     Binding: Ctrl-q
This is an operator command which rewrites the lines in the range using an ascii-art font. Currently only uppercase letters and some punctuation is included in the font. Example:
	is transformed into
  /*\|/            _   _   ._  _       _ ._  _   *\|/   /
 /  -+-   |\/| /\ | _|/    |_)|_   |_||_ |_)|_    -+-  / 
/   /|\*  |  |/`’\|_||\_   |_)|_   | ||_ | \|_    /|\*/  
Make sure to seperate comment delimiters from the comment by at least one space character if you use this command on comments.

Maps: Make Your Own Commands

mex enables you to bind one or more commands to a key and have them execute when you press the key in command mode. You can do this in two ways; one of them in configuration and one at "run-time".

The function map(key, meaning) allows you to specify key mappings in your configuration file. key should be a single key specifier whereas meaning can be multiple keys long.

For printable ASCII characters, the character means the key combination needed to print it i.e. 'a' means the key 'a', '{' means shift-'[' (on a us keyb). Other keys such as function keys and space characters can be specified as follows:
\C    Control; This key can be prepended to another to form one key since it’s a modifier.
\H    Home
\E    End
\P    Page Up
\N    Page Down
\U    Up
\D    Down
\L    Left
\R    Right
\n    Return
\b    Backspace
\t    Tab
\S    Space
\1    F1
\2    F2
\3    F3
\4    F4
\5    F5
\6    F6
\7    F7
\8    F8
\9    F9
\a    F10
\b    F11
\c    F12
\x    x

As an example, the options in source distribution contains the following:

	map("C", "c\\E")
	map("d", "d\\E")
	map("\\C\\t", ":focus\\n")
Note the control-tab command implemented as a mapping. Another point to be careful is, the escaped key codes are written with two backslash characters. This is because of the lua parser: lua does one level of \-decoding before passing the key definitions to map functions.

If you want to record some operations and then re-execute them, you can use the following commands:

exc_startmap     :startmap (or :sm) [key] Starts recording the succeeding keys and associates them with the given key.
exc_endmap     :endmap (or :em) [key] Stops recording keys. If a key was not given in :startmap, it must be given in this command. Otherwise the recording will continue.
After you’re done recording a map, you can execute the recorded keys by pressing the mapped key. A count also works here: the recorded keys will be replayed count times if you give one.

Working with Buffers

One of the motivations behind mex is to make editing multiple files as easy as possible. A buffer in mex is the representation of a file. They are identified by numbers in the form ’#<buffernumber>’. This number is displayed at the bottom right corner of a window displaying the buffer. User buffers start from #2 since #0 is used for the error buffer and #1 is used for the scratch buffer. See
buffer selection dialog for information on how to get a list of buffers.

When you switch from one buffer to another, the old one is kept in memory. It gets destroyed only when you explicitly unload it or try to quit from mex. Buffers with unsaved modifications will display a confirmation dialog when they are about to be destroyed.

Following commands are related to buffers and files:

exc_edit     :edit ( or :e ) buffer-spec Edits the given buffer in the current window. Or, edits the given file in the current window.
exc_unload     :unload ( or :ul ) [buffer-spec] Unloads the given buffer. If no buffer is specified, the current buffer is unloaded. This command fails for internal buffers.
exc_revert     :revert This command reverts the contents of the current buffer to the contents stored on disk. This command will fail for an unnamed or internal buffer since such buffers have no associated file on disk.
exc_write     :[range]write (or :[range]w) [filename] This command writes the current buffer to the given file. The filename is mandatory only when the buffer is unnamed or a range is given. When a range is given only the lines within the range are written.

See the section on backups on how to control the backup behaviour.

exc_read     :read This command inserts the contents of the given file at the cursor position.

Writing Files and Backups

mex backs up your files in order to protect them from mex’s faults and other errors that can occur during writing a file. The write algorithm is as follows:
  1. Rename the file to it’s backup name if it exists.
  2. Write the contents to a file named with a ’.tmp’ suffix.
  3. Rename the new file to the name of the file.
In order to achieve this, you must have write access to directories in which you edit a file. The ’.tmp’ suffix is there to ensure that the file named with the buffer’s name always contains all contents in the buffer. So, if there was an error during a write operation to file X, the resulting file will not be named X. Therefore when you retry to write after fixing the problem, the erronous file will not be backed up. This also ensures that backups are always proper.

When you try to write a buffer to an existing file that is named differently, mex displays a confirmation dialog about overwriting the file. The same applies if a file associated with a buffer was touched outside mex.

mex provides a way to control backups thru the option backupname.

Mounting Virtual File Systems

In addition to using the local disk, mex supports file operations on a remote host. You need to run a server process on the remote host in order to use files from that host. Then, you tell mex where the remote directory should be mounted locally. After this, accessing files on the remote host is identical to accessing files on the local disk.

The procedure to follow is:

After these steps, you can use the remote host’s disk in the same way you use the local disk (i.e. look at directory, read & write files etc).

New Line Schemes: Editing DOS or MAC Text Files

As you may know Windows,MacOS and UNIX use different character sequences to seperate lines. mex provides ways to specify which scheme to use when writing a file. There are two options that control the behaviour:
In addition to these options, you can use this command to explicitly set the scheme for the current buffer:
exc_newline     :newline (or :nl) dos|unix|mac|default Sets the newline scheme to the given value. If one of the first three is used, the options scheme or fallback_scheme are not taken into account and the given scheme is used. Otherwise the normal behaviour is restored and the options control the new-line scheme.

If you don’t give a scheme as an argument, this command will display the current scheme for the buffer.

Working with Windows

mex can display multiple buffers at the same time in different windows (or the same buffer in different windows). A window is displayed as a horizontal pane in the application window.

A window is identified by it’s number. This number is displayed in the form ’w<number>’ at the right side of it’s command area. When you want to mention a window, you just use the number without the ’w’. Following commands are used for working with multiple windows:

exc_window     :window ( or :wi ) [bufferspec] Creates a new window at the bottom of the application window with the buffer specified in it. Then sets focus to that window. If no buffer or file name is specified, the current buffer is used instead, with the cursor at the first character of the buffer.
exc_closewin     :closewindow ( or :cl ) [windownumber] Closes the given window. When no window number is given, it closes the current window. When a window is closed, all buffers that were edited only in that window are also unloaded. If any of these buffers have unsaved modifications, the destroy-buffer dialog is displayed. If the closed window is the only window, then mex exits.
exc_focus     :focus ( or :f ) [window] Sets focus to the given window. window argument defaults to the next window.
exc_ctrltab     Ctrl-Tab Sets focus to the next window. Wraps to the first (top) window if executed on the last (bottom) window.

Embedding Another Window

mex has a command-line option, -r , which tells it to reparent the window whose X identifier is given in WINDOWID environment variable. You don’t need to set this variable explicitly if you are executing mex from an rxvt window and would like mex to reparent the same window, since rxvt sets it automatically.

This command is not available if mex is compiled & linked with xwox instead of the regular Xlib.

When a window is reparented, it’s removed from the control of the window manager and is managed by mex from there on. Some window managers (one of them is Enlightenment) experience problems with this, so quitting mex and executing it again may be necessary if mex has not reparented the window properly at the first attempt. Good old twm has no problems with this, by the way.

Note that, mex does not do very much on the window other than moving it in the application window when the application window re-layouts itself. So, you shouldn’t quit from the reparented application without quitting from mex first.

When in command mode, the command ctrl-w will switch the focus to the reparented window and warp the mouse pointer to (20,20) in that window. The distribution also includes a small program called mx which switches the focus to the parent of the window whose X identifier is in WINDOWID environment variable. mx too warps the pointer, to the mex application window at (20,20). To sum up, you may switch focus to an embedded terminal emulator using ctrl-w and then switch back to mex by running mx. To make things even more homogeneous, you can add the line

bind ’Control-w:"mx\n"’
to your .bashrc and you have an IDE.

If you use ion wm you don’t need this at all.


File Selection

When you press <Tab> while entering a command in the command area, the file selection dialog is displayed if the first character of the non-whitespace sequence that ends at the cursor is not ’#’. If that character is a ’~’, then it is expanded to the value of the HOME environment variable.

Here are the keys and what they do in this dialog:

Completes the filename in the filename area as much as it can, just like bash’s filename completion.
Deletes the last element in the path string. i.e.
ctrl-backspace will turn it to

another one will

Clears the filename area. When the filename area is empty, the directory that will be searched on a Tab is the directory the current buffer resides in or the working directory of mex if the current buffer is not named.
Closes the dialog and returns the string in the filename area.
Cancels the dialog. When this dialog is cancelled, the string in the command area will remain unchanged.
Up / Down / Left / Right Arrows
Moves the highlight cursor to the file name displayed in the given direction. Although the dialog has no scroll bars, it will scroll up and down as the cursor moves.

Destroy Buffer

When a modified user buffer is about to be destroyed, the destroy-buffer dialog is displayed.

The "Save" button is not displayed if the buffer mentioned in the message box is an unnamed buffer. You can use the arrow keys or the uppercase letters to select an action (case is insignificant).

If you cancel this dialog, the command that displayed it will be cancelled. However, side effects may reside (i.e. closing unmodified buffers).

Buffer Selection

If you press <Tab> in the command area when the cursor is immediately after a ’#’ sign, the buffer selection menu will appear.

Modified buffers are marked with an ’*’ sign. You may type a number to select a buffer (to select buffers 0-9) or you may use the arrow keys to move the hilight cursor in this dialog. Cancelling this dialog leaves the contents of the command area unmodified.


mex uses a lua script for configuration. When it starts, it reads $HOME/.mexrc and merges the options in it with the default options.

There are two classes of options in mex; per-buffer options and global options. Per-buffer options are defined as lua functions in the following manner:

	function backupname(fn)
		return fn .. ".bak"
Here, backupname is the name of the option. When mex needs the value for this option, this function is called with the name of the file associated with the buffer and its return value is used as the option’s value.

Global options are defined for the same way for all buffers and are simple lua values. For example

	window_main.font= "fixed"
is a definition for the global option window_main.font. If you fail to provide a correct definition for a value, (i.e. set it to null or an incompatible value with the option type) mex will supply a default value.

All options have a type. This type is one of integer, string, list or boolean. Boolean options are just integer options, with zero corresponding to false. If you’d like to use hexadecimal values for integer options, you can use the hexval() function to convert a string to a number according to strtol() rules.

When writing string literals, beware that the lua parser does one level of \-decoding before passing the values to mex functions. Therefore, two backslashes are needed when you want to escape a character using &quo;\&quo;.

When a buffer gets created or changes its name (thru write), the options for the buffer are recalculated.

-->TODO<--- The following no longer applies since the port to lua. Commands related to options are:
:set Start editing the option buffer with empty contents in the current window.
:do Apply options in the option buffer. This command only works when the current buffer is the option buffer

tip: undo works in all buffers, including the option buffer. If you modify an option and don’t like it’s effects after you run :do , undo the changes and run :do again.

Below is a list of options.

tabstop     Type: int     Scope: per-buffer
Specifies to which positions the tab character will expand. Each tab position is a multiple of this value.
autoindent     Type: boolean     Scope: per-buffer
Turns autoindentation on and off.
backupname     Type: string     Scope: per-buffer
The function backupname(filename) is called every time a buffer needs to be written to disk. The argument is the name of the file to be written. This function should return the name of the backup file. If it returns a null string or anything other than a string (including nil), then no backups will be made for that file. If backing up is requested, a file is not written to disk unless its backup is successful.

mex tries hard to rename files to their backup names. If it can not rename a file, it will copy it. ->TODO<- since I rewrote the new FS interface, this no longer holds.

nl_scheme     Type: string     Scope: per-buffer
Valid values for this option are "unix", "mac", "dos", "default". The default is "default". The first three inform mex to use the respective scheme.

The last one tells mex to not modify the scheme of the buffer and use the scheme it found when it read the buffer. If the buffer was created within mex (not read from disk), the fallback_scheme option is used.

nl_fallback_scheme     Type: string     Scope: per-buffer
Valid values for this option are "unix", "mac", "dos", "default". The default is "unix". This option’s value controls what should be the scheme for new files if their scheme option is set to "default".

Appearance Options

These are options that change the look of mex. You may change border colors and widths, fonts, background and foreground colors of any window in mex. These options are all defined at the application scope.

One class of options set the resources for the ’text’ widget in mex. The line-number area(window_lineno), the main area(window_main) and the command area (window_cmd) are implemented as seperate text widgets. To set an option for a text widget, use the form

where window_main identifies the text widget and borderwidth identifies the option name. Here is a list of options for a text widget:

foreground   Type: int
Color used for displaying text.
background   Type: int
Background color of the window. See also ruler below.
ruler   Type: int
Color of the ruler lines. One line of every five lines is drawn with this background.
hilight   Type: int
Color of the cursor. This color is XOR’ed with the text and the background.
borderwidth   Type: int
Border width in pixels.
bordercolor   Type: int
Color of the window border.
font   Type: string
Font used to display text.
The following options are meaningful only for the given widgets. Note: any option that is not recognized is simply ignored instead of generating an error.
window_top.background   Type: int
This is the color of the rectangular area at the lower left corner of a window. This area is exposed since neither line number nor the status area owns it.
window_main.width   Type: int
window_main.height   Type: int
These define the initial size of the main text widget.
window_lineno.width   Type: int
window_cmd.height   Type: int
Self explanatory.

Installation, Usage,Reporting Bugs

Installing mex

I will always provide binaries that work on a i386 with a Mandrake-9.0 GNU/linux distribution. Other binary packages will be available in time, as users and other developers submit builds for other systems. Notes for each release will contain which package works on which systems. However, the binaries for Mandrake-9.0/i386 should work on most modern i386 distributions since no system calls that are linux-specific are used (i.e. ones that may be implemented in one kernel and not in another) and no assumption is made about the target system such as the usage of a particular library (other than libc and libX11 of course).

For basic operation, mex doesn’t require any installation procedure. You can just put it somewhere in $PATH and start using. Don’t forget to install the focus switching program mx if you plan to use the reparenting feature.

If you would like to use custom settings, you should put them in $HOME/.mexrc.

Command Line Arguments

The syntax for running mex from the command line is:

		mex [-r] [filename]
Currently there is only one command line option,
-r .

Compiling mex

Compilation is pretty straight-forward. You just edit the config file at the top of the source tree and then make. Note that mex doesn't use the autoconf tools.

@mex() can also be built to be run on a win32 machine. In order to do this, you&rqsuo;ll need a linux host with cross-compilation tools installed. I use mingw to make my windows builds. The same should work with mingw/cygwin on a windows build host, but I haven’t tried.

The build also produces

a macro processor based on lua.
a program to include binary data in a C program.
You may also install these at the installation directory using the proper variables in config if you're interested.

Reporting Bugs

If you find a bug in mex, which you will probably, you may send a bug report. A bug report may be sent to the author by email. The most useful bug report (the one that will most help me find and fix the bug) contains instructions on how to re-generate the bug. However, all bug reports are welcome even if short.

Optionally you may send a log of your editing session. If you are using the debug binary (which would help us very much), mex creates a directory under $HOME/.mex named with the process id. This directory contains the keylog for the session (all key events received from the X server) along with all files that were loaded into mex buffers during the session. These copies of files contain the contents of the files before mex referenced them for the first time. Content of a file is important in helping us locate bugs if you have executed searching commands (i.e. move-word-f or search-char) when editing the file. Which most probably you will, mex is not very different from, say, pico otherwise :). So, if you happen to work on GPL’ed code or otherwise publicly available code when the bug showed up, it would be very useful for us if you could send us everything under $HOME/.mex/<pidof@mex()thatfailed>/ along with your $HOME/.mexrc and defaults in the source tree if you have modified it.

Release Notes

Version: mex 3
Date: 5 Jun 2004

The win32 port is improved. mex doesn’t depend on the cygwin library any more.

The packaging has changed. Now, everything is in one big tarball.

No known bugs. They are yours to find.

Version: mex 2.0
Date: 2 May 2003

mex has been ported to win32. It can also run without an X server under a cygwin environment. See the Makefile and the package xwox for details. A lot of cleanup was done, along with some new commands.

Version: mex 1.0
Date: 5 March 2003

Support for changing options at runtime is implemented, but it is still being designed. Do not give mex an invalid option name, or it will crash. The crash may be prevented but properly handling the error requires that an error message is given indicating on what line the error occured and what the reason for the error was, which is not implemented yet. The preferred way to set options is to ’:read’ the defaults file or the .mexrc that comes with the distribution, modify the values and then apply the changes. Again, the crash is there so that I don’t forget about it. ??

An argument to :unload or :closewindow is not recognized. You must switch to the associated buffer/window before you can do it.

There is no way to turn off backing up files. There will be one when I’m pretty confident that mex does not contain serious bugs that will cause it to crash.

There is no modifiable/readonly flag in a buffer yet. That should be coming soon.

If you plan to use the debug binary, make sure that you have a writeable-executable $HOME/.mex/. mex will crash otherwise.

Helping in Development

mex is currently being developed by only one developer and being a free time project, I’m afraid the code doesn’t include many comments :). However, the code is written in a very modular structure and the code for commands are quite high level. If you plan to develop mex, I’d be more than happy to provide you with more technical details. Without anybody else to develop mex, there isn’t much motivation to explain the inner workings of it as you may guess.

Another and just as valuable way in helping mex’s development is to use it and give feedback on subjects like: how it ’feels’, whether it is easy to use, whether it’s set of features are satisfactory (probably not yet), what else would you like to have in it and why etc.

If you use mex and create good looking ’themes’ for it, I would be more than happy to include one of them in the distribution as the default theme. The defaults are made by me and I’m not very good at choosing colors usually. By the way, if you like mex so much that you want to create a logo for it, please feel free to.