From daa90d33be753c21c9c8c015a69f3955682898ca Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Mon, 7 Dec 2015 01:14:05 +0100 Subject: [PATCH] custom tools, removed chainAfter/Before and added more powerful chaining system. - it allows to redirected output stream to next chain item input stream. - previous cahin are reloaded once then never saved again. --- cesetup/cesetup.d | 4 +- src/ce_editor.pas | 3 + src/ce_tools.pas | 182 ++++++++++++++++++++++++----------------- src/ce_toolseditor.pas | 1 - wiki/wiki.txt | 49 +++++------ 5 files changed, 138 insertions(+), 101 deletions(-) diff --git a/cesetup/cesetup.d b/cesetup/cesetup.d index 9dd7a659..fc5cb14b 100644 --- a/cesetup/cesetup.d +++ b/cesetup/cesetup.d @@ -268,7 +268,7 @@ string targetFilename(Resource resource) } } -/// Extracts and write a resource to a file. +/// Extracts and writes a resource to a file. bool installResource(Resource resource) { const string fname = resource.targetFilename; @@ -293,7 +293,7 @@ bool installResource(Resource resource) return true; } -/// Deletes the file creates for a resource +/// Deletes the file created for a resource bool uninstallResource(Resource resource) { const string fname = resource.targetFilename; diff --git a/src/ce_editor.pas b/src/ce_editor.pas index 7c1fa559..eecc849c 100644 --- a/src/ce_editor.pas +++ b/src/ce_editor.pas @@ -20,6 +20,9 @@ type procedure SetVisible(Value: Boolean); override; end; + + //TODO-crefact: moves the macro recorded to TCESynMemo, + add visual feedback + declare shortcuts ecXXXX + { TCEEditorWidget } TCEEditorWidget = class(TCEWidget, ICEMultiDocObserver, ICEMultiDocHandler) diff --git a/src/ce_tools.pas b/src/ce_tools.pas index ff03f822..5ea66e93 100644 --- a/src/ce_tools.pas +++ b/src/ce_tools.pas @@ -11,8 +11,12 @@ uses type + TCEToolItems = class; + TCEToolItem = class(TCollectionItem) private + fToolItems: TCEToolItems; + fNextToolAlias: string; fProcess: TCEProcess; fExecutable: TCEFilename; fWorkingDir: TCEPathname; @@ -23,17 +27,17 @@ type fQueryParams: boolean; fClearMessages: boolean; fEditorToInput: boolean; - fChainBefore: TStringList; - fChainAfter: TStringList; + fOutputToNext: boolean; fShortcut: TShortcut; fMsgs: ICEMessagesDisplay; - procedure setParameters(aValue: TStringList); - procedure setChainBefore(aValue: TStringList); - procedure setChainAfter(aValue: TStringList); + procedure setParameters(value: TStringList); procedure processOutput(sender: TObject); - procedure execute; + procedure setToolAlias(value: string); + // + procedure setChainBefore(value: TStringList); + procedure setChainAfter(value: TStringList); published - property toolAlias: string read fToolAlias write fToolAlias; + property toolAlias: string read fToolAlias write setToolAlias; property options: TProcessOptions read fOpts write fOpts; property executable: TCEFilename read fExecutable write fExecutable; property workingDirectory: TCEPathname read fWorkingDir write fWorkingDir; @@ -42,22 +46,33 @@ type property queryParameters: boolean read fQueryParams write fQueryParams; property clearMessages: boolean read fClearMessages write fClearMessages; property editorToInput: boolean read fEditorToInput write fEditorToInput; - property chainBefore: TStringList read fChainBefore write setchainBefore; - property chainAfter: TStringList read fChainAfter write setChainAfter; property shortcut: TShortcut read fShortcut write fShortcut; + property nextToolAlias: string read fNextToolAlias write fNextToolAlias; + property outputToNext: boolean read fOutputToNext write fOutputToNext; + // + property chainBefore: TStringList write setChainBefore stored false; deprecated; + property chainAfter: TStringList write setChainAfter stored false; deprecated; public constructor create(ACollection: TCollection); override; destructor destroy; override; procedure assign(Source: TPersistent); override; + // + procedure execute(previous: TCEToolItem); + property process: TCEProcess read fProcess; + end; + + TCEToolItems = class(TCollection) + public + function findTool(const value: string): TCEToolItem; end; TCETools = class(TWritableLfmTextComponent, ICEMainMenuProvider, ICEEditableShortcut, ICEMultiDocObserver) private - fTools: TCollection; + fTools: TCEToolItems; fShctCount: Integer; fDoc: TCESynMemo; function getTool(index: Integer): TCEToolItem; - procedure setTools(const aValue: TCollection); + procedure setTools(value: TCEToolItems); // procedure menuDeclare(item: TMenuItem); procedure menuUpdate(item: TMenuItem); @@ -72,7 +87,7 @@ type function scedWantNext(out category, identifier: string; out aShortcut: TShortcut): boolean; procedure scedSendItem(const category, identifier: string; aShortcut: TShortcut); published - property tools: TCollection read fTools write setTools; + property tools: TCEToolItems read fTools write setTools; public constructor create(aOwner: TComponent); override; destructor destroy; override; @@ -97,73 +112,84 @@ const toolsFname = 'tools.txt'; {$REGION TCEToolItem -----------------------------------------------------------} +function TCEToolItems.findTool(const value: string): TCEToolItem; +var + item: TCollectionItem; +begin + for item in self do + if TCEToolItem(item).toolAlias = value then + exit(TCEToolItem(item)); + exit(nil); +end; + constructor TCEToolItem.create(ACollection: TCollection); begin inherited; - fToolAlias := format('', [ID]); + fToolItems := TCEToolItems(ACollection); + fToolAlias := format('', [ID]); fParameters := TStringList.create; - fChainBefore := TStringList.Create; - fChainAfter := TStringList.Create; end; destructor TCEToolItem.destroy; begin fParameters.Free; - fChainAfter.Free; - fChainBefore.Free; ce_processes.killProcess(fProcess); inherited; end; +procedure TCEToolItem.setChainBefore(value: TStringList); +begin + // kept to reload old setting files. 'xhainBefore' is not saved anymore. +end; + +procedure TCEToolItem.setChainAfter(value: TStringList); +begin + // kept to reload old setting files. 'chainAfter' is not saved anymore. +end; + procedure TCEToolItem.assign(Source: TPersistent); var tool: TCEToolItem; begin + // only used to clone a tool: so don't copy everything. if Source is TCEToolItem then begin tool := TCEToolItem(Source); // - toolAlias := tool.toolAlias; - chainAfter.Assign(tool.chainAfter); - chainBefore.Assign(tool.chainBefore); - queryParameters := tool.queryParameters; - clearMessages := tool.clearMessages; - fOpts := tool.fOpts; + toolAlias := tool.toolAlias; + queryParameters := tool.queryParameters; + clearMessages := tool.clearMessages; + options := tool.options; + executable := tool.executable; + workingDirectory := tool.workingDirectory; + editorToInput := tool.editorToInput; + showWindows := tool.showWindows; parameters.Assign(tool.parameters); - executable := tool.executable; - workingDirectory := tool.workingDirectory; end else inherited; end; -procedure TCEToolItem.setParameters(aValue: TStringList); +procedure TCEToolItem.setParameters(value: TStringList); begin - fParameters.Assign(aValue); + fParameters.Assign(value); end; -procedure TCEToolItem.setChainBefore(aValue: TStringList); +procedure TCEToolItem.setToolAlias(value: string); var - i: Integer; + i: integer = 0; begin - fChainBefore.Assign(aValue); - i := fChainBefore.IndexOf(fToolAlias); - if i <> -1 then - fChainBefore.Delete(i); + while fToolItems.findTool(value) <> nil do + begin + value += intToStr(i); + i += 1; + end; + fToolAlias := value; end; -procedure TCEToolItem.setChainAfter(aValue: TStringList); -var - i: Integer; -begin - fChainAfter.Assign(aValue); - i := fChainAfter.IndexOf(fToolAlias); - if i <> -1 then - fChainAfter.Delete(i); -end; - -procedure TCEToolItem.execute; +procedure TCEToolItem.execute(previous: TCEToolItem); var prm: string; + inp: string; begin ce_processes.killProcess(fProcess); // @@ -177,33 +203,53 @@ begin fProcess.Executable := exeFullName(symbolExpander.get(fExecutable)); fProcess.ShowWindow := fShowWin; fProcess.CurrentDirectory := symbolExpander.get(fWorkingDir); + for prm in fParameters do if not isStringDisabled(prm) then + fProcess.Parameters.AddText(symbolExpander.get(prm)); if fQueryParams then begin prm := ''; if InputQuery('Parameters', '', prm) then - if prm <> '' then fProcess.Parameters.DelimitedText := symbolExpander.get(prm); + if prm <> '' then fProcess.Parameters.AddText(symbolExpander.get(prm)); end; - for prm in fParameters do if not isStringDisabled(prm) then - fProcess.Parameters.AddText(symbolExpander.get(prm)); ensureNoPipeIfWait(fProcess); // if FileExists(fProcess.Executable) then + begin fProcess.Execute; + if (previous <> nil) and (previous.outputToNext) + and (poUsePipes in previous.Options) and (poUsePipes in Options) then + begin + setLength(inp, previous.process.OutputStack.Size); + previous.process.OutputStack.Position:=0; + previous.process.OutputStack.Read(inp[1], length(inp)); + fProcess.Input.Write(inp[1], length(inp)); + fProcess.CloseInput; + end; + end; end; procedure TCEToolItem.processOutput(sender: TObject); var lst: TStringList; str: string; + nxt: TCEToolItem; begin - getMessageDisplay(fMsgs); - lst := TStringList.Create; - try - fProcess.getFullLines(lst); - for str in lst do - fMsgs.message(str, nil, amcMisc, amkAuto); - finally - lst.Free; + if ((not fOutputToNext) or (fNextToolAlias = '')) and (poUsePipes in options) then + begin + getMessageDisplay(fMsgs); + lst := TStringList.Create; + try + fProcess.getFullLines(lst); + for str in lst do + fMsgs.message(str, nil, amcMisc, amkAuto); + finally + lst.Free; + end; + end; + if (not fProcess.Running) and (fNextToolAlias <> '') then + begin + nxt := fToolItems.findTool(fNextToolAlias); + if assigned(nxt) then nxt.execute(self); end; end; {$ENDREGION --------------------------------------------------------------------} @@ -214,7 +260,7 @@ var fname: string; begin inherited; - fTools := TCollection.Create(TCEToolItem); + fTools := TCEToolItems.Create(TCEToolItem); fname := getCoeditDocPath + toolsFname; if fileExists(fname) then loadFromFile(fname); // @@ -336,13 +382,12 @@ begin if fDoc <> aDoc then exit; fDoc := nil; end; - {$ENDREGION} {$REGION Tools things ----------------------------------------------------------} -procedure TCETools.setTools(const aValue: TCollection); +procedure TCETools.setTools(value: TCEToolItems); begin - fTools.Assign(aValue); + fTools.Assign(value); end; function TCETools.getTool(index: Integer): TCEToolItem; @@ -357,31 +402,18 @@ end; procedure TCETools.executeTool(aTool: TCEToolItem); var - nme: string; txt: string; - chained: TCollectionItem; begin if aTool = nil then exit; // - for nme in aTool.chainBefore do - for chained in fTools do - if TCEToolItem(chained).toolAlias = nme then - if TCEToolItem(chained).toolAlias <> aTool.toolAlias then - TCEToolItem(chained).execute; - // - aTool.execute; - if aTool.editorToInput and assigned(fDoc) and (poUsePipes in aTool.options) then + aTool.execute(nil); + if aTool.editorToInput and assigned(fDoc) and (poUsePipes in aTool.options) + and (aTool.fProcess.Input <> nil) then begin txt := fDoc.Text; aTool.fProcess.Input.Write(txt[1], length(txt)); aTool.fProcess.CloseInput; end; - // - for nme in aTool.chainAfter do - for chained in fTools do - if TCEToolItem(chained).toolAlias = nme then - if TCEToolItem(chained).toolAlias <> aTool.toolAlias then - TCEToolItem(chained).execute; end; procedure TCETools.executeTool(aToolIndex: Integer); diff --git a/src/ce_toolseditor.pas b/src/ce_toolseditor.pas index 06a07dd6..78d44d34 100644 --- a/src/ce_toolseditor.pas +++ b/src/ce_toolseditor.pas @@ -11,7 +11,6 @@ uses type { TCEToolsEditorWidget } - TCEToolsEditorWidget = class(TCEWidget) BtnAddTool: TBitBtn; btnMoveDown: TBitBtn; diff --git a/wiki/wiki.txt b/wiki/wiki.txt index 6cd255d3..72642546 100644 --- a/wiki/wiki.txt +++ b/wiki/wiki.txt @@ -32,7 +32,7 @@ Welcome to Coedit Wiki, the documentation source for the small Windows & Linux IDE for the D programming language. A summary of the content is accessible in the right side-bar. -*Note that this document is based on Coedit 2 alpha 2 and it does not represent yet the changes made to the development version* +*Note that this document is based on Coedit 2 development version and it does not represent anymore the latest official stable release* ![](https://raw.githubusercontent.com/BBasile/CoeditWikiData/master/coedit.win7.33.png) ![](https://raw.githubusercontent.com/BBasile/CoeditWikiData/master/coedit.linux.kde.33.png) @@ -106,7 +106,7 @@ libc.so.6 Download ans setup the tools: -* [Download](http://lazarus.freepascal.org/index.php?page=downloads) and setup the latest Lazarus (1.4.2) version and FPC / FPC sources (2.6.4) for your platform. +* [Download](http://lazarus.freepascal.org/index.php?page=downloads) and setup the latest Lazarus (1.4.4) version and FPC / FPC sources (2.6.4) for your platform. * Windows: the three packages are bundled in an installer. Even on Windows 64 bit, the 32 version must be setup. * Linux: the three packages must be downloaded and setup individually. Take care to the version number because the official rpm/deb source of a Linux distribution does not always propose the latest version ! @@ -145,7 +145,7 @@ See the products documentation for more information. Any Pascal or Delphi programmer who has interest to the D language can contribute. The process is based on _git_ and _Github_, using what's often called the _fork push pull_ model: -- _fork_ the _Coedit_ repository in your _Github_ account. +- fork the _Coedit_ repository in your _Github_ account. - clone this fork to your computer. - using Lazarus and FPC, develop, fix, optimize, do whatever could improve Coedit. - _push_ your changes to your online fork. @@ -314,12 +314,12 @@ _DCD_ also has a native configuration system. Refer to the official [_Readme_](h ### Usage -- CTRL + SPACE: invokes the completion. +- CTRL + SPACE: Calls the completion menu or auto-completes if possible. The default shortcut can be modified in the [shortcut editor][lnk_widg_opts]. - . invokes the completion if the editor option _autoDotDelay_ is greater than 0. -- CTRL + SHIFT + UP: quick jump to the declaration of the symbol located at the cursor position. +- CTRL + SHIFT + UP: Jumps to the declaration of the symbol located at the cursor. The default shortcut can be modified. - CTRL + LEFT MOUSE BUTTON: ditto. -- (: gets the function call tips. -- ): closes the call tips window. +- (: Gets the function call tips. +- ): Closes the call tips window. - ESC: ditto. Documentation comments associated to a symbol are displayed when hovering the symbol with the mouse. @@ -407,12 +407,12 @@ The _source editor widget_ is a standard code editor, specialized for highlighti It's based on the [**Synedit**](http://wiki.freepascal.org/SynEdit) suite, a powerful set of Pascal components and classes, which can be described as a _"Scintilla for Pascal"_. It features: -- folding (curly brackets blocks, multi-line strings, block comments). +- folding (curly brackets blocks, multi-line strings, block comments, nested block comments, DDoc comments blocks). - colorization of the following categories: keywords, numbers, symbols, comments, ASM operands and identifiers, DDoc comments. - colorization of the current identifier in the whole view. - standard keyboard navigation shortcuts CTRL + (SHIFT +) LEFT/RIGHT, CTRL + HOME, CTRL + END etc. - macro recording and playback using CTRL+SHIFT+R (start/stop recording) or CTRL+SHIFT+P (play). -- synchro-edit (activated when clicking the pen icon located in the gutter). +- synchro-edit (activated when clicking the pen icon located in the gutter, or with the shortcut CTRL+E and CTRL+SHIFT+E). - zoom: (CTRL+WHEEL, CTRL+MIDDLE MB, CTRL++, CTRL+-, CTRL+.). - display cache: for each document, the zoom ratio, the folds and the caret position are saved between two sessions. A cache file has a fixed life-time of three months from its last modification. - drag drop editing. @@ -455,12 +455,12 @@ The editor shortcuts are listed there: ![](https://raw.githubusercontent.com/BBasile/CoeditWikiData/master/optshortcut.png) -Note that you can edit text files in Coedit too (as well as any other file type suc as _*.dd_ D documentation files) +Note that you can edit text files in Coedit too (as well as any other file type such as _*.dd_ D documentation files) A simple highlighter is automatically set for this purpose: ![](https://raw.githubusercontent.com/BBasile/CoeditWikiData/master/sourceditor2.png) -It's also customizable in the option editor but the colorizer only recognizes identifiers and symbols. +It's also customizable in the option editor but the highlighter only recognizes identifiers and symbols. ## Find & replace widget @@ -694,7 +694,7 @@ Unfiltered options, sub categories can be expanded or collapsed. The field ***na ## DUB project editor -The DUB project editor is widget is devided in two panels: +The DUB project editor is widget is divided in two panels: ### Inspector @@ -751,13 +751,15 @@ This is a recommended setting because if a run-time error happens, it will be im ## Custom tools widget This widget allows to define a set of third party applications that can be launched from Coedit. -Thanks to the [symbolic strings][lnk_sym] it's possible for a tool to be aware of the document location or even to get the list of the sources used by a project. +The tools are not just applications that are launched from the software. Since they support [symbolic strings][lnk_sym] they can directly perform some actions on the current source file, in its directory, on all the sources of a project, etc. The tools can even be chained and the output stream of an item redirected to the input stream of the next. A few typical examples: - launch a console with its working directory set to the project file directory. - analyze the current document in _Dscanner_. (see the tutorials). -- generate the documentation for all the project D sources. -- use a custom build tool (_make_, _DUB_). +- format the current document with _dfmt_. +- generate the documentation for all the project sources. (see the tutorials). +- launch a custom build tool (_make_, _DUB_). +- launch a script that will zip and upload the latest project build. ![](https://raw.githubusercontent.com/BBasile/CoeditWikiData/master/toolseditor1.png) @@ -768,21 +770,22 @@ Toolbar: - ![](https://raw.githubusercontent.com/BBasile/Coedit/master/icons/window/application_flash.png): executes selected tool, according to the options it's associated to. This also works by double-clicking a tool alias. - ![](https://raw.githubusercontent.com/BBasile/Coedit/master/icons/window/application_double.png): clones selected tool. -A tool can be selected from the left side of the widget. If selected, a property inspector displays the options that can be defined: -- chainBefore: allow to define a list of tool to execute before the item. A list item has to match one of the *toolAlias* already defined. By default a tool is executed asynchronously. If it's desirable that a tool must finish before the next starts then **poWaitOnExit** must be set in the options. -- chainAfter. Idem but the tools defined in the list are executed after the item. -- clearMessages: if the tool standard output is redirected to the [messages widget][lnk_widg_msg] then the previous messages are cleared before the execution. +A tool can be selected from the left side of the widget. If selected, a property inspector displays the options that can be edited: + +- clearMessages: if the tool standard output is redirected to the [messages widget][lnk_widg_msg] then the previous messages are cleared before the execution. The output is redirected to the messages when **popUsePipes** is set and if the **nextToolALias** is empty. - editorToInput: when set, the content of the current editor is streamed to the tool standard input. - executable: the tool file name. If the system cannot find its path in the environment variables then it must be included. The field can include a [symbolic string][lnk_sym]. +- nextToolAlias: defines the alias of another tool that will be launched after this one returns. - options: various options for the process to create. If you set **popUsePipes** and **poStdErrToOutput** to true, then the standard output will be redirected to the message widget, category Misc. +- outputToNext: if **popUsePipes** is set in the options and if the next tool is defined then the next tool will see its input stream filled with the output stream. - parameters: allows to define the parameters, switches and options passed to the process. As usual, one item per line, no quotes. The items can include a [symbolic string][lnk_sym]. - queryParameters: if set to true then a small input query dialog will be shown before executing the tool. It can be filled with more _--para --meters_. -- shortcut: allow to define the keystroke to launch the tool. The shortcut can also be edited in the [options editor][lnk_widg_opts]. -- showWindow: allow to define how the tool window is displayed. Set to swoHIDE if the tool std out is redirected. +- shortcut: allow to define the keystroke used to launch the tool. The shortcut can also be edited in the [options editor][lnk_widg_opts]. +- showWindow: allow to define how the tool window is displayed. Set to *swoHIDE* if the tool std out is redirected. - toolAlias: the friendly name associated to the tool. -- workingDirectory: directory in which starts the tool. Not to mismatch with its path. The field can include a [symbolic string][lnk_sym]. +- workingDirectory: the directory in which the tool starts. Not to mismatch with its path. The field can include a [symbolic string][lnk_sym]. -The tools configuration is saved between each cession, in the same folder as the application [options][lnk_widg_opts]. +The configuration is saved between each session, in the same folder as the application [options][lnk_widg_opts]. ## Todo list