mirror of
https://github.com/wassname/pyreadline.git
synced 2026-06-27 16:10:38 +08:00
pyreadline: Patches for clipboard and some key-bindings. Changed version in setup.py to 1.13-svn.
This commit is contained in:
+24
-1
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user