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()

