fastGotoNode.py :  » Development » Leo » Leo-4.7.1-final » leo » plugins » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Development » Leo 
Leo » Leo 4.7.1 final » leo » plugins » fastGotoNode.py
#@+leo-ver=4-thin
#@+node:mork.20041018091414.1:@thin fastGotoNode.py
#@<< docstring >>
#@+node:ekr.20050226120947:<< docstring >>
'''A Leo plugin that adds the fast-goto-node minibuffer command that creates a
popup menu. You can summon this menu in two ways, depending on the
``fastgotonode_useKeyBinding`` setting:

- If this setting is True, the ``fastgotonode_binding`` setting should be a Key
  specifier that does not conflict with any key binding in leoSettings.leo.

- If this setting is False, the ``fastgotonode_binding`` setting should be some
  other event specifier, typically 'Button-3'.

You may also invoke the popup menu using Alt-x fast-goto-node.

This plugin offers 3 main feature sets:

1. Movement. If a node has ancestors,siblings or children a menu option will
appear offering the user the ability to jump to the node from thecurrentnode. import 
This is an improvement over moving one node at a time with the keyboard
commands.

2. Inserting text. These menus offer the current language keywords, the
directives the body recognizes and any @file type headline directives. It offers
the new user easy access to the different directives and ways to write a file.

3. Moving Nodes( experimental feature ). You can quickly move a node to its
parent's parent or after a sibling, if they exist.
'''
#@nonl
#@-node:ekr.20050226120947:<< docstring >>
#@nl

#@@language python
#@@tabwidth -4

from __future__ import generators# To make this plugin work with Python 2.2.

#@<< imports >>
#@+node:mork.20041018091414.2:<< imports >>
import leo.core.leoPlugins as leoPlugins
import leo.core.leoGlobals as g

import copy
import Tkinter
import tkFileDialog
import os
#@nonl
#@-node:mork.20041018091414.2:<< imports >>
#@nl
__version__ = ".107"
#@<< version history >>
#@+node:ekr.20050226120947.1:<< version history >>
#@@nocolor
#@+at
# 
# .100 EKR: Added init functions.
# .101 EKR:
# - Removed 'start2' hook.
# - Get c from keywords, not g.top().
# .102 EKR: Added 'return True' to end of init function.
# .103 EKR: Fixed crasher in addLanguageMenu.
# .104 EKR:
# - Define the fast-goto-node minibuffer command.
# - Use the useKeyBinding constant to specify whether to use a key binding or 
# <Button-3>.
# - Changed the docstring accordingly.
# - Corrected the imports to reflect standard usage.
# - Removed some strange code in getWindowMenu.
# .105 EKR:
# - Specify options in leoSettings.leo.
# - Fixed crasher: app -> g.app.
# - Use g.app.windowList to init windows.  This should be done dynamically.
# - Removed langdict stuff, but left the disabled code as a guide in case
#   somebody wants to implement langdict settings in leoSettings.leo.
# .106 EKR: Added from __future__ import generators to suppress warning in 
# Python 2.2.
# .107 EKR: Define smenu in init, **not** at the top level.
# This was the plugin that caused a Tk window to appear, regardless of the 
# gui.
# .108 EKR: Replaced leoColor.leoKeywords by g.globalDirectiveList.
#@-at
#@nonl
#@-node:ekr.20050226120947.1:<< version history >>
#@nl

#@+others
#@+node:ekr.20050226120947.2:init & helpers
def init ():

    if Tkinter is None: return False

    if g.app.gui is None:
        g.app.createTkGui(__file__)

    ok = g.app.gui.guiName() == "tkinter"

    if ok:
        global smenu
        smenu = Tkinter.Menu(tearoff=0,activeforeground='blue',activebackground='white')
        calculateMenuSize()
        leoPlugins.registerHandler(('open2','new'),registerPopupMenu)
        g.plugin_signon(__name__)

        if 0: # We now use leoSettings.leo to get all settings.
            pth = os.path.split(g.app.loadDir)
            lkpm = pth [0] + r"/plugins/fgn.fgn"
            if os.path.exists(lkpm):
                loadLanguages(lkpm)
    return ok
#@nonl
#@+node:mork.20041018091414.20:calculateMenuSize
def calculateMenuSize ():
    global maxmenu
    x = Tkinter.Menu()
    h = (x.winfo_screenheight()*.90) / 25
    maxmenu = int(h)
    x.destroy()
#@nonl
#@-node:mork.20041018091414.20:calculateMenuSize
#@+node:mork.20041018091414.19:registerPopupMenu
def registerPopupMenu (tag,keywords):

    c = keywords.get('c')
    if not c: return

    useKeyBinding = c.config.getBool('fastgotonode_useKeyBinding')
    binding = c.config.getString('fastgotonode_binding')

    def popper (event,c=c):
        pop(event,c)

    if useKeyBinding:
        if binding.startswith('<'): binding = binding[1:-1] # Stirp < and >
        c.keyHandler.registerCommand ('fast-goto-node',binding,popper,pane='all',verbose=True)
    else:
        if not binding.startswith('<'): binding = '<%s>' % binding # Add < and >
        c.keyHandler.registerCommand ('fast-goto-node',None,popper,pane='all',verbose=True)
        c.bind(c.frame.top,binding,popper)
#@nonl
#@-node:mork.20041018091414.19:registerPopupMenu
#@+node:mork.20041018091414.21:loadLanguages (not used)
if 0:

    langdict = {}

    def loadLanguages (lkpm):
        if g.isPython3:
            import configparser as ConfigParser
        else:
            import ConfigParser

        cp = ConfigParser.ConfigParser()
        cp.read(lkpm)
        which = ''
        sec = cp.sections()
        for z in sec:
            if z.strip() == 'language':
                which = z
                break
        if cp.has_section(which):
            op = cp.options(which)
            for z in op:
                z2 = cp.get(which,z).split(',')
                z2 = [x.strip() for x in z2]
                langdict [z] = z2
        for z in sec:
            if z.strip() == 'fgnconfig':
                which2 = z
                break
        if cp.has_section(which2):
            op2 = cp.options(which2)
            for z2 in op2:
                if z2.strip() == 'binder':
                    binder = cp.get(which2,z2)
                    break
#@nonl
#@-node:mork.20041018091414.21:loadLanguages (not used)
#@-node:ekr.20050226120947.2:init & helpers
#@+node:mork.20041018091414.3:disappear
maxmenu = 0
menus = []

def disappear (event,c):

    global smenu
    smenu.unpost()
    smenu.unbind_all("<Button-3>")
    c.frame.body.bodyCtrl.focus_set()
#@-node:mork.20041018091414.3:disappear
#@+node:mork.20041018091414.4:pop
lastwidg = None

def pop (event,c):
    clear()
    needs_sep = needsSeparator(smenu)

    def addMenu (label,menu):
        menus.append(menu)
        needs_sep.next()
        smenu.add_cascade(label=label,menu=menu)
        menu.configure(activeforeground='blue',activebackground='white')
        def em (event):
            smenu.focus_set()
        c.bind(menu,'<Expose>',em)

    c.bind(smenu,'<Left>',lambda event,c=c: disappear(event,c))

    ancmenu = getAncestorsMenu(smenu,c)
    if ancmenu:
        addMenu('Ancestors',ancmenu)

    sibmenu = getSiblingsMenu(smenu,c)
    if sibmenu:
        addMenu('Siblings',sibmenu)

    chimenu = getChildrenMenu(smenu,c)
    if chimenu:
        addMenu('Children',chimenu)

    winmenu = getWindowMenu(smenu,c)
    if winmenu:
        addMenu('Windows',winmenu)

    srmenu = getSectionReferenceMenu(smenu,c)
    if srmenu:
        addMenu('Insert '+'<'+'< '+'>'+'>',srmenu)

    menu, language = addLanguageMenu(smenu,c)
    if menu:
        addMenu(language,menu)

    dimenu = getDirectiveInsert(smenu,c)
    addMenu('Directives',dimenu)

    hmenu = getHeadlineMenu(smenu,c)
    addMenu('Headline',hmenu)

    mvamenu = getMoveAMenu(smenu,c)
    if mvamenu: addMenu("Mv_Ancestor",mvamenu)

    mvsmenu = getMoveSMenu(smenu,c)
    if mvsmenu: addMenu("Mv_Sibling",mvsmenu)

    smenu.bind_all("<Button-3>",lambda event,c=c: disappear(event,c))

    smenu.post(event.x_root,event.y_root)
    smenu.focus_set()
#@-node:mork.20041018091414.4:pop
#@+node:ekr.20060110203946.1:Menus
#@+node:mork.20041018091414.5:getSectionReferenceMenu
def getSectionReferenceMenu (pmenu,c):
    p = c.p
    nc = p.numberOfChildren()
    import re
    reg = re.compile("^<"+"<.+?>"+">$")
    srefs = []
    for z in range(nc):
        chi = p.nthChild(z)
        hl = chi.h
        if reg.match(hl):
            srefs.append(hl)

    srmenu = None
    if len(srefs):
        srefs.sort()
        srmenu = Tkinter.Menu(pmenu,tearoff=0)
        sb = shouldBreak()
        for z in srefs:
            c.add_command(srmenu,
                label = z,
                command = lambda label = z, c = c:
                paster(label,c,''), columnbreak = sb.next())

    return srmenu
#@nonl
#@-node:mork.20041018091414.5:getSectionReferenceMenu
#@+node:mork.20041018091414.6:getWindowMenu
def getWindowMenu (pmenu,c):
    wl = g.app.windowList
    winmenu = Tkinter.Menu(pmenu,tearoff=0)
    def bTF (frame):
        frame.bringToFront()
        g.app.setLog(frame.log)
        frame.body.bodyCtrl.focus_set()
        clear()
    sb = shouldBreak()
    for z in wl:
        c.add_command(winmenu,
            label = z.getTitle(),
            command = lambda frame = z: bTF(frame),
            columnbreak = sb.next())
    return winmenu
#@nonl
#@-node:mork.20041018091414.6:getWindowMenu
#@+node:mork.20041018091414.7:getChildrenMenu
def getChildrenMenu (pmenu,c):
    p = c.p
    nchildren = p.numberOfChildren()
    chimenu = None
    if nchildren > 0:
        chimenu = Tkinter.Menu(pmenu,tearoff=0)
        sb = shouldBreak()
        childnames = []
        children = {}
        for z in range(p.numberOfChildren()):
            child = p.nthChild(z)
            hs = child.h
            childnames.append(hs)
            children [hs] = child
        childnames.sort()
        def adder (a):
            hs = a
            child = children [hs]
            c.add_command(chimenu,
                label = hs,
                command = lambda p = child, c = c:
                jumpto(p,c),
                columnbreak = sb.next())
        map(adder,childnames)
    return chimenu
#@-node:mork.20041018091414.7:getChildrenMenu
#@+node:mork.20041018091414.8:getSiblingsMenu
def getSiblingsMenu (pmenu,c):
    siblings = []
    p = c.p
    siblings = getSiblingList(p)
    sibmenu = None
    def sorSibs (a,b):
        if a.h > b.h: return 1
        elif a.h < b.h: return-1
        return 0
    siblings.sort(sorSibs)
    if len(siblings) != 0:
        sibmenu = Tkinter.Menu(pmenu,tearoff=0)
        sb = shouldBreak()
        for z in siblings:
            hs = z.h
            c.add_command(sibmenu,
                label = hs,
                command = lambda p = z, c = c:
                jumpto(p,c),
                columnbreak = sb.next())

    return sibmenu
#@-node:mork.20041018091414.8:getSiblingsMenu
#@+node:mork.20041018113134:getSiblingList
def getSiblingList (p):

    siblings = []
    pnod = p.back()
    while pnod:
        siblings.append(pnod)
        pnod = pnod.back()
    siblings.reverse()
    nnod = p.next()
    while nnod:
        siblings.append(nnod)
        nnod = nnod.next()
    return siblings
#@nonl
#@-node:mork.20041018113134:getSiblingList
#@+node:mork.20041018091414.9:getAncestorsMenu
def getAncestorsMenu (pmenu,c):
        ancmenu = None
        alist = getAncestorList(c.p)
        if alist:
            ancmenu = Tkinter.Menu(pmenu,tearoff=0)
            sb = shouldBreak()
            for z in alist:
                hs = z.h
                c.add_command(ancmenu,
                    label = hs,
                    command = lambda parent = z, c = c:
                    jumpto(parent,c),
                    columnbreak = sb.next())

        return ancmenu
#@-node:mork.20041018091414.9:getAncestorsMenu
#@+node:mork.20041018114908:getAncestorList
def getAncestorList (p):

    alist = []
    parent = p.parent()
    while parent:
        alist.append(parent)
        parent = parent.parent()
    return alist
#@nonl
#@-node:mork.20041018114908:getAncestorList
#@+node:mork.20041018091414.10:addLanguageMenu
def addLanguageMenu (pmenu,c,haveseen={}):
    colorizer = c.frame.body.getColorizer()
    if not colorizer.language: return None, None

    if not haveseen.has_key(colorizer.language):
        lk = colorizer.language + '_keywords'
        try:
            kwords = getattr(colorizer,lk)
        except AttributeError:
            kwords = ()
        kwords = list(kwords)
        if 0: # no longer used.
            if langdict.has_key(colorizer.language):
                l = langdict [colorizer.language]
                for z in l:
                    kwords.append(z)
                kwords.sort()
    else:
        kwords = haveseen [colorizer.language]

    lmenu = Tkinter.Menu(pmenu,tearoff=0)
    sb = shouldBreak()
    for z in kwords:
        c.add_command(lmenu,
            label = z,
            command = lambda keyword = z, c = c:
            paster(keyword,c),
            columnbreak = sb.next())

    return lmenu, colorizer.language
#@nonl
#@-node:mork.20041018091414.10:addLanguageMenu
#@+node:mork.20041018120620:getMoveAMenu
def getMoveAMenu (pmenu,c):

    mvmenu = None

    def mvchild (p,p2,c=c):
        p.moveToNthChildOf(p2,0)
        c.redraw()

    p = c.p
    alist = getAncestorList(p)
    if alist: alist.pop(0)
    if alist:
        mvmenu = Tkinter.Menu(pmenu,tearoff=0)
        sb = shouldBreak()
        for z in alist:
            hs = z.h
            c.add_command(mvmenu,
                label = hs,
                command = lambda p = p, p2 = z:
                mvchild(p,p2),
                columnbreak = sb.next())
    return mvmenu
#@-node:mork.20041018120620:getMoveAMenu
#@+node:mork.20041018120620.1:getMoveSMenu
def getMoveSMenu (pmenu,c):

    smenu = None
    p = c.p
    sibs = getSiblingList(p)
    bk = p.back()
    if bk: sibs.remove(bk)
    def mafter (p,p2,c=c):
        p.moveAfter(p2)
        c.redraw()
    if sibs:
        smenu = Tkinter.Menu(pmenu,tearoff=0)
        sb = shouldBreak()
        for z in sibs:
            c.add_command(smenu,label=z.h,
                            command = lambda p = p, p2 = z: mafter(p,p2),
                            columnbreak = sb.next())
    return smenu
#@nonl
#@-node:mork.20041018120620.1:getMoveSMenu
#@+node:mork.20041018092814:getHeadlineMenu
def getHeadlineMenu (pmenu,c):

    p = c.p
    v = p.v
    def getValue (names,self=v):
        return names
    olFindAtFileName = v.findAtFileName
    v.findAtFileName = getValue
    names = v.anyAtFileNodeName()
    v.findAtFileName = olFindAtFileName
    names = list(names)
    names.sort()
    hmenu = Tkinter.Menu(pmenu,tearoff=0)
    c.add_command(hmenu,
        label = 'add <' + '<' + '>' + '>',
        command = lambda c = c: addGL(c))
    hmenu.add_separator()
    for z in names:
        c.add_command(hmenu,label=z,
                            command = lambda c = c, d = z, nm = names:
                                setFileDirective(c,d,nm))
    hmenu.add_separator()
    c.add_command(hmenu,label='remove @',command=lambda c=c,nm=names:
                                            removeFileDirective(c,nm))
    return hmenu
#@nonl
#@-node:mork.20041018092814:getHeadlineMenu
#@+node:mork.20041018091414.13:getDirectiveInsert
def getDirectiveInsert (pm,c,directives=[],directives2=[]):
    m = Tkinter.Menu(pm,tearoff=0)
    sb = shouldBreak()
    if len(directives) == 0:
        for z in g.globalDirectiveList:
            if not z.startswith('@'): z = '@' + z
            directives.append(z)
        directives.sort()
    for z in directives:
       c.add_command(m,
          label = z,
          columnbreak = sb.next(),
          command = lambda label = z, c = c:
          paster(label,c))

    return m
#@-node:mork.20041018091414.13:getDirectiveInsert
#@-node:ekr.20060110203946.1:Menus
#@+node:ekr.20060110203946.2:Utilities
#@+node:mork.20041018100044.1:getCleanHeadString
def getCleanHeadString (hS,names):

    def sT (a,b):
        if len(a) > len(b): return-1
        if len(a) < len(b): return 1
        return 0
    names = list(names)
    names.sort(sT)
    for z in names:
        hS2 = hS.lstrip()
        if hS2.startswith(z):
            hS = hS2.lstrip(z)
            hS = hS.lstrip()
            return hS
    return hS
#@nonl
#@-node:mork.20041018100044.1:getCleanHeadString
#@+node:mork.20041018091414.11:needsSeparator
def needsSeparator( menu ):
    yield None
    while 1:
        menu.add_separator()
        yield None
#@nonl
#@-node:mork.20041018091414.11:needsSeparator
#@+node:mork.20041018091414.12:shouldBreak
def shouldBreak():
    i = 0
    while 1:
        i += 1
        if i == maxmenu:
            i = 0
            yield True
        else: yield False
#@-node:mork.20041018091414.12:shouldBreak
#@+node:mork.20041018095448:setFileDirective
def setFileDirective( c , directive, names ):

    p = c.p
    hS = p.h
    hS = getCleanHeadString( hS, names )
    hS = directive + " " + hS
    c.setHeadString(p,hS )
    c.frame.body.bodyCtrl.focus_set()  
    c.frame.body.bodyCtrl.update_idletasks()
    c.redraw()
#@nonl
#@-node:mork.20041018095448:setFileDirective
#@+node:mork.20041018100044:removeFileDirective
def removeFileDirective (c,names):

    p = c.p
    hS = p.h
    hS = getCleanHeadString(hS,names)
    c.setHeadString(p,hS)
    c.frame.body.bodyCtrl.focus_set()
    c.frame.body.bodyCtrl.update_idletasks()
    c.redraw()
#@nonl
#@-node:mork.20041018100044:removeFileDirective
#@+node:mork.20041018091414.14:addGL
def addGL (c):
    vnode = c.currentVnode()
    hs = vnode.h
    nhs = "<" + "<" + hs + ">" + ">"
    c.setHeadString(vnode,nhs)
    c.frame.body.bodyCtrl.focus_set()
    c.frame.body.bodyCtrl.update_idletasks()
    c.redraw()
#@nonl
#@-node:mork.20041018091414.14:addGL
#@+node:mork.20041018091414.15:insertHeadline
def insertHeadline (directive,c):
    vnode = c.currentVnode()
    hs = vnode.h
    nhs = directive + " " + hs
    c.setHeadString(vnode,nhs)
    c.redraw()
#@nonl
#@-node:mork.20041018091414.15:insertHeadline
#@+node:mork.20041018091414.16:paster
def paster (directive,c,end=' '):
    bdy = c.frame.body
    bdy.insertAtInsertPoint(directive+end)
    bdy.onBodyChanged(undoType=None)
    bdy.bodyCtrl.focus_set()
    bdy.bodyCtrl.update_idletasks()
    c.redraw()
    bdy.bodyCtrl.focus_set()
#@nonl
#@-node:mork.20041018091414.16:paster
#@+node:mork.20041018091414.17:clear
def clear ():
    global menus
    smenu.delete(0,Tkinter.END)
    for z in menus:
        z.destroy()
    menus = []
#@-node:mork.20041018091414.17:clear
#@+node:mork.20041018091414.18:jumpto
def jumpto (vnode,c):
    smenu.unpost()
    c.frame.tree.expandAllAncestors(vnode)
    c.selectVnode(vnode)
    c.redraw()
#@-node:mork.20041018091414.18:jumpto
#@-node:ekr.20060110203946.2:Utilities
#@-others
#@nonl
#@-node:mork.20041018091414.1:@thin fastGotoNode.py
#@-leo
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.