Re: "Zen Coding" style module for Textadept

From: Jay <robert.jay.go....at.gmail.com>
Date: Fri, 4 Jun 2010 08:10:06 -0700 (PDT)

At some point I lost the script I was working on, my bad... anyways
here is what I got working again:

Fixes:
-debug print
-parser is now more generic
-defaults to div (as per zen spec => #content>.section is the same as
div#content>div.section)
--------------------------------------------------------------------------------
-- The MIT License

--
-- Copyright (c) 2010 Brian Schott
--
-- 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.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Note: I did not look at any of the Zen Coding code while creating
this
-- module. I looked only at the syntax reference posted here:
-- http://code.google.com/p/zen-coding/wiki/ZenHTMLSelectorsEn
--------------------------------------------------------------------------------
module('_m.hypertext.zen', package.seeall)
--------------------------------------------------------------------------------
-- Configuration options for the various tags.
--------------------------------------------------------------------------------
local SPECIAL_TAGS = {
	a = {singleLine = true, indentChildren = false, attributes =
{"href"}},
	acronym = {singleLine = true, indentChildren = false, attributes =
{"title"}},
	area = {singleLine = true, indentChildren = false, attributes =
{"shape", "coords", "href", "alt"}},
	bdo = {singleLine = true, indentChildren = false, attributes =
{"dir"}},
	button = {singleLine = true, indentChildren = false, attributes =
{"type"}},
	caption = {singleLine = true, indentChildren = false, attributes =
{}},
	colgroup = {singleLine = true, indentChildren = false, attributes =
{}},
	dl = {singleLine = true, indentChildren = false, attributes = {}},
	dt = {singleLine = true, indentChildren = false, attributes = {}},
	em = {singleLine = true, indentChildren = false, attributes = {}},
	h1 = {singleLine = false, indentChildren = false, attributes = {}},
	h2 = {singleLine = false, indentChildren = false, attributes = {}},
	h3 = {singleLine = false, indentChildren = false, attributes = {}},
	h4 = {singleLine = false, indentChildren = false, attributes = {}},
	h5 = {singleLine = false, indentChildren = false, attributes = {}},
	li = {singleLine = false, indentChildren = false, attributes = {}},
	iframe = {singleLine = false, indentChildren = true, attributes =
{"src", "width", "height"}},
	label = {singleLine = true, indentChildren = false, attributes =
{"for"}},
	map = {singleLine = true, indentChildren = false, attributes =
{"name"}},
	noframes = {singleLine = true, indentChildren = false, attributes =
{}},
	noscript = {singleLine = true, indentChildren = false, attributes =
{}},
	object = {singleLine = true, indentChildren = false, attributes =
{}},
	small = {singleLine = true, indentChildren = false, attributes = {}},
	span = {singleLine = true, indentChildren = false, attributes =
{"style"}},
	strong = {singleLine = true, indentChildren = false, attributes =
{}},
	sub = {singleLine = true, indentChildren = false, attributes = {}},
	sup = {singleLine = true, indentChildren = false, attributes = {}},
	table = {singleLine = false, indentChildren = true, attributes =
{"border"}},
	textarea = {singleLine = false, indentChildren = true, attributes =
{"rows", "cols"}},
	td = {singleLine = true, indentChildren = false, attributes = {}},
	th = {singleLine = true, indentChildren = false, attributes = {}},
	tr = {singleLine = false, indentChildren = false, attributes = {}},
	td = {singleLine = true, indentChildren = false, attributes = {}},
}
local function tokenizeZen(text)
	local i = 0
	local t = {}
	while #text ~= 0 do
		local capture = text:match("^%P+") or text:match("%p")
		if capture == nil then return nil end
		table.insert(t, capture)
		text = text:sub(#capture + 1)
		i = i + 1
	end
	return t
end
local function parseZen(partsTable)
	tree = {}
	currentParent = tree
	current = {class={}, children={}, multiplier=1}
	-- 0 = element name
	-- 1 = multiplier
	-- 2 = class
	-- 4 = id
	local meaning = 0
	for i, j in ipairs(partsTable) do
		if j:match(">") then
			table.insert(currentParent, current)
			print("adding "..(current.name or '<none>'))
			currentParent = current.children
			current = {class={}, children={}, multiplier=1}
			meaning = 0
		elseif j:match("%*") then
			meaning = 1
		elseif j:match("%.") then
			meaning = 2
		elseif j:match("%+") then
			table.insert(currentParent, current)
			print("adding "..(current.name or '<none>'))
			current = {class={}, children={}, multiplier=1}
			meaning = 0
		elseif j:match("#") then
			meaning = 3
		else
			if meaning == 0 then
				current.name = j
			elseif meaning == 1 then
				current.multiplier = tonumber(j)
			elseif meaning == 2 then
				table.insert(current.class, j)
			elseif meaning == 3 then
				current.id = j
			end
		end
	end
	print("adding "..(current.name or '<none>'))
	table.insert(currentParent, current)
	return tree
end
local function printStack(elementList, index)
	if #elementList == 0 then return "" end
	for index, current in ipairs(elementList) do
		for j = 1, current.multiplier do
			--if current.name == nil then return "" end
			buffer:add_text("<"..(current.name or "div"))
			if current.id ~= nil then
				buffer:add_text(" id=\""..current.id.."\"")
			end
			if #current.class ~= 0 then
				buffer:add_text(" class=\"")
				for i = 1, #current.class do
					if i > 1 then buffer:add_text(" ") end
					buffer:add_text(current.class[i])
				end
				buffer:add_text("\"")
			end
			if SPECIAL_TAGS[current.name] ~= nil then
				for index, attribute in
ipairs(SPECIAL_TAGS[current.name].attributes) do
					buffer:add_text(" "..attribute.."=\"\"")
				end
			end
			buffer:add_text(">")
			if SPECIAL_TAGS[current.name] == nil
					or SPECIAL_TAGS[current.name].indentChildren ~= false then
				buffer:new_line()
				buffer:tab()
			end
			printStack(current.children, index + 1)
			if SPECIAL_TAGS[current.name] == nil
					or SPECIAL_TAGS[current.name].indentChildren ~= false then
				if #current.children ~= 0 then buffer:new_line() end
				buffer:back_tab()
			end
			buffer:add_text("</"..(current.name or "div")..">")
			if SPECIAL_TAGS[current.name] == nil or
SPECIAL_TAGS[current.name].singleLine ~= true then
				if j ~= current.multiplier then buffer:new_line() end
			end
		end
		if index ~= #elementList then buffer:new_line() end
	end
end
function process_zen()
	buffer:begin_undo_action()
	local pos = buffer.current_pos
	buffer:word_left_end_extend()
	while true do
		if buffer:get_sel_text():match("^%s") == nil then
			if buffer.current_pos == 0 then break end
			buffer:word_left_end_extend()
		else
			buffer:word_right_extend()
			break
		end
	end
	local text = buffer:get_sel_text()
	local returnValue = false
	if text:match("[%w%*>%.]+") then
		local partsTable = tokenizeZen(text)
		if partsTable ~= nil then
			buffer:replace_sel("")
			returnValue = true
			local tree = parseZen(partsTable)
			printStack(tree, 1)
		else
			buffer:set_selection(pos, pos)
		end
	else
		buffer:set_selection(pos, pos)
	end
	buffer:end_undo_action()
	return returnValue
end
On May 21, 3:09 pm, Jay <robert.jay.go....at.gmail.com> wrote:
> adding them about 2/3 finished with attributes, fixed default divs
> already (rather trivial).
>
> -Jay
>
> On May 21, 1:55 am, Brian Schott <briancsch....at.gmail.com> wrote:
>
>
>
>
>
> > I'll get the debug statements fixed and a new version uploaded later
> > tonight.
>
> > Unrelated: 0.5 of Xmlcomplete is out. New feature: encloseTag function. It
> > places <|> and </|> on either side of the currently selected text. (The pipe
> > character represents a text cursor)http://caladbolg.net/textadeptwiki/uploads/xmlcomplete.lua
>
> > "adding two extra standard Zen code features:"
> > What about adding them? You did add them, or you're making a feature
> > request?
>
> > - Brian
>
> > On Thu, May 20, 2010 at 7:33 AM, Jay <robert.jay.go....at.gmail.com> wrote:
> > > adding two extra standard Zen code features:
>
> > > 1) Custom attributes: div[title], a[title="Hello world" rel],
> > > td[colspan=2].
> > > 2) div tag name can be omitted when writing element starting from ID
> > > or CLASS: #content>.section is the same as div#content>div.section.
>
> > > attributes are tricky...
>
> > > -Jay
>
> > --
> > You received this message because you are subscribed to the Google Groups "textadept" group.
> > To post to this group, send email to textadept.at.googlegroups.com.
> > To unsubscribe from this group, send email to textadept+unsubscribe.at.googlegroups.com.
> > For more options, visit this group athttp://groups.google.com/group/textadept?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups "textadept" group.
> To post to this group, send email to textadept.at.googlegroups.com.
> To unsubscribe from this group, send email to textadept+unsubscribe.at.googlegroups.com.
> For more options, visit this group athttp://groups.google.com/group/texta
Received on Fri 04 Jun 2010 - 11:10:06 EDT

This archive was generated by hypermail 2.2.0 : Thu 08 Mar 2012 - 11:44:57 EST