Skip to content

Commit fb01d05

Browse files
committed
First commit.
0 parents  commit fb01d05

File tree

7 files changed

+383
-0
lines changed

7 files changed

+383
-0
lines changed

README.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Snippets.alfredworkflow
2+
3+
[Download](https://github.com/pahen/Snippets.alfredworkflow/raw/master/CloudApp.alfredworkflow)
4+
5+
This workflow for [Alfred 2](http://www.alfredapp.com/) will search you snippets from the application [Snippets](http://www.snippetsapp.com/). It's not required to have Snippets running since it will search the data storage (XML file) directly.
6+
7+
## Usage
8+
9+
![](https://github.com/pahen/Snippets.alfredworkflow/raw/master/img/search.png)
10+
11+
```ENTER``` = Copy to clipboard
12+
13+
```CMD + ENTER``` = Copy & paste
14+
15+
```ALT + ENTER``` = View as Large Type
16+
17+
You can also create new snippets from a text selection anywhere by pressing ```CTRL + ALT + CMD + S```.
18+
19+
## TODO
20+
21+
Add support for searching on multiple keywords separated with space.

Snippets.alfredworkflow

30.6 KB
Binary file not shown.

img/search.png

52.4 KB
Loading

src/decode.php

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?php
2+
3+
echo base64_decode($argv[1]);

src/icon.png

27.7 KB
Loading

src/info.plist

+300
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>bundleid</key>
6+
<string></string>
7+
<key>connections</key>
8+
<dict>
9+
<key>02B4CB85-CBBC-424A-8CD9-BD60A5AFE062</key>
10+
<array>
11+
<dict>
12+
<key>destinationuid</key>
13+
<string>47247424-5AC2-4C55-8084-5E993E912178</string>
14+
<key>modifiers</key>
15+
<integer>0</integer>
16+
<key>modifiersubtext</key>
17+
<string></string>
18+
</dict>
19+
</array>
20+
<key>6345EB09-B01E-43FB-AC81-F0AE9E8B14B2</key>
21+
<array>
22+
<dict>
23+
<key>destinationuid</key>
24+
<string>02B4CB85-CBBC-424A-8CD9-BD60A5AFE062</string>
25+
<key>modifiers</key>
26+
<integer>0</integer>
27+
<key>modifiersubtext</key>
28+
<string></string>
29+
</dict>
30+
<dict>
31+
<key>destinationuid</key>
32+
<string>DE853A02-A282-4AB4-AC10-8F887A64555C</string>
33+
<key>modifiers</key>
34+
<integer>524288</integer>
35+
<key>modifiersubtext</key>
36+
<string>View snippet</string>
37+
</dict>
38+
<dict>
39+
<key>destinationuid</key>
40+
<string>BA2DCBB3-65CB-4B21-BD32-6216FC267B3E</string>
41+
<key>modifiers</key>
42+
<integer>1048576</integer>
43+
<key>modifiersubtext</key>
44+
<string>Copy &amp; Paste</string>
45+
</dict>
46+
</array>
47+
<key>6C7A2DB9-77E7-441C-A057-F50799C86E93</key>
48+
<array>
49+
<dict>
50+
<key>destinationuid</key>
51+
<string>AC8CDC1F-4867-4C11-B545-BF0C20AC8EA0</string>
52+
<key>modifiers</key>
53+
<integer>0</integer>
54+
<key>modifiersubtext</key>
55+
<string></string>
56+
</dict>
57+
</array>
58+
<key>AC8CDC1F-4867-4C11-B545-BF0C20AC8EA0</key>
59+
<array/>
60+
<key>BA2DCBB3-65CB-4B21-BD32-6216FC267B3E</key>
61+
<array>
62+
<dict>
63+
<key>destinationuid</key>
64+
<string>23F2AA28-EFD6-4082-B5B3-3D313CF5B63E</string>
65+
<key>modifiers</key>
66+
<integer>0</integer>
67+
<key>modifiersubtext</key>
68+
<string></string>
69+
</dict>
70+
</array>
71+
<key>DE853A02-A282-4AB4-AC10-8F887A64555C</key>
72+
<array>
73+
<dict>
74+
<key>destinationuid</key>
75+
<string>152542AB-5F99-4F4E-A40B-F321D3DAF875</string>
76+
<key>modifiers</key>
77+
<integer>0</integer>
78+
<key>modifiersubtext</key>
79+
<string></string>
80+
</dict>
81+
</array>
82+
</dict>
83+
<key>createdby</key>
84+
<string>Patrik Henningsson</string>
85+
<key>description</key>
86+
<string>Search or create snippets from Snippets</string>
87+
<key>disabled</key>
88+
<false/>
89+
<key>name</key>
90+
<string>Snippets</string>
91+
<key>objects</key>
92+
<array>
93+
<dict>
94+
<key>config</key>
95+
<dict>
96+
<key>argumenttype</key>
97+
<integer>0</integer>
98+
<key>escaping</key>
99+
<integer>0</integer>
100+
<key>keyword</key>
101+
<string>snip</string>
102+
<key>runningsubtext</key>
103+
<string>Searching...</string>
104+
<key>script</key>
105+
<string>php search.php '{query}'</string>
106+
<key>subtext</key>
107+
<string>Search or create snippets from Snippets</string>
108+
<key>title</key>
109+
<string>Snippets</string>
110+
<key>type</key>
111+
<integer>0</integer>
112+
<key>withspace</key>
113+
<true/>
114+
</dict>
115+
<key>type</key>
116+
<string>alfred.workflow.input.scriptfilter</string>
117+
<key>uid</key>
118+
<string>6345EB09-B01E-43FB-AC81-F0AE9E8B14B2</string>
119+
</dict>
120+
<dict>
121+
<key>type</key>
122+
<string>alfred.workflow.output.largetype</string>
123+
<key>uid</key>
124+
<string>152542AB-5F99-4F4E-A40B-F321D3DAF875</string>
125+
</dict>
126+
<dict>
127+
<key>config</key>
128+
<dict>
129+
<key>autopaste</key>
130+
<true/>
131+
<key>clipboardtext</key>
132+
<string></string>
133+
</dict>
134+
<key>type</key>
135+
<string>alfred.workflow.output.clipboard</string>
136+
<key>uid</key>
137+
<string>23F2AA28-EFD6-4082-B5B3-3D313CF5B63E</string>
138+
</dict>
139+
<dict>
140+
<key>config</key>
141+
<dict>
142+
<key>escaping</key>
143+
<integer>0</integer>
144+
<key>script</key>
145+
<string>php ./decode.php '{query}'</string>
146+
<key>type</key>
147+
<integer>0</integer>
148+
</dict>
149+
<key>type</key>
150+
<string>alfred.workflow.action.script</string>
151+
<key>uid</key>
152+
<string>DE853A02-A282-4AB4-AC10-8F887A64555C</string>
153+
</dict>
154+
<dict>
155+
<key>config</key>
156+
<dict>
157+
<key>autopaste</key>
158+
<false/>
159+
<key>clipboardtext</key>
160+
<string></string>
161+
</dict>
162+
<key>type</key>
163+
<string>alfred.workflow.output.clipboard</string>
164+
<key>uid</key>
165+
<string>47247424-5AC2-4C55-8084-5E993E912178</string>
166+
</dict>
167+
<dict>
168+
<key>config</key>
169+
<dict>
170+
<key>action</key>
171+
<integer>0</integer>
172+
<key>argument</key>
173+
<integer>1</integer>
174+
<key>hotkey</key>
175+
<integer>1</integer>
176+
<key>hotmod</key>
177+
<integer>1835008</integer>
178+
<key>hotstring</key>
179+
<string>S</string>
180+
<key>leftcursor</key>
181+
<false/>
182+
<key>modsmode</key>
183+
<integer>0</integer>
184+
</dict>
185+
<key>type</key>
186+
<string>alfred.workflow.trigger.hotkey</string>
187+
<key>uid</key>
188+
<string>6C7A2DB9-77E7-441C-A057-F50799C86E93</string>
189+
</dict>
190+
<dict>
191+
<key>config</key>
192+
<dict>
193+
<key>escaping</key>
194+
<integer>0</integer>
195+
<key>script</key>
196+
<string>$query = &lt;&lt;&lt;'END_OF_ALFRED_QUERY'
197+
{query}
198+
END_OF_ALFRED_QUERY;
199+
200+
$url = 'snippet:add?code=' . rawurlencode($query);
201+
$author = `osascript -e "long user name of (system info)" 2&gt;/dev/null`;
202+
203+
if (!empty($author)) {
204+
$url .= "&amp;amp;author=" . rawurlencode($author);
205+
}
206+
207+
exec('open "' . $url . '"');</string>
208+
<key>type</key>
209+
<integer>1</integer>
210+
</dict>
211+
<key>type</key>
212+
<string>alfred.workflow.action.script</string>
213+
<key>uid</key>
214+
<string>AC8CDC1F-4867-4C11-B545-BF0C20AC8EA0</string>
215+
</dict>
216+
<dict>
217+
<key>config</key>
218+
<dict>
219+
<key>escaping</key>
220+
<integer>0</integer>
221+
<key>script</key>
222+
<string>php ./decode.php '{query}'</string>
223+
<key>type</key>
224+
<integer>0</integer>
225+
</dict>
226+
<key>type</key>
227+
<string>alfred.workflow.action.script</string>
228+
<key>uid</key>
229+
<string>02B4CB85-CBBC-424A-8CD9-BD60A5AFE062</string>
230+
</dict>
231+
<dict>
232+
<key>config</key>
233+
<dict>
234+
<key>escaping</key>
235+
<integer>0</integer>
236+
<key>script</key>
237+
<string>php ./decode.php '{query}'</string>
238+
<key>type</key>
239+
<integer>0</integer>
240+
</dict>
241+
<key>type</key>
242+
<string>alfred.workflow.action.script</string>
243+
<key>uid</key>
244+
<string>BA2DCBB3-65CB-4B21-BD32-6216FC267B3E</string>
245+
</dict>
246+
</array>
247+
<key>readme</key>
248+
<string></string>
249+
<key>uidata</key>
250+
<dict>
251+
<key>02B4CB85-CBBC-424A-8CD9-BD60A5AFE062</key>
252+
<dict>
253+
<key>ypos</key>
254+
<real>10</real>
255+
</dict>
256+
<key>152542AB-5F99-4F4E-A40B-F321D3DAF875</key>
257+
<dict>
258+
<key>ypos</key>
259+
<real>170</real>
260+
</dict>
261+
<key>23F2AA28-EFD6-4082-B5B3-3D313CF5B63E</key>
262+
<dict>
263+
<key>ypos</key>
264+
<real>340</real>
265+
</dict>
266+
<key>47247424-5AC2-4C55-8084-5E993E912178</key>
267+
<dict>
268+
<key>ypos</key>
269+
<real>10</real>
270+
</dict>
271+
<key>6345EB09-B01E-43FB-AC81-F0AE9E8B14B2</key>
272+
<dict>
273+
<key>ypos</key>
274+
<real>170</real>
275+
</dict>
276+
<key>6C7A2DB9-77E7-441C-A057-F50799C86E93</key>
277+
<dict>
278+
<key>ypos</key>
279+
<real>590</real>
280+
</dict>
281+
<key>AC8CDC1F-4867-4C11-B545-BF0C20AC8EA0</key>
282+
<dict>
283+
<key>ypos</key>
284+
<real>590</real>
285+
</dict>
286+
<key>BA2DCBB3-65CB-4B21-BD32-6216FC267B3E</key>
287+
<dict>
288+
<key>ypos</key>
289+
<real>340</real>
290+
</dict>
291+
<key>DE853A02-A282-4AB4-AC10-8F887A64555C</key>
292+
<dict>
293+
<key>ypos</key>
294+
<real>170</real>
295+
</dict>
296+
</dict>
297+
<key>webaddress</key>
298+
<string>https://github.com/pahen/Snippets.alfredworkflow</string>
299+
</dict>
300+
</plist>

src/search.php

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
$keyword = $argv[1];
4+
$doc = new DOMDocument;
5+
6+
// this file has been serialized from Core Data (http://en.wikipedia.org/wiki/Core_Data).
7+
$doc->load(getenv('HOME') . '/Library/Application Support/Snippets/Snippets.xml');
8+
9+
$xpath = new DOMXPath($doc);
10+
11+
// create list of tags
12+
$tagList = array();
13+
foreach ($xpath->query('//object[@type="TAG"]') as $tag) {
14+
$tagList[$tag->getAttribute('id')] = $xpath->query('./attribute[@name="name"]', $tag)->item(0)->nodeValue;
15+
}
16+
17+
echo '<?xml version="1.0"?>';
18+
echo '<items>';
19+
20+
foreach ($xpath->query('//object[@type="SNIPPET"]') as $snippet) {
21+
// ignore deleted snippets
22+
if ($xpath->query('./attribute[@name="dateremoved"]', $snippet)->item(0)) {
23+
continue;
24+
}
25+
26+
$tags = array();
27+
$name = $xpath->query('./attribute[@name="name"]', $snippet)->item(0)->nodeValue;
28+
$tagIds = $xpath->query('./relationship[@name="tags"]', $snippet)->item(0)->getAttribute('idrefs');
29+
$codeId = $xpath->query('./relationship[@name="code"]', $snippet)->item(0)->getAttribute('idrefs');
30+
$code = $xpath->query('//object[@type="CODE" and @id="' . $codeId . '"]/attribute[@name="content"]')->item(0)->nodeValue;
31+
32+
if ($tagIds) {
33+
foreach(explode(' ', $tagIds) as $tagId) {
34+
$tags[] = $tagList[$tagId];
35+
}
36+
}
37+
38+
// do a case-insensitive match and see if we have a snippet with a matching tag, name, or code
39+
if (in_array(strtolower($keyword), array_map('strtolower', $tags)) || stristr($name, $keyword) || stristr($code, $keyword)) {
40+
$title = $name;
41+
42+
if (!empty($tags)) {
43+
$title .= ' (' . implode(', ', $tags) . ')';
44+
}
45+
46+
// unescape slashes (they are escaped in the XML file)
47+
$code = str_replace('\\\\', '\\', $code);
48+
49+
// encode the code in base64 to preserve newlines
50+
echo " <item uid=\"" . $snippet->getAttribute('id') . "\" arg=\"" . base64_encode($code) . "\">\n";
51+
echo " <title>" . $title . "</title>\n";
52+
echo " <subtitle>" . htmlspecialchars($code, ENT_QUOTES, 'utf-8') . "</subtitle>\n";
53+
echo " <icon>icon.png</icon>\n";
54+
echo " <valid>yes</valid>\n";
55+
echo " </item>\n";
56+
}
57+
}
58+
59+
echo '</items>';

0 commit comments

Comments
 (0)