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