Last active
December 13, 2015 19:18
-
-
Save blackfog/4961201 to your computer and use it in GitHub Desktop.
As described here (http://craigipedia.blogspot.com/2013/02/linking-drafts-day-one-and-textexpander.html) this script provides the glue between Drafts, TextExpander, Pythonista, and Day One on iOS to bring TextExpander fill-in support to a workflow.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
############################################################################# | |
# | |
# Fill-in Expander | |
# (c) 2013 Craig A. Pearlman | |
# code@craig.blackfog.net | |
# | |
# This code is licensed under a Creative Commons Attribution 3.0 Unported | |
# license (http://creativecommons.org/licenses/by/3.0/). Attribution is not | |
# required, but it would be a nice gesture. | |
# | |
# This is my first (real) python script. Please make corrections. I know it's | |
# a tad clumsy. | |
# | |
############################################################################# | |
# | |
# Call from Drafts with a custom URL action as follows: | |
# | |
# pythonista://fillin_expander?action=run&argv=[urlencoded snippet] | |
# | |
# Essentially, fill in the form in Drafts with the proper values. You will | |
# need to expand the snippet in Drafts, as well. If you want the action to | |
# fire off Day One at the end, you will need to enable firing actions from | |
# URL support in Drafts' settings. | |
# | |
# When done, this will return the filled-in snippet back to Drafts and then | |
# automatically shove it off to Day One (you can modify this behavior to suit | |
# your needs). | |
# | |
############################################################################# | |
# NOTE: this does not currently support "optional sections" (don't use 'em) | |
# TODO: See if there's a way to do this more graphically | |
### REQUIREMENTS ### | |
import console | |
import re | |
import sys | |
import urllib | |
import webbrowser | |
### FUNCTIONS ### | |
def parse_fillin(parts): | |
properties = dict() | |
last_key = 'type' | |
for part in parts: | |
components = re.split('=', part) | |
if 'type' in properties and \ | |
properties['type'] == 'fillpopup' and \ | |
'options' not in properties: | |
properties['options'] = [] | |
if (len(components) == 1): | |
if last_key == 'options': | |
properties['options'].append(components[0]) | |
else: | |
properties[last_key] = components[0] | |
last_key = 'options' | |
else: | |
if components[0] == 'default': | |
properties['default'] = components[1] | |
if 'options' in properties and 'default' in properties: | |
properties['options'].append(properties['default']) | |
else: | |
properties[ components[0] ] = components[1] | |
return properties | |
def prompt_text(properties): | |
prompt = 'TEXT (' + properties['name'] + ')' | |
if 'default' in properties: | |
prompt += ' [' + properties['default'] + ']: ' | |
else: | |
prompt += ': ' | |
sys.stdout.write(prompt) | |
data = sys.stdin.readline().rstrip() | |
if data == '' and 'default' in properties: | |
data = properties['default'] | |
return data | |
# separate from TEXT in case we decide to handle it differently | |
def prompt_area(properties): | |
prompt = 'AREA (' + properties['name'] + ')' | |
if 'default' in properties: | |
prompt += ' [' + properties['default'] + ']: ' | |
else: | |
prompt += ': ' | |
sys.stdout.write(prompt) | |
data = sys.stdin.readline().rstrip() | |
if data == '' and 'default' in properties: | |
data = properties['default'] | |
return data | |
def prompt_popup(properties): | |
sys.stdout.write('MENU (' + properties['name'] + ')') | |
if 'default' in properties: | |
sys.stdout.write(' [' + properties['default'] + ']: ') | |
else: | |
sys.stdout.write(': ') | |
sys.stdout.write("\n") | |
# there's something wonky in the indices here; prolly don't understand | |
# something about one of the functions (but it works) | |
for i in range(1, len(properties['options']) + 1): | |
print(' [' + str(i) + '] ' + properties['options'][i - 1]) | |
sys.stdout.write('=> ') | |
data = sys.stdin.readline().rstrip() | |
if (data == '' or not data.isdigit()) and 'default' in properties: | |
data = properties['options'].index(properties['default']) | |
else: | |
data = int(data) - 1 | |
return properties['options'][int(data)] | |
def do_replacements(fillin): | |
trimmed = re.sub('^%|%$', '', fillin) | |
parts = re.split(':', trimmed) | |
properties = parse_fillin(parts) | |
if properties['type'] == 'filltext': | |
return prompt_text(properties) | |
elif properties['type'] == 'fillpopup': | |
return prompt_popup(properties) | |
elif properties['type'] == 'fillarea': | |
return prompt_area(properties) | |
else: | |
raise Exception('Unsupported fillin type: ' + properties['type']) | |
### MAIN ### | |
console.clear() | |
# need to change to urllib.parse.x in 3.x (Apple, wherefore 2.x?) | |
snippet = urllib.unquote_plus(sys.argv[1]) | |
fillins = re.findall('%[^%]+%', snippet) | |
for fillin in fillins: | |
replacement = do_replacements(fillin) | |
#print(fillin.rstrip() + ': ' + replacement) | |
snippet = re.sub(fillin, replacement, snippet) | |
# need to change to urllib.parse.x in 3.x (Apple, wherefore 2.x?) | |
encoded_snippet = urllib.quote(snippet) | |
webbrowser.open('drafts://x-callback-url/create?text=' + encoded_snippet + \ | |
'&action=' + urllib.quote('Send to Day One')) | |
# END |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment