Example #1
0
    def embed(self): 
        """called from ns_do_context - embed layout in outline's
        @settings, an alternative to the Load/Save named layout system
        """

        # Careful: we could be unit testing.
        top_splitter = self.get_top_splitter()
        if not top_splitter: return

        c = self.c

        layout=top_splitter.get_saveable_layout()

        nd = g.findNodeAnywhere(c, "@data free-layout-layout")
        if not nd:
            settings = g.findNodeAnywhere(c, "@settings")
            if not settings:
                settings = c.rootPosition().insertAfter()
                settings.h = "@settings"
            nd = settings.insertAsNthChild(0)

        nd.h = "@data free-layout-layout"
        nd.b = json.dumps(layout, indent=4)

        nd = nd.parent()
        if not nd or nd.h != "@settings":
            g.es("WARNING: @data free-layout-layout node is not " \
                "under an active @settings node")

        c.redraw()
Example #2
0
    def openwith_rclick_cb():

        #print "Editing", path, fname
        if editor:
            cmd = '%s "%s"' % (editor, absp)
            g.es('Edit: %s' % cmd)
            subprocess.Popen(cmd, shell=True)
Example #3
0
 def init_env(self):
     '''
     Init c.abbrev_subst_env by executing the contents of the
     @data abbreviations-subst-env node.
     '''
     c = self.c
     at = c.atFileCommands
     if c.abbrev_place_start and self.enabled:
         aList = self.subst_env
         script = []
         for z in aList:
             # Compatibility with original design.
             if z.startswith('\\:'):
                 script.append(z[2:])
             else:
                 script.append(z)
         script = ''.join(script)
         # Allow Leo directives in @data abbreviations-subst-env trees.
         import leo.core.leoNodes as leoNodes
         v = leoNodes.VNode(context=c)
         root = leoNodes.Position(v)
         # Similar to g.getScript.
         script = at.writeFromString(
             root=root,
             s=script,
             forcePythonSentinels=True,
             useSentinels=False)
         script = script.replace("\r\n", "\n")
         try:
             exec(script, c.abbrev_subst_env, c.abbrev_subst_env)
         except Exception:
             g.es('Error exec\'ing @data abbreviations-subst-env')
             g.es_exception()
     else:
         c.abbrev_subst_start = False
Example #4
0
 def find(self, event=None):
     """Find the next unknown word."""
     trace = False and not g.unitTesting
     trace_lookup = False
     trace_end_body = False
     if not self.loaded:
         return
     c, n, p = self.c, 0, self.c.p
     if trace: g.trace('entry', p.h)
     sc = self.spellController
     w = c.frame.body.wrapper
     c.selectPosition(p)
     s = w.getAllText().rstrip()
     ins = w.getInsertPoint()
     # New in Leo 5.3: use regex to find words.
     last_p = p.copy()
     while True:
         for m in self.re_word.finditer(s[ins:]):
             start, word = m.start(0), m.group(0)
             if word in self.seen:
                 continue
             n += 1
             # Ignore the word if numbers precede or follow it.
             # Seems difficult to do this in the regex itself.
             k1 = ins + start - 1
             if k1 >= 0 and s[k1].isdigit():
                 continue
             k2 = ins + start + len(word)
             if k2 < len(s) and s[k2].isdigit():
                 continue
             if trace and trace_lookup: g.trace('lookup', word)
             alts = sc.processWord(word)
             if alts:
                 if trace: g.trace('%s searches' % n)
                 self.currentWord = word
                 i = ins + start
                 j = i + len(word)
                 self.showMisspelled(p)
                 self.tab.fillbox(alts, word)
                 c.invalidateFocus()
                 c.bodyWantsFocus()
                 w.setSelectionRange(i, j, insert=j)
                 w.see(j)
                 return
             else:
                 self.seen.add(word)
         # No more misspellings in p
         if trace and trace_end_body: g.trace('----- end of text', p.h)
         p.moveToThreadNext()
         if p:
             ins = 0
             s = p.b
         else:
             if trace: g.trace('%s searches' % n)
             g.es("no more misspellings")
             c.selectPosition(last_p)
             self.tab.fillbox([])
             c.invalidateFocus()
             c.bodyWantsFocus()
             return
Example #5
0
 def WriteOutputLine(lineString):
     'Writes a line of text to the output file.'
     try:
         ascFile.write("%s\n" % lineString)
     except IOError:
         g.es("Could not write to output file: %s" % ascFile.name)
         statusOfWriteOutputLine = CV.END_PROGRAM
Example #6
0
 def next_place(self, s, offset=0):
     """
     Given string s containing a placeholder like <| block |>,
     return (s2,start,end) where s2 is s without the <| and |>,
     and start, end are the positions of the beginning and end of block.
     """
     trace = False
     c = self.c
     new_pos = s.find(c.abbrev_place_start, offset)
     new_end = s.find(c.abbrev_place_end, offset)
     if (new_pos < 0 or new_end < 0) and offset:
         new_pos = s.find(c.abbrev_place_start)
         new_end = s.find(c.abbrev_place_end)
         if not (new_pos < 0 or new_end < 0):
             g.es("Found placeholder earlier in body")
     if new_pos < 0 or new_end < 0:
         if trace: g.trace('new_pos', new_pos, 'new_end', new_end)
         return s, None, None
     start = new_pos
     place_holder_delim = s[new_pos: new_end + len(c.abbrev_place_end)]
     place_holder = place_holder_delim[
         len(c.abbrev_place_start): -len(c.abbrev_place_end)]
     s2 = s[: start] + place_holder + s[start + len(place_holder_delim):]
     end = start + len(place_holder)
     if trace: g.trace(start, end, g.callers())
     return s2, start, end
Example #7
0
 def toggleAbbrevMode(self, event=None):
     '''Toggle abbreviation mode.'''
     k = self.c.k
     k.abbrevOn = not k.abbrevOn
     k.keyboardQuit()
     if not g.unitTesting and not g.app.batchMode:
         g.es('Abbreviations are ' + 'on' if k.abbrevOn else 'off')
Example #8
0
    def reclassify(self):
        """change priority codes"""

        g.es('\n Current distribution:')
        self.showDist()
        dat = {}
        for end in 'from', 'to':
            x0 = g.app.gui.runAskOkCancelStringDialog(
                self.c,'Reclassify priority' ,'%s priorities (1-7,19)' % end.upper())
            try:
                x0 = [int(i) for i in x0.replace(',',' ').split()
                      if int(i) in self.todo_priorities]
            except:
                g.es('Not understood, no action')
                return
            if not x0:
                g.es('No action')
                return
            dat[end] = x0

        if len(dat['from']) != len(dat['to']):
            g.es('Unequal list lengths, no action')
            return

        cnt = 0
        for p in self.pickleP.subtree():
            pri = int(self.getat(p.v, 'priority'))
            if pri in dat['from']:
                self.setat(p.v, 'priority', dat['to'][dat['from'].index(pri)])
                self.loadIcons(p)
                cnt += 1
        g.es('\n%d priorities reclassified, new distribution:' % cnt)
        self.showDist()
        if cnt:
            self.c.redraw_now()
Example #9
0
def jump_to_error_internal(c):
    
    import re
    regex = re.compile(r'  File "(.*)", line (\d+), in')
    
    lines = c.leo_screen.get_all(c)
    lines = lines.split('\n')
    
    skipped = 0
    for i in reversed(lines):
        match = regex.match(i)
        if match:
            if skipped == c.leo_screen.stack_frame:
                g.es("Line %s in %s"%(match.group(2), match.group(1)))
                filename = g.os_path_basename(match.group(1))
                for p in c.all_unique_positions():
                    if p.h.startswith('@') and p.h.endswith(filename):
                        c.selectPosition(p)
                        c.goToLineNumber(c).go(n=int(match.group(2)))
                        c.bodyWantsFocusNow()
                        break
                break
            skipped += 1
    else:
        g.es("%d error frames found in console content"%skipped)
Example #10
0
    def find_todo(self, p, stage = 0):
        """Recursively find the next todo"""

        # search is like XPath 'following' axis, all nodes after p in document order.
        # returning True should always propogate all the way back up to the top
        # stages: 0 - user selected start node, 1 - searching siblings, parents siblings, 2 - searching children

        if not p: return True  # not required - safety net

        # see if this node is a todo
        if stage != 0 and self.getat(p.v, 'priority') in self.todo_priorities:
            if p.getParent(): 
                self.c.selectPosition(p.getParent())
                self.c.expandNode()
            self.c.selectPosition(p)
            self.c.redraw()
            return True

        for nd in p.children():
            if self.find_todo(nd, stage = 2): return True

        if stage < 2 and p.getNext():
            if self.find_todo(p.getNext(), stage = 1): return True

        if stage < 2 and p.getParent() and p.getParent().getNext():
            if self.find_todo(p.getParent().getNext(), stage = 1): return True

        if stage == 0: g.es("None found")

        return False
Example #11
0
    def colours_menu(self,parent, p):

        c = self.c
        self.prep_pickle(p.v, 'fg')
        self.prep_pickle(p.v, 'bg')

        for var in (self.pickles['fg'].get(), self.pickles['bg'].get()):
            if var and var != '' and var != 'Other' and not self.colours.count(var):
                self.colours.insert(0, var)
                g.es("Added %s to the colour list" % (var))

        for label,var in (('Foreground',self.pickles['fg']),('Background',self.pickles['bg'])):
            menu = Tk.Menu(parent,tearoff=0,takefocus=1)
            for color in self.colours:
                menu.add_radiobutton(label=color,
                    variable=var, value=color,
                    command=self.redraw)
            parent.add_cascade(label=label,underline=0,menu=menu)

        def cleoColorsMenuCallback():
            self.remove_colours(p.v)
        def cleoColorsMenuSubtree():
            self.subtree_colours(p)

        c.add_command(parent,label='Remove Colouring', underline=0,
            command=cleoColorsMenuCallback)

        c.add_command(parent,label='Colour subtree', underline=0,
            command=cleoColorsMenuSubtree)

        def cleoAddColorsMenuCallback():
            self.add_colour()

        c.add_command(parent,label='New Colour', underline=0,
            command=cleoAddColorsMenuCallback)
Example #12
0
    def run(self, p):
        c = self.c
        q = p.b
        if not q.strip() or p.b.strip().startswith('--- '):
            q = p.h
        if p.h.strip().startswith('--'):
            q = None

        if q is None:
            g.es('No valid / uncommented query')
        else:
            self.psqlLink.send(q.strip()+'\n')
            ans = []
            maxlen=100
            for d in self.psqlReader(self.psqlLink):
                if d.strip():
                    ans.append(d)
                    if len(ans) > maxlen:
                        del ans[maxlen-10]
                        ans[maxlen-10] = '   ... skipping ...'
            n = p.insertAsNthChild(0)
            n.h = '-- ' + time.asctime()
            n.b = '\n'.join(ans)
            if p.b.strip().startswith('--- ') or not p.b.strip():
                p.b = '-'+n.h+'\n\n'+n.b
                p.contract()
            else:
                c.selectPosition(n)
            c.redraw()
Example #13
0
    def run(self, p):
        c = self.c
        q = p.b
        if not q.strip() or p.b.strip().startswith('### '):
            q = p.h
        if p.h.strip().startswith('#'):
            q = None

        if q is None:
            g.es('No valid / uncommented statement')
        else:
            path = self.getPath(c, p)
            if not path:
                path = os.path.dirname(c.fileName())
            if path:
                self.bashLink.send('cd %s\n' % path)
            self.bashLink.send(q.strip()+'\n')
            ans = []
            maxlen=100
            for d in self.bashReader(self.bashLink):
                if d.strip():
                    ans.append(d)
                    if len(ans) > maxlen:
                        del ans[maxlen-10]
                        ans[maxlen-10] = '   ... skipping ...'
            n = p.insertAsNthChild(0)
            n.h = '## ' + time.asctime()
            n.b = '\n'.join(ans)
            if p.b.strip().startswith('### ') or not p.b.strip():
                p.b = '#'+n.h+'\n\n'+n.b
                p.contract()
            else:
                c.selectPosition(n)
            c.redraw()
Example #14
0
    def startup (self):

        path = self.lib ; global dbs, libraries

        try:
            # 'r' and 'w' fail if the database doesn't exist.
            # 'c' creates it only if it doesn't exist.
            # 'n' always creates a new database.
            if dbs.has_key(path):
                self.db = dbs [path]
                self.trace('Library reusing: %s' % path)
            elif g.os_path_exists(path):
                self.db = anydbm.open(path,"rw")
                self.trace('Library reopening: %s' % path)
                dbs [path] = self.db
            else:
                self.trace('Library creating: %s' % path)
                self.db = anydbm.open(path,"c")
            self.path = path
        except Exception as err:
            g.es('Library: Exception creating database: %s' % (err,))

        ok = (self.path and self.db and
            hasattr(self.db,'isOpen') and self.db.isOpen() and hasattr(self.db,'sync'))
        if ok:
            dbs [path] = self.db
        else:
            g.es('problem starting Library: %s' % (path))
        return ok
Example #15
0
    def createAttrib(self, v, gui_parent=None):

        path,ok = QtWidgets.QInputDialog.getText(gui_parent,
            "Enter attribute path",
            "Enter path to attribute (space separated words)")

        ns = str(path).split()  # not the QString
        if not ok or not ns:
            g.es("Cancelled")
            return

        #FIXME type_ = {True: '_view', False: '_edit'}[readonly]
        type_ = '_edit'

        if '|' in ns[-1]:
            nslist = [ ns[:-1] + [i.strip()] for i in ns[-1].split('|') ]
        else:
            nslist = [ns]

        for ns in nslist:

            if type_ not in ns:
                ns.insert(-1, type_)

            self.setAttrib(v, ns, '')
Example #16
0
 def selectChapter(self, event=None):
     '''Use the minibuffer to get a chapter name, then create the chapter.'''
     cc, k = self, self.c.k
     names = cc.setAllChapterNames()
     g.es('Chapters:\n' + '\n'.join(names))
     k.setLabelBlue('Select chapter: ')
     k.get1Arg(event, handler=self.selectChapter1, tabList=names)
Example #17
0
def leo_echo_cb(out, err, code, ent):
    arg = ent['arg']
    g.es("> " + arg[0] + " " + repr(arg[1:])    )
    if out:
        g.es(out)
    if err:
        g.es_error(err)
    def label_to_subnode(self,event=None):
        """
        Convert a label of the current node to a subnode.
        """
        title = "Creating subnode"
        label_text = "Existing labels (on this node)"

        p = self.c.p
        labels = self.get_labels_dict(p)

        if labels is None:
            g.es("No labels defined for this node")
            return

        labelnames = labels.keys()
        labelnames.sort()
        root = self.c.frame.outerFrame
        widget = Pmw_combobox(root, title = title, label_text = label_text, scrolledlist_items = labelnames)
        result = widget.doit()
        if result == 'Cancel':
            return
        labelname = widget.dialog.get()
        g.es("Create subnode for label %s" % labelname)

        self.insert_node_for_label_as_child(p=p,labelname=labelname,labelcontent=labels[labelname])
Example #19
0
def cmd_PickDir(c):
    """cmd_PickDir - Show user a folder picker to create
    a new top level @path node

    :Parameters:
    - `c`: outline
    """

    p = c.p
    aList = g.get_directives_dict_list(p)
    path = c.scanAtPathDirectives(aList)
    if p.h.startswith('@'):  # see if it's a @<file> node of some sort
        nodepath = p.h.split(None, 1)[-1]
        nodepath = g.os_path_join(path, nodepath)
        if not g.os_path_isdir(nodepath):  # remove filename
            nodepath = g.os_path_dirname(nodepath)
        if g.os_path_isdir(nodepath):  # append if it's a directory
            path = nodepath

    ocwd = os.getcwd()
    try:
        os.chdir(path)
    except OSError:
        g.es("Couldn't find path %s"%path)
    dir_ = g.app.gui.runOpenDirectoryDialog("Pick a folder", "Pick a folder")
    os.chdir(ocwd)
    
    if not dir_:
        g.es("No folder selected")
        return
    
    nd = c.p.insertAfter()
    nd.h = "@path %s" % dir_
    c.redraw()
Example #20
0
    def zoom_toggle(self):
        """zoom_toggle - (Un)zoom current pane to be only expanded pane
        """

        if self.root.zoomed:
            for ns in self.top().self_and_descendants():
                if hasattr(ns, '_unzoom'):
                    # this splitter could have been added since
                    ns.setSizes(ns._unzoom)
        else:
            focused = Qt.QApplication.focusWidget()
            parents = []
            parent = focused
            while parent:
                parents.append(parent)
                parent = parent.parent()
            if not focused:
                g.es("Not zoomed, and no focus")
            for ns in self.top().self_and_descendants():
                
                ns._unzoom = ns.sizes()

                for i in range(ns.count()):
                    w = ns.widget(i)
                    if w in parents: 
                        sizes = [0] * len(ns._unzoom)
                        sizes[i] = sum(ns._unzoom)
                        ns.setSizes(sizes)
                        break
                    
        self.root.zoomed = not self.root.zoomed
    def marks_to_label(self,event=None):
        """
        Convert the existing marks to a label.
        """
        title = "show labels"

        labellist = self.collect_labels()
        root = self.c.frame.outerFrame
        widget = Pmw_combobox(root, title = title, label_text = 'Existing labels', scrolledlist_items = labellist)
        result = widget.doit()
        if result == 'Cancel':
            return
        labelname = widget.dialog.get()
        g.es("Convert the existing marks to label %s" % labelname)
        #  markedBit = self.c.rootVnode().__class__.markedBit
        for p in self.c.all_positions():
            if p.isMarked():
                # if (v.statusBits & markedBit ) != 0:
                labels_dict = self.get_labels_dict(p)
                if labels_dict is None:
                    labels_dict = {}
                # do nothing if the node already has such a label.
                if not labels_dict.has_key(labelname):
                    labels_dict[labelname] = ''
                    self.set_labels_dict(p, labels_dict)
                    p.setDirty()
Example #22
0
 def callTagHandler (self,bunch,tag,keywords):
     '''Call the event handler.'''
     trace = False and not g.unitTesting
     traceIdle = True
     handler,moduleName = bunch.fn,bunch.moduleName
     if trace and (traceIdle or tag != 'idle'):
         c = keywords.get('c')
         name = moduleName ; tag2 = 'leo.plugins.'
         if name.startswith(tag2): name = name[len(tag2):]
         g.trace('c: %s %23s : %s . %s' % (
             c and c.shortFileName() or '<no c>',
             tag,handler.__name__,name))
     # Make sure the new commander exists.
     for key in ('c','new_c'):
         c = keywords.get(key)
         if c:
             # Make sure c exists and has a frame.
             if not c.exists or not hasattr(c,'frame'):
                 # g.pr('skipping tag %s: c does not exist or does not have a frame.' % tag)
                 return None
     # Calls to registerHandler from inside the handler belong to moduleName.
     self.loadingModuleNameStack.append(moduleName)
     try:
         result = handler(tag,keywords)
     except Exception:
         g.es("hook failed: %s, %s, %s" % (tag, handler, moduleName))
         g.es_exception()
         result = None
     self.loadingModuleNameStack.pop()
     return result
Example #23
0
def styleNodeSelected( c ):
    '''Determines if a XSLT Style node has not been selected'''
    # if not stylenodes.has_key( c ):
    if c not in stylenodes:
        g.es( "No Style Node selected" )
        return False
    return True
Example #24
0
 def sn_decode(s):
     try:
         return AES.new(__ENCKEY[0]).decrypt(base64.b64decode(s)).decode('utf-8').strip()
     except UnicodeDecodeError:
         g.es("Decode failed")
         __ENCKEY[0] = None
         return None
Example #25
0
def processDocumentNode( c ):
    '''this executes the stylesheet node against the current node'''
    try:
        if not styleNodeSelected( c ): return
        proc = Processor()
        stylenode = stylenodes[ c ]
        pos = c.p
        c.selectPosition( stylenode )
        sIO = getString( c )
        mdom1 = minidom.parseString( sIO )
        sIO = str( mdom1.toxml() )
        hstring = str( stylenode.h )
        if hstring == "": hstring = "no headline"
        stylesource = InputSource.DefaultFactory.fromString( sIO, uri = hstring)
        proc.appendStylesheet( stylesource )
        c.selectPosition( pos )
        xmlnode = pos.v
        xIO = getString( c )
        mdom2 = minidom.parseString( xIO )
        xIO = str( mdom2.toxml())
        xhead = str( xmlnode.headString )
        if xhead == "": xhead = "no headline"
        xmlsource = InputSource.DefaultFactory.fromString( xIO, uri = xhead )
        result = proc.run( xmlsource )
        nhline = "xsl:transform of " + str( xmlnode.headString )
        p2 = pos.insertAfter() # tnode )
        p2.setBodyString(result)
        p2.setHeadString(nhline)
        c.redraw()

    except Exception as x:
        g.es( 'exception ' + str( x ))
    c.redraw()
Example #26
0
 def keyboard_popup(self):
     """Assign a quick move action with the current node
     as a target, to be triggered with quickmove_keyboard_action
     """
     c = self.c
     menu = QtGui.QMenu(c.frame.top)
     
     cmds = {}
     
     for name, first_last, long, short in quickMove.flavors:
         if first_last:
             todo = 'first child', 'last child', 'next sibling', 'prev sibling'
         else:
             todo = ['']
         for which in todo:
             if which:
                 which = " "+which.title()
             k = "Set as "+long+" "+short+which+' target'
             cmds[k] = {'first': which, 'type': name}
             menu.addAction(k)
             
     pos = c.frame.top.window().frameGeometry().center()
     action = menu.exec_(pos)
     if action is None:
         return
     k = str(action.text())   
     g.es(k)
     self.keyboard_target = quickMoveButton(
         self, c.p.v, cmds[k]['first'], type_=cmds[k]['type'])
Example #27
0
    def unl_to_pos(self, c2, for_p, bookmark=False):
        """"c2 may be an outline (like c) or an UNL (string)
        
        return c, p where c is an outline and p is a node to copy data to
        in that outline
        
        for_p is the p to be copied - needed to check for invalid recursive
        copy / move
        """

        if g.isString(c2):
            # c2 is an UNL indicating where to insert
            full_path = c2
            path, unl = full_path.split('#', 1)
            c2 = g.openWithFileName(path, old_c=self.c)
            self.c.bringToFront(c2=self.c)
            found, maxdepth, maxp = g.recursiveUNLFind(unl.split('-->'), c2)
            
            if found:
                
                if not bookmark and (for_p == maxp or for_p.isAncestorOf(maxp)):
                    g.es("Invalid move")
                    return None, None
                
                nd = maxp.insertAsNthChild(0)
            else:
                g.es("Could not find '%s'"%full_path)
                self.c.bringToFront(c2=self.c)
                return None, None
        else:
            # c2 is an outline, insert at top
            nd = c2.rootPosition().insertAfter()
            nd.copy().back().moveAfter(nd)

        return c2, nd
Example #28
0
 def check_blanks_and_tabs(self, lines):
     '''Check for intermixed blank & tabs.'''
     # Do a quick check for mixed leading tabs/blanks.
     fn = g.shortFileName(self.root.h)
     w = self.tab_width
     blanks = tabs = 0
     for s in g.splitLines(lines):
         lws = self.get_str_lws(s)
         blanks += lws.count(' ')
         tabs += lws.count('\t')
     # Make sure whitespace matches @tabwidth directive.
     if w < 0:
         ok = tabs == 0
         message = 'tabs found with @tabwidth %s in %s' % (w, fn)
     elif w > 0:
         ok = blanks == 0
         message = 'blanks found with @tabwidth %s in %s' % (w, fn)
     if ok:
         ok = blanks == 0 or tabs == 0
         message = 'intermixed blanks and tabs in: %s' % (fn)
     if not ok:
         if g.unitTesting:
             self.report(message)
         else:
             g.es(message)
     return ok
Example #29
0
    def permanentButton (self, event=None, v=None, type_=None, first=None):
        """make buttons on this node permanent

        NOTE: includes buttons deleted"""

        c = self.c
        if not v:
            p = c.p
            v = p.v

        qm = c.quickMove

        if 'quickMove' not in v.u or 'buttons' not in v.u['quickMove']:
            # possibly deleting old style list
            v.u['quickMove'] = {'buttons':[]}

        cnt = 0
        for mover, button in qm.buttons:
            if (mover.target == v and
                (not type_ or mover.type_ == type_) and
                (not first or mover.first == first)):
                cnt += 1
                v.u['quickMove']['buttons'].append(
                    {'first':mover.first, 'type': mover.type_})

        if cnt:
            g.es('Made buttons permanent')
        else:
            g.es("Didn't find button")
Example #30
0
    def printHandlers (self,c,moduleName=None):

        '''Print the handlers for each plugin.'''

        tabName = 'Plugins'
        c.frame.log.selectTab(tabName)

        if moduleName:
            s = 'handlers for %s...\n' % (moduleName)
        else:
            s = 'all plugin handlers...\n'
        g.es(s+'\n',tabName=tabName)

        data = []
        modules = {}
        for tag in self.handlers:
            bunches = self.handlers.get(tag)
            for bunch in bunches:
                name = bunch.moduleName
                tags = modules.get(name,[])
                tags.append(tag)
                modules[name] = tags

        n = 4
        for key in sorted(modules):
            tags = modules.get(key)
            if moduleName in (None,key):
                for tag in tags:
                    n = max(n,len(tag))
                    data.append((tag,key),)

        lines = ['%*s %s\n' % (-n,s1,s2) for (s1,s2) in data]
        g.es('',''.join(lines),tabName=tabName)
Example #31
0
    def openwith_rclick_cb():

        if editor:
            cmd = '%s "%s"' % (editor, absp)
            g.es('Edit: %s' % cmd)
            subprocess.Popen(cmd, shell=True)
Example #32
0
 def settings_find_undefined(self, event):
     g.es("Settings finder: no setting defined")
Example #33
0
 def printLastMacro(self, event=None):
     '''Print the last (unnamed) macro.'''
     if self.lastMacro:
         for event in self.lastMacro:
             g.es(repr(event.stroke))
    def importDir(self, dir, compteurglobal):
        """ La routine récursive de lecture des fichiers """

        if not g.os_path_exists(dir):
            if language == 'french':
                g.es("Ce répertoire n'existe pas: %s" + dir)
            else:
                g.es("No such Directory: %s" + dir)
            return compteurglobal

        head, tail = g.os_path_split(dir)
        c = self.c
        current = c.p
        try:
            #ici, on liste le contenu du répertoire
            body = ""
            #@+<< listdir >>
            #@+node:ekr.20050301083306.11: *4* << listdir >>
            try:
                fichiers = os.listdir(dir)
                dossiers = []
                for f in fichiers:
                    # mettre ici le code de création des noeuds
                    path = g.os_path_join(dir, f)
                    # est-ce un fichier ?
                    if g.os_path_isfile(path):
                        body += (f + "\n")
                    else:
                        # c'est alors un répertoire
                        dossiers.append(path)
                    compteurglobal += 1
            except Exception:
                if language == 'french':
                    g.es("erreur dans listage fichiers...")
                else:
                    g.es("os.listdir error...")
                g.es_exception()
            #@-<< listdir >>
            p = c.importCommands.createHeadline(current, body, tail)
            c.selectPosition(p)
            if dossiers:
                for d in dossiers:
                    compteurglobal = self.importDir(d, compteurglobal)
            c.setChanged(True)
            #sélectionne le noeud parent
            c.selectPosition(current)
        except Exception:
            if language == 'french':
                g.es("erreur d'insertion de noeud...")
            else:
                g.es("error while creating node...")
            g.es_exception()

        return compteurglobal
Example #35
0
def doNodeAction(pClicked, c):

   hClicked = pClicked.h.strip()

   #Display messages based on 'messageLevel'.  Valid values:
   #   0 = log no messages
   #   1 = log that the plugin was triggered and each matched patterns
   #   2 = log 1 & 'event passed'
   #   3 = log 1,2 & 'no match to pattern'
   #   4 = log 1,2,3, & any code debugging messages,
   #           matched pattern's 'directives', and '@file saved' settings
   messageLevel = c.config.getInt('nodeActions_message_level')

   if messageLevel >= 1:
      g.es( "nodeActions: triggered" )

   #Save @file type nodes before running script if enabled
   saveAtFile = c.config.getBool('nodeActions_save_atFile_nodes')
   if messageLevel >= 4:
      g.blue( "nA: Global nodeActions_save_atFile_nodes=",saveAtFile)
   #Find the "nodeActions" node
   pNA = g.findNodeAnywhere(c,"nodeActions")
   if not pNA:
      pNA = g.findNodeAnywhere(c,"NodeActions")

   if pNA:
      #Found "nodeActions" node
      foundPattern = False
      passEventExternal = False  #No pass to next plugin after pattern matched
      #Check entire subtree under the "nodeActions" node for pattern
      for pScript in pNA.subtree():

         #Nodes with subnodes are not tested for a match
         if pScript.hasChildren():
            continue

         #Don't trigger on double click of a nodeActions' pattern node
         if pClicked == pScript:
            continue

         pattern = pScript.h.strip()   #Pattern node's header
         if messageLevel >= 4:
            g.blue( "nA: Checking pattern '" + pattern)

         #if directives exist, parse them and set directive flags for later use
         directiveExists = re.search( " \[[V>X],?[V>X]?,?[V>X]?]$", pattern )
         if directiveExists:
            directives = directiveExists.group(0)
         else:
            directives = "[]"
         #What directives exist?
         useRegEx = re.search("X", directives) != None
         passEventInternal = re.search("V", directives) != None
         if not passEventExternal: #don't disable once enabled.
            passEventExternal = re.search(">", directives) != None
         #Remove the directives from the end of the pattern (if they exist)
         pattern = re.sub( " \[.*]$", "", pattern, 1)
         if messageLevel >= 4:
            g.blue( "nA:   Pattern='" + pattern + "' " + "(after directives removed)")

         #Keep copy of pattern without directives for message log
         patternOriginal = pattern

         #if pattern begins with "@files" and clicked node is an @file type
         #node then replace "@files" in pattern with clicked node's @file type
         patternBeginsWithAtFiles = re.search( "^@files ", pattern )
         clickedAtFileTypeNode = False #assume @file type node not clicked
         if patternBeginsWithAtFiles:
            #Check if first word in clicked header is in list of @file types
            firstWordInClickedHeader = hClicked.split()[0]
            if firstWordInClickedHeader in atFileTypes:
               clickedAtFileTypeNode = True #Tell "write @file type nodes" code
               #Replace "@files" in pattern with clicked node's @file type
               pattern = re.sub( "^@files", firstWordInClickedHeader, pattern)
               if messageLevel >= 4:
                  g.blue( "nA:   Pattern='" + pattern + "' " + "(after @files substitution)")

         #Check for pattern match to clicked node's header
         if useRegEx:
            match = re.search(pattern, hClicked)
         else:
            match = fnmatch.fnmatchcase(hClicked, pattern)
         if match:
            if messageLevel >= 1:
               g.blue( "nA: Matched pattern '" + patternOriginal + "'")
            if messageLevel >= 4:
               g.blue( "nA:   Directives: X=",useRegEx, "V=",passEventInternal,
                    ">=",passEventExternal,)
            #if @file type node, save node to disk (if configured)
            if clickedAtFileTypeNode:
               if saveAtFile:
                  #Problem - No way found to just save clicked node, saving all
                  c.fileCommands.writeAtFileNodes()
                  c.requestRedrawFlag = True
                  c.redraw()
                  if messageLevel >= 3:
                     g.blue( "nA:   Saved '" + hClicked + "'")
            #Run the script
            applyNodeAction(pScript, pClicked, c)
            #Indicate that at least one pattern was matched
            foundPattern = True
            #Don't trigger more patterns unless enabled in patterns' headline
            if passEventInternal == False:
               break
         else:
            if messageLevel >= 3:
               g.blue("nA: Did not match '" + patternOriginal + "'")

      #Finished checking headline against patterns
      if not foundPattern:
         #no match to any pattern, always pass event to next plugin
         if messageLevel >= 1:
            g.blue("nA: No patterns matched to """ + hClicked + '"')
         return False #TL - Inform onIconDoubleClick that no action was taken
      elif passEventExternal == True:
         #last matched pattern has directive to pass event to next plugin
         if messageLevel >= 2:
            g.blue("nA: Event passed to next plugin")
         return False #TL - Inform onIconDoubleClick to pass double-click event
      else:
         #last matched pattern did not have directive to pass event to plugin
         if messageLevel >= 2:
            g.blue("nA: Event not passed to next plugin")
         return True #TL - Inform onIconDoubleClick to not pass double-click
   else:
      #nodeActions plugin enabled without a 'nodeActions' node
      if messageLevel >= 4:
         g.blue("nA: The ""nodeActions"" node does not exist")
      return False #TL - Inform onIconDoubleClick that no action was taken
Example #36
0
    def showMenu(self, tag, k):

        # deprecated

        g.app.gui.killPopupMenu()

        if k['c'] != self.c: return  # not our problem

        p = k['p']
        self.c.selectPosition(p)
        v = p.v

        c = self.c

        # Create the menu.
        menu = Tk.Menu(None, tearoff=0, takefocus=0)

        commands = [
            (True, 'Mark as link source', self.markSrc),
            (True, 'Mark as link dest.', self.markDst),
            (True, 'Link to source', self.linkSrc),
            (True, 'Link to dest.', self.linkDst),
            (True, 'Undirected link', self.linkUnd),
            (True, 'Rescan links', self.loadLinksInt),
        ]

        if hasattr(v, 'unknownAttributes') and '_bklnk' in v.unknownAttributes:
            i = 0
            links = v.unknownAttributes['_bklnk']['links']
            dests = []
            while i < len(links):
                linkType, other = links[i]
                otherV = self.vnode[other]
                otherP = self.vnodePosition(otherV)
                if not self.c.positionExists(otherP):
                    g.es('Deleting lost link')
                    del links[i]
                else:
                    i += 1
                    dests.append((linkType, otherP))
            if dests:
                smenu = Tk.Menu(menu, tearoff=0, takefocus=1)
                for i in dests:

                    def goThere(where=i[1]):
                        c.selectPosition(where)

                    c.add_command(menu,
                                  label={
                                      'S': '->',
                                      'D': '<-',
                                      'U': '--'
                                  }[i[0]] + i[1].h,
                                  underline=0,
                                  command=goThere)

                    def delLink(on=v,
                                to=i[1].v.unknownAttributes['_bklnk']['id'],
                                type_=i[0]):
                        self.deleteLink(on, to, type_)

                    c.add_command(smenu,
                                  label={
                                      'S': '->',
                                      'D': '<-',
                                      'U': '--'
                                  }[i[0]] + i[1].h,
                                  underline=0,
                                  command=delLink)
                menu.add_cascade(label='Delete link', menu=smenu, underline=1)
                menu.add_separator()

        for command in commands:
            available, text, com = command
            if not available:
                continue
            c.add_command(menu, label=text, underline=0, command=com)

        # Show the menu.
        event = k['event']
        g.app.gui.postPopupMenu(self.c, menu, event.x_root, event.y_root)

        return None  # 'break' # EKR: Prevent other right clicks.
Example #37
0
    def create_rclick_cb():

        os.makedirs(absp)
        g.es("Created " + absp)
 def ns_do_context(self, id_, splitter, index):
     if id_.startswith('_fl_embed_layout'):
         self.embed()
         return True
     if id_.startswith('_fl_restore_default'):
         self.get_top_splitter().load_layout({
             'content': [{
                 'content':
                 ['_leo_pane:outlineFrame', '_leo_pane:logFrame'],
                 'orientation':
                 1,
                 'sizes': [509, 275]
             }, '_leo_pane:bodyFrame'],
             'orientation':
             2,
             'sizes': [216, 216]
         })
     if id_.startswith('_fl_help'):
         self.c.putHelpFor(__doc__)
         # g.handleUrl("http://leoeditor.com/")
         return True
     if id_ == '_fl_save_layout':
         if self.c.config.getData("free-layout-layout"):
             g.es(
                 "WARNING: embedded layout in @settings/@data free-layout-layout "
                 "will override saved layout")
         layout = self.get_top_splitter().get_saveable_layout()
         name = g.app.gui.runAskOkCancelStringDialog(
             self.c,
             title="Save layout",
             message="Name for layout?",
         )
         if name:
             self.c.db['_ns_layout'] = name
             d = g.app.db.get('ns_layouts', {})
             d[name] = layout
             # make sure g.app.db's __set_item__ is hit so it knows to save
             g.app.db['ns_layouts'] = d
         return True
     if id_.startswith('_fl_load_layout:'):
         if self.c.config.getData("free-layout-layout"):
             g.es(
                 "WARNING: embedded layout in @settings/@data free-layout-layout "
                 "will override saved layout")
         name = id_.split(':', 1)[1]
         self.c.db['_ns_layout'] = name
         layout = g.app.db['ns_layouts'][name]
         self.get_top_splitter().load_layout(layout)
         return True
     if id_.startswith('_fl_delete_layout:'):
         name = id_.split(':', 1)[1]
         if ('yes' == g.app.gui.runAskYesNoCancelDialog(
                 self.c, "Really delete Layout?",
                 "Really permanently delete the layout '%s'?" % name)):
             d = g.app.db.get('ns_layouts', {})
             del d[name]
             # make sure g.app.db's __set_item__ is hit so it knows to save
             g.app.db['ns_layouts'] = d
             if '_ns_layout' in self.c.db:
                 del self.c.db['_ns_layout']
         return True
     if id_.startswith('_fl_forget_layout:'):
         if '_ns_layout' in self.c.db:
             del self.c.db['_ns_layout']
         return True
     if id_.startswith('_fl_restore_layout:'):
         self.loadLayouts("reload", {'c': self.c}, reloading=True)
         return True
     return False
Example #39
0
def cmd_ShowCurrentPath(event):
    """Just show the path to the current file/directory node in the log pane."""
    c = event.get('c')
    g.es(getPath(c, c.p))
Example #40
0
 def onActivated(n, *args, **keys):
     color = color_list[n]
     sheet = template % (color, color)
     box.setStyleSheet(sheet)
     g.es("copied to clipboard:", color)
     QtWidgets.QApplication.clipboard().setText(color)
Example #41
0
    def moveCurrentNodeToTarget(self, checked=False):

        '''Move the current position to the last child of self.target.'''

        c = self.c
        p = c.p

        vnodes = [i.v for i in c.getSelectedPositions()]

        needs_undo = self.type_ != "jump"

        if needs_undo:
            bunch = c.undoer.beforeMoveNode(p)

        for v in vnodes:

            p2 = c.vnode2position(self.target)
            p = c.vnode2position(v)

            if not c.positionExists(p2):
                g.error('Target no longer exists: %s' % self.targetHeadString)
                return

            if self.type_ in ('clone', 'move'):  # all others are always valid?
                if p.v == p2.v or not self.checkMove(p,p2):
                    g.error('Invalid move: %s' % (self.targetHeadString))
                    return
            if p2.isAncestorOf(p):  # not for sibling moves
                p2.expand()
            nxt = p.visNext(c) or p.visBack(c)
            nxt = nxt.v
            # store a VNode instead of position as positions are too easily lost

            if self.type_ != 'jump':
                p.setDirty()  # before move to dirty current parent
                p2.setDirty()
                c.setChanged(changedFlag=True)

            if self.type_ == 'clone':
                p = p.clone()

            if self.type_ in ('move', 'clone'):
                if self.which == 'first child':
                    p.moveToFirstChildOf(p2)
                elif self.which == 'last child':
                    p.moveToLastChildOf(p2)
                elif self.which in ('next sibling', 'prev sibling'):
                    if not p2.parent():
                        raise Exception("Not implemented for top-level nodes") #FIXME
                    if self.which == 'next sibling':
                        p.moveToNthChildOf(p2.parent(), p2._childIndex)
                    elif self.which == 'prev sibling':
                        p.moveToNthChildOf(p2.parent(), p2._childIndex-1)
                else:
                    raise Exception("Unknown move type "+self.which)

            elif self.type_ == 'bkmk':
                unl = self.computeUNL(p)  # before tree changes
                if self.which == 'first child':
                    nd = p2.insertAsNthChild(0)
                elif self.which == 'last child':
                    nd = p2.insertAsLastChild()
                elif self.which == 'next sibling':
                    nd = p2.insertAfter()
                elif self.which == 'prev sibling':
                    nd = p2.insertBefore()
                else:
                    raise Exception("Unknown move type "+self.which)
                h = p.anyAtFileNodeName() or p.h
                while h and h[0] == '@':
                    h = h[1:]
                nd.h = h
                nd.b = unl

            elif self.type_ == 'copy':

                if self.which == 'first child':
                    nd = p2.insertAsNthChild(0)
                    quickMove.copy_recursively(p, nd)
                    # unlike p.copyTreeFromSelfTo, deepcopys p.v.u
                elif self.which == 'last child':
                    nd = p2.insertAsLastChild()
                    quickMove.copy_recursively(p, nd)
                elif self.which == 'next sibling':
                    nd = p2.insertAfter()
                    quickMove.copy_recursively(p, nd)
                elif self.which == 'prev sibling':
                    nd = p2.insertBefore()
                    quickMove.copy_recursively(p, nd)
                else:
                    raise Exception("Unknown move type "+self.which)

            elif self.type_ in ('linkTo', 'linkFrom'):
                blc = getattr(c, 'backlinkController', None)
                if blc is None:
                    g.es("Linking requires backlink.py plugin")
                    return
                if self.type_ == 'linkTo':
                    blc.vlink(p.v, p2.v)
                else:
                    blc.vlink(p2.v, p.v)

            if self.type_ in ('bkmk', 'clone', 'copy', 'move'):
                nxt = c.vnode2position(nxt)
            elif self.type_ == 'jump':
                nxt = c.vnode2position(self.target)
            else:
                nxt = None  # linkTo / linkFrom don't move

            if nxt is not None and c.positionExists(nxt):
                c.selectPosition(nxt)

        if needs_undo:
            c.undoer.afterMoveNode(p,'Quick Move', bunch)
            c.setChanged(True)

        c.redraw()
Example #42
0
def cmd_ToggleAutoLoad(event):
    """cmd_ToggleAutoLoad - toggle autoloading behavior
    """
    c = event.get('c')
    c.__active_path['do_autoload'] = not c.__active_path['do_autoload']
    g.es("Autoload: %s" % c.__active_path['do_autoload'])
Example #43
0
 def renameBuffer(self, event):
     """Rename a buffer, i.e., change a node's headline."""
     g.es('rename-buffer not ready yet')
     if 0:
         self.c.k.setLabelBlue('Rename buffer from: ')
         self.getBufferName(event, self.renameBufferFinisher1)
Example #44
0
def openDir(c, parent, d):
    """
    Expand / refresh an existing folder

    Note: With the addition of per folder inclusion/exclusion a check is done
    against both the current list of nodes and against the files/folders as
    they exist on the system. This check must be done in both places to keep
    the node list in sync with the file system while respecting the inc/exc
    lists - John Lunzer
    """

    # compare folder content to children
    try:
        path, dirs, files = next(os.walk(d))
    except StopIteration:
        # directory deleted?
        c.setHeadString(parent, '*' + parent.h.strip('*') + '*')
        return

    # parent.expand()  # why?

    oldlist = set()
    toRemove = set()
    newlist = []

    bodySplit = parent.b.splitlines()

    excdirs = False
    excfiles = False
    regEx = False
    if re.search('^excdirs', parent.b, flags=re.MULTILINE):
        excdirs = True
    if re.search('^excfiles', parent.b, flags=re.MULTILINE):
        excfiles = True
    if re.search('^re', parent.b, flags=re.MULTILINE):
        regEx = True

    inc = [
        line.replace('inc=', '') for line in bodySplit
        if line.startswith('inc=')
    ]
    exc = [
        line.replace('exc=', '') for line in bodySplit
        if line.startswith('exc=')
    ]

    #flatten lists if using comma separations
    inc = [item for line in inc for item in line.strip(' ').split(',')]
    exc = [item for line in exc for item in line.strip(' ').split(',')]

    # get children info
    for p in flattenOrganizers(parent):
        entry = p.h.strip('/*')
        if entry.startswith('@'):  # remove only the @part
            directive = entry.split(None, 1)
            if len(directive) > 1:
                entry = entry[len(directive[0]):].strip()
        #find existing inc/exc nodes to remove
        #using p.h allows for example exc=/ to remove all directories
        if not checkIncExc(p.h,inc,exc, regEx) or \
               (excdirs and entry in dirs) or \
               (excfiles and entry in files):
            toRemove.add(p.h)  #must not strip '/', so nodes can be removed
        else:
            oldlist.add(entry)

    # remove existing found inc/exc nodes
    for headline in toRemove:
        found = g.findNodeInChildren(c, parent, headline)
        if found:
            found.doDelete()

    # dirs trimmed by toRemove to remove redundant checks
    for d2 in set(dirs) - set([h.strip('/') for h in toRemove]):
        if d2 in oldlist:
            oldlist.discard(d2)
        else:
            if checkIncExc(d2, [i.strip('/') for i in inc],
                           [e.strip('/') for e in exc], regEx) and not excdirs:
                newlist.append('/' + d2 + '/')

    # files trimmed by toRemove, retains original functionality of plugin
    for f in set(files) - toRemove:
        if f in oldlist:
            oldlist.discard(f)
        else:
            if checkIncExc(f, inc, exc, regEx) and not excfiles:
                newlist.append(f)

    # insert newlist
    newlist.sort()
    ignored = 0
    newlist.reverse()  # un-reversed by the following loop
    for name in newlist:
        if inReList(name, c.__active_path['ignore']):
            ignored += 1
            continue

        p = parent.insertAsNthChild(0)
        c.setChanged(True)
        c.setHeadString(p, name)
        if name.startswith('/'):
            # sufficient test of dirness as we created newlist
            c.setBodyString(p, '@path ' + name.strip('/'))
        elif (c.__active_path['do_autoload']
              and inReList(name, c.__active_path['autoload'])):
            openFile(c, p, os.path.join(d, p.h), autoload=True)
        elif (c.__active_path['do_autoload']
              and c.__active_path['load_docstring']
              and name.lower().endswith(".py")):
            # do_autoload suppresses doc string loading because turning
            # autoload off is supposed to address situations where autoloading
            # causes problems, so don't still do some form of autoloading
            p.b = c.__active_path['DS_SENTINEL'] + "\n\n" + loadDocstring(
                os.path.join(d, p.h))
        p.setMarked()
        p.contract()

    if ignored:
        g.es('Ignored %d files in directory' % ignored)

    # warn / mark for orphan oldlist
    for p in flattenOrganizers(parent):
        h = p.h.strip('/*')  # strip / and *
        if (h not in oldlist or
            (p.hasChildren() and not isDirNode(p))):  # clears bogus '*' marks
            nh = p.h.strip('*')  # strip only *
        else:
            nh = '*' + p.h.strip('*') + '*'
            if isDirNode(p):
                for orphan in p.subtree():
                    c.setHeadString(orphan, '*' + orphan.h.strip('*') + '*')
        if p.h != nh:  # don't dirty node unless we must
            c.setHeadString(p, nh)

    c.selectPosition(parent)
Example #45
0
def styleNodeSelected(c):
    '''Determines if a XSLT Style node has not been selected'''
    if not stylenodes.has_key(c):
        g.es("No Style Node selected")
        return False
    return True
Example #46
0
    def addButton (self, which, type_="move", v=None, parent=None):
        '''Add a button that creates a target for future moves.'''
        c = self.c
        p = c.p
        if v is None:
            v = p.v
        sc = scriptingController(c)
        mb = quickMoveButton(self,v,which,type_=type_)
        txt=self.txts[type_]

        if parent:  # find parent button
            for i in self.buttons:
                if i[0].target.gnx == parent:
                    parent = i[1]
                    break
            else:
                g.es('Move to button parent not found, placing at top level')
                parent = None

        header = v.anyAtFileNodeName() or v.h  # drop @auto etc.

        text = txt + ":" + header if txt else header
        # createButton truncates text.

        if parent and g.app.gui.guiName() == "qt":
            pb = parent.button
            rc = QtWidgets.QAction(text, pb)
            rc.triggered.connect(mb.moveCurrentNodeToTarget)
            pb.insertAction(pb.actions()[0], rc)  # insert at top
            b = None
            mb.has_parent = True
            ### New code.
            t = c.config.getString('mod_scripting_subtext') or ''
            t2 = g.u(pb.text())
            if not t.endswith(t):
                pb.setText(t2+t)
            # else:
                # t = QtCore.QString(c.config.getString('mod_scripting_subtext') or '')
                # if not g.u(pb.text()).endswith(g.u(t)):
                    # pb.setText(pb.text()+t)
        else:
            b = sc.createIconButton(
                args=None,
                text=text,
                command = mb.moveCurrentNodeToTarget,
                statusLine = '%s current node to %s child of %s' % (
                    type_.title(), which, v.h),
                kind = "quick-move"
            )
            if g.app.gui.guiName() == "qt":

                def cb_goto_target(checked, c=c, v=v):
                    p = c.vnode2position(v)
                    c.selectPosition(p)
                    c.redraw()

                def cb_set_parent(checked, c=c, v=v, first=which, type_=type_):
                    c.quickMove.set_parent(v, first, type_)

                def cb_permanent(checked, c=c, v=v, type_=type_, first=which):
                    c.quickMove.permanentButton(v=v, type_=type_, first=first)

                # def cb_clear(event=None, c=c, v=v):
                #     c.quickMove.clearButton(v)

                for cb, txt in [
                    (cb_goto_target, 'Goto target'),
                    (cb_permanent, 'Make permanent'),
                    # (cb_clear, 'Clear permanent'),
                    (cb_set_parent, 'Set parent'),
                ]:
                    but = b.button
                    rc = QtWidgets.QAction(txt, but)
                    rc.triggered.connect(cb)
                    but.insertAction(but.actions()[-1], rc)
                        # insert rc before Remove Button

        self.buttons.append((mb,b))
Example #47
0
 def show_note(self):
     if stickynotes:
         stickynotes.stickynote_f({'c': self.c})
     else:
         g.es('stickynotes not available')
Example #48
0
 def mylyn_scores_f(*a):
     for k, v in self.scoring.items():
         g.es(str(k) + " " + str(v))
Example #49
0
    def itp(itPoll, cmdrB, cmdrRes, resultsRoot, subPscript, subPbabKill, wro,
            reo, wre, ree, itOut, itErr, start, createNodes):
        """ Poll for subprocess done

        Arguments:
            itPoll:  Idle time object for itp()
            cmdrB: Leo-Editor commander for the Leo-Babel root node
            cmdRes: Leo-Editor commander for resultsRoot
            resultsRoot: Results root
            subPscript:  Script subprocess object
            subPbabKill:  babel_kill subprocess object
            wro: File Descriptor
            reo: File Descriptor
            wre: File Descriptor
            ree: File Descriptor
            itOut: Idle time object
            itErr: Idle time object
            start:  Script start time
            createNodes: False --> Don't create results nodes
                True --> Create results nodes

        Returns:
            None
        """

        babelCmdr = cmdrB.user_dict['leo_babel']
        if babelCmdr.cmdDoneFlag:
            if babelCmdr.cmdDoneStdPolled and babelCmdr.cmdDoneErrPolled:
                itOut.stop()
                itErr.stop()
                itPoll.stop()
                wro.close()
                wre.close()
                colorCompletion = babelCmdr.colorCompletion
                leoG.es(babelCmdr.termMsg, color=colorCompletion)
                leoG.es(babelCmdr.etMsg, color=colorCompletion)
                if createNodes:
                    makeBabelNodes(cmdrRes, resultsRoot, reo, ree,
                                   babelCmdr.termMsg, babelCmdr.etMsg)
                reo.close()
                ree.close()
                babelCmdr.babelExecCnt += 1
        else:
            rc = subPscript.poll()
            if not rc is None:
                end = time.time()
                babelCmdr.cmdDoneFlag = True
                if subPbabKill.poll() is None:
                    # Kill subprocess has not terminated
                    # pylint: disable=no-member
                    os.kill(subPbabKill.pid, signal.SIGHUP)
                babelCmdr.termMsg = '{0} Subprocess Termination Code'.format(
                    rc)
                et = int(round(end - start))
                minutes, secs = divmod(et, 60)
                hours, minutes = divmod(minutes, 60)
                babelCmdr.etMsg = '{hr:02d}:{mi:02d}:{se:02d} Elapsed Time. {end} End Time'.format(
                    hr=hours,
                    mi=minutes,
                    se=secs,
                    end=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
Example #50
0
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
Example #51
0
    def open_temp_file(self, c, d, fn, testing=False):
        '''
        Open a temp file corresponding to fn in an external editor.

        d is a dictionary created from an @openwith settings node.

        'args':     the command-line arguments to be used to open the file.
        'ext':      the file extension.
        'kind':     the method used to open the file, such as subprocess.Popen.
        'name':     menu label (used only by the menu code).
        'shortcut': menu shortcut (used only by the menu code).
        '''
        trace = False and not g.unitTesting
        testing = testing or g.unitTesting
        arg_tuple = d.get('args', [])
        arg = ' '.join(arg_tuple)
        kind = d.get('kind')
        # This doesn't handle %ProgramFiles%
        # if kind in ('os.spawnl', 'subprocess.Popen'):
        # if not g.os_path_exists(arg):
        # g.trace('Executable not found', arg, arg_tuple)
        # return
        try:
            # All of these must be supported because they
            # could exist in @open-with nodes.
            command = '<no command>'
            if kind in ('os.system', 'os.startfile'):
                # New in Leo 5.7:
                # Use subProcess.Popen(..., shell=True)
                c_arg = self.join(arg, fn)
                if trace:
                    command = '%s -> subprocess.Popen(%s)' % (
                        kind, g.shortFileName(c_arg))
                    g.trace(command)
                if not testing:
                    try:
                        subprocess.Popen(c_arg, shell=True)
                    except OSError:
                        g.es_print('c_arg', repr(c_arg))
                        g.es_exception()
                # Legacy code.
                # command = 'os.startfile(%s)' % self.join(arg, fn)
                # if trace: g.trace(command)
                # # pylint: disable=no-member
                # # trust the user not to use this option on Linux.
                # if not testing:
                # os.startfile(arg, fn)
            elif kind == 'exec':
                g.es_print('open-with exec no longer valid.')
                # command = 'exec(%s)' % self.join(arg,fn)
                # if trace: g.trace(command)
                # if not testing:
                # exec(self.join(arg,fn),{},{})
            elif kind == 'os.spawnl':
                filename = g.os_path_basename(arg)
                command = 'os.spawnl(%s,%s,%s)' % (arg, filename, fn)
                if trace: g.trace(command)
                if not testing: os.spawnl(os.P_NOWAIT, arg, filename, fn)
            elif kind == 'os.spawnv':
                filename = os.path.basename(arg_tuple[0])
                vtuple = arg_tuple[1:]
                vtuple.insert(0, filename)
                # add the name of the program as the first argument.
                # Change suggested by Jim Sizelove.
                vtuple.append(fn)
                command = 'os.spawnv(%s)' % (vtuple)
                if trace: g.trace(command)
                if not testing:
                    os.spawnv(os.P_NOWAIT, arg[0], vtuple)  #???
            elif kind == 'subprocess.Popen':
                c_arg = self.join(arg, fn)
                command = 'subprocess.Popen(%s)' % c_arg
                if trace: g.trace(command)
                if not testing:
                    try:
                        subprocess.Popen(c_arg, shell=True)
                    except OSError:
                        g.es_print('c_arg', repr(c_arg))
                        g.es_exception()
            elif g.isCallable(kind):
                # Invoke openWith like this:
                # c.openWith(data=[func,None,None])
                # func will be called with one arg, the filename
                if trace: g.trace('%s(%s)' % (kind, fn))
                command = '%s(%s)' % (kind, fn)
                if not testing: kind(fn)
            else:
                command = 'bad command:' + str(kind)
                if not testing: g.trace(command)
            return command  # for unit testing.
        except Exception:
            g.es('exception executing open-with command:', command)
            g.es_exception()
            return 'oops: %s' % command
Example #52
0
    def run_diff_on_vcs(self, event=None):
        """run_diff_on_vcs - try and check out the previous version of the Leo
        file and compare a node with the same gnx in that file with the
        current node

        :Parameters:
        - `event`: Leo event
        """

        c = self.c

        dir_, filename = g.os_path_split(c.fileName())
        relative_path = []  # path from top of repo. to .leo file

        mode = None  # mode is which VCS to use
        # given A=/a/b/c/d/e, B=file.leo adjust to A=/a/b/c, B=d/e/file.leo
        # so that A is the path to the repo. and B the path in the repo. to
        # the .leo file
        path = dir_
        while not mode:
            for vcs in 'git', 'bzr':
                if g.os_path_exists(g.os_path_join(path, '.' + vcs)):
                    mode = vcs
                    break
            else:
                path, subpath = g.os_path_split(path)
                if not subpath:
                    break
                relative_path[0:0] = [subpath]

        if not mode:
            g.es("No supported VCS found in '%s'" % dir_)
            return

        gnx = c.p.gnx

        if mode == 'git':
            cmd = [
                'git',
                '--work-tree=%s' % path,
                'show',
                'HEAD:%s' % g.os_path_join(*(relative_path + [filename])),
            ]

        if mode == 'bzr':
            cmd = [
                'bzr',
                'cat',
                '--revision=revno:-1',
                c.fileName(),  # path,
                # g.os_path_join( *(relative_path + [filename]) ),
            ]

        cmd = subprocess.Popen(cmd,
                               stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE)
        data, err = cmd.communicate()

        aFile = StringIO(data)
        tree = leosax.get_leo_data(aFile)
        for node in tree.flat():
            if node.gnx == gnx:
                break
        else:
            g.es("Node (gnx) not found in previous version")
            return

        node.b = ''.join(node.b)
        self.run_appropriate_diff([node, c.p])
Example #53
0
def dumpfocus():
    f = QtWidgets.QApplication.instance().focusWidget()
    g.es("Focus: " + f)
    print("Focus: " + f)
Example #54
0
    def load_clouds(self, from_background=None):
        """
        load_clouds - Handle loading from cloud on startup and after
        background checking for changes.

        :param set from_background: set of (remote, ID) str tuples if we're
            called after a background check process finds changes.
        :return: <|returns|>
        :rtype: <|return type|>
        """
        if from_background is None:
            from_background = set()
        skipped = []
        background = []  # things to check in background
        for lc_v in self.find_clouds():
            kwargs = self.kw_from_node(lc_v)
            if from_background and \
                (kwargs['remote'], kwargs['ID']) not in from_background:
                # only process nodes from the background checking
                continue
            read = False
            read_on_load = kwargs.get('read_on_load', '').lower()
            if from_background:
                # was 'background', changes found, so now treat as 'ask'
                read_on_load = 'ask'
            if read_on_load == 'yes':
                read = True
            elif read_on_load == 'ask':
                try:
                    last_read = datetime.strptime(
                        lc_v.u['_leo_cloud']['last_read'],
                        "%Y-%m-%dT%H:%M:%S.%f")
                except KeyError:
                    last_read = None
                message = "Read cloud data '%s', overwriting local nodes?" % kwargs[
                    'ID']
                if last_read:
                    delta = datetime.now() - last_read
                    message = "%s\n%s, %sh:%sm:%ss ago" % (
                        message, last_read.strftime("%a %b %d %H:%M"),
                        24 * delta.days + int(delta.seconds / 3600),
                        int(delta.seconds / 60) % 60, delta.seconds % 60)
                read = g.app.gui.runAskYesNoCancelDialog(self.c,
                                                         "Read cloud data?",
                                                         message=message)
                read = str(read).lower() == 'yes'
            if read:
                self.read_current(p=self.c.vnode2position(lc_v))
            elif read_on_load == 'background':
                # second time round, with from_background data, this will
                # have been changed to 'ask' (above), so no infinite loop
                background.append((lc_v, kwargs,
                                   self.recursive_hash(lc_v, [],
                                                       include_current=False)))
            elif read_on_load == 'no':
                g.es("NOTE: not reading '%s' from cloud" % kwargs['ID'])
            elif read_on_load != 'ask':
                skipped.append(kwargs['ID'])
        if skipped:
            g.app.gui.runAskOkDialog(
                self.c,
                "Unloaded cloud data",
                message=
                "There is unloaded (possibly stale) cloud data, use\nread_on_load: yes|no|ask\n"
                "in @leo_cloud nodes to avoid this message.\nUnloaded data:\n%s"
                % ', '.join(skipped))

        if background:
            # send to background thread for checking
            names = ', '.join([i[1]['ID'] for i in background])
            g.es("Checking cloud trees in background:\n%s" % names)
            thread = threading.Thread(target=self.bg_check,
                                      args=(background, ))
            thread.start()
            # start watching for results
            g.IdleTime(self.bg_post_process).start()
Example #55
0
def save(self, event=None, fileName=None):
    '''Save a Leo outline to a file.'''
    if False and g.app.gui.guiName() == 'curses':
        g.trace('===== Save disabled in curses gui =====')
        return
    c = self
    p = c.p
    # Do this now: w may go away.
    w = g.app.gui.get_focus(c)
    inBody = g.app.gui.widget_name(w).startswith('body')
    if inBody:
        p.saveCursorAndScroll()
    if g.unitTesting and g.app.unitTestDict.get(
            'init_error_dialogs') is not None:
        # A kludge for unit testing:
        # indicated that c.init_error_dialogs and c.raise_error_dialogs
        # will be called below, *without* actually saving the .leo file.
        c.init_error_dialogs()
        c.raise_error_dialogs(kind='write')
        return
    if g.app.disableSave:
        g.es("save commands disabled", color="purple")
        return
    c.init_error_dialogs()
    # 2013/09/28: use the fileName keyword argument if given.
    # This supports the leoBridge.
    # Make sure we never pass None to the ctor.
    if fileName:
        c.frame.title = g.computeWindowTitle(fileName)
        c.mFileName = fileName
    if not c.mFileName:
        c.frame.title = ""
        c.mFileName = ""
    if c.mFileName:
        # Calls c.setChanged(False) if no error.
        g.app.syntax_error_files = []
        c.fileCommands.save(c.mFileName)
        c.syntaxErrorDialog()
    else:
        root = c.rootPosition()
        if not root.next() and root.isAtEditNode():
            # There is only a single @edit node in the outline.
            # A hack to allow "quick edit" of non-Leo files.
            # See https://bugs.launchpad.net/leo-editor/+bug/381527
            fileName = None
            # Write the @edit node if needed.
            if root.isDirty():
                c.atFileCommands.writeOneAtEditNode(root,
                                                    toString=False,
                                                    force=True)
            c.setChanged(False)
        else:
            fileName = ''.join(c.k.givenArgs)
            if not fileName:
                fileName = g.app.gui.runSaveFileDialog(
                    c,
                    initialfile=c.mFileName,
                    title="Save",
                    filetypes=[g.fileFilters('LEOFILES')],
                    defaultextension=g.defaultLeoFileExtension(c))
        c.bringToFront()
        if fileName:
            # Don't change mFileName until the dialog has suceeded.
            c.mFileName = g.ensure_extension(fileName,
                                             g.defaultLeoFileExtension(c))
            c.frame.title = c.computeWindowTitle(c.mFileName)
            c.frame.setTitle(c.computeWindowTitle(c.mFileName))
            # 2013/08/04: use c.computeWindowTitle.
            c.openDirectory = c.frame.openDirectory = g.os_path_dirname(
                c.mFileName)
            # Bug fix in 4.4b2.
            if g.app.qt_use_tabs and hasattr(c.frame, 'top'):
                c.frame.top.leo_master.setTabName(c, c.mFileName)
            c.fileCommands.save(c.mFileName)
            g.app.recentFilesManager.updateRecentFiles(c.mFileName)
            g.chdir(c.mFileName)
    # Done in FileCommands.save.
    # c.redraw_after_icons_changed()
    c.raise_error_dialogs(kind='write')
    # *Safely* restore focus, without using the old w directly.
    if inBody:
        c.bodyWantsFocus()
        p.restoreCursorAndScroll()
    else:
        c.treeWantsFocus()
Example #56
0
 def focusOutEvent(self, event):
     QtWidgets.QGraphicsItemGroup.focusOutEvent(self, event)
     self.bg.setBrush(QtGui.QBrush(QtGui.QColor(200, 240, 200)))
     g.es("focusOutEvent")
Example #57
0
def xml2leo(event, from_string=None):
    """handle import of an .xml file, places new subtree after c.p
    """
    c = event['c']
    p = c.p

    if from_string:
        parser_func = etree.fromstring
        file_name = from_string
    else:
        parser_func = etree.parse
        cd_here(c, p)
        file_name = g.app.gui.runOpenFileDialog(c,
                                                title="Open",
                                                filetypes=table,
                                                defaultextension=".xml")

        if not file_name:
            raise Exception("No file selected")

    try:
        xml_ = parser_func(file_name)
    except etree.XMLSyntaxError:
        xml_ = parser_func(file_name, parser=etree.HTMLParser())
    except Exception:
        g.es("Failed to read '%s'" % file_name)
        raise

    if from_string:
        # etree.fromstring and etree.parse return Element and
        # ElementTree respectively
        xml_ = etree.ElementTree(xml_)

    nd = p.insertAfter()
    nd.h = os.path.basename(file_name)

    # the root Element isn't necessarily the first thing in the XML file
    # move to the beginning of the list to capture preceding comments
    # and processing instructions
    toplevel = xml_.getroot()
    while toplevel.getprevious() is not None:
        toplevel = toplevel.getprevious()

    # move through list, covering root Element and any  comments
    # or processing instructions which follow it
    while toplevel is not None:
        append_element(toplevel, nd)
        toplevel = toplevel.getnext()

    nd.b = '<?xml version="%s"?>\n' % (xml_.docinfo.xml_version or '1.0')
    if xml_.docinfo.encoding:
        nd.b = '<?xml version="%s" encoding="%s"?>\n' % (
            xml_.docinfo.xml_version or '1.0', xml_.docinfo.encoding)
    if NSMAP:
        for k in sorted(NSMAP):
            if k:
                nd.b += "%s: %s\n" % (k, NSMAP[k])
            else:
                nd.b += "%s\n" % NSMAP[k]
    nd.b += xml_.docinfo.doctype + '\n'

    c.redraw()

    return nd
Example #58
0
 def focus():
     g.es(stack)
     c.selectPosition(pos)
Example #59
0
 def log(self, s, color=None):
     if color:
         g.es('sftp.py:', s, color=color)
     else:
         g.es('sftp.py:', s)
Example #60
0
def xml_validate(event):
    """Perform DTD validation on the xml and return error output
    or an empty string if there is none"""

    c = event['c']
    p = c.p

    # first just try and create the XML
    try:
        xml_ = xml_for_subtree(p)
    except ValueError:
        g.es('ERROR generating XML')
        g.es(traceback.format_exc())
        return

    g.es('XML generated, attempting DTD validation')

    if xml_.startswith('<?xml '):
        # Unicode strings with encoding declaration are not supported
        # so cut off the xml declaration
        xml_ = xml_.split('\n', 1)[1]

    # set cwd so local .dtd files can be found
    cd_here(c, p)

    # make xml indented because for some unknown reason pretty_print=True
    # in xml_for_subtree doesn't work
    # etree.fromstring only returns the root node,
    # losing the DTD, so etree.parse instead
    from io import StringIO
    xml_ = StringIO(xml_)
    xml_ = etree.tostring(etree.parse(xml_), pretty_print=True)

    parser = etree.XMLParser(dtd_validation=True)
    try:
        etree.fromstring(xml_, parser=parser)
        g.es('No errors found')
    except etree.XMLSyntaxError as xse:
        g.es('ERROR validating XML')
        g.es(str(xse))

        # seems XMLSyntaxError doesn't set lineno?  Get from message
        lineno = int(str(xse).split()[-3].strip(',')) - 1
        xml_text = xml_.split('\n')
        for i in range(max(0, lineno - 6), min(len(xml_text), lineno + 3)):
            g.es("%d%s %s" % (i, ':' if i != lineno else '*', xml_text[i]))