parent
ba7cc48dfb
commit
f69c3b1995
159
application.py
159
application.py
|
@ -581,6 +581,9 @@ class Application(object):
|
|||
if y >= len(w.buffer.lines) or x + swidth >= len(w.buffer.lines[y]):
|
||||
x = 0
|
||||
y += 1
|
||||
#XYZ
|
||||
while w.ishidden(y) and y < len(w.buffer.lines):
|
||||
y += 1
|
||||
else:
|
||||
x += swidth
|
||||
count += 1
|
||||
|
@ -615,25 +618,40 @@ class Application(object):
|
|||
for x in range(sx1, sx2):
|
||||
self.highlight_char(sy, x, fg, bg)
|
||||
|
||||
def map_point(self, p):
|
||||
count = 0
|
||||
x, y = w.first.xy()
|
||||
while count < slot.height:
|
||||
if p1.y == y and p1.x >= x and p1.x - x < slot.width:
|
||||
return (count, x)
|
||||
if x + slot.width > len(w.buffer.lines[y]):
|
||||
x = 0
|
||||
y += 1
|
||||
#XYZ
|
||||
while w.ishidden(y) and y < len(w.buffer.lines):
|
||||
y += 1
|
||||
else:
|
||||
x += slot.width
|
||||
count += 1
|
||||
|
||||
def draw_slot(self, i):
|
||||
assert self.active_slot < len(self.bufferlist.slots), "only two"
|
||||
assert i < len(self.bufferlist.slots), "only three"
|
||||
assert self.active_slot < len(self.bufferlist.slots), \
|
||||
"strange: %d < %d" % (self.active_slot, len(self.bufferlist.slots))
|
||||
assert i < len(self.bufferlist.slots), \
|
||||
"puzzling: %d < %d" % (i, len(self.bufferlist.slots))
|
||||
slot = self.bufferlist.slots[i]
|
||||
if slot.window is None:
|
||||
return
|
||||
w = slot.window
|
||||
modename = w.mode.name()
|
||||
|
||||
if modename in w.buffer.highlights:
|
||||
self._draw_slot_lit(i)
|
||||
else:
|
||||
self._draw_slot_raw(i)
|
||||
self._draw_slot(i)
|
||||
|
||||
# highlighted regions
|
||||
for (high_w, p1, p2, fg, bg) in self.highlighted_ranges:
|
||||
if w is high_w and p2 >= w.first and p1 <= w.last:
|
||||
count = 0
|
||||
(x, y) = w.first.xy()
|
||||
x, y = w.first.xy()
|
||||
px = p1.x
|
||||
while count < slot.height:
|
||||
if p1.y == y and px >= x and px - x < slot.width:
|
||||
|
@ -646,6 +664,9 @@ class Application(object):
|
|||
if x + slot.width > len(w.buffer.lines[y]):
|
||||
x = 0
|
||||
y += 1
|
||||
#XYZ
|
||||
while w.ishidden(y) and y < len(w.buffer.lines):
|
||||
y += 1
|
||||
else:
|
||||
x += slot.width
|
||||
count += 1
|
||||
|
@ -658,122 +679,36 @@ class Application(object):
|
|||
attr = color.build('default', shade, 'bold')
|
||||
self.win.addstr(j + slot.y_offset, limit + w.mode.lmargin, char, attr)
|
||||
|
||||
def _draw_line_margins(self, slot, count, w, y, x):
|
||||
lm, rm = w.mode.lmargin, w.mode.rmargin
|
||||
if y >= len(w.buffer.lines):
|
||||
ended = True
|
||||
cont = False
|
||||
else:
|
||||
ended = False
|
||||
cont = x + slot.width - lm - rm < len(w.buffer.lines[y])
|
||||
|
||||
i = slot.y_offset + count
|
||||
if lm:
|
||||
groups = w.mode.get_lmargin(y, x, ended, cont)
|
||||
for (x, lmargin, lattr) in groups:
|
||||
self.win.addstr(i, x, lmargin, lattr)
|
||||
if rm:
|
||||
groups = w.mode.get_rmargin(y, x, ended, cont)
|
||||
for (x, rmargin, rattr) in groups:
|
||||
self.win.addstr(i, slot.width - rm + x, rmargin, rattr)
|
||||
|
||||
def _draw_slot_raw(self, i):
|
||||
def _draw_slot(self, i):
|
||||
slot = self.bufferlist.slots[i]
|
||||
w = slot.window
|
||||
modename = w.mode.name()
|
||||
redattr = color.build_attr(color.pairs('red', 'default'))
|
||||
|
||||
(x, y) = w.first.xy()
|
||||
x, y = w.first.xy()
|
||||
lines = w.buffer.lines
|
||||
count = 0
|
||||
lm, rm = w.mode.lmargin, w.mode.rmargin
|
||||
swidth = slot.width - lm - rm
|
||||
while count < slot.height:
|
||||
#draw some margins
|
||||
self._draw_line_margins(slot, count, w, y, x)
|
||||
|
||||
# if the window has no more lines, display the "empty" symbol
|
||||
if y >= len(lines):
|
||||
self.win.addstr(slot.y_offset + count, 0 + lm, '~', redattr)
|
||||
count += 1
|
||||
continue
|
||||
|
||||
# get the line to draw and draw it
|
||||
line = lines[y]
|
||||
s = line[x:x + swidth]
|
||||
self.win.addstr(slot.y_offset + count, 0 + lm, s)
|
||||
|
||||
# see if we need to draw a line-continuation symbol or not
|
||||
if x + swidth >= len(line):
|
||||
x = 0
|
||||
y += 1
|
||||
else:
|
||||
x += swidth
|
||||
|
||||
# move on to the next physical line
|
||||
count += 1
|
||||
|
||||
def _draw_slot_lit(self, i):
|
||||
slot = self.bufferlist.slots[i]
|
||||
w = slot.window
|
||||
modename = w.mode.name()
|
||||
redattr = color.build_attr(color.pairs('red', 'default'))
|
||||
highlighter = w.buffer.highlights[modename]
|
||||
|
||||
(x, y) = w.first.xy()
|
||||
j = 0
|
||||
count = 0
|
||||
(lm, rm) = (w.mode.lmargin, w.mode.rmargin)
|
||||
swidth = slot.width - lm - rm
|
||||
assert len(w.buffer.lines) == len(highlighter.tokens)
|
||||
lit = w.mode.name() in w.buffer.highlights
|
||||
ended = False
|
||||
while count < slot.height:
|
||||
if y < len(w.buffer.lines):
|
||||
while j < len(highlighter.tokens[y]):
|
||||
token = highlighter.tokens[y][j]
|
||||
if token.string.endswith('\n'):
|
||||
tstring = token.string[:-1]
|
||||
if lit:
|
||||
rlines = w.render_line_lit(y, slot.width - lm - rm)
|
||||
else:
|
||||
tstring = token.string
|
||||
|
||||
assert token.y == y, '%d == %d' % (token.y, y)
|
||||
|
||||
s_offset = max(x - token.x, 0)
|
||||
x_offset = max(token.x - x, 0)
|
||||
assert x_offset <= swidth, '%d <= %d' % (x_offset, swidth)
|
||||
|
||||
s = tstring[s_offset:]
|
||||
token_done = x_offset + len(s) <= swidth
|
||||
token_wrap = x_offset + len(s) > swidth
|
||||
|
||||
# for debugging things like lexing/relexing/etc.
|
||||
if token._debug:
|
||||
attr = color.build('blue', 'green')
|
||||
elif token.color:
|
||||
attr = color.build(*token.color)
|
||||
else:
|
||||
attr = color.build("default", "default")
|
||||
|
||||
k = slot.y_offset + count
|
||||
self.win.addstr(k, x_offset + lm, s[:swidth - x_offset], attr)
|
||||
|
||||
if token_wrap:
|
||||
self._draw_line_margins(slot, count, w, y, x)
|
||||
x += swidth
|
||||
rlines = w.render_line_raw(y, slot.width - lm - rm)
|
||||
for j in range(0, len(rlines)):
|
||||
if lm:
|
||||
lcont = j > 0
|
||||
for rstr in slot.window.mode.get_lmargin(w, y, x, ended, lcont):
|
||||
rstr.draw(self.win, slot.y_offset + count, 0)
|
||||
for rstr in rlines[j]:
|
||||
rstr.draw(self.win, slot.y_offset + count, 0 + lm)
|
||||
if rm:
|
||||
rcont = j < len(rlines) - 1
|
||||
for rstr in slot.window.mode.get_rmargin(w, y, x, ended, rcont):
|
||||
rstr.draw(self.win, slot.y_offset + count, slot.width - rm)
|
||||
count += 1
|
||||
if token_done:
|
||||
j += 1
|
||||
if count >= slot.height:
|
||||
break
|
||||
|
||||
# we have finished this logical line of tokens
|
||||
self._draw_line_margins(slot, count, w, y, x)
|
||||
j = x = 0
|
||||
y += 1
|
||||
count += 1
|
||||
else:
|
||||
self._draw_line_margins(slot, count, w, y, x)
|
||||
self.win.addstr(slot.y_offset + count, 0 + lm, '~', redattr)
|
||||
count += 1
|
||||
ended = ended or y >= len(w.buffer.lines)
|
||||
|
||||
def draw_status_bar(self, slotname):
|
||||
slot = self.bufferlist.slots[slotname]
|
||||
|
|
|
@ -989,3 +989,23 @@ class SetModeTabWidth(Method):
|
|||
return
|
||||
app.modes[mode].tabwidth = vargs['width']
|
||||
w.set_error('Default tab width set to %d' % app.modes[mode].tabwidth)
|
||||
|
||||
class HideRange(Method):
|
||||
def _execute(self, w, **vargs):
|
||||
cursor = w.logical_cursor()
|
||||
if cursor.y < w.mark.y:
|
||||
y1, y2 = cursor.y, w.mark.y
|
||||
elif w.mark.y < cursor.y:
|
||||
y1, y2 = w.mark.y, cursor.y
|
||||
else:
|
||||
w.set_error("No line range selected")
|
||||
w.hide(y1, y2)
|
||||
w.set_error("Lines %d through %d hidden" % (y1, y2))
|
||||
class UnhideLine(Method):
|
||||
def _execute(self, w, **vargs):
|
||||
cursor = w.logical_cursor()
|
||||
if w.ishidden(cursor.y):
|
||||
w.unhide(cursor.y)
|
||||
w.set_error("Line %d is no longer hidden" % cursor.y)
|
||||
else:
|
||||
w.set_error("Line %d is not hidden" % cursor.y)
|
||||
|
|
|
@ -2,6 +2,7 @@ import math, os, sets, string
|
|||
import color, method
|
||||
from lex import Lexer
|
||||
from point import Point
|
||||
from render import RenderString
|
||||
|
||||
DEBUG = False
|
||||
|
||||
|
@ -224,27 +225,27 @@ class Fundamental(Handler):
|
|||
self.show_line_numbers = True
|
||||
l = len(self.window.buffer.lines)
|
||||
self.lmargin = int(math.log(l, 10)) + 3
|
||||
self.rmargin = 0
|
||||
def disable_line_numbers(self):
|
||||
self.show_line_numbers = False
|
||||
self.lmargin = 0
|
||||
self.rmargin = 1
|
||||
|
||||
def get_rmargin(self, y, x, ended=False, cont=False):
|
||||
def get_rmargin(self, w, y, x, ended=False, cont=False):
|
||||
c, fg, bg = " ", "red", "default"
|
||||
if cont:
|
||||
return ((0, '\\', color.build('red', 'default')),)
|
||||
else:
|
||||
return ((0, ' ', color.build('red', 'default')),)
|
||||
def get_lmargin(self, y, x=0, ended=False, cont=False):
|
||||
c = "\\"
|
||||
if w.hiddenindicator(y):
|
||||
bg = "green"
|
||||
return [RenderString(c, 0, color.build(fg, bg))]
|
||||
def get_lmargin(self, w, y, x, ended=False, cont=False):
|
||||
lm = self.lmargin
|
||||
if ended:
|
||||
i = int(math.log(y, 10)) + 1
|
||||
s = ('% *s' % (lm - 1, '-' * i))[-lm:] + ' '
|
||||
elif x == 0:
|
||||
elif not cont:
|
||||
s = ('% *d' % (lm - 1, y + 1))[-lm:] + ' '
|
||||
else:
|
||||
s = ' ' * lm
|
||||
return ((0, s, color.build('default', 'default', 'bold')),)
|
||||
return [RenderString(s, 0, color.build('default', 'default', 'bold'))]
|
||||
|
||||
# get mode name
|
||||
def name(self):
|
||||
|
|
21
mode/hex.py
21
mode/hex.py
|
@ -4,6 +4,7 @@ import color, mode
|
|||
from lex import Grammar, PatternRule, RegionRule
|
||||
from method import Method, Argument
|
||||
from point import Point
|
||||
from render import RenderString
|
||||
|
||||
class HexSetByteOrder(Method):
|
||||
'''Sets the byte-order to use to 'little', 'big', or 'native' order'''
|
||||
|
@ -310,16 +311,16 @@ class Hex(mode.Fundamental):
|
|||
def get_address(self, y, x):
|
||||
return (y * 16) + x
|
||||
|
||||
def get_lmargin(self, y, x=0, ended=False, cont=False):
|
||||
def get_lmargin(self, w, y, x, ended=False, cont=False):
|
||||
lm = self.lmargin
|
||||
if ended:
|
||||
s = ' -------- '
|
||||
else:
|
||||
addr = self.get_address(y, x)
|
||||
s = '0x%08x ' % addr
|
||||
return ((0, s, self.ccyan),)
|
||||
return (RenderString(s, 0, self.ccyan),)
|
||||
|
||||
def get_rmargin(self, y, x=0, ended=False, cont=False):
|
||||
def get_rmargin(self, w, y, x, ended=False, cont=False):
|
||||
if ended:
|
||||
return ((0, '', 0),)
|
||||
else:
|
||||
|
@ -329,17 +330,17 @@ class Hex(mode.Fundamental):
|
|||
i = self.window.buffer.cursorx_to_datax(cy, cx)
|
||||
|
||||
if i is None:
|
||||
rmargins = ((0, s, self.cgreen),)
|
||||
rmargins = (RenderString(s, 0, self.cgreen),)
|
||||
elif i < len(s):
|
||||
rmargins = ((0, s[0:i], self.cgreen),
|
||||
(i, s[i], self.ccursor),
|
||||
(i + 1, s[i+1:], self.cgreen))
|
||||
rmargins = (RenderString(s[0:i], 0, self.cgreen),
|
||||
RenderString(s[i], i, self.ccursor),
|
||||
RenderString(s[i+1:], i + 1, self.cgreen))
|
||||
else:
|
||||
rmargins= ((0, s[0:i], self.cgreen),
|
||||
(i, s[i], self.cgreen),)
|
||||
rmargins= (RenderString(s[0:i], 0, self.cgreen),
|
||||
RenderString(s[i], i, self.cgreen))
|
||||
return rmargins
|
||||
else:
|
||||
return ((0, s, self.cgreen),)
|
||||
return (RenderString(s, 0, self.cgreen),)
|
||||
|
||||
def read_data(self, cy, ix, size):
|
||||
b = self.window.buffer
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import color
|
||||
from point import Point
|
||||
|
||||
class RenderString(object):
|
||||
def __init__(self, s, x=0, attrs=None):
|
||||
if attrs is None:
|
||||
attrs = color.build('default', 'default')
|
||||
self.string = s
|
||||
self.x = x
|
||||
self.attrs = attrs
|
||||
def draw(self, cwin, y, x):
|
||||
cwin.addstr(y, self.x + x, self.string, self.attrs)
|
107
window.py
107
window.py
|
@ -1,6 +1,7 @@
|
|||
import os.path, string
|
||||
import color, highlight, regex
|
||||
from point import Point
|
||||
from render import RenderString
|
||||
|
||||
WORD_LETTERS = list(string.letters + string.digits)
|
||||
|
||||
|
@ -11,23 +12,22 @@ WORD_LETTERS = list(string.letters + string.digits)
|
|||
# error. both buffer and window need to be aware of this possibility for points.
|
||||
|
||||
class Window(object):
|
||||
boxtype = 'window'
|
||||
margins = ((80, 'blue'),)
|
||||
margins_visible = False
|
||||
def __init__(self, b, a, height=24, width=80, mode_name=None):
|
||||
self.buffer = b
|
||||
self.application = a
|
||||
self.height = height
|
||||
self.width = width
|
||||
|
||||
self.first = Point(0, 0)
|
||||
self.last = None
|
||||
self.cursor = Point(0, 0)
|
||||
self.mark = None
|
||||
self.active_point = None
|
||||
|
||||
self.height = height
|
||||
self.width = width
|
||||
|
||||
self.input_line = ""
|
||||
self.hidden_ranges = {}
|
||||
self.hidden_lines = {}
|
||||
|
||||
if mode_name is not None:
|
||||
pass
|
||||
|
@ -585,6 +585,31 @@ class Window(object):
|
|||
else:
|
||||
return self.buffer.lines[y][x]
|
||||
|
||||
# hiding stuff
|
||||
def hide(self, y1, y2):
|
||||
if y2 == 0:
|
||||
return
|
||||
for (py1, py2) in self.hidden_ranges.itervalues():
|
||||
if ((y1 >= py1 and y1 < py2) or
|
||||
(y2 >= py1 and y2 < py2) or
|
||||
(y1 <= py1 and y2 >= py2)):
|
||||
return
|
||||
for i in range(y1, y2):
|
||||
self.hidden_lines[i] = y2
|
||||
self.hidden_ranges[y2] = (y1, y2)
|
||||
def ishidden(self, y):
|
||||
return self.hidden_lines.setdefault(y, False)
|
||||
def hiddenindicator(self, y):
|
||||
return y in self.hidden_ranges
|
||||
def unhide(self, y):
|
||||
py2 = self.ishidden(y)
|
||||
if not py2:
|
||||
return
|
||||
py1 = self.hidden_ranges[py2][0]
|
||||
del self.hidden_ranges[py2]
|
||||
for i in range(py1, py2):
|
||||
self.hidden_lines[i] = False
|
||||
|
||||
# undo/redo
|
||||
def undo(self):
|
||||
p = self.buffer.undo()
|
||||
|
@ -629,8 +654,78 @@ class Window(object):
|
|||
def get_next_token_except_type_regex(self, p, name, regex):
|
||||
l = lambda t: t.name != name or regex.match(t.string)
|
||||
return self.get_next_token_by_lambda(p, l)
|
||||
|
||||
def get_next_token_by_types(self, p, *names):
|
||||
return self.get_next_token_by_lambda(p, lambda t: t.name in names)
|
||||
def get_next_token_except_types(self, p, *names):
|
||||
return self.get_next_token_by_lambda(p, lambda t: t.name not in names)
|
||||
|
||||
# application drawing
|
||||
#
|
||||
# render methods return a list of lists of RenderString objects
|
||||
# (i.e. multiple physical lines, each containing multiple areas to be drawn)
|
||||
def render_line(self, y, width):
|
||||
modename = self.mode.name()
|
||||
if modename in self.buffer.highlights:
|
||||
return self.render_line_lit(y, width)
|
||||
else:
|
||||
return self.render_line_raw(y, width)
|
||||
|
||||
def render_line_raw(self, y, width):
|
||||
if y >= len(self.buffer.lines):
|
||||
return [[RenderString('~', 0, color.build('red', 'default'))]]
|
||||
x = 0
|
||||
line = self.buffer.lines[y]
|
||||
lines = []
|
||||
if line:
|
||||
while x < len(line):
|
||||
lines.append(tuple([RenderString(line[x:x + width], 0)]))
|
||||
x += width
|
||||
else:
|
||||
lines.append(tuple([RenderString('', 0)]))
|
||||
return lines
|
||||
|
||||
def render_line_lit(self, y, width):
|
||||
if y >= len(self.buffer.lines):
|
||||
return [[RenderString('~', 0, color.build('red', 'default'))]]
|
||||
|
||||
modename = self.mode.name()
|
||||
highlighter = self.buffer.highlights[modename]
|
||||
|
||||
line = []
|
||||
lines = []
|
||||
|
||||
j = x = 0
|
||||
while j < len(highlighter.tokens[y]):
|
||||
# get our token, and do some basic checking/bleaching
|
||||
token = highlighter.tokens[y][j]
|
||||
if token.string.endswith('\n'):
|
||||
tstring = token.string[:-1]
|
||||
else:
|
||||
tstring = token.string
|
||||
assert token.y == y, '%d == %d' % (token.y, y)
|
||||
|
||||
# figure out what portion of the string to use
|
||||
s_offset = max(x - token.x, 0)
|
||||
s = tstring[s_offset:]
|
||||
|
||||
# for debugging things like lexing/relexing/etc.
|
||||
if token._debug:
|
||||
attr = color.build('blue', 'green')
|
||||
elif token.color:
|
||||
attr = color.build(*token.color)
|
||||
else:
|
||||
attr = color.build("default", "default")
|
||||
|
||||
# ok, so add a region with data, position, and color info
|
||||
x_offset = max(token.x - x, 0)
|
||||
line.append(RenderString(s[:width - x_offset], x_offset, attr))
|
||||
|
||||
# see if the token is wrapping, or if we move on to the next one
|
||||
if x_offset + len(s) > width:
|
||||
lines.append(line)
|
||||
line = []
|
||||
x += width
|
||||
else:
|
||||
j += 1
|
||||
lines.append(line)
|
||||
return lines
|
||||
|
|
Loading…
Reference in New Issue