Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
150 lines (140 sloc) 5.33 KB
;; C-SPC, C-M-SPC, C-u C-SPC enhancements
(defun mark-sexp (&optional arg)
"Set mark ARG sexps from point.
The place mark goes is the same place \\[forward-sexp] would
move to with the same argument.
If this command is repeated, it marks the next ARG sexps after the ones
already marked."
(interactive "p")
(cond ((and (eq last-command this-command) (mark t))
(set-mark
(save-excursion
(goto-char (mark))
(forward-sexp (or arg 1))
(point))))
(t
(push-mark
(save-excursion
(forward-sexp (or arg 1))
(point))
nil t))))
(defun pop-to-mark-command ()
"Jump to mark, and pop a new position for mark off the ring
\(does not affect global mark ring\)."
(interactive)
(if (null (mark t))
(error "No mark set in this buffer")
(goto-char (mark t))
(pop-mark)))
(defun push-mark-command (arg &optional nomsg)
"Set mark at where point is.
If no prefix arg and mark is already set there, just activate it.
Display `Mark set' unless the optional second arg NOMSG is non-nil."
(interactive "P")
(let ((mark (marker-position (mark-marker))))
(if (or arg (null mark) (/= mark (point)))
(push-mark nil nomsg t)
(setq mark-active t)
(unless nomsg
(message "Mark activated")))))
(defun set-mark-command (arg)
"Set mark at where point is, or jump to mark.
With no prefix argument, set mark, push old mark position on local mark
ring, and push mark on global mark ring. Immediately repeating the
command activates `transient-mark-mode' temporarily.
With argument, jump to mark, and pop a new position for mark off the ring
\(does not affect global mark ring\). Repeating the command without
an argument jumps to the next position off the mark ring.
Novice Emacs Lisp programmers often try to use the mark for the wrong
purposes. See the documentation of `set-mark' for more information."
(interactive "P")
(if (eq transient-mark-mode 'lambda)
(setq transient-mark-mode nil))
(cond
((not (eq this-command 'set-mark-command))
(if arg
(pop-to-mark-command)
(push-mark-command t)))
((eq last-command 'pop-to-mark-command)
(if (and (consp arg) (> (prefix-numeric-value arg) 4))
(push-mark-command nil)
(setq this-command 'pop-to-mark-command)
(pop-to-mark-command)))
((eq last-command 'pop-global-mark)
(if (and (consp arg) (> (prefix-numeric-value arg) 4))
(push-mark-command nil)
(setq this-command 'pop-global-mark)
(pop-global-mark)))
(arg
(setq this-command 'pop-to-mark-command)
(pop-to-mark-command))
((and (eq last-command 'set-mark-command)
mark-active (null transient-mark-mode))
(setq transient-mark-mode 'lambda)
(message "Transient-mark-mode temporarily enabled"))
(t
(push-mark-command nil))))
(defun push-mark (&optional location nomsg activate)
"Set mark at LOCATION (point, by default) and push old mark on mark ring.
If the last global mark pushed was not in the current buffer,
also push LOCATION on the global mark ring.
Display `Mark set' unless the optional second arg NOMSG is non-nil.
In Transient Mark mode, activate mark if optional third arg ACTIVATE non-nil.
Novice Emacs Lisp programmers often try to use the mark for the wrong
purposes. See the documentation of `set-mark' for more information.
In Transient Mark mode, this does not activate the mark."
(if (null (mark t))
nil
(setq mark-ring (cons (copy-marker (mark-marker)) mark-ring))
(if (> (length mark-ring) mark-ring-max)
(progn
(move-marker (car (nthcdr mark-ring-max mark-ring)) nil)
(setcdr (nthcdr (1- mark-ring-max) mark-ring) nil))))
(set-marker (mark-marker) (or location (point)) (current-buffer))
;; Now push the mark on the global mark ring.
(if (and global-mark-ring
(eq (marker-buffer (car global-mark-ring)) (current-buffer)))
;; The last global mark pushed was in this same buffer.
;; Don't push another one.
nil
(setq global-mark-ring (cons (copy-marker (mark-marker)) global-mark-ring))
(if (> (length global-mark-ring) global-mark-ring-max)
(progn
(move-marker (car (nthcdr global-mark-ring-max global-mark-ring))
nil)
(setcdr (nthcdr (1- global-mark-ring-max) global-mark-ring) nil))))
(or nomsg executing-kbd-macro (> (minibuffer-depth) 0)
(message "Mark set"))
(if (or activate (not transient-mark-mode))
(set-mark (mark t)))
nil)
(defun pop-mark ()
"Pop off mark ring into the buffer's actual mark.
Does not set point. Does nothing if mark ring is empty."
(if mark-ring
(progn
(setq mark-ring (nconc mark-ring (list (copy-marker (mark-marker)))))
(set-marker (mark-marker) (+ 0 (car mark-ring)) (current-buffer))
(deactivate-mark)
(move-marker (car mark-ring) nil)
(if (null (mark t)) (ding))
(setq mark-ring (cdr mark-ring)))))
(defalias 'exchange-dot-and-mark 'exchange-point-and-mark)
(defun exchange-point-and-mark (&optional arg)
"Put the mark where point is now, and point where the mark is now.
This command works even when the mark is not active,
and it reactivates the mark.
With prefix arg, `transient-mark-mode' is enabled temporarily."
(interactive "P")
(if arg
(if mark-active
(if (null transient-mark-mode)
(setq transient-mark-mode 'lambda))
(setq arg nil)))
(unless arg
(let ((omark (mark t)))
(if (null omark)
(error "No mark set in this buffer"))
(set-mark (point))
(goto-char omark)
nil)))