wiki:FileFindIns

Version 1 (modified by chriz, 9 years ago) (diff)

Migrated from old trac wiki

This insertion plugin adds links to files or images found in a specific directory matching the supplied pattern. Only tested on windows.

Filefind insertion

The filefind insertion tag has the following form

[:filefind:"PATTERN PATH";OPTION]

Pattern The pattern should be a Unix shell-style wildcards. When the -re option is used you can use a regular expression.

Path The path can be relative to the wiki folder or an absolute path.

Options

  • -d : Show only links to directories
  • -f : Show only links to files
  • -s : recurse subdirs
  • -re : use full regular expression

Examples List all files with index.html as last part of the name in a specific folder and subfolders:

[:filefind: "*index.html c:\doc\";-s]

List all files ending in pdf or doc in a specific folder and subfolders:

[:filefind: "(pdf|doc)$ C:\some\folder";-s;-re]

Imagefind insertion

The imagefind insertion tag has the following form

[:imagefind:"PATTERN DIRECTORY";RESIZE;OPTION]

Resize

  • r##% : resize to percentage of original i.e. r50%
  • s###x### : resize to specific size i.e. s100x50

Options

  • -s : recurse subdirs
  • -re : use full rexexp

Examples Show all jpg images ending with the number 7 in a specific folder and subfolders and resize to 20%:

[:imagefind: "7\.jpg C:\Pictures";r20%;-re;-s]

Save the code below to a file called FileFindIns.py in your user_extensions directory in the wikidpad program directory.

Forum thread about this: http://tech.groups.yahoo.com/group/wikidPad/message/4666

"""
30-11-2008: created by bousch_AT_gmail.com
Do with it what you want, no warranty whatsoever.
"""
import os, os.path, fnmatch
import pwiki.urllib_red as urllib
import string, re

WIKIDPAD_PLUGIN = (("InsertionByKey", 1), )

def describeInsertionKeys(ver, app):
    """
    API function for "InsertionByKey" plugins
    Returns a sequence of tuples describing the supported
    insertion keys. Each tuple has the form (insKey, exportTypes, handlerFactory)
    where insKey is the insertion key handled, exportTypes is a sequence of
    strings describing the supported export types and handlerFactory is
    a factory function (normally a class) taking the wxApp object as
    parameter and returning a handler object fulfilling the protocol
    for "insertion by key" (see EqnHandler as example).

    ver -- API version (can only be 1 currently)
    app -- wxApp object
    """
    return (
            (u"filefind", ("wikidpad_language",), FileFindHandler),
            (u"imagefind", ("wikidpad_language",), ImageFindHandler),
            )

    
def locate(pattern, root=os.curdir, incl_subdirs=False, fullre=False, showOnlyFiles=False, showOnlyDirs=False):
    """
    Locate all files matching supplied filename pattern in and below
    supplied root directory.
    """
    result = []
    def match(f, ptn, fullre): 
        if fullre:
            test = re.compile(ptn, re.IGNORECASE)
            return filter(test.search, f)
        else:
            return fnmatch.filter(f, ptn)

    def add_to_list(files, fileName):
        if showOnlyFiles:
            if os.path.isfile(fileName):
                files.append(fileName)
        elif showOnlyDirs:
            if os.path.isdir(fileName):
                files.append(fileName)
        else: files.append(fileName)
        
    if incl_subdirs:
        for path, dirs, files in os.walk(os.path.abspath(root)):
            for filename in match(files, pattern, fullre):
                add_to_list(result, os.path.join(path, filename))
    else:
        filenames = match(os.listdir(os.path.abspath(root)), pattern, fullre)
        for fn in filenames:
            add_to_list(result, os.path.join(os.path.abspath(root), fn))

    return result

def iif( bCondition, uTrue, uFalse ):
    """
    Immediate if, Python pre 2.5 is missing ternary operator
    """
    return ( uTrue, uFalse )[ not bCondition ]

class FileFindHandler:
    """
    Base class fulfilling the "insertion by key" protocol.
    """
    def __init__(self, app):
        self.app = app
        

    def taskStart(self, exporter, exportType):
        """
        This is called before any call to createContent() during an
        export task.
        An export task can be a single HTML page for
        preview or a single page or a set of pages for export.
        exporter -- Exporter object calling the handler
        exportType -- string describing the export type
        
        Calls to createContent() will only happen after a 
        call to taskStart() and before the call to taskEnd()
        """
        pass
        
    def taskEnd(self):
        """
        Called after export task ended and after the last call to
        createContent().
        """
        pass

    def createResult(self, path, pattern, files, insToken):
        result = "++++ Entries in %s matching pattern: \n" % (path.replace('\\', '/'))
        result += "<<pre\n%s\n>>\n" % pattern
        for fileName in files:
            fileName = "[file:%s | %s ]\n" % (urllib.pathname2url(fileName), fileName.replace('\\','/'))
            result += fileName
        return result

    def createContent(self, exporter, exportType, insToken):
        """
        Handle an insertion and create the appropriate content.

        exporter -- Exporter object calling the handler
        exportType -- string describing the export type
        insToken -- insertion token to create content for (see also 
                PageAst.Insertion)

        An insertion token has the following member variables:
            key: insertion key (unistring)
            value: value of an insertion (unistring)
            appendices: sequence of strings with the appendices

        Meaning and type of return value is solely defined by the type
        of the calling exporter.
        
        For HtmlXmlExporter a unistring is returned with the HTML code
        to insert instead of the insertion.        
        """
        if not insToken.value:
            # Nothing in, nothing out
            return u""

        # split the instoken
        # TODO: this makes it not work with patterns or folders with spaces, fix
        values = insToken.value.split()

        # handle options
        showOnlyDirs = "-d" in insToken.appendices
        showOnlyFiles = "-f" in insToken.appendices
        traverseSubdirs  = "-s" in insToken.appendices
        fullRegEx = "-re" in insToken.appendices
        
        # the firstitem is the filepattern
        pattern = values[0]
        # the second item is the path (optional)
        if len(values) > 1:
            path = values[1]
            if not os.path.isabs(path):
                path = os.path.abspath(os.path.join(os.path.dirname(exporter.getMainControl().getWikiConfigPath()), path))
        else:
            path = os.curdir

        files = locate(pattern, path, traverseSubdirs, fullRegEx, showOnlyFiles, showOnlyDirs)
        files.sort()
        return self.createResult(path, pattern, files, insToken)
        
        
    def getExtraFeatures(self):
        """
        Returns a list of bytestrings describing additional features supported
        by the plugin. Currently not specified further.
        """
        return ()
        
class ImageFindHandler(FileFindHandler):
    """
    This handler gets the first appendix and adds it to the file url.
    The appendix should be something like 's100x100 ' or 'r50%'
    """
    def createResult(self, path, pattern, files, insToken):
        modifier = ""
        if len(insToken.appendices):
            modifier = insToken.appendices[0]
        result = "++++ Entries in %s matching pattern: \n" % (path.replace('\\', '/'))
        result += "<<pre\n%s\n>>\n" % pattern
        for fileName in files:
            fileName = "file:%s%s\n" % (urllib.pathname2url(fileName), iif(modifier, ">" + modifier, ""))
            result += fileName
        return result