;; ;; Copyright 2011 Yusuke KAWAKAMI, Akihiro ARISAWA ;; ;; Licensed under the Apache License, Version 2.0 (the “License”); ;; you may not use this file except in compliance with the License. ;; You may obtain a copy of the License at ;; ;; www.apache.org/licenses/LICENSE-2.0 ;; ;; Unless required by applicable law or agreed to in writing, software ;; distributed under the License is distributed on an “AS IS” BASIS, ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ;; See the License for the specific language governing permissions and ;; limitations under the License.
;; ;; evernote-mode home page is at: code.google.com/p/emacs-evernote-mode/ ;; Author: Yusuke KAWAKAMI, Akihiro ARISAWA ;; Version: 0.41 ;; Keywords: tools, emacs, evernote, bookmark
;; This emacs lisp offers the interactive functions to open, edit, and update notes of Evernote. ;; The minor mode Evernote-mode is applied to the buffer editing a note of Evernote. ;; ;; Please copy this file into emacs lisp library directory or place it in ;; a directory (for example “~/lisp”) and write $HOME/.emacs like this. ;; ;; (add-to-list 'load-path “~/lisp”) ;; (require 'evernote-mode) ;; (setq evernote-enml-formatter-command '(“w3m” “-dump” “-I” “UTF8” “-O” “UTF8”)) ;; (global-set-key “C-cec” 'evernote-create-note) ;; (global-set-key “C-ceo” 'evernote-open-note) ;; (global-set-key “C-ces” 'evernote-search-notes) ;; (global-set-key “C-ceS” 'evernote-do-saved-search) ;; (global-set-key “C-cew” 'evernote-write-note) ;; (global-set-key “C-cep” 'evernote-post-region) ;; (global-set-key “C-ceb” 'evernote-browser) ;; ;; There is one hooks, evernotes-mode-hook. ;; The usage of the hook is shown as follows. ;; ;; (setq evernote-mode-hook ;; '(lambda () ;; (…)))
;;; Code
(require 'tree-widget)
(defun enh-bookmark-supported ()
(or (> emacs-major-version 23)
(and (= emacs-major-version 23)
(>= emacs-minor-version 1))))
(when (enh-bookmark-supported)
(declare-function bookmark-default-handler "bookmark" (bmk-record))
(declare-function bookmark-get-bookmark-record "bookmark" (bookmark))
(declare-function bookmark-make-record-default
"bookmark" (&optional no-file no-context posn))
(declare-function bookmark-name-from-full-record
"bookmark" (full-record)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Macros ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defmacro enh-command-with-auth (&rest body)
`(let (error-code
(try-func (lambda () ,@body)))
(setq error-code
(catch 'error
(progn
(funcall try-func)
t)))
(cond
((eq error-code t)
t)
((or (eq error-code enh-command-error-not-authed)
(eq error-code enh-command-error-invalid-auth)
(eq error-code enh-command-error-auth-expired))
(let ((error-code
(catch 'error
(progn
(evernote-login)
t))))
(if (eq error-code t)
(progn
(let (error-code)
(setq error-code
(catch 'error
(progn
(funcall try-func)
t)))
(unless (eq error-code t)
(message enh-command-last-error-message))))
(message enh-command-last-error-message))))
(t
(message enh-command-last-error-message)))))
(defmacro enh-base-create-note-interactive (ask-notebook)
"Common interactive procecure of creating a note"
`(progn
(if (called-interactively-p) (enh-clear-onmem-cache))
(enh-command-with-auth
(switch-to-buffer (enh-base-create-note-common "" ,ask-notebook t t nil)))))
(defmacro enh-base-write-note-interactive (ask-notebook)
"Common interactive procecure of writing a note"
`(progn
(if (called-interactively-p) (enh-clear-onmem-cache))
(enh-command-with-auth
(enh-base-create-note-common (buffer-name) ,ask-notebook ,nil t t))))
(defmacro enh-base-post-region-interactive (begin end arg ask-notebook)
"Common interactive procedure of posting a note"
`(progn
(if (called-interactively-p) (enh-clear-onmem-cache))
(enh-command-with-auth
(save-excursion
(save-restriction
(narrow-to-region ,begin ,end)
(if (and (enutil-neq ,arg nil) (enutil-neq ,arg 1))
(pop-to-buffer (enh-base-create-note-common (buffer-name) ,ask-notebook t t t))
(enh-base-create-note-common (buffer-name) ,ask-notebook nil nil t)))))))
(defmacro enutil-neq (&rest exprs)
`(not (eq ,@exprs)))
(defmacro enutil-nequal (&rest exprs)
`(not (equal ,@exprs)))
(defmacro enutil-push (elem list)
`(setq ,list (cons ,elem ,list)))
(defmacro enutil-pop (list)
`(prog1
(car ,list)
(setq ,list (cdr ,list))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; User options ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar evernote-username nil
"*An username of your evernote")
(defvar evernote-enml-formatter-command nil
"*Formatter for xhtml")
(defvar evernote-ruby-command “ruby”
"*Path of the ruby command")
(defvar evernote-password-cache nil
"*Non-nil means that password cache is enabled.
It is recommended to encrypt the file with EasyPG.“)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Interface for evernote-browsing-mode. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar evernote-browsing-page-list nil
"Buffer list of evernote browsing mode.")
(defvar evernote-browsing-current-page nil
"Current buffer of evernote browsing mode.")
(defvar evernote-browsing-mode-map
(let ((map (make-sparse-keymap))) (set-keymap-parent map widget-keymap) map) "Keymap used in evernote browsing mode.")
(define-key evernote-browsing-mode-map “o” 'widget-button-press) (define-key evernote-browsing-mode-map “n” 'evernote-browsing-open-next-note) (define-key evernote-browsing-mode-map “p” 'evernote-browsing-open-previous-note) (define-key evernote-browsing-mode-map “N” 'evernote-browsing-list-notebooks) (define-key evernote-browsing-mode-map “t” 'evernote-browsing-list-tags) (define-key evernote-browsing-mode-map “S” 'evernote-browsing-list-searches) (define-key evernote-browsing-mode-map “s” 'evernote-browsing-search-notes) (define-key evernote-browsing-mode-map “b” 'evernote-browsing-prev-page) (define-key evernote-browsing-mode-map “f” 'evernote-browsing-next-page) (define-key evernote-browsing-mode-map “d” 'evernote-browsing-delete-page) (define-key evernote-browsing-mode-map “l” 'evernote-browsing-reflesh) ;(define-key evernote-browsing-mode-map “e” 'evernote-browsing-change-edit-mode) ;(define-key evernote-browsing-mode-map “r” 'evernote-browsing-rename-note) ;(define-key evernote-browsing-mode-map “d” 'evernote-browsing-delete-note)
(defun evernote-browsing-mode ()
"Major mode for browsing notes."
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(setq evernote-browsing-mode t)
(use-local-map evernote-browsing-mode-map)
(setq truncate-lines t
major-mode 'evernote-browsing-mode
mode-name "Evernote-Browsing")
(goto-char (point-min)))
(defun evernote-browser ()
"Open an evernote browser"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(enh-browsing-update-page-list)
(if evernote-browsing-current-page
(enutil-move-cursor-to-window evernote-browsing-current-page)
(evernote-browsing-list-tags)))
(defun evernote-browsing-open-next-note ()
(interactive)
(next-line)
(when (eq enh-browsing-page-type 'note-list)
(condition-case nil
(widget-button-press (point))
(error nil))))
(defun evernote-browsing-open-previous-note ()
(interactive)
(previous-line)
(when (eq enh-browsing-page-type 'note-list)
(condition-case nil
(widget-button-press (point))
(error nil))))
(defun evernote-browsing-list-notebooks ()
"List tags"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(enh-browsing-update-page-list)
(let ((page (enh-browsing-get-page-of-type 'notebook-list)))
(if page
(progn
(setq evernote-browsing-current-page page)
(switch-to-buffer page))
(enh-browsing-push-page
(enh-browsing-create-page 'notebook-list "All Notebooks")))))
(defun evernote-browsing-list-tags ()
"List tags"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(enh-browsing-update-page-list)
(let ((page (enh-browsing-get-page-of-type 'tag-list)))
(if page
(progn
(setq evernote-browsing-current-page page)
(switch-to-buffer page))
(enh-browsing-push-page
(enh-browsing-create-page 'tag-list "All Tags")))))
(defun evernote-browsing-list-searches ()
"List saved searches"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(enh-browsing-update-page-list)
(let ((page (enh-browsing-get-page-of-type 'search-list)))
(if page
(progn
(setq evernote-browsing-current-page page)
(switch-to-buffer page))
(enh-browsing-push-page
(enh-browsing-create-page 'search-list "All Saved Searches")))))
(defun evernote-browsing-search-notes ()
"Search notes"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(let (note-attrs (query (read-string "Query:")))
(enh-command-with-auth
(setq note-attrs
(enh-command-get-note-attrs-from-query query)))
(enh-browsing-update-page-list)
(enh-browsing-push-page
(enh-browsing-create-page 'note-list
(format "Query Result of: %s" query)
note-attrs
`(lambda () (enh-command-get-note-attrs-from-query ,query))))))
(defun evernote-browsing-prev-page ()
"Move to the prev page"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(when (eq major-mode 'evernote-browsing-mode)
(enh-browsing-update-page-list)
(let ((prev-page (enh-browsing-get-prev-page)))
(if prev-page
(progn
(setq evernote-browsing-current-page prev-page)
(switch-to-buffer prev-page))
(message "[No more previous page]")))))
(defun evernote-browsing-next-page ()
"Move to the next page"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(when (eq major-mode 'evernote-browsing-mode)
(enh-browsing-update-page-list)
(let ((next-page (enh-browsing-get-next-page)))
(if next-page
(progn
(setq evernote-browsing-current-page next-page)
(switch-to-buffer next-page))
(message "[No more next page]")))))
(defun evernote-browsing-delete-page ()
"Delete current page" (interactive) (if (called-interactively-p) (enh-clear-onmem-cache)) (when (eq major-mode 'evernote-browsing-mode) (kill-buffer (current-buffer)) (enh-browsing-update-page-list) (switch-to-buffer evernote-browsing-current-page)))
(defun evernote-browsing-reflesh ()
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(when (eq major-mode 'evernote-browsing-mode)
(when enh-browsing-page-data-refresh-closure
(setq enh-browsing-page-data nil))
(funcall enh-browsing-page-setup-func)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Interface for evernote-mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar evernote-mode nil
"Non-nil if Evernote mode is enabled.")
(make-variable-buffer-local 'evernote-mode)
(defvar evernote-note-guid nil
"Note guid of the buffer")
(make-variable-buffer-local 'evernote-note-guid)
(defvar evernote-note-modified-name nil
"Modified name of the note before saving")
(make-variable-buffer-local 'evernote-note-modified-name)
(defvar evernote-note-modified-notebook-guid nil
"Modified noteobok guid of the note before saving")
(make-variable-buffer-local 'evernote-note-modified-notebook-guid)
(defvar evernote-note-modified-edit-mode nil
"Modified edit-mode of the note before saving")
(make-variable-buffer-local 'evernote-note-modified-edit-mode)
(defvar evernote-note-is-modified-tag-names nil
"Modified tag-names of the note before saving")
(make-variable-buffer-local 'evernote-note-is-modified-tag-names)
(defvar evernote-note-modified-tag-names nil
"Modified tag-names of the note before saving")
(make-variable-buffer-local 'evernote-note-modified-tag-names)
(defvar evernote-note-xhtml-mode-content nil
"Note contents as a string of XHTML")
(make-variable-buffer-local 'evernote-note-xhtml-mode-content)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Menu Settings ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar evernote-mode-display-menu t
"display the evernote menu on the menubar if this variable is not nil")
(defvar evernote-mode-map (make-sparse-keymap)
"Keymap used in evernote mode.")
(define-key evernote-mode-map “C-xC-s” 'evernote-save-note) (define-key evernote-mode-map “C-cen” 'evernote-change-notebook) (define-key evernote-mode-map “C-cet” 'evernote-edit-tags) (define-key evernote-mode-map “C-cee” 'evernote-change-edit-mode) (define-key evernote-mode-map “C-cer” 'evernote-rename-note) (define-key evernote-mode-map “C-ced” 'evernote-delete-note) (define-key evernote-mode-map “C-xC-q” 'evernote-toggle-read-only)
(defun enh-menu-is-visible-on-ordinary-mode ()
(not evernote-browsing-mode))
(defun enh-menu-is-visible-on-evernote-mode ()
(and evernote-mode (not evernote-browsing-mode)))
(defun enh-menu-is-visible-on-evernote-browsing-mode ()
evernote-browsing-mode)
(let ((menu-bar-map (make-sparse-keymap “Evernote”)))
(define-key-after global-map [menu-bar evernote]
`(menu-item "Evernote" ,menu-bar-map
:visible evernote-mode-display-menu)
'tools)
(define-key menu-bar-map [browser]
'(menu-item "Evernote Browser" evernote-browser
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [seperator-0]
'(menu-item "--" nil
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [toggle-read-only]
'(menu-item "Toggle Read Only" evernote-toggle-read-only
:visible (enh-menu-is-visible-on-evernote-mode)))
(define-key menu-bar-map [delete-note]
'(menu-item "Delete Note" evernote-delete-note
:visible (enh-menu-is-visible-on-evernote-mode)))
(define-key menu-bar-map [rename-note]
'(menu-item "Rename Note" evernote-rename-note
:visible (enh-menu-is-visible-on-evernote-mode)))
(define-key menu-bar-map [change-notebook]
'(menu-item "Change Notebook" evernote-change-notebook
:visible (enh-menu-is-visible-on-evernote-mode)))
(define-key menu-bar-map [change-edit-mode]
'(menu-item "Change Edit Mode" evernote-change-edit-mode
:visible (enh-menu-is-visible-on-evernote-mode)))
(define-key menu-bar-map [edit-tag]
'(menu-item "Edit Tag" evernote-edit-tags
:visible (enh-menu-is-visible-on-evernote-mode)))
(define-key menu-bar-map [save-note]
'(menu-item "Save Note" evernote-save-note
:visible (enh-menu-is-visible-on-evernote-mode)))
(define-key menu-bar-map [seperator-1]
'(menu-item "--" nil
:visible (enh-menu-is-visible-on-evernote-mode)))
(define-key menu-bar-map [edit-notebook]
'(menu-item "Edit Notebook" evernote-edit-notebook
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [create-notebook]
'(menu-item "Create Notebook" evernote-create-notebook
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [seperator-2]
'(menu-item "--" nil
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [edit-search]
'(menu-item "Edit Saved Search" evernote-edit-search
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [create-search]
'(menu-item "Create Saved Search" evernote-create-search
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [do-saved-search]
'(menu-item "Do Saved Search" evernote-do-saved-search
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [search-note]
'(menu-item "Search Note" evernote-search-notes
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [seperator-3]
'(menu-item "--" nil
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [post-region-in-notebook]
'(menu-item "Post Region (w/ notebook param)" evernote-post-region-in-notebook
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [post-region]
'(menu-item "Post Region" evernote-post-region
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [write-note-in-notebook]
'(menu-item "Write Note (w/ notebook param)" evernote-write-note-in-notebook
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [write-note]
'(menu-item "Write Note" evernote-write-note
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [create-note-in-notebook]
'(menu-item "Create Note (w/ notebook param)" evernote-create-note-in-notebook
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [create-note]
'(menu-item "Create Note" evernote-create-note
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [open-note-in-notebook]
'(menu-item "Open Note (w/ notebook param)" evernote-open-note-in-notebook
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [open-note]
'(menu-item "Open Note" evernote-open-note
:visible (enh-menu-is-visible-on-ordinary-mode)))
(define-key menu-bar-map [browsing-prev-page]
'(menu-item "Prev Page" evernote-browsing-prev-page
:visible (enh-menu-is-visible-on-evernote-browsing-mode)))
(define-key menu-bar-map [browsing-next-page]
'(menu-item "Next Page" evernote-browsing-next-page
:visible (enh-menu-is-visible-on-evernote-browsing-mode)))
(define-key menu-bar-map [browsing-search-notes]
'(menu-item "Searche Notes" evernote-browsing-search-notes
:visible (enh-menu-is-visible-on-evernote-browsing-mode)))
(define-key menu-bar-map [browsing-list-searches]
'(menu-item "List Saved Searches" evernote-browsing-list-searches
:visible (enh-menu-is-visible-on-evernote-browsing-mode)))
(define-key menu-bar-map [browsing-list-tags]
'(menu-item "List Tags" evernote-browsing-list-tags
:visible (enh-menu-is-visible-on-evernote-browsing-mode)))
(define-key menu-bar-map [browsing-list-notebooks]
'(menu-item "List Notebooks" evernote-browsing-list-notebooks
:visible (enh-menu-is-visible-on-evernote-browsing-mode))))
(defun evernote-mode (&optional guid)
"Toggle Evernote mode, a minor mode for using evernote functions."
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(or (assq 'evernote-mode minor-mode-alist)
(setq minor-mode-alist (cons '(evernote-mode " Evernote") minor-mode-alist)))
(or (assq 'evernote-mode minor-mode-map-alist)
(setq minor-mode-map-alist
(cons (cons 'evernote-mode evernote-mode-map) minor-mode-map-alist)))
(let ((modified (buffer-modified-p)))
(set-buffer-file-coding-system 'utf-8)
(set-buffer-modified-p modified))
(setq evernote-mode (not evernote-mode))
(if evernote-mode
(progn
(when guid (setq evernote-note-guid guid))
(enh-base-update-mode-line
evernote-note-modified-notebook-guid
evernote-note-is-modified-tag-names
evernote-note-modified-tag-names
evernote-note-modified-edit-mode)
(add-hook 'after-save-hook
'evernote-mode-after-save-hook
nil t)
(add-hook 'change-major-mode-hook
'evernote-mode-change-major-mode-hook
nil t)
(when (enh-bookmark-supported)
(enh-bookmark-prepare))
(run-hooks 'evernote-mode-hook))
(progn
(setq evernote-note-guid nil)
(setq vc-mode nil)
(remove-hook 'after-save-hook
'evernote-mode-after-save-hook)
(remove-hook 'change-major-mode-hook
'evernote-mode-change-major-mode-hook))))
(defun evernote-login ()
"Login"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(unwind-protect
(let* ((cache (enh-password-cache-load))
(usernames (mapcar #'car cache))
(username (or evernote-username
(read-string "Evernote user name:"
(car usernames) 'usernames)))
(cache-passwd (enutil-aget username cache)))
(unless (and cache-passwd
(eq (catch 'error
(progn
(enh-command-login username cache-passwd)
t))
t))
(let* ((passwd (read-passwd "Passwd:")))
(enh-command-login username passwd)
(setq evernote-username username)
(enh-password-cache-save (enutil-aset username cache passwd)))))
(enh-password-cache-close)))
(defun evernote-open-note (&optional ask-notebook)
"Open a note"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(enh-command-with-auth
(let* ((notebook-guid (and ask-notebook
(enutil-aget 'guid (enh-read-notebook))))
(tag-guids (enh-read-tag-guids
"Tags used for search (comma separated form. default search all tags):"))
(note-attrs
(enh-command-get-note-attrs-from-notebook-and-tag-guids notebook-guid tag-guids)))
(enh-base-open-note-common (enh-base-read-note-attr note-attrs))
(enh-browsing-update-page-list)
(enh-browsing-push-page
(enh-browsing-create-page 'note-list
(if tag-guids
(format "Notes with tag: %s"
(enh-tag-guids-to-comma-separated-names tag-guids))
"All notes")
note-attrs
`(lambda () (enh-command-get-note-attrs-from-notebook-and-tag-guids
,notebook-guid ',tag-guids)))
t))))
(defun evernote-open-note-in-notebook ()
"Open a note in the specified notebook" (interactive) (if (called-interactively-p) (enh-clear-onmem-cache)) (evernote-open-note t))
(defun evernote-search-notes ()
"Search notes with query and open a note among them"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(let ((query (read-string "Query:")))
(enh-command-with-auth
(let ((note-attrs
(enh-command-get-note-attrs-from-query
query)))
(enh-base-open-note-common (enh-base-read-note-attr note-attrs))
(enh-browsing-update-page-list)
(enh-browsing-push-page
(enh-browsing-create-page 'note-list
(format "Query Result of: %s" query)
note-attrs
`(lambda () (enh-command-get-note-attrs-from-query ,query)))
t)))))
(defun evernote-do-saved-search ()
"Do a saved search and open a note"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(enh-command-with-auth
(let* ((search-attr (enh-read-saved-search))
(note-attrs
(enh-command-get-note-attrs-from-query
(enutil-aget 'query search-attr))))
(enh-base-open-note-common (enh-base-read-note-attr note-attrs))
(enh-browsing-update-page-list)
(enh-browsing-push-page
(enh-browsing-create-page 'note-list
(format "Query Result of Saved Search: %s"
(enutil-aget 'name search-attr))
note-attrs
`(lambda () (enh-command-get-note-attrs-from-query
,(enutil-aget 'query search-attr))))
t))))
(defun evernote-create-note ()
"Create a note" (interactive) (enh-base-create-note-interactive nil))
(defun evernote-create-note-in-notebook ()
"Create a note in the specified notebook" (interactive) (enh-base-create-note-interactive t))
(defun evernote-write-note ()
"Write buffer to a note" (interactive) (enh-base-write-note-interactive nil))
(defun evernote-write-note-in-notebook ()
"Write buffer to a note in the specified notebook" (interactive) (enh-base-write-note-interactive t))
(defun evernote-post-region (begin end arg)
"Post the region as a note" (interactive "r\np") (enh-base-post-region-interactive begin end arg nil))
(defun evernote-post-region-in-notebook (begin end arg)
"Post the region as a note in the specified notebook" (interactive "r\np") (enh-base-post-region-interactive begin end arg t))
(defun evernote-save-note ()
"Save a note"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(cond
((not evernote-mode)
nil) ; do nothing
((not (buffer-modified-p))
(message "(No changes need to be saved)"))
(buffer-read-only
(ding)
(message "Unset read-only before you save"))
(t
(enh-command-with-auth
(enh-base-update-note-common
(current-buffer) ; contents
evernote-note-guid ; guid
(if evernote-note-modified-name ; name
evernote-note-modified-name
nil)
evernote-note-modified-notebook-guid ; notebook-guid
evernote-note-is-modified-tag-names ; is-tag-updated
(if evernote-note-is-modified-tag-names ; tag-names
evernote-note-modified-tag-names
nil)
(if evernote-note-modified-edit-mode ; edit-mode
evernote-note-modified-edit-mode
nil))
(if (or evernote-note-modified-name
evernote-note-modified-notebook-guid
evernote-note-is-modified-tag-names
evernote-note-modified-edit-mode)
(enh-browsing-reflesh-page 'note-list))
(setq evernote-note-modified-name nil
evernote-note-modified-notebook-guid nil
evernote-note-is-modified-tag-names nil
evernote-note-modified-tag-names nil
evernote-note-modified-edit-mode nil)
(set-buffer-modified-p nil)))))
(defun evernote-change-notebook ()
"Change notebook to which this note belongs"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(when evernote-mode
(let* (current-notebook-guid current-notebook-name next-notebook-guid)
(setq current-notebook-guid
(or evernote-note-modified-notebook-guid
(enutil-aget 'notebookGuid (enh-get-note-attr evernote-note-guid))))
(setq current-notebook-name
(enutil-aget 'name (enh-get-notebook-attr current-notebook-guid)))
(setq next-notebook-guid
(enutil-aget 'guid (enh-read-notebook current-notebook-name)))
(when (not (string= current-notebook-guid next-notebook-guid))
(setq evernote-note-modified-notebook-guid next-notebook-guid)
(enh-base-update-mode-line evernote-note-modified-notebook-guid
evernote-note-is-modified-tag-names
evernote-note-modified-tag-names
evernote-note-modified-edit-mode)
(set-buffer-modified-p t)))))
(defun evernote-edit-tags ()
"Add or remove tags from/to the note"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(when evernote-mode
(setq evernote-note-modified-tag-names
(enh-read-tag-names
"Change attached Tags (comma separated form):"
evernote-note-guid))
(setq evernote-note-is-modified-tag-names t) ; this must be after enh-read-tag-names
(enh-base-update-mode-line evernote-note-modified-notebook-guid
evernote-note-is-modified-tag-names
evernote-note-modified-tag-names
evernote-note-modified-edit-mode)
(set-buffer-modified-p t)))
(defun evernote-change-edit-mode ()
"Change edit mode of the note"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(when evernote-mode
(let* ((current-edit-mode
(or evernote-note-modified-edit-mode
(enutil-aget 'editMode (enh-get-note-attr evernote-note-guid))))
(next-edit-mode (enh-read-edit-mode current-edit-mode))
(need-change nil))
(when (not (string= current-edit-mode next-edit-mode))
(cond
;; XHTML mode, Confirm the buffer is saved.
((and (string= current-edit-mode "XHTML")
(buffer-modified-p))
(ding)
(message "Save the buffer before you change edit mode"))
;; XHTML mode, Formatted xml.
((and (string= current-edit-mode "XHTML")
buffer-read-only)
(when (y-or-n-p "Changing text mode will remove all format information. Continue? ")
(setq evernote-note-xhtml-mode-content nil)
(setq buffer-read-only nil)
(setq need-change t)))
;; XHTML mode, raw xml.
((and (string= current-edit-mode "XHTML")
(not buffer-read-only))
(setq evernote-note-xhtml-mode-content nil)
(setq need-change t))
;; HTML mode.
((string= current-edit-mode "TEXT")
(setq buffer-read-only nil)
(setq need-change t))))
(when need-change
(setq evernote-note-modified-edit-mode next-edit-mode)
(enh-base-update-mode-line
evernote-note-modified-notebook-guid
evernote-note-is-modified-tag-names
evernote-note-modified-tag-names
evernote-note-modified-edit-mode)
(set-buffer-modified-p t)))))
(defun evernote-rename-note ()
"Rename a note"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(when evernote-mode
(setq evernote-note-modified-name
(read-string "New note name:"
(enutil-aget 'title (enh-get-note-attr evernote-note-guid))))
(rename-buffer evernote-note-modified-name t)
(enh-base-change-major-mode-from-note-name evernote-note-modified-name)
(set-buffer-modified-p t)))
(defun evernote-delete-note ()
"Delete a note"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(if (and evernote-mode
(y-or-n-p "Do you really want to remove this note? "))
(enh-command-with-auth
(enh-command-delete-note evernote-note-guid)
(kill-buffer (current-buffer)))))
(defun evernote-create-notebook ()
"Create a notebook" (interactive) (if (called-interactively-p) (enh-clear-onmem-cache)) (let ((name (read-string "Notebook Name:"))) (enh-command-with-auth (enh-command-create-notebook name nil)) (enh-browsing-reflesh-page 'notebook-list)))
(defun evernote-edit-notebook ()
"Create a notebook"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(enh-command-with-auth
(let* ((notebook-alist (enh-get-notebook-name-attr-alist))
(notebook-attr
(enutil-aget
(completing-read
"Notebook:"
notebook-alist
nil t)
notebook-alist)))
(enh-command-update-notebook
(enutil-aget 'guid notebook-attr)
(read-string "New notebook name:"
(enutil-aget 'name notebook-attr))
(yes-or-no-p "Use as the default notebook:"))))
(clrhash enh-notebook-info)
(enh-browsing-reflesh-page 'notebook-list))
(defun evernote-create-search ()
"Create a saved search"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(let ((name (read-string "Saved Search Name:"))
(query (read-string "Query:")))
(enh-command-with-auth
(enh-command-create-search name query))
(enh-browsing-reflesh-page 'search-list)))
(defun evernote-edit-search ()
"Create a saved search"
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(enh-command-with-auth
(let* ((search-alist (enh-get-search-name-attr-alist))
(search-attr
(enutil-aget
(completing-read
"Saved search:"
search-alist
nil t)
search-alist)))
(enh-command-update-search
(enutil-aget 'guid search-attr)
(read-string "New Saved search name:"
(enutil-aget 'name search-attr))
(read-string "New Query:"
(enutil-aget 'query search-attr)))))
(clrhash enh-search-info)
(enh-browsing-reflesh-page 'search-list))
(defun evernote-toggle-read-only ()
(interactive)
(if (called-interactively-p) (enh-clear-onmem-cache))
(when evernote-mode
(if (string= (or evernote-note-modified-edit-mode
(enutil-aget 'editMode (enh-get-note-attr evernote-note-guid)))
"XHTML")
(if buffer-read-only
(progn
(setq buffer-read-only nil)
(let ((orig-buffer-modified-p (buffer-modified-p)))
(erase-buffer)
(insert evernote-note-xhtml-mode-content)
(goto-char (point-min))
(set-buffer-modified-p orig-buffer-modified-p)))
(if (buffer-modified-p)
(progn
(ding)
(message "Save the buffer before you toggle read only"))
(setq evernote-note-xhtml-mode-content
(buffer-substring (point-min) (point-max)))
(erase-buffer)
(enh-format-enml evernote-note-xhtml-mode-content (current-buffer))
(goto-char (point-min))
(set-buffer-modified-p nil)
(setq buffer-read-only t)))
(setq buffer-read-only (not buffer-read-only)))
(force-mode-line-update)))
(defvar evernote-mode-info-for-changing-major-mode nil
"Temporal values used when changing the major mode")
(defun evernote-mode-after-save-hook ()
"After save hook for evernote mode. This invalid evernote-mode"
(if evernote-mode
(evernote-mode)))
(defun evernote-mode-change-major-mode-hook ()
"Change major mode hook for evernote mode. This records the note info to the global variable to restore them after changing the major mode"
(if evernote-mode
(setq evernote-mode-info-for-changing-major-mode
(list
(cons 'guid evernote-note-guid)
(cons 'modified-name evernote-note-modified-name)
(cons 'modified-notebook-guid evernote-note-modified-notebook-guid)
(cons 'is-modified-tag-names evernote-note-is-modified-tag-names)
(cons 'modified-tag-names evernote-note-modified-tag-names)
(cons 'modified-edit-mode evernote-note-modified-edit-mode)
(cons 'note-xhtml-mode-content evernote-note-xhtml-mode-content)))))
(defun evernote-mode-after-change-major-mode-hook ()
"After change major mode hook for evernote mode. This restore the note info after changing the major mode"
(if evernote-mode-info-for-changing-major-mode
(progn
(setq evernote-note-modified-name
(enutil-aget 'modified-name evernote-mode-info-for-changing-major-mode))
(setq evernote-note-modified-notebook-guid
(enutil-aget 'modified-notebook-guid evernote-mode-info-for-changing-major-mode))
(setq evernote-note-is-modified-tag-names
(enutil-aget 'is-modified-tag-names evernote-mode-info-for-changing-major-mode))
(setq evernote-note-modified-tag-names
(enutil-aget 'modified-tag-names evernote-mode-info-for-changing-major-mode))
(setq evernote-note-modified-edit-mode
(enutil-aget 'modified-edit-mode evernote-mode-info-for-changing-major-mode))
(evernote-mode ; this must be after setting evernote-note-modified-xxx
(enutil-aget 'guid evernote-mode-info-for-changing-major-mode))
(setq evernote-note-xhtml-mode-content
(enutil-aget 'note-xhtml-mode-content evernote-mode-info-for-changing-major-mode))
(setq evernote-mode-info-for-changing-major-mode nil))))
(add-hook 'after-change-major-mode-hook
'evernote-mode-after-change-major-mode-hook)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Interface for inputing the note name in the minibuffer. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar evernote-read-note-map
(let ((map (make-sparse-keymap))) (set-keymap-parent map minibuffer-local-completion-map) map))
(define-key evernote-read-note-map [tab] 'evernote-read-note-completion) (define-key evernote-read-note-map “C-i” 'evernote-read-note-completion) (define-key evernote-read-note-map “C-m” 'evernote-read-note-finish) (define-key evernote-read-note-map “ ” 'self-insert-command)
(defun evernote-read-note-completion ()
"Complete note name and display completion list"
(interactive)
(let (word result start)
(setq word (enutil-get-minibuffer-string))
(setq result (try-completion word enh-base-displayed-name-attr-alist))
(cond
((eq result t)
(enutil-minibuffer-tmp-message "[Sole Completion]"))
((eq result nil)
(ding)
(enutil-minibuffer-tmp-message "[No Match]"))
((string= result word)
(enh-base-display-note-completion-buf
enh-base-displayed-name-formatted-name-alist
word))
(t (enutil-set-minibuffer-string result)
(end-of-buffer)
(if (eq t
(try-completion result
enh-base-displayed-name-attr-alist))
nil
(enutil-minibuffer-tmp-message "[Complete, but not unique]"))))))
(defun evernote-read-note-finish ()
"Finish input note name"
(interactive)
(if (assoc
(enutil-get-minibuffer-string)
enh-base-displayed-name-attr-alist)
(progn
(let ((completion-buf (get-buffer "*Evernote-Completions*")))
(if completion-buf
(kill-buffer completion-buf)))
(exit-minibuffer))
(enutil-minibuffer-tmp-message "[No Match]")))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Interface for evernote-search-mode. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar evernote-search-mode-map
(let ((map (make-sparse-keymap))) (set-keymap-parent map global-map) map) "Keymap used in evernote search mode.")
(define-key evernote-search-mode-map “C-m” 'evernote-select-note-in-search-mode)
(defvar evernote-search-mode-formatted-name-displayed-name-alist nil
"Alist from formatted names to names used only in evernote-search-mode buffer")
(make-variable-buffer-local 'evernote-search-mode-formatted-name-displayed-name-alist)
(defun evernote-search-mode ()
"Major mode for selecting a note."
(interactive)
(use-local-map evernote-search-mode-map)
(setq buffer-read-only t
truncate-lines t
major-mode 'evernote-search-mode
mode-name "Evernote-Search")
(goto-char (point-min)))
(defun evernote-select-note-in-search-mode ()
"Select a note name on this buffer and input it into the mini buffer"
(interactive)
(if (active-minibuffer-window)
(save-excursion
(let (displayed-name)
(setq displayed-name
(enutil-aget
(enutil-get-current-line-string)
evernote-search-mode-formatted-name-displayed-name-alist))
(if displayed-name
(progn
(kill-buffer (current-buffer))
(enutil-set-minibuffer-string displayed-name)
(exit-minibuffer)))))
(kill-buffer (current-buffer))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; For Anything ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun anything-c-evernote-title-set-candidates ()
(let ((buffer (get-buffer enh-command-output-buffer-name))
candidates)
(when buffer ; create candidates only when logined.
(enh-command-with-auth
(setq candidates
(enh-command-get-note-attrs-from-query
; Put '*' to match the start of a word.
; Note: A wildcard is only permitted at the end of the term,
; not at the beginning or middle for scalability reasons on the service
(format "intitle:\"%s\"*" anything-input))))
candidates)))
(defun anything-c-evernote-title-candidate-transformer (candidates)
(mapcar (lambda (cand)
(cons (enutil-aget 'title cand) cand))
candidates))
(defun anything-c-evernote-title-action (candidate)
(enh-base-open-note-common candidate))
(defvar anything-c-source-evernote-title
'((name . "Evernote Title")
(candidates . anything-c-evernote-title-set-candidates)
(candidate-transformer . anything-c-evernote-title-candidate-transformer)
(action . (("Open" . anything-c-evernote-title-action)))
(volatile)
(requires-pattern . 3)
(delayed)))
(defun anything-evernote-title ()
"Preconfigured `anything' for searching notes with the note names." (interactive) (anything-other-buffer 'anything-c-source-evernote-title "*anything evernote title*"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Helper functions for evernote-mode (enh-base-xxx) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defconst enh-base-enml-template
(concat "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">\n" "<en-note>\n" "</en-note>\n"))
(defun enh-base-open-note-common (note-attr)
"Common procedure of opening a note"
(let* ((note-guid (enutil-aget 'guid note-attr))
(note-name (enutil-aget 'title note-attr))
(note-edit-mode (enutil-aget 'editMode note-attr))
(note-content-file (enutil-aget 'contentFile note-attr))
(opened-buf (enh-base-find-opened-buffer note-guid)))
(unless note-content-file
(setq note-attr (enh-get-note-attr note-guid))
(setq note-content-file (enutil-aget 'contentFile note-attr)))
(if opened-buf
(enutil-move-cursor-to-window opened-buf t)
(let ((buf (generate-new-buffer note-name)))
(set-buffer buf)
(insert-file-contents note-content-file)
(when (string= note-edit-mode "XHTML")
(setq evernote-note-xhtml-mode-content (buffer-string))
(erase-buffer)
(enh-format-enml evernote-note-xhtml-mode-content (current-buffer))
(setq buffer-read-only t))
(evernote-mode note-guid)
; this must be after (evernote-mode) that setup the change major mode hooks.
(enh-base-change-major-mode-from-note-name note-name)
(goto-char (point-min))
(set-buffer-modified-p nil)
(pop-to-buffer buf)))))
(defun enh-base-create-note-common (default-note-name
ask-notebook
create-new-buffer
change-to-evernote-mode
&optional
use-current-buffer-content)
"Common procedure of creating a note"
(let ((notebook-guid (and ask-notebook
(enutil-aget 'guid (enh-read-notebook))))
(tag-names (enh-read-tag-names))
(name (read-string "Note name:" default-note-name))
(edit-mode (enh-read-edit-mode "TEXT"))
content
note-attr)
(if use-current-buffer-content
;; create a note from a buffer.
(progn
(setq note-attr
(enh-command-create-note (current-buffer)
name
notebook-guid
tag-names
edit-mode))
(setq content (buffer-substring (point-min) (point-max))))
;; create a note from scratch.
(if (string= edit-mode "TEXT") ;; edit-mode = TEXT
(with-temp-buffer
(setq note-attr
(enh-command-create-note (current-buffer)
name
notebook-guid
tag-names
edit-mode)))
(with-temp-buffer ;; edit-mode = XHTML
(insert enh-base-enml-template)
(setq note-attr
(enh-command-create-note (current-buffer)
name
notebook-guid
tag-names
edit-mode))
(setq content (buffer-substring (point-min) (point-max))))))
(enh-update-note-and-new-tag-attrs note-attr)
(let ((buf nil))
(save-excursion
(if create-new-buffer
(progn
(setq buf (generate-new-buffer name))
(set-buffer buf)
(when content (insert content)))
(when change-to-evernote-mode
(rename-buffer name t)))
(when change-to-evernote-mode
(set-visited-file-name nil) ; set-visited-file-name must be before (evernote-mode) because it changes the mode line.
(enh-base-change-major-mode-from-note-name name)
(if (not evernote-mode)
(evernote-mode (enutil-aget 'guid note-attr))
(setq evernote-note-guid (enutil-aget 'guid note-attr))
(enh-base-update-mode-line))
(set-buffer-modified-p nil)))
buf)))
(defun enh-base-update-note-common (inbuf guid &optional name notebook-guid is-tag-updated tag-names edit-mode)
"Common procedure of opening a note"
(let ((attr (enh-get-note-attr guid)))
(setq attr
(enh-command-update-note inbuf guid name notebook-guid is-tag-updated tag-names edit-mode))
(enh-update-note-and-new-tag-attrs attr)))
(defun enh-base-read-note-attr (note-attrs &optional display-completion)
"Prompts a note name and returns a note attribute"
(let ((name-num-hash (make-hash-table :test #'equal))
enh-base-displayed-name-attr-alist ; used in evernote-search-mode
enh-base-displayed-name-formatted-name-alist) ; used in evernote-search-mode
(mapc
(lambda (attr)
(let (name displayed-name)
(setq name (enutil-aget 'title attr))
(setq displayed-name
(enh-base-get-displayed-note-name name name-num-hash))
(setq enh-base-displayed-name-attr-alist
(cons (cons displayed-name attr)
enh-base-displayed-name-attr-alist))
(setq enh-base-displayed-name-formatted-name-alist
(cons (cons displayed-name
(format "%-30s %-20s %-15s %s"
(enutil-aget 'updated attr)
(enutil-aget 'name
(enh-get-notebook-attr (enutil-aget 'notebookGuid attr)))
(enh-tag-guids-to-comma-separated-names
(enutil-aget 'tagGuids attr)
15)
displayed-name))
enh-base-displayed-name-formatted-name-alist))))
note-attrs)
(setq enh-base-displayed-name-attr-alist
(nreverse enh-base-displayed-name-attr-alist))
(setq enh-base-displayed-name-formatted-name-alist
(nreverse enh-base-displayed-name-formatted-name-alist))
(if display-completion
(enh-base-display-note-completion-buf
enh-base-displayed-name-formatted-name-alist))
(enutil-aget (read-from-minibuffer "Note:"
nil evernote-read-note-map)
enh-base-displayed-name-attr-alist)))
(defun enh-base-get-displayed-note-name (name name-hash)
"Get displayed note name from the read note name"
(let ((num (gethash name name-num-hash))
result)
(if num
(progn
(setq num (+ num 1))
(setq result (format "%s(%d)" name num))
(puthash name num name-num-hash))
(setq result (substring name 0))
(puthash name 1 name-num-hash))
result))
(defun enh-base-display-note-completion-buf (displayed-name-formatted-name-alist &optional word)
(let (formatted-name-displayed-name-alist completion-buf)
(setq formatted-name-displayed-name-alist
(mapcar (lambda (displayed-name)
(cons
(enutil-aget
displayed-name
enh-base-displayed-name-formatted-name-alist)
displayed-name))
(all-completions
(if word
word
"")
enh-base-displayed-name-formatted-name-alist)))
(save-excursion
(setq completion-buf (get-buffer-create "*Evernote-Completions*"))
(set-buffer completion-buf)
(enh-base-display-note-completion-list
formatted-name-displayed-name-alist)
(setq evernote-search-mode-formatted-name-displayed-name-alist
formatted-name-displayed-name-alist)
(evernote-search-mode))
(display-buffer completion-buf)))
(defun enh-base-display-note-completion-list (formatted-name-displayed-name-alist)
"Display formatted note names on this buffer"
(setq buffer-read-only nil)
(erase-buffer)
(insert (format "total %d\n%-30s %-20s %-15s %s\n\n"
(length formatted-name-displayed-name-alist)
"Last Modified"
"Notebook"
"Tags"
"Title"))
(mapc (lambda (elem)
(insert (car elem) "\n"))
formatted-name-displayed-name-alist)
(setq buffer-read-only t))
(defun enh-base-change-major-mode-from-note-name (note-name)
(let ((buffer-file-name note-name)) (normal-mode)))
(defun enh-base-find-opened-buffer (guid)
"Find a buffer associated with guid"
(let ((found_buf nil))
(save-excursion
(mapc (lambda (buf)
(set-buffer buf)
(if (string= evernote-note-guid guid)
(setq found_buf buf)))
(buffer-list)))
found_buf))
(defun enh-base-update-mode-line (&optional notebook-guid is-set-tag-names tag-names edit-mode)
"Update mode line"
(let ((note-attr (enh-get-note-attr evernote-note-guid)))
(setq vc-mode
(concat "[Notebook:"
(if notebook-guid
(enutil-aget 'name (enh-get-notebook-attr notebook-guid))
(enutil-aget 'name (enh-get-notebook-attr
(enutil-aget 'notebookGuid note-attr))))
"] "
"[Tag:"
(if is-set-tag-names
(mapconcat #'identity tag-names ",")
(enh-tag-guids-to-comma-separated-names
(enutil-aget 'tagGuids note-attr)))
"] "
"[Edit mode:"
(if edit-mode
edit-mode
(enutil-aget 'editMode note-attr))
"]"))
(force-mode-line-update)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Helper functions for evernote-browsing-mode (enh-browsing-xxx) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar evernote-browsing-mode nil
"Non-nil if Evernote Browsing mode is enabled.")
(make-variable-buffer-local 'evernote-browsing-mode)
(defvar enh-browsing-page-type nil) (make-variable-buffer-local 'enh-browsing-page-type)
(defvar enh-browsing-page-description nil) (make-variable-buffer-local 'enh-browsing-page-description)
(defvar enh-browsing-page-data nil) (make-variable-buffer-local 'enh-browsing-page-data)
(defvar enh-browsing-page-data-refresh-closure nil) (make-variable-buffer-local 'enh-browsing-page-data-refresh-closure)
(defvar enh-browsing-page-widget-title nil) (make-variable-buffer-local 'enh-browsing-page-widget-title)
(defvar enh-browsing-page-widget-root nil) (make-variable-buffer-local 'enh-browsing-page-widget-root)
(defvar enh-browsing-page-setup-func nil) (make-variable-buffer-local 'enh-browsing-page-setup-func)
(defun enh-browsing-open-notebook (widget &rest ignored)
"Open a saved search in browsing mode"
(enh-clear-onmem-cache)
(let* ((guid (widget-value widget)) note-attrs)
(enh-command-with-auth
(setq note-attrs
(enh-command-get-note-attrs-from-notebook-and-tag-guids guid nil)))
(enh-browsing-update-page-list)
(enh-browsing-push-page
(enh-browsing-create-page 'note-list
(format "Notes in Notebook: %s"
(enutil-aget 'name
(enh-get-notebook-attr guid)))
note-attrs
`(lambda () (enh-command-get-note-attrs-from-notebook-and-tag-guids
,guid nil))))))
(defun enh-browsing-open-tag (widget &rest ignored)
"Open a tag in browsing mode"
(enh-clear-onmem-cache)
(let ((guid (widget-value widget)) note-attrs)
(enh-command-with-auth
(setq note-attrs
(enh-command-get-note-attrs-from-notebook-and-tag-guids
nil
(if guid
(list guid)
nil))))
(enh-browsing-update-page-list)
(enh-browsing-push-page
(enh-browsing-create-page 'note-list
(if guid
(format "Notes with tag %s"
(enutil-aget 'name
(enh-get-tag-attr guid)))
"All notes")
note-attrs
`(lambda () (enh-command-get-note-attrs-from-notebook-and-tag-guids
nil ',(if guid
(list guid)
nil)))))))
(defun enh-browsing-open-search (widget &rest ignored)
"Open a saved search in browsing mode"
(enh-clear-onmem-cache)
(let* ((guid (widget-value widget)) note-attrs)
(enh-command-with-auth
(setq note-attrs
(enh-command-get-note-attrs-from-query
(enutil-aget 'query
(enh-get-search-attr guid)))))
(enh-browsing-update-page-list)
(enh-browsing-push-page
(enh-browsing-create-page 'note-list
(format "Query Result of Saved Search: %s"
(enutil-aget 'name
(enh-get-search-attr guid)))
note-attrs
`(lambda () (enh-command-get-note-attrs-from-query
,(enutil-aget 'query
(enh-get-search-attr guid))))))))
(defun enh-browsing-open-note (widget &rest ignored)
"Open a note in browsing mode"
(enh-clear-onmem-cache)
(enh-command-with-auth
(let* ((guid (widget-value widget))
(note-attr (enh-get-note-attr guid))
(cur-buf (current-buffer)))
(enh-base-open-note-common note-attr)
(let ((command-keys (this-command-keys)))
(if (and (stringp command-keys)
(or (string= "o" command-keys)
(string= "n" command-keys)
(string= "p" command-keys)))
(enutil-move-cursor-to-window cur-buf t))))))
(defun enh-browsing-push-page (page &optional noswitch)
"Push a new page to the browsing mode"
(enutil-push page evernote-browsing-page-list)
(if noswitch
(save-excursion
(set-buffer page)
(funcall enh-browsing-page-setup-func))
(setq evernote-browsing-current-page page)
(switch-to-buffer page)
(enh-command-with-auth
(funcall enh-browsing-page-setup-func))))
(defun enh-browsing-create-page (type description &optional note-attrs refresh-closure)
"Create a page structure of the attr-list"
(let ((buf (generate-new-buffer (format "*ENB %s* " description))))
(save-excursion
(set-buffer buf)
(setq enh-browsing-page-type type
enh-browsing-page-description description
enh-browsing-page-data note-attrs
enh-browsing-page-data-refresh-closure refresh-closure)
(cond
((eq type 'notebook-list)
(setq enh-browsing-page-setup-func
'enh-browsing-setup-notebook-list-page))
((eq type 'tag-list)
(setq enh-browsing-page-setup-func
'enh-browsing-setup-tag-list-page))
((eq type 'search-list)
(setq enh-browsing-page-setup-func
'enh-browsing-setup-search-list-page))
((eq type 'note-list)
(setq enh-browsing-page-setup-func
'enh-browsing-setup-note-list-page)))
(evernote-browsing-mode))
buf))
(defun enh-browsing-setup-notebook-list-page ()
"Insert notebook list into the browsing buffer"
(when enh-browsing-page-widget-root
(widget-delete enh-browsing-page-widget-root)
(setq enh-browsing-page-widget-root nil))
(let ((notebook-list nil))
(maphash
(lambda (guid attr)
(let ((attr (enh-get-notebook-attr guid)))
(enutil-push `(push-button
:tag ,(format "%-30s %s"
(enutil-aget 'name attr)
(enutil-aget 'defaultNotebook attr))
:format "%[%t%]\n"
:notify enh-browsing-open-notebook
,guid)
notebook-list)))
(enh-get-notebook-attrs))
(setq enh-browsing-page-widget-root
(apply 'widget-create
`(group
(item ,(format "%s\n\ntotal %d\n%-30s %s\n"
enh-browsing-page-description
(hash-table-count (enh-get-notebook-attrs))
"Name"
"Default"))
,@(nreverse notebook-list)))))
(widget-setup)
(goto-char (point-min)))
(defun enh-browsing-setup-tag-list-page ()
"Create a page structure of the attr-list"
(when enh-browsing-page-widget-root
(widget-delete enh-browsing-page-widget-title)
(widget-delete enh-browsing-page-widget-root)
(setq enh-browsing-page-widget-title nil)
(setq enh-browsing-page-widget-root nil))
(let ((guid-children-hash (make-hash-table :test #'equal)))
(maphash
(lambda (guid attr)
(let* ((parent (enutil-aget 'parentGuid attr))
(children (gethash parent guid-children-hash)))
(if children
(puthash parent (cons guid children) guid-children-hash)
(puthash parent (list guid) guid-children-hash))))
(enh-get-tag-attrs))
(setq enh-browsing-page-widget-title
(widget-create 'item (format "Tag List\n\ntotal %d\n" (hash-table-count (enh-get-tag-attrs)))))
(setq enh-browsing-page-widget-root
(apply 'widget-create
(enh-browsing-get-tag-tree nil))))
(widget-setup)
(goto-char (point-min)))
(defun enh-browsing-get-tag-tree (guid) ; root (eq guid nil)
(let* ((children (gethash guid guid-children-hash))
(attr (enh-get-tag-attr guid))
(name (if attr (enutil-aget 'name attr) "All tags")))
(if children
`(tree-widget :node (push-button :tag ,name
:format "%[%t%]\n"
:notify enh-browsing-open-tag
,guid)
:args ,(mapcar
'enh-browsing-get-tag-tree
(nreverse children))
:open ,(if attr nil t))
`(push-button :tag ,name
:format "%[%t%]\n"
:notify enh-browsing-open-tag
,guid))))
(defun enh-browsing-setup-search-list-page ()
"Insert saved search list into the browsing buffer"
(when enh-browsing-page-widget-root
(widget-delete enh-browsing-page-widget-root)
(setq enh-browsing-page-widget-root nil))
(let ((search-list nil))
(maphash
(lambda (guid attr)
(let ((attr (enh-get-search-attr guid)))
(enutil-push `(push-button
:tag ,(format "%-30s %s"
(enutil-aget 'name attr)
(enutil-aget 'query attr))
:format "%[%t%]\n"
:notify enh-browsing-open-search
,guid)
search-list)))
(enh-get-search-attrs))
(setq enh-browsing-page-widget-root
(apply 'widget-create
`(group
(item ,(format "%s\n\ntotal %d\n%-30s %s\n"
enh-browsing-page-description
(hash-table-count (enh-get-search-attrs))
"Name"
"Query"))
,@(nreverse search-list)))))
(widget-setup)
(goto-char (point-min)))
(defun enh-browsing-setup-note-list-page ()
"Insert note list into the browsing buffer"
(when enh-browsing-page-widget-root
(widget-delete enh-browsing-page-widget-root)
(setq enh-browsing-page-widget-root nil))
(when (and (null enh-browsing-page-data)
enh-browsing-page-data-refresh-closure)
(setq enh-browsing-page-data (funcall enh-browsing-page-data-refresh-closure)))
(let ((note-attrs enh-browsing-page-data)
(note-list nil))
(mapc
(lambda (attr)
(enutil-push `(push-button
:tag ,(format "%-30s %-20s %-15s %4s %s"
(enutil-aget 'updated attr)
(enutil-aget 'name
(enh-get-notebook-attr (enutil-aget 'notebookGuid attr)))
(enh-tag-guids-to-comma-separated-names
(enutil-aget 'tagGuids attr)
15)
(enutil-aget 'editMode attr)
(enutil-aget 'title attr))
:format "%[%t%]\n"
:notify enh-browsing-open-note
,(enutil-aget 'guid attr))
note-list))
note-attrs)
(setq enh-browsing-page-widget-root
(apply 'widget-create
`(group
(item ,(format "%s\n\ntotal %d\n%-30s %-20s %-15s %4s %s\n"
enh-browsing-page-description
(length note-attrs)
"Last Modified"
"Notebook"
"Tags"
"Mode"
"Name"))
,@(nreverse note-list)))))
(widget-setup)
(goto-char (point-min)))
(defun enh-browsing-update-page-list ()
(setq evernote-browsing-page-list
(delete nil
(mapcar (lambda (page)
(if (buffer-live-p page) page nil))
evernote-browsing-page-list)))
(unless (memq evernote-browsing-current-page evernote-browsing-page-list)
(setq evernote-browsing-current-page (car evernote-browsing-page-list))))
(defun enh-browsing-get-prev-page ()
(cadr
(memq evernote-browsing-current-page
evernote-browsing-page-list)))
(defun enh-browsing-get-next-page ()
(catch 'next-page
(let (next-page)
(mapc
(lambda (page)
(when (eq page evernote-browsing-current-page)
(throw 'next-page next-page))
(setq next-page page))
evernote-browsing-page-list))))
(defun enh-browsing-get-page-of-type (type)
"Get a page of the type in the browsing mode"
(let ((result nil))
(save-excursion
(mapc
(lambda (page)
(set-buffer page)
(when (eq enh-browsing-page-type type)
(setq result page)))
evernote-browsing-page-list))
result))
(defun enh-browsing-reflesh-page (type)
"Reflesh current page"
(enh-browsing-update-page-list)
(save-excursion
(mapcar (lambda (page)
(set-buffer page)
(when (eq enh-browsing-page-type type)
(when enh-browsing-page-data-refresh-closure
(setq enh-browsing-page-data nil))
(funcall enh-browsing-page-setup-func)))
evernote-browsing-page-list)))
; ; ;(defun evernote-test-list-note () ; “Test” ; (interactive) ; (mapc ; (lambda (tag) ; (insert (format “guid=%s name=%sn” ; (enutil-aget 'guid tag) ; (enutil-aget 'name tag)))) ; (enutil-aget 'tags (enh-command-list-tag))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Functions for executing the external command (enh-command-xxx) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar enh-enclient-command
"/usr/lib/evernote-mode/enclient.rb" "Name of the enclient.rb command")
(defconst enh-command-process-name “Evernote-Client”) (defconst enh-command-output-buffer-name “Evernote-Client-Output”)
;; ;; Const variables. ;;
(defconst enh-command-error-ok 0) (defconst enh-command-error-not-found 100) (defconst enh-command-error-unexpected 101) (defconst enh-command-error-not-authed 102) (defconst enh-command-error-unknown 1) (defconst enh-command-error-bad-data-format 2) (defconst enh-command-error-permission-denied 3) (defconst enh-command-error-internal-error 4) (defconst enh-command-error-data-required 5) (defconst enh-command-error-limit-reached 6) (defconst enh-command-error-quota-reached 7) (defconst enh-command-error-invalid-auth 8) (defconst enh-command-error-auth-expired 9) (defconst enh-command-error-data-conflict 10) (defconst enh-command-error-enml-validation 11) (defconst enh-command-error-shared-unavailable 12)
(defvar enh-command-last-result-code enh-command-error-ok) (defvar enh-command-last-error-message nil) (defvar enh-command-next-command-id 0)
(defun enh-command-login (user passwd)
"Issue login command"
(enh-command-issue
(format ":class => %s, :user => %s, :passwd => %s"
(enutil-to-ruby-string "AuthCommand")
(enutil-to-ruby-string user)
(enutil-to-ruby-string passwd))))
(defun enh-command-get-notebook-attrs ()
"Issue listnotebooks command"
(let ((reply (enh-command-issue
(format ":class => %s"
(enutil-to-ruby-string "ListNotebookCommand")))))
(enutil-aget 'notebooks reply)))
(defun enh-command-get-tag-attrs ()
"Issue listtags command"
(let ((reply (enh-command-issue
(format ":class => %s"
(enutil-to-ruby-string "ListTagCommand")))))
(enutil-aget 'tags reply)))
(defun enh-command-get-note-attr (guid)
"Issue getnote command from the tag name list."
(let ((reply (enh-command-issue
(format ":class => %s, :guid => %s"
(enutil-to-ruby-string "GetNoteCommand")
(enutil-to-ruby-string guid)))))
(enutil-aget 'note reply)))
(defun enh-command-get-note-attrs-from-notebook-and-tag-guids (notebook-guid tag-guids)
"Issue listnotes command from the notebook guid and the tag guids."
(message "notebook %s" notebook-guid)
(let ((reply (enh-command-issue
(format ":class => %s, :notebook_guid => %s, :tag_guids => %s"
(enutil-to-ruby-string "ListNoteCommand")
(enutil-to-ruby-string notebook-guid)
(enutil-to-ruby-string-list tag-guids nil)))))
(enutil-aget 'notes reply)))
(defun enh-command-get-note-attrs-from-query (query)
"Issue listnotes command from the query."
(let ((reply (enh-command-issue
(format ":class => %s, :query => %s"
(enutil-to-ruby-string "SearchNoteCommand")
(enutil-to-ruby-string query)))))
(enutil-aget 'notes reply)))
(defun enh-command-get-note-content (guid edit-mode)
"Issue getnotecontent command specified by the guid and the edit mode."
(let ((reply (enh-command-issue
(format ":class => %s, :guid => %s, :edit_mode => %s"
(enutil-to-ruby-string "GetContentCommand")
(enutil-to-ruby-string guid)
(enutil-to-ruby-string edit-mode)))))
(enutil-aget 'content reply)))
(defun enh-command-create-note (inbuf name notebook-guid tag-names edit-mode)
"Issue createnote command specified by the guid, tags and the edit-mode."
(let ((reply (enh-command-issue
(format ":class => %s, :notebook_guid => %s, :title => %s, :tag_names => %s, :edit_mode => %s, :content => %s"
(enutil-to-ruby-string "CreateNoteCommand")
(enutil-to-ruby-string notebook-guid)
(enutil-to-ruby-string name)
(enutil-to-ruby-string-list tag-names nil)
(enutil-to-ruby-string edit-mode)
(enutil-to-ruby-string (enutil-buffer-string inbuf))))))
(enutil-aget 'note reply)))
(defun enh-command-update-note (inbuf guid name notebook-guid is-tag-updated tag-names edit-mode)
"Issue updatenote command specified by the guid and the parameters for updating."
(let ((reply (enh-command-issue
(format ":class => %s, :guid => %s, :notebook_guid => %s, :title => %s, :tag_names => %s, :edit_mode => %s, :content => %s"
(enutil-to-ruby-string "UpdateNoteCommand")
(enutil-to-ruby-string guid)
(enutil-to-ruby-string notebook-guid)
(enutil-to-ruby-string name)
(enutil-to-ruby-string-list tag-names is-tag-updated)
(enutil-to-ruby-string edit-mode)
(enutil-to-ruby-string (enutil-buffer-string inbuf))))))
(enutil-aget 'note reply)))
(defun enh-command-delete-note (guid)
"Issue deletenote command specified by the guid, tags and the edit mode."
(enh-command-issue
(format ":class => %s, :guid => %s"
(enutil-to-ruby-string "DeleteNoteCommand")
(enutil-to-ruby-string guid))))
(defun enh-command-create-notebook (name default-notebook)
"Issue createnotebook command"
(enh-command-issue
(format ":class => %s, :name => %s, :default_notebook => %s"
(enutil-to-ruby-string "CreateNotebookCommand")
(enutil-to-ruby-string name)
(if default-notebook "true" "false"))))
(defun enh-command-update-notebook (guid name default-notebook)
"Issue updatenotebook command"
(enh-command-issue
(format ":class => %s, :guid => %s, :name => %s, :default_notebook => %s"
(enutil-to-ruby-string "UpdateNotebookCommand")
(enutil-to-ruby-string guid)
(enutil-to-ruby-string name)
(if default-notebook "true" "false"))))
(defun enh-command-get-search-attrs ()
"Issue listsearch command"
(let ((reply (enh-command-issue
(format ":class => %s"
(enutil-to-ruby-string "ListSearchCommand")))))
(enutil-aget 'searches reply)))
(defun enh-command-create-search (name query)
"Issue createsearch command"
(enh-command-issue
(format ":class => %s, :name => %s, :query => %s"
(enutil-to-ruby-string "CreateSearchCommand")
(enutil-to-ruby-string name)
(enutil-to-ruby-string query))))
(defun enh-command-update-search (guid name query)
"Issue updatesearch command"
(enh-command-issue
(format ":class => %s, :guid => %s, :name => %s, :query => %s"
(enutil-to-ruby-string "UpdateSearchCommand")
(enutil-to-ruby-string guid)
(enutil-to-ruby-string name)
(enutil-to-ruby-string query))))
(defun enh-command-issue (command)
(enh-command-setup-process)
(let ((proc (get-process enh-command-process-name))
(reply nil)
(buffer (get-buffer enh-command-output-buffer-name)))
(message "Waiting for the result...")
(save-excursion
(set-buffer buffer)
(erase-buffer)
;(delete-region (point-min) (point-max))
(setq enh-command-next-command-id
(+ 1 enh-command-next-command-id))
(process-send-string proc
(format "{%s, :command_id => %d}"
command enh-command-next-command-id))
(process-send-string proc "\x00\n")
(while (or (not reply)
(enutil-neq (enutil-aget 'command_id reply)
enh-command-next-command-id))
(accept-process-output proc)
(setq reply (enutil-get-first-sexp-in-buffer))))
(message "")
(if (eq (enutil-aget 'class reply) 'ErrorReply)
(progn
(setq enh-command-last-result-code (enutil-aget 'result_code reply))
(setq enh-command-last-error-message (enutil-aget 'message reply))
(throw 'error enh-command-last-result-code))
(setq enh-command-last-result-code enh-command-error-ok)
reply)))
(defun enh-command-sentinel (process event)
(error "enclient.rb %s%s" event
(with-current-buffer enh-command-output-buffer-name
(buffer-string))))
(defun enh-command-setup-process ()
(let ((proc (get-process enh-command-process-name))
(process-connection-type nil)) ; use pipe instead of pty
(when (or (not proc)
(not (eq (process-status proc) 'run)))
(setq proc (start-process enh-command-process-name
enh-command-output-buffer-name
evernote-ruby-command "-S" enh-enclient-command))
(set-process-sentinel proc 'enh-command-sentinel)
(set-process-coding-system proc 'utf-8 'utf-8)
(set-process-query-on-exit-flag proc nil))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Helper functions for all modes in this file (enh-xxx) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar enh-notebook-info (make-hash-table :test #'equal)
"Notebook info associated with the guid")
(defvar enh-tag-info (make-hash-table :test #'equal)
"Tag info associated with the guid")
(defvar enh-search-info (make-hash-table :test #'equal)
"Saved search info associated with the guid")
(defvar enh-note-attr nil
"Note attr associated with most recently accessed guid")
(defvar enh-password-cache-file “~/.evernote-mode/password.gpg”
"Filename of saving password cache.")
(defvar enh-password-cache-buffer “ evernote-password-cache”)
(defun enh-get-notebook-attrs ()
(when (eq (hash-table-count enh-notebook-info) 0)
(mapc
(lambda (attr)
(puthash (enutil-aget 'guid attr) attr enh-notebook-info))
(enh-command-get-notebook-attrs)))
enh-notebook-info)
(defun enh-get-tag-attrs ()
(when (eq (hash-table-count enh-tag-info) 0)
(mapc
(lambda (attr)
(puthash (enutil-aget 'guid attr) attr enh-tag-info))
(enh-command-get-tag-attrs)))
enh-tag-info)
(defun enh-get-search-attrs ()
(when (eq (hash-table-count enh-search-info) 0)
(mapc
(lambda (attr)
(puthash (enutil-aget 'guid attr) attr enh-search-info))
(enh-command-get-search-attrs)))
enh-search-info)
(defun enh-get-note-attr (guid)
"Get the note attr from the guid"
(if (and enh-note-attr
(string= guid (enutil-aget 'guid enh-note-attr)))
enh-note-attr
(setq enh-note-attr (enh-command-get-note-attr guid))))
(defun enh-get-notebook-attr (guid)
"Get the notebook attr from the guid" (gethash guid (enh-get-notebook-attrs)))
(defun enh-get-tag-attr (guid)
"Get the tag attr from the guid" (gethash guid (enh-get-tag-attrs)))
(defun enh-get-search-attr (guid)
"Get the search attr from the guid" (gethash guid (enh-get-search-attrs)))
(defun enh-read-tag-guids (&optional prompt)
(enh-tag-names-to-guids
(enutil-completing-read-multiple
(if prompt
prompt
"Tags (comma separated form):")
(enh-get-tag-name-alist)
nil
t)))
(defun enh-read-tag-names (&optional prompt note-guid)
(enutil-completing-read-multiple
(if prompt
prompt
"Tags (comma separated form):")
(enh-get-tag-name-alist)
nil
nil
(if note-guid
(enh-tag-guids-to-comma-separated-names
(enutil-aget 'tagGuids
(enh-get-note-attr note-guid)))
nil)))
(defun enh-format-enml (content outbuf)
(if evernote-enml-formatter-command
(let ((infile (concat (make-temp-file "evernote-enml") ".html"))
(command (car evernote-enml-formatter-command))
(args (cdr evernote-enml-formatter-command)))
(setq args (append args (list infile)))
(with-temp-buffer
(insert content)
(write-region (point-min) (point-max) infile)
(message "") ; remove the message notifying writing to tmp file.
(let ((coding-system-for-read 'utf-8)
(coding-system-for-write 'utf-8))
(apply 'call-process
command
infile
outbuf
nil
args))))
(save-excursion ; insert the content as is.
(set-buffer outbuf)
(insert content))))
(defun enh-clear-onmem-cache ()
(clrhash enh-notebook-info) (clrhash enh-tag-info) (clrhash enh-search-info) (setq enh-note-attr nil))
(defun enh-read-notebook (&optional default)
(let ((notebook-name-attr-alist (enh-get-notebook-name-attr-alist)))
(enutil-aget (completing-read
"Notebook:"
notebook-name-attr-alist
nil
t
default)
notebook-name-attr-alist)))
(defun enh-read-saved-search (&optional prompt)
(let ((search-name-query-alist (enh-get-search-name-attr-alist)))
(enutil-aget (completing-read
(if prompt
prompt
"Saved search:")
search-name-query-alist
nil t)
search-name-query-alist)))
(defun enh-get-notebook-name-attr-alist ()
"Get the notebook alist for completion from command output"
(let (result)
(maphash
(lambda (guid attr)
(setq result
(cons
(cons (enutil-aget 'name attr)
attr)
result)))
(enh-get-notebook-attrs))
result))
(defun enh-get-tag-name-alist ()
"Get the tag alist for completion from command output"
(let (result)
(maphash
(lambda (guid attr)
(setq result
(cons
(list (enutil-aget 'name attr))
result)))
(enh-get-tag-attrs))
result))
(defun enh-get-search-name-attr-alist ()
"Get the alist for completion from command output"
(let (result)
(maphash
(lambda (guid attr)
(setq result
(cons
(cons (enutil-aget 'name attr)
attr)
result)))
(enh-get-search-attrs))
result))
(defun enh-update-note-and-new-tag-attrs (note-attr)
(let ((tag-guids (enutil-aget 'tagGuids note-attr))
(tag-attrs (enh-get-tag-attrs)))
(when (catch 'result
(mapc
(lambda (guid)
(unless (gethash guid tag-attrs)
(throw 'result t)))
tag-guids)
nil)
(enh-clear-onmem-cache)
(enh-browsing-reflesh-page 'tag-list))))
(defun enh-tag-guids-to-comma-separated-names (tag-guids &optional maxlen)
(let (line)
(setq line
(mapconcat
(lambda (guid)
(enutil-aget 'name (enh-get-tag-attr guid)))
tag-guids
","))
(if maxlen
(truncate-string-to-width line maxlen)
line)))
(defun enh-tag-names-to-comma-separated-oct-names (tag-names)
(mapconcat #'identity (mapcar 'enutil-string-to-oct tag-names) ","))
;;(defun enh-tag-guids-to-names (tag-guids) ;; (mapcar ;; (lambda (tag-guid) ;; (enutil-aget 'name (enh-get-tag-attr tag-guid))) ;; tag-guids))
(defun enh-notebook-name-to-guid (notebook-name)
(let ((notebook-attrs (enh-get-notebook-attrs)))
(catch 'guid
(maphash
(lambda (guid attr)
(let ((name (enutil-aget 'name attr)))
(if (equal notebook-name name)
(throw 'guid guid))))
notebook-attrs))))
(defun enh-tag-names-to-guids (tag-names)
(let ((tag-attrs (enh-get-tag-attrs)))
(mapcar
(lambda (name)
(catch 'guid
(maphash
(lambda (guid attr)
(let ((tag-name (enutil-aget 'name attr)))
(if (equal tag-name name)
(throw 'guid guid))))
tag-attrs)))
tag-names)))
(defun enh-read-edit-mode (default)
(let ((edit-mode
(completing-read "Edit mode (type \"TEXT\" or \"XHTML\"):"
'(("TEXT") ("XHTML"))
nil
t
default)))
(if (and edit-mode (not (string= edit-mode "")))
edit-mode
default)))
(defun enh-bookmark-make-record ()
"Make a emacs bookmark entry for a evernote buffer." `(,(buffer-name) ,@(bookmark-make-record-default 'no-file) ;; if bookmark-bmenu-toggle-filenames is t and a bookmark record doesn't ;; have filename field, , Emacs23.2 raises an error. ;; Here is the workaround suggested by ARISAWA Akihiro. (filename . ,(format "%s (evernote:%s)" (buffer-name) evernote-note-guid)) (handler . enh-bookmark-jump)))
(defun enh-bookmark-jump (bookmark) ;; Note: don't rename this function for the bookmark file compatibility
"Default bookmark handler for evernote buffers."
(enh-command-with-auth
(let ((filename (bookmark-get-filename bookmark)))
(if (and filename (string-match "(evernote:\\(.*\\))$" filename))
(progn
(let* ((guid (substring filename (match-beginning 1) (match-end 1)))
(attr (enh-command-get-note-attr guid)))
(enh-base-open-note-common attr)
(let ((buf (current-buffer)))
(bookmark-default-handler
`("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bookmark))))))
(message (format "Invalid bookmark %s" (bookmark-name-from-full-record bookmark)))))))
(defun enh-bookmark-prepare ()
(interactive)
(set (make-local-variable 'bookmark-make-record-function)
'enh-bookmark-make-record))
(defun enh-password-cache-load ()
"Load the password cache from the file"
(when (and evernote-password-cache
(file-exists-p enh-password-cache-file))
(with-current-buffer (get-buffer-create enh-password-cache-buffer)
(insert-file-contents enh-password-cache-file)
(read (current-buffer)))))
(defun enh-password-cache-save (user-password)
"Save the password cache to the file"
(when evernote-password-cache
(with-current-buffer (get-buffer-create enh-password-cache-buffer)
(write-region (prin1-to-string user-password) nil
enh-password-cache-file))))
(defun enh-password-cache-close ()
"Close the password cache buffer" (when (get-buffer enh-password-cache-buffer) (kill-buffer enh-password-cache-buffer)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; General util functions (enutil-xxx) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun enutil-completing-read-multiple
(prompt table &optional predicate require-match initial-input hist def inherit-input-method)
"Read multiple strings with completion. and return nil if no input is given"
(let (results)
(setq results
(completing-read-multiple prompt
table
predicate
require-match
initial-input
hist
def
inherit-input-method))
(delete "" results)))
(defun enutil-aget (key alist)
(let ((result-cons (assoc key alist)))
(when result-cons
(cdr result-cons))))
(defun enutil-aset (key alist value)
(let ((result-cons (assoc key alist)))
(if result-cons
(setcdr result-cons value)
(setq alist (cons (cons key value) alist)))
alist))
(defun enutil-get-current-line-string ()
(save-excursion
(buffer-substring
(progn
(beginning-of-line)
(point))
(progn
(end-of-line)
(point)))))
(defun enutil-erase-buffer-forcibly ()
(let ((buffer-read-only nil)) (erase-buffer)))
(defun enutil-get-first-line (str)
"Get first line of the string" (let ((begin (string-match "^.*$" str))) (substring str begin (match-end 0))))
(defun enutil-get-minibuffer-string ()
(save-excursion
(enutil-set-buffer-to-minibuffer)
(buffer-substring
(progn
(goto-char (+ 1 (minibuffer-prompt-width)))
(point))
(progn
(end-of-line)
(point)))))
(defun enutil-set-minibuffer-string (str)
(save-excursion
(enutil-set-buffer-to-minibuffer)
(delete-region
(progn
(goto-char (+ 1 (minibuffer-prompt-width)))
(point))
(progn
(end-of-line)
(point)))
(insert str)))
(defun enutil-set-buffer-to-minibuffer ()
(set-buffer (window-buffer (active-minibuffer-window))))
(defun enutil-minibuffer-tmp-message (msg)
(save-excursion (goto-char (point-max)) (save-excursion (insert " " msg)) (sit-for 1) (delete-region (point) (point-max))))
(defun enutil-move-cursor-to-window (buf &optional pop)
"Move cursor to the window associated with the bufer"
(let ((buf-window (get-buffer-window buf)))
(if buf-window
(select-window buf-window)
(if pop
(pop-to-buffer buf)
(switch-to-buffer buf)))))
(defun enutil-get-first-sexp-in-buffer ()
(condition-case nil
(car (read-from-string
(buffer-substring
(point-min)
(point-max))))
(error nil)))
(defun enutil-hash-mapcar (func hash)
(let (result)
(maphash
(lambda (key value)
(cons
(funcall func key value)
result)))
(nreverse result)))
(defun enutil-to-ruby-string (str)
(if str
(progn
(setq str (replace-regexp-in-string "\\\\" "\\\\\\\\" str))
(setq str (replace-regexp-in-string "'" "\\\\'" str))
(concat "'" str "'"))
"nil"))
(defun enutil-to-ruby-string-list (str-list return-empty-array)
(if str-list
(concat
"["
(mapconcat #'enutil-to-ruby-string str-list ",")
"]")
(if return-empty-array
"[]"
"nil")))
(defun enutil-buffer-string (buf)
(save-excursion (set-buffer buf) (buffer-string)))
(provide 'evernote-mode)
;;(setq debug-on-error t)
;; Local Variables: ;; indent-tabs-mode: nil ;; End: