1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
;;; intercal.el -- mode for editing INTERCAL code
;; This mode was written by Eric S. Raymond <esr@snark.thyrsus.com>
;; for the C-INTERCAL distribution, and is copyrighted by him 1992. Free
;; redistribution encouraged. Someday, maybe, this will be made part of GNU.
;; But probably not unless they take many mind-eroding drugs first.
;; This mode provides abbrevs for C-INTERCAL's statements, including COME FROM.
;; These abbrevs are context-sensitive and will generate either verb or gerund
;; form as appropriate. The keys RET, ( and * are also bound in useful ways.
;; The intercal-politesse-level adjustment purports to assist the hapless
;; INTERCAL programmer in meeting INTERCAL's Miss Manners requirement. In
;; INTERCAL-72 and C-INTERCAL releases after 0.7, no fewer than 1/5 and no
;; more than 1/3 of the program statements must contain a PLEASE to gratify
;; the iron whim of the INTERCAL compiler; this mode assists by randomly
;; expanding some fraction of the "do" abbrevs typed to PLEASE DO.
;; The intercal-politesse-level constant is the denominator of this fraction.
;; $Id: intercal.el,v 1.5 1996/11/14 04:02:00 esr Exp $
(defconst intercal-politesse-level 4
"Fraction of DOs that are automagically expanded to PLEASE DO.")
(defvar intercal-mode-map nil
"Keymap for INTERCAL mode.")
(if intercal-mode-map
nil
(setq intercal-mode-map (make-sparse-keymap))
(define-key intercal-mode-map "\t" 'tab-to-tab-stop)
(define-key intercal-mode-map "\r" 'intercal-return)
(define-key intercal-mode-map "(" 'intercal-paren)
(define-key intercal-mode-map "*" 'intercal-splat)
(define-key intercal-mode-map "\177" 'backward-delete-char-untabify)
)
(defvar intercal-mode-syntax-table nil
"Syntax table in use in Intercal-mode buffers.")
(if intercal-mode-syntax-table
nil
(let ((table (make-syntax-table)))
(modify-syntax-entry ?\\ "\\" table)
(modify-syntax-entry ?+ "." table)
(modify-syntax-entry ?- "." table)
(modify-syntax-entry ?= "." table)
(modify-syntax-entry ?% "." table)
(modify-syntax-entry ?< "." table)
(modify-syntax-entry ?> "." table)
(modify-syntax-entry ?& "." table)
(modify-syntax-entry ?| "." table)
(modify-syntax-entry ?\' "\"" table)
(setq intercal-mode-syntax-table table)))
(defvar intercal-mode-abbrev-table nil
"*Abbrev table in use in Intercal-mode buffers.")
(if intercal-mode-abbrev-table
nil
(define-abbrev-table 'intercal-mode-abbrev-table ())
(define-abbrev intercal-mode-abbrev-table "pl" "PLEASE" nil)
(define-abbrev intercal-mode-abbrev-table "ne" "" 'intercal-ne-abbrev)
(define-abbrev intercal-mode-abbrev-table "fo" "" 'intercal-fo-abbrev)
(define-abbrev intercal-mode-abbrev-table "res" "" 'intercal-res-abbrev)
(define-abbrev intercal-mode-abbrev-table "st" "" 'intercal-st-abbrev)
(define-abbrev intercal-mode-abbrev-table "ret" "" 'intercal-ret-abbrev)
(define-abbrev intercal-mode-abbrev-table "ig" "" 'intercal-ig-abbrev)
(define-abbrev intercal-mode-abbrev-table "rem" "" 'intercal-rem-abbrev)
(define-abbrev intercal-mode-abbrev-table "ab" "" 'intercal-ab-abbrev)
(define-abbrev intercal-mode-abbrev-table "rei" "" 'intercal-rei-abbrev)
(define-abbrev intercal-mode-abbrev-table "gi" "" 'intercal-gi-abbrev)
(define-abbrev intercal-mode-abbrev-table "rea" "" 'intercal-rea-abbrev)
(define-abbrev intercal-mode-abbrev-table "wr" "" 'intercal-wr-abbrev)
(define-abbrev intercal-mode-abbrev-table "co" "" 'intercal-co-abbrev)
(define-abbrev intercal-mode-abbrev-table "do" "" 'intercal-do-abbrev)
)
(defun use-gerund ()
(save-excursion
(beginning-of-line)
(or (looking-at ".*ABSTAIN") (looking-at ".*REINSTATE"))))
(defmacro make-intercal-abbrev (sym gerund verb)
(list 'defun sym '() (list 'insert (list 'if '(use-gerund) gerund verb))))
(make-intercal-abbrev intercal-ne-abbrev "NEXTING" "NEXT")
(make-intercal-abbrev intercal-fo-abbrev "FORGETTING" "FORGET")
(make-intercal-abbrev intercal-res-abbrev "RESUMING" "RESUME")
(make-intercal-abbrev intercal-st-abbrev "STASHING" "STASH")
(make-intercal-abbrev intercal-ret-abbrev "RETRIEVING" "RETRIEVE")
(make-intercal-abbrev intercal-ig-abbrev "IGNORING" "IGNORE")
(make-intercal-abbrev intercal-rem-abbrev "REMEMBERING" "REMEMBER")
(make-intercal-abbrev intercal-ab-abbrev "ABSTAINING" "ABSTAIN FROM")
(make-intercal-abbrev intercal-rei-abbrev "REINSTATING" "REINSTATE")
(make-intercal-abbrev intercal-gi-abbrev "GIVING UP" "GIVE UP")
(make-intercal-abbrev intercal-rea-abbrev "READING IN" "READ IN")
(make-intercal-abbrev intercal-wr-abbrev "WRITING OUT" "WRITE OUT")
(make-intercal-abbrev intercal-co-abbrev "COMING FROM" "COME FROM")
(defun intercal-do-abbrev ()
"Emit a DO (usually). Occasionally, emit PLEASE DO."
(insert
(if (zerop (% (random) intercal-politesse-level))
"PLEASE DO"
"DO")
))
(defun intercal-return ()
"Insert LFD + tab, to bring us back to code-indent level."
(interactive)
(if (eolp) (delete-horizontal-space))
(insert "\n")
(tab-to-tab-stop)
)
(defun intercal-paren ()
"Generate an INTERCAL label."
(interactive)
(if (and (bolp) (looking-at "[ \t]\\|$"))
(insert (format "(%d)"
(save-restriction
(widen)
(save-excursion
(beginning-of-line)
(1+ (count-lines 1 (point))))))
"\t")
(insert "(")))
(defun intercal-splat ()
"Begin an INTERCAL comment."
(interactive)
(insert "*")
(forward-char -1)
(delete-horizontal-space)
(forward-char 1)
(insert " ")
)
(defun intercal-mode ()
"A major editing mode for the language Intercal.
It activates the following abbrevs (each one appropriately modified to a
gerund if it occurs on a line with ABSTAIN or REINSTATE).
ab ABSTAIN co COME FROM fo FORGET
gi GIVE UP ig IGNORE ne NEXT
rea READ IN rei REINSTATE rem REMEMBER
res RESUME ret RETRIEVE st STASH
wr WRITE OUT pl PLEASE
Carriage return takes you to the first tab stop (code indent level).
Certain other single keys are bound to things which may or may not be useful.
You may consider discovering these one of the pleasures awaiting you in your
discovery of INTERCAL's unique ambience.
Turning on Intercal mode calls the value of the variable intercal-mode-hook
with no args, if that value is non-nil."
(interactive)
(kill-all-local-variables)
(use-local-map intercal-mode-map)
(setq major-mode 'intercal-mode)
(setq mode-name "Intercal")
(setq local-abbrev-table intercal-mode-abbrev-table)
(set-syntax-table intercal-mode-syntax-table)
(make-local-variable 'comment-start)
(setq comment-start "* ")
(make-local-variable 'comment-end)
(setq comment-end "")
(make-local-variable 'comment-column)
(setq comment-column 32)
(make-local-variable 'require-final-newline)
(setq require-final-newline t)
(setq abbrev-mode t)
(setq abbrev-all-caps t)
(run-hooks 'intercal-mode-hook))
(provide 'intercal-mode)
;;; intercal.el ends here
|