mirror of https://gitlab.com/basile.b/dexed.git
add an editor command to insert ddoc templates, close #135
This commit is contained in:
parent
260323080f
commit
6be3267993
|
@ -42,6 +42,7 @@ object CurrentProject: TCENativeProject
|
||||||
'src/mainfun.d'
|
'src/mainfun.d'
|
||||||
'src/common.d'
|
'src/common.d'
|
||||||
'src/halstead.d'
|
'src/halstead.d'
|
||||||
|
'src/ddoc_template.d'
|
||||||
)
|
)
|
||||||
ConfigurationIndex = 1
|
ConfigurationIndex = 1
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,193 @@
|
||||||
|
module ddoc_template;
|
||||||
|
|
||||||
|
import
|
||||||
|
std.stdio;
|
||||||
|
import
|
||||||
|
iz.memory;
|
||||||
|
import
|
||||||
|
dparse.ast, dparse.lexer, dparse.parser, dparse.rollback_allocator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the declaration at caretLine and write its ddoc template
|
||||||
|
* in the standard output.
|
||||||
|
*/
|
||||||
|
void getDdocTemplate(const(Module) mod, int caretLine)
|
||||||
|
{
|
||||||
|
DDocTemplateGenerator dtg = construct!DDocTemplateGenerator(caretLine);
|
||||||
|
dtg.visit(mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
final class DDocTemplateGenerator: ASTVisitor
|
||||||
|
{
|
||||||
|
alias visit = ASTVisitor.visit;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
int _caretline;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
this(int caretline)
|
||||||
|
{
|
||||||
|
_caretline = caretline;
|
||||||
|
}
|
||||||
|
|
||||||
|
override void visit(const(FunctionDeclaration) decl)
|
||||||
|
{
|
||||||
|
if (decl.name.line == _caretline)
|
||||||
|
{
|
||||||
|
writeln("/**\n * <short description> \n * \n * <detailed description>\n *");
|
||||||
|
|
||||||
|
if (decl.templateParameters || decl.parameters)
|
||||||
|
{
|
||||||
|
writeln(" * Params:");
|
||||||
|
|
||||||
|
if (decl.templateParameters && decl.templateParameters.templateParameterList)
|
||||||
|
{
|
||||||
|
foreach(const TemplateParameter p; decl.templateParameters
|
||||||
|
.templateParameterList.items)
|
||||||
|
{
|
||||||
|
if (p.templateAliasParameter)
|
||||||
|
writeln(" * ", p.templateAliasParameter.identifier.text, " = <description>");
|
||||||
|
else if (p.templateTupleParameter)
|
||||||
|
writeln(" * ", p.templateTupleParameter.identifier.text, " = <description>");
|
||||||
|
else if (p.templateTypeParameter)
|
||||||
|
writeln(" * ", p.templateTypeParameter.identifier.text, " = <description>");
|
||||||
|
else if (p.templateValueParameter)
|
||||||
|
writeln(" * ", p.templateValueParameter.identifier.text, " = <description>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (decl.parameters)
|
||||||
|
{
|
||||||
|
foreach(i, const Parameter p; decl.parameters.parameters)
|
||||||
|
{
|
||||||
|
if (p.name.text != "")
|
||||||
|
writeln(" * ", p.name.text, " = <description>");
|
||||||
|
else
|
||||||
|
writeln(" * __param", i, " = <description>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decl.returnType)
|
||||||
|
{
|
||||||
|
if (decl.returnType.type2 && decl.returnType.type2
|
||||||
|
&& decl.returnType.type2.builtinType != tok!"void")
|
||||||
|
writeln(" * \n * Returns: <return description>");
|
||||||
|
}
|
||||||
|
|
||||||
|
writeln(" */");
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (decl.name.line > _caretline)
|
||||||
|
return;
|
||||||
|
decl.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
override void visit(const(TemplateDeclaration) decl)
|
||||||
|
{
|
||||||
|
visitTemplateOrAggregate(decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
override void visit(const(ClassDeclaration) decl)
|
||||||
|
{
|
||||||
|
visitTemplateOrAggregate(decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
override void visit(const(StructDeclaration) decl)
|
||||||
|
{
|
||||||
|
visitTemplateOrAggregate(decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
override void visit(const(UnionDeclaration) decl)
|
||||||
|
{
|
||||||
|
visitTemplateOrAggregate(decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visitTemplateOrAggregate(T)(const(T) decl)
|
||||||
|
{
|
||||||
|
if (decl.name.line == _caretline)
|
||||||
|
{
|
||||||
|
writeln("/**\n * <short description> \n * \n * <detailed description>\n *");
|
||||||
|
|
||||||
|
if (decl.templateParameters)
|
||||||
|
{
|
||||||
|
writeln(" * Params:");
|
||||||
|
|
||||||
|
if (decl.templateParameters && decl.templateParameters.templateParameterList)
|
||||||
|
{
|
||||||
|
foreach(const TemplateParameter p; decl.templateParameters
|
||||||
|
.templateParameterList.items)
|
||||||
|
{
|
||||||
|
if (p.templateAliasParameter)
|
||||||
|
writeln(" * ", p.templateAliasParameter.identifier.text, " = <description>");
|
||||||
|
else if (p.templateTupleParameter)
|
||||||
|
writeln(" * ", p.templateTupleParameter.identifier.text, " = <description>");
|
||||||
|
else if (p.templateTypeParameter)
|
||||||
|
writeln(" * ", p.templateTypeParameter.identifier.text, " = <description>");
|
||||||
|
else if (p.templateValueParameter)
|
||||||
|
writeln(" * ", p.templateValueParameter.identifier.text, " = <description>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
writeln(" */");
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (decl.name.line > _caretline)
|
||||||
|
return;
|
||||||
|
decl.accept(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
version(unittest)
|
||||||
|
{
|
||||||
|
DDocTemplateGenerator parseAndVisit(const(char)[] source, int caretLine)
|
||||||
|
{
|
||||||
|
writeln;
|
||||||
|
RollbackAllocator allocator;
|
||||||
|
LexerConfig config = LexerConfig("", StringBehavior.source, WhitespaceBehavior.skip);
|
||||||
|
StringCache cache = StringCache(StringCache.defaultBucketCount);
|
||||||
|
const(Token)[] tokens = getTokensForParser(cast(ubyte[]) source, config, &cache);
|
||||||
|
Module mod = parseModule(tokens, "", &allocator);
|
||||||
|
DDocTemplateGenerator result = construct!(DDocTemplateGenerator)(caretLine);
|
||||||
|
result.visit(mod);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
q{ module a;
|
||||||
|
void foo(A...)(A a){}
|
||||||
|
}.parseAndVisit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
q{ module a;
|
||||||
|
void foo()(){}
|
||||||
|
}.parseAndVisit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
q{ module a;
|
||||||
|
int foo(int){}
|
||||||
|
}.parseAndVisit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
q{ module a;
|
||||||
|
class Foo(T, A...){}
|
||||||
|
}.parseAndVisit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
q{ module a;
|
||||||
|
struct Foo(alias Fun, A...){}
|
||||||
|
}.parseAndVisit(2);
|
||||||
|
}
|
||||||
|
|
|
@ -9,9 +9,10 @@ import
|
||||||
import
|
import
|
||||||
dparse.lexer, dparse.parser, dparse.ast, dparse.rollback_allocator;
|
dparse.lexer, dparse.parser, dparse.ast, dparse.rollback_allocator;
|
||||||
import
|
import
|
||||||
common, todos, symlist, imports, mainfun, halstead;
|
common, todos, symlist, imports, mainfun, halstead, ddoc_template;
|
||||||
|
|
||||||
|
|
||||||
|
private __gshared int caretLine;
|
||||||
private __gshared bool deepSymList;
|
private __gshared bool deepSymList;
|
||||||
private __gshared static Appender!(ubyte[]) source;
|
private __gshared static Appender!(ubyte[]) source;
|
||||||
private __gshared static Appender!(AstErrors) errors;
|
private __gshared static Appender!(AstErrors) errors;
|
||||||
|
@ -50,7 +51,8 @@ void main(string[] args)
|
||||||
|
|
||||||
// options for the work
|
// options for the work
|
||||||
getopt(args, std.getopt.config.passThrough,
|
getopt(args, std.getopt.config.passThrough,
|
||||||
"d", &deepSymList
|
"d", &deepSymList,
|
||||||
|
"l", &caretLine
|
||||||
);
|
);
|
||||||
|
|
||||||
// launch directly a work
|
// launch directly a work
|
||||||
|
@ -60,6 +62,7 @@ void main(string[] args)
|
||||||
"s", &handleSymListOption,
|
"s", &handleSymListOption,
|
||||||
"t", &handleTodosOption,
|
"t", &handleTodosOption,
|
||||||
"H", &handleHalsteadOption,
|
"H", &handleHalsteadOption,
|
||||||
|
"K", &handleDdocTemplateOption,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,6 +140,21 @@ void handleHalsteadOption()
|
||||||
.performHalsteadMetrics;
|
.performHalsteadMetrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handles the "-D" option: write the ddoc template for a given declaration
|
||||||
|
void handleDdocTemplateOption()
|
||||||
|
{
|
||||||
|
mixin(logCall);
|
||||||
|
|
||||||
|
RollbackAllocator alloc;
|
||||||
|
StringCache cache = StringCache(StringCache.defaultBucketCount);
|
||||||
|
LexerConfig config = LexerConfig("", StringBehavior.source);
|
||||||
|
|
||||||
|
source.data
|
||||||
|
.getTokensForParser(config, &cache)
|
||||||
|
.parseModule("", &alloc, &ignoreErrors)
|
||||||
|
.getDdocTemplate(caretLine);
|
||||||
|
}
|
||||||
|
|
||||||
private void handleErrors(string fname, size_t line, size_t col, string message,
|
private void handleErrors(string fname, size_t line, size_t col, string message,
|
||||||
bool err)
|
bool err)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,6 +22,8 @@ procedure getModulesImports(const files: string; results: TStrings);
|
||||||
|
|
||||||
procedure getHalsteadMetrics(source: TStrings; out jsn: TJSONObject);
|
procedure getHalsteadMetrics(source: TStrings; out jsn: TJSONObject);
|
||||||
|
|
||||||
|
procedure getDdocTemplate(source, res: TStrings;caretLine: integer);
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
var
|
var
|
||||||
|
@ -125,5 +127,30 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure getDdocTemplate(source, res: TStrings; caretLine: integer);
|
||||||
|
var
|
||||||
|
prc: TProcess;
|
||||||
|
str: string;
|
||||||
|
begin
|
||||||
|
str := getToolName;
|
||||||
|
if str.isEmpty then
|
||||||
|
exit;
|
||||||
|
prc := TProcess.Create(nil);
|
||||||
|
try
|
||||||
|
prc.Executable := str;
|
||||||
|
prc.Parameters.Add('-K');
|
||||||
|
prc.Parameters.Add('-l' + caretLine.ToString);
|
||||||
|
prc.Options := [poUsePipes {$IFDEF WINDOWS}, poNewConsole{$ENDIF}];
|
||||||
|
prc.ShowWindow := swoHIDE;
|
||||||
|
prc.Execute;
|
||||||
|
str := source.Text;
|
||||||
|
prc.Input.Write(str[1], str.length);
|
||||||
|
prc.CloseInput;
|
||||||
|
processOutputToStrings(prc, res);
|
||||||
|
finally
|
||||||
|
prc.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
|
@ -155,6 +155,10 @@ inherited CEEditorWidget: TCEEditorWidget
|
||||||
object MenuItem12: TMenuItem
|
object MenuItem12: TMenuItem
|
||||||
Caption = '-'
|
Caption = '-'
|
||||||
end
|
end
|
||||||
|
object mnuedDdocTmp: TMenuItem
|
||||||
|
Caption = 'Insert DDOC template'
|
||||||
|
OnClick = mnuedDdocTmpClick
|
||||||
|
end
|
||||||
object mnuedRename: TMenuItem
|
object mnuedRename: TMenuItem
|
||||||
Caption = 'Rename identifier'
|
Caption = 'Rename identifier'
|
||||||
OnClick = mnuedRenameClick
|
OnClick = mnuedRenameClick
|
||||||
|
|
|
@ -58,6 +58,7 @@ type
|
||||||
MenuItem10: TMenuItem;
|
MenuItem10: TMenuItem;
|
||||||
MenuItem11: TMenuItem;
|
MenuItem11: TMenuItem;
|
||||||
MenuItem12: TMenuItem;
|
MenuItem12: TMenuItem;
|
||||||
|
mnuedDdocTmp: TMenuItem;
|
||||||
mnuedPrevProtGrp: TMenuItem;
|
mnuedPrevProtGrp: TMenuItem;
|
||||||
mnuedNextProtGrp: TMenuItem;
|
mnuedNextProtGrp: TMenuItem;
|
||||||
MenuItem2: TMenuItem;
|
MenuItem2: TMenuItem;
|
||||||
|
@ -89,6 +90,7 @@ type
|
||||||
macRecorder: TSynMacroRecorder;
|
macRecorder: TSynMacroRecorder;
|
||||||
editorStatus: TStatusBar;
|
editorStatus: TStatusBar;
|
||||||
mnuEditor: TPopupMenu;
|
mnuEditor: TPopupMenu;
|
||||||
|
procedure mnuedDdocTmpClick(Sender: TObject);
|
||||||
procedure mnuedPrevProtGrpClick(Sender: TObject);
|
procedure mnuedPrevProtGrpClick(Sender: TObject);
|
||||||
procedure mnuedNextProtGrpClick(Sender: TObject);
|
procedure mnuedNextProtGrpClick(Sender: TObject);
|
||||||
procedure mnuedNextCareaClick(Sender: TObject);
|
procedure mnuedNextCareaClick(Sender: TObject);
|
||||||
|
@ -900,6 +902,12 @@ begin
|
||||||
fDoc.previousProtectionGroup;
|
fDoc.previousProtectionGroup;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCEEditorWidget.mnuedDdocTmpClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
if fDoc.isNotNil then
|
||||||
|
fDoc.insertDdocTemplate;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCEEditorWidget.mnuedNextProtGrpClick(Sender: TObject);
|
procedure TCEEditorWidget.mnuedNextProtGrpClick(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
if fDoc.isNotNil then
|
if fDoc.isNotNil then
|
||||||
|
|
|
@ -12,7 +12,7 @@ uses
|
||||||
md5,
|
md5,
|
||||||
//SynEditMarkupFoldColoring,
|
//SynEditMarkupFoldColoring,
|
||||||
Clipbrd, fpjson, jsonparser, LazUTF8, LazUTF8Classes, Buttons, StdCtrls,
|
Clipbrd, fpjson, jsonparser, LazUTF8, LazUTF8Classes, Buttons, StdCtrls,
|
||||||
ce_common, ce_writableComponent, ce_d2syn, ce_txtsyn, ce_dialogs,
|
ce_common, ce_writableComponent, ce_d2syn, ce_txtsyn, ce_dialogs, ce_dastworx,
|
||||||
ce_sharedres, ce_dlang, ce_stringrange, ce_dbgitf, ce_observer, ce_diff;
|
ce_sharedres, ce_dlang, ce_stringrange, ce_dbgitf, ce_observer, ce_diff;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
@ -272,6 +272,7 @@ type
|
||||||
procedure addCurLineBreakPoint;
|
procedure addCurLineBreakPoint;
|
||||||
procedure removeCurLineBreakPoint;
|
procedure removeCurLineBreakPoint;
|
||||||
procedure toggleCurLineBreakpoint;
|
procedure toggleCurLineBreakpoint;
|
||||||
|
procedure insertDdocTemplate;
|
||||||
function implementMain: THasMain;
|
function implementMain: THasMain;
|
||||||
procedure replaceUndoableContent(const value: string);
|
procedure replaceUndoableContent(const value: string);
|
||||||
//
|
//
|
||||||
|
@ -346,6 +347,7 @@ const
|
||||||
ecAddBreakpoint = ecUserFirst + 22;
|
ecAddBreakpoint = ecUserFirst + 22;
|
||||||
ecRemoveBreakpoint = ecUserFirst + 23;
|
ecRemoveBreakpoint = ecUserFirst + 23;
|
||||||
ecToggleBreakpoint = ecUserFirst + 24;
|
ecToggleBreakpoint = ecUserFirst + 24;
|
||||||
|
ecInsertDdocTemplate = ecUserFirst + 25;
|
||||||
|
|
||||||
var
|
var
|
||||||
D2Syn: TSynD2Syn; // used as model to set the options when no editor exists.
|
D2Syn: TSynD2Syn; // used as model to set the options when no editor exists.
|
||||||
|
@ -989,6 +991,7 @@ begin
|
||||||
AddKey(ecAddBreakpoint, 0, [], 0, []);
|
AddKey(ecAddBreakpoint, 0, [], 0, []);
|
||||||
AddKey(ecRemoveBreakpoint, 0, [], 0, []);
|
AddKey(ecRemoveBreakpoint, 0, [], 0, []);
|
||||||
AddKey(ecToggleBreakpoint, 0, [], 0, []);
|
AddKey(ecToggleBreakpoint, 0, [], 0, []);
|
||||||
|
AddKey(ecInsertDdocTemplate, 0, [], 0, []);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -1019,6 +1022,7 @@ begin
|
||||||
'ecAddBreakpoint': begin Int := ecAddBreakpoint; exit(true); end;
|
'ecAddBreakpoint': begin Int := ecAddBreakpoint; exit(true); end;
|
||||||
'ecRemoveBreakpoint': begin Int := ecRemoveBreakpoint; exit(true); end;
|
'ecRemoveBreakpoint': begin Int := ecRemoveBreakpoint; exit(true); end;
|
||||||
'ecToggleBreakpoint': begin Int := ecToggleBreakpoint; exit(true); end;
|
'ecToggleBreakpoint': begin Int := ecToggleBreakpoint; exit(true); end;
|
||||||
|
'ecInsertDdocTemplate': begin Int := ecInsertDdocTemplate; exit(true); end;
|
||||||
else exit(false);
|
else exit(false);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -1050,6 +1054,7 @@ begin
|
||||||
ecAddBreakpoint: begin Ident := 'ecAddBreakpoint'; exit(true); end;
|
ecAddBreakpoint: begin Ident := 'ecAddBreakpoint'; exit(true); end;
|
||||||
ecRemoveBreakpoint: begin Ident := 'ecRemoveBreakpoint'; exit(true); end;
|
ecRemoveBreakpoint: begin Ident := 'ecRemoveBreakpoint'; exit(true); end;
|
||||||
ecToggleBreakpoint: begin Ident := 'ecToggleBreakpoint'; exit(true); end;
|
ecToggleBreakpoint: begin Ident := 'ecToggleBreakpoint'; exit(true); end;
|
||||||
|
ecInsertDdocTemplate: begin Ident := 'ecInsertDdocTemplate'; exit(true); end;
|
||||||
else exit(false);
|
else exit(false);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -1120,6 +1125,8 @@ begin
|
||||||
removeCurLineBreakPoint;
|
removeCurLineBreakPoint;
|
||||||
ecToggleBreakpoint:
|
ecToggleBreakpoint:
|
||||||
toggleCurLineBreakpoint;
|
toggleCurLineBreakpoint;
|
||||||
|
ecInsertDdocTemplate:
|
||||||
|
insertDdocTemplate;
|
||||||
end;
|
end;
|
||||||
if fOverrideColMode and not SelAvail then
|
if fOverrideColMode and not SelAvail then
|
||||||
begin
|
begin
|
||||||
|
@ -1839,6 +1846,42 @@ begin
|
||||||
else
|
else
|
||||||
removeBreakPoint(CaretY);
|
removeBreakPoint(CaretY);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCESynMemo.insertDdocTemplate;
|
||||||
|
var
|
||||||
|
d: TStringList;
|
||||||
|
i: integer;
|
||||||
|
j: integer;
|
||||||
|
k: integer;
|
||||||
|
s: string;
|
||||||
|
p: TPoint;
|
||||||
|
begin
|
||||||
|
d := TStringList.Create;
|
||||||
|
try
|
||||||
|
getDdocTemplate(lines, d, CaretY);
|
||||||
|
if d.Text.isNotEmpty then
|
||||||
|
begin
|
||||||
|
BeginUndoBlock;
|
||||||
|
ExecuteCommand(ecLineStart, #0, nil);
|
||||||
|
k := CaretX;
|
||||||
|
p.y:= CaretY -1 ;
|
||||||
|
p.x:= 1 ;
|
||||||
|
ExecuteCommand(ecGotoXY, #0, @p);
|
||||||
|
for i := 0 to d.Count-1 do
|
||||||
|
begin
|
||||||
|
s := d[i];
|
||||||
|
ExecuteCommand(ecLineBreak, #0, nil);
|
||||||
|
while caretX < k do
|
||||||
|
ExecuteCommand(ecTab, #0, nil);
|
||||||
|
for j := 1 to s.length do
|
||||||
|
ExecuteCommand(ecChar, s[j], nil);
|
||||||
|
end;
|
||||||
|
EndUndoBlock;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
d.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
{$ENDREGION}
|
{$ENDREGION}
|
||||||
|
|
||||||
{$REGION DDoc & CallTip --------------------------------------------------------}
|
{$REGION DDoc & CallTip --------------------------------------------------------}
|
||||||
|
|
Loading…
Reference in New Issue