pmacs3/method/numbers.py

89 lines
2.4 KiB
Python

import re
import buffer, default, dirutil, regex, util, window
from point import Point
from method import Method, Argument
num_re = re.compile(r'(?:-?[1-9][0-9]*|0[xX][0-9A-Fa-f]+|0[0-7]+|0)')
def find_next_number(w, offset=0):
b = w.buffer
x, y = w.logical_cursor().xy()
x += offset
while y < len(b.lines):
m = num_re.search(b.lines[y], x)
if m:
if m.group(0).lower().startswith('0x'):
base = 16
elif m.group(0).startswith('0'):
base = 8
else:
base = 10
return (Point(m.start(), y), Point(m.end(), y), base)
x = 0
y += 1
return (None, None, None)
def find_prev_number(w, offset=0):
b = w.buffer
x, y = w.logical_cursor().xy()
x += offset
while y >= 0:
m = m2 = num_re.search(b.lines[y], 0, x)
while m2:
m = m2
m2 = num_re.search(b.lines[y], m2.end(), x)
if m:
return (Point(m.start(), y), Point(m.end(), y))
y -= 1
x = len(b.lines[y])
return (None, None)
def get_converter(s):
if s.startswith('0x') or s.startswith('0X'):
return lambda x: '0x%02x' % x
elif s.startswith('0') and len(s) > 1:
return oct
else:
return str
class GotoPrevNumber(Method):
def _execute(self, w, **vargs):
(p1, p2) = find_prev_number(w, -1)
if p1 is not None:
w.goto(p1)
class GotoNextNumber(Method):
def _execute(self, w, **vargs):
(p1, p2, base) = find_next_number(w, 1)
if p1 is not None:
w.goto(p2.add(-1, 0))
class Increment(Method):
'''Increment the next number'''
def _execute(self, w, **vargs):
(p1, p2, base) = find_next_number(w)
if p1 is None:
return
s = w.buffer.lines[p1.y][p1.x:p2.x]
num = int(s, base)
conv = get_converter(s)
w.set_error('found %r' % num)
w.delete(p1, p2)
s2 = conv(num + 1)
w.insert_string(p1, s2)
w.goto(p1)
class Decrement(Method):
'''Decrement the next number'''
def _execute(self, w, **vargs):
(p1, p2, base) = find_next_number(w)
if p1 is None:
return
s = w.buffer.lines[p1.y][p1.x:p2.x]
num = int(s, base)
conv = get_converter(s)
w.set_error('found %r' % num)
w.delete(p1, p2)
s2 = conv(num - 1)
w.insert_string(p1, s2)
w.goto(p1)