+
+;; State used by `comint-insert-previous-argument' when cycling.
+(defvar comint-insert-previous-argument-last-start-pos nil)
+(make-variable-buffer-local 'comint-insert-previous-argument-last-start-pos)
+(defvar comint-insert-previous-argument-last-index nil)
+(make-variable-buffer-local 'comint-insert-previous-argument-last-index)
+
+;; Needs fixing:
+;; make comint-arguments understand negative indices as bash does
+(defun comint-insert-previous-argument (index)
+ "Insert the INDEXth argument from the previous Comint command-line at point.
+Spaces are added at beginning and/or end of the inserted string if
+necessary to ensure that it's separated from adjacent arguments.
+Interactively, if no prefix argument is given, the last argument is inserted.
+Repeated interactive invocations will cycle through the same argument
+from progressively earlier commands (using the value of INDEX specified
+with the first command).
+This command is like `M-.' in bash."
+ (interactive "P")
+ (unless (null index)
+ (setq index (prefix-numeric-value index)))
+ (cond ((eq last-command this-command)
+ ;; Delete last input inserted by this command.
+ (delete-region comint-insert-previous-argument-last-start-pos (point))
+ (setq index comint-insert-previous-argument-last-index))
+ (t
+ ;; This is a non-repeat invocation, so initialize state.
+ (setq comint-input-ring-index nil)
+ (setq comint-insert-previous-argument-last-index index)
+ (when (null comint-insert-previous-argument-last-start-pos)
+ ;; First usage; initialize to a marker
+ (setq comint-insert-previous-argument-last-start-pos
+ (make-marker)))))
+ ;; Make sure we're not in the prompt, and add a beginning space if necess.
+ (if (<= (point) (comint-line-beginning-position))
+ (comint-bol)
+ (just-one-space))
+ ;; Remember the beginning of what we insert, so we can delete it if
+ ;; the command is repeated.
+ (set-marker comint-insert-previous-argument-last-start-pos (point))
+ ;; Insert the argument.
+ (let ((input-string (comint-previous-input-string 0)))
+ (when (string-match "[ \t\n]*&" input-string)
+ ;; strip terminating '&'
+ (setq input-string (substring input-string 0 (match-beginning 0))))
+ (insert (comint-arguments input-string index index)))
+ ;; Make next invocation return arg from previous input
+ (setq comint-input-ring-index (1+ (or comint-input-ring-index 0)))
+ ;; Add a terminating space if necessary.
+ (unless (eolp)
+ (just-one-space)))
+
+\f
+;; Support editing with `comint-prompt-read-only' set to t.
+
+(defun comint-update-fence ()
+ "Update read-only status of newline before point.
+The `fence' read-only property is used to indicate that a newline
+is read-only for no other reason than to \"fence off\" a
+following front-sticky read-only region. This is used to
+implement comint read-only prompts. If the text after a newline
+changes, the read-only status of that newline may need updating.
+That is what this function does.
+
+This function does nothing if point is not at the beginning of a
+line, or is at the beginning of the accessible portion of the buffer.
+Otherwise, if the character after point has a front-sticky
+read-only property, then the preceding newline is given a
+read-only property of `fence', unless it already is read-only.
+If the character after point does not have a front-sticky
+read-only property, any read-only property of `fence' on the
+preceding newline is removed."
+ (let* ((pt (point)) (lst (get-text-property pt 'front-sticky))
+ (inhibit-modification-hooks t))
+ (and (bolp)
+ (not (bobp))
+ (if (and (get-text-property pt 'read-only)
+ (if (listp lst) (memq 'read-only lst) t))
+ (unless (get-text-property (1- pt) 'read-only)
+ (put-text-property (1- pt) pt 'read-only 'fence))
+ (when (eq (get-text-property (1- pt) 'read-only) 'fence)
+ (remove-list-of-text-properties (1- pt) pt '(read-only)))))))
+
+(defun comint-kill-whole-line (&optional arg)
+ "Kill current line, ignoring read-only and field properties.
+With prefix arg, kill that many lines starting from the current line.
+If arg is negative, kill backward. Also kill the preceding newline,
+instead of the trailing one. \(This is meant to make \\[repeat] work well
+with negative arguments.)
+If arg is zero, kill current line but exclude the trailing newline.
+The read-only status of newlines is updated with `comint-update-fence',
+if necessary."
+ (interactive "p")
+ (let ((inhibit-read-only t) (inhibit-field-text-motion t))
+ (kill-whole-line arg)
+ (when (>= arg 0) (comint-update-fence))))
+
+(defun comint-kill-region (beg end &optional yank-handler)
+ "Like `kill-region', but ignores read-only properties, if safe.
+This command assumes that the buffer contains read-only
+\"prompts\" which are regions with front-sticky read-only
+properties at the beginning of a line, with the preceding newline
+being read-only to protect the prompt. This is true of the
+comint prompts if `comint-prompt-read-only' is non-nil. This
+command will not delete the region if this would create mutilated
+or out of place prompts. That is, if any part of a prompt is
+deleted, the entire prompt must be deleted and all remaining
+prompts should stay at the beginning of a line. If this is not
+the case, this command just calls `kill-region' with all
+read-only properties intact. The read-only status of newlines is
+updated using `comint-update-fence', if necessary."
+ (interactive "r")
+ (save-excursion
+ (let* ((true-beg (min beg end))
+ (true-end (max beg end))
+ (beg-bolp (progn (goto-char true-beg) (bolp)))
+ (beg-lst (get-text-property true-beg 'front-sticky))
+ (beg-bad (and (get-text-property true-beg 'read-only)
+ (if (listp beg-lst) (memq 'read-only beg-lst) t)))
+ (end-bolp (progn (goto-char true-end) (bolp)))
+ (end-lst (get-text-property true-end 'front-sticky))
+ (end-bad (and (get-text-property true-end 'read-only)
+ (if (listp end-lst) (memq 'read-only end-lst) t))))
+ (if (or (and (not beg-bolp) (or beg-bad end-bad))
+ (and (not end-bolp) end-bad))
+ (kill-region beg end yank-handler)
+ (let ((inhibit-read-only t))
+ (kill-region beg end yank-handler)
+ (comint-update-fence))))))
+