mirror of
https://github.com/wassname/pyreadline.git
synced 2026-06-27 16:10:38 +08:00
pyreadline-refactor: Added vi-mode patch, a lot of work remains.
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
2006-03-16 Jörgen Stenarson <jorgen.stenarson -at- bostream.nu>
|
||||
* Added vi patch
|
||||
|
||||
2006-03-16 Jörgen Stenarson <jorgen.stenarson -at- bostream.nu>
|
||||
* Refactored emacs mode
|
||||
|
||||
|
||||
@@ -522,11 +522,14 @@ class Console(object):
|
||||
else:
|
||||
return (info.dwSize.X, info.dwSize.Y)
|
||||
|
||||
def cursor(self, visible):
|
||||
def cursor(self, visible=None, size=None):
|
||||
'''Set cursor on or off.'''
|
||||
info = CONSOLE_CURSOR_INFO()
|
||||
if self.GetConsoleCursorInfo(self.hout, byref(info)):
|
||||
info.bVisible = visible
|
||||
if visible is not None:
|
||||
info.bVisible = visible
|
||||
if size is not None:
|
||||
info.dwSize = size
|
||||
self.SetConsoleCursorInfo(self.hout, byref(info))
|
||||
|
||||
def bell(self):
|
||||
|
||||
@@ -151,6 +151,7 @@ class TextLine(object):
|
||||
self._point=0
|
||||
self.mark=-1
|
||||
self.undo_stack=[]
|
||||
self.overwrite=False
|
||||
if isinstance(txtstr,TextLine): #copy
|
||||
if point is None:
|
||||
self.point=txtstr.point
|
||||
@@ -243,9 +244,15 @@ class TextLine(object):
|
||||
self.point = 0
|
||||
|
||||
def _insert_text(self, text):
|
||||
for c in text:
|
||||
self.line_buffer.insert(self.point, c)
|
||||
self.point += 1
|
||||
if self.overwrite:
|
||||
for c in text:
|
||||
#if self.point:
|
||||
self.line_buffer[self.point]= c
|
||||
self.point += 1
|
||||
else:
|
||||
for c in text:
|
||||
self.line_buffer.insert(self.point, c)
|
||||
self.point += 1
|
||||
|
||||
def __getitem__(self,key):
|
||||
#Check if key is LineSlice, convert to regular slice
|
||||
@@ -318,11 +325,14 @@ class TextLine(object):
|
||||
value=TextLine(value).line_buffer
|
||||
self.line_buffer=prev+value+rest
|
||||
|
||||
def __len__(self):
|
||||
return len(self.line_buffer)
|
||||
|
||||
def upper(self):
|
||||
self.line_buffer=self.line_buffer.upper()
|
||||
self.line_buffer=[x.upper() for x in self.line_buffer]
|
||||
|
||||
def lower(self):
|
||||
self.line_buffer=self.line_buffer.lower()
|
||||
self.line_buffer=[x.lower() for x in self.line_buffer]
|
||||
|
||||
def startswith(self,txt):
|
||||
return self.get_line_text().startswith(txt)
|
||||
@@ -523,4 +533,4 @@ if __name__=="__main__":
|
||||
[]
|
||||
print '%-15s "%s"'%(name,show_pos(q,pos,"^"))
|
||||
|
||||
|
||||
l=TextLine("kjjk")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
__all__=["emacs","notemacs"]
|
||||
import emacs,notemacs
|
||||
editingmodes=[emacs.EmacsMode,notemacs.NotEmacsMode]
|
||||
__all__=["emacs","notemacs","vi"]
|
||||
import emacs,notemacs,vi
|
||||
editingmodes=[emacs.EmacsMode,notemacs.NotEmacsMode,vi.ViMode]
|
||||
|
||||
#add check to ensure all modes have unique mode names
|
||||
@@ -0,0 +1,264 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#*****************************************************************************
|
||||
# Copyright (C) 2003-2006 Gary Bishop.
|
||||
# Copyright (C) 2006 Jorgen Stenarson. <jorgen.stenarson@bostream.nu>
|
||||
#
|
||||
# Distributed under the terms of the BSD License. The full license is in
|
||||
# the file COPYING, distributed as part of this software.
|
||||
#*****************************************************************************
|
||||
import os
|
||||
import pyreadline.logger as logger
|
||||
from pyreadline.logger import log
|
||||
from pyreadline.keysyms import key_text_to_keyinfo
|
||||
import pyreadline.lineeditor.lineobj as lineobj
|
||||
import pyreadline.lineeditor.history as history
|
||||
|
||||
class BaseMode(object):
|
||||
mode="base"
|
||||
def __init__(self,rlobj):
|
||||
self.rlobj=rlobj
|
||||
self.exit_dispatch = {}
|
||||
self.key_dispatch = {}
|
||||
self.startup_hook=None
|
||||
self.pre_input_hook=None
|
||||
|
||||
def __repr__(self):
|
||||
return "<BaseMode>"
|
||||
|
||||
def _gs(x):
|
||||
def g(self):
|
||||
return getattr(self.rlobj,x)
|
||||
def s(self,q):
|
||||
setattr(self.rlobj,x,q)
|
||||
return g,s
|
||||
|
||||
def _g(x):
|
||||
def g(self):
|
||||
return getattr(self.rlobj,x)
|
||||
return g
|
||||
|
||||
l_buffer=property(*_gs("l_buffer"))
|
||||
next_meta=property(*_gs("next_meta"))
|
||||
first_prompt=property(*_gs("first_prompt"))
|
||||
prompt=property(*_gs("prompt"))
|
||||
console=property(_g("console"))
|
||||
insert_text=property(_g("insert_text"))
|
||||
_print_prompt=property(_g("_print_prompt"))
|
||||
_update_line=property(_g("_update_line"))
|
||||
paste_line_buffer=property(_g("paste_line_buffer"))
|
||||
add_history=property(_g("add_history"))
|
||||
_bell=property(_g("_bell"))
|
||||
_clear_after=property(_g("_clear_after"))
|
||||
_set_cursor=property(_g("_set_cursor"))
|
||||
_print_prompt=property(_g("_print_prompt"))
|
||||
_update_prompt_pos=property(_g("_update_prompt_pos"))
|
||||
_update_line=property(_g("_update_line"))
|
||||
enable_win32_clipboard=property(_g("enable_win32_clipboard"))
|
||||
_bell=property(_g("_bell"))
|
||||
_history=property(_g("_history"))
|
||||
|
||||
def _readline_from_keyboard(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def readline(self, prompt=''):
|
||||
raise NotImplementedError
|
||||
|
||||
#Create key bindings:
|
||||
|
||||
def _bind_key(self, key, func):
|
||||
'''setup the mapping from key to call the function.'''
|
||||
keyinfo = key_text_to_keyinfo(key)
|
||||
# print key,keyinfo,func.__name__
|
||||
self.key_dispatch[keyinfo] = func
|
||||
|
||||
def _bind_exit_key(self, key):
|
||||
'''setup the mapping from key to call the function.'''
|
||||
keyinfo = key_text_to_keyinfo(key)
|
||||
self.exit_dispatch[keyinfo] = None
|
||||
|
||||
def init_editing_mode(self, e): # (C-e)
|
||||
'''When in vi command mode, this causes a switch to emacs editing
|
||||
mode.'''
|
||||
|
||||
raise NotImplementedError
|
||||
#completion commands
|
||||
|
||||
def _get_completions(self):
|
||||
|
||||
'''Return a list of possible completions for the string ending at the point.
|
||||
|
||||
Also set begidx and endidx in the process.'''
|
||||
completions = []
|
||||
self.begidx = self.l_buffer.point
|
||||
self.endidx = self.l_buffer.point
|
||||
buf=self.l_buffer.line_buffer
|
||||
if self.completer:
|
||||
# get the string to complete
|
||||
while self.begidx > 0:
|
||||
self.begidx -= 1
|
||||
if buf[self.begidx] in self.completer_delims:
|
||||
self.begidx += 1
|
||||
break
|
||||
text = ''.join(buf[self.begidx:self.endidx])
|
||||
log('complete text="%s"' % text)
|
||||
i = 0
|
||||
while 1:
|
||||
try:
|
||||
r = self.completer(text, i)
|
||||
except:
|
||||
break
|
||||
i += 1
|
||||
if r and r not in completions:
|
||||
completions.append(r)
|
||||
else:
|
||||
break
|
||||
log('text completions=%s' % completions)
|
||||
if not completions:
|
||||
# get the filename to complete
|
||||
while self.begidx > 0:
|
||||
self.begidx -= 1
|
||||
if buf[self.begidx] in ' \t\n':
|
||||
self.begidx += 1
|
||||
break
|
||||
text = ''.join(buf[self.begidx:self.endidx])
|
||||
log('file complete text="%s"' % text)
|
||||
completions = glob(os.path.expanduser(text) + '*')
|
||||
if self.mark_directories == 'on':
|
||||
mc = []
|
||||
for f in completions:
|
||||
if os.path.isdir(f):
|
||||
mc.append(f + os.sep)
|
||||
else:
|
||||
mc.append(f)
|
||||
completions = mc
|
||||
log('fnames=%s' % completions)
|
||||
return completions
|
||||
|
||||
|
||||
def _display_completions(self, completions):
|
||||
if not completions:
|
||||
return
|
||||
self.console.write('\n')
|
||||
wmax = max(map(len, completions))
|
||||
w, h = self.console.size()
|
||||
cols = max(1, int((w-1) / (wmax+1)))
|
||||
rows = int(math.ceil(float(len(completions)) / cols))
|
||||
for row in range(rows):
|
||||
s = ''
|
||||
for col in range(cols):
|
||||
i = col*rows + row
|
||||
if i < len(completions):
|
||||
self.console.write(completions[i].ljust(wmax+1))
|
||||
self.console.write('\n')
|
||||
self._print_prompt()
|
||||
|
||||
def complete(self, e): # (TAB)
|
||||
'''Attempt to perform completion on the text before point. The
|
||||
actual completion performed is application-specific. The default is
|
||||
filename completion.'''
|
||||
completions = self._get_completions()
|
||||
if completions:
|
||||
cprefix = commonprefix(completions)
|
||||
rep = [ c for c in cprefix ]
|
||||
self.l_buffer[self.begidx:self.endidx] = rep
|
||||
self.l_buffer.point += len(rep) - (self.endidx - self.begidx)
|
||||
if len(completions) > 1:
|
||||
if self.show_all_if_ambiguous == 'on':
|
||||
self._display_completions(completions)
|
||||
else:
|
||||
self._bell()
|
||||
else:
|
||||
self._bell()
|
||||
|
||||
def possible_completions(self, e): # (M-?)
|
||||
'''List the possible completions of the text before point. '''
|
||||
completions = self._get_completions()
|
||||
self._display_completions(completions)
|
||||
|
||||
def insert_completions(self, e): # (M-*)
|
||||
'''Insert all completions of the text before point that would have
|
||||
been generated by possible-completions.'''
|
||||
completions = self._get_completions()
|
||||
b = self.begidx
|
||||
e = self.endidx
|
||||
for comp in completions:
|
||||
rep = [ c for c in comp ]
|
||||
rep.append(' ')
|
||||
self.l_buffer[b:e] = rep
|
||||
b += len(rep)
|
||||
e = b
|
||||
self.line_cursor = b
|
||||
|
||||
def menu_complete(self, e): # ()
|
||||
'''Similar to complete, but replaces the word to be completed with a
|
||||
single match from the list of possible completions. Repeated
|
||||
execution of menu-complete steps through the list of possible
|
||||
completions, inserting each match in turn. At the end of the list of
|
||||
completions, the bell is rung (subject to the setting of bell-style)
|
||||
and the original text is restored. An argument of n moves n
|
||||
positions forward in the list of matches; a negative argument may be
|
||||
used to move backward through the list. This command is intended to
|
||||
be bound to TAB, but is unbound by default.'''
|
||||
pass
|
||||
|
||||
### Methods below here are bindable emacs functions
|
||||
|
||||
def beginning_of_line(self, e): # (C-a)
|
||||
'''Move to the start of the current line. '''
|
||||
self.l_buffer.beginning_of_line()
|
||||
|
||||
def end_of_line(self, e): # (C-e)
|
||||
'''Move to the end of the line. '''
|
||||
self.l_buffer.end_of_line()
|
||||
|
||||
def forward_char(self, e): # (C-f)
|
||||
'''Move forward a character. '''
|
||||
self.l_buffer.forward_char()
|
||||
|
||||
def backward_char(self, e): # (C-b)
|
||||
'''Move back a character. '''
|
||||
self.l_buffer.backward_char()
|
||||
|
||||
def forward_word(self, e): # (M-f)
|
||||
'''Move forward to the end of the next word. Words are composed of
|
||||
letters and digits.'''
|
||||
self.l_buffer.forward_word()
|
||||
|
||||
def backward_word(self, e): # (M-b)
|
||||
'''Move back to the start of the current or previous word. Words are
|
||||
composed of letters and digits.'''
|
||||
self.l_buffer.backward_word()
|
||||
|
||||
def clear_screen(self, e): # (C-l)
|
||||
'''Clear the screen and redraw the current line, leaving the current
|
||||
line at the top of the screen.'''
|
||||
self.console.page()
|
||||
|
||||
def redraw_current_line(self, e): # ()
|
||||
'''Refresh the current line. By default, this is unbound.'''
|
||||
pass
|
||||
|
||||
def accept_line(self, e): # (Newline or Return)
|
||||
'''Accept the line regardless of where the cursor is. If this line
|
||||
is non-empty, it may be added to the history list for future recall
|
||||
with add_history(). If this line is a modified history line, the
|
||||
history line is restored to its original state.'''
|
||||
return True
|
||||
|
||||
|
||||
def delete_char(self, e): # (C-d)
|
||||
'''Delete the character at point. If point is at the beginning of
|
||||
the line, there are no characters in the line, and the last
|
||||
character typed was not bound to delete-char, then return EOF.'''
|
||||
self.l_buffer.delete_char()
|
||||
|
||||
def backward_delete_char(self, e): # (Rubout)
|
||||
'''Delete the character behind the cursor. A numeric argument means
|
||||
to kill the characters instead of deleting them.'''
|
||||
self.l_buffer.backward_delete_char()
|
||||
|
||||
def self_insert(self, e): # (a, b, A, 1, !, ...)
|
||||
'''Insert yourself. '''
|
||||
if ord(e.char)!=0: #don't insert null character in buffer, can happen with dead keys.
|
||||
self.insert_text(e.char)
|
||||
|
||||
+4
-216
@@ -12,51 +12,16 @@ from pyreadline.logger import log
|
||||
from pyreadline.keysyms import key_text_to_keyinfo
|
||||
import pyreadline.lineeditor.lineobj as lineobj
|
||||
import pyreadline.lineeditor.history as history
|
||||
import basemode
|
||||
|
||||
class EmacsMode(object):
|
||||
class EmacsMode(basemode.BaseMode):
|
||||
mode="emacs"
|
||||
def __init__(self,rlobj):
|
||||
self.rlobj=rlobj
|
||||
self.exit_dispatch = {}
|
||||
self.key_dispatch = {}
|
||||
self.startup_hook=None
|
||||
self.pre_input_hook=None
|
||||
|
||||
super(EmacsMode,self).__init__(rlobj)
|
||||
|
||||
def __repr__(self):
|
||||
return "<EmacsMode>"
|
||||
|
||||
def _gs(x):
|
||||
def g(self):
|
||||
return getattr(self.rlobj,x)
|
||||
def s(self,q):
|
||||
setattr(self.rlobj,x,q)
|
||||
return g,s
|
||||
|
||||
def _g(x):
|
||||
def g(self):
|
||||
return getattr(self.rlobj,x)
|
||||
return g
|
||||
|
||||
l_buffer=property(*_gs("l_buffer"))
|
||||
next_meta=property(*_gs("next_meta"))
|
||||
first_prompt=property(*_gs("first_prompt"))
|
||||
prompt=property(*_gs("prompt"))
|
||||
console=property(_g("console"))
|
||||
insert_text=property(_g("insert_text"))
|
||||
_print_prompt=property(_g("_print_prompt"))
|
||||
_update_line=property(_g("_update_line"))
|
||||
paste_line_buffer=property(_g("paste_line_buffer"))
|
||||
add_history=property(_g("add_history"))
|
||||
_bell=property(_g("_bell"))
|
||||
_clear_after=property(_g("_clear_after"))
|
||||
_set_cursor=property(_g("_set_cursor"))
|
||||
_print_prompt=property(_g("_print_prompt"))
|
||||
_update_prompt_pos=property(_g("_update_prompt_pos"))
|
||||
_update_line=property(_g("_update_line"))
|
||||
enable_win32_clipboard=property(_g("enable_win32_clipboard"))
|
||||
_bell=property(_g("_bell"))
|
||||
_history=property(_g("_history"))
|
||||
|
||||
def _readline_from_keyboard(self):
|
||||
c=self.console
|
||||
while 1:
|
||||
@@ -124,50 +89,6 @@ class EmacsMode(object):
|
||||
log('returning(%s)' % self.l_buffer.get_line_text())
|
||||
return self.l_buffer.get_line_text() + '\n'
|
||||
|
||||
### Methods below here are bindable emacs functions
|
||||
|
||||
def beginning_of_line(self, e): # (C-a)
|
||||
'''Move to the start of the current line. '''
|
||||
self.l_buffer.beginning_of_line()
|
||||
|
||||
def end_of_line(self, e): # (C-e)
|
||||
'''Move to the end of the line. '''
|
||||
self.l_buffer.end_of_line()
|
||||
|
||||
def forward_char(self, e): # (C-f)
|
||||
'''Move forward a character. '''
|
||||
self.l_buffer.forward_char()
|
||||
|
||||
def backward_char(self, e): # (C-b)
|
||||
'''Move back a character. '''
|
||||
self.l_buffer.backward_char()
|
||||
|
||||
def forward_word(self, e): # (M-f)
|
||||
'''Move forward to the end of the next word. Words are composed of
|
||||
letters and digits.'''
|
||||
self.l_buffer.forward_word()
|
||||
|
||||
def backward_word(self, e): # (M-b)
|
||||
'''Move back to the start of the current or previous word. Words are
|
||||
composed of letters and digits.'''
|
||||
self.l_buffer.backward_word()
|
||||
|
||||
def clear_screen(self, e): # (C-l)
|
||||
'''Clear the screen and redraw the current line, leaving the current
|
||||
line at the top of the screen.'''
|
||||
self.console.page()
|
||||
|
||||
def redraw_current_line(self, e): # ()
|
||||
'''Refresh the current line. By default, this is unbound.'''
|
||||
pass
|
||||
|
||||
def accept_line(self, e): # (Newline or Return)
|
||||
'''Accept the line regardless of where the cursor is. If this line
|
||||
is non-empty, it may be added to the history list for future recall
|
||||
with add_history(). If this line is a modified history line, the
|
||||
history line is restored to its original state.'''
|
||||
return True
|
||||
|
||||
######### History commands
|
||||
def previous_history(self, e): # (C-p)
|
||||
'''Move back through the history list, fetching the previous command. '''
|
||||
@@ -283,17 +204,6 @@ class EmacsMode(object):
|
||||
the history list, inserting the last argument of each line in turn.'''
|
||||
pass
|
||||
|
||||
def delete_char(self, e): # (C-d)
|
||||
'''Delete the character at point. If point is at the beginning of
|
||||
the line, there are no characters in the line, and the last
|
||||
character typed was not bound to delete-char, then return EOF.'''
|
||||
self.l_buffer.delete_char()
|
||||
|
||||
def backward_delete_char(self, e): # (Rubout)
|
||||
'''Delete the character behind the cursor. A numeric argument means
|
||||
to kill the characters instead of deleting them.'''
|
||||
self.l_buffer.backward_delete_char()
|
||||
|
||||
def forward_backward_delete_char(self, e): # ()
|
||||
'''Delete the character under the cursor, unless the cursor is at
|
||||
the end of the line, in which case the character behind the cursor
|
||||
@@ -311,11 +221,6 @@ class EmacsMode(object):
|
||||
ws = ' ' * (self.tabstop - (self.line_cursor%self.tabstop))
|
||||
self.insert_text(ws)
|
||||
|
||||
def self_insert(self, e): # (a, b, A, 1, !, ...)
|
||||
'''Insert yourself. '''
|
||||
if ord(e.char)!=0: #don't insert null character in buffer, can happen with dead keys.
|
||||
self.insert_text(e.char)
|
||||
|
||||
def transpose_chars(self, e): # (C-t)
|
||||
'''Drag the character before the cursor forward over the character
|
||||
at the cursor, moving the cursor forward as well. If the insertion
|
||||
@@ -489,123 +394,6 @@ class EmacsMode(object):
|
||||
default, this is not bound to a key.'''
|
||||
pass
|
||||
|
||||
|
||||
def _get_completions(self):
|
||||
'''Return a list of possible completions for the string ending at the point.
|
||||
|
||||
Also set begidx and endidx in the process.'''
|
||||
completions = []
|
||||
self.begidx = self.l_buffer.point
|
||||
self.endidx = self.l_buffer.point
|
||||
buf=self.l_buffer.line_buffer
|
||||
if self.completer:
|
||||
# get the string to complete
|
||||
while self.begidx > 0:
|
||||
self.begidx -= 1
|
||||
if buf[self.begidx] in self.completer_delims:
|
||||
self.begidx += 1
|
||||
break
|
||||
text = ''.join(buf[self.begidx:self.endidx])
|
||||
log('complete text="%s"' % text)
|
||||
i = 0
|
||||
while 1:
|
||||
try:
|
||||
r = self.completer(text, i)
|
||||
except:
|
||||
break
|
||||
i += 1
|
||||
if r and r not in completions:
|
||||
completions.append(r)
|
||||
else:
|
||||
break
|
||||
log('text completions=%s' % completions)
|
||||
if not completions:
|
||||
# get the filename to complete
|
||||
while self.begidx > 0:
|
||||
self.begidx -= 1
|
||||
if buf[self.begidx] in ' \t\n':
|
||||
self.begidx += 1
|
||||
break
|
||||
text = ''.join(buf[self.begidx:self.endidx])
|
||||
log('file complete text="%s"' % text)
|
||||
completions = glob(os.path.expanduser(text) + '*')
|
||||
if self.mark_directories == 'on':
|
||||
mc = []
|
||||
for f in completions:
|
||||
if os.path.isdir(f):
|
||||
mc.append(f + os.sep)
|
||||
else:
|
||||
mc.append(f)
|
||||
completions = mc
|
||||
log('fnames=%s' % completions)
|
||||
return completions
|
||||
|
||||
def _display_completions(self, completions):
|
||||
if not completions:
|
||||
return
|
||||
self.console.write('\n')
|
||||
wmax = max(map(len, completions))
|
||||
w, h = self.console.size()
|
||||
cols = max(1, int((w-1) / (wmax+1)))
|
||||
rows = int(math.ceil(float(len(completions)) / cols))
|
||||
for row in range(rows):
|
||||
s = ''
|
||||
for col in range(cols):
|
||||
i = col*rows + row
|
||||
if i < len(completions):
|
||||
self.console.write(completions[i].ljust(wmax+1))
|
||||
self.console.write('\n')
|
||||
self._print_prompt()
|
||||
|
||||
def complete(self, e): # (TAB)
|
||||
'''Attempt to perform completion on the text before point. The
|
||||
actual completion performed is application-specific. The default is
|
||||
filename completion.'''
|
||||
completions = self._get_completions()
|
||||
if completions:
|
||||
cprefix = commonprefix(completions)
|
||||
rep = [ c for c in cprefix ]
|
||||
self.l_buffer[self.begidx:self.endidx] = rep
|
||||
self.l_buffer.point += len(rep) - (self.endidx - self.begidx)
|
||||
if len(completions) > 1:
|
||||
if self.show_all_if_ambiguous == 'on':
|
||||
self._display_completions(completions)
|
||||
else:
|
||||
self._bell()
|
||||
else:
|
||||
self._bell()
|
||||
|
||||
def possible_completions(self, e): # (M-?)
|
||||
'''List the possible completions of the text before point. '''
|
||||
completions = self._get_completions()
|
||||
self._display_completions(completions)
|
||||
|
||||
def insert_completions(self, e): # (M-*)
|
||||
'''Insert all completions of the text before point that would have
|
||||
been generated by possible-completions.'''
|
||||
completions = self._get_completions()
|
||||
b = self.begidx
|
||||
e = self.endidx
|
||||
for comp in completions:
|
||||
rep = [ c for c in comp ]
|
||||
rep.append(' ')
|
||||
self.l_buffer[b:e] = rep
|
||||
b += len(rep)
|
||||
e = b
|
||||
self.line_cursor = b
|
||||
|
||||
def menu_complete(self, e): # ()
|
||||
'''Similar to complete, but replaces the word to be completed with a
|
||||
single match from the list of possible completions. Repeated
|
||||
execution of menu-complete steps through the list of possible
|
||||
completions, inserting each match in turn. At the end of the list of
|
||||
completions, the bell is rung (subject to the setting of bell-style)
|
||||
and the original text is restored. An argument of n moves n
|
||||
positions forward in the list of matches; a negative argument may be
|
||||
used to move backward through the list. This command is intended to
|
||||
be bound to TAB, but is unbound by default.'''
|
||||
pass
|
||||
|
||||
def delete_char_or_list(self, e): # ()
|
||||
'''Deletes the character under the cursor if not at the beginning or
|
||||
end of the line (like delete-char). If at the end of the line,
|
||||
|
||||
@@ -12,53 +12,16 @@ from pyreadline.logger import log
|
||||
from pyreadline.keysyms import key_text_to_keyinfo
|
||||
import pyreadline.lineeditor.lineobj as lineobj
|
||||
import pyreadline.lineeditor.history as history
|
||||
import basemode
|
||||
|
||||
class NotEmacsMode(object):
|
||||
class NotEmacsMode(basemode.BaseMode):
|
||||
mode="notemacs"
|
||||
def __init__(self,rlobj):
|
||||
self.rlobj=rlobj
|
||||
self.exit_dispatch = {}
|
||||
self.key_dispatch = {}
|
||||
self.startup_hook=None
|
||||
self.pre_input_hook=None
|
||||
|
||||
super(NotEmacsMode,self).__init__(rlobj)
|
||||
|
||||
def __repr__(self):
|
||||
return "<NotEmacsMode>"
|
||||
|
||||
def _gs(x):
|
||||
def g(self):
|
||||
return getattr(self.rlobj,x)
|
||||
def s(self,q):
|
||||
setattr(self.rlobj,x,q)
|
||||
return g,s
|
||||
|
||||
def _g(x):
|
||||
def g(self):
|
||||
return getattr(self.rlobj,x)
|
||||
return g
|
||||
|
||||
l_buffer=property(*_gs("l_buffer"))
|
||||
next_meta=property(*_gs("next_meta"))
|
||||
first_prompt=property(*_gs("first_prompt"))
|
||||
prompt=property(*_gs("prompt"))
|
||||
console=property(_g("console"))
|
||||
insert_text=property(_g("insert_text"))
|
||||
_print_prompt=property(_g("_print_prompt"))
|
||||
_update_line=property(_g("_update_line"))
|
||||
paste_line_buffer=property(_g("paste_line_buffer"))
|
||||
add_history=property(_g("add_history"))
|
||||
_bell=property(_g("_bell"))
|
||||
_clear_after=property(_g("_clear_after"))
|
||||
_set_cursor=property(_g("_set_cursor"))
|
||||
_print_prompt=property(_g("_print_prompt"))
|
||||
_update_prompt_pos=property(_g("_update_prompt_pos"))
|
||||
_update_line=property(_g("_update_line"))
|
||||
enable_win32_clipboard=property(_g("enable_win32_clipboard"))
|
||||
_bell=property(_g("_bell"))
|
||||
|
||||
|
||||
|
||||
|
||||
def _readline_from_keyboard(self):
|
||||
c=self.console
|
||||
while 1:
|
||||
@@ -491,123 +454,6 @@ class NotEmacsMode(object):
|
||||
default, this is not bound to a key.'''
|
||||
pass
|
||||
|
||||
|
||||
def _get_completions(self):
|
||||
'''Return a list of possible completions for the string ending at the point.
|
||||
|
||||
Also set begidx and endidx in the process.'''
|
||||
completions = []
|
||||
self.begidx = self.l_buffer.point
|
||||
self.endidx = self.l_buffer.point
|
||||
buf=self.l_buffer.line_buffer
|
||||
if self.completer:
|
||||
# get the string to complete
|
||||
while self.begidx > 0:
|
||||
self.begidx -= 1
|
||||
if buf[self.begidx] in self.completer_delims:
|
||||
self.begidx += 1
|
||||
break
|
||||
text = ''.join(buf[self.begidx:self.endidx])
|
||||
log('complete text="%s"' % text)
|
||||
i = 0
|
||||
while 1:
|
||||
try:
|
||||
r = self.completer(text, i)
|
||||
except:
|
||||
break
|
||||
i += 1
|
||||
if r and r not in completions:
|
||||
completions.append(r)
|
||||
else:
|
||||
break
|
||||
log('text completions=%s' % completions)
|
||||
if not completions:
|
||||
# get the filename to complete
|
||||
while self.begidx > 0:
|
||||
self.begidx -= 1
|
||||
if buf[self.begidx] in ' \t\n':
|
||||
self.begidx += 1
|
||||
break
|
||||
text = ''.join(buf[self.begidx:self.endidx])
|
||||
log('file complete text="%s"' % text)
|
||||
completions = glob(os.path.expanduser(text) + '*')
|
||||
if self.mark_directories == 'on':
|
||||
mc = []
|
||||
for f in completions:
|
||||
if os.path.isdir(f):
|
||||
mc.append(f + os.sep)
|
||||
else:
|
||||
mc.append(f)
|
||||
completions = mc
|
||||
log('fnames=%s' % completions)
|
||||
return completions
|
||||
|
||||
def _display_completions(self, completions):
|
||||
if not completions:
|
||||
return
|
||||
self.console.write('\n')
|
||||
wmax = max(map(len, completions))
|
||||
w, h = self.console.size()
|
||||
cols = max(1, int((w-1) / (wmax+1)))
|
||||
rows = int(math.ceil(float(len(completions)) / cols))
|
||||
for row in range(rows):
|
||||
s = ''
|
||||
for col in range(cols):
|
||||
i = col*rows + row
|
||||
if i < len(completions):
|
||||
self.console.write(completions[i].ljust(wmax+1))
|
||||
self.console.write('\n')
|
||||
self._print_prompt()
|
||||
|
||||
def complete(self, e): # (TAB)
|
||||
'''Attempt to perform completion on the text before point. The
|
||||
actual completion performed is application-specific. The default is
|
||||
filename completion.'''
|
||||
completions = self._get_completions()
|
||||
if completions:
|
||||
cprefix = commonprefix(completions)
|
||||
rep = [ c for c in cprefix ]
|
||||
self.l_buffer[self.begidx:self.endidx] = rep
|
||||
self.l_buffer.point += len(rep) - (self.endidx - self.begidx)
|
||||
if len(completions) > 1:
|
||||
if self.show_all_if_ambiguous == 'on':
|
||||
self._display_completions(completions)
|
||||
else:
|
||||
self._bell()
|
||||
else:
|
||||
self._bell()
|
||||
|
||||
def possible_completions(self, e): # (M-?)
|
||||
'''List the possible completions of the text before point. '''
|
||||
completions = self._get_completions()
|
||||
self._display_completions(completions)
|
||||
|
||||
def insert_completions(self, e): # (M-*)
|
||||
'''Insert all completions of the text before point that would have
|
||||
been generated by possible-completions.'''
|
||||
completions = self._get_completions()
|
||||
b = self.begidx
|
||||
e = self.endidx
|
||||
for comp in completions:
|
||||
rep = [ c for c in comp ]
|
||||
rep.append(' ')
|
||||
self.l_buffer[b:e] = rep
|
||||
b += len(rep)
|
||||
e = b
|
||||
self.line_cursor = b
|
||||
|
||||
def menu_complete(self, e): # ()
|
||||
'''Similar to complete, but replaces the word to be completed with a
|
||||
single match from the list of possible completions. Repeated
|
||||
execution of menu-complete steps through the list of possible
|
||||
completions, inserting each match in turn. At the end of the list of
|
||||
completions, the bell is rung (subject to the setting of bell-style)
|
||||
and the original text is restored. An argument of n moves n
|
||||
positions forward in the list of matches; a negative argument may be
|
||||
used to move backward through the list. This command is intended to
|
||||
be bound to TAB, but is unbound by default.'''
|
||||
pass
|
||||
|
||||
def delete_char_or_list(self, e): # ()
|
||||
'''Deletes the character under the cursor if not at the beginning or
|
||||
end of the line (like delete-char). If at the end of the line,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,7 @@ name = 'pyreadline'
|
||||
# because bdist_rpm does not accept dashes (an RPM) convention, and
|
||||
# bdist_deb does not accept underscores (a Debian convention).
|
||||
|
||||
branch = 'refactor'
|
||||
|
||||
version = 'refactor'
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ from keysyms import key_text_to_keyinfo
|
||||
|
||||
import pyreadline.lineeditor.lineobj as lineobj
|
||||
import pyreadline.lineeditor.history as history
|
||||
import release
|
||||
|
||||
from modes import editingmodes
|
||||
|
||||
@@ -59,9 +60,10 @@ class Readline(object):
|
||||
self.tabstop = 4
|
||||
|
||||
self.editingmodes=[mode(self) for mode in editingmodes]
|
||||
for mode in self.editingmodes:
|
||||
mode.init_editing_mode(None)
|
||||
self.mode=self.editingmodes[0]
|
||||
|
||||
self.mode.init_editing_mode(None)
|
||||
self.begidx = 0
|
||||
self.endidx = 0
|
||||
|
||||
@@ -351,7 +353,9 @@ class Readline(object):
|
||||
def debug_output(on,filename="pyreadline_debug_log.txt"): #Not implemented yet
|
||||
logger.start_log(on,filename)
|
||||
logger.log("STARTING LOG")
|
||||
loc={"mode":mode,
|
||||
# print release.branch
|
||||
loc={"branch":release.branch,
|
||||
"mode":mode,
|
||||
"modes":modes,
|
||||
"set_mode":setmode,
|
||||
"bind_key":bind_key,
|
||||
|
||||
Reference in New Issue
Block a user