diff --git a/Default (Linux).sublime-keymap b/Default (Linux).sublime-keymap index ff7356d..c38fe58 100644 --- a/Default (Linux).sublime-keymap +++ b/Default (Linux).sublime-keymap @@ -5,5 +5,7 @@ { "keys": ["ctrl+k", "ctrl+o"], "command": "gist_list" }, { "keys": ["ctrl+k", "ctrl+["], "command": "insert_gist_list" }, { "keys": ["ctrl+k", "ctrl+]"], "command": "gist_add_file" }, - { "keys": ["ctrl+k", "ctrl+g"], "command": "gist_gitio" } + { "keys": ["ctrl+k", "ctrl+g"], "command": "gist_gitio" }, + { "keys": ["ctrl+k", "ctrl+k"], "command": "gist_copy_url" }, + { "keys": ["ctrl+k", "ctrl+b"], "command": "gist_open_browser" } ] diff --git a/Default (OSX).sublime-keymap b/Default (OSX).sublime-keymap index 11d9fb6..55e983d 100644 --- a/Default (OSX).sublime-keymap +++ b/Default (OSX).sublime-keymap @@ -5,5 +5,7 @@ { "keys": ["super+k", "super+o"], "command": "gist_list" }, { "keys": ["super+k", "super+["], "command": "insert_gist_list" }, { "keys": ["super+k", "super+]"], "command": "gist_add_file" }, - { "keys": ["super+k", "super+g"], "command": "gist_gitio" } + { "keys": ["super+k", "super+g"], "command": "gist_gitio" }, + { "keys": ["super+k", "super+k"], "command": "gist_copy_url" }, + { "keys": ["super+k", "super+b"], "command": "gist_open_browser" } ] diff --git a/Default (Windows).sublime-keymap b/Default (Windows).sublime-keymap index ff7356d..c38fe58 100644 --- a/Default (Windows).sublime-keymap +++ b/Default (Windows).sublime-keymap @@ -5,5 +5,7 @@ { "keys": ["ctrl+k", "ctrl+o"], "command": "gist_list" }, { "keys": ["ctrl+k", "ctrl+["], "command": "insert_gist_list" }, { "keys": ["ctrl+k", "ctrl+]"], "command": "gist_add_file" }, - { "keys": ["ctrl+k", "ctrl+g"], "command": "gist_gitio" } + { "keys": ["ctrl+k", "ctrl+g"], "command": "gist_gitio" }, + { "keys": ["ctrl+k", "ctrl+k"], "command": "gist_copy_url" }, + { "keys": ["ctrl+k", "ctrl+b"], "command": "gist_open_browser" } ] diff --git a/gist_40_request.py b/gist_40_request.py index 444d6af..3ef5337 100644 --- a/gist_40_request.py +++ b/gist_40_request.py @@ -1,5 +1,7 @@ import contextlib import json +import os +import tempfile import urllib.request as urllib try: @@ -7,7 +9,7 @@ except ImportError: from test.stubs import sublime -from gist_20_exceptions import MissingCredentialsException, SimpleHTTPError +from gist_20_exceptions import MissingCredentialsException def token_auth_string(): @@ -20,7 +22,14 @@ def token_auth_string(): return token -def api_request(url, data=None, token=None, https_proxy=None, method=None): +def cache_request(etag, content): + target = os.path.join(tempfile.gettempdir(), "{}.json".format(etag.strip('"'))) + with tempfile.NamedTemporaryFile(mode='wb',delete=False) as temp_file: + os.rename(temp_file.name, target) + temp_file.write(str.encode(content)) + temp_file.flush() + +def api_request(url, data=None, token=None, https_proxy=None, method=None, since_date=False): settings = sublime.load_settings('Gist.sublime-settings') request = urllib.Request(url) @@ -30,6 +39,8 @@ def api_request(url, data=None, token=None, https_proxy=None, method=None): request.add_header('Authorization', 'token ' + token) request.add_header('Accept', 'application/json') request.add_header('Content-Type', 'application/json') + if since_date: + request.add_header('If-Modified-Since', since_date) if data is not None: request.add_data(bytes(data.encode('utf8'))) @@ -51,8 +62,37 @@ def api_request(url, data=None, token=None, https_proxy=None, method=None): if response.code == 204: # no content return None - return json.loads(response.read().decode('utf8', 'ignore')) + etag = response.headers['ETag'] + content = response.read().decode('utf8', 'ignore') + if etag: + cache_request(etag, content) + + return json.loads(content) + + except Exception as e: + try: + # Make sure we can iterate this error. + iter(e) + httpcode = str(e.code) + + # If 304 is status code, let's see if we have a cached version, or refetch. + if (httpcode == '304') and ("ETag" in e.headers): + + # Get path to cached version. + cached = os.path.join(tempfile.gettempdir(), "{}.json".format(e.headers['ETag'].strip('"'))) + try: + # Attempt to open and return cached data. + with open(cached, 'r') as result: + data = json.load(result) + data['cached'] = True + return data + except: + + # Re-fetch gist, but get around rate-limit features: + # http://docs2.lfe.io/v3/#conditional-requests + return api_request(url, data, token, https_proxy, method, 'Thu, 05 Jul 2010 15:31:30 GMT') + except: + pass - except urllib.HTTPError as e: with contextlib.closing(e): - raise SimpleHTTPError('{}: {}'.format(e.code, e.read())) from e + raise e diff --git a/gist_60_helpers.py b/gist_60_helpers.py index d3aa3f4..9355d81 100644 --- a/gist_60_helpers.py +++ b/gist_60_helpers.py @@ -7,8 +7,14 @@ from test.stubs import sublime +def prefix_status_line(text, gist, gist_filename): + prefix = "Gist" + if 'cached' in gist: + prefix = prefix + " (cached)" + return "%s: %s (%s)" % (prefix, text, gist_filename) + def gistify_view(view, gist, gist_filename): - statusline_string = "Gist: " + gist_title(gist)[0] + statusline_string = gist_title(gist)[0] if not view.file_name(): view.set_name(gist_filename) @@ -19,7 +25,7 @@ def gistify_view(view, gist, gist_filename): view.settings().set('gist_description', gist['description']) view.settings().set('gist_url', gist["url"]) view.settings().set('gist_filename', gist_filename) - view.set_status("Gist", statusline_string) + view.set_status("Gist", prefix_status_line(statusline_string, gist, gist_filename)) def ungistify_view(view): diff --git a/gist_80.py b/gist_80.py index 4aedb1f..3e473d4 100644 --- a/gist_80.py +++ b/gist_80.py @@ -70,9 +70,9 @@ def _fn(*args, **kwargs): shutil.copy(default_settings_path, user_settings_path) sublime.active_window().open_file(user_settings_path) return None - except: + except Exception as e: traceback.print_exc() - sublime.error_message("Gist: unknown error (please, report a bug!)") + sublime.error_message("Gist: unknown error (please, report a bug!)\n " + str(e)) return None return _fn