Mercurial > hg > xemacs
changeset 0:107d592c5f4a
DICE versions, used by pers/common, recursive, I think/hope
author | Henry S. Thompson <ht@inf.ed.ac.uk> |
---|---|
date | Mon, 08 Feb 2021 11:44:37 +0000 |
parents | |
children | 6c73c7af9cdb |
files | local/ht-rooms-epoch.config lucid/lemacs-compat.el lucid/my-news.el lucid/rooms.el shared/alarm.el shared/compress.el shared/device-type-hacking.el shared/diary.el shared/gnus-init.el shared/hackbs.el shared/hist.el shared/ht-rooms.config shared/mail-extras.el shared/mdn-extras.el shared/motion.el shared/motion4.el shared/prompt-for-word.elc shared/refInsert.el shared/repl-comment.el shared/sgml-font-lock-keywords.el shared/xml-hack.el |
diffstat | 21 files changed, 4124 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/local/ht-rooms-epoch.config Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,34 @@ +(defvar no-news nil "inhibit news startup") + +(define-rooms '(("elisp" ("*scratch*" nil 0 0 80 23) + ((" a") (emacs-lisp-mode) 0 23 80 47)) + ("text" ((" b") nil 0 0 80 47)) + ("diary" ("diary.babyl" + (progn (rmail-input "~/mail/diary.babyl") + (setq ht-last-file + (expand-file-name + "~/mail/history/diary.msg"))) + 0 0 80 12) + ("diary.babyl-summary" (update-default-diary t) 0 11 80 23)) + ("news" ("*Newsgroup*" (if (not no-news)(gnus)) 0 0 80 47)) + ("mail" ("RMAIL" (rmail) 0 0 80 47)))) + +(sit-for 1) + +(defun make-lisp-room () + "create and go to a room for lisp work" + (interactive) + (establish-room '("lisp" + ("*lisp*" (run-lisp) 0 0 80 23) + ((" ") (lisp-mode) 0 23 80 47)) + t)) + +(defun make-prolog-room () + "create and go to a room for prolog work" + (interactive) + (establish-room '("prolog" + ("*prolog*" (site-caseq (edin (run-prolog)) + (parc (run-sicstus))) + 0 0 80 23) + ((" ") (prolog-mode) 0 23 80 47)) + t))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lucid/lemacs-compat.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,42 @@ +;; Last edited: Thu Sep 24 14:57:39 1992 +;; backwards compatibility + +(setq mail-aliases t) + +;; hack not really quite right +(defun current-msec-time () (* 1000 (car (cdr (current-time))))) +(defun last-event-time () (event-timestamp last-input-event)) + +;; inhibit-local-variables-regexps --> inhibit-first-line-modes-regexps +;; needs to be fixed for edb + + +(defun ht-rmail-cease-edit () + "check if diary edit, move if so" + (interactive) + (rmail-cease-edit) + (if editing-diary-entry + (progn (setq editing-diary-entry nil) + (ht-output-to-Calendar) + (rmail-output-to-rmail-file ht-diary-file-name 1) + (rmail-delete-forward)))) + +(defun fake-face-width (face) + ;; Hack since can't seem to do this directly + (cdr (assoc 'QUAD_WIDTH (x-font-properties (face-font face))))) + +(defun fake-face-height (face) + ;; Hack since can't seem to do this directly + (let ((prop (x-font-properties (face-font face)))) + ;; highly speculative . . . + (+ (cdr (assoc 'CAP_HEIGHT prop)) + (cdr (assoc 'X_HEIGHT prop))))) + +(if (not (fboundp 'face-width)) + (fset 'face-width (symbol-function 'fake-face-width))) + +(if (not (fboundp 'face-height)) + (fset 'face-height (symbol-function 'fake-face-height))) + +(provide 'lemacs-compat) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lucid/my-news.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,742 @@ +(load "gnus" nil t) +;(require 'spam) +(require 'cl) +;(spam-initialize) +(setq + gnus-select-method '(nntp "usenet.inf.ed.ac.uk") + gnus-post-method '(nntp "usenet.inf.ed.ac.uk") + gnus-nntp-server nil ; override local default + ) + +(setq gnus-use-scoring nil ; not used yet + gnus-summary-gather-subject-limit nil + gnus-thread-sort-functions + '(gnus-thread-sort-by-number gnus-thread-sort-by-simpl-subject) + gnus-summary-line-format "%U%R%5N%I%(%[%4L: %-12,12A%]%) %s\n" + gnus-summary-make-false-root 'none + gnus-mime-display-multipart-related-as-mixed t + gnus-simplify-subject-regexp "^\\(re[:;.]\\| \\|fwd:\\)*") + +(defsubst gnus-trim-simplify-subject (text) + (if (string-match gnus-simplify-subject-regexp text) + (substring text (match-end 0)) + text)) + +(defun gnus-thread-sort-by-simpl-subject (h1 h2) + "sort by slightly simplified subject" +; (message (format "%s:%s %s:%s" (mail-header-number (gnus-thread-header h1))(mail-header-subject (gnus-thread-header h1))(mail-header-number (gnus-thread-header h2))(mail-header-subject (gnus-thread-header h2)))) + (let ((case-fold-search t)) + (let ((result + (string-lessp + (downcase (gnus-trim-simplify-subject (mail-header-subject + (gnus-thread-header h1)))) + (downcase (gnus-trim-simplify-subject (mail-header-subject + (gnus-thread-header h2))))))) +; (message (format " %s\n" result)) + result))) + + +;; Database stuff + + +(defun open-white () + (setq whitelist-db (open-database "/disk/scratch/mail/white" 'berkeley-db))) + +(defun save-white () + (close-database whitelist-db) + (open-white)) + +(defun open-ad () + (setq adlist-db (open-database "/disk/scratch/mail/ad" 'berkeley-db))) + +(defun save-ad () + (close-database adlist-db) + (open-ad)) + +(defun open-quaker () + (setq quaker-db (open-database "/disk/scratch/mail/quaker" 'berkeley-db))) +(defun save-quaker () + (close-database quaker-db) + (open-quaker)) + +(defvar database-names '(whitelist-db adlist-db quaker-db) "sic") + +(defun db-status (&optional name) + "Check on the whereabouts of a name" + (interactive) + (let ((addr + (or name + (progn + (gnus-summary-goto-article (gnus-summary-article-number)) + (get-canonical-from-addr (get-current-from-components))))) + res) + (dolist (dbn database-names) + (if (get-database addr (eval dbn)) + (setq res (cons dbn res)))) + (if name + res + (message "%s" res)))) + +(defun add-white (&optional addToBBDB) + (interactive "P") + (gnus-summary-goto-article (gnus-summary-article-number)) + (let* ((components (get-current-from-components)) + (addr (get-canonical-from-addr components))) + (if (new-white addr) + (save-white)) + (if addToBBDB + (let ((bbdb-no-duplicates-p t)) + (bbdb-create-internal (car components) nil (cadr components) + nil nil nil))))) + +(defun add-ad () + (interactive) + (gnus-summary-goto-article (gnus-summary-article-number)) + (let ((addr (get-current-from-addr))) + (if (or (not (get-database addr whitelist-db)) + (yes-or-no-p "Already white, really convert to ad?")) + (if (new-ad addr) + (save-ad))))) + +(defun add-quaker() + (interactive) + (let ((addr (get-addr-before-point))) + (when (new-quaker addr) + (save-quaker)) + (quaker-sig-maybe))) + +(defun quaker-sig-if-to-quaker () + (let ((message-options)) + (save-excursion (message-options-set-recipient)) + (let* ((recipStr (message-options-get 'message-recipients)) + (recips (split-string (downcase recipStr) + ",[ \f\t\n\r\v]+" t))) + (while (and recips + (not (quaker-sig-if-quaker-1 (car recips)))) + (setq recips (cdr recips)))))) + +(defun quaker-sig-if-quaker () + (quaker-sig-if-quaker-1 (get-addr-before-point))) + +(defun quaker-sig-if-quaker-1 (addr) + (if (get-database addr quaker-db) + (progn (quaker-sig-maybe) + t))) + +(defun quaker-sig-maybe () + (save-excursion + (goto-char (point-max)) + (search-backward "\n-- \n") + (when (looking-at "\n-- \n Henry") + (forward-char 5) + (kill-entire-line 5) + (insert-file "/afs/inf.ed.ac.uk/user/h/ht/.quaker-sig")))) + +(defun kill-white () + (interactive) + (gnus-summary-goto-article (gnus-summary-article-number)) + (let ((addr (downcase (get-current-from-addr)))) + (rem-white addr))) + +(defun kill-ad () + (interactive) + (gnus-summary-goto-article (gnus-summary-article-number)) + (let ((addr (downcase (get-current-from-addr)))) + (rem-ad addr))) + +(defun get-from-gnus-addr () + (get-from-addr (gnus-fetch-field "From"))) + +(defun get-from-addr (addr) + (get-canonical-from-addr (gnus-extract-address-components addr))) + +(defun get-canonical-from-addr (components) + (downcase (cadr components))) + +(defun get-current-from-addr () + (with-current-buffer gnus-article-buffer + (get-from-gnus-addr))) + +(defun get-current-from-components () + (with-current-buffer gnus-article-buffer + (gnus-extract-address-components (gnus-fetch-field "From")))) + +(defun get-addr-before-point () + (let ((cur (point))) + (save-excursion + (get-from-addr (buffer-substring (+ (search-backward " ") 1) cur))) + )) + +(defun blacken-and-delete (group) + ;; mis-named now + ;; this is part of the expiry processing for xxxSPAM groups, and + ;; actually whitens the from addresses of #-marked articles + ;; The return value is crucial (and crucially outside of the scope of the if) + (if (memq number + (with-current-buffer gnus-summary-buffer + gnus-newsgroup-processable)) + (let ((addr (get-from-gnus-addr))) + (new-white addr))) + 'delete) + +(defun unwhiten-and-delete (group) + ;; unused except in stale groups -- usable as an expiry + (if (memq number + (with-current-buffer gnus-summary-buffer + gnus-newsgroup-processable)) + (let ((addr (get-from-gnus-addr))) + (remove-database addr whitelist-db))) + 'delete) + +(defun known-black (list) + (if (get-database (get-from-gnus-addr) blacklist-db) + list)) + +(defun white-spam (list) + (if (or (equal (get-database (get-from-gnus-addr) whitelist-db) "t") + (let ((case-fold-search t) + (subj (gnus-fetch-field "Subject")) + (from (get-from-gnus-addr))) + (or + (and subj (string-match white-subjects subj)) + (and from + (let ((fromDom (substring from (+ 1 (search "@" from))))) + (and fromDom (member fromDom white-domains))))))) + list)) + +(defun ad-spam (list) + (if (let ((from (get-from-gnus-addr))) + (or + (equal (get-database from adlist-db) "t") + (and from + (let ((fromDom (substring from (+ 1 (search "@" from))))) + (and fromDom (member fromDom ad-domains)))) + )) + list)) + +(defun bogoNote (group) + (if (memq number + (with-current-buffer gnus-summary-buffer + gnus-newsgroup-processable)) + (let ((addr (get-from-gnus-addr))) + (new-white addr))) + (shell-command-on-region (point-min) (point-max) + "/afs/inf.ed.ac.uk/user/h/ht/share/bin/local/makeBogo") + 'delete) + +(defun whiten-recip () + ;;; a hook for outgoing mail + (let* ((recips (message-options-get 'message-recipients)) + (res (mapcar (function new-white) + (split-string (downcase recips) + ",[ \f\t\n\r\v]*" t)))) + (while (and res (not (car res))) + (setq res (cdr res))) + (if res (save-white)))) + + +(defun new-white (addr) + (if (get-database addr whitelist-db) + nil + (put-database addr "t" whitelist-db) + t)) + +(defun new-ad (addr) + (if (get-database addr adlist-db) + nil + (put-database addr "t" adlist-db) + t)) + +(defun rem-ad (addr) + (remove-database addr adlist-db) + (save-ad)) + +(defun new-quaker (addr) + (if (get-database addr quaker-db) + nil + (put-database addr "t" quaker-db) + t)) + +(defun rem-white (addr) + (remove-database (downcase addr) whitelist-db) + (save-white)) + +(defun bogoOK (group) + (shell-command-on-region (point-min) (point-max) + "/afs/inf.ed.ac.uk/user/h/ht/share/bin/local/makeNonBogo") + 'delete) + +(defun del-dups () + (interactive) + (gnus-summary-sort-by-subject) + (gnus-summary-clear-mark-forward 1) + (goto-char (point-min)) + (let ((pos)) + (while (setq pos (search-forward "] " nil t)) + (end-of-line) + (let ((subj (buffer-substring pos (point)))) + (unless (equal subj "") + (let ((target (if (< (length subj) 26) + (concat "] " subj "\n") + (concat "] " (substring subj 0 25)))) + (done 0) + (case-fold-search nil)) + (while (and (= done 0) + (search-forward target nil t)) + (forward-char -3) + (setq done (gnus-summary-mark-as-read-forward 1)))))))) + (gnus-summary-limit-to-unread) + (gnus-summary-sort-by-original)) + +(defun mark-and-mark (n) + (interactive "p") + (while (>= n 1) + (gnus-summary-mark-as-read) + (gnus-summary-mark-as-processable 1) + (setq n (- n 1)))) + +(defun split-on-whole-field (field pat list) + (goto-char (point-max)) + (let ((hit (assq pat wsp-cache)) + rpat) + (if hit + (setq rpat (cdr hit)) + (setq rpat + (concat "^" + field + ":\\s-*" + (if (stringp pat) + pat + (cdr (assq pat + nnmail-split-abbrev-alist))) + "$")) + (setq wsp-cache (cons (cons pat rpat) wsp-cache))) + (if (re-search-backward rpat nil t) + list))) + +(defun ht-gnus-summary-delete-forward () + "REAL delete for nnmail gnus" + (interactive) + (gnus-summary-delete-article) + (gnus-summary-next-unread-article)) + +;; run the first time we make a summary window +(defun gnus-summary-mode-fun1 () + "install ht's mods" + (define-key gnus-summary-mode-map "D" 'ht-gnus-summary-delete-forward) + (define-key gnus-summary-mode-map "~" 'mark-and-mark) + (define-key gnus-summary-mode-map "\M-d" 'gnus-edit-and-move-to-diary) + (define-key gnus-summary-mode-map "\M-e" 'gnus-extract-attachment) + (define-key gnus-summary-mode-map "\M-w" 'add-white) + (define-key gnus-summary-mode-map [(control meta w)] 'copy-region-to-kill) + (define-key gnus-summary-mode-map "\M-h" 'showMPAhtml) + ;(define-key gnus-summary-mode-map [(control meta w)] 'kill-white) + (define-key gnus-summary-mode-map "\M-a" 'add-ad) + (define-key gnus-summary-mode-map "\M-n" 'ht-next-unseen-maybe) + (define-key gnus-summary-mode-map "\M-c" 'ht-catchup-and-next-unseen) + (define-key gnus-summary-mime-map "O" 'ht-article-save-parts) + (define-key gnus-summary-backend-map "M" 'ht-move-to-pers) + (remove-hook 'gnus-summary-mode-hook 'gnus-summary-mode-fun1)) + +(defun message-mode-fun1 () + (define-key message-mode-map [(control meta q)] 'add-quaker) + (remove-hook 'message-mode-hook 'message-mode-fun1)) + +(defvar ht-gnus-just-read nil) + +(defun ht-catchup-and-next-unseen () + (interactive) + (when (gnus-summary-catchup nil t nil 'fast) + (gnus-summary-exit) + (previous-line 1) + (ht-next-with-unseen 1))) + +(defun ht-next-unseen-maybe (n) + (interactive "p") + (cond + ((eq (gnus-summary-next-unread-subject n) n) + (gnus-summary-exit) + (previous-line 1) + (if (ht-next-with-unseen n) + (ht-read-group-unseen-only))))) + +(defun ht-gnus-pers-refresh (n) + (interactive "p") + (let ((gn (concat "nnml+ht:pers-" + (format-time-string "%Y-%m" (current-time))))) + (gnus-group-get-new-news) + (let ((nn (gnus-number-of-unseen-articles-in-group gn))) + (gnus-group-goto-group gn) + (cond + ((> nn 0) + (gnus-group-read-group nn)) + ((> n 1) + (let ((gnus-auto-select-subject + (lambda () + (goto-char (point-max)) + (previous-line 1)))) + (gnus-group-read-group nil t))) + (t (goto-char (point-min)) + (ht-next-with-unseen 1)))) + (message "%s" ht-gnus-just-read)) + ) + +(defun no-select () + (if (member gnus-newsgroup-name no-select-groups) + (progn (make-variable-buffer-local 'gnus-auto-select-first) + (setq gnus-auto-select-first nil)))) + +(defun showMPAhtml () + "Show the text/html parts of an multipart/alternative message using lynx" + (interactive) + (gnus-summary-select-article) + (with-current-buffer gnus-original-article-buffer + (shell-command-on-region (point-min) (point-max) "/afs/inf.ed.ac.uk/user/h/ht/share/bin/showMPA.sh") + ) + ) + + +;; run the first time we make a group window +(defun gnus-group-mode-fun1 () + "install ht's mods" + (require 'gnus-msg) + (define-key gnus-group-mode-map "\M-\C-g" 'ht-gnus-pers-refresh) + (define-key gnus-group-mode-map "\M-n" 'ht-next-with-unseen) + (define-key gnus-group-mode-map "\M-p" 'ht-previous-with-unseen) + (define-key gnus-group-mode-map "\M- " 'ht-read-group-unseen-only) + (define-key gnus-send-bounce-map "R" 'resend-to-schemadev) + (define-key gnus-send-bounce-map "x" 'flush-all-nogoods) + (remove-hook 'gnus-group-mode-hook 'gnus-group-mode-fun1)) + +(defun flush-all-nogoods () + (interactive) + (while (re-search-forward + "] \\(\\(Returned\\|\\([Uu]n\\|[Nn]on-?\\)deliver\\(able\\|ed\\)\\)\\( [Mm]ail\\|:?\\)\\|DELIVERY FAILURE\\|Delivery \\(Notification: Delivery has failed\\|Status Notification .\\(Failure\\|Delay\\).\\)\\|failure \\(notice\\|delivery\\)\\)" + nil t) + (gnus-summary-mark-as-read) + (end-of-line))) + +(defun gnus-user-format-function-t (header) + "display the to field (for archive messages)" + (let ((n (mail-header-number header))) + (with-current-buffer nntp-server-buffer + (save-excursion + (save-restriction + (let ((inhibit-point-motion-hooks t)) + (goto-char (point-min)) + (let ((beg (search-forward (format " %d Article retrieved." n))) + (end (search-forward "\n.\n"))) + (narrow-to-region beg end) + (goto-char beg) + (message-fetch-field "To")))))))) + +(defun gnus-extract-attachment () + "extract attachments from a multi-part mime message" + (interactive) + (let ((sm gnus-show-mime)) + (if sm + (progn (setq gnus-show-mime nil) + (gnus-summary-select-article t 'force)) + ) + (gnus-summary-show-all-headers) + (with-current-buffer gnus-article-buffer + (save-excursion + (save-restriction + (mime/viewer-mode) + (delete-other-windows) + (let ((pt 0)) + (while (progn + (mime-viewer/next-content) + (and + (equal "*Preview-*Article**" (buffer-name (current-buffer))) + (not (= pt (point))))) + (setq pt (point)) + (if (looking-at "^\\[[0-9]* \\([^ ]+ \\)+<") + (mime-viewer/extract-content))))))) + (kill-buffer "*Preview-*Article**") + (setq gnus-show-mime sm) + )) + +;;; Why??? +(make-variable-buffer-local 'gnus-extra-headers) +(make-variable-buffer-local 'nnmail-extra-headers) + + +(defun resend-to-schemadev () + (interactive) + (message "forwarding to xmlschema-dev") + (gnus-summary-resend-message "xmlschema-dev@w3.org" 1) + (gnus-summary-next-unread-article)) + +(defun brutal-resend () + (interactive) + (message "editing for resend. . .") + (unless (eq (gnus-summary-article-number) + gnus-current-article) + (gnus-summary-select-article t)) + (gnus-summary-toggle-header 1) + (with-current-buffer gnus-article-buffer + (toggle-read-only) + (gnus-article-date-original) + (goto-char (point-min)) + (replace-regexp "^\\(X-Diagnostic\\|X-Envelope-To\\|X-Original-To\\|Delivered-To\\):.*\n" "") + (goto-char (point-min)) + (gnus-summary-edit-article-done + (or (mail-header-references gnus-current-headers) "") + (gnus-group-read-only-p) gnus-summary-buffer nil)) + (call-interactively (function gnus-summary-resend-message)) + (gnus-summary-next-unread-article)) + +; (unless (fboundp 'builtin-coding-system-p) +; (fset 'builtin-coding-system-p (symbol-function 'coding-system-p)) +; (defun coding-system-p (obj) +; (cond +; ((builtin-coding-system-p obj) t) +; ((memq obj '(utf-8 gb2312 koi8-r iso-8859-1)) +; (message (format "Coding system: %s" obj)) +; t)))) + +;;; dangerous hack to improve display of names and subjects in mail/news +(if nil (progn +(require 'mm-util) +(defun mm-decode-coding-string (str cs) + (if (and str (eq cs 'utf-8)) + (if (or (string-match "Â" str) + (string-match "Ã" str)) + (let* ((r 0) ; read pointer + (w 0) ; write pointer + (l (length str))) + (while (< r l) + (let* ((c (aref str r)) + (i (char-int c))) + (cond ((= i 194) + (aset str w (aref str (+ r 1))) + (setq r (+ r 2))) + ((= i 195) + (aset str w + (int-char + (+ 64 + (char-int (aref str (+ r 1)))))) + (setq r (+ r 2))) + (t + (aset str w c) + (setq r (+ r 1))))) + (setq w (+ w 1))) + (substring str 0 w)) + str) + str)) + +(defun mm-sort-coding-systems-predicate (a b) + ;; from mm-util, abort if no priorities + (or (not mm-coding-system-priorities) + (let ((priorities + (mapcar (lambda (cs) + ;; Note: invalid entries are dropped silently + (and (setq cs (mm-coding-system-p cs)) + (coding-system-base cs))) + mm-coding-system-priorities))) + (and (setq a (mm-coding-system-p a)) + (if (setq b (mm-coding-system-p b)) + (> (length (memq (coding-system-base a) priorities)) + (length (memq (coding-system-base b) priorities))) + t))))))) + +(require 'browse-url) + +;;; This version collects extra lines if you use right-button +;;; to click on a URL +(defun browse-url (url &rest args) + "Ask a WWW browser to load URL. +Prompts for a URL, defaulting to the URL at or before point. Variable +`browse-url-browser-function' says which browser to use." + (interactive (browse-url-interactive-arg "URL: ")) + (unless (interactive-p) + (setq args (or args (list browse-url-new-window-flag)))) + (if (and (boundp 'event)(= 3 (event-button event))) + (let ((thisLine url)) + (while (and (progn (forward-char (length thisLine)) + (eolp)) + (progn (forward-line 1) + (beginning-of-line) + (not (looking-at "\\s-")))) + (looking-at "\\S-*") + (setq thisLine (buffer-substring (match-beginning 0) + (match-end 0))) + (setq url (concat url thisLine))))) + (if (functionp browse-url-browser-function) + (apply browse-url-browser-function url args) + ;; The `function' can be an alist; look down it for first match + ;; and apply the function (which might be a lambda). + (catch 'done + (dolist (bf browse-url-browser-function) + (when (string-match (car bf) url) + (apply (cdr bf) url args) + (throw 'done t))) + (error "No browse-url-browser-function matching URL %s" + url)))) + +(defun gnus-user-format-function-H (dummy) + (format "%c" + (cond ((eq gnus-tmp-summary-live ?*) + ?*) + ((> (gnus-number-of-unseen-articles-in-group gnus-tmp-group) 0) + ?.) + (t ? )))) + +(defun ht-next-with-unseen (n) + (interactive "p") + (let* ((gvl (mapcar (function string-to-number) + (split-string gnus-version-number "\\."))) + (pattern (if (or (> (car gvl) 5) + (and (eq (car gvl) 5) + (or (> (cadr gvl) 10) + (and (eq (cadr gvl) 10) + (> (caddr gvl) 7))))) + "\\." + ":\\."))) + (if (looking-at pattern) + (if (< n 0) + (backward-char 1) + (forward-char 1))) + (let ((missing 0) + (winning (looking-at pattern))) + (while (and (zerop missing) + (not winning)) + (setq missing (gnus-group-next-unread-group n)) + (setq winning (looking-at pattern))) + winning))) + +(defun ht-read-group-unseen-only () + (interactive) + (gnus-group-read-group + (gnus-number-of-unseen-articles-in-group (gnus-group-group-name)))) + +(defun ht-previous-with-unseen (n) + (interactive "p") + (ht-next-with-unseen (- n))) + +(defun ht-gnus-note-save-to-group () + (let ((g (caar group-art))) + (if (not (member g ht-gnus-just-read)) + (setq ht-gnus-just-read (cons g ht-gnus-just-read))))) + +(defvar ht-stash-directory "/disk/scratch/mail/stash/") + +(defun ht-save-part (handle n) + (let ((sup-type (mm-handle-media-supertype handle)) + (sub-type (mm-handle-media-subtype handle))) + (message (format "%s %s/%s" n sup-type sub-type)) + (cond ((and (equal sup-type "multipart") + (or (equal sub-type "alternative") + (equal sub-type "related"))) + (let ((alts (cddr handle)) + (j 0)) + (while alts + (let* ((alt (pop alts)) + (handle-type (mm-handle-type alt))) + (let* ((sub (mm-handle-media-subtype alt)) + (ext (cdr + (assoc sub '(("calendar" . "vcs") + ("v-calendar" . "vcs")))))) + (setq j (+ j 1)) + (if (not (or (mail-content-type-get + (mm-handle-disposition alt) 'filename) + (mail-content-type-get + handle-type 'name))) + (nconc + handle-type + (list (cons 'name (format "%s.%s.%s" + n j (or ext sub)))))) + (ht-save-part alt (format "%s.%s" n j))))))) + ((and (equal sup-type "text")(not + (member sub-type '("html" + "v-calendar" + "calendar")))) + (message "Skipping text part: %s" (mm-handle-disposition handle))) + (t + (mm-save-part handle))))) + +(defun ht-move-to-pers (n) + (interactive "p") + (gnus-summary-move-article n + (concat + "nnml+ht:pers-" + (format-time-string "%Y-%m" (current-time))))) + +(defun ht-article-save-parts (n) + "Save non t/p MIME parts starting at N, which is the numerical prefix." + (interactive "p2") + (let ((window (get-buffer-window gnus-article-buffer 'visible)) + frame) + (when window + ;; It is necessary to select the article window so that + ;; `gnus-article-goto-part' may really move the point. + (setq frame (selected-frame)) + (gnus-select-frame-set-input-focus (window-frame window)) + (unwind-protect + (save-window-excursion + (select-window window) + (let ((len (length gnus-article-mime-handle-alist))) + (setq mm-default-directory ht-stash-directory) + (while (<= n len) + (gnus-article-goto-part n) + (let ((handle (cdr (assq n gnus-article-mime-handle-alist)))) + (ht-save-part handle n)) + (setq n (+ n 1)) + ))) + (gnus-select-frame-set-input-focus frame)))) + ) + + +(defun gnus-article-part-wrapper (n function) + (let ((window (get-buffer-window gnus-article-buffer 'visible)) + frame) + (when window + ;; It is necessary to select the article window so that + ;; `gnus-article-goto-part' may really move the point. + (setq frame (selected-frame)) + (gnus-select-frame-set-input-focus (window-frame window)) + (unwind-protect + (save-window-excursion + (select-window window) + (when (> n (length gnus-article-mime-handle-alist)) + (error "No such part")) + (gnus-article-goto-part n) + (let ((handle (cdr (assq n gnus-article-mime-handle-alist)))) + (funcall function handle))) + (gnus-select-frame-set-input-focus frame))))) + +(defun mhstore-me (dir) + (interactive (list (read-directory-name "Save parts to " "/tmp" "/tmp" t))) + (let ((art (gnus-summary-article-number))) + (let* ((grp-parts (split-string gnus-newsgroup-name ":")) + (meth (car grp-parts)) + (grp (cadr grp-parts))) + (if (string= meth "nnml+ht") + (let ((doit + (format "cd %s && mhstore -f /disk/scratch/mail/Mail/%s/%s -auto" + dir grp art))) + (message doit) + (shell-command doit)) + )))) + +(defun my-message-send-and-exit (&optional arg) + (interactive "P") + (let ((message-required-mail-headers + (if arg + (mapcar + (lambda(x) + (if(and(consp x)(eq(cdr x)'In-Reply-To)) + (cons 'optional 'xyzzy) + x)) + message-required-mail-headers) + message-required-mail-headers))) + (orig-message-send-and-exit))) + +(require 'message) +(if (not (fboundp 'orig-message-send-and-exit)) + (progn + (fset 'orig-message-send-and-exit (symbol-function 'message-send-and-exit)) + (fset 'message-send-and-exit (symbol-function 'my-message-send-and-exit)))) + +(provide 'my-news)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lucid/rooms.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,293 @@ +;;; rooms facility for gnuemacs + +;;; Copyright Henry S. Thompson 1990 + +;;; Last edited: Wed Sep 14 08:48:27 1994 + +;;; v19.19 version + +(provide 'rooms) +(require 'prompt-for-word) + +(defvar rooms-table nil "a-list of rooms in the form (name . window-specs)") + +(defvar frames-table nil "a-list of room to frame mappings") + +(defvar rooms-map (let ((new (copy-keymap pfw-map))) + (define-key new "\C-r" 'minibuffer-complete-and-exit) + new) + "allow ^R as synonym for CR in prompt-for-word") + +(defmacro room-name (room) (list 'car room)) +(defmacro room-window-specs (room) (list 'cdr room)) +(defmacro make-room (name window-specs) (list 'cons name window-specs)) + +(defvar current-room nil "the current room") + +(defvar previous-room nil "the previous room") + +;; a window spec is of the form (buffer-name constitution . edges) +(defmacro ws-buffer-name (ws) (list 'car ws)) +(defmacro ws-constitution (ws) (list 'car (list 'cdr ws))) +(defmacro ws-edges (ws) (list 'cdr (list 'cdr ws))) +(defmacro make-ws (buffer-name constitution edges) + (list 'cons buffer-name + (list 'cons constitution edges))) + +(defun rooms-top (redraw) + "top level for rooms - prompts for room name and goes there. +Prefix arg forces room's frame to its defined contents. +Typing overrides initial suggestion, exiting completes. To name a new room +exit with ^N +To redefine an existing room, exit with ^R" + (interactive "PIf prefixed, forces room's frame, if any, to its defined contents") + (let ((name (prompt-for-word "Room: " (or (room-name previous-room) "") + rooms-table (if rooms-table + rooms-map))) + (e-o-c last-input-char) + room) + (cond ((eq e-o-c 18) ; ^R + (rooms-redefine-query name)) + (t + (if (setq room (assoc name rooms-table)) + (rooms-goto room redraw) + (rooms-new-query name)))))) + +(defun rooms-goto (room &optional redraw) "switch frame to ROOM's config" + (let ((room (if (stringp room) + (or (assoc room rooms-table) + (error "No room named %s" room)) + room)) + st-entry) + (if (not (eq room current-room)) + (setq previous-room current-room)) + (setq current-room room) + ;; lazy if mapped to frame and not redraw + (if (setq st-entry (assoc (room-name room) frames-table)) + ;; very tricky -- appears to be the only order that works! + (progn +; (focus-frame (cdr st-entry)) + (select-frame (cdr st-entry)) + (raise-frame (cdr st-entry)) ; gwm/empty.gwm/emacs-19.28 pblm??? + (if redraw (establish-room room))) + (establish-room room)))) + +(defun rooms-new-query (name) + "check to see if new room or definition wanted" + (if (y-or-n-p (concat "Define a new room named " + name + "? ")) + (rooms-new name) + (message ""))) + +(defun rooms-redefine-query (name) "check to see if new room wanted" + (if (y-or-n-p (concat "Redefine the room named " + name + "? ")) + (progn (setq rooms-table (delq (or (assoc name rooms-table) + (error "shouldnt")) + rooms-table)) + (rooms-new name)) + (message ""))) + +(defun rooms-new (name) "define a new room named NAME as per the current frame" + (interactive "sroom name for current frame: ") + (let ((here (selected-window)) + (looping t) + spec top-p next all-specs) + ;; collect specs for all windows on frame, noting top one + (setq next here) + (while looping + (setq spec (window-edges next)) + (setq all-specs (cons (make-ws (buffer-name (window-buffer next)) + nil + spec) + all-specs)) + (if (= (car (cdr spec)) 0) ; check for top + (progn (setq top-p all-specs) + (setq all-specs nil))) + (setq next (previous-window next)) + (if (eq next here) + (setq looping nil))) + (setq rooms-table + (cons + (make-room name + (nconc top-p + all-specs)) + rooms-table)) + (message (concat name " defined as current frame configuration")))) + +(global-set-key "\eo" 'rooms-top) + +(defun define-rooms (spec-list) "define rooms from specs" + (let ((spp spec-list)) + (while spp + (establish-room (car spp) t) + (setq spp (cdr spp))))) + +(defun establish-room (r-spec &optional create) "define room from spec" + ;; a room-spec is of the form (name . window-specs) + ;; a window spec is of the form (buffer-name constitution . edges) + ;; a buffer-name is either a string, in which case the constitution will be + ;; left to create it, or (<string>), in which case a new buffer of that name + ;; will be generated first. + ;; a constitution is either nil, a file name to be visited, or a form + ;; to be evaluated + ;; if create is nil, buffer is not touched (constitution is ignored) + (let ((r-name (room-name r-spec)) + (w-specs (room-window-specs r-spec)) + (used -1) + w-spec st-entry) + (if create + (while w-specs + (setq w-spec (car w-specs)) + (let ((buf-name (ws-buffer-name w-spec)) + (const (ws-constitution w-spec))) + ;; initialise the buffer + (if (consp buf-name) + (set-buffer (generate-new-buffer (car buf-name)))) + (if const + (condition-case foo + (if (stringp const) + (find-file const) + (eval const)) + (error (message "%s" foo))))) + (setq w-specs (cdr w-specs)))) + (setq w-specs (room-window-specs r-spec)) + (switch-to-buffer (let ((b-n (ws-buffer-name (car w-specs)))) + (if (consp b-n) + (car b-n) + b-n))) + (delete-other-windows) + (setq w-specs (cdr w-specs)) + (while w-specs + (setq w-spec (car w-specs)) + (let ((buf-name (ws-buffer-name w-spec)) + (edges (ws-edges w-spec))) + ;; make a window of the right size + ;; we assume full-width windows for now, with specs in top-to-bottom + (let ((top (1- (car (cdr edges))))) + (split-window-vertically (- top used)) + (setq used top)) + (other-window 1) + (switch-to-buffer (if (consp buf-name) + (car buf-name) + buf-name))) + (setq w-specs (cdr w-specs))) + (if create + (setq rooms-table (nconc rooms-table (list r-spec)))))) + +(defun make-frame-for-room (&optional name xpos ypos ixpos iypos) + "prompts for room name and makes a frame for it. +Typing overrides initial suggestion, exiting completes." + (interactive) + (let ((name (or name + (prompt-for-word "Room: " (or (room-name previous-room) "") + rooms-table (if rooms-table + rooms-map)))) + room) + (if (not (setq room (assoc name rooms-table))) + (error "no room named %s" name) + (let ((last-w-edges (ws-edges (last-element (room-window-specs room)))) + (st-entry (assoc name frames-table)) + ;; assume (falsely) that new frame will be like old one + (parms (frame-parameters nil)) + (sys-name (substring (system-name) 0 + (string-match "\\." (system-name)))) + frame) + (let ((width (car (cdr (cdr last-w-edges)))) + (height (+ + (or (cdr (assoc 'menu-bar-lines parms)) 0) + 1 ; allowing 1 for mode line + (if (let ((mb (cdr (assoc 'minibuffer parms)))) + (or + (eq mb t) + (and (windowp mb) + (eq (window-frame mb) + (selected-frame))))) + 1 + 0) + (car (cdr (cdr (cdr last-w-edges)))))) + (x-slop (+ (* 2 (+ (cdr (assoc 'border-width parms)) + (cdr (assoc 'internal-border-width parms)))) + (if (cdr (assoc 'vertical-scroll-bars parms)) + 19 + 0))) + (y-slop (+ (* 2 (+ (cdr (assoc 'border-width parms)) + (cdr (assoc 'internal-border-width parms)))) + (if (cdr (assoc 'horizontal-scroll-bars parms)) + 19 + 0) + 16 ; window title bar + )) + (title + (concat name + ":" (user-login-name) + (concat "@" sys-name) + ))) + (let ((args (list + (cons 'width width) + (cons 'height height) + ;; Note that x-parse-geometry doesn't handle all position cases + (cons 'left + (if xpos + (+ (if (string-match + "^[+]" xpos) + 0 + (- + (x-display-pixel-width) + (+ (* (face-width (get-face 'default)) + width) + x-slop))) + (car (read-from-string xpos) + )) + 0)) + (cons 'top + (if ypos + (+ (if (string-match + "^[+]" ypos) + 0 + (- + (x-display-pixel-height) + (+ (* (face-height (get-face 'default)) + height) + y-slop))) + (car + (read-from-string ypos))) + 0)) + (cons 'name title)))) + (setq frame + (make-frame args)))) + (if st-entry + (rplacd st-entry frame) + (setq frames-table (cons (cons name frame) + frames-table))) + (if (or ixpos iypos) + (position-frame-icon (or ixpos + (car + (cdr + (assoc 'left + (frame-parameters frame))))) + (or iypos (car + (cdr + (assoc 'top + (frame-parameters frame))))) + frame))) + (rooms-goto room t)))) + +(defun make-screen-for-room (&optional name xpos ypos ixpos iypos) + (make-frame-for-room name xpos ypos ixpos iypos)) + +(defun position-frame-icon (x y frame) + "fiddle to get the icon for a frame in a specified place" +) + +(defun last-element (list) + "Return last element of LIST." + (let ((last nil)) + (while list + (if (null (cdr list)) + (setq last (car list))) + (setq list (cdr list))) + last + ))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shared/alarm.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,123 @@ +;;; Last edited: Thu Jun 11 10:49:18 1992 +;;; alarm facility for emacs + +(provide 'alarm) + +(defvar alarm-process nil) + +(defvar alarm-callback nil) + +(defun alarm (seconds function) + "After SECONDS, funcall FUNCTION" + (if (and alarm-process + (not (eq (process-status alarm-process) 'exit))) + (error "already waiting") + (setq alarm-callback function) + (setq alarm-process + (start-process "alarm-clock" nil + "/bin/sleep" (format "%d" seconds))) + (set-process-sentinel alarm-process (function alarm-sentinel))) + ) + +(defun alarm-sentinel (process reason) + (setq asm reason) + (if (equal reason "finished\n") + (funcall alarm-callback) + (error "Bogus alarm message: %s" reason))) + +(defun alarm-stop () "turn off alarm" + (interactive) + (set-process-sentinel alarm-process nil) + (kill-process alarm-process) + (setq alarm-process nil)) + +(defvar idle-last-command nil) +(defvar idle-last-input-char nil) +(defvar idle-time nil) +(defvar idle-interval nil) +(defvar idle-function nil) +(defvar idle-count nil) + +(defun idle-timeout (seconds function &optional check-interval) + "If idle for SECONDS, call FUNCTION. Check every CHECK-INTERVAL, or 60 secs" + (setq idle-last-command last-command) + (setq idle-last-input-char last-input-char) + (setq idle-time seconds) + (setq idle-start-time (current-msec-time)) + (setq idle-interval (or check-interval 60)) + (setq idle-count (/ (+ seconds (1- idle-interval)) idle-interval)) + (setq idle-function function) + (alarm idle-interval (function idle-check))) + +(defun idle-check () + (setq idle-count (max (1- idle-count) 0)) +; (message "trying") + (if (and + (eq idle-last-command last-command) +; (message "tic") + (= idle-last-input-char last-input-char) +; (message "toc") + ) + (if (and (= idle-count 0) +; (message "torum") + (or + (let ((last-field-3 (last-event-time))) + ;; allow for wrap + (or (not last-field-3) +; (progn (message "tarum") nil) + (let ((last (logand 8388607 + last-field-3)) + (time (current-msec-time))) +; (message "%d %d %d" last time idle-time) + (> (/ (if (< time last) + (+ (- time last) 8388607) + (- time last)) + 1000) + idle-time)))))) + (save-excursion + (set-buffer (get-buffer-create "*Idle*")) + (insert-string "Idle at " (current-time-string) + (format " :\n %s -> " + idle-function)) + (insert-string (format "%s\n" + (save-excursion (funcall idle-function))))) + (alarm idle-interval (function idle-check))) + (setq idle-last-command last-command) + (setq idle-last-input-char last-input-char) + (setq idle-count (/ (+ idle-time (1- idle-interval)) idle-interval)) + (alarm idle-interval (function idle-check)))) + +(defvar idle-save-timeout nil) + +(defun idle-save (&optional minutes) + "If idle for more MINUTES (defaults to 5), save all changed buffers" + (interactive "nIdle after minutes: ") + (idle-timeout (setq idle-save-timeout (* 60 (or minutes 5))) + (quote idle-save-doit))) + +(defun idle-save-doit () + (let ((bufs (buffer-list)) + result) + (while bufs + (let ((buf (car bufs)) file-name) + (if (and (buffer-modified-p buf) + (setq file-name (buffer-file-name buf)) + (string-match "\\.babyl$" file-name)) + (progn (set-buffer buf) + (let ((require-final-newline nil)) + (save-buffer) + (setq result (cons file-name result)))))) + (setq bufs (cdr bufs))) + (idle-timeout idle-save-timeout (quote idle-save-doit)) + (if result + (mapconcat (function identity) + result + " ") + "nil"))) + +;; defaults +(defun current-msec-time () (the-time)) +(defun last-event-time () + (and (boundp '*last-event*) + (> (length *last-event*) 3) + (elt *last-event* 3)))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shared/compress.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,69 @@ +;;; Last edited: Thu Oct 3 12:28:00 1991 +;;; Handle compressed files +;;; adapted by Henry S. Thompson from Miles Bader from ??? +(provide 'compress) + +(defun uncompress-while-visiting () + "Temporary \"major mode\" used for .[gzZ] files, to uncompress the contents. +It then selects a major mode from the uncompressed file name and contents." + (if (and (not (null buffer-file-name)) + (string-match "\\.g?[zZ]$" buffer-file-name)) + (set-visited-file-name + (substring buffer-file-name 0 (match-beginning 0)))) + (message "Uncompressing...") + (let ((buffer-read-only nil)) + (shell-command-on-region (point-min) (point-max) "zcat" t)) + (message "Uncompressing...done") + (set-buffer-modified-p nil) + (normal-mode)) + +(setq auto-mode-alist + (cons '("\\.g?[zZ]$" . uncompress-while-visiting) auto-mode-alist)) + +(defun find-compressed-version () + "Hook to read and uncompress the compressed version of a file." + ;; Just pretend we had visited the compressed file, + ;; and uncompress-while-visiting will do the rest. + (let ((exts '("gz" "z" "Z")) ext found) + (while (and exts (setq ext (car exts)) (not found)) + (if (file-exists-p (concat buffer-file-name "." ext)) + (progn + (setq buffer-file-name (concat buffer-file-name "." ext)) + (insert-file-contents buffer-file-name t) + (goto-char (point-min)) + (setq error nil) + t) + (setq exts (cdr exts)))))) + +(setq find-file-not-found-hooks + (cons 'find-compressed-version find-file-not-found-hooks)) + +(defun compress-again () + "Hook to compress the uncompressed version of a file." + (let ((exts '("gz" "z" "Z")) ext found) + (while (and exts (setq ext (car exts)) (not found)) + (if (file-exists-p (concat buffer-file-name "." ext)) + (let ((here (current-buffer)) + (fake-buffer-file-name (concat buffer-file-name "." ext)) + (require-final-newline nil)) + (set-buffer (get-buffer-create " *compress*")) + (erase-buffer) + (insert-buffer here) + (message "Compressing...") + (shell-command-on-region (point-min) (point-max) + (if (equal "Z" ext) + "compress" + "gzip") t) + (message "Compressing...done") + (write-region (point-min)(point-max) fake-buffer-file-name) + (bury-buffer (current-buffer)) + (set-buffer here) + (set-buffer-modified-p nil) + (setq found t) + t) + (setq exts (cdr exts)))) + found)) + + +(setq write-file-hooks (cons 'compress-again write-file-hooks)) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shared/device-type-hacking.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,63 @@ + + +(defconst device-type-hacking-id "$Id: device-type-hacking.el,v 1.1 1996/07/25 22:17:36 rjc Exp $") + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; ;; + ;; Changes some values depending on device type ttys. have ;; + ;; control-h being delete and zmacs-regions turned off. ;; + ;; ;; + ;; Since select-frame-hook doesn't seem to be called for tty ;; + ;; devices, we have to cheat and set the tty defaults whenever a ;; + ;; frame is deselected. ;; + ;; ;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defvar zmacs-regions-specifier + (make-specifier-and-init 'boolean + '( (global ((tty). nil) ((x) . t)) ) + )) + + +(defun device-type-tty-selected () + + (define-key global-map '(control h) 'backward-delete-char-untabify) + ) + +(defun device-type-x-selected () + + (define-key global-map '(control h) 'help) + ) + +(defun device-type-select-frame-hook () + + (setq zmacs-regions + (specifier-instance zmacs-regions-specifier) + ) + + (if (equal (device-type (selected-device)) "tty") + (device-type-tty-selected) + (device-type-x-selected) + ) + + ) + +(defun device-type-deselect-frame-hook () + + (setq zmacs-regions + (not (specifier-instance zmacs-regions-specifier)) + ) + + (device-type-tty-selected) + + ) + +(setq deselect-frame-hook '(default-deselect-frame-hook)) +(setq select-frame-hook '(default-select-frame-hook)) + + +(add-hook 'select-frame-hook (function device-type-select-frame-hook)) +(add-hook 'deselect-frame-hook (function device-type-deselect-frame-hook) t) + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shared/diary.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,630 @@ +;; Last edited: Wed Oct 24 17:08:20 1990 +;; provide a simple diary facility on top of rmailsum +;; Copyright (C) 1990 Henry S. Thompson + +;; This file is part of GNU Emacs. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY. No author or distributor +;; accepts responsibility to anyone for the consequences of using it +;; or for whether it serves any particular purpose or works at all, +;; unless he says so in writing. Refer to the GNU Emacs General Public +;; License for full details. + +;; Everyone is granted permission to copy, modify and redistribute +;; GNU Emacs, but only under the conditions described in the +;; GNU Emacs General Public License. A copy of this license is +;; supposed to have been given to you along with GNU Emacs so you +;; can know your rights and responsibilities. It should be in a +;; file named COPYING. Among other things, the copyright notice +;; and this notice must be preserved on all copies. + +(provide 'diary) +(require 'mail-extras) + +(autoload 'sort-subr "sort") + +(defvar ht-diary-file-name "~/DIARY.babyl" + "default name of diary file") + +(defvar ht-Calendar-directory "~/Calendar") + +(defun xxx-date-lessp (date1 date2) + "Return T if DATE1 is earlyer than DATE2." + (string-lessp (gnus-comparable-date date1) + (gnus-comparable-date date2))) + +(defun xxx-comparable-date (date) + "Make comparable string by string-lessp from DATE." + (let ((month '(("JAN" . " 1")("FEB" . " 2")("MAR" . " 3") + ("APR" . " 4")("MAY" . " 5")("JUN" . " 6") + ("JUL" . " 7")("AUG" . " 8")("SEP" . " 9") + ("OCT" . "10")("NOV" . "11")("DEC" . "12"))) + (date (or date ""))) + ;; Can understand the following styles: + ;; (1) 14 Apr 89 03:20:12 GMT + ;; (2) Fri, 17 March 89 4:01:33 GMT + (if (string-match + "\\([0-9]+\\) \\([^ ,]+\\) \\([0-9]+\\) *\\([0-9:]*\\)" date) + (let ((year (substring date (match-beginning 3) (match-end 3))) + (mn (substring date + (match-beginning 2) + (+ 3 (match-beginning 2)))) + (day (substring date + (match-beginning 1) (match-end 1))) + (time (substring date (match-beginning 4) (match-end 4)))) + (concat + ;; Year + (if (= (length year) 2) + (if (string-match "^9" year) + (concat "19" year) + (concat "20" year)) + year) + ;; Month + (cdr + (assoc + (upcase mn) + month)) + ;; Day + (format "%2d" (string-to-int day)) + ;; Time + time)) + ;; Cannot understand DATE string. + date + ) + )) + +(defun update-default-diary (arg) "update a diary - with arg, the one for +this file. Without arg, the default (named in ht-diary-file-name)" + (interactive "P") + (if arg + (update-diary (current-buffer)) + (require-diary) + (update-diary (get-file-buffer ht-diary-file-name)))) + +(defun update-diary (buffer) +;; (setq rmail-summary-buffer (get-buffer-create "*Diary*")) + (let ((obuf (current-buffer))) + (set-buffer buffer) + (if (not has-diary-summary) + (progn (make-local-variable 'has-diary-summary) + (setq has-diary-summary t))) + (rmail-summary) + (set-buffer obuf))) + +(defun do-diary-update () "rmail-summary-mode-hook calls this" + (if (save-excursion (set-buffer rbuf) + has-diary-summary) + (progn + (make-local-variable 'diary-summary-buffer) + (setq diary-summary-buffer t) + (setq description (concat "Diary " description)) + (setq buffer-read-only nil) + (sort-diary-hdrs) + (format-diary-hdrs) + (setq buffer-read-only t) + (not-modified) + (beginning-of-buffer) + (setq mesg nil) ; to go to earliest, not first in file + ))) + +(defun require-diary () + (if (not (get-file-buffer ht-diary-file-name)) + (progn (rmail-input ht-diary-file-name) + (rmail-show-message 1)) + )) + +(defvar diary-summary-buffer nil "flag to identify diary summaries") +(defvar has-diary-summary nil "flag to identify buffers with diary summaries") + +(defun sort-diary-hdrs () + (interactive) + (goto-char (point-min)) + (sort-subr nil 'forward-line 'end-of-line 'get-diary-hdr-date nil)) + +(defun format-diary-hdrs () + (goto-char (point-min)) + (while (< (point)(point-max)) + (forward-char 5) + (delete-char 35) + (looking-at " *\\([0-9]*\\) *\\([a-zA-Z]*\\) *\\([0-9]*\\) *\\([0-9]*\\)") + (if (match-beginning 0) + (let ((day (buffer-substring (match-beginning 1)(match-end 1))) + (month (capitalize (buffer-substring (match-beginning 2) + (min (+ (match-beginning 2) + 3) + (match-end 2))))) + (year (buffer-substring (max + (- (match-end 3) 2) + (match-beginning 3)) + (match-end 3))) + (time (buffer-substring (match-beginning 4)(match-end 4)))) + (delete-char (+ 1 + (if (= (match-end 4) + (match-beginning 4)) + 0 ; fix for no time case + 1) + (- (match-end 4)(match-beginning 1)))) + (insert (format " %2s %3s %2s %4s " day month year time)))) + (forward-line 1)) + (goto-char (point-min))) + +(defun get-diary-hdr-date () + (looking-at " *[^ ]* *[^ ]* *[^ ]* *\\(.*\\)$") + (xxx-comparable-date (buffer-substring (match-beginning 1)(match-end 1)))) + + +(if (not (boundp 'rmail-edit-map)) + (load-library "rmailedit")) +(if (not (boundp 'rmail-summary-mode-map)) + (progn (load-library "rmailsum") + (rmail-summary-mode-fun1))) +(define-key rmail-edit-map "\C-c\C-c" 'ht-rmail-cease-edit) +(define-key rmail-edit-map "\C-c\C-]" 'ht-rmail-abort-edit) +;(defvar diary-mode-map (copy-keymap rmail-summary-mode-map)) +;(define-key diary-mode-map "s" 'diary-save) +(define-key rmail-mode-map "h" 'ht-rmail-summarise) +(setq rmail-summary-mode-hook 'do-diary-update) + +(defvar editing-diary-entry nil) + +(defun diary-save () + "save parent file and update" + (interactive) + (set-buffer rmail-buffer) + (rmail-expunge-and-save) + (if has-diary-summary (update-diary (current-buffer)))) + +(defun ht-rmail-summarise () + "Display a summary of all messages, one line per message. +If file is named as ht-diary-file-name, or the summary buffer is already +a diary summary, make it a Diary summary (see +\\[describe-mode] rmail-summary-mode for info)." + (interactive) + (if (eq (current-buffer) + (get-file-buffer ht-diary-file-name)) + (update-default-diary t) + (rmail-summary))) + +(defun edit-and-move-to-diary () + "try to add a date to subject field, move to diary on exit" + (interactive) + (make-local-variable 'editing-diary-entry) + (setq editing-diary-entry t) + (rmail-edit-current-message) + (goto-char (point-min)) + (search-forward "\n\n") + (let ((try-date (and + (re-search-forward + "[0-9][-0-9 ]*[- ][a-zA-Z][a-zA-Z]*[- 0-9]*" nil t) + (buffer-substring (match-beginning 0)(match-end 0)))) + sublp) + (goto-char (point-min)) + (setq sublp (search-forward "Subject: " nil t)) + (if try-date + (progn (set-mark (point)) + (insert try-date))))) + +(defun gnus-edit-and-move-to-diary (&optional no-delete) + "try to add a date to subject field, move to diary on exit" + (interactive "P") + (when (gnus-group-read-only-p) + (error "The current newsgroup does not support article editing")) + ;; Select article if needed. + (unless (eq (gnus-summary-article-number) + gnus-current-article) + (gnus-summary-select-article t)) + (gnus-article-date-original) + (message "About to forward. . .") + (gnus-summary-mail-forward 1) + (message "Begin forward. . .") + (goto-char (point-min)) + (search-forward "^To: " nil t) + (forward-char 4) + (insert "htcalendar@markup.co.uk") + (search-forward "------ Start of forwarded") + (let (sublp) + (save-excursion + (let ((try-date + (and + (or (re-search-forward "^\r?$" nil 1) t) + (re-search-forward + "[0-9][-0-9 ]*[- ][jfmasondJFMASOND][a-zA-Z]*[- 0-9]*" + (save-excursion (search-forward "\n--\n" nil t)) + t) + (buffer-substring (match-beginning 0)(match-end 0))))) + (goto-char (point-min)) + (setq sublp (search-forward "Subject: " nil t)) + (delete-region (point)(progn (search-forward "] " nil t))) + (message (format "date: |%s| %s" try-date sublp)) + (if (and sublp + try-date) + (progn (set-mark (point)) + (insert try-date))))) + (make-local-hook 'message-send-hook) + (if (and no-delete (equal (car no-delete) 16)) + (let ((hook '(lambda () + (ht-gnus-cease-edit nil) + nil t))) + (add-hook 'message-send-hook hook nil t) + + (message-send-and-exit) + (if (not (gnus-summary-next-unread-article)) + (gnus-summary-exit))) + (add-hook 'message-send-hook + `(lambda () + (ht-gnus-cease-edit ',no-delete) + ; (gnus-summary-edit-article-done + ; ,(or (mail-header-references gnus-current-headers) "") + ; ,(gnus-group-read-only-p) ,gnus-summary-buffer nil) + ; (switch-to-buffer gnus-summary-buffer))) + ; (goto-char (point-min)) + ; (search-forward "\nSubject: " nil t)) + ) + nil t) + (split-window-vertically 6) + (other-window 1) + (search-forward "\n\n" nil t) + (other-window 1) + (goto-char sublp) + (message "Exiting to buffer, we hope"))) + ) + +(defun ht-gnus-cease-edit (&optional no-delete) + "check if diary edit, move if so" + (interactive "P") + (message "ceasing. . .") + (ht-forward-to-Calendar) + (let ((rmail-summary-redo '(rmail-summary))) + (gnus-output-to-rmail ht-diary-file-name) + ) + (unless no-delete + (with-current-buffer gnus-summary-buffer + (gnus-summary-delete-article))) + (if (get-buffer "diary.babyl-summary") + (kill-buffer "diary.babyl-summary")) + (with-current-buffer "diary.babyl" + (rmail-mode) + (save-buffer) + (ht-rmail-summarise)) + (message "ceased")) + +(defun ht-gnus-summary-save-in-diary (&optional filename) + (gnus-eval-in-buffer-window gnus-save-article-buffer + (save-excursion + (save-restriction + (widen) + (gnus-output-to-rmail ht-diary-file-name))))) + +;; private copy to simulate hook +(defun ht-rmail-cease-edit () + "check if diary edit, move if so" + (interactive) + (rmail-cease-edit) + (if editing-diary-entry + (progn (setq editing-diary-entry nil) + (ht-forward-to-Calendar) + (rmail-output-to-rmail-file ht-diary-file-name 1) + (ht-rmail-delete-forward)))) + +;; try to add a diary subject field line to the appropriate calendar file +(defun ht-forward-to-Calendar () + (goto-char (point-min)) + (search-forward "Subject: ") + (or (looking-at + "\\([0-9]+\\) \\([A-Za-z]+\\) \\([0-9]+\\) \\([0-9:]*\\) ?\\(.*\\)\n") + (error "not a recognisable diary line")) + (let ((day (buffer-substring (match-beginning 1) (match-end 1))) + (month (buffer-substring (match-beginning 2) (match-end 2))) + (year (buffer-substring (match-beginning 3) (match-end 3))) + (time (buffer-substring (match-beginning 4) (match-end 4))) + (message (buffer-substring (match-beginning 5) (match-end 5))) + (mb (match-beginning 4)) + (me (match-end 5)) + ends e-day e-month fn) + (let ((year (if (string-match "^\\(19\\|20\\).." year) + year + (if (eq (length year) 2) + (concat "20" year) + (progn (if (and (equal time "")(eq (length year) 4)) + (setq time year)) + (format-time-string "%Y"))))) + (t-month (capitalize + (substring month 0 3)))) + (let* ((n-day (read day)) + (mon-table '((Jan . 1) + (Feb . 2) + (Mar . 3) + (Apr . 4) + (May . 5) + (Jun . 6) + (Jul . 7) + (Aug . 8) + (Sep . 9) + (Oct . 10) + (Nov . 11) + (Dec . 12))) + (a-month (assq (read t-month) + mon-table)) + (n-month (if a-month (cdr a-month) 0)) + (u-time (if (equal time "") "0" time)) + (hour (/ (read u-time) 100)) + (minute (mod (read u-time) 100)) + (nhour (if (> minute 29) + (+ 1 hour) + hour)) + (nminute (if (> minute 29) + (- minute 30) + (+ minute 30))) + (n-year (read year)) + (r-subj (mail-fetch-field "Subject")) + (body (save-excursion + (buffer-substring + (progn + (goto-char (point-min)) + (if (re-search-forward "^\r?$" nil 1) + (match-beginning 0) + (point-max))) + (point-max)))) + (subj-matches (string-match "^\\([^(]*\\)\\((\\(.*\\))\\)?" + message)) + (np-subj (match-string 1 message)) + (p-subj (or (match-string 3 message) "")) + (uid (or (mail-fetch-field "Message-id") + (let ((ct (current-time))) + (format "%d-%d-%d" + (car ct) + (cadr ct) + (caddr ct))))) + ) + (if (string-match " -- \\(.*\\)$" message) + (progn + (setq ends (substring message (match-beginning 1) + (match-end 1))) + (setq message (substring message 0 (match-beginning 0))) + (if (string-match "\\([0-9]+\\) \\([A-Za-z]+\\)" ends) + (progn + (setq e-day (substring ends (match-beginning 1) + (match-end 1))) + (setq e-month (assq + (read (capitalize + (substring + (substring ends (match-beginning 2) + (match-end 2)) + 0 3))) + mon-table)))))) + (setq fn (build-vcal-message (my-time-iso8601 + (encode-time + 0 minute + hour + n-day + n-month + n-year)) + (my-time-iso8601 + (if e-day + (encode-time + 0 (if (eq hour 0) 30 minute) ;nminute + (if (eq hour 0) 23 hour) ; nhour + (read e-day) + (if e-month (cdr e-month) 0) + n-year) + (encode-time + 0 minute ; nminute + (+ hour 1) ; nhour + n-day + n-month + n-year))) + "ORGANIZER;CN=\"Henry S. Thompson\":mailto:htcalendar@markup.co.uk" + ;(concat "ORGANIZER:" (mail-fetch-field "From")) + p-subj + body + np-subj + (concat "ht-vcal-" uid))) + (if fn + (progn + (goto-char (point-min)) + (if (search-forward "<#multipart " nil t) + (progn + (if (search-forward "<#multipart type=alternative" nil t) + (beginning-of-line) + (forward-line 2) + ;; now at beginning of forwarded text + (if (search-forward "<#part " nil t) + (progn + ;; now at beginning of _attachments_ + (beginning-of-line)) + ;; no attachments, probably never happens + (search-forward "<#/multipart>")))) + ;; plain text, make it multipart + (search-forward "-------- Start of forwarded") + (re-search-forward "^\r?$") + (forward-line 1) + (insert "<#multipart type=mixed>\n<#part type=text/plain charset=\"ISO-8859-1\" format=\"flowed\" disposition=inline nofile=yes>\n") + (search-forward "--------- End of forwarded") + (forward-line -1) + (insert "<#/multipart>\n") + (forward-line -1)) + (mml-attach-file fn "application/octet-stream" "diary event") +; (let ((res (shell-command-to-string +; (concat "updateCal.pl < " fn)))) +; (if (not (equal res "")) +; (message (format "update losing: %s" res)))) + ))) + (if (file-exists-p ht-Calendar-directory) + (let* ((dfn (concat ht-Calendar-directory + "/xy" + year + "/xc" + day + t-month + year)) + (buf (find-file-noselect dfn)) + ) + (save-excursion + (set-buffer buf) + (goto-char (point-max)) + (if (not (bolp)) + (insert "\n")) + (if time + (insert time " ")) + (insert message) + (let ((require-final-newline nil)) + (save-buffer))) + (if ends + ;; an end date also given + (if e-day + (let (t-e-month msg) + (setq msg (concat + (substring message 0 + (string-match " " message)) + " continues")) + (if (string-equal (setq t-e-month + (if e-month (car e-month) + t-month)) + t-month) + (fill-dates year t-month (1+ (car + (read-from-string day))) + (car + (read-from-string e-day)) + msg) + (fill-dates year t-month (1+ (car + (read-from-string day))) + (cdr (assoc t-month + '(("Jan" . 31) + ("Feb" . 28) + ("Mar" . 31) + ("Apr" . 30) + ("May" . 31) + ("Jun" . 30) + ("Jul" . 31) + ("Aug" . 31) + ("Sep" . 30) + ("Oct" . 31) + ("Nov" . 30) + ("Dec" . 31)))) + msg) + (fill-dates year t-e-month 1 + (car (read-from-string e-day)) + msg))) + (message "\C-g\C-gCouldn't parse end date: %s" ends))) + ))))) + +(defun fill-dates (year month start end mesg) + "fill the dates between start and end with message in the calendar" + (let ((day start)) + (while (<= day end) + (let* ((dfn (concat ht-Calendar-directory + "/xy" + year + "/xc" + (format "%d" day) + (format "%s" month) + year)) + (buf (find-file-noselect dfn))) + (save-excursion + (set-buffer buf) + (goto-char (point-max)) + (if (not (bolp)) + (insert "\n")) + (insert mesg) + (let ((require-final-newline nil)) + (save-buffer)))) + (setq day (1+ day))))) + +;; private copy +(defun ht-rmail-abort-edit () + "add a hook" + (interactive) + (setq editing-diary-entry nil) + (rmail-abort-edit)) + +(defun rmail-edit-current-message () + "Edit the contents of this message." + (interactive) + (rmail-edit-mode) + (make-local-variable 'rmail-old-text) + (setq rmail-old-text (buffer-substring (point-min) (point-max))) + (setq buffer-read-only nil) + (set-buffer-modified-p (buffer-modified-p)) + ;; Make mode line update. + (if (and (eq (key-binding "\C-c\C-c") 'ht-rmail-cease-edit) + (eq (key-binding "\C-c\C-]") 'ht-rmail-abort-edit)) + (if editing-diary-entry + (message "Editing: Type C-c C-c to move to diary and return to Rmail, C-c C-] to abort") + (message "Editing: Type C-c C-c to return to Rmail, C-c C-] to abort")) + (message (substitute-command-keys + "Editing: Type \\[rmail-cease-edit] to return to Rmail, \\[rmail-abort-edit] to abort")))) + + +(defun build-vcal-message (start end org location description summary uid) + (save-excursion + (let ((fn (concat "/tmp/" (make-temp-name "vcal") ".vcs"))) + (find-file fn) + (insert "BEGIN:VCALENDAR\nMETHOD:PUBLISH\nPRODID:-//Henry S. Thompson//gnus diary hack//EN\nVERSION:0.1\nBEGIN:VEVENT\n") + (insert "UID\n :")(insert uid)(insert "\n") + (insert "SUMMARY")(insert-encoded-maybe summary)(insert "\n") + (insert "DESCRIPTION")(insert-folded description)(insert "\r\n") + (insert "LOCATION")(insert-encoded-maybe location)(insert "\n") + (insert "DTSTART\n :")(insert start)(insert "Z\n") + (insert "DTEND\n :")(insert end)(insert "Z\n") + (insert "DTSTAMP\n :")(insert + (my-time-iso8601 (current-time))) + (insert "Z\n") + ;(insert "ORGANIZER")(insert-encoded-maybe org) + (insert org) + (insert "\n") + (insert "BEGIN:VALARM\nTRIGGER:-PT15M\nACTION:DISPLAY\nDESCRIPTION:Reminder\nEND:VALARM\n") + (insert "BEGIN:VALARM\nTRIGGER:-PT15M\nACTION:AUDIO\nDESCRIPTION:Reminder\nEND:VALARM\n") + (insert "END:VEVENT\nEND:VCALENDAR\n") + (save-buffer) + fn))) + +(defun insert-encoded-maybe (string) + (if (string-match "[\000-\007\n\013\015-\037\200-\377=]" string) + (progn + (insert ";ENCODING=QUOTED-PRINTABLE:") + (let ((beg (point))) + (insert string) + (message (format "%d;%d" beg (point))) + (quoted-printable-encode-region + beg + (point) + t + "^\000-\007\n\013\015-\037\200-\377=")) + (goto-char (point-max))) + (insert "\n :") + (insert string))) + +(defun insert-folded (string) + (insert "\n :") + (let ((beg (point))) + (insert string) + (narrow-to-region beg (point)) + (goto-char (point-min)) + (replace-string "\n" "\\n") + (goto-char (point-min)) + (replace-string "\r" "") + (goto-char (point-min)) + (replace-string "," "\\,") + (goto-char (point-min)) + (while (> (- (point-max) (point)) 72) + (forward-char 70) + (insert "\n ")) + (goto-char (point-max)) + (insert "\r\n") + (widen))) + +(defun my-time-iso8601 (time) + (let ((tzo (car (current-time-zone time))) + (hi (car time)) + (lo (cadr time)) + (ignore (cddr time))) + (gnus-time-iso8601 + (if (>= lo tzo) + (cons hi + (cons (- lo tzo) + ignore)) + (cons (- hi 1) + (cons (- (+ lo 65536) tzo) + ignore))) + )))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shared/gnus-init.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,422 @@ +;; Last edited: Fri Sep 7 12:19:43 2018 +;; gnus customisation + +(setq gnus-novice-user nil) +(setq gnus-message-archive-group + '((concat "general." (format-time-string + "%Y-%m" (current-time))))) + +(setq gnus-summary-ignore-duplicates t + gnus-auto-select-next 'quietly + gnus-save-newsrc-file nil + gnus-read-newsrc-file nil + gnus-save-killed-list nil + gnus-summary-display-arrow nil + gnus-check-new-newsgroups nil + gnus-auto-select-subject 'unseen-or-unread + gnus-your-organization "HCRC, University of Edinburgh" + gnus-buttonized-mime-types '("multipart/signed") + gnus-ignored-headers + "^Errors-To:\\|^Precedence:\\|^UNIX-From:" + gnus-default-directory "/afs/inf.ed.ac.uk/user/h/ht" + nnmail-message-id-cache-file "/disk/scratch/gnus/.nnmail-cache" + mm-discouraged-alternatives '("text/html") + nnmail-expiry-wait 28 + mail-sources + '((file :path "/disk/scratch/mail/ht_mbox")) + mail-source-crash-box "/tmp/crashbox" ; local disk + nndraft-directory "/disk/scratch/drafts/" + message-auto-save-directory "/disk/scratch/drafts/" + message-from-style 'angles + no-select-groups '("nnml+ht:cygwin") + gnus-group-line-format "%M%S%p%P%5y:%uH%(%g%)%l %O +") + +(setq bbdb/news-auto-create-p t) + +(setq wsp-cache nil) + +;;;(setq blacklist-db (open-database "~/.blacklist")) + +(require 'my-news) ; defines db functions + +(open-white) +(open-ad) +(open-quaker) + +(add-hook 'kill-emacs-hook + (lambda () + (if (database-live-p whitelist-db) + (close-database whitelist-db)) + (if (database-live-p quaker-db) + (close-database quaker-db)) + (if (database-live-p adlist-db) + (close-database adlist-db)))) + +(add-hook 'bbdb-complete-name-hooks 'quaker-sig-if-quaker) +(add-hook 'gnus-message-setup-hook 'quaker-sig-if-to-quaker) + +(setq nnmail-crosspost nil) +(setq nnmail-split-methods 'nnmail-split-fancy) + +(setq white-subjects "\\b\\(phd\\|ilcc\\)\\b") + +(setq white-domains (list)) + +(setq ad-domains (list "planetx.co.uk")) + +(setq w3c-lists1 + '((list "w3c-xml-schema-\\([a-zA-Z]+\\)\\(\\.w3\\.org\\)?" "xml-schema-\\1") + (list "chairs\\(\\.w3\\.org\\)?" "w3c-chairs" ) + (to "\\(w3c\\|public\\|member\\)-xml-\\([-a-zA-Z]+\\)\\(\\.w3\\.org\\)?" + "xml-\\2" ) + ;(list "w3t-\\([-a-zA-Z]+\\)\\(\\.w3\\.org\\)?" "w3t-\\1") + ;(list "team-\\([-a-zA-Z]+\\)\\(\\.w3\\.org\\)?" "w3-team-\\1") + ;(list "w3c-\\(xsl-wg\\|format\\|i18n-ig\\)\\(\\.w3\\.org\\)?" "w3c-xsl") + (list "w3c-\\([-a-zA-Z]+\\)\\(\\.w3\\.org\\)?" "w3c-\\1") + (list "member-\\(ac-uk\\|access\\)" "w3-member-\\1");[-a-zA-Z]+\\) + (to "public-xpointer-registry\\(-request\\)?" + "xpointer-registry");[-a-zA-Z]+ + (to "public-\\([-a-zA-Z]+\\)" "w3-public-\\1") + (to "w3c-xml-schema-\\([a-zA-Z]+\\)" "xml-schema-\\1") + (to "chairs" "w3c-chairs") + (to "w3c-xml-\\([-a-zA-Z]+\\)" "xml-\\1" ) + (to "www-xml-\\([-a-zA-Z]+\\)" "xml-\\1") + ;(list "www-\\([-a-zA-Z]+\\)" "www-\\1") + ;(to "w3c-\\(xsl-wg\\|format\\|i18n-ig\\)" "w3c-xsl") + ;(to "w3t-\\([-a-zA-Z]+\\)" "w3t-\\1") + ;(to "team-\\([-a-zA-Z]+\\)" "w3-team-\\1") + ;(to "w3c-\\([-a-zA-Z]+\\)" "w3c-\\1") + ;(to "xml-\\([-a-zA-Z]+\\)" "w3c-\\1") + ;(to "member-\\([-a-zA-Z]+\\)" "w3-member-\\1") + ;(to "ercim-\\([-a-zA-Z]+\\)" "ercim-\\1") + ;(to "w3t" "w3t") + )) + +(setq w3c-lists2 + '((to "w3t-archive" "w3t-archive") + (to "w3c-archive" "w3c-archive"))) + +(setq xml-lists1 + '(;(to "xml-uri" "nsuri") + (to ".*editor.*" "xml-rec-comments") + (to "xml-dev" "xml") + (to "xsl-list" "xsl") + ;(to "[Xx]emacs[- ]beta" "xemacs") + (to "xmlschema-dev" "schema-dev") + (to "xproc-dev" "xproc-dev") + ;(to "xml-sig" "xml-python") + ;(to "xml-plenary" "xml-plenary") + )) + +(setq xml-lists2 + '((list "ietf-xml-mime\\.imc\\.org" "xml-mime") + (list "xml-mime\\.ietf\\.org" "xml-mime"))) + +(setq misc-list1 + '(;(from "w3t-\\([a-zA-Z]+\\)-request" "w3t-\\1") + ;(from "w3c-\\([a-zA-Z]+\\)-request" "w3c-\\1") + ;(from "xml-\\([a-zA-Z]+\\)-request" "xml-\\1") + ;(from "p.woolman" "nhs-xml") + (from "Cron Daemon" "cron") + (from ".*@mail.gumtree.com" "personal") + (from ".*@postman.storyworth.com" "storyworth") + ;(from "\\(Richard\\.Kirkham\\|rachel\\.johnson\\|maria\\.papadaki\\|marisol\\.leonen\\|sangeeta\\.tewar\\|abdullah\\.alshamsi\\|.*@buid\\.ac\\.ae\\)" "buid") + (to "www-tag" "tag") + ;(to "webarch@noreply.github.com" "tag") + ;(to "dashboard-hackers" "beagle") + ;(to "pellet-users" "pellet") + (to "tkinter-discuss" "tkinter") + ;(to "sdp-students" "sdp") + (to "fnlp-students" "fnlp") + ;(from "fox@tardis\\.ed\\.ac\\.uk\\|s1505551" "fnlp") + (to "anlp-students" "anlp") + ;(from "nbnotifications" "anlp") + ;(: split-on-whole-field "Subject" "Re: MSc Project 18.*" "msc18") + (: split-on-whole-field "Subject" ".*FNLP.*" "fnlp") + ;(: split-on-whole-field "Subject" ".*SDP \\(MS .\\|final\\) evaluation" "sdpEval") + ;(: split-on-whole-field "Subject" ".*[[]SDP[]] \\(Your evaluation\\|Evaluation deadline\\).*" "sdpEval") + ;(: split-on-whole-field "Subject" ".*SDP.*" "sdp") + (: split-on-whole-field "Subject" ".*Welcome to ANLP, action needed.*" "anlp_github") + (: split-on-whole-field "Subject" ".*ANLP.*" "anlp") + (from "ANLP on Piazza" "anlp") + ;(from "FNLP on Piazza" "fnlp") + ;(from "no-reply@piazza.com" "anlp") + (: split-on-whole-field "Subject" ".*Personal Tutor.*" "tutees20") + (: split-on-whole-field "Subject" ".*Course Selection.*" "tutees20") + ;(: split-on-whole-field "Subject" ".*Sutton Trust.*" "inf-recruit") + (: split-on-whole-field "Subject" "mycron .*" "cron") + ;(: split-on-whole-field "Subject" "INF1-Cg experiment.*" "cgx_2013") + (: split-on-whole-field "Subject" ".*[[]urn[]].*" "urn") + (from "\\(106300.457@compuserve.com\\|elizdrummondyoung@gmail.com\\|jcdavey12@btinternet.com\\|andrewdolan@btinternet.com\\|wandbamoyes@btinternet.com\\)" "albertus") + (to "corpus-admin" "corpora") + (: split-on-whole-field "Subject" ".*Albertus.*" "albertus") + (: split-on-whole-field "Subject" ".*\\[corpus-admin\\].*" "corpora") + ;(to ".*@\\(hst\\|hthompson\\|henry\\.thompson\\)\\.name" "personal") + (from "mikereape@.*" "mikereape") + (from "\\(.*@mumble\\.net\\|jar@\\.csail\\.mit\\.edu\\)" "jar") + (from ".*@coulters.io" "belford") + (from ".*@umega.co.uk" "belford") + (to ".*@umega.co.uk" "belford") + (: split-on-whole-field "Subject" ".*belford.*" "belford") + )) + +(setq quaker-list + '((to "quaker-\\(l\\|spectrum\\)" "quaker") + ;(to "quaker-b" "quaker-b") + ;(to "QuakerBYM" "quaker-b") + ;(from "quaker-spectrum-approval" "quaker") + )) + +(setq sms-list + '((from "s1513009@.*" "ug4_18");\\|s1536017\\(s1443062\\|s1679328 + ;(from "Y.Chen-258@.*" "msc_19") + (from "\\(s1795066\\|s1825415\\|A.M.Magalhaes\\|T.Makino\\|S.Li-93\\|M.Maggiolo\\|ashe\\|Y.Li-242\\|E.J.Martin\\|K.Lohse\\|D.Li-28\\|S.D.Martin-1\\|K.Chen-35\\|J.Norris-3\\|S.Li-80\\|Y.Liu-236\\|J.Chen-114\\|Q.Zeng-3\\|Y.Liu-244\\|P.Guo-1\\|s1582739\\|B.Lun\\|X.Li-143\\|F.Li-17\\|K.R.Lu\\|Z.Li-86\\)@.*" "tutees18") + (from "\\(s1895309\\|s1765180\\|s1764494\\|s1645474\\|s1953043\\|s1651774\\|s1732316\\|s1742667\\)@.*" "tutees20") + )) + +(defalias 'tut20 (read-kbd-macro +"C-x o C-s < RET C-s @ C-b C-x C-x M-w C-x b gnus SPC RET C-s \"tutees20 RET C-r \\\\) RET \\\\| C-y C-a ESC ESC : nil RET ESC C-x M-x ht- 3*<backspace> set- ht SPC RET C-x C-s C-x b RET C-x o")) + +;;; groups only, comes _after_ split to pers-... for to: ht... +(setq misc-list2 + '(;(to "cogsci.general" "junk") + (from "anrdaemon@yandex.ru\\|gsenopu@gmail.com\\|pradeepan88@hotmail.com" "anr-doom") + ;(to "bp-people" "bp-people") + ;(to "ppelders" "ppelders") + ;(to "7vtw" "7vtw") + (to "\\(apps-review\\|uri-review\\|apps-discuss\\|discuss\\|architecture-discuss\\|appsdir\\|art\\)@[a-z.]*\\(ietf\\|iab\\).org" "ietf") + (to "urn@ietf.org" "urn") + (to "if-people" "if-people") + (to "maptask" "maptask") + ;(to "i18n-sig" "xml-python") + ;(to "spec-prod" "spec-prod") + ;(to "markup" "markup") + ;(to "system-notices" "w3c-sys-notes") + (to "[cC]ygwin" "cygwin") + ;(to "jde@sunsite.dk" "jde") + ;(to "jdee-users@lists.sourceforge.net" "jde") + (to "tagsoup-friends@yahoogroups.com" "tagsoup") + (to "screen-users@gnu.org" "screen") + (from "mailinglist@edinburghrc.co.uk" "erc") + (to "selenium-users" "selenium") + ;(to "ding" "gnus") + ;(to "dssslist" "dsssl") + ;(to "TEI-L" "tei") + (to "\\(announcements\\|unicode\\)@unicode.org" "unicode") + ;(to "squid-users@lists.squid-cache.org\\|squid-users@squid-cache.org" + ; "squid") + (to "exist-open" "exist") + (list "ilcc-\\([a-zA-Z]+\\)" "ilcc-\\1") + (to "ilcc" "ilcc") + (to ".*lecturers@inf.ed.ac.uk" "inf-teach") + (to "\\(aisyllabus\\|acstaff\\)" "inf-teach") + (to "\\(inf\\)?\\(pg\\|msc\\|teach\\|res\\|staff\\)\@inf\\(ormatics\\)?" + "inf-\\2" ) + ;(to "directors-of-studies" "inf-dos") + (to "common-crawl@googlegroups.com" "ccrawl") + ;(list "inkscape-user\\|openbox\\|ffmpeg-user" "misc-list") + )) + +(defvar ht-compiled-split nil) + +(defun set-ht-compiled-split () + "update the mail splitting rules" + (interactive) + (setq ht-compiled-split + (let* ((month + (format-time-string "%Y-%m" (current-time))) + (now-group (concat "group-" month)) + (now-pers (concat "pers-" month))) + `(| + (: split-on-whole-field "Subject" "testing" "junk") +;;; ("Content-Type" content-spam "gnSPAM") +;;; ("Content-Transfer-Encoding" encoding-spam "gnSPAM") +;;; (: split-on-whole-subj 'subject-spam "gnSPAM") + ;; Special to people who use Yahoo +;;; ("X-YahooFilteredBulk" ".*" "gnSPAM") +;;; (from author-spam "gnSPAM") + ;; A subject with no letters is SPAM +;;; (: split-on-whole-subj "^[^a-zA-Z]+$" "gnSPAM") + ;; It would be cool to check the + ;; date and toss it if it is "old" + (to "\\(w3[ct]\\|www\\|team\\|member\\|public\\|ercim\\)[^ ]*@.*" + (| ,@w3c-lists1 + (to "ht\\|henry\\|\\(h\\.?\\)?thompson?" ,now-pers) + ,@w3c-lists2 + (to "x.*@.*" (| ,@xml-lists1 + (to "ht\\|henry\\|\\(h\\.?\\)?thompson?" ,now-pers) + ,@xml-lists2 + ,now-group)))) + (to "x.*@.*" (| ,@xml-lists1 + (to "ht\\|henry\\|\\(h\\.?\\)?thompson?" ,now-pers) + ,@xml-lists2)) + ,@misc-list1 + (to "ht\\|henry\\|\\(h\\.?\\)?thompson?" + (| (from ".*@sms.ed.ac.uk" (| + ,@sms-list + ,now-pers)) + + ,now-pers)) + (to "quaker.*" (| + ,@quaker-list + ,now-group)) + ,@misc-list2 + ,now-group + )))) + +(set-ht-compiled-split) + +(setq nnmail-split-fancy + '(! + (lambda (sres) + (if (or (equal (car sres) "notSPAM") + (equal (car sres) "waSPAM")) + ;; documentation is wrong, no recursion, + ;; so we do it ourselves :-( + (nnmail-split-it ht-compiled-split) + sres)) + (| (: ad-spam "adverts") + (: white-spam "waSPAM") + ("X-Bogosity" "Yes.*" + (| + (From ".*ed\.ac\.uk" "edSPAM") ; NB From not from + ("X-Spam-Score" "0" "boSPAM") + "bfSPAM")) + (: split-on-whole-field "X-Spam-Level" "\\*\\*\\*\\*.*" + "saSPAM") + ("X-Spam-Status" "Yes.*" "saSPAM") + "notSPAM"))) + +(setq gnus-show-mime t) ; stale +(setq mml1991-use 'pgg + mml2015-use 'pgg + mm-verify-option 'always) + +(require 'mm-decode) +(setq mm-automatic-display (remove "text/html" mm-automatic-display)) + +(custom-set-faces) + +(add-hook 'gnus-group-mode-hook 'gnus-topic-mode) + +(add-hook 'gnus-summary-mode-hook 'gnus-summary-mode-fun1) + +;;; After hiding pgp, verify the message; +;;; only happens if pgp signature is found. + +;(add-hook 'gnus-article-hide-pgp-hook +; (lambda () +; (save-excursion +; (set-buffer gnus-original-article-buffer) +; (mc-verify)))) + + +(add-hook 'message-mode-hook 'message-mode-fun1) + +(add-hook 'gnus-group-mode-hook 'gnus-group-mode-fun1) +(add-hook 'gnus-select-group-hook 'no-select) + +(add-hook 'gnus-parse-headers-hook + '(lambda () + (gnus-summary-set-local-parameters gnus-newsgroup-name))) + + +;(add-hook 'gnus-summary-mode-hook 'mc-install-read-mode) +;(add-hook 'message-mode-hook 'mc-install-write-mode) +;(add-hook 'news-reply-mode-hook 'mc-install-write-mode) + +;;; Jack Vinson's (partial Fancy mail rules for killing SPAM) +;; Content with any of the following is probably SPAM + +(require 'nnmail) +(if (not (assq 'list nnmail-split-abbrev-alist)) + (setq nnmail-split-abbrev-alist + (cons '(list . "List-Id") nnmail-split-abbrev-alist))) + +(add-hook 'nnmail-split-abbrev-alist + (cons 'content-spam "text/html\\|big5\\|gb2312\\|ks_c_.*\\|euc-kr")) + +;; Encoding with any of the following is probably SPAM +(add-hook 'nnmail-split-abbrev-alist + (cons 'encoding-spam "binary\\|base64")) + +;; These special subjects are SPAM: +;; funny characters, whitespace followed by a string, no letters +;; and any words that are always SPAM +(add-hook 'nnmail-split-abbrev-alist + (cons 'subject-spam ".*\\([\177-\277\367]\\|=\\?big5\\?\\).*")) + +;; Bad authors who still get through all of this +(add-hook 'nnmail-split-abbrev-alist + (cons 'author-spam "explicit\\|amazing")) + +;; from w/o Resent-From +(add-hook 'nnmail-split-abbrev-alist + (cons 'From "from\\|sender")) + +;; And the actual splitting rule +;(setq nnmail-split-fancy +; '(| +; ;; Various mailing lists, match on Subject or Sender headers + ; (from mail "Boing") + ; (any "my_mailing_list@foo.com" "list_group") +; + ; ;; SPAM, SPAM, SPAM + ; ("Content-Type" content-spam "gnSPAM") + ; ("Content-Transfer-Encoding" encoding-spam "gnSPAM") + ; ("Subject" subject-spam "gnSPAM") + ; ;; Special to people who use Yahoo + ; ("X-YahooFilteredBulk" ".*" "gnSPAM") + ; (from author-spam "gnSPAM") + ;; A subject with no letters is SPAM +; ("Subject" "^[^a-zA-Z]+$" "gnSPAM") + ;; It would be cool to check the date and toss it if it is "old" + ;; Several spammers send mail that has ancient dates... + + ;; Additional splitting rules on Subject for convenience. + + ;; Everything else should be coming to me + ; (to "jackvinson" "misc") + + ;; Else it is SPAM + ; "gnSPAM") +; ) + +(add-hook 'message-sent-hook (function whiten-recip)) + +(add-hook 'gnus-get-new-news-hook (lambda () (setq ht-gnus-just-read nil))) +(add-hook 'gnus-after-getting-new-news-hook + (lambda () (message "%s" ht-gnus-just-read))) + +(add-hook 'nnml-prepare-save-mail-hook (function ht-gnus-note-save-to-group)) + +(require 'gnus-art) + +(nconc gnus-treatment-function-alist + '((gnus-treat-strip-uoe-warning gnus-article-strip-uoe-warning))) + +(defun gnus-article-strip-uoe-warning (&optional interactive &rest args) + "redirect for stripping" + (interactive (list t)) + (save-excursion + (set-buffer gnus-article-buffer) + (if interactive + (call-interactively 'article-strip-uoe-warning) + (apply 'article-strip-uoe-warning args)))) + +(defun article-strip-uoe-warning () + "strip the stupid uoe warning" + (interactive) + (save-excursion + (article-goto-body) + (let ((case-fold-search t)) + (when + (looking-at "This email was sent to you by someone outside the University.") + (gnus-delete-line)) + (when + (looking-at "You should only click on links or attachments if you are certain that the email is genuine and the content is safe.") + (gnus-delete-line)) + ))) + +(setq gnus-treat-strip-uoe-warning t)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shared/hackbs.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,12 @@ +;;; Last edited: Tue Sep 9 10:22:22 2003 +;;; Hack bs vs ctrl-h + +(provide 'hackbs) +(defun hack-ctlh (prompt) + (if (eq (device-or-frame-type (frame-device)) 'tty) + [(backspace)] + [(control h)])) + +(define-key key-translation-map [(control h)] 'hack-ctlh) + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shared/hist.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,161 @@ +;;; a tcsh-type history key facility for sub-shells +;; Last edited: Wed Nov 14 09:52:12 1990 + +(provide 'hist) +(require 'prompt-for-word) + +(defvar hk-last-mb nil "*begin of last hk match") + +(defvar hk-last-mark nil "*beginning of last hk insertion") + +(defvar hk-search-pat nil "*regexp for hk search") + +(defvar hk-last-point 0 "*end of last hk insertion") + +(defvar hkr-last-point 0 "*end of last hk pattern search insertion") + +(defvar hkr-search-pat nil "*regexp for hk user pattern search") + +(defvar hk-last-user-pat nil "*user part of last pattern search") + +(make-local-variable 'hk-last-mb) +(make-local-variable 'hk-last-mark) +(make-local-variable 'hk-last-point) +(make-local-variable 'hk-search-pat) +(make-local-variable 'hkr-search-pat) +(make-local-variable 'hkr-last-point) +(make-local-variable 'hk-last-user-pat) + +(defvar hk-pat-table '(("*shell*" . ".*: ") + ("*prolog*" . "| \\?- ") + ("*lisp*" . ">") + ("*inferior-lisp*" . ">")) + "default crux of prompt pattern, by buffer name") + +(defun hist-key (&optional rpt) + "offer a previous input, a la tcsh ^P" + (interactive "p") + (if (not rpt) (setq rpt 1)) + (let ((here (point)) + (pat (or hk-search-pat + (setq hk-search-pat + (concat "^" (or (cdr (assoc (buffer-name + (current-buffer)) + hk-pat-table)) + "") + "\\(.+\\)$"))))) + (hk-find-b rpt here pat))) + +(defun hk-find-b (rpt here pat) + "search backwards for pat, no dups, rpt times" + (while (> rpt 0) + (goto-char (if (= (point) hk-last-point) + hk-last-mb + (if (eobp) + (progn (beginning-of-line) + (setq hk-last-mark nil) + (point)) + (error "nowhere??")))) + (let ((keep-trying t)) + (while keep-trying + (if (re-search-backward pat nil t) + (let ((entry (buffer-substring (match-beginning 1) + (match-end 1)))) + (setq hk-last-mb (match-beginning 0)) + (goto-char (or hk-last-mark here)) + (if (looking-at (regexp-quote entry)) + (goto-char hk-last-mb) + (setq keep-trying nil) + (if hk-last-mark (delete-region hk-last-mark hk-last-point)) + (setq hk-last-mark (point)) + (push-mark (point) t) + (insert entry) + (setq hk-last-point (point)))) + (unwind-protect (error "no more??") + (goto-char (if hk-last-mark + hk-last-point + here)))))) + (setq rpt (1- rpt)))) + +(defun hist-key-back (&optional rpt) + "offer a previous input, a la tcsh ^N" + (interactive "p") + (if (not rpt) (setq rpt 1)) + (let ((here (point)) + (pat (or hk-search-pat + (error "no pattern")))) + (while (> rpt 0) + (goto-char (if (= (point) hk-last-point) + hk-last-mb + (error "lost context"))) + (let ((keep-trying t)) + (while keep-trying + (end-of-line) + (if (re-search-forward pat nil t) + (let ((entry (buffer-substring (match-beginning 1) + (match-end 1)))) + (setq hk-last-mb (match-beginning 0)) + (goto-char (or hk-last-mark here)) + (if (looking-at (regexp-quote entry)) + ;; allow for back to square one + (if (progn (end-of-line) + (eobp)) + (progn (setq keep-trying nil) + (if hk-last-mark + (delete-region hk-last-mark hk-last-point) + (error "shouldnt")) + (goto-char hk-last-mark)) + (goto-char hk-last-mb)) + (setq keep-trying nil) + (if hk-last-mark (delete-region hk-last-mark hk-last-point)) + (setq hk-last-mark (point)) + (push-mark (point) t) + (insert entry) + (setq hk-last-point (point)))) + (unwind-protect (error "no more??") + (goto-char (if hk-last-mark + hk-last-point + here)))))) + (setq rpt (1- rpt))))) + +(defun hist-key-search (&optional rpt pat) + "offer a previous input, searching backwards for a pattern" + (interactive "p") + (if (not rpt) (setq rpt 1)) + (let ((here (point)) + (full-pat + (if (= (point) hkr-last-point) + hkr-search-pat + (setq hkr-search-pat + (if (eobp) + (concat "^" + (or (cdr (assoc (buffer-name + (current-buffer)) + hk-pat-table)) + "") + "\\(.*" + (setq hk-last-user-pat + (or pat + (regexp-quote + (prompt-for-word + "Pattern: " + (or hk-last-user-pat "") + nil nil)))) + ".*\\)$") + (error "nowhere??")))))) + (hk-find-b rpt here full-pat) + (setq hkr-last-point hk-last-point))) + +(require 'shell) + +(define-key shell-mode-map "\ep" 'hist-key) +(define-key shell-mode-map "\en" 'hist-key-back) +(define-key shell-mode-map "\es" 'hist-key-search) +(define-key shell-mode-map "\e\C-i" 'shell-expand-file-name) + +;;; hack in case we've been given com-int +(if (not (boundp 'inferior-lisp-mode-map)) + (require 'inf-lisp)) +(define-key inferior-lisp-mode-map "\ep" 'hist-key) +(define-key inferior-lisp-mode-map "\en" 'hist-key-back) +;; note that prolog copies shell-mode-map, so no need to fix that
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shared/ht-rooms.config Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,36 @@ +(define-rooms '(("elisp" ("*scratch*" nil 0 0 80 47)) + ("text" ((" ") nil 0 0 80 47)) + ("diary" + ("diary.babyl" + (progn (rmail-input ht-diary-file-name) + (setq ht-last-file + (expand-file-name + "~/mail/history/diary.msg"))) + 0 0 80 11) + ("diary.babyl-summary" + (update-default-diary t) 0 11 80 23)) + ("news" ("*Group*" + (progn + (require 'my-news) + (gnus)) 0 0 80 47)) + )) + +;;; next two should be parameterised for screen height + +(defun make-lisp-room () + "create and go to a room for lisp work" + (interactive) + (establish-room '("lisp" + ("*lisp*" (run-lisp) 0 0 80 23) + ((" ") (lisp-mode) 0 23 80 47)) + t)) + +(defun make-prolog-room () + "create and go to a room for prolog work" + (interactive) + (establish-room '("prolog" + ("*prolog*" (run-prolog) 0 0 80 23) + ((" ") (prolog-mode) 0 23 80 47)) + t)) + +(rooms-goto (assoc "news" rooms-table) nil)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shared/mail-extras.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,503 @@ +;; Last edited: Fri Nov 2 10:26:24 1990 +;; extra widgets for rmail and rmailsum +;; Copyright (C) 1990 Henry S. Thompson + +;; This file is part of GNU Emacs. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY. No author or distributor +;; accepts responsibility to anyone for the consequences of using it +;; or for whether it serves any particular purpose or works at all, +;; unless he says so in writing. Refer to the GNU Emacs General Public +;; License for full details. + +;; Everyone is granted permission to copy, modify and redistribute +;; GNU Emacs, but only under the conditions described in the +;; GNU Emacs General Public License. A copy of this license is +;; supposed to have been given to you along with GNU Emacs so you +;; can know your rights and responsibilities. It should be in a +;; file named COPYING. Among other things, the copyright notice +;; and this notice must be preserved on all copies. + +(provide 'mail-extras) +(require 'rmail) +(require 'sendmail) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; mods and fixes for reading mail ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defvar ht-last-file (expand-file-name "~/XMAIL") + "default for moving mail to") +(make-variable-buffer-local 'ht-last-file) + +(defvar rmht-always-recompress t + "If non-nil, when saving into compressed babyl file, +always recompress and save immediately") + +(defvar rmht-allow-autosave t + "if non-nil, leaves autosave alone for compressed babyl files, +otherwise turns it off") + +(add-hook 'rmail-mode-hook 'rmail-mode-fun1) +(add-hook 'rmail-mode-hook 'rmail-mode-fun2) + +;; run the first time in to RMAIL +(defun rmail-mode-fun1 () + "add ht's mods to RMAIL" + (define-key rmail-mode-map "R" 'reply-w/o-cc) + (define-key rmail-mode-map "M" 'rmht-output) + (define-key rmail-mode-map "H" 'print-buffer) + (define-key rmail-mode-map "W" 'edit-and-move-to-diary) + (define-key rmail-mode-map "D" 'update-default-diary) + (define-key rmail-mode-map "F" 're-post-failed-mail) + (define-key rmail-mode-map "B" 'ht-write-body-to-file) + (define-key rmail-mode-map "E" 'extract-attachment) + ;; fix the doc string + (repl-comment 'rmail-mode + "Rmail Mode is used by \\[rmail] for editing Rmail files. +All normal editing commands are turned off. +Instead, these commands are available (additions from ht's mail-extras.el +indicated by *: + +. Move point to front of this message (same as \\[beginning-of-buffer]). +SPC Scroll to next screen of this message. +DEL Scroll to previous screen of this message. +n Move to Next non-deleted message. +p Move to Previous non-deleted message. +M-n Move to Next message whether deleted or not. +M-p Move to Previous message whether deleted or not. +> Move to the last message in Rmail file. +j Jump to message specified by numeric position in file. +M-s Search for string and show message it is found in. +d Delete this message, move to next nondeleted. +C-d Delete this message, move to previous nondeleted. +u Undelete message. Tries current message, then earlier messages + till a deleted message is found. +e Expunge deleted messages. +s Expunge and save the file. +q Quit Rmail: expunge, save, then switch to another buffer. +C-x C-s Save without expunging. +g Move new mail from system spool directory or mbox into this file. +m Mail a message (same as \\[mail-other-window]). +c Continue composing outgoing message started before. +r Reply to this message. Like m but initializes some fields. +R * Like r, but reply to originator only. +f Forward this message to another user. +F * like f, but assumes message is \"failed mail\" for re-sending +o Output this message to an Rmail file (append it). +C-o Output this message to a Unix-format mail file (append it). +M * Output this message to a file, + in format determined by extension (babyl for RMAIL/msg for Unix). +B * Write the body of the message to a file, leaving a pointer +H * Print the message (same as \\<global-map>\\[print-buffer]).\\<rmail-mode-map> +i Input Rmail file. Run Rmail on that file. +a Add label to message. It will be displayed in the mode line. +k Kill label. Remove a label from current message. +C-M-n Move to Next message with specified label + (label defaults to last one specified). + Standard labels: filed, unseen, answered, forwarded, deleted. + Any other label is present only if you add it with `a'. +C-M-p Move to Previous message with specified label +h, C-M-h Show headers buffer, with a one line summary of each message. +l, C-M-l Like h only just messages with particular label(s) are summarized. +C-M-r Like h only just messages with particular recipient(s) are summarized. +t Toggle header, show Rmail header if unformatted or vice versa. +w Edit the current message. C-c C-c to return to Rmail. +W * Edit the subject field. C-c C-c to move the message to the Diary. +D * Update the Diary. + +Messages for the diary (see also \\[describe-mode] in rmail-summary mode +or \\[describe-function] rmail-summary-mode) should have a subject field +which begins with the date and optional time of the event described therein. +These must be in the form + d m y t +where d is one or two digits for the day, +m is either the full month name or the first three letters thereof, +y is two digits for the year, +and t, if present, is 4 digits for the time, +thus for example + 31 Jun 91 1530 +") + (remove-hook 'rmail-mode-hook 'rmail-mode-fun1)) + +(defun rmail-mode-fun2 () + "always run in RMAIL mode" + (setq case-fold-search t)) + +(defun reply-w/o-cc () + "Reply as r, but without sending to other recipients" + (interactive) + (rmail-reply t)) + +(defun rmht-output (&optional file-name gnus) + "Move to a file, determining format by extension (babyl/msg)" + (interactive) + (if (not file-name) + (setq file-name (car (get-move-file-name)))) + (if (string-match "\\.g?[zZ]$" file-name) + (let ((clean-file-name (substring file-name 0 (match-beginning 0))) + there) + (if (setq there (get-file-buffer clean-file-name)) + nil + (save-window-excursion (rmail clean-file-name) + (setq there + (get-file-buffer clean-file-name)))) + (rmht-output clean-file-name gnus) + (if rmht-always-recompress + (save-excursion + (set-buffer there) + (save-buffer)) + (if (not rmht-allow-autosave) + (save-excursion + (set-buffer there) + (auto-save-mode -1))))) + (setq file-name (expand-file-name file-name)) + (save-excursion + (if (string-match "\\.babyl$" file-name) + (if gnus + (gnus-output-to-rmail file-name) + (rmail-output-to-rmail-file file-name 1)) + (if (string-match "\\.msg$" file-name) + (if (or (get-file-buffer file-name) + (file-exists-p file-name) + (yes-or-no-p + (concat "\"" file-name "\" does not exist, create it? "))) + (rmail-output file-name 1) + (error "Output file does not exist")) + (error "not a valid mail file: %s" file-name)))) + (setq ht-last-file file-name) + (if (not gnus) (ht-rmail-delete-forward)))) + +(defun get-move-file-name () + "get a file name for moving a message to" + (list (read-file-name + (concat "Output message to file: (default " + (file-name-nondirectory ht-last-file) + ") ") + (file-name-directory ht-last-file) + ht-last-file))) + +(defun re-post-failed-mail () + "try to salvage the original from failed mail and prepare to resend it" + (interactive) + (rmail-forward nil) + (let ((top (point)) + subjp textp) + (re-search-forward "^Subject: ") + (kill-line nil) + (setq subjp (point)) + (re-search-forward "^From: ") ; the bouncer + (re-search-forward "^From: ") ; should be us + (re-search-forward "^Subject: ") + (kill-line nil) + (save-excursion (goto-char subjp) + (yank)) + (beginning-of-line 3) + (setq textp (point)) + (goto-char top) + (re-search-forward (concat "^" (regexp-quote mail-header-separator) "$")) + (beginning-of-line 2) + (delete-region (point) textp) + (goto-char top))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; mods and fixes for mail summaries ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(add-hook 'rmail-summary-mode-hook 'rmail-summary-mode-fun1) + +;; run the first time we make a summary window +(defun rmail-summary-mode-fun1 () + "install ht's mods" + (define-key rmail-summary-mode-map "r" 'rms-reply-w-cc) + (define-key rmail-summary-mode-map "R" 'rms-reply-w/o-cc) + (define-key rmail-summary-mode-map "s" 'diary-save) + (define-key rmail-summary-mode-map "m" 'rms-move) + (define-key rmail-summary-mode-map "d" 'rms-delete) + (define-key rmail-summary-mode-map "h" 'rms-hardcopy) + (define-key rmail-summary-mode-map " " 'ht-rmailsum-scroll-msg-up) + (define-key rmail-summary-mode-map "\177" 'ht-rmailsum-scroll-msg-down) + ;; fix the doc string + (repl-comment 'rmail-summary-mode + "Major mode in effect in Rmail summary buffer. +A subset of the Rmail mode commands are supported in this mode. +As commands are issued in the summary buffer the corresponding +mail message is displayed in the rmail buffer. +Modifications from ht's mail-extras.el indicated with *: + +n Move to next undeleted message, or arg messages. +p Move to previous undeleted message, or arg messages. +C-n Move to next, or forward arg messages. +C-p Move to previous, or previous arg messages. +j Jump to the message at the cursor location. +d Delete the message at the cursor location and move to next message. +u Undelete this or previous deleted message. +q Quit Rmail. +x Exit and kill the summary window. +space * If cursor is on line of current message, + scroll message window forward. Otherwise, jump to indicated message. +delete * same as space, but scrolls backward. +r * Same as r in rmail window. Reply to current message. +R * Same as R in rmail window. Reply to current message, originator only. +s * Update and save the rmail file, and re-summarise. Re-sorts if Diary. +m * Same as M in rmail window. Moves message to file. +h * Same as H in rmail window. Prints message on line printer. + +Entering this mode calls value of hook variable rmail-summary-mode-hook. + +If the file summarised is called by the name given in ht-diary-file-name, +which defaults to diary.babyl, +then the summary will be called *Diary*, sorted in date order and +formated in a special way. + +Messages in the diary should have a subject field +which begins with the date and optional time of the event described therein. +These must be in the form + d m y t +where d is one or two digits for the day, +m is either the full month name or the first three letters thereof, +y is two digits for the year, +and t, if present, is 4 digits for the time, +thus for example +Subject: 31 Jun 91 1530 Hades freezing ceremony followed by champagne reception +") + (remove-hook 'rmail-summary-mode-hook 'rmail-summary-mode-fun1)) + +(defun rmht-sum-reply (sender-only) + "reply to current message" + (rmail-summary-goto-msg) + (pop-to-buffer rmail-buffer) + (rmail-reply sender-only) + (switch-to-buffer rmail-summary-buffer) + (switch-to-buffer "*mail*") +) + +(defun rms-reply-w-cc () + "Do r in RMAIL - reply to everybody" + (interactive) + (rmht-sum-reply nil)) + +(defun rms-reply-w/o-cc () + "Do R in RMAIL - reply to sender only" + (interactive) + (rmht-sum-reply t)) + +(defun rms-save () + "expunge deleted messages, save RMAIL file and re-display headers" + (interactive) + (pop-to-buffer rmail-buffer) + (rmail-expunge-and-save) + (rmail-summary)) + +(defun rms-delete () + "delete current and move down to next in summary buffer" + (interactive) + (rmail-summary-goto-msg) + (save-excursion + (rmail-summary-delete-forward nil)) + (rms-del)) + +(defun rms-move () + "Move to a file, mode determined by file extension (babyl/msg)" + (interactive) + (rmail-summary-goto-msg) + (save-excursion + (set-buffer rmail-buffer) + (rmht-output)) + (rms-del)) + +(defun rms-del () + "mark current summary line as deleted and move down" + (let ((buffer-read-only nil)) + (skip-chars-forward " ") + (skip-chars-forward "[0-9]") + (delete-char 1) + (insert "D")) + (forward-line 1)) + +(defun rms-hardcopy () + "hardcopy the current message" + (interactive) + (pop-to-buffer rmail-buffer) + (print-buffer) + (pop-to-buffer rmail-summary-buffer)) + + +;; fix interpretation of SPACE and DEL in summary windows to +;; 1) scroll the right window regardless of how many panes are up; +;; 2) go to the message associated with the current line if not already there, +;; a la gnus, for instance + +(defun ht-rmailsum-normalise () + "if not already showing message named on current line, go to it & return t" + (beginning-of-line) + (let ((current-msg-num (cdr (assoc 'rmail-current-message + (buffer-local-variables + (or rmail-buffer + (error + "not in a summary buffer")))))) + (line-message-num (string-to-int + (buffer-substring + (point) + (min (point-max)(+ 5 (point))))))) + (if (= current-msg-num line-message-num) + nil + (rmail-summary-goto-msg line-message-num) + t))) + +(defun ht-rmailsum-scroll-msg-up (&optional dist) + "goto other message or scroll current message forward" + (interactive "P") + (if (ht-rmailsum-normalise) + nil + (pop-to-buffer rmail-buffer) + (scroll-up dist) + (pop-to-buffer rmail-summary-buffer))) + +(defun ht-rmailsum-scroll-msg-down (&optional dist) + "goto other message or scroll current message backward" + (interactive "P") + (if (ht-rmailsum-normalise) + nil + (pop-to-buffer rmail-buffer) + (scroll-down dist) + (pop-to-buffer rmail-summary-buffer))) + +(autoload 'edit-and-move-to-diary "diary") +(autoload 'update-diary "diary") +(autoload 'diary-save "diary") + +;; unfortunately, gnus mucks about with the buffers before calling +;; mail, so we have to intervene to make the about-to-mail-hook work right + +(defun ht-Subject-mode-fun () + "fix the map to save window state" +; (define-key gnus-summary-mode-map "r" 'ht-Subject-mail-reply) +; (define-key gnus-summary-mode-map "R" 'ht-Subject-mail-reply-with-original) +; (define-key gnus-summary-mode-map "m" 'ht-Subject-mail-other-window) + (define-key gnus-summary-save-map "M" 'ht-Subject-move) + (remove-hook 'gnus-summary-mode-hook 'ht-Subject-mode-fun)) + +(add-hook 'gnus-summary-mode-hook 'ht-Subject-mode-fun) + +(defun ht-Subject-mail-reply (yank) + "Runs about-to-mail-hook, then calls gnus-summary-mail-reply" + (interactive "P") + (require 'sendmail) + (run-hooks 'about-to-mail-hook) + (let (about-to-mail-hook) + (gnus-summary-reply yank))) + +(defun ht-Subject-mail-reply-with-original () + "Runs about-to-mail-hook, then calls gnus-summary-mail-reply-with-original" + (interactive) + (require 'sendmail) + (run-hooks 'about-to-mail-hook) + (let (about-to-mail-hook) + (gnus-summary-reply-with-original))) + +(defun ht-Subject-mail-other-window () + "Runs about-to-mail-hook, then calls gnus-summary-mail-other-window" + (interactive) + (require 'sendmail) + (run-hooks 'about-to-mail-hook) + (let (about-to-mail-hook) + (gnus-summary-mail-other-window))) + +(defun ht-Subject-move () + "Move article to a file, mode determined by file extension (babyl/msg)" + (interactive) + (gnus-summary-select-article) + (save-excursion + (set-buffer gnus-article-buffer) + (rmht-output nil t))) + + +(defun ht-write-body-to-file (file) + "Write the body of the message to a file and replace it with a pointer" + (interactive "FFile to save in: ") + (goto-char (point-min)) + (or (search-forward "\n\n" nil t) + (error "Can't find text")) + (write-region (point)(point-max) file) + (rmail-edit-current-message) + (delete-region (point)(point-max)) + (insert "\n>> " file "\n") + (rmail-cease-edit) + (rmht-output)) + +(defun extract-attachment () + "extract attachments from a multi-part mime message" + (interactive) + (rmail-toggle-header) + (mime/viewer-mode) + (let ((pt 0)) + (while (progn + (mime-viewer/next-content) + (and + (equal "*Preview-RMAIL*" (buffer-name (current-buffer))) + (not (= pt (point))))) + (setq pt (point)) + (if (looking-at "^\\[[0-9]* [^ ]+ <") + (mime-viewer/extract-content)))) + (if (not (equal "*Preview-RMAIL*" (buffer-name (current-buffer)))) + ;; we fell off the end + (rmail-previous-undeleted-message 1)) + (kill-buffer "*Preview-RMAIL*") + ) + +;; see message-citation-line-function in message.el +(defun safe-citation () + (when message-reply-headers + (let ((from (mail-header-from message-reply-headers))) + (cond ((string-match "^\"?\\([^\"]*\\)\"? <.*>$" from) + (insert (match-string 1 from) " writes:\n\n")) + ((string-match "^\\([^<@]*\\)@" from) + (insert (match-string 1 from) " writes:\n\n")) + (t + (insert "[anon] writes:\n\n")))))) + + +(setq message-citation-line-function (function safe-citation)) + +;(load-library "mailcrypt") ; provides "mc-setversion" +;(mc-setversion "gpg") ; for PGP 2.6 (default); also "5.0" and "gpg" +;(autoload 'mc-install-write-mode "mailcrypt" nil t) +;(autoload 'mc-install-read-mode "mailcrypt" nil t) +;(add-hook 'mail-mode-hook 'mc-install-write-mode) +;(add-hook 'gnus-summary-mode-hook 'mc-install-read-mode) +;(add-hook 'message-mode-hook 'mc-install-write-mode) +;(add-hook 'news-reply-mode-hook 'mc-install-write-mode) +;(setq mc-passwd-timeout 6000) +;;; Key server at Cambridge University (Cambridge, England) +;(setq mc-pgp-fetch-methods '(mc-pgp-fetch-from-keyrings +; mc-pgp-fetch-from-http)) +;(require 'pgg) +;(add-hook 'message-send-hook 'my-sign-message) +(setq hack-yn-map (copy-keymap query-replace-map)) +(define-key hack-yn-map 'return 'act) + +(defun my-sign-message () + (goto-char (point-min)) + (unless + (or + (re-search-forward "<#\\(part\\|mml\\) " nil t) + ; signing attachments doesn't seem + ; to work well + (search-forward "\n-- \nHenry S. Thompson, Central Edinburgh LM" nil t) + ; Don't sign Quaker mail + ) + (let* ((headers (mail-header-extract-no-properties)) + (cc (mail-header 'cc)) + (to (mail-header 'to))) + (if (and to + (not (string-match "htcalendar[@]markup\.co\.uk" to)) + (not (string-match "^ht$" to)) + (or + (string-match "w3.org" to) + (and cc (string-match "w3.org" cc)) + (let ((query-replace-map hack-yn-map)) + (y-or-n-p "Sign message? ")))) + (mml-secure-message-sign-pgp)))))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shared/mdn-extras.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,167 @@ +;; Last edited: Thu Jun 11 14:04:02 1992 +;; stub for henry's mail reading and diary maintenance tools +;; Copyright (C) 1990 Henry S. Thompson +;; Edit history: made diary-setup do (update-default-diary nil) instead of t + +;; This file is part of GNU Emacs. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY. No author or distributor +;; accepts responsibility to anyone for the consequences of using it +;; or for whether it serves any particular purpose or works at all, +;; unless he says so in writing. Refer to the GNU Emacs General Public +;; License for full details. + +;; Everyone is granted permission to copy, modify and redistribute +;; GNU Emacs, but only under the conditions described in the +;; GNU Emacs General Public License. A copy of this license is +;; supposed to have been given to you along with GNU Emacs so you +;; can know your rights and responsibilities. It should be in a +;; file named COPYING. Among other things, the copyright notice +;; and this notice must be preserved on all copies. + +(provide 'mdn-extras) + +;; get my sendmail, on way or another + +(if (featurep 'sendmail) + ;; already loaded - overwrite + (site-caseq + (parc (load "~hthompso/emacs/shared/sendmail")))) + +(setq command-switch-alist + (nconc command-switch-alist '(("-m" . ht-mail-setup) + ("-mail" . ht-mail-setup) + ("-d" . ht-diary-setup) + ("-diary" . ht-diary-setup)))) + +(setq command-switch-alist + (nconc command-switch-alist '(("-n" . ht-news-setup) + ("-news" . ht-news-setup)))) + +(autoload 'gnus "gnus" "read news" t) + +(defvar ht-default-config nil "saved window configuration after startup") +(defvar ht-back-config (current-window-configuration) + "saved window configuration from before ^Cw/^C^w") + +(defun ht-mail-setup (&optional arg) + "set up my mail reading and do it" + (interactive) + (require 'mail-extras) ; mail stuff + (if (featurep 'gnus) ; in case gnus is around + (split-window-vertically)) + (rmail) + (setq ht-default-config (current-window-configuration))) + +(defun ht-diary-setup (&optional arg) + "diary setup" + (interactive) + (require 'diary) + (update-default-diary nil) ; set up standard config. + (if (featurep 'rmail) + (if (featurep 'gnus) ; in case gnus is around + (progn (other-window 1) + (split-window) + (other-window 1) + (switch-to-buffer (get-file-buffer rmail-file-name))) + (switch-to-buffer (get-file-buffer rmail-file-name)) + (other-window 1) + (split-window) + (other-window 1) + (switch-to-buffer (save-excursion (set-buffer (get-file-buffer + ht-diary-file-name)) + rmail-summary-buffer)) + (other-window 1))) + (setq ht-default-config (current-window-configuration))) + +(defun ht-news-setup (&optional arg) + "set up my GNUS and do it" + (interactive) + (require 'my-news) ; GNUS stuff + (if (featurep 'rmail) + (split-window-vertically)) + (gnus) + (setq ht-default-config (current-window-configuration)) + (unless (gnuserv-running-p) + (gnuserv-start)) + ) + +(defun default-config () + "restore screen to default config" + (interactive) + (setq ht-back-config (current-window-configuration)) + (set-window-configuration ht-default-config)) + +(defun back-config () + (interactive) + (set-window-configuration (prog1 ht-back-config + (setq ht-back-config + (current-window-configuration))))) + +(global-set-key "\C-cw" 'default-config) + +(global-set-key "\C-c\C-w" 'back-config) + +(setq mail-custom-fields + '(("To" (fill-addr-field (local-field-var to "")) "\C-t") + ("Subject" (ht-subj-with-reply) "\C-s"))) + +(defun ht-subj-with-reply () + (let ((subj (local-field-var subject "")) + (irt (local-field-var in-reply-to))) + (if (and in-reply-to + (not (string-match "^Re:" subj))) + (concat "Re: " subj) + subj))) + + +;;; Henry's special double update hack + +(add-hook 'rmail-mode-hook 'rmail-mode-fun3) + +(defun get-mail-news-and () + "update both if both present" + (interactive) + (rmail-get-new-mail) + (let (nw) + (setq nw (get-buffer "*Newsgroup*")) + (if nw + (save-window-excursion + (pop-to-buffer nw) + (gnus-group-get-new-news))))) + +;;; rescued from old rmail +;;; hacked to cope with differences between e19 and lucid +(defun ht-rmail-delete-forward (&optional backward) + "Delete this message and move to next nondeleted one. +Deleted messages stay in the file until the \\[rmail-expunge] command is given. +With prefix argument, delete and move backward. +If there is no nondeleted message to move to +in the preferred or specified direction, move in the other direction." + (interactive "P") + (rmail-set-attribute "deleted" t) + (if (or + (string-match "Lucid" emacs-version) + (and (boundp 'emacs-minor-version) + (> emacs-minor-version 19) ; not sure where pblm was fixed + ; certainly by 28 + )) + (if (not (rmail-next-undeleted-message (if backward -1 1))) + (if (rmail-previous-undeleted-message (if backward -1 1)) + (message "") ; override the stupid one + )) + (if (rmail-next-undeleted-message (if backward -1 1)) + (if (not (rmail-previous-undeleted-message (if backward -1 1))) + (message ""))))) + +(defun rmail-mode-fun4 () + (setq buffer-auto-save-file-name nil) + (make-variable-buffer-local 'backup-inhibited) + (setq backup-inhibited t)) + +(defun rmail-mode-fun3 () + (define-key rmail-mode-map "G" 'get-mail-news-and) + (define-key rmail-mode-map "d" 'ht-rmail-delete-forward) + (remove-hook 'rmail-mode-hook 'rmail-mode-fun3) + (add-hook 'rmail-mode-hook 'rmail-mode-fun4 t))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shared/motion.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,319 @@ +;;; Copyright (C) 1990 Alan M. Carroll +;;; +;;; This file is for use with Epoch, a modified version of GNU Emacs. +;;; Requires Epoch 3.2 or later. +;;; +;;; This code is distributed in the hope that it will be useful, +;;; bute WITHOUT ANY WARRANTY. No author or distributor accepts +;;; responsibility to anyone for the consequences of using this code +;;; or for whether it serves any particular purpose or works at all, +;;; unless explicitly stated in a written agreement. +;;; +;;; Everyone is granted permission to copy, modify and redistribute +;;; this code, but only under the conditions described in the +;;; GNU Emacs General Public License, except the original author nor his +;;; agents are bound by the License in their use of this code. +;;; (These special rights for the author in no way restrict the rights of +;;; others given in the License or this prologue) +;;; A copy of this license is supposed to have been given to you along +;;; with Epoch so you can know your rights and responsibilities. +;;; It should be in a file named COPYING. Among other things, the +;;; copyright notice and this notice must be preserved on all copies. +;;; +(provide 'motion) +(require 'button) +(require 'mouse) +;;; +;;; version tohandle mouse stuff +;;; +;;; [cjl] now use primitive epoch::move-button when possible. +;;; +(defvar horizontal-drag-inc 5 "Number of columns to scroll when the pointer is to the left or right of the window") +(defvar vertical-drag-inc 2 "Number of lines to scroll when the pointer is above or below the edge of the window") + +(defvar mouse::downp nil "State variable for mouse dragging internals") +(defvar mouse::last-point -1 "Last location of a motion event") + +(make-variable-buffer-local 'drag-button) +(make-variable-buffer-local 'mouse-down-marker) + +(defvar motion::attribute (reserve-attribute) "Attribute for drag buttons") +(setq epoch::buttons-modify-buffer nil) + +(defvar motion::style nil "style used by drag buttons") + +;; +;; Set window-setup-hook to call motion::init(), which sets default +;; style for button dragging +;; +(epoch-add-setup-hook 'motion::init) +(defun motion::init () + (and (not motion::style) (setq motion::style (make-style))) + (set-style-foreground motion::style (foreground)) + (set-style-background motion::style (background)) + (set-style-underline motion::style (foreground)) + (set-attribute-style motion::attribute motion::style) + ;; enable the handler + (push-event 'motion 'motion::handler) + ;; set up hints on all the current screens + (dolist (s (screen-list t)) (epoch::set-motion-hints t s)) + ;; enable hints on future screens + (push '(motion-hints t) epoch::screen-properties) + ) + +(setq-default drag-button nil) +(setq-default mouse-down-marker nil) + +;;; ------------------------------------------------------------------------ +(defun set-mouse-marker (&optional location) + (if (null mouse-down-marker) + (setq mouse-down-marker (make-marker)) + ) + (set-marker mouse-down-marker (or location (point))) +) +;;; -------------------------------------------------------------------------- +;;; generic arg is a list of ( POINT BUFFER WINDOW SCREEN ) +;;; +(defun end-mouse-drag (arg) + (setq mouse::last-point -1) ;always do this cleanup + (when mouse::downp + (setq mouse::downp nil) + (mouse::copy-button drag-button) + (if (buttonp drag-button) + (if (<= (point) (button-start drag-button)) + (progn + (push-mark (button-end drag-button) t) + (goto-char (button-start drag-button)) + ) + ;; ELSE point is past drag button start + (progn + (push-mark (button-start drag-button) t) + (goto-char (button-end drag-button)) + ) + ) + ) + ) +) + +(defun start-mouse-drag (arg) + (when arg + (setq mouse::downp 'start) + (mouse::set-point arg) + (set-mouse-marker) + (setq mouse::last-point (point)) + (if drag-button + (progn (delete-button drag-button) (setq drag-button nil) ) + ) + ) +) + +(defun extend-mouse-drag (arg) + (setq mouse::downp 'extend) + (let + ( + (m1 (and drag-button (button-start drag-button))) + (m2 (and drag-button (button-end drag-button))) + (spot (car arg)) ;point of the mouse click. + ) + (if (null m1) (setq m1 0)) + (if (null m2) (setq m2 0)) + (cond + ((or (null drag-button) (null mouse-down-marker)) + (setq drag-button (add-button (point) spot motion::attribute) ) + (set-mouse-marker) + ) + ((<= spot m1) + (setq drag-button (move-button drag-button spot m2) ) + (set-mouse-marker m2) + ) + ((>= spot m2) + (setq drag-button (move-button drag-button m1 spot) ) + (set-mouse-marker m1) + ) + ((<= mouse-down-marker spot) + (setq drag-button (move-button drag-button m1 spot) ) + (set-mouse-marker m1) + ) + (t + (setq drag-button (move-button drag-button spot m2) ) + (set-mouse-marker m2) + ) + ) + (epoch::redisplay-screen) + (setq mouse::last-point (point)) + ) +) + +;;; ------------------------------------------------------------------------ +;;; Define the handler +;;; +(defun motion::handler (type value scr) + (if (null mouse-down-marker) (set-mouse-marker)) + (if (and (boundp 'mouse::downp) mouse::downp) + (mouse-sweep-update) + ) +) +;;; +(defun mouse-sweep-update() + (let* + (x y pos drag-m1 drag-m2 pnt orig-m1 orig-m2 + (out-of-bounds t) + (epoch::event-handler-abort nil) + (w (selected-window)) + (w-edges (window-edges w)) + (left (car w-edges)) + (top (elt w-edges 1)) + (right (- (elt w-edges 2) (+ 2 left))) + (bottom (- (elt w-edges 3) (+ 2 top))) + ever + ) + (if drag-button + (progn (setq orig-m1 (or (button-start drag-button) -1)) + (setq orig-m2 (or (button-end drag-button) -1))) + (progn (setq orig-m1 mouse-down-marker) + (setq orig-m2 (point)))) + (while + (and + out-of-bounds + (setq pos (query-mouse)) + (/= 0 (logand mouse-any-mask (elt pos 2))) + ) + ;;convert to window relative co-ordinates + (setq x (- (car pos) left)) + (setq y (- (elt pos 1) top)) + (setq out-of-bounds + (not (and (<= 0 y) (<= y bottom) (<= 0 x) (<= x right))) + ) + + ;; scrolling conditions + (condition-case errno + (progn + (if (< y 0) (scroll-down vertical-drag-inc)) + (if (> y bottom) (scroll-up vertical-drag-inc)) + ) + (error ) ;nothing, just catch it + ) + (if (< x 0) (scroll-right horizontal-drag-inc)) + (if (> x right) (scroll-left horizontal-drag-inc)) + (setq y (max 0 (min bottom y))) + (setq x (max 0 (min right x))) + + (setq pnt (car (epoch::coords-to-point (+ x left) (+ y top)))) + (when (/= mouse::last-point pnt) + (if (> mouse-down-marker pnt) + (progn + (setq drag-m1 pnt) + (setq drag-m2 (marker-position mouse-down-marker)) + ) + (progn + (setq drag-m1 (marker-position mouse-down-marker)) + (setq drag-m2 pnt) + ) + ) + ;; don't move for trivial reasons + (when (or ever (/= drag-m1 orig-m1) (/= drag-m2 orig-m2)) + (setq ever t) + (if (not drag-button) + (setq drag-button + (add-button mouse-down-marker + (point) motion::attribute ) + ) + ) + (move-button drag-button drag-m1 drag-m2) + (epoch::redisplay-screen) + ) + ) + (setq mouse::last-point pnt) + ) + ) +) +;;; ------------------------------------------------------------------------ +;;; Code for selecting lines using motion events. Assumes that the line is +;;; left unmarked on button up +;;; +(defvar mouse::line-button nil "Button for selected line") +;;; +(defun mouse-select-line-start (arg) + (mouse::set-point arg) ;go there + (setq mouse::last-point (point)) + (let ( bol ) + (save-excursion + (beginning-of-line) + (setq bol (point)) + (end-of-line) + (setq mouse::line-button (add-button bol (point) motion::attribute)) + ) + ) + (push-event 'motion 'mouse-select-line-update) +) +;;; +(defun mouse-select-line-end (arg) + (setq mouse::last-point -1) + (when mouse::line-button (delete-button mouse::line-button)) + (pop-event 'motion) +) +;;; +(defun mouse-select-line-update (type value scr) + (let* + ( + y + pos + bol + (out-of-bounds t) + (epoch::event-handler-abort nil) + (w-edges (window-edges (selected-window))) + (top (elt w-edges 1)) + (bottom (- (elt w-edges 3) (+ 2 top))) + max-vscroll + ) + (while + (and + out-of-bounds + (setq pos (query-mouse)) + (/= 0 (logand mouse-any-mask (elt pos 2))) + ) + ;;convert to window relative co-ordinates + (setq y (- (elt pos 1) top)) + (setq out-of-bounds (not (and (<= 0 y) (<= y bottom)))) + + ;; Scrolling hard, because of possibly shrink-wrapped windows. + ;; set max-vscroll to be the most we could scroll down and not have + ;; empty lines at the bottom + (save-excursion + (move-to-window-line bottom) ;go to the last line in the window + (setq max-vscroll + (- vertical-drag-inc (forward-line vertical-drag-inc)) + ) + (if (and (> max-vscroll 0) (eobp) (= 0 (current-column))) + (decf max-vscroll) + ) + ) + (condition-case errno + (progn + (if (< y 0) (scroll-down vertical-drag-inc)) + (if (> y bottom) (scroll-up (min max-vscroll vertical-drag-inc))) + ) + ;; CONDITIONS + (error) ;nothing, just want to catch it + ) + (setq y (max 0 (min bottom y))) + + ;;move to the new point + (move-to-window-line y) + (beginning-of-line) (setq bol (point)) + (end-of-line) + (when (/= mouse::last-point (point)) + (move-button mouse::line-button bol (point)) + (epoch::redisplay-screen) + ) + (setq mouse::last-point (point)) + ) + ) +) +;;; -------------------------------------------------------------------------- +;;; install all our variouse handlers +(global-set-mouse mouse-left mouse-down 'start-mouse-drag) +(global-set-mouse mouse-left mouse-up 'end-mouse-drag) +(global-set-mouse mouse-right mouse-down 'extend-mouse-drag) +(global-set-mouse mouse-right mouse-up 'end-mouse-drag) +(global-set-mouse mouse-middle mouse-down 'mouse::paste-cut-buffer)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shared/motion4.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,385 @@ +;;; Copyright (C) 1991 Christopher J. Love +;;; +;;; This file is for use with Epoch, a modified version of GNU Emacs. +;;; Requires Epoch 4.0 or later. +;;; +;;; This code is distributed in the hope that it will be useful, +;;; bute WITHOUT ANY WARRANTY. No author or distributor accepts +;;; responsibility to anyone for the consequences of using this code +;;; or for whether it serves any particular purpose or works at all, +;;; unless explicitly stated in a written agreement. +;;; +;;; Everyone is granted permission to copy, modify and redistribute +;;; this code, but only under the conditions described in the +;;; GNU Emacs General Public License, except the original author nor his +;;; agents are bound by the License in their use of this code. +;;; (These special rights for the author in no way restrict the rights of +;;; others given in the License or this prologue) +;;; A copy of this license is supposed to have been given to you along +;;; with Epoch so you can know your rights and responsibilities. +;;; It should be in a file named COPYING. Among other things, the +;;; copyright notice and this notice must be preserved on all copies. +;;; +;;; $Revision: 1.2 $ +;;; $Source: /home/user5/ht/emacs/shared/RCS/motion4.el,v $ +;;; $Date: 1992/03/18 21:44:10 $ +;;; $Author: ht $ +;;; +;;; motion.el - provide draggin/hi-lighting of primary selection +;;; +;;; Original version by Alan Carroll +;;; Epoch 4.0 modifications by Chris Love +;;; Abort-isearch and other ideas from Ken Laprade and others. +;;; +(provide 'motion) +(redisplay-screen) ; fix epoch4.0a race bug? +(require 'zone) +(require 'mouse) + +;;; ------------------------------------------------------------------------ +;;; Interface values +(defvar horizontal-drag-inc 5 + "Number of columns to scroll when the pointer is to the left or right of the window") +(defvar vertical-drag-inc 2 + "Number of lines to scroll when the pointer is above or below the edge of the window") + +(defvar mouse::downp nil "State variable for mouse dragging internals") +(defvar mouse::last-point -1 "Last location of a motion event") + +(setq epoch::zones-modify-buffer nil) +(defvar motion::style nil "style used by drag zones") + +(defvar drag-zone nil + "Epoch zone to be used for hilighting selected text region." +) +(setq-default drag-zone nil) +(setq-default mouse-down-marker nil) + +;;; ------------------------------------------------------------------------ +;;; Set window-setup-hook to call motion::init(), which sets default +;;; style for zone dragging. Default style is underlining; can be changed +;;; in .emacs file. +(epoch-add-setup-hook 'motion::init) + +(defun motion::init () + (and (not motion::style) (setq motion::style (make-style))) + (set-style-foreground motion::style (foreground)) + (set-style-background motion::style (background)) + (set-style-underline motion::style (foreground)) + ;; enable the handler + (push-event 'motion 'motion::handler) + ;; set up hints on all the current screens + (dolist (s (screen-list t)) (epoch::set-motion-hints t s)) + ;; enable hints on future screens + (push '(motion-hints t) epoch::screen-properties) + ) + +;;; ------------------------------------------------------------------------ +(defun set-mouse-marker (&optional location) + (if (null mouse-down-marker) + (setq mouse-down-marker (make-marker)) + ) + (set-marker mouse-down-marker (or location (point))) +) + +;;; -------------------------------------------------------------------------- +;;; Functions to provide dragging & hilighting. +;;; arg is a list of ( POINT BUFFER WINDOW SCREEN ) +(defun end-mouse-drag (arg) + (setq mouse::last-point -1) ;always do this cleanup + (when mouse::downp + (setq mouse::downp nil) + (mouse::copy-zone drag-zone) + (let ( + (s (and drag-zone (zone-start drag-zone))) + (e (and drag-zone (zone-end drag-zone))) + ) + (if (null s) (setq s 1)) + (if (null e) (setq e 1)) + (if (zonep drag-zone) + (if (<= (point) s) + (progn + (push-mark e t) + (goto-char s) + ) + ;; ELSE point is past drag zone start + (progn + (push-mark s t) + (goto-char e) + ) + ) + ) + ) + ) +) + +(defun start-mouse-drag (arg) + (when arg + (setq mouse::downp 'start) +; (message "%s" arg) + (mouse::set-point arg) + (abort-isearch) + (set-mouse-marker) + (setq mouse::last-point (point)) + (if drag-zone + (progn + (message "ddz") + (delete-zone drag-zone) + (setq drag-zone nil) + (redisplay-screen) + ) + ) + ) +) + +(defun extend-mouse-drag (arg) + (setq mouse::downp 'extend) + (let + ( + (m1 (and drag-zone (zone-start drag-zone))) + (m2 (and drag-zone (zone-end drag-zone))) + (spot (car arg)) ;point of the mouse click. + ) + (if (null m1) (setq m1 0)) + (if (null m2) (setq m2 0)) + (cond + ((or (null drag-zone) (null mouse-down-marker)) + (setq drag-zone (add-zone (point) spot motion::style) ) + (set-zone-transient drag-zone t) + (set-mouse-marker) + ) + ((<= spot m1) + (setq drag-zone (move-zone drag-zone spot m2) ) + (set-mouse-marker m2) + ) + ((>= spot m2) + (setq drag-zone (move-zone drag-zone m1 spot) ) + (set-mouse-marker m1) + ) + ((<= mouse-down-marker spot) + (setq drag-zone (move-zone drag-zone m1 spot) ) + (set-mouse-marker m1) + ) + (t + (setq drag-zone (move-zone drag-zone spot m2) ) + (set-mouse-marker m2) + ) + ) + (epoch::redisplay-screen) + (setq mouse::last-point (point)) + ) +) + +;;; ------------------------------------------------------------------------ +;;; Define the handler for dragging, etc. +(defun motion::handler (type value scr) + (if (null mouse-down-marker) (set-mouse-marker)) + (if (and (boundp 'mouse::downp) mouse::downp) + (mouse-sweep-update) + ) +) + +;;; +(defun mouse-sweep-update() + (let* + ( + drag-m1 + drag-m2 + pnt + pos + x + y + (w (selected-window)) + (out-of-bounds t) + (epoch::event-handler-abort nil) + (w-edges (window-pixedges w)) + (left (car w-edges)) + (top (elt w-edges 1)) + (right (- (elt w-edges 2) left 1)) + (bottom (- (elt w-edges 4) top 1)) + ) + (while + (and + out-of-bounds + (setq pos (query-pointer)) + (/= 0 (logand mouse-any-mask (elt pos 2))) + ) + ;;convert to window relative co-ordinates + (setq x (- (car pos) left)) + (setq y (- (elt pos 1) top)) + (setq out-of-bounds + (not (and (<= 0 y) (<= y bottom) (<= 0 x) (<= x right))) + ) + ;; scrolling conditions + (condition-case errno + (progn + (if (< y 0) (scroll-down vertical-drag-inc)) + (if (> y bottom) (scroll-up vertical-drag-inc)) + ) + (error ) ;nothing, just catch it + ) +;; Disable horizontal scrolling. +; (if (< x left) (scroll-right horizontal-drag-inc)) +; (if (> x right) (scroll-left horizontal-drag-inc)) + (setq y (max 1 (min bottom y))) + (setq x (max 0 (min right x))) + (setq pnt (car (epoch::coords-to-point (+ x left) (+ y top)))) + (when (/= mouse::last-point pnt) + (if (> mouse-down-marker pnt) + (progn + (setq drag-m1 pnt) + (setq drag-m2 (marker-position mouse-down-marker)) + ) + (progn + (setq drag-m1 (marker-position mouse-down-marker)) + (setq drag-m2 (1+ pnt)) + ) + ) + ;; moved this in here so that zone won't get made if + ;; only motion is jitter within a single character + ;; this fixes a bunch of bogus (often empty) + ;; entries in the kill ring + (if drag-zone + (move-zone drag-zone drag-m1 drag-m2) + (progn (setq drag-zone + (add-zone drag-m1 drag-m2 motion::style ) + ) + (set-zone-transient drag-zone t) + ) + ) + (redisplay-screen) + ) + (setq mouse::last-point pnt) + ) + ) +) + +;;; ------------------------------------------------------------------------ +;;; Code for selecting lines using motion events. Assumes that the line is +;;; left unmarked on zone up +(defvar mouse::line-zone nil "Zone for selected line") +;;; +(defun mouse-select-line-start (arg) + (mouse::set-point arg) ;go there + (setq mouse::last-point (point)) + (let ( bol ) + (save-excursion + (beginning-of-line) + (setq bol (point)) + (end-of-line) + (setq mouse::line-zone (add-zone bol (point) motion::style)) + ) + ) + (push-event 'motion 'mouse-select-line-update) +) +;;; +(defun mouse-select-line-end (arg) + (setq mouse::last-point -1) + (when mouse::line-zone (delete-zone mouse::line-zone)) + (pop-event 'motion) +) +;;; +(defun mouse-select-line-update (type value scr) + (let* + ( + y + pos + bol + (out-of-bounds t) + (epoch::event-handler-abort nil) + (w-edges (window-pixedges (selected-window))) + (top (elt w-edges 1)) + (bottom (- (elt w-edges 4) top 1)) + max-vscroll + ) + (while + (and + out-of-bounds + (setq pos (query-pointer)) + (/= 0 (logand mouse-any-mask (elt pos 2))) + ) + ;;convert to window relative co-ordinates + (setq y (- (elt pos 1) top)) + (setq out-of-bounds (not (and (<= 0 y) (<= y bottom)))) + + ;; Scrolling hard, because of possibly shrink-wrapped windows. + ;; set max-vscroll to be the most we could scroll down and not have + ;; empty lines at the bottom + (save-excursion + (move-to-window-line bottom) ;go to the last line in the window + (setq max-vscroll + (- vertical-drag-inc (forward-line vertical-drag-inc)) + ) + (if (and (> max-vscroll 0) (eobp) (= 0 (current-column))) + (decf max-vscroll) + ) + ) + (condition-case errno + (progn + (if (< y 0) (scroll-down vertical-drag-inc)) + (if (> y bottom) (scroll-up (min max-vscroll vertical-drag-inc))) + ) + ;; CONDITIONS + (error) ;nothing, just want to catch it + ) + (setq y (max 0 (min bottom y))) + + ;;move to the new point + (move-to-window-line y) + (beginning-of-line) (setq bol (point)) + (end-of-line) + (when (/= mouse::last-point (point)) + (move-zone mouse::line-zone bol (point)) + (epoch::redisplay-screen) + ) + (setq mouse::last-point (point)) + ) + ) +) +;;; -------------------------------------------------------------------------- +;; Stolen from AMC +(defun mouse::buffer-line (marg) + "Show the line number and buffer of the mouse EVENT" + ;; marg is (point buffer window screen) + ;; Pop over to the clicked buffer + (save-excursion (set-buffer (cadr marg)) + ;; Figure out how far down the mouse point is + (let ((n (count-lines (point-min) (car marg)))) + ;; display it. Include the buffer name for good measure. + (message (format "Line %d in %s" n (buffer-name (cadr marg)))) +))) + +;; Blow out of any current isearch +(defun abort-isearch () "Abort any isearch in progress." + (condition-case err + (throw 'search-done t) + (no-catch nil))) +;;; -------------------------------------------------------------------------- +;;; install all our various handlers +(global-set-mouse mouse-left mouse-down 'start-mouse-drag) +(global-set-mouse mouse-left mouse-shift 'mouse::buffer-line) +(global-set-mouse mouse-left mouse-up 'end-mouse-drag) +(global-set-mouse mouse-right mouse-down 'extend-mouse-drag) +(global-set-mouse mouse-right mouse-up 'end-mouse-drag) +(global-set-mouse mouse-middle mouse-down 'mouse::paste-cut-buffer) + + +(defun mouse-set-spot (arg) + "Set point at mouse. With double-click, set mark there as well. +Blinks matching paren if sitting after one. Intended to be bound +to a window down button." + (start-mouse-drag arg) + (let ((buf (current-buffer)) + (p (point))) + (mouse::set-point arg) + (if (and (equal p (point)) + (equal buf (current-buffer))) + (if (and (= mouse::clicks 1) + (not (eq (mark) (point)))) + (push-mark)) + (setq mouse::clicks 0)) + (if (eq (char-syntax (preceding-char)) ?\)) + (blink-matching-open))) + (abort-isearch)) + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shared/refInsert.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,45 @@ +;;; refInsert.el --- replace url with ref, resolve at end + +(provide 'refInsert) +;;; Code: + +(defun reference () + "Insert a reference" + (interactive) + (let ((current-point (point)) + (beginning (search-backward " +" (point-min) t))) + (save-excursion + (if (not (equal beginning nil)) + (goto-char beginning)) + (let ((url-point (search-forward-regexp "[a-zA-Z]+:[^ +]+" (+ current-point 1) t)) + (ref "http://www.w3.org/DOM")) + (if (not (equal url-point nil)) + (progn + (setq ref (buffer-substring (match-beginning 0) (match-end 0))) + (replace-match "") + (setq current-point (point)))) + + (setq ref (read-string "Reference? " ref)) + (setq nbReferences + (string-to-number (read-string "Reference number? " + (number-to-string (+ nbReferences 1))))) + (let ((search-p (search-forward-regexp "^-- +" (point-max) t))) + (if (equal search-p nil) + (end-of-buffer) + (progn (goto-char search-p) (previous-line 1))) + (insert (concat "[" (number-to-string nbReferences) "] " + ref)) + (newline)))) + (goto-char current-point) + (insert (concat "[" (number-to-string nbReferences) "]")) + )) + +(setq nbReferences 0) + +(add-hook 'mail-setup-hook (lambda () (setq nbReferences 0))) +(add-hook 'gnus-message-setup-hook (lambda () (setq nbReferences 0))) + +;;; %F ends here
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shared/repl-comment.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,59 @@ +;; Universal (?) replace comment in function + +;; Last edited: Thu Oct 7 09:39:50 1993 +(defun repl-comment (fn comment) + "replace/install as FN's comment COMMENT, no matter what emacs/compiler" + (let ((defn (symbol-function fn))) + (if (consp defn) + (if (eq (car defn) 'autoload) + (progn (load-library (car (cdr defn))) + (if (equal defn (symbol-function fn)) + (error "autoloading didn't help define %s" fn) + (repl-comment fn comment))) + ;; either symbolic or old byte-compiler + (if (eq (car defn) 'lambda) + (if (stringp (car (cdr (cdr defn)))) + (rplaca (cdr (cdr defn)) + comment) + (rplacd (cdr defn) + (cons comment + (cdr (cdr defn))))) + (error "can't diagnose defn %s" defn))) + ;; array or not + (if (compiled-function-p defn) + (fset fn (if (fboundp 'compiled-function-arglist) + (progn (make-byte-code + (compiled-function-arglist defn) + (compiled-function-instructions defn) + (compiled-function-constants defn) + (compiled-function-stack-depth defn) + comment + (compiled-function-interactive defn)) defn) + (repl-byte fn (list (cons 4 comment))))) + (error "unrecognised defn %s" defn))))) + +(defun repl-byte (fn alist) + "compute a new byte-code defn for FN, replacing +elements using ALIST, which is interpreted as (index . newbit). +Elements are 0: arglist 1: byte-codes 2: symbols 3: stack-depth 4: comment" + (let + ((defn (symbol-function fn))) + (let ((ln (if (sequencep defn) + (length defn) + ;; hack otherwise + 6)) + (i 0) + new entry) + (apply (function make-byte-code) + (progn (while (< i ln) + (setq new + (cons + (if (setq entry (assoc i alist)) + (cdr entry) + (aref defn i)) + new)) + (setq i (1+ i))) + (nreverse new)))))) + + +(provide 'repl-comment)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shared/sgml-font-lock-keywords.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,11 @@ +(defvar sgml-font-lock-keywords +'(;; highlight defining forms. + ("^<!\\([^- \t\n]+\\)[ \t\n]\\s-*\\(% \\)?\\(\\S-+\\)" + (1 font-lock-keyword-face) (3 font-lock-function-name-face)) + ("</?\\([-a-z0-9.A-Z]+\\)" 1 font-lock-function-name-face t) ; allow overlap to speed up + ("\\(/\\)>" 1 font-lock-function-name-face) + ("[%&][^ \t\n;]+" . font-lock-string-face) + ("--[^-]+\\(-[^-]+\\)*--" . font-lock-comment-face) + ("^<[?].*>" . font-lock-string-face) + ) +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/shared/xml-hack.el Mon Feb 08 11:44:37 2021 +0000 @@ -0,0 +1,8 @@ +(defun sgml-tag-again () + "Insert another of the tag we're in as sibling" + (interactive ) + (let ((elt (sgml-element-name (sgml-find-element-of (point))))) + (sgml-up-element) + (sgml-insert-element elt))) + +(define-key sgml-mode-map "\C-cn" 'sgml-tag-again)