pyreadline-refactor: Fixing clipboard bugs, adding some editing functions

This commit is contained in:
jstenar
2006-10-18 21:25:49 +00:00
parent b1992d2c82
commit b1fe88f8c6
6 changed files with 134 additions and 70 deletions
+3 -1
View File
@@ -115,8 +115,10 @@ def make_KeyPress(char,state,keycode):
control = (state & (4+8)) != 0
meta = (state & (1+2)) != 0
shift = (state & 0x10) != 0
if control:
if control and char !="\x00":
char = chr(VkKeyScan(ord(char)) & 0xff)
elif control:
char=chr(keycode)
try:
keyname=code2sym_map[keycode]
except KeyError:
+74 -28
View File
@@ -9,7 +9,7 @@ import re,operator
import wordmatcher
import pyreadline.clipboard as clipboard
from pyreadline.logger import log,log_sock
class NotAWordError(IndexError):
pass
@@ -292,7 +292,7 @@ class TextLine(object):
stop=key.stop(self)
else:
stop=key.stop
return TextLine(self.line_buffer[start:stop],point=0)
return self.__class__(self.line_buffer[start:stop],point=0)
elif isinstance(key,LinePositioner):
return self.line_buffer[key(self)]
elif isinstance(key,tuple):
@@ -337,15 +337,15 @@ class TextLine(object):
if isinstance(key,slice):
start=key.start
stop=key.stop
prev=self.line_buffer[:start]
rest=self.line_buffer[stop:]
elif isinstance(key,LinePositioner):
start=key(self)
stop=start+1
else:
start=key
stop=key+1
value=TextLine(value).line_buffer
prev=self.line_buffer[:start]
value=self.__class__(value).line_buffer
rest=self.line_buffer[stop:]
out=prev+value+rest
if len(out)>=len(self):
self.point=len(self)
@@ -356,10 +356,16 @@ class TextLine(object):
def upper(self):
self.line_buffer=[x.upper() for x in self.line_buffer]
return self
def lower(self):
self.line_buffer=[x.lower() for x in self.line_buffer]
return self
def capitalize(self):
self.set_line(self.get_line_text().capitalize(),self.point)
return self
def startswith(self,txt):
return self.get_line_text().startswith(txt)
@@ -390,12 +396,16 @@ class ReadLineTextBuffer(TextLine):
def __repr__(self):
return 'ReadLineTextBuffer("%s",point=%s,mark=%s,selection_mark=%s)'%(self.line_buffer,self.point,self.mark,self.selection_mark)
def insert_text(self,char):
self.delete_selection()
self.selection_mark=-1
self._insert_text(char)
def to_clipboard(self):
if self.enable_win32_clipboard:
clipboard.set_clipboard_text(self.get_line_text())
######### Movement
def beginning_of_line(self):
@@ -473,6 +483,7 @@ class ReadLineTextBuffer(TextLine):
return True
else:
return False
self.selection_mark=-1
def delete_char(self):
if not self.delete_selection():
@@ -492,93 +503,128 @@ class ReadLineTextBuffer(TextLine):
del self[PrevWordStart:Point]
self.selection_mark=-1
def forward_delete_word(self):
if not self.delete_selection():
#del self[PrevWordEnd:Point]
del self[Point:NextWordStart]
self.selection_mark=-1
def delete_current_word(self):
if not self.delete_selection():
del self[CurrentWord]
self.selection_mark=-1
def delete_horizontal_space(self):
if not self.delete_selection():
pass
if self[Point] in " \t":
del self[PrevWordEnd:NextWordStart]
self.selection_mark=-1
######### Case
def upcase_word(self):
p=self.point
try:
self[CurrentWord]=self[CurrentWord].line_buffer.upper()
self[CurrentWord]=self[CurrentWord].upper()
self.point=p
except NotAWordError:
pass
def downcase_word(self):
p=self.point
try:
self[CurrentWord]=self[CurrentWord].line_buffer.lower()
self[CurrentWord]=self[CurrentWord].lower()
self.point=p
except NotAWordError:
pass
def capitalize_word(self):
def capitalize_word(self):
p=self.point
try:
self[CurrentWord]=self[CurrentWord].line_buffer.capitalize()
self[CurrentWord]=self[CurrentWord].capitalize()
self.point=p
except NotAWordError:
pass
########### Transpose
def transpose_chars(self):
pass
p2=Point(self)
if p2==0:
return
elif p2==len(self):
p2=p2-1
p1=p2-1
self[p2],self[p1]=self[p1],self[p2]
self.point=p2+1
def transpose_words(self):
pass
word1=TextLine(self)
word2=TextLine(self)
if self.point==len(self):
word2.point=PrevWordStart
word1.point=PrevWordStart(word2)
else:
word1.point=PrevWordStart
word2.point=NextWordStart
stop1=NextWordEnd(word1)
stop2=NextWordEnd(word2)
start1=word1.point
start2=word2.point
self[start2:stop2]=word1[Point:NextWordEnd]
self[start1:stop1]=word2[Point:NextWordEnd]
self.point=stop2
############ Kill
def kill_line(self):
if self.enable_win32_clipboard:
toclipboard="".join(self.line_buffer[self.point:])
clipboard.set_clipboard_text(toclipboard)
self[self.point:].to_clipboard()
del self.line_buffer[self.point:]
def kill_whole_line(self):
clipboard.set_clipboard_text()
self[:].to_clipboard()
del self[:]
def backward_kill_line(self):
clipboard.set_clipboard_text()
self[StartOfLine:Point].to_clipboard()
del self[StartOfLine:Point]
def unix_line_discard(self):
clipboard.set_clipboard_text(self[StartOfLine:Point])
del self[StartOfLine:Point]
pass
def kill_word(self):
"""Kills to next word ending"""
clipboard.set_clipboard_text(self[Point:NextWordEnd])
self[Point:NextWordEnd].to_clipboard()
del self[Point:NextWordEnd]
def backward_kill_word(self):
"""Kills to next word ending"""
clipboard.set_clipboard_text(self[PrevWordStart:Point])
self[PrevWordStart:Point].to_clipboard()
if not self.delete_selection():
del self[PrevWordStart:Point]
self.selection_mark=-1
def forward_kill_word(self):
"""Kills to next word ending"""
self[Point:NextWordEnd].to_clipboard()
if not self.delete_selection():
del self[Point:NextWordEnd]
self.selection_mark=-1
def unix_word_rubout(self):
clipboard.set_clipboard_text(self[PrevSpace:Point])
self[PrevSpace:Point].to_clipboard()
if not self.delete_selection():
del self[PrevSpace:Point]
self.selection_mark=-1
def kill_region(self):
clipboard.set_clipboard_text()
pass
def copy_region_as_kill(self):
clipboard.set_clipboard_text()
pass
def copy_backward_word(self):
clipboard.set_clipboard_text()
pass
def copy_forward_word(self):
clipboard.set_clipboard_text()
pass
+1 -1
View File
@@ -26,7 +26,7 @@ host="localhost"
port=8081
logsocket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
show_event=["keypress","bound_function"]
show_event=["keypress","bound_function","bind_key"]
show_event=["bound_function"]
def log_sock(s,event_type=None):
+46 -3
View File
@@ -84,6 +84,7 @@ class BaseMode(object):
print "Trying to bind non method to keystroke:%s,%s"%(key,func)
raise PyreadlineError("Trying to bind non method to keystroke:%s,%s,%s,%s"%(key,func,type(func),type(self._bind_key)))
keyinfo = make_KeyPress_from_keydescr(key.lower()).tuple()
log(">>>%s -> %s<<<"%(keyinfo,func.__name__))
self.key_dispatch[keyinfo] = func
def _bind_exit_key(self, key):
@@ -282,6 +283,21 @@ class BaseMode(object):
self.l_buffer.backward_word_extend_selection()
def upcase_word(self, e): # (M-u)
'''Uppercase the current (or following) word. With a negative
argument, uppercase the previous word, but do not move the cursor.'''
self.l_buffer.upcase_word()
def downcase_word(self, e): # (M-l)
'''Lowercase the current (or following) word. With a negative
argument, lowercase the previous word, but do not move the cursor.'''
self.l_buffer.downcase_word()
def capitalize_word(self, e): # (M-c)
'''Capitalize the current (or following) word. With a negative
argument, capitalize the previous word, but do not move the cursor.'''
self.l_buffer.capitalize_word()
def clear_screen(self, e): # (C-l)
@@ -312,11 +328,20 @@ class BaseMode(object):
to kill the characters instead of deleting them.'''
self.l_buffer.backward_delete_char()
def backward_delete_word(self, e): # (Rubout)
def backward_delete_word(self, e): # (Control-Rubout)
'''Delete the character behind the cursor. A numeric argument means
to kill the characters instead of deleting them.'''
self.l_buffer.backward_delete_word()
def forward_delete_word(self, e): # (Control-Delete)
'''Delete the character behind the cursor. A numeric argument means
to kill the characters instead of deleting them.'''
self.l_buffer.forward_delete_word()
def delete_horizontal_space(self, e): # ()
'''Delete all spaces and tabs around point. By default, this is unbound. '''
self.l_buffer.delete_horizontal_space()
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.
@@ -326,13 +351,17 @@ class BaseMode(object):
# Paste from clipboard
def paste(self,e):
'''Paste windows clipboard'''
'''Paste windows clipboard.
Assume single line strip other lines and end of line markers and trailing spaces''' #(Control-v)
if self.enable_win32_clipboard:
txt=clipboard.get_clipboard_text_and_convert(False)
txt=txt.split("\n")[0].strip("\r").strip("\n")
log("paste: >%s<"%map(ord,txt))
self.insert_text(txt)
def paste_mulitline_code(self,e):
'''Paste windows clipboard'''
'''Paste windows clipboard as multiline code.
Removes any empty lines in the code'''
reg=re.compile("\r?\n")
if self.enable_win32_clipboard:
txt=clipboard.get_clipboard_text_and_convert(False)
@@ -372,6 +401,20 @@ class BaseMode(object):
'''Copy the text in the region to the windows clipboard.'''
self.l_buffer.cut_selection_to_clipboard()
def dump_functions(self, e): # ()
'''Print all of the functions and their key bindings to the Readline
output stream. If a numeric argument is supplied, the output is
formatted in such a way that it can be made part of an inputrc
file. This command is unbound by default.'''
print
txt="\n".join(self.rl_settings_to_string())
print txt
self._print_prompt()
def commonprefix(m):
"Given a list of pathnames, returns the longest common leading component"
if not m: return ''
+4 -28
View File
@@ -275,21 +275,6 @@ class EmacsMode(basemode.BaseMode):
of the line, this transposes the last two words on the line.'''
self.l_buffer.transpose_words()
def upcase_word(self, e): # (M-u)
'''Uppercase the current (or following) word. With a negative
argument, uppercase the previous word, but do not move the cursor.'''
self.l_buffer.upcase_word()
def downcase_word(self, e): # (M-l)
'''Lowercase the current (or following) word. With a negative
argument, lowercase the previous word, but do not move the cursor.'''
self.l_buffer.downcase_word()
def capitalize_word(self, e): # (M-c)
'''Capitalize the current (or following) word. With a negative
argument, capitalize the previous word, but do not move the cursor.'''
self.l_buffer.capitalize_word()
def overwrite_mode(self, e): # ()
'''Toggle overwrite mode. With an explicit positive numeric
argument, switches to overwrite mode. With an explicit non-positive
@@ -324,7 +309,8 @@ class EmacsMode(basemode.BaseMode):
words, to the end of the next word. Word boundaries are the same as
forward-word.'''
self.l_buffer.kill_word()
forward_kill_word=kill_word
def backward_kill_word(self, e): # (M-DEL)
'''Kill the word behind point. Word boundaries are the same as
backward-word. '''
@@ -335,10 +321,6 @@ class EmacsMode(basemode.BaseMode):
boundary. The killed text is saved on the kill-ring.'''
self.l_buffer.unix_word_rubout()
def delete_horizontal_space(self, e): # ()
'''Delete all spaces and tabs around point. By default, this is unbound. '''
pass
def kill_region(self, e): # ()
'''Kill the text in the current region. By default, this command is unbound. '''
pass
@@ -476,13 +458,6 @@ class EmacsMode(basemode.BaseMode):
case, the line is accepted as if a newline had been typed.'''
pass
def dump_functions(self, e): # ()
'''Print all of the functions and their key bindings to the Readline
output stream. If a numeric argument is supplied, the output is
formatted in such a way that it can be made part of an inputrc
file. This command is unbound by default.'''
pass
def dump_variables(self, e): # ()
'''Print all of the settable variables and their values to the
Readline output stream. If a numeric argument is supplied, the
@@ -516,7 +491,7 @@ class EmacsMode(basemode.BaseMode):
self._bind_key('Right', self.forward_char)
self._bind_key('Control-f', self.forward_char)
self._bind_key('BackSpace', self.backward_delete_char)
self._bind_key('Control-BackSpace', self.backward_delete_word)
self._bind_key('Control-BackSpace', self.backward_delete_word)
self._bind_key('Home', self.beginning_of_line)
self._bind_key('End', self.end_of_line)
@@ -576,6 +551,7 @@ class EmacsMode(basemode.BaseMode):
self._bind_key("multiply", self.self_insert)
self._bind_key("divide", self.self_insert)
self._bind_key("vk_decimal", self.self_insert)
log("RUNNING INIT EMACS")
# make it case insensitive
def commonprefix(m):
+6 -9
View File
@@ -19,7 +19,7 @@ import operator
import exceptions
import clipboard,logger,console
from logger import log
from logger import log,log_sock
from error import ReadlineError,GetSetError
from pyreadline.keysyms.common import make_KeyPress_from_keydescr
@@ -241,7 +241,7 @@ class Readline(object):
## Internal functions
def rl_settings_to_string(self,e=None):
def rl_settings_to_string(self):
out=["%-20s: %s"%("show all if ambigous",self.show_all_if_ambiguous)]
out.append("%-20s: %s"%("mark_directories",self.mark_directories))
out.append("%-20s: %s"%("bell_style",self.bell_style))
@@ -250,15 +250,9 @@ class Readline(object):
tablepat="%-7s %-7s %-7s %-15s %-15s "
out.append(tablepat%("Control","Meta","Shift","Keycode/char","Function"))
bindings=[(k[0],k[1],k[2],k[3],v.__name__) for k,v in self.mode.key_dispatch.iteritems()]
#print self.mode.key_dispatch
#bindings=[str(v) for k,v in self.mode.key_dispatch.iteritems()]
bindings.sort()
for key in bindings:
pass
# out.append(str(key))
out.append(tablepat%(key))
if e:
print "\n".join(out)
return out
def _bell(self):
@@ -334,10 +328,13 @@ class Readline(object):
def setmode(name):
self.mode=modes[name]
def bind_key(key,name):
# print "bind",key,name
log("bind %s %s"%(key,name))
log_sock("bindkey: %s %s"%(key,name),"bind_key")
if hasattr(modes[mode],name):
# print "can bind",key,name
modes[mode]._bind_key(key,getattr(modes[mode],name))
else:
print "Trying to bind unknown command '%s' to key '%s'"%(name,key)
def un_bind_key(key):
keyinfo = make_KeyPress_from_keydescr(key).tuple()
if keyinfo in modes[mode].key_dispatch: