pyreadline: Patches for clipboard and some key-bindings. Changed version in setup.py to 1.13-svn.

This commit is contained in:
jstenar
2006-01-21 19:36:28 +00:00
parent 70638c4e3c
commit 74b401f389
4 changed files with 235 additions and 4 deletions
+24 -1
View File
@@ -1,3 +1,27 @@
2006-01-21 Jörgen Stenarson <jorgen.stenarson -at- bostream.nu>
* Added clipboard functionality. ctypes clipboard code
borrowed from example code posted to ctypes-users. See
http://aspn.activestate.com/ASPN/Mail/Message/ctypes-users/1771866
* Control-Shift-v moved quoted insert from Control-v
* Control-v straight paste from clipboard
* Alt-v ipython_paste. Does some preprocessing of data. If
clipboard text is shorter than 300 characters and has no
newlines and tabs, then assume it is a path and change all
\ to / and then add \ before all spaces. This means you can
paste paths and use them in magic command %cd. If text is
multiline it assumes tabseparated data should be list of
list, if all is numeric assume it should be an array.
* Control-y yank, alias for Control-v.
* Control-k kill line, move text from cursor to end of line
into clipboard. Should be move to kill buffer but the kill
buffer is not implemented.
* Added kill line and yank functionality. As well as mark and
copy-region-to-clipboard.
* Control-m set-mark sets the copy region mark
* Control-q copies region between mark and cursor to clipboard
* Changed version in setup.py to 1.13-svn
2006-01-21 Jörgen Stenarson <jorgen.stenarson -at- bostream.nu>
* Patch to get swedish characters working when python
@@ -11,4 +35,3 @@
* Changed all python files to conform to 4 space indent.
* Added changelog
* Added os.path.expanduser to expand out ~/.history paths
+56 -2
View File
@@ -1,3 +1,4 @@
# -*- coding: ISO-8859-1 -*-
''' an attempt to implement readline for Python in Python using ctypes'''
import string
@@ -15,6 +16,19 @@ import Console
from Console import log
from keysyms import key_text_to_keyinfo,printable_chars_in_codepage
import clipboard
import ctypes
enable_win32_clipboard=True
#assumes data on clipboard is path if shorter than 300 characters and doesn't contain \t or \n
#and replace \ with / for easier use in ipython
enable_ipython_paste_for_paths=True
#automatically convert tabseparated data to list of lists or array constructors
enable_ipython_paste_list_of_lists=True
def quote_char(c):
if c in printable_chars_in_codepage:
return c
@@ -53,6 +67,7 @@ class Readline:
self.show_all_if_ambiguous = 'off'
self.mark_directories = 'on'
self.bell_style = 'none'
self.mark=-1
def _bell(self):
'''ring the bell if requested.'''
@@ -669,6 +684,9 @@ class Readline:
def kill_line(self, e): # (C-k)
'''Kill the text from point to the end of the line. '''
if enable_win32_clipboard:
toclipboard="".join(self.line_buffer[self.line_cursor:])
clipboard.set_clipboard_text(toclipboard)
self.line_buffer[self.line_cursor:] = []
def backward_kill_line(self, e): # (C-x Rubout)
@@ -726,6 +744,18 @@ class Readline:
yanked right away. By default, this command is unbound.'''
pass
def copy_region_to_clipboard(self, e): # ()
'''Copy the text in the region to the windows clipboard.'''
if enable_win32_clipboard:
mark=min(self.mark,len(self.line_buffer))
cursor=min(self.line_cursor,len(self.line_buffer))
if self.mark==-1:
return
begin=min(cursor,mark)
end=max(cursor,mark)
toclipboard="".join(self.line_buffer[begin:end])
clipboard.SetClipboardText(str(toclipboard))
def copy_backward_word(self, e): # ()
'''Copy the word before point to the kill buffer. The word
boundaries are the same as backward-word. By default, this command
@@ -738,6 +768,24 @@ class Readline:
unbound.'''
pass
def paste(self,e):
'''Paste windows clipboard'''
if enable_win32_clipboard:
txt=clipboard.get_clipboard_text_and_convert(False)
self.insert_text(txt)
def ipython_paste(self,e):
'''Paste windows clipboard. If enable_ipython_paste_list_of_lists is
True then try to convert tabseparated data to repr of list of lists or
repr of array'''
if enable_win32_clipboard:
txt=clipboard.get_clipboard_text_and_convert(
enable_ipython_paste_list_of_lists)
if enable_ipython_paste_for_paths:
if len(txt)<300 and ("\t" not in txt) and ("\n" not in txt):
txt=txt.replace("\\","/").replace(" ",r"\ ")
self.insert_text(txt)
def yank(self, e): # (C-y)
'''Yank the top of the kill ring into the buffer at point. '''
pass
@@ -948,7 +996,7 @@ class Readline:
def set_mark(self, e): # (C-@)
'''Set the mark to the point. If a numeric argument is supplied, the
mark is set to that position.'''
pass
self.mark=self.line_cursor
def exchange_point_and_mark(self, e): # (C-x C-x)
'''Swap the point with the mark. The current cursor position is set
@@ -1048,7 +1096,13 @@ class Readline:
self._bind_key('Meta-d', self.kill_word)
self._bind_key('Meta-Delete', self.backward_kill_word)
self._bind_key('Control-w', self.unix_word_rubout)
self._bind_key('Control-v', self.quoted_insert)
self._bind_key('Control-Shift-v', self.quoted_insert)
self._bind_key('Control-v', self.paste)
self._bind_key('Alt-v', self.ipython_paste)
self._bind_key('Control-y', self.paste)
self._bind_key('Control-k', self.kill_line)
self._bind_key('Control-m', self.set_mark)
self._bind_key('Control-q', self.copy_region_to_clipboard)
# Add keybindings for numpad
# first the number keys
+154
View File
@@ -0,0 +1,154 @@
###################################
#
# Based on recipe posted to ctypes-users
# see archive
# http://aspn.activestate.com/ASPN/Mail/Message/ctypes-users/1771866
#
#
###################################################################################
#
# The Python win32clipboard lib functions work well enough ... except that they
# can only cut and paste items from within one application, not across
# applications or processes.
#
# I've written a number of Python text filters I like to run on the contents of
# the clipboard so I need to call the Windows clipboard API with global memory
# for my filters to work properly.
#
# Here's some sample code solving this problem using ctypes.
#
# This is my first work with ctypes. It's powerful stuff, but passing arguments
# in and out of functions is tricky. More sample code would have been helpful,
# hence this contribution.
#
###################################################################################
from ctypes import *
from win32con import CF_TEXT, GHND
OpenClipboard = windll.user32.OpenClipboard
EmptyClipboard = windll.user32.EmptyClipboard
GetClipboardData = windll.user32.GetClipboardData
GetClipboardFormatName = windll.user32.GetClipboardFormatNameA
SetClipboardData = windll.user32.SetClipboardData
EnumClipboardFormats = windll.user32.EnumClipboardFormats
CloseClipboard = windll.user32.CloseClipboard
OpenClipboard.argtypes=[c_int]
EnumClipboardFormats.argtypes=[c_int]
CloseClipboard.argtypes=[]
GetClipboardFormatName.argtypes=[c_uint,c_char_p,c_int]
GetClipboardData.argtypes=[c_int]
SetClipboardData.argtypes=[c_int,c_int]
GlobalLock = windll.kernel32.GlobalLock
GlobalAlloc = windll.kernel32.GlobalAlloc
GlobalUnlock = windll.kernel32.GlobalUnlock
GlobalLock.argtypes=[c_int]
GlobalUnlock.argtypes=[c_int]
memcpy = cdll.msvcrt.memcpy
def enum():
OpenClipboard(0)
q=EnumClipboardFormats(0)
while q:
print q,
q=EnumClipboardFormats(q)
CloseClipboard()
def getformatname(format):
buffer = c_buffer(" "*100)
bufferSize = sizeof(buffer)
OpenClipboard(0)
GetClipboardFormatName(format,buffer,bufferSize)
CloseClipboard()
return buffer.value
def GetClipboardText():
text = ""
if OpenClipboard(0):
hClipMem = GetClipboardData(CF_TEXT)
if hClipMem:
GlobalLock.restype = c_char_p
text = GlobalLock(hClipMem)
GlobalUnlock(hClipMem)
CloseClipboard()
return text
def make_tab(lists):
if hasattr(lists,"tolist"):
lists=lists.tolist()
ut=[]
for rad in lists:
if type(rad) in [list,tuple]:
ut.append("\t".join(["%s"%x for x in rad]))
else:
ut.append("%s"%rad)
return "\n".join(ut)
def send_data(lists):
SetClipboardText(make_tab(lists))
def SetClipboardText(text):
buffer = c_buffer(text)
bufferSize = sizeof(buffer)
hGlobalMem = GlobalAlloc(c_int(GHND), c_int(bufferSize))
GlobalLock.restype = c_void_p
lpGlobalMem = GlobalLock(c_int(hGlobalMem))
memcpy(lpGlobalMem, addressof(buffer), c_int(bufferSize))
GlobalUnlock(c_int(hGlobalMem))
if OpenClipboard(0):
EmptyClipboard()
SetClipboardData(c_int(CF_TEXT), c_int(hGlobalMem))
CloseClipboard()
def set_clipboard_text(toclipboard):
SetClipboardText(str(toclipboard))
def make_list_of_list(txt):
def make_num(x):
try:
return int(x)
except ValueError:
try:
return float(x)
except ValueError:
try:
return complex(x)
except ValueError:
return x
return x
ut=[]
flag=False
for rad in [x for x in txt.split("\r\n") if x!=""]:
raden=[make_num(x) for x in rad.split("\t")]
if str in map(type,raden):
flag=True
ut.append(raden)
return ut,flag
def get_clipboard_text_and_convert(paste_list=False):
"""Get txt from clipboard. if paste_list==True the convert tab separated
data to list of lists. Enclose list of list in array() if all elements are
numeric"""
txt=GetClipboardText()
if txt:
if paste_list and "\t" in txt:
array,flag=make_list_of_list(txt)
if flag:
txt=repr(array)
else:
txt="array(%s)"%repr(array)
txt="".join([c for c in txt if c not in " \t\r\n"])
return txt
if __name__ == '__main__':
txt=GetClipboardText() # display last text clipped
print txt
+1 -1
View File
@@ -1,7 +1,7 @@
from distutils.core import setup
setup(name="readline",
version="1.12",
version="1.13-svn",
description="Python implementation of GNU readline",
author="Gary Bishop",
author_email="gb@cs.unc.edu",