3 (defvar *kill-ring
* nil
6 (defvar *kill-ring-max
* 60
7 "Maximum length of kill ring before oldest elements are thrown away.")
9 (defvar *kill-ring-yank-pointer
* nil
10 "The tail of the kill ring whose car is the last thing yanked.")
12 (defcustom *eval-expression-print-level
* 4
13 "Value for `print-level' while printing value in `eval-expression'.
14 A value of nil means no limit."
16 :type
'(choice (const :tag
"No Limit" nil
) integer
)
19 (defcustom *eval-expression-print-length
* 12
20 "Value for `print-length' while printing value in `eval-expression'.
21 A value of nil means no limit."
23 :type
'(choice (const :tag
"No Limit" nil
) integer
)
26 (defcustom *eval-expression-debug-on-error
* t
27 "If non-nil set `debug-on-error' to t in `eval-expression'.
28 If nil, don't change the value of `debug-on-error'."
33 (define-condition kill-ring-empty
(lice-condition)
34 () (:documentation
"Raised when a yank is attempted but the kill ring is empty"))
36 ;; (when (or (and (< n 0)
37 ;; (< (point (current-buffer)) 0))
38 ;; (> (point (current-buffer))
40 ;; (decf (marker-position (buffer-point (current-buffer))) n))
42 (defcommand forward-char
((&optional
(n 1))
44 "Move the point forward N characters in the current buffer."
45 (incf (marker-position (buffer-point (current-buffer))) n
)
46 (cond ((< (point) (begv))
48 (signal 'beginning-of-buffer
))
51 (signal 'end-of-buffer
))))
53 (defcommand backward-char
((&optional
(n 1))
57 (defun buffer-beginning-of-line ()
58 "Return the point in the buffer that is the beginning of the line that P is on."
59 (if (or (not (char-before))
60 (char= (char-before) #\Newline
))
62 (let ((bol (buffer-scan-newline (current-buffer) (point) 0 0)))
63 (if (and (char= (char-after bol
) #\Newline
)
64 (< bol
(1- (buffer-size (current-buffer)))))
68 (defun buffer-end-of-line ()
69 "Return the point in the buffer that is the end of the line that P is on."
70 (if (or (not (char-after))
71 (char= (char-after) #\Newline
))
73 (let ((eol (buffer-scan-newline (current-buffer) (point) (1- (buffer-size (current-buffer))) 1)))
74 ;; XXX: a bit of a kludge. if the eol char isn't a newline then it
75 ;; has to be the end of the buffer, so advance the point by one,
76 ;; which is the actual end of the line.
77 (if (char= (char-after eol
) #\Newline
)
81 (defun forward-line (n)
82 "Move n lines forward (backward if n is negative).
83 Precisely, if point is on line I, move to the start of line I + n.
84 If there isn't room, go as far as possible (no error).
85 Returns the count of lines left to move. If moving forward,
86 that is n - number of lines moved; if backward, n + number moved.
87 With positive n, a non-empty line at the end counts as one line
88 successfully moved (for the return value)."
91 (signal 'end-of-buffer
))
94 (signal 'beginning-of-buffer
)))
96 (multiple-value-bind (p lines
) (buffer-scan-newline (current-buffer)
97 (point (current-buffer))
98 (1- (buffer-size (current-buffer)))
100 ;; Increment p by one so the point is at the beginning of the
102 (when (or (char= (char-after p
) #\Newline
)
103 (= p
(1- (buffer-size (current-buffer)))))
107 (signal 'end-of-buffer
))
112 (multiple-value-bind (p lines
)
113 (buffer-scan-newline (current-buffer)
115 ;; A little mess to figure out how
116 ;; many newlines to search for to
117 ;; give the proper output.
120 (if (and (char-after (point))
121 (char= (char-after (point)) #\Newline
))
124 (when (char= (char-after p
) #\Newline
)
129 (signal 'beginning-of-buffer
))
132 (defcommand self-insert-command
((arg)
134 "Insert the character you type.
135 Whichever character you type to run this command is inserted."
136 (dformat +debug-v
+ "currentb: ~a ~a~%" (current-buffer) *current-buffer
*)
138 (insert-move-point (current-buffer) (make-string arg
:initial-element
(key-char *current-event
*)))
140 (insert-move-point (current-buffer) (key-char *current-event
*)))))
142 (defcommand newline
((&optional n
)
144 "Insert N new lines."
145 (insert-move-point (current-buffer) (make-string (or n
1) :initial-element
#\Newline
)))
147 (defcommand open-line
((n) :prefix
)
148 "Insert a newline and leave point before it.
149 **If there is a fill prefix and/or a left-margin, insert them on the new line
150 **if the line would have been blank.
151 With arg N, insert N newlines."
153 (dotimes (i n
) (newline 1))
156 (defcommand next-line
((&optional
(arg 1))
158 "Move cursor vertically down N lines."
159 (let ((col (current-column)))
161 (if (<= col
(- (buffer-end-of-line) (point)))
162 (goto-char (+ (point) col
))
163 (goto-char (buffer-end-of-line)))))
165 (defcommand previous-line
((&optional
(arg 1))
167 "Move cursor vertically up N lines."
168 (let ((col (current-column)))
169 ;; FIXME: this is all fucked
170 (forward-line (- arg
))
174 (if (<= col
(- (buffer-end-of-line) (point)))
175 (goto-char (+ (point) col
))
176 (goto-char (buffer-end-of-line)))))
178 (defcommand delete-backward-char
()
179 "Delete the previous N characters."
180 (buffer-delete (current-buffer) (point (current-buffer)) -
1))
182 (defcommand delete-char
()
183 "Delete the following N characters."
184 (buffer-delete (current-buffer) (point (current-buffer)) 1))
186 (defun line-move-invisible-p (pos)
187 "Return non-nil if the character after POS is currently invisible."
189 (get-char-property pos
'invisible
)))
190 (if (eq (buffer-local :buffer-invisibility-spec
) t
)
192 (or (find prop
(buffer-local :buffer-invisibility-spec
))
193 (assoc prop
(remove-if-not 'listp
(buffer-local :buffer-invisibility-spec
)))))))
195 (defcustom track-eol nil
196 "*Non-nil means vertical motion starting at end of line keeps to ends of lines.
197 This means moving to the end of each line moved onto.
198 The beginning of a blank line does not count as the end of a line."
200 :group
'editing-basics
)
202 (defcustom *line-move-ignore-invisible
* t
203 "*Non-nil means \\[next-line] and \\[previous-line] ignore invisible lines.
204 Outline mode sets this."
206 :group
'editing-basics
)
208 (defcustom-buffer-local :goal-column nil
209 "*Semipermanent goal column for vertical motion, as set by \\[set-goal-column], or nil."
210 :type
'(choice integer
211 (const :tag
"None" nil
))
212 :group
'editing-basics
)
214 (defvar *temporary-goal-column
* 0
215 "Current goal column for vertical motion.
216 It is the column where point was
217 at the start of current run of vertical motion commands.
218 When the `track-eol' feature is doing its job, the value is 9999.")
220 (defun line-move (arg &optional noerror to-end try-vscroll
)
221 "This is like line-move-1 except that it also performs
222 vertical scrolling of tall images if appropriate.
223 That is not really a clean thing to do, since it mixes
224 scrolling with cursor motion. But so far we don't have
225 a cleaner solution to the problem of making C-n do something
226 useful given a tall image."
227 ;; XXX: Fuckit the vertical scrolling for now
228 ;; (if (and auto-window-vscroll try-vscroll
229 ;; ;; But don't vscroll in a keyboard macro.
230 ;; ;; FIXME: kbd macros
231 ;; ;; (not defining-kbd-macro)
232 ;; ;; (not executing-kbd-macro)
234 ;; (let ((forward (> arg 0))
235 ;; (part (nth 2 (pos-visible-in-window-p (point) nil t))))
236 ;; (if (and (consp part)
237 ;; (> (if forward (cdr part) (car part)) 0))
238 ;; (set-window-vscroll nil
240 ;; (+ (window-vscroll nil t)
242 ;; (* (frame-char-height) arg)))
244 ;; (- (window-vscroll nil t)
246 ;; (* (frame-char-height) (- arg))))))
248 ;; (set-window-vscroll nil 0)
249 ;; (when (line-move-1 arg noerror to-end)
250 ;; (when (not forward)
251 ;; ;; Update display before calling pos-visible-in-window-p,
252 ;; ;; because it depends on window-start being up-to-date.
254 ;; ;; If the current line is partly hidden at the bottom,
255 ;; ;; scroll it partially up so as to unhide the bottom.
256 ;; (if (and (setq part (nth 2 (pos-visible-in-window-p
257 ;; (line-beginning-position) nil t)))
259 ;; (set-window-vscroll nil (cdr part) t)))
261 (line-move-1 arg noerror to-end
))
264 (defun line-move-1 (arg &optional noerror to-end
)
265 "This is the guts of next-line and previous-line.
266 Arg says how many lines to move.
267 The value is t if we can move the specified number of lines."
268 ;; Don't run any point-motion hooks, and disregard intangibility,
269 ;; for intermediate positions.
270 (let ((*inhibit-point-motion-hooks
* t
)
275 (if (not (find *last-command
* '(next-line previous-line
)))
276 (setq *temporary-goal-column
*
277 (if (and track-eol
(eolp)
278 ;; Don't count beg of empty line as end of line
279 ;; unless we just did explicit end-of-line.
280 (or (not (bolp)) (eq *last-command
* 'move-end-of-line
)))
284 (if (and (not (integerp (buffer-local :selective-display
)))
285 (not *line-move-ignore-invisible
*))
286 ;; Use just newline characters.
287 ;; Set ARG to 0 if we move as many lines as requested.
289 (progn (if (> arg
1) (forward-line (1- arg
)))
290 ;; This way of moving forward ARG lines
291 ;; verifies that we have a newline after the last one.
292 ;; It doesn't get confused by intangible text.
294 (if (zerop (forward-line 1))
296 (and (zerop (forward-line arg
))
300 (signal (if (< arg
0)
304 ;; Move by arg lines, but ignore invisible ones.
306 (while (and (> arg
0) (not done
))
307 ;; If the following character is currently invisible,
308 ;; skip all characters with that same `invisible' property value.
309 (while (and (not (eobp)) (line-move-invisible-p (point)))
310 (goto-char (next-char-property-change (point))))
313 ;; If there's no invisibility here, move over the newline.
317 (signal 'end-of-buffer
)
319 ((and (> arg
1) ;; Use vertical-motion for last move
320 (not (integerp (buffer-local :selective-display
)))
321 (not (line-move-invisible-p (point))))
322 ;; We avoid vertical-motion when possible
323 ;; because that has to fontify.
325 ;; Otherwise move a more sophisticated way.
326 ((zerop (vertical-motion 1))
328 (signal 'end-of-buffer
)
331 (setq arg
(1- arg
))))
332 ;; The logic of this is the same as the loop above,
333 ;; it just goes in the other direction.
334 (while (and (< arg
0) (not done
))
339 (signal 'beginning-of-buffer nil
)
341 ((and (< arg -
1) ;; Use vertical-motion for last move
342 (not (integerp (buffer-local :selective-display
)))
343 (not (line-move-invisible-p (1- (point)))))
345 ((zerop (vertical-motion -
1))
347 (signal 'beginning-of-buffer nil
)
351 (while (and ;; Don't move over previous invis lines
352 ;; if our target is the middle of this line.
353 (or (zerop (or (buffer-local :goal-column
) *temporary-goal-column
*))
355 (not (bobp)) (line-move-invisible-p (1- (point))))
356 (goto-char (previous-char-property-change (point))))))))
357 ;; This is the value the function returns.
361 ;; If we did not move down as far as desired,
362 ;; at least go to end of line.
365 ;; If we did not move up as far as desired,
366 ;; at least go to beginning of line.
369 (line-move-finish (or (buffer-local :goal-column
) *temporary-goal-column
*)
372 (defun line-move-finish (column opoint forward
)
375 ;; Set REPEAT to t to repeat the whole thing.
379 (line-beg (save-excursion (beginning-of-line) (point)))
381 ;; Compute the end of the line
382 ;; ignoring effectively invisible newlines.
384 ;; Like end-of-line but ignores fields.
385 (skip-chars-forward "^\n")
386 (while (and (not (eobp)) (line-move-invisible-p (point)))
387 (goto-char (next-char-property-change (point)))
388 (skip-chars-forward "^\n"))
391 ;; Move to the desired column.
392 (line-move-to-column column
)
395 ;; Process intangibility within a line.
396 ;; With inhibit-point-motion-hooks bound to nil, a call to
397 ;; goto-char moves point past intangible text.
399 ;; However, inhibit-point-motion-hooks controls both the
400 ;; intangibility and the point-entered/point-left hooks. The
401 ;; following hack avoids calling the point-* hooks
402 ;; unnecessarily. Note that we move *forward* past intangible
403 ;; text when the initial and final points are the same.
405 (let ((inhibit-point-motion-hooks nil
))
408 ;; If intangibility moves us to a different (later) place
409 ;; in the same line, use that as the destination.
410 (if (<= (point) line-end
)
412 ;; If that position is "too late",
413 ;; try the previous allowable position.
418 ;; If going forward, don't accept the previous
419 ;; allowable position if it is before the target line.
421 ;; If going backward, don't accept the previous
422 ;; allowable position if it is still after the target line.
423 (<= (point) line-end
))
425 ;; As a last resort, use the end of the line.
426 (setq new line-end
)))))
428 ;; Now move to the updated destination, processing fields
429 ;; as well as intangibility.
431 (let ((inhibit-point-motion-hooks nil
))
433 (constrain-to-field new opoint nil t
434 'inhibit-line-move-field-capture
)))
436 ;; If all this moved us to a different line,
437 ;; retry everything within that new line.
438 (when (or (< (point) line-beg
) (> (point) line-end
))
439 ;; Repeat the intangibility and field processing.
442 (defun line-move-to-column (col)
443 "Try to find column COL, considering invisibility.
444 This function works only in certain cases,
445 because what we really need is for `move-to-column'
446 and `current-column' to be able to ignore invisible text."
449 (let ((opoint (point)))
451 ;; move-to-column doesn't respect field boundaries.
452 (goto-char (constrain-to-field (point) opoint
))))
454 (when (and *line-move-ignore-invisible
*
455 (not (bolp)) (line-move-invisible-p (1- (point))))
456 (let ((normal-location (point))
457 (normal-column (current-column)))
458 ;; If the following character is currently invisible,
459 ;; skip all characters with that same `invisible' property value.
460 (while (and (not (eobp))
461 (line-move-invisible-p (point)))
462 (goto-char (next-char-property-change (point))))
463 ;; Have we advanced to a larger column position?
464 (if (> (current-column) normal-column
)
465 ;; We have made some progress towards the desired column.
466 ;; See if we can make any further progress.
467 (line-move-to-column (+ (current-column) (- col normal-column
)))
468 ;; Otherwise, go to the place we originally found
469 ;; and move back over invisible text.
470 ;; that will get us to the same place on the screen
471 ;; but with a more reasonable buffer position.
473 (goto-char normal-location
)
474 (let ((line-beg (save-excursion (beginning-of-line) (point))))
475 (while (and (not (bolp)) (line-move-invisible-p (1- (point))))
476 (goto-char (previous-char-property-change (point) line-beg
)))))))))
478 (defcommand beginning-of-line
((&optional
(n 1))
480 "Move the point to the beginning of the line in the current buffer."
481 (check-type n number
)
482 (set-point (line-beginning-position n
)))
484 (defcommand move-beginning-of-line
((arg)
486 "Move point to beginning of current line as displayed.
487 \(If there's an image in the line, this disregards newlines
488 which are part of the text that the image rests on.)
490 With argument ARG not nil or 1, move forward ARG - 1 lines first.
491 If point reaches the beginning or end of buffer, it stops there.
492 To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
493 (or arg
(setq arg
1))
496 start first-vis first-vis-field-value
)
498 ;; Move by lines, if ARG is not 1 (the default).
500 (line-move (1- arg
) t
))
502 ;; Move to beginning-of-line, ignoring fields and invisibles.
503 (skip-chars-backward "\\n\\n") ;; FIXME: was "^\n"
504 (while (and (not (bobp)) (line-move-invisible-p (1- (point))))
505 (goto-char (previous-char-property-change (point)))
506 (skip-chars-backward "\\n\\n")) ;; FIXME: was "^\n"
509 ;; Now find first visible char in the line
510 (while (and (not (eobp)) (line-move-invisible-p (point)))
511 (goto-char (next-char-property-change (point))))
512 (setq first-vis
(point))
514 ;; See if fields would stop us from reaching FIRST-VIS.
515 (setq first-vis-field-value
516 (constrain-to-field first-vis orig
(/= arg
1) t nil
))
518 (goto-char (if (/= first-vis-field-value first-vis
)
519 ;; If yes, obey them.
520 first-vis-field-value
521 ;; Otherwise, move to START with attention to fields.
522 ;; (It is possible that fields never matter in this case.)
523 (constrain-to-field (point) orig
524 (/= arg
1) t nil
)))))
527 (defcommand end-of-line
((&optional n
)
529 "Move the point to the end of the line in the current buffer."
530 ;; FIXME: handle prefix
532 (setf (marker-position (buffer-point (current-buffer))) (buffer-end-of-line)))
534 (defcommand erase-buffer
((&optional buffer
))
535 "Erase the contents of the current buffer."
536 (buffer-erase (or buffer
(current-buffer))))
538 (defcommand execute-extended-command
((prefix)
540 "Read a user command from the minibuffer."
541 (let ((cmd (read-command (case (prefix-numeric-value prefix
)
544 (t (format nil
"~a M-x " prefix
))))))
545 (if (lookup-command cmd
)
547 (dispatch-command cmd
))
548 (message "No Match"))))
550 (defcommand switch-to-buffer
((buffer &optional norecord
)
551 (:buffer
"Switch To Buffer: " (buffer-name (other-buffer (current-buffer)))))
552 "Select buffer buffer in the current window.
553 If buffer does not identify an existing buffer,
554 then this function creates a buffer with that name.
556 When called from Lisp, buffer may be a buffer, a string (a buffer name),
557 or nil. If buffer is nil, then this function chooses a buffer
558 using `other-buffer'.
559 Optional second arg norecord non-nil means
560 do not put this buffer at the front of the list of recently selected ones.
561 This function returns the buffer it switched to.
563 WARNING: This is NOT the way to work on another buffer temporarily
564 within a Lisp program! Use `set-buffer' instead. That avoids messing with
565 the window-buffer correspondences."
567 (setf buffer
(other-buffer (current-buffer))))
568 (let ((w (frame-current-window (selected-frame))))
569 (when (typep w
'minibuffer-window
)
570 (error "its a minibuffer"))
571 (setf buffer
(get-buffer-create buffer
))
574 (record-buffer buffer
))
575 (set-window-buffer w buffer
)))
577 (defcommand save-buffers-kill-emacs
()
578 ;; TODO: save-some-buffers
579 (throw 'lice-quit t
))
581 (defcommand kill-buffer
((buffer)
582 (:buffer
"Kill buffer: " (buffer-name (current-buffer)) t
))
583 "Kill the buffer BUFFER.
584 The argument may be a buffer or may be the name of a buffer.
585 defaults to the current buffer.
587 Value is t if the buffer is actually killed, nil if user says no.
589 The value of `kill-buffer-hook' (which may be local to that buffer),
590 if not void, is a list of functions to be called, with no arguments,
591 before the buffer is actually killed. The buffer to be killed is current
592 when the hook functions are called.
594 Any processes that have this buffer as the `process-buffer' are killed
596 (let* ((target (get-buffer buffer
))
597 (other (other-buffer target
)))
600 ;; all windows carrying the buffer need a new buffer
601 (loop for w in
(frame-window-list (selected-frame))
602 do
(when (eq (window-buffer w
) target
)
603 (set-window-buffer w other
)))
604 (setf *buffer-list
* (delete target
*buffer-list
*)))
605 (error "No such buffer ~a" buffer
))))
607 (defun eval-echo (string)
608 ;; FIXME: don't just abandon the output
609 (let* ((stream (make-string-output-stream))
610 (*standard-output
* stream
)
611 (*error-output
* stream
)
613 (multiple-value-bind (sexpr pos
) (read-from-string string
)
614 (if (= pos
(length string
))
615 (message "~s" (eval sexpr
))
616 (error "Trailing garbage is ~a" string
)))))
618 (defun eval-print (string)
619 (multiple-value-bind (sexpr pos
) (read-from-string string
)
620 (if (= pos
(length string
))
621 (insert (format nil
"~%~s~%" (eval sexpr
)))
622 (error "Trailing garbage is ~a" string
))))
624 (defcommand eval-expression
((s)
628 ;;(error (c) (message "Eval error: ~s" c))))
630 (defcommand exchange-point-and-mark
()
632 (goto-char (marker-position (mark-marker)))
633 (set-marker (mark-marker) p
)))
635 (defcommand set-mark-command
()
636 (set-marker (mark-marker) (point))
637 (message "Mark set"))
639 (defun push-mark (&optional location nomsg activate
)
640 "Set mark at LOCATION (point, by default) and push old mark on mark ring.
641 If the last global mark pushed was not in the current buffer,
642 also push LOCATION on the global mark ring.
643 Display `Mark set' unless the optional second arg NOMSG is non-nil.
644 In Transient Mark mode, activate mark if optional third arg ACTIVATE non-nil.
646 Novice Emacs Lisp programmers often try to use the mark for the wrong
647 purposes. See the documentation of `set-mark' for more information.
649 In Transient Mark mode, this does not activate the mark."
651 (set-marker (mark-marker) (point))
653 (message "Mark set")))
655 ;; (defun kill-ring-save (beg end)
656 ;; "Save the region to the kill ring."
658 (defcommand scroll-up
()
659 (let ((win (get-current-window)))
660 (window-scroll-up win
(max 1 (- (window-height win
)
661 *next-screen-context-lines
*)))))
663 (defcommand scroll-down
()
664 (let ((win (get-current-window)))
665 (window-scroll-down win
(max 1 (- (window-height win
)
666 *next-screen-context-lines
*)))))
668 (defcommand end-of-buffer
()
669 "Move point to the end of the buffer; leave mark at previous position.
670 With arg N, put point N/10 of the way from the end.
672 If the buffer is narrowed, this command uses the beginning and size
673 of the accessible part of the buffer."
675 (goto-char (point-max)))
677 (defcommand just-one-space
((&optional
(n 1))
679 "Delete all spaces and tabs around point, leaving one space (or N spaces)."
680 (let ((orig-pos (point)))
681 (skip-chars-backward (coerce '(#\Space
#\Tab
) 'string
))
682 (constrain-to-field nil orig-pos
)
684 (if (char= (following-char) #\Space
)
690 (skip-whitespace-forward)
691 (constrain-to-field nil orig-pos t
)))))
693 (defcommand beginning-of-buffer
()
694 "Move point to the beginning of the buffer; leave mark at previous position.
695 With arg N, put point N/10 of the way from the beginning.
697 If the buffer is narrowed, this command uses the beginning and size
698 of the accessible part of the buffer."
700 (goto-char (point-min)))
702 (defcommand split-window-vertically
()
703 (split-window (get-current-window)))
705 (defcommand split-window-horizontally
()
706 (split-window (get-current-window) nil t
))
708 (defcommand other-window
()
709 (let ((w (next-window (get-current-window) t
)))
712 (message "No other window."))))
714 (defcommand switch-to-buffer-other-window
((buffer)
715 (:buffer
"Switch to buffer in other window: " (buffer-name (other-buffer (current-buffer)))))
716 (let* ((cw (get-current-window))
717 (w (or (next-window cw
)
720 (switch-to-buffer buffer
)))
722 (defcommand keyboard-quit
()
727 (defun kill-new (string &optional replace
)
728 "Make STRING the latest kill in the kill ring.
729 Set the kill-ring-yank pointer to point to it.
730 Optional second argument REPLACE non-nil means that STRING will replace
731 the front of the kill ring, rather than being added to the list."
734 (setf (car *kill-ring
*) string
)
735 (push string
*kill-ring
*))
736 (when (> (length *kill-ring
*) *kill-ring-max
*)
737 (setf (cdr (nthcdr (1- *kill-ring-max
*) *kill-ring
*)) nil
))
738 (setf *kill-ring-yank-pointer
* *kill-ring
*))
740 (defun copy-region-as-kill (start end
&optional
(buffer (current-buffer)))
741 (multiple-value-setq (start end
) (validate-region start end buffer
))
742 (kill-new (buffer-substring start end buffer
)))
744 (defcommand kill-ring-save
()
745 (copy-region-as-kill (mark) (point)))
747 (defcommand kill-region
((beg end
)
750 "Kill between point and mark.
751 The text is deleted but saved in the kill ring.
752 The command C-y can retrieve it from there.
753 (If you want to kill and then yank immediately, use M-w.)"
754 (copy-region-as-kill beg end
)
755 (delete-region beg end
))
758 (defcommand kill-line
()
762 (signal 'end-of-buffer
))
763 (if (char= (buffer-char-after (current-buffer) (point)) #\Newline
)
765 (goto-char (buffer-end-of-line)))
768 (defun current-kill (n &optional do-not-move
)
769 "Rotate the yanking point by N places, and then return that kill.
770 If optional arg DO-NOT-MOVE is non-nil, then don't actually move the
771 yanking point; just return the Nth kill forward."
773 (signal 'kill-ring-empty
))
774 (let ((argth-kill-element
775 (nthcdr (mod (- n
(length *kill-ring-yank-pointer
*))
776 (length *kill-ring
*))
779 (setf *kill-ring-yank-pointer
* argth-kill-element
))
780 (car argth-kill-element
)))
784 (insert (current-kill 0)))
786 (defcommand yank-pop
()
787 (unless (eq *last-command
* 'yank
)
788 (error "Previous command was not a yank: ~a" *last-command
*))
789 (setf *this-command
* 'yank
)
790 (delete-region (mark) (point))
791 (insert (current-kill 1)))
793 ;;; universal argument
795 (defun prefix-numeric-value (prefix)
796 "Return numeric meaning of raw prefix argument RAW.
797 A raw prefix argument is what you get from :raw-prefix.
798 Its numeric meaning is what you would get from :prefix."
805 (integerp (car prefix
)))
812 "Return numeric meaning of *prefix-arg*"
813 (prefix-numeric-value *prefix-arg
*))
815 (defun raw-prefix-arg ()
816 "Return the current prefix arg in raw form."
819 (defvar *overriding-map-is-bound
* nil
)
820 (defvar *saved-overriding-map
* nil
)
821 (defvar *universal-argument-num-events
* nil
)
823 (defvar *universal-argument-map
*
824 (let ((map (make-sparse-keymap)))
825 ;;(define-key map (kbd "t") 'universal-argument-other-key)
826 (define-key map t
'universal-argument-other-key
)
827 ;;(define-key map [switch-frame] nil)
828 (define-key map
(kbd "C-u") 'universal-argument-more
)
829 (define-key map
(kbd "-") 'universal-argument-minus
)
830 (define-key map
(kbd "0") 'digit-argument
)
831 (define-key map
(kbd "1") 'digit-argument
)
832 (define-key map
(kbd "2") 'digit-argument
)
833 (define-key map
(kbd "3") 'digit-argument
)
834 (define-key map
(kbd "4") 'digit-argument
)
835 (define-key map
(kbd "5") 'digit-argument
)
836 (define-key map
(kbd "6") 'digit-argument
)
837 (define-key map
(kbd "7") 'digit-argument
)
838 (define-key map
(kbd "8") 'digit-argument
)
839 (define-key map
(kbd "9") 'digit-argument
)
840 ;; (define-key map [kp-0] 'digit-argument)
841 ;; (define-key map [kp-1] 'digit-argument)
842 ;; (define-key map [kp-2] 'digit-argument)
843 ;; (define-key map [kp-3] 'digit-argument)
844 ;; (define-key map [kp-4] 'digit-argument)
845 ;; (define-key map [kp-5] 'digit-argument)
846 ;; (define-key map [kp-6] 'digit-argument)
847 ;; (define-key map [kp-7] 'digit-argument)
848 ;; (define-key map [kp-8] 'digit-argument)
849 ;; (define-key map [kp-9] 'digit-argument)
850 ;; (define-key map [kp-subtract] 'universal-argument-minus)
852 "Keymap used while processing \\[universal-argument].")
854 (defun ensure-overriding-map-is-bound ()
855 "Check `*overriding-terminal-local-map*' is `*universal-argument-map*'."
856 (unless *overriding-map-is-bound
*
857 (setf *saved-overriding-map
* *overriding-terminal-local-map
*
858 *overriding-terminal-local-map
* *universal-argument-map
*
859 *overriding-map-is-bound
* t
)))
861 (defun restore-overriding-map ()
862 "Restore `*overriding-terminal-local-map*' to its saved value."
863 (setf *overriding-terminal-local-map
* *saved-overriding-map
*
864 *overriding-map-is-bound
* nil
))
866 (defcommand universal-argument
()
867 (setf *prefix-arg
* (list 4)
868 *universal-argument-num-events
* (length (this-command-keys)))
869 (ensure-overriding-map-is-bound))
871 (defcommand universal-argument-more
((arg)
874 (setf *prefix-arg
* (list (* 4 (car arg
))))
876 (setf *prefix-arg
* (list -
4))
878 (setf *prefix-arg
* arg
)
879 (restore-overriding-map))))
880 (setf *universal-argument-num-events
* (length (this-command-keys))))
882 (defcommand negative-argument
((arg)
884 "Begin a negative numeric argument for the next command.
885 \\[universal-argument] following digits or minus sign ends the argument."
886 (cond ((integerp arg
)
887 (setf *prefix-arg
* (- arg
)))
889 (setf *prefix-arg
* nil
))
891 (setf *prefix-arg
* '-
)))
892 (setf *universal-argument-num-events
* (length (this-command-keys)))
893 (ensure-overriding-map-is-bound))
895 (defcommand digit-argument
((arg)
897 "Part of the numeric argument for the next command.
898 \\[universal-argument] following digits or minus sign ends the argument."
899 (let* ((char (last-command-char))
900 (digit (- (logand (char-code char
) #o177
) (char-code #\
0))))
901 (cond ((integerp arg
)
902 (setf *prefix-arg
* (+ (* arg
10)
903 (if (< arg
0) (- digit
) digit
))))
905 ;; Treat -0 as just -, so that -01 will work.
906 (setf *prefix-arg
* (if (zerop digit
) '-
(- digit
))))
908 (setf *prefix-arg
* digit
))))
909 (setf *universal-argument-num-events
* (length (this-command-keys)))
910 (ensure-overriding-map-is-bound))
912 ;; For backward compatibility, minus with no modifiers is an ordinary
913 ;; command if digits have already been entered.
914 (defcommand universal-argument-minus
((arg)
917 (universal-argument-other-key arg
)
918 (negative-argument arg
)))
920 ;; Anything else terminates the argument and is left in the queue to be
921 ;; executed as a command.
922 (defcommand universal-argument-other-key
((arg)
924 (setf *prefix-arg
* arg
)
925 (let* ((keylist (this-command-keys)))
926 (setf *unread-command-events
* keylist
))
927 ;; (append (nthcdr *universal-argument-num-events* keylist)
928 ;; *unread-command-events*)))
929 ;;FIXME: (reset-this-command-lengths)
930 (restore-overriding-map))
933 ;; (defcommand append-to-buffer ((buffer :buffer "Append to buffer: " (buffer-name (other-buffer (current-buffer))))
934 ;; (start :region-beginning)
935 ;; (end :region-end))
936 ;; "Append to specified buffer the text of the region.
937 ;; It is inserted into that buffer before its point.
939 ;; When calling from a program, give three arguments:
940 ;; buffer (or buffer name), start and end.
941 ;; start and end specify the portion of the current buffer to be copied."
942 ;; (let ((oldbuf (current-buffer)))
944 ;; (let* ((append-to (get-buffer-create buffer))
945 ;; (windows (get-buffer-window-list append-to t t))
947 ;; (set-buffer append-to)
948 ;; (setf point (point))
949 ;; (barf-if-buffer-read-only)
950 ;; (insert-buffer-substring oldbuf start end)
951 ;; (dolist (window windows)
952 ;; (when (= (window-point window) point)
953 ;; (set-window-point window (point))))))))
955 (defcommand transpose-chars
((arg)
957 "Interchange characters around point, moving forward one character.
958 With prefix arg ARG, effect is to take character before point
959 and drag it forward past ARG other characters (backward if ARG negative).
960 If no argument and at end of line, the previous two chars are exchanged."
961 (and (null arg
) (eolp) (forward-char -
1))
962 (transpose-subr 'forward-char
(prefix-numeric-value arg
)))
964 (defcommand transpose-words
((arg)
966 "Interchange words around point, leaving point at end of them.
967 With prefix arg ARG, effect is to take word before or around point
968 and drag it forward past ARG other words (backward if ARG negative).
969 If ARG is zero, the words around or after point and around or after mark
971 ;; FIXME: `foo a!nd bar' should transpose into `bar and foo'.
972 (transpose-subr 'forward-word arg
))
974 ;; (defun transpose-sexps ((arg)
976 ;; "Like \\[transpose-words] but applies to sexps.
977 ;; Does not work on a sexp that point is in the middle of
978 ;; if it is a list or string."
981 ;; ;; Here we should try to simulate the behavior of
982 ;; ;; (cons (progn (forward-sexp x) (point))
983 ;; ;; (progn (forward-sexp (- x)) (point)))
984 ;; ;; Except that we don't want to rely on the second forward-sexp
985 ;; ;; putting us back to where we want to be, since forward-sexp-function
986 ;; ;; might do funny things like infix-precedence.
988 ;; ;;(looking-at "\\sw\\|\\s_")
989 ;; ;; FIXME: we don't have looking-at or syntax classes. Fake it for now
990 ;; (or (alpha-char-p (char-after (point)))
991 ;; (find (char-after (point)) "*/+-%$!@&"))
993 ;; (save-excursion (forward-char -1)
994 ;; ;; (looking-at "\\sw\\|\\s_")
995 ;; ;; FIXME: we don't have looking-at or syntax classes. Fake it for now
996 ;; (or (alpha-char-p (char-after (point)))
997 ;; (find (char-after (point)) "*/+-%$!@&"))
999 ;; ;; Jumping over a symbol. We might be inside it, mind you.
1000 ;; (progn (funcall (if (> arg 0)
1001 ;; 'skip-syntax-backward 'skip-syntax-forward)
1003 ;; (cons (save-excursion (forward-sexp arg) (point)) (point)))
1004 ;; ;; Otherwise, we're between sexps. Take a step back before jumping
1005 ;; ;; to make sure we'll obey the same precedence no matter which direction
1007 ;; (funcall (if (> arg 0) 'skip-syntax-backward 'skip-syntax-forward) " .")
1008 ;; (cons (save-excursion (forward-sexp arg) (point))
1009 ;; (progn (while (or (forward-comment (if (> arg 0) 1 -1))
1010 ;; (not (zerop (funcall (if (> arg 0)
1011 ;; 'skip-syntax-forward
1012 ;; 'skip-syntax-backward)
1017 (defcommand transpose-lines
((arg)
1019 "Exchange current line and previous line, leaving point after both.
1020 With argument ARG, takes previous line and moves it past ARG lines.
1021 With argument 0, interchanges line point is in with line mark is in."
1022 (transpose-subr (function
1026 ;; Move forward over ARG lines,
1027 ;; but create newlines if necessary.
1028 (setq arg
(forward-line arg
))
1029 (if (char/= (preceding-char) #\Newline
)
1030 (setq arg
(1+ arg
)))
1033 (forward-line arg
))))
1036 (defun transpose-subr (mover arg
&optional special
)
1037 (let ((aux (if special mover
1039 (cons (progn (funcall mover x
) (point))
1040 (progn (funcall mover
(- x
)) (point))))))
1045 (setq pos1
(funcall aux
1))
1047 (setq pos2
(funcall aux
1))
1048 (transpose-subr-1 pos1 pos2
))
1049 (exchange-point-and-mark))
1051 (setq pos1
(funcall aux -
1))
1052 (setq pos2
(funcall aux arg
))
1053 (transpose-subr-1 pos1 pos2
)
1054 (goto-char (car pos2
)))
1056 (setq pos1
(funcall aux -
1))
1057 (goto-char (car pos1
))
1058 (setq pos2
(funcall aux arg
))
1059 (transpose-subr-1 pos1 pos2
)))))
1061 (defun transpose-subr-1 (pos1 pos2
)
1062 (when (> (car pos1
) (cdr pos1
)) (setq pos1
(cons (cdr pos1
) (car pos1
))))
1063 (when (> (car pos2
) (cdr pos2
)) (setq pos2
(cons (cdr pos2
) (car pos2
))))
1064 (when (> (car pos1
) (car pos2
))
1066 (setq pos1 pos2 pos2 swap
)))
1067 (if (> (cdr pos1
) (car pos2
)) (error "Don't have two things to transpose"))
1068 ;; (atomic-change-group
1070 ;; FIXME: We first delete the two pieces of text, so markers that
1071 ;; used to point to after the text end up pointing to before it :-(
1072 (setq word2
(delete-and-extract-region (car pos2
) (cdr pos2
)))
1073 (goto-char (car pos2
))
1074 (insert (delete-and-extract-region (car pos1
) (cdr pos1
)))
1075 (goto-char (car pos1
))
1080 (defcustom-buffer-local :fill-prefix nil
1081 "*String for filling to insert at front of new line, or nil for none."
1082 :type
'(choice (const :tag
"None" nil
)
1088 (provide :lice-0.1
/simple
)