summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/idlelib/Bindings.py10
-rw-r--r--Lib/idlelib/EditorWindow.py52
-rw-r--r--Lib/idlelib/NEWS.txt21
-rw-r--r--Lib/idlelib/config-main.def33
-rw-r--r--Lib/idlelib/configDialog.py26
-rw-r--r--Lib/idlelib/configHandler.py61
-rw-r--r--Lib/idlelib/configHelpSourceEdit.py47
-rw-r--r--Lib/idlelib/configSectionNameDialog.py6
8 files changed, 164 insertions, 92 deletions
diff --git a/Lib/idlelib/Bindings.py b/Lib/idlelib/Bindings.py
index b177a5e..abce56b 100644
--- a/Lib/idlelib/Bindings.py
+++ b/Lib/idlelib/Bindings.py
@@ -65,16 +65,16 @@ menudefs = [
('!_Auto-open Stack Viewer', '<<toggle-jit-stack-viewer>>' ),
]),
('options', [
- ('_Configure Idle...', '<<open-config-dialog>>'),
+ ('_Configure IDLE...', '<<open-config-dialog>>'),
None,
('Revert to _Default Settings', '<<revert-all-settings>>'),
]),
('help', [
- ('_IDLE Help...', '<<help>>'),
- ('Python _Documentation...', '<<python-docs>>'),
- ('View IDLE _Readme...', '<<view-readme>>'),
+ ('_About IDLE', '<<about-idle>>'),
+ ('IDLE _Readme', '<<view-readme>>'),
None,
- ('_About IDLE...', '<<about-idle>>'),
+ ('_IDLE Help', '<<help>>'),
+ ('Python _Docs', '<<python-docs>>'),
]),
]
diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py
index b940c3b..b9522fc 100644
--- a/Lib/idlelib/EditorWindow.py
+++ b/Lib/idlelib/EditorWindow.py
@@ -247,8 +247,8 @@ class EditorWindow:
menudict[name] = menu = Menu(mbar, name=name)
mbar.add_cascade(label=label, menu=menu, underline=underline)
self.fill_menus()
- #create the ExtraHelp menu, if required
- self.ResetExtraHelpMenu()
+ self.base_helpmenu_length = self.menudict['help'].index(END)
+ self.reset_help_menu_entries()
def postwindowsmenu(self):
# Only called when Windows menu exists
@@ -315,7 +315,8 @@ class EditorWindow:
return "break"
def display_docs(self, url):
- url = os.path.normpath(url)
+ if not (url.startswith('www') or url.startswith('http')):
+ url = os.path.normpath(url)
if sys.platform.count('win') or sys.platform.count('nt'):
os.startfile(url)
else:
@@ -530,29 +531,28 @@ class EditorWindow:
menu.entryconfig(index,accelerator=accel)
#print 'accel now:',accel,'\n'
- def ResetExtraHelpMenu(self):
- "Load or update the Extra Help menu if required"
- menuList=idleConf.GetAllExtraHelpSourcesList()
- helpMenu=self.menudict['help']
- cascadeIndex=helpMenu.index(END)-1
- if menuList:
- if not hasattr(self,'menuExtraHelp'):
- self.menuExtraHelp=Menu(self.menubar)
- helpMenu.insert_cascade(cascadeIndex,label='Extra Help',
- underline=1,menu=self.menuExtraHelp)
- self.menuExtraHelp.delete(1,END)
- for menuItem in menuList:
- self.menuExtraHelp.add_command(label=menuItem[0],
- command=self.__DisplayExtraHelpCallback(menuItem[1]))
- else: #no extra help items
- if hasattr(self,'menuExtraHelp'):
- helpMenu.delete(cascadeIndex-1)
- del(self.menuExtraHelp)
-
- def __DisplayExtraHelpCallback(self,helpFile):
- def DisplayExtraHelp(helpFile=helpFile):
- self.display_docs(helpFile)
- return DisplayExtraHelp
+ def reset_help_menu_entries(self):
+ "Update the additional help entries on the Help menu"
+ help_list = idleConf.GetAllExtraHelpSourcesList()
+ helpmenu = self.menudict['help']
+ # first delete the extra help entries, if any
+ helpmenu_length = helpmenu.index(END)
+ if helpmenu_length > self.base_helpmenu_length:
+ helpmenu.delete((self.base_helpmenu_length + 1), helpmenu_length)
+ # then rebuild them
+ if help_list:
+ helpmenu.add_separator()
+ for entry in help_list:
+ cmd = self.__extra_help_callback(entry[1])
+ helpmenu.add_command(label=entry[0], command=cmd)
+ # and update the menu dictionary
+ self.menudict['help'] = helpmenu
+
+ def __extra_help_callback(self, helpfile):
+ "Create a callback with the helpfile value frozen at definition time"
+ def display_extra_help(helpfile=helpfile):
+ self.display_docs(helpfile)
+ return display_extra_help
def UpdateRecentFilesList(self,newFile=None):
"Load or update the recent files list, and menu if required"
diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt
index de72ea4..f6ed853 100644
--- a/Lib/idlelib/NEWS.txt
+++ b/Lib/idlelib/NEWS.txt
@@ -7,6 +7,27 @@ What's New in IDLEfork 0.9 Alpha 2?
*Release date: XX-XXX-2003*
+- Change default: IDLE now starts with Python Shell.
+
+- Removed the File Path from the Additional Help Sources scrolled list.
+
+- Add capability to access Additional Help Sources on the web if the
+ Help File Path begins with //http or www. (Otherwise local path is
+ validated, as before.)
+
+- Additional Help Sources were not being posted on the Help menu in the
+ order entered. Implement sorting the list by [HelpFiles] 'option'
+ number.
+
+- Add Browse button to New Help Source dialog. Arrange to start in
+ Python/Doc if platform is Windows, otherwise start in current directory.
+
+- Put the Additional Help Sources directly on the Help menu instead of in
+ an Extra Help cascade menu. Rearrange the Help menu so the Additional
+ Help Sources come last. Update help.txt appropriately.
+
+- Fix Tk root pop-ups in configSectionNameDialog.py and configDialog.py
+
- Uniform capitalization in General tab of ConfigDialog, update the doc string.
- Fix bug in ConfigDialog where SaveAllChangedConfig() was unexpectedly
diff --git a/Lib/idlelib/config-main.def b/Lib/idlelib/config-main.def
index cd52b21..9d520c1 100644
--- a/Lib/idlelib/config-main.def
+++ b/Lib/idlelib/config-main.def
@@ -25,9 +25,21 @@
# retained unless specifically deleted within the config dialog. Choosing
# one of the default themes or keysets just applies the relevant settings
# from the default file.
+#
+# Additional help sources are listed in the [HelpFiles] section and must be
+# viewable by a web browser (or the Windows Help viewer in the case of .chm
+# files). These sources will be listed on the Help menu. The pattern is
+# <sequence_number = menu item;/path/to/help/source>
+# You can't use a semi-colon in a menu item or path. The path will be platform
+# specific because of path separators, drive specs etc.
+#
+# It is best to use the Configuration GUI to set up additional help sources!
+# Example:
+#1 = My Extra Help Source;/usr/share/doc/foo/index.html
+#2 = Another Help Source;/path/to/another.pdf
[General]
-editor-on-startup= 1
+editor-on-startup= 0
print-command-posix=lpr %s
print-command-win=start /min notepad /p %s
@@ -51,22 +63,3 @@ default= 1
name= IDLE Classic Windows
[HelpFiles]
-#additional help sources, must be viewable by an html browser
-#will be listed on the Help/Other Help menu
-#option names are the sequence number of the option
-#values take the form: menu item;/path/to/help/source
-#obviously you can't use a semi-colon in a menu item or path and the path will
-#be platform specific because of path separators, drive specs etc.
-#eg.:
-#1= My Extra Help Source;/usr/share/doc/foo/index.html
-#2= Another Help Source;/path/to/another.html
-
-#[RecentFiles]
-#this section will only be present in the user config file idle-main.cfg
-#where it will record the most recently openned files in the form
-#IndexNum= /full/path/of/file , for display on the File/Recent Files menu
-#it is present here for reference only
-#eg.:
-#1=/most/recently/openned/file
-#2=/next/most/recently/openned/file
-#etc.
diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py
index f8db74d..814689c 100644
--- a/Lib/idlelib/configDialog.py
+++ b/Lib/idlelib/configDialog.py
@@ -677,7 +677,8 @@ class ConfigDialog(Toplevel):
def DeleteCustomKeys(self):
keySetName=self.customKeys.get()
if not tkMessageBox.askyesno('Delete Key Set','Are you sure you wish '+
- 'to delete the key set '+`keySetName`+' ?'):
+ 'to delete the key set '+`keySetName`+' ?',
+ parent=self):
return
#remove key set from config
idleConf.userCfg['keys'].remove_section(keySetName)
@@ -703,7 +704,8 @@ class ConfigDialog(Toplevel):
def DeleteCustomTheme(self):
themeName=self.customTheme.get()
if not tkMessageBox.askyesno('Delete Theme','Are you sure you wish '+
- 'to delete the theme '+`themeName`+' ?'):
+ 'to delete the theme '+`themeName`+' ?',
+ parent=self):
return
#remove theme from config
idleConf.userCfg['highlight'].remove_section(themeName)
@@ -874,7 +876,7 @@ class ConfigDialog(Toplevel):
helpSource=GetHelpSourceDialog(self,'New Help Source').result
if helpSource:
self.userHelpList.append( (helpSource[0],helpSource[1]) )
- self.listHelp.insert(END,helpSource[0]+' '+helpSource[1])
+ self.listHelp.insert(END,helpSource[0])
self.UpdateUserHelpChangedItems()
self.SetHelpListButtonStates()
@@ -887,7 +889,7 @@ class ConfigDialog(Toplevel):
return #no changes
self.userHelpList[itemIndex]=newHelpSource
self.listHelp.delete(itemIndex)
- self.listHelp.insert(itemIndex,newHelpSource[0]+' '+newHelpSource[1])
+ self.listHelp.insert(itemIndex,newHelpSource[0])
self.UpdateUserHelpChangedItems()
self.SetHelpListButtonStates()
@@ -899,12 +901,11 @@ class ConfigDialog(Toplevel):
self.SetHelpListButtonStates()
def UpdateUserHelpChangedItems(self):
- #clear and rebuild the HelpFiles section in self.changedItems
- if self.changedItems['main'].has_key('HelpFiles'):
- del(self.changedItems['main']['HelpFiles'])
+ "Clear and rebuild the HelpFiles section in self.changedItems"
+ self.changedItems['main']['HelpFiles'] = {}
for num in range(1,len(self.userHelpList)+1):
self.AddChangedItem('main','HelpFiles',str(num),
- string.join(self.userHelpList[num-1],';'))
+ string.join(self.userHelpList[num-1][:2],';'))
def LoadFontCfg(self):
##base editor font selection list
@@ -1019,10 +1020,10 @@ class ConfigDialog(Toplevel):
#initial window size
self.winWidth.set(idleConf.GetOption('main','EditorWindow','width'))
self.winHeight.set(idleConf.GetOption('main','EditorWindow','height'))
- #help browsing
- self.userHelpList=idleConf.GetExtraHelpSourceList('user')
+ # additional help sources
+ self.userHelpList = idleConf.GetAllExtraHelpSourcesList()
for helpItem in self.userHelpList:
- self.listHelp.insert(END,helpItem[0]+' '+helpItem[1])
+ self.listHelp.insert(END,helpItem[0])
self.SetHelpListButtonStates()
#self.userHelpBrowser.set(idleConf.GetOption('main','General',
# 'user-help-browser',default=0,type='bool'))
@@ -1086,6 +1087,7 @@ class ConfigDialog(Toplevel):
if section == 'HelpFiles':
#this section gets completely replaced
idleConf.userCfg['main'].remove_section('HelpFiles')
+ cfgTypeHasChanges = True
for item in self.changedItems[configType][section].keys():
value = self.changedItems[configType][section][item]
if self.SetUserValue(configType,section,item,value):
@@ -1107,7 +1109,7 @@ class ConfigDialog(Toplevel):
instance.ResetColorizer()
instance.ResetFont()
instance.ResetKeybindings()
- instance.ResetExtraHelpMenu()
+ instance.reset_help_menu_entries()
def Cancel(self):
self.destroy()
diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py
index cf2b6db..22e83a6 100644
--- a/Lib/idlelib/configHandler.py
+++ b/Lib/idlelib/configHandler.py
@@ -1,14 +1,25 @@
+"""Provides access to stored IDLE configuration information.
+
+Refer to the comments at the beginning of config-main.def for a description of
+the available configuration files and the design implemented to update user
+configuration information. In particular, user configuration choices which
+duplicate the defaults will be removed from the user's configuration files,
+and if a file becomes empty, it will be deleted.
+
+The contents of the user files may be altered using the Options/Configure IDLE
+menu to access the configuration GUI (configDialog.py), or manually.
+
+Throughout this module there is an emphasis on returning useable defaults
+when a problem occurs in returning a requested configuration value back to
+idle. This is to allow IDLE to continue to function in spite of errors in
+the retrieval of config information. When a default is returned instead of
+a requested config value, a message is printed to stderr to aid in
+configuration problem notification and resolution.
+
"""
-Provides access to stored idle configuration information.
-"""
-# Throughout this module there is an emphasis on returning useable defaults
-# when a problem occurs in returning a requested configuration value back to
-# idle. This is to allow idle to continue to function in spite of errors in
-# the retrieval of config information. When a default is returned instead of
-# a requested config value, a message is printed to stderr to aid in
-# configuration problem notification and resolution.
-
-import os, sys, string
+import os
+import sys
+import string
from ConfigParser import ConfigParser, NoOptionError, NoSectionError
class InvalidConfigType(Exception): pass
@@ -123,9 +134,11 @@ class IdleUserConfParser(IdleConfParser):
os.remove(self.file)
def Save(self):
- """
- If config isn't empty, write file to disk. If config is empty,
- remove the file from disk if it exists.
+ """Update user configuration file.
+
+ Remove empty sections. If resulting config isn't empty, write the file
+ to disk. If config is empty, remove the file from disk if it exists.
+
"""
if not self.IsEmpty():
cfgFile=open(self.file,'w')
@@ -555,11 +568,14 @@ class IdleConf:
return keyBindings
def GetExtraHelpSourceList(self,configSet):
- """
- Returns a list of tuples containing the details of any additional
- help sources configured in the requested configSet ('user' or 'default')
- , or an empty list if there are none. Returned tuples are of the form
- form (menu_item , path_to_help_file , option).
+ """Fetch list of extra help sources from a given configSet.
+
+ Valid configSets are 'user' or 'default'. Return a list of tuples of
+ the form (menu_item , path_to_help_file , option), or return the empty
+ list. 'option' is the sequence number of the help resource. 'option'
+ values determine the position of the menu items on the Help menu,
+ therefore the returned list must be sorted by 'option'.
+
"""
helpSources=[]
if configSet=='user':
@@ -580,8 +596,17 @@ class IdleConf:
helpPath=value[1].strip()
if menuItem and helpPath: #neither are empty strings
helpSources.append( (menuItem,helpPath,option) )
+ helpSources.sort(self.__helpsort)
return helpSources
+ def __helpsort(self, h1, h2):
+ if int(h1[2]) < int(h2[2]):
+ return -1
+ elif int(h1[2]) > int(h2[2]):
+ return 1
+ else:
+ return 0
+
def GetAllExtraHelpSourcesList(self):
"""
Returns a list of tuples containing the details of all additional help
diff --git a/Lib/idlelib/configHelpSourceEdit.py b/Lib/idlelib/configHelpSourceEdit.py
index bd799da..25569ca 100644
--- a/Lib/idlelib/configHelpSourceEdit.py
+++ b/Lib/idlelib/configHelpSourceEdit.py
@@ -1,14 +1,19 @@
"Dialog to specify or edit the parameters for a user configured help source."
+import os
+
from Tkinter import *
import tkMessageBox
-import os
+import tkFileDialog
class GetHelpSourceDialog(Toplevel):
def __init__(self, parent, title, menuItem='', filePath=''):
- """
- menuItem - string, the menu item to edit, if any
- filePath - string, the help file path to edit, if any
+ """Get menu entry and url/ local file location for Additional Help
+
+ User selects a name for the Help resource and provides a web url
+ or a local file as its source. The user can enter a url or browse
+ for the file.
+
"""
Toplevel.__init__(self, parent)
self.configure(borderwidth=5)
@@ -39,7 +44,7 @@ class GetHelpSourceDialog(Toplevel):
self.menu = StringVar(self)
self.path = StringVar(self)
self.fontSize = StringVar(self)
- self.frameMain = Frame(self, borderwidth=2, relief=SUNKEN)
+ self.frameMain = Frame(self, borderwidth=2, relief=GROOVE)
self.frameMain.pack(side=TOP, expand=TRUE, fill=BOTH)
labelMenu = Label(self.frameMain, anchor=W, justify=LEFT,
text='Menu Item:')
@@ -47,7 +52,7 @@ class GetHelpSourceDialog(Toplevel):
width=30)
self.entryMenu.focus_set()
labelPath = Label(self.frameMain, anchor=W, justify=LEFT,
- text='Help File Path:')
+ text='Help File Path: Enter URL or browse for file')
self.entryPath = Entry(self.frameMain, textvariable=self.path,
width=40)
self.entryMenu.focus_set()
@@ -55,17 +60,41 @@ class GetHelpSourceDialog(Toplevel):
self.entryMenu.pack(anchor=W, padx=5, pady=3)
labelPath.pack(anchor=W, padx=5, pady=3)
self.entryPath.pack(anchor=W, padx=5, pady=3)
+ browseButton = Button(self.frameMain, text='Browse', width=8,
+ command=self.browseFile)
+ browseButton.pack(pady=3)
frameButtons = Frame(self)
frameButtons.pack(side=BOTTOM, fill=X)
self.buttonOk = Button(frameButtons, text='OK',
width=8, default=ACTIVE, command=self.Ok)
self.buttonOk.grid(row=0, column=0, padx=5,pady=5)
- self.buttonOk.bind('<Return>', self.Ok)
- #self.buttonOk.focus()
self.buttonCancel = Button(frameButtons, text='Cancel',
width=8, command=self.Cancel)
self.buttonCancel.grid(row=0, column=1, padx=5, pady=5)
+ def browseFile(self):
+ filetypes = [
+ ("HTML Files", "*.htm *.html", "TEXT"),
+ ("PDF Files", "*.pdf", "TEXT"),
+ ("Windows Help Files", "*.chm"),
+ ("Text Files", "*.txt", "TEXT"),
+ ("All Files", "*")]
+ path = self.path.get()
+ if path:
+ dir, base = os.path.split(path)
+ else:
+ base = None
+ if sys.platform.count('win') or sys.platform.count('nt'):
+ dir = os.path.join(os.path.dirname(sys.executable), 'Doc')
+ if not os.path.isdir(dir):
+ dir = os.getcwd()
+ else:
+ dir = os.getcwd()
+ opendialog = tkFileDialog.Open(parent=self, filetypes=filetypes)
+ file = opendialog.show(initialdir=dir, initialfile=base)
+ if file:
+ self.path.set(file)
+
def MenuOk(self):
"Simple validity check for a sensible menu item name"
menuOk = True
@@ -97,6 +126,8 @@ class GetHelpSourceDialog(Toplevel):
parent=self)
self.entryPath.focus_set()
pathOk = False
+ elif path.startswith('www.') or path.startswith('http'):
+ pathOk = True
elif not os.path.exists(path):
tkMessageBox.showerror(title='File Path Error',
message='Help file path does not exist.',
diff --git a/Lib/idlelib/configSectionNameDialog.py b/Lib/idlelib/configSectionNameDialog.py
index 7b768f1..4f1b002 100644
--- a/Lib/idlelib/configSectionNameDialog.py
+++ b/Lib/idlelib/configSectionNameDialog.py
@@ -63,16 +63,16 @@ class GetCfgSectionNameDialog(Toplevel):
name.strip()
if not name: #no name specified
tkMessageBox.showerror(title='Name Error',
- message='No name specified.')
+ message='No name specified.', parent=self)
nameOk=0
elif len(name)>30: #name too long
tkMessageBox.showerror(title='Name Error',
message='Name too long. It should be no more than '+
- '30 characters.')
+ '30 characters.', parent=self)
nameOk=0
elif name in self.usedNames:
tkMessageBox.showerror(title='Name Error',
- message='This name is already in use.')
+ message='This name is already in use.', parent=self)
nameOk=0
return nameOk