forked from johtso/Snipplr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
snipplr.py
213 lines (172 loc) · 7.05 KB
/
snipplr.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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
import os
import threading
from xmlrpclib import ServerProxy, Error
import HTMLParser
from itertools import groupby
from operator import itemgetter
import sublime
import sublime_plugin
from utils import Worker, status, handle_thread
def get_api_key():
"""Loads API key from settings."""
settings = sublime.load_settings('snipplr.sublime-settings')
api_key = settings.get('api_key')
if not api_key:
sublime.error_message("No Snipplr API key found in settings")
return api_key
class SnipplrInsertCommand(sublime_plugin.TextCommand):
"""Search for snippet and insert it into document at cursor position."""
def run(self, edit):
self.api_key = get_api_key()
if not self.api_key:
return
self.server = ServerProxy("http://snipplr.com/xml-rpc.php")
self.keywords_prompt()
self.threads = {}
self.snippet = None
def keywords_prompt(self):
self.view.window().show_input_panel("Keywords:", "", self.search, None, None)
def search(self, keywords):
t = Worker(lambda: self._search(keywords))
t.start()
self.threads['search'] = t
handle_thread(t, 'Searching Snipplr for: ' + keywords, self.search_cb)
def _search(self, keywords):
try:
return self.server.snippet.list(self.api_key, keywords)
except Error, v:
if v.faultCode is 1:
return []
else:
return False
def search_cb(self):
result = self.threads['search'].result
if result == []:
status('No matching snippets found')
self.keywords_prompt()
elif result == False:
status('Error: Problem searching for snippets')
else:
# The API seems to often send multiple results for the same snippet
# so we need to remove duplicates
get_id = itemgetter('id')
unique_snippets = [next(g) for a, g
in groupby(sorted(result, key=get_id), get_id)]
self.search_results = unique_snippets
result_titles = [snippet['title'] for snippet in unique_snippets]
self.result_selection_prompt(result_titles)
def result_selection_prompt(self, result_titles):
status('Please select a snippet to insert')
self.view.window().show_quick_panel(result_titles,
self.result_selection_cb)
def result_selection_cb(self, index):
if index >= 0:
selection = self.search_results[index]
t = Worker(lambda: self.download(selection['id']))
t.start()
self.threads['download'] = t
handle_thread(t, 'Downloading snippet (%s)' % (selection['title'],),
self.download_cb)
def download(self, snippet_id):
try:
snippet = self.server.snippet.get(snippet_id)
h = HTMLParser.HTMLParser()
snippet = h.unescape(snippet['source'])
return snippet
except Error:
return False
def download_cb(self):
snippet = self.threads['download'].result
if not snippet == False:
self.insert_snippet(snippet)
else:
status('Error: Problem downloading snippet')
def insert_snippet(self, snippet):
selections = self.view.sel()
edit = self.view.begin_edit('snipplr')
try:
if len(selections) > 0:
for sel in selections:
self.view.insert(edit, sel.begin(), snippet)
else:
self.view.insert(edit, 0, snippet)
finally:
self.view.end_edit(edit)
status('Snippet inserted')
class SnipplrUploadCommand(sublime_plugin.TextCommand):
"""Upload currently selected text to Snipplr."""
def run(self, edit):
self.api_key = get_api_key()
if not self.api_key:
return
regions = self.view.sel()
if not (len(regions) > 0) or (regions[0].empty()):
status("Error: No content selected")
return
self.snippet = {
'title': None,
'tags': None,
'language': None,
'source': self.view.substr(regions[0])
}
self.threads = {}
self.server = ServerProxy("http://snipplr.com/xml-rpc.php")
t = Worker(self.get_languages)
t.start()
self.threads['get_languages'] = t
self.title_prompt()
def get_languages(self):
try:
return self.server.languages.list()
except Error:
status("Error: Problem fetching languages")
def title_prompt(self):
self.view.window().show_input_panel("Title:", "",
self.title_cb, None, None)
def title_cb(self, title):
self.snippet['title'] = title
self.tags_prompt()
def tags_prompt(self):
self.view.window().show_input_panel("Tags (space delimited):", "",
self.tags_cb, None, None)
def tags_cb(self, tags):
self.snippet['tags'] = tags
# Open the language prompt once languages have downloaded
handle_thread(self.threads['get_languages'],
'Downloading language list',
cb=self.language_prompt)
def language_prompt(self):
self.languages = self.threads['get_languages'].result
self.language_names = self.languages.values()
# Get the language of the current view
syntax_path = self.view.settings().get('syntax')
filename = os.path.splitext(os.path.basename(syntax_path))[0]
# Normalise the language name to hopefully match Snipplr's
view_language = filename.lower().replace(' ', '-')
def sort_key(cur_lang):
def f(lang):
return -1 if (lang == cur_lang) else lang
return f
# Sort languages alphabetically, and put current view language first
self.language_list = sorted(self.languages.keys(), key=sort_key(view_language))
status('Please select snippet language')
languages = [self.languages[key] for key in self.language_list]
self.view.window().show_quick_panel(languages, self.language_cb)
def language_cb(self, index):
if index >= 0:
self.snippet['language'] = self.language_list[index]
t = threading.Thread(target=self.upload_snippet)
t.start()
handle_thread(t, 'Uploading snippet')
def upload_snippet(self):
snippet = self.snippet
try:
result = self.server.snippet.post(self.api_key, snippet['title'],
snippet['source'], snippet['tags'],
snippet['language'])
if result['success'] == '1':
status('Snippet successfully uploaded', True)
else:
status('Error: Problem uploading snippet', True)
except Error:
status('Error: Problem uploading snippet', True)