def handleAtPluginNode(self, p): '''Handle @plugin nodes.''' c = self.c tag = "@plugin" h = p.h assert (g.match(h, 0, tag)) # Get the name of the module. theFile = h[len(tag):].strip() # The following two lines break g.loadOnePlugin #if theFile[-3:] == ".py": # theFile = theFile[:-3] # in fact, I believe the opposite behavior is intended: add .py if it doesn't exist if theFile[-3:] != ".py": theFile = theFile + ".py" theFile = g.toUnicode(theFile) if not self.atPluginNodes: g.warning("disabled @plugin: %s" % (theFile)) # elif theFile in g.app.loadedPlugins: elif g.pluginIsLoaded(theFile): g.warning("plugin already loaded: %s" % (theFile)) else: theModule = g.loadOnePlugin(theFile)
def strip(self): '''Display a file with all sentinel lines removed''' # get a path object for this position c = self.c currentPath = self.getCurrentPath() if currentPath.exists(): path = currentPath.abspath() s = 'currentPath: %s' % path g.es_print(s) filelines = path.lines() # Add an @ignore directive. lines = ['@ignore\n'] verbatim = False for line in filelines: if verbatim: lines.append(line) verbatim = False elif line.strip().startswith('#@verbatim'): verbatim = True elif not line.strip().startswith('#@'): lines.append(line) c.setBodyText(self.current, ''.join(lines)) else: g.warning('path does not exist: %s' % (str(currentPath)))
def handleAtPluginNode (self,p): '''Handle @plugin nodes.''' c = self.c tag = "@plugin" h = p.h assert(g.match(h,0,tag)) # Get the name of the module. theFile = h[len(tag):].strip() # The following two lines break g.loadOnePlugin #if theFile[-3:] == ".py": # theFile = theFile[:-3] # in fact, I believe the opposite behavior is intended: add .py if it doesn't exist if theFile[-3:] != ".py": theFile = theFile + ".py" theFile = g.toUnicode(theFile) if not self.atPluginNodes: g.warning("disabled @plugin: %s" % (theFile)) # elif theFile in g.app.loadedPlugins: elif g.pluginIsLoaded(theFile): g.warning("plugin already loaded: %s" % (theFile)) else: theModule = g.loadOnePlugin(theFile)
def strip(self): '''Display a file with all sentinel lines removed''' # get a path object for this position c = self.c currentPath = self.getCurrentPath() if currentPath.exists(): path = currentPath.abspath() s = 'currentPath: %s' % path g.es_print(s) filelines = path.lines() # Add an @ignore directive. lines = ['@ignore\n'] verbatim = False for line in filelines: if verbatim: lines.append(line) verbatim = False elif line.strip().startswith('#@verbatim'): verbatim = True elif not line.strip().startswith('#@'): lines.append(line) c.setBodyText(self.current,''.join(lines)) else: g.warning('path does not exist: %s' % (str(currentPath)))
def check_line(p, line, st): # every child node ends with return #@+others #@+node:vitalije.20170726193840.1: *4* verbatim lines if is_verbatim(line): return 1, 2 #@+node:vitalije.20170726193927.1: *4* others m = others_pat.match(line) if m: n = inc(st) for p1 in others_iterator(p): n = numerate_node(p1, n) n = inc(n) return (0, n - st) if delim_st else (0, n - st) #@+node:vitalije.20170726193858.1: *4* directives in clean if not delim_st and g.isDirective(line): return 0, 0 #@+node:vitalije.20170726193908.1: *4* all if line.strip() == '@all': n = st + 1 for p1 in p.subtree(): n += 1 if vlines(p1): flines = [] for x in vlines(p1): n += 1 if is_verbatim(x): n += 1 flines.append(n) flines.append(n + 1) else: flines = [n] flines_data[pkey(p1)] = tuple(flines), n return 1, n - st #@+node:vitalije.20170726193920.1: *4* section reference m = section_pat.match(line) if m: p1 = g.findReference(m.group(2), p) if not p1: g.warning('unresolved section reference %s' % m.group(2)) if delim_st: return 0, 2 return 0, 0 n = inc(st) n = numerate_node(p1, n) n = inc(n) return (0, n - st) if delim_st else (0, n - st) #@+node:vitalije.20170726193933.1: *4* doc part if doc_pattern.match(line): if delim_st: return 0, 1 return 0, 0 #@+node:vitalije.20170726193941.1: *4* code part if code_pattern.match(line): if delim_st: return 0, 1 return 0, 0 #@-others # if we get here it is an ordinary line return 0, 1
def addComments(self, event=None): #@+<< addComments docstring >> #@+node:ekr.20171123135625.35: *3* << addComments docstring >> #@@pagewidth 50 ''' Converts all selected lines to comment lines using the comment delimiters given by the applicable @language directive. Inserts single-line comments if possible; inserts block comments for languages like html that lack single-line comments. @bool indent_added_comments If True (the default), inserts opening comment delimiters just before the first non-whitespace character of each line. Otherwise, inserts opening comment delimiters at the start of each line. *See also*: delete-comments. ''' #@-<< addComments docstring >> c = self p = c.p head, lines, tail, oldSel, oldYview = self.getBodyLines() if not lines: g.warning('no text selected') return # The default language in effect at p. language = c.frame.body.colorizer.scanLanguageDirectives(p) if c.hasAmbiguousLanguage(p): language = c.getLanguageAtCursor(p, language) d1, d2, d3 = g.set_delims_from_language(language) d2 = d2 or '' d3 = d3 or '' if d1: openDelim, closeDelim = d1 + ' ', '' else: openDelim, closeDelim = d2 + ' ', ' ' + d3 # Comment out non-blank lines. indent = c.config.getBool('indent-added-comments', default=True) result = [] for line in lines: if line.strip(): i = g.skip_ws(line, 0) if indent: result.append(line[0:i] + openDelim + line[i:].replace('\n', '') + closeDelim + '\n') else: result.append(openDelim + line.replace('\n', '') + closeDelim + '\n') else: result.append(line) result = ''.join(result) c.updateBodyPane(head, result, tail, undoType='Add Comments', oldSel=None, oldYview=oldYview)
def command_helper(self, event, kind, preview, verbose): def predicate(p): return self.filename(p) # Find all roots. t1 = time.time() c = self.c self.kind = kind p = event.p if event and hasattr(event, 'p') else c.p roots = g.findRootsWithPredicate(c, p, predicate=predicate) if not roots: g.warning('No @adoc nodes in', p.h) return [] # Write each root to a file. i_paths = [] for p in roots: try: i_path = self.filename(p) # #1398. i_path = c.expand_path_expression(i_path) i_path = g.os_path_finalize(i_path) with open(i_path, 'w', encoding='utf-8', errors='replace') as self.output_file: self.write_root(p) i_paths.append(i_path) except IOError: g.es_print(f"Can not open {i_path!r}") except Exception: g.es_print(f"Unexpected exception opening {i_path!r}") g.es_exception() # Convert each file to html. o_paths = [] for i_path in i_paths: o_path = self.compute_opath(i_path) o_paths.append(o_path) if kind == 'adoc': self.run_asciidoctor(i_path, o_path) elif kind == 'pandoc': self.run_pandoc(i_path, o_path) elif kind == 'sphinx': self.run_sphinx(i_path, o_path) else: g.trace('BAD KIND') return None if kind != 'sphinx': print(f"{kind}: wrote {o_path}") if preview: if kind == 'sphinx': g.es_print('preview not available for sphinx') else: # open .html files in the default browser. g.execute_shell_commands(o_paths) t2 = time.time() if verbose: n = len(i_paths) g.es_print(f"{kind}: wrote {n} file{g.plural(n)} " f"in {(t2-t1):4.2f} sec.") return i_paths
def check_line(p, line, st): # every child node ends with return #@+others #@+node:vitalije.20170726193840.1: *4* verbatim lines if is_verbatim(line): return 1, 2 #@+node:vitalije.20170726193927.1: *4* others m = others_pat.match(line) if m: n = inc(st) for p1 in others_iterator(p): n = numerate_node(p1, n) n = inc(n) return (0, n-st) if delim_st else (0, n-st) #@+node:vitalije.20170726193858.1: *4* directives in clean if not delim_st and g.isDirective(line): return 0, 0 #@+node:vitalije.20170726193908.1: *4* all if line.strip() == '@all': n = st + 1 for p1 in p.subtree(): n += 1 if vlines(p1): flines = [] for x in vlines(p1): n += 1 if is_verbatim(x): n+=1 flines.append(n) flines.append(n+1) else: flines = [n] flines_data[pkey(p1)] = tuple(flines), n return 1, n - st #@+node:vitalije.20170726193920.1: *4* section reference m = section_pat.match(line) if m: p1 = g.findReference(m.group(2), p) if not p1: g.warning('unresolved section reference %s'%m.group(2)) if delim_st: return 0,2 return 0,0 n = inc(st) n = numerate_node(p1, n) n = inc(n) return (0, n-st) if delim_st else (0, n-st) #@+node:vitalije.20170726193933.1: *4* doc part if doc_pattern.match(line): if delim_en: return 0, 2 return 1,1 #@+node:vitalije.20170726193941.1: *4* code part if code_pattern.match(line): if delim_en: return 1, 2 if delim_st: return 0, 1 return 0, 0 #@-others # if we get here it is an ordinary line return 0,1
def insert_ignore_directive(self, parent): c = self.c # Do *not* update the screen by setting p.b. parent.v.b = parent.v.b.rstrip() + '\n@ignore\n' if g.unitTesting: pass elif parent.isAnyAtFileNode() and not parent.isAtAutoNode(): g.warning('inserting @ignore') c.import_error_nodes.append(parent.h)
def insert_ignore_directive(self, parent): c = self.c parent.v.b = parent.v.b.rstrip() + '\n@ignore\n' # Do *not* update the screen by setting p.b. if g.unitTesting: g.app.unitTestDict['fail'] = g.callers() elif parent.isAnyAtFileNode() and not parent.isAtAutoNode(): g.warning('inserting @ignore') c.import_error_nodes.append(parent.h)
def deleteComments(self, event=None): #@+<< deleteComments docstring >> #@+node:ekr.20171123135625.37: *3* << deleteComments docstring >> #@@pagewidth 50 """ Removes one level of comment delimiters from all selected lines. The applicable @language directive determines the comment delimiters to be removed. Removes single-line comments if possible; removes block comments for languages like html that lack single-line comments. *See also*: add-comments. """ #@-<< deleteComments docstring >> c = self p = c.p head, lines, tail, oldSel, oldYview = self.getBodyLines() result = [] if not lines: g.warning('no text selected') return # The default language in effect at p. language = c.frame.body.colorizer.scanLanguageDirectives(p) if c.hasAmbiguousLanguage(p): language = c.getLanguageAtCursor(p, language) d1, d2, d3 = g.set_delims_from_language(language) if d1: # Remove the single-line comment delim in front of each line d1b = d1 + ' ' n1, n1b = len(d1), len(d1b) for s in lines: i = g.skip_ws(s, 0) if g.match(s, i, d1b): result.append(s[:i] + s[i + n1b :]) elif g.match(s, i, d1): result.append(s[:i] + s[i + n1 :]) else: result.append(s) else: # Remove the block comment delimiters from each line. n2, n3 = len(d2), len(d3) for s in lines: i = g.skip_ws(s, 0) j = s.find(d3, i + n2) if g.match(s, i, d2) and j > -1: first = i + n2 if g.match(s, first, ' '): first += 1 last = j if g.match(s, last - 1, ' '): last -= 1 result.append(s[:i] + s[first:last] + s[j + n3 :]) else: result.append(s) result = ''.join(result) c.updateBodyPane( head, result, tail, undoType='Delete Comments', oldSel=None, oldYview=oldYview)
def scrOrResRoot(cmdrb, gld, babelG, babelRoot, scrOrRes): """ Get the Script or Results Root Arguments: cmdrb: Leo-Editor commander for the Babel Root gld: The global dictionary used for the execution of the Babel Parameters script. babelG: Babel globals babelRoot: Babel Root scrOrRes: "script" for Script root "results" for Results root Returns: (cmdrx, rootx): cmdrx: Commander for root position rootx: Root position """ rootx = gld.get('babel_{0}'.format(scrOrRes)) if rootx is None: # Rootx is a child of babelRoot. cmdrx = cmdrb rootx = babelRoot.getNthChild({ 'script': 0, 'results': 1 }[scrOrRes]) if not rootx: raise babelG.babel_api.BABEL_ROOT( '{ord} child of current node must be ' 'the {sor} root.'.format(ord={ 'script': 'First', 'results': 'Second' }[scrOrRes], sor=scrOrRes)) elif isinstance(rootx, type('abc')): # scriptRoot is a UNL pathname, nodePart = unlSplit(rootx) if pathname is None: cmdrx = cmdrb else: cmdrx = None cmdrx, posList = unl2pos(rootx, cmdr=cmdrx) if not posList: raise babelG.babel_api.BABEL_UNL_NO_POS( '{0} Root UNL does not match any ' 'position.'.format(scrOrRes.capitalize())) else: rootx = posList[0] if len(posList) > 1: warning = '{0} Root UNL satisfies {1} positions.'.format( scrOrRes.capitalize(), len(posList)) leoG.warning(warning) else: # scriptRoot is (cmdr, pos) pair cmdrx, rootx = rootx rootx = rootx.copy() return cmdrx, rootx
def refreshFromDisk(self, event=None): '''Refresh an @<file> node from disk.''' trace = False and not g.unitTesting c, p, u = self, self.p, self.undoer c.nodeConflictList = [] fn = p.anyAtFileNodeName() shouldDelete = (not g.SQLITE) or (c.sqlite_connection is None) if fn: b = u.beforeChangeTree(p) redraw_flag = True at = c.atFileCommands c.recreateGnxDict() # Fix bug 1090950 refresh from disk: cut node ressurection. i = g.skip_id(p.h, 0, chars='@') word = p.h[0:i] if word == '@auto': # This includes @auto-* if shouldDelete: p.deleteAllChildren() # Fix #451: refresh-from-disk selects wrong node. p = at.readOneAtAutoNode(fn, p) elif word in ('@thin', '@file'): if shouldDelete: p.deleteAllChildren() at.read(p, force=True) elif word in ('@clean', ): # Wishlist 148: use @auto parser if the node is empty. if p.b.strip() or p.hasChildren(): at.readOneAtCleanNode(p) else: # Fix #451: refresh-from-disk selects wrong node. p = at.readOneAtAutoNode(fn, p) elif word == '@shadow': if shouldDelete: p.deleteAllChildren() at.read(p, force=True, atShadow=True) elif word == '@edit': if shouldDelete: p.deleteAllChildren() at.readOneAtEditNode(fn, p) else: g.es_print('can not refresh from disk\n%r' % p.h) redraw_flag = False else: g.warning('not an @<file> node:\n%r' % (p.h)) redraw_flag = False if redraw_flag: # Fix #451: refresh-from-disk selects wrong node. c.selectPosition(p) u.afterChangeTree(p, command='refresh-from-disk', bunch=b) # Create the 'Recovered Nodes' tree. c.fileCommands.handleNodeConflicts() t1 = time.clock() c.redraw() t2 = time.clock() if trace: n = sum([1 for z in p.self_and_subtree()]) h = sum([hash(z.h) for z in p.self_and_subtree()]) g.trace('%s nodes, hash: %s in %5.2f sec. %r' % (n, h, (t2 - t1), p.h))
def deleteComments(self, event=None): #@+<< deleteComments docstring >> #@+node:ekr.20171123135625.37: *3* << deleteComments docstring >> #@@pagewidth 50 ''' Removes one level of comment delimiters from all selected lines. The applicable @language directive determines the comment delimiters to be removed. Removes single-line comments if possible; removes block comments for languages like html that lack single-line comments. *See also*: add-comments. ''' #@-<< deleteComments docstring >> c = self p = c.p head, lines, tail, oldSel, oldYview = self.getBodyLines() result = [] if not lines: g.warning('no text selected') return # The default language in effect at p. language = c.frame.body.colorizer.scanLanguageDirectives(p) if c.hasAmbiguousLanguage(p): language = c.getLanguageAtCursor(p, language) d1, d2, d3 = g.set_delims_from_language(language) if d1: # Remove the single-line comment delim in front of each line d1b = d1 + ' ' n1, n1b = len(d1), len(d1b) for s in lines: i = g.skip_ws(s, 0) if g.match(s, i, d1b): result.append(s[: i] + s[i + n1b:]) elif g.match(s, i, d1): result.append(s[: i] + s[i + n1:]) else: result.append(s) else: # Remove the block comment delimiters from each line. n2, n3 = len(d2), len(d3) for s in lines: i = g.skip_ws(s, 0) j = s.find(d3, i + n2) if g.match(s, i, d2) and j > -1: first = i + n2 if g.match(s, first, ' '): first += 1 last = j if g.match(s, last - 1, ' '): last -= 1 result.append(s[: i] + s[first: last] + s[j + n3:]) else: result.append(s) result = ''.join(result) c.updateBodyPane(head, result, tail, undoType='Delete Comments', oldSel=None, oldYview=oldYview)
def refreshFromDisk(self, event=None): """Refresh an @<file> node from disk.""" c, p, u = self, self.p, self.undoer c.nodeConflictList = [] fn = p.anyAtFileNodeName() shouldDelete = c.sqlite_connection is None if not fn: g.warning(f"not an @<file> node: {p.h!r}") return # #1603. if os.path.isdir(fn): g.warning(f"not a file: {fn!r}") return b = u.beforeChangeTree(p) redraw_flag = True at = c.atFileCommands c.recreateGnxDict() # Fix bug 1090950 refresh from disk: cut node ressurection. i = g.skip_id(p.h, 0, chars='@') word = p.h[0:i] if word == '@auto': # This includes @auto-* if shouldDelete: p.v._deleteAllChildren() # Fix #451: refresh-from-disk selects wrong node. p = at.readOneAtAutoNode(p) elif word in ('@thin', '@file'): if shouldDelete: p.v._deleteAllChildren() at.read(p) elif word == '@clean': # Wishlist 148: use @auto parser if the node is empty. if p.b.strip() or p.hasChildren(): at.readOneAtCleanNode(p) else: # Fix #451: refresh-from-disk selects wrong node. p = at.readOneAtAutoNode(p) elif word == '@shadow': if shouldDelete: p.v._deleteAllChildren() at.read(p) elif word == '@edit': at.readOneAtEditNode(fn, p) # Always deletes children. elif word == '@asis': # Fix #1067. at.readOneAtAsisNode(fn, p) # Always deletes children. else: g.es_print(f"can not refresh from disk\n{p.h!r}") redraw_flag = False if redraw_flag: # Fix #451: refresh-from-disk selects wrong node. c.selectPosition(p) u.afterChangeTree(p, command='refresh-from-disk', bunch=b) # Create the 'Recovered Nodes' tree. c.fileCommands.handleNodeConflicts() c.redraw()
def refreshFromDisk(self, event=None): '''Refresh an @<file> node from disk.''' trace = False and not g.unitTesting c, p, u = self, self.p, self.undoer c.nodeConflictList = [] fn = p.anyAtFileNodeName() shouldDelete = (not g.SQLITE) or (c.sqlite_connection is None) if fn: b = u.beforeChangeTree(p) redraw_flag = True at = c.atFileCommands c.recreateGnxDict() # Fix bug 1090950 refresh from disk: cut node ressurection. i = g.skip_id(p.h, 0, chars='@') word = p.h[0: i] if word == '@auto': # This includes @auto-* if shouldDelete: p.deleteAllChildren() # Fix #451: refresh-from-disk selects wrong node. p = at.readOneAtAutoNode(fn, p) elif word in ('@thin', '@file'): if shouldDelete: p.deleteAllChildren() at.read(p, force=True) elif word in ('@clean',): # Wishlist 148: use @auto parser if the node is empty. if p.b.strip() or p.hasChildren(): at.readOneAtCleanNode(p) else: # Fix #451: refresh-from-disk selects wrong node. p = at.readOneAtAutoNode(fn, p) elif word == '@shadow': if shouldDelete: p.deleteAllChildren() at.read(p, force=True, atShadow=True) elif word == '@edit': if shouldDelete: p.deleteAllChildren() at.readOneAtEditNode(fn, p) else: g.es_print('can not refresh from disk\n%r' % p.h) redraw_flag = False else: g.warning('not an @<file> node:\n%r' % (p.h)) redraw_flag = False if redraw_flag: # Fix #451: refresh-from-disk selects wrong node. c.selectPosition(p) u.afterChangeTree(p, command='refresh-from-disk', bunch=b) # Create the 'Recovered Nodes' tree. c.fileCommands.handleNodeConflicts() t1 = time.clock() c.redraw() t2 = time.clock() if trace: n = sum([1 for z in p.self_and_subtree()]) h = sum([hash(z.h) for z in p.self_and_subtree()]) g.trace('%s nodes, hash: %s in %5.2f sec. %r' % (n, h, (t2-t1), p.h))
def setBackgroundColor(self, colorName, name, w): '''Set the background color of the vr pane.''' pc = self if not colorName: return styleSheet = 'QTextEdit#%s { background-color: %s; }' % (name, colorName) # g.trace(name,colorName) if QtGui.QColor(colorName).isValid(): w.setStyleSheet(styleSheet) elif colorName not in pc.badColors: pc.badColors.append(colorName) g.warning('invalid body background color: %s' % (colorName))
def setBackgroundColor (self,colorName,name,w): '''Set the background color of the vr pane.''' pc = self if not colorName: return styleSheet = 'QTextEdit#%s { background-color: %s; }' % (name,colorName) # g.trace(name,colorName) if QtGui.QColor(colorName).isValid(): w.setStyleSheet(styleSheet) elif colorName not in pc.badColors: pc.badColors.append(colorName) g.warning('invalid body background color: %s' % (colorName))
def processTopTree(self, p): """Call processTree for @rst and @slides node p's subtree or p's ancestors.""" def predicate(p): return self.is_rst_node(p) or g.match_word(p.h, 0, '@slides') roots = g.findRootsWithPredicate(self.c, p, predicate=predicate) if roots: for p in roots: self.processTree(p) else: g.warning('No @rst or @slides nodes in', p.h)
def getWordConnection(): """Get a connection to Word""" g.es("Trying to connect to Word") try: word = win32com.client.gencache.EnsureDispatch("Word.Application") word.Visible = 1 word.Documents.Add() return word except Exception as err: g.warning("Failed to connect to Word") raise
def refreshFromDisk(self, event=None): '''Refresh an @<file> node from disk.''' c, p, u = self, self.p, self.undoer c.nodeConflictList = [] fn = p.anyAtFileNodeName() shouldDelete = (not g.SQLITE) or (c.sqlite_connection is None) if not fn: g.warning('not an @<file> node:\n%r' % (p.h)) return b = u.beforeChangeTree(p) redraw_flag = True at = c.atFileCommands c.recreateGnxDict() # Fix bug 1090950 refresh from disk: cut node ressurection. i = g.skip_id(p.h, 0, chars='@') word = p.h[0: i] if word == '@auto': # This includes @auto-* if shouldDelete: p.v._deleteAllChildren() # Fix #451: refresh-from-disk selects wrong node. p = at.readOneAtAutoNode(fn, p) elif word in ('@thin', '@file'): if shouldDelete: p.v._deleteAllChildren() at.read(p, force=True) elif word == '@clean': # Wishlist 148: use @auto parser if the node is empty. if p.b.strip() or p.hasChildren(): at.readOneAtCleanNode(p) else: # Fix #451: refresh-from-disk selects wrong node. p = at.readOneAtAutoNode(fn, p) elif word == '@shadow': if shouldDelete: p.v._deleteAllChildren() at.read(p, force=True, atShadow=True) elif word == '@edit': at.readOneAtEditNode(fn, p) # Always deletes children. elif word == '@asis': # Fix #1067. at.readOneAtAsisNode(fn, p) # Always deletes children. else: g.es_print('can not refresh from disk\n%r' % p.h) redraw_flag = False if redraw_flag: # Fix #451: refresh-from-disk selects wrong node. c.selectPosition(p) u.afterChangeTree(p, command='refresh-from-disk', bunch=b) # Create the 'Recovered Nodes' tree. c.fileCommands.handleNodeConflicts() c.redraw()
def addComments(self, event=None): #@+<< addComments docstring >> #@+node:ekr.20171123135625.35: *3* << addComments docstring >> #@@pagewidth 50 ''' Converts all selected lines to comment lines using the comment delimiters given by the applicable @language directive. Inserts single-line comments if possible; inserts block comments for languages like html that lack single-line comments. @bool indent_added_comments If True (the default), inserts opening comment delimiters just before the first non-whitespace character of each line. Otherwise, inserts opening comment delimiters at the start of each line. *See also*: delete-comments. ''' #@-<< addComments docstring >> c = self; p = c.p head, lines, tail, oldSel, oldYview = self.getBodyLines() if not lines: g.warning('no text selected') return # The default language in effect at p. language = c.frame.body.colorizer.scanLanguageDirectives(p) if c.hasAmbiguousLanguage(p): language = c.getLanguageAtCursor(p, language) d1, d2, d3 = g.set_delims_from_language(language) d2 = d2 or ''; d3 = d3 or '' if d1: openDelim, closeDelim = d1 + ' ', '' else: openDelim, closeDelim = d2 + ' ', ' ' + d3 # Comment out non-blank lines. indent = c.config.getBool('indent-added-comments', default=True) result = [] for line in lines: if line.strip(): i = g.skip_ws(line, 0) if indent: result.append(line[0: i] + openDelim + line[i:].replace('\n', '') + closeDelim + '\n') else: result.append(openDelim + line.replace('\n', '') + closeDelim + '\n') else: result.append(line) result = ''.join(result) c.updateBodyPane(head, result, tail, undoType='Add Comments', oldSel=None, oldYview=oldYview)
def init_language(self): '''Init self.language.''' c = self.c language = g.toUnicode(c.config.getString('enchant_language')) if language: try: ok = enchant.dict_exists(language) except Exception: ok = False if not ok: g.warning('Invalid language code for Enchant', repr(language)) g.es_print('Using "en_US" instead') language = 'en_US' self.language = language
def scrOrResRoot(cmdrb, gld, babelG, babelRoot, scrOrRes): """ Get the Script or Results Root Arguments: cmdrb: Leo-Editor commander for the Babel Root gld: The global dictionary used for the execution of the Babel Parameters script. babelG: Babel globals babelRoot: Babel Root scrOrRes: "script" for Script root "results" for Results root Returns: (cmdrx, rootx): cmdrx: Commander for root position rootx: Root position """ rootx = gld.get('babel_{0}'.format(scrOrRes)) if rootx is None: # Rootx is a child of babelRoot. cmdrx = cmdrb rootx = babelRoot.getNthChild({'script': 0, 'results': 1}[scrOrRes]) if not rootx: raise babelG.babel_api.BABEL_ROOT('{ord} child of current node must be ' 'the {sor} root.'.format( ord={'script': 'First', 'results': 'Second'}[scrOrRes], sor=scrOrRes)) elif isinstance(rootx, type('abc')): # scriptRoot is a UNL pathname, nodePart = unlSplit(rootx) if pathname is None: cmdrx = cmdrb else: cmdrx = None cmdrx, posList = unl2pos(rootx, cmdr=cmdrx) if not posList: raise babelG.babel_api.BABEL_UNL_NO_POS('{0} Root UNL does not match any ' 'position.'.format(scrOrRes.capitalize())) else: rootx = posList[0] if len(posList) > 1: warning = '{0} Root UNL satisfies {1} positions.'.format( scrOrRes.capitalize(), len(posList)) leoG.warning(warning) else: # scriptRoot is (cmdr, pos) pair cmdrx, rootx = rootx rootx = rootx.copy() return cmdrx, rootx
def getWordConnection(): """Get a connection to Word""" g.es("Trying to connect to Word") try: word = win32com.client.gencache.EnsureDispatch("Word.Application") word.Visible = 1 word.Documents.Add() return word except Exception: g.warning("Failed to connect to Word") raise
def fail(self, lines, n, root): '''Select the last line of the last node of root's tree.''' c = self.c w = c.frame.body.wrapper c.selectPosition(root) c.redraw_now() if not g.unitTesting: if len(lines) < n: g.warning('only', len(lines), 'lines') else: g.warning('line', n, 'not found') # Put the cursor on the last line of body text. w.setInsertPoint(len(root.b)) c.bodyWantsFocus() w.seeInsertPoint()
def pickle(self, p): '''Pickle val and return the hexlified result.''' try: ua = p.v.u s = pickle.dumps(ua, protocol=1) s2 = binascii.hexlify(s) s3 = g.ue(s2, 'utf-8') return s3 except pickle.PicklingError: g.warning("ignoring non-pickleable value", ua, "in", p.h) return '' except Exception: g.error("pd.pickle: unexpected exception in", p.h) g.es_exception() return ''
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 init_language(self): """Init self.language.""" c = self.c language = g.checkUnicode(c.config.getString('enchant-language')) if language: try: ok = enchant.dict_exists(language) except Exception: ok = False if not ok: g.warning('Invalid language code for Enchant', repr(language)) g.es_print('Using "en_US" instead') g.es_print('Use @string enchant_language to specify your language') language = 'en_US' self.language = language
def init_language(self): '''Init self.language.''' c = self.c language = g.toUnicode(c.config.getString('enchant_language')) if language: try: ok = enchant.dict_exists(language) except Exception: ok = False if not ok: g.warning('Invalid language code for Enchant', repr(language)) g.es_print('Using "en_US" instead') g.es_print('Use @string enchant_language to specify your language') language = 'en_US' self.language = language
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 pickle(self, p): """Pickle val and return the hexlified result.""" try: ua = p.v.u s = pickle.dumps(ua, protocol=1) s2 = binascii.hexlify(s) s3 = g.toUnicode(s2, 'utf-8') return s3 except pickle.PicklingError: g.warning("ignoring non-pickleable value", ua, "in", p.h) return '' except Exception: g.error("pd.pickle: unexpected exception in", p.h) g.es_exception() return ''
def onIconDoubleClick(tag, keywords): v = keywords.get("p") or keywords.get( "v") # Use p for 4.2 code base, v for 4.1 code base. c = keywords.get("c") # g.trace(c) if c and v: h = v.h.strip() if h and h[0] != '@': #@+<< find path and start file >> #@+node:ekr.20040828103325.4: *3* << find path and start file >> # Set the base directory by searching for @folder directives in ancestors. thisdir = os.path.abspath(os.curdir) # remember the current dir basedir = thisdir[:] # use current dir as default. parv = v.parent() # start with parent while parv: # stop when no more parent found p = parv.h.strip() if g.match_word(p, 0, '@folder'): basedir = p[8:] # take rest of headline as pathname break # we found the closest @folder else: parv = parv.parent() # try the parent of the parent fname = os.path.join(basedir, h) # join path and filename startdir, filename = os.path.split(fname) try: os.chdir(startdir) dirfound = 1 except: g.es(startdir + ' - folder not found') dirfound = 0 if dirfound: fullpath = g.os_path_join(startdir, filename) fullpath = g.os_path_abspath(fullpath) if g.os_path_exists(filename): try: # Warning: os.startfile usually does not throw exceptions. os.startfile( filename ) # Try to open the file; it may not work for all file types. except Exception: g.es(filename + ' - file not found in ' + startdir) g.es_exception() else: g.warning('%s not found in %s' % (filename, startdir)) os.chdir(thisdir) # restore the original current dir.
def __init__(self, c): """Ctor for EnchantClass class.""" self.c = c language = g.toUnicode(c.config.getString('enchant_language')) # Set the base language if language and not enchant.dict_exists(language): g.warning('Invalid language code for Enchant', repr(language)) g.es_print('Using "en_US" instead') language = 'en_US' # Compute fn, the full path to the local dictionary. fn = c.config.getString('enchant_local_dictionary') if not fn: fn = g.os_path_finalize_join(g.app.loadDir, "..", "plugins", 'spellpyx.txt') # Fix bug https://github.com/leo-editor/leo-editor/issues/108 if not g.os_path_exists(fn): fn = g.os_path_finalize_join(g.app.homeDir, '.leo', 'spellpyx.txt') self.open_dict(fn, language)
def findDebugger(self): '''Find the debugger using settings.''' c = self.c pythonDir = g.os_path_dirname(sys.executable) debuggers = ( c.config.getString('debugger-path'), g.os_path_join(pythonDir, 'Lib', 'site-packages', 'winpdb.py'), # winpdb 1.1.2 or newer g.os_path_join(pythonDir, 'scripts', '_winpdb.py'), # oder version. ) for debugger in debuggers: if debugger: debugger = c.os_path_finalize(debugger) if g.os_path_exists(debugger): return debugger g.warning('debugger does not exist:', debugger) g.es('no debugger found.') return None
def __init__(self, c): """Ctor for EnchantClass class.""" self.c = c language = g.toUnicode(c.config.getString("enchant_language")) # Set the base language if language and not enchant.dict_exists(language): g.warning("Invalid language code for Enchant", repr(language)) g.es_print('Using "en_US" instead') language = "en_US" # Compute fn, the full path to the local dictionary. fn = c.config.getString("enchant_local_dictionary") if not fn: fn = g.os_path_finalize_join(g.app.loadDir, "..", "plugins", "spellpyx.txt") # Fix bug https://github.com/leo-editor/leo-editor/issues/108 if not g.os_path_exists(fn): fn = g.os_path_finalize_join(g.app.homeDir, ".leo", "spellpyx.txt") self.open_dict(fn, language)
def fail(self, lines, n, root): """Select the last line of the last node of root's tree.""" c = self.c w = c.frame.body.wrapper c.selectPosition(root) c.redraw() if not g.unitTesting: if len(lines) < n: g.warning('only', len(lines), 'lines') else: g.warning('line', n, 'not found') c.frame.clearStatusLine() c.frame.putStatusLine(f"goto-global-line not found: {n}") # Put the cursor on the last line of body text. w.setInsertPoint(len(root.b)) c.bodyWantsFocus() w.seeInsertPoint()
def onIconDoubleClick(tag,keywords): v = keywords.get("p") or keywords.get("v") # Use p for 4.2 code base, v for 4.1 code base. c = keywords.get("c") # g.trace(c) if c and v: h = v.h.strip() if h and h[0]!='@': #@+<< find path and start file >> #@+node:ekr.20040828103325.4: *3* << find path and start file >> # Set the base directory by searching for @folder directives in ancestors. thisdir = os.path.abspath(os.curdir) # remember the current dir basedir = thisdir[:] # use current dir as default. parv = v.parent() # start with parent while parv: # stop when no more parent found p = parv.h.strip() if g.match_word(p,0,'@folder'): basedir = p[8:] # take rest of headline as pathname break # we found the closest @folder else: parv = parv.parent() # try the parent of the parent fname = os.path.join(basedir,h) # join path and filename startdir, filename = os.path.split(fname) try: os.chdir(startdir) dirfound = 1 except: g.es(startdir+' - folder not found') dirfound = 0 if dirfound: fullpath = g.os_path_join(startdir,filename) fullpath = g.os_path_abspath(fullpath) if g.os_path_exists(filename): try: # Warning: os.startfile usually does not throw exceptions. os.startfile(filename) # Try to open the file; it may not work for all file types. except Exception: g.es(filename+' - file not found in '+startdir) g.es_exception() else: g.warning('%s not found in %s' % (filename,startdir)) os.chdir(thisdir) # restore the original current dir.
def doFileAction(filename, c): p = g.findNodeAnywhere(c,"FileActions") if p: done = False name = os.path.split(filename)[1] for p2 in p.children(): pattern = p2.h.strip() if fnmatch.fnmatchcase(name, pattern): applyFileAction(p2, filename, c) done = True break if not done: g.warning("no file action matches " + filename) return False #TL - Inform onIconDoubleClick that no action was taken return True #TL - Inform onIconDoubleClick that action was taken g.warning("no FileActions node") return False #TL - Inform onIconDoubleClick that no action was taken
def view(self): ''' Place the contents of a file in the body pane the file is either in the current headstring, or found by ascending the tree ''' # get a path object for this position currentPath = self.getCurrentPath() if currentPath.exists(): g.es('currentPath: %s' % currentPath.abspath()) if currentPath.isfile(): self.processFile(currentPath, self.current) if currentPath.isdir(): self.processDirectory(currentPath, self.current) else: g.warning('path does not exist: %s' % (str(currentPath)))
def __init__(self, c): """Ctor for EnchantClass class.""" # pylint: disable=super-init-not-called self.c = c language = g.toUnicode(c.config.getString('enchant_language')) # Set the base language if language and not enchant.dict_exists(language): g.warning('Invalid language code for Enchant', repr(language)) g.es_print('Using "en_US" instead') language = 'en_US' # Compute fn, the full path to the local dictionary. fn = c.config.getString('enchant_local_dictionary') if not fn: fn = g.os_path_finalize_join(g.app.loadDir, "..", "plugins", 'spellpyx.txt') # Fix bug https://github.com/leo-editor/leo-editor/issues/108 if not g.os_path_exists(fn): fn = g.os_path_finalize_join(g.app.homeDir, '.leo', 'spellpyx.txt') self.open_dict(fn, language)
def findDebugger(self): '''Find the debugger using settings.''' c = self.c pythonDir = g.os_path_dirname(sys.executable) debuggers = ( c.config.getString('debugger_path'), g.os_path_join(pythonDir, 'Lib', 'site-packages', 'winpdb.py'), # winpdb 1.1.2 or newer g.os_path_join(pythonDir, 'scripts', '_winpdb.py'), # oder version. ) for debugger in debuggers: if debugger: debugger = c.os_path_finalize(debugger) if g.os_path_exists(debugger): return debugger else: g.warning('debugger does not exist:', debugger) g.es('no debugger found.') return None
def insertHeadlineBefore(self, event=None): """Insert a node before the presently selected node.""" c, current, u = self, self.p, self.undoer op_name = 'Insert Node Before' if not current: return None # Can not insert before the base of a hoist. if c.hoistStack and current == c.hoistStack[-1].p: g.warning('can not insert a node before the base of a hoist') return None c.endEditing() undoData = u.beforeInsertNode(current) p = current.insertBefore() g.doHook('create-node', c=c, p=p) p.setDirty() c.setChanged() u.afterInsertNode(p, op_name, undoData) c.redrawAndEdit(p, selectAll=True) return p
def pickle (self,p): '''Pickle val and return the hexlified result.''' trace = False and g.unitTesting try: ua = p.v.u s = pickle.dumps(ua,protocol=1) s2 = binascii.hexlify(s) s3 = g.ue(s2,'utf-8') if trace: g.trace('\n', type(ua),ua,'\n',type(s),repr(s),'\n', type(s2),s2,'\n',type(s3),s3) return s3 except pickle.PicklingError: g.warning("ignoring non-pickleable value",ua,"in",p.h) return '' except Exception: g.error("pd.pickle: unexpected exception in",p.h) g.es_exception() return ''
def pickle(self, p): '''Pickle val and return the hexlified result.''' trace = False and g.unitTesting try: ua = p.v.u s = pickle.dumps(ua, protocol=1) s2 = binascii.hexlify(s) s3 = g.ue(s2, 'utf-8') if trace: g.trace('\n', type(ua), ua, '\n', type(s), repr(s), '\n', type(s2), s2, '\n', type(s3), s3) return s3 except pickle.PicklingError: g.warning("ignoring non-pickleable value", ua, "in", p.h) return '' except Exception: g.error("pd.pickle: unexpected exception in", p.h) g.es_exception() return ''
def doFileAction(filename, c): p = g.findNodeAnywhere(c,"FileActions") if p: done = False name = os.path.split(filename)[1] for p2 in p.children(): pattern = p2.h.strip() if fnmatch.fnmatchcase(name, pattern): applyFileAction(p2, filename, c) done = True break if not done: g.warning("no file action matches " + filename) return False #TL - Inform onIconDoubleClick that no action was taken else: return True #TL - Inform onIconDoubleClick that action was taken else: g.warning("no FileActions node") return False #TL - Inform onIconDoubleClick that no action was taken
def handleAtPluginNode(self, p): '''Handle @plugin nodes.''' c = self.c tag = "@plugin" h = p.h assert (g.match(h, 0, tag)) # Get the name of the module. theFile = h[len(tag):].strip() if theFile[-3:] == ".py": theFile = theFile[:-3] theFile = g.toUnicode(theFile) if not self.atPluginNodes: g.warning("disabled @plugin: %s" % (theFile)) # elif theFile in g.app.loadedPlugins: elif g.pluginIsLoaded(theFile): g.warning("plugin already loaded: %s" % (theFile)) else: theModule = g.loadOnePlugin(theFile)
def handleAtPluginNode (self,p): '''Handle @plugin nodes.''' c = self.c tag = "@plugin" h = p.h assert(g.match(h,0,tag)) # Get the name of the module. theFile = h[len(tag):].strip() if theFile[-3:] == ".py": theFile = theFile[:-3] theFile = g.toUnicode(theFile) if not self.atPluginNodes: g.warning("disabled @plugin: %s" % (theFile)) # elif theFile in g.app.loadedPlugins: elif g.pluginIsLoaded(theFile): g.warning("plugin already loaded: %s" % (theFile)) else: theModule = g.loadOnePlugin(theFile)
def start_file(c,p): # Set the base directory by searching for @folder directives in ancestors. h = p.h.strip() thisdir = os.path.abspath(os.curdir) # remember the current dir basedir = thisdir[:] # use current dir as default. parent = p.parent() # start with parent while parent: # stop when no more parent found p = parent.h.strip() if g.match_word(p,0,'@folder'): basedir = p[8:] # take rest of headline as pathname break # we found the closest @folder else: parent = parent.parent() # try the parent of the parent fname = os.path.join(basedir,h) # join path and filename startdir, filename = os.path.split(fname) try: os.chdir(startdir) dirfound = 1 except: g.es(startdir+' - folder not found') dirfound = 0 if dirfound: fullpath = g.os_path_join(startdir,filename) fullpath = g.os_path_abspath(fullpath) if g.os_path_exists(filename): try: # Warning: os.startfile usually does not throw exceptions. # pylint: disable=no-member # Previous code checks that os.startfile exists. os.startfile(filename) # This may not work for all file types. except Exception: g.es(filename+' - file not found in '+startdir) g.es_exception() else: g.warning('%s not found in %s' % (filename,startdir)) os.chdir(thisdir) # restore the original current dir.
def start_file(c,p): # Set the base directory by searching for @folder directives in ancestors. h = p.h.strip() thisdir = os.path.abspath(os.curdir) # remember the current dir basedir = thisdir[:] # use current dir as default. parent = p.parent() # start with parent while parent: # stop when no more parent found p = parent.h.strip() if g.match_word(p,0,'@folder'): basedir = p[8:] # take rest of headline as pathname break # we found the closest @folder else: parent = parent.parent() # try the parent of the parent fname = os.path.join(basedir,h) # join path and filename startdir, filename = os.path.split(fname) try: os.chdir(startdir) dirfound = 1 except Exception: g.es(startdir+' - folder not found') dirfound = 0 if dirfound: fullpath = g.os_path_join(startdir,filename) fullpath = g.os_path_abspath(fullpath) if g.os_path_exists(filename): try: # Warning: os.startfile usually does not throw exceptions. # pylint: disable=no-member # Previous code checks that os.startfile exists. os.startfile(filename) # This may not work for all file types. except Exception: g.es(filename+' - file not found in '+startdir) g.es_exception() else: g.warning('%s not found in %s' % (filename,startdir)) os.chdir(thisdir) # restore the original current dir.
def initAtAutoWrite(self, p): """Init underlining for for an @auto write.""" # User-defined underlining characters make no sense in @auto-rst. d = p.v.u.get('rst-import', {}) underlines2 = d.get('underlines2', '') # # Do *not* set a default for overlining characters. if len(underlines2) > 1: underlines2 = underlines2[0] g.warning(f"too many top-level underlines, using {underlines2}") underlines1 = d.get('underlines1', '') # # Pad underlines with default characters. default_underlines = '=+*^~"\'`-:><_' if underlines1: for ch in default_underlines[1:]: if ch not in underlines1: underlines1 = underlines1 + ch else: underlines1 = default_underlines self.at_auto_underlines = underlines2 + underlines1 self.underlines1 = underlines1 self.underlines2 = underlines2
def extractSectionNames(self, event=None): ''' Create child nodes for every section reference in the selected text. - The headline of each new child node is the section reference. - The body of each child node is empty. ''' c = self current = c.p u = c.undoer undoType = 'Extract Section Names' body = c.frame.body head, lines, tail, oldSel, oldYview = c.getBodyLines() if not lines: g.warning('No lines selected') return u.beforeChangeGroup(current, undoType) found = False for s in lines: name = findSectionName(c, s) if name: undoData = u.beforeInsertNode(current) p = createLastChildNode(c, current, name, None) u.afterInsertNode(p, undoType, undoData) found = True c.validateOutline() if found: u.afterChangeGroup(current, undoType) c.redraw(p) else: g.warning("selected text should contain section names") # Restore the selection. i, j = oldSel w = body.wrapper if w: w.setSelectionRange(i, j) w.setFocus()
def collect_data(): p = c.rootPosition() seen = set() while p: v = p.v if v.gnx in seen: p.moveToNodeAfterTree() continue seen.add(v.gnx) h = v.h if h.startswith('@transformer '): name = h.partition(' ')[2].strip() trscripts[name] = g.getScript(c, p.copy(), useSentinels=False, forcePythonSentinels=True) p.moveToNodeAfterTree() elif h.startswith('@transform-node '): name = h.partition(' ')[2].strip() name, sep, rest = name.partition('(') if not sep: g.warning('wrong syntax expected "("', nodeLink=p) p.moveToThreadNext() continue srcgnx, sep, rest = rest.partition(')') if not sep: g.warning('wrong syntax expected ")"', nodeLink=p) p.moveToThreadNext() continue srcgnx = srcgnx.strip() if not srcgnx in c.fileCommands.gnxDict: g.warning('unknown gnx', srcgnx, nodeLink=p) p.moveToThreadNext() continue trtargets[v.gnx] = (name, srcgnx) p.moveToThreadNext() else: p.moveToThreadNext()
def warning(self, s): if not g.unitTesting: g.warning('Warning:', s)
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
def onHeadChanged (self,p,undoType='Typing',s=None,e=None): '''Officially change a headline.''' trace = False and not g.unitTesting verbose = False c = self.c ; u = c.undoer if not p: if trace: g.trace('** no p') return item = self.getCurrentItem() if not item: if trace and verbose: g.trace('** no item') return if not e: e = self.getTreeEditorForItem(item) if not e: if trace and verbose: g.trace('** not editing') return s = g.u(e.text()) if g.doHook("headkey1",c=c,p=c.p,v=c.p,s=s): return self.closeEditorHelper(e,item) oldHead = p.h changed = s != oldHead if changed: # New in Leo 4.10.1. if trace: g.trace('new',repr(s),'old',repr(p.h)) #@+<< truncate s if it has multiple lines >> #@+node:ekr.20120409185504.10028: *4* << truncate s if it has multiple lines >> # Remove trailing newlines before warning of truncation. while s and s[-1] == '\n': s = s[:-1] # Warn if there are multiple lines. i = s.find('\n') if i > -1: s = s[:i] if s != oldHead: g.warning("truncating headline to one line") limit = 1000 if len(s) > limit: s = s[:limit] if s != oldHead: g.warning("truncating headline to",limit,"characters") #@-<< truncate s if it has multiple lines >> p.initHeadString(s) item.setText(0,s) # Required to avoid full redraw. undoData = u.beforeChangeNodeContents(p,oldHead=oldHead) if not c.changed: c.setChanged(True) # New in Leo 4.4.5: we must recolor the body because # the headline may contain directives. c.frame.body.recolor(p,incremental=True) dirtyVnodeList = p.setDirty() u.afterChangeNodeContents(p,undoType,undoData, dirtyVnodeList=dirtyVnodeList) g.doHook("headkey2",c=c,p=c.p,v=c.p,s=s) # This is a crucial shortcut. if g.unitTesting: return if changed: self.redraw_after_head_changed() if 0: # Don't do this: it interferes with clicks, and is not needed. if self.stayInTree: c.treeWantsFocus() else: c.bodyWantsFocus() p.v.contentModified() c.outerUpdate()
def skip_message(self, s, p): '''Print a standard message about skipping a node.''' message = '%s. skipped:' % s g.warning('%22s %s' % (message, p.h))