Skip to main content



Pragtical searches a list of paths to store user configuration. This path is also known as USERDIR. The first path that is available will be used.

  1. <path_to_pragtical_executable>/user
  3. $XDG_CONFIG_HOME/pragtical
  4. $HOME/.config/pragtical

On Windows, $HOME will be replaced with $USERPROFILE.

User Module

Pragtical is mainly configured through the user module. The user module is a Lua script run by Pragtical during startup, before plugins are loaded. Thus, you can change configuration options, bind shortcut keys, load color schemes, change the fonts among other things.

To modify the user module, you can run the command core:open-user-module. You can also modify the file USERDIR/init.lua directly. Pragtical will reload the file on file change.

Project Module

The project module is an optional module which is loaded from the current project's directory when Pragtical is started. Project modules can be useful for things like adding custom commands for project-specific build systems, or loading project-specific plugins.

The project module is loaded when the editor starts, after the user module is loaded but before plugins are loaded.

To modify project module, you can run the command core:open-project-module. The command will create a project module if it does not exist.

Settings GUI

The settings plugin provides a GUI to configure Pragtical.

Settings User Interface


Pragtical comes with JetBrains Mono and Fira Sans by default.

To change the fonts used by the editor, you can change the variable style.font and style.code_font. These variables are responsible for the UI font and code font respectively.

To load a font, you can use renderer.font.load(). This function allows you to load a font file as long as it is supported by FreeType. The function takes in the path to the font file and the pixel size of the font.

When displaying text with multiple languages, multiple fonts are often required. Pragtical supports fallback fonts by using the function This function takes in a table of fonts loaded by renderer.font.load(). Pragtical will attempt to render fonts based on the order the fonts are added to the table.

For this example, we'll load Noto Sans Mono, which is located in /usr/share/fonts/noto/NotoSansMono-Regular.ttf and set it as our code font.

local style = require ""
-- SCALE is the pixel scaling required for the current DPI setup.
-- This converts the font size from points to pixels.
style.code_font = renderer.font.load("/usr/share/fonts/noto/NotoSansMono-Regular.ttf", 15 * SCALE)

Next, we'll also load Noto Sans Mono CJK SC, which is located in /usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc and use it as fallback.

local style = require ""
-- do not ever do style.code_font = { style.code_font, ... }
-- style.code_font can be a font group and pragtical does not
-- support nested font groups!
style.code_font = {
renderer.font.load("/usr/share/fonts/noto/NotoSansMono-Regular.ttf", 15 * SCALE),
renderer.font.load("/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc", 15 * SCALE)
No .ttc fonts support

Pragtical does not support using a specfific face in a TrueType collection (.ttc) file. Only the first face can be used.

Keyboard shortcuts

Keyboard shortcuts are managed by the core.keymap module. This module maps keyboard shortcuts to one or more commands, where each command has a predicate that determine whether it should run based on certain conditions.

For a list of default keyboard shortcuts, check out these pages:

Adding a keyboard shortcut

To add keyboard shortcuts, you can use keymap.add().

For example, to bind ctrl+m to move the cursor backwards and then upwards, do:

local keymap = require "core.keymap"
keymap.add {
["ctrl+m"] = "doc:move-to-previous-char"
keymap.add {
["ctrl+m"] = "doc:move-to-previous-line"

Pragtical will automatically execute both commands in the order that they're added.

Alternatively, to override a keyboard shortcut completely, add true on the second parameter of keybind.add().

local keymap = require "core.keymap"
keymap.add {
["ctrl+m"] = "doc:move-to-previous-char"
["ctrl+m"] = "doc:move-to-previous-line"
}, true)

This will cause Pragtical to only run core:move-to-previous-line when ctrl+m is pressed.

Removing a keyboard shortcut

To remove an existing keyboard shortcut, you can use keymap.unbind().

In this example, we will unbind ctrl+m.

local keymap = require "core.keymap"
keymap.unbind("ctrl+m", "doc:move-to-previous-line")
keymap.unbind("ctrl+m", "doc:move-to-previous-char")

This will unbind the two commands from ctrl+m.

Alternatively, to unbind all commands from ctrl+m, you can omit the second parameter to keymap.unbind().

local keymap = require "core.keymap"
keymap.unbind("ctrl+m", "doc:move-to-previous-line")
keymap.unbind("ctrl+m", "doc:move-to-previous-char")


The default theme is a dark theme. Themes are implemented as plugins that changes the styling variables of Pragtical.

This can be changed with core.reload_module() and loading the appropriate theme file.

To load the theme summer, add core.reload_module "colors.summer".

core.reload_module "color.summer"

Other options

There are a lot of configuration options that can be modified. A list of these options can be found in data/core/config.lua, but we'll list a few common ones here.


To change the indentation size and type, set config.indent_size and config.tab_type respectively.

local config = require "core.config"
config.indent_size = 4 -- set indentation to 4
config.tab_type = -- "soft" for spaces, "hard" for tabs

Window decoration

If you're on platforms such as Wayland where window decoration may be client drawn, you can set config.borderless to true. This will let Pragtical draw its own window decoration.

local config = require "core.config"
-- enable custom window borders
config.borderless = true

Project files limit

When opening large directories, Pragtical will often complain about reaching the project file limit. This is because Pragtical becomes slower when it needs to index these files on startup.

If your filesystem has good performance, you can increase this limit by setting config.max_project_files to something else. The default value is 2000.

local config = require "core.config"
-- set max project files to 5000
config.max_project_files = 5000

Ignoring files

Pragtical does not index certain files and directories by default, such as version control and executables. This can be modified by changing config.ignore_files. This value is a table of Lua patterns. For directories, the pattern ends with a forward slash (/). For files, the pattern ends with the end anchor ($).

local config = require "core.config"
-- ignore .data/
table.insert(config.ignore_files, "^")


You can disable or change the blinking rate of the caret.

local config = require "core.config"
config.disable_blink = true -- disable caret blinking
config.blink_period = 0.4 -- change caret blink rate

FPS (Frame rate)

The default frame rate is set to 60. If this causes an issue, you can set it via config.fps.

local config = require "core.config"
-- set FPS to 30
config.fps = 30


You can disable any animations/transitions by setting config.transitions to false. To disable individual transitions, you can set any member of config.disabled_transitions to true.

local config = require "core.config"
-- disable all transitions
config.transitions = false
-- disable commandview and scroll transitions
config.disabled_transitions = {
commandview = true,
scroll = true

To change the animation rate, set config.animation_rate.

local config = require "core.config"
-- slow down the animations to half speed
config.animation_rate = 0.5

Other options

A quick reference of other options.
max_log_itemsMaximum number of log items to store before discarding them.
message_timeoutTime (seconds) to show each message on the StatusView.
mouse_wheel_scrollNumber of pixels per "scroll".
animate_drag_scrollEnable smooth scrolling.
force_scrollbar_statusAlways expand ("expanded") or hide ("contracted") the scrollbar.
file_size_limitFile size limit (MB) before Pragtical refuses to load it.
symbol_patternLua pattern used by Pragtical to find symbols.
non_word_charsA pattern used to find non-word characters.
undo_merge_timeoutTime (seconds) before Pragtical merges edits to form a single undo step.
max_undosNumber of undo to store per document.
max_tabsNumber of tabs to show before overflowing.
always_show_tabsIf true, always show tabs even if only one file is open.
highlight_current_lineHighlights the current line.
line_heightThe spacing between each line.
keep_newline_whitespaceIf true, removes any line that only contains whitespace (space, tabs, etc.)
line_limitAn advisory limit for characters per line.
tab_close_buttonShows or hides the tab close button for each tab.
max_clicksMaximum number of clicks you can perform in the editor.


Since the user and project module loads before any plugins, you can configure or disable any plugins in the user and project modules. Plugins obtain their configuration from a table in the config.plugins table. You can add code to user module that modifies the table.

To disable a plugin, you need to set the associated config.plugins entry to false. This tells Pragtical to not load the plugin on startup. It will not load nor unload the plugin from the current instance.

Some plugins may have options to enable/disable themselves.

This allows the plugins to be loaded and toggled without a restart.

In this example, we'll enable the drawwhitespace plugin and set it to only draw whitespaces in the selected text.

local config = require "core.config"
config.plugins.drawwhitespace = {
show_selected_only = true

To disable the plugin, simply assign config.plugins.drawwhitespace to false.

local config = require "core.config"
config.plugins.drawwhitespace = false