blob: 9db712031f1f7b5138c3633f88aa57d5cf83101b [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. Gavac11ccf32001-09-24 09:43:17 +0000113 def Save(self):
114 """
Steven M. Gava2d7bb3f2002-01-29 08:35:29 +0000115 If config isn't empty, write file to disk. If config is empty,
116 remove the file from disk if it exists.
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000117 """
Steven M. Gava2d7bb3f2002-01-29 08:35:29 +0000118 if not self.IsEmpty():
119 cfgFile=open(self.file,'w')
120 self.write(cfgFile)
121 else:
122 if os.path.exists(self.file):
123 os.remove(self.file)
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000124
125class IdleConf:
126 """
127 holds config parsers for all idle config files:
128 default config files
129 (idle install dir)/config-main.def
130 (idle install dir)/config-extensions.def
131 (idle install dir)/config-highlight.def
132 (idle install dir)/config-keys.def
133 user config files
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000134 (user home dir)/.idlerc/config-main.cfg
135 (user home dir)/.idlerc/config-extensions.cfg
136 (user home dir)/.idlerc/config-highlight.cfg
137 (user home dir)/.idlerc/config-keys.cfg
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000138 """
139 def __init__(self):
140 self.defaultCfg={}
141 self.userCfg={}
142 self.cfg={}
143 self.CreateConfigHandlers()
144 self.LoadCfgFiles()
145 #self.LoadCfg()
146
147 def CreateConfigHandlers(self):
148 """
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000149 set up a dictionary of config parsers for default and user
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000150 configurations respectively
151 """
152 #build idle install path
153 if __name__ != '__main__': # we were imported
Steven M. Gava7cff66d2002-02-01 03:02:37 +0000154 idleDir=os.path.dirname(__file__)
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000155 else: # we were exec'ed (for testing only)
Steven M. Gava7cff66d2002-02-01 03:02:37 +0000156 idleDir=os.path.abspath(sys.path[0])
157 userDir=self.GetUserCfgDir()
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000158 configTypes=('main','extensions','highlight','keys')
159 defCfgFiles={}
160 usrCfgFiles={}
161 for cfgType in configTypes: #build config file names
Steven M. Gava7cff66d2002-02-01 03:02:37 +0000162 defCfgFiles[cfgType]=os.path.join(idleDir,'config-'+cfgType+'.def')
163 usrCfgFiles[cfgType]=os.path.join(userDir,'config-'+cfgType+'.cfg')
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000164 for cfgType in configTypes: #create config parsers
165 self.defaultCfg[cfgType]=IdleConfParser(defCfgFiles[cfgType])
166 self.userCfg[cfgType]=IdleUserConfParser(usrCfgFiles[cfgType])
167
Steven M. Gava7cff66d2002-02-01 03:02:37 +0000168 def GetUserCfgDir(self):
169 """
170 Creates (if required) and returns a filesystem directory for storing
171 user config files.
172 """
173 cfgDir='.idlerc'
174 userDir=os.path.expanduser('~')
175 if userDir != '~': #'HOME' exists as a key in os.environ
176 if not os.path.exists(userDir):
177 warn=('\n Warning: HOME environment variable points to\n '+
178 userDir+'\n but the path does not exist.\n')
179 sys.stderr.write(warn)
180 userDir='~'
181 if userDir=='~': #we still don't have a home directory
182 #traditionally idle has defaulted to os.getcwd(), is this adeqate?
183 userDir = os.getcwd() #hack for no real homedir
184 userDir=os.path.join(userDir,cfgDir)
185 if not os.path.exists(userDir):
186 try: #make the config dir if it doesn't exist yet
187 os.mkdir(userDir)
188 except IOError:
189 warn=('\n Warning: unable to create user config directory\n '+
190 userDir+'\n')
191 sys.stderr.write(warn)
192 return userDir
193
Steven M. Gava2a63a072001-10-26 06:50:54 +0000194 def GetOption(self, configType, section, option, default=None, type=None):
Steven M. Gava429a86af2001-10-23 10:42:12 +0000195 """
196 Get an option value for given config type and given general
197 configuration section/option or return a default. If type is specified,
198 return as type. Firstly the user configuration is checked, with a
199 fallback to the default configuration, and a final 'catch all'
200 fallback to a useable passed-in default if the option isn't present in
201 either the user or the default configuration.
202 configType must be one of ('main','extensions','highlight','keys')
Steven M. Gava0cae01c2002-01-04 07:53:06 +0000203 If a default is returned a warning is printed to stderr.
Steven M. Gava429a86af2001-10-23 10:42:12 +0000204 """
205 if self.userCfg[configType].has_option(section,option):
206 return self.userCfg[configType].Get(section, option, type=type)
207 elif self.defaultCfg[configType].has_option(section,option):
208 return self.defaultCfg[configType].Get(section, option, type=type)
Steven M. Gava052937f2002-02-11 02:20:53 +0000209 else: #returning default, print warning
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000210 warning=('\n Warning: configHandler.py - IdleConf.GetOption -\n'+
211 ' problem retrieving configration option '+`option`+'\n'+
212 ' from section '+`section`+'.\n'+
213 ' returning default value: '+`default`+'\n')
214 sys.stderr.write(warning)
Steven M. Gava429a86af2001-10-23 10:42:12 +0000215 return default
216
Steven M. Gava2a63a072001-10-26 06:50:54 +0000217 def GetSectionList(self, configSet, configType):
218 """
219 Get a list of sections from either the user or default config for
220 the given config type.
221 configSet must be either 'user' or 'default'
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000222 configType must be one of ('main','extensions','highlight','keys')
Steven M. Gava2a63a072001-10-26 06:50:54 +0000223 """
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000224 if not (configType in ('main','extensions','highlight','keys')):
Steven M. Gava2a63a072001-10-26 06:50:54 +0000225 raise 'Invalid configType specified'
226 if configSet == 'user':
227 cfgParser=self.userCfg[configType]
228 elif configSet == 'default':
229 cfgParser=self.defaultCfg[configType]
230 else:
231 raise 'Invalid configSet specified'
Steven M. Gava2a63a072001-10-26 06:50:54 +0000232 return cfgParser.sections()
233
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000234 def GetHighlight(self, theme, element, fgBg=None):
235 """
236 return individual highlighting theme elements.
237 fgBg - string ('fg'or'bg') or None, if None return a dictionary
238 containing fg and bg colours (appropriate for passing to Tkinter in,
239 e.g., a tag_config call), otherwise fg or bg colour only as specified.
240 """
Steven M. Gava9f25e672002-02-11 02:51:18 +0000241 if self.defaultCfg['highlight'].has_section(theme):
242 themeDict=self.GetThemeDict('default',theme)
243 else:
244 themeDict=self.GetThemeDict('user',theme)
245 fore=themeDict[element+'-foreground']
246 if element=='cursor': #there is no config value for cursor bg
247 back=themeDict['normal-background']
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000248 else:
Steven M. Gava9f25e672002-02-11 02:51:18 +0000249 back=themeDict[element+'-background']
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000250 highlight={"foreground": fore,"background": back}
251 if not fgBg: #return dict of both colours
252 return highlight
253 else: #return specified colour only
254 if fgBg == 'fg':
255 return highlight["foreground"]
256 if fgBg == 'bg':
257 return highlight["background"]
258 else:
259 raise 'Invalid fgBg specified'
Steven M. Gava9f25e672002-02-11 02:51:18 +0000260
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000261 def GetThemeDict(self,type,themeName):
Steven M. Gava2a63a072001-10-26 06:50:54 +0000262 """
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000263 type - string, 'default' or 'user' theme type
264 themeName - string, theme name
265 Returns a dictionary which holds {option:value} for each element
266 in the specified theme. Values are loaded over a set of ultimate last
267 fallback defaults to guarantee that all theme elements are present in
268 a newly created theme.
Steven M. Gava2a63a072001-10-26 06:50:54 +0000269 """
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000270 if type == 'user':
271 cfgParser=self.userCfg['highlight']
272 elif type == 'default':
273 cfgParser=self.defaultCfg['highlight']
274 else:
275 raise 'Invalid theme type specified'
276 #foreground and background values are provded for each theme element
277 #(apart from cursor) even though all these values are not yet used
278 #by idle, to allow for their use in the future. Default values are
279 #generally black and white.
280 theme={ 'normal-foreground':'#000000',
281 'normal-background':'#ffffff',
282 'keyword-foreground':'#000000',
283 'keyword-background':'#ffffff',
284 'comment-foreground':'#000000',
285 'comment-background':'#ffffff',
286 'string-foreground':'#000000',
287 'string-background':'#ffffff',
288 'definition-foreground':'#000000',
289 'definition-background':'#ffffff',
290 'hilite-foreground':'#000000',
291 'hilite-background':'gray',
292 'break-foreground':'#ffffff',
293 'break-background':'#000000',
294 'hit-foreground':'#ffffff',
295 'hit-background':'#000000',
296 'error-foreground':'#ffffff',
297 'error-background':'#000000',
298 #cursor (only foreground can be set)
299 'cursor-foreground':'#000000',
300 #shell window
301 'stdout-foreground':'#000000',
302 'stdout-background':'#ffffff',
303 'stderr-foreground':'#000000',
304 'stderr-background':'#ffffff',
305 'console-foreground':'#000000',
306 'console-background':'#ffffff' }
307 for element in theme.keys():
Steven M. Gava052937f2002-02-11 02:20:53 +0000308 if not cfgParser.has_option(themeName,element):
309 #we are going to return a default, print warning
310 warning=('\n Warning: configHandler.py - IdleConf.GetThemeDict'+
311 ' -\n problem retrieving theme element '+`element`+
312 '\n from theme '+`themeName`+'.\n'+
313 ' returning default value: '+`theme[element]`+'\n')
314 sys.stderr.write(warning)
315 colour=cfgParser.Get(themeName,element,default=theme[element])
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000316 theme[element]=colour
317 return theme
318
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000319 def CurrentTheme(self):
320 """
321 Returns the name of the currently active theme
322 """
Steven M. Gava0cae01c2002-01-04 07:53:06 +0000323 return self.GetOption('main','Theme','name',default='')
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000324
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000325 def CurrentKeys(self):
326 """
Steven M. Gava052937f2002-02-11 02:20:53 +0000327 Returns the name of the currently active key set
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000328 """
Steven M. Gava0cae01c2002-01-04 07:53:06 +0000329 return self.GetOption('main','Keys','name',default='')
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000330
331 def GetExtensions(self, activeOnly=1):
332 """
333 Gets a list of all idle extensions declared in the config files.
334 activeOnly - boolean, if true only return active (enabled) extensions
335 """
Steven M. Gavac628a062002-01-19 10:33:21 +0000336 extns=self.RemoveKeyBindNames(
337 self.GetSectionList('default','extensions'))
338 userExtns=self.RemoveKeyBindNames(
339 self.GetSectionList('user','extensions'))
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000340 for extn in userExtns:
341 if extn not in extns: #user has added own extension
342 extns.append(extn)
343 if activeOnly:
344 activeExtns=[]
345 for extn in extns:
Steven M. Gava5f28e8f2002-01-21 06:38:21 +0000346 if self.GetOption('extensions',extn,'enable',default=1,
347 type='bool'):
Steven M. Gavaad4f5322002-01-03 12:05:17 +0000348 #the extension is enabled
349 activeExtns.append(extn)
350 return activeExtns
351 else:
352 return extns
353
Steven M. Gavac628a062002-01-19 10:33:21 +0000354 def RemoveKeyBindNames(self,extnNameList):
355 #get rid of keybinding section names
356 names=extnNameList
357 kbNameIndicies=[]
358 for name in names:
359 if name.endswith('_bindings') or name.endswith('_cfgBindings'):
360 kbNameIndicies.append(names.index(name))
361 kbNameIndicies.sort()
362 kbNameIndicies.reverse()
363 for index in kbNameIndicies: #delete each keybinding section name
364 del(names[index])
365 return names
366
Steven M. Gavaa498af22002-02-01 01:33:36 +0000367 def GetExtnNameForEvent(self,virtualEvent):
368 """
369 Returns the name of the extension that virtualEvent is bound in, or
370 None if not bound in any extension.
371 virtualEvent - string, name of the virtual event to test for, without
372 the enclosing '<< >>'
373 """
374 extName=None
375 vEvent='<<'+virtualEvent+'>>'
376 for extn in self.GetExtensions(activeOnly=0):
377 for event in self.GetExtensionKeys(extn).keys():
378 if event == vEvent:
379 extName=extn
Steven M. Gavaa498af22002-02-01 01:33:36 +0000380 return extName
381
Steven M. Gavac628a062002-01-19 10:33:21 +0000382 def GetExtensionKeys(self,extensionName):
383 """
384 returns a dictionary of the configurable keybindings for a particular
385 extension,as they exist in the dictionary returned by GetCurrentKeySet;
Steven M. Gavaa498af22002-02-01 01:33:36 +0000386 that is, where previously used bindings are disabled.
Steven M. Gavac628a062002-01-19 10:33:21 +0000387 """
388 keysName=extensionName+'_cfgBindings'
389 activeKeys=self.GetCurrentKeySet()
390 extKeys={}
391 if self.defaultCfg['extensions'].has_section(keysName):
392 eventNames=self.defaultCfg['extensions'].GetOptionList(keysName)
393 for eventName in eventNames:
394 event='<<'+eventName+'>>'
395 binding=activeKeys[event]
396 extKeys[event]=binding
397 return extKeys
398
399 def __GetRawExtensionKeys(self,extensionName):
400 """
401 returns a dictionary of the configurable keybindings for a particular
402 extension, as defined in the configuration files, or an empty dictionary
403 if no bindings are found
404 """
405 keysName=extensionName+'_cfgBindings'
406 extKeys={}
407 if self.defaultCfg['extensions'].has_section(keysName):
408 eventNames=self.defaultCfg['extensions'].GetOptionList(keysName)
409 for eventName in eventNames:
410 binding=self.GetOption('extensions',keysName,
411 eventName,default='').split()
412 event='<<'+eventName+'>>'
413 extKeys[event]=binding
414 return extKeys
415
416 def GetExtensionBindings(self,extensionName):
417 """
418 Returns a dictionary of all the event bindings for a particular
419 extension. The configurable keybindings are returned as they exist in
420 the dictionary returned by GetCurrentKeySet; that is, where re-used
421 keybindings are disabled.
422 """
423 bindsName=extensionName+'_bindings'
424 extBinds=self.GetExtensionKeys(extensionName)
425 #add the non-configurable bindings
426 if self.defaultCfg['extensions'].has_section(bindsName):
427 eventNames=self.defaultCfg['extensions'].GetOptionList(bindsName)
428 for eventName in eventNames:
429 binding=self.GetOption('extensions',bindsName,
430 eventName,default='').split()
431 event='<<'+eventName+'>>'
432 extBinds[event]=binding
433
434 return extBinds
435
Steven M. Gava0cae01c2002-01-04 07:53:06 +0000436 def GetKeyBinding(self, keySetName, eventStr):
437 """
438 returns the keybinding for a specific event.
439 keySetName - string, name of key binding set
440 eventStr - string, the virtual event we want the binding for,
441 represented as a string, eg. '<<event>>'
442 """
443 eventName=eventStr[2:-2] #trim off the angle brackets
444 binding=self.GetOption('keys',keySetName,eventName,default='').split()
445 return binding
446
Steven M. Gavac628a062002-01-19 10:33:21 +0000447 def GetCurrentKeySet(self):
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000448 return self.GetKeySet(self.CurrentKeys())
449
450 def GetKeySet(self,keySetName):
Steven M. Gava2a63a072001-10-26 06:50:54 +0000451 """
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000452 Returns a dictionary of: all requested core keybindings, plus the
Steven M. Gavac628a062002-01-19 10:33:21 +0000453 keybindings for all currently active extensions. If a binding defined
454 in an extension is already in use, that binding is disabled.
455 """
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000456 keySet=self.GetCoreKeys(keySetName)
Steven M. Gavac628a062002-01-19 10:33:21 +0000457 activeExtns=self.GetExtensions(activeOnly=1)
458 for extn in activeExtns:
459 extKeys=self.__GetRawExtensionKeys(extn)
460 if extKeys: #the extension defines keybindings
461 for event in extKeys.keys():
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000462 if extKeys[event] in keySet.values():
Steven M. Gavac628a062002-01-19 10:33:21 +0000463 #the binding is already in use
464 extKeys[event]='' #disable this binding
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000465 keySet[event]=extKeys[event] #add binding
466 return keySet
467
Steven M. Gavaa498af22002-02-01 01:33:36 +0000468 def IsCoreBinding(self,virtualEvent):
469 """
470 returns true if the virtual event is bound in the core idle keybindings.
471 virtualEvent - string, name of the virtual event to test for, without
472 the enclosing '<< >>'
473 """
474 return ('<<'+virtualEvent+'>>') in self.GetCoreKeys().keys()
475
Steven M. Gavac628a062002-01-19 10:33:21 +0000476 def GetCoreKeys(self, keySetName=None):
477 """
478 returns the requested set of core keybindings, with fallbacks if
479 required.
Steven M. Gavaf9bb90e2002-01-24 06:02:50 +0000480 Keybindings loaded from the config file(s) are loaded _over_ these
481 defaults, so if there is a problem getting any core binding there will
482 be an 'ultimate last resort fallback' to the CUA-ish bindings
483 defined here.
Steven M. Gava2a63a072001-10-26 06:50:54 +0000484 """
Steven M. Gava17d01542001-12-03 00:37:28 +0000485 keyBindings={
Steven M. Gavaa498af22002-02-01 01:33:36 +0000486 '<<copy>>': ['<Control-c>', '<Control-C>'],
487 '<<cut>>': ['<Control-x>', '<Control-X>'],
488 '<<paste>>': ['<Control-v>', '<Control-V>'],
Steven M. Gava17d01542001-12-03 00:37:28 +0000489 '<<beginning-of-line>>': ['<Control-a>', '<Home>'],
490 '<<center-insert>>': ['<Control-l>'],
491 '<<close-all-windows>>': ['<Control-q>'],
492 '<<close-window>>': ['<Alt-F4>'],
Steven M. Gava17d01542001-12-03 00:37:28 +0000493 '<<end-of-file>>': ['<Control-d>'],
494 '<<python-docs>>': ['<F1>'],
495 '<<python-context-help>>': ['<Shift-F1>'],
496 '<<history-next>>': ['<Alt-n>'],
497 '<<history-previous>>': ['<Alt-p>'],
498 '<<interrupt-execution>>': ['<Control-c>'],
499 '<<open-class-browser>>': ['<Alt-c>'],
500 '<<open-module>>': ['<Alt-m>'],
501 '<<open-new-window>>': ['<Control-n>'],
502 '<<open-window-from-file>>': ['<Control-o>'],
503 '<<plain-newline-and-indent>>': ['<Control-j>'],
504 '<<redo>>': ['<Control-y>'],
505 '<<remove-selection>>': ['<Escape>'],
506 '<<save-copy-of-window-as-file>>': ['<Alt-Shift-s>'],
507 '<<save-window-as-file>>': ['<Alt-s>'],
508 '<<save-window>>': ['<Control-s>'],
509 '<<select-all>>': ['<Alt-a>'],
510 '<<toggle-auto-coloring>>': ['<Control-slash>'],
Steven M. Gava0cae01c2002-01-04 07:53:06 +0000511 '<<undo>>': ['<Control-z>'],
512 '<<find-again>>': ['<Control-g>', '<F3>'],
513 '<<find-in-files>>': ['<Alt-F3>'],
514 '<<find-selection>>': ['<Control-F3>'],
515 '<<find>>': ['<Control-f>'],
516 '<<replace>>': ['<Control-h>'],
517 '<<goto-line>>': ['<Alt-g>'] }
Steven M. Gava17d01542001-12-03 00:37:28 +0000518 if keySetName:
Steven M. Gava0cae01c2002-01-04 07:53:06 +0000519 for event in keyBindings.keys():
520 binding=self.GetKeyBinding(keySetName,event)
Steven M. Gava49745752002-02-18 01:43:11 +0000521 if binding:
Steven M. Gava0cae01c2002-01-04 07:53:06 +0000522 keyBindings[event]=binding
Steven M. Gava49745752002-02-18 01:43:11 +0000523 else: #we are going to return a default, print warning
524 warning=('\n Warning: configHandler.py - IdleConf.GetCoreKeys'+
525 ' -\n problem retrieving key binding for event '+
526 `event`+'\n from key set '+`keySetName`+'.\n'+
527 ' returning default value: '+`keyBindings[event]`+'\n')
528 sys.stderr.write(warning)
Steven M. Gava17d01542001-12-03 00:37:28 +0000529 return keyBindings
Steven M. Gava49745752002-02-18 01:43:11 +0000530
Steven M. Gava085eb1b2002-02-05 04:52:32 +0000531 def GetExtraHelpSourceList(self,configSet):
532 """
533 Returns a list of tuples containing the details of any additional
534 help sources configured in the requested configSet ('user' or 'default')
535 , or an empty list if there are none. Returned tuples are of the form
536 form (menu_item , path_to_help_file , option).
537 """
538 helpSources=[]
539 if configSet=='user':
540 cfgParser=self.userCfg['main']
541 elif configSet=='default':
542 cfgParser=self.defaultCfg['main']
543 else:
544 raise 'Invalid configSet specified'
545 options=cfgParser.GetOptionList('HelpFiles')
546 for option in options:
547 value=cfgParser.Get('HelpFiles',option,default=';')
548 if value.find(';')==-1: #malformed config entry with no ';'
549 menuItem='' #make these empty
550 helpPath='' #so value won't be added to list
551 else: #config entry contains ';' as expected
552 value=string.split(value,';')
553 menuItem=value[0].strip()
554 helpPath=value[1].strip()
555 if menuItem and helpPath: #neither are empty strings
556 helpSources.append( (menuItem,helpPath,option) )
557 return helpSources
558
559 def GetAllExtraHelpSourcesList(self):
560 """
561 Returns a list of tuples containing the details of all additional help
562 sources configured, or an empty list if there are none. Tuples are of
563 the format returned by GetExtraHelpSourceList.
564 """
565 allHelpSources=( self.GetExtraHelpSourceList('default')+
566 self.GetExtraHelpSourceList('user') )
567 return allHelpSources
568
Steven M. Gavac11ccf32001-09-24 09:43:17 +0000569 def LoadCfgFiles(self):
570 """
571 load all configuration files.
572 """
573 for key in self.defaultCfg.keys():
574 self.defaultCfg[key].Load()
575 self.userCfg[key].Load() #same keys
576
577 def SaveUserCfgFiles(self):
578 """
579 write all loaded user configuration files back to disk
580 """
581 for key in self.userCfg.keys():
582 self.userCfg[key].Save()
583
584idleConf=IdleConf()
585
586### module test
587if __name__ == '__main__':
588 def dumpCfg(cfg):
589 print '\n',cfg,'\n'
590 for key in cfg.keys():
591 sections=cfg[key].sections()
592 print key
593 print sections
594 for section in sections:
595 options=cfg[key].options(section)
596 print section
597 print options
598 for option in options:
599 print option, '=', cfg[key].Get(section,option)
600 dumpCfg(idleConf.defaultCfg)
601 dumpCfg(idleConf.userCfg)
602 print idleConf.userCfg['main'].Get('Theme','name')
603 #print idleConf.userCfg['highlight'].GetDefHighlight('Foo','normal')