+;;; Useful input history functions, courtesy of the Ergo group.
+
+;;; Eleven commands:
+;;; comint-dynamic-list-input-ring List history in help buffer.
+;;; comint-previous-input Previous input...
+;;; comint-previous-matching-input ...matching a string.
+;;; comint-previous-matching-input-from-input ... matching the current input.
+;;; comint-next-input Next input...
+;;; comint-next-matching-input ...matching a string.
+;;; comint-next-matching-input-from-input ... matching the current input.
+;;; comint-backward-matching-input Backwards input...
+;;; comint-forward-matching-input ...matching a string.
+;;; comint-replace-by-expanded-history Expand history at point;
+;;; replace with expanded history.
+;;; comint-magic-space Expand history and insert space.
+;;;
+;;; Three functions:
+;;; comint-read-input-ring Read into comint-input-ring...
+;;; comint-write-input-ring Write to comint-input-ring-file-name.
+;;; comint-replace-by-expanded-history-before-point Workhorse function.
+
+(defun comint-read-input-ring (&optional silent)
+ "Sets the buffer's `comint-input-ring' from a history file.
+The name of the file is given by the variable `comint-input-ring-file-name'.
+The history ring is of size `comint-input-ring-size', regardless of file size.
+If `comint-input-ring-file-name' is nil this function does nothing.
+
+If the optional argument SILENT is non-nil, we say nothing about a
+failure to read the history file.
+
+This function is useful for major mode commands and mode hooks.
+
+The structure of the history file should be one input command per line,
+with the most recent command last.
+See also `comint-input-ignoredups' and `comint-write-input-ring'."
+ (cond ((or (null comint-input-ring-file-name)
+ (equal comint-input-ring-file-name ""))
+ nil)
+ ((not (file-readable-p comint-input-ring-file-name))
+ (or silent
+ (message "Cannot read history file %s"
+ comint-input-ring-file-name)))
+ (t
+ (let ((history-buf (get-buffer-create " *temp*"))
+ (file comint-input-ring-file-name)
+ (count 0)
+ (ring (make-ring comint-input-ring-size)))
+ (unwind-protect
+ (save-excursion
+ (set-buffer history-buf)
+ (widen)
+ (erase-buffer)
+ (insert-file-contents file)
+ ;; Save restriction in case file is already visited...
+ ;; Watch for those date stamps in history files!
+ (goto-char (point-max))
+ (while (and (< count comint-input-ring-size)
+ (re-search-backward "^[ \t]*\\([^#\n].*\\)[ \t]*$"
+ nil t))
+ (let ((history (buffer-substring (match-beginning 1)
+ (match-end 1))))
+ (if (or (null comint-input-ignoredups)
+ (ring-empty-p ring)
+ (not (string-equal (ring-ref ring 0) history)))
+ (ring-insert-at-beginning ring history)))
+ (setq count (1+ count))))
+ (kill-buffer history-buf))
+ (setq comint-input-ring ring
+ comint-input-ring-index nil)))))
+
+(defun comint-write-input-ring ()
+ "Writes the buffer's `comint-input-ring' to a history file.
+The name of the file is given by the variable `comint-input-ring-file-name'.
+The original contents of the file are lost if `comint-input-ring' is not empty.
+If `comint-input-ring-file-name' is nil this function does nothing.
+
+Useful within process sentinels.
+
+See also `comint-read-input-ring'."
+ (cond ((or (null comint-input-ring-file-name)
+ (equal comint-input-ring-file-name "")
+ (null comint-input-ring) (ring-empty-p comint-input-ring))
+ nil)
+ ((not (file-writable-p comint-input-ring-file-name))
+ (message "Cannot write history file %s" comint-input-ring-file-name))
+ (t
+ (let* ((history-buf (get-buffer-create " *Temp Input History*"))
+ (ring comint-input-ring)
+ (file comint-input-ring-file-name)
+ (index (ring-length ring)))
+ ;; Write it all out into a buffer first. Much faster, but messier,
+ ;; than writing it one line at a time.
+ (save-excursion
+ (set-buffer history-buf)
+ (erase-buffer)
+ (while (> index 0)
+ (setq index (1- index))
+ (insert (ring-ref ring index) ?\n))
+ (write-region (buffer-string) nil file nil 'no-message)
+ (kill-buffer nil))))))
+
+
+(defun comint-dynamic-list-input-ring ()
+ "List in help buffer the buffer's input history."
+ (interactive)
+ (if (or (not (ring-p comint-input-ring))
+ (ring-empty-p comint-input-ring))
+ (message "No history")
+ (let ((history nil)
+ (history-buffer " *Input History*")
+ (index (1- (ring-length comint-input-ring)))
+ (conf (current-window-configuration)))
+ ;; We have to build up a list ourselves from the ring vector.
+ (while (>= index 0)
+ (setq history (cons (ring-ref comint-input-ring index) history)
+ index (1- index)))
+ ;; Change "completion" to "history reference"
+ ;; to make the display accurate.
+ (with-output-to-temp-buffer history-buffer
+ (display-completion-list history)
+ (set-buffer history-buffer)
+ (forward-line 3)
+ (while (search-backward "completion" nil 'move)
+ (replace-match "history reference")))
+ (sit-for 0)
+ (message "Hit space to flush")
+ (let ((ch (read-event)))
+ (if (eq ch ?\ )
+ (set-window-configuration conf)
+ (setq unread-command-events (list ch)))))))
+
+
+(defun comint-regexp-arg (prompt)
+ ;; Return list of regexp and prefix arg using PROMPT.
+ (let* ((minibuffer-history-sexp-flag nil)
+ ;; Don't clobber this.
+ (last-command last-command)
+ (regexp (read-from-minibuffer prompt nil nil nil
+ 'minibuffer-history-search-history)))
+ (list (if (string-equal regexp "")
+ (setcar minibuffer-history-search-history
+ (nth 1 minibuffer-history-search-history))
+ regexp)
+ (prefix-numeric-value current-prefix-arg))))
+
+(defun comint-search-arg (arg)
+ ;; First make sure there is a ring and that we are after the process mark
+ (cond ((not (comint-after-pmark-p))
+ (error "Not at command line"))
+ ((or (null comint-input-ring)
+ (ring-empty-p comint-input-ring))
+ (error "Empty input ring"))
+ ((zerop arg)
+ ;; arg of zero resets search from beginning, and uses arg of 1
+ (setq comint-input-ring-index nil)
+ 1)
+ (t
+ arg)))
+
+(defun comint-search-start (arg)
+ ;; Index to start a directional search, starting at comint-input-ring-index
+ (if comint-input-ring-index
+ ;; If a search is running, offset by 1 in direction of arg
+ (mod (+ comint-input-ring-index (if (> arg 0) 1 -1))
+ (ring-length comint-input-ring))
+ ;; For a new search, start from beginning or end, as appropriate
+ (if (>= arg 0)
+ 0 ; First elt for forward search
+ (1- (ring-length comint-input-ring))))) ; Last elt for backward search
+
+(defun comint-previous-input-string (arg)
+ "Return the string ARG places along the input ring.
+Moves relative to `comint-input-ring-index'."
+ (ring-ref comint-input-ring (if comint-input-ring-index
+ (mod (+ arg comint-input-ring-index)
+ (ring-length comint-input-ring))
+ arg)))