Annotation of 43BSDReno/contrib/emacs-18.55/lisp/compile.el, revision 1.1

1.1     ! root        1: ;; Run compiler as inferior of Emacs, and parse its error messages.
        !             2: ;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
        !             3: 
        !             4: ;; This file is part of GNU Emacs.
        !             5: 
        !             6: ;; GNU Emacs is distributed in the hope that it will be useful,
        !             7: ;; but WITHOUT ANY WARRANTY.  No author or distributor
        !             8: ;; accepts responsibility to anyone for the consequences of using it
        !             9: ;; or for whether it serves any particular purpose or works at all,
        !            10: ;; unless he says so in writing.  Refer to the GNU Emacs General Public
        !            11: ;; License for full details.
        !            12: 
        !            13: ;; Everyone is granted permission to copy, modify and redistribute
        !            14: ;; GNU Emacs, but only under the conditions described in the
        !            15: ;; GNU Emacs General Public License.   A copy of this license is
        !            16: ;; supposed to have been given to you along with GNU Emacs so you
        !            17: ;; can know your rights and responsibilities.  It should be in a
        !            18: ;; file named COPYING.  Among other things, the copyright notice
        !            19: ;; and this notice must be preserved on all copies.
        !            20: 
        !            21: (provide 'compile)
        !            22: 
        !            23: (defvar compilation-process nil
        !            24:   "Process created by compile command, or nil if none exists now.
        !            25: Note that the process may have been \"deleted\" and still
        !            26: be the value of this variable.")
        !            27: 
        !            28: (defvar compilation-error-list nil
        !            29:   "List of error message descriptors for visiting erring functions.
        !            30: Each error descriptor is a list of length two.
        !            31: Its car is a marker pointing to an error message.
        !            32: Its cadr is a marker pointing to the text of the line the message is about,
        !            33:   or nil if that is not interesting.
        !            34: The value may be t instead of a list;
        !            35: this means that the buffer of error messages should be reparsed
        !            36: the next time the list of errors is wanted.")
        !            37: 
        !            38: (defvar compilation-parsing-end nil
        !            39:   "Position of end of buffer when last error messages parsed.")
        !            40: 
        !            41: (defvar compilation-error-message nil
        !            42:   "Message to print when no more matches for compilation-error-regexp are found")
        !            43: 
        !            44: ;; The filename excludes colons to avoid confusion when error message
        !            45: ;; starts with digits.
        !            46: (defvar compilation-error-regexp
        !            47:   "\\([^ :\n]+\\(: *\\|, line \\|(\\)[0-9]+\\)\\|\\([0-9]+ *of *[^ \n]+\\)"
        !            48:   "Regular expression for filename/linenumber in error in compilation log.")
        !            49: 
        !            50: (defun compile (command)
        !            51:   "Compile the program including the current buffer.  Default: run `make'.
        !            52: Runs COMMAND, a shell command, in a separate process asynchronously
        !            53: with output going to the buffer *compilation*.
        !            54: You can then use the command \\[next-error] to find the next error message
        !            55: and move to the source code that caused it."
        !            56:   (interactive (list (read-string "Compile command: " compile-command)))
        !            57:   (setq compile-command command)
        !            58:   (compile1 compile-command "No more errors"))
        !            59: 
        !            60: (defun grep (command)
        !            61:   "Run grep, with user-specified args, and collect output in a buffer.
        !            62: While grep runs asynchronously, you can use the \\[next-error] command
        !            63: to find the text that grep hits refer to."
        !            64:   (interactive "sRun grep (with args): ")
        !            65:   (compile1 (concat "grep -n " command " /dev/null")
        !            66:            "No more grep hits" "grep"))
        !            67: 
        !            68: (defun compile1 (command error-message &optional name-of-mode)
        !            69:   (save-some-buffers)
        !            70:   (if compilation-process
        !            71:       (if (or (not (eq (process-status compilation-process) 'run))
        !            72:              (yes-or-no-p "A compilation process is running; kill it? "))
        !            73:          (condition-case ()
        !            74:              (let ((comp-proc compilation-process))
        !            75:                (interrupt-process comp-proc)
        !            76:                (sit-for 1)
        !            77:                (delete-process comp-proc))
        !            78:            (error nil))
        !            79:        (error "Cannot have two compilation processes")))
        !            80:   (setq compilation-process nil)
        !            81:   (compilation-forget-errors)
        !            82:   (setq compilation-error-list t)
        !            83:   (setq compilation-error-message error-message)
        !            84:   (setq compilation-process
        !            85:        (start-process "compilation" "*compilation*"
        !            86:                       shell-file-name
        !            87:                       "-c" (concat "exec " command)))
        !            88:   (with-output-to-temp-buffer "*compilation*"
        !            89:     (princ "cd ")
        !            90:     (princ default-directory)
        !            91:     (terpri)
        !            92:     (princ command)
        !            93:     (terpri))
        !            94:   (let ((regexp compilation-error-regexp))
        !            95:     (save-excursion
        !            96:       (set-buffer "*compilation*")
        !            97:       (make-local-variable 'compilation-error-regexp)
        !            98:       (setq compilation-error-regexp regexp)))
        !            99:   (set-process-sentinel compilation-process 'compilation-sentinel)
        !           100:   (let* ((thisdir default-directory)
        !           101:         (outbuf (process-buffer compilation-process))
        !           102:         (outwin (get-buffer-window outbuf)))
        !           103:     (if (eq outbuf (current-buffer))
        !           104:        (goto-char (point-max)))
        !           105:     (save-excursion
        !           106:       (set-buffer outbuf)
        !           107:       (buffer-flush-undo outbuf)
        !           108:       (let ((start (save-excursion (set-buffer outbuf) (point-min))))
        !           109:        (set-window-start outwin start)
        !           110:        (or (eq outwin (selected-window))
        !           111:            (set-window-point outwin start)))
        !           112:       (setq default-directory thisdir)
        !           113:       (fundamental-mode)
        !           114:       (setq mode-name (or name-of-mode "Compilation"))
        !           115:       ;; Make log buffer's mode line show process state
        !           116:       (setq mode-line-process '(": %s")))))
        !           117: 
        !           118: ;; Called when compilation process changes state.
        !           119: 
        !           120: (defun compilation-sentinel (proc msg)
        !           121:   (cond ((null (buffer-name (process-buffer proc)))
        !           122:         ;; buffer killed
        !           123:         (set-process-buffer proc nil))
        !           124:        ((memq (process-status proc) '(signal exit))
        !           125:         (let* ((obuf (current-buffer))
        !           126:                omax opoint)
        !           127:           ;; save-excursion isn't the right thing if
        !           128:           ;;  process-buffer is current-buffer
        !           129:           (unwind-protect
        !           130:               (progn
        !           131:                 ;; Write something in *compilation* and hack its mode line,
        !           132:                 (set-buffer (process-buffer proc))
        !           133:                 (setq omax (point-max) opoint (point))
        !           134:                 (goto-char (point-max))
        !           135:                 (insert ?\n mode-name " " msg)
        !           136:                 (forward-char -1)
        !           137:                 (insert " at "
        !           138:                         (substring (current-time-string) 0 -5))
        !           139:                 (forward-char 1)
        !           140:                 (setq mode-line-process
        !           141:                       (concat ": "
        !           142:                               (symbol-name (process-status proc))))
        !           143:                 ;; If buffer and mode line will show that the process
        !           144:                 ;; is dead, we can delete it now.  Otherwise it
        !           145:                 ;; will stay around until M-x list-processes.
        !           146:                 (delete-process proc))
        !           147:             (setq compilation-process nil)
        !           148:             ;; Force mode line redisplay soon
        !           149:             (set-buffer-modified-p (buffer-modified-p)))
        !           150:           (if (and opoint (< opoint omax))
        !           151:               (goto-char opoint))
        !           152:           (set-buffer obuf)))))
        !           153: 
        !           154: (defun kill-compilation ()
        !           155:   "Kill the process made by the \\[compile] command."
        !           156:   (interactive)
        !           157:   (if compilation-process
        !           158:       (interrupt-process compilation-process)))
        !           159: 
        !           160: (defun kill-grep ()
        !           161:   "Kill the process made by the \\[grep] command."
        !           162:   (interactive)
        !           163:   (if compilation-process
        !           164:       (interrupt-process compilation-process)))
        !           165: 
        !           166: (defun next-error (&optional argp)
        !           167:   "Visit next compilation error message and corresponding source code.
        !           168: This operates on the output from the \\[compile] command.
        !           169: If all preparsed error messages have been processed,
        !           170: the error message buffer is checked for new ones.
        !           171: A non-nil argument (prefix arg, if interactive)
        !           172: means reparse the error message buffer and start at the first error."
        !           173:   (interactive "P")
        !           174:   (if (or (eq compilation-error-list t)
        !           175:          argp)
        !           176:       (progn (compilation-forget-errors)
        !           177:             (setq compilation-parsing-end 1)))
        !           178:   (if compilation-error-list
        !           179:       nil
        !           180:     (save-excursion
        !           181:       (switch-to-buffer "*compilation*")
        !           182:       (set-buffer-modified-p nil)
        !           183:       (compilation-parse-errors)))
        !           184:   (let ((next-error (car compilation-error-list)))
        !           185:     (if (null next-error)
        !           186:        (error (concat compilation-error-message
        !           187:                       (if (and compilation-process
        !           188:                                (eq (process-status compilation-process)
        !           189:                                    'run))
        !           190:                           " yet" ""))))
        !           191:     (setq compilation-error-list (cdr compilation-error-list))
        !           192:     (if (null (car (cdr next-error)))
        !           193:        nil
        !           194:       (switch-to-buffer (marker-buffer (car (cdr next-error))))
        !           195:       (goto-char (car (cdr next-error)))
        !           196:       (set-marker (car (cdr next-error)) nil))
        !           197:     (let* ((pop-up-windows t)
        !           198:           (w (display-buffer (marker-buffer (car next-error)))))
        !           199:       (set-window-point w (car next-error))
        !           200:       (set-window-start w (car next-error)))
        !           201:     (set-marker (car next-error) nil)))
        !           202: 
        !           203: ;; Set compilation-error-list to nil, and
        !           204: ;; unchain the markers that point to the error messages and their text,
        !           205: ;; so that they no longer slow down gap motion.
        !           206: ;; This would happen anyway at the next garbage collection,
        !           207: ;; but it is better to do it right away.
        !           208: (defun compilation-forget-errors ()
        !           209:   (if (eq compilation-error-list t)
        !           210:       (setq compilation-error-list nil))
        !           211:   (while compilation-error-list
        !           212:     (let ((next-error (car compilation-error-list)))
        !           213:       (set-marker (car next-error) nil)
        !           214:       (if (car (cdr next-error))
        !           215:          (set-marker (car (cdr next-error)) nil)))
        !           216:     (setq compilation-error-list (cdr compilation-error-list))))
        !           217: 
        !           218: (defun compilation-parse-errors ()
        !           219:   "Parse the current buffer as error messages.
        !           220: This makes a list of error descriptors, compilation-error-list.
        !           221: For each source-file, line-number pair in the buffer,
        !           222: the source file is read in, and the text location is saved in compilation-error-list.
        !           223: The function next-error, assigned to \\[next-error], takes the next error off the list
        !           224: and visits its location."
        !           225:   (setq compilation-error-list nil)
        !           226:   (message "Parsing error messages...")
        !           227:   (let (text-buffer
        !           228:        last-filename last-linenum)
        !           229:     ;; Don't reparse messages already seen at last parse.
        !           230:     (goto-char compilation-parsing-end)
        !           231:     ;; Don't parse the first two lines as error messages.
        !           232:     ;; This matters for grep.
        !           233:     (if (bobp)
        !           234:        (forward-line 2))
        !           235:     (while (re-search-forward compilation-error-regexp nil t)
        !           236:       (let (linenum filename
        !           237:            error-marker text-marker)
        !           238:        ;; Extract file name and line number from error message.
        !           239:        (save-restriction
        !           240:          (narrow-to-region (match-beginning 0) (match-end 0))
        !           241:          (goto-char (point-max))
        !           242:          (skip-chars-backward "[0-9]")
        !           243:          ;; If it's a lint message, use the last file(linenum) on the line.
        !           244:          ;; Normally we use the first on the line.
        !           245:          (if (= (preceding-char) ?\()
        !           246:              (progn
        !           247:                (narrow-to-region (point-min) (1+ (buffer-size)))
        !           248:                (end-of-line)
        !           249:                (re-search-backward compilation-error-regexp)
        !           250:                (skip-chars-backward "^ \t\n")
        !           251:                (narrow-to-region (point) (match-end 0))
        !           252:                (goto-char (point-max))
        !           253:                (skip-chars-backward "[0-9]")))
        !           254:          ;; Are we looking at a "filename-first" or "line-number-first" form?
        !           255:          (if (looking-at "[0-9]")
        !           256:              (progn
        !           257:                (setq linenum (read (current-buffer)))
        !           258:                (goto-char (point-min)))
        !           259:            ;; Line number at start, file name at end.
        !           260:            (progn
        !           261:              (goto-char (point-min))
        !           262:              (setq linenum (read (current-buffer)))
        !           263:              (goto-char (point-max))
        !           264:              (skip-chars-backward "^ \t\n")))
        !           265:          (setq filename (compilation-grab-filename)))
        !           266:        ;; Locate the erring file and line.
        !           267:        (if (and (equal filename last-filename)
        !           268:                 (= linenum last-linenum))
        !           269:            nil
        !           270:          (beginning-of-line 1)
        !           271:          (setq error-marker (point-marker))
        !           272:          ;; text-buffer gets the buffer containing this error's file.
        !           273:          (if (not (equal filename last-filename))
        !           274:              (setq text-buffer
        !           275:                    (and (file-exists-p (setq last-filename filename))
        !           276:                         (find-file-noselect filename))
        !           277:                    last-linenum 0))
        !           278:          (if text-buffer
        !           279:              ;; Go to that buffer and find the erring line.
        !           280:              (save-excursion
        !           281:                (set-buffer text-buffer)
        !           282:                (if (zerop last-linenum)
        !           283:                    (progn
        !           284:                      (goto-char 1)
        !           285:                      (setq last-linenum 1)))
        !           286:                (forward-line (- linenum last-linenum))
        !           287:                (setq last-linenum linenum)
        !           288:                (setq text-marker (point-marker))
        !           289:                (setq compilation-error-list
        !           290:                      (cons (list error-marker text-marker)
        !           291:                            compilation-error-list)))))
        !           292:        (forward-line 1)))
        !           293:     (setq compilation-parsing-end (point-max)))
        !           294:   (message "Parsing error messages...done")
        !           295:   (setq compilation-error-list (nreverse compilation-error-list)))
        !           296: 
        !           297: (defun compilation-grab-filename ()
        !           298:   "Return a string which is a filename, starting at point.
        !           299: Ignore quotes and parentheses around it, as well as trailing colons."
        !           300:   (if (eq (following-char) ?\")
        !           301:       (save-restriction
        !           302:        (narrow-to-region (point)
        !           303:                          (progn (forward-sexp 1) (point)))
        !           304:        (goto-char (point-min))
        !           305:        (read (current-buffer)))
        !           306:     (buffer-substring (point)
        !           307:                      (progn
        !           308:                        (skip-chars-forward "^ :,\n\t(")
        !           309:                        (point)))))
        !           310: 
        !           311: (define-key ctl-x-map "`" 'next-error)

unix.superglobalmegacorp.com

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