Annotation of 43BSDReno/contrib/emacs-18.55/dist-1.3/fi/subproc.el, revision 1.1.1.1

1.1       root        1: ;;
                      2: ;; copyright (C) 1987, 1988 Franz Inc, Berkeley, Ca.
                      3: ;;
                      4: ;; The software, data and information contained herein are the property 
                      5: ;; of Franz, Inc.  
                      6: ;;
                      7: ;; This file (or any derivation of it) may be distributed without 
                      8: ;; further permission from Franz Inc. as long as:
                      9: ;;
                     10: ;;     * it is not part of a product for sale,
                     11: ;;     * no charge is made for the distribution, other than a tape
                     12: ;;       fee, and
                     13: ;;     * all copyright notices and this notice are preserved.
                     14: ;;
                     15: ;; If you have any comments or questions on this interface, please feel
                     16: ;; free to contact Franz Inc. at
                     17: ;;     Franz Inc.
                     18: ;;     Attn: Kevin Layer
                     19: ;;     1995 University Ave
                     20: ;;     Suite 275
                     21: ;;     Berkeley, CA 94704
                     22: ;;     (415) 548-3600
                     23: ;; or
                     24: ;;     emacs-info%[email protected]
                     25: ;;     ucbvax!franz!emacs-info
                     26: 
                     27: ;; $Header: subproc.el,v 1.46 88/11/22 20:21:39 layer Exp $
                     28: 
                     29: ;; This file has its (distant) roots in lisp/shell.el, so:
                     30: ;;
                     31: ;; Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
                     32: ;;
                     33: ;; This file is derived from part of GNU Emacs.
                     34: ;;
                     35: ;; GNU Emacs is distributed in the hope that it will be useful,
                     36: ;; but WITHOUT ANY WARRANTY.  No author or distributor
                     37: ;; accepts responsibility to anyone for the consequences of using it
                     38: ;; or for whether it serves any particular purpose or works at all,
                     39: ;; unless he says so in writing.  Refer to the GNU Emacs General Public
                     40: ;; License for full details.
                     41: ;;
                     42: ;; Everyone is granted permission to copy, modify and redistribute
                     43: ;; GNU Emacs, but only under the conditions described in the
                     44: ;; GNU Emacs General Public License.   A copy of this license is
                     45: ;; supposed to have been given to you along with GNU Emacs so you
                     46: ;; can know your rights and responsibilities.  It should be in a
                     47: ;; file named COPYING.  Among other things, the copyright notice
                     48: ;; and this notice must be preserved on all copies.
                     49: 
                     50: ;; Low-level subprocess mode guts
                     51: 
                     52: ;;;;
                     53: ;;; Variables and Constants
                     54: ;;;;
                     55: 
                     56: (defvar fi:common-lisp-image-name "cl"
                     57:   "*Default Common Lisp image to invoke from `fi:common-lisp'.  If the
                     58: value is a string then it names the image file or image path that
                     59: `fi:common-lisp' invokes.  Otherwise, the value of this variable is given
                     60: to funcall, the result of which should yield a string which is the image
                     61: name or path.")
                     62: 
                     63: (defvar fi:common-lisp-image-arguments nil
                     64:   "*Default Common Lisp image arguments when invoked from `fi:common-lisp',
                     65: which must be a list of strings.")
                     66: 
                     67: (defvar fi:common-lisp-prompt-pattern
                     68:   "^\\(\\[[0-9]+c?\\] \\|\\[step\\] \\)?<[-A-Za-z]* ?[0-9]*?> "
                     69:   "*The regular expression which matches the Common Lisp prompt, used in
                     70: Inferior Common Lisp mode.  Anything from beginning of line up to the end
                     71: of what this pattern matches is deemed to be a prompt.")
                     72: 
                     73: (defvar fi:franz-lisp-image-name "lisp"
                     74:   "*Default Franz Lisp image to invoke from `fi:franz-lisp'.  If the value
                     75: is a string then it names the image file or image path that
                     76: `fi:common-lisp' invokes.  Otherwise, the value of this variable is given
                     77: to funcall, the result of which should yield a string which is the image
                     78: name or path.")
                     79: 
                     80: (defvar fi:franz-lisp-image-arguments nil
                     81:   "*Default Franz Lisp image arguments when invoked from `fi:franz-lisp'.")
                     82: 
                     83: (defvar fi:franz-lisp-prompt-pattern
                     84:   "^[-=]> +\\|^c{[0-9]+} +"
                     85:   "*The regular expression which matches the Franz Lisp prompt, used in
                     86: Inferior Franz Lisp mode.  Anything from beginning of line up to the end
                     87: of what this pattern matches is deemed to be a prompt.")
                     88: 
                     89: (defvar fi:shell-popd-regexp ":?popd"
                     90:   "*The regular expression matching the C shell `popd' command.  If nil, no
                     91: automatic directory changes will be made.")
                     92: 
                     93: (defvar fi:shell-pushd-regexp ":?pushd"
                     94:   "*The regular expression matching the C shell `pushd' command.  If nil,
                     95: no automatic directory changes will be made.")
                     96: 
                     97: (defvar fi:shell-cd-regexp ":?cd"
                     98:   "*The regular expression matching the C shell `cd' command.  If nil,
                     99: no automatic directory changes will be made.")
                    100: 
                    101: (defvar fi:common-lisp-package-regexp
                    102:   "(in-package\\>\\|:\\<pa\\>\\|:\\<pac\\>\\|:\\<pack\\>\\|:\\<packa\\>\\|:\\<packag\\>\\|:\\<package\\>"
                    103:   "*The regular expression matching the Common Lisp expression(s) to change
                    104: packages.  If nil, no automatic package tracking will be done.")
                    105: 
                    106: (defvar fi:subprocess-map-nl-to-cr nil
                    107:   "*If t, then map newline to carriage-return.")
                    108: 
                    109: (defvar fi:subprocess-continuously-show-output-in-visible-buffer t
                    110:   "*If t, output from a subprocess to a visible buffer is continuously
                    111: shown.  If a subprocess buffer is visible and the window point is beyond
                    112: the process output marker, output to that buffer from its associated
                    113: process will be continuously visible.  If the window point is before the
                    114: process output marker, the window is not updated.  This is a buffer-local
                    115: symbol.")
                    116: 
                    117: (defvar fi:subprocess-write-quantum 120
                    118:   "*Maximum size in bytes of a single write request to a subprocess.")
                    119: 
                    120: (defvar fi:subprocess-enable-superkeys nil
                    121:   "*If t, certain keys become `superkeys' in subprocess buffers--this
                    122: should be set before starting any subprocesses.  The superkeys are C-a,
                    123: C-d, C-o,C-u, C-w, C-z, and C-\\, which will behave as they would in the
                    124: current local keymap when typed at the end of a subprocess buffer.  If
                    125: typed elsewhere, these keys have their normal global binding.  This is a
                    126: buffer-local symbol.  Use setq-default to set the default value for this
                    127: symbol.")
                    128: 
                    129: (defvar fi:display-buffer-function 'switch-to-buffer
                    130:   "*If non-nil, then it is used as the function which is funcall'd with one
                    131: argument, a buffer, to display a subprocess buffer when it is created (ie,
                    132: from `fi:common-lisp').")
                    133: 
                    134: ;;;;;;;;;;;;;;;;;;;;;; internal vars
                    135: 
                    136: (defvar fi::cl-package-regexp nil
                    137:   "The real Common Lisp package regexp, which is nil in all buffer except
                    138: Inferior Common Lisp buffers.")
                    139: 
                    140: (defvar fi::last-input-start nil
                    141:   "Marker for start of last input in fi:shell-mode or fi:inferior-lisp-mode
                    142: buffer.")
                    143: 
                    144: (defvar fi::last-input-end nil
                    145:   "Marker for end of last input in fi:shell-mode or fi:inferior-lisp-mode
                    146: buffer.")
                    147: 
                    148: (defvar fi::sublisp-name nil
                    149:   "Name of inferior lisp process.")
                    150: 
                    151: (defvar fi::freshest-franz-sublisp-name nil
                    152:   "Name of franz lisp subprocess most recently invoked.")
                    153: 
                    154: (defvar fi::freshest-common-sublisp-name nil
                    155:   "Name of common lisp subprocess most recently invoked.")
                    156: 
                    157: (defvar fi::shell-directory-stack nil
                    158:   "List of directories saved by pushd in this buffer's shell.")
                    159: 
                    160: ;;;;
                    161: ;;; User visible functions
                    162: ;;;;
                    163: 
                    164: (defun fi:common-lisp (&optional buffer-number)
                    165:   "Start a Common Lisp subprocess in a buffer whose name is determined
                    166: from the optional prefix argument BUFFER-NUMBER.  Common Lisp buffer names
                    167: start with `*common-lisp' and end with `*', with an optional `-N' in
                    168: between.  If BUFFER-NUMBER is not given it defaults to 1.  If BUFFER-NUMBER
                    169: is >= 0, then the buffer is named `*common-lisp-<BUFFER-NUMBER>*'.  If
                    170: BUFFER-NUMBER is < 0, then the first available buffer name is chosen.
                    171: 
                    172: The image file and image arguments are taken from the variables
                    173: `fi:common-lisp-image-name' and `fi:common-lisp-image-arguments'.
                    174: 
                    175: See fi:explicit-common-lisp."
                    176:   (interactive "p")
                    177:   (let ((proc (fi::make-subprocess
                    178:               buffer-number "common-lisp" 
                    179:               'fi:inferior-common-lisp-mode
                    180:               fi:common-lisp-prompt-pattern
                    181:               fi:common-lisp-image-name
                    182:               fi:common-lisp-image-arguments)))
                    183:     (setq fi::freshest-common-sublisp-name (process-name proc))
                    184:     proc))
                    185: 
                    186: (defun fi:explicit-common-lisp (&optional buffer-number
                    187:                                          image-name image-arguments)
                    188:   "The same as fi:common-lisp, except that the image and image arguments
                    189: are read from the minibuffer."
                    190:   (interactive "p\nsImage name: \nxImage arguments (a list): ")
                    191:   (let ((proc (fi::make-subprocess
                    192:               buffer-number "common-lisp" 
                    193:               'fi:inferior-common-lisp-mode
                    194:               fi:common-lisp-prompt-pattern
                    195:               image-name image-arguments)))
                    196:     (setq fi::freshest-common-sublisp-name (process-name proc))
                    197:     proc))
                    198: 
                    199: (defun fi:remote-common-lisp (&optional buffer-number host)
                    200:   "Start a Common Lisp subprocess in a buffer whose name is determined
                    201: from the optional prefix argument BUFFER-NUMBER, where the Common Lisp
                    202: image is run on another machine.  Common Lisp buffer names start with
                    203: `*common-lisp' and end with `*', with an optional `-N' in between.  If
                    204: BUFFER-NUMBER is not given it defaults to 1.  If BUFFER-NUMBER is >= 0,
                    205: then the buffer is named `*common-lisp-<BUFFER-NUMBER>*'.  If BUFFER-NUMBER
                    206: is < 0, then the first available buffer name is chosen.
                    207: 
                    208: The host on which the image is run is read from the minibuffer.
                    209: 
                    210: The image file and image arguments are taken from the variables
                    211: `fi:common-lisp-image-name' and `fi:common-lisp-image-arguments'.
                    212: 
                    213: See fi:explicit-remote-common-lisp."
                    214:   (interactive "p\nsRemote host name: ")
                    215:   (let ((proc (fi::make-subprocess
                    216:               buffer-number "common-lisp" 
                    217:               'fi:inferior-common-lisp-mode
                    218:               fi:common-lisp-prompt-pattern
                    219:               "rsh"
                    220:               (append (list host fi:common-lisp-image-name)
                    221:                       fi:common-lisp-image-arguments))))
                    222:     (setq fi::freshest-common-sublisp-name (process-name proc))
                    223:     proc))
                    224: 
                    225: (defun fi:explicit-remote-common-lisp (&optional buffer-number host
                    226:                                                 image-name image-arguments)
                    227:   "The same as fi:remote-common-lisp, except that the image and image
                    228: arguments are read from the minibuffer."
                    229:   (interactive
                    230:    "p\nsRemote host name: \nsImage name: \nxImage arguments (a list): ")
                    231:   (let ((proc (fi::make-subprocess
                    232:               buffer-number "common-lisp" 
                    233:               'fi:inferior-common-lisp-mode
                    234:               fi:common-lisp-prompt-pattern
                    235:               "rsh"
                    236:               (append (list host image-name) image-arguments))))
                    237:     (setq fi::freshest-common-sublisp-name (process-name proc))
                    238:     proc))
                    239: 
                    240: (defun fi:tcp-common-lisp (&optional buffer-number)
                    241:   "In a buffer whose name is determined from the optional prefix argument
                    242: BUFFER-NAME, connect to a Common Lisp using either a UNIX domain socket
                    243: file or internet port number.  Common Lisp buffer names start with
                    244: `*common-lisp' and end with `*', with an optional `-N' in between.  If
                    245: BUFFER-NUMBER is not given it defaults to 1.  If BUFFER-NUMBER is >= 0,then
                    246: the buffer is named `*common-lisp-<BUFFER-NUMBER>*'.  If BUFFER-NUMBER is <
                    247: 0, then the first available buffer name is chosen.
                    248: 
                    249: See `fi:unix-domain' and `fi:explicit-tcp-common-lisp'."
                    250:   (interactive "p")
                    251:   (let ((proc (fi::make-tcp-connection
                    252:               buffer-number "tcp-common-lisp" 'fi:tcp-common-lisp-mode
                    253:               fi:common-lisp-prompt-pattern)))
                    254:     (setq fi::freshest-common-sublisp-name (process-name proc))
                    255:     proc))
                    256: 
                    257: (defun fi:explicit-tcp-common-lisp (&optional buffer-number host service)
                    258:   "The same as fi:tcp-common-lisp, except that the host name a port number
                    259: are read from the minibuffer.  Use a port number of 0 for UNIX domain
                    260: sockets."
                    261:   (interactive
                    262:    "p\nsHost name: \nnService port number (0 for UNIX domain): ")
                    263:   (let ((proc (fi::make-tcp-connection
                    264:               buffer-number "tcp-common-lisp" 'fi:tcp-common-lisp-mode
                    265:               fi:common-lisp-prompt-pattern
                    266:               host service)))
                    267:     (setq fi::freshest-common-sublisp-name (process-name proc))
                    268:     proc))
                    269: 
                    270: (defun fi:franz-lisp (&optional buffer-number)
                    271:   "Start a Franz Lisp subprocess in a buffer whose name is determined
                    272: from the optional prefix argument BUFFER-NUMBER.  Franz Lisp buffer names
                    273: start with `*franz-lisp' and end with `*', with an optional `-N' in
                    274: between.  If BUFFER-NUMBER is not given it defaults to 1.  If BUFFER-NUMBER
                    275: is >= 0, then the buffer is named `*franz-lisp-<BUFFER-NUMBER>*'.  If
                    276: BUFFER-NUMBER is < 0, then the first available buffer name is chosen.
                    277: 
                    278: The image file and image arguments are taken from the variables
                    279: `fi:franz-lisp-image-name' and `fi:franz-lisp-image-arguments'.
                    280: 
                    281: See fi:explicit-franz-lisp."
                    282:   (interactive "p")
                    283:   (let ((proc (fi::make-subprocess
                    284:               buffer-number "franz-lisp" 
                    285:               'fi:inferior-franz-lisp-mode
                    286:               fi:franz-lisp-prompt-pattern
                    287:               fi:franz-lisp-image-name
                    288:               fi:franz-lisp-image-arguments)))
                    289:     (setq fi::freshest-franz-sublisp-name (process-name proc))
                    290:     proc))
                    291: 
                    292: (defun fi:explicit-franz-lisp (&optional buffer-number
                    293:                                         image-name image-arguments)
                    294:   "The same as fi:franz-lisp, except that the image and image arguments
                    295: are read from the minibuffer."
                    296:   (interactive "p\nsImage name: \nxImage arguments (a list): ")
                    297:   (let ((proc (fi::make-subprocess
                    298:               buffer-number "franz-lisp" 
                    299:               'fi:inferior-franz-lisp-mode
                    300:               fi:franz-lisp-prompt-pattern
                    301:               image-name image-arguments)))
                    302:     (setq fi::freshest-franz-sublisp-name (process-name proc))
                    303:     proc))
                    304: 
                    305: ;;;;
                    306: ;;; Internal functions
                    307: ;;;;
                    308: 
                    309: (defun fi::make-subprocess (buffer-number process-name mode-function
                    310:                                          image-prompt image-file
                    311:                                          image-arguments)
                    312:   (let* ((buffer (fi::make-process-buffer process-name buffer-number))
                    313:         (default-dir default-directory)
                    314:         (buffer-name (buffer-name buffer))
                    315:         (process (get-buffer-process buffer))
                    316:         (status (if process (process-status process)))
                    317:         (runningp (memq status '(run stop)))
                    318:         start-up-feed-name)
                    319:     (if (and (not runningp)
                    320:             (consp image-file))
                    321:        (setq image-file (funcall image-file)))
                    322:     (if fi:display-buffer-function
                    323:        (funcall fi:display-buffer-function buffer)
                    324:       (switch-to-buffer buffer))
                    325:     (if runningp
                    326:        (goto-char (point-max))
                    327:       (setq default-directory default-dir)
                    328:       (if process (delete-process process))
                    329:       (setq process (apply 'start-process
                    330:                           (append (list buffer-name buffer image-file)
                    331:                                   image-arguments)))
                    332:       (set-process-sentinel process 'fi::subprocess-sentinel)
                    333:       (set-process-filter process 'fi::subprocess-filter)
                    334:       (setq start-up-feed-name
                    335:        (if image-file
                    336:            (concat "~/.emacs_" (file-name-nondirectory image-file))))
                    337:       (cond
                    338:        ((and start-up-feed-name (file-exists-p start-up-feed-name))
                    339:         ;; I hope 1 second is enough!
                    340:         (sleep-for 1)
                    341:         (goto-char (point-max))
                    342:         (insert-file-contents start-up-feed-name)
                    343:         (setq start-up-feed-name (buffer-substring (point) (point-max)))
                    344:         (delete-region (point) (point-max))
                    345:         (fi::send-string-split process start-up-feed-name
                    346:                                fi:subprocess-map-nl-to-cr)))
                    347:       (goto-char (point-max))
                    348:       (set-marker (process-mark process) (point))
                    349:       (let ((saved-input-ring fi::input-ring))
                    350:        (funcall mode-function)
                    351:        (setq fi::input-ring saved-input-ring))
                    352:       (make-local-variable 'subprocess-prompt-pattern)
                    353:       (setq subprocess-prompt-pattern image-prompt)
                    354:       (fi::make-subprocess-variables))
                    355:     process))
                    356: 
                    357: (defun fi::make-tcp-connection (buffer-number buffer-name mode image-prompt
                    358:                                    &optional given-host
                    359:                                              given-service)
                    360:   (let* ((buffer (fi::make-process-buffer buffer-name buffer-number))
                    361:         (default-dir default-directory)
                    362:         (buffer-name (buffer-name buffer))
                    363:         (host (if given-host
                    364:                   (expand-file-name given-host)
                    365:                 (if fi:unix-domain
                    366:                     (expand-file-name fi:unix-domain-socket)
                    367:                   fi:local-host-name)))
                    368:         (service (if given-service
                    369:                      given-service
                    370:                    (if fi:unix-domain 0 fi:excl-service-name)))
                    371:         proc status)
                    372:     (if fi:display-buffer-function
                    373:        (funcall fi:display-buffer-function buffer)
                    374:       (switch-to-buffer buffer))
                    375:     (setq proc (get-buffer-process buffer))
                    376:     (setq status (if proc (process-status proc)))
                    377:     (if (eq status 'run)
                    378:        (error
                    379:         "can't start a TCP Common Lisp in a buffer which has a subprocess"))
                    380:     (if (eq status 'open)
                    381:        (goto-char (point-max))
                    382:       (setq default-directory default-dir)
                    383:       (setq proc (open-network-stream buffer-name buffer host service))
                    384:       ;;
                    385:       ;; HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK
                    386:       ;; The first input the new (Common Lisp) process is sent is the name
                    387:       ;; of the process.  This is so that the processes are named similarly
                    388:       ;; in Emacs and Lisp.
                    389:       ;;
                    390:       (process-send-string proc (format "\"%s\"\n" (buffer-name buffer)))
                    391: 
                    392:       (goto-char (point-max))
                    393:       (set-marker (process-mark proc) (point))
                    394:       (let ((saved-input-ring fi::input-ring))
                    395:        (funcall mode)
                    396:        (setq fi::input-ring saved-input-ring))      
                    397:       (make-local-variable 'subprocess-prompt-pattern)
                    398:       (setq subprocess-prompt-pattern image-prompt)
                    399:       (fi::make-subprocess-variables))
                    400:     proc))
                    401: 
                    402: (defun fi::make-process-buffer (name number)
                    403:   (let ((buffer-name
                    404:         (cond
                    405:           ((not (numberp number))
                    406:            (concat "*" name "*"))
                    407:           ((> number 1)
                    408:            ;; just return the buffer name
                    409:            (concat "*" name "-" number "*"))
                    410:           ((< number 0)
                    411:            ;; search for the first available buffer
                    412:            (let (buffer-name n)
                    413:              (if (not (fi::process-running
                    414:                        (setq buffer-name (concat "*" name "*"))))
                    415:                  buffer-name
                    416:                (setq n 2)
                    417:                (while (fi::process-running (setq buffer-name
                    418:                                              (concat "*" name "-" n "*")))
                    419:                  (setq n (+ n 1)))
                    420:                buffer-name)))
                    421:           (t (concat "*" name "*")))))
                    422:     (or (get-buffer buffer-name)
                    423:        (get-buffer-create buffer-name))))
                    424: 
                    425: (defun fi::make-subprocess-variables ()
                    426:   (setq fi::input-ring-max fi:default-input-ring-max)
                    427:   (setq fi::input-ring-yank-pointer nil)
                    428:   (setq fi::shell-directory-stack nil)
                    429:   (setq fi::last-input-search-string "")
                    430:   (setq fi::last-input-start (make-marker))
                    431:   (setq fi::last-input-end (make-marker)))
                    432: 
                    433: (defun fi::send-region-split (process start-position end-position
                    434:                                      &optional nl-cr)
                    435:   "Send region to process in small pieces."
                    436:   (interactive "sSend region in pieces (to process): \nr")
                    437:   (let* ((start (if (markerp start-position)
                    438:                    (marker-position start-position)
                    439:                  start-position))
                    440:         (end (if (markerp end-position)
                    441:                  (marker-position end-position)
                    442:                end-position))
                    443:         (string (buffer-substring start end)))
                    444:     (fi::send-string-split process string nl-cr)))
                    445: 
                    446: (defun fi::send-string-split (process string &optional nl-cr)
                    447:   "Send string to process in small pieces using send-string."
                    448:   (interactive "sSend (to process): \nsSend to process in pieces (string): ")
                    449:   (let ((size (length string))
                    450:        (filtered-string
                    451:         (if nl-cr
                    452:             (fi::substitute-chars-in-string '((?\n . ?\r)) string)
                    453:           string))
                    454:        (start 0))
                    455:     (while (and (> size 0)
                    456:                (condition-case nil
                    457:                    (progn
                    458:                      (send-string
                    459:                       process
                    460:                       (substring filtered-string
                    461:                                  start
                    462:                                  (+ start
                    463:                                     (min size
                    464:                                          fi:subprocess-write-quantum))))
                    465:                      t)
                    466:                  (error
                    467:                   (message "Error writing to subprocess.")
                    468:                   nil)))
                    469:       (setq size (- size fi:subprocess-write-quantum))
                    470:       (setq start (+ start fi:subprocess-write-quantum)))))
                    471: 
                    472: ;;; Sentinel and filter for subprocesses.  The sentinel is currently
                    473: ;;;   not used.
                    474: (defun fi::subprocess-sentinel (process status)
                    475:   t)
                    476: 
                    477: (defun fi::subprocess-filter (process output &optional stay)
                    478:   "Filter output from processes tied to buffers.
                    479: This function implements continuous output to visible buffers."
                    480:   (let* ((old-buffer (current-buffer))
                    481:         (buffer (process-buffer process))
                    482:         (in-buffer (eq buffer old-buffer))
                    483:         (window-of-buffer (get-buffer-window buffer))
                    484:         (no-window (or (null window-of-buffer)
                    485:                        (not (windowp window-of-buffer))))
                    486:         (xmarker (process-mark process))
                    487:         (marker (if (marker-position xmarker)
                    488:                     xmarker
                    489:                   (set-marker (make-marker) 0 buffer)))
                    490:         (marker-point (marker-position marker))
                    491:         (output-length (length output))
                    492:         old-point
                    493:         point-not-before-marker
                    494:         new-point)
                    495:     ;; The three symbols below are not bound above because `(window-point)'
                    496:     ;;   for the selected window does not always return the same thing as the
                    497:     ;;   function `(point)' in that window!  [Version 18 is supposed to fix
                    498:     ;;   this bug.]
                    499:     ;; Note that there is no function that returns all of the windows that
                    500:     ;;   are currently displaying a buffer.  Because of this, not all windows
                    501:     ;;   will be updated properly by this filter function.  What should be
                    502:     ;;   done is to loop through all windows displaying the buffer and do
                    503:     ;;   `(set-window-point)' in each.
                    504:     (if (not in-buffer)
                    505:        (progn
                    506:          (set-buffer buffer)
                    507:          (setq old-point
                    508:            (if no-window
                    509:                (point)
                    510:              (window-point window-of-buffer))))
                    511:       (setq old-point (point)))
                    512:     (setq point-not-before-marker (>= old-point marker-point))
                    513:     (setq new-point (if point-not-before-marker
                    514:                        (+ old-point output-length)
                    515:                      old-point))
                    516:     (save-excursion
                    517:       ;; Go to point of last output by fi::make-process and insert new
                    518:       ;;   output there, preserving position of the marker.
                    519:       (goto-char marker-point)
                    520:       ;; The code below works around what appears to be a display bug
                    521:       ;;   in GNU Emacs 17.  If `(insert-before-markers)' is used when
                    522:       ;;   the process marker (process-mark), window-start point
                    523:       ;;   (window-start), and window point (point) are all coincident,
                    524:       ;;   the window display `sticks' on the topmost line.  We use
                    525:       ;;   `(insert-string)' followed by `(set-marker)' to avoid this
                    526:       ;;   problem.  This also happens to be the way
                    527:       ;;   `handle_process_output()' deals with this in `process.c'.
                    528:       (insert-string output)
                    529:       (set-marker marker (point)))
                    530:     (if (not in-buffer)
                    531:        (if (and fi:subprocess-continuously-show-output-in-visible-buffer
                    532:                 point-not-before-marker)
                    533:            ;; Keep window's notion of `point' in a constant relationship to
                    534:            ;;   the process output marker.
                    535:            (if no-window
                    536:                (goto-char new-point)
                    537:              (set-window-point window-of-buffer new-point))
                    538:          (if no-window
                    539:              t;; Still there.
                    540:            (set-window-point window-of-buffer old-point)))
                    541:       (goto-char new-point))
                    542:     (cond
                    543:       (in-buffer nil)
                    544:       (stay old-buffer)
                    545:       (t (set-buffer old-buffer)))))
                    546: 
                    547: (defun fi::subprocess-watch-for-special-commands ()
                    548:   "Watch for special commands like, for example, `cd' in a shell."
                    549:   (if (null fi::shell-directory-stack)
                    550:       (setq fi::shell-directory-stack (list default-directory)))
                    551:   (condition-case ()
                    552:       ;; "To err is really not nice." -dkl 11/21/88
                    553:       (save-excursion
                    554:        (goto-char fi::last-input-start)
                    555:        (cond
                    556:          ((and fi::cl-package-regexp (looking-at fi::cl-package-regexp))
                    557:           (goto-char (match-end 0))
                    558:           (cond
                    559:             ((or (looking-at "[ \t]*[':]\\(.*\\)[ \t]*)")
                    560:                  (looking-at "[ \t]*\"\\(.*\\)\"[ \t]*)"))
                    561:              ;; (in-package foo)
                    562:              (setq fi:package
                    563:                (buffer-substring (match-beginning 1) (match-end 1))))
                    564:             ((looking-at "[ \t]+\\(.*\\)[ \t]*$")
                    565:              ;; :pa foo
                    566:              (setq fi:package
                    567:                (buffer-substring (match-beginning 1) (match-end 1)))))
                    568:           ;; need to do something here to force the minibuffer to
                    569:           ;; redisplay:
                    570:           (set-buffer-modified-p (buffer-modified-p)))
                    571:          ((and fi:shell-popd-regexp (looking-at fi:shell-popd-regexp))
                    572:           (goto-char (match-end 0))
                    573:           (cond
                    574:             ((looking-at ".*&[ \t]*$")
                    575:              ;; "popd ... &" executes in a subshell!
                    576:              )
                    577:             (t
                    578:              (let ((n (if (looking-at "[ \t]+\\+\\([0-9]*\\)")
                    579:                           (car
                    580:                            (read-from-string
                    581:                             (buffer-substring (match-beginning 1)
                    582:                                               (match-end 1)))))))
                    583:                (if (null n)
                    584:                    (cd (car (setq fi::shell-directory-stack
                    585:                               (cdr fi::shell-directory-stack))))
                    586:                  ;; pop n'th entry
                    587:                  (if (> n (length fi::shell-directory-stack))
                    588:                      (message "Directory stack not that deep.")
                    589:                    (let ((tail (nthcdr (+ n 1) fi::shell-directory-stack)))
                    590:                      (rplacd (nthcdr (- n 1) fi::shell-directory-stack)
                    591:                              nil)
                    592:                      (setq fi::shell-directory-stack
                    593:                        (append fi::shell-directory-stack tail)))))))))
                    594:          ((and fi:shell-pushd-regexp (looking-at fi:shell-pushd-regexp))
                    595:           (goto-char (match-end 0))
                    596:           (cond
                    597:             ((looking-at ".*&[ \t]*$")
                    598:              ;; "pushd ... &" executes in a subshell!
                    599:              )
                    600:             ((looking-at "[ \t]+\\+\\([0-9]+\\)[ \t]*[;\n]")
                    601:              ;; pushd +n
                    602:              (let ((n (car (read-from-string
                    603:                             (buffer-substring (match-beginning 1)
                    604:                                               (match-end 1))))))
                    605:                (if (< n 1)
                    606:                    (message "Illegal stack element: %s" n)
                    607:                  (if (> n (length fi::shell-directory-stack))
                    608:                      (message "Directory stack not that deep.")
                    609:                    (let ((head (nthcdr n fi::shell-directory-stack)))
                    610:                      (rplacd (nthcdr (- n 1) fi::shell-directory-stack)
                    611:                              nil)
                    612:                      (setq fi::shell-directory-stack
                    613:                        (append head fi::shell-directory-stack))
                    614:                      (cd (car head)))))))
                    615:             ((looking-at "[ \t]+\\([^ \t]+\\)[;\n]")
                    616:              ;; pushd dir
                    617:              (let ((dir (expand-file-name
                    618:                          (substitute-in-file-name
                    619:                           (buffer-substring (match-beginning 1)
                    620:                                             (match-end 1))))))
                    621:                (if (file-directory-p dir)
                    622:                    (progn
                    623:                      (setq fi::shell-directory-stack
                    624:                        (cons dir fi::shell-directory-stack))
                    625:                      (cd dir)))))
                    626:             ((looking-at "[ \t]*[;\n]")
                    627:              ;; pushd
                    628:              (if (< (length fi::shell-directory-stack) 2)
                    629:                  (message "Directory stack not that deep.")
                    630:                (setq fi::shell-directory-stack
                    631:                  (append (list (car (cdr fi::shell-directory-stack))
                    632:                                (car fi::shell-directory-stack))
                    633:                          (cdr (cdr fi::shell-directory-stack))))
                    634:                (cd (car fi::shell-directory-stack))))))
                    635:          ((and fi:shell-cd-regexp (looking-at fi:shell-cd-regexp))
                    636:           (goto-char (match-end 0))
                    637:           (cond
                    638:             ((looking-at ".*&[ \t]*$")
                    639:              ;; "cd foo &" executes in a subshell!
                    640:              )
                    641:             ((looking-at "[ \t]*[;\n]")
                    642:              ;; cd
                    643:              (cd (rplaca fi::shell-directory-stack (getenv "HOME"))))
                    644:             ((looking-at "[ \t]+\\([^ \t]+\\)[ \t]*[;\n]")
                    645:              ;; cd dir
                    646:              (let ((dir (expand-file-name
                    647:                          (substitute-in-file-name
                    648:                           (buffer-substring (match-beginning 1)
                    649:                                             (match-end 1))))))
                    650:                (if (file-directory-p dir)
                    651:                    (progn
                    652:                      (rplaca fi::shell-directory-stack dir)
                    653:                      (cd dir)))))))))
                    654:     (error nil)))
                    655: 
                    656: ;;;;
                    657: ;;; Initializations
                    658: ;;;;
                    659: 
                    660: (mapcar 'make-variable-buffer-local
                    661:        '(fi:shell-popd-regexp
                    662:          fi:shell-pushd-regexp 
                    663:          fi:shell-cd-regexp
                    664:          fi::cl-package-regexp
                    665:          fi:package
                    666:          fi:subprocess-map-nl-to-cr
                    667:          fi:subprocess-continuously-show-output-in-visible-buffer
                    668:          fi:subprocess-enable-superkeys
                    669:          fi:subprocess-super-key-map
                    670: 
                    671:          fi::shell-directory-stack
                    672:          fi::last-input-start
                    673:          fi::last-input-end
                    674:          fi::input-ring
                    675:          fi::input-ring-max
                    676:          fi::input-ring-yank-pointer
                    677:          fi::last-input-search-string))

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.