* emacs/ updates

This commit is contained in:
Dirk-Jan C. Binnema
2011-08-06 10:43:33 +03:00
parent 8e6429a764
commit d90208b0c5
4 changed files with 208 additions and 159 deletions

View File

@ -116,7 +116,7 @@ moving")
(defvar mu-trash-folder nil "location of your trash-folder folder") (defvar mu-trash-folder nil "location of your trash-folder folder")
(setq (setq
mu-maildir "/home/djcb/Maildir" mu-maildir "/home/djcb/Maildir"
mu-inbox-folder "/inbox" mu-inbox-folder "/inbox"
mu-outbox-folder "/outbox" mu-outbox-folder "/outbox"
mu-sent-folder "/sent" mu-sent-folder "/sent"
@ -127,17 +127,17 @@ moving")
(setq mu-quick-folders (setq mu-quick-folders
'("/archive" "/bulkarchive" "/todo")) '("/archive" "/bulkarchive" "/todo"))
(defun mu-ask-folder (prompt) (defun mu-ask-maildir (prompt &optional fullpath)
"ask user with PROMPT for a folder name, return the full path "ask user with PROMPT for a maildir name, if fullpath is
the folder" non-nill, return the fulpath (ie, mu-maildir prepended to the
maildir"
(interactive) (interactive)
(let* (let*
((showfolders ((showfolders
(delete-dups (delete-dups
(append (list mu-inbox-folder mu-sent-folder) mu-quick-folders))) (append (list mu-inbox-folder mu-sent-folder) mu-quick-folders)))
(chosen (ido-completing-read prompt showfolders))) (chosen (ido-completing-read prompt showfolders)))
(concat mu-maildir chosen))) (concat (if fullpath mu-maildir "") chosen)))
(defun mu-ask-key (prompt) (defun mu-ask-key (prompt)
"Get a char from user, only accepting characters marked with [x] in prompt, "Get a char from user, only accepting characters marked with [x] in prompt,
@ -217,7 +217,11 @@ old one first"
(defun mu-log (frm &rest args) (defun mu-log (frm &rest args)
(with-current-buffer (get-buffer-create "*mu-log*") (with-current-buffer (get-buffer-create "*mu-log*")
(insert (apply 'format (concat frm "\n") args)))) (goto-char (point-max))
(insert (apply 'format
(concat
(format-time-string "%x %X " (current-time))
frm "\n") args))))
(provide 'mu-common) (provide 'mu-common)

View File

@ -89,51 +89,54 @@ the mu find output")
"process-filter for the 'mu find --format=sexp output; it "process-filter for the 'mu find --format=sexp output; it
accumulates the strings into valid sexps by checking of the accumulates the strings into valid sexps by checking of the
';;eom' end-of-msg marker, and then evaluating them" ';;eom' end-of-msg marker, and then evaluating them"
(save-excursion (when (buffer-live-p (process-buffer proc))
(setq mu-buf (concat mu-buf str)) (with-current-buffer (process-buffer proc)
(let ((eom (string-match mu-eom mu-buf))) (save-excursion
(while (numberp eom) (setq mu-buf (concat mu-buf str))
(let* ((msg (car (read-from-string (substring mu-buf 0 eom)))) (let ((eom (string-match mu-eom mu-buf)))
(inhibit-read-only t)) (while (numberp eom)
(goto-char (point-max)) (let* ((msg (car (read-from-string (substring mu-buf 0 eom))))
(mu-headers-set-path (plist-get msg :path)) (inhibit-read-only t))
(save-match-data (insert (mu-headers-header msg) ?\n))) (goto-char (point-max))
(setq mu-buf (substring mu-buf (match-end 0))) (mu-headers-set-path (plist-get msg :path))
(setq eom (string-match mu-eom mu-buf)))))) (save-match-data (insert (mu-headers-header msg) ?\n)))
(setq mu-buf (substring mu-buf (match-end 0)))
(setq eom (string-match mu-eom mu-buf))))))))
(defun mu-headers-process-sentinel (proc msg) (defun mu-headers-process-sentinel (proc msg)
"Check the mu-headers process upon completion" "Check the mu-headers process upon completion"
(let ((status (process-status proc)) (when (buffer-live-p (process-buffer proc))
(exit-status (process-exit-status proc))) (with-current-buffer (process-buffer proc)
(if (memq status '(exit signal)) (let ((status (process-status proc))
(let ((inhibit-read-only t) (exit-status (process-exit-status proc)))
(text (if (memq status '(exit signal))
(cond (let ((inhibit-read-only t)
((eq status 'signal) (text
"Search process killed (results incomplete)")
((eq status 'exit)
(cond (cond
((= 0 exit-status) "End of search results") ((eq status 'signal)
((= 2 exit-status) "No matches found") "Search process killed (results incomplete)")
((= 4 exit-status) "Database problem; try running 'mu index'") ((eq status 'exit)
(t (format "Some error occured; mu-headers returned %d" (cond
exit-status)))) ((= 0 exit-status) "End of search results")
(t "Unknown status")))) ;; shouldn't happen ((= 2 exit-status) "No matches found")
(save-excursion ((= 4 exit-status) "Database problem; try running 'mu index'")
(goto-char (point-max)) (t (format "Some error occured; mu-headers returned %d"
(insert (mu-str text))))))) exit-status))))
(t "Unknown status")))) ;; shouldn't happen
(save-excursion
(goto-char (point-max))
(insert (mu-str text)))))))))
;; Note, the 'mu find --format=sexp' sexp is almost the same as the ones that ;; Note, the 'mu find --format=sexp' sexp is almost the same as the ones that
;; 'mu view --format=sexp' produces (see mu-get-message), with the difference ;; 'mu view --format=sexp' produces (see mu-get-message), with the difference
;; that former may give more than one result, and that mu-headers output comes ;; that former may give more than one result, and that mu-headers output comes
;; from the database rather than file, and does _not_ contain the message body ;; from the database rather than file, and does _not_ contain the message body
(defun mu-headers (expr) (defun mu-headers-search (expr)
"search in the mu database" "search in the mu database"
(interactive "s[mu] messages to find: ") (interactive "s[mu] search for: ")
(let* ((buf (mu-get-new-buffer mu-headers-buffer-name)) (let* ((buf (mu-get-new-buffer mu-headers-buffer-name))
(dummy-arg "--fields=\"dummy\"") ;; ignored (dummy-arg "--fields=\"dummy\"") ;; ignored
(proc (start-process mu-headers-buffer-name buf (proc (start-process mu-headers-buffer-name buf
mu-binary mu-binary
"find" "find"
@ -145,6 +148,7 @@ the mu find output")
"--format=sexp" "--format=sexp"
"--quiet" "--quiet"
expr))) expr)))
(mu-log "search: '%s'" expr)
(switch-to-buffer buf) (switch-to-buffer buf)
(mu-headers-mode) (mu-headers-mode)
@ -262,17 +266,25 @@ set text property 'path"
(defvar mu-headers-mode-map (defvar mu-headers-mode-map
(let ((map (make-sparse-keymap))) (let ((map (make-sparse-keymap)))
(define-key map "s" 'mu-headers-search)
(define-key map "q" 'mu-quit-buffer) (define-key map "q" 'mu-quit-buffer)
(define-key map "s" 'mu-headers-change-sort) (define-key map "s" 'mu-headers-change-sort)
(define-key map "g" 'mu-headers-refresh) (define-key map "g" 'mu-headers-refresh)
;; navigation
(define-key map "n" 'mu-headers-next)
(define-key map "p" 'mu-headers-previous)
(define-key map "j" 'mu-headers-jump-to-maildir)
;; marking/unmarking/executing ;; marking/unmarking/executing
(define-key map "m" 'mu-headers-mark-for-move) (define-key map "m" 'mu-headers-mark-for-move)
(define-key map "d" 'mu-headers-mark-for-trash) (define-key map "d" 'mu-headers-mark-for-trash)
(define-key map "D" 'mu-headers-mark-for-deletion) (define-key map "D" 'mu-headers-mark-for-deletion)
(define-key map "u" 'mu-headers-unmark) (define-key map "u" 'mu-headers-unmark)
(define-key map "U" 'mu-headers-unmark-all)
(define-key map "x" 'mu-headers-marked-execute) (define-key map "x" 'mu-headers-marked-execute)
;; message composition ;; message composition
(define-key map "r" 'mu-reply) (define-key map "r" 'mu-reply)
(define-key map "f" 'mu-forward) (define-key map "f" 'mu-forward)
@ -301,6 +313,12 @@ set text property 'path"
(progn (message "No message before this one") nil) (progn (message "No message before this one") nil)
t)) t))
(defun mu-headers-jump-to-maildir ()
"show the messages in one of the standard folders"
(interactive)
(let ((fld (mu-ask-maildir "Jump to maildir: ")))
(mu-headers-search (concat "maildir:" fld))))
(defun mu-headers-refresh () (defun mu-headers-refresh ()
"re-run the query for the current search expression, but only "re-run the query for the current search expression, but only
if the search process is not already running" if the search process is not already running"
@ -349,7 +367,7 @@ if the search process is not already running"
(and (call-interactively 'mu-headers-change-sort-order) (and (call-interactively 'mu-headers-change-sort-order)
(call-interactively 'mu-headers-change-sort-direction))) (call-interactively 'mu-headers-change-sort-direction)))
(defun mu-headers-add-marked (src dst) (defun mu-headers-add-marked (src &optional dst)
(let ((bol (line-beginning-position 1))) (let ((bol (line-beginning-position 1)))
(if (gethash bol mu-headers-marks-hash) (if (gethash bol mu-headers-marks-hash)
(progn (message "Message is already marked") nil) (progn (message "Message is already marked") nil)
@ -361,7 +379,6 @@ if the search process is not already running"
(progn (message "Message is not marked") nil) (progn (message "Message is not marked") nil)
(progn (remhash bol mu-headers-marks-hash) t)))) (progn (remhash bol mu-headers-marks-hash) t))))
(defun mu-headers-set-marker (kar) (defun mu-headers-set-marker (kar)
"set the marker at the beginning of this line" "set the marker at the beginning of this line"
(beginning-of-line 1) (beginning-of-line 1)
@ -372,28 +389,31 @@ if the search process is not already running"
(defun mu-headers-mark (action) (defun mu-headers-mark (action)
"mark the current msg for something: move, delete, trash, unmark" "mark the current msg for something: move, delete, trash, unmark"
(let ((target) (src (mu-headers-get-path))) (let ((target) (src (mu-headers-get-path)))
(when (and src (when src
(case action (case action
(move (move
(when (mu-headers-add-marked src (mu-ask-folder "Target maildir: ")) (when (mu-headers-add-marked src
(mu-headers-set-marker ?m))) (mu-ask-maildir "Target maildir: " t))
(trash (mu-headers-set-marker ?m)))
(when (mu-headers-add-marked src mu-trash-folder) (trash
(mu-headers-set-marker ?d))) (when (mu-headers-add-marked src
(delete (concat mu-maildir mu-trash-folder))
(when (mu-headers-add-marked src "/dev/null") (mu-headers-set-marker ?d)))
(mu-headers-set-marker ?D))) (delete
(unmark (when (mu-headers-add-marked src "/dev/null")
(when (mu-headers-remove-marked src "dummy") (mu-headers-set-marker ?D)))
(mu-headers-set-marker nil))) (unmark
(unmark-all (when (mu-headers-remove-marked)
(when (y-or-n-p (format "Sure you want to remove all (%d) marks? " (mu-headers-set-marker nil)))
(hash-table-count mu-headers-marks-hash))) (unmark-all
(save-excursion (when (y-or-n-p (format "Sure you want to remove all (%d) marks? "
(maphash (lambda (k v) (goto-char k) (mu-headers-mark 'unmark)) (hash-table-count mu-headers-marks-hash)))
mu-headers-marks-hash))) (save-excursion
(t (message "Unsupported mark type")))))))) (maphash (lambda (k v) (goto-char k) (mu-headers-mark 'unmark))
mu-headers-marks-hash)))
(t (message "Unsupported mark type"))))
(move-beginning-of-line 2))))
(defun mu-headers-marks-execute () (defun mu-headers-marks-execute ()
"execute the actions for all marked messages" "execute the actions for all marked messages"
(interactive) (interactive)
@ -409,16 +429,36 @@ if the search process is not already running"
(when (mu-message-move src target) (when (mu-message-move src target)
(goto-char bol) (goto-char bol)
(mu-headers-remove-marked) (mu-headers-remove-marked)
(put-text-property bol (line-beginning-position 2) (put-text-property (line-beginning-position 1)
'face 'invisible)))) ;; when it succeedes, hide msg..) (line-beginning-position 2)
mu-headers-marks-hash)))))) 'invisible t)))) ;; when it succeedes, hide msg..)
mu-headers-marks-hash))
(message "Done")
))))
(defun mu-headers-mark-for-move () (interactive) (mu-headers-mark 'move)) (defun mu-headers-mark-for-move () (interactive) (mu-headers-mark 'move))
(defun mu-headers-mark-for-trash () (interactive) (mu-headers-mark 'trash)) (defun mu-headers-mark-for-trash () (interactive) (mu-headers-mark 'trash))
(defun mu-headers-mark-for-delete () (interactive) (mu-headers-mark 'delete)) (defun mu-headers-mark-for-delete () (interactive) (mu-headers-mark 'delete))
(defun mu-headers-mark-for-deletion () (interactive) (mu-headers-mark 'delete))
(defun mu-headers-unmark () (interactive) (mu-headers-mark 'unmark)) (defun mu-headers-unmark () (interactive) (mu-headers-mark 'unmark))
(defun mu-headers-unmark-all () (interactive) (mu-headers-mark 'unmark-all)) (defun mu-headers-unmark-all () (interactive) (mu-headers-mark 'unmark-all))
(defun mu-headers-reply ()
"Reply to the message at point"
(interactive)
(let ((path (mu-headers-get-path)))
(if path
(mu-message-reply path)
(message "No message at point"))))
(defun mu-headers-forward ()
"Reply to the message at point"
(interactive)
(let ((path (mu-headers-get-path)))
(if path
(mu-message-forward path)
(message "No message at point"))))
(provide 'mu-headers) (provide 'mu-headers)

View File

@ -57,77 +57,84 @@
""))) "")))
(replace-regexp-in-string "^" " > " body))) (replace-regexp-in-string "^" " > " body)))
(defun mu-message-recipients-remove (email lst) (defun mu-message-recipients-remove (lst email-to-remove)
"remove the recipient with EMAIL from the recipient list (of "remove the recipient with EMAIL from the recipient list (of
form '( (\"A\" . \"a@example.com\") (\"B\" . \"B@example.com\"))" form '( (\"A\" . \"a@example.com\") (\"B\" . \"B@example.com\"))"
(remove-if (lambda (c) (string= email (downcase (cdr c))) lst))) (remove-if (lambda (name-email)
(string= email-to-remove (downcase (cdr name-email))))
lst))
(defun mu-message-recipients-to-string (lst) (defun mu-message-recipients-to-string (lst)
"convert a recipient list (of form '( (\"A\" "convert a recipient list (of form '( (\"A\"
. \"a@example.com\") (\"B\" . \"B@example.com\") into a string . \"a@example.com\") (\"B\" . \"B@example.com\") into a string
useful for from/to headers" useful for from/to headers"
(message "recips: %S" lst)
(mapconcat (mapconcat
(lambda (recip) (lambda (recip)
(let ((name (car recip) (email (cdr recip)))) (let ((name (car recip)) (email (cdr recip)))
(format "%s <%s>" (or name "") email))) lst ",")) (format "%s <%s>" (or name "") email))) lst ", "))
(defun mu-message-hidden-header (hdr val) (defun mu-message-hidden-header (hdr val)
"return user-invisible header to the message (HDR: VAL\n)" "return user-invisible header to the message (HDR: VAL\n)"
(propertize (format "%s: %s\n" hdr val) 'invisible t)) (propertize (format "%s: %s\n" hdr val) 'invisible t))
(defun mu-message-reply-or-forward (path &optional forward reply-all) (defun mu-message-reply (path)
"create a reply to the message at PATH; if FORWARD is non-nil, "create a reply to the message at PATH. After creation, switch
create a forwarded message. After creation, switch to the message editor" to the message editor"
(let* ((cmd (concat mu-binary " view --format=sexp " path))
(str (shell-command-to-string cmd))
(msg (car (read-from-string str)))
(buf (get-buffer-create
(generate-new-buffer-name "*mu-draft*")))
(to-lst (mu-message-recipients-remove
(append (plist-get msg :from) (plist-get msg :to))
user-mail-address))
(cc-lst (mu-message-recipients-remove (plist-get msg :cc)
user-mail-address)))
(with-current-buffer buf
(insert
(format "From: %s <%s>\n" user-full-name user-mail-address)
(mu-message-hidden-header "User-agent" (mu-message-user-agent))
(if (boundp 'mail-reply-to) (insert (format "Reply-To: %s\n"
mail-reply-to)) "")
(format "To: %s\n" (if to-lst (mu-message-recipients-to-string to-lst) ""))
(if cc-lst
(format "Cc: %s\n" (mu-message-recipients-to-string cc-lst)))
"Subject: " mu-message-reply-prefix (plist-get msg :subject) "\n"
"--text follows this line--\n\n"
(mu-message-attribution msg)
(mu-message-cite msg)))
(switch-to-buffer buf)
(message-mode)
(message-goto-body)))
(defun mu-message-forward (path)
"create a forward to the message at PATH. After creation, switch
to the message editor"
(let* ((cmd (concat mu-binary " view --format=sexp " path)) (let* ((cmd (concat mu-binary " view --format=sexp " path))
(str (shell-command-to-string cmd)) (str (shell-command-to-string cmd))
(msg (car (read-from-string str))) (msg (car (read-from-string str)))
(buf (get-buffer-create (buf (get-buffer-create
(generate-new-buffer-name "*mu-draft*")))) (generate-new-buffer-name "*mu-draft*"))))
(with-current-buffer buf (with-current-buffer buf
(insert (insert
(format "From: %s <%s>\n" user-full-name user-mail-address) (format "From: %s <%s>\n" user-full-name user-mail-address)
(mu-message-hidden-header "User-agent" (mu-message-user-agent))) (mu-message-hidden-header "User-agent" (mu-message-user-agent))
"To: \n"
(when (boundp 'mail-reply-to) "Subject: " mu-message-forward-prefix (plist-get msg :subject) "\n"
(insert (format "Reply-To: %s\n" mail-reply-to)))
(if forward
(insert
"To:\n"
"Subject: " mu-message-forward-prefix (plist-get msg :subject) "\n")
(insert
"To: " (car (car (plist-get msg :from))) "\n"
"Subject: " mu-message-reply-prefix (plist-get msg :subject) "\n"))
(insert
"--text follows this line--\n\n" "--text follows this line--\n\n"
(mu-message-attribution msg) (mu-message-attribution msg)
(mu-message-cite msg)) (mu-message-cite msg)))
;; (when mail-signature (insert mail-signature))
(message-mode)
(if forward
(message-goto-to)
(message-goto-body))
(switch-to-buffer buf))))
(defun mu-message-reply ()
"create a reply to the message at point; After creation, switch
to the message editor"
(let ((path (mu-get-path)))
(when path
(mu-ask-key "Reply to [s]ender only or to [a]ll?")
(mu-message-reply-or-forward path))))
(defun mu-message-forward (path) (switch-to-buffer buf)
"create a forward-message to the message at PATH; After (message-mode)
creation, switch to the message editor" (message-goto-to)))
(mu-message-reply-or-forward path t))
(defun mu-message-move (src targetdir) (defun mu-message-move (src targetdir)
"move message at PATH using 'mu mv'; if targetdir is "move message at PATH using 'mu mv'; if targetdir is
@ -145,17 +152,14 @@ otherwise"
"Message moving failed")) "Message moving failed"))
;; now, if saving worked, anynchronously try to update the database ;; now, if saving worked, anynchronously try to update the database
(when fulltarget (when fulltarget
(mu-log "Removing from database: %s" src)
(start-process " *mu-remove*" nil mu-binary "remove" src) (start-process " *mu-remove*" nil mu-binary "remove" src)
(unless (string= targetdir "/dev/null")
(start-process " *mu-add*" nil mu-binary "add" fulltarget))))) (if (string= targetdir "/dev/null")
t
(mu-log "Adding to database: %s" fulltarget)
(start-process " *mu-add*" nil mu-binary "add" fulltarget) t))))
;; note, we don't check the result of the db output ;; note, we don't check the result of the db output
(provide 'mu-message) (provide 'mu-message)

View File

@ -15,7 +15,7 @@
;; GNU Emacs is distributed in the hope that it will be useful, ;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theq
;; GNU General Public License for more details. ;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License ;; You should have received a copy of the GNU General Public License
@ -34,6 +34,7 @@
:to :to
:subject :subject
:date :date
:attachments
:path) :path)
"list of header fields to display in the message view") "list of header fields to display in the message view")
@ -55,6 +56,25 @@ from which this buffer was invoked (buffer local)")
lst ","))) lst ",")))
(concat header val "\n")))) (concat header val "\n"))))
(defun mu-view-header-contact (field lst face)
(when lst
(let* ((header (concat (propertize field 'face 'mu-header-face) ": "))
(val (mapconcat (lambda(c)
(propertize (or (car c) (cdr c) "?") 'face face))
lst ", ")))
(concat header val "\n"))))
(defun mu-view-header-attachments (field lst face)
(when lst
(let* ((header (concat (propertize field 'face 'mu-header-face) ": "))
(val (mapconcat
(lambda(att)
(let ((idx (nth 0 att)) (fname (nth 1 att)) (ctype (nth 2 att)))
(propertize fname 'face face)))
lst ", ")))
(concat header val "\n"))))
(defun mu-view-body (msg face) (defun mu-view-body (msg face)
"view the body; try text first, if that does not work, try html" "view the body; try text first, if that does not work, try html"
(cond (cond
@ -90,7 +110,11 @@ from which this buffer was invoked (buffer local)")
(:date (:date
(mu-view-header "Date" (mu-view-header "Date"
(format-time-string mu-date-format-long (format-time-string mu-date-format-long
(plist-get msg :date)) 'mu-date-face)))) (plist-get msg :date)) 'mu-date-face))
(:attachments
(mu-view-header-attachments "Attachments" (plist-get msg :attachments)
'mu-path-face)
)))
mu-view-header-fields "") mu-view-header-fields "")
"\n" "\n"
(mu-view-body msg 'mu-body-face) (mu-view-body msg 'mu-body-face)
@ -131,12 +155,12 @@ buffer."
;; navigation between messages ;; navigation between messages
(define-key map "n" 'mu-view-next) (define-key map "n" 'mu-view-next)
(define-key map "p" 'mu-view-prev) (define-key map "p" 'mu-view-prev)
;; marking/unmarking ;; marking/unmarking
(define-key map "d" 'mu-view-mark-for-trash) (define-key map "d" '(lambda (mu-view-mark 'trash)))
(define-key map "D" 'mu-view-mark-for-deletion) (define-key map "D" '(lambda (mu-view-mark 'delete)))
(define-key map "m" 'mu-view-mark-for-move) (define-key map "m" '(lambda (mu-view-mark 'move)))
(define-key map "u" 'mu-view-unmark) (define-key map "u" '(lambda (mu-view-mark 'unmark)))
(define-key map "x" 'mu-view-marked-execute) (define-key map "x" 'mu-view-marked-execute)
map) map)
@ -182,33 +206,10 @@ also `with-temp-buffer'."
(when (mu-headers-prev) (when (mu-headers-prev)
(mu-view (mu-headers-get-path) (current-buffer))))) (mu-view (mu-headers-get-path) (current-buffer)))))
(defun mu-view-mark-for-trash () (defun mu-view-mark (mark)
"mark for thrashing" "mark for MARK"
(interactive) (interactive)
(with-current-headers-buffer (with-current-headers-buffer (mu-headers-mark mark)))
(when (mu-headers-mark 'trash)
(mu-view-next))))
(defun mu-view-mark-for-deletion ()
"mark for deletion"
(interactive)
(with-current-headers-buffer
(when (mu-headers-mark 'delete)
(mu-view-next))))
(defun mu-view-mark-for-move ()
"mark for moving"
(interactive)
(with-current-headers-buffer
(when (mu-headers-mark 'move)
(mu-view-next))))
(defun mu-view-unmark ()
"unmark this message"
(interactive)
(with-current-headers-buffer
(when (mu-headers-mark 'none)
(mu-view-next))))
;; we don't allow executing marks from the view buffer, to protect user from ;; we don't allow executing marks from the view buffer, to protect user from
;; accidentally deleting stuff... ;; accidentally deleting stuff...