From eff8a039ba99b0ce8f35e2da215e8df3704957c1 Mon Sep 17 00:00:00 2001 From: juha Date: Mon, 31 Aug 2020 07:10:22 +0000 Subject: [PATCH] =?UTF-8?q?JediCodeFormat:=20Add=20option=20to=20format=20?= =?UTF-8?q?only=20selected=20text.=20Issue=20#37652,=20patch=20from=20Domi?= =?UTF-8?q?ngo=20Galm=C3=A9s.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: trunk@63850 - --- .../jcf2/IdePlugin/lazarus/jcfidemain.pas | 127 ++++++++++++++++-- .../jcf2/IdePlugin/lazarus/jcfideregister.pas | 55 +++++--- components/jcf2/ReadWrite/Converter.pas | 43 +++--- 3 files changed, 166 insertions(+), 59 deletions(-) diff --git a/components/jcf2/IdePlugin/lazarus/jcfidemain.pas b/components/jcf2/IdePlugin/lazarus/jcfidemain.pas index ed7620c696..a0f080c765 100644 --- a/components/jcf2/IdePlugin/lazarus/jcfidemain.pas +++ b/components/jcf2/IdePlugin/lazarus/jcfidemain.pas @@ -36,11 +36,16 @@ See http://www.gnu.org/licenses/gpl.html interface uses - { freepascal }SysUtils, Classes, - { lazarus design time } - LazIDEIntf, SrcEditorIntf, IDEMsgIntf, ProjectIntf, IDEExternToolIntf, - { local} - EditorConverter, FileConverter, ConvertTypes, jcfuiconsts; + SysUtils, Classes, + // BuildIntf + ProjectIntf, IDEExternToolIntf, + // IdeIntf + LazIDEIntf, SrcEditorIntf, IDEMsgIntf, + // LCL + Menus, Dialogs, Controls, + // local + EditorConverter, FileConverter, Converter, ConvertTypes, + JcfUIConsts, JcfStringUtils, JcfSettings, fAbout, frFiles; type @@ -67,6 +72,7 @@ type constructor Create; destructor Destroy; override; + procedure DoFormatSelection(Sender: TObject); procedure DoFormatCurrentIDEWindow(Sender: TObject); procedure DoFormatProject(Sender: TObject); procedure DoFormatOpen(Sender: TObject); @@ -78,15 +84,6 @@ type implementation -uses - { lazarus } - Menus, Dialogs, Controls, - { jcf } - JcfStringUtils, - { local } - fAbout, frFiles, JcfSettings; - - function FileIsAllowedType(const psFileName: string): boolean; const ALLOWED_FILE_TYPES: array[1..5] of string = ('.pas', '.pp', '.dpr', '.lpr', '.dpk'); @@ -229,6 +226,108 @@ begin LazarusIDE.DoOpenIDEOptions(TfFiles); end; +//offset in bytes of first char of the lines. 1 based. +procedure FindLineOffsets(const aStr: string; aLineStart, aLineEnd: integer; + out aLineStartOffset: integer; out aLineEndOffset:integer); +var + lineCount:integer; + len:integer; + pC:PChar; + offset:integer; +begin + len:=length(aStr); + pC:=@aStr[1]; + lineCount:=1; + offset:=1; + aLineStartOffset:=0; + aLineEndOffset:=0; + if len<1 then + exit; + if aLineStart=1 then + aLineStartOffset:=offset; + if (aLineEnd=1) then + aLineEndOffset:=offset; + while (offset<=len) and (lineCount<=aLineEnd) do + begin + while (offset<=len) and (pC^<>#10) do + begin + inc(offset); + inc(pC); + end; + if (pC^=#10) and (offset p2.y) then + begin + p1 := srcEditor.BlockEnd; + p2 := srcEditor.BlockBegin; + end; + if p2.x<=1 then + begin + if p2.y>1 then + p2.y:=p2.y-1; + end; + p2.x:=Length(srcEditor.Lines[p2.y-1])+1; //last char + p1.x:=1; + end; + +var + sourceCode: string; + BlockBegin, BlockEnd: TPoint; + fcConverter: TConverter; + lineStartOffset,lineEndOffset: integer; + wi: integer; + outputstr: string; +begin + if (SourceEditorManagerIntf = nil) or (SourceEditorManagerIntf.ActiveEditor = nil) then + begin + LogIdeMessage('', 'No current window', mtInputError, -1, -1); + exit; + end; + srcEditor := SourceEditorManagerIntf.ActiveEditor; + if (srcEditor.SelectionAvailable=false) or srcEditor.ReadOnly then + Exit; + sourceCode := srcEditor.GetText(False); //get ALL editor text. + GetSelectedBlockFullLines(BlockBegin,BlockEnd); + fcConverter := TConverter.Create; + try + fcConverter.OnStatusMessage := LogIDEMessage; + fcConverter.InputCode := sourceCode; + fcConverter.GuiMessages:=true; + FindLineOffsets(sourceCode,BlockBegin.Y,BlockEnd.Y,lineStartOffset,lineEndOffset); + fcConverter.ConvertPart(lineStartOffset,lineEndOffset,true); + wI:=length(fcConverter.OutputCode); + outputstr:=Copy(fcConverter.OutputCode,1,wI-4); // converter adds 2 line ends 0d0a 0d0a + if fcConverter.ConvertError=false then + srcEditor.ReplaceText(BlockBegin, BlockEnd, outputstr); + finally + fcConverter.Free; + end; +end; + procedure TJcfIdeMain.DoAbout(Sender: TObject); var lcAbout: TfrmAboutBox; diff --git a/components/jcf2/IdePlugin/lazarus/jcfideregister.pas b/components/jcf2/IdePlugin/lazarus/jcfideregister.pas index d5e4b6c6cc..11986cdd15 100644 --- a/components/jcf2/IdePlugin/lazarus/jcfideregister.pas +++ b/components/jcf2/IdePlugin/lazarus/jcfideregister.pas @@ -51,27 +51,30 @@ uses JcfIdeMain, JcfRegistrySettings; const - FORMAT_MENU_NAME = 'jcfJEDICodeFormat'; - FORMAT_CURRENT_NAME = 'jcfCurrentEditorWindow'; - FORMAT_PROJECT_MENU_NAME = 'jcfAllFilesinProject'; - FORMAT_OPEN_MENU_NAME = 'jcfAllOpenWindows'; + FORMAT_MENU_NAME = 'jcfJEDICodeFormat'; + FORMAT_SELECTION_NAME = 'jcfSelectionText'; + FORMAT_CURRENT_NAME = 'jcfCurrentEditorWindow'; + FORMAT_PROJECT_MENU_NAME = 'jcfAllFilesinProject'; + FORMAT_OPEN_MENU_NAME = 'jcfAllOpenWindows'; //FORMAT_REG_SETTINGS_MENU_NAME = 'jcfRegistrySettings'; FORMAT_SETTINGS_MENU_NAME = 'jcfFormatSettings'; - FORMAT_ABOUT_MENU_NAME = 'jcfAbout'; + FORMAT_ABOUT_MENU_NAME = 'jcfAbout'; FORMAT_CATEGORY_IDECMD_NAME = 'jcfFormat'; - FORMAT_MENU_SECTION1 = 'jcfSection1'; - FORMAT_MENU_SECTION2 = 'jcfSection2'; + FORMAT_MENU_SECTION1 = 'jcfSection1'; + FORMAT_MENU_SECTION2 = 'jcfSection2'; resourcestring - FORMAT_MENU = 'JEDI Code &Format'; - FORMAT_CURRENT_MENU = '&Current Editor Window'; - FORMAT_CURRENT_IDECMD = 'Format code in current editor window'; - FORMAT_PROJECT_MENU = '&All Files in Project'; - FORMAT_OPEN_MENU = 'All &Open Windows'; + FORMAT_MENU = 'JEDI Code &Format'; + FORMAT_SELECTION_MENU = 'Selection'; + FORMAT_CURRENT_MENU = '&Current Editor Window'; + FORMAT_SELECTION_IDECMD = 'Format code in Selection'; + FORMAT_CURRENT_IDECMD = 'Format code in current editor window'; + FORMAT_PROJECT_MENU = '&All Files in Project'; + FORMAT_OPEN_MENU = 'All &Open Windows'; //FORMAT_REG_SETTINGS_MENU = '&Registry Settings'; - FORMAT_SETTINGS_MENU = '&Format Settings'; - FORMAT_ABOUT_MENU = '&About'; - FORMAT_CATEGORY_IDECMD = 'JEDI Code Format'; + FORMAT_SETTINGS_MENU = '&Format Settings'; + FORMAT_ABOUT_MENU = '&About'; + FORMAT_CATEGORY_IDECMD = 'JEDI Code Format'; const DefaultJCFOptsFile = 'jcfsettings.cfg'; @@ -109,24 +112,32 @@ end; procedure Register; var Cat: TIDECommandCategory; - Key: TIDEShortCut; fcMainMenu, SubSection: TIDEMenuSection; - CmdFormatFile: TIDECommand; + KeySelect, KeyUnit: TIDEShortCut; + CmdSelect, CmdUnit: TIDECommand; begin SetLazarusDefaultFileName; GetDefaultSettingsFileName := IDEGetDefaultSettingsFileName; Cat := IDECommandList.CreateCategory(nil, FORMAT_CATEGORY_IDECMD_NAME, FORMAT_CATEGORY_IDECMD, IDECmdScopeSrcEditOnly); - // Ctrl + D ? - Key := IDEShortCut(VK_D, [SSctrl], VK_UNKNOWN, []); - CmdFormatFile := RegisterIDECommand(Cat, FORMAT_CURRENT_NAME, FORMAT_CURRENT_IDECMD, Key, - lcJCFIDE.DoFormatCurrentIDEWindow); fcMainMenu := RegisterIDESubMenu(itmSourceTools, FORMAT_MENU_NAME, FORMAT_MENU); + KeySelect := IDEShortCut(VK_UNKNOWN, []); + // We are running out of free shortcut combinations. Ctrl+Shift+Alt+D is free. + //KeySelect := IDEShortCut(VK_D, [ssShift,ssAlt,SSctrl]); + CmdSelect := RegisterIDECommand(Cat, FORMAT_SELECTION_NAME, FORMAT_SELECTION_IDECMD, + KeySelect, lcJCFIDE.DoFormatSelection); + RegisterIDEMenuCommand(fcMainMenu, FORMAT_SELECTION_NAME, FORMAT_SELECTION_MENU, + lcJCFIDE.DoFormatSelection, nil, CmdSelect); + + // Ctrl + D + KeyUnit := IDEShortCut(VK_D, [SSctrl]); + CmdUnit := RegisterIDECommand(Cat, FORMAT_CURRENT_NAME, FORMAT_CURRENT_IDECMD, + KeyUnit, lcJCFIDE.DoFormatCurrentIDEWindow); RegisterIDEMenuCommand(fcMainMenu, FORMAT_CURRENT_NAME, FORMAT_CURRENT_MENU, - lcJCFIDE.DoFormatCurrentIDEWindow, nil, CmdFormatFile); + lcJCFIDE.DoFormatCurrentIDEWindow, nil, CmdUnit); RegisterIDEMenuCommand(fcMainMenu, FORMAT_PROJECT_MENU_NAME, FORMAT_PROJECT_MENU, lcJCFIDE.DoFormatProject); diff --git a/components/jcf2/ReadWrite/Converter.pas b/components/jcf2/ReadWrite/Converter.pas index ace7326c3e..0dc0b57065 100644 --- a/components/jcf2/ReadWrite/Converter.pas +++ b/components/jcf2/ReadWrite/Converter.pas @@ -37,10 +37,11 @@ unit Converter; interface uses - { delphi } SysUtils, Controls, Forms, - { local } ConvertTypes, ParseTreeNode, - BuildTokenList, - BuildParseTree, BaseVisitor; + SysUtils, strutils, + // LCL + Controls, Forms, + // local + ConvertTypes, ParseTreeNode, BuildTokenList, BuildParseTree, BaseVisitor; type @@ -89,7 +90,8 @@ type procedure Clear; procedure Convert; - procedure ConvertPart(const piStartIndex, piEndIndex: Integer); + procedure ConvertPart(const piStartIndex, piEndIndex: Integer; + aOnlyOutputSelection: boolean=false); procedure CollectOutput(const pcRoot: TParseTreeNode); @@ -298,17 +300,10 @@ begin // is it a leaf with source? if (pcRoot is TSourceToken) then - begin - fsOutputCode := fsOutputCode + TSourceToken(pcRoot).SourceCode; - end - else - begin - // recurse, write out all child nodes + fsOutputCode := fsOutputCode + TSourceToken(pcRoot).SourceCode + else // recurse, write out all child nodes for liLoop := 0 to pcRoot.ChildNodeCount - 1 do - begin CollectOutput(pcRoot.ChildNodes[liLoop]); - end; - end; end; function TConverter.GetOnStatusMessage: TStatusMessageProc; @@ -365,7 +360,8 @@ begin fShowParseTree.ShowParseTree(fcBuildParseTree.Root); end; -procedure TConverter.ConvertPart(const piStartIndex, piEndIndex: Integer); +procedure TConverter.ConvertPart(const piStartIndex, piEndIndex: Integer; + aOnlyOutputSelection: boolean); const FORMAT_START = '{}'; FORMAT_END = '{}'; @@ -398,17 +394,18 @@ begin Convert; - { locate the markers in the output, - and replace before and after } + { locate the markers in the output, and replace before and after } liOutputStart := Pos(FORMAT_START, fsOutputCode) + Length(FORMAT_START); - liOutputEnd := Pos(FORMAT_END, fsOutputCode); - + liOutputEnd := PosEx(FORMAT_END, fsOutputCode,liOutputStart); { splice } - lsNewOutput := StrLeft(fsInputCode, liRealInputStart - 1); - lsNewOutput := lsNewOutput + Copy(fsOutputCode, liOutputStart, (liOutputEnd - liOutputStart)); - lsNewOutput := lsNewOutput + StrRestOf(fsInputCode, liRealInputEnd + Length(FORMAT_START) + Length(FORMAT_END)); - + if aOnlyOutputSelection then + lsNewOutput := Copy(fsOutputCode, liOutputStart, (liOutputEnd - liOutputStart)) + else begin + lsNewOutput := StrLeft(fsInputCode, liRealInputStart - 1); + lsNewOutput := lsNewOutput + Copy(fsOutputCode, liOutputStart, (liOutputEnd - liOutputStart)); + lsNewOutput := lsNewOutput + StrRestOf(fsInputCode, liRealInputEnd + Length(FORMAT_START) + Length(FORMAT_END)); + end; fsOutputCode := lsNewOutput; end;