2009-03-09 23:46:49 -04:00
|
|
|
from util import defaultdict
|
2008-11-08 10:30:04 -05:00
|
|
|
import math, os, string
|
2007-10-21 20:55:29 -04:00
|
|
|
import color, method
|
|
|
|
from lex import Lexer
|
|
|
|
from point import Point
|
2008-04-20 23:10:25 -04:00
|
|
|
from render import RenderString
|
2007-10-21 20:55:29 -04:00
|
|
|
|
|
|
|
DEBUG = False
|
|
|
|
|
|
|
|
class ActionError(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
class Handler(object):
|
|
|
|
def __init__(self):
|
2008-05-04 02:40:30 -04:00
|
|
|
self.prefixes = set(["C-x", "C-c", "C-u"])
|
2007-10-21 20:55:29 -04:00
|
|
|
self.last_sequence = ''
|
|
|
|
self.curr_tokens = []
|
|
|
|
self.bindings = {}
|
|
|
|
|
|
|
|
# handle adding and removing actions
|
|
|
|
def add_action(self, action):
|
|
|
|
if self.window is None:
|
|
|
|
return
|
|
|
|
elif action.name in self.window.application.methods:
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
self.window.application.methods[action.name] = action
|
|
|
|
def del_action(self, name):
|
|
|
|
if self.window is None:
|
|
|
|
return
|
|
|
|
for binding in self.bindings.keys():
|
|
|
|
if self.bindings[binding] == name:
|
|
|
|
del self.bindings[binding]
|
|
|
|
def add_binding(self, name, sequence):
|
|
|
|
if self.window is None:
|
2009-02-15 12:06:35 -05:00
|
|
|
#return
|
|
|
|
raise Exception("No window available")
|
2007-10-21 20:55:29 -04:00
|
|
|
elif not hasattr(self.window, 'application'):
|
2009-02-15 12:06:35 -05:00
|
|
|
raise Exception("No application available")
|
2007-10-21 20:55:29 -04:00
|
|
|
elif name not in self.window.application.methods:
|
2009-02-15 12:06:35 -05:00
|
|
|
raise Exception("No action called %r found" % name)
|
2007-10-21 20:55:29 -04:00
|
|
|
else:
|
|
|
|
self.bindings[sequence] = name
|
|
|
|
def add_bindings(self, name, sequences):
|
|
|
|
if self.window is None:
|
|
|
|
return
|
|
|
|
for sequence in sequences:
|
|
|
|
self.add_binding(name, sequence)
|
|
|
|
def del_binding(self, sequence):
|
|
|
|
if self.window is None:
|
|
|
|
return
|
|
|
|
del self.bindings[sequence]
|
|
|
|
def add_action_and_bindings(self, action, sequences):
|
|
|
|
if self.window is None:
|
|
|
|
return
|
|
|
|
self.add_action(action)
|
|
|
|
for sequence in sequences:
|
|
|
|
self.add_binding(action.name, sequence)
|
|
|
|
|
|
|
|
def handle_token(self, t):
|
|
|
|
'''self.handle_token(token): returns None, or the action to
|
|
|
|
take. raises an exception on unknown input'''
|
|
|
|
self.curr_tokens.append(t)
|
|
|
|
sequence = " ".join(self.curr_tokens)
|
|
|
|
if sequence in self.bindings:
|
|
|
|
act = self.window.application.methods[self.bindings[sequence]]
|
|
|
|
self.last_sequence = sequence
|
|
|
|
self.curr_tokens = []
|
|
|
|
return act
|
|
|
|
elif t in self.prefixes:
|
|
|
|
for binding in self.bindings:
|
|
|
|
if binding.startswith(sequence):
|
|
|
|
return None
|
|
|
|
self.curr_tokens = []
|
|
|
|
self.last_sequence = sequence
|
2008-05-16 19:02:22 -04:00
|
|
|
raise ActionError("no action defined for %r" % (sequence))
|
2007-10-21 20:55:29 -04:00
|
|
|
|
|
|
|
class Fundamental(Handler):
|
|
|
|
'''This is the default mode'''
|
2009-03-17 15:24:10 -04:00
|
|
|
name = "Fundamental"
|
2008-11-08 10:30:04 -05:00
|
|
|
paths = []
|
|
|
|
basenames = []
|
|
|
|
extensions = []
|
|
|
|
detection = []
|
|
|
|
savetabs = False
|
|
|
|
tabwidth = 4
|
|
|
|
tabbercls = None
|
|
|
|
grammar = None
|
|
|
|
lexer = None
|
|
|
|
tabber = None
|
|
|
|
context = None
|
|
|
|
colors = {}
|
|
|
|
word_letters = None
|
2009-02-15 12:06:35 -05:00
|
|
|
commentc = None
|
2008-10-15 17:17:16 -04:00
|
|
|
|
|
|
|
# config settings installed/modified by the mode
|
|
|
|
config = {}
|
|
|
|
dconfig = {}
|
|
|
|
lconfig = {}
|
|
|
|
sconfig = {}
|
|
|
|
|
2008-04-18 23:32:08 -04:00
|
|
|
actions = []
|
2009-02-15 12:06:35 -05:00
|
|
|
_bindings = {}
|
2008-04-25 10:20:40 -04:00
|
|
|
completers = {}
|
2009-04-06 11:21:43 -04:00
|
|
|
format = "%(flag)s %(bname)s (%(mname)s) %(indent)s %(cursor)s %(perc)s %(vc-info)s"
|
2007-10-21 20:55:29 -04:00
|
|
|
|
2009-02-05 12:12:52 -05:00
|
|
|
header_size = 3
|
|
|
|
header_fg = 'default'
|
|
|
|
header_bg = 'blue'
|
|
|
|
|
2009-01-31 22:34:43 -05:00
|
|
|
## margins
|
2009-02-05 10:21:24 -05:00
|
|
|
def _get_header(self): return self.get_setting('header')
|
|
|
|
def _set_header(self, value): return self.set_setting('header', value)
|
|
|
|
header = property(_get_header, _set_header)
|
|
|
|
def _get_footer(self): return self.get_setting('footer')
|
|
|
|
def _set_footer(self, value): return self.set_setting('footer', value)
|
|
|
|
footer = property(_get_footer, _set_footer)
|
|
|
|
def _get_lmargin(self): return self.get_setting('lmargin')
|
|
|
|
def _set_lmargin(self, value): return self.set_setting('lmargin', value)
|
|
|
|
lmargin = property(_get_lmargin, _set_lmargin)
|
|
|
|
def _get_rmargin(self): return self.get_setting('rmargin')
|
|
|
|
def _set_rmargin(self, value): return self.set_setting('rmargin', value)
|
|
|
|
rmargin = property(_get_rmargin, _set_rmargin)
|
2008-04-06 22:31:13 -04:00
|
|
|
|
2007-10-21 20:55:29 -04:00
|
|
|
def install(cls, app):
|
2009-03-17 15:24:10 -04:00
|
|
|
app.setmode(cls.name.lower(), cls, paths=cls.paths,
|
2008-11-08 12:44:59 -05:00
|
|
|
bases=cls.basenames, exts=cls.extensions,
|
2007-10-21 20:55:29 -04:00
|
|
|
detection=cls.detection)
|
2008-03-16 01:23:14 -04:00
|
|
|
for (key, val) in cls.colors.iteritems():
|
|
|
|
if key in app.token_colors:
|
2009-03-17 15:24:10 -04:00
|
|
|
s = 'token_colors: name %r conflict in %r' % (key, cls.name)
|
2008-03-16 11:39:17 -04:00
|
|
|
raise Exception, s
|
2008-03-16 01:23:14 -04:00
|
|
|
else:
|
|
|
|
app.token_colors[key] = val
|
2008-10-15 17:17:16 -04:00
|
|
|
|
|
|
|
# install configuration stuff
|
2008-12-02 15:21:28 -05:00
|
|
|
for (key, val) in cls.config.iteritems():
|
|
|
|
assert key not in app.config, "config conflict: %r" % key
|
|
|
|
app.config[key] = val
|
2008-10-15 17:17:16 -04:00
|
|
|
for (key, val) in cls.lconfig.iteritems():
|
|
|
|
app.config.setdefault(key, [])
|
|
|
|
for val2 in val:
|
|
|
|
app.config[key].append(val2)
|
|
|
|
for (key, val) in cls.sconfig.iteritems():
|
2008-11-08 10:30:04 -05:00
|
|
|
app.config.setdefault(key, set())
|
2008-10-15 17:17:16 -04:00
|
|
|
app.config[key].add(val)
|
|
|
|
for (key, d) in cls.dconfig.iteritems():
|
|
|
|
app.config.setdefault(key, {})
|
|
|
|
for (subkey, val) in d.iteritems():
|
|
|
|
app.config[key][subkey] = val
|
|
|
|
|
2008-04-18 23:32:08 -04:00
|
|
|
for mcls in cls.actions:
|
2008-04-17 10:34:32 -04:00
|
|
|
m = mcls()
|
|
|
|
if m.name in app.methods:
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
app.methods[m.name] = m
|
2009-02-15 12:06:35 -05:00
|
|
|
|
2008-04-25 10:20:40 -04:00
|
|
|
for (datatype, completer) in cls.completers.iteritems():
|
|
|
|
app.set_completer(datatype, completer)
|
2007-10-21 20:55:29 -04:00
|
|
|
install = classmethod(install)
|
|
|
|
|
|
|
|
def __init__(self, w):
|
2008-03-16 01:23:14 -04:00
|
|
|
assert w is not None
|
2007-10-21 20:55:29 -04:00
|
|
|
self.window = w
|
|
|
|
Handler.__init__(self)
|
|
|
|
|
2009-01-31 22:34:43 -05:00
|
|
|
#xyz
|
|
|
|
self.init_setting('lmargin', 0)
|
|
|
|
self.init_setting('rmargin', 1)
|
|
|
|
self.init_setting('header', 0)
|
|
|
|
self.init_setting('footer', 0)
|
|
|
|
|
2007-10-21 20:55:29 -04:00
|
|
|
# first let's add all the "default" actions
|
|
|
|
self.add_bindings('start-of-line', ('C-a', 'HOME',))
|
|
|
|
self.add_bindings('end-of-line', ('C-e', 'END',))
|
|
|
|
self.add_bindings('backward', ('C-b', 'L_ARROW',))
|
|
|
|
self.add_bindings('forward', ('C-f', 'R_ARROW',))
|
|
|
|
self.add_bindings('center-view', ('C-l',))
|
|
|
|
self.add_bindings('next-line', ('C-n', 'D_ARROW',))
|
|
|
|
self.add_bindings('previous-line', ('C-p', 'U_ARROW',))
|
|
|
|
self.add_bindings('next-section', ('M-n', 'M-D_ARROW',))
|
|
|
|
self.add_bindings('previous-section', ('M-p', 'M-U_ARROW',))
|
|
|
|
self.add_bindings('page-down', ('C-v', 'PG_DN',))
|
|
|
|
self.add_bindings('page-up', ('M-v', 'PG_UP',))
|
|
|
|
self.add_bindings('goto-beginning', ('M-<',))
|
|
|
|
self.add_bindings('goto-end', ('M->',))
|
|
|
|
self.add_bindings('delete-left', ('DELETE', 'BACKSPACE',))
|
|
|
|
self.add_bindings('delete-left-word', ('M-DELETE', 'M-BACKSPACE',))
|
|
|
|
self.add_bindings('delete-right', ('C-d',))
|
|
|
|
self.add_bindings('delete-right-word', ('M-d',))
|
|
|
|
self.add_bindings('kill-region', ('C-w',))
|
|
|
|
self.add_bindings('copy-region', ('M-w',))
|
|
|
|
self.add_bindings('kill', ('C-k',))
|
|
|
|
self.add_bindings('copy', ('M-k',))
|
|
|
|
self.add_bindings('yank', ('C-y',))
|
|
|
|
self.add_bindings('pop-kill', ('M-y',))
|
|
|
|
self.add_bindings('right-word', ('M-f',))
|
|
|
|
self.add_bindings('left-word', ('M-b',))
|
|
|
|
self.add_bindings('set-mark', ('C-@',))
|
|
|
|
self.add_bindings('switch-buffer', ('C-x b',))
|
|
|
|
self.add_bindings('switch-mark', ('C-x C-x',))
|
|
|
|
self.add_bindings('undo', ('C-/', 'C-x u',))
|
|
|
|
self.add_bindings('redo', ('M-/', 'M-_', 'C-x r',))
|
|
|
|
self.add_bindings('goto-line', ('M-g',))
|
|
|
|
self.add_bindings('forward-chars', ('C-x M-c',))
|
|
|
|
self.add_bindings('forward-lines', ('C-x M-n',))
|
|
|
|
self.add_bindings('search', ('C-s',))
|
|
|
|
self.add_bindings('reverse-search', ('C-r',))
|
|
|
|
self.add_bindings('regex-search', ('M-C-s',))
|
|
|
|
self.add_bindings('regex-reverse-search', ('M-C-r',))
|
|
|
|
self.add_bindings('toggle-margins', ('M-m',))
|
|
|
|
self.add_bindings('replace', ('M-%',))
|
|
|
|
self.add_bindings('regex-replace', ('M-$',))
|
|
|
|
self.add_bindings('open-file', ('C-x C-f',))
|
|
|
|
self.add_bindings('kill-buffer', ('C-x k',))
|
|
|
|
self.add_bindings('list-buffers', ('C-x C-b',))
|
|
|
|
self.add_bindings('meta-x', ('M-x',))
|
|
|
|
self.add_bindings('wrap-line', ('M-q',))
|
|
|
|
self.add_bindings('transpose-words', ('M-t',))
|
|
|
|
self.add_bindings('save-buffer', ('C-x C-s',))
|
|
|
|
self.add_bindings('save-buffer-as', ('C-x C-w',))
|
|
|
|
self.add_bindings('relex-buffer', ('M-r',))
|
|
|
|
self.add_bindings('exit', ('C-x C-c',))
|
|
|
|
self.add_bindings('split-window', ('C-x s', 'C-x 2',))
|
|
|
|
self.add_bindings('unsplit-window', ('C-u s', 'C-x 1',))
|
|
|
|
self.add_bindings('toggle-window', ('C-x o',))
|
|
|
|
self.add_bindings('delete-left-whitespace', ('C-c DELETE', 'C-c BACKSPACE',))
|
|
|
|
self.add_bindings('delete-right-whitespace', ('C-c d',))
|
|
|
|
self.add_bindings('insert-space', ('SPACE',))
|
|
|
|
self.add_bindings('insert-tab', ('TAB',))
|
|
|
|
self.add_bindings('insert-newline', ('RETURN',))
|
|
|
|
self.add_bindings('comment-region', ('C-c #',))
|
|
|
|
self.add_bindings('uncomment-region', ('C-u C-c #',))
|
|
|
|
self.add_bindings('justify-right', ('C-c f',))
|
|
|
|
self.add_bindings('justify-left', ('C-c b',))
|
|
|
|
self.add_bindings('indent-block', ('C-c >',))
|
|
|
|
self.add_bindings('unindent-block', ('C-c <',))
|
2008-05-28 18:13:40 -04:00
|
|
|
self.add_bindings('token-complete', ('C-x TAB',))
|
2007-10-21 20:55:29 -04:00
|
|
|
self.add_bindings('open-aes-file', ('C-c a',))
|
|
|
|
self.add_bindings('open-console', ('M-e',))
|
2008-03-17 03:28:07 -04:00
|
|
|
self.add_bindings('show-bindings-buffer', ('C-c M-h',))
|
|
|
|
self.add_bindings('show-functions-buffer', ('C-c M-?',))
|
|
|
|
self.add_bindings('which-command', ('M-h',))
|
|
|
|
self.add_bindings('cmd-help-buffer', ('M-?',))
|
2007-10-21 20:55:29 -04:00
|
|
|
self.add_bindings('set-mode', ('C-x m',))
|
2008-06-10 14:29:19 -04:00
|
|
|
self.add_bindings('cancel', ('C-]', 'C-g',))
|
2008-03-17 03:16:15 -04:00
|
|
|
self.add_bindings('exec', ('C-c e', 'C-c !'))
|
2007-10-21 20:55:29 -04:00
|
|
|
self.add_bindings('grep', ('C-c g',))
|
2008-03-20 09:31:43 -04:00
|
|
|
self.add_bindings('pipe', ('C-c p', 'C-c |'))
|
2007-10-21 20:55:29 -04:00
|
|
|
self.add_bindings('view-buffer-parent', ('C-c .',))
|
2008-02-27 02:33:24 -05:00
|
|
|
self.add_bindings('insert-squotes', ('M-\'',))
|
|
|
|
self.add_bindings('insert-dquotes', ('M-"',))
|
2008-03-16 01:23:14 -04:00
|
|
|
self.add_bindings('get-token', ('C-c t',))
|
2008-04-06 22:31:13 -04:00
|
|
|
self.add_bindings('insert-text', ('C-c i',))
|
|
|
|
self.add_bindings('insert-text2', ('C-c M-i',))
|
|
|
|
self.add_bindings('insert-multiline-text', ('C-c m',))
|
2009-03-13 00:36:20 -04:00
|
|
|
self.add_bindings('increment', ('M-+', 'M-='))
|
2008-11-09 00:43:34 -05:00
|
|
|
self.add_bindings('decrement', ('M--',))
|
2007-10-21 20:55:29 -04:00
|
|
|
|
2008-11-20 16:27:52 -05:00
|
|
|
self.add_bindings('uppercase-word', ('M-u',))
|
|
|
|
self.add_bindings('lowercase-word', ('M-l',))
|
|
|
|
|
2009-03-13 00:36:20 -04:00
|
|
|
i = 31
|
|
|
|
|
2008-11-08 10:30:04 -05:00
|
|
|
# used for all word operations
|
|
|
|
if not self.word_letters:
|
2008-11-08 12:44:59 -05:00
|
|
|
self.word_letters = w.application.config['word_letters']
|
2008-11-08 10:30:04 -05:00
|
|
|
|
2007-10-21 20:55:29 -04:00
|
|
|
# create all the insert actions for the basic text input
|
2009-06-13 21:46:38 -04:00
|
|
|
for c in string.ascii_letters + string.digits + string.punctuation:
|
2007-10-21 20:55:29 -04:00
|
|
|
self.add_binding('insert-string-%s' % c, c)
|
|
|
|
|
2009-02-15 12:06:35 -05:00
|
|
|
# per-mode bindings
|
|
|
|
for (name, sequences) in self._bindings.iteritems():
|
|
|
|
self.add_bindings(name, sequences)
|
|
|
|
|
2007-10-21 20:55:29 -04:00
|
|
|
# lexing for highlighting, etc.
|
|
|
|
if self.grammar:
|
2008-03-28 09:44:39 -04:00
|
|
|
self.lexer = Lexer(self, self.grammar)
|
|
|
|
else:
|
|
|
|
self.lexer = None
|
|
|
|
self.gstack = {}
|
|
|
|
self.ghist = {}
|
2007-10-21 20:55:29 -04:00
|
|
|
|
|
|
|
# tab handling
|
|
|
|
if self.tabbercls:
|
|
|
|
self.tabber = self.tabbercls(self)
|
|
|
|
|
2009-01-31 22:34:43 -05:00
|
|
|
# buffer settings
|
|
|
|
def get_setting(self, name):
|
2009-03-17 15:24:10 -04:00
|
|
|
self.window.buffer.settings.setdefault(self.name, {})
|
|
|
|
return self.window.buffer.settings[self.name].get(name)
|
2009-01-31 22:34:43 -05:00
|
|
|
def init_setting(self, name, value):
|
2009-03-17 15:24:10 -04:00
|
|
|
self.window.buffer.settings.setdefault(self.name, {})
|
|
|
|
self.window.buffer.settings[self.name].setdefault(name, value)
|
2009-01-31 22:34:43 -05:00
|
|
|
def set_setting(self, name, value):
|
2009-03-17 15:24:10 -04:00
|
|
|
self.window.buffer.settings.setdefault(self.name, {})
|
|
|
|
self.window.buffer.settings[self.name][name] = value
|
2009-01-31 22:34:43 -05:00
|
|
|
|
2009-01-28 16:28:33 -05:00
|
|
|
# header
|
|
|
|
def showing_header(self):
|
|
|
|
return self.header != 0
|
2009-02-05 10:21:24 -05:00
|
|
|
def _enable_header(self):
|
2009-02-05 12:12:52 -05:00
|
|
|
self.header = self.header_size
|
2009-02-05 10:21:24 -05:00
|
|
|
def _disable_header(self):
|
2009-01-28 16:28:33 -05:00
|
|
|
self.header = 0
|
|
|
|
|
2009-02-05 10:21:24 -05:00
|
|
|
def enable_header(self):
|
|
|
|
self._enable_header()
|
|
|
|
self._slot_reset()
|
|
|
|
def disable_header(self):
|
|
|
|
self._disable_header()
|
|
|
|
self._slot_reset()
|
|
|
|
def _slot_reset(self):
|
|
|
|
w = self.window
|
|
|
|
slot = w.application.bufferlist.find_window_slot(w)
|
|
|
|
assert slot is not None
|
|
|
|
slot.reset()
|
|
|
|
|
2009-01-28 16:28:33 -05:00
|
|
|
# line numbers
|
|
|
|
def showing_line_numbers(self):
|
|
|
|
return self.lmargin != 0
|
2008-04-06 22:31:13 -04:00
|
|
|
def enable_line_numbers(self):
|
2008-04-07 15:27:35 -04:00
|
|
|
l = len(self.window.buffer.lines)
|
|
|
|
self.lmargin = int(math.log(l, 10)) + 3
|
2008-04-06 22:31:13 -04:00
|
|
|
def disable_line_numbers(self):
|
|
|
|
self.lmargin = 0
|
|
|
|
|
2009-01-28 16:28:33 -05:00
|
|
|
# headers and margins
|
2009-02-05 10:21:24 -05:00
|
|
|
def get_header(self):
|
2009-02-05 12:12:52 -05:00
|
|
|
fg, bg = self.header_fg, self.header_bg
|
2009-02-05 10:47:20 -05:00
|
|
|
|
|
|
|
if self.tabber is None:
|
|
|
|
s = "Header support is not available for this mode"
|
2009-03-06 11:39:47 -05:00
|
|
|
hs = [[RenderString(s=s, attrs=color.build(fg, bg))]]
|
2009-02-05 10:47:20 -05:00
|
|
|
while len(hs) < 3:
|
2009-03-06 11:39:47 -05:00
|
|
|
hs.insert(0, [RenderString(s='', attrs=color.build(fg, bg))])
|
2009-02-05 10:47:20 -05:00
|
|
|
return hs
|
|
|
|
|
|
|
|
w = self.window
|
|
|
|
y = self.window.first.y
|
|
|
|
if self.window.first.x > 0:
|
|
|
|
y += 1
|
|
|
|
lvl = self.tabber.get_level(y)
|
|
|
|
markers = self.tabber.record[y]
|
|
|
|
if w.buffer.is_whitespace(y):
|
|
|
|
ws = None
|
|
|
|
else:
|
|
|
|
ws = w.buffer.count_leading_whitespace(y)
|
|
|
|
|
|
|
|
hs = []
|
|
|
|
i = len(markers) - 1
|
|
|
|
while i >= 0 and len(hs) < 3:
|
|
|
|
marker = markers[i]
|
|
|
|
i -= 1
|
|
|
|
if marker.y == y:
|
|
|
|
continue
|
|
|
|
if ws and marker.level > ws:
|
|
|
|
continue
|
|
|
|
s = w.buffer.lines[marker.y][:w.width - 1]
|
2009-03-06 11:39:47 -05:00
|
|
|
hs.insert(0, [RenderString(s=s, attrs=color.build(fg, bg))])
|
2009-02-05 10:47:20 -05:00
|
|
|
while len(hs) < 3:
|
2009-03-06 11:39:47 -05:00
|
|
|
hs.insert(0, [RenderString(s='', attrs=color.build(fg, bg))])
|
2009-02-05 10:47:20 -05:00
|
|
|
return hs
|
|
|
|
|
2009-02-05 10:21:24 -05:00
|
|
|
def get_footer(self):
|
2009-01-28 16:28:33 -05:00
|
|
|
fg, bg = "default", "red"
|
2009-03-06 11:39:47 -05:00
|
|
|
return [[RenderString(s='footer', attrs=color.build(fg, bg))]]
|
2008-04-20 23:10:25 -04:00
|
|
|
def get_rmargin(self, w, y, x, ended=False, cont=False):
|
|
|
|
c, fg, bg = " ", "red", "default"
|
2008-04-07 03:16:34 -04:00
|
|
|
if cont:
|
2008-04-20 23:10:25 -04:00
|
|
|
c = "\\"
|
2008-05-03 15:41:06 -04:00
|
|
|
return [RenderString(s=c, attrs=color.build(fg, bg))]
|
2008-04-20 23:10:25 -04:00
|
|
|
def get_lmargin(self, w, y, x, ended=False, cont=False):
|
2008-04-07 15:27:35 -04:00
|
|
|
lm = self.lmargin
|
2008-04-07 03:16:34 -04:00
|
|
|
if ended:
|
|
|
|
i = int(math.log(y, 10)) + 1
|
2008-04-07 15:27:35 -04:00
|
|
|
s = ('% *s' % (lm - 1, '-' * i))[-lm:] + ' '
|
2008-04-20 23:10:25 -04:00
|
|
|
elif not cont:
|
2008-04-07 15:27:35 -04:00
|
|
|
s = ('% *d' % (lm - 1, y + 1))[-lm:] + ' '
|
2008-04-07 03:16:34 -04:00
|
|
|
else:
|
2008-04-07 15:27:35 -04:00
|
|
|
s = ' ' * lm
|
2008-05-03 15:41:06 -04:00
|
|
|
return [RenderString(s=s, attrs=color.build('default', 'default', 'bold'))]
|
2008-04-06 22:31:13 -04:00
|
|
|
|
2008-05-09 15:01:59 -04:00
|
|
|
def _get_flag(self):
|
|
|
|
b = self.window.buffer
|
|
|
|
if b.readonly():
|
|
|
|
if b.changed():
|
|
|
|
return '%*'
|
|
|
|
else:
|
|
|
|
return '%%'
|
|
|
|
else:
|
|
|
|
if b.changed():
|
|
|
|
return '**'
|
|
|
|
else:
|
|
|
|
return '--'
|
|
|
|
def _get_perc(self):
|
|
|
|
w = self.window
|
|
|
|
if w.first_is_visible():
|
|
|
|
return "Top"
|
|
|
|
elif w.last_is_visible():
|
|
|
|
return "Bot"
|
|
|
|
else:
|
|
|
|
return "%2d%%" % (w.first.y*100 / len(w.buffer.lines))
|
2008-09-20 10:54:54 -04:00
|
|
|
def _get_indent(self):
|
|
|
|
b = self.window.buffer
|
|
|
|
if b.writetabs:
|
2009-01-24 13:54:04 -05:00
|
|
|
t = 't'
|
2008-09-20 10:54:54 -04:00
|
|
|
else:
|
2009-01-24 13:54:04 -05:00
|
|
|
t = 's'
|
2008-09-20 10:54:54 -04:00
|
|
|
return '%d%s' % (b.indentlvl, t)
|
2008-05-09 15:01:59 -04:00
|
|
|
def _get_mark(self):
|
|
|
|
w = self.window
|
|
|
|
if w.mark:
|
|
|
|
return '(%d,%d)' % (w.mark.y + 1, w.mark.x + 1)
|
|
|
|
else:
|
|
|
|
return '(None)'
|
|
|
|
def get_status_names(self):
|
|
|
|
w = self.window
|
|
|
|
c = w.logical_cursor()
|
2009-03-04 14:44:41 -05:00
|
|
|
d = defaultdict(str)
|
|
|
|
d2 = {
|
2008-05-09 15:01:59 -04:00
|
|
|
'bname': w.buffer.name(),
|
2009-03-17 15:24:10 -04:00
|
|
|
'mname': self.name,
|
2008-05-09 15:01:59 -04:00
|
|
|
'flag': self._get_flag(),
|
|
|
|
'perc': self._get_perc(),
|
2008-09-20 10:54:54 -04:00
|
|
|
'indent': self._get_indent(),
|
2008-05-09 15:01:59 -04:00
|
|
|
'cursor': '(%d,%d)' % (c.y + 1, c.x + 1),
|
2009-03-04 14:44:41 -05:00
|
|
|
'first': '(%d,%d)' % (w.first.y + 1, w.first.x + 1),
|
2008-05-09 15:01:59 -04:00
|
|
|
'mark': self._get_mark(),
|
|
|
|
}
|
2009-03-04 14:44:41 -05:00
|
|
|
d.update(d2)
|
|
|
|
d.update(dict(w.buffer.metadata))
|
2008-09-20 10:54:54 -04:00
|
|
|
return d
|
2008-05-09 15:01:59 -04:00
|
|
|
def get_status_bar(self):
|
|
|
|
names = self.get_status_names()
|
|
|
|
return self.format % names
|
|
|
|
|
2007-10-21 20:55:29 -04:00
|
|
|
# handle input tokens
|
|
|
|
def handle_token(self, t):
|
|
|
|
'''self.handle_token(token): handles input "token"'''
|
|
|
|
self.window.active_point = None
|
|
|
|
self.window.clear_error()
|
|
|
|
try:
|
|
|
|
act = Handler.handle_token(self, t)
|
|
|
|
if act is None:
|
2009-04-13 00:22:59 -04:00
|
|
|
self.window.set_msg(' '.join(self.curr_tokens))
|
2007-10-21 20:55:29 -04:00
|
|
|
return
|
|
|
|
else:
|
|
|
|
act.execute(self.window)
|
2009-03-19 00:23:09 -04:00
|
|
|
self.window.application.post_action_hook(act)
|
|
|
|
#self.window.application.last_action = act.name
|
2007-10-21 20:55:29 -04:00
|
|
|
except ActionError, e:
|
2008-06-10 14:29:19 -04:00
|
|
|
#XYZ: HACK--should fix
|
2008-11-08 10:30:04 -05:00
|
|
|
if t in ('C-]', 'C-g'):
|
2009-04-13 00:22:59 -04:00
|
|
|
self.window.set_msg('Cancelled')
|
2008-11-08 10:30:04 -05:00
|
|
|
else:
|
|
|
|
self.window.set_error(str(e))
|
2007-10-21 20:55:29 -04:00
|
|
|
except Exception, e:
|
|
|
|
if DEBUG:
|
|
|
|
raise
|
|
|
|
else:
|
2009-03-25 21:21:13 -04:00
|
|
|
self.window.set_error(str(e))
|
2007-10-21 20:55:29 -04:00
|
|
|
|
|
|
|
def region_added(self, p, newlines):
|
2009-03-17 15:24:10 -04:00
|
|
|
mname = self.name
|
2009-03-24 17:23:55 -04:00
|
|
|
|
2008-05-11 19:40:06 -04:00
|
|
|
if self.lexer is not None:
|
2007-10-21 20:55:29 -04:00
|
|
|
ydelta = len(newlines) - 1
|
|
|
|
xdelta = len(newlines[-1])
|
|
|
|
ghist = {}
|
|
|
|
for name in self.ghist:
|
|
|
|
for gp in self.ghist[name]:
|
|
|
|
if gp < p:
|
|
|
|
newp = gp
|
|
|
|
elif ydelta == 0:
|
|
|
|
if p.y == gp.y:
|
|
|
|
newp = Point(gp.x + xdelta, gp.y)
|
|
|
|
else:
|
|
|
|
newp = gp
|
|
|
|
else:
|
|
|
|
if gp.y == p.y:
|
|
|
|
newp = Point(gp.x + xdelta, gp.y + ydelta)
|
|
|
|
else:
|
|
|
|
newp = Point(gp.x, gp.y + ydelta)
|
|
|
|
ghist.setdefault(name, {})
|
|
|
|
ghist[name][newp] = self.ghist[name][gp]
|
|
|
|
self.ghist = ghist
|
2009-03-24 17:23:55 -04:00
|
|
|
|
2007-10-21 20:55:29 -04:00
|
|
|
if self.tabber is not None:
|
2008-05-11 19:40:06 -04:00
|
|
|
self.tabber.region_added(p, newlines)
|
|
|
|
if self.context is not None:
|
|
|
|
self.context.region_added(p, newlines)
|
|
|
|
|
|
|
|
def region_removed(self, p1, p2):
|
|
|
|
if self.lexer is not None:
|
2007-10-21 20:55:29 -04:00
|
|
|
ydelta = p2.y - p1.y
|
|
|
|
xdelta = p2.x - p1.x
|
|
|
|
ghist = {}
|
|
|
|
for name in self.ghist:
|
|
|
|
for gp in self.ghist[name]:
|
|
|
|
if gp < p1:
|
|
|
|
newp = gp
|
|
|
|
elif p1 <= gp and gp < p2:
|
|
|
|
continue
|
|
|
|
elif ydelta == 0:
|
|
|
|
if gp.y == p2.y:
|
|
|
|
newp = Point(gp.x - xdelta, gp.y)
|
|
|
|
else:
|
|
|
|
newp = gp
|
|
|
|
else:
|
|
|
|
if gp.y == p2.y:
|
|
|
|
newp = Point(gp.x - xdelta, gp.y - ydelta)
|
|
|
|
else:
|
|
|
|
newp = Point(gp.x, gp.y - ydelta)
|
|
|
|
ghist.setdefault(name, {})
|
|
|
|
ghist[name][newp] = self.ghist[name][gp]
|
|
|
|
self.ghist = ghist
|
2008-05-11 19:40:06 -04:00
|
|
|
if self.tabber is not None:
|
|
|
|
self.tabber.region_removed(p1, p2)
|
|
|
|
if self.context is not None:
|
|
|
|
self.context.region_removed(p1, p2)
|
|
|
|
|
2007-10-21 20:55:29 -04:00
|
|
|
install = Fundamental.install
|