Interacting with the OS
This is where Pragtical's Lua code interact with its underlying C engine.
Using the System API
There are many functions that belong to this API; not all are necessary for plugin development. As such, we'll ignore them here and only document the useful ones.
Clipboard
system.set_clipboard(text) offers plain text, and system.get_clipboard()
reads text or returns nil when none is available:
system.set_clipboard("Copied from Pragtical")
local text = system.get_clipboard()
For other formats, inspect system.get_clipboard_mime_types() and pass a MIME
type to get_clipboard. Raw reads preserve binary bytes and their length.
set_clipboard(data, mime_type) offers data under one type; a table of MIME
types offers the same payload under each type. Arbitrary format support depends
on the operating system and SDL clipboard backend.
for _, mime in ipairs(system.get_clipboard_mime_types() or {}) do
print(mime)
end
system.set_clipboard('{"kind":"example"}', "application/json")
local data = system.get_clipboard("application/json")
The API transfers bytes; it does not encode an image or convert file formats
for you. For text/uri-list, use common.uri_list_to_paths() rather than
splitting or percent-decoding the payload by hand. The matching helpers
common.path_to_uri() and common.uri_to_path() convert individual paths and
file URIs. Plain document paste uses URI-list paths when no text payload is
available; this is not a universal native file-list API.
See the System API and Common API for format details.
File / Directory operations
These functions deal with files, directories and paths.
-- Returns a list of files and directories in a directory.
function system.list_dir(path: string): {string}, string end
-- Creates a new directory.
function system.mkdir(path: string): boolean, string end
-- Removes a directory.
function system.rmdir(path: string): boolean string end
-- Changes the current working directory (equivalent to the `cd` command)
function system.chdir(path: string): () end
-- Resolves the input path (removing all '.' and '..') into an absolute path.
function system.absolute_path(path: string): () end
-- Types of paths
local enum FileType
"file"
"dir"
end
-- The information for a path
local record FileInfo
modified: number
size: number
type: FileType
symlink: boolean
end
-- Returns information for a file or a directory.
function system.get_file_info(path: string): FileInfo, string end
system.get_file_info() returns a table with the following properties:
modified: Modification time in seconds (UNIX timestamp).size: Size of the file in bytes.type: Type of the path (Can befileordir).symlink: The directory is a symlink (Only set on Linux and on directories).
All the functions listed above except system.chdir() will return nil
followed by an error message when an error occurred.
system.chdir() will throw an error if an error occurred.
Examples:
-- DO NOT RUN THIS CODE!
-- the code and its outputs are purely for demonstration only,
-- and will not reflect your actual usage.
local dir = "../pragtical"
local dir_resolved = system.absolute_path(dir)
-- prints:
-- /home/user/gh/pragtical
print(dir_resolved)
-- prints:
-- .git => dir
-- docs => dir
-- .editorconfig => file
-- LICENSE => file
-- ...
-- pragtical => file
for i, d in ipairs(system.list_dir(dir_resolved)) do
local info = system.get_file_info(dir_resolved .. "/" .. d)
print(d .. " => " .. info.type)
end
-- create some directories
-- this will not work because system.mkdir() doesn't create directories
-- recursively, just like `mkdir` command without the `-p` option.
-- prints:
-- false No such file or directory
print(system.mkdir(dir_resolved .. "/1/2"))
-- these will work
-- prints:
-- true
print(system.mkdir(dir_resolved .. "/1"))
-- prints:
-- true
print(system.mkdir(dir_resolved .. "/1/2"))
-- system.rmdir() does not support removing non-empty dirs, so
-- this will not work and print an error
-- prints:
-- false Directory not empty
print(system.rmdir(dir_resolved .. "/1"))
-- instead, you should try to remove them recursively, making sure that each
-- directory is empty
-- prints:
-- true
print(system.rmdir(dir_resolved .. "/1/2"))
-- prints:
-- true
print(system.rmdir(dir_resolved .. "/1"))
Timing
system.get_time() returns time in seconds since Pragtical started.
It is a high-precision alternative to os.time().
function system.get_time(): number end
Examples:
-- prints:
-- 30148.079763237
print(system.get_time())
Window manipulation
Window helpers take a renwindow as their first argument. Use core.window
for the editor window; do not omit it or pass a width in its place.
local core = require "core"
system.set_window_mode(core.window, "normal")
system.set_window_size(core.window, 1280, 800, 80, 80)
local width, height, x, y = system.get_window_size(core.window)
local focused = system.window_has_focus(core.window)
Modes are "normal", "maximized", "minimized", and "fullscreen".
get_window_size returns logical width, height, x and y as separate results.
For renderer-pixel dimensions, use core.window:get_size(). This distinction
matters on scaled displays and when capturing a window with renderer.to_canvas.
system.set_window_opacity(core.window, opacity) accepts a value from 0 to 1
and returns whether the platform accepted it. set_window_title and
set_window_bordered also take the target window first. The editor manages
its own title and borderless decorations, so normal plugins should leave
those policies to core and configuration.
system.set_window_hit_test(window, title_height, controls_width, resize_border, interactive_rect) defines custom decoration regions in renderer coordinates.
The optional { x, y, w, h } rectangle keeps interactive title-bar contents
out of the drag region. Resize regions are inactive while maximized or
fullscreen. Calling it with only the window disables custom hit testing.
See the System API and Window API for complete signatures, native file dialogs, and renderer information.
Miscellaneous
system.exec() runs a command in the background.
It is useful if you just want to run a program and doesn't care about its
output and exit code.
If you want more features, consider using the Process API.
system.fuzzy_match() generates a score for sorting text based on relevance.
function system.exec(command: string): () end
function system.fuzzy_match(haystack: string,
needle: string,
file: boolean): number
end
system.exec() accepts a string containing a command to run.
This command will be run as system("<command> &") on POSIX platforms and
cmd /c "<command>" on Windows, so make sure that the command is escaped
properly.
system.fuzzy_match() takes in a haystack (a possible match) and a needle
(the string to search) to generate a similarity score.
If the score is 1, both strings are identical.
When the third argument is true, the matching will be done backwards as this
is more suitable for matching paths.