Andreas Fuchs asf@boinkor.net wrote:
Today, Luke Gorrie luke@bluetail.com wrote:
You mean like C-a but working from any line? Maybe a job for C-M-u (backward-up-list)?
Something like that; anything that takes (point) to the true beginning of the input and not to the beginning of the line would be fine. I'd just like to have a way to navigate large expressions easily (-:
Comint mode has C-c C-p to go to previous prompt. This is taken in the slime-repl by slime-pprint-eval-last-expression, which is not really needed in the repl I think. Unbind that and bind to comint-previous-prompt, and you're partway there. My problem is then: if what comes between the prompts is only OUTPUT, comint-previous-prompt will not work because it is looking for the start of the previous input. This is not a problem in the normal comint modes, because you always have some input before you get any output. With lisp, which can be provoked to do output either from a running thread or something coming in on the slime connection, this is not good enough. I suggest removing :inferior t from the \C-p the 'slime-keys' variable, and adding something like (tested for 5 minutes):
(defun slime-repl-previous-prompt (n) "Move to end of Nth previous prompt in the buffer. Unlike comint mode `comint-use-prompt-regexp-instead-of-fields' has no effect, and we look for a read-only (i.e. prompt ) field rather than an input field. " ;; cribbed and hacked from comint-previous-prompt (interactive "p") (slime-repl-next-prompt (- n)))
(defun slime-repl-next-prompt (n) "Move to end of Nth next prompt in the buffer. Unlike comint mode `comint-use-prompt-regexp-instead-of-fields' has no effect, and we look for a read-only (i.e. prompt ) field rather than an input field. " ;; cribbed and hacked from comint-next-prompt ;; the 'read-only' thing is really not nice, but what else but a prompt ;; would ever be read only? (interactive "p") (let ((pos (point)) (input-pos nil) prev-pos) (while (/= n 0) (setq prev-pos pos) (setq pos (if (> n 0) (next-single-char-property-change pos 'read-only) (previous-single-char-property-change pos 'read-only))) (cond ((or (null pos) (= pos prev-pos)) ;; Ran off the end of the buffer. (when (> n 0) ;; There's always an input field at the end of the ;; buffer, but it has a `field' property of nil. (setq input-pos (point-max))) ;; stop iterating (setq n 0)) ((eq (get-char-property pos 'read-only) nil) (setq n (if (< n 0) (1+ n) (1- n))) (setq input-pos pos)))) (when input-pos (goto-char input-pos))))
(define-key slime-repl-mode-map "\C-c\C-n" 'slime-repl-next-prompt) (define-key slime-repl-mode-map "\C-c\C-p" 'slime-repl-previous-prompt)
The reason this has only been tested for 5 minutes is that I had an even grosser hack bound on C-a. This will move to column 0 if we're already at the prompt, and then to the previous prompt if we're already at col 0. This hack will henceforth be abandoned.
(defun slime-repl-bol () "Go to the beginning of line or the prompt." (interactive) (let ((point (point))) (if (and (>= (point) slime-repl-input-start-mark) (slime-same-line-p (point) slime-repl-input-start-mark)) (goto-char slime-repl-input-start-mark) (beginning-of-line 1)) (if (eql point (point)) ; go to very beginning of line (forward-line 0)) (if (eql point (point)) ; go to end of previous field (goto-char (previous-single-char-property-change (point) 'read-only)))))