最近,在翻译iOS微信SDK的头文件,发现Objective C的类声明翻译成delphi,每个类都要重复输入一样的格式,很是麻烦。
OC = interface(NSObject) //(其中OC为类名)
['{D2B85162-56EC-49A1-8147-44FF05A43147}']
//对象方法
end;
OCClass= interface(NSObjectClass)
['{1EFADA09-CB9B-4625-857D-733E00C5B266}']
//类方法
end;
TOC = class(TOCGenericImport<OCClass, OC>)
end;
如果用手工复制再改类名,很容易忘记重新生成接口GUID。为此想利用IDE代码输入模板,自动产生这一块代码,特别是自动产生接口GUID,这样就不会重复了。
代码编辑界面输入"cl"将出现上图所示的模板选择提示,我们选择第二个将在当前位置自动生成如下图所示代码。
这里主要使用的是Live Template功能,关于它的介绍请自行查看帮助文档。IDE已经内置了众多这样的模板,通过菜单 View -> Template打开Templates Window,这里我们可以修改,增加模板。
我们打开class模板,复制里面的内容后关闭,在新建一个模板,粘贴复制的内容,通过修改定义来构建自己的模板。
(注:默认创建的新模板文件名为Template1.xml,位于C:\Users\Administrator\Documents\Embarcadero\Studio\code_templates目录下,在此目录下的模板IDE自动加载)
具体的模板定义语法请查看帮助,这里给出修改后的OCImport模板内容:
<?xml version="1.0" encoding="utf-8" ?>
<codetemplate xmlns="http://schemas.borland.com/Delphi/2005/codetemplates" version="1.0.0">
<template name="OCImport" invoke="manual">
<description>Object C Class Import Declare</description>
<author>TU2</author>
<point name="classname">
<script language="Delphi">
InvokeCodeCompletion;
</script>
<text>MyOC</text>
<hint>Object C Class Name</hint>
</point>
<point name="guid1">
<script language="InsertValue" onvalidate="true">
Type=GUID;Format=['%s']
</script>
</point>
<point name="guid2">
<script language="InsertValue" onvalidate="true">
Type=GUID;Format=['%s']
</script>
</point>
<code language="Delphi" context="typedecl" delimiter="|"><![CDATA[
|classname| = interface(NSObject)
|guid1|
|*|{ object method declarations }
end;
|classname|Class = interface(NSObjectClass)
|guid2|
|*|{ class method declarations }
end;
T|classname| = class(TOCGenericImport<|classname|Class, |classname|>) end;
]]>
</code>
</template>
</codetemplate>
上面的定义需要插入两个GUID值,为此需要定义一个名为InsertValue的Delphi Script引擎,它定义两个参数,值类型Type和格式化串Format,当前支持Type=GUID,后面可以实现支持插入当前时间等等。
{
编辑器增强
}
unit ExtendingEditorImpl;
interface
uses
SysUtils, Classes, ToolsAPI, CodeTemplateAPI, System.RegularExpressionsCore;
type
/// <summary>模板值插入引擎</summary>
TInsertValueScriptEngine = class(TNotifierObject, IOTACodeTemplateScriptEngine)
protected
{IOTACodeTemplateScriptEngine}
function GetIDString: WideString;
function GetLanguage: WideString;
procedure Execute(const ATemplate: IOTACodeTemplate; const APoint: IOTACodeTemplatePoint;
const ASyncPoints: IOTASyncEditPoints; const AScript: IOTACodeTemplateScript; var Cancel: Boolean);
end;
procedure Register;
implementation
uses SyncObjs, Windows, Vcl.Menus, Vcl.Dialogs, Vcl.Clipbrd;
procedure Register;
begin
(BorlandIDEServices as IOTACodeTemplateServices).RegisterScriptEngine(TInsertValueScriptEngine.Create);
end;
{ TInsertValueScriptEngine }
procedure TInsertValueScriptEngine.Execute(const ATemplate: IOTACodeTemplate;
const APoint: IOTACodeTemplatePoint; const ASyncPoints: IOTASyncEditPoints;
const AScript: IOTACodeTemplateScript; var Cancel: Boolean);
procedure InsertGuid(const AFormat: string);
var
AGuid: TGUID;
sTemp: string;
begin
CreateGUID(AGuid);
sTemp := GUIDToString(AGuid);
if AFormat<>'' then
sTemp := Format(AFormat, [sTemp]);
APoint.Value := sTemp;
end;
var
sType, s: string;
AStrList: TStringList;
begin
Cancel := True;
try
AStrList := TStringList.Create;
try
AStrList.Delimiter := ';';
AStrList.StrictDelimiter := True;
AStrList.DelimitedText := AScript.Script;
sType := AStrList.Values['Type'];
if CompareText(sType, 'Guid')=0 then
InsertGuid(AStrList.Values['Format']);
finally
AStrList.Free;
end;
Cancel := False;
except
end;
end;
function TInsertValueScriptEngine.GetIDString: WideString;
begin
Result := '{98731108-92C9-4AA3-9EA3-AF018BF44309}';
end;
function TInsertValueScriptEngine.GetLanguage: WideString;
begin
Result := 'InsertValue';
end;
end.
编译上面的IDE扩展包并安装到系统中,重启IDE,在编辑器中输入OC将出现提示模板:
选择后将自动产生如下代码:
这种模板还有一个好处是只要输入第一个类名,后面几处都级联自动更名。
相关资源下载:OCImport.xml
ExtendingEditor.bpl(Delphi 10.1 Berlin)
最新资源:https://github.com/chinawsb/QSDK/tree/master