classification
Title: IDLE - pasting text doesn't delete selection
Type: enhancement Stage: resolved
Components: IDLE Versions: Python 3.6, Python 3.5, Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: terry.reedy Nosy List: Guilherme.Simões, Mark.Young, Todd.Rovito, gpolo, ned.deily, python-dev, r.david.murray, roger.serwy, serhiy.storchaka, terry.reedy, weeble
Priority: normal Keywords: patch

Created on 2009-02-01 18:52 by weeble, last changed 2016-06-12 04:37 by serhiy.storchaka. This issue is now closed.

Files
File name Uploaded Description Edit
issue5124.patch roger.serwy, 2013-05-26 16:10 review
idle_paste_replace.patch serhiy.storchaka, 2016-06-04 11:24 review
x11-paste.diff terry.reedy, 2016-06-08 06:36 review
x11-paste-36.diff terry.reedy, 2016-06-09 22:45 review
x11-paste-35.diff terry.reedy, 2016-06-09 22:46 review
x11-paste-27.diff terry.reedy, 2016-06-09 22:46 review
Messages (40)
msg80914 - (view) Author: Weeble (weeble) Date: 2009-02-01 18:52
Steps to reproduce:
1. Start IDLE.
2. Enter some text:

spam
eggs

3. Select the first line ("spam") and press control+c to copy.
4. Select the second line ("eggs") and press control+v to paste.

Expected result:

spam
spam

(With the caret at the end of the second line and no selection.)

Actual result (IDLE 2.6, Tk/Tcl 8.4, Linux):

spam
eggsspam

(With "eggs" selected and the caret at the end of the second line.)

I don't think this happens to me on Windows. It might be deliberate; I
know that Tk has slightly different behaviour on Windows and Linux. But
it doesn't seem to be consistent with other behaviour: for example, if
instead of pasting I start typing, the selected text is erased and the
typed text replaces it.

I can look into this myself, but I would appreciate if someone else can
confirm that this is not the expected behaviour, since perhaps it is
only my Windows background that leads me to expect this.
msg80915 - (view) Author: Guilherme Polo (gpolo) * (Python committer) Date: 2009-02-01 19:04
This is not really related to IDLE, it is how the Text widget behaves
under Linux, you will notice the same with tcl/tk 8.5.

Nevertheless, I would prefer to have the same results under Windows and
Linux.
msg91166 - (view) Author: Guilherme Polo (gpolo) * (Python committer) Date: 2009-08-01 18:55
btw, I just added a patch for issue3559 which could be easily adjusted
to work as described in this issue.
msg190061 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2013-05-26 04:06
On Win7, I get the replacement behavior. I get the same in Notepad and Firefox, so this may be standard Windows behavior. What is standard in other linex and mac apps? If the tk difference is a standard platform difference, I might think we should leave it alone.
msg190063 - (view) Author: Todd Rovito (Todd.Rovito) * Date: 2013-05-26 05:31
"What is standard in other linex and mac apps?"
-On Mac OS X 10.8.3 TextEdit I get the replacement behavior
-On Linux CentOS 6.4 gedit I get the replacement behavior
-On IDLE under the latest 3.4 pull I get the replacement behavior with Max OS X 10.8.3
-On IDLE under the latest 3.4 pull I get the eggsspam behavior with Linux CentOS 6.4 as Weeble described in the original bug report

So from my perspective Linux is behaving differently than Windows and Mac OS X.
msg190066 - (view) Author: Ned Deily (ned.deily) * (Python committer) Date: 2013-05-26 06:52
X11-based Tk follows general X11 practice with regard to text pasting.  See http://wiki.tcl.tk/3771 for some background.  Old school X11 users expect pasting to work that way.  This is yet another instance where Tk attempts to conform to the platform it is running on.  I recommend closing this issue as X11 Tk (and, hence, IDLE) has behaved like this forever and changing it would be painful for many current X11 IDLE users.
msg190097 - (view) Author: Roger Serwy (roger.serwy) * (Python committer) Date: 2013-05-26 16:10
There are many X11 applications that replace the selection with pasted text. GTK and Qt widgets behave that way. Here's a brief list: gedit (GTK), gummi (GTK), kate (Qt), texmaker (Qt).

Tkinter, for me, has become increasingly frustrating due to these subtle platform differences. (See #14146, #13582, and many more that deal with Tk on Mac.) For IDLE, I consider these behavior differences bugs.

The attached patch "fixes" this issue.
msg190117 - (view) Author: Guilherme Simões (Guilherme.Simões) * Date: 2013-05-26 22:00
I think IDLE should ignore general X11 practice. I used Linux for years and have never seen this behavior before because almost all programs behave in the Mac/Windows way.
msg190120 - (view) Author: Ned Deily (ned.deily) * (Python committer) Date: 2013-05-26 22:59
Unfortunately, there is no one right answer to paste behavior on X11, unlike on native Windows and Mac implementations where there is essentially system-wide consistent paste behavior enforced by the underlying operating system.  As the Tk Wiki points out (and the comments hers concur), different users are going to have different expectations.  If we want to make this behavior available with X11 Tk, then it really should be a user configurable option.  Without providing an option, the overriding design principle is that the status quo wins a stalemate (http://www.boredomandlaziness.org/2011/02/status-quo-wins-stalemate.html).
msg190124 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2013-05-27 01:57
I agree that the paste replace should be added as an option on linux, but without a broader survey of Linux Idle users to convince me otherwise, I have to agree that the default should stay as it is. I do not see any call to make the x11 behavior an option on mac and windows.
msg190128 - (view) Author: Todd Rovito (Todd.Rovito) * Date: 2013-05-27 03:24
I haver verified Roger's patch does indeed fix the problem on Linux CentOS 6.4 with IDLE 3.4.

The Linux situation is complex.  Basically as I see it over the years pure X11 applications are becoming extinct and most developers either use GTK (for GNOME) or QT (for KDE). I don't blame anybody for moving to one of these toolkits because writing a pure X11 application is painful.  In the near future Wayland http://en.wikipedia.org/wiki/Wayland_(display_server_protocol) will take over and I wonder how many X11 applications will actually be ported.  I agree with Roger we should try and make IDLE as consistent as possible across operating systems.  

+1 for applying the patch.
msg192676 - (view) Author: Mark Young (Mark.Young) Date: 2013-07-08 17:26
+1 at least providing the option. This behavior is obnoxious and weird (no other program on linux that I know of does this (not to say no such program exists)). If I didn't want the original gone, I wouldn't have highlighted it.
msg267126 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-06-03 18:20
I just got a complaint from a Linux user who says IDLE is the only application she uses on Linux that has this augment rather than replace behavior.  She also uses IDLE on Windows, so this unique IDLE-Linux behavior is quite annoying.  Replace at least needs to be an option.

Serhiy (or other current Linux user), what do you know about typical behavior on Linux today?
msg267128 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2016-06-03 18:35
For what it is worth, as a dedicated X11 user, *if* the target is already hilighted by the application I expect the replace behavior.  But in my usage I never select the target myself, since that would replace my selection buffer.  So in essence I'm seeing the "augment" behavior, but it's because I click to place the cursor where I want to paste, I don't select a target block to replace.
msg267136 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-06-03 18:57
Thank you David, that does help.  Your comment emphasizes that on other systems and many other X-11 apps, the user already chooses 'replace' versus 'insert' by selecting a replacement or not.   I presume the 'selection buffer' you refer to is different from the 'clipboard' (or whatever linux calls it).  Otherwise, Roger's patch would not work and I assume he tested it.

Simply applying Roger's patch, in 3.6, would be **MUCH** easier than adding a new option.  I could even add a line to the sign-on message: "Paste now replaces selected text.  Use undo to correct mistakes."

Assuming the patch does work, here is a workaround for releases that lack it. Create in Lib/idlelib a file called, for instance @MYPATCHES.txt and insert with the following, to remind what to do after upgrading to a new bugfix release.
---
To make paste replace selection, insert the following 3 lines at the top (after the def line) of EditorWindow.paste, about line 600, in file EditorWindow.py (3.5 and before) or editor.py (3.6 and after).

        sel = self.text.tag_ranges("sel")
        if sel:
            self.text.delete(*sel)   # issue5124
---

Save and then follow the instruction to patch the editor file. If doing the edit in IDLE, hit F5 to test the patched EditorWindow.
msg267155 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-03 20:09
In modern text editors selecting text with a mouse moves text cursor, and moving the cursor by arrow keys cancels the selection (if Shift is not pressed). But in terminal emulators selecting text with a mouse doesn't move text cursor, and moving the cursor doesn't cancel the selection. This might be an initial reason for Tk behavior.

Since IDLE editor window is rather a text editor than a terminal emulator, I think 'replace' is more preferable. But I'm not so sure about IDLE shell window.

EditorWindow.text is not the only Text widget. There are many other Text and Entry widgets are created. We should change the behavior of all Text and Entry widgets globally. I'll try to write a patch.
msg267161 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2016-06-03 20:44
Note that I would find it *very* confusing if the paste took place at some other location than the cursor location.  From Serhiy's description I don't think that's an issue in the proposed change.
msg267252 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-04 11:24
Here is a patch that makes pasting text in all Text, Entry and Spinbox widgets to delete selection.
msg267535 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-06 15:11
Ping.
msg267578 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-06-07 00:50
I can't test but I looked at the patch.  It uses the new-to-me fact that bound 'functions' can be tcl code in a string.  For me, root.bind_class('Text', '<<Patch>>') returns the code string '\n    tk_textPaste %W\n'.  Options for the patch:

0. Do nothing.
1. 3.6 as option (default TBD).
2. 3.6 as fixed change.
3. All versions as option (default TBD).
4. All versions as fixed change.

I have determined that adding new sections to config-main does not affect previous releases, so 1 and 3 are possible.  See the post I just made to #27099 as to what is needed for new options.

For 1 and 3, there is the question of default - 'insert' versus 'replace', and for 3, whether it should be the same in all versions.  I don't think 'insert' and the option should stay around forever.

The question we need to think about is what would be best for beginners. The young but experienced Widows user, new to Linux, reported this to me as a bug that tripped her up a lot.

Serhiy, I think that this change, at least as an option, should be in tkinter, so as to make it more 'cross-platform'.  In the meantime, I will look at including this with the changes in #20799.

I am thinking about posting to python-ideas for other opinions on what to do in which package.
msg267586 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-07 04:24
I think it is better to fix this in all versions unconditionally.

This simple workaround is good enough for IDLE, but if add it as a part of Tkinter, it should be much more complex. I prefer to provide this as a recipe at http://code.activestate.com/recipes/langs/python/ .
msg267597 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-06-07 06:20
I presume you mean option 4. I understand this to be what David and others expected.

Ned, what do you think now?  You were opposed 3 years ago, but we have a bit more evidence that the current behavior is out of whack with current Linux practice.  Should I ask for for linux experiences and opinions on python-ideas?
msg267683 - (view) Author: Ned Deily (ned.deily) * (Python committer) Date: 2016-06-07 14:33
Terry, after the discussion I don't have a strong opinion one way or the other.  It seems that current X11 users expect the replace behavior, so option 4 seems fine to me.
msg267796 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-06-08 06:36
To avoid bloating pyshell.main further, and to facilitate testing, I put the new code in a separate function called from main and a test.  The test should PASS as is and FAIL on X11 with the call to fix_x11_paste commented out.  If it does not, it is not a test and should be modified. When we have a real test, I will apply.  x11-paste.diff is against 3.6.  I already have 2.7 and 3.5 versions.
msg267797 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-08 06:50
Tested. LGTM.
msg268064 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-06-09 22:45
For 3.6, I added ttk.Entry to x11 fixer.  I expanded tests to Entry and Spinboxes.  I noted in a comment that tk.Entry/Spinbox, but not ttk.Entry, would not paste with generated <<Paste>> event without a 0-length selection.  This might be a glitch in tk, but pasting with line Entry worked fine.  Will attach 3.5 and 2.7 patches as well.

The 2.7 test results in ThemeChanged warnings when run as part of test_idle, but not when run alone.  I am ignoring this.

I will apply when tests run on x11.
msg268082 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-10 04:26
I deliberately omitted ttk.Entry, because it doesn't have special behavior on X11.
msg268086 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-06-10 05:22
I presume then that the tests pass on Linux with TEntry removed.  I take this as repudiation of the 'X11' behavior by the tk maintainers, and as support for changing the old widgets.  Having different paste behavior in text and entry widgets, or even different entry widgets (in the same release of IDLE, when some but not all 'Entry's have been converted) would be pretty bad.
msg268179 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-11 04:52
It would be better to exclude TEntry from the list. This is a hack, and as every hack it can be not fully compatible with future Tk versions.
msg268182 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-06-11 05:23
I had some trouble committing and pushing these patches.  After deleting TEntry and committed the 2.7 and 3.5 patches and tried to do the usual 3.5 to default forward merge in TortoiseHG.  I got

% hg merge --tool :merge --verbose 101861
resolving manifests
abort: case-folding collision between Lib/idlelib/pyshell.py and Lib/idlelib/PyShell.py
[command returned code 255 Fri Jun 10 22:33:09 2016]

This seems to be a known problem.  After some effort to resolve the situation, I gave up and used my replaced my repository with a copy of my backup copy, to undo the things I had tried.

Since the renames on 5/22, I have done other merges without problem, but I rechecked and none involved a file where case was the only difference. I will try again by temporarily renaming pyshell back to PyShell first.
msg268189 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2016-06-11 06:07
New changeset 99760b6a181e by Terry Jan Reedy in branch 'default':
Issue #5124: Temporary pyshell rename to avoid case-folding collision in merge.
https://hg.python.org/cpython/rev/99760b6a181e

New changeset 6c469b50e198 by Terry Jan Reedy in branch '2.7':
Issue #5124: Paste with selection should always replace.
https://hg.python.org/cpython/rev/6c469b50e198

New changeset f8b40e0d5913 by Terry Jan Reedy in branch '3.5':
Issue #5124: Paste with selection should always replace.
https://hg.python.org/cpython/rev/f8b40e0d5913
msg268191 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2016-06-11 06:11
New changeset 095e79636663 by Terry Jan Reedy in branch 'default':
Issue #5124: rename PyShell back to pyshell and patch test for 3.6
https://hg.python.org/cpython/rev/095e79636663
msg268200 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2016-06-11 08:32
New changeset 3017e41b0c99 by Terry Jan Reedy in branch '2.7':
Issue #5124: NEWS entries.
https://hg.python.org/cpython/rev/3017e41b0c99

New changeset 62b949a179cb by Terry Jan Reedy in branch '3.5':
Issue #5124: NEWS entries.
https://hg.python.org/cpython/rev/62b949a179cb

New changeset 2fc15579606b by Terry Jan Reedy in branch 'default':
Merge Issue #5124: NEWS entries.
https://hg.python.org/cpython/rev/2fc15579606b
msg268204 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-11 09:23
entry=entry in test is not needed.
msg268260 - (view) Author: Ned Deily (ned.deily) * (Python committer) Date: 2016-06-11 19:42
Terry, the 2.7 version of the test changes is causing buildbot and test_idle failures when the "gui" condition is not met. See, for example, http://buildbot.python.org/all/builders/AMD64%20Snow%20Leop%202.7/builds/1400.
msg268265 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2016-06-11 20:26
New changeset 274308a3b8b6 by Terry Jan Reedy in branch '2.7':
Issue #5124: For 2.7, move requires('gui') from module level to setUpClass.
https://hg.python.org/cpython/rev/274308a3b8b6
msg268266 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-06-11 20:30
Oh right, requires('gui') does not work at module level in 2.7.
This should fix.  Will try to check next round of bot builds.
msg268296 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-06-11 23:42
The two stable buildbots that failed on test_idle before do not now: AMD64 SnowLeapard 1403, AMD64 Win 7 2258.
msg268319 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2016-06-12 04:28
Serhiy: entry=entry as much as any name=expression pair to print the value of variable entry on test failure, either "entry=<tkinter.Entry object .58910800>)" or "entry=<tkinter.ttk.Entry object .58911024>)", as in

======================================================================
FAIL: test_paste_entry (__main__.PasteTest) (ans='two', end='end', entry=<tkinter.ttk.Entry object .58911024>)
Test pasting into an entry with and without a selection.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "F:\Python\dev\36\lib\idlelib\idle_test\test_editmenu.py", line 53, in test_paste_entry
    self.assertTrue(False)
AssertionError: False is not true
msg268320 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-06-12 04:37
Ah, I looked on 3.5 change and missed that in 3.6 you test both tkinter.Entry and ttk.Entry.
History
Date User Action Args
2016-06-12 04:37:15serhiy.storchakasetmessages: + msg268320
2016-06-12 04:28:04terry.reedysetmessages: + msg268319
2016-06-11 23:42:59terry.reedysetstatus: open -> closed

messages: + msg268296
stage: needs patch -> resolved
2016-06-11 20:30:07terry.reedysetmessages: + msg268266
2016-06-11 20:26:32python-devsetmessages: + msg268265
2016-06-11 19:42:52ned.deilysetstatus: closed -> open

messages: + msg268260
stage: resolved -> needs patch
2016-06-11 09:23:24serhiy.storchakasetmessages: + msg268204
2016-06-11 08:32:51python-devsetmessages: + msg268200
2016-06-11 06:12:11terry.reedysetstatus: open -> closed
resolution: fixed
stage: commit review -> resolved
2016-06-11 06:11:21python-devsetmessages: + msg268191
2016-06-11 06:07:01python-devsetnosy: + python-dev
messages: + msg268189
2016-06-11 05:23:34terry.reedysetmessages: + msg268182
2016-06-11 04:52:08serhiy.storchakasetmessages: + msg268179
2016-06-10 05:22:07terry.reedysetmessages: + msg268086
2016-06-10 04:26:46serhiy.storchakasetmessages: + msg268082
2016-06-09 22:46:28terry.reedysetfiles: + x11-paste-27.diff
2016-06-09 22:46:14terry.reedysetfiles: + x11-paste-35.diff
2016-06-09 22:46:01terry.reedysetfiles: + x11-paste-36.diff

messages: + msg268064
2016-06-08 06:50:52serhiy.storchakasetmessages: + msg267797
stage: patch review -> commit review
2016-06-08 06:36:39terry.reedysetfiles: + x11-paste.diff
assignee: terry.reedy
messages: + msg267796
2016-06-07 14:33:38ned.deilysetmessages: + msg267683
2016-06-07 06:20:14terry.reedysetmessages: + msg267597
2016-06-07 04:24:03serhiy.storchakasetmessages: + msg267586
2016-06-07 00:50:08terry.reedysetmessages: + msg267578
2016-06-06 15:11:58serhiy.storchakasetmessages: + msg267535
2016-06-04 11:24:01serhiy.storchakasetfiles: + idle_paste_replace.patch

messages: + msg267252
stage: test needed -> patch review
2016-06-03 20:44:35r.david.murraysetmessages: + msg267161
2016-06-03 20:09:43serhiy.storchakasetmessages: + msg267155
2016-06-03 18:57:15terry.reedysetmessages: + msg267136
versions: + Python 3.5, Python 3.6, - Python 3.3, Python 3.4
2016-06-03 18:35:26r.david.murraysetnosy: + r.david.murray
messages: + msg267128
2016-06-03 18:20:00terry.reedysetnosy: + serhiy.storchaka
messages: + msg267126
2014-02-03 17:05:40BreamoreBoysetnosy: - BreamoreBoy
2013-07-08 17:26:10Mark.Youngsetnosy: + Mark.Young
messages: + msg192676
2013-05-27 03:24:07Todd.Rovitosetmessages: + msg190128
2013-05-27 01:57:09terry.reedysettype: behavior -> enhancement
messages: + msg190124
2013-05-26 22:59:26ned.deilysetmessages: + msg190120
2013-05-26 22:00:53Guilherme.Simõessetnosy: + Guilherme.Simões
messages: + msg190117
2013-05-26 16:10:39roger.serwysetfiles: + issue5124.patch
keywords: + patch
messages: + msg190097
2013-05-26 06:52:42ned.deilysetnosy: + ned.deily
messages: + msg190066
2013-05-26 05:31:55Todd.Rovitosetmessages: + msg190063
2013-05-26 04:06:42terry.reedysetversions: + Python 2.7, Python 3.3, Python 3.4
nosy: + Todd.Rovito

messages: + msg190061

type: behavior
stage: test needed
2013-05-26 03:25:28BreamoreBoysetnosy: + terry.reedy, roger.serwy, BreamoreBoy
2009-08-01 18:55:42gpolosetmessages: + msg91166
2009-02-01 19:04:37gpolosetnosy: + gpolo
messages: + msg80915
2009-02-01 18:52:13weeblecreate