home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD1.bin
/
new
/
util
/
edit
/
jade
/
lisp
/
edit.jl
< prev
next >
Wrap
Lisp/Scheme
|
1994-10-05
|
15KB
|
514 lines
;;;; edit.jl -- High-level editing functions
;;; Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
;;; This file is part of Jade.
;;; Jade is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 2, or (at your option)
;;; any later version.
;;; Jade is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;; You should have received a copy of the GNU General Public License
;;; along with Jade; see the file COPYING. If not, write to
;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
(defvar word-regexp "[a-zA-Z0-9]"
"Regular expression which defines a character in a word.")
(defvar word-not-regexp "[^a-zA-Z0-9]|$"
"Regular expression which defines anything that is not in a word.")
(defvar paragraph-regexp "^[\t ]*$"
"Regular expression which matches a paragraph-separating piece of text.")
(make-variable-buffer-local 'word-regexp)
(make-variable-buffer-local 'word-not-regexp)
(make-variable-buffer-local 'paragraph-regexp)
(defvar auto-mark (make-mark)
"Mark which some commands use to track the previous cursor position.")
;; Words
(defun forward-word (&optional number pos move)
"Return the position of first character after the end of this word.
NUMBER is the number of words to move, negative values mean go backwards.
If MOVE is t then the cursor is moved to the result."
(interactive "p\n\nt")
(unless number
(setq number 1))
(unless pos
(setq pos (cursor-pos)))
(cond
((< number 0)
;; go backwards
(while (/= number 0)
(setq pos (prev-char 1 pos))
(when (looking-at word-not-regexp pos)
;; not in word
(unless (setq pos (find-prev-regexp word-regexp pos))
(error "Start of buffer")))
;; in middle of word
(unless (setq pos (find-prev-regexp word-not-regexp pos))
(error "Start of buffer"))
(setq
pos (find-next-regexp word-regexp pos)
number (1+ number))))
(t
;; forwards
(while (/= number 0)
(when (looking-at word-not-regexp pos)
;; already at end of a word
(unless (setq pos (find-next-regexp word-regexp pos))
(error "End of buffer")))
(unless (setq pos (find-next-regexp word-not-regexp pos))
(error "End of buffer"))
(setq number (1- number)))))
(when move
(goto-char pos))
pos)
(defun backward-word (&optional number pos move)
"Basically `(forward-word -NUMBER POS MOVE)'"
(interactive "p\n\nt")
(forward-word (if number (- number) -1) pos move))
(defun kill-word (count)
"Kills from the cursor to the end of the word."
(interactive "p")
(kill-area (cursor-pos) (forward-word count)))
(defun backward-kill-word (count)
"Kills from the start of the word to the cursor."
(interactive "p")
(kill-area (forward-word (- count)) (cursor-pos)))
(defun word-start (&optional pos)
"Returns the position of the start of *this* word."
(when (looking-at word-regexp pos)
(unless (find-prev-regexp word-not-regexp pos)
(error "Start of buffer"))
(find-next-regexp word-regexp (match-end))))
(defun in-word-p (&optional pos)
"Returns t if POS is inside a word."
(when (looking-at word-regexp pos)
t))
(defun mark-word (count &optional pos)
"Marks COUNT words from POS."
(interactive "p")
(set-rect-blocks nil nil)
(mark-block (or pos (cursor-pos)) (forward-word count pos)))
(defun transpose-words (count)
"Move the word at (before) the cursor COUNT words forwards."
(interactive "p")
(transpose-items 'forward-word 'backward-word count))
;; Paragraphs
(defun forward-paragraph (&optional pos buf move)
"Returns the position of the start of the next paragraph. If MOVE
is t then the cursor is set to this position."
(interactive "\n\nt")
(setq pos (or (find-next-regexp paragraph-regexp
(next-char 1 (if pos
(copy-pos pos)
(cursor-pos)))
buf)
(buffer-end)))
(when move
(goto-char pos))
pos)
(defun backward-paragraph (&optional pos buf move)
"Returns the start of the previous paragraph. If MOVE is t the cursor is
set to this position."
(interactive "\n\nt")
(setq pos (or (find-prev-regexp paragraph-regexp
(prev-char 1 (if pos
(copy-pos pos)
(cursor-pos)))
buf)
(buffer-start)))
(when move
(goto-char pos))
pos)
(defun mark-paragraph ()
"Set the block-marks to the current paragraph."
(interactive)
(let
((par (forward-paragraph)))
(set-rect-blocks nil nil)
(mark-block (backward-paragraph par) par)))
;; Block handling
(defun copy-block (&aux rc)
"If a block is marked in the current window, return the text it contains and
unmark the block."
(when (blockp)
(setq rc (funcall (if (rect-blocks-p) 'copy-rect 'copy-area)
(block-start) (block-end)))
(block-kill))
rc)
(defun cut-block (&aux rc)
"Similar to `copy-block' except the block is cut (copied then deleted) from
the buffer."
(when (blockp)
(setq rc (funcall (if (rect-blocks-p) 'cut-rect 'cut-area)
(block-start) (block-end)))
(block-kill))
rc)
(defun delete-block ()
"Deletes the block marked in the current window (if one exists)."
(interactive)
(when (blockp)
(funcall (if (rect-blocks-p) 'delete-rect 'delete-area)
(block-start) (block-end))
(block-kill)))
(defun insert-block (&optional pos)
"If a block is marked in the current window, copy it to position POS, then
unmark the block."
(interactive)
(when (blockp)
(if (rect-blocks-p)
(insert-rect (copy-rect (block-start) (block-end)) pos)
(insert (copy-area (block-start) (block-end)) pos))
(block-kill)))
(defun toggle-rect-blocks ()
"Toggles the state of the flag saying whether blocks in this window are
marked sequentially (the default) or as rectangles."
(interactive)
(set-rect-blocks nil (not (rect-blocks-p))))
(defun kill-block ()
"Kills the block marked in this window."
(interactive)
(kill-string (cut-block)))
(defun copy-block-as-kill ()
"Kills the block marked in this window but doesn't actually delete it from
the buffer."
(interactive)
(kill-string (copy-block)))
(defun mark-block (start end)
"Mark a block from START to END. This does an extra redraw if there's already
a block marked to save lots of flicker."
(if (blockp)
(progn
(block-kill)
;; Cunning hack -- the refresh algorithm(?) doesn't like the block
;; killed then reset in one go, the whole screen is redraw :-( So
;; do two refreshes...
(refresh-all))
(block-kill))
(block-start start)
(block-end end))
(defun mark-whole-buffer ()
"Mark a block containing the whole of the buffer."
(interactive)
(set-rect-blocks nil nil)
(mark-block (buffer-start) (buffer-end)))
(defun upcase-area (start end &optional buffer)
"Makes all alpha characters in the specified region of text upper-case."
(interactive "-m\nM")
(translate-area start end upcase-table buffer))
(defun downcase-area (start end &optional buffer)
"Makes all alpha characters in the specified region of text lower-case."
(interactive "-m\nM")
(translate-area start end downcase-table buffer))
(defun upcase-word (count)
"Makes the next COUNT words from the cursor upper-case."
(interactive "p")
(let
((pos (forward-word count)))
(upcase-area (cursor-pos) pos)
(goto-char pos)))
(defun capitalize-word ()
"The first character of this word (the one under the cursor) is made
upper-case, the rest lower-case."
(interactive)
(unless (in-word-p)
(goto-char (find-next-regexp word-regexp)))
(translate-area (cursor-pos) (next-char) upcase-table)
(goto-next-char)
(when (in-word-p)
(downcase-word 1)))
(defun downcase-word (count)
"Makes the word under the cursor lower case."
(interactive "p")
(let
((pos (forward-word count)))
(downcase-area (cursor-pos) pos)
(goto-char pos)))
(defun mark-region ()
"Sets the block-marks to the area between the cursor position and the
au