883f5587e8ebb815a18b198a0c4d1e631b92b458
[lice.git] / simple.lisp
blob883f5587e8ebb815a18b198a0c4d1e631b92b458
1 (in-package :lice)
3 (defvar *kill-ring* nil
4 "The kill ring.")
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."
15 :group 'lisp
16 :type '(choice (const :tag "No Limit" nil) integer)
17 :version "21.1")
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."
22 :group 'lisp
23 :type '(choice (const :tag "No Limit" nil) integer)
24 :version "21.1")
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'."
29 :group 'lisp
30 :type 'boolean
31 :version "21.1")
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))
39 ;; (point-max)))
40 ;; (decf (marker-position (buffer-point (current-buffer))) n))
42 (defcommand forward-char ((&optional (n 1))
43 :prefix)
44 "Move the point forward N characters in the current buffer."
45 (incf (marker-position (buffer-point (current-buffer))) n)
46 (cond ((< (point) (begv))
47 (goto-char (begv))
48 (signal 'beginning-of-buffer))
49 ((> (point) (zv))
50 (goto-char (zv))
51 (signal 'end-of-buffer))))
53 (defcommand backward-char ((&optional (n 1))
54 :prefix)
55 (forward-char (- n)))
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))
61 (point)
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)))))
65 (1+ bol)
66 bol))))
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))
72 (point)
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)
78 eol
79 (1+ eol)))))
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)."
89 (cond ((and (> n 0)
90 (= (point) (zv)))
91 (signal 'end-of-buffer))
92 ((and (< n 0)
93 (= (point) (begv)))
94 (signal 'beginning-of-buffer)))
95 (if (> n 0)
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
101 ;; line.
102 (when (or (char= (char-after p) #\Newline)
103 (= p (1- (buffer-size (current-buffer)))))
104 (incf p))
105 (goto-char p)
106 (when (zerop lines)
107 (signal 'end-of-buffer))
108 (- n lines))
109 (if (and (= n 0)
110 (not (char-before)))
112 ;; A little mess to figure out how many newlines to search
113 ;; for to give the proper output.
114 (let ((lines (if (and (char-after (point))
115 (char= (char-after (point)) #\Newline))
116 (- n 2)
117 (1- n))))
118 (multiple-value-bind (p flines)
119 (buffer-scan-newline (current-buffer)
120 (point) (begv)
121 lines)
122 (when (and (char= (char-after p) #\Newline)
123 (= flines (- lines)))
124 (incf p))
125 (goto-char p)
126 (when (and (< n 0)
127 (zerop flines))
128 (signal 'beginning-of-buffer))
129 (+ n flines))))))
131 (defcommand self-insert-command ((arg)
132 :prefix)
133 "Insert the character you type.
134 Whichever character you type to run this command is inserted."
135 (dformat +debug-v+ "currentb: ~a ~a~%" (current-buffer) *current-buffer*)
136 (if (>= arg 2)
137 (insert-move-point (current-buffer) (make-string arg :initial-element (key-char *current-event*)))
138 (when (> arg 0)
139 (insert-move-point (current-buffer) (key-char *current-event*)))))
141 (defcommand newline ((&optional n)
142 :prefix)
143 "Insert N new lines."
144 (insert-move-point (current-buffer) (make-string (or n 1) :initial-element #\Newline)))
146 (defcommand open-line ((n) :prefix)
147 "Insert a newline and leave point before it.
148 **If there is a fill prefix and/or a left-margin, insert them on the new line
149 **if the line would have been blank.
150 With arg N, insert N newlines."
151 (let ((loc (point)))
152 (dotimes (i n) (newline 1))
153 (goto-char loc)))
155 (defcommand next-line ((&optional (arg 1))
156 :prefix)
157 "Move cursor vertically down N lines."
158 (let ((col (current-column)))
159 (forward-line arg)
160 (if (<= col (- (buffer-end-of-line) (point)))
161 (goto-char (+ (point) col))
162 (goto-char (buffer-end-of-line)))))
164 (defcommand previous-line ((&optional (arg 1))
165 :prefix)
166 "Move cursor vertically up N lines."
167 (let ((col (current-column)))
168 ;; FIXME: this is all fucked
169 (forward-line (- arg))
170 ;;(forward-line 0)
171 ;;(backward-char 1)
172 ;;(forward-line 0)
173 (if (<= col (- (buffer-end-of-line) (point)))
174 (goto-char (+ (point) col))
175 (goto-char (buffer-end-of-line)))))
177 (defcommand delete-backward-char ()
178 "Delete the previous N characters."
179 (buffer-delete (current-buffer) (point (current-buffer)) -1))
181 (defcommand delete-char ()
182 "Delete the following N characters."
183 (buffer-delete (current-buffer) (point (current-buffer)) 1))
185 (defun line-move-invisible-p (pos)
186 "Return non-nil if the character after POS is currently invisible."
187 (let ((prop
188 (get-char-property pos 'invisible)))
189 (if (eq *buffer-invisibility-spec* t)
190 prop
191 (or (find prop *buffer-invisibility-spec*)
192 (assoc prop (remove-if 'listp *buffer-invisibility-spec*))))))
194 (defcustom track-eol nil
195 "*Non-nil means vertical motion starting at end of line keeps to ends of lines.
196 This means moving to the end of each line moved onto.
197 The beginning of a blank line does not count as the end of a line."
198 :type 'boolean
199 :group 'editing-basics)
201 (defcustom *line-move-ignore-invisible* t
202 "*Non-nil means \\[next-line] and \\[previous-line] ignore invisible lines.
203 Outline mode sets this."
204 :type 'boolean
205 :group 'editing-basics)
207 (defcustom-buffer-local *goal-column* nil
208 "*Semipermanent goal column for vertical motion, as set by \\[set-goal-column], or nil."
209 :type '(choice integer
210 (const :tag "None" nil))
211 :group 'editing-basics)
213 (defvar *temporary-goal-column* 0
214 "Current goal column for vertical motion.
215 It is the column where point was
216 at the start of current run of vertical motion commands.
217 When the `track-eol' feature is doing its job, the value is 9999.")
219 (defun line-move (arg &optional noerror to-end try-vscroll)
220 "This is like line-move-1 except that it also performs
221 vertical scrolling of tall images if appropriate.
222 That is not really a clean thing to do, since it mixes
223 scrolling with cursor motion. But so far we don't have
224 a cleaner solution to the problem of making C-n do something
225 useful given a tall image."
226 (declare (ignore try-vscroll))
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)
233 ;; )
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
239 ;; (if forward
240 ;; (+ (window-vscroll nil t)
241 ;; (min (cdr part)
242 ;; (* (frame-char-height) arg)))
243 ;; (max 0
244 ;; (- (window-vscroll nil t)
245 ;; (min (car part)
246 ;; (* (frame-char-height) (- arg))))))
247 ;; t)
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.
253 ;; (sit-for 0)
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)))
258 ;; (> (cdr part) 0))
259 ;; (set-window-vscroll nil (cdr part) t)))
260 ;; t)))
261 (line-move-1 arg noerror to-end))
262 ;; ))
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 (declare (ignore to-end))
271 (let ((*inhibit-point-motion-hooks* t)
272 (opoint (point))
273 (forward (> arg 0)))
274 (unwind-protect
275 (progn
276 (if (not (find *last-command* '(next-line previous-line)))
277 (setq *temporary-goal-column*
278 (if (and track-eol (eolp)
279 ;; Don't count beg of empty line as end of line
280 ;; unless we just did explicit end-of-line.
281 (or (not (bolp)) (eq *last-command* 'move-end-of-line)))
282 9999
283 (current-column))))
285 (if (and (not (integerp *selective-display*))
286 (not *line-move-ignore-invisible*))
287 ;; Use just newline characters.
288 ;; Set ARG to 0 if we move as many lines as requested.
289 (or (if (> arg 0)
290 (progn (if (> arg 1) (forward-line (1- arg)))
291 ;; This way of moving forward ARG lines
292 ;; verifies that we have a newline after the last one.
293 ;; It doesn't get confused by intangible text.
294 (end-of-line)
295 (if (zerop (forward-line 1))
296 (setq arg 0)))
297 (and (zerop (forward-line arg))
298 (bolp)
299 (setq arg 0)))
300 (unless noerror
301 (signal (if (< arg 0)
302 'beginning-of-buffer
303 'end-of-buffer)
304 nil)))
305 ;; Move by arg lines, but ignore invisible ones.
306 (let (done)
307 (while (and (> arg 0) (not done))
308 ;; If the following character is currently invisible,
309 ;; skip all characters with that same `invisible' property value.
310 (while (and (not (eobp)) (line-move-invisible-p (point)))
311 (goto-char (next-char-property-change (point))))
312 ;; Now move a line.
313 (end-of-line)
314 ;; If there's no invisibility here, move over the newline.
315 (cond
316 ((eobp)
317 (if (not noerror)
318 (signal 'end-of-buffer)
319 (setq done t)))
320 ((and (> arg 1) ;; Use vertical-motion for last move
321 (not (integerp *selective-display*))
322 (not (line-move-invisible-p (point))))
323 ;; We avoid vertical-motion when possible
324 ;; because that has to fontify.
325 (forward-line 1))
326 ;; Otherwise move a more sophisticated way.
327 ((zerop (vertical-motion 1))
328 (if (not noerror)
329 (signal 'end-of-buffer)
330 (setq done t))))
331 (unless done
332 (setq arg (1- arg))))
333 ;; The logic of this is the same as the loop above,
334 ;; it just goes in the other direction.
335 (while (and (< arg 0) (not done))
336 (beginning-of-line)
337 (cond
338 ((bobp)
339 (if (not noerror)
340 (signal 'beginning-of-buffer nil)
341 (setq done t)))
342 ((and (< arg -1) ;; Use vertical-motion for last move
343 (not (integerp *selective-display*))
344 (not (line-move-invisible-p (1- (point)))))
345 (forward-line -1))
346 ((zerop (vertical-motion -1))
347 (if (not noerror)
348 (signal 'beginning-of-buffer nil)
349 (setq done t))))
350 (unless done
351 (setq arg (1+ arg))
352 (while (and ;; Don't move over previous invis lines
353 ;; if our target is the middle of this line.
354 (or (zerop (or *goal-column* *temporary-goal-column*))
355 (< arg 0))
356 (not (bobp)) (line-move-invisible-p (1- (point))))
357 (goto-char (previous-char-property-change (point))))))))
358 ;; This is the value the function returns.
359 (= arg 0))
361 (cond ((> arg 0)
362 ;; If we did not move down as far as desired,
363 ;; at least go to end of line.
364 (end-of-line))
365 ((< arg 0)
366 ;; If we did not move up as far as desired,
367 ;; at least go to beginning of line.
368 (beginning-of-line))
370 (line-move-finish (or *goal-column* *temporary-goal-column*)
371 opoint forward))))))
373 (defun line-move-finish (column opoint forward)
374 (let ((repeat t))
375 (while repeat
376 ;; Set REPEAT to t to repeat the whole thing.
377 (setq repeat nil)
379 (let (new
380 (line-beg (save-excursion (beginning-of-line) (point)))
381 (line-end
382 ;; Compute the end of the line
383 ;; ignoring effectively invisible newlines.
384 (save-excursion
385 ;; Like end-of-line but ignores fields.
386 (skip-chars-forward "^\n")
387 (while (and (not (eobp)) (line-move-invisible-p (point)))
388 (goto-char (next-char-property-change (point)))
389 (skip-chars-forward "^\n"))
390 (point))))
392 ;; Move to the desired column.
393 (line-move-to-column column)
394 (setq new (point))
396 ;; Process intangibility within a line.
397 ;; With inhibit-point-motion-hooks bound to nil, a call to
398 ;; goto-char moves point past intangible text.
400 ;; However, inhibit-point-motion-hooks controls both the
401 ;; intangibility and the point-entered/point-left hooks. The
402 ;; following hack avoids calling the point-* hooks
403 ;; unnecessarily. Note that we move *forward* past intangible
404 ;; text when the initial and final points are the same.
405 (goto-char new)
406 (let ((*inhibit-point-motion-hooks* nil))
407 (goto-char new)
409 ;; If intangibility moves us to a different (later) place
410 ;; in the same line, use that as the destination.
411 (if (<= (point) line-end)
412 (setq new (point))
413 ;; If that position is "too late",
414 ;; try the previous allowable position.
415 ;; See if it is ok.
416 (progn
417 (backward-char)
418 (if (if forward
419 ;; If going forward, don't accept the previous
420 ;; allowable position if it is before the target line.
421 (< line-beg (point))
422 ;; If going backward, don't accept the previous
423 ;; allowable position if it is still after the target line.
424 (<= (point) line-end))
425 (setq new (point))
426 ;; As a last resort, use the end of the line.
427 (setq new line-end)))))
429 ;; Now move to the updated destination, processing fields
430 ;; as well as intangibility.
431 (goto-char opoint)
432 (let ((*inhibit-point-motion-hooks* nil))
433 (goto-char
434 (constrain-to-field new opoint nil t
435 'inhibit-line-move-field-capture)))
437 ;; If all this moved us to a different line,
438 ;; retry everything within that new line.
439 (when (or (< (point) line-beg) (> (point) line-end))
440 ;; Repeat the intangibility and field processing.
441 (setq repeat t))))))
443 (defun line-move-to-column (col)
444 "Try to find column COL, considering invisibility.
445 This function works only in certain cases,
446 because what we really need is for `move-to-column'
447 and `current-column' to be able to ignore invisible text."
448 (if (zerop col)
449 (beginning-of-line)
450 (let ((opoint (point)))
451 (move-to-column col)
452 ;; move-to-column doesn't respect field boundaries.
453 (goto-char (constrain-to-field (point) opoint))))
455 (when (and *line-move-ignore-invisible*
456 (not (bolp)) (line-move-invisible-p (1- (point))))
457 (let ((normal-location (point))
458 (normal-column (current-column)))
459 ;; If the following character is currently invisible,
460 ;; skip all characters with that same `invisible' property value.
461 (while (and (not (eobp))
462 (line-move-invisible-p (point)))
463 (goto-char (next-char-property-change (point))))
464 ;; Have we advanced to a larger column position?
465 (if (> (current-column) normal-column)
466 ;; We have made some progress towards the desired column.
467 ;; See if we can make any further progress.
468 (line-move-to-column (+ (current-column) (- col normal-column)))
469 ;; Otherwise, go to the place we originally found
470 ;; and move back over invisible text.
471 ;; that will get us to the same place on the screen
472 ;; but with a more reasonable buffer position.
473 (progn
474 (goto-char normal-location)
475 (let ((line-beg (save-excursion (beginning-of-line) (point))))
476 (while (and (not (bolp)) (line-move-invisible-p (1- (point))))
477 (goto-char (previous-char-property-change (point) line-beg)))))))))
479 (defcommand beginning-of-line ((&optional (n 1))
480 :prefix)
481 "Move the point to the beginning of the line in the current buffer."
482 (check-type n number)
483 (set-point (line-beginning-position n)))
485 (defcommand move-beginning-of-line ((arg)
486 :prefix)
487 "Move point to beginning of current line as displayed.
488 \(If there's an image in the line, this disregards newlines
489 which are part of the text that the image rests on.)
491 With argument ARG not nil or 1, move forward ARG - 1 lines first.
492 If point reaches the beginning or end of buffer, it stops there.
493 To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
494 (or arg (setq arg 1))
496 (let ((orig (point))
497 start first-vis first-vis-field-value)
499 ;; Move by lines, if ARG is not 1 (the default).
500 (if (/= arg 1)
501 (line-move (1- arg) t))
503 ;; Move to beginning-of-line, ignoring fields and invisibles.
504 (skip-chars-backward "\\n\\n") ;; FIXME: was "^\n"
505 (while (and (not (bobp)) (line-move-invisible-p (1- (point))))
506 (goto-char (previous-char-property-change (point)))
507 (skip-chars-backward "\\n\\n")) ;; FIXME: was "^\n"
508 (setq start (point))
510 ;; Now find first visible char in the line
511 (while (and (not (eobp)) (line-move-invisible-p (point)))
512 (goto-char (next-char-property-change (point))))
513 (setq first-vis (point))
515 ;; See if fields would stop us from reaching FIRST-VIS.
516 (setq first-vis-field-value
517 (constrain-to-field first-vis orig (/= arg 1) t nil))
519 (goto-char (if (/= first-vis-field-value first-vis)
520 ;; If yes, obey them.
521 first-vis-field-value
522 ;; Otherwise, move to START with attention to fields.
523 ;; (It is possible that fields never matter in this case.)
524 (constrain-to-field (point) orig
525 (/= arg 1) t nil)))))
528 (defcommand end-of-line ((&optional (n 1))
529 :prefix)
530 "Move point to end of current line.
531 With argument N not nil or 1, move forward N - 1 lines first.
532 If point reaches the beginning or end of buffer, it stops there.
533 To ignore intangibility, bind `inhibit-point-motion-hooks' to t.
535 This function constrains point to the current field unless this moves
536 point to a different line than the original, unconstrained result. If
537 N is nil or 1, and a rear-sticky field ends at point, the point does
538 not move. To ignore field boundaries bind `inhibit-field-text-motion'
539 to t."
540 (let (newpos)
541 (loop
542 (setf newpos (line-end-position n))
543 (set-point newpos)
544 (cond
545 ((and (> (point) newpos)
546 (char= (buffer-fetch-char (1- (point)) (current-buffer))
547 #\Newline))
548 ;; If we skipped over a newline that follows an invisible
549 ;; intangible run, move back to the last tangible position
550 ;; within the line.
551 (set-point (1- (point)))
552 (return))
553 ((and (> (point) newpos)
554 (< (point) (zv))
555 (char/= (buffer-fetch-char (point) (current-buffer))
556 #\Newline))
557 ;; If we skipped something intangible and now we're not
558 ;; really at eol, keep going.
559 (setf n 1))
560 (t (return))))
561 nil))
563 (defcommand erase-buffer ((&optional (buffer (current-buffer))))
564 "Erase the contents of the current buffer."
565 (buffer-erase buffer))
567 (defcommand execute-extended-command ((prefix)
568 :raw-prefix)
569 "Read a user command from the minibuffer."
570 (let* ((name (read-command (case (prefix-numeric-value prefix)
571 (1 "M-x ")
572 (4 "C-u M-x ")
573 (t (format nil "~a M-x " prefix)))))
574 (cmd (lookup-command name)))
575 (if cmd
576 (progn
577 (dispatch-command name)
578 (setf *this-command* (command-name cmd)))
579 (message "No Match"))))
581 (defcommand switch-to-buffer ((buffer &optional norecord)
582 (:buffer "Switch To Buffer: " (buffer-name (other-buffer (current-buffer)))))
583 "Select buffer buffer in the current window.
584 If buffer does not identify an existing buffer,
585 then this function creates a buffer with that name.
587 When called from Lisp, buffer may be a buffer, a string (a buffer name),
588 or nil. If buffer is nil, then this function chooses a buffer
589 using `other-buffer'.
590 Optional second arg norecord non-nil means
591 do not put this buffer at the front of the list of recently selected ones.
592 This function returns the buffer it switched to.
594 WARNING: This is NOT the way to work on another buffer temporarily
595 within a Lisp program! Use `set-buffer' instead. That avoids messing with
596 the window-buffer correspondences."
597 (unless buffer
598 (setf buffer (other-buffer (current-buffer))))
599 (let ((w (frame-current-window (selected-frame))))
600 (when (typep w 'minibuffer-window)
601 (error "its a minibuffer"))
602 (setf buffer (get-buffer-create buffer))
603 (set-buffer buffer)
604 (unless norecord
605 (record-buffer buffer))
606 (set-window-buffer w buffer)))
608 (defcommand save-buffers-kill-emacs ()
609 ;; TODO: save-some-buffers
610 (throw 'lice-quit t))
612 (defcommand kill-buffer ((buffer)
613 (:buffer "Kill buffer: " (buffer-name (current-buffer)) t))
614 "Kill the buffer BUFFER.
615 The argument may be a buffer or may be the name of a buffer.
616 defaults to the current buffer.
618 Value is t if the buffer is actually killed, nil if user says no.
620 The value of `kill-buffer-hook' (which may be local to that buffer),
621 if not void, is a list of functions to be called, with no arguments,
622 before the buffer is actually killed. The buffer to be killed is current
623 when the hook functions are called.
625 Any processes that have this buffer as the `process-buffer' are killed
626 with SIGHUP."
627 (let* ((target (get-buffer buffer))
628 (other (other-buffer target)))
629 (if target
630 (progn
631 ;; all windows carrying the buffer need a new buffer
632 (loop for w in (frame-window-list (selected-frame))
633 do (when (eq (window-buffer w) target)
634 (set-window-buffer w other)))
635 (setf *buffer-list* (delete target *buffer-list*)))
636 (error "No such buffer ~a" buffer))))
638 (defun eval-echo (string)
639 ;; FIXME: don't just abandon the output
640 (let* ((stream (make-string-output-stream))
641 (*standard-output* stream)
642 (*error-output* stream)
643 (*debug-io* stream))
644 (multiple-value-bind (sexpr pos) (read-from-string string)
645 (if (= pos (length string))
646 (message "~s" (eval sexpr))
647 (error "Trailing garbage is ~a" string)))))
649 (defun eval-print (string)
650 (multiple-value-bind (sexpr pos) (read-from-string string)
651 (if (= pos (length string))
652 (insert (format nil "~%~s~%" (eval sexpr)))
653 (error "Trailing garbage is ~a" string))))
655 (defcommand eval-expression ((s)
656 (:string "Eval: "))
657 ;;(handler-case
658 (eval-echo s))
659 ;;(error (c) (message "Eval error: ~s" c))))
661 (defcommand exchange-point-and-mark ()
662 (let ((p (point)))
663 (goto-char (marker-position (mark-marker)))
664 (set-marker (mark-marker) p)))
666 ;; FIXME: this variable is here just so code compiles. we still need
667 ;; to implement it.
668 (defvar transient-mark-mode nil)
670 (defcommand set-mark-command ()
671 (set-marker (mark-marker) (point))
672 (message "Mark set"))
674 (defun push-mark (&optional location nomsg activate)
675 "Set mark at LOCATION (point, by default) and push old mark on mark ring.
676 If the last global mark pushed was not in the current buffer,
677 also push LOCATION on the global mark ring.
678 Display `Mark set' unless the optional second arg NOMSG is non-nil.
679 In Transient Mark mode, activate mark if optional third arg ACTIVATE non-nil.
681 Novice Emacs Lisp programmers often try to use the mark for the wrong
682 purposes. See the documentation of `set-mark' for more information.
684 In Transient Mark mode, this does not activate the mark."
685 (declare (ignore location activate))
686 ;; TODO implement
687 (set-marker (mark-marker) (point))
688 (unless nomsg
689 (message "Mark set")))
691 ;; (defun kill-ring-save (beg end)
692 ;; "Save the region to the kill ring."
694 (defcommand scroll-up ((&optional arg)
695 :raw-prefix)
696 (let ((win (get-current-window)))
697 (window-scroll-up win (max 1 (or (and arg (prefix-numeric-value arg))
698 (- (window-height win)
699 *next-screen-context-lines*))))))
701 (defcommand scroll-down ((&optional arg)
702 :raw-prefix)
703 (let ((win (get-current-window)))
704 (window-scroll-down win (max 1 (or (and arg (prefix-numeric-value arg))
705 (- (window-height win)
706 *next-screen-context-lines*))))))
708 (defcommand end-of-buffer ()
709 "Move point to the end of the buffer; leave mark at previous position.
710 With arg N, put point N/10 of the way from the end.
712 If the buffer is narrowed, this command uses the beginning and size
713 of the accessible part of the buffer."
714 (set-mark-command)
715 (goto-char (point-max)))
717 (defcommand just-one-space ((&optional (n 1))
718 :prefix)
719 "Delete all spaces and tabs around point, leaving one space (or N spaces)."
720 (let ((orig-pos (point)))
721 (skip-chars-backward (coerce '(#\Space #\Tab) 'string))
722 (constrain-to-field nil orig-pos)
723 (dotimes (i n)
724 (if (char= (following-char) #\Space)
725 (forward-char 1)
726 (insert #\Space)))
727 (delete-region
728 (point)
729 (progn
730 (skip-whitespace-forward)
731 (constrain-to-field nil orig-pos t)))))
733 (defcommand beginning-of-buffer ()
734 "Move point to the beginning of the buffer; leave mark at previous position.
735 With arg N, put point N/10 of the way from the beginning.
737 If the buffer is narrowed, this command uses the beginning and size
738 of the accessible part of the buffer."
739 (set-mark-command)
740 (goto-char (point-min)))
742 (defcommand split-window-vertically ()
743 (split-window (get-current-window)))
745 (defcommand split-window-horizontally ()
746 (split-window (get-current-window) nil t))
748 (defcommand other-window ()
749 (let ((w (next-window (get-current-window) t)))
750 (if w
751 (select-window w)
752 (message "No other window."))))
754 (defcommand switch-to-buffer-other-window ((buffer)
755 (:buffer "Switch to buffer in other window: " (buffer-name (other-buffer (current-buffer)))))
756 (let* ((cw (get-current-window))
757 (w (or (next-window cw)
758 (split-window cw))))
759 (select-window w)
760 (switch-to-buffer buffer)))
762 (defcommand keyboard-quit ()
763 (signal 'quit))
765 ;;; kill ring
767 (defun kill-new (string &optional replace)
768 "Make STRING the latest kill in the kill ring.
769 Set the kill-ring-yank pointer to point to it.
770 Optional second argument REPLACE non-nil means that STRING will replace
771 the front of the kill ring, rather than being added to the list."
772 (if (and replace
773 *kill-ring*)
774 (setf (car *kill-ring*) string)
775 (push string *kill-ring*))
776 (when (> (length *kill-ring*) *kill-ring-max*)
777 (setf (cdr (nthcdr (1- *kill-ring-max*) *kill-ring*)) nil))
778 (setf *kill-ring-yank-pointer* *kill-ring*))
780 (defun copy-region-as-kill (start end &optional (buffer (current-buffer)))
781 (multiple-value-setq (start end) (validate-region start end buffer))
782 (kill-new (buffer-substring start end buffer)))
784 (defcommand kill-ring-save ()
785 (copy-region-as-kill (mark) (point)))
787 (defcommand kill-region ((beg end)
788 :region-beginning
789 :region-end)
790 "Kill between point and mark.
791 The text is deleted but saved in the kill ring.
792 The command C-y can retrieve it from there.
793 (If you want to kill and then yank immediately, use M-w.)"
794 (copy-region-as-kill beg end)
795 (delete-region beg end))
798 (defcommand kill-line ()
799 (kill-region (point)
800 (progn
801 (when (eobp)
802 (signal 'end-of-buffer))
803 (if (char= (buffer-char-after (current-buffer) (point)) #\Newline)
804 (forward-line 1)
805 (goto-char (buffer-end-of-line)))
806 (point))))
808 (defun current-kill (n &optional do-not-move)
809 "Rotate the yanking point by N places, and then return that kill.
810 If optional arg DO-NOT-MOVE is non-nil, then don't actually move the
811 yanking point; just return the Nth kill forward."
812 (unless *kill-ring*
813 (signal 'kill-ring-empty))
814 (let ((argth-kill-element
815 (nthcdr (mod (- n (length *kill-ring-yank-pointer*))
816 (length *kill-ring*))
817 *kill-ring*)))
818 (unless do-not-move
819 (setf *kill-ring-yank-pointer* argth-kill-element))
820 (car argth-kill-element)))
822 (defcommand yank ()
823 (set-mark-command)
824 (insert (current-kill 0)))
826 (defcommand yank-pop ()
827 (unless (eq *last-command* 'yank)
828 (error "Previous command was not a yank: ~a" *last-command*))
829 (setf *this-command* 'yank)
830 (delete-region (mark) (point))
831 (insert (current-kill 1)))
833 ;;; universal argument
835 (defun prefix-numeric-value (prefix)
836 "Return numeric meaning of raw prefix argument RAW.
837 A raw prefix argument is what you get from :raw-prefix.
838 Its numeric meaning is what you would get from :prefix."
839 ;; TODO
840 (cond ((null prefix)
842 ((eq prefix '-)
844 ((and (consp prefix)
845 (integerp (car prefix)))
846 (car prefix))
847 ((integerp prefix)
848 prefix)
849 (t 1)))
851 (defun prefix-arg ()
852 "Return numeric meaning of *prefix-arg*"
853 (prefix-numeric-value *prefix-arg*))
855 (defun raw-prefix-arg ()
856 "Return the current prefix arg in raw form."
857 *prefix-arg*)
859 (defvar *overriding-map-is-bound* nil)
860 (defvar *saved-overriding-map* nil)
861 (defvar *universal-argument-num-events* nil)
863 (defvar *universal-argument-map*
864 (let ((map (make-sparse-keymap)))
865 ;;(define-key map (kbd "t") 'universal-argument-other-key)
866 (define-key map t 'universal-argument-other-key)
867 ;;(define-key map [switch-frame] nil)
868 (define-key map (kbd "C-u") 'universal-argument-more)
869 (define-key map (kbd "-") 'universal-argument-minus)
870 (define-key map (kbd "0") 'digit-argument)
871 (define-key map (kbd "1") 'digit-argument)
872 (define-key map (kbd "2") 'digit-argument)
873 (define-key map (kbd "3") 'digit-argument)
874 (define-key map (kbd "4") 'digit-argument)
875 (define-key map (kbd "5") 'digit-argument)
876 (define-key map (kbd "6") 'digit-argument)
877 (define-key map (kbd "7") 'digit-argument)
878 (define-key map (kbd "8") 'digit-argument)
879 (define-key map (kbd "9") 'digit-argument)
880 ;; (define-key map [kp-0] 'digit-argument)
881 ;; (define-key map [kp-1] 'digit-argument)
882 ;; (define-key map [kp-2] 'digit-argument)
883 ;; (define-key map [kp-3] 'digit-argument)
884 ;; (define-key map [kp-4] 'digit-argument)
885 ;; (define-key map [kp-5] 'digit-argument)
886 ;; (define-key map [kp-6] 'digit-argument)
887 ;; (define-key map [kp-7] 'digit-argument)
888 ;; (define-key map [kp-8] 'digit-argument)
889 ;; (define-key map [kp-9] 'digit-argument)
890 ;; (define-key map [kp-subtract] 'universal-argument-minus)
891 map)
892 "Keymap used while processing \\[universal-argument].")
894 (defun ensure-overriding-map-is-bound ()
895 "Check `*overriding-terminal-local-map*' is `*universal-argument-map*'."
896 (unless *overriding-map-is-bound*
897 (setf *saved-overriding-map* *overriding-terminal-local-map*
898 *overriding-terminal-local-map* *universal-argument-map*
899 *overriding-map-is-bound* t)))
901 (defun restore-overriding-map ()
902 "Restore `*overriding-terminal-local-map*' to its saved value."
903 (setf *overriding-terminal-local-map* *saved-overriding-map*
904 *overriding-map-is-bound* nil))
906 (defcommand universal-argument ()
907 (setf *prefix-arg* (list 4)
908 *universal-argument-num-events* (length (this-command-keys)))
909 (ensure-overriding-map-is-bound))
911 (defcommand universal-argument-more ((arg)
912 :raw-prefix)
913 (if (consp arg)
914 (setf *prefix-arg* (list (* 4 (car arg))))
915 (if (eq arg '-)
916 (setf *prefix-arg* (list -4))
917 (progn
918 (setf *prefix-arg* arg)
919 (restore-overriding-map))))
920 (setf *universal-argument-num-events* (length (this-command-keys))))
922 (defcommand negative-argument ((arg)
923 :raw-prefix)
924 "Begin a negative numeric argument for the next command.
925 \\[universal-argument] following digits or minus sign ends the argument."
926 (cond ((integerp arg)
927 (setf *prefix-arg* (- arg)))
928 ((eq arg '-)
929 (setf *prefix-arg* nil))
931 (setf *prefix-arg* '-)))
932 (setf *universal-argument-num-events* (length (this-command-keys)))
933 (ensure-overriding-map-is-bound))
935 (defcommand digit-argument ((arg)
936 :raw-prefix)
937 "Part of the numeric argument for the next command.
938 \\[universal-argument] following digits or minus sign ends the argument."
939 (let* ((char (last-command-char))
940 (digit (- (logand (char-code char) #o177) (char-code #\0))))
941 (cond ((integerp arg)
942 (setf *prefix-arg* (+ (* arg 10)
943 (if (< arg 0) (- digit) digit))))
944 ((eq arg '-)
945 ;; Treat -0 as just -, so that -01 will work.
946 (setf *prefix-arg* (if (zerop digit) '- (- digit))))
948 (setf *prefix-arg* digit))))
949 (setf *universal-argument-num-events* (length (this-command-keys)))
950 (ensure-overriding-map-is-bound))
952 ;; For backward compatibility, minus with no modifiers is an ordinary
953 ;; command if digits have already been entered.
954 (defcommand universal-argument-minus ((arg)
955 :raw-prefix)
956 (if (integerp arg)
957 (universal-argument-other-key arg)
958 (negative-argument arg)))
960 ;; Anything else terminates the argument and is left in the queue to be
961 ;; executed as a command.
962 (defcommand universal-argument-other-key ((arg)
963 :raw-prefix)
964 (setf *prefix-arg* arg)
965 (let* ((keylist (this-command-keys)))
966 (setf *unread-command-events* keylist))
967 ;; (append (nthcdr *universal-argument-num-events* keylist)
968 ;; *unread-command-events*)))
969 ;;FIXME: (reset-this-command-lengths)
970 (restore-overriding-map))
973 ;; (defcommand append-to-buffer ((buffer :buffer "Append to buffer: " (buffer-name (other-buffer (current-buffer))))
974 ;; (start :region-beginning)
975 ;; (end :region-end))
976 ;; "Append to specified buffer the text of the region.
977 ;; It is inserted into that buffer before its point.
979 ;; When calling from a program, give three arguments:
980 ;; buffer (or buffer name), start and end.
981 ;; start and end specify the portion of the current buffer to be copied."
982 ;; (let ((oldbuf (current-buffer)))
983 ;; (save-excursion
984 ;; (let* ((append-to (get-buffer-create buffer))
985 ;; (windows (get-buffer-window-list append-to t t))
986 ;; point)
987 ;; (set-buffer append-to)
988 ;; (setf point (point))
989 ;; (barf-if-buffer-read-only)
990 ;; (insert-buffer-substring oldbuf start end)
991 ;; (dolist (window windows)
992 ;; (when (= (window-point window) point)
993 ;; (set-window-point window (point))))))))
995 (defcommand transpose-chars ((arg)
996 :prefix)
997 "Interchange characters around point, moving forward one character.
998 With prefix arg ARG, effect is to take character before point
999 and drag it forward past ARG other characters (backward if ARG negative).
1000 If no argument and at end of line, the previous two chars are exchanged."
1001 (and (null arg) (eolp) (forward-char -1))
1002 (transpose-subr 'forward-char (prefix-numeric-value arg)))
1004 (defcommand transpose-words ((arg)
1005 :prefix)
1006 "Interchange words around point, leaving point at end of them.
1007 With prefix arg ARG, effect is to take word before or around point
1008 and drag it forward past ARG other words (backward if ARG negative).
1009 If ARG is zero, the words around or after point and around or after mark
1010 are interchanged."
1011 ;; FIXME: `foo a!nd bar' should transpose into `bar and foo'.
1012 (transpose-subr 'forward-word arg))
1014 ;; (defun transpose-sexps ((arg)
1015 ;; :prefix)
1016 ;; "Like \\[transpose-words] but applies to sexps.
1017 ;; Does not work on a sexp that point is in the middle of
1018 ;; if it is a list or string."
1019 ;; (transpose-subr
1020 ;; (lambda (arg)
1021 ;; ;; Here we should try to simulate the behavior of
1022 ;; ;; (cons (progn (forward-sexp x) (point))
1023 ;; ;; (progn (forward-sexp (- x)) (point)))
1024 ;; ;; Except that we don't want to rely on the second forward-sexp
1025 ;; ;; putting us back to where we want to be, since forward-sexp-function
1026 ;; ;; might do funny things like infix-precedence.
1027 ;; (if (if (> arg 0)
1028 ;; ;;(looking-at "\\sw\\|\\s_")
1029 ;; ;; FIXME: we don't have looking-at or syntax classes. Fake it for now
1030 ;; (or (alpha-char-p (char-after (point)))
1031 ;; (find (char-after (point)) "*/+-%$!@&"))
1032 ;; (and (not (bobp))
1033 ;; (save-excursion (forward-char -1)
1034 ;; ;; (looking-at "\\sw\\|\\s_")
1035 ;; ;; FIXME: we don't have looking-at or syntax classes. Fake it for now
1036 ;; (or (alpha-char-p (char-after (point)))
1037 ;; (find (char-after (point)) "*/+-%$!@&"))
1038 ;; )))
1039 ;; ;; Jumping over a symbol. We might be inside it, mind you.
1040 ;; (progn (funcall (if (> arg 0)
1041 ;; 'skip-syntax-backward 'skip-syntax-forward)
1042 ;; "w_")
1043 ;; (cons (save-excursion (forward-sexp arg) (point)) (point)))
1044 ;; ;; Otherwise, we're between sexps. Take a step back before jumping
1045 ;; ;; to make sure we'll obey the same precedence no matter which direction
1046 ;; ;; we're going.
1047 ;; (funcall (if (> arg 0) 'skip-syntax-backward 'skip-syntax-forward) " .")
1048 ;; (cons (save-excursion (forward-sexp arg) (point))
1049 ;; (progn (while (or (forward-comment (if (> arg 0) 1 -1))
1050 ;; (not (zerop (funcall (if (> arg 0)
1051 ;; 'skip-syntax-forward
1052 ;; 'skip-syntax-backward)
1053 ;; ".")))))
1054 ;; (point)))))
1055 ;; arg 'special))
1057 (defcommand transpose-lines ((arg)
1058 :prefix)
1059 "Exchange current line and previous line, leaving point after both.
1060 With argument ARG, takes previous line and moves it past ARG lines.
1061 With argument 0, interchanges line point is in with line mark is in."
1062 (transpose-subr (function
1063 (lambda (arg)
1064 (if (> arg 0)
1065 (progn
1066 ;; Move forward over ARG lines,
1067 ;; but create newlines if necessary.
1068 (setq arg (forward-line arg))
1069 (if (char/= (preceding-char) #\Newline)
1070 (setq arg (1+ arg)))
1071 (if (> arg 0)
1072 (newline arg)))
1073 (forward-line arg))))
1074 arg))
1076 (defun transpose-subr (mover arg &optional special)
1077 (let ((aux (if special mover
1078 (lambda (x)
1079 (cons (progn (funcall mover x) (point))
1080 (progn (funcall mover (- x)) (point))))))
1081 pos1 pos2)
1082 (cond
1083 ((= arg 0)
1084 (save-excursion
1085 (setq pos1 (funcall aux 1))
1086 (goto-char (mark))
1087 (setq pos2 (funcall aux 1))
1088 (transpose-subr-1 pos1 pos2))
1089 (exchange-point-and-mark))
1090 ((> arg 0)
1091 (setq pos1 (funcall aux -1))
1092 (setq pos2 (funcall aux arg))
1093 (transpose-subr-1 pos1 pos2)
1094 (goto-char (car pos2)))
1096 (setq pos1 (funcall aux -1))
1097 (goto-char (car pos1))
1098 (setq pos2 (funcall aux arg))
1099 (transpose-subr-1 pos1 pos2)))))
1101 (defun transpose-subr-1 (pos1 pos2)
1102 (when (> (car pos1) (cdr pos1)) (setq pos1 (cons (cdr pos1) (car pos1))))
1103 (when (> (car pos2) (cdr pos2)) (setq pos2 (cons (cdr pos2) (car pos2))))
1104 (when (> (car pos1) (car pos2))
1105 (let ((swap pos1))
1106 (setq pos1 pos2 pos2 swap)))
1107 (if (> (cdr pos1) (car pos2)) (error "Don't have two things to transpose"))
1108 ;; (atomic-change-group
1109 (let (word2)
1110 ;; FIXME: We first delete the two pieces of text, so markers that
1111 ;; used to point to after the text end up pointing to before it :-(
1112 (setq word2 (delete-and-extract-region (car pos2) (cdr pos2)))
1113 (goto-char (car pos2))
1114 (insert (delete-and-extract-region (car pos1) (cdr pos1)))
1115 (goto-char (car pos1))
1116 (insert word2)))
1118 ;;;
1120 (defcustom-buffer-local *fill-prefix* nil
1121 "*String for filling to insert at front of new line, or nil for none."
1122 :type '(choice (const :tag "None" nil)
1123 string)
1124 :group 'fill)
1126 (defvar *fundamental-mode*
1127 (make-instance 'major-mode
1128 :name "Fundamental")
1129 "Major mode not specialized for anything in particular.
1130 Other major modes are defined by comparison with this one.")
1132 (defun turn-on-auto-fill ()
1133 "Unconditionally turn on Auto Fill mode."
1134 ;; FIXME: implement
1138 ;; FIXME: put this info in the following condition
1139 ;; (put 'mark-inactive 'error-conditions '(mark-inactive error))
1140 ;; (put 'mark-inactive 'error-message "The mark is not active now")
1142 (define-condition mark-inactive (lice-condition)
1145 (defvar activate-mark-hook nil
1146 "Hook run when the mark becomes active.
1147 It is also run at the end of a command, if the mark is active and
1148 it is possible that the region may have changed")
1150 (defvar deactivate-mark-hook nil
1151 "Hook run when the mark becomes inactive.")
1153 (defun mark (&optional force)
1154 "Return this buffer's mark value as integer, or nil if never set.
1156 In Transient Mark mode, this function signals an error if
1157 the mark is not active. However, if `mark-even-if-inactive' is non-nil,
1158 or the argument FORCE is non-nil, it disregards whether the mark
1159 is active, and returns an integer or nil in the usual way.
1161 If you are using this in an editing command, you are most likely making
1162 a mistake; see the documentation of `set-mark'."
1163 (if (or force (not transient-mark-mode) mark-active mark-even-if-inactive)
1164 (marker-position (mark-marker))
1165 (signal 'mark-inactive nil)))
1167 ;; ;; Many places set mark-active directly, and several of them failed to also
1168 ;; ;; run deactivate-mark-hook. This shorthand should simplify.
1169 ;; (defsubst deactivate-mark ()
1170 ;; "Deactivate the mark by setting `mark-active' to nil.
1171 ;; \(That makes a difference only in Transient Mark mode.)
1172 ;; Also runs the hook `deactivate-mark-hook'."
1173 ;; (cond
1174 ;; ((eq transient-mark-mode 'lambda)
1175 ;; (setq transient-mark-mode nil))
1176 ;; (transient-mark-mode
1177 ;; (setq mark-active nil)
1178 ;; (run-hooks 'deactivate-mark-hook))))
1180 (defun set-mark (pos)
1181 "Set this buffer's mark to POS. Don't use this function!
1182 That is to say, don't use this function unless you want
1183 the user to see that the mark has moved, and you want the previous
1184 mark position to be lost.
1186 Normally, when a new mark is set, the old one should go on the stack.
1187 This is why most applications should use `push-mark', not `set-mark'.
1189 Novice Emacs Lisp programmers often try to use the mark for the wrong
1190 purposes. The mark saves a location for the user's convenience.
1191 Most editing commands should not alter the mark.
1192 To remember a location for internal use in the Lisp program,
1193 store it in a Lisp variable. Example:
1195 (let ((beg (point))) (forward-line 1) (delete-region beg (point)))."
1197 (if pos
1198 (progn
1199 (setq mark-active t)
1200 (run-hooks 'activate-mark-hook)
1201 (set-marker (mark-marker) pos (current-buffer)))
1202 ;; Normally we never clear mark-active except in Transient Mark mode.
1203 ;; But when we actually clear out the mark value too,
1204 ;; we must clear mark-active in any mode.
1205 (progn
1206 (setq mark-active nil)
1207 (run-hooks 'deactivate-mark-hook)
1208 (set-marker (mark-marker) nil))))
1210 (define-buffer-local mark-ring nil
1211 "The list of former marks of the current buffer, most recent first.")
1212 (make-variable-buffer-local 'mark-ring)
1213 (setf (get 'mark-ring 'permanent-local) t)
1215 (defcustom mark-ring-max 16
1216 "*Maximum size of mark ring. Start discarding off end if gets this big."
1217 :type 'integer
1218 :group 'editing-basics)
1220 (defvar global-mark-ring nil
1221 "The list of saved global marks, most recent first.")
1223 (defcustom global-mark-ring-max 16
1224 "*Maximum size of global mark ring. \
1225 Start discarding off end if gets this big."
1226 :type 'integer
1227 :group 'editing-basics)
1229 (defcommand pop-to-mark-command ()
1230 "Jump to mark, and pop a new position for mark off the ring
1231 \(does not affect global mark ring\)."
1232 (if (null (mark t))
1233 (error "No mark set in this buffer")
1234 (progn
1235 (goto-char (mark t))
1236 (pop-mark))))
1238 ;; (defun push-mark-command (arg &optional nomsg)
1239 ;; "Set mark at where point is.
1240 ;; If no prefix arg and mark is already set there, just activate it.
1241 ;; Display `Mark set' unless the optional second arg NOMSG is non-nil."
1242 ;; (interactive "P")
1243 ;; (let ((mark (marker-position (mark-marker))))
1244 ;; (if (or arg (null mark) (/= mark (point)))
1245 ;; (push-mark nil nomsg t)
1246 ;; (setq mark-active t)
1247 ;; (run-hooks 'activate-mark-hook)
1248 ;; (unless nomsg
1249 ;; (message "Mark activated")))))
1251 (defcustom set-mark-command-repeat-pop nil
1252 "*Non-nil means that repeating \\[set-mark-command] after popping will pop.
1253 This means that if you type C-u \\[set-mark-command] \\[set-mark-command]
1254 will pop twice."
1255 :type 'boolean
1256 :group 'editing)
1258 ;; (defun set-mark-command (arg)
1259 ;; "Set mark at where point is, or jump to mark.
1260 ;; With no prefix argument, set mark, and push old mark position on local
1261 ;; mark ring; also push mark on global mark ring if last mark was set in
1262 ;; another buffer. Immediately repeating the command activates
1263 ;; `transient-mark-mode' temporarily.
1265 ;; With argument, e.g. \\[universal-argument] \\[set-mark-command], \
1266 ;; jump to mark, and pop a new position
1267 ;; for mark off the local mark ring \(this does not affect the global
1268 ;; mark ring\). Use \\[pop-global-mark] to jump to a mark off the global
1269 ;; mark ring \(see `pop-global-mark'\).
1271 ;; If `set-mark-command-repeat-pop' is non-nil, repeating
1272 ;; the \\[set-mark-command] command with no prefix pops the next position
1273 ;; off the local (or global) mark ring and jumps there.
1275 ;; With a double \\[universal-argument] prefix argument, e.g. \\[universal-argument] \
1276 ;; \\[universal-argument] \\[set-mark-command], unconditionally
1277 ;; set mark where point is.
1279 ;; Setting the mark also sets the \"region\", which is the closest
1280 ;; equivalent in Emacs to what some editors call the \"selection\".
1282 ;; Novice Emacs Lisp programmers often try to use the mark for the wrong
1283 ;; purposes. See the documentation of `set-mark' for more information."
1284 ;; (interactive "P")
1285 ;; (if (eq transient-mark-mode 'lambda)
1286 ;; (setq transient-mark-mode nil))
1287 ;; (cond
1288 ;; ((and (consp arg) (> (prefix-numeric-value arg) 4))
1289 ;; (push-mark-command nil))
1290 ;; ((not (eq this-command 'set-mark-command))
1291 ;; (if arg
1292 ;; (pop-to-mark-command)
1293 ;; (push-mark-command t)))
1294 ;; ((and set-mark-command-repeat-pop
1295 ;; (eq last-command 'pop-to-mark-command))
1296 ;; (setq this-command 'pop-to-mark-command)
1297 ;; (pop-to-mark-command))
1298 ;; ((and set-mark-command-repeat-pop
1299 ;; (eq last-command 'pop-global-mark)
1300 ;; (not arg))
1301 ;; (setq this-command 'pop-global-mark)
1302 ;; (pop-global-mark))
1303 ;; (arg
1304 ;; (setq this-command 'pop-to-mark-command)
1305 ;; (pop-to-mark-command))
1306 ;; ((and (eq last-command 'set-mark-command)
1307 ;; mark-active (null transient-mark-mode))
1308 ;; (setq transient-mark-mode 'lambda)
1309 ;; (message "Transient-mark-mode temporarily enabled"))
1310 ;; (t
1311 ;; (push-mark-command nil))))
1313 ;; (defun push-mark (&optional location nomsg activate)
1314 ;; "Set mark at LOCATION (point, by default) and push old mark on mark ring.
1315 ;; If the last global mark pushed was not in the current buffer,
1316 ;; also push LOCATION on the global mark ring.
1317 ;; Display `Mark set' unless the optional second arg NOMSG is non-nil.
1318 ;; In Transient Mark mode, activate mark if optional third arg ACTIVATE non-nil.
1320 ;; Novice Emacs Lisp programmers often try to use the mark for the wrong
1321 ;; purposes. See the documentation of `set-mark' for more information.
1323 ;; In Transient Mark mode, this does not activate the mark."
1324 ;; (unless (null (mark t))
1325 ;; (setq mark-ring (cons (copy-marker (mark-marker)) mark-ring))
1326 ;; (when (> (length mark-ring) mark-ring-max)
1327 ;; (move-marker (car (nthcdr mark-ring-max mark-ring)) nil)
1328 ;; (setcdr (nthcdr (1- mark-ring-max) mark-ring) nil)))
1329 ;; (set-marker (mark-marker) (or location (point)) (current-buffer))
1330 ;; ;; Now push the mark on the global mark ring.
1331 ;; (if (and global-mark-ring
1332 ;; (eq (marker-buffer (car global-mark-ring)) (current-buffer)))
1333 ;; ;; The last global mark pushed was in this same buffer.
1334 ;; ;; Don't push another one.
1335 ;; nil
1336 ;; (setq global-mark-ring (cons (copy-marker (mark-marker)) global-mark-ring))
1337 ;; (when (> (length global-mark-ring) global-mark-ring-max)
1338 ;; (move-marker (car (nthcdr global-mark-ring-max global-mark-ring)) nil)
1339 ;; (setcdr (nthcdr (1- global-mark-ring-max) global-mark-ring) nil)))
1340 ;; (or nomsg executing-kbd-macro (> (minibuffer-depth) 0)
1341 ;; (message "Mark set"))
1342 ;; (if (or activate (not transient-mark-mode))
1343 ;; (set-mark (mark t)))
1344 ;; nil)
1346 ;; (defun pop-mark ()
1347 ;; "Pop off mark ring into the buffer's actual mark.
1348 ;; Does not set point. Does nothing if mark ring is empty."
1349 ;; (when mark-ring
1350 ;; (setq mark-ring (nconc mark-ring (list (copy-marker (mark-marker)))))
1351 ;; (set-marker (mark-marker) (+ 0 (car mark-ring)) (current-buffer))
1352 ;; (move-marker (car mark-ring) nil)
1353 ;; (if (null (mark t)) (ding))
1354 ;; (setq mark-ring (cdr mark-ring)))
1355 ;; (deactivate-mark))
1357 (defcommand back-to-indentation ()
1358 "Move point to the first non-whitespace character on this line."
1359 (beginning-of-line 1)
1360 (skip-syntax-forward '(:whitespace) (line-end-position))
1361 ;; Move back over chars that have whitespace syntax but have the p flag.
1362 (backward-prefix-chars))
1364 (provide :lice-0.1/simple)