From 7f9ea6e1a992864909b0736951df4b007359d187 Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Wed, 16 Dec 2015 08:32:00 +0100 Subject: [PATCH] added 'Dfmt commander' widget, closes #8 --- lazproj/coedit.lpi | 9 +- lazproj/coedit.lpr | 2 +- src/ce_dfmt.lfm | 73 +++++++++++++++ src/ce_dfmt.pas | 227 +++++++++++++++++++++++++++++++++++++++++++++ src/ce_infos.lfm | 42 ++++----- src/ce_infos.pas | 6 +- src/ce_main.pas | 5 +- wiki/wiki.todo.txt | 3 +- 8 files changed, 341 insertions(+), 26 deletions(-) create mode 100644 src/ce_dfmt.lfm create mode 100644 src/ce_dfmt.pas diff --git a/lazproj/coedit.lpi b/lazproj/coedit.lpi index b85c391c..17a584c8 100644 --- a/lazproj/coedit.lpi +++ b/lazproj/coedit.lpi @@ -137,7 +137,7 @@ - + @@ -369,6 +369,13 @@ + + + + + + + diff --git a/lazproj/coedit.lpr b/lazproj/coedit.lpr index 700f4047..6e13bb22 100644 --- a/lazproj/coedit.lpr +++ b/lazproj/coedit.lpr @@ -10,7 +10,7 @@ uses ce_observer, ce_libman, ce_tools, ce_dcd, ce_main, ce_writableComponent, ce_symstring, ce_staticmacro, ce_inspectors, ce_editoroptions, ce_dockoptions, ce_shortcutseditor, ce_mru, ce_processes, ce_dubproject, ce_dialogs, -ce_dubprojeditor, ce_gdb, ce_controls; +ce_dubprojeditor, ce_gdb, ce_controls, ce_dfmt; {$R *.res} diff --git a/src/ce_dfmt.lfm b/src/ce_dfmt.lfm new file mode 100644 index 00000000..e6dd4024 --- /dev/null +++ b/src/ce_dfmt.lfm @@ -0,0 +1,73 @@ +inherited CEDfmtWidget: TCEDfmtWidget + Left = 562 + Height = 365 + Top = 245 + Width = 458 + Caption = 'Dfmt commander' + ClientHeight = 365 + ClientWidth = 458 + inherited Back: TPanel + Left = 4 + Height = 357 + Top = 4 + Width = 450 + BorderSpacing.Around = 4 + ClientHeight = 357 + ClientWidth = 450 + inherited Content: TPanel + Height = 357 + Width = 450 + ClientHeight = 357 + ClientWidth = 450 + object dfmtOptionEditor: TTIPropertyGrid[0] + Left = 4 + Height = 313 + Top = 4 + Width = 442 + Align = alClient + BorderSpacing.Around = 4 + CheckboxForBoolean = False + DefaultValueFont.Color = clWindowText + Filter = [tkInteger, tkChar, tkEnumeration, tkFloat, tkSet, tkMethod, tkSString, tkLString, tkAString, tkWString, tkVariant, tkArray, tkRecord, tkInterface, tkClass, tkObject, tkWChar, tkBool, tkInt64, tkQWord, tkDynArray, tkInterfaceRaw, tkProcVar, tkUString, tkUChar, tkHelper] + Indent = 10 + NameFont.Color = clWindowText + OnEditorFilter = dfmtOptionEditorEditorFilter + PreferredSplitterX = 220 + SplitterX = 220 + ValueFont.Color = clGreen + end + object pnlFooter: TPanel[1] + Left = 4 + Height = 32 + Top = 321 + Width = 442 + Align = alBottom + BorderSpacing.Around = 4 + BevelOuter = bvLowered + ClientHeight = 32 + ClientWidth = 442 + TabOrder = 1 + object btnCancel: TSpeedButton + Left = 375 + Height = 26 + Hint = 'restore previous format' + Top = 3 + Width = 30 + Align = alRight + BorderSpacing.Left = 2 + BorderSpacing.Around = 2 + end + object btnApply: TSpeedButton + Left = 409 + Height = 26 + Hint = 'apply formating' + Top = 3 + Width = 30 + Align = alRight + BorderSpacing.Left = 2 + BorderSpacing.Around = 2 + end + end + end + end +end diff --git a/src/ce_dfmt.pas b/src/ce_dfmt.pas new file mode 100644 index 00000000..a2341a7b --- /dev/null +++ b/src/ce_dfmt.pas @@ -0,0 +1,227 @@ +unit ce_dfmt; + +{$I ce_defines.inc} + +interface + +uses + Classes, SysUtils, FileUtil, RTTIGrids, Forms, Controls, Graphics, ExtCtrls, + Menus, Buttons, process, ce_widget, ce_interfaces, ce_observer, ce_synmemo, + ce_writableComponent, ce_common, ce_sharedres, PropEdits, ObjectInspector; + +type + + DfmtEol = (cr, lf, crlf); + DfmtIdentstyle = (tab, space); + DfmtBraceStyle = (allman, otbs, stroustrup); + + // wraps dfmt options to build the command line with ease + // and allows to save the options between session. + TCEDmtWrapper = class(TWritableLfmTextComponent) + private + fEol: DfmtEol; + fTabStyle: DfmtIdentstyle; + fIdentSize: integer; + fTabWidth: integer; + fHardLLen: integer; + fSoftLLen: integer; + fBraceStyle: DfmtBraceStyle; + fSpaceCast: boolean; + fSplitOp: boolean; + fCompactLbl: boolean; + fSpaceSelImp: boolean; + published + property endOfline: DfmtEol read fEol write fEol default lf; + property identationStyle: DfmtIdentstyle read fTabStyle write fTabStyle default space; + property identSize: integer read fIdentSize write fIdentSize default 4; + property tabWidth: integer read fTabWidth write fTabWidth default 8; + property hardLineLen: integer read fHardLLen write fHardLLen default 120; + property softLineLen: integer read fSoftLLen write fSoftLLen default 80; + property braceStyle: DfmtBraceStyle read fBraceStyle write fBraceStyle default allman; + property spaceAfterCast: boolean read fSpaceCast write fSpaceCast default true; + property spaceAfterImport: boolean read fSpaceSelImp write fSpaceSelImp default true; + property splitOpAtPrevLine: boolean read fSplitOp write fSplitOp default true; + property compactLabeledStatements: boolean read fCompactLbl write fCompactLbl default true; + public + constructor create(AOwner: TComponent); override; + procedure getCommandLine(str: TStrings); + end; + + { TCEDfmtWidget } + + TCEDfmtWidget = class(TCEWidget, ICEMultiDocObserver) + btnApply: TSpeedButton; + btnCancel: TSpeedButton; + pnlFooter: TPanel; + dfmtOptionEditor: TTIPropertyGrid; + procedure dfmtOptionEditorEditorFilter(Sender: TObject; + aEditor: TPropertyEditor; var aShow: boolean); + private + fDoc: TCESynMemo; + fBackup: TStringList; + fDmtWrapper: TCEDmtWrapper; + // + procedure docNew(aDoc: TCESynMemo); + procedure docFocused(aDoc: TCESynMemo); + procedure docChanged(aDoc: TCESynMemo); + procedure docClosing(aDoc: TCESynMemo); + // + procedure doApply(sender: TObject); + procedure doCancel(sender: TObject); + public + constructor create(aOwner: TComponent); override; + destructor destroy; override; + end; + +implementation +{$R *.lfm} + +const + optFname = 'dfmt.txt'; + +{$REGION Standard Comp/Obj------------------------------------------------------} +constructor TCEDfmtWidget.create(aOwner: TComponent); +var + fname: string; +begin + inherited; + fDmtWrapper := TCEDmtWrapper.Create(self); + fBackup := TStringList.Create; + // + fname := getCoeditDocPath + optFname; + if fileExists(fname) then + fDmtWrapper.loadFromFile(fname); + // + btnCancel.OnClick := @doCancel; + btnApply.OnClick := @doApply; + AssignPng(btnCancel, 'cancel'); + AssignPng(btnApply, 'accept'); + // + dfmtOptionEditor.TIObject := fDmtWrapper; +end; + +destructor TCEDfmtWidget.destroy; +begin + dfmtOptionEditor.TIObject := nil; + fDmtWrapper.saveToFile(getCoeditDocPath + optFname); + fBackup.Free; + inherited; +end; + +constructor TCEDmtWrapper.create(AOwner: TComponent); +begin + inherited; + fEol := lf; + fTabStyle := DfmtIdentstyle.space; + fIdentSize := 4; + fTabWidth := 8; + fHardLLen := 120; + fSoftLLen := 80; + fBraceStyle := DfmtBraceStyle.allman; + fSpaceCast := true; + fSpaceSelImp := true; + fSplitOp := true; + fCompactLbl := true; +end; + +procedure TCEDfmtWidget.dfmtOptionEditorEditorFilter(Sender: TObject; + aEditor: TPropertyEditor; var aShow: boolean); +begin + case aEditor.GetName of + 'Tag', 'Name': aShow := false; + else aShow := true; + end; +end; +{$ENDREGION} + +{$REGION ICEMultiDocObserver ---------------------------------------------------} +procedure TCEDfmtWidget.docNew(aDoc: TCESynMemo); +begin + fDoc := aDoc; +end; + +procedure TCEDfmtWidget.docFocused(aDoc: TCESynMemo); +begin + if aDoc = fDoc + then exit; + fDoc := aDoc; +end; + +procedure TCEDfmtWidget.docChanged(aDoc: TCESynMemo); +begin +end; + +procedure TCEDfmtWidget.docClosing(aDoc: TCESynMemo); +begin + if fDoc <> aDoc then + exit; + fDoc := nil; +end; +{$ENDREGION} + +{$REGION Dfmt things -----------------------------------------------------------} +procedure TCEDmtWrapper.getCommandLine(str: TStrings); +const + eol: array[DfmtEol] of string = ('cr', 'lf', 'crlf'); + falsetrue: array[boolean] of string = ('false', 'true'); + idtstyle: array[DfmtIdentstyle] of string = ('tab', 'space'); + brc: array[DfmtBraceStyle] of string = ('allman', 'otbs', 'stroustrup'); +begin + str.Add('--end_of_line=' + eol[endOfline]); + str.Add('--max_line_length=' + intToStr(hardLineLen)); + str.Add('--soft_max_line_length=' + intToStr(softLineLen)); + str.Add('--indent_size=' + intToStr(identSize)); + str.Add('--indent_style=' + idtstyle[identationStyle]); + str.Add('--tab_width=' + intToStr(tabWidth)); + str.Add('--brace_style=' + brc[braceStyle]); + str.Add('--split_operator_at_line_end=' + falsetrue[splitOpAtPrevLine]); + str.Add('--space_after_cast=' + falsetrue[spaceAfterCast]); + str.Add('--selective_import_space=' + falsetrue[spaceAfterImport]); + str.Add('--compact_labeled_statements=' + falsetrue[compactLabeledStatements]); +end; + +procedure TCEDfmtWidget.doApply(sender: TObject); +var + inp: string; + prc: TProcess; + str: TStringList; +begin + if not assigned(fDoc) then + exit; + + fBackup.Assign(fDoc.Lines); + prc := TProcess.create(nil); + try + fDmtWrapper.getCommandLine(prc.Parameters); + prc.Options:= prc.Options + [poUsePipes, poStderrToOutPut]; + prc.Executable:= exeFullName('dfmt' + exeExt); + prc.Execute; + inp := fDoc.Lines.Text; + prc.Input.Write(inp[1], length(inp)); + prc.CloseInput; + while prc.Running do (*!*); + try + str := TStringList.Create; + processOutputToStrings(prc,str); + fDoc.SelectAll; + fDoc.SelText:= str.Text; + except + fDoc.Lines.Assign(fBackup); + end; + finally + prc.free; + str.free; + end; +end; + +procedure TCEDfmtWidget.doCancel(sender: TObject); +begin + if not assigned(fDoc) then + exit; + + fDoc.Lines.Assign(fBackup); +end; +{$ENDREGION} + +end. + diff --git a/src/ce_infos.lfm b/src/ce_infos.lfm index 307cffee..877844c8 100644 --- a/src/ce_infos.lfm +++ b/src/ce_infos.lfm @@ -1,38 +1,38 @@ inherited CEInfoWidget: TCEInfoWidget Left = 713 - Height = 401 + Height = 423 Top = 245 - Width = 406 + Width = 411 BorderIcons = [biSystemMenu, biMinimize, biMaximize] Caption = 'About' - ClientHeight = 401 - ClientWidth = 406 + ClientHeight = 423 + ClientWidth = 411 inherited Back: TPanel - Height = 401 - Width = 406 - ClientHeight = 401 - ClientWidth = 406 + Height = 423 + Width = 411 + ClientHeight = 423 + ClientWidth = 411 inherited Content: TPanel - Height = 401 - Width = 406 - ClientHeight = 401 - ClientWidth = 406 + Height = 423 + Width = 411 + ClientHeight = 423 + ClientWidth = 411 object GroupBox1: TGroupBox[0] Left = 4 Height = 105 Top = 4 - Width = 398 + Width = 403 Align = alTop BorderSpacing.Around = 4 Caption = 'about' ClientHeight = 75 - ClientWidth = 394 + ClientWidth = 399 TabOrder = 0 object Label1: TLabel Left = 0 Height = 75 Top = 0 - Width = 394 + Width = 399 Align = alClient Alignment = taCenter AutoSize = False @@ -46,20 +46,20 @@ inherited CEInfoWidget: TCEInfoWidget end object GroupBox2: TGroupBox[1] Left = 4 - Height = 284 + Height = 306 Top = 113 - Width = 398 + Width = 403 Align = alClient BorderSpacing.Around = 4 Caption = 'tools status' - ClientHeight = 254 - ClientWidth = 394 + ClientHeight = 276 + ClientWidth = 399 TabOrder = 1 object boxTools: TScrollBox Left = 4 - Height = 246 + Height = 268 Top = 4 - Width = 386 + Width = 391 HorzScrollBar.Page = 1 VertScrollBar.Page = 1 Align = alClient diff --git a/src/ce_infos.pas b/src/ce_infos.pas index 3f3bb8fe..9b059a19 100644 --- a/src/ce_infos.pas +++ b/src/ce_infos.pas @@ -176,7 +176,11 @@ begin fIsModal := true; fIsDockable := false; // - toolItem := TToolInfo.Construct(self, tikOptional, 'gdc', + toolItem := TToolInfo.Construct(self, tikOptional, 'dfmt', + 'optional, the D source code formater, needed by the Dfmt commander widget'); + toolItem.Parent := boxTools; + toolItem.ReAlign; + toolItem := TToolInfo.Construct(self, tikOptional, 'dfmt', 'optional, the GDC D compiler'); toolItem.Parent := boxTools; toolItem.ReAlign; diff --git a/src/ce_main.pas b/src/ce_main.pas index d2fa54bc..8bd6cde2 100644 --- a/src/ce_main.pas +++ b/src/ce_main.pas @@ -12,7 +12,7 @@ uses ce_widget, ce_messages, ce_interfaces, ce_editor, ce_projinspect, ce_projconf, ce_search, ce_miniexplorer, ce_libman, ce_libmaneditor, ce_todolist, ce_observer, ce_toolseditor, ce_procinput, ce_optionseditor, ce_symlist, ce_mru, ce_processes, - ce_infos, ce_dubproject, ce_dialogs, ce_dubprojeditor, ce_gdb; + ce_infos, ce_dubproject, ce_dialogs, ce_dubprojeditor, ce_gdb, ce_dfmt; type @@ -225,6 +225,7 @@ type fInfoWidg: TCEInfoWidget; fDubProjWidg: TCEDubProjectEditorWidget; fGdbWidg: TCEGdbWidget; + fDfmtWidg: TCEDfmtWidget; fFirstShown: boolean; fProjFromCommandLine: boolean; @@ -812,6 +813,7 @@ begin fInfoWidg := TCEInfoWidget.create(self); fDubProjWidg:= TCEDubProjectEditorWidget.create(self); fGdbWidg := TCEGdbWidget.create(self); + fDfmtWidg := TCEDfmtWidget.create(self); getMessageDisplay(fMsgs); @@ -830,6 +832,7 @@ begin fWidgList.addWidget(@fInfoWidg); fWidgList.addWidget(@fDubProjWidg); fWidgList.addWidget(@fGdbWidg); + fWidgList.addWidget(@fDfmtWidg); fWidgList.sort(@CompareWidgCaption); for widg in fWidgList do diff --git a/wiki/wiki.todo.txt b/wiki/wiki.todo.txt index 091a6833..cc90ac5f 100644 --- a/wiki/wiki.todo.txt +++ b/wiki/wiki.todo.txt @@ -3,4 +3,5 @@ - project config widget, base/overridden config specifications. Note about pre/post build proc as their options cant be overridden. - project config widget, base/overridden config. screenshot for widget view 'All categories'. - applications options (MRU & reload last stuff). -- editor, toolbar description, split view description + screenshot. \ No newline at end of file +- editor, toolbar description, split view description + screenshot. +- widget section for Dfmt commander. \ No newline at end of file