1 ;;; sieve-mode.el --- Sieve code editing commands for Emacs
3 ;; Copyright (C) 2001-2018 Free Software Foundation, Inc.
5 ;; Author: Simon Josefsson <simon@josefsson.org>
7 ;; This file is part of GNU Emacs.
9 ;; GNU Emacs is free software: you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation, either version 3 of the License, or
12 ;; (at your option) any later version.
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
24 ;; This file contain editing mode functions and font-lock support for
25 ;; editing Sieve scripts. It sets up C-mode with support for
26 ;; sieve-style #-comments and a lightly hacked syntax table. It was
27 ;; strongly influenced by awk-mode.el.
29 ;; Put something similar to the following in your .emacs to use this file:
31 ;; (load "~/lisp/sieve")
32 ;; (setq auto-mode-alist (cons '("\\.siv\\'" . sieve-mode) auto-mode-alist))
37 ;; "Sieve: A Mail Filtering Language",
42 ;; 2001-03-02 version 1.0 posted to gnu.emacs.sources
43 ;; version 1.1 change file extension into ".siv" (official one)
44 ;; added keymap and menubar to hook into sieve-manage
45 ;; 2001-10-31 version 1.2 committed to Oort Gnus
49 (autoload 'sieve-manage
"sieve")
50 (autoload 'sieve-upload
"sieve")
58 (defcustom sieve-mode-hook nil
59 "Hook run in sieve mode buffers."
64 (defface sieve-control-commands
65 '((((type tty
) (class color
)) (:foreground
"blue" :weight light
))
66 (((class grayscale
) (background light
)) (:foreground
"LightGray" :bold t
))
67 (((class grayscale
) (background dark
)) (:foreground
"DimGray" :bold t
))
68 (((class color
) (background light
)) (:foreground
"Orchid"))
69 (((class color
) (background dark
)) (:foreground
"LightSteelBlue"))
71 "Face used for Sieve Control Commands.")
73 (defface sieve-action-commands
74 '((((type tty
) (class color
)) (:foreground
"blue" :weight bold
))
75 (((class color
) (background light
)) (:foreground
"Blue"))
76 (((class color
) (background dark
)) (:foreground
"LightSkyBlue"))
77 (t (:inverse-video t
:bold t
)))
78 "Face used for Sieve Action Commands.")
80 (defface sieve-test-commands
81 '((((type tty
) (class color
)) (:foreground
"magenta"))
82 (((class grayscale
) (background light
))
83 (:foreground
"LightGray" :bold t
:underline t
))
84 (((class grayscale
) (background dark
))
85 (:foreground
"Gray50" :bold t
:underline t
))
86 (((class color
) (background light
)) (:foreground
"CadetBlue"))
87 (((class color
) (background dark
)) (:foreground
"Aquamarine"))
88 (t (:bold t
:underline t
)))
89 "Face used for Sieve Test Commands.")
91 (defface sieve-tagged-arguments
92 '((((type tty
) (class color
)) (:foreground
"cyan" :weight bold
))
93 (((class grayscale
) (background light
)) (:foreground
"LightGray" :bold t
))
94 (((class grayscale
) (background dark
)) (:foreground
"DimGray" :bold t
))
95 (((class color
) (background light
)) (:foreground
"Purple"))
96 (((class color
) (background dark
)) (:foreground
"Cyan"))
98 "Face used for Sieve Tagged Arguments.")
101 (defconst sieve-font-lock-keywords
105 (cons (regexp-opt '("require" "if" "else" "elsif" "stop")
107 'sieve-control-commands
)
109 (cons (regexp-opt '("fileinto" "redirect" "reject" "keep" "discard")
111 'sieve-action-commands
)
113 (cons (regexp-opt '("address" "allof" "anyof" "exists" "false"
114 "true" "header" "not" "size" "envelope"
117 'sieve-test-commands
)
119 'sieve-tagged-arguments
))))
123 (defvar sieve-mode-syntax-table
124 (let ((st (make-syntax-table)))
125 (modify-syntax-entry ?
\\ "\\" st
)
126 (modify-syntax-entry ?
\n "> " st
)
127 (modify-syntax-entry ?
\f "> " st
)
128 (modify-syntax-entry ?\
# "< " st
)
129 (modify-syntax-entry ?
/ ". 14" st
)
130 (modify-syntax-entry ?
* ". 23b" st
)
131 (modify-syntax-entry ?
+ "." st
)
132 (modify-syntax-entry ?-
"." st
)
133 (modify-syntax-entry ?
= "." st
)
134 (modify-syntax-entry ?%
"." st
)
135 (modify-syntax-entry ?
< "." st
)
136 (modify-syntax-entry ?
> "." st
)
137 (modify-syntax-entry ?
& "." st
)
138 (modify-syntax-entry ?|
"." st
)
139 (modify-syntax-entry ?_
"_" st
)
140 (modify-syntax-entry ?
\' "\"" st
)
142 "Syntax table in use in sieve-mode buffers.")
145 ;; Key map definition
147 (defvar sieve-mode-map
148 (let ((map (make-sparse-keymap)))
149 (define-key map
"\C-c\C-l" 'sieve-upload
)
150 (define-key map
"\C-c\C-c" 'sieve-upload-and-kill
)
151 (define-key map
"\C-c\C-m" 'sieve-manage
)
153 "Key map used in sieve mode.")
157 (easy-menu-define sieve-mode-menu sieve-mode-map
160 ["Upload script" sieve-upload t
]
161 ["Manage scripts on server" sieve-manage t
]))
163 ;; Code for Sieve editing mode.
166 (defun sieve-syntax-propertize (beg end
)
168 (sieve-syntax-propertize-text end
)
170 (syntax-propertize-rules
171 ;; FIXME: When there's a "text:" with a # comment, the \n plays dual role:
172 ;; it closes the comment and starts the string. This is problematic for us
173 ;; since syntax-table entries can either close a comment or
174 ;; delimit a string, but not both.
175 ("\\_<text:[ \t]*\\(?:#.*\\(.\\)\\)?\\(\n\\)"
177 (2 (prog1 (unless (save-excursion
178 (nth 8 (syntax-ppss (match-beginning 0))))
179 (string-to-syntax "|"))
180 (sieve-syntax-propertize-text end
)))))
183 (defun sieve-syntax-propertize-text (end)
184 (let ((ppss (syntax-ppss)))
185 (when (and (eq t
(nth 3 ppss
))
186 (re-search-forward "^\\.\\(\n\\)" end
'move
))
187 (put-text-property (match-beginning 1) (match-end 1)
188 'syntax-table
(string-to-syntax "|")))))
191 (define-derived-mode sieve-mode c-mode
"Sieve"
192 "Major mode for editing Sieve code.
193 This is much like C mode except for the syntax of comments. Its keymap
194 inherits from C mode's and it has the same variables for customizing
195 indentation. It has its own abbrev table and its own syntax table.
197 Turning on Sieve mode runs `sieve-mode-hook'."
198 (set (make-local-variable 'paragraph-start
) (concat "$\\|" page-delimiter
))
199 (set (make-local-variable 'paragraph-separate
) paragraph-start
)
200 (set (make-local-variable 'comment-start
) "#")
201 (set (make-local-variable 'comment-end
) "")
202 ;;(set (make-local-variable 'comment-start-skip) "\\(^\\|\\s-\\);?#+ *")
203 (set (make-local-variable 'comment-start-skip
) "#+ *")
204 (set (make-local-variable 'syntax-propertize-function
)
205 #'sieve-syntax-propertize
)
206 (set (make-local-variable 'font-lock-defaults
)
207 '(sieve-font-lock-keywords nil nil
((?_ .
"w"))))
208 (easy-menu-add-item nil nil sieve-mode-menu
))
210 (provide 'sieve-mode
)
212 ;; sieve-mode.el ends here