def cleanButtonText (self,s,minimal=False): '''Clean the text following @button or @command so that it is a valid name of a minibuffer command.''' # 2011/10/16: Delete {tag} s = s.strip() i,j = s.find('{'),s.find('}') if -1 < i < j: s = s[:i] + s[j+1:] s = s.strip() if minimal: return s.lower() for tag in ('@key','@args','@color',): i = s.find(tag) if i > -1: j = s.find('@',i+1) if i < j: s = s[:i] + s[j:] else: s = s[:i] s = s.strip() if 1: # Not great, but spaces, etc. interfere with tab completion. # 2011/10/16 *do* allow '@' sign. chars = g.toUnicode(string.ascii_letters + string.digits + '@') aList = [ch if ch in chars else '-' for ch in g.toUnicode(s)] s = ''.join(aList) s = s.replace('--','-') while s.startswith('-'): s = s[1:] while s.endswith('-'): s = s[:-1] return s.lower()
def readBibTexFileIntoTree(bibFile, c): """Read BibTeX file and parse it into @bibtex tree The file is split at '\n@' and each section is divided into headline ('@string' in strings and '@entrytype key' in others) and body text (without outmost braces). These are stored in biblist, which is a list of tuples ('headline', 'body text') for each entry, all the strings in the first element. For each element of biblist, a vnode is created and headline and body text put into place.""" entrylist, biblist = [],[] strings = '' rawstring = '\n' # read 'bibFile' by lines, strip leading whitespace and store as one # string into 'rawstring'. Split 'rawstring' at '\n@' get a list of entries. for i in [o.lstrip() for o in bibFile.readlines()]: rawstring = rawstring + i for i in rawstring.split('\n@')[1:]: if i[:6] == 'string': # store all @string declarations into 'strings' strings = strings + i[7:].strip()[:-1] + '\n' else: # store all alse into 'entrylist' entrylist.append(('@' + i[:i.find(',')].replace('{',' ').replace('(', ' ').replace('\n',''), i[i.find(',')+1:].rstrip().lstrip('\n')[:-1])) if strings: biblist.append(('@string', strings)) biblist = biblist + entrylist p = c.p for i in biblist: p2 = p.insertAsLastChild() c.setHeadString(p2,g.toUnicode(i[0])) c.setBodyString(p2,g.toUnicode(i[1]))
def cleanButtonText(self, s, minimal=False): """Clean the text following @button or @command so that it is a valid name of a minibuffer command.""" # 2011/10/16: Delete {tag} s = s.strip() i, j = s.find("{"), s.find("}") if -1 < i < j: s = s[:i] + s[j + 1 :] s = s.strip() if minimal: return s.lower() for tag in ("@key", "@args", "@color"): i = s.find(tag) if i > -1: j = s.find("@", i + 1) if i < j: s = s[:i] + s[j:] else: s = s[:i] s = s.strip() if 1: # Not great, but spaces, etc. interfere with tab completion. # 2011/10/16 *do* allow '@' sign. chars = g.toUnicode(string.ascii_letters + string.digits + "@") aList = [ch if ch in chars else "-" for ch in g.toUnicode(s)] s = "".join(aList) s = s.replace("--", "-") while s.startswith("-"): s = s[1:] while s.endswith("-"): s = s[:-1] return s.lower()
def createOutlineFromCacheList(self, parent_v, aList, fileName, top=True): ''' Create outline structure from recursive aList built by makeCacheList. ''' trace = False and not g.unitTesting # and fileName.endswith('leoFileCommands.py') c = self.c if not c: g.internalError('no c') return if top: if trace: g.trace(g.shortFileName(fileName)) c.cacheListFileName = fileName if not aList: if trace: g.trace('no list') return h, b, gnx, children = aList if h is not None: v = parent_v # Does this destroy the ability to handle the rare case? v._headString = g.toUnicode(h) v._bodyString = g.toUnicode(b) for child_tuple in children: h, b, gnx, grandChildren = child_tuple if trace: g.trace('%30s %3s %s' % (gnx, len(grandChildren), h.strip())) isClone, child_v = self.fastAddLastChild(fileName, gnx, parent_v) if isClone: self.checkForChangedNodes(child_tuple, fileName, parent_v) else: self.createOutlineFromCacheList(child_v, child_tuple, fileName, top=False)
def insert_read_only_node (c,p,name): if name=="": name = g.app.gui.runOpenFileDialog( title="Open", filetypes=[("All files", "*")], ) c.setHeadString(p,"@read-only %s" % name) c.redraw() parse = urlparse.urlparse(name) try: if parse[0] == 'ftp': file = FTPurl(name) # FTP URL elif parse[0] == 'http': file = urllib.urlopen(name) # HTTP URL else: file = open(name,"r") # local file g.es("..." + name) new = file.read() file.close() except IOError as msg: # g.es("error reading %s: %s" % (name, msg)) # g.es("...not found: " + name) c.setBodyString(p,"") # Clear the body text. return True # Mark the node as changed. else: ext = os.path.splitext(parse[2])[1] if ext.lower() in ['.htm', '.html']: #@+<< convert HTML to text >> #@+node:edream.110203113231.895: *3* << convert HTML to text >> fh = StringIO() fmt = AbstractFormatter(DumbWriter(fh)) # the parser stores parsed data into fh (file-like handle) parser = HTMLParser(fmt) # send the HTML text to the parser parser.feed(new) parser.close() # now replace the old string with the parsed text new = fh.getvalue() fh.close() # finally, get the list of hyperlinks and append to the end of the text hyperlinks = parser.anchorlist numlinks = len(hyperlinks) if numlinks > 0: hyperlist = ['\n\n--Hyperlink list follows--'] for i in range(numlinks): hyperlist.append("\n[%d]: %s" % (i+1,hyperlinks[i])) # 3/26/03: was i. new = new + ''.join(hyperlist) #@-<< convert HTML to text >> previous = p.b c.setBodyString(p,new) changed = (g.toUnicode(new) != g.toUnicode(previous)) if changed and previous != "": g.es("changed: %s" % name) # A real change. return changed
def emit_message(c, parent, root, message): '''Create all the children of p.''' for part in message.walk(): part.get_content_maintype() payload = part.get_payload() subject = g.toUnicode(message.get('subject')) from_ = g.toUnicode(message.get('from')) if parent and subject.lower().startswith ('re:'): p = parent.insertAsLastChild() else: p = parent = root.insertAsLastChild() payload = g.toUnicode(payload) p.h = '%s [%s]' % (subject, from_) p.b = g.toUnicode(strip_tags(payload)) return parent
def fastAddLastChild(self, parent_v, gnxString): ''' Create new VNode as last child of the receiver. If the gnx exists already, create a clone instead of new VNode. ''' trace = False and not g.unitTesting c = self.c indices = g.app.nodeIndices gnxString = g.toUnicode(gnxString) gnxDict = c.fileCommands.gnxDict if gnxString is None: v = None else: v = gnxDict.get(gnxString) is_clone = v is not None if trace: g.trace( 'clone', '%-5s' % (is_clone), 'parent_v', parent_v, 'gnx', gnxString, 'v', repr(v)) if is_clone: pass else: if gnxString: assert g.isUnicode(gnxString) v = leoNodes.VNode(context=c, gnx=gnxString) if g.trace_gnxDict: g.trace(c.shortFileName(), gnxString, v) else: v = leoNodes.VNode(context=c) # This is not an error: it can happen with @auto nodes. # g.trace('**** no gnx for',v,parent_v) child_v = v child_v._linkAsNthChild(parent_v, parent_v.numberOfChildren()) child_v.setVisited() # Supress warning/deletion of unvisited nodes. return is_clone, child_v
def shellCommand1(self, event): k = self.c.k command = g.toUnicode(k.arg) if command: # k.commandName = 'shell-command: %s' % command # k.clearState() self.executeSubprocess(event, command)
def restore_gnx(self,d,gnx,root,unl): ''' d is an *outer* gnx dict, associating nodes *outside* the tree with positions. Let p1 be the position of the node *within* root's tree corresponding to unl. Let p2 be the position of any node *outside* root's tree with the given gnx. - Set p1.v.fileIndex = gnx. - If p2 exists, relink p1 so it is a clone of p2. ''' trace = False and not g.unitTesting p1 = self.find_position_for_relative_unl(root,unl) fn = self.c.shortFileName() if p1: p2 = d.get(gnx) old_gnx = p1.v.gnx if p2: if p1.h == p2.h and p1.b == p2.b: p1._relinkAsCloneOf(p2) # Warning: p1 *no longer exists* here. # _relinkAsClone does *not* set p1.v = p2.v. if trace: g.trace(fn,'clone:',old_gnx,'->',gnx,unl) else: g.es_print('mismatch in cloned node',p1.h) elif trace: g.trace(fn,' node:',old_gnx,'->',gnx,unl) g.app.nodeIndices.updateLastIndex(g.toUnicode(gnx)) else: if trace: g.trace('unl not found: %s' % unl)
def convert_notebook(self, nb): '''Convert the notebook to a string.''' # Do *not* catch exceptions here. s = json.dumps(nb, sort_keys=True, indent=4, separators=(',', ': ')) return g.toUnicode(s)
def readBibTexFileIntoTree(bibFile, c): '''Import a BibTeX file into a @bibtex tree.''' bibList,entries, strings = [],[],[] # bibList is a list of tuples (h,b). s = '\n'+''.join([z.lstrip() for z in bibFile.readlines()]) s = g.toUnicode(s) for line in s.split('\n@')[1:]: kind,rest = line[:6],line[7:].strip() if kind == 'string': strings.append(rest[:-1] + '\n') else: i = min(line.find(','),line.find('\n')) h = '@' + line[:i] h = h.replace('{',' ').replace('(',' ').replace('\n','') b = line[i+1:].rstrip().lstrip('\n')[:-1] entries.append((h,b),) if strings: h,b = '@string',''.join(strings) bibList.append((h,b),) bibList.extend(entries) for h,b in bibList: p = c.p.insertAsLastChild() p.b,p.h = b,h c.p.expand() c.redraw()
def readBibTexFileIntoTree(c, fn, p): '''Import a BibTeX file into a @bibtex tree.''' root = p.copy() g.es('reading:', fn) s = g.readFileIntoEncodedString(fn) # Read the encoded bytes for g.getEncodingAt() if not s or not s.strip(): return encoding = g.getEncodingAt(p, s) s = g.toUnicode(s, encoding=encoding) aList, entries, strings = [], [], [] # aList is a list of tuples (h,b). s = '\n' + ''.join([z.lstrip() for z in g.splitLines(s)]) for line in s.split('\n@')[1:]: kind, rest = line[: 6], line[7:].strip() if kind == 'string': strings.append(rest[: -1] + '\n') else: i = min(line.find(','), line.find('\n')) h = '@' + line[: i] h = h.replace('{', ' ').replace('(', ' ').replace('\n', '') b = line[i + 1:].rstrip().lstrip('\n')[: -1] entries.append((h, b),) if strings: h, b = '@string', ''.join(strings) aList.append((h, b),) aList.extend(entries) for h, b in aList: p = root.insertAsLastChild() p.b, p.h = b, h root.expand() c.redraw()
def readBibTexFileIntoTree(bibFile, c): """Import a BibTeX file into a @bibtex tree.""" bibList, entries, strings = [], [], [] # bibList is a list of tuples (h,b). s = "\n" + "".join([z.lstrip() for z in bibFile.readlines()]) s = g.toUnicode(s) for line in s.split("\n@")[1:]: kind, rest = line[:6], line[7:].strip() if kind == "string": strings.append(rest[:-1] + "\n") else: i = min(line.find(","), line.find("\n")) h = "@" + line[:i] h = h.replace("{", " ").replace("(", " ").replace("\n", "") b = line[i + 1 :].rstrip().lstrip("\n")[:-1] entries.append((h, b)) if strings: h, b = "@string", "".join(strings) bibList.append((h, b)) bibList.extend(entries) for h, b in bibList: p = c.p.insertAsLastChild() p.b, p.h = b, h c.p.expand() c.redraw()
def doMacTweaks(self, actual_ch, ch, mods): '''Replace MacOS Alt characters.''' if not g.isMac: return actual_ch, ch, mods if ch == 'Backspace': # On the Mac, the reported char can be DEL (7F) return '\b', ch, mods if len(mods) == 1 and mods[0] == 'Alt': # Patch provided by resi147. # See the thread: special characters in MacOSX, like '@'. mac_d = { '/': '\\', '5': '[', '6': ']', '7': '|', '8': '{', '9': '}', 'e': '€', 'l': '@', } if ch.lower() in mac_d: # Ignore the case. actual_ch = ch = g.toUnicode(mac_d.get(ch.lower())) mods = [] return actual_ch, ch, mods
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 get_version_from_git(short=True): trace = False import shlex import re import subprocess import sys try: is_windows = sys.platform.startswith('win') p = subprocess.Popen( shlex.split('git log -1 --date=default-local'), stdout=subprocess.PIPE, stderr=None if trace else subprocess.PIPE, # subprocess.DEVNULL is Python 3 only. shell=is_windows, ) out, err = p.communicate() out = g.toUnicode(out) if trace: g.trace(out) m = re.search('commit (.*)\n', out) commit = m.group(1).strip() if m else '' if commit and short: commit = commit[:8] m = re.search('Date: (.*)\n', out) date = m.group(1).strip() if m else '' if trace: g.trace(commit, date) return commit, date except Exception: # We are using an official release. # g.es_exception() return None, None
def update_md(self, s, keywords): '''Update markdown text in the vr pane.''' pc = self; c = pc.c; p = c.p s = s.strip().strip('"""').strip("'''").strip() isHtml = s.startswith('<') and not s.startswith('<<') if trace: g.trace('isHtml:', isHtml, p.h) # Do this regardless of whether we show the widget or not. w = pc.ensure_text_widget() assert pc.w if s: pc.show() if not got_markdown: isHtml = True s = '<pre>\n%s</pre>' % s if not isHtml: # Not html: convert to html. path = g.scanAllAtPathDirectives(c, p) or c.getNodePath(p) if not os.path.isdir(path): path = os.path.dirname(path) if os.path.isdir(path): os.chdir(path) try: msg = '' # The error message from docutils. if pc.title: s = pc.underline(pc.title) + s pc.title = None mdext = c.config.getString('view-rendered-md-extensions') or 'extra' mdext = [x.strip() for x in mdext.split(',')] s = markdown(s, mdext) s = g.toUnicode(s) except SystemMessage as sm: msg = sm.args[0] if 'SEVERE' in msg or 'FATAL' in msg: s = 'MD error:\n%s\n\n%s' % (msg, s) sb = w.verticalScrollBar() if sb: d = pc.scrollbar_pos_dict if pc.node_changed: # Set the scrollbar. pos = d.get(p.v, sb.sliderPosition()) sb.setSliderPosition(pos) else: # Save the scrollbars d[p.v] = pos = sb.sliderPosition() # 2016/03/25: honor @language md. colorizer = c.frame.body.colorizer language = colorizer.scanColorDirectives(p) if ( language in ('markdown', 'md') or pc.default_kind in ('big', 'rst', 'html', 'md') ): w.setHtml(s) if pc.default_kind == 'big': w.zoomIn(4) # Doesn't work. else: w.setPlainText(s) if sb and pos: # Restore the scrollbars sb.setSliderPosition(pos)
def update_rst(self, s, keywords): """Update rst in the vr pane.""" pc = self c = pc.c p = c.p s = s.strip().strip('"""').strip("'''").strip() isHtml = s.startswith("<") and not s.startswith("<<") if trace: g.trace("isHtml", isHtml, p.h) # Do this regardless of whether we show the widget or not. w = pc.ensure_text_widget() assert pc.w if s: pc.show() if not got_docutils: isHtml = True s = "<pre>\n%s</pre>" % s if not isHtml: # Not html: convert to html. path = g.scanAllAtPathDirectives(c, p) or c.getNodePath(p) if not os.path.isdir(path): path = os.path.dirname(path) if os.path.isdir(path): os.chdir(path) try: msg = "" # The error message from docutils. if pc.title: s = pc.underline(pc.title) + s pc.title = None # Call docutils to get the string. s = publish_string(s, writer_name="html") if trace: g.trace("after docutils", len(s)) s = g.toUnicode(s) # 2011/03/15 show = True except SystemMessage as sm: # g.trace(sm,sm.args) msg = sm.args[0] if "SEVERE" in msg or "FATAL" in msg: s = "RST error:\n%s\n\n%s" % (msg, s) sb = w.verticalScrollBar() if sb: d = pc.scrollbar_pos_dict if pc.node_changed: # Set the scrollbar. pos = d.get(p.v, sb.sliderPosition()) sb.setSliderPosition(pos) else: # Save the scrollbars d[p.v] = pos = sb.sliderPosition() if pc.default_kind in ("big", "rst", "html", "md"): w.setHtml(s) if pc.default_kind == "big": w.zoomIn(4) # Doesn't work. else: w.setPlainText(s) if sb and pos: # Restore the scrollbars sb.setSliderPosition(pos)
def __init__ (self,rc,s): ropeResources.File.__init__(self,rc,'<string-resource') for ivar in ('c','rc','s'): assert not hasattr(self,ivar),ivar self.c = rc.c self.rc = rc s = g.toUnicode(s, encoding='utf-8',reportErrors=True) self.s = g.adjustTripleString(s,self.c.tab_width)
def get_file_from_branch(self, branch, fn): '''Get the file from the hed of the given branch.''' # Get the file using git. command = 'git show %s:%s' % (branch, fn) directory = self.repo_dir lines = g.execGitCommand(command, directory) s = ''.join(lines) return g.toUnicode(s).replace('\r','')
def update_rst (self,s,keywords): trace = False and not g.unitTesting pc = self ; c = pc.c ; p = c.p s = s.strip().strip('"""').strip("'''").strip() isHtml = s.startswith('<') and not s.startswith('<<') if trace: g.trace('isHtml',isHtml,p.h) # Do this regardless of whether we show the widget or not. w = pc.ensure_text_widget() assert pc.w if s: pc.show() if not got_docutils: isHtml = True s = '<pre>\n%s</pre>' % s if not isHtml: # Not html: convert to html. path = g.scanAllAtPathDirectives(c,p) or c.getNodePath(p) if not os.path.isdir(path): path = os.path.dirname(path) if os.path.isdir(path): os.chdir(path) try: msg = '' # The error message from docutils. if pc.title: s = pc.underline(pc.title) + s pc.title = None # Call docutils to get the string. s = publish_string(s,writer_name='html') s = g.toUnicode(s) # 2011/03/15 show = True except SystemMessage as sm: # g.trace(sm,sm.args) msg = sm.args[0] if 'SEVERE' in msg or 'FATAL' in msg: s = 'RST error:\n%s\n\n%s' % (msg,s) sb = w.verticalScrollBar() if sb: d = pc.scrollbar_pos_dict if pc.node_changed: # Set the scrollbar. pos = d.get(p.v,sb.sliderPosition()) sb.setSliderPosition(pos) else: # Save the scrollbars d[p.v] = pos = sb.sliderPosition() if pc.default_kind in ('big','rst','html', 'md'): w.setHtml(s) if pc.default_kind == 'big': w.zoomIn(4) # Doesn't work. else: w.setPlainText(s) if sb and pos: # Restore the scrollbars sb.setSliderPosition(pos)
def doEnter(self, event): # set cursor to end of line to avoid line splitting trace = False and not g.unitTesting textCursor = self.textCursor() position = len(self.document().toPlainText()) textCursor.setPosition(position) self.setTextCursor(textCursor) lines = [] block = self.document().lastBlock() # #792: python_console plugin doesn't handle copy/paste properly. while block: line = g.toUnicode(block.text()) block = block.previous() done = g.match(line, 0, '>>>') if done: line = line [4:] # remove marker lines.insert(0, line.rstrip()) if done: break if trace: g.trace() g.printObj(lines) self.historyIndex = -1 if len(lines) > 1: # #792: python_console plugin doesn't handle copy/paste properly. self.append('') self.command = '\n'.join(lines).rstrip() + '\n' self.interpreter.runIt(self.command) self.command = '' self.marker() return if self.customCommands(line): return None self.haveLine = bool(line) if self.haveLine: self.history.insert(0, line) if line[-1] == ':': self.multiLine = True g.trace(self.haveLine, self.multiLine, repr(line)) if self.haveLine: if self.multiLine: self.command += line + '\n' # + command and line self.append('') else: self.command = line self.append('') self.interpreter.runIt(self.command) self.command = '' else: if self.multiLine: self.append('') self.interpreter.runIt(self.command) self.command = '' self.multiLine = False # back to single line else: # Do nothing. self.append('') self.marker() return None
def __init__(self, c, chapterController, name): self.c = c self.cc = cc = chapterController self.name = g.toUnicode(name) self.selectLockout = False # True: in chapter.select logic. # State variables: saved/restored when the chapter is unselected/selected. self.p = c.p self.root = self.findRootNode() if cc.tt: cc.tt.createTab(name)
def read_words(self, kind, fn): '''Return all the words from the dictionary file.''' words = set() try: with open(fn, 'rb') as f: s = g.toUnicode(f.read()) for line in g.splitLines(s): self.add_expanded_line(line, words) except Exception: g.es_print('can not open %s dictionary: %s' % (kind, fn)) return words
def trial_write(self): '''Return the trial write for self.root.''' at = self.c.atFileCommands # Leo 5.6: Allow apparent section refs for *all* languages. ivar = 'allow_undefined_refs' try: setattr(at, ivar, True) result = at.atAutoToString(self.root) finally: if hasattr(at, ivar): delattr(at, ivar) return g.toUnicode(result, self.encoding)
def run(self, tokens): ''' The main line of PythonTokenBeautifier class. Called by prettPrintNode & test_beautifier. ''' def oops(): g.trace('unknown kind', self.kind) self.code_list = [] self.state_stack = [] self.file_start() for token5tuple in tokens: t1, t2, t3, t4, t5 = token5tuple srow, scol = t3 self.kind = token.tok_name[t1].lower() self.val = g.toUnicode(t2) self.raw_val = g.toUnicode(t5) if srow != self.last_line_number: # Handle a previous backslash. if self.backslash_seen: self.backslash() # Start a new row. raw_val = self.raw_val.rstrip() self.backslash_seen = raw_val.endswith('\\') # g.trace('backslash_seen',self.backslash_seen) if self.paren_level > 0: s = self.raw_val.rstrip() n = g.computeLeadingWhitespaceWidth(s, self.tab_width) # This n will be one-too-many if formatting has # changed: foo ( # to: foo( self.line_indent(ws=' ' * n) # Do not set self.lws here! self.last_line_number = srow # g.trace('%10s %r'% (self.kind,self.val)) func = getattr(self, 'do_' + self.kind, oops) func() self.file_end() return ''.join([z.to_string() for z in self.code_list])
def runList(c,aList): ''' Run all commands in aList (in a separate thread). Do not change Leo's outline in this thread! ''' f = open('produce.log', 'w+') PIPE = subprocess.PIPE try: for command in aList: if command.startswith(pr): c.at_produce_command = command command = command.lstrip(pr).lstrip() f.write('produce: %s\n' % command ) # EKR: 2017/05/05 # Replace popen3 per https://docs.python.org/2.4/lib/node245.html # fi, fo, fe = os.popen3(command) p = subprocess.Popen( command, # bufsize=bufsize, # close_fds=True, # Dubious to disable this. stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True, ) fi, fo, fe = p.stdin, p.stdout, p.stderr while 1: txt = g.toUnicode(fo.read()) f.write(txt) if txt == '': break while 1: txt = g.toUnicode(fe.read()) f.write(txt) if txt == '': break fi.close() fo.close() fe.close() f.write('===============\n' ) f.seek(0) f.read() finally: f.close()
def match_prefix(self, ch, i, j, prefix, s): i = j - len(prefix) word = g.toUnicode(prefix) + g.toUnicode(ch) tag = 'tree' val = self.tree_abbrevs_d.get(word) # if val: g.trace('*****',word,'...\n\n',len(val)) if not val: val, tag = self.abbrevs.get(word, (None, None)) if val: ### if trace and verbose: g.trace(repr(word), 'val', val, 'tag', tag) # Require a word match if the abbreviation is itself a word. if ch in ' \t\n': word = word.rstrip() if word.isalnum() and word[0].isalpha(): if i == 0 or s[i - 1] in ' \t\n': return i, tag, word, val else: i -= 1 else: return i, tag, word, val else: i -= 1 return i, tag, None, None
def check(self, unused_s, parent): '''True if perfect import checks pass.''' if g.app.suppressImportChecks: g.app.suppressImportChecks = False return True c = self.c sfn = g.shortFileName(self.root.h) s1 = g.toUnicode(self.file_s, self.encoding) s2 = self.trial_write() lines1, lines2 = g.splitLines(s1), g.splitLines(s2) if 0: # An excellent trace for debugging. g.trace(c.shortFileName()) g.printObj(lines1, tag='lines1') g.printObj(lines2, tag='lines2') if self.strict: # Ignore blank lines only. # Adding nodes may add blank lines. lines1 = self.strip_blank_lines(lines1) lines2 = self.strip_blank_lines(lines2) else: # Ignore blank lines and leading whitespace. # Importing may regularize whitespace, and that's good. lines1 = self.strip_all(lines1) lines2 = self.strip_all(lines2) # Forgive trailing whitespace problems in the last line. # This is not the same as clean_last_lines. if lines1 and lines2 and lines1 != lines2: lines1[-1] = lines1[-1].rstrip()+'\n' lines2[-1] = lines2[-1].rstrip()+'\n' # self.trace_lines(lines1, lines2, parent) ok = lines1 == lines2 if not ok and not self.strict: # Issue an error only if something *other than* lws is amiss. lines1, lines2 = self.strip_lws(lines1), self.strip_lws(lines2) ok = lines1 == lines2 if ok and not g.unitTesting: print('warning: leading whitespace changed in:', self.root.h) if not ok: self.show_failure(lines1, lines2, sfn) # self.trace_lines(lines1, lines2, parent) # Ensure that the unit tests fail when they should. # Unit tests do not generate errors unless the mismatch line does not match. if g.app.unitTesting: d = g.app.unitTestDict d['result'] = ok if not ok: d['fail'] = g.callers() # Used in a unit test. c.importCommands.errors += 1 return ok
def __init__(self, c, chapterController, name): self.c = c self.cc = cc = chapterController self.name = g.toUnicode(name) self.selectLockout = False # True: in chapter.select logic. # State variables: saved/restored when the chapter is unselected/selected. if self.name == 'main': self.p = c.p or c.rootPosition() else: self.p = None # Set later. root = self.findRootNode() if cc.tt: #g.trace('(chapter) calling cc.tt.createTab(%s)' % (name)) cc.tt.createTab(name)
def sn_getenckey(dummy=None): txt,ok = QInputDialog.getText(None, 'Enter key', 'Enter key.\nData lost if key is lost.\nSee docs. for key upgrade notes.', ) if not ok: return if str(txt).startswith('v0:'): txt = QString(txt[3:]) else: txt = g.toUnicode(txt) # arbitrary kludge to convert string to 256 bits - don't change sha = SHA.new() md5 = MD5.new() sha.update(txt.encode('utf-8')) md5.update(txt.encode('utf-8')) __ENCKEY[0] = sha.digest()[:16] + md5.digest()[:16] if len(__ENCKEY[0]) != 32: raise Exception("sn_getenckey failed to build key")
def executeSubprocess(self, event, command): '''Execute a command in a separate process.''' trace = False and not g.unitTesting import sys k = self.c.k try: p = subprocess.Popen( shlex.split(command), stdout=subprocess.PIPE, stderr=None if trace else subprocess.PIPE, # subprocess.DEVNULL is Python 3 only. shell=sys.platform.startswith('win'), ) out, err = p.communicate() for line in g.splitLines(out): g.es_print(g.toUnicode(line.rstrip())) except Exception: g.es_exception() k.keyboardQuit() # Inits vim mode too. g.es('Done: %s' % command)
def add_expanded_line(self, s, words): """Add the expansion of line s to the words set.""" s = g.toUnicode(s).strip() if not s or s.startswith('#'): return # Strip off everything after / i = s.find('/') if i > -1: flags = s[i+1:].strip().lower() s = s[:i].strip() else: flags = '' if not s: return words.add(s) words.add(s.lower()) # Flags are not properly documented. # Adding plurals is good enough for now. if 's' in flags and not s.endswith('s'): words.add(s+'s') words.add(s.lower()+'s')
def convert_to_html(self, s): '''Convert s to html using docutils.''' c, p = self.c, self.c.p # Update the current path. path = g.scanAllAtPathDirectives(c, p) or c.getNodePath(p) if not os.path.isdir(path): path = os.path.dirname(path) if os.path.isdir(path): os.chdir(path) try: if self.title: s = self.underline(self.title) + s self.title = None # Call docutils to get the string. s = publish_string(s, writer_name='html') s = g.toUnicode(s) except SystemMessage as sm: msg = sm.args[0] if 'SEVERE' in msg or 'FATAL' in msg: s = 'RST error:\n%s\n\n%s' % (msg, s) return s
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.''' 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: g.loadOnePlugin(theFile)
def doMacTweaks(self, actual_ch, ch, mods): '''Replace MacOS Alt characters.''' ### g.trace(mods, repr(actual_ch), repr(ch) if g.isMac and len(mods) == 1 and mods[0] == 'Alt': # Patch provided by resi147. # See the thread: special characters in MacOSX, like '@'. mac_d = { '/': '\\', '5': '[', '6': ']', '7': '|', '8': '{', '9': '}', 'e': '€', 'l': '@', } if ch.lower() in mac_d: # Ignore the case. actual_ch = ch = g.toUnicode(mac_d.get(ch.lower())) mods = [] return actual_ch, ch, mods
def renameChapterByName(self, newName): cc, c, d, tt = self, self.c, self.chaptersDict, self.tt chapter = cc.selectedChapter oldName = chapter.name del d[oldName] d[newName] = chapter chapter.name = g.toUnicode(newName) root = cc.findChapterNode(oldName) if root: root.initHeadString('@chapter %s' % newName) if tt: try: tt.lockout = True tt.destroyTab(oldName) tt.createTab(newName) tt.setTabLabel(newName) finally: tt.lockout = False cc.selectChapterByName(newName) # Necessary. # cc.note('renamed "%s" to "%s"' % (oldName,newName)) else: cc.note('no @chapter %s' % (oldName))
def get_ch(self, event, stroke, w): '''Get the ch from the stroke.''' ch = g.toUnicode(event and event.char or '') if self.expanding: return None if w.hasSelection(): return None assert g.isStrokeOrNone(stroke), stroke if stroke in ('BackSpace', 'Delete'): return None d = {'Return': '\n', 'Tab': '\t', 'space': ' ', 'underscore': '_'} if stroke: ch = d.get(stroke.s, stroke.s) if len(ch) > 1: if (stroke.find('Ctrl+') > -1 or stroke.find('Alt+') > -1 or stroke.find('Meta+') > -1 ): ch = '' else: ch = event.char if event else '' else: ch = event.char return ch
def convert_to_markdown(self, s): '''Convert s to html using the markdown processor.''' pc = self c, p = pc.c, pc.c.p path = g.scanAllAtPathDirectives(c, p) or c.getNodePath(p) if not os.path.isdir(path): path = os.path.dirname(path) if os.path.isdir(path): os.chdir(path) try: if pc.title: s = pc.underline(pc.title) + s pc.title = None mdext = c.config.getString('view-rendered-md-extensions') or 'extra' mdext = [x.strip() for x in mdext.split(',')] s = markdown(s, mdext) s = g.toUnicode(s) except SystemMessage as sm: msg = sm.args[0] if 'SEVERE' in msg or 'FATAL' in msg: s = 'MD error:\n%s\n\n%s' % (msg, s) return s
def fastAddLastChild(self, fileName, gnxString, parent_v): ''' Create new VNode as last child of the receiver. If the gnx exists already, create a clone instead of new VNode. ''' trace = 'gnx' in g.app.debug c = self.c gnxString = g.toUnicode(gnxString) gnxDict = c.fileCommands.gnxDict if gnxString is None: v = None else: v = gnxDict.get(gnxString) is_clone = v is not None if trace: g.trace('clone', '%-5s' % (is_clone), 'parent_v', parent_v, 'gnx', gnxString, 'v', repr(v)) if is_clone: # new-read: update tempRoots. if not hasattr(v, 'tempRoots'): v.tempRoots = set() v.tempRoots.add(fileName) else: if gnxString: assert g.isUnicode(gnxString) v = leoNodes.VNode(context=c, gnx=gnxString) if 'gnx' in g.app.debug: g.trace(c.shortFileName(), gnxString, v) else: v = leoNodes.VNode(context=c) # This is not an error: it can happen with @auto nodes. # g.trace('**** no gnx for',v,parent_v) # Indicate that this node came from an external file. v.tempRoots = set() v.tempRoots.add(fileName) child_v = v child_v._linkAsNthChild(parent_v, parent_v.numberOfChildren()) child_v.setVisited() # Supress warning/deletion of unvisited nodes. return is_clone, child_v
def get_file_from_rev(self, rev, fn): """Get the file from the given rev, or the working directory if None.""" if rev: # Get the file using git. command = f"git show {rev}:{fn}" lines = g.execGitCommand(command, self.repo_dir) s = ''.join(lines) else: # Get the file from the working directory. path = g.os_path_finalize_join(self.repo_dir, fn) if g.os_path_exists(path): try: with open(path, 'rb') as f: # Was 'r' s = f.read() except Exception: g.es_print('Can not read', path) g.es_exception() s = '' else: g.trace('not found:', path) s = '' return g.toUnicode(s).replace('\r', '')
def restore_gnx(self, d, gnx, root, unl): """ d is an *outer* gnx dict, associating nodes *outside* the tree with positions. Let p1 be the position of the node *within* root's tree corresponding to unl. Let p2 be the position of any node *outside* root's tree with the given gnx. - Set p1.v.fileIndex = gnx. - If p2 exists, relink p1 so it is a clone of p2. """ p1 = self.find_position_for_relative_unl(root, unl) if not p1: return p2 = d.get(gnx) if p2: if p1.h == p2.h and p1.b == p2.b: p1._relinkAsCloneOf(p2) # Warning: p1 *no longer exists* here. # _relinkAsClone does *not* set p1.v = p2.v. else: g.es_print('mismatch in cloned node', p1.h) else: # Fix #526: A major bug: this was not set! p1.v.fileIndex = gnx g.app.nodeIndices.updateLastIndex(g.toUnicode(gnx))
def xml_for_subtree(nd): """get the xml for the subtree at nd """ lines = nd.b.split('\n') line0 = 0 while line0 < len(lines) and not lines[line0].strip(): line0 += 1 xml_dec = None if line0 < len(lines) and lines[line0].startswith('<?xml '): xml_dec = lines.pop(0) while lines and lines[0].strip() and not lines[0].startswith('<'): kv = lines.pop(0).split(': ', 1) if len(kv) == 1: NSMAP[None] = kv[0] else: NSMAP[kv[0]] = kv[1] dtd = '\n'.join(lines).strip() elements = [get_element(i) for i in nd.children()] ans = [] if xml_dec is not None: ans.append(xml_dec) if dtd: ans.append(dtd) for ele in elements: ans.append(etree.tostring(ele, pretty_print=True)) ans = [g.toUnicode(z) for z in ans] # EKR: 2011/04/29 return '\n'.join(ans)
def loadOnePlugin(self, moduleOrFileName, tag='open0', verbose=False): """ Load one plugin from a file name or module. Use extensive tracing if --trace-plugins is in effect. Using a module name allows plugins to be loaded from outside the leo/plugins directory. """ global optional_modules trace = 'plugins' in g.app.debug def report(message): if trace and not g.unitTesting: g.es_print(f"loadOnePlugin: {message}") # Define local helper functions. #@+others #@+node:ekr.20180528160855.1: *5* function:callInitFunction def callInitFunction(result): """True to call the top-level init function.""" try: # Indicate success only if init_result is True. # Careful: this may throw an exception. init_result = result.init() if init_result not in (True, False): report(f"{moduleName}.init() did not return a bool") if init_result: self.loadedModules[moduleName] = result self.loadedModulesFilesDict[moduleName] = ( g.app.config.enabledPluginsFileName) else: report(f"{moduleName}.init() returned False") result = None except Exception: report(f"exception loading plugin: {moduleName}") g.es_exception() result = None return result #@+node:ekr.20180528162604.1: *5* function:finishImport def finishImport(result): """Handle last-minute checks.""" if tag == 'unit-test-load': return result # Keep the result, but do no more. if hasattr(result, 'init'): return callInitFunction(result) # # No top-level init function. if g.unitTesting: # Do *not* load the module. self.loadedModules[moduleName] = None return None # Guess that the module was loaded correctly. report(f"fyi: no top-level init() function in {moduleName}") self.loadedModules[moduleName] = result return result #@+node:ekr.20180528160744.1: *5* function:loadOnePluginHelper def loadOnePluginHelper(moduleName): result = None try: __import__(moduleName) # Look up through sys.modules, __import__ returns toplevel package result = sys.modules[moduleName] except g.UiTypeException: report( f"plugin {moduleName} does not support {g.app.gui.guiName()} gui" ) except ImportError: report(f"error importing plugin: {moduleName}") # except ModuleNotFoundError: # report('module not found: %s' % moduleName) except SyntaxError: report(f"syntax error importing plugin: {moduleName}") except Exception: report(f"exception importing plugin: {moduleName}") g.es_exception() return result #@+node:ekr.20180528162300.1: *5* function:reportFailedImport def reportFailedImport(): """Report a failed import.""" if g.app.batchMode or g.app.inBridge or g.unitTesting: return if (self.warn_on_failure and tag == 'open0' and not g.app.gui.guiName().startswith('curses') and moduleName not in optional_modules): report(f"can not load enabled plugin: {moduleName}") #@-others if not g.app.enablePlugins: report(f"plugins disabled: {moduleOrFileName}") return None if moduleOrFileName.startswith('@'): report(f"ignoring Leo directive: {moduleOrFileName}") # Return None, not False, to keep pylint happy. # Allow Leo directives in @enabled-plugins nodes. return None moduleName = self.regularizeName(moduleOrFileName) if self.isLoaded(moduleName): module = self.loadedModules.get(moduleName) return module assert g.app.loadDir moduleName = g.toUnicode(moduleName) # # Try to load the plugin. try: self.loadingModuleNameStack.append(moduleName) result = loadOnePluginHelper(moduleName) finally: self.loadingModuleNameStack.pop() if not result: if trace: reportFailedImport() return None # # Last-minute checks. try: self.loadingModuleNameStack.append(moduleName) result = finishImport(result) finally: self.loadingModuleNameStack.pop() if result: # #1688: Plugins can update globalDirectiveList. # Recalculate g.directives_pat. g.update_directives_pat() report(f"loaded: {moduleName}") self.signonModule = result # for self.plugin_signon. return result
def cvt(s): return g.choose(g.isUnicode(s), s, g.toUnicode(s, self.encoding))
def _insert_date_node(self, parent, date, format): p = parent.insertAsLastChild() p.h = date.strftime(g.toUnicode(format)) return p
def on_idle(tag, keywords): # Tracing interfere with interprocess communication. trace = False and not g.unitTesting a = g.app if a.killed: return if trace: g.trace('open_with.py', tag, keywords) 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:EKR.20040517075715.7: *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:EKR.20040517075715.6: *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: # See how the user wants to resolve the conflict. g.es("conflict in " + g.shortFileName(path), color="red") 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.es("updated from: " + g.shortFileName(path), color="blue") 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.es("not updated from: " + g.shortFileName(path), color="blue") #@-<< update p's body text >> except Exception: if 1: g.es_exception()
def shellCommand1(self, event): k = self.c.k command = g.toUnicode(k.arg) if command: self.executeSubprocess(event, command)
def doEnter(self, event): '''Handle the <return> key.''' # # Set cursor to end of line to avoid line splitting textCursor = self.textCursor() position = len(self.document().toPlainText()) textCursor.setPosition(position) self.setTextCursor(textCursor) lines = [] block = self.document().lastBlock() # # Scan backward, looking for lines. pasteFlag = False while block: line = g.toUnicode(block.text()) line = line.replace('\t', ' ' * 4) block = block.previous() if line.startswith('>>> '): lines.insert(0, line[4:].rstrip()) break elif line.startswith('... '): lines.insert(0, line[4:].rstrip()) else: lines.insert(0, line.rstrip()) pasteFlag = True # Enter continuation mode for pasted lines. if pasteFlag and lines and lines[-1].strip(): self.multiLine = True # # Always end the input. self.append('') # # Handle special lines. last_line = lines and lines[-1] if self.customCommands(last_line): return # Handle the history and indent. if last_line.strip(): self.history.insert(0, last_line.rstrip()) self.indent = len(last_line) - len(last_line.lstrip()) if last_line.rstrip().endswith(':'): self.indent += 4 # # Just return if the last line if it is a non-blank continued line. if len(lines) > 1 and last_line.strip(): self.insert_marker() return # # Clean the lines. lines = [z for z in lines if z.strip()] # # Just add the marker if we are done. if not lines: self.insert_marker() return the_code = self.compile_lines(lines) if the_code is None: # Continuation mode. self.multiLine = True self.insert_marker() return # # End continuation mode. self.multiLine = False self.indent = 0 if the_code != 'error': self.run_code(the_code) self.insert_marker()
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
async def client_main_loop(timeout): global n_async_responses uri = f"ws://{wsHost}:{wsPort}" action_list = _get_action_list() async with websockets.connect(uri) as websocket: # pylint: disable=no-member if trace and verbose: print(f"{tag}: asyncInterval.timeout: {timeout}") # Await the startup package. json_s = g.toUnicode(await websocket.recv()) d = json.loads(json_s) if trace and verbose: print(f"startup package: {d}") n = 0 while True: n += 1 try: times_d[n] = time.perf_counter() await asyncio.sleep(timeout) # Get the next package. The last action is shut_down. try: action, param = action_list[n - 1] except IndexError: break request_package = { "id": n, "action": action, "param": param, } if trace and verbose: print(f"{tag}: send: id: {n} package: {request_package}") # Send the next request. request = json.dumps(request_package, separators=(',', ':')) await websocket.send(request) # Wait for response to request n. inner_n = 0 while True: inner_n += 1 assert inner_n < 50 # Arbitrary. try: json_s = None json_s = g.toUnicode(await websocket.recv()) d = json.loads(json_s) except Exception: if json_s is not None: g.trace('json_s', json_s) g.print_exception() break _show_response(n, d) # This loop invariant guarantees we receive messages in order. is_async = "async" in d n2 = d.get("id") assert is_async or n == n2, (action, n, d) if is_async: n_async_responses += 1 else: break except websockets.exceptions.ConnectionClosedError as e: print(f"{tag}: connection closed: {e}") break except websockets.exceptions.ConnectionClosed: print(f"{tag}: connection closed normally") break except Exception as e: print('') print(f"{tag}: internal client error {e}") print(f"{tag}: request_package: {request_package}") g.print_exception() print('') print(f"Asynchronous responses: {n_async_responses}") print(f"Unknown response times: {n_unknown_response_times}") print(f" Known response times: {n_known_response_times}") print( f" Average response_time: {(tot_response_time/n_known_response_times):3.2} sec." )
def insert_read_only_node(c, p, name): if name == "": name = g.app.gui.runOpenFileDialog( c, title="Open", filetypes=[("All files", "*")], ) c.setHeadString(p, "@read-only %s" % name) c.redraw() parse = urlparse(name) try: if parse[0] == 'ftp': f = FTPurl(name) # FTP URL elif parse[0] == 'http': f = urlopen(name) # HTTP URL else: f = open(name, "r") # local file g.es("..." + name) new = f.read() f.close() except IOError: # as msg: # g.es("error reading %s: %s" % (name, msg)) # g.es("...not found: " + name) c.setBodyString(p, "") # Clear the body text. return True # Mark the node as changed. else: ext = os.path.splitext(parse[2])[1] if ext.lower() in ['.htm', '.html']: #@+<< convert HTML to text >> #@+node:edream.110203113231.895: *3* << convert HTML to text >> fh = StringIO() fmt = AbstractFormatter(DumbWriter(fh)) # the parser stores parsed data into fh (file-like handle) ### pylint: disable=too-many-function-args parser = HTMLParser(fmt) # send the HTML text to the parser parser.feed(new) parser.close() # now replace the old string with the parsed text new = fh.getvalue() fh.close() # finally, get the list of hyperlinks and append to the end of the text ### pylint: disable=no-member hyperlinks = parser.anchorlist numlinks = len(hyperlinks) if numlinks > 0: hyperlist = ['\n\n--Hyperlink list follows--'] for i in range(numlinks): hyperlist.append("\n[%d]: %s" % (i + 1, hyperlinks[i])) # 3/26/03: was i. new = new + ''.join(hyperlist) #@-<< convert HTML to text >> previous = p.b c.setBodyString(p, new) changed = (g.toUnicode(new) != g.toUnicode(previous)) if changed and previous != "": g.es("changed: %s" % name) # A real change. return changed
def get_file(self, path): """Return the contents of the file whose path is given.""" with open(path, 'rb') as f: s = f.read() return g.toUnicode(s).replace('\r', '')
def retrieve(self, name): data = self.db[name] data = zlib.decompress(data) return g.toUnicode(data, reportErrors=True)
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 update_rst (self,s,keywords): trace = False and not g.unitTesting pc = self ; c = pc.c ; p = c.p s = s.strip().strip('"""').strip("'''").strip() isHtml = s.startswith('<') and not s.startswith('<<') if trace: g.trace('isHtml',isHtml) # Do this regardless of whether we show the widget or not. w = pc.ensure_text_widget() assert pc.w if s: pc.show() else: if pc.auto_hide: pass # needs review # pc.hide() return if got_docutils and not isHtml: # Not html: convert to html. path = g.scanAllAtPathDirectives(c,p) or c.getNodePath(p) if not os.path.isdir(path): path = os.path.dirname(path) if os.path.isdir(path): os.chdir(path) try: msg = '' # The error message from docutils. if pc.title: s = pc.underline(pc.title) + s pc.title = None s = publish_string(s,writer_name='html') s = g.toUnicode(s) # 2011/03/15 show = True except SystemMessage as sm: # g.trace(sm,sm.args) msg = sm.args[0] if 'SEVERE' in msg or 'FATAL' in msg: s = 'RST error:\n%s\n\n%s' % (msg,s) sb = w.verticalScrollBar() if sb: d = pc.scrollbar_pos_dict if pc.node_changed: # Set the scrollbar. pos = d.get(p.v,sb.sliderPosition()) sb.setSliderPosition(pos) else: # Save the scrollbars d[p.v] = pos = sb.sliderPosition() if pc.kind in ('big','rst','html'): w.setHtml(s) if pc.kind == 'big': w.zoomIn(4) # Doesn't work. else: w.setPlainText(s) if sb and pos: # Restore the scrollbars sb.setSliderPosition(pos)
def doEnter(self, event): '''Handle the <return> key.''' # # Binding for functions. interp = self.interpreter #@+others # Helper function #@+node:ekr.20190619185252.1: *5* function: compute_indent def compute_indent(line): '''Return the indentation of a line.''' indent = len(line) - len(line.lstrip()) if line.endswith(':'): indent += 4 return indent #@+node:ekr.20190619183908.1: *5* function: compile_lines def compile_lines(lines): '''Compile one or more lines, returning the compiled code.''' source = ''.join(lines) try: return code.compile_command(source) except SyntaxError: interp.showsyntaxerror() except Exception: interp.showtraceback() return None #@+node:ekr.20190619190805.1: *5* function: compile_and_run_lines def compile_and_run_lines(lines): '''Compile and run code lines. Return 1 if there are errors.''' assert lines the_code = compile_lines(lines) if the_code: return run_code(the_code) return None #@+node:ekr.20180525110907.1: *5* fucntion: run_code def run_code(the_code): '''Execute the compiled code. Return True if all went well.''' try: interp.runcode(the_code) return True except SyntaxError: interp.showsyntaxerror() except Exception: interp.showtraceback() return False #@-others # # Set cursor to end of line to avoid line splitting textCursor = self.textCursor() position = len(self.document().toPlainText()) textCursor.setPosition(position) self.setTextCursor(textCursor) lines = [] block = self.document().lastBlock() # # Scan backward, looking for lines. while block: line = g.toUnicode(block.text()) line = line.replace('\t', ' ' * 4) block = block.previous() if line.startswith('>>> '): lines.insert(0, line[4:]) break elif line.startswith('... '): lines.insert(0, line[4:]) else: lines.insert(0, line) # # Always end the log line. self.append('') # # Clean the lines and compute the last line. last_line = lines[-1].rstrip() if lines else '' lines = [z.rstrip() + '\n' for z in lines if z.strip()] if self.customCommands(last_line): return # # Handle the history and set self.indent for insert_marker. if last_line.strip(): self.history.insert(0, last_line) self.indent = compute_indent(last_line) # # Check for a continued line. if self.indent > 0 and last_line: self.insert_marker() return # # Execute lines in groups, delimited by indentation. indent, ok, exec_lines = 0, True, [] for line in lines: indent = compute_indent(line) if exec_lines else 0 if indent > 0 or not exec_lines: exec_lines.append(line) continue # End of a group. ok = compile_and_run_lines(exec_lines) exec_lines = [line] if not ok: break # Tail group. if ok and exec_lines: compile_and_run_lines(exec_lines) self.indent = 0 self.insert_marker()
def loadOnePlugin(self, moduleOrFileName, tag='open0', verbose=False): '''Load one plugin with extensive tracing if --trace-plugins is in effect.''' global optional_modules # verbose is no longer used: all traces are verbose trace = g.app.trace_plugins # This trace can be useful during unit testing. # The proper way to disable this while running unit tests # externally is to g.app.trace_plugins off. def report(message): g.es_print('loadOnePlugin: %s' % message) if not g.app.enablePlugins: if trace: report('plugins disabled: %s' % moduleOrFileName) return None if moduleOrFileName.startswith('@'): if trace: report('ignoring Leo directive: %s' % moduleOrFileName) 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: report('already loaded: %s' % moduleName) 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: __import__(moduleName) # need to look up through sys.modules, __import__ returns toplevel package result = sys.modules[moduleName] except g.UiTypeException: if trace: report('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. report('error importing plugin: %s' % moduleName) g.es_exception() result = None except SyntaxError: if trace or tag == 'open0': # Just give the warning once. report('syntax error importing plugin: %s' % moduleName) # g.es_exception() result = None except Exception: if trace: report('exception importing plugin: %s' % 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): report('%s.init() did not return a bool' % moduleName) if init_result: self.loadedModules[moduleName] = result self.loadedModulesFilesDict[ moduleName] = g.app.config.enabledPluginsFileName else: if trace: # not g.app.initing: report('%s.init() returned False' % moduleName) result = None except Exception: if trace: report('exception loading plugin: %s' % moduleName) 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: if trace: report('fyi: no top-level init() function in %s' % moduleName) self.loadedModules[moduleName] = result self.loadingModuleNameStack.pop() if g.app.batchMode or g.app.inBridge or g.unitTesting: pass elif result: if trace: report('loaded: %s' % moduleName) elif trace or self.warn_on_failure: if trace or tag == 'open0': if moduleName not in optional_modules: report('can not load enabled plugin: %s' % moduleName) return result