# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
# 
# The contents of this file are subject to the Mozilla Public License
# Version 1.1 (the "License"); you may not use this file except in
# compliance with the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
# 
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License.
# 
# The Original Code is Komodo code.
# 
# The Initial Developer of the Original Code is ActiveState Software Inc.
# Portions created by ActiveState Software Inc are Copyright (C) 2000-2007
# ActiveState Software Inc. All Rights Reserved.
# 
# Contributor(s):
#   ActiveState Software Inc
# 
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
# 
# ***** END LICENSE BLOCK *****

# Komodo RHTML language service.
#
# Generated by 'luddite.py' on Thu Jul  5 12:35:29 2007.
#

import logging
from koXMLLanguageBase import koHTMLLanguageBase

import scimozindent

log = logging.getLogger("koRHTMLLanguage")
#log.setLevel(logging.DEBUG)


def registerLanguage(registry):
    log.debug("Registering language RHTML")
    registry.registerLanguage(KoRHTMLLanguage())


class KoRHTMLLanguage(koHTMLLanguageBase):
    name = "RHTML"
    lexresLangName = "RHTML"
    _reg_desc_ = "%s Language" % name
    _reg_contractid_ = "@activestate.com/koLanguage?language=%s;1" % name
    _reg_clsid_ = "{A554B7D4-7920-4BDC-BA71-5D8555B9C9DB}"
    defaultExtension = '.rhtml'

    lang_from_udl_family = {'CSL': 'JavaScript', 'TPL': 'RHTML', 'M': 'HTML', 'CSS': 'CSS', 'SSL': 'Ruby'}

    sample = """<ul>
<% @products.each do |p| %>
  <li><%=  @p.name %></li>
<% end %>
</ul>
"""

    def insertInternalNewline_Special(self, scimoz, indentStyle, currentPos,
                                      allowExtraNewline, style_info):
        """
        Split %|% so the %'s are on separate lines, and there's a blank line
        in the middle.
        """
        if indentStyle is None or currentPos < 2:
            return None
        if scimoz.getStyleAt(currentPos) != scimoz.SCE_UDL_TPL_OPERATOR:
            return None
        percentChar = ord("%")
        if scimoz.getCharAt(currentPos) != percentChar:
            return None
        prevPos = currentPos - 1 # ascii
        if scimoz.getStyleAt(prevPos) != scimoz.SCE_UDL_TPL_OPERATOR:
            return None
        if scimoz.getCharAt(prevPos) != percentChar:
            return None
        prev2Pos = prevPos - 1
        if scimoz.getStyleAt(prev2Pos) != scimoz.SCE_UDL_TPL_OPERATOR:
            return None
        if scimoz.getCharAt(prev2Pos) != ord("<"):
            return None        
        lineNo = scimoz.lineFromPosition(currentPos)
        closeIndentWidth = self._getIndentWidthForLine(scimoz, lineNo)
        if indentStyle == 'smart':
            """
            i<%|% ==>
            
            i<%
            i....<|>
            i%
            
            where "i" denotes the current leading indentation
            """
            intermediateLineIndentWidth = self._getNextLineIndent(scimoz, lineNo)
        else:
            """
            i<%|% ==>
            
            i<%
            i<|>
            i%
            
            Note that the indentation of inner attr lines are ignored, even in block-indent mode:
            i<foo
            i........attr="val">|</foo> =>
            
            i<foo
            i........attr="val">
            i</foo>
            """
            intermediateLineIndentWidth = closeIndentWidth
        
        currentEOL = eollib.eol2eolStr[eollib.scimozEOL2eol[scimoz.eOLMode]]
        textToInsert = currentEOL + scimozindent.makeIndentFromWidth(scimoz, intermediateLineIndentWidth)
        finalPosn = currentPos + len(textToInsert) #ascii-safe
        if allowExtraNewline:
            textToInsert += currentEOL + scimozindent.makeIndentFromWidth(scimoz, closeIndentWidth)
        scimoz.addText(len(textToInsert), textToInsert) #ascii-safe
        return finalPosn
    
    def computeIndent(self, scimoz, indentStyle, continueComments):
        return self._computeIndent(scimoz, indentStyle, continueComments, self._style_info)

    def _computeIndent(self, scimoz, indentStyle, continueComments, style_info):
	res = self._doIndentHere(scimoz, indentStyle, continueComments, style_info)
	if res is None:
	    return koHTMLLanguageBase._computeIndent(self, scimoz, indentStyle, continueComments, self._style_info)
	return res

    def _keyPressed(self, ch, scimoz, style_info):
	res = self._doKeyPressHere(ch, scimoz, style_info)
	if res is None:
	    return koHTMLLanguageBase._keyPressed(self, ch, scimoz, style_info)
	return res

    _startWords = "begin case else elsif ensure for if rescue unless until while".split(" ")

    def _doIndentHere(self, scimoz, indentStyle, continueComments, style_info):
	pos = scimoz.positionBefore(scimoz.currentPos)
	startPos = scimoz.currentPos
	style = scimoz.getStyleAt(pos)
	if style != scimoz.SCE_UDL_TPL_OPERATOR:
	    return None
	if scimoz.getWCharAt(pos) != ">":
	    return None
	pos -= 1
	style = scimoz.getStyleAt(pos)
	if style != scimoz.SCE_UDL_TPL_OPERATOR:
	    return None
	if scimoz.getWCharAt(pos) != "%":
	    return None
	curLineNo = scimoz.lineFromPosition(pos)
	lineStartPos = scimoz.positionFromLine(curLineNo)
        delta, numTags = self._getTagDiffDelta(scimoz, lineStartPos, startPos)
        if delta < 0 and numTags == 1 and curLineNo > 0:
            didDedent, dedentAmt = self.dedentThisLine(scimoz, curLineNo, startPos)
            if didDedent:
                return dedentAmt
            else:
                # Since RHTML tags end with a ">", keep the
                # HTML auto-indenter out of here.
                return self._getRawIndentForLine(scimoz, curLineNo)
	indentWidth = self._getIndentWidthForLine(scimoz, curLineNo)
	indent = scimoz.indent
	newIndentWidth = indentWidth + delta * indent
	if newIndentWidth < 0:
	    newIndentWidth = 0
	#qlog.debug("new indent width: %d", newIndentWidth)
	return scimozindent.makeIndentFromWidth(scimoz, newIndentWidth)

    def _doKeyPressHere(self, ch, scimoz, style_info):
	# Returns either None or an indent string
	pos = scimoz.positionBefore(scimoz.currentPos)
	startPos = scimoz.currentPos
	style = scimoz.getStyleAt(pos)
	if style != scimoz.SCE_UDL_TPL_OPERATOR:
	    return None
	if scimoz.getWCharAt(pos) != ">":
	    return None
	pos -= 1
	curLineNo = scimoz.lineFromPosition(pos)
	lineStartPos = scimoz.positionFromLine(curLineNo)
        delta, numTags = self._getTagDiffDelta(scimoz, lineStartPos, startPos)
        if delta < 0 and numTags == 1 and curLineNo > 0:
            didDedent, dedentAmt = self.dedentThisLine(scimoz, curLineNo, startPos)
            if didDedent:
                return dedentAmt
        # Assume the tag's indent level is fine, so don't let the
        # HTML auto-indenter botch things up.
        return self._getRawIndentForLine(scimoz, curLineNo)

    def _getTagDiffDelta(self, scimoz, lineStartPos, startPos):
	data = scimoz.getStyledText(lineStartPos, startPos)
	chars = data[0::2]
	styles = [ord(x) for x in data[1::2]]
	lim = len(styles)
	delta = 0
        numTags = 0
	i = 0
	limSub1 = lim - 1
	while i < limSub1:
	    if (styles[i] == scimoz.SCE_UDL_TPL_OPERATOR
		and styles[i + 1] == scimoz.SCE_UDL_TPL_OPERATOR
		and chars[i] == '<'
		and chars[i + 1] == "%"):
		j = i + 2
		while (j < lim
		       and styles[j] == scimoz.SCE_UDL_SSL_DEFAULT):
		    j += 1
		if styles[j] != scimoz.SCE_UDL_SSL_WORD:
		    i = j + 1
                    continue
		wordStart = j
		while (j < lim
		       and styles[j] == scimoz.SCE_UDL_SSL_WORD):
		    j += 1
		word = chars[wordStart:j]
		if word == 'end':
                    numTags += 1
		    delta -= 1
		elif word in self._startWords:
                    numTags += 1
		    delta += 1
		i = j
	    else:
		i += 1
        return delta, numTags
