1638 lines
54 KiB
EmacsLisp
1638 lines
54 KiB
EmacsLisp
;;; muttrc-mode.el --- Major mode to edit muttrc under Emacs
|
|
|
|
;;; Copyright (C) 2000, 2001, 2002 Laurent Pelecq
|
|
;;; Copyright (C) 2009 Kumar Appaiah
|
|
;;;
|
|
;;; Authors: Laurent Pelecq <laurent.pelecq@soleil.org>
|
|
;;; Kumar Appaiah <a.kumar@alumni.iitm.ac.in>
|
|
|
|
;;; This program is free software; you can redistribute it and/or modify
|
|
;;; it under the terms of the GNU General Public License as published by
|
|
;;; the Free Software Foundation; either version 2, or (at your option)
|
|
;;; any later version.
|
|
;;;
|
|
;;; This program is distributed in the hope that it will be useful,
|
|
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
;;; GNU General Public License for more details.
|
|
;;;
|
|
;;; You should have received a copy of the GNU General Public License
|
|
;;; along with this program; if not, write to the Free Software
|
|
;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
;;; Supported Emacs:
|
|
;;; ================
|
|
;;; This mode has only been tested on Emacs 21.2. If you
|
|
;;; encounter problems with older versions or with Xemacs, let me
|
|
;;; know.
|
|
|
|
;;; Installation:
|
|
;;; =============
|
|
;;; Add this lines to your .emacs:
|
|
;;; (autoload 'muttrc-mode "muttrc-mode.el"
|
|
;;; "Major mode to edit muttrc files" t)
|
|
;;; (setq auto-mode-alist
|
|
;;; (append '(("muttrc\\'" . muttrc-mode))
|
|
;;; auto-mode-alist))
|
|
;;; Be sure this file is in a directory that appears in the load-path.
|
|
;;;
|
|
;;; You mail want to use this mode for other files like the mail
|
|
;;; aliases file. In that case just add the following lines at the end
|
|
;;; of these files:
|
|
;;; ### Local Variables: ***
|
|
;;; ### mode: muttrc ***
|
|
;;; ### End: ***
|
|
|
|
;;; Customization:
|
|
;;; ==============
|
|
;;; Execute: M-x configure-group RET muttrc RET
|
|
;;;
|
|
;;; By default, help on command/variable is displayed automatically
|
|
;;; while executing a command to modify them. Disable this feature if
|
|
;;; you have problems with.
|
|
|
|
;;; Description:
|
|
;;; ============
|
|
;;; This mode first goal is to provide syntax highlighting with
|
|
;;; font-lock. The basic fontification appears on strings, comments,
|
|
;;; command names and variables. Additional fontification for commands
|
|
;;; arguments can be enabled through the customization buffer.
|
|
;;;
|
|
;;; Main commands are:
|
|
;;; C-x c -- muttrc-insert-command
|
|
;;; C-x s -- muttrc-set-variable
|
|
;;; C-x S -- muttrc-unset-variable
|
|
;;;
|
|
;;; Type C-h m for all key bindings.
|
|
|
|
;;; BUGS:
|
|
;;; =====
|
|
;;; - Multiline commands are not properly handled and can lead to
|
|
;;; unexpected result.
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
;;; ------------------------------------------------------------
|
|
;;; Requirement
|
|
;;; ------------------------------------------------------------
|
|
|
|
(require 'man)
|
|
|
|
(defconst muttrc-mode-version "$Revision: 1.2 $")
|
|
|
|
;;; ------------------------------------------------------------
|
|
;;; Configurable stuff
|
|
;;; ------------------------------------------------------------
|
|
|
|
(defgroup muttrc nil
|
|
"Muttrc editing commands for Emacs."
|
|
:group 'files
|
|
:prefix "muttrc-")
|
|
|
|
(defcustom muttrc-manual-path "/usr/share/doc/mutt/manual.txt.gz"
|
|
"Path to the Mutt manual."
|
|
:type 'string
|
|
:group 'muttrc)
|
|
|
|
(defcustom muttrc-display-help t
|
|
"Display help for each command/variable modification if set."
|
|
:type 'boolean
|
|
:group 'muttrc)
|
|
|
|
(defcustom muttrc-folder-abbrev ?+
|
|
"Character used to refer to the folder directory."
|
|
:type '(choice (const :tag "+" ?+)
|
|
(const :tag "=" ?=))
|
|
:group 'muttrc)
|
|
|
|
(defcustom muttrc-argument-faces-alist
|
|
'((alias . bold)
|
|
(address . default)
|
|
(face . default)
|
|
(color . default)
|
|
(command . default)
|
|
(path . default)
|
|
(function . default)
|
|
(header . default)
|
|
(hook . default)
|
|
(key . default)
|
|
(map . default)
|
|
(mimetype . default)
|
|
(object . default)
|
|
(regexp . default)
|
|
(sequence . default)
|
|
(string . default)
|
|
(hook-type . default))
|
|
"List of faces for the Muttrc command arguments. Standard faces are
|
|
symbols like 'bold, 'underline, ... Muttrc files must be revisited in
|
|
order for the modifications to take effect."
|
|
:type '(repeat (cons symbol symbol))
|
|
:group 'muttrc)
|
|
|
|
;;; ------------------------------------------------------------
|
|
;;; For backward compatibility
|
|
;;; ------------------------------------------------------------
|
|
|
|
(or (functionp 'match-string-no-properties)
|
|
(defalias 'match-string-no-properties 'match-string))
|
|
|
|
;;; ------------------------------------------------------------
|
|
;;; Mutt variables and commands
|
|
;;; ------------------------------------------------------------
|
|
|
|
(defconst muttrc-arg-handler-alist
|
|
'((alias muttrc-get-word "Alias")
|
|
(boolean muttrc-get-boolean "Enable")
|
|
(number muttrc-get-number "Number")
|
|
(address muttrc-get-string "Address")
|
|
(face muttrc-get-from-list "Face" muttrc-face-alist t)
|
|
(color muttrc-get-from-list "Color" muttrc-color-alist)
|
|
(command muttrc-get-command "Command")
|
|
(statement muttrc-get-statement "Command")
|
|
(assignment muttrc-get-assignment "Variable" t)
|
|
(variable muttrc-get-assignment "Variable" nil)
|
|
(path muttrc-get-path "Path")
|
|
(function muttrc-get-from-list "Function" muttrc-mutt-function-alist)
|
|
(header muttrc-get-from-list "Header name" muttrc-header-alist)
|
|
(hook-type muttrc-get-from-list "Hook" muttrc-hook-alist t)
|
|
(key muttrc-get-string "Key")
|
|
(map muttrc-get-from-list "Map" muttrc-map-alist t)
|
|
(mimetype muttrc-get-from-list "MIME type" muttrc-mimetype-alist)
|
|
(object muttrc-get-from-list "Object" muttrc-object-alist)
|
|
(regexp muttrc-get-string "Regular expression")
|
|
(sequence muttrc-get-string "Sequence")
|
|
(string muttrc-get-string "String")
|
|
(alias-sort-order muttrc-get-from-list "Sort order"
|
|
muttrc-alias-sort-order-alist)
|
|
(aux-sort-order muttrc-get-from-list "Sort order"
|
|
muttrc-aux-sort-order-alist)
|
|
(browser-sort-order muttrc-get-from-list "Sort order"
|
|
muttrc-browser-sort-order-alist)
|
|
(pgp-sort-order muttrc-get-from-list "Sort order"
|
|
muttrc-pgp-sort-order-alist)
|
|
(quadoption muttrc-get-from-list "Option" muttrc-quadoption-alist)
|
|
(sort-order muttrc-get-from-list "Sort order"
|
|
muttrc-sort-order-alist))
|
|
"List of handler for each type of argument. The format is:
|
|
\(ARG-TYPE FACE HANDLER PROMPT HANDLER-ARGS\).
|
|
The PROMPT can be overwritten by in command description.")
|
|
|
|
(defconst muttrc-face-alist
|
|
'(("none" . 1) ("bold" . 2) ("underline" . 3)
|
|
("reverse" . 4) ("standout". 5)))
|
|
|
|
(defconst muttrc-color-alist
|
|
'(("default" . 0)
|
|
("black" . 1) ("blue" . 2) ("cyan" . 3) ("green" . 4)
|
|
("magenta" . 5) ("red" . 6) ("white" . 7) ("yellow" . 8)
|
|
("brightdefault" . 9)
|
|
("brightblack" . 10) ("brightblue" . 11) ("brightcyan" . 12)
|
|
("brightgreen" . 13) ("brightmagenta" . 14) ("brightred" . 15)
|
|
("brightwhite" . 16) ("brightyellow" . 17)))
|
|
|
|
(defconst muttrc-object-alist
|
|
'(("attachment" . 0)
|
|
("body" . 1)
|
|
("bold" . 2)
|
|
("error" . 3)
|
|
("hdrdefault" . 4)
|
|
("header" . 5)
|
|
("index" . 6)
|
|
("indicator" . 7)
|
|
("markers" . 8)
|
|
("message" . 9)
|
|
("normal" . 10)
|
|
("quoted" . 11)
|
|
("search" . 12)
|
|
("signature" . 13)
|
|
("status" . 14)
|
|
("tilde" . 15)
|
|
("tree" . 16)
|
|
("underline" . 17))
|
|
"Mutt object on which color apply.")
|
|
|
|
(defconst muttrc-header-alist
|
|
'(("content-transfer-encoding" . 0)
|
|
("content-type" . 1)
|
|
("date" . 2)
|
|
("from" . 3)
|
|
("message-id" . 4)
|
|
("mime-version" . 5)
|
|
("organization" . 6)
|
|
("received" . 7)
|
|
("reply-to" . 8)
|
|
("resent-from" . 9)
|
|
("subject" . 10)
|
|
("to" . 11)
|
|
("x-accept-language" . 12)
|
|
("x-mailer" . 13)
|
|
("x-mimetrack" . 14)
|
|
("x-sender" . 15)))
|
|
|
|
(defconst muttrc-hook-alist
|
|
'(("folder-hook" . 0) ("send-hook" . 1) ("save-hook" . 2)
|
|
("mbox-hook" . 3) ("fcc-hook" . 4) ("fcc-save-hook" . 5)
|
|
("message-hook" . 5) ("charset-hook" . 6) ("iconv-hook" . 7)
|
|
("account-hook" . 8) ("append-hook" . 9) ("close-hook" . 10)
|
|
("crypt-hook" . 11) ("send2-hook" . 12) ("reply-hook" . 13)
|
|
("open-hook" . 14)))
|
|
|
|
(defconst muttrc-map-alist
|
|
'(("alias" . 0) ("attach" . 1) ("browser" . 2) ("compose" . 3)
|
|
("editor" . 4) ("generic" . 5) ("index" . 6) ("pager" . 7)
|
|
("pgp" . 8) ("postpone" . 9) ("query" . 10)))
|
|
|
|
(defconst muttrc-mimetype-alist
|
|
'(("application/andrew-inset" "ez")
|
|
("application/excel" "xls")
|
|
("application/fractals" "fif")
|
|
("application/java-archive" "jar")
|
|
("application/mac-binhex40" "hqx")
|
|
("application/msword" "doc" "dot")
|
|
("application/octet-stream" "exe" "bin")
|
|
("application/oda" "oda")
|
|
("application/pdf" "pdf")
|
|
("application/pdf")
|
|
("application/pgp" "pgp")
|
|
("application/postscript" "ai" "eps" "ps" "PS")
|
|
("application/pre-encrypted" "enc")
|
|
("application/rtf" "rtf")
|
|
("application/vnd.lotus-wordpro" "lwp" "sam")
|
|
("application/vnd.ms-access" "mdb" "mda" "mde")
|
|
("application/vnd.ms-excel" "xls")
|
|
("application/vnd.ms-powerpoint" "ppt" "pot" "ppa" "pps" "pwz")
|
|
("application/vnd.ms-schedule" "scd" "sch" "sc2")
|
|
("application/wordperfect5.1" "wpd" "wp6")
|
|
("application/x-arj-compressed" "arj")
|
|
("application/x-bcpio" "bcpio")
|
|
("application/x-chess-pgn" "pgn")
|
|
("application/x-cpio" "cpio")
|
|
("application/x-csh" "csh")
|
|
("application/x-debian-package" "deb")
|
|
("application/x-dvi" "dvi")
|
|
("application/x-fortezza-ckl" "ckl")
|
|
("application/x-gtar" "gtar")
|
|
("application/x-gunzip" "gz")
|
|
("application/x-hdf" "hdf")
|
|
("application/x-javascript" "js" "mocha")
|
|
("application/x-javascript-config" "jsc")
|
|
("application/x-latex" "latex")
|
|
("application/x-mif" "mif")
|
|
("application/x-msdos-program" "com" "exe" "bat")
|
|
("application/x-netcdf" "cdf" "nc")
|
|
("application/x-ns-proxy-autoconfig" "pac")
|
|
("application/x-ns-proxy-autoconfig")
|
|
("application/x-perl" "pl" "pm")
|
|
("application/x-pkcs7-crl" "crl")
|
|
("application/x-pkcs7-mime" "p7m" "p7c")
|
|
("application/x-pkcs7-signature" "p7s")
|
|
("application/x-rar-compressed" "rar")
|
|
("application/x-sh" "sh")
|
|
("application/x-shar" "shar")
|
|
("application/x-stuffit" "sit")
|
|
("application/x-sv4cpio" "sv4cpio")
|
|
("application/x-sv4crc" "sv4crc")
|
|
("application/x-tar" "tar")
|
|
("application/x-tar-gz" "tgz" "tar.gz")
|
|
("application/x-tcl" "tcl")
|
|
("application/x-tex" "tex")
|
|
("application/x-texinfo" "texi" "texinfo")
|
|
("application/x-troff" "t" "tr" "roff")
|
|
("application/x-troff-man" "man")
|
|
("application/x-troff-me" "me")
|
|
("application/x-troff-ms" "ms")
|
|
("application/x-ustar" "ustar")
|
|
("application/x-wais-source" "src")
|
|
("application/x-zip-compressed" "zip")
|
|
("audio/basic" "au" "snd")
|
|
("audio/basic" "snd")
|
|
("audio/midi" "mid" "midi")
|
|
("audio/ulaw" "au")
|
|
("audio/x-aiff" "aif" "aifc" "aiff")
|
|
("audio/x-aiff" "aif" "aiff" "aifc")
|
|
("audio/x-wav" "wav")
|
|
("image/gif" "gif")
|
|
("image/ief" "ief")
|
|
("image/jpeg" "jpe" "jpeg" "jpg")
|
|
("image/png" "png")
|
|
("image/tiff" "tif" "tiff")
|
|
("image/tiff")
|
|
("image/x-MS-bmp" "bmp")
|
|
("image/x-cmu-raster" "ras")
|
|
("image/x-photo-cd" "pcd")
|
|
("image/x-portable-anymap" "pnm")
|
|
("image/x-portable-bitmap" "pbm")
|
|
("image/x-portable-graymap" "pgm")
|
|
("image/x-portable-pixmap" "ppm")
|
|
("image/x-rgb" "rgb")
|
|
("image/x-xbitmap" "xbm")
|
|
("image/x-xpixmap" "xpm")
|
|
("image/x-xwindowdump" "xwd")
|
|
("text/html" "html" "htm" "shtml")
|
|
("text/plain" "txt" "text")
|
|
("text/richtext" "rtx")
|
|
("text/tab-separated-values" "tsv")
|
|
("text/x-setext" "etx")
|
|
("text/x-vcard" "vcf")
|
|
("text/x-vcard")
|
|
("video/dl" "dl")
|
|
("video/fli" "fli")
|
|
("video/gl" "gl")
|
|
("video/mpeg" "mpeg" "mpg" "mpe" "mpv" "vbs" "mpegv")
|
|
("video/quicktime" "qt" "mov" "moov")
|
|
("video/x-msvideo" "avi")
|
|
("video/x-sgi-movie" "movie")
|
|
("x-world/x-vrml" "vrm" "vrml" "wrl")))
|
|
|
|
(defconst muttrc-command-alist
|
|
'(
|
|
("folder-hook" ((string) (statement)) nil nil)
|
|
("alias" ((alias) (address)) t nil)
|
|
("unalias" ((alias) (address)) t nil)
|
|
("alternative_order" ((mimetype)) t nil)
|
|
("auto_view" ((mimetype)) t nil)
|
|
("bind" ((map) (key) (function)) nil t)
|
|
("color" ((object)
|
|
(color "Foreground")
|
|
(color "Background")
|
|
(regexp)) nil t)
|
|
("charset-hook" ((string "Alias")
|
|
(string "Charset")) nil nil)
|
|
("fcc-hook" ((regexp) (path)) nil nil)
|
|
("fcc-save-hook" ((regexp) (path)) nil nil)
|
|
("folder-hook" ((regexp) (statement)) nil nil)
|
|
("ignore" ((header)) t nil)
|
|
("iconv-hook" ((string "Charset")
|
|
(string "Local charset")) nil nil)
|
|
("unignore" ((header)) t nil)
|
|
("hdr_order" ((header)) t nil)
|
|
("unhdr_order" ((header)) t nil)
|
|
("lists" ((address)) t nil)
|
|
("unlists" ((address)) t nil)
|
|
("macro" ((map) (key) (sequence)
|
|
(string "Description")) nil t)
|
|
("mailboxes" ((path)) t nil)
|
|
("mono" ((object) (face) (regexp)) nil t)
|
|
("mbox-hook" ((regexp) (path)) nil nil)
|
|
("message-hook" ((regexp) (statement)) nil nil)
|
|
("my_hdr" ((string "Header")) nil nil)
|
|
("unmy_hdr" ((header)) t nil)
|
|
("push" ((string)) nil nil)
|
|
("pgp-hook" ((regexp)
|
|
(string "Keyid")) nil nil)
|
|
("save-hook" ((regexp) (path)) nil nil)
|
|
("score" ((regexp)
|
|
(number "Value")) nil nil)
|
|
("unscore" ((regexp)) t nil)
|
|
("send-hook" ((regexp) (statement)) nil nil)
|
|
("source" ((path)) nil nil)
|
|
("subscribe" ((address)) t nil)
|
|
("unsubscribe" ((address)) t nil)
|
|
("unhook" ((hook-type)) nil nil)
|
|
("alternates" ((regexp)) nil nil)
|
|
("unalternates" ((regexp)) nil nil))
|
|
"List of muttrc commands with their arguments. Format is:
|
|
COMMAND '\(ARG1 ARG2 ...\) REPEAT OPTIONAL
|
|
REPEAT and OPTIONAL apply to the last argument.
|
|
ARGn is the list of arguments for muttrc-call-arg-handler. Each args
|
|
is a list \(ARGTYPE \[ARGNAME\]\).")
|
|
|
|
(defconst muttrc-statement-alist
|
|
(append
|
|
'(("set" ((assignment)) t nil)
|
|
("unset" ((variable)) t nil))
|
|
muttrc-command-alist)
|
|
"Additional muttrc commands with their arguments that are handled
|
|
differently. See muttrc-command-alist")
|
|
|
|
|
|
(defconst muttrc-variables-alist
|
|
'(("abort_nosubject" quadoption "ask-yes")
|
|
("abort_unmodified" quadoption "yes")
|
|
("alias_file" path "~/.muttrc")
|
|
("alias_format" string "%4n %2f %t %-10a %r")
|
|
("allow_8bit" boolean t)
|
|
("allow_ansi" boolean nil)
|
|
("arrow_cursor" boolean nil)
|
|
("ascii_chars" boolean nil)
|
|
("askbcc" boolean nil)
|
|
("askcc" boolean nil)
|
|
("assumed_charset" string "us-ascii")
|
|
("attach_format" string "%u%D%I %t%4n %T%.40d%> [%.7m/%.10M, %.6e%?C?, %C?, %s] ")
|
|
("attach_sep" string "\\n")
|
|
("attach_split" boolean t)
|
|
("attribution" string "On %d, %n wrote:")
|
|
("autoedit" boolean nil)
|
|
("auto_tag" boolean nil)
|
|
("beep" boolean t)
|
|
("beep_new" boolean nil)
|
|
("bounce" quadoption "ask-yes")
|
|
("bounce_delivered" boolean t)
|
|
("braille_friendly" boolean nil)
|
|
("charset" string "")
|
|
("check_new" boolean t)
|
|
("collapse_unread" boolean t)
|
|
("uncollapse_jump" boolean nil)
|
|
("compose_format" string "-- Mutt: Compose [Approx. msg size: %l Atts: %a]%>-")
|
|
("config_charset" string "")
|
|
("confirmappend" boolean t)
|
|
("confirmcreate" boolean t)
|
|
("connect_timeout" number 30)
|
|
("content_type" string "text/plain")
|
|
("copy" quadoption "yes")
|
|
("crypt_use_gpgme" boolean nil)
|
|
("crypt_autopgp" boolean t)
|
|
("crypt_autosmime" boolean t)
|
|
("date_format" string "!%a, %b %d, %Y at %I:%M:%S%p %Z")
|
|
("default_hook" string "~f %s !~P | (~P ~C %s)")
|
|
("delete" quadoption "ask-yes")
|
|
("delete_untag" boolean t)
|
|
("digest_collapse" boolean t)
|
|
("display_filter" path "")
|
|
("dotlock_program" path "/usr/bin/mutt_dotlock")
|
|
("dsn_notify" string "")
|
|
("dsn_return" string "")
|
|
("duplicate_threads" boolean t)
|
|
("edit_headers" boolean nil)
|
|
("editor" path "")
|
|
("encode_from" boolean nil)
|
|
("envelope_from_address" e-mail "")
|
|
("escape" string "~")
|
|
("fast_reply" boolean nil)
|
|
("fcc_attach" boolean t)
|
|
("fcc_clear" boolean nil)
|
|
("file_charset" string "")
|
|
("folder" path "~/Mail")
|
|
("folder_format" string "%2C %t %N %F %2l %-8.8u %-8.8g %8s %d %f")
|
|
("followup_to" boolean t)
|
|
("force_name" boolean nil)
|
|
("forward_decode" boolean t)
|
|
("forward_edit" quadoption "yes")
|
|
("forward_format" string "[%a: %s]")
|
|
("forward_quote" boolean nil)
|
|
("from" e-mail "")
|
|
("gecos_mask" regular "^[^,]*")
|
|
("hdrs" boolean t)
|
|
("header" boolean nil)
|
|
("help" boolean t)
|
|
("hidden_host" boolean nil)
|
|
("hide_limited" boolean nil)
|
|
("hide_missing" boolean t)
|
|
("hide_thread_subject" boolean t)
|
|
("hide_top_limited" boolean nil)
|
|
("hide_top_missing" boolean t)
|
|
("history" number 10)
|
|
("honor_followup_to" quadoption "yes")
|
|
("hostname" string "")
|
|
("ignore_list_reply_to" boolean nil)
|
|
("imap_authenticators" string "")
|
|
("imap_check_subscribed" boolean nil)
|
|
("imap_delim_chars" string "/.")
|
|
("imap_headers" string "")
|
|
("imap_home_namespace" string "")
|
|
("imap_idle" boolean nil)
|
|
("imap_keepalive" number 900)
|
|
("imap_list_subscribed" boolean nil)
|
|
("imap_login" string "")
|
|
("imap_pass" string "")
|
|
("imap_passive" boolean t)
|
|
("imap_peek" boolean t)
|
|
("imap_servernoise" boolean t)
|
|
("imap_user" string "")
|
|
("implicit_autoview" boolean nil)
|
|
("include" quadoption "ask-yes")
|
|
("include_onlyfirst" boolean nil)
|
|
("indent_string" string "> ")
|
|
("index_format" string "%4C %Z %{%b %d} %-15.15L (%?l?%4l&%4c?) %s")
|
|
("hdr_format" string "%4C %Z %{%b %d} %-15.15L (%?l?%4l&%4c?) %s")
|
|
("ispell" path "ispell")
|
|
("keep_flagged" boolean nil)
|
|
("locale" string "C")
|
|
("mail_check" number 5)
|
|
("mailcap_path" string "")
|
|
("mailcap_sanitize" boolean t)
|
|
("maildir_mtime" boolean nil)
|
|
("header_cache" path "")
|
|
("maildir_header_cache_verify" boolean t)
|
|
("header_cache_pagesize" string "16384")
|
|
("maildir_trash" boolean nil)
|
|
("mark_old" boolean t)
|
|
("markers" boolean t)
|
|
("mask" regular "!^\.[^.]")
|
|
("mbox" path "~/mbox")
|
|
("mbox_type" folder mbox)
|
|
("metoo" boolean nil)
|
|
("menu_context" number 0)
|
|
("menu_move_off" boolean t)
|
|
("menu_scroll" boolean nil)
|
|
("meta_key" boolean nil)
|
|
("mh_purge" boolean nil)
|
|
("mh_seq_flagged" string "flagged")
|
|
("mh_seq_replied" string "replied")
|
|
("mh_seq_unseen" string "unseen")
|
|
("mime_forward" quadoption "no")
|
|
("mime_forward_decode" boolean nil)
|
|
("mime_forward_rest" quadoption "yes")
|
|
("pgp_mime_signature_filename" string "signature.asc")
|
|
("pgp_mime_signature_description" string "Digital signature")
|
|
("mix_entry_format" string "%4n %c %-16s %a")
|
|
("mixmaster" path "mixmaster")
|
|
("move" quadoption "ask-no")
|
|
("message_cachedir" path "")
|
|
("message_format" string "%s")
|
|
("narrow_tree" boolean nil)
|
|
("net_inc" number 10)
|
|
("pager" path "builtin")
|
|
("pager_context" number 0)
|
|
("pager_format" string "-%Z- %C/%m: %-20.20n %s")
|
|
("pager_index_lines" number 0)
|
|
("pager_stop" boolean nil)
|
|
("crypt_autosign" boolean nil)
|
|
("crypt_autoencrypt" boolean nil)
|
|
("pgp_ignore_subkeys" boolean t)
|
|
("crypt_replyencrypt" boolean t)
|
|
("crypt_replysign" boolean nil)
|
|
("crypt_replysignencrypted" boolean nil)
|
|
("crypt_timestamp" boolean t)
|
|
("pgp_use_gpg_agent" boolean nil)
|
|
("crypt_verify_sig" quadoption "yes")
|
|
("pgp_verify_sig" quadoption "yes")
|
|
("smime_is_default" boolean nil)
|
|
("smime_ask_cert_label" boolean t)
|
|
("smime_decrypt_use_default_key" boolean t)
|
|
("pgp_entry_format" string "%4n %t%f %4l/0x%k %-4a %2c %u")
|
|
("pgp_good_sign" regular "")
|
|
("pgp_check_exit" boolean t)
|
|
("pgp_long_ids" boolean nil)
|
|
("pgp_retainable_sigs" boolean nil)
|
|
("pgp_autoinline" boolean nil)
|
|
("pgp_replyinline" boolean nil)
|
|
("pgp_show_unusable" boolean t)
|
|
("pgp_sign_as" string "")
|
|
("pgp_strict_enc" boolean t)
|
|
("pgp_timeout" number 300)
|
|
("pgp_sort_keys" sort address)
|
|
("pgp_mime_auto" quadoption "ask-yes")
|
|
("pgp_auto_decode" boolean nil)
|
|
("pgp_decode_command" string "")
|
|
("pgp_getkeys_command" string "")
|
|
("pgp_verify_command" string "")
|
|
("pgp_decrypt_command" string "")
|
|
("pgp_clearsign_command" string "")
|
|
("pgp_sign_command" string "")
|
|
("pgp_encrypt_sign_command" string "")
|
|
("pgp_encrypt_only_command" string "")
|
|
("pgp_import_command" string "")
|
|
("pgp_export_command" string "")
|
|
("pgp_verify_key_command" string "")
|
|
("pgp_list_secring_command" string "")
|
|
("pgp_list_pubring_command" string "")
|
|
("forward_decrypt" boolean t)
|
|
("smime_timeout" number 300)
|
|
("smime_encrypt_with" string "")
|
|
("smime_keys" path "")
|
|
("smime_ca_location" path "")
|
|
("smime_certificates" path "")
|
|
("smime_decrypt_command" string "")
|
|
("smime_verify_command" string "")
|
|
("smime_verify_opaque_command" string "")
|
|
("smime_sign_command" string "")
|
|
("smime_sign_opaque_command" string "")
|
|
("smime_encrypt_command" string "")
|
|
("smime_pk7out_command" string "")
|
|
("smime_get_cert_command" string "")
|
|
("smime_get_signer_cert_command" string "")
|
|
("smime_import_cert_command" string "")
|
|
("smime_get_cert_email_command" string "")
|
|
("smime_default_key" string "")
|
|
("ssl_force_tls" boolean nil)
|
|
("ssl_starttls" quadoption "yes")
|
|
("certificate_file" path "~/.mutt_certificates")
|
|
("ssl_use_sslv3" boolean t)
|
|
("ssl_use_tlsv1" boolean t)
|
|
("ssl_min_dh_prime_bits" number 0)
|
|
("ssl_ca_certificates_file" path "")
|
|
("pipe_split" boolean nil)
|
|
("pipe_decode" boolean nil)
|
|
("pipe_sep" string "\\n")
|
|
("pop_authenticators" string "")
|
|
("pop_auth_try_all" boolean t)
|
|
("pop_checkinterval" number 60)
|
|
("pop_delete" quadoption "ask-no")
|
|
("pop_host" string "")
|
|
("pop_last" boolean nil)
|
|
("pop_reconnect" quadoption "ask-yes")
|
|
("pop_user" string "")
|
|
("pop_pass" string "")
|
|
("post_indent_string" string "")
|
|
("postpone" quadoption "ask-yes")
|
|
("postponed" path "~/postponed")
|
|
("preconnect" string "")
|
|
("print" quadoption "ask-no")
|
|
("print_command" path "lpr")
|
|
("print_decode" boolean t)
|
|
("print_split" boolean nil)
|
|
("prompt_after" boolean t)
|
|
("query_command" path "")
|
|
("quit" quadoption "yes")
|
|
("quote_regexp" regular "^([ \t]*[|>:}#])+")
|
|
("read_inc" number 10)
|
|
("read_only" boolean nil)
|
|
("realname" string "")
|
|
("recall" quadoption "ask-yes")
|
|
("record" path "~/sent")
|
|
("reply_regexp" regular "^(re([\[0-9\]+])*|aw):[ \t]*")
|
|
("reply_self" boolean nil)
|
|
("reply_to" quadoption "ask-yes")
|
|
("resolve" boolean t)
|
|
("reverse_alias" boolean nil)
|
|
("reverse_name" boolean nil)
|
|
("reverse_realname" boolean t)
|
|
("rfc2047_parameters" boolean nil)
|
|
("save_address" boolean nil)
|
|
("save_empty" boolean t)
|
|
("save_name" boolean nil)
|
|
("score" boolean t)
|
|
("score_threshold_delete" number -1)
|
|
("score_threshold_flag" number 9999)
|
|
("score_threshold_read" number -1)
|
|
("send_charset" string "us-ascii:iso-8859-1:utf-8")
|
|
("sendmail" path "/usr/sbin/sendmail -oem -oi")
|
|
("sendmail_wait" number 0)
|
|
("shell" path "")
|
|
("sig_dashes" boolean t)
|
|
("sig_on_top" boolean nil)
|
|
("signature" path "~/.signature")
|
|
("simple_search" string "~f %s | ~s %s")
|
|
("smart_wrap" boolean t)
|
|
("smileys" regular "(>From )|(:[-^]?[][)(><}{|/DP])")
|
|
("sleep_time" number 1)
|
|
("sort" sort date)
|
|
("sort_alias" sort alias)
|
|
("sort_aux" sort date)
|
|
("sort_browser" sort alpha)
|
|
("sort_re" boolean t)
|
|
("spam_separator" string ",")
|
|
("spoolfile" path "")
|
|
("status_chars" string "-*%A")
|
|
("status_format" string "-%r-Mutt: %f [Msgs:%?M?%M/?%m%?n? New:%n?%?o? Old:%o?%?d? Del:%d?%?F? Flag:%F?%?t? Tag:%t?%?p? Post:%p?%?b? Inc:%b?%?l? %l?]---(%s/%S)-%>-(%P)---")
|
|
("status_on_top" boolean nil)
|
|
("strict_mime" boolean t)
|
|
("strict_threads" boolean nil)
|
|
("suspend" boolean t)
|
|
("text_flowed" boolean nil)
|
|
("thread_received" boolean nil)
|
|
("thorough_search" boolean nil)
|
|
("tilde" boolean nil)
|
|
("timeout" number 600)
|
|
("tmpdir" path "")
|
|
("to_chars" string " +TCFL")
|
|
("tunnel" string "")
|
|
("use_8bitmime" boolean nil)
|
|
("use_domain" boolean t)
|
|
("use_envelope_from" boolean nil)
|
|
("use_from" boolean t)
|
|
("use_idn" boolean t)
|
|
("use_ipv6" boolean t)
|
|
("user_agent" boolean t)
|
|
("visual" path "")
|
|
("wait_key" boolean t)
|
|
("weed" boolean t)
|
|
("wrap_search" boolean t)
|
|
("wrapmargin" number 0)
|
|
("write_inc" number 10)
|
|
("write_bcc" boolean t)
|
|
("xterm_icon" string "M%?n?AIL&ail?")
|
|
("xterm_set_titles" boolean nil)
|
|
("xterm_title" string "Mutt with %?m?%m messages&no messages?%?n? [%n NEW]?"))
|
|
"List of muttrc variables. Format is:
|
|
VARIABLE TYPE DEFAULT"
|
|
)
|
|
|
|
(defconst muttrc-mutt-function-alist
|
|
'(("attach-file" . 0)
|
|
("attach-key" . 1)
|
|
("attach-message" . 2)
|
|
("backspace" . 3)
|
|
("backward-char" . 4)
|
|
("bol" . 5)
|
|
("bottom-page" . 6)
|
|
("bounce-message" . 7)
|
|
("buffy-cycle" . 8)
|
|
("change-dir" . 9)
|
|
("change-folder" . 10)
|
|
("change-folder-readonly" . 11)
|
|
("check-new" . 12)
|
|
("clear-flag" . 13)
|
|
("complete" . 14)
|
|
("complete-query" . 15)
|
|
("copy-file" . 16)
|
|
("copy-message" . 17)
|
|
("create-alias" . 18)
|
|
("current-bottom" . 19)
|
|
("current-middle" . 20)
|
|
("current-top" . 21)
|
|
("decode-copy" . 22)
|
|
("decode-save" . 23)
|
|
("delete-char" . 24)
|
|
("delete-entry" . 25)
|
|
("delete-message" . 26)
|
|
("delete-pattern" . 27)
|
|
("delete-subthread" . 28)
|
|
("delete-thread" . 29)
|
|
("detach-file" . 30)
|
|
("display-address" . 31)
|
|
("display-message" . 32)
|
|
("display-toggle-weed" . 33)
|
|
("edit" . 34)
|
|
("edit-bcc" . 35)
|
|
("edit-cc" . 36)
|
|
("edit-description" . 37)
|
|
("edit-encoding" . 38)
|
|
("edit-fcc" . 39)
|
|
("edit-file" . 40)
|
|
("edit-from" . 41)
|
|
("edit-headers" . 42)
|
|
("edit-message" . 43)
|
|
("edit-mime" . 44)
|
|
("edit-reply-to" . 45)
|
|
("edit-subject" . 46)
|
|
("edit-to" . 47)
|
|
("edit-type" . 48)
|
|
("enter-command" . 49)
|
|
("enter-mask" . 50)
|
|
("eol" . 51)
|
|
("exit" . 52)
|
|
("extract-keys" . 53)
|
|
("fetch-mail" . 54)
|
|
("filter-entry" . 55)
|
|
("first-entry" . 56)
|
|
("flag-message" . 57)
|
|
("forget-passphrase" . 58)
|
|
("forward-char" . 59)
|
|
("forward-message" . 60)
|
|
("group-reply" . 61)
|
|
("half-down" . 62)
|
|
("half-up" . 63)
|
|
("help" . 64)
|
|
("history-down" . 65)
|
|
("history-up" . 66)
|
|
("ispell" . 67)
|
|
("jump" . 68)
|
|
("kill-eol" . 69)
|
|
("kill-line" . 70)
|
|
("kill-word" . 71)
|
|
("last-entry" . 72)
|
|
("limit" . 73)
|
|
("list-reply" . 74)
|
|
("mail" . 75)
|
|
("mail-key" . 76)
|
|
("mark-as-new" . 77)
|
|
("middle-page" . 78)
|
|
("new-mime" . 79)
|
|
("next-entry" . 80)
|
|
("next-line" . 81)
|
|
("next-new" . 82)
|
|
("next-page" . 83)
|
|
("next-subthread" . 84)
|
|
("next-thread" . 85)
|
|
("next-undeleted" . 86)
|
|
("next-unread" . 87)
|
|
("parent-message" . 88)
|
|
("pgp-menu" . 89)
|
|
("pipe-entry" . 90)
|
|
("pipe-message" . 91)
|
|
("postpone-message" . 92)
|
|
("previous-entry" . 93)
|
|
("previous-line" . 94)
|
|
("previous-new" . 95)
|
|
("previous-page" . 96)
|
|
("previous-subthread" . 97)
|
|
("previous-thread" . 98)
|
|
("previous-undeleted" . 99)
|
|
("previous-unread" . 100)
|
|
("print-entry" . 101)
|
|
("print-message" . 102)
|
|
("query" . 103)
|
|
("query-append" . 104)
|
|
("quit" . 105)
|
|
("quote-char" . 106)
|
|
("read-subthread" . 107)
|
|
("read-thread" . 108)
|
|
("recall-message" . 109)
|
|
("redraw-screen" . 110)
|
|
("refresh" . 111)
|
|
("rename-file" . 112)
|
|
("reply" . 113)
|
|
("save-entry" . 114)
|
|
("save-message" . 115)
|
|
("search" . 116)
|
|
("search-next" . 117)
|
|
("search-opposite" . 118)
|
|
("search-reverse" . 119)
|
|
("search-toggle" . 120)
|
|
("select-entry" . 121)
|
|
("select-new" . 122)
|
|
("send-message" . 123)
|
|
("set-flag" . 124)
|
|
("shell-escape" . 125)
|
|
("show-limit" . 126)
|
|
("show-version" . 127)
|
|
("skip-quoted" . 128)
|
|
("sort" . 129)
|
|
("sort-mailbox" . 130)
|
|
("sort-reverse" . 131)
|
|
("subscribe" . 132)
|
|
("sync-mailbox" . 133)
|
|
("tag-entry" . 134)
|
|
("tag-message" . 135)
|
|
("tag-pattern" . 136)
|
|
("tag-prefix" . 137)
|
|
("tag-thread" . 138)
|
|
("toggle-mailboxes" . 139)
|
|
("toggle-new" . 140)
|
|
("toggle-quoted" . 141)
|
|
("toggle-subscribed" . 142)
|
|
("toggle-unlink" . 143)
|
|
("toggle-write" . 144)
|
|
("top" . 145)
|
|
("top-page" . 146)
|
|
("undelete-entry" . 147)
|
|
("undelete-message" . 148)
|
|
("undelete-pattern" . 149)
|
|
("undelete-subthread" . 150)
|
|
("undelete-thread" . 151)
|
|
("unsubscribe" . 152)
|
|
("untag-pattern" . 153)
|
|
("verify-key" . 154)
|
|
("view-attach" . 155)
|
|
("view-attachments" . 156)
|
|
("view-file" . 157)
|
|
("view-mailcap" . 158)
|
|
("view-name" . 159)
|
|
("view-text" . 160)
|
|
("write-fcc" . 161))
|
|
"List of Mutt command (not muttrc!)")
|
|
|
|
(defconst muttrc-alias-sort-order-alist
|
|
'(("address" . 0) ("alias" . 1) ("unsorted" . 2)))
|
|
|
|
(defconst muttrc-aux-sort-order-alist
|
|
'(("date-sent" . 0) ("reverse-date-sent" . 1) ("last-date-sent" . 2)
|
|
("date-received" . 3) ("reverse-date-received" . 4)
|
|
("last-date-received" . 5)
|
|
("from" . 6) ("reverse-from" . 7) ("last-from" . 8)
|
|
("mailbox-order" . 9) ("reverse-mailbox-order" . 10)
|
|
("last-mailbox-order" . 11)
|
|
("score" . 12) ("reverse-score" . 13) ("last-score" . 14)
|
|
("size" . 15) ("reverse-size" . 16) ("last-size" . 17)
|
|
("subject" . 18) ("reverse-subject" . 19) ("last-subject" . 20)
|
|
("threads" . 21) ("reverse-threads" . 22) ("last-threads" . 23)
|
|
("to" . 24) ("reverse-to" . 25) ("last-to" . 26)))
|
|
|
|
(defconst muttrc-browser-sort-order-alist
|
|
'(("alpha" . 0) ("date" . 1) ("size" . 2) ("unsorted" . 3)))
|
|
|
|
(defconst muttrc-pgp-sort-order-alist
|
|
'(("address" . 0) ("date" . 1) ("keyid" . 2)
|
|
("reverse-address" . 3) ("reverse-date" . 4)
|
|
("reverse-keyid" . 5) ("reverse-trust" . 6)
|
|
("trust" . 7)))
|
|
|
|
(defconst muttrc-quadoption-alist
|
|
'(("yes" .0) ("no" .1) ("ask-yes" .2) ("ask-no" .3)))
|
|
|
|
(defconst muttrc-sort-order-alist
|
|
'(("date-sent" . 0) ("reverse-date-sent" . 1)
|
|
("date-received" . 2) ("reverse-date-received" . 3)
|
|
("from" . 4) ("reverse-from" . 5)
|
|
("mailbox-order" . 6) ("reverse-mailbox-order" . 7)
|
|
("score" . 8) ("reverse-score" . 9)
|
|
("size" . 10) ("reverse-size" . 11)
|
|
("subject" . 12) ("reverse-subject" . 13)
|
|
("threads" . 14) ("reverse-threads" . 15)
|
|
("to" . 16) ("reverse-to" . 17)))
|
|
|
|
;;; ------------------------------------------------------------
|
|
;;; Font-lock definitions
|
|
;;; ------------------------------------------------------------
|
|
|
|
(defun muttrc-string-regexp (quote-char)
|
|
(let ((c (char-to-string quote-char)))
|
|
(format "%s\\([^\n%s]\\|[\\].\\)*%s" c c c)))
|
|
|
|
(defvar muttrc-generic-arg-regexp
|
|
(concat "\\("
|
|
(muttrc-string-regexp ?\")
|
|
"\\|"
|
|
"'\\([^']*\\)'"
|
|
"\\|"
|
|
(muttrc-string-regexp ?\`)
|
|
"\\|"
|
|
"\\([^\n\t \"'`#;\\]\\|[\\].\\)+"
|
|
"\\)"))
|
|
|
|
(defvar muttrc-generic-arg-sequence-regexp
|
|
(concat "\\(\\s-*" muttrc-generic-arg-regexp "+\\)*"))
|
|
|
|
(defvar muttrc-non-command-keyword-regexp
|
|
"\\(^\\|;\\)\\s-*\\<\\(set\\|unset\\|toggle\\|reset\\)\\>")
|
|
|
|
(defvar muttrc-variable-regexp
|
|
(concat "\\<\\(\\(no\\|inv\\)?\\("
|
|
(mapconcat 'car muttrc-variables-alist "\\|")
|
|
"\\)\\)\\>"))
|
|
|
|
(defvar muttrc-assignement-regexp
|
|
(concat muttrc-variable-regexp
|
|
"\\s-*\\(=\\s-*" muttrc-generic-arg-regexp "\\)?"))
|
|
|
|
(defun muttrc-search-command-forward (command &optional limit)
|
|
(let ((cmd-desc (assoc command muttrc-command-alist)))
|
|
(if cmd-desc
|
|
(let ((cmd-match-data '())
|
|
(cmd-args (cadr cmd-desc))
|
|
(origin (point))
|
|
beg-0 end-0)
|
|
(catch 'done
|
|
(while (and (not cmd-match-data)
|
|
(re-search-forward
|
|
(concat "\\(;\\|^\\)\\s-*\\(" command "\\)")
|
|
limit t))
|
|
(let ((beg (nth 4 (match-data)))
|
|
(end (nth 5 (match-data))))
|
|
(setq beg-0 beg)
|
|
(setq cmd-match-data (list beg end)))
|
|
(let ((args cmd-args))
|
|
(while args
|
|
(let ((arg-type (caar args))
|
|
(arg-re (if (null (cdr args))
|
|
muttrc-generic-arg-sequence-regexp
|
|
muttrc-generic-arg-regexp)))
|
|
(skip-syntax-forward "-")
|
|
(if (looking-at arg-re)
|
|
(let ((beg (nth 0 (match-data)))
|
|
(end (nth 1 (match-data))))
|
|
(goto-char end)
|
|
(setq cmd-match-data (append cmd-match-data
|
|
(list beg end)))
|
|
(setq end-0 end)
|
|
(setq args (cdr args)))
|
|
(progn
|
|
(setq args nil)
|
|
(setq cmd-match-data nil)))))
|
|
(when cmd-match-data
|
|
(set-match-data (cons beg-0
|
|
(cons end-0
|
|
cmd-match-data)))
|
|
(throw 'done t))))
|
|
(goto-char origin)
|
|
nil)))))
|
|
|
|
|
|
(defun muttrc-font-lock-keywords ()
|
|
(let ((command-alist muttrc-command-alist)
|
|
keywords)
|
|
(while command-alist
|
|
(let* ((cmd (caar command-alist))
|
|
(args (cadr (car command-alist)))
|
|
(regexp (eval ; Simulate a closure
|
|
(list
|
|
'lambda '(&optional limit)
|
|
(list 'muttrc-search-command-forward cmd 'limit))))
|
|
(hilighters '((1 font-lock-keyword-face)))
|
|
(n 2))
|
|
(while args
|
|
(let ((arg-type (caar args))
|
|
(last-arg-p (null (cdr args))))
|
|
(setq hilighters
|
|
(append hilighters
|
|
(let ((face
|
|
(or (cdr-safe
|
|
(assoc arg-type
|
|
muttrc-argument-faces-alist))
|
|
'default)))
|
|
(list (append (list n (list 'quote face))
|
|
(if last-arg-p '(nil t))))))))
|
|
(setq n (1+ n))
|
|
(setq args (cdr args)))
|
|
(setq keywords (append keywords (list (cons regexp hilighters))))
|
|
(setq command-alist (cdr command-alist))))
|
|
(append keywords
|
|
(list
|
|
(list muttrc-non-command-keyword-regexp 2
|
|
font-lock-keyword-face)
|
|
(list muttrc-assignement-regexp 1
|
|
font-lock-variable-name-face)))
|
|
))
|
|
|
|
;;; ------------------------------------------------------------
|
|
;;; Mode specific customization
|
|
;;; ------------------------------------------------------------
|
|
|
|
(defconst muttrc-mode-map nil
|
|
"The keymap that is used in Muttrc mode.")
|
|
(if (null muttrc-mode-map)
|
|
(setq muttrc-mode-map
|
|
(let ((map (make-sparse-keymap))
|
|
(help-map (make-sparse-keymap))
|
|
(ctrl-c-map (make-sparse-keymap)))
|
|
(define-key map "\C-c" ctrl-c-map)
|
|
(define-key ctrl-c-map "c" 'muttrc-insert-command)
|
|
(define-key ctrl-c-map "C" 'comment-region)
|
|
(define-key ctrl-c-map "s" 'muttrc-set-variable)
|
|
(define-key ctrl-c-map "S" 'muttrc-unset-variable)
|
|
(define-key ctrl-c-map "f" 'muttrc-find-variable-in-buffer)
|
|
(define-key ctrl-c-map "h" help-map)
|
|
(define-key help-map "m" 'muttrc-find-manual-file)
|
|
(define-key help-map "v" 'muttrc-find-variable-help)
|
|
(define-key help-map "c" 'muttrc-find-command-help)
|
|
map)))
|
|
|
|
(defvar muttrc-mode-syntax-table nil)
|
|
(when (null muttrc-mode-syntax-table)
|
|
(setq muttrc-mode-syntax-table (make-syntax-table))
|
|
(modify-syntax-entry ?# "< " muttrc-mode-syntax-table)
|
|
(modify-syntax-entry ?\n "> " muttrc-mode-syntax-table)
|
|
(modify-syntax-entry ?\' "$ " muttrc-mode-syntax-table)
|
|
(modify-syntax-entry ?\' "$ " muttrc-mode-syntax-table)
|
|
(modify-syntax-entry ?_ "w " muttrc-mode-syntax-table)
|
|
(modify-syntax-entry ?- "w " muttrc-mode-syntax-table)
|
|
)
|
|
|
|
;;; ------------------------------------------------------------
|
|
;;; The mode function itself.
|
|
;;; ------------------------------------------------------------
|
|
|
|
;;;###autoload
|
|
(defun muttrc-mode ()
|
|
"Major mode for editing Muttrc files.
|
|
This function ends by invoking the function(s) `muttrc-mode-hook'.
|
|
|
|
\\{muttrc-mode-map}
|
|
"
|
|
|
|
(interactive)
|
|
(kill-all-local-variables)
|
|
|
|
;; Font lock.
|
|
(make-local-variable 'font-lock-defaults)
|
|
(setq font-lock-defaults
|
|
'('muttrc-font-lock-keywords
|
|
nil nil nil nil
|
|
(font-lock-syntactic-keywords . (("'[^'\n]*'" 0 "\"")))))
|
|
|
|
;; Comment stuff.
|
|
(make-local-variable 'comment-start)
|
|
(setq comment-start "#")
|
|
(make-local-variable 'comment-end)
|
|
(setq comment-end "")
|
|
(make-local-variable 'comment-start-skip)
|
|
(setq comment-start-skip "#+[ \t]*")
|
|
|
|
;; become the current major mode
|
|
(setq major-mode 'muttrc-mode)
|
|
(setq mode-name "Muttrc")
|
|
|
|
;; Activate keymap and syntax table.
|
|
(use-local-map muttrc-mode-map)
|
|
(set-syntax-table muttrc-mode-syntax-table)
|
|
|
|
(run-hooks 'muttrc-mode-hook))
|
|
|
|
|
|
|
|
;;; ------------------------------------------------------------
|
|
;;; Other functions
|
|
;;; ------------------------------------------------------------
|
|
|
|
(defun muttrc-perform-nonreg-test ()
|
|
(interactive)
|
|
(save-excursion
|
|
(goto-char (point-min))
|
|
(while (re-search-forward "^# Begin\\s-+\\(.*\\)$" nil t)
|
|
(let ((test-name (match-string-no-properties 1))
|
|
(expr ""))
|
|
(catch 'loop
|
|
(while t
|
|
(or (= (forward-line 1) 0)
|
|
(throw 'loop t))
|
|
(if (looking-at (format "^# End\\s-+%s\\s-*"
|
|
(regexp-quote test-name)))
|
|
(throw 'loop t))
|
|
(if (looking-at "^# End\\s-+\\(.*\\)$")
|
|
(error "Found end of %s before %s"
|
|
(match-string-no-properties 1) test-name))
|
|
(if (looking-at "^[^#]")
|
|
(error "End of %s not found" test-name))
|
|
(if (looking-at "^#\\s-*\\(.*\\)$")
|
|
(setq expr (concat expr (match-string-no-properties 1))))))
|
|
(if (eval (read expr))
|
|
(message "Passed: %s" test-name)
|
|
(error "Failed: %s" test-name))))))
|
|
|
|
(defun muttrc-quote-string (s)
|
|
"Add a backslash on quotes and surround by quotes if needed."
|
|
(save-match-data
|
|
(cond ((or (not s) (equal s "")) "''")
|
|
((string-match "^[^']*\\s-[^']*$" s) (format "'%s'" s))
|
|
((string-match "\\s-" s)
|
|
(concat "\""
|
|
(mapconcat (lambda (c)
|
|
(if (eq c ?\") "\\\""
|
|
(char-to-string c)))
|
|
s "")
|
|
"\""))
|
|
(t s))))
|
|
|
|
(defun muttrc-prompt-string (prompt-base &optional default)
|
|
(if default
|
|
(format "%s [%s]: " prompt-base default)
|
|
(format "%s: " prompt-base)))
|
|
|
|
(defun muttrc-token-around-point (alist &optional strip-fun)
|
|
(let ((word (and (functionp 'thing-at-point)
|
|
(funcall (or strip-fun 'identity)
|
|
(funcall 'thing-at-point 'word)))))
|
|
(if (and word (assoc word alist))
|
|
word)))
|
|
|
|
(defun muttrc-assignement (varname modifier &optional value)
|
|
(concat (format "%s%s" (or modifier "") varname)
|
|
(if (stringp value)
|
|
(format "=%s"
|
|
(muttrc-quote-string value))
|
|
"")))
|
|
|
|
(defun muttrc-split-next-set-line ()
|
|
"Returns the current line splitted into tokens. The result is a list
|
|
of tokens like:
|
|
\((CMD START END) ((VAR1 MODIFIER1 ASSIGNMENT1 START END) ... REST)).
|
|
Last element REST is one string that is the rest of the line."
|
|
(if (re-search-forward
|
|
"^\\s-*\\(set\\|unset\\|toggle\\|reset\\)\\s-+" nil t)
|
|
(let ((line (list (list (match-string-no-properties 1)
|
|
(match-beginning 1)
|
|
(match-end 1))))
|
|
(limit (save-excursion
|
|
(end-of-line)
|
|
(point))))
|
|
(catch 'done
|
|
(while (< (point) limit)
|
|
(or (looking-at
|
|
(format "\\<\\(inv\\|no\\)?\\([a-z][a-z_]*\\)\\>"))
|
|
(throw 'done t))
|
|
(let ((modifier (match-string-no-properties 1))
|
|
(varname (match-string-no-properties 2))
|
|
(assignment nil))
|
|
(goto-char (match-end 0))
|
|
(skip-syntax-forward "-" limit)
|
|
(if (or (looking-at ; Set without quote
|
|
"=\\s-*\\([^'\" \t\n#]+\\)")
|
|
(looking-at ; Set with double quote (")
|
|
"=\\s-*\"\\(\\([^\"\\]\\|\\\\.\\)*\\)\"")
|
|
(looking-at ; Set with single quote (')
|
|
"=\\s-*'\\([^']*\\)'"))
|
|
(let ((type (let ((desc (assoc varname
|
|
muttrc-variables-alist)))
|
|
(if desc (cadr desc)))))
|
|
(if type
|
|
(and (eq type 'boolean)
|
|
(message "%s: can't assign a boolean" varname))
|
|
(message "%s: unknown Muttrc variable"
|
|
varname))
|
|
(setq assignment (match-string-no-properties 1))
|
|
(goto-char (match-end 0))))
|
|
(nconc line (list (list varname modifier
|
|
assignment
|
|
(match-beginning 0)
|
|
(match-end 0))))
|
|
(skip-syntax-forward "-" limit))))
|
|
(skip-syntax-backward "-")
|
|
(if (looking-at ".+$")
|
|
(nconc line (list (list (match-string-no-properties 0)))))
|
|
(end-of-line)
|
|
line)))
|
|
|
|
(defun muttrc-splice-assignment (line varname)
|
|
"Returns a list where assignements for VARNAME are separated from
|
|
assignment for other variables."
|
|
(let ((l (cdr line))
|
|
(in '())
|
|
(out '()))
|
|
(while (and l (consp (car l)))
|
|
(let ((arg (car l)))
|
|
(if (string= (car arg) varname)
|
|
(setq in (append in (list arg)))
|
|
(setq out (append out (list arg)))))
|
|
(setq l (cdr l)))
|
|
(list in out)))
|
|
|
|
(defun muttrc-new-value (cmd varname type modifier value default)
|
|
(if (eq type 'boolean)
|
|
(cond ((string= cmd "set")
|
|
(cond ((null modifier) t)
|
|
((string= modifier "no") nil)
|
|
((string= modifier "inv") (not value))))
|
|
((string= cmd "unset")
|
|
(cond ((null modifier) nil)
|
|
((string= modifier "no") t)
|
|
((string= modifier "inv") value)))
|
|
((string= cmd "toggle") (not value))
|
|
((string= cmd "reset")
|
|
(cond ((null modifier) default)
|
|
((string= modifier "no") (not default))
|
|
((string= modifier "inv") (not default)))))
|
|
(cond ((string= cmd "set") value)
|
|
((string= cmd "unset") default)
|
|
((string= cmd "toggle")
|
|
(error "%s: can't toggle non boolean" varname))
|
|
((string= cmd "reset") default))))
|
|
|
|
(defun muttrc-get-value-and-point (varname)
|
|
"Fetch the value of VARIABLE from the current buffer. It returns a
|
|
cons (VALUE . POINT) where POINT is the beginning of the line defining
|
|
VARNAME."
|
|
(save-excursion
|
|
(let ((var-descriptor (assoc varname muttrc-variables-alist)))
|
|
(or var-descriptor
|
|
(error "%s: unknown variable." varname))
|
|
(goto-char (point-min))
|
|
(let ((type (nth 0 (cdr var-descriptor)))
|
|
(default (nth 1 (cdr var-descriptor)))
|
|
(pos nil))
|
|
(let ((value default))
|
|
;; We search all the definitions in the buffer because some
|
|
;; users may use toggle or set inv...
|
|
(catch 'done
|
|
(while t
|
|
(let ((line (muttrc-split-next-set-line)))
|
|
(or line (throw 'done t))
|
|
(let ((cmd (caar line))
|
|
(assignments
|
|
(car (muttrc-splice-assignment line varname))))
|
|
(if assignments
|
|
(setq pos (save-excursion
|
|
(beginning-of-line)
|
|
(point))))
|
|
(while assignments
|
|
(let ((modifier (nth 1 (car assignments)))
|
|
(new-value (nth 2 (car assignments))))
|
|
(setq value
|
|
(muttrc-new-value cmd varname type modifier
|
|
(or new-value value)
|
|
default)))
|
|
(setq assignments (cdr assignments)))))))
|
|
(cons value pos))))))
|
|
|
|
(defun muttrc-get-value (varname)
|
|
"Fetch the value of VARIABLE from the current buffer."
|
|
(let ((value (muttrc-get-value-and-point varname)))
|
|
(and value (car value))))
|
|
|
|
;;; ------------------------------------------------------------
|
|
;;; Viewing manual
|
|
;;; ------------------------------------------------------------
|
|
|
|
(defvar muttrc-manual-buffer-name "*Mutt Manual*")
|
|
|
|
(defun muttrc-find-manual-file-no-select ()
|
|
"Convert overstriking and underlining to the correct fonts in a
|
|
file. The buffer does not visit the file."
|
|
(interactive)
|
|
(or (file-readable-p muttrc-manual-path)
|
|
(error "%s: file not found" muttrc-manual-path))
|
|
(let ((buf (get-buffer-create muttrc-manual-buffer-name)))
|
|
(save-excursion
|
|
(set-buffer buf)
|
|
(if (not buffer-read-only)
|
|
(let ((insert-contents-fun
|
|
(condition-case nil
|
|
(and (require 'jka-compr)
|
|
'jka-compr-insert-file-contents)
|
|
(error 'insert-file-contents))))
|
|
(funcall insert-contents-fun muttrc-manual-path nil nil nil t)
|
|
(buffer-disable-undo buf)
|
|
(Man-fontify-manpage)
|
|
(set-buffer-modified-p nil)
|
|
(toggle-read-only)
|
|
(goto-char (point-min))))
|
|
buf)))
|
|
|
|
(defun muttrc-find-manual-file ()
|
|
"Convert overstriking and underlining to the correct fonts in a
|
|
file. The buffer does not visit the file."
|
|
(interactive)
|
|
(switch-to-buffer-other-window
|
|
(muttrc-find-manual-file-no-select) t))
|
|
|
|
(defun muttrc-search-command-help-forward (command)
|
|
(when (re-search-forward
|
|
(format "^[ \t]*Usage:\\s-*\\(\\[un\\]\\)?%s" command)
|
|
nil t)
|
|
(goto-char (match-beginning 0))
|
|
(forward-line -2)
|
|
(point)))
|
|
|
|
(defun muttrc-search-variable-help-forward (command)
|
|
(when (and (re-search-forward
|
|
(format "^[ \t]*%s\\.?\\s-*%s\\s-*$"
|
|
"\\([1-9][0-9.]*\\)"
|
|
(regexp-quote variable))
|
|
nil t)
|
|
(re-search-forward
|
|
(format "^[ \t]*%s\\.?\\s-*%s\\s-*$"
|
|
"\\([1-9][0-9.]*\\)"
|
|
(regexp-quote variable))
|
|
nil t)
|
|
(re-search-forward
|
|
(format "^[ \t]*%s\\.?\\s-*%s\\s-*$"
|
|
(regexp-quote (match-string-no-properties 1))
|
|
(regexp-quote variable))
|
|
nil t))
|
|
(goto-char (match-beginning 0))
|
|
(point)))
|
|
|
|
(defun muttrc-find-help (search-fun topic)
|
|
"Find an help topic in the manual and display it. Returns the manual
|
|
buffer."
|
|
(let ((buf (muttrc-find-manual-file-no-select)))
|
|
(let ((win (get-buffer-window buf))
|
|
help-start)
|
|
(save-excursion
|
|
(set-buffer buf)
|
|
(goto-char (point-min))
|
|
(or (funcall search-fun topic)
|
|
(error "%s: entry not found in Mutt manual." command))
|
|
(setq help-start (point))
|
|
(unless (get-buffer-window buf)
|
|
(switch-to-buffer-other-window buf t))
|
|
(set-window-start win help-start)))
|
|
buf))
|
|
|
|
(defun muttrc-find-command-help (&optional command)
|
|
(interactive
|
|
(let ((word (muttrc-token-around-point muttrc-command-alist)))
|
|
(list (muttrc-get-from-list "Command" word 'muttrc-command-alist t))))
|
|
(muttrc-find-help 'muttrc-search-command-help-forward
|
|
(if (string-match "^un\\(.*\\)$" command)
|
|
(match-string-no-properties 1 command)
|
|
command)))
|
|
|
|
(defun muttrc-find-variable-help (&optional variable)
|
|
(interactive
|
|
(list
|
|
(let ((word (muttrc-token-around-point
|
|
muttrc-variables-alist
|
|
(function
|
|
(lambda (word)
|
|
(if (and word
|
|
(string-match "^\\(no\\|inv\\)\\(.*\\)$" word))
|
|
(match-string-no-properties 2 word)
|
|
word))))))
|
|
(muttrc-get-from-list "Variable" word 'muttrc-variables-alist))))
|
|
(muttrc-find-help 'muttrc-search-variable-help-forward variable))
|
|
|
|
(defun muttrc-bury-manual-buffer ()
|
|
(let ((buf (get-buffer muttrc-manual-buffer-name)))
|
|
(if buf (bury-buffer buf))))
|
|
|
|
;;; ------------------------------------------------------------
|
|
;;; Argument handlers
|
|
;;; ------------------------------------------------------------
|
|
|
|
(defun muttrc-call-arg-handler (key default &optional prompt)
|
|
"Call the function that properly prompts for an argument type."
|
|
(let ((handler-args (assoc key muttrc-arg-handler-alist)))
|
|
(or handler-args
|
|
(error "%s: unknown argument type." (symbol-name key)))
|
|
(let ((cmd (nth 0 (cdr handler-args)))
|
|
(default-prompt (nth 1 (cdr handler-args)))
|
|
(args (cdr (cddr handler-args))))
|
|
(apply cmd (or prompt default-prompt) default args))))
|
|
|
|
(defun muttrc-get-boolean (prompt &optional default)
|
|
"Prompt for a boolean."
|
|
(y-or-n-p (format "%s? " prompt)))
|
|
|
|
(defun muttrc-get-number (prompt default)
|
|
"Prompt for a string and return DEFAULT if the string is empty"
|
|
(or (read-from-minibuffer (muttrc-prompt-string prompt default))
|
|
default))
|
|
|
|
(defun muttrc-get-string (prompt default)
|
|
"Prompt for a string and return DEFAULT if the string is empty"
|
|
(let ((s (read-from-minibuffer (muttrc-prompt-string prompt default))))
|
|
(if (> (length s) 0) s default)))
|
|
|
|
(defun muttrc-get-word (prompt default)
|
|
"Prompt for a word and return DEFAULT if it is empty"
|
|
(let ((s (read-from-minibuffer (muttrc-prompt-string prompt default))))
|
|
(or (string-match "^\\w*$" s)
|
|
(error "%s: invalid entry, expecting a word" s))
|
|
(if (> (length s) 0) s default)))
|
|
|
|
(defun muttrc-get-from-list (prompt default list &optional require-match)
|
|
"Prompt for a string from list and return DEFAULT if the string is empty"
|
|
(let ((s (completing-read (muttrc-prompt-string prompt default)
|
|
(symbol-value list)
|
|
nil require-match)))
|
|
(if (> (length s) 0) s default)))
|
|
|
|
(defun muttrc-get-path (prompt default)
|
|
"Prompt for a path and return DEFAULT if the string is empty. The
|
|
muttrc folder prefix is replaced by MUTTRC-FOLDER-ABBREV."
|
|
(let* ((folder (muttrc-get-value "folder"))
|
|
(path (read-file-name (muttrc-prompt-string prompt default)
|
|
folder folder)))
|
|
(let ((compacted-path
|
|
(if (string-match (format "^%s/?\\(.*\\)$" (regexp-quote folder))
|
|
path)
|
|
(format "%s%s"
|
|
(char-to-string muttrc-folder-abbrev)
|
|
(match-string-no-properties 1 path))
|
|
path)))
|
|
(if (not (string= compacted-path
|
|
(char-to-string muttrc-folder-abbrev)))
|
|
compacted-path
|
|
default))))
|
|
|
|
(defun muttrc-get-assignment (&optional prompt default
|
|
with-value-p)
|
|
(let ((varname (completing-read (muttrc-prompt-string prompt default)
|
|
muttrc-variables-alist)))
|
|
(if (assoc varname muttrc-variables-alist)
|
|
(let* ((type (cadr (assoc varname muttrc-variables-alist)))
|
|
(default (car-safe (muttrc-get-value-and-point varname)))
|
|
(value (if with-value-p
|
|
(muttrc-call-arg-handler type default "Value"))))
|
|
(if with-value-p
|
|
(muttrc-assignement varname
|
|
(and (eq type 'boolean)
|
|
(not value)
|
|
"no")
|
|
value)
|
|
varname))
|
|
default)))
|
|
|
|
;;; ------------------------------------------------------------
|
|
;;; Commands insertion
|
|
;;; ------------------------------------------------------------
|
|
|
|
(defun muttrc-get-command (&optional prompt default)
|
|
"Prompts the usr for a command to enter and asks for all the arguments."
|
|
(let* ((cmd (muttrc-get-from-list "Command" nil 'muttrc-command-alist t))
|
|
(cmd-descriptor (cdr (assoc cmd muttrc-command-alist)))
|
|
(arg-list-type (nth 0 cmd-descriptor))
|
|
(repeat-p (nth 1 cmd-descriptor))
|
|
(optional-p (nth 2 cmd-descriptor))
|
|
(arg-list-value (list cmd)))
|
|
(save-window-excursion
|
|
(if (and muttrc-display-help)
|
|
(save-excursion
|
|
(muttrc-find-command-help cmd)))
|
|
(while arg-list-type
|
|
(let* ((arg-type (caar arg-list-type))
|
|
(arg (apply 'muttrc-call-arg-handler
|
|
(append (list arg-type nil)
|
|
(cdar arg-list-type)))))
|
|
(if arg
|
|
(progn
|
|
(nconc arg-list-value
|
|
(list (if (eq arg-type 'assignment)
|
|
arg ; assignment are quoted by handler
|
|
(muttrc-quote-string arg))))
|
|
(if (and repeat-p
|
|
(null (cdr arg-list-type)))
|
|
(setq optional-p t)
|
|
(setq arg-list-type (cdr arg-list-type))))
|
|
(if (and (null (cdr arg-list-type))
|
|
optional-p)
|
|
(setq arg-list-type nil)
|
|
(error "Argument required"))))))
|
|
(muttrc-bury-manual-buffer)
|
|
(mapconcat 'identity arg-list-value " ")))
|
|
|
|
(defun muttrc-get-statement (&optional prompt default)
|
|
(let ((muttrc-command-alist muttrc-statement-alist))
|
|
(muttrc-get-command prompt default)))
|
|
|
|
(defun muttrc-insert-command ()
|
|
"Insert a muttrc command on the current line."
|
|
(interactive)
|
|
(let ((cmd-line (muttrc-get-command)))
|
|
(beginning-of-line)
|
|
(or (eolp) (forward-line 1))
|
|
(insert cmd-line)
|
|
(newline)))
|
|
|
|
;;; ------------------------------------------------------------
|
|
;;; Setting variables
|
|
;;; ------------------------------------------------------------
|
|
|
|
(defun muttrc-update-current-line (varname type &optional value)
|
|
"Rewrites the current line by setting VARNAME to VALUE. If the
|
|
statement is not \"set\", the variable is removed. In set statement,
|
|
it is removed if the value is NIL and the variable is not a boolean.
|
|
The function returns t is the variable is really assigned in the line."
|
|
(let* ((line (muttrc-split-next-set-line))
|
|
(cmd (caar line))
|
|
(kill-whole-line t)
|
|
(args "")
|
|
(set-p nil))
|
|
(beginning-of-line)
|
|
(kill-line)
|
|
(let ((l (cdr line)))
|
|
(while l
|
|
(let ((elt (car l)))
|
|
(if (consp elt)
|
|
(let ((this-var (nth 0 elt))
|
|
(this-modifier (nth 1 elt))
|
|
(this-value (nth 2 elt)))
|
|
(let ((assignement
|
|
(if (string= this-var varname)
|
|
(when (string= cmd "set")
|
|
(setq set-p t)
|
|
(cond ((eq type 'boolean)
|
|
(muttrc-assignement varname
|
|
(if (not value) "no")
|
|
value))
|
|
(value
|
|
(muttrc-assignement varname nil value))
|
|
(t (setq set-p nil))))
|
|
(muttrc-assignement this-var
|
|
this-modifier
|
|
this-value))))
|
|
(if assignement
|
|
(setq args (concat args " " assignement)))))
|
|
(setq args (concat args elt))))
|
|
(setq l (cdr l))))
|
|
(when (not (string= args ""))
|
|
(insert cmd)
|
|
(insert args)
|
|
(newline))
|
|
(backward-char 1)
|
|
set-p))
|
|
|
|
(defun muttrc-update-variable (varname type value pos)
|
|
(catch 'done
|
|
(when pos
|
|
(goto-char pos)
|
|
(if (muttrc-update-current-line varname type value)
|
|
(throw 'done t)))
|
|
(end-of-line)
|
|
(let ((cr-after-p (bolp))
|
|
(cmd (if (or value (eq type 'boolean)) "set" "unset"))
|
|
(modifier (if (and (not value) (eq type 'boolean)) "no")))
|
|
(or cr-after-p (newline))
|
|
(insert cmd " "
|
|
(muttrc-assignement varname modifier value))
|
|
(if cr-after-p (newline))))
|
|
t)
|
|
|
|
(defun muttrc-set-variable (&optional varname type value pos)
|
|
(interactive
|
|
(let* ((varname (muttrc-get-from-list "Variable" nil
|
|
'muttrc-variables-alist t))
|
|
(type (cadr (assoc varname muttrc-variables-alist)))
|
|
(default (muttrc-get-value-and-point varname)))
|
|
(list varname type
|
|
(save-window-excursion
|
|
(if muttrc-display-help
|
|
(save-excursion
|
|
(muttrc-find-variable-help varname)))
|
|
(muttrc-call-arg-handler type (car default)))
|
|
(cdr default))))
|
|
(muttrc-bury-manual-buffer)
|
|
(muttrc-update-variable varname type value pos))
|
|
|
|
(defun muttrc-unset-variable (&optional varname type pos)
|
|
(interactive
|
|
(let* ((varname (muttrc-get-from-list "Variable" nil
|
|
'muttrc-variables-alist t))
|
|
(type (cadr (assoc varname muttrc-variables-alist)))
|
|
(default (muttrc-get-value-and-point varname)))
|
|
(list varname type (cdr default))))
|
|
(muttrc-update-variable varname type nil pos))
|
|
|
|
(defun muttrc-find-variable-in-buffer (&optional varname)
|
|
(interactive
|
|
(list (muttrc-get-from-list "Variable" nil
|
|
'muttrc-variables-alist t)))
|
|
(let* ((var-info (muttrc-get-value-and-point varname))
|
|
(value (car var-info))
|
|
(pos (cdr-safe var-info)))
|
|
(if pos
|
|
(goto-char pos)
|
|
(progn
|
|
(message "%s: variable not set (default: %s)" varname value)))))
|
|
|
|
;;; ------------------------------------------------------------
|
|
;;; Almost the end
|
|
;;; ------------------------------------------------------------
|
|
|
|
(provide 'muttrc-mode)
|
|
|
|
;;; muttrc-mode.el ends here
|