ACME-like text-buffer/editor by Felix Winkelmann
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
utils Merge branch 'felix' May 13, 2018
.plumb Import of version 2018-02-27 Mar 2, 2018
B Import of version 2018-05-07 May 13, 2018
README Import of version 2018-05-07 May 13, 2018
awd Import of version 2018-02-27 Mar 2, 2018
build Import of version 2018-02-27 Mar 2, 2018
dotma.tcl Terminus font May 13, 2018
ma Merge branch 'felix' May 13, 2018
ma-eval Import of version 2018-05-07 May 13, 2018
plumb Import of version 2018-05-07 May 13, 2018
pty.c Import of version 2018-05-07 May 13, 2018
win Import of version 2018-02-27 Mar 2, 2018


88,dPYba,,adPYba,  ,adPPYYba,  
88P'   "88"    "8a ""     `Y8  
88      88      88 ,adPPPPP88  
88      88      88 88,    ,88  
88      88      88 `"8bbdP"Y8  

"ma" is a minimalistic clone of the acme[1] editor used in Plan 9,
and is written in Tcl/Tk. It has been tested with Tcl/Tk 8.5, mostly
under Linux. "ma" has successfully been run on Mac OS X with XQuartz,
but needs a tiling window manager to be used in a satisfactory way.

I used emacs[2] for years, but got bored with the ever growing number
of extensions and key-combinations that one accumulates when intensively
using that editor. I also got fed up with the fact that purely keyboard
driven interfaces involve frantic typing, something that appears to stress
me. Acme, which is heavily mouse-controlled, seems to produce a more
relaxed, single-handed use, especially for navigation and browsing. I'm
slower now (or at least this is my impression), but less hectic while
working (it seems).

Another advantage of acme is the dynamic nature of extending the
user-interface while one is using it - nearly everything is text, and
nearly every text can be mouse-sensitive.

Note that this editor is single-window based - it doesn't provide multiple
windows, nor does it manage them in any way (this is delegated to the
window manager.)




and put the files "ma", "awd", "win", "pty", "plumb" and "B" in your
PATH and ".plumb" into your $HOME.


"ma" attempts to work as much as possible like Acme, but does no
own window-management.  Configuration is done in the file "~/.ma",
holding Tcl code to modify fonts, colors, etc.  A number of command-line
options can be provided to set various of these options and to run "ma"
in special modes, or comunicate with the "registry", a "ma" instance
that allows locating files that are already open.

To start the registry, run

  ma -registry &

The registry is implemented using the Tk "send" command, so X-forwarding
must be disabled (enter "xhost" to see wether this is the case). "ma"
should still run, but features related to the registry will not be
available in this case (locating already open windows, and "Putall".)

The "B" program takes one ore more filenames (optionally followed by
an address) and opens the given files or activates already open windows
holding these files.

"pty" is a generic program running a subprocess in a pseudo terminal and
is used by "win" to have interactive windows inside a "ma" instance. Note
that this is currently very crude and does not support escape codes of
any kind.

"ma-eval" can be used to evaluate Tcl code in a running "ma" instance,
"awd" sets the label of the window in which the command is executed. You
can create an alias for "cd" to set the label automatically when used
inside an interactive shell window:

alias cd="_cd"

function _cd () {
    \cd "$@"
    if test -n "$MA"; then
        awd bash

When the registry is running, the window that has the current focus is
drawn with a white border around it. Executing commands in the body of
another window will then perform the execution in the context of the
focus window. Execution in the tag of a window always has that window
as context, regardless of focus.

When you create a new, unnamed window and want to save it, then just
edit the filename (initially "<unnamed>"). Also saving the file under a
different name can be done the same way.

The "plumb" program performs a very simple Plan-9 like "plumbing" based
on regular expressions, see ".plumb" for some examples on how to define
rules, which consists of Tcl code associated to regular expressions.
"plumb" takes a string as argument and runs the plumbing rules
in "~/.plumb" until a rule matches and succeeds. Text sweeped or
clicked with B3 will invoke "plumb" with the string as argument.

Environment variables:

    If set, all code that is executed in "win" mode or via B2 is logged in
    the file given in this variable (this includes all input, including

    Lists additional include-directories, separated by ":" (default:

    Shell to use for executing commands (default: "bash")

    Set to the name of the wish(1) instance when executing external

Access from the command line:

Using "ma-eval", some elements from a "ma" window can be
accessed by sending Tcl code to the process in which a shell command
was initiated:

For example,

    ma-eval $MA GetBody

would print the contents of the window body to stdout. Here is a selection 
of  some useful Tcl commands that you can use (for more intricate access,
study the "ma" source code):

    SetBody TEXT
    SetTag TEXT
    SetLabel TEXT
    ReplaceFile FILENAME
    Insert TEXT
    InsertFile FILENAME
    Append TEXT
    AppendFile FILENAME

Note that text may have to be suitable quoted to be passed trough
to the Tcl interpreter that is running in the window, like this:

    ma-eval $MA Insert "{this is a test}"


At the start of the "ma" script, you will find a number of global
variables that hold default values for fonts, colors and other
settings that are used throughtout the editor. Modify these at
your convenience.


The easiest way to add commands is simply to put scripts or programs
in your PATH. If you want more thorough integration, you can also
define commands at the Tcl level, by using "DefineCommand REGEX EXPR" 
to define Tcl code to be executed when the command given in REGEX is 
executed, i.e.

    DefineCommand {^MyCommand\s+(.+)$} { ... }

Arguments (subpatterns in the regex) can be extracted with "GetArg".

"ma" is not finished, and probably never will. For more information,
consult the source code or contact me[3].

To do:

- (bug) crash of program in win-mode doesn't print any message
- (bug) KeyRelease-event in .tag (getting through after invoking dmenu(1) 
  in this case) results in incorrect resize of tag, even though only 
  first line contains text
- (bug) Automatic resizing of the tag doesn't always work
- (bug) sort order in columnar listing is wrong (should be rowwise, not 
- (bug) Mac/X11: wrong arrow cursor (points right)
- (bug) Tk seems to clear the clipboard when exiting, so the contents 
  copied from a terminated instance are not recovered
- (bug) the (pseudo-)selection is sometimes retained even after input
- (bug) "Look" doesn't keep selection after a few repeated searches
- (bug) "Back" should not put position on search-stack if search wraps


- the file-registry needs to be explicitly started
- the "Kill" command (Del key) is too coarse and kills all subprocesses
- width use for computing columnar layout seems not to be correct 
  (always 80?)
- autosnarf when selecting: no idea how to do this, keeping current 
  selection and copying when selection gets empty doesn't work, since 
  selection by mouse apparently clears it in between movements
  - perhaps detect when selection changes from non-empty to empty
- there is no "Zerox" command
- works very bad on Mac/Aqua and Windows:
  - Mac: default Tcl/Tk crashes, freshly installed (Aqua) aborts 
    unexpectedly, B2/B3 are swapped, slow startup (Mac/X11 works 
    surprisingly well, though)
  - Windows: cursor in text widget barely visible (black, even on dark 
    background), startup very slow, binding Ctrl-keys doesn't seem to 
    work, UpdateTag doesn't seem to treat filename as valid and inserts 
    Win-style path before it (this is with Active State Tcl/Tk, 8.6.4)
- B1B2/B1B3 doesn't work when B1 was double-clicked
- there is no backup-file
- B2 in .sbar should respect current offset from mouse-pointer to top
  of bar (currently scrolls so that top of bar is reference-point)
- The move-box of a window is faked with a special unicode char
- Address syntax only supports a subset of acme/sam and is rather crude 
  (see also comment in ParseAddr), "/.../"/"?...?" addresses only select 
  a position, not ranges
- In "win" mode, MA tries to remove the prompt from input lines, but 
  moving the insertion point may confuse this, if possible use a prompt 
  for interactively used programs that will be ignored (e.g. ":;" for sh)
- Password-entry in "win" mode works only when the insertion cursor is 
  not moved by mouse or cursor-movement keys
- "Putall" is implemented, but will save all files in all open windows, 
  even on virtual screens not currently visible
- there is no "Edit" command

Differences to acme(1):

- Tab does not insert "\t" but whitespace
- (obviously) single-window mode
- no dynamic update of undo/redo commands tag (except filename)
- auto-chmod when saving file beginning with "#!/"
- missing commands: "Zerox", "Edit", "Incl"
- supports Up/Down movement by line
- inserting with active selection doesn't snarf
- indentation-setting is window-local
- executing with redirection in "win" mode invokes shell, and does not 
  send the command to the process running in the window
- executing in tag always has current window as context, executing in body 
  has currently focussed window as context (if registry is running)
- double-clicking opening bracket selects forward, but quote-scanning
  works backwards (in acme both bracket and quotes only select backwards)
- indent-mode works differently
- word under cursor is defined as ws-delimited (excluding parentheses)
- win-mode: pressing RETURN before current insert point sends the whole 
- "noscroll" mode is much weaker and only available in "+Errors" + "win" 
- basic keyboard commands for mouse-less operation: 
  C-1 (toggle focus), C-2 (execute selection), C-3 (acquire selection)
- B3-search is case-insensitive, search with "Look" is not
- "//.../" address disables most regex syntax (used for ctags)
- Various emacsish keyboad sequences, as provided by the Tk text widget
- Additional commands: 
    Anchor: add address of insertion point into tag
    Withdraw: hide window
    Tcl CODE: execute Tcl code
    Crnl: toggle between UNIX/DOS line-terminator encoding
    Back: jump back to previous address after search
    Interrupt: send ^C to interactive subprocess
- MA supports paren-matching
- Shift-B3 is equivalent to B2
- Acquiring an existing window doesn't warp mouse to current selection
- The "Local" command toggles a state whether directories are opened
  in the current window or a new one

All of MA's source code is hereby placed in the public domain


    Thanks to:

        Lucas Sköldqvist for various tips and suggestions.
        Kooda for fixing the completely broken implementation of pty.c

Version history:


    - B2 in win mode is equivalent to "Send" command.
    - Reduced some unnecessary "Flash"ing.
    - Executing with redirection keeps the result selected.
    - Getting the effective selection worked only when target widget had focus,
      resulting in selection/pseudoselection confusion.
    - In "win" mode the "Interrupt" command inserts ^C into the input stream.
    - Directory view should now format columns correctly after window has been
      shown for the first time.
    - Fixed a problem with plumbing a string beginning with Tcl redirection
    - If the result-string of a remote call via "ma-eval" is empty, no 
      output is produced.
    - The registry resolved symlinks before locating a file.
    - Executing with "|" or "<" tries to keep visible area.


    - Added "Local" command (suggested by C-Keen).
    - Attempt to optimize <<Selection>> event handler which seems to be slow
      on ssome machines.
    - B2 can now be used to abort B3-sweeping.
    - When "scroll" mode is off, try to keep start of output received by every external
       command at top of screen.
    - Pressing <Delete> sends SIGINT instead of SIGKILL now.
    - The "pty" programm catches SIGINT and propagates it to the process group.
    - Location of existing windows via registry handles spaces in directory names
    - Filenames with single quote in label are correctly quoted using double quotes.
    - Execution with redirection always uses body selection or whole body.
    - Dropped the "Replace" command (use an external tools like sed(1) or "LR"
      from ma-utils).
    - Re-activation of directory window refreshes contents.


    - C-k on end of line just deletes the newline and doesn't overwrite the cut buffer.
    - On-demand update of tag for "Put", "Back".
    - added read and write hooks.
    - "Look" doesn't warp mouse pointer.
    - All MA windows that are not directory listings or output windows track "dirty" state.
    - "Put <name>" always saves, regardless of the type of window.
    - Dotfiles command for directories.
    - Added several hooks for integrating the directory editor (diredit.tcl).
    - New files have a default name ("<unnamed>").
    - Removed tag marker, "dirty" state is indicated by tag font style (italic).
    - Double-B1 on empty line does not highlight line.
    - Extracted plumbing into separate tool ("plumb").
    - If the label is changed and the file does not exist yet, save text even if unmodified.
    - Removed "Wrap" and default to char-wrapping.
    - Renaming and saving output window properly reregisters the window.


    - When the label is updated, set the windows' title accordingly (suggested by Lucas Sköldqvist.)
    - added termination_hook.
    - Always enable word-wrap in win mode.
    - Computing the word under the cursor ignores the label marker character.
    - Added "Back" command to move insertion mark back to old position after search.
    - Replaced pty.c with a version that doesn't eat CPU time and is much simpler (thanks to


    - Corrected initial tag relayout.
    - Resizing scrolls to bottom if "scroll" mode is on.
    - Dropped "-noscroll" option, added "-scroll".
    - Filename completion adds final "/" for directory only if it doesn't need quoting.
    - Added "name_hook", moved "project" files into extension.
    - Replaces some message-boxes with marked text in +Errors window.
    - Revertion shows message when file is modified, similar to "Del".
    - "Wrap" command is shown in tag by default.    
    - "Get FNAME" checks whether the current file is modified.


    - "New" starts new instance in current context.
    - "Send" just appends at end (as in acme).
    - Added "Putall".
    - final delimiter in "/.../" + "?...?" addresses is optional now.
    - switching to existing window via B3 warps mouse pointer to current selection
      or insertion point.
    - got rid of spurious newlines in tag that where sometimes added.
    - directory listing quotes with "\"", when filename includes "\''".
    - text in tag window wraps correctly when the window is resized.
    - ESC selects up to insertion point at last mouse click, not the clicked location.
    - the "dirty" marker is filtered out in most cases of clicking the label.
    - (mostly) correct handling of backspace when entering passwords in win-mode.
    - B1B2B3 leaves file unmodified.
    - C-k snarfs deleted text.
    - B1-doubleclick in the empty space after a text line selects the complete line.


    - added some improvements in built-in plumbing rules.
    - the registry logs its actions inside its own text body.
    - the scroll-area is grayed in "scroll" mode.
    - failure to open file outputs error in "+Errors" window.
    - auto-detection of line-end translation, CRNL line-temrinators are preserved.
    - fixed problems in some uses of "catch" which didn't properly evaluate their arguments.
    - directory listings quote filenames, when necessary.
    - running subprocesses are now not killed on termination.
    - added MA_LABEL environment variable for subprocesses.
    - a clicked word does not include parentheses or brackets/braces now.
    - the history file is now made user-accessible only when written.
    - added (crude) support for password entry in win-mode.
    - added "-fontstyle" option.


    - initial release.