Textadept Manual

Written by Mitchell Foral. (mitchell{att}caladbolg.net)

Introduction

Textadept is a fast, minimalist, and ridiculously extensible text editor for Linux, Mac OSX, and Windows. The C++ core will always be less than 2000 lines of code (excluding comments and blank lines) and contains the bare framework for a text editor. More than half of the C++ base is the Lua extension, and nearly everything in Textadept is controlled by Lua, making the editor's extensibility almost limitless.

Requirements

If you are interested in compiling Textadept, you will need the following:

Main Features

  • Uses scintilla-st, a fork of Scintilla that utilizes dynamic Lua lexers.
  • Unlimited split views, a dynamic side view for showing opened buffers, a file browser, etc., integrated find/replace view, and a Lua command entry.
  • A plethora of Lua scripts for easily manipulating text and source code.
  • Integrated Lua LPeg and LuaFileSystem libraries.

Installation

Linux

After downloading and unpacking Textadept to any directory, you have two options: move it to /usr/share/textadept (may require root privilages) or move it to a different directory. If you choose the latter, you will need to recompile Textadept after making some changes discussed below. Then create a symlink from the textadept/textadept binary to /usr/bin/ or somewhere in your PATH.

Mac OSX

After installing the GTK+ OSX framework, simply place textadept.app in your Applications directory like any other app.

Windows

Unpack Textadept into any directory and it's all set to go.

Compiling Textadept

First, unpack textadept_x.x.src.zip into any folder.

If you wish to change or add to the default key commands for non-Scintilla widgets that are built into the UI, search in src/textadept.c and src/lua_interface.c for *_keypress functions. For key codes, refer to GDK's gdkkeysyms.h (typically in /usr/include for Linux, the place where you installed the GTK+ for Windows include directory for Windows, and /Library/Frameworks/Gtk.framework/Headers/gdk for Mac OSX).

Linux

If your Textadept directory is not /usr/share/textadept, you must edit src/textadept.h's textadept_home variable to reflect the path to the folder. Remember that two \'s are necessary to make one \ character in a C++ literal string.

Compile scintilla-st by going to src/scintilla-st/gtk and running make. Then go back to src/ and run make to build Textadept. If you haven't already, create a symlink from the binary to /usr/bin/ or elsewhere in your PATH.

Note: make sure src/scintilla-st/gtk/makefile's INCLUDEDIRS contains the path to Textadept's Lua header files (src/lua/). Add them if necessary like so: -Ipath/to/lua/headers.

Mac OSX

First put CocoaDialog.app in your ~/Applications directory.

Open xcode/textadept.xcodeproj in XCode, change the active build configuration combo box from Debug to Release (if necessary), click Build, and copy the resulting xcode/build/Release/textadept.app to a folder of your choice.

Note: if CocoaDialog can't found, you need to change its location in the project by right-clicking CocoaDialog.app, selecting Get Info, and changing the path.

Windows

When installing GTK+ for Windows, you will have to manually tweak the include/ directory structure from the parts of GTK you downloaded until it looks like the following:

atk/
gdk/
gdk-pixbuf/
gio/
glib/
gobject/
gtk/
pango/
cairo*.h
gdkconfig.h
glib*.h
gmodule.h
iconv.h
libintl.h
png*.h
zconf.h
zlib.h

(Any files that have '*' in them represent multiple files with similar names.)

Open visualstudio/textadept.sln in Visual C++ Express 2008, change the Debug option in the toolbar combo box to Release, click the Build menu and select Build Textadept, and copy the resulting visualstudio/Release/textadept.exe to your Textadept folder root.

Note: my GTK install is in C:\Program Files\GTK\2.12.9\. This directory is referenced from the Visual Studio solution file. If you get include errors for GTK files, you will need to click the Project menu and select Properties, navigate to Configuration Properties -> C/C++, change the GTK include directory in Additional Include Directories to the include directory for your system, and then do the same for Configuration Properties -> Linker and Additional Library Directories.

Configuration and Usage

Initialization

Textadept first loads core/init.lua to initialize its core funtionality. Then init.lua is loaded for all extension and generic modules. Extension modules are in core/ext/. Generic modules are in modules/. You can disable an extension by commenting it out (put a -- before the require statement.) Finally, command line arguments are processed.

Before loading the default modules in init.lua, Textadept checks for and runs a .ta_modules Lua file in your HOME or USERPROFILE path. (Typically /home/username/ for Linux, C:\Documents and Settings\username\ for Windows, and /Users/username/ for Mac OSX). This file is presumed to contain 'require' statements to load your custom set of modules rather than the default ones. If this file is found and run successfully, init.lua's default modules will not be loaded.

Themes

Built-in themes are located in themes/. Each Textadept theme is its own folder with three files: buffer.lua, lexer.lua, and view.lua. The buffer theme sets default buffer properties like tabs and indentation. The view theme sets things like caret color and current line background color. Lexer themes set the color and style definitions used by most lexers. A 'scite' theme is provided for users accustomed to SciTE. 'light' is the default theme.

To tell Textadept to use a different built-in theme, create a .ta_theme file in your HOME or USERPROFILE path (its location was described above). Its contents should contain the theme's name.

To use a theme not built-in to Textadept, put the path to that theme's directory in .ta_theme. Remember the theme structure described earlier still applies.

If an error occurs while loading a theme, error messages are printed to standard out.

The Project Manager theme is different from Textadept and lexer themes. You can read about creating one in textadept.pm's LuaDoc.

Events

Textadept is very event-driven. Events occur when users create new buffers, close existing ones, modify saved ones, enter text, etc. Each event has a set of handlers. Handlers are simply Lua functions executed in the order they are added for a specific event. There is a list of default events.

Users are not limited to default events. Handlers can be added for custom event names and handled by calling textadept.events.handle('name' [, args]).

Two events users might like to be aware of are the view_new and buffer_new events. They are handled whenever a new view or buffer is created. The default handlers are located in core/events.lua and contain code that sets the default properties of views and buffers such as properties, margins, markers, tab and indent styles, etc. Each user might want to provide their own custom configuration. Modifying these handlers is not necessary however. Theme files can be used to set these properties.

Menus

Textadept has a built-in menu (ext/menu.lua) that provides access to pretty much every feature Textadept has, but you can replace it with a user-created one. Create a menu using textadept.gtkmenu and assign it to the textadept.menubar field. Here is an example.

local gtkmenu = textadept.gtkmenu
textadept.menubar = {
  gtkmenu {
    title = 'File',
    { 'gtk-new',   1 },
    { 'gtk-open',  2 },
    { 'gtk-save',  3 },
    { 'gtk-close', 4 },
    { 'separator', 0 },
    { 'gtk-quit',  5 },
  },
  gtkmenu {
    title = 'Edit',
    { 'gtk-undo',  10 },
    { 'gtk-redo',  11 },
    { 'separator', 12 },
    { 'gtk-copy',  13 },
    { 'gtk-paste', 14 },
  }
}

Of course, this menu is pretty useless because no actions have been assigned to a menu item when it is clicked on. Actions can be performed by a menu_clicked event handler.

local actions = {
  [1] = textadept.new_buffer,
  [2] = textadept.io.open,
  [3] = textadept.io.save
}

textadept.events.add_handler('menu_clicked',
  function(menu_id)
    local f = actions[menu_id]
    if type(f) == 'function' then f() end
  end)

Key Commands

Power users typically do not want to use menus. Textadept was designed to be very keyboard-driven and thus has a dynamic key command manager in textadept.keys. The standard key commands are contained in core/ext/key_commands.lua. Most features have a key command, but the ones that do not are labeled as -- TODO:. In addition to dynamic key commands, static ones exist for various Textadept UI elements that cannot be changed without recompiling Textadept.

  • Lua Command Entry
    • Enter - Executes entry text as Lua code.
    • Escape - Hides completion buffer if it is open.
    • Tab - Display possible completions.
  • Textadept
    • Escape - Hides the find/replace frame if it is open.
  • Project Manager
    • Escape - Refocuses the Scintilla window.
  • Find/Replace Frame
    • Enter - Find next or previous.

The following LuaDoc pages could be useful for adding or editing key commands: buffer, view, and textadept.

Project Manager

The project manager's name is a bit deceptive. It is really just a side pane that can hold any treeview-based data structure, not just a list of files in a project. Different 'browser's can display different data. For example, Textadept has browsers for opened buffers, a filesystem, modules, and more. All available browsers can be seen in core/ext/pm/. Each browser is activated by a special prefix in the PM text entry. when writing a new browser, it must contain all the functions as described in textadept.pm.browser.

Modules

Modules are basically Lua packages of functionality. Earlier, generic modules were mentioned. They are typically always available. Other modules are language-specific. They are available for specific programming languages like Lua or C++. _m has more information.

File Types

File types can be recognized and associated with lexers through core/ext/mime_types.conf. Textadept can identify a good amount of file types, but if one is not recognized, here is what to do:

  1. Look in lexers/. Is the lexer for your file type's language supported? If not, you can write one. Consult lexer for excellent documentation.
  2. Look in core/ext/mime_types.conf. Is your file extension supported? If not, add the extension and assign it a lexer name that exists in lexers/.
  3. Is your file extension-less? Do you want to identify it by its shebang line? If so, add an identifying shebang word and assign it a lexer name that exists in lexers/ and prepend a '#' before the word.
  4. Is your file extension-less? Do you want to identify it by a pattern on its first line of text? If so, add a '/'-prefixed Lua pattern and assign it a lexer name that exists in lexers/. Remember only the last space is significant, not spaces in your pattern.

Locale & Internationalization

All Textadept messages displayed are located in core/locale.conf. To change the language, simply replace this file with a similar file containing the translated messages. See core/locale.conf for more information.

Feel free to translate Textadept and send your modified locale.conf files to me. I will put them up on the site where they can be accessed.

Additional Information

The LuaDoc is a valuable resource for all aspects of Textadept. Not only does it contain Textadept's Lua API, it also contains textual documentation for the more complicated parts of the editor. This manual was not intended to completely comprehensive.

Lua Command Entry

Access to Textadept's Lua state is available through this command entry. Do take caution as careless use could crash Textadept and/or cause loss of unsaved data. This entry is useful for debugging, inspecting, and/or entering buffer or view commands. On a side note, instead of using print, use textadept.print because the former prints to standard out while the latter prints to a Textadept output buffer.

Tab completion is available! Pressing Tab will display a list of available completions. Use the arrow keys to make a selection and press Enter to insert it.

Lexers

Everything you could ever want to know about lexers and how to write them can be found in lexer's LuaDoc.

Known Issues

Win32 (all are GTK-Win issues):

  • Dragging and dropping text within Textadept copies it rather than moves it.

Mac (all are GTK-OSX issues):

  • Find area checkboxes and statusbar text sometimes do not update when changed. They must be hidden and then reshown. Manually resizing the window appears to work for a continually updating statusbar.
  • Dragging and dropping text within Textadept copies it rather than moves it.
  • Pango usually cannot render CJK and can cause crashes.
  • Project Manager cursor sometimes will not update until focus is lost.
  • Alt-key composing does not work properly.

Why Another Text Editor? Why Lua?

Previously, I used SciTE for the longest time. It is small, fast, and extensible with Lua. You may know that I am the author of two SciTE-related projects: scite-tools and SciTE-st. scite-tools is a collection of Lua scripts that provide powerful editing capabilities such as snippets, dynamic key commands, and programming language modes. On the other hand, SciTE-st has a "fork" of Scintilla that uses dynamic Lua lexers instead of static C++ ones.

While SciTE is relatively small and fast, I think it is still a bit too big. My vision of a "perfect" editor is a small static core with the ability to add dynamic extensions to it on a per-user basis, much like Emacs and VIM in terms of their extensibility, though the applications themselves are far too big and bloated. A dynamic extension language would be required, but it has to be small and fast. Ruby and Python are far too large for the scope of this project. Having used Lua heavily in both of my projects, I fell in love with the language's speed and elegance, so it was a natural choice.

Overview of Changes to Scintilla (Scintilla-st)

  • Dynamic lexer that replaces Scintilla's standard ones.
  • AutoCSeparator is | (pipe), not ?.
  • Added new messages:
    • SCI_GETLEXERLANGUAGE([unused], const char* languageName) Returns the name of the lexer currently loaded.
    • SCI_GETSTYLENAME([unused], const char* styleName) Returns the name of the style under the caret.
  • Removed some default key commands: Ctrl+L, Ctrl+Shift+L, Ctrl+T, Ctrl+Shift+T, Ctrl+D, Ctrl+U, Ctrl+Shift+U

Thanks

  • Vais Salikhov
  • Alex Bepple

Valid XHTML 1.0!