Three wishes : Jump back. paren match and code alignment any one? lazarus / 9-Editor ---------------------------------------------------------------------- EganSolo · 2014-06-26 20:12 Hi guys,   Two features that I would love to see:    1. A "jump back" features: Say, I ctrl click on a method name. The editor jumps to that method declaration. Great. Would love to have a "back" arrow that takes me to the jumping point I started from. As it is, I keep the history window open at all times and use it to jump back.    2. Lazarus is able to match begin/end. Anyway it could match '(' and ')'?    3. Code-block alignment: say I have a list of statements within a use case. Would love to align them on the ':' following the keywords as in:      case foobar of         shortthing:  a := b;         tiny: a := b + c - d + e;         longerthingherealos: a := d * e;     end;     Press a magic key and presto:      case foobar of         shortthing               :  a := b                   ;         tiny                          :  a := b + c - d + e  ;              longerthingherealso : a := d * e               ;      end;   This code alignment should work on any block of assignment. I'm fine if it works only when we have a list of one-liners   Lastly, I would love to contribute to extend the editor and what would greatly help is a documented example on how to do that. For instance, I would love to add a window that allows us to manage multiple projects at the same time a la Delphi and an example that showcases how to add such a window and how to hook into Lazarus would be great. Thanks for a great IDE! Egan ---------------------------------------------------------------------- taazz · 2014-06-26 20:24 Quote from: EganSolo on June 26, 2014, 10:12:48 pmHi guys,   Two features that I would love to see:    1. A "jump back" features: Say, I ctrl click on a method name. The editor jumps to that method declaration. Great. Would love to have a "back" arrow that takes me to the jumping point I started from. As it is, I keep the history window open at all times and use it to jump back. default short cut keys are ctrl+h for back and shift+ctrl+h for forward if I remember correctly, I usually change them immediately on all installations so I might be a bit out of sync with the short cuts. ---------------------------------------------------------------------- EganSolo · 2014-06-26 20:41 Hey Taazz, Thanks you for the info! You are correct: Ctrl+h jumps to the reference and Ctrl+shif+h jumps back.  Great! One down, two more to go! Egan ---------------------------------------------------------------------- Blaazen · 2014-06-26 20:47 Quotedefault short cut keys are ctrl+h for back and shift+ctrl+h for forward if I remember correctly, I usually change them immediately on all installations so I might be a bit out of sync with the short cuts.Recently (yesterday or today) was added Alt+Left and Alt+Right as secondary shortcuts for this, because of request on mailing list and Delphi compatibility. ---------------------------------------------------------------------- Blaazen · 2014-06-26 20:51 Quote2. Lazarus is able to match begin/end. Anyway it could match '(' and ')'?If you mean syntax highlight, it can. When caret is on one of pair of braces, both are drawn bold. Maybe it's configurable, I didn't observe it. EDIT: It is configurable: (menu) Tools -> Options -> (nodes) Editor -> Display -> Colors, (item) Brackets highlight ---------------------------------------------------------------------- EganSolo · 2014-06-26 20:54 Thank you for adding "Alt + Left" and "Alt+right" This is very helpful. In regards to the paren matching, yes, indeed, it is there. Please bear with me since I'm still finding my way around Lazarus. The edit does indeed match them by bolding the matching parens. I didn't see it before because it is a bit too subtle for me. After checking the options, I found a way to make paren match more prominent: For any other newbie such as myself: 1. Go to Tools=>Options->Editor->Display->Colors 2. Scroll down to the "Text" section 3. Select "Brackets Highlight" 4. Consider selecting a color for "Text Mark" to draw a box around the brackets. Great, 2 down, one more to go. ---------------------------------------------------------------------- Martin_fr · 2014-06-26 21:12 Quote from: EganSolo on June 26, 2014, 10:12:48 pm   1. A "jump back" features: Say, I ctrl click on a method name. The editor jumps to that method declaration. Great. Would love to have a "back" arrow that takes me to the jumping point I started from. As it is, I keep the history window open at all times and use it to jump back. You can also use the 4th/5th button of a 5 button mouse. Or assign it to any mouse button you like. Menu: "View" > "Jump history" > A window with all the entries of the history, you can click them to jump Quote   3. Code-block alignment: say I have a list of statements within a use case. Would love to align them on the ':' following the keywords as See: http://wiki.lazarus.freepascal.org/Editor_Macros_PascalScript#Example Open the editor macros, add this macro, and you can do it. e.g specify ":" and it will align the first : in each line of the current selection. ---------------------------------------------------------------------- EganSolo · 2014-06-26 22:32 Hey Martin_fr,   Thank you for the link to the macro. Very interesting. Based on the various help pages I read, it would seem that:   The Window Edit Macro does not allow us to create the macro listed in the link you provided, per the page at http://wiki.lazarus.freepascal.org/IDE_Window:_Editor_MacrosWe need to use IntantFPC with Lazarus, which requires the installation of the InstantFPCLaz package. No problem there.Once the macro has been compiled with InstantFPC, how does it become available in Lazarus? The wiki page at http://wiki.lazarus.freepascal.org/InstantFPC explains how to create a PascalScript with IntantFPC in Lazarus but not how to run it. Any suggestions?Once again, thank you all for your assistance! This has been very helpful. Egan ---------------------------------------------------------------------- Martin_fr · 2014-06-27 02:09 You do not need instant fpc. However it does not work on all CPU, e.g, It may not work on PPC. It should work on intel/amd 32/64 windows, linux, and iirc mac. Check under packages, that "EditorMacroScript" is installed. If yes, check under menu "Tools" > "Options" "Editor Macro Script" > "State"  is "Active" ----- Then go to Menu: "view" > "Editor macros" This is actually not proper documented. There is on "Create new". Simply hit record, and press the "cursor down" key, and "stop" recording. Now you have a new macro: - move it to the "IDE" section to make it permanent - select it and press "edit", paste the example code, save (check for errors in message window) and close the editor. - Assign a key Select some text in any editor (several lines), and press the key you assigned. ---------------------------------------------------------------------- EganSolo · 2014-06-28 02:05 Dear Martin_fr,   Thank you, again for your help and guidance.   I followed your instructions and they worked flawlessly.   Here's my way of giving back to the community: I rewrote the script and extended it in a different direction. Code: [Select]{   Macro Name: Align_Statements   Author    : Egan Solo   Purpose   : Given a list of statements and a list of symbols, this               macro will align the content of the statements so that the               symbols will fall in the same column.               Given this list of statements:               var a:integer;                   bool: boolean;                   AnInt: integer;               and assuming the list of space-separated symbols is : ;               then running this macro will yield:               var a     : integer ;                   bool  : boolean ;                   AnInt : integer ;               If the list of symbols is empty, the macro has no effect.               If a statement does not contain any of the symbols, it is left               unchanged.   Suggested   Key combo:  Alt E + Alt A (for Alt Edit + Alt Align).   Limitations: 1. The list of symbols must consist of non-repeating entries.                2. Each symbol can appear no more than once in each statement.                Example:                  Given this block                  function F1(a:integer; b:boolean): string;                  procedure P2(c:currency; var d: extended);                  And the list of symbols : ;                  then outcome of the macro will be:                  function F1(a :integer  ; b:boolean): string;                  procedure P2(c:currency ; var d: extended);                  That is, it will process the first occurence of each symbol                  in order. Alternatively, if the list of symbols were ; :                  then the outcome would be:                  function F1(a:integer   ; b    : boolean): string;                  procedure P2(c:currency ; var d: extended); } var   Separators      : Array of String       ;   TopLeftCorner    ,   BottomRightCorner: TPoint;   InputFromUser    : String; Function EmptySelection : Boolean; begin   Result := Not Caller.SelAvail; end; procedure FillBlanks(const aNum: integer); var i : integer; begin   for I := 1 to aNum do ecChar(' '); end; Procedure GetSelectionBlock; begin   TopLeftCorner := Caller.BlockBegin;   BottomRightCorner := Caller.BlockEnd;   if    (TopLeftCorner.y > BottomRightCorner.y)      or (              (TopLeftCorner.y = BottomRightCorner.y)          and              (TopLeftCorner.x > BottomRightCorner.x)         )   then begin     TopLeftCorner     := Caller.BlockEnd  ;     BottomRightCorner := Caller.BlockBegin;   end; end; Function GetNumOfSeparators(Const InputFromUser : String) : Integer; var i   : integer;     len : integer; begin   Result := 0;   i      := 1;   len    := length(InputFromUser);   Repeat     While (i <= len) and (InputFromUser[i] = ' ') do inc(i);     If i <= Len     then begin       Inc(Result);       While (i <= len) and (InputFromUser[i] <> ' ') do inc(i);     end;   until (i > len); end; Procedure GetSeparators(Const S: String; const ArraySize : integer); var i           : integer;     len         : Integer;     Accumulator : String;     ArrayPos    : integer; begin   SetLength(Separators, ArraySize);   len       := Length(S);   i         := 1        ;   ArrayPos  := 0        ;   Repeat     While (i <= len) and (S[i] = ' ') do inc(i);     Accumulator := '';     While (i <= len) and (S[i] <> ' ')     do begin       Accumulator := Accumulator + S[i];       inc(i);     end;     If Accumulator <> ''     then begin       Separators[ArrayPos] := Accumulator;       inc(ArrayPos);     end;   until i > len; end; Function ProcessInputFromUser: Boolean; var len : integer;     S   : String; begin    //Prepopulate S with frequently used symbols.    S := ': := ;';    Result := InputQuery( 'Enter ordered list of symbols separated by spaces',                          'Symbols', S);    If Result    then begin       len := GetNumOfSeparators(S);       If len > 0       then GetSeparators(S,len);    end; end; Function FindSeparatorNewPos(const aSeparator : String): Integer; var LineIdx     : integer;     aPos        : integer;     CurrentLine : String ; begin    Result  := 0 ;    For LineIdx := TopLeftCorner.y to BottomRightCorner.y-1 do      begin        CurrentLine := Caller.Lines[LineIdx - 1];        aPos := Pos(aSeparator,CurrentLine);        If aPos > Result        then Result := aPos;      end;    If Result > 0    then Inc(Result); //To introduce one more space. end; Procedure UpdateSeparatorPosInLine(const LineNum : integer; const Separator: String;                                    const NewPos  : integer); var CurrentPos : Integer; begin   If CurrentPos < NewPos   then begin     CurrentPos := Pos(Separator, Caller.Lines[LineNum-1]);     if CurrentPos > 0     then begin       Caller.LogicalCaretXY := Point(CurrentPos, LineNum);       FillBlanks(NewPos-CurrentPos);     end;   end; end; Procedure UpdateSeparatorPosInBlock(const Separator : String; const NewPos : integer); var i : integer; begin   for i := TopLeftCorner.y to BottomRightCorner.y-1   do  UpdateSeparatorPosInLine(i,Separator,NewPos); end; Procedure UpdateBlock; var SepIdx : integer;     NewPos : Integer; begin   For SepIdx := Low(Separators) to High(Separators) do   begin     NewPos := FindSeparatorNewPos(Separators[SepIdx]);     UpdateSeparatorPosInBlock(Separators[SepIdx], NewPos);   end; end; begin   if EmptySelection() or (Not ProcessInputFromUser()) then exit;   GetSelectionBlock();   UpdateBlock(); end. ---------------------------------------------------------------------- Martin_fr · 2014-06-28 03:34 Wow, thanks. I added a link back here to the page on the forum. Or maybe we can create a wiki page with lots of useful macros, and you can move it there. ---------------------------------------------------------------------- EganSolo · 2014-06-28 07:35 Would love to. Also, is there a way to include files in these macros or can I somehow reference a unit? I do plan on creating a series of macros and would like to centralize the common procedures and functions in a shared include file or unit instead of copying from macro to macro. Any pointer in the right direction would be greatly appreciated. ---------------------------------------------------------------------- Martin_fr · 2014-06-28 13:44 No includes, sorry. Afaik, it would be possible to predefine some units (iirc pascal script supports it), but that is not implemented in the editor macro wrapper code. I would not recommend "files" because that means less portability. The editor macro package would need to handle storing and loading of units.