AkelEmmet - Emmet (ex Zen Coding) wrapper for AkelPad

English main discussion
  • Author
  • Message
Offline
Posts: 53
Joined: Wed Dec 09, 2015 6:33 pm

AkelEmmet - Emmet (ex Zen Coding) wrapper for AkelPad

Post by beotiger »

AkelEmmet

AkelEmmet is an Emmet http://emmet.io (ex Zen Coding) wrapper for AkelPad.

Upgrade to AkelEmmet 1.2!

If you have AkelEmmet 1.0 or AkelEmmet 1.1 please upgrade to AkelEmmet 1.2. To upgrade download new archive from location below and unpack it to [AkelPad]\AkelFiles\Plugs\Scripts. You can remove folder [AkelPad]\AkelFiles\Tools\emmet then. Do not forget to move your snippets and extensions if you have ones from Tools\emmet\ext folder to Plugs\Scripts\Include\Emmet\ext. Change menu entries for Context::Menu Edit and ToolBar menu to set new path to icon_16.ico as shown below.



Image
Image



You need Scripts plugin to run this AkelEmmet wrapper. All other plugins are optional.


1. Installation

1.1 Downloading and unpacking

Download AkelEmmet 1.2 and unzip it to [AkelPad]\AkelFiles\Plugs\Scripts


1.2 Add menu entries for toolbar and context menu (optional)
Note: for menu entries you need ToolBar and ContextMenu plugins.

Call ContextMenu::Main plugin function (Options - Plug-ins...) and add following code at the end of ContextMenu::ShowMenu section:

Code: Select all

"EMMET"
{
	"Expand Abbreviation" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=0')
	"Wrap with Abbreviation" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=3')
	"Balance Tag" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=1')
	"Balance Tag Inward" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=2')
	"Next Edit Point" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=4')
	"Previous Edit Point" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=5')
	SEPARATOR1
	"Merge Lines" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=6')
	"Remove Tag" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=7')
	"Split/Join Tag" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=8')
	"Toggle Comment" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=9')
	SEPARATOR1
	"Select Next Item" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=17')
	"Select Previous Item" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=18')
	"Reflect CSS Value" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=19')
	SEPARATOR1
	"Evaluate Math Expresison" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=10')
	"Increment Number By 1" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=11')
	"Decrement Number By 1" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=12')
	"Increment Number By 0.1" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=13')
	"Decrement Number By 0.1" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=14')
	"Increment Number By 10" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=15')
	"Decrement Number By 10" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=16')
	SEPARATOR1
	"Update Image Size" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=20')
	"Encode/Decode image to data:URL" Call("Scripts::Main", 1, "AkelEmmet.js", '-action=21')
}


Now add following code in ContextMenu::Edit menu section:

Code: Select all

SEPARATOR1
	"Emmet" Menu("EMMET") Icon("%a\AkelFiles\Plugs\Scripts\Include\Emmet\icon_16.ico")


Click right mouse button on any place inside tool bar and add the following code at place you like most

Code: Select all

SEPARATOR1
"Emmet: Expand Abbreviation"  Call("Scripts::Main", 1, "AkelEmmet.js", '-action=0') Menu("EMMET") Icon("%a\AkelFiles\Plugs\Scripts\Include\Emmet\icon_16.ico")
SEPARATOR1


1.3 Adding hotkey
Add hotkey [Ctrl+Enter] (or any of your choice) for calling AkelEmmet.js script.
Its default action is 'expand_abbreviation' - that is expand abbreviation.
You can do this by calling Scripts::Main (Alt-p, Scripts::Main, [Call]) and assigning key for AkelEmmet.js script.

To make hotkeys for various Emmet actions you need Hotkeys plugin.
To see some Emmet's logs you need to have Log plugin installed.

All plugins mentioned here are official and can be downloaded
from official plugins page at http://akelpad.sourceforge.net/en/plugins.php


2. Usage.
Call AkelEmmet.js with parameter `action` to exec any of supported Emmet actions.
`action` can be # of command from list (see source of AkelEmmet.js for full list of commands)
or name of Emmet action, e.g. 'match_pair_outward' or 'toggle_comment'

Examples:
Call("Scripts::Main", 1, "AkelEmmet.js") - to run default action which is 'expand_abbreviation'
Call("Scripts::Main", 1, "AkelEmmet.js", `-action=4`) - to run 'next_edit_point' action
Call("Scripts::Main", 1, "AkelEmmet.js", `-action='select_next_item'`) - to select next item
and so on.

You can set hotkeys for desired commands through Hotkey plugin.

Recommended hotkeys (its up to you):
[Ctrl+Enter] Expand Abbreviation Call("Scripts::Main", 1, "AkelEmmet.js")
[Ctrl+Shift+Enter] Wrap with Abbreviation Call("Scripts::Main", 1, "AkelEmmet.js", `-action=3`)
[Ctrl+Alt+Right] Emmet next edit point Call("Scripts::Main", 1, "AkelEmmet.js", `-action=4`)
[Ctrl+Alt+Left] Emmet previous edit point Call("Scripts::Main", 1, "AkelEmmet.js", `-action=5`)
[Alt+T] Toggle comment Call("Scripts::Main", 1, "AkelEmmet.js", `-action='toggle_comment'`)
* Note: toggle comment works for HTML/CSS files

3. Test
Type in abbreviation and press [Ctrl+Enter] if you defined it as a hotkey for default Emmet action to expand it.

Open empty document (Ctrl+n), type in following abbreviation and expand it:

Code: Select all

!(h1{Hello world!}+ul>li*5>lorem50^^h1{Bye-bye})
Then save it as hi-emmet.html (Ctrl+s) for example and run it in your browser.

Code: Select all

div>ul>li*5>b
p*5>lorem12(span.span-deva$*3>b{This is my span #$})
div#content>h1+p
div#page>div.logo+ul#navigation>li*5>a[style="text-decoration: none" id="link$$"]
table>(tr.g$>td^tr>td)*3
{Item$${newline}}*3
html:xs


To test some CSS snippets open css file and try to expand

Code: Select all

w100
h10p+m5e
@f
@f+
tdn
posrel
ov-h
ovh
oh
trs
trf
-super-foo
-wm-trf
lg(left, #fff 50%, #000)
lorem10
pb
p10p
db+w100+h100+posa+l-100+t60


Note that same abbreviation for css and html files can expand differently.


4. Extending
You can put Emmet extensions into `Include\Emmet\ext` folder.

Extensions are simple .js files that uses Emmet modules and resources
to create new actions, modify existing ones etc.

When any Emmet action starts, all `*.js` files in `Include\Emmet\ext` folder will be eval'ed,
and all `snippets*.json` files will extend `snippets` Emmet object.

It allows you to extend and rewrite Emmet behaviour and snippets any way you want.

That's all. Good coding.
--
beotiger

P.S.

Code: Select all

The MIT License (MIT)

Copyright (c) 2012 Sergey Chikuyonok <serge.che@gmail.com>
Support for AkelPad by beotiger http://beotiger.com 2016-01-05

Permission is hereby granted, free of charge, to any person obtaining a copy of 
this software and associated documentation files (the "Software"), to deal in the 
Software without restriction, including without limitation the rights to use, 
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the 
Software, and to permit persons to whom the Software is furnished to do so, 
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all 
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Last edited by beotiger on Thu Jan 07, 2016 10:04 am, edited 3 times in total.

Offline
Posts: 2247
Joined: Tue Aug 07, 2007 2:03 pm
Location: Vinnitsa, Ukraine

Post by FeyFre »

1. Рекомендую за рамки принятых каталогов не вылезять:
скрипты которые вызываются - в Scripts
скрипты которые используются другими скриптами и никогда не вызываются пользователем - в Scripts/Include
Далее 1:

eval(AkelPad.ReadFile(...)); обязательно заменить на AkelPad.Include(). Поверьте на слово.

Далее 2:

Code: Select all

		getCurrentLine: function() {
			var range = this.getCurrentLineRange();
			var nSelStart = AkelPad.GetSelStart(),
					nSelEnd = AkelPad.GetSelEnd();
					
					
			AkelPad.SetSel(range.start, range.end);
			var text = AkelPad.GetSelText();
			// restore selection
			AkelPad.SetSel(nSelStart, nSelEnd);
			return text;
		},
нужно сделать так

Code: Select all

getCurrentLine: function() {
			var range = this.getCurrentLineRange();
			return AkelPad.GetTextRange(range.start, range.end);
		}
т.е. нет абсолютно никакой необходимости играться выделениями.

Далее 3:

Code: Select all

		getSyntax: function(){
			return require('actionUtils').detectSyntax(this, 
				AkelPad.GetFilePath(this.getFilePath(), 4 /*FILE_EXT*/).toLowerCase());
		},
Этот код может и должен быть улучшен, а именно: перед ориентацией на расширение рекомендуется спросить в других местах текущий контекст, например у плагина Coder

beotiger, у вас то руки раньше дошли чем у меня.

Offline
Posts: 53
Joined: Wed Dec 09, 2015 6:33 pm

Post by beotiger »

FeyFre wrote:1. Рекомендую за рамки принятых каталогов не вылезять:
скрипты которые вызываются - в Scripts
скрипты которые используются другими скриптами и никогда не вызываются пользователем - в Scripts/Include
Далее 1:

eval(AkelPad.ReadFile(...)); обязательно заменить на AkelPad.Include(). Поверьте на слово.

Далее 2:

Code: Select all

		getCurrentLine: function() {
			var range = this.getCurrentLineRange();
			var nSelStart = AkelPad.GetSelStart(),
					nSelEnd = AkelPad.GetSelEnd();
					
					
			AkelPad.SetSel(range.start, range.end);
			var text = AkelPad.GetSelText();
			// restore selection
			AkelPad.SetSel(nSelStart, nSelEnd);
			return text;
		},
нужно сделать так

Code: Select all

getCurrentLine: function() {
			var range = this.getCurrentLineRange();
			return AkelPad.GetTextRange(range.start, range.end);
		}
т.е. нет абсолютно никакой необходимости играться выделениями.

Далее 3:

Code: Select all

		getSyntax: function(){
			return require('actionUtils').detectSyntax(this, 
				AkelPad.GetFilePath(this.getFilePath(), 4 /*FILE_EXT*/).toLowerCase());
		},
Этот код может и должен быть улучшен, а именно: перед ориентацией на расширение рекомендуется спросить в других местах текущий контекст, например у плагина Coder

beotiger, у вас то руки раньше дошли чем у меня.
FeyFre спасибо за замечания! Все они учтены в новой версии скрипта - AkelEmmet 1.2.
Так же скрипт получил новую постоянную локацию - http://akelpad.sourceforge.net/forum/vi ... 0266#30266

FeyFre thanks for your notes. They have been taken into consideration and new version of AkelEmmet is out. It's faster and better due to you!
Also AkelEmmet got new persistent location - http://akelpad.sourceforge.net/forum/vi ... 0266#30266

Offline
Site Admin
Posts: 6311
Joined: Thu Jul 06, 2006 7:20 am

Post by Instructor »

beotiger
file.js wrote:function WriteFile(sFile, sData)
AkelPad.WriteFile?

Юникод кодировку скрипта (AkelEmmet.js) лучше использовать с BOM.

KDJ
Offline
Posts: 1949
Joined: Sat Mar 06, 2010 7:40 pm
Location: Poland

Post by KDJ »

beotiger
I wrote WriteFile function at a time when there was no WriteFile method in Scripts plugin.
Now you can use AkelPad.WriteFile instead of WriteFile.

Offline
Posts: 53
Joined: Wed Dec 09, 2015 6:33 pm

Post by beotiger »

Instructor wrote:beotiger
file.js wrote:function WriteFile(sFile, sData)
AkelPad.WriteFile?

Code: Select all

Read contents of a file.

  ReadFile(pFile[, nFlags][, nCodePage][, bBOM][, nBytesMax]);


Code: Select all

Write file content.

  WriteFile(vFile, pContent, nContentLen, nCodePage, bBOM[, nFlags]);


Меня смущает, что при записи файла обязательно указывать кодировку, тогда как при чтении её можно опустить.

Какую кодировку указывать при записи бинарных данных?
Никаких преобразований над бинарными данными не делается?

Instructor wrote:Юникод кодировку скрипта (AkelEmmet.js) лучше использовать с BOM.
Причина?

Offline
Posts: 2247
Joined: Tue Aug 07, 2007 2:03 pm
Location: Vinnitsa, Ukraine

Post by FeyFre »

beotiger, забудь о бинарных данных. Все строки которые ходят внутри АР и в плагинах(в т.ч. скриптах) - z-строки, внутри хранятся в UTF-16 кодировке. Если что-то такое нужно делать - АР не помощник.
Для этих целей есть oSys.Call(диспетчер системных вызовов WINAPI), AkelPad.Mem*(менеджер памяти).
Причина?
Чтобы потом можно было распознать кодировку автоматически, а не гадать на гуще. Конечно если в файле полезные данные исключительно в наборе символов iso8859-1, то не правильно распознанная кодировка данных не испортит.

Offline
Posts: 582
Joined: Mon Apr 08, 2013 9:50 pm
Location: Win7SP1x64, APx64

Post by Drugmix »

Не знал, что можно просто взять и приделать стороннюю обёртку к АкелПаду.
А все функции (хоткеи, плагины, скрипты) акелпада при этом продолжают нормально работать?
Интересно было бы пощупать AkelPad со Scintilla обёрткой.

Offline
Posts: 2247
Joined: Tue Aug 07, 2007 2:03 pm
Location: Vinnitsa, Ukraine

Post by FeyFre »

Drugmix, больше скажу: это не первая успешная попытка прикрутить zen_coding.
Интересно было бы пощупать AkelPad со Scintilla обёрткой.
"Установил Скайп на телефон, теперь могу пользоваться телефоном как телефоном". При таких вбросах нужно ссылку давать на испытуемое :)

Offline
Posts: 53
Joined: Wed Dec 09, 2015 6:33 pm

Post by beotiger »

Drugmix wrote:Не знал, что можно просто взять и приделать стороннюю обёртку к АкелПаду.
Emmet написан на чистом JavaScript, поэтому всю работу за нас выолняет великолепный Scripts плагин. нам надо было только переписать характерные для AkelPad'а функции редактирования текста и работы с файлами.
Drugmix wrote:А все функции (хоткеи, плагины, скрипты) акелпада при этом продолжают нормально работать?
AkelEmmet.js - это обычный скрипт, который Вы запускате либо из Scripts плагина, либо по назначению горячих клавиш. Он никак не влияет на работу самого редактора. В нём содержатся действия Emmet'а, для которых можно также назначить горячие клавиши или пункты меню. Прочитайте AkelEmmet_readme_ru.txt для понимания ситуации.
FeyFre wrote:Drugmix, больше скажу: это не первая успешная попытка прикрутить zen_coding.
FeyFre, там ссылки битые, может их исправить, а то они меня ввели в заблуждение.
FeyFre wrote:
Интересно было бы пощупать AkelPad со Scintilla обёрткой.
"Установил Скайп на телефон, теперь могу пользоваться телефоном как телефоном". При таких вбросах нужно ссылку давать на испытуемое :)
Тут имеется в виду, наверное, что если сделать обёртку Scintilla для AkelPad'а, то можно будет использовать Scintilla-плагины.
Теоретически можно наверное, только сколько это займет человеко-часов неясно. Да и зачем. У AkelPad'а своя неповторимая атмосфера и своя философия работы с текстом, по моему скромному мнению.

Offline
Posts: 53
Joined: Wed Dec 09, 2015 6:33 pm

Post by beotiger »

FeyFre wrote:beotiger, забудь о бинарных данных. Все строки которые ходят внутри АР и в плагинах(в т.ч. скриптах) - z-строки, внутри хранятся в UTF-16 кодировке. Если что-то такое нужно делать - АР не помощник.
Для этих целей есть oSys.Call(диспетчер системных вызовов WINAPI), AkelPad.Mem*(менеджер памяти).
FeyFre, на основе KDJ's FileAndStream_functions.js я написал функцию

Code: Select all

//-----------------------------------------------------
// sContent = readFile(sFile)
//
// Arguments:
// sFile   - full file name
//
// Return value:
// sContent - content of file
//-----------------------------------------------------
function ReadFile(sFile)
{
  var sContent = '',
  		br;	// bytes read

  var hFromFile = AkelPad.SystemFunction().Call("Kernel32::CreateFile" + _TCHAR,
                    sFile, //lpFileName
                    0x80000000, //dwDesiredAccess = GENERIC_READ
                    1,          //dwShareMode = FILE_SHARE_READ
                    0,          //lpSecurityAttributes
                    3,          //dwCreationDisposition = OPEN_EXISTING
                    0x08000000, //dwFlagsAndAttributes = FILE_FLAG_SEQUENTIAL_SCAN
                    0);         //hTemplateFile

   if(hFromFile != -1) {
     var nBufSize       = 64 * 1024;
     var lpBuffer       = AkelPad.MemAlloc(nBufSize);
     var lpBytesRead    = AkelPad.MemAlloc(4);

     do
     {
       AkelPad.SystemFunction().Call("Kernel32::ReadFile", hFromFile, lpBuffer, nBufSize, lpBytesRead, 0);
			 if(br = AkelPad.MemRead(lpBytesRead, 3 /*DT_DWORD*/))	// bytes read
       		sContent += AkelPad.MemRead(lpBuffer, 0 /*DT_ANSI*/, br);
     }
     while (br == nBufSize);

     AkelPad.MemFree(lpBuffer);
     AkelPad.MemFree(lpBytesRead);
     AkelPad.SystemFunction().Call("Kernel32::CloseHandle", hFromFile);
   }
 
  return sContent;
}
, которая читает бинарный файл.
Но потом сравнил её со встроенным методом AkelPad.ReadFile и увидел, что они читают одинаково, поэтому отказался от неё.
WriteFile'же в editor.js остался, так как мне неясно, как ведет себя AkelPad.WriteFile при записи бинарников (по причине, описанной выше).

Offline
Site Admin
Posts: 6311
Joined: Thu Jul 06, 2006 7:20 am

Post by Instructor »

beotiger
file.js wrote:AkelPad.MemCopy(lpBuffer, sData, 0);
0 это DT_ANSI. Т.е. можно заменить WriteFile на:

Code: Select all

AkelPad.WriteFile(sFile, sData, -1, AkelPad.SystemFunction().Call("kernel32::GetACP"), false);
А с версии 4.9.8 можно использовать -1:

Code: Select all

AkelPad.WriteFile(sFile, sData, -1, -1, false);

Offline
Posts: 171
Joined: Thu Dec 01, 2011 11:15 pm
Location: Россия

Post by LonerD »

Balance в скрипте не работает таким образом, как продемонстрировано на сайте Emmet, или это только у меня проблемы возникли?
Выделяется только один раз, и при последующих нажатиях выделение не расширяется на теги уровнем выше.
Balance Tag Inward - в большую сторону один раз выделяется, и всё, выделение не уменьшается.

Encode/Decode Image to data:URL и Update Image Size тоже как-то непонятно - скрипт просто открывает окошко лог-файла.

Offline
Posts: 60
Joined: Tue Aug 21, 2012 11:17 am
Location: UK

Post by tmsg »

Discussion (English)... really?

KDJ
Offline
Posts: 1949
Joined: Sat Mar 06, 2010 7:40 pm
Location: Poland

Post by KDJ »

tmsg
Discussion is English-Russian. :)

-----
Instructor wrote:А с версии 4.9.8 можно использовать -1:

Code: Select all

AkelPad.WriteFile(sFile, sData, -1, -1, false);
This is not documented in Scripts-Eng.txt.
Post Reply