home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / packages / comint-isearch.el < prev    next >
Encoding:
Text File  |  1992-06-16  |  10.4 KB  |  326 lines

  1. ; Return-Path: <mathur@nas.nasa.gov>
  2. ; Received: from hal.com (hal-backbone) by halaus.hal.com (4.1/SMI-4.1)
  3. ;     id AA06798; Fri, 10 Apr 92 17:06:06 CDT
  4. ; Received: from mail.cis.ohio-state.edu by hal.com (4.1/SMI-4.1)
  5. ;     id AA08054; Fri, 10 Apr 92 15:05:47 PDT
  6. ; Received: from wk218.nas.nasa.gov by mail.cis.ohio-state.edu (5.61-kk/5.911008)
  7. ;     id AA29703; Fri, 10 Apr 92 18:05:32 -0400
  8. ; Received: by wk218.nas.nasa.gov (5.61/1.34)
  9. ;     id AA21659; Fri, 10 Apr 92 15:05:04 -0700
  10. ; Date: Fri, 10 Apr 92 15:05:04 -0700
  11. ; From: mathur@nas.nasa.gov (Sanjay R. Mathur)
  12. ; Reply-To: tg.southern@rxuk.xerox.com
  13. ; Subject: comint-isearch
  14. ; Status: OR
  15. ; [ I am forwarding this on behalf of Terry. Please address any responses
  16. ;   directly to him at the address below.  -- Sanjay ]
  17. ; This is an incremental command search mode for comint.  Previous
  18. ; commands that match are inserted on the command line as you type.
  19. ; Anyone familiar with the emacs isearch or bash should find this easy
  20. ; to adapt to.
  21. ; Terry.
  22. ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  23. ;   Terry Glanfield, +44 483 753 057, tg.southern@rxuk.xerox.com 
  24. ; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  25. ;;; -*-Emacs-Lisp-*- Incremental command search for comint
  26. ;;; Terry Glanfield (tg.southern@rxuk.xerox.com)
  27. ;;; Version 1.0
  28. ;;; 
  29. ;;; This file is not part of GNU Emacs but the same permissions apply.
  30. ;;; 
  31. ;;; GNU Emacs is free software; you can redistribute it and/or modify
  32. ;;; it under the terms of the GNU General Public License as published by
  33. ;;; the Free Software Foundation; either version 1, or (at your option)
  34. ;;; any later version.
  35. ;;;
  36. ;;; GNU Emacs is distributed in the hope that it will be useful,
  37. ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  38. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  39. ;;; GNU General Public License for more details.
  40. ;;;
  41. ;;; You should have received a copy of the GNU General Public License
  42. ;;; along with GNU Emacs; see the file COPYING.  If not, write to
  43. ;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  44. ;;;
  45. ;;;
  46. ;;; This is an incremental command search mode for comint.  Previous
  47. ;;; commands that match are inserted on the command line as you type.
  48. ;;; Anyone familiar with the emacs isearch or bash should find this easy
  49. ;;; to adapt to.
  50. ;;; 
  51. ;;; It is based on ideas from bash and borrows heavily from isearch.el.
  52. ;;; 
  53. ;;; Differences from bash:
  54. ;;;   * C-s searches forwards
  55. ;;;   * DEL cancels characters or moves to previous search
  56. ;;;   * C-g also moves to previous successful search
  57. ;;;   * Inserts previous search string
  58. ;;; 
  59. ;;; Differences from isearch:
  60. ;;;   * No C-w or C-y
  61. ;;;   * No wrap around, yet
  62. ;;; 
  63. ;;; It uses the variables search-repeat-char, search-exit-char etc.
  64. ;;; 
  65. ;;;  recommended usage:
  66. ;;; (setq cmushell-load-hook
  67. ;;;       '((lambda ()
  68. ;;;       (require 'comint-isearch)
  69. ;;;       (define-key cmushell-mode-map "\C-r" 'comint-isearch))))
  70.  
  71. ;; LCD Archive Entry:
  72. ;; comint-isearch|Terry Glanfield|tg.southern@rxuk.xerox.com|
  73. ;; Command line incremental searching for comint.|
  74. ;; 92-04-10|Version 1.0|~/packages/comint-isearch.el.Z|
  75.  
  76. (require 'comint)
  77. (provide 'comint-isearch)
  78.  
  79. (defvar comint-last-isearch-string nil
  80.   "Last string searched for in comint-isearch.")
  81.  
  82. (defvar comint-isearch-buffer " *Ring Buffer*"
  83.   "Buffer used in comint-isearch")
  84.  
  85. (defun comint-isearch ()
  86.   "Do incremental searching for commands in comint shells.
  87. As you type characters, they add to the search string and the
  88. matching command line from the history ring is inserted.
  89. Type Delete to cancel characters from end of search string.
  90. Type ESC to exit, leaving point at location found.
  91. Type C-r to search again, C-s to search again forwards.
  92. Type C-q to quote control character to search for it.
  93. Type RET to send this command to the shell.
  94. Other control and meta characters terminate the search
  95.  and are then executed normally.
  96. The above special characters are mostly controlled by parameters;
  97.  do M-x apropos on search-.*-char to find them.
  98. C-g while searching or when search has failed
  99.  cancels input back to what has been found successfully.
  100. C-g when search is successful aborts and moves point to starting point."
  101.   (interactive)
  102.   (let ((ring-len (ring-length input-ring)))
  103.     (cond ((not (comint-after-pmark-p))
  104.        (isearch-backward))
  105.       ((<= ring-len 0)
  106.        (message "Empty input ring")
  107.        (ding))
  108.       (t
  109.        (comint-isearch-internal)))))
  110.  
  111. (defun comint-isearch-internal ()
  112.   (let* ((search-string "")
  113.      (search-message "")
  114.      (success t)
  115.      (cmds nil)
  116.      (forward nil)
  117.      (pmark (marker-position
  118.          (process-mark (get-buffer-process (current-buffer)))))
  119.      (saved-prompt (buffer-substring
  120.             (save-excursion (beginning-of-line) (point))
  121.             pmark))
  122.      (saved-command (buffer-substring
  123.              pmark
  124.              (save-excursion (end-of-line) (point))))
  125.      (saved-point (- (point-max) (point)))
  126.      (ring input-ring)
  127.      (ring-buf (get-buffer-create comint-isearch-buffer))
  128.      (ring-point nil)
  129.      (line-point 0)
  130.      (abort-flag nil)
  131.      (inhibit-quit t))  ;Prevent ^G from quitting.
  132.     (save-excursion
  133.       (set-buffer ring-buf)
  134.       ;; fill temporary buffer with history ring
  135.       (erase-buffer)
  136.       (let ((n ring-len))
  137.     (while (> n 0)
  138.       (setq n (1- n))
  139.       (insert (ring-ref ring n) 10)))
  140.       (insert saved-command)
  141.       (end-of-buffer)
  142.       (backward-char saved-point)
  143.       (setq ring-point (point))
  144.       (setq line-point (- (point-max) (point))))
  145.     (comint-isearch-push)
  146.     (catch 'search-done
  147.       (while t
  148.     (or (>= unread-command-char 0)
  149.         (progn
  150.           (or (input-pending-p)
  151.           (comint-isearch-prompt))))
  152.     (let ((char (if quit-flag
  153.             ?\C-g
  154.               (read-char))))
  155.       (setq quit-flag nil)
  156.       (cond ((and (>= char 128)
  157.               search-exit-option)
  158.          (setq unread-command-char char)
  159.          ;; Meta character means exit search.
  160.          (setq unread-command-char char)
  161.          (throw 'search-done t))
  162.         ((eq char search-exit-char)
  163.          ;; Esc means exit search normally.
  164.          (throw 'search-done t))
  165.         ((= char ?\C-g)
  166.          ;; ^G means the user tried to quit.
  167.          ;; needs to be more clever
  168.          (ding)
  169.          (discard-input)
  170.          (if success
  171.              ;; really do quit.
  172.              (progn (setq abort-flag t)
  173.                 (throw 'search-done t))
  174.            ;; If search is failing, rub out until it is once more
  175.            ;;  successful.
  176.            (while (not success) (comint-isearch-pop))
  177.            ;; If it is now at the start, exit anyway
  178.            (if (equal search-string "")
  179.                (progn (setq abort-flag t)
  180.                   (throw 'search-done t)))))
  181.         ((or (eq char search-repeat-char)
  182.              (eq char search-reverse-char))
  183.          (if (eq forward (eq char search-repeat-char))
  184.              ;; C-s in forward or C-r in reverse.
  185.              (if (equal search-string "")
  186.              ;; If search string is empty, use last one.
  187.              (setq search-string comint-last-isearch-string
  188.                    search-message (mapconcat 'text-char-description
  189.                              search-string ""))
  190.                ;; If already have what to search for, repeat it.
  191.                (or success (ding)))
  192.            ;; C-s in reverse or C-r in forward, change direction.
  193.            (setq forward (not forward)))
  194.          (setq success t)
  195.          (or (equal search-string "")
  196.              (comint-isearch-search t))
  197.          (comint-isearch-push))
  198.         ((= char search-delete-char)
  199.          ;; Rubout means discard last input item and move point
  200.          ;; back.  If buffer is empty, just beep.
  201.           (if (null (cdr cmds))
  202.               (ding)
  203.             (comint-isearch-pop)))
  204.         ((or (= char ?\r)
  205.              (= char ?\n))
  206.          ;; Accept this line
  207.          (setq unread-command-char char)
  208.          (throw 'search-done t))
  209.         (t
  210.          ;; could add search-yank-word-char
  211.          ;; and search-yank-line-char in here
  212.          (cond ((and
  213.              search-exit-option
  214.              (/= char search-quote-char)
  215.              (or (= char ?\177)
  216.                  (and (< char ? ) (/= char ?\t) (/= char ?\r))))
  217.             ;; Any other control char =>
  218.             ;;  unread it and exit the search normally.
  219.             (setq unread-command-char char)
  220.             (throw 'search-done t))
  221.                (t
  222.             ;; Any other character => add it to the
  223.             ;;  search string and search.
  224.             (and (= char search-quote-char)
  225.                  (setq char (read-quoted-char
  226.                      (comint-isearch-prompt t))))
  227.             (setq search-string (concat
  228.                          search-string
  229.                          (char-to-string char))
  230.                   search-message (concat
  231.                           search-message
  232.                           (text-char-description char)))))
  233.          (if success
  234.              (comint-isearch-search))
  235.          (comint-isearch-push))))))
  236.     (message "")
  237.     (delete-region
  238.      (progn (beginning-of-line) (point))
  239.      (progn (end-of-line) (point)))
  240.     (insert-string saved-prompt)
  241.     (if (or abort-flag
  242.         (equal search-string ""))
  243.     (progn (insert saved-command)
  244.            (backward-char saved-point))
  245.       (progn (insert (comint-isearch-selected-line))
  246.          (backward-char line-point)
  247.          (if (> (length search-string) 0)
  248.          (setq comint-last-isearch-string search-string))))
  249.     (set-marker (process-mark (get-buffer-process (current-buffer))) pmark)))
  250.  
  251. (defun comint-isearch-selected-line ()
  252.   (save-excursion
  253.     (set-buffer ring-buf)
  254.     (goto-char ring-point)
  255.     (beginning-of-line)
  256.     (buffer-substring
  257.      (point)
  258.      (progn (end-of-line) (point)))))
  259.  
  260. (defun comint-isearch-prompt (&optional c-q-hack)
  261.   (let ((m (concat "(I-search: '"
  262.            search-message
  263.            (if c-q-hack "^Q" "")
  264.            "'): "))
  265.     (c (if ring-point
  266.            (comint-isearch-selected-line)
  267.          "")))
  268.     (beginning-of-line)
  269.     (delete-region (point) (save-excursion (end-of-line) (point)))
  270.     (insert-string m c)
  271.     (backward-char line-point)
  272.     ;; ditch garbage from mini-buffer
  273.     (message " ")))
  274.  
  275. (defun comint-isearch-pop ()
  276.   (setq cmds (cdr cmds))
  277.   (let ((cmd (car cmds)))
  278.     (setq search-string (car cmd)
  279.       search-message (car (cdr cmd))
  280.       success (nth 2 cmd)
  281.       forward (nth 3 cmd)
  282.       ring-point (nth 4 cmd)
  283.       line-point (nth 5 cmd))
  284.     (save-excursion
  285.       (set-buffer ring-buf)
  286.       (goto-char ring-point))))
  287.  
  288. (defun comint-isearch-push ()
  289.   (setq cmds (cons (list search-string search-message success
  290.              forward ring-point line-point)
  291.            cmds)))
  292.  
  293. (defun comint-isearch-search (&optional repeat)
  294.   (save-excursion
  295.     (set-buffer ring-buf)
  296.     (if forward
  297.     (goto-char ring-point)
  298.       (goto-char (+ ring-point (if (null repeat) (length search-string) 0))))
  299.     (condition-case lossage
  300.     (let ((inhibit-quit nil))
  301.       (setq success
  302.         (funcall
  303.          (if forward 'search-forward 'search-backward)
  304.          search-string nil t))
  305.       (if success
  306.           (progn (setq ring-point (point))
  307.              (end-of-line)
  308.              (setq line-point (- (point) ring-point)))))
  309.       (quit (setq unread-command-char ?\C-g)
  310.         (setq success nil)))
  311.     (if success
  312.     nil
  313.       ;; Ding if failed this time after succeeding last time.
  314.       (and (nth 2 (car cmds))
  315.        (ding)))))
  316.  
  317.  
  318.