]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-95191: IDLE: Include prompts when saving Shell GH-95554 (#95558)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Tue, 2 Aug 2022 11:17:50 +0000 (04:17 -0700)
committerGitHub <noreply@github.com>
Tue, 2 Aug 2022 11:17:50 +0000 (13:17 +0200)
(cherry picked from commit b85411fc5e9e223a6bd44f89f674ee3b2e29b99e)

Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu>
Lib/idlelib/NEWS.txt
Lib/idlelib/idle_test/test_iomenu.py
Lib/idlelib/iomenu.py
Lib/idlelib/pyshell.py
Misc/NEWS.d/next/IDLE/2022-08-01-23-31-48.gh-issue-95191.U7vryB.rst [new file with mode: 0644]

index add0d8c6bead2c6ff7e89578ab38ece98bfbf806..999b67181319cfa9a95e1dab16333382653b61df 100644 (file)
@@ -4,6 +4,8 @@ Released 2023-04-03?
 =========================
 
 
+gh-95191: Include prompts when saving Shell (interactive input/output).
+
 gh-95511: Fix the Shell context menu copy-with-prompts bug of copying
 an extra line when one selects whole lines.
 
index e338893c09e6a14c12e873d449a492b024373dac..2fb836dba216721052f4493b5417b8b84ce34d11 100644 (file)
@@ -1,10 +1,12 @@
 "Test , coverage 17%."
 
-from idlelib import iomenu, util
+from idlelib import iomenu
 import unittest
 from test.support import requires
 from tkinter import Tk
 from idlelib.editor import EditorWindow
+from idlelib import util
+from idlelib.idle_test.mock_idle import Func
 
 
 class IOBindingTest(unittest.TestCase):
@@ -36,9 +38,14 @@ class IOBindingTest(unittest.TestCase):
         io = self.io
         fix = io.fixnewlines
         text = io.editwin.text
+
+        # Make the editor temporarily look like Shell.
         self.editwin.interp = None
-        eq(fix(), '')
-        del self.editwin.interp
+        shelltext = '>>> if 1'
+        self.editwin.get_prompt_text = Func(result=shelltext)
+        eq(fix(), shelltext)  # Get... call and '\n' not added.
+        del self.editwin.interp, self.editwin.get_prompt_text
+
         text.insert(1.0, 'a')
         eq(fix(), 'a'+io.eol_convention)
         eq(text.get('1.0', 'end-1c'), 'a\n')
index 327e885203c3ca75a045178587390fa65bfa6a2d..af8159c2b33f51c912c9bfacad232dd90202c915 100644 (file)
@@ -251,11 +251,17 @@ class IOBinding:
             return False
 
     def fixnewlines(self):
-        "Return text with final \n if needed and os eols."
-        if (self.text.get("end-2c") != '\n'
-            and not hasattr(self.editwin, "interp")):  # Not shell.
-            self.text.insert("end-1c", "\n")
-        text = self.text.get("1.0", "end-1c")
+        """Return text with os eols.
+
+        Add prompts if shell else final \n if missing.
+        """
+
+        if hasattr(self.editwin, "interp"):  # Saving shell.
+            text = self.editwin.get_prompt_text('1.0', self.text.index('end-1c'))
+        else:
+            if self.text.get("end-2c") != '\n':
+                self.text.insert("end-1c", "\n")  # Changes 'end-1c' value.
+            text = self.text.get('1.0', "end-1c")
         if self.eol_convention != "\n":
             text = text.replace("\n", self.eol_convention)
         return text
index ba33f581ea30f09da4ad3d73bb5e4c8c7f937cff..e7fef5f69daa303ae6f5dc8d4729159d9d034b56 100755 (executable)
@@ -995,6 +995,23 @@ class PyShell(OutputWindow):
     def get_standard_extension_names(self):
         return idleConf.GetExtensions(shell_only=True)
 
+    def get_prompt_text(self, first, last):
+        """Return text between first and last with prompts added."""
+        text = self.text.get(first, last)
+        lineno_range = range(
+            int(float(first)),
+            int(float(last))
+         )
+        prompts = [
+            self.shell_sidebar.line_prompts.get(lineno)
+            for lineno in lineno_range
+        ]
+        return "\n".join(
+            line if prompt is None else f"{prompt} {line}"
+            for prompt, line in zip(prompts, text.splitlines())
+        ) + "\n"
+
+
     def copy_with_prompts_callback(self, event=None):
         """Copy selected lines to the clipboard, with prompts.
 
@@ -1011,23 +1028,9 @@ class PyShell(OutputWindow):
         sellast = text.index('sel.last')
         if sellast[-1] != '0':
             sellast = text.index("sel.last+1line linestart")
-
-        selected_text = self.text.get(selfirst, sellast)
-        selection_lineno_range = range(
-            int(float(selfirst)),
-            int(float(sellast))
-        )
-        prompts = [
-            self.shell_sidebar.line_prompts.get(lineno)
-            for lineno in selection_lineno_range
-        ]
-        selected_text_with_prompts = "\n".join(
-            line if prompt is None else f"{prompt} {line}"
-            for prompt, line in zip(prompts, selected_text.splitlines())
-        ) + "\n"
-
         text.clipboard_clear()
-        text.clipboard_append(selected_text_with_prompts)
+        prompt_text = self.get_prompt_text(selfirst, sellast)
+        text.clipboard_append(prompt_text)
 
     reading = False
     executing = False
diff --git a/Misc/NEWS.d/next/IDLE/2022-08-01-23-31-48.gh-issue-95191.U7vryB.rst b/Misc/NEWS.d/next/IDLE/2022-08-01-23-31-48.gh-issue-95191.U7vryB.rst
new file mode 100644 (file)
index 0000000..94d3dbb
--- /dev/null
@@ -0,0 +1 @@
+Include prompts when saving Shell (interactive input and output).