Jump to content

darnocian

Members
  • Content Count

    111
  • Joined

  • Last visited

  • Days Won

    2

Everything posted by darnocian

  1. darnocian

    How to get the actual UTC time??

    In my opinion, I'd try fix the OS configuration, or use a 3rd party if the default provided by the OS isn't good enough. From an application perspective, there should be a level of trust on basic services provided by system, otherwise there would be a lot of app bloat if everyone had to distrust them... When it comes to the APIs we use from the OS or the RTL, the key thing we need to pay attention to is the locale configuration (defined by the OS again), and use the appropriate toUTC/fromUTC type functionality. This is especially important when applying these functions appropriately when obtaining data from 3rd party sources and converting the timestamps appropriately, which would normally be sourced in UTC. On windows (desktop and server), there is w32tm.exe (windows time service) https://docs.microsoft.com/en-us/windows-server/networking/windows-time-service/windows-time-service-tools-and-settings. On my workstation this was disabled till I enabled it, but the other benefit is that within a larger organisation, the sysadmins could script something to deploy and enable appropriately with whatever the standard is so that everyone was covered consistently. I have worked on time sensitive apps before where we had 3rd party time agents on the host machine that synchronised the time, and custom libraries that worked with those agents, but this was because there was a very very low tolerance for any time drift at any time because the application was financial in nature working on financial market data in realtime and logging required more granular timestamp information. I'd try to stick to RTL functions or standard system calls like what @Wagner Landgraf referenced above, but that is my opinion.
  2. darnocian

    Parsing Text search expression

    I felt like playing with this idea for Delphi - as like writing parsers. 😉 Years ago I did something similar for a document management system in a different language. I've written a small demo illustrating 2 ways of parsing https://github.com/sempare/sempare-delphi-fts-expression I did this for fun and in a few hours, so it is still very raw. It contains a hand rolled lexer and parser, but hopefully can give you some ideas how to do this too. In the first (Sempare.FullTextSearch.SimpleExpression.Test.pas) you can see some scenarios: procedure TSimpleExprTest.TestSimpleExpr; begin assert.AreEqual('name = ''conrad''', tparser.ParseStr('name', '"conrad"')); end; procedure TSimpleExprTest.TestWildCard2Expr; begin assert.AreEqual('(name like ''conrad%'') or (name like ''%pete'')', tparser.ParseStr('name', '"conrad%" "%pete"')); end; procedure TSimpleExprTest.TestWildCardExpr; begin assert.AreEqual('name like ''conrad%''', tparser.ParseStr('name', '"conrad%"')); end; procedure TSimpleExprTest.TestNotExpr; begin assert.AreEqual('not (name = ''conrad'')', tparser.ParseStr('name', 'not "conrad"')); end; procedure TSimpleExprTest.TestOrExpr; begin assert.AreEqual('(name = ''abc'') or (name = ''def'')', tparser.ParseStr('name', '"abc" or "def"')); end; procedure TSimpleExprTest.TestPrecidentExpr; begin assert.AreEqual('(name = ''abc'') and (not ((name = ''321'') or (name = ''def'')))', tparser.ParseStr('name', '''abc'' and not ''321'' or ''def''')); end; The second (Sempare.FullTextSearch.Expression.Test.pas) is a bit more general. It illustrates parsing, but implementation at present is fairly basic as just a pretty printer: procedure TExprTest.TestNotExpr; begin assert.Areequal('not (name != ''conrad'')', tparser.ParseStr('not (name!="conrad")')); end; procedure TExprTest.TestOrExpr; begin assert.Areequal('(name = ''abc'') or (text = ''def'')', tparser.ParseStr('name = ''abc'' or text = ''def''')); end; procedure TExprTest.TestPrecidentExpr; begin assert.Areequal('((name = ''abc'') and (value = ''321'')) or (text = ''def'')', // tparser.ParseStr('name = ''abc'' and value = ''321'' or text = ''def''')); end; procedure TExprTest.TestStartsWithExpr; begin assert.Areequal('name like ''abc%''', tparser.ParseStr('name starts with "abc"')); end; above you can see that the parsing identifies the precedence and places brackets appropriately. Also it changed 'starts with' to 'like'... NOTE: there are 2 different parsers implemented for the above scenarios (but both named TParser - just depends which unit is being referenced) Hope you find this useful.
  3. I was just testing an fmx app on ios and noticed that when editing in a tedit, I keep on getting little notifications at the top of the device '<app>pasted from <device>' every time I enter any character. I expected that notification to only happen when pasting from other apps on the device, not from the current one and not for every single keypress. Has anyone encountered this before?
  4. the only way to get around it appears to be by explicitly setting the clipboard content in the current app (programatically or by the user copying something in the app), but switching between apps will result in the problem occurring again. I'm not sure if there is a workaround without Apple being involved - I suspect all we can do is inform users if this becomes annoying.
  5. I replicated the issue. I thought I was going mad. As per @sjordi opinion, it probably is just an iOS issue.. To reproduce: I switched to chrome and just copied the URL... switched back to the app, and then you can see the result as I'm typing:
  6. Actually, I just created a minimal version now with just a TEdit on it - and I didn't get the behaviour. I should have done this initially. 😉
  7. Yeah, I definitely agree with the benefit of the feature... but I would expect it to only happen when actually pasting from the clipboard - not while typing keys... I'll try knock something together with XCode to see what a standard input control like a UITextField would do as comparison... maybe there is something in FMX doing something it should have to. Will keep you posted.
  8. Thanks @sjordi. I feel better it isn't just me. ;)
  9. @mvanrijnen @Edwin Yip Thanks for the references. The aim with the Sempare Template Engine was to have a template engine that was native to Delphi and could be used for web, but also for other kinds of purposes such as code or config generation. At the time I wrote it, dmustache was mainly what was available, but I wanted a template language that was more readable and pascal-like, and from a library perspective providing more flexibility in terms of extension points (custom functions) and the ability to support various sub-template inclusion patterns (content with header/footer, main template referencing content template, etc) and dynamic loading. Due to the fact that looping is a feature, it also has to be safe and offers a timeout if template processing takes too long due to data processing or bad logic. It does rely on RTTI, which does mean there is a performance penalty, but I chose functionality/flexibility over performance to start. I have not had problems reported yet, so I suspect performance has been acceptable for users, as it has been for my use cases. Documentation wise, it should be fairly well covered on github, but I have been working on a CHM help edition which can be used from the IDE with context sensitive help which may be a bit more friendly for those that don't want to necessarily have to browse to the the github docs. Please email me conrad@sempare.ltd/conrad.vermeulen@gmail.com if you are interested and can notify you when it is available. If you have feature requests/comments feel free to raise them on the issue tracker (https://github.com/sempare/sempare-delphi-template-engine/issues). I do check here periodically, but may miss things or reply late. In the next release, I'm allowing for discovery of variables and functions that are referenced. So if you provide a template editor and are using a dictionary/json to pass variables, the UI can know upfront what the required variables are and perform additional validation if required, prompting the user if anything is missing. Alternatively, it could be a way to identify variables that are required, allowing for optimal querying of data from database before populating the template. This is just a complementary feature to an existing feature where errors can be raised if a referenced variable is not present. Further, I hope to create some more examples with more popular web frameworks soon, as I think many people find it easier to see how things work from demos. I realise licensing as GPL may be contentious, but I've gone with the 'free as in speech vs free as in beer' approach. So for a nominal one time fee, you can use it under the commercial license without any restriction. I'll keep you posted on new developments as they unfold.
  10. darnocian

    Poor performance of Python script

    One of the biggest issues with python, not necessarily python4d, is that everything is boxed. Many analytical packages use some packages like numpy/scipy which have some very powerful underlying C code that provides the boost without needing the boxing and unboxing of values where the python code is just providing very flexible glue. import numpy def test(size): x = numpy.random.rand(size) * 10 return numpy.logical_or(x > 6, x < 2).astype(int) * 20 + 20 test(500000) to get the above to work, you will need to install numpy if you don't already have it: pip install numpy It may be interesting to see if this approach provides any improvements? In the above, I could see there being a cost with the way it still has to evaluate the logical expression with a callback.
  11. 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.
  12. 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.
  13. 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.
  14. 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.
  15. 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.
  16. 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)
  17. 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
  18. 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.
  19. darnocian

    Creating custom file groupings

    Thanks Remy.
  20. 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.
  21. 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.
  22. 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)
  23. 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 %>
  24. 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.
  25. 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
×