parent
b9d304e2c7
commit
dddfa7a347
|
@ -143,6 +143,7 @@ class Application(object):
|
|||
# buffer list stuff
|
||||
self.bufferlist = bufferlist.BufferList(height, width)
|
||||
self.active_slot = 0
|
||||
self.complete_slot = None
|
||||
|
||||
# run user custom code here
|
||||
self.rcerror = None
|
||||
|
@ -199,6 +200,70 @@ class Application(object):
|
|||
curses.nonl()
|
||||
curses.def_prog_mode()
|
||||
|
||||
def completion_window_is_open(self):
|
||||
n = self.complete_slot
|
||||
if n is None:
|
||||
pass
|
||||
elif n >= len(self.bufferlist.slots):
|
||||
self.complete_slot = None
|
||||
elif self.bufferlist.slots[n].window is None:
|
||||
self.complete_slot = None
|
||||
elif not hasattr(self.bufferlist.slots[n].window.buffer, '_completion'):
|
||||
self.complete_slot = None
|
||||
else:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_completion_window(self):
|
||||
return self.bufferlist.slots[self.complete_slot].window
|
||||
|
||||
def open_completion_buffer(self, s, candidates):
|
||||
opened = False
|
||||
previous = None
|
||||
if len(self.bufferlist.slots) == 1:
|
||||
self.add_slot()
|
||||
opened = True
|
||||
|
||||
n = len(self.bufferlist.slots) - 1
|
||||
if self.active_slot == n:
|
||||
n -= 1
|
||||
|
||||
if not opened:
|
||||
previous = self.bufferlist.slots[n].window.buffer
|
||||
|
||||
lines = ["This is a completion buffer:", ""]
|
||||
if len(candidates) > self.bufferlist.slots[n].height:
|
||||
m = len(candidates) - (len(candidates) // 2)
|
||||
mlen = 0
|
||||
for c in candidates[:m]:
|
||||
mlen = max(mlen, len(c))
|
||||
for i in range(0, m):
|
||||
if m + i < len(candidates):
|
||||
c1, c2 = candidates[i * 2], candidates[i * 2 + 1]
|
||||
lines.append("%-*s %-s" % (mlen, c1, c2))
|
||||
else:
|
||||
lines.append(candidates[i * 2])
|
||||
else:
|
||||
lines = list(candidates)
|
||||
data = '\n'.join(lines)
|
||||
|
||||
b = self.data_buffer("*Completions*", data, switch_to=False)
|
||||
b._completion = s
|
||||
b._opened = opened
|
||||
b._previous = previous
|
||||
self.bufferlist.set_slot(n, b)
|
||||
self.complete_slot = n
|
||||
|
||||
def close_completion_buffer(self):
|
||||
w = self.get_completion_window()
|
||||
opened = w.buffer._opened
|
||||
if opened:
|
||||
self.bufferlist.remove_slot(self.complete_slot)
|
||||
else:
|
||||
self.bufferlist.set_slot(self.complete_slot, w.buffer._previous)
|
||||
self.close_buffer(w.buffer)
|
||||
self.complete_slot = None
|
||||
|
||||
def set_completer(self, datatype, completer):
|
||||
method.DATATYPES[datatype] = completer
|
||||
|
||||
|
@ -246,6 +311,17 @@ class Application(object):
|
|||
return (slot.height, slot.width)
|
||||
|
||||
# files and stuff
|
||||
def close_buffer(self, b):
|
||||
self.bufferlist.remove_buffer(b)
|
||||
b.close()
|
||||
active_slot = self.bufferlist.slots[self.active_slot]
|
||||
for i in range(0, len(self.bufferlist.slots)):
|
||||
if self.bufferlist.slots[i].is_empty():
|
||||
if self.bufferlist.hidden_buffers:
|
||||
self.bufferlist.set_slot(i, self.bufferlist.hidden_buffers[0])
|
||||
else:
|
||||
self.bufferlist.set_slot(i, active_slot.window.buffer)
|
||||
|
||||
def open_path(self, path, binary=False, cipher=None, password=None):
|
||||
path = os.path.abspath(os.path.realpath(util.expand_tilde(path)))
|
||||
b = self.get_buffer_by_path(path)
|
||||
|
@ -369,6 +445,7 @@ class Application(object):
|
|||
self.add_buffer(b)
|
||||
if switch_to:
|
||||
self.switch_buffer(b)
|
||||
return b
|
||||
def color_data_buffer(self, name, data, switch_to=True, modename='colortext'):
|
||||
if self.has_buffer_name(name):
|
||||
b = self.bufferlist.buffer_names[name]
|
||||
|
|
|
@ -125,6 +125,11 @@ class BufferList(object):
|
|||
if hasattr(b, 'path') and b.path == path:
|
||||
return b
|
||||
return None
|
||||
def close_buffer(self, b):
|
||||
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)
|
||||
def remove_buffer(self, b):
|
||||
assert b in self.buffers, "buffer %s does not exist" % (b.name())
|
||||
for i in range(0, len(self.slots)):
|
||||
|
|
|
@ -809,6 +809,8 @@ class Cancel(Method):
|
|||
'''Cancel command in-progress, and return to the main buffer'''
|
||||
def execute(self, w, **vargs):
|
||||
w.application.close_mini_buffer()
|
||||
if w.application.completion_window_is_open():
|
||||
w.application.close_completion_buffer()
|
||||
w.set_error('Cancel')
|
||||
|
||||
class SplitWindow(Method):
|
||||
|
|
|
@ -70,10 +70,7 @@ class KillBuffer(Method):
|
|||
def _doit(self):
|
||||
a = self._old_window.application
|
||||
b = self._to_kill
|
||||
if a.bufferlist.is_buffer_visible(b):
|
||||
a.bufferlist.set_slot(a.active_slot, a.bufferlist.hidden_buffers[0])
|
||||
a.bufferlist.remove_buffer(b)
|
||||
b.close()
|
||||
a.close_buffer(b)
|
||||
def _callback(self, v):
|
||||
a = self._old_window.application
|
||||
if v == 'yes':
|
||||
|
|
61
mode/mini.py
61
mode/mini.py
|
@ -1,25 +1,70 @@
|
|||
import method, mode
|
||||
import string
|
||||
import buffer, method, mode, window
|
||||
|
||||
class MiniInsertString(method.InsertString):
|
||||
_is_method = False
|
||||
def __init__(self, s):
|
||||
method.InsertString.__init__(self, s)
|
||||
self.name = "mini-insert-string-%s" % s
|
||||
def _execute(self, w, **vargs):
|
||||
try:
|
||||
app = w.application
|
||||
w.insert_string_at_cursor(self.string)
|
||||
if app.completion_window_is_open():
|
||||
app.close_completion_buffer()
|
||||
except buffer.ReadOnlyError:
|
||||
w.set_error('Buffer is read-only')
|
||||
|
||||
class MiniInsertSpace(method.Method):
|
||||
def _execute(self, w, **vargs):
|
||||
try:
|
||||
app = w.application
|
||||
w.insert_string_at_cursor(' ')
|
||||
if app.completion_window_is_open():
|
||||
app.close_completion_buffer()
|
||||
except buffer.ReadOnlyError:
|
||||
w.set_error('Buffer is read-only')
|
||||
|
||||
class MiniCallback(method.Method):
|
||||
def execute(self, window, **vargs):
|
||||
window.buffer.do_callback()
|
||||
def execute(self, w, **vargs):
|
||||
app = w.application
|
||||
if app.completion_window_is_open():
|
||||
app.close_completion_buffer()
|
||||
w.buffer.do_callback()
|
||||
|
||||
class MiniTabComplete(method.Method):
|
||||
def execute(self, window, **vargs):
|
||||
b = window.buffer
|
||||
def execute(self, w, **vargs):
|
||||
app = w.application
|
||||
b = w.buffer
|
||||
if b.tabber is None:
|
||||
window.application.set_error("No tab completion")
|
||||
w.application.set_error("No tab completion")
|
||||
return
|
||||
s1 = b.make_string()
|
||||
s2, exists, complete = b.tabber.tab_string(s1, window)
|
||||
s2, exists, complete = b.tabber.tab_string(s1, w)
|
||||
b.set_data(s2)
|
||||
|
||||
if app.completion_window_is_open():
|
||||
w2 = app.get_completion_window()
|
||||
if w2.last_is_visible():
|
||||
w2.goto_beginning()
|
||||
else:
|
||||
w2.page_down()
|
||||
else:
|
||||
candidates = sorted(b.tabber.get_candidates(s1))
|
||||
if len(candidates) > 1:
|
||||
app.open_completion_buffer(s2, candidates)
|
||||
|
||||
class Mini(mode.Fundamental):
|
||||
modename = 'Mini'
|
||||
actions = [MiniCallback, MiniTabComplete]
|
||||
actions = [MiniCallback, MiniTabComplete, MiniInsertSpace]
|
||||
def __init__(self, w):
|
||||
mode.Fundamental.__init__(self, w)
|
||||
self.add_bindings('mini-callback', ('RETURN',))
|
||||
self.add_bindings('mini-tab-complete', ('TAB',))
|
||||
|
||||
# create all the insert actions for the basic text input
|
||||
for c in string.letters + string.digits + string.punctuation:
|
||||
self.add_action_and_bindings(MiniInsertString(c), (c,))
|
||||
self.add_bindings('mini-insert-space', ('SPACE',))
|
||||
|
||||
install = Mini.install
|
||||
|
|
|
@ -73,7 +73,7 @@ def find(r, w, move=False, direction='next', start=None, end=None):
|
|||
break
|
||||
if newc:
|
||||
w.goto(newc[0])
|
||||
else:
|
||||
elif ranges:
|
||||
i = 0
|
||||
if direction == 'next':
|
||||
i = -1
|
||||
|
|
Loading…
Reference in New Issue