Merge lp:~dcaro/clicompanion/fix-923535 into lp:clicompanion
- fix-923535
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Marek Bardoński | ||||
Approved revision: | 112 | ||||
Merged at revision: | 108 | ||||
Proposed branch: | lp:~dcaro/clicompanion/fix-923535 | ||||
Merge into: | lp:clicompanion | ||||
Prerequisite: | lp:~dcaro/clicompanion/fix-623475 | ||||
Diff against target: |
382 lines (+247/-10) 7 files modified
MANIFEST (+2/-0) clicompanionlib/config.py (+1/-1) clicompanionlib/plugins.py (+41/-1) clicompanionlib/tabs.py (+48/-7) clicompanionlib/view.py (+2/-1) plugins/LaunchpadURL.py (+62/-0) plugins/StandardURLs.py (+91/-0) |
||||
To merge this branch: | bzr merge lp:~dcaro/clicompanion/fix-923535 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Marek Bardoński | Approve | ||
Review via email: mp+90633@code.launchpad.net |
Commit message
Description of the change
Added the urls plugins to allow the user to click on urls to open them, added the standard (http/https/
- 111. By David Caro "<email address hidden>"
-
added new url plugins
David Caro (dcaro) wrote : | # |
You have to go to the plugins configuration and enable them first (that's because the config file is not overwrited if it exists).
So for this to work, just go to Preferences -> Plugins and double click the checkbox of the StandardURLs plugin and LaunchpadURL plugin. After this (inmediatly, you don't need to restart) when you pass the mouse over a recognized url, it will be underscored, in that moment you can press ctrl+click and that will open a tab/window of your preferred browser.
I hope you like it!
Marek Bardoński (bdfhjk) wrote : | # |
OK, thanks for explain. I will try it now.
Marek Bardoński (bdfhjk) wrote : | # |
I found small bugs:
After typing lp:clicompanion and pressing [enter], then created link is '
https:/
created from underlined ' lp:clicompanion: nie znaleziono polecenia \n
user@user-
After typing lp:12312 and pressing [enter], I have two links - one correct
to bug, and one '
https:/
'
- 112. By David Caro "<email address hidden>"
-
The url matching regexp was way too permissive, and incorrect paths were
matched
David Caro (dcaro) wrote : | # |
Fixed, the regexp matching launchpad branches was too permissive and false positives were matched. It should be fixed now (it's a lot more strict, so maybe real urls that have some strange chars in them are not matched correctly, but now most of urls will match).
Also you don't need to hit enter for the url to get underscored ;)
Marek Bardoński (bdfhjk) wrote : | # |
2012/3/4 David Caro <email address hidden>
> Fixed, the regexp matching launchpad branches was too permissive and false
> positives were matched. It should be fixed now (it's a lot more strict, so
> maybe real urls that have some strange chars in them are not matched
> correctly, but now most of urls will match).
>
> Also you don't need to hit enter for the url to get underscored ;)
>
> --
> https:/
> You are reviewing the proposed merge of lp:~dcaro/clicompanion/fix-923535
> into lp:clicompanion.
>
OK, I will test it soon.
Marek Bardoński (bdfhjk) wrote : | # |
Tested - problems solved.
Thanks for implementing nice feature!
Preview Diff
1 | === modified file 'MANIFEST' | |||
2 | --- MANIFEST 2012-01-08 01:37:38 +0000 | |||
3 | +++ MANIFEST 2012-03-04 09:53:18 +0000 | |||
4 | @@ -17,4 +17,6 @@ | |||
5 | 17 | plugins/CommandLineFU.py | 17 | plugins/CommandLineFU.py |
6 | 18 | plugins/__init__.py | 18 | plugins/__init__.py |
7 | 19 | plugins/LocalCommandList.py | 19 | plugins/LocalCommandList.py |
8 | 20 | plugins/StandardURLs.py | ||
9 | 21 | plugins/LaunchpadURL.py | ||
10 | 20 | 22 | ||
11 | 21 | 23 | ||
12 | === modified file 'clicompanionlib/config.py' | |||
13 | --- clicompanionlib/config.py 2012-01-15 14:23:05 +0000 | |||
14 | +++ clicompanionlib/config.py 2012-03-04 09:53:18 +0000 | |||
15 | @@ -60,7 +60,7 @@ | |||
16 | 60 | "update_login_records": ("True", 'bool'), | 60 | "update_login_records": ("True", 'bool'), |
17 | 61 | }, | 61 | }, |
18 | 62 | 'general': {"debug": ('False', 'bool'), | 62 | 'general': {"debug": ('False', 'bool'), |
20 | 63 | "plugins": ('LocalCommandList, CommandLineFU', 'str') | 63 | "plugins": ('LocalCommandList, CommandLineFU, StandardURLs', 'str') |
21 | 64 | }, | 64 | }, |
22 | 65 | 'LocalCommandList': {"cheatsheet": | 65 | 'LocalCommandList': {"cheatsheet": |
23 | 66 | (os.path.expanduser("~/.clicompanion2"), 'str'), | 66 | (os.path.expanduser("~/.clicompanion2"), 'str'), |
24 | 67 | 67 | ||
25 | === modified file 'clicompanionlib/plugins.py' | |||
26 | --- clicompanionlib/plugins.py 2012-01-15 14:23:05 +0000 | |||
27 | +++ clicompanionlib/plugins.py 2012-03-04 09:53:18 +0000 | |||
28 | @@ -47,6 +47,7 @@ | |||
29 | 47 | import sys | 47 | import sys |
30 | 48 | import os | 48 | import os |
31 | 49 | import inspect | 49 | import inspect |
32 | 50 | import webbrowser | ||
33 | 50 | from clicompanionlib.utils import dbg | 51 | from clicompanionlib.utils import dbg |
34 | 51 | 52 | ||
35 | 52 | 53 | ||
36 | @@ -97,7 +98,7 @@ | |||
37 | 97 | if capability in capabilities \ | 98 | if capability in capabilities \ |
38 | 98 | and plugin in self.allowed: | 99 | and plugin in self.allowed: |
39 | 99 | plugins.append((plugin, pclass)) | 100 | plugins.append((plugin, pclass)) |
41 | 100 | dbg('Matching plugin %s for %s' % (plugin, capability)) | 101 | dbg('Matching plugin %s for capability %s' % (plugin, capability)) |
42 | 101 | return plugins | 102 | return plugins |
43 | 102 | 103 | ||
44 | 103 | def get_plugin_conf(self, plugin): | 104 | def get_plugin_conf(self, plugin): |
45 | @@ -207,3 +208,42 @@ | |||
46 | 207 | def __init__(self, config): | 208 | def __init__(self, config): |
47 | 208 | Plugin.__init__(self) | 209 | Plugin.__init__(self) |
48 | 209 | self.config = config | 210 | self.config = config |
49 | 211 | |||
50 | 212 | class URLPlugin(Plugin): | ||
51 | 213 | ''' | ||
52 | 214 | Plugion that matches an url in the screen and executes some action. | ||
53 | 215 | ''' | ||
54 | 216 | __capabilities__ = [ 'URL' ] | ||
55 | 217 | |||
56 | 218 | |||
57 | 219 | def __init__(self, config): | ||
58 | 220 | Plugin.__init__(self) | ||
59 | 221 | self.config = config | ||
60 | 222 | ## This is the regexp that will trigger the callback | ||
61 | 223 | matches = [''] | ||
62 | 224 | |||
63 | 225 | def callback(self, url, matchnum): | ||
64 | 226 | ## When the regexp is found, this function will be called | ||
65 | 227 | pass | ||
66 | 228 | |||
67 | 229 | def open_url(self, url): | ||
68 | 230 | """ | ||
69 | 231 | Open a given URL, generic for all the URL plugins to use | ||
70 | 232 | """ | ||
71 | 233 | oldstyle = False | ||
72 | 234 | if gtk.gtk_version < (2, 14, 0) or \ | ||
73 | 235 | not hasattr(gtk, 'show_uri') or \ | ||
74 | 236 | not hasattr(gtk.gdk, 'CURRENT_TIME'): | ||
75 | 237 | oldstyle = True | ||
76 | 238 | if not oldstyle: | ||
77 | 239 | try: | ||
78 | 240 | gtk.show_uri(None, url, gtk.gdk.CURRENT_TIME) | ||
79 | 241 | except: | ||
80 | 242 | oldstyle = True | ||
81 | 243 | if oldstyle: | ||
82 | 244 | dbg('Old gtk (%s,%s,%s), calling xdg-open' % gtk.gtk_version) | ||
83 | 245 | try: | ||
84 | 246 | subprocess.Popen(["xdg-open", url]) | ||
85 | 247 | except: | ||
86 | 248 | dbg('xdg-open did not work, falling back to webbrowser.open') | ||
87 | 249 | webbrowser.open(url) | ||
88 | 210 | 250 | ||
89 | === modified file 'clicompanionlib/tabs.py' | |||
90 | --- clicompanionlib/tabs.py 2012-01-15 20:40:56 +0000 | |||
91 | +++ clicompanionlib/tabs.py 2012-03-04 09:53:18 +0000 | |||
92 | @@ -42,6 +42,7 @@ | |||
93 | 42 | import clicompanionlib.utils as cc_utils | 42 | import clicompanionlib.utils as cc_utils |
94 | 43 | import clicompanionlib.helpers as cc_helpers | 43 | import clicompanionlib.helpers as cc_helpers |
95 | 44 | import clicompanionlib.preferences as cc_pref | 44 | import clicompanionlib.preferences as cc_pref |
96 | 45 | import clicompanionlib.config as cc_conf | ||
97 | 45 | 46 | ||
98 | 46 | 47 | ||
99 | 47 | class TerminalTab(gtk.ScrolledWindow): | 48 | class TerminalTab(gtk.ScrolledWindow): |
100 | @@ -56,12 +57,15 @@ | |||
101 | 56 | ()), | 57 | ()), |
102 | 57 | } | 58 | } |
103 | 58 | 59 | ||
105 | 59 | def __init__(self, title, config, profile='default', directory=None): | 60 | def __init__(self, title, config, profile='default', directory=None, |
106 | 61 | pluginloader=None): | ||
107 | 60 | gtk.ScrolledWindow.__init__(self) | 62 | gtk.ScrolledWindow.__init__(self) |
108 | 61 | self.config = config | 63 | self.config = config |
109 | 64 | self.pluginloader = pluginloader | ||
110 | 62 | self.title = title | 65 | self.title = title |
111 | 63 | self.profile = 'profile::' + profile | 66 | self.profile = 'profile::' + profile |
112 | 64 | self.vte = vte.Terminal() | 67 | self.vte = vte.Terminal() |
113 | 68 | self.matches = {} | ||
114 | 65 | self.add(self.vte) | 69 | self.add(self.vte) |
115 | 66 | self.vte.connect("child-exited", lambda *x: self.emit('quit')) | 70 | self.vte.connect("child-exited", lambda *x: self.emit('quit')) |
116 | 67 | self.update_records = self.config.getboolean(self.profile, | 71 | self.update_records = self.config.getboolean(self.profile, |
117 | @@ -78,7 +82,7 @@ | |||
118 | 78 | logutmp=self.update_records, | 82 | logutmp=self.update_records, |
119 | 79 | logwtmp=self.update_records, | 83 | logwtmp=self.update_records, |
120 | 80 | loglastlog=self.update_records) | 84 | loglastlog=self.update_records) |
122 | 81 | self.vte.connect("button_press_event", self.copy_paste_menu) | 85 | self.vte.connect("button_press_event", self.on_click) |
123 | 82 | self.update_config() | 86 | self.update_config() |
124 | 83 | self.show_all() | 87 | self.show_all() |
125 | 84 | 88 | ||
126 | @@ -205,8 +209,34 @@ | |||
127 | 205 | 209 | ||
128 | 206 | self.vte.set_allow_bold(config.getboolean(self.profile, 'bold_text')) | 210 | self.vte.set_allow_bold(config.getboolean(self.profile, 'bold_text')) |
129 | 207 | self.vte.set_word_chars(config.get(self.profile, 'sel_word')) | 211 | self.vte.set_word_chars(config.get(self.profile, 'sel_word')) |
132 | 208 | 212 | self.vte.match_clear_all() | |
133 | 209 | def copy_paste_menu(self, vte, event): | 213 | self.load_url_plugins() |
134 | 214 | |||
135 | 215 | def check_for_match(self, event): | ||
136 | 216 | """ | ||
137 | 217 | Check if the mouse is over a URL | ||
138 | 218 | """ | ||
139 | 219 | return (self.vte.match_check(int(event.x / self.vte.get_char_width()), | ||
140 | 220 | int(event.y / self.vte.get_char_height()))) | ||
141 | 221 | |||
142 | 222 | def run_match_callback(self, match): | ||
143 | 223 | url = match[0] | ||
144 | 224 | match = match[1] | ||
145 | 225 | for plg, m_plg in self.matches.items(): | ||
146 | 226 | if match in m_plg[1]: | ||
147 | 227 | dbg('Matched %s for url %s' % (plg, url)) | ||
148 | 228 | matchnum = m_plg[1].index(match) | ||
149 | 229 | m_plg[0].callback(url, matchnum) | ||
150 | 230 | |||
151 | 231 | def on_click(self, vte, event): | ||
152 | 232 | ## left click | ||
153 | 233 | if event.button == 1: | ||
154 | 234 | # Ctrl+leftclick on a URL should open it | ||
155 | 235 | if event.state & gtk.gdk.CONTROL_MASK == gtk.gdk.CONTROL_MASK: | ||
156 | 236 | match = self.check_for_match(event) | ||
157 | 237 | if match: | ||
158 | 238 | self.run_match_callback(match) | ||
159 | 239 | ## Rght click menu | ||
160 | 210 | if event.button == 3: | 240 | if event.button == 3: |
161 | 211 | time = event.time | 241 | time = event.time |
162 | 212 | ## right-click popup menu Copy | 242 | ## right-click popup menu Copy |
163 | @@ -366,6 +396,14 @@ | |||
164 | 366 | self.profile = 'profile::' + profile | 396 | self.profile = 'profile::' + profile |
165 | 367 | self.update_config() | 397 | self.update_config() |
166 | 368 | 398 | ||
167 | 399 | def load_url_plugins(self): | ||
168 | 400 | for pg_name, pg_class in self.pluginloader.get_plugins(['URL']): | ||
169 | 401 | pg_conf = cc_conf.CLIConfigView(pg_name, self.config) | ||
170 | 402 | self.matches[pg_name] = (pg_class(pg_conf), []) | ||
171 | 403 | for match in self.matches[pg_name][0].matches: | ||
172 | 404 | dbg('Adding match %s for plugin %s' % (match, pg_name)) | ||
173 | 405 | self.matches[pg_name][1].append(self.vte.match_add(match)) | ||
174 | 406 | |||
175 | 369 | 407 | ||
176 | 370 | class TerminalsNotebook(gtk.Notebook): | 408 | class TerminalsNotebook(gtk.Notebook): |
177 | 371 | __gsignals__ = { | 409 | __gsignals__ = { |
178 | @@ -375,11 +413,12 @@ | |||
179 | 375 | ()), | 413 | ()), |
180 | 376 | } | 414 | } |
181 | 377 | 415 | ||
183 | 378 | def __init__(self, config): | 416 | def __init__(self, config, pluginloader): |
184 | 379 | gtk.Notebook.__init__(self) | 417 | gtk.Notebook.__init__(self) |
185 | 380 | #definition gcp - global page count, how many pages have been created | 418 | #definition gcp - global page count, how many pages have been created |
186 | 381 | self.gcp = 0 | 419 | self.gcp = 0 |
187 | 382 | self.global_config = config | 420 | self.global_config = config |
188 | 421 | self.pluginloader = pluginloader | ||
189 | 383 | ## The "Add Tab" tab | 422 | ## The "Add Tab" tab |
190 | 384 | add_tab_button = gtk.Button("+") | 423 | add_tab_button = gtk.Button("+") |
191 | 385 | ## tooltip for "Add Tab" tab | 424 | ## tooltip for "Add Tab" tab |
192 | @@ -428,9 +467,11 @@ | |||
193 | 428 | current_page = self.get_nth_page(self.get_current_page()) | 467 | current_page = self.get_nth_page(self.get_current_page()) |
194 | 429 | cwd = cc_utils.get_pid_cwd(current_page.pid) | 468 | cwd = cc_utils.get_pid_cwd(current_page.pid) |
195 | 430 | if cwd: | 469 | if cwd: |
197 | 431 | newtab = TerminalTab(title, self.global_config, directory=cwd) | 470 | newtab = TerminalTab(title, self.global_config, directory=cwd, |
198 | 471 | pluginloader=self.pluginloader) | ||
199 | 432 | else: | 472 | else: |
201 | 433 | newtab = TerminalTab(title, self.global_config) | 473 | newtab = TerminalTab(title, self.global_config, |
202 | 474 | pluginloader=self.pluginloader) | ||
203 | 434 | label = self.create_tab_label(title, newtab) | 475 | label = self.create_tab_label(title, newtab) |
204 | 435 | self.insert_page(newtab, label, self.get_n_pages() - 1) | 476 | self.insert_page(newtab, label, self.get_n_pages() - 1) |
205 | 436 | self.set_current_page(self.get_n_pages() - 2) | 477 | self.set_current_page(self.get_n_pages() - 2) |
206 | 437 | 478 | ||
207 | === modified file 'clicompanionlib/view.py' | |||
208 | --- clicompanionlib/view.py 2012-01-28 19:38:19 +0000 | |||
209 | +++ clicompanionlib/view.py 2012-03-04 09:53:18 +0000 | |||
210 | @@ -223,7 +223,8 @@ | |||
211 | 223 | 223 | ||
212 | 224 | ## set various parameters on the main window (size, etc) | 224 | ## set various parameters on the main window (size, etc) |
213 | 225 | self.init_config() | 225 | self.init_config() |
215 | 226 | self.term_notebook = cc_tabs.TerminalsNotebook(self.config) | 226 | self.term_notebook = cc_tabs.TerminalsNotebook(self.config, |
216 | 227 | self.pluginloader) | ||
217 | 227 | 228 | ||
218 | 228 | ########################### | 229 | ########################### |
219 | 229 | #### Here we create the commands notebook for the expander | 230 | #### Here we create the commands notebook for the expander |
220 | 230 | 231 | ||
221 | === added file 'plugins/LaunchpadURL.py' | |||
222 | --- plugins/LaunchpadURL.py 1970-01-01 00:00:00 +0000 | |||
223 | +++ plugins/LaunchpadURL.py 2012-03-04 09:53:18 +0000 | |||
224 | @@ -0,0 +1,62 @@ | |||
225 | 1 | #!/usr/bin/env python | ||
226 | 2 | # -*- coding: utf-8 -*- | ||
227 | 3 | # | ||
228 | 4 | # LaunchpadURL.py - URL plugin for launchpad bugs, repos and code | ||
229 | 5 | # | ||
230 | 6 | # Copyright 2012 David Caro <david.caro.estevez@gmail.com> | ||
231 | 7 | # | ||
232 | 8 | # This program is free software: you can redistribute it and/or modify it | ||
233 | 9 | # under the terms of the GNU General Public License version 3, as published | ||
234 | 10 | # by the Free Software Foundation. | ||
235 | 11 | # | ||
236 | 12 | # This program is distributed in the hope that it will be useful, but | ||
237 | 13 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
238 | 14 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
239 | 15 | # PURPOSE. See the GNU General Public License for more details. | ||
240 | 16 | # | ||
241 | 17 | # You should have received a copy of the GNU General Public License along | ||
242 | 18 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
243 | 19 | # | ||
244 | 20 | |||
245 | 21 | |||
246 | 22 | import pygtk | ||
247 | 23 | pygtk.require('2.0') | ||
248 | 24 | import gobject | ||
249 | 25 | import webbrowser | ||
250 | 26 | |||
251 | 27 | try: | ||
252 | 28 | import gtk | ||
253 | 29 | except: | ||
254 | 30 | ## do not use gtk, just print | ||
255 | 31 | print _("You need to install the python gtk bindings package" | ||
256 | 32 | "'python-gtk2'") | ||
257 | 33 | sys.exit(1) | ||
258 | 34 | |||
259 | 35 | from clicompanionlib.utils import dbg | ||
260 | 36 | import clicompanionlib.plugins as plugins | ||
261 | 37 | |||
262 | 38 | |||
263 | 39 | class LaunchpadURL(plugins.URLPlugin): | ||
264 | 40 | ''' | ||
265 | 41 | Match launchpad urls and open them on the browser | ||
266 | 42 | ''' | ||
267 | 43 | __authors__ = 'David Caro <david.caro.estevez@gmail.com>' | ||
268 | 44 | __info__ = ('This plugins enables launchpad urls to be matched.') | ||
269 | 45 | __title__ = 'Launchpad URLS' | ||
270 | 46 | |||
271 | 47 | pathchars = "-A-Za-z0-9_.+?/~#" | ||
272 | 48 | nonums = "-A-Za-z_.+?/~#" | ||
273 | 49 | |||
274 | 50 | def __init__(self, config): | ||
275 | 51 | plugins.URLPlugin.__init__(self, config) | ||
276 | 52 | self.matches = ['lp:[0-9]+', | ||
277 | 53 | 'lp:[' + self.pathchars + ']*[' \ | ||
278 | 54 | + self.nonums + '][' + self.pathchars + ']*'] | ||
279 | 55 | |||
280 | 56 | def callback(self, url, matchnum): | ||
281 | 57 | dbg('Openeing launchpad url ' + url) | ||
282 | 58 | if matchnum == 0: | ||
283 | 59 | url = 'http://bugs.launchpad.net/bugs/' + url[3:] | ||
284 | 60 | else: | ||
285 | 61 | url = 'http://code.launchpad.net/+branch/' + url[3:] | ||
286 | 62 | self.open_url(url) | ||
287 | 0 | 63 | ||
288 | === added file 'plugins/StandardURLs.py' | |||
289 | --- plugins/StandardURLs.py 1970-01-01 00:00:00 +0000 | |||
290 | +++ plugins/StandardURLs.py 2012-03-04 09:53:18 +0000 | |||
291 | @@ -0,0 +1,91 @@ | |||
292 | 1 | #!/usr/bin/env python | ||
293 | 2 | # -*- coding: utf-8 -*- | ||
294 | 3 | # | ||
295 | 4 | # StandardURLs.py - URL plugin for common urls (http, ftp, etc.) | ||
296 | 5 | # | ||
297 | 6 | # Copyright 2012 David Caro <david.caro.estevez@gmail.com> | ||
298 | 7 | # | ||
299 | 8 | # This program is free software: you can redistribute it and/or modify it | ||
300 | 9 | # under the terms of the GNU General Public License version 3, as published | ||
301 | 10 | # by the Free Software Foundation. | ||
302 | 11 | # | ||
303 | 12 | # This program is distributed in the hope that it will be useful, but | ||
304 | 13 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
305 | 14 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
306 | 15 | # PURPOSE. See the GNU General Public License for more details. | ||
307 | 16 | # | ||
308 | 17 | # You should have received a copy of the GNU General Public License along | ||
309 | 18 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
310 | 19 | # | ||
311 | 20 | |||
312 | 21 | |||
313 | 22 | import pygtk | ||
314 | 23 | pygtk.require('2.0') | ||
315 | 24 | import gobject | ||
316 | 25 | import webbrowser | ||
317 | 26 | |||
318 | 27 | try: | ||
319 | 28 | import gtk | ||
320 | 29 | except: | ||
321 | 30 | ## do not use gtk, just print | ||
322 | 31 | print _("You need to install the python gtk bindings package" | ||
323 | 32 | "'python-gtk2'") | ||
324 | 33 | sys.exit(1) | ||
325 | 34 | |||
326 | 35 | from clicompanionlib.utils import dbg | ||
327 | 36 | import clicompanionlib.plugins as plugins | ||
328 | 37 | |||
329 | 38 | |||
330 | 39 | class StandardURLs(plugins.URLPlugin): | ||
331 | 40 | ''' | ||
332 | 41 | Match launchpad urls and open them on the browser | ||
333 | 42 | ''' | ||
334 | 43 | __authors__ = 'David Caro <david.caro.estevez@gmail.com>' | ||
335 | 44 | __info__ = ('This plugins enables some common urls to be matched.') | ||
336 | 45 | __title__ = 'Standard URLS' | ||
337 | 46 | |||
338 | 47 | def __init__(self, config): | ||
339 | 48 | plugins.URLPlugin.__init__(self, config) | ||
340 | 49 | self.matches = [] | ||
341 | 50 | |||
342 | 51 | userchars = "-A-Za-z0-9" | ||
343 | 52 | passchars = "-A-Za-z0-9,?;.:/!%$^*&~\"#'" | ||
344 | 53 | hostchars = "-A-Za-z0-9" | ||
345 | 54 | pathchars = "-A-Za-z0-9_$.+!*(),;:@&=?/~#%'\"" | ||
346 | 55 | schemes = ("(news:|telnet:|nntp:|https?:|ftps?:|webcal:)//") | ||
347 | 56 | user = "([" + userchars + "]+(:[" + passchars + "]+)?)?" | ||
348 | 57 | urlpath = "/[" + pathchars + "]*[^]'.}>) \t\r\n,\\\"]" | ||
349 | 58 | email = ("[a-zA-Z0-9][a-zA-Z0-9.+-]*@[a-zA-Z0-9][a-zA-Z0-9-]*" | ||
350 | 59 | "\.[a-zA-Z0-9][a-zA-Z0-9-]+[.a-zA-Z0-9-]*") | ||
351 | 60 | |||
352 | 61 | lboundry = "\\<" | ||
353 | 62 | rboundry = "\\>" | ||
354 | 63 | |||
355 | 64 | ## http/https/ftp/ftps/webcal/nntp/telnet urls | ||
356 | 65 | self.matches.append(schemes + user + "[" + hostchars + "]*\.[" | ||
357 | 66 | + hostchars + ".]+(:[0-9]+)?(" + urlpath + ")?") | ||
358 | 67 | ## file | ||
359 | 68 | self.matches.append('file:///[' + pathchars + "]*") | ||
360 | 69 | ## SIP | ||
361 | 70 | self.matches.append('(callto:|h323:|sip:)' | ||
362 | 71 | + "[" + userchars + "+][" | ||
363 | 72 | + userchars + ".]*(:[0-9]+)?@?[" | ||
364 | 73 | + pathchars + "]+" | ||
365 | 74 | + rboundry) | ||
366 | 75 | |||
367 | 76 | self.matches.append("(mailto:)?" + email) | ||
368 | 77 | ## news | ||
369 | 78 | self.matches.append('news:[-A-Z\^_a-z{|}~!"#$%&\'()*+' | ||
370 | 79 | + ',./0-9;:=?`]+@' + "[-A-Za-z0-9.]+(:[0-9]+)?") | ||
371 | 80 | ## General url (www.host.com or ftp.host.com) | ||
372 | 81 | self.matches.append("(www|ftp)[" + hostchars + "]*\.[" | ||
373 | 82 | + hostchars + ".]+(:[0-9]+)?(" + urlpath + ")?/?") | ||
374 | 83 | |||
375 | 84 | def callback(self, url, matchnum): | ||
376 | 85 | dbg('Opening common url ' + url) | ||
377 | 86 | if matchnum == 5: | ||
378 | 87 | if url[:3] == 'www': | ||
379 | 88 | url = 'http://' + url | ||
380 | 89 | else: | ||
381 | 90 | url = 'ftp://' + url | ||
382 | 91 | self.open_url(url) |
Hi David!
Sorry for long time before review, I have much work with preparation for very important for me contest.
I have applied your path, but I can't see how it work. After typing http:// www.google. com in terminal and click [enter], it isn't appear as link and isn't clickable.
Please explain, how your path should work - and thank you for working on it!
Marek