parent
d769305721
commit
bb2716a532
323
application.py
323
application.py
|
@ -1,9 +1,10 @@
|
|||
#!/usr/bin/env python
|
||||
import curses, curses.ascii, getpass, os, re, string, sys, termios, time
|
||||
import curses, curses.ascii, getpass, os, re, string, sets, sys, termios, time
|
||||
import traceback
|
||||
|
||||
import buffer, bufferlist, color, completer, keyinput, method, minibuffer
|
||||
import mode, point, sets, util, window
|
||||
import buffer2, bufferlist, color, completer, keyinput, method, minibuffer
|
||||
import mode2, util, window2
|
||||
from point2 import Point
|
||||
|
||||
# modes
|
||||
import mode, mode_c, mode_mini, mode_python, mode_nasm, mode_perl, mode_search
|
||||
|
@ -75,61 +76,62 @@ class Application:
|
|||
self.set_error("Dynamic color not available")
|
||||
|
||||
# initialize our modes
|
||||
self.modes = {
|
||||
'blame': mode_blame.Blame,
|
||||
'c': mode_c.C,
|
||||
'console': mode_console.Console,
|
||||
'diff': mode_diff.Diff,
|
||||
'fundamental': mode.Fundamental,
|
||||
'mini': mode_mini.Mini,
|
||||
'nasm': mode_nasm.Nasm,
|
||||
'perl': mode_perl.Perl,
|
||||
'python': mode_python.Python,
|
||||
'replace': mode_replace.Replace,
|
||||
'search': mode_search.Search,
|
||||
'sh': mode_sh.Sh,
|
||||
'text': mode_text.Text,
|
||||
'which': mode_which.Which,
|
||||
'xml': mode_xml.XML,
|
||||
'mutt': mode_mutt.Mutt,
|
||||
'sql': mode_sql.Sql,
|
||||
'javascript': mode_javascript.Javascript,
|
||||
'template': mode_tt.Template,
|
||||
}
|
||||
self.modes = {'fundamental': mode2.Fundamental}
|
||||
# self.modes = {
|
||||
# 'blame': mode_blame.Blame,
|
||||
# 'c': mode_c.C,
|
||||
# 'console': mode_console.Console,
|
||||
# 'diff': mode_diff.Diff,
|
||||
# 'fundamental': mode.Fundamental,
|
||||
# 'mini': mode_mini.Mini,
|
||||
# 'nasm': mode_nasm.Nasm,
|
||||
# 'perl': mode_perl.Perl,
|
||||
# 'python': mode_python.Python,
|
||||
# 'replace': mode_replace.Replace,
|
||||
# 'search': mode_search.Search,
|
||||
# 'sh': mode_sh.Sh,
|
||||
# 'text': mode_text.Text,
|
||||
# 'which': mode_which.Which,
|
||||
# 'xml': mode_xml.XML,
|
||||
# 'mutt': mode_mutt.Mutt,
|
||||
# 'sql': mode_sql.Sql,
|
||||
# 'javascript': mode_javascript.Javascript,
|
||||
# 'template': mode_tt.Template,
|
||||
# }
|
||||
|
||||
# these are used in this order to determine which mode to open certain
|
||||
# kinds of files
|
||||
self.mode_paths = {
|
||||
'/etc/profile': 'sh',
|
||||
#'/etc/profile': 'sh',
|
||||
}
|
||||
self.mode_basenames = {
|
||||
'.bashrc': 'sh',
|
||||
'.bash_profile': 'sh',
|
||||
'.profile': 'sh',
|
||||
#'.bashrc': 'sh',
|
||||
#'.bash_profile': 'sh',
|
||||
#'.profile': 'sh',
|
||||
}
|
||||
self.mode_extensions = {
|
||||
'.py': 'python',
|
||||
'.pl': 'perl',
|
||||
'.pm': 'perl',
|
||||
'.t': 'perl',
|
||||
'.c': 'c',
|
||||
'.txt': 'text',
|
||||
'.s': 'nasm',
|
||||
'.sh': 'sh',
|
||||
'.bash': 'sh',
|
||||
'.xml': 'xml',
|
||||
'.xml.in': 'xml',
|
||||
'.html': 'xml',
|
||||
'.htm': 'xml',
|
||||
'.sql': 'sql',
|
||||
'.js': 'javascript',
|
||||
'.tt': 'template'
|
||||
# '.py': 'python',
|
||||
# '.pl': 'perl',
|
||||
# '.pm': 'perl',
|
||||
# '.t': 'perl',
|
||||
# '.c': 'c',
|
||||
# '.txt': 'text',
|
||||
# '.s': 'nasm',
|
||||
# '.sh': 'sh',
|
||||
# '.bash': 'sh',
|
||||
# '.xml': 'xml',
|
||||
# '.xml.in': 'xml',
|
||||
# '.html': 'xml',
|
||||
# '.htm': 'xml',
|
||||
# '.sql': 'sql',
|
||||
# '.js': 'javascript',
|
||||
# '.tt': 'template'
|
||||
}
|
||||
self.mode_detection = {
|
||||
'python': 'python',
|
||||
'perl': 'perl',
|
||||
'sh': 'sh',
|
||||
'bash': 'sh',
|
||||
# 'python': 'python',
|
||||
# 'perl': 'perl',
|
||||
# 'sh': 'sh',
|
||||
# 'bash': 'sh',
|
||||
}
|
||||
|
||||
# initialize our methods
|
||||
|
@ -153,17 +155,17 @@ class Application:
|
|||
|
||||
# initialize our buffers
|
||||
# note that the first buffer in buffers will be initially visible
|
||||
buffers.append(buffer.ScratchBuffer())
|
||||
buffers.append(buffer.ConsoleBuffer())
|
||||
buffers.append(buffer2.ScratchBuffer())
|
||||
buffers.append(buffer2.ConsoleBuffer())
|
||||
self.bufferlist = bufferlist.BufferList(height, width)
|
||||
self.active_slot = 0
|
||||
self.resize_slots()
|
||||
|
||||
# build windows for our buffers
|
||||
for b in buffers:
|
||||
window.Window(b, self, height, width, slot=self.active_slot,
|
||||
mode_name=init_mode)
|
||||
window2.Window(b, self, height, width, mode_name=init_mode)
|
||||
self.bufferlist.add_buffer(b)
|
||||
self.bufferlist.set_slot(0, buffers[0])
|
||||
self.resize_windows()
|
||||
|
||||
# see if the user has requested that we go to a particular line
|
||||
|
@ -203,21 +205,17 @@ class Application:
|
|||
return locals()
|
||||
|
||||
def add_slot(self):
|
||||
# XYZ
|
||||
b = self.bufferlist.slots[self.active_slot].buffer
|
||||
n = self.bufferlist.add_slot(0, 0, 0, b)
|
||||
self.resize_slots()
|
||||
self.add_window_to_buffer(b, n)
|
||||
self.resize_windows()
|
||||
def remove_slot(self, slotname):
|
||||
n = self.bufferlist.add_slot()
|
||||
self.bufferlist.set_slot(n, b)
|
||||
def remove_slot(self, n):
|
||||
assert len(self.bufferlist.slots) > 1, "oh no you didn't!"
|
||||
assert slotname >= 0 and slotname < len(self.bufferlist.slots), \
|
||||
"invalid slot: %r (%r)" % (slotname, len(self.bufferlist.slots))
|
||||
b = self.bufferlist.slots[slotname].buffer
|
||||
self.bufferlist.remove_slot(slotname)
|
||||
assert n >= 0 and n < len(self.bufferlist.slots), \
|
||||
"invalid slot: %r (%r)" % (n, len(self.bufferlist.slots))
|
||||
self.bufferlist.remove_slot(n)
|
||||
if self.active_slot > slotname:
|
||||
self.active_slot = max(0, self.active_slot - 1)
|
||||
self.resize_slots()
|
||||
self.resize_windows()
|
||||
def single_slot(self):
|
||||
while len(self.bufferlist.slots) > 1:
|
||||
if self.active_slot == 0:
|
||||
|
@ -225,10 +223,10 @@ class Application:
|
|||
else:
|
||||
self.remove_slot(0)
|
||||
|
||||
def get_window_height_width(self, slotname):
|
||||
assert slotname >= 0 and slotname < len(self.bufferlist.slots), \
|
||||
def get_window_height_width(self, i):
|
||||
assert i >= 0 and i < len(self.bufferlist.slots), \
|
||||
"invalid slot: %r" % slotname
|
||||
slot = self.bufferlist.slots[slotname]
|
||||
slot = self.bufferlist.slots[i]
|
||||
return (slot.height, slot.width)
|
||||
|
||||
# mini buffer handling
|
||||
|
@ -243,7 +241,7 @@ class Application:
|
|||
self.mini_prompt = prompt
|
||||
self.mini_buffer = minibuffer.MiniBuffer(callback, method, tabber,
|
||||
modename)
|
||||
window.Window(self.mini_buffer, self, height=1,
|
||||
window2.Window(self.mini_buffer, self, height=1,
|
||||
width=self.x-1-len(self.mini_prompt)-1, slot='mini')
|
||||
self.mini_active = True
|
||||
def exec_mini_buffer(self):
|
||||
|
@ -273,8 +271,8 @@ class Application:
|
|||
else:
|
||||
assert 0 <= self.active_slot and self.active_slot < len(self.bufferlist.slots), \
|
||||
"0 <= %d < %d" % (self.active_slot, len(self.bufferlist.slots))
|
||||
slotname = self.active_slot
|
||||
return self.bufferlist.slots[slotname].buffer.get_window(slotname)
|
||||
i = self.active_slot
|
||||
return self.bufferlist.slots[i].window
|
||||
|
||||
# buffer handling
|
||||
def file_buffer(self, path, data, switch_to=True):
|
||||
|
@ -283,7 +281,7 @@ class Application:
|
|||
f = open(path, 'w')
|
||||
f.write(data)
|
||||
f.close()
|
||||
b = buffer.FileBuffer(path)
|
||||
b = buffer2.FileBuffer(path)
|
||||
b.open()
|
||||
self.add_window_to_buffer(b, self.active_slot)
|
||||
self.add_buffer(b)
|
||||
|
@ -293,7 +291,7 @@ class Application:
|
|||
if self.has_buffer_name(name):
|
||||
b = self.bufferlist.buffer_names[name]
|
||||
self.remove_buffer(b)
|
||||
b = buffer.DataBuffer(name, data)
|
||||
b = buffer2.DataBuffer(name, data)
|
||||
if modename is not None:
|
||||
b.modename = modename
|
||||
self.add_window_to_buffer(b, self.active_slot)
|
||||
|
@ -328,7 +326,7 @@ class Application:
|
|||
def add_window_to_buffer(self, b, slotname):
|
||||
if not b.has_window(slotname):
|
||||
slot = self.bufferlist.slots[slotname]
|
||||
window.Window(b, self, height=slot.height, width=slot.width, slot=slotname)
|
||||
window2.Window(b, self, height=slot.height, width=slot.width)
|
||||
|
||||
# error string handling
|
||||
def set_error(self, s):
|
||||
|
@ -355,16 +353,16 @@ class Application:
|
|||
y_offset += y + 1
|
||||
slot = self.bufferlist.slots[n-1].resize(y_pool, x, y_offset)
|
||||
def resize_windows(self):
|
||||
for b in self.bufferlist.buffers:
|
||||
keys = b.windows.keys()
|
||||
for name in keys:
|
||||
try:
|
||||
(height, width) = self.get_window_height_width(name)
|
||||
b.windows[name].set_size(width, height)
|
||||
except:
|
||||
w = b.windows[name]
|
||||
del b.windows[name]
|
||||
# kill w now
|
||||
#for slot in
|
||||
pass
|
||||
# for b in self.bufferlist.buffers:
|
||||
# keys = b.windows.keys()
|
||||
# for w in b.windows:
|
||||
# try:
|
||||
# (height, width) = self.get_window_height_width(name)
|
||||
# b.windows[name].set_size(width, height)
|
||||
# except:
|
||||
# b.windows.remove(w)
|
||||
|
||||
# hide the curses cursor
|
||||
def hide_cursor(self):
|
||||
|
@ -398,12 +396,12 @@ class Application:
|
|||
# undo/redo
|
||||
def undo(self):
|
||||
try:
|
||||
self.window().buffer.undo()
|
||||
self.window().undo()
|
||||
except Exception, e:
|
||||
self.set_error("%s" % (e))
|
||||
def redo(self):
|
||||
try:
|
||||
self.window().buffer.redo()
|
||||
self.window().redo()
|
||||
except Exception, e:
|
||||
self.set_error("%s" % (e))
|
||||
|
||||
|
@ -503,101 +501,38 @@ class Application:
|
|||
self.draw_slot(i)
|
||||
self.draw_status_bar(i)
|
||||
|
||||
def draw_slot(self, slotname):
|
||||
slot = self.bufferlist.slots[slotname]
|
||||
if not slot.buffer.has_window(slotname):
|
||||
def draw_slot(self, i):
|
||||
#return
|
||||
slot = self.bufferlist.slots[i]
|
||||
if slot.window is None:
|
||||
return
|
||||
w = slot.buffer.get_window(slotname)
|
||||
lines = w.visible_lines()
|
||||
regions = w.mode.visible_regions()
|
||||
## FIXME: why isn't this always the same????
|
||||
assert (len(lines) == len(regions) or
|
||||
len(lines) == len(regions) - 1), "%d,%d" % (len(lines),
|
||||
len(regions)-1)
|
||||
assert len(lines) > 0, "no lines... why?"
|
||||
m = min(len(lines), slot.height)
|
||||
assert m > 0
|
||||
x = slot.width
|
||||
y = slot.height
|
||||
y_offset = slot.offset
|
||||
w = slot.window
|
||||
|
||||
assert x > 0
|
||||
assert y > 0
|
||||
red_attr = color.build_attr(color.pairs('red', 'default'))
|
||||
for i in range(0, m):
|
||||
j = 0
|
||||
line = lines[i]
|
||||
for r in regions[i]:
|
||||
try:
|
||||
# start, end, attr, value, ttype = r
|
||||
assert 0 <= r.start, "0 <= %d" % (r.start)
|
||||
assert r.start <= r.end, "%d <= %d" % (r.start, r.end)
|
||||
assert r.end <= len(line), "%d <= %d" % (r.end, len(line))
|
||||
except Exception, e:
|
||||
s = "\n".join([repr(x) for x in regions])
|
||||
raise Exception, "%s\n%s\n\n%s\n\n%s\n\n%s\n\n%d" % \
|
||||
(e, s, regions[i], r, repr(line), len(line))
|
||||
assert line[r.start:r.end] == r.value, \
|
||||
"%r != %r" % (line[r.start:r.end], r.value)
|
||||
try:
|
||||
if DARK_BACKGROUND:
|
||||
attr = r.attr | curses.A_BOLD
|
||||
else:
|
||||
attr = r.attr
|
||||
self.win.addnstr(i + y_offset, r.start, r.value, r.end - r.start, attr)
|
||||
except Exception, e:
|
||||
raise Exception, "%s\n%s %s %s %s" % \
|
||||
(e, repr(i), repr(r.start), repr(r.value), repr(r.end - r.start))
|
||||
j = r.end
|
||||
if j < len(line):
|
||||
# this is cheating... FIXME
|
||||
self.win.addnstr(i + y_offset, j, line[j:], len(line) - j)
|
||||
j += len(line) - j
|
||||
if j < x:
|
||||
self.win.addnstr(i + y_offset, j, ' ' * (x-j), (x-j))
|
||||
if w.continued_visible_line(i):
|
||||
self.win.addch(i + y_offset, x, '\\', red_attr)
|
||||
lines = w.buffer.lines
|
||||
count = 0
|
||||
(x, y) = w.first.xy()
|
||||
cursor = w.logical_cursor()
|
||||
(cx, cy) = cursor.xy()
|
||||
(px, py) = (None, None)
|
||||
while count < slot.height:
|
||||
if y >= len(lines):
|
||||
self.win.addstr(count, 0, '~' + ' ' * (slot.width - 1))
|
||||
else:
|
||||
self.win.addch(i + y_offset, x, ' ')
|
||||
if cy == y and cx >= x and cx < x + slot.width:
|
||||
px = cx - x
|
||||
py = count
|
||||
line = lines[y]
|
||||
subline = line[x:x + slot.width]
|
||||
if len(subline) < slot.width:
|
||||
subline += ' ' * (slot.width - len(subline))
|
||||
self.win.addstr(slot.offset + count, 0, line[x:x + slot.width])
|
||||
|
||||
for i in range(m, y):
|
||||
self.win.addnstr(i + y_offset, 0, '~' + ' ' * (x), x + 1, red_attr)
|
||||
|
||||
for (high_w, lp1, lp2) in self.highlighted_ranges:
|
||||
if lp1.y != lp2.y:
|
||||
# this region is incoherent, so skip it, or die, whatever
|
||||
#raise Exception, "haddock %d != %d" % (lp1.y, lp2.y)
|
||||
pass
|
||||
elif w is not high_w:
|
||||
# this region isn't in the current window so skip it
|
||||
pass
|
||||
else:
|
||||
(pp1, pp2) = (w.physical_point(lp1), w.physical_point(lp2))
|
||||
vo = w.visible_offset()
|
||||
(vp1, vp2) = (pp1.offset(0, -vo), pp2.offset(0, -vo))
|
||||
if vp2.y < 0 or vp1.y > w.height:
|
||||
# this region is not visible, so skip it
|
||||
pass
|
||||
if x + slot.width >= len(line):
|
||||
x = 0
|
||||
y += 1
|
||||
else:
|
||||
# first let's fix our points so we're sure they're visible
|
||||
if vp1.y < 0:
|
||||
vp1 = point.Point(0,0)
|
||||
if vp2.y > w.height:
|
||||
vp2 = point.Point(len(lines[-1]), w.height-1)
|
||||
|
||||
if vp1.y == vp2.y:
|
||||
# our region physically fits on one line; this is easy
|
||||
b = lines[vp1.y][vp1.x:vp2.x]
|
||||
self.win.addstr(vp1.y + y_offset, vp1.x, b, curses.A_REVERSE)
|
||||
else:
|
||||
# our region spans multiple physical lines, so deal
|
||||
b1 = lines[vp1.y][vp1.x:]
|
||||
self.win.addstr(vp1.y + y_offset, vp1.x, b1, curses.A_REVERSE)
|
||||
for i in range(vp1.y + 1, vp2.y):
|
||||
b = lines[i]
|
||||
self.wind.addstr(i + y_offset, 0, b, curses.A_REVERSE)
|
||||
b2 = lines[vp2.y][:vp2.x]
|
||||
self.win.addstr(vp2.y + y_offset, 0, b2, curses.A_REVERSE)
|
||||
x += slot.width
|
||||
count += 1
|
||||
|
||||
if self.margins_visible:
|
||||
for (limit, shade) in self.margins:
|
||||
|
@ -606,44 +541,42 @@ class Application:
|
|||
# the actual character is the lower 8 bits, and the
|
||||
# attribute is the upper 8 bits; we will ignore the
|
||||
# attribute and just get the character
|
||||
char = self.win.inch(i + y_offset, limit) & 255
|
||||
char = self.win.inch(i + slot.offset, limit) & 255
|
||||
attr = color.build('default', shade, 'bold')
|
||||
self.win.addch(i + y_offset, limit, char, attr)
|
||||
self.win.addch(i + slot.offset, limit, char, attr)
|
||||
|
||||
if self.mini_active is False and self.active_slot == slotname:
|
||||
if w.active_point is not None and w.point_is_visible(w.active_point):
|
||||
if self.mini_active is False and self.active_slot == i:
|
||||
if False and w.active_point is not None and w.point_is_visible(w.active_point):
|
||||
pa = w.physical_point(w.active_point)
|
||||
va = pa.offset(0, -w.visible_offset())
|
||||
if len(lines[va.y]):
|
||||
a = lines[va.y][va.x]
|
||||
else:
|
||||
a = ' '
|
||||
self.win.addch(va.y + y_offset, va.x, a, curses.A_REVERSE)
|
||||
self.win.addch(va.y + slot.offset, va.x, a, curses.A_REVERSE)
|
||||
else:
|
||||
cursor = w.visible_cursor()
|
||||
cx, cy = (cursor.x, cursor.y)
|
||||
assert px is not None and py is not None
|
||||
|
||||
if cy >= len(lines):
|
||||
self.set_error('in main1: cursor error; %d >= %d' %
|
||||
(cy, len(lines)))
|
||||
self.set_error('in main1: cursor error; %d >= %d' % (cy, len(lines)))
|
||||
return
|
||||
elif cx == len(lines[cy]):
|
||||
c = ' '
|
||||
elif cx > len(lines[cy]):
|
||||
self.set_error('why? %r %r' % (cursor, len(lines[cy])))
|
||||
elif px > len(lines[cy]):
|
||||
self.set_error('why? %r %r' % (cx, len(lines[cy])))
|
||||
return
|
||||
else:
|
||||
c = lines[cy][cx]
|
||||
self.win.addch(cy + y_offset, cx, c, curses.A_REVERSE)
|
||||
self.win.addch(slot.offset + py , px, c, curses.A_REVERSE)
|
||||
|
||||
def draw_status_bar(self, slotname):
|
||||
slot = self.bufferlist.slots[slotname]
|
||||
if not slot.buffer.has_window(slotname):
|
||||
if slot.window is None:
|
||||
return
|
||||
|
||||
w = slot.buffer.get_window(slotname)
|
||||
w = slot.window
|
||||
b = w.buffer
|
||||
cursor = w.logical_cursor()
|
||||
pcursor = w.physical_cursor()
|
||||
first = w.first
|
||||
last = w.last
|
||||
|
||||
|
@ -661,7 +594,7 @@ class Application:
|
|||
if w.mark:
|
||||
mark = w.mark
|
||||
else:
|
||||
mark = point.Point(-1, -1)
|
||||
mark = Point(-1, -1)
|
||||
name = b.name()
|
||||
|
||||
if w.first_is_visible():
|
||||
|
@ -673,8 +606,10 @@ class Application:
|
|||
|
||||
# XYZ: we should actually use more of the 'state' variables
|
||||
|
||||
format = "----:%s-Fl %-18s (%s)--L%d--C%d--%s"
|
||||
status = format % (modflag, name, w.mode.name(), cursor.y+1, cursor.x+1, perc)
|
||||
#format = "----:%s-Fl %-18s (%s)--L%d--C%d--%s"
|
||||
#status = format % (modflag, name, w.mode.name(), cursor.y+1, cursor.x+1, perc)
|
||||
format = "----:%s-Fl %-18s (%s)--L%d--C%d--%s--%s--%s"
|
||||
status = format % (modflag, name, w.mode.name(), cursor.y+1, cursor.x+1, w.first, w.last, perc)
|
||||
status = status[:slot.width + 1]
|
||||
status += "-" * (slot.width - len(status) + 1)
|
||||
self.win.addnstr(slot.height + slot.offset, 0, status, slot.width + 1,
|
||||
|
@ -729,11 +664,11 @@ class Application:
|
|||
|
||||
def open_aes_file(path, nl, name=None):
|
||||
p = getpass.getpass("Please enter the AES password: ")
|
||||
b = buffer.AesBuffer(path, p, nl, name)
|
||||
b = buffer2.AesBuffer(path, p, nl, name)
|
||||
return b
|
||||
|
||||
def open_plain_file(path, nl, name=None):
|
||||
b = buffer.FileBuffer(path, nl, name)
|
||||
b = buffer2.FileBuffer(path, nl, name)
|
||||
return b
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
125
bufferlist.py
125
bufferlist.py
|
@ -1,66 +1,105 @@
|
|||
import sets
|
||||
|
||||
class Slot:
|
||||
def __init__(self, height, width, offset, buffer=None):
|
||||
def __init__(self, height, width, offset):
|
||||
self.height = height
|
||||
self.width = width
|
||||
self.offset = offset
|
||||
self.buffer = buffer
|
||||
self.resize(height, width, offset)
|
||||
self.window = None
|
||||
def is_empty(self):
|
||||
return self.buffer is None
|
||||
return self.window is None
|
||||
def resize(self, height, width, offset):
|
||||
self.height = height
|
||||
self.width = width
|
||||
self.offset = offset
|
||||
# possible callbacks
|
||||
def remove(self):
|
||||
# possible callbacks
|
||||
pass
|
||||
if self.window is not None:
|
||||
self.window.set_size(self.width, self.height)
|
||||
def set(self, w):
|
||||
self.window = w
|
||||
w.set_size(self.width, self.height)
|
||||
def unset(self):
|
||||
if not self.is_empty():
|
||||
old_w = self.window
|
||||
self.window = None
|
||||
return old_w
|
||||
else:
|
||||
return None
|
||||
|
||||
class BufferList:
|
||||
def __init__(self, height, width, buffers=()):
|
||||
self.slots = []
|
||||
self.add_slot(height, width, 0)
|
||||
|
||||
self.buffers = sets.Set()
|
||||
self.buffer_names = {}
|
||||
self.height = height
|
||||
self.width = width
|
||||
self.buffers = sets.Set()
|
||||
self.buffer_names = {}
|
||||
self.hidden_buffers = []
|
||||
self.slots = []
|
||||
|
||||
self.add_slot()
|
||||
self.fit_slots()
|
||||
for b in buffers:
|
||||
self.add_buffer(b)
|
||||
def fit_slots(self):
|
||||
heights = [self.height / len(self.slots)] * len(self.slots)
|
||||
for i in range(0, self.height % len(self.slots)):
|
||||
heights[i] += 1
|
||||
offsets = [0]
|
||||
for i in range(1, len(self.slots)):
|
||||
offsets.insert(i, offsets[i - 1] + heights[i - 1])
|
||||
for i in range(0, len(self.slots)):
|
||||
self.slots[i].resize(heights[i], self.width, offsets[i])
|
||||
def resize(self, height, width):
|
||||
self.height = height
|
||||
self.width = width
|
||||
self.fit_slots()
|
||||
|
||||
def is_window_visible(self, w):
|
||||
for slot in self.slots:
|
||||
if w is slot.window:
|
||||
return True
|
||||
return False
|
||||
def is_buffer_visible(self, b):
|
||||
for slot in self.slots:
|
||||
if slot.window is not None and b is slot.window.buffer:
|
||||
return True
|
||||
return False
|
||||
|
||||
# manipulate slots
|
||||
def add_slot(self, height, width, offset=0, buffer=None):
|
||||
self.slots.append(Slot(height, width, offset, buffer))
|
||||
def add_slot(self):
|
||||
self.slots.append(Slot(self.height, self.width, 0))
|
||||
self.fit_slots()
|
||||
return len(self.slots) - 1
|
||||
def empty_slot(self, i):
|
||||
assert i > -1 and i < len(self.slots), "slot %d does not exist" % i
|
||||
return self.slots[i].is_empty()
|
||||
def unset_slot(self, i):
|
||||
assert i > -1 and i < len(self.slots), "slot %d does not exist" % i
|
||||
old_w = self.slots[i].unset()
|
||||
if old_w is not None:
|
||||
old_b = old_w.buffer
|
||||
if not self.is_buffer_visible(old_b):
|
||||
self.hidden_buffers.insert(0, old_b)
|
||||
if len(old_b.windows) > 1:
|
||||
old_b.remove_window(old_w)
|
||||
|
||||
def set_slot(self, i, b):
|
||||
assert i > -1 and i < len(self.slots), "slot %d does not exist" % i
|
||||
assert b in self.buffers, "buffer %s does not exist" % (b.name())
|
||||
self.unset_slot(i)
|
||||
|
||||
if b in self.hidden_buffers:
|
||||
self.hidden_buffers.remove(b)
|
||||
if not self.slots[i].is_empty():
|
||||
b2 = self.slots[i].buffer
|
||||
self.hidden_buffers.insert(0, b2)
|
||||
self.slots[i].buffer = b
|
||||
if self.is_window_visible(b.windows[0]):
|
||||
app = b.windows[0].application
|
||||
w = window2.Window(b, app, height=slot.height, width=slot.width)
|
||||
else:
|
||||
w = b.windows[0]
|
||||
self.slots[i].set(w)
|
||||
|
||||
def remove_slot(self, i):
|
||||
assert i > -1 and i < len(self.slots), "slot %d does not exist" % i
|
||||
if not self.slots[i].is_empty():
|
||||
b = self.slots[i].buffer
|
||||
self.hidden_buffers.insert(0, b)
|
||||
self.slots[i].remove()
|
||||
self.unset_slot(i)
|
||||
del self.slots[i]
|
||||
|
||||
# now fix the stored slot numbers for all the
|
||||
for b in self.buffers:
|
||||
for j in range(i, len(self.slots)):
|
||||
if b.has_window(j+1):
|
||||
w = b.get_window(j+1)
|
||||
del b.windows[j+1]
|
||||
w.slot = j
|
||||
b.windows[j] = w
|
||||
self.fit_slots()
|
||||
|
||||
# add/remove buffers
|
||||
def add_buffer(self, b):
|
||||
|
@ -68,9 +107,6 @@ class BufferList:
|
|||
self.buffers.add(b)
|
||||
self.buffer_names[b.name()] = b
|
||||
self.hidden_buffers.append(b)
|
||||
for i in range(0, len(self.slots)):
|
||||
if self.empty_slot(i):
|
||||
self.set_slot(i, b)
|
||||
def has_buffer(self, b):
|
||||
return b in self.buffers
|
||||
def has_buffer_name(self, name):
|
||||
|
@ -84,9 +120,10 @@ class BufferList:
|
|||
return None
|
||||
def remove_buffer(self, b):
|
||||
assert b in self.buffers, "buffer %s does not exist" % (b.name())
|
||||
for slot in self.slots:
|
||||
if slot.buffer is b:
|
||||
slot.buffer = None
|
||||
for i in range(0, len(self.slots)):
|
||||
slot = self.slots[i]
|
||||
if self.slots[i].window is not None and self.slots[i].window.buffer is b:
|
||||
self.unset_slot(i)
|
||||
self.buffers.remove(b)
|
||||
del self.buffer_names[b.name()]
|
||||
if b in self.hidden_buffers:
|
||||
|
@ -96,9 +133,9 @@ class BufferList:
|
|||
def is_buffer_hidden(self, b):
|
||||
assert b in self.buffers, "buffer %s does not exist" % (b.name())
|
||||
return b in self.hidden_buffers
|
||||
def is_buffer_visible(self, b):
|
||||
assert b in self.buffers, "buffer %s does not exist" % (b.name())
|
||||
for slot in self.slots:
|
||||
if slot.buffer is b:
|
||||
return True
|
||||
return False
|
||||
# def is_buffer_visible(self, b):
|
||||
# assert b in self.buffers, "buffer %s does not exist" % (b.name())
|
||||
# for slot in self.slots:
|
||||
# if slot.buffer is b:
|
||||
# return True
|
||||
# return False
|
||||
|
|
|
@ -4,7 +4,7 @@ import lex2
|
|||
color_list = []
|
||||
color_list.extend(['\033[3%dm' % x for x in range(0, 8)])
|
||||
color_list.extend(['\033[3%d;1m' % x for x in range(0, 8)])
|
||||
color_list.append('\033[0m')
|
||||
color_list.extend(['\033[0m'])
|
||||
|
||||
color_names = [
|
||||
'black', 'dred', 'dgreen', 'brown', 'dblue', 'dpurple', 'dcyan', 'lgrey',
|
||||
|
@ -158,7 +158,7 @@ class Highlighter:
|
|||
tx2 = token.x + len(token.string)
|
||||
|
||||
# the notation "*|*| " refers to what the text spans, i.e.:
|
||||
# before|during|after
|
||||
# before|during|after the deletion
|
||||
if (y, tx2) <= (y1, x1):
|
||||
# *| |
|
||||
newtokens[y].append(token)
|
||||
|
|
24
method.py
24
method.py
|
@ -336,7 +336,7 @@ class InsertString(Method):
|
|||
self.help = "Insert %r into the current buffer." % s
|
||||
self.string = s
|
||||
def _execute(self, window, **vargs):
|
||||
window.insert_string(self.string)
|
||||
window.insert_string_at_cursor(self.string)
|
||||
|
||||
# killing/copying/etc.
|
||||
class Kill(Method):
|
||||
|
@ -487,18 +487,18 @@ class SwitchMark(Method):
|
|||
class InsertNewline(Method):
|
||||
'''Insert newline into buffer at the cursor'''
|
||||
def _execute(self, window, **vargs):
|
||||
window.insert_string('\n')
|
||||
window.insert_string_at_cursor('\n')
|
||||
class InsertSpace(Method):
|
||||
'''Insert space into buffer at the cursor'''
|
||||
def _execute(self, window, **vargs):
|
||||
window.insert_string(' ')
|
||||
window.insert_string_at_cursor(' ')
|
||||
class InsertTab(Method):
|
||||
'''Insert tab into buffer, or tabbify line, depending on mode'''
|
||||
def _execute(self, window, **vargs):
|
||||
cursor = window.logical_cursor()
|
||||
i = window.mode.get_indentation_level(cursor.y)
|
||||
if i is None:
|
||||
window.insert_string(' ')
|
||||
window.insert_string_at_cursor(' ')
|
||||
else:
|
||||
j = window.buffer.count_leading_whitespace(cursor.y)
|
||||
if i != j:
|
||||
|
@ -541,7 +541,7 @@ class CommentRegion(Method):
|
|||
window.input_line = "Empty kill region"
|
||||
return
|
||||
for y in range(p1.y, p2.y):
|
||||
window.buffer.insert_string(point.Point(0, y), "#")
|
||||
window.buffer.insert_string_at_cursor(point.Point(0, y), "#")
|
||||
class UncommentRegion(Method):
|
||||
'''Remove a comment from every line in the current buffer'''
|
||||
def _execute(self, w, **vargs):
|
||||
|
@ -582,7 +582,7 @@ class WrapLine(Method):
|
|||
old_cursor.y += 1
|
||||
window.goto(point.Point(j, i))
|
||||
window.right_delete()
|
||||
window.insert_string('\n')
|
||||
window.insert_string_at_cursor('\n')
|
||||
i += 1
|
||||
|
||||
l = len(window.buffer.lines[old_cursor.y])
|
||||
|
@ -627,7 +627,7 @@ class JustifyRight(Method):
|
|||
if i >= len(prev_line):
|
||||
return
|
||||
s = ' ' * (i - cursor.x)
|
||||
window.insert_string(s)
|
||||
window.insert_string_at_cursor(s)
|
||||
class JustifyLeft(Method):
|
||||
'''Justify text with the previous line left from the cursor by whitespace'''
|
||||
def _execute(self, window, **vargs):
|
||||
|
@ -767,7 +767,7 @@ class UnindentBlock(Method):
|
|||
if lines[i].startswith(' '):
|
||||
lines[i] = lines[i][4:]
|
||||
w.buffer.delete_string(point.Point(0, p1.y), point.Point(0, p2.y))
|
||||
w.buffer.insert_string(point.Point(0, p1.y), '\n'.join(lines) + '\n')
|
||||
w.buffer.insert_string_at_cursor(point.Point(0, p1.y), '\n'.join(lines) + '\n')
|
||||
class IndentBlock(Method):
|
||||
'''Add 4 spaces to each line in region'''
|
||||
def _execute(self, w, **vargs):
|
||||
|
@ -785,7 +785,7 @@ class IndentBlock(Method):
|
|||
for i in range(0, len(lines)):
|
||||
lines[i] = ' ' + lines[i]
|
||||
w.buffer.delete_string(point.Point(0, p1.y), point.Point(0, p2.y))
|
||||
w.buffer.insert_string(point.Point(0, p1.y), '\n'.join(lines) + '\n')
|
||||
w.buffer.insert_string_at_cursor(point.Point(0, p1.y), '\n'.join(lines) + '\n')
|
||||
|
||||
class CodeComplete(Method):
|
||||
'''Complete based on tokenized strings'''
|
||||
|
@ -830,7 +830,7 @@ class CodeComplete(Method):
|
|||
pass
|
||||
elif sofar:
|
||||
w.buffer.delete_string(p1, p2)
|
||||
w.buffer.insert_string(p1, sofar)
|
||||
w.buffer.insert_string_at_cursor(p1, sofar)
|
||||
if num_seen == 1:
|
||||
w.application.set_error('Unique!')
|
||||
else:
|
||||
|
@ -1279,7 +1279,7 @@ class CloseTag(Method):
|
|||
def _execute(self, w, **vargs):
|
||||
# if w.mode doesn't do tag matching, just insert the character return
|
||||
if not w.mode.tag_matching:
|
||||
w.insert_string(self.mytag)
|
||||
w.insert_string_at_cursor(self.mytag)
|
||||
return
|
||||
|
||||
# first, de-reference some variables and actually do the insertion
|
||||
|
@ -1289,7 +1289,7 @@ class CloseTag(Method):
|
|||
buffer = w.buffer
|
||||
#cursor = w.physical_cursor()
|
||||
tag_stack = []
|
||||
w.insert_string(self.mytag)
|
||||
w.insert_string_at_cursor(self.mytag)
|
||||
cursor = w.physical_cursor()
|
||||
assert cursor.x > 0, "my assumptions made an ass out of u and me"
|
||||
|
||||
|
|
22
mode2.py
22
mode2.py
|
@ -3,7 +3,8 @@ import sets, string
|
|||
|
||||
import color, default, highlight, method, point
|
||||
|
||||
DEBUG = False
|
||||
#DEBUG = False
|
||||
DEBUG = True
|
||||
|
||||
class Handler:
|
||||
def __init__(self):
|
||||
|
@ -191,8 +192,6 @@ class Fundamental(Handler):
|
|||
self.window.application.set_error(err)
|
||||
|
||||
def invalidate(self):
|
||||
if self.tabber is not None:
|
||||
self.tabber.invalidate()
|
||||
if self.lexer is not None:
|
||||
self.highlighter.invalidate_regions()
|
||||
|
||||
|
@ -212,20 +211,13 @@ class Fundamental(Handler):
|
|||
regions = self.get_regions()
|
||||
return regions[i:i+self.window.height]
|
||||
|
||||
def region_added(self, p, xdiff, ydiff, s):
|
||||
def region_added(self, p, newlines):
|
||||
if self.lexer is not None:
|
||||
if self.tabber is not None and s != ' ' and s != ' ':
|
||||
self.tabber.invalidate()
|
||||
self.highlighter.region_added(p, xdiff, ydiff, s)
|
||||
self.highlighter.relex_add(lines, p.y, p.x, newlines)
|
||||
|
||||
def region_removed(self, p1, p2, s):
|
||||
def region_removed(self, p1, p2):
|
||||
if self.lexer is not None:
|
||||
if self.tabber is not None:
|
||||
self.tabber.invalidate()
|
||||
self.highlighter.region_removed(p1, p2, s)
|
||||
self.highlighter.relex_del(lines, p1, p2)
|
||||
|
||||
def get_indentation_level(self, y):
|
||||
if self.tabber is None:
|
||||
return None
|
||||
else:
|
||||
return self.tabber.get_indentation_level(y)
|
||||
return None
|
||||
|
|
Loading…
Reference in New Issue