+2001-06-01 Kenichi OKADA <okada@opaopa.org>
+
+ * SLIM: Version 1.14.7 released.
+
+2001-06-01 Katsumi Yamaoka <yamaoka@jpl.org>
+
+ * mel-b-el.el: Require `pces' for the macro `as-binary-process'
+ when compiling.
+
+ * mel-q.el: Add a comment that the feature `poem' is also required
+ for the macro `as-binary-process'.
+
+2001-05-31 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+
+ Merged MIME Parameter Value decoder.
+
+ * mime-parse.el (mime-decode-parameters): Renamed from
+ `mime-decode-parameter-plist'.
+ (mime-decode-parameter-alist): Removed.
+ (mime-decode-alist-to-plist): Ditto.
+
+ * FLIM-API.en (mime-entity-encoding): Abolish optional argument
+ `default-encoding'.
+ (mime-parse-Content-Tranfer-Encoding): Ditto.
+
+2001-05-02 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+
+ * eword-decode.el (eword-decode-encoded-word): Don't use `let'.
+
+ * mime-parse.el (mime-decode-parameter-plist): Modified
+ description of return value.
+ (mime-parse-Content-Type): Ditto.
+ (mime-read-Content-Type): Ditto.
+ (mime-parse-Content-Disposition): Ditto.
+ (mime-read-Content-Disposition): Ditto.
+ (mime-parse-Content-Transfer-Encoding): Ditto.
+ (mime-read-Content-Transfer-Encoding): Ditto.
+
+2001-05-01 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+
+ * mime-parse.el (mime-parse-parameters): Don't use `equal' for
+ strings.
+ (mime-parse-Content-Type): Ditto.
+
+2001-04-30 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+
+ * mime-parse.el (mime-decode-parameter-value): Use one temporary
+ buffer.
+ (mime-decode-parameter-plist): Changed internal data structure.
+
+2001-04-28 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+
+ * eword-decode.el (eword-encoded-word-regexp): Match for language.
+ (eword-decode-region): Refer the 7th parens, not 6th.
+ (eword-decode-encoded-word): Extract language information.
+ (eword-decode-encoded-text): New optional argument `language'.
+
+ * mime-def.el (mime-charset-regexp): Updated for RFC2231.
+
+ * mime-parse.el (mime-decode-parameter-plist): Fix regexp.
+ Use symbol for language information.
+
+ * tests/test-rfc2231.el: Renamed all testcases.
+
+2001-04-27 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+
+ * mime-parse.el (mime-decode-parameter-value): Don't use
+ `int-char'.
+
+2001-04-27 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+
+ * mime.el (mime-entity-read-field): Would capitalize twice.
+
+ * mmbuffer.el (mime-entity-fetch-field): Ditto.
+
+ * mmexternal.el (mime-entity-fetch-field): Ditto.
+
+ * mmgeneric.el (mime-entity-fetch-field): Ditto.
+
+2001-04-26 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+
+ * mime-parse.el (mime-decode-parameter-plist): Modified
+ description of return value.
+ (mime-parse-Content-Type): Ditto.
+ (mime-read-Content-Type): Ditto.
+ (mime-parse-Content-Disposition): Ditto.
+ (mime-read-Content-Disposition): Ditto.
+ (mime-read-Content-Transfer-Encoding): Ditto.
+
+2001-04-25 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+
+ * mime-parse.el (mime-lexical-analyze): Removed comments.
+
+2001-04-22 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+
+ * mime-parse.el (mime-decode-parameter-value): New
+ implementation; use temporary buffer for conversion.
+ (mime-decode-parameter-encode-segment): Ditto.
+ (mime-decode-parameter-plist): Would put empty language info.
+
+ * test/test-rfc2231.el (test-rfc2231-10, test-rfc2231-11,
+ test-rfc2231-12): New testcases for language info.
+
+2001-04-22 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+
+ * mime-parse.el: Fixed comments.
+
+ * test/test-rfc2231.el (test-rfc2231-9): New testcase.
+
+2001-04-22 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+
+ * test/test-rfc2231.el (test-rfc2231-7, test-rfc2231-8):
+ New testcases.
+
+2001-04-22 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+
+ * mime-def.el (mime-content-type-parameter): Expand
+ `mime-content-type-parameters'.
+
+ * mime-parse.el (mime-parse-Content-Disposition): Add
+ description of return value to the docstring.
+ (mime-parse-Content-Transfer-Encoding): Ditto.
+
+ * test/test-rfc2231.el: Made independent of internal
+ representation of Content-Type.
+
+2001-04-22 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+
+ * FLIM-MK (check-flim): Limit filename of test files.
+
+ * test/test-rfc2231.el: New file.
+
+2001-04-19 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+
+ * mime-parse.el (mime-decode-parameter-plist): Shortcut for
+ parameters without extensions.
+
+2001-04-19 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+
+ * mime-def.el (make-mime-content-type): Don't reverse parameters.
+ (make-mime-content-disposition): New function.
+
+ * mime-parse.el (mime-decode-parameter-value): Removed comments.
+ (mime-decode-parameter-encode-segment): New function.
+ (mime-decode-parameter-plist): New implementation.
+ Switched from decode-then-concat to concat-then-decode model.
+ (mime-parse-parameters): Strip quoted-pair in quoted-string.
+ (mime-parse-Content-Type): Use `make-mime-content-type'.
+ (mime-parse-Content-Disposition): Use
+ `make-mime-content-disposition'.
+
2001-04-15 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
* eword-decode.el (eword-lexical-analyze-internal):
Fix typo. [cf. <emacs-mime-ja:00425>]
+2001-04-11 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
+
+ * mime-parse.el (mime-decode-parameter-value): Allow lowercase.
+ (mime-decode-parameter-plist): Ditto.
+
2001-04-10 Akihiro Arisawa <ari@mbf.sphere.ne.jp>
* std11.el (std11-lexical-analyze): Fix typo.
+2001-04-01 Daiki Ueno <ueno@unixuser.org>
+
+ * lunit.el (lunit-test-listener-*): Abolish generic interface.
+ (lunit-test-result-notify): New function.
+ (lunit-test-result-run): Use it.
+ (lunit-test-result-error): Use it.
+ (lunit-test-result-failure): Use it.
+ (lunit-create-index-function): New function.
+ (lunit-generate-template): New command.
+
2001-03-19 Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
* hmac-md5.el, hmac-sha1.el: Revert to load-time check.
FLIM (Faithful Library about Internet Message) API
Version 1.14
- Draft Release 2
+ Draft Release 3
* Notation
(Usage: SEMI 1.14 MIME-View)
-[Function] mime-entity-encoding (entity &optional default-encoding)
+[Function] mime-entity-encoding (entity)
Return content-transfer-encoding of ENTITY.
- If the ENTITY does not have Content-Transfer-Encoding field, this
- function returns DEFAULT-ENCODING. If it is nil, "7bit" is used as
- default value.
+ If the ENTITY does not have valid Content-Transfer-Encoding field,
+ return nil.
[Suggest]
(Usage: SEMI 1.14 MIME-View)
[Required]<Suggest>
-* MIME Field parsing
+* MIME Field
** How to use
(require 'mime)
-** Level 2 features
+** Parsing
[Variable] mime-field-parser-alist
Alist to specify field parser.
-
-[Function] mime-parse-Content-Type (string)
- Parse STRING as field-body of Content-Type field.
-
-Return value is
- (PRIMARY-TYPE SUBTYPE (NAME1 . VALUE1)(NAME2 . VALUE2) ...)
-or nil. PRIMARY-TYPE and SUBTYPE are symbol and NAME_n and VALUE_n
-are string.
+ [Suggest]
-[Function] mime-read-Content-Type ()
- Read field-body of Content-Type field from current-buffer,
-and return parsed it. Format of return value is as same as
-`mime-parse-Content-Type'.
+[Function] mime-parse-msg-id (tokens)
+ Parse TOKENS as msg-id of Content-Id or Message-Id field.
+ [Suggest]
-[Function] mime-parse-Content-Disposition (string)
- Parse STRING as field-body of Content-Disposition field.
+[Function] mime-uri-parse-cid (string)
+ Parse STRING as cid URI.
-[Function] mime-read-Content-Disposition ()
- Read field-body of Content-Disposition field from current-buffer,
-and return parsed it.
+ [Suggest]
[Function] mime-parse-Content-Transfer-Encoding (string)
Parse STRING as field-body of Content-Transfer-Encoding field.
+ If STRING is not a valid Content-Transfer-Encoding field,
+ return nil.
+
+ [Suggest]
-[Function] mime-read-Content-Transfer-Encoding (&optional default-encoding)
+[Function] mime-read-Content-Transfer-Encoding ()
Read field-body of Content-Transfer-Encoding field from
-current-buffer, and return it.
+ current-buffer, and return it.
-If is is not found, return DEFAULT-ENCODING.
+ [Suggest]
-[Function] mime-parse-msg-id (tokens)
- Parse TOKENS as msg-id of Content-Id or Message-Id field.
+* STD 11
+** How to use
-[Function] mime-uri-parse-cid (string)
- Parse STRING as cid URI.
+(require 'std11)
-* STD 11 parsing
+** Header
-** How to use
+[Function] std11-narrow-to-header (&optional boundary)
+ Narrow to the message header.
-(require 'std11)
+ If BOUNDARY is not nil, it is used as message header separator.
+
+ [Required]
-** Level 1 features
+** Field
[Function] std11-fetch-field (name)
Return the value of the header field NAME.
-The buffer is expected to be narrowed to just the headers of the message.
+ The buffer is expected to be narrowed to just the headers of the
+ message.
-
-[Function] std11-narrow-to-header (&optional boundary)
- Narrow to the message header.
-
-If BOUNDARY is not nil, it is used as message header separator.
+ [Required]
[Function] std11-field-body (name &optional boundary)
Return the value of the header field NAME.
-If BOUNDARY is not nil, it is used as message header separator.
+ If BOUNDARY is not nil, it is used as message header separator.
+
+ [Required]
[Function] std11-unfold-string (string)
Unfold STRING as message header field.
+ [Required]
+
-** Level 2 features
+** Lexical Analysis
[Function] std11-lexical-analyze (string &optional analyzer start)
Analyze STRING as lexical tokens of STD 11.
+ [Suggest]
+
+
+** Address
[Function] std11-address-string (address)
Return string of address part from parsed ADDRESS of RFC 822.
+ [Suggest]
+
[Function] std11-full-name-string (address)
Return string of full-name part from parsed ADDRESS of RFC 822.
-
-[Function] std11-msg-id-string (msg-id)
- Return string from parsed MSG-ID of RFC 822.
-
-
-[Function] std11-fill-msg-id-list-string (string &optional column)
- Fill list of msg-id in STRING, and return the result.
+ [Suggest]
[Function] std11-parse-address-string (string)
Parse STRING as mail address.
+ [Suggest]
+
[Function] std11-parse-addresses-string (string)
Parse STRING as mail address list.
+ [Suggest]
+
+
+[Function] std11-extract-address-components (string)
+ Extract full name and canonical address from STRING.
+
+ Returns a list of the form (FULL-NAME CANONICAL-ADDRESS). If no
+ name can be extracted, FULL-NAME will be nil.
+
+ [Suggest]
+
+
+** Message-ID
+
+[Function] std11-msg-id-string (msg-id)
+ Return string from parsed MSG-ID of RFC 822.
+
+ [Suggest]
+
[Function] std11-parse-msg-id-string (string)
Parse STRING as msg-id.
+ [Suggest]
+
[Function] std11-parse-msg-ids-string (string)
Parse STRING as `*(phrase / msg-id)'.
+ [Suggest]
-[Function] std11-extract-address-components (string)
- Extract full name and canonical address from STRING.
- Returns a list of the form (FULL-NAME CANONICAL-ADDRESS). If no
- name can be extracted, FULL-NAME will be nil.
+[Function] std11-fill-msg-id-list-string (string &optional column)
+ Fill list of msg-id in STRING, and return the result.
+
+ [Suggest]
* SMTP
[Suggest]
+
[Function] smtp-via-smtp (sender recipients buffer)
Like `smtp-send-buffer', but sucks in any errors.
(defun check-flim ()
(config-flim)
(require 'lunit)
- (let ((files (directory-files "tests" t))
+ (let ((files (directory-files "tests" t "^test-.*\\.el$"))
(suite (lunit-make-test-suite)))
(while files
(if (file-regular-p (car files))
PACKAGE = slim
API = 1.14
-RELEASE = 6
+RELEASE = 7
TAR = tar
RM = /bin/rm -f
1.14.4 \e$BA0ED0&\e(B
1.14.5 \e$B0BC#M4<B\e(B
1.14.6 \e$BGO^<1QN$2?\e(B
------- \e$B<r0f:LL>\e(B
+1.14.7 \e$B<r0f:LL>\e(B
1.14.0 Ninokuchi \e$(B?7%N8}\e(B
1.14.1 Yagi \e$(BH,LZ\e(B ; = \e$(B6aE4\e(B \e$(BBg:e@~\e(B
1.14.2 Yagi-Nishiguchi \e$(BH,LZ@>8}\e(B
------- Unebigory\e-Dòmae\e-A \e$(B@&K58fNMA0\e(B
+1.14.3 Unebigory\e-Dòmae\e-A \e$(B@&K58fNMA0\e(B
------ Kashiharajing\e-Dþ-mae\e-A \e$(B3`86?@5\A0\e(B ; = \e$(B6aE4\e(B \e$(BFnBg:e@~!"5HLn@~\e(B
(eval-when-compile
(concat (regexp-quote "=?")
"\\("
- mime-charset-regexp
+ mime-charset-regexp ; 1
"\\)"
+ "\\("
+ (regexp-quote "*")
+ mime-language-regexp ; 2
+ "\\)?"
(regexp-quote "?")
- "\\([BbQq]\\)"
+ "\\("
+ mime-encoding-regexp ; 3
+ "\\)"
(regexp-quote "?")
"\\("
- eword-encoded-text-regexp
+ eword-encoded-text-regexp ; 4
"\\)"
(regexp-quote "?="))))
)
"\\(\n?[ \t]\\)+"
"\\(" eword-encoded-word-regexp "\\)")
nil t)
- (replace-match "\\1\\6")
+ (replace-match "\\1\\7")
(goto-char (point-min))
)
(while (re-search-forward eword-encoded-word-regexp nil t)
word))
(defun eword-decode-encoded-word (word &optional must-unfold)
- "Decode WORD if it is an encoded-word.
-
-If your emacs implementation can not decode the charset of WORD, it
-returns WORD. Similarly the encoded-word is broken, it returns WORD.
-
-If MUST-UNFOLD is non-nil, it unfolds and eliminates line-breaks even
-if there are in decoded encoded-word (generated by bad manner MUA such
-as a version of Net$cape)."
- (or (if (string-match eword-encoded-word-regexp word)
- (let ((charset
- (substring word (match-beginning 1) (match-end 1))
- )
- (encoding
- (upcase
- (substring word (match-beginning 2) (match-end 2))
- ))
- (text
- (substring word (match-beginning 3) (match-end 3))
- ))
- (condition-case err
- (eword-decode-encoded-text charset encoding text must-unfold)
- (error
- (funcall eword-decode-encoded-word-error-handler word err)
- ))
- ))
+ "Decode WORD as an encoded-word.
+
+If charset is unknown or unsupported, return WORD.
+If encoding is unknown, or some error occurs while decoding,
+`eword-decode-encoded-word-error-handler' is called with WORD and an
+error condition.
+
+If MUST-UNFOLD is non-nil, unfold decoded WORD."
+ (or (and (string-match eword-encoded-word-regexp word)
+ (condition-case err
+ (eword-decode-encoded-text
+ ;; charset
+ (substring word (match-beginning 1)(match-end 1))
+ ;; language
+ (when (match-beginning 2)
+ (intern
+ (downcase
+ (substring word (1+ (match-beginning 2))(match-end 2)))))
+ ;; encoding
+ (upcase
+ (substring word (match-beginning 3)(match-end 3)))
+ ;; encoded-text
+ (substring word (match-beginning 4)(match-end 4))
+ must-unfold)
+ (error
+ (funcall eword-decode-encoded-word-error-handler word err))))
word))
;;; @ encoded-text decoder
;;;
-(defun eword-decode-encoded-text (charset encoding string
+(defun eword-decode-encoded-text (charset language encoding string
&optional must-unfold)
"Decode STRING as an encoded-text.
If your emacs implementation can not decode CHARSET, it returns nil.
+If LANGUAGE is non-nil, it is put to `mime-language' text-property.
If ENCODING is not \"B\" or \"Q\", it occurs error.
So you should write error-handling code if you don't want break by errors.
If MUST-UNFOLD is non-nil, it unfolds and eliminates line-breaks even
if there are in decoded encoded-text (generated by bad manner MUA such
as a version of Net$cape)."
- (let ((cs (mime-charset-to-coding-system charset)))
- (if cs
- (let ((dest (encoded-text-decode-string string encoding)))
- (when dest
- (setq dest (decode-mime-charset-string dest charset))
- (if must-unfold
- (mapconcat (function
- (lambda (chr)
- (cond ((eq chr ?\n) "")
- ((eq chr ?\t) " ")
- (t (char-to-string chr)))
- ))
- (std11-unfold-string dest)
- "")
- dest))))))
+ (when (mime-charset-to-coding-system charset)
+ (let ((dest (encoded-text-decode-string string encoding)))
+ (when dest
+ (setq dest (decode-mime-charset-string dest charset))
+ (when must-unfold
+ (mapconcat
+ (function
+ (lambda (chr)
+ (cond ((eq chr ?\n) "")
+ ((eq chr ?\t) " ")
+ (t (char-to-string chr)))))
+ (std11-unfold-string dest) ""))
+ (when language
+ (put-text-property 0 (length dest) 'mime-language language dest))
+ dest))))
;;; @ lexical analyze
;;; @ test listener
;;;
-(luna-define-class lunit-test-listener ())
-
-(luna-define-generic lunit-test-listener-error (listener case error)
- "An error occurred.")
-
-(luna-define-generic lunit-test-listener-failure (listener case failure)
- "A failure occurred.")
-
-(luna-define-generic lunit-test-listener-start (listener case)
- "A test started.")
-
-(luna-define-generic lunit-test-listener-end (listener case)
- "A test ended.")
+(luna-define-class lunit-test-listener)
;;; @ test result
;;;
(luna-define-generic lunit-test-result-run (result case)
"Run the test case.")
+(luna-define-generic lunit-test-result-notify (result message &rest args)
+ "Report the current state of execution.")
+
(luna-define-generic lunit-test-result-error (result case error)
"Add error to the list of errors.
The passed in exception caused the error.")
"Return a newly allocated `lunit-test-result' instance with LISTENERS."
(luna-make-entity 'lunit-test-result :listeners listeners))
-(luna-define-method lunit-test-result-run ((result lunit-test-result) case)
- (let ((listeners (lunit-test-result-listeners-internal result)))
+(luna-define-method lunit-test-result-notify ((result lunit-test-result)
+ message args)
+ (let ((listeners
+ (lunit-test-result-listeners-internal result)))
(dolist (listener listeners)
- (lunit-test-listener-start listener case))
- (condition-case error
- (lunit-test-case-run case)
- (lunit-failure
- (lunit-test-result-failure result case (nth 1 error)))
- (lunit-error
- (lunit-test-result-error result case (cdr error))))
- (dolist (listener listeners)
- (lunit-test-listener-end listener case))))
+ (apply #'luna-send listener message listener args))))
+
+(luna-define-method lunit-test-result-run ((result lunit-test-result) case)
+ (lunit-test-result-notify result 'lunit-test-listener-start case)
+ (condition-case error
+ (lunit-test-case-run case)
+ (lunit-failure
+ (lunit-test-result-failure result case (nth 1 error)))
+ (lunit-error
+ (lunit-test-result-error result case (cdr error))))
+ (lunit-test-result-notify result 'lunit-test-listener-end case))
(luna-define-method lunit-test-result-error ((result lunit-test-result)
case error)
- (let ((listeners (lunit-test-result-listeners-internal result))
- (errors (lunit-test-result-errors-internal result)))
- (if errors
- (nconc errors (list (cons case error)))
- (lunit-test-result-set-errors-internal result (list (cons case error))))
- (dolist (listener listeners)
- (lunit-test-listener-error listener case error))))
+ (let ((errors
+ (lunit-test-result-errors-internal result)))
+ (setq errors (nconc errors (list (cons case error))))
+ (lunit-test-result-set-errors-internal result errors))
+ (lunit-test-result-notify result 'lunit-test-listener-error case error))
(luna-define-method lunit-test-result-failure ((result lunit-test-result)
case failure)
- (let ((listeners (lunit-test-result-listeners-internal result))
- (failures (lunit-test-result-failures-internal result)))
- (if failures
- (nconc failures (list (cons case failure)))
- (lunit-test-result-set-failures-internal result (list (cons case failure))))
- (dolist (listener listeners)
- (lunit-test-listener-failure listener case failure))))
+ (let ((failures
+ (lunit-test-result-failures-internal result)))
+ (setq failures (nconc failures (list (cons case failure))))
+ (lunit-test-result-set-failures-internal result failures))
+ (lunit-test-result-notify result 'lunit-test-listener-failure case failure))
(luna-define-method lunit-test-result-add-listener ((result lunit-test-result)
listener)
- (let ((listeners (lunit-test-result-listeners-internal result)))
- (if listeners
- (nconc listeners (list listener))
- (lunit-test-result-set-listeners-internal result (list listener)))))
+ (let ((listeners
+ (lunit-test-result-listeners-internal result)))
+ (setq listeners (nconc listeners (list listener)))
+ (lunit-test-result-set-listeners-internal result listeners)))
;;; @ test case
;;;
(luna-define-method lunit-test-suite-add-test ((suite lunit-test-suite) test)
(let ((tests (lunit-test-suite-tests-internal suite)))
- (if tests
- (nconc tests (list test))
- (lunit-test-suite-set-tests-internal suite (list test)))))
+ (lunit-test-suite-set-tests-internal suite (nconc tests (list test)))))
(luna-define-method lunit-test-number-of-tests ((suite lunit-test-suite))
(let ((tests (lunit-test-suite-tests-internal suite))
case failure)
(princ (format " failure: %S" failure)))
-(luna-define-method lunit-test-listener-start ((printer lunit-test-printer) case)
+(luna-define-method lunit-test-listener-start ((printer lunit-test-printer)
+ case)
(princ (format "Running `%S#%S'..."
(luna-class-name case)
(lunit-test-name-internal case))))
(let* ((printer
(luna-make-entity 'lunit-test-printer))
(result
- (lunit-make-test-result printer))
- failures
- errors)
+ (lunit-make-test-result printer)))
(lunit-test-run test result)
- (setq failures (lunit-test-result-failures-internal result)
- errors (lunit-test-result-errors-internal result))
- (princ (format "%d runs, %d failures, %d errors\n"
- (lunit-test-number-of-tests test)
- (length failures)
- (length errors)))))
+ (let ((failures
+ (lunit-test-result-failures-internal result))
+ (errors
+ (lunit-test-result-errors-internal result)))
+ (princ (format "%d runs, %d failures, %d errors\n"
+ (lunit-test-number-of-tests test)
+ (length failures)
+ (length errors))))))
+
+(defvar imenu-create-index-function)
+(defun lunit-create-index-function ()
+ (require 'imenu)
+ (save-excursion
+ (unwind-protect
+ (progn
+ (goto-char (point-min))
+ (setq imenu-generic-expression
+ '((nil "^\\s-*(def\\(un\\|subst\\|macro\\)\\s-+\\([-A-Za-z0-9+*|:]+\\)" 2)))
+ (funcall imenu-create-index-function))
+ (setq imenu-create-index-function lisp-imenu-generic-expression))))
+
+(defun lunit-generate-template (file)
+ (interactive "fGenerate lunit template for: ")
+ (save-excursion
+ (set-buffer (find-file-noselect file))
+ (let ((index-alist
+ (lunit-create-index-function)))
+ (with-output-to-temp-buffer "*Lunit template*"
+ (let* ((feature
+ (file-name-sans-extension
+ (file-name-nondirectory file)))
+ (class
+ (concat "test-" feature)))
+ (set-buffer standard-output)
+ (insert "\
+\(require 'lunit)
+\(require '" feature ")
+
+\(luna-define-class " class " (lunit-test-case))
+
+")
+ (dolist (index index-alist)
+ (insert "\
+\(luna-define-method " class "-" (car index) " ((case " class "))
+ (lunit-assert nil))
+
+")))))))
(provide 'lunit)
;;; mel-b-el.el --- Base64 encoder/decoder.
-;; Copyright (C) 1992,1995,1996,1997,1998,1999 Free Software Foundation, Inc.
+;; Copyright (C) 1992,95,96,97,98,99,2001 Free Software Foundation, Inc.
;; Author: ENAMI Tsugutomo <enami@sys.ptg.sony.co.jp>
;; MORIOKA Tomohiko <tomo@m17n.org>
;;; Code:
(require 'mime-def)
+(eval-when-compile
+ ;; XXX: the macro `as-binary-process' should be provided when compiling.
+ (require 'pces))
;;; @ variables
;;; mel-q.el --- Quoted-Printable encoder/decoder.
-;; Copyright (C) 1995,1996,1997,1998,1999 Free Software Foundation, Inc.
+;; Copyright (C) 1995,96,97,98,99,2000,2001 Free Software Foundation, Inc.
;; Author: MORIOKA Tomohiko <tomo@m17n.org>
;; Created: 1995/6/25
(require 'path-util)
(eval-when-compile
;; XXX: should provide char-list instead of string-to-char-list.
+ ;; XXx: and also the macro `as-binary-process' should be provided
+ ;; XXx: by the module "pces" which will be loaded by way of "poem".
(require 'poem))
+
;;; @ Quoted-Printable encoder
;;;
;;; mime-def.el --- definition module about MIME -*- coding: iso-2022-jp; -*-
-;; Copyright (C) 1995,96,97,98,99,2000 Free Software Foundation, Inc.
+;; Copyright (C) 1995,96,97,98,99,2000,2001 Free Software Foundation, Inc.
;; Author: MORIOKA Tomohiko <tomo@m17n.org>
+;; Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
;; Keywords: definition, MIME, multimedia, mail, news
;; This file is part of FLIM (Faithful Library about Internet Message).
(require 'mcharset)
(require 'alist)
-(eval-when-compile
- (require 'cl) ; list*
- (require 'luna) ; luna-arglist-to-arguments
- )
+(eval-when-compile (require 'luna)) ; luna-arglist-to-arguments
(eval-and-compile
- (defconst mime-library-product ["SLIM" (1 14 6) "\e$BGO^<1QN$2?\e(B"]
+ (defconst mime-library-product ["SLIM" (1 14 7) "\e$B<r0f:LL>\e(B"]
"Product name, version number and code name of MIME-library package."))
(defmacro mime-product-name (product)
(defalias 'char-int 'identity))
-;;; @ about STD 11
+;;; @ MIME constants
;;;
-(eval-and-compile
- (defconst std11-quoted-pair-regexp "\\\\.")
- (defconst std11-non-qtext-char-list '(?\" ?\\ ?\r ?\n))
- (defconst std11-qtext-regexp
- (eval-when-compile
- (concat "[^" std11-non-qtext-char-list "]"))))
-(defconst std11-quoted-string-regexp
- (eval-when-compile
- (concat "\""
- (regexp-*
- (regexp-or std11-qtext-regexp std11-quoted-pair-regexp))
- "\"")))
+(defconst mime-tspecial-char-list
+ '(?\] ?\[ ?\( ?\) ?< ?> ?@ ?, ?\; ?: ?\\ ?\" ?/ ?? ?=))
+(defconst mime-token-regexp
+ (concat "[^" mime-tspecial-char-list "\000-\040]+"))
+(defconst mime-attribute-char-regexp
+ (concat "[^" mime-tspecial-char-list "\000-\040"
+ "*'%" ; introduced in RFC 2231.
+ "]"))
+(defconst mime-charset-regexp
+ (concat "[^" mime-tspecial-char-list "\000-\040"
+ "*'%" ; should not include "%"?
+ "]+"))
-;;; @ about MIME
-;;;
+;; More precisely, length of "[A-Za-z]+" is limited to at most 8.
+;; (defconst mime-language-regexp "[A-Za-z]+\\(-[A-Za-z]+\\)*")
+(defconst mime-language-regexp "[-A-Za-z]+")
-(eval-and-compile
- (defconst mime-tspecial-char-list
- '(?\] ?\[ ?\( ?\) ?< ?> ?@ ?, ?\; ?: ?\\ ?\" ?/ ?? ?=)))
-(defconst mime-token-regexp
- (eval-when-compile
- (concat "[^" mime-tspecial-char-list "\000-\040]+")))
-(defconst mime-charset-regexp mime-token-regexp)
-
-(defconst mime-media-type/subtype-regexp
- (concat mime-token-regexp "/" mime-token-regexp))
+(defconst mime-encoding-regexp mime-token-regexp)
;;; @@ base64 / B
;;;
(defsubst make-mime-content-type (type subtype &optional parameters)
- (list* (cons 'type type)
- (cons 'subtype subtype)
- (nreverse parameters))
- )
+ (cons (cons 'type type)
+ (cons (cons 'subtype subtype)
+ parameters)))
(defsubst mime-content-type-primary-type (content-type)
"Return primary-type of CONTENT-TYPE."
(defsubst mime-content-type-subtype (content-type)
"Return subtype of CONTENT-TYPE."
- (cdr (cadr content-type)))
+ (cdr (car (cdr content-type))))
(defsubst mime-content-type-parameters (content-type)
"Return parameters of CONTENT-TYPE."
- (cddr content-type))
+ (cdr (cdr content-type)))
(defsubst mime-content-type-parameter (content-type parameter)
"Return PARAMETER value of CONTENT-TYPE."
- (cdr (assoc parameter (mime-content-type-parameters content-type))))
+ (cdr (assoc parameter (cdr (cdr content-type)))))
(defsubst mime-type/subtype-string (type &optional subtype)
;;; @ Content-Disposition
;;;
+(defsubst make-mime-content-disposition (type &optional parameters)
+ (cons (cons 'type type)
+ parameters))
+
(defsubst mime-content-disposition-type (content-disposition)
"Return disposition-type of CONTENT-DISPOSITION."
(cdr (car content-disposition)))
;;; mime-parse.el --- MIME message parser
-;; Copyright (C) 1994,1995,1996,1997,1998,1999 Free Software Foundation, Inc.
+;; Copyright (C) 1994,95,96,97,98,99,2001 Free Software Foundation, Inc.
;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
;; Keywords: parse, MIME, multimedia, mail, news
-;; This file is part of SEMI (Spadework for Emacs MIME Interfaces).
+;; This file is part of FLIM (Faithful Library about Internet Message).
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
(defun mime-analyze-tspecial (string start)
(if (and (> (length string) start)
(memq (aref string start) mime-tspecial-char-list))
- (cons (cons 'tpecials (substring string start (1+ start)))
- (1+ start))
- ))
+ (cons (cons 'tspecials (substring string start (1+ start)))
+ (1+ start))))
(defun mime-analyze-token (string start)
(if (and (string-match mime-token-regexp string start)
(= (match-beginning 0) start))
(let ((end (match-end 0)))
(cons (cons 'mime-token (substring string start end))
- ;;(substring string end)
- end)
- )))
+ end))))
+
+(defun mime-lexical-analyze (string)
+ "Analyze STRING as lexical tokens of MIME."
+ (let ((ret (std11-lexical-analyze string mime-lexical-analyzer))
+ prev tail)
+ ;; skip leading linear-white-space.
+ (while (memq (car (car ret)) '(spaces comment))
+ (setq ret (cdr ret)))
+ (setq prev ret
+ tail (cdr ret))
+ ;; remove linear-white-space.
+ (while tail
+ (if (memq (car (car tail)) '(spaces comment))
+ (progn
+ (setcdr prev (cdr tail))
+ (setq tail (cdr tail)))
+ (setq prev (cdr prev)
+ tail (cdr tail))))
+ ret))
;;; @ field parser
;;;
-(defconst mime/content-parameter-value-regexp
- (concat "\\("
- std11-quoted-string-regexp
- "\\|[^; \t\n]*\\)"))
-
-(defconst mime::parameter-regexp
- (concat "^[ \t]*\;[ \t]*\\(" mime-token-regexp "\\)"
- "[ \t]*=[ \t]*\\(" mime/content-parameter-value-regexp "\\)"))
-
-(defun mime-parse-parameter (str)
- (if (string-match mime::parameter-regexp str)
- (let ((e (match-end 2)))
- (cons
- (cons (downcase (substring str (match-beginning 1) (match-end 1)))
- (std11-strip-quoted-string
- (substring str (match-beginning 2) e))
- )
- (substring str e)
- ))))
-
-
-;;; @ Content-Type
+(defun mime-decode-parameter-value (text charset language)
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert text)
+ (goto-char (point-min))
+ (while (re-search-forward "%[0-9A-Fa-f][0-9A-Fa-f]" nil t)
+ (insert (prog1 (string-to-int
+ (buffer-substring (point)(- (point) 2))
+ 16)
+ (delete-region (point)(- (point) 3)))))
+ (setq text (buffer-string))
+ (when charset
+ ;; I believe that `decode-mime-charset-string' of mcs-e20.el should
+ ;; be independent of the value of `enable-multibyte-characters'.
+ (erase-buffer)
+ (set-buffer-multibyte t)
+ (setq text (decode-mime-charset-string text charset)))
+ (when language
+ (put-text-property 0 (length text) 'mime-language language text))
+ text))
+
+(defun mime-decode-parameter-encode-segment (segment)
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert segment)
+ (goto-char (point-min))
+ (while (progn
+ (when (looking-at (eval-when-compile
+ (concat mime-attribute-char-regexp "+")))
+ (goto-char (match-end 0)))
+ (not (eobp)))
+ (insert (prog1 (format "%%%02X" (char-int (char-after)))
+ (delete-region (point)(1+ (point))))))
+ (buffer-string)))
+
+(defun mime-decode-parameters (params)
+ "Decode PARAMS as a property list of MIME parameter values.
+Return value is an association list of MIME parameter values.
+If parameter continuation is used, segments of values are concatenated.
+If parameters contain charset information, values are decoded.
+If parameters contain language information, it is set to `mime-language'
+property of the decoded-value."
+ ;; (unless (zerop (% (length params) 2)) ...)
+ (let ((len (/ (length params) 2))
+ dest eparams)
+ (while params
+ (if (and (string-match (eval-when-compile
+ (concat "^\\(" mime-attribute-char-regexp "+\\)"
+ "\\(\\*[0-9]+\\)?" ; continuation
+ "\\(\\*\\)?$")) ; charset/language
+ (car params))
+ (> (match-end 0) (match-end 1)))
+ ;; parameter value extensions are used.
+ (let* ((attribute (downcase
+ (substring (car params) 0 (match-end 1))))
+ (section (if (match-beginning 2)
+ (string-to-int
+ (substring (car params)
+ (1+ (match-beginning 2))
+ (match-end 2)))
+ 0))
+ ;; EPARAM := (ATTRIBUTE VALUES CHARSET LANGUAGE)
+ ;; VALUES := [1*VALUE] ; vector of LEN elements.
+ (eparam (assoc attribute eparams))
+ (value (progn
+ (setq params (cdr params))
+ (car params))))
+ (if eparam
+ (setq eparam (cdr eparam))
+ (setq eparam (list (make-vector len nil) nil nil)
+ eparams (cons (cons attribute eparam) eparams)))
+ ;; if parameter-name ends with "*", it is an extended-parameter.
+ (if (match-beginning 3)
+ (if (zerop section)
+ ;; extended-initial-parameter.
+ (if (string-match (eval-when-compile
+ (concat
+ "^\\(" mime-charset-regexp "\\)?"
+ "'\\(" mime-language-regexp "\\)?"
+ "'\\(\\(" mime-attribute-char-regexp
+ "\\|%[0-9A-Fa-f][0-9A-Fa-f]\\)+\\)$"))
+ value)
+ (progn
+ ;; text
+ (aset (car eparam) 0
+ (substring value (match-beginning 3)))
+ (setq eparam (cdr eparam))
+ ;; charset
+ (when (match-beginning 1)
+ (setcar eparam
+ (downcase
+ (substring value 0 (match-end 1)))))
+ (setq eparam (cdr eparam))
+ ;; language
+ (when (match-beginning 2)
+ (setcar eparam
+ (intern
+ (downcase
+ (substring value
+ (match-beginning 2)
+ (match-end 2)))))))
+ ;; invalid parameter-value.
+ (aset (car eparam) 0
+ (mime-decode-parameter-encode-segment value)))
+ ;; extended-other-parameter.
+ (if (string-match (eval-when-compile
+ (concat
+ "^\\(\\(" mime-attribute-char-regexp
+ "\\|%[0-9A-Fa-f][0-9A-Fa-f]\\)+\\)$"))
+ value)
+ (aset (car eparam) section value)
+ ;; invalid parameter-value.
+ (aset (car eparam) section
+ (mime-decode-parameter-encode-segment value))))
+ ;; regular-parameter. parameter continuation only.
+ (aset (car eparam) section
+ (mime-decode-parameter-encode-segment value))))
+ ;; parameter value extensions are not used,
+ ;; or invalid attribute-name (in RFC2231, although valid in RFC2045).
+ (setq dest (cons (cons (downcase (car params))
+;;; ;; decode (invalid!) encoded-words.
+;;; (eword-decode-string
+;;; (decode-mime-charset-string
+;;; (car (cdr params))
+;;; default-mime-charset)
+;;; 'must-unfold)
+ (car (cdr params)))
+ dest)
+ params (cdr params)))
+ (setq params (cdr params)))
+ ;; concat and decode parameters.
+ (while eparams
+ (setq dest (cons (cons (car (car eparams)) ; attribute
+ (mime-decode-parameter-value
+ (mapconcat (function identity)
+ (nth 1 (car eparams)) ; values
+ "")
+ (nth 2 (car eparams)) ; charset
+ (nth 3 (car eparams)) ; language
+ ))
+ dest)
+ eparams (cdr eparams)))
+ dest))
+
+;;; for compatibility with flim-1_13-rfc2231 API.
+(defalias 'mime-parse-parameters-from-list 'mime-decode-parameters)
+(make-obsolete 'mime-parse-parameters-from-list 'mime-decode-parameters)
+
+(defun mime-parse-parameters (tokens)
+ "Parse TOKENS as MIME parameter values.
+Return a property list, which is a list of the form
+\(PARAMETER-NAME1 VALUE1 PARAMETER-NAME2 VALUE2...)."
+ (let (params attribute)
+ (while (and tokens
+ (eq (car (car tokens)) 'tspecials)
+ (string= (cdr (car tokens)) ";")
+ (setq tokens (cdr tokens))
+ (eq (car (car tokens)) 'mime-token)
+ (progn
+ (setq attribute (cdr (car tokens)))
+ (setq tokens (cdr tokens)))
+ (eq (car (car tokens)) 'tspecials)
+ (string= (cdr (car tokens)) "=")
+ (setq tokens (cdr tokens))
+ (memq (car (car tokens)) '(mime-token quoted-string)))
+ (setq params (cons (if (eq (car (car tokens)) 'quoted-string)
+ (std11-strip-quoted-pair (cdr (car tokens)))
+ (cdr (car tokens)))
+ (cons attribute params))
+ tokens (cdr tokens)))
+ (nreverse params)))
+
+
+;;; @@ Content-Type
;;;
;;;###autoload
-(defun mime-parse-Content-Type (string)
- "Parse STRING as field-body of Content-Type field.
-Return value is
- (PRIMARY-TYPE SUBTYPE (NAME1 . VALUE1)(NAME2 . VALUE2) ...)
-or nil. PRIMARY-TYPE and SUBTYPE are symbol and NAME_n and VALUE_n
-are string."
- (setq string (std11-unfold-string string))
- (if (string-match `,(concat "^\\(" mime-token-regexp
- "\\)/\\(" mime-token-regexp "\\)") string)
- (let* ((type (downcase
- (substring string (match-beginning 1) (match-end 1))))
- (subtype (downcase
- (substring string (match-beginning 2) (match-end 2))))
- ret dest)
- (setq string (substring string (match-end 0)))
- (while (setq ret (mime-parse-parameter string))
- (setq dest (cons (car ret) dest)
- string (cdr ret))
- )
- (make-mime-content-type (intern type)(intern subtype)
- (nreverse dest))
- )))
+(defun mime-parse-Content-Type (field-body)
+ "Parse FIELD-BODY as a Content-Type field.
+FIELD-BODY is a string.
+Return value is a mime-content-type object.
+If FIELD-BODY is not a valid Content-Type field, return nil."
+ (let ((tokens (mime-lexical-analyze field-body)))
+ (when (eq (car (car tokens)) 'mime-token)
+ (let ((primary-type (cdr (car tokens))))
+ (setq tokens (cdr tokens))
+ (when (and (eq (car (car tokens)) 'tspecials)
+ (string= (cdr (car tokens)) "/")
+ (setq tokens (cdr tokens))
+ (eq (car (car tokens)) 'mime-token))
+ (make-mime-content-type
+ (intern (downcase primary-type))
+ (intern (downcase (cdr (car tokens))))
+ (mime-decode-parameters
+ (mime-parse-parameters (cdr tokens)))))))))
;;;###autoload
(defun mime-read-Content-Type ()
- "Read field-body of Content-Type field from current-buffer,
-and return parsed it. Format of return value is as same as
-`mime-parse-Content-Type'."
- (let ((str (std11-field-body "Content-Type")))
- (if str
- (mime-parse-Content-Type str)
+ "Parse field-body of Content-Type field of current-buffer.
+Return value is a mime-content-type object.
+If Content-Type field is not found, return nil."
+ (let ((field-body (std11-field-body "Content-Type")))
+ (if field-body
+ (mime-parse-Content-Type field-body)
)))
-;;; @ Content-Disposition
+;;; @@ Content-Disposition
;;;
-(eval-and-compile
- (defconst mime-disposition-type-regexp mime-token-regexp)
- )
-
;;;###autoload
-(defun mime-parse-Content-Disposition (string)
- "Parse STRING as field-body of Content-Disposition field."
- (setq string (std11-unfold-string string))
- (if (string-match (eval-when-compile
- (concat "^" mime-disposition-type-regexp)) string)
- (let* ((e (match-end 0))
- (type (downcase (substring string 0 e)))
- ret dest)
- (setq string (substring string e))
- (while (setq ret (mime-parse-parameter string))
- (setq dest (cons (car ret) dest)
- string (cdr ret))
- )
- (cons (cons 'type (intern type))
- (nreverse dest))
- )))
+(defun mime-parse-Content-Disposition (field-body)
+ "Parse FIELD-BODY as a Content-Disposition field.
+FIELD-BODY is a string.
+Return value is a mime-content-disposition object.
+If FIELD-BODY is not a valid Content-Disposition field, return nil."
+ (let ((tokens (mime-lexical-analyze field-body)))
+ (when (eq (car (car tokens)) 'mime-token)
+ (make-mime-content-disposition
+ (intern (downcase (cdr (car tokens))))
+ (mime-decode-parameters
+ (mime-parse-parameters (cdr tokens)))))))
;;;###autoload
(defun mime-read-Content-Disposition ()
- "Read field-body of Content-Disposition field from current-buffer,
-and return parsed it."
- (let ((str (std11-field-body "Content-Disposition")))
- (if str
- (mime-parse-Content-Disposition str)
+ "Parse field-body of Content-Disposition field of current-buffer.
+Return value is a mime-content-disposition object.
+If Content-Disposition field is not found, return nil."
+ (let ((field-body (std11-field-body "Content-Disposition")))
+ (if field-body
+ (mime-parse-Content-Disposition field-body)
)))
-;;; @ Content-Transfer-Encoding
+;;; @@ Content-Transfer-Encoding
;;;
;;;###autoload
-(defun mime-parse-Content-Transfer-Encoding (string)
- "Parse STRING as field-body of Content-Transfer-Encoding field."
- (let ((tokens (std11-lexical-analyze string mime-lexical-analyzer))
- token)
- (while (and tokens
- (setq token (car tokens))
- (std11-ignored-token-p token))
- (setq tokens (cdr tokens)))
- (if token
- (if (eq (car token) 'mime-token)
- (downcase (cdr token))
- ))))
+(defun mime-parse-Content-Transfer-Encoding (field-body)
+ "Parse FIELD-BODY as a Content-Transfer-Encoding field.
+FIELD-BODY is a string.
+Return value is a string.
+If FIELD-BODY is not a valid Content-Transfer-Encoding field, return nil."
+ (let ((tokens (mime-lexical-analyze field-body)))
+ (when (eq (car (car tokens)) 'mime-token)
+ (downcase (cdr (car tokens))))))
;;;###autoload
-(defun mime-read-Content-Transfer-Encoding (&optional default-encoding)
- "Read field-body of Content-Transfer-Encoding field from
-current-buffer, and return it.
-If is is not found, return DEFAULT-ENCODING."
- (let ((str (std11-field-body "Content-Transfer-Encoding")))
- (if str
- (mime-parse-Content-Transfer-Encoding str)
- default-encoding)))
+(defun mime-read-Content-Transfer-Encoding ()
+ "Parse field-body of Content-Transfer-Encoding field of current-buffer.
+Return value is a string.
+If Content-Transfer-Encoding field is not found, return nil."
+ (let ((field-body (std11-field-body "Content-Transfer-Encoding")))
+ (if field-body
+ (mime-parse-Content-Transfer-Encoding field-body)
+ )))
-;;; @ Content-Id / Message-Id
+;;; @@ Content-ID / Message-ID
;;;
;;;###autoload
(defun mime-parse-msg-id (tokens)
- "Parse TOKENS as msg-id of Content-Id or Message-Id field."
+ "Parse TOKENS as msg-id of Content-ID or Message-ID field."
(car (std11-parse-msg-id tokens)))
;;;###autoload
(defun mime-uri-parse-cid (string)
"Parse STRING as cid URI."
- (inline
- (mime-parse-msg-id (cons '(specials . "<")
- (nconc
- (cdr (cdr (std11-lexical-analyze string)))
- '((specials . ">")))))))
+ (mime-parse-msg-id (cons '(specials . "<")
+ (nconc
+ (cdr (cdr (std11-lexical-analyze string)))
+ '((specials . ">"))))))
;;; @ message parser
(prog1
field-name
(setq field-name (symbol-name field-name)))
- (intern (capitalize (capitalize field-name))))))
+ (intern (capitalize field-name)))))
(cond ((eq sym 'Content-Type)
(mime-entity-content-type entity)
)
(let ((ret (std11-fetch-field field-name)))
(when ret
(or (symbolp field-name)
- (setq field-name
- (intern (capitalize (capitalize field-name)))))
+ (setq field-name (intern (capitalize field-name))))
(mime-entity-set-original-header-internal
entity
(put-alist field-name ret
(let ((ret (std11-fetch-field field-name)))
(when ret
(or (symbolp field-name)
- (setq field-name
- (intern (capitalize (capitalize field-name)))))
+ (setq field-name (intern (capitalize field-name))))
(mime-entity-set-original-header-internal
entity
(put-alist field-name ret
(luna-define-method mime-entity-fetch-field ((entity mime-entity)
field-name)
(or (symbolp field-name)
- (setq field-name (intern (capitalize (capitalize field-name)))))
+ (setq field-name (intern (capitalize field-name))))
(cdr (assq field-name
(mime-entity-original-header-internal entity))))