|
0
|
1 # -*-Mode:python-*-
|
|
|
2
|
|
|
3 import os
|
|
|
4 import tempfile
|
|
|
5 import sys
|
|
|
6 import subprocess
|
|
|
7 import webbrowser
|
|
|
8 import urllib
|
|
|
9 import threading
|
|
|
10 from StringIO import StringIO
|
|
|
11
|
|
|
12 def getFuelApplication():
|
|
|
13 from xpcom import components
|
|
|
14 fuel_cls = components.classes["@mozilla.org/fuel/application;1"]
|
|
|
15 fuel_abs = fuel_cls.createInstance()
|
|
|
16 fuel_if = components.interfaces.fuelIApplication
|
|
|
17 return fuel_abs.queryInterface(fuel_if)
|
|
|
18
|
|
|
19 def getCommandDispatcher():
|
|
|
20 from xpcom import components
|
|
|
21
|
|
|
22 ci = components.interfaces
|
|
|
23 cc = components.classes
|
|
|
24
|
|
|
25 Application = getFuelApplication()
|
|
|
26 document = Application.activeWindow.activeTab.document
|
|
|
27
|
|
|
28 mediator = cc["@mozilla.org/appshell/window-mediator;1"].getService(ci.nsIWindowMediator)
|
|
|
29 window = mediator.getMostRecentWindow("navigator:browser")
|
|
|
30 return window.document.commandDispatcher
|
|
|
31
|
|
|
32 def cmd_info(ensoapi):
|
|
|
33 thing = getCommandDispatcher()
|
|
|
34
|
|
|
35 thing._build_all_supported_interfaces_()
|
|
|
36 lines = []
|
|
|
37 for iname in thing._interface_names_:
|
|
|
38 methods = []
|
|
|
39 properties = []
|
|
|
40 for mname in thing._interface_names_[iname]._method_infos_:
|
|
|
41 if mname != "QueryInterface":
|
|
|
42 methods.append( "%s()" % mname )
|
|
|
43 for pname in thing._interface_names_[iname]._property_getters_:
|
|
|
44 properties.append( "%s" % pname )
|
|
|
45 lines.append("%s:" % iname)
|
|
|
46 if methods:
|
|
|
47 lines.extend([" METHODS: %s" % ", ".join(methods)])
|
|
|
48 if properties:
|
|
|
49 lines.extend([" PROPERTIES: %s" % ", ".join(properties)])
|
|
|
50
|
|
|
51 ensoapi.set_selection( {"text" : "\n\n".join(lines)} )
|
|
|
52
|
|
|
53 def cmd_highlight(ensoapi):
|
|
|
54 """
|
|
|
55 Highlights your current selection.
|
|
|
56 """
|
|
|
57
|
|
|
58 window = getCommandDispatcher().focusedWindow
|
|
|
59 document = window.document
|
|
|
60 sel = window.getSelection()
|
|
|
61 if sel.rangeCount >= 1:
|
|
|
62 range = sel.getRangeAt(0)
|
|
|
63 newNode = document.createElement("span")
|
|
|
64 newNode.style.background = "yellow"
|
|
|
65 range.surroundContents(newNode)
|
|
|
66
|
|
|
67 def cmd_count_lines(ensoapi):
|
|
|
68 seldict = ensoapi.get_selection()
|
|
|
69 ensoapi.display_message( "Selection is %s lines." %
|
|
|
70 len(seldict.get("text","").splitlines()) )
|
|
|
71
|
|
|
72 def _get_filelike_timestamp():
|
|
|
73 import time
|
|
|
74
|
|
|
75 return time.strftime("%Y%m%d%H%M%S")
|
|
|
76
|
|
|
77 def _get_clipboard_img_datafile():
|
|
|
78 import AppKit
|
|
|
79
|
|
|
80 pb = AppKit.NSPasteboard.generalPasteboard()
|
|
|
81 if pb.availableTypeFromArray_([AppKit.NSTIFFPboardType]):
|
|
|
82 bytes = pb.dataForType_(AppKit.NSTIFFPboardType).bytes()
|
|
|
83 datafile = StringIO(str(bytes))
|
|
|
84 return datafile
|
|
|
85 else:
|
|
|
86 return None
|
|
|
87
|
|
|
88 def image_command(func):
|
|
|
89 def wrapper(ensoapi):
|
|
|
90 import Image
|
|
|
91
|
|
|
92 datafile = _get_clipboard_img_datafile()
|
|
|
93 if datafile:
|
|
|
94 img = Image.open(datafile)
|
|
|
95 return func(ensoapi, img)
|
|
|
96 else:
|
|
|
97 files = ensoapi.get_selection().get("files", [])
|
|
|
98 if files:
|
|
|
99 if len(files) == 1:
|
|
|
100 filename = files[0]
|
|
|
101 img = None
|
|
|
102 try:
|
|
|
103 img = Image.open(filename)
|
|
|
104 except IOError, e:
|
|
|
105 ensoapi.display_message("An error occurred: %s." % e)
|
|
|
106 if img:
|
|
|
107 return func(ensoapi, img)
|
|
|
108 else:
|
|
|
109 ensoapi.display_message("More than one file selected.")
|
|
|
110 else:
|
|
|
111 ensoapi.display_message("No image in clipboard, and no "
|
|
|
112 "file selected.")
|
|
|
113 return wrapper
|
|
|
114
|
|
|
115 @image_command
|
|
|
116 def cmd_get_image_size(ensoapi, img):
|
|
|
117 outputfile = StringIO()
|
|
|
118 img.save(outputfile, "PNG")
|
|
|
119 png_size = outputfile.tell()
|
|
|
120 outputfile = StringIO()
|
|
|
121 img.save(outputfile, "JPEG", quality=90)
|
|
|
122 jpg_size = outputfile.tell()
|
|
|
123 ensoapi.display_message("png size: %d bytes. jpg-90 size: %d bytes." %
|
|
|
124 (png_size, jpg_size))
|
|
|
125
|
|
|
126 def cmd_unupload_image(ensoapi):
|
|
|
127 url = ensoapi.get_selection().get("text", "")
|
|
|
128 if url:
|
|
|
129 if url.startswith(REMOTE_UPLOAD_URL):
|
|
|
130 filename = url[len(REMOTE_UPLOAD_URL):]
|
|
|
131 localfile = os.path.join(LOCAL_UPLOAD_DIR, filename)
|
|
|
132 # It's just easier to upload a truncated file than it is
|
|
|
133 # to remove the file remotely.
|
|
|
134 open(localfile, "w").close()
|
|
|
135 popen = subprocess.Popen(
|
|
|
136 ["scp",
|
|
|
137 localfile,
|
|
|
138 "%s%s" % (REMOTE_UPLOAD_DIR, filename)]
|
|
|
139 )
|
|
|
140 while popen.poll() is None:
|
|
|
141 yield
|
|
|
142 if popen.returncode == 0:
|
|
|
143 os.remove(localfile)
|
|
|
144 ensoapi.display_message("Image removed.")
|
|
|
145 else:
|
|
|
146 ensoapi.display_message("An error occurred.")
|
|
|
147 else:
|
|
|
148 ensoapi.display_message("URL is not an upload URL.")
|
|
|
149 else:
|
|
|
150 ensoapi.display_message("No selection!")
|
|
|
151
|
|
|
152 LOCAL_UPLOAD_DIR = "/Users/varmaa/Archive/toolness-images/"
|
|
|
153 REMOTE_UPLOAD_DIR = "toolness.com:/home/varmaa/toolness.com/images/"
|
|
|
154 REMOTE_UPLOAD_URL = "http://www.toolness.com/images/"
|
|
|
155
|
|
|
156 @image_command
|
|
|
157 def cmd_upload_image(ensoapi, img):
|
|
|
158 filename = "%s.jpg" % _get_filelike_timestamp()
|
|
|
159 localfile = os.path.join(LOCAL_UPLOAD_DIR, filename)
|
|
|
160 img.save(localfile, quality=90)
|
|
|
161
|
|
|
162 ensoapi.display_message("Uploading image...")
|
|
|
163
|
|
|
164 popen = subprocess.Popen(
|
|
|
165 ["scp",
|
|
|
166 localfile,
|
|
|
167 "%s%s" % (REMOTE_UPLOAD_DIR, filename)]
|
|
|
168 )
|
|
|
169 while popen.poll() is None:
|
|
|
170 yield
|
|
|
171 if popen.returncode == 0:
|
|
|
172 webbrowser.open("%s%s" % (REMOTE_UPLOAD_URL, filename))
|
|
|
173 else:
|
|
|
174 ensoapi.display_message("An error occurred.")
|
|
|
175
|
|
|
176 class ThreadedFunc(threading.Thread):
|
|
|
177 def __init__(self, target):
|
|
|
178 self.__target = target
|
|
|
179 threading.Thread.__init__(self)
|
|
|
180 self.__success = False
|
|
|
181 self.__retval = None
|
|
|
182 self.start()
|
|
|
183
|
|
|
184 def run(self):
|
|
|
185 self.__retval = self.__target()
|
|
|
186 self.__success = True
|
|
|
187
|
|
|
188 def wasSuccessful(self):
|
|
|
189 if self.isAlive():
|
|
|
190 raise Exception( "Thread not finished" )
|
|
|
191 return self.__success
|
|
|
192
|
|
|
193 def getRetval(self):
|
|
|
194 if self.isAlive():
|
|
|
195 raise Exception( "Thread not finished" )
|
|
|
196 return self.__retval
|
|
|
197
|
|
|
198 def htmlifier(func):
|
|
|
199 def wrapper(ensoapi):
|
|
|
200 seldict = ensoapi.get_selection()
|
|
|
201 text = seldict.get("text", "")
|
|
|
202 html = seldict.get("html", text)
|
|
|
203 if not text:
|
|
|
204 ensoapi.display_message("No selection!")
|
|
|
205 else:
|
|
|
206 result = func(ensoapi, html)
|
|
|
207 ensoapi.set_selection(
|
|
|
208 {"html":result,
|
|
|
209 "text":result}
|
|
|
210 )
|
|
|
211
|
|
|
212 return wrapper
|
|
|
213
|
|
|
214 @htmlifier
|
|
|
215 def cmd_bold(ensoapi, text):
|
|
|
216 return "<b>%s</b>" % text
|
|
|
217
|
|
|
218 @htmlifier
|
|
|
219 def cmd_italics(ensoapi, text):
|
|
|
220 return "<i>%s</i>" % text
|
|
|
221
|
|
|
222 @htmlifier
|
|
|
223 def cmd_monospace(ensoapi, text):
|
|
|
224 return "<pre>%s</pre>" % text
|
|
|
225
|
|
|
226 def cmd_normalize(ensoapi):
|
|
|
227 normal_template = "<span style=\"font-weight: normal;\">%s</span>"
|
|
|
228 seldict = ensoapi.get_selection()
|
|
|
229 text = seldict.get("text", "")
|
|
|
230 if not text:
|
|
|
231 ensoapi.display_message("No selection!")
|
|
|
232 else:
|
|
|
233 ensoapi.set_selection(
|
|
|
234 {"html":normal_template % text,
|
|
|
235 "text":text} )
|
|
|
236
|
|
|
237 def cmd_paste_html(ensoapi):
|
|
|
238 ensoapi.set_selection(
|
|
|
239 {"text":"u do not support html.",
|
|
|
240 "html":"<p>hai2u, <i>u support html</i>!</p>"}
|
|
|
241 )
|
|
|
242
|
|
|
243 def cmd_get_pb_info(ensoapi):
|
|
|
244 import AppKit
|
|
|
245
|
|
|
246 pb = AppKit.NSPasteboard.generalPasteboard()
|
|
|
247
|
|
|
248 pbtypes = pb.types()
|
|
|
249 for string in pbtypes:
|
|
|
250 print "type: %s" % string
|
|
|
251
|
|
|
252 def make_get_url_func(url):
|
|
|
253 def get_url():
|
|
|
254 import urllib2
|
|
|
255
|
|
|
256 f = urllib2.urlopen(url)
|
|
|
257 return f.read()
|
|
|
258 return get_url
|
|
|
259
|
|
|
260 def get_weather(xml_data):
|
|
|
261 """
|
|
|
262 Shows the weather for the given place.
|
|
|
263 """
|
|
|
264
|
|
|
265 import elementtree.ElementTree as ET
|
|
|
266
|
|
|
267 page = ET.fromstring(xml_data)
|
|
|
268
|
|
|
269 weather = page.find( "weather/current_conditions" )
|
|
|
270
|
|
|
271 return {
|
|
|
272 'f' : weather.find( "temp_f" ).get( "data" ),
|
|
|
273 'c' : weather.find( "temp_c" ).get( "data" ),
|
|
|
274 'humidity' : weather.find( "humidity" ).get( "data" ),
|
|
|
275 'wind' : weather.find( "wind_condition" ).get( "data" )
|
|
|
276 }
|
|
|
277
|
|
|
278 def test_get_weather():
|
|
|
279 xml_data = """<?xml version="1.0"?><xml_api_reply version="1"><weather module_id="0" tab_id="0"><forecast_information><city data="Chicago, IL"/><postal_code data="60657"/><latitude_e6 data=""/><longitude_e6 data=""/><forecast_date data="2008-04-07"/><current_date_time data="2008-04-07 06:38:00 +0000"/><unit_system data="US"/></forecast_information><current_conditions><condition data="Cloudy"/><temp_f data="57"/><temp_c data="14"/><humidity data="Humidity: 47%"/><icon data="/images/weather/cloudy.gif"/><wind_condition data="Wind: N at 0 mph"/></current_conditions><forecast_conditions><day_of_week data="Today"/><low data="40"/><high data="56"/><icon data="/images/weather/cloudy.gif"/><condition data="Cloudy"/></forecast_conditions><forecast_conditions><day_of_week data="Tue"/><low data="45"/><high data="54"/><icon data="/images/weather/thunderstorm.gif"/><condition data="Thunderstorm"/></forecast_conditions><forecast_conditions><day_of_week data="Wed"/><low data="40"/><high data="54"/><icon data="/images/weather/mostly_sunny.gif"/><condition data="Partly Sunny"/></forecast_conditions><forecast_conditions><day_of_week data="Thu"/><low data="38"/><high data="49"/><icon data="/images/weather/chance_of_rain.gif"/><condition data="Chance of Showers"/></forecast_conditions></weather></xml_api_reply>"""
|
|
|
280
|
|
|
281 assert get_weather(xml_data) == {'c': '14', 'humidity': 'Humidity: 47%', 'wind': 'Wind: N at 0 mph', 'f': '57'}
|
|
|
282
|
|
|
283 def cmd_weather(ensoapi, place="san francisco"):
|
|
|
284 zipcode = cmd_weather.places[place]
|
|
|
285 url = "http://www.google.com/ig/api?weather=%s" % zipcode
|
|
|
286 thread = ThreadedFunc(make_get_url_func(url))
|
|
|
287 while thread.isAlive():
|
|
|
288 yield
|
|
|
289 weather_xml = thread.getRetval()
|
|
|
290 if not weather_xml:
|
|
|
291 ensoapi.display_message("An error occurred when getting the weather.")
|
|
|
292 else:
|
|
|
293 wdict = get_weather(weather_xml)
|
|
|
294 wdict["place"] = place
|
|
|
295 ensoapi.display_message(u"In %(place)s it is "
|
|
|
296 u"%(f)s\u00b0F/%(c)s\u00b0C, "
|
|
|
297 u"%(humidity)s, %(wind)s." % wdict)
|
|
|
298
|
|
|
299 cmd_weather.places = { "san francisco" : "94115",
|
|
|
300 "chicago" : "60640",
|
|
|
301 "mountain view" : "94043" }
|
|
|
302
|
|
|
303 cmd_weather.valid_args = cmd_weather.places.keys()
|
|
|
304
|
|
|
305 def cmd_what_is_my_ip(ensoapi):
|
|
|
306 thread = ThreadedFunc(make_get_url_func("http://www.toolness.com/ip/"))
|
|
|
307 while thread.isAlive():
|
|
|
308 yield
|
|
|
309 ensoapi.display_message("%s." % thread.getRetval())
|
|
|
310
|
|
|
311 def cmd_character_count(ensoapi):
|
|
|
312 text = ensoapi.get_selection().get("text", "").strip()
|
|
|
313 if not text:
|
|
|
314 ensoapi.display_message( "No selection." )
|
|
|
315 ensoapi.display_message( "%d characters." % len(text) )
|
|
|
316
|
|
|
317 def cmd_email_to_me(ensoapi):
|
|
|
318 text = ensoapi.get_selection().get("text", "").strip()
|
|
|
319 if not text:
|
|
|
320 ensoapi.display_message( "No selection." )
|
|
|
321 else:
|
|
|
322 server = "mail.toolness.com"
|
|
|
323 port = 587
|
|
|
324 username = "no-reply@toolness.com"
|
|
|
325 password = "4p5o3j45ot%$"
|
|
|
326
|
|
|
327 mailfrom = "varmaa@gmail.com"
|
|
|
328 rcpttos = ["varmaa@gmail.com"]
|
|
|
329
|
|
|
330 text = text.encode("ascii", "xmlcharrefreplace")
|
|
|
331 subject = text.splitlines()[0]
|
|
|
332 text = ("This message was sent by Enso's "
|
|
|
333 "'email to' command.\n\n" + text)
|
|
|
334 data = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s" % \
|
|
|
335 (mailfrom, ", ".join(rcpttos), subject, text)
|
|
|
336
|
|
|
337 def sendmail():
|
|
|
338 import smtplib
|
|
|
339
|
|
|
340 try:
|
|
|
341 svr = smtplib.SMTP( server, port )
|
|
|
342 svr.login( username, password )
|
|
|
343 svr.sendmail( mailfrom, rcpttos, data )
|
|
|
344 svr.quit()
|
|
|
345 except:
|
|
|
346 success[0] = False
|
|
|
347 raise
|
|
|
348
|
|
|
349 thread = ThreadedFunc(sendmail)
|
|
|
350 ensoapi.display_message( "Sending message..." )
|
|
|
351 while thread.isAlive():
|
|
|
352 yield
|
|
|
353 if thread.wasSuccessful():
|
|
|
354 ensoapi.display_message( "Message sent." )
|
|
|
355 else:
|
|
|
356 ensoapi.display_message(
|
|
|
357 "An error occurred when sending the message."
|
|
|
358 )
|
|
|
359
|
|
|
360 def cmd_date(ensoapi):
|
|
|
361 import time
|
|
|
362
|
|
|
363 ensoapi.display_message( "%s" % time.asctime() )
|
|
|
364
|
|
|
365 def cmd_insert_date(ensoapi):
|
|
|
366 import time
|
|
|
367
|
|
|
368 ensoapi.set_selection( time.asctime() )
|
|
|
369
|
|
|
370 class WebSearchCmd(object):
|
|
|
371 def __init__(self, url_template):
|
|
|
372 self._url_template = url_template
|
|
|
373
|
|
|
374 def __call__(self, ensoapi, query=None):
|
|
|
375 if not query:
|
|
|
376 query = ensoapi.get_selection().get("text", u"")
|
|
|
377 query = query.strip()
|
|
|
378
|
|
|
379 if not query:
|
|
|
380 ensoapi.display_message( "No query." )
|
|
|
381 return
|
|
|
382
|
|
|
383 query = urllib.quote( query.encode("utf-8") )
|
|
|
384
|
|
|
385 webbrowser.open( self._url_template % {"query" : query} )
|
|
|
386
|
|
|
387 cmd_wiki = WebSearchCmd("http://en.wikipedia.org/wiki/%(query)s")
|
|
|
388 cmd_wowhead = WebSearchCmd("http://www.wowhead.com/?search=%(query)s")
|
|
|
389 cmd_amaz = WebSearchCmd("http://www.amazon.com/exec/obidos/search-handle-url/index%%3Dblended%%26field-keywords%%3D%(query)s%%26store-name%%3Dall-product-search")
|
|
|
390 cmd_yp = WebSearchCmd("http://local.google.com/local?sc=1&q=%(query)s&near=2418+washington+94115&btnG=Google+Search")
|
|
|
391 cmd_imdb = WebSearchCmd("http://www.imdb.com/find?s=all&q=%(query)s&x=0&y=0")
|
|
|
392 cmd_mdc = WebSearchCmd("http://www.google.com/search?hl=en&q=%(query)s+site%%3Adeveloper.mozilla.org&btnG=Google+Search")
|
|
|
393 cmd_mxr = WebSearchCmd("http://mxr.mozilla.org/mozilla/search?string=%(query)s")
|
|
|
394 cmd_phonebook = WebSearchCmd("https://ldap.mozilla.org/phonebook/search.php?search=%(query)s")
|
|
|
395
|
|
|
396 # For help on this one see http://www.squarefree.com/bugzilla/quicksearch-help.html
|
|
|
397 cmd_bugzilla = WebSearchCmd("https://bugzilla.mozilla.org/buglist.cgi?quicksearch=%(query)s")
|
|
|
398
|
|
|
399 def cmd_farewell(ensoapi):
|
|
|
400 import AppKit
|
|
|
401
|
|
|
402 app = AppKit.NSApplication.sharedApplication()
|
|
|
403 app.terminate_(None)
|
|
|
404
|
|
|
405 class Launcher(object):
|
|
|
406 def __init__(self):
|
|
|
407 import Foundation
|
|
|
408 import AppKit
|
|
|
409
|
|
|
410 self._targets = {}
|
|
|
411
|
|
|
412 query = Foundation.NSMetadataQuery.alloc().init()
|
|
|
413 queryString = ( "((kMDItemKind == \"Application\") "
|
|
|
414 " and (kMDItemSupportFileType != \"MDSystemFile\"))" )
|
|
|
415 queryString += " or (kMDItemKind == \"Mac OS X Preference Pane\")"
|
|
|
416 predicate = Foundation.NSPredicate.predicateWithFormat_(
|
|
|
417 queryString
|
|
|
418 )
|
|
|
419 query.setPredicate_( predicate )
|
|
|
420 if query.startQuery() != True:
|
|
|
421 raise Exception( "startQuery() failed." )
|
|
|
422 self._query = query
|
|
|
423 self._workspace = AppKit.NSWorkspace.sharedWorkspace()
|
|
|
424 self._targets = {}
|
|
|
425
|
|
|
426 def get_namespace(self):
|
|
|
427 return self._targets.keys()
|
|
|
428
|
|
|
429 def get_target(self, name):
|
|
|
430 return self._targets[name]
|
|
|
431
|
|
|
432 def update(self):
|
|
|
433 query = self._query
|
|
|
434
|
|
|
435 while query.isGathering():
|
|
|
436 yield
|
|
|
437
|
|
|
438 # TODO: Modify this so we just get notified whenever the query
|
|
|
439 # results change instead of constantly "polling" every time
|
|
|
440 # the quasimode starts.
|
|
|
441
|
|
|
442 resultList = []
|
|
|
443 targets = {}
|
|
|
444
|
|
|
445 query.disableUpdates()
|
|
|
446 numresults = query.resultCount()
|
|
|
447
|
|
|
448 BATCH_SIZE = 10
|
|
|
449
|
|
|
450 for i in range( numresults ):
|
|
|
451 result = query.resultAtIndex_( i )
|
|
|
452 fsname = result.valueForAttribute_("kMDItemFSName")
|
|
|
453 name = result.valueForAttribute_("kMDItemDisplayName")
|
|
|
454 kind = result.valueForAttribute_("kMDItemKind")
|
|
|
455 if name:
|
|
|
456 name = name.lower()
|
|
|
457 itempath = result.valueForAttribute_("kMDItemPath")
|
|
|
458 if kind == "Mac OS X Preference Pane":
|
|
|
459 name += " preferences"
|
|
|
460 target = ShellOpenLaunchableTarget(itempath)
|
|
|
461 else:
|
|
|
462 target = AppLaunchableTarget(self._workspace, itempath)
|
|
|
463 resultList.append(name)
|
|
|
464 targets[name] = target
|
|
|
465 if i / BATCH_SIZE == i / float(BATCH_SIZE):
|
|
|
466 yield
|
|
|
467 #print "total results: %s" % numresults
|
|
|
468 query.enableUpdates()
|
|
|
469 targets["computer"] = ShellOpenLaunchableTarget("/")
|
|
|
470 self._targets = targets
|
|
|
471
|
|
|
472 class AppLaunchableTarget(object):
|
|
|
473 def __init__(self, workspace, path):
|
|
|
474 self._workspace = workspace
|
|
|
475 self._path = path
|
|
|
476
|
|
|
477 def launch(self, with_files=None):
|
|
|
478 if with_files:
|
|
|
479 for filename in with_files:
|
|
|
480 self._workspace.openFile_withApplication_(
|
|
|
481 filename,
|
|
|
482 self._path
|
|
|
483 )
|
|
|
484 else:
|
|
|
485 self._workspace.launchApplication_( self._path )
|
|
|
486
|
|
|
487 def can_launch_with(self):
|
|
|
488 return True
|
|
|
489
|
|
|
490 class ShellOpenLaunchableTarget(object):
|
|
|
491 def __init__(self, path):
|
|
|
492 self._path = path
|
|
|
493
|
|
|
494 def launch(self):
|
|
|
495 subprocess.Popen( ["open", self._path] )
|
|
|
496
|
|
|
497 def can_launch_with(self):
|
|
|
498 return False
|
|
|
499
|
|
|
500 class OpenCommand(object):
|
|
|
501 """
|
|
|
502 Opens an application, folder, or URL.
|
|
|
503 """
|
|
|
504
|
|
|
505 def __init__(self, launcher):
|
|
|
506 self.launcher = launcher
|
|
|
507 self._isFetchingArgs = False
|
|
|
508
|
|
|
509 def on_quasimode_start(self):
|
|
|
510 if self._isFetchingArgs:
|
|
|
511 return
|
|
|
512
|
|
|
513 self._isFetchingArgs = True
|
|
|
514
|
|
|
515 for _ in self.launcher.update():
|
|
|
516 yield
|
|
|
517
|
|
|
518 self.valid_args = self.launcher.get_namespace()
|
|
|
519
|
|
|
520 self._isFetchingArgs = False
|
|
|
521
|
|
|
522 valid_args = []
|
|
|
523
|
|
|
524 def __call__(self, ensoapi, target=None):
|
|
|
525 if not target:
|
|
|
526 seldict = ensoapi.get_selection()
|
|
|
527 if seldict.get("files"):
|
|
|
528 for file in seldict["files"]:
|
|
|
529 subprocess.Popen( ["open", file] )
|
|
|
530 elif seldict.get("text"):
|
|
|
531 filename = seldict["text"].strip()
|
|
|
532 if os.path.isabs(filename):
|
|
|
533 subprocess.Popen( ["open", filename] )
|
|
|
534 else:
|
|
|
535 webbrowser.open(filename)
|
|
|
536 else:
|
|
|
537 self.launcher.get_target(target).launch()
|
|
|
538
|
|
|
539 class OpenWithCommand(object):
|
|
|
540 """
|
|
|
541 Opens the selected file(s) with a particular application.
|
|
|
542 """
|
|
|
543
|
|
|
544 def __init__(self, launcher):
|
|
|
545 self.launcher = launcher
|
|
|
546
|
|
|
547 def _get_valid_args(self):
|
|
|
548 return self.launcher.get_namespace()
|
|
|
549
|
|
|
550 valid_args = property(_get_valid_args)
|
|
|
551
|
|
|
552 def __call__(self, ensoapi, target):
|
|
|
553 files = ensoapi.get_selection().get("files", [])
|
|
|
554 targ = self.launcher.get_target(target)
|
|
|
555 if not files:
|
|
|
556 ensoapi.display_message("No files selected!")
|
|
|
557 elif not targ.can_launch_with():
|
|
|
558 ensoapi.display_message("Can't open files with %s." % target)
|
|
|
559 else:
|
|
|
560 targ.launch(files)
|
|
|
561
|
|
|
562 cmd_go = OpenCommand(Launcher())
|
|
|
563 cmd_open = cmd_go
|
|
|
564 cmd_bust_with = OpenWithCommand(cmd_open.launcher)
|
|
|
565
|
|
|
566 def cmd_run_python(ensoapi):
|
|
|
567 """
|
|
|
568 runs the selected text as python code.
|
|
|
569 """
|
|
|
570
|
|
|
571 text = ensoapi.get_selection().get("text","")
|
|
|
572
|
|
|
573 if not text:
|
|
|
574 ensoapi.display_message("No text selection!")
|
|
|
575 return
|
|
|
576
|
|
|
577 output_fd, output_name = tempfile.mkstemp()
|
|
|
578
|
|
|
579 # TODO: This is for OSX only; will have to figure out what to do
|
|
|
580 # for other platforms.
|
|
|
581 cmd = text.replace( "\r", "\n" )
|
|
|
582
|
|
|
583 try:
|
|
|
584 compile( cmd, "<selected text>", "eval" )
|
|
|
585 is_eval = True
|
|
|
586 except:
|
|
|
587 is_eval = False
|
|
|
588
|
|
|
589 if is_eval:
|
|
|
590 cmd = "print %s," % cmd
|
|
|
591
|
|
|
592 cmd = ("try:\n"
|
|
|
593 " from autoimp import *\n"
|
|
|
594 "except ImportError:\n"
|
|
|
595 " pass\n\n" + cmd )
|
|
|
596
|
|
|
597 popen = subprocess.Popen(
|
|
|
598 [ sys.executable,
|
|
|
599 "-c", cmd ],
|
|
|
600 stdout = output_fd,
|
|
|
601 stderr = subprocess.STDOUT,
|
|
|
602 )
|
|
|
603
|
|
|
604 while popen.poll() is None:
|
|
|
605 yield
|
|
|
606
|
|
|
607 os.close(output_fd)
|
|
|
608
|
|
|
609 output_text = open(output_name, "r").read().strip()
|
|
|
610 if output_text:
|
|
|
611 seldict = {"text" : "\n".join([text, output_text])}
|
|
|
612 ensoapi.set_selection(seldict)
|
|
|
613 else:
|
|
|
614 if popen.returncode == 0:
|
|
|
615 ensoapi.display_message("Code run successfully.")
|
|
|
616 else:
|
|
|
617 ensoapi.display_message("An error occurred.")
|
|
|
618
|
|
|
619 os.remove(output_name)
|
|
|
620
|
|
|
621 def cmd_doctest(ensoapi):
|
|
|
622 """
|
|
|
623 python doctests the selected section of plain text.
|
|
|
624 """
|
|
|
625
|
|
|
626 text = ensoapi.get_selection().get("text","")
|
|
|
627
|
|
|
628 if not text:
|
|
|
629 ensoapi.display_message("No text selection!")
|
|
|
630 return
|
|
|
631
|
|
|
632 # TODO: This is for OSX only; will have to figure out what to do
|
|
|
633 # for other platforms.
|
|
|
634 new_text = text.replace( "\r", "\n" )
|
|
|
635
|
|
|
636 fd, source_name = tempfile.mkstemp()
|
|
|
637 os.close(fd)
|
|
|
638 open(source_name, "wb").write(new_text)
|
|
|
639
|
|
|
640 output_fd, output_name = tempfile.mkstemp()
|
|
|
641
|
|
|
642 cmd = ("import doctest; doctest.testfile(%s, "
|
|
|
643 "module_relative=False)" % repr(source_name))
|
|
|
644
|
|
|
645 popen = subprocess.Popen(
|
|
|
646 [ sys.executable,
|
|
|
647 "-c", cmd ],
|
|
|
648 stdout = output_fd,
|
|
|
649 stderr = subprocess.STDOUT,
|
|
|
650 )
|
|
|
651
|
|
|
652 while popen.poll() is None:
|
|
|
653 yield
|
|
|
654
|
|
|
655 os.close(output_fd)
|
|
|
656
|
|
|
657 if popen.returncode == 0:
|
|
|
658 output_text = open(output_name, "r").read()
|
|
|
659 if output_text:
|
|
|
660 seldict = {"text":text + output_text}
|
|
|
661 ensoapi.set_selection(seldict)
|
|
|
662 else:
|
|
|
663 ensoapi.display_message("All doctests successful!")
|
|
|
664 else:
|
|
|
665 ensoapi.display_message("An error occurred.")
|
|
|
666
|
|
|
667 os.remove(source_name)
|
|
|
668 os.remove(output_name)
|
|
|
669
|
|
|
670 def cmd_nosetest(ensoapi):
|
|
|
671 """
|
|
|
672 runs nosetests on the selected region of python code.
|
|
|
673 """
|
|
|
674
|
|
|
675 text = ensoapi.get_selection().get("text","")
|
|
|
676
|
|
|
677 if not text:
|
|
|
678 ensoapi.display_message("No text selection!")
|
|
|
679 return
|
|
|
680
|
|
|
681 # TODO: This is for OSX only; will have to figure out what to do
|
|
|
682 # for other platforms.
|
|
|
683 new_text = text.replace( "\r", "\n" )
|
|
|
684
|
|
|
685 fd, source_name = tempfile.mkstemp(suffix=".py")
|
|
|
686 os.close(fd)
|
|
|
687 open(source_name, "wb").write(new_text)
|
|
|
688
|
|
|
689 output_fd, output_name = tempfile.mkstemp()
|
|
|
690
|
|
|
691 popen = subprocess.Popen(
|
|
|
692 [ "nosetests",
|
|
|
693 source_name,
|
|
|
694 "--with-doctest" ],
|
|
|
695 stdout = output_fd,
|
|
|
696 stderr = subprocess.STDOUT,
|
|
|
697 )
|
|
|
698
|
|
|
699 while popen.poll() is None:
|
|
|
700 yield
|
|
|
701
|
|
|
702 os.close(output_fd)
|
|
|
703
|
|
|
704 output_text = open(output_name, "r").read()
|
|
|
705 if output_text:
|
|
|
706 if popen.returncode == 0:
|
|
|
707 lines = output_text.splitlines()
|
|
|
708 ensoapi.display_message(lines[2])
|
|
|
709 else:
|
|
|
710 seldict = {"text":text + output_text}
|
|
|
711 ensoapi.set_selection(seldict)
|
|
|
712 else:
|
|
|
713 raise AssertionError( "nosetests didn't return anything!" )
|
|
|
714
|
|
|
715 os.remove(source_name)
|
|
|
716 os.remove(output_name)
|
|
|
717
|
|
|
718 def cmd_insert_html(ensoapi):
|
|
|
719 ensoapi.set_selection( {"html":"<b>hi</b> <p>there</p>"} )
|
|
|
720
|
|
|
721 def _runAppleScript( script ):
|
|
|
722 params = [ "osascript", "-e", script ]
|
|
|
723 popen = subprocess.Popen( params )
|
|
|
724
|
|
|
725 def cmd_screen_saver(ensoapi):
|
|
|
726 """
|
|
|
727 Starts your screen saver.
|
|
|
728 """
|
|
|
729
|
|
|
730 _runAppleScript(
|
|
|
731 "tell application id \"com.apple.ScreenSaver.Engine\" "
|
|
|
732 "to launch"
|
|
|
733 )
|
|
|
734
|
|
|
735 def cmd_sleep(ensoapi):
|
|
|
736 """
|
|
|
737 Puts your computer to sleep.
|
|
|
738 """
|
|
|
739
|
|
|
740 _runAppleScript(
|
|
|
741 "tell application \"Finder\" to sleep"
|
|
|
742 )
|
|
|
743
|
|
|
744 def cmd_play(ensoapi):
|
|
|
745 """
|
|
|
746 Plays the current iTunes song.
|
|
|
747 """
|
|
|
748
|
|
|
749 _runAppleScript(
|
|
|
750 "tell application \"iTunes\" to play"
|
|
|
751 )
|
|
|
752
|
|
|
753 def cmd_pause(ensoapi):
|
|
|
754 """
|
|
|
755 Pauses the current iTunes song.
|
|
|
756 """
|
|
|
757
|
|
|
758 _runAppleScript(
|
|
|
759 "tell application \"iTunes\" to pause"
|
|
|
760 )
|
|
|
761
|
|
|
762
|
|
|
763 def cmd_next_track(ensoapi):
|
|
|
764 """
|
|
|
765 Goes to the next track on iTunes.
|
|
|
766 """
|
|
|
767
|
|
|
768 _runAppleScript(
|
|
|
769 "tell application \"iTunes\" to next track"
|
|
|
770 )
|
|
|
771
|
|
|
772 def cmd_previous_track(ensoapi):
|
|
|
773 """
|
|
|
774 Goes to the previous track on iTunes.
|
|
|
775 """
|
|
|
776
|
|
|
777 _runAppleScript(
|
|
|
778 "tell application \"iTunes\" to back track"
|
|
|
779 )
|
|
|
780
|
|
|
781 KIRITSU_DIR = "/Users/varmaa/Documents/kiritsu"
|
|
|
782 KIRITSU_MAKE_SCRIPT = "%s/MakeEverything.py" % KIRITSU_DIR
|
|
|
783 KIRITSU_VIEW_TEMPLATE = "file://%s/%s.html"
|
|
|
784 KIRITSU_VIEWS = ["work", "play", "chores"]
|
|
|
785
|
|
|
786 def cmd_refresh_kiritsu(ensoapi):
|
|
|
787 """
|
|
|
788 Refreshes all kiritsu feeds.
|
|
|
789 """
|
|
|
790
|
|
|
791 popen = subprocess.Popen(
|
|
|
792 [sys.executable,
|
|
|
793 KIRITSU_MAKE_SCRIPT],
|
|
|
794 cwd = KIRITSU_DIR
|
|
|
795 )
|
|
|
796
|
|
|
797 ensoapi.display_message( "Please wait while kiritsu retrieves "
|
|
|
798 "new feeds." )
|
|
|
799
|
|
|
800 while popen.poll() is None:
|
|
|
801 yield
|
|
|
802
|
|
|
803 if popen.returncode != 0:
|
|
|
804 ensoapi.display_message( "An error occurred in Kiritsu." )
|
|
|
805 else:
|
|
|
806 ensoapi.display_message( "Kiritsu is done." )
|
|
|
807
|
|
|
808 def cmd_view( ensoapi, viewname ):
|
|
|
809 """
|
|
|
810 Opens the given kiritsu view.
|
|
|
811 """
|
|
|
812
|
|
|
813 webbrowser.open( KIRITSU_VIEW_TEMPLATE % (KIRITSU_DIR, viewname) )
|
|
|
814
|
|
|
815 cmd_view.valid_args = KIRITSU_VIEWS
|
|
|
816
|
|
|
817 def cmd_rest(ensoapi):
|
|
|
818 import sys
|
|
|
819
|
|
|
820 ensoapi.display_message( "please wait..." )
|
|
|
821 popen = subprocess.Popen(
|
|
|
822 [ sys.executable,
|
|
|
823 "-c", "import time;time.sleep(2.0)" ]
|
|
|
824 )
|
|
|
825 while popen.poll() is None:
|
|
|
826 yield
|
|
|
827 if popen.returncode == 0:
|
|
|
828 msg = "done!"
|
|
|
829 else:
|
|
|
830 msg = "an error occurred."
|
|
|
831 ensoapi.display_message( msg )
|