From 94bd5162211f695d53c5928a2fcb8ba0397e572a Mon Sep 17 00:00:00 2001 From: bordaigorl Date: Tue, 14 Oct 2014 10:28:10 +0100 Subject: [PATCH 01/52] Adding styling for inline code --- Evernote.sublime-settings | 1 + lib/markdown2.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Evernote.sublime-settings b/Evernote.sublime-settings index 9707ea1..c18685d 100644 --- a/Evernote.sublime-settings +++ b/Evernote.sublime-settings @@ -2,6 +2,7 @@ "inline_css": { "pre": "color: #000000; font-family: monospace,monospace; font-size: 0.9em; white-space: pre-wrap; word-wrap: break-word; background-color: #f8f8f8; border: 1px solid #cccccc; border-radius: 3px; overflow: auto; padding: 6px 10px; margin-bottom: 10px;", "code": "color: black; font-family: monospace,monospace; font-size: 0.9em;", + "inline-code": "color: #000000; font-family: monospace,monospace; padding: 0.1em 0.2em; margin: 0.1em; font-size: 85%; background-color: #F5F5F5; border-radius: 3px; border: 1px solid #cccccc;", "h1": "margin-bottom: 1em; margin-top: 1.2em;", "footnotes": "border-top: 1px solid #9AB39B; font-size: 80%;", "hr": "color:#9AB39B;background-color:#9AB39B;height:1px;border:none;", diff --git a/lib/markdown2.py b/lib/markdown2.py index d80642b..c293949 100644 --- a/lib/markdown2.py +++ b/lib/markdown2.py @@ -1635,7 +1635,7 @@ def _do_fenced_code_blocks(self, text): def _code_span_sub(self, match): c = match.group(2).strip(" \t") c = self._encode_code(c) - return "%s" % c + return "%s" % (self._html_class_str_from_tag("inline-code"), c) def _do_code_spans(self, text): # * Backtick quotes are used for spans. From bfdf0299174296890f2a2f332e7d8266f9603d3f Mon Sep 17 00:00:00 2001 From: bordaigorl Date: Tue, 14 Oct 2014 19:44:11 +0100 Subject: [PATCH 02/52] Support Unicode HTML escapes and solve Python3 incompatibility --- lib/html2text.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/html2text.py b/lib/html2text.py index 7d36912..33bcaf8 100644 --- a/lib/html2text.py +++ b/lib/html2text.py @@ -39,7 +39,7 @@ def has_key(x, y): xrange = range # Use Unicode characters instead of their ascii psuedo-replacements -UNICODE_SNOB = 0 +UNICODE_SNOB = 1 # Escape all special characters. Output is less readable, but avoids corner case formatting issues. ESCAPE_SNOB = 0 @@ -281,7 +281,7 @@ def close(self): self.outtext = self.outtext.join(self.outtextlist) if self.unicode_snob: - nbsp = unichr(name2cp('nbsp')) + nbsp = chr(name2cp('nbsp')) else: nbsp = u' ' self.outtext = self.outtext.replace(u' _place_holder;', nbsp) @@ -801,7 +801,7 @@ def charref(self, name): return unifiable_n[c] else: try: - return unichr(c) + return chr(c) except NameError: #Python3 return chr(c) @@ -813,7 +813,7 @@ def entityref(self, c): except KeyError: return "&" + c + ';' else: try: - return unichr(name2cp(c)) + return chr(name2cp(c)) except NameError: #Python3 return chr(name2cp(c)) From 9ee0844ae068fb4fede2351d5f81d15cbbbe1ecd Mon Sep 17 00:00:00 2001 From: bordaigorl Date: Thu, 6 Nov 2014 11:21:14 +0000 Subject: [PATCH 03/52] Styling: inlined pre bg-color gets overwritten by pygments; correct white bg to #f8f8f8 in `github` style (solves #56) --- Evernote.sublime-settings | 2 +- lib/pygments/styles/github.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Evernote.sublime-settings b/Evernote.sublime-settings index c18685d..31f7368 100644 --- a/Evernote.sublime-settings +++ b/Evernote.sublime-settings @@ -1,6 +1,6 @@ { "inline_css": { - "pre": "color: #000000; font-family: monospace,monospace; font-size: 0.9em; white-space: pre-wrap; word-wrap: break-word; background-color: #f8f8f8; border: 1px solid #cccccc; border-radius: 3px; overflow: auto; padding: 6px 10px; margin-bottom: 10px;", + "pre": "color: #000000; font-family: monospace,monospace; font-size: 0.9em; white-space: pre-wrap; word-wrap: break-word; border: 1px solid #cccccc; border-radius: 3px; overflow: auto; padding: 6px 10px; margin-bottom: 10px;", "code": "color: black; font-family: monospace,monospace; font-size: 0.9em;", "inline-code": "color: #000000; font-family: monospace,monospace; padding: 0.1em 0.2em; margin: 0.1em; font-size: 85%; background-color: #F5F5F5; border-radius: 3px; border: 1px solid #cccccc;", "h1": "margin-bottom: 1em; margin-top: 1.2em;", diff --git a/lib/pygments/styles/github.py b/lib/pygments/styles/github.py index 552e1ca..9d7a1b4 100644 --- a/lib/pygments/styles/github.py +++ b/lib/pygments/styles/github.py @@ -25,7 +25,7 @@ class GithubStyle(Style): default_style = '' - background_color = '#ffffff' + background_color = '#f8f8f8' styles = { Comment.Multiline: 'italic #999988', From 169d3a9a73b27fb9e17d4e7683abe5fed0a4fb02 Mon Sep 17 00:00:00 2001 From: bordaigorl Date: Thu, 20 Nov 2014 12:37:08 +0000 Subject: [PATCH 04/52] Bugfix: inline css needs to end with semicolon allowing further concatenation (solves #55) --- sublime_evernote.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sublime_evernote.py b/sublime_evernote.py index 29ef900..b7ce2bb 100644 --- a/sublime_evernote.py +++ b/sublime_evernote.py @@ -241,6 +241,10 @@ def load_settings(self): EvernoteDo.MD_EXTRAS['wiki-tables'] = None css = self.settings.get("inline_css") if css is not None: + for tag in css: + css[tag] = css[tag].strip() + if not css[tag].endswith(";"): + css[tag] = css[tag] + ";" EvernoteDo.MD_EXTRAS['inline-css'] = css self.md_syntax = self.settings.get("md_syntax") if not self.md_syntax: From 9f69e61c489fa1f5ef3c5fc0a728754dc26bfdc1 Mon Sep 17 00:00:00 2001 From: bordaigorl Date: Mon, 15 Dec 2014 23:55:00 +0000 Subject: [PATCH 05/52] Autocomplete: space and comma trigger autocomplete only when enabled --- Default.sublime-keymap | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Default.sublime-keymap b/Default.sublime-keymap index ad96c35..cde7db7 100644 --- a/Default.sublime-keymap +++ b/Default.sublime-keymap @@ -1,6 +1,7 @@ [ { "keys": [","], "command": "run_macro_file", "args":{"file": "Packages/Evernote/EvernoteAutoTags.sublime-macro"}, "context": [ + { "key": "setting.evernote_autocomplete", "operator": "equal", "operand": true }, { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, { "key": "preceding_text", "operator": "regex_match", "operand": "^\\s*tags\\s*:.*$", "match_all": true }, { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted", "match_all": true }, @@ -10,6 +11,7 @@ }, { "keys": [" "], "command": "auto_complete", "context": [ + { "key": "setting.evernote_autocomplete", "operator": "equal", "operand": true }, { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, { "key": "preceding_text", "operator": "regex_match", "operand": "^\\s*tags\\s*:\\s*$", "match_all": true }, { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted", "match_all": true }, @@ -19,6 +21,7 @@ }, { "keys": [","], "command": "run_macro_file", "args":{"file": "Packages/Evernote/EvernoteAutoTagsQuoted.sublime-macro"}, "context": [ + { "key": "setting.evernote_autocomplete", "operator": "equal", "operand": true }, { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, { "key": "preceding_text", "operator": "regex_match", "operand": "^\\s*tags\\s*:.*$", "match_all": true }, { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted", "match_all": true }, From 936e1a9d3991d08164d39e30e32126bf8e837c24 Mon Sep 17 00:00:00 2001 From: bordaigorl Date: Mon, 15 Dec 2014 23:55:31 +0000 Subject: [PATCH 06/52] Add setting for smarty_pants Markdown extra --- README.md | 1 + sublime_evernote.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/README.md b/README.md index 8e9f4a6..c5bf4e2 100644 --- a/README.md +++ b/README.md @@ -224,6 +224,7 @@ Setting | Purpose `inline_css` | a dictionary associating some HTML element names to inline CSS styles; currently the only elements that can be styled in this way are: `pre`, `code`, `h1`, `hr`, `blockquote` and `sup`. Additionally `footnotes` can be associated to some style for the `div` containing the footnotes at the end of the note. The markdown of a note can contain (almost) arbitrary HTML blocks *but* Evernote only accepts a subset of the elements and attributes (`class` and `id` are disallowed). See [here](http://dev.evernote.com/doc/articles/enml.php) for details. `code_highlighting_style` | a pygments style among `autumn`, `default`, `github`, `monokai`, `perldoc`, `vim`, `borland`, `emacs`, `igor`, `murphy`, `rrt`, `vs`, `bw`, `friendly`, `native`, `tango`, `xcode`, `colorful`, `fruity`, `manni`, `pastie`, `trac`. `code_friendly` | if `true` the `code-friendly` extra of markdown2 is enabled +`smarty_pants` | if `true` the `smarty-pants` extra of markdown2 is enabled `evernote_autocomplete` | when this setting is true, suggestions will be offered for autocompletion of the `notebook` and `tags` fields in metadata. Default is true. `notes_order` | how to sort the notes in the panels; possible values: `created`, `updated`, `relevance`, `update_sequence_number`, `title`. Set the `notes_order_ascending` setting to `true` to reverse the selected order. `max_notes` | maximum number of notes in a panel; default is 100. diff --git a/sublime_evernote.py b/sublime_evernote.py index b7ce2bb..34a082d 100644 --- a/sublime_evernote.py +++ b/sublime_evernote.py @@ -239,6 +239,8 @@ def load_settings(self): EvernoteDo.MD_EXTRAS['code-friendly'] = None if self.settings.get("wiki_tables"): EvernoteDo.MD_EXTRAS['wiki-tables'] = None + if self.settings.get("smarty_pants"): + EvernoteDo.MD_EXTRAS['smarty-pants'] = None css = self.settings.get("inline_css") if css is not None: for tag in css: From ee0fbc2da40c4bd2973cd510ed411fa74e79f80d Mon Sep 17 00:00:00 2001 From: bordaigorl Date: Fri, 23 Jan 2015 00:58:14 +0000 Subject: [PATCH 07/52] If only one results of search, open it directly skipping panel (solves #65) --- sublime_evernote.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sublime_evernote.py b/sublime_evernote.py index 34a082d..cccfe4c 100644 --- a/sublime_evernote.py +++ b/sublime_evernote.py @@ -646,6 +646,11 @@ def on_note(i): return self.message('Retrieving note "%s"...' % notes[i].title) self.open_note(notes[i].guid, **kwargs) + + if len(notes) == 1: + on_note(0) + return + if show_notebook: menu = ["[%s] » %s" % (self.notebook_from_guid(note.notebookGuid).name, note.title) for note in notes] # menu = [[note.title, self.notebook_from_guid(note.notebookGuid).name] for note in notes] From a285a5f38e8ea9a1e592b768e074b2b6f114e01b Mon Sep 17 00:00:00 2001 From: bordaigorl Date: Wed, 7 Jan 2015 09:41:57 +0000 Subject: [PATCH 08/52] Track edits and ask user what to do on close --- sublime_evernote.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/sublime_evernote.py b/sublime_evernote.py index 34a082d..6c6f46c 100644 --- a/sublime_evernote.py +++ b/sublime_evernote.py @@ -594,6 +594,7 @@ def __update_note(): self.view.settings().set("$evernote", True) self.view.settings().set("$evernote_guid", cnote.guid) self.view.settings().set("$evernote_title", cnote.title) + self.view.settings().set("$evernote_modified", False) self.message("Successfully updated note: guid:%s" % cnote.guid) self.update_status_info(cnote) except Exception as e: @@ -1097,6 +1098,25 @@ def on_post_save(self, view): if self.settings.get('update_on_save'): view.run_command("save_evernote_note") + def on_modified(self, view): + if view.settings().get("$evernote"): + view.settings().set("$evernote_modified", True) + + def on_pre_close(self, view): + if view.settings().get("$evernote") and view.settings().get("$evernote_modified"): + # There is no API to cancel the closing of a view + # so we let Sublime close it but clone it first and then ask the user. + choices = ["Close and discard changes", "Save to Evernote and close"] + view.window().run_command("clone_file") + cloned = view.window().active_view() + def on_choice(i): + if i == 1: + cloned.run_command("save_evernote_note") + if i >= 0: + cloned.settings().set("$evernote_modified", False) + cloned.close() + cloned.window().show_quick_panel(choices, on_choice) + def on_query_context(self, view, key, operator, operand, match_all): if key != "evernote_note": return None From 12399170158d8e353ff9b9db255d8a38c56c5860 Mon Sep 17 00:00:00 2001 From: bordaigorl Date: Fri, 23 Jan 2015 02:37:30 +0000 Subject: [PATCH 09/52] Better query context listener (added `evernote_has_guid`) --- sublime_evernote.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/sublime_evernote.py b/sublime_evernote.py index cccfe4c..711a439 100644 --- a/sublime_evernote.py +++ b/sublime_evernote.py @@ -1103,14 +1103,17 @@ def on_post_save(self, view): view.run_command("save_evernote_note") def on_query_context(self, view, key, operator, operand, match_all): - if key != "evernote_note": - return None - - res = view.settings().get("$evernote", False) - if (operator == sublime.OP_NOT_EQUAL) ^ (not operand): - res = not res - - return res + if key == "evernote_note": + res = view.settings().get("$evernote", False) + if (operator == sublime.OP_NOT_EQUAL) ^ (not operand): + res = not res + return res + elif key == "evernote_has_guid": + res = bool(view.settings().get("$evernote_guid")) + if (operator == sublime.OP_NOT_EQUAL) ^ (not operand): + res = not res + return res + return None first_time = True From fdd5e5049ada7ff28e78b91848354e4c655166dd Mon Sep 17 00:00:00 2001 From: bordaigorl Date: Fri, 23 Jan 2015 03:07:45 +0000 Subject: [PATCH 10/52] Make send, save and load note run on separate thread --- sublime_evernote.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sublime_evernote.py b/sublime_evernote.py index 711a439..9ac57d4 100644 --- a/sublime_evernote.py +++ b/sublime_evernote.py @@ -543,6 +543,9 @@ def on_notebook(notebook): on_cancel() def __send_note(notebookGuid): + sublime.set_timeout_async(lambda: __send_note_async(notebookGuid), 0) + + def __send_note_async(notebookGuid): note.notebookGuid = notebookGuid LOG(note.title) @@ -600,7 +603,7 @@ def __update_note(): if sublime.ok_cancel_dialog('Evernote complained:\n\n%s\n\nRetry?' % explain_error(e)): self.connect(self.__update_note) - __update_note() + sublime.set_timeout_async(__update_note, 0) def is_enabled(self): if self.view.settings().get("$evernote_guid", False): @@ -698,6 +701,9 @@ def find_notes(self, search_args, max_notes=None): NoteStore.NotesMetadataResultSpec(includeTitle=True, includeNotebookGuid=True)).notes def open_note(self, guid, convert=True, **unk_args): + sublime.set_timeout_async(lambda: self.do_open_note(guid, convert, **unk_args),0) + + def do_open_note(self, guid, convert=True, **unk_args): try: noteStore = self.get_note_store() note = noteStore.getNote(self.token(), guid, True, False, False, False) From aac69d0d15ee6f68980e82615dfc01b1a19c0881 Mon Sep 17 00:00:00 2001 From: bordaigorl Date: Fri, 23 Jan 2015 12:26:11 +0000 Subject: [PATCH 11/52] Readme: acknowledge donor --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c5bf4e2..f7bfc3a 100644 --- a/README.md +++ b/README.md @@ -262,6 +262,8 @@ The plugin has been made possible by the contribution of several people: If you think your name should be here, let us know! +Also thanks to first donor, Matthew Baltrusitis! + Libraries (some adapted to work with Evernote formats): * Markdown2 converter: [trentm](https://github.com/trentm/python-markdown2/) From 4314534613c397df729b8bc376c1ba4018fa9055 Mon Sep 17 00:00:00 2001 From: bordaigorl Date: Fri, 23 Jan 2015 15:42:40 +0000 Subject: [PATCH 12/52] Revert "Add setting for smarty_pants Markdown extra" This is due to conflict with `` tags where attributes quote would get replaced with smart quotes making the markup invalid. This reverts commit 936e1a9d3991d08164d39e30e32126bf8e837c24. --- README.md | 1 - sublime_evernote.py | 2 -- 2 files changed, 3 deletions(-) diff --git a/README.md b/README.md index f7bfc3a..d5629bc 100644 --- a/README.md +++ b/README.md @@ -224,7 +224,6 @@ Setting | Purpose `inline_css` | a dictionary associating some HTML element names to inline CSS styles; currently the only elements that can be styled in this way are: `pre`, `code`, `h1`, `hr`, `blockquote` and `sup`. Additionally `footnotes` can be associated to some style for the `div` containing the footnotes at the end of the note. The markdown of a note can contain (almost) arbitrary HTML blocks *but* Evernote only accepts a subset of the elements and attributes (`class` and `id` are disallowed). See [here](http://dev.evernote.com/doc/articles/enml.php) for details. `code_highlighting_style` | a pygments style among `autumn`, `default`, `github`, `monokai`, `perldoc`, `vim`, `borland`, `emacs`, `igor`, `murphy`, `rrt`, `vs`, `bw`, `friendly`, `native`, `tango`, `xcode`, `colorful`, `fruity`, `manni`, `pastie`, `trac`. `code_friendly` | if `true` the `code-friendly` extra of markdown2 is enabled -`smarty_pants` | if `true` the `smarty-pants` extra of markdown2 is enabled `evernote_autocomplete` | when this setting is true, suggestions will be offered for autocompletion of the `notebook` and `tags` fields in metadata. Default is true. `notes_order` | how to sort the notes in the panels; possible values: `created`, `updated`, `relevance`, `update_sequence_number`, `title`. Set the `notes_order_ascending` setting to `true` to reverse the selected order. `max_notes` | maximum number of notes in a panel; default is 100. diff --git a/sublime_evernote.py b/sublime_evernote.py index 711a439..2a2be22 100644 --- a/sublime_evernote.py +++ b/sublime_evernote.py @@ -239,8 +239,6 @@ def load_settings(self): EvernoteDo.MD_EXTRAS['code-friendly'] = None if self.settings.get("wiki_tables"): EvernoteDo.MD_EXTRAS['wiki-tables'] = None - if self.settings.get("smarty_pants"): - EvernoteDo.MD_EXTRAS['smarty-pants'] = None css = self.settings.get("inline_css") if css is not None: for tag in css: From 4313095bc8180edfc24e1145e70c80d29b45bede Mon Sep 17 00:00:00 2001 From: bordaigorl Date: Fri, 23 Jan 2015 16:23:05 +0000 Subject: [PATCH 13/52] Introduce `async_do` and make most operations asyncronous --- sublime_evernote.py | 94 +++++++++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 33 deletions(-) diff --git a/sublime_evernote.py b/sublime_evernote.py index 9ac57d4..a2bb120 100644 --- a/sublime_evernote.py +++ b/sublime_evernote.py @@ -195,6 +195,30 @@ def explain_error(err): return 'Evernote plugin error, please contact developer at\n'\ 'https://github.com/bordaigorl/sublime-evernote/issues' +def async_do(f, progress_msg="Evernote operation", done_msg=None): + if not done_msg: + done_msg = progress_msg + ': ' + "done!" + status = {'done': False, 'i': 0} + def do_stuff(s): + try: + f() + except: + raise + finally: + s['done'] = True + + def progress(s): + if s['done']: + sublime.status_message(done_msg) + else: + i = s['i'] + bar = "... [%s=%s]" % (' '*i, ' '*(7-i)) + sublime.status_message(progress_msg + bar) + s['i'] = (i + 1) % 8 + sublime.set_timeout(lambda: progress(s), 100) + + sublime.set_timeout(lambda: progress(status), 0) + sublime.set_timeout_async(lambda: do_stuff(status), 0) class EvernoteDo(): @@ -543,7 +567,7 @@ def on_notebook(notebook): on_cancel() def __send_note(notebookGuid): - sublime.set_timeout_async(lambda: __send_note_async(notebookGuid), 0) + async_do(lambda: __send_note_async(notebookGuid), "Sending note") def __send_note_async(notebookGuid): note.notebookGuid = notebookGuid @@ -603,7 +627,7 @@ def __update_note(): if sublime.ok_cancel_dialog('Evernote complained:\n\n%s\n\nRetry?' % explain_error(e)): self.connect(self.__update_note) - sublime.set_timeout_async(__update_note, 0) + async_do(__update_note, "Updating note") def is_enabled(self): if self.view.settings().get("$evernote_guid", False): @@ -666,12 +690,12 @@ def on_notebook(notebook): return search_args['notebookGuid'] = notebooks[notebook].guid notes = self.find_notes(search_args, max_notes) - sublime.set_timeout(lambda: notes_panel(notes), 0) + async_do(lambda: notes_panel(notes), "Fetching notes list") def do_search(query): self.message("Searching notes...") search_args['words'] = query - notes_panel(self.find_notes(search_args, max_notes), True) + async_do(lambda: notes_panel(self.find_notes(search_args, max_notes), True), "Fetching notes list") if note_guid: self.open_note(note_guid, **kwargs) @@ -701,7 +725,7 @@ def find_notes(self, search_args, max_notes=None): NoteStore.NotesMetadataResultSpec(includeTitle=True, includeNotebookGuid=True)).notes def open_note(self, guid, convert=True, **unk_args): - sublime.set_timeout_async(lambda: self.do_open_note(guid, convert, **unk_args),0) + async_do(lambda: self.do_open_note(guid, convert, **unk_args), "Retrieving note") def do_open_note(self, guid, convert=True, **unk_args): try: @@ -804,8 +828,10 @@ def open_note(self, guid, insert_in_content=True, filename=None, prompt=False, * note.content = content[0:-10] + \ '' % (mime, h.hexdigest()) note.resources = resources - noteStore.updateNote(self.token(), note) - self.message("Successfully attached to note '%s'" % note.title) + def do(): + noteStore.updateNote(self.token(), note) + self.message("Successfully attached to note '%s'" % note.title) + async_do(do, "Uploading attachment") except Exception as e: sublime.error_message(explain_error(e)) @@ -950,30 +976,32 @@ def do_run(self, edit, insert_in_content=True, filename=None, prompt=False): explain_error(e)) return - try: - guid = self.view.settings().get("$evernote_guid") - noteStore = self.get_note_store() - note = noteStore.getNote(self.token(), guid, False, False, False, False) - mime = mimetypes.guess_type(filename)[0] or "application/octet-stream" - h = hashlib.md5(filecontents) - attachment = Types.Resource( - # noteGuid=guid, - mime=mime, - data=Types.Data(body=filecontents, size=len(filecontents), bodyHash=h.digest()), - attributes=Types.ResourceAttributes(attachment=not insert_in_content, **attr)) - resources = note.resources or [] - resources.append(attachment) - note.resources = resources - self.message("Uploading attachment...") - noteStore.updateNote(self.token(), note) - if insert_in_content: - view.insert(edit, view.sel()[0].a, - '' % (mime, h.hexdigest())) - sublime.set_timeout(lambda: view.run_command("save_evernote_note"), 10) - except Exception as e: - sublime.error_message( - "Evernote plugin cannot insert the attachment.\n" + - explain_error(e)) + def upload_async(): + try: + guid = self.view.settings().get("$evernote_guid") + noteStore = self.get_note_store() + note = noteStore.getNote(self.token(), guid, False, False, False, False) + mime = mimetypes.guess_type(filename)[0] or "application/octet-stream" + h = hashlib.md5(filecontents) + attachment = Types.Resource( + # noteGuid=guid, + mime=mime, + data=Types.Data(body=filecontents, size=len(filecontents), bodyHash=h.digest()), + attributes=Types.ResourceAttributes(attachment=not insert_in_content, **attr)) + resources = note.resources or [] + resources.append(attachment) + note.resources = resources + noteStore.updateNote(self.token(), note) + if insert_in_content: + tag = '' % (mime, h.hexdigest()) + view.run_command('insert', {'characters': tag}) + sublime.set_timeout(lambda: view.run_command("save_evernote_note"), 10) + except Exception as e: + sublime.error_message( + "Evernote plugin cannot insert the attachment.\n" + + explain_error(e)) + + async_do(upload_async, "Uploading attachment") def is_enabled(self): if self.view.settings().get("$evernote_guid", False): @@ -1008,9 +1036,9 @@ def do_run(self, edit, filename=None, prompt=False): for r in resources] def on_done(i): - sublime.set_timeout_async(lambda: on_done2(i), 10) + async_do(lambda: on_done_async(i), "Fetching Attachment") - def on_done2(i): + def on_done_async(i): if i >= 0: import tempfile, mimetypes try: From 6bb5dbfbe6cc7b16338d531338ca8179534a424d Mon Sep 17 00:00:00 2001 From: bordaigorl Date: Fri, 23 Jan 2015 17:36:07 +0000 Subject: [PATCH 14/52] Better bookeeping of `$evernote_modified` --- sublime_evernote.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sublime_evernote.py b/sublime_evernote.py index 6c6f46c..a39516d 100644 --- a/sublime_evernote.py +++ b/sublime_evernote.py @@ -737,6 +737,7 @@ def open_note(self, guid, convert=True, **unk_args): newview.show(0) self.message('Note "%s" opened!' % note.title) self.update_status_info(note, newview) + newview.settings().set("$evernote_modified", False) except Exception as e: sublime.error_message(explain_error(e)) @@ -1103,7 +1104,7 @@ def on_modified(self, view): view.settings().set("$evernote_modified", True) def on_pre_close(self, view): - if view.settings().get("$evernote") and view.settings().get("$evernote_modified"): + if view and view.settings().get("$evernote") and view.settings().get("$evernote_modified"): # There is no API to cancel the closing of a view # so we let Sublime close it but clone it first and then ask the user. choices = ["Close and discard changes", "Save to Evernote and close"] From 827ce9f7b2991ee51950ee09550a1b4673f686f4 Mon Sep 17 00:00:00 2001 From: bordaigorl Date: Sun, 25 Jan 2015 13:06:54 +0000 Subject: [PATCH 15/52] Set syntax before appending context in open note to avoid FOUC --- sublime_evernote.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sublime_evernote.py b/sublime_evernote.py index 2a2be22..a151b7b 100644 --- a/sublime_evernote.py +++ b/sublime_evernote.py @@ -730,12 +730,13 @@ def open_note(self, guid, convert=True, **unk_args): newview.settings().set("$evernote", True) newview.settings().set("$evernote_guid", note.guid) newview.settings().set("$evernote_title", note.title) - append_to_view(newview, meta+mdtxt) syntax = self.md_syntax + note_contents = meta+mdtxt else: syntax = find_syntax("XML") - append_to_view(newview, note.content) + note_contents = note.content newview.set_syntax_file(syntax) + append_to_view(newview, note_contents) newview.show(0) self.message('Note "%s" opened!' % note.title) self.update_status_info(note, newview) From 21bf8cfde42d7390af641fab79678e7c803998db Mon Sep 17 00:00:00 2001 From: bordaigorl Date: Sun, 25 Jan 2015 13:11:10 +0000 Subject: [PATCH 16/52] Check cloned view has been created --- sublime_evernote.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sublime_evernote.py b/sublime_evernote.py index a39516d..d48b0e8 100644 --- a/sublime_evernote.py +++ b/sublime_evernote.py @@ -1110,6 +1110,8 @@ def on_pre_close(self, view): choices = ["Close and discard changes", "Save to Evernote and close"] view.window().run_command("clone_file") cloned = view.window().active_view() + if not cloned: + return def on_choice(i): if i == 1: cloned.run_command("save_evernote_note") From 51bb25fecf1b380d2c53d27119c485fe53365473 Mon Sep 17 00:00:00 2001 From: bordaigorl Date: Sun, 25 Jan 2015 16:01:12 +0000 Subject: [PATCH 17/52] Adding version --- sublime_evernote.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sublime_evernote.py b/sublime_evernote.py index a151b7b..2cdb9d7 100644 --- a/sublime_evernote.py +++ b/sublime_evernote.py @@ -36,7 +36,8 @@ from base64 import b64encode, b64decode -USER_AGENT = {'User-Agent': 'SublimeEvernote/2.0'} +EVERNOTE_PLUGIN_VERSION = "2.6" +USER_AGENT = {'User-Agent': 'SublimeEvernote/' + EVERNOTE_PLUGIN_VERSION} EVERNOTE_SETTINGS = "Evernote.sublime-settings" SUBLIME_EVERNOTE_COMMENT_BEG = "