blob: 1afd19ef3b0d24e45d3685ea80f94cff94a96ae5 [file] [log] [blame]
Steven M. Gava2a63a072001-10-26 06:50:54 +00001"""
Steven M. Gavaad4f5322002-01-03 12:05:17 +00002Provides access to stored idle configuration information.
Steven M. Gavaad4f5322002-01-03 12:05:17 +00003"""
Steven M. Gavac5976402002-01-04 03:06:08 +00004# Throughout this module there is an emphasis on returning useable defaults
5# when a problem occurs in returning a requested configuration value back to
6# idle. This is to allow idle to continue to function in spite of errors in
7# the retrieval of config information. When a default is returned instead of
8# a requested config value, a message is printed to stderr to aid in
9# configuration problem notification and resolution.
10
Steven M. Gava085eb1b2002-02-05 04:52:32 +000011import os, sys, string
Steven M. Gavac11ccf32001-09-24 09:43:17 +000012from ConfigParser import ConfigParser, NoOptionError, NoSectionError
13
14class IdleConfParser(ConfigParser):
15 """
16 A ConfigParser specialised for idle configuration file handling
17 """
18 def __init__(self, cfgFile, cfgDefaults=None):
19 """
20 cfgFile - string, fully specified configuration file name
21 """
22 self.file=cfgFile
23 ConfigParser.__init__(self,defaults=cfgDefaults)
24
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +000025 def Get(self, section, option, type=None, default=None):
Steven M. Gavac11ccf32001-09-24 09:43:17 +000026 """
27 Get an option value for given section/option or return default.
28 If type is specified, return as type.
29 """
Steven M. Gava41a85322001-10-29 08:05:34 +000030 if type=='bool':
31 getVal=self.getboolean
32 elif type=='int':
33 getVal=self.getint
34 else:
35 getVal=self.get
Steven M. Gavac11ccf32001-09-24 09:43:17 +000036 if self.has_option(section,option):
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +000037 #return getVal(section, option, raw, vars, default)
Steven M. Gava429a86af2001-10-23 10:42:12 +000038 return getVal(section, option)
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +000039 else:
40 return default
Steven M. Gavac11ccf32001-09-24 09:43:17 +000041
Steven M. Gavac11ccf32001-09-24 09:43:17 +000042 def GetOptionList(self,section):
43 """
44 Get an option list for given section
45 """
Steven M. Gava085eb1b2002-02-05 04:52:32 +000046 if self.has_section(section):
Steven M. Gavac11ccf32001-09-24 09:43:17 +000047 return self.options(section)
48 else: #return a default value
49 return []
50
Steven M. Gavac11ccf32001-09-24 09:43:17 +000051 def Load(self):
52 """
53 Load the configuration file from disk
54 """
55 self.read(self.file)
56
57class IdleUserConfParser(IdleConfParser):
58 """
Steven M. Gava2d7bb3f2002-01-29 08:35:29 +000059 IdleConfigParser specialised for user configuration handling.
Steven M. Gavac11ccf32001-09-24 09:43:17 +000060 """
Steven M. Gava2d7bb3f2002-01-29 08:35:29 +000061
62 def AddSection(self,section):
63 """
64 if section doesn't exist, add it
65 """
66 if not self.has_section(section):
67 self.add_section(section)
68
69 def RemoveEmptySections(self):
70 """
71 remove any sections that have no options
72 """
73 for section in self.sections():
74 if not self.GetOptionList(section):
75 self.remove_section(section)
76
77 def IsEmpty(self):
78 """
79 Remove empty sections and then return 1 if parser has no sections
80 left, else return 0.
81 """
82 self.RemoveEmptySections()
83 if self.sections():
84 return 0
85 else:
86 return 1
87
88 def RemoveOption(self,section,option):
89 """
90 If section/option exists, remove it.
91 Returns 1 if option was removed, 0 otherwise.
92 """
93 if self.has_section(section):
94 return self.remove_option(section,option)
95
96 def SetOption(self,section,option,value):
97 """
98 Sets option to value, adding section if required.
99 Returns 1 if option was added or changed, otherwise 0.
100 """
101 if self.has_option(section,option):
102 if self.get(section,option)==value:
103 return 0
104 else:
105 self.set(section,option,value)
106 return 1
107 else:
108 if not self.has_section(section):
109 self.add_section(section)
110 self.set(section,option,value)
111 return 1
112
Steven M. Gavab77d3432002-03-02 07:16:21 +0000113 def RemoveFile(self):
114 """
115 Removes the user config file from disk if it exists.
116 """
117 if os.path.exists(self.file):
118 os.remove(self.file)
119
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000120 def Save(self):
121 """
Steven M. Gava2d7bb3f2002-01-29 08:35:29 +0000122 If config isn't empty, write file to disk. If config is empty,
123 remove the file from disk if it exists.
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000124 """
Steven M. Gava2d7bb3f2002-01-29 08:35:29 +0000125 if not self.IsEmpty():
126 cfgFile=open(self.file,'w')
127 self.write(cfgFile)
128 else:
Steven M. Gavab77d3432002-03-02 07:16:21 +0000129 self.RemoveFile()
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000130
131class IdleConf:
132 """
133 holds config parsers for all idle config files:
134 default config files
135 (idle install dir)/config-main.def
136 (idle install dir)/config-extensions.def
137 (idle install dir)/config-highlight.def
138 (idle install dir)/config-keys.def
139 user config files
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000140 (user home dir)/.idlerc/config-main.cfg
141 (user home dir)/.idlerc/config-extensions.cfg
142 (user home dir)/.idlerc/config-highlight.cfg
143 (user home dir)/.idlerc/config-keys.cfg
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000144 """
145 def __init__(self):
146 self.defaultCfg={}
147 self.userCfg={}
148 self.cfg={}
149 self.CreateConfigHandlers()
150 self.LoadCfgFiles()
151 #self.LoadCfg()
152
153 def CreateConfigHandlers(self):
154 """
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000155 set up a dictionary of config parsers for default and user
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000156 configurations respectively
157 """
158 #build idle install path
159 if __name__ != '__main__': # we were imported
Steven M. Gava7cff66d2002-02-01 03:02:37 +0000160 idleDir=os.path.dirname(__file__)
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000161 else: # we were exec'ed (for testing only)
Steven M. Gava7cff66d2002-02-01 03:02:37 +0000162 idleDir=os.path.abspath(sys.path[0])
163 userDir=self.GetUserCfgDir()
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000164 configTypes=('main','extensions','highlight','keys')
165 defCfgFiles={}
166 usrCfgFiles={}
167 for cfgType in configTypes: #build config file names
Steven M. Gava7cff66d2002-02-01 03:02:37 +0000168 defCfgFiles[cfgType]=os.path.join(idleDir,'config-'+cfgType+'.def')
169 usrCfgFiles[cfgType]=os.path.join(userDir,'config-'+cfgType+'.cfg')
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000170 for cfgType in configTypes: #create config parsers
171 self.defaultCfg[cfgType]=IdleConfParser(defCfgFiles[cfgType])
172 self.userCfg[cfgType]=IdleUserConfParser(usrCfgFiles[cfgType])
173
Steven M. Gava7cff66d2002-02-01 03:02:37 +0000174 def GetUserCfgDir(self):
175 """
176 Creates (if required) and returns a filesystem directory for storing
177 user config files.
178 """
179 cfgDir='.idlerc'
180 userDir=os.path.expanduser('~')
181 if userDir != '~': #'HOME' exists as a key in os.environ
182 if not os.path.exists(userDir):
183 warn=('\n Warning: HOME environment variable points to\n '+
184 userDir+'\n but the path does not exist.\n')
185 sys.stderr.write(warn)
186 userDir='~'
187 if userDir=='~': #we still don't have a home directory
188 #traditionally idle has defaulted to os.getcwd(), is this adeqate?
189 userDir = os.getcwd() #hack for no real homedir
190 userDir=os.path.join(userDir,cfgDir)
191 if not os.path.exists(userDir):
192 try: #make the config dir if it doesn't exist yet
193 os.mkdir(userDir)
194 except IOError:
195 warn=('\n Warning: unable to create user config directory\n '+
196 userDir+'\n')
197 sys.stderr.write(warn)
198 return userDir
199
Steven M. Gava2a63a072001-10-26 06:50:54 +0000200 def GetOption(self, configType, section, option, default=None, type=None):
Steven M. Gava429a86af2001-10-23 10:42:12 +0000201 """
202 Get an option value for given config type and given general
203 configuration section/option or return a default. If type is specified,
204 return as type. Firstly the user configuration is checked, with a
205 fallback to the default configuration, and a final 'catch all'
206 fallback to a useable passed-in default if the option isn't present in
207 either the user or the default configuration.
208 configType must be one of ('main','extensions','highlight','keys')
Steven M. Gava0cae01c2002-01-04 07:53:06 +0000209 If a default is returned a warning is printed to stderr.
Steven M. Gava429a86af2001-10-23 10:42:12 +0000210 """
211 if self.userCfg[configType].has_option(section,option):
212 return self.userCfg[configType].Get(section, option, type=type)
213 elif self.defaultCfg[configType].has_option(section,option):
214 return self.defaultCfg[configType].Get(section, option, type=type)
Steven M. Gava052937f2002-02-11 02:20:53 +0000215 else: #returning default, print warning
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000216 warning=('\n Warning: configHandler.py - IdleConf.GetOption -\n'+
217 ' problem retrieving configration option '+`option`+'\n'+
218 ' from section '+`section`+'.\n'+
219 ' returning default value: '+`default`+'\n')
220 sys.stderr.write(warning)
Steven M. Gava429a86af2001-10-23 10:42:12 +0000221 return default
222
Steven M. Gava2a63a072001-10-26 06:50:54 +0000223 def GetSectionList(self, configSet, configType):
224 """
225 Get a list of sections from either the user or default config for
226 the given config type.
227 configSet must be either 'user' or 'default'
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000228 configType must be one of ('main','extensions','highlight','keys')
Steven M. Gava2a63a072001-10-26 06:50:54 +0000229 """
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000230 if not (configType in ('main','extensions','highlight','keys')):
Steven M. Gava2a63a072001-10-26 06:50:54 +0000231 raise 'Invalid configType specified'
232 if configSet == 'user':
233 cfgParser=self.userCfg[configType]
234 elif configSet == 'default':
235 cfgParser=self.defaultCfg[configType]
236 else:
237 raise 'Invalid configSet specified'
Steven M. Gava2a63a072001-10-26 06:50:54 +0000238 return cfgParser.sections()
239
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000240 def GetHighlight(self, theme, element, fgBg=None):
241 """
242 return individual highlighting theme elements.
243 fgBg - string ('fg'or'bg') or None, if None return a dictionary
244 containing fg and bg colours (appropriate for passing to Tkinter in,
245 e.g., a tag_config call), otherwise fg or bg colour only as specified.
246 """
Steven M. Gava9f25e672002-02-11 02:51:18 +0000247 if self.defaultCfg['highlight'].has_section(theme):
248 themeDict=self.GetThemeDict('default',theme)
249 else:
250 themeDict=self.GetThemeDict('user',theme)
251 fore=themeDict[element+'-foreground']
252 if element=='cursor': #there is no config value for cursor bg
253 back=themeDict['normal-background']
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000254 else:
Steven M. Gava9f25e672002-02-11 02:51:18 +0000255 back=themeDict[element+'-background']
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000256 highlight={"foreground": fore,"background": back}
257 if not fgBg: #return dict of both colours
258 return highlight
259 else: #return specified colour only
260 if fgBg == 'fg':
261 return highlight["foreground"]
262 if fgBg == 'bg':
263 return highlight["background"]
264 else:
265 raise 'Invalid fgBg specified'
Steven M. Gava9f25e672002-02-11 02:51:18 +0000266
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000267 def GetThemeDict(self,type,themeName):
Steven M. Gava2a63a072001-10-26 06:50:54 +0000268 """
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000269 type - string, 'default' or 'user' theme type
270 themeName - string, theme name
271 Returns a dictionary which holds {option:value} for each element
272 in the specified theme. Values are loaded over a set of ultimate last
273 fallback defaults to guarantee that all theme elements are present in
274 a newly created theme.
Steven M. Gava2a63a072001-10-26 06:50:54 +0000275 """
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000276 if type == 'user':
277 cfgParser=self.userCfg['highlight']
278 elif type == 'default':
279 cfgParser=self.defaultCfg['highlight']
280 else:
281 raise 'Invalid theme type specified'
282 #foreground and background values are provded for each theme element
283 #(apart from cursor) even though all these values are not yet used
284 #by idle, to allow for their use in the future. Default values are
285 #generally black and white.
286 theme={ 'normal-foreground':'#000000',
287 'normal-background':'#ffffff',
288 'keyword-foreground':'#000000',
289 'keyword-background':'#ffffff',
290 'comment-foreground':'#000000',
291 'comment-background':'#ffffff',
292 'string-foreground':'#000000',
293 'string-background':'#ffffff',
294 'definition-foreground':'#000000',
295 'definition-background':'#ffffff',
296 'hilite-foreground':'#000000',
297 'hilite-background':'gray',
298 'break-foreground':'#ffffff',
299 'break-background':'#000000',
300 'hit-foreground':'#ffffff',
301 'hit-background':'#000000',
302 'error-foreground':'#ffffff',
303 'error-background':'#000000',
304 #cursor (only foreground can be set)
305 'cursor-foreground':'#000000',
306 #shell window
307 'stdout-foreground':'#000000',
308 'stdout-background':'#ffffff',
309 'stderr-foreground':'#000000',
310 'stderr-background':'#ffffff',
311 'console-foreground':'#000000',
312 'console-background':'#ffffff' }
313 for element in theme.keys():
Steven M. Gava052937f2002-02-11 02:20:53 +0000314 if not cfgParser.has_option(themeName,element):
315 #we are going to return a default, print warning
316 warning=('\n Warning: configHandler.py - IdleConf.GetThemeDict'+
317 ' -\n problem retrieving theme element '+`element`+
318 '\n from theme '+`themeName`+'.\n'+
319 ' returning default value: '+`theme[element]`+'\n')
320 sys.stderr.write(warning)
321 colour=cfgParser.Get(themeName,element,default=theme[element])
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000322 theme[element]=colour
323 return theme
324
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000325 def CurrentTheme(self):
326 """
327 Returns the name of the currently active theme
328 """
Steven M. Gava0cae01c2002-01-04 07:53:06 +0000329 return self.GetOption('main','Theme','name',default='')
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000330
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000331 def CurrentKeys(self):
332 """
Steven M. Gava052937f2002-02-11 02:20:53 +0000333 Returns the name of the currently active key set
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000334 """
Steven M. Gava0cae01c2002-01-04 07:53:06 +0000335 return self.GetOption('main','Keys','name',default='')
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000336
337 def GetExtensions(self, activeOnly=1):
338 """
339 Gets a list of all idle extensions declared in the config files.
340 activeOnly - boolean, if true only return active (enabled) extensions
341 """
Steven M. Gavac628a062002-01-19 10:33:21 +0000342 extns=self.RemoveKeyBindNames(
343 self.GetSectionList('default','extensions'))
344 userExtns=self.RemoveKeyBindNames(
345 self.GetSectionList('user','extensions'))
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000346 for extn in userExtns:
347 if extn not in extns: #user has added own extension
348 extns.append(extn)
349 if activeOnly:
350 activeExtns=[]
351 for extn in extns:
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000352 if self.GetOption('extensions',extn,'enable',default=1,
353 type='bool'):
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000354 #the extension is enabled
355 activeExtns.append(extn)
356 return activeExtns
357 else:
358 return extns
359
Steven M. Gavac628a062002-01-19 10:33:21 +0000360 def RemoveKeyBindNames(self,extnNameList):
361 #get rid of keybinding section names
362 names=extnNameList
363 kbNameIndicies=[]
364 for name in names:
365 if name.endswith('_bindings') or name.endswith('_cfgBindings'):
366 kbNameIndicies.append(names.index(name))
367 kbNameIndicies.sort()
368 kbNameIndicies.reverse()
369 for index in kbNameIndicies: #delete each keybinding section name
370 del(names[index])
371 return names
372
Steven M. Gavaa498af22002-02-01 01:33:36 +0000373 def GetExtnNameForEvent(self,virtualEvent):
374 """
375 Returns the name of the extension that virtualEvent is bound in, or
376 None if not bound in any extension.
377 virtualEvent - string, name of the virtual event to test for, without
378 the enclosing '<< >>'
379 """
380 extName=None
381 vEvent='<<'+virtualEvent+'>>'
382 for extn in self.GetExtensions(activeOnly=0):
383 for event in self.GetExtensionKeys(extn).keys():
384 if event == vEvent:
385 extName=extn
Steven M. Gavaa498af22002-02-01 01:33:36 +0000386 return extName
387
Steven M. Gavac628a062002-01-19 10:33:21 +0000388 def GetExtensionKeys(self,extensionName):
389 """
390 returns a dictionary of the configurable keybindings for a particular
391 extension,as they exist in the dictionary returned by GetCurrentKeySet;
Steven M. Gavaa498af22002-02-01 01:33:36 +0000392 that is, where previously used bindings are disabled.
Steven M. Gavac628a062002-01-19 10:33:21 +0000393 """
394 keysName=extensionName+'_cfgBindings'
395 activeKeys=self.GetCurrentKeySet()
396 extKeys={}
397 if self.defaultCfg['extensions'].has_section(keysName):
398 eventNames=self.defaultCfg['extensions'].GetOptionList(keysName)
399 for eventName in eventNames:
400 event='<<'+eventName+'>>'
401 binding=activeKeys[event]
402 extKeys[event]=binding
403 return extKeys
404
405 def __GetRawExtensionKeys(self,extensionName):
406 """
407 returns a dictionary of the configurable keybindings for a particular
408 extension, as defined in the configuration files, or an empty dictionary
409 if no bindings are found
410 """
411 keysName=extensionName+'_cfgBindings'
412 extKeys={}
413 if self.defaultCfg['extensions'].has_section(keysName):
414 eventNames=self.defaultCfg['extensions'].GetOptionList(keysName)
415 for eventName in eventNames:
416 binding=self.GetOption('extensions',keysName,
417 eventName,default='').split()
418 event='<<'+eventName+'>>'
419 extKeys[event]=binding
420 return extKeys
421
422 def GetExtensionBindings(self,extensionName):
423 """
424 Returns a dictionary of all the event bindings for a particular
425 extension. The configurable keybindings are returned as they exist in
426 the dictionary returned by GetCurrentKeySet; that is, where re-used
427 keybindings are disabled.
428 """
429 bindsName=extensionName+'_bindings'
430 extBinds=self.GetExtensionKeys(extensionName)
431 #add the non-configurable bindings
432 if self.defaultCfg['extensions'].has_section(bindsName):
433 eventNames=self.defaultCfg['extensions'].GetOptionList(bindsName)
434 for eventName in eventNames:
435 binding=self.GetOption('extensions',bindsName,
436 eventName,default='').split()
437 event='<<'+eventName+'>>'
438 extBinds[event]=binding
439
440 return extBinds
441
Steven M. Gava0cae01c2002-01-04 07:53:06 +0000442 def GetKeyBinding(self, keySetName, eventStr):
443 """
444 returns the keybinding for a specific event.
445 keySetName - string, name of key binding set
446 eventStr - string, the virtual event we want the binding for,
447 represented as a string, eg. '<<event>>'
448 """
449 eventName=eventStr[2:-2] #trim off the angle brackets
450 binding=self.GetOption('keys',keySetName,eventName,default='').split()
451 return binding
452
Steven M. Gavac628a062002-01-19 10:33:21 +0000453 def GetCurrentKeySet(self):
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000454 return self.GetKeySet(self.CurrentKeys())
455
456 def GetKeySet(self,keySetName):
Steven M. Gava2a63a072001-10-26 06:50:54 +0000457 """
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000458 Returns a dictionary of: all requested core keybindings, plus the
Steven M. Gavac628a062002-01-19 10:33:21 +0000459 keybindings for all currently active extensions. If a binding defined
460 in an extension is already in use, that binding is disabled.
461 """
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000462 keySet=self.GetCoreKeys(keySetName)
Steven M. Gavac628a062002-01-19 10:33:21 +0000463 activeExtns=self.GetExtensions(activeOnly=1)
464 for extn in activeExtns:
465 extKeys=self.__GetRawExtensionKeys(extn)
466 if extKeys: #the extension defines keybindings
467 for event in extKeys.keys():
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000468 if extKeys[event] in keySet.values():
Steven M. Gavac628a062002-01-19 10:33:21 +0000469 #the binding is already in use
470 extKeys[event]='' #disable this binding
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000471 keySet[event]=extKeys[event] #add binding
472 return keySet
473
Steven M. Gavaa498af22002-02-01 01:33:36 +0000474 def IsCoreBinding(self,virtualEvent):
475 """
476 returns true if the virtual event is bound in the core idle keybindings.
477 virtualEvent - string, name of the virtual event to test for, without
478 the enclosing '<< >>'
479 """
480 return ('<<'+virtualEvent+'>>') in self.GetCoreKeys().keys()
481
Steven M. Gavac628a062002-01-19 10:33:21 +0000482 def GetCoreKeys(self, keySetName=None):
483 """
484 returns the requested set of core keybindings, with fallbacks if
485 required.
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000486 Keybindings loaded from the config file(s) are loaded _over_ these
487 defaults, so if there is a problem getting any core binding there will
488 be an 'ultimate last resort fallback' to the CUA-ish bindings
489 defined here.
Steven M. Gava2a63a072001-10-26 06:50:54 +0000490 """
Steven M. Gava17d01542001-12-03 00:37:28 +0000491 keyBindings={
Steven M. Gavaa498af22002-02-01 01:33:36 +0000492 '<<copy>>': ['<Control-c>', '<Control-C>'],
493 '<<cut>>': ['<Control-x>', '<Control-X>'],
494 '<<paste>>': ['<Control-v>', '<Control-V>'],
Steven M. Gava17d01542001-12-03 00:37:28 +0000495 '<<beginning-of-line>>': ['<Control-a>', '<Home>'],
496 '<<center-insert>>': ['<Control-l>'],
497 '<<close-all-windows>>': ['<Control-q>'],
498 '<<close-window>>': ['<Alt-F4>'],
Steven M. Gava17d01542001-12-03 00:37:28 +0000499 '<<end-of-file>>': ['<Control-d>'],
500 '<<python-docs>>': ['<F1>'],
501 '<<python-context-help>>': ['<Shift-F1>'],
502 '<<history-next>>': ['<Alt-n>'],
503 '<<history-previous>>': ['<Alt-p>'],
504 '<<interrupt-execution>>': ['<Control-c>'],
505 '<<open-class-browser>>': ['<Alt-c>'],
506 '<<open-module>>': ['<Alt-m>'],
507 '<<open-new-window>>': ['<Control-n>'],
508 '<<open-window-from-file>>': ['<Control-o>'],
509 '<<plain-newline-and-indent>>': ['<Control-j>'],
Steven M. Gava7981ce52002-06-11 04:45:34 +0000510 '<<print-window>>': ['<Control-p>'],
Steven M. Gava17d01542001-12-03 00:37:28 +0000511 '<<redo>>': ['<Control-y>'],
512 '<<remove-selection>>': ['<Escape>'],
513 '<<save-copy-of-window-as-file>>': ['<Alt-Shift-s>'],
514 '<<save-window-as-file>>': ['<Alt-s>'],
515 '<<save-window>>': ['<Control-s>'],
516 '<<select-all>>': ['<Alt-a>'],
517 '<<toggle-auto-coloring>>': ['<Control-slash>'],
Steven M. Gava0cae01c2002-01-04 07:53:06 +0000518 '<<undo>>': ['<Control-z>'],
519 '<<find-again>>': ['<Control-g>', '<F3>'],
520 '<<find-in-files>>': ['<Alt-F3>'],
521 '<<find-selection>>': ['<Control-F3>'],
522 '<<find>>': ['<Control-f>'],
523 '<<replace>>': ['<Control-h>'],
524 '<<goto-line>>': ['<Alt-g>'] }
Steven M. Gava17d01542001-12-03 00:37:28 +0000525 if keySetName:
Steven M. Gava0cae01c2002-01-04 07:53:06 +0000526 for event in keyBindings.keys():
527 binding=self.GetKeyBinding(keySetName,event)
Steven M. Gava49745752002-02-18 01:43:11 +0000528 if binding:
Steven M. Gava0cae01c2002-01-04 07:53:06 +0000529 keyBindings[event]=binding
Steven M. Gava49745752002-02-18 01:43:11 +0000530 else: #we are going to return a default, print warning
531 warning=('\n Warning: configHandler.py - IdleConf.GetCoreKeys'+
532 ' -\n problem retrieving key binding for event '+
533 `event`+'\n from key set '+`keySetName`+'.\n'+
534 ' returning default value: '+`keyBindings[event]`+'\n')
535 sys.stderr.write(warning)
Steven M. Gava17d01542001-12-03 00:37:28 +0000536 return keyBindings
Steven M. Gava49745752002-02-18 01:43:11 +0000537
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000538 def GetExtraHelpSourceList(self,configSet):
539 """
540 Returns a list of tuples containing the details of any additional
541 help sources configured in the requested configSet ('user' or 'default')
542 , or an empty list if there are none. Returned tuples are of the form
543 form (menu_item , path_to_help_file , option).
544 """
545 helpSources=[]
546 if configSet=='user':
547 cfgParser=self.userCfg['main']
548 elif configSet=='default':
549 cfgParser=self.defaultCfg['main']
550 else:
551 raise 'Invalid configSet specified'
552 options=cfgParser.GetOptionList('HelpFiles')
553 for option in options:
554 value=cfgParser.Get('HelpFiles',option,default=';')
555 if value.find(';')==-1: #malformed config entry with no ';'
556 menuItem='' #make these empty
557 helpPath='' #so value won't be added to list
558 else: #config entry contains ';' as expected
559 value=string.split(value,';')
560 menuItem=value[0].strip()
561 helpPath=value[1].strip()
562 if menuItem and helpPath: #neither are empty strings
563 helpSources.append( (menuItem,helpPath,option) )
564 return helpSources
565
566 def GetAllExtraHelpSourcesList(self):
567 """
568 Returns a list of tuples containing the details of all additional help
569 sources configured, or an empty list if there are none. Tuples are of
570 the format returned by GetExtraHelpSourceList.
571 """
572 allHelpSources=( self.GetExtraHelpSourceList('default')+
573 self.GetExtraHelpSourceList('user') )
574 return allHelpSources
575
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000576 def LoadCfgFiles(self):
577 """
578 load all configuration files.
579 """
580 for key in self.defaultCfg.keys():
581 self.defaultCfg[key].Load()
582 self.userCfg[key].Load() #same keys
583
584 def SaveUserCfgFiles(self):
585 """
586 write all loaded user configuration files back to disk
587 """
588 for key in self.userCfg.keys():
589 self.userCfg[key].Save()
590
591idleConf=IdleConf()
592
593### module test
594if __name__ == '__main__':
595 def dumpCfg(cfg):
596 print '\n',cfg,'\n'
597 for key in cfg.keys():
598 sections=cfg[key].sections()
599 print key
600 print sections
601 for section in sections:
602 options=cfg[key].options(section)
603 print section
604 print options
605 for option in options:
606 print option, '=', cfg[key].Get(section,option)
607 dumpCfg(idleConf.defaultCfg)
608 dumpCfg(idleConf.userCfg)
609 print idleConf.userCfg['main'].Get('Theme','name')
610 #print idleConf.userCfg['highlight'].GetDefHighlight('Foo','normal')