Package libxyz :: Module launcher
[hide private]
[frames] | no frames]

Source Code for Module libxyz.launcher

  1  #-*- coding: utf8 -* 
  2  # 
  3  # Max E. Kuznecov ~syhpoon <syhpoon@syhpoon.name> 2008 
  4  # 
  5  # This file is part of XYZCommander. 
  6  # XYZCommander is free software: you can redistribute it and/or modify 
  7  # it under the terms of the GNU Lesser Public License as published by 
  8  # the Free Software Foundation, either version 3 of the License, or 
  9  # (at your option) any later version. 
 10  # XYZCommander is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 13  # GNU Lesser Public License for more details. 
 14  # You should have received a copy of the GNU Lesser Public License 
 15  # along with XYZCommander. If not, see <http://www.gnu.org/licenses/>. 
 16   
 17  """ 
 18  Launcher - all neccessary initialization 
 19  """ 
 20   
 21  import sys 
 22  import gettext 
 23  import getopt 
 24  import locale 
 25  import os 
 26  import glob 
 27  import __builtin__ 
 28   
 29  import libxyz 
 30  import libxyz.ui as uilib 
 31  import libxyz.const as const 
 32  import libxyz.core as core 
 33   
 34  from libxyz.ui import lowui 
 35  from libxyz.version import Version 
 36  from libxyz.core.plugins import PluginManager 
 37  from libxyz.core import logger 
 38  from libxyz.core import dsl 
 39  from libxyz.core.utils import ustring, bstring 
 40  from libxyz.vfs import VFSDispatcher 
 41   
 42  from libxyz.exceptions import * 
 43   
44 -class Launcher(object):
45 """ 46 Startup class 47 """ 48 49 EVENT_STARTUP = u"event:startup" 50
51 - def __init__(self):
52 """ 53 Initialization 54 """ 55 self._path_sel = libxyz.PathSelector() 56 gettext.install(u"xyzcmd", localedir=self._path_sel.get_locale_dir(), 57 unicode=True) 58 59 self.cmdopts = "d:c:s:lvh" 60 self._list_skins = False 61 self.allowed_colors = (1, 16, 88, 256) 62 63 self.xyz = core.XYZData() 64 self.xyz.conf = {} 65 self.xyz.hm = core.HookManager() 66 self.dsl = dsl.XYZ(self.xyz) 67 self.xyz.sm = core.SkinManager() 68 self.xyz.am = core.ActionManager(self.xyz) 69 self.xyz.km = core.KeyManager(self.xyz) 70 self.xyz.vfs = VFSDispatcher(self.xyz) 71 self.xyz.pm = PluginManager(self.xyz, 72 self._path_sel.get_plugins_dir()) 73 74 self._conf = {} 75 self._saved_term = None 76 self._driver = None 77 self._started = False 78 79 self._create_home()
80 81 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 82
83 - def run(self):
84 """ 85 Run commander 86 """ 87 88 self._set_enc() 89 90 self.parse_args() 91 self.parse_configs_1() 92 93 if self._list_skins: 94 self._show_skins() 95 self.quit() 96 97 self._driver = self._conf.get("driver", 98 self.xyz.conf["xyz"]["term_lib"]) 99 100 self.xyz.term = core.utils.setup_term() 101 102 self.init_logger() 103 104 self.xyz.input = core.InputWrapper(self.xyz) 105 self.xyz.screen = uilib.display.init_display(self._driver) 106 107 self.init_skin() 108 self.parse_configs_2() 109 110 self._started = True 111 xyzlog.process_pending() 112 113 self.xyz.screen.run_wrapper(self._run) 114 115 self.finalize()
116 117 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 118
119 - def _set_enc(self):
120 """ 121 Try to preset local_encoding using current locale settings. 122 After xyz conf is parsed, this value will be overriden by 123 local_encoding from conf, if defined 124 """ 125 126 __builtin__.__dict__["xyzenc"] = locale.getpreferredencoding()
127 128 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 129
130 - def _run(self):
131 panel = uilib.Panel(self.xyz) 132 self.xyz.top = lowui.Filler(panel) 133 134 self.xyz.hm.dispatch(self.EVENT_STARTUP) 135 panel.loop()
136 137 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 138
139 - def _create_home(self):
140 """ 141 Create .xyzcmd in homedir 142 """ 143 144 if os.path.isdir(self._path_sel.user_dir): 145 return 146 147 try: 148 os.makedirs(self._path_sel.user_dir) 149 150 for d in (const.CONF_DIR, 151 const.PLUGINS_DIR, 152 const.SKINS_DIR, 153 ): 154 os.mkdir(os.path.join(self._path_sel.user_dir, d)) 155 except Exception: 156 return
157 158 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 159
160 - def parse_args(self):
161 """ 162 Parse command line arguments 163 """ 164 165 try: 166 _opts, _args = getopt.getopt(sys.argv[1:], self.cmdopts) 167 except getopt.GetoptError, e: 168 self.error(str(e)) 169 self.usage() 170 self.quit() 171 172 for _o, _a in _opts: 173 if _o == "-d": 174 self._conf["driver"] = _a 175 elif _o == "-c": 176 _colors = int(_a) 177 self._conf["colors"] = _colors 178 elif _o == "-s": 179 self._conf["skin"] = _a 180 elif _o == "-l": 181 self._list_skins = True 182 elif _o == "-v": 183 self.version() 184 self.quit() 185 else: 186 self.usage() 187 self.quit()
188 189 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 190
191 - def init_logger(self):
192 """ 193 Initiate Logger object and put it into builtin namespace 194 """ 195 196 _log = logger.LogLevel() 197 198 try: 199 _levels = self.xyz.conf[u"plugins"][u":sys:logger"][u"levels"] 200 except KeyError: 201 _levels = (logger.LogLevel().ALL,) 202 else: 203 if not isinstance(_levels, tuple) and not \ 204 isinstance(_levels, list): 205 _levels = (_levels,) 206 207 try: 208 _levels = [getattr(_log, x) for x in _levels] 209 except Exception: 210 raise XYZValueError(_(u"Invalid value %s.\n"\ 211 u"A list of valid log levels expected") 212 % ustring(_levels)) 213 214 try: 215 _lines = self.xyz.conf[u"plugins"][u":sys:logger"][u"lines"] 216 # Value not defined in conf 217 except KeyError: 218 _lines = 100 219 220 try: 221 _lines = abs(int(_lines)) 222 except ValueError: 223 raise XYZValueError(_(u"Invalid value %s. "\ 224 u"A positive integer expected") % 225 ustring(_lines)) 226 227 _logger = core.logger.Logger(self.xyz, _levels, _lines) 228 229 __builtin__.__dict__["xyzlog"] = _logger
230 231 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 232
233 - def init_skin(self):
234 """ 235 Init selected skin 236 """ 237 238 colors = self._conf.get("colors", 239 self.xyz.conf["xyz"]["term_colors"]) 240 241 if colors not in self.allowed_colors: 242 self.usage() 243 self.quit() 244 245 skin = self.xyz.sm.get(self._conf.get("skin", 246 self.xyz.conf[u"xyz"][u"skin"])) 247 248 249 if skin and skin.colors and colors not in skin.colors: 250 xyzlog.warning(_(u"Skin %s is not usable with requested "\ 251 u"color settings. Using default.") % skin.name) 252 skin = self.xyz.sm.get(const.DEFAULT_SKIN) 253 254 if skin is None: 255 skin = self.xyz.sm.get(const.DEFAULT_SKIN) 256 257 # Purge unused skins to save some memory 258 self.xyz.sm.clear() 259 260 self.xyz.screen.register_palette(skin.get_palette_list(self._driver)) 261 262 if hasattr(self.xyz.screen, "set_terminal_properties"): 263 self.xyz.screen.set_terminal_properties(colors=colors) 264 265 self.xyz.skin = skin 266 self.xyz.skin.set_screen(self.xyz.screen)
267 268 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 269
270 - def parse_configs_1(self):
271 """ 272 Parse configuration. Phase 1 273 """ 274 275 self._parse_conf_file(const.XYZ_CONF_FILE) 276 self._parse_conf_file(const.PLUGINS_CONF_FILE) 277 self._parse_conf_file(const.ALIASES_CONF_FILE) 278 self._parse_conf_file(const.ICMD_CONF_FILE) 279 self._parse_conf_file(const.VFS_CONF_FILE) 280 self._parse_conf_file(const.HOOKS_CONF_FILE) 281 282 # Load skins 283 self._parse_skins() 284 285 # local_encoding set, override guessed encoding 286 if "local_encoding" in self.xyz.conf["xyz"]: 287 __builtin__.__dict__["xyzenc"] = \ 288 self.xyz.conf["xyz"]["local_encoding"]
289 290 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 291
292 - def parse_configs_2(self):
293 """ 294 Parse configuration. Phase 2 295 """ 296 297 self._parse_conf_file(const.KEYS_CONF_FILE) 298 self._parse_conf_file(const.ACTIONS_CONF_FILE)
299 300 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 301
302 - def _parse_conf_file(self, conf_file):
303 """ 304 Parse configuration files, first system then user one if any 305 @param conf_file: File to parse 306 """ 307 308 _system, _user = self._path_sel.get_conf(conf_file) 309 310 # Exec system config first 311 self._parse_file(_system, _(u"Error parsing system config %s: %s")) 312 313 # Now try to exec users's conf, if exists 314 if os.path.exists(_user): 315 self._parse_file(_user, _(u"Error parsing user config %s: %s"))
316 317 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 318
319 - def _parse_skins(self):
320 """ 321 Load all skins in system and user home dirs 322 """ 323 324 user_skins, system_skins = self._path_sel.get_skins_dir() 325 326 system_skins = glob.glob(os.path.join(system_skins, "*")) 327 328 if os.path.exists(user_skins): 329 user_skins = glob.glob(os.path.join(user_skins, "*")) 330 else: 331 user_skins = [] 332 333 for skin in system_skins + user_skins: 334 res = self._parse_file(skin, error=False) 335 336 if res != True: 337 self.error(_(u"Skipping skin %s due to parsing error: %s") % 338 (skin, res), False)
339 340 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 341
342 - def _parse_file(self, file, tmpl=None, error=True):
343 """ 344 Parse XYZCommander config 345 """ 346 347 if tmpl is None: 348 tmpl = _(u"Error parsing config %s: %s") 349 350 try: 351 dsl.exec_file(file) 352 except DSLError, e: 353 if error: 354 self.error(tmpl % (file, unicode(e))) 355 else: 356 return unicode(e) 357 358 return True
359 360 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 361
362 - def usage(self):
363 """ 364 Show usage 365 """ 366 367 print _(u"""\ 368 %s version %s 369 Usage: %s [-d driver][-c colors][-s skin][-lvh] 370 -d -- Display driver (raw (default) or curses) 371 -c -- Number of colors terminal supports (1, 16 (default), 88, 256) 372 -s -- Skin name 373 -l -- Show available skins 374 -v -- Show version 375 -h -- Show this help message\ 376 """) % (const.PROG, Version.version, os.path.basename(sys.argv[0]))
377 378 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 379
380 - def version(self):
381 """ 382 Show version 383 """ 384 385 print _(u"%s version %s") % (const.PROG, Version.version)
386 387 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 388
389 - def quit(self):
390 """ 391 Quit program 392 """ 393 394 sys.exit()
395 396 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 397
398 - def error(self, msg, quit=True):
399 """ 400 Print error message and optionally quit 401 """ 402 403 if self._started: 404 xyzlog.log(msg) 405 else: 406 # Before logger initiated, print errors to stdout 407 print msg 408 409 if quit: 410 self.quit()
411 412 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 413
414 - def finalize(self):
415 """ 416 Perform shutdown procedures 417 """ 418 419 if self.xyz.term is not None: 420 core.utils.restore_term(self.xyz.term)
421 422 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 423
424 - def _show_skins(self):
425 """ 426 Show installed skins 427 """ 428 429 for skin in self.xyz.sm.get_all(): 430 print "%s\t-- %s" % (skin.name, skin.version)
431