Textadept 12.6 Manual

Contents

  1. Introduction
  2. Getting Started
  3. User Interface
  4. Working with Files and Projects
  5. Adept Editing
  6. Compile, Run, Build, and Test
  7. Modules
  8. Themes
  9. Scripting
  10. Compiling
  11. Appendix

Introduction

Overview

textadept terminal

Textadept is a fast, minimalist, and remarkably extensible cross-platform text editor for programmers. It is a traditional desktop application and has both a graphical user interface (GUI), and a terminal user interface (TUI). Written in a combination of C, C++, and Lua, the editor is extremely light on resources and very responsive.

About This Manual

This manual uses the following typographical conventions:

Key bindings use the following modifier key representations:

Modifier Windows, Linux, and BSD macOS Terminal
Control Ctrl ^ ^
Alt Alt M-
Command N/A N/A
Shift Shift S-

This manual uses the following terminology:

Finally, this manual assumes you are familiar enough with the Lua programming language that you can understand the simple code samples spread throughout the manual’s contents. If you would like to quickly get up to speed, or need a refresher, the Lua Quick Reference may be of help.

Getting Started

Requirements

Textadept’s pre-built binaries require the following:

You can compile Textadept from source for use with different UI library versions, such as Qt 6 and GTK 2.24.

Download

Textadept releases and their release notes can be found here. Select the appropriate binary package for your platform. You can optionally download a companion set of modules that provide extra features and functionality for the core application.

Windows Note: antivirus software may flag the Windows package as containing a virus or malware. This is a false-positive, caused by Textadept’s terminal version executable, which is a console application.

BSD Note: binary packages for BSD are not available. You will have to compile Textadept manually. Installing and running Textadept will be similar to the Linux instructions below.

Installation

Installing Textadept is simple and easy – no administrator privileges necessary. On Windows and Linux, simply unpack the archive anywhere. On macOS, unpack the archive and move Textadept.app to your user or system Applications/ folder like any other macOS application. The macOS archive also contains a ta script for launching Textadept from the command line. You can put this script somewhere in your $PATH (e.g. /usr/local/bin/), but this is optional.

If you downloaded Textadept’s extra set of modules, unpack it into ~/.textadept/ (keeping the top-level modules/ directory intact). If ~/.textadept/ does not exist, either create it manually, or run Textadept, which creates it for you. You could instead unpack the extra modules into Textadept’s directory (thus merging the two modules/ directories), but this is not recommended, as it may make upgrading more difficult

Note: Textadept generally does not auto-load modules, so you will need to load any extra modules you installed manually. The modules section describes this process.

Updating

Textadept does not have an auto-update process, as it does not connect to the internet (it is just a text editor). Instead, download new versions as they release (typically the first day of the month every month or two), and unpack or copy its contents into your current installation, overwriting it.

Running

windows macos linux terminal

Run Textadept on Windows by double-clicking textadept.exe or textadept-curses.exe. On macOS, double-click Textadept.app or invoke the ta script from the command line. On Linux, invoke textadept, textadept-gtk, or textadept-curses from a file browser, run dialog, terminal, etc.

Linux Note: it is not possible to provide a single Textadept binary that runs correctly on all systems. If the editor will not start on your machine, you must compile it manually.

For better platform integration:

Textadept accepts the following command line arguments:

Option Description
-e <code>, --execute <code> Run the given Lua code
-f, --force Forces unique instance
-h, --help Shows thisa
-l <line>, --line <line> Jumps to a line in the previously opened file
-L <script>, --lua <script> Runs the given file as a Lua script and exits
-n, --nosession No state saving/restoring functionality
-p, --preserve Preserve ^Q and ^S flow control sequencesb
-s <name>, --session <name> Loads the given session on startupc
-u <dir>, --userhome <dir> Sets alternate user data directory
-v, --version Prints version and copyright infoa
- Read stdin into a new buffera

aThe terminal version does not support these.
bNon-Windows terminal version only.
cQt interprets --session for itself, so -s must be used.

Note: the -L and --lua options instructs Textadept to function as a standalone Lua interpreter. All other command line options have no effect, but they are available to the script via the global arg table. Textadept defines arg as it is described in the Lua manual: the script name goes at index 0, the first argument after the script name goes at index 1, and so on; arguments before the script name (i.e. the Textadept binary and the -L or --lua option) go to negative indices. Textadept does not emulate Lua’s command line options or its default package.path and package.cpath settings.

Textadept also accepts files and projects to open from the command line. For example:

textadept /path/to/file1 ../relative/path/to/file2
textadept /path/to/project/ relative/path/to/file1 relative/file2

Unless you specify a filename as an absolute path, Textadept assumes it is relative to the application’s current working directory (cwd). Textadept’s cwd is initially the command line’s cwd. (If Textadept is not being run from the command line, its cwd is unspecified.) If a project directory is specified, it becomes Textadept’s cwd, but Textadept does not open any files in that directory. If multiple project directories are specified, the last one becomes the cwd.

By default, Textadept saves its state when it exits. If you do not give Textadept any files or projects to open, do not specify a session to load, and do not disable session functionality, the editor tries to restore its state at last exit.

The GUI version of Textadept is a single-instance application – if you invoke it again while it is already open (e.g. opening a file from a file browser or command line), the action happens in the original instance. Pass the -f or --force command line flag to override this behavior and run a new instance of Textadept. You can disable this behavior on Windows by creating a shortcut to textadept.exe that passes this flag and use that shortcut to run Textadept. Similarly on Linux, you can set up your button or menu launchers to pass the flag to the textadept or textadept-gtk executables.

Textadept can run as a portable application, for example from a USB flash drive. Normally, all settings and user data is stored in ~/.textadept/. However, you can override this user directory using the -u or --userhome command line option. For example, invoking textadept.exe with the command line arguments -u userdata will read from and store settings and user data to a userdata/ directory located inside an installation of Textadept. You can create a Windows shortcut that passes these command line arguments to the Textadept executable and use that shortcut to run Textadept portably.

Preferences

The special file ~/.textadept/init.lua is a Lua script where you specify your editor preferences and customize what the application does when it starts. Open it using the “Edit > Preferences” menu item. It is initially empty. You can use this file to:

These topics will be covered throughout this manual. Textadept’s comprehensive Lua API includes all configurable settings for buffers, views, and modules.

Here is a sample ~/.textadept/init.lua for illustration:

-- Adjust the default theme's font and size.
if not CURSES then
	view:set_theme('light', {font = 'Monospace', size = 12})
end

-- Always use spaces for indentation.
io.detect_indentation = false
buffer.use_tabs = false
buffer.tab_width = 2

-- Always strip trailing spaces on save, automatically highlight the current
-- word, and use C89-style block comments in C code.
textadept.editing.strip_trailing_spaces = true
textadept.editing.highlight_words = textadept.editing.HIGHLIGHT_CURRENT
textadept.editing.comment_string.c = '/*|*/'

-- Create a key binding to the "Edit > Preferences" menu item.
if not OSX and not CURSES then
	keys['ctrl+,'] = textadept.menu.menubar['Edit/Preferences'][2]
end

-- Load an external module and bind a key to it.
local lsp = require('lsp')
keys['ctrl+f12'] = lsp.goto_declaration

-- Recognize .luadoc files as Lua code.
lexer.detect_extensions.luadoc = 'lua'

-- Change the run commands for Lua and Python
textadept.run.run_commands.lua = 'lua5.1 "%f"'
textadept.run.run_commands.python = 'python3 "%f"'

-- Always use PEP-8 indentation style for Python files, and spaces for YAML files.
events.connect(events.LEXER_LOADED, function(name)
	if name == 'python' or name == 'yaml' then
		buffer.use_tabs = false
		buffer.tab_width = 4
	end
end)

Note: ~/.textadept/init.lua must not call any functions that create buffers and views (e.g. ui.print(), io.open_file(), and buffer.new()) at file-level scope. Buffers and views can only be created within functions assigned to keys, associated with menu items, or connected to events.

User Interface

ui

Textadept’s user interface is sleek and simple. It consists of:

Terminal version note: the menu bar and tab bar are not supported.

The titlebar shows the name and path of the current, active buffer. A ‘*’ character, if present, indicates there are unsaved changes in that buffer.

Textadept’s user interface has been translated into a few different languages. When the application starts, it attempts to auto-detect your language settings by reading from the $LANG environment variable. If this fails, or if the editor does not support your language, it falls back on English. You can manually set your locale by copying one of the locale configuration files from Textadept’s core/locales/ to your ~/.textadept/ directory and renaming it locale.conf. If you would like to translate Textadept into your language, please translate the English messages in core/locale.conf and send me (see the bottom of README.md) the modified file for inclusion in a future release.

The menu bar provides access to nearly all of Textadept’s editing features. Almost every menu item has a key binding for quick access. Some languages and platforms also provide menu mnemonics for opening and selecting menu items. For example, on Windows and Linux/BSD with the English language, Alt+E opens the “Edit” menu, S opens the “Select” sub-menu, and L invokes the “Select Line” menu item.

Textadept’s menu items are also accessible in the form of a searchable dialog via Ctrl+P on Windows and Linux/BSD, ⌘P on macOS, and ^P in the terminal version. (Despite the fact that the terminal version does not have a menu, it does have this dialog.) Typing part of the name of any command in the dialog filters the list, with spaces being wildcards. The arrow keys move the selection up and down. Pressing Enter, selecting OK, or double-clicking on a command invokes it. (The terminal version requires pressing Enter.) Using this dialog is an alternative to navigating the menus or remembering key bindings. You can also use it to quickly look up key bindings for particular commands.

menu dialog menu dialog curses

Note: some commands have more than one key binding, but only one of those bindings (chosen at random) is shown in the menu and dialog.

You can extend Textadept’s menu (and dialog) with your own menus, sub-menus, and menu items by modifying the textadept.menu.menubar table. For example, in your ~/.textadept/init.lua:

local tools = textadept.menu.menubar['Tools']
tools[#tools + 1] = {''} -- separator
tools[#tools + 1] = {'Reset L&ua State', reset} -- mark 'u' as the mnemonic

Tab Bar

The tab bar displays all of Textadept’s open buffers by name, though it is only visible when two or more buffers are open. A ‘*’ character, if present, indicates there are unsaved changes in the marked buffer. When two or more views are open, the active tab applies to the active view, and clicking on a tab switches to its buffer in that view. Right-clicking on the tab bar brings up a context menu. Rearrange tabs by clicking, dragging, and dropping them. Toggle the visibility of the tab bar (as long as more than one buffer is open) using the “Buffer > Toggle Tab Bar” menu item. Turn off the tab bar completely by setting ui.tabs. For example, in your ~/.textadept/init.lua:

ui.tabs = false

Cycle to the next buffer via Ctrl+Tab or Ctrl+PgDn on Windows and Linux/BSD, ^⇥ or ⌘⇟on macOS, and M-PgDn in the terminal version. Cycle to the previous buffer via Ctrl+Shift+Tab or Ctrl+PgUp, ^⇧⇥ or ⌘⇞, and M-PgUp.

Textadept’s tabs are also accessible in the form of a searchable dialog via Ctrl+B on Windows and Linux/BSD, ⌘B on macOS, and ^B in the terminal version. (Despite the fact that the terminal version does not have a tab bar, it does have this dialog.) The dialog displays a list of currently open buffers. Typing part of any filename filters the list, with spaces being wildcards. The arrow keys move the selection up and down. Pressing Enter, selecting OK, or double-clicking on a buffer switches to it. (The terminal version requires pressing Enter.) This feature is particularly useful when many files are open, and navigating through the tab bar is tedious.

buffer browser buffer browser filtered

The dialog shows more recently used buffers towards the top. You can change the dialog show buffers in left-to-right tab order by setting ui.buffer_list_zorder. For example, in your ~/.textadept/init.lua:

ui.buffer_list_zorder = false

Editor View

editor

The editor view is where you will spend most of your time in Textadept. You can split it vertically and horizontally as many times as you like, and you can view the same buffer in two or more separate views. Resize split views by clicking and dragging on the splitter bar that separates them. Right-clicking inside a view brings up a context menu.

Note: depending on the split sequence, the order when cycling between views may not be linear.

Find & Replace Pane

find & replace

The find & replace pane searches for text in files and directories. It has the usual find and replace functionality you would expect, along with “Match Case”, “Whole Word”, “Regex”, and “In Files” options. The pane also stores find and replace history that you can cycle through.

Note: Textadept does not support multi-line searches (either regex or plain text).

Terminal version note: find and replace history is limited to 100 items each.

Summon the pane via Ctrl+F on Windows and Linux/BSD, ⌘F on macOS, and ^F in the terminal version.

In the GUI version:

In the terminal version:

When the “Regex” find option is enabled, the “Replace” entry interprets the following character sequences:

Tip: by default, “Replace All” replaces all text in the buffer. Selecting text and then performing “Replace All” replaces all text in that selection only.

Tip: You can make Textadept automatically highlight all instances of found text in the current buffer by setting ui.find.highlight_all_matches. For example, in your ~/.textadept/init.lua:

ui.find.highlight_all_matches = true

Find in Files

Textadept can search for text within multiple files and directories via Ctrl+Shift+F on Windows and Linux/BSD, ⌘⇧F on macOS, and M-^F in the terminal version. Invoking “Find Next” prompts you for a directory to search in. The “Replace” entry transforms into a “Filter” entry that contains files and directories to include or exclude from the search.

A filter consists of a comma-separated list of glob patterns that match filenames and directories to include or exclude. Patterns are inclusive by default. Exclusive patterns begin with a ‘!’. If no inclusive patterns are given, any filename is initially considered. As a convenience, ‘/’ also matches the Windows directory separator. The default filter excludes many common binary files and version control directories from searches.

Tip: Textadept keeps track of filters set per-directory. You can also set per-directory filters in Lua by modifying ui.find_in_files_filters. For example, in your ~/.textadept/init.lua:

-- Only search in certain source directories.
ui.find.find_in_files_filters['/path/to/project'] = {'/include', '/src'}

Textadept shows search results in a temporary buffer. Jump to the next or previous result via Ctrl+Alt+G or Ctrl+Alt+Shift+G, respectively, on Windows and Linux/BSD; ^⌘G or ^⌘⇧G, respectively, on macOS; and M-G or M-S-G, respectively, in the terminal version. You can also double-click on a result to jump to it, or use the arrow keys to navigate within the list and press Enter.

find in files

Incremental Find

Textadept searches for text incrementally as you type when you summon the find & replace pane via Ctrl+Alt+F on Windows and Linux/BSD, ^⌘F on macOS, and M-F in the terminal version. The “In Files” option does not apply in this mode.

Command Entry

The command entry has many different roles:

Each role has its own history that can be cycled through via the Up and Down key bindings on Windows, Linux, BSD, and the terminal version; and and on macOS.

Lua Command Entry

command entry

Open the Lua command entry via Ctrl+E on Windows and Linux/BSD, ⌘E on macOS, and ^E in the terminal version. Type in the Lua command or code to run and press Enter to execute it. Textadept’s Lua API contains all of the application’s built-in commands, settings, etc.

Show code completion candidates via Tab on Windows, Linux, BSD, and the terminal version; and on macOS. Use the arrow keys to make a selection and press Enter to insert it.

Lua code here runs in a modified environment for your convenience:

For example:

Lua code Command entry equivalent
buffer:reload() reload
view:split(true) split(true)
ui.tabs = false tabs = false
textadept.keys['ctrl+n'] = buffer.new keys['ctrl+n'] = new

Warning: Textadept will not prevent you from wrecking its internal Lua state, so please be careful.

Tip: Textadept’s -e and --execute command line arguments run the given code as if it was entered in the editor’s Lua command entry. Since the GUI version of Textadept is a single-instance application, you can send commands to that instance. For example:

textadept /path/to/file &
textadept -e "io.open_file('/path/to/another/file')"

Shell Command Entry and Filtering Text

Filter text through shell commands via Ctrl+| on Windows and Linux/BSD, ⌘| on macOS, and ^\ or ^| in the terminal version. For example, filtering a buffer’s text through the Unix sort command will sort that buffer’s lines.

pre-sort sorted

Text passed as standard input to shell commands is determined as follows:

  1. If no text is selected, the entire buffer’s text is used.
  2. If text is selected and either spans a single line, is a multiple selection, or is a rectangular selection, only that selected text is used.
  3. If text is selected and spans multiple lines, all text on those lines is used. However, if the end of the selection is at the beginning of a line, that line is omitted.

The command’s standard output replaces its input text.

Warning: commands that emit stdout while reading stdin (as opposed to emitting stdout only after stdin is closed) may hang the GTK and terminal versions of Textadept if input generates more output than stdout can buffer. For example, on Linux stdout may only be able to buffer 64K while there is still incoming input.

Statusbar

The statusbar consists of two parts:

Buffer status information includes:

Working with Files and Projects

Textadept provides many ways to open files:

Windows Note: Due to limitations in Lua and Microsoft’s C runtime (MSVCRT), Textadept can only open files whose filenames contain characters in the system’s encoding, even if Windows properly displays characters outside that encoding. For example, if the system’s encoding is CP1252 (English and most European languages), Textadept cannot open a filename that contains Japanese characters in it. This limitation only exists for file names, not file contents.

Projects

Textadept’s only concept of a project is a parent directory under a recognized form of version control (Git, Mercurial, SVN, Bazaar, and Fossil). There is no “Open Project” action. Textadept can work with multiple projects at once, since the current project depends largely on context:

  1. If the current buffer is a file, Textadept walks up its parent directory tree, looking for a version control directory. If one is found, its parent directory is the current project.
  2. Textadept walks up its current working directory (cwd) tree, looking for a version control directory. If one is found, its parent directory is the current project.
  3. If no version control directory is found, there is no current project.

Tip: you can specify Textadept’s current working directory by passing it on the command line when running the application. This effectively starts Textadept with a “default project”.

Textadept’s quick open dialog for opening a file from the current project displays the first 5000 files it finds. You can increase this limit by changing io.quick_open_max. You can also filter out certain file types from showing in the list by adding a project-specific filter to io.quick_open_filters. For example, in your ~/.textadept/init.lua:

io.quick_open_max = 10000 -- support huge projects
io.quick_open_filters['/path/to/project'] = {'/include', '/src'}

A filter consists of a comma-separated list of glob patterns that match filenames and directories to include or exclude. Patterns are inclusive by default. Exclusive patterns begin with a ‘!’. If no inclusive patterns are given, any filename is initially considered. As a convenience, ‘/’ also matches the Windows directory separator. The default filter excludes many common binary files and version control directories from searches.

quick open

You can mimic a more traditional approach to projects by saving and loading project-specific sessions using the “File > Save Session…” and “File > Load Session…” menu items, respectively, as well as using the -s and --session command line arguments. Textadept stores session files in ~/.textadept/, and the default session name is “session”.

Language

Textadept attempts to identify the programming language associated with files it opens and assign a lexer for syntax highlighting:

  1. The first line of the file is checked against the Lua patterns in lexer.detect_patterns. If there is a match, Textadept uses the lexer associated with that matching pattern.
  2. The file’s extension is checked against those in lexer.detect_extensions. If there is a match, Textadept uses the lexer associated with that extension. If the file does not have an extension, Textadept uses the entire file name in the check.
  3. Textadept falls back on a plain text lexer.

You can change or add lexers associated with first line patterns, file extensions, and file names by modifying lexer.detect_patterns and lexer.detect_extensions. For example, in your ~/.textadept/init.lua:

lexer.detect_patterns['^#!.+/zsh'] = 'bash'
lexer.detect_extensions.luadoc = 'lua'

Textadept has lexers for more than 100 different programming languages, but if it is missing a lexer for your language, you can write one, place it in your ~/.textadept/lexers/ directory, and add an extension and/or pattern for it.

Tip: placing lexers in your user data directory avoids the possibility of you overwriting them when you update Textadept.

You can manually change a buffer’s lexer via Ctrl+Shift+L on Windows and Linux/ BSD, ⌘⇧L on macOS, and M-^L in the terminal version. Typing part of a lexer name in the dialog filters the list, with spaces being wildcards. The arrow keys move the selection up and down. Pressing Enter, selecting OK, or double-clicking on a lexer assigns it to the current buffer. (The terminal version requires pressing Enter.)

End of Line Mode

Textadept attempts to detect a file’s end-of-line mode (EOL mode), falling back on CRLF (“\r\n”) by default on Windows, and LF (‘\n’) on all other platforms. You can manually change this mode using the “Buffer > EOL Mode” menu.

Indentation

Textadept also attempts to identify a file’s indentation settings, though the editor is more likely to misidentify files with mixed indentation.

You can manually change a buffer’s indentation by following these steps:

  1. Toggle between using tabs and spaces via Ctrl+Alt+T on Windows and Linux/BSD, ^⌘T on macOS, and M-T in the terminal version.
  2. Set the indentation size using the “Buffer > Indentation” menu.
  3. Optionally convert existing indentation to the new indentation settings using the “Buffer > Indentation > Convert Indentation” menu item.

The default indentation setting is a tab representing 8 spaces, but you can change this globally and on a language-specific basis. For example, in your ~/.textadept/init.lua:

-- Disallow auto-detection of indentation.
io.detect_indentation = false

-- Default indentation settings for all buffers.
buffer.use_tabs = false
buffer.tab_width = 2

-- Indentation settings for individual languages.
events.connect(events.LEXER_LOADED, function(name)
	if name == 'python' or name == 'yaml' then
		buffer.use_tabs = false
		buffer.tab_width = 4
	elseif name == 'go' then
		buffer.use_tabs = true
		buffer.tab_width = 4
	end
end)

Encoding

Textadept attempts to detect a file’s character encoding, either UTF-8, ASCII, CP1252, or UTF-16. If you have files with other encodings, you can either:

The “Buffer > Encoding” menu also allows you to change the current file’s encoding.

View Settings

Textadept normally does not wrap long lines into view, nor does it show whitespace characters. You can toggle line wrapping for the current buffer via Ctrl+\ on Windows and Linux/BSD, ⌘\ on macOS, and M-\ in the terminal version. You can toggle whitespace visibility for the current buffer using the “View > Toggle View Whitespace” menu item. The editor represents visible spaces as dots and visible tabs as arrows.

On the left side of each editor view are margins that show line numbers, bookmarks, and fold markers. You can toggle the visibility of these margins using the “View > Toggle Margins” menu item.

The GUI version of Textadept shows small guiding lines based on indentation level. You can toggle the visibility of these guides for the current view using the “View > Toggle Show Indent Guides” menu item.

The GUI version of Textadept also allows you to temporarily change the current view’s font size:

Adept Editing

Textadept implements a commonly accepted set of text editor features and key bindings across each of its Platforms, including Bash-style key bindings on macOS and in the terminal version. The editor also has its own advanced features, many of which are described in the following sections.

Brace Matching, Auto-pair, and Typeover

Textadept highlights matching brace characters when the caret is over one of them: ‘(‘, ‘)’, ‘[’, ‘]’, ‘{‘, or ‘}’ for programming languages, and ‘<’ or ‘>’ for XML-like markup languages. Jump to the current character’s complement via Ctrl+M on Windows and Linux/BSD, ⌘M on macOS, and M-M in the terminal version.

The editor automatically inserts the complement of typed opening brace and quote characters, deletes that complement if you type Backspace, and moves over the complement if you type it (as opposed to inserting it again). You can configure or disable this behavior by modifying textadept.editing.auto_pairs and textadept.editing.typeover_auto_paired. For example, in your ~/.textadept/init.lua:

-- Auto-pair and typeover '*' (Markdown emphasis/strong).
textadept.editing.auto_pairs['*'] = '*'

-- Disable only typeover.
textadept.editing.typeover_auto_paired = false

-- Disable auto-pair and typeover.
textadept.editing.auto_pairs = nil

Word Highlight

Textadept can automatically highlight all occurrences of the word under the caret, or all occurrences of the selected word (e.g. a variable name), by setting textadept.editing.highlight_words. For example, in your ~/.textadept/init.lua:

-- Highlight all occurrences of the current word.
textadept.editing.highlight_words = textadept.editing.HIGHLIGHT_CURRENT
-- Highlight all occurrences of the selected word.
textadept.editing.highlight_words = textadept.editing.HIGHLIGHT_SELECTED

word highlight

Textadept does not perform any automatic highlighting by default.

Autocompletion

Textadept autocompletes words in the current buffer via Ctrl+Enter on Windows and Linux/BSD, ⌘↩ on macOS, and ^Enter in the terminal version. If there are multiple candidates, the editor shows a list of suggestions. Continuing to type may change the suggestion. Use the arrow keys to navigate within the list and press Enter to finish the completion. You can expand the word pool to include all open buffers by setting textadept.editing.autocomplete_all_words. For example, in ~/.textadept/init.lua:

textadept.editing.autocomplete_all_words = true

Tip: the external Language Server Protocol module provides language-specific autocompletions. It also shows symbol documentation. These features enable you to easily configure and extend Textadept, as well as understand its API, all from within the editor itself.

autocomplete api doc

Text Selections

Textadept has three kinds of text selections: contiguous, multiple, and rectangular.

You can create contiguous selections as follows:

You can create multiple selections as follows:

Textadept mirrors any typed or pasted text at each selection. Deselect a particular additional selection by holding down Ctrl and clicking it with the mouse.

pre rename renamed

You can create a rectangular selection as follows:

Textadept allows a zero-width rectangular selection that spans multiple lines, and mirrors any typed or pasted text on all of those lines.

rectangular selection rectangular edit

You can also copy rectangular blocks of text and paste them into rectangular blocks of the same size.

Note: macOS does not support directly pasting into rectangular selections. Instead, use the Lua Command Entry and enter replace_rectangular(clipboard_text) after copying a block of text.

Text Transformations

Textadept can apply many different transformations to the current word, line, and selected text:

Textadept records buffer positions within views over time and allows for navigating through that history. Navigate backward or forward via Ctrl+[ or Ctrl+], respectively, on Windows and Linux/BSD; ⌘[ or ⌘], respectively, on macOS; and M-[ or M-], respectively, in the terminal version.

Go To Line

Jump to a specific line in the current buffer via Ctrl+G on Windows and Linux/BSD, ⌘G on macOS, and ^G in the terminal version. Enter the line number to go to in the prompt, and press Enter or click OK.

Bookmarks

Textadept allows you to bookmark lines and jump back to them later:

The editor displays bookmarks in the left-hand margin after line numbers.

Macros

Macros enable you to record a series of edits and play them back without having to write a custom Lua script:

Tip: the previously recorded/loaded macro is always registered to 0 (zero), so if you accidentally recorded/loaded a macro without having registered/saved the previous one, you can reload and play it via Ctrl+Alt+R 0 on Windows and Linux/BSD, ^⌘R 0 on macOS, and M-R 0 in the terminal version.

Snippets

Snippets are dynamic text templates for quickly inserting code constructs. They may contain plain text, placeholders for interactive input, mirrors and transforms for interactive input, and arbitrary Shell code.

snippet snippet expanded

A snippet has a trigger word associated with template text in the snippets table. The snippets documentation describes snippet syntax. Language-specific snippets are in a subtable assigned to their language’s lexer name. Snippets may also be the contents of files in a snippet directory, with file names being trigger words.

Code Folding

Many of Textadept’s lexers can identify blocks of code and mark their fold points in the editor’s left-hand margin. Toggle the visibility of a code block by clicking on its marker, or toggle the visibility of the current block via Ctrl+} on Windows and Linux/BSD, ⌘} on macOS, and M-} in the terminal version.

folding

Virtual Space

Textadept normally constrains the caret within the content of text lines. Enabling virtual space allows you to move the caret into the space beyond the ends of lines. Toggle virtual space using the “View > Toggle Virtual Space” menu item.

Key Bindings

Key bindings are key sequences assigned to commands (Lua functions) in the keys table. A key sequence is an ordered combination of modifier keys followed by either the key’s inserted character or, if no such character exists, the string representation of the key according to keys.KEYSYMS. Language-specific keys are in a subtable assigned to their language’s lexer name. You can assign key sequences to tables of key bindings to create key chains (e.g. Emacs C-x prefix). You can also group key bindings into modes such that while a mode is active, Textadept ignores all key bindings outside that mode until the mode is unset (e.g. Vim-style modal editing). The keys documentation describes all of this in more detail.

Compile, Run, Build, and Test

Textadept knows most of the commands that compile and/or run code in source files. It also knows some of the commands that build projects, and you can tell the editor how to run your project’s test suite. Finally, Textadept allows you to run arbitrary commands in the context of your project. The editor prints command output in real-time to a temporary buffer and marks any warning and error messages it recognizes.

Prior to running a compile, run, build, or test command, Textadept prompts you with either:

  1. A command it thinks is appropriate for the current file or project.
  2. A command you have specified for the current context (e.g. via ~/.textadept/init.lua).
  3. A command you have previously run in the current context.
  4. A blank command for you to fill in.

Make any necessary changes to the command and then run it by pressing Enter. Cycle through command history via Up and Down on Windows, Linux, BSD, and the terminal version; and and on macOS. Cancel the prompt via Esc. Textadept remembers compile and run commands on a per-filename basis, and it remembers build, test, and project commands on a per-directory basis.

runtime error

You can configure Textadept to run commands immediately without a prompt by setting textadept.run.run_without_prompt. You can also have the editor print command output in the background by changing textadept.run.run_in_background. For example, in your ~/.textadept/init.lua:

textadept.run.run_without_prompt = true
textadept.run.run_in_background = true

You can change or add compile, run, build, test, and project commands by modifying the textadept.run.compile_commands, textadept.run.run_commands, textadept.run.build_commands, textadept.run.test_commands, and textadept.run.run_project_commands tables, respectively. For example, in your ~/.textadept/init.lua:

textadept.run.compile_commands.foo = 'foo "%f"'
textadept.run.run_commands.foo = './"%e"'

textadept.run.build_commands['/path/to/project'] = 'make -C src -j4'
textadept.run.test_commands['/path/to/project'] = 'lua tests.lua'
textadept.run.run_project_commands['/path/to/project'] = function()

end

Tip: you can set compile and run commands on a per-filename basis.

macOS Tip: GUI applications like Textadept.app run in a restricted environment with a stripped-down $PATH. (The terminal version is unaffected.) Thus, Textadept may fail to find compile/run programs outside that $PATH (e.g. programs installed with Homebrew). The editor attempts to work around this by silently invoking your $SHELL and extracting its environment (including its full $PATH), but if this fails, you will need to supply absolute paths to executables.

Modules

Modules are packages of Lua code that provide functionality for Textadept. Most of the editor’s features come from individual modules (Textadept’s core/ and modules/ directories). Textadept can load modules when the application starts up, and it can load modules on-demand in response to events. Once a module is loaded, it persists in memory and is never unloaded.

Textadept attempts to load a given module from the following locations:

  1. Your ~/.textadept/modules/ directory.
  2. Textadept’s modules/ directory.

Tip: placing modules in your user data directory avoids the possibility of you overwriting them when you update Textadept.

Just because a module exists does not mean Textadept will automatically load it. The editor only loads modules it is explicitly told to load (e.g. from your ~/.textadept/init.lua). For example, in your ~/.textadept/init.lua:

local lsp = require('lsp')
lsp.server_commands.cpp = 'clangd'

If you have a module for a particular programming language, you can automatically load it when opening a file of that type:

events.connect(events.LEXER_LOADED, function(name)
	if package.searchpath(name, package.path) then require(name) end
end)

Note: lexer language names are typically the names of lexer files in your ~/.textadept/lexers/ directory and Textadept’s lexers/ directory.

Developing Modules

Modules follow the Lua package model: a module is either a single Lua file or a group of Lua files in a directory that contains an init.lua file (which is the module’s entry point). The name of the module is its file name or directory name, respectively. Here are some basic guidelines for developing modules, and some things to keep in mind:

Themes

Themes customize the editor’s look and feel. Textadept comes with three built-in themes: “light”, “dark”, and “term”. The default theme for the GUI version is “light” if light mode is currently enabled, or “dark” if dark mode is enabled. The default theme for the terminal version is “term”.

light theme dark theme

A theme consists of a single Lua file, and defines the colors and text display settings (styles) used in syntax highlighting. It also assigns colors to various UI elements like carets, selections, margins, markers, highlights, errors, and warnings.

Note: Textadept cannot theme its own GUI widgets. You must use the theming tools provided by the applicable Qt or GTK widget toolkit.

Textadept attempts to load themes from the following locations:

  1. Your ~/.textadept/themes/ directory.
  2. Textadept’s themes/ directory.

Tip: placing themes in your user data directory avoids the possibility of you overwriting them when you update Textadept.

You can set Textadept’s theme using view:set_theme(). You can also tweak a theme’s styles on a per-language basis. For example, in your ~/.textadept/init.lua:

if not CURSES then
	view:set_theme('light', {font = 'Monospace', size = 12})
	-- You can alternatively use the following to keep the default theme:
	-- view:set_theme{font = 'Monospace', size = 12}
end

-- Color Java class names black instead of the default yellow.
events.connect(events.LEXER_LOADED, function(name)
	if name ~= 'java' then return end
	local default_fore = view.style_fore[view.STYLE_DEFAULT]
	view.style_fore[buffer:style_of_name(lexer.CLASS)] = default_fore
end)

Tip: you can experiment with themes without having to restart Textadept by using the reset() command in the Lua Command Entry. After making changes to either your ~/.textadept/init.lua or theme file, issue the reset command to reload your changes.

Scripting

Nearly every aspect of Textadept can be scripted, extended, and customized with Lua. In fact, most of the editor’s features are implemented in Lua: syntax highlighting, opening and saving files, and search and replace, to name a few. Textadept contains its own internal copy of Lua 5.4.

Being an event-driven application, Textadept simply responds to input like key presses, mouse clicks, and state changes by running Lua code (more specifically, executing Lua functions). For example, when you press a key, Textadept emits an events.KEYPRESS event, which its core/keys.lua is listening for. When the editor recognizes a key sequence like Ctrl+O on Windows and Linux/BSD, core/keys.lua looks up which Lua function is assigned to the keys['ctrl+o'] key. By default, it is io.open_file(), so Textadept executes that function, which prompts the user for a file to open. You could bind a different function to that key and the editor will duly execute it instead. Similarly, when Textadept opens a file via io.open_file(), that function emits a events.FILE_OPENED event, which you could listen for in your ~/.textadept/init.lua and perform your own action, such as loading some project-specific tools for editing that file.

Your ~/.textadept/init.lua is the entry point to scripting Textadept. In this file you can set up custom key bindings, menu items, and event handlers that will perform custom actions. Here are some ideas:

Textadept’s Lua API is extensively documented and serves as the ultimate resource when it comes to scripting the editor.

Compiling

Textadept uses CMake to build on Windows, macOS, Linux, and BSD. CMake automatically detects which UI toolkits are available and builds for them. On Windows and macOS you can then use CMake to create a self-contained application to run from anywhere. On Linux and BSD you can either use CMake to install Textadept, or place compiled binaries into Textadept’s root directory and run it from there.

Requirements

Textadept requires the following:

macOS Note: XCode provides Clang.

Linux Note: a package manager likely supplies these requirements. On Ubuntu for example, the build-essential, qtbase5-dev, libgtk-3-dev (or libgtk2.0-dev), and libncurses-dev packages are all that is needed.

Compiling

Basic procedure:

  1. Configure CMake by pointing it to Textadept’s source directory (where CMakeLists.txt is), specify a directory to build in, and optionally specify a directory to install to. CMake will determine what UI toolkits are available and fetch third-party build dependencies.
    cmake
  2. Build Textadept.
  3. Either copy the built binaries to Textadept’s source directory or use CMake to install it.

For example:

cmake -S . -B build_dir -D CMAKE_BUILD_TYPE=RelWithDebInfo \
	-D CMAKE_INSTALL_PREFIX=build_dir/install
cmake --build build_dir -j # compiled binaries are in build_dir/
cmake --install build_dir # self-contained installation is in build_dir/install/

Windows Note: you need to run these commands from Visual Studio’s developer command prompt if you are not using CMake’s GUI and Visual Studio.

Tip: you can use the environment variable TEXTADEPT_HOME to specify the location of Textadept’s root directory. Doing so allows you to run Textadept executables directly from the binary directory without having to install or copy them.

Windows and macOS Note: when creating the self-contained Qt version of Textadept, Qt’s bin/ directory should be in your %PATH% or $PATH, respectively.

CMake boolean variables that affect the build:

Appendix

Regex and Lua Pattern Syntax

The following table outlines Regex and Lua Pattern syntax:

Regex Lua Meaning
. . Matches any character
[[:alpha:]] %a Matches any letter
\d %d Matches any digit
[[:lower:]] %l Matches any lower case character
[[:punct:]] %p Matches any punctuation character
\s %s Matches any space character
[[:upper:]] %u Matches any upper case character
\w %w Matches any alphanumeric character (Regex includes ‘_’)
[[:xdigit:]] %x Matches any hexadecimal digit
[set] [set] Matches any character in set, including ranges like A-Z
[^set] [^set] Matches the complement of set
* * Matches the previous item (Regex) or class (Lua) 0+ times
+ + Matches the previous item or class 1+ times
*? - Matches the previous item or class 0+ times, non-greedily
+?   Matches the previous item 1+ times, non-greedily
? ? Matches the previous item or class once or not at all
{m,n}   Matches the previous item between m and n times
{m,}   Matches the previous item at least m times
{m}   Matches the previous item exactly m times
|   Matches either the previous item or the next item
  %bxy Matches a balanced string bounded by x and y
  %f[set] Matches a position between characters not in and in set
\<   Matches the beginning of a word
\>   Matches the end of a word
\b   Matches a word boundary
^ ^ Matches the beginning of a line unless inside a set
$ $ Matches the end of a line unless inside a set
( ( The beginning of a captured matching region
) ) The end of a captured matching region
(?:)   Consider matched “” as a single, uncaptured item
\n %n The nth captured matching region’s texta
\x %x Non-alphanumeric character x, ignoring special meaning

aIn replacement text, “\0” (Regex) or “%0” (Lua) represents all matched text.

Textadept’s regular expressions are based on the C++11 standard for ECMAScript. There are a number of references for this syntax on the internet, including:

More information on Lua patterns can be found in the Lua 5.4 Reference Manual.

Terminal Version Compatibility

Textadept’s terminal version requires a font with good glyph support (like DejaVu Sans Mono or Liberation Mono), and lacks some GUI features due to the terminal’s constraints:

Directory Structure

Textadept’s directory structure is organized as follows:

Technologies

Textadept is composed of the following technologies:

Migrating from Textadept 11 to 12

API Changes

Old API Change New API
_G    
N/A Added GTK, QT
OSX Changed Always true on macOS, not just in the GUI version
_M Removed N/Aa
_SCINTILLA    
next_* Renamed new_*
buffer    
tab_label Changed Write-only
property_int Removed N/A
MARKNUM_FOLDER* Renamed view.MARKNUM_FOLDER*
events    
KEYPRESS Changed Changed arguments
TAB_CLICKED Changed Changed arguments
MOUSE Changed Changed arguments
io    
N/A Added ensure_final_newlineb
quick_open() Changed Removed opts parameter
lexer    
N/A Added names()
colors Renamed view.colors
styles Renamed view.styles
fold* Renamed view.fold*
token() Renamed tag(), and made into an instance method
property_expanded Removed N/A
starts_line() Changed Added allow_indent parameter
last_char_includes() Renamed after_set()
word_match() Changed Can also be used as an instance method
N/A Added set_word_list()
N/A Added number_() and friends
to_eol() Changed prefix parameter is optional
fold_line_groups Removed N/A
textadept.editing    
INDIC_BRACEMATCH Removed N/Ac
brace_matches Removed N/Ad
auto_pairs Changed Keys are string characters, not byte values
typeover_chars Changed typeover_auto_paired
api_files Removed N/A
show_documentation Removed N/A
textadept.file_types Removed N/A
extensions Renamed lexer.detect_extensions
patterns Renamed lexer.detect_patterns
select_lexer() Replaced textadept.menu.menubar['Buffer/Select Lexer...'][2]
textadept.macros    
play() Changed Added optional filename parameter
textadept.run    
error_patterns Removed N/A
set_arguments() Removed N/Ae
N/A Added run_project(), run_project_commands
N/A Added INDIC_WARNING, INDIC_ERROR
textadept.snippets    
cancel_current Renamed cancel
N/A Added transform_methods
N/A Added variables
ui    
N/A Added output()
silent_print Replaced print_silent(), output_silent()
_print() Renamed print_to()
switch_buffer() Changed Removed zorder parameter in favor of buffer_list_zorder
N/A Added suspend()
ui.command_entry    
append_history() Removed N/A
run() Changed Changed parameter list
ui.dialogs    
msgbox(), ok_msgbox(), yesno_msgbox() Replaced message()
inputbox(), standard_inputbox() Replaced input()
secure_inputbox(), secure_standard_inputbox() Removed N/A
fileselect(), filesave() Replaced open(), save()
progressbar() Replaced progress()
filteredlist() Replaced list()
dropdown(), standard_dropdown() Removed N/A
textbox(), optionselect(), colorselect(), fontselect() Removed N/A
view    
N/A Added set_styles()

bNo longer part of textadept.editing.strip_trailing_spaces
cUse view.STYLE_BRACEBAD and view.STYLE_BRACELIGHT instead
dAngles as brace characters is auto-detected now
eSee below how compile and run commands have changed

Theme Changes

Textadept has a new set of themes and styles to set. All styles are view-specific; they are no longer tied to lexers. This means one view can have a light theme, and another can have a dark theme.

Themes can be migrated from Textadept 11 to 12 in the following way:

Lexer Changes

Textadept’s lexers use a new convention and no longer contain styling information. Custom lexers should be migrated, and themes are responsible for styling custom tags. Also, lexers no longer have access to Textadept’s Lua state or any buffer information. They are strictly sandboxed.

events.LEXER_LOADED will be emitted less frequently than before. For example, switching between buffers will no longer emit it. You may want to also connect lexer-specific event handlers to events.BUFFER_AFTER_SWITCH and events.VIEW_AFTER_SWITCH and check buffer.lexer_language from within them.

Snippet Changes

Textadept now supports TextMate-style snippets. The legacy format is still supported, but those snippets should be migrated as soon as possible.

Compile, Run, Build, and Test Changes

All compile, run, build, and test commands no longer fire immediately when invoked. Instead, candidate commands are displayed in the command entry first. Pressing Enter will run the command. This allows for in-place modifications of commands that will be remembered next time the command is run for a particular file/project. As a result, per-file and per-project command histories are now available.

Also, command output uses a new “output” lexer which recognizes warnings and errors. Textadept no longer attempts its own warning/error detection.

Key Bindings Changes

Textadept’s key bindings have been redesigned to be as consistent as possible between operating systems and platforms.

As a result, macros recorded in Textadept 11 will likely not be compatible in Textadept 12.

Dialog Changes

Dialogs have been simplified in order to accommodate multiple platforms (currently Qt, GTK, and curses). In general, affirmative responses return input data rather than returning buttons and then input data, and negative responses return nil. For example, pressing Enter or clicking “Ok” in an input dialog returns the text entered rather than returning a button code (that needs to be interpreted) and text entered. Similarly, pressing Escape or clicking “Cancel” in an input dialog returns nil rather than returning a button code that needs to be interpreted.

Dialogs no longer accept a string_output option. Buttons are always returned as numbers and list selections are always returned as numeric indices.

Filter Changes

Filters for lfs.walk() and io.quick_open() no longer use Lua patterns, but use typical shell glob patterns instead. This means special characters like ‘-‘ and ‘+’ can be used literally and longer need to be escaped with ‘%’.

Language Module Changes

Textadept no longer automatically loads language modules. They need to be manually loaded like other modules. You can either do this directly on startup from your ~/.textadept/init.lua, or lazy load them from an events.LEXER_LOADED event handler in your ~/.textadept/init.lua:

require('lua') -- load language module on startup

-- Lazy-load language modules as files are opened.
events.connect(events.LEXER_LOADED, function(name)
	if package.searchpath(name, package.path) then require(name) end
end)

If you prefer old behavior that loads all language modules into a global _M table, then you can do this:

_M = {}
events.connect(events.LEXER_LOADED, function(name)
	if package.searchpath(name, package.path) then _M[name] = require(name) end
end)

Accessing and changing menu items from top-level menus (menubar, context menu, and tab menu) has a new shorthand notation:

local select_word = textadept.menu.menubar['Edit/Select/Select Word'][2]
local find = textadept.menu.menubar['Search/Find']
find[1], find[2] = 'Custom Find', custom_find_function

Previously, you had to perform cumbersome one-at-a-time indexing:

local select_word = textadept.menu.menubar[_L['Edit']][_L['Select']][_L['Select Word']][2]
local find = textadept.menu.menubar[_L['Search']][_L['Find']]
find[1], find[2] = 'Custom Find', custom_find_function

Also, menu labels are auto-localized. You can use your locale’s labels or Textadept’s English ones.