<commit_before>import sublime, sublime_plugin
from lib.util import communicate, which

import sys
# reload lib.util on update/reload of primary module
# so improvements will be loaded without a sublime restart
sys.modules['lib.util'] = reload(sys.modules['lib.util'])

import os
import re
import shlex

INDENTATION = '  '

class BoundaryError(Exception): pass

def xiki(view):
	settings = view.settings()

	output = None
	cmd = None
	oldcwd = None
	if settings.get('xiki'):
		indent, sign, path, tag, tree = find_tree(view)
		print 'xiki', sign, path, tree

		pos = get_pos(view)
		if get_line(view, 1).startswith(indent + INDENTATION):
			if sign == '-':
				replace_line(view, pos, indent + '+ ' + tag)

			edit = view.begin_edit()
			cleanup(view, edit, pos, indent + INDENTATION)
			select(view, pos)
			view.end_edit(edit)
			return
		elif sign == '$':
			if path:
				oldcwd = os.getcwd()

				# maybe this should be offloaded into find_tree
				# so path will be multiple directories instead of just a base dir
				path_re = r'^(.+)/%s$' % re.escape(tag)
				match = re.match(path_re, tree)
				if match:
					os.chdir(os.path.join(path, match.group(1)))
				else:
					os.chdir(path)

			cmd = shlex.split(tag.encode('ascii', 'replace'), True)
		elif path:
			# directory listing or file open
			target = os.path.join(path, tree)
			if os.path.isfile(target):
				sublime.active_window().open_file(target)
				return
			elif os.path.isdir(target):
				dirs = ''
				files = ''
				for entry in os.listdir(target):
					absolute = os.path.join(target, entry)
					if os.path.isdir(absolute):
						dirs += '+ %s/\n' % entry
					else:
						files += '%s\n' % entry

				output = (dirs + files) or '\n'
		elif sign == '-':
			# dunno here
			return
		elif tree:
			if which('ruby'):
				cmd = ['ruby', which('xiki')]
			else:
				cmd = ['xiki']

			cmd += tree.split(' ')

		if cmd:
			output = communicate(cmd, None, 3, return_error=True)
			if oldcwd:
				os.chdir(oldcwd)

		if output:
			if sign == '+':
				replace_line(view, pos, indent + '- ' + tag)

			insert(view, output, indent + INDENTATION)

def find_tree(view):
	regex = re.compile(r'^(\s*)([-+$]\s*)?(.*)$')

	view.run_command('single_selection')
	line = get_line(view)
	match = regex.match(line)

	line_indent = last_indent = match.group(1)
	sign = (match.group(2) or '').strip()
	tag = match.group(3)
	tree = [tag]
	if tag.startswith('/'):
		sign = '/'

	offset = -1
	while last_indent != '':
		try:
			line = get_line(view, offset)
		except BoundaryError:
			break

		offset -= 1

		match = regex.match(line)
		if match:
			indent = match.group(1)
			part = match.group(3)

			if len(indent) < len(last_indent) and part:
				last_indent = indent
				tree.insert(0, part.rstrip('/'))

	new_tree = []
	path = None
	for part in reversed(tree):
		if part.startswith('@'):
			new_tree.insert(0, part.strip('@'))
			break
		elif part.startswith('/'):
			path = part
			break
		else:
			new_tree.insert(0, part)

	return line_indent, sign, path, tag, '/'.join(new_tree)

# helpers

def replace_line(view, point, text):<commit_msg>allow transversal of / and show errors in transversal<commit_after>import sublime, sublime_plugin
from lib.util import communicate, which

import sys
# reload lib.util on update/reload of primary module
# so improvements will be loaded without a sublime restart
sys.modules['lib.util'] = reload(sys.modules['lib.util'])

import os
import re
import shlex

INDENTATION = '  '

class BoundaryError(Exception): pass

def xiki(view):
	settings = view.settings()

	output = None
	cmd = None
	oldcwd = None
	if settings.get('xiki'):
		indent, sign, path, tag, tree = find_tree(view)
		print 'xiki', sign, path, tree

		pos = get_pos(view)
		if get_line(view, 1).startswith(indent + INDENTATION):
			if sign == '-':
				replace_line(view, pos, indent + '+ ' + tag)

			edit = view.begin_edit()
			cleanup(view, edit, pos, indent + INDENTATION)
			select(view, pos)
			view.end_edit(edit)
			return
		elif sign == '$':
			if path:
				oldcwd = os.getcwd()

				# maybe this should be offloaded into find_tree
				# so path will be multiple directories instead of just a base dir
				path_re = r'^(.+)/%s$' % re.escape(tag)
				match = re.match(path_re, tree)
				if match:
					os.chdir(os.path.join(path, match.group(1)))
				else:
					os.chdir(path)

			cmd = shlex.split(tag.encode('ascii', 'replace'), True)
		elif path:
			# directory listing or file open
			target = os.path.join(path, tree)
			if os.path.isfile(target):
				sublime.active_window().open_file(target)
				return
			elif os.path.isdir(target):
				dirs = ''
				files = ''
				listing = []
				try:
					listing = os.listdir(target)
				except OSError, err:
					dirs = '- ' + err.strerror + '\n'

				for entry in listing:
						absolute = os.path.join(target, entry)
						if os.path.isdir(absolute):
							dirs += '+ %s/\n' % entry
						else:
							files += '%s\n' % entry

				output = (dirs + files) or '\n'
		elif sign == '-':
			# dunno here
			return
		elif tree:
			if which('ruby'):
				cmd = ['ruby', which('xiki')]
			else:
				cmd = ['xiki']

			cmd += tree.split(' ')

		if cmd:
			output = communicate(cmd, None, 3, return_error=True)
			if oldcwd:
				os.chdir(oldcwd)

		if output:
			if sign == '+':
				replace_line(view, pos, indent + '- ' + tag)

			insert(view, output, indent + INDENTATION)

def find_tree(view):
	regex = re.compile(r'^(\s*)([-+$]\s*)?(.*)$')

	view.run_command('single_selection')
	line = get_line(view)
	match = regex.match(line)

	line_indent = last_indent = match.group(1)
	sign = (match.group(2) or '').strip()
	tag = match.group(3)
	tree = [tag]
	if tag.startswith('/'):
		sign = '/'

	offset = -1
	while last_indent != '':
		try:
			line = get_line(view, offset)
		except BoundaryError:
			break

		offset -= 1

		match = regex.match(line)
		if match:
			indent = match.group(1)
			part = match.group(3)

			if len(indent) < len(last_indent) and part:
				last_indent = indent
				tree.insert(0, part)

	new_tree = []
	path = None
	for part in reversed(tree):
		if part.startswith('@'):
			new_tree.insert(0, part.strip('@'))
			break
		elif part.startswith('/'):
			path = part
			break
		else:
			new_tree.insert(0, part)

	return line_indent, sign, path, tag, '/'.join(new_tree).replace('//', '/')

# helpers

def replace_line(view, point, text):
{'fraction_non_alphanumeric': 0.15267295597484276, 'fraction_numerical': 0.004088050314465409, 'mean_word_length': 3.119818652849741, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2777967', 'n_tokens_mistral': 2719, 'n_tokens_neox': 2264, 'n_words': 590}