Initial commit

This commit is contained in:
2026-03-26 01:01:07 -07:00
commit fa8503a6d7

199
rtf-mode-el.el Normal file
View File

@@ -0,0 +1,199 @@
;;; rtf-mode.el --- Emacs major mode for viewing/editing raw RTF source
;; Copyright (C) 2006 Sean M. Burke (but released under GPL)
;; Time-stamp: <2008-01-05 19:12:08 AKST sburke@cpan.org>
;; Author: Sean M. Burke <sburke@cpan.org>
;; Maintainer: Sean M. Burke <sburke@cpan.org>
;; Keywords: wp, rtf, languages
;; Version: 1.1
;; X-URL: http://interglacial.com/rtf/emacs/
;;; Commentary:
;; Major mode for viewing/editing RTF source. I wrote this mostly for
;; the sake of syntax-highlighting, and for the {}-matching. It offers
;; little else in the way of conveniences (like key shortcuts.)
;; (If are interested in such conveniences, email me.)
;;
;; I maintain a homepage for this mode, at http://interglacial.com/rtf/emacs/
;;
;; Note that this mode doesn't (yet?) specially handle Help-RTF constructs.
;;
;; Also note that at time of writing (Oct 2006), Xemacs doesn't seem to
;; support some of the functions that this mode requires. Sorry, Xemacs users!
;;
;; As with many programming modes, the default wrapping mechinisms
;; (whether via auto-fill-mode, or via fill-paragraph etc commands) do
;; not behave at all well. So I've disabled wrapping as best I can,
;; so you don't end up corrupting documents. Moreover, implementing
;; wrapping in RTF seems fairly difficult because of how spaces are
;; sometimes a significant token in RTF whereas newlines are not.
;;
;; For more on RTF, see http://interglacial.com/rtf/ and also be a chum and
;; go get this little book I wrote: http://www.amazon.com/dp/0596004753
;;
;;; Boilerplate
;; This file is not part of GNU Emacs.
;;
;; This 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, version 2.
;;
;; This 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
;; GNU Emacs; see the file COPYING. If not, write to the Free Software
;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
;;; Change log:
;; 2006-10-23 version 1.1
;; Public release. Just a minor internal optimization.
;; (We new use regexp-opt to build our regexp from rtf-loudcmds.)
;; 2006-10-22 version 1.0
;; Public release.
;;; Code:
(require 'generic)
(defmacro rtf-mkface (name basis desc)
`(defface
,name
(list (list t :inherit ,basis))
,(concat "Face used to highlight rtf-mode " desc ".")
:group 'rtf))
(rtf-mkface rtf-brace-face 'font-lock-string-face "braces")
(rtf-mkface rtf-charescape-face 'font-lock-function-name-face "numeric escapes")
(rtf-mkface rtf-loud-cword-face 'font-lock-warning-face "important commands")
(rtf-mkface rtf-cword-face 'font-lock-keyword-face "commands")
(rtf-mkface rtf-cword-param-face 'font-lock-builtin-face "command-parameters")
(rtf-mkface rtf-cword-endingspace-face 'font-lock-comment-face "command-ending spaces")
(rtf-mkface rtf-star-face 'font-lock-doc-face "\\* commands")
(rtf-mkface rtf-escnewline-face 'font-lock-constant-face "\\ [Newline] sequences")
(rtf-mkface rtf-esctab-face 'font-lock-warning-face "\\ [Tab] sequences")
(rtf-mkface rtf-escother-face 'font-lock-type-face "\\ [other] sequences")
(rtf-mkface rtf-trailing-whitespace-face 'highlight "trailing space")
(defvar rtf-loudcmds
'(
rtf1 page pard par line sectd sect footnote
cell row trowd
fonttbl info colortbl stylesheet
)
"A few structurally super-important (and parameterless) RTF commands.")
;======================================================================
(defun rtf-make-loudcmd-re (cmdlist)
(concat "\\(\\\\\\)\\("
(regexp-opt (mapcar 'symbol-name cmdlist))
"\\)\\b\\( ?\\)"))
(define-generic-mode 'rtf-mode
nil ; the comment syntax list -- nil because RTF has no comments!
nil ; keyword-list -- nil because we do everything below
(list ; the font lock list...
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; * Control words, \foo123, \foo-123, \foo
; A few structurally super-important (and parameterless) control words:
(list (rtf-make-loudcmd-re rtf-loudcmds)
'(1 'rtf-cword-face)
'(2 'rtf-loud-cword-face)
'(3 'rtf-cword-endingspace-face)
)
'("\\(\\\\u-?[0-9]+ ?\\)" ; a unicodey escape
1 'rtf-charescape-face)
'("\\(\\\\[a-zA-Z]+\\)\\(-?[0-9]+\\)\\( ?\\)" ; with a num-param
(1 'rtf-cword-face)
(2 'rtf-cword-param-face)
(3 'rtf-cword-endingspace-face)
)
'("\\(\\\\[a-zA-Z]+\\)\\( ?\\)" ; no param
(1 'rtf-cword-face)
(2 'rtf-cword-endingspace-face)
)
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; * Control symbols
; ~ the fancy \* thing...
'("\\(\\\\\\*\\)" 1 'rtf-star-face)
; ~ \'xx escape
'("\\(\\\\'[a-fA-F0-9][a-fA-F0-9]\\)" 1 'rtf-charescape-face)
; ~ \[NEWLINE] which means \par
'("\\(\\\\\012\\)" 1 'rtf-escnewline-face)
; ~ \[TAB] which means \tab
'("\\(\\\\\011\\)" 1 'rtf-esctab-face)
; ~ \_ where _ is anything else, but probably one of ' - : \ _ { | } ~
'("\\(\\\\[^a-zA-Z'\011\012]\\)" 1 'rtf-escother-face)
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; * '{' and '}' (unescaped, that is)
'("\\({\\|}\\)" 1 'rtf-brace-face)
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; And, incidentally:
; ~ trailing whitespace -- not an error, but which is /significant/!
'("\\([ \011]+\\)$" 1 'rtf-trailing-whitespace-face)
;; You COULD highlight /all/ significant spaces in the document with this:
;("\\([ \011]+\\)" 1 'rtf-trailing-whitespace-face)
;; but that would probably be more confusing than useful.
)
(list ".rtf\\'" ) ; auto-mode list -- our extensions
(list 'rtf-mode-setup-function)
"A major mode for editing/viewing RTF source.")
; TODO: support for blobs? Seems tricky.
;======================================================================
(defun rtf-mode-stultify-character (str)
"Mark this one-character string as nonmagical in the syntax table."
(modify-syntax-entry (string-to-char str) "."))
(defun rtf-mode-fill-paragraph (arg)
(message "rtf-mode doesn't currently support filling paragraphs")
; This is just to inhibit the actual normal filler, because
; that's usually a really bad idea for RTF. (I will have
; to write a replacement for it eventually, but it'll be
; quite tricky.)
t)
(defun rtf-mode-setup-function ()
(dolist (s (split-string "\"()[]\\" ""))
(rtf-mode-stultify-character s))
(set (make-local-variable 'require-final-newline) nil)
; Many RTF files end on a "}" without a newline after it
(set (make-local-variable 'fill-paragraph-function) 'rtf-mode-fill-paragraph)
;(set (make-local-variable 'fill-prefix) " ")
; ^^ That'd be good for entering text content, but it inserts
; significant spaces when you're entering commands!
t
)
(provide 'rtf-mode)
;;; rtf-mode.el ends here