parent
733dba7274
commit
975b3665d9
|
@ -14,6 +14,7 @@ use strict;
|
|||
use warnings;
|
||||
|
||||
use DBI;
|
||||
use Carp;
|
||||
|
||||
use TBB::ID;
|
||||
|
||||
|
|
327
mode_perl.py
327
mode_perl.py
|
@ -79,8 +79,6 @@ class PerlGrammar(Grammar):
|
|||
PatternRule(name=r'method', pattern=r"(?<=->)[a-zA-Z_][a-zA-Z_0-9]*"),
|
||||
PatternRule(name=r'function', pattern=r"&\$*(?:[a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]*"),
|
||||
PatternRule(name=r'builtin', pattern=r"(?<!->)&?(?:write|warn|wantarray|waitpid|wait|vec|values|utime|use|untie|unshift|unpack|unlink|undef|umask|ucfirst|uc|truncate|times|time|tied|tie|telldir|tell|syswrite|system|sysseek|sysread|sysopen|syscall|symlink|substr|sub|study|stat|srand|sqrt|sprintf|split|splice|sort|socketpair|socket|sleep|sin|shutdown|shmwrite|shmread|shmget|shmctl|shift|setsockopt|setservent|setpwent|setprotoent|setpriority|setpgrp|setnetent|sethostent|setgrent|send|semop|semget|semctl|select|seekdir|seek|scalar|rmdir|rindex|rewinddir|reverse|return|reset|require|rename|ref|redo|recv|readpipe|readlink|readline|readdir|read|rand|quotemeta|push|prototype|printf|print|pos|pop|pipe|package|pack|our|ord|opendir|open|oct|no|next|my|msgsnd|msgrcv|msgget|msgctl|mkdir|map|lstat|log|lock|localtime|local|listen|link|length|lcfirst|lc|last|kill|keys|join|ioctl|int|index|import|hex|grep|goto|gmtime|glob|getsockopt|getsockname|getservent|getservbyport|getservbyname|getpwuid|getpwnam|getpwent|getprotoent|getprotobynumber|getprotobyname|getpriority|getppid|getpgrp|getpeername|getnetent|getnetbyname|getnetbyaddr|getlogin|gethostent|gethostbyname|gethostbyaddr|getgrnam|getgrgid|getgrent|getc|formline|format|fork|flock|fileno|fcntl|exp|exit|exists|exec|eval|eof|endservent|endpwent|endprotoent|endnetent|endhostent|endgrent|each|dump|do|die|delete|defined|dbmopen|dbmclose|crypt|cos|continue|connect|closedir|close|chroot|chr|chown|chop|chomp|chmod|chdir|caller|bless|binmode|bind|atan2|alarm|accept|abs)(?![a-zA-Z0-9_])"),
|
||||
PatternRule(name=r'function', pattern=r"(?:[a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]*(?= *\()"),
|
||||
PatternRule(name=r'class', pattern=r"(?:[a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]*(?=->)"),
|
||||
|
||||
# quote operator
|
||||
RegionRule(name=r'quoted', start=r'q[rqwx]? *\(', grammar=g, end=r'\)'),
|
||||
|
@ -90,6 +88,9 @@ class PerlGrammar(Grammar):
|
|||
RegionRule(name=r'quoted', start=r'q[rqwx]? *(?P<delim>[^ #])', grammar=g, end=r'%(delim)s'),
|
||||
RegionRule(name=r'quoted', start=r'q[rqwx]?#', grammar=g, end=r'#'),
|
||||
|
||||
PatternRule(name=r'function', pattern=r"(?:[a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]*(?= *\()"),
|
||||
PatternRule(name=r'class', pattern=r"(?:[a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]*(?=->)"),
|
||||
|
||||
# nested regions
|
||||
#RegionRule(name=r'paren', start=r'\(', grammar=None, end=r'\)'),
|
||||
#RegionRule(name=r'brace', start=r'{', grammar=None, end=r'}'),
|
||||
|
@ -169,12 +170,13 @@ class Perl(mode2.Fundamental):
|
|||
def __init__(self, w):
|
||||
mode2.Fundamental.__init__(self, w)
|
||||
|
||||
self.add_action_and_bindings(PerlSetLib(), ('C-c l',))
|
||||
self.add_action_and_bindings(PerlCheckSyntax(), ('C-c s',))
|
||||
self.add_action_and_bindings(PerlHashCleanup(), ('C-c h',))
|
||||
#self.add_action_and_bindings(PerlHashCleanup2(), ('C-c h',))
|
||||
self.add_action_and_bindings(PerlViewModulePerldoc(), ('C-c v',))
|
||||
self.add_action_and_bindings(PerlViewWordPerldoc(), ('C-c p',))
|
||||
self.add_action_and_bindings(PerlWrapLine(), ('M-q',))
|
||||
#self.add_action_and_bindings(PerlWrapLine(), ('M-q',))
|
||||
self.add_action_and_bindings(PerlGotoFunction(), ('C-c M-g',))
|
||||
self.add_action_and_bindings(PerlWhichFunction(), ('C-c w',))
|
||||
self.add_action_and_bindings(PerlListFunctions(), ('C-c W',))
|
||||
|
@ -279,6 +281,10 @@ class Perl(mode2.Fundamental):
|
|||
'translate.end': color.build('magenta', 'default'),
|
||||
'translate.null': color.build('magenta', 'default'),
|
||||
}
|
||||
|
||||
# perl-specific
|
||||
self.functions = None
|
||||
self.perllib = 'lib'
|
||||
|
||||
def name(self):
|
||||
return "Perl"
|
||||
|
@ -290,88 +296,36 @@ class Perl(mode2.Fundamental):
|
|||
m = regex.perl_function.match(b.lines[i])
|
||||
if m:
|
||||
self.functions[m.group(1)] = i
|
||||
|
||||
def get_functions(self):
|
||||
if self.functions is None:
|
||||
self.build_function_map()
|
||||
return self.functions
|
||||
|
||||
def get_function_names(self):
|
||||
functions = self.get_functions()
|
||||
pairs = [[functions[key], key] for key in functions]
|
||||
pairs.sort()
|
||||
names = [x[1] for x in pairs]
|
||||
return names
|
||||
|
||||
class PerlWrapLine(method.Method):
|
||||
'''Wrap lines, comments, POD'''
|
||||
margin = 80
|
||||
comment_re = re.compile('^( *)(#+)( *)([^ ].*)$')
|
||||
def _execute(self, w, **vargs):
|
||||
pcursor = w.physical_cursor()
|
||||
r = w.get_region(pcursor)
|
||||
if r is None:
|
||||
return
|
||||
|
||||
t = r[4]
|
||||
if t == 'pod':
|
||||
assert False, 'POD: %s' % repr(r)
|
||||
elif t == 'comment':
|
||||
self._wrap_comment(w)
|
||||
else:
|
||||
return
|
||||
|
||||
def _wrap_comment(self, w):
|
||||
l = w.logical_cursor()
|
||||
m = self.comment_re.match(w.buffer.lines[l.y])
|
||||
if not m:
|
||||
assert False, 'no match oh geez'
|
||||
|
||||
pad = m.group(1) + m.group(2) + m.group(3)
|
||||
data = m.group(4) + ' '
|
||||
|
||||
start = l.y
|
||||
end = l.y + 1
|
||||
|
||||
while end < len(w.buffer.lines):
|
||||
m = self.comment_re.match(w.buffer.lines[end])
|
||||
if m:
|
||||
data += m.group(4) + ' '
|
||||
end += 1
|
||||
else:
|
||||
break
|
||||
|
||||
words = [word for word in data.split() if word]
|
||||
|
||||
lines = [pad]
|
||||
for word in words:
|
||||
if len(lines[-1]) == len(pad):
|
||||
lines[-1] += word
|
||||
elif len(lines[-1]) + 1 + len(word) <= self.margin:
|
||||
lines[-1] += ' ' + word
|
||||
else:
|
||||
lines.append(pad + word)
|
||||
|
||||
# remove the old text and add the new
|
||||
start_p = Point(0, start)
|
||||
end_p = Point(len(w.buffer.lines[end-1]), end-1)
|
||||
w.kill(start_p, end_p)
|
||||
w.insert(start_p, '\n'.join(lines))
|
||||
|
||||
class PerlCheckSyntax(method.Method):
|
||||
'''Check the syntax of a perl file'''
|
||||
class PerlSetLib(method.Method):
|
||||
'''Set the path(s) to find perl modules'''
|
||||
def _args(self):
|
||||
return [method.Argument("lib", type=type(""), prompt="Location of lib: ",
|
||||
default=default.build_constant("."))]
|
||||
def _execute(self, window, **vargs):
|
||||
a = vargs['lib']
|
||||
cmd = "perl -c -I '%s' '%s'" % (a, window.buffer.path)
|
||||
def _execute(self, w, **vargs):
|
||||
w.mode.perllib = vargs['lib']
|
||||
|
||||
class PerlCheckSyntax(method.Method):
|
||||
'''Check the syntax of a perl file'''
|
||||
def _execute(self, w, **vargs):
|
||||
app = w.application
|
||||
cmd = "perl -c -I '%s' '%s'" % (w.mode.perllib, w.buffer.path)
|
||||
(status, output) = commands.getstatusoutput(cmd)
|
||||
if status == 0:
|
||||
window.application.set_error("Syntax OK")
|
||||
window.application.data_buffer("*Perl-Check-Syntax*", output, switch_to=False)
|
||||
app.set_error("Syntax OK")
|
||||
app.data_buffer("*Perl-Check-Syntax*", output, switch_to=False)
|
||||
else:
|
||||
window.application.data_buffer("*Perl-Check-Syntax*", output)
|
||||
app.data_buffer("*Perl-Check-Syntax*", output)
|
||||
|
||||
class PerlViewModulePerldoc(method.Method):
|
||||
'''View documentation about this file using perldoc'''
|
||||
|
@ -382,65 +336,46 @@ class PerlViewModulePerldoc(method.Method):
|
|||
|
||||
class PerlViewWordPerldoc(method.Method):
|
||||
'''View documentation about a package or function using perldoc'''
|
||||
def _try(self, w, word, asfunc=False):
|
||||
if asfunc:
|
||||
cmd = "PERL5LIB=%r perldoc -t -T -f '%s'" % (w.mode.perllib, word)
|
||||
else:
|
||||
cmd = "PERL5LIB=%r perldoc -t -T '%s'" % (w.mode.perllib, word)
|
||||
(status, data) = commands.getstatusoutput(cmd)
|
||||
if status == 0:
|
||||
return data
|
||||
else:
|
||||
return None
|
||||
def _show(self, w, data, word):
|
||||
w.application.data_buffer("*Perldoc*", data, switch_to=True)
|
||||
w.application.set_error('displaying documentation for %r' % word)
|
||||
def _execute(self, w, **vargs):
|
||||
cursor = w.logical_cursor()
|
||||
line = w.buffer.lines[cursor.y]
|
||||
word = w.get_word(wl=string.letters + string.digits + '_:')
|
||||
|
||||
word_chars = string.letters + string.digits + '_:'
|
||||
|
||||
if line[cursor.x] not in word_chars:
|
||||
w.application.set_error('error: no word selected')
|
||||
# make sure that the name is (mostly) valid
|
||||
if word is None:
|
||||
w.application.set_error('no word selected')
|
||||
return
|
||||
|
||||
start = cursor.x
|
||||
while start > 0 and line[start - 1] in word_chars:
|
||||
start -= 1
|
||||
|
||||
end = cursor.x + 1
|
||||
while end < len(line) - 1 and line[end] in word_chars:
|
||||
end += 1
|
||||
|
||||
word = line[start:end]
|
||||
w.application.set_error('the current word is: %r' % word)
|
||||
|
||||
ok = False
|
||||
data = ''
|
||||
|
||||
perl_word_re = re.compile('^[a-zA-Z_][a-zA-Z_0-9]*(?:::[a-zA-Z_][a-zA-Z0-9]*)*$')
|
||||
if not perl_word_re.match(word):
|
||||
elif ':' in word and '::' not in word:
|
||||
w.application.set_error('invalid word: %r' % word)
|
||||
return
|
||||
|
||||
if '::' in word:
|
||||
# we are probably dealing with a package
|
||||
parts = word.split('::')
|
||||
while len(parts) > 0:
|
||||
newword = '::'.join(parts)
|
||||
cmd = "perldoc -t -T '%s'" % newword
|
||||
(status, data) = commands.getstatusoutput(cmd)
|
||||
if status == 0:
|
||||
word = newword
|
||||
ok = True
|
||||
break
|
||||
parts.pop(-1)
|
||||
elif ':' in word:
|
||||
w.application.set_error('invalid word2222: %r' % word)
|
||||
return
|
||||
else:
|
||||
cmd = "perldoc -t -T -f '%s'" % word
|
||||
(status, data) = commands.getstatusoutput(cmd)
|
||||
if status == 0:
|
||||
ok = True
|
||||
else:
|
||||
cmd = "perldoc -t -T -f '%s'" % word
|
||||
(status, data) = commands.getstatusoutput(cmd)
|
||||
ok = status == 0
|
||||
# first try it is a package
|
||||
parts = word.split('::')
|
||||
while len(parts) > 0:
|
||||
newword = '::'.join(parts)
|
||||
data = self._try(w, newword, asfunc=False)
|
||||
if data:
|
||||
self._show(w, data, newword)
|
||||
return
|
||||
parts.pop(-1)
|
||||
|
||||
if not ok:
|
||||
w.application.set_error('nothing found for %r' % word)
|
||||
# then try it as a function
|
||||
data = self._try(w, word, asfunc=True)
|
||||
if data:
|
||||
self._show(w, data, parts[0])
|
||||
else:
|
||||
w.application.data_buffer("*Perldoc*", data, switch_to=True)
|
||||
w.application.set_error('displaying documentation for %r' % word)
|
||||
w.application.set_error('nothing found for %r' % word)
|
||||
|
||||
class PerlGotoFunction(method.Method):
|
||||
'''Jump to a function defined in this module'''
|
||||
|
@ -557,103 +492,57 @@ class PerlHashCleanup(method.Method):
|
|||
window.kill(start_p, end_p)
|
||||
window.insert_string(start_p, data)
|
||||
|
||||
class PerlHashCleanup2(method.Method):
|
||||
'''Correctly align assignment blocks and literal hashes'''
|
||||
def process_line2(self, line_regions, sep=None, indent=None):
|
||||
(pre_toks, sep_tok, post_toks) = ([], None, [])
|
||||
ok = False
|
||||
before = True
|
||||
for r in line_regions:
|
||||
(start, end, attr, s, name) = r
|
||||
if name == "":
|
||||
continue
|
||||
elif before:
|
||||
if len(pre_toks) == 0:
|
||||
pre_toks.append(r)
|
||||
elif (name == "delimiter" and s == sep or
|
||||
(sep is None and (s == "=" or s == "=>"))):
|
||||
sep_tok = r
|
||||
before = False
|
||||
else:
|
||||
pre_toks.append(r)
|
||||
else:
|
||||
post_toks.append(r)
|
||||
ok = True
|
||||
|
||||
if ok:
|
||||
return (True, sep_tok[3], (pre_toks, sep_tok, post_toks))
|
||||
else:
|
||||
return (False, "", ([], None, []))
|
||||
|
||||
def _execute(self, w, **vargs):
|
||||
cursor = w.logical_cursor()
|
||||
b = w.buffer
|
||||
|
||||
# so this is where we will store the groups that we find
|
||||
groups_by_line = {}
|
||||
|
||||
all_regions = w.mode.get_regions()
|
||||
line_regions = all_regions[cursor.y]
|
||||
(ok, sep, group) = self.process_line2(line_regions)
|
||||
|
||||
if not ok:
|
||||
raise Exception, "Not a perl hash line"
|
||||
groups_by_line[cursor.y] = group
|
||||
|
||||
# find the beginning of this hash block
|
||||
start = cursor.y
|
||||
while start >= 0:
|
||||
(ok2, sep2, group2) = self.process_line2(all_regions[start - 1], sep)
|
||||
if not ok2:
|
||||
break
|
||||
start -= 1
|
||||
groups_by_line[start] = group2
|
||||
|
||||
# find the end of this hash block
|
||||
end = cursor.y
|
||||
while end < len(b.lines) - 1:
|
||||
(ok2, sep2, group2) = self.process_line2(all_regions[end + 1], sep)
|
||||
if not ok2:
|
||||
break
|
||||
end += 1
|
||||
groups_by_line[end] = group2
|
||||
|
||||
# find the minimum indented line
|
||||
indent_w = None
|
||||
for k in groups_by_line:
|
||||
x = groups_by_line[k][0][0].start
|
||||
if indent_w is None or x < indent_w:
|
||||
indent_w = x
|
||||
|
||||
# find the max key length
|
||||
key_w = None
|
||||
for k in groups_by_line:
|
||||
x = groups_by_line[k][0][-1].end - groups_by_line[k][0][0].start
|
||||
if key_w is None or x > key_w:
|
||||
key_w = x
|
||||
|
||||
# for each line, format it correctly
|
||||
keys = groups_by_line.keys()
|
||||
keys.sort()
|
||||
data = ''
|
||||
for i in keys:
|
||||
line = ' ' * indent_w
|
||||
l = groups_by_line[i][0][0].start
|
||||
for t in groups_by_line[i][0]:
|
||||
line += ' ' * max(0, t.start - l)
|
||||
line += t.value
|
||||
l = t.end
|
||||
line += ' ' * max(0, key_w - l + groups_by_line[i][0][0].start)
|
||||
line += ' ' + groups_by_line[i][1].value + ' '
|
||||
l = groups_by_line[i][2][0].start
|
||||
for t in groups_by_line[i][2]:
|
||||
line += ' ' * max(0, t.start - l)
|
||||
line += t.value
|
||||
l = t.end
|
||||
data += line + '\n'
|
||||
|
||||
# remove the old text and add the new
|
||||
start_p = Point(0, start)
|
||||
end_p = Point(0, end + 1)
|
||||
w.kill(start_p, end_p)
|
||||
w.insert(start_p, data)
|
||||
#class PerlWrapLine(method.Method):
|
||||
# '''Wrap lines, comments, POD'''
|
||||
# margin = 80
|
||||
# comment_re = re.compile('^( *)(#+)( *)([^ ].*)$')
|
||||
# def _execute(self, w, **vargs):
|
||||
# pcursor = w.physical_cursor()
|
||||
# r = w.get_region(pcursor)
|
||||
# if r is None:
|
||||
# return
|
||||
#
|
||||
# t = r[4]
|
||||
# if t == 'pod':
|
||||
# assert False, 'POD: %s' % repr(r)
|
||||
# elif t == 'comment':
|
||||
# self._wrap_comment(w)
|
||||
# else:
|
||||
# return
|
||||
#
|
||||
# def _wrap_comment(self, w):
|
||||
# l = w.logical_cursor()
|
||||
# m = self.comment_re.match(w.buffer.lines[l.y])
|
||||
# if not m:
|
||||
# assert False, 'no match oh geez'
|
||||
#
|
||||
# pad = m.group(1) + m.group(2) + m.group(3)
|
||||
# data = m.group(4) + ' '
|
||||
#
|
||||
# start = l.y
|
||||
# end = l.y + 1
|
||||
#
|
||||
# while end < len(w.buffer.lines):
|
||||
# m = self.comment_re.match(w.buffer.lines[end])
|
||||
# if m:
|
||||
# data += m.group(4) + ' '
|
||||
# end += 1
|
||||
# else:
|
||||
# break
|
||||
#
|
||||
# words = [word for word in data.split() if word]
|
||||
#
|
||||
# lines = [pad]
|
||||
# for word in words:
|
||||
# if len(lines[-1]) == len(pad):
|
||||
# lines[-1] += word
|
||||
# elif len(lines[-1]) + 1 + len(word) <= self.margin:
|
||||
# lines[-1] += ' ' + word
|
||||
# else:
|
||||
# lines.append(pad + word)
|
||||
#
|
||||
# # remove the old text and add the new
|
||||
# start_p = Point(0, start)
|
||||
# end_p = Point(len(w.buffer.lines[end-1]), end-1)
|
||||
# w.kill(start_p, end_p)
|
||||
# w.insert(start_p, '\n'.join(lines))
|
||||
|
|
138
mode_python.py
138
mode_python.py
|
@ -120,8 +120,142 @@ class PythonGrammar(Grammar):
|
|||
),
|
||||
]
|
||||
|
||||
class PythonTabber(tab2.StackTabber):
|
||||
pass
|
||||
class PythonTabber(tab2.Tabber):
|
||||
start_tags = {'(': ')',
|
||||
'{': '}',
|
||||
'[': ']'}
|
||||
|
||||
close_tags = {')': '(',
|
||||
'}': '{',
|
||||
']': '['}
|
||||
|
||||
def __init__(self, m):
|
||||
tab2.Tabber.__init__(self, m)
|
||||
|
||||
|
||||
|
||||
def stack_append(self, item):
|
||||
self.tab_stack.append(item)
|
||||
def stack_pop(self):
|
||||
self.tab_stack.pop(-1)
|
||||
|
||||
def base_indentation_level(self, y):
|
||||
return y == 0
|
||||
|
||||
def calculate_tabs(self, start=0, goal=None):
|
||||
lines = self.mode.window.buffer.lines
|
||||
tokens = self.mode.highlighter.tokens
|
||||
buffer = self.mode.window.buffer
|
||||
|
||||
if self.levels is None:
|
||||
self.levels = [None] * (len(lines))
|
||||
|
||||
self.index = 0
|
||||
self.y = start
|
||||
self.base = 0
|
||||
self.tab_stack = []
|
||||
|
||||
# we want to process every logical line in the file
|
||||
while self.y < len(lines):
|
||||
line = lines[self.y]
|
||||
start_index = self.index
|
||||
|
||||
start_point = point.Point(0, self.y)
|
||||
start_offset = buffer.get_point_offset(start_point)
|
||||
end_point = point.Point(len(line), self.y)
|
||||
end_offset = buffer.get_point_offset(end_point)
|
||||
|
||||
# we want to find all the tokens on the line we are currently processing
|
||||
while self.index < len(tokens):
|
||||
token = tokens[self.index]
|
||||
if token.end > end_offset:
|
||||
break
|
||||
self.index += 1
|
||||
|
||||
self.handle_line(line,
|
||||
start_offset, start_index,
|
||||
end_offset, self.index)
|
||||
|
||||
self.levels[self.y] = self.line_depth
|
||||
self.y += 1
|
||||
if goal is not None and self.y > goal:
|
||||
break
|
||||
|
||||
def get_line_depth(self):
|
||||
if len(self.tab_stack) > 0:
|
||||
return self.tab_stack[-1][1]
|
||||
else:
|
||||
return self.base
|
||||
|
||||
def handle_line(self, line, start_offset, start_index, end_offset, end_index):
|
||||
self.line_depth = self.get_line_depth()
|
||||
tokens = self.mode.highlighter.tokens
|
||||
|
||||
if start_index >= len(tokens):
|
||||
return
|
||||
if regex.whitespace.match(line):
|
||||
return
|
||||
|
||||
if len(self.tab_stack) == 0 and tokens[start_index].start >= start_offset:
|
||||
self.base = util.count_leading_whitespace(line)
|
||||
|
||||
for i in range(start_index, end_index):
|
||||
token = tokens[i]
|
||||
s = token.string
|
||||
if s in self.start_tags:
|
||||
if i < end_index - 1:
|
||||
i = tokens[i+1].start - start_offset
|
||||
elif len(self.tab_stack) > 0:
|
||||
i = self.tab_stack[-1][1] + 4
|
||||
else:
|
||||
i = self.base + 4
|
||||
self.stack_append((s, i))
|
||||
elif s in self.close_tags:
|
||||
assert len(self.tab_stack), "Unbalanced closing tag"
|
||||
assert self.tab_stack[-1][0] == self.close_tags[s], "Unmatched closing tag"
|
||||
self.stack_pop()
|
||||
if i == start_index:
|
||||
self.line_depth = self.get_line_depth()
|
||||
|
||||
if tokens[start_index].start < start_offset:
|
||||
self.line_depth = -1
|
||||
|
||||
prebase = self.base
|
||||
s = tokens[start_index].string
|
||||
e = tokens[end_index-1].string
|
||||
|
||||
if s == "except" or s == "elif" or s == "else":
|
||||
if self.y > 0 and self.line_depth == self.levels[self.y - 1]:
|
||||
self.line_depth = max(0, self.line_depth - 4)
|
||||
elif (s == "return" or s == "raise" or s == "yield" or s == "break" or
|
||||
s == "pass" or s == 'continue'):
|
||||
self.base = max(0, self.base - 4)
|
||||
|
||||
if e == "\\":
|
||||
if len(self.tab_stack) and self.tab_stack[-1][0] == "\\":
|
||||
pass
|
||||
else:
|
||||
self.stack_append(("\\", prebase + 4))
|
||||
return
|
||||
elif e == ":":
|
||||
self.base += 4
|
||||
elif len(self.tab_stack) and self.tab_stack[-1][0] == "\\":
|
||||
self.stack_pop()
|
||||
|
||||
def get_indentation_level(self, y):
|
||||
if self.levels is not None and self.levels[y] is not None:
|
||||
result = self.levels[y]
|
||||
else:
|
||||
i = max(0, y - 1)
|
||||
while i > 0:
|
||||
if self.base_indentation_level(i):
|
||||
break
|
||||
i -= 1
|
||||
self.calculate_tabs(i, y)
|
||||
result = self.levels[y]
|
||||
if result == -1:
|
||||
return None
|
||||
return result
|
||||
|
||||
class Python(mode2.Fundamental):
|
||||
tabbercls = PythonTabber
|
||||
|
|
36
window2.py
36
window2.py
|
@ -2,7 +2,8 @@ import os.path, string
|
|||
import regex
|
||||
from point2 import Point
|
||||
|
||||
WORD_LETTERS = list(string.letters + string.digits)
|
||||
#WORD_LETTERS = list(string.letters + string.digits)
|
||||
WORD_LETTERS = string.letters + string.digits + "_"
|
||||
|
||||
# note about the cursor: the cursor position will insert in front of the
|
||||
# character it highlights. to this end, it needs to be able to highlight behind
|
||||
|
@ -294,26 +295,27 @@ class Window(object):
|
|||
p = self.find_right_word()
|
||||
if p is not None:
|
||||
self.goto(p)
|
||||
def get_word_bounds_at_point(self, p):
|
||||
def get_word_bounds_at_point(self, p, wl=WORD_LETTERS):
|
||||
if len(self.buffer.lines[p.y]) == 0:
|
||||
return
|
||||
elif p.x == 0:
|
||||
p1 = self.find_left_word(Point(p.x + 1, p.y))
|
||||
p2 = self.find_right_word()
|
||||
else:
|
||||
p1 = self.find_left_word()
|
||||
p2 = self.find_right_word(Point(p.x - 1, p.y))
|
||||
return (p1, p2)
|
||||
def get_word_at_point(self, p):
|
||||
bounds = self.get_word_bounds_at_point(p)
|
||||
return None
|
||||
elif self.cursor_char() not in wl:
|
||||
return None
|
||||
x1 = x2 = p.x
|
||||
while x1 > 0 and self.xy_char(x1 - 1, p.y) in wl:
|
||||
x1 -= 1
|
||||
while x2 < len(self.buffer.lines[p.y]) and self.xy_char(x2, p.y) in wl:
|
||||
x2 += 1
|
||||
return (Point(x1, p.y), Point(x2, p.y))
|
||||
def get_word_at_point(self, p, wl=WORD_LETTERS):
|
||||
bounds = self.get_word_bounds_at_point(p, wl)
|
||||
if bounds is None:
|
||||
return None
|
||||
else:
|
||||
return self.buffer.get_substring(bounds[0], bounds[1])
|
||||
def get_word_bounds(self):
|
||||
return self.get_word_bounds_at_point(self.logical_cursor())
|
||||
def get_word(self):
|
||||
return self.get_word_at_point(self.logical_cursor())
|
||||
def get_word_bounds(self, wl=WORD_LETTERS):
|
||||
return self.get_word_bounds_at_point(self.logical_cursor(), wl)
|
||||
def get_word(self, wl=WORD_LETTERS):
|
||||
return self.get_word_at_point(self.logical_cursor(), wl)
|
||||
|
||||
# page up/down
|
||||
def _pshift_up(self, p, num):
|
||||
|
@ -496,7 +498,7 @@ class Window(object):
|
|||
|
||||
# querying
|
||||
def cursor_char(self):
|
||||
self.point_char(self.logical_cursor())
|
||||
return self.point_char(self.logical_cursor())
|
||||
def point_char(self, p):
|
||||
return self.xy_char(p.x, p.y)
|
||||
def xy_char(self, x, y):
|
||||
|
|
Loading…
Reference in New Issue