Bruce Sherwood RFE/Patch
SF 661318

Adds autosave capability to IDLE and IDLE configuration dialog.

User can Run/F5 without explicit save dialog.

The default is to require the user to confirm the save.

M ScriptBinding.py
M config-main.def
M configDialog.py
diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py
index b6d9da3..00f533b 100644
--- a/Lib/idlelib/ScriptBinding.py
+++ b/Lib/idlelib/ScriptBinding.py
@@ -24,6 +24,8 @@
 import tkMessageBox
 import PyShell
 
+from configHandler import idleConf
+
 IDENTCHARS = string.ascii_letters + string.digits + "_"
 
 indent_message = """Error: Inconsistent indentation detected!
@@ -144,27 +146,37 @@
         The debugger requires a source file.  Make sure there is one, and that
         the current version of the source buffer has been saved.  If the user
         declines to save or cancels the Save As dialog, return None.
+
+        If the user has configured IDLE for Autosave, the file will be
+        silently saved if it already exists and is dirty.
+        
         """
+        filename = self.editwin.io.filename
         if not self.editwin.get_saved():
-            msg = """Source Must Be Saved
-     OK to Save?"""
-            mb = tkMessageBox.Message(
-                                title="Save Before Run or Check",
-                                message=msg,
-                                icon=tkMessageBox.QUESTION,
-                                type=tkMessageBox.OKCANCEL,
-                                default=tkMessageBox.OK,
-                                master=self.editwin.text)
-            reply = mb.show()
-            if reply == "ok":
+            autosave = idleConf.GetOption('main', 'General',
+                                          'autosave', type='bool')
+            if autosave and filename:
                 self.editwin.io.save(None)
             else:
-                return None
-        # filename is None if file doesn't exist
-        filename = self.editwin.io.filename
-        self.editwin.text.focus_set()
+                reply = self.ask_save_dialog()
+                self.editwin.text.focus_set()
+                if reply == "ok":
+                    self.editwin.io.save(None)
+                    filename = self.editwin.io.filename
+                else:
+                    filename = None
         return filename
 
+    def ask_save_dialog(self):
+        msg = "Source Must Be Saved\n" + 5*' ' + "OK to Save?"
+        mb = tkMessageBox.Message(title="Save Before Run or Check",
+                                  message=msg,
+                                  icon=tkMessageBox.QUESTION,
+                                  type=tkMessageBox.OKCANCEL,
+                                  default=tkMessageBox.OK,
+                                  master=self.editwin.text)
+        return mb.show()
+
     def errorbox(self, title, message):
         # XXX This should really be a function of EditorWindow...
         tkMessageBox.showerror(title, message, master=self.editwin.text)
diff --git a/Lib/idlelib/config-main.def b/Lib/idlelib/config-main.def
index c011048..70b8c1a 100644
--- a/Lib/idlelib/config-main.def
+++ b/Lib/idlelib/config-main.def
@@ -40,6 +40,7 @@
 
 [General]
 editor-on-startup= 0
+autosave= 0
 print-command-posix=lpr %s
 print-command-win=start /min notepad /p %s
 
@@ -49,7 +50,7 @@
 font= courier
 font-size= 12
 font-bold= 0
-encoding=none
+encoding= none
 
 [Indent]
 use-spaces= 1
diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py
index 6cbc74f..bdf253b 100644
--- a/Lib/idlelib/configDialog.py
+++ b/Lib/idlelib/configDialog.py
@@ -334,6 +334,7 @@
         self.winWidth=StringVar(self)
         self.winHeight=StringVar(self)
         self.startupEdit=IntVar(self)
+        self.autoSave=IntVar(self)
         self.encoding=StringVar(self)
         self.userHelpBrowser=BooleanVar(self)
         self.helpBrowser=StringVar(self)
@@ -342,16 +343,24 @@
         frame=self.tabPages.pages['General']['page']
         #body section frames
         frameRun=Frame(frame,borderwidth=2,relief=GROOVE)
+        frameSave=Frame(frame,borderwidth=2,relief=GROOVE)
         frameWinSize=Frame(frame,borderwidth=2,relief=GROOVE)
         frameEncoding=Frame(frame,borderwidth=2,relief=GROOVE)
         frameHelp=Frame(frame,borderwidth=2,relief=GROOVE)
         #frameRun
         labelRunTitle=Label(frameRun,text='Startup Preferences')
-        labelRunChoiceTitle=Label(frameRun,text='On Startup : ')
+        labelRunChoiceTitle=Label(frameRun,text='At Startup')
         radioStartupEdit=Radiobutton(frameRun,variable=self.startupEdit,
             value=1,command=self.SetKeysType,text="Open Edit Window")
         radioStartupShell=Radiobutton(frameRun,variable=self.startupEdit,
             value=0,command=self.SetKeysType,text='Open Shell Window')
+        #frameSave
+        labelSaveTitle=Label(frameSave,text='Autosave Preference')
+        labelRunSaveTitle=Label(frameSave,text='At Start of Run (F5)  ')
+        radioSaveAsk=Radiobutton(frameSave,variable=self.autoSave,
+            value=0,command=self.SetKeysType,text="Prompt to Save")
+        radioSaveAuto=Radiobutton(frameSave,variable=self.autoSave,
+            value=1,command=self.SetKeysType,text='No Prompt')
         #frameWinSize
         labelWinSizeTitle=Label(frameWinSize,text='Initial Window Size'+
                 '  (in characters)')
@@ -370,7 +379,7 @@
         radioEncNone=Radiobutton(frameEncoding,variable=self.encoding,
             value="none",text="None")
         #frameHelp
-        labelHelpTitle=Label(frameHelp,text='Help Options')
+        ##labelHelpTitle=Label(frameHelp,text='Help Options')
         frameHelpList=Frame(frameHelp)
         frameHelpListButtons=Frame(frameHelpList)
         labelHelpListTitle=Label(frameHelpList,text='Additional Help Sources:')
@@ -396,14 +405,20 @@
         #widget packing
         #body
         frameRun.pack(side=TOP,padx=5,pady=5,fill=X)
+        frameSave.pack(side=TOP,padx=5,pady=5,fill=X)
         frameWinSize.pack(side=TOP,padx=5,pady=5,fill=X)
-	frameEncoding.pack(side=TOP,padx=5,pady=5,fill=X)
+        frameEncoding.pack(side=TOP,padx=5,pady=5,fill=X)
         frameHelp.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH)
         #frameRun
         labelRunTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
         labelRunChoiceTitle.pack(side=LEFT,anchor=W,padx=5,pady=5)
-        radioStartupEdit.pack(side=LEFT,anchor=W,padx=5,pady=5)
-        radioStartupShell.pack(side=LEFT,anchor=W,padx=5,pady=5)
+        radioStartupShell.pack(side=RIGHT,anchor=W,padx=5,pady=5)
+        radioStartupEdit.pack(side=RIGHT,anchor=W,padx=5,pady=5)
+        #frameSave
+        labelSaveTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
+        labelRunSaveTitle.pack(side=LEFT,anchor=W,padx=5,pady=5)
+        radioSaveAuto.pack(side=RIGHT,anchor=W,padx=5,pady=5)
+        radioSaveAsk.pack(side=RIGHT,anchor=W,padx=5,pady=5)
         #frameWinSize
         labelWinSizeTitle.pack(side=LEFT,anchor=W,padx=5,pady=5)
         entryWinHeight.pack(side=RIGHT,anchor=E,padx=10,pady=5)
@@ -416,7 +431,7 @@
         radioEncUTF8.pack(side=RIGHT,anchor=E,pady=5)
         radioEncLocale.pack(side=RIGHT,anchor=E,pady=5)
         #frameHelp
-        labelHelpTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
+        ##labelHelpTitle.pack(side=TOP,anchor=W,padx=5,pady=5)
         frameHelpListButtons.pack(side=RIGHT,padx=5,pady=5,fill=Y)
         frameHelpList.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH)
         labelHelpListTitle.pack(side=TOP,anchor=W)
@@ -448,6 +463,7 @@
         self.winWidth.trace_variable('w',self.VarChanged_winWidth)
         self.winHeight.trace_variable('w',self.VarChanged_winHeight)
         self.startupEdit.trace_variable('w',self.VarChanged_startupEdit)
+        self.autoSave.trace_variable('w',self.VarChanged_autoSave)
         self.encoding.trace_variable('w',self.VarChanged_encoding)
 
     def VarChanged_fontSize(self,*params):
@@ -542,6 +558,10 @@
         value=self.startupEdit.get()
         self.AddChangedItem('main','General','editor-on-startup',value)
 
+    def VarChanged_autoSave(self,*params):
+        value=self.autoSave.get()
+        self.AddChangedItem('main','General','autosave',value)
+
     def VarChanged_encoding(self,*params):
         value=self.encoding.get()
         self.AddChangedItem('main','EditorWindow','encoding',value)
@@ -1038,11 +1058,15 @@
         #startup state
         self.startupEdit.set(idleConf.GetOption('main','General',
                 'editor-on-startup',default=1,type='bool'))
+        #autosave state
+        self.autoSave.set(idleConf.GetOption('main', 'General', 'autosave',
+                                             default=0, type='bool'))
         #initial window size
         self.winWidth.set(idleConf.GetOption('main','EditorWindow','width'))
         self.winHeight.set(idleConf.GetOption('main','EditorWindow','height'))
         # default source encoding
-        self.encoding.set(idleConf.GetOption('main','EditorWindow','encoding'))
+        self.encoding.set(idleConf.GetOption('main', 'EditorWindow',
+                                             'encoding', default='none'))
         # additional help sources
         self.userHelpList = idleConf.GetAllExtraHelpSourcesList()
         for helpItem in self.userHelpList: