def gen_ref(self, line, parent, target): """ Generate the ref line. Return the headline. """ indent_ws = self.get_str_lws(line) h = self.clean_headline(line, p=None) if self.gen_refs: # Fix #441: Make sure all section refs are unique. d = self.refs_dict n = d.get(h, 0) d[h] = n + 1 if n > 0: h = '%s: %s' % (n, h) headline = g.angleBrackets(' %s ' % h) ref = '%s%s\n' % ( indent_ws, g.angleBrackets(' %s ' % h)) else: if target.ref_flag: ref = None else: ref = '%s@others\n' % indent_ws target.at_others_flag = True target.ref_flag = True # Don't generate another @others in this target. headline = h if ref: self.add_line(parent, ref) return headline
def gen_ref(self, line, parent, target): ''' Generate the ref line. Return the headline. ''' indent_ws = self.get_str_lws(line) h = self.clean_headline(line, p=None) if self.gen_refs: # Fix #441: Make sure all section refs are unique. d = self.refs_dict n = d.get(h, 0) d [h] = n + 1 if n > 0: h = '%s: %s' % (n, h) headline = g.angleBrackets(' %s ' % h) ref = '%s%s\n' % ( indent_ws, g.angleBrackets(' %s ' % h)) else: if target.ref_flag: ref = None else: ref = '%s@others\n' % indent_ws target.at_others_flag = True target.ref_flag = True # Don't generate another @others in this target. headline = h if ref: self.add_line(parent,ref) return headline
def test_section_node(self): p = self.c.p p1 = p.insertAsLastChild() p1.setHeadString('@file zzz') body = ''' %s ''' % (g.angleBrackets(' section ')) p1.setBodyString(body) p2 = p1.insertAsLastChild() head = g.angleBrackets(' section ') p2.setHeadString(head) self.assertEqual(p1.textOffset(), 0) self.assertEqual(p2.textOffset(), 3)
def __init__(self, c): '''Ctor for ParamClass.''' self.c = c self.pattern = g.angleBrackets( r'\s*\w*?\s*\(\s*([^,]*?,)\s*?(\w+)\s*\)\s*') + '$' self.regex = re.compile(self.pattern) self.addMenu() # Now gui-independent.
def __init__ (self,c): '''Ctor for ParamClass.''' self.c = c # self.pattern = g.angleBrackets(r'\w*?\(([^,]*?,)*?([^,])+?\)') + '$' self.pattern = g.angleBrackets(r'\s*\w*?\s*\(\s*([^,]*?,)\s*?(\w+)\s*\)\s*') + '$' # g.trace("self.pattern: %s" % self.pattern) self.regex = re.compile(self.pattern) self.addMenu() # Now gui-independent.
def parameterize (self,event=None): c = self.c tree = c.frame.tree body = c.frame.body w = body.wrapper current = c.currentVnode() if not self.params: self.params = self.findParameters(current) if not self.params: return sr = s = body.getAllText() sr = sr.split('\n') i = w.getInsertPoint() row,col = g.convertPythonIndexToRowCol(s,i) sr = sr[row] sr = sr[:col] sr = sr.rstrip() match = self.regex.search(sr) if not match: g.trace(self.regex) g.trace('no match',repr(sr)) return sr = sr [match.start(): match.end()] for z in range(current.numberOfChildren()): child = current.nthChild(z) if child.headString == sr: return pieces = sr.split('(',1) searchline = pieces [0] + ">>" pieces [1] = pieces [1].rstrip('>') pieces [1] = pieces [1].rstrip(')') sections = pieces [1].split(',') node = None for z in range(self.params.numberOfChildren()): child = self.params.nthChild(z) if child.matchHeadline(searchline): node = child break return bodys = node.b v = current.insertAsNthChild(0) #,tn) v.setBodyString(bodys) v.setHeadString(sr) for z in range(0,len(sections)): head = g.angleBrackets(str(z+1)+"$") bod = sections [z] v.insertAsNthChild(0) #,t) v.setBodyString(bod) v.setHeadString(head) c.redraw()
def parameterize(self, event=None): c = self.c tree = c.frame.tree body = c.frame.body w = body.bodyCtrl current = c.currentVnode() if not self.params: self.params = self.findParameters(current) if not self.params: return sr = s = body.getAllText() sr = sr.split('\n') i = w.getInsertPoint() row, col = g.convertPythonIndexToRowCol(s, i) sr = sr[row] sr = sr[:col] sr = sr.rstrip() match = self.regex.search(sr) if not match: g.trace(self.regex) g.trace('no match', repr(sr)) return sr = sr[match.start():match.end()] for z in range(current.numberOfChildren()): child = current.nthChild(z) if child.headString == sr: return pieces = sr.split('(', 1) searchline = pieces[0] + ">>" pieces[1] = pieces[1].rstrip('>') pieces[1] = pieces[1].rstrip(')') sections = pieces[1].split(',') node = None for z in range(self.params.numberOfChildren()): child = self.params.nthChild(z) if child.matchHeadline(searchline): node = child break return bodys = node.b v = current.insertAsNthChild(0) #,tn) v.setBodyString(bodys) v.setHeadString(sr) for z in range(0, len(sections)): head = g.angleBrackets(str(z + 1) + "$") bod = sections[z] v.insertAsNthChild(0) #,t) v.setBodyString(bod) v.setHeadString(head) c.redraw()
def __init__(self, c): self.c = c self.body = c.frame.body self.params = None self.pattern = g.angleBrackets(r'\w*?\(([^,]*?,)*?([^,])+?\)') + '$' self.regex = re.compile(self.pattern) self.addMenu() # Now gui-independent.
def __init__ (self,c): self.c = c self.body = c.frame.body self.params = None self.pattern = g.angleBrackets(r'\w*?\(([^,]*?,)*?([^,])+?\)') + '$' self.regex = re.compile(self.pattern) self.addMenu() # Now gui-independent.
def make_clones(self, p): """Make clones for all undefined sections in p.b.""" for s in g.splitLines(p.b): m = self.section_pat.match(s) if m: section_name = g.angleBrackets(m.group(1).strip()) section_p = self.make_clone(p, section_name) if not section_p: print(f"MISSING: {section_name:30} {p.h}") self.errors += 1
def parameterize(self, event=None): trace = False and not g.unitTesting c = self.c w = c.frame.body.wrapper # EKR: always search for parms. params = self.findParameters(c.p) if not params: return sr = s = w.getAllText() if trace: g.trace("body: %s" % sr) sr = sr.split('\n') i = w.getInsertPoint() row, col = g.convertPythonIndexToRowCol(s, i) sr = sr[row] sr = sr[:col] sr = sr.rstrip() if trace: g.trace("regex search on: %s" % sr) match = self.regex.search(sr) if not match: g.es("no match") return sr = sr[match.start():match.end()] if trace: g.trace("found sr", sr) for child in c.p.children(): if child.h == sr: return pieces = sr.split('(', 1) searchline = pieces[0] + ">>" # EKR: added rstrip(). pieces[1] = pieces[1].rstrip().rstrip('>') pieces[1] = pieces[1].rstrip().rstrip(')') sections = pieces[1].split(',') if trace: g.trace("pieces: %s\n" % (pprint.pformat(pieces)), "searchline: %s\n" % (searchline), "sections: %s\n" % (pprint.pformat(sections))) node = None for child in params.children(): if child.matchHeadline(searchline): node = child break else: if trace: g.trace('not found', searchline) return c.setCurrentPosition(node) if trace: g.trace("found: %s'\n%s" % (node.h, node.b)) for i, section in enumerate(sections): p = c.p.insertAsNthChild(i) p.b = section p.h = g.angleBrackets(str(i + 1) + "$") c.redraw()
def test_at_comment(self): c, x = self.c, self.x h = '@file /test/test_at_comment.txt' root = c.rootPosition() root.h = h # To match contents. #@+<< define contents >> #@+node:ekr.20211101090447.1: *4* << define contents >> (test_at_comment) # Be careful: no line should look like a Leo sentinel! contents = textwrap.dedent(f'''\ !!! -*- coding: utf-8 -*- !!!AT+leo-ver=5-thin !!!AT+node:{root.gnx}: * {h} !!!AT@first """Classes to read and write @file nodes.""" !!!AT@comment !!! !!!AT+LB test >> !!!AT+node:ekr.20211101090015.2: ** LB test >> print('in test section') print('done') !!!AT-LB test >> !!!AT+others !!!AT+node:ekr.20211101090015.3: ** spam def spam(): pass !!!AT+node:ekr.20211101090015.4: ** eggs def eggs(): pass !!!AT-others !!!AT@language plain !!!AT-leo ''').replace('AT', '@').replace('LB', '<<') #@-<< define contents >> x.read_into_root(contents, path='test', root=root) s = c.atFileCommands.atFileToString(root, sentinels=True) self.assertEqual(contents, s) child1 = root.firstChild() child2 = child1.next() child3 = child2.next() table = ( (child1, g.angleBrackets(' test ')), (child2, 'spam'), (child3, 'eggs'), ) for child, h in table: self.assertEqual(child.h, h)
def parameterize (self,event=None): trace = True and not g.unitTesting c = self.c w = c.frame.body.wrapper # EKR: always search for parms. params = self.findParameters(c.p) if not params: return sr = s = w.getAllText() if trace: g.trace("body: %s" % sr) sr = sr.split('\n') i = w.getInsertPoint() row,col = g.convertPythonIndexToRowCol(s,i) sr = sr[row] sr = sr[:col] sr = sr.rstrip() if trace: g.trace("regex search on: %s" % sr) match = self.regex.search(sr) if not match: g.es("no match") return sr = sr [match.start(): match.end()] if trace: g.trace("found sr",sr) for child in c.p.children(): if child.h == sr: return pieces = sr.split('(',1) searchline = pieces [0] + ">>" # EKR: added rstrip(). pieces [1] = pieces [1].rstrip().rstrip('>') pieces [1] = pieces [1].rstrip().rstrip(')') sections = pieces [1].split(',') if trace: g.trace( "pieces: %s\n" % (pprint.pformat(pieces)), "searchline: %s\n" % (searchline), "sections: %s\n" % (pprint.pformat(sections))) node = None for child in params.children(): if child.matchHeadline(searchline): node = child break else: if trace: g.trace('not found',searchline) return c.setCurrentPosition(node) if trace: g.trace("found: %s'\n%s" % (node.h,node.b)) for i in range(0,len(sections)): p = c.p.insertAsNthChild(i) p.b = sections [i] p.h = g.angleBrackets(str(i+1)+"$") c.redraw()
def test_putRefLine(self): at, p = self.at, self.c.p at.initWriteIvars(p) # Create one section definition node. name1 = g.angleBrackets('section 1') child1 = p.insertAsLastChild() child1.h = name1 child1.b = "print('test_putRefLine')\n" # Create the valid section reference. s = f" {name1}\n" # Careful: init n2 and n2. name, n1, n2 = at.findSectionName(s, 0, p) self.assertTrue(name) at.putRefLine(s, 0, n1, n2, name, p)
def test_findSectionName(self): # Test code per #2303. at, p = self.at, self.c.p at.initWriteIvars(p) ref = g.angleBrackets(' abc ') table = ( (True, f"{ref}\n"), (True, f"{ref}"), (True, f" {ref} \n"), (False, f"if {ref}:\n"), (False, f"{ref} # comment\n"), (False, f"# {ref}\n"), ) for valid, s in table: name, n1, n2 = at.findSectionName(s, 0, p) self.assertEqual(valid, bool(name), msg=repr(s))
def toggleAngleBrackets(self, event=None): '''Add or remove double angle brackets from the headline of the selected node.''' c = self; p = c.p if g.app.batchMode: c.notValidInBatchMode("Toggle Angle Brackets") return c.endEditing() s = p.h.strip() if (s[0: 2] == "<<" or s[-2:] == ">>" # Must be on separate line. ): if s[0: 2] == "<<": s = s[2:] if s[-2:] == ">>": s = s[: -2] s = s.strip() else: s = g.angleBrackets(' ' + s + ' ') p.setHeadString(s) c.redrawAndEdit(p, selectAll=True)
def toggleAngleBrackets(self, event=None): '''Add or remove double angle brackets from the headline of the selected node.''' c = self p = c.p if g.app.batchMode: c.notValidInBatchMode("Toggle Angle Brackets") return c.endEditing() s = p.h.strip() if (s[0:2] == "<<" or s[-2:] == ">>" # Must be on separate line. ): if s[0:2] == "<<": s = s[2:] if s[-2:] == ">>": s = s[:-2] s = s.strip() else: s = g.angleBrackets(' ' + s + ' ') p.setHeadString(s) c.redrawAndEdit(p, selectAll=True)
def parameterize (self,event=None): c = self.c w = c.frame.body.wrapper # EKR: always search for parms. params = self.findParameters(c.p) if not params: return sr = s = w.getAllText() sr = sr.split('\n') i = w.getInsertPoint() row,col = g.convertPythonIndexToRowCol(s,i) sr = sr[row] sr = sr[:col] sr = sr.rstrip() match = self.regex.search(sr) if not match: g.es("no match") return sr = sr [match.start(): match.end()] for child in c.p.children(): if child.h == sr: return pieces = sr.split('(',1) searchline = pieces [0] + ">>" # EKR: added rstrip(). pieces [1] = pieces [1].rstrip().rstrip('>') pieces [1] = pieces [1].rstrip().rstrip(')') sections = pieces [1].split(',') node = None for child in params.children(): if child.matchHeadline(searchline): node = child break else: return c.setCurrentPosition(node) for i, section in enumerate(sections): p = c.p.insertAsNthChild(i) p.b = section p.h = g.angleBrackets(str(i+1)+"$") c.redraw()
def toggleAngleBrackets(self, event=None): """Add or remove double angle brackets from the headline of the selected node.""" c = self p = c.p if g.app.batchMode: c.notValidInBatchMode("Toggle Angle Brackets") return c.endEditing() s = p.h.strip() # 2019/09/12: Guard against black. lt = "<<" rt = ">>" if s[0:2] == lt or s[-2:] == rt: if s[0:2] == "<<": s = s[2:] if s[-2:] == ">>": s = s[:-2] s = s.strip() else: s = g.angleBrackets(' ' + s + ' ') p.setHeadString(s) c.redrawAndEdit(p, selectAll=True)
</html>"""), #@+node:ekr.20180324065152.2: *4* Section refs vs @others UserTip( n=626, tags=[], title="Use section references sparingly", text=""" Within scripts, use section references only when code must be placed exactly. Here is a common pattern for @file nodes for python files: @first # -*- coding: utf-8 -*- %s %s """ % (g.angleBrackets('imports'), '@others')), #@+node:ekr.20180324085629.1: *4* Use section refs to avoid "one @others per node" rule UserTip( n=0, tags=['Scripting',], title='Use section refs to avoid one @others per node rule', text=""" Nodes can have at most one @others directive. You can work around this restriction as follows: %(at)sfile myFile.py %(at)sothers %(start)s organizer %(end)s where the body of the %(start)s organizer %(end)s node contains just @others.""" % {
def importCiscoConfig(c): if not c or not c.exists: return current = c.p #@+<< open file >> #@+node:edream.110203113231.673: *3* << open file >> # name = tkFileDialog.askopenfilename( # title="Import Cisco Configuration File", # filetypes=[("All files", "*")] # ) name = g.app.gui.runOpenFileDialog (c, title="Import Cisco Configuration File", filetypes=[("All files", "*")], defaultextension='ini', ) if not name: return p = current.insertAsNthChild(0) c.setHeadString(p,"cisco config: %s" % name) c.redraw() try: fh = open(name) g.es("importing: %s" % name) linelist = fh.read().splitlines() fh.close() except IOError as msg: g.es("error reading %s: %s" % (name, msg)) return #@-<< open file >> # define which additional child nodes will be created # these keywords must NOT be followed by indented blocks customBlocks = ['aaa','ip as-path','ip prefix-list','ip route', 'ip community-list','access-list','snmp-server','ntp', 'boot','service','logging'] out = [] blocks = {} children = [] lines = len(linelist) i = 0 skipToNextLine = 0 # create level-0 and level-1 children while i<(lines-1): for customLine in customBlocks: if (linelist[i].startswith(customLine) or linelist[i].startswith('no %s' % customLine)): #@+<< process custom line >> #@+node:edream.110203113231.674: *3* << process custom line >> if customLine not in blocks: blocks[customLine] = [] out.append(g.angleBrackets(customLine)) # create first-level child child = p.insertAsNthChild(0) c.setHeadString(child,g.angleBrackets(customLine)) children.append(child) blocks[customLine].append(linelist[i]) #@-<< process custom line >> skipToNextLine = 1 break if skipToNextLine: skipToNextLine = 0 else: if linelist[i+1].startswith(' '): #@+<< process indented block >> #@+node:edream.110203113231.675: *3* << process indented block >> space = linelist[i].find(' ') if space == -1: space = len(linelist[i]) key = linelist[i][:space] if key in blocks: blocks[key] = [] out.append(g.angleBrackets(key)) # create first-level child child = p.insertAsNthChild(0) c.setHeadString(child,g.angleBrackets(key)) children.append(child) value = [linelist[i]] # loop through the indented lines i = i+1 try: while linelist[i].startswith(' '): value.append(linelist[i]) i = i+1 except Exception: # EOF pass i = i-1 # restore index # now add the value to the dictionary blocks[key].append(value) #@-<< process indented block >> else: out.append(linelist[i]) i=i+1 # process last line out.append(linelist[i]) #@+<< complete outline >> #@+node:edream.110203113231.676: *3* << complete outline >> # first print the level-0 text outClean = [] prev = '' for line in out: if line=='!' and prev=='!': pass # skip repeated comment lines else: outClean.append(line) prev = line c.setBodyString(p,'\n'.join(outClean)) # scan through the created outline and add children for child in children: # extract the key from the headline. Uhm... :) key = child.h.split('<<' )[1].split('>>')[0].strip() if key in blocks: # if type(blocks[key][0]) == type(''): if g.isString(blocks[key][0]): # it's a string, no sub-children, so just print the text c.setBodyString(child,'\n'.join(blocks[key])) else: # it's a multi-level node for value in blocks[key]: # each value is a list containing the headline and then the text subchild = child.insertAsNthChild(0) c.setHeadString(subchild,value[0]) c.setBodyString(subchild,'\n'.join(value)) # child.sortChildren() else: # this should never happen g.es("Unknown key: %s" % key) # p.sortChildren() current.expand() c.redraw_now()
"""), #@+node:ekr.20180324065152.2: *4* Section refs vs @others UserTip( n=626, tags=[], title="Use section references sparingly", text="""\ Within scripts, use section references only when code must be placed exactly. Here is a common pattern for @file nodes for python files: @first # -*- coding: utf-8 -*- %s %s """ % (g.angleBrackets('imports'), '@others')), #@+node:ekr.20180324085629.1: *4* Use section refs to avoid "one @others per node" rule UserTip( n=0, tags=['Scripting',], title='Use section refs to avoid one @others per node rule', text="""\ Nodes can have at most one @others directive. You can work around this restriction as follows: %(at)sfile myFile.py %(at)sothers %(start)s organizer %(end)s where the body of the %(start)s organizer %(end)s node contains just @others.""" % {