mirror of https://gitlab.com/basile.b/dexed.git
improved todo list widget and tool
This commit is contained in:
parent
14565e51b8
commit
2968b95e0a
|
@ -18,7 +18,6 @@ object CurrentProject: TCEProject
|
||||||
end
|
end
|
||||||
item
|
item
|
||||||
name = 'release'
|
name = 'release'
|
||||||
outputOptions.inlining = True
|
|
||||||
outputOptions.boundsCheck = offAlways
|
outputOptions.boundsCheck = offAlways
|
||||||
outputOptions.optimizations = True
|
outputOptions.optimizations = True
|
||||||
outputOptions.release = True
|
outputOptions.release = True
|
||||||
|
@ -33,7 +32,7 @@ object CurrentProject: TCEProject
|
||||||
Sources.Strings = (
|
Sources.Strings = (
|
||||||
'cetodo.d'
|
'cetodo.d'
|
||||||
)
|
)
|
||||||
ConfigurationIndex = 0
|
ConfigurationIndex = 1
|
||||||
LibraryAliases.Strings = (
|
LibraryAliases.Strings = (
|
||||||
'libdparse'
|
'libdparse'
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,32 +1,39 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
TODO source code analyzer for Coedit projects/files
|
TODO source code analyzer for Coedit projects/files
|
||||||
|
|
||||||
Format: // TODO [fields] : text
|
## Format:
|
||||||
|
|
||||||
|
``
|
||||||
|
// TODO [fields] : text
|
||||||
|
``
|
||||||
|
|
||||||
- TODO: used to detect that the comment is a "TODO" comment. The keyword is not
|
- TODO: used to detect that the comment is a "TODO" comment. The keyword is not
|
||||||
case sensitive.
|
case sensitive.
|
||||||
|
|
||||||
- fields: an optional list of property with a format similar to the execution argument
|
- fields: an optional list of property with a format similar to the execution argument
|
||||||
of a program: -<char x><property for char x>-<char y><property for char y>.
|
of a program: `-<char x><property for char x>-<char y><property for char y>`.
|
||||||
possible fields include:
|
possible fields include:
|
||||||
- c: TODO category, e.g: -cserialization -cpersistence -cerrorhandling
|
- c: TODO category, e.g: _-cserialization_, _-cpersistence_, _ -cerrorhandling_.
|
||||||
- a: TODO assignee, e.g: -aMisterFreeze -aMadameMichou -aJhonSmith
|
- a: TODO assignee, e.g: _-aMisterFreeze_, _-aMadameMichou_, _-aJhonSmith_.
|
||||||
- p: TODO priority, eg: -p8 -p0
|
- p: TODO priority, eg: _-p8_, _-p0_.
|
||||||
- s: TODO status, e.g -sPartiallyFixed, -sDone
|
- s: TODO status, e.g _-sPartiallyFixed_, _-sDone_.
|
||||||
|
|
||||||
- text: the literal message, e.g: "set this property as const() to set it read only".
|
- text: the literal message, e.g: "set this property as const() to set it read only".
|
||||||
|
|
||||||
full examples:
|
## Examples:
|
||||||
|
|
||||||
// TODO: set this property as const() to set it read only.
|
``// TODO: set this property as const() to make it read-only.``
|
||||||
// TODO-cfeature: save this property in the inifile.
|
|
||||||
// TODO-cannnotations-p8: annotates the member of the module as @safe and if possible nothrow.
|
|
||||||
|
|
||||||
- widget to tool IPC:
|
``// TODO-cfeature: save this property in the inifile.``
|
||||||
|
|
||||||
The widget call the tool with a list of file as argument and read the process
|
``// TODO-cannnotations-p8: annotate the members of the module with @safe and if possible nothrow.``
|
||||||
output on exit. the widget expects to find some TODO items in LFM format, according
|
|
||||||
to the classes declarations of TTodoItems (the collection container) and TTodoItem(the collection item)
|
## Widget-to-tool IPC:
|
||||||
|
|
||||||
|
The widget calls the tool with a file list as argument and reads the process
|
||||||
|
output on exit. The widget expects to find some _TODO items_ in _LFM_ format,
|
||||||
|
according to the classes declarations of TTodoItems (the collection container)
|
||||||
|
and TTodoItem(the collection item).
|
||||||
|
|
||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
module cetodo;
|
module cetodo;
|
||||||
|
@ -38,18 +45,26 @@ import std.file, std.path, std.range;
|
||||||
// libdparse
|
// libdparse
|
||||||
import std.d.ast, std.d.lexer, std.d.parser;
|
import std.d.ast, std.d.lexer, std.d.parser;
|
||||||
|
|
||||||
|
/// Encapsulates the fields of a _TODO comment_.
|
||||||
private struct TodoItem
|
private struct TodoItem
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Enumerates the possible fields of _a TODO comment_.
|
||||||
|
* They must match the published member of the widget-side class TTodoItem.
|
||||||
|
*/
|
||||||
private enum TodoField {filename, line, text, category, assignee, priority, status}
|
private enum TodoField {filename, line, text, category, assignee, priority, status}
|
||||||
private string[TodoField] fFields;
|
private string[TodoField] fFields;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a TODO item with its fields.
|
* Constructs a TODO item with its fields.
|
||||||
* Params:
|
* Params:
|
||||||
* fname = the file where the item is located. mandatory.
|
* fname = the file where the _TODO comment_ is located. mandatory.
|
||||||
* line = the line where the item is located. mandatory.
|
* line = the line where the _TODO comment_ is located. mandatory.
|
||||||
* text = the TODO text. mandatory.
|
* text = the _TODO comment_ main text. mandatory.
|
||||||
|
* cat = the _TODO comment_ category, optional.
|
||||||
|
* ass = the _TODO comment_ assignee, optional.
|
||||||
|
* prior = the _TODO comment_ priority, as an integer litteral, optional.
|
||||||
|
* status = the _TODO comment_ status, optional.
|
||||||
*/
|
*/
|
||||||
@safe public this(string fname, string line, string text, string cat = "", string ass = "", string prior = "", string status = "")
|
@safe public this(string fname, string line, string text, string cat = "", string ass = "", string prior = "", string status = "")
|
||||||
{
|
{
|
||||||
|
@ -93,8 +108,8 @@ private alias TodoItems = TodoItem * [];
|
||||||
* Params:
|
* Params:
|
||||||
* args = a list of files to analyze.
|
* args = a list of files to analyze.
|
||||||
* Called each time a document is focused. Args is set using:
|
* Called each time a document is focused. Args is set using:
|
||||||
* - the symbolic string <CFF> (current file is not in a project).
|
* - the symbolic string `<CFF>` (current file is not in a project).
|
||||||
* - the symbolic string <CPFS> (current file is in a project).
|
* - the symbolic string `<CPFS>` (current file is in a project).
|
||||||
*/
|
*/
|
||||||
void main(string[] args)
|
void main(string[] args)
|
||||||
{
|
{
|
||||||
|
@ -111,12 +126,22 @@ void main(string[] args)
|
||||||
auto config = LexerConfig(f, StringBehavior.source);
|
auto config = LexerConfig(f, StringBehavior.source);
|
||||||
StringCache cache = StringCache(StringCache.defaultBucketCount);
|
StringCache cache = StringCache(StringCache.defaultBucketCount);
|
||||||
auto lexer = DLexer(src, config, &cache);
|
auto lexer = DLexer(src, config, &cache);
|
||||||
|
|
||||||
// analyze the tokens
|
// analyze the tokens
|
||||||
foreach(tok; lexer) token2TodoItem(tok, f, todoItems);
|
foreach(tok; lexer) token2TodoItem(tok, f, todoItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
// serialize the items using the pascal component streaming text format
|
// serialize the items using the pascal component streaming text format
|
||||||
foreach(todoItem; todoItems) todoItem.serialize(LfmString);
|
foreach(todoItem; todoItems) todoItem.serialize(LfmString);
|
||||||
// the widget has the TODOs in the output
|
|
||||||
|
// separates the data sent in procOutput() from those sent in procTerminated()
|
||||||
|
// TODO-cbugfix: find a way to determine if stdout has been written
|
||||||
|
if (stdout.size != 0) {
|
||||||
|
stdout.flush;
|
||||||
|
readln;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the widget has the LFM script in the output, it reads in procTerminated()
|
||||||
if (LfmString.length) writefln("object TTodoItems\n items = <\n%s>\nend", LfmString);
|
if (LfmString.length) writefln("object TTodoItems\n items = <\n%s>\nend", LfmString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,13 @@ interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, FileUtil, TreeFilterEdit, ListFilterEdit, Forms, Controls,
|
Classes, SysUtils, FileUtil, TreeFilterEdit, ListFilterEdit, Forms, Controls,
|
||||||
Graphics, Dialogs, ExtCtrls, Menus, Buttons, StdCtrls, ComCtrls, ce_widget,
|
Graphics, Dialogs, ExtCtrls, Menus, Buttons, StdCtrls, ComCtrls, asyncprocess,
|
||||||
process, ce_common, ce_interfaces, ce_synmemo, ce_project, ce_symstring;
|
ce_widget, process, ce_common, ce_interfaces, ce_synmemo, ce_project, ce_symstring;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
|
TTodoContext = (tcNone, tcProject, tcFile);
|
||||||
|
|
||||||
// represents a TODO item
|
// represents a TODO item
|
||||||
// warning: the props names must be kept in sync with the values set in the tool.
|
// warning: the props names must be kept in sync with the values set in the tool.
|
||||||
TTodoItem = class(TCollectionItem)
|
TTodoItem = class(TCollectionItem)
|
||||||
|
@ -64,6 +66,7 @@ type
|
||||||
fDoc: TCESynMemo;
|
fDoc: TCESynMemo;
|
||||||
fToolProcess: TCheckedAsyncProcess;
|
fToolProcess: TCheckedAsyncProcess;
|
||||||
fTodos: TTodoItems;
|
fTodos: TTodoItems;
|
||||||
|
fLogMessager: TCELogMessageSubject;
|
||||||
// ICEMultiDocObserver
|
// ICEMultiDocObserver
|
||||||
procedure docNew(aDoc: TCESynMemo);
|
procedure docNew(aDoc: TCESynMemo);
|
||||||
procedure docFocused(aDoc: TCESynMemo);
|
procedure docFocused(aDoc: TCESynMemo);
|
||||||
|
@ -76,6 +79,7 @@ type
|
||||||
procedure projFocused(aProject: TCEProject);
|
procedure projFocused(aProject: TCEProject);
|
||||||
procedure projCompiling(aProject: TCEProject);
|
procedure projCompiling(aProject: TCEProject);
|
||||||
// TODOlist things
|
// TODOlist things
|
||||||
|
function getContext: TTodoContext;
|
||||||
procedure killToolProcess;
|
procedure killToolProcess;
|
||||||
procedure callToolProcess;
|
procedure callToolProcess;
|
||||||
procedure procTerminated(sender: TObject);
|
procedure procTerminated(sender: TObject);
|
||||||
|
@ -157,6 +161,7 @@ var
|
||||||
begin
|
begin
|
||||||
inherited;
|
inherited;
|
||||||
fTodos := TTodoItems.Create(self);
|
fTodos := TTodoItems.Create(self);
|
||||||
|
fLogMessager := TCELogMessageSubject.create;
|
||||||
lstItems.OnDblClick := @lstItemsDoubleClick;
|
lstItems.OnDblClick := @lstItemsDoubleClick;
|
||||||
btnRefresh.OnClick := @btnRefreshClick;
|
btnRefresh.OnClick := @btnRefreshClick;
|
||||||
|
|
||||||
|
@ -177,6 +182,7 @@ end;
|
||||||
destructor TCETodoListWidget.destroy;
|
destructor TCETodoListWidget.destroy;
|
||||||
begin
|
begin
|
||||||
killToolProcess;
|
killToolProcess;
|
||||||
|
fLogMessager.Free;
|
||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
{$ENDREGION}
|
{$ENDREGION}
|
||||||
|
@ -236,6 +242,19 @@ end;
|
||||||
{$ENDREGION}
|
{$ENDREGION}
|
||||||
|
|
||||||
{$REGION Todo list things ------------------------------------------------------}
|
{$REGION Todo list things ------------------------------------------------------}
|
||||||
|
function TCETodoListWidget.getContext: TTodoContext;
|
||||||
|
begin
|
||||||
|
result := tcNone;
|
||||||
|
//
|
||||||
|
if ((fProj = nil) and (fDoc = nil)) then exit;
|
||||||
|
if ((fProj = nil) and (fDoc <> nil)) then exit(tcFile);
|
||||||
|
if ((fProj <> nil) and (fDoc = nil)) then exit(tcProject);
|
||||||
|
//
|
||||||
|
result := tcFile;
|
||||||
|
if not FileExists(fDoc.fileName) then exit;
|
||||||
|
if fProj.isProjectSource(fDoc.fileName) then exit(tcProject);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCETodoListWidget.killToolProcess;
|
procedure TCETodoListWidget.killToolProcess;
|
||||||
begin
|
begin
|
||||||
if fToolProcess = nil then exit;
|
if fToolProcess = nil then exit;
|
||||||
|
@ -247,16 +266,14 @@ end;
|
||||||
|
|
||||||
procedure TCETodoListWidget.callToolProcess;
|
procedure TCETodoListWidget.callToolProcess;
|
||||||
var
|
var
|
||||||
asProject: boolean;
|
ctxt: TTodoContext;
|
||||||
begin
|
begin
|
||||||
clearTodoList;
|
clearTodoList;
|
||||||
if not exeInSysPath(ToolExeName) then exit;
|
if not exeInSysPath(ToolExeName) then exit;
|
||||||
|
ctxt := getContext;
|
||||||
|
if ctxt = tcNone then exit;
|
||||||
if (fDoc = nil) and (fProj = nil)then exit;
|
if (fDoc = nil) and (fProj = nil)then exit;
|
||||||
//
|
//
|
||||||
if (fProj <> nil) then if (fDoc = nil) then asProject := true;
|
|
||||||
if (fProj = nil) then if (fDoc <> nil) then asProject := false;
|
|
||||||
if (fProj <> nil) then if (fDoc <> nil) then asProject := (fProj.isProjectSource(fDoc.fileName));
|
|
||||||
//
|
|
||||||
killToolProcess;
|
killToolProcess;
|
||||||
// process parameter
|
// process parameter
|
||||||
fToolProcess := TCheckedAsyncProcess.Create(nil);
|
fToolProcess := TCheckedAsyncProcess.Create(nil);
|
||||||
|
@ -266,16 +283,32 @@ begin
|
||||||
fToolProcess.OnTerminate := @procTerminated;
|
fToolProcess.OnTerminate := @procTerminated;
|
||||||
fToolProcess.OnReadData := @procOutput;
|
fToolProcess.OnReadData := @procOutput;
|
||||||
// files passed to the tool argument
|
// files passed to the tool argument
|
||||||
if asProject then fToolProcess.Parameters.Add(symbolExpander.get('<CPFS>'))
|
if ctxt = tcProject then fToolProcess.Parameters.Add(symbolExpander.get('<CPFS>'))
|
||||||
else fToolProcess.Parameters.AddText(symbolExpander.get('<CFF>'));
|
else fToolProcess.Parameters.AddText(symbolExpander.get('<CFF>'));
|
||||||
//
|
//
|
||||||
fToolProcess.Execute;
|
fToolProcess.Execute;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCETodoListWidget.procOutput(sender: TObject);
|
procedure TCETodoListWidget.procOutput(sender: TObject);
|
||||||
|
var
|
||||||
|
str: TStringList;
|
||||||
|
msg: string;
|
||||||
|
ctxt: TTodoContext;
|
||||||
begin
|
begin
|
||||||
// output during run-time
|
subjLmFromString(fLogMessager, 'called even if nothing in output', fProj, amcProj, amkAuto);
|
||||||
// should not be called
|
str := TStringList.Create;
|
||||||
|
try
|
||||||
|
processOutputToStrings(TAsyncProcess(fToolProcess), str);
|
||||||
|
ctxt := getContext;
|
||||||
|
for msg in str do case ctxt of
|
||||||
|
tcNone: subjLmFromString(fLogMessager, msg, nil, amcMisc, amkAuto);
|
||||||
|
tcFile: subjLmFromString(fLogMessager, msg, fDoc, amcEdit, amkAuto);
|
||||||
|
tcProject:subjLmFromString(fLogMessager, msg, fProj, amcProj, amkAuto);
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
str.Free;
|
||||||
|
end;
|
||||||
|
fToolProcess.Input.WriteByte($0A);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCETodoListWidget.procTerminated(sender: TObject);
|
procedure TCETodoListWidget.procTerminated(sender: TObject);
|
||||||
|
|
Loading…
Reference in New Issue