forked from nikipore/alfred-python
-
Notifications
You must be signed in to change notification settings - Fork 0
/
alfred.py
97 lines (78 loc) · 2.57 KB
/
alfred.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# -*- coding: utf-8 -*-
import itertools
import os
import plistlib
import unicodedata
import sys
from xml.etree.ElementTree import Element, SubElement, tostring
"""
You should run your script via your shell with all escape options ticked.
The command line should be
python3 yourscript.py "{query}" arg2 arg3 ...
"""
UNESCAPE_CHARACTERS = """ ;()"""
_MAX_RESULTS_DEFAULT = 9
with open("info.plist", "rb") as plist:
preferences = plistlib.load(plist)
bundleid = preferences['bundleid']
class Item(object):
@classmethod
def str(cls, value):
try:
items = iter(list(value.items()))
except AttributeError:
return str(value)
else:
return dict(list(map(str, item)) for item in items)
def __init__(self, attributes, title, subtitle, icon=None):
self.attributes = attributes
self.title = title
self.subtitle = subtitle
self.icon = icon
def __str__(self):
return tostring(self.xml(), encoding='unicode')
def xml(self):
item = Element('item', self.str(self.attributes))
for attribute in ('title', 'subtitle', 'icon'):
value = getattr(self, attribute)
if value is None:
continue
if len(value) == 2 and isinstance(value[1], dict):
(value, attributes) = value
else:
attributes = {}
SubElement(item, attribute, self.str(attributes)).text = self.str(value)
return item
def args(characters=None):
return tuple(unescape(decode(arg), characters) for arg in sys.argv[1:])
def config():
return _create('config')
def decode(s):
return unicodedata.normalize('NFD', s)
def env(key):
return os.environ['alfred_%s' % key]
def uid(uid):
return '-'.join(map(str, (bundleid, uid)))
def unescape(query, characters=None):
for character in (UNESCAPE_CHARACTERS if (characters is None) else characters):
query = query.replace('\\%s' % character, character)
return query
def work(volatile):
path = {
True: env('workflow_cache'),
False: env('workflow_data')
}[bool(volatile)]
return _create(path)
def write(text):
sys.stdout.write(text)
def xml(items, maxresults=_MAX_RESULTS_DEFAULT):
root = Element('items')
for item in itertools.islice(items, maxresults):
root.append(item.xml())
return tostring(root, encoding='unicode')
def _create(path):
if not os.path.isdir(path):
os.mkdir(path)
if not os.access(path, os.W_OK):
raise IOError('No write access: %s' % path)
return path