Pascal Emmet

I'll try to publish some code I use in my program.
User avatar
Rickard Johansson
Site Admin
Posts: 5821
Joined: 19 Jul 2006 14:29

Pascal Emmet

Post by Rickard Johansson » 30 May 2019 13:59

In RJ TextEd I wrote my own version of Emmet. It is not based on the original Emmet code, but written from scratch in Delphi (object pascal).

You are perfectly free to use it in your own code or applications. But if you're using it in a commercial product I would appreciate a donation.

The Emmet code only expand abbreviation or wrap text with abbreviation. All other editor stuff like handle tab points or multi cursors you will have to handle yourself in your own code. That's what I do in RJ TextEd.

Cheat sheets
There are a few minor differences between my version of Emmet and standard Emmet (e.g. the lorem generator).

Emmet-Pascal cheat sheet: https://www.rj-texted.se/Help/Emmetcheatsheet.html.
Standard Emmet cheat sheet: https://docs.emmet.io/cheat-sheet/

If you improve the code you may post it in this forum.

Version 1.10 (2019-07-28)
Pascal Emmet.zip
(22.46 KiB) Downloaded 14 times
Changes:
Version 1.10
* Removed "public" keyword from TExpandOptions.
* Fixed an issue in ExtractFilters().

Version 1.09
* TEmmet can now handle some filters. A filter is added at the end of the abbreviation using a pipe |.

Code: Select all

      E.g. ul>li*|t

      c - Comment important tags (containing class or id attributes).
      e - Escape XML-unsafe characters: <, > and &. E.g. <p>|e => &lt;p&gt;&lt;/p&gt;
      s - Single line. Expand everything to a single line of code.
      t - Trim line markers from wrapped lines e.g. "* ", "- " or "1."
      w - Wordwrap selected or lorem generated text. Default width is 80.
      w<x> - Wordwrap at column x. E.g. |w120 will wrap lines at column 120.

      Ex.
        sAbbrev = ul>li*|t

        sSelText =
          * Line 1
          * Line 2

        Result =
          <ul>
            <li>Line 1</li>
            <li>Line 2</li>
          </ul>
* Added several options in a record "TExpandOptions" that can be passed to the expand function.
Options are:

Code: Select all

  AddSlashToEmptyTags: Boolean;  // Add a slash to empty tags e.g. <img src="" />
  AlwaysAddNewLine: Boolean;     // Always add linefeed after each tag (usually used in XML)
  CommentTags: Boolean;          // Comment important tags (containing class or id attributes).
  IndentChilds: Boolean;         // Indent child tags. If you set this to false - no indention will be used.
  SingleLine: Boolean            // Expand everything to a single line of code.
  TabSize: Integer;              // Tab size in characters. This is only used with wordwrap.
  TrimLineMarkers: Boolean;      // Trim line markers from wrapped lines e.g. "* ", "- " or "1."
  Wordwrap: Boolean;             // Word wrap selected or lorem generated text.
  WordwrapAt: Integer;           // Wrap at given column. The nearest space or symbol will be used as wrap position


* Added overload function to "ExpandAbbreviation()". The first one uses default options and the other one
enables you to set expand options.

Version 1.08
* Direction issue with multiply.
* Changes to the constructior.

Version 1.07
* Added support for placeholders $# used in "Wrap with abbreviation". The placeholder is replaced with one line of selected text.

Code: Select all

      E.g.
        sAbbrev = "ul>li[title=$#]*>{$#}+img[alt=$#]"

        sSelText =
           "About
            New
            Products
            Contacts"

        Result =
           "<ul>
              <li title="About">About<img src="" alt="About" /></li>
              <li title="New">New<img src="" alt="New" /></li>
              <li title="Products">Products<img src="" alt="Products" /></li>
              <li title="Contacts">Contacts<img src="" alt="Contacts" /></li>
           </ul>"
* Added new parameters to the constructor.

Version 1.06
* Space should be treated as stop character.
* Implicit tag issue.
* User attribute space issue.

Version 1.05
* Fixed a child indent issue.

Version 1.04
* Added standard vendor prefix "-" to CSS. E.g. -bdrs (which works the same as -v-bdrs).
* Space issue with siblings.
* A trim issue that may result in wrong indention.
* Id and class attribute issue.

Version 1.03
* Fixed several issues and updated the snippets.ini file.

Version 1.02
* Addressed some warnings in Lazarus

Version 1.01
* Fixed a multiply issue in ProcessTagMultiplication(...)

Alextp
Posts: 28
Joined: 23 Aug 2014 23:36

Re: Pascal Emmet

Post by Alextp » 30 May 2019 21:57

Thank you very much! It is easier to get patches on Github, so I ve put repo here:
https://github.com/Alexey-T/Emmet-Pascal

Made fix to support FreePascal. (added var DirectorySeparator for Delphi, will test it ASAP.)

Alextp
Posts: 28
Joined: 23 Aug 2014 23:36

Re: Pascal Emmet

Post by Alextp » 30 May 2019 22:09

In Lazarus it works, good. But the first abbrev from https://docs.emmet.io/abbreviations/
don't fully work.
#page>div.logo+ul#navigation>li*5>a{Item $}

Alextp
Posts: 28
Joined: 23 Aug 2014 23:36

Re: Pascal Emmet

Post by Alextp » 31 May 2019 00:33

Added EmmetHelper unit (the same repo on github). It can find Emmet abbrev inside any line. It truncates line from <tag> and </tag> but skips Emmet ">" chars.

User avatar
Rickard Johansson
Site Admin
Posts: 5821
Joined: 19 Jul 2006 14:29

Re: Pascal Emmet

Post by Rickard Johansson » 31 May 2019 09:52

Fixed the multiply issue in ProcessTagMultiplication(...) and added the new version in my first post.

Thanks!

Alextp
Posts: 28
Joined: 23 Aug 2014 23:36

Re: Pascal Emmet

Post by Alextp » 31 May 2019 10:33

Thanks, that was fixed. I will test more cases, maybe all examples of Emmet, and will let you know. Will help as a tester.

Alextp
Posts: 28
Joined: 23 Aug 2014 23:36

Re: Pascal Emmet

Post by Alextp » 31 May 2019 10:44

RIchard,
we need class (TEmmet) property: IndentString, which can be set to #9 or to StringOfChar(' ', N). You know it is needed for editors.

Alextp
Posts: 28
Joined: 23 Aug 2014 23:36

Re: Pascal Emmet

Post by Alextp » 31 May 2019 10:50

And good to have property TabStopChar, with default value '|'.

User avatar
Rickard Johansson
Site Admin
Posts: 5821
Joined: 19 Jul 2006 14:29

Re: Pascal Emmet

Post by Rickard Johansson » 31 May 2019 11:40

Indent
I do all the indent processing in the editor component. Using #9 as indent marker makes processing each line very simple and it's easy to replace with spaces. It's also easier to position the whole block where it's supposed to be.

Instead of adding that to the Emmet.pas - maybe you could write a helper function to process tabs. Maybe have an initial indent position "InitialIndentString" and "IndentString", or something similar...

| - tab stop char
The tab stop char is added to snippets and abbreviations in the file snippets.ini...

User avatar
Rickard Johansson
Site Admin
Posts: 5821
Joined: 19 Jul 2006 14:29

Re: Pascal Emmet

Post by Rickard Johansson » 31 May 2019 11:52

Actually... It may be helpful to have an editor class (TEditor) that creates the TEmmet object and contain some helpful methods that makes it easier to use.

Alextp
Posts: 28
Joined: 23 Aug 2014 23:36

Re: Pascal Emmet

Post by Alextp » 31 May 2019 12:00

Agree - IndentString is not needed, as well as prop for |.
I have founds bugs.
https://docs.emmet.io/cheat-sheet/

Bugs are
https://github.com/Alexey-T/Emmet-Pascal/issues

User avatar
Rickard Johansson
Site Admin
Posts: 5821
Joined: 19 Jul 2006 14:29

Re: Pascal Emmet

Post by Rickard Johansson » 31 May 2019 12:23

They all work at my end :?

Are you using Lazarus? Could there be something in the code that works differently in Lazarus? Linefeeds maybe?

I use #13#10 as linefeed which works perfectly in Delphi and makes the result easy to process.

User avatar
Rickard Johansson
Site Admin
Posts: 5821
Joined: 19 Jul 2006 14:29

Re: Pascal Emmet

Post by Rickard Johansson » 31 May 2019 12:30

Actually the abbreviation "c" isn't implemented (yet).

Alextp
Posts: 28
Joined: 23 Aug 2014 23:36

Re: Pascal Emmet

Post by Alextp » 31 May 2019 12:57

Lazarus, yes. It gives warnings.
IMO these are the reason.

- main is "function ClimpUpOneLevel" result is not set. What result to set?
- func AddExpanded result is not inited. (you have Result:= Result+....)
- func GetAbbreviationNames: param AList must not be "out" - with "out" FreePascal uses write-only parameter
- func GetSnippetNames: AList must not be "out"

User avatar
Rickard Johansson
Site Admin
Posts: 5821
Joined: 19 Jul 2006 14:29

Re: Pascal Emmet

Post by Rickard Johansson » 31 May 2019 13:10

Fixed (see first post). Hope that helps... :?

Post Reply