def CloseProcess(c): global RunNode,ExitCode,WorkDir global In,OutThread,ErrThread # Close file and get error code. In.close() OutThread.File.close() ExitCode = ErrThread.File.close() # Unmark the node and reset it. RunNode.clearMarked() RunNode = None # Reset the working dir. if WorkDir != None: os.chdir(WorkDir) WorkDir = None # Write exit code. if ExitCode is None: g.blue("@run done") else: g.error("@run exits with code: %s" % (str(ExitCode))) # Redraw. c.redraw()
def copyMarked(self, event=None): """Copy all marked nodes as children of a new node.""" c = self; u = c.undoer; p1 = c.p.copy() # Create a new node to hold clones. parent = p1.insertAfter() parent.h = 'Copies of marked nodes' copied, n, p = [], 0, c.rootPosition() while p: # Careful: don't clone already-cloned nodes. if p == parent: p.moveToNodeAfterTree() elif p.isMarked() and p.v not in copied: copied.append(p.v) p2 = p.copyWithNewVnodes(copyMarked=True) p2._linkAsNthChild(parent, n) p.moveToNodeAfterTree() n += 1 else: p.moveToThreadNext() if n: c.setChanged() parent.expand() c.selectPosition(parent) u.afterCopyMarkedNodes(p1) else: parent.doDelete() c.selectPosition(p1) if not g.unitTesting: g.blue(f"copied {n} nodes") c.redraw()
def stop(tag, keywords): c = keywords.get('c') if not c: g.trace('can not happen') return multi = scanForMultiPath(c) # g.trace(g.dictToString(multi)) for fileName in multi.keys(): paths = multi[fileName] for path in paths: try: if os.path.isdir(path): shutil.copy2(fileName, path) g.blue("multifile:\nWrote %s to %s" % (fileName, path)) else: g.error( "multifile:\n%s is not a directory, not writing %s" % (path, fileName)) except: g.error("multifile:\nCant write %s to %s" % (fileName, path)) g.es_exception_type() files.clear()
def dtest(self, event): """The handler for dtest """ import leo.core.leoGlobals as g # get a valid temporary filename createfile, tempfilename = g.create_temp_file() createfile.close() selected = False # if text is selected, only test selection if self.c.frame.body.hasTextSelection(): selected = True selection = self.c.frame.body.getSelectedText() tempfile = open(tempfilename, 'w') tempfile.write(selection) tempfile.close() # if no selection, test this subtree else: self.c.importCommands.flattenOutline(tempfilename) tempfile = open(tempfilename) text = tempfile.readlines() tempfile.close() # strip trailing whitespace, an annoying source of doctest failures text = [line.rstrip() for line in text] text = "\n".join(text) tempfile = open(tempfilename, 'w') tempfile.write(text) tempfile.close() import copy # build globals dictionary globals = {'c':copy.copy(self.c), 'g':g} # run doctest on temporary file failures, tests = doctest.testfile(tempfilename, module_relative = False, optionflags = doctest.ELLIPSIS, globs = globals) #@+<<report summary of results>> #@+node:ekr.20070119094733.10: *4* <<report summary of results>> if selected: g.es('Result of running doctest on selected text;') else: g.es('Result of running doctest on this subtree;') if failures == 0: g.blue("%s tests run successfully" % tests) if failures == 1: g.error("There was one failure in %s tests" % tests) if failures > 1: g.error("%s failures in %s tests" % (failures, tests)) #@-<<report summary of results>> #clean up temp file os.remove(tempfilename)
def writeFileFromNode(self, event=None): """ If node starts with @read-file-into-node, use the full path name in the headline. Otherwise, prompt for a file name. """ c, p = self, self.p c.endEditing() h = p.h.rstrip() s = p.b tag = '@read-file-into-node' if h.startswith(tag): fileName = h[len(tag):].strip() else: fileName = None if not fileName: fileName = g.app.gui.runSaveFileDialog(c, title='Write File From Node', filetypes=[ ("All files", "*"), ("Python files", "*.py"), ("Leo files", "*.leo") ], defaultextension=None) if fileName: try: with open(fileName, 'w') as f: g.chdir(fileName) if s.startswith('@nocolor\n'): s = s[len('@nocolor\n'):] f.write(s) f.flush() g.blue('wrote:', fileName) except IOError: g.error('can not write %s', fileName)
def writeFileFromNode(self, event=None): '''If node starts with @read-file-into-node, use the full path name in the headline. Otherwise, prompt for a file name. ''' c = self; p = c.p c.endEditing() h = p.h.rstrip() s = p.b tag = '@read-file-into-node' if h.startswith(tag): fileName = h[len(tag):].strip() else: fileName = None if not fileName: filetypes = [("All files", "*"), ("Python files", "*.py"), ("Leo files", "*.leo"),] fileName = g.app.gui.runSaveFileDialog(c, initialfile=None, title='Write File From Node', filetypes=filetypes, defaultextension=None) if fileName: try: with open(fileName, 'w') as f: g.chdir(fileName) if s.startswith('@nocolor\n'): s = s[len('@nocolor\n'):] if not g.isPython3: # 2010/08/27 s = g.toEncodedString(s, reportErrors=True) f.write(s) f.flush() g.blue('wrote:', fileName) except IOError: g.error('can not write %s', fileName)
def CloseProcess(c): global RunNode,ExitCode,WorkDir global In,OutThread,ErrThread # Close file and get error code. In.close() OutThread.File.close() ExitCode = ErrThread.File.close() # Unmark the node and reset it. RunNode.clearMarked() RunNode = None # Reset the working dir. if WorkDir is not None: os.chdir(WorkDir) WorkDir = None # Write exit code. if ExitCode is None: g.blue("@run done") else: g.error("@run exits with code: %s" % (str(ExitCode))) # Redraw. c.redraw()
def reportDirectories(self): g = self.g for kind, theDir in ( ("global config", g.app.globalConfigDir), ("home", g.app.homeDir), ): g.blue('', kind, 'directory', '', ':', theDir)
def init(): '''Return True if the plugin has loaded successfully.''' g.blue("nodeActions: Init") ok = not g.app.unitTesting # Dangerous for unit testing. if ok: g.registerHandler("icondclick1", onIconDoubleClickNA) g.plugin_signon(__name__) return ok
def init(): g.blue("nodeActions: Init") ok = not g.app.unitTesting # Dangerous for unit testing. if ok: g.registerHandler("icondclick1", onIconDoubleClickNA) g.plugin_signon(__name__) return ok
def enableGcTrace(self, event=None): '''Disable tracing of Python's Garbage Collector.''' g.trace_gc = True g.enable_gc_debug() if g.trace_gc_verbose: g.blue('enabled verbose gc stats') else: g.blue('enabled brief gc stats')
def doMinidomTest( c ): '''This def performs a simple test on a node. Can the data be successfully parsed by minidom or not. Results are output to the log''' s = getString( c ) try: mdom = minidom.parseString( s ) except Exception as x: g.error("Minidom could not parse node because of:\n %s" % x) return g.blue("Minidom could parse the node")
def doMinidomTest(c): '''This def performs a simple test on a node. Can the data be successfully parsed by minidom or not. Results are output to the log''' s = getString(c) try: mdom = minidom.parseString(s) except Exception as x: g.error("Minidom could not parse node because of:\n %s" % x) return g.blue("Minidom could parse the node")
def update_open_with_node(self, ef): """Update the body text of ef.p to the contents of ef.path.""" assert isinstance(ef, ExternalFile), ef c, p = ef.c, ef.p.copy() g.blue(f"updated {p.h}") s, e = g.readFileIntoString(ef.path) p.b = s if c.config.getBool('open-with-goto-node-on-update'): c.selectPosition(p) if c.config.getBool('open-with-save-on-update'): c.save() else: p.setDirty() c.setChanged()
def executeScriptFromButton (self,b,buttonText,gnx): '''Called from callbacks to execute the script in node p whose gnx is given.''' c = self.c if c.disableCommandsMessage: g.blue(c.disableCommandsMessage) else: g.app.scriptDict = {} p = self.find_gnx(gnx) if p: args = self.getArgs(p.h) c.executeScript(args=args,p=p,silent=True) # Remove the button if the script asks to be removed. if g.app.scriptDict.get('removeMe'): g.es("Removing '%s' button at its request" % buttonText) self.deleteButton(b)
def handleAtScriptNode(self, p): '''Handle @script nodes.''' c = self.c tag = "@script" assert (g.match(p.h, 0, tag)) name = p.h[len(tag):].strip() args = self.getArgs(p) if self.atScriptNodes: g.blue("executing script %s" % (name)) c.executeScript(args=args, p=p, useSelectedText=False, silent=True) else: g.warning("disabled @script: %s" % (name)) if 0: # Do not assume the script will want to remain in this commander. c.bodyWantsFocus()
def handleAtScriptNode (self,p): '''Handle @script nodes.''' c = self.c tag = "@script" assert(g.match(p.h,0,tag)) name = p.h[len(tag):].strip() args = self.getArgs(p) if self.atScriptNodes: g.blue("executing script %s" % (name)) c.executeScript(args=args,p=p,useSelectedText=False,silent=True) else: g.warning("disabled @script: %s" % (name)) if 0: # Do not assume the script will want to remain in this commander. c.bodyWantsFocus()
def update_open_with_node(self, ef): '''Update the body text of ef.p to the contents of ef.path.''' trace = False and not g.unitTesting assert isinstance(ef, ExternalFile), ef if trace: g.trace(repr(ef)) c, p = ef.c, ef.p.copy() # Ask the user how to resolve the conflict. if self.ask(c, ef.path, p=p): g.blue('updated %s' % p.h) s, e = g.readFileIntoString(ef.path) p.b = s if c.config.getBool('open_with_goto_node_on_update'): c.selectPosition(p) if c.config.getBool('open_with_save_on_update'): c.save()
def update_open_with_node(self, ef): '''Update the body text of ef.p to the contents of ef.path.''' assert isinstance(ef, ExternalFile), ef c, p = ef.c, ef.p.copy() # Ask the user how to resolve the conflict. if self.ask(c, ef.path, p=p): g.blue('updated %s' % p.h) s, e = g.readFileIntoString(ef.path) p.b = s if c.config.getBool('open-with-goto-node-on-update'): c.selectPosition(p) if c.config.getBool('open-with-save-on-update'): c.save() else: p.setDirty() c.setChanged(True)
def update_open_with_node(self, ef): '''Update the body text of ef.p to the contents of ef.path.''' assert isinstance(ef, ExternalFile), ef c, p = ef.c, ef.p.copy() # Ask the user how to resolve the conflict. if self.ask(c, ef.path, p=p): g.blue(f"updated {p.h}") s, e = g.readFileIntoString(ef.path) p.b = s if c.config.getBool('open-with-goto-node-on-update'): c.selectPosition(p) if c.config.getBool('open-with-save-on-update'): c.save() else: p.setDirty() c.setChanged()
def loadHandlers(self, tag, keys): """Load all enabled plugins from the plugins directory""" def pr(*args, **keys): if not g.app.unitTesting: g.es_print(*args, **keys) s = g.app.config.getEnabledPlugins() if not s: return if tag == 'open0' and not g.app.silentMode and not g.app.batchMode: if 0: s2 = '@enabled-plugins found in %s' % ( g.app.config.enabledPluginsFileName) g.blue(s2) for plugin in s.splitlines(): if plugin.strip() and not plugin.lstrip().startswith('#'): self.loadOnePlugin(plugin.strip(), tag=tag)
def executeScriptFromButton(self, b, buttonText, gnx): '''Called from callbacks to execute the script in node p whose gnx is given.''' c = self.c if c.disableCommandsMessage: g.blue(c.disableCommandsMessage) else: g.app.scriptDict = {} p = self.find_gnx(gnx) if p: args = self.getArgs(p.h) c.executeScript(args=args, p=p, silent=True) # Remove the button if the script asks to be removed. if g.app.scriptDict.get('removeMe'): g.es("Removing '%s' button at its request" % buttonText) self.deleteButton(b)
def goToNextClone(self, event=None): """ Select the next node that is a clone of the selected node. If the selected node is not a clone, do find-next-clone. """ c, p = self, self.p cc = c.chapterController; p = c.p if not p: return if not p.isCloned(): c.findNextClone() return v = p.v p.moveToThreadNext() wrapped = False while 1: if p and p.v == v: break elif p: p.moveToThreadNext() elif wrapped: break else: wrapped = True p = c.rootPosition() if p: c.expandAllAncestors(p) if cc: # #252: goto-next clone activate chapter. chapter = cc.getSelectedChapter() old_name = chapter and chapter.name new_name = cc.findChapterNameForPosition(p) if new_name == old_name: # Always do a full redraw. c.redraw(p) else: if 1: cc.selectChapterByName(new_name) c.redraw(p) else: # Old code. c.selectPosition(p) cc.selectChapterByName(new_name) else: # Always do a full redraw. c.redraw(p) else: g.blue('done')
def executeScriptFromSettingButton(self, args, b, script, buttonText): '''Called from callbacks to execute the script in node p.''' c = self.c if c.disableCommandsMessage: g.blue(c.disableCommandsMessage) else: g.app.scriptDict = {} c.executeScript(args=args, script=script, silent=True) # Remove the button if the script asks to be removed. if g.app.scriptDict.get('removeMe'): g.es("Removing '%s' button at its request" % buttonText) self.deleteButton(b) if 0: # Do *not* set focus here: the script may have changed the focus. c.frame.bodyWantsFocus()
def markChangedHeadlines(self, event=None): """Mark all nodes that have been changed.""" c = self; u = c.undoer; undoType = 'Mark Changed' current = c.p c.endEditing() u.beforeChangeGroup(current, undoType) for p in c.all_unique_positions(): if p.isDirty() and not p.isMarked(): bunch = u.beforeMark(p, undoType) # c.setMarked calls a hook. c.setMarked(p) p.setDirty() c.setChanged() u.afterMark(p, undoType, bunch) u.afterChangeGroup(current, undoType) if not g.unitTesting: g.blue('done') c.redraw_after_icons_changed()
def executeScriptFromSettingButton (self,args,b,script,buttonText): '''Called from callbacks to execute the script in node p.''' c = self.c if c.disableCommandsMessage: g.blue(c.disableCommandsMessage) else: g.app.scriptDict = {} c.executeScript(args=args,script=script,silent=True) # Remove the button if the script asks to be removed. if g.app.scriptDict.get('removeMe'): g.es("Removing '%s' button at its request" % buttonText) self.deleteButton(b) if 0: # Do *not* set focus here: the script may have changed the focus. c.bodyWantsFocus()
def executeScriptFromButton (self,b,buttonText,p,script): '''Execute an @button script in p.b or script.''' c = self.c if c.disableCommandsMessage: g.blue(c.disableCommandsMessage) return None if not p and not script: g.trace('can not happen: no p and no script') return g.app.scriptDict = {} args = self.getArgs(p) if not script: script = self.getScript(p) c.executeScript(args=args,p=p,script=script,silent=True) # Remove the button if the script asks to be removed. if g.app.scriptDict.get('removeMe'): g.es("Removing '%s' button at its request" % buttonText) self.deleteButton(b)
def executeScriptFromButton(self, b, buttonText, p, script): '''Execute an @button script in p.b or script.''' c = self.c if c.disableCommandsMessage: g.blue(c.disableCommandsMessage) return None if not p and not script: g.trace('can not happen: no p and no script') return g.app.scriptDict = {} args = self.getArgs(p) if not script: script = self.getScript(p) c.executeScript(args=args, p=p, script=script, silent=True) # Remove the button if the script asks to be removed. if g.app.scriptDict.get('removeMe'): g.es("Removing '%s' button at its request" % buttonText) self.deleteButton(b)
def goToNextDirtyHeadline(self, event=None): """Select the node that is marked as changed.""" c = self; p = c.p if not p: return p.moveToThreadNext() wrapped = False while 1: if p and p.isDirty(): break elif p: p.moveToThreadNext() elif wrapped: break else: wrapped = True p = c.rootPosition() if not p: g.blue('done') c.treeSelectHelper(p) # Sets focus.
def goToPrevMarkedHeadline(self, event=None): """Select the next marked node.""" c = self; p = c.p if not p: return p.moveToThreadBack() wrapped = False while 1: if p and p.isMarked(): break elif p: p.moveToThreadBack() elif wrapped: break else: wrapped = True p = c.rootPosition() if not p: g.blue('done') c.treeSelectHelper(p) # Sets focus.
def on_open (tag,keywords): c = keywords.get("c") if not c: return p = c.rootPosition() g.blue("scanning for @read-only nodes...") while p: h = p.h if g.match_word(h,0,"@read-only"): changed = insert_read_only_node(c,p,h[11:]) g.red("changing %s" % p.h) if changed: if not p.isDirty(): p.setDirty() if not c.isChanged(): c.setChanged(changed) p.moveToThreadNext() c.redraw()
def on_open(tag, keywords): c = keywords.get("c") if not c: return p = c.rootPosition() g.blue("scanning for @read-only nodes...") while p: h = p.h if g.match_word(h, 0, "@read-only"): changed = insert_read_only_node(c, p, h[11:]) g.red("changing %s" % p.h) if changed: if not p.isDirty(): p.setDirty() if not c.isChanged(): c.setChanged() p.moveToThreadNext() c.redraw()
def cmd_Export(event): '''Export the current node to Word''' c = event.get('c') try: word = getWordConnection() if word: header_style = getConfiguration().get("Main", "Header_Style") # Based on the rst plugin g.blue("Writing tree to Word") config = getConfiguration() writeNodeAndTree( c, word, config.get("Main", "header_style").strip(), 1, int(config.get("Main", "max_headings")), config.get("Main", "use_section_numbers") == "Yes", "") g.es("Done!") except Exception as err: g.error("Exception writing Word") g.es_exception()
def markChangedRoots(self, event=None): """Mark all changed @root nodes.""" c = self; u = c.undoer; undoType = 'Mark Changed' current = c.p c.endEditing() u.beforeChangeGroup(current, undoType) for p in c.all_unique_positions(): if p.isDirty() and not p.isMarked(): s = p.b flag, i = g.is_special(s, "@root") if flag: bunch = u.beforeMark(p, undoType) c.setMarked(p) # Calls a hook. p.setDirty() c.setChanged() u.afterMark(p, undoType, bunch) u.afterChangeGroup(current, undoType) if not g.unitTesting: g.blue('done') c.redraw_after_icons_changed()
def findNextClone(self, event=None): """Select the next cloned node.""" c = self; p = c.p; cc = c.chapterController if not p: return if p.isCloned(): p.moveToThreadNext() flag = False while p: if p.isCloned(): flag = True; break else: p.moveToThreadNext() if flag: if cc: # name = cc.findChapterNameForPosition(p) cc.selectChapterByName('main') c.selectPosition(p) c.redraw_after_select(p) else: g.blue('no more clones')
def stop (tag,keywords): c = keywords.get('c') if not c: g.trace('can not happen') return multi = scanForMultiPath(c) for fileName in multi: paths = multi.get(fileName) for path in paths: try: if os.path.isdir(path): shutil.copy2(fileName,path) g.blue("multifile:\nWrote %s to %s" % (fileName,path)) else: g.error("multifile:\n%s is not a directory, not writing %s" % (path,fileName)) except Exception: g.error("multifile:\nCant write %s to %s" % (fileName,path)) g.es_exception_type() files.clear()
def loadHandlers(self, tag, keys): """ Load all enabled plugins. Using a module name (without the trailing .py) allows a plugin to be loaded from outside the leo/plugins directory. """ def pr(*args, **keys): if not g.app.unitTesting: g.es_print(*args, **keys) s = g.app.config.getEnabledPlugins() if not s: return if tag == 'open0' and not g.app.silentMode and not g.app.batchMode: if 0: s2 = f"@enabled-plugins found in {g.app.config.enabledPluginsFileName}" g.blue(s2) for plugin in s.splitlines(): if plugin.strip() and not plugin.lstrip().startswith('#'): self.loadOnePlugin(plugin.strip(), tag=tag)
def cmd_Export(event): '''Export the current node to Word''' c = event.get('c') try: word = getWordConnection() if word: # header_style = getConfiguration().get("Main", "Header_Style") # Based on the rst plugin g.blue("Writing tree to Word") config = getConfiguration() writeNodeAndTree(c,word, config.get("Main", "header_style").strip(), 1, int(config.get("Main", "max_headings")), config.get("Main", "use_section_numbers") == "Yes", "") g.es("Done!") except Exception: g.error("Exception writing Word") g.es_exception()
def executeScriptFromButton(self, b, buttonText, p, script): """ Called in various contexts to execute an @button script. 1. If p is given, use the script in p.b. 2. If script is given, use that. 3. Finally, search for the node whose gnx is given. qt_frame.py call this method, so it must be a method of this class. """ c = self.c if c.disableCommandsMessage: g.blue(c.disableCommandsMessage) return None g.app.scriptDict = {} args = self.getArgs(p) # Note: use c.p, not p! c.executeScript(args=args, p=p, script=script, silent=True) # Remove the button if the script asks to be removed. if g.app.scriptDict.get("removeMe"): g.es("Removing '%s' button at its request" % buttonText) self.deleteButton(b)
def deleteMarked(self, event=None): """Delete all marked nodes.""" c = self; u = c.undoer; p1 = c.p.copy() undo_data, p = [], c.rootPosition() while p: if p.isMarked(): undo_data.append(p.copy()) next = p.positionAfterDeletedTree() p.doDelete() p = next else: p.moveToThreadNext() if undo_data: u.afterDeleteMarkedNodes(undo_data, p1) if not g.unitTesting: g.blue(f"deleted {len(undo_data)} nodes") c.setChanged() # Don't even *think* about restoring the old position. c.contractAllHeadlines() c.selectPosition(c.rootPosition()) c.redraw()
def loadHandlers(self, tag, keys): ''' Load all enabled plugins. Using a module name (without the trailing .py) allows a plugin to be loaded from outside the leo/plugins directory. ''' def pr(*args, **keys): if not g.app.unitTesting: g.es_print(*args, **keys) s = g.app.config.getEnabledPlugins() if not s: return if tag == 'open0' and not g.app.silentMode and not g.app.batchMode: if 0: s2 = '@enabled-plugins found in %s' % ( g.app.config.enabledPluginsFileName) g.blue(s2) for plugin in s.splitlines(): if plugin.strip() and not plugin.lstrip().startswith('#'): self.loadOnePlugin(plugin.strip(), tag=tag)
def cloneMarked(self, event=None): """Clone all marked nodes as children of a new node.""" c = self; u = c.undoer; p1 = c.p.copy() # Create a new node to hold clones. parent = p1.insertAfter() parent.h = 'Clones of marked nodes' cloned, n, p = [], 0, c.rootPosition() while p: # Careful: don't clone already-cloned nodes. if p == parent: p.moveToNodeAfterTree() elif p.isMarked() and p.v not in cloned: cloned.append(p.v) if 0: # old code # Calling p.clone would cause problems p.clone().moveToLastChildOf(parent) else: # New code. # Create the clone directly as a child of parent. p2 = p.copy() n = parent.numberOfChildren() p2._linkAsNthChild(parent, n) p.moveToNodeAfterTree() n += 1 else: p.moveToThreadNext() if n: c.setChanged() parent.expand() c.selectPosition(parent) u.afterCloneMarkedNodes(p1) else: parent.doDelete() c.selectPosition(p1) if not g.unitTesting: g.blue(f"cloned {n} nodes") c.redraw()
def OpenProcess(p): global RunNode,WorkDir global In,OutThread,ErrThread,ExitCode command = p.h[4:].strip() # Remove @run if not command: return #@+<< set the working directory or return >> #@+node:ekr.20040910094754: *3* << set the working directory or return >> args = command.split(' ') path,fname = os.path.split(args[0]) if g.match(fname,0,'#'): return if path: if os.access(path,os.F_OK) == 1: WorkDir=os.getcwd() os.chdir(path) else: g.error("@run: invalid path: %s" % (path)) return #@-<< set the working directory or return >> #@+<< set the command, removing all args following '#' >> #@+node:ekr.20040910100935: *3* << set the command, removing all args following '#' >> command = fname for arg in args[1:]: if g.match(arg,0,'#'): break else: command += ' ' + arg.strip() #@-<< set the command, removing all args following '#' >> if not command.strip(): return RunNode=p args = [] #@+<< append arguments from child nodes to command >> #@+node:ekr.20040910095147: *3* << append arguments from child nodes to command >> for child in p.children(): h = child.h if g.match_word(h,0,"@arg"): arg = h[4:].strip() args.append(arg) else: if ( not g.match_word(h,0,"@run") and not g.match_word(h,0,"@in") and not g.match_word(h,0,"@input") ): args.append(child.b.strip()) #@-<< append arguments from child nodes to command >> g.blue("@run %s>%s" % (os.getcwd(),command)) for arg in args: g.blue("@arg %s" % arg) command += ' ' + ' '.join(args) # Start the threads and open the pipe. OutThread = readingThread() ErrThread = readingThread() # In,OutThread.File,ErrThread.File = os.popen3(command,"t") #### OutThread.File,In,ErrThread.File = os.popen3(command,"t") PIPE = subprocess.PIPE proc = subprocess.Popen(command, shell=True) # , # bufsize=bufsize, # stdin=PIPE,stdout=PIPE,stderr=PIPE) # ,close_fds=True) In = proc.stdin OutThread.File = proc.stdout ErrThread.File = proc.stderr OutThread.start() ErrThread.start() # Mark and select the node. RunNode.setMarked() c = RunNode.v.context c.selectPosition(RunNode) if os.name in ("nt","dos"): c.redraw()
def message (self,s): g.blue(s)
def editnode_on_idle (tag,keywords): #g.trace(tag,keywords) import os a = g.app if a.killed: return # g.trace('open with plugin') for dict in a.openWithFiles: path = dict.get("path") c = dict.get("c") encoding = dict.get("encoding",None) p = dict.get("p") old_body = dict.get("body") if path and os.path.exists(path): try: time = os.path.getmtime(path) # g.trace(path,time,dict.get('time')) if time and time != dict.get("time"): dict["time"] = time # inhibit endless dialog loop. # The file has changed. #@+<< set s to the file text >> #@+node:ville.20090701142447.5474: *3* << set s to the file text >> try: # Update v from the changed temp file. f=open(path) s=f.read() f.close() except: g.es("can not open " + g.shortFileName(path)) break #@-<< set s to the file text >> #@+<< update p's body text >> #@+node:ville.20090701142447.5475: *3* << update p's body text >> # Convert body and s to whatever encoding is in effect. body = p.b body = g.toEncodedString(body,encoding,reportErrors=True) s = g.toEncodedString(s,encoding,reportErrors=True) conflict = body != old_body and body != s # Set update if we should update the outline from the file. if conflict: # 2012/02/04: Don't raise dialog for files opened with vim.py, xemacs.py, etc. paths = [z.get('path') for z in g.app.openWithFiles] if path in paths: update = True else: # See how the user wants to resolve the conflict. g.error("conflict in " + g.shortFileName(path)) message = "Replace changed outline with external changes?" result = g.app.gui.runAskYesNoDialog(c,"Conflict!",message) update = result.lower() == "yes" else: update = s != body if update: g.blue("updated from: " + g.shortFileName(path)) s = g.toUnicode(s,encoding=encoding) c.setBodyString(p,s) #TL - 7/2/08 Converted to configurable 'goto node...' if c.config.getBool('open_with_goto_node_on_update'): c.selectPosition(p) dict["body"] = s # A patch by Terry Brown. if c.config.getBool('open_with_save_on_update'): c.save() elif conflict: g.blue("not updated from: " + g.shortFileName(path)) #@-<< update p's body text >> except Exception: # g.es_exception() pass
def doNodeAction(pClicked, c): hClicked = pClicked.h.strip() #Display messages based on 'messageLevel'. Valid values: # 0 = log no messages # 1 = log that the plugin was triggered and each matched patterns # 2 = log 1 & 'event passed' # 3 = log 1,2 & 'no match to pattern' # 4 = log 1,2,3, & any code debugging messages, # matched pattern's 'directives', and '@file saved' settings messageLevel = c.config.getInt('nodeActions_message_level') if messageLevel >= 1: g.es( "nodeActions: triggered" ) #Save @file type nodes before running script if enabled saveAtFile = c.config.getBool('nodeActions_save_atFile_nodes') if messageLevel >= 4: g.blue( "nA: Global nodeActions_save_atFile_nodes=",saveAtFile) #Find the "nodeActions" node pNA = g.findNodeAnywhere(c,"nodeActions") if not pNA: pNA = g.findNodeAnywhere(c,"NodeActions") if pNA: #Found "nodeActions" node foundPattern = False passEventExternal = False #No pass to next plugin after pattern matched #Check entire subtree under the "nodeActions" node for pattern for pScript in pNA.subtree(): #Nodes with subnodes are not tested for a match if pScript.hasChildren(): continue #Don't trigger on double click of a nodeActions' pattern node if pClicked == pScript: continue pattern = pScript.h.strip() #Pattern node's header if messageLevel >= 4: g.blue( "nA: Checking pattern '" + pattern) #if directives exist, parse them and set directive flags for later use # pylint: disable=anomalous-backslash-in-string directiveExists = re.search( " \[[V>X],?[V>X]?,?[V>X]?]$", pattern ) if directiveExists: directives = directiveExists.group(0) else: directives = "[]" #What directives exist? useRegEx = re.search("X", directives) != None passEventInternal = re.search("V", directives) != None if not passEventExternal: #don't disable once enabled. passEventExternal = re.search(">", directives) != None #Remove the directives from the end of the pattern (if they exist) pattern = re.sub( " \[.*]$", "", pattern, 1) if messageLevel >= 4: g.blue( "nA: Pattern='" + pattern + "' " + "(after directives removed)") #Keep copy of pattern without directives for message log patternOriginal = pattern #if pattern begins with "@files" and clicked node is an @file type #node then replace "@files" in pattern with clicked node's @file type patternBeginsWithAtFiles = re.search( "^@files ", pattern ) clickedAtFileTypeNode = False #assume @file type node not clicked if patternBeginsWithAtFiles: #Check if first word in clicked header is in list of @file types firstWordInClickedHeader = hClicked.split()[0] if firstWordInClickedHeader in atFileTypes: clickedAtFileTypeNode = True #Tell "write @file type nodes" code #Replace "@files" in pattern with clicked node's @file type pattern = re.sub( "^@files", firstWordInClickedHeader, pattern) if messageLevel >= 4: g.blue( "nA: Pattern='" + pattern + "' " + "(after @files substitution)") #Check for pattern match to clicked node's header if useRegEx: match = re.search(pattern, hClicked) else: match = fnmatch.fnmatchcase(hClicked, pattern) if match: if messageLevel >= 1: g.blue( "nA: Matched pattern '" + patternOriginal + "'") if messageLevel >= 4: g.blue( "nA: Directives: X=",useRegEx, "V=",passEventInternal, ">=",passEventExternal,) #if @file type node, save node to disk (if configured) if clickedAtFileTypeNode: if saveAtFile: #Problem - No way found to just save clicked node, saving all c.fileCommands.writeAtFileNodes() c.requestRedrawFlag = True c.redraw() if messageLevel >= 3: g.blue( "nA: Saved '" + hClicked + "'") #Run the script applyNodeAction(pScript, pClicked, c) #Indicate that at least one pattern was matched foundPattern = True #Don't trigger more patterns unless enabled in patterns' headline if passEventInternal == False: break else: if messageLevel >= 3: g.blue("nA: Did not match '" + patternOriginal + "'") #Finished checking headline against patterns if not foundPattern: #no match to any pattern, always pass event to next plugin if messageLevel >= 1: g.blue("nA: No patterns matched to """ + hClicked + '"') return False #TL - Inform onIconDoubleClick that no action was taken elif passEventExternal == True: #last matched pattern has directive to pass event to next plugin if messageLevel >= 2: g.blue("nA: Event passed to next plugin") return False #TL - Inform onIconDoubleClick to pass double-click event else: #last matched pattern did not have directive to pass event to plugin if messageLevel >= 2: g.blue("nA: Event not passed to next plugin") return True #TL - Inform onIconDoubleClick to not pass double-click else: #nodeActions plugin enabled without a 'nodeActions' node if messageLevel >= 4: g.blue("nA: The ""nodeActions"" node does not exist") return False #TL - Inform onIconDoubleClick that no action was taken
def loadOnePlugin (self,moduleOrFileName,tag='open0',verbose=False): trace = False and not g.unitTesting verbose = False or verbose if not g.app.enablePlugins: if trace: g.trace('plugins disabled') return None if moduleOrFileName.startswith('@'): if trace: g.trace('ignoring Leo directive') return None # Return None, not False, to keep pylint happy. # Allow Leo directives in @enabled-plugins nodes. moduleName = self.regularizeName(moduleOrFileName) if self.isLoaded(moduleName): module = self.loadedModules.get(moduleName) if trace and verbose: g.warning('loadOnePlugin: plugin',moduleName,'already loaded') return module assert g.app.loadDir moduleName = g.toUnicode(moduleName) # This import will typically result in calls to registerHandler. # if the plugin does _not_ use the init top-level function. self.loadingModuleNameStack.append(moduleName) try: toplevel = __import__(moduleName) # need to look up through sys.modules, __import__ returns toplevel package result = sys.modules[moduleName] except g.UiTypeException: if not g.unitTesting and not g.app.batchMode: g.es_print('Plugin %s does not support %s gui' % ( moduleName,g.app.gui.guiName())) result = None except ImportError: if trace or tag == 'open0': # Just give the warning once. g.error('error importing plugin:',moduleName) g.es_exception() result = None except SyntaxError: if trace or tag == 'open0': # Just give the warning once. g.error('syntax error importing plugin:',moduleName) # g.es_exception() result = None except Exception as e: g.error('exception importing plugin ' + moduleName) g.es_exception() result = None self.loadingModuleNameStack.pop() if result: self.signonModule = result # for self.plugin_signon. self.loadingModuleNameStack.append(moduleName) if tag == 'unit-test-load': pass # Keep the result, but do no more. elif hasattr(result,'init'): try: # Indicate success only if init_result is True. init_result = result.init() if init_result not in (True,False): g.error('Error: %s.init did not return a bool' % (moduleName)) if init_result: self.loadedModules[moduleName] = result self.loadedModulesFilesDict[moduleName] = g.app.config.enabledPluginsFileName else: if verbose and not g.app.initing: g.error('loadOnePlugin: failed to load module',moduleName) result = None except Exception: g.error('exception loading plugin') g.es_exception() result = None else: # No top-level init function. # Guess that the module was loaded correctly, # but do *not* load the plugin if we are unit testing. if g.app.unitTesting: result = None self.loadedModules[moduleName] = None else: g.trace('no init()',moduleName) self.loadedModules[moduleName] = result self.loadingModuleNameStack.pop() if g.app.batchMode or g.app.inBridge: # or g.unitTesting pass elif result: if trace or verbose: g.blue('loadOnePlugin: loaded',moduleName) else: if trace or self.warn_on_failure or (verbose and not g.app.initing): if trace or tag == 'open0': g.error('loadOnePlugin: can not load enabled plugin:',moduleName) return result