Flying Meat

Example Python Scripts for VoodooPad


Unless otherwise noted, to run these scripts put them in an empty page and then choose the "Plugin ▸ Python ▸ Run page as Python" menu item.


Or you can download this website as a Voodoopad document, and run them directly from this page, by selecting them first, and then choosing the "Run page as Python" menu item.


List all the page names in the current document to the current page.


thelist = ""

textView = windowController.textView()

document = windowController.document()

for key in document.keys():

page = document.pageForKey_(key)

thelist = thelist + page.displayName() + "\n"

 

textView.insertText_(thelist)



Creating a new page named "Python Rocks", and insert the link into the current page.


textView = windowController.textView()

document = windowController.document()

document.createNewPageWithName_("Python Rocks")

textView.insertText_("Python Rocks")



Printing out the contents of the index page


document = windowController.document()

page = document.pageForKey_("index")

pageText = page.dataAsAttributedString().string()

vpconsole(pageText)



Lookup the page data for the current page, and change it's contents.

(Note: this is not undoable)


currentPage = windowController.currentPage()

attributedString = currentPage.dataAsAttributedString()

attributedString.mutableString().setString_("It's all gone!")

currentPage.setDataAsAttributedString_(attributedString)


Tell the text view to select all, and then insert the text "Hi".


windowController.textView().selectAll_(None)

windowController.textView().insertText_("Hi")



Display a dialog box.

This example displays a dialog box with a default button that says "Go Away"


AppKit.NSAlert.alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat_("Hello", "Go Away", None, None, "This is the message").runModal()



Highlight the selected text yellow.

(You'd need to put this in a file named "HighlightYellow.py" in your ~/Library/Application Support/VoodooPad/Script PlugIns/ folder.


VPScriptMenuTitle = "Highlight Yellow"

import AppKit


def main(windowController, *args, **kwargs):

    textView = windowController.textView()

    color = AppKit.NSColor.yellowColor()

    textView.textStorage().addAttribute_value_range_("NSBackgroundColor", color, textView.selectedRange())




Toggle a yellow highlight for the current selection.

This is a variation of the "Highlight Yellow" plugin, which will set and unset the background color for text.


You will need to put this in a file named "ToggleYellowHighlight.py" in your ~/Library/Application Support/VoodooPad/Script PlugIns/ folder, and restart VoodooPad.


# -*- coding: utf-8 -*-

VPScriptMenuTitle = "Toggle Yellow Highlight"

import AppKit


def main(windowController, *args, **kwargs):

    textView = windowController.textView()

    

    # [0] is the location, and [1] is the length of the selected range

    selectedTextStartIndex = textView.selectedRange()[0]

    

    # since the argument for effectiveRange is a pointer, and python doesn't have pointers...

    # we get two results back from this argument.

    (atts, effectiveRange) = textView.textStorage().attributesAtIndex_effectiveRange_(selectedTextStartIndex)

    

    if (atts.has_key("NSBackgroundColor")):

        textView.textStorage().removeAttribute_range_("NSBackgroundColor", textView.selectedRange())

    else:

        color = AppKit.NSColor.yellowColor()

        textView.textStorage().addAttribute_value_range_("NSBackgroundColor", color, textView.selectedRange())

    




Change the font for the current selection to Monaco 10, with a keyboard shortcut

(You'd need to put this in a file named "Monaco.py" in your ~/Library/Application Support/VoodooPad/Script PlugIns/ folder.


VPScriptMenuTitle = "Make Selection Monaco 10"

VPShortcutMask    = "command control"

VPShortcutKey     = "m"


import AppKit


def main(windowController, *args, **kwargs):

    textView = windowController.textView()

    f = AppKit.NSFont.fontWithName_size_("Monaco", 10)

    attrs = {AppKit.NSFontAttributeName: f}

    

    # wrapping our change in shouldChangeTextInRange_replacementString_ + didChangeText

    # allows for free undo support

    if textView.shouldChangeTextInRange_replacementString_(textView.selectedRange(), None):

        textView.textStorage().setAttributes_range_(attrs, textView.selectedRange())

        textView.didChangeText()

    



Make a new email with Microsoft Entourage, from the current page

(You'd need to put this in a file named "MicrosoftEntourage.py" in your ~/Library/Application Support/VoodooPad/Script PlugIns/ folder.


VPScriptSuperMenuTitle = None

VPScriptMenuTitle = "Send page to Microsoft Entourage"


import AppKit


def main(windowController, *args, **kwargs):

    text = windowController.textView().textStorage().string()

    

    # clean up some text, to make it safe for AppleScript

    text = text.replace('"', '\\"')

    text = text.replace("\n", "\r")

    

    script = 'tell application "Microsoft Entourage"\n' + 'set m to make new outgoing message at out box folder with properties {content:"' + text + '"}\n' + 'open m\n' + 'end tell'

    

    AppKit.NSAppleScript.alloc().initWithSource_(script).executeAndReturnError_(None)




List all the pages in the document with a meta value named "todo".


document = windowController.document()

textView = windowController.textView()

list = "My todo pages list:\n"

for key in document.keys():

page = document.pageForKey_(key)

if (page.metaValueForKey_("todo") != None):

    list = list + " * " + page.displayName() + "\n"


textView.insertText_(list)




Look for the word "@todo" in all the pages, and list page name with the line.


theList = ""

document = windowController.document()

for key in document.keys():

page = document.pageForKey_(key)

if page.uti() == "com.fm.page":

    attString = page.dataAsAttributedString()

    for line in attString.mutableString().splitlines():

        if line.find("@todo") >= 0:

            theList = theList + "\n" + page.displayName() + ": " + line.strip()


windowController.textView().insertText_(theList)




Reveal document in Finder (uses AppleScript + Python)


document = windowController.document()

script = '''set s to "%s"

set p to POSIX file s

tell application "Finder"

    activate

    reveal p

end tell''' % (document.fileName())


print(script)


AppKit.NSAppleScript.alloc().initWithSource_(script).executeAndReturnError_(None)



Make a new page with the selected text, without opening it.

(You'd need to put this in a file named "Make new page.py" in your ~/Library/Application Support/VoodooPad/Script PlugIns/ folder, and restart VoodooPad.


VPScriptSuperMenuTitle = None

VPScriptMenuTitle = "Make a new page without opening"


def main(windowController, *args, **kwargs):

    document = windowController.document()

    textView = windowController.textView()

    pageName = textView.textStorage().string().substringWithRange_(textView.selectedRange())

    if len(pageName) == 0:

        print("Sorry, blank words are not allowed")

    else:

        document.createNewPageWithName_(pageName)




A webserver event:


# assign this to the "Web server will send page" event

# check and see if we are dealing with a regular text page type.

if eventDictionary['item'].uti() == 'com.fm.page':

    # grab what's going to be sent out to the browser (this is the raw html)

    output = eventDictionary['output']

    

    # look for the key $lookingFor$ , and replace it with the string "replaceValue"

    # notice that we assign the value back to the event dictionary.  This way, VoodooPad

    # gets the updated value.

    eventDictionary['output'] = output.replace("$lookingForKey$", "<b>This is the substitute value</b>")

    







Getting the current page's modified date


page = windowController.currentPage()

mDate = page.modifiedDate()

cDate = page.createdDate()

print(mDate)

print(cDate)

# printing the page create date in a nicer format

prettyDate = cDate.descriptionWithCalendarFormat_timeZone_locale_("%d/%m/%Y %I:%m %p", None, None)

print(prettyDate)



Getting a pages' name


page = windowController.currentPage()

print(page.displayName())



Getting a pages' unique ID, which stays the same event between page renames


page = windowController.currentPage()

print(page.uuid())



Getting a page's contents, as plain text


page = windowController.currentPage()

text = page.dataAsAttributedString().string()

print(text)



Getting a page's contents, as an NSData object (such as if it was a PDF)


document = windowController.document()

page     = document.pageForKey_("sample pdf.pdf")

data     = page.data()

data.writeToFile_atomically_("/tmp/foo.pdf", True)

os.popen("open /tmp/foo.pdf")



Find out if the page is encrypted or not


page = windowController.currentPage()


if (page.isEncrypted()):

    print("The page is encrypted")

else:

    print("The page is not encrypted")



Appending text to a page


document     = windowController.document()

page         = document.pageForKey_("sample page")

attString    = page.dataAsAttributedString()

attString.mutableString().appendString_("\nThis is new text")

page.setDataAsAttributedString_(attString)



Setting the text for a page


document     = windowController.document()

page         = document.pageForKey_("sample page")

attString    = page.dataAsAttributedString()

attString.mutableString().setString_("This is a sample page")

page.setDataAsAttributedString_(attString)


Getting the tags for a page


document = windowController.document()

page = windowController.currentPage()

for tag in page.tagNames():

    print(tag)



List the pages with a particular tag


document = windowController.document()

for pageUUID in document.uuidsInTagName_("Script"):

    page = document.pageForUUID_(pageUUID)

    print(page.displayName())

    


Save the current page as HTML, using Cocoa libraries.

(You'd need to put this in a file named "pythonhtml.py" in your ~/Library/Application Support/VoodooPad/Script PlugIns/ folder, and restart VoodooPad.


import Foundation

import AppKit


VPScriptSuperMenuTitle = None

VPScriptMenuTitle = "Save as HTML via Python"


def main(windowController, *args, **kwargs):

    

    document = windowController.document()

    textView = windowController.textView()

    page     = windowController.currentPage()

    

    range = Foundation.NSMakeRange(0, textView.textStorage().length())

    

    data, err = textView.textStorage().dataFromRange_documentAttributes_error_(range, {'DocumentType':'NSHTML'}, None)

    

    savePanel = AppKit.NSSavePanel.savePanel()

    savePanel.setTitle_("Save as HTML")

    button = savePanel.runModalForDirectory_file_(None, page.displayName() + ".html")

    

    if button == AppKit.NSFileHandlingPanelOKButton:

        data.writeToFile_atomically_(savePanel.filename(), True)

        




Add the selected numbers up

You will need to put this in a file named "Add.py" in your ~/Library/Application Support/VoodooPad/Script PlugIns/ folder, and restart VoodooPad.


VPScriptMenuTitle = "Add Selection"


import Foundation

import AppKit


def main(windowController, *args, **kwargs):

    

    textView = windowController.textView()

    addString = "0"

    for range in textView.selectedRanges():

        # workaround - selectedRanges() doesn't return the same thing as selectedRange()

        range = Foundation.NSRangeFromString(str(range).replace("NSRange: ", ""))

        

        text = textView.textStorage().string().substringWithRange_(range).strip()

        addString = addString + " + " + text

        

    x = eval(addString)

    print("The total is: " + str(x))





Pasting to the current page as 12pt Courier New

You will need to put this in a file named "PasteCourierNew.py" in your ~/Library/Application Support/VoodooPad/Script PlugIns/ folder, and restart VoodooPad.


VPScriptMenuTitle = "Paste as Courier New 12pt"


from AppKit import *

from Foundation import *


def main(windowController, *args, **kwargs):

    textView = windowController.textView()

    f = NSFont.fontWithName_size_("Courier New", 12)

    attrs = {NSFontAttributeName: f}

    

    pb = NSPasteboard.generalPasteboard()

    s  = pb.stringForType_(NSStringPboardType)

    

    if s is None:

        return # in case we didn't have text on the clipboard

    

    attstr = NSMutableAttributedString.alloc().initWithString_(s)

    attstr.setAttributes_range_(attrs, (0, len(s)))

    

    # wrapping our change in shouldChangeTextInRange_replacementString_ + didChangeText

    # allows for free undo support

    if textView.shouldChangeTextInRange_replacementString_(textView.selectedRange(), None):

        textView.insertText_(attstr)

        textView.didChangeText()




Making a new page, based off the current page name

You will need to put this in a file named "MakeSubpageLink.py" in your ~/Library/Application Support/VoodooPad/Script PlugIns/ folder, and restart VoodooPad.


What this script does is make a new page based off of the current page name and the currently selected text.  For example, let's say you are on a page named "Social Experiments", and you had the text "Method" selected.  Running this script would create a new page named "Social Experiments.Method", add a custom link to the word "Method".


# -*- coding: utf-8 -*-

VPScriptMenuTitle = "Make Sub-page Link"


import AppKit


def main(windowController, *args, **kwargs):

    page     = windowController.currentPage()

    textView = windowController.textView()

    document = windowController.document()

    

    # grab the selected text out of our text view.

    selectedText = textView.string().substringWithRange_(textView.selectedRange())

    

    # remove any whitespace on it.

    selectedText = selectedText.strip()

    

    if len(selectedText) <= 0:

        print("There was no text selected")

        return

    

    # make our new page name, based on the current page and the selected text

    newPageName = page.displayName() + u"." + selectedText

    

    # tell the document to make a new page, with our new name.

    newPage = document.createNewPageWithName_(newPageName)

    

    # This is the voodoopad item url scheme.  We're going to add a custom

    # link to the selected text with it, but first we have to make the link

    link = "x-voodoopad-item://" + newPage.uuid()

    

    # this helps with undo.  First we ask the text view if it's ok to change the selection

    if textView.shouldChangeTextInRange_replacementString_(textView.selectedRange(), None):

        # and then set the link.

        textView.textStorage().addAttribute_value_range_(AppKit.NSLinkAttributeName, link, textView.selectedRange())

    

    # if we wanted to then open the page, we'd do this:

    # document.openPageWithTitle_(newPageName)






Create a list of all the page names in the document

You will need to put this in a file named "GeneratePageIndex.py" in your ~/Library/Application Support/VoodooPad/Script PlugIns/ folder, and restart VoodooPad.


# -*- coding: utf-8 -*-

VPScriptMenuTitle = "Generate Page Index"


import Foundation


def main(windowController, *args, **kwargs):

    

    textView = windowController.textView()

    document = windowController.document()

    

    pageToAppendTo = windowController.currentPage()

    

    # if we wanted to use a particular page, such as "Index Page", 

    # we would uncomment this line and optionally change

    # the page name

    #pageToAppendTo = document.createNewPageWithName_("Index Page")

    

    theList = ""

    for key in document.keys():

        page = document.pageForKey_(key)

        theList = theList + page.displayName() + "\n"

    

    # Silly cocoa stuff to set the string.

    atts = Foundation.NSAttributedString.alloc().initWithString_(theList)

    pageToAppendTo.setDataAsAttributedString_(atts)

    





Insert a custom page template into the current page.

You will need to put this in a file named "InsertPageTemplate.py" in your ~/Library/Application Support/VoodooPad/Script PlugIns/ folder, and restart VoodooPad.


The '<# #>' text are placeholders, and you can use the keyboard shortcut cmd-/ to automatically select those.


# -*- coding: utf-8 -*-

VPScriptMenuTitle = "Insert Page Template"

import AppKit

def main(windowController, *args, **kwargs):

    document = windowController.document()

    textView = windowController.textView()

    template = '''

Last updated:


----- Background:

<# #>


----- Objective

<# #>


----- Current status:

<# #>


----- Timeline:

<# #>


----- Results:

<# #>


----- Linked Documents:'''

    

    # wrapping our change in shouldChangeTextInRange_replacementString_ + didChangeText

    # allows for free undo support

    if textView.shouldChangeTextInRange_replacementString_(textView.selectedRange(), None):

        textView.textStorage().mutableString().appendString_(template)

        textView.didChangeText()

    










» Back to the start page or Download this site as a VoodooPad document