Sign in Join
Wiki copytemporary

Revision 1 of 2, by DomingoGP on 1-23-2022. The page as it is now.

Editor Macros PascalScript

General

The PascalScript macro functionality is available in Lazarus 1.1 and later. To use the feature you have to install the package EditorMacroScript, which includes the Pascal Script package. Pascal Script is provided by REM Objects. A minimum package is provided with the Lazarus 1.1 distribution.

Availability

This functionality is only available on selected platforms/architectures:

Simple actions

All simple Keyboard actions are represented as follows:

ecLeft;
Move Caret one to the left (in the editor that invoked the macro)

ecChar('a');
Inserts an 'a'

See the unit SynEditKeyCmds in package SynEdit, and IDECommands in IDEIntf for a full list. Or use the Recorder to get the names of actions.

Functions

pascal
    Function MessageDlg( const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint ): Integer;
    Function MessageDlgPos( const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint; X, Y: Integer): Integer;
    Function MessageDlgPosHelp( const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint; X, Y: Integer; const HelpFileName: string): Integer;
    Procedure ShowMessage( const Msg: string );
    Procedure ShowMessagePos( const Msg: string; X, Y  Integer );
    Function InputBox( const ACaption, APrompt, ADefault: string): string;
    Function InputQuery( const ACaption, APrompt: string; var Value: string): Boolean;

Objects provided

Scripts can refer to the invoking SynEdit via the identifier "Caller".

Caller: TSynEdit

The following methods and properties are available:

Caret

pascal
    property CaretX: Integer;
    property CaretY: Integer;
    property CaretXY: TPoint;
    property LogicalCaretXY: TPoint;
    property LogicalCaretX: Integer;
    procedure MoveCaretIgnoreEOL(const NewCaret: TPoint);
    procedure MoveLogicalCaretIgnoreEOL(const NewLogCaret: TPoint);

Selection

pascal
    property BlockBegin: TPoint;
    property BlockEnd: TPoint;
    property SelAvail: Boolean; // read only
    property SelText: string;
    property SelectionMode: TSynSelectionMode;
    procedure ClearSelection;
    procedure SelectAll;
    procedure SelectToBrace;
    procedure SelectWord;
    procedure SelectLine(WithLeadSpaces: Boolean);
    procedure SelectParagraph;

Search/Replace

pascal
    function SearchReplace(const ASearch, AReplace: string; AOptions: TSynSearchOptions): integer;
    function SearchReplaceEx(const ASearch, AReplace: string; AOptions: TSynSearchOptions; AStart: TPoint): integer;

    TSynSearchOptions = set of
    ( ssoMatchCase, ssoWholeWord,
      ssoBackwards,
      ssoEntireScope, ssoSelectedOnly,  // Default is From Caret to End-of-text (or begin-of-text if backward) 
      ssoReplace, ssoReplaceAll,        // Otherwise the function does a search only
      ssoPrompt,                        // Show the prompt before replacing
      ssoSearchInReplacement,           // continue search-replace in replacement (with ssoReplaceAll) // replace recursive
      ssoRegExpr, ssoRegExprMultiLine,
      ssoFindContinue                   // Assume the current selection is the last match, and start search behind selection
                                        // (before if ssoBackward) // Default is to start at caret (Only SearchReplace / SearchReplaceEx has start/end param)
    );

Returns the number of replacements done. When Searching, returns 1 if found, 0 if not found. If found the match will be selected (use BlockBegin/End).

pascal
  if Caller.SearchReplace('FindMe', ' ', []) > 0 then begin
    // Selection is set to the first occurrence of FindMe (searched from position of caret)
  end;

Text

pascal
    property Lines[Index: Integer]: string; // read only
    property LinesCount: integer; // read only   (new for Lazarus 2.2)
    property LineAtCaret: string;  // read only
    procedure InsertTextAtCaret(aText: String; aCaretMode : TSynCaretAdjustMode);
    property TextBetweenPoints[aStartPoint, aEndPoint: TPoint]: String              // Logical Points
    procedure SetTextBetweenPoints(aStartPoint, aEndPoint: TPoint;
                                   const AValue: String;
                                   aFlags: TSynEditTextFlags = [];
                                   aCaretMode: TSynCaretAdjustMode;
                                   aMarksMode: TSynMarksAdjustMode;
                                   aSelectionMode: TSynSelectionMode
                                  );

Clipboard

pascal
    procedure CopyToClipboard;
    procedure CutToClipboard;
    procedure PasteFromClipboard;
    property CanPaste: Boolean     // read only

Logical / Physical

pascal
    function LogicalToPhysicalPos(const p: TPoint): TPoint;
    function LogicalToPhysicalCol(const Line: String; Index, LogicalPos
                              : integer): integer;
    function PhysicalToLogicalPos(const p: TPoint): TPoint;
    function PhysicalToLogicalCol(const Line: string;
                                  Index, PhysicalPos: integer): integer;
    function PhysicalLineLength(Line: String; Index: integer): integer;

ClipBoard: TClipBoard

pascal
    property AsText: String;

Available Macros / Downloads

<table> <caption>Editor macros</caption> <tbody> <tr> <td><p><strong>Description</strong></p></td> <td><p><strong>Link</strong></p></td> </tr> <tr> <td><p><strong>Column Align Source code</strong></p> <p>A macro that aligns selected code to a specific token. It looks for a specific token in each selected line, and aligns each occurrence of it.</p> <p>Select the 3 lines. If the selection starts right before the ":" then the ":" will be detected. A prompt will ask you to confirm the ":". Then all ":" will be aligned. (If you use a word for alignment, please note, that it will be matched regardless of word boundaries)</p> <p>You can vertically align things like := or // or (</p> <table> <tbody> <tr> <td><div class="sourceCode" id="cb1"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a> foo := <span class="dv">1</span>;</span> <span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> something := <span class="dv">2</span>;</span> <span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> x := -<span class="dv">3</span>;</span></code></pre></div></td> <td><div class="sourceCode" id="cb2"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a> foo := <span class="dv">1</span>;</span> <span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> something := <span class="dv">2</span>;</span> <span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> x := -<span class="dv">3</span>;</span></code></pre></div></td> </tr> </tbody> </table></td> <td><p>Editor Macro Column Align Source</p></td> </tr> <tr> <td><p><strong>Count array elements</strong></p> <p>A macro to count the boundaries in an array constant.</p> <table> <tbody> <tr> <td><div class="sourceCode" id="cb3"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a> <span class="kw">const</span> foo: <span class="kw">array</span> [<span class="dv">0.</span>.] <span class="kw">of</span> <span class="dt">integer</span> = (</span> <span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a> <span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>,</span> <span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> <span class="dv">4</span></span> <span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a> );</span></code></pre></div></td> <td><div class="sourceCode" id="cb4"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a> <span class="kw">const</span> foo: <span class="kw">array</span> [<span class="dv">0..3</span>] <span class="kw">of</span> <span class="dt">integer</span> = (</span> <span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a> <span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>,</span> <span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a> <span class="dv">4</span></span> <span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a> );</span></code></pre></div></td> </tr> </tbody> </table></td> <td><p>See <a href="http://forum.lazarus.freepascal.org/index.php/topic,27186.msg167883.html#msg167883">http://forum.lazarus.freepascal.org/index.php/topic,27186.msg167883.html#msg167883</a> for counting array elements.</p></td> </tr> <tr> <td><p><strong>Add PasDoc for function declaration</strong></p> <p>Comments a procedure/function in <a href="https://github.com/pasdoc/pasdoc/wiki">PasDoc</a> format</p> <p>Example: Executing the macro with the caret in the line of function declaration will insert the comment before.</p> <table> <tbody> <tr> <td><div class="sourceCode" id="cb5"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">function</span> AddRadioButton(<span class="kw">const</span> aCaption: <span class="dt">string</span>; aChecked: <span class="dt">boolean</span> = <span class="kw">False</span>): TCheckBox;</span></code></pre></div></td> <td><div class="sourceCode" id="cb6"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="co">{ Description</span></span> <span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="co"> @param(aCaption description )</span></span> <span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="co"> @param(aChecked description )</span></span> <span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="co"> @returns( description )</span></span> <span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="co"> @raises( none )</span></span> <span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="co">}</span></span> <span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="kw">function</span> AddRadioButton(<span class="kw">const</span> aCaption: <span class="dt">string</span>; aChecked: <span class="dt">boolean</span> = <span class="kw">False</span>): TRadioButton;</span></code></pre></div></td> </tr> </tbody> </table> <p><a href="https://github.com/DomingoGP/LazarusMacroPasDoc"><span>https://github.com/DomingoGP/LazarusMacroPasDoc</span></a></p></td> <td><p><a href="https://github.com/DomingoGP/LazarusMacroPasDoc/blob/master/MacroPasDocLazarus.txt">MacroPasDocLazarus.txt</a></p></td> </tr> <tr> <td><p><strong>Sort selected lines</strong></p> <p>There are two macros, one with the normal alphabetical order and another that orders by type</p> <table> <tbody> <tr> <td><div class="sourceCode" id="cb7"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a> c:<span class="dt">integer</span>;</span> <span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a> b:<span class="dt">integer</span>;</span> <span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a> d:<span class="dt">boolean</span>;</span> <span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a> a:<span class="dt">boolean</span>;</span></code></pre></div></td> <td><div class="sourceCode" id="cb8"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a> <span class="co">//normal sorting</span></span> <span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a> a:<span class="dt">boolean</span>;</span> <span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a> b:<span class="dt">integer</span>;</span> <span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a> c:<span class="dt">integer</span>;</span> <span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a> d:<span class="dt">boolean</span>;</span></code></pre></div></td> <td><div class="sourceCode" id="cb9"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a> <span class="co">//sorting by type</span></span> <span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a> d:<span class="dt">boolean</span>;</span> <span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a> a:<span class="dt">boolean</span>;</span> <span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a> c:<span class="dt">integer</span>;</span> <span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a> b:<span class="dt">integer</span>; </span></code></pre></div></td> </tr> </tbody> </table></td> <td><p><a href="https://github.com/DomingoGP/LazarusMacroPasDoc/blob/master/MacroSortLinesLazarus.txt">MacroSortLinesLazarus.txt</a></p> <p><a href="https://github.com/DomingoGP/LazarusMacroPasDoc/blob/master/MacroSortByTypeLazarus.txt">MacroSortByTypeLazarus.txt</a></p></td> </tr> <tr> <td></td> <td></td> </tr> <tr> <td><p><strong>Column Align by procedure/function name the selected lines</strong></p> <table> <tbody> <tr> <td><div class="sourceCode" id="cb10"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a> <span class="kw">constructor</span> Create;</span> <span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">destructor</span> Destroy; <span class="kw">override</span>;</span> <span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">function</span> Load(<span class="kw">const</span> aFileName:TFileName):<span class="dt">boolean</span>;</span> <span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">procedure</span> Save(<span class="kw">const</span> aFileName:TFileName); </span> <span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a> <span class="kw">function</span> Size:<span class="dt">integer</span>; </span></code></pre></div></td> <td><div class="sourceCode" id="cb11"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a> <span class="kw">constructor</span> Create;</span> <span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">destructor</span> Destroy; <span class="kw">override</span></span> <span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">function</span> Load(<span class="kw">const</span> aFileName:TFileName):<span class="dt">boolean</span>;</span> <span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">procedure</span> Save(<span class="kw">const</span> aFileName:TFileName); </span> <span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a> <span class="kw">function</span> Size:<span class="dt">integer</span>;</span></code></pre></div></td> </tr> </tbody> </table></td> <td><p><a href="https://github.com/DomingoGP/LazarusMacroPasDoc/blob/master/MacroAlignFunctionProcedureNamesLazarus.txt">MacroAlignFunctionProcedureNamesLazarus.txt</a></p></td> </tr> <tr> <td></td> <td></td> </tr> <tr> <td><p><strong>Sort selected function/procedures declarations by Name, keeps the comments before the function/procedure</strong></p> <table> <tbody> <tr> <td><div class="sourceCode" id="cb12"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a> <span class="kw">destructor</span> Destroy; <span class="kw">override</span>;</span> <span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">constructor</span> Create;</span> <span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">procedure</span> Save(<span class="kw">const</span> aFileName:TFileName);</span> <span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a> <span class="co">{ Load the aFileName }</span></span> <span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a> <span class="kw">function</span> Load(<span class="kw">const</span> aFileName:TFileName):<span class="dt">boolean</span>;</span> <span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a> <span class="kw">function</span> Size:<span class="dt">integer</span>; </span></code></pre></div></td> <td><div class="sourceCode" id="cb13"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a> <span class="kw">constructor</span> Create;</span> <span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">destructor</span> Destroy; <span class="kw">override</span>;</span> <span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a> <span class="co">{ Load the aFileName }</span></span> <span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">function</span> Load(<span class="kw">const</span> aFileName:TFileName):<span class="dt">boolean</span>;</span> <span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a> <span class="kw">procedure</span> Save(<span class="kw">const</span> aFileName:TFileName);</span> <span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a> <span class="kw">function</span> Size:<span class="dt">integer</span>; </span></code></pre></div></td> </tr> </tbody> </table></td> <td><p><a href="https://github.com/DomingoGP/LazarusMacroPasDoc/blob/master/MacroSortFuncProcLazarus.txt">MacroSortFuncProcLazarus.txt</a></p></td> </tr> <tr> <td></td> <td></td> </tr> <tr> <td></td> <td></td> </tr> <tr> <td><p><strong>Sort selected units in the uses clause</strong></p> <table> <tbody> <tr> <td><div class="sourceCode" id="cb14"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a> <span class="kw">uses</span></span> <span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a> Classes, SysUtils, Forms, Controls, Graphics, Dialogs; </span></code></pre></div></td> <td><div class="sourceCode" id="cb15"><pre class="sourceCode pascal"><code class="sourceCode pascal"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a> <span class="kw">uses</span></span> <span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a> Classes, Controls, Dialogs, Forms, Graphics, SysUtils;</span></code></pre></div></td> </tr> </tbody> </table></td> <td><p><a href="https://github.com/DomingoGP/LazarusMacroPasDoc/blob/master/MacroSortUsesLazarus.txt">MacroSortUsesLazarus.txt</a></p></td> </tr> <tr> <td></td> <td></td> </tr> </tbody> </table>

See also


From the Free Pascal wiki, page "Editor Macros PascalScript", as it stood on 2022-01-23 after a change by DomingoGP, out of the wiki's dump of 2024-05-26. 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.