~ubuntu-branches/ubuntu/utopic/evernote-mode/utopic-proposed

« back to all changes in this revision

Viewing changes to .pc/change_install_destination/evernote-mode.el

  • Committer: Bazaar Package Importer
  • Author(s): Youhei SASAKI
  • Date: 2010-11-16 14:45:38 UTC
  • Revision ID: james.westby@ubuntu.com-20101116144538-4ox9xv49zzvj1048
Tags: 0.10-1
Initial release (Closes: #603668)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
;;
 
2
;;  Copyright 2010 Yusuke Kawakami
 
3
;;
 
4
;;   Licensed under the Apache License, Version 2.0 (the "License");
 
5
;;   you may not use this file except in compliance with the License.
 
6
;;   You may obtain a copy of the License at
 
7
;;
 
8
;;       http://www.apache.org/licenses/LICENSE-2.0
 
9
;;
 
10
;;   Unless required by applicable law or agreed to in writing, software
 
11
;;   distributed under the License is distributed on an "AS IS" BASIS,
 
12
;;   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
;;   See the License for the specific language governing permissions and
 
14
;;   limitations under the License.
 
15
 
 
16
;;
 
17
;; evernote-mode home page is at:
 
18
;; Author: Yusuke Kawakami
 
19
;; Version: 0.03
 
20
;; Keywords: tools
 
21
 
 
22
;; This emacs lisp offers the interactive functions to open, edit, and update notes of Evernote.
 
23
;; The minor mode Evernote-mode is applied to the buffer editing a note of Evernote.
 
24
;;
 
25
;; Please copy this file into emacs lisp library directory or place it in
 
26
;; a directory (for example "~/lisp") and write $HOME/.emacs like this.
 
27
;;
 
28
;;      (add-to-list 'load-path "~/lisp")
 
29
;;      (require 'evernote-mode)
 
30
;;      (global-set-key "\C-cec" 'evernote-create-note)
 
31
;;      (global-set-key "\C-ceo" 'evernote-open-note)
 
32
;;      (global-set-key "\C-ces" 'evernote-search-notes)
 
33
;;      (global-set-key "\C-ceS" 'evernote-do-saved-search)
 
34
;;      (global-set-key "\C-cew" 'evernote-write-note)
 
35
;;
 
36
;; There is one hooks, evernotes-mode-hook.
 
37
;; The usage of the hook is shown as follows.
 
38
;;
 
39
;; (setq evernote-mode-hook
 
40
;;   '(lambda ()
 
41
;;      (...)))
 
42
 
 
43
;;; Code
 
44
 
 
45
(defvar evernote-mode nil
 
46
  "Non-nil if Evernote mode is enabled.")
 
47
(make-variable-buffer-local 'evernote-mode)
 
48
 
 
49
(defvar evernote-note-guid nil
 
50
  "Note guid of the buffer")
 
51
(make-variable-buffer-local 'evernote-note-guid)
 
52
 
 
53
(defvar evernote-note-name nil
 
54
  "Note name of the buffer")
 
55
(make-variable-buffer-local 'evernote-note-name)
 
56
 
 
57
(defvar evernote-note-tags nil
 
58
  "Tags of the buffer")
 
59
(make-variable-buffer-local 'evernote-note-tags)
 
60
 
 
61
(defvar evernote-note-edit-mode nil
 
62
  "Edit mode of the buffer")
 
63
(make-variable-buffer-local 'evernote-note-edit-mode)
 
64
 
 
65
(defvar evernote-mode-map (make-sparse-keymap)
 
66
  "Keymap used in evernote mode.")
 
67
(define-key evernote-mode-map "\C-x\C-s" 'evernote-save-note)
 
68
(define-key evernote-mode-map "\C-cet"   'evernote-edit-tags)
 
69
(define-key evernote-mode-map "\C-cee"   'evernote-change-edit-mode)
 
70
(define-key evernote-mode-map "\C-cer"   'evernote-rename-note)
 
71
(define-key evernote-mode-map "\C-ced"   'evernote-delete-note)
 
72
 
 
73
(defvar evernote-read-note-map
 
74
  (copy-keymap minibuffer-local-completion-map))
 
75
(define-key evernote-read-note-map [tab] 'evernote-read-note-completion)
 
76
(define-key evernote-read-note-map "\C-i" 'evernote-read-note-completion)
 
77
(define-key evernote-read-note-map "\C-m" 'evernote-read-note-finish)
 
78
(define-key evernote-read-note-map  " "   'self-insert-command)
 
79
 
 
80
 
 
81
(defvar evernote-search-mode-map (copy-keymap global-map)
 
82
  "Keymap used in evernote search mode.")
 
83
(define-key evernote-search-mode-map "\C-m" 'evernote-select-note-in-search-mode)
 
84
 
 
85
(defvar evernote-search-mode-formatted-name-displayed-name-alist nil
 
86
  "Alist from formatted names to names used only in evernote-search-mode buffer")
 
87
(make-variable-buffer-local 'evernote-search-mode-formatted-name-displayed-name-alist)
 
88
 
 
89
 
 
90
(defconst evernote-command-output-buffer-name "*Evernote-Client-Output*")
 
91
(defconst evernote-error-ok                  0)
 
92
(defconst evernote-error-fail                100)
 
93
(defconst evernote-error-parse               101)
 
94
(defconst evernote-error-unknown             1)
 
95
(defconst evernote-error-bad-data-format     2)
 
96
(defconst evernote-error-permission-denied   3)
 
97
(defconst evernote-error-internal-error      4)
 
98
(defconst evernote-error-data-required       5)
 
99
(defconst evernote-error-limit-reached       6)
 
100
(defconst evernote-error-quota-reached       7)
 
101
(defconst evernote-error-invalid-auth        8)
 
102
(defconst evernote-error-auth-expired        9)
 
103
(defconst evernote-error-data-conflict      10)
 
104
(defconst evernote-error-enml-validation    11)
 
105
(defconst evernote-error-shared-unavailable 12)
 
106
 
 
107
 
 
108
;;
 
109
;; Interactive functions.
 
110
;;
 
111
 
 
112
 
 
113
(defun evernote-open-note ()
 
114
  "Open a note"
 
115
  (interactive)
 
116
  (evernote-command-with-auth
 
117
   (lambda ()
 
118
     (evernote-open-note-common
 
119
      (evernote-command-get-note-list-from-tags
 
120
       (evernote-completing-read-multiple
 
121
        "Tags used for search (comma separated form. default search all tags):"
 
122
        (evernote-get-tag-alist
 
123
         (evernote-command-get-tag-list))
 
124
        nil t))))))
 
125
 
 
126
 
 
127
(defun evernote-search-notes ()
 
128
  "Search notes with query and open a note among them"
 
129
  (interactive)
 
130
  (evernote-command-with-auth
 
131
   (lambda ()
 
132
     (evernote-open-note-common
 
133
      (evernote-command-get-note-list-from-query
 
134
       (read-string "Query:"))
 
135
      t))))
 
136
 
 
137
 
 
138
(defun evernote-do-saved-search ()
 
139
  "Do a saved search and open a note"
 
140
  (interactive)
 
141
  (evernote-command-with-auth
 
142
   (lambda ()
 
143
     (evernote-open-note-common
 
144
      (evernote-command-get-note-list-from-query
 
145
       (let ((search-alist
 
146
              (evernote-get-search-alist (evernote-command-get-search-list))))
 
147
         (evernote-assoc-cdr
 
148
          'query
 
149
          (evernote-assoc-cdr
 
150
           (completing-read
 
151
            "Saved search:"
 
152
            search-alist
 
153
            nil t)
 
154
           search-alist))))
 
155
      t))))
 
156
 
 
157
 
 
158
(defun evernote-open-note-common (note-command-output &optional display-completion)
 
159
  "Common procedure of opening a note"
 
160
  (let (note-attr note-guid note-name note-edit-mode note-tags opened-buf)
 
161
    (setq note-attr (evernote-read-note-attr note-command-output display-completion))
 
162
    (setq note-guid (evernote-assoc-cdr 'guid note-attr)
 
163
          note-name (evernote-assoc-cdr 'name note-attr)
 
164
          note-edit-mode (evernote-assoc-cdr 'edit-mode note-attr)
 
165
          note-tags (evernote-assoc-cdr 'tags note-attr))
 
166
    (setq opened-buf (evernote-find-opened-buffer note-guid))
 
167
    (if opened-buf
 
168
        (evernote-move-cursor-to-window opened-buf)
 
169
      (progn
 
170
        (evernote-create-note-buffer
 
171
         note-guid
 
172
         note-name
 
173
         note-edit-mode
 
174
         note-tags
 
175
         (evernote-command-get-note-content note-guid note-edit-mode))))))
 
176
 
 
177
 
 
178
(defun evernote-save-note ()
 
179
  "Save a note"
 
180
  (interactive)
 
181
  (if (and evernote-note-guid (buffer-modified-p))
 
182
      (evernote-command-with-auth
 
183
       (lambda ()
 
184
         (progn
 
185
           (evernote-command-update-note
 
186
            (current-buffer)
 
187
            evernote-note-guid
 
188
            evernote-note-name
 
189
            evernote-note-tags
 
190
            evernote-note-edit-mode)
 
191
           (set-buffer-modified-p nil))))
 
192
    (message "(No changes need to be saved)")))
 
193
 
 
194
 
 
195
(defun evernote-create-note ()
 
196
  "Create a note"
 
197
  (interactive)
 
198
  (evernote-command-with-auth
 
199
   (lambda ()
 
200
     (let (tags name edit-mode)
 
201
       (setq tags
 
202
             (evernote-completing-read-multiple
 
203
              "Attached Tags (comma separated form):"
 
204
              (evernote-get-tag-alist
 
205
               (evernote-command-get-tag-list))))
 
206
       (setq name (read-string "Note name:"))
 
207
       (setq edit-mode "TEXT")
 
208
       (switch-to-buffer (generate-new-buffer name))
 
209
       (evernote-command-create-note (current-buffer)
 
210
                                     name
 
211
                                     tags
 
212
                                     edit-mode)
 
213
       (setq evernote-note-guid (evernote-eval-command-result)
 
214
             evernote-note-name name
 
215
             evernote-note-tags tags
 
216
             evernote-note-edit-mode edit-mode)
 
217
       (evernote-mode)
 
218
       (evernote-update-mode-line)
 
219
       (set-buffer-modified-p nil)))))
 
220
 
 
221
 
 
222
(defun evernote-write-note ()
 
223
  "Write buffer to a note"
 
224
  (interactive)
 
225
  (evernote-command-with-auth
 
226
   (lambda ()
 
227
     (let (tags name edit-mode)
 
228
       (setq tags
 
229
             (evernote-completing-read-multiple
 
230
              "Attached Tags (comma separated form):"
 
231
              (evernote-get-tag-alist
 
232
               (evernote-command-get-tag-list))))
 
233
       (setq name (read-string "Note name:" (buffer-name)))
 
234
       (setq edit-mode (evernote-read-edit-mode "TEXT"))
 
235
       (evernote-command-create-note (current-buffer)
 
236
                                     name
 
237
                                     tags
 
238
                                     edit-mode)
 
239
       (setq evernote-note-guid (evernote-eval-command-result)
 
240
             evernote-note-name name
 
241
             evernote-note-tags tags
 
242
             evernote-note-edit-mode edit-mode)
 
243
       (if (not evernote-mode)
 
244
           (evernote-mode))
 
245
       (rename-buffer name t)
 
246
       (evernote-update-mode-line)
 
247
       (set-buffer-modified-p nil)))))
 
248
 
 
249
 
 
250
(defun evernote-edit-tags ()
 
251
  "Add or remove tags from/to the note"
 
252
  (interactive)
 
253
  (evernote-command-with-auth
 
254
   (lambda ()
 
255
     (if evernote-mode
 
256
         (progn
 
257
           (setq evernote-note-tags
 
258
                 (evernote-completing-read-multiple
 
259
                  "Change attached Tags (comma separated form):"
 
260
                  (evernote-get-tag-alist (evernote-command-get-tag-list))
 
261
                  nil nil (mapconcat #'identity evernote-note-tags ",")))
 
262
           (evernote-update-mode-line)
 
263
           (set-buffer-modified-p t))))))
 
264
 
 
265
 
 
266
(defun evernote-change-edit-mode ()
 
267
  "Change edit mode of the note"
 
268
  (interactive)
 
269
  (evernote-command-with-auth
 
270
   (lambda ()
 
271
     (if evernote-mode
 
272
         (progn
 
273
           (setq evernote-note-edit-mode
 
274
                 (evernote-read-edit-mode evernote-note-edit-mode))
 
275
           (evernote-update-mode-line)
 
276
           (set-buffer-modified-p t))))))
 
277
 
 
278
 
 
279
(defun evernote-rename-note ()
 
280
  "Rename a note"
 
281
  (interactive)
 
282
  (if evernote-mode
 
283
      (progn
 
284
        (setq evernote-note-name
 
285
              (read-string "New note name:" evernote-note-name))
 
286
        (rename-buffer evernote-note-name t)
 
287
        (set-buffer-modified-p t))))
 
288
 
 
289
 
 
290
(defun evernote-delete-note ()
 
291
  "Delete a note"
 
292
  (interactive)
 
293
  (if (and evernote-mode
 
294
           (y-or-n-p "Do you really want to remove this note? "))
 
295
      (evernote-command-with-auth
 
296
       (lambda ()
 
297
         (evernote-command-delete-note evernote-note-guid)
 
298
         (kill-buffer (current-buffer))))))
 
299
 
 
300
 
 
301
(defun evernote-create-search ()
 
302
  "Create a saved search"
 
303
  (interactive)
 
304
  (evernote-command-with-auth
 
305
   (lambda ()
 
306
     (evernote-command-create-search
 
307
      (read-string "Saved Search Name:")
 
308
      (read-string "Query:")))))
 
309
 
 
310
 
 
311
;;
 
312
;; Helper functions.
 
313
;;
 
314
 
 
315
(defun evernote-command-with-auth (func &rest args)
 
316
  "Add or remove tags from/to the note"
 
317
  (let ((error-code (catch 'error (apply func args))))
 
318
    (if (or (eq error-code evernote-error-invalid-auth)
 
319
            (eq error-code evernote-error-auth-expired))
 
320
        (let ((error-code (catch 'error (evernote-command-login))))
 
321
          (if (eq error-code t)
 
322
              (apply func args)
 
323
            (message (evernote-error-message error-code))))
 
324
      (message (evernote-error-message error-code)))))
 
325
 
 
326
 
 
327
(defun evernote-get-tag-alist (tag-command-out)
 
328
  "Get the alist for completion from command output"
 
329
  (let (acc collect-tagname)
 
330
    (setq collect-tagname
 
331
          (lambda (node)
 
332
            (setq acc
 
333
                  (cons
 
334
                   (list (evernote-assoc-cdr 'name node))
 
335
                   acc))
 
336
            (mapc collect-tagname (evernote-assoc-cdr 'children node))))
 
337
    (mapcar collect-tagname tag-command-out)
 
338
    (nreverse acc)))
 
339
 
 
340
 
 
341
(defun evernote-get-search-alist (search-command-out)
 
342
  "Get the alist for completion from command output"
 
343
  (mapcar
 
344
   (lambda (elem)
 
345
     (cons
 
346
      (evernote-assoc-cdr 'name elem)
 
347
      elem))
 
348
   search-command-out))
 
349
 
 
350
 
 
351
(defun evernote-read-note-attr (note-command-out &optional display-completion)
 
352
  "Prompts a note name and returns a note attribute"
 
353
  (let ((name-num-hash (make-hash-table :test #'equal))
 
354
        evernote-note-displayed-name-attr-alist ; used in evernote-search-mode
 
355
        evenote-note-displayed-name-formatted-name-alist) ; used in evernote-search-mode
 
356
    (mapc
 
357
     (lambda (attr)
 
358
       (let (name displayed-name)
 
359
         (setq name (evernote-assoc-cdr 'name attr))
 
360
         (setq displayed-name
 
361
               (evernote-get-displayed-note-name name name-num-hash))
 
362
         (setq evernote-note-displayed-name-attr-alist
 
363
               (cons (cons displayed-name attr)
 
364
                     evernote-note-displayed-name-attr-alist))
 
365
         (setq evenote-note-displayed-name-formatted-name-alist
 
366
               (cons (cons displayed-name
 
367
                           (format "%s   %s"
 
368
                                   (evernote-assoc-cdr 'updated attr)
 
369
                                   displayed-name))
 
370
                     evenote-note-displayed-name-formatted-name-alist))))
 
371
     note-command-out)
 
372
    (setq evernote-note-displayed-name-attr-alist
 
373
          (nreverse evernote-note-displayed-name-attr-alist))
 
374
    (setq evenote-note-displayed-name-formatted-name-alist
 
375
          (nreverse evenote-note-displayed-name-formatted-name-alist))
 
376
    (if display-completion
 
377
        (evernote-display-note-completion-buf
 
378
         evenote-note-displayed-name-formatted-name-alist))
 
379
    (evernote-assoc-cdr (read-from-minibuffer "Note:"
 
380
                                              nil evernote-read-note-map)
 
381
                        evernote-note-displayed-name-attr-alist)))
 
382
 
 
383
 
 
384
(defun evernote-get-displayed-note-name (name name-hash)
 
385
  "Get displayed note name from the read note name"
 
386
  (let ((num (gethash name name-num-hash))
 
387
        result)
 
388
    (if num
 
389
        (progn
 
390
          (setq num (+ num 1))
 
391
          (setq result (format "%s(%d)" name num))
 
392
          (puthash name num name-num-hash))
 
393
      (setq result (substring name 0))
 
394
      (puthash name 1 name-num-hash))
 
395
    result))
 
396
 
 
397
 
 
398
(defun evernote-read-note-completion ()
 
399
  "Complete note name and display completion list"
 
400
  (interactive)
 
401
  (let (word result start)
 
402
    (setq word (evernote-get-minibuffer-string))
 
403
    (setq result (try-completion word evernote-note-displayed-name-attr-alist))
 
404
    ;(evernote-minibuffer-tmp-message (concat "[" word "]"))
 
405
    (cond
 
406
     ((eq result t)
 
407
      (evernote-minibuffer-tmp-message "[Sole Completion]"))
 
408
     ((eq result nil)
 
409
      (ding)
 
410
      (evernote-minibuffer-tmp-message "[No Match]"))
 
411
     ((string= result word)
 
412
      (evernote-display-note-completion-buf
 
413
       evenote-note-displayed-name-formatted-name-alist))
 
414
     (t (evernote-set-minibuffer-string result)
 
415
        (end-of-buffer)
 
416
        (if (eq t
 
417
                (try-completion result
 
418
                                evernote-note-displayed-name-attr-alist))
 
419
            nil
 
420
          (evernote-minibuffer-tmp-message "[Complete, but not unique]"))))))
 
421
 
 
422
 
 
423
(defun evernote-read-note-finish ()
 
424
  "Finish input note name"
 
425
  (interactive)
 
426
  (if (assoc
 
427
       (evernote-get-minibuffer-string)
 
428
       evernote-note-displayed-name-attr-alist)
 
429
      (progn
 
430
        (let ((completion-buf (get-buffer "*Evernote-Completions*")))
 
431
          (if completion-buf
 
432
              (kill-buffer completion-buf)))
 
433
        (exit-minibuffer))
 
434
    (evernote-minibuffer-tmp-message "[No Match]")))
 
435
 
 
436
 
 
437
(defun evernote-display-note-completion-buf (displayed-name-formatted-name-alist &optional word)
 
438
  (let (formatted-name-displayed-name-alist completion-buf)
 
439
    (setq formatted-name-displayed-name-alist
 
440
          (mapcar (lambda (displayed-name)
 
441
                    (cons
 
442
                     (evernote-assoc-cdr
 
443
                      displayed-name
 
444
                      evenote-note-displayed-name-formatted-name-alist)
 
445
                     displayed-name))
 
446
                  (all-completions
 
447
                   (if word
 
448
                       word
 
449
                     "")
 
450
                   evenote-note-displayed-name-formatted-name-alist)))
 
451
    (save-excursion
 
452
      (setq completion-buf (get-buffer-create "*Evernote-Completions*"))
 
453
      (set-buffer completion-buf)
 
454
      (evernote-display-note-completion-list
 
455
       formatted-name-displayed-name-alist)
 
456
      (setq evernote-search-mode-formatted-name-displayed-name-alist
 
457
            formatted-name-displayed-name-alist)
 
458
      (evernote-search-mode))
 
459
    (display-buffer completion-buf)))
 
460
 
 
461
 
 
462
(defun evernote-display-note-completion-list (formatted-name-displayed-name-alist)
 
463
  "Display formatted note names on this buffer"
 
464
  (setq buffer-read-only nil)
 
465
  (erase-buffer)
 
466
  (mapc (lambda (elem)
 
467
          (insert (car elem) "\n"))
 
468
        formatted-name-displayed-name-alist)
 
469
  (setq buffer-read-only t))
 
470
 
 
471
 
 
472
(defun evernote-select-note-in-search-mode ()
 
473
  "Select a note name on this buffer and input it into the mini buffer"
 
474
  (interactive)
 
475
  (save-excursion
 
476
    (let (displayed-name)
 
477
      (setq displayed-name
 
478
            (evernote-assoc-cdr
 
479
             (evernote-get-current-line-string)
 
480
             evernote-search-mode-formatted-name-displayed-name-alist))
 
481
      (kill-buffer (current-buffer))
 
482
      (if (active-minibuffer-window)
 
483
          (progn
 
484
            (evernote-set-minibuffer-string displayed-name)
 
485
            (exit-minibuffer))))))
 
486
 
 
487
 
 
488
(defun evernote-find-opened-buffer (guid)
 
489
  "Find a buffer associated with guid"
 
490
  (let ((found_buf nil))
 
491
    (save-excursion
 
492
      (mapc (lambda (buf)
 
493
              (set-buffer buf)
 
494
              (if (string= evernote-note-guid guid)
 
495
                  (setq found_buf buf)))
 
496
            (buffer-list)))
 
497
    found_buf))
 
498
 
 
499
 
 
500
(defun evernote-move-cursor-to-window (buf)
 
501
  "Move cursor to the window associated with the bufer"
 
502
  (let ((buf-window (get-buffer-window buf)))
 
503
    (if buf-window
 
504
        (select-window buf-window)
 
505
      (pop-to-buffer buf))))
 
506
 
 
507
 
 
508
(defun evernote-create-note-buffer (guid name edit-mode tags content)
 
509
  "Create new buffer for the note"
 
510
  (save-excursion
 
511
    (let ((buf (generate-new-buffer name)))
 
512
      (set-buffer buf)
 
513
      (insert content)
 
514
      (setq evernote-note-guid guid
 
515
            evernote-note-name name
 
516
            evernote-note-edit-mode edit-mode
 
517
            evernote-note-tags tags)
 
518
      (evernote-mode)
 
519
      (goto-char (point-min))
 
520
      (evernote-update-mode-line)
 
521
      (set-buffer-modified-p nil)
 
522
      (pop-to-buffer buf))))
 
523
 
 
524
 
 
525
(defun evernote-get-tag-list-string (tags maxlen)
 
526
  (substring
 
527
   (mapconcat #'identity tags ",")
 
528
   0 maxlen))
 
529
 
 
530
 
 
531
(defun evernote-read-edit-mode (default)
 
532
  (completing-read "Edit Mode (type \"TEXT\" or \"XHTML\"):"
 
533
                   '(("TEXT") ("XHTML"))
 
534
                   nil t default))
 
535
 
 
536
 
 
537
(defun evernote-string-to-oct (string)
 
538
  "Convert the string into quoted backslashed octal edit mode."
 
539
  (concat
 
540
   "\""
 
541
   (apply 'concat (mapcar (lambda (string)
 
542
                            (format "\\%03o" string))
 
543
                          (mapcar 'identity (encode-coding-string string 'utf-8))))
 
544
   "\""))
 
545
 
 
546
 
 
547
(defun evernote-assoc-cdr (key alist)
 
548
  (cdr (assoc key alist)))
 
549
 
 
550
 
 
551
(defun evernote-get-current-line-string ()
 
552
  (save-excursion
 
553
    (buffer-substring
 
554
     (progn
 
555
       (beginning-of-line)
 
556
       (point))
 
557
     (progn
 
558
       (end-of-line)
 
559
       (point)))))
 
560
 
 
561
 
 
562
(defun evernote-get-minibuffer-string ()
 
563
  (save-excursion
 
564
    (evernote-set-buffer-to-minibuffer)
 
565
    (buffer-substring
 
566
     (progn
 
567
       (goto-char (+ 1 (minibuffer-prompt-width)))
 
568
       (point))
 
569
     (progn
 
570
       (end-of-line)
 
571
       (point)))))
 
572
 
 
573
 
 
574
(defun evernote-set-minibuffer-string (str)
 
575
  (save-excursion
 
576
    (evernote-set-buffer-to-minibuffer)
 
577
    (delete-region
 
578
     (progn
 
579
       (goto-char (+ 1 (minibuffer-prompt-width)))
 
580
       (point))
 
581
     (progn
 
582
       (end-of-line)
 
583
       (point)))
 
584
    (insert str)))
 
585
 
 
586
 
 
587
(defun evernote-set-buffer-to-minibuffer ()
 
588
  (set-buffer (window-buffer (active-minibuffer-window))))
 
589
 
 
590
 
 
591
(defun evernote-minibuffer-tmp-message (msg)
 
592
  (save-excursion
 
593
    (goto-char (point-max))
 
594
    (save-excursion (insert " " msg))
 
595
    (sit-for 1)
 
596
    (delete-region (point) (point-max))))
 
597
 
 
598
 
 
599
(defun evernote-update-mode-line ()
 
600
  "Update mode line"
 
601
  (setq vc-mode
 
602
        (concat "[Tag:" (mapconcat #'identity evernote-note-tags ",") "] "
 
603
                "[Edit mode:" evernote-note-edit-mode "]"))
 
604
  (force-mode-line-update))
 
605
 
 
606
 
 
607
(defun evernote-completing-read-multiple
 
608
  (prompt table &optional predicate require-match initial-input hist def inherit-input-method)
 
609
  "Read multiple strings with completion. and return nil if no input is given"
 
610
  (let (results)
 
611
    (setq results
 
612
          (completing-read-multiple prompt
 
613
                                    table
 
614
                                    predicate
 
615
                                    require-match
 
616
                                    initial-input
 
617
                                    hist
 
618
                                    def
 
619
                                    inherit-input-method))
 
620
    (delete "" results)))
 
621
 
 
622
 
 
623
;;
 
624
;; Command interface.
 
625
;;
 
626
 
 
627
(defun evernote-command-login ()
 
628
  "Issue login command"
 
629
  (let* ((user (read-string "Evernote user name:"))
 
630
         (passwd (read-passwd "Passwd:")))
 
631
    (evernote-issue-command nil "login" user passwd)))
 
632
 
 
633
 
 
634
(defun evernote-command-get-tag-list ()
 
635
  "Issue listtags command"
 
636
  (evernote-issue-command nil "listtags")
 
637
  (evernote-eval-command-result))
 
638
 
 
639
 
 
640
(defun evernote-command-get-note-list-from-tags (tag-names)
 
641
  "Issue listnotes command from the tag name list."
 
642
  (if tag-names
 
643
      (let ((oct-tag-names
 
644
             (mapconcat #'identity (mapcar 'evernote-string-to-oct tag-names) ",")))
 
645
        (evernote-issue-command nil "listnotes" "-t" oct-tag-names))
 
646
    (evernote-issue-command nil "listnotes"))
 
647
  (evernote-eval-command-result))
 
648
 
 
649
 
 
650
(defun evernote-command-get-note-list-from-query (query)
 
651
  "Issue listnotes command from the query."
 
652
  (if query
 
653
      (let ((oct-query (evernote-string-to-oct query)))
 
654
        (evernote-issue-command nil "listnotes" "-q" oct-query))
 
655
    (evernote-issue-command nil "listnotes"))
 
656
  (evernote-eval-command-result))
 
657
 
 
658
 
 
659
(defun evernote-command-get-note-content (guid note-edit-mode)
 
660
  "Issue getnotecontent command specified by the guid and the edit mode."
 
661
  (let ((option (cond
 
662
                 ((string= note-edit-mode "XHTML") "-x")
 
663
                 ((string= note-edit-mode "TEXT") "--text"))))
 
664
    (evernote-issue-command nil "getnotecontent" guid option)
 
665
    (evernote-get-command-result)))
 
666
 
 
667
 
 
668
(defun evernote-command-create-note (inbuf name tags edit-mode)
 
669
  "Issue createnote command specified by the guid, tags and the edit-mode."
 
670
  (let (edit-mode-option)
 
671
    (cond
 
672
     ((string= edit-mode "XHTML")
 
673
      (setq edit-mode-option "-x"))
 
674
     ((string= edit-mode "TEXT")
 
675
      (setq edit-mode-option "--text")))
 
676
    (if tags
 
677
        (evernote-issue-command inbuf
 
678
                                "createnote" "-c"
 
679
                                "-t" (mapconcat #'identity (mapcar 'evernote-string-to-oct tags) ",")
 
680
                                (evernote-string-to-oct name)
 
681
                                edit-mode-option)
 
682
      (evernote-issue-command inbuf
 
683
                              "createnote" "-c"
 
684
                              (evernote-string-to-oct name)
 
685
                              edit-mode-option))))
 
686
 
 
687
 
 
688
(defun evernote-command-update-note (inbuf guid name tags edit-mode)
 
689
  "Issue updatenote command specified by the guid and the parameters for updating."
 
690
  (let (edit-mode-option)
 
691
    (cond
 
692
     ((string= edit-mode "XHTML")
 
693
      (setq edit-mode-option "-x"))
 
694
     ((string= edit-mode "TEXT")
 
695
      (setq edit-mode-option "--text")))
 
696
    (if tags
 
697
        (evernote-issue-command inbuf
 
698
                                "updatenote" "-c"
 
699
                                "-t" (mapconcat #'identity (mapcar 'evernote-string-to-oct tags) ",")
 
700
                                guid (evernote-string-to-oct name) edit-mode-option)
 
701
      (evernote-issue-command inbuf
 
702
                              "updatenote" "-c" "--delete-all-tags"
 
703
                              guid (evernote-string-to-oct name) edit-mode-option))))
 
704
 
 
705
 
 
706
(defun evernote-command-delete-note (guid)
 
707
  "Issue deletenote command specified by the guid, tags and the edit mode."
 
708
  (evernote-issue-command nil "deletenote" guid))
 
709
 
 
710
 
 
711
(defun evernote-command-get-search-list ()
 
712
  "Issue listsearch command"
 
713
  (evernote-issue-command nil "listsearch")
 
714
  (evernote-eval-command-result))
 
715
 
 
716
 
 
717
(defun evernote-command-create-search (name query)
 
718
  "Issue createsearch command"
 
719
  (evernote-issue-command nil
 
720
                          "createsearch"
 
721
                          (evernote-string-to-oct name)
 
722
                          (evernote-string-to-oct query)))
 
723
 
 
724
 
 
725
(defun evernote-issue-command (inbuf &rest args)
 
726
  "Invoke external process to issue an evernote command."
 
727
  (let ((outbuf (get-buffer-create evernote-command-output-buffer-name))
 
728
        (infile nil)
 
729
        (coding-system-for-read 'utf-8)
 
730
        (coding-system-for-write 'utf-8))
 
731
    (if inbuf
 
732
        (save-excursion
 
733
          (set-buffer inbuf)
 
734
          (setq infile (make-temp-file "evernote"))
 
735
          (write-region (point-min) (point-max) infile)))
 
736
    (save-excursion
 
737
      (set-buffer outbuf)
 
738
      (set-buffer-file-coding-system 'utf-8)
 
739
      (erase-buffer))
 
740
    (message "Waiting for the result...")
 
741
    (let ((result (apply 'call-process "ruby" infile outbuf nil "-S" "enclient.rb" args)))
 
742
      (message "")
 
743
      (cond
 
744
       ((eq result evernote-error-ok) t)
 
745
       (t (throw 'error result))))))
 
746
 
 
747
 
 
748
(defun evernote-get-command-result ()
 
749
  "Get the result of the result of the lately issued command as a string."
 
750
  (let ((outbuf (get-buffer-create evernote-command-output-buffer-name)))
 
751
    (save-excursion
 
752
      (set-buffer outbuf)
 
753
      (set-buffer-file-coding-system 'utf-8)
 
754
      (buffer-substring (point-min) (point-max)))))
 
755
 
 
756
 
 
757
(defun evernote-eval-command-result ()
 
758
  "Get the result of the result of the lately issued command as a string and eval the string."
 
759
  (let ((outbuf (get-buffer-create evernote-command-output-buffer-name)))
 
760
    (save-excursion
 
761
      (set-buffer outbuf)
 
762
      (set-buffer-file-coding-system 'utf-8)
 
763
      (car (read-from-string
 
764
            (buffer-substring (point-min) (point-max)))))))
 
765
 
 
766
 
 
767
(defun evernote-error-message (error-code)
 
768
  "Get the error message corresponding to  the integer command result."
 
769
  (cond
 
770
   ((eq error-code evernote-error-ok)                 "OK")
 
771
   ((eq error-code evernote-error-fail)               "System error")
 
772
   ((eq error-code evernote-error-parse)              "Parse error")
 
773
   ((eq error-code evernote-error-unknown)            "Unknown error")
 
774
   ((eq error-code evernote-error-bad-data-format)    "Bad data format")
 
775
   ((eq error-code evernote-error-permission-denied)  "Permission denied")
 
776
   ((eq error-code evernote-error-internal-error)     "Internal error")
 
777
   ((eq error-code evernote-error-data-required)      "Data required")
 
778
   ((eq error-code evernote-error-limit-reached)      "Limit reached")
 
779
   ((eq error-code evernote-error-quota-reached)      "Quota reached")
 
780
   ((eq error-code evernote-error-invalid-auth)       "Invalid auth")
 
781
   ((eq error-code evernote-error-auth-expired)       "Auth expired")
 
782
   ((eq error-code evernote-error-data-conflict)      "Data conflict")
 
783
   ((eq error-code evernote-error-enml-validation)    "Enml validation. Tried to save a note of invalid format.")
 
784
   ((eq error-code evernote-error-shared-unavailable) "Shared unavailable")))
 
785
 
 
786
 
 
787
;;
 
788
;; Evernote mode
 
789
;;
 
790
 
 
791
(defun evernote-search-mode ()
 
792
  "Major mode for selecting a note."
 
793
  (interactive)
 
794
  (use-local-map evernote-search-mode-map)
 
795
  (setq buffer-read-only t
 
796
        truncate-lines t
 
797
        major-mode 'evernote-search-mode
 
798
        mode-name "Evernote-Search")
 
799
  (goto-char (point-min)))
 
800
 
 
801
;;
 
802
;; Evernote mode
 
803
;;
 
804
 
 
805
(defun evernote-mode ()
 
806
  "Toggle Evernote mode, a minor mode for using evernote functions."
 
807
  (interactive)
 
808
  (or (assq 'evernote-mode minor-mode-alist)
 
809
      (setq minor-mode-alist (cons '(evernote-mode " Evernote") minor-mode-alist)))
 
810
  (or (assq 'evernote-mode minor-mode-map-alist)
 
811
      (setq minor-mode-map-alist
 
812
            (cons (cons 'evernote-mode evernote-mode-map) minor-mode-map-alist)))
 
813
  (set-buffer-file-coding-system 'utf-8)
 
814
  (setq evernote-mode (not evernote-mode))
 
815
  (setq vc-mode
 
816
        (concat "[Tag:" (mapconcat #'identity evernote-note-tags ",") "] "
 
817
                "[Edit Mode:" evernote-note-edit-mode "]"))
 
818
  (run-hooks 'evernote-mode-hook))
 
819
 
 
820
 
 
821
(provide 'evernote-mode)
 
822
 
 
823
;;(setq debug-on-error t)
 
824