def make_stub_file(self, p): '''Make a stub file in ~/stubs for the @<file> node at p.''' import ast import leo.core.leoAst as leoAst assert p.isAnyAtFileNode() c = self.c fn = p.anyAtFileNodeName() if not fn.endswith('.py'): g.es_print('not a python file', fn) return abs_fn = g.fullPath(c, p) if not g.os_path_exists(abs_fn): g.es_print('not found', abs_fn) return if g.os_path_exists(self.output_directory): base_fn = g.os_path_basename(fn) out_fn = g.os_path_finalize_join(self.output_directory, base_fn) else: g.es_print('not found', self.output_directory) return out_fn = out_fn[:-3] + '.pyi' out_fn = os.path.normpath(out_fn) self.output_fn = out_fn # compatibility with stand-alone script s = open(abs_fn).read() node = ast.parse(s,filename=fn,mode='exec') leoAst.StubTraverser(controller=self).run(node)
def jump_to_error_internal(c): import re regex = re.compile(r' File "(.*)", line (\d+), in') lines = c.leo_screen.get_all(c) lines = lines.split('\n') skipped = 0 for i in reversed(lines): match = regex.match(i) if match: if skipped == c.leo_screen.stack_frame: g.es("Line %s in %s"%(match.group(2), match.group(1))) filename = g.os_path_basename(match.group(1)) for p in c.all_unique_positions(): if p.h.startswith('@') and p.h.endswith(filename): c.selectPosition(p) c.goToLineNumber(c).go(n=int(match.group(2))) c.bodyWantsFocusNow() break break skipped += 1 else: g.es("%d error frames found in console content"%skipped)
def make_stub_file(self, p): '''Make a stub file in ~/stubs for the @<file> node at p.''' import ast assert p.isAnyAtFileNode() c = self.c fn = p.anyAtFileNodeName() if not fn.endswith('.py'): g.es_print('not a python file', fn) return abs_fn = g.fullPath(c, p) if not g.os_path_exists(abs_fn): g.es_print('not found', abs_fn) return if g.os_path_exists(self.output_directory): base_fn = g.os_path_basename(fn) out_fn = g.os_path_finalize_join(self.output_directory, base_fn) else: g.es_print('not found', self.output_directory) return out_fn = out_fn[:-3] + '.pyi' out_fn = g.os_path_normpath(out_fn) self.output_fn = out_fn # compatibility with stand-alone script s = open(abs_fn).read() node = ast.parse(s, filename=fn, mode='exec') # Make the traverser *after* creating output_fn and output_directory ivars. x = self.msf.StubTraverser(controller=self) x.output_fn = self.output_fn x.output_directory = self.output_directory x.trace_matches = self.trace_matches x.trace_patterns = self.trace_patterns x.trace_reduce = self.trace_reduce x.trace_visitors = self.trace_visitors x.run(node)
def jump_to_error_internal(c): import re regex = re.compile(r' File "(.*)", line (\d+), in') lines = c.leo_screen.get_all(c) lines = lines.split('\n') skipped = 0 for i in reversed(lines): match = regex.match(i) if match: if skipped == c.leo_screen.stack_frame: g.es("Line %s in %s" % (match.group(2), match.group(1))) filename = g.os_path_basename(match.group(1)) for p in c.all_unique_positions(): if p.h.startswith('@') and p.h.endswith(filename): c.selectPosition(p) c.goToLineNumber(int(match.group(2))) c.bodyWantsFocusNow() break break skipped += 1 else: g.es("%d error frames found in console content" % skipped)
def find_file(self, fn): '''Return the @<file> node matching fn.''' c = self.c fn = g.os_path_basename(fn) for p in c.all_unique_positions(): if p.isAnyAtFileNode(): fn2 = p.anyAtFileNodeName() if fn2.endswith(fn): return p return None
def find_file(self, fn): """Return the @<file> node matching fn.""" c = self.c fn = g.os_path_basename(fn) for p in c.all_unique_positions(): if p.isAnyAtFileNode(): fn2 = p.anyAtFileNodeName() if fn2.endswith(fn): return p return None
def regularizeName(self, moduleOrFileName): """ Return the module name used as a key to this modules dictionaries. We *must* allow .py suffixes, for compatibility with @enabled-plugins nodes. """ if not moduleOrFileName.endswith('.py'): # A module name. Return it unchanged. return moduleOrFileName # # 1880: The legacy code implictly assumed that os.path.dirname(fn) was empty! # The new code explicitly ignores any directories in the path. fn = g.os_path_basename(moduleOrFileName) return "leo.plugins." + fn[:-3]
#@+leo-ver=5-thin #@+node:tbrown.20171028115143.1: * @file ../plugins/editpane/webkitview.py #@+<< webkitview.py imports >> #@+node:tbrown.20171028115457.1: ** << webkitview.py imports >> import os import leo.core.leoGlobals as g assert g from leo.core.leoQt import QtWebKit, QtWebKitWidgets if 'engine' in g.os_path_basename(QtWebKitWidgets.__file__).lower(): # not loading webkit view, webengine masquerading as webkit raise ImportError #@-<< webkitview.py imports >> #@+others #@+node:tbrown.20171028115457.2: ** _path_from_pos def _path_from_pos(c, p): """_path_from_pos - get folder for position FIXME: should be in Leo core somewhere. Args: p (position): position Returns: str: path """ p = p.copy() def atfile(p): word0 = p.h.split()[0] return ( word0 in g.app.atFileNames|set(['@auto']) or
def wrap(cb=cb, name="Bookmark to top of "+g.os_path_basename(c2.fileName())): self.do_wrap(cb, name)
#@+leo-ver=5-thin #@+node:tbrown.20171028115143.1: * @file ../plugins/editpane/webkitview.py #@+<< webkitview.py imports >> #@+node:tbrown.20171028115457.1: ** << webkitview.py imports >> import os import leo.core.leoGlobals as g assert g from leo.core.leoQt import QtWebKit, QtWebKitWidgets if 'engine' in g.os_path_basename(QtWebKitWidgets.__file__).lower(): # not loading webkit view, webengine masquerading as webkit raise ImportError #@-<< webkitview.py imports >> #@+others #@+node:tbrown.20171028115457.2: ** _path_from_pos def _path_from_pos(c, p): """_path_from_pos - get folder for position FIXME: should be in Leo core somewhere. Args: p (position): position Returns: str: path """ p = p.copy() def atfile(p): word0 = p.h.split()[0]
def popup(self, c, p, menu): """make popup menu entry for tree context menu""" if c != self.c: return # wrong commander for cb, name in reversed(self.recent_moves): a = QtGui.QAction(name, menu) a.connect(a, QtCore.SIGNAL("triggered()"), lambda cb=cb, name=name: self.do_wrap(cb, name)) menu.insertAction(menu.actions()[0], a) pathmenu = menu.addMenu("Move") # copy / cut to other outline for txt, cut in ("Copy to...", False), ("Move to...", True): sub = pathmenu.addMenu(txt) # global targets for target in g.app.db['_quickmove']['global_targets']: a = sub.addAction(target['name']) def cb(c2=target['unl'], cut=cut): self.to_other(c2, cut=cut) def wrap(cb=cb, name=txt.strip('.') + ' ' + target['name']): self.do_wrap(cb, name) a.connect(a, QtCore.SIGNAL("triggered()"), wrap) # top of open outlines for c2 in g.app.commanders(): a = sub.addAction("Top of " + g.os_path_basename(c2.fileName())) def cb(c2=c2, cut=cut): self.to_other(c2, cut=cut) def wrap(cb=cb, name=txt.strip('.') + ' top of ' + g.os_path_basename(c2.fileName())): self.do_wrap(cb, name) a.connect(a, QtCore.SIGNAL("triggered()"), wrap) # bookmark to other outline sub = pathmenu.addMenu("Bookmark to...") # global targets for target in g.app.db['_quickmove']['global_targets']: a = sub.addAction(target['name']) def cb(c2=target['unl'], cut=cut): self.bookmark_other(c2) def wrap(cb=cb, name="Bookmark to " + target['name']): self.do_wrap(cb, name) a.connect(a, QtCore.SIGNAL("triggered()"), wrap) # top of open outlines for c2 in g.app.commanders(): a = sub.addAction(g.os_path_basename(c2.fileName())) def cb(c2=c2): self.bookmark_other(c2) def wrap(cb=cb, name="Bookmark to top of " + g.os_path_basename(c2.fileName())): self.do_wrap(cb, name) a.connect(a, QtCore.SIGNAL("triggered()"), wrap) # add new global target, etc. a = pathmenu.addAction("Add node as target") a.connect(a, QtCore.SIGNAL("triggered()"), lambda p=p: self.add_target(p)) a = pathmenu.addAction("Show targets") a.connect(a, QtCore.SIGNAL("triggered()"), lambda p=p: self.show_targets()) a = pathmenu.addAction("Read targets") a.connect(a, QtCore.SIGNAL("triggered()"), lambda p=p: self.read_targets()) # actions within this outline for name, dummy, command in self.local_imps: a = pathmenu.addAction(name) a.connect(a, QtCore.SIGNAL("triggered()"), command)
def wrap(checked, cb=cb, name=txt.strip('.') + ' top of ' + g.os_path_basename(c2.fileName())): self.do_wrap(cb, name)
def wrap(checked, cb=cb, name="Bookmark to top of " + g.os_path_basename(c2.fileName())): self.do_wrap(cb, name)
myLeoSettings.leo and remove the default content, i.e. make this node blank, then CKEditor will generate a toolbar with all available features. To make a button to toggle the editor on and off, use:: @button rich c.k.simulateCommand('cke-text-switch') """ #@-<< docstring >> #@+<< imports >> #@+node:tbrown.20130813134319.14335: ** << imports >> (richtext.py) import leo.core.leoGlobals as g from leo.core.leoQt import QtCore,QtWidgets,QtWebKit,QtWebKitWidgets if QtWebKit: real_webkit = 'engine' not in g.os_path_basename(QtWebKit.__file__).lower() else: real_webkit = False import time # pylint: disable=no-name-in-module if g.isPython3: from urllib.parse import unquote else: from urllib import unquote #@-<< imports >> #@+others #@+node:tbrown.20130813134319.14337: ** init (richtext.py) def init(): '''Return True if the plugin has loaded successfully.''' if not QtWebKit: return False
def open_temp_file(self, c, d, fn, testing=False): ''' Open a temp file corresponding to fn in an external editor. d is a dictionary created from an @openwith settings node. 'args': the command-line arguments to be used to open the file. 'ext': the file extension. 'kind': the method used to open the file, such as subprocess.Popen. 'name': menu label (used only by the menu code). 'shortcut': menu shortcut (used only by the menu code). ''' trace = False and not g.unitTesting testing = testing or g.unitTesting arg_tuple = d.get('args', []) arg = ' '.join(arg_tuple) kind = d.get('kind') # This doesn't handle %ProgramFiles% # if kind in ('os.spawnl', 'subprocess.Popen'): # if not g.os_path_exists(arg): # g.trace('Executable not found', arg, arg_tuple) # return try: # All of these must be supported because they # could exist in @open-with nodes. command = '<no command>' if kind in ('os.system', 'os.startfile'): # New in Leo 5.7: # Use subProcess.Popen(..., shell=True) c_arg = self.join(arg, fn) if trace: command = '%s -> subprocess.Popen(%s)' % ( kind, g.shortFileName(c_arg)) g.trace(command) if not testing: try: subprocess.Popen(c_arg, shell=True) except OSError: g.es_print('c_arg', repr(c_arg)) g.es_exception() # Legacy code. # command = 'os.startfile(%s)' % self.join(arg, fn) # if trace: g.trace(command) # # pylint: disable=no-member # # trust the user not to use this option on Linux. # if not testing: # os.startfile(arg, fn) elif kind == 'exec': g.es_print('open-with exec no longer valid.') # command = 'exec(%s)' % self.join(arg,fn) # if trace: g.trace(command) # if not testing: # exec(self.join(arg,fn),{},{}) elif kind == 'os.spawnl': filename = g.os_path_basename(arg) command = 'os.spawnl(%s,%s,%s)' % (arg, filename, fn) if trace: g.trace(command) if not testing: os.spawnl(os.P_NOWAIT, arg, filename, fn) elif kind == 'os.spawnv': filename = os.path.basename(arg_tuple[0]) vtuple = arg_tuple[1:] vtuple.insert(0, filename) # add the name of the program as the first argument. # Change suggested by Jim Sizelove. vtuple.append(fn) command = 'os.spawnv(%s)' % (vtuple) if trace: g.trace(command) if not testing: os.spawnv(os.P_NOWAIT, arg[0], vtuple) #??? elif kind == 'subprocess.Popen': c_arg = self.join(arg, fn) command = 'subprocess.Popen(%s)' % c_arg if trace: g.trace(command) if not testing: try: subprocess.Popen(c_arg, shell=True) except OSError: g.es_print('c_arg', repr(c_arg)) g.es_exception() elif g.isCallable(kind): # Invoke openWith like this: # c.openWith(data=[func,None,None]) # func will be called with one arg, the filename if trace: g.trace('%s(%s)' % (kind, fn)) command = '%s(%s)' % (kind, fn) if not testing: kind(fn) else: command = 'bad command:' + str(kind) if not testing: g.trace(command) return command # for unit testing. except Exception: g.es('exception executing open-with command:', command) g.es_exception() return 'oops: %s' % command
def open_file_in_external_editor(self, c, d, fn, testing=False): ''' Open a file fn in an external editor. This will be an entire external file, or a temp file for a single node. d is a dictionary created from an @openwith settings node. 'args': the command-line arguments to be used to open the file. 'ext': the file extension. 'kind': the method used to open the file, such as subprocess.Popen. 'name': menu label (used only by the menu code). 'p': the nearest @<file> node, or None. 'shortcut': menu shortcut (used only by the menu code). ''' testing = testing or g.unitTesting arg_tuple = d.get('args', []) arg = ' '.join(arg_tuple) kind = d.get('kind') try: # All of these must be supported because they # could exist in @open-with nodes. command = '<no command>' if kind in ('os.system', 'os.startfile'): # New in Leo 5.7: # Use subProcess.Popen(..., shell=True) c_arg = self.join(arg, fn) if not testing: try: subprocess.Popen(c_arg, shell=True) except OSError: g.es_print('c_arg', repr(c_arg)) g.es_exception() elif kind == 'exec': g.es_print('open-with exec no longer valid.') elif kind == 'os.spawnl': filename = g.os_path_basename(arg) command = f"os.spawnl({arg},{filename},{fn})" if not testing: os.spawnl(os.P_NOWAIT, arg, filename, fn) elif kind == 'os.spawnv': filename = os.path.basename(arg_tuple[0]) vtuple = arg_tuple[1:] vtuple.insert(0, filename) # add the name of the program as the first argument. # Change suggested by Jim Sizelove. vtuple.append(fn) command = f"os.spawnv({vtuple})" if not testing: os.spawnv(os.P_NOWAIT, arg[0], vtuple) #??? elif kind == 'subprocess.Popen': c_arg = self.join(arg, fn) command = f"subprocess.Popen({c_arg})" if not testing: try: subprocess.Popen(c_arg, shell=True) except OSError: g.es_print('c_arg', repr(c_arg)) g.es_exception() elif hasattr(kind, '__call__'): # Invoke openWith like this: # c.openWith(data=[func,None,None]) # func will be called with one arg, the filename command = f"{kind}({fn})" if not testing: kind(fn) else: command = 'bad command:' + str(kind) if not testing: g.trace(command) return command # for unit testing. except Exception: g.es('exception executing open-with command:', command) g.es_exception() return f"oops: {command}"
def wrap(cb=cb, name=txt.strip('.')+' top of '+g.os_path_basename(c2.fileName())): self.do_wrap(cb, name)
def popup(self, c, p, menu): """make popup menu entry for tree context menu""" # pylint: disable=function-redefined # several callbacks have the same name. if c != self.c: return # wrong commander for cb, name in reversed(self.recent_moves): a = QtGui.QAction(name, menu) a.connect(a, QtCore.SIGNAL("triggered()"), lambda cb=cb, name=name: self.do_wrap(cb, name)) menu.insertAction(menu.actions()[0], a) pathmenu = menu.addMenu("Move") # copy / cut to other outline for txt, cut in ("Copy to...", False), ("Move to...", True): sub = pathmenu.addMenu(txt) # global targets for target in g.app.db['_quickmove']['global_targets']: a = sub.addAction(target['name']) def cb(c2=target['unl'], cut=cut): self.to_other(c2, cut=cut) def wrap(cb=cb, name=txt.strip('.')+' '+target['name']): self.do_wrap(cb, name) a.connect(a, QtCore.SIGNAL("triggered()"), wrap) # top of open outlines for c2 in g.app.commanders(): a = sub.addAction("Top of " + g.os_path_basename(c2.fileName())) def cb(c2=c2, cut=cut): self.to_other(c2, cut=cut) def wrap(cb=cb, name=txt.strip('.')+' top of '+g.os_path_basename(c2.fileName())): self.do_wrap(cb, name) a.connect(a, QtCore.SIGNAL("triggered()"), wrap) # bookmark to other outline sub = pathmenu.addMenu("Bookmark to...") # global targets for target in g.app.db['_quickmove']['global_targets']: a = sub.addAction(target['name']) def cb(c2=target['unl'], cut=cut): self.bookmark_other(c2) def wrap(cb=cb, name="Bookmark to "+target['name']): self.do_wrap(cb, name) a.connect(a, QtCore.SIGNAL("triggered()"), wrap) # top of open outlines for c2 in g.app.commanders(): a = sub.addAction(g.os_path_basename(c2.fileName())) def cb(c2=c2): self.bookmark_other(c2) def wrap(cb=cb, name="Bookmark to top of "+g.os_path_basename(c2.fileName())): self.do_wrap(cb, name) a.connect(a, QtCore.SIGNAL("triggered()"), wrap) # add new global target, etc. a = pathmenu.addAction("Add node as target") a.connect(a, QtCore.SIGNAL("triggered()"), lambda p=p: self.add_target(p)) a = pathmenu.addAction("Show targets") a.connect(a, QtCore.SIGNAL("triggered()"), lambda p=p: self.show_targets()) a = pathmenu.addAction("Read targets") a.connect(a, QtCore.SIGNAL("triggered()"), lambda p=p: self.read_targets()) # actions within this outline for name,dummy,command in self.local_imps: a = pathmenu.addAction(name) a.connect(a, QtCore.SIGNAL("triggered()"), command)
def open_temp_file(self, c, d, fn, testing=False): ''' Open a temp file corresponding to fn in an external editor. d is a dictionary created from an @openwith settings node. 'args': the command-line arguments to be used to open the file. 'ext': the file extension. 'kind': the method used to open the file, such as subprocess.Popen. 'name': menu label (used only by the menu code). 'shortcut': menu shortcut (used only by the menu code). ''' trace = False and not g.unitTesting testing = testing or g.unitTesting arg_tuple = d.get('args', []) arg = ' '.join(arg_tuple) kind = d.get('kind') try: # All of these must be supported because they # could exist in @open-with nodes. command = '<no command>' if kind == 'os.startfile': command = 'os.startfile(%s)' % self.join(arg, fn) if trace: g.trace(command) # pylint: disable=no-member # trust the user not to use this option on Linux. if not testing: os.startfile(self.join(arg, fn)) elif kind == 'exec': g.es_print('open-with exec no longer valid.') # command = 'exec(%s)' % self.join(arg,fn) # if trace: g.trace(command) # if not testing: # exec(self.join(arg,fn),{},{}) elif kind == 'os.spawnl': filename = g.os_path_basename(arg) command = 'os.spawnl(%s,%s,%s)' % (arg, filename, fn) if trace: g.trace(command) if not testing: os.spawnl(os.P_NOWAIT, arg, filename, fn) elif kind == 'os.spawnv': filename = os.path.basename(arg_tuple[0]) vtuple = arg_tuple[1:] vtuple.insert(0, filename) # add the name of the program as the first argument. # Change suggested by Jim Sizelove. vtuple.append(fn) command = 'os.spawnv(%s)' % (vtuple) if trace: g.trace(command) if not testing: os.spawnv(os.P_NOWAIT, arg[0], vtuple) #??? elif kind == 'subprocess.Popen': c_arg = self.join(arg, fn) command = 'subprocess.Popen(%s)' % c_arg if trace: g.trace(command) if not testing: try: subprocess.Popen(c_arg, shell=True) except OSError: g.es_print('c_arg', repr(c_arg)) g.es_exception() elif g.isCallable(kind): # Invoke openWith like this: # c.openWith(data=[func,None,None]) # func will be called with one arg, the filename if trace: g.trace('%s(%s)' % (kind, fn)) command = '%s(%s)' % (kind, fn) if not testing: kind(fn) else: command = 'bad command:' + str(kind) if not testing: g.trace(command) return command # for unit testing. except Exception: g.es('exception executing open-with command:', command) g.es_exception() return 'oops: %s' % command
myLeoSettings.leo and remove the default content, i.e. make this node blank, then CKEditor will generate a toolbar with all available features. To make a button to toggle the editor on and off, use:: @button rich c.k.simulateCommand('cke-text-switch') """ #@-<< docstring >> #@+<< imports >> #@+node:tbrown.20130813134319.14335: ** << imports >> (richtext.py) import leo.core.leoGlobals as g from leo.core.leoQt import QtCore, QtWidgets, QtWebKit, QtWebKitWidgets if QtWebKit: real_webkit = 'engine' not in g.os_path_basename(QtWebKit.__file__).lower() else: real_webkit = False import time from urllib.parse import unquote #@-<< imports >> #@+others #@+node:tbrown.20130813134319.14337: ** init (richtext.py) def init(): '''Return True if the plugin has loaded successfully.''' if not QtWebKit: return False name = g.app.gui.guiName() ok = name == 'qt'
def popup(self, c, p, menu): """make popup menu entry for tree context menu""" # pylint: disable=function-redefined # several callbacks have the same name. if c != self.c: return # wrong commander for cb, name in reversed(self.recent_moves): a = QtWidgets.QAction(name, menu) a.triggered.connect( lambda checked, cb=cb, name=name: self.do_wrap(cb, name)) menu.insertAction(menu.actions()[0], a) pathmenu = menu.addMenu("Move") # copy / cut to other outline cut = None for txt, cut in ("Copy to...", False), ("Move to...", True): sub = pathmenu.addMenu(txt) # global targets for target in g.app.db['_quickmove']['global_targets']: a = sub.addAction(target['name']) def cb(c2=target['unl'], cut=cut): self.to_other(c2, cut=cut) def wrap(checked, cb=cb, name=txt.strip('.') + ' ' + target['name']): self.do_wrap(cb, name) a.triggered.connect(wrap) # top of open outlines for c2 in g.app.commanders(): a = sub.addAction("Top of " + g.os_path_basename(c2.fileName())) def cb(c2=c2, cut=cut): self.to_other(c2, cut=cut) def wrap(checked, cb=cb, name=txt.strip('.') + ' top of ' + g.os_path_basename(c2.fileName())): self.do_wrap(cb, name) a.triggered.connect(wrap) # bookmark to other outline sub = pathmenu.addMenu("Bookmark to...") # global targets for target in g.app.db['_quickmove']['global_targets']: a = sub.addAction(target['name']) def cb(c2=target['unl'], cut=cut): self.bookmark_other(c2) def wrap(checked, cb=cb, name="Bookmark to " + target['name']): self.do_wrap(cb, name) a.triggered.connect(wrap) # top of open outlines for c2 in g.app.commanders(): a = sub.addAction(g.os_path_basename(c2.fileName())) def cb(c2=c2): self.bookmark_other(c2) def wrap(checked, cb=cb, name="Bookmark to top of " + g.os_path_basename(c2.fileName())): self.do_wrap(cb, name) a.triggered.connect(wrap) # actions within this outline need_submenu = 'Move', 'Copy', 'Clone', 'Bookmark', 'Link' current_kind = None current_submenu = None for name, dummy, command in self.local_imps: kind = name.split()[0] if kind in need_submenu: if current_kind != kind: current_submenu = pathmenu.addMenu(kind) current_kind = kind else: current_submenu = pathmenu a = current_submenu.addAction(name) a.triggered.connect(lambda checked, command=command: command()) # add new global target, etc. a = pathmenu.addAction("Add node as target") a.triggered.connect(lambda checked, p=p: self.add_target(p)) a = pathmenu.addAction("Show targets") a.triggered.connect(lambda checked, p=p: self.show_targets()) a = pathmenu.addAction("Read targets") a.triggered.connect(lambda checked, p=p: self.read_targets())
def open_file_in_external_editor(self, c, d, fn, testing=False): ''' Open a file fn in an external editor. This will be an entire external file, or a temp file for a single node. d is a dictionary created from an @openwith settings node. 'args': the command-line arguments to be used to open the file. 'ext': the file extension. 'kind': the method used to open the file, such as subprocess.Popen. 'name': menu label (used only by the menu code). 'p': the nearest @<file> node, or None. 'shortcut': menu shortcut (used only by the menu code). ''' testing = testing or g.unitTesting arg_tuple = d.get('args', []) arg = ' '.join(arg_tuple) kind = d.get('kind') try: # All of these must be supported because they # could exist in @open-with nodes. command = '<no command>' if kind in ('os.system', 'os.startfile'): # New in Leo 5.7: # Use subProcess.Popen(..., shell=True) c_arg = self.join(arg, fn) if not testing: try: subprocess.Popen(c_arg, shell=True) except OSError: g.es_print('c_arg', repr(c_arg)) g.es_exception() elif kind == 'exec': g.es_print('open-with exec no longer valid.') elif kind == 'os.spawnl': filename = g.os_path_basename(arg) command = 'os.spawnl(%s,%s,%s)' % (arg, filename, fn) if not testing: os.spawnl(os.P_NOWAIT, arg, filename, fn) elif kind == 'os.spawnv': filename = os.path.basename(arg_tuple[0]) vtuple = arg_tuple[1:] vtuple.insert(0, filename) # add the name of the program as the first argument. # Change suggested by Jim Sizelove. vtuple.append(fn) command = 'os.spawnv(%s)' % (vtuple) if not testing: os.spawnv(os.P_NOWAIT, arg[0], vtuple) #??? elif kind == 'subprocess.Popen': c_arg = self.join(arg, fn) command = 'subprocess.Popen(%s)' % c_arg if not testing: try: subprocess.Popen(c_arg, shell=True) except OSError: g.es_print('c_arg', repr(c_arg)) g.es_exception() elif g.isCallable(kind): # Invoke openWith like this: # c.openWith(data=[func,None,None]) # func will be called with one arg, the filename command = '%s(%s)' % (kind, fn) if not testing: kind(fn) else: command = 'bad command:' + str(kind) if not testing: g.trace(command) return command # for unit testing. except Exception: g.es('exception executing open-with command:', command) g.es_exception() return 'oops: %s' % command