home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
me34src.zip
/
me3
/
mutt
/
builtin
/
basic.mut
< prev
next >
Wrap
Lisp/Scheme
|
1995-01-14
|
45KB
|
1,741 lines
;; Basic user interaction commands
;; C Durland 9/92 Public Domain
;?*(yesno)
;?*pgm*(delete-char n) - delete n characters. ?n < 0? do as pgm
;/Changed (looking-at any ...) to
;/ (looking-at pattern move) [STRING [BOOL] : BOOL]
;;;;;;;;;; keymaps
;; Keymaps have two parts: prefix keys, the keymap
;; Ids: 0 is global map, 1 is buffer local map, manage like marks.
;; Always immortal, can't free
;; (prefix-key keymap-id ...)
;;/(create-keymap)
;;/(clear-keymap) Yech - only for back compatibility
;;/(install-keymap id)
;;/(bind-key keymap-id pgm-name key-name ...)
; ability to program the dialog buffer eg want to bind a key to insert the
; current buffer (M-.). Also want to unbind everything so you don't have
; to use C-q in describe-key.
; bring out the undo numbers so they can be configured. Also save undo stats.
;; (window-length n x)
;; x : shrink top window, shrink bottom window, you decide
;; z : the window to shrink????
;; Notes
;; make arg-prefix int32
;; replace or add twiddle.mut with transpose- stuff from simple.el
;; add (do-self-insert) so can do a read-only mode or vi mode
;; 2 mods to (nth-buffer n) - negative n and skip flags.
;; read-only
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;added:
; /(scroll-other-window)
; Note big difference with GNU scroll-down/up = like my pager
(include me.mh)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(small-int goal-column)
;; Move forward by full lines. If prefix < 0 move backwards.
;; The last command controls how the goal column is set.
;; Bound to "C-n"
(defun
next-line
{
(bool s)
;; Reset goal if last key not C-p or C-n
(if (command-flag CMDFLG-NTEST-AND-SET CF-LINE)
(goal-column (current-column)))
(s (forward-line (arg-prefix)))
(current-column goal-column)
(arg-flag FALSE 1) ;; reset arg count
s
}
previous-line { (arg-prefix (- 0 (arg-prefix))) (next-line) }
)
(defun
nextchar (int n) HIDDEN
{
(arg-flag FALSE 1) ;; reset arg count
(forward-char n)
}
next-character { (nextchar (arg-prefix)) }
previous-character { (nextchar (- 0 (arg-prefix))) }
)
(defun
MAIN
{
(bind-key GLOBAL-KEYMAP
"next-line" "C-n"
"previous-line" "C-p"
"next-character" "C-f"
"previous-character" "C-b"
)
}
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Notes:
;; For self-insert characters,
;; (arg-prefix n)(exe-key (convert-to CHARACTER char))) will put n
;; chars in to the current buffer. But if char is bound to
;; anything (like tab is), you could get an infinite loop.
(defun insert-n-chars (int n)(string chars) HIDDEN
{
(int j)
(j n)(while (< 0 j) { (insert-text chars)(-= j 1) })
})
;; Insert tab(s) into buffer.
;; If tabsize == 0, use true tabs. Otherwise, simulate tab stops every
;; tabsize characters using blanks.
;; Bound to "C-i"
(defun tab
{
(int n tab-size)
(n (arg-prefix))
(arg-flag FALSE 1) ;; reset arg count
(if (<= n 0) (done)) ;; I can insert 0 or more tabs but not less
(if (== 0 (tab-size (tab-stops)))
(insert-n-chars n "^I")
{
(arg-prefix (- (* n tab-size) (mod (- (current-column) 1) tab-size)))
(exe-key 0x20)
})
; (insert-n-chars
; (- (* n tab-size) (mod (- (current-column) 1) tab-size)) " "))
TRUE
})
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Insert a newline.
;; Bound to "C-m"
;; Returns:
;; TRUE or aborts
(defun newline
{
(int n)
(n (arg-prefix))
(arg-flag FALSE 1) ;; reset arg count
(if (<= n 0) ;; I can insert 0 or more newlines but not less
{ TRUE (done) })
(insert-n-chars n "^J")
TRUE
})
;; Open up some blank space. The basic plan is to insert a bunch of
;; newlines, and then back up over them.
;; Bound to "C-o" (oh)
(defun open-line
{
(int n)
(n (arg-prefix))
(if (<= n 0)
{
(arg-flag FALSE 1) ;; reset arg count
(done) ;; nothing to do in this case
})
(newline)
(forward-char (- 0 n))
})
;; Insert a newline, then enough tabs and spaces to duplicate the
;; indentation of the previous line. Assumes tabs are every eight
;; characters. Figure out the indentation of the current line. Insert a
;; newline by calling the standard routine. Insert the indentation by
;; inserting the right number of tabs and spaces.
;; Notes:
;; If the cursor is in the middle of the leading whitespace, don't go
;; past it when calculating the indent. This makes newline-and-indent
;; at the start of a line work "right".
;; ??? If the current line is blank, should I get rid of the whitespace?
;; ??? If doing more than one newline-and-indent, do I leave lines with
;; just whitespace on them?
;; !!!???(is-space) thinks C-l is white space so this will indent screwy
;; under page breaks. Is this a bug? Maybe should use (looking-at '[
;; ^I]') (like the C code did). Could also break the line, use
;; looking-at '\ +' to get the indent Drawback is may not be optimal
;; tabbing vs spaces - BFD?
;; Bound to "C-j"
(defun newline-and-indent
{
(int n col indent)
(n (arg-prefix))
(arg-flag FALSE 1) ;; reset arg count
(if (<= n 0) (done))
(col (current-column))
(current-column 1)
(while (and (is-space) (!= col (current-column))) (forward-char 1))
(indent (current-column))
; (current-column col)
;
; (while (!= 0 n)
; {
; (newline)(to-col indent)
; (-= n 1)
; })
(current-column 1)
(if (looking-at '\ +$') ;; doesn't work for <ws><dot>[<ws>]text
(delete-whitespace)
(current-column col))
(insert-n-chars n "^J")
(to-col indent)
})
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;; Regions, Cuts and Yanks ;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Routine to add text to the cut buffer.
;; This is a routine that everybody calls (instead of putting the code
;; in all the routines) because:
;; - Localizes cut buffer management.
;; - Allows other packages to overload this. For example, the
;; kill-ring creates its own hook and the cut routines just work.
(defun
cut-save-hook (int mark1 mark2) (bool prepend)
{
;; Clear the cut buffer if last command wasn't also a cut
(if (command-flag CMDFLG-NTEST-AND-SET CF-CUT) (clear-bag CUT-BUFFER))
(if prepend
(prepend-to-bag CUT-BUFFER APPEND-REGION mark1 mark2)
(append-to-bag CUT-BUFFER APPEND-REGION mark1 mark2))
TRUE
}
)
;; Copy all of the characters in the region to the cut buffer. Don't move
;; dot at all. This is a bit like a cut region followed by a yank.
;; Bound to "M-w"
(defun copy-region
{
(if (not (mark-valid THE-MARK))
{ (msg "Need to set the mark!") FALSE (done) })
(floc "cut-save-hook" THE-DOT THE-MARK FALSE)
TRUE
})
;; Copy the region to the cut buffer and then delete it.
;; Bound to "C-w"
(defun cut-region { (if (copy-region) (delete-region)) })
;; Yank text back from the cut buffer.
;; Bound to "C-y"
;; Notes:
;; This works or aborts - insert-bag bails if it runs out of memory.
(defun yank
{
(int n)
(n (arg-prefix))
(arg-flag FALSE 1) ;; reset arg count
(if (<= n 0) { TRUE (done) }) ;; nothing to do in this case
(while (!= 0 n) { (insert-bag CUT-BUFFER)(-= n 1) })
TRUE
})
;; Cut line(s) of text.
;; If called without an argument, it cuts from dot to the end of the line,
;; unless it is at the end of the line, where it cuts the newline.
;; If called with an argument:
;; 0: Cut from the start of the line to dot.
;; Positive: Cut from dot forward over that number of newlines.
;; Negative: Cut backwards that number of newlines.
;; Bound to "C-k"
;; Notes:
;; If n > number of lines left in the buffer, just cut those. This means
;; you can use a real big n to delete all text to the end of the buffer.
;; This also fixes a problem for Mutt programs that got a region (that
;; included the end-of-buffer) and tried to use cut-line to delete the
;; region.
;; The end of buffer checking is pretty sloppy. I can get away with this
;; because forward-line doesn't wrap around the ends of the buffer.
;;
(defun cut-line
{
(int n mark)
(set-mark (mark (create-mark)))
(if (not (arg-flag))
{
; (n (current-column))(end-of-line)
; (if (== 0 (- (current-column) n)) (forward-line 1))
(if (looking-at '\ *$') ;; GNU behavior
(forward-line 1)
(end-of-line))
}
(forward-line (arg-prefix)))
(floc "cut-save-hook" THE-DOT mark (< (arg-prefix) 0))
(delete-region THE-DOT mark)
(free-mark mark)
(arg-flag FALSE 1) ;; reset arg count
TRUE ;;!!!???!!! can I check this? do I care?
})
;; Delete n characters at the dot in the current buffer. If n is
;; negative, delete n characters before the dot.
;; Input:
;; n : number of characters to delete.
;; Notes:
;; If n is bigger than the number of characters to either end of the
;; buffer (ie trying to delete more than there is), only delete what
;; can.
;; This is the same as delete-characters but is not meant to be called by
;; a user key.
(defun
delete-char (int n)
{
(int mark)
(set-mark (mark (create-mark)))
(forward-char n)
(delete-region THE-DOT mark)
(free-mark mark)
TRUE ;;!!!???? return value?
}
)
;; Delete n characters at the dot in the current buffer. If n is
;; negative, delete n characters before the dot.
;; Input:
;; n : number of characters to delete.
;; Notes:
;; If n is bigger than the number of characters to either end of the
;; buffer (ie trying to delete more than there is), only delete what
;; can.
;; If 1 < (abs n), put the characters in the cut buffer. This to make it
;; easy to recover from accidently typing something like C-u 12345 C-h.
;; Not sure how useful this is with undo.
;; If deleting backwards, prepend cut text to the cut buffer so it will
;; look correct when yanked.
(defun
delete-characters (int n) HIDDEN
{
(bool a-cut)
(int mark)
(a-cut (arg-flag))
(set-mark (mark (create-mark)))
(forward-char n)
(if a-cut (floc "cut-save-hook" THE-DOT mark (< n 0)))
(delete-region THE-DOT mark)
(free-mark mark)
(arg-flag FALSE 1) ;; reset arg count
TRUE ;;!!!??? can I check this?
}
)
;; Delete forward.
;; If any argument is present, it cuts rather than deletes, to prevent loss
;; of text if typed with a big argument.
;; Normally bound to "C-d"
(defun delete-character { (delete-characters (arg-prefix)) })
;; Delete backwards.
;; Like delete forward, this actually does a cut if argument (^U) used.
;; Bound "C-h" (backspace).
(defun delete-previous-character
{ (delete-characters (- 0 (arg-prefix))) })
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun any-modified-buffers
{
(int j bp)
(for (j 0) (< j (buffers)) (+= j 1)
{
(bp (nth-buffer j))
(if (== BFModified ;; Check to see if we care about this buffer
(bit-and (buffer-flags bp) (bit-or BFModified BFNoCare)))
{ TRUE (done) })
})
FALSE
})
;; Quit command. If an argument, always quit. Otherwise confirm if a
;; buffer has been changed and not written out.
;; Bound to "C-x C-c" and "C-c"
(defun exit
{
(if (or (arg-flag) ;; Argument forces it
(not (any-modified-buffers)) ;; All buffers clean
(yesno "Modified buffers! Exit anyway")) ;; User says it's OK
(stop-ME EXIT-ME))
})
;; Abort.
;; Beep the beeper. Cut off any keyboard macro, etc., that are in progress.
;; Bound to "C-g"
(defun
abort
{
(stop-ME HALT-ALL-PROGRAMS) ;; also stops this routine
}
MAIN { (register-hook STOP-ME-HOOK "terminated") }
terminated (int n)
{
(if (== n HALT-ALL-PROGRAMS)
{
(msg "[Terminated]")
(beep)
})
}
)
(defun
buffer-read-only (bool read-only)
{
(if (== (nargs) 1) ;; got read-only
(buffer-flags -1
(if read-only
(bit-or (buffer-flags -1) BFRead_only)
(bit-clear (buffer-flags -1) BFRead_only))))
(!= 0 (bit-and (buffer-flags -1) BFRead_only))
}
toggle-read-only { (buffer-read-only (not (buffer-read-only))) }
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Files ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun
cannonize-file-name (string fname)
{
(int bid)
(bid (create-buffer ""))
(file-name bid fname)
(fname (file-name bid))
(free-buffer bid)
(!= "" fname)
}
attached-file (string full-file-name)
{
(int j)
(for (j 0) (< j (buffers)) (+= j 1)
(if (== full-file-name (file-name (nth-buffer j)))
{ (nth-buffer j) (done) }))
-2
}
make-unique-buffer-name (string base-name)
{
(int n)
(string new-name)
(if (== -2 (attached-buffer base-name)) { base-name (done) })
(n 1)
(while
(!= -2 (attached-buffer (new-name (concat base-name "<" (+= n 1) ">"))))
())
new-name
}
)
(const
PF-VISIT 0
PF-READ 1
PF-INSERT 2
PF-WRITE 3
)
;; Prompt and ask for a file name for the file read/write/insert
;; routines.
;; What it does:
;; - If the current buffer has a file name and that file name is a
;; path (ie has a "/" in it), prime ask with the path. Otherwise,
;; prime ask with the current directory (being careful not to prime
;; with "//" in case cwd is "/".
;; - Ask the user for a file name.
;; - If they don't change the prime, return "" (since a path is not a
;; file name).
;; If they type "/foo", "~/foo" or "C:foo" (such that the input
;; looks like "/hoho//foo" because of the prime), return "/foo".
;; This makes it easy to override the prime. This is what GNU
;; does.
;; Return the input.
;; Notes:
;; The prime breaks file name completion if you have something like
;; "/hoho//foo". Not sure how to fix this. Don't like it in C
;; code, maybe with a programmable minibuffer could detect this
;; case before the completion occurs.
;; This is OS specific. Ick. But can be overridden.
(defun
ask-for-file-name (int op)(string prompt)
{
(string fname b prime)
(prime
(if (and (!= "" (file-name -1)) (re-string '\(.+/\)' (file-name -1)))
(sub~ (get-matched "&"))
(concat (sub~ (current-directory))
(if (== "/" (extract-elements (current-directory) -1 1)) "" "/"))))
(prime-ask prime) (ask-user) (fname (complete CC_FNAME prompt))
(cond
(== prime fname) (fname "") ;; No response == ""
(== prime (extract-elements fname 0 (length-of prime)))
{
(b (extract-elements fname (length-of prime) 1000))
(if
(or
(re-string '\(/.+\)' b) ;; /foo//bar => /bar
(re-string '\(~.+\)' b) ;; /foo/~/bar => ~/bar
(re-string '\([a-zA-Z]:.+\)' b)) ;; /foo/C:/bar => C:/bar
(fname (get-matched '\1')))
})
fname
}
)
(defun
read-it (string fname) HIDDEN
{
(bool save-undo s)
(int n error-code)
(save-undo (undo-state))(turn-off-undo)
(clear-buffer)
(msg "Reading file ...") ;; this can take a long time
(s
(if (file-to-buffer fname (loc n) (loc error-code))
{
(msg "[Read " n " line" (if (!= 1 n) "s]" "]"))
(beginning-of-buffer)
(read-file-hook)
TRUE
}
{
(if (== FIO_FNF error-code)
{ (msg "[New file]") TRUE }
FALSE)
}))
(buffer-modified -1 (not s)) ;; Not modified if no errors
(undo-state save-undo)
s
}
write-it (file-name) HIDDEN
{
(int n error-code)
(msg "Writing file ...") ;; this can take a long time
(if (buffer-to-file file-name (loc n) (loc error-code))
{ (msg "[Wrote " n " line" (if (!= 1 n) "s]" "]")) TRUE }
{
(if (!= 0 (bit-and (buffer-flags -1) BFBad_read))
(msg "Buffer didn't read correctly, not written."))
FALSE
})
}
)
;; Select a file for editing.
;; Look around to see if you can find the file in another buffer; If you
;; can find it just make it current. If you cannot find the file, read
;; it into a buffer and make current.
;; Input:
;; f: If no arg, use the current window to display the buffer.
;; Otherwise, split the current window to create a new window for the
;; buffer.
;; Bound to "C-xC-v" and "C-xC-f"
(defun
visit-file
{
(bool popup)
(int bid)
(string fname bname)
(popup (arg-flag))
(arg-flag FALSE 1) ;; reset arg count
(fname
(if (== 0 (nargs))
(floc "ask-for-file-name" PF-VISIT "Visit file: ")
(ask)))
(if (== "" fname) { FALSE (done) }) ;;!!!???
(if (not (cannonize-file-name fname))
{
;;!!!?? do I want complain?
(msg "Not a valid file name!")
FALSE
(done)
})
(if (!= -2 (bid (attached-file fname)))
{
(msg "[Old buffer]")
(if popup ;; popup a window for the buffer
(current-window (popup-buffer bid 1 1))
{
(current-buffer bid TRUE)
(current-line 1)
})
TRUE
(done)
})
(bname (make-unique-buffer-name (buffer-name fname)))
(bid (create-buffer bname BFHuman))
(file-name bid fname)
(if popup ;; popup a window for the buffer
(current-window (popup-buffer bid 1 1))
(current-buffer bid TRUE))
(read-it fname)
}
)
;; Read a file into the current buffer. This is really easy; all you do
;; is find the name of the file, and call the standard "read a file
;; into the current buffer" code.
;; Bound to "C-x C-r"
(defun read-file
{
(string read-from)
(arg-flag FALSE 1) ;; reset arg count
(read-from
(if (== 0 (nargs))
(floc "ask-for-file-name" PF-READ "Read file: ")
(ask)))
(if (and (== "" read-from) (== "" (read-from (file-name -1))))
{
(msg "Buffer \"" (buffer-name -1)
"\" is not attached to a file, can't read.")
FALSE
(done)
})
;;;!!! good enough test or restrict to MUNGED buffers?
(if (and (buffer-modified -1)
(not (yesno "Buffer has been modified, overwrite it anyway")))
{ FALSE (done) })
(file-name -1 read-from)
(read-it read-from)
})
;; Insert a file at the dot.
;; Leave the dot at the start of the insert and put the mark after the
;; insert (ala GNU).
(defun insert-file
{
(int n error-code)
(string read-from)
(read-from
(if (== 0 (nargs))
(floc "ask-for-file-name" PF-INSERT "Insert file: ")
(ask)))
(if (== "" read-from)
{
(msg "Not a valid file name!")
FALSE
(done)
})
(set-mark THE-MARK)
(if (file-to-buffer read-from (loc n) (loc error-code))
{
(swap-marks)
(msg "[Inserted " n " line" (if (!= 1 n) "s]" "]"))
TRUE
}
{
(if (== FIO_FNF error-code) (msg "\"" read-from "\" not found!"))
FALSE
})
})
;; Ask for a file name and write the contents of the current buffer
;; to that file. Clear the buffer changed flag.
;; Bound to "C-x C-w"
(defun write-file
{
(string write-to)
(write-to
(if (== 0 (nargs))
(floc "ask-for-file-name" PF-WRITE "Write file: ")
(ask)))
(if (and (== "" write-to) (== "" (write-to (file-name -1))))
{
(msg "Buffer \"" (buffer-name -1)
"\" is not attached to a file, can't write.")
FALSE
(done)
})
(write-it write-to)
})
;; Save the contents of the current buffer in its associatd file. Do
;; nothing if nothing has changed (this may be a bug, not a feature).
;; Error if there is no remembered file name for the buffer.
;; Bound to "C-x C-s"
(defun save-buffer
{
(int n)
(if (== "" (file-name -1)) ;; Must have a name
{
(msg "No file name for buffer \"" (buffer-name -1) "\".")
FALSE
(done)
})
(if (== 0 (bit-and (buffer-flags -1) BFModified))
{
(msg "Buffer \"" (buffer-name -1) "\" not modified, not written.")
TRUE
(done)
})
(write-it (file-name -1))
})
(defun MAIN
{
(bind-key GLOBAL-KEYMAP
"insert-file" "C-xi"
"read-file" "C-xC-r"
"visit-file" "C-xC-f"
"visit-file" "C-xC-v"
"save-buffer" "C-xC-s"
"write-file" "C-xC-w")
})
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Select a new current buffer and attach it to a current window.
;; If arg-flag, then the buffer must exist.
;; Changes the current buffer and current window.
;; Bound to "C-x b"
;; Notes
;; Undo is turned on (via buffer-created-hook in undo.mut) for interactive
;; buffers.
(int switch's-previous-buffer)
(defun
switch-to-buffer
{
(bool aflag)
(int bid previous-bid)
(string new-buffer-name)
;; if previous buffer doesn't exist, turn off prompt
(if (not (buffer-exists switch's-previous-buffer))
(switch's-previous-buffer -1))
(new-buffer-name (complete CC_BUF
(concat
"Use buffer"
(if (== -1 switch's-previous-buffer)
": "
(concat " [" (buffer-name switch's-previous-buffer) "]: ")))))
(aflag (arg-flag))
(arg-flag FALSE 1) ;; reset arg count
(if (and
(== "" new-buffer-name)
(== "" (new-buffer-name (buffer-name switch's-previous-buffer))))
{ FALSE (done) })
(previous-bid (current-buffer))
(if (!= -2 (bid (attached-buffer new-buffer-name)))
(current-buffer bid TRUE) ;; The buffer already exists
(if (aflag) ;; It doesn't but should
{
(msg "Buffer \"" new-buffer-name "\" does not exist.")
FALSE
(done)
}
(current-buffer ;; Create that sucker
(create-buffer new-buffer-name
(bit-or BFImmortal BFInteractive)) TRUE)))
(switch's-previous-buffer previous-bid)
TRUE
}
use-existing-buffer
{
(arg-prefix 1)
(switch-to-buffer (complete CC_BUF "Use existing buffer: "))
}
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Marks ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun
mark-valid (int mark-id)
{
(save-point {{ (goto-mark (arg 0)) }} mark-id)
}
)
(defun
exchange-dot-and-mark
{
(if (not (mark-valid THE-MARK))
{ (msg "Need to set the mark!") FALSE (done) })
(swap-marks THE-DOT THE-MARK)
}
set-the-mark
{
(set-mark THE-MARK)
(msg "Mark set.")
}
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;; Cursor Movement ;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun
beginning-of-buffer { (current-line 1) }
end-of-buffer { (current-line -1)(forward-line 1) }
beginning-of-line { (current-column 1) }
end-of-line { (if (forward-line 1) (forward-char -1)) }
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun ME-command
{
(string command)
(command (complete (bit-or CC_PGM CC_SYSVAR) "Run command: "))
(if (== "" command) { FALSE (done) }) ;;!!!???
(if (not (pgm-exists command))
{
(if (check-name-of-sysvar command FALSE)
{
(set-sysvar command)
(done)
})
(msg "Command \"" command "\" does not exist.")
(need-help 0)
(done)
})
(floc (command) ())
})
;; Universal argument
;; Grap arg from keyboard, run the key.
;; Bound to "C-u"
;; Notes:
;; The arg is maintained as a positive number because it makes the math
;; easier.
;; You can prime the arg. For example, if you want M-5 to run
;; universal-argument starting at 5, use:
;; (defun Meta-5 { (arg-prefix 5)(universal-argument) }
;; (bind-to-key "Meta-5" "M-5")
(int universal-argument-status)
(defun
universal-argument-no-key
{
(== 0 universal-argument-status)
}
universal-argument
{
(int key n mflag)
(mflag 0) ;; -1 => minus, 0 => no key hit, 1 => key hit
(n (if (arg-flag) (arg-prefix) 4))
(msg "Arg: " n)
(while (or
(and (<= 0x30 (key (get-key))) (<= key 0x39)) ;; 0 <= key <= 9
(== key 0x155) ;; C-u
(== key 0x2D)) ;; -
{
(cond
(== key 0x155) (*= n 4) ;; C-u
(== key 0x2D) ;; -
{
(if (!= 0 mflag) (break))
(n 0) (mflag -1)
}
TRUE
{
(if (== 0 mflag) { (if (not (arg-flag)) (n 0)) (mflag 1) })
(n (+ (* 10 n)(- key 0x30))) ;; n = 10*n +(key - '0')
}
)
(msg "Arg: " (if (>= mflag 0) n (if (!= 0 n) (- 0 n) -1)))
})
(if (== -1 mflag) { (if (== 0 n) (n 1) (*= n -1)) })
(universal-argument-status mflag)
(arg-prefix n)(exe-key key)
;; (exe-key) resets arg count
}
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Words ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Notes:
;; Could merge delete-words with delete-characters easily.
;; If deleting backwards, prepend cut text to the cut buffer so it will
;; look correct when yanked.
(defun
delete-words (int n) HIDDEN
{
(int mark)
(set-mark (mark (create-mark)))
(forward-word n)
(floc "cut-save-hook" THE-DOT mark (< n 0))
(delete-region THE-DOT mark)
(free-mark mark)
(arg-flag FALSE 1) ;; reset arg count
TRUE ;; !!!??? am I sure
}
cut-word { (delete-words (arg-prefix)) }
cut-previous-word { (delete-words (- 0 (arg-prefix))) }
)
(defun
forward_word (int n) HIDDEN
{
(arg-flag FALSE 1) ;; reset arg count
(forward-word n)
}
next-word { (forward_word (arg-prefix)) }
previous-word { (forward_word (- 0 (arg-prefix))) }
)
(defun
MAIN
{
(bind-key GLOBAL-KEYMAP
"cut-previous-word" "M-C-h"
"cut-word" "M-d"
"cut-word" "M-C-?"
"next-word" "M-f"
"previous-word" "M-b")
}
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; OS Stuff ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Fork a shell so the user can mess around outside of ME and return to
;; their edit session later.
;; Bound to "C-z"
(defun spawn-shell
{
(OS-shell (arg-prefix))
(arg-flag FALSE 1) ;; reset arg count
TRUE
})
;; Have the OS (usually though a shell) run a command (such as "ls").
;; Bound to "C-x !"
(defun shell-command ; [(string the-command)]
{
(string command)
;;!!! actually, this should be if no args or ask-user
(if (== 0 (nargs)) ;; (shell-command) most likely just bound to a key
{
(if (== "" (command (ask "Shell command: "))) { FALSE (done) })
(ask-user)
(OS-command command "[Return to resume editing]")
}
(OS-command (arg 0)))
})
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Quote the next character, and insert it into the buffer. All the
;; characters are taken literally, with the exception of the newline,
;; which always has its line splitting meaning. The character is
;; always read, even if it is inserted 0 times, for regularity.
;; Bound to "C-q" and "C-^" (for terminals that need XON-XOFF).
;; Notes:
;; Doesn't work so hot for multi character keys (like the function keys).
(defun quote
{
(int n)
(string key)
(n (arg-prefix))
(arg-flag FALSE 1) ;; reset arg count
(key (getchar))
(if (== key "0") ;;!!!??? ^Qx31 => "1"?
(key (convert-to CHARACTER (convert-to NUMBER (ask "ASCII number: ")))))
(if (<= n 0) (done)) ;; that was easy
(insert-n-chars n key)
})
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;!!! I really need to set parents ask frame here!
(defun
bind-to-key
{
(string command key)
(if (== "clear-keymap" (command (complete CC_PGM "Global bind command: ")))
(clear-keymap GLOBAL-KEYMAP)
(bind-key GLOBAL-KEYMAP command
(if (== "" (key (ask "To key: "))) "C-m" key)))
}
bind-local-key
{
(string command key)
(if (== "clear-keymap" (command (complete CC_PGM "Local bind command: ")))
(clear-keymap LOCAL-KEYMAP)
(bind-key LOCAL-KEYMAP command
(if (== "" (key (ask "To key: "))) "C-m" key)))
}
)
;;!!! clone GNUs global-set-key and local-set-key
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;; Keyboard Macros ;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun
MAIN { (register-hook STOP-ME-HOOK "End-macro") }
End-macro
{
(if (== MACRO-RECORDING (keystroke-macro MACRO-STATE))
(McModeline FALSE))
}
start-macro
{
(if (!= MACRO-OFF (keystroke-macro MACRO-STATE))
{ (msg "Can't start a macro now.")(done) })
(keystroke-macro MACRO-START)
(McModeline TRUE)
}
end-macro
{
(if (!= MACRO-RECORDING (keystroke-macro MACRO-STATE))
{ (msg "Not recording a macro!")(done) })
(keystroke-macro MACRO-END)
(McModeline FALSE)
}
execute-macro
{
(int n)
(if (!= MACRO-OFF (keystroke-macro MACRO-STATE))
{ (msg "Stop recording before replaying.")(done) })
(n (arg-prefix))
(arg-flag FALSE 1) ;; reset arg count
(keystroke-macro MACRO-REPLAY n)
}
MAIN
{
(bind-key GLOBAL-KEYMAP
"end-macro" "C-x)"
"execute-macro" "C-xe"
"start-macro" "C-x(")
}
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;; Library Routines ;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;!!! I could pack bit-or, bit-and and bit-xor into (bit-op op x y z ...)
;; and put the routines here.
(defun
bit-not (int x) { (bit-xor x -1) }
bit-clear (int x bit) { (bit-and x (bit-not bit)) }
)
(defun
BoB ;; return TRUE if at begining of buffer
{
(if (forward-char -1)
{ (forward-char 1) FALSE }
TRUE)
}
;; Notes
;; EoB is just as easy (but would be slow in a while loop).
)
(defun
save-point (pointer defun code) ;; [args]
{
(int point)
(set-mark (point (create-mark)))
(restore-point-and-return-value
{{
(goto-mark (arg 0))(free-mark (arg 0))
}} (code (push-args 1)) point)
}
save-excursion (pointer defun code) ;; [args]
{
(bool displayed)
(int buffer mark)
(set-mark (mark (create-mark)))
(buffer (current-buffer))
(displayed (== buffer (attached-buffer (current-window))))
(restore-point-and-return-value
{{
(current-buffer (arg 0) (arg 1))
(goto-mark (arg 2))(free-mark (arg 2))
}} (code (push-args 1)) buffer displayed mark)
}
restore-point-and-return-value
(pointer defun restore-point) ; return-value args-for-code
HIDDEN
{
(restore-point (push-args 2))
(arg 1) ;; Return value
}
)
;; Returns:
;; -2 : Buffer not displayed in a window
;; id : Id of window showing buffer
(defun
buffer-displayed (int buffer-id)
{
(int n)
(for (n 0) (< n (windows)) (+= n 1)
(if (== buffer-id (attached-buffer n)) { n (done) }))
-2 ;; buffer not displayed
}
)
(defun
buffer-exists (int buffer-id)
{
(int j)
(for (j 0) (< j (buffers)) (+= j 1)
(if (== buffer-id (nth-buffer j)) { TRUE (done) }))
FALSE
}
)
(defun
prepend-to-bag (int the-bag op)
;; (string text) | (int mark1 mark2) | (int chars)
{
(int bag)
(bag (create-bag))
(append-to-bag bag (push-args 1))
(append-to-bag bag APPEND-TEXT (bag-to-string the-bag))
(clear-bag the-bag)
(append-to-bag the-bag APPEND-TEXT (bag-to-string bag))
(free-bag bag)
}
)
(defun
foreach (object)(pointer defun code)
{
(int n j)
(n (length-of object))
(for (j 0) (< j n) (+= j 1)
(if (not (code (extract-element object j) (push-args 2))) (break)))
}
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Load Mutt code from a file.
;; Notes:
;; There is a bit of a sleeze here. I want to (sometimes) load a file
;; only if it hasn't already been loaded so I (way) overload the
;; flags. This is for back compatibility with ME2.
(defun
load
{
(bool complain check-first)
(complain (not (arg-flag)))
(check-first (if (== 42 (arg-prefix)) TRUE FALSE))
(arg-flag FALSE 1) ;; reset arg count
(load-code (complete CC_FNAME "Load file: ") complain check-first)
}
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;; The ME Command Line ;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; file eg me2 foo
;; +linenum file eg me2 +34 foo
;; -i file eg me2 -i foo, me2 +30 foo -i sam
;; -insert file same as -i
(bool read-em-all read-a-file)
(defun
next-file
{
(int n)
(n (arg-prefix))
(arg-flag FALSE 1) ;; reset arg count
(while (>= (-= n 1) 0)
{
(read-a-file FALSE)
(if (any-cmd-line-args-left)
(process-command-line)
{ (msg "All files read in.")(done) })
})
}
)
(defun
MAIN
{
(register-hook COMMAND-LINE-HOOK "ME-command-line")
}
ME-command-line (string cmd-arg)
{
(int n)
(string the-arg)
(cond
(re-string '\+\(\d+\)$' cmd-arg) ;; +linenum file
{
(n (convert-to NUMBER (get-matched '\1')))
(next-cmd-line-arg the-arg)(visit-file the-arg)
(current-line n)
}
(== "-all" cmd-arg) (read-em-all TRUE) ;; -all
(or (== "-i" cmd-arg)(== "-insert" cmd-arg)) ;; -i[nsert] file
{ (next-cmd-line-arg the-arg)(insert-file the-arg) }
(or (== "-l" cmd-arg)(== "-load" cmd-arg)) ;; -l[oad] file
{ (next-cmd-line-arg the-arg)(load the-arg) }
(or (== "-f" cmd-arg)(== "-funcall" cmd-arg)) ;; -f[uncall] pgm
{ (next-cmd-line-arg the-arg)(floc (the-arg)()) }
(re-string '[^--].*' cmd-arg) ;; no leading dash => file
{
(if (and (not (read-em-all)) (read-a-file))
{
(push-back-cmd-arg)
(stop-processing-cmd-line)
}
{
(read-a-file TRUE)
(visit-file cmd-arg)
})
}
TRUE { FALSE (done) } ;; none of the above
)
TRUE ;; one of the above
}
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;; List Commands ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun
do-apropos (string word) HIDDEN
{
(int bid b2)
(if (!= -2 (bid (attached-buffer HELP-BUFFER)))
{
(b2 (current-buffer))
(current-buffer bid)(clear-buffer)
(current-buffer b2)
}
(bid (create-buffer HELP-BUFFER
(bit-or BFNoCare BFImmortal BFInteractive))))
(list-keys bid word 7 GLOBAL-KEYMAP)
(popup-buffer bid 1 1)
}
apropos
{
(do-apropos
(complete (bit-or CC_MUTT CC_PGM CC_SYSVAR) "Apropos keyword: "))
}
describe-bindings { (do-apropos "") }
describe-key ;; what is a key bound to
{
(string key bind)
(key (ask "Key: "))
(if (== "" (bind (key-bound-to key)))(msg key " is not bound.")
(msg key " is bound to " bind))
}
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Ask a yes or no question in the message line. Must be answered with
;; something starting with n, N, y or Y. A CR ain't good enough!
;; Input:
;; prompt: What to ask the user. " [y/n]? " is appended.
;; Returns: TRUE, FALSE, or aborts
;;!!! this is REAL iffy
;; Need to set parents ask frame, access to MMask_pgm()
;(defun yesno ; (string prompt ...)
;{
; (while TRUE
; {
; (ask-user) ;;!!!???
; (switch (extract-elements (ask (push-args 0) " [y/n]? ") 0 1)
; "y" { TRUE (done) }
; "Y" { TRUE (done) }
; "n" { FALSE (done) }
; "N" { FALSE (done) }
; )
; })
;;;!!!???if (MMask_pgm) return FALSE; ;; I think I need this!
;})
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;; Version Info ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Version and other general information about ME. This is (typically)
;; stuff that ME internals send so that Mutt programs can do machine/OS
;; dependent things.
;; Typical keys and list of data with that key:
;; OS: Major (such as Unix or MS-DOS), minor (such as HP-UX).
;; version: Program name (ME), major release, minor, patch level, date
;; of first release (of this version), date this version was released.
;; author: Name, email address, postal address.
;; Indexes into version info
(const
VERSION-VERSION-KEY "version"
VERSION-NAME 0
VERSION-MAJOR 1
VERSION-MINOR 2
VERSION-PATCH 3
VERSION-FIRST-RELEASE 4
VERSION-THIS-RELEASE 5
VERSION-AUTHOR-KEY "author"
VERSION-AUTHOR 0
VERSION-EMAIL 1
VERSION-MAIL 2
VERSION-OS-KEY "OS"
VERSION-OS-MAJOR 0
VERSION-OS-MINOR 1
)
(list version-info)
(defun
version-hook (string key info1 info2) ;; etc
{
(list info)
(insert-object version-info 1000 key (insert-object info 0 (push-args 1)))
}
get-version-info (string key) ;; Return list of infos
{
(int n j)
(n (length-of (version-info)))
(for (j 0) (< j n) (+= j 2)
{
(if (== key (extract-element version-info j))
{
(extract-element version-info (+ j 1))
(done)
})
})
(extract-elements version-info 0 0) ;; empty list
}
version-query (string key subkey)
{
(int n j)
(list info)
(if (== 1 (nargs)) { (get-version-info key)(done) })
(n (length-of (info (get-version-info key))))
(for (j 0) (< j n) (+= j 1)
(if (== subkey (extract-element info j)) { TRUE (done) }))
FALSE
}
)
(const
VERSION-BUFFER "*version-info*"
)
(defun
vn (int n) HIDDEN { (extract-element (get-version-info "version") n) }
vn1 (string key)(int n) HIDDEN
{ (extract-element (get-version-info key) n) }
version
{
(msg (vn VERSION-NAME)(vn VERSION-MAJOR)
" (Mutt Editor " (vn VERSION-MAJOR) ") "
(vn VERSION-FIRST-RELEASE)
" v" (vn VERSION-MAJOR) "." (vn VERSION-MINOR) " "
(vn VERSION-THIS-RELEASE)
" (c) " (vn1 "author" VERSION-AUTHOR)
)
}
; version-verbose
; {
; (int bid b2)
;
; (b2 (current-buffer))
; (if (== -2 (bid (attached-buffer VERSION-BUFFER)))
; (bid (create-buffer VERSION-BUFFER
; (bit-or BFNoCare BFImmortal BFInteractive))))
;
; (popup-buffer bid 1 1)
; (current-buffer bid)(clear-buffer)
; (insert-text
; "Name: " (vn VERSION-NAME)(vn VERSION-MAJOR) "^J"
; "Author: " (vn1 "author" VERSION-AUTHOR) "^J"
; "OS: " (vn1 "OS" VERSION-OS-MAJOR) " " (vn1 "OS" VERSION-OS-MINOR)
; )
; (current-buffer b2)
; }
bug-report
{
(small-int month day year weekday hh mm ss) ;; TimeInfo
(int bid)
(list info)
(read-clock (loc month))
(visit-file "bugreport")
(insert-text
"To: " (vn1 "author" VERSION-EMAIL) "^J"
"Subject: Bug Report for " (vn VERSION-NAME) " "
(vn VERSION-MAJOR) "." (vn VERSION-MINOR) " "
(vn VERSION-PATCH) " " (vn VERSION-THIS-RELEASE) "^J"
"Reply-To: <your email address>^J"
"Date: " month "/" day "/" year "^J"
"^J"
"If you don't have Email, send to:^J" (vn1 "author" VERSION-AUTHOR) ", "
(vn1 "author" VERSION-MAIL) "^J^J"
" OS: " (vn1 "OS" VERSION-OS-MAJOR) " "
(vn1 "OS" VERSION-OS-MINOR) "^J"
"^J"
"Please enter bug report/gripe/comment:^J"
)
(end-of-buffer)
(text-mode)
}
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;; Bug Patches ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;; and Backwards Compatibility ;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun
window-height { (window-length (push-args 0)) }
goto-line (n) { (current-line n) }
)
(defun beeper
{
(if (== 0 (nargs))
(beep -1)
(beep (push-args 0)))
})
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Keys ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun
!9 MAIN HIDDEN ;; do this early! Before any binds
{
(prefix-key 0 "C-[") ;; escape is also Meta
(prefix-key 1 "C-x")
}
)
(defun MAIN ;; bind keys
{
;; hidebuf.mut isearch.mut markring.mut register.mut search.mut
;; compile.mut findit.mut
;; ?GNU Emacs bindings
(bind-key GLOBAL-KEYMAP
"abort" "C-g"
"apropos" "M-?"
"dabbrev-expand" "M-/"
"exchange-dot-and-mark" "C-xC-x"
"set-the-mark" "C-@"
"set-the-mark" "M- "
"exit" "C-xC-c"
"exit" "C-c"
"ME-command" "M-x"
"next-file" "C-xf"
"open-line" "C-o"
"newline" "C-m"
"newline-and-indent" "C-j"
"newline-and-indent" "M-C-o"
"tab" "C-i"
"quote" "C-q"
"quote" 'C-^' ;; In case XOFF takes over C-q
"shell-command" "C-x!"
"spawn-shell" "C-z"
"switch-to-buffer" "C-xb"
"use-existing-buffer" "C-xC-o"
"transpose-chars" "C-t" ;; in twiddle.mut
"universal-argument" "C-u"
"beginning-of-buffer" "M-<"
"end-of-buffer" "M->"
"beginning-of-line" "C-a"
"end-of-line" "C-e"
"copy-region" "M-w"
"cut-region" "C-w"
"yank" "C-y"
"cut-line" "C-k"
"delete-character" "C-d"
"delete-character" "C-?"
"delete-previous-character" "C-h"
"delete-buffer" "C-xk" ;; in delbuf.mut
"query-replace" "M-q" ;; not GNU
"query-replace" "M-%"
"re-query-replace" "M-C-q"
"Goto-line" "M-g"
"indent-rigidly" "C-xC-i" ;; in indent.mut
"list-buffers" "C-xC-b" ;; in bstats.mut
"show-buffer-stats" "C-x=" ;; in bstats.mut
"toggle-read-only" "C-xC-q"
"spell-word" "M-$" ;; in spell.mut
"downcase-region" "C-xC-l" ;; in case.mut
"upcase-region" "C-xC-u" ;; in case.mut
"downcase-word" "M-l" ;; in case.mut
"upcase-word" "M-u" ;; in case.mut
"capitalize-word" "M-c" ;; in case.mut
"copy-to-register" "C-xx" ;; in register.mut
"copy-region-to-rectangle" "C-xr" ;; in register.mut
"insert-register" "C-xg" ;; in register.mut
"point-to-register" "C-x/" ;; in register.mut
"register-to-point" "C-xj" ;; in register.mut
"undo" 'C-_' ;; undo.mut GNU binding
"undo" "C-xu" ;; undo.mut GNU binding
;; Function keys
"delete-whitespace" "F-1" ;; F1
"next-buffer" "F-2" ;; F2
"cut-the-line" "F-5" ;; F5
"p-match" "F-6" ;; F6 in pmatch.mut
"CR->CR&indent" "F-7" ;; F7
"CR->CR" "F-8" ;; F8
"set-the-mark" "F-0" ;; F10
"mark-and-home" "F-A" ;; Home key
"mark-and-end" "F-B" ;; End key
"previous-line" "F-C" ;; Up Arrow
"next-line" "F-D" ;; Down Arrow
"next-character" "F-E" ;; Right Arrow
"previous-character" "F-F" ;; Left Arrow
"center-cursor" "F-G" ;; Insert key
"delete-character" "F-H" ;; Delete key
"previous-page" "F-I" ;; Page Down
"next-page" "F-J" ;; Page Up
"cut-line" "F-K" ;; Clear Line (HP terminals)
"cut-the-line" "F-L" ;; Delete Line (HP terminals)
"set-the-mark" "F-N" ;; Select (HP terminals)
"scroll-down" "F-O" ;; Roll/Scroll Up
"scroll-up" "F-P" ;; Roll/Scroll Down
;; Number pad
"mark-and-home" "F-{" ;; Number pad Home key
"mark-and-end" "F-}" ;; Number pad End key
"previous-line" 'F-^' ;; Number pad Up Arrow
"next-line" "F-." ;; Number pad Down Arrow
"next-character" "F->" ;; Number pad Right Arrow
"previous-character" "F-<" ;; Number pad Left Arrow
"toggle-overstrike" "F-&" ;; Number pad Insert
"delete-character" "F-#" ;; Number pad Delete
"next-page" "F-[" ;; Number pad Page Up
"previous-page" "F-]" ;; Number pad Page Down
;; Mouse
"do-mouse" MOUSE-KEY ;; From the mouse driver
)
})