Jump to content

darnocian

Members
  • Content Count

    26
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by darnocian

  1. I'd like to advertise the Sempare Template Engine for Delphi. The Sempare Template Engine for Delphi allows for flexible text manipulation. It can be used for generating email, html, source code, xml, configuration, etc. It is available on github via https://github.com/sempare/sempare-delphi-template-engine It is also available via Delphinus (https://github.com/Memnarch/Delphinus) Simply add the 'src' directory to the search path to get started. Sample usage: program Example; uses Sempare.Template; type TInformation = record name: string; favourite_sport : string; end; begin var tpl := Template.parse('My name is <% name %>. My favourite sport is <% favourite_sport %>.'); var information : TInformation; information.name := 'conrad'; information.favourite_sport := 'ultimate'; writeln(Template.eval(tpl, information)); end. Features include: statements if, elif, else statements for and while statements include statement with statement function/method calls expressions simple expression evaluation (logical, numerical and string) variable definition functions and methods calls dereference records, classes, arrays, JSON objects, TDataSet descendants and dynamic arrays ternary operator safety max run-time protection customisation custom script token replacement add custom functions strip recurring spaces and new lines lazy template resolution parse time evaluation of expressions/statements allow use of custom encoding (UTF-8 with BOM, UTF-8 without BOM, ASCII, etc) extensible RTTI interface to easily dereference classes and interfaces (current customisations for ITemplateVariables, TDictionary, TJsonObject) There are numerous unit tests that can be reviewed as to how to use the various features. Happy for all to play with it. Released under GPL and Commercial License. Any feedback welcome.
  2. darnocian

    ANN: Sempare Template Engine for Delphi

    v1.4.1 is available on GetIt now. Sorry, that release is not compatible with XE4 (my CI is running the latest Delphi only - something in my dev pipeline to support more generally). The version in github has an XE4 compatible fix, but will be bundled into the next release.
  3. darnocian

    ANN: Sempare Template Engine for Delphi

    Hi A new version v1.4.1 is now available and merged into the main branch. This will be available on GetIt shortly. The new version includes a bug fix mentioned above impacting on the fmt() function.
  4. darnocian

    ANN: Sempare Template Engine for Delphi

    No problem. I just realised I could configure email notifications on this thread as well. Either location will do, but this topic may get a bit long. 😀I was just mentioning as I only saw this after a few days.
  5. darnocian

    XLS 2 XLSX

    The apache POI java library ( https://poi.apache.org/ ) is pretty good when it comes to working with the office formats. I've mainly used it for extracting data, but have seen examples of it used for conversion too.
  6. darnocian

    ANN: Sempare Template Engine for Delphi

    Assert.AreEqual('123.457', Template.Eval('<% x := 123.456789 %><% fmt("%6.3f", x) %>')); here is a quick fix in Sempare.Template.Functions.pas: class function TInternalFuntions.Fmt(const AArgs: TArray<TValue>): string; var LArgs: TArray<TVarrec>; LIdx: integer; begin setlength(LArgs, high(AArgs)); for LIdx := 1 to high(AArgs) do LArgs[LIdx - 1] := AArgs[LIdx].AsVarRec; exit(format(AsString(AArgs[0]), LArgs)); end; I need to check into why the current helper does something different. Will get a fix into the main release soon. (fix is on dev branch)
  7. darnocian

    ANN: Sempare Template Engine for Delphi

    I created a test and the following is runs properly: Assert.AreEqual('543.21', Template.Eval('<% x:= 543.21 %><% x %>')); Assert.AreEqual('5.1234', Template.Eval('<% x:= 5.1234 %><% x %>')); floating point numbers should be using dot (.) as illustrated above. I'm not sure about fmt() offhand. Will investigate. fmt() is just a wrapper around SysUtils.Format(fmt, ...). Might be some issue with TValue to TVarRec conversion, but will double check. Most of the templates I've worked on passed values into the engine via the input record/class, but appreciate this should not be a problem. BTW. it is better to raise issues on github. https://github.com/sempare/sempare-delphi-template-engine/issues
  8. Hi. I use the Rad Studio ‘Build Tools’ functionality to do some code generation. Using a config file and my ‘build tool’, associated .pas files are created during during compilation. Do you know if there is a way to get the IDE to group the related files the way it does with the pas and dfm files? Is there some config/registry setting for this or would it require a custom IDE plugin? Any insight appreciated.
  9. darnocian

    Creating custom file groupings

    Thanks Remy.
  10. darnocian

    Delphi and the new Apple M1 CPU

    I did a few tests using WINE a while ago and was quite impressed. I have never got the IDE itself to run on it since I've used it over the years. However, creating some 'hello world' console, VCL and FMX apps I was pleasantly surprised they worked quite well, but had seen some 'glitches' with FMX under 64bit.
  11. darnocian

    Delphi and the new Apple M1 CPU

    Not sure if you guys saw https://www.zdnet.com/article/aws-engineer-puts-windows-10-on-arm-on-apple-mac-m1-and-it-thrashes-surface-pro-x/ It is an old article from Dec 2020. They used Qemu which may be an alternative to launch Windows if VMware is not available. It would be cool to see some others confirm how well it works till we see what VMware comes up with.
  12. darnocian

    ANN: Sempare Template Engine for Delphi

    BTW. The new release v1.4.0 is now also available on GetIt (https://getitnow.embarcadero.com/?q=sempare&amp;product=rad-studio)
  13. darnocian

    ANN: Sempare Template Engine for Delphi

    I think subres should be an index into ChildRecords. Try change: to '<% for subresIdx in ChildRecords %>SubRes: |<% ChildRecords[subresIdx].Description %>|<br><%end%>'+ I've just renamed the variable as well to make it clearer. It may seem undesirable, but did it this way as sometimes you want to know where you are in the array. If you have many variables, you should be able to do: <% with ChildRecords[subresIdx] %> <% Description %> <% Vehicle %> <% end %>
  14. darnocian

    ANN: Sempare Template Engine for Delphi

    I tried to provide flexibility in many places. https://github.com/sempare/sempare-delphi-template-engine/blob/master/docs/configuration.md begin var ctx := Template.Context; ctx.StartToken := '{{'; ctx.EndToken := '}}'; Assert.IsEqual('hello', Template.Eval(ctx, '{{ if true }}hello{{else}}bye{{end}}')); end; There is a restriction however. Must be 2 characters in length. It will work as long as it doesn't conflict with any of the other tokens (no validation is done on this however, so you just need to check if you do override) There is also a global override where you can set GDefaultOpenTag and GDefaultCloseTag. These are defined in Sempare.Template.Context.pas. Once set, you don't have to explicitly create a context if you don't need one.
  15. darnocian

    ANN: Sempare Template Engine for Delphi

    Hi, Just a small announcement that a new version (v1.4.0) has been released. Changes: NEW: Context.StreamWriterProvider which allows greater flexibility in providing custom overrides to the StreamWriter NEW: Support for statement start and end tokens allowing for content to be swallowed (useful when statements are multi line) NEW: Added helper variables and functions for spaces, newlines, tabs, chr() and ord() FIX: Issue with custom text writer that supported a few options regarding newlines, but had a bug when it came to carriage returns. (not noticeable under html) FIX: Fixed a double free bug in a ParseFile helper. UPDATE: Documentation updates Context.StreamWriterProvider flexibility var ctx := Template.Context(); ctx.StreamWriterProvider := function(const AStream: TStream; AContext: ITemplateContext): TStreamWriter begin result := TStreamWriter.Create(AStream); end; The above is an example of how the override can be done on a per context basis. There is a GDefaultStreamProvider which is used when the context is initially created which can be used for global initialisation. Allow swallowing of content between start and end statement tokens Say you have a scenario like: <% for i := 1 to 5 %> <% i %> <% end %> What you may notice is that there are many newlines that appear something like: 1 2 3 4 5 Now consider the following: <% for i := 1 to 5 |> <% i %> <| end %> In this scenario, all normal output between |> and <| are ignored, except statements such as explicit print() or variable references will work as normal. Why? It just means that the template becomes responsible for any indenting and newlines within the end (|>) and start ( <|) tokens. --- If you have any feature requests or bug reports, please raise them on https://github.com/sempare/sempare-delphi-template-engine/issues
  16. darnocian

    ANN: Sempare Template Engine for Delphi

    A fix is now in the dev branch with some additional tests and a way to also change the StreamWriter if required. Will look at new tagged release next week or so. (with the fix in the dev branch, the the Context workaround above would be invalidated)
  17. darnocian

    ANN: Sempare Template Engine for Delphi

    @mvanrijnen Just looking at the bug you highlighted, there is also an alternative workaround by setting the IContext.NewLine = #$A. procedure TTestTemplate.TestNewLine; type TRec = record Value: string; description: string; end; var r: TRec; s: string; ctx: ITemplateContext; begin ctx := Template.Context(); ctx.newline := #10; r.Value := 'a value'; r.description := 'some desc'; s := Template.Eval(ctx, 'Value: <% value %>'#$D#$A'Description: <% description %>', r); Assert.AreEqual('Value: a value'#$D#$A'Description: some desc', s); end; I have a custom StreamWriter that allows for stripping repeated whitespace and new lines. I'll look into also providing a way to override that better.
  18. darnocian

    ANN: Sempare Template Engine for Delphi

    Yes. Use in a multi threaded environment should be totally fine. I've even used it to serve html on an indy server. There is locking used internally when accessing some internally managed collections as required. You can load templates on the fly and the locks ensure the state of the structures don't get corrupted. You can load/parse templates upfront or on demand safely. There is no global/shared state that should cause any issues. There are a few different Template.Eval() overrides which allow you to use the templates that have been pre-parsed, or you can just reprocess a textual representation as required. When evaluation takes place, the state is totally independent of any other execution on other threads.
  19. darnocian

    ANN: Sempare Template Engine for Delphi

    I just looked at the tests... mostly testing with #$A. 😉 But made a test to replicate the issue.
  20. darnocian

    ANN: Sempare Template Engine for Delphi

    Thanks for the report. Could you please raise the issues on https://github.com/sempare/sempare-delphi-template-engine/issues I'll check it out. A double #$D would not be ideal. The #$A is more easily noticeable, but most of the stuff I used was HTML where this would have been ignored.
  21. Performance wise 100% agree with you David. It was more an example to check it out initialisation in case that was an issue.
  22. I realise this is an old post... The other thing - usually with COM, you need to CoInitialize() in each thread, and if you are a nice citizen, CoUninitialize(). To coordinate shutdown, you may also want to look at TCountdownEvent from System.SyncObjs. TCountdownEvent waits for a counter to reach zero. A signal in a thread would trigger the countdown. Could do something like (sorry, I automatically referenced TTask.Run rather than Parallel.Async) // This is pseudocode, so might not be 100% accurate with params var event := TCountdownEvent.Create(); event.AddCount(length(workList)); for var work in workList do begin TTask.Run(procedure begin CoInitialize(); try process(work); finally CoUninitalize(); event.signal(); end; end; end; event.WaitFor(INFINITE); With the above code, if run from a UI would still block, so that should also be threaded if the UI is meant to remain responsive.
  23. darnocian

    ANN: Sempare Template Engine for Delphi

    A new version (v1.3.1) is available on github with bug fixes (https://github.com/sempare/sempare-delphi-template-engine) Hope to have the update in getit shortly too.
  24. darnocian

    ANN: Sempare Template Engine for Delphi

    It is now available via GetIt as well
  25. darnocian

    Accessing the memory of a Python List

    FYI. I recall that you can reference the base ptr on the underlying PyArray. Definitely coming from unmanaged code, you want to try avoid copying if you can. C++ Boost does it quite nicely actually. I last bridged the c++ / python route a number of years ago, so with delphi it will be possible. https://www.boost.org/doc/libs/1_64_0/libs/python/doc/html/numpy/tutorial/ndarray.html https://github.com/boostorg/python/blob/develop/src/numpy/ndarray.cpp inside there is from_data_impl which I think should also be an interesting reference.
×