Difference between revisions of "IDE Window: Editor Macros"
Line 55: | Line 55: | ||
* Macros are restricted to the Editor. You cannot currently record actions made in the Form Designer. | * Macros are restricted to the Editor. You cannot currently record actions made in the Form Designer. | ||
* Sometimes you may be able to record actions apart from the editing of text. However, this is not supported, and playback may not render the desired effects correctly (or at all). E.g. It is possible to record stepping in the debugger (F7,F8,F9), but on playback you may find some of the commands are skipped at random. | * Sometimes you may be able to record actions apart from the editing of text. However, this is not supported, and playback may not render the desired effects correctly (or at all). E.g. It is possible to record stepping in the debugger (F7,F8,F9), but on playback you may find some of the commands are skipped at random. | ||
+ | |||
+ | = Macros for download = | ||
+ | |||
+ | {| class="wikitable" | ||
+ | |+Editor macros | ||
+ | |- | ||
+ | |'''Description''' | ||
+ | |'''Source Code''' | ||
+ | |- style="vertical-align:top;" | ||
+ | | | ||
+ | Comments a procedure/function in [https://github.com/pasdoc/pasdoc/wiki PasDoc] format | ||
+ | |||
+ | example: | ||
+ | |||
+ | function AddRadioButton(const aCaption: string; aChecked: boolean = False): TCheckBox; | ||
+ | |||
+ | Executing the macro with the caret in the line of function declaration will insert the comment before. | ||
+ | |||
+ | { Description | ||
+ | @param(aCaption description ) | ||
+ | @param(aChecked description ) | ||
+ | @returns( description ) | ||
+ | @raises( none ) | ||
+ | } | ||
+ | function AddRadioButton(const aCaption: string; aChecked: boolean = False): TRadioButton; | ||
+ | |||
+ | [https://github.com/DomingoGP/LazarusMacroPasDoc https://github.com/DomingoGP/LazarusMacroPasDoc] | ||
+ | |||
+ | | | ||
+ | <nowiki> | ||
+ | // Lazarus editor macro. Template for pasdoc functions and procedures documentation | ||
+ | // Execute with caret in the precedure/function line declaration. | ||
+ | // Autor: Domingo Galmés | ||
+ | // public domain. | ||
+ | function StrTokenPos(const aStr: string; const aDelimiters: string;var aPos:integer): string; | ||
+ | var | ||
+ | wI: integer; | ||
+ | wL: integer; | ||
+ | wStart: integer; | ||
+ | begin | ||
+ | wL := Length(aStr); | ||
+ | //skip delimiters | ||
+ | wI := aPos; | ||
+ | while wI <= wL do | ||
+ | begin | ||
+ | if Pos(aStr[wI],aDelimiters) = 0 then | ||
+ | break; | ||
+ | Inc(wI); | ||
+ | end; | ||
+ | if wI > wL then // all chars are delimiters | ||
+ | begin | ||
+ | Result := ''; | ||
+ | aPos := 0; | ||
+ | Exit; | ||
+ | end; | ||
+ | wStart := wI; | ||
+ | while wI <= wL do // while not delimiters | ||
+ | begin | ||
+ | if Pos(aStr[wI],aDelimiters) > 0 then | ||
+ | Break; | ||
+ | Inc(wI); | ||
+ | end; | ||
+ | result := Copy(aStr, wStart, wI - wStart); | ||
+ | Inc(wI); //skip final delimiter (only one) | ||
+ | if wI<=wL then | ||
+ | aPos:=wI | ||
+ | else | ||
+ | aPos:=0; | ||
+ | end; | ||
+ | |||
+ | var | ||
+ | text:string; | ||
+ | start:TPoint; | ||
+ | declaration:string; | ||
+ | openParens:integer; | ||
+ | p:integer; | ||
+ | parameters:string; | ||
+ | l,line:integer; | ||
+ | inComment:boolean; | ||
+ | inSet:boolean; | ||
+ | isFunction:boolean; | ||
+ | parameter,parameterlower:string; | ||
+ | begin | ||
+ | ecLineStart; | ||
+ | start:=Caller.CaretXY; | ||
+ | declaration:=Caller.Lines[start.Y-1]; | ||
+ | p:=1; | ||
+ | text:=LowerCase(StrTokenPos(declaration,' ',p)); | ||
+ | isFunction:=false; | ||
+ | if text='function' then | ||
+ | isFunction:=true | ||
+ | else if text<>'procedure' then | ||
+ | exit; | ||
+ | |||
+ | line:=0; | ||
+ | // search '(' parameters start | ||
+ | openParens:=0; | ||
+ | l:=length(declaration); | ||
+ | //p:=1; | ||
+ | while p<=l do | ||
+ | begin | ||
+ | if declaration[p]='(' then | ||
+ | begin | ||
+ | Inc(openParens); | ||
+ | inc(p); | ||
+ | break; | ||
+ | end; | ||
+ | inc(p); | ||
+ | end; | ||
+ | // seachr ')' parameters end | ||
+ | inComment:=false; | ||
+ | inSet:=false; | ||
+ | while p<=l do | ||
+ | begin | ||
+ | if declaration[p]=#39 then // 'in string'. | ||
+ | begin | ||
+ | inc(p); | ||
+ | while (p<=l) do | ||
+ | begin | ||
+ | if declaration[p]=#39 then | ||
+ | begin | ||
+ | if (p<l) and (declaration[p+1]=#39) then // escape ' | ||
+ | inc(p) | ||
+ | else | ||
+ | break; | ||
+ | end; | ||
+ | inc(p); | ||
+ | end; | ||
+ | end | ||
+ | else if (declaration[p]='{') then | ||
+ | inComment:=true | ||
+ | else if inComment=true then | ||
+ | begin | ||
+ | if declaration[p]='}' then | ||
+ | inComment:=false; | ||
+ | end | ||
+ | else if (declaration[p]='[') then | ||
+ | inSet:=true | ||
+ | else if inSet=true then | ||
+ | begin | ||
+ | if declaration[p]=']' then | ||
+ | inSet:=false; | ||
+ | end | ||
+ | else if declaration[p]='(' then | ||
+ | begin | ||
+ | Inc(openParens); | ||
+ | end | ||
+ | else if declaration[p]=')' then | ||
+ | begin | ||
+ | Dec(openParens); | ||
+ | if openParens=0 then | ||
+ | break; | ||
+ | end | ||
+ | else if declaration[p]='/' then //line comment | ||
+ | begin | ||
+ | if (p<l) and (declaration[p+1]='/') then | ||
+ | begin | ||
+ | p:=l+1; //next line. | ||
+ | end; | ||
+ | end | ||
+ | else | ||
+ | begin | ||
+ | parameters:=parameters+declaration[p]; | ||
+ | end; | ||
+ | |||
+ | inc(p); | ||
+ | if p>l then | ||
+ | begin | ||
+ | inc(line); | ||
+ | declaration:=Caller.Lines[start.Y-1+line]; | ||
+ | l:=length(declaration); | ||
+ | p:=1; | ||
+ | end; | ||
+ | end; | ||
+ | // separamos parameters por , o ; y despreciamos despues de : | ||
+ | //{parameters: aV1,aV2,aV3:integer;const aS1:string= } | ||
+ | //procedure Hola2(aV1,aV2,aV3:integer;const aS1:string='27'); | ||
+ | text:='{ Description '+#10; | ||
+ | p:=1; | ||
+ | while p>0 do | ||
+ | begin | ||
+ | parameter:=StrTokenPos(parameters,',;',p); | ||
+ | l:=1; | ||
+ | parameter:=Trim(StrTokenPos(parameter,':',l)); | ||
+ | parameterlower:=LowerCase(parameter); | ||
+ | l:=length(parameter); | ||
+ | if Pos('var',parameterlower)>0 then | ||
+ | parameter:=Copy(parameter,5,l-4) | ||
+ | else if Pos('constref',parameterlower)>0 then | ||
+ | parameter:=Copy(parameter,10,l-9) | ||
+ | else if Pos('const',parameterlower)>0 then | ||
+ | parameter:=Copy(parameter,7,l-6) | ||
+ | else if Pos('out',parameterlower)>0 then | ||
+ | parameter:=Copy(parameter,5,l-4); | ||
+ | parameter:=Trim(parameter); | ||
+ | text:=text+' @param('+parameter+' description )'+#10; | ||
+ | end; | ||
+ | if isFunction then | ||
+ | text:=text+' @returns( description )'+#10; | ||
+ | text:=text+' @raises( none )'+#10; | ||
+ | text:=text+'}'+#10; | ||
+ | //Caller.CaretXY:=start; | ||
+ | Caller.insertTextAtCaret(text,scamEnd); | ||
+ | end. | ||
+ | |||
+ | </nowiki> | ||
+ | |- | ||
+ | |||
+ | |} |
Revision as of 18:07, 21 August 2020
│
Deutsch (de) │
English (en) │
русский (ru) │
- Lazarus 1.0 supports only macros entered via the keyboard
- The Editor Macros window is available in release versions of Lazarus from 1.2.6 onwards. It is not available in the Lazarus 1.0 release.
- See also Editor_Macros_PascalScript
Editor macros
Lazarus lets you record an unlimited number of macros. The Editor macros dialog allows you to choose which recorded macro is currently played by the dialog's Play button (or by using the default shortcut key combination ⇧ Shift+Ctrl+P when editing code). Recorded macros can be saved for future reuse by moving them to the project session's saved settings, or to the IDE configuration settings.
Display
All macros are displayed in one of 3 groupings:
- Recorded
- This lists newly recorded macros. These macros are not saved, and are lost when the IDE is closed.
- Project
- This lists macros you have opted to be saved with the project session. Each project can have its own set of macros.
Note: If the project is configured not to save a session, then macros in this group are not saved, and will be lost when the project is closed. - IDE
- This group lists all macros that will be saved with the IDE configuration settings. These macros are available to all projects.
Macros can be moved between Project and IDE using the appropriate button.
Macros may show a status icon:
- Current macro. This can be set using the "Select" button. This is the macro that will be played when you use the keyboard shortcut (the default is [Shift][Ctrl][P]).
- This macro is currently being recorded.
- This macro is currently playing.
- This macro is broken. This icon indicates that the macro could not be loaded from the configuration file, and so the macro cannot be used. (It will remain untouched in its broken form in the config file).
The Interface of the Editor macros dialog
- Select
- Sets the current macro which will be used by the keyboard shortcut.
The Play button is not affected by this. - Rename...
- Rename the macro (Macro1, Macro2, etc., the default names assigned by the IDE, are almost completely uninformative, and should be changed to a suitable self-descriptive name such as AlignSelectedLinesAtColon).
- Edit Key
- Assign a key-combination for invoking the macro from the keyboard.
- Edit
- Edit the macro as source - a new tab is opened in the Source Editor where you can view the naming used by the macro recorder and edit the macro source as needed.
- Delete
- Delete the macro.
- Play
- Play the selected macro. This is the macro selected by clicking the list. Not the "current" macro.
- Repeat
- Sets how often the macro is played when the Play button is pressed. This setting affects only the Play button (the keyboard shortcut invokes only a single execution of the macro).
- Record
- Starts the recording of a new macro.
During recording this button doubles as a pause/continue button, allowing you to pause or continue the macro recording.
If anything was recorded, the new macro will be set as the "current" macro in the Source Editor. - Stop
- This button ends the recording, and also allows you to interrupt and stop repeated play. In certain circumstances, it is possible to stop in the middle of a playing macro.
- Move to
- Project/Ide: These two buttons move the selected macro to the indicated group when you want to save the macro for future use. The buttons are enabled or disabled according to the possible action(s).
Invoking macros from the keyboard
The Lazarus IDE sets up the following 2 keyboard shortcuts by default:
- ⇧ Shift+Ctrl+P Play the current macro
- ⇧ Shift+Ctrl+R Start/Stop recording a new macro
- During recording, the shortcut for Play can be used to Pause recording
Limitations
- A macro can only be recorded from a single editor.
A macro can be played in any editor window afterwards, but only in one editor window at a time. - Macros only record commands issued by keyboard, and certain menu commands.
Changes caused by mouse buttons or movement (such as moving the caret or selecting text) are [b]not[/b] recorded. - Macros are restricted to the Editor. You cannot currently record actions made in the Form Designer.
- Sometimes you may be able to record actions apart from the editing of text. However, this is not supported, and playback may not render the desired effects correctly (or at all). E.g. It is possible to record stepping in the debugger (F7,F8,F9), but on playback you may find some of the commands are skipped at random.
Macros for download
Description | Source Code |
Comments a procedure/function in PasDoc format example: function AddRadioButton(const aCaption: string; aChecked: boolean = False): TCheckBox; Executing the macro with the caret in the line of function declaration will insert the comment before. { Description @param(aCaption description ) @param(aChecked description ) @returns( description ) @raises( none ) } function AddRadioButton(const aCaption: string; aChecked: boolean = False): TRadioButton; https://github.com/DomingoGP/LazarusMacroPasDoc |
// Lazarus editor macro. Template for pasdoc functions and procedures documentation // Execute with caret in the precedure/function line declaration. // Autor: Domingo Galmés // public domain. function StrTokenPos(const aStr: string; const aDelimiters: string;var aPos:integer): string; var wI: integer; wL: integer; wStart: integer; begin wL := Length(aStr); //skip delimiters wI := aPos; while wI <= wL do begin if Pos(aStr[wI],aDelimiters) = 0 then break; Inc(wI); end; if wI > wL then // all chars are delimiters begin Result := ''; aPos := 0; Exit; end; wStart := wI; while wI <= wL do // while not delimiters begin if Pos(aStr[wI],aDelimiters) > 0 then Break; Inc(wI); end; result := Copy(aStr, wStart, wI - wStart); Inc(wI); //skip final delimiter (only one) if wI<=wL then aPos:=wI else aPos:=0; end; var text:string; start:TPoint; declaration:string; openParens:integer; p:integer; parameters:string; l,line:integer; inComment:boolean; inSet:boolean; isFunction:boolean; parameter,parameterlower:string; begin ecLineStart; start:=Caller.CaretXY; declaration:=Caller.Lines[start.Y-1]; p:=1; text:=LowerCase(StrTokenPos(declaration,' ',p)); isFunction:=false; if text='function' then isFunction:=true else if text<>'procedure' then exit; line:=0; // search '(' parameters start openParens:=0; l:=length(declaration); //p:=1; while p<=l do begin if declaration[p]='(' then begin Inc(openParens); inc(p); break; end; inc(p); end; // seachr ')' parameters end inComment:=false; inSet:=false; while p<=l do begin if declaration[p]=#39 then // 'in string'. begin inc(p); while (p<=l) do begin if declaration[p]=#39 then begin if (p<l) and (declaration[p+1]=#39) then // escape ' inc(p) else break; end; inc(p); end; end else if (declaration[p]='{') then inComment:=true else if inComment=true then begin if declaration[p]='}' then inComment:=false; end else if (declaration[p]='[') then inSet:=true else if inSet=true then begin if declaration[p]=']' then inSet:=false; end else if declaration[p]='(' then begin Inc(openParens); end else if declaration[p]=')' then begin Dec(openParens); if openParens=0 then break; end else if declaration[p]='/' then //line comment begin if (p<l) and (declaration[p+1]='/') then begin p:=l+1; //next line. end; end else begin parameters:=parameters+declaration[p]; end; inc(p); if p>l then begin inc(line); declaration:=Caller.Lines[start.Y-1+line]; l:=length(declaration); p:=1; end; end; // separamos parameters por , o ; y despreciamos despues de : //{parameters: aV1,aV2,aV3:integer;const aS1:string= } //procedure Hola2(aV1,aV2,aV3:integer;const aS1:string='27'); text:='{ Description '+#10; p:=1; while p>0 do begin parameter:=StrTokenPos(parameters,',;',p); l:=1; parameter:=Trim(StrTokenPos(parameter,':',l)); parameterlower:=LowerCase(parameter); l:=length(parameter); if Pos('var',parameterlower)>0 then parameter:=Copy(parameter,5,l-4) else if Pos('constref',parameterlower)>0 then parameter:=Copy(parameter,10,l-9) else if Pos('const',parameterlower)>0 then parameter:=Copy(parameter,7,l-6) else if Pos('out',parameterlower)>0 then parameter:=Copy(parameter,5,l-4); parameter:=Trim(parameter); text:=text+' @param('+parameter+' description )'+#10; end; if isFunction then text:=text+' @returns( description )'+#10; text:=text+' @raises( none )'+#10; text:=text+'}'+#10; //Caller.CaretXY:=start; Caller.insertTextAtCaret(text,scamEnd); end. |