-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathwrap_selection_as_link.py
101 lines (87 loc) · 3.08 KB
/
wrap_selection_as_link.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
import sublime, sublime_plugin
import os, sys, re
# import modules in current directory
dist_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, dist_dir)
# Python 2/3 compatible
import chardet, pystache
try:
# Python 3 (ST3)
from urllib.request import Request, urlopen
except ImportError:
# Python 2 (ST2)
from urllib2 import Request, urlopen
def preemptive_imports():
""" needed to ensure ability to import these classes later within functions, due to the way ST2 loads plug-in modules """
from chardet import universaldetector
preemptive_imports()
class WrapSelectionAsLinkCommand(sublime_plugin.TextCommand):
def get_url_title(self, url):
try:
req = Request(url, headers={'User-Agent' : "Sublime Text 2 Hyperlink Helper"})
f = urlopen(req)
url = f.geturl()
content = f.read()
decoded_content = content.decode(chardet.detect(content)['encoding'])
title = re.search(r"<title>([^<>]*)</title>", decoded_content, re.I).group(1)
title = title.strip()
return title
except Exception as e:
sublime.error_message("Error fetching page title: %s" % str(e))
return None
def make_url(self, text):
# convert email addresses to mailto: links
match = re.match(r"^(mailto:)?(.*?@.*\..*)$", text)
if match:
return "mailto:%s" % match.group(2)
else:
# convert Amazon links (possibly containing affiliate codes) to canonical URLs
match = re.match(r"^https?://www.(amazon.(?:com|co.uk|co.jp|ca|fr|de))/.+?/([A-Z0-9]{10})/[-a-zA-Z0-9_./%?=&]+$", text)
if match:
return "http://%s/dp/%s" % (match.group(1), match.group(2))
else:
# pass through other URLs untouched
match = re.match(r"^[a-zA-Z][a-zA-Z0-9.+-]*://.*$", text)
if match:
return text
else:
# add http:// protocol to URLs without them
match = re.match(r"^(www\..*|.*\.(com|net|org|info|[a-z]{2}))$", text)
if match:
return "http://%s" % text
else:
# pass through non-whitespace text unmodified
match = re.match(r"^\S+$", text)
if match:
return text
else:
return "http://example.com/"
def run(self, edit):
nonempty_sels = []
# set aside nonempty selections
for s in reversed(self.view.sel()):
if not s.empty():
nonempty_sels.append(s)
self.view.sel().subtract(s)
# expand remaining (empty) selections to words
self.view.run_command("expand_selection", {"to": "word"})
# add nonempty selections back in
for s in nonempty_sels:
self.view.sel().add(s)
txt = sublime.get_clipboard().strip()
url = self.make_url(txt)
title = None
if re.match(r"^https?://", url) and url != "http://example.com/":
title = { 'title': self.get_url_title(url) }
# apply the links
old_sels = []
for s in (self.view.sel()):
old_sels.append(s)
self.view.sel().clear()
for s in reversed(old_sels):
if not s.empty():
txt = self.view.substr(s)
link = pystache.render(self.view.settings().get('hyperlink_helper_link_format'), {'url': url, 'title?': title, 'input': txt})
self.view.replace(edit, s, link)
pos = s.begin() + len(link)
self.view.sel().add(sublime.Region(pos, pos))