# -*- coding: iso-8859-2 -*-
#
# reST roles helpers
#
# Wojciech Muła, http://0x80.pl/
# Public domain

#  2.12.2006
#   - tabstop option added
# 11.10.2006
#   - source_dir added

import re
import os

from docutils import io, nodes, statemachine, utils
from docutils.parsers.rst import directives, roles, states
from docutils.transforms import misc

def py_getdef(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine):

	filename = arguments[0]
	numbers  = 'lineno' 	in options
	unindent = 'unindent'	in options
	pattern  = options['def']
	try:
		tabstop = options['tabstop']
	except KeyError:
		tabstop = None
	
	# get source direcorty
	source     = state_machine.input_lines.source(lineno - state_machine.input_offset - 1)
	source_dir = os.path.dirname(os.path.abspath(source))

	f = open(os.path.join(source_dir, filename), 'r')
	if tabstop is None:
		lines = [(lineno+1, line.rstrip())\
		         for (lineno, line) in enumerate(f)]
	else:
		lines = [(lineno+1, line.rstrip().expandtabs(tabstop))\
		         for (lineno, line) in enumerate(f)]
		
	f.close()

	for block in pattern.replace('\t',' ').split(' '):
		kind, name = block.split(':')
		lines = py_grep(lines, name.strip(), kind.strip())
	
	if not lines:	# empty
		return [nodes.literal_block('', '')]
	else:
		if unindent:
			# get first line indention
			n = len(lines[0][1]) - len(lines[0][1].lstrip())
			for i, (lineno, line) in enumerate(lines):
				lines[i] = (lineno, line[n:])

		if numbers:
			text = '\n'.join("%4d %s" % item for item in lines)
		else:
			text = '\n'.join( (line for (lineno,line) in lines) )

		return [nodes.literal_block(text, text)]

py_getdef.arguments = (1, 0, 1)
py_getdef.content = 0
py_getdef.options = {'def'    	: directives.unchanged_required,
                     'lineno' 	: directives.flag,
                     'unindent' : directives.flag,
					 'tabstop'	: directives.positive_int,
					 }


def py_grep(list, name, type="def"):
	regexp = re.compile("^\s*%s\s+%s" % (type, name))

	for i, (lineno, line) in enumerate(list):
		if regexp.match(line):
			return py_getblock(list[i:])
	return []

def py_getblock(code):
	if len(code) == 0:
		return []

	def get_indention(line, expandtabs=True):
		"""Get line's indention"""
		l = len(line)
		if expandtabs:
			t = len(line.expandtabs().lstrip())
			return l-t
		else:
			t = len(line.lstrip())
			return l-t
	
	initial_indent = get_indention(code[0][1])
	result = [code[0]]
	for lineno, line in code[1:]:
		indent = get_indention(line)
		if line != '' and indent == initial_indent:
			break
		else:
			result.append( (lineno, line) )
	
	while len(result) and result[-1][1] == '':
		result.pop()
	
	return result

# vim: ts=4 sw=4

