From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 27-FEB-1991 23:34:46.50
To:	ARISIA::EVERHART
CC:	
Subj:	"Better" EDT.EL for GNU Emacs (was EDT for Unix)

From:	RELAY-INFO-VAX@CRVAX.SRI.COM@SMTP@CRDGW2
To:	Everhart@Arisia@MRGATE

Received:  by crdgw1.ge.com (5.57/GE 1.87)
	 id AA15729; Wed, 27 Feb 91 23:17:40 EST
Received: From UCBVAX.BERKELEY.EDU by CRVAX.SRI.COM with TCP; Tue, 26 FEB 91 20:53:32 PST
Received: by ucbvax.Berkeley.EDU (5.63/1.42)
	id AA15229; Tue, 26 Feb 91 20:32:54 -0800
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 27 Feb 91 04:06:25 GMT
From: eplrx7!mroz@louie.udel.edu  (Peter Mroz)
Organization: DuPont Engineering Physics Lab
Subject: "Better" EDT.EL for GNU Emacs (was EDT for Unix)
Message-Id: <1991Feb27.040625.24130@eplrx7.uucp>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

I put this together some years ago with the help of Skip Montanaro.  It
provides GNU Emacs with an EDT emulation that I thought was better than
the one that comes with GNU.  As usual the usual redundant redundant
disclaimers apply.  Enjoy...


;; Copyright (C) 1986 Free Software Foundation, Inc.
;;  It started from public domain code by Mike Clarkson
;;  but has been greatly altered.

;; 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.

;; Latest revisions 5/8/87 Peter Mroz:

;;   o Disabled on-off capability.  When you invoke edt-mode, it's there till
;;     you exit emacs.  I saw no reason to enable/disable this mode.
;;   o Disabled some of the keybindings - the only edt stuff available is the
;;     keypad.  everything else is gnu emacs.  somebody really went wild with
;;     gold key bindings in the previous edt emulation.
;;   o "Simplified" how the gold key works (maybe!).  When you hit the gold
;;     key, it sets the value of gold-key-active to t.  When you hit another
;;     keypad key, that function resets gold-key-active to nil.  Modeled after
;;     some code I got from Skip Montanaro.  If you hit RESET (.) the gold
;;     key is deactivated.
;;   o Also "simplified" how advance and backup work.  When you hit those keys,
;;     you set edt-direction to 1 and -1 respectively.  The direction is still
;;     shown in the mode line as a minor mode.
;;   o Added help screen for PF2; GOLD-PF2 performs an apropos.  The EDT help
;;     screen is kind of sneaky - it only shows on half of the screen.  To
;;     see the whole thing one has to start learning Gnu Emacs commands!  See
;;     the definition of edt-map below for the help screen.
;;   o The SUBS key (GOLD-ENTER) works differently than it does in EDT.  It
;;     prompts for everything and then invokes replace-string.
;;   o The ENTER key does not work.  Use a carriage return.
;;
;;   o To use, include the following lines in LOADDEFS.EL
;;
;;	(autoload 'edt-mode "edt"
;;	  "\
;;	Begin emulating DEC's EDT editor.  Sets up the arrow and keypad keys.
;;	Hit PF2 for the keypad bindings.  Note that this function does not
;;	work if called directly from the .emacs file.  Instead, the .emacs
;;	file should do (setq term-setup-hook 'edt-mode) Then this function
;;	will be called at the time when it will work."
;;	  t)
;;
;;     Then, just type M-x edt-mode.  Or put the line indicated above into
;;     your .emacs file
;;
;;* * * * * * * * * * * * * * * * * * * * *
;;* * * * * * * Global variables* * * * * *
(defvar edt-last-deleted-lines ""
  "Last text deleted by an EDT emulation line-delete command.")

(defvar edt-delete-buffer "edt-delete"
  "Buffer used by the edt replace command")

(defvar edt-find-string ""
  "search string used by edt fndnxt command")

(defvar edt-last-deleted-words ""
  "Last text deleted by an EDT emulation word-delete command.")

(defvar edt-last-deleted-chars ""
  "Last text deleted by an EDT emulation character-delete command.")

(defvar edt-direction '1
  "Current direction for gnu emacs edt mode 1=advance, -1=backup")

(defvar edt-direction-string " ADVANCE"
  "Direction of edt commands, shown in the mode line as a minor mode")

(defvar gold-key-active nil
  "Flag to tell whether or not the gold key has been hit")

(defvar edt-map nil
  "maps VT100/VT200 numeric keypad functions to edt-like functions for gnu
emacs.  Normal emacs control character functions are still active.  NOTE: THIS
IS NOT EDT.  The only thing that looks like EDT is the keypad.  The keypad
functions provided are:
+--------+--------+--------+--------+   Hit PF1 PF2 for help on a particular
|PF1     |PF2     |PF3     |PF4     |   topic.  To see more of this buffer hit
|        |        | FNDNXT | DEL L  |   C-X o to switch to this window, and 
|  GOLD  |  HELP  |  FIND  | UND L  |   then C-X 1 to delete the other window.
+--------+--------+--------+--------+   For a tutorial on gnu emacs type C-H t.
|7       |8       |9       |-       |   Some basic gnu emacs commands are:
|  PAGE  |  SECT  | APPEND | DEL W  |     C-X C-F   find file          
| COMMAND|  FILL  | REPLACE| UND W  |  	  C-X C-C   exit emacs         
+--------+--------+--------+--------+     C-X C-S   save current buffer
|4       |5       |6       |,       |     C-Z       pause emacs        
| ADVANCE| BACKUP |  CUT   | DEL C  |     C-G       keyboard quit      
| BOTTOM |  TOP   | PASTE  | UND C  |   To get back to the previous buffer  
+--------+--------+--------+--------+   type C-X b <cR>.
|1       |2       |3       |Enter   |   
|  WORD  |  EOL   |  CHAR  |        |            Box meaning            
|CHNGCASE| DEL EOL| SPECINS|        |          +------------------+   
+--------+--------+--------+        |          |keypad key        |   
|0                |.       |        |          | Normal function  |
|      LINE       | SELECT |  ENTER |          |   GOLD function  |
|    OPEN LINE    | RESET  |  SUBS  |          +------------------+
+-----------------+--------+--------+")

;* * * * * * * * * * * * * * * * * * * * * 
; Bind the numeric keypad keys
(if (not edt-map)
    (progn
      (setq edt-map (make-keymap))		; normal  / gold function
      (define-key edt-map "P" 'edt-pf1)		; gold key
      (define-key edt-map "Q" 'edt-pf2)		; help
      (define-key edt-map "R" 'edt-pf3)		; fndnxt  / find
      (define-key edt-map "S" 'edt-pf4)		; del l   / und l
      (define-key edt-map "w" 'edt-7)		; page    / command
      (define-key edt-map "x" 'edt-8)		; sect    / fill
      (define-key edt-map "y" 'edt-9)		; append  / replace
      (define-key edt-map "m" 'edt-minus)	; del w   / und w
      (define-key edt-map "t" 'edt-4)		; advance / backup
      (define-key edt-map "u" 'edt-5)		; backup  / top
      (define-key edt-map "v" 'edt-6)		; cut     / paste
      (define-key edt-map "l" 'edt-comma)	; del c   / und c
      (define-key edt-map "q" 'edt-1)		; word    / chngcase
      (define-key edt-map "r" 'edt-2)		; eol     / del eol
      (define-key edt-map "s" 'edt-3)		; char    / specins
      (define-key edt-map "M" 'edt-enter)	; enter   / subs
      (define-key edt-map "p" 'edt-0)		; line    / open-line
      (define-key edt-map "n" 'edt-period)	; select  / reset
      (define-key global-map "\eO" edt-map)))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-delete-current-line (num)
  "Delete one or specified number of lines after point.
This includes the newline character at the end of each line.
They are saved for the EDT undelete-lines command."
  (interactive "p")
  (let ((beg (point)))
    (forward-line num)
    (if (not (eq (preceding-char) ?\n))
	(insert "\n"))
    (setq edt-last-deleted-lines
	  (buffer-substring beg (point)))
    (delete-region beg (point))))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-delete-to-eol (num)
  "Delete text up to end of line.  With argument, delete up to to Nth
line-end past point.  They are saved for the EDT undelete-lines
command."
  (interactive "p")
  (let ((beg (point)))
    (forward-char 1)
    (end-of-line num)
    (setq edt-last-deleted-lines
	  (buffer-substring beg (point)))
    (delete-region beg (point))))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-delete-current-word (num)
  "Delete one or specified number of words after or before point,
depending on the sign of num.  They are saved for the EDT
undelete-words command."
  (interactive "p")
  (let ((beg (point)))
    (forward-word num)
    (setq edt-last-deleted-words
	  (buffer-substring beg (point)))
    (delete-region beg (point))))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-delete-current-char (num)
  "Delete one or specified number of characters before or after point,
depending on the sign of num.  They are saved for the EDT
undelete-chars command."
  (interactive "p")
  (let ((beg (+ (point) num)))
    ; Make sure beg is a valid spot in the buffer
    (setq beg (max (point-min) (min (point-max) beg)))
    (setq edt-last-deleted-chars (buffer-substring (point) beg))
    (delete-region (point) beg)))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-undelete-lines ()
  "Yank lines deleted by last EDT line-deletion command."
  (interactive)
  (insert edt-last-deleted-lines))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-undelete-words ()
  "Yank words deleted by last EDT word-deletion command."
  (interactive)
  (insert edt-last-deleted-words))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-undelete-chars ()
  "Yank characters deleted by last EDT character-deletion command."
  (interactive)
  (insert edt-last-deleted-chars))

;* * * * * * * * * * * * * * * * * * * * * 
(defun goto-percent (perc)
  "Move point to ARG percentage of the buffer."
  (interactive "NGoto-percentage: ")
  (if (or (> perc 100) (< perc 0))
      (error "Percentage %d out of range 0 < percent < 100" perc)
    (goto-char (/ (* (point-max) perc) 100))))

;* * * * * * * * * * * * * * * * * * * * * 
(defun update-mode-line ()
  "Make sure mode-line in the current buffer reflects all changes."
  (set-buffer-modified-p (buffer-modified-p))
  (sit-for 0))

;* * * * * * * * * * * * * * * * * * * * * 
(defun beginning-of-window ()
  "Home cursor to top of window."
  (interactive)
  (move-to-window-line 0))

;* * * * * * * * * * * * * * * * * * * * * 
(defun line-to-bottom-of-window ()
  "Move the current line to the top of the window."
  (interactive)
  (recenter -1))

;* * * * * * * * * * * * * * * * * * * * * 
(defun line-to-top-of-window ()
  "Move the current line to the top of the window."
  (interactive)
  (recenter 0))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-case-flip-character (num)
  "Change the case of the character under the cursor.
Accepts a prefix argument of the number of characters to invert."
  (interactive "p")
  (while (> num 0)
    (funcall (if (<= ?a (following-char))
		 'upcase-region 'downcase-region)
	     (point) (1+ (point)))
    (forward-char 1)
    (setq num (1- num))))

;* * * * * * * * * * * * * * * * * * * * * 
(defun indent-or-fill-region ()
  "Fill region in text modes, indent region in programming language modes."
  (interactive)
  (if (string= paragraph-start "^$\\|^")
      (indent-region (point) (mark) nil)
    (fill-region (point) (mark))))

;* * * * * * * * * * * * * * * * * * * * * 
(defun mark-section-wisely ()
  "Mark the section in a manner consistent with the major-mode.  Uses
mark-defun for emacs-lisp, lisp, mark-c-function for C, and
mark-paragraph for other modes.  This function isn't bound to anything
but it is useful"
  (interactive)
  (cond  ((eq major-mode 'emacs-lisp-mode)
	  (mark-defun))
	 ((eq major-mode 'lisp-mode)
	  (mark-defun))
	 ((eq major-mode 'c-mode)
	  (mark-c-function))
	 (t (mark-paragraph))))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-0 (num)
  "NORMAL: move by a LINE in the current direction  GOLD: OPEN LINE"
  (interactive "p")
  (if gold-key-active
      ; OPEN LINE
      (progn
	(open-line num)
	(setq gold-key-active nil))
    ; else LINE
    (forward-line (* edt-direction num))))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-1 (num)
  "NORMAL: move by a WORD in the current direction  GOLD: CHNGCASE"
  (interactive "p")
  (if gold-key-active
      ; CHNGCASE
      (progn
	(edt-case-flip-character num)
	(setq gold-key-active nil))
    ; else WORD
    (forward-word (* edt-direction num))))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-2 (num)
  "NORMAL: EOL move to the end of the line   GOLD: DEL EOL"
  (interactive "p")
  (if gold-key-active
      ; DEL EOL
      (progn
	(edt-delete-to-eol num)
	(setq gold-key-active nil))
    ; else EOL
    (end-of-line (* edt-direction num))))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-3 (num)
  "NORMAL: move by a CHAR in the current direction   GOLD: SPECINS for control
characters or octal codes"
  (interactive "p")
  (if gold-key-active
      ; SPECINS
      (progn
	(message "SPECINS (hit a control character or enter the octal code): ")
	(quoted-insert '1)
	(setq gold-key-active nil))
    ; CHAR
    (forward-char (* edt-direction num))))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-4 ()
  "NORMAL: change direction to ADVANCE   GOLD: go to the BOTTOM of the file"
  (interactive)
  (if gold-key-active
      ; BOTTOM
      (progn
	(goto-char (point-max))
	(message "Bottom of file")
	(setq gold-key-active nil))
    ; else ADVANCE
    (setq edt-direction '1)
    (setq edt-direction-string " ADVANCE")
    (update-mode-line)))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-5 ()
  "NORMAL: change direction to BACKUP   GOLD: go to the TOP of the file"
  (interactive)
  (if gold-key-active
      ; TOP
      (progn
	(goto-char (point-min))
	(message "Top of file")
	(setq gold-key-active nil))
    ; else BACKUP
    (setq edt-direction '-1)
    (setq edt-direction-string " BACKUP")
    (update-mode-line)))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-6 ()
  "NORMAL: CUT from the current position to the mark   GOLD: PASTE what was cut
starting at the current position.  Uses the yank buffer"
  (interactive)
  (if gold-key-active
      ; PASTE
      (progn
  	(yank)
	(setq gold-key-active nil))
    ; else CUT
    (kill-region (mark) (point))))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-7 (num)
  "NORMAL: move by a PAGE in the current direction    GOLD: COMMAND
execute an emacs command.  A page is usually delimited by ^L."
  (interactive "p")
  (if gold-key-active
      ; COMMAND
      (progn
	(execute-extended-command nil)
	(setq gold-key-active nil))
    ; else PAGE
    (if (eq edt-direction '1)
	(forward-page num)
      (backward-page num))))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-8 (num)
  "NORMAL: move by a SECTion in the current direction    GOLD: FILL
 a text region; indent a program"
  (interactive "p")
  (if gold-key-active
      ; FILL
      (progn
	(indent-or-fill-region)
	(setq gold-key-active nil))
    ; else SECT
    (scroll-up (* edt-direction (- (* (window-height) num) 2)))))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-9 (num)
  "NORMAL: APPEND    GOLD: REPLACE text between point and mark
with the kill buffer.  The APPEND function deletes text between point and 
mark and appends it to the kill buffer"
  (interactive "p")
  (if gold-key-active
      ; REPLACE
      (progn
	(copy-to-buffer edt-delete-buffer (mark) (point))
	(delete-region (mark) (point))
	(yank)
	(setq gold-key-active nil))
    ; else APPEND
    (append-next-kill)
    (kill-region (mark) (point))))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-pf1 ()
  "NORMAL: turn on the GOLD key functions    GOLD: same"
  (interactive)
  (message "GOLD-")
  (setq gold-key-active t))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-pf2 ()
  "NORMAL: EDT Help    GOLD: apropos on a selected topic - try edt"
  (interactive)
  (if gold-key-active
      (progn
	(apropos (read-input "Help topic: "))
	(setq gold-key-active nil))
    ; otherwise display a help screen the way edt does
    (describe-variable 'edt-map)
    (other-window '1)
    (search-forward "maps VT100" (point-max) t)
    (recenter '0)
    (other-window '1)
    (message "Type C-X 1 to remove help window")))
;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-pf3 ()
  "NORMAL: FNDNXT   GOLD: FIND a string in the current direction
FNDNXT finds the next occurrence of the find string"
  (interactive)
  (if gold-key-active
      (progn
	; FIND
	(setq edt-find-string (read-input "Search for: "))
	(setq gold-key-active nil)))
  ; FIND and FNDNXT
  (message (concat "Searching for " "\"" edt-find-string "\""))
  (if (eq '1 edt-direction)
      (search-forward edt-find-string (point-max) nil)
    (search-backward edt-find-string (point-min) nil)))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-pf4 (num)
  "NORMAL: delete a line    GOLD: undelete a line"
  (interactive "p")
  (if gold-key-active
      (progn
	; UND L
	(edt-undelete-lines)
	(setq gold-key-active nil))
    ; DEL L
    (edt-delete-current-line num)))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-period ()
  "NORMAL: SELECT set the mark at the current cursor position    GOLD: RESET
cancels the effect of the Gold key, sets the current direction to forward"
  (interactive)
  (if gold-key-active
      (progn
	; RESET
	(redraw-display)
	(setq gold-key-active nil)
	; Set the current direction to forward
	(edt-4))
    ; else SELECT by setting the mark
    (push-mark (point))))
  
;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-enter ()
  "NORMAL: none    GOLD: SUBS replace string starting from current position"
  (interactive)
  (if gold-key-active
      (progn
	; SUBS
	(let (old-string
	      new-string)
	  (setq old-string (read-input "Replace string: "))
	  (setq new-string
		(read-input
		 (concat "Replace string " old-string " with: ")))
	  (replace-string old-string new-string nil)
	  (setq gold-key-active nil)))
    ; else the user must hit RET instead of the ENTER key.  Sorry . . .
    (message "Enter key not used.  Hit <cR> instead")))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-comma (num)
  "NORMAL: delete a character in current direction    GOLD: undelete a character"
  (interactive "p")
  (if gold-key-active
      (progn
	; UND C
	(edt-undelete-chars)
	(setq gold-key-active nil))
    ; DEL C
    (edt-delete-current-char (* edt-direction num))))

;* * * * * * * * * * * * * * * * * * * * * 
(defun edt-minus (num)
  "NORMAL: delete a word in the current direction   GOLD: undelete a word"
  (interactive "p")
  (if gold-key-active
      (progn
	; UND W
	(edt-undelete-words)
	(setq gold-key-active nil))
    ; DEL W
    (edt-delete-current-word (* edt-direction num))))

;* * * * * * * * * * * * * * * * * * * * *
(defun edt-mode ()
"Begin emulating DEC's EDT editor.  Sets up the arrow and keypad keys.
Hit PF2 for the keypad bindings.  Note that this function does not
work if called directly from the .emacs file.  Instead, the .emacs
file should do (setq term-setup-hook 'edt-mode) Then this function
will be called at the time when it will work."
  (interactive)
  ; disable default binding of esc [
  (global-unset-key "\e[")
  ; VT100 arrow keys
  (global-set-key "\e[A" 'previous-line)
  (global-set-key "\e[B" 'next-line)
  (global-set-key "\e[C" 'forward-char)
  (global-set-key "\e[D" 'backward-char)
  (global-set-key "\eOA" 'previous-line)
  (global-set-key "\eOB" 'next-line)
  (global-set-key "\eOC" 'forward-char)
  (global-set-key "\eOD" 'backward-char)

  ; Create edt's delete buffer
  (get-buffer-create edt-delete-buffer)

  ; Make direction of motion show in mode line.  Note that in this version
  ; edt emulation is always on
  (or (assq 'edt-direction-string minor-mode-alist)
      (setq minor-mode-alist (cons '(edt-direction-string edt-direction-string)
				   minor-mode-alist))))
-- 
    Peter Mroz                    |    E.I. Du Pont de Nemours & Co.
    eplrx7!mroz@uunet.uu.net      |    Consultant, Scicon
    mrozpa%wmvx@dupont.com        |    DuPont Building, D4078
                                  |    Wilmington, DE 19898
--
The UUCP Mailer

