Wiki copymirror

This is a mirror of the wiki at pascal.chat. Editing, history and sign-in are there.

CudaText API

Intro

This is API for CudaText in Python.

Event plugins

To make plugin react to some program event, add method to class Command. For example, method "Command.on_save" will be called by program event "on_save" - if plugin is subscribed to that event. Event methods have param "ed_self": this is Editor object in which event occurred. This object is the same as object "ed" in most cases ("ed" always refers to focused editor), but in some cases event occurs in inactive editor, e.g. command "Save all tabs" calls event "on_save" for passive tabs.

Plugin can subscribe to events in several ways:

Event handlers (Command.on_nnnnn methods) return-value is ignored is many cases, but sometimes return value True or False has special meaning. Usually the False return value blocks propagation of event to other plugins, so don't return False if not necessary.

Events - General

Events - Tabs

Events - Editor

Events - Editor clicks

Events - State changes

Constants in "on_state":

Constants in "on_state_ed":

Events - Smart commands

Events - Panels

Events - Macros

Note: To run each on_macro item (with number) later, call ed.cmd(): number is command code, string after comma is command text.

Events priority

By default all events in all plugins have priority=0. So for any event, if 2+ plugins handle this event, they're called in the order on module names (e.g. cuda_aa, then cuda_dd, then cuda_mmm).

You may want to handle some event first. To change priority for your plugin event, write in install.inf event like this: "on_key+", "on_key++"... with any number of "+" up to 4. Each "+" makes higher priority. So first called "on_key" with maximal number of "+", last called "on_key" without "+".

Lazy events

By default all event handlers, except on_exit, are not "lazy". On_exit is always "lazy" - it means that it's called only for already loaded plugins. To make other event handlers lazy, write in install.inf event name with "~":

pascal
events=on_focus~,on_open~,on_state~

It's allowed to combine "+" and "~" suffixes, like on_focus~++

Callback parameter

Callback parameter is supported in several API functions: dlg_proc, timer_proc, menu_proc, button_proc etc. For all functions, "string form" of callback is supported. For most but not all functions, "callable form" is supported too.

Parameter can be in these forms:

For example:

Value after "info=" can be of any type, e.g. "info=20;" will pass int 20 to callback, "info='my';" will pass string 'my'.

Global functions

version

pascal
app_exe_version()

Returns version of program. String, 4 dot-separated numbers.

pascal
app_api_version()

Returns version of API. String, 3 dot-separated numbers.

Example of version check:

pascal
from cudatext import *
      if app_api_version() < '1.0.350':
          msg_box('Plugin needs newer program version', MB_OK+MB_ICONWARNING)

app_path

pascal
app_path(id)

Returns some file-system path. Possible values of "id":

app_proc

pascal
app_proc(id, text)

Performs application-wide action.

Parameter "text" is usually string, but can be of other types (bool, int, float, tuple/list of simple types).

app_proc - Getting handles

app_proc - Misc properties

app_proc - Search properties

Actions work with props of Find/Replace dialog, and props of low-level search engine. When user runs some search command in the dialog, dialog applies its props to the search engine. So most of the time, props of dialog and search engine are sync'ed. But they aren't sync'ed if user just typed new text in the dialog. They also aren't sync'ed if user runs some search command via Command Palette or hotkey (e.g. "find current word, previous").

app_proc - System

app_proc - Clipboard

app_proc - Plugin calls

app_proc - Hotkeys

app_proc - Python

app_proc - Themes

Notes:

Actions:

app_proc - Sessions

Session is a set of opened files + untitled tabs, with some properties of editors in these tabs, with group-indexes of tabs, with layout of groups. Session format is JSON.

(Feature of API version 1.0.418.) Session-related actions support specifying the JSON path, into which session will be saved/loaded. If you want to use this feature, add the JSON path to the session filename, after pipe-char "|", e.g. "/some/path/sessionname.cuda-session|/my/key". Here "/my/key" specifies the JSON path of 2 levels ("key" inside "my").

app_proc - Sidebar panels

General notes:

Actions:

app_proc - Bottom-bar panels

app_proc - Splitters

Splitter id:

Actions:

Positions of group splitters (G1, G2, G3, G4, G5) are determined by grouping view, in one view splitter may be horizontal with one parent panel, in other view - vertical with another parent panel. Detailed:

pascal
2VERT     t G1 t
    
    2HORZ     t
              G1
              t
    
    3VERT     t G1 t G2 t
    
    3HORZ     t
              G1
              t
              G2
              t
    
    1P2VERT    t G3 t
                   G2
                    t
    
    1P2HORZ    t
               G3
               t G2 t
    
    4VERT     t G1 t G2 t G3 t
    
    4HORZ     t
              G1
              t
              G2
              t
              G3
              t
    
    4GRID     t G1 t
              G3
              t G2 t
    
    6VERT     t G1 t G2 t G3 t G4 t G5 t
    
    6HORZ     t
              G1
              t
              G2
              t
              G3
              t
              G4
              t
              G5
              t
    
    6GRID     t G1 t G2 t
              G3
              t G1 t G2 t

app_proc - Show/Hide/Undock UI elements

Actions get/set state of UI elements, "value" must be False/True:

app_proc - Screen coordinates

Notes:

Actions:

app_log

pascal
app_log(id, text, panel="")

Performs action with standard panels in the bottom panel: Output, Validate, Console.

Possible values of "panel":

Possible values of "id" for Output/Validate panels:

Possible values of "id" for Console panel:

Example

For line "line 10 column 20: text message here" the following regex and indexes can be used:

app_idle

pascal
app_idle(wait=False)

Performs application's message-processing. If wait=True, also waits for new UI event.

emmet

pascal
emmet(id, text, p1="", p2="")

Performs action with embedded Emmet engine. Possible values of "id":

msg_box

pascal
msg_box(text, flags)

Shows modal message-box.

Param "text" is message text. Multi-line text with "\n" is supported.

Param "flags" is sum of button-value (OK, OK/Cancel, Yes/No etc):

and icon-value:

Returns int code of pressed button (returns ID_CANCEL if dialog cancelled):

msg_box_ex

pascal
msg_box_ex(caption, text, buttons, icon, focused=0)

Shows modal message-box with any number of buttons with any captions.

Returns int index of pressed button (0-based), or None of cancelled.

msg_status

pascal
msg_status(text, process_messages=False)

Shows given text in statusbar.

Param "process_messages": if True, function also does UI messages processing. It takes some time, it is needed to refresh status of Esc-key pressed. After call msg_status(..., True) you can get state of Esc-key pressed via PROC_GET_ESCAPE, otherwise plugin gets an old state, until UI messages are processed.

msg_status_alt

pascal
msg_status_alt(text, pause, pos=HINTPOS_CARET, x=0, y=0)

Shows given text in the floating tooptip.

dlg_input

pascal
dlg_input(prompt, text)

Shows modal dialog to input one string. Returns entered string or None if cancelled.

dlg_input_ex

pascal
dlg_input_ex(number, caption,
                  prompt1   , text1="", prompt2="", text2="", prompt3="", text3="",
                  prompt4="", text4="", prompt5="", text5="", prompt6="", text6="",
                  prompt7="", text7="", prompt8="", text8="", prompt9="", text9="",
                  prompt10="", text10="")

Shows modal dialog to enter 1 to 10 string fields at once. Returns list of strings or None if cancelled.

dlg_file

pascal
dlg_file(is_open, init_filename, init_dir, filters, caption="")

Shows "Open file" or "Save file as" modal dialog. Returns filename (or list of filenames) or None if cancelled.

Additional options:

dlg_dir

pascal
dlg_dir(init_dir, caption="Select folder")

Shows dialog to select folder path. Returns path (str), or None if cancelled.

dlg_menu

pascal
dlg_menu(id, items, focused=0, caption="", clip=0, w=0, h=0)

Shows menu-like dialog. Returns index of selected item (0-based), or None if cancelled.

Possible values of "id":

Additional flags to add to above "id" values:

Parameters:

dlg_color

pascal
dlg_color(value)

Shows select-color dialog with given initial color (int).

Returns int color, or None if cancelled.

dlg_hotkey

pascal
dlg_hotkey(title="")

Shows dialog to press single hotkey.

Returns str of hotkey (e.g. "F1", "Ctrl+Alt+B") or None if cancelled.

dlg_hotkeys

pascal
dlg_hotkeys(command, lexer="")

Shows dialog to configure hotkeys of internal command or plugin. Returns bool: OK pressed and hotkeys saved (to keys.json).

Param "command" can be:

Param "lexer" is optional lexer name. If not empty, dialog enables checkbox "For current lexer" and, if checkbox checked, saves hotkey to lexer-specific config "keys lexer NNNN.json".

dlg_custom

pascal
dlg_custom(title, size_x, size_y, text, focused=-1, get_dict=False)

Shows dialog with controls of many types. This is legacy API, it is recommended to use "dlg_proc" instead.

dlg_custom - Types of controls

Details:

dlg_custom - Properties of controls

Parameter "text" in "dlg_custom" is "\n"-separated items, one item per control. Each item is chr(1)-separated properties in the form "name=value". Possible properties:

dlg_custom - Property "items"

Possible values of "items" in "dlg_custom":

Action DLG_CTL_PROP_GET also returns key "items" (in the same format) for these controls: "listbox", "checklistbox", "listview", "checklistview".

dlg_custom - Property "columns"

Action DLG_CTL_PROP_GET also returns key "columns" in the same format.

Action DLG_CTL_PROP_SET, for "listview", allows both "items" (it sets columns) and "columns", and "columns" is applied last.

dlg_custom - Property "val"

dlg_custom - Properties "ex"

Properties "ex0"..."ex9" are specific to each control kind. They have different simple types (str, bool, int...). Note: for dlg_custom, bool values must be specified as "0"/"1", not as strings "True"/"False".

dlg_custom - Return value

Dialog is closed by clicking any button or by changing of any control which has "act=1".

dlg_custom - Notes

controls autosizes.png

dlg_proc

pascal
dlg_proc(id_dialog, id_action, prop="", index=-1, index2=-1, name="")

Advanced work with dialogs (forms). More advanced than "dlg_custom", forms can show in modal/nonmodal way, controls can change their value during form showing.

Often the function works with some control. To pass some control here, use one of 2 methods:

dlg_proc - Types of controls

Possible types of UI controls are described in "dlg_custom" topic. Additional types, supported only by "dlg_proc":

dlg_proc - Forms properties

dlg_proc - Forms events

These are also properties of forms.

How to get nice key description in "on_key_down", e.g. "Ctrl+Alt+Esc" from id_ctl=27 and data="ca":

pascal
str_key =\
          ('Meta+' if 'm' in data else '')+\
          ('Ctrl+' if 'c' in data else '')+\
          ('Alt+' if 'a' in data else '')+\
          ('Shift+' if 's' in data else '')+\
          app_proc(PROC_HOTKEY_INT_TO_STR, id_ctl)

dlg_proc - Control properties

Special properties for control "listview":

Special properties for controls "tabs", "pages", "toolbar", "statusbar":

dlg_proc - Control events - general

General events for all controls:

dlg_proc - Control events - for specific controls

Special events for controls "listview", "checklistview":

Special events for control "listbox_ex":

Special events for control "treeview":

dlg_proc - Control events - for editor control

Special events for control "editor"/"editor_edit"/"editor_combo":

dlg_proc - Signatures of event callbacks

Callbacks must be in forms shown in the topic #Callback_parameter. Callbacks can be functions (out of class) or class methods, it depends on the look of the callback (again see "Callback parameter" topic).

pascal
# for functions
    def my_callback(id_dlg, id_ctl, data='', info=''):
      pass
    
    # for class methods
    class Command:
      def my_callback(self, id_dlg, id_ctl, data='', info=''):
        pass

Parameters:

dlg_proc - Actions

Param "prop": it can be of any simple type (str, int, bool), also tuple/list (of any simple type), also dict (keys: str, values: simple type or tuple/list). Most used is dict. Example: prop={"cap": "...", "x": 10, "y": 10, "w": 600, "en": False}.

Param "id_dialog": int, form handle. Ignored only for DLG_CREATE action (pass 0 with it).

Possible values of "id_action":

dlg_proc - Anchors

Anchor is attaching of control's side to another control, or to the parent form, so control is auto positioned, initially and on form resize. Lazarus IDE has such Anchor Editor dialog:

Anchor Editor en.png

In this dialog you see, that all 4 sides of control attach to one of 3 sides of another control (or parent form).

To change anchors of control, set its properties: a_l, a_r, a_t, a_b. Initially left/top anchors are set (to the parent form).

Side value "[" aligns control to left/top side of target:

pascal
+--------+
             | target |
             +--------+
     
             +--------------+
             |   control    |
             +--------------+

Side value "]" aligns control to right/bottom side of target:

pascal
+--------+
              | target |
              +--------+
     
        +--------------+
        |   control    |
        +--------------+

Side value "-" centers control relative to target:

pascal
+--------+
              | target |
              +--------+
     
           +--------------+
           |   control    |
           +--------------+

Useful information in the Lazarus wiki: Anchor_Docking#Why_use_Anchors_instead_of_Align.3F.

Example: to attach "colorpanel" to the right side of form, clear left anchor (set to None), and add right/bottom anchors. This also sets spacing-aroung (padding) to 6 pixels.

pascal
#attach colorpanel to the right
      dlg_proc(id_form, DLG_CTL_PROP_SET, index=n, prop=
          { 'a_l': None, 'a_r': ('', ']'), 'a_b': ('', ']'), 'sp_a': 6  } )

dlg_proc - Example

Detailed demo plugin exists, it shows many dlg_proc actions, shows modal/nonmodal forms, uses callbacks, moves control by button click, moves control on form resize. It is in the CudaText repo with name "cuda_testing_dlg_proc".

dlg_commands

pascal
dlg_commands(options, title="", w=0, h=0)

Show commands dialog, which is customizable version of Commands (F1) dialog in CudaText.

Param "options" should be 0 or sum of int flags:

Params "w" and "h": if values>0, they are width and height of dialog.

Returns string if command selected, or None if cancelled.

file_open

pascal
file_open(filename, group=-1, options="")
    file_open((filename1, filename2), group=-1, options="")

Opens editor tab with given filename. If filename already opened, activates its tab.

First parameter can be 2-tuple / 2-list of string, to open 2 files in a single tab, in a splitted view. In this case, second filename won't be handled specially for zip file, picture file, binary file etc.

The case of empty filename: opens empty untitled tab. The case of empty filename1 and non-empty filename2 is not supported: it also opens empty untitled tab, not splitted.

Returns bool. True, if first filename is empty. Otherwise, returns True if first filename exists, and second filename is empty or exists. For zip file (only first filename is checked for it), returns True only if zip file contains valid CudaText add-on, and it was installed.

Note: "ed" is always the current editor, after file_open() current editor changes, and "ed" is the new cur editor.

Example opens untitled tab, and writes multi-line text to it:

pascal
file_open('')
      ed.set_text_all(text)

ed_handles

pascal
ed_handles()

Returns range object, which contains int handles of all editor UI-tabs. Pass each handle to Editor() to make editor object from handle.

Example which shows filenames of all tabs:

pascal
for h in ed_handles():
            e = Editor(h)
            print(e.get_filename())

Note: resulting int handles are virtual (small int numbers, not memory addresses). To get unique handle which is memory address of an editor, use PROP_HANDLE_SELF:

pascal
for h in ed_handles():
            e = Editor(h)
            print('Unique handle:', e.get_prop(PROP_HANDLE_SELF, ''))

ed_group

pascal
ed_group(index)

Returns Editor object for active editor in tab-group with given group-index. Returns None for incorrect index, or if no tabs in this group.

Index possible values: 0..5 (first 6 groups) and 6..8 (3 floating groups).

ini_read/ini_write

pascal
ini_read(filename, section, key, value)
    ini_write(filename, section, key, value)

Reads/writes single string from/to .ini file. Params:

On read: returns string value. On write: returns None.

ini_proc

pascal
ini_proc(id, filename, section="", key="")

Performs action on .ini file. Filename can be without path, this means that path of "settings" dir is used.

Possible values of "id":

lexer_proc

pascal
lexer_proc(id, value)

Perform some lexer-related action.

Possible values of "id":

tree_proc

pascal
tree_proc(id_tree, id_action, id_item=0, index=0, text="", image_index=-1, data="")

Perform action on treeview UI-control.

Possible values of "id_action":

Example of fast treeview filling , with locking to prevert treeview repaints:

pascal
tree_proc(h_tree, TREE_LOCK)
    
        for i in range(5000):
            tree_proc(h_tree, TREE_ITEM_ADD, index=-1, text='text')
    
        tree_proc(h_tree, TREE_UNLOCK)

Example of getting code-tree text range for some code-tree node. The following is the Console input commands and their outputs. Comments "### ..." are inserted by hands later.

pascal
### Step 1 - get handle of code-tree.
    
    >>> ct=app_proc(PROC_GET_CODETREE,'')
    >>> ct
    140556715678064
    
    ### Step 2 - enumerate code-tree root level.
    
    >>> =tree_proc(ct, TREE_ITEM_ENUM_EX, id_item=0)
    [{'id': 140556582911424, 'text': 'log', 'data': '', 'img': 5, 'sub_items': False},
    {'id': 140556582911904, 'text': 'Command', 'data': '', 'img': 1, 'sub_items': True}]
    
    ### Step 3 - enumerate sub-items of 'Command' node.
    ### We got last node with 'text'=='Command' and 'sub_items':True.
    ### Copy its id and pass it to param "id_item".
    
    >>> =tree_proc(ct, TREE_ITEM_ENUM_EX, id_item=140556582911904)
    [{'id': 140556582912064, 'text': '__init__', 'data': '', 'img': 5, 'sub_items': False},
    {'id': 140556582913344, 'text': 'on_focus', 'data': '', 'img': 5, 'sub_items': False},
    {'id': 140556582913504, 'text': 'work', 'data': '', 'img': 5, 'sub_items': False}]
    
    ### Step 4 - get text range of node.
    ### Copy id of some item and get its text range (x1, y1, x2, y2).
    
    >>> =tree_proc(ct, TREE_ITEM_GET_RANGE, id_item=140556582913504)
    (4, 102, 21, 180)

listbox_proc

pascal
listbox_proc(id_listbox, id_action, index=0, text="", tag=0)

Perform action on listbox UI-control.

Possible values of "id_action":

Listbox can have columns. It works only if listbox is not owner-drawn, and column sizes were set via LISTBOX_SET_COLUMNS. You must add separator-chars inside items to split items into columns. Column sizes are passed as list of int. Each list item can be:

Actions for columns:

Example adds 3 columns:

pascal
listbox_proc(h_list, LISTBOX_SET_COLUMN_SEP, text='|')
      listbox_proc(h_list, LISTBOX_SET_COLUMNS, text=[-50,0,-20]) # width<0 means value in??%
      listbox_proc(h_list, LISTBOX_ADD, index=-1, text='first|second|third')

canvas_proc

pascal
canvas_proc(id_canvas, id_action,
      text="", color=-1, size=-1,
      x=-1, y=-1, x2=-1, y2=-1,
      style=-1, p1=-1, p2=-1)

Performs action on canvas, ie drawing surface of some GUI control. Param "id_canvas" is handle of canvas of some GUI control. Special value 0 means testing empty panel, it appears at the top of app, when used.

Possible values of "id_action":

timer_proc

pascal
timer_proc(id, callback, interval, tag="")

Perform action on timers. Many different timers are allowed, they work at the same time, each unique callback makes new timer with its own interval. To stop some timer, you must specify the same callback as you did on starting that timer.

Possible values of "id":

Result is True if params are OK, False if params not OK (callback string incorrect, not created callback specified on stopping); or None (for unknown "id").

timer_proc - Callbacks

Callback param must be in one of these forms: #Callback_parameter.

Callbacks in timer_proc must be declared as:

pascal
#function
    def my(tag='', info=''):
      pass
    #method
    class Command:
      def my(self, tag='', info=''):
        pass

menu_proc

pascal
menu_proc(id_menu, id_action, command="", caption="", index=-1, hotkey="", tag="")

Perform action on menu items.

menu_proc - Menu id

Value of "id_menu" can be:

menu_proc - Command for new items

Value of "command" parameter for MENU_ADD can be:

menu_proc - Properties as dict

Some actions get dict for menu items. Note that some keys are optional, they are returned only when value is not the default (e.g. "vis" is returned only when visibility is off). Dict keys:

menu_proc - Actions

Possible values of "id_action":

menu_proc - Example

Example adds item "Misc" to the main menu, and sub-items: "About", separator, "Rename file" (from CudaExt plugin):

pascal
menuid = menu_proc('top', MENU_ADD, caption='Misc')
      n = menu_proc(menuid, MENU_ADD, command=2700, caption='About')
      n = menu_proc(menuid, MENU_ADD, caption='-')
      n = menu_proc(menuid, MENU_ADD, command='cuda_ext.rename_file', caption='Rename file')

Example creates popup-menu with one item and shows it at (x=100, y=100):

pascal
h = menu_proc(0, MENU_CREATE)
      menu_proc(h, MENU_ADD, command=2700, caption='About...')
      menu_proc(h, MENU_SHOW, command=(100,100) )

toolbar_proc

pascal
toolbar_proc(id_bar, id_action, text="", text2="", command=0, index=-1, index2=-1)

Perform action on toolbar UI control.

Param "id_bar": int handle of toolbar.

Param "id_action" possible values:

statusbar_proc

pascal
statusbar_proc(id_bar, id_action, index=-1, tag=0, value="")

Perform action on statusbar UI control.

Param "id_action" can be:

Notes:

imagelist_proc

pascal
imagelist_proc(id_list, id_action, value="")

Perform action on imagelist object.

Param "id_list" is int handle of imagelist. It is required for all actions, except IMAGELIST_CREATE, where it should be 0.

Possible values of "id_action":

image_proc

pascal
image_proc(id_image, id_action, value="")

Perform action on image object.

Param "id_image" is int handle of image. It is required for all actions, except IMAGE_CREATE, where it should be 0.

Possible values of "id_action":

button_proc

pascal
button_proc(id_button, id_action, value="")

Perform action on extended button (control type "button_ex").

Param "id_button" is int handle of button.

Possible values of "id_action":

Note: Toolbars contain several "button_ex" objects, which are anchored one to another (horizontally or vertically). You can also construct such toolbar by hands. API toolbar_proc() don't allow to specify kind of buttons, it sets kind from button properties.

finder_proc

pascal
finder_proc(id_finder, id_action, value="", setcaret=True)

Perform action on text search engine.

Param "id_finder" is int handle of search engine.

Possible values of "id_action":

more

Editor class

Editor class has methods to work with editor-controls.

Notes:

Carets

Editor.get_carets

pascal
get_carets()

Returns list of 4-tuples, each item is info about one caret: (PosX, PosY, EndX, EndY).

Example shows text of first caret's selection:

pascal
carets = ed.get_carets()
        x1, y1, x2, y2 = carets[0]
        if y2>=0:
            # sort (y,x) pairs
            if (y1, x1)>(y2, x2):
                x1, y1, x2, y2 = x2, y2, x1, y1
            s = ed.get_text_substr(x1, y1, x2, y2)
            msg_status('Selection: '+s)

Editor.set_caret

pascal
set_caret(posx, posy, endx=-1, endy=-1, id=CARET_SET_ONE, options=0)

Controls carets. Possible values of "id":

Param "options" must be 0 or sum of the following flags:

Text read/write

Editor.get_text_all

pascal
get_text_all()

Returns the entire editor text as string.

Notes:

Editor.set_text_all

pascal
set_text_all(text)

Sets the entire editor text, from given string. Text can have any line-breaks (LF, CRLF, CR, mixed).

Notes:

pascal
lines = text.splitlines()
      ed.replace_lines(0, ed.get_line_count()-1, lines)

Editor.get_line_len

pascal
get_line_len(index)

Returns length of internal line UTF-16 (without BOM) representation. It is not the same as len(ed.get_text_line(index)), if internal UTF-16 representation has surrogate-pairs. Returns None if index is incorrect.

Editor.get_text_line

pascal
get_text_line(index, max_len=0)

Returns single line (str) with given index (0-based). Without ending line-break char(s). Returns None if index is incorrect.

If param "max_len" is non-zero, and UTF-8 length of given line is greater than "max_len", function returns empty str. This allows to skip huge lines.

Editor.set_text_line

pascal
set_text_line(index, text)

Changes single line with given index (0-based) to given text. Text should be without line-breaks, because "\n" and "\r" chars will be replaced with "_".

Special "index" values:

Editor.get_text_substr

pascal
get_text_substr(x1, y1, x2, y2)

Returns substring from position (x1, y1) to bigger position (x2, y2). Coordinates x1 / x2 are in the UTF-16 internal representation of line.

Editor.delete

pascal
delete(x1, y1, x2, y2)

Deletes range from position (x1, y1) to bigger position (x2, y2). Coordinates x1 / x2 are in the UTF-16 internal representation of line.

Note: don't pass tuple from get_carets()[0], this tuple has not sorted positions (x1, y1) and (x2, y2), you need to sort them (first sort by y, then by x).

Example replaces selection of 1st caret with text:

pascal
x0, y0, x1, y1 = ed.get_carets()[0]
            if (y0, x0) >= (y1, x1): #note that y first
                x0, y0, x1, y1 = x1, y1, x0, y0
    
            ed.set_caret(x0, y0)
            ed.delete(x0, y0, x1, y1)
            ed.insert(x0, y0, text)

Editor.insert

pascal
insert(x, y, text)

Inserts given text at position (x, y). If param "y" is after the actual line-count, appends block to the end (even to final line without line-ending). Coordinate "x" is in the UTF-16 internal representation of line. Text can be multi-line, all CR LF will be converted to currently used line-breaks.

Returns 2-tuple (x, y) of position after inserted text. It is on the same line, if text is single line. Returns None if cannot insert.

Editor.replace

pascal
replace(x1, y1, x2, y2, text)

Replaces range from position (x1, y1) to bigger position (x2, y2), with new text. Coordinates x1 / x2 are in the UTF-16 internal representation of line.

Function does the same as delete+insert, but

Returns 2-tuple (x, y) of position after inserted text.

Editor.replace_lines

pascal
replace_lines(y1, y2, lines)

Deletes whole lines from index y1 to y2, then inserts new lines from specified list.

Returns bool: index y1 correct, replace done.

Selection

Editor.get_text_sel

pascal
get_text_sel()

Returns selected text for 1st caret (empty, if no selection).

Editor.get_sel_mode

pascal
get_sel_mode()

Returns current selection mode:

Editor.get_sel_lines

pascal
get_sel_lines()

Returns 2-tuple, indexes of first and last lines affected by first caret selection. Returns (-1,-1) if no selection.

Editor.get_sel_rect, Editor.set_sel_rect

pascal
get_sel_rect()
    set_sel_rect(x1, y1, x2, y2)

Returns/sets coords of column selection.

Returns 4-tuple (x1, y1, x2, y2). All 0 if no column selection.

Properties

Editor.get_line_count

pascal
get_line_count()

Returns number of lines.

Editor.get_char_count

pascal
get_char_count(max_chars, max_time)

Returns number of UTF-16 characters.

Each UTF-16 character in internal storage is counted as 1. Line-break is counted as 1, even for CR LF endings.

Editor.get_filename

pascal
get_filename(options="")

Returns filename (string) of the editor.

If param "options" contains char "*", the real file name is always returned, even in picture/binary viewer mode.

Editor.get_prop

pascal
get_prop(id, value="")

Returns editor's property.

Param "value" can be: str, number, bool (for bool it can be also "0"/"1"). Possible values of "id":

Editor.set_prop

pascal
set_prop(id, value)

Sets editor's property.

Param "value" can be: str, number, bool (for bool it can be also "0"/"1"), tuple of simple type. Possible values of "id":

props vs options

Many get_prop/set_prop ids correspond to CudaText options. List of corresponding pairs:

Editor.bookmark

pascal
bookmark(id, nline, nkind=1, ncolor=-1, text="", auto_del=True, show=True, tag=0)

Controls bookmarks. Possible values of "id":

Additional internal list Bookmarks2 exists, which holds list of background bookmarks. They have lower paint priority than usual bookmarks, so background bookmark is painted only if usual bookmark not exists. Actions BOOKMARK2_* are used for Bookmarks2 list, actions have the same meaning. Background bookmarks don't have gutter icon and mouse-over tooltip. They share the single setup with usual bookmarks.

Notes:

Editor.decor

pascal
decor(id, line=-1, tag=0, text="", color=0, bold=False, italic=False, image=-1, auto_del=True)

Controls decorations on gutter. It is used to show some visual marks, which look like bookmark icons, but independent of bookmarks. Possible values of "id":

Notes:

Editor.folding

pascal
folding(id, index=-1, item_x=-1, item_y=-1, item_y2=-1, item_staple=False, item_hint="", item_x2=0, item_tag=0)

Performs action on folding ranges. Possible values of "id":

Editor.get_sublexer_ranges

pascal
get_sublexer_ranges()

Returns list of ranges which belong to nested lexers (sublexers of current lexer for entire file, e.g. "JavaScript" inside "PHP", "CSS" inside "HTML"). Returns list of 5-tuples, or None if no ranges. Each tuple is:

Editor.get_token

pascal
get_token(id, index1=0, index2=0)

Returns info about lexer "tokens". "Token" is minimal text fragment for lexer, e.g. one identifier, one operator, one whole comment, one whole string. Each token has its color from lexer properties or color theme. Function returns None if no lexer is active in editor.

Possible values of "id":

Editor.get_wrapinfo

pascal
get_wrapinfo(param1=-1, param2=-1)

Gets info about wrapping of lines on screen. It allows to calculate, at which positions long lines are wrapped (when "word wrap mode" is on). It allows to see, which text parts are folded.

Returns list of dict, for specified lines range. Dict items has keys:

Parameter "param1" is the minimal line index (0-based) for which to return the information. Parameter "param2" is the maximal line index. Notes:

Editor.markers

pascal
markers(id, x=0, y=0, tag=0, len_x=0, len_y=0, line_len=0)

Controls markers (used e.g. in Snippets plugin). Possible values of "id":

Editor.attr

pascal
attr(id, tag=0, x=0, y=0, len=1,
         color_font=COLOR_NONE, color_bg=COLOR_NONE, color_border=COLOR_NONE,
         font_bold=0, font_italic=0, font_strikeout=0,
         border_left=0, border_right=0, border_down=0, border_up=0,
         show_on_map=False, map_only=0 )

Controls additional color attributes. Possible values of "id":

Notes:

Editor.hotspots

pascal
hotspots(id, tag=0, tag_str="", pos="")

Controls hotspot ranges. When mouse cursor moves in/out of hotspot, event on_hotspot is called.

Possible values of "id":

Misc

Editor.save

pascal
save(filename="", as_copy=False)

Saves editor's text to file. Returns bool: file was saved without errors.

Param "filename" (str): suggested filename to save to.

Param "as_copy" (bool):

Notes:

Editor.cmd

pascal
cmd(code, text="")

Runs any command in editor by its integer code. See possible codes in module "cudatext_cmd".

Param "text" is needed only for rare commands, mainly for "cCommand_TextInsert".

Notes:

Editor.focus

pascal
focus()

Focuses editor-control (and activates editor's ui-tab if editor is contained in ui-tab).

Notes:

Editor.lock, Editor.unlock

pascal
lock()
    unlock()

Functions lock, then unlock editor. "Locked" editor is not painted and shows only hourglass (or another) icon.

Call "lock" increases counter, "unlock" decreases this counter (it's safe to call "unlock" more times, counter will be 0). When counter is >0, editor is locked.

Editor.convert

pascal
convert(id, x, y, text="")

Converts something in editor. Possible values of "id":

Returns None if params are incorrect, or cannot calculate the result.

Editor.complete

pascal
complete(text, len1, len2, selected=0, alt_order=False)

Shows auto-completion listbox with given items.

Function returns None and listbox stays open. When user chooses listbox item, its data is inserted.

Note:

If an item begins with "<html>", #HTML formatting is allowed in this item.

Editor.complete_alt

pascal
complete_alt(text, snippet_id, len_chars, selected=0)

Shows alternative completion listbox. This allows to insert complex snippets, not only simple words.

Function returns None and listbox stays open. When user chooses listbox item, event "on_snippet" is called in plugin.

Function params:

After user has chosen some item in the completion listbox, event "on_snippet" will be called with parameters:

If an item begins with "<html>", #HTML formatting is allowed in this item.

Editor.gap

pascal
gap(id, num1, num2, tag=-1, size=0, color=COLOR_NONE)

Performs action on inter-line gaps (they don't overlap text above/below). Possible values of "id":

Example plugin:

pascal
from cudatext import *
    class Command:
        def run(self):
            for i in range(ed.get_line_count()//2):
                self.do_gap(i*2)
    
        def do_gap(self, num):
            id_bitmap, id_canvas = ed.gap(GAP_MAKE_BITMAP, 600, 50)
            canvas_proc(id_canvas, CANVAS_SET_BRUSH, color=0xa0ffa0)
            canvas_proc(id_canvas, CANVAS_POLYGON, '200,0,300,30,200,50')
            canvas_proc(id_canvas, CANVAS_SET_BRUSH, color=0xffffff, style=BRUSH_CLEAR)
            canvas_proc(id_canvas, CANVAS_TEXT, x=230, y=10, text='gap %d'%(num+1))
            canvas_proc(id_canvas, CANVAS_SET_BRUSH, color=0xffffff, style=BRUSH_SOLID)
            ed.gap(GAP_ADD, num, id_bitmap)

Editor.dim

pascal
dim(id, index=0, index2=0, value=100)

Controls dim (shade, fade) ranges, which blend text font color with background color. Dim value is 0..255, 0 means "no effect", 255 means "text is transparent".

Possible values of "id":

Editor.action

pascal
action(id, param1="", param2="", param3="")

Performs some action in editor. Possible values of "id":

Editor.micromap

pascal
micromap(id, param1=0, param2=0, param3=0)

Controls editor's micromap. Possible values of "id":

HTML formatting

Several APIs support rendering of HTML-formatted strings. Small subset of HTML tags is supported:

pascal
<b>bold style</b>
    <i>italic style</i>
    <u>underline style</u>
    <s>strikeout style</s>
    <font color="#AABBCC">colored font</font>
    <font color="#ABC">colored font</font>

TreeHelpers

CudaText contains built-in support for TreeHelpers. They build code-tree for additional lexers. TreeHelpers must be plugins, which have special install.inf file (Ini format).

Section "info":

Section(s) "treehelper" followed by any string (e.g. "treehelper1"):

File init.py must contain getter method(s), referenced by install.inf. Getter has signature (with any name):

pascal
def get_headers(filename, lines)

Getter must return list of tuples: (pos, level, caption, icon).

Getter can also return value not of "list" type, in this case CudaText will not update the code-tree.

TreeHelpers can be written in Pascal too. This way they will work much faster. To write/debug a TreeHelper in Pascal, use the project "treehelpertester" in the CudaText GitHub repo. These TreeHelpers were rewritten from Python to Pascal and are built-in now:

Linters

Linters are 2nd-level plugins for CudaLint plugin. CudaLint was ported from SublimeLinter 3, and its linters should be ported from SublimeLinter linters. Here is example:

To see how to port, compare files "linter.py". Other files must be added like in other CudaLint linters.

Tech info

Format of text for cmd_MouseClick

Text is "X,Y" where X/Y are position of caret relative to top-caret (other carets removed when command runs). If Y is 0, X is addition to caret's x. If Y not 0, Y is addition to caret's y, and X is absolute caret's x.

Finder options as string

Some APIs allow to specify finder options as a string. Such string can have the following chars:

Format of text for cmd_FinderAction

Text is chr(1) separated items:

Format of serialized Undo

Text is "\n"-separated undo (or redo) items. Each undo item is tab-separated elements:

1. Editing action, enum 0..6:

2. Index of changed line (not for mouse clicks), 0-based.

3. End-of-line kind, enum 0..3:

4. Line state, enum 0..3:

5. Several chr(1)-separated items:

5.1. Caret position(s). Carets are ";"-separated and x/y coords (32-bit) are ","-separated. "x_begin,y_begin;x_end,y_end;" for 1 caret.

5.2. Marker position(s). 64-bit numbers ","-separated, where each marker is encoded as 7 numbers:

5.3. Global action counter, 32-bit integer. Several undo-items can have the same global action counter.

5.4. OS tick counter, 64-bit integer, in milliseconds (shows how much time is passed betweem items).

5.5. Command code, 32-bit integer which possible values are contained in Python module cudatext_cmd. Value=0 means "command code is not set".

5.6. Caret position(s) for the paired editor (which is visible when menu item "View / Split tab" is called in CudaText).

5.7. Marker position(s) for the paired editor.

6. Soft-mark flag, number 0/1 (boolean). Logic of soft/hard marks is described in the wiki page ATSynEdit.

7. Hard-mark flag, number 0/1.

8. Line text, in UTF-8. This text can have tab-chars, tab-char is not separator in this last item.

API of 3rd-party plugins

API of Options Editor

Options Editor plugin (preinstalled in CudaText) has API which allows to call its dialog with custom options. Example shows dialog with 4 custom options, with custom title. Options which user changed in dialog will be saved to user.json or lexer-specific config.

pascal
import os
    import cudax_lib as appx
    import cuda_options_editor as op_ed
    
    fn_config = 'cuda_my_plugin.json' # without path!
    meta_info = [
            {
                "opt": "my_opt_1",
                "cmt": ["Comment line 1",
                        "Comment line 2",
                        "Comment line 3"],
                "def": True,        # Default value
                "frm": "bool",      # Value type from
                                    #   bool float int str - simple types
                                    #   font - font name
                                    #   font-e - font name or empty
                                    #   hotk - hotkey
                                    #   file - file path
                                    #   strs  - list of str
                                    #   int2s - dict int to str
                                    #   str2s - dict str to str
                "chp": "MySection"  # Section (can be empty)
            },
            {   "opt": "my_opt_2",
                "cmt": ["Comment"],
                "def": "v1",
                "frm": "strs",
                "lst": ["v1", "v2"]
            },
            {   "opt": "my_opt_3",
                "cmt": ["Comment"],
                "def": 11,
                "frm": "int2s",
                "dct": [[11, "value for 11"], [22, "value for 22"]]
            },
            {   "opt": "my_opt_4",
                "cmt": ["Comment"],
                "def": "a",
                "frm": "int2s",
                "dct": [["a", "value for a"], ["b", "value for b"]]
            }
            ]
    
    class Command:
        def get_opt(path, val):
            return appx.get_opt(path, val, user_json=fn_config)
    
        def config(self):
            subset = '' # section in user.json, if user.json is used
            title = 'My Plugin Options'
            how = {'hide_lex_fil': True, 'stor_json': fn_config}
            op_ed.OptEdD(
                path_keys_info = meta_info,
                subset = subset,
                how = how
                ).show(title)
            do_load_plugin_options() # some plugin function to reread options

This will show:

cudatext options editor.png

Options Editor stores values in JSON with trailing comma, so to read these options, plugin must use cudax_lib.get_opt() instead of json.load().

API of Project Manager

Opening project from plugin

To open a project, you need to call the Project Manager's method Command.action_open_project, which can be done via action PROC_EXEC_PLUGIN. For example, this code loads the project "/home/user/tt.cuda-proj":

pascal
app_proc(PROC_EXEC_PLUGIN, 'cuda_project_man,action_open_project,/home/user/tt.cuda-proj')

Getting current project info

Project Manager plugin (preinstalled in CudaText) gives API to read properties of currently opened project. It has global variable global_project_info , which is dict with keys:

Example gets list of root project items:

pascal
import cuda_project_man as p
         nodes = p.global_project_info['nodes']

Result without opened project:

pascal
>>> p.global_project_info
      {'filename': '', 'nodes': [], 'vars': [], 'mainfile': ''}

Result with opened folder in unsaved project:

pascal
>>> p.global_project_info
      {'filename': '', 'nodes': ['/home/name/datadir'], 'vars': [], 'mainfile': ''}

Result with opened folder in saved project:

pascal
>>> p.global_project_info
      {'filename': '/home/name/test.cuda-proj', 'nodes': ['/home/name/datadir'], 'vars': [], 'mainfile': ''}

Also global function project_variables() exists, which is handy wrapper around global_project_info. It returns dict with keys:

Its code currently is:

pascal
def project_variables():
        res = collections.OrderedDict()
        data = global_project_info
        res['ProjDir'] = os.path.dirname(data.get('filename', ''))
    
        fn = data.get('mainfile', '')
        res['ProjMainFile'] = fn
        res['ProjMainFileNameOnly'] = os.path.basename(fn)
        res['ProjMainFileNameNoExt'] = '.'.join(os.path.basename(fn).split('.')[0:-1])
    
        data = global_project_info.get('vars', [])
        for item in data:
            s1, s2 = item.split('=', maxsplit=1)
            res[s1] = s2
        return res

Questions

How plugin can fill code-tree

How plugin can show tooltips on mouse-over

How to make auto-completion plugin

Good example is "HTML Class Complete": https://github.com/CudaText-addons/cuda_html_class_complete

Show me the template of complex plugin with side-panel and bottom-panel

Here is the example plugin: https://github.com/CudaText-addons/cuda_r_plugin . It provides:

History

1.0.167

1.0.168

1.0.169

1.0.170

1.0.171

1.0.172

1.0.173

1.0.174

1.0.175

1.0.176

1.0.177

1.0.178

1.0.179

1.0.180

1.0.181

1.0.182

1.0.183

1.0.184

1.0.185 (app 1.11.0)

1.0.186 (app 1.12.0)

1.0.187 (app 1.12.2)

1.0.188 (app 1.13.0)

1.0.189 (app 1.13.1)

1.0.190 (app 1.14.0)

1.0.191 (app 1.14.2)

1.0.192 (app 1.14.8)

1.0.193 (app 1.15.0)

1.0.194 (app 1.15.4)

1.0.195 (app 1.15.5)

1.0.196 (app 1.16.2)

1.0.197 (app 1.17.2)

1.0.198 (app 1.18.0)

1.0.199 (app 1.19.2)

1.0.200 (app 1.20.2)

1.0.201 (app 1.21.0)

1.0.202 (app 1.23.0)

1.0.203 (app 1.23.4)

1.0.204 (app 1.23.5)

1.0.205 (app 1.24.1)

1.0.206 (app 1.24.2)

1.0.207 (app 1.25.1)

1.0.208 (app 1.26.2)

1.0.208 (app 1.27.2)

1.0.210 (app 1.29.0)

1.0.211 (app 1.32.0)

1.0.212 (app 1.32.2)

1.0.213 (app 1.32.3)

1.0.214 (app 1.32.4)

1.0.215 (app 1.34.1)

1.0.216 (app 1.34.2)

1.0.217 (app 1.34.4)

1.0.218 (app 1.38.0)

1.0.219 (app 1.38.1)

1.0.220 (app 1.38.2)

1.0.221 (app 1.38.3)

1.0.222 (app 1.38.5)

1.0.223 (app 1.39.1)

1.0.224 (app 1.39.5)

1.0.225 (app 1.40.0)

1.0.226 (app 1.40.1)

1.0.227 (app 1.40.2)

1.0.228 (app 1.40.7)

1.0.229 (app 1.43.0)

1.0.230 (app 1.44.0)

1.0.231 (app 1.45.5)

1.0.232 (app 1.46.2)

1.0.233 (app 1.47.0)

1.0.233 (app 1.47.1)

1.0.234 (app 1.47.5)

1.0.235 (app 1.48.2)

1.0.236 (app 1.48.3)

1.0.237 (app 1.49.1)

1.0.238 (app 1.49.5)

1.0.239 (app 1.51.2)

1.0.240 (app 1.52.1)

1.0.242 (app 1.53.6)

1.0.243 (app 1.55.0)

1.0.244 (app 1.55.1)

1.0.245 (app 1.55.3)

1.0.246 (app 1.56.1)

1.0.247 (app 1.56.3)

1.0.248 (app 1.56.6)

1.0.249 (app 1.57.5)

1.0.250 (app 1.57.7)

1.0.251 (app 1.57.8)

1.0.252 (app 1.58.1)

1.0.253 (app 1.59.0)

1.0.254 (app 1.60.1)

1.0.255 (app 1.60.5)

1.0.256 (app 1.60.7)

1.0.257 (app 1.62.0)

1.0.258 (app 1.62.5)

1.0.259 (app 1.63.5)

1.0.260 (app 1.63.6)

1.0.261 (app 1.64.2)

1.0.262 (app 1.64.4)

1.0.263 (app 1.65.6)

1.0.264 (app 1.66.7)

1.0.265 (app 1.66.9)

1.0.266 (app 1.67.0)

1.0.267 (app 1.70.3)

1.0.268 (app 1.71.5)

1.0.269 (app 1.71.6)

1.0.270 (app 1.72.1)

1.0.271 (app 1.73.1)

1.0.272 (app 1.74.0)

1.0.273 (app 1.74.1)

1.0.274 (app 1.74.7)

1.0.275 (app 1.76.0)

1.0.276 (app 1.76.6)

1.0.277 (app 1.77.2)

1.0.278 (app 1.77.4)

1.0.279 (app 1.77.6)

1.0.280 (app 1.77.6)

1.0.281 (app 1.78.5)

1.0.282 (app 1.78.6)

1.0.283 (app 1.78.7)

1.0.284 (app 1.79.0)

1.0.285 (app 1.79.1)

1.0.286 (app 1.79.2)

1.0.287 (app 1.79.3)

1.0.288 (app 1.81.0)

1.0.289 (app 1.81.2)

1.0.290 (app 1.81.3)

1.0.291 (app 1.83.0)

1.0.292 (app 1.83.2)

1.0.293 (app 1.84.2)

1.0.294 (app 1.84.5)

1.0.295 (app 1.84.6)

1.0.296 (app 1.85.1)

1.0.297 (app 1.85.1)

1.0.298 (app 1.85.2)

1.0.299 (app 1.86.0)

1.0.300 (app 1.86.2)

1.0.301 (app 1.86.2)

1.0.302 (app 1.86.3)

1.0.303 (app 1.87.5)

1.0.304 (app 1.87.5)

1.0.305 (app 1.87.6)

1.0.306 (app 1.88.2)

1.0.307 (app 1.88.6)

1.0.310 (app 1.88.8)

1.0.312 (app 1.89.1)

1.0.313 (app 1.89.2)

1.0.314 (app 1.89.4)

1.0.315 (app 1.89.6)

1.0.316 (app 1.90.0)

1.0.317 (app 1.91.1)

1.0.318 (app 1.92.0)

1.0.319 (app 1.92.5)

1.0.320 (app 1.94.0)

1.0.321 (app 1.94.5)

1.0.322 (app 1.96.2)

1.0.323 (app 1.97.1)

1.0.324 (app 1.97.2)

1.0.325 (app 1.97.5.2)

1.0.326 (app 1.98.3)

1.0.327 (app 1.99.5)

1.0.328 (app 1.100.5)

1.0.329 (app 1.101.0)

1.0.330 (app 1.102.2)

1.0.331 (app 1.102.6)

1.0.332 (app 1.102.7)

1.0.333 (app 1.103.2)

1.0.334 (app 1.104.1)

1.0.335 (app 1.104.5)

1.0.336 (app 1.105.1)

1.0.337 (app 1.105.1)

1.0.338 (app 1.105.2)

1.0.339 (app 1.105.3)

1.0.340 (app 1.105.3)

1.0.341 (app 1.105.6)

1.0.342 (app 1.106.1)

1.0.343 (app 1.106.8)

1.0.344 (app 1.106.8)

1.0.345 (app 1.107.0)

1.0.346 (app 1.107.2)

1.0.347 (app 1.107.6)

1.0.348 (app 1.108.0)

1.0.349 (app 1.108.6)

1.0.350 (app 1.110.0)

1.0.351 (app 1.114.0)

1.0.352 (app 1.115.6)

1.0.353 (app 1.115.7)

1.0.354 (app 1.117.2)

1.0.355 (app 1.119.5)

1.0.357 (app 1.121.4)

1.0.358 (app 1.123.0)

1.0.360 (app 1.123.0)

1.0.362 (app 1.123.2)

1.0.364 (app 1.123.5)

1.0.365 (app 1.124.1)

1.0.366 (app 1.124.1)

1.0.367 (app 1.124.3)

1.0.368 (app 1.125.0)

1.0.369 (app 1.125.0)

1.0.370 (app 1.128.1)

1.0.371 (app 1.128.5)

1.0.372 (app 1.128.5)

1.0.373 (app 1.129.4)

1.0.374 (app 1.129.7)

1.0.375 (app 1.129.8)

1.0.376 (app 1.130.1)

1.0.377 (app 1.130.5)

1.0.379 (app 1.131.0)

1.0.381 (app 1.131.1)

1.0.383 (app 1.132.0)

1.0.385 (app 1.132.0)

1.0.388 (app 1.132.9)

1.0.390 (app 1.133.0)

1.0.391 (app 1.133.1)

1.0.392 (app 1.133.2)

1.0.393 (app 1.133.6)

1.0.394 (app 1.134.1.2)

1.0.397 (app 1.135.2)

1.0.398 (app 1.136.1)

1.0.399 (app 1.136.2)

1.0.401 (app 1.137.1)

1.0.402 (app 1.137.3)

1.0.403 (app 1.137.3)

1.0.404 (app 1.137.7)

1.0.405 (app 1.139.0)

1.0.406 (app 1.139.1)

1.0.407 (app 1.139.2)

1.0.408 (app 1.140.6)

1.0.409 (app 1.142.0)

1.0.410 (app 1.142.1)

1.0.411 (app 1.145.1)

1.0.412 (app 1.146.1)

1.0.413 (app 1.148.1)

1.0.414 (app 1.149.4)

1.0.415 (app 1.153.1)

1.0.416 (app 1.157.2)

1.0.417 (app 1.157.6)

1.0.418 (app 1.158.3)

1.0.419 (app 1.159.0)

1.0.420 (app 1.159.3)

1.0.421 (app 1.163.2)

1.0.422 (app 1.166.0)

1.0.423 (app 1.166.1)

1.0.424 (app 1.166.4)

1.0.425 (app 1.166.6)

1.0.426 (app 1.167.2)

1.0.427 (app 1.169.1)

1.0.428 (app 1.169.5)

1.0.429 (app 1.170.1)

1.0.430 (app 1.171.0)

1.0.431 (app 1.171.5)

1.0.432 (app 1.172.1)

1.0.433 (app 1.173.0)

1.0.435 (app 1.176.5)

1.0.436 (app 1.178.0)

1.0.437 (app 1.180.5)

1.0.438 (app 1.182.0)

1.0.439 (app 1.184.0)

1.0.441 (app 1.185.5)

1.0.442 (app 1.186.1)

1.0.443 (app 1.186.5)

1.0.444 (app 1.189.0)

1.0.445 (app 1.190.1)

1.0.446 (app 1.195.1)

1.0.447 (app 1.196.3)

1.0.448 (app 1.197.0)

1.0.449 (app 1.206.0)

1.0.450 (app 1.206.4)

1.0.451 (app 1.206.6)

1.0.452 (app 1.209.0)

1.0.453 (app 1.210.5)

1.0.454 (app 1.211.3)

1.0.455 (app 1.212.1)

1.0.456 (app 1.214.2)

1.0.457 (app 1.214.7)

1.0.458 (app 1.214.7.2)

1.0.459 (app 1.215.0)

1.0.460 (app 1.216.0)

1.0.461 (app 1.218.0)

1.0.462 (app 1.219.0)

1.0.463 (app 1.222.0)

1.0.464 (app 1.223.6)


From the Free Pascal wiki, page "CudaText API", as the Internet Archive kept it on 2025-06-17, last changed on 2025-05-11. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 1, last changed by WikiArchive .