diff options
| author | Daiki Ueno | 2012-04-26 11:03:19 +0900 |
|---|---|---|
| committer | Daiki Ueno | 2012-04-26 11:03:19 +0900 |
| commit | 823ad1d7e83d2e98ba19d686f3c310707ca27c9a (patch) | |
| tree | 760fb7be50307daa5e1e042088d89dab0c53dc61 | |
| parent | 8a4ca8e339479442885e7c79af1ec32cb79b7895 (diff) | |
| download | emacs-823ad1d7e83d2e98ba19d686f3c310707ca27c9a.tar.gz emacs-823ad1d7e83d2e98ba19d686f3c310707ca27c9a.zip | |
Revive plstore editing mode previously reverted due to feature freeze.
| -rw-r--r-- | lisp/gnus/ChangeLog | 10 | ||||
| -rw-r--r-- | lisp/gnus/plstore.el | 135 |
2 files changed, 139 insertions, 6 deletions
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog index 52f140d9192..be4d0675781 100644 --- a/lisp/gnus/ChangeLog +++ b/lisp/gnus/ChangeLog | |||
| @@ -1,3 +1,13 @@ | |||
| 1 | 2012-04-26 Daiki Ueno <ueno@unixuser.org> | ||
| 2 | |||
| 3 | * plstore.el: Revive the editing feature. | ||
| 4 | (plstore-mode): New mode to edit plstore file. | ||
| 5 | (plstore-mode-toggle-display, plstore-mode-original) | ||
| 6 | (plstore-mode-decoded): New command. | ||
| 7 | (plstore--encode, plstore--decode, plstore--write-contents-functions) | ||
| 8 | (plstore--insert-buffer, plstore--make): New function. | ||
| 9 | (plstore-open, plstore-save): Simplify by using them. | ||
| 10 | |||
| 1 | 2012-04-16 Glenn Morris <rgm@gnu.org> | 11 | 2012-04-16 Glenn Morris <rgm@gnu.org> |
| 2 | 12 | ||
| 3 | * nndraft.el (nndraft-request-list): Fix declaration. | 13 | * nndraft.el (nndraft-request-list): Fix declaration. |
diff --git a/lisp/gnus/plstore.el b/lisp/gnus/plstore.el index cbd5e2a3b0a..2f446c84071 100644 --- a/lisp/gnus/plstore.el +++ b/lisp/gnus/plstore.el | |||
| @@ -64,8 +64,18 @@ | |||
| 64 | ;; | 64 | ;; |
| 65 | ;; Editing: | 65 | ;; Editing: |
| 66 | ;; | 66 | ;; |
| 67 | ;; Currently not supported but in the future plstore will provide a | 67 | ;; This file also provides `plstore-mode', a major mode for editing |
| 68 | ;; major mode to edit PLSTORE files. | 68 | ;; the PLSTORE format file. Visit a non-existing file and put the |
| 69 | ;; following line: | ||
| 70 | ;; | ||
| 71 | ;; (("foo" :host "foo.example.org" :secret-user "user")) | ||
| 72 | ;; | ||
| 73 | ;; where the prefixing `:secret-' means the property (without | ||
| 74 | ;; `:secret-' prefix) is marked as secret. Thus, when you save the | ||
| 75 | ;; buffer, the `:secret-user' property is encrypted as `:user'. | ||
| 76 | ;; | ||
| 77 | ;; You can toggle the view between encrypted form and the decrypted | ||
| 78 | ;; form with C-c C-c. | ||
| 69 | 79 | ||
| 70 | ;;; Code: | 80 | ;;; Code: |
| 71 | 81 | ||
| @@ -107,6 +117,10 @@ symmetric encryption will be used.") | |||
| 107 | 117 | ||
| 108 | (put 'plstore-encrypt-to 'permanent-local t) | 118 | (put 'plstore-encrypt-to 'permanent-local t) |
| 109 | 119 | ||
| 120 | (defvar plstore-encoded nil) | ||
| 121 | |||
| 122 | (put 'plstore-encoded 'permanent-local t) | ||
| 123 | |||
| 110 | (defvar plstore-cache-passphrase-for-symmetric-encryption nil) | 124 | (defvar plstore-cache-passphrase-for-symmetric-encryption nil) |
| 111 | (defvar plstore-passphrase-alist nil) | 125 | (defvar plstore-passphrase-alist nil) |
| 112 | 126 | ||
| @@ -194,10 +208,6 @@ symmetric encryption will be used.") | |||
| 194 | (generate-new-buffer (format " plstore %s" filename)))) | 208 | (generate-new-buffer (format " plstore %s" filename)))) |
| 195 | (store (plstore--make buffer))) | 209 | (store (plstore--make buffer))) |
| 196 | (with-current-buffer buffer | 210 | (with-current-buffer buffer |
| 197 | ;; In the future plstore will provide a major mode called | ||
| 198 | ;; `plstore-mode' to edit PLSTORE files. | ||
| 199 | (if (eq major-mode 'plstore-mode) | ||
| 200 | (error "%s is opened for editing; kill the buffer first" file)) | ||
| 201 | (erase-buffer) | 211 | (erase-buffer) |
| 202 | (condition-case nil | 212 | (condition-case nil |
| 203 | (insert-file-contents-literally file) | 213 | (insert-file-contents-literally file) |
| @@ -435,6 +445,119 @@ If no one is selected, symmetric encryption will be performed. " | |||
| 435 | (plstore--insert-buffer plstore) | 445 | (plstore--insert-buffer plstore) |
| 436 | (save-buffer))) | 446 | (save-buffer))) |
| 437 | 447 | ||
| 448 | (defun plstore--encode (plstore) | ||
| 449 | (plstore--decrypt plstore) | ||
| 450 | (let ((merged-alist (plstore--get-merged-alist plstore))) | ||
| 451 | (concat "(" | ||
| 452 | (mapconcat | ||
| 453 | (lambda (entry) | ||
| 454 | (setq entry (copy-sequence entry)) | ||
| 455 | (let ((merged-plist (cdr (assoc (car entry) merged-alist))) | ||
| 456 | (plist (cdr entry))) | ||
| 457 | (while plist | ||
| 458 | (if (string-match "\\`:secret-" (symbol-name (car plist))) | ||
| 459 | (setcar (cdr plist) | ||
| 460 | (plist-get | ||
| 461 | merged-plist | ||
| 462 | (intern (concat ":" | ||
| 463 | (substring (symbol-name | ||
| 464 | (car plist)) | ||
| 465 | (match-end 0))))))) | ||
| 466 | (setq plist (nthcdr 2 plist))) | ||
| 467 | (prin1-to-string entry))) | ||
| 468 | (plstore--get-alist plstore) | ||
| 469 | "\n") | ||
| 470 | ")"))) | ||
| 471 | |||
| 472 | (defun plstore--decode (string) | ||
| 473 | (let* ((alist (car (read-from-string string))) | ||
| 474 | (pointer alist) | ||
| 475 | secret-alist | ||
| 476 | plist | ||
| 477 | entry) | ||
| 478 | (while pointer | ||
| 479 | (unless (stringp (car (car pointer))) | ||
| 480 | (error "Invalid PLSTORE format %s" string)) | ||
| 481 | (setq plist (cdr (car pointer))) | ||
| 482 | (while plist | ||
| 483 | (when (string-match "\\`:secret-" (symbol-name (car plist))) | ||
| 484 | (setq entry (assoc (car (car pointer)) secret-alist)) | ||
| 485 | (unless entry | ||
| 486 | (setq entry (list (car (car pointer))) | ||
| 487 | secret-alist (cons entry secret-alist))) | ||
| 488 | (setcdr entry (plist-put (cdr entry) | ||
| 489 | (intern (concat ":" | ||
| 490 | (substring (symbol-name | ||
| 491 | (car plist)) | ||
| 492 | (match-end 0)))) | ||
| 493 | (car (cdr plist)))) | ||
| 494 | (setcar (cdr plist) t)) | ||
| 495 | (setq plist (nthcdr 2 plist))) | ||
| 496 | (setq pointer (cdr pointer))) | ||
| 497 | (plstore--make nil alist nil secret-alist))) | ||
| 498 | |||
| 499 | (defun plstore--write-contents-functions () | ||
| 500 | (when plstore-encoded | ||
| 501 | (let ((store (plstore--decode (buffer-string))) | ||
| 502 | (file (buffer-file-name))) | ||
| 503 | (unwind-protect | ||
| 504 | (progn | ||
| 505 | (set-visited-file-name nil) | ||
| 506 | (with-temp-buffer | ||
| 507 | (plstore--insert-buffer store) | ||
| 508 | (write-region (buffer-string) nil file))) | ||
| 509 | (set-visited-file-name file) | ||
| 510 | (set-buffer-modified-p nil)) | ||
| 511 | t))) | ||
| 512 | |||
| 513 | (defun plstore-mode-original () | ||
| 514 | "Show the original form of the this buffer." | ||
| 515 | (interactive) | ||
| 516 | (when plstore-encoded | ||
| 517 | (if (and (buffer-modified-p) | ||
| 518 | (y-or-n-p "Save buffer before reading the original form? ")) | ||
| 519 | (save-buffer)) | ||
| 520 | (erase-buffer) | ||
| 521 | (insert-file-contents-literally (buffer-file-name)) | ||
| 522 | (set-buffer-modified-p nil) | ||
| 523 | (setq plstore-encoded nil))) | ||
| 524 | |||
| 525 | (defun plstore-mode-decoded () | ||
| 526 | "Show the decoded form of the this buffer." | ||
| 527 | (interactive) | ||
| 528 | (unless plstore-encoded | ||
| 529 | (if (and (buffer-modified-p) | ||
| 530 | (y-or-n-p "Save buffer before decoding? ")) | ||
| 531 | (save-buffer)) | ||
| 532 | (let ((store (plstore--make (current-buffer)))) | ||
| 533 | (plstore--init-from-buffer store) | ||
| 534 | (erase-buffer) | ||
| 535 | (insert | ||
| 536 | (substitute-command-keys "\ | ||
| 537 | ;;; You are looking at the decoded form of the PLSTORE file.\n\ | ||
| 538 | ;;; To see the original form content, do \\[plstore-mode-toggle-display]\n\n")) | ||
| 539 | (insert (plstore--encode store)) | ||
| 540 | (set-buffer-modified-p nil) | ||
| 541 | (setq plstore-encoded t)))) | ||
| 542 | |||
| 543 | (defun plstore-mode-toggle-display () | ||
| 544 | "Toggle the display mode of PLSTORE between the original and decoded forms." | ||
| 545 | (interactive) | ||
| 546 | (if plstore-encoded | ||
| 547 | (plstore-mode-original) | ||
| 548 | (plstore-mode-decoded))) | ||
| 549 | |||
| 550 | ;;;###autoload | ||
| 551 | (define-derived-mode plstore-mode emacs-lisp-mode "PLSTORE" | ||
| 552 | "Major mode for editing PLSTORE files." | ||
| 553 | (make-local-variable 'plstore-encoded) | ||
| 554 | (add-hook 'write-contents-functions #'plstore--write-contents-functions) | ||
| 555 | (define-key plstore-mode-map "\C-c\C-c" #'plstore-mode-toggle-display) | ||
| 556 | ;; to create a new file with plstore-mode, mark it as already decoded | ||
| 557 | (if (called-interactively-p 'any) | ||
| 558 | (setq plstore-encoded t) | ||
| 559 | (plstore-mode-decoded))) | ||
| 560 | |||
| 438 | (provide 'plstore) | 561 | (provide 'plstore) |
| 439 | 562 | ||
| 440 | ;;; plstore.el ends here | 563 | ;;; plstore.el ends here |